Repository: Azure/iot-edge-opc-publisher Branch: release/2.9.15 Commit: ed10198e4d1a Files: 1761 Total size: 24.5 MB Directory structure: gitextract_707ivrax/ ├── .editorconfig ├── .gdnbaselines ├── .gitattributes ├── .github/ │ ├── CODEOWNERS │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.md │ │ └── feature_request.md │ ├── dependabot.yml │ └── workflows/ │ ├── codeql.yml │ ├── dotnet.yml │ └── test.yml ├── .gitignore ├── .mcp.json ├── .sscignore ├── CODEOWNERS ├── Industrial-IoT.slnx ├── LICENSE ├── NOTICE ├── Nuget.Config ├── SECURITY.md ├── azure-pipelines.yml ├── common.props ├── contributing.md ├── deploy/ │ ├── azuredeploy.json │ ├── azuredeploy.parameters.json │ ├── deploy.ps1 │ ├── docker/ │ │ ├── build.cmd │ │ ├── dapr/ │ │ │ ├── pubsub.yaml │ │ │ └── statestore.yaml │ │ ├── docker-compose.yaml │ │ ├── gcdump.ps1 │ │ ├── mosquitto/ │ │ │ ├── mosquitto.conf │ │ │ └── settings.json │ │ ├── opentelemetry/ │ │ │ ├── collector.yaml │ │ │ ├── dashboards/ │ │ │ │ └── opc-publisher.json │ │ │ ├── dashboards.yaml │ │ │ ├── datasources.yaml │ │ │ ├── prometheus.yml │ │ │ └── tempo.yaml │ │ ├── publisher_secrets.txt │ │ ├── readme.md │ │ ├── with-dapr.yaml │ │ ├── with-limits.yaml │ │ ├── with-localimage.yaml │ │ ├── with-localvolume.yaml │ │ ├── with-monitor.yaml │ │ ├── with-mosquitto.yaml │ │ ├── with-opentelemetry.yaml │ │ └── with-pcap-capture.yaml │ ├── iotedge/ │ │ ├── .gitignore │ │ ├── arm/ │ │ │ ├── TLSSettings.ps1 │ │ │ ├── default.yml │ │ │ ├── dps-enroll.ps1 │ │ │ ├── dsc-install.ps1 │ │ │ ├── edge-setup.ps1 │ │ │ ├── edge-setup.sh │ │ │ ├── eflow-setup.ps1 │ │ │ ├── simulation.sh │ │ │ └── testing.yml │ │ ├── azuredeploy.json │ │ ├── azuredeploy.parameters.json │ │ ├── edgehubdev.cmd │ │ ├── edgehubdev.json │ │ ├── eflow-setup.json │ │ ├── eflow-setup.ps1 │ │ └── readme.md │ ├── kubernetes/ │ │ ├── cluster-setup.ps1 │ │ ├── common/ │ │ │ └── cluster-utils.psm1 │ │ ├── debug/ │ │ │ ├── Dockerfile │ │ │ ├── build.ps1 │ │ │ ├── debug.json │ │ │ ├── debug.ps1 │ │ │ ├── entrypoint.sh │ │ │ └── forward-mq.ps1 │ │ ├── deploy.ps1 │ │ ├── iotops/ │ │ │ ├── adr-tool.ps1 │ │ │ ├── azure_iot_ops-2.0.0b4.dev1-py3-none-any.whl │ │ │ ├── enable-preview.ps1 │ │ │ └── opc-publisher-connector-metadata.json │ │ ├── readme.md │ │ └── simulation/ │ │ ├── deploy.ps1 │ │ └── helm/ │ │ ├── opc-plc/ │ │ │ ├── Chart.yaml │ │ │ ├── templates/ │ │ │ │ ├── _helpers.tpl │ │ │ │ ├── opc-plc_configMap.yaml │ │ │ │ ├── opc-plc_default_application_certificate.yaml │ │ │ │ ├── opc-plc_deployment.yaml │ │ │ │ └── opc-plc_service.yaml │ │ │ └── values.yaml │ │ ├── opc-test/ │ │ │ ├── Chart.yaml │ │ │ ├── templates/ │ │ │ │ ├── _helpers.tpl │ │ │ │ ├── opc-test_default_application_certificate.yaml │ │ │ │ ├── opc-test_deployment.yaml │ │ │ │ └── opc-test_service.yaml │ │ │ └── values.yaml │ │ ├── opc-umati/ │ │ │ └── templates/ │ │ │ └── umati_deployment.yaml │ │ └── umati/ │ │ ├── Chart.yaml │ │ ├── templates/ │ │ │ ├── _helpers.tpl │ │ │ ├── umati_configMap.yaml │ │ │ ├── umati_default_application_certificate.yaml │ │ │ ├── umati_deployment.yaml │ │ │ └── umati_service.yaml │ │ └── values.yaml │ └── readme.md ├── docs/ │ ├── _config.yml │ ├── opc-publisher/ │ │ ├── api.md │ │ ├── commandline.md │ │ ├── definitions.md │ │ ├── deployment.json │ │ ├── directmethods.md │ │ ├── features.md │ │ ├── intfilesamples.md │ │ ├── messageformats.md │ │ ├── migrationpath.md │ │ ├── observability.md │ │ ├── openapi.json │ │ ├── publishednodes_2.5.json │ │ ├── publishednodes_2.8.json │ │ ├── readme.md │ │ ├── security.md │ │ ├── transports.md │ │ └── troubleshooting.md │ ├── readme.md │ └── release-announcement.md ├── e2e-tests/ │ ├── .gitignore │ ├── Directory.Build.props │ ├── IIoTPlatform-E2E-Tests.slnx │ ├── OpcPublisher-E2E-Tests/ │ │ ├── Config/ │ │ │ ├── IContainerRegistryConfig.cs │ │ │ ├── IDeviceConfig.cs │ │ │ ├── IIoTEdgeConfig.cs │ │ │ ├── IIoTHubConfig.cs │ │ │ ├── IOpcPlcConfig.cs │ │ │ └── ISshConfig.cs │ │ ├── GlobalSuppressions.cs │ │ ├── MessagingMode.cs │ │ ├── OpcPublisher-AE-E2E-Tests.csproj │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ ├── PublishedNodesConfigurations.cs │ │ ├── RegistryHelper.cs │ │ ├── Standalone/ │ │ │ ├── C_EventNamespaceTestTheory.cs │ │ │ ├── C_EventsStressTestTheory.cs │ │ │ ├── C_PendingConditionsTestTheory.cs │ │ │ ├── C_PublishConditionsTestTheory.cs │ │ │ ├── C_WhereClauseTestTheory.cs │ │ │ ├── D_AlarmDirectMethodTestTheory.cs │ │ │ ├── D_EventDirectMethodTestTheory.cs │ │ │ └── DynamicAciTestBase.cs │ │ ├── TestConstants.cs │ │ ├── TestExtensions/ │ │ │ ├── IIoTPlatformTestContext.cs │ │ │ ├── IIoTStandaloneTestContext.cs │ │ │ ├── PriorityOrderAttribute.cs │ │ │ └── TestCaseOrderer.cs │ │ ├── TestHelper.cs │ │ ├── TestModels/ │ │ │ ├── BaseEventTypePayload.cs │ │ │ ├── ConditionTypePayload.cs │ │ │ ├── DataValueObject.cs │ │ │ ├── EventData.cs │ │ │ ├── PendingConditionEventData.cs │ │ │ ├── SimpleEventsStep.cs │ │ │ ├── SystemCycleStatusEventTypePayload.cs │ │ │ └── SystemEventTypePayload.cs │ │ ├── deploy/ │ │ │ ├── DeploymentConfiguration.cs │ │ │ ├── IIoTHubEdgeDeployment.cs │ │ │ ├── IoTHubEdgeBaseDeployment.cs │ │ │ ├── IoTHubPublisherDeployment.cs │ │ │ └── ModuleDeploymentConfiguration.cs │ │ ├── opc-plc-files/ │ │ │ └── sc001.json │ │ └── xunit.runner.json │ └── readme.md ├── readme.md ├── samples/ │ ├── .gitignore │ ├── Http/ │ │ ├── BrowseAll/ │ │ │ ├── BrowseAll.cs │ │ │ └── BrowseAll.csproj │ │ ├── GetConfiguration/ │ │ │ ├── GetConfiguration.cs │ │ │ └── GetConfiguration.csproj │ │ ├── GetDiagnostics/ │ │ │ ├── GetDiagnostics.cs │ │ │ └── GetDiagnostics.csproj │ │ ├── HttpSamples.slnx │ │ ├── Parameters.cs │ │ ├── ReadCurrentTime/ │ │ │ ├── ReadCurrentTime.cs │ │ │ └── ReadCurrentTime.csproj │ │ ├── SetConfiguration/ │ │ │ ├── SetConfiguration.cs │ │ │ └── SetConfiguration.csproj │ │ ├── WriteReadbackValue/ │ │ │ ├── WriteReadbackValue.cs │ │ │ └── WriteReadbackValue.csproj │ │ └── readme.md │ ├── IoTHub/ │ │ ├── ApproveRejected/ │ │ │ ├── ApproveRejected.cs │ │ │ └── ApproveRejected.csproj │ │ ├── BrowseCertificates/ │ │ │ ├── BrowseCertificates.cs │ │ │ └── BrowseCertificates.csproj │ │ ├── GetCertificate/ │ │ │ ├── GetApplicationCert.cs │ │ │ └── GetApplicationCert.csproj │ │ ├── GetConfiguration/ │ │ │ ├── GetConfiguration.cs │ │ │ └── GetConfiguration.csproj │ │ ├── IoTHubSamples.slnx │ │ ├── ManageWriter/ │ │ │ ├── ManageWriter.cs │ │ │ └── ManageWriter.csproj │ │ ├── MonitorMessages/ │ │ │ ├── MonitorMessages.cs │ │ │ └── MonitorMessages.csproj │ │ ├── Parameters.cs │ │ ├── ReadCurrentTime/ │ │ │ ├── ReadCurrentTime.cs │ │ │ └── ReadCurrentTime.csproj │ │ ├── ResetClients/ │ │ │ ├── GetAndResetConnections.cs │ │ │ └── GetAndResetConnections.csproj │ │ ├── WriteReadbackValue/ │ │ │ ├── WriteReadbackValue.cs │ │ │ └── WriteReadbackValue.csproj │ │ └── readme.md │ ├── Mqtt/ │ │ ├── GetConfiguration/ │ │ │ ├── GetConfiguration.cs │ │ │ └── GetConfiguration.csproj │ │ ├── ManageWriter/ │ │ │ ├── ManageWriter.cs │ │ │ └── ManageWriter.csproj │ │ ├── MonitorMessages/ │ │ │ ├── MonitorMessages.cs │ │ │ └── MonitorMessages.csproj │ │ ├── MqttSamples.slnx │ │ ├── ReadAttributes/ │ │ │ ├── ReadAttributes.cs │ │ │ └── ReadAttributes.csproj │ │ ├── ReadCurrentTime/ │ │ │ ├── ReadCurrentTime.cs │ │ │ └── ReadCurrentTime.csproj │ │ ├── WriteReadbackValue/ │ │ │ ├── WriteReadbackValue.cs │ │ │ └── WriteReadbackValue.csproj │ │ └── readme.md │ └── Netcap/ │ ├── Directory.Build.props │ ├── Netcap.slnx │ ├── build.sh │ ├── readme.md │ └── src/ │ ├── .dockerignore │ ├── Dockerfile │ ├── Extensions.cs │ ├── Gateway.cs │ ├── Netcap.cs │ ├── Netcap.csproj │ ├── Pcap.cs │ ├── Program.cs │ ├── Publisher.cs │ └── Storage.cs ├── src/ │ ├── .gitignore │ ├── Azure.IIoT.OpcUa/ │ │ ├── src/ │ │ │ ├── Azure.IIoT.OpcUa.csproj │ │ │ ├── Encoders/ │ │ │ │ ├── AvroBinaryReader.cs │ │ │ │ ├── AvroBinaryWriter.cs │ │ │ │ ├── AvroDecoder.cs │ │ │ │ ├── AvroEncoder.cs │ │ │ │ ├── AvroFileReader.cs │ │ │ │ ├── AvroFileWriter.cs │ │ │ │ ├── AvroFileWriterOptions.cs │ │ │ │ ├── AvroSchemaBuilder.cs │ │ │ │ ├── AvroSchemaTraverser.cs │ │ │ │ ├── BaseAvroDecoder.cs │ │ │ │ ├── BaseAvroEncoder.cs │ │ │ │ ├── ConsoleWriter.cs │ │ │ │ ├── ConsoleWriterOptions.cs │ │ │ │ ├── ContentType.cs │ │ │ │ ├── DecodingException.cs │ │ │ │ ├── EncodingException.cs │ │ │ │ ├── Extensions/ │ │ │ │ │ ├── EncodeableEx.cs │ │ │ │ │ ├── Extensions.cs │ │ │ │ │ ├── JsonSerializerUtcEx.cs │ │ │ │ │ ├── LocalizedTextEx.cs │ │ │ │ │ ├── NodeIdEx.cs │ │ │ │ │ ├── QualifiedNameEx.cs │ │ │ │ │ ├── StatusCodeEx.cs │ │ │ │ │ └── TypeInfoEx.cs │ │ │ │ ├── Extensions.cs │ │ │ │ ├── IVariantEncoder.cs │ │ │ │ ├── JsonDecoderEx.cs │ │ │ │ ├── JsonEncoderEx.cs │ │ │ │ ├── JsonVariantEncoder.cs │ │ │ │ ├── MessageSchemaTypes.cs │ │ │ │ ├── Models/ │ │ │ │ │ ├── DataSet.cs │ │ │ │ │ ├── EncodeableDictionary.cs │ │ │ │ │ ├── EncodeableJToken.cs │ │ │ │ │ ├── EncodeableVariantValue.cs │ │ │ │ │ └── KeyDataValuePair.cs │ │ │ │ ├── PubSub/ │ │ │ │ │ ├── AvroDataSetMessage.cs │ │ │ │ │ ├── AvroNetworkMessage.cs │ │ │ │ │ ├── BaseDataSetMessage.cs │ │ │ │ │ ├── BaseNetworkMessage.cs │ │ │ │ │ ├── EncoderExtensions.cs │ │ │ │ │ ├── IDataSetMetaDataResolver.cs │ │ │ │ │ ├── JsonDataSetMessage.cs │ │ │ │ │ ├── JsonMetadataMessage.cs │ │ │ │ │ ├── JsonNetworkMessage.cs │ │ │ │ │ ├── MessageType.cs │ │ │ │ │ ├── MonitoredItemMessage.cs │ │ │ │ │ ├── PubSubMessage.cs │ │ │ │ │ ├── StackExtensions.cs │ │ │ │ │ ├── UadpDataSetMessage.cs │ │ │ │ │ ├── UadpDiscoveryMessage.cs │ │ │ │ │ ├── UadpMetadataMessage.cs │ │ │ │ │ └── UadpNetworkMessage.cs │ │ │ │ ├── Schemas/ │ │ │ │ │ ├── Avro/ │ │ │ │ │ │ ├── AvroBuiltInSchemas.cs │ │ │ │ │ │ ├── AvroDataSet.cs │ │ │ │ │ │ ├── AvroDataSetMessage.cs │ │ │ │ │ │ ├── AvroNetworkMessage.cs │ │ │ │ │ │ ├── AvroSchema.cs │ │ │ │ │ │ ├── BaseDataSetMessage.cs │ │ │ │ │ │ ├── BaseNetworkMessage.cs │ │ │ │ │ │ ├── IAvroSchema.cs │ │ │ │ │ │ ├── JsonBuiltInSchemas.cs │ │ │ │ │ │ ├── JsonDataSet.cs │ │ │ │ │ │ ├── JsonDataSetMessage.cs │ │ │ │ │ │ ├── JsonNetworkMessage.cs │ │ │ │ │ │ └── MonitoredItemMessage.cs │ │ │ │ │ ├── BaseBuiltInSchemas.cs │ │ │ │ │ ├── BaseDataSetSchema.cs │ │ │ │ │ ├── Json/ │ │ │ │ │ │ ├── JsonBuiltInSchemas.cs │ │ │ │ │ │ ├── JsonDataSet.cs │ │ │ │ │ │ ├── JsonDataSetMessage.cs │ │ │ │ │ │ ├── JsonNetworkMessage.cs │ │ │ │ │ │ ├── JsonSchema.cs │ │ │ │ │ │ ├── JsonSchemaExtensions.cs │ │ │ │ │ │ ├── JsonSchemaVersion.cs │ │ │ │ │ │ ├── JsonSchemaVocabulary.cs │ │ │ │ │ │ ├── JsonSchemaWriter.cs │ │ │ │ │ │ └── MonitoredItemMessage.cs │ │ │ │ │ ├── SchemaOptions.cs │ │ │ │ │ ├── SchemaRank.cs │ │ │ │ │ ├── SchemaUtils.cs │ │ │ │ │ └── Uadp/ │ │ │ │ │ └── UadpNetworkMessage.cs │ │ │ │ ├── Utils/ │ │ │ │ │ └── TypeMaps.cs │ │ │ │ ├── ZipFileReader.cs │ │ │ │ └── ZipFileWriter.cs │ │ │ ├── Exceptions/ │ │ │ │ ├── ConnectionException.cs │ │ │ │ └── ServerBusyException.cs │ │ │ ├── Extensions/ │ │ │ │ ├── LinqEx.cs │ │ │ │ ├── StreamEx.cs │ │ │ │ ├── StringEx.cs │ │ │ │ └── TimerEx.cs │ │ │ ├── IMetricsContext.cs │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ └── Publisher/ │ │ │ ├── Diagnostics.cs │ │ │ ├── Extensions/ │ │ │ │ ├── AggregateConfigurationModelEx.cs │ │ │ │ ├── AggregateFilterModelEx.cs │ │ │ │ ├── ApplicationInfoModelEx.cs │ │ │ │ ├── ApplicationRegistrationModelEx.cs │ │ │ │ ├── AuthenticationMethodModelEx.cs │ │ │ │ ├── ConditionHandlingOptionsModelEx.cs │ │ │ │ ├── ConnectionModelEx.cs │ │ │ │ ├── ContentFilterElementModelEx.cs │ │ │ │ ├── ContentFilterModelEx.cs │ │ │ │ ├── CredentialModelEx.cs │ │ │ │ ├── DataChangeFilterModelEx.cs │ │ │ │ ├── DataSetMetaDataModelEx.cs │ │ │ │ ├── DataSetWriterModelEx.cs │ │ │ │ ├── DiagnosticsModelEx.cs │ │ │ │ ├── DiscoveryConfigModelEx.cs │ │ │ │ ├── DiscoveryRequestModelEx.cs │ │ │ │ ├── EndpointModelEx.cs │ │ │ │ ├── EndpointRegistrationModelEx.cs │ │ │ │ ├── EventFilterModelEx.cs │ │ │ │ ├── FileSystemServicesEx.cs │ │ │ │ ├── FilterOperandModelEx.cs │ │ │ │ ├── ModelChangeHandlingOptionsModelEx.cs │ │ │ │ ├── NodeServicesEx.cs │ │ │ │ ├── OpcNodeModelEx.cs │ │ │ │ ├── PublishedDataItemsModelEx.cs │ │ │ │ ├── PublishedDataSetEventModelEx.cs │ │ │ │ ├── PublishedDataSetModelEx.cs │ │ │ │ ├── PublishedDataSetSettingsModelEx.cs │ │ │ │ ├── PublishedDataSetSourceModelEx.cs │ │ │ │ ├── PublishedDataSetTriggerModelEx.cs │ │ │ │ ├── PublishedDataSetVariableModelEx.cs │ │ │ │ ├── PublishedEventItemsModelEx.cs │ │ │ │ ├── PublishedNodesEntryModelEx.cs │ │ │ │ ├── RegistryOperationContextModelEx.cs │ │ │ │ ├── SimpleAttributeOperandModelEx.cs │ │ │ │ ├── UserIdentityModelEx.cs │ │ │ │ ├── X509CertificateChainModelEx.cs │ │ │ │ └── X509CertificateModelEx.cs │ │ │ ├── ICertificateServices.cs │ │ │ ├── IConnectionServices.cs │ │ │ ├── IFileSystemServices.cs │ │ │ ├── IHistoryServices.cs │ │ │ ├── INetworkDiscovery.cs │ │ │ ├── INodeServices.cs │ │ │ ├── IPublishServices.cs │ │ │ ├── IServerDiscovery.cs │ │ │ └── Runtime.cs │ │ └── tests/ │ │ ├── Azure.IIoT.OpcUa.Tests.csproj │ │ ├── Encoders/ │ │ │ ├── AvroBaseTests.cs │ │ │ ├── AvroDataSetTests.cs │ │ │ ├── AvroEncoderTests.cs │ │ │ ├── AvroFileWriterTests.cs │ │ │ ├── Extensions/ │ │ │ │ ├── ExpandedNodeIdExTests.cs │ │ │ │ ├── LocalizedTextExTests.cs │ │ │ │ ├── NodeIdExTests.cs │ │ │ │ ├── QualifiedNameExTests.cs │ │ │ │ └── TypeInfoExTests.cs │ │ │ ├── JsonDataSetTests.cs │ │ │ ├── Models/ │ │ │ │ └── EncodeableDictionaryTests.cs │ │ │ ├── PubSub/ │ │ │ │ ├── AvroNetworkMessageEncoderDecoderTests1.cs │ │ │ │ ├── AvroNetworkMessageEncoderDecoderTests2.cs │ │ │ │ ├── AvroNetworkMessageFileWriterReaderTests.cs │ │ │ │ ├── JsonNetworkMessageEncoderDecoderTests.cs │ │ │ │ ├── JsonNetworkMessageEncoderTests1.cs │ │ │ │ ├── JsonNetworkMessageEncoderTests2.cs │ │ │ │ ├── MonitoredItemMessageEncoderDecoderTests.cs │ │ │ │ ├── PubSubMessageContentFlagHelper.cs │ │ │ │ └── UadpNetworkMessageEncoderDecoderTests.cs │ │ │ ├── SchemaUtilsTests.cs │ │ │ ├── Schemas/ │ │ │ │ ├── AvroNetworkMessageAvroSchemaTests.cs │ │ │ │ ├── AvroSchema/ │ │ │ │ │ ├── Default/ │ │ │ │ │ │ ├── CyclicReads.json │ │ │ │ │ │ ├── KeepAlive.json │ │ │ │ │ │ ├── KeyFrames.json │ │ │ │ │ │ ├── PendingAlarms.json │ │ │ │ │ │ ├── PlcSimulation.json │ │ │ │ │ │ └── SimpleEvents.json │ │ │ │ │ ├── Multiple/ │ │ │ │ │ │ ├── CyclicReads.json │ │ │ │ │ │ ├── KeepAlive.json │ │ │ │ │ │ ├── KeyFrames.json │ │ │ │ │ │ ├── PendingAlarms.json │ │ │ │ │ │ ├── PlcSimulation.json │ │ │ │ │ │ └── SimpleEvents.json │ │ │ │ │ ├── NetworkMessage/ │ │ │ │ │ │ ├── CyclicReads.json │ │ │ │ │ │ ├── KeepAlive.json │ │ │ │ │ │ ├── KeyFrames.json │ │ │ │ │ │ ├── PendingAlarms.json │ │ │ │ │ │ ├── PlcSimulation.json │ │ │ │ │ │ └── SimpleEvents.json │ │ │ │ │ ├── NetworkMessageDefault/ │ │ │ │ │ │ ├── CyclicReads.json │ │ │ │ │ │ ├── KeepAlive.json │ │ │ │ │ │ ├── KeyFrames.json │ │ │ │ │ │ ├── PendingAlarms.json │ │ │ │ │ │ ├── PlcSimulation.json │ │ │ │ │ │ └── SimpleEvents.json │ │ │ │ │ ├── Raw/ │ │ │ │ │ │ ├── CyclicReads.json │ │ │ │ │ │ ├── KeepAlive.json │ │ │ │ │ │ ├── KeyFrames.json │ │ │ │ │ │ ├── PendingAlarms.json │ │ │ │ │ │ ├── PlcSimulation.json │ │ │ │ │ │ └── SimpleEvents.json │ │ │ │ │ ├── RawReversible/ │ │ │ │ │ │ ├── CyclicReads.json │ │ │ │ │ │ ├── KeepAlive.json │ │ │ │ │ │ ├── KeyFrames.json │ │ │ │ │ │ ├── PendingAlarms.json │ │ │ │ │ │ ├── PlcSimulation.json │ │ │ │ │ │ └── SimpleEvents.json │ │ │ │ │ └── Single/ │ │ │ │ │ ├── CyclicReads.json │ │ │ │ │ ├── KeepAlive.json │ │ │ │ │ ├── KeyFrames.json │ │ │ │ │ ├── PendingAlarms.json │ │ │ │ │ ├── PlcSimulation.json │ │ │ │ │ └── SimpleEvents.json │ │ │ │ ├── JavroSchema/ │ │ │ │ │ ├── Default/ │ │ │ │ │ │ ├── CyclicReads.json │ │ │ │ │ │ ├── KeepAlive.json │ │ │ │ │ │ ├── KeyFrames.json │ │ │ │ │ │ ├── PendingAlarms.json │ │ │ │ │ │ ├── PlcSimulation.json │ │ │ │ │ │ └── SimpleEvents.json │ │ │ │ │ ├── Multiple/ │ │ │ │ │ │ ├── CyclicReads.json │ │ │ │ │ │ ├── KeepAlive.json │ │ │ │ │ │ ├── KeyFrames.json │ │ │ │ │ │ ├── PendingAlarms.json │ │ │ │ │ │ ├── PlcSimulation.json │ │ │ │ │ │ └── SimpleEvents.json │ │ │ │ │ ├── NetworkMessage/ │ │ │ │ │ │ ├── CyclicReads.json │ │ │ │ │ │ ├── KeepAlive.json │ │ │ │ │ │ ├── KeyFrames.json │ │ │ │ │ │ ├── PendingAlarms.json │ │ │ │ │ │ ├── PlcSimulation.json │ │ │ │ │ │ └── SimpleEvents.json │ │ │ │ │ ├── NetworkMessageDefault/ │ │ │ │ │ │ ├── CyclicReads.json │ │ │ │ │ │ ├── KeepAlive.json │ │ │ │ │ │ ├── KeyFrames.json │ │ │ │ │ │ ├── PendingAlarms.json │ │ │ │ │ │ ├── PlcSimulation.json │ │ │ │ │ │ └── SimpleEvents.json │ │ │ │ │ ├── Raw/ │ │ │ │ │ │ ├── CyclicReads.json │ │ │ │ │ │ ├── KeepAlive.json │ │ │ │ │ │ ├── KeyFrames.json │ │ │ │ │ │ ├── PendingAlarms.json │ │ │ │ │ │ ├── PlcSimulation.json │ │ │ │ │ │ └── SimpleEvents.json │ │ │ │ │ ├── RawReversible/ │ │ │ │ │ │ ├── CyclicReads.json │ │ │ │ │ │ ├── KeepAlive.json │ │ │ │ │ │ ├── KeyFrames.json │ │ │ │ │ │ ├── PendingAlarms.json │ │ │ │ │ │ ├── PlcSimulation.json │ │ │ │ │ │ └── SimpleEvents.json │ │ │ │ │ ├── Samples/ │ │ │ │ │ │ ├── CyclicReads.json │ │ │ │ │ │ ├── KeepAlive.json │ │ │ │ │ │ ├── KeyFrames.json │ │ │ │ │ │ ├── PendingAlarms.json │ │ │ │ │ │ ├── PlcSimulation.json │ │ │ │ │ │ └── SimpleEvents.json │ │ │ │ │ ├── SamplesRaw/ │ │ │ │ │ │ ├── CyclicReads.json │ │ │ │ │ │ ├── KeepAlive.json │ │ │ │ │ │ ├── KeyFrames.json │ │ │ │ │ │ ├── PendingAlarms.json │ │ │ │ │ │ ├── PlcSimulation.json │ │ │ │ │ │ └── SimpleEvents.json │ │ │ │ │ └── Single/ │ │ │ │ │ ├── CyclicReads.json │ │ │ │ │ ├── KeepAlive.json │ │ │ │ │ ├── KeyFrames.json │ │ │ │ │ ├── PendingAlarms.json │ │ │ │ │ ├── PlcSimulation.json │ │ │ │ │ └── SimpleEvents.json │ │ │ │ ├── JsonNetworkMessageAvroSchemaTests.cs │ │ │ │ ├── JsonNetworkMessageJsonSchemaTests.cs │ │ │ │ └── JsonSchema/ │ │ │ │ ├── Default/ │ │ │ │ │ ├── CyclicReads.json │ │ │ │ │ ├── KeepAlive.json │ │ │ │ │ ├── KeyFrames.json │ │ │ │ │ ├── PendingAlarms.json │ │ │ │ │ ├── PlcSimulation.json │ │ │ │ │ └── SimpleEvents.json │ │ │ │ ├── Multiple/ │ │ │ │ │ ├── CyclicReads.json │ │ │ │ │ ├── KeepAlive.json │ │ │ │ │ ├── KeyFrames.json │ │ │ │ │ ├── PendingAlarms.json │ │ │ │ │ ├── PlcSimulation.json │ │ │ │ │ └── SimpleEvents.json │ │ │ │ ├── NetworkMessage/ │ │ │ │ │ ├── CyclicReads.json │ │ │ │ │ ├── KeepAlive.json │ │ │ │ │ ├── KeyFrames.json │ │ │ │ │ ├── PendingAlarms.json │ │ │ │ │ ├── PlcSimulation.json │ │ │ │ │ └── SimpleEvents.json │ │ │ │ ├── NetworkMessageDefault/ │ │ │ │ │ ├── CyclicReads.json │ │ │ │ │ ├── KeepAlive.json │ │ │ │ │ ├── KeyFrames.json │ │ │ │ │ ├── PendingAlarms.json │ │ │ │ │ ├── PlcSimulation.json │ │ │ │ │ └── SimpleEvents.json │ │ │ │ ├── Raw/ │ │ │ │ │ ├── CyclicReads.json │ │ │ │ │ ├── KeepAlive.json │ │ │ │ │ ├── KeyFrames.json │ │ │ │ │ ├── PendingAlarms.json │ │ │ │ │ ├── PlcSimulation.json │ │ │ │ │ └── SimpleEvents.json │ │ │ │ ├── RawReversible/ │ │ │ │ │ ├── CyclicReads.json │ │ │ │ │ ├── KeepAlive.json │ │ │ │ │ ├── KeyFrames.json │ │ │ │ │ ├── PendingAlarms.json │ │ │ │ │ ├── PlcSimulation.json │ │ │ │ │ └── SimpleEvents.json │ │ │ │ ├── Samples/ │ │ │ │ │ ├── CyclicReads.json │ │ │ │ │ ├── KeepAlive.json │ │ │ │ │ ├── KeyFrames.json │ │ │ │ │ ├── PendingAlarms.json │ │ │ │ │ ├── PlcSimulation.json │ │ │ │ │ └── SimpleEvents.json │ │ │ │ ├── SamplesRaw/ │ │ │ │ │ ├── CyclicReads.json │ │ │ │ │ ├── KeepAlive.json │ │ │ │ │ ├── KeyFrames.json │ │ │ │ │ ├── PendingAlarms.json │ │ │ │ │ ├── PlcSimulation.json │ │ │ │ │ └── SimpleEvents.json │ │ │ │ └── Single/ │ │ │ │ ├── CyclicReads.json │ │ │ │ ├── KeepAlive.json │ │ │ │ ├── KeyFrames.json │ │ │ │ ├── PendingAlarms.json │ │ │ │ ├── PlcSimulation.json │ │ │ │ └── SimpleEvents.json │ │ │ ├── Services/ │ │ │ │ ├── VariantEncoderBooleanTests.cs │ │ │ │ ├── VariantEncoderByteTests.cs │ │ │ │ ├── VariantEncoderDoubleTests.cs │ │ │ │ ├── VariantEncoderEx.cs │ │ │ │ ├── VariantEncoderFloatTests.cs │ │ │ │ ├── VariantEncoderInt16Tests.cs │ │ │ │ ├── VariantEncoderInt32Tests.cs │ │ │ │ ├── VariantEncoderInt64Tests.cs │ │ │ │ ├── VariantEncoderMiscTests.cs │ │ │ │ ├── VariantEncoderSByteTests.cs │ │ │ │ ├── VariantEncoderStringTests.cs │ │ │ │ ├── VariantEncoderUInt16Tests.cs │ │ │ │ ├── VariantEncoderUInt32Tests.cs │ │ │ │ └── VariantEncoderUInt64Tests.cs │ │ │ ├── VariantVariants.cs │ │ │ └── ZipFileWriterTests.cs │ │ ├── GlobalSuppressions.cs │ │ ├── Publisher/ │ │ │ ├── Extensions/ │ │ │ │ └── OpcNodeModelExTests.cs │ │ │ └── Models/ │ │ │ └── PublishedNodesEntryModelTests.cs │ │ └── Resources/ │ │ ├── CyclicReads.json │ │ ├── KeepAlive.json │ │ ├── KeyFrames.json │ │ ├── PendingAlarms.json │ │ ├── PlcSimulation.json │ │ └── SimpleEvents.json │ ├── Azure.IIoT.OpcUa.Publisher/ │ │ ├── src/ │ │ │ ├── Azure.IIoT.OpcUa.Publisher.csproj │ │ │ ├── Constants.cs │ │ │ ├── Discovery/ │ │ │ │ ├── NetworkDiscovery.cs │ │ │ │ ├── ProgressLogger.cs │ │ │ │ ├── ProgressPublisher.cs │ │ │ │ └── ServerDiscovery.cs │ │ │ ├── Extensions/ │ │ │ │ ├── ContainerBuilderEx.cs │ │ │ │ ├── DataSetWriterModelEx.cs │ │ │ │ ├── PublishedDataSetSourceModelEx.cs │ │ │ │ └── RequestHeaderModelEx.cs │ │ │ ├── IApiKeyProvider.cs │ │ │ ├── IAssetConfiguration.cs │ │ │ ├── IClientDiagnostics.cs │ │ │ ├── IConfigurationServices.cs │ │ │ ├── IDiagnosticCollector.cs │ │ │ ├── IDiscoveryProgress.cs │ │ │ ├── IDiscoveryServices.cs │ │ │ ├── IMessageEncoder.cs │ │ │ ├── IMessageSink.cs │ │ │ ├── INodeServicesInternal.cs │ │ │ ├── IProcessControl.cs │ │ │ ├── IPublishedNodesServices.cs │ │ │ ├── IPublisher.cs │ │ │ ├── IRuntimeStateReporter.cs │ │ │ ├── ISslCertProvider.cs │ │ │ ├── IStorageProvider.cs │ │ │ ├── IWriterGroupControl.cs │ │ │ ├── IWriterGroupDiagnostics.cs │ │ │ ├── IWriterGroupScope.cs │ │ │ ├── IWriterGroupScopeFactory.cs │ │ │ ├── Models/ │ │ │ │ ├── AssetDeviceConfiguration.cs │ │ │ │ ├── DataSetWriterContext.cs │ │ │ │ ├── DiscoveryRequest.cs │ │ │ │ └── MessagingProfile.cs │ │ │ ├── Parser/ │ │ │ │ ├── Extensions/ │ │ │ │ │ └── Extensions.cs │ │ │ │ ├── FilterModelBuilder.cs │ │ │ │ ├── FilterQueryGrammar.cs │ │ │ │ ├── FilterQueryParser.cs │ │ │ │ ├── IFilterParser.cs │ │ │ │ ├── IFilterParserContext.cs │ │ │ │ ├── ParserException.cs │ │ │ │ ├── RelativePathParser.cs │ │ │ │ └── SessionParserContext.cs │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ ├── Runtime/ │ │ │ │ ├── PublisherConfig.cs │ │ │ │ ├── PublisherOptions.cs │ │ │ │ ├── TopicBuilder.cs │ │ │ │ └── TopicTemplatesOptions.cs │ │ │ ├── Services/ │ │ │ │ ├── AssetDeviceIntegration.cs │ │ │ │ ├── AsyncEnumerableBrowser.cs │ │ │ │ ├── ConfigurationBrowser.cs │ │ │ │ ├── ConfigurationServices.cs │ │ │ │ ├── DataSetWriter.cs │ │ │ │ ├── Extensions.cs │ │ │ │ ├── FileSystemServices.cs │ │ │ │ ├── HistoryServices.cs │ │ │ │ ├── NetworkMessageEncoder.cs │ │ │ │ ├── NetworkMessageSink.cs │ │ │ │ ├── NodeServices.cs │ │ │ │ ├── PublishedNodesJsonServices.cs │ │ │ │ ├── PublisherDiagnosticCollector.cs │ │ │ │ ├── PublisherModule.cs │ │ │ │ ├── PublisherService.cs │ │ │ │ ├── RollingAverage.cs │ │ │ │ ├── RuntimeStateReporter.cs │ │ │ │ ├── WriterGroupDataSource.cs │ │ │ │ └── WriterGroupScopeFactory.cs │ │ │ ├── Stack/ │ │ │ │ ├── AsyncEnumerableBase.cs │ │ │ │ ├── AsyncEnumerableStack.cs │ │ │ │ ├── Extensions/ │ │ │ │ │ ├── AssetsEx.cs │ │ │ │ │ ├── CertificateStoreEx.cs │ │ │ │ │ ├── CertificateTrustListEx.cs │ │ │ │ │ ├── ContainerBuilderEx.cs │ │ │ │ │ ├── DataValueEx.cs │ │ │ │ │ ├── DiscoveredEndpointModelEx.cs │ │ │ │ │ ├── DiscoveryClientEx.cs │ │ │ │ │ ├── EndpointDescriptionEx.cs │ │ │ │ │ ├── FileSystemEx.cs │ │ │ │ │ ├── FilterEncoderEx.cs │ │ │ │ │ ├── MonitoredItemEx.cs │ │ │ │ │ ├── NodeStateEx.cs │ │ │ │ │ ├── OperationLimitsEx.cs │ │ │ │ │ ├── RelativePathEx.cs │ │ │ │ │ ├── SequenceNumber.cs │ │ │ │ │ ├── ServiceResponseEx.cs │ │ │ │ │ ├── ServiceResultEx.cs │ │ │ │ │ ├── SessionEx.cs │ │ │ │ │ ├── StackModelsEx.cs │ │ │ │ │ ├── StackTypesEx.cs │ │ │ │ │ ├── SubscriptionModelEx.cs │ │ │ │ │ └── VariantEncoderEx.cs │ │ │ │ ├── IEndpointDiscovery.cs │ │ │ │ ├── IOpcUaBrowser.cs │ │ │ │ ├── IOpcUaCertificates.cs │ │ │ │ ├── IOpcUaClientDiagnostics.cs │ │ │ │ ├── IOpcUaClientManager.cs │ │ │ │ ├── IOpcUaConfiguration.cs │ │ │ │ ├── IOpcUaSession.cs │ │ │ │ ├── ISessionHandle.cs │ │ │ │ ├── ISessionServices.cs │ │ │ │ ├── ISubscriber.cs │ │ │ │ ├── ISubscription.cs │ │ │ │ ├── ISubscriptionDiagnostics.cs │ │ │ │ ├── Models/ │ │ │ │ │ ├── AttributeMap.cs │ │ │ │ │ ├── BaseMonitoredItemModel.cs │ │ │ │ │ ├── ConnectionIdentifier.cs │ │ │ │ │ ├── DataMonitoredItemModel.cs │ │ │ │ │ ├── DiscoveredEndpointModel.cs │ │ │ │ │ ├── EndpointIdentifier.cs │ │ │ │ │ ├── EventMonitoredItemModel.cs │ │ │ │ │ ├── ImmutableRelativePath.cs │ │ │ │ │ ├── MonitoredAddressSpaceModel.cs │ │ │ │ │ ├── MonitoredItemNotificationModel.cs │ │ │ │ │ ├── MonitoredItemSourceFlags.cs │ │ │ │ │ ├── SampledDataValueModel.cs │ │ │ │ │ ├── ServiceCallContext.cs │ │ │ │ │ ├── ServiceResponse.cs │ │ │ │ │ └── SubscriptionModel.cs │ │ │ │ ├── Runtime/ │ │ │ │ │ ├── CertificateInfo.cs │ │ │ │ │ ├── CertificateStore.cs │ │ │ │ │ ├── FlatCertificateStore.cs │ │ │ │ │ ├── OpcUaClientConfig.cs │ │ │ │ │ ├── OpcUaClientOptions.cs │ │ │ │ │ ├── OpcUaSubscriptionConfig.cs │ │ │ │ │ ├── OpcUaSubscriptionOptions.cs │ │ │ │ │ ├── SecurityOptions.cs │ │ │ │ │ └── TransportOptions.cs │ │ │ │ ├── Services/ │ │ │ │ │ ├── OpcUaApplication.cs │ │ │ │ │ ├── OpcUaClient.Browser.cs │ │ │ │ │ ├── OpcUaClient.Sampler.cs │ │ │ │ │ ├── OpcUaClient.Subscription.cs │ │ │ │ │ ├── OpcUaClient.cs │ │ │ │ │ ├── OpcUaClientManager.cs │ │ │ │ │ ├── OpcUaClientTagList.cs │ │ │ │ │ ├── OpcUaMonitoredItem.Condition.cs │ │ │ │ │ ├── OpcUaMonitoredItem.CyclicRead.cs │ │ │ │ │ ├── OpcUaMonitoredItem.DataChange.cs │ │ │ │ │ ├── OpcUaMonitoredItem.Event.cs │ │ │ │ │ ├── OpcUaMonitoredItem.Heartbeat.cs │ │ │ │ │ ├── OpcUaMonitoredItem.ModelChange.cs │ │ │ │ │ ├── OpcUaMonitoredItem.cs │ │ │ │ │ ├── OpcUaSession.cs │ │ │ │ │ ├── OpcUaStack.cs │ │ │ │ │ ├── OpcUaStackKeySetLogger.cs │ │ │ │ │ ├── OpcUaSubscription.cs │ │ │ │ │ └── OpcUaSubscriptionNotification.cs │ │ │ │ ├── StackExtensions.cs │ │ │ │ └── Transport/ │ │ │ │ ├── Extensions/ │ │ │ │ │ ├── EndPointEx.cs │ │ │ │ │ ├── IPAddressEx.cs │ │ │ │ │ ├── NetworkInformationEx.cs │ │ │ │ │ └── PhysicalAddressEx.cs │ │ │ │ ├── IAsyncProbe.cs │ │ │ │ ├── IPortProbe.cs │ │ │ │ ├── IScanner.cs │ │ │ │ ├── Models/ │ │ │ │ │ ├── AddressRange.cs │ │ │ │ │ ├── IPv4Address.cs │ │ │ │ │ ├── NetInterface.cs │ │ │ │ │ ├── NetworkClass.cs │ │ │ │ │ └── PortRange.cs │ │ │ │ ├── Probe/ │ │ │ │ │ └── ServerProbe.cs │ │ │ │ └── Scanner/ │ │ │ │ ├── BaseConnectProbe.cs │ │ │ │ ├── NetworkScanner.cs │ │ │ │ └── PortScanner.cs │ │ │ └── Storage/ │ │ │ ├── PhysicalFileProviderFactory.cs │ │ │ ├── PublishedNodesConverter.cs │ │ │ └── PublishedNodesProvider.cs │ │ └── tests/ │ │ ├── Azure.IIoT.OpcUa.Publisher.Tests.csproj │ │ ├── GlobalSuppressions.cs │ │ ├── Logging.cs │ │ ├── Model/ │ │ │ └── MonitoredItemModelTests.cs │ │ ├── Parser/ │ │ │ ├── ContentFilterParserTests.cs │ │ │ ├── EventFilterParserTests.cs │ │ │ └── TestParserContext.cs │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ ├── Publisher/ │ │ │ ├── empty_pn.json │ │ │ ├── pn_2.5_legacy.json │ │ │ ├── pn_2.5_legacy_error.json │ │ │ ├── pn_assets.json │ │ │ ├── pn_assets_with_optional_fields.json │ │ │ ├── pn_events.json │ │ │ ├── pn_opc_nodes_empty.json │ │ │ ├── pn_opc_nodes_empty_and_null.json │ │ │ ├── pn_opc_nodes_null.json │ │ │ ├── pn_pending_alarms.json │ │ │ ├── publishednodes.json │ │ │ ├── publishednodes_with_duplicates.json │ │ │ └── publishednodeswithoptionalfields.json │ │ ├── Runtime/ │ │ │ └── TopicBuilderTests.cs │ │ ├── Services/ │ │ │ ├── Alarms/ │ │ │ │ └── NodeServicesTests.cs │ │ │ ├── Asset/ │ │ │ │ ├── ConfigurationTest1.cs │ │ │ │ ├── ConfigurationTest2.cs │ │ │ │ ├── ConfigurationTest3.cs │ │ │ │ ├── ConfigurationTest4.cs │ │ │ │ ├── WriteCollection1.cs │ │ │ │ ├── WriteCollection2.cs │ │ │ │ ├── WriteCollection3.cs │ │ │ │ └── WriteCollection4.cs │ │ │ ├── AssetDeviceIntegrationTests.cs │ │ │ ├── DeterministicAlarms/ │ │ │ │ ├── NodeServicesTests1.cs │ │ │ │ └── NodeServicesTests2.cs │ │ │ ├── Encoder/ │ │ │ │ ├── MonitoredItemMessageEncoderJsonGzipTests.cs │ │ │ │ ├── MonitoredItemMessageEncoderJsonTests.cs │ │ │ │ ├── NetworkMessage.cs │ │ │ │ ├── NetworkMessageEncoderJsonGzipTests.cs │ │ │ │ ├── NetworkMessageEncoderJsonTests.cs │ │ │ │ ├── NetworkMessageEncoderLegacyTests.cs │ │ │ │ └── NetworkMessageEncoderUadpTests.cs │ │ │ ├── FileSystem/ │ │ │ │ ├── BrowseTests.cs │ │ │ │ ├── FileCollection.cs │ │ │ │ ├── OperationsTests.cs │ │ │ │ ├── ReadTests.cs │ │ │ │ └── WriteTests.cs │ │ │ ├── HistoricalAccess/ │ │ │ │ ├── NodeServicesTests.cs │ │ │ │ ├── ReadAtTimesTests.cs │ │ │ │ ├── ReadCollection.cs │ │ │ │ ├── ReadModifiedTests.cs │ │ │ │ ├── ReadProcessedTests.cs │ │ │ │ ├── ReadValuesTests.cs │ │ │ │ └── UpdateValuesTests.cs │ │ │ ├── HistoricalEvents/ │ │ │ │ ├── NodeServicesTests.cs │ │ │ │ └── ReadCollection.cs │ │ │ ├── Plc/ │ │ │ │ ├── NodeServicesTests1.cs │ │ │ │ └── NodeServicesTests2.cs │ │ │ ├── PublishedNodesJsonServicesTests.cs │ │ │ ├── RuntimeStateReporterTests.cs │ │ │ ├── SimpleEvents/ │ │ │ │ └── NodeServicesTests.cs │ │ │ └── TestData/ │ │ │ ├── BrowsePathTests.cs │ │ │ ├── BrowseStreamTests.cs │ │ │ ├── BrowseTests.cs │ │ │ ├── CallArrayTests.cs │ │ │ ├── CallScalarTests.cs │ │ │ ├── ExpandTests1.cs │ │ │ ├── ExpandTests2.cs │ │ │ ├── MetadataArrayTests.cs │ │ │ ├── MetadataScalarTests.cs │ │ │ ├── MetadataTests.cs │ │ │ ├── ReadArrayTests.cs │ │ │ ├── ReadCollection.cs │ │ │ ├── ReadScalarTests.cs │ │ │ ├── WriteArrayTests.cs │ │ │ ├── WriteCollection.cs │ │ │ └── WriteScalarTests.cs │ │ ├── Stack/ │ │ │ ├── Extensions/ │ │ │ │ ├── RelativePathExTests.cs │ │ │ │ └── SequenceNumberTests.cs │ │ │ ├── GetBrowsePathsFromRootTests.cs │ │ │ ├── GetSimpleEventFilterTests.cs │ │ │ ├── OpcUaApplicationTests.cs │ │ │ ├── OpcUaMonitoredItemTests.cs │ │ │ ├── OpcUaMonitoredItemTestsBase.cs │ │ │ └── Transport/ │ │ │ ├── Extensions/ │ │ │ │ └── NetworkInformationExTests.cs │ │ │ └── Models/ │ │ │ ├── AddressRangeTests.cs │ │ │ ├── IPv4AddressTests.cs │ │ │ └── PortRangeTests.cs │ │ ├── Storage/ │ │ │ └── PublishedNodesJobConverterTests.cs │ │ └── Utils/ │ │ ├── TempFileProviderBase.cs │ │ └── Utils.cs │ ├── Azure.IIoT.OpcUa.Publisher.Models/ │ │ ├── src/ │ │ │ ├── AdditionalData.cs │ │ │ ├── AggregateConfigurationModel.cs │ │ │ ├── AggregateFilterModel.cs │ │ │ ├── ApplicationInfoModel.cs │ │ │ ├── ApplicationRegistrationModel.cs │ │ │ ├── ApplicationType.cs │ │ │ ├── AttributeReadRequestModel.cs │ │ │ ├── AttributeReadResponseModel.cs │ │ │ ├── AttributeWriteRequestModel.cs │ │ │ ├── AttributeWriteResponseModel.cs │ │ │ ├── AuthenticationMethodModel.cs │ │ │ ├── Azure.IIoT.OpcUa.Publisher.Models.csproj │ │ │ ├── BrowseDirection.cs │ │ │ ├── BrowseFirstRequestModel.cs │ │ │ ├── BrowseFirstResponseModel.cs │ │ │ ├── BrowseNextRequestModel.cs │ │ │ ├── BrowseNextResponseModel.cs │ │ │ ├── BrowsePathRequestModel.cs │ │ │ ├── BrowsePathResponseModel.cs │ │ │ ├── BrowseStreamChunkModel.cs │ │ │ ├── BrowseStreamRequestModel.cs │ │ │ ├── BrowseViewModel.cs │ │ │ ├── CertificateStoreName.cs │ │ │ ├── ChannelDiagnosticModel.cs │ │ │ ├── ChannelKeyModel.cs │ │ │ ├── ConditionHandlingOptionsModel.cs │ │ │ ├── ConnectionDiagnosticsModel.cs │ │ │ ├── ConnectionModel.cs │ │ │ ├── ConnectionOptions.cs │ │ │ ├── Constants.cs │ │ │ ├── ContentFilterElementModel.cs │ │ │ ├── ContentFilterModel.cs │ │ │ ├── CredentialModel.cs │ │ │ ├── CredentialType.cs │ │ │ ├── DataChangeFilterModel.cs │ │ │ ├── DataChangeTriggerType.cs │ │ │ ├── DataLocation.cs │ │ │ ├── DataSetFieldContentFlags.cs │ │ │ ├── DataSetMessageContentFlags.cs │ │ │ ├── DataSetMetaDataModel.cs │ │ │ ├── DataSetOrderingType.cs │ │ │ ├── DataSetRoutingMode.cs │ │ │ ├── DataSetWriterMessageSettingsModel.cs │ │ │ ├── DataSetWriterModel.cs │ │ │ ├── DataTypeMetadataModel.cs │ │ │ ├── DeadbandType.cs │ │ │ ├── DeleteEventsDetailsModel.cs │ │ │ ├── DeleteValuesAtTimesDetailsModel.cs │ │ │ ├── DeleteValuesDetailsModel.cs │ │ │ ├── DiagnosticsLevel.cs │ │ │ ├── DiagnosticsModel.cs │ │ │ ├── DiscoveryCancelRequestModel.cs │ │ │ ├── DiscoveryConfigModel.cs │ │ │ ├── DiscoveryEventModel.cs │ │ │ ├── DiscoveryMode.cs │ │ │ ├── DiscoveryProgressModel.cs │ │ │ ├── DiscoveryProgressType.cs │ │ │ ├── DiscoveryRequestModel.cs │ │ │ ├── DiscoveryResultModel.cs │ │ │ ├── EndpointConnectivityState.cs │ │ │ ├── EndpointEventModel.cs │ │ │ ├── EndpointEventType.cs │ │ │ ├── EndpointInfoModel.cs │ │ │ ├── EndpointModel.cs │ │ │ ├── EndpointRegistrationModel.cs │ │ │ ├── EnumDescriptionModel.cs │ │ │ ├── EnumFieldDescriptionModel.cs │ │ │ ├── EventFilterModel.cs │ │ │ ├── ExceptionDeviationType.cs │ │ │ ├── ExtensionFieldModel.cs │ │ │ ├── FileInfoModel.cs │ │ │ ├── FileOpenWriteOptionsModel.cs │ │ │ ├── FileSystemObjectModel.cs │ │ │ ├── FileWriteMode.cs │ │ │ ├── FilterOperandModel.cs │ │ │ ├── FilterOperatorType.cs │ │ │ ├── GetConfiguredEndpointsRequestModel.cs │ │ │ ├── GetConfiguredEndpointsResponseModel.cs │ │ │ ├── GetConfiguredNodesOnEndpointResponseModel.cs │ │ │ ├── HeartbeatBehavior.cs │ │ │ ├── HistoricEventModel.cs │ │ │ ├── HistoricValueModel.cs │ │ │ ├── HistoryConfigurationModel.cs │ │ │ ├── HistoryConfigurationRequestModel.cs │ │ │ ├── HistoryConfigurationResponseModel.cs │ │ │ ├── HistoryReadNextRequestModel.cs │ │ │ ├── HistoryReadNextResponseModel.cs │ │ │ ├── HistoryReadRequestModel.cs │ │ │ ├── HistoryReadResponseModel.cs │ │ │ ├── HistoryServerCapabilitiesModel.cs │ │ │ ├── HistoryUpdateOperation.cs │ │ │ ├── HistoryUpdateRequestModel.cs │ │ │ ├── HistoryUpdateResponseModel.cs │ │ │ ├── InstanceDeclarationModel.cs │ │ │ ├── LocalizedTextModel.cs │ │ │ ├── MessageEncoding.cs │ │ │ ├── MessageTimestamp.cs │ │ │ ├── MessagingMode.cs │ │ │ ├── MethodCallArgumentModel.cs │ │ │ ├── MethodCallRequestModel.cs │ │ │ ├── MethodCallResponseModel.cs │ │ │ ├── MethodMetadataArgumentModel.cs │ │ │ ├── MethodMetadataModel.cs │ │ │ ├── MethodMetadataRequestModel.cs │ │ │ ├── MethodMetadataResponseModel.cs │ │ │ ├── ModelChangeHandlingOptionsModel.cs │ │ │ ├── ModificationInfoModel.cs │ │ │ ├── MonitoredItemWatchdogCondition.cs │ │ │ ├── MonitoringItemMode.cs │ │ │ ├── NamespaceFormat.cs │ │ │ ├── NetworkMessageContentFlags.cs │ │ │ ├── NodeAccessLevel.cs │ │ │ ├── NodeAccessRestrictions.cs │ │ │ ├── NodeAttribute.cs │ │ │ ├── NodeClass.cs │ │ │ ├── NodeEventNotifier.cs │ │ │ ├── NodeIdModel.cs │ │ │ ├── NodeMetadataRequestModel.cs │ │ │ ├── NodeMetadataResponseModel.cs │ │ │ ├── NodeModel.cs │ │ │ ├── NodePathTargetModel.cs │ │ │ ├── NodeReferenceModel.cs │ │ │ ├── NodeType.cs │ │ │ ├── NodeValueRank.cs │ │ │ ├── OpcAuthenticationMode.cs │ │ │ ├── OpcNodeModel.cs │ │ │ ├── OperationContextModel.cs │ │ │ ├── OperationLimitsModel.cs │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ ├── PublishBulkRequestModel.cs │ │ │ ├── PublishBulkResponseModel.cs │ │ │ ├── PublishDiagnosticInfoModel.cs │ │ │ ├── PublishStartRequestModel.cs │ │ │ ├── PublishStartResponseModel.cs │ │ │ ├── PublishStopRequestModel.cs │ │ │ ├── PublishStopResponseModel.cs │ │ │ ├── PublishedDataItemsModel.cs │ │ │ ├── PublishedDataSetEventModel.cs │ │ │ ├── PublishedDataSetMessageSchemaModel.cs │ │ │ ├── PublishedDataSetMetaDataModel.cs │ │ │ ├── PublishedDataSetMethodModel.cs │ │ │ ├── PublishedDataSetModel.cs │ │ │ ├── PublishedDataSetSettingsModel.cs │ │ │ ├── PublishedDataSetSourceModel.cs │ │ │ ├── PublishedDataSetTriggerModel.cs │ │ │ ├── PublishedDataSetVariableModel.cs │ │ │ ├── PublishedEventItemsModel.cs │ │ │ ├── PublishedFieldMetaDataModel.cs │ │ │ ├── PublishedItemListRequestModel.cs │ │ │ ├── PublishedItemListResponseModel.cs │ │ │ ├── PublishedItemModel.cs │ │ │ ├── PublishedMethodItemsModel.cs │ │ │ ├── PublishedNetworkMessageSchemaModel.cs │ │ │ ├── PublishedNodeCreateAssetRequestModel.cs │ │ │ ├── PublishedNodeDeleteAssetRequestModel.cs │ │ │ ├── PublishedNodeExpansionModel.cs │ │ │ ├── PublishedNodesEntryModel.cs │ │ │ ├── PublishedNodesEntryRequestModel.cs │ │ │ ├── PublishedNodesResponseModel.cs │ │ │ ├── PublisherDiagnosticTargetType.cs │ │ │ ├── PublishingQueueSettingsModel.cs │ │ │ ├── QueryCompilationRequestModel.cs │ │ │ ├── QueryCompilationResponseModel.cs │ │ │ ├── QueryType.cs │ │ │ ├── ReadEventsDetailsModel.cs │ │ │ ├── ReadModifiedValuesDetailsModel.cs │ │ │ ├── ReadProcessedValuesDetailsModel.cs │ │ │ ├── ReadRequestModel.cs │ │ │ ├── ReadResponseModel.cs │ │ │ ├── ReadValuesAtTimesDetailsModel.cs │ │ │ ├── ReadValuesDetailsModel.cs │ │ │ ├── RelativePathElementModel.cs │ │ │ ├── RequestEnvelope.cs │ │ │ ├── RequestHeaderModel.cs │ │ │ ├── RolePermissionModel.cs │ │ │ ├── RolePermissions.cs │ │ │ ├── RuntimeStateEventModel.cs │ │ │ ├── RuntimeStateEventType.cs │ │ │ ├── SecurityMode.cs │ │ │ ├── ServerCapabilitiesModel.cs │ │ │ ├── ServerEndpointQueryModel.cs │ │ │ ├── ServerRegistrationRequestModel.cs │ │ │ ├── ServiceCounterModel.cs │ │ │ ├── ServiceResponse.cs │ │ │ ├── ServiceResultModel.cs │ │ │ ├── SessionDiagnosticsModel.cs │ │ │ ├── SetConfiguredEndpointsRequestModel.cs │ │ │ ├── SimpleAttributeOperandModel.cs │ │ │ ├── SimpleTypeDescriptionModel.cs │ │ │ ├── SkipValidationAttribute.cs │ │ │ ├── StructureDescriptionModel.cs │ │ │ ├── StructureFieldDescriptionModel.cs │ │ │ ├── StructureType.cs │ │ │ ├── SubscriptionDiagnosticsModel.cs │ │ │ ├── SubscriptionWatchdogBehavior.cs │ │ │ ├── TestConnectionRequestModel.cs │ │ │ ├── TestConnectionResponseModel.cs │ │ │ ├── TimestampsToReturn.cs │ │ │ ├── TypeDefinitionModel.cs │ │ │ ├── UpdateEventsDetailsModel.cs │ │ │ ├── UpdateValuesDetailsModel.cs │ │ │ ├── UserIdentityModel.cs │ │ │ ├── ValueReadRequestModel.cs │ │ │ ├── ValueReadResponseModel.cs │ │ │ ├── ValueWriteRequestModel.cs │ │ │ ├── ValueWriteResponseModel.cs │ │ │ ├── VariableMetadataModel.cs │ │ │ ├── WriteRequestModel.cs │ │ │ ├── WriteResponseModel.cs │ │ │ ├── WriterGroupDiagnosticModel.cs │ │ │ ├── WriterGroupMessageSettingsModel.cs │ │ │ ├── WriterGroupModel.cs │ │ │ ├── WriterGroupTransport.cs │ │ │ ├── X509CertificateChainModel.cs │ │ │ ├── X509CertificateModel.cs │ │ │ └── X509ChainStatus.cs │ │ └── tests/ │ │ ├── Azure.IIoT.OpcUa.Publisher.Models.Tests.csproj │ │ ├── Fixtures/ │ │ │ └── TypeFixture.cs │ │ ├── GlobalSuppressions.cs │ │ ├── JsonSerializerTests.cs │ │ ├── MsgPackSerializerTests.cs │ │ ├── NewtonsoftSerializerTests.cs │ │ └── PublishNodesEndpointApiModelTests.cs │ ├── Azure.IIoT.OpcUa.Publisher.Module/ │ │ ├── cli/ │ │ │ ├── Azure.IIoT.OpcUa.Publisher.Module.Cli.csproj │ │ │ ├── Initfiles/ │ │ │ │ ├── Kepserver.init │ │ │ │ ├── MachineTools.init │ │ │ │ ├── Machinery.init │ │ │ │ ├── Objects.init │ │ │ │ └── Variables.init │ │ │ ├── Profiles/ │ │ │ │ ├── AllBad.json │ │ │ │ ├── BrowsePath.json │ │ │ │ ├── CyclicReads.json │ │ │ │ ├── DataItems.json │ │ │ │ ├── DataSetTopics.json │ │ │ │ ├── Deadband.json │ │ │ │ ├── Empty.json │ │ │ │ ├── Extremes.json │ │ │ │ ├── FastTime.json │ │ │ │ ├── FixedAndData.json │ │ │ │ ├── Fixedvalue.json │ │ │ │ ├── Heartbeat.json │ │ │ │ ├── Heartbeat2.json │ │ │ │ ├── Heartbeat3.json │ │ │ │ ├── Isa95Jobs.json │ │ │ │ ├── KeepAlive.json │ │ │ │ ├── KeyFrames.json │ │ │ │ ├── ModelChanges.json │ │ │ │ ├── MultiDataSetWriter.json │ │ │ │ ├── MultiEndpoint.json │ │ │ │ ├── MultiWriterGroup.json │ │ │ │ ├── MultiWriterGroupFs.json │ │ │ │ ├── NoNodes.json │ │ │ │ ├── PendingAlarms.json │ │ │ │ ├── PlcSimulation.json │ │ │ │ ├── RegisteredRead.json │ │ │ │ ├── SimpleEvents.json │ │ │ │ ├── SlowSample.json │ │ │ │ ├── SomeBad.json │ │ │ │ ├── SubscribeErrors.json │ │ │ │ ├── TopicPerNode.json │ │ │ │ └── UnifiedNamespace.json │ │ │ ├── Program.cs │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ └── publishednodes.json │ │ ├── src/ │ │ │ ├── Azure.IIoT.OpcUa.Publisher.Module.csproj │ │ │ ├── Controllers/ │ │ │ │ ├── CertificatesController.cs │ │ │ │ ├── ConfigurationController.cs │ │ │ │ ├── DiagnosticsController.cs │ │ │ │ ├── DiscoveryController.cs │ │ │ │ ├── FileSystemController.cs │ │ │ │ ├── GeneralController.cs │ │ │ │ ├── HistoryController.cs │ │ │ │ ├── LegacyController.cs │ │ │ │ ├── PublisherController.cs │ │ │ │ └── WriterController.cs │ │ │ ├── Filters/ │ │ │ │ ├── ControllerExceptionFilterAttribute.cs │ │ │ │ └── RouterExceptionFilterAttribute.cs │ │ │ ├── Program.cs │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ ├── Runtime/ │ │ │ │ ├── CommandLine.cs │ │ │ │ ├── Configuration.cs │ │ │ │ ├── Security.cs │ │ │ │ └── Syslog.cs │ │ │ └── Startup.cs │ │ └── tests/ │ │ ├── Azure.IIoT.OpcUa.Publisher.Module.Tests.csproj │ │ ├── Clients/ │ │ │ ├── Adapters/ │ │ │ │ ├── DiscoveryApiAdapter.cs │ │ │ │ ├── HistoryApiAdapter.cs │ │ │ │ ├── PublisherApiAdapter.cs │ │ │ │ └── TwinApiAdapter.cs │ │ │ ├── ConfigurationServicesRestClient.cs │ │ │ ├── FileSystemServicesRestClient.cs │ │ │ ├── HistoryServicesRestClient.cs │ │ │ └── NodeServicesRestClient.cs │ │ ├── Controller/ │ │ │ ├── Alarms/ │ │ │ │ ├── Json/ │ │ │ │ │ └── NodeServicesTests.cs │ │ │ │ └── MsgPack/ │ │ │ │ └── NodeServicesTests.cs │ │ │ ├── Asset/ │ │ │ │ ├── Json/ │ │ │ │ │ ├── ConfigurationTest1.cs │ │ │ │ │ ├── ConfigurationTest2.cs │ │ │ │ │ ├── ConfigurationTest3.cs │ │ │ │ │ ├── ConfigurationTest4.cs │ │ │ │ │ ├── WriteCollection1.cs │ │ │ │ │ ├── WriteCollection2.cs │ │ │ │ │ ├── WriteCollection3.cs │ │ │ │ │ └── WriteCollection4.cs │ │ │ │ └── MsgPack/ │ │ │ │ ├── ConfigurationTest1.cs │ │ │ │ ├── ConfigurationTest2.cs │ │ │ │ ├── ConfigurationTest3.cs │ │ │ │ ├── ConfigurationTest4.cs │ │ │ │ ├── WriteCollection1.cs │ │ │ │ ├── WriteCollection2.cs │ │ │ │ ├── WriteCollection3.cs │ │ │ │ └── WriteCollection4.cs │ │ │ ├── DeterministicAlarms/ │ │ │ │ ├── Json/ │ │ │ │ │ ├── NodeServicesTests1.cs │ │ │ │ │ └── NodeServicesTests2.cs │ │ │ │ └── MsgPack/ │ │ │ │ ├── NodeServicesTests1.cs │ │ │ │ └── NodeServicesTests2.cs │ │ │ ├── DmApiPublisherControllerTests.cs │ │ │ ├── FileSystem/ │ │ │ │ ├── Json/ │ │ │ │ │ ├── BrowseTests.cs │ │ │ │ │ ├── FileCollection.cs │ │ │ │ │ ├── OperationsTests.cs │ │ │ │ │ ├── ReadTests.cs │ │ │ │ │ └── WriteTests.cs │ │ │ │ └── MsgPack/ │ │ │ │ ├── BrowseTests.cs │ │ │ │ ├── FileCollection.cs │ │ │ │ ├── OperationsTests.cs │ │ │ │ ├── ReadTests.cs │ │ │ │ └── WriteTests.cs │ │ │ ├── HistoricalAccess/ │ │ │ │ ├── Json/ │ │ │ │ │ ├── NodeServicesTests.cs │ │ │ │ │ ├── ReadAtTimesTests.cs │ │ │ │ │ ├── ReadCollection.cs │ │ │ │ │ ├── ReadModifiedTests.cs │ │ │ │ │ ├── ReadProcessedTests.cs │ │ │ │ │ ├── ReadValuesTests.cs │ │ │ │ │ └── UpdateValuesTests.cs │ │ │ │ └── MsgPack/ │ │ │ │ ├── NodeServicesTests.cs │ │ │ │ ├── ReadAtTimesTests.cs │ │ │ │ ├── ReadCollection.cs │ │ │ │ ├── ReadModifiedTests.cs │ │ │ │ ├── ReadProcessedTests.cs │ │ │ │ ├── ReadValuesTests.cs │ │ │ │ └── UpdateValuesTests.cs │ │ │ ├── HistoricalEvents/ │ │ │ │ ├── Json/ │ │ │ │ │ ├── NodeServicesTests.cs │ │ │ │ │ └── ReadCollection.cs │ │ │ │ └── MsgPack/ │ │ │ │ ├── NodeServicesTests.cs │ │ │ │ └── ReadCollection.cs │ │ │ ├── Plc/ │ │ │ │ ├── Json/ │ │ │ │ │ ├── NodeServicesTests1.cs │ │ │ │ │ └── NodeServicesTests2.cs │ │ │ │ └── MsgPack/ │ │ │ │ ├── NodeServicesTests1.cs │ │ │ │ └── NodeServicesTests2.cs │ │ │ ├── SimpleEvents/ │ │ │ │ ├── Json/ │ │ │ │ │ └── NodeServicesTests.cs │ │ │ │ └── MsgPack/ │ │ │ │ └── NodeServicesTests.cs │ │ │ └── TestData/ │ │ │ ├── Json/ │ │ │ │ ├── BrowsePathTests.cs │ │ │ │ ├── BrowseStreamTests.cs │ │ │ │ ├── BrowseTests.cs │ │ │ │ ├── CallArrayTests.cs │ │ │ │ ├── CallScalarTests.cs │ │ │ │ ├── ExpandTests1.cs │ │ │ │ ├── MetadataArrayTests.cs │ │ │ │ ├── MetadataScalarTests.cs │ │ │ │ ├── MetadataTests.cs │ │ │ │ ├── ReadCollection.cs │ │ │ │ ├── ValueReadArrayTests.cs │ │ │ │ ├── ValueReadScalarTests.cs │ │ │ │ ├── ValueWriteArrayTests.cs │ │ │ │ ├── ValueWriteScalarTests.cs │ │ │ │ └── WriteCollection.cs │ │ │ └── MsgPack/ │ │ │ ├── BrowsePathTests.cs │ │ │ ├── BrowseStreamTests.cs │ │ │ ├── BrowseTests.cs │ │ │ ├── CallArrayTests.cs │ │ │ ├── CallScalarTests.cs │ │ │ ├── ExpandTests1.cs │ │ │ ├── MetadataArrayTests.cs │ │ │ ├── MetadataScalarTests.cs │ │ │ ├── MetadataTests.cs │ │ │ ├── ReadCollection.cs │ │ │ ├── ValueReadArrayTests.cs │ │ │ ├── ValueReadScalarTests.cs │ │ │ ├── ValueWriteArrayTests.cs │ │ │ ├── ValueWriteScalarTests.cs │ │ │ └── WriteCollection.cs │ │ ├── Fixtures/ │ │ │ ├── PublisherIntegrationTestBase.cs │ │ │ ├── PublisherModule.cs │ │ │ ├── PublisherModuleFixture.cs │ │ │ ├── ReferenceServerReadCollection.cs │ │ │ ├── TempFileProviderBase.cs │ │ │ ├── TestSerializerType.cs │ │ │ └── TwinIntegrationTestBase.cs │ │ ├── GlobalSuppressions.cs │ │ ├── Logging.cs │ │ ├── Mqtt/ │ │ │ ├── Alarms/ │ │ │ │ └── NodeServicesTests.cs │ │ │ ├── DeterministicAlarms/ │ │ │ │ ├── NodeServicesTests1.cs │ │ │ │ └── NodeServicesTests2.cs │ │ │ ├── HistoricalAccess/ │ │ │ │ ├── NodeServicesTests.cs │ │ │ │ ├── ReadAtTimesTests.cs │ │ │ │ ├── ReadCollection.cs │ │ │ │ ├── ReadModifiedTests.cs │ │ │ │ ├── ReadProcessedTests.cs │ │ │ │ ├── ReadValuesTests.cs │ │ │ │ └── UpdateValuesTests.cs │ │ │ ├── HistoricalEvents/ │ │ │ │ ├── NodeServicesTests.cs │ │ │ │ └── ReadCollection.cs │ │ │ ├── Plc/ │ │ │ │ ├── NodeServicesTests1.cs │ │ │ │ └── NodeServicesTests2.cs │ │ │ ├── ReferenceServer/ │ │ │ │ ├── MqttConfigurationIntegrationTests.cs │ │ │ │ ├── MqttPubSubIntegrationTests.cs │ │ │ │ └── MqttUnifiedNamespaceTests.cs │ │ │ ├── SimpleEvents/ │ │ │ │ └── NodeServicesTests.cs │ │ │ └── TestData/ │ │ │ ├── BrowsePathTests.cs │ │ │ ├── BrowseStreamTests.cs │ │ │ ├── BrowseTests.cs │ │ │ ├── CallArrayTests.cs │ │ │ ├── CallScalarTests.cs │ │ │ ├── MetadataArrayTests.cs │ │ │ ├── MetadataScalarTests.cs │ │ │ ├── MetadataTests.cs │ │ │ ├── ReadCollection.cs │ │ │ ├── ValueReadArrayTests.cs │ │ │ ├── ValueReadScalarTests.cs │ │ │ ├── ValueWriteArrayTests.cs │ │ │ ├── ValueWriteScalarTests.cs │ │ │ └── WriteCollection.cs │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ ├── Resources/ │ │ │ ├── CyclicRead.json │ │ │ ├── DataItems.json │ │ │ ├── DataItems1.json │ │ │ ├── DataItems2.json │ │ │ ├── Deadband.json │ │ │ ├── DmApiPayloadCollection.json │ │ │ ├── DmApiPayloadTwoEndpoints.json │ │ │ ├── ExtensionFields.json │ │ │ ├── Fixedvalue.json │ │ │ ├── Heartbeat.json │ │ │ ├── Heartbeat2.json │ │ │ ├── HeartbeatErrors.json │ │ │ ├── Isa95Jobs.json │ │ │ ├── KeepAlive.json │ │ │ ├── KeyFrames.json │ │ │ ├── ModelChanges.json │ │ │ ├── PendingAlarms.json │ │ │ ├── RegisteredRead.json │ │ │ ├── SimpleEvents.json │ │ │ ├── SimpleEvents2.json │ │ │ ├── UnifiedNamespace.json │ │ │ └── empty_pn.json │ │ ├── Runtime/ │ │ │ ├── CommandLineTest.cs │ │ │ ├── PublisherCliTests.cs │ │ │ └── PublisherControllerTests.cs │ │ ├── Sdk/ │ │ │ ├── Alarms/ │ │ │ │ └── NodeServicesTests.cs │ │ │ ├── DeterministicAlarms/ │ │ │ │ ├── NodeServicesTests1.cs │ │ │ │ └── NodeServicesTests2.cs │ │ │ ├── HistoricalAccess/ │ │ │ │ ├── NodeServicesTests.cs │ │ │ │ ├── ReadAtTimesTests.cs │ │ │ │ ├── ReadCollection.cs │ │ │ │ ├── ReadModifiedTests.cs │ │ │ │ ├── ReadProcessedTests.cs │ │ │ │ ├── ReadValuesTests.cs │ │ │ │ └── UpdateValuesTests.cs │ │ │ ├── HistoricalEvents/ │ │ │ │ ├── NodeServicesTests.cs │ │ │ │ └── ReadCollection.cs │ │ │ ├── Isa95Jobs/ │ │ │ │ └── BasicPubSubIntegrationTests.cs │ │ │ ├── Plc/ │ │ │ │ ├── NodeServicesTests1.cs │ │ │ │ └── NodeServicesTests2.cs │ │ │ ├── ReferenceServer/ │ │ │ │ ├── AdvancedPubSubIntegrationTests.cs │ │ │ │ ├── BasicPubSubIntegrationTests.cs │ │ │ │ ├── BasicSamplesIntegrationTests.cs │ │ │ │ └── ReverseConnectIntegrationTests.cs │ │ │ ├── SimpleEvents/ │ │ │ │ └── NodeServicesTests.cs │ │ │ └── TestData/ │ │ │ ├── BrowsePathTests.cs │ │ │ ├── BrowseStreamTests.cs │ │ │ ├── BrowseTests.cs │ │ │ ├── CallArrayTests.cs │ │ │ ├── CallScalarTests.cs │ │ │ ├── MetadataArrayTests.cs │ │ │ ├── MetadataScalarTests.cs │ │ │ ├── MetadataTests.cs │ │ │ ├── ReadCollection.cs │ │ │ ├── ValueReadArrayTests.cs │ │ │ ├── ValueReadScalarTests.cs │ │ │ ├── ValueWriteArrayTests.cs │ │ │ ├── ValueWriteScalarTests.cs │ │ │ └── WriteCollection.cs │ │ └── _dummy_.sln │ ├── Azure.IIoT.OpcUa.Publisher.Sdk/ │ │ └── src/ │ │ ├── Azure.IIoT.OpcUa.Publisher.Sdk.csproj │ │ ├── Clients/ │ │ │ ├── DiscoveryApiClient.cs │ │ │ ├── Extensions.cs │ │ │ ├── HistoryApiClient.cs │ │ │ ├── PublisherApiClient.cs │ │ │ └── TwinApiClient.cs │ │ ├── IDiscoveryApi.cs │ │ ├── IHistoryApi.cs │ │ ├── IPublisherApi.cs │ │ ├── ITwinApi.cs │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ └── SdkOptions.cs │ ├── Azure.IIoT.OpcUa.Publisher.Testing/ │ │ ├── cli/ │ │ │ ├── Azure.IIoT.OpcUa.Publisher.Testing.Cli.csproj │ │ │ ├── FlatCertificateStore.cs │ │ │ ├── Program.cs │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ └── TestServerFactory.cs │ │ ├── src/ │ │ │ ├── Alarms/ │ │ │ │ ├── AlarmConditionNodeManager.cs │ │ │ │ ├── AlarmConditionServer.cs │ │ │ │ ├── AlarmConditionServerConfiguration.cs │ │ │ │ ├── AreaState.cs │ │ │ │ ├── ModelUtils.cs │ │ │ │ ├── Namespaces.cs │ │ │ │ ├── SourceState.cs │ │ │ │ ├── UnderlyingSystem.cs │ │ │ │ ├── UnderlyingSystemAlarm.cs │ │ │ │ ├── UnderlyingSystemAlarmStates.cs │ │ │ │ └── UnderlyingSystemSource.cs │ │ │ ├── Asset/ │ │ │ │ ├── AssetNodeManager.cs │ │ │ │ ├── AssetServer.cs │ │ │ │ ├── AssetTag.cs │ │ │ │ ├── FileManager.cs │ │ │ │ ├── IAsset.cs │ │ │ │ ├── ModbusBinding.cs │ │ │ │ ├── ModbusFormExtension.cs │ │ │ │ ├── ModbusProtocol.cs │ │ │ │ ├── ModbusTcpAsset.cs │ │ │ │ ├── Namespaces.cs │ │ │ │ ├── Samples/ │ │ │ │ │ └── SimulatedAsset.td.jsonld │ │ │ │ ├── SimulatedAsset.cs │ │ │ │ ├── SimulatedBinding.cs │ │ │ │ ├── SimulatedFormExtension.cs │ │ │ │ └── ThingDescription.cs │ │ │ ├── Azure.IIoT.OpcUa.Publisher.Testing.Servers.csproj │ │ │ ├── Boiler/ │ │ │ │ ├── BoilerNodeManager.cs │ │ │ │ ├── BoilerServer.cs │ │ │ │ ├── BoilerState.cs │ │ │ │ ├── BoilerStateMachineState.cs │ │ │ │ └── GenericController.cs │ │ │ ├── Common/ │ │ │ │ ├── DataChangeMonitoredItem.cs │ │ │ │ ├── FolderConfiguration.cs │ │ │ │ ├── MonitoredNode.cs │ │ │ │ └── SampleNodeManager.cs │ │ │ ├── DataAccess/ │ │ │ │ ├── BlockState.cs │ │ │ │ ├── DataAccessNodeManager.cs │ │ │ │ ├── DataAccessServer.cs │ │ │ │ ├── DataAccessServerConfiguration.cs │ │ │ │ ├── ModelUtils.cs │ │ │ │ ├── Namespaces.cs │ │ │ │ ├── SegmentBrowser.cs │ │ │ │ ├── SegmentState.cs │ │ │ │ ├── UnderlyingSystem.cs │ │ │ │ ├── UnderlyingSystemBlock.cs │ │ │ │ ├── UnderlyingSystemDataType.cs │ │ │ │ ├── UnderlyingSystemSegment.cs │ │ │ │ ├── UnderlyingSystemTag.cs │ │ │ │ └── UnderlyingSystemTagType.cs │ │ │ ├── DeterministicAlarms/ │ │ │ │ ├── Configuration/ │ │ │ │ │ ├── Alarm.cs │ │ │ │ │ ├── AlarmObjectStates.cs │ │ │ │ │ ├── AlarmsConfiguration.cs │ │ │ │ │ ├── ConditionStates.cs │ │ │ │ │ ├── Event.cs │ │ │ │ │ ├── Folder.cs │ │ │ │ │ ├── Script.cs │ │ │ │ │ ├── ScriptException.cs │ │ │ │ │ ├── Source.cs │ │ │ │ │ ├── StateChange.cs │ │ │ │ │ └── Step.cs │ │ │ │ ├── DeterministicAlarmsNodeManager.cs │ │ │ │ ├── DeterministicAlarmsServer.cs │ │ │ │ ├── Model/ │ │ │ │ │ ├── SimConditionStatesEnum.cs │ │ │ │ │ ├── SimFolderState.cs │ │ │ │ │ └── SimSourceNodeState.cs │ │ │ │ ├── Namespaces.cs │ │ │ │ ├── ScriptEngine.cs │ │ │ │ ├── SimBackend/ │ │ │ │ │ ├── SimAlarmStateBackend.cs │ │ │ │ │ ├── SimBackendService.cs │ │ │ │ │ └── SimSourceNodeBackend.cs │ │ │ │ └── readme.md │ │ │ ├── FileSystem/ │ │ │ │ ├── DirectoryBrowser.cs │ │ │ │ ├── DirectoryObjectState.cs │ │ │ │ ├── FileHandle.cs │ │ │ │ ├── FileObjectState.cs │ │ │ │ ├── FileSystem.cs │ │ │ │ ├── FileSystemNodeManager.cs │ │ │ │ ├── FileSystemServer.cs │ │ │ │ ├── FileSystemServerConfiguration.cs │ │ │ │ ├── ModelUtils.cs │ │ │ │ └── Namespaces.cs │ │ │ ├── Generated/ │ │ │ │ ├── Asset/ │ │ │ │ │ └── Design/ │ │ │ │ │ ├── Asset.Classes.cs │ │ │ │ │ ├── Asset.Constants.cs │ │ │ │ │ └── Asset.NodeSet2.xml │ │ │ │ ├── Boiler/ │ │ │ │ │ └── Design/ │ │ │ │ │ ├── Boiler.Classes.cs │ │ │ │ │ ├── Boiler.Constants.cs │ │ │ │ │ ├── Boiler.NodeIds.csv │ │ │ │ │ ├── Boiler.NodeSet.xml │ │ │ │ │ ├── Boiler.NodeSet2.xml │ │ │ │ │ ├── Boiler.PredefinedNodes.uanodes │ │ │ │ │ ├── Boiler.PredefinedNodes.xml │ │ │ │ │ ├── Boiler.Types.bsd │ │ │ │ │ ├── Boiler.Types.xsd │ │ │ │ │ ├── BoilerDesign.csv │ │ │ │ │ └── BoilerDesign.xml │ │ │ │ ├── BuildDesigns.bat │ │ │ │ ├── BuildNodesets.bat │ │ │ │ ├── HistoricalEvents/ │ │ │ │ │ └── Design/ │ │ │ │ │ ├── HistoricalEvents.Classes.cs │ │ │ │ │ ├── HistoricalEvents.Constants.cs │ │ │ │ │ ├── HistoricalEvents.NodeIds.csv │ │ │ │ │ ├── HistoricalEvents.NodeSet.xml │ │ │ │ │ ├── HistoricalEvents.NodeSet2.xml │ │ │ │ │ ├── HistoricalEvents.PredefinedNodes.uanodes │ │ │ │ │ ├── HistoricalEvents.PredefinedNodes.xml │ │ │ │ │ ├── HistoricalEvents.Types.bsd │ │ │ │ │ ├── HistoricalEvents.Types.xsd │ │ │ │ │ ├── ModelDesign.csv │ │ │ │ │ └── ModelDesign.xml │ │ │ │ ├── Isa95Jobs/ │ │ │ │ │ ├── Design/ │ │ │ │ │ │ ├── UAModel.ISA95_JOBCONTROL_V2.Classes.cs │ │ │ │ │ │ ├── UAModel.ISA95_JOBCONTROL_V2.Constants.cs │ │ │ │ │ │ ├── UAModel.ISA95_JOBCONTROL_V2.DataTypes.cs │ │ │ │ │ │ ├── UAModel.ISA95_JOBCONTROL_V2.NodeIds.csv │ │ │ │ │ │ ├── UAModel.ISA95_JOBCONTROL_V2.NodeIds.permissions.csv │ │ │ │ │ │ ├── UAModel.ISA95_JOBCONTROL_V2.NodeSet.xml │ │ │ │ │ │ ├── UAModel.ISA95_JOBCONTROL_V2.NodeSet2.documentation.csv │ │ │ │ │ │ ├── UAModel.ISA95_JOBCONTROL_V2.NodeSet2.xml │ │ │ │ │ │ ├── UAModel.ISA95_JOBCONTROL_V2.PredefinedNodes.uanodes │ │ │ │ │ │ ├── UAModel.ISA95_JOBCONTROL_V2.PredefinedNodes.xml │ │ │ │ │ │ ├── UAModel.ISA95_JOBCONTROL_V2.Types.bsd │ │ │ │ │ │ └── UAModel.ISA95_JOBCONTROL_V2.Types.xsd │ │ │ │ │ └── Nodesets/ │ │ │ │ │ ├── opc.ua.isa95-jobcontrol.nodeids.csv │ │ │ │ │ ├── opc.ua.isa95-jobcontrol.nodeset2.documentation.csv │ │ │ │ │ ├── opc.ua.isa95-jobcontrol.nodeset2.xml │ │ │ │ │ ├── opc.ua.isa95-jobcontrol.types.bsd │ │ │ │ │ └── opc.ua.isa95-jobcontrol.types.xsd │ │ │ │ ├── MemoryBuffer/ │ │ │ │ │ └── Design/ │ │ │ │ │ ├── MemoryBuffer.Classes.cs │ │ │ │ │ ├── MemoryBuffer.Constants.cs │ │ │ │ │ ├── MemoryBuffer.NodeIds.csv │ │ │ │ │ ├── MemoryBuffer.NodeSet.xml │ │ │ │ │ ├── MemoryBuffer.NodeSet2.xml │ │ │ │ │ ├── MemoryBuffer.PredefinedNodes.uanodes │ │ │ │ │ ├── MemoryBuffer.PredefinedNodes.xml │ │ │ │ │ ├── MemoryBuffer.Types.bsd │ │ │ │ │ ├── MemoryBuffer.Types.xsd │ │ │ │ │ ├── MemoryBufferDesign.csv │ │ │ │ │ └── MemoryBufferDesign.xml │ │ │ │ ├── Plc/ │ │ │ │ │ └── Design/ │ │ │ │ │ ├── ModelDesign.csv │ │ │ │ │ ├── ModelDesign.xml │ │ │ │ │ ├── PlcModel.Classes.cs │ │ │ │ │ ├── PlcModel.Constants.cs │ │ │ │ │ ├── PlcModel.DataTypes.cs │ │ │ │ │ ├── PlcModel.NodeIds.csv │ │ │ │ │ ├── PlcModel.NodeSet.xml │ │ │ │ │ ├── PlcModel.NodeSet2.xml │ │ │ │ │ ├── PlcModel.PredefinedNodes.uanodes │ │ │ │ │ ├── PlcModel.PredefinedNodes.xml │ │ │ │ │ ├── PlcModel.Types.bsd │ │ │ │ │ └── PlcModel.Types.xsd │ │ │ │ ├── SimpleEvents/ │ │ │ │ │ └── Design/ │ │ │ │ │ ├── ModelDesign.csv │ │ │ │ │ ├── ModelDesign.xml │ │ │ │ │ ├── SimpleEvents.Classes.cs │ │ │ │ │ ├── SimpleEvents.Constants.cs │ │ │ │ │ ├── SimpleEvents.DataTypes.cs │ │ │ │ │ ├── SimpleEvents.NodeIds.csv │ │ │ │ │ ├── SimpleEvents.NodeSet.xml │ │ │ │ │ ├── SimpleEvents.NodeSet2.xml │ │ │ │ │ ├── SimpleEvents.PredefinedNodes.uanodes │ │ │ │ │ ├── SimpleEvents.PredefinedNodes.xml │ │ │ │ │ ├── SimpleEvents.Types.bsd │ │ │ │ │ └── SimpleEvents.Types.xsd │ │ │ │ ├── TestData/ │ │ │ │ │ └── Design/ │ │ │ │ │ ├── TestData.Classes.cs │ │ │ │ │ ├── TestData.Constants.cs │ │ │ │ │ ├── TestData.DataTypes.cs │ │ │ │ │ ├── TestData.NodeIds.csv │ │ │ │ │ ├── TestData.NodeSet.xml │ │ │ │ │ ├── TestData.NodeSet2.xml │ │ │ │ │ ├── TestData.PredefinedNodes.uanodes │ │ │ │ │ ├── TestData.PredefinedNodes.xml │ │ │ │ │ ├── TestData.Types.bsd │ │ │ │ │ ├── TestData.Types.xsd │ │ │ │ │ ├── TestDataDesign.csv │ │ │ │ │ └── TestDataDesign.xml │ │ │ │ ├── Vehicles/ │ │ │ │ │ └── Design/ │ │ │ │ │ ├── ModelDesign1.csv │ │ │ │ │ ├── ModelDesign1.xml │ │ │ │ │ ├── ModelDesign2.csv │ │ │ │ │ ├── ModelDesign2.xml │ │ │ │ │ ├── Vehicles.Instances.Constants.cs │ │ │ │ │ ├── Vehicles.Instances.DataTypes.cs │ │ │ │ │ ├── Vehicles.Instances.NodeIds.csv │ │ │ │ │ ├── Vehicles.Instances.NodeSet.xml │ │ │ │ │ ├── Vehicles.Instances.NodeSet2.xml │ │ │ │ │ ├── Vehicles.Instances.PredefinedNodes.uanodes │ │ │ │ │ ├── Vehicles.Instances.PredefinedNodes.xml │ │ │ │ │ ├── Vehicles.Instances.Types.bsd │ │ │ │ │ ├── Vehicles.Instances.Types.xsd │ │ │ │ │ ├── Vehicles.Types.Classes.cs │ │ │ │ │ ├── Vehicles.Types.Constants.cs │ │ │ │ │ ├── Vehicles.Types.DataTypes.cs │ │ │ │ │ ├── Vehicles.Types.NodeIds.csv │ │ │ │ │ ├── Vehicles.Types.NodeSet.xml │ │ │ │ │ ├── Vehicles.Types.NodeSet2.xml │ │ │ │ │ ├── Vehicles.Types.PredefinedNodes.uanodes │ │ │ │ │ ├── Vehicles.Types.PredefinedNodes.xml │ │ │ │ │ ├── Vehicles.Types.Types.bsd │ │ │ │ │ └── Vehicles.Types.Types.xsd │ │ │ │ └── Views/ │ │ │ │ └── Design/ │ │ │ │ ├── Engineering.Constants.cs │ │ │ │ ├── Engineering.NodeIds.csv │ │ │ │ ├── Engineering.NodeSet.xml │ │ │ │ ├── Engineering.NodeSet2.xml │ │ │ │ ├── Engineering.PredefinedNodes.uanodes │ │ │ │ ├── Engineering.PredefinedNodes.xml │ │ │ │ ├── Engineering.Types.bsd │ │ │ │ ├── Engineering.Types.xsd │ │ │ │ ├── EngineeringDesign.csv │ │ │ │ ├── EngineeringDesign.xml │ │ │ │ ├── Model.Classes.cs │ │ │ │ ├── Model.Constants.cs │ │ │ │ ├── Model.NodeIds.csv │ │ │ │ ├── Model.NodeSet.xml │ │ │ │ ├── Model.NodeSet2.xml │ │ │ │ ├── Model.PredefinedNodes.uanodes │ │ │ │ ├── Model.PredefinedNodes.xml │ │ │ │ ├── Model.Types.bsd │ │ │ │ ├── Model.Types.xsd │ │ │ │ ├── ModelDesign.csv │ │ │ │ ├── ModelDesign.xml │ │ │ │ ├── Operations.Constants.cs │ │ │ │ ├── Operations.NodeIds.csv │ │ │ │ ├── Operations.NodeSet.xml │ │ │ │ ├── Operations.NodeSet2.xml │ │ │ │ ├── Operations.PredefinedNodes.uanodes │ │ │ │ ├── Operations.PredefinedNodes.xml │ │ │ │ ├── Operations.Types.bsd │ │ │ │ ├── Operations.Types.xsd │ │ │ │ ├── OperationsDesign.csv │ │ │ │ └── OperationsDesign.xml │ │ │ ├── GlobalSuppressions.cs │ │ │ ├── HistoricalAccess/ │ │ │ │ ├── ArchiveFolder.cs │ │ │ │ ├── ArchiveFolderBrowser.cs │ │ │ │ ├── ArchiveFolderState.cs │ │ │ │ ├── ArchiveItem.cs │ │ │ │ ├── ArchiveItemState.cs │ │ │ │ ├── Data/ │ │ │ │ │ ├── Dynamic/ │ │ │ │ │ │ ├── Boolean.txt │ │ │ │ │ │ ├── Byte.txt │ │ │ │ │ │ ├── DateTime.txt │ │ │ │ │ │ ├── Double.txt │ │ │ │ │ │ ├── Float.txt │ │ │ │ │ │ ├── Int16.txt │ │ │ │ │ │ ├── Int32.txt │ │ │ │ │ │ ├── Int64.txt │ │ │ │ │ │ ├── SByte.txt │ │ │ │ │ │ ├── String.txt │ │ │ │ │ │ ├── UInt16.txt │ │ │ │ │ │ ├── UInt32.txt │ │ │ │ │ │ └── UInt64.txt │ │ │ │ │ └── Sample/ │ │ │ │ │ ├── Boolean.txt │ │ │ │ │ ├── Byte.txt │ │ │ │ │ ├── ByteString.txt │ │ │ │ │ ├── DateTime.txt │ │ │ │ │ ├── Double.txt │ │ │ │ │ ├── Float.txt │ │ │ │ │ ├── Historian1.xlsx │ │ │ │ │ ├── Historian1ExpectedData.csv │ │ │ │ │ ├── Historian2ExpectedData.csv │ │ │ │ │ ├── Historian3ExpectedData.csv │ │ │ │ │ ├── Int16.txt │ │ │ │ │ ├── Int32.txt │ │ │ │ │ ├── Int64.txt │ │ │ │ │ ├── SByte.txt │ │ │ │ │ ├── String.txt │ │ │ │ │ ├── UInt16.txt │ │ │ │ │ ├── UInt32.txt │ │ │ │ │ └── UInt64.txt │ │ │ │ ├── DataFileReader.cs │ │ │ │ ├── HistoricalAccessNodeManager.cs │ │ │ │ ├── HistoricalAccessServer.cs │ │ │ │ ├── HistoricalAccessServerConfiguration.cs │ │ │ │ ├── Namespaces.cs │ │ │ │ ├── NodeTypes.cs │ │ │ │ └── UnderlyingSystem.cs │ │ │ ├── HistoricalEvents/ │ │ │ │ ├── HistoricalEventsNodeManager.cs │ │ │ │ ├── HistoricalEventsServer.cs │ │ │ │ ├── HistoricalEventsServerConfiguration.cs │ │ │ │ └── ReportGenerator.cs │ │ │ ├── IServerFactory.cs │ │ │ ├── IServerHost.cs │ │ │ ├── ITestServer.cs │ │ │ ├── Isa95Jobs/ │ │ │ │ ├── Isa95JobControlNodeManager.cs │ │ │ │ ├── Isa95JobControlServer.cs │ │ │ │ └── Isa95JobControlServerConfiguration.cs │ │ │ ├── MemoryBuffer/ │ │ │ │ ├── MemoryBufferBrowser.cs │ │ │ │ ├── MemoryBufferConfiguration.cs │ │ │ │ ├── MemoryBufferMonitoredItem.cs │ │ │ │ ├── MemoryBufferNodeManager.cs │ │ │ │ ├── MemoryBufferServer.cs │ │ │ │ ├── MemoryBufferState.cs │ │ │ │ └── MemoryTagState.cs │ │ │ ├── PerfTest/ │ │ │ │ ├── MemoryRegisterState.cs │ │ │ │ ├── Namespaces.cs │ │ │ │ ├── PerfTestNodeManager.cs │ │ │ │ ├── PerfTestServer.cs │ │ │ │ ├── PerfTestServerConfiguration.cs │ │ │ │ └── UnderlyingSystem.cs │ │ │ ├── Plc/ │ │ │ │ ├── Models/ │ │ │ │ │ ├── BaseDataVariableStateExtended.cs │ │ │ │ │ ├── IPluginNodes.cs │ │ │ │ │ ├── NodeWithIntervals.cs │ │ │ │ │ └── SimulatedVariableNode.cs │ │ │ │ ├── NamespaceType.cs │ │ │ │ ├── Namespaces.cs │ │ │ │ ├── PlcNodeManager.cs │ │ │ │ ├── PlcServer.cs │ │ │ │ ├── PlcSimulation.cs │ │ │ │ └── PluginNodes/ │ │ │ │ ├── ComplexTypePluginNode.cs │ │ │ │ ├── DataPluginNodes.cs │ │ │ │ ├── DeterministicGuidPluginNodes.cs │ │ │ │ ├── DipPluginNode.cs │ │ │ │ ├── FastPluginNodes.cs │ │ │ │ ├── FastRandomPluginNodes.cs │ │ │ │ ├── LongIdPluginNode.cs │ │ │ │ ├── LongStringPluginNodes.cs │ │ │ │ ├── NegTrendPluginNode.cs │ │ │ │ ├── NodeType.cs │ │ │ │ ├── PosTrendPluginNode.cs │ │ │ │ ├── SlowFastCommon.cs │ │ │ │ ├── SlowPluginNodes.cs │ │ │ │ ├── SlowRandomPluginNodes.cs │ │ │ │ ├── SpecialCharNamePluginNode.cs │ │ │ │ └── SpikePluginNode.cs │ │ │ ├── Properties/ │ │ │ │ └── AssemblyInfo.cs │ │ │ ├── Reference/ │ │ │ │ ├── Namespaces.cs │ │ │ │ ├── ReferenceNodeManager.cs │ │ │ │ ├── ReferenceServer.cs │ │ │ │ └── ReferenceServerConfiguration.cs │ │ │ ├── ServerConsoleHost.cs │ │ │ ├── ServerFactory.cs │ │ │ ├── SimpleEvents/ │ │ │ │ ├── SimpleEventsNodeManager.cs │ │ │ │ ├── SimpleEventsServer.cs │ │ │ │ └── SimpleEventsServerConfiguration.cs │ │ │ ├── TestData/ │ │ │ │ ├── AnalogArrayValueObjectState.cs │ │ │ │ ├── AnalogScalarValueObjectState.cs │ │ │ │ ├── ArrayValueObjectState.cs │ │ │ │ ├── HistoryArchive.cs │ │ │ │ ├── MethodTestState.cs │ │ │ │ ├── ScalarValueObjectState.cs │ │ │ │ ├── TestDataNodeManager.cs │ │ │ │ ├── TestDataNodeManagerConfiguration.cs │ │ │ │ ├── TestDataObjectState.cs │ │ │ │ ├── TestDataServer.cs │ │ │ │ ├── TestDataSystem.cs │ │ │ │ ├── TestSystemConditionState.cs │ │ │ │ ├── UserArrayValueObjectState.cs │ │ │ │ └── UserScalarValueObjectState.cs │ │ │ ├── Utils/ │ │ │ │ ├── DeterministicGuid.cs │ │ │ │ ├── FastTimer.cs │ │ │ │ ├── FastTimerElapsedEventArgs.cs │ │ │ │ ├── ITimer.cs │ │ │ │ ├── TestDataGenerator.cs │ │ │ │ └── TimeService.cs │ │ │ ├── Vehicles/ │ │ │ │ ├── Namespaces.cs │ │ │ │ ├── VehiclesNodeManager.cs │ │ │ │ ├── VehiclesServer.cs │ │ │ │ └── VehiclesServerConfiguration.cs │ │ │ └── Views/ │ │ │ ├── ViewsNodeManager.cs │ │ │ ├── ViewsServer.cs │ │ │ └── ViewsServerConfiguration.cs │ │ └── tests/ │ │ ├── Azure.IIoT.OpcUa.Publisher.Testing.csproj │ │ ├── Extensions/ │ │ │ └── OpcUaClientManagerEx.cs │ │ ├── Fixtures/ │ │ │ ├── AlarmsServer.cs │ │ │ ├── AssetServer.cs │ │ │ ├── BaseServerFixture.cs │ │ │ ├── DeterministicAlarmsServer1.cs │ │ │ ├── DeterministicAlarmsServer2.cs │ │ │ ├── FileSystemServer.cs │ │ │ ├── HistoricalAccessServer.cs │ │ │ ├── HistoricalEventsServer.cs │ │ │ ├── Isa95JobsServer.cs │ │ │ ├── PlcServer.cs │ │ │ ├── ReferenceServer.cs │ │ │ ├── SimpleEventsServer.cs │ │ │ └── TestDataServer.cs │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ ├── Runtime/ │ │ │ └── TestClientConfig.cs │ │ └── Tests/ │ │ ├── Alarms/ │ │ │ └── AlarmServerTests.cs │ │ ├── Asset/ │ │ │ ├── AssetTests1.cs │ │ │ ├── AssetTests2.cs │ │ │ ├── AssetTests3.cs │ │ │ └── AssetTests4.cs │ │ ├── DeterministicAlarms/ │ │ │ ├── DeterministicAlarmsTests1.cs │ │ │ ├── DeterministicAlarmsTests2.cs │ │ │ └── Extensions/ │ │ │ └── Extensions.cs │ │ ├── FileSystem/ │ │ │ ├── BrowseTests.cs │ │ │ ├── OperationsTests.cs │ │ │ ├── ReadTests.cs │ │ │ └── WriteTests.cs │ │ ├── HistoricalAccess/ │ │ │ ├── HistoryReadValuesAtTimes.cs │ │ │ ├── HistoryReadValuesModified.cs │ │ │ ├── HistoryReadValuesProcessed.cs │ │ │ ├── HistoryReadValuesTests.cs │ │ │ ├── HistoryUpdateValuesTests.cs │ │ │ └── NodeHistoricalAccessTests.cs │ │ ├── HistoricalEvents/ │ │ │ └── NodeHistoricalEventsTests.cs │ │ ├── Isa95Jobs/ │ │ │ └── Isa95JobsServerTests.cs │ │ ├── Plc/ │ │ │ ├── PlcModelComplexTypeTests.cs │ │ │ └── SimulatorNodesTests.cs │ │ ├── SimpleEvents/ │ │ │ └── SimpleEventsServerTests.cs │ │ └── TestData/ │ │ ├── BrowsePathTests.cs │ │ ├── BrowseServicesTests.cs │ │ ├── BrowseStreamTests.cs │ │ ├── CallArrayMethodTests.cs │ │ ├── CallScalarMethodTests.cs │ │ ├── ConfigurationTests1.cs │ │ ├── ConfigurationTests2.cs │ │ ├── NodeMetadataTests.cs │ │ ├── ReadArrayValueTests.cs │ │ ├── ReadScalarValueTests.cs │ │ ├── WriteArrayValueTests.cs │ │ └── WriteScalarValueTests.cs │ └── Directory.Build.props ├── testenvironments.json ├── tools/ │ ├── checkdocs.cmd │ ├── clean.sh │ ├── codecoverage.cmd │ ├── docgen.cmd │ ├── e2etesting/ │ │ ├── DeployAKS.ps1 │ │ ├── DeployEdge.ps1 │ │ ├── DeployPLCs.ps1 │ │ ├── DeployStandalone.ps1 │ │ ├── DeployTestResources.ps1 │ │ ├── DetermineKeyVaultName.ps1 │ │ ├── GetSecrets.ps1 │ │ ├── SetKeyVaultPermissions.ps1 │ │ ├── SetKeyVaultSecrets.ps1 │ │ ├── SetTestVariables.ps1 │ │ ├── SetVariables.ps1 │ │ └── steps/ │ │ ├── cleanup.yml │ │ ├── deploystandalone.yml │ │ ├── deploytestresources.yml │ │ └── runtests.yml │ └── swagger.cmd └── version.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .editorconfig ================================================ # Remove the line below if you want to inherit .editorconfig settings from higher directories root = true # JSON files, shell scripts [*.{json,sh}] # New line preferences end_of_line = lf insert_final_newline = true # C# files [*.cs] dotnet_diagnostic.IDE0055.severity = none #### Core EditorConfig Options #### # Indentation and spacing indent_size = 4 indent_style = space tab_width = 4 # New line preferences end_of_line = crlf insert_final_newline =true # Organize usings dotnet_separate_import_directive_groups = false dotnet_sort_system_directives_first = false file_header_template = unset # this. and Me. preferences dotnet_style_qualification_for_event = false:suggestion dotnet_style_qualification_for_field = false:suggestion dotnet_style_qualification_for_method = false:suggestion dotnet_style_qualification_for_property = false:suggestion # Language keywords vs BCL types preferences dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion dotnet_style_predefined_type_for_member_access = true:suggestion # Parentheses preferences dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:suggestion dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:suggestion dotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:suggestion # Modifier preferences dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent # Expression-level preferences dotnet_style_coalesce_expression = true:suggestion dotnet_style_collection_initializer = true:suggestion dotnet_style_explicit_tuple_names = true:suggestion dotnet_style_null_propagation = true:suggestion dotnet_style_object_initializer = true:suggestion dotnet_style_operator_placement_when_wrapping = beginning_of_line dotnet_style_prefer_auto_properties = true:suggestion dotnet_style_prefer_compound_assignment = true:suggestion dotnet_style_prefer_conditional_expression_over_assignment = true:silent dotnet_style_prefer_conditional_expression_over_return = true:silent dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion dotnet_style_prefer_inferred_tuple_names = true:suggestion dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion dotnet_style_prefer_simplified_boolean_expressions = true:suggestion dotnet_style_prefer_simplified_interpolation = true:suggestion # Field preferences dotnet_style_readonly_field = true:warning # Parameter preferences dotnet_code_quality_unused_parameters = all:suggestion # Suppression preferences dotnet_remove_unnecessary_suppression_exclusions = none #### C# Coding Conventions #### dotnet_style_operator_placement_when_wrapping = beginning_of_line dotnet_style_coalesce_expression = true:suggestion dotnet_style_null_propagation = true:suggestion dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion dotnet_style_prefer_auto_properties = true:silent dotnet_style_object_initializer = true:suggestion dotnet_style_collection_initializer = true:suggestion dotnet_style_prefer_simplified_boolean_expressions = true:suggestion dotnet_style_prefer_conditional_expression_over_assignment = true:silent dotnet_style_prefer_conditional_expression_over_return = true:silent dotnet_style_explicit_tuple_names = true:suggestion dotnet_style_prefer_inferred_tuple_names = true:suggestion dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion dotnet_style_prefer_compound_assignment = true:suggestion dotnet_style_prefer_simplified_interpolation = true:suggestion dotnet_style_namespace_match_folder = true:suggestion dotnet_style_readonly_field = true:warning dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion dotnet_style_predefined_type_for_member_access = true:suggestion dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent dotnet_style_allow_multiple_blank_lines_experimental = true:silent dotnet_style_allow_statement_immediately_after_block_experimental = true:silent dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:suggestion dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:suggestion dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:suggestion dotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion dotnet_style_qualification_for_field = false:suggestion dotnet_style_qualification_for_property = false:suggestion dotnet_style_qualification_for_method = false:suggestion dotnet_style_qualification_for_event = false:suggestion # var preferences csharp_style_var_elsewhere = true:suggestion csharp_style_var_for_built_in_types = true:suggestion csharp_style_var_when_type_is_apparent = true:suggestion # Expression-bodied members csharp_style_expression_bodied_accessors = when_on_single_line:silent csharp_style_expression_bodied_constructors = false:suggestion csharp_style_expression_bodied_indexers = when_on_single_line:silent csharp_style_expression_bodied_lambdas = when_on_single_line:silent csharp_style_expression_bodied_local_functions = when_on_single_line:silent csharp_style_expression_bodied_methods = false:suggestion csharp_style_expression_bodied_operators = when_on_single_line:silent csharp_style_expression_bodied_properties = when_on_single_line:silent # Pattern matching preferences csharp_style_pattern_matching_over_as_with_null_check = true:suggestion csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion csharp_style_prefer_not_pattern = true:suggestion csharp_style_prefer_pattern_matching = true:none csharp_style_prefer_switch_expression = false:suggestion csharp_style_prefer_method_group_conversion = true:silent csharp_style_prefer_top_level_statements = true:silent csharp_style_prefer_null_check_over_type_check = true:suggestion csharp_style_prefer_local_over_anonymous_function = true:suggestion csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion csharp_style_prefer_tuple_swap = true:suggestion csharp_style_prefer_utf8_string_literals = true:suggestion csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent csharp_style_prefer_extended_property_pattern = true:suggestion # Null-checking preferences csharp_style_conditional_delegate_call = true:suggestion # Modifier preferences csharp_prefer_static_local_function = true:warning csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:silent # Code-block preferences csharp_prefer_braces = true:suggestion csharp_prefer_simple_using_statement = true:silent # Expression-level preferences csharp_prefer_simple_default_expression = true:suggestion csharp_style_deconstructed_variable_declaration = true:suggestion csharp_style_inlined_variable_declaration = true:suggestion csharp_style_pattern_local_over_anonymous_function = true:suggestion csharp_style_prefer_index_operator = true:suggestion csharp_style_prefer_range_operator = true:suggestion csharp_style_throw_expression = true:suggestion csharp_style_unused_value_assignment_preference = discard_variable:silent csharp_style_unused_value_expression_statement_preference = discard_variable:none # 'using' directive preferences csharp_using_directive_placement = inside_namespace:suggestion #### C# Formatting Rules #### # New line preferences csharp_new_line_before_catch = true csharp_new_line_before_else = true csharp_new_line_before_finally = true csharp_new_line_before_members_in_anonymous_types = true csharp_new_line_before_members_in_object_initializers = true csharp_new_line_before_open_brace = all csharp_new_line_between_query_expression_clauses = true # Indentation preferences csharp_indent_block_contents = true csharp_indent_braces = false csharp_indent_case_contents = true csharp_indent_case_contents_when_block = true csharp_indent_labels = one_less_than_current csharp_indent_switch_labels = true # Space preferences csharp_space_after_cast = false csharp_space_after_colon_in_inheritance_clause = true csharp_space_after_comma = true csharp_space_after_dot = false csharp_space_after_keywords_in_control_flow_statements = true csharp_space_after_semicolon_in_for_statement = true csharp_space_around_binary_operators = before_and_after csharp_space_around_declaration_statements = false csharp_space_before_colon_in_inheritance_clause = true csharp_space_before_comma = false csharp_space_before_dot = false csharp_space_before_open_square_brackets = false csharp_space_before_semicolon_in_for_statement = false csharp_space_between_empty_square_brackets = false csharp_space_between_method_call_empty_parameter_list_parentheses = false csharp_space_between_method_call_name_and_opening_parenthesis = false csharp_space_between_method_call_parameter_list_parentheses = false csharp_space_between_method_declaration_empty_parameter_list_parentheses = false csharp_space_between_method_declaration_name_and_open_parenthesis = false csharp_space_between_method_declaration_parameter_list_parentheses = false csharp_space_between_parentheses = false csharp_space_between_square_brackets = false # Wrapping preferences csharp_preserve_single_line_blocks = true csharp_preserve_single_line_statements = true #### Naming styles #### # Naming rules dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion dotnet_naming_rule.types_should_be_pascal_case.symbols = types dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case dotnet_naming_rule.async_method_should_be_ends_in_async.severity = suggestion dotnet_naming_rule.async_method_should_be_ends_in_async.symbols = async_method dotnet_naming_rule.async_method_should_be_ends_in_async.style = ends_in_async dotnet_naming_rule.public_const_field_should_be_pascal_case.severity = suggestion dotnet_naming_rule.public_const_field_should_be_pascal_case.symbols = public_const_field dotnet_naming_rule.public_const_field_should_be_pascal_case.style = pascal_case dotnet_naming_rule.public_static_readonly_field_should_be_pascal_case.severity = suggestion dotnet_naming_rule.public_static_readonly_field_should_be_pascal_case.symbols = public_static_readonly_field dotnet_naming_rule.public_static_readonly_field_should_be_pascal_case.style = pascal_case dotnet_naming_rule.private_or_protected_const_field_should_be_begins_with_k.severity = suggestion dotnet_naming_rule.private_or_protected_const_field_should_be_begins_with_k.symbols = private_or_protected_const_field dotnet_naming_rule.private_or_protected_const_field_should_be_begins_with_k.style = begins_with_k dotnet_naming_rule.private_or_protected_static_readonly_field_should_be_begins_with_k.severity = suggestion dotnet_naming_rule.private_or_protected_static_readonly_field_should_be_begins_with_k.symbols = private_or_protected_static_readonly_field dotnet_naming_rule.private_or_protected_static_readonly_field_should_be_begins_with_k.style = begins_with_k dotnet_naming_rule.public_or_protected_field_should_be_begins_with__.severity = suggestion dotnet_naming_rule.public_or_protected_field_should_be_begins_with__.symbols = public_or_protected_field dotnet_naming_rule.public_or_protected_field_should_be_begins_with__.style = begins_with__ dotnet_naming_rule.private_or_internal_field_should_be_begins_with__.severity = suggestion dotnet_naming_rule.private_or_internal_field_should_be_begins_with__.symbols = private_or_internal_field dotnet_naming_rule.private_or_internal_field_should_be_begins_with__.style = begins_with__ dotnet_naming_rule.private_or_internal_static_field_should_be_begins_with__.severity = suggestion dotnet_naming_rule.private_or_internal_static_field_should_be_begins_with__.symbols = private_or_internal_static_field dotnet_naming_rule.private_or_internal_static_field_should_be_begins_with__.style = begins_with__ # Symbol specifications dotnet_naming_symbols.interface.applicable_kinds = interface dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal dotnet_naming_symbols.interface.required_modifiers = dotnet_naming_symbols.public_or_protected_field.applicable_kinds = field dotnet_naming_symbols.public_or_protected_field.applicable_accessibilities = public, protected dotnet_naming_symbols.public_or_protected_field.required_modifiers = dotnet_naming_symbols.private_or_internal_field.applicable_kinds = field dotnet_naming_symbols.private_or_internal_field.applicable_accessibilities = internal, private dotnet_naming_symbols.private_or_internal_field.required_modifiers = dotnet_naming_symbols.private_or_internal_static_field.applicable_kinds = field dotnet_naming_symbols.private_or_internal_static_field.applicable_accessibilities = internal, private dotnet_naming_symbols.private_or_internal_static_field.required_modifiers = static dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal dotnet_naming_symbols.types.required_modifiers = dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal dotnet_naming_symbols.non_field_members.required_modifiers = dotnet_naming_symbols.async_method.applicable_kinds = method dotnet_naming_symbols.async_method.applicable_accessibilities = * dotnet_naming_symbols.async_method.required_modifiers = async dotnet_naming_symbols.private_or_protected_const_field.applicable_kinds = field dotnet_naming_symbols.private_or_protected_const_field.applicable_accessibilities = private, protected, protected_internal, private_protected, local dotnet_naming_symbols.private_or_protected_const_field.required_modifiers = const dotnet_naming_symbols.private_or_protected_static_readonly_field.applicable_kinds = field dotnet_naming_symbols.private_or_protected_static_readonly_field.applicable_accessibilities = private, protected, protected_internal, private_protected, local dotnet_naming_symbols.private_or_protected_static_readonly_field.required_modifiers = readonly, static dotnet_naming_symbols.public_const_field.applicable_kinds = field dotnet_naming_symbols.public_const_field.applicable_accessibilities = public, internal dotnet_naming_symbols.public_const_field.required_modifiers = const dotnet_naming_symbols.public_static_readonly_field.applicable_kinds = field dotnet_naming_symbols.public_static_readonly_field.applicable_accessibilities = public, internal dotnet_naming_symbols.public_static_readonly_field.required_modifiers = readonly # Naming styles dotnet_naming_style.pascal_case.required_prefix = dotnet_naming_style.pascal_case.required_suffix = dotnet_naming_style.pascal_case.word_separator = dotnet_naming_style.pascal_case.capitalization = pascal_case dotnet_naming_style.begins_with_i.required_prefix = I dotnet_naming_style.begins_with_i.required_suffix = dotnet_naming_style.begins_with_i.word_separator = dotnet_naming_style.begins_with_i.capitalization = pascal_case dotnet_naming_style.begins_with__.required_prefix = _ dotnet_naming_style.begins_with__.required_suffix = dotnet_naming_style.begins_with__.word_separator = dotnet_naming_style.begins_with__.capitalization = camel_case dotnet_naming_style.ends_in_async.required_prefix = dotnet_naming_style.ends_in_async.required_suffix = Async dotnet_naming_style.ends_in_async.word_separator = dotnet_naming_style.ends_in_async.capitalization = pascal_case dotnet_naming_style.begins_with_k.required_prefix = k dotnet_naming_style.begins_with_k.required_suffix = dotnet_naming_style.begins_with_k.word_separator = dotnet_naming_style.begins_with_k.capitalization = pascal_case csharp_style_namespace_declarations= block_scoped:warning # IDE0046: Convert to conditional expression dotnet_diagnostic.IDE0046.severity = silent # IDE0045: Convert to conditional expression dotnet_diagnostic.IDE0045.severity = silent # IDE0130: Namespace does not match folder structure dotnet_diagnostic.IDE0130.severity = none # IDE0010: Add missing cases dotnet_diagnostic.IDE0010.severity = silent # IDE0072: Add missing cases dotnet_diagnostic.IDE0072.severity = silent # RCS1138: Add summary to documentation comment. dotnet_diagnostic.RCS1138.severity = suggestion # RCS1163: Unused parameter dotnet_diagnostic.RCS1163.severity = silent # RCS1180: Inline lazy initialization dotnet_diagnostic.RCS1180.severity = silent # RCS1194: Implement exception constructors. dotnet_diagnostic.RCS1194.severity = silent # RCS1073: Convert 'if' to 'return' statement. dotnet_diagnostic.RCS1073.severity = silent # RCS1112: Combine 'Enumerable.Where' method chain. dotnet_diagnostic.RCS1112.severity = silent # RCS1237: Use bit shift operator. dotnet_diagnostic.RCS1237.severity = silent # RCS1135: Declare enum member with zero value (when enum has FlagsAttribute). dotnet_diagnostic.RCS1135.severity = silent # RCS1079: Throwing of new NotImplementedException. dotnet_diagnostic.RCS1079.severity = silent # RCS1238: Avoid nested ?: operators. dotnet_diagnostic.RCS1238.severity = silent # CA1062: Variant value validation dotnet_code_quality.CA1062.null_check_validation_methods = IsNull|CheckNull # Default severity for analyzer diagnostics with category 'Naming' dotnet_analyzer_diagnostic.category-Naming.severity = suggestion # Default severity for analyzer diagnostics with category 'Performance' dotnet_analyzer_diagnostic.category-Performance.severity = suggestion # CA1303: Do not pass literals as localized parameters dotnet_diagnostic.CA1303.severity = none # CA1031: Do not catch general exception types dotnet_diagnostic.CA1031.severity = none # CA1062: Validate arguments of public methods dotnet_diagnostic.CA1062.severity = silent # CA1711: Identifiers should not have incorrect suffix dotnet_diagnostic.CA1711.severity = silent # CA2225: Operator overloads have named alternates dotnet_diagnostic.CA2225.severity = silent # CA1848: Use the LoggerMessage delegates dotnet_diagnostic.CA1848.severity = silent # CA1819: Properties should not return arrays dotnet_diagnostic.CA1819.severity = silent # CA1055: URI-like return values should not be strings dotnet_diagnostic.CA1055.severity = silent # CA1056: URI-like properties should not be strings dotnet_diagnostic.CA1056.severity = silent # CA1054: URI-like parameters should not be strings dotnet_diagnostic.CA1054.severity = silent dotnet_diagnostic.CA1309.severity=suggestion # CA1810: Initialize reference type static fields inline dotnet_diagnostic.CA1810.severity = none dotnet_diagnostic.CA1032.severity= silent dotnet_diagnostic.CA1304.severity=suggestion dotnet_diagnostic.CA1305.severity=suggestion dotnet_diagnostic.CA1307.severity=suggestion dotnet_diagnostic.CA1310.severity=warning dotnet_diagnostic.CA1727.severity=warning dotnet_diagnostic.CA2201.severity=warning dotnet_diagnostic.CA2215.severity=warning dotnet_diagnostic.CA5351.severity=warning dotnet_diagnostic.CA5350.severity=warning dotnet_diagnostic.CA5360.severity=error dotnet_diagnostic.CA5359.severity=warning dotnet_diagnostic.CA5363.severity=warning dotnet_diagnostic.CA5364.severity=warning dotnet_diagnostic.CA5365.severity=warning dotnet_diagnostic.CA5366.severity=warning dotnet_diagnostic.CA5373.severity=warning dotnet_diagnostic.CA5379.severity=warning dotnet_diagnostic.CA5385.severity=warning dotnet_diagnostic.CA5384.severity=warning dotnet_diagnostic.CA5397.severity=warning dotnet_diagnostic.CA5394.severity=suggestion # IDE0066: Convert switch statement to expression dotnet_diagnostic.IDE0066.severity = suggestion dotnet_diagnostic.CA1200.severity = suggestion dotnet_diagnostic.CA1848.severity = suggestion dotnet_diagnostic.CA2011.severity = warning dotnet_diagnostic.CA2009.severity = warning dotnet_diagnostic.CA1001.severity = warning dotnet_diagnostic.CA1311.severity = suggestion # Default severity for analyzer diagnostics with category 'Style' dotnet_analyzer_diagnostic.category-Style.severity = silent dotnet_code_quality_unused_parameters = all:suggestion dotnet_diagnostic.RCS1090.severity = warning dotnet_diagnostic.RCS1035.severity = suggestion dotnet_diagnostic.RCS1034.severity = suggestion dotnet_diagnostic.RCS1040.severity = suggestion dotnet_diagnostic.RCS1042.severity = suggestion dotnet_diagnostic.RCS1043.severity = suggestion dotnet_diagnostic.RCS1061.severity = suggestion dotnet_diagnostic.RCS1066.severity = suggestion dotnet_diagnostic.RCS1069.severity = suggestion dotnet_diagnostic.RCS1071.severity = suggestion dotnet_diagnostic.RCS1091.severity = suggestion dotnet_diagnostic.RCS1124.severity = suggestion dotnet_diagnostic.RCS1129.severity = suggestion dotnet_diagnostic.RCS1136.severity = suggestion dotnet_diagnostic.RCS1141.severity = suggestion dotnet_diagnostic.RCS1140.severity = suggestion dotnet_diagnostic.RCS1142.severity = suggestion dotnet_diagnostic.RCS1145.severity = suggestion dotnet_diagnostic.RCS1143.severity = suggestion dotnet_diagnostic.RCS1151.severity = suggestion dotnet_diagnostic.RCS1165.severity = suggestion dotnet_diagnostic.RCS1188.severity = suggestion dotnet_diagnostic.RCS1181.severity = suggestion dotnet_diagnostic.RCS1182.severity = suggestion dotnet_diagnostic.RCS1201.severity = suggestion dotnet_diagnostic.RCS1211.severity = suggestion dotnet_diagnostic.RCS1228.severity = none dotnet_diagnostic.RCS1229.severity = warning dotnet_diagnostic.RCS1244.severity = suggestion # xUnit1033: Test classes decorated with 'Xunit.IClassFixture' or 'Xunit.ICollectionFixture' should add a constructor argument of type TFixture dotnet_diagnostic.xUnit1033.severity = silent # xUnit1044: The type argument is not serializable, which will cause Test Explorer to not enumerate individual data rows. Consider using a type that is known to be serializable. dotnet_diagnostic.xUnit1044.severity = silent # CA1716: Identifiers should not match keywords dotnet_diagnostic.CA1716.severity = none csharp_style_prefer_primary_constructors = false:suggestion # CA1861: Avoid constant arrays as arguments dotnet_diagnostic.CA1861.severity = silent # CA1724: Type names should not match namespaces dotnet_diagnostic.CA1724.severity = silent # CA1812: Avoid uninstantiated internal classes dotnet_diagnostic.CA1812.severity = silent # CA1003: Use generic event handler instances dotnet_diagnostic.CA1003.severity = silent # CA1008: Enums should have zero value dotnet_diagnostic.CA1008.severity = silent csharp_style_prefer_readonly_struct = true:suggestion csharp_style_prefer_readonly_struct_member = true:suggestion csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent dotnet_diagnostic.RCS1055.severity = suggestion dotnet_diagnostic.RCS1039.severity = suggestion csharp_prefer_static_anonymous_function = true:suggestion csharp_prefer_system_threading_lock = true:suggestion # IDE0058: Expression value is never used dotnet_diagnostic.IDE0058.severity = none # IDE0078: Use pattern matching dotnet_diagnostic.IDE0078.severity = none [*.{cs,vb}] dotnet_style_coalesce_expression = true:silent dotnet_style_null_propagation = true:suggestion dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion dotnet_style_prefer_auto_properties = true:silent dotnet_style_operator_placement_when_wrapping = beginning_of_line tab_width = 4 indent_size = 4 end_of_line = crlf dotnet_style_object_initializer = true:suggestion dotnet_style_namespace_match_folder = false:silent dotnet_diagnostic.CA2007.severity = warning dotnet_diagnostic.CA1848.severity = silent dotnet_diagnostic.CA1036.severity = suggestion dotnet_diagnostic.CA1051.severity = silent dotnet_diagnostic.CA1711.severity = silent dotnet_diagnostic.CA1819.severity = suggestion dotnet_diagnostic.CA3061.severity = suggestion dotnet_diagnostic.CA3075.severity = suggestion dotnet_diagnostic.CA3076.severity = suggestion dotnet_diagnostic.CA3077.severity = suggestion dotnet_diagnostic.CA3147.severity = suggestion dotnet_diagnostic.CA5369.severity = suggestion dotnet_diagnostic.CA5371.severity = suggestion dotnet_diagnostic.CA5370.severity = suggestion dotnet_diagnostic.CA5372.severity = suggestion dotnet_diagnostic.CA5374.severity = warning dotnet_diagnostic.CA2251.severity = suggestion dotnet_style_prefer_collection_expression = when_types_exactly_match:suggestion dotnet_style_collection_initializer = true:suggestion dotnet_style_prefer_simplified_boolean_expressions = true:suggestion dotnet_style_prefer_conditional_expression_over_assignment = true:silent # IDE0270: Use coalesce expression dotnet_diagnostic.IDE0270.severity = silent # IDE0130: Namespace does not correspond to file location dotnet_diagnostic.IDE0130.severity = silent dotnet_diagnostic.CA1031.severity = silent dotnet_style_prefer_conditional_expression_over_return = true:silent dotnet_style_explicit_tuple_names = true:suggestion dotnet_style_prefer_inferred_tuple_names = true:suggestion dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion dotnet_style_prefer_compound_assignment = true:suggestion dotnet_style_prefer_simplified_interpolation = true:suggestion dotnet_style_namespace_match_folder = false:suggestion dotnet_style_readonly_field = true:warning dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion dotnet_style_predefined_type_for_member_access = true:suggestion dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent dotnet_style_allow_multiple_blank_lines_experimental = true:silent dotnet_style_allow_statement_immediately_after_block_experimental = true:silent dotnet_code_quality_unused_parameters = all:suggestion dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:suggestion dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:suggestion dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:suggestion dotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion dotnet_style_qualification_for_field = false:suggestion dotnet_style_qualification_for_property = false:suggestion dotnet_style_qualification_for_method = false:suggestion dotnet_style_qualification_for_event = false:suggestion ================================================ FILE: .gdnbaselines ================================================ { "hydrated": false, "properties": { "helpUri": "https://eng.ms/docs/microsoft-security/security/azure-security/cloudai-security-fundamentals-engineering/security-integration/guardian-wiki/microsoft-guardian/general/baselines" }, "version": "1.0.0", "baselines": { "default": { "name": "default", "createdDate": "2025-08-08 15:38:41Z", "lastUpdatedDate": "2025-08-08 15:38:41Z" } }, "results": { "6509bdf379f034da9286d6a99b43a48c28d25e6ed7a27498cdd040ca8d2716e3": { "signature": "6509bdf379f034da9286d6a99b43a48c28d25e6ed7a27498cdd040ca8d2716e3", "alternativeSignatures": [ "f6b70eed777a2be53d74c33c31bb729cfa646ab63add95fc1c0fa9af2498a78c" ], "memberOf": [ "default" ], "createdDate": "2025-08-08 15:38:41Z" }, "58ae6a48f45ca345b98cdda729972ce4308cf93c8efb96deb348e3e91598cc0d": { "signature": "58ae6a48f45ca345b98cdda729972ce4308cf93c8efb96deb348e3e91598cc0d", "alternativeSignatures": [ "647af3f9494531075db1bd4924b6bccf8508acc3de6c32eb8d41b905f0b0d1e0" ], "memberOf": [ "default" ], "createdDate": "2025-08-08 15:38:41Z" } } } ================================================ FILE: .gitattributes ================================================ # Default behavior: if Git thinks a file is text (as opposed to binary), it # will normalize line endings to LF in the repository, but convert to your # platform's native line endings on checkout (e.g., CRLF for Windows). * text=auto # Explicitly declare text files you want to always be normalized and converted # to native line endings on checkout. E.g., #*.c text # Declare files that will always have LF line endings on checkout. E.g., *.sh text eol=lf *.json text eol=lf *.rb text eol=lf *.go text eol=lf *.java text eol=lf *.ts text eol=lf *.js text eol=lf *.py text eol=lf # Denote all files that should not have line endings normalized, should not be # merged, and should not show in a textual diff. *.docm binary *.docx binary *.ico binary *.lib binary *.png binary *.pptx binary *.snk binary *.vsdx binary *.xps binary *.dll binary *.exe binary ================================================ FILE: .github/CODEOWNERS ================================================ * @Azure/azure-industrial-iot ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.md ================================================ --- name: Bug report about: Create a report to help us improve title: '' labels: '' assignees: '' --- **Describe the bug** A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error **Expected behavior** A clear and concise description of what you expected to happen. **Screenshots** If applicable, add screenshots to help explain your problem. **Desktop (please complete the following information):** - OS: [e.g. iOS] - Browser [e.g. chrome, safari] - Version [e.g. 22] **Smartphone (please complete the following information):** - Device: [e.g. iPhone6] - OS: [e.g. iOS8.1] - Browser [e.g. stock browser, safari] - Version [e.g. 22] **Additional context** Add any other context about the problem here. ================================================ FILE: .github/ISSUE_TEMPLATE/feature_request.md ================================================ --- name: Feature request about: Suggest an idea for this project title: '' labels: '' assignees: '' --- **Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] **Describe the solution you'd like** A clear and concise description of what you want to happen. **Describe alternatives you've considered** A clear and concise description of any alternative solutions or features you've considered. **Additional context** Add any other context or screenshots about the feature request here. ================================================ FILE: .github/dependabot.yml ================================================ # To get started with Dependabot version updates, you'll need to specify which # package ecosystems to update and where the package manifests are located. # Please see the documentation for all configuration options: # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates version: 2 updates: - package-ecosystem: "nuget" directory: "/" # Location of package manifests schedule: interval: "daily" open-pull-requests-limit: 25 # Raise pull requests in worker branch nuget target-branch: "main" ================================================ FILE: .github/workflows/codeql.yml ================================================ name: "CodeQL" on: push: branches: [ "latest", "main", "release/*" ] pull_request: branches: [ "latest", "main", "release/*" ] schedule: - cron: '37 9 * * 5' jobs: analyze: name: Analyze (${{ matrix.language }}) runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} permissions: security-events: write packages: read actions: read contents: read strategy: fail-fast: false matrix: include: - language: csharp build-mode: autobuild steps: - name: Setup .NET uses: actions/setup-dotnet@v3 with: dotnet-version: 9.0.x - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 0 - name: Cleanup Nuget.Config run: | find . -name "Nuget.Config" -type f -delete - name: Initialize CodeQL uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} # queries: security-extended,security-and-quality - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 with: category: "/language:${{matrix.language}}" ================================================ FILE: .github/workflows/dotnet.yml ================================================ name: Build Solutions on: push: branches: [ "latest", "main" ] pull_request: branches: [ "latest", "main" ] jobs: build: runs-on: ubuntu-latest strategy: matrix: solution: - '**/*.slnx' steps: - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup .NET uses: actions/setup-dotnet@v3 with: dotnet-version: 9.0.x - name: Restore dependencies run: dotnet restore ${{ matrix.solution }} -s https://api.nuget.org/v3/index.json - name: Build run: dotnet build ${{ matrix.solution }} --configuration Release --no-restore ================================================ FILE: .github/workflows/test.yml ================================================ name: Build and Test on: push: branches: [ "latest", "main" ] pull_request: branches: [ "latest", "main" ] jobs: build: runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, windows-latest] steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: 9.0.x - name: Restore dependencies run: dotnet restore -s https://api.nuget.org/v3/index.json - name: Build run: dotnet build --no-restore - name: Test run: dotnet test --no-build --verbosity normal ================================================ FILE: .gitignore ================================================ /**/*.user /**/*.cache /**/*.user.json /**/*.nupkg /**/obj/** /**/.vs /**/bin/** /**/pki/** /**/csx/** /**/ecf/** /**/*.log /**/*.err /**/*.sdf /**/*.rsa /**/*.opendb /**/*.opensdf /**/*.vc.db /.vscode/** /build/** *.sarif *.dll *.so *.pdb *.der *.pfx *.exe /src/out /src/Logs /_tmpout/** /TestResults/** /**/TestResults/** /**/packages/** /**/appsettings.*.json .env *.crt *.key *.user *.cache CodeCoverage coverage.cobertura.xml /api/csharp-api/api/*.yml /api/csharp-api/api/*.manifest /api/csharp-api/_site node_modules .sonarqube/** ================================================ FILE: .mcp.json ================================================ { "inputs": [ { "id": "github_pat", "description": "GitHub personal access token", "type": "promptString", "password": true } ], "servers": { "microsoft.docs.mcp": { "type": "http", "url": "https://learn.microsoft.com/api/mcp" }, "github": { "type": "stdio", "command": "docker", "args": [ "run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", "ghcr.io/github/github-mcp-server" ], "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "${input:github_pat}" } } } } ================================================ FILE: .sscignore ================================================ { "cfs": ["CFS0001", "CFS0013"] } ================================================ FILE: CODEOWNERS ================================================ # Always ensure to include industrial-iot-pr for every item that follows. * @Azure/industrial-iot-pr # Only exception is doc updates /docs/ @Azure/azure-industrial-iot ================================================ FILE: Industrial-IoT.slnx ================================================ ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) Microsoft Corporation. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE ================================================ FILE: NOTICE ================================================ NOTICES AND INFORMATION Do Not Translate or Localize This software incorporates material from third parties. Microsoft makes certain open source code available at https://3rdpartysource.microsoft.com, or you may send a check or money order for US $5.00, including the product name, the open source component name, platform, and version number, to: Source Code Compliance Team Microsoft Corporation One Microsoft Way Redmond, WA 98052 USA Notwithstanding any other terms, you may reverse engineer this software to the extent required to debug changes to any libraries licensed under the GNU Lesser General Public License. --------------------------------------------------------- As an OPC Foundation Corporate Member, Microsoft distributes any code dual licensed under the RCL or GPLv2 license, under the RCL license. --------------------------------------------------------- OPCFoundation.NetStandard.Opc.Ua.Core 1.4.368.58 - OTHER https://opcfoundation.org/license/redistributables/1.3/ Copyright, OPC Foundation OPC REDISTRIBUTABLES Agreement of Use Version 1.3, February 06, 2017, OPC Foundation The terms and conditions of the Agreement apply to the Software Deliverables including without limitation any OPC Foundation: updates, supplements Internet-based services, and support services for the Software Deliverables, unless OPC Foundation specifies that any other terms accompany such items, in which case the alternate terms specified by OPC Foundation would apply. BY USING THE SOURCE DELIVERABLES, YOU ACCEPT THE TERMS OF THIS AGREEMENT. IF YOU DO NOT ACCEPT THE TERMS OF THIS AGREEMENT, DO NOT USE THE SOFTWARE DELIVERABLES. If you comply with this Agreement, you have the rights below. 1. INSTALLATION AND USE RIGHTS. You may install and use any number of copies of the Software Deliverables. 2. ADDITIONAL LICENSING REQUIREMENTS AND/OR USE RIGHTS. Distributable Code. The Software Deliverables contain compiled code that you are permitted to distribute with programs you develop if you comply with the terms below. Right to Use and Distribute. You may copy and distribute all files that are part of this Software Deliverables. Third Party Distribution. You may permit distributors of your programs to copy and distribute the Software Deliverables as part of those programs. Distribution Requirements. For any Software Deliverables you distribute, you must: add significant primary functionality to it in your programs; require distributors and external end users to agree to terms that protect it at least as much as this Agreement; display your valid copyright notice on your programs; and indemnify, defend, and hold harmless the OPC Foundation from any claims, including attorneys’ fees, related to the distribution or use of your programs. Distribution Restrictions. You may not: alter any copyright, trademark or patent notice in the Software Deliverables; use the OPC Foundation’s trademarks in your programs’ names or in a way that suggests your programs come from or are endorsed by the OPC Foundation; include Software Deliverables in malicious, deceptive or unlawful programs; modify or distribute the source code of any Software Deliverables so that any part of it becomes subject to an Excluded License. An Excluded License is one that requires, as a condition of use, modification or distribution, that (1). the code be disclosed or distributed in source code form; or (2) permit or otherwise allow others to have the right to modify such Software Deliverables; or create additional software components that directly link or directly load the Software Deliverables without accepting the corresponding source license for that Software Deliverable. 3. SCOPE OF LICENSE. The Software Deliverables are licensed, not sold. This Agreement only gives you some rights to use the Software Deliverables. The OPC Foundation reserves all other rights. Unless applicable law gives you more rights despite this limitation, you may use the software only as expressly permitted in this Agreement. In doing so, you must comply with any technical limitations in the Software Deliverables that only allow you to use it in certain ways. You may not: disclose the results of any benchmark tests of the Software Deliverables to any third party without OPC Foundation’s prior written approval; work around any technical limitations in the Software Deliverables; reverse engineer, decompile or disassemble the Software Deliverables, except and only to the extent that applicable law expressly permits, despite this limitation; make more copies of the Software Deliverables than specified in this Agreement or allowed by applicable law, despite this limitation; publish the Software Deliverables for others to copy; or rent, lease or lend the Software Deliverables. 4. BACKUP COPY. You may make one backup copy of the Software Deliverables. You may use such copy only to reinstall the Software. 5. DOCUMENTATION. Any person that has valid access to your computer or internal network may copy and use the documentation related to the Software Deliverables for your internal reference purposes. 6. EXPORT RESTRICTIONS. The Software Deliverables are subject to United States export laws and regulations. You must comply with all domestic and international export laws and regulations that apply to the Software Deliverables. These laws include restrictions on destinations, end users and end use. 7. SUPPORT SERVICES. Because you accept the Software3 Deliverables from OPC Foundation “as is,” OPC Foundation may not provide support services for it. 8. ENTIRE AGREEMENT. This Agreement, and the terms for supplements, updates, Internet-based services and support services that you use, are the entire Agreement for the Software Deliverables and support services. 10. LEGAL EFFECT This Agreement describes certain legal rights. You may have other rights under the laws of your country. This Agreement does not change your rights under the laws of your country if the laws of your country do not permit it to do so. 11. DISCLAIMER OF WARRANTY. THE SOFTWARE DELIVERABLES ARE LICENSED “AS-IS.” YOU BEAR THE RISK OF USING THE SPECIFICATIONS. THE OPC FOUNDATION MAKES NO WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, WITH REGARD TO THE SOFTWARE DELIVERABLES, INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF TITLE OR OWNERSHIP, IMPLIED WARRANTY OF MERCHANTABILITY, OR WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE OR USE.YOU MAY HAVE ADDITIONAL CONSUMER RIGHTS UNDER YOUR LOCAL LAWS THAT THIS AGREEMENT CANNOT CHANGE. TO THE EXTENT PERMITTED UNDER YOUR LOCAL LAWS, THE OPC FOUNDATION EXCLUDES THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE OPC FOUNDATION BE LIABLE FOR ERRORS CONTAINED IN THE SOURCE DELIVERABLES OR FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, RELIANCE OR COVER DAMAGES, INCLUDING LOSS OF PROFITS, REVENUE, DATA, OR USE, INCURRED BY ANY USER OR ANY THIRD PARTY IN CONNECTION WITH THE FURNISHING, PERFORMANCE, OR USE OF THE SOFTWARE DELIVERABLES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE USING THE SOFTWARE DELIVERABLES IS BORNE BY YOU AND/OR THE USER. --------------------------------------------------------- https://opcfoundation.org/license/source/1.11/index.html License information for OPC Source Deliverables A. Introduction The OPC Foundation provides source code as sample code/reference implementation. The source code is provided as-is, with no warranty, support, or misrepresentation of the quality of code. The OPC Foundation provides communication stacks, sample libraries, sample applications and utilities. All sources are available either as a downloadable ZIP file or in a repository on github (https://github.com/OPCFoundation/ ). B. License models The OPC Foundation provides different licenses depending on the component and on the membership status of the user of the sources. A single ZIP file or a single repository can contain multiple components where the sources have different license models. The valid license is in the header of each source file. Following are basic rules on how the OPC Foundation licenses the different components: 1. OPC UA core components (OPC UA Stacks, OPC UA Local Discovery Server - LDS) follow a dual-license model: * *OPC Foundation Corporate Members*: RCL enables OPC Foundation corporate members to deploy their applications using the core component sources without being required to disclose the application code. * *Users that are not OPC Foundation corporate-members*: GPL 2.0 Based on the GPL 2.0 license terms these users must disclose their application code when using the core component sources. 2. Samples and Utilities: All samples and most of the utilities are provided under the MIT license for OPC Foundation Members and Non-Members. --------------------------------------------------------- https://opcfoundation.org/license/rcl.html RCL License Reciprocal Community License 1.00 (RCL1.00) Version 1.00, June 24, 2009 Copyright (C) 2008,2009 OPC Foundation, Inc., All Rights Reserved. PREAMBLE The Reciprocal Community License (RCL) is based on the concept of reciprocity or, if you prefer, fairness. The RCL is adapted from the Open Source Reciprocal Public License (RPL) where the “Public” in the Open Source RPL license is replaced by the “Community” in the RCL License. In short, the RPL license grew out of a desire to close loopholes in previous open source licenses, loopholes that allowed parties to acquire open source software and derive financial benefit from it without having to release their improvements or derivatives to the community which enabled them. This occurred any time an entity did not release their application to a "third party". While there is a certain freedom in this model of licensing, it struck the authors of the RPL as being unfair to the open source community at large and to the original authors of the works in particular. After all, bug fixes, extensions, and meaningful and valuable derivatives were not consistently faster, growth and expansion of the overall open source software base. While you should clearly read and understand the entire license, the essence of the RCL is found in two definitions: "Deploy" and "Required Components". Regarding deployment, under the RCL your changes, bug fixes, extensions, etc. must be made available to the community when you Deploy in any form -- either internally or to an outside party. Once you start running the software you have to start sharing the software. Further, under the RCL all derivative work components you author including schemas, scripts, source code, documentation, etc. -- must be shared. You have to share the whole pie, not an isolated slice of it. The authored components you must share are confined to the original module licensed (e.g. SDK, stack, wrapper, proxy, utility, etc.). You do not need to share any additional authored components that you create that utilize the licensed component. This license is meant to be friendly to commercial software vendors that must protect the IP in their code. You are not expected to share your proprietary source code that makes use of the module(s) licensed under this agreement. The specific terms and conditions of the license are defined in the remainder of this document. 1 LICENSE TERMS 1.1 General; Applicability & Definitions. This Reciprocal Community License Version 1.00 ("License") applies to any programs or other works as well as any and all updates or maintenance releases of said programs or works ("Software") not already covered by this License which the Software copyright holder ("Licensor") makes available containing a License Notice (hereinafter defined) from the Licensor specifying or allowing use or distribution under the terms of this License. As used in this License: 1.2 "Contributor" means any person or entity who created or contributed to the creation of an Extension. 1.3 "Deploy" means to use, Serve, sublicense or distribute Licensed Software other than for Your internal Research and/or Personal Use, and includes without limitation, any and all internal use or distribution of Licensed Software within Your business or organization other than for Research and/or Personal Use, as well as direct or indirect sublicensing or distribution of Licensed Software by You to any third party. 1.4 "Derivative Works" as used in this License is defined under U.S. copyright law. 1.5 "Extensions" means any Modifications, Derivative Works, or Required Components as those terms are defined in this License. 1.6 "License" means this Reciprocal Community License. 1.7 "License Notice" means any notice contained in EXHIBIT A. 1.8 "Licensed Software" means any Software licensed pursuant to this License. Licensed Software also includes all previous Extensions from any Contributor that You receive. 1.9 "Licensor" means the copyright holder of any Software previously not covered by this License who releases the Software under the terms of this License. 1.10 "Modifications" means any additions to or deletions from the substance or structure of (i) a file containing Licensed Software, or (ii) any new file that contains any part of Licensed Software. 1.11 "Original Licensor" means the Licensor that is the copyright holder of the original work. For this license the Original Licensor is always the OPC Foundation. 1.12 "Personal Use" means use of Licensed Software by an individual solely for his or her personal, private and non-commercial purposes. An individual's use of Licensed Software in his or her capacity as an officer, employee, member, independent contractor or agent of a corporation, business or organization (commercial or non-commercial) does not qualify as Personal Use. 1.13 "Required Components" means any text, programs, scripts, schema, interface definitions, control files, or other works created by You which are required by a third party of average skill to successfully install and run Licensed Software containing Your Modifications, or to install and run Your Derivative Works. Required Components by this definition are the supporting works that are necessary to utilize your Modifications and Derivative Works. This does not include your applications and supporting works that utilize the Licensed Software. 1.14 "Research" means investigation or experimentation for the purpose of understanding the nature and limits of the Licensed Software and its potential uses. 1.15 "Serve" means to deliver Licensed Software and/or Your Extensions by means of a computer network to one or more computers for purposes of execution of Licensed Software and/or Your Extensions. 1.16 "Software" means any computer programs or other works as well as any updates or maintenance releases of those programs or works which are distributed publicly by Licensor. 1.17 "Source Code" means the preferred form for making modifications to the Licensed Software and/or Your Extensions, including all modules contained therein, plus any associated text, interface definition files, scripts used to control compilation and installation of an executable program or other components required by a third party of average skill to build a running version of the Licensed Software or Your Extensions. 1.18 "User-Visible Attribution Notice" means any notice contained in EXHIBIT B. 1.19 "You" or "Your" means an individual or a legal entity exercising rights under this License. For legal entities, "You" or "Your" includes any entity which controls, is controlled by, or is under common control with, You, where "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of fifty percent (50%) or more of the outstanding shares or beneficial ownership of such entity. 2.0 Acceptance Of License. You are not required to accept this License since you have not signed it, however nothing else grants you permission to use, copy, distribute, modify, or create derivatives of either the Software or any Extensions created by a Contributor. These actions are prohibited by law if you do not accept this License. Therefore, by performing any of these actions You indicate Your acceptance of this License and Your agreement to be bound by all its terms and conditions. IF YOU DO NOT AGREE WITH ALL THE TERMS AND CONDITIONS OF THIS LICENSE DO NOT USE, MODIFY, CREATE DERIVATIVES, OR DISTRIBUTE THE SOFTWARE. IF IT IS IMPOSSIBLE FOR YOU TO COMPLY WITH ALL THE TERMS AND CONDITIONS OF THIS LICENSE THEN YOU CAN NOT USE, MODIFY, CREATE DERIVATIVES, OR DISTRIBUTE THE SOFTWARE. 3.0 Grant of License From Licensor. Subject to the terms and conditions of this License, Licensor hereby grants You a world-wide, royalty-free, non- exclusive license, subject to Licensor's intellectual property rights, and any third party intellectual property claims derived from the Licensed Software under this License, to do the following: 3.1 Use, reproduce, modify, display, and perform Licensed Software and Your Extensions in both Source Code form or as an executable program. You may also sublicense and distribute Licensed Software and Your Extensions as an executable program. OPC Foundation Corporate Members may also sublicense and distribute Licensed Software and Your Extensions in Source Code form. 3.2 Create Derivative Works (as that term is defined under U.S. copyright law) of Licensed Software. 3.3 Under claims of patents now or hereafter owned or controlled by Licensor, to make, use, have made, and/or otherwise dispose of Licensed Software or portions thereof, but solely to the extent that any such claim is necessary to enable You to make, use, have made, and/or otherwise dispose of Licensed Software or portions thereof. 3.4 Licensor reserves the right to release new versions of the Software with different features, specifications, capabilities, functions, licensing terms, general availability or other characteristics. Title, ownership rights, and intellectual property rights in and to the Licensed Software shall remain in Licensor and/or its Contributors. 4.0 Grant of License From Contributor. By application of the provisions in Section 6 below, each Contributor hereby grants You a world-wide, royalty- free, non-exclusive license, subject to said Contributor's intellectual property rights, and any third party intellectual property claims derived from the Licensed Software under this License, to do the following: 4.1 Use, reproduce, modify, display and perform any Extensions Deployed by such Contributor or portions thereof, in both Source Code form or as an executable program, either on an unmodified basis or as part of Derivative Works. You may also sublicense and distribute Extensions Deployed by such Contributor or portions thereof, as an executable program. OPC Foundation Corporate Members may also sublicense and distribute Extensions Deployed by such Contributor or portions thereof,in Source Code form. 4.2 Under claims of patents now or hereafter owned or controlled by Contributor, to make, use, have made, and/or otherwise dispose of Extensions or portions thereof, but solely to the extent that any such claim is necessary to enable You to make, use, have made, and/or otherwise dispose of Licensed Software or portions thereof. 5.0 Exclusions From License Grant. Nothing in this License shall be deemed to grant any rights to trademarks, copyrights, patents, trade secrets or any other intellectual property of Licensor or any Contributor except as expressly stated herein. Except as expressly stated in Sections 3 and 4, no other patent rights, express or implied, are granted herein. Your Extensions may require additional patent licenses from Licensor or Contributors which each may grant in its sole discretion. No right is granted to the trademarks of Licensor or any Contributor even if such marks are included in the Licensed Software. Nothing in this License shall be interpreted to prohibit Licensor from licensing under different terms from this License any code that Licensor otherwise would have a right to license. 5.1 You expressly acknowledge and agree that although Licensor and each Contributor grants the licenses to their respective portions of the Licensed Software set forth herein, no assurances are provided by Licensor or any Contributor that the Licensed Software does not infringe the patent or other intellectual property rights of any other entity. Licensor and each Contributor disclaim any liability to You for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, You hereby assume sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow You to distribute the Licensed Software, it is Your responsibility to acquire that license before distributing the Licensed Software. 6.0 Your Obligations And Grants. In consideration of, and as an express condition to, the licenses granted to You under this License You hereby agree that any Modifications, Derivative Works, or Required Components (collectively Extensions) that You create or to which You contribute are governed by the terms of this License including, without limitation, Section 4. Any Extensions that You create or to which You contribute must be Deployed under the terms of this License or a future version of this License released under Section 7. You hereby grant to Licensor and all third parties a world-wide, non-exclusive, royalty-free license under those intellectual property rights You own or control to use, reproduce, display, perform, modify, create derivatives, sublicense, and distribute Licensed Software, in any form. Any Extensions You make and Deploy must have a distinct title so as to readily tell any subsequent user or Contributor that the Extensions are by You. You must include a copy of this License or directions on how to obtain a copy with every copy of the Extensions You distribute. You agree not to offer or impose any terms on any Source Code or executable version of the Licensed Software, or its Extensions that alter or restrict the applicable version of this License or the recipients' rights hereunder. Additionally, you herby grant to the Original Licensor the right to use, reproduce, display, perform, modify, create derivatives, sublicense, and distribute Licensed Software, in any form, under the terms of this license and/or any other license terms it sees fit. 6.1 Availability of Source Code. You must make available, under the terms of this License, the Source Code of any Extensions that You Deploy, by uploading the Source Code directly to the website of the Original Licensor. The Source Code for any version that You Deploy must be made available within one (1) month of when you Deploy. You may not charge a fee for any copy of the Source Code distributed under this Section. At the sole discretion of the Original Licensor, some or all of Your contributed Source Code may be included in a future baseline version released by the Original Licensor. 6.2 Description of Modifications. You must cause any Modifications that You create or to which You contribute to be documented in the Source Code, clearly describing the additions, changes or deletions You made. You must include a prominent statement that the Modifications are derived, directly or indirectly, from the Licensed Software and include the names of the Licensor and any Contributor to the Licensed Software in (i) the Source Code and (ii) in any notice displayed by the Licensed Software You distribute or in related documentation in which You describe the origin or ownership of the Licensed Software. You may not modify or delete any pre-existing copyright notices, change notices or License text in the Licensed Software without written permission of the respective Licensor or Contributor. 6.3 Intellectual Property Matters. a. Third Party Claims. If You have knowledge that a license to a third party's intellectual property right is required to exercise the rights granted by this License, You must include a human-readable file with Your distribution that describes the claim and the party making the claim in sufficient detail that a recipient will know whom to contact. b. Contributor APIs. If Your Extensions include an application programming interface ("API") and You have knowledge of patent licenses that are reasonably necessary to implement that API, You must also include this information in a human-readable file supplied with Your distribution. c. Representations. You represent that, except as disclosed pursuant to 6.3(a) above, You believe that any Extensions You distribute are Your original creations and that You have sufficient rights to grant the rights conveyed by this License. 6.4 Required Notices. a. License Text. You must duplicate this License or instructions on how to acquire a copy in any documentation You provide along with the Source Code of any Extensions You create or to which You contribute, wherever You describe recipients' rights relating to Licensed Software. b. License Notice. You must duplicate any notice contained in EXHIBIT A (the "License Notice") in each file of the Source Code of any copy You distribute of the Licensed Software and Your Extensions. If You create an Extension, You may add Your name as a Contributor to the Source Code and accompanying documentation along with a description of the contribution. If it is not possible to put the License Notice in a particular Source Code file due to its structure, then You must include such License Notice in a location where a user would be likely to look for such a notice. c. User-Visible Attribution. You must duplicate any notice contained in EXHIBIT B (the "User-Visible Attribution Notice") in each user-visible display of the Licensed Software and Your Extensions which delineates copyright, ownership, or similar attribution information. If You create an Extension, You may add Your name as a Contributor, and add Your attribution notice, as an equally visible and functional element of any User-Visible Attribution Notice content. To ensure proper attribution, You must also include such User-Visible Attribution Notice in at least one location in the Software documentation where a user would be likely to look for such notice. 6.5 Additional Terms. You may choose to offer, and charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Licensed Software. However, You may do so only on Your own behalf, and not on behalf of the Licensor or any Contributor except as permitted under other agreements between you and Licensor or Contributor. You must make it clear that any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Licensor and every Contributor for any liability plus attorney fees, costs, and related expenses due to any such action or claim incurred by the Licensor or such Contributor as a result of warranty, support, indemnity or liability terms You offer. 6.6 Conflicts With Other Licenses. Where any portion of Your Extensions, by virtue of being Derivative Works of another product or similar circumstance, fall under the terms of another license, the terms of that license should be honored however You must also make Your Extensions available under this License. If the terms of this License continue to conflict with the terms of the other license you may write the Licensor for permission to resolve the conflict in a fashion that remains consistent with the intent of this License. Such permission will be granted at the sole discretion of the Licensor. 7.0 Versions of This License. Licensor may publish from time to time revised versions of the License. Once Licensed Software has been published under a particular version of the License, You may always continue to use it under the terms of that version. You may also choose to use such Licensed Software under the terms of any subsequent version of the License published by Licensor. No one other than Licensor has the right to modify the terms applicable to Licensed Software created under this License. 7.1 If You create or use a modified version of this License, which You may do only in order to apply it to software that is not already Licensed Software under this License, You must rename Your license so that it is not confusingly similar to this License, and must make it clear that Your license contains terms that differ from this License. In so naming Your license, You may not use any trademark of Licensor or of any Contributor. Should Your modifications to this License be limited to alteration of a) Section 13.8 solely to modify the legal Jurisdiction or Venue for disputes, b) EXHIBIT A solely to define License Notice text, or c) to EXHIBIT B solely to define a User-Visible Attribution Notice, You may continue to refer to Your License as the Reciprocal Community License or simply the RCL. 8.0 Disclaimer of Warranty. LICENSED SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE LICENSED SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. FURTHER THERE IS NO WARRANTY MADE AND ALL IMPLIED WARRANTIES ARE DISCLAIMED THAT THE LICENSED SOFTWARE MEETS OR COMPLIES WITH ANY DESCRIPTION OF PERFORMANCE OR OPERATION, SAID COMPATIBILITY AND SUITABILITY BEING YOUR RESPONSIBILITY. LICENSOR DISCLAIMS ANY WARRANTY, IMPLIED OREXPRESSED,THAT ANY CONTRIBUTOR'S EXTENSIONS MEET ANY STANDARD OF COMPATIBILITY OR DESCRIPTION OF PERFORMANCE. THE ENTIRE RISK AS TO THE QUALITY ANDPERFORMANCE OF THE LICENSED SOFTWARE IS WITH YOU. SHOULD LICENSED SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, YOU (AND NOT THE LICENSOR OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. UNDER THE TERMS OF THIS LICENSOR WILL NOT SUPPORT THIS SOFTWARE AND IS UNDER NO OBLIGATION TO ISSUE UPDATES TO THIS SOFTWARE. LICENSOR HAS NO KNOWLEDGE OF ERRANT CODE OR VIRUS IN THIS SOFTWARE, BUT DOES NOT WARRANT THAT THE SOFTWARE IS FREE FROM SUCH ERRORS OR VIRUSES. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF LICENSED SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. 9.0 Limitation of Liability. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL THE LICENSOR, ANY CONTRIBUTOR, OR ANY DISTRIBUTOR OF LICENSED SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY INDIRECT,SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTERFAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENTAPPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THISEXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. 10.0 Restricted Rights Legend. This Specification is provided with Restricted Rights. Use, duplication or disclosure by the U.S. government is subject to restrictions as set forth in (a) this Agreement pursuant to DFARs 227.7202-3(a); (b) subparagraph (c)(1)(i) of the Rights in Technical Data and Computer Software clause at DFARs 252.227-7013; or (c) the Commercial Computer Software Restricted Rights clause at FAR 52.227-19 subdivision (c)(1) and (2), as applicable. Contractor / manufacturer are the OPC Foundation,. 16101 N. 82nd Street, Suite 3B, Scottsdale, AZ, 85260-1830 11.0 Responsibility for Claims. As between Licensor and Contributors, each party is responsible for claims and damages arising, directly or indirectly, out of its utilization of rights under this License which specifically disclaims warranties and limits any liability of the Licensor. This paragraph is to be used in conjunction with and controlled by the Disclaimer Of Warranties of Section 8, the Limitation Of Damages in Section 9, and the disclaimer against use for High Risk Activities in Section 10. The Licensor has thereby disclaimed all warranties and limited any damages that it is or may be liable for. You agree to work with Licensor and Contributors to distribute such responsibility on an equitable basis consistent with the terms of this License including Sections 8, 9, and 10. Nothing herein is intended or shall be deemed to constitute any admission of liability. 12.0 Termination. This License and all rights granted hereunder will terminate immediately in the event of the circumstances described in Section 136 or if applicable law prohibits or restricts You from fully and or specifically complying with Sections 3, 4 and/or 6, or prevents the enforceability of any of those Sections, and You must immediately discontinue any use of Licensed Software. 12.1 Automatic Termination Upon Breach. This License and the rights granted hereunder will terminate automatically if You fail to comply with the terms herein and fail to cure such breach within thirty (30) days of becoming aware of the breach. All sublicenses to the Licensed Software that are properly granted shall survive any termination of this License. Provisions that, by their nature, must remain in effect beyond the termination of this License, shall survive. 12.2 Termination Upon Assertion of Patent Infringement. If You initiate litigation by asserting a patent infringement claim (excluding declaratory judgment actions) against Licensor or a Contributor (Licensor or Contributor against whom You file such an action is referred to herein as "Respondent") alleging that Licensed Software directly or indirectly infringes any patent, then any and all rights granted by such Respondent to You under Sections 3 or 4 of this License shall terminate prospectively upon sixty (60) days notice from Respondent (the "Notice Period") unless within that Notice Period You either agree in writing (i) to pay Respondent a mutually agreeable reasonably royalty for Your past or future use of Licensed Software made by such Respondent, or (ii) withdraw Your litigation claim with respect to Licensed Software against such Respondent. If within said Notice Period a reasonable royalty and payment arrangement are not mutually agreed upon in writing by the parties or the litigation claim is not withdrawn, the rights granted by Licensor to You under Sections 3 and 4 automatically terminate at the expiration of said Notice Period. 12.3 Reasonable Value of This License. If You assert a patent infringement claim against Respondent alleging that Licensed Software directly or indirectly infringes any patent where such claim is resolved (such as by license or settlement) prior to the initiation of patent infringement litigation, then the reasonable value of the licenses granted by said Respondent under Sections 3 and 4 shall be taken into account in determining the amount or value of any payment or license. 12.4 No Retroactive Effect of Termination. In the event of termination under this Section all end user license agreements (excluding licenses to distributors and resellers) that have been validly granted by You or any distributor hereunder prior to termination shall survive termination. 13.0 Miscellaneous. 13.1 U.S. Government End Users. The Licensed Software is a "commercial item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer software" and "commercial computer software documentation," as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Licensed Software with only those rights set forth herein. 13.2 Relationship of Parties. This License will not be construed as creating an agency, partnership, joint venture, or any other form of legal association between or among You, Licensor, or any Contributor, and You will not represent to the contrary, whether expressly, by implication, appearance, or otherwise. 13.3 Independent Development. Nothing in this License will impair Licensor's right to acquire, license, develop, subcontract, market, or distribute technology or products that perform the same or similar functions as, or otherwise compete with, Extensions that You may develop, produce, market, or distribute. 13.4 Consent To Breach Not Waiver. Failure by Licensor or Contributor to enforce any provision of this License will not be deemed a waiver of future enforcement of that or any other provision. 13.5 Severability. This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. 13.6 Inability to Comply Due to Statute or Regulation. If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Licensed Software due to statute, judicial order, or regulation, then You cannot use, modify, or distribute the software. 13.7 Export Restrictions. You may be restricted with respect to downloading or otherwise acquiring, exporting, or reexporting the Licensed Software or any underlying information or technology by United States and other applicable laws and regulations. By downloading or by otherwise obtaining the Licensed Software, You are agreeing to be responsible for compliance with all applicable laws and regulations. 13.8 Arbitration, Jurisdiction & Venue. This License shall be governed by Minnesota law provisions (except to the extent applicable law, if any, provides otherwise), excluding its conflict-of-law provisions. You expressly agree that any dispute relating to this License shall be submitted to binding arbitration under the rules then prevailing of the American Arbitration Association. You further agree that Minnesota USA is proper venue and grant such arbitration proceeding jurisdiction as may be appropriate for purposes of resolving any dispute under this License. Judgment upon any award made in arbitration may be entered and enforced in any court of competent jurisdiction. The arbitrator shall award attorney's fees and costs of arbitration to the prevailing party. Should either party find it necessary to enforce its arbitration award or seek specific performance of such award in a civil court of competent jurisdiction, the prevailing party shall be entitled to reasonable attorney's fees and costs. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. You and Licensor expressly waive any rights to a jury trial in any litigation concerning Licensed Software or this License. Any law or regulation that provides that the language of a contract shall be construed against the drafter shall not apply to this License. 13.9 Entire Agreement. This License constitutes the entire agreement between the parties with respect to the subject matter hereof. EXHIBIT A The License Notice below must appear in each file of the Source Code of any copy You distribute of the Licensed Software or any Extensions thereto: Unless explicitly acquired and licensed from Licensor under another license, the contents of this file are subject to the Reciprocal Community License ("RCL") Version 0.9, or subsequent versions as allowed by the RCL, and You may not copy or use this file in either source code or executable form, except in compliance with the terms and conditions of the RCL. All software distributed under the RCL is provided strictly on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, AND LICENSOR HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT, OR NON-INFRINGEMENT. See the RCL for specific language governing rights and limitations under the RCL. EXHIBIT B The User-Visible Attribution Notice below, when provided, must appear in each user-visible display as defined in Section 6.4 (c): “Portions copyright © by OPC Foundation, Inc. and licensed under the Reciprocal Community License (RCL) --------------------------------------------------------- https://opcfoundation.org/license/gpl.html GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS --------------------------------------------------------- https://opcfoundation.org/license/mit.html MIT License OPC Foundation MIT License 1.00 Copyright (c) 2008-2022 OPC Foundation, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- OPCFoundation.NetStandard.Opc.Ua.Client 1.4.368.58 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- OPCFoundation.NetStandard.Opc.Ua.Client.ComplexTypes 1.4.368.58 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- OPCFoundation.NetStandard.Opc.Ua.Configuration 1.4.368.58 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- OPCFoundation.NetStandard.Opc.Ua.Security.Certificates 1.4.368.58 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- OPCFoundation.NetStandard.Opc.Ua.Server 1.4.368.58 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- BuildBundlerMinifier 3.2.449 - Apache-2.0 Copyright 2017 Copyright James Newton-King 2008 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Castle.Core 5.1.0 - Apache-2.0 (c) 2004-2022 Castle Project - http://www.castleproject.org Copyright 2004-2021 Castle Project - http://www.castleproject.org Copyright (c) 2004-2022 Castle Project - http://www.castleproject.org Copyright 2004-2021 Castle Project - http://www.castleproject.org/ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- FluentAssertions 6.7.0 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- FluentValidation 11.2.2 - Apache-2.0 (c) Jeremy Skinner, .NET Foundation, and contributors 2008-2022 Copyright (c) Jeremy Skinner, .NET Foundation, and contributors 2008-2022 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- FluentValidation.DependencyInjectionExtensions 11.2.2 - Apache-2.0 (c) Jeremy Skinner, .NET Foundation, and contributors 2008-2022 Copyright (c) Jeremy Skinner, .NET Foundation, and contributors 2008-2022 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- IdentityModel 6.0.0 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- IdentityModel.OidcClient 3.1.2 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Authentication.Abstractions 2.2.0 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Authorization 2.2.0 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Authorization.Policy 2.2.0 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Cryptography.Internal 3.1.24 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.DataProtection 3.1.24 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.DataProtection.Abstractions 3.1.24 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.DataProtection.AzureKeyVault 3.1.24 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.DataProtection.AzureStorage 3.1.24 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Hosting 2.1.1 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Hosting.Abstractions 2.1.1 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Hosting.Abstractions 2.2.0 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Hosting.Server.Abstractions 2.1.1 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Hosting.Server.Abstractions 2.2.0 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Http 2.1.22 - Apache-2.0 (c) Microsoft Corporation. Copyright (c) .NET Foundation and Contributors Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Http 2.2.0 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Http.Abstractions 2.1.1 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Http.Abstractions 2.2.0 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Http.Connections 1.1.0 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Http.Connections.Client 5.0.1 - Apache-2.0 (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright (c) 2019 David Fowler Copyright (c) 2016 Richard Morris Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation. Copyright (c) 2014-2018 Michael Daines Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) .NET Foundation and Contributors Copyright (c) 2010-2019 Google LLC. http://angular.io/license Copyright (c) Sindre Sorhus (https://sindresorhus.com) Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Http.Connections.Common 5.0.1 - Apache-2.0 (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright (c) 2019 David Fowler Copyright (c) 2016 Richard Morris Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation. Copyright (c) 2014-2018 Michael Daines Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) .NET Foundation and Contributors Copyright (c) 2010-2019 Google LLC. http://angular.io/license Copyright (c) Sindre Sorhus (https://sindresorhus.com) Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Http.Extensions 2.1.1 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Http.Extensions 2.2.0 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Http.Features 2.1.1 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Http.Features 2.2.0 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Routing 2.2.0 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Routing.Abstractions 2.2.0 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.SignalR 1.1.0 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.SignalR.Core 1.1.0 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.SignalR.Protocols.Json 1.1.0 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.WebSockets 2.2.1 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.WebUtilities 2.1.1 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.WebUtilities 2.2.0 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Configuration.Binder 2.0.0 - Apache-2.0 Copyright Microsoft Corporation Copyright (c) Microsoft Corporation Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Configuration.EnvironmentVariables 2.1.1 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Configuration.FileExtensions 3.1.0 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Configuration.Json 3.1.0 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.FileProviders.Physical 3.1.0 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.FileSystemGlobbing 3.1.0 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Hosting.Abstractions 3.1.8 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.ObjectPool 2.1.1 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.ObjectPool 2.2.0 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Options.ConfigurationExtensions 2.0.0 - Apache-2.0 Copyright Microsoft Corporation Copyright (c) Microsoft Corporation Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Net.Http.Headers 2.1.1 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Net.Http.Headers 2.2.0 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- NuGet.Frameworks 5.11.0 - Apache-2.0 (c) Microsoft Corporation. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Roslynator.Analyzers 3.1.0 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Serilog 2.10.0 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Serilog 2.12.0 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Serilog.AspNetCore 6.0.1 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Serilog.Extensions.Hosting 5.0.1 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Serilog.Extensions.Logging 3.1.0 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Serilog.Formatting.Compact 1.1.0 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Serilog.Settings.Configuration 3.3.0 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Serilog.Sinks.ApplicationInsights 4.0.0 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Serilog.Sinks.Console 4.0.1 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Serilog.Sinks.Console 4.1.0 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Serilog.Sinks.Debug 2.0.0 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Serilog.Sinks.File 5.0.0 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Serilog.Sinks.Trace 3.0.0 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- WindowsAzure.Storage 9.3.2 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- WindowsAzure.Storage 9.3.3 - Apache-2.0 (c) Microsoft Corporation. Copyright 2018 Microsoft Corp. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- xunit 2.4.2 - Apache-2.0 Copyright (c) .NET Foundation Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- xunit.abstractions 2.0.3 - Apache-2.0 Copyright (c) Outercurve Foundation Copyright (c) Outercurve Foundation WrapNonExceptionThrows RSDS Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- xunit.analyzers 1.0.0 - Apache-2.0 Copyright (c) .NET Foundation Copyright (c) .NET Foundation xUnit.net Copyright (c) .NET Foundation xunit.analyzers, analyzers, roslyn, xunit, xunit.net Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- xunit.assert 2.4.2 - Apache-2.0 Copyright (c) .NET Foundation Copyright (c) .NET Foundation xUnit.net Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- xunit.core 2.4.2 - Apache-2.0 Copyright (c) .NET Foundation Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- xunit.extensibility.core 2.4.2 - Apache-2.0 Copyright (c) .NET Foundation Copyright (c) .NET Foundation xUnit.net Copyright (c) .NET Foundation 0xUnit.net Copyright (c) .NET Foundation xUnit.net Runner Utility Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- xunit.extensibility.execution 2.4.2 - Apache-2.0 Copyright (c) .NET Foundation Copyright (c) .NET Foundation xUnit.net Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Microsoft.CommonDataModel.ObjectModel 1.0.15 - Apache-2.0 AND MS-PL AND MS-RL (c) Microsoft Corporation. Apache-2.0 AND MS-PL AND MS-RL --------------------------------------------------------- --------------------------------------------------------- Antlr4 4.6.6 - BSD-3-Clause Copyright (c) . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------- --------------------------------------------------------- Antlr4.CodeGenerator 4.6.6 - BSD-3-Clause Copyright Sam Harwell 2011 Copyright Sam Harwell 2015 Copyright Sam Harwell 2016 Copyright (c) Sam Harwell 2015 Copyright (c) Terence Parr, Sam Harwell. Copyright (c) . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------- --------------------------------------------------------- Antlr4.Runtime 4.6.6 - BSD-3-Clause Copyright (c) . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------- --------------------------------------------------------- Moq 4.18.2 - BSD-3-Clause Copyright (c) 2007, Clarius Consulting, Manas Technology Solutions, InSTEDD, and Contributors Copyright (c) . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------- --------------------------------------------------------- NLog 4.6.7 - BSD-3-Clause Copyright (c) 2004-2019 NLog Project ACopyright (c) 2004-2019 NLog Project Copyright (c) . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Data.Edm 5.8.4 - mit (c) Microsoft Corporation. mit --------------------------------------------------------- --------------------------------------------------------- Microsoft.Data.OData 5.8.4 - mit (c) Microsoft Corporation. mit --------------------------------------------------------- --------------------------------------------------------- Accelist.FluentValidation.Blazor 4.0.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Autofac 5.2.0 - MIT Copyright 2015 Autofac MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Autofac.Extensions.DependencyInjection 6.0.0 - MIT Copyright 2015 Autofac MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Autofac.Extras.Moq 5.0.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- AutoFixture 4.17.0 - MIT Copyright Ploeh 2011 Copyright (c) Ploeh 2011 MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- AutoFixture.AutoMoq 4.17.0 - MIT Copyright Ploeh 2011 Copyright (c) Ploeh 2011 MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Azure.Core 1.21.0 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Azure.Core 1.22.0 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Azure.Core 1.25.0 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Azure.Identity 1.4.0 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Azure.Storage.Blobs 12.14.0 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Azure.Storage.Common 12.13.0 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Azure.Storage.Files.DataLake 12.12.1 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Blazored.Modal 4.1.0 - MIT Copyright 2018 (c) Chris Sainty. 5Copyright 2018 (c) Chris Sainty. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Blazored.SessionStorage 2.2.0 - MIT (c) Chris Sainty. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- coverlet.collector 3.1.2 - MIT Copyright 2008 - 2018 Jb Evain Copyright Microsoft Corporation Copyright James Newton-King 2008 MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- coverlet.msbuild 3.1.2 - MIT Copyright 2008 - 2018 Jb Evain Copyright Microsoft Corporation Copyright James Newton-King 2008 MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Fare 2.1.1 - MIT Copyright Nikos Baxevanis 2016 Copyright (c) Nikos Baxevanis 2016 Regex Test NFA DFA Automaton MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- JetBrains.Annotations 2021.2.0 - MIT Copyright (c) 2016 JetBrains http://www.jetbrains.com MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Json.More.Net 1.7.0 - MIT MIT License Copyright (c) 2022 Greg Dennis Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- JsonPointer.Net 2.2.1 - MIT MIT License Copyright (c) 2020 Greg Dennis Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- JsonSchema.Net 3.2.1 - MIT MIT License Copyright (c) 2022 Greg Dennis Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- MessagePack 2.4.35 - MIT (c) Yoshifumi Kawai and contributors Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2017 Yoshifumi Kawai and contributors MessagePack for C# MIT License Copyright (c) 2017 Yoshifumi Kawai and contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --- lz4net Copyright (c) 2013-2017, Milosz Krajewski All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------- --------------------------------------------------------- MessagePack.Annotations 2.4.35 - MIT (c) Yoshifumi Kawai and contributors Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2017 Yoshifumi Kawai and contributors MessagePack for C# MIT License Copyright (c) 2017 Yoshifumi Kawai and contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --- lz4net Copyright (c) 2013-2017, Milosz Krajewski All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.ApplicationInsights 2.21.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.ApplicationInsights.AspNetCore 2.21.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.ApplicationInsights.DependencyCollector 2.21.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.ApplicationInsights.EventCounterCollector 2.21.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.ApplicationInsights.PerfCounterCollector 2.21.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.ApplicationInsights.WindowsServer 2.21.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel 2.21.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Authentication.AzureAD.UI 6.0.10 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright (c) 2019 David Fowler Copyright (c) 2016 Richard Morris Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2014-2018 Michael Daines Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) .NET Foundation and Contributors Copyright (c) 2019-2020 West Wind Technologies Copyright (c) 2010-2019 Google LLC. http://angular.io/license Copyright (c) Sindre Sorhus (https://sindresorhus.com) MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Authentication.JwtBearer 6.0.10 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright (c) 2019 David Fowler Copyright (c) 2016 Richard Morris Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2014-2018 Michael Daines Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) .NET Foundation and Contributors Copyright (c) 2019-2020 West Wind Technologies Copyright (c) 2010-2019 Google LLC. http://angular.io/license Copyright (c) Sindre Sorhus (https://sindresorhus.com) MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Authentication.OpenIdConnect 6.0.10 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright (c) 2019 David Fowler Copyright (c) 2016 Richard Morris Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2014-2018 Michael Daines Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) .NET Foundation and Contributors Copyright (c) 2019-2020 West Wind Technologies Copyright (c) 2010-2019 Google LLC. http://angular.io/license Copyright (c) Sindre Sorhus (https://sindresorhus.com) MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Authorization 6.0.10 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright (c) 2019 David Fowler Copyright (c) 2016 Richard Morris Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2014-2018 Michael Daines Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) .NET Foundation and Contributors Copyright (c) 2019-2020 West Wind Technologies Copyright (c) 2010-2019 Google LLC. http://angular.io/license Copyright (c) Sindre Sorhus (https://sindresorhus.com) MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Components 6.0.10 - MIT (c) Microsoft Corporation Copyright (c) 2014 Waybury Copyright (c) 1998 John D. Polstra Copyright (c) 2013 - 2018 AngleSharp Copyright (c) 2000-2013 Julian Seward Copyright (c) 2011-2018 Twitter, Inc. Copyright (c) 1996-1998 John D. Polstra Copyright (c) .NET Foundation Contributors Copyright (c) 2011, The Outercurve Foundation Copyright (c) 2011-2018 The Bootstrap Authors Copyright (c) 2007 John Birrell (jb@freebsd.org) Copyright (c) 1989, 1993 The Regents of the University of California Copyright (c) 1990, 1993 The Regents of the University of California MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Components.Analyzers 6.0.10 - MIT (c) Microsoft Corporation Copyright (c) 2014 Waybury Copyright (c) 1998 John D. Polstra Copyright (c) 2013 - 2018 AngleSharp Copyright (c) 2000-2013 Julian Seward Copyright (c) 2011-2018 Twitter, Inc. Copyright (c) 1996-1998 John D. Polstra Copyright (c) .NET Foundation Contributors Copyright (c) 2011, The Outercurve Foundation Copyright (c) 2011-2018 The Bootstrap Authors Copyright (c) 2007 John Birrell (jb@freebsd.org) Copyright (c) 1989, 1993 The Regents of the University of California Copyright (c) 1990, 1993 The Regents of the University of California MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Components.Forms 6.0.10 - MIT (c) Microsoft Corporation Copyright (c) 2014 Waybury Copyright (c) 1998 John D. Polstra Copyright (c) 2013 - 2018 AngleSharp Copyright (c) 2000-2013 Julian Seward Copyright (c) 2011-2018 Twitter, Inc. Copyright (c) 1996-1998 John D. Polstra Copyright (c) .NET Foundation Contributors Copyright (c) 2011, The Outercurve Foundation Copyright (c) 2011-2018 The Bootstrap Authors Copyright (c) 2007 John Birrell (jb@freebsd.org) Copyright (c) 1989, 1993 The Regents of the University of California Copyright (c) 1990, 1993 The Regents of the University of California MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Components.Web 6.0.10 - MIT (c) Microsoft Corporation Copyright (c) 2014 Waybury Copyright (c) 1998 John D. Polstra Copyright (c) 2013 - 2018 AngleSharp Copyright (c) 2000-2013 Julian Seward Copyright (c) 2011-2018 Twitter, Inc. Copyright (c) 1996-1998 John D. Polstra Copyright (c) .NET Foundation Contributors Copyright (c) 2011, The Outercurve Foundation Copyright (c) 2011-2018 The Bootstrap Authors Copyright (c) 2007 John Birrell (jb@freebsd.org) Copyright (c) 1989, 1993 The Regents of the University of California Copyright (c) 1990, 1993 The Regents of the University of California MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Connections.Abstractions 6.0.10 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright (c) 2019 David Fowler Copyright (c) 2016 Richard Morris Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2014-2018 Michael Daines Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) .NET Foundation and Contributors Copyright (c) 2019-2020 West Wind Technologies Copyright (c) 2010-2019 Google LLC. http://angular.io/license Copyright (c) Sindre Sorhus (https://sindresorhus.com) MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Http.Connections.Client 6.0.10 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright (c) 2019 David Fowler Copyright (c) 2016 Richard Morris Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2014-2018 Michael Daines Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) .NET Foundation and Contributors Copyright (c) 2019-2020 West Wind Technologies Copyright (c) 2010-2019 Google LLC. http://angular.io/license Copyright (c) Sindre Sorhus (https://sindresorhus.com) MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Http.Connections.Common 6.0.10 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright (c) 2019 David Fowler Copyright (c) 2016 Richard Morris Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2014-2018 Michael Daines Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) .NET Foundation and Contributors Copyright (c) 2019-2020 West Wind Technologies Copyright (c) 2010-2019 Google LLC. http://angular.io/license Copyright (c) Sindre Sorhus (https://sindresorhus.com) MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.JsonPatch 6.0.0-rc.1.21452.15 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.JsonPatch 6.0.10 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright (c) 2019 David Fowler Copyright (c) 2016 Richard Morris Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2014-2018 Michael Daines Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) .NET Foundation and Contributors Copyright (c) 2019-2020 West Wind Technologies Copyright (c) 2010-2019 Google LLC. http://angular.io/license Copyright (c) Sindre Sorhus (https://sindresorhus.com) MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Metadata 6.0.10 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright (c) 2019 David Fowler Copyright (c) 2016 Richard Morris Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2014-2018 Michael Daines Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) .NET Foundation and Contributors Copyright (c) 2019-2020 West Wind Technologies Copyright (c) 2010-2019 Google LLC. http://angular.io/license Copyright (c) Sindre Sorhus (https://sindresorhus.com) MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Mvc.NewtonsoftJson 6.0.0-rc.1.21452.15 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright (c) 2019 David Fowler Copyright (c) 2016 Richard Morris Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2007 James Newton-King Copyright (c) Microsoft Corporation. Copyright (c) 2014-2018 Michael Daines Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) .NET Foundation and Contributors Copyright (c) 2010-2019 Google LLC. http://angular.io/license Copyright (c) Sindre Sorhus (https://sindresorhus.com) MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Mvc.NewtonsoftJson 6.0.10 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright (c) 2019 David Fowler Copyright (c) 2016 Richard Morris Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2014-2018 Michael Daines Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) .NET Foundation and Contributors Copyright (c) 2019-2020 West Wind Technologies Copyright (c) 2010-2019 Google LLC. http://angular.io/license Copyright (c) Sindre Sorhus (https://sindresorhus.com) MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Mvc.Testing 6.0.10 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright (c) 2019 David Fowler Copyright (c) 2016 Richard Morris Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2014-2018 Michael Daines Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) .NET Foundation and Contributors Copyright (c) 2019-2020 West Wind Technologies Copyright (c) 2010-2019 Google LLC. http://angular.io/license Copyright (c) Sindre Sorhus (https://sindresorhus.com) MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Mvc.Versioning 5.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Microsoft Corporation. MIT License Copyright (c) Microsoft Corporation. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.SignalR.Client 6.0.10 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.SignalR.Client.Core 6.0.10 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.SignalR.Common 6.0.10 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.SignalR.Protocols.Json 6.0.10 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.SignalR.Protocols.MessagePack 6.0.10 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright (c) 2019 David Fowler Copyright (c) 2016 Richard Morris Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2014-2018 Michael Daines Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) .NET Foundation and Contributors Copyright (c) 2019-2020 West Wind Technologies Copyright (c) 2010-2019 Google LLC. http://angular.io/license Copyright (c) Sindre Sorhus (https://sindresorhus.com) MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson 6.0.10 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.TestHost 6.0.10 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright (c) 2019 David Fowler Copyright (c) 2016 Richard Morris Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2014-2018 Michael Daines Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) .NET Foundation and Contributors Copyright (c) 2019-2020 West Wind Technologies Copyright (c) 2010-2019 Google LLC. http://angular.io/license Copyright (c) Sindre Sorhus (https://sindresorhus.com) MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Core.NewtonsoftJson 1.0.0 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.EventHubs 4.3.2 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.EventHubs.Processor 4.3.2 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.KeyVault 3.0.5 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.KeyVault.Core 2.0.4 - MIT Copyright (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.KeyVault.Core 3.0.3 - MIT (c) Microsoft Corporation. Copyright (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.KeyVault.WebKey 3.0.5 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.ApplicationInsights 0.3.0-preview - MIT (c) Microsoft Corporation. Copyright (c) 2019 Microsoft Copyright (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.AppService.Fluent 1.38.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.Authorization 2.12.0-preview - MIT (c) Microsoft Corporation. Copyright (c) 2019 Microsoft Copyright (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.BatchAI.Fluent 1.38.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.Cdn.Fluent 1.38.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.Compute.Fluent 1.38.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.ContainerInstance.Fluent 1.38.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.ContainerRegistry.Fluent 1.38.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.ContainerService.Fluent 1.38.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.CosmosDB.Fluent 1.38.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.Dns.Fluent 1.38.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.EventHub.Fluent 1.38.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.Fluent 1.38.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.Graph.RBAC.Fluent 1.38.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.IotHub 4.2.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.KeyVault.Fluent 1.38.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.Locks.Fluent 1.38.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.Monitor.Fluent 1.38.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.Msi.Fluent 1.38.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.Network.Fluent 1.38.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.OperationalInsights 0.23.0-preview - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.PrivateDns.Fluent 1.38.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.Redis.Fluent 1.38.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.ResourceManager.Fluent 1.38.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.Search.Fluent 1.38.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.ServiceBus.Fluent 1.38.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.SignalR 1.1.0 - MIT (c) Microsoft Corporation. Copyright (c) 2019 Microsoft Copyright (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.Sql.Fluent 1.38.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.Storage.Fluent 1.38.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Management.TrafficManager.Fluent 1.38.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.ServiceBus 5.2.0 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Services.AppAuthentication 1.0.3 - MIT (c) Microsoft Corporation. Copyright (c) Microsoft Corporation. 9Copyright (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Services.AppAuthentication 1.6.2 - MIT (c) Microsoft Corporation. Copyright (c) 2019 Microsoft Copyright (c) Microsoft Corporation. 9Copyright (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.SignalR 1.18.3 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.SignalR.Management 1.18.3 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.SignalR.Protocols 1.18.3 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Storage.Blob 10.0.1 - MIT (c) Microsoft Corporation. Copyright 2019 Microsoft Corp. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Storage.Blob 11.1.7 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Storage.Common 10.0.1 - MIT (c) Microsoft Corporation. Copyright 2019 Microsoft Corp. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Storage.Common 11.1.7 - MIT (c) Microsoft Corporation. Copyright 2019 Microsoft Corp. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Bcl.AsyncInterfaces 1.0.0 - MIT (c) Microsoft Corporation. Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2007 James Newton-King Copyright (c) 1991-2017 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Bcl.AsyncInterfaces 1.1.1 - MIT The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Build.Tasks.Git 1.1.1 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.ApiDescription.Server 6.0.5 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Caching.Abstractions 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Configuration 6.0.1 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2020 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Configuration.Abstractions 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Configuration.Binder 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Configuration.CommandLine 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Configuration.EnvironmentVariables 6.0.1 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2020 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Configuration.FileExtensions 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Configuration.Ini 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Configuration.Json 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Configuration.UserSecrets 6.0.1 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2020 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.DependencyInjection 5.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.DependencyInjection 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.DependencyInjection 6.0.1 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2020 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.DependencyInjection.Abstractions 5.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.DependencyInjection.Abstractions 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.DependencyModel 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Diagnostics.HealthChecks 6.0.10 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright (c) 2019 David Fowler Copyright (c) 2016 Richard Morris Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2014-2018 Michael Daines Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) .NET Foundation and Contributors Copyright (c) 2019-2020 West Wind Technologies Copyright (c) 2010-2019 Google LLC. http://angular.io/license Copyright (c) Sindre Sorhus (https://sindresorhus.com) MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions 6.0.10 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright (c) 2019 David Fowler Copyright (c) 2016 Richard Morris Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2014-2018 Michael Daines Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) .NET Foundation and Contributors Copyright (c) 2019-2020 West Wind Technologies Copyright (c) 2010-2019 Google LLC. http://angular.io/license Copyright (c) Sindre Sorhus (https://sindresorhus.com) MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Features 6.0.10 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright (c) 2019 David Fowler Copyright (c) 2016 Richard Morris Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2014-2018 Michael Daines Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) .NET Foundation and Contributors Copyright (c) 2019-2020 West Wind Technologies Copyright (c) 2010-2019 Google LLC. http://angular.io/license Copyright (c) Sindre Sorhus (https://sindresorhus.com) MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.FileProviders.Abstractions 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.FileProviders.Physical 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.FileSystemGlobbing 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Hosting 6.0.1 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2020 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Hosting.Abstractions 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Http 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Logging 5.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Logging 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Logging.Abstractions 5.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Logging.Abstractions 6.0.2 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2020 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Logging.ApplicationInsights 2.21.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Logging.Configuration 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Logging.Console 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Logging.Debug 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Logging.EventLog 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Logging.EventSource 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Options 5.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Options 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Options.ConfigurationExtensions 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Primitives 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Graph.Auth 1.0.0-preview.7 - MIT (c) Microsoft Corporation. Copyright (c) 2018 Microsoft Graph MIT License Copyright (c) 2018 Microsoft Graph Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Identity.Client 4.30.1 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Identity.Client 4.47.2 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Identity.Client.Extensions.Msal 2.18.4 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.Abstractions 6.22.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.Abstractions 6.24.0 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.Clients.ActiveDirectory 3.14.2 - MIT Copyright (c) Microsoft Corporation. 9Copyright (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.Clients.ActiveDirectory 5.2.9 - MIT (c) Microsoft Corporation. Copyright (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.JsonWebTokens 5.4.0 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.JsonWebTokens 5.5.0 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.JsonWebTokens 6.24.0 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.Logging 1.1.2 - MIT Copyright (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.Logging 5.4.0 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.Logging 5.5.0 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.Logging 6.24.0 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.Protocols 6.24.0 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.24.0 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.Tokens 5.1.2 - MIT Copyright (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.Tokens 5.4.0 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.Tokens 5.5.0 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.Tokens 6.24.0 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.JSInterop 6.0.10 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright (c) 2019 David Fowler Copyright (c) 2016 Richard Morris Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2014-2018 Michael Daines Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) .NET Foundation and Contributors Copyright (c) 2019-2020 West Wind Technologies Copyright (c) 2010-2019 Google LLC. http://angular.io/license Copyright (c) Sindre Sorhus (https://sindresorhus.com) MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.NET.StringTools 1.0.0 - MIT (c) Microsoft Corporation. Copyright (c) 2015 Christian Klutz Copyright (c) .NET Foundation and Contributors MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Rest.ClientRuntime 2.3.20 - MIT (c) Microsoft Corporation. Copyright (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Rest.ClientRuntime 2.3.21 - MIT (c) Microsoft Corporation. Copyright (c) 2019 Microsoft Copyright (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Rest.ClientRuntime 2.3.24 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Rest.ClientRuntime.Azure 3.3.18 - MIT (c) Microsoft Corporation. Copyright (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Rest.ClientRuntime.Azure 3.3.19 - MIT (c) Microsoft Corporation. Copyright (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Rest.ClientRuntime.Azure.Authentication 2.4.1 - MIT (c) Microsoft Corporation. Copyright (c) 2019 Microsoft Copyright (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.SourceLink.Common 1.1.1 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.SourceLink.GitHub 1.1.1 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Win32.SystemEvents 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Mono.Options 6.12.0.148 - MIT (c) Microsoft Corporation. Copyright (c) 1990-2009 Info-ZIP. Copyright (c) .NET Foundation Contributors copyrighted by the Free Software Foundation Copyright (c) 1989, 1991 Free Software Foundation, Inc. Copyright 2006 James Newton-King http://www.newtonsoft.com MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- nbgv 3.5.113 - MIT Copyright (c) Manuel Romer Copyright 1995-2017 Mark Adler Copyright James Newton-King 2008 Copyright LibGit2Sharp contributors Copyright (c) 2007 James Newton-King Copyright (c) LibGit2Sharp contributors Copyright James Newton-King 2008 Json.NET Copyright 1995-2017 Mark Adler +3 CScs DEFG Copyright (c) .NET Foundation and Contributors Copyright 1995-2017 Jean-loup Gailly and Mark Adler MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Nerdbank.GitVersioning 3.5.113 - MIT Copyright 1995-2017 Mark Adler Copyright James Newton-King 2008 Copyright LibGit2Sharp contributors Copyright James Newton-King 2008 Json.NET Copyright 1995-2017 Mark Adler +3 CScs DEFG Copyright (c) .NET Foundation and Contributors Copyright AssemblyCompany AssemblyConfiguration Copyright 1995-2017 Jean-loup Gailly and Mark Adler MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Newtonsoft.Json 10.0.3 - MIT Copyright James Newton-King 2008 Copyright (c) 2007 James Newton-King Copyright James Newton-King 2008 Json.NET The MIT License (MIT) Copyright (c) 2007 James Newton-King Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Newtonsoft.Json 13.0.1 - MIT Copyright James Newton-King 2008 Copyright (c) 2007 James Newton-King Copyright (c) James Newton-King 2008 Copyright James Newton-King 2008 Json.NET The MIT License (MIT) Copyright (c) 2007 James Newton-King Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Newtonsoft.Json.Bson 1.0.2 - MIT Copyright James Newton-King 2017 Copyright (c) 2017 James Newton-King Copyright (c) James Newton-King 2017 The MIT License (MIT) Copyright (c) 2017 James Newton-King Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- OPCFoundation.NetStandard.Opc.Ua.Client 1.4.370.12 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- OPCFoundation.NetStandard.Opc.Ua.Client.ComplexTypes 1.4.370.12 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- OPCFoundation.NetStandard.Opc.Ua.Configuration 1.4.370.12 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- OPCFoundation.NetStandard.Opc.Ua.Security.Certificates 1.4.370.12 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- OPCFoundation.NetStandard.Opc.Ua.Server 1.4.370.12 - MIT Copyright 2004-2022 OPC Foundation, Inc Copyright (c) 2008-2022 OPC Foundation, Inc. Copyright (c) 2004-2022 OPC Foundation, Inc OPCFoundation OPC MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- prometheus-net 6.0.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- prometheus-net.AspNetCore 6.0.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Swashbuckle.AspNetCore 6.4.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Swashbuckle.AspNetCore.Annotations 6.4.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Swashbuckle.AspNetCore.Newtonsoft 6.4.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Swashbuckle.AspNetCore.Swagger 6.4.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Swashbuckle.AspNetCore.SwaggerGen 6.4.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Swashbuckle.AspNetCore.SwaggerUI 6.4.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Configuration.ConfigurationManager 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Diagnostics.EventLog 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Diagnostics.PerformanceCounter 4.7.0 - MIT (c) Microsoft Corporation. Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2007 James Newton-King Copyright (c) 1991-2017 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Drawing.Common 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Formats.Asn1 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.IdentityModel.Tokens.Jwt 5.4.0 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.IdentityModel.Tokens.Jwt 5.5.0 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.IdentityModel.Tokens.Jwt 6.24.0 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.IO.FileSystem.AccessControl 4.7.0 - MIT (c) Microsoft Corporation. Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2007 James Newton-King Copyright (c) 1991-2017 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.IO.Hashing 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.IO.Pipelines 6.0.3 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2020 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Memory 4.5.4 - MIT (c) Microsoft Corporation. Copyright (c) 2011, Google Inc. (c) 1997-2005 Sean Eron Anderson. Copyright (c) 1991-2017 Unicode, Inc. Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) 2004-2006 Intel Corporation Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Memory.Data 1.0.2 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Net.WebSockets.WebSocketProtocol 4.5.3 - MIT (c) Microsoft Corporation. Copyright (c) 2011, Google Inc. (c) 1997-2005 Sean Eron Anderson. Copyright (c) 1991-2017 Unicode, Inc. Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) 2004-2006 Intel Corporation Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Runtime.Caching 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Runtime.CompilerServices.Unsafe 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Security.AccessControl 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Security.Cryptography.Pkcs 4.7.0 - MIT (c) Microsoft Corporation. Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2007 James Newton-King Copyright (c) 1991-2017 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Security.Cryptography.ProtectedData 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Security.Cryptography.Xml 4.7.0 - MIT (c) Microsoft Corporation. Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2007 James Newton-King Copyright (c) 1991-2017 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Security.Permissions 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Spatial 5.8.4 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Text.Encodings.Web 4.7.2 - MIT (c) Microsoft Corporation. Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2007 James Newton-King Copyright (c) 1991-2017 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Text.Encodings.Web 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Text.Json 4.7.2 - MIT (c) Microsoft Corporation. Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2007 James Newton-King Copyright (c) 1991-2017 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Text.Json 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Text.Json 6.0.2 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2020 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Threading.Channels 4.5.0 - MIT (c) Microsoft Corporation. Copyright (c) 2011, Google Inc. (c) 1997-2005 Sean Eron Anderson. Copyright (c) 1991-2017 Unicode, Inc. Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) 2004-2006 Intel Corporation Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Threading.Channels 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.ValueTuple 4.5.0 - MIT (c) Microsoft Corporation. Copyright (c) 2011, Google Inc. (c) 1997-2005 Sean Eron Anderson. Copyright (c) 1991-2017 Unicode, Inc. Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) 2004-2006 Intel Corporation Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Windows.Extensions 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- xunit.runner.visualstudio 2.4.5 - MIT Copyright (c) .NET Foundation Copyright (c) 2015 .NET Foundation Copyright (c) Outercurve Foundation Copyright (c) .NET Foundation and Contributors Copyright (c) .NET Foundation xUnit.net Runner Utility Copyright (c) .NET Foundation ,xUnit.net Runner Utility Copyright (c) .NET Foundation 1xUnit.net Runner Utility Copyright (c) .NET Foundation xUnit.net Runner Reporters Copyright (c) .NET Foundation .xUnit.net Runner Reporters Copyright (c) Outercurve Foundation WrapNonExceptionThrows RSDS Copyright (c) .NET Foundation and Contributors. Visual Studio 2019 Unless otherwise noted, the source code here is covered by the following license: Copyright (c) .NET Foundation and Contributors All Rights Reserved Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ----------------------- The code in src/xunit.runner.visualstudio/Utility/AssemblyResolution/Microsoft.DotNet.PlatformAbstractions was imported from: https://github.com/dotnet/core-setup/tree/v2.0.1/src/managed/Microsoft.DotNet.PlatformAbstractions The code in src/xunit.runner.visualstudio/Utility/AssemblyResolution/Microsoft.DotNet.PlatformAbstractions was imported from: https://github.com/dotnet/core-setup/tree/v2.0.1/src/managed/Microsoft.Extensions.DependencyModel Both sets of code are covered by the following license: The MIT License (MIT) Copyright (c) 2015 .NET Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Validation 2.4.18 - MS-PL Microsoft Public License (Ms-PL) This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software. 1. Definitions The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law. A "contribution" is the original software, or any additions or changes to the software. A "contributor" is any person that distributes its contribution under this license. "Licensed patents" are a contributor's patent claims that read directly on its contribution. 2. Grant of Rights (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. 3. Conditions and Limitations (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees, or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. --------------------------------------------------------- --------------------------------------------------------- Xunit.SkippableFact 1.4.13 - MS-PL Microsoft Public License (Ms-PL) This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software. 1. Definitions The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law. A "contribution" is the original software, or any additions or changes to the software. A "contributor" is any person that distributes its contribution under this license. "Licensed patents" are a contributor's patent claims that read directly on its contribution. 2. Grant of Rights (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. 3. Conditions and Limitations (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees, or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. --------------------------------------------------------- NOTICES AND INFORMATION Do Not Translate or Localize This software incorporates material from third parties. Microsoft makes certain open source code available at https://3rdpartysource.microsoft.com, or you may send a check or money order for US $5.00, including the product name, the open source component name, platform, and version number, to: Source Code Compliance Team Microsoft Corporation One Microsoft Way Redmond, WA 98052 USA Notwithstanding any other terms, you may reverse engineer this software to the extent required to debug changes to any libraries licensed under the GNU Lesser General Public License. --------------------------------------------------------- Castle.Core 4.0.0 - Apache-2.0 Copyright 2004-2016 Castle Project Copyright 2004-2017 Castle Project Copyright (c) 2004-2017 Castle Project ECopyright (c) 2004-2017 Castle Project Copyright 2004-2016 Castle Project - http://www.castleproject.org/ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Castle.Core 5.1.1 - Apache-2.0 (c) 2004-2022 Castle Project - http://www.castleproject.org Copyright 2004-2021 Castle Project - http://www.castleproject.org Copyright (c) 2004-2022 Castle Project - http://www.castleproject.org Copyright 2004-2021 Castle Project - http://www.castleproject.org/ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Dapr.Client 1.11.0 - Apache-2.0 Copyright (c) Microsoft Corporation Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Dapr.Extensions.Configuration 1.11.0 - Apache-2.0 Copyright (c) Microsoft Corporation Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- FluentAssertions 6.11.0 - Apache-2.0 Copyright Dennis Doomen 2010-2023 Copyright Dennis Doomen 2010-2023 MSTest2 xUnit NUnit MSpec NSpec TDD BDD Fluent Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- NuGet.Frameworks 6.5.0 - Apache-2.0 (c) Microsoft Corporation Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- OpenTelemetry.Exporter.OpenTelemetryProtocol.Logs 1.5.0-rc.1 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- OpenTelemetry.Exporter.Prometheus.AspNetCore 1.4.0-rc.4 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- OpenTelemetry.Instrumentation.AspNetCore 1.0.0-rc9.14 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- OpenTelemetry.Instrumentation.Http 1.0.0-rc9.14 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- OpenTelemetry.Instrumentation.Runtime 1.5.0 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Roslynator.Analyzers 4.3.0 - Apache-2.0 Copyright (c) 2016-2023 Josef Pihrt Copyright (c) 2016-2023 Josef Pihrt LThis Copyright (c) 2016-2023 Josef Pihrt WThis Copyright (c) 2016-2023 Josef Pihrt Roslyn Analyzer Refactoring Productivity CodeAnalysis C CSharp Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Roslynator.Formatting.Analyzers 4.3.0 - Apache-2.0 Copyright (c) 2016-2023 Josef Pihrt Copyright (c) 2016-2023 Josef Pihrt LThis Copyright (c) 2016-2023 Josef Pihrt WThis Copyright (c) 2016-2023 Josef Pihrt Roslyn Analyzer Formatting Productivity CodeAnalysis C CSharp Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- WindowsAzure.Storage 9.3.2 - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- xunit 2.4.2 - Apache-2.0 Copyright (c) .NET Foundation Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- xunit.abstractions 2.0.3 - Apache-2.0 Copyright (c) Outercurve Foundation Copyright (c) Outercurve Foundation WrapNonExceptionThrows RSDS Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- xunit.analyzers 1.0.0 - Apache-2.0 Copyright (c) .NET Foundation Copyright (c) .NET Foundation xUnit.net Copyright (c) .NET Foundation xunit.analyzers, analyzers, roslyn, xunit, xunit.net Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- xunit.assert 2.4.2 - Apache-2.0 Copyright (c) .NET Foundation Copyright (c) .NET Foundation xUnit.net Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- xunit.core 2.4.2 - Apache-2.0 Copyright (c) .NET Foundation Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- xunit.extensibility.core 2.4.2 - Apache-2.0 Copyright (c) .NET Foundation Copyright (c) .NET Foundation xUnit.net Copyright (c) .NET Foundation 0xUnit.net Copyright (c) .NET Foundation xUnit.net Runner Utility Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- xunit.extensibility.execution 2.4.2 - Apache-2.0 Copyright (c) .NET Foundation Copyright (c) .NET Foundation xUnit.net Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Moq 4.7.0 - BSD-2-Clause Copyright (c) . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------- --------------------------------------------------------- Antlr4 4.6.6 - BSD-3-Clause Copyright (c) . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------- --------------------------------------------------------- Antlr4.CodeGenerator 4.6.6 - BSD-3-Clause Copyright Sam Harwell 2011 Copyright Sam Harwell 2015 Copyright Sam Harwell 2016 Copyright (c) Sam Harwell 2015 Copyright (c) Terence Parr, Sam Harwell. Copyright (c) . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------- --------------------------------------------------------- Antlr4.Runtime 4.6.6 - BSD-3-Clause Copyright (c) . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------- --------------------------------------------------------- Google.Api.CommonProtos 2.2.0 - BSD-3-Clause Copyright 2016, Google Inc. Copyright 2016, Google Inc. All Rights Reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------- --------------------------------------------------------- Google.Protobuf 3.19.4 - BSD-3-Clause Copyright 2008 Google Inc. Copyright 2015, Google Inc. Copyright 2015, Google Inc. Protocol Buffers Binary Serialization Format Google Copyright (c) . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------- --------------------------------------------------------- Moq 4.18.4 - BSD-3-Clause Copyright (c) 2007, Clarius Consulting, Manas Technology Solutions, InSTEDD, and Contributors Copyright (c) . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------- --------------------------------------------------------- nbgv 3.6.133 - CC-BY-4.0 AND MIT AND MS-PL Copyright (c) Manuel Romer Copyright 1995-2017 Mark Adler Copyright James Newton-King 2008 Copyright LibGit2Sharp contributors Copyright (c) 2007 James Newton-King Copyright (c) LibGit2Sharp contributors Copyright James Newton-King 2008 Json.NET Copyright 1995-2017 Mark Adler +3 CScs DEFG Copyright (c) .NET Foundation and Contributors Copyright 1995-2017 Jean-loup Gailly and Mark Adler CC-BY-4.0 AND MIT AND MS-PL --------------------------------------------------------- --------------------------------------------------------- Autofac 7.0.1 - MIT Copyright 2015 Autofac Copyright (c) 2015 Autofac MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Autofac.Extensions.DependencyInjection 8.0.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Autofac.Extras.Moq 6.1.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- AutoFixture 4.18.0 - MIT Copyright Ploeh 2011 Copyright (c) Ploeh 2011 MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Azure.Core 1.32.0 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Azure.Core.Amqp 1.3.0 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Azure.Identity 1.9.0 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Azure.Messaging.EventHubs 5.9.2 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Azure.Messaging.EventHubs.Processor 5.9.2 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Azure.Security.KeyVault.Certificates 4.1.0 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Azure.Security.KeyVault.Secrets 4.5.0 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Azure.Storage.Blobs 12.16.0 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Azure.Storage.Common 12.15.0 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- coverlet.msbuild 6.0.0 - MIT Copyright 2008 - 2018 Jb Evain Copyright Microsoft Corporation Copyright James Newton-King 2008 MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Divergic.Logging.Xunit 4.2.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Fare 2.1.1 - MIT Copyright Nikos Baxevanis 2016 Copyright (c) Nikos Baxevanis 2016 Regex Test NFA DFA Automaton MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Irony 1.2.0 - MIT Copyright 2019 IronyProject Copyright IronyProject, 2019 MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Json.More.Net 1.8.0 - MIT (c) Microsoft 2023 Copyright (c) 2022 Greg Dennis MIT License Copyright (c) 2022 Greg Dennis Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Cryptography.Internal 7.0.7 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright (c) 2019 David Fowler Copyright (c) 2016 Richard Morris Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2014-2018 Michael Daines Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) .NET Foundation and Contributors Copyright (c) 2019-2020 West Wind Technologies Copyright (c) 2010-2019 Google LLC. http://angular.io/license Copyright (c) Sindre Sorhus (https://sindresorhus.com) MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.DataProtection 7.0.7 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright (c) 2019 David Fowler Copyright (c) 2016 Richard Morris Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2014-2018 Michael Daines Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) .NET Foundation and Contributors Copyright (c) 2019-2020 West Wind Technologies Copyright (c) 2010-2019 Google LLC. http://angular.io/license Copyright (c) Sindre Sorhus (https://sindresorhus.com) MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.DataProtection.Abstractions 7.0.7 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright (c) 2019 David Fowler Copyright (c) 2016 Richard Morris Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2014-2018 Michael Daines Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) .NET Foundation and Contributors Copyright (c) 2019-2020 West Wind Technologies Copyright (c) 2010-2019 Google LLC. http://angular.io/license Copyright (c) Sindre Sorhus (https://sindresorhus.com) MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.JsonPatch 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright (c) 2019 David Fowler Copyright (c) 2016 Richard Morris Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2014-2018 Michael Daines Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) .NET Foundation and Contributors Copyright (c) 2019-2020 West Wind Technologies Copyright (c) 2010-2019 Google LLC. http://angular.io/license Copyright (c) Sindre Sorhus (https://sindresorhus.com) MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Mvc.NewtonsoftJson 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright (c) 2019 David Fowler Copyright (c) 2016 Richard Morris Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2014-2018 Michael Daines Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) .NET Foundation and Contributors Copyright (c) 2019-2020 West Wind Technologies Copyright (c) 2010-2019 Google LLC. http://angular.io/license Copyright (c) Sindre Sorhus (https://sindresorhus.com) MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.AspNetCore.Mvc.Versioning 5.1.0 - MIT (c) Microsoft Corporation Copyright (c) Microsoft Corporation MIT License Copyright (c) Microsoft Corporation. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Amqp 2.6.2 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Devices 1.39.0 - MIT (c) Microsoft 2023 (c) Microsoft Corporation Copyright (c) Microsoft Corporation Microsoft Azure IoT SDKs Copyright (c) Microsoft Corporation All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Devices.Client 1.42.0 - MIT (c) Microsoft 2023 (c) Microsoft Corporation Copyright (c) Microsoft Corporation Microsoft Azure IoT SDKs Copyright (c) Microsoft Corporation All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Azure.Devices.Shared 1.30.3 - MIT (c) Microsoft 2023 (c) Microsoft Corporation Copyright (c) Microsoft Corporation Microsoft Azure IoT SDKs Copyright (c) Microsoft Corporation All rights reserved. MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Bcl.AsyncInterfaces 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Build.Tasks.Git 1.1.1 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.ApiDescription.Server 6.0.5 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Caching.Abstractions 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Caching.Memory 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Configuration 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Configuration.Abstractions 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Configuration.Binder 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Configuration.Binder 7.0.4 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Configuration.CommandLine 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Configuration.EnvironmentVariables 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Configuration.FileExtensions 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Configuration.Json 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Configuration.UserSecrets 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.DependencyInjection 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.DependencyInjection.Abstractions 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.DependencyModel 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.FileProviders.Abstractions 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.FileProviders.Physical 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.FileSystemGlobbing 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Hosting 7.0.1 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Hosting.Abstractions 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Http 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Logging 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Logging.Abstractions 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Logging.Abstractions 7.0.1 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Logging.Configuration 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Logging.Console 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Logging.Debug 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Logging.EventLog 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Logging.EventSource 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Options 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Options 7.0.1 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Options.ConfigurationExtensions 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Extensions.Primitives 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Identity.Abstractions 3.2.0 - MIT (c) Microsoft Corporation Copyright (c) Microsoft Corporation MIT License Copyright (c) Microsoft Corporation. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE --------------------------------------------------------- --------------------------------------------------------- Microsoft.Identity.Client 4.49.1 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Identity.Client 4.54.1 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Identity.Client.Extensions.Msal 2.25.3 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Identity.Web 2.12.4 - MIT (c) Microsoft Corporation Copyright (c) Microsoft Corporation MIT License Copyright (c) Microsoft Corporation. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE --------------------------------------------------------- --------------------------------------------------------- Microsoft.Identity.Web.Certificate 2.12.4 - MIT (c) Microsoft Corporation Copyright (c) Microsoft Corporation MIT License Copyright (c) Microsoft Corporation. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE --------------------------------------------------------- --------------------------------------------------------- Microsoft.Identity.Web.Certificateless 2.12.4 - MIT (c) Microsoft Corporation Copyright (c) Microsoft Corporation MIT License Copyright (c) Microsoft Corporation. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE --------------------------------------------------------- --------------------------------------------------------- Microsoft.Identity.Web.Diagnostics 2.12.4 - MIT (c) Microsoft Corporation Copyright (c) Microsoft Corporation MIT License Copyright (c) Microsoft Corporation. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE --------------------------------------------------------- --------------------------------------------------------- Microsoft.Identity.Web.TokenAcquisition 2.12.4 - MIT (c) Microsoft Corporation Copyright (c) Microsoft Corporation MIT License Copyright (c) Microsoft Corporation. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE --------------------------------------------------------- --------------------------------------------------------- Microsoft.Identity.Web.TokenCache 2.12.4 - MIT (c) Microsoft Corporation Copyright (c) Microsoft Corporation MIT License Copyright (c) Microsoft Corporation. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.Abstractions 6.22.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.Abstractions 6.30.0 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.JsonWebTokens 6.30.0 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.Logging 6.30.0 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.LoggingExtensions 6.30.0 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.Protocols 6.30.0 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.Protocols.OpenIdConnect 6.30.0 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.Tokens 6.30.0 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IdentityModel.Validators 6.30.0 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.IO.RecyclableMemoryStream 2.3.2 - MIT Copyright Microsoft 2015 (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.NET.Build.Containers 7.0.304 - MIT (c) Microsoft Corporation Copyright James Newton-King 2008 Copyright James Newton-King 2008 Json.NET MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.NET.StringTools 17.6.3 - MIT (c) Microsoft Corporation Copyright (c) 2015 Christian Klutz Copyright (c) .NET Foundation and Contributors MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Rest.ClientRuntime 2.3.21 - MIT (c) Microsoft Corporation. Copyright (c) 2019 Microsoft Copyright (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.SourceLink.Common 1.1.1 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.SourceLink.GitHub 1.1.1 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Win32.SystemEvents 4.7.0 - MIT (c) Microsoft Corporation. Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2007 James Newton-King Copyright (c) 1991-2017 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Mono.Options 6.12.0.148 - MIT (c) Microsoft Corporation. Copyright (c) 1990-2009 Info-ZIP. Copyright (c) .NET Foundation Contributors copyrighted by the Free Software Foundation Copyright (c) 1989, 1991 Free Software Foundation, Inc. Copyright 2006 James Newton-King http://www.newtonsoft.com MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- MQTTnet 4.2.1.781 - MIT Copyright (c) .NET Foundation and Contributors Copyright (c) .NET Foundation and Contributors MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- MQTTnet.Extensions.ManagedClient 4.2.1.781 - MIT Copyright (c) .NET Foundation and Contributors Copyright (c) .NET Foundation and Contributors MQTT Message Queue Telemetry Transport MQTTClient MQTTServer Server MQTTBroker Broker NETStandard IoT InternetOfThings Messaging Hardware Arduino Sensor Actuator M2M ESP Smart Home Cities Automation Xamarin Blazor MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Nerdbank.GitVersioning 3.6.133 - MIT Copyright 1995-2017 Mark Adler Copyright James Newton-King 2008 Copyright LibGit2Sharp contributors Copyright James Newton-King 2008 Json.NET Copyright 1995-2017 Mark Adler +3 CScs DEFG Copyright (c) .NET Foundation and Contributors Copyright AssemblyCompany AssemblyConfiguration Copyright 1995-2017 Jean-loup Gailly and Mark Adler MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Newtonsoft.Json.Bson 1.0.2 - MIT Copyright James Newton-King 2017 Copyright (c) 2017 James Newton-King Copyright (c) James Newton-King 2017 The MIT License (MIT) Copyright (c) 2017 James Newton-King Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Nito.AsyncEx 5.1.2 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Nito.AsyncEx.Context 5.1.2 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Nito.AsyncEx.Coordination 5.1.2 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Nito.AsyncEx.Interop.WaitHandles 5.1.2 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Nito.AsyncEx.Oop 5.1.2 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Nito.AsyncEx.Tasks 5.1.2 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Nito.Cancellation 1.1.2 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Nito.Collections.Deque 1.1.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Nito.Disposables 2.2.1 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Nito.Disposables 2.4.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Swashbuckle.AspNetCore 6.5.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Swashbuckle.AspNetCore.Annotations 6.5.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Swashbuckle.AspNetCore.Newtonsoft 6.5.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Swashbuckle.AspNetCore.Swagger 6.5.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Swashbuckle.AspNetCore.SwaggerGen 6.5.0 - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Swashbuckle.AspNetCore.SwaggerUI 6.5.0 - MIT (c) ,u r(1970) MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Configuration.ConfigurationManager 4.4.0 - MIT The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Configuration.ConfigurationManager 4.4.1 - MIT The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Diagnostics.EventLog 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Diagnostics.EventLog 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Drawing.Common 4.7.2 - MIT (c) Microsoft Corporation. Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2007 James Newton-King Copyright (c) 1991-2017 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Formats.Asn1 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Formats.Asn1 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.IdentityModel.Tokens.Jwt 6.30.0 - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.IO.FileSystem.AccessControl 5.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.IO.Hashing 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.IO.Pipelines 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Linq.Async 6.0.1 - MIT Copyright (c) .NET Foundation and Contributors. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Memory 4.5.3 - MIT Copyright (c) 2011, Google Inc. (c) 1997-2005 Sean Eron Anderson. Copyright (c) 1991-2017 Unicode, Inc. Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) 2004-2006 Intel Corporation Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Memory 4.5.4 - MIT (c) Microsoft Corporation. Copyright (c) 2011, Google Inc. (c) 1997-2005 Sean Eron Anderson. Copyright (c) 1991-2017 Unicode, Inc. Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) 2004-2006 Intel Corporation Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Memory.Data 1.0.2 - MIT (c) Microsoft Corporation. MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Net.Http.Json 5.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Runtime.CompilerServices.Unsafe 5.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Runtime.CompilerServices.Unsafe 6.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Security.AccessControl 5.0.0 - MIT (c) Microsoft Corporation. Copyright (c) Andrew Arnott Copyright 2018 Daniel Lemire Copyright 2012 the V8 project Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. Copyright (c) 1998 Microsoft. To (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2017 Yoshifumi Kawai Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2018 Alexander Chermyanin Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) The Internet Society 1997. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) The Internet Society (2003). Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Security.Cryptography.Pkcs 7.0.3 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Security.Cryptography.ProtectedData 4.4.0 - MIT (c) Microsoft Corporation. (c) 1997-2005 Sean Eron Anderson. Copyright (c) 1991-2017 Unicode, Inc. Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Security.Cryptography.ProtectedData 4.7.0 - MIT (c) Microsoft Corporation. Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2007 James Newton-King Copyright (c) 1991-2017 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Security.Cryptography.Xml 7.0.1 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Text.Encodings.Web 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Text.Json 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Threading.Channels 4.7.1 - MIT (c) Microsoft Corporation. Copyright (c) .NET Foundation. Copyright (c) 2011, Google Inc. (c) 1997-2005 Sean Eron Anderson. Copyright (c) 2007 James Newton-King Copyright (c) 1991-2017 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2005-2007, Nick Galbreath Portions (c) International Organization Copyright (c) 2015 The Chromium Authors. Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) .NET Foundation Contributors Copyright (c) .NET Foundation and Contributors Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers THIS WORK IS PROVIDED AS The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- System.Threading.Channels 7.0.0 - MIT (c) Microsoft Corporation Copyright (c) Andrew Arnott Copyright 2019 LLVM Project Copyright 2018 Daniel Lemire Copyright (c) .NET Foundation Copyright (c) 2011, Google Inc. Copyright (c) 2020 Dan Shechter (c) 1997-2005 Sean Eron Anderson Copyright (c) 1998 Microsoft. To Copyright (c) 2017 Yoshifumi Kawai Copyright (c) 2005-2020 Rich Felker Copyright (c) Microsoft Corporation Copyright (c) 2007 James Newton-King Copyright (c) 2012-2014, Yann Collet Copyright (c) 1991-2022 Unicode, Inc. Copyright (c) 2013-2017, Alfred Klomp Copyright 2012 the V8 project authors Copyright (c) 1999 Lucent Technologies Copyright (c) 2008-2016, Wojciech Mula Copyright (c) 2011-2020 Microsoft Corp Copyright (c) 2015-2017, Wojciech Mula Copyright (c) 2021 csFastFloat authors Copyright (c) 2005-2007, Nick Galbreath Copyright (c) 2015 The Chromium Authors Copyright (c) 2018 Alexander Chermyanin Copyright (c) The Internet Society 1997 Portions (c) International Organization Copyright (c) 2004-2006 Intel Corporation Copyright (c) 2013-2017, Milosz Krajewski Copyright (c) 2016-2017, Matthieu Darbois Copyright (c) The Internet Society (2003) Copyright (c) .NET Foundation Contributors Copyright (c) 2020 Mara Bos Copyright (c) .NET Foundation and Contributors Copyright (c) 2008-2020 Advanced Micro Devices, Inc. Copyright (c) 2019 Microsoft Corporation, Daan Leijen Copyright (c) 2011 Novell, Inc (http://www.novell.com) Copyright (c) 1995-2022 Jean-loup Gailly and Mark Adler Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors Copyright (c) 2014 Ryan Juckett http://www.ryanjuckett.com Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. Copyright (c) YEAR W3C(r) (MIT, ERCIM, Keio, Beihang). Disclaimers Copyright (c) 2015 THL A29 Limited, a Tencent company, and Milo Yip Copyright (c) 1980, 1986, 1993 The Regents of the University of California Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the University of California Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & Digital Equipment Corporation, Maynard, Mass. To The MIT License (MIT) Copyright (c) .NET Foundation and Contributors All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- xRetry 1.9.0 - MIT Copyright Josh Keegan 2019-2023 XUnit Retry Test-Automation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- xunit.runner.visualstudio 2.4.5 - MIT Copyright (c) .NET Foundation Copyright (c) 2015 .NET Foundation Copyright (c) Outercurve Foundation Copyright (c) .NET Foundation and Contributors Copyright (c) .NET Foundation xUnit.net Runner Utility Copyright (c) .NET Foundation ,xUnit.net Runner Utility Copyright (c) .NET Foundation 1xUnit.net Runner Utility Copyright (c) .NET Foundation xUnit.net Runner Reporters Copyright (c) .NET Foundation .xUnit.net Runner Reporters Copyright (c) Outercurve Foundation WrapNonExceptionThrows RSDS Copyright (c) .NET Foundation and Contributors. Visual Studio 2019 Unless otherwise noted, the source code here is covered by the following license: Copyright (c) .NET Foundation and Contributors All Rights Reserved Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ----------------------- The code in src/xunit.runner.visualstudio/Utility/AssemblyResolution/Microsoft.DotNet.PlatformAbstractions was imported from: https://github.com/dotnet/core-setup/tree/v2.0.1/src/managed/Microsoft.DotNet.PlatformAbstractions The code in src/xunit.runner.visualstudio/Utility/AssemblyResolution/Microsoft.DotNet.PlatformAbstractions was imported from: https://github.com/dotnet/core-setup/tree/v2.0.1/src/managed/Microsoft.Extensions.DependencyModel Both sets of code are covered by the following license: The MIT License (MIT) Copyright (c) 2015 .NET Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Validation 2.4.18 - MS-PL Microsoft Public License (Ms-PL) This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software. 1. Definitions The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law. A "contribution" is the original software, or any additions or changes to the software. A "contributor" is any person that distributes its contribution under this license. "Licensed patents" are a contributor's patent claims that read directly on its contribution. 2. Grant of Rights (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. 3. Conditions and Limitations (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees, or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. --------------------------------------------------------- --------------------------------------------------------- Xunit.SkippableFact 1.4.13 - MS-PL Microsoft Public License (Ms-PL) This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software. 1. Definitions The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law. A "contribution" is the original software, or any additions or changes to the software. A "contributor" is any person that distributes its contribution under this license. "Licensed patents" are a contributor's patent claims that read directly on its contribution. 2. Grant of Rights (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. 3. Conditions and Limitations (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees, or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. --------------------------------------------------------- ================================================ FILE: Nuget.Config ================================================ ================================================ FILE: SECURITY.md ================================================ ## Security Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. ## Reporting Security Issues **Please do not report security vulnerabilities through public GitHub issues.** Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) * Full paths of source file(s) related to the manifestation of the issue * The location of the affected source code (tag/branch/commit or direct URL) * Any special configuration required to reproduce the issue * Step-by-step instructions to reproduce the issue * Proof-of-concept or exploit code (if possible) * Impact of the issue, including how an attacker might exploit the issue This information will help us triage your report more quickly. If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. ## Preferred Languages We prefer all communications to be in English. ## Policy Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). ================================================ FILE: azure-pipelines.yml ================================================ pr: autoCancel: 'true' drafts: 'true' branches: include: - '*' trigger: batch: 'true' branches: include: - latest - main - release/* parameters: - name: onebranch displayName: 'One Branch to use' type: string default: 'main' values: - 'main' - 'test' jobs: - job: OneBranchTrigger pool: vmImage: 'ubuntu-latest' timeoutInMinutes: 120 displayName: Trigger Governed Pipeline steps: - task: PowerShell@2 displayName: 'Determine pipeline and parameters' inputs: targetType: 'inline' pwsh: true script: | $message = '$(Build.SourceVersionMessage)' if ([string]::IsNullOrWhiteSpace($message)) { $message = 'No message' } $message = $message -replace "[^a-zA-Z0-9\s]", "" $message = $message.Trim() $message = $message.substring(0, [System.Math]::Min(100, $message.Length)) $branchName = '$(Build.SourceBranch)' $branchName = $branchName -replace "refs/heads/", "" if ('$(Build.Reason)' -eq 'PullRequest') { $pipelineDefinition = 'Industrial-IoT-PullRequest' $templateParameters = "ref: $(Build.SourceBranch), buildInfo: '$message'" Write-Host "Triggering Pull Request build for $(Build.SourceBranch)..." } elseif ('$(Build.SourceBranch)' -like 'refs/heads/release/*') { $pipelineDefinition = 'Industrial-IoT-Official' $templateParameters = "branch: $branchName, buildInfo: '$message'" Write-Host "Triggering official build for branch $branchName..." } else { $pipelineDefinition = 'Industrial-IoT-Buddy' $templateParameters = "branch: $branchName, buildInfo: '$message'" Write-Host "Triggering buddy build for branch $branchName ..." } Write-Host "$(Build.Reason): Trigger $pipelineDefinition with '$templateParameters'..." Write-Host "##vso[task.setvariable variable=pipelineDefinition]$pipelineDefinition" Write-Host "##vso[task.setvariable variable=templateParameters]$templateParameters" - task: TriggerBuild@4 displayName: 'Trigger Build' inputs: definitionIsInCurrentTeamProject: true buildDefinition: $(pipelineDefinition) queueBuildForUserThatTriggeredBuild: false ignoreSslCertificateErrors: false useSameSourceVersion: false useCustomSourceVersion: false useSameBranch: false branchToUse: '${{ parameters.onebranch }}' storeInEnvironmentVariable: true authenticationMethod: 'OAuth Token' password: $(System.AccessToken) enableBuildInQueueCondition: true dependentOnSuccessfulBuildCondition: false dependentOnFailedBuildCondition: false checkbuildsoncurrentbranch: false failTaskIfConditionsAreNotFulfilled: false templateParameters: '$(templateParameters)' - task: PowerShell@2 displayName: 'Update build number and tags' inputs: targetType: 'inline' pwsh: true script: | $buildId = $(TriggeredBuildIds) $buildUrl = "$(System.TeamFoundationCollectionUri)$(System.TeamProject)/_build/results?buildId=$buildId" Write-Host "Triggered build $buildUrl ..." Write-Host "##vso[build.addbuildtag]$(pipelineDefinition) build $buildId" Write-Host "##vso[task.logissue type=warning]$buildUrl" Write-Host "##vso[build.updatebuildnumber]$buildId" - task: WaitForBuildToFinish@3 displayName: 'Wait for build to finish' inputs: definitionIsInCurrentTeamProject: true ignoreSslCertificateErrors: false waitForQueuedBuildsToFinishRefreshTime: '90' failTaskIfBuildsNotSuccessful: true cancelBuildsIfAnyFails: false treatPartiallySucceededBuildAsSuccessful: true downloadBuildArtifacts: false clearVariable: true authenticationMethod: 'OAuth Token' password: $(System.AccessToken) ================================================ FILE: common.props ================================================ Azure Industrial IoT Platform https://github.com/Azure/Industrial-IoT MIT NU5125;RS1022;AD0001 Microsoft Microsoft © Microsoft Corporation. All rights reserved. icon.png readme.md $(RepositoryUrl)/releases $(RepositoryUrl) true Industrial;Industrial IoT;Manufacturing;Azure;IoT;.NET true en-US 13.0 false disable false false win-x64;linux-x64;linux-musl-x64;linux-musl-arm;linux-musl-arm64 true snupkg true true true true All preview default false $(MSBuildProjectFullPath).$([System.Guid]::NewGuid().ToString().Substring(0,8)).sarif ================================================ FILE: contributing.md ================================================ We'll be glad to accept patches and contributions to the project. There are just few guidelines we ask to follow. Contribution License Agreement ============================== If you want/plan to contribute, we ask you to sign a [CLA](https://cla.microsoft.com/) (Contribution License Agreement). A friendly bot will remind you about it when you submit a pull-request. Submitting a contribution ========================= It's generally best to start by [opening a new issue](https://help.github.com/articles/creating-an-issue) describing the work you intend to submit. Even for minor tasks, it's helpful to know what contributors are working on. Please mention in the initial issue that you are planning to work on it, so that it can be assigned to you. Follow the usual GitHub flow process of [forking the project](https://help.github.com/articles/fork-a-repo), and setup a new branch to work in. Each group of changes should be done in separate branches, in order to ensure that a pull request only includes the changes related to one issue. Any significant change should almost always be accompanied by tests. Look at the existing tests to see the testing approach and style used. Follow the project coding style, to ensure consistency and quick code reviews. We heavily rely on dependency injection using *Autofac* and thus ask to follow the same paradigm when adding new code. Do your best to have clear commit messages for each change, in order to keep consistency throughout the project. Reference the issue number (#num). A good commit message serves at least these purposes: * Speed up the pull request review process * Help future developers to understand the purpose of your code * Help the maintainer write release notes One-line messages are fine for small changes, but bigger changes should look like this: ``` $ git commit -m "A brief summary of the commit > > A paragraph describing what changed and its impact." ``` Finally, push the commits to your fork, submit a pull request, wait for all gates to pass and fix any issues found as part of the gate process. The team might ask for some [changes](https://help.github.com/articles/committing-changes-to-a-pull-request-branch-created-from-a-fork) before merging the pull request. ================================================ FILE: deploy/azuredeploy.json ================================================ { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "userPrincipalId": { "type": "string", "defaultValue": "", "metadata": { "description": "Specifies the object ID of a principal in your Azure Active Directory tenant to access the deployed services." } }, "userManagedIdentityName": { "type": "string", "defaultValue": "[concat('msi', take(uniqueString(subscription().subscriptionId, resourceGroup().id), 5))]", "metadata": { "description": "The name of the managed identity to create. If client principal was omitted a default identity will be provisioned to access resources." } }, "storageName": { "type": "string", "defaultValue": "[concat('storage', take(uniqueString(subscription().subscriptionId, resourceGroup().id), 6))]", "metadata": { "description": "The name of the storage account created as part of the deployment." } }, "storageSkuName": { "type": "string", "defaultValue": "Standard_LRS", "allowedValues": [ "Standard_LRS", "Standard_GRS", "Standard_RAGRS", "Standard_ZRS", "Premium_LRS" ], "metadata": { "description": "The storage SKU to use." } }, "iotHubName": { "type": "string", "defaultValue": "[concat('iothub-', take(uniqueString(subscription().subscriptionId, resourceGroup().id), 6))]", "metadata": { "description": "The name of Azure IoT Hub created as part of the deployment." } }, "iotHubSku": { "type": "string", "defaultValue": "S1", "allowedValues": [ "F1", "S1", "S2", "S3" ], "metadata": { "description": "The Azure IoT Hub SKU to use." } }, "iotHubCapacity": { "type": "int", "defaultValue": 1, "metadata": { "description": "The Azure IoT Hub SKU capacity to use." } }, "iotHubTier": { "type": "string", "defaultValue": "Standard", "allowedValues": [ "Free", "Standard" ], "metadata": { "description": "The Azure IoT Hub tier to use." } }, "iotHubPartitionCount": { "type": "int", "defaultValue": 4, "metadata": { "description": "The Azure IoT Hub default endpoint partition count." } }, "iotHubRetentionInDays": { "type": "int", "defaultValue": 2, "metadata": { "description": "The Azure IoT Hub default message retention in days." } }, "dpsName": { "type": "string", "defaultValue": "[concat('dps', take(uniqueString(subscription().subscriptionId, resourceGroup().id), 6))]", "metadata": { "description": "The name of the Azure Device Provisioning service created as part of this deployment." } }, "dpsSku": { "type": "string", "defaultValue": "S1", "allowedValues": [ "S1" ], "metadata": { "description": "The Azure Device Provisioning service SKU to use." } }, "dpsCapacity": { "type": "int", "defaultValue": 1, "minValue": 1, "maxValue": 3, "metadata": { "description": "The Azure Device Provisioning service capacity." } }, "tags": { "type": "object", "defaultValue": {}, "metadata": { "description": "Tags for Azure resources." } } }, "variables": { "iotHubResourceId": "[resourceId('Microsoft.Devices/Iothubs', parameters('iotHubName'))]", "iotHubContributorRoleId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4fc6c259-987e-4a07-842e-c321cc9d413f')]", "iotHubPrincipalRoleAssignment": "[guid(parameters('iotHubName'), parameters('userPrincipalId'))]", "iotHubKeyName": "iothubowner", "iotHubKeyResource": "[resourceId('Microsoft.Devices/Iothubs/Iothubkeys', parameters('iotHubName'), variables('iotHubKeyName'))]", "iotHubTelemetryConsumerGroup": "telemetry", "iotHubEventsConsumerGroup": "events", "userManagedIdentityResourceId": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('userManagedIdentityName'))]", "storageResourceId": "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageName'))]", "storageBlobDataOwnerRoleId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b')]", "storageAccountContributorRoleId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '17d1049b-9a84-46fb-8f53-869881c3d3ab')]", "storagePrincipalBlobDataOwnerRoleAssignment": "[guid(parameters('storageName'), 'StorageBlobDataOwner', parameters('userPrincipalId'))]", "storagePrincipalStorageAccountContributorRoleAssignment": "[guid(parameters('storageName'), 'StorageAccountContributor', parameters('userPrincipalId'))]", "storageRoleAssignment": "[guid(parameters('storageName'), parameters('userManagedIdentityName'))]", "dpsResourceId": "[resourceId('Microsoft.Devices/provisioningServices', parameters('dpsName'))]" }, "resources": [ { "comments": "User managed identity.", "name": "[parameters('userManagedIdentityName')]", "type": "Microsoft.ManagedIdentity/userAssignedIdentities", "apiVersion": "2023-01-31", "location": "[resourceGroup().location]", "tags": "[parameters('tags')]" }, { "comments": "Create an Azure IoT Hub.", "apiVersion": "2023-06-30", "type": "Microsoft.Devices/Iothubs", "name": "[parameters('iotHubName')]", "location": "[resourceGroup().location]", "identity": { "userAssignedIdentities": { "[variables('userManagedIdentityResourceId')]": {} }, "type": "UserAssigned" }, "tags": "[parameters('tags')]", "sku": { "name": "[parameters('iotHubSku')]", "tier": "[parameters('iotHubTier')]", "capacity": "[parameters('iotHubCapacity')]" }, "properties": { "location": "[resourceGroup().location]", "ipFilterRules": [], "disableLocalAuth": false, "eventHubEndpoints": { "events": { "retentionTimeInDays": "[parameters('iotHubRetentionInDays')]", "partitionCount": "[parameters('iotHubPartitionCount')]" } }, "routing": { "endpoints": { "serviceBusQueues": [], "serviceBusTopics": [], "eventHubs": [], "storageContainers": [] }, "routes": [ { "name": "TwinChanges", "source": "TwinChangeEvents", "condition": "true", "endpointNames": [ "events" ], "isEnabled": true }, { "name": "DeviceLifecycle", "source": "DeviceLifecycleEvents", "condition": "true", "endpointNames": [ "events" ], "isEnabled": true } ], "fallbackRoute": { "name": "$fallback", "source": "DeviceMessages", "condition": "true", "endpointNames": [ "events" ], "isEnabled": true } }, "messagingEndpoints": { "fileNotifications": { "lockDurationAsIso8601": "PT1M", "ttlAsIso8601": "PT1H", "maxDeliveryCount": 10 } }, "cloudToDevice": { "maxDeliveryCount": 10, "defaultTtlAsIso8601": "PT1H", "feedback": { "lockDurationAsIso8601": "PT1M", "ttlAsIso8601": "PT1H", "maxDeliveryCount": 10 } }, "features": "None" }, "dependsOn": [ "[variables('storageResourceId')]", "[variables('userManagedIdentityResourceId')]" ] }, { "comments": "Add optionally the iot hub owner role to the user principal.", "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "name": "[variables('iotHubPrincipalRoleAssignment')]", "condition": "[not(empty(parameters('userPrincipalId')))]", "scope": "[variables('iotHubResourceId')]", "properties": { "roleDefinitionId": "[variables('iotHubContributorRoleId')]", "principalId": "[parameters('userPrincipalId')]" }, "dependsOn": [ "[variables('iotHubResourceId')]" ] }, { "comments": "Create a Telemetry Consumer Group in IoT Hub.", "apiVersion": "2019-03-22", "name": "[concat(parameters('iotHubName'), '/events/', variables('iotHubTelemetryConsumerGroup'))]", "type": "Microsoft.Devices/Iothubs/eventhubEndpoints/ConsumerGroups", "tags": "[parameters('tags')]", "dependsOn": [ "[variables('iotHubResourceId')]" ] }, { "comments": "And a edge Events Consumer Group in the hub.", "apiVersion": "2019-03-22", "name": "[concat(parameters('iotHubName'), '/events/', variables('iotHubEventsConsumerGroup'))]", "type": "Microsoft.Devices/Iothubs/eventhubEndpoints/ConsumerGroups", "tags": "[parameters('tags')]", "dependsOn": [ "[variables('iotHubResourceId')]" ] }, { "comments": "Create blob storage account for event processing offset snapshots.", "type": "Microsoft.Storage/storageAccounts", "name": "[parameters('storageName')]", "apiVersion": "2023-04-01", "location": "[resourceGroup().location]", "tags": "[parameters('tags')]", "kind": "StorageV2", "sku": { "name": "[parameters('storageSkuName')]" }, "properties": { "networkAcls": { "bypass": "AzureServices", "virtualNetworkRules": [], "ipRules": [], "defaultAction": "Allow" }, "defaultToOAuthAuthentication": true, "allowSharedKeyAccess": false, "supportsHttpsTrafficOnly": true, "encryption": { "services": { "file": { "enabled": true }, "blob": { "enabled": true } }, "keySource": "Microsoft.Storage" } } }, { "comments": "Assign access to own blobs in the storage to our managed identity.", "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "name": "[variables('storageRoleAssignment')]", "scope": "[variables('storageResourceId')]", "properties": { "roleDefinitionId": "[variables('storageBlobDataOwnerRoleId')]", "principalId": "[reference(variables('userManagedIdentityResourceId'), '2018-11-30').principalId]", "principalType": "ServicePrincipal" }, "dependsOn": [ "[variables('userManagedIdentityResourceId')]", "[variables('storageResourceId')]" ] }, { "comments": "And optionally the storage blob data owner role...", "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "name": "[variables('storagePrincipalBlobDataOwnerRoleAssignment')]", "condition": "[not(empty(parameters('userPrincipalId')))]", "scope": "[variables('storageResourceId')]", "properties": { "roleDefinitionId": "[variables('storageBlobDataOwnerRoleId')]", "principalId": "[parameters('userPrincipalId')]" }, "dependsOn": [ "[variables('storageResourceId')]" ] }, { "comments": "... as well as the storage account contributor role to the user principal.", "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "name": "[variables('storagePrincipalStorageAccountContributorRoleAssignment')]", "condition": "[not(empty(parameters('userPrincipalId')))]", "scope": "[variables('storageResourceId')]", "properties": { "roleDefinitionId": "[variables('storageAccountContributorRoleId')]", "principalId": "[parameters('userPrincipalId')]" }, "dependsOn": [ "[variables('storageResourceId')]" ] }, { "comments": "Create Azure Device Provisioning service.", "type": "Microsoft.Devices/provisioningServices", "name": "[parameters('dpsName')]", "apiVersion": "2022-12-12", "location": "[resourceGroup().location]", "tags": "[parameters('tags')]", "sku": { "name": "[parameters('dpsSku')]", "capacity": "[parameters('dpsCapacity')]" }, "properties": { "iotHubs": [ { "connectionString": "[concat('HostName=', reference(variables('iotHubResourceId')).hostName, ';SharedAccessKeyName=', variables('iotHubKeyName'), ';SharedAccessKey=', listKeys(variables('iotHubKeyResource'), '2018-04-01').primaryKey)]", "iotHubResourceId": "[variables('iotHubResourceId')]", "location": "[resourceGroup().location]", "name": "[reference(variables('iotHubResourceId')).hostName]" } ] }, "dependsOn": [ "[variables('iotHubResourceId')]" ] } ], "outputs": { "iotHubConnString": { "type": "string", "value": "[concat('HostName=', reference(variables('iotHubResourceId')).hostName, ';SharedAccessKeyName=', variables('iotHubKeyName'), ';SharedAccessKey=', listKeys(variables('iotHubKeyResource'), '2018-04-01').primaryKey)]", "metadata": { "description": "The connection string for the IoT Hub. Use this to connect to IoT Hub using your user principal or managed identity." } }, "dpsConnString": { "type": "string", "value": "[concat('HostName=', reference(variables('dpsResourceId'), '2018-01-22'). serviceOperationsHostName, ';SharedAccessKeyName=', listKeys(variables('dpsResourceId'), '2018-01-22').value[0].keyName, ';SharedAccessKey=', listKeys(variables('dpsResourceId'), '2018-01-22').value[0].primaryKey)]", "metadata": { "description": "The connection string for the Device Provisioning Service. Use this to deploy IoT Edge devices using DPS." } }, "dpsIdScope": { "type": "string", "value": "[reference(variables('dpsResourceId'), '2018-01-22').idScope]", "metadata": { "description": "The ID scope for the Device Provisioning Service. Use this to deploy IoT Edge devices using DPS." } }, "tenantId": { "type": "string", "value": "[subscription().tenantId]", "metadata": { "description": "The tenant ID of the Azure subscription." } } } } ================================================ FILE: deploy/azuredeploy.parameters.json ================================================ { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", "parameters": { "userPrincipalId": { "value": "", "metadata": { "description": "The user principal ID of the user who will be assigned as the owner of the IoT Hub and DPS. Leave empty to not give access to a user principal ID.", "displayName": "User Principal ID" } }, "storageSkuName": { "value": "Standard_LRS", "metadata": { "description": "The SKU name for the storage account. Valid values are Standard_LRS, Standard_GRS, Standard_RAGRS, Premium_LRS, Standard_ZRS, Premium_ZRS.", "displayName": "Storage Account SKU Name" } }, "iotHubSku": { "value": "S1", "metadata": { "description": "The SKU for the IoT Hub. Valid values are S1, S2, S3, B1, B2, B3, F1.", "displayName": "IoT Hub SKU" } }, "iotHubCapacity": { "value": 1, "metadata": { "description": "The capacity for the IoT Hub. This is the number of units for the IoT Hub. For S1, S2, and S3 SKUs, this is the number of throughput units.", "displayName": "IoT Hub Capacity" } }, "iotHubTier": { "value": "Standard", "metadata": { "description": "The tier for the IoT Hub. Valid values are Basic, Standard, Free, and Premium. Note that the Free tier has limitations on the number of devices and messages.", "displayName": "IoT Hub Tier" } }, "iotHubPartitionCount": { "value": 4, "metadata": { "description": "The partition count for the IoT Hub. This is the number of partitions for the IoT Hub. The default value is 4, but it can be set to a maximum of 32 for S1, S2, and S3 SKUs.", "displayName": "IoT Hub Partition Count" } }, "iotHubRetentionInDays": { "value": 2, "metadata": { "description": "The message retention period for the IoT Hub. This is the number of days that messages are retained in the IoT Hub. The default value is 2 days, but it can be set to a maximum of 7 days for S1, S2, and S3 SKUs.", "displayName": "IoT Hub Retention (Days)" } }, "dpsSku": { "value": "S1", "metadata": { "description": "The SKU for the Device Provisioning Service. Valid values are S1, S2, S3, B1, B2, B3, F1.", "displayName": "DPS SKU" } }, "dpsCapacity": { "value": 1, "metadata": { "description": "The capacity for the Device Provisioning Service. This is the number of units for the DPS. For S1, S2, and S3 SKUs, this is the number of throughput units.", "displayName": "DPS Capacity" } } } } ================================================ FILE: deploy/deploy.ps1 ================================================ <# .SYNOPSIS Deploys Azure services required for the Industrial IoT solution. .DESCRIPTION Deploys the Industrial IoT services and dependencies on Azure. .PARAMETER Name The name of the deployment. .PARAMETER ResourceGroup The name of the resource group to deploy to. .PARAMETER TenantId The Azure tenant ID to use for the deployment. .PARAMETER SubscriptionId The Azure subscription ID to use for the deployment. .PARAMETER Location The Azure region to deploy the resources to. .PARAMETER NoPrompt If specified, the script will not prompt for confirmation before saving the environment variables to a file. #> param( [string] [Parameter(Mandatory = $true)] $Name, [string] $ResourceGroup, [string] $TenantId, [string] $SubscriptionId, [string] $Location, [switch] $NoPrompt ) $ErrorActionPreference = 'Continue' $scriptDir = Split-Path -Path $MyInvocation.MyCommand.Path # # Dump command line arguments # if ([string]::IsNullOrWhiteSpace($script:ResourceGroup)) { $script:ResourceGroup = $script:Name } Write-Host "Using resource group $($script:ResourceGroup)..." -ForegroundColor Cyan if ([string]::IsNullOrWhiteSpace($script:TenantId)) { $script:TenantId = $env:AZURE_TENANT_ID } if (![string]::IsNullOrWhiteSpace($script:TenantId)) { Write-Host "Using tenant $($script:TenantId)..." -ForegroundColor Cyan } if ([string]::IsNullOrWhiteSpace($script:Location)) { $script:Location = "westus" } Write-Host "Using location $($script:Location)..." -ForegroundColor Cyan if ([string]::IsNullOrWhiteSpace($script:OpsInstanceName)) { $script:OpsInstanceName = $script:Name } $errOut = $($azVersion = (az version)[1].Split(":")[1].Split('"')[1]) 2>&1 if ($azVersion -lt "2.74.0" -or !$azVersion) { Write-Host "Azure CLI version 2.74.0 or higher is required. $errOut" ` -ForegroundColor Red exit -1 } # # Log into azure # Write-Host "Log into Azure..." -ForegroundColor Cyan $loginParams = @( "--only-show-errors" ) if (![string]::IsNullOrWhiteSpace($script:TenantId)) { $loginParams += @("--tenant", $script:TenantId) } $session = (az login @loginParams) | ConvertFrom-Json if (-not $session) { Write-Host "Error: Login failed." -ForegroundColor Red exit -1 } if ([string]::IsNullOrWhiteSpace($SubscriptionId)) { $script:SubscriptionId = $session[0].id } if ([string]::IsNullOrWhiteSpace($TenantId)) { $script:TenantId = $session[0].tenantId } $errOut = $($rg = & { az group show ` --name $script:ResourceGroup ` --subscription $script:SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if (!$rg) { Write-Host "Creating resource group $script:ResourceGroup..." -ForegroundColor Cyan $errOut = $($rg = & { az group create ` --name $script:ResourceGroup ` --location $script:Location ` --subscription $script:SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if (-not $? -or !$rg) { Write-Host "Error creating resource group - $($errOut)." -ForegroundColor Red exit -1 } Write-Host "Resource group $($rg.id) created." -ForegroundColor Green } else { Write-Host "Resource group $($rg.id) exists." -ForegroundColor Green } Write-Host "Deploying resources to $($script:ResourceGroup)..." -ForegroundColor Cyan $azureDeployFile = Join-Path $script:ScriptDir "azuredeploy.json" & { az deployment group create ` --name $script:Name ` --resource-group $rg.Name ` --template-file $azureDeployFile ` --parameters "userPrincipalId=$(az ad signed-in-user show --query id -o tsv)" ` --subscription $script:SubscriptionId ` --only-show-errors --no-prompt --no-wait } | Out-Null if ($?) { az deployment group wait --created --interval 3 ` --name $script:Name ` --resource-group $rg.Name ` --subscription $script:SubscriptionId ` --only-show-errors } if (-not $?) { Write-Host "Error deploying resources." -ForegroundColor Red exit -1 } Write-Host "Deployment $($script:Name) completed." -ForegroundColor Green $errOut = $($deployment = & { az deployment group show ` --name $script:Name ` --resource-group $rg.Name ` --subscription $script:SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if (!$deployment.properties.outputs) { $deployment | ConvertTo-Json -Depth 10 | Out-Host Write-Host "Deployment $($script:Name) not found - $($errOut)." -ForegroundColor Red exit -1 } $rootDir = $scriptDir while (![string]::IsNullOrEmpty($rootDir)) { if (Test-Path -Path (Join-Path $rootDir "Industrial-IoT.sln") -PathType Leaf) { break } $rootDir = Split-Path $rootDir } $writeFile = $true $ENVVARS = Join-Path $rootDir ".env" if (-not $script:NoPrompt.IsPresent) { $writeFile = $false $prompt = "Save environment as $ENVVARS for local development? [y/n]" $reply = Read-Host -Prompt $prompt if ($reply -match "[yY]") { $writeFile = $true } } if ($writeFile) { if (Test-Path $ENVVARS) { if (-not $script:NoPrompt.IsPresent) { $prompt = "Overwrite existing .env file in $rootDir? [y/n]" if ($reply -match "[yY]") { Remove-Item $ENVVARS -Force } else { $writeFile = $false } } else { Remove-Item $ENVVARS -Force } } } Function Get-EnvironmentVariables() { Param( $deployment ) if (![string]::IsNullOrEmpty($script:ResourceGroup)) { Write-Output "PCS_RESOURCE_GROUP=$($script:ResourceGroup)" } if (![string]::IsNullOrEmpty($script:SubscriptionId)) { Write-Output "PCS_SUBSCRIPTION_ID=$($script:SubscriptionId)" } $var = $deployment.properties.outputs.tenantId.value if (![string]::IsNullOrEmpty($var)) { Write-Output "PCS_AUTH_TENANT=$($var)" } $var = $deployment.properties.outputs.iotHubConnString.value if (![string]::IsNullOrEmpty($var)) { Write-Output "PCS_IOTHUB_CONNSTRING=$($var)" } $var = $deployment.properties.outputs.dpsConnString.value if (![string]::IsNullOrEmpty($var)) { Write-Output "PCS_DPS_CONNSTRING=$($var)" } $var = $deployment.properties.outputs.dpsIdScope.value if (![string]::IsNullOrEmpty($var)) { Write-Output "PCS_DPS_IDSCOPE=$($var)" } } if ($writeFile) { Get-EnvironmentVariables $deployment | Out-File -Encoding ascii ` -FilePath $ENVVARS Write-Host Write-Host ".env file created in $rootDir." Write-Host Write-Warning "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" Write-Warning "!The file contains security keys to your Azure resources!" Write-Warning "! Safeguard the contents of this file, or delete it now !" Write-Warning "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" Write-Host } else { Get-EnvironmentVariables $deployment | Out-Default } ================================================ FILE: deploy/docker/build.cmd ================================================ @echo off setlocal set CMDLINE=--self-contained false /t:PublishContainer -r linux-x64 set PROJECT=../../src/Azure.IIoT.OpcUa.Publisher.Module/src/Azure.IIoT.OpcUa.Publisher.Module.csproj dotnet restore %PROJECT% -s https://api.nuget.org/v3/index.json dotnet publish %PROJECT% -c Release %CMDLINE% /p:ContainerImageTag=latest dotnet publish %PROJECT% -c Debug %CMDLINE% /p:ContainerImageTag=debug ================================================ FILE: deploy/docker/dapr/pubsub.yaml ================================================ apiVersion: dapr.io/v1alpha1 kind: Component metadata: name: redis-pubsub spec: type: pubsub.redis version: v1 metadata: - name: redisHost value: redis:6379 ================================================ FILE: deploy/docker/dapr/statestore.yaml ================================================ apiVersion: dapr.io/v1alpha1 kind: Component metadata: name: statestore spec: type: state.redis version: v1 metadata: - name: redisHost value: redis:6379 - name: redisPassword value: "" - name: actorStateStore value: "true" ================================================ FILE: deploy/docker/docker-compose.yaml ================================================ services: ############################ # OPC PLC Simulation ############################ opcplc: container_name: opcplc image: mcr.microsoft.com/iotedge/opc-plc:${OPC_PLC_TAG:-latest} ports: - "50000:50000" command: [ "--sph=True", "--spf=/shared/opcplc.json", "--pn=50000", "--alm=True", "--ses=True", "--ei=${EVENT_NODES:-100}", "--gn=${GUID_NODES:-100}", "--fn=${FAST_NODES:-4900}", "--sn=${SLOW_NODES:-4900}", "--aa=True" ] volumes: - shared:/shared:rw ############################ # OPC Publisher ############################ publisher: container_name: publisher image: mcr.microsoft.com/iotedge/opc-publisher:${OPC_PUBLISHER_TAG:-2.9} user: root ports: - "9071:80" - "9072:443" command: [ "-c", "--aa", "--bs=1", "--bi=0", "--di=60", "--cl=5", "--cto=30", "--sto=1200", "--rs", "--dm=True", "--cfa", "--lfm=syslog", "--pki=/shared/pki", "--npd=${NODES_PER_DATASET:-5000}" ] environment: PublishedNodesFile: /shared/opcplc.json ADDITIONAL_CONFIGURATION: /run/secrets/publisher-secrets secrets: - publisher-secrets volumes: - shared:/shared:rw volumes: shared: secrets: publisher-secrets: file: ./publisher_secrets.txt ================================================ FILE: deploy/docker/gcdump.ps1 ================================================ <# .SYNOPSIS Create gc dump files periodically .PARAMETER WaitSeconds The number of seconds to wait in between dumps #> param( [int] $WaitSeconds = 1, [string] $Path = "dumps" ) # start with monitor and dump gc Remove-Item -Path $Path -Recurse -Force -ErrorAction SilentlyContinue New-Item -ItemType Directory -Path $Path $StartTime = $(get-date) docker compose -f docker-compose.yaml -f with-monitor.yaml -f with-limits.yaml up -d $dumpIndex = 0 while ($true) { Start-Sleep -Seconds $WaitSeconds try { curl http://localhost:9084/gcdump -o $Path/dump$($dumpIndex).gcdump } catch { break } $dumpIndex++ } $elapsedTime = $(get-date) - $StartTime Write-Host "Ran for (hh:mm:ss) $($elapsedTime.ToString("hh\:mm\:ss"))" #docker compose -f docker-compose.yaml -f with-monitor.yaml -f with-limits.yaml down ================================================ FILE: deploy/docker/mosquitto/mosquitto.conf ================================================ # from https://mosquitto.org/man/mosquitto-conf-5.html allow_anonymous true listener 1883 persistence false #persistence_location /tmp/mosquitto/data #log_dest file /var/log/mosquitto/mosquitto.log log_dest stdout log_dest topic # If using syslog logging (not on Windows), messages will be logged to the # "daemon" facility by default. Use the log_facility option to choose which of # local0 to local7 to log to instead. The option value should be an integer # value, e.g. "log_facility 5" to use local5. #log_facility # Possible types are: debug, error, warning, notice, information, # none, subscribe, unsubscribe, websockets, all. # Note that debug type messages are for decoding the incoming/outgoing # network packets. They are not logged in "topics". log_type error log_type warning log_type notice log_type information # If set to true, client connection and disconnection messages will be included # in the log. connection_messages true # If set to true, add a timestamp value to each log message. log_timestamp true ================================================ FILE: deploy/docker/mosquitto/settings.json ================================================ { "ConnectionManager_connections": { "mosquitto": { "configVersion": 1, "certValidation": false, "clientId": "mqtt-explorer", "id": "6b3e0a76-c99d-464d-a74c-9c0d1c483edf", "name": "mosquitto", "encryption": false, "subscriptions": [ { "topic": "#", "qos": 0 }, { "topic": "$SYS/#", "qos": 0 } ], "type": "mqtt", "host": "mosquitto", "port": 1883, "protocol": "mqtt" } } } ================================================ FILE: deploy/docker/opentelemetry/collector.yaml ================================================ receivers: otlp: protocols: grpc: http: exporters: prometheus: endpoint: 0.0.0.0:8889 otlp: endpoint: tempo:4317 tls: insecure: true loki: endpoint: http://loki:3100/loki/api/v1/push format: json labels: resource: service.name: "service_name" service.instance.id: "service_instance_id" service: pipelines: metrics: receivers: [ otlp ] exporters: [ prometheus ] traces: receivers: [ otlp ] exporters: [ otlp ] logs: receivers: [ otlp ] exporters: [ loki ] ================================================ FILE: deploy/docker/opentelemetry/dashboards/opc-publisher.json ================================================ { "annotations": { "list": [ { "builtIn": 1, "datasource": "-- Grafana --", "enable": true, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", "name": "Annotations & Alerts", "target": { "limit": 100, "matchAny": false, "tags": [], "type": "dashboard" }, "type": "dashboard" } ] }, "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, "id": null, "links": [], "liveNow": false, "panels": [ { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": { "type": "prometheus", "uid": "PBFA97CFB590B2093" }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 9, "w": 12, "x": 0, "y": 0 }, "hiddenSeries": false, "id": 2, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "nullPointMode": "null", "options": { "alertThreshold": true }, "percentage": false, "pluginVersion": "8.3.3", "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "iiot_edge_publisher_messages{}", "interval": "", "legendFormat": "Messages sent", "refId": "A" } ], "thresholds": [], "timeRegions": [], "title": "Publisher - Messages ", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "mode": "time", "show": true, "values": [] }, "yaxes": [ { "format": "short", "logBase": 1, "show": true }, { "format": "short", "logBase": 1, "show": true } ], "yaxis": { "align": false } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": { "type": "prometheus", "uid": "PBFA97CFB590B2093" }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 0 }, "hiddenSeries": false, "id": 18, "legend": { "alignAsTable": false, "avg": true, "current": false, "max": true, "min": true, "rightSide": false, "show": true, "total": false, "values": true }, "lines": true, "linewidth": 1, "nullPointMode": "null", "options": { "alertThreshold": true }, "percentage": false, "pluginVersion": "8.3.3", "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "histogram_quantile(0.985, sum(rate(iiot_edge_publisher_messages_duration_bucket[5m])) by (le))", "interval": "", "legendFormat": "98.5th percentile", "refId": "C" }, { "expr": "histogram_quantile(0.95, sum(rate(iiot_edge_publisher_messages_duration_bucket[5m])) by (le))", "interval": "", "legendFormat": "95th percentile", "refId": "A" }, { "expr": "histogram_quantile(0.80, sum(rate(iiot_edge_publisher_messages_duration_bucket[5m])) by (le))", "interval": "", "legendFormat": "80th percentile", "refId": "B" } ], "thresholds": [], "timeRegions": [], "title": "Publisher - Messages send duration", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "transformations": [], "type": "graph", "xaxis": { "mode": "time", "show": true, "values": [] }, "yaxes": [ { "format": "short", "logBase": 1, "show": true }, { "format": "short", "logBase": 1, "show": true } ], "yaxis": { "align": false } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": { "type": "prometheus", "uid": "PBFA97CFB590B2093" }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 8 }, "hiddenSeries": false, "id": 20, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "nullPointMode": "null", "options": { "alertThreshold": true }, "percentage": false, "pluginVersion": "8.3.3", "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "iiot_edge_publisher_iothub_queue_dropped_count{}", "interval": "", "legendFormat": "", "refId": "A" } ], "thresholds": [], "timeRegions": [], "title": "Publisher - Dropped count", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "mode": "time", "show": true, "values": [] }, "yaxes": [ { "format": "short", "logBase": 1, "show": true }, { "format": "short", "logBase": 1, "show": true } ], "yaxis": { "align": false } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": { "type": "prometheus", "uid": "PBFA97CFB590B2093" }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 9 }, "hiddenSeries": false, "id": 22, "legend": { "avg": true, "current": false, "max": true, "min": true, "show": true, "total": false, "values": true }, "lines": true, "linewidth": 1, "nullPointMode": "null", "options": { "alertThreshold": true }, "percentage": false, "pluginVersion": "8.3.3", "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "datasource": { "type": "prometheus", "uid": "PBFA97CFB590B2093" }, "exemplar": true, "expr": "rate(process_runtime_dotnet_gc_heap_size{}[$__interval])", "interval": "", "legendFormat": "GC {{generation}}", "refId": "A" } ], "thresholds": [], "timeRegions": [], "title": "Publisher - Dotnet GC", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "mode": "time", "show": true, "values": [] }, "yaxes": [ { "format": "short", "logBase": 1, "show": true }, { "format": "short", "logBase": 1, "show": true } ], "yaxis": { "align": false } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": { "type": "prometheus", "uid": "PBFA97CFB590B2093" }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 16 }, "hiddenSeries": false, "id": 12, "legend": { "avg": true, "current": false, "max": true, "min": true, "show": true, "total": false, "values": true }, "lines": true, "linewidth": 1, "nullPointMode": "null", "options": { "alertThreshold": true }, "percentage": false, "pluginVersion": "8.3.3", "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "iiot_edge_publisher_chunk_size_average", "interval": "", "legendFormat": "Average chunk size", "refId": "A" } ], "thresholds": [], "timeRegions": [], "title": "Publisher - Chunk Size", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "mode": "time", "show": true, "values": [] }, "yaxes": [ { "format": "short", "logBase": 1, "show": true }, { "format": "short", "logBase": 1, "show": true } ], "yaxis": { "align": false } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": { "type": "prometheus", "uid": "PBFA97CFB590B2093" }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 24 }, "hiddenSeries": false, "id": 14, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "nullPointMode": "null", "options": { "alertThreshold": true }, "percentage": false, "pluginVersion": "8.3.3", "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "iiot_edge_publisher_data_changes_per_second{}", "interval": "", "legendFormat": "", "refId": "A" } ], "thresholds": [], "timeRegions": [], "title": "Publisher - Data Changes per Sec", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "mode": "time", "show": true, "values": [] }, "yaxes": [ { "format": "short", "logBase": 1, "show": true }, { "format": "short", "logBase": 1, "show": true } ], "yaxis": { "align": false } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": { "type": "prometheus", "uid": "PBFA97CFB590B2093" }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 32 }, "hiddenSeries": false, "id": 16, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "nullPointMode": "null", "options": { "alertThreshold": true }, "percentage": false, "pluginVersion": "8.3.3", "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "iiot_edge_publisher_iothub_queue_size{}", "interval": "", "legendFormat": "Queue Size", "refId": "A" } ], "thresholds": [], "timeRegions": [], "title": "Publisher - Queue Size", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "mode": "time", "show": true, "values": [] }, "yaxes": [ { "format": "short", "logBase": 1, "show": true }, { "format": "short", "logBase": 1, "show": true } ], "yaxis": { "align": false } } ], "refresh": false, "schemaVersion": 34, "style": "dark", "tags": [], "templating": { "list": [] }, "time": { "from": "now-6h", "to": "now" }, "timepicker": {}, "timezone": "", "title": "Publisher", "uid": "RbYIZhBMk", "version": 4, "weekStart": "" } ================================================ FILE: deploy/docker/opentelemetry/dashboards.yaml ================================================ apiVersion: 1 providers: - name: dashboards type: file options: path: /etc/dashboards foldersFromFilesStructure: true ================================================ FILE: deploy/docker/opentelemetry/datasources.yaml ================================================ apiVersion: 1 datasources: - name: Prometheus type: prometheus access: proxy orgId: 1 uid: PBFA97CFB590B2093 url: http://prometheus:9090 basicAuth: false isDefault: false version: 1 editable: false - name: Tempo type: tempo access: proxy orgId: 1 url: http://tempo:3200 basicAuth: false isDefault: false version: 1 editable: false apiVersion: 1 uid: tempo - name: Loki type: loki access: proxy orgId: 1 url: http://loki:3100 basicAuth: false isDefault: true version: 1 editable: false apiVersion: 1 jsonData: derivedFields: - datasourceUid: tempo matcherRegex: (?:"traceid"):"(\w+)" name: TraceID url: $${__value.raw} ================================================ FILE: deploy/docker/opentelemetry/prometheus.yml ================================================ global: scrape_interval: 5s # Set the scrape interval to every 5 seconds. Default is every 1 minute. evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute. # scrape_timeout is set to the global default (10s). alerting: alertmanagers: - static_configs: - targets: # - alertmanager:9093 scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['localhost:9090'] - job_name: 'collector' static_configs: - targets: ['collector:8889'] ================================================ FILE: deploy/docker/opentelemetry/tempo.yaml ================================================ server: http_listen_port: 3200 distributor: receivers: otlp: protocols: http: grpc: storage: trace: backend: local local: path: /tmp/tempo/blocks ================================================ FILE: deploy/docker/publisher_secrets.txt ================================================ ApiKey=myKey1 ================================================ FILE: deploy/docker/readme.md ================================================ # Deploy in docker compose > IMPORTANT: Docker compose based hosting is experimental and only supported on a best effort basis. ## Table Of Contents - [General usage](#general-usage) - [Running with Open Telemetry stack](#running-with-open-telemetry-stack) - [Running with dotnet-monitor](#running-with-dotnet-monitor) - [Running with Mosquitto MQTT broker](#running-with-mosquitto-mqtt-broker) - [Setting resource limits on OPC Publisher](#setting-resource-limits-on-opc-publisher) ## General usage Ensure you have docker compose installed. Run ```bash docker compose up -d ``` To start OPC Publisher and OPC PLC. If you want to build OPC Publisher images from the repo run ```cmd build ``` To stop run ```bash docker compose down -d ``` To connect to Azure IoT Hub set the `EdgeHubConnectionString` environment variable to a Azure IoT Hub device connection string. Such connection string can be obtained in the portal or through the AZ command line. > If you use a `.env` file to set the variable, remember to delete the file since the connection string contains secrets! You can run OPC Publisher with a couple of additional components to aid in development: - Use [Open Telemetry](#running-with-open-telemetry-stack) and track metrics. - Observe OPC Publisher under [dotnet monitor](#running-with-dotnet-monitor) - Run with [Mosquitto MQTT broker](#running-with-mosquitto-mqtt-broker) The different configurations can be mixed and matched. ### Running with Open Telemetry stack To run OPC Publisher with the Open Telemetry collector connected to Loki, Tempo, Prometheus and Grafana and observe metrics run ```bash docker compose -f docker-compose.yaml -f with-opentelemtry.yaml up -d ``` ### Running with dotnet-monitor To create dump files and performance traces of OPC Publisher you can attach dotnet monitor tool. ```bash docker compose -f docker-compose.yaml -f with-monitor.yaml up -d ``` ### Running with Mosquitto MQTT broker You can connect OPC Publisher with MQTT output to Mosquitto. The included configuration includes the OPC Foundation UA Cloud dashboard. ```bash docker compose -f docker-compose.yaml -f with-mosquitto.yaml up -d ``` Hint: Ensure that you keep the OPC PLC nodes configured to a minimum to show nice graphs. ## Setting resource limits on OPC Publisher You should set limits that are not aggressive and take the following runtime characteristics into account: - Number of sessions. Each session requires significant memory (10-20 MB depending on the size of the server) - Number of nodes. Each node has a cache of last value - Number of messages queued up for batching. - Size of the data per monitored item It is recommended to set a limit of 4gb. But you should monitor runtime usage in production to determined exact numbers. You can run the OPC Publisher with 50m limits under docker, which is not supported by either .net nor us. Nevertheless, the following docker compose configuration shows which settings you can set to run OPC Publisher container for several hours in this mode. ```bash docker compose -f docker-compose.yaml -f with-limits.yaml up -d ``` We use this mode to test for leaks over time. You an use the `gcdump.ps1` powershell script to start the same together with dotnet-monitor to periodically dump the GC and observe differences in memory use over time. This setup is certainly experimental because: - Running the above command uses the null transport sink, so no data is ever buffered, messages are just thrown away. The more that is buffered before sending the more memory is required. - Alpine images must be used if you want to run for more than 3 seconds with said limit. The official OPC Publisher images are based on Alpine, but the ones built from the repository do not. - We disable meta data loading which has significant memory overhead. But you might need it. - The publisher publishes 11 nodes with value changes every 1 second. There is no buffering enabled, the messages are immediately dropped after encoding. - The setup is continuously under GC pressure and a good chunk of CPU is used for garbage collection and compression. - Open Telemetry and Prometheus metrics are disabled as they consume a large amount of memory. - The .net GC is configured to be over aggressive which are not ideal for production scenarios. ================================================ FILE: deploy/docker/with-dapr.yaml ================================================ services: ############################ # OPC Publisher ############################ publisher: environment: DaprConnectionString: "PubSubComponent=redis-pubsub" ############################ # Dapr sidecar for publisher ############################ publisher-dapr: image: "daprio/daprd:edge" command: [ "./daprd", "-app-id", "publisher", "-placement-host-address", "placement:50006", "-components-path", "/components" ] volumes: - "./dapr:/components" depends_on: - publisher network_mode: "service:publisher" ############################ # Redis state store ############################ redis: container_name: redis hostname: redis image: "redis:alpine" ports: - "6379:6379" ############################ # Dapr placement service ############################ placement: image: "daprio/dapr" command: ["./placement", "-port", "50006"] ports: - "50006:50006" ############################ # Redis dashboard ############################ redis-commander: container_name: redis-commander hostname: redis-commander image: ghcr.io/joeferner/redis-commander:latest restart: always environment: - REDIS_HOSTS=local:redis:6379 ports: - "8081:8081" ================================================ FILE: deploy/docker/with-limits.yaml ================================================ services: ############################ # OPC PLC Simulation ############################ opcplc: command: [ "--sph", "--spf=/shared/opcplc.json", "--pn=50000", "--fn=1", "--sn=0", "--gn=0", "--nd", "--nn", "--ns", "--np", "--nv", "--aa" ] ############################ # OPC Publisher ############################ publisher: cpus: "0.5" mem_limit: 100m environment: EnableMetrics: false MaxNetworkMessageSendQueueSize: 4 DOTNET_ReadyToRun: 1 DOTNET_TieredPGO: 0 DOTNET_TC_QuickJitForLoops: 0 DOTNET_GCConserveMemory: 9 DOTNET_GCHeapHardLimitPercent: 30 ================================================ FILE: deploy/docker/with-localimage.yaml ================================================ services: publisher: image: iotedge/opc-publisher:${OPC_PUBLISHER_TAG:-latest} ================================================ FILE: deploy/docker/with-localvolume.yaml ================================================ services: publisher: environment: PublishedNodesFile: /shared/pn.json UseFileChangePolling: True volumes: - shared:/shared:rw volumes: shared: driver: local driver_opts: type: none device: c:\Shared o: bind ================================================ FILE: deploy/docker/with-monitor.yaml ================================================ services: ############################ # OPC PLC Simulation ############################ # opcplc: # environment: # DOTNET_DiagnosticPorts: /shared/diag/dotnet-monitor.sock ############################ # OPC Publisher ############################ publisher: environment: DOTNET_DiagnosticPorts: /shared/diag/dotnet-monitor.sock ############################ # dotnet-monitor ############################ monitor: container_name: monitor image: mcr.microsoft.com/dotnet/monitor:latest ports: - "9084:52325" command: [ "collect", "--no-auth" ] environment: DOTNETMONITOR_DiagnosticPort__ConnectionMode: listen DOTNETMONITOR_Storage__DefaultSharedPath: /shared/diag DOTNETMONITOR_Storage__DumpTempFolder: /shared/diag/tmp DOTNETMONITOR_Metrics__Endpoints: http://+:52325 DOTNETMONITOR_Urls: http://localhost:52323 volumes: - shared:/shared ================================================ FILE: deploy/docker/with-mosquitto.yaml ================================================ services: ############################ # OPC Publisher ############################ publisher: environment: MqttClientConnectionString: "HostName=mosquitto;Port=1883;UseTls=false;Protocol=v5" TelemetryTopicTemplate: "opcua/{Encoding}/data/{PublisherId}/{WriterGroup}/{DataSetWriter}" DataSetMetaDataTopicTemplate: "opcua/{Encoding}/metadata/{PublisherId}/{WriterGroup}/{DataSetWriter}" DiagnosticsTopicTemplate: "opcua/{Encoding}/data/{PublisherId}/{WriterGroup}/diagnostic" EventsTopicTemplate: "opcua/{Encoding}/status/{PublisherId}" DefaultDataSetRouting: "UseBrowseNames" MessagingMode: "SingleRawDataSet" PublisherId: Microsoft SiteId: Munich depends_on: - mosquitto ############################ # Mosquitto ############################ mosquitto: container_name: mosquitto image: "eclipse-mosquitto:latest" restart: unless-stopped ports: - "1883:1883" volumes: - mosquitto:/mosquitto/data - "./mosquitto/mosquitto.conf:/mosquitto/config/mosquitto.conf" ############################ # MQTT explorer ############################ mqtt-explorer: container_name: mqtt-explorer image: "smeagolworms4/mqtt-explorer:latest" ports: - "4000:4000" volumes: - "./mosquitto/settings.json:/mqtt-explorer/config/settings.json" depends_on: - mosquitto ############################ # UA Cloud dashboard ############################ dashboard: container_name: dashboard image: "ghcr.io/opcfoundation/ua-clouddashboard:main" ports: - "8000:80" environment: IGNORE_MISSING_METADATA: 1 USE_MQTT: 1 CLIENT_NAME: "dashboard" BROKER_NAME: "mosquitto" BROKER_PORT: "1883" TOPIC: Microsoft/factory1/# depends_on: - mosquitto volumes: mosquitto: ================================================ FILE: deploy/docker/with-opentelemetry.yaml ================================================ services: ############################ # OPC Publisher ############################ publisher: environment: OtlpCollectorEndpoint: "http://collector:4317" ############################ # OTEL Collector ############################ collector: image: otel/opentelemetry-collector-contrib:0.42.0 container_name: collector restart: unless-stopped command: [ "--config=/etc/collector.yaml" ] ports: - "4317:4317" - "8889:8889" volumes: - ./opentelemetry/collector.yaml:/etc/collector.yaml ############################ # Prometheus for collector ############################ prometheus: container_name: prometheus image: prom/prometheus:latest restart: unless-stopped volumes: - ./opentelemetry/prometheus.yml:/etc/prometheus/prometheus.yml ############################ # tempo for collector ############################ tempo: container_name: tempo image: grafana/tempo:latest restart: unless-stopped command: [ "-config.file=/etc/tempo.yaml" ] volumes: - ./opentelemetry/tempo.yaml:/etc/tempo.yaml ############################ # Loki for collector ############################ loki: container_name: loki image: grafana/loki:latest restart: unless-stopped command: [ "-config.file=/etc/loki/local-config.yaml" ] ############################ # Dashboarding ############################ grafana: container_name: grafana image: grafana/grafana:8.3.3 ports: - "3000:3000" volumes: - ./opentelemetry/datasources.yaml:/etc/grafana/provisioning/datasources/datasources.yaml - ./opentelemetry/dashboards.yaml:/etc/grafana/provisioning/dashboards/dashboards.yaml - ./opentelemetry/dashboards/:/etc/dashboards/ environment: - GF_AUTH_ANONYMOUS_ENABLED=true - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin - GF_AUTH_DISABLE_LOGIN_FORM=true depends_on: - prometheus - tempo - loki ================================================ FILE: deploy/docker/with-pcap-capture.yaml ================================================ services: ############################ # OPC PLC Simulation ############################ opcplc: command: [ "--sph=True", "--spf=/shared/pn.json", "--pn=50000", "--fn=8000", "--aa=True", "--ut=True" ] ############################ # Network capture ############################ pcap: container_name: pcap image: travelping/pcap cap_add: - NET_ADMIN network_mode: host volumes: - shared:/data:rw environment: IFACE: any FORMAT: pcapng MAXFILENUM: 10 MAXFILESIZE: 200 FILENAME: dump.pcap FILTER: "src or dst host 192.168.80.2" volumes: shared: ================================================ FILE: deploy/iotedge/.gitignore ================================================ eflow-setup/* *.log ================================================ FILE: deploy/iotedge/arm/TLSSettings.ps1 ================================================ #*************************************************************************************************************** # This script supports the TLS 1.2 everywhere project # It does the following: # * By default it disables TLS 1.O, TLS 1.1, SSLv2, SSLv3 and Enables TLS1.2 # * The CipherSuite order is set to the SDL approved version. # * The FIPS MinEncryptionLevel is set to 3. # * RC4 is disabled # * A log with a transcript of all actions taken is generated #*************************************************************************************************************** #************************************************ SCRIPT USAGE ************************************************ # .\TLSSettings.ps1 # -SetCipherOrder : Excellence/Min-Bar, default(Excellence), use B to set Min-Bar. (Min-Bar ordering prefers ciphers with smaller key sizes to improve performance over security) # -RebootIfRequired : $true/$false, default($true), use $false to disable auto-reboot (Settings won't take effect until a reboot is completed) # -EnableOlderTlsVersions : $true/$false, default($false), use $true to explicitly Enable TLS1.0, TLS1.1 #*************************************************************************************************************** #***************************TEAM CAN DETERMINE WHAT CIPHER SUITE ORDER IS CHOSEN ****************************** # Option B provides the min-bar configuration (small trade-off: performance over security) # Syntax: .\TLSSettings.ps1 -SetCipherOrder B # if no option is supplied, you will get the opportunity for excellence cipher order (small trade-off: security over performance) # Syntax: .\TLSSettings.ps1 #*************************************************************************************************************** param ( [string]$SetCipherOrder = " ", [bool]$RebootIfRequired = $true, [bool]$EnableOlderTlsVersions = $false ) #******************* FUNCTION THAT ACTUALLY UPDATES KEYS; WILL RETURN REBOOT FLAG IF CHANGES *********************** Function Set-CryptoSetting { param ( $regKeyName, $value, $valuedata, $valuetype ) $restart = $false # Check for existence of registry key, and create if it does not exist If (!(Test-Path -Path $regKeyName)) { New-Item $regKeyName | Out-Null } # Get data of registry value, or null if it does not exist $val = (Get-ItemProperty -Path $regKeyName -Name $value -ErrorAction SilentlyContinue).$value If ($val -eq $null) { # Value does not exist - create and set to desired value New-ItemProperty -Path $regKeyName -Name $value -Value $valuedata -PropertyType $valuetype | Out-Null $restart = $true } Else { # Value does exist - if not equal to desired value, change it If ($val -ne $valuedata) { Set-ItemProperty -Path $regKeyName -Name $value -Value $valuedata $restart = $true } } $restart } #*************************************************************************************************************** #******************* FUNCTION THAT DISABLES RC4 *********************** Function DisableRC4 { $restart = $false $subkeys = Get-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL" $ciphers = $subkeys.OpenSubKey("Ciphers", $true) Write-Log -Message "----- Checking the status of RC4 -----" -Logfile $logLocation -Severity Information $RC4 = $false if ($ciphers.SubKeyCount -eq 0) { $k1 = $ciphers.CreateSubKey("RC4 128/128") $k1.SetValue("Enabled", 0, [Microsoft.Win32.RegistryValueKind]::DWord) $restart = $true $k2 = $ciphers.CreateSubKey("RC4 64/128") $k2.SetValue("Enabled", 0, [Microsoft.Win32.RegistryValueKind]::DWord) $k3 = $ciphers.CreateSubKey("RC4 56/128") $k3.SetValue("Enabled", 0, [Microsoft.Win32.RegistryValueKind]::DWord) $k4 = $ciphers.CreateSubKey("RC4 40/128") $k4.SetValue("Enabled", 0, [Microsoft.Win32.RegistryValueKind]::DWord) Write-Log -Message "RC4 was disabled " -Logfile $logLocation -Severity Information $RC4 = $true } If ($RC4 -ne $true) { Write-Log -Message "There was no change for RC4 " -Logfile $logLocation -Severity Information } $restart } #*************************************************************************************************************** #******************* FUNCTION CHECKS FOR PROBLEMATIC FIPS SETTING AND FIXES IT *********************** Function Test-RegistryValueForFipsSettings { $restart = $false $fipsPath = @( "HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp", "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services", "HKLM:\System\CurrentControlSet\Control\Terminal Server\DefaultUserConfiguration" ) $fipsValue = "MinEncryptionLevel" foreach ($path in $fipsPath) { Write-Log -Message "Checking to see if $($path)\$fipsValue exists" -Logfile $logLocation -Severity Information $ErrorActionPreference = "stop" Try { $result = Get-ItemProperty -Path $path | Select-Object -ExpandProperty $fipsValue if ($result -eq 4) { set-itemproperty -Path $path -Name $fipsValue -value 3 Write-Log -Message "Regkey $($path)\$fipsValue was changed from value $result to a value of 3" -Logfile $logLocation -Severity Information $restart = $true } else { Write-Log -Message "Regkey $($path)\$fipsValue left at value $result" -Logfile $logLocation -Severity Information } } Catch [System.Management.Automation.ItemNotFoundException] { Write-Log -Message "Reg path $path was not found" -Logfile $logLocation -Severity Information } Catch [System.Management.Automation.PSArgumentException] { Write-Log -Message "Regkey $($path)\$fipsValue was not found" -Logfile $logLocation -Severity Information } Catch { Write-Log -Message "Error of type $($Error[0].Exception.GetType().FullName) trying to get $($path)\$fipsValue" -Logfile $logLocation -Severity Information } Finally {$ErrorActionPreference = "Continue" } } $restart } #*************************************************************************************************************** #********************************** FUNCTION THAT CREATE LOG DIRECTORY IF IT DOES NOT EXIST ******************************* function CreateLogDirectory { $TARGETDIR = "$env:HOMEDRIVE\Logs" if ( -Not (Test-Path -Path $TARGETDIR ) ) { New-Item -ItemType directory -Path $TARGETDIR | Out-Null } $TARGETDIR = $TARGETDIR + "\" + "TLSSettingsLogFile.csv" return $TARGETDIR } #*************************************************************************************************************** #********************************** FUNCTION THAT LOGS WHAT THE SCRIPT IS DOING ******************************* function Write-Log { [CmdletBinding()] param( [Parameter()] [ValidateNotNullOrEmpty()] [string]$Message, [Parameter()] [ValidateNotNullOrEmpty()] [string]$LogFile, [Parameter()] [ValidateNotNullOrEmpty()] [ValidateSet('Information', 'Warning', 'Error')] [string]$Severity = 'Information' ) [pscustomobject]@{ Time = (Get-Date -f g) Message = $Message Severity = $Severity } | ConvertTo-Csv -NoTypeInformation | Select-Object -Skip 1 | Out-File -Append -FilePath $LogFile } #********************************TLS CipherSuite Settings ******************************************* # CipherSuites for windows OS < 10 function Get-BaseCipherSuitesOlderWindows() { param ( [Parameter(Mandatory=$true, Position=0)][bool] $isExcellenceOrder ) $cipherorder = @() if ($isExcellenceOrder -eq $true) { $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384_P384" $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P256" $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384_P384" $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P256" $cipherorder += "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384" $cipherorder += "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256" } else { $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P256" $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384_P384" $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P256" $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384_P384" $cipherorder += "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256" $cipherorder += "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384" } # Add additional ciphers when EnableOlderTlsVersions flag is set to true if ($EnableOlderTlsVersions) { $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P256" $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P256" $cipherorder += "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P256" $cipherorder += "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P256" $cipherorder += "TLS_RSA_WITH_AES_256_GCM_SHA384" $cipherorder += "TLS_RSA_WITH_AES_128_GCM_SHA256" $cipherorder += "TLS_RSA_WITH_AES_256_CBC_SHA256" $cipherorder += "TLS_RSA_WITH_AES_128_CBC_SHA256" $cipherorder += "TLS_RSA_WITH_AES_256_CBC_SHA" $cipherorder += "TLS_RSA_WITH_AES_128_CBC_SHA" } return $cipherorder } # Ciphersuites needed for backwards compatibility with Firefox, Chrome # Server 2012 R2 doesn't support TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 # Both firefox and chrome negotiate ECDHE_RSA_AES_256_CBC_SHA1, Edge negotiates ECDHE_RSA_AES_256_CBC_SHA384 function Get-BrowserCompatCipherSuitesOlderWindows() { param ( [Parameter(Mandatory=$true, Position=0)][bool] $isExcellenceOrder ) $cipherorder = @() if ($isExcellenceOrder -eq $true) { $cipherorder += "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384" # (uses SHA-1) $cipherorder += "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P256" # (uses SHA-1) } else { $cipherorder += "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P256" # (uses SHA-1) $cipherorder += "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384" # (uses SHA-1) } return $cipherorder } # Ciphersuites for OS versions windows 10 and above function Get-BaseCipherSuitesWin10Above() { param ( [Parameter(Mandatory=$true, Position=0)][bool] $isExcellenceOrder ) $cipherorder = @() if ($isExcellenceOrder -eq $true) { $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" $cipherorder += "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" $cipherorder += "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384" $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256" $cipherorder += "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384" $cipherorder += "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" } else { $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" $cipherorder += "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" $cipherorder += "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256" $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384" $cipherorder += "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" $cipherorder += "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384" } # Add additional ciphers when EnableOlderTlsVersions flag is set to true if ($EnableOlderTlsVersions) { $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P256" $cipherorder += "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P256" $cipherorder += "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P256" $cipherorder += "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P256" $cipherorder += "TLS_RSA_WITH_AES_256_GCM_SHA384" $cipherorder += "TLS_RSA_WITH_AES_128_GCM_SHA256" $cipherorder += "TLS_RSA_WITH_AES_256_CBC_SHA256" $cipherorder += "TLS_RSA_WITH_AES_128_CBC_SHA256" $cipherorder += "TLS_RSA_WITH_AES_256_CBC_SHA" $cipherorder += "TLS_RSA_WITH_AES_128_CBC_SHA" } return $cipherorder } #******************************* TLS Version Settings **************************************************** function Get-RegKeyPathForTls12() { $regKeyPath = @( "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2", "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client", "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Server" ) return $regKeyPath } function Get-RegKeyPathForTls11() { $regKeyPath = @( "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1", "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Client", "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Server" ) return $regKeyPath } function Get-RegKeypathForTls10() { $regKeyPath = @( "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0", "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Client", "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server" ) return $regKeyPath } function Get-RegKeyPathForSsl30() { $regKeyPath = @( "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0", "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Client", "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Server" ) return $regKeyPath } function Get-RegKeyPathForSsl20() { $regKeyPath = @( "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0", "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Client", "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Server" ) return $regKeyPath } #Initialize reboot value to false $reboot = $false #*****************************Create the logfile if not does not exist*************************************** $logLocation = CreateLogDirectory #Start writing to the logs Write-Log -Message "========== Start of logging for a script execution ==========" -Logfile $logLocation -Severity Information $registryPathGoodGuys = @() $registryPathBadGuys = @() # we enable TLS 1.2 and disable SSL 2.0, 3.0 in any case $registryPathGoodGuys += Get-RegKeyPathForTls12 $registryPathBadGuys += Get-RegKeyPathForSsl20 $registryPathBadGuys += Get-RegKeyPathForSsl30 # add TLS 1.0/1.1 to good/bad depending on user's preference # default is adding TLS 1.0/1.1 to bad if ($EnableOlderTlsVersions) { $registryPathGoodGuys += Get-RegKeypathForTls10 $registryPathGoodGuys += Get-RegKeyPathForTls11 Write-Log -Message "Enabling TLS1.2, TLS1.1, TLS1.0. Disabling SSL3.0, SSL2.0" -Logfile $logLocation -Severity Information } else { $registryPathBadGuys += Get-RegKeypathForTls10 $registryPathBadGuys += Get-RegKeyPathForTls11 Write-Log -Message "Enabling TLS1.2. Disabling TLS1.1, TLS1.0, SSL3.0, SSL2.0" -Logfile $logLocation -Severity Information } Write-Log -Message "Check which registry keys exist already and which registry keys need to be created." -Logfile $logLocation -Severity Information #******************* CREATE THE REGISTRY KEYS IF THEY DON'T EXIST******************************** # Check for existence of GoodGuy registry keys, and create if they do not exist For ($i = 0; $i -lt $registryPathGoodGuys.Length; $i = $i + 1) { Write-Log -Message "Checking for existing of key: $($registryPathGoodGuys[$i]) " -Logfile $logLocation -Severity Information If (!(Test-Path -Path $registryPathGoodGuys[$i])) { New-Item $registryPathGoodGuys[$i] | Out-Null Write-Log -Message "Creating key: $($registryPathGoodGuys[$i]) " -Logfile $logLocation -Severity Information } } # Check for existence of BadGuy registry keys, and create if they do not exist For ($i = 0; $i -lt $registryPathBadGuys.Length; $i = $i + 1) { Write-Log -Message "Checking for existing of key: $($registryPathBadGuys[$i]) " -Logfile $logLocation -Severity Information If (!(Test-Path -Path $registryPathBadGuys[$i])) { Write-Log -Message "Creating key: $($registryPathBadGuys[$i]) " -Logfile $logLocation -Severity Information New-Item $registryPathBadGuys[$i] | Out-Null } } #******************* EXPLICITLY DISABLE SSLV2, SSLV3, TLS10 AND TLS11 ******************************** For ($i = 0; $i -lt $registryPathBadGuys.Length; $i = $i + 1) { if ($registryPathBadGuys[$i].Contains("Client") -Or $registryPathBadGuys[$i].Contains("Server")) { Write-Log -Message "Disabling this key: $($registryPathBadGuys[$i]) " -Logfile $logLocation -Severity Information $result = Set-CryptoSetting $registryPathBadGuys[$i].ToString() Enabled 0 DWord $result = Set-CryptoSetting $registryPathBadGuys[$i].ToString() DisabledByDefault 1 DWord $reboot = $reboot -or $result } } #********************************* EXPLICITLY Enable TLS12 **************************************** For ($i = 0; $i -lt $registryPathGoodGuys.Length; $i = $i + 1) { if ($registryPathGoodGuys[$i].Contains("Client") -Or $registryPathGoodGuys[$i].Contains("Server")) { Write-Log -Message "Enabling this key: $($registryPathGoodGuys[$i]) " -Logfile $logLocation -Severity Information $result = Set-CryptoSetting $registryPathGoodGuys[$i].ToString() Enabled 1 DWord $result = Set-CryptoSetting $registryPathGoodGuys[$i].ToString() DisabledByDefault 0 DWord $reboot = $reboot -or $result } } #************************************** Disable RC4 ************************************************ $result = DisableRC4 $reboot = $reboot -or $result #************************************** Set Cipher Suite Order ************************************** Write-Log -Message "----- starting ciphersuite order calculation -----" -Logfile $logLocation -Severity Information $configureExcellenceOrder = $true if ($SetCipherOrder.ToUpper() -eq "B") { $configureExcellenceOrder = $false Write-Host "The min bar cipher suite order was chosen." Write-Log -Message "The min bar cipher suite order was chosen." -Logfile $logLocation -Severity Information } else { Write-Host "The opportunity for excellence cipher suite order was chosen." Write-Log -Message "The opportunity for excellence cipher suite order was chosen." -Logfile $logLocation -Severity Information } $cipherlist = @() if ([Environment]::OSVersion.Version.Major -lt 10) { $cipherlist += Get-BaseCipherSuitesOlderWindows -isExcellenceOrder $configureExcellenceOrder $cipherlist += Get-BrowserCompatCipherSuitesOlderWindows -isExcellenceOrder $configureExcellenceOrder } else { $cipherlist += Get-BaseCipherSuitesWin10Above -isExcellenceOrder $configureExcellenceOrder } $cipherorder = [System.String]::Join(",", $cipherlist) Write-Host "Appropriate ciphersuite order : $cipherorder" Write-Log -Message "Appropriate ciphersuite order : $cipherorder" -Logfile $logLocation -Severity Information $CipherSuiteRegKey = "HKLM:\SOFTWARE\Policies\Microsoft\Cryptography\Configuration\SSL\00010002" if (!(Test-Path -Path $CipherSuiteRegKey)) { New-Item $CipherSuiteRegKey | Out-Null $reboot = $True Write-Log -Message "Creating key: $($CipherSuiteRegKey) " -Logfile $logLocation -Severity Information } $val = (Get-Item -Path $CipherSuiteRegKey -ErrorAction SilentlyContinue).GetValue("Functions", $null) Write-Log -Message "Previous cipher suite value: $val " -Logfile $logLocation -Severity Information Write-Log -Message "New cipher suite value : $cipherorder " -Logfile $logLocation -Severity Information if ($val -ne $cipherorder) { Write-Log -Message "Cipher suite order needs to be updated. " -Logfile $logLocation -Severity Information Write-Host "The original cipher suite order needs to be updated", `n, $val Set-ItemProperty -Path $CipherSuiteRegKey -Name Functions -Value $cipherorder Write-Log -Message "Cipher suite value was updated. " -Logfile $logLocation -Severity Information $reboot = $True } else { Write-Log -Message "Cipher suite order does not need to be updated. " -Logfile $logLocation -Severity Information Write-Log -Message "Cipher suite value was not updated as there was no change. " -Logfile $logLocation -Severity Information } #****************************** CHECK THE FIPS SETTING WHICH IMPACTS RDP'S ALLOWED CIPHERS ************************** #Check for FipsSettings Write-Log -Message "Checking to see if reg keys exist and if MinEncryptionLevel is set to 4" -Logfile $logLocation -Severity Information $result = Test-RegistryValueForFipsSettings $reboot = $reboot -or $result #************************************** REBOOT ************************************** if ($RebootIfRequired) { Write-Log -Message "You set the RebootIfRequired flag to true. If changes are made, the system will reboot " -Logfile $logLocation -Severity Information # If any settings were changed, reboot If ($reboot) { Write-Log -Message "Rebooting now... " -Logfile $logLocation -Severity Information Write-Log -Message "Using this command: shutdown.exe /r /t 5 /c ""Crypto settings changed"" /f /d p:2:4 " -Logfile $logLocation -Severity Information Write-Host "Rebooting now..." shutdown.exe /r /t 5 /c "Crypto settings changed" /f /d p:2:4 } Else { Write-Host "Nothing get updated." Write-Log -Message "Nothing get updated. " -Logfile $logLocation -Severity Information } } else { Write-Log -Message "You set the RebootIfRequired flag to false. If changes are made, the system will NOT reboot " -Logfile $logLocation -Severity Information Write-Log -Message "No changes will take effect until a reboot has been completed. " -Logfile $logLocation -Severity Information Write-Log -Message "Script does not include a reboot by design" -Logfile $logLocation -Severity Information } Write-Log -Message "========== End of logging for a script execution ==========" -Logfile $logLocation -Severity Information ================================================ FILE: deploy/iotedge/arm/default.yml ================================================ version: '3' services: opcserver0: image: mcr.microsoft.com/iotedge/opc-plc:latest restart: always command: --aa -pn 51200 -fn 50 -fr 1 -sn 250 -sr 10 ports: - "51200:51200" opcserver1: image: mcr.microsoft.com/iotedge/opc-plc:latest restart: always command: --aa -pn 51200 -fn 50 -fr 1 -sn 250 -sr 10 ports: - "51201:51201" opcserver2: image: mcr.microsoft.com/iotedge/opc-plc:latest restart: always command: --aa -pn 51200 -fn 50 -fr 1 -sn 250 -sr 10 ports: - "51202:51202" ================================================ FILE: deploy/iotedge/arm/dps-enroll.ps1 ================================================ <# .SYNOPSIS Creates a new enrollment in dps .DESCRIPTION Creates a new random enrollment in dps and returns enrollment information .PARAMETER dpsConnString The Azure Device Provisioning Service connection string .PARAMETER os The operating system to enroll #> param( [Parameter(Mandatory)] [string] $dpsConnString, [Parameter(Mandatory)] [string] $os ) #****************************************************************************** # Generate a random key #****************************************************************************** Function New-Key() { param( $length = 15 ) $digits = 48..57 $lcLetters = 65..90 $password = ` [char](Get-Random -Count 1 -InputObject ($lcLetters)) + ` [char](Get-Random -Count 1 -InputObject ($digits)) $password += get-random -Count ($length - 4) ` -InputObject ($digits + $lcLetters) |` ForEach-Object -begin { $aa = $null } -process { $aa += [char]$_ } -end { $aa } return $password } $registrationId = (New-Key).ToLower() # Parse connection string $hostName = $null $keyName = $null $key = $null $dpsConnString.Split(';') | ForEach-Object { $kv = $_ $x = "HostName=" if ($kv.StartsWith($x)) { $hostName = $kv.Replace($x, "").Trim() return } $x = "SharedAccessKeyName=" if ($kv.StartsWith($x)) { $keyName = $kv.Replace($x, "").Trim() } $x = "SharedAccessKey=" if ($kv.StartsWith($x)) { $key = $kv.Replace($x, "").Trim() return } } # Create sas token Add-Type -AssemblyName System.Web $audience = $hostName $expires=([DateTimeOffset]::Now.ToUnixTimeSeconds()) + 300 $signatureString=[System.Web.HttpUtility]::UrlEncode($audience)+ "`n" + [string]$expires $hmac = New-Object System.Security.Cryptography.HMACSHA256 $hmac.key = [Convert]::FromBase64String($key) $signature = $HMAC.ComputeHash([Text.Encoding]::UTF8.GetBytes($signatureString)) $signature = [Convert]::ToBase64String($signature) $sasToken = "SharedAccessSignature " ` + "sr=" + [System.Web.HttpUtility]::UrlEncode($audience) ` + "&sig=" + [System.Web.HttpUtility]::UrlEncode($signature) ` + "&se=" + $expires ` + "&skn=" + $keyName # Create enrollment $headers = @{"Authorization" = $sasToken; "Content-Type" = "application/json"} Add-Type -AssemblyName System.Net $deviceId = [System.Net.Dns]::GetHostName() $body = @{ attestation = @{ type = "symmetricKey" } deviceId = $deviceId initialTwin = @{ tags = @{ __type__ = "iiotedge" os = $os } } registrationId = $registrationId capabilities = @{ iotEdge = $true } } | ConvertTo-Json $uri = "https://$($hostName)/enrollments/$($registrationId)?api-version=2019-03-31" try { $response = $body | Invoke-RestMethod -Method Put -Headers $headers -Uri $uri return @{ registrationId = $response.registrationId primaryKey = $response.attestation.symmetricKey.primaryKey } } catch { Write-Host $_.Exception.Message return $null } ================================================ FILE: deploy/iotedge/arm/dsc-install.ps1 ================================================ Configuration InstallWindowsFeatures { Import-DscResource -ModuleName PsDesiredStateConfiguration Node "localhost" { LocalConfigurationManager { RebootNodeIfNeeded = $true ActionAfterReboot = 'ContinueConfiguration' } WindowsFeature Hyper-V { Name = "Hyper-V" Ensure = "Present" IncludeAllSubFeature = $true } Script VirtualMachinePlatform { SetScript = { Enable-WindowsOptionalFeature -Online -FeatureName "VirtualMachinePlatform" } TestScript = { (Get-WindowsOptionalFeature -Online -FeatureName "VirtualMachinePlatform").State -eq "Enabled" } GetScript = { @{ Result = Get-WindowsOptionalFeature -Online -FeatureName "VirtualMachinePlatform" } } } WindowsFeature Hyper-V-Management-Tools { Name = "RSAT-Hyper-V-Tools" Ensure = "Present" } Script Microsoft-Hyper-V-Management-PowerShell { SetScript = { Enable-WindowsOptionalFeature -Online -FeatureName "Microsoft-Hyper-V-Management-PowerShell" } TestScript = { (Get-WindowsOptionalFeature -Online -FeatureName "Microsoft-Hyper-V-Management-PowerShell").State -eq "Enabled" } GetScript = { @{ Result = Get-WindowsOptionalFeature -Online -FeatureName "Microsoft-Hyper-V-Management-PowerShell" } } } WindowsFeature DHCP { Name = "DHCP" Ensure = "Present" IncludeAllSubFeature = $true } WindowsFeature DHCP-Management-Tools { Name = "RSAT-DHCP" Ensure = "Present" } Script OpenSSH-Client-Capability { SetScript = { Add-WindowsCapability -Online -Name "OpenSSH.Client*" } TestScript = { (Get-WindowsCapability -Online -Name "OpenSSH.Client*").State -eq "Installed" } GetScript = { @{ Result = Get-WindowsCapability -Online -Name "OpenSSH.Client*" } } } } } ================================================ FILE: deploy/iotedge/arm/edge-setup.ps1 ================================================ <# .SYNOPSIS Configure IoT edge .DESCRIPTION Configure IoT edge on linux vm to use DPS. .PARAMETER dpsConnString The Dps connection string .PARAMETER idScope The Dps id scope #> param( [Parameter(Mandatory)] [string] $dpsConnString, [Parameter(Mandatory)] [string] $idScope ) $path = Split-Path $script:MyInvocation.MyCommand.Path $enrollPath = join-path $path dps-enroll.ps1 $file = "/etc/aziot/config.toml" if (Test-Path $file) { Write-Host "Already configured." return } Write-Host "Create new IoT Edge enrollment." $enrollment = & $enrollPath -dpsConnString $dpsConnString -os Linux Write-Host "Configure and initialize IoT Edge on Linux using enrollment information." # add dps setting $configtoml = "`nauto_reprovisioning_mode = `"OnErrorOnly`"" $configtoml += "`n" $configtoml += "`n[aziot_keys]" $configtoml += "`n" $configtoml += "`n[preloaded_keys]" $configtoml += "`n" $configtoml += "`n[cert_issuance]" $configtoml += "`n" $configtoml += "`n[preloaded_certs]" $configtoml += "`n" $configtoml += "`n[tpm]" $configtoml += "`n" $configtoml += "`n[agent]" $configtoml += "`nname = `"edgeAgent`"" $configtoml += "`ntype = `"docker`"" $configtoml += "`nimagePullPolicy = `"on-create`"" $configtoml += "`n" $configtoml += "`n[agent.config]" $configtoml += "`nimage = `"mcr.microsoft.com/azureiotedge-agent:1.4`"" $configtoml += "`n" $configtoml += "`n[agent.config.createOptions]" $configtoml += "`n" $configtoml += "`n[agent.env]" $configtoml += "`n" $configtoml += "`n[connect]" $configtoml += "`nworkload_uri = `"unix:///var/run/iotedge/workload.sock`"" $configtoml += "`nmanagement_uri = `"unix:///var/run/iotedge/mgmt.sock`"" $configtoml += "`n" $configtoml += "`n[listen]" $configtoml += "`nworkload_uri = `"fd://aziot-edged.workload.socket`"" $configtoml += "`nmanagement_uri = `"fd://aziot-edged.mgmt.socket`"" $configtoml += "`nmin_tls_version = `"tls1.0`"" $configtoml += "`n[watchdog]" $configtoml += "`nmax_retries = `"infinite`"" $configtoml += "`n" $configtoml += "`n[provisioning]" $configtoml += "`nsource = `"dps`"" $configtoml += "`nglobal_endpoint = `"https://global.azure-devices-provisioning.net`"" $configtoml += "`nid_scope = `"$($idScope)`"" $configtoml += "`n" $configtoml += "`n[provisioning.attestation]" $configtoml += "`nmethod = `"symmetric_key`"" $configtoml += "`nregistration_id = `"$($enrollment.registrationId)`"" $configtoml += "`nsymmetric_key = { value = `"$($enrollment.primaryKey)`" }" $configtoml += "`n" $configtoml | Out-Host $configtoml | Out-File $file -Force ================================================ FILE: deploy/iotedge/arm/edge-setup.sh ================================================ #!/bin/bash -e while [ "$#" -gt 0 ]; do case "$1" in --dpsConnString) dpsConnString="$2" ;; --idScope) idScope="$2" ;; esac shift done curdir="$( cd "$(dirname "$0")" ; pwd -P )" echo "In $curdir..." osversion=$(lsb_release -sr) if [[ -z "$osversion" ]]; then echo "Not an Ubuntu image..." exit 1 fi echo "Prepare Ubuntu $osversion..." DEBIAN_FRONTEND=noninteractive # install powershell and iotedge curl -O https://packages.microsoft.com/config/ubuntu/$osversion/packages-microsoft-prod.deb dpkg -i packages-microsoft-prod.deb apt-get update apt-get install -y --no-install-recommends powershell echo "Powershell installed." curl -o microsoft-prod.list https://packages.microsoft.com/config/ubuntu/$osversion/multiarch/prod.list cp ./microsoft-prod.list /etc/apt/sources.list.d/ curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg cp ./microsoft.gpg /etc/apt/trusted.gpg.d/ apt-get update apt-get install -y --no-install-recommends moby-engine moby-cli apt-get install -y --no-install-recommends aziot-edge defender-iot-micro-agent-edge echo "Iotedge installed." echo "Provisioning iotedge..." sleep 3 pwsh -File $curdir/edge-setup.ps1 -dpsConnString $dpsConnString -idScope $idScope echo "Iotedge provisioned." iotedge config apply ================================================ FILE: deploy/iotedge/arm/eflow-setup.ps1 ================================================ <# .SYNOPSIS Setup Eflow IoT edge .DESCRIPTION Setup Eflow IoT edge on windows vm to use DPS using DSC. .PARAMETER dpsConnString The Dps connection string .PARAMETER idScope The Dps id scope #> param( [Parameter(Mandatory)] [string] $dpsConnString, [Parameter(Mandatory)] [string] $idScope ) $eflowMsiUri = "https://aka.ms/AzEFLOWMSI_1_4_LTS_X64" $ErrorActionPreference = "Stop" $path = Split-Path $script:MyInvocation.MyCommand.Path $enrollPath = join-path $path dps-enroll.ps1 # Set-ExecutionPolicy -ExecutionPolicy AllSigned -Force Start-Transcript -path (join-path $path "edge-setup.log") [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force Install-Module Subnet -Force Write-Host "Download IoT Edge installer." $msiPath = $([io.Path]::Combine($env:TEMP, 'AzureIoTEdge.msi')) $ProgressPreference = 'SilentlyContinue' [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 Invoke-WebRequest $eflowMsiUri -OutFile $msiPath Write-Host "Run IoT Edge installer." Start-Process -Wait msiexec -ArgumentList "/i","$([io.Path]::Combine($env:TEMP, 'AzureIoTEdge.msi'))","/qn" Write-Host "Existing virtual switches:" Get-VmSwitch $switch = "NestedSwitch" Write-Host "Add virtual switch $($switch)..." New-VMSwitch -Name $switch -SwitchType Internal $switchAlias = "vEthernet ($($switch))" Write-Host "Network Adapter for '$($switchAlias)'" $itf = Get-NetAdapter -Name $switchAlias -ErrorAction SilentlyContinue while (!$itf) { Start-Sleep -Seconds 3 $itf = Get-NetAdapter -Name $switchAlias -ErrorAction SilentlyContinue } $itf | Out-Host $ifIndex = $itf.ifIndex $virtualSwitchIp = Get-NetIPAddress -AddressFamily IPv4 -InterfaceIndex $ifIndex -ErrorAction SilentlyContinue while (!$virtualSwitchIp) { Start-Sleep -Seconds 3 $virtualSwitchIp = Get-NetIPAddress -AddressFamily IPv4 -InterfaceIndex $ifIndex -ErrorAction SilentlyContinue } $virtualSwitchIp | Out-Host $subnet = Get-Subnet -IP $virtualSwitchIp.IPAddress -MaskBits 24 Write-Host "Create new ip address $($subnet.HostAddresses[0])/$($subnet.MaskBits)" New-NetIPAddress -IPAddress $subnet.HostAddresses[0] -PrefixLength $subnet.MaskBits -InterfaceIndex $ifIndex Write-Host "Create NAT $($subnet.NetworkAddress)}/$($subnet.MaskBits)" New-NetNat -Name $switch -InternalIPInterfaceAddressPrefix "$($subnet.NetworkAddress)/$($subnet.MaskBits)" Start-Sleep -Seconds 10 Write-Host "Configure DHCP" cmd.exe /c "netsh dhcp add securitygroups" Restart-Service dhcpserver # select a set of 100 addresses $startIp = $subnet.HostAddresses[100] $endIp = $subnet.HostAddresses[200] Write-Host "Add DHCP scope to $startIp - $endIp ..." Add-DhcpServerV4Scope -Name "AzureIoTEdgeScope" -StartRange $startIp -EndRange $endIp -SubnetMask $subnet.SubnetMask -State Active Set-DhcpServerV4OptionValue -ScopeID $subnet.NetworkAddress -Router $subnet.HostAddresses[0] Restart-service dhcpserver Write-Host "ipconfig:" ipconfig /all Write-Host "Deploy eflow with switch $($switch)." Deploy-Eflow -acceptEula Yes -acceptOptionalTelemetry Yes -vSwitchType "Internal" -vSwitchName $switch Get-EflowVmAddr Get-EflowVmEndpoint Get-EflowNetwork -vSwitchName $switch Write-Host "Create new IoT Edge enrollment in DPS." $enrollment = & $enrollPath -dpsConnString $dpsConnString -os Windows Write-Host "Provision eflow with DPS registration $($enrollment.registrationId) in DPS scope $($idScope)." Provision-EflowVm -provisioningType DpsSymmetricKey -scopeId $idScope -registrationId $enrollment.registrationId -symmKey $enrollment.primaryKey Write-Host "Eflow provisioned." Start-EflowVm Verify-EflowVm Write-Host "Eflow running." ================================================ FILE: deploy/iotedge/arm/simulation.sh ================================================ #!/bin/bash -ex ADMIN=$USER IMAGES_NAMESPACE= IMAGES_TAG= DOCKER_SERVER= DOCKER_USER= DOCKER_PASSWORD= DOCKER_COMPOSE_FILE="default.yml" DEBIAN_FRONTEND=noninteractive APP_PATH="/app" ENVVARS="${APP_PATH}/.env" # ======================================================================== while [ "$#" -gt 0 ]; do case "$1" in --admin) ADMIN="$2" ;; --name) DOCKER_COMPOSE_FILE="$2.yml" ;; --imagesNamespace) IMAGES_NAMESPACE="$2" ;; --imagesTag) IMAGES_TAG="$2" ;; --dockerServer) DOCKER_SERVER="$2" ;; --dockerUser) DOCKER_USER="$2" ;; --dockerPassword) DOCKER_PASSWORD="$2" ;; esac shift done # ======================================================================== apt-get update apt-get remove -y docker docker-engine docker.io apt-get autoremove -y apt-get install -y --no-install-recommends apt-transport-https ca-certificates curl software-properties-common openssl curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - apt-key fingerprint 0EBFCD88 add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" apt-get update apt-get install -y --no-install-recommends docker-ce usermod -aG docker $USER usermod -aG docker $ADMIN curl -L "https://github.com/docker/compose/releases/download/1.25.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose # ======================================================================== mkdir -p ${APP_PATH} chmod ugo+rX ${APP_PATH} cp -f ${DOCKER_COMPOSE_FILE} ${APP_PATH}/docker-compose.yml cp -f simulation.sh ${APP_PATH}/simulation.sh cd ${APP_PATH} touch docker-compose.yml && chmod 644 docker-compose.yml chmod 755 simulation.sh # ======================================================================== if [ -z "$DOCKER_SERVER" ]; then DOCKER_SERVER=mcr.microsoft.com fi if [ -z "$DOCKER_USER" ]; then echo -e "Deploying from public ${DOCKER_SERVER}." else echo -e "Logging into private registry at ${DOCKER_SERVER}." docker login -u $DOCKER_USER -p $DOCKER_PASSWORD $DOCKER_SERVER fi chown -R $ADMIN ${APP_PATH} cd ${APP_PATH} rm -f ${ENVVARS} if [ -z "$IMAGES_NAMESPACE" ]; then echo "REPOSITORY=${DOCKER_SERVER}" >> ${ENVVARS} else echo "REPOSITORY=${DOCKER_SERVER}/${IMAGES_NAMESPACE}" >> ${ENVVARS} fi if [ -z "$IMAGES_TAG" ]; then echo -e "Using latest version of images as defined in compose file." else echo "VERSION=${IMAGES_TAG}" >> ${ENVVARS} fi touch ${ENVVARS} && chmod 644 ${ENVVARS} docker-compose pull docker-compose up -d if [ $? -eq 0 ] then echo "Simulation started." exit 0 else echo "Failure: Cannot start simulation." >&2 exit 1 fi ================================================ FILE: deploy/iotedge/arm/testing.yml ================================================ version: '3' services: opcserver0: image: ${REPOSITORY:-mcr.microsoft.com}/iot/opc-ua-test-server:${VERSION:-latest} restart: always ports: - "51200:51200" environment: - SERVER_PORT=51200 opcserver1: image: ${REPOSITORY:-mcr.microsoft.com}/iot/opc-ua-test-server:${VERSION:-latest} restart: always ports: - "51201:51201" environment: - SERVER_PORT=51201 opcserver2: image: ${REPOSITORY:-mcr.microsoft.com}/iot/opc-ua-test-server:${VERSION:-latest} restart: always ports: - "51202:51202" environment: - SERVER_PORT=51202 opcserver3: image: ${REPOSITORY:-mcr.microsoft.com}/iot/opc-ua-test-server:${VERSION:-latest} restart: always ports: - "51203:51203" environment: - SERVER_PORT=51203 opcserver4: image: ${REPOSITORY:-mcr.microsoft.com}/iot/opc-ua-test-server:${VERSION:-latest} restart: always ports: - "51204:51204" environment: - SERVER_PORT=51204 opcserver5: image: ${REPOSITORY:-mcr.microsoft.com}/iot/opc-ua-test-server:${VERSION:-latest} restart: always ports: - "51205:51205" environment: - SERVER_PORT=51205 opcserver6: image: ${REPOSITORY:-mcr.microsoft.com}/iot/opc-ua-test-server:${VERSION:-latest} restart: always ports: - "51206:51206" environment: - SERVER_PORT=51206 opcserver7: image: ${REPOSITORY:-mcr.microsoft.com}/iot/opc-ua-test-server:${VERSION:-latest} restart: always ports: - "51207:51207" environment: - SERVER_PORT=51207 opcserver8: image: ${REPOSITORY:-mcr.microsoft.com}/iot/opc-ua-test-server:${VERSION:-latest} restart: always ports: - "51208:51208" environment: - SERVER_PORT=51208 opcserver9: image: ${REPOSITORY:-mcr.microsoft.com}/iot/opc-ua-test-server:${VERSION:-latest} restart: always ports: - "51209:51209" environment: - SERVER_PORT=51209 ================================================ FILE: deploy/iotedge/azuredeploy.json ================================================ { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "edgeName": { "type": "string", "metadata": { "description": "Name of the IoT Edge virtual machine." } }, "simulationProfile": { "type": "string", "defaultValue": "default", "allowedValues": [ "default", "testing" ], "metadata": { "description": "The name of the simulation docker-compose file on github without extension." } }, "dpsIdScope": { "type": "string", "metadata": { "description": "Device provisioning service id scope." } }, "dpsConnString": { "type": "secureString", "metadata": { "description": "Azure Device Provisioning service connection string." } }, "edgeOs": { "type": "string", "allowedValues": [ "linux", "windows" ], "defaultValue": "linux", "metadata": { "description": "Operating system to use for the virtual edge." } }, "edgeUsername": { "type": "string", "defaultValue": "", "metadata": { "description": "Username for the IoT Edge virtual machine." } }, "edgePassword": { "type": "securestring", "defaultValue": "", "metadata": { "description": "Password for the IoT Edge virtual machine." } }, "edgeVmSize": { "type": "string", "defaultValue": "", "metadata": { "description": "The size of the gateway VM to provision." } }, "numberOfSimulations": { "type": "int", "defaultValue": 1, "maxValue": 255, "minValue": 1, "metadata": { "description": "Number of simulated factories to deploy." } }, "simulationVmSize": { "type": "string", "defaultValue": "", "metadata": { "description": "The size of the simulation VM to provision." } }, "dockerServer": { "type": "string", "defaultValue": "mcr.microsoft.com", "metadata": { "description": "Specifies the endpoint of the Container Registry." } }, "dockerUser": { "type": "string", "defaultValue": "", "metadata": { "description": "Specifies the user to log into the Container Registry." } }, "dockerPassword": { "type": "secureString", "defaultValue": "", "metadata": { "description": "Specifies the password to the Container Registry." } }, "imagesNamespace": { "type": "string", "defaultValue": "", "metadata": { "description": "Specifies the namespace prefix for the images in the Container Registry." } }, "imagesTag": { "type": "string", "defaultValue": "latest", "metadata": { "description": "Specifies the image version tag to use for all images." } }, "templateUrl": { "type": "string", "defaultValue": "https://raw.githubusercontent.com/Azure/Industrial-IoT", "metadata": { "description": "The artifacts url from which to pull all linked templates. Default is official repository." } }, "branchName": { "type": "string", "defaultValue": "main", "metadata": { "description": "The branch from which to deploy deploy services and application. Default to main." } }, "managedIdentityResourceId": { "type": "string", "defaultValue": "", "metadata": { "description": "A user created managed identity to use for keyvault access. If not provided, above secret will be used to gain access to keyvault." } }, "tags": { "type": "object", "defaultValue": {}, "metadata": { "description": "Tags for Azure resources." } } }, "variables": { "instanceId": "[take(uniqueString(subscription().subscriptionId, resourceGroup().id, parameters('edgeName'), parameters('edgeOs')), 7)]", "vmPrefix": "[if(equals(parameters('edgeOs'), 'windows'), take(parameters('edgeName'), 6), parameters('edgeName'))]", "vmName": "[tolower(concat(variables('vmPrefix'), '-', variables('instanceId')))]", "vmResourceId": "[resourceId('Microsoft.Compute/virtualMachines', variables('vmName'))]", "nicResourceName": "[concat(variables('vmName'), '-nic')]", "nicResourceId": "[resourceId(resourceGroup().name,'Microsoft.Network/networkInterfaces', variables('nicResourceName'))]", "vnetResourceName": "[concat(variables('vmName'), '-vnet')]", "vnetResourceId": "[resourceId(resourceGroup().name,'Microsoft.Network/virtualNetworks', variables('vnetResourceName'))]", "nsgResourceName": "[concat(variables('vmName'), '-nsg')]", "nsgResourceId": "[resourceId(resourceGroup().name,'Microsoft.Network/virtualNetworks', variables('nsgResourceName'))]", "simulationName": "[concat(variables('vmName'), '-sim')]", "simulationResourceName": "[concat(deployment().name, '.edge')]", "identity": { "type": "UserAssigned", "userAssignedIdentities": { "[parameters('managedIdentityResourceId')]": { } } }, "windowsDscProperties": { "publisher": "Microsoft.Powershell", "type": "DSC", "typeHandlerVersion": "2.77", "autoUpgradeMinorVersion": true, "settings": { "wmfVersion": "latest", "configuration": { "url": "[concat(parameters('templateUrl'), '/', parameters('branchName'), '/deploy/iotedge/arm/dsc-install.zip')]", "script": "dsc-install.ps1", "function": "InstallWindowsFeatures" } } }, "windowsVmExtension": { "publisher": "Microsoft.Compute", "type": "CustomScriptExtension", "typeHandlerVersion": "1.9", "autoUpgradeMinorVersion": true, "settings": { "fileUris": [ "[concat(parameters('templateUrl'), '/', parameters('branchName'), '/deploy/iotedge/arm/dps-enroll.ps1')]", "[concat(parameters('templateUrl'), '/', parameters('branchName'), '/deploy/iotedge/arm/eflow-setup.ps1')]", "[concat(parameters('templateUrl'), '/', parameters('branchName'), '/deploy/iotedge/arm/TLSSettings.ps1')]" ] }, "protectedSettings": { "commandToExecute": "[concat('powershell -ExecutionPolicy Unrestricted -File ./eflow-setup.ps1 -idScope \"', parameters('dpsIdScope'), '\" -dpsConnString \"', parameters('dpsConnString'), '\"')]" } }, "windowsOsProfile": { "computerName": "[variables('vmName')]", "adminUsername": "[parameters('edgeUsername')]", "adminPassword": "[if(not(empty(parameters('edgePassword'))), parameters('edgePassword'), json('null'))]", "windowsConfiguration": { "enableAutomaticUpdates": true, "provisionVmAgent": true } }, "windowsVmSku": "Standard_D4s_v4", "windowsImage": { "publisher": "MicrosoftWindowsServer", "offer": "WindowsServer", "sku": "2022-Datacenter", "version": "latest" }, "linuxVmSku": "[if(not(empty(parameters('edgeVmSize'))), parameters('edgeVmSize'), 'Standard_B2s')]", "linuxImage": { "publisher": "Canonical", "offer": "UbuntuServer", "sku": "18.04-LTS", "version": "latest" }, "linuxOsProfile": { "computerName": "[variables('vmName')]", "adminUsername": "[parameters('edgeUsername')]", "adminPassword": "[if(not(empty(parameters('edgePassword'))), parameters('edgePassword'), json('null'))]" }, "linuxVmExtension": { "publisher": "Microsoft.Azure.Extensions", "type": "CustomScript", "typeHandlerVersion": "2.0", "autoUpgradeMinorVersion": true, "settings": { "fileUris": [ "[concat(parameters('templateUrl'), '/', parameters('branchName'), '/deploy/iotedge/arm/dps-enroll.ps1')]", "[concat(parameters('templateUrl'), '/', parameters('branchName'), '/deploy/iotedge/arm/edge-setup.ps1')]", "[concat(parameters('templateUrl'), '/', parameters('branchName'), '/deploy/iotedge/arm/edge-setup.sh')]" ] }, "protectedSettings": { "commandToExecute": "[concat('sudo bash edge-setup.sh --idScope \"', parameters('dpsIdScope'), '\" --dpsConnString \"', parameters('dpsConnString'), '\"')]" } }, "imagesTagOrLatest": "[if(empty(parameters('imagesTag')), 'latest', parameters('imagesTag'))]", "edgeVmSku": "[if(equals(parameters('edgeOs'), 'linux'), variables('linuxVmSku'), variables('windowsVmSku'))]", "simulationVmSku": "[if(not(empty(parameters('simulationVmSize'))), parameters('simulationVmSize'), variables('linuxVmSku'))]" }, "resources": [ { "comments": "Virtual edge network.", "name": "[variables('vnetResourceName')]", "type": "Microsoft.Network/virtualNetworks", "apiVersion": "2019-09-01", "location": "[resourceGroup().location]", "tags": "[parameters('tags')]", "properties": { "addressSpace": { "addressPrefixes": [ "10.1.8.0/22" ] }, "subnets": [ { "name": "vm-subnet", "properties": { "addressPrefix": "10.1.8.0/24" } } ] }, "dependsOn": [ ] }, { "comments": "Network interface for edge virtual machine to use.", "name": "[variables('nicResourceName')]", "type": "Microsoft.Network/networkInterfaces", "apiVersion": "2019-09-01", "location": "[resourceGroup().location]", "tags": "[parameters('tags')]", "properties": { "ipConfigurations": [ { "name": "ipconfig1", "properties": { "subnet": { "id": "[concat(variables('vnetResourceId'), '/subnets/', 'vm-subnet')]" }, "privateIPAllocationMethod": "Dynamic" } } ] }, "dependsOn": [ "[variables('vnetResourceId')]" ] }, { "type": "Microsoft.Network/networkSecurityGroups", "apiVersion": "2023-04-01", "name": "[variables('nsgResourceName')]", "location": "[resourceGroup().location]", "properties": { "securityRules": [ { "name": "default-allow-22", "id": "[resourceId('Microsoft.Network/networkSecurityGroups/securityRules', variables('nsgResourceName'), 'default-allow-22')]", "type": "Microsoft.Network/networkSecurityGroups/securityRules", "properties": { "protocol": "Tcp", "sourcePortRange": "*", "destinationPortRange": "22", "sourceAddressPrefix": "*", "destinationAddressPrefix": "*", "access": "Allow", "priority": 1000, "direction": "Inbound", "sourcePortRanges": [], "destinationPortRanges": [], "sourceAddressPrefixes": [], "destinationAddressPrefixes": [] } }, { "name": "DenyAnyHTTPSOutbound", "id": "[resourceId('Microsoft.Network/networkSecurityGroups/securityRules', variables('nsgResourceName'), 'DenyAnyHTTPSOutbound')]", "type": "Microsoft.Network/networkSecurityGroups/securityRules", "properties": { "protocol": "TCP", "sourcePortRange": "*", "destinationPortRange": "443", "sourceAddressPrefix": "*", "destinationAddressPrefix": "*", "access": "Deny", "priority": 1010, "direction": "Outbound", "sourcePortRanges": [], "destinationPortRanges": [], "sourceAddressPrefixes": [], "destinationAddressPrefixes": [] } }, { "name": "DenyAnyHTTPOutbound", "id": "[resourceId('Microsoft.Network/networkSecurityGroups/securityRules', variables('nsgResourceName'), 'DenyAnyHTTPOutbound')]", "type": "Microsoft.Network/networkSecurityGroups/securityRules", "properties": { "protocol": "TCP", "sourcePortRange": "*", "destinationPortRange": "80", "sourceAddressPrefix": "*", "destinationAddressPrefix": "*", "access": "Deny", "priority": 1020, "direction": "Outbound", "sourcePortRanges": [], "destinationPortRanges": [], "sourceAddressPrefixes": [], "destinationAddressPrefixes": [] } } ] } }, { "comments": "Virtual machine hosting the IoT Edge installation.", "name": "[variables('vmName')]", "type": "Microsoft.Compute/virtualMachines", "apiVersion": "2022-03-01", "location": "[resourceGroup().location]", "tags": "[parameters('tags')]", "identity": "[if(not(empty(parameters('managedIdentityResourceId'))), variables('identity'), '')]", "properties": { "hardwareProfile": { "vmSize": "[variables('edgeVmSku')]" }, "osProfile": "[if(equals(parameters('edgeOs'), 'linux'), variables('linuxOsProfile'), variables('windowsOsProfile'))]", "storageProfile": { "imageReference": "[if(equals(parameters('edgeOs'), 'linux'), variables('linuxImage'), variables('windowsImage'))]", "osDisk": { "createOption": "FromImage" } }, "networkProfile": { "networkInterfaces": [ { "id": "[variables('nicResourceId')]" } ] } }, "dependsOn": [ "[variables('nicResourceId')]" ] }, { "comments": "Install required windows features for eflow installtion on vm.", "type": "Microsoft.Compute/virtualMachines/extensions", "apiVersion": "2021-03-01", "condition": "[not(equals(parameters('edgeOs'), 'linux'))]", "name": "[concat(variables('vmName'), '/', 'InstallWindowsFeatures')]", "location": "[resourceGroup().location]", "properties": "[variables('windowsDscProperties')]", "dependsOn": [ "[variables('vmResourceId')]" ] }, { "comments": "One time script execution to install and onboard IoT Edge and deploy workloads", "type": "Microsoft.Compute/virtualMachines/extensions", "name": "[concat(variables('vmName'), '/', 'scriptextensions')]", "apiVersion": "2019-03-01", "location": "[resourceGroup().location]", "tags": "[parameters('tags')]", "properties": "[if (equals(parameters('edgeOs'), 'linux'), variables('linuxVmExtension'), variables('windowsVmExtension'))]", "dependsOn": [ "[variables('vmResourceId')]", "[resourceId('Microsoft.Compute/virtualMachines/extensions', variables('vmName'), 'InstallWindowsFeatures')]" ] }, { "comments": "Deploy factory network simulation.", "type": "Microsoft.Resources/deployments", "apiVersion": "2019-08-01", "name": "[concat(variables('simulationResourceName'), copyIndex())]", "condition": "[not(equals(parameters('numberOfSimulations'), 0))]", "copy": { "count": "[if(not(equals(0, parameters('numberOfSimulations'))), parameters('numberOfSimulations'), 1)]", "mode": "Parallel", "name": "simulationcopies" }, "properties": { "mode": "Incremental", "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "resources": [ { "comments": "Network interface for simulation virtual machine to use.", "name": "[concat(variables('simulationName'), copyIndex(), '-nic')]", "type": "Microsoft.Network/networkInterfaces", "apiVersion": "2019-09-01", "location": "[resourceGroup().location]", "tags": "[parameters('tags')]", "properties": { "ipConfigurations": [ { "name": "ipconfig1", "properties": { "subnet": { "id": "[concat(variables('vnetResourceId'), '/subnets/', 'vm-subnet')]" }, "privateIPAllocationMethod": "Dynamic" } } ] }, "dependsOn": [ ] }, { "comments": "VM running the simulation", "type": "Microsoft.Compute/virtualMachines", "name": "[concat(variables('simulationName'), copyIndex())]", "apiVersion": "2019-03-01", "location": "[resourceGroup().location]", "tags": "[parameters('tags')]", "properties": { "hardwareProfile": { "vmSize": "[variables('simulationVmSku')]" }, "osProfile": { "computerName": "[concat(variables('simulationName'), copyIndex())]", "adminUsername": "[parameters('edgeUsername')]", "adminPassword": "[if(not(empty(parameters('edgePassword'))), parameters('edgePassword'), json('null'))]" }, "storageProfile": { "imageReference": "[variables('linuxImage')]", "osDisk": { "createOption": "FromImage" } }, "networkProfile": { "networkInterfaces": [ { "id": "[resourceId('Microsoft.Network/networkInterfaces/', concat(variables('simulationName'), copyIndex(), '-nic'))]" } ] } }, "dependsOn": [ "[resourceId('Microsoft.Network/networkInterfaces/', concat(variables('simulationName'), copyIndex(), '-nic'))]" ] }, { "comments": "One time script execution to prepare the VM environment", "type": "Microsoft.Compute/virtualMachines/extensions", "name": "[concat(variables('simulationName'), copyIndex(), '/', 'scriptextensions')]", "apiVersion": "2019-03-01", "location": "[resourceGroup().location]", "tags": "[parameters('tags')]", "properties": { "publisher": "Microsoft.Azure.Extensions", "type": "CustomScript", "typeHandlerVersion": "2.0", "autoUpgradeMinorVersion": true, "settings": { "fileUris": [ "[concat(parameters('templateUrl'), '/', parameters('branchName'), '/deploy/iotedge/arm/simulation.sh')]", "[concat(parameters('templateUrl'), '/', parameters('branchName'), '/deploy/iotedge/arm/', parameters('simulationProfile'), '.yml')]" ] }, "protectedSettings": { "commandToExecute": "[concat('sudo bash simulation.sh ', ' --admin ', parameters('edgeUsername'), ' --name ', parameters('simulationProfile'), ' --imagesNamespace ', concat('\"', parameters('imagesNamespace'), '\"'), ' --imagesTag ', concat('\"', variables('imagesTagOrLatest'), '\"'), ' --dockerServer ', concat('\"', parameters('dockerServer'), '\"'), ' --dockerUser ', concat('\"', parameters('dockerUser'), '\"'), ' --dockerPassword ', concat('\"', parameters('dockerPassword'), '\"'))]" } }, "dependsOn": [ "[resourceId('Microsoft.Compute/virtualMachines/', concat(variables('simulationName'), copyIndex()))]" ] } ] } }, "dependsOn": [ "[variables('vnetResourceId')]" ] } ], "outputs": { "edgeUsername": { "type": "string", "value": "[parameters('edgeUsername')]" } } } ================================================ FILE: deploy/iotedge/azuredeploy.parameters.json ================================================ { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", "parameters": { "edgeName": { "value": "", "metadata": { "description": "The name of the IoT Edge device. This name must be unique within the IoT Hub.", "displayName": "IoT Edge Device Name" } }, "dpsIdScope": { "value": "", "metadata": { "description": "The ID scope for the Device Provisioning Service. This is used to identify the DPS instance.", "displayName": "DPS ID Scope" } }, "dpsConnString": { "value": "", "metadata": { "description": "The connection string for the Device Provisioning Service.", "displayName": "DPS Connection String" } } } } ================================================ FILE: deploy/iotedge/edgehubdev.cmd ================================================ @REM Copyright (c) Microsoft. All rights reserved. @REM Licensed under the MIT license. See LICENSE file in the project root for full license information. @setlocal EnableExtensions EnableDelayedExpansion @echo off set current-path=%~dp0 rem // remove trailing slash set current-path=%current-path:~0,-1% set build_root=%current-path%\.. set clean= set _config=Release set _verbose= :args-loop if "%1" equ "" goto :args-done if "%1" equ "--xtrace" goto :arg-trace if "%1" equ "-x" goto :arg-trace if "%1" equ "--debug" goto :arg-config if "%1" equ "-d" goto :arg-config if "%1" equ "--verbose" goto :arg-verbose if "%1" equ "-v" goto :arg-verbose if "%1" equ "--hub-name" goto :arg-hub-name if "%1" equ "-n" goto :arg-hub-name if "%1" equ "--tenant" goto :arg-tenant if "%1" equ "-t" goto :arg-tenant if "%1" equ "--subscription" goto :arg-subscription if "%1" equ "-s" goto :arg-subscription goto :usage :args-continue shift goto :args-loop :usage echo Run opc publisher in the edgehubdev context. echo Usage: run.cmd [options] echo options: echo -n --hub-name [name] specify hub name to install into (REQUIRED). echo -t --tenant [id] specify the tenant to log into. echo -s --subscription [id] set the subscription to use. echo -v --verbose Log output from edge hub dev. echo -d --debug build debug container images. echo -x --xtrace print a trace of each command. exit /b 1 :arg-trace echo on goto :args-continue :arg-config set _config=Debug goto :args-continue :arg-verbose set _verbose=-v goto :args-continue :arg-hub-name shift set _hub-name=%1 goto :args-continue :arg-subscription shift set _subscription=%1 goto :args-continue :arg-tenant shift set _tenant=-t %1 goto :args-continue :args-done goto :validate-args :validate-args if "%_hub-name%" == "" echo Missing required argument --hub-name. && goto :usage goto :main rem rem Check edgehubdev and docker rem :main call iotedgehubdev --version if !ERRORLEVEL! == 0 goto :docker echo First install iotedgehubdev per https://github.com/Azure/iotedgehubdev. goto :error :docker call docker ps -a > nul 2>&1 if !ERRORLEVEL! == 0 goto :login echo Docker is not running or installed. goto :error rem rem Login rem :login call az account show > nul 2>&1 if !ERRORLEVEL! == 0 goto :setsub echo Login to Azure... call az login %_tenant% goto :setsub :setsub if "%_subscription%" == "" goto :build call az account set -s %subscription% > nul 2>&1 if !ERRORLEVEL! == 0 goto :build echo Failed to change subscription! goto :error rem rem Build and publish rem :build set c=--self-contained false /t:PublishContainer /p:ContainerImageTag=latest set p=Azure.IIoT.OpcUa.Publisher.Module echo Building %_config% image... call dotnet publish ../../src/%p%/src/%p%.csproj -c %_config% %c% > nul 2>&1 if !ERRORLEVEL! == 0 goto :run echo Failed to build %_config% image! goto :error rem rem Setup and start rem :run set c= set c=%c% az iot hub connection-string show set c=%c% --hub-name %_hub-name% set c=%c% -o tsv --query connectionString for /f "tokens=*" %%a in ('%c%') do set _HUB_CS=%%a if !ERRORLEVEL! == 0 goto :check echo Failed to get connection string for iot hub %_hub-name%! goto :error :check for /f "tokens=*" %%a in ('hostname') do set hostname=%%a call az iot hub device-identity show -n %_hub-name% --device-id %hostname% > nul 2>&1 if not !ERRORLEVEL! == 0 goto :create set c= set c=%c% az iot hub device-identity connection-string show set c=%c% --hub-name %_hub-name% --device-id %hostname% set c=%c% -o tsv --query connectionString for /f "tokens=*" %%a in ('%c%') do set _EH_CS=%%a if !ERRORLEVEL! == 0 goto :setup :create echo Creating device %hostname% in %_hub-name%. call az iot edge devices create -n %_hub-name% --device id=%hostname% if !ERRORLEVEL! == 0 goto :check echo Failed to create edge device %hostname% in %_hub-name%. goto :error :setup call iotedgehubdev setup -c "%_EH_CS%" -i "%_HUB_CS%" -g %hostname% if !ERRORLEVEL! == 0 goto :start echo Failed to setup iotedgehubdev! goto :error :start if not exist %current-path%\edgehubdev.json goto :error call iotedgehubdev start -d %current-path%\edgehubdev.json %_verbose% if !ERRORLEVEL! == 0 goto :done echo Failed to start iotedgehubdev! goto :error :done goto :eof :error exit /b 1 ================================================ FILE: deploy/iotedge/edgehubdev.json ================================================ { "modulesContent": { "$edgeAgent": { "properties.desired": { "schemaVersion": "1.1", "runtime": { "type": "docker", "settings": { "minDockerVersion": "v1.25", "loggingOptions": "", "registryCredentials": {} } }, "systemModules": { "edgeAgent": { "type": "docker", "settings": { "image": "mcr.microsoft.com/azureiotedge-agent:1.4", "createOptions": "" } }, "edgeHub": { "type": "docker", "status": "running", "restartPolicy": "always", "settings": { "image": "mcr.microsoft.com/azureiotedge-hub:1.4", "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"5671/tcp\":[{\"HostPort\":\"5671\"}], \"8883/tcp\":[{\"HostPort\":\"8883\"}],\"443/tcp\":[{\"HostPort\":\"443\"}]}}}" }, "env": { "SslProtocols": { "value": "tls1.2" } } } }, "modules": { "publisher": { "version": "1.0", "type": "docker", "status": "running", "restartPolicy": "always", "settings": { "image": "iotedge/opc-publisher:latest", "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"443/tcp\":[{\"HostPort\":\"8081\"}]},\"CapDrop\":[\"CHOWN\",\"SETUID\"]},\"Hostname\":\"publisher\",\"User\":\"root\",\"Cmd\":[\"--strict\",\"--pki=/mount/pki\",\"--cf\",\"--mm=PubSub\",\"--me=Json\",\"--cl=5\",\"--sl\",\"--aa\"]}" } }, "opcplc": { "version": "1.0", "type": "docker", "status": "running", "restartPolicy": "always", "settings": { "image": "mcr.microsoft.com/iotedge/opc-plc:latest", "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"50000/tcp\":[{\"HostPort\":\"50000\"}]},\"CapDrop\":[\"CHOWN\",\"SETUID\"]},\"Hostname\":\"opcplc\",\"User\":\"root\",\"Cmd\":[\"--sph=True\",\"--pki=/mount/pki\",\"--pn=50000\",\"--alm=True\",\"--ses=True\",\"--sn=1000\",\"--fn=1000\",\"--aa=True\"]}" } } } } }, "$edgeHub": { "properties.desired": { "schemaVersion": "1.0", "routes": { "publisherToUpstream": "FROM /messages/modules/publisher/* INTO $upstream", "leafToUpstream": "FROM /messages/* WHERE NOT IS_DEFINED($connectionModuleId) INTO $upstream" }, "storeAndForwardConfiguration": { "timeToLiveSecs": 7200 } } } } } ================================================ FILE: deploy/iotedge/eflow-setup.json ================================================ { "$edgeAgent": { "properties.desired": { "schemaVersion": "1.1", "runtime": { "type": "docker", "settings": { "minDockerVersion": "v1.25", "loggingOptions": "", "registryCredentials": {} } }, "systemModules": { "edgeAgent": { "type": "docker", "settings": { "image": "mcr.microsoft.com/azureiotedge-agent:1.4", "createOptions": "" } }, "edgeHub": { "type": "docker", "status": "running", "restartPolicy": "always", "settings": { "image": "mcr.microsoft.com/azureiotedge-hub:1.4", "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"5671/tcp\":[{\"HostPort\":\"5671\"}], \"8883/tcp\":[{\"HostPort\":\"8883\"}],\"443/tcp\":[{\"HostPort\":\"443\"}]}}}" }, "env": { "SslProtocols": { "value": "tls1.2" } } } }, "modules": { "publisher": { "version": "1.0", "type": "docker", "status": "running", "restartPolicy": "always", "settings": { "image": "mcr.microsoft.com/iotedge/opc-publisher:latest", "createOptions": "{\"HostConfig\":{\"Binds\": [\"/tmp/host:/mount\"],\"PortBindings\":{\"443/tcp\":[{\"HostPort\":\"8081\"}]}},\"User\":\"root\",\"Cmd\":[\"--strict\",\"--pf=/mount/pn.json\",\"--pki=/mount/pki\",\"--cf\",\"--mm=PubSub\",\"--me=Json\",\"--cl=5\",\"--sl\",\"--aa\"]}" } }, "opcplc": { "version": "1.0", "type": "docker", "status": "running", "restartPolicy": "always", "settings": { "image": "mcr.microsoft.com/iotedge/opc-plc:latest", "createOptions": "{\"HostConfig\":{\"Binds\": [\"/tmp/host:/mount\"]},\"User\":\"root\",\"Cmd\":[\"--sph=True\",\"--spf=/mount/plc.json\",\"--vf1k=0\",\"--vfbs=0\",\"--gn=0\",\"--nd=True\",\"--np=True\",\"--nn=True\",\"--pn=50000\",\"--alm=True\",\"--ses=True\",\"--sn=10\",\"--fn=10\",\"--aa=True\"]}" } } } } }, "$edgeHub": { "properties.desired": { "schemaVersion": "1.1", "routes": { "publisherToUpstream": "FROM /messages/modules/publisher/* INTO $upstream" }, "storeAndForwardConfiguration": { "timeToLiveSecs": 7200 } } } } ================================================ FILE: deploy/iotedge/eflow-setup.ps1 ================================================ <# .SYNOPSIS Setup Eflow IoT edge (must run as admin) .DESCRIPTION Setup Eflow IoT edge on the device. This script will install the Azure IoT Edge runtime and deploy the Eflow IoT edge modules specified in the eflow-setup.json manifest. .NOTES DO NOT USE FOR PRODUCTION SYSTEMS. This script is intended for development and testing purposes only. .PARAMETER IotHubName The IoT Hub name. .PARAMETER TenantId The tenant id to use when logging into Azure. .PARAMETER SubscriptionId The subscription id to scope all activity to. .PARAMETER SharedFolderPath The shared folder path on the host system to mount into the guest. .PARAMETER ProvisioningOnly Only provision an existing eflow vm to an Azure IoT Hub. .PARAMETER DebuggingSupport Enable debugging support in eflow. .PARAMETER NoModules Do not deploy any modules. .PARAMETER NoCleanup Perform no cleanup after successfuly run. #> param( [string] $IotHubName, [string] $TenantId, [string] $SubscriptionId, [string] $SharedFolderPath, [switch] $ProvisioningOnly, [switch] $DebuggingSupport, [ValidateSet("Debug", "Release")] [string] $Configuration = "Debug", [switch] $NoModules, [switch] $NoCleanup ) #Requires -RunAsAdministrator $eflowMsiUri = "https://aka.ms/AzEFLOWMSI_1_4_LTS_X64" $ErrorActionPreference = "Stop" $path = Split-Path $script:MyInvocation.MyCommand.Path if ([string]::IsNullOrWhiteSpace($TenantId)) { $TenantId = $env:AZURE_TENANT_ID } $setupPath = Join-Path $path "eflow-setup" if (!(Test-Path $setupPath)) { New-Item -ItemType Directory -Path $setupPath | Out-Null } # Set-ExecutionPolicy -ExecutionPolicy AllSigned -Force Start-Transcript -path $(join-path $setupPath "eflow-setup.log") -Append Update-AzConfig -DisplayBreakingChangeWarning $false | Out-Null if (![string]::IsNullOrWhiteSpace($SubscriptionId)) { Update-AzConfig -DefaultSubscriptionForLogin $SubscriptionId } $azargs = @{} if (![string]::IsNullOrWhiteSpace($TenantId)) { $azargs.Add("-Tenant", $TenantId) } Connect-AzAccount @azargs # Find iot hub if ([string]::IsNullOrWhiteSpace($IotHubName)) { Write-Host "Please choose an Azure Iot Hub from the list (using its index):" $script:index = 0 $hubs = Get-AzIoTHub $hubs | Format-Table -AutoSize -Property ` @{Name = "Index"; Expression = { ($script:index++) } }, ` @{Name = "Hub"; Expression = { $_.Name } }` | Out-Host while ($true) { $option = Read-Host ">" try { if ([int]$option -ge 1 -and [int]$option -le $hubs.Count) { break } } catch { Write-Host "Invalid index '$($option)' provided." } Write-Host "Choose from the list using an index between 1 and $($hubs.Count)." } $hub = $hubs[$option - 1] } else { $hub = Get-AzIoTHub | Where-Object Name -eq $IotHubName if (!$hub) { throw "IoT Hub $IotHubName not found." } } if (!$ProvisioningOnly.IsPresent) { Write-Host "(Re-) Installing Azure IoT Edge eflow..." [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force | Out-Null Install-Module Subnet -Force | Out-Null $msiPath = Join-Path $setupPath "AzureIoTEdge.msi" if (!(Test-Path $msiPath)) { Write-Host "Downloading Azure IoT Edge eflow installer..." [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 Invoke-WebRequest $eflowMsiUri -OutFile $msiPath } # uninstall existing IoT Edge runtime if needed Start-Process -Wait msiexec -ArgumentList "/x", "$msiPath", "/qn" ` -ErrorAction SilentlyContinue | Out-Null Write-Host "Run Azure IoT Edge eflow installer." Start-Process -Wait msiexec -ArgumentList "/i", "$msiPath", "/qn" $mountPath = "C:\Shared" if (![string]::IsNullOrWhiteSpace($SharedFolderPath)) { $mountPath = $SharedFolderPath } $fullPath = Join-Path $mountPath "EFLOW-Shared" if (!(Test-Path $fullPath)) { New-Item -ItemType Directory -Path $fullPath | Out-Null } $sharedFolderConfig = @( @{ sharedFolderRoot = $mountPath sharedFolders = @( @{ hostFolderPath = "EFLOW-Shared" readOnly = $false targetFolderOnGuest = "/tmp/host" } ) } ) $sharedFoldersJsonPath = Join-Path $setupPath "SharedFolders.json" $sharedFolderConfig | ConvertTo-Json ` | Set-Content -Path $sharedFoldersJsonPath -Force -Encoding UTF8 Write-Host "Deploy Azure IoT Edge eflow with r/w folder $fullPath as /mount..." Deploy-Eflow -acceptEula Yes -acceptOptionalTelemetry Yes ` -cpuCount 2 -memoryInMB 4096 -vmLogSize Large ` -sharedFoldersJsonPath $sharedFoldersJsonPath if ($LASTEXITCODE -ne 0) { throw "Failed to deploy eflow." } Write-Host "Successfully installed and deployed eflow." Get-EflowNetwork | ConvertTo-Json Get-EflowVmAddr | ConvertTo-Json Get-EflowVmEndpoint | ConvertTo-Json #Get-EflowNetworkInterface #Get-EflowHostConfiguration #Get-EflowVmTelemetryOption #Get-EflowVmUserName #Get-EflowVmFeature #Get-EflowVmSharedFolder #Get-EflowVmTpmProvisioningInfo #Connect-EflowVm Connect to eflow vm } Write-Host "Provisioning eflow vm..." $ok = Verify-EflowVm if (!$ok) { throw "Eflow VM not created." } $vmName = Get-EflowVmName if (!$vmName) { throw "Failed to get eflow vm name." } Write-Host "Creating new IoT Edge device $vmName in $($hub.Name)..." $device = $hub | Get-AzIotHubDevice -DeviceId $vmName if (!$device.EdgeEnabled) { $hub | Remove-AzIotHubDevice -DeviceId $vmName $device = $null } if (!$device) { $device = $hub | Add-AzIotHubDevice -DeviceId $vmName ` -AuthMethod shared_private_key -Status Enabled -EdgeEnabled } $devConnString = $hub | Get-AzIotHubDeviceConnectionString -DeviceId $device.Id if (!$devConnString) { throw "Failed to get device connection string for $vmName." } if ([string]::IsNullOrWhiteSpace($devConnString.ConnectionString)) { throw "Device connection string for $vmName was empty." } Write-Host "Provision Azure IoT Edge Eflow VM $vmName..." # ensure started Start-EflowVm if ($DebuggingSupport.IsPresent) { Write-Host "Configuring debugging support in eflow..." Set-EflowVmFeature -feature Defender -enable:$False $ds = "/etc/systemd/system/docker.service" # Configure the EFLOW virtual machine Docker engine to accept external # connections, and add the appropriate firewall rules. Invoke-EflowVmCommand ` "sudo iptables -A INPUT -p tcp --dport 2375 -j ACCEPT" # Create a copy of the EFLOW VM _docker.service_ in the system folder. Invoke-EflowVmCommand ` "sudo cp /lib/systemd/system/docker.service $ds" # Replace the service execution line to listen for external connections. Invoke-EflowVmCommand ` "sudo sed -i 's/-H fd:\/\// -H fd:\/\/ -H tcp:\/\/0.0.0.0:2375/g' $ds" # Reload the EFLOW VM services configurations. Invoke-EflowVmCommand ` "sudo systemctl daemon-reload" # Reload the Docker engine service. Invoke-EflowVmCommand ` "sudo systemctl restart docker.service" # Check that the Docker engine is listening to external connections. Invoke-EflowVmCommand ` "sudo netstat -lntp | grep dockerd" $vmIp = Get-EflowVmAddr if (!$NoModules.IsPresent) { $containerRegistry = "$($hub.Name)acr" -replace '[^a-zA-Z0-9]' $registry = Get-AzContainerRegistry -Name $containerRegistry ` -ResourceGroupName $hub.Resourcegroup -ErrorAction SilentlyContinue if (!$registry) { Write-Host "Creating ACR $($containerRegistry) in $($hub.Location) ..." $registry = New-AzContainerRegistry -Name $containerRegistry ` -ResourceGroupName $hub.Resourcegroup -Location $hub.Location ` -EnableAdminUser -Sku Standard } Write-Host "Getting credentials from ACR $($containerRegistry) ..." $registrySecret = Get-AzContainerRegistryCredential -Name $containerRegistry ` -ResourceGroupName $hub.Resourcegroup $containerRegistryUsername = $registrySecret.Username $containerRegistryPassword = $registrySecret.Password $containerRegistryServer = $registry.LoginServer Connect-AzContainerRegistry -Name $containerRegistry $proj = $path | Split-Path | Split-Path | ` Join-Path -ChildPath "src" | ` Join-Path -ChildPath "Azure.IIoT.OpcUa.Publisher.Module" | ` Join-Path -ChildPath "src" | ` Join-Path -ChildPath "Azure.IIoT.OpcUa.Publisher.Module.csproj" Write-Host "Building and pushing debug module to $containerRegistry..." dotnet publish $proj -c $Configuration --self-contained false ` /t:PublishContainer /p:ContainerImageTag=$($Configuration.ToLower()) ` /p:ContainerRegistry=$containerRegistryServer $image = "$containerRegistryServer/iotedge/opc-publisher:$($Configuration.ToLower())" } Write-Host "Use 'docker -H tcp://$($vmIp[1]):2375' to connect to docker." Write-Host "Follow instructions in https://aka.ms/iotedge-eflow-debugging." } Provision-EflowVm -provisioningType ManualConnectionString ` -devConnString $devConnString.ConnectionString if ($LASTEXITCODE -ne 0) { throw "Failed to provision eflow vm $vmName." } Write-Host "Azure IoT Edge Eflow VM $vmName provisioned." # work around for ConvertFrom-Json not supporting -AsHashtable in PS 5.1 function ConvertPSObjectToHashtable { param ([Parameter(ValueFromPipeline)] $InputObject) if ($null -eq $InputObject) { return $null } if ($InputObject -is [System.Collections.IEnumerable] ` -and $InputObject -isnot [string]) { $collection = @( foreach ($object in $InputObject) { ConvertPSObjectToHashtable $object } ) Write-Output -NoEnumerate $collection } elseif ($InputObject -is [psobject]) { $hash = @{} foreach ($property in $InputObject.PSObject.Properties) { $hash[$property.Name] = ` (ConvertPSObjectToHashtable $property.Value).PSObject.BaseObject } $hash } else { $InputObject } } if (!$NoModules.IsPresent) { Write-Host "Deploying modules..." $modulesContentFile = Join-Path $path "eflow-setup.json" if (!(Test-Path $modulesContentFile)) { throw "Module content file $modulesContentFile not found." } $modulesContent = Get-Content -Raw -Path $modulesContentFile ` | ConvertFrom-Json | ConvertPSObjectToHashtable if ($DebuggingSupport.IsPresent) { # Update with our debug image $desired = $modulesContent["`$edgeAgent"]["properties.desired"] $desired["modules"]["publisher"]["settings"]["image"] = $image $desired["runtime"]["settings"]["registryCredentials"] = @{ $containerRegistry = @{ username = $containerRegistryUsername password = $containerRegistryPassword address = $containerRegistryServer } } # $modulesContent | ConvertTo-Json -Depth 10 } $hub | Set-AzIotHubEdgeModule -DeviceId $device.Id ` -ModulesContent $modulesContent | Out-Null } Start-Sleep -Seconds 10 $vm = Get-EflowVm if (!$vm) { throw "Failed to get eflow vm." } Write-Host "" Write-Host "Edge status:" Write-Host "========================================================" Write-Host "" $vm.EdgeRuntimeStatus.SystemCtlStatus | ForEach-Object { $_ | Out-Host } $vm.EdgeRuntimeStatus.ModuleList | ForEach-Object { $_ | Out-Host } Write-Host "" Write-Host "========================================================" Write-Host "" Write-Host "Azure IoT Edge eflow successfully installed!" Stop-Transcript if (!$NoCleanup.IsPresent) { Write-Host "Cleaning up..." Remove-Item -Path $setupPath -Force -Recurse -ErrorAction SilentlyContinue } else { Remove-Item -Path $(join-path $setupPath "eflow-setup.log") -Force ` -ErrorAction SilentlyContinue Get-EflowLogs -zipName $(Join-Path $setupPath "eflow-logs.zip") } ================================================ FILE: deploy/iotedge/readme.md ================================================ # IoT Edge deployment scripts > DO NOT USE FOR PRODUCTION SYSTEMS. The scripts here are intended for development and testing purposes only. ## Table Of Contents - [Deploy IoT Edge simulation to Azure](#deploy-iot-edge-simulation-to-azure) - [Azure IoT Edge EFLOW](#azure-iot-edge-eflow) - [Deploying a debug OPC Publisher](#deploying-a-debug-opc-publisher) - [IoTEdgeHubDev](#iotedgehubdev) - [Azure VM based IoT Edge](#azure-vm-based-iot-edge) ## Deploy IoT Edge simulation to Azure [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FIndustrial-IoT%2Fmain%2Fdeploy%2Fiotedge%2Fazuredeploy.json) ## Azure IoT Edge EFLOW To simplify setting up a development IoT Edge *on Windows*, run the `eflow-setup.ps1` script in a powershell session with Administrator privileges. The script was tested on Windows 11. It will install and configure [Azure IoT Edge EFLOW](https://learn.microsoft.com/azure/iot-edge/quickstart) against an existing IoT Hub. The IoT Hub name can be provided on the command line or selected. Use the `-Tenant` and `-Subscription` parameters of the powershell script to narrow which IoT Hub is selected. The script will also deploy an initial set up modules (OPC PLC and OPC Publisher) sharing a common shared volume. This setup is similar to the [docker-compose](../docker/), but not intended for production deployments. > Once the modules in `eflow-setup.json` are deployed the OPC Publisher will start to produce data that is uploaded to IoT Hub. This data can be significant and will accrue charges. Make sure to stop the VM when you do not need it anymore (Run `powershell Stop-EflowVm` - Administrator privileges needed). If you want to deploy a naked IOT Edge, re-provision the IoT Edge with the `-NoModules` switch. By default the shared folder is persisted on the Host OS in the `C:\Shared` folder. If you like to choose a different folder, supply the full path using the `-SharedFolderPath` script parameter. > The module PKI is persisted into the shared folder path. It contains keys which are secrets, make sure to guard access to the folder and properly delete the content when you are done with your development tasks. The script also provides an option to `-ProvisioningOnly` an existing EFLOW installation against a different IOT Hub. The device ID will always be the name of the VM, which should be set as `%HOSTNAME%_EFLOW`. You can find and manage this device in the portal or via AZ CLI. If the IoT Edge VM has been provisioned before, the script will prompt to confirm whether to re-provision the VM. ### Deploying a debug OPC Publisher The script can also set up the Azure IoT Edge EFLOW device to support [debugging](https://aka.ms/iotedge-eflow-debugging). Use the `-DebuggingSupport` parameter to do so. The script will print the docker command line that can be used from the host to access the docker daemon on the guest. Furthermore, if `-NoModules` is not set the script will build a debug container image of OPC Publisher from the current branch and deploy it into the IoT Edge instance instead of deploying the `latest` released container of OPC Publisher. The debug image can then be debugged using the previously mentioned instructions. ## IoTEdgeHubDev In addition the folder contains a script to run OPC Publisher and OPC PLC in `IoTEdgeHubDev` tool. The script does not install, and only configures the `IoTEdgeHubDev` tool. Also, volume mapping support on Windows is only provided in version 0.14.3 or higher. For this reason the deployed manifest has file mapping turned off. > Note: The IoTEdgeHubDev tool is in maintenance mode and is not supported anymore. It is recommended to use the earlier mechanism to create a simulation IoT Edge. ## Azure VM based IoT Edge If you are looking to setup a Azure IoT Edge VM in Azure (Windows or Linux), take a look at the deployment scripts [here](../scripts/). ================================================ FILE: deploy/kubernetes/cluster-setup.ps1 ================================================ <# .SYNOPSIS Setup local AIO cluster and connect to Arc (must run as admin) .DESCRIPTION Setup local AIO cluster and connect to Arc. This script installs the cluster type chosen and all other required dependencies and connect it to the cloud via Arc. Then it will install AIO on it. .NOTES DO NOT USE FOR PRODUCTION SYSTEMS. This script is intended for development and testing purposes only. .PARAMETER Name The name of the cluster .PARAMETER OpsInstanceName The name of the instance to create. Default is the same as the cluster name. .PARAMETER ClusterNamespace The namespace to create the instance in. Default is azure-iot-operations. .PARAMETER ResourceGroup The resource group to create or use for the cluster. Default is the same as the cluster name. .PARAMETER SharedFolderPath The shared folder path on the host system to mount into the guest. .PARAMETER TenantId The tenant id to use when logging into Azure. .PARAMETER SubscriptionId The subscription id to scope all activity to. .PARAMETER Location The location of the cluster. .PARAMETER ClusterType The type of cluster to create. Default is microk8s. .PARAMETER Connector Whether to deploy the OPC Publisher as connector. Official installs the official connector build, Local builds and deploys a local version. Debug the debug version. Default is Official. .PARAMETER OpsVersion The version of Azure IoT Operations to use. Default is the latest stable release. .PARAMETER OpsTrain The train to use if an OpsVersion is chosen. Default is integration. .PARAMETER Force Force reinstall. .PARAMETER OpsExtension (Internal) Use a preview version of the Azure IoT Operations extension to use. .PARAMETER DeployPlcSimulation Whether to deploy the PLC simulation. Default is false. .PARAMETER DeployTestSimulation Whether to deploy the Test simulation. Default is false. #> param( [string] [Parameter(Mandatory = $true)] $Name, [string] $OpsInstanceName, [string] $SharedFolderPath, [string] $ResourceGroup, [string] $TenantId, [string] $SubscriptionId, [string] $Location, [string] [ValidateSet( "kind", "minikube", "k3d", "microk8s" )] $ClusterType = "microk8s", [string] $ClusterNamespace, [string] [ValidateSet( "None", "Official", "Local", "Debug" )] $Connector = "Official", [string] $OpsVersion = $null, [string] [ValidateSet( "integration", "stable", "dev" )] $OpsTrain = "integration", [switch] $Force, [string] [ValidateSet( "preview", "installed", "stable" )] $OpsExtension = "stable", [switch] $DeployPlcSimulation, [switch] $DeployTestSimulation, [switch] $EnableNetworkDiscovery ) #Requires -RunAsAdministrator $ErrorActionPreference = 'Continue' if (![Environment]::Is64BitProcess) { Write-Host "Error: Run this in 64bit Powershell session" -ForegroundColor Red exit -1 } $scriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Path Import-Module $(Join-Path $(Join-Path $scriptDirectory "common") "cluster-utils.psm1") -Force # # Dump command line arguments # $forceReinstall = $script:Force.IsPresent if ($forceReinstall) { Write-Host "Force reinstall..." -ForegroundColor Yellow } if ([string]::IsNullOrWhiteSpace($script:ResourceGroup)) { $script:ResourceGroup = $script:Name } Write-Host "Using resource group $($script:ResourceGroup)..." -ForegroundColor Cyan if ([string]::IsNullOrWhiteSpace($script:TenantId)) { $script:TenantId = $env:AZURE_TENANT_ID } if (![string]::IsNullOrWhiteSpace($script:TenantId)) { Write-Host "Using tenant $($script:TenantId)..." -ForegroundColor Cyan } if ([string]::IsNullOrWhiteSpace($script:Location)) { $script:Location = "westus" } Write-Host "Using location $($script:Location)..." -ForegroundColor Cyan if ([string]::IsNullOrWhiteSpace($script:OpsInstanceName)) { $script:OpsInstanceName = $script:Name } Write-Host "Using instance name $($script:OpsInstanceName)..." -ForegroundColor Cyan if ([string]::IsNullOrWhiteSpace($script:ClusterNamespace)) { $script:ClusterNamespace = "azure-iot-operations" } else { Write-Host " ... with cluster namespace $($script:ClusterNamespace)..." ` -ForegroundColor Cyan } if (![string]::IsNullOrEmpty($script:OpsVersion)) { Write-Host " ... and version $($script:OpsVersion) ($($script:OpsTrain))..." ` -ForegroundColor Cyan } $mountPath = "C:\Shared" if (![string]::IsNullOrWhiteSpace($script:SharedFolderPath)) { $mountPath = $script:SharedFolderPath } #Write-Host "Using shared folder path $mountPath..." -ForegroundColor Cyan [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 # Install az cli if not installed or version is too old $installAz = $false try { $azVersion = (az version)[1].Split(":")[1].Split('"')[1] if ($azVersion -lt "2.74.0" -or !$azVersion) { $installAz = $true } } catch { $installAz = $true } if ($installAz) { Write-Host "Installing Az CLI..." -ForegroundColor Cyan Set-ExecutionPolicy Bypass -Scope Process -Force $ProgressPreference = 'SilentlyContinue' Invoke-WebRequest -Uri https://aka.ms/installazurecliwindowsx64 -OutFile .\AzureCLI.msi Start-Process msiexec.exe -Wait -ArgumentList '/I AzureCLI.msi /quiet' Remove-Item .\AzureCLI.msi } else { Write-Host "Az CLI version $azVersion found." -ForegroundColor Green } # # Log into azure # Write-Host "Log into Azure..." -ForegroundColor Cyan $loginParams = @( "--only-show-errors" ) if (![string]::IsNullOrWhiteSpace($script:TenantId)) { $loginParams += @("--tenant", $script:TenantId) } $session = (az login @loginParams) | ConvertFrom-Json if (-not $session) { Write-Host "Error: Login failed." -ForegroundColor Red exit -1 } if ([string]::IsNullOrWhiteSpace($SubscriptionId)) { $script:SubscriptionId = $session[0].id } if ([string]::IsNullOrWhiteSpace($TenantId)) { $script:TenantId = $session[0].tenantId } Write-Host "Ensuring all required dependencies are installed..." -ForegroundColor Cyan if ($script:ClusterType -ne "none" ` -and $script:ClusterType -ne "microk8s" ` -and $script:Connector -ne "None") { # check if docker is installed $errOut = $($docker = & { docker version --format json | ConvertFrom-Json }) 2>&1 if (-not $? -or !$docker.Server) { $docker | Out-Host Write-Host "Docker not installed or running : $errOut" -ForegroundColor Red exit -1 } Write-Host "Found $($docker.Server.Platform.Name)..." -ForegroundColor Green } # Install required az extensions az config set extension.dynamic_install_allow_preview=true --only-show-errors 2>&1 ` | Out-Null $ensureLatest = "false" $extensions = @( "connectedk8s", "k8s-configuration" ) if ($script:OpsExtension -eq "stable"){ $ensureLatest = "true" $extensions += "azure-iot-ops" } elseif ($script:OpsExtension -eq "preview") { $query = "[?!contains(name, '255')].{ Name:name, Date:properties.creationTime }" $iotOpsWhl = $($(az storage blob list ` --container-name drop --account-name azedgecli --auth-mode login ` --query "max_by($query, &Date)" ` --output json) | ConvertFrom-Json).Name if ((-not $?) -or (-not $iotOpsWhl)) { Write-Host "Error: No preview extension found." -ForegroundColor Red exit -1 } else { $extensionVersion = $iotOpsWhl ` -replace "azext_iot_ops-", "" -replace "-py3-none-any.whl", "" # Create a temp folder $temp = New-Item -ItemType Directory -Path ([System.IO.Path]::GetTempPath()) ` -Name ([System.Guid]::NewGuid().ToString()) ` | Select-Object -ExpandProperty FullName $ext = "$($temp)/$($iotOpsWhl)" $errOut = $($stdOut = & { az storage blob download ` --auth-mode login ` --container-name drop ` --account-name azedgecli ` --name $iotOpsWhl ` --file $ext }) 2>&1 if ($?) { $errOut = $($stdOut = & { az extension add --allow-preview true ` --upgrade --yes --source $ext }) 2>&1 } if (-not $?) { Write-Host "Error installing iot ops extension $($extensionVersion) - $($errOut)." ` -ForegroundColor Red exit -1 } Write-Host "Using iot ops extension version $($extensionVersion)..." ` -ForegroundColor Cyan } } foreach ($p in $extensions) { $errOut = $($stdOut = & { az extension add ` --upgrade ` --name $p ` --allow-preview true }) 2>&1 if (-not $?) { $stdOut | Out-Host Write-Host "Error installing az extension $p : $errOut" -ForegroundColor Red exit -1 } } if (![string]::IsNullOrWhiteSpace($SubscriptionId)) { az account set --subscription $SubscriptionId 2>&1 | Out-Null } # Install chocolatey $errOut = $($chocolateyVersion = & { choco --version }) 2>&1 if (!$chocolateyVersion -or $errOut) { Write-Host "Installing Chocolatey CLI..." -ForegroundColor Cyan [System.Net.ServicePointManager]::SecurityProtocol = ` [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 $scriptLoc = 'https://community.chocolatey.org/install.ps1' Invoke-Expression ((New-Object System.Net.WebClient).DownloadString($scriptLoc)) } # Install or upgrade kind, helm and kubectl, k9s and headlamp $packages = @( "kubernetes-cli", "kubernetes-helm", "headlamp", "k9s" ) if ($script:ClusterType -ne "none" -and $script:ClusterType -ne "microk8s") { $packages += $script:ClusterType } foreach ($p in $packages) { $errOut = $($stdOut = & { choco install $p --yes }) 2>&1 if (-not $?) { $stdOut | Out-Host Write-Host "Error during chocolatey install of $p : $errOut" -ForegroundColor Red exit -1 } $errOut = $($stdOut = & { choco upgrade $p --yes }) 2>&1 if (-not $?) { $stdOut | Out-Host Write-Host "Error during chocolatey upgrade of $p : $errOut" -ForegroundColor Red exit -1 } } # # Create the cluster # if ($script:ClusterType -eq "none") { Write-Host "Skipping cluster creation..." -ForegroundColor Green } elseif ($script:ClusterType -eq "microk8s") { # ensure multipass is running Start-Service -Name "Multipass" -ErrorAction SilentlyContinue | Out-Null $errOut = $($stdOut = & { microk8s status }) 2>&1 if (-not $?) { Write-Host "Error querying microk8s status - $($errOut)" -ForegroundColor Red exit -1 } if (!$forceReinstall -and $stdOut -match "microk8s is running") { Write-Host "Microk8s cluster is running..." -ForegroundColor Green } else { Write-Host "Resetting microk8s cluster..." -ForegroundColor Cyan microk8s uninstall microk8s install --cpu 4 --mem 12 microk8s start if (-not $?) { Write-Host "Error starting microk8s cluster - $($errOut)" -ForegroundColor Red exit -1 } Write-Host "Microk8s cluster started." -ForegroundColor Green } $features = @( "dns", "hostpath-storage", "ingress" ) foreach ($f in $features) { $errOut = $($stdOut = & { microk8s enable $f }) 2>&1 if (-not $?) { $stdOut | Out-Host Write-Host "Error enabling microk8s feature $f : $errOut" ` -ForegroundColor Red exit -1 } } $(microk8s config) | Out-File $env:USERPROFILE/.kube/config -Encoding utf8 -Force } elseif ($script:ClusterType -eq "k3d") { $errOut = $($table = & { k3d cluster list --no-headers } -split "`n") 2>&1 if (-not $?) { Write-Host "Error querying k3d clusters - $($errOut)" -ForegroundColor Red exit -1 } $clusters = $table | ForEach-Object { $($_ -split " ")[0].Trim() } if (($clusters -contains $script:Name) -and (!$forceReinstall)) { Write-Host "Cluster $script:Name exists..." -ForegroundColor Green } else { foreach ($cluster in $clusters) { if (!$forceReinstall) { if ($(Read-Host "Delete existing cluster $cluster? [Y/N]") -ne "Y") { continue } } Write-Host "Deleting existing cluster $cluster..." -ForegroundColor Yellow k3d cluster delete $cluster 2>&1 | Out-Null } Write-Host "Creating k3d cluster $script:Name..." -ForegroundColor Cyan $fullPath1 = Join-Path $mountPath "system" if (!(Test-Path $fullPath1)) { New-Item -ItemType Directory -Path $fullPath1 | Out-Null } $volumeMapping1 = "$($fullPath1):/var/lib/rancher/k3s/storage@all" $fullPath2 = Join-Path $mountPath "user" if (!(Test-Path $fullPath2)) { New-Item -ItemType Directory -Path $fullPath2 | Out-Null } $volumeMapping2 = "$($fullPath2):/storage/user@all" $env:K3D_FIX_MOUNTS = 1 k3d cluster create $script:Name ` --agents 3 ` --servers 1 ` --volume $volumeMapping1 ` --volume $volumeMapping2 ` --env K3D_FIX_MOUNTS=1@all ` --wait if (-not $?) { Write-Host "Error creating k3d cluster - $($errOut)" -ForegroundColor Red exit -1 } Write-Host "Cluster created..." -ForegroundColor Green } } elseif ($script:ClusterType -eq "minikube") { $errOut = $($clusters = & { minikube profile list -o json } | ConvertFrom-Json) 2>&1 if (($clusters.valid.Name -contains $script:Name) -and (!$forceReinstall)) { Write-Host "Valid minikube cluster $script:Name exists..." -ForegroundColor Green # Start the cluster if ($stat.Host -Contains "Stopped" -or $stat.APIServer -Contains "Stopped" -or $stat.Kubelet -Contains "Stopped") { Write-Host "Minikube cluster $script:Name stopped. Starting..." -ForegroundColor Cyan minikube start -p $script:Name if (-not $?) { Write-Host "Error starting minikube cluster." -ForegroundColor Red minikube logs --file=$($script:Name).log exit -1 } Write-Host "Minikube cluster $script:Name started." -ForegroundColor Green } else { Write-Host "Minikube cluster $script:Name running." -ForegroundColor Green } } elseif (-not $?) { Write-Host "Error querying minikube clusters - $($errOut)" -ForegroundColor Red exit -1 } else { if ($forceReinstall) { Write-Host "Deleting other clusters..." -ForegroundColor Yellow minikube delete --all --purge } elseif ($clusters.invalid.Name -contains $script:Name) { Write-Host "Delete bad minikube cluster $script:Name..." -ForegroundColor Yellow minikube delete -p $script:Name } Write-Host "Creating new minikube cluster $script:Name..." -ForegroundColor Cyan if (Get-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-All) { Write-Host "Hyper-V is enabled..." -ForegroundColor Green } else { Write-Host "Enabling Hyper-V..." -ForegroundColor Cyan $hv = Enable-WindowsOptionalFeature -Online ` -FeatureName Microsoft-Hyper-V-All if ($hv.RestartNeeded) { Write-Host "Restarting..." -ForegroundColor Yellow Restart-Computer -Force } } if (Get-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-Management-PowerShell) { Write-Host "Hyper-V commands installed..." -ForegroundColor Green } else { $hv = Enable-WindowsOptionalFeature -Online ` -FeatureName Microsoft-Hyper-V-Management-PowerShell if ($hv.RestartNeeded) { Write-Host "Restarting..." -ForegroundColor Yellow Restart-Computer -Force } } Start-Sleep -Seconds 5 & { minikube start -p $script:Name --cpus=4 --memory=8192 --nodes=4 --driver=hyperv } if (-not $?) { Write-Host "Error creating minikube cluster - $($errOut)" -ForegroundColor Red minikube logs --file=$($script:Name).log exit -1 } Write-Host "Cluster created..." -ForegroundColor Green } } elseif ($script:ClusterType -eq "kind") { $errOut = $($clusters = & { kind get clusters } -split "`n") 2>&1 if (($clusters -contains $script:Name) -and (!$forceReinstall)) { Write-Host "Cluster $script:Name exists..." -ForegroundColor Green } elseif (-not $?) { Write-Host "Error querying kind clusters - $($errOut)" -ForegroundColor Red exit -1 } else { foreach ($cluster in $clusters) { if (!$forceReinstall) { if ($(Read-Host "Delete existing cluster $cluster? [Y/N]") -ne "Y") { continue } } Write-Host "Deleting existing cluster $cluster..." -ForegroundColor Yellow kind delete cluster --name $cluster 2>&1 | Out-Null } Write-Host "Creating kind cluster $script:Name..." -ForegroundColor Cyan $clusterConfig = @" kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane extraPortMappings: - containerPort: 80 hostPort: 80 listenAddress: "127.0.0.1" - role: worker - role: worker - role: worker - role: worker - role: worker "@ $clusterConfig -replace "`r`n", "`n" ` | kind create cluster --name $script:Name --config - if (-not $?) { Write-Host "Error creating kind cluster - $($errOut)" -ForegroundColor Red exit -1 } Write-Host "Cluster created..." -ForegroundColor Green } } else { Write-Host "Error: Unsupported cluster type $script:ClusterType" -ForegroundColor Red exit -1 } $errOut = $($stdOut = & { kubectl get nodes }) 2>&1 if (-not $?) { $stdOut | Out-Host Write-Host "Cluster not reachable : $errOut" -ForegroundColor Red exit -1 } $stdOut | Out-Host Write-Host "Registering the required resource providers..." -ForegroundColor Cyan $resourceProviders = @( "Microsoft.ExtendedLocation", "Microsoft.Kubernetes", "Microsoft.KubernetesConfiguration", "Microsoft.EventGrid", "Microsoft.EventHub", "Microsoft.KeyVault", "Microsoft.Storage", "Microsoft.IoTOperations", "Microsoft.Kusto" ) foreach ($rp in $resourceProviders) { $errOut = $($obj = & { az provider show -n $rp ` --subscription $SubscriptionId ` --only-show-errors --output json | ConvertFrom-Json }) 2>&1 if (-not $?) { Write-Host "Error querying provider $rp : $errOut" -ForegroundColor Red exit -1 } if ($obj.registrationState -eq "Registered") { continue } $errOut = $($retVal = & { az provider register -n ` $rp --subscription $SubscriptionId --wait }) 2>&1 if (-not $?) { $retVal | Out-Host Write-Host "Error registering provider $rp : $errOut" -ForegroundColor Red exit -1 } Write-Host "Resource provider $rp registered." -ForegroundColor Green } $errOut = $($rg = & { az group show ` --name $script:ResourceGroup ` --subscription $script:SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if ($rg -and $forceReinstall) { Write-Host "Deleting existing resource group $($rg.Name)..." ` -ForegroundColor Yellow az group delete --name $rg.Name --subscription $SubscriptionId ` --only-show-errors --yes $rg = $null } if (!$rg) { Write-Host "Creating resource group $script:ResourceGroup..." -ForegroundColor Cyan $errOut = $($rg = & { az group create ` --name $script:ResourceGroup ` --location $script:Location ` --subscription $script:SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if (-not $? -or !$rg) { Write-Host "Error creating resource group - $($errOut)." -ForegroundColor Red exit -1 } Write-Host "Resource group $($rg.id) created." -ForegroundColor Green } else { Write-Host "Resource group $($rg.id) exists." -ForegroundColor Green } # # Create Azure resources # # Managed identity $errOut = $($mi = & { az identity show ` --name $script:Name ` --resource-group $($rg.Name) ` --subscription $SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if (!$mi) { Write-Host "Creating managed identity $script:Name..." -ForegroundColor Cyan $errOut = $($mi = & { az identity create ` --name $script:Name ` --location $Location ` --resource-group $($rg.Name) ` --subscription $SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if (-not $? -or !$mi) { Write-Host "Error creating managed identity - $($errOut)." -ForegroundColor Red exit -1 } Write-Host "Managed identity $($mi.id) created." -ForegroundColor Green } else { Write-Host "Managed identity $($mi.id) exists." -ForegroundColor Green } # Storage account $storageAccountName = $script:Name.Replace("-", "") $errOut = $($stg = & { az storage account show ` --name $storageAccountName ` --resource-group $($rg.Name) ` --subscription $SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if (!$stg) { Write-Host "Creating Storage account $storageAccountName" -ForegroundColor Cyan $errOut = $($stg = & { az storage account create ` --name $storageAccountName ` --location $Location ` --resource-group $($rg.Name) ` --allow-shared-key-access false ` --enable-hierarchical-namespace ` --subscription $SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if (-not $? -or !$stg) { Write-Host "Error creating storage $storageAccountName - $($errOut)." ` -ForegroundColor Red exit -1 } Write-Host "Storage account $($stg.id) created." -ForegroundColor Green } else { Write-Host "Storage account $($stg.id) exists." -ForegroundColor Green } # Event Hub namespace $eventHubNamespace = $script:Name $errOut = $($ehNs = & { az eventhubs namespace show ` --name $eventHubNamespace ` --resource-group $($rg.Name) ` --subscription $SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if (!$ehNs) { Write-Host "Creating Event Hub Namespace $($eventHubNamespace)..." -ForegroundColor Cyan $errOut = $($ehNs = & { az eventhubs namespace create ` --name $eventHubNamespace ` --resource-group $rg.Name ` --location $Location ` --disable-local-auth true ` --subscription $SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if (-not $? -or !$ehNs) { Write-Host "Error creating Event Hub Namespace $($eventHubNamespace) - $($errOut)." ` -ForegroundColor Red exit -1 } Write-Host "Event Hub Namespace $($ehNs.id) created." -ForegroundColor Green } else { Write-Host "Event Hub Namespace $($ehNs.id) exists." -ForegroundColor Green } # Keyvault $keyVaultName = $script:Name + "kv" $errOut = $($kv = & { az keyvault show ` --name $keyVaultName ` --subscription $SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if (!$kv) { Write-Host "Creating Key vault $keyVaultName" -ForegroundColor Cyan az keyvault purge --name $keyVaultName --location $Location ` --subscription $SubscriptionId 2>&1 | Out-Null $errOut = $($kv = & { az keyvault create ` --enable-rbac-authorization true ` --name $keyVaultName ` --resource-group $($rg.Name) ` --subscription $SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if (-not $? -or !$kv) { Write-Host "Error creating Azure Keyvault - $($errOut)." ` -ForegroundColor Red exit -1 } if ($kv.properties.enableSoftDelete) { az keyvault update ` --name $keyVaultName ` --enable-soft-delete false ` --resource-group $($rg.Name) ` --subscription $SubscriptionId 2>&1 | Out-Null } Write-Host "Key vault $($kv.id) created..." -ForegroundColor Green } else { Write-Host "Key vault $($kv.id) exists." -ForegroundColor Green } # # Assign roles to the managed identity # $roleAssignments = @( @("Contributor", $stg.id, $mi.principalId), @("Storage Blob Data Owner", $stg.id, $mi.principalId), @("Contributor", $ehNs.id, $mi.principalId), @("Contributor", $rg.id, $mi.principalId), @("Key Vault Administrator", $kv.id, $mi.principalId) ) foreach ($ra in $roleAssignments) { Write-Host "Assigning $($ra[0]) role to $($ra[2])..." -ForegroundColor Cyan $errOut = $($obj = & { az role assignment create ` --role $ra[0] ` --assignee-object-id $ra[2] ` --assignee-principal-type ServicePrincipal ` --scope $ra[1] | ConvertFrom-Json }) 2>&1 if (-not $?) { Write-Host "Error assigning role $($ra[0]) to $($ra[2]) : $errOut" ` -ForegroundColor Red #exit -1 } Write-Host "Role $($ra[0]) assigned to $($ra[2])." -ForegroundColor Green } # Azure IoT Operations schema registry $srName = "$($script:Name.ToLowerInvariant())sr" $errOut = $($sr = & { az iot ops schema registry show ` --name $srName ` --resource-group $($rg.Name) ` --subscription $SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if (!$sr) { Write-Host "Creating Azure IoT Operations schema registry..." -ForegroundColor Cyan $errOut = $($sr = & { az iot ops schema registry create ` --name $srName ` --resource-group $($rg.Name) ` --registry-namespace $srName ` --location $Location ` --sa-resource-id $stg.id ` --subscription $SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if (-not $? -or !$sr) { Write-Host "Error creating Azure IoT Operations schema registry - $($errOut)." ` -ForegroundColor Red exit -1 } Write-Host "Azure IoT Operations schema registry $($sr.id) created." ` -ForegroundColor Green } else { Write-Host "Azure IoT Operations schema registry $($sr.id) exists." ` -ForegroundColor Green } # # Connect the cluster to Arc # $errOut = $($cc = & { az connectedk8s show ` --name $script:Name ` --resource-group $($rg.Name) ` --subscription $SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if ($cc -and !$forceReinstall -and $cc.properties.connectivityStatus -ne "Offline") { Write-Host "Cluster $($cc.name) already connected to Arc." -ForegroundColor Green } else { if ($cc) { Write-Host "Disconnecting existing Arc cluster $($cc.name)..." ` -ForegroundColor Yellow az connectedk8s delete --only-show-errors ` --name $cc.name ` --resource-group $($rg.Name) ` --subscription $SubscriptionId ` --yes 2>&1 | Out-Null if (-not $?) { Write-Host "Error: disconnecting cluster $($cc.name) from Arc failed." ` -ForegroundColor Red exit -1 } } Write-Host "Connecting cluster to Arc in $($rg.Name)..." -ForegroundColor Cyan az connectedk8s connect --only-show-errors ` --name $script:Name ` --resource-group $($rg.Name) ` --subscription $SubscriptionId ` --correlation-id "d009f5dd-dba8-4ac7-bac9-b54ef3a6671a" 2>&1 | Out-Host if (-not $?) { Write-Host "Error: connecting cluster $($script:Name) to Arc failed." -ForegroundColor Red exit -1 } $errOut = $($cc = & { az connectedk8s show ` --name $script:Name ` --resource-group $($rg.Name) ` --subscription $SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 Write-Host "Cluster $($cc.name) connected to Arc." -ForegroundColor Green } # enable custom location feature $errOut = $($objectId = & { az ad sp show ` --id bc313c14-388c-4e7d-a58e-70017303ee3b --query id -o tsv }) 2>&1 Write-Host "Enabling custom location feature for cluster $script:Name..." -ForegroundColor Cyan az connectedk8s enable-features ` --name $cc.name ` --resource-group $rg.Name ` --subscription $SubscriptionId ` --custom-locations-oid $objectId ` --features cluster-connect custom-locations ` --only-show-errors if (-not $?) { Write-Host "Error: Failed to enable custom location feature." -ForegroundColor Red exit -1 } # enable workload identity if ($cc.securityProfile.workloadIdentity.enabled -and $cc.oidcIssuerProfile.enabled){ Write-Host "Workload identity already enabled for cluster $script:Name." -ForegroundColor Green } else { Write-Host "Enabling workload identity for cluster $script:Name..." -ForegroundColor Cyan az connectedk8s update ` --name $cc.name ` --resource-group $rg.Name ` --subscription $SubscriptionId ` --auto-upgrade true ` --enable-oidc-issuer ` --enable-workload-identity ` --only-show-errors if (-not $?) { Write-Host "Error: Failed to enable workload identity." -ForegroundColor Red exit -1 } Write-Host "Workload identity enabled for cluster $script:Name." -ForegroundColor Green } # Validate we have a connected cluster while ($true) { $errOut = $($cc = & { az connectedk8s show ` --name $script:Name ` --resource-group $($rg.Name) ` --subscription $SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if ($cc.properties.connectivityStatus -eq "Connected") { Write-Host "Cluster $($cc.name) connected to Arc." -ForegroundColor Green break } Write-Host "Waiting for cluster $($cc.name) to connect - $($cc.properties.connectivityStatus)..." ` -ForegroundColor Yellow Start-Sleep -Seconds 10 } # # Create adr namespace # $adrNsResource = "/subscriptions/$($SubscriptionId)" $adrNsResource = "$($adrNsResource)/resourceGroups/$($rg.Name)" $adrNsResource = "$($adrNsResource)/providers/Microsoft.DeviceRegistry/namespaces/$($script:Name)" $errOut = $($ns = & { az rest --method get ` --url "$($adrNsResource)?api-version=2025-10-01" ` --headers "Content-Type=application/json" } | ConvertFrom-Json) 2>&1 if (!$ns -or !$ns.id) { $body = @{ location = $Location identity = @{ type = "SystemAssigned" } properties = @{} } | ConvertTo-Json -Depth 100 $tempFile = New-TemporaryFile $body | Out-File -FilePath $tempFile -Encoding utf8 -Force Write-Host "Creating ADR namespace $adrNsResource..." -ForegroundColor Cyan $errOut = $($ns = & { az rest --method put ` --url "$($adrNsResource)?api-version=2025-10-01" ` --headers "Content-Type=application/json" ` --body @$tempFile } | ConvertFrom-Json) 2>&1 if (-not $?) { Write-Host "Error: Failed to create ADR namespace $($adrNsResource) - $($errOut)." ` -ForegroundColor Red Remove-Item $tempFile -Force exit -1 } Remove-Item $tempFile -Force Write-Host "ADR namespace $($ns.id) created." -ForegroundColor Green } else { Write-Host "ADR namespace $($ns.id) exists." -ForegroundColor Green } # # Create Azure IoT Operations instance # $errOut = $($iotOps = & { az iot ops show ` --resource-group $rg.Name ` --name $script:OpsInstanceName ` --subscription $SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if ($iotOps) { # first check cluster extension is deployed on the cluster and if not reset the instance $queryVersion = "[?scope.cluster.releaseNamespace == '$($script:ClusterNamespace)'" $queryVersion = "$($queryVersion) && extensionType == 'microsoft.iotoperations'" $queryVersion = "$($queryVersion) ].{ version:currentVersion, train:releaseTrain }" $currentVersion = $(az k8s-extension list ` --cluster-name $script:Name --cluster-type connectedClusters ` --resource-group $rg.Name ` --query $queryVersion --output json) | ConvertFrom-Json if (!$currentVersion) { Write-Host "No Azure IoT Operations extension found on cluster $script:Name. Resetting." ` - ForegroundColor Yellow az iot ops delete --name $iotOps.name --cluster $script:Name --yes --only-show-errors ` --resource-group $rg.Name --subscription $SubscriptionId ` if (-not $?) { Write-Host "Error removing Azure IoT Operations instance from cluster $script:Name." ` -ForegroundColor Red exit -1 } Write-Host "Azure IoT Operations instance removed from cluster $script:Name." ` -ForegroundColor Green $iotOps = $null $currentVersion = $null } else { Write-Host "Azure IoT Operations instance found with $($currentVersion.Version)." ` -ForegroundColor Green } } if (!$iotOps) { Write-Host "Initializing cluster $script:Name for deployment of Azure IoT operations..." ` -ForegroundColor Cyan $iotOpsInit = @( "init", ` "--cluster", $script:Name, ` "--resource-group", $rg.Name, ` "--subscription", $SubscriptionId, ` "--ensure-latest", $ensureLatest, ` "--only-show-errors" ) & az iot ops $iotOpsInit if (-not $?) { Write-Host "Error initializing cluster $script:Name for Azure IoT Operations." ` -ForegroundColor Red exit -1 } Write-Host "Cluster ready for Azure IoT Operations deployment..." ` -ForegroundColor Green Write-Host "Creating the Azure IoT Operations instance $($script:OpsInstanceName)..." ` -ForegroundColor Cyan $iotOpsCreate = @( "create", ` "--cluster", $script:Name, ` "--resource-group", $rg.Name, ` "--subscription", $SubscriptionId, ` "--cluster-namespace", $script:ClusterNamespace, ` "--name", $script:OpsInstanceName, ` "--location", $Location, ` "--sr-resource-id", $sr.id, ` "--ns-resource-id", $ns.id, ` "--add-insecure-listener", "true", ` "--only-show-errors" ) if ($script:OpsVersion) { $iotOpsCreate += "--ops-train", $script:OpsTrain $iotOpsCreate += "--ops-version", $script:OpsVersion } & az iot ops $iotOpsCreate if (-not $?) { & az iot ops $iotOpsCreate if (-not $?) { Write-Host "Error creating Azure IoT Operations instance - $($errOut)." ` -ForegroundColor Red exit -1 } } Write-Host "Enabling Azure IoT Operations resource sync..." ` -ForegroundColor Cyan $errOut = $(az iot ops rsync enable ` --resource-group $($rg.Name) ` --instance $script:OpsInstanceName ` --subscription $SubscriptionId ` --only-show-errors) 2>&1 if (-not $?) { Write-Host "Error enabling Azure IoT Operations resource sync - $($errOut)." ` -ForegroundColor Red exit -1 } Write-Host "Azure IoT Operations resource sync enabled." ` -ForegroundColor Green $errOut = $($iotOps = & { az iot ops show ` --resource-group $($rg.Name) ` --name $script:OpsInstanceName ` --subscription $SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if (-not $iotOps) { Write-Host "Error retrieving created Azure IoT Operations instance - $($errOut)." ` -ForegroundColor Red exit -1 } Write-Host "Azure IoT Operations instance $($iotOps.id) created." ` -ForegroundColor Green } else { # check if we need to upgrade the cluster extension $upgrade = $true if ($script:OpsVersion -and $currentVersion.Version -ge $script:OpsVersion) { $upgrade = $false if ($script:OpsTrain -and $script:OpsTrain -ne $currentVersion.Train) { $upgrade = $true } } if ($upgrade) { Write-Host "Upgrading Azure IoT Operations $($iotOps.id) $($currentVersion.Version)..." ` -ForegroundColor Cyan $iotOpsUpgrade = @( "upgrade", ` "--name", $iotOps.name, ` "--resource-group", $rg.Name, ` "--subscription", $SubscriptionId, ` "--only-show-errors", "--yes" ) if ($script:OpsVersion) { $iotOpsUpgrade += "--ops-train", $script:OpsTrain $iotOpsUpgrade += "--ops-version", $script:OpsVersion } & az iot ops $iotOpsUpgrade if (-not $?) { Write-Host "Error upgrading Azure IoT Operations instance - $($errOut)." ` -ForegroundColor Red exit -1 } Write-Host "Azure IoT Operations $($iotOps.id) upgraded ..." ` -ForegroundColor Green } else { Write-Host "Azure IoT Operations $($iotOps.id) at version $($currentVersion.Version)." ` -ForegroundColor Green } } $errOut = $($mia = & { az iot ops identity show ` --name $iotOps.name ` --resource-group $($rg.Name) ` --subscription $SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if (!$mia -or $mia.type -ne "UserAssigned") { Write-Host "Assign managed identity $($mi.id) to instance $($iotOps.id)..." ` -ForegroundColor Cyan $errOut = $($mia = & { az iot ops identity assign ` --name $iotOps.name ` --resource-group $($rg.Name) ` --subscription $SubscriptionId ` --mi-user-assigned $mi.id ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if (-not $? -or !$mia) { Write-Host "Error assigning managed identity to instance - $($errOut)." ` -ForegroundColor Red exit -1 } Write-Host "Managed identity $($mi.id) assigned to instance $($iotOps.id)." ` -ForegroundColor Green } else { Write-Host "Managed identity $($mi.id) already assigned to $($iotOps.id)." ` -ForegroundColor Green } $errOut = $($ss = & { az iot ops secretsync list ` --instance $iotOps.name ` --resource-group $($rg.Name) ` --subscription $SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if (!$ss) { Write-Host "Enabling secret sync with $($kv.id) for instance $($iotOps.id)..." ` -ForegroundColor Cyan $errOut = $($ss = & { az iot ops secretsync enable ` --instance $iotOps.name ` --kv-resource-id $kv.id ` --resource-group $rg.Name ` --subscription $SubscriptionId ` --mi-user-assigned $mi.id ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if (-not $? -or !$ss) { Write-Host "Error enabling secret sync for instance - $($errOut)." ` -ForegroundColor Red exit -1 } Write-Host "Secret sync with $($kv.id) enabled for $($iotOps.id)." ` -ForegroundColor Green } else { Write-Host "Secret sync with $($kv.id) already enabled in $($iotOps.id)." ` -ForegroundColor Green } $eventHubEndpointName = "eventhub-endpoint" $errOut = $($eh = & { az iot ops dataflow endpoint show ` --instance $iotOps.name ` --name $eventHubEndpointName ` --resource-group $rg.Name ` --subscription $SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if (!$eh) { Write-Host "Creating Event Hub endpoint $($eventHubEndpointName) in $($iotOps.id)..." ` -ForegroundColor Cyan $errOut = $($eh = & { az iot ops dataflow endpoint create eventhub ` --name $eventHubEndpointName ` --instance $iotOps.name ` --resource-group $rg.Name ` --eventhub-namespace $ehNs.Name ` --subscription $SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if (-not $? -or !$ss) { Write-Host "Error creating Event Hub endpoint $($eventHubEndpointName) - $($errOut)." ` -ForegroundColor Red exit -1 } Write-Host "Event Hub endpoint $($dp.id) created in $($iotOps.id)." ` -ForegroundColor Green } else { Write-Host "Event Hub endpoint $($eh.id) exists in $($iotOps.id)." ` -ForegroundColor Green } # # Deploy opc publisher as connector # if ($script:Connector -ne "None") { $discoveryMode = "Off" if ($script:EnableNetworkDiscovery.IsPresent) { $discoveryMode = "Fast" } & $(Join-Path $scriptDirectory "deploy.ps1") ` -Name $script:Name ` -ClusterType $script:ClusterType ` -ConnectorType $script:Connector ` -OpsInstanceName $iotOps.Name ` -AdrNamespaceName $ns.Name ` -SubscriptionId $SubscriptionId ` -TenantId $TenantId ` -ResourceGroup $rg.Name ` -Location $Location ` -NetworkDiscoveryMode $discoveryMode ` -SkipLogin ` -Force # :$forceReinstall ` if (-not $?) { Write-Host "Error deploying opc publisher connector." -ForegroundColor Red exit -1 } } else { Write-Host "No connector selected - no connector will be deployed..." ` -ForegroundColor Yellow } # # Deploy simulation servers # if ($script:DeployPlcSimulation.IsPresent) { & $(Join-Path $(Join-Path $scriptDirectory "simulation") "deploy.ps1") ` -DeploymentName "simulation1" ` -SimulationName "opc-plc" -Count 2 ` -InstanceName $script:OpsInstanceName ` -AdrNamespaceName $script:Name ` -SubscriptionId $SubscriptionId ` -TenantId $TenantId ` -ResourceGroup $rg.Name ` -Location $Location ` -Namespace $script:ClusterNamespace ` -SkipLogin ` -Force # :$forceReinstall ` if (-not $?) { Write-Host "Error deploying opc plc simulation servers." -ForegroundColor Red exit -1 } } if ($script:DeployTestSimulation.IsPresent) { & $(Join-Path $(Join-Path $scriptDirectory "simulation") "deploy.ps1") ` -DeploymentName "simulation2" ` -SimulationName "opc-test" -Count 2 ` -InstanceName $script:OpsInstanceName ` -AdrNamespaceName $script:Name ` -SubscriptionId $SubscriptionId ` -TenantId $TenantId ` -ResourceGroup $rg.Name ` -Location $Location ` -Namespace $script:ClusterNamespace ` -SkipLogin ` -Force # :$forceReinstall ` if (-not $?) { Write-Host "Error deploying test simulation servers." -ForegroundColor Red exit -1 } } ================================================ FILE: deploy/kubernetes/common/cluster-utils.psm1 ================================================ # Common utilities <# .SYNOPSIS Imports a container image into a Kubernetes cluster. .DESCRIPTION Imports a container image into different types of Kubernetes clusters (microk8s, k3d, kind). Handles the specific import requirements for each cluster type. .PARAMETER ClusterType The type of Kubernetes cluster (microk8s, k3d, or kind). .PARAMETER ContainerImage The container image to import. #> function Import-ContainerImage { [CmdletBinding()] param( [string] [Parameter(Mandatory = $true)] [ValidateSet( "microk8s", "k3d", "kind")] $ClusterType, [string] [Parameter(Mandatory = $true)] $ContainerImage ) Write-Host "Importing $ContainerImage into $ClusterType cluster..." -ForegroundColor Cyan switch ($ClusterType) { "microk8s" { # Windows only, support on linux is not implemented yet $imageTar = Join-Path $env:TEMP "image.tar" docker image save $ContainerImage -o $imageTar multipass transfer $imageTar microk8s-vm:/tmp/image.tar microk8s ctr image import /tmp/image.tar Remove-Item -Path $imageTar -Force docker image rm -f $ContainerImage $ContainerImage = "docker.io/$ContainerImage" } "k3d" { # import in all clusters which avoids asking for the cluster name $clusters = $(& { k3d cluster list --no-headers } -split ")`n") ` | ForEach-Object { $($_ -split " ")[0].Trim() } k3d image import $ContainerImage ` --mode auto ` --cluster $($clusters -join ",") } "kind" { kind load docker-image $ContainerImage } } Write-Host "Container $ContainerImage imported into $ClusterType cluster." -ForegroundColor Green } # Export module members Export-ModuleMember -Function Import-ContainerImage ================================================ FILE: deploy/kubernetes/debug/Dockerfile ================================================ FROM mcr.microsoft.com/dotnet/runtime-deps #FROM mcr.microsoft.com/dotnet/sdk:latest AS base USER root WORKDIR /app #### Remote Debugging Setup #### # Update package lists, install openssh-server, curl, and unzip. RUN apt-get update && \ apt-get install -y --no-install-recommends \ openssh-server curl unzip rsync procps net-tools tcpdump && \ rm -rf /var/lib/apt/lists/* && \ mkdir /var/run/sshd && \ # Set root password to "password123!" echo 'root:password123!' | chpasswd && \ # Configure SSH: allow root login and enable password authentication. sed -i 's/^#*PermitRootLogin .*/PermitRootLogin yes/' /etc/ssh/sshd_config && \ sed -i 's/^#*PasswordAuthentication .*/PasswordAuthentication yes/' /etc/ssh/sshd_config && \ echo "PermitUserEnvironment yes" >> /etc/ssh/sshd_config && \ # Install vsdbg for remote debugging with vs-code (vs 2022 installs its own version) curl -sSL https://aka.ms/getvsdbgsh | bash /dev/stdin -v latest -l /vsdbg && \ # Prepare SSH environment for root mkdir -p /root/.ssh && chmod 700 /root/.ssh # Expose the SSH port (22) EXPOSE 22 # Copy the custom entrypoint script into the container. COPY ./entrypoint.sh /app/entrypoint.sh RUN chmod +x /app/entrypoint.sh # Use our entrypoint script to start SSH ENTRYPOINT ["/app/entrypoint.sh"] ================================================ FILE: deploy/kubernetes/debug/build.ps1 ================================================ <# .SYNOPSIS Build a debug version of OPC Publisher and make it available in the local AIO cluster. .NOTES DO NOT USE FOR PRODUCTION SYSTEMS. This script is intended for development and testing purposes only. .PARAMETER Configuration The build configuration to use. Default is "Debug". .PARAMETER ClusterType The type of Kubernetes cluster to use. Default is "microk8s". #> param( [string] [ValidateSet( "Debug", "Release" )] $Configuration = "Debug", [string] [ValidateSet( "kind", "minikube", "k3d", "microk8s" )] $ClusterType = "microk8s", [switch] $StartDebugger ) $scriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Path Import-Module $(Join-Path $(Join-Path $(Split-Path $scriptDirectory) "common") ` "cluster-utils.psm1") -Force $projFile = "Azure.IIoT.OpcUa.Publisher.Module" $projFile = "../../../src/$($projFile)/src/$($projFile).csproj" $containerName = "iotedge/opc-publisher" $containerTag = Get-Date -Format "MMddHHmmss" $containerImage = "$($containerName):$($containerTag)" Write-Host "Publishing $Configuration OPC Publisher as $containerImage..." ` -ForegroundColor Cyan dotnet clean $projFile -c $Configuration dotnet restore $projFile -s https://api.nuget.org/v3/index.json dotnet publish $projFile -c $Configuration --self-contained false --no-restore ` /t:PublishContainer -r linux-x64 /p:ContainerImageTag=$($containerTag) if (-not $?) { Write-Host "Error building opc publisher connector." -ForegroundColor Red exit -1 } Write-Host "$Configuration container image $containerImage published successfully." ` -ForegroundColor Green Import-ContainerImage -ClusterType $script:ClusterType -ContainerImage $containerImage if ($StartDebugger) { ./debug.ps1 -Image $containerImage } ================================================ FILE: deploy/kubernetes/debug/debug.json ================================================ { "securityContext": { "runAsNonRoot": false, "runAsUser": 0, "runAsGroup": 0, "fsGroup": 0, "privileged": true } } ================================================ FILE: deploy/kubernetes/debug/debug.ps1 ================================================ <# .SYNOPSIS Make a pod debuggable by attaching a debugger container to it. .DESCRIPTION This script builds a Docker image for the vsdbg debugger and attaches it to a specified pod in a Kubernetes cluster. It requires Docker and kubectl to be installed and configured. .PARAMETER PodName The name of the pod to debug. .PARAMETER ContainerName The name of the container in the pod to debug. .PARAMETER Namespace The Kubernetes namespace where the pod is located. .PARAMETER ClusterType The type of Kubernetes cluster. Default is "microk8s". .PARAMETER Image If specified, the script will replace the existing image in the pod See --set-image in kubectl debug documentation. #> param( [string] $PodName, [string] $ContainerName, [string] $Namespace, [string] [ValidateSet( "kind", "minikube", "k3d", "microk8s" )] $ClusterType ="microk8s", [string] $Image, [switch] $Fork ) $ErrorActionPreference = 'Stop' $scriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Path Import-Module $(Join-Path $(Join-Path $(Split-Path $scriptDirectory) "common") ` "cluster-utils.psm1") -Force # Get a list of pods and let user select one if (-not (Get-Command kubectl -ErrorAction SilentlyContinue)) { Write-Host "kubectl is not installed or not in the PATH." -ForegroundColor Red exit -1 } if (-not (Get-Command docker -ErrorAction SilentlyContinue)) { Write-Host "docker is not installed or not in the PATH." -ForegroundColor Red exit -1 } # get list of namespaces and let user select one $namespaces = kubectl get namespaces --no-headers | ForEach-Object { $_.Split()[0] } if (-not $namespaces) { Write-Host "No namespaces found." -ForegroundColor Red exit -1 } if (-not $script:Namespace) { $script:Namespace = $namespaces | Out-GridView -Title "Select a namespace" -PassThru if (-not $script:Namespace) { Write-Host "No namespace selected." -ForegroundColor Yellow exit 0 } } else { if (-not $namespaces.Contains($script:Namespace)) { Write-Host "Namespace '$script:Namespace' not found." -ForegroundColor Red exit -1 } Write-Host "Using namespace '$script:Namespace'." -ForegroundColor Green } function Select-PodName { # get list of pods in the namespace and let user select one $pods = kubectl get pods -n $Namespace --no-headers | ForEach-Object { $_.Split()[0] } if (-not $pods) { Write-Host "No pods found in namespace '$Namespace'." -ForegroundColor Red exit -1 } if (-not $script:PodName) { $script:PodName = $pods | Out-GridView -Title "Select a pod to debug" -PassThru if (-not $script:PodName) { Write-Host "No pod selected." -ForegroundColor Yellow exit 0 } } else { if (-not $pods.Contains($script:PodName)) { Write-Host "Pod '$script:PodName' not found in namespace '$Namespace'." ` -ForegroundColor Red exit -1 } } } Select-PodName Write-Host "Using pod '$script:PodName'." -ForegroundColor Green # Build and make .net debugger image available in cluster $containerTag = Get-Date -Format "MMddHHmmss" $debuggerImage = "debugger:$($containerTag)" Write-Host "Building debugger image with tag '$containerTag'..." ` -ForegroundColor Cyan docker build --progress auto -f Dockerfile -t $debuggerImage . Write-Host "Debugger image built with tag '$containerTag'." ` -ForegroundColor Green Import-ContainerImage -ClusterType $script:ClusterType ` -ContainerImage $debuggerImage while ($true) { # Get main container name if not specified $containers = $(kubectl get pod $script:PodName -n $Namespace ` -o jsonpath-as-json='{.spec.containers[*].name}') | ConvertFrom-Json if (-not $containers -or $containers.Count -eq 0) { Write-Host "No containers found in pod '$script:PodName'." -ForegroundColor Red exit -1 } # If ContainerName is not specified, use the first container if (-not $ContainerName) { # if one use it otherwise let user select one if ($containers.Count -eq 1) { $ContainerName = $containers Write-Host "Using container '$ContainerName' in pod '$script:PodName'." ` -ForegroundColor Green } else { $ContainerName = $containers ` | Out-GridView -Title "Select a container to debug" -PassThru if (-not $ContainerName) { Write-Host "No container selected." -ForegroundColor Yellow exit 0 } } } else { if (-not $containers.Contains($ContainerName)) { Write-Host "Container '$ContainerName' not found in pod '$script:PodName'." ` -ForegroundColor Red exit -1 } Write-Host "Attach debugger to container '$ContainerName' in pod '$script:PodName'." ` -ForegroundColor Green } $ephemeralContainers = $(kubectl get pod $script:PodName -n $Namespace ` -o jsonpath-as-json='{.spec.ephemeralContainers[*].name}') | ConvertFrom-Json if (-not $ephemeralContainers -or -not $ephemeralContainers.Contains("debugger")) { # Debugger container is not attached yet, so we can proceed Write-Host "Debugger container not attached to pod '$script:PodName'." ` -ForegroundColor Green break } Write-Host "Debugger already attached to pod '$script:PodName' - Restarting pod." ` -ForegroundColor Yellow # Delete the current pod so we can recreate it with the debug container kubectl -n $Namespace delete pod $script:PodName --wait=true # Now wait for the pod to be restarted Write-Host "Waiting for pod '$script:PodName' to be restarted..." -ForegroundColor Cyan while ($true) { $podStatus = kubectl get pod $script:PodName -n $Namespace -o jsonpath='{.status.phase}' if ($podStatus -eq "Running") { Write-Host "Pod '$script:PodName' is running."` -ForegroundColor Green break } elseif ($podStatus -eq "Pending") { Write-Host "Pod '$script:PodName' is pending..."` -ForegroundColor Yellow } elseif (!$podStatus -or $podStatus -eq "") { $script:PodName = $null Select-PodName Write-Host "Switching to Pod '$script:PodName'." ` -ForegroundColor Green } else { Write-Host "Pod '$script:PodName' is in state '$podStatus'." ` -ForegroundColor Yellow } Start-Sleep -Seconds 1 } } if ($script:Fork.IsPresent) { # Check if the pods already contain a debug pod $debugPod = "$($script:PodName)-debug" if ($pods.Contains($debugPod)) { # delete the existing debug pod Write-Host "Debug pod '$($debugPod)' already exists - deleting it." ` -ForegroundColor Yellow # kubectl -n $Namespace delete pod $debugPod --wait=true } # Attach the debugger container to the specified pod and container Write-Host "Forking pod '$script:PodName' with container '$ContainerName' to '$($debugPod)'..." ` -ForegroundColor Cyan if ($Image) { # Replace the existing image in the pod kubectl -n $Namespace debug $script:PodName -n $($Namespace) ` -it --attach=false ` --image=docker.io/library/debugger:$($containerTag) ` --container=debugger ` --keep-annotations=true ` --keep-labels=true ` --keep-init-containers=true ` --keep-liveness=true ` --keep-readiness=true ` --keep-startup=true ` --same-node=true ` --set-image="$($ContainerName)=$($Image)" ` --image-pull-policy=IfNotPresent ` --share-processes=true ` --profile=sysadmin ` --custom=debug.json ` --copy-to=$($debugPod) ` } else { kubectl -n $Namespace debug $script:PodName -n $($Namespace) ` -it --attach=false ` --image=docker.io/library/debugger:$($containerTag) ` --container=debugger ` --keep-annotations=true ` --keep-labels=true ` --keep-init-containers=true ` --keep-liveness=true ` --keep-readiness=true ` --keep-startup=true ` --same-node=true ` --image-pull-policy=IfNotPresent ` --share-processes=true ` --profile=sysadmin ` --custom=debug.json ` --copy-to=$($debugPod) ` } if (-not $?) { Write-Host "Failed to fork pod '$script:PodName' with container '$ContainerName' to '$($debugPod)'." ` -ForegroundColor Red exit -1 } Write-Host "Debugging pod '$script:PodName' as '$($debugPod)' with container '$ContainerName'." ` -ForegroundColor Green $script:PodName = $debugPod } elseif ($Image) { # Set the image to the specified one Write-Host "Replacing image in pod '$script:PodName' for container '$ContainerName' with '$Image'..." ` -ForegroundColor Cyan kubectl set image "pod/$($script:PodName)" "$($ContainerName)=$($Image)" -n $($Namespace) if (-not $?) { Write-Host "Failed to replace image in pod '$script:PodName' for container '$ContainerName'." ` -ForegroundColor Red exit -1 } Write-Host "Image in pod '$script:PodName' for container '$ContainerName' replaced with '$Image'." ` -ForegroundColor Green } # Now wait for the pod to start Write-Host "Checking state of pod '$script:PodName'..." -ForegroundColor Cyan while ($true) { $podStatus = kubectl get pod $script:PodName -n $Namespace -o jsonpath='{.status.phase}' if ($podStatus -eq "Running") { if ($Image) { $podDescription = $(kubectl get pod $script:PodName -n $Namespace -o json) ` | ConvertFrom-Json $images = $podDescription.spec.containers.image if ($images -contains $Image) { Write-Host "Pod '$script:PodName' is running with '$Image'."` -ForegroundColor Green break } else { Write-Host "Pod '$script:PodName' is running but still using the old image." ` -ForegroundColor Yellow } } else { Write-Host "Pod '$script:PodName' is running."` -ForegroundColor Green break } } elseif ($podStatus -eq "Pending") { Write-Host "Pod '$script:PodName' is pending..."` -ForegroundColor Yellow } elseif (!$podStatus -or $podStatus -eq "") { $ContainerName = $containers ` | Out-GridView -Title "Select a container to debug" -PassThru if (-not $ContainerName) { Write-Host "No container selected." -ForegroundColor Yellow exit 0 } Write-Host "Pod '$script:PodName' in unknown state..."` -ForegroundColor Red } else { Write-Host "Pod '$script:PodName' is in state '$podStatus'." ` -ForegroundColor Yellow } Start-Sleep -Seconds 1 } if (-not $script:Fork.IsPresent) { Write-Host "Attaching debugger to pod '$script:PodName' and container '$ContainerName'..." ` -ForegroundColor Cyan # Attach to running container kubectl -n $Namespace debug $script:PodName -n $($Namespace) ` --image=docker.io/library/debugger:$($containerTag) ` --target=$ContainerName ` --container=debugger ` --image-pull-policy=IfNotPresent ` --share-processes=true ` --profile=sysadmin ` --custom=debug.json ` -it --attach=false Write-Host "Debugging pod '$script:PodName' and container '$ContainerName'." ` -ForegroundColor Green } Write-Host "Visual Studio Debugger listening on localhost:50000." ` -ForegroundColor Green kubectl port-forward -n $($Namespace) --address=0.0.0.0 pod/$($script:PodName) 50000:22 ================================================ FILE: deploy/kubernetes/debug/entrypoint.sh ================================================ #!/bin/bash # # Start ssh server to accept incoming debugger connections on port 22. # echo "Starting SSH server..." /usr/sbin/sshd # # Workaround for the debugged container not sharing the /tmp directory with # the debugger which VS Debugger requires to set up the ipc to the process # being debugged. See https://github.com/microsoft/MIEngine/issues/1488 and # https://github.com/dotnet/runtime/issues/37444 for more information. # if [ -n "$1" ]; then PROCESS="$1" elif [ -n "$__DEBUG_TARGET" ]; then PROCESS="$__DEBUG_TARGET" else PROCESS="dotnet" fi CUR= U="root" while true; do # Check if the process is running PID=$(pgrep -f $PROCESS) if [ -z "$PID" ]; then if [ -n "$CUR" ]; then echo "$PROCESS process $CUR stopped." CUR= fi sleep 2s elif [ "$PID" != "$CUR" ]; then if [ -z "$CUR" ]; then echo "$PROCESS process $PID started." else echo "$PROCESS process $CUR restarted as $PID." fi CUR=$PID # Update the TMPDIR environment variable for all users in bashrc echo "Setting TMPDIR to /proc/$CUR/$U/tmp for the current user..." if grep -q "export TMPDIR=" ~/.bashrc; then sed -i "s|^export TMPDIR=.*|export TMPDIR=/proc/$CUR/$U/tmp|" ~/.bashrc else echo "export TMPDIR=/proc/$CUR/$U/tmp" >> ~/.bashrc fi ARGS=$(ps -o args= -p $CUR) ARGS=$(set $ARGS && shift && echo $1) echo "$PROCESS started with PID $CUR and arguments '$ARGS'" echo "Waiting..." sleep 3s # point to the dotnet runtime in the debugged process echo "Linking /usr/share/dotnet to /proc/$CUR/$U/usr/share/dotnet" ln -sf /proc/$CUR/$U/usr/share/dotnet /usr/share/dotnet # Try to make the dll/pdb files available to the debugger process... ARG_PATH=$(dirname "${ARGS}") mkdir -p $ARG_PATH find $ARG_PATH/ -type l -delete echo "Linking files from /proc/$CUR/$U$ARG_PATH/ to $ARG_PATH/" FILES=$(find /proc/$CUR/$U$ARG_PATH/ \ -regextype posix-extended -regex '.*\.(pdb|dll)$' \ -exec realpath --relative-to=/proc/$CUR/$U/ {} \;) for i in $FILES; do echo "Linking /proc/$CUR/$U/$i to /$i" ln -sf /proc/$CUR/$U/$i /$i done else sleep 10s fi done ================================================ FILE: deploy/kubernetes/debug/forward-mq.ps1 ================================================ <# This script forwards the MQTT port of the aio-broker-insecure service in the specified namespace. It is intended for debugging purposes in a Kubernetes cluster. Presumes the --enable-insecure-listener was used during az iot ops create. #> param( [string] $Namespace = "azure-iot-operations" ) kubectl -n $Namespace port-forward service/aio-broker-insecure 1883:1883 ================================================ FILE: deploy/kubernetes/deploy.ps1 ================================================ <# .SYNOPSIS Setup local AIO cluster and connect to Arc (must run as admin) .DESCRIPTION Setup local AIO cluster and connect to Arc. This script installs the cluster type chosen and all other required dependencies and connect it to the cloud via Arc. Then it will install AIO on it. .NOTES DO NOT USE FOR PRODUCTION SYSTEMS. This script is intended for development and testing purposes only. .PARAMETER Name The name of the cluster .PARAMETER OpsInstanceName The name of the Azure IoT Ops instance. Default is the same as the cluster name. .PARAMETER AdrNamespaceName The name of the ADR namespace to create or use. Default is the same as the cluster name. .PARAMETER ResourceGroup The resource group to create or use for the cluster. Default is the same as the cluster name. .PARAMETER TenantId The tenant id to use when logging into Azure. .PARAMETER SubscriptionId The subscription id to scope all activity to. .PARAMETER Location The location of the cluster. .PARAMETER ClusterType The type of cluster to create. Default is microk8s. .PARAMETER ConnectorType Whether to deploy the OPC Publisher as connector. Official installs the official connector build, Local builds and deploys a local version. Debug the debug version. Default is Official. .PARAMETER BucketSize The size of the bucket to use to partition devices across connectors. Default is 1 where every connector gets one device. .PARAMETER NetworkDiscoveryMode Network discovery mode to use. Default is "Off" (disabled). .PARAMETER SkipLogin Skip the login to Azure. This is useful when running in a CI/CD .PARAMETER Force Force reinstall. #> param( [string] [Parameter(Mandatory = $true)] $Name, [string] $OpsInstanceName, [string] $AdrNamespaceName, [string] $ResourceGroup, [string] $TenantId, [string] $SubscriptionId, [string] $Location, [string] [ValidateSet( "kind", "minikube", "k3d", "microk8s" )] $ClusterType = "microk8s", [string] [ValidateSet( "Official", "Local", "Debug" )] $ConnectorType = "Official", [string] [ValidateSet( "Off", "Fast", "Local", "Full" )] $NetworkDiscoveryMode = "Off", [int] $BucketSize = 1, [switch] $SkipLogin, [switch] $Force ) $ErrorActionPreference = 'Continue' $scriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Path Import-Module $(Join-Path $(Join-Path $scriptDirectory "common") "cluster-utils.psm1") -Force # # Dump command line arguments # if ([string]::IsNullOrWhiteSpace($script:ResourceGroup)) { $script:ResourceGroup = $script:Name Write-Host "Using resource group $($script:ResourceGroup)..." -ForegroundColor Cyan } if ([string]::IsNullOrWhiteSpace($script:Location)) { $script:Location = "westus" Write-Host "Using location $($script:Location)..." -ForegroundColor Cyan } if ([string]::IsNullOrWhiteSpace($script:OpsInstanceName)) { $script:OpsInstanceName = $Name Write-Host "Using instance name $($script:OpsInstanceName)..." -ForegroundColor Cyan } if ([string]::IsNullOrWhiteSpace($script:AdrNamespaceName)) { $script:AdrNamespaceName = $Name Write-Host "Using ADR namespace name $($script:AdrNamespaceName)..." -ForegroundColor Cyan } # check if docker and az cli are installed $errOut = $($docker = & { docker version --format json | ConvertFrom-Json }) 2>&1 if (-not $? -or !$docker.Server) { $docker | Out-Host Write-Host "Docker not installed or running : $errOut" -ForegroundColor Red exit -1 } $errOut = $($azVersion = (az version)[1].Split(":")[1].Split('"')[1]) 2>&1 if ($azVersion -lt "2.74.0" -or !$azVersion) { Write-Host "Azure CLI version 2.74.0 or higher is required." ` -ForegroundColor Red exit -1 } $errOut = $($azVersion = & {az extension list -o json ` --query "[?name == 'azure-iot-ops']"} | ConvertFrom-Json) 2>&1 if (!$azVersion -or $azVersion[0].version -lt "2.0.0") { Write-Host "Azure IoT Operations Extension version 2.0 or higher is required." ` -ForegroundColor Red exit -1 } # # Log into azure # if (-not $script:SkipLogin.IsPresent -or -not $SubscriptionId) { if ([string]::IsNullOrWhiteSpace($script:TenantId)) { $script:TenantId = $env:AZURE_TENANT_ID } Write-Host "Log into Azure..." -ForegroundColor Cyan $loginParams = @( "--only-show-errors" ) if (![string]::IsNullOrWhiteSpace($script:TenantId)) { $loginParams += @("--tenant", $script:TenantId) } $session = (az login @loginParams) | ConvertFrom-Json if (-not $session) { Write-Host "Error: Login failed." -ForegroundColor Red exit -1 } if ([string]::IsNullOrWhiteSpace($script:SubscriptionId)) { $script:SubscriptionId = $session[0].id } if ([string]::IsNullOrWhiteSpace($script:TenantId)) { $script:TenantId = $session[0].tenantId } } # # Check adr namespace schema registry and azure iot instance exists # $errOut = $($rg = & { az group show ` --name $script:ResourceGroup ` --subscription $script:SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if (!$rg) { Write-Host "Resource group $($script:ResourceGroup) not found - $($errOut)." ` -ForegroundColor Red exit -1 } $adrNsResource = "/subscriptions/$($script:SubscriptionId)" $adrNsResource = "$($adrNsResource)/resourceGroups/$($script:ResourceGroup)" $adrNsResource = "$($adrNsResource)/providers/Microsoft.DeviceRegistry" $adrNsResource = "$($adrNsResource)/namespaces/$($script:AdrNamespaceName)" $errOut = $($ns = & { az rest --method get ` --url "$($adrNsResource)?api-version=2025-10-01" ` --headers "Content-Type=application/json" } | ConvertFrom-Json) 2>&1 if (!$ns -or !$ns.id) { Write-Host "ADR namespace $($script:AdrNamespaceName) not found - $($errOut)." ` -ForegroundColor Red exit -1 } $errOut = $($iotOps = & { az iot ops show ` --resource-group $script:ResourceGroup ` --name $script:OpsInstanceName ` --subscription $script:SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if (!$iotOps) { Write-Host "Azure IoT Operations instance $($script:OpsInstanceName) not found - $($errOut)." ` -ForegroundColor Red exit -1 } # # Deploy publisher as connector # $containerTag = "latest" $containerRegistry = $null $containerName = "iotedge/opc-publisher" if ($script:ConnectorType -eq "Official") { Write-Host "Using official OPC Publisher image as connector..." -ForegroundColor Cyan $containerPull = "Always" $containerRegistry = @{ registrySettingsType = "ContainerRegistry" containerRegistrySettings = @{ registry = "mcr.microsoft.com" } } $containerImage = "mcr.microsoft.com/$($containerName):$($containerTag)" $connectorMetadataRef = "mcr.microsoft.com/$($containerName):$($containerTag)-metadata" } else { $projFile = "Azure.IIoT.OpcUa.Publisher.Module" $projFile = "../../src/$($projFile)/src/$($projFile).csproj" $configuration = $script:ConnectorType if ($configuration -eq "Local") { $configuration = "Release" } $containerTag = Get-Date -Format "MMddHHmmss" $containerImage = "$($containerName):$($containerTag)" $connectorMetadataRef = $null Write-Host "Publishing $configuration OPC Publisher as $containerImage..." ` -ForegroundColor Cyan dotnet restore $projFile -s https://api.nuget.org/v3/index.json dotnet publish $projFile -c $configuration --self-contained false --no-restore ` /t:PublishContainer -r linux-x64 /p:ContainerImageTag=$($containerTag) if (-not $?) { Write-Host "Error building opc publisher connector." -ForegroundColor Red exit -1 } Write-Host "$configuration container image $containerImage published successfully." ` -ForegroundColor Green $containerPull = "IfNotPresent" # Import container image Import-ContainerImage -ClusterType $script:ClusterType -ContainerImage $containerImage if ($script:ClusterType -eq "microk8s") { $containerImage = "docker.io/$($containerImage)" $containerRegistry = @{ registrySettingsType = "ContainerRegistry" containerRegistrySettings = @{ registry = "docker.io" } } } } # Deploy connector template $tempFile = New-TemporaryFile $template = @{ extendedLocation = $iotOps.extendedLocation properties = @{ aioMetadata = @{ aioMinVersion = "1.2.*" aioMaxVersion = "1.*.*" } runtimeConfiguration = @{ runtimeConfigurationType = "ManagedConfiguration" managedConfigurationSettings = @{ managedConfigurationType = "ImageConfiguration" imageConfigurationSettings = @{ imageName = $containerName imagePullPolicy = $containerPull replicas = 1 # set to 2 when HA is supported registrySettings = $containerRegistry tagDigestSettings = @{ tagDigestType = "Tag" tag = $containerTag } } allocation = @{ policy = "Bucketized" bucketSize = $script:BucketSize } additionalConfiguration = @{ EnableMetrics = "True" UseFileChangePolling = "True" AioNetworkDiscoveryMode = $null AioNetworkDiscoveryInterval = $null DisableDataSetMetaData = "True" LogFormat = "syslog" # Needed because we are not running as "app" user PkiRootPath = "/var/tmp/pki" PublishedNodesFile = "/var/tmp/pn.json" CreatePublishFileIfNotExist = "True" } #persistentVolumeClaims = @( # @{ # claimName = "opcpublisherdata" # mountPath = "/app" # } #) secrets = @() } } deviceInboundEndpointTypes = @( @{ endpointType = "Microsoft.OpcPublisher" version = "2.9" displayName = "OPC Publisher" } ) diagnostics = @{ logs = @{ level = "info" } } connectorMetadataRef = $connectorMetadataRef mqttConnectionConfiguration = @{ host = "aio-broker:18883" authentication = @{ method = "ServiceAccountToken" serviceAccountTokenSettings = @{ audience = "aio-internal" } } tls = @{ mode = "Enabled" trustedCaCertificateConfigMapRef = "azure-iot-operations-aio-ca-trust-bundle" } } } } | ConvertTo-Json -Depth 100 # Workaround for discovery while discovery handler is not yet supported if ($script:NetworkDiscoveryMode -ne "Off") { Write-Host "Network Discovery via discovery handler is not supported yet." ` -ForegroundColor Yellow Write-Host "Enabling discovery in connector instead." ` -ForegroundColor Yellow $additionalConfig = $template.properties.runtimeConfiguration.additionalConfiguration $additionalConfig.AioNetworkDiscoveryMode = $script:NetworkDiscoveryMode $additionalConfig.AioNetworkDiscoveryInterval = "00:10:00" $script:NetworkDiscoveryMode = "Off" } $template | Out-File -FilePath $tempFile -Encoding utf8 -Force $ctName = "opc-publisher" $ctResource = "/subscriptions/$($script:SubscriptionId)" $ctResource = "$($ctResource)/resourceGroups/$($rg.Name)" $ctResource = "$($ctResource)/providers/Microsoft.IoTOperations" $ctResource = "$($ctResource)/instances/$($iotOps.name)" $ctResource = "$($ctResource)/akriConnectorTemplates/$($ctName)" Write-Host "Deploying connector template $($ctName)..." -ForegroundColor Cyan az rest --method put ` --url "$($ctResource)?api-version=2025-09-01-preview" ` --headers "Content-Type=application/json" ` --body @$tempFile if (-not $?) { Write-Host "Error deploying connector template $($ctName) - $($errOut)." ` -ForegroundColor Red Remove-Item -Path $tempFile -Force exit -1 } # Deploy discovery handler - disabled in current version of Azure IoT Operations if ($script:NetworkDiscoveryMode -ne "Off") { $template = @{ extendedLocation = $iotOps.extendedLocation properties = @{ aioMetadata = @{ aioMinVersion = "1.2.*" aioMaxVersion = "1.*.*" } imageConfiguration = @{ imageName = $containerName imagePullPolicy = $containerPull registrySettings = $containerRegistry tagDigestSettings = @{ tagDigestType = "Tag" tag = $containerTag } } mode = "Enabled" schedule = @{ scheduleType = "Cron" # or "Continuous" or "RunOnce" cron = "*/10 * * * *" } additionalConfiguration = @{ AioNetworkDiscoveryMode = "$($script:NetworkDiscoveryMode)" EnableMetrics = "True" UseFileChangePolling = "True" LogFormat = "syslog" DisableDataSetMetaData = "True" # Needed because we are not running as "app" user PkiRootPath = "/var/tmp/pki" PublishedNodesFile = "/var/tmp/pn.json" CreatePublishFileIfNotExist = "True" } discoverableDeviceEndpointTypes = @( @{ endpointType = "Microsoft.OpcPublisher" version = "2.9" #displayName = "OPC Publisher" } ) secrets = @() diagnostics = @{ logs = @{ level = "info" } } connectorMetadataRef = $connectorMetadataRef mqttConnectionConfiguration = @{ host = "aio-broker:18883" authentication = @{ method = "ServiceAccountToken" serviceAccountTokenSettings = @{ audience = "aio-internal" } } tls = @{ mode = "Enabled" trustedCaCertificateConfigMapRef = "azure-iot-operations-aio-ca-trust-bundle" } } } } | ConvertTo-Json -Depth 100 $template | Out-File -FilePath $tempFile -Encoding utf8 -Force $dhName = "opc-publisher" $dhResource = "/subscriptions/$($script:SubscriptionId)" $dhResource = "$($dhResource)/resourceGroups/$($rg.Name)" $dhResource = "$($dhResource)/providers/Microsoft.IoTOperations" $dhResource = "$($dhResource)/instances/$($iotOps.name)" $dhResource = "$($dhResource)/akriDiscoveryHandlers/$($dhName)" Write-Host "Deploying discovery handler template $($dhName)..." -ForegroundColor Cyan az rest --method put ` --url "$($dhResource)?api-version=2025-09-01-preview" ` --headers "Content-Type=application/json" ` --body @$tempFile if (-not $?) { Write-Host "Error deploying discovery handler template $($dhName) - $($errOut)." ` -ForegroundColor Red Remove-Item -Path $tempFile -Force exit -1 } } Remove-Item -Path $tempFile -Force ================================================ FILE: deploy/kubernetes/iotops/adr-tool.ps1 ================================================ <# .SYNOPSIS Enables onboarding and cleanup of namespace resources in Azure Device Registry. .DESCRIPTION This tool can be used to onboard discovered assets and devices as assets and devices or clean them up. It requires the Azure CLI to be installed. When used in "Onboard" mode, it will monitor (loop) for new discovered assets and devices in ADR and copy them as new assets and devices. This is a simpler way to test discovery than the UX based onboarding flow via the Digital Operation experience. When used in "Cleanup" mode, it will delete all discovered and onboarded assets and devices in ADR. .NOTES DO NOT USE FOR PRODUCTION SYSTEMS. This script is intended for development and testing purposes only. .PARAMETER Action The action to perform. Valid values are "Onboard" and "Cleanup". Default is "Onboard". If "Cleanup" is specified, the script will delete all discovered assets and devices. .PARAMETER AdrNamespaceName The ADR namespace to use for the instance. Default is the same as the instance name. .PARAMETER ResourceGroup The resource group to create or use for the cluster. Default is the same as the cluster name. .PARAMETER SubscriptionId The subscription id where the namespace is located. If not specified, the script will use the current subscription. .PARAMETER TenantId The tenant id to use when logging into Azure. If not specified, the script will use the current tenant. .PARAMETER RunOnce If specified, the script will run only one iteration of the action and exit. Otherwise it will run the action to completion. .PARAMETER Force If specified, the script will force the onboarding of devices and assets even if they already exist. .PARAMETER SkipLogin If specified, the script will skip the login step and use the current session. #> param( [string] [Parameter(Mandatory = $true)] [ValidateSet( "Onboard", "Cleanup" )] [string] $Action, [string] [Parameter(Mandatory = $true)] $Name, [string] $AdrNamespaceName, [string] $ResourceGroup, [string] $SubscriptionId = "53d910a7-f1f8-4b7a-8ee0-6e6b67bddd82", [string] $TenantId, [switch] $RunOnce, [switch] $Force, [switch] $SkipLogin ) $ErrorActionPreference = 'Continue' if ([string]::IsNullOrWhiteSpace($ResourceGroup)) { $ResourceGroup = $script:Name Write-Host "Using resource group $ResourceGroup..." -ForegroundColor Cyan } if ([string]::IsNullOrWhiteSpace($script:AdrNamespaceName)) { $script:AdrNamespaceName = $script:Name Write-Host "Using ADR namespace name $($script:AdrNamespaceName)..." -ForegroundColor Cyan } $azVersion = (az version)[1].Split(":")[1].Split('"')[1] if ($azVersion -lt "2.74.0" -or !$azVersion) { Write-Host "Azure CLI version 2.74.0 or higher is required." ` -ForegroundColor Red exit -1 } # # Log into azure # if (-not $script:SkipLogin.IsPresent) { Write-Host "Log into Azure..." -ForegroundColor Cyan $loginParams = @( "--only-show-errors" ) if (![string]::IsNullOrWhiteSpace($script:TenantId)) { $loginParams += @("--tenant", $script:TenantId) } $session = (az login @loginParams) | ConvertFrom-Json if (-not $session) { Write-Host "Error: Login failed." -ForegroundColor Red exit -1 } if ([string]::IsNullOrWhiteSpace($script:SubscriptionId)) { $script:SubscriptionId = $session[0].id } if ([string]::IsNullOrWhiteSpace($script:TenantId)) { $script:TenantId = $session[0].tenantId } } # # Check adr namespace exists # $adrNsResource = "/subscriptions/$($script:SubscriptionId)" $adrNsResource = "$($adrNsResource)/resourceGroups/$($script:ResourceGroup)" $adrNsResource = "$($adrNsResource)/providers/Microsoft.DeviceRegistry" $adrNsResource = "$($adrNsResource)/namespaces/$($AdrNamespaceName)" $errOut = $($ns = & { az rest --method get ` --url "$($adrNsResource)?api-version=2025-10-01" ` --headers "Content-Type=application/json" } | ConvertFrom-Json) 2>&1 if (!$ns -or !$ns.id) { Write-Host "ADR namespace $($adrNsResource) not found - $($errOut)." ` -ForegroundColor Red exit -1 } # # Remove properties from discovered resource that are not supported on actual resource # function Remove-PropertyRecursively { param ( [Parameter(Mandatory)] [PSObject] $Object, [Parameter(Mandatory)] [string] $PropertyName ) # Check if the object is a hashtable or PSCustomObject if ($Object -is [System.Collections.IDictionary]) { # Remove the property if it exists if ($Object.ContainsKey($PropertyName)) { $Object.Remove($PropertyName) } # Recursively process nested objects foreach ($key in $Object.Keys) { Remove-PropertyRecursively -Object $Object[$key] -PropertyName $PropertyName } } elseif ($Object -is [System.Collections.IEnumerable] -and -not ($Object -is [string])) { # Iterate through enumerable objects foreach ($item in $Object) { Remove-PropertyRecursively -Object $item -PropertyName $PropertyName } } elseif ($Object -is [PSCustomObject]) { # Remove the property if it exists if ($Object.PSObject.Properties[$PropertyName]) { $Object.PSObject.Properties.Remove($PropertyName) } # Recursively process nested properties foreach ($property in $Object.PSObject.Properties) { Remove-PropertyRecursively -Object $property.Value -PropertyName $PropertyName } } } if ($script:Action -eq "Cleanup") { $resourceTypes = @( "discoveredAssets", "discoveredDevices", "assets", "devices" ) $itemsDeleted = $true while ($itemsDeleted) { $itemsDeleted = $false foreach ($resourceType in $resourceTypes) { Write-Host "Deleting all $($resourceType) in ADR namespace $($ns.name)..." ` -ForegroundColor Cyan $errOut = $($resources = & { az rest --method get ` --url "$($ns.id)/$($resourceType)?api-version=2025-10-01" ` --headers "Content-Type=application/json" } | ConvertFrom-Json) 2>&1 if ($resources -and $resources.value) { foreach ($resource in $resources.value) { $itemsDeleted = $true $errOut = & { az rest --method delete ` --url "$($resource.id)?api-version=2025-10-01" ` --headers "Content-Type=application/json" } 2>&1 $name = "$($resourceType.TrimEnd('s')) $($resource.name)" if (-not $?) { Write-Host "Error deleting $($name): $($errOut)" ` -ForegroundColor Red } else { Write-Host "Deleted $($name)." -ForegroundColor Green } } } } if ($script:RunOnce.IsPresent) { break } } } elseif ($script:Action -eq "Onboard") { $tempFile = New-TemporaryFile Write-Host "Onboarding devices and assets in ADR namespace $($ns.name)..." ` -ForegroundColor Green while ($true) { $errOut = $($dDevices = & { az rest --method get ` --url "$($ns.id)/discoveredDevices?api-version=2025-10-01" ` --headers "Content-Type=application/json" } | ConvertFrom-Json) 2>&1 $onboardComplete = $false $needsSync = $false if ($dDevices -and $dDevices.value) { foreach ($dDevice in $dDevices.value) { $errOut = $($device = & { az rest --method get ` --url "$($ns.id)/devices/$($dDevice.name)?api-version=2025-10-01" ` --headers "Content-Type=application/json" } | ConvertFrom-Json) 2>&1 if ($device -and $device.id) { Write-Host "Device $($device.name) exists with version $($device.properties.version)..." ` -ForegroundColor Cyan if ($dDevice.properties.version -eq 1) { # always sync first version $needsSync = $true } elseif ($device.properties.version -ne $dDevice.properties.version) { Write-Host "Discovered Device $($dDevice.name) has a different version $($dDevice.properties.version)." ` -ForegroundColor Yellow $needsSync = $true } elseif (-not $script:Force.IsPresent) { Write-Host "Device $($device.name) is up to date." -ForegroundColor Green $onboardComplete = $true continue } } Remove-PropertyRecursively -Object $dDevice.properties -PropertyName "supportedAuthenticationMethods" $body = @{ extendedLocation = $dDevice.extendedLocation location = $dDevice.location properties = @{ externalDeviceId = $dDevice.properties.externalDeviceId enabled = $true endpoints = $dDevice.properties.endpoints } } | ConvertTo-Json -Depth 100 #$body | Out-Host $body | Out-File -FilePath $tempFile -Encoding utf8 -Force Write-Host "Create or update device $($dDevice.name)..." -ForegroundColor Cyan $errOut = $($device = & { az rest --method put ` --url "$($ns.id)/devices/$($dDevice.name)?api-version=2025-10-01" ` --headers "Content-Type=application/json" ` --body @$tempFile } | ConvertFrom-Json) 2>&1 if (!$device.id) { Write-Host "Error onboarding device $($dDevice.name): $($errOut)" ` -ForegroundColor Red } else { Write-Host "Device $($device.name) created or updated successfully." ` -ForegroundColor Green $onboardComplete = $true } } } else { Write-Host "No discovered devices found." -ForegroundColor Yellow } $errOut = $($dAssets = & { az rest --method get ` --url "$($ns.id)/discoveredAssets?api-version=2025-10-01" ` --headers "Content-Type=application/json" } | ConvertFrom-Json) 2>&1 if ($dAssets -and $dAssets.value) { foreach ($dAsset in $dAssets.value) { $errOut = $($asset = & { az rest --method get ` --url "$($ns.id)/assets/$($dAsset.name)?api-version=2025-10-01" ` --headers "Content-Type=application/json" } | ConvertFrom-Json) 2>&1 if ($asset -and $asset.id) { Write-Host "Asset $($asset.name) exists with version $($asset.properties.version)..." ` -ForegroundColor Cyan if ($asset.properties.version -ne $dAsset.properties.version) { Write-Host "Discovered Asset $($dAsset.name) has a different version $($dAsset.properties.version)." ` -ForegroundColor Yellow $needsSync = $true } elseif (-not $script:Force.IsPresent) { Write-Host "Asset $($asset.name) is up to date." -ForegroundColor Green $onboardComplete = $true continue } } $displayName = $dAsset.properties.displayName if (!$displayName) { $displayName = $dAsset.properties.model } Remove-PropertyRecursively -Object $dAsset.properties -PropertyName "lastUpdatedOn" $body = @{ extendedLocation = $dAsset.extendedLocation location = $dAsset.location properties = @{ externalAssetId = $dAsset.properties.externalAssetId enabled = $true displayName = $displayName description = $dAsset.properties.description manufacturer = $dAsset.properties.manufacturer model = $dAsset.properties.model productCode = $dAsset.properties.productCode hardwareRevision = $dAsset.properties.hardwareRevision softwareRevision = $dAsset.properties.softwareRevision documentationUri = $dAsset.properties.documentationUri serialNumber = $dAsset.properties.serialNumber defaultDatasetsDestinations = ` $dAsset.properties.defaultDatasetsDestinations defaultEventsDestinations = ` $dAsset.properties.defaultEventsDestinations defaultStreamsDestinations = ` $dAsset.properties.defaultStreamsDestinations defaultDatasetsConfiguration = ` $dAsset.properties.defaultDatasetsConfiguration defaultEventsConfiguration = ` $dAsset.properties.defaultEventsConfiguration defaultStreamsConfiguration = ` $dAsset.properties.defaultStreamsConfiguration defaultManagementGroupsConfiguration = ` $dAsset.properties.defaultManagementGroupsConfiguration # .... add more properties as needed deviceRef = $dAsset.properties.deviceRef discoveredAssetRefs = @($dAsset.name) assetTypeRefs = [array]$dAsset.properties.assetTypeRefs datasets = [array]$dAsset.properties.datasets eventGroups = [array]$dAsset.properties.eventGroups streams = [array]$dAsset.properties.streams managementGroups = [array]$dAsset.properties.managementGroups } } | ConvertTo-Json -Depth 100 #$body | Out-Host $body | Out-File -FilePath $tempFile -Encoding utf8 -Force Write-Host "Create or update asset $($dAsset.name)..." -ForegroundColor Cyan $errOut = $($asset = & { az rest --method put ` --url "$($ns.id)/assets/$($dAsset.name)?api-version=2025-10-01" ` --headers "Content-Type=application/json" ` --body @$tempFile } | ConvertFrom-Json) 2>&1 if (!$asset.id) { Write-Host "Error onboarding asset $($dAsset.name): $($errOut)" ` -ForegroundColor Red } else { Write-Host "Asset $($asset.name) created or updated successfully." ` -ForegroundColor Green $onboardComplete = $true } } } else { Write-Host "No discovered assets found." -ForegroundColor Yellow } if ($script:RunOnce.IsPresent -and $onboardComplete -and -not $needsSync) { break } if ($needsSync) { continue } Start-Sleep -Seconds 60 } Remove-Item -Path $tempFile -Force } else { Write-Host "Invalid action $($script:Action)." -ForegroundColor Red exit -1 } ================================================ FILE: deploy/kubernetes/iotops/enable-preview.ps1 ================================================ <# This script enables the Azure IoT Operations Private Preview feature and installs the necessary extension. It requires the Azure CLI and the Azure IoT Operations extension to be installed. #> param ( [string] $SubscriptionId ) az feature register --name PrivatePreview2509 --namespace Microsoft.IoTOperations ` --subscription $SubscriptionId ` --only-show-errors Write-Host "Azure IoT Operations Private Preview enabled." -ForegroundColor Green Write-Host "You must use '--ops-extension preview' parameter for ./cluster.setup.ps1 script" ` -ForegroundColor Yellow Write-Host "Otherwise this script must be run again." -ForegroundColor Yellow ================================================ FILE: deploy/kubernetes/iotops/opc-publisher-connector-metadata.json ================================================ { "$schema": "https://raw.githubusercontent.com/Azure/iot-operations-sdks/refs/heads/main/doc/akri_connector/connector-metadata-schema.json", "name": "OpcPublisher", "description": "OPC Publisher Connector", "version": "2.9.0", "maintainer": "iiotadmin@microsoft.com", "vendor": "Microsoft", "imageConfigurationSettings": { "imageName": "mcr.microsoft.com/iotedge/opc-publisher", "tag": "latest" }, "supportedArchitectures": [ "linux/amd64", "linux/arm64", "linux/arm/v7" ], "sourceCode": { "language": ".NET", "languageVersion": ".NET 9.0", "sdks": { "connectorPackageVersion": "0.13.0-preview" } }, "aioMetadata": { "aioMinVersion": "1.2.*", "aioMaxVersion": "1.*.*" }, "inboundEndpoints": [ { "endpointType": "Microsoft.OpcPublisher", "description": "Connect to an OPC UA server and publish data to Azure.", "supportedAuthenticationTypes": [ "anonymous", "usernamePassword" ], "assetsEnabledByDefault": true, "version": "2.9", "fields": { "address": { "input": "required", "type": "string", "description": "The endpoint URL of the OPC UA server to connect to.", "regex": [ "^opc.(tcp|http|https)://.+$" ], "exampleValue": "opc.tcp://localhost:4840" } }, "additionalConfigurationSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "DeviceEndpointModel", "description": "Configuration model for OPC UA endpoint security and connection settings.", "type": "object", "properties": { "EndpointSecurityPolicy": { "type": "string", "minLength": 1, "maxLength": 512, "examples": [ "Basic256Sha256", "Aes256_Sha256_RsaPss", "http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256" ], "description": "The security policy URI to use for the endpoint connection. Defines the encryption and signing algorithms used for communication.", "errorMessage": { "type": "Must be a string or null", "minLength": "Security policy cannot be empty", "maxLength": "Security policy cannot exceed 512 characters" } }, "EndpointSecurityMode": { "type": "string", "enum": [ "None", "Sign", "SignAndEncrypt" ], "default": "SignAndEncrypt", "examples": [ "None", "Sign", "SignAndEncrypt" ], "description": "The security mode to use for the endpoint. None (no security), Sign (messages signed), or SignAndEncrypt (messages signed and encrypted).", "errorMessage": { "enum": "Must be one of: None, Sign, SignAndEncrypt" } }, "UseReverseConnect": { "type": "boolean", "default": false, "examples": [ true, false ], "description": "Use reverse connect to connect to the endpoint. Enable when the server needs to initiate the connection to the client.", "errorMessage": { "type": "Must be a boolean or omitted" } }, "RunAssetDiscovery": { "type": "boolean", "default": false, "examples": [ true, false ], "description": "Runs asset discovery on the endpoint. Enable to automatically discover and catalog available assets.", "errorMessage": { "type": "Must be a boolean or omitted" } }, "AssetTypes": { "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 256 }, "uniqueItems": true, "examples": [ [ "ns=1;s=PumpType", "nsu=https://opcfoundation.org/UA;i=2345" ] ], "description": "List of asset types to discover when RunAssetDiscovery is enabled. Each type must be unique.", "errorMessage": { "uniqueItems": "Asset types must be unique", "items": { "minLength": "Asset type name cannot be empty", "maxLength": "Asset type name cannot exceed 256 characters" } } }, "DumpConnectionDiagnostics": { "type": "boolean", "default": false, "examples": [ true, false ], "description": "Enables detailed server diagnostics logging for the connection. Enable for troubleshooting connection issues.", "errorMessage": { "type": "Must be a boolean or omitted" } } }, "additionalProperties": false, "dependencies": { "AssetTypes": [ "RunAssetDiscovery" ] } }, "datasets": { "limits": { "minimum": 0 }, "fields": { "dataSource": { "input": "required" }, "typeRef": { "input": "optional" } }, "destinations": { "supportedDestinations": [ "Mqtt", "BrokerStateStore" ], "defaultDestination": { "destination": "Mqtt", "topic": "{PublisherId}/{WriterGroupName}/{DataSetWriterName}", "qos": 1, "ttl": 0, "retain": "never" } }, "datasetConfigurationSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "DataSetEventModel", "description": "Dataset and event default and resource additional configuration model. Inherits all properties from PublishedNodesEntryModel and adds mapped properties for samplingInterval, publishingInterval, keyFrameCount, and StartInstance.", "type": "object", "properties": { "publishingInterval": { "type": "integer", "minimum": 0, "maximum": 4294967295, "examples": [ 100, 1000, 5000 ], "description": "The publishing interval in milliseconds for this dataset writer. Controls how frequently data is published.", "errorMessage": { "type": "Must be an integer in milliseconds or omitted", "minimum": "Must be non-negative", "maximum": "Must not exceed maximum supported interval (4294967295ms)" } }, "samplingInterval": { "type": "integer", "minimum": 0, "maximum": 4294967295, "examples": [ 100, 500, 1000 ], "description": "Default sampling interval in milliseconds for all data points in the dataset. Controls how frequently data is read from nodes.", "errorMessage": { "type": "Must be an integer in milliseconds or omitted", "minimum": "Must be non-negative", "maximum": "Must not exceed maximum supported interval (4294967295ms)" } }, "MessageEncoding": { "type": "string", "enum": [ "Json", "Avro" ], "default": "Json", "examples": [ "Json", "Avro" ], "description": "The encoding format to use for messages. Json (human-readable), Avro (raw format).", "errorMessage": { "enum": "Must be one of: Json, Uadp, Binary" } }, "keyFrameCount": { "type": "integer", "minimum": 1, "maximum": 1000, "examples": [ 1, 10, 100 ], "description": "Controls key frame insertion frequency in the message stream. Higher values reduce bandwidth but increase latency for new subscribers.", "errorMessage": { "type": "Must be an integer or omitted", "minimum": "Must be at least 1", "maximum": "Must not exceed 1000" } }, "Priority": { "type": "integer", "minimum": 0, "maximum": 255, "examples": [ 0, 100, 255 ], "description": "Priority of the writer subscription (0-255). Higher values indicate higher priority for resource allocation and processing.", "errorMessage": { "type": "Must be an integer or omitted", "minimum": "Must be non-negative", "maximum": "Must not exceed 255" } }, "DataSetClassId": { "type": "string", "format": "uuid", "description": "The optional dataset class id as it shall appear in dataset messages and dataset metadata." }, "DataSetDescription": { "type": "string", "description": "The optional description of the dataset." }, "DataSetExtensionFields": { "type": "object", "description": "Optional key-value pairs inserted into key frame and metadata messages in the same data set.", "additionalProperties": true }, "DefaultHeartbeatInterval": { "type": "integer", "minimum": 0, "maximum": 4294967295, "examples": [ 60000, 300000 ], "description": "The interval in milliseconds at which to publish heartbeat messages.", "errorMessage": { "type": "Must be an integer in milliseconds or omitted", "minimum": "Must be non-negative", "maximum": "Must not exceed maximum supported interval (4294967295ms)" } }, "DefaultHeartbeatBehavior": { "type": "string", "enum": [ "WatchChange", "Periodically", "None" ], "default": "WatchChange", "examples": [ "WatchChange", "Periodically", "None" ], "description": "Configures how heartbeat messages are handled for all nodes. WatchChange (on value changes), Periodically (fixed intervals), or None (disabled).", "errorMessage": { "enum": "Must be one of: WatchChange, Periodically, None" } }, "SendKeepAliveDataSetMessages": { "type": "boolean", "default": false, "examples": [ true, false ], "description": "Controls whether to send keep alive messages for this dataset. Enable to maintain connection health monitoring.", "errorMessage": { "type": "Must be a boolean value" } }, "MaxKeepAliveCount": { "type": "integer", "minimum": 0, "maximum": 1000, "examples": [ 3, 10, 20 ], "description": "Defines how many publishing timer expirations to wait before sending a keep-alive message. Larger values reduce traffic but increase detection time.", "errorMessage": { "type": "Must be an integer or omitted", "minimum": "Must be non-negative", "maximum": "Must not exceed 1000" } }, "DataSetWriterWatchdogBehavior": { "type": "string", "enum": [ "Restart", "Halt", "Continue" ], "default": "Restart", "examples": [ "Restart", "Halt", "Continue" ], "description": "Defines what action to take when the watchdog timer triggers. Restart (reinitialize writer), Halt (stop publishing), or Continue (keep running).", "errorMessage": { "enum": "Must be one of: Restart, Halt, Continue" } }, "OpcNodeWatchdogCondition": { "type": "string", "enum": [ "NoData", "Error", "Any" ], "default": "NoData", "examples": [ "NoData", "Error", "Any" ], "description": "Specifies the condition that triggers the watchdog behavior. NoData (no updates received), Error (error occurs), or Any (either condition).", "errorMessage": { "enum": "Must be one of: NoData, Error, Any" } }, "DisableSubscriptionTransfer": { "type": "boolean", "default": false, "examples": [ true, false ], "description": "Controls whether subscription transfer is disabled during reconnect. Enable to prevent subscription state transfer.", "errorMessage": { "type": "Must be a boolean or omitted" } }, "RepublishAfterTransfer": { "type": "boolean", "default": true, "examples": [ true, false ], "description": "Controls whether to republish missed values after a subscription is transferred during reconnect handling. Enable to ensure data consistency.", "errorMessage": { "type": "Must be a boolean or omitted" } } }, "additionalProperties": true }, "alternativeTypeName": { "singular": "DataSet", "plural": "DataSets" }, "dataPoints": { "limits": { "minimum": 1 }, "fields": { "dataSource": { "input": "required" }, "typeRef": { "input": "optional" } }, "dataPointConfigurationSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Data Set Data point configuration", "description": "Data point additional configuration model.", "type": "object", "properties": { "SamplingInterval": { "type": "integer", "minimum": 0, "maximum": 4294967295, "examples": [ 100, 1000, 5000 ], "description": "Server-side sampling rate in milliseconds. The value 0 means use the fastest practical rate.", "errorMessage": { "type": "Must be an integer in milliseconds or omitted", "minimum": "Must be non-negative", "maximum": "Must not exceed maximum supported interval (4294967295ms)" } }, "AttributeId": { "type": "string", "enum": [ "Value", "DataType", "AccessLevel", "ArrayDimensions", "BrowseName", "DisplayName", "Description", "WriteMask", "UserWriteMask", "IsAbstract", "Symmetric", "InverseName" ], "default": "Value", "examples": [ "Value", "DataType", "DisplayName" ], "description": "The OPC UA attribute to monitor on the node. Specifies which characteristic of the node to monitor.", "errorMessage": { "enum": "Must be a valid OPC UA attribute identifier" } }, "DataChangeTrigger": { "type": "string", "enum": [ "Status", "StatusValue", "StatusValueTimestamp" ], "default": "StatusValue", "examples": [ "Status", "StatusValue", "StatusValueTimestamp" ], "description": "Specifies what triggers value change notifications: Status (only status changes), StatusValue (status or value changes), or StatusValueTimestamp (status, value, or timestamp changes).", "errorMessage": { "enum": "Must be one of: Status, StatusValue, StatusValueTimestamp" } }, "QueueSize": { "type": "integer", "minimum": 1, "maximum": 65536, "examples": [ 1, 100, 1000 ], "description": "Size of the server-side queue for this monitored item. Larger queues consume more memory but provide better buffering.", "errorMessage": { "type": "Must be an integer or omitted", "minimum": "Must be at least 1", "maximum": "Must not exceed maximum queue size (65536)" } }, "DeadbandType": { "type": "string", "enum": [ "None", "Absolute", "Percent" ], "default": "None", "examples": [ "None", "Absolute", "Percent" ], "description": "Deadband type of the data change filter to apply. None (no filtering), Absolute (absolute value change), or Percent (percentage value change).", "errorMessage": { "enum": "Must be one of: None, Absolute, Percent" } }, "DeadbandValue": { "type": [ "number", "null" ], "minimum": 0, "examples": [ 0.1, 1.0, 5.0 ], "description": "Deadband value of the data change filter to apply. For Absolute type, this is the absolute change required. For Percent type, this is the percentage change required (0-100).", "errorMessage": { "type": "Must be a number or omitted", "minimum": "Must be non-negative" } }, "DiscardNew": { "type": "boolean", "default": false, "examples": [ true, false ], "description": "Controls queue overflow behavior for monitored items. If true, new values are discarded when queue is full. If false, oldest values are discarded." }, "RegisterNode": { "type": "boolean", "default": false, "examples": [ true, false ], "description": "Optimize node access using RegisterNodes service. Improves performance for frequently accessed nodes but consumes server resources.", "errorMessage": { "type": "Must be a boolean or omitted" } }, "UseCyclicRead": { "type": "boolean", "default": false, "examples": [ true, false ], "description": "Use periodic reads instead of monitored items. Enable for nodes that don't support subscriptions or for specific polling requirements. Required to be true when using CyclicReadMaxAge.", "errorMessage": { "type": "Must be a boolean or omitted" } }, "CyclicReadMaxAge": { "type": "integer", "minimum": 0, "maximum": 4294967295, "examples": [ 1000, 5000, 60000 ], "description": "Maximum age for cached values in cyclic reads (milliseconds). Values older than this are considered stale and will trigger a new read. Only used when UseCyclicRead is true.", "errorMessage": { "type": "Must be an integer in milliseconds or omitted", "minimum": "Must be non-negative", "maximum": "Must not exceed maximum supported age (4294967295ms)", "dependencies": "Requires UseCyclicRead to be true" } }, "HeartbeatInterval": { "type": "integer", "minimum": 0, "maximum": 4294967295, "examples": [ 60000, 300000 ], "description": "Node-specific heartbeat interval in milliseconds.", "errorMessage": { "type": "Must be an integer in milliseconds or omitted", "minimum": "Must be non-negative", "maximum": "Must not exceed maximum supported interval (4294967295ms)" } }, "HeartbeatBehavior": { "type": "string", "enum": [ "WatchChange", "Periodically", "None" ], "default": "WatchChange", "examples": [ "WatchChange", "Periodically", "None" ], "description": "Controls heartbeat message generation for this node: WatchChange (on value changes), Periodically (at fixed intervals), or None (disabled).", "errorMessage": { "enum": "Must be one of: WatchChange, Periodically, None" } }, "SkipFirst": { "type": "boolean", "default": false, "examples": [ true, false ], "description": "Controls handling of initial value notification. If true, skips the first value after subscription creation to avoid initial value spikes.", "errorMessage": { "type": "Must be a boolean or omitted" } }, "IndexRange": { "type": "string", "pattern": "^\\d+(:?\\d+)?$", "examples": [ "0", "1:3", "2:5" ], "description": "Range specification for array or string values. Use single index (e.g., '1') or range (e.g., '1:3'). First element is at index 0.", "errorMessage": { "pattern": "Must be a single index or range in format 'start:end'" } } }, "required": [], "additionalProperties": true, "dependencies": { "CyclicReadMaxAge": { "properties": { "UseCyclicRead": { "enum": [ true ] } }, "required": [ "UseCyclicRead" ] } } }, "alternativeTypeName": { "singular": "NodeId", "plural": "NodeIds" } } }, "eventGroups": { "limits": { "minimum": 0 }, "fields": { "dataSource": { "input": "optional" }, "typeRef": { "input": "optional" } }, "alternativeTypeName": { "singular": "EventGroup", "plural": "EventGroups" }, "eventGroupConfigurationSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Event group configuration", "description": "Event group additional configuration model.", "type": "object", "properties": {} }, "events": { "limits": { "minimum": 0 }, "fields": { "dataSource": { "input": "required" }, "typeRef": { "input": "optional" } }, "destinations": { "supportedDestinations": [ "Mqtt" ], "defaultDestination": { "destination": "Mqtt", "topic": "{PublisherId}/{WriterGroupName}/{EventGroupName}", "qos": 1, "ttl": 0, "retain": "never" } }, "eventConfigurationSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Event configuration model", "description": "Event resource additional configuration model.", "type": "object", "properties": { "QueueSize": { "type": "integer", "minimum": 1, "maximum": 65536, "examples": [ 1, 100, 1000 ], "description": "Size of the server-side queue for this monitored item. Larger queues consume more memory but provide better buffering.", "errorMessage": { "type": "Must be an integer or omitted", "minimum": "Must be at least 1", "maximum": "Must not exceed maximum queue size (65536)" } }, "PublishingInterval": { "type": "integer", "minimum": 0, "maximum": 4294967295, "examples": [ 100, 1000, 5000 ], "description": "The publishing interval in milliseconds for this dataset writer. Controls how frequently data is published.", "errorMessage": { "type": "Must be an integer in milliseconds or omitted", "minimum": "Must be non-negative", "maximum": "Must not exceed maximum supported interval (4294967295ms)" } }, "DiscardNew": { "type": "boolean", "default": false, "examples": [ true, false ], "description": "Controls queue overflow behavior for monitored items. If true, new values are discarded when queue is full. If false, oldest values are discarded." }, "EventFilter": { "$ref": "#/definitions/EventFilterModel", "description": "Event Filter to apply. When specified the node is assumed to be an event notifier node to subscribe to." }, "ConditionHandling": { "$ref": "#/definitions/ConditionHandlingOptionsModel", "description": "Settings for pending condition handling." }, "SkipFirst": { "type": "boolean", "default": false, "examples": [ true, false ], "description": "Controls handling of initial value notification. If true, skips the first value after subscription creation to avoid initial value spikes.", "errorMessage": { "type": "Must be a boolean or omitted" } }, "MessageEncoding": { "type": "string", "enum": [ "Json", "Avro" ], "default": "Json", "examples": [ "Json", "Avro" ], "description": "The encoding format to use for messages. Json (human-readable), Avro (raw format).", "errorMessage": { "enum": "Must be one of: Json, Uadp, Binary" } }, "Priority": { "type": "integer", "minimum": 0, "maximum": 255, "examples": [ 0, 100, 255 ], "description": "Priority of the writer subscription (0-255). Higher values indicate higher priority for resource allocation and processing.", "errorMessage": { "type": "Must be an integer or omitted", "minimum": "Must be non-negative", "maximum": "Must not exceed 255" } }, "DataSetClassId": { "type": "string", "format": "uuid", "description": "The optional dataset class id as it shall appear in dataset messages and dataset metadata." }, "DataSetDescription": { "type": "string", "description": "The optional description of the dataset." }, "SendKeepAliveDataSetMessages": { "type": "boolean", "default": false, "examples": [ true, false ], "description": "Controls whether to send keep alive messages for this dataset. Enable to maintain connection health monitoring.", "errorMessage": { "type": "Must be a boolean value" } }, "MaxKeepAliveCount": { "type": "integer", "minimum": 0, "maximum": 1000, "examples": [ 3, 10, 20 ], "description": "Defines how many publishing timer expirations to wait before sending a keep-alive message. Larger values reduce traffic but increase detection time.", "errorMessage": { "type": "Must be an integer or omitted", "minimum": "Must be non-negative", "maximum": "Must not exceed 1000" } }, "DataSetWriterWatchdogBehavior": { "type": "string", "enum": [ "Restart", "Halt", "Continue" ], "default": "Restart", "examples": [ "Restart", "Halt", "Continue" ], "description": "Defines what action to take when the watchdog timer triggers. Restart (reinitialize writer), Halt (stop publishing), or Continue (keep running).", "errorMessage": { "enum": "Must be one of: Restart, Halt, Continue" } }, "OpcNodeWatchdogCondition": { "type": "string", "enum": [ "NoData", "Error", "Any" ], "default": "NoData", "examples": [ "NoData", "Error", "Any" ], "description": "Specifies the condition that triggers the watchdog behavior. NoData (no updates received), Error (error occurs), or Any (either condition).", "errorMessage": { "enum": "Must be one of: NoData, Error, Any" } }, "DisableSubscriptionTransfer": { "type": "boolean", "default": false, "examples": [ true, false ], "description": "Controls whether subscription transfer is disabled during reconnect. Enable to prevent subscription state transfer.", "errorMessage": { "type": "Must be a boolean or omitted" } }, "RepublishAfterTransfer": { "type": "boolean", "default": true, "examples": [ true, false ], "description": "Controls whether to republish missed values after a subscription is transferred during reconnect handling. Enable to ensure data consistency.", "errorMessage": { "type": "Must be a boolean or omitted" } } }, "additionalProperties": true, "definitions": { "EventFilterModel": { "type": "object", "description": "Event filter for OPC UA event monitoring.", "properties": { "whereClause": { "$ref": "#/definitions/ContentFilterModel", "description": "Where clause for event filtering." }, "typeDefinitionId": { "type": "string", "description": "Simple event Type definition node id." } }, "additionalProperties": false }, "ContentFilterModel": { "type": "object", "description": "Content filter for event filtering (structure not detailed in provided context).", "properties": {}, "additionalProperties": true }, "ConditionHandlingOptionsModel": { "type": "object", "description": "Condition handling options", "properties": { "updateInterval": { "type": "integer", "minimum": 0, "description": "Time interval for sending pending interval updates in seconds." }, "snapshotInterval": { "type": "integer", "minimum": 0, "description": "Time interval for sending pending interval snapshot in seconds." } }, "additionalProperties": false } } }, "alternativeTypeName": { "singular": "Event", "plural": "Events" } } }, "managementGroups": { "limits": { "minimum": 0 }, "fields": { "dataSource": { "input": "optional" }, "typeRef": { "input": "optional" } }, "managementGroupConfigurationSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Service configuration", "description": "Service additional configuration model.", "type": "object", "properties": {} }, "alternativeTypeName": { "singular": "Service", "plural": "Services" }, "managementGroupActions": { "limits": { "minimum": 0 }, "fields": { "targetUri": { "input": "required" }, "typeRef": { "input": "optional" } }, "actionConfigurationSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "title": "Service call configuration model", "description": "Service call additional configuration model.", "type": "object", "properties": {} }, "alternativeTypeName": { "singular": "Service Call", "plural": "Service Calls" } } } } ], "inboundEndpointAlternativeTypeName": { "singular": "OPC UA Server", "plural": "OPC UA Servers" }, "endpointsEnabledByDefault": true, "isPreview": true, "recommendedAllocationPolicy": "bucketized", "recommendedReplicas": 1, "connectorConfigurationKeys": [ { "key": "UseFileChangePolling", "description": "Poll for file changes instead of using a file system watcher.\nUse this setting when the underlying file system does not support file system notifications such as in some docker container setups.\nDefault: `false`\n" }, { "key": "PublisherId", "description": "Sets the publisher id of the publisher.\nDefault: `not set` which results in the IoT edge identity being used \n" }, { "key": "SiteId", "description": "Sets the site name of the publisher module.\nDefault: `not set` \n" }, { "key": "ApiKey", "description": "Sets the api key that must be used to authenticate calls on the publisher REST endpoint.\nDefault: `not set` (Key will be generated if not available) \n" }, { "key": "DisableOpenApiEndpoint", "description": "Disable the OPC Publisher Open API endpoint exposed by the built-in HTTP server.\nDefault: `false` (enabled).\n" }, { "key": "UseStandardsCompliantEncoding", "description": "Use strict OPC UA standard compliance. It is recommended to run the publisher in compliant mode for best interoperability.\nBe aware that explicitly specifying other command line options can result in non-comnpliance despite this option being set.\nDefault: `false` for backwards compatibility (2.5.x - 2.8.x)\n" }, { "key": "DefaultNamespaceFormat", "description": "The format to use when serializing node ids and qualified names containing a namespace uri into a string.\nAllowed values:\n `Uri`\n `Index`\n `Expanded`\n `ExpandedWithNamespace0`\nDefault: `Expanded` if `-c` is specified, otherwise `Uri` for backwards compatibility.\n" }, { "key": "MessagingMode", "description": "The messaging mode for messages\nAllowed values:\n `PubSub`\n `Samples`\n `FullNetworkMessages`\n `FullSamples`\n `DataSetMessages`\n `SingleDataSetMessage`\n `DataSets`\n `SingleDataSet`\n `RawDataSets`\n `SingleRawDataSet`\nDefault: `PubSub` if `-c` is specified, otherwise `Samples` for backwards compatibility.\n" }, { "key": "WriteValueWhenDataSetHasSingleEntry", "description": "When a data set has a single entry the encoder will write only the value of a data set entry and omit the key.\nThis is not compliant with OPC UA Part 14.\nDefault: `false`.\n" }, { "key": "MessageEncoding", "description": "The message encoding for messages\nAllowed values:\n `Uadp`\n `Json`\n `Xml`\n `Avro`\n `IsReversible`\n `JsonReversible`\n `IsGzipCompressed`\n `JsonGzip`\n `AvroGzip`\n `JsonReversibleGzip`\nDefault: `Json`.\n" }, { "key": "BatchTriggerInterval", "description": "The network message publishing interval in milliseconds. Determines the publishing period at which point messages are emitted.\nWhen `--bs` (`BatchSize`) is 1 and `--bi` is set to 0 batching is disabled.\nDefault: `10000` (10 seconds).\nAlso can be set using `BatchTriggerInterval` environment variable in the form of a duration string in the form `[d.]hh:mm:ss[.fffffff]`.\n" }, { "key": "BatchSize", "description": "The number of incoming OPC UA subscription notifications to collect until sending a network messages. When `--bs` (`BatchSize`) is set to 1 and `--bi` (`BatchTriggerInterval`) is 0 batching is disabled and messages are sent as soon as notifications arrive.\nDefault: `50`.\n" }, { "key": "RemoveDuplicatesFromBatch", "description": "Use this option to remove values with the same node id from batch messages in legacy `Samples` mode. Sends only the latest value as per the value's source timestamp.\nOnly applies to `Samples` mode, otherwise this setting is ignored.\nDefault: `false` (keep all duplicate values).\n" }, { "key": "MessageTimestamp", "description": "The value to set as as the timestamp property of messages during encoding (if the encoding supports writing message timestamps).\nAllowed values:\n `CurrentTimeUtc`\n `PublishTime`\n `EncodingTimeUtc`\nDefault: `CurrentTimeUtc` to use the time when the message was created in OPC Publisher.\n" }, { "key": "MaxNodesPerDataSet", "description": "Maximum number of nodes within a Subscription. When there are more nodes configured for a data set writer, they will be added to new subscriptions. This also affects metadata message size. \nDefault: `1000`.\n" }, { "key": "DefaultKeyFrameCount", "description": "The default number of delta messages to send until a key frame message is sent. If 0, no key frame messages are sent, if 1, every message will be a key frame. \nDefault: `0`.\n" }, { "key": "EnableDataSetKeepAlives", "description": "Enables sending keep alive messages triggered by writer subscription's keep alive notifications. This setting can be used to enable the messaging profile's support for keep alive messages.\nIf the chosen messaging profile does not support keep alive messages this setting is ignored.\nDefault: `false` (to save bandwidth).\n" }, { "key": "SendDataSetKeepAlivesAsKeyFrame", "description": "When the sending of keep alive messages is enabled determines whether the empty keep alive message will be promoted to a key frame messages\nDefault: `false`.\n" }, { "key": "DefaultMetaDataUpdateTime", "description": "Default value in milliseconds for the metadata send interval which determines in which interval metadata is sent.\nEven when disabled, metadata is still sent when the metadata version changes unless `--mm=*Samples` (`MessagingMode)=*Samples`) is set in which case this setting is ignored. Only valid for network message encodings. \nDefault: `0` which means periodic sending of metadata is disabled.\n" }, { "key": "DisableDataSetMetaData", "description": "Disables sending any metadata when metadata version changes. This setting can be used to also override the messaging profile's default support for metadata sending.\nIt is recommended to disable sending metadata when too many nodes are part of a data set as this can slow down start up time.\nDefault: `False` if the messaging profile selected supports sending metadata and `--strict` (`UseStandardsCompliantEncoding`) is set but not '--dct' (`DisableComplexTypeSystem`), `True` otherwise.\n" }, { "key": "AsyncMetaDataLoadTimeout", "description": "The default duration in seconds a publish request should wait until the meta data is loaded.\nLoaded metadata guarantees a metadata message is sent before the first message is sent but loading of metadata takes time during subscription setup. Set to `0` to block until metadata is loaded.\nOnly used if meta data is supported and enabled.\nDefault: `5000` milliseconds.\n" }, { "key": "PreferAvroOverJsonSchema", "description": "Publish Avro schema even for Json encoded messages. Automatically enables publishing schemas as if `--ps` was set.\nDefault: `false`.\n" }, { "key": "MaxNetworkMessageSendQueueSize", "description": "The maximum number of messages to buffer on the send path before messages are dropped.\nDefault: `4096`\n" }, { "key": "DefaultWriterGroupPartitionCount", "description": "The number of partitions to split the writer group into. Each partition represents a data flow to the transport sink. The partition is selected by topic hash.\nDefault: `0` (partitioning is disabled)\n" }, { "key": "HttpServerPort", "description": "The port on which the http server of OPC Publisher is listening.\nDefault: `9072` if no value is provided.\n" }, { "key": "UnsecureHttpServerPort", "description": "Allow unsecure access to the REST api of OPC Publisher. A port can be specified if the default port 9071 is not desired.\nDo not enable this in production as it exposes the Api Key on the network.\nDefault: `disabled`, if specified without a port `9071` port is used.\n" }, { "key": "RenewTlsCertificateOnStartup", "description": "If set a new tls certificate is created during startup updating any previously created ones.\nDefault: `false`.\n" }, { "key": "DefaultSamplingInterval", "description": "Default value in milliseconds to request the servers to sample values. This value is used if an explicit sampling interval for a node was not configured. \nDefault: `1000`.\nAlso can be set using `DefaultSamplingInterval` environment variable in the form of a duration string in the form `[d.]hh:mm:ss[.fffffff]`.\n" }, { "key": "DefaultPublishingInterval", "description": "Default value in milliseconds for the publishing interval setting of a subscription created with an OPC UA server. This value is used if an explicit publishing interval was not configured.\nWhen setting to `0` the server decides the lowest publishing interval it can support.\nDefault: `1000`.\nAlso can be set using `DefaultPublishingInterval` environment variable in the form of a duration string in the form `[d.]hh:mm:ss[.fffffff]`.\n" }, { "key": "EnableImmediatePublishing", "description": "By default OPC Publisher will create a subscription with publishing disabled and only enable it after it has filled it with all configured monitored items. Use this setting to create the subscription with publishing already enabled.\nDefault: `false`.\n" }, { "key": "DefaultKeepAliveCount", "description": "Specifies the default number of publishing intervals before a keep alive is returned with the next queued publishing response.\nDefault: `auto set based on publishing interval`.\n" }, { "key": "DefaultLifetimeCount", "description": "Default subscription lifetime count which is a multiple of the keep alive counter and when reached instructs the server to declare the subscription invalid.\nDefault: `auto set based on publishing interval`.\n" }, { "key": "DefaultQueueSize", "description": "Default queue size for all monitored items if queue size was not specified in the configuration.\nDefault: `1` (for backwards compatibility).\n" }, { "key": "AutoSetQueueSizes", "description": "(Experimental) Automatically calculate queue sizes for monitored items using the subscription publishing interval and the item's sampling rate as max(configured queue size, roundup(publishinginterval / samplinginterval)).\nNote that the server might revise the queue size down if it cannot handle the calculated size.\nDefault: `false` (disabled).\n" }, { "key": "DiscardNew", "description": "The publisher is using this as default value for the discard old setting of monitored item queue configuration. Setting to true will ensure that new values are dropped before older ones are drained. \nDefault: `false` (which is the OPC UA default).\n" }, { "key": "DefaultDataChangeTrigger", "description": "Default data change trigger for all monitored items configured in the published nodes configuration unless explicitly overridden.\nAllowed values:\n `Status`\n `StatusValue`\n `StatusValueTimestamp`\nDefault: `StatusValue` (which is the OPC UA default).\n" }, { "key": "DefaultMonitoredItemWatchdogSeconds", "description": "The subscription and monitored item watchdog timeout in seconds the subscription uses to check on late reporting monitored items unless overridden in the published nodes configuration explicitly.\nDefault: `not set` (watchdog disabled).\n" }, { "key": "DefaultMonitoredItemWatchdogCondition", "description": "The default condition when to run the action configured as the watchdog behavior. The condition can be overridden in the published nodes configuration.\nAllowed values:\n `WhenAllAreLate`\n `WhenAnyIsLate`\nDefault: `WhenAllAreLate` (if enabled).\n" }, { "key": "DefaultWatchdogBehavior", "description": "Default behavior of the subscription and monitored item watchdog mechanism unless overridden in the published nodes configuration explicitly.\nAllowed values:\n `Diagnostic`\n `Reset`\n `FailFast`\n `ExitProcess`\nDefault: `Diagnostic` (if enabled).\n" }, { "key": "DefaultSkipFirst", "description": "The publisher is using this as default value for the skip first setting of nodes configured without a skip first setting. A value of True will skip sending the first notification received when the monitored item is added to the subscription.\nDefault: `False` (disabled).\n" }, { "key": "RepublishAfterTransfer", "description": "Configure whether publisher republishes missed subscription notifications still in the server queue after transferring a subscription during reconnect handling.\nThis can result in out of order notifications after a reconnect but minimizes data loss.\nDefault: `False` (disabled).\n" }, { "key": "DefaultSamplingUsingCyclicRead", "description": "All nodes should be sampled using periodical client reads instead of subscriptions services, unless otherwise configured.\nDefault: `false`.\n" }, { "key": "MaxMonitoredItemPerSubscription", "description": "Max monitored items per subscription until the subscription is split.\nThis is used if the server does not provide limits in its server capabilities.\nDefault: `not set`.\n" }, { "key": "EnableSequentialPublishing", "description": "Set to false to disable sequential publishing in the protocol stack.\nDefault: `True` (enabled).\n" }, { "key": "SubscriptionManagementIntervalSeconds", "description": "The interval in seconds after which the publisher re-applies the desired state of the subscription to a session.\nDefault: `0` (only on configuration change).\n" }, { "key": "BadMonitoredItemRetryDelaySeconds", "description": "The delay in seconds after which nodes that were rejected by the server while added or updating a subscription or while publishing, are re-applied to a subscription.\nSet to 0 to disable retrying.\nDefault: `1800` seconds.\n" }, { "key": "InvalidMonitoredItemRetryDelaySeconds", "description": "The delay in seconds after which the publisher attempts to re-apply nodes that were incorrectly configured to a subscription.\nSet to 0 to disable retrying.\nDefault: `300` seconds.\n" }, { "key": "BadMonitoredItemRetryDelayMaxSeconds", "description": "The max delay in seconds between retrying nodes that were rejected by the server while added or updating a subscription or while publishing.\nWhen set an exponential retry policy is used with the `--bmr` (`BadMonitoredItemRetryDelaySeconds`) value as the starting delay.\nDefault: `not set`.\n" }, { "key": "InvalidMonitoredItemRetryDelayMaxSeconds", "description": "The max delay in seconds between retrying nodes that were incorrectly configured in the a subscription.\nWhen set an exponential retry policy is used with the `--inr` (`InvalidMonitoredItemRetryDelaySeconds`) value as the starting delay.\nDefault: `not set`.\n" }, { "key": "SubscriptionErrorRetryDelaySeconds", "description": "The delay in seconds between attempts to create a subscription in a session.\nSet to 0 to disable retrying.\nDefault: `2` seconds.\n" }, { "key": "DefaultUseReverseConnect", "description": "(Experimental) Use reverse connect for all endpoints in the published nodes configuration unless otherwise configured.\nDefault: `false`.\n" }, { "key": "DisableSubscriptionTransfer", "description": "Do not attempt to transfer subscriptions when reconnecting but re-establish the subscription.\nDefault: `false`.\n" }, { "key": "DisableComplexTypeSystem", "description": "Never load the complex type system for any connections that are required for subscriptions.\nThis setting not just disables meta data messages but also prevents transcoding of unknown complex types in outgoing messages.\nDefault: `false`.\n" }, { "key": "DisableSessionPerWriterGroup", "description": "Disable creating a separate session per writer group. Instead sessions are re-used across writer groups.\nDefault: `False`.\n" }, { "key": "IgnoreConfiguredPublishingIntervals", "description": "Always use the publishing interval provided via `--op` (DefaultPublishingInterval) and ignore all publishing interval settings in the configuration.\nCombine with `--op=0` ((DefaultPublishingInterval)=0) to let the server use the lowest publishing interval it can support.\nDefault: `False` (disabled).\n" }, { "key": "AutoAcceptUntrustedCertificates", "description": "The publisher accepts untrusted certificates presented by a server it connects to.\nThis does not include servers presenting bad certificates or certificates that fail chain validation. These errors cannot be suppressed and connection will always be rejected.\nWARNING: This setting should never be used in production environments!\n" }, { "key": "RejectUnknownRevocationStatus", "description": "Set this to `False` to accept certificates presented by a server that have an unknown revocation status.\nWARNING: This setting should never be used in production environments!\nDefault: `True`.\n" }, { "key": "CreateSessionTimeout", "description": "Amount of time in seconds to wait until a session is connected.\nDefault: `5` seconds.\n" }, { "key": "MinReconnectDelay", "description": "The minimum amount of time in milliseconds to wait reconnection of session is attempted again.\nDefault: `1000` milliseconds.\n" }, { "key": "MaxReconnectDelay", "description": "The maximum amount of time in milliseconds to wait between reconnection attempts of the session.\nDefault: `60000` milliseconds.\n" }, { "key": "DefaultSessionTimeout", "description": "Maximum amount of time in seconds that a session should remain open by the OPC server without any activity (session timeout). Requested from the OPC server at session creation.\nDefault: `60` seconds.\n" }, { "key": "KeepAliveInterval", "description": "The interval in seconds the publisher is sending keep alive messages to the OPC servers on the endpoints it is connected to.\nDefault: `10` seconds.\n" }, { "key": "DefaultServiceCallTimeout", "description": "Maximum amount of time in seconds that a service call should take before it is being cancelled.\nThis value can be overridden in the request header.\nDefault: `180` seconds.\n" }, { "key": "DefaultConnectTimeout", "description": "Maximum amount of time in seconds that a service call should wait for a connected session to be used.\nThis value can be overridden in the request header.\nDefault: `not set` (in this case the default service call timeout value is used).\n" }, { "key": "OperationTimeout", "description": "The operation service call timeout of individual service requests to the server in milliseconds. As opposed to the `--sct` (DefaultServiceCallTimeout) timeout, this is the timeout hint provided to the server in every request.\nThis value can be overridden in the request header.\nDefault: `120000` milliseconds.\n" }, { "key": "LingerTimeoutSeconds", "description": "Amount of time in seconds to delay closing a client and underlying session after the a last service call.\nUse this setting to speed up multiple subsequent calls.\nDefault: `0` sec (no linger).\n" }, { "key": "ReverseConnectPort", "description": "The port to use when accepting inbound reverse connect requests from servers.\nDefault: `4840`.\n" }, { "key": "MaxNodesPerReadOverride", "description": "Limit max number of nodes to read in a single read request when batching reads or the server limit if less.\nDefault: `0` (using server limit).\n" }, { "key": "MaxNodesPerBrowseOverride", "description": "Limit max number of nodes per browse request when batching browse operations or the server limit if less.\nDefault: `0` (using server limit).\n" }, { "key": "NodeCacheCapacity", "description": "The max size of the node caches used in the complex type system.\nThere are caches (values, nodes, references).\nDefault: `4096`.\n" }, { "key": "NodeCacheTimeout", "description": "The timeout of a node cache entries if not used in milliseconds.\nDefault: `3600`.\n" }, { "key": "MinPublishRequests", "description": "Minimum number of publish requests to queue once subscriptions are created in the session.\nDefault: `2`.\n" }, { "key": "PublishRequestsPerSubscriptionPercent", "description": "Percentage ratio of publish requests per subscriptions in the session in percent up to the number configured using `--xpr` (MaxPublishRequests).\nDefault: `100`% (1 request per subscription).\n" }, { "key": "MaxPublishRequests", "description": "Maximum number of publish requests to every queue once subscriptions are created in the session.\nDefault: `10`.\n" }, { "key": "DisableComplexTypePreloading", "description": "Complex types (structures, enumerations) a server exposes are preloaded from the server after the session is connected. In some cases this can cause problems either on the client or server itself. Use this setting to disable pre-loading support.\nNote that since the complex type system is used for meta data messages it will still be loaded at the time the subscription is created, therefore also disable meta data support if you want to ensure the complex types are never loaded for an endpoint.\nDefault: `false`.\n" }, { "key": "SecurityTokenLifetime", "description": "OPC UA Stack Transport Secure Channel - Security token lifetime in milliseconds.\nDefault: `3600000` (1h).\n" }, { "key": "ChannelLifetime", "description": "OPC UA Stack Transport Secure Channel - Channel lifetime in milliseconds.\nDefault: `300000` (5 min).\n" }, { "key": "MaxBufferSize", "description": "OPC UA Stack Transport Secure Channel - Max buffer size.\nDefault: `65535` (64KB -1).\n" }, { "key": "MaxMessageSize", "description": "OPC UA Stack Transport Secure Channel - Max message size.\nDefault: `4194304` (4 MB).\n" }, { "key": "MaxArrayLength", "description": "OPC UA Stack Transport Secure Channel - Max array length.\nDefault: `65535` (64KB - 1).\n" }, { "key": "MaxStringLength", "description": "The max length of a string opc can transmit/receive over the OPC UA secure channel.\nDefault: `130816` (128KB - 256).\n" }, { "key": "MaxByteStringLength", "description": "OPC UA Stack Transport Secure Channel - Max byte string length.\nDefault: `1048576` (1MB).\n" }, { "key": "ApplicationUri", "description": "Application URI as per OPC UA definition inside the OPC UA client application configuration presented to the server.\nDefault: `not set`.\n" }, { "key": "ProductUri", "description": "The Product URI as per OPC UA definition inside the OPC UA client application configuration presented to the server.\nDefault: `not set`.\n" }, { "key": "RejectSha1SignedCertificates", "description": "If set to `False` OPC Publisher will accept SHA1 certificates which have been officially deprecated and are unsafe to use.\nNote: Set this to `False` to support older equipment that uses Sha1 signed certificates rather than using no security.\nDefault: `True`.\n" }, { "key": "MinimumCertificateKeySize", "description": "Minimum accepted certificate size.\nNote: It is recommended to this value to the highest certificate key size possible based on the connected OPC UA servers.\nDefault: 1024.\n" }, { "key": "AddAppCertToTrustedStore", "description": "Set to `False` to disable adding the publisher's own certificate to the trusted store automatically.\nDefault: `True`.\n" }, { "key": "ApplicationCertificateSubjectName", "description": "The subject name for the app cert.\nDefault: `CN=, C=DE, S=Bav, O=Microsoft, DC=localhost`.\n" }, { "key": "ApplicationName", "description": "The name for the app (used during OPC UA authentication).\nDefault: `Microsoft.Azure.IIoT`\n" }, { "key": "TryConfigureFromExistingAppCert", "description": "Automatically set the application subject name, host name and application uri from the first valid application certificate found in the application certificate store path.\nIf the chosen certificate is valid, it will be used, otherwise a new, self-signed certificate with the information will be created.\nDefault: `false`.\n" }, { "key": "LogLevel", "description": "The loglevel to use.\nAllowed values:\n `Trace`\n `Debug`\n `Information`\n `Warning`\n `Error`\n `Critical`\n `None`\nDefault: `Information`.\n" }, { "key": "DiagnosticsInterval", "description": "Produce publisher diagnostic information at this specified interval in seconds.\nBy default diagnostics are written to the OPC Publisher logger (which requires at least --loglevel or environment variable `LogLevel` =`information`) unless configured differently using `--pd` (DiagnosticsTarget).\n`0` disables diagnostic output.\nDefault:60000 (60 seconds).\nAlso can be set using `DiagnosticsInterval` environment variable in the form of a duration string in the form `[d.]hh:mm:ss[.fffffff]`\".\n" }, { "key": "DiagnosticsTarget", "description": "Configures how to emit diagnostics information at the `--di` (DiagnosticsInterval) configured interval.\nUse this to for example emit diagnostics as events to the event topic template instead of the console.\nAllowed values:\n `Logger`\n `Events`\nDefault: `Logger`.\n" }, { "key": "DisableResourceMonitoring", "description": "Disable resource monitoring as part of the diagnostics output and metrics.\nDefault: `false` (enabled).\n" }, { "key": "DebugLogNotifications", "description": "Log ingress subscription notifications at Informational level to aid debugging.\nDefault: `disabled`.\n" }, { "key": "DebugLogNotificationsWithHeartbeat", "description": "Include heartbeats in notifications log.\nIf set also implicitly enables debug logging via `--ln` (DebugLogNotifications).\nDefault: `disabled`.\n" }, { "key": "DebugLogNotificationsFilter", "description": "Only log notifications where the data set field name, subscription name, or data set name match the provided regular expression pattern.\nIf set implicitly enables debug logging via `--ln` (DebugLogNotifications).\nDefault: `null` (matches all).\n" }, { "key": "DebugLogEncodedNotifications", "description": "Log encoded subscription and monitored item notifications at Informational level to aid debugging.\nDefault: `disabled`.\n" }, { "key": "OpcUaKeySetLogFolderName", "description": "Writes negotiated symmetric keys for all running client connection to this file.\nThe file can be loaded by Wireshark 4.3 and used to decrypt encrypted channels when analyzing network traffic captures.\nNote that enabling this feature presents a security risk!\nDefault: `disabled`.\n" } ] } ================================================ FILE: deploy/kubernetes/readme.md ================================================ # Azure IoT Operations Development Environment Setup This guide explains how to set up a local development environment for Azure IoT Operations (AIO) and how to install OPC Publisher as a Akri connector. > This functionality is **experimental**. OPC Publisher running as connector in Azure IoT Operations > is not supported by Microsoft. > **Use the Azure IoT Operations built in OPC UA connectivity support for production!** ## Cluster Setup The [`cluster-setup.ps1`](./cluster-setup.ps1) PowerShell script sets up a local Kubernetes cluster and connects it to Azure Arc. It is a convenient way to boot strap a Azure IoT Operations cluster on Windows targeting K3D, MicroK8s, Minikube and Kind. > Linux is currently not supported / has not been tested. > Currently only K3D and MicroK8s have been tested. > Only version 1.2 or higher of Azure IoT Operations is supported which is currently in > preview. ### Prerequisites - Windows 11 with PowerShell. - Azure subscription with required permissions - All other dependencies are installed, however, if you intend to use microk8s install it using the [public installer](https://microk8s.io/docs/install-windows) **including multipass** before running the script. > The script must be run as administrator and is not intended to set up production clusters. ### Using the cluster setup script ```powershell # Basic usage .\cluster-setup.ps1 -Name # Full syntax with all parameters .\cluster-setup.ps1 ` -Name ` # Required: Cluster and resource name [-InstanceName ] ` # Optional: AIO instance name (default: same as cluster) [-InstanceNamespace ] ` # Optional: K8s namespace (default: azure-iot-operations) [-ResourceGroup ] ` # Optional: Resource group (default: same as cluster) [-SharedFolderPath ] ` # Optional: Shared storage path (default: C:\Shared) [-Location ] ` # Optional: Azure region (default: westus) [-ClusterType ] ` # Optional: microk8s, kind, k3d, minikube (default: microk8s) [-Connector ] ` # Optional: None, Official, Local, Debug (default: Official) [-OpsVersion ] ` # Optional: Azure IoT Operations version [-OpsTrain ] ` # Optional: integration, stable, dev (default: integration) [-Force] # Optional: Force reinstallation # Examples # Basic setup with defaults .\cluster-setup.ps1 -Name "myCluster" # Custom configuration with different cluster type .\cluster-setup.ps1 ` -Name "myCluster" ` -ClusterType "kind" ` -InstanceNamespace "iot-ops" ` -Connector "Local" # Development setup with specific version and train .\cluster-setup.ps1 ` -Name "devCluster" ` -OpsVersion "1.2.96" ` -OpsTrain "dev" ` -Connector "Debug" ` -Force ``` ### Akri and Azure Asset and Device Registry Integration The cluster setup script by default deploys the officially built OPC Publisher as a Akri connector into the cluster. The connector will handle publishing of data that is configured in Assets that are bound to a device endpoint. These can be created in ADR using the AZ CLI as well as the Digital Operations experience user interface. There are 2 devices installed by default pointing to 2 running OPC PLC simulation servers running in the cluster. The connector will discover assets in OPC PLC via the AssetTypes configuration option on the device "none" endpoint. It will also add all endpoints of the server to the device and publishes a discovered device resource to Akri with the additional endpoints and the same identifier as the original device. For convenience the script also enables the insecure listener on the MQTT broker. Forward the insecure port (1883) locally using the `.\debug\forward-mq.ps1`. ### Onboarding discovered Assets and Devices The import or onboarding flow can be managed using the Digital Operations Experience user interface. The `.\iotops\adr-tool.ps1` powershell script can be used to effectively copy the discovered resource into Azure Device Registry and allows you to bypass the DOE experience. #### Using the onboarding script ```powershell # Basic usage .\iotops\adr-tool.ps1 -AdrNamespaceName -ResourceGroup # Full syntax with all options .\iotops\adr-tool.ps1 ` -Action Onboard ` -AdrNamespaceName ` # Required: ADR namespace name -ResourceGroup ` # Required: Azure resource group [-SubscriptionId ] ` # Optional: Azure subscription ID [-Location ] ` # Optional: Azure region (default: westus) [-TenantId ] ` # Optional: Azure tenant ID [-RunOnce] ` # Optional: Run once and exit [-Force] ` # Optional: Force update existing resources [-SkipLogin] # Optional: Skip Azure login ``` You can run the script in a loop or just once. Note that the discovered devices and assets will take several minutes to be synchronized into Azure and that can happen in any order. Run the script again or in loop mode to bring all resources in and back down to the cluster. ## Advanced The debug folder contains scripts to build and debug the OPC Publisher. ### Adding more sample servers to the cluster The `.\simulation\deploy.ps1` script allows you to deploy not just OPC PLC but also the test server included in this repository. It also allows you to add other simulations. For more information check out the script help. ### Building OPC Publisher and deploying into the cluster You can use [`.\debug\build.ps1`](./debug/build.ps1) to build a debug version. ```powershell # Basic usage .\debug\build.ps1 # Full syntax with all parameters .\debug\build.ps1 ` [-Configuration ] ` # Optional: Debug or Release (default: Debug) [-ClusterType ] ` # Optional: Target cluster type (default: microk8s) [-StartDebugger] # Optional: Start debugger after build # Examples # Build with default settings (Debug configuration) .\debug\build.ps1 # Build release configuration for specific cluster .\debug\build.ps1 ` -Configuration "Release" ` -ClusterType "kind" # Build and start debugging session .\debug\build.ps1 ` -Configuration "Debug" ` -StartDebugger ``` The script builds the OPC Publisher and starts the `debug.ps1` script pointing to the built container. Debugging is described in the next section. ### Attaching the Debugger Use [`.\debug\debug.ps1`](./debug/debug.ps1) to attach the debugger to the running OPC Publisher that can be connected to the Visual Studio 2022 or Visual Studio Code debugger: ```powershell # Basic usage (interactive) .\debug\debug.ps1 # Full syntax with all parameters .\debug\debug.ps1 ` [-PodName ] ` # Optional: Target pod name (prompts if omitted) [-ContainerName ] ` # Optional: Target container name (prompts if omitted) [-Namespace ] ` # Optional: K8s namespace (default: azure-iot-operations) [-ClusterType ] ` # Optional: Cluster type (default: microk8s) [-Image ] ` # Optional: Debug image to replace in pod [-Fork] # Optional: Create new pod instead of modifying existing # Examples # Interactive debugging (prompts for pod and container) .\debug\debug.ps1 # Debug specific pod and container .\debug\debug.ps1 ` -PodName "opc-publisher" ` -ContainerName "publisher" # Debug with custom namespace and image .\debug\debug.ps1 ` -PodName "opc-publisher" ` -Namespace "iot-debug" ` -Image "debug-publisher:latest" ` -Fork ``` Once the debugger is attached you can open the solution file in Visual Studio 2022 and attach to the selected container using a SSH connection to localhost:50000. ================================================ FILE: deploy/kubernetes/simulation/deploy.ps1 ================================================ <# .SYNOPSIS Deploys OPC UA simulation servers in a Kubernetes cluster and registers them with Azure IoT Operations. .DESCRIPTION This script deploys a specified number of OPC UA simulation servers using Helm and registers them as devices in Azure IoT Operations. Each server is configured with specific endpoint settings and asset discovery capabilities. .NOTES DO NOT USE FOR PRODUCTION SYSTEMS. This script is intended for development and testing purposes only. .PARAMETER SimulationName The type of simulation to deploy. Currently supports "opc-plc" "umati", "umati-public" and "opc-test". Default is "opc-plc". .PARAMETER Count Number of simulation servers to deploy. .PARAMETER AdrNamespaceName The Azure IoT Operations namespace to deploy the simulation devices into. Must exist already. .PARAMETER Namespace The Kubernetes namespace where the simulation servers will be deployed. .PARAMETER ResourceGroup The resource group to create or use for the cluster. Default is the same as the cluster name. .PARAMETER SubscriptionId The subscription id to scope all activity to. .PARAMETER Location The Azure region where the resources will be created. .PARAMETER OpsInstanceName The name of the Azure IoT Operations instance to register the devices with. This instance must already exist. .PARAMETER DeploymentName The name of the Helm deployment for the simulation servers. .PARAMETER Force If specified, will force the creation of devices even if they already exist in the ADR namespace. .PARAMETER SkipLogin If specified, will skip the Azure login step. .PARAMETER ClusterType The type of Kubernetes cluster to deploy to. Valid values are "kind", "minikube", "k3d", and "microk8s". Optional and only needed if you want to deploy opc-test from local repo. #> param( [string] [Parameter(Mandatory = $true)] $DeploymentName, [string] [ValidateSet( "opc-plc", "opc-test", "umati", "umati-public" )] $SimulationName = "opc-plc", [int] $Count = 1, [string] [Parameter(Mandatory = $true)] $OpsInstanceName, [string] [Parameter(Mandatory = $true)] $ResourceGroup, [string] [Parameter(Mandatory = $true)] $AdrNamespaceName, [string] $SubscriptionId, [string] $TenantId, [string] $Location = "westus", [string] $Namespace, [string] [ValidateSet( "kind", "minikube", "k3d", "microk8s" )] $ClusterType ="microk8s", [switch] $AddServerType, [switch] $Force, [switch] $SkipLogin ) $ErrorActionPreference = "Continue" $scriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Path Import-Module $(Join-Path $(Join-Path $(Split-Path $scriptDirectory) "common") ` "cluster-utils.psm1") -Force $azVersion = (az version)[1].Split(":")[1].Split('"')[1] if ($azVersion -lt "2.74.0" -or !$azVersion) { Write-Host "Azure CLI version 2.74.0 or higher is required." ` -ForegroundColor Red exit -1 } # # Log into azure # if (-not $script:SkipLogin.IsPresent) { Write-Host "Log into Azure..." -ForegroundColor Cyan $loginParams = @( "--only-show-errors" ) if (![string]::IsNullOrWhiteSpace($TenantId)) { $loginParams += @("--tenant", $TenantId) } $session = (az login @loginParams) | ConvertFrom-Json if (-not $session) { Write-Host "Error: Login failed." -ForegroundColor Red exit -1 } if ([string]::IsNullOrWhiteSpace($SubscriptionId)) { $SubscriptionId = $session[0].id } if ([string]::IsNullOrWhiteSpace($TenantId)) { $TenantId = $session[0].tenantId } } # # Check adr namespace and azure iot instances exists # $adrNsResource = "/subscriptions/$($SubscriptionId)" $adrNsResource = "$($adrNsResource)/resourceGroups/$($ResourceGroup)" $adrNsResource = "$($adrNsResource)/providers/Microsoft.DeviceRegistry" $adrNsResource = "$($adrNsResource)/namespaces/$($AdrNamespaceName)" $errOut = $($ns = & { az rest --method get ` --url "$($adrNsResource)?api-version=2025-10-01" ` --headers "Content-Type=application/json" } | ConvertFrom-Json) 2>&1 if (!$ns -or !$ns.id) { Write-Host "ADR namespace $($adrNsResource) not found - $($errOut)." ` -ForegroundColor Red exit -1 } $errOut = $($iotOps = & { az iot ops show ` --resource-group $script:ResourceGroup ` --name $script:OpsInstanceName ` --subscription $SubscriptionId ` --only-show-errors --output json } | ConvertFrom-Json) 2>&1 if (!$iotOps) { Write-Host "Error: Failed to get IoT Operations instance - $($errOut)." ` -ForegroundColor Red exit -1 } # # Get list of namespaces and let user select one or validate the one provided # $namespaces = kubectl get namespaces --no-headers | ForEach-Object { $_.Split()[0] } if (-not $namespaces) { Write-Host "No namespaces found." -ForegroundColor Red exit -1 } if (-not $script:Namespace) { $script:Namespace = $namespaces | Out-GridView -Title "Select a namespace" -PassThru if (-not $script:Namespace) { Write-Host "No namespace selected." -ForegroundColor Yellow exit 0 } } else { if (-not $namespaces.Contains($script:Namespace)) { Write-Host "Namespace '$script:Namespace' not found." -ForegroundColor Red exit -1 } Write-Host "Using namespace '$script:Namespace'." -ForegroundColor Green } $displayName = "$($script:Count) $($script:SimulationName) simulation servers" if ($script:SimulationName -eq "umati-public") { Write-Host "Using public Umati server for simulation." -ForegroundColor Yellow $script:Count = 1 } elseif ($script:SimulationName -eq "opc-test" -and $script:ClusterType) { Write-Host "Building opc-test-server image for simulation." -ForegroundColor Yellow $projFile = "Azure.IIoT.OpcUa.Publisher.Testing" $projFile = "../../../src/$($projFile)/cli/$($projFile).Cli.csproj" $configuration = "Debug" $containerTag = "latest" $containerName = "iot/opc-ua-test-server" $containerImage = "$($containerName):$($containerTag)" Write-Host "Publishing $configuration Simulation as $containerImage..." ` -ForegroundColor Cyan dotnet restore $projFile -s https://api.nuget.org/v3/index.json dotnet publish $projFile -c $configuration --self-contained false --no-restore ` /t:PublishContainer -r linux-x64 /p:ContainerImageTag=$($containerTag) if (-not $?) { Write-Host "Error building opc-ua-test server image connector." -ForegroundColor Red exit -1 } Write-Host "$configuration container image $containerImage published successfully." ` -ForegroundColor Green Import-ContainerImage -ClusterType $script:ClusterType -ContainerImage $containerImage $helmPath = Join-Path $(Join-Path $scriptDirectory "helm") $script:SimulationName helm upgrade -i $script:DeploymentName "$($helmPath)" ` --namespace $script:Namespace ` --set simulations=$script:Count ` --set deployDefaultIssuerCA=false ` --set image=$($containerName) ` --set tag=$($containerTag) ` --set pullPolicy=IfNotPresent ` --wait if (-not $?) { Write-Host "Error deploying $($displayName) as $($script:DeploymentName)." ` -ForegroundColor Red exit -1 } Write-Host "Deployment of $($displayName) as $($script:DeploymentName) completed." ` -ForegroundColor Green } else { Write-Host "Deploying $($displayName) as $($script:DeploymentName)..." ` -ForegroundColor Cyan $helmPath = Join-Path $(Join-Path $scriptDirectory "helm") $script:SimulationName helm upgrade -i $script:DeploymentName "$($helmPath)" ` --namespace $script:Namespace ` --set simulations=$script:Count ` --set deployDefaultIssuerCA=false ` --wait if (-not $?) { Write-Host "Error deploying $($displayName) as $($script:DeploymentName)." ` -ForegroundColor Red exit -1 } Write-Host "Deployment of $($displayName) as $($script:DeploymentName) completed." ` -ForegroundColor Green } $tempFile = New-TemporaryFile # # Deployment simulation configuration # $assetTypes = @() if ($script:AddServerType) { $assetTypes += "nsu=http://opcfoundation.org/UA/;i=2004" } switch ($script:SimulationName) { "opc-plc" { # OPC Plc $assetTypes += "nsu=http://opcfoundation.org/UA/Boiler/;i=1132" $assetTypes += "nsu=http://microsoft.com/Opc/OpcPlc/Boiler;i=1000" $assetTypes += "nsu=http://microsoft.com/Opc/OpcPlc/Boiler;i=3" } "opc-test" { $assetTypes += "nsu=http://opcfoundation.org/UA/Boiler/;i=1132" # BoilerType $assetTypes += "nsu=http://opcfoundation.org/UA/WoT-Con/;i=115" # AssetType #$assetTypes += "nsu=FileSystem;i=16314" # FileSystemType } "umati" { # $assetTypes += "nsu=http://opcfoundation.org/UA/MachineTool/;i=14" # monitoring $assetTypes += "nsu=http://opcfoundation.org/UA/MachineTool/;i=13" # machine tool } "umati-public" { # $assetTypes += "nsu=http://opcfoundation.org/UA/MachineTool/;i=14" # monitoring $assetTypes += "nsu=http://opcfoundation.org/UA/MachineTool/;i=13" # machine tool } } for ($i = 0; $i -lt $script:Count; $i++) { $suffix = $("{0:D6}" -f $i) $deviceName = "$($script:SimulationName)-$($suffix)" $deviceResource = "$($ns.id)/devices/$($deviceName)" $errOut = $($device = & { az rest --method get ` --url "$($deviceResource)?api-version=2025-10-01" ` --headers "Content-Type=application/json" } | ConvertFrom-Json) 2>&1 if (!$device -or !$device.id -or $script:Force.IsPresent) { if ($script:SimulationName -eq "umati-public") { $address = "opc.tcp://opcua.umati.app:4840" } else { $address = "$($script:SimulationName)-$($DeploymentName)-$($suffix)" $address = "$($address).$($script:Namespace).svc.cluster.local" $address = "opc.tcp://$($address):4840" } $body = @{ extendedLocation = $iotOps.extendedLocation location = $Location properties = @{ enabled = $true attributes = @{ deviceType = "LDS" } endpoints = @{ inbound = @{ "none" = @{ address = $address endpointType = "Microsoft.OpcPublisher" version = "2.9" authentication = @{ method = "Anonymous" } additionalConfiguration = $(@{ EndpointSecurityMode = "None" EndpointSecurityPolicy = "None" RunAssetDiscovery = $True AssetTypes = $assetTypes } | ConvertTo-Json -Depth 100 -Compress) } } } } } | ConvertTo-Json -Depth 100 $body | Out-File -FilePath $tempFile -Encoding utf8 -Force Write-Host "Creating ADR namespaced device $deviceResource..." -ForegroundColor Cyan $errOut = $($device = & { az rest --method put ` --url "$($deviceResource)?api-version=2025-10-01" ` --headers "Content-Type=application/json" ` --body @$tempFile } | ConvertFrom-Json) 2>&1 if (-not $? -or !$device -or !$device.id) { Write-Host "Error: Failed to create device $($deviceResource) - $($errOut)." ` -ForegroundColor Red Remove-Item -Path $tempFile -Force exit -1 } Write-Host "ADR namespaced device $($device.id) created." -ForegroundColor Green } else { Write-Host "ADR namespaced device $($device.id) exists." -ForegroundColor Green } } Remove-Item -Path $tempFile -Force ================================================ FILE: deploy/kubernetes/simulation/helm/opc-plc/Chart.yaml ================================================ apiVersion: v2 name: microsoft-opc-plc description: A Helm chart for Kubernetes that deploys the OPC PLC. type: application version: 2.9-alpha.1 appVersion: 2.9-alpha.1 ================================================ FILE: deploy/kubernetes/simulation/helm/opc-plc/templates/_helpers.tpl ================================================ {{/* Expand the name of the chart. */}} {{- define "simulation.name" -}} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} {{- end }} {{/* Create chart name and version as used by the chart label. */}} {{- define "simulation.chart" -}} {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} {{- end }} {{/* Name of ConfigMap for OPC PLC. */}} {{- define "simulation.configmap" -}} {{- printf "%s-%s" "opc-plc-config" $.Release.Name | replace "+" "_" | trunc 63 | trimSuffix "-" }} {{- end }} {{/* Common labels */}} {{- define "simulation.labels" -}} helm.sh/chart: {{ include "simulation.chart" . }} {{ include "simulation.selectorLabels" . }} {{- if .Chart.AppVersion }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} {{- end }} app.kubernetes.io/managed-by: {{ .Release.Service }} {{- end }} {{/* Selector labels */}} {{- define "simulation.selectorLabels" -}} app.kubernetes.io/name: {{ include "simulation.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} ================================================ FILE: deploy/kubernetes/simulation/helm/opc-plc/templates/opc-plc_configMap.yaml ================================================ apiVersion: v1 kind: ConfigMap metadata: name: {{ include "simulation.configmap" . }} namespace: {{ .Release.Namespace }} labels: {{- include "simulation.labels" . | nindent 4 }} data: nodesfile.json: |- { "Folder": "MyTelemetry", "NodeList": [ { "NodeId": "panic", "Name": "Panic", "DataType": "Boolean", "ValueRank": -1, "AccessLevel": "CurrentReadOrWrite", "Description": "Node that panics, if written" } ] } ================================================ FILE: deploy/kubernetes/simulation/helm/opc-plc/templates/opc-plc_default_application_certificate.yaml ================================================ {{- $simulationLabels := include "simulation.labels" . -}} {{- $releaseName := .Release.Name -}} {{ range $i := until (.Values.simulations | int) }} {{ $suffix := printf "%s-%06d" $releaseName $i }} {{- if $.Capabilities.APIVersions.Has "cert-manager.io/v1" }} apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: opc-ua-opc-plc-default-application-{{ $suffix }} namespace: {{ $.Release.Namespace }} labels: {{- $simulationLabels | nindent 4 }} spec: # Secret names are always required. secretName: opc-ua-opc-plc-default-application-cert-{{ $suffix }} duration: 8760h # 365d renewBefore: 4380h # 182d subject: # It is recommended that the user sets here in the subject at least the organization's name. This information will be stored in the certificate and helps to identify the certificate. # organizations: # - Microsoft commonName: OpcPlc isCA: false privateKey: algorithm: RSA encoding: PKCS1 size: 2048 rotationPolicy: Always usages: - content commitment - digital signature - key encipherment - data encipherment - cert sign - client auth - server auth # At least one of a DNS Name, URI, or IP address is required. uris: - urn:OpcPlc:opc-plc-{{ $suffix }} dnsNames: - opc-plc-{{ $suffix }}.{{ $.Release.Namespace }} - opc-plc-{{ $suffix }} issuerRef: kind: Issuer {{- if $.Values.deployDefaultIssuerCA }} name: aio-opc-opcuabroker-default-root-ca-issuer {{- else }} name: aio-opc-ua-self-signed-issuer {{- end }} {{- else }} {{ fail "cert-manager is required to create Certificate resource. Please install cert-manager."}} {{- end }} --- {{ end }} ================================================ FILE: deploy/kubernetes/simulation/helm/opc-plc/templates/opc-plc_deployment.yaml ================================================ {{- $simulationLabels := include "simulation.labels" . -}} {{- $simulationSelectorLabels := include "simulation.selectorLabels" . -}} {{- $simulationConfigMap := include "simulation.configmap" . -}} {{- $releaseName := .Release.Name -}} {{ range $i := until (.Values.simulations | int) }} {{ $suffix := printf "%s-%06d" $releaseName $i }} apiVersion: apps/v1 kind: Deployment metadata: name: opc-plc-{{ $suffix }} namespace: {{ $.Release.Namespace }} labels: {{- $simulationLabels | nindent 4 }} app.kubernetes.io/component: opc-plc-{{ $suffix }} spec: selector: matchLabels: {{- $simulationSelectorLabels | nindent 6 }} app.kubernetes.io/component: opc-plc-{{ $suffix }} template: metadata: labels: {{- $simulationSelectorLabels | nindent 8 }} app.kubernetes.io/component: opc-plc-{{ $suffix }} spec: {{- with $.Values.pullSecrets }} imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} nodeSelector: "kubernetes.io/os": linux containers: - name: opc-plc {{- if $.Values.setSecurityContext }} securityContext: allowPrivilegeEscalation: false privileged: false # OPC PLC runs as root. # runAsNonRoot: true # readOnlyRootFilesystem: true capabilities: drop: - ALL seccompProfile: type: RuntimeDefault {{- end }} image: {{ $.Values.image }}:{{ $.Values.tag }} imagePullPolicy: {{ $.Values.pullPolicy }} ports: - containerPort: 4840 args: - "--ph=opc-plc-{{ $suffix }}.{{ $.Release.Namespace }}" - "--cdn=opc-plc-{{ $suffix }}.{{ $.Release.Namespace }},opc-plc-{{ $suffix }}" - "--nodesfile=/app/nodesfile.json" - "--ut" {{- if $.Values.autoAcceptUntrustedCertificates }} - "--autoaccept" {{- end }} - "--sn={{ $.Values.slowNodes }}" - "--sr=10" - "--fn={{ $.Values.fastNodes }}" - "--veryfastrate={{ $.Values.fastRate }}" - "--gn=5" - "--pn=4840" {{- if $.Values.openTelemetry.endpointUri }} - "--otlpee={{ $.Values.openTelemetry.endpointUri }}" - "--otlpei={{ $.Values.openTelemetry.exportIntervalSeconds }}" - "--otlpep={{ $.Values.openTelemetry.exportProtocol }}" {{- end }} - "--maxsessioncount={{ $.Values.maxSessionCount }}" - "--maxsubscriptioncount={{ $.Values.maxSubscriptionCount }}" - "--maxqueuedrequestcount={{ $.Values.maxQueuedRequestCount }}" - "--ses" - "--alm" - "--at=FlatDirectory" - "--drurs" # Check if additionalArgs are defined and have arguments for the current instance {{- if and (hasKey $.Values "additionalArgs") (not (empty $.Values.additionalArgs)) (index $.Values.additionalArgs $i) }} # Add additional arguments for the current instance {{- range (index $.Values.additionalArgs $i) }} - {{ . }} {{- end }} {{- end }} volumeMounts: - name: opc-plc-config-{{ $suffix }} mountPath: /app/nodesfile.json subPath: nodesfile.json - name: opc-ua-opc-plc-default-application-cert-{{ $suffix }} mountPath: /app/pki/own/ - name: opc-ua-opc-plc-default-trusted-cert-{{ $suffix }} mountPath: /app/pki/trusted/ {{ if $.Values.resources }} resources: {{ toYaml $.Values.resources | indent 10 }} {{- end }} volumes: - name: opc-plc-config-{{ $suffix }} configMap: name: {{ $simulationConfigMap }} - name: opc-ua-opc-plc-default-application-cert-{{ $suffix }} secret: secretName: opc-ua-opc-plc-default-application-cert-{{ $suffix }} - name: opc-ua-opc-plc-default-trusted-cert-{{ $suffix }} # fallback to trust the own certificate secret. this contain the CA certificate when used. secret: secretName: opc-ua-opc-plc-default-application-cert-{{ $suffix }} --- {{ end }} ================================================ FILE: deploy/kubernetes/simulation/helm/opc-plc/templates/opc-plc_service.yaml ================================================ {{- $simulationLabels := include "simulation.labels" . -}} {{- $simulationSelectorLabels := include "simulation.selectorLabels" . -}} {{- $releaseName := .Release.Name -}} {{ range $i := until (.Values.simulations | int) }} {{ $suffix := printf "%s-%06d" $releaseName $i }} apiVersion: v1 kind: Service metadata: name: opc-plc-{{ $suffix }} namespace: {{ $.Release.Namespace }} labels: {{- $simulationLabels | nindent 4 }} app.kubernetes.io/component: opc-plc-{{ $suffix }}-service spec: type: ClusterIP selector: {{- $simulationSelectorLabels | nindent 4 }} app.kubernetes.io/component: opc-plc-{{ $suffix }} ports: - port: 4840 protocol: TCP targetPort: 4840 --- {{ end }} ================================================ FILE: deploy/kubernetes/simulation/helm/opc-plc/values.yaml ================================================ image: mcr.microsoft.com/iotedge/opc-plc tag: latest pullPolicy: Always pullSecrets: [] # Controls number of OPC PLCs that should be deployed. simulations: 1 openTelemetry: # OpenTelemetry Endpoint Uri endpointUri: null # OpenTelemetry Export Interval in seconds exportIntervalSeconds: 60 # OpenTelemetry Export Protocol exportProtocol: grpc # Number of fast nodes. fastNodes: 2000 # Rate in milliseconds to change fast nodes. fastRate: 1000 # Number of slow nodes. slowNodes: 25 # Maximum number of parallel sessions. maxSessionCount: 100 # Maximum number of subscriptions. maxSubscriptionCount: 100 # Maximum number of requests that will be queued waiting for a thread. maxQueuedRequestCount: 2000 # Controls if the security bar is lowered for the OPC PLC simulation server. When set to true, all client connections will be accepted. autoAcceptUntrustedCertificates: true # Controls if the security context should be set for the OPC PLC simulation server. setSecurityContext: true # Additional arguments for the OPC PLC simulation # This should be an array of arrays, where each inner array contains the arguments for a specific instance. additionalArgs: [] resources: requests: memory: 192Mi cpu: 125m limits: memory: 768Mi cpu: 500m nameOverride: null deployDefaultIssuerCA: false ================================================ FILE: deploy/kubernetes/simulation/helm/opc-test/Chart.yaml ================================================ apiVersion: v2 name: microsoft-opc-test description: A Helm chart for Kubernetes that deploys the OPC UA test servers. type: application version: 2.9.15-alpha.1 appVersion: 2.9.15-alpha.1 ================================================ FILE: deploy/kubernetes/simulation/helm/opc-test/templates/_helpers.tpl ================================================ {{/* Expand the name of the chart. */}} {{- define "simulation.name" -}} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} {{- end }} {{/* Create chart name and version as used by the chart label. */}} {{- define "simulation.chart" -}} {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} {{- end }} {{/* Common labels */}} {{- define "simulation.labels" -}} helm.sh/chart: {{ include "simulation.chart" . }} {{ include "simulation.selectorLabels" . }} {{- if .Chart.AppVersion }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} {{- end }} app.kubernetes.io/managed-by: {{ .Release.Service }} {{- end }} {{/* Selector labels */}} {{- define "simulation.selectorLabels" -}} app.kubernetes.io/name: {{ include "simulation.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} ================================================ FILE: deploy/kubernetes/simulation/helm/opc-test/templates/opc-test_default_application_certificate.yaml ================================================ {{- $simulationLabels := include "simulation.labels" . -}} {{- $releaseName := .Release.Name -}} {{ range $i := until (.Values.simulations | int) }} {{ $suffix := printf "%s-%06d" $releaseName $i }} {{- if $.Capabilities.APIVersions.Has "cert-manager.io/v1" }} apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: opc-ua-opc-test-default-application-{{ $suffix }} namespace: {{ $.Release.Namespace }} labels: {{- $simulationLabels | nindent 4 }} spec: # Secret names are always required. secretName: opc-ua-opc-test-default-application-cert-{{ $suffix }} duration: 8760h # 365d renewBefore: 4380h # 182d subject: # It is recommended that the user sets here in the subject at least the organization's name. This information will be stored in the certificate and helps to identify the certificate. # organizations: # - Microsoft commonName: OpcTester isCA: false privateKey: algorithm: RSA encoding: PKCS1 size: 2048 rotationPolicy: Always usages: - content commitment - digital signature - key encipherment - data encipherment - cert sign - client auth - server auth # At least one of a DNS Name, URI, or IP address is required. uris: - urn:OpcTester:opc-test-{{ $suffix }} dnsNames: - opc-test-{{ $suffix }}.{{ $.Release.Namespace }} - opc-test-{{ $suffix }} issuerRef: kind: Issuer {{- if $.Values.deployDefaultIssuerCA }} name: aio-opc-opcuabroker-default-root-ca-issuer {{- else }} name: aio-opc-ua-self-signed-issuer {{- end }} {{- else }} {{ fail "cert-manager is required to create Certificate resource. Please install cert-manager."}} {{- end }} --- {{ end }} ================================================ FILE: deploy/kubernetes/simulation/helm/opc-test/templates/opc-test_deployment.yaml ================================================ {{- $simulationLabels := include "simulation.labels" . -}} {{- $simulationSelectorLabels := include "simulation.selectorLabels" . -}} {{- $releaseName := .Release.Name -}} {{ range $i := until (.Values.simulations | int) }} {{ $suffix := printf "%s-%06d" $releaseName $i }} apiVersion: apps/v1 kind: Deployment metadata: name: opc-test-{{ $suffix }} namespace: {{ $.Release.Namespace }} labels: {{- $simulationLabels | nindent 4 }} app.kubernetes.io/component: opc-test-{{ $suffix }} spec: selector: matchLabels: {{- $simulationSelectorLabels | nindent 6 }} app.kubernetes.io/component: opc-test-{{ $suffix }} template: metadata: labels: {{- $simulationSelectorLabels | nindent 8 }} app.kubernetes.io/component: opc-test-{{ $suffix }} spec: {{- with $.Values.pullSecrets }} imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} nodeSelector: "kubernetes.io/os": linux containers: - name: opc-test {{- if $.Values.setSecurityContext }} securityContext: allowPrivilegeEscalation: false privileged: false # OPC Tester runs as root. # runAsNonRoot: true # readOnlyRootFilesystem: true capabilities: drop: - ALL seccompProfile: type: RuntimeDefault {{- end }} image: {{ $.Values.image }}:{{ $.Values.tag }} imagePullPolicy: {{ $.Values.pullPolicy }} ports: - containerPort: 4840 args: - "--port" - "4840" - "--hosts" - "opc-test-{{ $suffix }}.{{ $.Release.Namespace }},opc-test-{{ $suffix }}" # Check if additionalArgs are defined and have arguments for the current instance {{- if and (hasKey $.Values "additionalArgs") (not (empty $.Values.additionalArgs)) (index $.Values.additionalArgs $i) }} # Add additional arguments for the current instance {{- range (index $.Values.additionalArgs $i) }} - {{ . }} {{- end }} {{- end }} volumeMounts: - name: opc-ua-opc-test-default-application-cert-{{ $suffix }} mountPath: /app/pki/own/ - name: opc-ua-opc-test-default-trusted-cert-{{ $suffix }} mountPath: /app/pki/trusted/ {{ if $.Values.resources }} resources: {{ toYaml $.Values.resources | indent 10 }} {{- end }} volumes: - name: opc-ua-opc-test-default-application-cert-{{ $suffix }} secret: secretName: opc-ua-opc-test-default-application-cert-{{ $suffix }} - name: opc-ua-opc-test-default-trusted-cert-{{ $suffix }} # fallback to trust the own certificate secret. this contain the CA certificate when used. secret: secretName: opc-ua-opc-test-default-application-cert-{{ $suffix }} --- {{ end }} ================================================ FILE: deploy/kubernetes/simulation/helm/opc-test/templates/opc-test_service.yaml ================================================ {{- $simulationLabels := include "simulation.labels" . -}} {{- $simulationSelectorLabels := include "simulation.selectorLabels" . -}} {{- $releaseName := .Release.Name -}} {{ range $i := until (.Values.simulations | int) }} {{ $suffix := printf "%s-%06d" $releaseName $i }} apiVersion: v1 kind: Service metadata: name: opc-test-{{ $suffix }} namespace: {{ $.Release.Namespace }} labels: {{- $simulationLabels | nindent 4 }} app.kubernetes.io/component: opc-test-{{ $suffix }}-service spec: type: ClusterIP selector: {{- $simulationSelectorLabels | nindent 4 }} app.kubernetes.io/component: opc-test-{{ $suffix }} ports: - port: 4840 protocol: TCP targetPort: 4840 --- {{ end }} ================================================ FILE: deploy/kubernetes/simulation/helm/opc-test/values.yaml ================================================ image: mcr.microsoft.com/iot/opc-ua-test-server tag: 2.9.15 pullPolicy: Always pullSecrets: [] # Controls number of OPC UA Test servers that should be deployed. simulations: 1 # Unused, opc test always uses the default application certificate. # TODO, remove and pass same to opc-plc as additionalArgs autoAcceptUntrustedCertificates: true # Controls if the security context should be set for the OPC UA Test server simulation server. setSecurityContext: true # Additional arguments for the OPC UA Test server simulation # This should be an array of arrays, where each inner array contains the arguments for a specific instance. additionalArgs: [] resources: requests: memory: 192Mi cpu: 125m limits: memory: 768Mi cpu: 500m nameOverride: null deployDefaultIssuerCA: false ================================================ FILE: deploy/kubernetes/simulation/helm/opc-umati/templates/umati_deployment.yaml ================================================ {{- $simulationLabels := include "simulation.labels" . -}} {{- $simulationSelectorLabels := include "simulation.selectorLabels" . -}} {{- $releaseName := .Release.Name -}} {{ range $i := until (.Values.simulations | int) }} {{ $suffix := printf "%s-%06d" $releaseName $i }} apiVersion: apps/v1 kind: Deployment metadata: name: umati-{{ $suffix }} namespace: {{ $.Release.Namespace }} labels: {{- $simulationLabels | nindent 4 }} app.kubernetes.io/component: umati-{{ $suffix }} spec: selector: matchLabels: {{- $simulationSelectorLabels | nindent 6 }} app.kubernetes.io/component: umati-{{ $suffix }} template: metadata: labels: {{- $simulationSelectorLabels | nindent 8 }} app.kubernetes.io/component: umati-{{ $suffix }} spec: {{- with $.Values.pullSecrets }} imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} nodeSelector: "kubernetes.io/os": linux containers: - name: umati {{- if $.Values.setSecurityContext }} securityContext: allowPrivilegeEscalation: false privileged: false # runAsNonRoot: true # readOnlyRootFilesystem: true capabilities: drop: - ALL seccompProfile: type: RuntimeDefault {{- end }} image: {{ $.Values.image }}:{{ $.Values.tag }} imagePullPolicy: {{ $.Values.pullPolicy }} ports: - containerPort: 4840 args: - "/app/configuration.json" volumeMounts: - name: umati-config-{{ $suffix }} mountPath: /app/configuration.json subPath: configuration.json - name: opc-ua-umati-default-application-cert-{{ $suffix }} mountPath: /app/pki/own/ - name: opc-ua-umati-default-trusted-cert-{{ $suffix }} mountPath: /app/pki/trusted/ {{ if $.Values.resources }} resources: {{ toYaml $.Values.resources | indent 10 }} {{- end }} volumes: - name: umati-config-{{ $suffix }} configMap: name: umati-config-{{ $suffix }} - name: opc-ua-umati-default-application-cert-{{ $suffix }} secret: secretName: opc-ua-umati-default-application-cert-{{ $suffix }} - name: opc-ua-umati-default-trusted-cert-{{ $suffix }} # fallback to trust the own certificate secret. this contain the CA certificate when used. secret: secretName: opc-ua-umati-default-application-cert-{{ $suffix }} --- {{ end }} ================================================ FILE: deploy/kubernetes/simulation/helm/umati/Chart.yaml ================================================ apiVersion: v2 name: umati-sample-server description: A Helm chart for Kubernetes that deploys the Umati sample server. type: application version: 1.0-alpha.1 appVersion: 1.0-alpha.1 ================================================ FILE: deploy/kubernetes/simulation/helm/umati/templates/_helpers.tpl ================================================ {{/* Expand the name of the chart. */}} {{- define "simulation.name" -}} {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} {{- end }} {{/* Create chart name and version as used by the chart label. */}} {{- define "simulation.chart" -}} {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} {{- end }} {{/* Common labels */}} {{- define "simulation.labels" -}} helm.sh/chart: {{ include "simulation.chart" . }} {{ include "simulation.selectorLabels" . }} {{- if .Chart.AppVersion }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} {{- end }} app.kubernetes.io/managed-by: {{ .Release.Service }} {{- end }} {{/* Selector labels */}} {{- define "simulation.selectorLabels" -}} app.kubernetes.io/name: {{ include "simulation.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} ================================================ FILE: deploy/kubernetes/simulation/helm/umati/templates/umati_configMap.yaml ================================================ {{- $simulationLabels := include "simulation.labels" . -}} {{- $releaseName := .Release.Name -}} {{ range $i := until (.Values.simulations | int) }} {{ $suffix := printf "%s-%06d" $releaseName $i }} apiVersion: v1 kind: ConfigMap metadata: name: umati-config-{{ $suffix }} namespace: {{ $.Release.Namespace }} labels: {{- $simulationLabels | nindent 4 }} data: configuration.json: |- { "Hostname": "umati-{{ $suffix }}.{{ $.Release.Namespace }}.svc.cluster.local", "Port": 4840, "UserPassAuthentication": [], "Encryption": { "ServerCert": "/app/pki/own/tls.crt", "ServerKey": "/app/pki/own/key.der", "TrustedClients": ["trusted/trustedClient.der"], "IssuerCerts": [], "Revocation": [] } } --- {{ end }} ================================================ FILE: deploy/kubernetes/simulation/helm/umati/templates/umati_default_application_certificate.yaml ================================================ {{- $simulationLabels := include "simulation.labels" . -}} {{- $releaseName := .Release.Name -}} {{ range $i := until (.Values.simulations | int) }} {{ $suffix := printf "%s-%06d" $releaseName $i }} {{- if $.Capabilities.APIVersions.Has "cert-manager.io/v1" }} apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: opc-ua-umati-default-application-{{ $suffix }} namespace: {{ $.Release.Namespace }} labels: {{- $simulationLabels | nindent 4 }} spec: # Secret names are always required. secretName: opc-ua-umati-default-application-cert-{{ $suffix }} #additionalOutputFormats: #- type: DER duration: 8760h # 365d renewBefore: 4380h # 182d subject: # It is recommended that the user sets here in the subject at least the organization's name. This information will be stored in the certificate and helps to identify the certificate. # organizations: # - Microsoft commonName: UMATI isCA: false privateKey: algorithm: RSA encoding: PKCS1 size: 2048 rotationPolicy: Always usages: - content commitment - digital signature - key encipherment - data encipherment - cert sign - client auth - server auth # At least one of a DNS Name, URI, or IP address is required. uris: - urn:UMATI:umati-{{ $suffix }} dnsNames: - umati-{{ $suffix }}.{{ $.Release.Namespace }} - umati-{{ $suffix }} issuerRef: kind: Issuer {{- if $.Values.deployDefaultIssuerCA }} name: aio-opc-opcuabroker-default-root-ca-issuer {{- else }} name: aio-opc-ua-self-signed-issuer {{- end }} {{- else }} {{ fail "cert-manager is required to create Certificate resource. Please install cert-manager."}} {{- end }} --- {{ end }} ================================================ FILE: deploy/kubernetes/simulation/helm/umati/templates/umati_deployment.yaml ================================================ {{- $simulationLabels := include "simulation.labels" . -}} {{- $simulationSelectorLabels := include "simulation.selectorLabels" . -}} {{- $releaseName := .Release.Name -}} {{ range $i := until (.Values.simulations | int) }} {{ $suffix := printf "%s-%06d" $releaseName $i }} apiVersion: apps/v1 kind: Deployment metadata: name: umati-{{ $suffix }} namespace: {{ $.Release.Namespace }} labels: {{- $simulationLabels | nindent 4 }} app.kubernetes.io/component: umati-{{ $suffix }} spec: selector: matchLabels: {{- $simulationSelectorLabels | nindent 6 }} app.kubernetes.io/component: umati-{{ $suffix }} template: metadata: labels: {{- $simulationSelectorLabels | nindent 8 }} app.kubernetes.io/component: umati-{{ $suffix }} spec: hostname: umati-{{ $suffix }} {{- with $.Values.pullSecrets }} imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} nodeSelector: "kubernetes.io/os": linux containers: - name: umati {{- if $.Values.setSecurityContext }} securityContext: allowPrivilegeEscalation: false privileged: false # runAsNonRoot: true # readOnlyRootFilesystem: true capabilities: drop: - ALL seccompProfile: type: RuntimeDefault {{- end }} image: {{ $.Values.image }}:{{ $.Values.tag }} imagePullPolicy: {{ $.Values.pullPolicy }} ports: - containerPort: 4840 args: - "/app/configuration.json" volumeMounts: - name: umati-config-{{ $suffix }} mountPath: /app/configuration.json subPath: configuration.json - name: opc-ua-umati-default-application-cert-{{ $suffix }} mountPath: /app/pki/own/ - name: opc-ua-umati-default-trusted-cert-{{ $suffix }} mountPath: /app/pki/trusted/ {{ if $.Values.resources }} resources: {{ toYaml $.Values.resources | indent 10 }} {{- end }} volumes: - name: umati-config-{{ $suffix }} configMap: name: umati-config-{{ $suffix }} - name: opc-ua-umati-default-application-cert-{{ $suffix }} secret: secretName: opc-ua-umati-default-application-cert-{{ $suffix }} - name: opc-ua-umati-default-trusted-cert-{{ $suffix }} # fallback to trust the own certificate secret. this contain the CA certificate when used. secret: secretName: opc-ua-umati-default-application-cert-{{ $suffix }} --- {{ end }} ================================================ FILE: deploy/kubernetes/simulation/helm/umati/templates/umati_service.yaml ================================================ {{- $simulationLabels := include "simulation.labels" . -}} {{- $simulationSelectorLabels := include "simulation.selectorLabels" . -}} {{- $releaseName := .Release.Name -}} {{ range $i := until (.Values.simulations | int) }} {{ $suffix := printf "%s-%06d" $releaseName $i }} apiVersion: v1 kind: Service metadata: name: umati-{{ $suffix }} namespace: {{ $.Release.Namespace }} labels: {{- $simulationLabels | nindent 4 }} app.kubernetes.io/component: umati-{{ $suffix }}-service spec: type: ClusterIP selector: {{- $simulationSelectorLabels | nindent 4 }} app.kubernetes.io/component: umati-{{ $suffix }} ports: - port: 4840 protocol: TCP targetPort: 4840 --- {{ end }} ================================================ FILE: deploy/kubernetes/simulation/helm/umati/values.yaml ================================================ image: ghcr.io/umati/sample-server tag: develop pullPolicy: Always pullSecrets: [] # Controls number of OPC PLCs that should be deployed. simulations: 1 # Controls if the security bar is lowered for the Umati sample simulation server. When set to true, all client connections will be accepted. autoAcceptUntrustedCertificates: true # Controls if the security context should be set for the Umati sample simulation server. setSecurityContext: true # Additional arguments for the Umati sample simulation # This should be an array of arrays, where each inner array contains the arguments for a specific instance. additionalArgs: [] resources: requests: memory: 192Mi cpu: 125m limits: memory: 768Mi cpu: 500m nameOverride: null deployDefaultIssuerCA: false ================================================ FILE: deploy/readme.md ================================================ # Deploy IoT services [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2FIndustrial-IoT%2Fmain%2Fdeploy%2Fazuredeploy.json) You can also deploy the required resources using the provided script: ```powershell ./deploy.ps1 -Name ``` Once completed you can [deploy Azure IoT Edge using ARM](./iotedge/azuredeploy.json) or [using the provided scripts](./iotedge/readme.md). ================================================ FILE: docs/_config.yml ================================================ remote_theme: MicrosoftLearning/Jekyll-Theme ================================================ FILE: docs/opc-publisher/api.md ================================================ ## Resources ### Certificates This section lists the certificate APi provided by OPC Publisher providing all public and private key infrastructure (PKI) related API methods. The method name for all transports other than HTTP (which uses the shown HTTP methods and resource uris) is the name of the subsection header. To use the version specific method append "_V1" or "_V2" to the method name. #### AddTrustedHttpsCertificateAsync ``` POST /v2/pki/https/certs ``` ##### Description Add a certificate chain to the trusted https store. The certificate is provided as a concatenated set of certificates with the first the one to add, and the remainder the issuer chain. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The certificate chain.|string (byte)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful.|No Content| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**500**|An internal error ocurred.|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### ApproveRejectedCertificate ``` POST /v2/pki/rejected/certs/{thumbprint}/approve ``` ##### Description Move a rejected certificate from the rejected folder to the trusted folder on the publisher. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Path**|**thumbprint**
*required*|The thumbprint of the certificate to trust.|string| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful.|No Content| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**500**|An internal error ocurred.|[ProblemDetails](definitions.md#problemdetails)| ##### Produces * `application/json` * `application/x-msgpack` #### AddCertificateChain ``` POST /v2/pki/trusted/certs ``` ##### Description Add a certificate chain to the specified store. The certificate is provided as a concatenated asn encoded set of certificates with the first the one to add, and the remainder the issuer chain. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The certificate chain.|string (byte)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful.|No Content| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**500**|An internal error ocurred.|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### RemoveAll ``` DELETE /v2/pki/{store} ``` ##### Description Remove all certificates and revocation lists from the specified store. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Path**|**store**
*required*|The store to add the certificate to|string| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful.|No Content| |**400**|The passed in information such store name is invalid|[ProblemDetails](definitions.md#problemdetails)| |**404**|Nothing could be found.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An internal error ocurred.|[ProblemDetails](definitions.md#problemdetails)| ##### Produces * `application/json` * `application/x-msgpack` #### ListCertificates ``` GET /v2/pki/{store}/certs ``` ##### Description Get the certificates in the specified certificate store ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Path**|**store**
*required*|The store to enumerate|string| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful.|< [X509CertificateModel](definitions.md#x509certificatemodel) > array| |**400**|The passed in information such as store name is invalid|[ProblemDetails](definitions.md#problemdetails)| |**404**|Nothing could be found.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An internal error ocurred.|[ProblemDetails](definitions.md#problemdetails)| ##### Produces * `application/json` * `application/x-msgpack` #### AddCertificate ``` PATCH /v2/pki/{store}/certs ``` ##### Description Add a certificate to the specified store. The certificate is provided as a pfx/pkcs12 optionally password protected blob. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Path**|**store**
*required*|The store to add the certificate to|string| |**Query**|**password**
*optional*|The optional password of the pfx|string| |**Body**|**body**
*required*|The pfx encoded certificate.|string (byte)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful.|No Content| |**400**|The passed in information such as store name is invalid|[ProblemDetails](definitions.md#problemdetails)| |**500**|An internal error ocurred.|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### RemoveCertificate ``` DELETE /v2/pki/{store}/certs/{thumbprint} ``` ##### Description Remove a certificate with the provided thumbprint from the specified store. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Path**|**store**
*required*|The store to add the certificate to|string| |**Path**|**thumbprint**
*required*|The thumbprint of the certificate to delete.|string| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful.|No Content| |**400**|The passed in information such store name is invalid|[ProblemDetails](definitions.md#problemdetails)| |**404**|Nothing could be found.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An internal error ocurred.|[ProblemDetails](definitions.md#problemdetails)| ##### Produces * `application/json` * `application/x-msgpack` #### ListCertificateRevocationLists ``` GET /v2/pki/{store}/crls ``` ##### Description Get the certificates in the specified certificated store ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Path**|**store**
*required*|The store to enumerate|string| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful.|< string (byte) > array| |**400**|The passed in information such as store name is invalid|[ProblemDetails](definitions.md#problemdetails)| |**404**|Nothing could be found.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An internal error ocurred.|[ProblemDetails](definitions.md#problemdetails)| ##### Produces * `application/json` * `application/x-msgpack` #### RemoveCertificateRevocationList ``` DELETE /v2/pki/{store}/crls ``` ##### Description Remove a certificate revocation list from the specified store. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Path**|**store**
*required*|The store to add the certificate to|string| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful.|No Content| |**400**|The passed in information such store name is invalid|[ProblemDetails](definitions.md#problemdetails)| |**404**|Nothing could be found.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An internal error ocurred.|[ProblemDetails](definitions.md#problemdetails)| ##### Produces * `application/json` * `application/x-msgpack` #### AddCertificateRevocationList ``` PATCH /v2/pki/{store}/crls ``` ##### Description Add a certificate revocation list to the specified store. The certificate revocation list is provided as a der encoded blob. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Path**|**store**
*required*|The store to add the certificate to|string| |**Body**|**body**
*required*|The pfx encoded certificate.|string (byte)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful.|No Content| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**500**|An internal error ocurred.|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` ### Configuration This section contains the API to configure OPC Publisher. The method name for all transports other than HTTP (which uses the shown HTTP methods and resource uris) is the name of the subsection header. To use the version specific method append "_V1" or "_V2" to the method name. #### [GetConfiguredEndpoints](./directmethods.md#getconfiguredendpoints_v1) ``` GET /v2/configuration ``` ##### Description Get a list of nodes under a configured endpoint in the configuration. Further information is provided in the OPC Publisher documentation. configuration. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Query**|**IncludeNodes**
*optional*|Include nodes that make up the configuration|boolean| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The data was retrieved.|[GetConfiguredEndpointsResponseModel](definitions.md#getconfiguredendpointsresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Produces * `application/json` * `application/x-msgpack` #### [SetConfiguredEndpoints](./directmethods.md#setconfiguredendpoints_v1) ``` PUT /v2/configuration ``` ##### Description Enables clients to update the entire published nodes configuration in one call. This includes clearing the existing configuration. Further information is provided in the OPC Publisher documentation. configuration. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The new published nodes configuration|[SetConfiguredEndpointsRequestModel](definitions.md#setconfiguredendpointsrequestmodel)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful.|No Content| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### [AddOrUpdateEndpoints](./directmethods.md#addorupdateendpoints_v1) ``` PATCH /v2/configuration ``` ##### Description Add or update endpoint configuration and nodes on a server. Further information is provided in the OPC Publisher documentation. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The parts of the configuration to add or update.|< [PublishedNodesEntryModel](definitions.md#publishednodesentrymodel) > array| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful.|[PublishedNodesResponseModel](definitions.md#publishednodesresponsemodel)| |**404**|The endpoint was not found to add to|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### PublishBulk ``` POST /v2/configuration/bulk ``` ##### Description Configure node values to publish and unpublish in bulk. The group field in the Connection Model can be used to specify a writer group identifier that will be used in the configuration entry that is created from it inside OPC Publisher. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The nodes to publish or unpublish.|[PublishBulkRequestModelRequestEnvelope](definitions.md#publishbulkrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful.|[PublishBulkResponseModel](definitions.md#publishbulkresponsemodel)| |**404**|The item could not be unpublished|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### [GetDiagnosticInfo](./directmethods.md#getdiagnosticinfo_v1) ``` POST /v2/configuration/diagnostics ``` ##### Description Get the list of diagnostics info for all dataset writers in the OPC Publisher at the point the call is received. Further information is provided in the OPC Publisher documentation. ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful.|< [PublishDiagnosticInfoModel](definitions.md#publishdiagnosticinfomodel) > array| |**405**|Call not supported or functionality disabled.|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Produces * `application/json` * `application/x-msgpack` #### [GetConfiguredNodesOnEndpoint](./directmethods.md#getconfigurednodesonendpoint_v) ``` POST /v2/configuration/endpoints/list/nodes ``` ##### Description Get the nodes of a published nodes entry object returned earlier from a call to GetConfiguredEndpoints. Further information is provided in the OPC Publisher documentation. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The entry model from a call to GetConfiguredEndpoints for which to gather the nodes.|[PublishedNodesEntryModel](definitions.md#publishednodesentrymodel)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The information was returned.|[GetConfiguredNodesOnEndpointResponseModel](definitions.md#getconfigurednodesonendpointresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**404**|The entry was not found.|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### PublishList ``` POST /v2/configuration/list ``` ##### Description Get all published nodes for a server endpoint. The group field that was used in the Connection Model to start publishing must also be specified in this connection model. ##### Parameters |Type|Name|Schema| |---|---|---| |**Body**|**body**
*required*|[PublishedItemListRequestModelRequestEnvelope](definitions.md#publisheditemlistrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The items were found and returned.|[PublishedItemListResponseModel](definitions.md#publisheditemlistresponsemodel)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### [PublishNodes](./directmethods.md#publishnodes_v1) ``` POST /v2/configuration/nodes ``` ##### Description PublishNodes enables a client to add a set of nodes to be published. Further information is provided in the OPC Publisher documentation. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The request contains the nodes to publish.|[PublishedNodesEntryModel](definitions.md#publishednodesentrymodel)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful.|[PublishedNodesResponseModel](definitions.md#publishednodesresponsemodel)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### [UnpublishNodes](./directmethods.md#unpublishnodes_v1) ``` POST /v2/configuration/nodes/unpublish ``` ##### Description UnpublishNodes method enables a client to remove nodes from a previously configured DataSetWriter. Further information is provided in the OPC Publisher documentation. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The request payload specifying the nodes to unpublish.|[PublishedNodesEntryModel](definitions.md#publishednodesentrymodel)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful.|[PublishedNodesResponseModel](definitions.md#publishednodesresponsemodel)| |**404**|The nodes could not be unpublished|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### [UnpublishAllNodes](./directmethods.md#unpublishallnodes_v1) ``` POST /v2/configuration/nodes/unpublish/all ``` ##### Description Unpublish all specified nodes or all nodes in the publisher configuration. Further information is provided in the OPC Publisher documentation. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*optional*|The request contains the parts of the configuration to remove.|[PublishedNodesEntryModel](definitions.md#publishednodesentrymodel)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful.|[PublishedNodesResponseModel](definitions.md#publishednodesresponsemodel)| |**404**|The nodes could not be unpublished|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### PublishStart ``` POST /v2/configuration/start ``` ##### Description Start publishing values from a node on a server. The group field in the Connection Model can be used to specify a writer group identifier that will be used in the configuration entry that is created from it inside OPC Publisher. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The server and node to publish.|[PublishStartRequestModelRequestEnvelope](definitions.md#publishstartrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful.|[PublishStartResponseModel](definitions.md#publishstartresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### PublishStop ``` POST /v2/configuration/stop ``` ##### Description Stop publishing values from a node on the specified server. The group field that was used in the Connection Model to start publishing must also be specified in this connection model. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The node to stop publishing|[PublishStopRequestModelRequestEnvelope](definitions.md#publishstoprequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful.|[PublishStopResponseModel](definitions.md#publishstopresponsemodel)| |**404**|The item could not be unpublished|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` ### Diagnostics This section lists the diagnostics APi provided by OPC Publisher providing connection related diagnostics API methods. The method name for all transports other than HTTP (which uses the shown HTTP methods and resource uris) is the name of the subsection header. To use the version specific method append "_V1" or "_V2" to the method name. #### GetActiveConnections ``` GET /v2/connections ``` ##### Description Get all active connections the publisher is currently managing. ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful.|< [ConnectionModel](definitions.md#connectionmodel) > array| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Produces * `application/json` * `application/x-msgpack` #### GetChannelDiagnostics ``` GET /v2/diagnostics/channels ``` ##### Description Get channel diagnostic information for all connections. ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful.|< [ChannelDiagnosticModel](definitions.md#channeldiagnosticmodel) > array| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Produces * `application/json` * `application/x-msgpack` #### WatchChannelDiagnostics ``` GET /v2/diagnostics/channels/watch ``` ##### Description Get channel diagnostic information for all connections. The first set of diagnostics are the diagnostics active for all connections, continue reading to get updates. ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful.|[ChannelDiagnosticModelIAsyncEnumerable](definitions.md#channeldiagnosticmodeliasyncenumerable)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Produces * `application/json` * `application/x-msgpack` #### GetConnectionDiagnostics ``` GET /v2/diagnostics/connections ``` ##### Description Get diagnostics for all active clients including server and client session diagnostics. ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful.|[ConnectionDiagnosticsModelIAsyncEnumerable](definitions.md#connectiondiagnosticsmodeliasyncenumerable)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Produces * `application/json` * `application/x-msgpack` #### ResetAllConnections ``` GET /v2/reset ``` ##### Description Can be used to reset all established connections causing a full reconnect and recreate of all subscriptions. ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful.|No Content| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Produces * `application/json` * `application/x-msgpack` ### Discovery OPC UA and network discovery related API. The method name for all transports other than HTTP (which uses the shown HTTP methods and resource uris) is the name of the subsection header. To use the version specific method append "_V1" or "_V2" to the method #### Discover ``` POST /v2/discovery ``` ##### Description Start network discovery using the provided discovery request configuration. The discovery results are published to the configured default event transport. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The discovery configuration to use during the discovery run.|[DiscoveryRequestModel](definitions.md#discoveryrequestmodel)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|boolean| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### Cancel ``` POST /v2/discovery/cancel ``` ##### Description Cancel a discovery run that is ongoing using the discovery request token specified in the discover operation. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The information needed to cancel the discovery operation.|[DiscoveryCancelRequestModel](definitions.md#discoverycancelrequestmodel)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|boolean| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### FindServer ``` POST /v2/discovery/findserver ``` ##### Description Find servers matching the specified endpoint query spec. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The endpoint query specifying the matching criteria for the discovered endpoints.|[ServerEndpointQueryModel](definitions.md#serverendpointquerymodel)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[ApplicationRegistrationModel](definitions.md#applicationregistrationmodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### Register ``` POST /v2/discovery/register ``` ##### Description Start server registration. The results of the registration are published as events to the default event transport. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|Contains all information to perform the registration request including discovery url to use.|[ServerRegistrationRequestModel](definitions.md#serverregistrationrequestmodel)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|boolean| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` ### FileSystem This section lists the file transfer API provided by OPC Publisher providing access to file transfer services to move files in and out of a server using the File transfer specification. The method name for all transports other than HTTP (which uses the shown HTTP methods and resource uris) is the name of the subsection header. To use the version specific method append "_V1" or "_V2" to the method name. #### CreateDirectory ``` POST /v2/filesystem/create/directory/{name} ``` ##### Description Create a new directory in an existing file system or directory on the server. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Path**|**name**
*required*|The name of the directory to create as child under the parent directory provided|string| |**Body**|**body**
*required*|The file system or directory object to create the directory in and the connection information identifying the server to connect to perform the operation on.|[FileSystemObjectModelRequestEnvelope](definitions.md#filesystemobjectmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[FileSystemObjectModelServiceResponse](definitions.md#filesystemobjectmodelserviceresponse)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### CreateFile ``` POST /v2/filesystem/create/file/{name} ``` ##### Description Create a new file in a directory or file system on the server ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Path**|**name**
*required*|The name of the file to create as child under the directory or filesystem provided|string| |**Body**|**body**
*required*|The file system or directory object to create the file in and the connection information identifying the server to connect to perform the operation on.|[FileSystemObjectModelRequestEnvelope](definitions.md#filesystemobjectmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[FileSystemObjectModelServiceResponse](definitions.md#filesystemobjectmodelserviceresponse)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### DeleteFileSystemObject ``` POST /v2/filesystem/delete ``` ##### Description Delete a file or directory in an existing file system on the server. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The file or directory object to delete and the connection information identifying the server to connect to perform the operation on.|[FileSystemObjectModelRequestEnvelope](definitions.md#filesystemobjectmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[ServiceResultModel](definitions.md#serviceresultmodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### DeleteFileOrDirectory ``` POST /v2/filesystem/delete/{fileOrDirectoryNodeId} ``` ##### Description Delete a file or directory in the specified directory or file system. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Path**|**fileOrDirectoryNodeId**
*required*|The node id of the file or directory to delete|string| |**Body**|**body**
*required*|The filesystem or directory object in which to delete the specified file or directory and the connection to use for the operation.|[FileSystemObjectModelRequestEnvelope](definitions.md#filesystemobjectmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[ServiceResultModel](definitions.md#serviceresultmodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### Download ``` GET /v2/filesystem/download ``` ##### Description Download a file from the server ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Header**|**x-ms-connection**
*required*|The connection information identifying the server to connect to perform the operation on. This is passed as json serialized via the header "x-ms-connection"|string| |**Header**|**x-ms-target**
*required*|The file object to upload. This is passed as json serialized via the header "x-ms-target"|string| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|No Content| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Produces * `application/json` * `application/x-msgpack` #### GetFileInfo ``` POST /v2/filesystem/info/file ``` ##### Description Gets the file information for a file on the server. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The file object and connection information identifying the server to connect to perform the operation on.|[FileSystemObjectModelRequestEnvelope](definitions.md#filesystemobjectmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[FileInfoModelServiceResponse](definitions.md#fileinfomodelserviceresponse)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### GetFileSystems ``` POST /v2/filesystem/list ``` ##### Description Gets all file systems of the server. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The connection information identifying the server to connect to perform the operation on.|[ConnectionModel](definitions.md#connectionmodel)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[FileSystemObjectModelServiceResponseIAsyncEnumerable](definitions.md#filesystemobjectmodelserviceresponseiasyncenumerable)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### GetDirectories ``` POST /v2/filesystem/list/directories ``` ##### Description Gets all directories in a directory or file system ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The directory or filesystem object and connection information identifying the server to connect to perform the operation on.|[FileSystemObjectModelRequestEnvelope](definitions.md#filesystemobjectmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[FileSystemObjectModelIEnumerableServiceResponse](definitions.md#filesystemobjectmodelienumerableserviceresponse)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### GetFiles ``` POST /v2/filesystem/list/files ``` ##### Description Get files in a directory or file system on a server. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The directory or filesystem object and connection information identifying the server to connect to perform the operation on.|[FileSystemObjectModelRequestEnvelope](definitions.md#filesystemobjectmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[FileSystemObjectModelIEnumerableServiceResponse](definitions.md#filesystemobjectmodelienumerableserviceresponse)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### GetParent ``` POST /v2/filesystem/parent ``` ##### Description Gets the parent directory or filesystem of a file or directory. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The file or directory object and connection information identifying the server to connect to perform the operation on.|[FileSystemObjectModelRequestEnvelope](definitions.md#filesystemobjectmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[FileSystemObjectModelServiceResponse](definitions.md#filesystemobjectmodelserviceresponse)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### Upload ``` POST /v2/filesystem/upload ``` ##### Description Upload a file to the server. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Header**|**x-ms-connection**
*required*|The connection information identifying the server to connect to perform the operation on. This is passed as json serialized via the header "x-ms-connection"|string| |**Header**|**x-ms-options**
*required*|The file write options to use passed as header "x-ms-mode"|string| |**Header**|**x-ms-target**
*required*|The file object to upload. This is passed as json serialized via the header "x-ms-target"|string| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|No Content| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Produces * `application/json` * `application/x-msgpack` ### General This section lists the general APi provided by OPC Publisher providing all connection, endpoint and address space related API methods. The method name for all transports other than HTTP (which uses the shown HTTP methods and resource uris) is the name of the subsection header. To use the version specific method append "_V1" or "_V2" to the method name. #### BrowseStream (only HTTP transport) ``` POST /v2/browse ``` ##### Description Recursively browse a node to discover its references and nodes. The results are returned as a stream of nodes and references. Consult the relevant section of the OPC UA reference specification for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The request payload and connection information identifying the server to connect to perform the operation on.|[BrowseStreamRequestModelRequestEnvelope](definitions.md#browsestreamrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[BrowseStreamChunkModelIAsyncEnumerable](definitions.md#browsestreamchunkmodeliasyncenumerable)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### Browse ``` POST /v2/browse/first ``` ##### Description Browse a a node to discover its references. For more information consult the relevant section of the OPC UA reference specification. The operation might return a continuation token. The continuation token can be used in the BrowseNext method call to retrieve the remainder of references or additional continuation tokens. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The request payload and connection information identifying the server to connect to perform the operation on.|[BrowseFirstRequestModelRequestEnvelope](definitions.md#browsefirstrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[BrowseFirstResponseModel](definitions.md#browsefirstresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### BrowseNext ``` POST /v2/browse/next ``` ##### Description Browse next ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The request payload and connection information identifying the server to connect to perform the operation on.|[BrowseNextRequestModelRequestEnvelope](definitions.md#browsenextrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[BrowseNextResponseModel](definitions.md#browsenextresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### BrowsePath ``` POST /v2/browse/path ``` ##### Description Translate a start node and browse path into 0 or more target nodes. Allows programming aginst types in OPC UA. For more information consult the relevant section of the OPC UA reference specification. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The request payload and connection information identifying the server to connect to perform the operation on.|[BrowsePathRequestModelRequestEnvelope](definitions.md#browsepathrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[BrowsePathResponseModel](definitions.md#browsepathresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### MethodCall ``` POST /v2/call ``` ##### Description Call a method on the OPC UA server endpoint with the specified input arguments and received the result in the form of the method output arguments. See the relevant section of the OPC UA reference specification for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The request payload and connection information identifying the server to connect to perform the operation on.|[MethodCallRequestModelRequestEnvelope](definitions.md#methodcallrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[MethodCallResponseModel](definitions.md#methodcallresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### MethodMetadata ``` POST /v2/call/$metadata ``` ##### Description Get the metadata for calling the method. This API is obsolete. Use the more powerful GetMetadata method instead. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The request payload and connection information identifying the server to connect to perform the operation on.|[MethodMetadataRequestModelRequestEnvelope](definitions.md#methodmetadatarequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[MethodMetadataResponseModel](definitions.md#methodmetadataresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### GetServerCapabilities ``` POST /v2/capabilities ``` ##### Description Get the capabilities of the server. The server capabilities are exposed as a property of the server object and this method provides a convinient way to retrieve them. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The request payload and connection information identifying the server to connect to perform the operation on.|[RequestHeaderModelRequestEnvelope](definitions.md#requestheadermodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[ServerCapabilitiesModel](definitions.md#servercapabilitiesmodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### GetEndpointCertificate ``` POST /v2/certificate ``` ##### Description Get a server endpoint's certificate and certificate chain if available. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The server endpoint to get the certificate for.|[EndpointModel](definitions.md#endpointmodel)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[X509CertificateChainModel](definitions.md#x509certificatechainmodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryGetServerCapabilities ``` POST /v2/history/capabilities ``` ##### Description Get the historian capabilities exposed as part of the OPC UA server server object. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The request payload and connection information identifying the server to connect to perform the operation on.|[RequestHeaderModelRequestEnvelope](definitions.md#requestheadermodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[HistoryServerCapabilitiesModel](definitions.md#historyservercapabilitiesmodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryGetConfiguration ``` POST /v2/history/configuration ``` ##### Description Get the historian configuration of a historizing node in the OPC UA server ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The request payload and connection information identifying the server to connect to perform the operation on.|[HistoryConfigurationRequestModelRequestEnvelope](definitions.md#historyconfigurationrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[HistoryConfigurationResponseModel](definitions.md#historyconfigurationresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryRead ``` POST /v2/historyread/first ``` ##### Description Read the history using the respective OPC UA service call. See the relevant section of the OPC UA reference specification for more information. If continuation is returned the remaining results of the operation can be read using the HistoryReadNext method. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The request payload and connection information identifying the server to connect to perform the operation on.|[VariantValueHistoryReadRequestModelRequestEnvelope](definitions.md#variantvaluehistoryreadrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[VariantValueHistoryReadResponseModel](definitions.md#variantvaluehistoryreadresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryReadNext ``` POST /v2/historyread/next ``` ##### Description Read next history using the respective OPC UA service call. See the relevant section of the OPC UA reference specification for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The request payload and connection information identifying the server to connect to perform the operation on.|[HistoryReadNextRequestModelRequestEnvelope](definitions.md#historyreadnextrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[VariantValueHistoryReadNextResponseModel](definitions.md#variantvaluehistoryreadnextresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryUpdate ``` POST /v2/historyupdate ``` ##### Description Update history using the respective OPC UA service call. Consult the relevant section of the OPC UA reference specification for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The request payload and connection information identifying the server to connect to perform the operation on.|[VariantValueHistoryUpdateRequestModelRequestEnvelope](definitions.md#variantvaluehistoryupdaterequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[HistoryUpdateResponseModel](definitions.md#historyupdateresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### GetMetadata ``` POST /v2/metadata ``` ##### Description Get the type metadata for a any node. For data type nodes the response contains the data type metadata including fields. For method nodes the output and input arguments metadata is provided. For objects and object types the instance declaration is returned. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The request payload and connection information identifying the server to connect to perform the operation on.|[NodeMetadataRequestModelRequestEnvelope](definitions.md#nodemetadatarequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[NodeMetadataResponseModel](definitions.md#nodemetadataresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### CompileQuery ``` POST /v2/query/compile ``` ##### Description Compile a query string into a query spec that can be used when setting up event filters on monitored items that monitor events. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The compilation request and connection information.|[QueryCompilationRequestModelRequestEnvelope](definitions.md#querycompilationrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[QueryCompilationResponseModel](definitions.md#querycompilationresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### ValueRead ``` POST /v2/read ``` ##### Description Read the value of a variable node. This uses the service detailed in the relevant section of the OPC UA reference specification. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The request payload and connection information identifying the server to connect to perform the operation on.|[ValueReadRequestModelRequestEnvelope](definitions.md#valuereadrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[ValueReadResponseModel](definitions.md#valuereadresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### NodeRead ``` POST /v2/read/attributes ``` ##### Description Read any writeable attribute of a specified node on the server. See the relevant section of the OPC UA reference specification for more information. The attributes supported by the node are dependend on the node class of the node. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The request payload and connection information identifying the server to connect to perform the operation on.|[ReadRequestModelRequestEnvelope](definitions.md#readrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[ReadResponseModel](definitions.md#readresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### TestConnection ``` POST /v2/test ``` ##### Description Test connection to an opc ua server. The call will not establish any persistent connection but will just allow a client to test that the server is available. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The request payload and connection information identifying the server to connect to perform the operation on.|[TestConnectionRequestModelRequestEnvelope](definitions.md#testconnectionrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[TestConnectionResponseModel](definitions.md#testconnectionresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### ValueWrite ``` POST /v2/write ``` ##### Description Write the value of a variable node. This uses the service detailed in the relevant section of the OPC UA reference specification. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The request payload and connection information identifying the server to connect to perform the operation on.|[ValueWriteRequestModelRequestEnvelope](definitions.md#valuewriterequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[ValueWriteResponseModel](definitions.md#valuewriteresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### NodeWrite ``` POST /v2/write/attributes ``` ##### Description Write any writeable attribute of a specified node on the server. See the relevant section of the OPC UA reference specification for more information. The attributes supported by the node are dependend on the node class of the node. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The request payload and connection information identifying the server to connect to perform the operation on.|[WriteRequestModelRequestEnvelope](definitions.md#writerequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[WriteResponseModel](definitions.md#writeresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` ### History This section lists all OPC UA HDA or Historian related API provided by OPC Publisher. The method name for all transports other than HTTP (which uses the shown HTTP methods and resource uris) is the name of the subsection header. To use the version specific method append "_V1" or "_V2" to the method name. #### HistoryDeleteEvents ``` POST /v2/history/events/delete ``` ##### Description Delete event entries in a timeseries of the server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The events to delete in the timeseries.|[DeleteEventsDetailsModelHistoryUpdateRequestModelRequestEnvelope](definitions.md#deleteeventsdetailsmodelhistoryupdaterequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[HistoryUpdateResponseModel](definitions.md#historyupdateresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryInsertEvents ``` POST /v2/history/events/insert ``` ##### Description Insert event entries into a specified timeseries of the historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The events to insert into the timeseries.|[UpdateEventsDetailsModelHistoryUpdateRequestModelRequestEnvelope](definitions.md#updateeventsdetailsmodelhistoryupdaterequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[HistoryUpdateResponseModel](definitions.md#historyupdateresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryStreamEvents (only HTTP transport) ``` POST /v2/history/events/read ``` ##### Description Read an entire event timeseries from an OPC UA server historian as stream. See the relevant section of the OPC UA reference specification and respective service documentation for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The events to read in the timeseries.|[ReadEventsDetailsModelHistoryReadRequestModelRequestEnvelope](definitions.md#readeventsdetailsmodelhistoryreadrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[HistoricEventModelIAsyncEnumerable](definitions.md#historiceventmodeliasyncenumerable)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryReadEvents ``` POST /v2/history/events/read/first ``` ##### Description Read an event timeseries inside the OPC UA server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The events to read in the timeseries.|[ReadEventsDetailsModelHistoryReadRequestModelRequestEnvelope](definitions.md#readeventsdetailsmodelhistoryreadrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[HistoricEventModelArrayHistoryReadResponseModel](definitions.md#historiceventmodelarrayhistoryreadresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryReadEventsNext ``` POST /v2/history/events/read/next ``` ##### Description Continue reading an event timeseries inside the OPC UA server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The continuation from a previous read request.|[HistoryReadNextRequestModelRequestEnvelope](definitions.md#historyreadnextrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[HistoricEventModelArrayHistoryReadNextResponseModel](definitions.md#historiceventmodelarrayhistoryreadnextresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryReplaceEvents ``` POST /v2/history/events/replace ``` ##### Description Replace events in a timeseries in the historian of the OPC UA server. See the relevant section of the OPC UA reference specification and respective service documentation for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The events to replace with in the timeseries.|[UpdateEventsDetailsModelHistoryUpdateRequestModelRequestEnvelope](definitions.md#updateeventsdetailsmodelhistoryupdaterequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[HistoryUpdateResponseModel](definitions.md#historyupdateresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryUpsertEvents ``` POST /v2/history/events/upsert ``` ##### Description Upsert events into a time series of the opc server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The events to upsert into the timeseries.|[UpdateEventsDetailsModelHistoryUpdateRequestModelRequestEnvelope](definitions.md#updateeventsdetailsmodelhistoryupdaterequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[HistoryUpdateResponseModel](definitions.md#historyupdateresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryDeleteValues ``` POST /v2/history/values/delete ``` ##### Description Delete value change entries in a timeseries of the server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The values to delete in the timeseries.|[DeleteValuesDetailsModelHistoryUpdateRequestModelRequestEnvelope](definitions.md#deletevaluesdetailsmodelhistoryupdaterequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[HistoryUpdateResponseModel](definitions.md#historyupdateresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryDeleteValuesAtTimes ``` POST /v2/history/values/delete/attimes ``` ##### Description Delete value change entries in a timeseries of the server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The values to delete in the timeseries.|[DeleteValuesAtTimesDetailsModelHistoryUpdateRequestModelRequestEnvelope](definitions.md#deletevaluesattimesdetailsmodelhistoryupdaterequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[HistoryUpdateResponseModel](definitions.md#historyupdateresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryDeleteModifiedValues ``` POST /v2/history/values/delete/modified ``` ##### Description Delete value change entries in a timeseries of the server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The values to delete in the timeseries.|[DeleteValuesDetailsModelHistoryUpdateRequestModelRequestEnvelope](definitions.md#deletevaluesdetailsmodelhistoryupdaterequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[HistoryUpdateResponseModel](definitions.md#historyupdateresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryInsertValues ``` POST /v2/history/values/insert ``` ##### Description Insert value change entries in a timeseries of the server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The values to insert into the timeseries.|[UpdateValuesDetailsModelHistoryUpdateRequestModelRequestEnvelope](definitions.md#updatevaluesdetailsmodelhistoryupdaterequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[HistoryUpdateResponseModel](definitions.md#historyupdateresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryStreamValues (only HTTP transport) ``` POST /v2/history/values/read ``` ##### Description Read an entire timeseries from an OPC UA server historian as stream. See the relevant section of the OPC UA reference specification and respective service documentation for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The values to read in the timeseries.|[ReadValuesDetailsModelHistoryReadRequestModelRequestEnvelope](definitions.md#readvaluesdetailsmodelhistoryreadrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[HistoricValueModelIAsyncEnumerable](definitions.md#historicvaluemodeliasyncenumerable)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryStreamValuesAtTimes (only HTTP transport) ``` POST /v2/history/values/read/attimes ``` ##### Description Read specific timeseries data from an OPC UA server historian as stream. See the relevant section of the OPC UA reference specification and respective service documentation for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The values to read in the timeseries.|[ReadValuesAtTimesDetailsModelHistoryReadRequestModelRequestEnvelope](definitions.md#readvaluesattimesdetailsmodelhistoryreadrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[HistoricValueModelIAsyncEnumerable](definitions.md#historicvaluemodeliasyncenumerable)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryReadValues ``` POST /v2/history/values/read/first ``` ##### Description Read a data change timeseries inside the OPC UA server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The values to read in the timeseries.|[ReadValuesDetailsModelHistoryReadRequestModelRequestEnvelope](definitions.md#readvaluesdetailsmodelhistoryreadrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[HistoricValueModelArrayHistoryReadResponseModel](definitions.md#historicvaluemodelarrayhistoryreadresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryReadValuesAtTimes ``` POST /v2/history/values/read/first/attimes ``` ##### Description Read parts of a timeseries inside the OPC UA server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The values to read in the timeseries.|[ReadValuesAtTimesDetailsModelHistoryReadRequestModelRequestEnvelope](definitions.md#readvaluesattimesdetailsmodelhistoryreadrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[HistoricValueModelArrayHistoryReadResponseModel](definitions.md#historicvaluemodelarrayhistoryreadresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryReadModifiedValues ``` POST /v2/history/values/read/first/modified ``` ##### Description Read modified changes in a timeseries inside the OPC UA server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The values to read in the timeseries.|[ReadModifiedValuesDetailsModelHistoryReadRequestModelRequestEnvelope](definitions.md#readmodifiedvaluesdetailsmodelhistoryreadrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[HistoricValueModelArrayHistoryReadResponseModel](definitions.md#historicvaluemodelarrayhistoryreadresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryReadProcessedValues ``` POST /v2/history/values/read/first/processed ``` ##### Description Read processed timeseries data inside the OPC UA server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The values to read in the timeseries.|[ReadProcessedValuesDetailsModelHistoryReadRequestModelRequestEnvelope](definitions.md#readprocessedvaluesdetailsmodelhistoryreadrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[HistoricValueModelArrayHistoryReadResponseModel](definitions.md#historicvaluemodelarrayhistoryreadresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryStreamModifiedValues (only HTTP transport) ``` POST /v2/history/values/read/modified ``` ##### Description Read an entire modified series from an OPC UA server historian as stream. See the relevant section of the OPC UA reference specification and respective service documentation for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The values to read in the timeseries.|[ReadModifiedValuesDetailsModelHistoryReadRequestModelRequestEnvelope](definitions.md#readmodifiedvaluesdetailsmodelhistoryreadrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[HistoricValueModelIAsyncEnumerable](definitions.md#historicvaluemodeliasyncenumerable)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryReadValuesNext ``` POST /v2/history/values/read/next ``` ##### Description Continue reading a timeseries inside the OPC UA server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The continuation token from a previous read operation.|[HistoryReadNextRequestModelRequestEnvelope](definitions.md#historyreadnextrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[HistoricValueModelArrayHistoryReadNextResponseModel](definitions.md#historicvaluemodelarrayhistoryreadnextresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryStreamProcessedValues (only HTTP transport) ``` POST /v2/history/values/read/processed ``` ##### Description Read processed timeseries data from an OPC UA server historian as stream. See the relevant section of the OPC UA reference specification and respective service documentation for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The values to read in the timeseries.|[ReadProcessedValuesDetailsModelHistoryReadRequestModelRequestEnvelope](definitions.md#readprocessedvaluesdetailsmodelhistoryreadrequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[HistoricValueModelIAsyncEnumerable](definitions.md#historicvaluemodeliasyncenumerable)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryReplaceValues ``` POST /v2/history/values/replace ``` ##### Description Replace value change entries in a timeseries of the server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The values to replace with in the timeseries.|[UpdateValuesDetailsModelHistoryUpdateRequestModelRequestEnvelope](definitions.md#updatevaluesdetailsmodelhistoryupdaterequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[HistoryUpdateResponseModel](definitions.md#historyupdateresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### HistoryUpsertValues ``` POST /v2/history/values/upsert ``` ##### Description Upsert value change entries in a timeseries of the server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The values to upsert into the timeseries.|[UpdateValuesDetailsModelHistoryUpdateRequestModelRequestEnvelope](definitions.md#updatevaluesdetailsmodelhistoryupdaterequestmodelrequestenvelope)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The operation was successful or the response payload contains relevant error information.|[HistoryUpdateResponseModel](definitions.md#historyupdateresponsemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` ### Writer This section contains the API to configure data set writers and writer groups inside OPC Publisher. It supersedes the configuration API. Applications should use one or the other, but not both at the same time. The method name for all transports other than HTTP (which uses the shown HTTP methods and resource uris) is the name of the subsection header. To use the version specific method append "_V1" or "_V2" to the method name. #### ExpandAndCreateOrUpdateDataSetWriterEntries ``` POST /v2/writer ``` ##### Description Create a series of published nodes entries using the provided entry as template. The entry is expanded using expansion configuration provided. Expanded entries are returned one by one with error information if any. The configuration is also saved in the local configuration store. The server must be online and accessible for the expansion to work. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The entry to create for the writer and node expansion configuration to use|[PublishedNodeExpansionModelPublishedNodesEntryRequestModel](definitions.md#publishednodeexpansionmodelpublishednodesentryrequestmodel)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The item was created|[PublishedNodesEntryModelServiceResponseIAsyncEnumerable](definitions.md#publishednodesentrymodelserviceresponseiasyncenumerable)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**403**|A unique item could not be found to update.|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### CreateOrUpdateDataSetWriterEntry ``` PUT /v2/writer ``` ##### Description Create a published nodes entry for a specific writer group and dataset writer. The entry must specify a unique writer group and dataset writer id. A null value is treated as empty string. If the entry is found it is replaced, if it is not found, it is created. If more than one entry is found with the same writer group and writer id an error is returned. The writer entry provided must include at least one node which will be the initial set. All nodes must specify a unique dataSetFieldId. A null value is treated as empty string. Publishing intervals at node level are also not supported and generate an error. Publishing intervals must be configured at the data set writer level. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The entry to create for the writer|[PublishedNodesEntryModel](definitions.md#publishednodesentrymodel)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The item was created|No Content| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**403**|A unique item could not be found to update.|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### CreateOrUpdateAsset ``` POST /v2/writer/assets ``` ##### Description Creates an asset from the entry in the request and the configuration provided in the Web of Things Asset json configuration property. The entry must contain a data set name which will be used as the asset name. The writer can stay empty. It will be set to the asset id on successful return. The server must support the WoT profile per . The asset will be created and the configuration updated to reference it. A wait time can be provided as optional query parameter to wait until the server has settled after uploading the configuration. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The contains the entry and WoT file to configure the server to expose the asset.|[VariantValuePublishedNodeCreateAssetRequestModel](definitions.md#variantvaluepublishednodecreateassetrequestmodel)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The asset was created|[PublishedNodesEntryModelServiceResponse](definitions.md#publishednodesentrymodelserviceresponse)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**403**|Forbidden|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### CreateOrUpdateAsset (With binary configuration) ``` POST /v2/writer/assets/create ``` ##### Description Creates an asset from the entry in the request and the configuration provided in the Web of Things Asset configuration byte buffer. The entry must contain a data set name which will be used as the asset name. The writer can stay empty. It will be set to the asset id on successful return. The server must support the WoT profile per . The asset will be created and the configuration updated to reference it. A wait time can be provided as optional query parameter to wait until the server has settled after uploading the configuration. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The contains the entry and WoT file to configure the server to expose the asset.|[ByteArrayPublishedNodeCreateAssetRequestModel](definitions.md#bytearraypublishednodecreateassetrequestmodel)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The asset was created|[PublishedNodesEntryModelServiceResponse](definitions.md#publishednodesentrymodelserviceresponse)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**403**|Forbidden|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### DeleteAsset ``` POST /v2/writer/assets/delete ``` ##### Description Delete the asset referenced by the entry in the request. The entry must contain the asset id to delete. The asset id is the data set writer id. The entry must also contain the writer group id or deletion of the asset in the configuration will fail before the asset is deleted. The server must support WoT connectivity profile per . First the entry in the configuration will be deleted and then the asset on the server. If deletion of the asset in the configuration fails it will not be deleted in the server. An optional request option force can be used to force the deletion of the asset in the server regardless of the failure to delete the entry in the configuration. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|Request that contains the entry of the asset that should be deleted.|[PublishedNodeDeleteAssetRequestModel](definitions.md#publishednodedeleteassetrequestmodel)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The asset was deleted successfully|[ServiceResultModel](definitions.md#serviceresultmodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**403**|Forbidden|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### GetAllAssets ``` POST /v2/writer/assets/list ``` ##### Description Get a list of entries representing the assets in the server. This will not touch the configuration, it will obtain the list from the server. If the server does not support the result will be empty. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The entry to use to list the assets with the optional header information used when invoking services on the server.|[RequestHeaderModelPublishedNodesEntryRequestModel](definitions.md#requestheadermodelpublishednodesentryrequestmodel)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|Successfully completed the listing|[PublishedNodesEntryModelServiceResponseIAsyncEnumerable](definitions.md#publishednodesentrymodelserviceresponseiasyncenumerable)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**403**|Forbidden|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### ExpandWriter ``` POST /v2/writer/expand ``` ##### Description Expands the provided nodes in the entry to a series of published node entries. The provided entry is used template. The entry is expanded using expansion configuration provided. Expanded entries are returned one by one with error information if any. The configuration is not updated but the resulting entries can be modified and later saved in the configuration using the configuration API. The server must be online and accessible for the expansion to work. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Body**|**body**
*required*|The entry to expand and the node expansion configuration to use. If no configuration is provided a default configuration is used which and no error entries are returned.|[PublishedNodeExpansionModelPublishedNodesEntryRequestModel](definitions.md#publishednodeexpansionmodelpublishednodesentryrequestmodel)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The item was created|[PublishedNodesEntryModelServiceResponseIAsyncEnumerable](definitions.md#publishednodesentrymodelserviceresponseiasyncenumerable)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**403**|A unique item could not be found to update.|[ProblemDetails](definitions.md#problemdetails)| |**408**|The operation timed out.|[ProblemDetails](definitions.md#problemdetails)| |**500**|An unexpected error occurred|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### GetDataSetWriterEntry ``` GET /v2/writer/{dataSetWriterGroup}/{dataSetWriterId} ``` ##### Description Get the published nodes entry for a specific writer group and dataset writer. Dedicated errors are returned if no, or no unique entry could be found. The entry does not contain the nodes. Nodes can be retrieved using the GetNodes API. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Path**|**dataSetWriterGroup**
*required*|The writer group name of the entry|string| |**Path**|**dataSetWriterId**
*required*|The data set writer identifer of the entry|string| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The item was found|[PublishedNodesEntryModel](definitions.md#publishednodesentrymodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**403**|There is no unique item present.|[ProblemDetails](definitions.md#problemdetails)| |**404**|The item was not found|[ProblemDetails](definitions.md#problemdetails)| ##### Produces * `application/json` * `application/x-msgpack` #### AddOrUpdateNode ``` PUT /v2/writer/{dataSetWriterGroup}/{dataSetWriterId} ``` ##### Description Add a node to a dedicated data set writer in a writer group. A node must have a unique DataSetFieldId. If the field already exists, the node is updated. If a node does not have a dataset field id an error is returned. Publishing intervals at node level are also not supported and generate an error. Publishing intervals must be configured at the data set writer level. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Path**|**dataSetWriterGroup**
*required*|The writer group name of the entry|string| |**Path**|**dataSetWriterId**
*required*|The data set writer identifer of the entry|string| |**Query**|**insertAfterFieldId**
*optional*|Field after which to insert the nodes. If not specified, nodes are added at the end of the entry|string| |**Body**|**body**
*required*|Node to add or update|[OpcNodeModel](definitions.md#opcnodemodel)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The item was added|No Content| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**403**|A unique item could not be found to update.|[ProblemDetails](definitions.md#problemdetails)| |**404**|An entry was not found to add the node to|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### RemoveDataSetWriterEntry ``` DELETE /v2/writer/{dataSetWriterGroup}/{dataSetWriterId} ``` ##### Description Remove the published nodes entry for a specific data set writer in a writer group. Dedicated errors are returned if no, or no unique entry could be found. ##### Parameters |Type|Name|Description|Schema|Default| |---|---|---|---|---| |**Path**|**dataSetWriterGroup**
*required*|The writer group name of the entry|string|| |**Path**|**dataSetWriterId**
*required*|The data set writer identifer of the entry|string|| |**Query**|**force**
*optional*|Force delete all writers even if more than one were found. Does not error when none were found.|boolean|`"false"`| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The entry was removed|No Content| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**403**|A unique item could not be found to remove.|[ProblemDetails](definitions.md#problemdetails)| |**404**|The entry to remove was not found|[ProblemDetails](definitions.md#problemdetails)| ##### Produces * `application/json` * `application/x-msgpack` #### AddOrUpdateNodes ``` POST /v2/writer/{dataSetWriterGroup}/{dataSetWriterId}/add ``` ##### Description Add Nodes to a dedicated data set writer in a writer group. Each node must have a unique DataSetFieldId. If the field already exists, the node is updated. If a node does not have a dataset field id an error is returned. Publishing intervals at node level are also not supported and generate an error. Publishing intervals must be configured at the data set writer level. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Path**|**dataSetWriterGroup**
*required*|The writer group name of the entry|string| |**Path**|**dataSetWriterId**
*required*|The data set writer identifer of the entry|string| |**Query**|**insertAfterFieldId**
*optional*|Field after which to insert the nodes. If not specified, nodes are added at the end of the entry|string| |**Body**|**body**
*required*|Nodes to add or update|< [OpcNodeModel](definitions.md#opcnodemodel) > array| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The items were added|No Content| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**403**|A unique entry could not be found to add to.|[ProblemDetails](definitions.md#problemdetails)| |**404**|The entry was not found|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### GetNodes ``` GET /v2/writer/{dataSetWriterGroup}/{dataSetWriterId}/nodes ``` ##### Description Get Nodes from a data set writer in a writer group. The nodes can optionally be offset from a previous last node identified by the dataSetFieldId and pageanated by the pageSize. If the dataSetFieldId is not found, an empty list is returned. If the dataSetFieldId is not specified, the first page is returned. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Path**|**dataSetWriterGroup**
*required*|The writer group name of the entry|string| |**Path**|**dataSetWriterId**
*required*|The data set writer identifer of the entry|string| |**Query**|**lastDataSetFieldId**
*optional*|the field id after which to start the page. If not specified, nodes from the beginning are returned.|string| |**Query**|**pageSize**
*optional*|Number of nodes to return|integer (int32)| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The items were found|< [OpcNodeModel](definitions.md#opcnodemodel) > array| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**403**|A unique item could not be found to get nodes from.|[ProblemDetails](definitions.md#problemdetails)| |**404**|The entry was not found|[ProblemDetails](definitions.md#problemdetails)| ##### Produces * `application/json` * `application/x-msgpack` #### RemoveNodes ``` POST /v2/writer/{dataSetWriterGroup}/{dataSetWriterId}/remove ``` ##### Description Remove Nodes that match the provided data set field ids from a data set writer in a writer group. If one of the fields is not found, no error is returned, however, if all fields are not found an error is returned. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Path**|**dataSetWriterGroup**
*required*|The writer group name of the entry|string| |**Path**|**dataSetWriterId**
*required*|The data set writer identifer of the entry|string| |**Body**|**body**
*required*|The identifiers of the fields to remove|< string > array| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|Some or all items were removed|No Content| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**403**|A unique item could not be found to remove from.|[ProblemDetails](definitions.md#problemdetails)| |**404**|The entry or all items to remove were not found|[ProblemDetails](definitions.md#problemdetails)| ##### Consumes * `application/json` * `application/x-msgpack` ##### Produces * `application/json` * `application/x-msgpack` #### GetNode ``` GET /v2/writer/{dataSetWriterGroup}/{dataSetWriterId}/{dataSetFieldId} ``` ##### Description Get a node from a dataset in a writer group. Dedicated errors are returned if no, or no unique entry could be found, or the node does not exist. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Path**|**dataSetFieldId**
*required*|The data set field id of the node to return|string| |**Path**|**dataSetWriterGroup**
*required*|The writer group name of the entry|string| |**Path**|**dataSetWriterId**
*required*|The data set writer identifer of the entry|string| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The item was retrieved|[OpcNodeModel](definitions.md#opcnodemodel)| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**403**|A unique item could not be found to get a node from.|[ProblemDetails](definitions.md#problemdetails)| |**404**|The entry or item was not found|[ProblemDetails](definitions.md#problemdetails)| ##### Produces * `application/json` * `application/x-msgpack` #### RemoveNode ``` DELETE /v2/writer/{dataSetWriterGroup}/{dataSetWriterId}/{dataSetFieldId} ``` ##### Description Remove a node with the specified data set field id from a data set writer in a writer group. If the field is not found, an error is returned. ##### Parameters |Type|Name|Description|Schema| |---|---|---|---| |**Path**|**dataSetFieldId**
*required*|Identifier of the field to remove|string| |**Path**|**dataSetWriterGroup**
*required*|The writer group name of the entry|string| |**Path**|**dataSetWriterId**
*required*|The data set writer identifer of the entry|string| ##### Responses |HTTP Code|Description|Schema| |---|---|---| |**200**|The item was removed|No Content| |**400**|The passed in information is invalid|[ProblemDetails](definitions.md#problemdetails)| |**403**|A unique item could not be found to remove from.|[ProblemDetails](definitions.md#problemdetails)| |**404**|The entry or item to remove was not found|[ProblemDetails](definitions.md#problemdetails)| ##### Produces * `application/json` * `application/x-msgpack` ================================================ FILE: docs/opc-publisher/commandline.md ================================================ # OPC Publisher configuration via command line options and environment variables [Home](./readme.md) > This documentation applies to version 2.9 The following OPC Publisher configuration can be applied by Command Line Interface (CLI) options or as environment variable settings. Any CamelCase options can also be provided using environment variables (without the preceding `--`). When both environment variable and CLI argument are provided, the command line option will override the environment variable. > IMPORTANT: The command line of OPC Publisher only understands below command line options. You cannot specify environment variables on the command line (e.g., like `env1=value env2=value`). All option names are **case-sensitive**! Secrets such as `EdgeHubConnectionString`, other connection strings, or the `ApiKey` should never be provided on the command line or as environment variables. It should be avoided at all cost. A file using the `.env` format can be specified using the `ADDITIONAL_CONFIGURATION` environment variable. The contents will be loaded before the command line arguments are evaluated. If a file name is not provided via said environment variable, OPC Publisher tries to load the `/run/secrets/.env` file. This approach integrates well with [docker secrets](https://github.com/compose-spec/compose-spec/blob/master/05-services.md#secrets). An example of this can be found [here](https://raw.githubusercontent.com/Azure/Industrial-IoT/main/deploy/docker/docker-compose.yaml). > Please note that rolling of secrets is not supported and that any errors loading secrets is silently discarded. ```text ██████╗ ██████╗ ██████╗ ██████╗ ██╗ ██╗██████╗ ██╗ ██╗███████╗██╗ ██╗███████╗██████╗ ██╔═══██╗██╔══██╗██╔════╝ ██╔══██╗██║ ██║██╔══██╗██║ ██║██╔════╝██║ ██║██╔════╝██╔══██╗ ██║ ██║██████╔╝██║ ██████╔╝██║ ██║██████╔╝██║ ██║███████╗███████║█████╗ ██████╔╝ ██║ ██║██╔═══╝ ██║ ██╔═══╝ ██║ ██║██╔══██╗██║ ██║╚════██║██╔══██║██╔══╝ ██╔══██╗ ╚██████╔╝██║ ╚██████╗ ██║ ╚██████╔╝██████╔╝███████╗██║███████║██║ ██║███████╗██║ ██║ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝╚══════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ 2.9.15-rc.19+6ad3d509a8 (.NET 9.0.9/linux-x64/OPC Stack 1.5.377.11) General ------- -h, --help Show help and exit. -f, --pf, --publishfile, --PublishedNodesFile=VALUE The name of the file containing the configuration of the nodes to be published as well as the information to connect to the OPC UA server sources. This file is also used to persist changes made through the control plane, e.g., through IoT Hub device method calls. When no file is specified a default ` publishednodes.json` file is created in the working directory. Default: `publishednodes.json` --cf, --createifnotexist, --CreatePublishFileIfNotExist[=VALUE] Permit publisher to create the the specified publish file if it does not exist. The new file will be created under the access rights of the publisher module. The default file 'publishednodes.json' is always created when no file name was provided on the command line and this option is ignored. If a file was specified but does not exist and should not be created the module exits. Default: `false` --pol, --usepolling, --UseFileChangePolling[=VALUE] Poll for file changes instead of using a file system watcher. Use this setting when the underlying file system does not support file system notifications such as in some docker container setups. Default: `false` --fe, --forceencryptedcredentials, --ForceCredentialEncryption[=VALUE] If set to true the publisher will never write plain text credentials into the published nodes configuration file. If a credential cannot be written to the file using the IoT Edge workload API crypto provider the publisher will exit with an error. Default: `false` (write secrets as plain text into the configuration file which should be properly ACL'ed) --id, --publisherid, --PublisherId=VALUE Sets the publisher id of the publisher. Default: `not set` which results in the IoT edge identity being used -s, --site, --SiteId=VALUE Sets the site name of the publisher module. Default: `not set` --pi, --initfile, --InitFilePath[=VALUE] A file from which to read initialization instructions. Use this option to have OPC Publisher run a set of method calls found in this file. The file must be formatted using a subset of the .http/.rest file format without support for indentation, scripting or environment variables. Default: `not set` (disabled). If only a file name is specified, it is loaded from the path specifed using `--pn`. If just the argument is provided without a value the default is ` publishednodes.init`. --il, --initlog, --InitLogFile=VALUE A file into which the results of the initialization instructions are written. Only valid if `--pi` option is specified. Default: If a init file is set using `--pi`, it is appended with the `.log` extension. If just a file name is used, the file is created in the same folder as the init file configured using the `--pi` command line option. --rs, --runtimestatereporting, --RuntimeStateReporting[=VALUE] Enable that when publisher starts or restarts it reports its runtime state using a restart message. Default: `false` (disabled) --api-key, --ApiKey=VALUE Sets the api key that must be used to authenticate calls on the publisher REST endpoint. Default: `not set` (Key will be generated if not available) --doa, --disableopenapi, --DisableOpenApiEndpoint[=VALUE] Disable the OPC Publisher Open API endpoint exposed by the built-in HTTP server. Default: `false` (enabled). Messaging configuration ----------------------- -c, --strict, --UseStandardsCompliantEncoding[=VALUE] Use strict OPC UA standard compliance. It is recommended to run the publisher in compliant mode for best interoperability. Be aware that explicitly specifying other command line options can result in non- comnpliance despite this option being set. Default: `false` for backwards compatibility (2. 5.x - 2.8.x) --nf, --namespaceformat, --DefaultNamespaceFormat=VALUE The format to use when serializing node ids and qualified names containing a namespace uri into a string. Allowed values: `Uri` `Index` `Expanded` `ExpandedWithNamespace0` Default: `Expanded` if `-c` is specified, otherwise `Uri` for backwards compatibility. --mm, --messagingmode, --MessagingMode=VALUE The messaging mode for messages Allowed values: `PubSub` `Samples` `FullNetworkMessages` `FullSamples` `DataSetMessages` `SingleDataSetMessage` `DataSets` `SingleDataSet` `RawDataSets` `SingleRawDataSet` Default: `PubSub` if `-c` is specified, otherwise `Samples` for backwards compatibility. --ode, --optimizeddatasetencoding, --WriteValueWhenDataSetHasSingleEntry[=VALUE] When a data set has a single entry the encoder will write only the value of a data set entry and omit the key. This is not compliant with OPC UA Part 14. Default: `false`. --me, --messageencoding, --MessageEncoding=VALUE The message encoding for messages Allowed values: `Uadp` `Json` `Xml` `Avro` `IsReversible` `JsonReversible` `IsGzipCompressed` `JsonGzip` `AvroGzip` `JsonReversibleGzip` Default: `Json`. --bi, --batchtriggerinterval, --BatchTriggerInterval=VALUE The network message publishing interval in milliseconds. Determines the publishing period at which point messages are emitted. When `--bs` is 1 and `--bi` is set to 0 batching is disabled. Default: `10000` (10 seconds). Also can be set using `BatchTriggerInterval` environment variable in the form of a duration string in the form `[d.]hh:mm:ss[.fffffff]`. --bs, --batchsize, --BatchSize=VALUE The number of incoming OPC UA subscription notifications to collect until sending a network messages. When `--bs` is set to 1 and `--bi` is 0 batching is disabled and messages are sent as soon as notifications arrive. Default: `50`. --rdb, --removedupsinbatch, --RemoveDuplicatesFromBatch[=VALUE] Use this option to remove values with the same node id from batch messages in legacy `Samples` mode. Sends only the latest value as per the value's source timestamp. Only applies to `Samples` mode, otherwise this setting is ignored. Default: `false` (keep all duplicate values). --ms, --maxmessagesize, --iothubmessagesize, --IoTHubMaxMessageSize=VALUE The maximum size of the messages to emit. In case the encoder cannot encode a message because the size would be exceeded, the message is dropped. Otherwise the encoder will aim to chunk messages if possible. Default: `256k` in case of IoT Hub messages, `0` otherwise. --qos, --DefaultQualityOfService=VALUE The default quality of service to use for data set messages. This does not apply to metadata messages which are always sent with `AtLeastOnce` semantics. Allowed values: `AtMostOnce` `AtLeastOnce` `ExactlyOnce` Default: `AtLeastOnce`. --ttl, --DefaultMessageTimeToLive=VALUE The default time to live for all network message published in milliseconds if the transport supports it. This does not apply to metadata messages which are always sent with a ttl of the metadata update interval or infinite ttl. Default: `not set` (infinite). --retain, --DefaultMessageRetention[=VALUE] Whether by default to send messages with retain flag to a broker if the transport supports it. This does not apply to metadata messages which are always sent as retained messages. Default: `false'. --mts, --messagetimestamp, --MessageTimestamp=VALUE The value to set as as the timestamp property of messages during encoding (if the encoding supports writing message timestamps). Allowed values: `CurrentTimeUtc` `PublishTime` `EncodingTimeUtc` Default: `CurrentTimeUtc` to use the time when the message was created in OPC Publisher. --npd, --maxnodesperdataset, --MaxNodesPerDataSet=VALUE Maximum number of nodes within a Subscription. When there are more nodes configured for a data set writer, they will be added to new subscriptions. This also affects metadata message size. Default: `1000`. --kfc, --keyframecount, --DefaultKeyFrameCount=VALUE The default number of delta messages to send until a key frame message is sent. If 0, no key frame messages are sent, if 1, every message will be a key frame. Default: `0`. --ka, --sendkeepalives, --EnableDataSetKeepAlives[=VALUE] Enables sending keep alive messages triggered by writer subscription's keep alive notifications. This setting can be used to enable the messaging profile's support for keep alive messages. If the chosen messaging profile does not support keep alive messages this setting is ignored. Default: `false` (to save bandwidth). --kaf, --keepalivesaskeyframe, --SendDataSetKeepAlivesAsKeyFrame[=VALUE] When the sending of keep alive messages is enabled determines whether the empty keep alive message will be promoted to a key frame messages Default: `false`. --msi, --metadatasendinterval, --DefaultMetaDataUpdateTime=VALUE Default value in milliseconds for the metadata send interval which determines in which interval metadata is sent. Even when disabled, metadata is still sent when the metadata version changes unless `--mm=* Samples` is set in which case this setting is ignored. Only valid for network message encodings. Default: `0` which means periodic sending of metadata is disabled. --dm, --disablemetadata, --DisableDataSetMetaData[=VALUE] Disables sending any metadata when metadata version changes. This setting can be used to also override the messaging profile's default support for metadata sending. It is recommended to disable sending metadata when too many nodes are part of a data set as this can slow down start up time. Default: `false` if the messaging profile selected supports sending metadata and `--strict` is set but not '--dct', `True` otherwise. --amt, --asyncmetadataloadtimeout, --AsyncMetaDataLoadTimeout=VALUE The default duration in seconds a publish request should wait until the meta data is loaded. Loaded metadata guarantees a metadata message is sent before the first message is sent but loading of metadata takes time during subscription setup. Set to `0` to block until metadata is loaded. Only used if meta data is supported and enabled. Default: `5000` milliseconds. --ps, --publishschemas, --PublishMessageSchema[=VALUE] Publish the Avro or Json message schemas to schema registry or subtopics. Automatically enables complex type system and metadata support. Only has effect if the messaging profile supports publishing schemas. Default: `True` if the message encoding requires schemas (for example Avro) otherwise `False`. --asj, --preferavro, --PreferAvroOverJsonSchema[=VALUE] Publish Avro schema even for Json encoded messages. Automatically enables publishing schemas as if ` --ps` was set. Default: `false`. --daf, --disableavrofiles, --DisableAvroFileWriter[=VALUE] Disable writing avro files and instead dump messages and schema as zip files using the filesystem transport. Default: `false`. --om, --maxsendqueuesize, --MaxNetworkMessageSendQueueSize=VALUE The maximum number of messages to buffer on the send path before messages are dropped. Default: `4096` --wgp, --writergrouppartitions, --DefaultWriterGroupPartitionCount=VALUE The number of partitions to split the writer group into. Each partition represents a data flow to the transport sink. The partition is selected by topic hash. Default: `0` (partitioning is disabled) -t, --dmt, --defaultmessagetransport, --DefaultTransport=VALUE The desired transport to use to publish network messages with. Requires the transport to be properly configured (see transport settings). Allowed values: `IoTHub` `Mqtt` `EventHub` `Dapr` `Http` `FileSystem` `AioMqtt` `AioDss` `Null` Default: `IoTHub` or the first configured transport of the allowed value list. Transport settings ------------------ -b, --mqc, --mqttclientconnectionstring, --MqttClientConnectionString=VALUE An mqtt connection string to use. Use this option to connect OPC Publisher to a MQTT Broker endpoint. To connect to an MQTT broker use the format ' HostName=;Port=[;Username=< Username>;Password=;Protocol=<'v5'|' v311'>]'. To publish via MQTT by default specify `-t=Mqtt`. Default: `not set`. -e, --ec, --edgehubconnectionstring, --dc, --deviceconnectionstring, --EdgeHubConnectionString=VALUE A edge hub or iot hub connection string to use if you run OPC Publisher outside of IoT Edge. The connection string can be obtained from the IoT Hub portal. It is not required to use this option if running inside IoT Edge. To publish through IoT Edge by default specify `-t=IoTHub`. Default: `not set`. --ht, --ih, --iothubprotocol, --Transport=VALUE Protocol to use for communication with EdgeHub. Allowed values: `None` `AmqpOverTcp` `AmqpOverWebsocket` `Amqp` `MqttOverTcp` `Tcp` `MqttOverWebsocket` `Websocket` `Mqtt` `Any` Default: `Mqtt` if device or edge hub connection string is provided, ignored otherwise. --eh, --eventhubnamespaceconnectionstring, --EventHubNamespaceConnectionString=VALUE The connection string of an existing event hub namespace to use for the Azure EventHub transport. Default: `not set`. --sg, --schemagroup, --SchemaGroupName=VALUE The schema group in an event hub namespace to publish message schemas to. Default: `not set`. -d, --dcs, --daprconnectionstring, --DaprConnectionString=VALUE Connect the OPC Publisher to a dapr pub sub component using a connection string. The connection string specifies the PubSub component to use and allows you to configure the side car connection if needed. Use the format 'PubSubComponent= [;GrpcPort=;HttpPort=[; Scheme=<'https'|'http'>][;Host=]][; CheckSideCarHealth=<'true'|'false'>]'. To publish through dapr by default specify `-t= Dapr`. Default: `not set`. -w, --hcs, --httpconnectionstring, --HttpConnectionString=VALUE Allows OPC Publisher to publish multipart messages to a topic path using the http protocol (web hook). Specify the target host and configure the optional connection settings using a connection string of the format 'HostName=[; Port=][;Scheme=<'https'|'http'>][;Put=true] [;ApiKey=]'. To publish via HTTP by default specify `-t=Http`. Default: `not set`. -o, --outdir, --OutputRoot=VALUE A folder to write messages into. Use this option to have OPC Publisher write messages to a folder structure under this folder. The structure reflects the topic tree. To publish into the file system folder by default specify `-t=FileSystem`. Default: `not set`. -p, --httpserverport, --HttpServerPort=VALUE The port on which the http server of OPC Publisher is listening. Default: `443` if no value is provided. --unsecurehttp, --UnsecureHttpServerPort[=VALUE] Allow unsecure access to the REST api of OPC Publisher. A port can be specified if the default port 80 is not desired. Do not enable this in production as it exposes the Api Key on the network. Default: `disabled`, if specified without a port `80` port is used. --rtc, --renewtlscert, --RenewTlsCertificateOnStartup[=VALUE] If set a new tls certificate is created during startup updating any previously created ones. Default: `false`. --useopenapiv3, --UseOpenApiV3[=VALUE] If enabled exposes the open api schema of OPC Publisher using v3 schema (yaml). Only valid if Open API endpoint is not disabled. Default: `v2` (json). Routing configuration --------------------- --rtt, --roottopictemplate, --RootTopicTemplate[=VALUE] The default root topic of OPC Publisher. If not specified, the `{PublisherId}` template is the root topic. Currently only the template variables `{SiteId}` and `{PublisherId}` can be used as dynamic substituations in the template. If the template variable does not exist it is replaced with the `$default` string. Default: `{PublisherId}`. --mtt, --methodtopictemplate, --MethodTopicTemplate=VALUE The topic at which OPC Publisher's method handler is mounted. If not specified, the `{RootTopic}/methods` template will be used as root topic with the method names as sub topic. Only `{RootTopic}` `{SiteId}` and `{PublisherId}` can currently be used as replacement variables in the template. Default: `{RootTopic}/methods`. --ttt, --telemetrytopictemplate, --TelemetryTopicTemplate[=VALUE] The default topic that all messages are sent to. If not specified, the `{RootTopic}/messages/{ WriterGroup}` template will be used as root topic for all events sent by OPC Publisher. The template variables `{RootTopic}` `{SiteId}` `{Encoding}` `{PublisherId}` `{DataSetClassId}` `{DataSetWriter}` and `{WriterGroup}` can be used as dynamic parts in the template. If a template variable does not exist the name of the variable is emitted. Default: `{RootTopic}/messages/{WriterGroup}`. --ett, --eventstopictemplate, --EventsTopicTemplate=VALUE The topic into which OPC Publisher publishes any events that are not telemetry messages such as discovery or runtime events. If not specified, the `{RootTopic}/events` template will be used. Only `{RootTopic}` `{SiteId}` `{Encoding}` and `{PublisherId}` can currently be used as replacement variables in the template. Default: `{RootTopic}/events`. --dtt, --diagnosticstopictemplate, --DiagnosticsTopicTemplate=VALUE The topic into which OPC Publisher publishes writer group diagnostics events. If not specified, the `{RootTopic}/diagnostics/{ WriterGroup}` template will be used. Only `{RootTopic}` `{SiteId}` `{Encoding}` `{PublisherId}` and `{WriterGroup}` can currently be used as replacement variables in the template. Default: `{RootTopic}/diagnostics/{WriterGroup}` --mdt, --metadatatopictemplate, --DataSetMetaDataTopicTemplate[=VALUE] The topic that metadata should be sent to. In case of MQTT the message will by default be sent as RETAIN message with a TTL of either metadata send interval or infinite if metadata send interval is not configured. Only valid if metadata is supported and/or explicitely enabled. The template variables `{RootTopic}` `{SiteId}` `{TelemetryTopic}` `{Encoding}` `{PublisherId}` `{DataSetClassId}` `{DataSetWriter}` and `{WriterGroup}` can be used as dynamic parts in the template. Default: `{TelemetryTopic}` which means metadata is sent to the same output as regular messages. If specified without value, the default output is `{TelemetryTopic}/metadata`. --stt, --schematopictemplate, --SchemaTopicTemplate[=VALUE] The topic that schemas should be sent to if schema publishing is configured. In case of MQTT schemas will not be sent with . Only valid if schema publishing is enabled (`-- ps`). The template variables `{RootTopic}` `{SiteId}` `{PublisherId}` `{TelemetryTopic}` can be used as variables inside the template. Default: `{TelemetryTopic}/schema` which means the schema is sent to a sub topic where the telemetry message is sent to. --uns, --datasetrouting, --DefaultDataSetRouting=VALUE Configures whether messages should automatically be routed using the browse path of the monitored item inside the address space starting from the RootFolder. The browse path is appended as topic structure to the telemetry topic root which can be configured using `--ttt`. Reserved characters in browse names are escaped with their hex ASCII code. Allowed values: `None` `UseBrowseNames` `UseBrowseNamesWithNamespaceIndex` Default: `None` (Topics must be configured). --ri, --enableroutinginfo, --EnableRoutingInfo[=VALUE] Add routing information to messages. The name of the property is `$$RoutingInfo` and the value is the `DataSetWriterGroup` from which the particular message is emitted. Disabled if ` EnableCloudEvents` is enabled. Default: `False`. --ce, --cloudevents, --EnableCloudEvents[=VALUE] Add cloud event headers to messages. The cloud events comply to the opc ua cloud events extension. Default: `False`. Subscription settings --------------------- --oi, --opcsamplinginterval, --DefaultSamplingInterval=VALUE Default value in milliseconds to request the servers to sample values. This value is used if an explicit sampling interval for a node was not configured. Default: `1000`. Also can be set using `DefaultSamplingInterval` environment variable in the form of a duration string in the form `[d.]hh:mm:ss[.fffffff]`. --op, --opcpublishinginterval, --DefaultPublishingInterval=VALUE Default value in milliseconds for the publishing interval setting of a subscription created with an OPC UA server. This value is used if an explicit publishing interval was not configured. When setting `--op=0` the server decides the lowest publishing interval it can support. Default: `1000`. Also can be set using `DefaultPublishingInterval` environment variable in the form of a duration string in the form `[d.]hh:mm:ss[.fffffff]`. --eip, --immediatepublishing, --EnableImmediatePublishing[=VALUE] By default OPC Publisher will create a subscription with publishing disabled and only enable it after it has filled it with all configured monitored items. Use this setting to create the subscription with publishing already enabled. Default: `false`. --ska, --keepalivecount, --DefaultKeepAliveCount=VALUE Specifies the default number of publishing intervals before a keep alive is returned with the next queued publishing response. Default: `auto set based on publishing interval`. --slt, --lifetimecount, --DefaultLifetimeCount=VALUE Default subscription lifetime count which is a multiple of the keep alive counter and when reached instructs the server to declare the subscription invalid. Default: `auto set based on publishing interval`. --fd, --fetchdisplayname, --FetchOpcNodeDisplayName[=VALUE] Fetches the displayname for the monitored items subscribed if a display name was not specified in the configuration. Note: This has high impact on OPC Publisher startup performance. Default: `false` (disabled). --fp, --fetchpathfromroot, --FetchOpcBrowsePathFromRoot[=VALUE] (Experimental) Explicitly disable or enable retrieving relative paths from root for monitored items. Default: `false` (disabled). --qs, --queuesize, --DefaultQueueSize=VALUE Default queue size for all monitored items if queue size was not specified in the configuration. Default: `1` (for backwards compatibility). --aq, --autosetqueuesize, --AutoSetQueueSizes[=VALUE] (Experimental) Automatically calculate queue sizes for monitored items using the subscription publishing interval and the item's sampling rate as max(configured queue size, roundup( publishinginterval / samplinginterval)). Note that the server might revise the queue size down if it cannot handle the calculated size. Default: `false` (disabled). --ndo, --nodiscardold, --DiscardNew[=VALUE] The publisher is using this as default value for the discard old setting of monitored item queue configuration. Setting to true will ensure that new values are dropped before older ones are drained. Default: `false` (which is the OPC UA default). --mc, --monitoreditemdatachangetrigger, --DefaultDataChangeTrigger=VALUE Default data change trigger for all monitored items configured in the published nodes configuration unless explicitly overridden. Allowed values: `Status` `StatusValue` `StatusValueTimestamp` Default: `StatusValue` (which is the OPC UA default). --mwt, --monitoreditemwatchdog, --DefaultMonitoredItemWatchdogSeconds=VALUE The subscription and monitored item watchdog timeout in seconds the subscription uses to check on late reporting monitored items unless overridden in the published nodes configuration explicitly. Default: `not set` (watchdog disabled). --mwc, --monitoreditemwatchdogcondition, --DefaultMonitoredItemWatchdogCondition=VALUE The default condition when to run the action configured as the watchdog behavior. The condition can be overridden in the published nodes configuration. Allowed values: `WhenAllAreLate` `WhenAnyIsLate` Default: `WhenAllAreLate` (if enabled). --dwb, --watchdogbehavior, --DefaultWatchdogBehavior=VALUE Default behavior of the subscription and monitored item watchdog mechanism unless overridden in the published nodes configuration explicitly. Allowed values: `Diagnostic` `Reset` `FailFast` `ExitProcess` Default: `Diagnostic` (if enabled). --sf, --skipfirst, --DefaultSkipFirst[=VALUE] The publisher is using this as default value for the skip first setting of nodes configured without a skip first setting. A value of True will skip sending the first notification received when the monitored item is added to the subscription. Default: `False` (disabled). --rat, --republishaftertransfer, --RepublishAfterTransfer[=VALUE] Configure whether publisher republishes missed subscription notifications still in the server queue after transferring a subscription during reconnect handling. This can result in out of order notifications after a reconnect but minimizes data loss. Default: `False` (disabled). --hbb, --heartbeatbehavior, --DefaultHeartbeatBehavior=VALUE Default behavior of the heartbeat mechanism unless overridden in the published nodes configuration explicitly. Allowed values: `WatchdogLKV` `WatchdogLKG` `PeriodicLKV` `PeriodicLKG` `WatchdogLKVWithUpdatedTimestamps` `WatchdogLKVDiagnosticsOnly` `PeriodicLKVDropValue` `PeriodicLKGDropValue` Default: `WatchdogLKV` (Sending LKV in a watchdog fashion). --hb, --heartbeatinterval, --DefaultHeartbeatInterval=VALUE The publisher is using this as default value in seconds for the heartbeat interval setting of nodes that were configured without a heartbeat interval setting. A heartbeat is sent at this interval if no value has been received. Default: `0` (disabled) Also can be set using `DefaultHeartbeatInterval` environment variable in the form of a duration string in the form `[d.]hh:mm:ss[.fffffff]`. --ucr, --usecyclicreads, --DefaultSamplingUsingCyclicRead[=VALUE] All nodes should be sampled using periodical client reads instead of subscriptions services, unless otherwise configured. Default: `false`. --xmi, --maxmonitoreditems, --MaxMonitoredItemPerSubscription=VALUE Max monitored items per subscription until the subscription is split. This is used if the server does not provide limits in its server capabilities. Default: `not set`. --da, --deferredacks, --UseDeferredAcknoledgements[=VALUE] (Experimental) Acknoledge subscription notifications only when the data has been successfully published. Default: `false`. --rbp, --rebrowseperiod, --DefaultRebrowsePeriod=VALUE (Experimental) The default time to wait until the address space model is browsed again when generating model change notifications. Default: `12:00:00`. --sqp, --sequentialpublishing, --EnableSequentialPublishing[=VALUE] Set to false to disable sequential publishing in the protocol stack. Default: `True` (enabled). --smi, --subscriptionmanagementinterval, --SubscriptionManagementIntervalSeconds=VALUE The interval in seconds after which the publisher re-applies the desired state of the subscription to a session. Default: `0` (only on configuration change). --bnr, --badnoderetrydelay, --BadMonitoredItemRetryDelaySeconds=VALUE The delay in seconds after which nodes that were rejected by the server while added or updating a subscription or while publishing, are re-applied to a subscription. Set to 0 to disable retrying. Default: `1800` seconds. --inr, --invalidnoderetrydelay, --InvalidMonitoredItemRetryDelaySeconds=VALUE The delay in seconds after which the publisher attempts to re-apply nodes that were incorrectly configured to a subscription. Set to 0 to disable retrying. Default: `300` seconds. --bmd, --badnoderetrymaxdelay, --BadMonitoredItemRetryDelayMaxSeconds=VALUE The max delay in seconds between retrying nodes that were rejected by the server while added or updating a subscription or while publishing. When set an exponential retry policy is used with the `--bmr` value as the starting delay. Default: `not set`. --imd, --invalidnoderetrymaxdelay, --InvalidMonitoredItemRetryDelayMaxSeconds=VALUE The max delay in seconds between retrying nodes that were incorrectly configured in the a subscription. When set an exponential retry policy is used with the `--inr` value as the starting delay. Default: `not set`. --ser, --subscriptionerrorretrydelay, --SubscriptionErrorRetryDelaySeconds=VALUE The delay in seconds between attempts to create a subscription in a session. Set to 0 to disable retrying. Default: `2` seconds. --urc, --usereverseconnect, --DefaultUseReverseConnect[=VALUE] (Experimental) Use reverse connect for all endpoints in the published nodes configuration unless otherwise configured. Default: `false`. --dtr, --disabletransferonreconnect, --DisableSubscriptionTransfer[=VALUE] Do not attempt to transfer subscriptions when reconnecting but re-establish the subscription. Default: `false`. --dct, --disablecomplextypesystem, --DisableComplexTypeSystem[=VALUE] Never load the complex type system for any connections that are required for subscriptions. This setting not just disables meta data messages but also prevents transcoding of unknown complex types in outgoing messages. Default: `false`. --dsg, --disablesessionpergroup, --DisableSessionPerWriterGroup[=VALUE] Disable creating a separate session per writer group. Instead sessions are re-used across writer groups. Default: `False`. --ipi, --ignorepublishingintervals, --IgnoreConfiguredPublishingIntervals[=VALUE] Always use the publishing interval provided via command line argument `--op` and ignore all publishing interval settings in the configuration. Combine with `--op=0` to let the server use the lowest publishing interval it can support. Default: `False` (disabled). OPC UA Client configuration --------------------------- --aa, --acceptuntrusted, --AutoAcceptUntrustedCertificates[=VALUE] The publisher accepts untrusted certificates presented by a server it connects to. This does not include servers presenting bad certificates or certificates that fail chain validation. These errors cannot be suppressed and connection will always be rejected. WARNING: This setting should never be used in production environments! --rur, --rejectunknownrevocationstatus, --RejectUnknownRevocationStatus[=VALUE] Set this to `False` to accept certificates presented by a server that have an unknown revocation status. WARNING: This setting should never be used in production environments! Default: `True`. --ct, --createsessiontimeout, --CreateSessionTimeout=VALUE Amount of time in seconds to wait until a session is connected. Default: `5` seconds. --mr, --reconnectperiod, --MinReconnectDelay=VALUE The minimum amount of time in milliseconds to wait reconnection of session is attempted again. Default: `1000` milliseconds. --xr, --maxreconnectperiod, --MaxReconnectDelay=VALUE The maximum amount of time in millseconds to wait between reconnection attempts of the session. Default: `60000` milliseconds. --sto, --sessiontimeout, --DefaultSessionTimeout=VALUE Maximum amount of time in seconds that a session should remain open by the OPC server without any activity (session timeout). Requested from the OPC server at session creation. Default: `60` seconds. --ki, --keepaliveinterval, --KeepAliveInterval=VALUE The interval in seconds the publisher is sending keep alive messages to the OPC servers on the endpoints it is connected to. Default: `10` seconds. --sct, --servicecalltimeout, --DefaultServiceCallTimeout=VALUE Maximum amount of time in seconds that a service call should take before it is being cancelled. This value can be overridden in the request header. Default: `180` seconds. --cto, --connecttimeout, --DefaultConnectTimeout=VALUE Maximum amount of time in seconds that a service call should wait for a connected session to be used. This value can be overridden in the request header. Default: `not set` (in this case the default service call timeout value is used). --ot, --operationtimeout, --OperationTimeout=VALUE The operation service call timeout of individual service requests to the server in milliseconds. As opposed to the `--sco` timeout, this is the timeout hint provided to the server in every request. This value can be overridden in the request header. Default: `120000` milliseconds. --cl, --clientlinger, --LingerTimeoutSeconds=VALUE Amount of time in seconds to delay closing a client and underlying session after the a last service call. Use this setting to speed up multiple subsequent calls. Default: `0` sec (no linger). --rcp, --reverseconnectport, --ReverseConnectPort=VALUE The port to use when accepting inbound reverse connect requests from servers. Default: `4840`. --mnr, --maxnodesperread, --MaxNodesPerReadOverride=VALUE Limit max number of nodes to read in a single read request when batching reads or the server limit if less. Default: `0` (using server limit). --mnb, --maxnodesperbrowse, --MaxNodesPerBrowseOverride=VALUE Limit max number of nodes per browse request when batching browse operations or the server limit if less. Default: `0` (using server limit). --ncc, --nodecachecapacity, --NodeCacheCapacity=VALUE The max size of the node caches used in the complex type system. There are caches (values, nodes, references). Default: `4096`. --nct, --nodecachetimeout, --NodeCacheTimeout=VALUE The timeout of a node cache entries if not used in milliseconds. Default: `3600`. --mpr, --minpublishrequests, --MinPublishRequests=VALUE Minimum number of publish requests to queue once subscriptions are created in the session. Default: `2`. --ppr, --percentpublishrequests, --PublishRequestsPerSubscriptionPercent=VALUE Percentage ratio of publish requests per subscriptions in the session in percent up to the number configured using `--xpr`. Default: `100`% (1 request per subscription). --xpr, --maxpublishrequests, --MaxPublishRequests=VALUE Maximum number of publish requests to every queue once subscriptions are created in the session. Default: `10`. --dcp, --disablecomplextypepreloading, --DisableComplexTypePreloading[=VALUE] Complex types (structures, enumerations) a server exposes are preloaded from the server after the session is connected. In some cases this can cause problems either on the client or server itself. Use this setting to disable pre-loading support. Note that since the complex type system is used for meta data messages it will still be loaded at the time the subscription is created, therefore also disable meta data support if you want to ensure the complex types are never loaded for an endpoint. Default: `false`. --otl, --opctokenlifetime, --SecurityTokenLifetime=VALUE OPC UA Stack Transport Secure Channel - Security token lifetime in milliseconds. Default: `3600000` (1h). --ocl, --opcchannellifetime, --ChannelLifetime=VALUE OPC UA Stack Transport Secure Channel - Channel lifetime in milliseconds. Default: `300000` (5 min). --omb, --opcmaxbufferlen, --MaxBufferSize=VALUE OPC UA Stack Transport Secure Channel - Max buffer size. Default: `65535` (64KB -1). --oml, --opcmaxmessagelen, --MaxMessageSize=VALUE OPC UA Stack Transport Secure Channel - Max message size. Default: `4194304` (4 MB). --oal, --opcmaxarraylen, --MaxArrayLength=VALUE OPC UA Stack Transport Secure Channel - Max array length. Default: `65535` (64KB - 1). --ol, --opcmaxstringlen, --MaxStringLength=VALUE The max length of a string opc can transmit/ receive over the OPC UA secure channel. Default: `130816` (128KB - 256). --obl, --opcmaxbytestringlen, --MaxByteStringLength=VALUE OPC UA Stack Transport Secure Channel - Max byte string length. Default: `1048576` (1MB). --au, --appuri, --ApplicationUri=VALUE Application URI as per OPC UA definition inside the OPC UA client application configuration presented to the server. Default: `not set`. --pu, --producturi, --ProductUri=VALUE The Product URI as per OPC UA definition insde the OPC UA client application configuration presented to the server. Default: `not set`. --rejectsha1, --RejectSha1SignedCertificates=VALUE If set to `False` OPC Publisher will accept SHA1 certificates which have been officially deprecated and are unsafe to use. Note: Set this to `False` to support older equipment that uses Sha1 signed certificates rather than using no security. Default: `True`. --mks, --minkeysize, --MinimumCertificateKeySize=VALUE Minimum accepted certificate size. Note: It is recommended to this value to the highest certificate key size possible based on the connected OPC UA servers. Default: 1024. --tm, --trustmyself, --AddAppCertToTrustedStore=VALUE Set to `False` to disable adding the publisher's own certificate to the trusted store automatically. Default: `True`. --sn, --appcertsubjectname, --ApplicationCertificateSubjectName=VALUE The subject name for the app cert. Default: `CN=, C=DE, S=Bav, O=Microsoft, DC=localhost`. --an, --appname, --ApplicationName=VALUE The name for the app (used during OPC UA authentication). Default: `Microsoft.Azure.IIoT` --pki, --pkirootpath, --PkiRootPath=VALUE PKI certificate store root path. Default: `pki`. --ap, --appcertstorepath, --ApplicationCertificateStorePath=VALUE The path where the own application cert should be stored. Default: $"{PkiRootPath}/own". --apt, --at, --appcertstoretype, --ApplicationCertificateStoreType=VALUE The own application cert store type. Allowed values: `Directory` `X509Store` `FlatDirectory` Default: `Directory`. --cfa, --configurefromappcert, --TryConfigureFromExistingAppCert[=VALUE] Automatically set the application subject name, host name and application uri from the first valid application certificate found in the application certificate store path. If the chosen certificate is valid, it will be used, otherwise a new, self-signed certificate with the information will be created. Default: `false`. --apw, --appcertstorepwd, --ApplicationCertificatePassword=VALUE Password to use when storing the application certificate in the store folder if the store is of type `Directory`. Default: empty, which means application certificate is not protected by default. --tp, --trustedcertstorepath, --TrustedPeerCertificatesPath=VALUE The path of the trusted cert store. Default: $"{PkiRootPath}/trusted". --tpt, --TrustedPeerCertificatesType=VALUE Trusted peer certificate store type. Allowed values: `Directory` `X509Store` `FlatDirectory` Default: `Directory`. --rp, --rejectedcertstorepath, --RejectedCertificateStorePath=VALUE The path of the rejected cert store. Default: $"{PkiRootPath}/rejected". --rpt, --RejectedCertificateStoreType=VALUE Rejected certificate store type. Allowed values: `Directory` `X509Store` `FlatDirectory` Default: `Directory`. --ip, --issuercertstorepath, --TrustedIssuerCertificatesPath=VALUE The path of the trusted issuer cert store. Default: $"{PkiRootPath}/issuer". --ipt, --TrustedIssuerCertificatesType=VALUE Trusted issuer certificate store type. Allowed values: `Directory` `X509Store` `FlatDirectory` Default: `Directory`. --up, --usercertstorepath, --TrustedUserCertificatesPath=VALUE The path of the certificate store for user certificates. Default: $"{PkiRootPath}/users". --upt, --TrustedUserCertificatesType=VALUE Type of certificate store for all User certificates. Allowed values: `Directory` `X509Store` `FlatDirectory` Default: `Directory`. --uip, --userissuercertstorepath, --UserIssuerCertificatesPath=VALUE The path of the user issuer cert store. Default: $"{PkiRootPath}/users/issuer". --uit, --UserIssuerCertificatesType=VALUE Type of the issuer certificate store for User certificates. Allowed values: `Directory` `X509Store` `FlatDirectory` Default: `Directory`. Diagnostic options ------------------ --ll, --loglevel, --LogLevel=VALUE The loglevel to use. Allowed values: `Trace` `Debug` `Information` `Warning` `Error` `Critical` `None` Default: `Information`. --lfm, --logformat, --LogFormat=VALUE The log format to use when writing to the console. Allowed values: `simple` `syslog` `systemd` Default: `simple`. --di, --diagnosticsinterval, --DiagnosticsInterval=VALUE Produce publisher diagnostic information at this specified interval in seconds. By default diagnostics are written to the OPC Publisher logger (which requires at least -- loglevel `information`) unless configured differently using `--pd`. `0` disables diagnostic output. Default:60000 (60 seconds). Also can be set using `DiagnosticsInterval` environment variable in the form of a duration string in the form `[d.]hh:mm:ss[.fffffff]`". --pd, --diagnosticstarget, --DiagnosticsTarget=VALUE Configures how to emit diagnostics information at the `--di` configured interval. Use this to for example emit diagnostics as events to the event topic template instead of the console. Allowed values: `Logger` `Events` Default: `Logger`. --dr, --disableresourcemonitoring, --DisableResourceMonitoring[=VALUE] Disable resource monitoring as part of the diagnostics output and metrics. Default: `false` (enabled). --ln, --lognotifications[=VALUE] Log ingress subscription notifications at Informational level to aid debugging. Default: `disabled`. --lnh, --lognotificationsandheartbeats[=VALUE] Include heartbeats in notifications log. If set also implicitly enables debug logging via `--ln`. Default: `disabled`. --lnf, --lognotificationfilter[=VALUE] Only log notifications where the data set field name, subscription name, or data set name match the provided regular expression pattern. If set implicitly enables debug logging via `-- ln`. Default: `null` (matches all). --len, --logencodednotifications[=VALUE] Log encoded subscription and monitored item notifications at Informational level to aid debugging. Default: `disabled`. --sl, --opcstacklogging, --EnableOpcUaStackLogging[=VALUE] Enable opc ua stack logging beyond logging at error level. Default: `disabled`. --ksf, --keysetlogfolder, --OpcUaKeySetLogFolderName[=VALUE] Writes negotiated symmetric keys for all running client connection to this file. The file can be loaded by Wireshark 4.3 and used to decrypt encrypted channels when analyzing network traffic captures. Note that enabling this feature presents a security risk! Default: `disabled`. --ecw, --enableconsolewriter, --EnableConsoleWriter[=VALUE] Enable writing encoded messages to standard error log through the filesystem transport (must enable via `-t FileSystem` and `-o` must be set to either `stderr` or `stdout`). Default: `false`. --oc, --otlpcollector, --OtlpCollectorEndpoint=VALUE Specifiy the OpenTelemetry collector grpc endpoint url to export diagnostics to. Default: `disabled`. --eol, --enableotellogging, --EnableOtelLogging[=VALUE] Enable logging over open telemetry endpoint. By default only metrics are enabled. Default: `disabled`. --eot, --enableoteltraces, --EnableOtelTraces[=VALUE] Enable traces over open telemetry endpoint. By default only metrics are emitted. Default: `disabled`. --oxi, --otlpexportinterval, --OtlpExportIntervalMilliseconds=VALUE The interval in milliseconds when OpenTelemetry is exported to the collector endpoint. Default: `15000` (15 seconds). --mms, --maxmetricstreams, --OtlpMaxMetricStreams=VALUE Specifiy the max number of streams to collect in the default view. Default: `4000`. --em, --enableprometheusendpoint, --EnableMetrics[=VALUE] Explicitly enable or disable exporting prometheus metrics directly on the standard path. Default: `disabled` if Otlp collector is configured, otherwise `enabled`. --ari, --addruntimeinstrumentation, --OtlpRuntimeInstrumentation[=VALUE] Include metrics captured for the underlying runtime and web server. Default: `False`. --ats, --addtotalsuffix, --OtlpTotalNameSuffixForCounters[=VALUE] Add total suffix to all counter instrument names when exporting metrics via prometheus exporter. Default: `False`. ``` Currently supported combinations of `--mm` snd `--me` can be found [here](./messageformats.md). ================================================ FILE: docs/opc-publisher/definitions.md ================================================ ## Definitions ### AdditionalData Flags that are set by the historian when returning archived values. *Type* : enum (None, Partial, ExtraData, MultipleValues) ### AggregateConfigurationModel Aggregate configuration |Name|Description|Schema| |---|---|---| |**percentDataBad**
*optional*|Percent of data that is bad|integer (int32)| |**percentDataGood**
*optional*|Percent of data that is good|integer (int32)| |**treatUncertainAsBad**
*optional*|Whether to treat uncertain as bad|boolean| |**useSlopedExtrapolation**
*optional*|Whether to use sloped extrapolation.|boolean| ### ApplicationInfoModel Application info model |Name|Description|Schema| |---|---|---| |**applicationId**
*required*|Unique application id|string| |**applicationName**
*optional*|Default name of application|string| |**applicationType**
*optional*||[ApplicationType](definitions.md#applicationtype)| |**applicationUri**
*required*|Unique application uri|string| |**capabilities**
*optional*|The capabilities advertised by the server.|< string > array| |**created**
*optional*||[OperationContextModel](definitions.md#operationcontextmodel)| |**discovererId**
*optional*|Discoverer that registered the application|string| |**discoveryProfileUri**
*optional*|Discovery profile uri|string| |**discoveryUrls**
*optional*|Discovery urls of the server|< string > array| |**gatewayServerUri**
*optional*|Gateway server uri|string| |**hostAddresses**
*optional*|Host addresses of server application or null|< string > array| |**locale**
*optional*|Locale of default name - defaults to "en"|string| |**localizedNames**
*optional*|Localized Names of application keyed on locale|< string, string > map| |**notSeenSince**
*optional*|Last time application was seen if not visible|string (date-time)| |**productUri**
*optional*|Product uri|string| |**siteId**
*optional*|Site of the application
**Example** : `"productionlineA"`|string| |**updated**
*optional*||[OperationContextModel](definitions.md#operationcontextmodel)| ### ApplicationRegistrationModel Application with optional list of endpoints |Name|Description|Schema| |---|---|---| |**application**
*required*||[ApplicationInfoModel](definitions.md#applicationinfomodel)| |**endpoints**
*optional*|List of endpoints for it|< [EndpointRegistrationModel](definitions.md#endpointregistrationmodel) > array| ### ApplicationType Application type *Type* : enum (Server, Client, ClientAndServer, DiscoveryServer) ### AttributeReadRequestModel Attribute to read |Name|Description|Schema| |---|---|---| |**attribute**
*required*||[NodeAttribute](definitions.md#nodeattribute)| |**nodeId**
*required*|Node to read from or write to (mandatory)
**Minimum length** : `1`|string| ### AttributeReadResponseModel Attribute value read |Name|Description|Schema| |---|---|---| |**errorInfo**
*optional*||[ServiceResultModel](definitions.md#serviceresultmodel)| |**value**
*required*|Attribute value|object| ### AttributeWriteRequestModel Attribute and value to write to it |Name|Description|Schema| |---|---|---| |**attribute**
*required*||[NodeAttribute](definitions.md#nodeattribute)| |**nodeId**
*required*|Node to write to (mandatory)
**Minimum length** : `1`|string| |**value**
*required*|Value to write (mandatory)|object| ### AttributeWriteResponseModel Attribute write result |Name|Schema| |---|---| |**errorInfo**
*optional*|[ServiceResultModel](definitions.md#serviceresultmodel)| ### AuthenticationMethodModel Authentication Method model |Name|Description|Schema| |---|---|---| |**configuration**
*optional*|Method specific configuration|object| |**credentialType**
*optional*||[CredentialType](definitions.md#credentialtype)| |**id**
*required*|Method id
**Minimum length** : `1`|string| |**securityPolicy**
*optional*|Security policy to use when passing credential.|string| ### BrowseDirection Direction to browse *Type* : enum (Forward, Backward, Both) ### BrowseFirstRequestModel Browse request model |Name|Description|Schema| |---|---|---| |**direction**
*optional*||[BrowseDirection](definitions.md#browsedirection)| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**maxReferencesToReturn**
*optional*|Max number of references to return. There might
be less returned as this is up to the client
restrictions. Set to 0 to return no references
or target nodes.
(default is decided by client e.g. 60)|integer (int64)| |**noSubtypes**
*optional*|Whether to include subtypes of the reference type.
(default is false)|boolean| |**nodeClassFilter**
*optional*|Filter returned target nodes by only returning
nodes that have classes defined in this array.
(default: null - all targets are returned)|enum (Object, Variable, Method, ObjectType, VariableType, ReferenceType, DataType, View)| |**nodeId**
*optional*|Node to browse.
(defaults to root folder).|string| |**nodeIdsOnly**
*optional*|Whether to only return the raw node id
information and not read the target node.
(default is false)|boolean| |**readVariableValues**
*optional*|Whether to read variable values on target nodes.
(default is false)|boolean| |**referenceTypeId**
*optional*|Reference types to browse.
(default: hierarchical).|string| |**targetNodesOnly**
*optional*|Whether to collapse all references into a set of
unique target nodes and not show reference
information.
(default is false)|boolean| |**view**
*optional*||[BrowseViewModel](definitions.md#browseviewmodel)| ### BrowseFirstRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[BrowseFirstRequestModel](definitions.md#browsefirstrequestmodel)| ### BrowseFirstResponseModel Browse response model |Name|Description|Schema| |---|---|---| |**continuationToken**
*optional*|Continuation token if more results pending.|string| |**errorInfo**
*optional*||[ServiceResultModel](definitions.md#serviceresultmodel)| |**node**
*required*||[NodeModel](definitions.md#nodemodel)| |**references**
*required*|References returned|< [NodeReferenceModel](definitions.md#nodereferencemodel) > array| ### BrowseNextRequestModel Request node browsing continuation |Name|Description|Schema| |---|---|---| |**abort**
*optional*|Whether to abort browse and release.
(default: false)|boolean| |**continuationToken**
*required*|Continuation token from previews browse request.
(mandatory)
**Minimum length** : `1`|string| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**nodeIdsOnly**
*optional*|Whether to only return the raw node id
information and not read the target node.
(default is false)|boolean| |**readVariableValues**
*optional*|Whether to read variable values on target nodes.
(default is false)|boolean| |**targetNodesOnly**
*optional*|Whether to collapse all references into a set of
unique target nodes and not show reference
information.
(default is false)|boolean| ### BrowseNextRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[BrowseNextRequestModel](definitions.md#browsenextrequestmodel)| ### BrowseNextResponseModel Result of node browse continuation |Name|Description|Schema| |---|---|---| |**continuationToken**
*optional*|Continuation token if more results pending.|string| |**errorInfo**
*optional*||[ServiceResultModel](definitions.md#serviceresultmodel)| |**references**
*required*|References returned|< [NodeReferenceModel](definitions.md#nodereferencemodel) > array| ### BrowsePathRequestModel Browse nodes by path |Name|Description|Schema| |---|---|---| |**browsePaths**
*required*|The paths to browse from node.
(mandatory)|< < string > array > array| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**nodeId**
*optional*|Node to browse from (defaults to root folder).|string| |**nodeIdsOnly**
*optional*|Whether to only return the raw node id
information and not read the target node.
(default is false)|boolean| |**readVariableValues**
*optional*|Whether to read variable values on target nodes.
(default is false)|boolean| ### BrowsePathRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[BrowsePathRequestModel](definitions.md#browsepathrequestmodel)| ### BrowsePathResponseModel Result of node browse continuation |Name|Description|Schema| |---|---|---| |**errorInfo**
*optional*||[ServiceResultModel](definitions.md#serviceresultmodel)| |**targets**
*optional*|Targets|< [NodePathTargetModel](definitions.md#nodepathtargetmodel) > array| ### BrowseStreamChunkModelIAsyncEnumerable *Type* : object ### BrowseStreamRequestModel Browse stream request model |Name|Description|Schema| |---|---|---| |**direction**
*optional*||[BrowseDirection](definitions.md#browsedirection)| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**noRecurse**
*optional*|Whether to not browse recursively
(default is false)|boolean| |**noSubtypes**
*optional*|Whether to include subtypes of the reference type.
(default is false)|boolean| |**nodeClassFilter**
*optional*|Filter returned target nodes by only returning
nodes that have classes defined in this array.
(default: null - all targets are returned)|enum (Object, Variable, Method, ObjectType, VariableType, ReferenceType, DataType, View)| |**nodeId**
*optional*|Start nodes to browse.
(defaults to root folder).|< string > array| |**readVariableValues**
*optional*|Whether to read variable values on source nodes.
(default is false)|boolean| |**referenceTypeId**
*optional*|Reference types to browse.
(default: hierarchical).|string| |**view**
*optional*||[BrowseViewModel](definitions.md#browseviewmodel)| ### BrowseStreamRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[BrowseStreamRequestModel](definitions.md#browsestreamrequestmodel)| ### BrowseViewModel View to browse |Name|Description|Schema| |---|---|---| |**timestamp**
*optional*|Browses at or before this timestamp.|string (date-time)| |**version**
*optional*|Browses specific version of the view.|integer (int64)| |**viewId**
*required*|Node of the view to browse
**Minimum length** : `1`|string| ### ByteArrayPublishedNodeCreateAssetRequestModel Request to create an asset in the configuration api |Name|Description|Schema| |---|---|---| |**configuration**
*required*|The asset configuration to use when creating the asset.|string (byte)| |**entry**
*required*||[PublishedNodesEntryModel](definitions.md#publishednodesentrymodel)| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**waitTime**
*optional*|Time to wait after the configuration is applied to perform
the configuration of the asset in the configuration api.
This is to let the server settle.|string (date-span)| ### ChannelDiagnosticModel Channel diagnostics model |Name|Description|Schema| |---|---|---| |**channelId**
*optional*|The id assigned to the channel that the token
belongs to.|integer (int64)| |**client**
*optional*||[ChannelKeyModel](definitions.md#channelkeymodel)| |**connection**
*required*||[ConnectionModel](definitions.md#connectionmodel)| |**createdAt**
*optional*|When the token was created by the server
(refers to the server's clock).|string (date-time)| |**lifetime**
*optional*|The lifetime of the token|string (date-span)| |**localIpAddress**
*optional*|Effective local ip address used for the connection
if connected. Empty if disconnected.|string| |**localPort**
*optional*|The effective local port used when connected,
null if disconnected.|integer (int32)| |**remoteIpAddress**
*optional*|Effective remote ip address used for the
connection if connected. Empty if disconnected.|string| |**remotePort**
*optional*|The effective remote port used when connected,
null if disconnected.|integer (int32)| |**server**
*optional*||[ChannelKeyModel](definitions.md#channelkeymodel)| |**sessionCreated**
*optional*|When the session was created.|string (date-time)| |**sessionId**
*optional*|The session id if connected. Empty if disconnected.|string| |**timeStamp**
*required*|Timestamp of the diagnostic information|string (date-time)| |**tokenId**
*optional*|The id assigned to the token.|integer (int64)| ### ChannelDiagnosticModelIAsyncEnumerable *Type* : object ### ChannelKeyModel Channel token key model. |Name|Description|Schema| |---|---|---| |**iv**
*required*|Iv|< integer (int32) > array| |**key**
*required*|Key|< integer (int32) > array| |**sigLen**
*required*|Signature length|integer (int32)| ### ConditionHandlingOptionsModel Condition handling options model |Name|Description|Schema| |---|---|---| |**snapshotInterval**
*optional*|Time interval for sending pending interval snapshot in seconds.|integer (int32)| |**updateInterval**
*optional*|Time interval for sending pending interval updates in seconds.|integer (int32)| ### ConnectionDiagnosticsModelIAsyncEnumerable *Type* : object ### ConnectionModel Connection model |Name|Description|Schema| |---|---|---| |**diagnostics**
*optional*||[DiagnosticsModel](definitions.md#diagnosticsmodel)| |**endpoint**
*required*||[EndpointModel](definitions.md#endpointmodel)| |**group**
*optional*|Connection group allows splitting connections
per purpose.|string| |**locales**
*optional*|Optional list of preferred locales in preference order.|< string > array| |**options**
*optional*||[ConnectionOptions](definitions.md#connectionoptions)| |**user**
*optional*||[CredentialModel](definitions.md#credentialmodel)| ### ConnectionOptions Options that can be applied to a connection *Type* : enum (None, UseReverseConnect, NoComplexTypeSystem, NoSubscriptionTransfer, DumpDiagnostics) ### ContentFilterElementModel An expression element in the filter ast |Name|Description|Schema| |---|---|---| |**filterOperands**
*optional*|The operands in the element for the operator|< [FilterOperandModel](definitions.md#filteroperandmodel) > array| |**filterOperator**
*optional*||[FilterOperatorType](definitions.md#filteroperatortype)| ### ContentFilterModel Content filter |Name|Description|Schema| |---|---|---| |**elements**
*optional*|The flat list of elements in the filter AST|< [ContentFilterElementModel](definitions.md#contentfilterelementmodel) > array| ### CredentialModel Credential model. For backwards compatibility the actual credentials to pass to the server is set through the value property. |Name|Schema| |---|---| |**type**
*optional*|[CredentialType](definitions.md#credentialtype)| |**value**
*optional*|[UserIdentityModel](definitions.md#useridentitymodel)| ### CredentialType Type of credentials to use for authentication *Type* : enum (None, UserName, X509Certificate, JwtToken) ### DataChangeTriggerType Data change trigger *Type* : enum (Status, StatusValue, StatusValueTimestamp) ### DataLocation Indicate the data location *Type* : enum (Raw, Calculated, Interpolated) ### DataSetRoutingMode Specifies how OPC UA node paths are mapped to message routing paths/topics. Controls automatic topic structure generation from OPC UA address space. Used to create a unified namespace when publishing to message brokers that support hierarchical routing like MQTT. *Type* : enum (None, UseBrowseNames, UseBrowseNamesWithNamespaceIndex) ### DataTypeMetadataModel Data type metadata model |Name|Description|Schema| |---|---|---| |**dataType**
*optional*|The data type for the instance declaration.|string| ### DeadbandType Deadband type *Type* : enum (Absolute, Percent) ### DeleteEventsDetailsModel The events to delete |Name|Description|Schema| |---|---|---| |**eventIds**
*required*|Events to delete|< string (byte) > array| ### DeleteEventsDetailsModelHistoryUpdateRequestModel Request node history update |Name|Description|Schema| |---|---|---| |**browsePath**
*optional*|An optional path from NodeId instance to
the actual node.|< string > array| |**details**
*required*||[DeleteEventsDetailsModel](definitions.md#deleteeventsdetailsmodel)| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**nodeId**
*optional*|Node to update (mandatory without browse path)|string| ### DeleteEventsDetailsModelHistoryUpdateRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[DeleteEventsDetailsModelHistoryUpdateRequestModel](definitions.md#deleteeventsdetailsmodelhistoryupdaterequestmodel)| ### DeleteValuesAtTimesDetailsModel Deletes data at times |Name|Description|Schema| |---|---|---| |**reqTimes**
*required*|The timestamps to delete|< string (date-time) > array| ### DeleteValuesAtTimesDetailsModelHistoryUpdateRequestModel Request node history update |Name|Description|Schema| |---|---|---| |**browsePath**
*optional*|An optional path from NodeId instance to
the actual node.|< string > array| |**details**
*required*||[DeleteValuesAtTimesDetailsModel](definitions.md#deletevaluesattimesdetailsmodel)| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**nodeId**
*optional*|Node to update (mandatory without browse path)|string| ### DeleteValuesAtTimesDetailsModelHistoryUpdateRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[DeleteValuesAtTimesDetailsModelHistoryUpdateRequestModel](definitions.md#deletevaluesattimesdetailsmodelhistoryupdaterequestmodel)| ### DeleteValuesDetailsModel Delete values |Name|Description|Schema| |---|---|---| |**endTime**
*optional*|End time to delete until|string (date-time)| |**startTime**
*optional*|Start time|string (date-time)| ### DeleteValuesDetailsModelHistoryUpdateRequestModel Request node history update |Name|Description|Schema| |---|---|---| |**browsePath**
*optional*|An optional path from NodeId instance to
the actual node.|< string > array| |**details**
*required*||[DeleteValuesDetailsModel](definitions.md#deletevaluesdetailsmodel)| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**nodeId**
*optional*|Node to update (mandatory without browse path)|string| ### DeleteValuesDetailsModelHistoryUpdateRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[DeleteValuesDetailsModelHistoryUpdateRequestModel](definitions.md#deletevaluesdetailsmodelhistoryupdaterequestmodel)| ### DiagnosticsLevel Level of diagnostics requested in responses *Type* : enum (None, Status, Information, Debug, Verbose) ### DiagnosticsModel Diagnostics configuration |Name|Description|Schema| |---|---|---| |**auditId**
*optional*|Client audit log entry.
(default: client generated)|string| |**level**
*optional*||[DiagnosticsLevel](definitions.md#diagnosticslevel)| |**timeStamp**
*optional*|Timestamp of request.
(default: client generated)|string (date-time)| ### DiscoveryCancelRequestModel Discovery cancel request |Name|Description|Schema| |---|---|---| |**context**
*optional*||[OperationContextModel](definitions.md#operationcontextmodel)| |**id**
*optional*|Id of discovery request|string| ### DiscoveryConfigModel Discovery configuration api model |Name|Description|Schema| |---|---|---| |**addressRangesToScan**
*optional*|Address ranges to scan (null == all wired nics)|string| |**discoveryUrls**
*optional*|List of preset discovery urls to use|< string > array| |**idleTimeBetweenScans**
*optional*|Delay time between discovery sweeps|string (date-span)| |**locales**
*optional*|List of locales to filter with during discovery|< string > array| |**maxNetworkProbes**
*optional*|Max network probes that should ever run.|integer (int32)| |**maxPortProbes**
*optional*|Max port probes that should ever run.|integer (int32)| |**minPortProbesPercent**
*optional*|Probes that must always be there as percent of max.|integer (int32)| |**networkProbeTimeout**
*optional*|Network probe timeout|string (date-span)| |**portProbeTimeout**
*optional*|Port probe timeout|string (date-span)| |**portRangesToScan**
*optional*|Port ranges to scan (null == all unassigned)|string| ### DiscoveryMode Discovery mode to use *Type* : enum (Off, Local, Network, Fast, Scan) ### DiscoveryRequestModel Discovery request |Name|Description|Schema| |---|---|---| |**configuration**
*optional*||[DiscoveryConfigModel](definitions.md#discoveryconfigmodel)| |**context**
*optional*||[OperationContextModel](definitions.md#operationcontextmodel)| |**discovery**
*optional*||[DiscoveryMode](definitions.md#discoverymode)| |**id**
*optional*|Id of discovery request|string| ### EndpointModel Endpoint model |Name|Description|Schema| |---|---|---| |**alternativeUrls**
*optional*|Alternative endpoint urls that can be used for
accessing and validating the server|< string > array| |**certificate**
*optional*|Endpoint certificate thumbprint|string| |**securityMode**
*optional*||[SecurityMode](definitions.md#securitymode)| |**securityPolicy**
*optional*|Security policy uri to use for communication.
default to best.|string| |**url**
*required*|Endpoint url to use to connect with
**Minimum length** : `1`|string| ### EndpointRegistrationModel Endpoint registration |Name|Description|Schema| |---|---|---| |**authenticationMethods**
*optional*|Supported authentication methods that can be selected to
obtain a credential and used to interact with the endpoint.|< [AuthenticationMethodModel](definitions.md#authenticationmethodmodel) > array| |**discovererId**
*optional*|Entity that registered and can access the endpoint|string| |**endpoint**
*optional*||[EndpointModel](definitions.md#endpointmodel)| |**endpointUrl**
*optional*|Original endpoint url of the endpoint|string| |**id**
*required*|Endpoint identifier which is hashed from
the supervisor, site and url.
**Minimum length** : `1`|string| |**securityLevel**
*optional*|Security level of the endpoint|integer (int32)| |**siteId**
*optional*|Registered site of the endpoint|string| ### EventFilterModel Event filter |Name|Description|Schema| |---|---|---| |**selectClauses**
*optional*|Select clauses|< [SimpleAttributeOperandModel](definitions.md#simpleattributeoperandmodel) > array| |**typeDefinitionId**
*optional*|Simple event Type definition node id|string| |**whereClause**
*optional*||[ContentFilterModel](definitions.md#contentfiltermodel)| ### ExceptionDeviationType Exception deviation type *Type* : enum (AbsoluteValue, PercentOfValue, PercentOfRange, PercentOfEURange) ### FileInfoModel File info |Name|Description|Schema| |---|---|---| |**lastModified**
*optional*|The time the file was last modified.|string (date-time)| |**maxBufferSize**
*optional*|The maximum number of bytes of
the read and write buffers.|integer (int64)| |**mimeType**
*optional*|The media type of the file based on RFC 2046.|string| |**openCount**
*optional*|The number of currently valid file handles on
the file.|integer (int32)| |**size**
*optional*|The size of the file in Bytes. When a file is
currently opened for write, the size might not be
accurate or available.|integer (int64)| |**writable**
*optional*|Whether the file is writable.|boolean| ### FileInfoModelServiceResponse Response envelope |Name|Schema| |---|---| |**errorInfo**
*optional*|[ServiceResultModel](definitions.md#serviceresultmodel)| |**result**
*optional*|[FileInfoModel](definitions.md#fileinfomodel)| ### FileSystemObjectModel File system object model |Name|Description|Schema| |---|---|---| |**browsePath**
*optional*|The browse path to the filesystem object|< string > array| |**name**
*optional*|The name of the filesystem object|string| |**nodeId**
*optional*|The node id of the filesystem object|string| ### FileSystemObjectModelIEnumerableServiceResponse Response envelope |Name|Description|Schema| |---|---|---| |**errorInfo**
*optional*||[ServiceResultModel](definitions.md#serviceresultmodel)| |**result**
*optional*|Result|< [FileSystemObjectModel](definitions.md#filesystemobjectmodel) > array| ### FileSystemObjectModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[FileSystemObjectModel](definitions.md#filesystemobjectmodel)| ### FileSystemObjectModelServiceResponse Response envelope |Name|Schema| |---|---| |**errorInfo**
*optional*|[ServiceResultModel](definitions.md#serviceresultmodel)| |**result**
*optional*|[FileSystemObjectModel](definitions.md#filesystemobjectmodel)| ### FileSystemObjectModelServiceResponseIAsyncEnumerable *Type* : object ### FilterOperandModel Filter operand |Name|Description|Schema| |---|---|---| |**alias**
*optional*|Optional alias to refer to it makeing it a
full blown attribute operand|string| |**attributeId**
*optional*||[NodeAttribute](definitions.md#nodeattribute)| |**browsePath**
*optional*|Browse path of attribute operand|< string > array| |**dataType**
*optional*|Data type if operand is a literal|string| |**index**
*optional*|Element reference in the outer list if
operand is an element operand|integer (int64)| |**indexRange**
*optional*|Index range of attribute operand|string| |**nodeId**
*optional*|Type definition node id if operand is
simple or full attribute operand.|string| |**value**
*optional*|Variant value if operand is a literal|object| ### FilterOperatorType Filter operator type *Type* : enum (Equals, IsNull, GreaterThan, LessThan, GreaterThanOrEqual, LessThanOrEqual, Like, Not, Between, InList, And, Or, Cast, InView, OfType, RelatedTo, BitwiseAnd, BitwiseOr) ### GetConfiguredEndpointsResponseModel Result of GetConfiguredEndpoints method call |Name|Description|Schema| |---|---|---| |**endpoints**
*optional*|Collection of Endpoints in the configuration|< [PublishedNodesEntryModel](definitions.md#publishednodesentrymodel) > array| ### GetConfiguredNodesOnEndpointResponseModel Result of GetConfiguredNodesOnEndpoint method call |Name|Description|Schema| |---|---|---| |**opcNodes**
*optional*|Collection of Nodes configured for a particular endpoint|< [OpcNodeModel](definitions.md#opcnodemodel) > array| ### HeartbeatBehavior Controls how heartbeat messages are handled for monitored items. Heartbeats help maintain awareness of node state and connection health even when values don't change. Can be configured globally via the --hbb command line option. Works with heartbeat interval settings. *Type* : enum (WatchdogLKV, WatchdogLKG, PeriodicLKV, PeriodicLKG, WatchdogLKVWithUpdatedTimestamps, WatchdogLKVDiagnosticsOnly, Reserved, PeriodicLKVDropValue, PeriodicLKGDropValue) ### HistoricEventModel Historic event |Name|Description|Schema| |---|---|---| |**eventFields**
*required*|The selected fields of the event|object| ### HistoricEventModelArrayHistoryReadNextResponseModel History read continuation result |Name|Description|Schema| |---|---|---| |**continuationToken**
*optional*|Continuation token if more results pending.|string| |**errorInfo**
*optional*||[ServiceResultModel](definitions.md#serviceresultmodel)| |**history**
*required*|History as json encoded extension object|< [HistoricEventModel](definitions.md#historiceventmodel) > array| ### HistoricEventModelArrayHistoryReadResponseModel History read results |Name|Description|Schema| |---|---|---| |**continuationToken**
*optional*|Continuation token if more results pending.|string| |**errorInfo**
*optional*||[ServiceResultModel](definitions.md#serviceresultmodel)| |**history**
*required*|History as json encoded extension object|< [HistoricEventModel](definitions.md#historiceventmodel) > array| ### HistoricEventModelIAsyncEnumerable *Type* : object ### HistoricValueModel Historic data |Name|Description|Schema| |---|---|---| |**additionalData**
*optional*||[AdditionalData](definitions.md#additionaldata)| |**dataLocation**
*optional*||[DataLocation](definitions.md#datalocation)| |**dataType**
*optional*|Built in data type of the updated values|string| |**modificationInfo**
*optional*||[ModificationInfoModel](definitions.md#modificationinfomodel)| |**serverPicoseconds**
*optional*|Additional resolution for the server timestamp.|integer (int32)| |**serverTimestamp**
*optional*|The server timestamp associated with the value.|string (date-time)| |**sourcePicoseconds**
*optional*|Additional resolution for the source timestamp.|integer (int32)| |**sourceTimestamp**
*optional*|The source timestamp associated with the value.|string (date-time)| |**status**
*optional*||[ServiceResultModel](definitions.md#serviceresultmodel)| |**value**
*optional*|The value of data value.|object| ### HistoricValueModelArrayHistoryReadNextResponseModel History read continuation result |Name|Description|Schema| |---|---|---| |**continuationToken**
*optional*|Continuation token if more results pending.|string| |**errorInfo**
*optional*||[ServiceResultModel](definitions.md#serviceresultmodel)| |**history**
*required*|History as json encoded extension object|< [HistoricValueModel](definitions.md#historicvaluemodel) > array| ### HistoricValueModelArrayHistoryReadResponseModel History read results |Name|Description|Schema| |---|---|---| |**continuationToken**
*optional*|Continuation token if more results pending.|string| |**errorInfo**
*optional*||[ServiceResultModel](definitions.md#serviceresultmodel)| |**history**
*required*|History as json encoded extension object|< [HistoricValueModel](definitions.md#historicvaluemodel) > array| ### HistoricValueModelIAsyncEnumerable *Type* : object ### HistoryConfigurationModel History configuration |Name|Description|Schema| |---|---|---| |**aggregateConfiguration**
*optional*||[AggregateConfigurationModel](definitions.md#aggregateconfigurationmodel)| |**aggregateFunctions**
*optional*|Allowed aggregate functions|< string, string > map| |**definition**
*optional*|Human readable string that specifies how
the value of this HistoricalDataNode is
calculated|string| |**endOfArchive**
*optional*|The last date of the archive|string (date-time)| |**exceptionDeviation**
*optional*|Minimum amount that the data for the
Node shall change in order for the change
to be reported to the history database|number (double)| |**exceptionDeviationType**
*optional*||[ExceptionDeviationType](definitions.md#exceptiondeviationtype)| |**maxTimeInterval**
*optional*|Specifies the maximum interval between data
points in the history repository
regardless of their value change|string (date-span)| |**minTimeInterval**
*optional*|Specifies the minimum interval between
data points in the history repository
regardless of their value change|string (date-span)| |**serverTimestampSupported**
*optional*|Server supports ServerTimestamps in addition
to SourceTimestamp|boolean| |**startOfArchive**
*optional*|The date before which there is no data in the
archive either online or offline|string (date-time)| |**startOfOnlineArchive**
*optional*|Date of the earliest data in the online archive|string (date-time)| |**stepped**
*optional*|specifies whether the historical data was
collected in such a manner that it should
be displayed as SlopedInterpolation (sloped
line between points) or as SteppedInterpolation
(vertically-connected horizontal lines
between points) when raw data is examined.
This Property also effects how some
Aggregates are calculated|boolean| ### HistoryConfigurationRequestModel Request history configuration |Name|Description|Schema| |---|---|---| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**nodeId**
*required*|Continuation token to continue reading more
results.
**Minimum length** : `1`|string| ### HistoryConfigurationRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[HistoryConfigurationRequestModel](definitions.md#historyconfigurationrequestmodel)| ### HistoryConfigurationResponseModel Response with history configuration |Name|Schema| |---|---| |**configuration**
*optional*|[HistoryConfigurationModel](definitions.md#historyconfigurationmodel)| |**errorInfo**
*optional*|[ServiceResultModel](definitions.md#serviceresultmodel)| ### HistoryReadNextRequestModel Request node history read continuation |Name|Description|Schema| |---|---|---| |**abort**
*optional*|Abort reading after this read|boolean| |**continuationToken**
*required*|Continuation token to continue reading more
results.
**Minimum length** : `1`|string| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| ### HistoryReadNextRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[HistoryReadNextRequestModel](definitions.md#historyreadnextrequestmodel)| ### HistoryServerCapabilitiesModel History Server capabilities |Name|Description|Schema| |---|---|---| |**aggregateFunctions**
*optional*|Supported aggregate functions|< string, string > map| |**deleteAtTimeCapability**
*optional*|Server support deleting data at times|boolean| |**deleteEventCapability**
*optional*|Server supports deleting events|boolean| |**deleteRawCapability**
*optional*|Server supports deleting raw data|boolean| |**insertAnnotationCapability**
*optional*|Allows inserting annotations|boolean| |**insertDataCapability**
*optional*|Server supports inserting data|boolean| |**insertEventCapability**
*optional*|Server supports inserting events|boolean| |**maxReturnDataValues**
*optional*|Maximum number of historic data values that will
be returned in a single read.|integer (int64)| |**maxReturnEventValues**
*optional*|Maximum number of events that will be returned
in a single read.|integer (int64)| |**replaceDataCapability**
*optional*|Server supports replacing historic data|boolean| |**replaceEventCapability**
*optional*|Server supports replacing events|boolean| |**serverTimestampSupported**
*optional*|Server supports ServerTimestamps in addition
to SourceTimestamp|boolean| |**supportsHistoricData**
*optional*|Server supports historic data access|boolean| |**supportsHistoricEvents**
*optional*|Server supports historic event access|boolean| |**updateDataCapability**
*optional*|Server supports updating historic data|boolean| |**updateEventCapability**
*optional*|Server supports updating events|boolean| ### HistoryUpdateOperation History update type *Type* : enum (Insert, Replace, Update, Delete) ### HistoryUpdateResponseModel History update results |Name|Description|Schema| |---|---|---| |**errorInfo**
*optional*||[ServiceResultModel](definitions.md#serviceresultmodel)| |**results**
*optional*|List of results from the update operation|< [ServiceResultModel](definitions.md#serviceresultmodel) > array| ### InstanceDeclarationModel Instance declaration meta data |Name|Description|Schema| |---|---|---| |**browseName**
*optional*|The browse name for the instance declaration.|string| |**browsePath**
*optional*|The browse path|< string > array| |**description**
*optional*|The description for the instance declaration.|string| |**displayName**
*optional*|The display name for the instance declaration.|string| |**displayPath**
*optional*|A localized path to the instance declaration.|string| |**method**
*optional*||[MethodMetadataModel](definitions.md#methodmetadatamodel)| |**modellingRule**
*optional*|The modelling rule for the instance
declaration (i.e. Mandatory or Optional).|string| |**modellingRuleId**
*optional*|The modelling rule node id.|string| |**nodeClass**
*optional*||[NodeClass](definitions.md#nodeclass)| |**nodeId**
*optional*|The node id for the instance.|string| |**overriddenDeclaration**
*optional*||[InstanceDeclarationModel](definitions.md#instancedeclarationmodel)| |**rootTypeId**
*optional*|The type that the declaration belongs to.|string| |**variable**
*optional*||[VariableMetadataModel](definitions.md#variablemetadatamodel)| ### MessageEncoding Specifies the encoding format for OPC UA Publisher messages. Can be combined with compression and reversibility flags to control message format characteristics. *Type* : enum (Uadp, Json, Xml, Avro, IsReversible, JsonReversible, IsGzipCompressed, JsonGzip, AvroGzip, JsonReversibleGzip) ### MessagingMode Defines how OPC UA Publisher formats and structures messages for transport. Each mode provides different trade-offs between message completeness, bandwidth efficiency, and compatibility with different message consumers. *Type* : enum (PubSub, Samples, FullNetworkMessages, FullSamples, DataSetMessages, SingleDataSetMessage, DataSets, SingleDataSet, RawDataSets, SingleRawDataSet) ### MethodCallArgumentModel Method argument model |Name|Description|Schema| |---|---|---| |**dataType**
*optional*|Data type Id of the value (from meta data)|string| |**value**
*optional*|Initial value or value to use|object| ### MethodCallRequestModel Call request model |Name|Description|Schema| |---|---|---| |**arguments**
*optional*|Arguments for the method - null means no args|< [MethodCallArgumentModel](definitions.md#methodcallargumentmodel) > array| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**methodBrowsePath**
*optional*|An optional component path from the node identified by
MethodId or from a resolved objectId to the actual
method node.|< string > array| |**methodId**
*optional*|Method id of method to call.|string| |**objectBrowsePath**
*optional*|An optional component path from the node identified by
ObjectId to the actual object or objectType node.
If ObjectId is null, the root node (i=84) is used|< string > array| |**objectId**
*optional*|Context of the method, i.e. an object or object type
node. If null then the method is called in the context
of the inverse HasComponent reference of the MethodId
if it exists.|string| ### MethodCallRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[MethodCallRequestModel](definitions.md#methodcallrequestmodel)| ### MethodCallResponseModel Method call response model |Name|Description|Schema| |---|---|---| |**errorInfo**
*optional*||[ServiceResultModel](definitions.md#serviceresultmodel)| |**results**
*required*|Resulting output values of method call|< [MethodCallArgumentModel](definitions.md#methodcallargumentmodel) > array| ### MethodMetadataArgumentModel Method argument metadata model |Name|Description|Schema| |---|---|---| |**arrayDimensions**
*optional*|Optional Array dimension of argument|integer (int64)| |**defaultValue**
*optional*|Default value for the argument|object| |**description**
*optional*|Optional description of argument|string| |**errorInfo**
*optional*||[ServiceResultModel](definitions.md#serviceresultmodel)| |**name**
*required*|Name of the argument|string| |**type**
*required*||[NodeModel](definitions.md#nodemodel)| |**valueRank**
*optional*||[NodeValueRank](definitions.md#nodevaluerank)| ### MethodMetadataModel Method metadata model |Name|Description|Schema| |---|---|---| |**inputArguments**
*optional*|Input argument meta data|< [MethodMetadataArgumentModel](definitions.md#methodmetadataargumentmodel) > array| |**objectId**
*optional*|Id of object that the method is a component of|string| |**outputArguments**
*optional*|output argument meta data|< [MethodMetadataArgumentModel](definitions.md#methodmetadataargumentmodel) > array| ### MethodMetadataRequestModel Method metadata request model |Name|Description|Schema| |---|---|---| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**methodBrowsePath**
*optional*|An optional component path from the node identified by
MethodId to the actual method node.|< string > array| |**methodId**
*optional*|Method id of method to call.
(Required)|string| ### MethodMetadataRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[MethodMetadataRequestModel](definitions.md#methodmetadatarequestmodel)| ### MethodMetadataResponseModel Result of method metadata query |Name|Description|Schema| |---|---|---| |**errorInfo**
*optional*||[ServiceResultModel](definitions.md#serviceresultmodel)| |**inputArguments**
*optional*|Input argument meta data|< [MethodMetadataArgumentModel](definitions.md#methodmetadataargumentmodel) > array| |**objectId**
*optional*|Id of object that the method is a component of|string| |**outputArguments**
*optional*|output argument meta data|< [MethodMetadataArgumentModel](definitions.md#methodmetadataargumentmodel) > array| ### ModelChangeHandlingOptionsModel Describes how model changes are published |Name|Description|Schema| |---|---|---| |**rebrowseIntervalTimespan**
*optional*|Rebrowse period|string (date-span)| ### ModificationInfoModel Modification information |Name|Description|Schema| |---|---|---| |**modificationTime**
*optional*|Modification time|string (date-time)| |**updateType**
*optional*||[HistoryUpdateOperation](definitions.md#historyupdateoperation)| |**userName**
*optional*|User who made the change|string| ### MonitoredItemWatchdogCondition Defines the conditions that trigger the subscription watchdog behavior. Works in conjunction with OpcNodeWatchdogTimespan to determine when nodes are considered "late" and DataSetWriterWatchdogBehavior to define the response. Can be configured globally via the --mwc command line option. *Type* : enum (WhenAllAreLate, WhenAnyIsLate) ### NamespaceFormat Namespace serialization format for node ids and qualified names. *Type* : enum (Uri, Index, Expanded, ExpandedWithNamespace0) ### NodeAccessLevel Flags that can be set for the AccessLevel attribute. *Type* : enum (None, CurrentRead, CurrentWrite, HistoryRead, HistoryWrite, SemanticChange, StatusWrite, TimestampWrite, NonatomicRead, NonatomicWrite, WriteFullArrayOnly) ### NodeAccessRestrictions Flags that can be read or written in the AccessRestrictions attribute. *Type* : enum (None, SigningRequired, EncryptionRequired, SessionRequired) ### NodeAttribute Node attribute identifiers *Type* : enum (NodeId, NodeClass, BrowseName, DisplayName, Description, WriteMask, UserWriteMask, IsAbstract, Symmetric, InverseName, ContainsNoLoops, EventNotifier, Value, DataType, ValueRank, ArrayDimensions, AccessLevel, UserAccessLevel, MinimumSamplingInterval, Historizing, Executable, UserExecutable, DataTypeDefinition, RolePermissions, UserRolePermissions, AccessRestrictions) ### NodeClass Node class *Type* : enum (Object, Variable, Method, ObjectType, VariableType, ReferenceType, DataType, View) ### NodeEventNotifier Flags that can be set for the EventNotifier attribute. *Type* : enum (SubscribeToEvents, HistoryRead, HistoryWrite) ### NodeIdModel Represents an OPC UA Node identifier in string format. Used to identify nodes in the OPC UA address space for monitoring. Supports standard OPC UA node ID formats including: - Namespace index and identifier (ns=0;i=85) - String identifiers (ns=2;s=MyNode) - GUID identifiers (ns=3;g=8599E6C4-6667-4FB7-9EA9-C6896B31DB02) - Opaque/binary identifiers (ns=4;b=FA34E...) |Name|Description|Schema| |---|---|---| |**Identifier**
*optional*|The node identifier string in standard OPC UA notation.
Format: ns={namespace};{type}={value}
Examples:
- ns=0;i=85 (numeric identifier)
- ns=2;s=MyNode (string identifier)
- ns=3;g=8599E6C4-6667-4FB7-9EA9-C6896B31DB02 (GUID)
- ns=4;b=FA34E... (binary/opaque)
If namespace index is omitted, ns=0 is assumed.|string| ### NodeMetadataRequestModel Node metadata request model |Name|Description|Schema| |---|---|---| |**browsePath**
*optional*|An optional component path from the node identified by
NodeId to the actual node.|< string > array| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**nodeId**
*optional*|Node id of the type.
(Required)|string| ### NodeMetadataRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[NodeMetadataRequestModel](definitions.md#nodemetadatarequestmodel)| ### NodeMetadataResponseModel Node metadata model |Name|Description|Schema| |---|---|---| |**dataTypeMetadata**
*optional*||[DataTypeMetadataModel](definitions.md#datatypemetadatamodel)| |**description**
*optional*|The description for the node.|string| |**displayName**
*optional*|The display name of the node.|string| |**errorInfo**
*optional*||[ServiceResultModel](definitions.md#serviceresultmodel)| |**nethodMetadata**
*optional*||[MethodMetadataModel](definitions.md#methodmetadatamodel)| |**nodeClass**
*optional*||[NodeClass](definitions.md#nodeclass)| |**nodeId**
*optional*|The node id of the node|string| |**typeDefinition**
*optional*||[TypeDefinitionModel](definitions.md#typedefinitionmodel)| |**variableMetadata**
*optional*||[VariableMetadataModel](definitions.md#variablemetadatamodel)| ### NodeModel Node model |Name|Description|Schema| |---|---|---| |**accessLevel**
*optional*||[NodeAccessLevel](definitions.md#nodeaccesslevel)| |**accessRestrictions**
*optional*||[NodeAccessRestrictions](definitions.md#nodeaccessrestrictions)| |**arrayDimensions**
*optional*|Array dimensions of variable or variable type.
(default: empty array)|integer (int64)| |**browseName**
*optional*|Browse name|string| |**children**
*optional*|Whether node has children which are defined as
any forward hierarchical references.
(default: unknown)|boolean| |**containsNoLoops**
*optional*|Whether a view contains loops. Null if
not a view.|boolean| |**dataType**
*optional*|If variable the datatype of the variable.
(default: null)|string| |**dataTypeDefinition**
*optional*|Data type definition in case node is a
data type node and definition is available,
otherwise null.|object| |**description**
*optional*|Description if any|string| |**displayName**
*optional*|Display name|string| |**errorInfo**
*optional*||[ServiceResultModel](definitions.md#serviceresultmodel)| |**eventNotifier**
*optional*||[NodeEventNotifier](definitions.md#nodeeventnotifier)| |**executable**
*optional*|If method node class, whether method can
be called.|boolean| |**historizing**
*optional*|Whether the value of a variable is historizing.
(default: false)|boolean| |**inverseName**
*optional*|Inverse name of the reference if the node is
a reference type, otherwise null.|string| |**isAbstract**
*optional*|Whether type is abstract, if type can
be abstract. Null if not type node.
(default: false)|boolean| |**minimumSamplingInterval**
*optional*|Minimum sampling interval for the variable
value, otherwise null if not a variable node.
(default: null)|number (double)| |**nodeClass**
*optional*||[NodeClass](definitions.md#nodeclass)| |**nodeId**
*required*|Id of node.
(Mandatory).
**Minimum length** : `1`|string| |**rolePermissions**
*optional*|Role permissions|< [RolePermissionModel](definitions.md#rolepermissionmodel) > array| |**serverPicoseconds**
*optional*|Pico seconds part of when value was read at server.|integer (int32)| |**serverTimestamp**
*optional*|Timestamp of when value was read at server.|string (date-time)| |**sourcePicoseconds**
*optional*|Pico seconds part of when value was read at source.|integer (int32)| |**sourceTimestamp**
*optional*|Timestamp of when value was read at source.|string (date-time)| |**symmetric**
*optional*|Whether the reference is symmetric in case
the node is a reference type, otherwise
null.|boolean| |**typeDefinitionId**
*optional*|Optional type definition of the node|string| |**userAccessLevel**
*optional*||[NodeAccessLevel](definitions.md#nodeaccesslevel)| |**userExecutable**
*optional*|If method node class, whether method can
be called by current user.
(default: false if not executable)|boolean| |**userRolePermissions**
*optional*|User Role permissions|< [RolePermissionModel](definitions.md#rolepermissionmodel) > array| |**userWriteMask**
*optional*|User write mask for the node
(default: 0)|integer (int64)| |**value**
*optional*|Value of variable or default value of the
subtyped variable in case node is a variable
type, otherwise null.|object| |**valueRank**
*optional*||[NodeValueRank](definitions.md#nodevaluerank)| |**writeMask**
*optional*|Default write mask for the node
(default: 0)|integer (int64)| ### NodePathTargetModel Node path target |Name|Description|Schema| |---|---|---| |**browsePath**
*required*|The target browse path|< string > array| |**remainingPathIndex**
*optional*|Remaining index in path|integer (int32)| |**target**
*required*||[NodeModel](definitions.md#nodemodel)| ### NodeReferenceModel Reference model |Name|Description|Schema| |---|---|---| |**direction**
*optional*||[BrowseDirection](definitions.md#browsedirection)| |**errorInfo**
*optional*||[ServiceResultModel](definitions.md#serviceresultmodel)| |**referenceTypeId**
*optional*|Reference Type id|string| |**target**
*required*||[NodeModel](definitions.md#nodemodel)| ### NodeType The node type *Type* : enum (Unknown, Variable, DataVariable, Property, DataType, View, Object, Event, Interface) ### NodeValueRank Constants defined for the ValueRank attribute. *Type* : enum (OneOrMoreDimensions, OneDimension, TwoDimensions, ScalarOrOneDimension, Any, Scalar) ### OpcAuthenticationMode Specifies the authentication method used to connect to OPC UA servers. The chosen mode determines how the Publisher authenticates itself to servers. When using credentials or certificates, encrypted communication should be enabled via UseSecurity or EndpointSecurityMode to protect authentication secrets. *Type* : enum (Anonymous, UsernamePassword, Certificate) ### OpcNodeModel Defines configuration for monitoring an OPC UA node. Contains settings for sampling, filtering, publishing behavior, and message routing. This model allows fine-grained control over how each node's data is collected and transmitted. Part of a PublishedNodesEntryModel's OpcNodes collection. |Name|Description|Schema| |---|---|---| |**AttributeId**
*optional*||[NodeAttribute](definitions.md#nodeattribute)| |**BrowsePath**
*optional*|Relative path through the address space to reach target
node. Sequence of browse names from starting node to
target. Example: ["Objects", "Server", "Data",
"Dynamic", "Scalar"]. Allows referencing nodes through
hierarchical structure. Alternative to direct node ID
addressing.|< string > array| |**ConditionHandling**
*optional*||[ConditionHandlingOptionsModel](definitions.md#conditionhandlingoptionsmodel)| |**CyclicReadMaxAge**
*optional*|Maximum age for cached values in cyclic reads. Specified in
milliseconds. Default: 0 (no caching) Only applies when
UseCyclicRead is true. Server may return cached value if
within max age. Helps reduce server load in high-frequency
reads. Ignored when CyclicReadMaxAgeTimespan is defined.|integer (int32)| |**CyclicReadMaxAgeTimespan**
*optional*|Maximum age for cached values in cyclic reads as TimeSpan.
Takes precedence over CyclicReadMaxAge if both defined.
Only applies when UseCyclicRead is true. Default:
"00:00:00" (no caching) Example: "00:00:00.500" for 500ms
max cache age. Helps optimize read performance vs data
freshness.|string (date-span)| |**DataChangeTrigger**
*optional*||[DataChangeTriggerType](definitions.md#datachangetriggertype)| |**DataSetClassFieldId**
*optional*|Unique identifier for correlating fields with dataset
class metadata. Links monitored item data with dataset
class field definitions. Used to provide context and type
information for the field. Must match corresponding field
ID in dataset class metadata. Important for proper message
decoding by subscribers.|string (uuid)| |**DataSetFieldId**
*optional*|Custom identifier for this node in dataset messages. Used
as field name in message payloads if specified. Falls back
to DisplayName if not provided. Helps correlate data with
specific measurements or tags. Must be unique within a
dataset writer.|string| |**DeadbandType**
*optional*||[DeadbandType](definitions.md#deadbandtype)| |**DeadbandValue**
*optional*|Deadband value of the data change filter to apply. Does
not apply to events|number (double)| |**DiscardNew**
*optional*|Controls queue overflow behavior for monitored items.
True: Discard newest values when queue is full (LIFO).
False: Discard oldest values when queue is full (FIFO,
default). Use True to preserve historical data during
connection issues. Use False to maintain current value
accuracy.|boolean| |**DisplayName**
*optional*|Human-readable name for the monitored item. Used as field
identifier if DataSetFieldId not specified. Can be
overridden by actual node DisplayName if
FetchDisplayName=true. Helps identify data sources in
messages and logs. Should be unique within a dataset for
clear identification.|string| |**EventFilter**
*optional*||[EventFilterModel](definitions.md#eventfiltermodel)| |**ExpandedNodeId**
*optional*|Alternative node identifier with full namespace URI. Same
as Id but uses complete namespace URI instead of index.
Format: "nsu={uri};{type}={value}" Example:
"nsu=http://opcfoundation.org/UA/;i=2258" Provides more
portable node identification across servers.|string| |**FetchDisplayName**
*optional*|Retrieve node's DisplayName attribute on startup. True:
Query and use actual display name False: Use configured
DisplayName (default) Overrides DataSetFetchDisplayNames
setting. Used for human-readable field identification.|boolean| |**HeartbeatBehavior**
*optional*||[HeartbeatBehavior](definitions.md#heartbeatbehavior)| |**HeartbeatInterval**
*optional*|Node-specific heartbeat interval in milliseconds.
Overrides DefaultHeartbeatInterval from parent
configuration. Controls how often heartbeat messages are
generated. Set to 0 to disable heartbeats for this node.
Ignored when HeartbeatIntervalTimespan is defined.|integer (int32)| |**HeartbeatIntervalTimespan**
*optional*|Node-specific heartbeat interval as TimeSpan. Takes
precedence over HeartbeatInterval if both defined.
Overrides DefaultHeartbeatIntervalTimespan setting.
Provides more precise control over timing. Example:
"00:00:10" for 10-second interval.|string (date-span)| |**Id**
*optional*|The OPC UA node identifier string in standard notation.
Format: ns={namespace};{type}={value} Required field that
uniquely identifies the node to monitor. Examples:
"ns=2;s=MyTag", "ns=0;i=2258" See OPC UA Part 3 for node
ID format specifications.|string| |**IndexRange**
*optional*|Range specification for array or string values. Format:
"start:end" or "index". Examples: "0:3" (first 4
elements), "7" (8th element) Allows monitoring specific
array elements. Default: null (entire value monitored)|string| |**MethodMetadata**
*optional*||[MethodMetadataModel](definitions.md#methodmetadatamodel)| |**ModelChangeHandling**
*optional*||[ModelChangeHandlingOptionsModel](definitions.md#modelchangehandlingoptionsmodel)| |**OpcPublishingInterval**
*optional*|Client-side publishing rate in milliseconds. Controls how
often the server sends notifications. Must be >=
OpcSamplingInterval for proper operation. Overrides
DataSetPublishingInterval when specified. Ignored if
OpcPublishingIntervalTimespan is defined.|integer (int32)| |**OpcPublishingIntervalTimespan**
*optional*|OpcPublishingInterval as TimeSpan.|string (date-span)| |**OpcSamplingInterval**
*optional*|Server-side sampling rate in milliseconds. Determines how
often the server checks for value changes. Default from
DataSetSamplingInterval if not specified. Should be less
than or equal to OpcPublishingInterval for effective
sampling. Ignored when OpcSamplingIntervalTimespan is
defined.|integer (int32)| |**OpcSamplingIntervalTimespan**
*optional*|Server-side sampling rate as a TimeSpan. Takes precedence
over OpcSamplingInterval if both are defined. Provides
more precise control over timing than milliseconds.
Example: "00:00:00.100" for 100ms sampling. Should be
less than or equal to OpcPublishingIntervalTimespan for
effective sampling.|string (date-span)| |**QualityOfService**
*optional*||[QoS](definitions.md#qos)| |**QueueSize**
*optional*|Size of the server-side queue for this monitored item.
Controls how many values can be buffered during slow
connections. Values are discarded according to DiscardNew
when queue is full. Default is 1 unless otherwise
configured. Larger queues help prevent data loss but use
more server memory.|integer (int64)| |**RegisterNode**
*optional*|Optimize node access using RegisterNodes service. True:
Register node for faster subsequent reads False: Use
direct node access (default) Can improve performance for
frequently accessed nodes. Server must support
RegisterNodes service.|boolean| |**SkipFirst**
*optional*|Controls handling of initial value notification. True:
Suppress first value from monitored item. False: Publish
initial value (default). Useful when only changes are
relevant. Server always sends initial value on creation.|boolean| |**Topic**
*optional*|Custom routing topic/queue for this node's messages.
Overrides writer and writer group queue settings. Enables
node-specific message routing patterns. Messages are split
into separate network messages when nodes have different
topics. Format depends on transport (e.g., MQTT topic
syntax).|string| |**TriggeredNodes**
*optional*|Collection of dependent nodes triggered by this node. Read
atomically when parent node changes. Limited to one level
of triggering (no cascading). Useful for maintaining data
consistency between related measurements. Changes to
triggered nodes must be made through parent node's API
calls.|< [OpcNodeModel](definitions.md#opcnodemodel) > array| |**TypeDefinitionId**
*optional*|A type definition id that references a well known opc ua
type definition node for the variable represented by this
node entry.|string| |**UseCyclicRead**
*optional*|Use periodic reads instead of monitored items. True: Sample
using CyclicRead service calls False: Use standard
subscription monitoring (default) Useful for nodes that
don't support monitoring or when consistent sampling
timing is required. Consider CyclicReadMaxAge when
enabled.|boolean| ### OperationContextModel Operation log model |Name|Description|Schema| |---|---|---| |**AuthorityId**
*optional*|User|string| |**Time**
*optional*|Operation time|string (date-time)| ### OperationLimitsModel Server limits |Name|Description|Schema| |---|---|---| |**maxArrayLength**
*optional*|Max array length supported|integer (int64)| |**maxBrowseContinuationPoints**
*optional*|Max browse continuation points|integer (int32)| |**maxByteStringLength**
*optional*|Max byte buffer length supported|integer (int64)| |**maxHistoryContinuationPoints**
*optional*|Max history continuation points|integer (int32)| |**maxMonitoredItemsPerCall**
*optional*|Max monitored items that can be updated at once.|integer (int64)| |**maxNodesPerBrowse**
*optional*|Max nodes that can be part of a single browse call.|integer (int64)| |**maxNodesPerHistoryReadData**
*optional*|Number of nodes that can be in a History Read value call|integer (int64)| |**maxNodesPerHistoryReadEvents**
*optional*|Number of nodes that can be in a History Read events call|integer (int64)| |**maxNodesPerHistoryUpdateData**
*optional*|Number of nodes that can be in a History Update call|integer (int64)| |**maxNodesPerHistoryUpdateEvents**
*optional*|Number of nodes that can be in a History events update call|integer (int64)| |**maxNodesPerMethodCall**
*optional*|Max nodes that can be read in single method call|integer (int64)| |**maxNodesPerNodeManagement**
*optional*|Max nodes that can be added or removed in a single call.|integer (int64)| |**maxNodesPerRead**
*optional*|Max nodes that can be read in single read call|integer (int64)| |**maxNodesPerRegisterNodes**
*optional*|Max nodes that can be registered at once|integer (int64)| |**maxNodesPerTranslatePathsToNodeIds**
*optional*|Max nodes that can be part of a browse path|integer (int64)| |**maxNodesPerWrite**
*optional*|Max nodes that can be read in single write call|integer (int64)| |**maxQueryContinuationPoints**
*optional*|Max query continuation points|integer (int32)| |**maxStringLength**
*optional*|Max string length supported|integer (int64)| |**minSupportedSampleRate**
*optional*|Min supported sampling rate|number (double)| ### ProblemDetails |Name|Schema| |---|---| |**detail**
*optional*|string| |**instance**
*optional*|string| |**status**
*optional*|integer (int32)| |**title**
*optional*|string| |**type**
*optional*|string| ### PublishBulkRequestModel Publish in bulk request |Name|Description|Schema| |---|---|---| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**nodesToAdd**
*optional*|Node to add|< [PublishedItemModel](definitions.md#publisheditemmodel) > array| |**nodesToRemove**
*optional*|Node to remove|< string > array| ### PublishBulkRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[PublishBulkRequestModel](definitions.md#publishbulkrequestmodel)| ### PublishBulkResponseModel Result of bulk request |Name|Description|Schema| |---|---|---| |**nodesToAdd**
*optional*|Node to add|< [ServiceResultModel](definitions.md#serviceresultmodel) > array| |**nodesToRemove**
*optional*|Node to remove|< [ServiceResultModel](definitions.md#serviceresultmodel) > array| ### PublishDiagnosticInfoModel Model for a diagnostic info. |Name|Description|Schema| |---|---|---| |**connectionRetries**
*optional*|ConnectionRetries|integer (int64)| |**encoderAvgIoTChunkUsage**
*optional*|EncoderAvgIoTChunkUsage|number (double)| |**encoderAvgIoTMessageBodySize**
*optional*|EncoderAvgIoTMessageBodySize|number (double)| |**encoderAvgNotificationsMessage**
*optional*|EncoderAvgNotificationsMessage|number (double)| |**encoderIoTMessagesProcessed**
*optional*|EncoderIoTMessagesProcessed|integer (int64)| |**encoderMaxMessageSplitRatio**
*optional*|Encoder max message split ratio|number (double)| |**encoderNotificationsDropped**
*optional*|EncoderNotificationsDropped|integer (int64)| |**encoderNotificationsProcessed**
*optional*|EncoderNotificationsProcessed|integer (int64)| |**encodingBlockInputSize**
*optional*|EncodingBlockInputSize|integer (int64)| |**encodingBlockOutputSize**
*optional*|EncodingBlockOutputSize|integer (int64)| |**endpoints**
*optional*|Endpoints covered by the diagnostics model.
The endpoints are all part of the same writer
group. Specify|< [PublishedNodesEntryModel](definitions.md#publishednodesentrymodel) > array| |**estimatedIoTChunksPerDay**
*optional*|EstimatedIoTChunksPerDay|number (double)| |**ingestionDuration**
*optional*|IngestionDuration|string (date-span)| |**ingressBatchBlockBufferSize**
*optional*|IngressBatchBlockBufferSize|integer (int64)| |**ingressCyclicReads**
*optional*|Number of cyclic reads of the total value changes|integer (int64)| |**ingressDataChanges**
*optional*|IngressDataChanges|integer (int64)| |**ingressDataChangesInLastMinute**
*optional*|Data changes received in the last minute|integer (int64)| |**ingressEventNotifications**
*optional*|Number of incoming event notifications|integer (int64)| |**ingressEvents**
*optional*|Total incoming events so far.|integer (int64)| |**ingressHeartbeats**
*optional*|Number of heartbeats of the total value changes|integer (int64)| |**ingressValueChanges**
*optional*|IngressValueChanges|integer (int64)| |**ingressValueChangesInLastMinute**
*optional*|Value changes received in the last minute|integer (int64)| |**monitoredOpcNodesFailedCount**
*optional*|MonitoredOpcNodesFailedCount|integer (int64)| |**monitoredOpcNodesSucceededCount**
*optional*|MonitoredOpcNodesSucceededCount|integer (int64)| |**opcEndpointConnected**
*optional*|OpcEndpointConnected|boolean| |**outgressInputBufferCount**
*optional*|OutgressInputBufferCount|integer (int64)| |**outgressInputBufferDropped**
*optional*|OutgressInputBufferDropped|integer (int64)| |**outgressIoTMessageCount**
*optional*|OutgressIoTMessageCount|integer (int64)| |**sentMessagesPerSec**
*optional*|SentMessagesPerSec|number (double)| ### PublishStartRequestModel Publish request |Name|Schema| |---|---| |**header**
*optional*|[RequestHeaderModel](definitions.md#requestheadermodel)| |**item**
*required*|[PublishedItemModel](definitions.md#publisheditemmodel)| ### PublishStartRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[PublishStartRequestModel](definitions.md#publishstartrequestmodel)| ### PublishStartResponseModel Result of publish request |Name|Schema| |---|---| |**errorInfo**
*optional*|[ServiceResultModel](definitions.md#serviceresultmodel)| ### PublishStopRequestModel Unpublish request |Name|Description|Schema| |---|---|---| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**nodeId**
*required*|Node of published item to unpublish
**Minimum length** : `1`|string| ### PublishStopRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[PublishStopRequestModel](definitions.md#publishstoprequestmodel)| ### PublishStopResponseModel Result of publish stop request |Name|Schema| |---|---| |**errorInfo**
*optional*|[ServiceResultModel](definitions.md#serviceresultmodel)| ### PublishedItemListRequestModel Request list of published items |Name|Description|Schema| |---|---|---| |**continuationToken**
*optional*|Continuation token or null to start|string| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| ### PublishedItemListRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[PublishedItemListRequestModel](definitions.md#publisheditemlistrequestmodel)| ### PublishedItemListResponseModel List of published nodes |Name|Description|Schema| |---|---|---| |**continuationToken**
*optional*|Continuation or null if final|string| |**items**
*optional*|Monitored items|< [PublishedItemModel](definitions.md#publisheditemmodel) > array| ### PublishedItemModel A monitored and published item |Name|Description|Schema| |---|---|---| |**displayName**
*optional*|Display name of the variable node monitored|string| |**heartbeatInterval**
*optional*|Heartbeat interval to use|string (date-span)| |**nodeId**
*required*|Variable node monitored
**Minimum length** : `1`|string| |**publishingInterval**
*optional*|Publishing interval to use|string (date-span)| |**samplingInterval**
*optional*|Sampling interval to use|string (date-span)| ### PublishedNodeDeleteAssetRequestModel Contains entry in the published nodes configuration representing the asset as well as an optional request header. |Name|Description|Schema| |---|---|---| |**entry**
*required*||[PublishedNodesEntryModel](definitions.md#publishednodesentrymodel)| |**force**
*optional*|The asset on the server is deleted no matter whether
the removal in the publisher configuration was successful
or not.|boolean| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| ### PublishedNodeExpansionModel Node expansion configuration. Configures how an entry should be expanded into configuration. If a node is an object it is expanded to all contained variables. If a node is an object type, all objects of that type are searched from the object root node. These found objects are then expanded into their variables. If the node is a variable, the variable is expanded to include all contained variables or properties. All entries will have the data set field id configured as data set class id. If a node is a variable type, then all variables of this type are found and added to a single writer entry. Note: That by themselves these variables are no further expanded. |Name|Description|Schema| |---|---|---| |**createSingleWriter**
*optional*|By default the api will create a new distinct
writer per expanded object. Objects that cannot
be expanded are part of the originally provided
writer. The writer id is then post fixed with
the data set field id of the object node field.
If true, all variables of all expanded nodes are
added to the originally provided entry.|boolean| |**discardErrors**
*optional*|Errors are silently discarded and only
successfully expanded nodes are returned.|boolean| |**excludeRootIfInstanceNode**
*optional*|If the node is an object or variable instance do
not include it but only the instances underneath
them.|boolean| |**flattenTypeInstance**
*optional*|If false, treats instance nodes found just like
objects that need to be expanded. In case of a
companion spec object type this could be set to
true, flattening the structure into a single
writer that represents the object in its entirety.
However, when using generic interfaces that can
be implemented across objects in the address
space and only its variables are important, it
might be useful to set this to false.|boolean| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**includeMethods**
*optional*|Include not just variables and events but also
methods when expanding an object.|boolean| |**maxDepth**
*optional*|Max browse depth for object search operation or
when searching for an instance of a type.
To only expand an object to its variables set
this value to 0. The depth of expansion of a
variable itself can be controlled via the
Azure.IIoT.OpcUa.Publisher.Models.PublishedNodeExpansionModel.MaxLevelsToExpand" property.
If the root object is excluded a value of 0 is
equivalent to a value of 1 to get the first level
of objects contained in the object but not the
object itself, e.g. a folder object.|integer (int64)| |**maxLevelsToExpand**
*optional*|Max number of levels to expand an instance node
such as an object or variable into resulting
variables.
If the node is a variable instance to start with
but the Azure.IIoT.OpcUa.Publisher.Models.PublishedNodeExpansionModel.ExcludeRootIfInstanceNode
property is set to excluded it, then setting this
value to 0 is equivalent to a value of 1 to get
the first level of variables contained in the
variable, but not the variable itself. Otherwise
only the variable itelf is returned. If the node
is an object instance, 0 is equivalent to
infinite and all levels are expanded.|integer (int64)| |**noSubTypesOfTypeNodes**
*optional*|Do not consider subtypes of an object type when
searching for instances of the type.|boolean| |**useBrowseNameAsDisplayName**
*optional*|Use the browse name as display name for nodes. The
display name is rooted in the parent node from
which browsing occurs, or just the browse name if
the browse root is not a parent.|boolean| ### PublishedNodeExpansionModelPublishedNodesEntryRequestModel Wraps a request and a published nodes entry to bind to a body more easily for api that requires an entry and additional configuration |Name|Schema| |---|---| |**entry**
*required*|[PublishedNodesEntryModel](definitions.md#publishednodesentrymodel)| |**request**
*optional*|[PublishedNodeExpansionModel](definitions.md#publishednodeexpansionmodel)| ### PublishedNodesEntryModel Configuration model for OPC UA Publisher that defines how OPC UA nodes are published to messaging systems. Used to configure connections to OPC UA servers, setup node monitoring, and control message publishing. Key features: - Endpoint configuration and security settings - Writer group and dataset organization - Publishing intervals and sampling controls - Message batching and triggering - Subscription and monitoring options - Heartbeat and watchdog behaviors - Security modes and authentication For detailed configuration options, see individual properties. |Name|Description|Schema| |---|---|---| |**BatchSize**
*optional*|The number of notifications that are queued before a
network message is generated. Controls message batching for
optimizing network traffic vs latency. For historic reasons
the default value is 50 unless otherwise configured via the
--bs command line option.|integer (int64)| |**BatchTriggerInterval**
*optional*|The interval at which batched network messages are
published, in milliseconds. Messages are published when
this interval elapses or when BatchSize is reached. For
historic reasons the default is 10 seconds unless
configured via --bi. Ignored when
BatchTriggerIntervalTimespan is specified. Used with
BatchSize to optimize network traffic vs latency.|integer (int32)| |**BatchTriggerIntervalTimespan**
*optional*|The interval at which batched network messages are
published, as a TimeSpan. Takes precedence over
BatchTriggerInterval if both are defined. Messages are
published when this interval elapses or when BatchSize is
reached. Provides more precise control over publishing
timing than millisecond interval. Used with BatchSize to
optimize network traffic vs latency.|string (date-span)| |**DataSetClassId**
*optional*|The optional dataset class id as it shall appear in dataset
messages and dataset metadata. Used to uniquely identify the
type of dataset being published. Default: Guid.Empty|string (uuid)| |**DataSetDescription**
*optional*|The optional description of the dataset.|string| |**DataSetExtensionFields**
*optional*|Optional key-value pairs inserted into key frame and
metadata messages in the same data set. Values are
formatted using OPC UA Variant JSON encoding. Used to add
contextual information to datasets.|< string, object > map| |**DataSetFetchDisplayNames**
*optional*|Controls whether to fetch display names of monitored
variable nodes and use those inside messages as field
names. When true, fetches display names for all nodes. If
false, uses DisplayName value if provided; if not provided,
uses the node id. Can be configured via --fd command line
option.|boolean| |**DataSetKeyFrameCount**
*optional*|Controls key frame insertion frequency in the message
stream. A key frame contains all current values, while
delta frames only contain changes. Setting this ensures
periodic complete state updates, useful for late-joining
consumers or state synchronization. Key frames can also
include configured DataSetExtensionFields for additional
context. Default: 0 (key frames disabled)|integer (int64)| |**DataSetName**
*optional*|The optional name of the dataset as it will appear in the
dataset metadata. Used for identification and organization
of datasets.|string| |**DataSetPublishingInterval**
*optional*|The publishing interval used for a grouped set of nodes
under a certain DataSetWriter, expressed in milliseconds.
When a specific node underneath DataSetWriter defines
OpcPublishingInterval (or Timespan), its value will
overwrite this interval and potentially split the data set
writer into more than one subscription. Ignored when
DataSetPublishingIntervalTimespan is present.|integer (int32)| |**DataSetPublishingIntervalTimespan**
*optional*|The publishing interval for a dataset writer, expressed as a
TimeSpan value. Takes precedence over
DataSetPublishingInterval if defined. Provides more precise
control over timing than milliseconds. When overridden by
node-specific intervals, the writer may split into multiple
subscriptions.|string (date-span)| |**DataSetRootNodeId**
*optional*|A root node that all nodes that use a non rooted browse paths in the
dataset should start from.|string| |**DataSetRouting**
*optional*||[DataSetRoutingMode](definitions.md#datasetroutingmode)| |**DataSetSamplingInterval**
*optional*|Default sampling interval in milliseconds for all monitored
items in the dataset. Used if individual nodes don't
specify their own sampling interval. Follows OPC UA
specification for sampling behavior. Ignored when
DataSetSamplingIntervalTimespan is present. Defaults to
value configured via --oi command line option.|integer (int32)| |**DataSetSamplingIntervalTimespan**
*optional*|Default sampling interval as TimeSpan for all monitored
items in the dataset. Takes precedence over
DataSetSamplingInterval if both are defined. Used if
individual nodes don't specify their own sampling interval.
Provides more precise control over sampling timing. Follows
OPC UA specification for sampling behavior.|string (date-span)| |**DataSetSourceUri**
*optional*|Contains an uri identifier that allows correlation of the writer
data set source into other systems. Will be used as part of
cloud events header if enabled.|string| |**DataSetSubject**
*optional*|Contains an identifier that allows correlation of the writer
group into other systems in the context of the source. Will be
used as part of cloud events header if enabled.|string| |**DataSetType**
*optional*|A type definition id that references a well known opc ua type
definition node for the dataset represented by this entry.
If set it is used in context of cloud events to specify a concrete
type of dataset message in the cloud events type header.|string| |**DataSetWriterGroup**
*optional*|The data set writer group collecting datasets defined for a
certain endpoint. This attribute is used to identify the
session opened into the server. The default value consists
of the EndpointUrl string, followed by a deterministic hash
composed of the EndpointUrl, UseSecurity,
OpcAuthenticationMode, UserName and Password attributes.|string| |**DataSetWriterId**
*optional*|The unique identifier for a data set writer used to collect
OPC UA nodes to be semantically grouped and published with
the same publishing interval. When not specified, uses a
string representing the common publishing interval of the
nodes in the data set collection. This attribute uniquely
identifies a data set within a DataSetWriterGroup. The
uniqueness is determined using the provided DataSetWriterId
and the publishing interval of the grouped OpcNodes.|string| |**DataSetWriterWatchdogBehavior**
*optional*||[SubscriptionWatchdogBehavior](definitions.md#subscriptionwatchdogbehavior)| |**DefaultHeartbeatBehavior**
*optional*||[HeartbeatBehavior](definitions.md#heartbeatbehavior)| |**DefaultHeartbeatInterval**
*optional*|The interval in milliseconds at which to publish heartbeat
messages. Heartbeat acts like a watchdog that fires after
this interval has passed and no new value has been
received. A value of 0 disables heartbeat. Ignored when
DefaultHeartbeatIntervalTimespan is defined. See
heartbeat.md for detailed behavior documentation.|integer (int32)| |**DefaultHeartbeatIntervalTimespan**
*optional*|The heartbeat interval as TimeSpan for all nodes in this
dataset. Takes precedence over DefaultHeartbeatInterval if
defined. Controls how often heartbeat messages are
published when no value changes occur.|string (date-span)| |**DisableSubscriptionTransfer**
*optional*|Controls whether subscription transfer is disabled during
reconnect. When false (default), attempts to transfer
subscriptions on reconnect to maintain data continuity. Set
to true to fix interoperability issues with servers that
don't support subscription transfer. Can be configured
globally via command line options.|boolean| |**DumpConnectionDiagnostics**
*optional*|Enables detailed server diagnostics logging for the
connection. When enabled, provides additional diagnostic
information useful for troubleshooting connectivity,
authentication, and subscription issues. The diagnostics
data is included in the publisher's logs. Default: false|boolean| |**EncryptedAuthPassword**
*optional*|The encrypted password for authentication when
OpcAuthenticationMode is UsernamePassword. For certificate
authentication, contains the password to access the private
key. Encrypted credentials at rest can be enforced using
the --fce command line option. Version 2.6+ stores
credentials in plain text by default, while 2.5 and below
always encrypted them.|string| |**EncryptedAuthUsername**
*optional*|The encrypted username for authentication when
OpcAuthenticationMode is UsernamePassword. Encrypted
credentials at rest can be enforced using the --fce command
line option. Version 2.6+ stores credentials in plain text
by default, while 2.5 and below always encrypted them.|string| |**EndpointSecurityMode**
*optional*||[SecurityMode](definitions.md#securitymode)| |**EndpointSecurityPolicy**
*optional*|The security policy URI to use for the endpoint connection.
Overrides UseSecurity setting and refines
EndpointSecurityMode choice. Examples include
"http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256".
If the specified policy is not available with the chosen
security mode, connectivity will fail. This allows enforcing
specific security requirements.|string| |**EndpointUrl**
*required*|The required OPC UA server endpoint URL to connect to. This
is the only required field in the configuration. Format:
"opc.tcp://host:port/path"
**Minimum length** : `1`|string| |**LastChangeDateTime**
*optional*|The time the Publisher configuration was last updated.
Read only and informational only.|string (date-time)| |**MaxKeepAliveCount**
*optional*|Defines how many publishing timer expirations to wait
before sending a keep-alive message when no notifications
are pending. Works with SendKeepAliveDataSetMessages to
maintain connection awareness. Keep-alive messages help
detect connection issues even when no data changes are
occurring.|integer (int64)| |**MessageEncoding**
*optional*||[MessageEncoding](definitions.md#messageencoding)| |**MessageRetention**
*optional*|Controls message retention for this specific writer.
Overrides WriterGroupMessageRetention at the individual
writer level. Only applied if the transport technology
supports retention. Together with QueueName, allows
splitting messages across different queues with different
retention policies.|boolean| |**MessageTtlTimespan**
*optional*|Time-to-live duration for messages sent by this specific
writer. Overrides WriterGroupMessageTtlTimespan at the
individual writer level. Only applied if the transport
technology supports message TTL. Allows different TTL
settings for different types of data.|string (date-span)| |**MessagingMode**
*optional*||[MessagingMode](definitions.md#messagingmode)| |**MetaDataQueueName**
*optional*|The queue name to use for metadata messages from this
writer. Overrides the default metadata topic template.
Allows routing metadata to specific destinations separate
from data messages.|string| |**MetaDataRetention**
*optional*|Metadata retention setting for the dataset writer.|boolean| |**MetaDataTtlTimespan**
*optional*|Metadata time-to-live duration for the dataset writer.|string (date-span)| |**MetaDataUpdateTime**
*optional*|The interval in milliseconds at which metadata messages are
sent, even when the metadata has not changed. Only applies
when metadata messaging is supported or explicitly enabled.
Ignored when MetaDataUpdateTimeTimespan is defined.|integer (int32)| |**MetaDataUpdateTimeTimespan**
*optional*|The interval as TimeSpan at which metadata messages are
sent, even when metadata has not changed. Takes precedence
over MetaDataUpdateTime if both are defined. Only applies
when metadata messaging is supported or explicitly enabled.|string (date-span)| |**NodeId**
*optional*||[NodeIdModel](definitions.md#nodeidmodel)| |**OpcAuthenticationMode**
*optional*||[OpcAuthenticationMode](definitions.md#opcauthenticationmode)| |**OpcAuthenticationPassword**
*optional*|The plaintext password for UsernamePassword authentication,
or the password protecting the private key for Certificate
authentication. For Certificate mode, this must match the
password used when adding the certificate to the PKI store.|string| |**OpcAuthenticationUsername**
*optional*|The plaintext username for UsernamePassword authentication,
or the subject name of the certificate for Certificate
authentication. When using Certificate mode, this refers to
a certificate in the User certificate store of the PKI
configuration.|string| |**OpcNodeWatchdogCondition**
*optional*||[MonitoredItemWatchdogCondition](definitions.md#monitoreditemwatchdogcondition)| |**OpcNodeWatchdogTimespan**
*optional*|The timeout duration used to monitor whether monitored
items in the subscription are continuously reporting fresh
data. This watchdog mechanism helps detect stale data or
connectivity issues. When this timeout expires, the
configured DataSetWriterWatchdogBehavior is triggered based
on OpcNodeWatchdogCondition. Expressed as a TimeSpan value.|string (date-span)| |**OpcNodes**
*optional*|The DataSet collection grouping the nodes to be published
for the specific DataSetWriter. Each node can specify
monitoring parameters including sampling intervals, deadband
settings, and event filtering options. Contains variable
nodes or event notifiers to monitor.|< [OpcNodeModel](definitions.md#opcnodemodel) > array| |**Priority**
*optional*|Priority of the writer subscription.|integer (int32)| |**PublisherId**
*optional*|Set a publisher id to use that is different form the
global publisher identity.|string| |**QualityOfService**
*optional*||[QoS](definitions.md#qos)| |**QueueName**
*optional*|Overrides the writer group queue name at the individual
writer level. When specified, causes network messages to be
split across different queues. The split also takes QoS
settings into account, allowing fine-grained control over
message routing and delivery guarantees.|string| |**RepublishAfterTransfer**
*optional*|Controls whether to republish missed values after a
subscription is transferred during reconnect handling. Only
applies when DisableSubscriptionTransfer is false. Helps
ensure no data is lost during connection interruptions.
Default: true|boolean| |**SendKeepAliveAsKeyFrameMessages**
*optional*|When sending of keep alive messages is enabled, this
flag controls whether the keep alive messages are sent
as key frames. Key frames contain all current values.|boolean| |**SendKeepAliveDataSetMessages**
*optional*|Controls whether to send keep alive messages for this
dataset when a subscription keep alive notification is
received. Keep alive messages help maintain connection
status awareness. Only valid if the messaging mode supports
keep alive messages. Default: false|boolean| |**UseReverseConnect**
*optional*|Use reverse connect to connect ot the endpoint|boolean| |**UseSecurity**
*optional*|Controls whether to use a secure OPC UA transport mode to
establish a session. When true, defaults to
SecurityMode.NotNone which requires signed or encrypted
communication. When false, uses SecurityMode.None with no
security. Can be overridden by EndpointSecurityMode and
EndpointSecurityPolicy settings. Use encrypted
communication whenever possible to protect credentials and
data.|boolean| |**Version**
*optional*|A monotonically increasing number identifying the change
version. At this point the version number is informational
only, but should be provided in API requests if available.
Not used inside file based configuration.|integer (int64)| |**WriterGroupMessageRetention**
*optional*|Controls whether messages should be retained by the
messaging system. Only applied if the transport technology
supports message retention. When true, messages are kept by
the broker even after delivery. Useful for late-joining
subscribers to receive the last known values.|boolean| |**WriterGroupMessageTtlTimepan**
*optional*|Time-to-live duration for messages sent through the writer
group. Only applied if the transport technology supports
message TTL. After this duration expires, messages may be
discarded by the messaging system. Used to prevent stale
data from being processed by consumers.|string (date-span)| |**WriterGroupPartitions**
*optional*|Specifies how many partitions to split the writer group
into when publishing to target topics. Used to distribute
message load and enable parallel processing by consumers.
Default is 1 partition. Particularly useful for
high-throughput scenarios or when using partitioned
queues/topics in the messaging system.|integer (int32)| |**WriterGroupProperties**
*optional*|Additional properties of the writer group that should be retained
with the configuration.|< string, object > map| |**WriterGroupQualityOfService**
*optional*||[QoS](definitions.md#qos)| |**WriterGroupQueueName**
*optional*|Overrides the default writer group topic template for
message routing. Used to customize where messages from this
writer group are published. Particularly useful when
publishing to MQTT topics or message queues where specific
routing patterns are needed.|string| |**WriterGroupRootNodeId**
*optional*|A node that represents the writer group in the server address space.
This is the instance id of the root node from which all datasets
originate. It is informational only and would not need to be
configured|string| |**WriterGroupTransport**
*optional*||[WriterGroupTransport](definitions.md#writergrouptransport)| |**WriterGroupTransportConfiguration**
*optional*|Pass connection string for the transport layer. This works
for transports that support connection strings such as
IoT Hub or Event Hubs. It enables overriding the default
connection string configured for the publisher. The transport
must be configured using the command line options first, and
can be overriden here. If it is not configured on the command
line first, the setting here is ignored.|string| |**WriterGroupType**
*optional*|A type that is attached to the writer group and explains the shape
of the writer group. It is the type definition id of the writer
group root node id. It is informational only and would not need
to be configured|string| ### PublishedNodesEntryModelServiceResponse Response envelope |Name|Schema| |---|---| |**errorInfo**
*optional*|[ServiceResultModel](definitions.md#serviceresultmodel)| |**result**
*optional*|[PublishedNodesEntryModel](definitions.md#publishednodesentrymodel)| ### PublishedNodesEntryModelServiceResponseIAsyncEnumerable *Type* : object ### PublishedNodesResponseModel PublishNodes direct method response *Type* : object ### QoS *Type* : enum (AtMostOnce, AtLeastOnce, ExactlyOnce) ### QueryCompilationRequestModel Query compiler request model |Name|Description|Schema| |---|---|---| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**query**
*required*|The query to compile.
**Minimum length** : `1`|string| |**queryType**
*optional*||[QueryType](definitions.md#querytype)| ### QueryCompilationRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[QueryCompilationRequestModel](definitions.md#querycompilationrequestmodel)| ### QueryCompilationResponseModel Query compiler response model |Name|Schema| |---|---| |**errorInfo**
*optional*|[ServiceResultModel](definitions.md#serviceresultmodel)| |**eventFilter**
*optional*|[EventFilterModel](definitions.md#eventfiltermodel)| ### QueryType Query type *Type* : enum (Event, Query) ### ReadEventsDetailsModel Read event data |Name|Description|Schema| |---|---|---| |**endTime**
*optional*|End time to read to|string (date-time)| |**filter**
*optional*||[EventFilterModel](definitions.md#eventfiltermodel)| |**numEvents**
*optional*|Number of events to read|integer (int64)| |**startTime**
*optional*|Start time to read from|string (date-time)| ### ReadEventsDetailsModelHistoryReadRequestModel Request node history read |Name|Description|Schema| |---|---|---| |**browsePath**
*optional*|An optional path from NodeId instance to
the actual node.|< string > array| |**details**
*required*||[ReadEventsDetailsModel](definitions.md#readeventsdetailsmodel)| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**indexRange**
*optional*|Index range to read, e.g. 1:2,0:1 for 2 slices
out of a matrix or 0:1 for the first item in
an array, string or bytestring.
See 7.22 of part 4: NumericRange.|string| |**nodeId**
*optional*|Node to read from (mandatory without browse path)|string| |**timestampsToReturn**
*optional*||[TimestampsToReturn](definitions.md#timestampstoreturn)| ### ReadEventsDetailsModelHistoryReadRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[ReadEventsDetailsModelHistoryReadRequestModel](definitions.md#readeventsdetailsmodelhistoryreadrequestmodel)| ### ReadModifiedValuesDetailsModel Read modified data |Name|Description|Schema| |---|---|---| |**endTime**
*optional*|The end time to read to|string (date-time)| |**numValues**
*optional*|The number of values to read|integer (int64)| |**startTime**
*optional*|The start time to read from|string (date-time)| ### ReadModifiedValuesDetailsModelHistoryReadRequestModel Request node history read |Name|Description|Schema| |---|---|---| |**browsePath**
*optional*|An optional path from NodeId instance to
the actual node.|< string > array| |**details**
*required*||[ReadModifiedValuesDetailsModel](definitions.md#readmodifiedvaluesdetailsmodel)| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**indexRange**
*optional*|Index range to read, e.g. 1:2,0:1 for 2 slices
out of a matrix or 0:1 for the first item in
an array, string or bytestring.
See 7.22 of part 4: NumericRange.|string| |**nodeId**
*optional*|Node to read from (mandatory without browse path)|string| |**timestampsToReturn**
*optional*||[TimestampsToReturn](definitions.md#timestampstoreturn)| ### ReadModifiedValuesDetailsModelHistoryReadRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[ReadModifiedValuesDetailsModelHistoryReadRequestModel](definitions.md#readmodifiedvaluesdetailsmodelhistoryreadrequestmodel)| ### ReadProcessedValuesDetailsModel Read processed historic data |Name|Description|Schema| |---|---|---| |**aggregateConfiguration**
*optional*||[AggregateConfigurationModel](definitions.md#aggregateconfigurationmodel)| |**aggregateType**
*optional*|The aggregate type to apply. Can be the name of
the aggregate if available in the history server
capabilities, or otherwise will be used as a node
id referring to the aggregate.|string| |**endTime**
*optional*|End time to read until|string (date-time)| |**processingInterval**
*optional*|Interval to process|string (date-span)| |**startTime**
*optional*|Start time to read from.|string (date-time)| ### ReadProcessedValuesDetailsModelHistoryReadRequestModel Request node history read |Name|Description|Schema| |---|---|---| |**browsePath**
*optional*|An optional path from NodeId instance to
the actual node.|< string > array| |**details**
*required*||[ReadProcessedValuesDetailsModel](definitions.md#readprocessedvaluesdetailsmodel)| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**indexRange**
*optional*|Index range to read, e.g. 1:2,0:1 for 2 slices
out of a matrix or 0:1 for the first item in
an array, string or bytestring.
See 7.22 of part 4: NumericRange.|string| |**nodeId**
*optional*|Node to read from (mandatory without browse path)|string| |**timestampsToReturn**
*optional*||[TimestampsToReturn](definitions.md#timestampstoreturn)| ### ReadProcessedValuesDetailsModelHistoryReadRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[ReadProcessedValuesDetailsModelHistoryReadRequestModel](definitions.md#readprocessedvaluesdetailsmodelhistoryreadrequestmodel)| ### ReadRequestModel Request node attribute read |Name|Description|Schema| |---|---|---| |**attributes**
*required*|Attributes to read|< [AttributeReadRequestModel](definitions.md#attributereadrequestmodel) > array| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| ### ReadRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[ReadRequestModel](definitions.md#readrequestmodel)| ### ReadResponseModel Result of attribute reads |Name|Description|Schema| |---|---|---| |**errorInfo**
*optional*||[ServiceResultModel](definitions.md#serviceresultmodel)| |**results**
*required*|All results of attribute reads|< [AttributeReadResponseModel](definitions.md#attributereadresponsemodel) > array| ### ReadValuesAtTimesDetailsModel Read data at specified times |Name|Description|Schema| |---|---|---| |**reqTimes**
*required*|Requested datums|< string (date-time) > array| |**useSimpleBounds**
*optional*|Whether to use simple bounds|boolean| ### ReadValuesAtTimesDetailsModelHistoryReadRequestModel Request node history read |Name|Description|Schema| |---|---|---| |**browsePath**
*optional*|An optional path from NodeId instance to
the actual node.|< string > array| |**details**
*required*||[ReadValuesAtTimesDetailsModel](definitions.md#readvaluesattimesdetailsmodel)| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**indexRange**
*optional*|Index range to read, e.g. 1:2,0:1 for 2 slices
out of a matrix or 0:1 for the first item in
an array, string or bytestring.
See 7.22 of part 4: NumericRange.|string| |**nodeId**
*optional*|Node to read from (mandatory without browse path)|string| |**timestampsToReturn**
*optional*||[TimestampsToReturn](definitions.md#timestampstoreturn)| ### ReadValuesAtTimesDetailsModelHistoryReadRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[ReadValuesAtTimesDetailsModelHistoryReadRequestModel](definitions.md#readvaluesattimesdetailsmodelhistoryreadrequestmodel)| ### ReadValuesDetailsModel Read historic values |Name|Description|Schema| |---|---|---| |**endTime**
*optional*|End of period to read. Set to null if no
specific end time is specified.|string (date-time)| |**numValues**
*optional*|The maximum number of values returned for any Node
over the time range. If only one time is specified,
the time range shall extend to return this number
of values. 0 or null indicates that there is no
maximum.|integer (int64)| |**returnBounds**
*optional*|Whether to return the bounding values or not.|boolean| |**startTime**
*optional*|Beginning of period to read. Set to null
if no specific start time is specified.|string (date-time)| ### ReadValuesDetailsModelHistoryReadRequestModel Request node history read |Name|Description|Schema| |---|---|---| |**browsePath**
*optional*|An optional path from NodeId instance to
the actual node.|< string > array| |**details**
*required*||[ReadValuesDetailsModel](definitions.md#readvaluesdetailsmodel)| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**indexRange**
*optional*|Index range to read, e.g. 1:2,0:1 for 2 slices
out of a matrix or 0:1 for the first item in
an array, string or bytestring.
See 7.22 of part 4: NumericRange.|string| |**nodeId**
*optional*|Node to read from (mandatory without browse path)|string| |**timestampsToReturn**
*optional*||[TimestampsToReturn](definitions.md#timestampstoreturn)| ### ReadValuesDetailsModelHistoryReadRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[ReadValuesDetailsModelHistoryReadRequestModel](definitions.md#readvaluesdetailsmodelhistoryreadrequestmodel)| ### RequestHeaderModel Request header model |Name|Description|Schema| |---|---|---| |**connectTimeout**
*optional*|Connect timeout in ms. As opposed to the service call
timeout this terminates the entire transaction if
it takes longer than the timeout to connect a session
A connect and reconnect during the service call
resets the timeout therefore the overall time for
the call to complete can be longer than specified.|integer (int32)| |**diagnostics**
*optional*||[DiagnosticsModel](definitions.md#diagnosticsmodel)| |**elevation**
*optional*||[CredentialModel](definitions.md#credentialmodel)| |**locales**
*optional*|Optional list of preferred locales in preference
order to be used during connecting the session.
We suggest to use the connection object to set
the locales|< string > array| |**namespaceFormat**
*optional*||[NamespaceFormat](definitions.md#namespaceformat)| |**operationTimeout**
*optional*|Operation timeout in ms. This applies to every
operation that is invoked, not to the entire
transaction and overrides the configured operation
timeout.|integer (int32)| |**serviceCallTimeout**
*optional*|Service call timeout in ms. As opposed to the
operation timeout this terminates the entire
transaction if it takes longer than the timeout to
complete. Note that a connect and reconnect during
the service call is gated by the connect timeout
setting. If a connect timeout is not specified
this timeout is used also for connect timeout.|integer (int32)| ### RequestHeaderModelPublishedNodesEntryRequestModel Wraps a request and a published nodes entry to bind to a body more easily for api that requires an entry and additional configuration |Name|Schema| |---|---| |**entry**
*required*|[PublishedNodesEntryModel](definitions.md#publishednodesentrymodel)| |**request**
*optional*|[RequestHeaderModel](definitions.md#requestheadermodel)| ### RequestHeaderModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[RequestHeaderModel](definitions.md#requestheadermodel)| ### RolePermissionModel Role permission model |Name|Description|Schema| |---|---|---| |**permissions**
*optional*||[RolePermissions](definitions.md#rolepermissions)| |**roleId**
*required*|Identifier of the role object.
**Minimum length** : `1`|string| ### RolePermissions Individual permissions assigned to a role *Type* : enum (None, Browse, ReadRolePermissions, WriteAttribute, WriteRolePermissions, WriteHistorizing, Read, Write, ReadHistory, InsertHistory, ModifyHistory, DeleteHistory, ReceiveEvents, Call, AddReference, RemoveReference, DeleteNode, AddNode) ### SecurityMode Specifies the security mode for OPC UA endpoint connections. Determines how messages are protected during transmission between the Publisher and OPC UA servers. Proper security mode selection is crucial for protecting sensitive data and credentials. *Type* : enum (Best, Sign, SignAndEncrypt, None, NotNone) ### ServerCapabilitiesModel Server capabilities |Name|Description|Schema| |---|---|---| |**MaxMonitoredItems**
*optional*|Supported aggregate functions|integer (int64)| |**MaxMonitoredItemsPerSubscription**
*optional*|Supported aggregate functions|integer (int64)| |**MaxMonitoredItemsQueueSize**
*optional*|Supported aggregate functions|integer (int64)| |**MaxSelectClauseParameters**
*optional*|Supported aggregate functions|integer (int64)| |**MaxSessions**
*optional*|Supported aggregate functions|integer (int64)| |**MaxSubscriptions**
*optional*|Supported aggregate functions|integer (int64)| |**MaxSubscriptionsPerSession**
*optional*|Supported aggregate functions|integer (int64)| |**MaxWhereClauseParameters**
*optional*|Supported aggregate functions|integer (int64)| |**aggregateFunctions**
*optional*|Supported aggregate functions|< string, string > map| |**conformanceUnits**
*optional*|Supported aggregate functions|< string > array| |**modellingRules**
*optional*|Supported modelling rules|< string, string > map| |**operationLimits**
*required*||[OperationLimitsModel](definitions.md#operationlimitsmodel)| |**serverProfileArray**
*optional*|Server profiles|< string > array| |**supportedLocales**
*optional*|Supported locales|< string > array| ### ServerEndpointQueryModel Endpoint model |Name|Description|Schema| |---|---|---| |**certificate**
*optional*|Endpoint must match with this certificate thumbprint|string| |**discoveryUrl**
*optional*|Discovery url to use to query|string| |**securityMode**
*optional*||[SecurityMode](definitions.md#securitymode)| |**securityPolicy**
*optional*|Endpoint must support this Security policy.|string| |**url**
*optional*|Endpoint url that should match the found endpoint|string| ### ServerRegistrationRequestModel Server registration request |Name|Description|Schema| |---|---|---| |**context**
*optional*||[OperationContextModel](definitions.md#operationcontextmodel)| |**discoveryUrl**
*required*|Discovery url to use for registration
**Minimum length** : `1`|string| |**id**
*optional*|User defined request id|string| ### ServiceResultModel Service result |Name|Description|Schema| |---|---|---| |**additionalInfo**
*optional*|Additional information if available|string| |**errorMessage**
*optional*|Error message in case of error or null.|string| |**inner**
*optional*||[ServiceResultModel](definitions.md#serviceresultmodel)| |**locale**
*optional*|Locale of the error message|string| |**namespaceUri**
*optional*|Namespace uri|string| |**statusCode**
*optional*|Error code - if null operation succeeded.|integer (int64)| |**symbolicId**
*optional*|Symbolic identifier|string| ### SetConfiguredEndpointsRequestModel Set configured endpoints request call |Name|Description|Schema| |---|---|---| |**endpoints**
*optional*|Endpoints and nodes that make up the configuration|< [PublishedNodesEntryModel](definitions.md#publishednodesentrymodel) > array| ### SimpleAttributeOperandModel Simple attribute operand model |Name|Description|Schema| |---|---|---| |**attributeId**
*optional*||[NodeAttribute](definitions.md#nodeattribute)| |**browsePath**
*optional*|Browse path of attribute operand|< string > array| |**dataSetClassFieldId**
*optional*|Optional data set class field id (Publisher extension)|string (uuid)| |**displayName**
*optional*|Optional display name|string| |**indexRange**
*optional*|Index range of attribute operand|string| |**typeDefinitionId**
*optional*|Type definition node id if operand is
simple or full attribute operand.|string| ### SubscriptionWatchdogBehavior Defines how the publisher responds when monitored items stop reporting data. The watchdog triggers when items are late according to OpcNodeWatchdogTimespan and OpcNodeWatchdogCondition settings. Can be configured globally via the --dwb command line option. *Type* : enum (Diagnostic, Reset, FailFast, ExitProcess) ### TestConnectionRequestModel Test connection request |Name|Schema| |---|---| |**header**
*optional*|[RequestHeaderModel](definitions.md#requestheadermodel)| ### TestConnectionRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[TestConnectionRequestModel](definitions.md#testconnectionrequestmodel)| ### TestConnectionResponseModel Test connection response |Name|Schema| |---|---| |**errorInfo**
*optional*|[ServiceResultModel](definitions.md#serviceresultmodel)| ### TimestampsToReturn Timestamps *Type* : enum (Both, Source, Server, None) ### TypeDefinitionModel Type definition |Name|Description|Schema| |---|---|---| |**browseName**
*optional*|Browse name|string| |**description**
*optional*|Description if any|string| |**displayName**
*optional*|Display name|string| |**nodeType**
*optional*||[NodeType](definitions.md#nodetype)| |**typeDefinitionId**
*required*|The node id of the type of the node
**Minimum length** : `1`|string| |**typeHierarchy**
*optional*|Super types hierarchy starting from base type
up to Azure.IIoT.OpcUa.Publisher.Models.TypeDefinitionModel.TypeDefinitionId which is
not included.|< [NodeModel](definitions.md#nodemodel) > array| |**typeMembers**
*optional*|Fully inherited instance declarations of the type
of the node.|< [InstanceDeclarationModel](definitions.md#instancedeclarationmodel) > array| ### UpdateEventsDetailsModel Insert, upsert or replace historic events |Name|Description|Schema| |---|---|---| |**events**
*required*|The new events to insert|< [HistoricEventModel](definitions.md#historiceventmodel) > array| |**filter**
*optional*||[EventFilterModel](definitions.md#eventfiltermodel)| ### UpdateEventsDetailsModelHistoryUpdateRequestModel Request node history update |Name|Description|Schema| |---|---|---| |**browsePath**
*optional*|An optional path from NodeId instance to
the actual node.|< string > array| |**details**
*required*||[UpdateEventsDetailsModel](definitions.md#updateeventsdetailsmodel)| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**nodeId**
*optional*|Node to update (mandatory without browse path)|string| ### UpdateEventsDetailsModelHistoryUpdateRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[UpdateEventsDetailsModelHistoryUpdateRequestModel](definitions.md#updateeventsdetailsmodelhistoryupdaterequestmodel)| ### UpdateValuesDetailsModel Insert, upsert, or update historic values |Name|Description|Schema| |---|---|---| |**values**
*required*|Values to insert|< [HistoricValueModel](definitions.md#historicvaluemodel) > array| ### UpdateValuesDetailsModelHistoryUpdateRequestModel Request node history update |Name|Description|Schema| |---|---|---| |**browsePath**
*optional*|An optional path from NodeId instance to
the actual node.|< string > array| |**details**
*required*||[UpdateValuesDetailsModel](definitions.md#updatevaluesdetailsmodel)| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**nodeId**
*optional*|Node to update (mandatory without browse path)|string| ### UpdateValuesDetailsModelHistoryUpdateRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[UpdateValuesDetailsModelHistoryUpdateRequestModel](definitions.md#updatevaluesdetailsmodelhistoryupdaterequestmodel)| ### UserIdentityModel User identity model |Name|Description|Schema| |---|---|---| |**password**
*optional*|For Azure.IIoT.OpcUa.Publisher.Models.CredentialType.UserName authentication
this is the password of the user.

For Azure.IIoT.OpcUa.Publisher.Models.CredentialType.X509Certificate authentication
this is the passcode to export the configured certificate's
private key.

Not used for the other authentication types.|string| |**thumbprint**
*optional*|For Azure.IIoT.OpcUa.Publisher.Models.CredentialType.X509Certificate authentication
this is the thumbprint of the configured certificate to use.
Either Azure.IIoT.OpcUa.Publisher.Models.UserIdentityModel.User or Azure.IIoT.OpcUa.Publisher.Models.UserIdentityModel.Thumbprint must be
used to select the certificate in the user certificate store.

Not used for the other authentication types.|string| |**user**
*optional*|For Azure.IIoT.OpcUa.Publisher.Models.CredentialType.UserName authentication
this is the name of the user.

For Azure.IIoT.OpcUa.Publisher.Models.CredentialType.X509Certificate authentication
this is the subject name of the certificate that has been
configured.
Either Azure.IIoT.OpcUa.Publisher.Models.UserIdentityModel.User or Azure.IIoT.OpcUa.Publisher.Models.UserIdentityModel.Thumbprint must be
used to select the certificate in the user certificate store.

Not used for the other authentication types.|string| ### ValueReadRequestModel Request node value read |Name|Description|Schema| |---|---|---| |**browsePath**
*optional*|An optional path from NodeId instance to
an actual node.|< string > array| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**indexRange**
*optional*|Index range to read, e.g. 1:2,0:1 for 2 slices
out of a matrix or 0:1 for the first item in
an array, string or bytestring.
See 7.22 of part 4: NumericRange.|string| |**maxAge**
*optional*|Maximum age of the value to be read in milliseconds.
The age of the value is based on the difference
between the ServerTimestamp and the time when
the Server starts processing the request.
If not supplied, the Server shall attempt to read
a new value from the data source.|string (date-span)| |**nodeId**
*optional*|Node to read from (mandatory)|string| |**timestampsToReturn**
*optional*||[TimestampsToReturn](definitions.md#timestampstoreturn)| ### ValueReadRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[ValueReadRequestModel](definitions.md#valuereadrequestmodel)| ### ValueReadResponseModel Value read response model |Name|Description|Schema| |---|---|---| |**dataType**
*optional*|Built in data type of the value read.|string| |**errorInfo**
*optional*||[ServiceResultModel](definitions.md#serviceresultmodel)| |**serverPicoseconds**
*optional*|Pico seconds part of when value was read at server.|integer (int32)| |**serverTimestamp**
*optional*|Timestamp of when value was read at server.|string (date-time)| |**sourcePicoseconds**
*optional*|Pico seconds part of when value was read at source.|integer (int32)| |**sourceTimestamp**
*optional*|Timestamp of when value was read at source.|string (date-time)| |**value**
*optional*|Value read|object| ### ValueWriteRequestModel Value write request model |Name|Description|Schema| |---|---|---| |**browsePath**
*optional*|An optional path from NodeId instance to
the actual node.|< string > array| |**dataType**
*optional*|A built in datatype for the value. This can
be a data type from browse, or a built in
type.
(default: best effort)|string| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**indexRange**
*optional*|Index range to write|string| |**nodeId**
*optional*|Node id to write value to.|string| |**value**
*required*|Value to write. The system tries to convert
the value according to the data type value,
e.g. convert comma seperated value strings
into arrays. (Mandatory)|object| ### ValueWriteRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[ValueWriteRequestModel](definitions.md#valuewriterequestmodel)| ### ValueWriteResponseModel Value write response model |Name|Schema| |---|---| |**errorInfo**
*optional*|[ServiceResultModel](definitions.md#serviceresultmodel)| ### VariableMetadataModel Variable metadata model |Name|Description|Schema| |---|---|---| |**arrayDimensions**
*optional*|Array dimensions of the variable.|integer (int64)| |**dataType**
*optional*||[DataTypeMetadataModel](definitions.md#datatypemetadatamodel)| |**valueRank**
*optional*||[NodeValueRank](definitions.md#nodevaluerank)| ### VariantValueHistoryReadNextResponseModel History read continuation result |Name|Description|Schema| |---|---|---| |**continuationToken**
*optional*|Continuation token if more results pending.|string| |**errorInfo**
*optional*||[ServiceResultModel](definitions.md#serviceresultmodel)| |**history**
*required*|History as json encoded extension object|object| ### VariantValueHistoryReadRequestModel Request node history read |Name|Description|Schema| |---|---|---| |**browsePath**
*optional*|An optional path from NodeId instance to
the actual node.|< string > array| |**details**
*required*|The HistoryReadDetailsType extension object
encoded in json and containing the tunneled
Historian reader request.|object| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**indexRange**
*optional*|Index range to read, e.g. 1:2,0:1 for 2 slices
out of a matrix or 0:1 for the first item in
an array, string or bytestring.
See 7.22 of part 4: NumericRange.|string| |**nodeId**
*optional*|Node to read from (mandatory without browse path)|string| |**timestampsToReturn**
*optional*||[TimestampsToReturn](definitions.md#timestampstoreturn)| ### VariantValueHistoryReadRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[VariantValueHistoryReadRequestModel](definitions.md#variantvaluehistoryreadrequestmodel)| ### VariantValueHistoryReadResponseModel History read results |Name|Description|Schema| |---|---|---| |**continuationToken**
*optional*|Continuation token if more results pending.|string| |**errorInfo**
*optional*||[ServiceResultModel](definitions.md#serviceresultmodel)| |**history**
*required*|History as json encoded extension object|object| ### VariantValueHistoryUpdateRequestModel Request node history update |Name|Description|Schema| |---|---|---| |**browsePath**
*optional*|An optional path from NodeId instance to
the actual node.|< string > array| |**details**
*required*|The HistoryUpdateDetailsType extension object
encoded as json Variant and containing the tunneled
update request for the Historian server. The value
is updated at edge using above node address.|object| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**nodeId**
*optional*|Node to update (mandatory without browse path)|string| ### VariantValueHistoryUpdateRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[VariantValueHistoryUpdateRequestModel](definitions.md#variantvaluehistoryupdaterequestmodel)| ### VariantValuePublishedNodeCreateAssetRequestModel Request to create an asset in the configuration api |Name|Description|Schema| |---|---|---| |**configuration**
*required*|The asset configuration to use when creating the asset.|object| |**entry**
*required*||[PublishedNodesEntryModel](definitions.md#publishednodesentrymodel)| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| |**waitTime**
*optional*|Time to wait after the configuration is applied to perform
the configuration of the asset in the configuration api.
This is to let the server settle.|string (date-span)| ### WriteRequestModel Request node attribute write |Name|Description|Schema| |---|---|---| |**attributes**
*required*|Attributes to update|< [AttributeWriteRequestModel](definitions.md#attributewriterequestmodel) > array| |**header**
*optional*||[RequestHeaderModel](definitions.md#requestheadermodel)| ### WriteRequestModelRequestEnvelope Wraps a request and a connection to bind to a body more easily for api that requires a connection endpoint |Name|Schema| |---|---| |**connection**
*required*|[ConnectionModel](definitions.md#connectionmodel)| |**request**
*optional*|[WriteRequestModel](definitions.md#writerequestmodel)| ### WriteResponseModel Result of attribute write |Name|Description|Schema| |---|---|---| |**errorInfo**
*optional*||[ServiceResultModel](definitions.md#serviceresultmodel)| |**results**
*required*|All results of attribute writes|< [AttributeWriteResponseModel](definitions.md#attributewriteresponsemodel) > array| ### WriterGroupTransport Specifies the transport technology used to publish messages from OPC Publisher. Each transport offers different capabilities for message delivery, routing, and quality of service. The transport choice affects how messages are delivered and what features are available. *Type* : enum (IoTHub, Mqtt, EventHub, Dapr, Http, FileSystem, AioMqtt, AioDss, Null) ### X509CertificateChainModel Certificate chain |Name|Description|Schema| |---|---|---| |**chain**
*optional*|Chain|< [X509CertificateModel](definitions.md#x509certificatemodel) > array| |**status**
*optional*|Chain validation status if validated|enum (NotTimeValid, Revoked, NotSignatureValid, NotValidForUsage, UntrustedRoot, RevocationStatusUnknown, Cyclic, InvalidExtension, InvalidPolicyConstraints, InvalidBasicConstraints, InvalidNameConstraints, HasNotSupportedNameConstraint, HasNotDefinedNameConstraint, HasNotPermittedNameConstraint, HasExcludedNameConstraint, PartialChain, CtlNotTimeValid, CtlNotSignatureValid, CtlNotValidForUsage, HasWeakSignature, OfflineRevocation, NoIssuanceChainPolicy, ExplicitDistrust, HasNotSupportedCriticalExtension)| ### X509CertificateModel Certificate model |Name|Description|Schema| |---|---|---| |**hasPrivateKey**
*optional*|Contains private key|boolean| |**notAfterUtc**
*optional*|Not after validity|string (date-time)| |**notBeforeUtc**
*optional*|Not before validity|string (date-time)| |**pfx**
*optional*|Certificate as Pkcs12|< integer (int32) > array| |**selfSigned**
*optional*|Self signed certificate|boolean| |**serialNumber**
*optional*|Serial number|string| |**subject**
*optional*|Subject|string| |**thumbprint**
*optional*|Thumbprint|string| ### X509ChainStatus Status of x509 chain *Type* : enum (NotTimeValid, Revoked, NotSignatureValid, NotValidForUsage, UntrustedRoot, RevocationStatusUnknown, Cyclic, InvalidExtension, InvalidPolicyConstraints, InvalidBasicConstraints, InvalidNameConstraints, HasNotSupportedNameConstraint, HasNotDefinedNameConstraint, HasNotPermittedNameConstraint, HasExcludedNameConstraint, PartialChain, CtlNotTimeValid, CtlNotSignatureValid, CtlNotValidForUsage, HasWeakSignature, OfflineRevocation, NoIssuanceChainPolicy, ExplicitDistrust, HasNotSupportedCriticalExtension) ================================================ FILE: docs/opc-publisher/deployment.json ================================================ { "modulesContent": { "$edgeAgent": { "properties.desired": { "schemaVersion": "1.1", "runtime": { "type": "docker", "settings": { "minDockerVersion": "v1.25", "loggingOptions": "", "registryCredentials": {} } }, "systemModules": { "edgeAgent": { "type": "docker", "settings": { "image": "mcr.microsoft.com/azureiotedge-agent:1.4", "createOptions": "" } }, "edgeHub": { "type": "docker", "status": "running", "restartPolicy": "always", "settings": { "image": "mcr.microsoft.com/azureiotedge-hub:1.4", "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"5671/tcp\":[{\"HostPort\":\"5671\"}], \"8883/tcp\":[{\"HostPort\":\"8883\"}],\"443/tcp\":[{\"HostPort\":\"443\"}]}}}" }, "env": { "SslProtocols": { "value": "tls1.2" } } } }, "modules": { "publisher": { "version": "1.0", "type": "docker", "status": "running", "restartPolicy": "always", "settings": { "image": "iotedge/opc-publisher:debug", "createOptions": "{\"User\":\"root\",\"HostConfig\":{\"PortBindings\":{\"80/tcp\":[{\"HostPort\":\"8080\"}],\"443/tcp\":[{\"HostPort\":\"8081\"}]},\"CapDrop\":[\"CHOWN\",\"SETUID\"]}}" } } } } }, "$edgeHub": { "properties.desired": { "schemaVersion": "1.0", "routes": { "publisherToUpstream": "FROM /messages/modules/publisher/* INTO $upstream", "leafToUpstream": "FROM /messages/* WHERE NOT IS_DEFINED($connectionModuleId) INTO $upstream" }, "storeAndForwardConfiguration": { "timeToLiveSecs": 7200 } } } } } ================================================ FILE: docs/opc-publisher/directmethods.md ================================================ # Configuration API [Home](./readme.md) For large-scale deployments, automating the configuration and management of OPC Publisher is critical. OPC Publisher version 2.8.2 and later implements [IoT Hub Direct Methods](https://docs.microsoft.com/azure/iot-hub/iot-hub-devguide-direct-methods), which can be called from an application using the [IoT Hub Device SDK](https://docs.microsoft.com/azure/iot-hub/iot-hub-devguide-sdks). Azure IoT Hub's Cloud-to-Device (C2D) commands allow you to remotely configure and control OPC Publisher instances running on IoT Edge devices. For example, you can send commands to update the configuration, restart the module, or change runtime parameters without needing to manually intervene on each device. An example of sending a C2D command to update the configuration: ```bash az iot hub invoke-module-method --hub-name --device-id --module-name --method-name SetConfiguredEndpoints --method-payload '{"Endpoints": [{"EndpointUrl": "opc.tcp://new-opc-server:4840", "OpcNodes": [{"Id": "ns=2;i=10853"}]}]}' ``` The following direct methods and many more can be used to remotely configure the OPC Publisher: - [Shutdown\_V2](#shutdown_v2) - [GetServerCertificate\_V2](#getservercertificate_v2) - [GetApiKey\_V2](#getapikey_v2) - [PublishNodes\_V1](#publishnodes_v1) - [AddOrUpdateEndpoints\_V1](#addorupdateendpoints_v1) - [UnpublishNodes\_V1](#unpublishnodes_v1) - [UnpublishAllNodes\_V1](#unpublishallnodes_v1) - [GetConfiguredEndpoints\_V1](#getconfiguredendpoints_v1) - [SetConfiguredEndpoints\_V1](#setconfiguredendpoints_v1) - [GetConfiguredNodesOnEndpoint\_V1](#getconfigurednodesonendpoint_v1) - [GetDiagnosticInfo\_V1](#getdiagnosticinfo_v1) The corresponding REST API of OPC Publisher 2.9 (with same operation names and [type definitions](./definitions.md)) is documented [here](./api.md). In addition to calling the API through HTTP REST calls (Preview) you can call the configuration API through MQTT v5 (Preview) in OPC Publisher 2.9. If you need to migrate your application from OPC Publisher 2.5.x to OPC Publisher 2.8.2 or later, we provide the needed information in a [separate document](./migrationpath.md). It is important to understand the [configuration schema](./readme.md#configuration-schema) as it is the foundation of the OPC Publisher configuration surface and represented by the [PublishedNodesEntryModel](./definitions.md#publishednodesentrymodel). Now let's dive into each direct method request and response payloads with examples. ## Shutdown_V2 This API call allows you to shutdown the publisher. By passing a `true`, the publisher is immediately terminates the process with an error and reports an error message. When passing `false`, the exits the process without a 0 exit code. _Request_: `true` or `false` or nothing. _Response_: Potentially nothing if the publisher is immediately shutdown _Example_: > _Method Name_: `Shutdown_V2` > > _Request_: > > ```json > true > ``` > > _Response_: > > ```json > n/a > ``` ## GetServerCertificate_V2 This API can be called to retrieve the HTTP certificate that secures the REST endpoint. A caller should call this API and then validate the server certificate presented against this certificate. The certificate can be cached for the duration of its validity period. _Request_: An empty object or `null` can be passed since no argument is required. _Response_: when successful Status 200 and the certificate in PEM format. _Exceptions_: an exception is thrown when method call returns status other than 200 _Example_: > _Method Name_: `GetServerCertificate_V2` > > _Request_: > > ```json > null > ``` > > _Response_: > > ```json > "-----BEGIN CERTIFICATE-----\n ``` The certificate Key can also be read from the IoT Hub device twin as `__certificate__` reported property, together with the ip address, hostname, schema, and port (`__ip__`, `__hostname__`, `__scheme__`, and `__port__`). ## GetApiKey_V2 This API call allows a caller to programmatically obtain the current API key. The API key is passed in the `Authorization` header of the HTTP request sent to the HTTP endpoint. The format of the header value is `ApiKey `, e.g., `ApiKey 85.........F78`. _Request_: follows strictly the request [payload schema](./definitions.md#publishednodesentrymodel), the `OpcNodes` attribute being mandatory. _Response_: when successful Status 200 and an empty json (`{}`) as payload _Exceptions_: an exception is thrown when method call returns status other than 200 _Example_: > _Method Name_: `GetApiKey_V2` > > _Request_: > > ```json > null > ``` > > _Response_: > > ```json > "85.........F78" > ``` The API Key can also be read from the IoT Hub device twin as the `__apikey__` reported property. ## PublishNodes_V1 PublishNodes enables a client to add a set of nodes to be published. A [`DataSetWriter`](./readme.md#configuration-schema) groups nodes which results in seperate subscriptions being created (grouped further by the Publishing interval, if different ones are configured, but these have no bearing on the `DataSetWriter` identity). A `DataSetWriter`s identity is the combination of `DataSetWriterId`, `DataSetName`, `DataSetKeyFrameCount`, `DataSetClassId`, and connection relevant information such as credentials, security mode, and endpoint Url. To update a `DataSetWriter` this information must match exactly. When a `DataSetWriter` already exists, the nodes are incrementally added to the same [`dataset`](./readme.md#configuration-schema). When it doesn't already exist, a new `DataSetWriter` is created with the initial set of nodes contained in the request. When working with `DataSetWriterGroup`s it is important to note that all groups not part of the publish request are removed. To incrementally update `DataSetWriterGroup`s of `DataSetWriter`s use [`AddOrUpdateEndpoints_v1`](#addorupdateendpoints_v1) API instead. _Request_: follows strictly the request [payload schema](./definitions.md#publishednodesentrymodel), the `OpcNodes` attribute being mandatory. _Response_: when successful Status 200 and an empty json (`{}`) as payload _Exceptions_: an exception is thrown when method call returns status other than 200 _Example_: > _Method Name_: `PublishNodes_V1` > > _Request_: > > ```json > { > "EndpointUrl": "opc.tcp://opcplc:50000", > "DataSetWriterGroup": "Asset0", > "DataSetWriterId": "DataFlow0", > "DataSetPublishingInterval": 5000, > "OpcNodes": [ > { > "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt0" > } > ] > } > ``` > > _Response_: > > ```json > { > "status": 200, > "payload": {} > } > ``` More information can be found in the [API documentation](./api.md#publishnodes) ## AddOrUpdateEndpoints_V1 This method allows updating multiple endpoints (`DataSetWriter`s) without effecting others. Unlike `PublishNodes_V1` method, `AddOrUpdateEndpoints_V1` replaces the nodes of an endpoint (`DataSetWriter`) with the one provided in the method's request payload. By providing an empty list of nodes in a request, a endpoint (`DataSetWriter`) can be removed from a `DataSetWriterGroup`. Removing the last from a group removes the group. _Request_: represents a list of objects, which should strictly follow the request payload schema as described above. The `OpcNodes` attribute being empty list or `null` will be interpreted as a removal request for that endpoint (`DataSetWriter`). _Response_: when successful - Status 200 and an empty json (`{}`) as payload _Exceptions_: a response corresponding to an exception will be returned if: - request payload contains deletion request for an endpoint (`DataSetWriter`) that isn't present in publisher configuration - request payload contains two or more entries for the same endpoint (`DataSetWriter`) _Example_: > _Method Name_: `AddOrUpdateEndpoints_V1` > > _Payload_: > > ```json > [ > { > "EndpointUrl": "opc.tcp://opcplc:50000", > "DataSetWriterGroup": "Asset1", > "DataSetWriterId": "DataFlow1", > "DataSetPublishingInterval": 5000, > "OpcNodes": [ > { > "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt0", > } > ] > }, > { > "EndpointUrl": "opc.tcp://opcplc:50001", > "DataSetWriterGroup": "Asset2", > "DataSetWriterId": "DataFlow2", > "OpcNodes": [] > } > ] > ``` > > _Response_: > > ```json > { > "status": 200, > "payload": {} > } > ``` More information can be found in the [API documentation](./api.md#addorupdateendpoints) ## UnpublishNodes_V1 UnpublishNodes method enables a client to remove nodes from a previously configured `DataSetWriter`. A `DataSetWriter`s identity is the combination of `DataSetWriterId`, `DataSetName`, `DataSetKeyFrameCount`, `DataSetClassId` and connection relevant information such as credentials, security mode, and endpoint Url. To update a `DataSetWriter` this information must match exactly. If value of the `OpcNodes` attribute is `null` or an empty list, then the whole DataSetWriter entity is removed. _Note_: If all the nodes from a DataSet are to be unpublished, the DataSetWriter entity is removed from the configuration storage. _Request_: follows strictly the request payload schema, the `OpcNodes` attribute not being mandatory. _Response_: when successful - Status 200 and an empty json (`{}`) as Payload _Exceptions_: a response corresponding to an exception will be returned if: - request payload contains an endpoint (DataSet) that isn't present in publisher configuration - request payload contains a node that isn't present in publisher configuration _Example_: > _Method Name_: `UnpublishNodes_V1` > > _Request_: > > ```json > { > "EndpointUrl": "opc.tcp://opcplc:50000", > "DataSetWriterGroup": "Asset0", > "DataSetWriterId": "DataFlow0", > "DataSetPublishingInterval": 5000, > "OpcNodes": [ > { > "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt0" > } > ] > } > ``` > > _Response_: > > ```json > { > "status": 200, > "payload": {} > } > ``` More information can be found in the [API documentation](./api.md#unpublishnodes) ## UnpublishAllNodes_V1 UnpublishAllNodes method enables a client to remove all the nodes from a previously configured DataSetWriter. The DataSetWriter entity will be removed from the configuration storage. When an empty payload is set or the endpoint in payload is null, the complete configuration of the publisher will be purged. _Request_: follows strictly the request payload schema, the `OpcNodes` attribute should be excluded. _Response_: when successful - Status 200 and an empty json (`{}`) as Payload _Exceptions_: a response corresponding to an exception will be returned if: - request payload contains an endpoint (DataSet) that isn't present in publisher configuration - request payload contains `OpcNodes` _Example_: > _Method Name_: `UnpublishAllNodes_V1` > > _Payload_: > > ```json > { > "EndpointUrl": "opc.tcp://opcplc:50000", > "DataSetWriterGroup": "Asset1", > "DataSetWriterId": "DataFlow1", > "DataSetPublishingInterval": 5000 > } > ``` > > _Response_: > > ```json > { > "status": 200, > "payload": {} > } > ``` More information can be found in the [API documentation](./api.md#unpublishallnodes) ## GetConfiguredEndpoints_V1 Returns the configured endpoints (`DataSetWriter`s) _Request_: empty json (`{}`) _Response_: the list of configured endpoints (and optional parameters). _Exceptions_: an exception is thrown when method call returns status other than 200 _Example_: > _Method Name_: `GetConfiguredEndpoints_V1` > > _Response_: > > ```json > { > "status": 200, > "payload": { > "endpoints": [ > { > "endpointUrl": "opc.tcp://opcplc:50000", > "dataSetWriterGroup": "Asset1", > "dataSetWriterId": "DataFlow1", > "dataSetPublishingInterval": 5000, > }, > { > "endpointUrl": "opc.tcp://opcplc:50001" > } > ] > } > } > ``` More information can be found in the [API documentation](./api.md#getconfiguredendpoints) ## SetConfiguredEndpoints_V1 Sets the configured endpoints (`DataSetWriter`s) and thus allows to update all configuration at once. The configuration on the OPC Publisher is replaced with the request payload content. Use empty array of endpoints to clear the entire content of the published nodes file. _Request_: A list of configured endpoints (and optional parameters). _Response_: empty json (`{}`) _Exceptions_: an exception is thrown when method call returns status other than 200 _Example_: > _Method Name_: `SetConfiguredEndpoints_V1` > > _Payload_: > > ```json > { > "endpoints": [ > { > "endpointUrl": "opc.tcp://opcplc:50000", > "dataSetWriterGroup": "Asset1", > "dataSetWriterId": "DataFlow1", > "dataSetPublishingInterval": 5000, > }, > { > "endpointUrl": "opc.tcp://opcplc:50001" > } > ] > } > ``` > > _Response_: > > ```json > { > "status": 200, > "payload": {} > } > ``` More information can be found in the [API documentation](./api.md#setconfiguredendpoints) ## GetConfiguredNodesOnEndpoint_V1 Returns the nodes configured for one Endpoint (`DataSetWriter`s). _Request_: contains the elements defining the Dataset. Please note that the Dataset definition should fully match the one that is present in OPC Publisher configuration. _Response_: list of `OpcNodes` configured for the selected Endpoint (and optional parameters). _Exceptions_: an exception is thrown when method call returns status other than 200 _Example_: > _Method Name_: `GetConfiguredNodesOnEndpoints_V1` > > _Payload_: > > ```json > { > "EndpointUrl": "opc.tcp://192.168.100.20:50000", > "DataSetWriterGroup": "Asset0", > "DataSetWriterId": "DataFlow0", > "DataSetPublishingInterval": 5000 > } > ``` > > _Response_: > > ```json > { > "status": 200, > "payload": { > "opcNodes": [ > { > "id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=SlowUInt1", > "opcSamplingIntervalTimespan": "00:00:10", > "heartbeatIntervalTimespan": "00:00:50" > } > ] > } > } > ``` More information can be found in the [API documentation](./api.md#getconfigurednodesonendpoint) ## GetDiagnosticInfo_V1 Returns a list of actual metrics for all concrete `DataSetWriter`s. This includes virtual `DataSetWriter`s created due to different publishing intervals configured. The name of these contain the original name provided and a hash value. _Request_: empty json (`{}`) _Response_: list of actual metrics for every endpoint (Dataset). _Exceptions_: an exception is thrown when method call returns status other than 200 _Note_: passwords aren't being part of the response. _Example_: > _Method Name_: `GetDiagnosticInfo_V1` > > _Response_: > > ```json > { > "status":200, > "payload":[ > { > "endpoint": { > "endpointUrl": "opc.tcp://opcplc:50000", > "dataSetWriterGroup": "Asset1", > "useSecurity": false, > "opcAuthenticationMode": "UsernamePassword", > "opcAuthenticationUsername": "Usr" > }, > "sentMessagesPerSec": 2.6, > "ingestionDuration": "{00:00:25.5491702}", > "ingressDataChanges": 25, > "ingressValueChanges": 103, > "ingressBatchBlockBufferSize": 0, > "encodingBlockInputSize": 0, > "encodingBlockOutputSize": 0, > "encoderNotificationsProcessed": 83, > "encoderNotificationsDropped": 0, > "encoderIoTMessagesProcessed": 2, > "encoderAvgNotificationsMessage": 41.5, > "encoderAvgIoTMessageBodySize": 6128, > "encoderAvgIoTChunkUsage": 1.158034, > "estimatedIoTChunksPerDay": 13526.858105160689, > "outgressBatchBlockBufferSize": 0, > "outgressInputBufferCount": 0, > "outgressInputBufferDropped": 0, > "outgressIoTMessageCount": 0, > "connectionRetries": 0, > "opcEndpointConnected": true, > "monitoredOpcNodesSucceededCount": 5, > "monitoredOpcNodesFailedCount": 0, > "ingressEventNotifications": 0, > "ingressEvents": 0 > } > ] > } > ``` More information can be found in the [API documentation](./api.md#getdiagnosticinfocinfo) ================================================ FILE: docs/opc-publisher/features.md ================================================ # Features [Home](./readme.md) The following table shows the supported features of OPC Publisher and planned feature additions. Preview features are supported through GitHub issues only, experimental features will become preview or fully supported features if you request so through GitHub issues or by contacting us. If you would like to see additional features added, please open a feature request. | Feature | Sub Feature | 2.8 | 2.9 | Feature state | | ------- | ----------- |---- | --- | ------------- | | Uses latest .net reference stack ||X|X|| | .net Version || .net 6 | .net 9 || | Secure channel transport and configuration ||X|X|| | OPC UA HTTP transport and configuration ||-|-|#1997| | Secure channel over web socket transport and configuration ||-|-|#1997| | Secure channel certificate management [API](./api.md#certificates) ||||| | | Client Cert |-|X|| | | Using EST |-|-|| | | GDS Pull from GDS server |-|-|#2081| | | GDS Server Push to OPC Publisher |-|-|| | Session-reconnect handling across connection loss ||X|X|| | | Using official .net stack implementation |-|X|| | [Reverse Connect](./readme.md#using-opc-ua-reverse-connect) ||-|X|Preview| | User authentication ||||| | | Username / Password authentication |X|X|| | | X509 based user authentication ||X|| | | Token based user authentication |-|-|| | Get Endpoint and Server information [API](./api.md#getservercapabilities) ||-|X|Preview| | Connect and Disconnect [API](./api.md) ||-|X|Preview| | Test connection [API](./api.md#testconnection) ||-|X|Preview| | Browse [API](./api.md#browse) ||-|X|| | | Browse first/next |-|X|| | | RegEx Browse filter |-|-|| | | Streaming browse "Fast browsing" / Partial node set export |-|X|Preview| | | Publish model change feed change events |-|X|Experimental| | Translate browse path [API](./api.md) ||-|X|| | Read [API](./api.md#valueread) ||||| | | Read Value |-|X|| | | Read other attributes of nodes |-|X|| | | Get instance metadata |-|X|| | Write [API](./api.md#valuewrite)||||| | | Write Value |-|X|| | | Write other attributes of nodes |-|X|| | Method Call [API](./api.md#methodcall) ||-|X|| | HDA [API](./api.md#history) for processed, modified, at-times, events time series data ||||| | | Read |-|X|Preview| | | Streaming read |-|X|Experimental| | | Update |-|X|Preview| | | Upsert |-|X|Preview| | | Delete |-|X|Preview| | File Transfer [API](./api.md#filesystem) ([Part 20](https://reference.opcfoundation.org/Core/Part20/v105/docs/)) ||||| | | List file systems |-|X|Experimental| | | Browse file systems on server |-|X|Experimental| | | Create files and directories |-|X|Experimental| | | Download files |-|X|Experimental| | | Upload files to directory |-|X|Experimental| | | Delete files and directories |-|X|Experimental| | | Substitutable Close method |-|X|Experimental| | | Temporary file transfer |-|-|| | Subscribe to [value changes](./readme.md#configuration-schema) ||||| | | Value change subscriptions |X|X|| | | Data change filter support |-|X|| | | Using browse path to node |-|X|| | | Deadband |-|X|| | | Status trigger |-|X|| | | Set server queue size per value|-|X|| | | Set server queue LIFO/FIFO behavior per value|-|X|| | | Set queue size using publishing interval and sampling interval |-|X|Preview| | | Periodic read ([cyclic read](./readme.md#sampling-and-publishing-interval-configuration))|-|X|Preview| | | Heartbeat (Periodic resending of last known value) |X|X|| | | Configurable heartbeat behavior (LKG, LKV) ||X|| | | Heartbeat message timestamp source configuration ||X|| | Subscribe to [events](./readme.md#configuring-event-subscriptions) ||||| | | Using browse path to event notifier |-|X|| | | Simple (get all events of a type from event notifier)|-|X|| | | Event filter (filter events on server before sending)|-|X|| | | Condition handling / Condition snapshots|-|X|Preview| | Subscribe to nodes that are not variables or event notifiers ||||| | | All variables under and object |-|X|Preview| | | All Objects and variables of an object type |-|X|Preview| | | All Variables of a variable type |-|X|Preview| | Triggering ||||| | | Using Server side triggering service (SetTriggering) |-|-|| | | Client side sampling of values on event |-|-|| | Re-evaluate subscriptions ||||| | | Periodically |-|X|| | | While monitored items failed to be applied |-|X|| | | On data model change events |-|-|#1209| | Subscription watchdog ||||| | | When all monitored items are not reporting within an interval |-|X|| | | When a monitored item is not reporting within an interval |-|X|| | | When subscription is deleted on server |-|X|| | | Configure whether to reset or terminate |-|X|| | Registered Nodes ||||| | | For periodic reads (registered read) |-|X|Preview| | | For monitored items |-|X|Preview| | | Register API call |-|-|| | | Unregister API call |-|-|| | Client-side transport queue configuration ||||| | | Batch size and publishing interval publisher wide |X|X|| | | Batch size and publishing interval per group |-|X|| | | Load shedding |X|X|| | | Queue jumping / Priority messages|-|-|| | | Advanced overflow handling strategies|-|-|| | IIoT Platform 2.8 Orchestrated mode support ||X|-|| | 0 message loss||-|-|| | Transfer subscription||||| | | On reconnect |-|X|| | | On startup |-|-|| | Re-activate session on startup (Transfer session)||||| | Deferred Notification Acknowledgement||-|X|Experimental| | Back pressure to server||-|-|| | Published nodes JSON [schema](./readme.md#configuration-schema) support ||||| | | v2.5 |X|X|| | | v2.8 |X|X|| | | v2.9 |-|X|| | | JSON schema validation |X|-|| | | Bootstrapped from Azure Storage blob |-|-|#2284| | API to configure and subscribe to Objects, Types and Assets ||||| | | All variables under an object as writers |-|X|Experimental| | | All variables of objects of a certain object type or subtype |-|X|Experimental| | | All variables of a variable type or subtype |-|X|Experimental| | | Asset configuration using Web of Things Description per [Part 10100-1](https://reference.opcfoundation.org/WoT/v100/docs/)|-|X|Experimental| | | Asset admin shell support per [Part 30270](https://reference.opcfoundation.org/I4AAS/v100/docs/)|-|-|| | OPC UA Pub/Sub configuration API ([Part 14](https://reference.opcfoundation.org/Core/Part14/v105/docs/))||-|-|| | Data contextualization ||||| | | Add Endpoint/Dataset name to message header (Routing) |X|X|| | | [Enrichment](./readme.md#key-frames-delta-frames-and-extension-fields) |-|X|| | | Transformation |-|-|| | | Normalization |-|-|| | Running as docker outside IoT Edge or K8s ||-|X|Experimental| | [IoT Edge](./readme.md#install-iot-edge) deployment support ||X|X|| | | Fully functional in nested (ISA95) setup |-|X|| | | IoT Hub direct method-based configuration|X|X|| | | IoT Hub direct method-based API calls|-|X|| | | DTDL interface for API |-|-|| | [MQTT](./transports.md#mqtt) request response-based API and configuration ||||| | | v5 request response |-|X|Preview| | | v3.11 using IoT Hub like &rid= correlation |-|X|Experimental| | [HTTP](./transports.md#built-in-http-api-server) REST command/control and configuration API ||-|X|Preview| | Kafka request response-based API and configuration ||-|-|| | Configuration via OPC UA endpoint ||-|-|| | Prometheus [Metrics](./observability.md) ||||| | | For module metrics |X|X|| | | Endpoint metrics |X|X|| | | Process data |-|-|Backlog| | Periodic diagnostic output ||||| | | To Console |X|X|| | | To Diagnostics Topic/Output |-|X|| | | As OPC UA PubSub Message |-|-|Backlog| | Health and liveness probe / watchdog ||-|-|Backlog| | Message and event publishing [transports](./transports.md) ||||| | | IoT Hub |X|X|| | | MQTT topics |-|X|Preview| | | Publishing to [Azure EventHub](./transports.md#azure-eventhub) |-|X|Preview| | | Dapr Pub/Sub (Kafka, Redis, etc.) |-|X|Experimental| | | Publishing to a Web hook|-|X|Experimental| | | Dump messages and schemas to zip files in file system |-|X|Experimental| | | Null sink|-|X|Experimental| | Multiple cloud transports enabled in parallel ||-|X|Preview| | Select desired transport per writer group ||-|X|Preview| | Cloud Events support ||-|-|via Dapr| | OPC UA Pub Sub [message content profiles](./messageformats.md) ||||| | | (Full and simple) data set messages |X|X|| | | (Full and simple) Network messages |X|X|| | | Raw message format |-|X|| | | Single data set format |-|X|| | | Custom configuration using content flags |-|-|| | | Configurable per writer group |-|X|| | OPC UA Pub Sub message [encoding](./messageformats.md) ||||| | | JSON Encoding |X|X|| | | [Non-Reversible](https://reference.opcfoundation.org/Core/Part6/v105/docs/) |-|X|| | | [Reversible](https://reference.opcfoundation.org/Core/Part6/v105/docs/) |-|X|| | | [Compact](https://reference.opcfoundation.org/Core/Part6/v105/docs/) |-|-|| | | [Verbose](https://reference.opcfoundation.org/Core/Part6/v105/docs/) |-|-|| | | GZIP JSON Encoding |-|X|| | | JSON Schema publishing for JSON encoding |-|X|Experimental| | | UADP Binary encoding per [Part 14](https://reference.opcfoundation.org/Core/Part14/v105/docs/)|-|X|Preview| | | Avro and Avro+Gzip encoding with Schema publishing |-|X|Experimental| | | [Samples JSON encoding](./messageformats.md#samples-mode-encoding-legacy) – Legacy |X|X|Deprecated| | | Samples Binary encoding – Legacy |X|-|| | | Configurable per writer group |-|X|| | OPC UA [Part 14](https://reference.opcfoundation.org/Core/Part14/v105/docs/) Pub Sub Message types ||||| | | [Delta frame messages](./messageformats.md#data-value-change-messages) |-|X|| | | [Key frame messages](./readme.md#key-frames-delta-frames-and-extension-fields) / Key frame count |-|X|| | | [Event messages](./messageformats.md#event-messages) |-|X|| | | Keep alive messages |-|X|| | | Data Set Metadata messages (on change and periodic) |-|X|| | | Discovery messages |-|-|| | | Publisher status messages |-|-|| | Unified Namespace ||||| | | Topic templates at writer group and dataset writer level |-|X|Preview| | | Automatic topic routing using OPC UA browse paths |-|X|Experimental| ================================================ FILE: docs/opc-publisher/intfilesamples.md ================================================ # Init file samples [Home](./readme.md#configuration-via-init-file) You find here examples that leverage the [init file capabilities](./readme.md#configuration-via-init-file) of OPC Publisher (since 2.9.12). ## Table Of Contents - [Find and create writers for all machine tools in a server](#find-and-create-writers-for-all-machine-tools-in-a-server) - [Add all variables in a server to a single data set writer](#add-all-variables-in-a-server-to-a-single-data-set-writer) - [Add machine objects as data set writers](#add-machine-objects-as-data-set-writers) - [Create a Web of Things Asset and add a data set writer](#create-a-web-of-things-asset-and-add-a-data-set-writer) ## Find and create writers for all machine tools in a server This init file uses the [ExpandAndCreateOrUpdateDataSetWriterEntries API](./api.md#expandandcreateorupdatedatasetwriterentries) to generate writers for each machine tool found on the server. A machine tool is an object that compiles to the MachineTool ObjectType as defined in the [OPC 40501-1](https://reference.opcfoundation.org/MachineTool/v102/docs/8.1) (machine tool companion specification). For this reason, this and the following 2 samples use the publicly hosted [Umati](https://umati.org/) reference server giving a good understanding on how to leverage the OPC UA companion specifications. ``` json ### // 3 retries in case of failure, with a delay of 5 seconds between // @delay 5 // @retries 3 // Creates writer entries for all objects that implement the // machine tool object type or one of its subtypes on the server ExpandAndCreateOrUpdateDataSetWriterEntries_V2 { "entry": { "EndpointUrl": "opc.tcp://opcua.umati.app:4840", "UseSecurity": false, "DataSetWriterGroup": "MachineTools", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/MachineTool/;i=13" } ] } } ### // Shutdown the publisher in case the expansion failed // and let docker restart it. The Fail fast argument // provided as json payload. # @on-error Shutdown_V2 true ### ``` This results in a result (log) file that shows the result of the execution of the individual methods on the publisher API and that looks like this (the response payload is abbreviated and in any case not indented): ``` json ### // 3 retries in case of failure, with a delay of 5 seconds between // Creates writer entries for all objects that implement the // machine tool object type or one of its subtypes on the server ExpandAndCreateOrUpdateDataSetWriterEntries_V2 200 [{"result":{"DataSetWrite ....... tionMode":"Anonymous"}}] ### // Shutdown the publisher in case the expansion failed // and let docker restart it. The Fail fast argument // provided as json payload. Shutdown_V2 // @skipped reason = success ### ``` ## Add all variables in a server to a single data set writer The following example uses the same API but with the ObjectsFolder (`i=85`) node as root, drilling down 10 levels and capturing all variables into a single writer entry in the published nodes configuration. ``` json ### // 3 retries in case of failure, with a delay of 5 seconds between // @delay 5 // @retries 3 ExpandAndCreateOrUpdateDataSetWriterEntries_V2 { "entry": { "EndpointUrl": "opc.tcp://opcua.umati.app:4840", "UseSecurity": false, "DataSetWriterGroup": "All", "OpcNodes": [ { "Id": "i=85" } ] }, "request": { "createSingleWriter": true, "maxDepth": 10, "discardErrors": true } } ### // Shutdown the publisher in case the expansion failed // and let docker restart it. The Fail fast argument // provided as json payload. # @on-error Shutdown_V2 true ### ``` ## Add machine objects as data set writers The following example uses again the same API but with the Machines folder (`nsu=http://opcfoundation.org/UA/Machinery/;i=1001`) node as root capturing all variables into several writer entries in the published nodes configuration. ``` json ### // @delay 5 ExpandAndCreateOrUpdateDataSetWriterEntries { "entry": { "EndpointUrl": "opc.tcp://opcua.umati.app:4840", "UseSecurity": false, "DataSetWriterGroup": "Machinery Objects", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Machinery/;i=1001" } ] } } // @retries 3 ### Shutdown // @on-error ### ``` ## Create a Web of Things Asset and add a data set writer The following shows how to create a Asset in a [WoT connectivity](https://reference.opcfoundation.org/WoT/v100/docs/) compatible server using a WoT Thing instance model using the [Asset](./api.md#createorupdateasset) API. An compatible sample server can be found [here](https://github.com/OPCFoundation/UA-EdgeTranslator). > Please note that the asset name inside the configuration must match the `DataSetName` property. ``` json ### CreateOrUpdateAsset { "entry": { "EndpointUrl": "opc.tcp://localhost:4840", "UseSecurity": true, "DataSetWriterGroup": "Assets", "DataSetName": "MyAsset1" }, "waitTime": "00:00:01", "configuration": { "@context": [ "https://www.w3.org/2022/wot/td/v1.1" ], "id": "urn:Simple PLC", "securityDefinitions": { "nosec_sc": { "scheme": "nosec" } }, "security": [ "nosec_sc" ], "@type": [ "tm:ThingModel" ], "name": "MyAsset1", "base": "ads://127.0.0.1:8534", "title": "Untitled1", "properties": { "Global_Version.stLibVersion_Tc2_Standard": { "type": "number", "opcua:nodeId": null, "opcua:type": null, "opcua:fieldPath": null, "readOnly": true, "observable": true, "forms": [ { "href": "Global_Version.stLibVersion_Tc2_Standard?36", "op": [ "readproperty", "observeproperty" ], "type": "xsd:float", "pollingTime": 1000 } ] }, "Global_Version.stLibVersion_Tc2_System": { "type": "number", "opcua:nodeId": null, "opcua:type": null, "opcua:fieldPath": null, "readOnly": true, "observable": true, "forms": [ { "href": "Global_Version.stLibVersion_Tc2_System?36", "op": [ "readproperty", "observeproperty" ], "type": "xsd:float", "pollingTime": 1000 } ] }, "Global_Version.stLibVersion_Tc3_Module": { "type": "number", "opcua:nodeId": null, "opcua:type": null, "opcua:fieldPath": null, "readOnly": true, "observable": true, "forms": [ { "href": "Global_Version.stLibVersion_Tc3_Module?36", "op": [ "readproperty", "observeproperty" ], "type": "xsd:float", "pollingTime": 1000 } ] }, "GVL_VAR.temp": { "type": "number", "opcua:nodeId": null, "opcua:type": null, "opcua:fieldPath": null, "readOnly": true, "observable": true, "forms": [ { "href": "GVL_VAR.temp?4", "op": [ "readproperty", "observeproperty" ], "type": "xsd:float", "pollingTime": 1000 } ] } } } ### # @on-error Shutdown_V2 ### ``` ================================================ FILE: docs/opc-publisher/messageformats.md ================================================ # Telemetry Message Formats [Home](./readme.md) > This documentation applies to version 2.9 ## Table Of Contents - [Messaging Profiles supported by OPC Publisher](#messaging-profiles-supported-by-opc-publisher) - [OPC UA Pub Sub Encoding](#opc-ua-pub-sub-encoding) - [Standards compliance](#standards-compliance) - [Delta and key frame messages](#delta-and-key-frame-messages) - [Event messages](#event-messages) - [Reversible encoding](#reversible-encoding) - [Pending Alarm snapshots](#pending-alarm-snapshots) - [Keep Alive messages](#keep-alive-messages) - [Samples mode encoding (Legacy)](#samples-mode-encoding-legacy) - [Value change messages in Samples mode](#value-change-messages-in-samples-mode) - [Event messages in Samples mode](#event-messages-in-samples-mode) OPC Publisher supports a rich set of message formats, including legacy formats supported. ## Messaging Profiles supported by OPC Publisher | Messaging Mode
(--mm) | Message Encoding
(--me) | NetworkMessageContentMask | DataSetMessageContentMask | DataSetFieldContentMask | Metadata supported | KeyFrames supported | KeepAlive supported | Schema publishing | |--------------------------|----------------------------|---------------------------|---------------------------|-------------------------|--------------------|---------------------|---------------------|-------------------| | Samples | Json | DataSetMessageHeader, MonitoredItemMessage
(0x2) | MetaDataVersion, MajorVersion, MinorVersion, MessageType, DataSetWriterName
(0xB0000062) | StatusCode, SourceTimestamp, NodeId, DisplayName, EndpointUrl
(0x3) | | | | | FullSamples | Json | DataSetMessageHeader, MonitoredItemMessage
(0x2) | Timestamp, MetaDataVersion, DataSetWriterId, MajorVersion, MinorVersion, SequenceNumber, MessageType, DataSetWriterName
(0xF200006F) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | | | | | PubSub | Json | PublisherId, WriterGroupId, NetworkMessageNumber, SequenceNumber, PayloadHeader, Timestamp, DataSetClassId, NetworkMessageHeader, DataSetMessageHeader
(0x1B) | MetaDataVersion, MajorVersion, MinorVersion, MessageType, DataSetWriterName
(0xB0000062) | StatusCode, SourceTimestamp, NodeId, DisplayName, EndpointUrl
(0x3) | X | X | X | | FullNetworkMessages | Json | PublisherId, WriterGroupId, NetworkMessageNumber, SequenceNumber, PayloadHeader, Timestamp, DataSetClassId, NetworkMessageHeader, DataSetMessageHeader
(0x1B) | Timestamp, MetaDataVersion, DataSetWriterId, MajorVersion, MinorVersion, SequenceNumber, MessageType, DataSetWriterName
(0xF200006F) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | X | X | X | | PubSub | JsonGzip | PublisherId, WriterGroupId, NetworkMessageNumber, SequenceNumber, PayloadHeader, Timestamp, DataSetClassId, NetworkMessageHeader, DataSetMessageHeader
(0x1B) | MetaDataVersion, MajorVersion, MinorVersion, MessageType, DataSetWriterName
(0xB0000062) | StatusCode, SourceTimestamp, NodeId, DisplayName, EndpointUrl
(0x3) | X | X | X | | FullNetworkMessages | JsonGzip | PublisherId, WriterGroupId, NetworkMessageNumber, SequenceNumber, PayloadHeader, Timestamp, DataSetClassId, NetworkMessageHeader, DataSetMessageHeader
(0x1B) | Timestamp, MetaDataVersion, DataSetWriterId, MajorVersion, MinorVersion, SequenceNumber, MessageType, DataSetWriterName
(0xF200006F) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | X | X | X | | PubSub | JsonReversible | PublisherId, WriterGroupId, NetworkMessageNumber, SequenceNumber, PayloadHeader, Timestamp, DataSetClassId, NetworkMessageHeader, DataSetMessageHeader
(0x1B) | MetaDataVersion, MajorVersion, MinorVersion, MessageType, DataSetWriterName, ReversibleFieldEncoding
(0xB00000E2) | StatusCode, SourceTimestamp, NodeId, DisplayName, EndpointUrl
(0x3) | X | X | X | | PubSub | JsonReversibleGzip | PublisherId, WriterGroupId, NetworkMessageNumber, SequenceNumber, PayloadHeader, Timestamp, DataSetClassId, NetworkMessageHeader, DataSetMessageHeader
(0x1B) | MetaDataVersion, MajorVersion, MinorVersion, MessageType, DataSetWriterName, ReversibleFieldEncoding
(0xB00000E2) | StatusCode, SourceTimestamp, NodeId, DisplayName, EndpointUrl
(0x3) | X | X | X | | FullNetworkMessages | JsonReversible | PublisherId, WriterGroupId, NetworkMessageNumber, SequenceNumber, PayloadHeader, Timestamp, DataSetClassId, NetworkMessageHeader, DataSetMessageHeader
(0x1B) | Timestamp, MetaDataVersion, DataSetWriterId, MajorVersion, MinorVersion, SequenceNumber, MessageType, DataSetWriterName, ReversibleFieldEncoding
(0xF20000EF) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | X | X | X | | FullNetworkMessages | JsonReversibleGzip | PublisherId, WriterGroupId, NetworkMessageNumber, SequenceNumber, PayloadHeader, Timestamp, DataSetClassId, NetworkMessageHeader, DataSetMessageHeader
(0x1B) | Timestamp, MetaDataVersion, DataSetWriterId, MajorVersion, MinorVersion, SequenceNumber, MessageType, DataSetWriterName, ReversibleFieldEncoding
(0xF20000EF) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | X | X | X | | Samples | JsonReversible | DataSetMessageHeader, MonitoredItemMessage
(0x2) | MetaDataVersion, MajorVersion, MinorVersion, MessageType, DataSetWriterName, ReversibleFieldEncoding
(0xB00000E2) | StatusCode, SourceTimestamp, NodeId, DisplayName, EndpointUrl
(0x3) | | | | | Samples | JsonReversibleGzip | DataSetMessageHeader, MonitoredItemMessage
(0x2) | MetaDataVersion, MajorVersion, MinorVersion, MessageType, DataSetWriterName, ReversibleFieldEncoding
(0xB00000E2) | StatusCode, SourceTimestamp, NodeId, DisplayName, EndpointUrl
(0x3) | | | | | FullSamples | JsonReversible | DataSetMessageHeader, MonitoredItemMessage
(0x2) | Timestamp, MetaDataVersion, DataSetWriterId, MajorVersion, MinorVersion, SequenceNumber, MessageType, DataSetWriterName, ReversibleFieldEncoding
(0xF20000EF) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | | | | | FullSamples | JsonReversibleGzip | DataSetMessageHeader, MonitoredItemMessage
(0x2) | Timestamp, MetaDataVersion, DataSetWriterId, MajorVersion, MinorVersion, SequenceNumber, MessageType, DataSetWriterName, ReversibleFieldEncoding
(0xF20000EF) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | | | | | DataSetMessages | Json | DataSetMessageHeader
(0x2) | Timestamp, MetaDataVersion, DataSetWriterId, MajorVersion, MinorVersion, SequenceNumber, MessageType, DataSetWriterName
(0xF200006F) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | X | X | X | | DataSetMessages | JsonGzip | DataSetMessageHeader
(0x2) | Timestamp, MetaDataVersion, DataSetWriterId, MajorVersion, MinorVersion, SequenceNumber, MessageType, DataSetWriterName
(0xF200006F) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | X | X | X | | DataSetMessages | JsonReversible | DataSetMessageHeader
(0x2) | Timestamp, MetaDataVersion, DataSetWriterId, MajorVersion, MinorVersion, SequenceNumber, MessageType, DataSetWriterName, ReversibleFieldEncoding
(0xF20000EF) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | X | X | X | | DataSetMessages | JsonReversibleGzip | DataSetMessageHeader
(0x2) | Timestamp, MetaDataVersion, DataSetWriterId, MajorVersion, MinorVersion, SequenceNumber, MessageType, DataSetWriterName, ReversibleFieldEncoding
(0xF20000EF) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | X | X | X | | SingleDataSetMessage | Json | DataSetMessageHeader, SingleDataSetMessage
(0x6) | Timestamp, MetaDataVersion, DataSetWriterId, MajorVersion, MinorVersion, SequenceNumber, MessageType, DataSetWriterName
(0xF200006F) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | X | X | X | | SingleDataSetMessage | JsonGzip | DataSetMessageHeader, SingleDataSetMessage
(0x6) | Timestamp, MetaDataVersion, DataSetWriterId, MajorVersion, MinorVersion, SequenceNumber, MessageType, DataSetWriterName
(0xF200006F) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | X | X | X | | SingleDataSetMessage | JsonReversible | DataSetMessageHeader, SingleDataSetMessage
(0x6) | Timestamp, MetaDataVersion, DataSetWriterId, MajorVersion, MinorVersion, SequenceNumber, MessageType, DataSetWriterName, ReversibleFieldEncoding
(0xF20000EF) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | X | X | X | | SingleDataSetMessage | JsonReversibleGzip | DataSetMessageHeader, SingleDataSetMessage
(0x6) | Timestamp, MetaDataVersion, DataSetWriterId, MajorVersion, MinorVersion, SequenceNumber, MessageType, DataSetWriterName, ReversibleFieldEncoding
(0xF20000EF) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | X | X | X | | DataSets | Json | 0
(0x0) | 0
(0xF2000000) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | X | X | X | | DataSets | JsonGzip | 0
(0x0) | 0
(0xF2000000) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | X | X | X | | SingleDataSet | Json | SingleDataSetMessage
(0x4) | 0
(0xF2000000) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | X | X | X | | SingleDataSet | JsonGzip | SingleDataSetMessage
(0x4) | 0
(0xF2000000) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | X | X | X | | DataSets | JsonReversible | 0
(0x0) | 0
(0xF2000000) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | X | X | X | | DataSets | JsonReversibleGzip | 0
(0x0) | 0
(0xF2000000) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | X | X | X | | SingleDataSet | JsonReversible | SingleDataSetMessage
(0x4) | 0
(0xF2000000) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | X | X | X | | SingleDataSet | JsonReversibleGzip | SingleDataSetMessage
(0x4) | 0
(0xF2000000) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | X | X | X | | RawDataSets | Json | 0
(0x0) | 0
(0x0) | RawData
(0x20) | | X | X | | RawDataSets | JsonGzip | 0
(0x0) | 0
(0x0) | RawData
(0x20) | | X | X | | SingleRawDataSet | Json | SingleDataSetMessage
(0x4) | 0
(0x0) | RawData
(0x20) | X | X | X | | SingleRawDataSet | JsonGzip | SingleDataSetMessage
(0x4) | 0
(0x0) | RawData
(0x20) | X | X | X | | RawDataSets | JsonReversible | 0
(0x0) | 0
(0x0) | RawData
(0x20) | | X | X | | RawDataSets | JsonReversibleGzip | 0
(0x0) | 0
(0x0) | RawData
(0x20) | | X | X | | SingleRawDataSet | JsonReversible | SingleDataSetMessage
(0x4) | 0
(0x0) | RawData
(0x20) | X | X | X | | SingleRawDataSet | JsonReversibleGzip | SingleDataSetMessage
(0x4) | 0
(0x0) | RawData
(0x20) | X | X | X | | PubSub | Uadp | PublisherId, WriterGroupId, NetworkMessageNumber, SequenceNumber, PayloadHeader, Timestamp, DataSetClassId, NetworkMessageHeader, DataSetMessageHeader
(0x2F5) | MetaDataVersion, MajorVersion, MinorVersion, MessageType, DataSetWriterName
(0x18) | StatusCode, SourceTimestamp, NodeId, DisplayName, EndpointUrl
(0x3) | X | X | X | | FullNetworkMessages | Uadp | PublisherId, WriterGroupId, NetworkMessageNumber, SequenceNumber, PayloadHeader, Timestamp, DataSetClassId, NetworkMessageHeader, DataSetMessageHeader
(0x2F5) | Timestamp, MetaDataVersion, DataSetWriterId, MajorVersion, MinorVersion, SequenceNumber, MessageType, DataSetWriterName
(0x39) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | X | X | X | | DataSetMessages | Uadp | DataSetMessageHeader
(0x0) | Timestamp, MetaDataVersion, DataSetWriterId, MajorVersion, MinorVersion, SequenceNumber, MessageType, DataSetWriterName
(0x39) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | X | X | X | | SingleDataSetMessage | Uadp | DataSetMessageHeader, SingleDataSetMessage
(0x0) | Timestamp, MetaDataVersion, DataSetWriterId, MajorVersion, MinorVersion, SequenceNumber, MessageType, DataSetWriterName
(0x39) | StatusCode, SourceTimestamp, ServerTimestamp, NodeId, DisplayName, EndpointUrl, ApplicationUri, ExtensionFields
(0x7) | X | X | X | | RawDataSets | Uadp | 0
(0x0) | 0
(0x0) | RawData
(0x20) | | X | X | | SingleRawDataSet | Uadp | SingleDataSetMessage
(0x0) | 0
(0x0) | RawData
(0x20) | X | X | X | ## OPC UA Pub Sub Encoding To use the OPC UA PubSub format specify a value for `--mm` on the command line. This needs to be done because the OPC publisher defaults to `--mm=Samples` mode which existed before the introduction of OPC UA standards compliant PubSub format. You should always use PubSub format specified in the OPC UA Standard. We will not support the non standards compliant Samples mode in versions greater than 2.*. ### Standards compliance OPC Publisher 2.9 and above supports strict adherence to Part 6 and Part 14 of the OPC UA specification when it comes to network message encoding. To enable strict mode use the `-c` or `--strict` [command line](./commandline.md) option. For backwards compatibility this option is off by default. > It is highly recommended to always run OPC Publisher with strict adherence turned on. Strict mode is continuously adjusted as we do interoperability testing and parts of the standard are clarified. The following are the key differences between strict compliance and the compatibility mode with previous versions of OPC Publisher: | Strict mode | Compatibility mode | |-------------|--------------------| | `PubSub` is the default encoding mode if nothing else is specified | `Samples` is the default encoding mode and `--mm=PubSub` must be explicitly specified | | `DataSetWriterId` is a unique integer in the `DataSetWriterGroup` | `DataSetWriterId` is the writer name string | | `DataSetWriterName` is the writer name string | `DataSetWriterName` is not used | | Network messages contain array of data set messages when batching | Array of network messages is sent when batching | | `Status` field is status code integer only (as per Part 14) | `Status` is fully JSON encoded Status code (per Part 6) | | JSON encoding compliant with Part 6 | Microsoft [JSON extensions](../json.md) | ### Delta and key frame messages This section covers data value change messages (Message type `ua-deltaframe` and `ua-keyframe`). Details for OPC UA Alarms and Events messages (`ua-event`) can be found [further on](#event-messages). The following messages are emitted for data value changes in a subscription if `--mm=PubSub` message mode is used with `--me=Json`: ```json { "body": { "MessageId": "27", "MessageType": "ua-data", "PublisherId": "opc.tcp://opcplc:50000_70FB9F43", "Messages": [ { "DataSetWriterId": 1, "DataSetWriterName": "1000", "SequenceNumber": 27, "MetaDataVersion": { "MajorVersion": 1, "MinorVersion": 0 }, "MessageType": "ua-deltaframe", "Timestamp": "2022-03-18T12:55:21.3424136Z", "Payload": { "AlternatingBoolean": { "Value": true, "SourceTimestamp": "2022-03-18T12:55:20.9313098Z", "ServerTimestamp": "2022-03-18T12:55:20.9314784Z" }, "StepUp": { "Value": 23305, "SourceTimestamp": "2022-03-18T12:55:21.3313539Z", "ServerTimestamp": "2022-03-18T12:55:21.3313638Z" }, "RandomSignedInt32": { "Value": 1076635612, "SourceTimestamp": "2022-03-18T12:55:21.3419164Z", "ServerTimestamp": "2022-03-18T12:55:21.3419728Z" }, "RandomUnsignedInt32": { "Value": 1461169798, "SourceTimestamp": "2022-03-18T12:55:21.3419727Z", "ServerTimestamp": "2022-03-18T12:55:21.3420045Z" }, "BadFastUInt1": { "StatusCode": { "Symbol": "BadNoCommunication", "Code": 2150694912 }, "SourceTimestamp": "2022-03-18T12:55:20.8409353Z", "ServerTimestamp": "2022-03-18T12:55:20.8409362Z" } } } ] }, "enqueuedTime": "Fri Mar 18 2022 13:55:21 GMT+0100 (Central European Standard Time)", "properties": { "$$ContentType": "application/x-network-message-json-v1", "iothub-message-schema": "application/json", "$$ContentEncoding": "utf-8" } } ``` The data set messages in the `ua-data` network message can be delta frames (`ua-deltaframe`, containing only changed values in the dataset), key frames (`ua-keyframe`, containing all values of the dataset), keep alive messages (`ua-keepalive`, containing no payload), or [events and conditions](#event-messages). IMPORTANT: Depending on the number of nodes in a subscription and the data type of properties inside a single dataset, data set messages contained in a network message can be very large. Indeed, it can potentially be too large and not fit into IoT Hub Messages which are limited to 256 kB. In this case messages might not be sent. You can try to use `--me=JsonGzip` to compress messages using Gzip compression, or use `--me=Uadp` which supports network message chuncing (and overcomes any transport limitation). If neither help or are an option it is recommended to create smaller subscriptions (by adding less nodes to an endpoint) or disable dataset metadata message sending using `--dm=False`. The data set is described by a corresponding metadata message (message type `ua-metdata`), which is emitted prior to the first message and whenever the configuration is updated requiring an update of the metadata. Metadata can also be sent periodically, which can be configured using the control plane of OPC Publisher. ```json { "body": [ { "MessageId": "0", "MessageType": "ua-metadata", "PublisherId": "opc.tcp://localhost:57537/UA/SampleServer_A2425855", "DataSetWriterId": 1, "MetaData": { "Namespaces": [ "http://opcfoundation.org/UA/", "urn:localhost:OPCFoundation:CoreSampleServer", "http://test.org/UA/Data/", "http://opcfoundation.org/UA/Boiler/" ], "StructureDataTypes": [], "EnumDataTypes": [], "SimpleDataTypes": [], "Fields": [ { "Name": "Output", "BuiltInType": 26, "DataType": "Number", "ValueRank": -1, "ArrayDimensions": [], "DataSetFieldId": "fcab2ed0-c6b2-4456-a4c3-ed985e5c708d", "Properties": [] } ], "ConfigurationVersion": { "MajorVersion": 1222304635, "MinorVersion": 1289056823 } } } ], "enqueuedTime": "Mon Jan 23 2023 13:49:02 GMT+0200 (Central European Summer Time)", "properties": { "$$ContentType": "application/x-network-message-json-v1", "iothub-message-schema": "application/ua+json", "$$ContentEncoding": "utf-8" } } ``` IMPORTANT: Depending on the number of nodes in a subscription, a Metadata messages can be very large. Indeed, it can potentially be too large and not fit into IoT Hub Messages which are limited to 256 kB. In this case they are created but never sent. You can choose to use `--me=JsonGzip` to compress messages using Gzip compression, or use `--me=Uadp` which supports network message chunking. If neither help or are an option it is recommended to create smaller subscriptions (by adding less nodes to an endpoint) or disable dataset metadata message sending using `--dm=False`. ### Event messages This section describes what the output looks like when listening for events in the OPC Publisher. To use the OPC UA PubSub format specify the `--mm=PubSub` command line. This needs to be done because the OPC publisher defaults to `--mm=Samples` [mode](#samples-mode-encoding-legacy) which existed before the introduction of OPC UA standards compliant PubSub format. Events should be produced in the PubSub format specified in the OPC UA Standard. The payload is an event which consists of fields selected in the select clause and its values. The following is an example of the output you will se when listening to events from the Simple Events sample: ```json { "body": [ { "MessageId": "43", "MessageType": "ua-data", "PublisherId": "SIMPLE-EVENTS", "DataSetWriterGroup": "SIMPLE-EVENTS", "Messages": [ { "DataSetWriterId": "SIMPLE-EVENTS", "MetaDataVersion": { "MajorVersion": 1222304427, "MinorVersion": 801860751 }, "MessageType": "ua-event", "Payload": { "EventId": "+6CQjN1eqkO6+yHJnxMz5w==", "EventType": "http://microsoft.com/Opc/OpcPlc/SimpleEvents#i=14", "Message": "The system cycle '59' has started.", "ReceiveTime": "2021-06-21T12:38:55.5814091Z", "Severity": 1, "SourceName": "System", "SourceNode": "i=2253", "http://opcfoundation.org/SimpleEvents#CurrentStep": { "Name": "Step 1", "Duration": 1000.0 }, "Time": "2021-06-21T12:38:55.5814078Z" } } ] } ], "enqueuedTime": "Mon Jan 21 2023 14:39:02 GMT+0200 (Central European Summer Time)", "properties": { "$$ContentType": "application/x-network-message-json-v1", "iothub-message-schema": "application/ua+json", "$$ContentEncoding": "utf-8" } } ``` The event is described by the corresponding metadata message, which is emitted prior to the first message and whenever the configuration is updated requiring an update of the metadata. Metadata can also be sent periodically, which can be configured using the control plane of OPC Publisher. The following metadata is provided in `--strict` mode: ```json { "body": [ { "MessageId": "edecf7ec-5ae8-4957-82ef-7f915dddb5be", "MessageType": "ua-metadata", "PublisherId": "opc.tcp://localhost:55924/UA/SampleServer_E8BAB2AD", "DataSetWriterId": 1, "MetaData": { "Namespaces": [ "http://opcfoundation.org/UA/", "http://test.org/UA/Data/", "http://test.org/UA/Data//Instance", "http://opcfoundation.org/UA/Boiler//Instance", "urn:localhost:somecompany.com:VehiclesServer", "http://opcfoundation.org/UA/Vehicles/Types", "http://opcfoundation.org/UA/Vehicles/Instances", "http://opcfoundation.org/ReferenceApplications", "http://opcfoundation.org/UA/Diagnostics", "http://opcfoundation.org/UA/Boiler/" ], "StructureDataTypes": [ { "DataTypeId": { "Id": 183, "Namespace": "http://opcfoundation.org/SimpleEvents" }, "Name": { "Name": "CycleStepDataType", "Uri": "http://opcfoundation.org/SimpleEvents" }, "StructureDefinition": { "BaseDataType": { "Id": 22 }, "StructureType": "Structure_0", "Fields": [ { "Name": "Name", "DataType": { "Id": 12 }, "ValueRank": -1, "ArrayDimensions": [], "MaxStringLength": 0, "IsOptional": false }, { "Name": "Duration", "DataType": { "Id": 11 }, "ValueRank": -1, "ArrayDimensions": [], "MaxStringLength": 0, "IsOptional": false } ] } } ], "EnumDataTypes": [], "SimpleDataTypes": [], "Fields": [ { "Name": "EventId", "FieldFlags": 0, "BuiltInType": 15, "DataType": { "Id": 15 }, "ValueRank": -1, "ArrayDimensions": [], "MaxStringLength": 0, "DataSetFieldId": "487f710c-9f43-4425-9a77-03f3396362f7", "Properties": [] }, { "Name": "Message", "FieldFlags": 0, "BuiltInType": 21, "DataType": { "Id": 21 }, "ValueRank": -1, "ArrayDimensions": [], "MaxStringLength": 0, "DataSetFieldId": "15c7bc3a-4714-4f5e-9874-d4671288f5a0", "Properties": [] }, { "Name": "http://opcfoundation.org/SimpleEvents#CycleId", "FieldFlags": 0, "BuiltInType": 12, "DataType": { "Id": 12 }, "ValueRank": -1, "ArrayDimensions": [], "MaxStringLength": 0, "DataSetFieldId": "03378140-f21b-4ee1-9bbe-01325e847128", "Properties": [] }, { "Name": "http://opcfoundation.org/SimpleEvents#CurrentStep", "FieldFlags": 0, "BuiltInType": 22, "DataType": { "Id": 183, "Namespace": "http://opcfoundation.org/SimpleEvents" }, "ValueRank": -1, "ArrayDimensions": [], "MaxStringLength": 0, "DataSetFieldId": "a9cd0d57-ae64-4e20-b113-b3df52cb6a59", "Properties": [] } ], "ConfigurationVersion": { "MajorVersion": 1222308210, "MinorVersion": 2861644214 } }, "DataSetWriterName": "1000" } ], "enqueuedTime": "Mon Jan 23 2023 13:49:02 GMT+0200 (Central European Summer Time)", "properties": { "$$ContentType": "application/x-network-message-json-v1", "iothub-message-schema": "application/ua+json", "$$ContentEncoding": "utf-8" } } ``` IMPORTANT: Depending on the number of members in an event type and their data types, data set messages contained in a network message can be large. In some cases a JSON metadata message can potentially be too large and not fit into IoT Hub Messages which are limited to 256 kB. In this case messages might not be sent. You can try to use `--me=JsonGzip` to compress event data set messages using Gzip compression, or use `--me=Uadp` which supports network message chunking (and overcomes any transport limitation). If neither help or are an option it is recommended to use an event filter and select the properties needed or disable dataset metadata message sending altogether using `--dm=False`. ### Reversible encoding The format produced here does not contain enough information to decode the message using the OPC UA type system. If you need to decode messages using a OPC UA JSON decoder the command-line option called `UseReversibleEncoding` can be set to `true`. If you enable this setting the output will look like as follows: ```json { "body": [ { "MessageId": "5", "MessageType": "ua-data", "PublisherId": "opc.tcp://localhost:54340/UA/SampleServer_5CB8F1A5", "Messages": [ { "DataSetWriterId": "SIMPLE-EVENTS", "MetaDataVersion": { "MajorVersion": 1222304426, "MinorVersion": 3462403799 }, "MessageType": "ua-event", "Payload": { "EventId": { "Type": "ByteString", "Body": "88C2T817uUWMVNDclyOFnA==" }, "Message": { "Type": "LocalizedText", "Body": { "Text": "The system cycle \u00275\u0027 has started.", "Locale": "en-US" } }, "http://opcfoundation.org/SimpleEvents#CycleId": { "Type": "String", "Body": "5" }, "http://opcfoundation.org/SimpleEvents#CurrentStep": { "Type": "ExtensionObject", "Body": { "TypeId": "http://opcfoundation.org/SimpleEvents#i=183", "Encoding": "Json", "Body": { "Name": "Step 1", "Duration": 1000.0 } } } } } ] } ], "enqueuedTime": "Mon Jun 21 2021 14:45:22 GMT+0200 (Central European Summer Time)", "properties": { "$$ContentType": "application/x-network-message-json-v1", "iothub-message-schema": "application/ua+json", "$$ContentEncoding": "utf-8" } } ``` This JSON contains the metadata information to decode each variant value. ### Pending Alarm snapshots The OPC Publisher also supports sending Pending Alarms (or conditions) which are events that are associated with a condition, as described in the user guide for [configuration of events](./readme.md#configuring-event-subscriptions). When this feature is enabled, it will listen to all ConditionType derived events and cache all that have has the `Retain` property set to true. It will then periodically generate output to broadcast the condition case still being in effect. When running against the OPC Foundation's Alarms & Conditions reference server sample the output will look like this: ```json { "body": [ { "MessageId": "34", "MessageType": "ua-data", "PublisherId": "PENDING-ALARMS", "DataSetWriterGroup": "PENDING-ALARMS", "Messages": [ { "DataSetWriterId": "PENDING-ALARMS", "MetaDataVersion": { "MajorVersion": 1, "MinorVersion": 0 }, "MessageType": "ua-condition", "Payload": { "EventId": "PQpa0fNNwUym272/HW40ww==", "EventType": "i=2830", "LocalTime": { "Offset": 60, "DaylightSavingInOffset": true }, "Message": "The dialog was activated", "ReceiveTime": "2022-12-20T17:03:02.1338153Z", "Severity": 100, "SourceName": "EastTank", "SourceNode": "http://opcfoundation.org/AlarmCondition#s=1%3aColours%2fEastTank", "Time": "2022-12-20T17:03:02.1338153Z" } } ] } ], "enqueuedTime": "Mon Jun 21 2021 14:56:53 GMT+0200 (Central European Summer Time)", "properties": { "$$ContentType": "application/x-network-message-json-v1", "iothub-message-schema": "application/ua+json", "$$ContentEncoding": "utf-8" } } ``` The important part to highlight here is that the payload is an array of events which have the Retain property set to true. Otherwise it's very similar to value change messages earlier. ### Keep Alive messages Keep alive messages must be explicitly enabled (since they potentially consume bandwidth and cost). To Enable them for the OPC Publisher use the `--ka` [command line](./commandline.md) argument or enable it for a specific `DataSetWriter` in the [configuration](./readme.md#configuration-schema). [Samples](#samples-mode-encoding-legacy) mode does not support keep alive messages even when enabled. Keep alive messages are part of the network message. A network message can contain more data sets from other writers that are also keep alive messages or of other message types. A simple keep alive message is shown here: ```json { "body": { "MessageId": "64", "MessageType": "ua-data", "PublisherId": "MyPublisher", "Messages": [ { "DataSetWriterId": 1, "DataSetWriterName": "DataSet33", "SequenceNumber": 66, "MetaDataVersion": { "MajorVersion": 1, "MinorVersion": 0 }, "MessageType": "ua-keepalive", "Timestamp": "2023-03-18T12:55:21.3423234Z" } ] } } ``` ## Samples mode encoding (Legacy) > IMPORTANT: Legacy `Samples` encoding mode is a message format that predates OPC UA PubSub message encoding and is thus considered legacy and not standards conform. We might decide to not support the non standards compliant Samples mode in future versions of OPC Publisher. ### Value change messages in Samples mode In samples mode value change messages look like this: ```json { "body": { "NodeId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=StepUp", "EndpointUrl": "opc.tcp://opcplc:50000/", "ApplicationUri": "urn:OpcPlc:opcplc", "DisplayName": "StepUp", "Timestamp": "2022-03-18T12:52:42.137703Z", "Value": { "Value": 21713, "SourceTimestamp": "2022-03-18T12:52:42.1327544Z", "ServerTimestamp": "2022-03-18T12:52:42.1327633Z" }, "SequenceNumber": 120, "ExtensionFields": { "PublisherId": "opc.tcp://opcplc:50000_D09D61EF", "DataSetWriterId": "1000" } }, "enqueuedTime": "Fri Mar 18 2022 13:52:42 GMT+0100 (Central European Standard Time)", "properties": { "$$ContentType": "application/x-monitored-item-json-v1", "iothub-message-schema": "application/json", "$$ContentEncoding": "utf-8" } } ``` To provide compatibility with new version of the IIoT Platform's telemetry processors the OPC Publisher should be started in standalone mode with `--fm=true` argument and produces messages like shown here: ```json { "body": { "NodeId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=RandomUnsignedInt32", "EndpointUrl": "opc.tcp://opcplc:50000/", "ApplicationUri": "urn:OpcPlc:opcplc", "Timestamp": "2022-03-18T12:58:45.6660994Z", "Value": { "Value": 1059185306, "SourceTimestamp": "2022-03-18T12:58:45.6329923Z", "ServerTimestamp": "2022-03-18T12:58:45.6331823Z" }, "SequenceNumber": 22, "ExtensionFields": { "PublisherId": "opc.tcp://opcplc:50000_D3C751BF", "DataSetWriterId": "1000" } }, "enqueuedTime": "Fri Mar 18 2022 13:58:45 GMT+0100 (Central European Standard Time)", "properties": { "$$ContentType": "application/x-monitored-item-json-v1", "iothub-message-schema": "application/json", "$$ContentEncoding": "utf-8" } } { "body": { "NodeId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=BadFastUInt1", "EndpointUrl": "opc.tcp://opcplc:50000/", "ApplicationUri": "urn:OpcPlc:opcplc", "Timestamp": "2022-03-18T12:58:41.6538735Z", "Value": { "StatusCode": { "Symbol": "BadNoCommunication", "Code": 2150694912 }, "SourceTimestamp": "2022-03-18T12:58:40.840659Z", "ServerTimestamp": "2022-03-18T12:58:40.8406599Z" }, "SequenceNumber": 18, "ExtensionFields": { "PublisherId": "opc.tcp://opcplc:50000_D3C751BF", "DataSetWriterId": "1000" } }, "enqueuedTime": "Fri Mar 18 2022 13:58:41 GMT+0100 (Central European Standard Time)", "properties": { "$$ContentType": "application/x-monitored-item-json-v1", "iothub-message-schema": "application/json", "$$ContentEncoding": "utf-8" } } ``` The following message is an example with batching/bulk mode enabled. Here OPC Publisher was started with the `--bs=5` argument, where 5 is the number of messages to be batched. ```json "body": [ { "NodeId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=AlternatingBoolean", "EndpointUrl": "opc.tcp://opcplc:50000/", "ApplicationUri": "urn:OpcPlc:opcplc", "Timestamp": "2022-03-18T13:01:56.7551553Z", "Value": { "Value": false, "SourceTimestamp": "2022-03-18T13:01:55.9333398Z", "ServerTimestamp": "2022-03-18T13:01:55.933447Z" }, "SequenceNumber": 22, "ExtensionFields": { "PublisherId": "opc.tcp://opcplc:50000_9C43F84E", "DataSetWriterId": "1000" } }, { "NodeId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=StepUp", "EndpointUrl": "opc.tcp://opcplc:50000/", "ApplicationUri": "urn:OpcPlc:opcplc", "Timestamp": "2022-03-18T13:01:56.7551553Z", "Value": { "Value": 27259, "SourceTimestamp": "2022-03-18T13:01:56.7393301Z", "ServerTimestamp": "2022-03-18T13:01:56.7401032Z" }, "SequenceNumber": 22, "ExtensionFields": { "PublisherId": "opc.tcp://opcplc:50000_9C43F84E", "DataSetWriterId": "1000" } }, { "NodeId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=RandomSignedInt32", "EndpointUrl": "opc.tcp://opcplc:50000/", "ApplicationUri": "urn:OpcPlc:opcplc", "Timestamp": "2022-03-18T13:01:56.7551553Z", "Value": { "Value": -2127202062, "SourceTimestamp": "2022-03-18T13:01:56.7393504Z", "ServerTimestamp": "2022-03-18T13:01:56.7398952Z" }, "SequenceNumber": 22, "ExtensionFields": { "PublisherId": "opc.tcp://opcplc:50000_9C43F84E", "DataSetWriterId": "1000" } }, { "NodeId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=RandomUnsignedInt32", "EndpointUrl": "opc.tcp://opcplc:50000/", "ApplicationUri": "urn:OpcPlc:opcplc", "Timestamp": "2022-03-18T13:01:56.7551553Z", "Value": { "Value": 456421443, "SourceTimestamp": "2022-03-18T13:01:56.739439Z", "ServerTimestamp": "2022-03-18T13:01:56.7395003Z" }, "SequenceNumber": 22, "ExtensionFields": { "PublisherId": "opc.tcp://opcplc:50000_9C43F84E", "DataSetWriterId": "1000" } }, { "NodeId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=BadFastUInt1", "EndpointUrl": "opc.tcp://opcplc:50000/", "ApplicationUri": "urn:OpcPlc:opcplc", "Timestamp": "2022-03-18T13:01:56.7551553Z", "Value": { "Value": 5, "SourceTimestamp": "2022-03-18T13:01:55.8426847Z", "ServerTimestamp": "2022-03-18T13:01:55.8427264Z" }, "SequenceNumber": 22, "ExtensionFields": { "PublisherId": "opc.tcp://opcplc:50000_9C43F84E", "DataSetWriterId": "1000" } } ], "enqueuedTime": "Fri Mar 18 2022 14:01:56 GMT+0100 (Central European Standard Time)", "properties": { "$$ContentType": "application/x-monitored-item-json-v1", "iothub-message-schema": "application/json", "$$ContentEncoding": "utf-8" } } ``` To provide compatible with the Connected Factory 1.0 and versions of OPC Publisher <= 2.5, OPC Publisher can be started in standalone mode with `--fm=false` argument: ```json { "body": { "NodeId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=StepUp", "EndpointUrl": "opc.tcp://opcplc:50000/", "Value": { "Value": 28679, "SourceTimestamp": "2022-03-18T13:04:18.7244388Z" } }, "enqueuedTime": "Fri Mar 18 2022 14:04:18 GMT+0100 (Central European Standard Time)", "properties": { "$$ContentType": "application/x-monitored-item-json-v1", "iothub-message-schema": "application/json", "$$ContentEncoding": "utf-8" } } ``` or ```json { "body": { "NodeId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=BadFastUInt1", "EndpointUrl": "opc.tcp://opcplc:50000/", "Value": { "Value": 4, "StatusCode": { "Symbol": "UncertainLastUsableValue", "Code": 1083179008 }, "SourceTimestamp": "2022-03-18T13:04:14.8405063Z" } }, "enqueuedTime": "Fri Mar 18 2022 14:04:15 GMT+0100 (Central European Standard Time)", "properties": { "$$ContentType": "application/x-monitored-item-json-v1", "iothub-message-schema": "application/json", "$$ContentEncoding": "utf-8" } } ``` In this case, if OPC Publisher is started in bulk mode with `--bs=5` argument a message would look like: ```json { "body": [ { "NodeId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=AlternatingBoolean", "EndpointUrl": "opc.tcp://opcplc:50000/", "Value": { "Value": true, "SourceTimestamp": "2022-03-18T13:06:30.932775Z" } }, { "NodeId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=StepUp", "EndpointUrl": "opc.tcp://opcplc:50000/", "Value": { "Value": 30003, "SourceTimestamp": "2022-03-18T13:06:31.1337676Z" } }, { "NodeId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=RandomSignedInt32", "EndpointUrl": "opc.tcp://opcplc:50000/", "Value": { "Value": -2052144044, "SourceTimestamp": "2022-03-18T13:06:31.1338343Z" } }, { "NodeId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=RandomUnsignedInt32", "EndpointUrl": "opc.tcp://opcplc:50000/", "Value": { "Value": 186770890, "SourceTimestamp": "2022-03-18T13:06:31.1339985Z" } }, { "NodeId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=BadFastUInt1", "EndpointUrl": "opc.tcp://opcplc:50000/", "Value": { "StatusCode": { "Symbol": "BadNoCommunication", "Code": 2150694912 }, "SourceTimestamp": "2022-03-18T13:06:30.8423538Z" } } ], "enqueuedTime": "Fri Mar 18 2022 14:06:31 GMT+0100 (Central European Standard Time)", "properties": { "$$ContentType": "application/x-monitored-item-json-v1", "iothub-message-schema": "application/json", "$$ContentEncoding": "utf-8" } } ``` ### Event messages in Samples mode The following sample messages show how events look like in legacy samples mode: ```json { "body": { "NodeId": "i=2253", "EndpointUrl": "opc.tcp://localhost:57965/UA/SampleServer", "DisplayName": "SimpleEvents", "Value": { "EventId": "JdRhF43ktkKvJBrk\u002BsePkg==", "Message": "The system cycle \u00271\u0027 has started.", "http://opcfoundation.org/SimpleEvents#CycleId": "1", "http://opcfoundation.org/SimpleEvents#CurrentStep": { "Name": "Step 1", "Duration": 1000.0 } } }, "enqueuedTime": "Fri Mar 18 2022 14:04:18 GMT+0100 (Central European Standard Time)", "properties": { "$$ContentType": "application/x-monitored-item-json-v1", "iothub-message-schema": "application/json", "$$ContentEncoding": "utf-8" } } ``` With `--fm=True` enabling full featured messages, these would then look like: ```json { "body": { "NodeId": "i=2253", "EndpointUrl": "opc.tcp://localhost:56769/UA/SampleServer", "ApplicationUri": "urn:SampleServer", "DisplayName": "SimpleEvents", "Timestamp": "2022-12-05T11:00:18.1907826Z", "Value": { "EventId": "MB0Xs/BZ5US/BeKOUtsL8A==", "Message": "The system cycle \u00273\u0027 has started.", "http://opcfoundation.org/SimpleEvents#CycleId": "3", "http://opcfoundation.org/SimpleEvents#CurrentStep": { "Name": "Step 1", "Duration": 1000.0 } }, "SequenceNumber": 2, "ExtensionFields": { "PublisherId": "opc.tcp://localhost:56769/UA/SampleServer_59F0BDE1", "DataSetWriterId": "1000" } }, "enqueuedTime": "Fri Mar 18 2022 14:04:18 GMT+0100 (Central European Standard Time)", "properties": { "$$ContentType": "application/x-monitored-item-json-v1", "iothub-message-schema": "application/json", "$$ContentEncoding": "utf-8" } } ``` Pending Alarms (or conditions) sent in Samples mode look as follows: ```json { "body": { "NodeId": "i=2253", "EndpointUrl": "opc.tcp://localhost:56692/UA/SampleServer", "DisplayName": "PendingAlarms", "Value": { "EventId": "xW5uvGPSuUWBdvp8IfSueQ==", "EventType": "i=2830", "LocalTime": { "Offset": 60, "DaylightSavingInOffset": true }, "Message": "The dialog was activated", "ReceiveTime": "2022-12-20T15:53:10.3815705Z", "Severity": 100, "SourceName": "EastTank", "SourceNode": "http://opcfoundation.org/AlarmCondition#s=1%3aColours%2fEastTank", "Time": "2022-12-20T15:53:10.3815705Z" } }, "enqueuedTime": "Fri Mar 18 2022 14:04:18 GMT+0100 (Central European Standard Time)", "properties": { "$$ContentType": "application/x-monitored-item-json-v1", "iothub-message-schema": "application/json", "$$ContentEncoding": "utf-8" } } ``` Finally, using reversable mode, legacy samples messages will look as follows: ```json { "body": { "NodeId": "i=2253", "EndpointUrl": "opc.tcp://localhost:54040/UA/SampleServer", "DisplayName": "SimpleEvents", "Value": { "Type": "ExtensionObject", "Body": { "TypeId": "http://microsoft.com/Industrial-IoT/OpcPublisher#i=1", "Encoding": "Json", "Body": { "EventId": { "Type": "ByteString", "Body": "xbAm3QTXwEKsVZFcsHSdzA==" }, "Message": { "Type": "LocalizedText", "Body": { "Text": "The system cycle \u00271\u0027 has started.", "Locale": "en-US" } }, "http://opcfoundation.org/SimpleEvents#CycleId": { "Type": "String", "Body": "1" }, "http://opcfoundation.org/SimpleEvents#CurrentStep": { "Type": "ExtensionObject", "Body": { "TypeId": "http://opcfoundation.org/SimpleEvents#i=183", "Encoding": "Json", "Body": { "Name": "Step 1", "Duration": 1000.0 } } } } } } }, "enqueuedTime": "Fri Mar 18 2022 14:04:18 GMT+0100 (Central European Standard Time)", "properties": { "$$ContentType": "application/x-monitored-item-json-v1", "iothub-message-schema": "application/json", "$$ContentEncoding": "utf-8" } } ``` ================================================ FILE: docs/opc-publisher/migrationpath.md ================================================ # Migrate from previous versions of OPC Publisher to 2.9 and higher [Home](./readme.md) ## Table Of Contents - [Why the changes from 2.8 to 2.9?](#why-the-changes-from-28-to-29) - [Breaking changes](#breaking-changes) - [Migrating Cosmos DB job definitions](#migrating-cosmos-db-job-definitions) - [Upgrading OPC Publisher published nodes configuration file (pn.json)](#upgrading-opc-publisher-published-nodes-configuration-file-pnjson) - [Command Line Arguments](#command-line-arguments) - [OPC Publisher 2.5.x Command Line Arguments supported in 2.8.2 or higher](#opc-publisher-25x-command-line-arguments-supported-in-282-or-higher) - [Direct Method compatibility](#direct-method-compatibility) - [OPC Publisher 2.5.x direct methods supported in 2.8.2](#opc-publisher-25x-direct-methods-supported-in-282) - [PublishNodes (PublishNodes\_V1)](#publishnodes-publishnodes_v1) - [GetConfiguredEndpoints (GetConfiguredEndpoints\_V1)](#getconfiguredendpoints-getconfiguredendpoints_v1) - [GetConfiguredNodesOnEndpoint (GetConfiguredNodesOnEndpoint\_V1)](#getconfigurednodesonendpoint-getconfigurednodesonendpoint_v1) - [GetDiagnosticInfo (GetDiagnosticInfo\_V1)](#getdiagnosticinfo-getdiagnosticinfo_v1) - [UnpublishNodes (UnpublishNodes\_V1)](#unpublishnodes-unpublishnodes_v1) - [UnpublishAllNodes (UnpublishAllNodes\_V1)](#unpublishallnodes-unpublishallnodes_v1) - [OPC Publisher 2.5.x direct methods not supported in 2.8.2](#opc-publisher-25x-direct-methods-not-supported-in-282) - [GetDiagnosticLog](#getdiagnosticlog) - [GetDiagnosticStartupLog](#getdiagnosticstartuplog) - [ExitApplication](#exitapplication) - [GetInfo](#getinfo) ## Why the changes from 2.8 to 2.9? Customers told us they want to leverage the capabilities of OPC Twin. However, deploying and operating a micro service architecture is often times too costly and too difficult for them. Many times customers were already using an Azure IoT Hub instance to manage other devices and wanted to leverage this instance also for OPC UA enabled assets. What they were looking for was the standalone version of OPC Publisher but with its capabilities extended to provide read/write/call capabilities also. We also found significant problems with the orchestration approach in OPC Publisher to continue its development. For one, the size constraints imposed by keeping the entire configuration of a publisher in a single document in Cosmos DB became an issue for some customers. And the overhead of the communication between publisher and cloud services and the need for a second cloud connection bypassing IoT Edge were a problem for stable and reliable production use. We reacted by combining all 3 edge modules into OPC Publisher 2.9 and combining all cloud services into a single web service that is now optional. Yes, you can directy interact with OPC Publisher through IoT Hub or MQTT/HTTP (Preview). We also updated OPC Publisher to leverage .net 8 performance improvements and to use more defensive coding and code analysis moving the code base forward. ## Breaking changes We provided backwards compatibility (e.g., you need to use the `-c`, `--strict` command line argument to enable standards compliance) in OPC Publisher. *OPC Publisher 2.9 is therefore a drop in replacement for OPC Publisher 2.8 in standalone mode* with the following exceptions: - Log levels specified through the `--loglevel` [command line option](./commandline.md) have been aligned to standard .net log levels, e.g., to specify verbose logging, use `Trace`. However, if you were using the 2.8 micro services before then you must be aware of the following breaking changes: - Due to the simplification of the cloud services we **removed the IAI installer and Helm chart** support. It is still possible to deploy the web api container in AKS but we do not provide any tooling to do that. - OPC Publisher 2.9 **removes "orchestrated mode"**. This means you must [migrate your Cosmos DB job definitions](#migrating-cosmos-db-job-definitions) using the migration tooling. - We also removed the **telemetry processors** and the secondary event hub to read the proprietary data set messages from. To migrate change your event hub processor or ingestion code to read OPC Publisher telemetry messages directly from IoT Hub event hub compatible endpoint. - We retained Open API compatibility to the 2.8 cloud service API in the new OPC Publisher cloud web service's API. This includes using the same route paths as in the AKS hosted version of the 2.8 platform. However, the following **API changes** were made: - OPC Publisher 2.9 does not support activation and deactivation of Endpoint Twins, which allowed OPC Twin endpoints to be addressed with a IoT Hub device id. Instead all API's must be invoked with a `ConnectionModel` parameter (`connection`) and the original request model. - The concept of supervisor (the OPC Twin module instance) and discoverer (the OPC Discovery module instance) are completely equivalent to the publisher concept in 2.9. The supervisor, discovery, and publisher REST APIs have been retained for backwards compatibility and return the same information which is the twin of the Publisher module. However, this also means there is no migration from OPC Twin or OPC Discovery to OPC Publisher 2.9, settings have to be re-applied. - With removal of the database and orchestrated mode we changed the existing Publishing API to directly update the publisher configuration which has different performance characteristics than in 2.8 especially for the bulk publishing API. - The GetSupervisorStatus and ResetSupervisor API has been removed without replacement. - GetEndpointCertificate API now returns a `X509CertificateChainModel` instead of a byte array in 2.8. - OPC Discovery capabilities are integrated into OPC Publisher 2.9. ### Migrating Cosmos DB job definitions COMING SOON ## Upgrading OPC Publisher published nodes configuration file (pn.json) OPC Publisher can consume published nodes JSON files version 2.5.x or higher without any modifications. Each OPC Publisher since has added new fields to configure publishing but maintained backwards compatibilty with older versions, such as 2.5.*x*. The full schema of published nodes JSON file that works in all versions since 2.5.* looks like this: ```json [ { "EndpointUrl": "string", "UseSecurity": "boolean", "OpcAuthenticationMode": "string", "OpcAuthenticationUsername": "string", "OpcAuthenticationPassword": "string", "DataSetWriterGroup": "string", "DataSetWriterId": "string", "DataSetPublishingInterval": "integer", "DataSetPublishingIntervalTimespan": "string", "Tag": "string", "OpcNodes": [ { "Id": "string", "ExpandedNodeId": "string", "DataSetFieldId ": "string", "DisplayName": "string", "OpcSamplingInterval": "integer", "OpcSamplingIntervalTimespan": "string", "OpcPublishingInterval": "integer", "OpcPublishingIntervalTimespan": "string", "HeartbeatInterval": "integer", "HeartbeatIntervalTimespan": "string", "SkipFirst": "bool", "QueueSize": "integer" } ] } ] ``` For details of each field you can consult the [direct methods API documentation](./directmethods.md) as the fields of published nodes JSON schema map directly to that of direct method API calls. The only difference is that `OpcAuthenticationUsername` and `OpcAuthenticationPassword` are refereed to as `UserName` and `Password` in direct method API calls. Please note that OPC Publisher 2.9 can still consume legacy `NodeId`-based node definitions (as can be found in [`publishednodes_2.5.json`](publishednodes_2.5.json?raw=1)), but we strongly recommend to use `OpcNodes`-based definitions instead. Please consider migrating your old published nodes JSON files that use `NodeId` to the newer schema. ## Command Line Arguments To learn more about how to use comman-line arguments to configure OPC Publisher, please refer to [this](./commandline.md) doc. ### OPC Publisher 2.5.x Command Line Arguments supported in 2.8.2 or higher Any removed command line arguments will still silently work. The following table describes the command line arguments, which were available in OPC Publisher 2.5.x and their compatibility in OPC Publisher 2.8.2 and above. | **Command Line Options** | **in 2.8.2 and above** | **Alternative** | |-------------------------------------- |--------------------------|-----------------| | --pf, --publishfile=VALUE | yes | | | --tc, --telemetryconfigfile=VALUE | no | | | --s, --site=VALUE | yes | | | --ic, --iotcentral | no | | | --sw, --sessionconnectwait=VALUE | no | | | --mq, --monitoreditemqueuecapacity=VALUE| no | use --om, --maxoutgressmessages=VALUE | | --di, --diagnosticsinterval=VALUE | yes | | | --ns, --noshutdown=VALUE | no | | | --rf, --runforever | no | | | --lf, --logfile=VALUE | no | IoT Edge support bundle or live logs | | --lt, --logflushtimespan=VALUE | no | IoT Edge support bundle or live logs | | --ll, --loglevel=VALUE | yes | | | --ih, --iothubprotocol=VALUE | yes | | | --ms, --iothubmessagesize=VALUE | yes | | | --si, --iothubsendinterval=VALUE | yes | | | --dc, --deviceconnectionstring=VALUE | yes | | | --c, --connectionstring=VALUE | no | use --dc, --deviceconnectionstring=VALUE | | --hb, --heartbeatinterval=VALUE | yes | | | --sf, --skipfirstevent=VALUE | yes (2.9.0 or above) | same as --skipfirst=VALUE | | --pn, --portnum=VALUE | no | | | --pa, --path=VALUE | no | | | --lr, --ldsreginterval=VALUE | no | | | --ol, --opcmaxstringlen=VALUE | yes | | | --ot, --operationtimeout=VALUE | yes | | | --oi, --opcsamplinginterval=VALUE | yes | | | --op, --opcpublishinginterval=VALUE | yes | | | --ct, --createsessiontimeout=VALUE | yes | | | --ki, --keepaliveinterval=VALUE | yes | | | --kt, --keepalivethreshold=VALUE | yes | | | --aa, --autoaccept | yes | | | --tm, --trustmyself=VALUE | yes | | | --to, --trustowncert | no | same as --tm, --trustmyself | | --fd, --fetchdisplayname=VALUE | yes | | | --fn, --fetchname | no | same as --fd, --fetchdisplayname | | --ss, --suppressedopcstatuscodes=VALUE | no | | | --at, --appcertstoretype=VALUE | yes | | | --ap, --appcertstorepath=VALUE | yes | | | --tp, --trustedcertstorepath=VALUE | yes | | | --rp, --rejectedcertstorepath=VALUE | yes | | | --ip, --issuercertstorepath=VALUE | yes | | | --csr | no | | | --ab, --applicationcertbase64=VALUE | no | | | --af, --applicationcertfile=VALUE | no | | | --pb, --privatekeybase64=VALUE | no | | | --pk, --privatekeyfile=VALUE | no | | | --cp, --certpassword=VALUE | no | | | --tb, --addtrustedcertbase64=VALUE | no | | | --tf, --addtrustedcertfile=VALUE | no | | | --ib, --addissuercertbase64=VALUE | no | | | --if, --addissuercertfile=VALUE | no | | | --rb, --updatecrlbase64=VALUE | no | | | --uc, --updatecrlfile=VALUE | no | | | --rc, --removecert=VALUE | no | | | --dt, --devicecertstoretype=VALUE | no | | | --dp, --devicecertstorepath=VALUE | no | | | -i, --install | no | | | -h, --help | yes | | | --st, --opcstacktracemask=VALUE | no | | | --sd, --shopfloordomain=VALUE | no | same as --s, --site option | | --vc, --verboseconsole=VALUE | no | | | --as, --autotrustservercerts=VALUE | no | same as --aa, --acceptuntrusted | | --autoaccept=VALUE | yes | same as --aa, --acceptuntrusted | | --tt, --trustedcertstoretype=VALUE | no | env variable TrustedPeerCertificatesType=VALUE | | --rt, --rejectedcertstoretype=VALUE | no | env variable RejectedCertificateStoreType=VALUE | | --it, --issuercertstoretype=VALUE | no | env variable TrustedIssuerCertificatesType=VALUE | ## Direct Method compatibility OPC Publisher version 2.8.2 and above implements [IoT Hub Direct Methods](https://docs.microsoft.com/azure/iot-hub/iot-hub-devguide-direct-methods), which can be called from applications using the [IoT Hub Device SDK](https://docs.microsoft.com/azure/iot-hub/iot-hub-devguide-sdks). The direct method request payload of OPC Publisher 2.8.2 and above is backwards compatible with OPC Publisher 2.5.x direct methods. The payload schema allows also configuration of attributes introduced in `pn.json` in OPC Publisher 2.6.x and above (for example: DataSetWriterGroup, DataSetWriterId, QueueSize per node, ...) **Limitations:** Continuation points for GetConfiguredEndpoints and GetConfiguredNodesOnEndpoint aren't available in 2.8.2 or above. Instead a chunking protocol is used when the .net sdk packages are used. **Note:** The objects and primitives names in the direct method payload api model are camel case formatted in 2.8.2. This follows the guidelines of the rest of the api models through the IIoT Platform. Since the names in json payloads in 2.5.x are pascal case formed, we highly recommend enabling case-insensitive Json parsing in your direct methods based configuration tool. You can find details on json case-insensitive serialization here: [how to enable case-insensitive property name matching with System.Text.Json](https://docs.microsoft.com/dotnet/standard/serialization/system-text-json-character-casing), or here: [Newtonsoft Json Serialization Naming Strategy](https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Serialization_DefaultNamingStrategy.htm) ## OPC Publisher 2.5.x direct methods supported in 2.8.2 The following table describes the direct methods, which were available in OPC Publisher 2.5.x with their request and response payloads. | **MethodName** | **Request** | **Response** | **in 2.8.2 and above** | |----------------------------------|-----------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------| | **PublishNodes** | EndpointUrl, List\, UseSecurity, UserName, Password | Status, List\ | Yes | | **UnpublishNodes** | EndpointUrl, List\ | Status, List\ | Yes | | **UnpublishAllNodes** | EndpointUrl | Status, List\ | Yes | | **GetConfiguredEndpoints** | - | List\ | Yes | | **GetConfiguredNodesOnEndpoint** | EndpointUrl | EndpointUrl, List< OpcNodeOnEndpointModel > where OpcNodeOnEndpointModel contains: Id ExpandedNodeId OpcSamplingInterval OpcPublishingInterval DisplayName HeartbeatInterval | Yes | | **GetDiagnosticInfo** | - | DiagnosticInfoMethodResponseModel | Yes | | **GetDiagnosticLog** | - | MissedMessageCount, LogMessageCount, List\ | No* | | **GetDiagnosticStartupLog** | - | MissedMessageCount, LogMessageCount, List\ | No* | | **ExitApplication** | SecondsTillExit (optional) | StatusCode, List\ | No* | | **GetInfo** | - | GetInfoMethodResponseModel | No* | *This functionality is provided by direct methods of the IoT Edge `edgeAgent` module. For more information, see ["Communicate with edgeAgent using built-in direct methods"](https://docs.microsoft.com/azure/iot-edge/how-to-edgeagent-direct-method). An outdated, archived [sample application](https://github.com/Azure-Samples/iot-edge-opc-publisher-nodeconfiguration) used to configure OPC Publisher 2.5.x can be used to configure OPC Publisher 2.8.2. For new applications, direct method names with a `_V2` suffix should be used. For backward compatibility of older applications direct method names without the `_V2` suffix are supported, but are subject of deprecation. ### PublishNodes (PublishNodes_V1) `Request` ```json { "EndpointUrl": "opc.tcp://sandboxhost-637811493394507132:50000", "UseSecurity": false, "OpcNodes":[ { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/Boiler;s=Boiler" }, { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=65e451f1-56f1-ce84-a44f-6addf176beaf" }, { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1" } ] } ``` `Response` (2.5.x) ```json { "status": 200, "payload": [ "'nsu=http://microsoft.com/Opc/OpcPlc/Boiler;s=Boiler': added", "'nsu=http://microsoft.com/Opc/OpcPlc/;s=65e451f1-56f1-ce84-a44f-6addf176beaf': added", "'nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1': added" ] } ``` `Response` (2.8.2) ```json { "status": 200, "payload": {} } ``` ### GetConfiguredEndpoints (GetConfiguredEndpoints_V1) `Request` {} `Response` (2.5.x) Without any configured endpoints: ```json { "status": 200, "payload": { "Endpoints": [] } } ``` With configured endpoints: ```json { "status": 200, "payload": { "Endpoints": [ { "EndpointUrl":"opc.tcp://sandboxhost-637811493394507132:50000" } ] } } ``` `Response` (2.8.2) Without configured endpoints: ```json { "status": 200, "payload": { "endpoints": [] } } ``` With configured endpoints: ```json { "status": 200, "payload": { "endpoints": [ { "endpointUrl":"opc.tcp://sandboxhost-637811493394507132:50000" } ] } } ``` ### GetConfiguredNodesOnEndpoint (GetConfiguredNodesOnEndpoint_V1) `Request` ```json { "EndpointUrl": "opc.tcp://sandboxhost-637811493394507132:50000" } ``` `Response` (2.5.x) ```json { "status": 200, "payload": { "EndpointUrl": "opc.tcp://sandboxhost-637811493394507132:50000", "OpcNodes": [ { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/Boiler;s=Boiler" }, { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=65e451f1-56f1-ce84-a44f-6addf176beaf" }, { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1" } ] } } ``` If `UnpublishAllNodes` is called on that endpoint, then the response will be: ```json { "status": 200, "payload": { "endpointUrl": "opc.tcp://sandboxhost-637811493394507132:50000", "opcNodes": [] } } ``` `Response` (2.8.2) ```json { "status":200, "payload": { "opcNodes": [ { "id": "nsu=http://microsoft.com/Opc/OpcPlc/Boiler;s=Boiler" }, { "id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=65e451f1-56f1-ce84-a44f-6addf176beaf" }, { "id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1" } ] } } ``` If the endpoint isn't configured or `UnpublishAllNodes` is called on that endpoint, then the response will be: ```json { "status": 404, "payload": "Endpoint not found: opc.tcp://sandboxhost-637811493394507132:50000/" } ``` ### GetDiagnosticInfo (GetDiagnosticInfo_V1) `Request` {} `Response` (2.5.x) ```json { "status": 200, "payload": { "PublisherStartTime": "2022-02-22T18:07:56.363511Z", "NumberOfOpcSessionsConfigured": 1, "NumberOfOpcSessionsConnected": 0, "NumberOfOpcSubscriptionsConfigured": 1, "NumberOfOpcSubscriptionsConnected": 0, "NumberOfOpcMonitoredItemsConfigured": 3, "NumberOfOpcMonitoredItemsMonitored": 0, "NumberOfOpcMonitoredItemsToRemove": 0, "MonitoredItemsQueueCapacity": 8192, "MonitoredItemsQueueCount": 0, "EnqueueCount": 13060, "EnqueueFailureCount": 0, "NumberOfEvents": 13060, "SentMessages": 30, "SentLastTime": "2022-02-22T19:03:39.3249082Z", "SentBytes": 3000192, "FailedMessages": 0, "TooLargeCount": 0, "MissedSendIntervalCount": 8, "WorkingSetMB": 118, "DefaultSendIntervalSeconds": 10, "HubMessageSize": 262144, "HubProtocol": 3 } } ``` `Response` (2.8.2) ```json { "status": 200, "payload": [ { "endpoint": { "endpointUrl": "opc.tcp://sandboxhost-637811493394507132:50000", "dataSetWriterGroup": "Asset1", "useSecurity": false, "opcAuthenticationMode": "UsernamePassword", "opcAuthenticationUsername": "Usr" }, "sentMessagesPerSec": 2.6, "ingestionDuration": "{00:00:25.5491702}", "ingressDataChanges": 25, "ingressValueChanges": 103, "ingressBatchBlockBufferSize": 0, "encodingBlockInputSize": 0, "encodingBlockOutputSize": 0, "encoderNotificationsProcessed": 83, "encoderNotificationsDropped": 0, "encoderIoTMessagesProcessed": 2, "encoderAvgNotificationsMessage": 41.5, "encoderAvgIoTMessageBodySize": 6128, "encoderAvgIoTChunkUsage": 1.158034, "estimatedIoTChunksPerDay": 13526.858105160689, "outgressBatchBlockBufferSize": 0, "outgressInputBufferCount": 0, "outgressInputBufferDropped": 0, "outgressIoTMessageCount": 0, "connectionRetries": 0, "opcEndpointConnected": true, "monitoredOpcNodesSucceededCount": 5, "monitoredOpcNodesFailedCount": 0, "ingressEventNotifications": 0, "ingressEvents": 0 } ] } ``` ### UnpublishNodes (UnpublishNodes_V1) If *OpcNodes* is omitted, then all nodes are unpublished and the endpoint is removed. `Request` ```json { "EndpointUrl": "opc.tcp://sandboxhost-637811493394507132:50000", "OpcNodes": [ { "Id":"nsu=http://microsoft.com/Opc/OpcPlc/;s=65e451f1-56f1-ce84-a44f-6addf176beaf" } ] } ``` `Response` (2.5.x) ```json { "status": 200, "payload": [ "Id 'nsu=http://microsoft.com/Opc/OpcPlc/;s=65e451f1-56f1-ce84-a44f-6addf176beaf': tagged for removal" ] } ``` `Response` (2.8.2) ```json { "status": 200, "payload": {} } ``` ### UnpublishAllNodes (UnpublishAllNodes_V1) `Request` ```json { "EndpointUrl": "opc.tcp://sandboxhost-637811493394507132:50000" } ``` `Response` (2.5.x) ```json { "status": 200, "payload": [ "All monitored items in all subscriptions on endpoint 'opc.tcp://sandboxhost-637811493394507132:50000' tagged for removal" ] } ``` `Response` (2.8.2) ```json { "status": 200, "payload": {} } ``` ## OPC Publisher 2.5.x direct methods not supported in 2.8.2 The direct methods not available in OPC Publisher 2.8.2, there are changes required to apply to the applications, which do use them. ### GetDiagnosticLog To retrieve the logs of an IoT Edge module, please check the built-in direct methods provided by IoT Edge `edgeAgent` module [here](https://docs.microsoft.com/azure/iot-edge/how-to-retrieve-iot-edge-logs?view=iotedge-2020-11#retrieve-module-logs). ### GetDiagnosticStartupLog To get diagnostic info of OPC Publisher, please refer to this [link](https://docs.microsoft.com/azure/iot-edge/how-to-edgeagent-direct-method?view=iotedge-2020-11#diagnostic-direct-methods). ### ExitApplication If OPC Publisher is in failed state or other unhealthy behavior, you could trigger `RestartModule` direct method to stop and then restart the module. To learn more about this direct method, please have a look at [this](https://docs.microsoft.com/azure/iot-edge/how-to-edgeagent-direct-method?view=iotedge-2020-11) in-built direct method provided by IoT Edge. ### GetInfo To get the info like version, OS, etc., please refer to the properties provided by IoT Edge which is documented [here](https://docs.microsoft.com/azure/iot-edge/module-edgeagent-edgehub?view=iotedge-2020-11). ================================================ FILE: docs/opc-publisher/observability.md ================================================ # Observability [Home](./readme.md) ## Table Of Contents - [Logging](#logging) - [Runtime diagnostics output](#runtime-diagnostics-output) - [Available metrics](#available-metrics) - [IoT Edge Metrics collector](#iot-edge-metrics-collector) - [OpenTelemetry](#opentelemetry) - [Prometheus](#prometheus) - [Setup](#setup) - [View Prometheus dashboard](#view-prometheus-dashboard) - [View Grafana dashboard](#view-grafana-dashboard) ## Logging Logging can be configured using the `--ll` [command line argument](./commandline.md). It allows to set a desired log level. More fine grained logging can be configured using an appsettings.json file as per .net documentation. It is also possible to enable more detailed logging of the OPC UA stack using the `--sl` option. To get the logs the `iotedge` command line utility can be used. Run the following from the local command line: ```bash iotedge logs -f ``` These logs contain the current state of operation and can be used to narrow down an issue. Additionally, logs from edge modules can be fetched [via direct methods](https://github.com/Azure/iotedge/blob/master/doc/built-in-logs-pull.md) describes how to fetch and upload logs from Edge modules. ## Runtime diagnostics output The OPC Publisher emits metrics through its Prometheus endpoint (`/metrics`). To learn more about how to create a local metrics dashboard for OPC Publisher V2.7, refer to the tutorial [here](./observability.md). To measure the performance of OPC Publisher, the `di` parameter can be used to print metrics to the log in the interval specified (in seconds). Using `--pd=Events` the diagnostics information can instead be emitted to a topic or to IoT Hub. The routing or topic can be configured using the `--dtt` [command line option](./commandline.md). The following table describes the instruments that are collected per writer group and subsequently emitted: | Log line item name | Diagnostic info property name | Description | |-----------------------------------------|-------------------------------------|-------------| | # OPC Publisher Version (Runtime) | n/a | The full version and runtime used by the publisher | | # Time | timestamp | The timestamp of the diagnostics information | | # Ingestion duration | ingestionDuration | How long the data flow inside the publisher has been executing after it was created (either from file or API) | | # Opc endpoint connected? | opcEndpointConnected | Whether the pipeline is currently connected to the OPC UA server endpoint or in a reconnect attempt. | | # Connection retries | connectionRetries | How many times connections to the OPC UA server broke and needed to be reconnected as it pertains to the data flow. | | # Monitored Opc nodes succeeded count | monitoredOpcNodesSucceededCount | How many of the configured monitored items have been established successfully inside the data flow's OPC UA subscription and should be producing data. | | # Monitored Opc nodes failed count | monitoredOpcNodesFailedCount | How many of the configured monitored items inside the data flow failed to be created in the subscription (the logs will provide more information). | | # Subscriptions count | subscriptionsCount (*) | How many subscriptions were created that contain above monitored items. | | # Queued/Minimum request count | publishRequestsRatio (*) | The ratio of currently queued requests to the server as a percentage of the subscription count measured here vs. the overall number of subscriptions in the underlying session (e.g., if the session is shared). | | | minPublishRequestsRatio (*) | The ratio of minimum number of publish requests that should always be queued to the server. | | # Good/Bad Publish request count | goodPublishRequestsRatio (*) | The ratio of currently queued publish requests that are in progress in the server and awaiting a response. | | | badPublishRequestsRatio (*) | The ratio of defunct publish requests which have not been resulting in a publish response from the server. | | # Ingress value changes | ingressValueChanges | The number of value changes inside the OPC UA subscription notifications processed by the data flow. | | # Ingress Events | ingressEvents | The number of events that were part of these OPC UA subscription notifications that were so far processed by the data flow. | | # Received Data Change Notifications | ingressDataChanges | The number of OPC UA subscription notification messages with data value changes that have been received by publisher inside this data flow | | # Received Event Notifications | ingressEventNotifications | The number of OPC UA subscription notification messages with events that have been received by publisher so far inside this data flow | | # Received Keep Alive Notifications | ingressEventNotifications | The number of received OPC UA subscription notification messages that were keep alive messages | | # Generated Cyclic read Notifications | ingressCyclicReads | The number of cyclic read notifications generated from sampling nodes on the client side. Each notification contains the changed value. | | # Generated Heartbeats Notifications | ingressHeartbeats | The number of notifications that contain heartbeats. Each notification contains the heartbeat value. | | # Notification batch buffer size | ingressBatchBlockBufferSize | The number of messages awaiting encoding and sending tot he telemetry message destination inside the data flow pipeline. | | # Encoder input / output size | encodingBlockInputSize | The number of messages awaiting encoding into the output format. | | | encodingBlockOutputSize | The number of messages already encoded and waiting to be sent to the telemetry message destination. | | # Encoder Notif. processed/dropped | encoderNotificationsProcessed | The total number of subscription notifications processed by the encoder stage of the data flow pipeline since the pipeline started. | | | encoderNotificationsDropped | The total number of subscription notifications that were dropped because they could not be encoded, e.g., due to their size being to large to fit into the message. | | # Encoder Network Messages produced | encoderIoTMessagesProcessed | The total number of encoded messages produced by the encoder since the start of the pipeline. | | # Encoder avg Notifications/Message | encoderAvgNotificationsMessage | The average number of subscription notifications that were pressed into a message. | | # Encoder avg Message body size | encoderAvgIoTMessageBodySize | The average size of the message body produced over the course of the pipeline run. | | # Encoder avg Chunk (4 Kb) usage | encoderAvgIoTChunkUsage | The average use of IoT Hub chunks (4k). | | # Estimated Chunks (4 KB) per day | estimatedIoTChunksPerDay | An estimate of how many chunks are used per day by publisher which enables correct sizing of the IoT Hub to avoid data loss due to throttling. | | # Egress Messages queued/dropped | outgressInputBufferCount | The aggregated number of messages waiting in the input buffer of the configured telemetry message destination sinks. | | | outgressInputBufferDropped | The aggregated number of messages that were dropped in any of the configured telemetry message destination sinks. | | # Egress Messages successfully sent | outgressIoTMessageCount | The aggregated number of messages that were sent by all configured telemetry message destination sinks. | | | sentMessagesPerSec | Publisher throughput meaning the number of messages sent to the telemetry message destination (e.g., IoT Hub / Edge Hub) per second | (*) Not exposed through the API ## Available metrics By convention, all instrument names start with _"iiot"_, e.g., `iiot__`. Metrics are collected through the .net Observability infrastructure. For backwards compatibility and to support IoT Edge metrics collector, metrics from OPC Publisher are exposed in Prometheus format on path _/metrics_ on the default HTTP server port (see `-p` [command line argument](./commandline.md). When binding the HTTPS port to 9072 on the host machine, the URL becomes . One can combine information from multiple metrics to understand and paint a bigger picture of the state of the publisher. The following table describes the individual default metrics which are in Prometheus format. | Instrument Name | Dimensions | Description | Type | |-----------------|------------|-------------|------| | iiot_edge_module_start | Edge modules start timestamp with version. Used to calculate uptime, device restarts. | gauge | | iiot_edge_publisher_monitored_items | Total monitored items per subscription | gauge | | iiot_edge_device_reconnected | OPC UA server reconnection count | gauge | | iiot_edge_device_disconnected | OPC UA server disconnection count | gauge | | iiot_edge_reconnected | Edge device reconnection count | gauge | | iiot_edge_disconnected | Edge device disconnection count | gauge | | iiot_edge_publisher_messages_duration | Time taken to send messages from publisher. Used to calculate P50, P90, P95, P99, P99.9 | histogram | | iiot_edge_publisher_value_changes | OPC UA server ValuesChanges delivered for processing | counter | | iiot_edge_publisher_value_changes_per_second | OPC UA server ValuesChanges delivered for processing per second | gauge | | iiot_edge_publisher_heartbeats | OPC Publisher heartbeats delivered for processing and included in the value changes. | counter | | iiot_edge_publisher_cyclicreads | OPC Publisher cyclic reads delivered for processing and included in the value changes. | counter | | iiot_edge_publisher_data_changes | OPC UA server DataChanges delivered for processing | counter | | iiot_edge_publisher_data_changes_per_second | OPC UA server DataChanges delivered for processing | gauge | | iiot_edge_publisher_iothub_queue_size | Queued messages to IoTHub | gauge | | iiot_edge_publisher_iothub_queue_dropped_count | IoTHub dropped messages count | gauge | | iiot_edge_publisher_messages | Messages sent to IoTHub | counter | | iiot_edge_publisher_messages_per_second | Messages sent to IoTHub per second | gauge | | iiot_edge_publisher_connection_retries | Connection retries to OPC UA server | gauge | | iiot_edge_publisher_encoded_notifications | Encoded OPC UA server notifications count | counter | | iiot_edge_publisher_dropped_notifications | Dropped OPC UA server notifications count | counter | | iiot_edge_publisher_processed_messages | Processed IoT messages count | counter | | iiot_edge_publisher_notifications_per_message_average | OPC UA sever notifications per IoT message average | gauge | | iiot_edge_publisher_encoded_message_size_average | Encoded IoT message body size average | gauge | | iiot_edge_publisher_chunk_size_average | IoT Hub chunk size average | gauge | | iiot_edge_publisher_estimated_message_chunks_per_day | Estimated IoT Hub chunks charged per day | gauge | | iiot_edge_publisher_is_connection_ok | Is the endpoint connection ok? | gauge | | iiot_edge_publisher_good_nodes | How many nodes are receiving data for this endpoint? | gauge | | iiot_edge_publisher_bad_nodes | How many nodes are misconfigured for this endpoint? | gauge | You can use the IoT Edge [Metrics Collector](#iot-edge-metrics-collector) module to collect the metrics. Edge modules would be instrumented with [Prometheus](https://github.com/prometheus-net/prometheus-net) metrics. Each module would expose the metrics on a pre-defined port. The `metricscollector` module would use the configuration settings to scrape metrics in a defined interval. It would then push the scraped metrics to Log Analytics Workspace. Using Azure Data Explorer (ADX), we can then query our metrics from workspace. We are creating and deploying an Azure Workbook which would provide insights into the edge modules. This would act as our primary monitoring system for edge modules. ## IoT Edge Metrics collector The metrics collector module pulls metrics exposed by OPC Publisher and pushes them to the Log Analytics workspace. ![metrics](./media/metrics.jpeg) The default configuration to enable scraping metrics is: ```json { "schemaVersion": "1.0", "scrapeFrequencySecs": 120, "metricsFormat": "Json", "syncTarget": "AzureLogAnalytics", "endpoints": { "opcpublisher": "http://opcpublisher/metrics" } } ``` > This assumes the http server in OPC Publisher has not been disabled. Disabling the internal HTTP server also disables the Prometheus endpoint. ## OpenTelemetry It is possible to export all [metrics](#available-metrics), traces and [logs](#logging) to an OpenTelemetry (OTEL) collector. To specify the OTLP GRPC endpoint to export to, use the `--oc` [command line argument](./commandline.md). An example setup using the OpenTelemetry (OTEL) Contrib Collector and Grafana stack can be found in the `/deploy/docker` folder. ## Prometheus OPC Publisher module also exposes all [metrics](#available-metrics) to a Prometheus scraper (at the standard `/metrics` path). For troubleshooting and debugging, a local Grafana dashboard can be configured on Azure IoT Edge. > It is recommended to use the OpenTelemetry collector and expose metrics from the collector to Prometheus. This section shows you how to setup and view OPC Publisher and EdgeHub metrics as bird's eye view and how to quickly drill down into the issues in case of failures. In this tutorial two pre-configured docker images (for Prometheus and Grafana) must be created and deployed as Azure IoT Edge Modules. The Prometheus Module scrapes the metrics from OPC Publisher and EdgeHub, while Grafana is used for visualization of metrics. ### Setup 1. Create and configure [Azure Container Registry](https://docs.microsoft.com/azure/container-registry/container-registry-get-started-portal) to have an admin account enabled. **Registry name** and **password** are needed for pushing the docker images of Prometheus and Grafana. ![01](./media/01.JPG) 2. Create and push images to this ACR: - Download the zip (_metricsdashboard.zip_) located in this folder and extract it. - Navigate to **prometheus** folder as shown: ![02](./media/02.JPG) - Edit _prometheus.yml_ if needed. It defaults to scraping EdgeHub metrics at 9600 and OPC Publisher metrics at 9702. If only OPC Publisher metrics are needed, then remove the scraping config of EdgeHub. - Run _buildimage.bat_ and enter the _registryname_, _password_ and _tagname_ when prompted. It will push the **edgeprometheus** image to container registry. ![03](./media/03.JPG) - Navigate back to the **grafana** folder and run _buildimage.bat_ located in this folder. Enter the same information to push the **edgegrafana** image to ACR. 3. Now go to the portal and verify that the images are present, as shown in the image below. ![04](./media/04.JPG) 4. IoT Edge should now be configured to expose metrics. Navigate to the IoT Edge device to be used and perform the following steps: - Select **Set Modules** to update the configuration - Enter the registry information in the **Container Registry Credentials** so that it can authenticate with the Azure Container Registry. ![05](./media/05.JPG) - Optional: Enable metrics of _edgeHub_ (Note: As of release 1.0.10, metrics are automatically exposed by default on http port **9600** of the EdgeHub) - Select the **Runtime Settings** option and for the EdgeHub and Agent, make sure that the stable version is selected with version 1.0.9.4+ ![06](./media/06.JPG) - Adjust the EdgeHub **Create Options** to include the Exposed Ports directive as shown above. - Add the following environment variables to the EdgeHub. (Not needed for version 1.0.10+) **ExperimentalFeatures__Enabled : true** **ExperimentalFeaturesEnable__Metrics : true** - Save the dialog to complete the runtime adjustments. - Expose port on publisher module: - Navigate to the publisher and expose port **9702** to allow the metrics to be scraped, by adding the exposed ports option in the Container Create Options in the Azure portal. ![07](./media/07.JPG) - Select **Update** to complete the changes made to the OPC publisher module. 5. Now add new modules based on the Prometheus and Grafana images created previously. - Prometheus: - Add a new “IoT Edge Module” from the “+ Add” drop down list. - Add a module named **prometheus** with the image uploaded previously to the Azure Container Registry. ![08](./media/08.JPG) - In the **Container Create Options** expose and bind the Prometheus port 9090. ```json { "Hostname": "prometheus", "ExposedPorts": { "9090/tcp": {} }, "HostConfig": { "PortBindings": { "9090/tcp": [ { "HostPort": 9090 } ] } } } ``` - Click **Update** to complete the changes to the Prometheus module. - Select **Review and Create** and complete the deployment by choosing **Create**. - Grafana: - Add a new “IoT Edge Module” from the “+ Add” drop down list. - Add a module named **grafana** with the image uploaded previously to the Azure Container Registry. ![09](./media/09.JPG) - Update the environment variables to control access to the Grafana dashboard. - GF_SECURITY_ADMIN_USER - the user name you want to use - GF_SECURITY_ADMIN_PASSWORD - a password of your choice - GF_SERVER_ROOT_URL - http://localhost:3000 ![10](./media/10.JPG) - In the **Container Create Options** expose and bind the Grafana port 3000. ```json { "Hostname": "grafana", "ExposedPorts": { "3000/tcp": {} }, "HostConfig": { "PortBindings": { "3000/tcp": [ { "HostPort": 3000 } ] } } } ``` - Click **Update** to complete the changes to the Grafana module. - Select **Review and Create** and complete the deployment by choosing **Create**. - Verify all the modules are running successfully: ![15](./media/15.JPG) ### View Prometheus dashboard - Navigate to the Prometheus dashboard through a web browser on the IoT Edge’s host on port 9090. - host IP or name}:9090/graph - **Note**: When using a VM, make sure to add an inbound rule for port 9090 - Check the target state by navigating to **/targets** ![12](./media/12.JPG) - Metrics can be viewed as shown: ![11](./media/11.JPG) - ![13](./media/13.JPG) ### View Grafana dashboard - Navigate to the Grafana dashboard through a web browser against the edge’s host on port 3000. - http://{edge host IP or name}:3000 - When prompted for a user name and password enter the values entered in the environment variables - **Note**: When using a VM, make sure to add an inbound rule for port 3000 - Prometheus has already been configured as a data source and can now be directly accessed. Prometheus is scraping EdgeHub and OPC Publisher metrics. - Select the dashboards option to view the available dashboards and select “Publisher” to view the pre-configured dashboard as shown below. ![14](./media/14.JPG) - One could easily add/remove more panels to this dashboard as per the needs. ================================================ FILE: docs/opc-publisher/openapi.json ================================================ { "swagger": "2.0", "info": { "title": "OpcPublisher", "description": "", "contact": { "url": "https://www.github.com/Azure/Industrial-IoT" }, "license": { "name": "MIT LICENSE", "url": "https://opensource.org/licenses/MIT" }, "version": "v2" }, "host": "localhost:9071", "schemes": [ "https", "http" ], "paths": { "/v2/pki/{store}/certs": { "get": { "tags": [ "Certificates" ], "summary": "ListCertificates", "description": "Get the certificates in the specified certificate store", "operationId": "ListCertificates", "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "path", "name": "store", "description": "The store to enumerate", "required": true, "type": "string" } ], "responses": { "200": { "description": "The operation was successful.", "schema": { "type": "array", "items": { "$ref": "#/definitions/X509CertificateModel" } } }, "400": { "description": "The passed in information such as store name is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "404": { "description": "Nothing could be found.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An internal error ocurred.", "schema": { "$ref": "#/definitions/ProblemDetails" } } } }, "patch": { "tags": [ "Certificates" ], "summary": "AddCertificate", "description": "Add a certificate to the specified store. The certificate is provided as a pfx/pkcs12 optionally password protected blob.", "operationId": "AddCertificate", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "path", "name": "store", "description": "The store to add the certificate to", "required": true, "type": "string" }, { "in": "query", "name": "password", "description": "The optional password of the pfx", "type": "string" }, { "in": "body", "name": "body", "description": "The pfx encoded certificate.", "required": true, "schema": { "format": "byte", "type": "string" } } ], "responses": { "200": { "description": "The operation was successful." }, "400": { "description": "The passed in information such as store name is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An internal error ocurred.", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/pki/{store}/crls": { "get": { "tags": [ "Certificates" ], "summary": "ListCertificateRevocationLists", "description": "Get the certificates in the specified certificated store", "operationId": "ListCertificateRevocationLists", "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "path", "name": "store", "description": "The store to enumerate", "required": true, "type": "string" } ], "responses": { "200": { "description": "The operation was successful.", "schema": { "type": "array", "items": { "format": "byte", "type": "string" } } }, "400": { "description": "The passed in information such as store name is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "404": { "description": "Nothing could be found.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An internal error ocurred.", "schema": { "$ref": "#/definitions/ProblemDetails" } } } }, "patch": { "tags": [ "Certificates" ], "summary": "AddCertificateRevocationList", "description": "Add a certificate revocation list to the specified store. The certificate revocation list is provided as a der encoded blob.", "operationId": "AddCertificateRevocationList", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "path", "name": "store", "description": "The store to add the certificate to", "required": true, "type": "string" }, { "in": "body", "name": "body", "description": "The pfx encoded certificate.", "required": true, "schema": { "format": "byte", "type": "string" } } ], "responses": { "200": { "description": "The operation was successful." }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An internal error ocurred.", "schema": { "$ref": "#/definitions/ProblemDetails" } } } }, "delete": { "tags": [ "Certificates" ], "summary": "RemoveCertificateRevocationList", "description": "Remove a certificate revocation list from the specified store.", "operationId": "RemoveCertificateRevocationList", "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "path", "name": "store", "description": "The store to add the certificate to", "required": true, "type": "string" } ], "responses": { "200": { "description": "The operation was successful." }, "400": { "description": "The passed in information such store name is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "404": { "description": "Nothing could be found.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An internal error ocurred.", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/pki/trusted/certs": { "post": { "tags": [ "Certificates" ], "summary": "AddCertificateChain", "description": "Add a certificate chain to the specified store. The certificate is provided as a concatenated asn encoded set of certificates with the first the one to add, and the remainder the issuer chain.", "operationId": "AddCertificateChain", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The certificate chain.", "required": true, "schema": { "format": "byte", "type": "string" } } ], "responses": { "200": { "description": "The operation was successful." }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An internal error ocurred.", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/pki/rejected/certs/{thumbprint}/approve": { "post": { "tags": [ "Certificates" ], "summary": "ApproveRejectedCertificate", "description": "Move a rejected certificate from the rejected folder to the trusted folder on the publisher.", "operationId": "ApproveRejectedCertificate", "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "path", "name": "thumbprint", "description": "The thumbprint of the certificate to trust.", "required": true, "type": "string" } ], "responses": { "200": { "description": "The operation was successful." }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An internal error ocurred.", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/pki/https/certs": { "post": { "tags": [ "Certificates" ], "summary": "AddTrustedHttpsCertificateAsync", "description": "Add a certificate chain to the trusted https store. The certificate is provided as a concatenated set of certificates with the first the one to add, and the remainder the issuer chain.", "operationId": "AddTrustedHttpsCertificate", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The certificate chain.", "required": true, "schema": { "format": "byte", "type": "string" } } ], "responses": { "200": { "description": "The operation was successful." }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An internal error ocurred.", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/pki/{store}/certs/{thumbprint}": { "delete": { "tags": [ "Certificates" ], "summary": "RemoveCertificate", "description": "Remove a certificate with the provided thumbprint from the specified store.", "operationId": "RemoveCertificate", "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "path", "name": "store", "description": "The store to add the certificate to", "required": true, "type": "string" }, { "in": "path", "name": "thumbprint", "description": "The thumbprint of the certificate to delete.", "required": true, "type": "string" } ], "responses": { "200": { "description": "The operation was successful." }, "400": { "description": "The passed in information such store name is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "404": { "description": "Nothing could be found.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An internal error ocurred.", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/pki/{store}": { "delete": { "tags": [ "Certificates" ], "summary": "RemoveAll", "description": "Remove all certificates and revocation lists from the specified store.", "operationId": "RemoveAll", "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "path", "name": "store", "description": "The store to add the certificate to", "required": true, "type": "string" } ], "responses": { "200": { "description": "The operation was successful." }, "400": { "description": "The passed in information such store name is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "404": { "description": "Nothing could be found.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An internal error ocurred.", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/configuration/start": { "post": { "tags": [ "Configuration" ], "summary": "PublishStart", "description": "Start publishing values from a node on a server. The group field in the Connection Model can be used to specify a writer group identifier that will be used in the configuration entry that is created from it inside OPC Publisher.", "operationId": "PublishStart", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The server and node to publish.", "required": true, "schema": { "$ref": "#/definitions/PublishStartRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful.", "schema": { "$ref": "#/definitions/PublishStartResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/configuration/stop": { "post": { "tags": [ "Configuration" ], "summary": "PublishStop", "description": "Stop publishing values from a node on the specified server. The group field that was used in the Connection Model to start publishing must also be specified in this connection model.", "operationId": "PublishStop", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The node to stop publishing", "required": true, "schema": { "$ref": "#/definitions/PublishStopRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful.", "schema": { "$ref": "#/definitions/PublishStopResponseModel" } }, "404": { "description": "The item could not be unpublished", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/configuration/bulk": { "post": { "tags": [ "Configuration" ], "summary": "PublishBulk", "description": "Configure node values to publish and unpublish in bulk. The group field in the Connection Model can be used to specify a writer group identifier that will be used in the configuration entry that is created from it inside OPC Publisher.", "operationId": "PublishBulk", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The nodes to publish or unpublish.", "required": true, "schema": { "$ref": "#/definitions/PublishBulkRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful.", "schema": { "$ref": "#/definitions/PublishBulkResponseModel" } }, "404": { "description": "The item could not be unpublished", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/configuration/list": { "post": { "tags": [ "Configuration" ], "summary": "PublishList", "description": "Get all published nodes for a server endpoint. The group field that was used in the Connection Model to start publishing must also be specified in this connection model.", "operationId": "PublishList", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "", "required": true, "schema": { "$ref": "#/definitions/PublishedItemListRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The items were found and returned.", "schema": { "$ref": "#/definitions/PublishedItemListResponseModel" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/configuration/nodes": { "post": { "tags": [ "Configuration" ], "summary": "[PublishNodes](./directmethods.md#publishnodes_v1)", "description": "PublishNodes enables a client to add a set of nodes to be published. Further information is provided in the OPC Publisher documentation.", "operationId": "PublishNodes", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The request contains the nodes to publish.", "required": true, "schema": { "$ref": "#/definitions/PublishedNodesEntryModel" } } ], "responses": { "200": { "description": "The operation was successful.", "schema": { "$ref": "#/definitions/PublishedNodesResponseModel" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/configuration/nodes/unpublish": { "post": { "tags": [ "Configuration" ], "summary": "[UnpublishNodes](./directmethods.md#unpublishnodes_v1)", "description": "UnpublishNodes method enables a client to remove nodes from a previously configured DataSetWriter. Further information is provided in the OPC Publisher documentation.", "operationId": "UnpublishNodes", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The request payload specifying the nodes to unpublish.", "required": true, "schema": { "$ref": "#/definitions/PublishedNodesEntryModel" } } ], "responses": { "200": { "description": "The operation was successful.", "schema": { "$ref": "#/definitions/PublishedNodesResponseModel" } }, "404": { "description": "The nodes could not be unpublished", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/configuration/nodes/unpublish/all": { "post": { "tags": [ "Configuration" ], "summary": "[UnpublishAllNodes](./directmethods.md#unpublishallnodes_v1)", "description": "Unpublish all specified nodes or all nodes in the publisher configuration. Further information is provided in the OPC Publisher documentation.", "operationId": "UnpublishAllNodes", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The request contains the parts of the configuration to remove.", "schema": { "$ref": "#/definitions/PublishedNodesEntryModel" } } ], "responses": { "200": { "description": "The operation was successful.", "schema": { "$ref": "#/definitions/PublishedNodesResponseModel" } }, "404": { "description": "The nodes could not be unpublished", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/configuration": { "patch": { "tags": [ "Configuration" ], "summary": "[AddOrUpdateEndpoints](./directmethods.md#addorupdateendpoints_v1)", "description": "Add or update endpoint configuration and nodes on a server. Further information is provided in the OPC Publisher documentation.", "operationId": "AddOrUpdateEndpoints", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The parts of the configuration to add or update.", "required": true, "schema": { "type": "array", "items": { "$ref": "#/definitions/PublishedNodesEntryModel" } } } ], "responses": { "200": { "description": "The operation was successful.", "schema": { "$ref": "#/definitions/PublishedNodesResponseModel" } }, "404": { "description": "The endpoint was not found to add to", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } }, "get": { "tags": [ "Configuration" ], "summary": "[GetConfiguredEndpoints](./directmethods.md#getconfiguredendpoints_v1)", "description": "Get a list of nodes under a configured endpoint in the configuration. Further information is provided in the OPC Publisher documentation. configuration.", "operationId": "GetConfiguredEndpoints", "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "query", "name": "IncludeNodes", "description": "Include nodes that make up the configuration", "type": "boolean" } ], "responses": { "200": { "description": "The data was retrieved.", "schema": { "$ref": "#/definitions/GetConfiguredEndpointsResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } }, "put": { "tags": [ "Configuration" ], "summary": "[SetConfiguredEndpoints](./directmethods.md#setconfiguredendpoints_v1)", "description": "Enables clients to update the entire published nodes configuration in one call. This includes clearing the existing configuration. Further information is provided in the OPC Publisher documentation. configuration.", "operationId": "SetConfiguredEndpoints", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The new published nodes configuration", "required": true, "schema": { "$ref": "#/definitions/SetConfiguredEndpointsRequestModel" } } ], "responses": { "200": { "description": "The operation was successful." }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/configuration/endpoints/list/nodes": { "post": { "tags": [ "Configuration" ], "summary": "[GetConfiguredNodesOnEndpoint](./directmethods.md#getconfigurednodesonendpoint_v)", "description": "Get the nodes of a published nodes entry object returned earlier from a call to GetConfiguredEndpoints. Further information is provided in the OPC Publisher documentation.", "operationId": "GetConfiguredNodesOnEndpoint", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The entry model from a call to GetConfiguredEndpoints for which to gather the nodes.", "required": true, "schema": { "$ref": "#/definitions/PublishedNodesEntryModel" } } ], "responses": { "200": { "description": "The information was returned.", "schema": { "$ref": "#/definitions/GetConfiguredNodesOnEndpointResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "404": { "description": "The entry was not found.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/configuration/diagnostics": { "post": { "tags": [ "Configuration" ], "summary": "[GetDiagnosticInfo](./directmethods.md#getdiagnosticinfo_v1)", "description": "Get the list of diagnostics info for all dataset writers in the OPC Publisher at the point the call is received. Further information is provided in the OPC Publisher documentation.", "operationId": "GetDiagnosticInfo", "produces": [ "application/json", "application/x-msgpack" ], "responses": { "200": { "description": "The operation was successful.", "schema": { "type": "array", "items": { "$ref": "#/definitions/PublishDiagnosticInfoModel" } } }, "405": { "description": "Call not supported or functionality disabled.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/reset": { "get": { "tags": [ "Diagnostics" ], "summary": "ResetAllConnections", "description": "Can be used to reset all established connections causing a full reconnect and recreate of all subscriptions.", "operationId": "ResetAllConnections", "produces": [ "application/json", "application/x-msgpack" ], "responses": { "200": { "description": "The operation was successful." }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/connections": { "get": { "tags": [ "Diagnostics" ], "summary": "GetActiveConnections", "description": "Get all active connections the publisher is currently managing.", "operationId": "GetActiveConnections", "produces": [ "application/json", "application/x-msgpack" ], "responses": { "200": { "description": "The operation was successful.", "schema": { "type": "array", "items": { "$ref": "#/definitions/ConnectionModel" } } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/diagnostics/connections": { "get": { "tags": [ "Diagnostics" ], "summary": "GetConnectionDiagnostics", "description": "Get diagnostics for all active clients including server and client session diagnostics.", "operationId": "GetConnectionDiagnostics", "produces": [ "application/json", "application/x-msgpack" ], "responses": { "200": { "description": "The operation was successful.", "schema": { "$ref": "#/definitions/ConnectionDiagnosticsModelIAsyncEnumerable" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/diagnostics/channels": { "get": { "tags": [ "Diagnostics" ], "summary": "GetChannelDiagnostics", "description": "Get channel diagnostic information for all connections.", "operationId": "GetChannelDiagnostics", "produces": [ "application/json", "application/x-msgpack" ], "responses": { "200": { "description": "The operation was successful.", "schema": { "type": "array", "items": { "$ref": "#/definitions/ChannelDiagnosticModel" } } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/diagnostics/channels/watch": { "get": { "tags": [ "Diagnostics" ], "summary": "WatchChannelDiagnostics", "description": "Get channel diagnostic information for all connections. The first set of diagnostics are the diagnostics active for all connections, continue reading to get updates.", "operationId": "WatchChannelDiagnostics", "produces": [ "application/json", "application/x-msgpack" ], "responses": { "200": { "description": "The operation was successful.", "schema": { "$ref": "#/definitions/ChannelDiagnosticModelIAsyncEnumerable" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/discovery/findserver": { "post": { "tags": [ "Discovery" ], "summary": "FindServer", "description": "Find servers matching the specified endpoint query spec.", "operationId": "FindServer", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The endpoint query specifying the matching criteria for the discovered endpoints.", "required": true, "schema": { "$ref": "#/definitions/ServerEndpointQueryModel" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/ApplicationRegistrationModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/discovery/register": { "post": { "tags": [ "Discovery" ], "summary": "Register", "description": "Start server registration. The results of the registration are published as events to the default event transport.", "operationId": "Register", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "Contains all information to perform the registration request including discovery url to use.", "required": true, "schema": { "$ref": "#/definitions/ServerRegistrationRequestModel" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "type": "boolean" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/discovery": { "post": { "tags": [ "Discovery" ], "summary": "Discover", "description": "Start network discovery using the provided discovery request configuration. The discovery results are published to the configured default event transport.", "operationId": "Discover", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The discovery configuration to use during the discovery run.", "required": true, "schema": { "$ref": "#/definitions/DiscoveryRequestModel" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "type": "boolean" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/discovery/cancel": { "post": { "tags": [ "Discovery" ], "summary": "Cancel", "description": "Cancel a discovery run that is ongoing using the discovery request token specified in the discover operation.", "operationId": "Cancel", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The information needed to cancel the discovery operation.", "required": true, "schema": { "$ref": "#/definitions/DiscoveryCancelRequestModel" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "type": "boolean" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/filesystem/list": { "post": { "tags": [ "FileSystem" ], "summary": "GetFileSystems", "description": "Gets all file systems of the server.", "operationId": "GetFileSystems", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/ConnectionModel" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/FileSystemObjectModelServiceResponseIAsyncEnumerable" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/filesystem/list/directories": { "post": { "tags": [ "FileSystem" ], "summary": "GetDirectories", "description": "Gets all directories in a directory or file system", "operationId": "GetDirectories", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The directory or filesystem object and connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/FileSystemObjectModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/FileSystemObjectModelIEnumerableServiceResponse" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/filesystem/list/files": { "post": { "tags": [ "FileSystem" ], "summary": "GetFiles", "description": "Get files in a directory or file system on a server.", "operationId": "GetFiles", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The directory or filesystem object and connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/FileSystemObjectModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/FileSystemObjectModelIEnumerableServiceResponse" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/filesystem/parent": { "post": { "tags": [ "FileSystem" ], "summary": "GetParent", "description": "Gets the parent directory or filesystem of a file or directory.", "operationId": "GetParent", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The file or directory object and connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/FileSystemObjectModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/FileSystemObjectModelServiceResponse" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/filesystem/info/file": { "post": { "tags": [ "FileSystem" ], "summary": "GetFileInfo", "description": "Gets the file information for a file on the server.", "operationId": "GetFileInfo", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The file object and connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/FileSystemObjectModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/FileInfoModelServiceResponse" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/filesystem/create/file/{name}": { "post": { "tags": [ "FileSystem" ], "summary": "CreateFile", "description": "Create a new file in a directory or file system on the server", "operationId": "CreateFile", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "path", "name": "name", "description": "The name of the file to create as child under the directory or filesystem provided", "required": true, "type": "string" }, { "in": "body", "name": "body", "description": "The file system or directory object to create the file in and the connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/FileSystemObjectModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/FileSystemObjectModelServiceResponse" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/filesystem/create/directory/{name}": { "post": { "tags": [ "FileSystem" ], "summary": "CreateDirectory", "description": "Create a new directory in an existing file system or directory on the server.", "operationId": "CreateDirectory", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "path", "name": "name", "description": "The name of the directory to create as child under the parent directory provided", "required": true, "type": "string" }, { "in": "body", "name": "body", "description": "The file system or directory object to create the directory in and the connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/FileSystemObjectModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/FileSystemObjectModelServiceResponse" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/filesystem/delete": { "post": { "tags": [ "FileSystem" ], "summary": "DeleteFileSystemObject", "description": "Delete a file or directory in an existing file system on the server.", "operationId": "DeleteFileSystemObject", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The file or directory object to delete and the connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/FileSystemObjectModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/ServiceResultModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/filesystem/delete/{fileOrDirectoryNodeId}": { "post": { "tags": [ "FileSystem" ], "summary": "DeleteFileOrDirectory", "description": "Delete a file or directory in the specified directory or file system.", "operationId": "DeleteFileOrDirectory", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "path", "name": "fileOrDirectoryNodeId", "description": "The node id of the file or directory to delete", "required": true, "type": "string" }, { "in": "body", "name": "body", "description": "The filesystem or directory object in which to delete the specified file or directory and the connection to use for the operation.", "required": true, "schema": { "$ref": "#/definitions/FileSystemObjectModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/ServiceResultModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/filesystem/download": { "get": { "tags": [ "FileSystem" ], "summary": "Download", "description": "Download a file from the server", "operationId": "Download", "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "header", "name": "x-ms-connection", "description": "The connection information identifying the server to connect to perform the operation on. This is passed as json serialized via the header \"x-ms-connection\"", "required": true, "type": "string" }, { "in": "header", "name": "x-ms-target", "description": "The file object to upload. This is passed as json serialized via the header \"x-ms-target\"", "required": true, "type": "string" } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information." }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/filesystem/upload": { "post": { "tags": [ "FileSystem" ], "summary": "Upload", "description": "Upload a file to the server.", "operationId": "Upload", "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "header", "name": "x-ms-connection", "description": "The connection information identifying the server to connect to perform the operation on. This is passed as json serialized via the header \"x-ms-connection\"", "required": true, "type": "string" }, { "in": "header", "name": "x-ms-target", "description": "The file object to upload. This is passed as json serialized via the header \"x-ms-target\"", "required": true, "type": "string" }, { "in": "header", "name": "x-ms-options", "description": "The file write options to use passed as header \"x-ms-mode\"", "required": true, "type": "string" } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information." }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/capabilities": { "post": { "tags": [ "General" ], "summary": "GetServerCapabilities", "description": "Get the capabilities of the server. The server capabilities are exposed as a property of the server object and this method provides a convinient way to retrieve them.", "operationId": "GetServerCapabilities", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The request payload and connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/RequestHeaderModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/ServerCapabilitiesModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/browse/first": { "post": { "tags": [ "General" ], "summary": "Browse", "description": "Browse a a node to discover its references. For more information consult the relevant section of the OPC UA reference specification. The operation might return a continuation token. The continuation token can be used in the BrowseNext method call to retrieve the remainder of references or additional continuation tokens.", "operationId": "Browse", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The request payload and connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/BrowseFirstRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/BrowseFirstResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/browse/next": { "post": { "tags": [ "General" ], "summary": "BrowseNext", "description": "Browse next", "operationId": "BrowseNext", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The request payload and connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/BrowseNextRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/BrowseNextResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/browse": { "post": { "tags": [ "General" ], "summary": "BrowseStream (only HTTP transport)", "description": "Recursively browse a node to discover its references and nodes. The results are returned as a stream of nodes and references. Consult the relevant section of the OPC UA reference specification for more information.", "operationId": "BrowseStream", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The request payload and connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/BrowseStreamRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/BrowseStreamChunkModelIAsyncEnumerable" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/browse/path": { "post": { "tags": [ "General" ], "summary": "BrowsePath", "description": "Translate a start node and browse path into 0 or more target nodes. Allows programming aginst types in OPC UA. For more information consult the relevant section of the OPC UA reference specification.", "operationId": "BrowsePath", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The request payload and connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/BrowsePathRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/BrowsePathResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/read": { "post": { "tags": [ "General" ], "summary": "ValueRead", "description": "Read the value of a variable node. This uses the service detailed in the relevant section of the OPC UA reference specification.", "operationId": "ValueRead", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The request payload and connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/ValueReadRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/ValueReadResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/write": { "post": { "tags": [ "General" ], "summary": "ValueWrite", "description": "Write the value of a variable node. This uses the service detailed in the relevant section of the OPC UA reference specification.", "operationId": "ValueWrite", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The request payload and connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/ValueWriteRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/ValueWriteResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/metadata": { "post": { "tags": [ "General" ], "summary": "GetMetadata", "description": "Get the type metadata for a any node. For data type nodes the response contains the data type metadata including fields. For method nodes the output and input arguments metadata is provided. For objects and object types the instance declaration is returned.", "operationId": "GetMetadata", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The request payload and connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/NodeMetadataRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/NodeMetadataResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/query/compile": { "post": { "tags": [ "General" ], "summary": "CompileQuery", "description": "Compile a query string into a query spec that can be used when setting up event filters on monitored items that monitor events.", "operationId": "CompileQuery", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The compilation request and connection information.", "required": true, "schema": { "$ref": "#/definitions/QueryCompilationRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/QueryCompilationResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/call/$metadata": { "post": { "tags": [ "General" ], "summary": "MethodMetadata", "description": "Get the metadata for calling the method. This API is obsolete. Use the more powerful GetMetadata method instead.", "operationId": "MethodMetadata", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The request payload and connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/MethodMetadataRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/MethodMetadataResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/call": { "post": { "tags": [ "General" ], "summary": "MethodCall", "description": "Call a method on the OPC UA server endpoint with the specified input arguments and received the result in the form of the method output arguments. See the relevant section of the OPC UA reference specification for more information.", "operationId": "MethodCall", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The request payload and connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/MethodCallRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/MethodCallResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/read/attributes": { "post": { "tags": [ "General" ], "summary": "NodeRead", "description": "Read any writeable attribute of a specified node on the server. See the relevant section of the OPC UA reference specification for more information. The attributes supported by the node are dependend on the node class of the node.", "operationId": "NodeRead", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The request payload and connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/ReadRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/ReadResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/write/attributes": { "post": { "tags": [ "General" ], "summary": "NodeWrite", "description": "Write any writeable attribute of a specified node on the server. See the relevant section of the OPC UA reference specification for more information. The attributes supported by the node are dependend on the node class of the node.", "operationId": "NodeWrite", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The request payload and connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/WriteRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/WriteResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/historyread/first": { "post": { "tags": [ "General" ], "summary": "HistoryRead", "description": "Read the history using the respective OPC UA service call. See the relevant section of the OPC UA reference specification for more information. If continuation is returned the remaining results of the operation can be read using the HistoryReadNext method.", "operationId": "HistoryRead", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The request payload and connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/VariantValueHistoryReadRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/VariantValueHistoryReadResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/historyread/next": { "post": { "tags": [ "General" ], "summary": "HistoryReadNext", "description": "Read next history using the respective OPC UA service call. See the relevant section of the OPC UA reference specification for more information.", "operationId": "HistoryReadNext", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The request payload and connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/HistoryReadNextRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/VariantValueHistoryReadNextResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/historyupdate": { "post": { "tags": [ "General" ], "summary": "HistoryUpdate", "description": "Update history using the respective OPC UA service call. Consult the relevant section of the OPC UA reference specification for more information.", "operationId": "HistoryUpdate", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The request payload and connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/VariantValueHistoryUpdateRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/HistoryUpdateResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/certificate": { "post": { "tags": [ "General" ], "summary": "GetEndpointCertificate", "description": "Get a server endpoint's certificate and certificate chain if available.", "operationId": "GetEndpointCertificate", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The server endpoint to get the certificate for.", "required": true, "schema": { "$ref": "#/definitions/EndpointModel" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/X509CertificateChainModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/history/capabilities": { "post": { "tags": [ "General" ], "summary": "HistoryGetServerCapabilities", "description": "Get the historian capabilities exposed as part of the OPC UA server server object.", "operationId": "HistoryGetServerCapabilities", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The request payload and connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/RequestHeaderModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/HistoryServerCapabilitiesModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/history/configuration": { "post": { "tags": [ "General" ], "summary": "HistoryGetConfiguration", "description": "Get the historian configuration of a historizing node in the OPC UA server", "operationId": "HistoryGetConfiguration", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The request payload and connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/HistoryConfigurationRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/HistoryConfigurationResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/test": { "post": { "tags": [ "General" ], "summary": "TestConnection", "description": "Test connection to an opc ua server. The call will not establish any persistent connection but will just allow a client to test that the server is available.", "operationId": "TestConnection", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The request payload and connection information identifying the server to connect to perform the operation on.", "required": true, "schema": { "$ref": "#/definitions/TestConnectionRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/TestConnectionResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/history/events/replace": { "post": { "tags": [ "History" ], "summary": "HistoryReplaceEvents", "description": "Replace events in a timeseries in the historian of the OPC UA server. See the relevant section of the OPC UA reference specification and respective service documentation for more information.", "operationId": "HistoryReplaceEvents", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The events to replace with in the timeseries.", "required": true, "schema": { "$ref": "#/definitions/UpdateEventsDetailsModelHistoryUpdateRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/HistoryUpdateResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/history/events/insert": { "post": { "tags": [ "History" ], "summary": "HistoryInsertEvents", "description": "Insert event entries into a specified timeseries of the historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information.", "operationId": "HistoryInsertEvents", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The events to insert into the timeseries.", "required": true, "schema": { "$ref": "#/definitions/UpdateEventsDetailsModelHistoryUpdateRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/HistoryUpdateResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/history/events/upsert": { "post": { "tags": [ "History" ], "summary": "HistoryUpsertEvents", "description": "Upsert events into a time series of the opc server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information.", "operationId": "HistoryUpsertEvents", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The events to upsert into the timeseries.", "required": true, "schema": { "$ref": "#/definitions/UpdateEventsDetailsModelHistoryUpdateRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/HistoryUpdateResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/history/events/delete": { "post": { "tags": [ "History" ], "summary": "HistoryDeleteEvents", "description": "Delete event entries in a timeseries of the server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information.", "operationId": "HistoryDeleteEvents", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The events to delete in the timeseries.", "required": true, "schema": { "$ref": "#/definitions/DeleteEventsDetailsModelHistoryUpdateRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/HistoryUpdateResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/history/values/delete/attimes": { "post": { "tags": [ "History" ], "summary": "HistoryDeleteValuesAtTimes", "description": "Delete value change entries in a timeseries of the server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information.", "operationId": "HistoryDeleteValuesAtTimes", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The values to delete in the timeseries.", "required": true, "schema": { "$ref": "#/definitions/DeleteValuesAtTimesDetailsModelHistoryUpdateRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/HistoryUpdateResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/history/values/delete/modified": { "post": { "tags": [ "History" ], "summary": "HistoryDeleteModifiedValues", "description": "Delete value change entries in a timeseries of the server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information.", "operationId": "HistoryDeleteModifiedValues", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The values to delete in the timeseries.", "required": true, "schema": { "$ref": "#/definitions/DeleteValuesDetailsModelHistoryUpdateRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/HistoryUpdateResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/history/values/delete": { "post": { "tags": [ "History" ], "summary": "HistoryDeleteValues", "description": "Delete value change entries in a timeseries of the server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information.", "operationId": "HistoryDeleteValues", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The values to delete in the timeseries.", "required": true, "schema": { "$ref": "#/definitions/DeleteValuesDetailsModelHistoryUpdateRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/HistoryUpdateResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/history/values/replace": { "post": { "tags": [ "History" ], "summary": "HistoryReplaceValues", "description": "Replace value change entries in a timeseries of the server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information.", "operationId": "HistoryReplaceValues", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The values to replace with in the timeseries.", "required": true, "schema": { "$ref": "#/definitions/UpdateValuesDetailsModelHistoryUpdateRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/HistoryUpdateResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/history/values/insert": { "post": { "tags": [ "History" ], "summary": "HistoryInsertValues", "description": "Insert value change entries in a timeseries of the server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information.", "operationId": "HistoryInsertValues", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The values to insert into the timeseries.", "required": true, "schema": { "$ref": "#/definitions/UpdateValuesDetailsModelHistoryUpdateRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/HistoryUpdateResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/history/values/upsert": { "post": { "tags": [ "History" ], "summary": "HistoryUpsertValues", "description": "Upsert value change entries in a timeseries of the server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information.", "operationId": "HistoryUpsertValues", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The values to upsert into the timeseries.", "required": true, "schema": { "$ref": "#/definitions/UpdateValuesDetailsModelHistoryUpdateRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/HistoryUpdateResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/history/events/read/first": { "post": { "tags": [ "History" ], "summary": "HistoryReadEvents", "description": "Read an event timeseries inside the OPC UA server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information.", "operationId": "HistoryReadEvents", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The events to read in the timeseries.", "required": true, "schema": { "$ref": "#/definitions/ReadEventsDetailsModelHistoryReadRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/HistoricEventModelArrayHistoryReadResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/history/events/read/next": { "post": { "tags": [ "History" ], "summary": "HistoryReadEventsNext", "description": "Continue reading an event timeseries inside the OPC UA server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information.", "operationId": "HistoryReadEventsNext", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The continuation from a previous read request.", "required": true, "schema": { "$ref": "#/definitions/HistoryReadNextRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/HistoricEventModelArrayHistoryReadNextResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/history/values/read/first": { "post": { "tags": [ "History" ], "summary": "HistoryReadValues", "description": "Read a data change timeseries inside the OPC UA server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information.", "operationId": "HistoryReadValues", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The values to read in the timeseries.", "required": true, "schema": { "$ref": "#/definitions/ReadValuesDetailsModelHistoryReadRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/HistoricValueModelArrayHistoryReadResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/history/values/read/first/attimes": { "post": { "tags": [ "History" ], "summary": "HistoryReadValuesAtTimes", "description": "Read parts of a timeseries inside the OPC UA server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information.", "operationId": "HistoryReadValuesAtTimes", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The values to read in the timeseries.", "required": true, "schema": { "$ref": "#/definitions/ReadValuesAtTimesDetailsModelHistoryReadRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/HistoricValueModelArrayHistoryReadResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/history/values/read/first/processed": { "post": { "tags": [ "History" ], "summary": "HistoryReadProcessedValues", "description": "Read processed timeseries data inside the OPC UA server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information.", "operationId": "HistoryReadProcessedValues", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The values to read in the timeseries.", "required": true, "schema": { "$ref": "#/definitions/ReadProcessedValuesDetailsModelHistoryReadRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/HistoricValueModelArrayHistoryReadResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/history/values/read/first/modified": { "post": { "tags": [ "History" ], "summary": "HistoryReadModifiedValues", "description": "Read modified changes in a timeseries inside the OPC UA server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information.", "operationId": "HistoryReadModifiedValues", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The values to read in the timeseries.", "required": true, "schema": { "$ref": "#/definitions/ReadModifiedValuesDetailsModelHistoryReadRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/HistoricValueModelArrayHistoryReadResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/history/values/read/next": { "post": { "tags": [ "History" ], "summary": "HistoryReadValuesNext", "description": "Continue reading a timeseries inside the OPC UA server historian. See the relevant section of the OPC UA reference specification and respective service documentation for more information.", "operationId": "HistoryReadValuesNext", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The continuation token from a previous read operation.", "required": true, "schema": { "$ref": "#/definitions/HistoryReadNextRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/HistoricValueModelArrayHistoryReadNextResponseModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/history/values/read": { "post": { "tags": [ "History" ], "summary": "HistoryStreamValues (only HTTP transport)", "description": "Read an entire timeseries from an OPC UA server historian as stream. See the relevant section of the OPC UA reference specification and respective service documentation for more information.", "operationId": "HistoryStreamValues", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The values to read in the timeseries.", "required": true, "schema": { "$ref": "#/definitions/ReadValuesDetailsModelHistoryReadRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/HistoricValueModelIAsyncEnumerable" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/history/values/read/modified": { "post": { "tags": [ "History" ], "summary": "HistoryStreamModifiedValues (only HTTP transport)", "description": "Read an entire modified series from an OPC UA server historian as stream. See the relevant section of the OPC UA reference specification and respective service documentation for more information.", "operationId": "HistoryStreamModifiedValues", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The values to read in the timeseries.", "required": true, "schema": { "$ref": "#/definitions/ReadModifiedValuesDetailsModelHistoryReadRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/HistoricValueModelIAsyncEnumerable" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/history/values/read/attimes": { "post": { "tags": [ "History" ], "summary": "HistoryStreamValuesAtTimes (only HTTP transport)", "description": "Read specific timeseries data from an OPC UA server historian as stream. See the relevant section of the OPC UA reference specification and respective service documentation for more information.", "operationId": "HistoryStreamValuesAtTimes", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The values to read in the timeseries.", "required": true, "schema": { "$ref": "#/definitions/ReadValuesAtTimesDetailsModelHistoryReadRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/HistoricValueModelIAsyncEnumerable" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/history/values/read/processed": { "post": { "tags": [ "History" ], "summary": "HistoryStreamProcessedValues (only HTTP transport)", "description": "Read processed timeseries data from an OPC UA server historian as stream. See the relevant section of the OPC UA reference specification and respective service documentation for more information.", "operationId": "HistoryStreamProcessedValues", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The values to read in the timeseries.", "required": true, "schema": { "$ref": "#/definitions/ReadProcessedValuesDetailsModelHistoryReadRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/HistoricValueModelIAsyncEnumerable" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/history/events/read": { "post": { "tags": [ "History" ], "summary": "HistoryStreamEvents (only HTTP transport)", "description": "Read an entire event timeseries from an OPC UA server historian as stream. See the relevant section of the OPC UA reference specification and respective service documentation for more information.", "operationId": "HistoryStreamEvents", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The events to read in the timeseries.", "required": true, "schema": { "$ref": "#/definitions/ReadEventsDetailsModelHistoryReadRequestModelRequestEnvelope" } } ], "responses": { "200": { "description": "The operation was successful or the response payload contains relevant error information.", "schema": { "$ref": "#/definitions/HistoricEventModelIAsyncEnumerable" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/writer": { "put": { "tags": [ "Writer" ], "summary": "CreateOrUpdateDataSetWriterEntry", "description": "Create a published nodes entry for a specific writer group and dataset writer. The entry must specify a unique writer group and dataset writer id. A null value is treated as empty string. If the entry is found it is replaced, if it is not found, it is created. If more than one entry is found with the same writer group and writer id an error is returned. The writer entry provided must include at least one node which will be the initial set. All nodes must specify a unique dataSetFieldId. A null value is treated as empty string. Publishing intervals at node level are also not supported and generate an error. Publishing intervals must be configured at the data set writer level.", "operationId": "CreateOrUpdateDataSetWriterEntry", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The entry to create for the writer", "required": true, "schema": { "$ref": "#/definitions/PublishedNodesEntryModel" } } ], "responses": { "200": { "description": "The item was created" }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "403": { "description": "A unique item could not be found to update.", "schema": { "$ref": "#/definitions/ProblemDetails" } } } }, "post": { "tags": [ "Writer" ], "summary": "ExpandAndCreateOrUpdateDataSetWriterEntries", "description": "Create a series of published nodes entries using the provided entry as template. The entry is expanded using expansion configuration provided. Expanded entries are returned one by one with error information if any. The configuration is also saved in the local configuration store. The server must be online and accessible for the expansion to work.", "operationId": "ExpandAndCreateOrUpdateDataSetWriterEntries", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The entry to create for the writer and node expansion configuration to use", "required": true, "schema": { "$ref": "#/definitions/PublishedNodeExpansionModelPublishedNodesEntryRequestModel" } } ], "responses": { "200": { "description": "The item was created", "schema": { "$ref": "#/definitions/PublishedNodesEntryModelServiceResponseIAsyncEnumerable" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "403": { "description": "A unique item could not be found to update.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/writer/{dataSetWriterGroup}/{dataSetWriterId}": { "get": { "tags": [ "Writer" ], "summary": "GetDataSetWriterEntry", "description": "Get the published nodes entry for a specific writer group and dataset writer. Dedicated errors are returned if no, or no unique entry could be found. The entry does not contain the nodes. Nodes can be retrieved using the GetNodes API.", "operationId": "GetDataSetWriterEntry", "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "path", "name": "dataSetWriterGroup", "description": "The writer group name of the entry", "required": true, "type": "string" }, { "in": "path", "name": "dataSetWriterId", "description": "The data set writer identifer of the entry", "required": true, "type": "string" } ], "responses": { "200": { "description": "The item was found", "schema": { "$ref": "#/definitions/PublishedNodesEntryModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "403": { "description": "There is no unique item present.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "404": { "description": "The item was not found", "schema": { "$ref": "#/definitions/ProblemDetails" } } } }, "put": { "tags": [ "Writer" ], "summary": "AddOrUpdateNode", "description": "Add a node to a dedicated data set writer in a writer group. A node must have a unique DataSetFieldId. If the field already exists, the node is updated. If a node does not have a dataset field id an error is returned. Publishing intervals at node level are also not supported and generate an error. Publishing intervals must be configured at the data set writer level.", "operationId": "AddOrUpdateNode", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "path", "name": "dataSetWriterGroup", "description": "The writer group name of the entry", "required": true, "type": "string" }, { "in": "path", "name": "dataSetWriterId", "description": "The data set writer identifer of the entry", "required": true, "type": "string" }, { "in": "query", "name": "insertAfterFieldId", "description": "Field after which to insert the nodes. If not specified, nodes are added at the end of the entry", "type": "string" }, { "in": "body", "name": "body", "description": "Node to add or update", "required": true, "schema": { "$ref": "#/definitions/OpcNodeModel" } } ], "responses": { "200": { "description": "The item was added" }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "403": { "description": "A unique item could not be found to update.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "404": { "description": "An entry was not found to add the node to", "schema": { "$ref": "#/definitions/ProblemDetails" } } } }, "delete": { "tags": [ "Writer" ], "summary": "RemoveDataSetWriterEntry", "description": "Remove the published nodes entry for a specific data set writer in a writer group. Dedicated errors are returned if no, or no unique entry could be found.", "operationId": "RemoveDataSetWriterEntry", "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "path", "name": "dataSetWriterGroup", "description": "The writer group name of the entry", "required": true, "type": "string" }, { "in": "path", "name": "dataSetWriterId", "description": "The data set writer identifer of the entry", "required": true, "type": "string" }, { "in": "query", "name": "force", "description": "Force delete all writers even if more than one were found. Does not error when none were found.", "type": "boolean", "default": false } ], "responses": { "200": { "description": "The entry was removed" }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "403": { "description": "A unique item could not be found to remove.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "404": { "description": "The entry to remove was not found", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/writer/{dataSetWriterGroup}/{dataSetWriterId}/add": { "post": { "tags": [ "Writer" ], "summary": "AddOrUpdateNodes", "description": "Add Nodes to a dedicated data set writer in a writer group. Each node must have a unique DataSetFieldId. If the field already exists, the node is updated. If a node does not have a dataset field id an error is returned. Publishing intervals at node level are also not supported and generate an error. Publishing intervals must be configured at the data set writer level.", "operationId": "AddOrUpdateNodes", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "path", "name": "dataSetWriterGroup", "description": "The writer group name of the entry", "required": true, "type": "string" }, { "in": "path", "name": "dataSetWriterId", "description": "The data set writer identifer of the entry", "required": true, "type": "string" }, { "in": "query", "name": "insertAfterFieldId", "description": "Field after which to insert the nodes. If not specified, nodes are added at the end of the entry", "type": "string" }, { "in": "body", "name": "body", "description": "Nodes to add or update", "required": true, "schema": { "type": "array", "items": { "$ref": "#/definitions/OpcNodeModel" } } } ], "responses": { "200": { "description": "The items were added" }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "403": { "description": "A unique entry could not be found to add to.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "404": { "description": "The entry was not found", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/writer/{dataSetWriterGroup}/{dataSetWriterId}/remove": { "post": { "tags": [ "Writer" ], "summary": "RemoveNodes", "description": "Remove Nodes that match the provided data set field ids from a data set writer in a writer group. If one of the fields is not found, no error is returned, however, if all fields are not found an error is returned.", "operationId": "RemoveNodes", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "path", "name": "dataSetWriterGroup", "description": "The writer group name of the entry", "required": true, "type": "string" }, { "in": "path", "name": "dataSetWriterId", "description": "The data set writer identifer of the entry", "required": true, "type": "string" }, { "in": "body", "name": "body", "description": "The identifiers of the fields to remove", "required": true, "schema": { "type": "array", "items": { "type": "string" } } } ], "responses": { "200": { "description": "Some or all items were removed" }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "403": { "description": "A unique item could not be found to remove from.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "404": { "description": "The entry or all items to remove were not found", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/writer/{dataSetWriterGroup}/{dataSetWriterId}/{dataSetFieldId}": { "delete": { "tags": [ "Writer" ], "summary": "RemoveNode", "description": "Remove a node with the specified data set field id from a data set writer in a writer group. If the field is not found, an error is returned.", "operationId": "RemoveNode", "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "path", "name": "dataSetWriterGroup", "description": "The writer group name of the entry", "required": true, "type": "string" }, { "in": "path", "name": "dataSetWriterId", "description": "The data set writer identifer of the entry", "required": true, "type": "string" }, { "in": "path", "name": "dataSetFieldId", "description": "Identifier of the field to remove", "required": true, "type": "string" } ], "responses": { "200": { "description": "The item was removed" }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "403": { "description": "A unique item could not be found to remove from.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "404": { "description": "The entry or item to remove was not found", "schema": { "$ref": "#/definitions/ProblemDetails" } } } }, "get": { "tags": [ "Writer" ], "summary": "GetNode", "description": "Get a node from a dataset in a writer group. Dedicated errors are returned if no, or no unique entry could be found, or the node does not exist.", "operationId": "GetNode", "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "path", "name": "dataSetWriterGroup", "description": "The writer group name of the entry", "required": true, "type": "string" }, { "in": "path", "name": "dataSetWriterId", "description": "The data set writer identifer of the entry", "required": true, "type": "string" }, { "in": "path", "name": "dataSetFieldId", "description": "The data set field id of the node to return", "required": true, "type": "string" } ], "responses": { "200": { "description": "The item was retrieved", "schema": { "$ref": "#/definitions/OpcNodeModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "403": { "description": "A unique item could not be found to get a node from.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "404": { "description": "The entry or item was not found", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/writer/{dataSetWriterGroup}/{dataSetWriterId}/nodes": { "get": { "tags": [ "Writer" ], "summary": "GetNodes", "description": "Get Nodes from a data set writer in a writer group. The nodes can optionally be offset from a previous last node identified by the dataSetFieldId and pageanated by the pageSize. If the dataSetFieldId is not found, an empty list is returned. If the dataSetFieldId is not specified, the first page is returned.", "operationId": "GetNodes", "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "path", "name": "dataSetWriterGroup", "description": "The writer group name of the entry", "required": true, "type": "string" }, { "in": "path", "name": "dataSetWriterId", "description": "The data set writer identifer of the entry", "required": true, "type": "string" }, { "in": "query", "name": "lastDataSetFieldId", "description": "the field id after which to start the page. If not specified, nodes from the beginning are returned.", "type": "string" }, { "in": "query", "name": "pageSize", "description": "Number of nodes to return", "type": "integer", "format": "int32" } ], "responses": { "200": { "description": "The items were found", "schema": { "type": "array", "items": { "$ref": "#/definitions/OpcNodeModel" } } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "403": { "description": "A unique item could not be found to get nodes from.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "404": { "description": "The entry was not found", "schema": { "$ref": "#/definitions/ProblemDetails" } } }, "x-ms-pageable": { "nextLinkName": "lastDataSetFieldId" } } }, "/v2/writer/expand": { "post": { "tags": [ "Writer" ], "summary": "ExpandWriter", "description": "Expands the provided nodes in the entry to a series of published node entries. The provided entry is used template. The entry is expanded using expansion configuration provided. Expanded entries are returned one by one with error information if any. The configuration is not updated but the resulting entries can be modified and later saved in the configuration using the configuration API. The server must be online and accessible for the expansion to work.", "operationId": "ExpandWriter", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The entry to expand and the node expansion configuration to use. If no configuration is provided a default configuration is used which and no error entries are returned.", "required": true, "schema": { "$ref": "#/definitions/PublishedNodeExpansionModelPublishedNodesEntryRequestModel" } } ], "responses": { "200": { "description": "The item was created", "schema": { "$ref": "#/definitions/PublishedNodesEntryModelServiceResponseIAsyncEnumerable" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "403": { "description": "A unique item could not be found to update.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/writer/assets/create": { "post": { "tags": [ "Writer" ], "summary": "CreateOrUpdateAsset (With binary configuration)", "description": "Creates an asset from the entry in the request and the configuration provided in the Web of Things Asset configuration byte buffer. The entry must contain a data set name which will be used as the asset name. The writer can stay empty. It will be set to the asset id on successful return. The server must support the WoT profile per . The asset will be created and the configuration updated to reference it. A wait time can be provided as optional query parameter to wait until the server has settled after uploading the configuration.", "operationId": "CreateOrUpdateAsset2", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The contains the entry and WoT file to configure the server to expose the asset.", "required": true, "schema": { "$ref": "#/definitions/ByteArrayPublishedNodeCreateAssetRequestModel" } } ], "responses": { "200": { "description": "The asset was created", "schema": { "$ref": "#/definitions/PublishedNodesEntryModelServiceResponse" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "403": { "description": "Forbidden", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/writer/assets": { "post": { "tags": [ "Writer" ], "summary": "CreateOrUpdateAsset", "description": "Creates an asset from the entry in the request and the configuration provided in the Web of Things Asset json configuration property. The entry must contain a data set name which will be used as the asset name. The writer can stay empty. It will be set to the asset id on successful return. The server must support the WoT profile per . The asset will be created and the configuration updated to reference it. A wait time can be provided as optional query parameter to wait until the server has settled after uploading the configuration.", "operationId": "CreateOrUpdateAsset", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The contains the entry and WoT file to configure the server to expose the asset.", "required": true, "schema": { "$ref": "#/definitions/VariantValuePublishedNodeCreateAssetRequestModel" } } ], "responses": { "200": { "description": "The asset was created", "schema": { "$ref": "#/definitions/PublishedNodesEntryModelServiceResponse" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "403": { "description": "Forbidden", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/writer/assets/list": { "post": { "tags": [ "Writer" ], "summary": "GetAllAssets", "description": "Get a list of entries representing the assets in the server. This will not touch the configuration, it will obtain the list from the server. If the server does not support the result will be empty.", "operationId": "GetAllAssets", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "The entry to use to list the assets with the optional header information used when invoking services on the server.", "required": true, "schema": { "$ref": "#/definitions/RequestHeaderModelPublishedNodesEntryRequestModel" } } ], "responses": { "200": { "description": "Successfully completed the listing", "schema": { "$ref": "#/definitions/PublishedNodesEntryModelServiceResponseIAsyncEnumerable" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "403": { "description": "Forbidden", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } }, "/v2/writer/assets/delete": { "post": { "tags": [ "Writer" ], "summary": "DeleteAsset", "description": "Delete the asset referenced by the entry in the request. The entry must contain the asset id to delete. The asset id is the data set writer id. The entry must also contain the writer group id or deletion of the asset in the configuration will fail before the asset is deleted. The server must support WoT connectivity profile per . First the entry in the configuration will be deleted and then the asset on the server. If deletion of the asset in the configuration fails it will not be deleted in the server. An optional request option force can be used to force the deletion of the asset in the server regardless of the failure to delete the entry in the configuration.", "operationId": "DeleteAsset", "consumes": [ "application/json", "application/x-msgpack" ], "produces": [ "application/json", "application/x-msgpack" ], "parameters": [ { "in": "body", "name": "body", "description": "Request that contains the entry of the asset that should be deleted.", "required": true, "schema": { "$ref": "#/definitions/PublishedNodeDeleteAssetRequestModel" } } ], "responses": { "200": { "description": "The asset was deleted successfully", "schema": { "$ref": "#/definitions/ServiceResultModel" } }, "400": { "description": "The passed in information is invalid", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "403": { "description": "Forbidden", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "408": { "description": "The operation timed out.", "schema": { "$ref": "#/definitions/ProblemDetails" } }, "500": { "description": "An unexpected error occurred", "schema": { "$ref": "#/definitions/ProblemDetails" } } } } } }, "definitions": { "AdditionalData": { "description": "Flags that are set by the historian when\r\nreturning archived values.", "enum": [ "None", "Partial", "ExtraData", "MultipleValues" ], "type": "string", "x-ms-enum": { "name": "AdditionalData", "modelAsString": false } }, "AggregateConfigurationModel": { "description": "Aggregate configuration", "type": "object", "properties": { "treatUncertainAsBad": { "description": "Whether to treat uncertain as bad", "type": "boolean" }, "percentDataBad": { "format": "int32", "description": "Percent of data that is bad", "type": "integer" }, "percentDataGood": { "format": "int32", "description": "Percent of data that is good", "type": "integer" }, "useSlopedExtrapolation": { "description": "Whether to use sloped extrapolation.", "type": "boolean" } }, "additionalProperties": false }, "ApplicationInfoModel": { "description": "Application info model", "required": [ "applicationId", "applicationUri" ], "type": "object", "properties": { "applicationId": { "description": "Unique application id", "type": "string" }, "applicationType": { "$ref": "#/definitions/ApplicationType" }, "applicationUri": { "description": "Unique application uri", "type": "string" }, "productUri": { "description": "Product uri", "type": "string" }, "applicationName": { "description": "Default name of application", "type": "string" }, "locale": { "description": "Locale of default name - defaults to \"en\"", "type": "string" }, "localizedNames": { "description": "Localized Names of application keyed on locale", "type": "object", "additionalProperties": { "type": "string" } }, "capabilities": { "description": "The capabilities advertised by the server.", "type": "array", "items": { "type": "string" } }, "discoveryUrls": { "description": "Discovery urls of the server", "type": "array", "items": { "type": "string" } }, "discoveryProfileUri": { "description": "Discovery profile uri", "type": "string" }, "gatewayServerUri": { "description": "Gateway server uri", "type": "string" }, "hostAddresses": { "description": "Host addresses of server application or null", "type": "array", "items": { "type": "string" } }, "siteId": { "description": "Site of the application", "type": "string", "example": "productionlineA" }, "discovererId": { "description": "Discoverer that registered the application", "type": "string" }, "notSeenSince": { "format": "date-time", "description": "Last time application was seen if not visible", "type": "string" }, "created": { "$ref": "#/definitions/OperationContextModel" }, "updated": { "$ref": "#/definitions/OperationContextModel" } }, "additionalProperties": false }, "ApplicationRegistrationModel": { "description": "Application with optional list of endpoints", "required": [ "application" ], "type": "object", "properties": { "application": { "$ref": "#/definitions/ApplicationInfoModel" }, "endpoints": { "description": "List of endpoints for it", "type": "array", "items": { "$ref": "#/definitions/EndpointRegistrationModel" } } }, "additionalProperties": false }, "ApplicationType": { "description": "Application type", "enum": [ "Server", "Client", "ClientAndServer", "DiscoveryServer" ], "type": "string", "x-ms-enum": { "name": "ApplicationType", "modelAsString": false } }, "AttributeReadRequestModel": { "description": "Attribute to read", "required": [ "attribute", "nodeId" ], "type": "object", "properties": { "nodeId": { "description": "Node to read from or write to (mandatory)", "minLength": 1, "type": "string" }, "attribute": { "$ref": "#/definitions/NodeAttribute" } }, "additionalProperties": false }, "AttributeReadResponseModel": { "description": "Attribute value read", "required": [ "value" ], "type": "object", "properties": { "value": { "description": "Attribute value", "type": "object" }, "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "AttributeWriteRequestModel": { "description": "Attribute and value to write to it", "required": [ "attribute", "nodeId", "value" ], "type": "object", "properties": { "nodeId": { "description": "Node to write to (mandatory)", "minLength": 1, "type": "string" }, "attribute": { "$ref": "#/definitions/NodeAttribute" }, "value": { "description": "Value to write (mandatory)", "type": "object" } }, "additionalProperties": false }, "AttributeWriteResponseModel": { "description": "Attribute write result", "type": "object", "properties": { "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "AuthenticationMethodModel": { "description": "Authentication Method model", "required": [ "id" ], "type": "object", "properties": { "id": { "description": "Method id", "minLength": 1, "type": "string" }, "credentialType": { "$ref": "#/definitions/CredentialType" }, "securityPolicy": { "description": "Security policy to use when passing credential.", "type": "string" }, "configuration": { "description": "Method specific configuration", "type": "object" } }, "additionalProperties": false }, "BrowseDirection": { "description": "Direction to browse", "enum": [ "Forward", "Backward", "Both" ], "type": "string", "x-ms-enum": { "name": "BrowseDirection", "modelAsString": false } }, "BrowseFirstRequestModel": { "description": "Browse request model", "type": "object", "properties": { "nodeId": { "description": "Node to browse.\r\n(defaults to root folder).", "type": "string" }, "direction": { "$ref": "#/definitions/BrowseDirection" }, "view": { "$ref": "#/definitions/BrowseViewModel" }, "referenceTypeId": { "description": "Reference types to browse.\r\n(default: hierarchical).", "type": "string" }, "noSubtypes": { "description": "Whether to include subtypes of the reference type.\r\n(default is false)", "type": "boolean" }, "maxReferencesToReturn": { "format": "int64", "description": "Max number of references to return. There might\r\nbe less returned as this is up to the client\r\nrestrictions. Set to 0 to return no references\r\nor target nodes.\r\n(default is decided by client e.g. 60)", "type": "integer" }, "targetNodesOnly": { "description": "Whether to collapse all references into a set of\r\nunique target nodes and not show reference\r\ninformation.\r\n(default is false)", "type": "boolean" }, "readVariableValues": { "description": "Whether to read variable values on target nodes.\r\n(default is false)", "type": "boolean" }, "nodeClassFilter": { "description": "Filter returned target nodes by only returning\r\nnodes that have classes defined in this array.\r\n(default: null - all targets are returned)", "enum": [ "Object", "Variable", "Method", "ObjectType", "VariableType", "ReferenceType", "DataType", "View" ], "type": "string", "items": { "$ref": "#/definitions/NodeClass" }, "x-ms-enum": { "name": "NodeClass", "modelAsString": false } }, "header": { "$ref": "#/definitions/RequestHeaderModel" }, "nodeIdsOnly": { "description": "Whether to only return the raw node id\r\ninformation and not read the target node.\r\n(default is false)", "type": "boolean" } }, "additionalProperties": false }, "BrowseFirstRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/BrowseFirstRequestModel" } }, "additionalProperties": false }, "BrowseFirstResponseModel": { "description": "Browse response model", "required": [ "node", "references" ], "type": "object", "properties": { "node": { "$ref": "#/definitions/NodeModel" }, "references": { "description": "References returned", "type": "array", "items": { "$ref": "#/definitions/NodeReferenceModel" } }, "continuationToken": { "description": "Continuation token if more results pending.", "type": "string" }, "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "BrowseNextRequestModel": { "description": "Request node browsing continuation", "required": [ "continuationToken" ], "type": "object", "properties": { "continuationToken": { "description": "Continuation token from previews browse request.\r\n(mandatory)", "minLength": 1, "type": "string" }, "abort": { "description": "Whether to abort browse and release.\r\n(default: false)", "type": "boolean" }, "targetNodesOnly": { "description": "Whether to collapse all references into a set of\r\nunique target nodes and not show reference\r\ninformation.\r\n(default is false)", "type": "boolean" }, "readVariableValues": { "description": "Whether to read variable values on target nodes.\r\n(default is false)", "type": "boolean" }, "header": { "$ref": "#/definitions/RequestHeaderModel" }, "nodeIdsOnly": { "description": "Whether to only return the raw node id\r\ninformation and not read the target node.\r\n(default is false)", "type": "boolean" } }, "additionalProperties": false }, "BrowseNextRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/BrowseNextRequestModel" } }, "additionalProperties": false }, "BrowseNextResponseModel": { "description": "Result of node browse continuation", "required": [ "references" ], "type": "object", "properties": { "references": { "description": "References returned", "type": "array", "items": { "$ref": "#/definitions/NodeReferenceModel" } }, "continuationToken": { "description": "Continuation token if more results pending.", "type": "string" }, "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "BrowsePathRequestModel": { "description": "Browse nodes by path", "required": [ "browsePaths" ], "type": "object", "properties": { "nodeId": { "description": "Node to browse from (defaults to root folder).", "type": "string" }, "browsePaths": { "description": "The paths to browse from node.\r\n(mandatory)", "type": "array", "items": { "type": "array", "items": { "type": "string" } } }, "readVariableValues": { "description": "Whether to read variable values on target nodes.\r\n(default is false)", "type": "boolean" }, "header": { "$ref": "#/definitions/RequestHeaderModel" }, "nodeIdsOnly": { "description": "Whether to only return the raw node id\r\ninformation and not read the target node.\r\n(default is false)", "type": "boolean" } }, "additionalProperties": false }, "BrowsePathRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/BrowsePathRequestModel" } }, "additionalProperties": false }, "BrowsePathResponseModel": { "description": "Result of node browse continuation", "type": "object", "properties": { "targets": { "description": "Targets", "type": "array", "items": { "$ref": "#/definitions/NodePathTargetModel" } }, "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "BrowseStreamChunkModelIAsyncEnumerable": { "type": "object", "additionalProperties": false }, "BrowseStreamRequestModel": { "description": "Browse stream request model", "type": "object", "properties": { "header": { "$ref": "#/definitions/RequestHeaderModel" }, "nodeId": { "description": "Start nodes to browse.\r\n(defaults to root folder).", "type": "array", "items": { "type": "string" } }, "direction": { "$ref": "#/definitions/BrowseDirection" }, "view": { "$ref": "#/definitions/BrowseViewModel" }, "referenceTypeId": { "description": "Reference types to browse.\r\n(default: hierarchical).", "type": "string" }, "noSubtypes": { "description": "Whether to include subtypes of the reference type.\r\n(default is false)", "type": "boolean" }, "readVariableValues": { "description": "Whether to read variable values on source nodes.\r\n(default is false)", "type": "boolean" }, "noRecurse": { "description": "Whether to not browse recursively\r\n(default is false)", "type": "boolean" }, "nodeClassFilter": { "description": "Filter returned target nodes by only returning\r\nnodes that have classes defined in this array.\r\n(default: null - all targets are returned)", "enum": [ "Object", "Variable", "Method", "ObjectType", "VariableType", "ReferenceType", "DataType", "View" ], "type": "string", "items": { "$ref": "#/definitions/NodeClass" }, "x-ms-enum": { "name": "NodeClass", "modelAsString": false } } }, "additionalProperties": false }, "BrowseStreamRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/BrowseStreamRequestModel" } }, "additionalProperties": false }, "BrowseViewModel": { "description": "View to browse", "required": [ "viewId" ], "type": "object", "properties": { "viewId": { "description": "Node of the view to browse", "minLength": 1, "type": "string" }, "version": { "format": "int64", "description": "Browses specific version of the view.", "type": "integer" }, "timestamp": { "format": "date-time", "description": "Browses at or before this timestamp.", "type": "string" } }, "additionalProperties": false }, "ByteArrayPublishedNodeCreateAssetRequestModel": { "description": "Request to create an asset in the configuration api", "required": [ "configuration", "entry" ], "type": "object", "properties": { "header": { "$ref": "#/definitions/RequestHeaderModel" }, "entry": { "$ref": "#/definitions/PublishedNodesEntryModel" }, "configuration": { "format": "byte", "description": "The asset configuration to use when creating the asset.", "type": "string" }, "waitTime": { "format": "date-span", "description": "Time to wait after the configuration is applied to perform\r\nthe configuration of the asset in the configuration api.\r\nThis is to let the server settle.", "type": "string" } }, "additionalProperties": false }, "ChannelDiagnosticModel": { "description": "Channel diagnostics model", "required": [ "connection", "timeStamp" ], "type": "object", "properties": { "timeStamp": { "format": "date-time", "description": "Timestamp of the diagnostic information", "type": "string" }, "sessionId": { "description": "The session id if connected. Empty if disconnected.", "type": "string" }, "sessionCreated": { "format": "date-time", "description": "When the session was created.", "type": "string" }, "connection": { "$ref": "#/definitions/ConnectionModel" }, "remoteIpAddress": { "description": "Effective remote ip address used for the\r\nconnection if connected. Empty if disconnected.", "type": "string" }, "remotePort": { "format": "int32", "description": "The effective remote port used when connected,\r\nnull if disconnected.", "type": "integer" }, "localIpAddress": { "description": "Effective local ip address used for the connection\r\nif connected. Empty if disconnected.", "type": "string" }, "localPort": { "format": "int32", "description": "The effective local port used when connected,\r\nnull if disconnected.", "type": "integer" }, "channelId": { "format": "int64", "description": "The id assigned to the channel that the token\r\nbelongs to.", "type": "integer" }, "tokenId": { "format": "int64", "description": "The id assigned to the token.", "type": "integer" }, "createdAt": { "format": "date-time", "description": "When the token was created by the server\r\n(refers to the server's clock).", "type": "string" }, "lifetime": { "format": "date-span", "description": "The lifetime of the token", "type": "string" }, "client": { "$ref": "#/definitions/ChannelKeyModel" }, "server": { "$ref": "#/definitions/ChannelKeyModel" } }, "additionalProperties": false }, "ChannelDiagnosticModelIAsyncEnumerable": { "type": "object", "additionalProperties": false }, "ChannelKeyModel": { "description": "Channel token key model.", "required": [ "iv", "key", "sigLen" ], "type": "object", "properties": { "iv": { "description": "Iv", "type": "array", "items": { "format": "int32", "type": "integer" } }, "key": { "description": "Key", "type": "array", "items": { "format": "int32", "type": "integer" } }, "sigLen": { "format": "int32", "description": "Signature length", "type": "integer" } }, "additionalProperties": false }, "ConditionHandlingOptionsModel": { "description": "Condition handling options model", "type": "object", "properties": { "updateInterval": { "format": "int32", "description": "Time interval for sending pending interval updates in seconds.", "type": "integer" }, "snapshotInterval": { "format": "int32", "description": "Time interval for sending pending interval snapshot in seconds.", "type": "integer" } }, "additionalProperties": false }, "ConnectionDiagnosticsModelIAsyncEnumerable": { "type": "object", "additionalProperties": false }, "ConnectionModel": { "description": "Connection model", "required": [ "endpoint" ], "type": "object", "properties": { "endpoint": { "$ref": "#/definitions/EndpointModel" }, "user": { "$ref": "#/definitions/CredentialModel" }, "diagnostics": { "$ref": "#/definitions/DiagnosticsModel" }, "group": { "description": "Connection group allows splitting connections\r\nper purpose.", "type": "string" }, "locales": { "description": "Optional list of preferred locales in preference order.", "type": "array", "items": { "type": "string" } }, "options": { "$ref": "#/definitions/ConnectionOptions" } }, "additionalProperties": false }, "ConnectionOptions": { "description": "Options that can be applied to a connection", "enum": [ "None", "UseReverseConnect", "NoComplexTypeSystem", "NoSubscriptionTransfer", "DumpDiagnostics" ], "type": "string", "x-ms-enum": { "name": "ConnectionOptions", "modelAsString": false } }, "ContentFilterElementModel": { "description": "An expression element in the filter ast", "type": "object", "properties": { "filterOperator": { "$ref": "#/definitions/FilterOperatorType" }, "filterOperands": { "description": "The operands in the element for the operator", "type": "array", "items": { "$ref": "#/definitions/FilterOperandModel" } } }, "additionalProperties": false }, "ContentFilterModel": { "description": "Content filter", "type": "object", "properties": { "elements": { "description": "The flat list of elements in the filter AST", "type": "array", "items": { "$ref": "#/definitions/ContentFilterElementModel" } } }, "additionalProperties": false }, "CredentialModel": { "description": "Credential model. For backwards compatibility\r\nthe actual credentials to pass to the server is set\r\nthrough the value property.", "type": "object", "properties": { "type": { "$ref": "#/definitions/CredentialType" }, "value": { "$ref": "#/definitions/UserIdentityModel" } }, "additionalProperties": false }, "CredentialType": { "description": "Type of credentials to use for authentication", "enum": [ "None", "UserName", "X509Certificate", "JwtToken" ], "type": "string", "x-ms-enum": { "name": "CredentialType", "modelAsString": false } }, "DataChangeTriggerType": { "description": "Data change trigger", "enum": [ "Status", "StatusValue", "StatusValueTimestamp" ], "type": "string", "x-ms-enum": { "name": "DataChangeTriggerType", "modelAsString": false } }, "DataLocation": { "description": "Indicate the data location", "enum": [ "Raw", "Calculated", "Interpolated" ], "type": "string", "x-ms-enum": { "name": "DataLocation", "modelAsString": false } }, "DataSetRoutingMode": { "description": "Specifies how OPC UA node paths are mapped to message routing paths/topics.\r\nControls automatic topic structure generation from OPC UA address space.\r\nUsed to create a unified namespace when publishing to message brokers\r\nthat support hierarchical routing like MQTT.", "enum": [ "None", "UseBrowseNames", "UseBrowseNamesWithNamespaceIndex" ], "type": "string", "x-ms-enum": { "name": "DataSetRoutingMode", "modelAsString": false } }, "DataTypeMetadataModel": { "description": "Data type metadata model", "type": "object", "properties": { "dataType": { "description": "The data type for the instance declaration.", "type": "string" } }, "additionalProperties": false }, "DeadbandType": { "description": "Deadband type", "enum": [ "Absolute", "Percent" ], "type": "string", "x-ms-enum": { "name": "DeadbandType", "modelAsString": false } }, "DeleteEventsDetailsModel": { "description": "The events to delete", "required": [ "eventIds" ], "type": "object", "properties": { "eventIds": { "description": "Events to delete", "type": "array", "items": { "format": "byte", "type": "string" } } }, "additionalProperties": false }, "DeleteEventsDetailsModelHistoryUpdateRequestModel": { "description": "Request node history update", "required": [ "details" ], "type": "object", "properties": { "nodeId": { "description": "Node to update (mandatory without browse path)", "type": "string" }, "browsePath": { "description": "An optional path from NodeId instance to\r\nthe actual node.", "type": "array", "items": { "type": "string" } }, "details": { "$ref": "#/definitions/DeleteEventsDetailsModel" }, "header": { "$ref": "#/definitions/RequestHeaderModel" } }, "additionalProperties": false }, "DeleteEventsDetailsModelHistoryUpdateRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/DeleteEventsDetailsModelHistoryUpdateRequestModel" } }, "additionalProperties": false }, "DeleteValuesAtTimesDetailsModel": { "description": "Deletes data at times", "required": [ "reqTimes" ], "type": "object", "properties": { "reqTimes": { "description": "The timestamps to delete", "type": "array", "items": { "format": "date-time", "type": "string" } } }, "additionalProperties": false }, "DeleteValuesAtTimesDetailsModelHistoryUpdateRequestModel": { "description": "Request node history update", "required": [ "details" ], "type": "object", "properties": { "nodeId": { "description": "Node to update (mandatory without browse path)", "type": "string" }, "browsePath": { "description": "An optional path from NodeId instance to\r\nthe actual node.", "type": "array", "items": { "type": "string" } }, "details": { "$ref": "#/definitions/DeleteValuesAtTimesDetailsModel" }, "header": { "$ref": "#/definitions/RequestHeaderModel" } }, "additionalProperties": false }, "DeleteValuesAtTimesDetailsModelHistoryUpdateRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/DeleteValuesAtTimesDetailsModelHistoryUpdateRequestModel" } }, "additionalProperties": false }, "DeleteValuesDetailsModel": { "description": "Delete values", "type": "object", "properties": { "startTime": { "format": "date-time", "description": "Start time", "type": "string" }, "endTime": { "format": "date-time", "description": "End time to delete until", "type": "string" } }, "additionalProperties": false }, "DeleteValuesDetailsModelHistoryUpdateRequestModel": { "description": "Request node history update", "required": [ "details" ], "type": "object", "properties": { "nodeId": { "description": "Node to update (mandatory without browse path)", "type": "string" }, "browsePath": { "description": "An optional path from NodeId instance to\r\nthe actual node.", "type": "array", "items": { "type": "string" } }, "details": { "$ref": "#/definitions/DeleteValuesDetailsModel" }, "header": { "$ref": "#/definitions/RequestHeaderModel" } }, "additionalProperties": false }, "DeleteValuesDetailsModelHistoryUpdateRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/DeleteValuesDetailsModelHistoryUpdateRequestModel" } }, "additionalProperties": false }, "DiagnosticsLevel": { "description": "Level of diagnostics requested in responses", "enum": [ "None", "Status", "Information", "Debug", "Verbose" ], "type": "string", "x-ms-enum": { "name": "DiagnosticsLevel", "modelAsString": false } }, "DiagnosticsModel": { "description": "Diagnostics configuration", "type": "object", "properties": { "level": { "$ref": "#/definitions/DiagnosticsLevel" }, "auditId": { "description": "Client audit log entry.\r\n(default: client generated)", "type": "string" }, "timeStamp": { "format": "date-time", "description": "Timestamp of request.\r\n(default: client generated)", "type": "string" } }, "additionalProperties": false }, "DiscoveryCancelRequestModel": { "description": "Discovery cancel request", "type": "object", "properties": { "id": { "description": "Id of discovery request", "type": "string" }, "context": { "$ref": "#/definitions/OperationContextModel" } }, "additionalProperties": false }, "DiscoveryConfigModel": { "description": "Discovery configuration api model", "type": "object", "properties": { "addressRangesToScan": { "description": "Address ranges to scan (null == all wired nics)", "type": "string" }, "networkProbeTimeout": { "format": "date-span", "description": "Network probe timeout", "type": "string" }, "maxNetworkProbes": { "format": "int32", "description": "Max network probes that should ever run.", "type": "integer" }, "portRangesToScan": { "description": "Port ranges to scan (null == all unassigned)", "type": "string" }, "portProbeTimeout": { "format": "date-span", "description": "Port probe timeout", "type": "string" }, "maxPortProbes": { "format": "int32", "description": "Max port probes that should ever run.", "type": "integer" }, "minPortProbesPercent": { "format": "int32", "description": "Probes that must always be there as percent of max.", "type": "integer" }, "idleTimeBetweenScans": { "format": "date-span", "description": "Delay time between discovery sweeps", "type": "string" }, "discoveryUrls": { "description": "List of preset discovery urls to use", "type": "array", "items": { "type": "string" } }, "locales": { "description": "List of locales to filter with during discovery", "type": "array", "items": { "type": "string" } } }, "additionalProperties": false }, "DiscoveryMode": { "description": "Discovery mode to use", "enum": [ "Off", "Local", "Network", "Fast", "Scan" ], "type": "string", "x-ms-enum": { "name": "DiscoveryMode", "modelAsString": false } }, "DiscoveryRequestModel": { "description": "Discovery request", "type": "object", "properties": { "id": { "description": "Id of discovery request", "type": "string" }, "discovery": { "$ref": "#/definitions/DiscoveryMode" }, "configuration": { "$ref": "#/definitions/DiscoveryConfigModel" }, "context": { "$ref": "#/definitions/OperationContextModel" } }, "additionalProperties": false }, "EndpointModel": { "description": "Endpoint model", "required": [ "url" ], "type": "object", "properties": { "url": { "description": "Endpoint url to use to connect with", "minLength": 1, "type": "string" }, "alternativeUrls": { "description": "Alternative endpoint urls that can be used for\r\naccessing and validating the server", "type": "array", "items": { "type": "string" } }, "securityMode": { "$ref": "#/definitions/SecurityMode" }, "securityPolicy": { "description": "Security policy uri to use for communication.\r\ndefault to best.", "type": "string" }, "certificate": { "description": "Endpoint certificate thumbprint", "type": "string" } }, "additionalProperties": false }, "EndpointRegistrationModel": { "description": "Endpoint registration", "required": [ "id" ], "type": "object", "properties": { "id": { "description": "Endpoint identifier which is hashed from\r\nthe supervisor, site and url.", "minLength": 1, "type": "string" }, "endpointUrl": { "description": "Original endpoint url of the endpoint", "type": "string" }, "siteId": { "description": "Registered site of the endpoint", "type": "string" }, "discovererId": { "description": "Entity that registered and can access the endpoint", "type": "string" }, "endpoint": { "$ref": "#/definitions/EndpointModel" }, "securityLevel": { "format": "int32", "description": "Security level of the endpoint", "type": "integer" }, "authenticationMethods": { "description": "Supported authentication methods that can be selected to\r\nobtain a credential and used to interact with the endpoint.", "type": "array", "items": { "$ref": "#/definitions/AuthenticationMethodModel" } } }, "additionalProperties": false }, "EventFilterModel": { "description": "Event filter", "type": "object", "properties": { "selectClauses": { "description": "Select clauses", "type": "array", "items": { "$ref": "#/definitions/SimpleAttributeOperandModel" } }, "whereClause": { "$ref": "#/definitions/ContentFilterModel" }, "typeDefinitionId": { "description": "Simple event Type definition node id", "type": "string" } }, "additionalProperties": false }, "ExceptionDeviationType": { "description": "Exception deviation type", "enum": [ "AbsoluteValue", "PercentOfValue", "PercentOfRange", "PercentOfEURange" ], "type": "string", "x-ms-enum": { "name": "ExceptionDeviationType", "modelAsString": false } }, "FileInfoModel": { "description": "File info", "type": "object", "properties": { "size": { "format": "int64", "description": "The size of the file in Bytes. When a file is\r\ncurrently opened for write, the size might not be\r\naccurate or available.", "type": "integer" }, "writable": { "description": "Whether the file is writable.", "type": "boolean" }, "openCount": { "format": "int32", "description": "The number of currently valid file handles on\r\nthe file.", "type": "integer" }, "mimeType": { "description": "The media type of the file based on RFC 2046.", "type": "string" }, "maxBufferSize": { "format": "int64", "description": "The maximum number of bytes of\r\nthe read and write buffers.", "type": "integer" }, "lastModified": { "format": "date-time", "description": "The time the file was last modified.", "type": "string" } }, "additionalProperties": false }, "FileInfoModelServiceResponse": { "description": "Response envelope", "type": "object", "properties": { "result": { "$ref": "#/definitions/FileInfoModel" }, "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "FileSystemObjectModel": { "description": "File system object model", "type": "object", "properties": { "nodeId": { "description": "The node id of the filesystem object", "type": "string" }, "browsePath": { "description": "The browse path to the filesystem object", "type": "array", "items": { "type": "string" } }, "name": { "description": "The name of the filesystem object", "type": "string" } }, "additionalProperties": false }, "FileSystemObjectModelIEnumerableServiceResponse": { "description": "Response envelope", "type": "object", "properties": { "result": { "description": "Result", "type": "array", "items": { "$ref": "#/definitions/FileSystemObjectModel" } }, "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "FileSystemObjectModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/FileSystemObjectModel" } }, "additionalProperties": false }, "FileSystemObjectModelServiceResponse": { "description": "Response envelope", "type": "object", "properties": { "result": { "$ref": "#/definitions/FileSystemObjectModel" }, "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "FileSystemObjectModelServiceResponseIAsyncEnumerable": { "type": "object", "additionalProperties": false }, "FilterOperandModel": { "description": "Filter operand", "type": "object", "properties": { "index": { "format": "int64", "description": "Element reference in the outer list if\r\noperand is an element operand", "type": "integer" }, "value": { "description": "Variant value if operand is a literal", "type": "object" }, "nodeId": { "description": "Type definition node id if operand is\r\nsimple or full attribute operand.", "type": "string" }, "browsePath": { "description": "Browse path of attribute operand", "type": "array", "items": { "type": "string" } }, "attributeId": { "$ref": "#/definitions/NodeAttribute" }, "indexRange": { "description": "Index range of attribute operand", "type": "string" }, "alias": { "description": "Optional alias to refer to it makeing it a\r\nfull blown attribute operand", "type": "string" }, "dataType": { "description": "Data type if operand is a literal", "type": "string" } }, "additionalProperties": false }, "FilterOperatorType": { "description": "Filter operator type", "enum": [ "Equals", "IsNull", "GreaterThan", "LessThan", "GreaterThanOrEqual", "LessThanOrEqual", "Like", "Not", "Between", "InList", "And", "Or", "Cast", "InView", "OfType", "RelatedTo", "BitwiseAnd", "BitwiseOr" ], "type": "string", "x-ms-enum": { "name": "FilterOperatorType", "modelAsString": false } }, "GetConfiguredEndpointsResponseModel": { "description": "Result of GetConfiguredEndpoints method call", "type": "object", "properties": { "endpoints": { "description": "Collection of Endpoints in the configuration", "type": "array", "items": { "$ref": "#/definitions/PublishedNodesEntryModel" } } }, "additionalProperties": false }, "GetConfiguredNodesOnEndpointResponseModel": { "description": "Result of GetConfiguredNodesOnEndpoint method call", "type": "object", "properties": { "opcNodes": { "description": "Collection of Nodes configured for a particular endpoint", "type": "array", "items": { "$ref": "#/definitions/OpcNodeModel" } } }, "additionalProperties": false }, "HeartbeatBehavior": { "description": "Controls how heartbeat messages are handled for monitored items.\r\nHeartbeats help maintain awareness of node state and connection health\r\neven when values don't change. Can be configured globally via the\r\n--hbb command line option. Works with heartbeat interval settings.", "enum": [ "WatchdogLKV", "WatchdogLKG", "PeriodicLKV", "PeriodicLKG", "WatchdogLKVWithUpdatedTimestamps", "WatchdogLKVDiagnosticsOnly", "Reserved", "PeriodicLKVDropValue", "PeriodicLKGDropValue" ], "type": "string", "x-ms-enum": { "name": "HeartbeatBehavior", "modelAsString": false } }, "HistoricEventModel": { "description": "Historic event", "required": [ "eventFields" ], "type": "object", "properties": { "eventFields": { "description": "The selected fields of the event", "type": "object", "items": { "description": "A variant which can be represented by any value including null.", "type": "object" } } }, "additionalProperties": false }, "HistoricEventModelArrayHistoryReadNextResponseModel": { "description": "History read continuation result", "required": [ "history" ], "type": "object", "properties": { "history": { "description": "History as json encoded extension object", "type": "array", "items": { "$ref": "#/definitions/HistoricEventModel" } }, "continuationToken": { "description": "Continuation token if more results pending.", "type": "string" }, "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "HistoricEventModelArrayHistoryReadResponseModel": { "description": "History read results", "required": [ "history" ], "type": "object", "properties": { "history": { "description": "History as json encoded extension object", "type": "array", "items": { "$ref": "#/definitions/HistoricEventModel" } }, "continuationToken": { "description": "Continuation token if more results pending.", "type": "string" }, "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "HistoricEventModelIAsyncEnumerable": { "type": "object", "additionalProperties": false }, "HistoricValueModel": { "description": "Historic data", "type": "object", "properties": { "value": { "description": "The value of data value.", "type": "object" }, "dataType": { "description": "Built in data type of the updated values", "type": "string" }, "status": { "$ref": "#/definitions/ServiceResultModel" }, "sourceTimestamp": { "format": "date-time", "description": "The source timestamp associated with the value.", "type": "string" }, "sourcePicoseconds": { "format": "int32", "description": "Additional resolution for the source timestamp.", "type": "integer" }, "serverTimestamp": { "format": "date-time", "description": "The server timestamp associated with the value.", "type": "string" }, "serverPicoseconds": { "format": "int32", "description": "Additional resolution for the server timestamp.", "type": "integer" }, "dataLocation": { "$ref": "#/definitions/DataLocation" }, "modificationInfo": { "$ref": "#/definitions/ModificationInfoModel" }, "additionalData": { "$ref": "#/definitions/AdditionalData" } }, "additionalProperties": false }, "HistoricValueModelArrayHistoryReadNextResponseModel": { "description": "History read continuation result", "required": [ "history" ], "type": "object", "properties": { "history": { "description": "History as json encoded extension object", "type": "array", "items": { "$ref": "#/definitions/HistoricValueModel" } }, "continuationToken": { "description": "Continuation token if more results pending.", "type": "string" }, "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "HistoricValueModelArrayHistoryReadResponseModel": { "description": "History read results", "required": [ "history" ], "type": "object", "properties": { "history": { "description": "History as json encoded extension object", "type": "array", "items": { "$ref": "#/definitions/HistoricValueModel" } }, "continuationToken": { "description": "Continuation token if more results pending.", "type": "string" }, "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "HistoricValueModelIAsyncEnumerable": { "type": "object", "additionalProperties": false }, "HistoryConfigurationModel": { "description": "History configuration", "type": "object", "properties": { "stepped": { "description": "specifies whether the historical data was\r\ncollected in such a manner that it should\r\nbe displayed as SlopedInterpolation (sloped\r\nline between points) or as SteppedInterpolation\r\n(vertically-connected horizontal lines\r\nbetween points) when raw data is examined.\r\nThis Property also effects how some\r\nAggregates are calculated", "type": "boolean" }, "definition": { "description": "Human readable string that specifies how\r\nthe value of this HistoricalDataNode is\r\ncalculated", "type": "string" }, "maxTimeInterval": { "format": "date-span", "description": "Specifies the maximum interval between data\r\npoints in the history repository\r\nregardless of their value change", "type": "string" }, "minTimeInterval": { "format": "date-span", "description": "Specifies the minimum interval between\r\ndata points in the history repository\r\nregardless of their value change", "type": "string" }, "exceptionDeviation": { "format": "double", "description": "Minimum amount that the data for the\r\nNode shall change in order for the change\r\nto be reported to the history database", "type": "number" }, "exceptionDeviationType": { "$ref": "#/definitions/ExceptionDeviationType" }, "startOfArchive": { "format": "date-time", "description": "The date before which there is no data in the\r\narchive either online or offline", "type": "string" }, "endOfArchive": { "format": "date-time", "description": "The last date of the archive", "type": "string" }, "startOfOnlineArchive": { "format": "date-time", "description": "Date of the earliest data in the online archive", "type": "string" }, "serverTimestampSupported": { "description": "Server supports ServerTimestamps in addition\r\nto SourceTimestamp", "type": "boolean" }, "aggregateConfiguration": { "$ref": "#/definitions/AggregateConfigurationModel" }, "aggregateFunctions": { "description": "Allowed aggregate functions", "type": "object", "additionalProperties": { "type": "string" } } }, "additionalProperties": false }, "HistoryConfigurationRequestModel": { "description": "Request history configuration", "required": [ "nodeId" ], "type": "object", "properties": { "header": { "$ref": "#/definitions/RequestHeaderModel" }, "nodeId": { "description": "Continuation token to continue reading more\r\nresults.", "minLength": 1, "type": "string" } }, "additionalProperties": false }, "HistoryConfigurationRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/HistoryConfigurationRequestModel" } }, "additionalProperties": false }, "HistoryConfigurationResponseModel": { "description": "Response with history configuration", "type": "object", "properties": { "configuration": { "$ref": "#/definitions/HistoryConfigurationModel" }, "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "HistoryReadNextRequestModel": { "description": "Request node history read continuation", "required": [ "continuationToken" ], "type": "object", "properties": { "continuationToken": { "description": "Continuation token to continue reading more\r\nresults.", "minLength": 1, "type": "string" }, "abort": { "description": "Abort reading after this read", "type": "boolean" }, "header": { "$ref": "#/definitions/RequestHeaderModel" } }, "additionalProperties": false }, "HistoryReadNextRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/HistoryReadNextRequestModel" } }, "additionalProperties": false }, "HistoryServerCapabilitiesModel": { "description": "History Server capabilities", "type": "object", "properties": { "supportsHistoricData": { "description": "Server supports historic data access", "type": "boolean" }, "supportsHistoricEvents": { "description": "Server supports historic event access", "type": "boolean" }, "maxReturnDataValues": { "format": "int64", "description": "Maximum number of historic data values that will\r\nbe returned in a single read.", "type": "integer" }, "maxReturnEventValues": { "format": "int64", "description": "Maximum number of events that will be returned\r\nin a single read.", "type": "integer" }, "insertDataCapability": { "description": "Server supports inserting data", "type": "boolean" }, "replaceDataCapability": { "description": "Server supports replacing historic data", "type": "boolean" }, "updateDataCapability": { "description": "Server supports updating historic data", "type": "boolean" }, "deleteRawCapability": { "description": "Server supports deleting raw data", "type": "boolean" }, "deleteAtTimeCapability": { "description": "Server support deleting data at times", "type": "boolean" }, "insertEventCapability": { "description": "Server supports inserting events", "type": "boolean" }, "replaceEventCapability": { "description": "Server supports replacing events", "type": "boolean" }, "updateEventCapability": { "description": "Server supports updating events", "type": "boolean" }, "deleteEventCapability": { "description": "Server supports deleting events", "type": "boolean" }, "insertAnnotationCapability": { "description": "Allows inserting annotations", "type": "boolean" }, "serverTimestampSupported": { "description": "Server supports ServerTimestamps in addition\r\nto SourceTimestamp", "type": "boolean" }, "aggregateFunctions": { "description": "Supported aggregate functions", "type": "object", "additionalProperties": { "type": "string" } } }, "additionalProperties": false }, "HistoryUpdateOperation": { "description": "History update type", "enum": [ "Insert", "Replace", "Update", "Delete" ], "type": "string", "x-ms-enum": { "name": "HistoryUpdateOperation", "modelAsString": false } }, "HistoryUpdateResponseModel": { "description": "History update results", "type": "object", "properties": { "results": { "description": "List of results from the update operation", "type": "array", "items": { "$ref": "#/definitions/ServiceResultModel" } }, "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "InstanceDeclarationModel": { "description": "Instance declaration meta data", "type": "object", "properties": { "rootTypeId": { "description": "The type that the declaration belongs to.", "type": "string" }, "browsePath": { "description": "The browse path", "type": "array", "items": { "type": "string" } }, "displayPath": { "description": "A localized path to the instance declaration.", "type": "string" }, "modellingRule": { "description": "The modelling rule for the instance\r\ndeclaration (i.e. Mandatory or Optional).", "type": "string" }, "nodeId": { "description": "The node id for the instance.", "type": "string" }, "nodeClass": { "$ref": "#/definitions/NodeClass" }, "browseName": { "description": "The browse name for the instance declaration.", "type": "string" }, "displayName": { "description": "The display name for the instance declaration.", "type": "string" }, "description": { "description": "The description for the instance declaration.", "type": "string" }, "variable": { "$ref": "#/definitions/VariableMetadataModel" }, "method": { "$ref": "#/definitions/MethodMetadataModel" }, "overriddenDeclaration": { "$ref": "#/definitions/InstanceDeclarationModel" }, "modellingRuleId": { "description": "The modelling rule node id.", "type": "string" } }, "additionalProperties": false }, "MessageEncoding": { "description": "Specifies the encoding format for OPC UA Publisher messages.\r\nCan be combined with compression and reversibility flags to control\r\nmessage format characteristics.", "enum": [ "Uadp", "Json", "Xml", "Avro", "IsReversible", "JsonReversible", "IsGzipCompressed", "JsonGzip", "AvroGzip", "JsonReversibleGzip" ], "type": "string", "x-ms-enum": { "name": "MessageEncoding", "modelAsString": false } }, "MessagingMode": { "description": "Defines how OPC UA Publisher formats and structures messages for transport.\r\nEach mode provides different trade-offs between message completeness,\r\nbandwidth efficiency, and compatibility with different message consumers.", "enum": [ "PubSub", "Samples", "FullNetworkMessages", "FullSamples", "DataSetMessages", "SingleDataSetMessage", "DataSets", "SingleDataSet", "RawDataSets", "SingleRawDataSet" ], "type": "string", "x-ms-enum": { "name": "MessagingMode", "modelAsString": false } }, "MethodCallArgumentModel": { "description": "Method argument model", "type": "object", "properties": { "value": { "description": "Initial value or value to use", "type": "object" }, "dataType": { "description": "Data type Id of the value (from meta data)", "type": "string" } }, "additionalProperties": false }, "MethodCallRequestModel": { "description": "Call request model", "type": "object", "properties": { "methodId": { "description": "Method id of method to call.", "type": "string" }, "objectId": { "description": "Context of the method, i.e. an object or object type\r\nnode. If null then the method is called in the context\r\nof the inverse HasComponent reference of the MethodId\r\nif it exists.", "type": "string" }, "arguments": { "description": "Arguments for the method - null means no args", "type": "array", "items": { "$ref": "#/definitions/MethodCallArgumentModel" } }, "methodBrowsePath": { "description": "An optional component path from the node identified by\r\nMethodId or from a resolved objectId to the actual\r\nmethod node.", "type": "array", "items": { "type": "string" } }, "objectBrowsePath": { "description": "An optional component path from the node identified by\r\nObjectId to the actual object or objectType node.\r\nIf ObjectId is null, the root node (i=84) is used", "type": "array", "items": { "type": "string" } }, "header": { "$ref": "#/definitions/RequestHeaderModel" } }, "additionalProperties": false }, "MethodCallRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/MethodCallRequestModel" } }, "additionalProperties": false }, "MethodCallResponseModel": { "description": "Method call response model", "required": [ "results" ], "type": "object", "properties": { "results": { "description": "Resulting output values of method call", "type": "array", "items": { "$ref": "#/definitions/MethodCallArgumentModel" } }, "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "MethodMetadataArgumentModel": { "description": "Method argument metadata model", "required": [ "name", "type" ], "type": "object", "properties": { "name": { "description": "Name of the argument", "type": "string" }, "description": { "description": "Optional description of argument", "type": "string" }, "type": { "$ref": "#/definitions/NodeModel" }, "defaultValue": { "description": "Default value for the argument", "type": "object" }, "valueRank": { "$ref": "#/definitions/NodeValueRank" }, "arrayDimensions": { "format": "int64", "description": "Optional Array dimension of argument", "type": "integer", "items": { "format": "int64", "type": "integer" } }, "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "MethodMetadataModel": { "description": "Method metadata model", "type": "object", "properties": { "objectId": { "description": "Id of object that the method is a component of", "type": "string" }, "inputArguments": { "description": "Input argument meta data", "type": "array", "items": { "$ref": "#/definitions/MethodMetadataArgumentModel" } }, "outputArguments": { "description": "output argument meta data", "type": "array", "items": { "$ref": "#/definitions/MethodMetadataArgumentModel" } } }, "additionalProperties": false }, "MethodMetadataRequestModel": { "description": "Method metadata request model", "type": "object", "properties": { "methodId": { "description": "Method id of method to call.\r\n(Required)", "type": "string" }, "methodBrowsePath": { "description": "An optional component path from the node identified by\r\nMethodId to the actual method node.", "type": "array", "items": { "type": "string" } }, "header": { "$ref": "#/definitions/RequestHeaderModel" } }, "additionalProperties": false }, "MethodMetadataRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/MethodMetadataRequestModel" } }, "additionalProperties": false }, "MethodMetadataResponseModel": { "description": "Result of method metadata query", "type": "object", "properties": { "objectId": { "description": "Id of object that the method is a component of", "type": "string" }, "inputArguments": { "description": "Input argument meta data", "type": "array", "items": { "$ref": "#/definitions/MethodMetadataArgumentModel" } }, "outputArguments": { "description": "output argument meta data", "type": "array", "items": { "$ref": "#/definitions/MethodMetadataArgumentModel" } }, "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "ModelChangeHandlingOptionsModel": { "description": "Describes how model changes are published", "type": "object", "properties": { "rebrowseIntervalTimespan": { "format": "date-span", "description": "Rebrowse period", "type": "string" } }, "additionalProperties": false }, "ModificationInfoModel": { "description": "Modification information", "type": "object", "properties": { "modificationTime": { "format": "date-time", "description": "Modification time", "type": "string" }, "updateType": { "$ref": "#/definitions/HistoryUpdateOperation" }, "userName": { "description": "User who made the change", "type": "string" } }, "additionalProperties": false }, "MonitoredItemWatchdogCondition": { "description": "Defines the conditions that trigger the subscription watchdog behavior.\r\nWorks in conjunction with OpcNodeWatchdogTimespan to determine when nodes\r\nare considered \"late\" and DataSetWriterWatchdogBehavior to define the response.\r\nCan be configured globally via the --mwc command line option.", "enum": [ "WhenAllAreLate", "WhenAnyIsLate" ], "type": "string", "x-ms-enum": { "name": "MonitoredItemWatchdogCondition", "modelAsString": false } }, "NamespaceFormat": { "description": "Namespace serialization format for node ids\r\nand qualified names.", "enum": [ "Uri", "Index", "Expanded", "ExpandedWithNamespace0" ], "type": "string", "x-ms-enum": { "name": "NamespaceFormat", "modelAsString": false } }, "NodeAccessLevel": { "description": "Flags that can be set for the AccessLevel attribute.", "enum": [ "None", "CurrentRead", "CurrentWrite", "HistoryRead", "HistoryWrite", "SemanticChange", "StatusWrite", "TimestampWrite", "NonatomicRead", "NonatomicWrite", "WriteFullArrayOnly" ], "type": "string", "x-ms-enum": { "name": "NodeAccessLevel", "modelAsString": false } }, "NodeAccessRestrictions": { "description": "Flags that can be read or written in the\r\nAccessRestrictions attribute.", "enum": [ "None", "SigningRequired", "EncryptionRequired", "SessionRequired" ], "type": "string", "x-ms-enum": { "name": "NodeAccessRestrictions", "modelAsString": false } }, "NodeAttribute": { "description": "Node attribute identifiers", "enum": [ "NodeId", "NodeClass", "BrowseName", "DisplayName", "Description", "WriteMask", "UserWriteMask", "IsAbstract", "Symmetric", "InverseName", "ContainsNoLoops", "EventNotifier", "Value", "DataType", "ValueRank", "ArrayDimensions", "AccessLevel", "UserAccessLevel", "MinimumSamplingInterval", "Historizing", "Executable", "UserExecutable", "DataTypeDefinition", "RolePermissions", "UserRolePermissions", "AccessRestrictions" ], "type": "string", "x-ms-enum": { "name": "NodeAttribute", "modelAsString": false } }, "NodeClass": { "description": "Node class", "enum": [ "Object", "Variable", "Method", "ObjectType", "VariableType", "ReferenceType", "DataType", "View" ], "type": "string", "x-ms-enum": { "name": "NodeClass", "modelAsString": false } }, "NodeEventNotifier": { "description": "Flags that can be set for the EventNotifier attribute.", "enum": [ "SubscribeToEvents", "HistoryRead", "HistoryWrite" ], "type": "string", "x-ms-enum": { "name": "NodeEventNotifier", "modelAsString": false } }, "NodeIdModel": { "description": "Represents an OPC UA Node identifier in string format.\r\nUsed to identify nodes in the OPC UA address space for monitoring.\r\nSupports standard OPC UA node ID formats including:\r\n- Namespace index and identifier (ns=0;i=85)\r\n- String identifiers (ns=2;s=MyNode)\r\n- GUID identifiers (ns=3;g=8599E6C4-6667-4FB7-9EA9-C6896B31DB02)\r\n- Opaque/binary identifiers (ns=4;b=FA34E...)", "type": "object", "properties": { "Identifier": { "description": "The node identifier string in standard OPC UA notation.\r\nFormat: ns={namespace};{type}={value}\r\nExamples:\r\n- ns=0;i=85 (numeric identifier)\r\n- ns=2;s=MyNode (string identifier)\r\n- ns=3;g=8599E6C4-6667-4FB7-9EA9-C6896B31DB02 (GUID)\r\n- ns=4;b=FA34E... (binary/opaque)\r\nIf namespace index is omitted, ns=0 is assumed.", "type": "string" } }, "additionalProperties": false }, "NodeMetadataRequestModel": { "description": "Node metadata request model", "type": "object", "properties": { "header": { "$ref": "#/definitions/RequestHeaderModel" }, "nodeId": { "description": "Node id of the type.\r\n(Required)", "type": "string" }, "browsePath": { "description": "An optional component path from the node identified by\r\nNodeId to the actual node.", "type": "array", "items": { "type": "string" } } }, "additionalProperties": false }, "NodeMetadataRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/NodeMetadataRequestModel" } }, "additionalProperties": false }, "NodeMetadataResponseModel": { "description": "Node metadata model", "type": "object", "properties": { "nodeId": { "description": "The node id of the node", "type": "string" }, "nodeClass": { "$ref": "#/definitions/NodeClass" }, "displayName": { "description": "The display name of the node.", "type": "string" }, "description": { "description": "The description for the node.", "type": "string" }, "variableMetadata": { "$ref": "#/definitions/VariableMetadataModel" }, "dataTypeMetadata": { "$ref": "#/definitions/DataTypeMetadataModel" }, "nethodMetadata": { "$ref": "#/definitions/MethodMetadataModel" }, "typeDefinition": { "$ref": "#/definitions/TypeDefinitionModel" }, "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "NodeModel": { "description": "Node model", "required": [ "nodeId" ], "type": "object", "properties": { "nodeClass": { "$ref": "#/definitions/NodeClass" }, "displayName": { "description": "Display name", "type": "string" }, "nodeId": { "description": "Id of node.\r\n(Mandatory).", "minLength": 1, "type": "string" }, "description": { "description": "Description if any", "type": "string" }, "browseName": { "description": "Browse name", "type": "string" }, "value": { "description": "Value of variable or default value of the\r\nsubtyped variable in case node is a variable\r\ntype, otherwise null.", "type": "object" }, "sourcePicoseconds": { "format": "int32", "description": "Pico seconds part of when value was read at source.", "type": "integer" }, "sourceTimestamp": { "format": "date-time", "description": "Timestamp of when value was read at source.", "type": "string" }, "serverPicoseconds": { "format": "int32", "description": "Pico seconds part of when value was read at server.", "type": "integer" }, "serverTimestamp": { "format": "date-time", "description": "Timestamp of when value was read at server.", "type": "string" }, "errorInfo": { "$ref": "#/definitions/ServiceResultModel" }, "accessRestrictions": { "$ref": "#/definitions/NodeAccessRestrictions" }, "writeMask": { "format": "int64", "description": "Default write mask for the node\r\n(default: 0)", "type": "integer" }, "userWriteMask": { "format": "int64", "description": "User write mask for the node\r\n(default: 0)", "type": "integer" }, "isAbstract": { "description": "Whether type is abstract, if type can\r\nbe abstract. Null if not type node.\r\n(default: false)", "type": "boolean" }, "containsNoLoops": { "description": "Whether a view contains loops. Null if\r\nnot a view.", "type": "boolean" }, "eventNotifier": { "$ref": "#/definitions/NodeEventNotifier" }, "executable": { "description": "If method node class, whether method can\r\nbe called.", "type": "boolean" }, "userExecutable": { "description": "If method node class, whether method can\r\nbe called by current user.\r\n(default: false if not executable)", "type": "boolean" }, "dataTypeDefinition": { "description": "Data type definition in case node is a\r\ndata type node and definition is available,\r\notherwise null.", "type": "object" }, "accessLevel": { "$ref": "#/definitions/NodeAccessLevel" }, "userAccessLevel": { "$ref": "#/definitions/NodeAccessLevel" }, "dataType": { "description": "If variable the datatype of the variable.\r\n(default: null)", "type": "string" }, "valueRank": { "$ref": "#/definitions/NodeValueRank" }, "arrayDimensions": { "format": "int64", "description": "Array dimensions of variable or variable type.\r\n(default: empty array)", "type": "integer", "items": { "format": "int64", "type": "integer" } }, "historizing": { "description": "Whether the value of a variable is historizing.\r\n(default: false)", "type": "boolean" }, "minimumSamplingInterval": { "format": "double", "description": "Minimum sampling interval for the variable\r\nvalue, otherwise null if not a variable node.\r\n(default: null)", "type": "number" }, "inverseName": { "description": "Inverse name of the reference if the node is\r\na reference type, otherwise null.", "type": "string" }, "symmetric": { "description": "Whether the reference is symmetric in case\r\nthe node is a reference type, otherwise\r\nnull.", "type": "boolean" }, "rolePermissions": { "description": "Role permissions", "type": "array", "items": { "$ref": "#/definitions/RolePermissionModel" } }, "userRolePermissions": { "description": "User Role permissions", "type": "array", "items": { "$ref": "#/definitions/RolePermissionModel" } }, "typeDefinitionId": { "description": "Optional type definition of the node", "type": "string" }, "children": { "description": "Whether node has children which are defined as\r\nany forward hierarchical references.\r\n(default: unknown)", "type": "boolean" } }, "additionalProperties": false }, "NodePathTargetModel": { "description": "Node path target", "required": [ "browsePath", "target" ], "type": "object", "properties": { "browsePath": { "description": "The target browse path", "type": "array", "items": { "type": "string" } }, "target": { "$ref": "#/definitions/NodeModel" }, "remainingPathIndex": { "format": "int32", "description": "Remaining index in path", "type": "integer" } }, "additionalProperties": false }, "NodeReferenceModel": { "description": "Reference model", "required": [ "target" ], "type": "object", "properties": { "referenceTypeId": { "description": "Reference Type id", "type": "string" }, "direction": { "$ref": "#/definitions/BrowseDirection" }, "target": { "$ref": "#/definitions/NodeModel" }, "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "NodeType": { "description": "The node type", "enum": [ "Unknown", "Variable", "DataVariable", "Property", "DataType", "View", "Object", "Event", "Interface" ], "type": "string", "x-ms-enum": { "name": "NodeType", "modelAsString": false } }, "NodeValueRank": { "description": "Constants defined for the ValueRank attribute.", "enum": [ "OneOrMoreDimensions", "OneDimension", "TwoDimensions", "ScalarOrOneDimension", "Any", "Scalar" ], "type": "string", "x-ms-enum": { "name": "NodeValueRank", "modelAsString": false } }, "OpcAuthenticationMode": { "description": "Specifies the authentication method used to connect to OPC UA servers.\r\nThe chosen mode determines how the Publisher authenticates itself to servers.\r\nWhen using credentials or certificates, encrypted communication should be enabled\r\nvia UseSecurity or EndpointSecurityMode to protect authentication secrets.", "enum": [ "Anonymous", "UsernamePassword", "Certificate" ], "type": "string", "x-ms-enum": { "name": "OpcAuthenticationMode", "modelAsString": false } }, "OpcNodeModel": { "description": "Defines configuration for monitoring an OPC UA node.\r\nContains settings for sampling, filtering, publishing\r\nbehavior, and message routing. This model allows\r\nfine-grained control over how each node's data is collected\r\nand transmitted. Part of a PublishedNodesEntryModel's\r\nOpcNodes collection.", "type": "object", "properties": { "Id": { "description": "The OPC UA node identifier string in standard notation.\r\nFormat: ns={namespace};{type}={value} Required field that\r\nuniquely identifies the node to monitor. Examples:\r\n\"ns=2;s=MyTag\", \"ns=0;i=2258\" See OPC UA Part 3 for node\r\nID format specifications.", "type": "string" }, "OpcSamplingInterval": { "format": "int32", "description": "Server-side sampling rate in milliseconds. Determines how\r\noften the server checks for value changes. Default from\r\nDataSetSamplingInterval if not specified. Should be less\r\nthan or equal to OpcPublishingInterval for effective\r\nsampling. Ignored when OpcSamplingIntervalTimespan is\r\ndefined.", "type": "integer" }, "OpcSamplingIntervalTimespan": { "format": "date-span", "description": "Server-side sampling rate as a TimeSpan. Takes precedence\r\nover OpcSamplingInterval if both are defined. Provides\r\nmore precise control over timing than milliseconds.\r\nExample: \"00:00:00.100\" for 100ms sampling. Should be\r\nless than or equal to OpcPublishingIntervalTimespan for\r\neffective sampling.", "type": "string" }, "DataSetFieldId": { "description": "Custom identifier for this node in dataset messages. Used\r\nas field name in message payloads if specified. Falls back\r\nto DisplayName if not provided. Helps correlate data with\r\nspecific measurements or tags. Must be unique within a\r\ndataset writer.", "type": "string" }, "DataSetClassFieldId": { "format": "uuid", "description": "Unique identifier for correlating fields with dataset\r\nclass metadata. Links monitored item data with dataset\r\nclass field definitions. Used to provide context and type\r\ninformation for the field. Must match corresponding field\r\nID in dataset class metadata. Important for proper message\r\ndecoding by subscribers.", "type": "string" }, "DisplayName": { "description": "Human-readable name for the monitored item. Used as field\r\nidentifier if DataSetFieldId not specified. Can be\r\noverridden by actual node DisplayName if\r\nFetchDisplayName=true. Helps identify data sources in\r\nmessages and logs. Should be unique within a dataset for\r\nclear identification.", "type": "string" }, "QueueSize": { "format": "int64", "description": "Size of the server-side queue for this monitored item.\r\nControls how many values can be buffered during slow\r\nconnections. Values are discarded according to DiscardNew\r\nwhen queue is full. Default is 1 unless otherwise\r\nconfigured. Larger queues help prevent data loss but use\r\nmore server memory.", "type": "integer" }, "DiscardNew": { "description": "Controls queue overflow behavior for monitored items.\r\nTrue: Discard newest values when queue is full (LIFO).\r\nFalse: Discard oldest values when queue is full (FIFO,\r\ndefault). Use True to preserve historical data during\r\nconnection issues. Use False to maintain current value\r\naccuracy.", "type": "boolean" }, "DataChangeTrigger": { "$ref": "#/definitions/DataChangeTriggerType" }, "DeadbandType": { "$ref": "#/definitions/DeadbandType" }, "DeadbandValue": { "format": "double", "description": "Deadband value of the data change filter to apply. Does\r\nnot apply to events", "type": "number" }, "EventFilter": { "$ref": "#/definitions/EventFilterModel" }, "ConditionHandling": { "$ref": "#/definitions/ConditionHandlingOptionsModel" }, "BrowsePath": { "description": "Relative path through the address space to reach target\r\nnode. Sequence of browse names from starting node to\r\ntarget. Example: [\"Objects\", \"Server\", \"Data\",\r\n\"Dynamic\", \"Scalar\"]. Allows referencing nodes through\r\nhierarchical structure. Alternative to direct node ID\r\naddressing.", "type": "array", "items": { "type": "string" } }, "AttributeId": { "$ref": "#/definitions/NodeAttribute" }, "IndexRange": { "description": "Range specification for array or string values. Format:\r\n\"start:end\" or \"index\". Examples: \"0:3\" (first 4\r\nelements), \"7\" (8th element) Allows monitoring specific\r\narray elements. Default: null (entire value monitored)", "type": "string" }, "Topic": { "description": "Custom routing topic/queue for this node's messages.\r\nOverrides writer and writer group queue settings. Enables\r\nnode-specific message routing patterns. Messages are split\r\ninto separate network messages when nodes have different\r\ntopics. Format depends on transport (e.g., MQTT topic\r\nsyntax).", "type": "string" }, "QualityOfService": { "$ref": "#/definitions/QoS" }, "HeartbeatBehavior": { "$ref": "#/definitions/HeartbeatBehavior" }, "HeartbeatInterval": { "format": "int32", "description": "Node-specific heartbeat interval in milliseconds.\r\nOverrides DefaultHeartbeatInterval from parent\r\nconfiguration. Controls how often heartbeat messages are\r\ngenerated. Set to 0 to disable heartbeats for this node.\r\nIgnored when HeartbeatIntervalTimespan is defined.", "type": "integer" }, "HeartbeatIntervalTimespan": { "format": "date-span", "description": "Node-specific heartbeat interval as TimeSpan. Takes\r\nprecedence over HeartbeatInterval if both defined.\r\nOverrides DefaultHeartbeatIntervalTimespan setting.\r\nProvides more precise control over timing. Example:\r\n\"00:00:10\" for 10-second interval.", "type": "string" }, "SkipFirst": { "description": "Controls handling of initial value notification. True:\r\nSuppress first value from monitored item. False: Publish\r\ninitial value (default). Useful when only changes are\r\nrelevant. Server always sends initial value on creation.", "type": "boolean" }, "OpcPublishingInterval": { "format": "int32", "description": "Client-side publishing rate in milliseconds. Controls how\r\noften the server sends notifications. Must be >=\r\nOpcSamplingInterval for proper operation. Overrides\r\nDataSetPublishingInterval when specified. Ignored if\r\nOpcPublishingIntervalTimespan is defined.", "type": "integer" }, "OpcPublishingIntervalTimespan": { "format": "date-span", "description": "OpcPublishingInterval as TimeSpan.", "type": "string" }, "UseCyclicRead": { "description": "Use periodic reads instead of monitored items. True: Sample\r\nusing CyclicRead service calls False: Use standard\r\nsubscription monitoring (default) Useful for nodes that\r\ndon't support monitoring or when consistent sampling\r\ntiming is required. Consider CyclicReadMaxAge when\r\nenabled.", "type": "boolean" }, "RegisterNode": { "description": "Optimize node access using RegisterNodes service. True:\r\nRegister node for faster subsequent reads False: Use\r\ndirect node access (default) Can improve performance for\r\nfrequently accessed nodes. Server must support\r\nRegisterNodes service.", "type": "boolean" }, "FetchDisplayName": { "description": "Retrieve node's DisplayName attribute on startup. True:\r\nQuery and use actual display name False: Use configured\r\nDisplayName (default) Overrides DataSetFetchDisplayNames\r\nsetting. Used for human-readable field identification.", "type": "boolean" }, "ModelChangeHandling": { "$ref": "#/definitions/ModelChangeHandlingOptionsModel" }, "TriggeredNodes": { "description": "Collection of dependent nodes triggered by this node. Read\r\natomically when parent node changes. Limited to one level\r\nof triggering (no cascading). Useful for maintaining data\r\nconsistency between related measurements. Changes to\r\ntriggered nodes must be made through parent node's API\r\ncalls.", "type": "array", "items": { "$ref": "#/definitions/OpcNodeModel" } }, "CyclicReadMaxAge": { "format": "int32", "description": "Maximum age for cached values in cyclic reads. Specified in\r\nmilliseconds. Default: 0 (no caching) Only applies when\r\nUseCyclicRead is true. Server may return cached value if\r\nwithin max age. Helps reduce server load in high-frequency\r\nreads. Ignored when CyclicReadMaxAgeTimespan is defined.", "type": "integer" }, "CyclicReadMaxAgeTimespan": { "format": "date-span", "description": "Maximum age for cached values in cyclic reads as TimeSpan.\r\nTakes precedence over CyclicReadMaxAge if both defined.\r\nOnly applies when UseCyclicRead is true. Default:\r\n\"00:00:00\" (no caching) Example: \"00:00:00.500\" for 500ms\r\nmax cache age. Helps optimize read performance vs data\r\nfreshness.", "type": "string" }, "TypeDefinitionId": { "description": "A type definition id that references a well known opc ua\r\ntype definition node for the variable represented by this\r\nnode entry.", "type": "string" }, "MethodMetadata": { "$ref": "#/definitions/MethodMetadataModel" }, "ExpandedNodeId": { "description": "Alternative node identifier with full namespace URI. Same\r\nas Id but uses complete namespace URI instead of index.\r\nFormat: \"nsu={uri};{type}={value}\" Example:\r\n\"nsu=http://opcfoundation.org/UA/;i=2258\" Provides more\r\nportable node identification across servers.", "type": "string" } }, "additionalProperties": false }, "OperationContextModel": { "description": "Operation log model", "type": "object", "properties": { "AuthorityId": { "description": "User", "type": "string" }, "Time": { "format": "date-time", "description": "Operation time", "type": "string" } }, "additionalProperties": false }, "OperationLimitsModel": { "description": "Server limits", "type": "object", "properties": { "minSupportedSampleRate": { "format": "double", "description": "Min supported sampling rate", "type": "number" }, "maxBrowseContinuationPoints": { "format": "int32", "description": "Max browse continuation points", "type": "integer" }, "maxQueryContinuationPoints": { "format": "int32", "description": "Max query continuation points", "type": "integer" }, "maxHistoryContinuationPoints": { "format": "int32", "description": "Max history continuation points", "type": "integer" }, "maxArrayLength": { "format": "int64", "description": "Max array length supported", "type": "integer" }, "maxStringLength": { "format": "int64", "description": "Max string length supported", "type": "integer" }, "maxByteStringLength": { "format": "int64", "description": "Max byte buffer length supported", "type": "integer" }, "maxNodesPerBrowse": { "format": "int64", "description": "Max nodes that can be part of a single browse call.", "type": "integer" }, "maxNodesPerRead": { "format": "int64", "description": "Max nodes that can be read in single read call", "type": "integer" }, "maxNodesPerWrite": { "format": "int64", "description": "Max nodes that can be read in single write call", "type": "integer" }, "maxNodesPerMethodCall": { "format": "int64", "description": "Max nodes that can be read in single method call", "type": "integer" }, "maxNodesPerHistoryReadData": { "format": "int64", "description": "Number of nodes that can be in a History Read value call", "type": "integer" }, "maxNodesPerHistoryReadEvents": { "format": "int64", "description": "Number of nodes that can be in a History Read events call", "type": "integer" }, "maxNodesPerHistoryUpdateData": { "format": "int64", "description": "Number of nodes that can be in a History Update call", "type": "integer" }, "maxNodesPerHistoryUpdateEvents": { "format": "int64", "description": "Number of nodes that can be in a History events update call", "type": "integer" }, "maxNodesPerRegisterNodes": { "format": "int64", "description": "Max nodes that can be registered at once", "type": "integer" }, "maxNodesPerTranslatePathsToNodeIds": { "format": "int64", "description": "Max nodes that can be part of a browse path", "type": "integer" }, "maxNodesPerNodeManagement": { "format": "int64", "description": "Max nodes that can be added or removed in a single call.", "type": "integer" }, "maxMonitoredItemsPerCall": { "format": "int64", "description": "Max monitored items that can be updated at once.", "type": "integer" } }, "additionalProperties": false }, "ProblemDetails": { "type": "object", "properties": { "type": { "type": "string" }, "title": { "type": "string" }, "status": { "format": "int32", "type": "integer" }, "detail": { "type": "string" }, "instance": { "type": "string" } }, "additionalProperties": { } }, "PublishBulkRequestModel": { "description": "Publish in bulk request", "type": "object", "properties": { "nodesToAdd": { "description": "Node to add", "type": "array", "items": { "$ref": "#/definitions/PublishedItemModel" } }, "nodesToRemove": { "description": "Node to remove", "type": "array", "items": { "type": "string" } }, "header": { "$ref": "#/definitions/RequestHeaderModel" } }, "additionalProperties": false }, "PublishBulkRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/PublishBulkRequestModel" } }, "additionalProperties": false }, "PublishBulkResponseModel": { "description": "Result of bulk request", "type": "object", "properties": { "nodesToAdd": { "description": "Node to add", "type": "array", "items": { "$ref": "#/definitions/ServiceResultModel" } }, "nodesToRemove": { "description": "Node to remove", "type": "array", "items": { "$ref": "#/definitions/ServiceResultModel" } } }, "additionalProperties": false }, "PublishDiagnosticInfoModel": { "description": "Model for a diagnostic info.", "type": "object", "properties": { "endpoints": { "description": "Endpoints covered by the diagnostics model.\r\nThe endpoints are all part of the same writer\r\ngroup. Specify", "type": "array", "items": { "$ref": "#/definitions/PublishedNodesEntryModel" } }, "sentMessagesPerSec": { "format": "double", "description": "SentMessagesPerSec", "type": "number" }, "ingestionDuration": { "format": "date-span", "description": "IngestionDuration", "type": "string" }, "ingressDataChanges": { "format": "int64", "description": "IngressDataChanges", "type": "integer" }, "ingressValueChanges": { "format": "int64", "description": "IngressValueChanges", "type": "integer" }, "ingressBatchBlockBufferSize": { "format": "int64", "description": "IngressBatchBlockBufferSize", "type": "integer" }, "encodingBlockInputSize": { "format": "int64", "description": "EncodingBlockInputSize", "type": "integer" }, "encodingBlockOutputSize": { "format": "int64", "description": "EncodingBlockOutputSize", "type": "integer" }, "encoderNotificationsProcessed": { "format": "int64", "description": "EncoderNotificationsProcessed", "type": "integer" }, "encoderNotificationsDropped": { "format": "int64", "description": "EncoderNotificationsDropped", "type": "integer" }, "encoderIoTMessagesProcessed": { "format": "int64", "description": "EncoderIoTMessagesProcessed", "type": "integer" }, "encoderAvgNotificationsMessage": { "format": "double", "description": "EncoderAvgNotificationsMessage", "type": "number" }, "encoderAvgIoTMessageBodySize": { "format": "double", "description": "EncoderAvgIoTMessageBodySize", "type": "number" }, "encoderAvgIoTChunkUsage": { "format": "double", "description": "EncoderAvgIoTChunkUsage", "type": "number" }, "estimatedIoTChunksPerDay": { "format": "double", "description": "EstimatedIoTChunksPerDay", "type": "number" }, "outgressInputBufferCount": { "format": "int64", "description": "OutgressInputBufferCount", "type": "integer" }, "outgressInputBufferDropped": { "format": "int64", "description": "OutgressInputBufferDropped", "type": "integer" }, "outgressIoTMessageCount": { "format": "int64", "description": "OutgressIoTMessageCount", "type": "integer" }, "connectionRetries": { "format": "int64", "description": "ConnectionRetries", "type": "integer" }, "opcEndpointConnected": { "description": "OpcEndpointConnected", "type": "boolean" }, "monitoredOpcNodesSucceededCount": { "format": "int64", "description": "MonitoredOpcNodesSucceededCount", "type": "integer" }, "monitoredOpcNodesFailedCount": { "format": "int64", "description": "MonitoredOpcNodesFailedCount", "type": "integer" }, "ingressEventNotifications": { "format": "int64", "description": "Number of incoming event notifications", "type": "integer" }, "ingressEvents": { "format": "int64", "description": "Total incoming events so far.", "type": "integer" }, "encoderMaxMessageSplitRatio": { "format": "double", "description": "Encoder max message split ratio", "type": "number" }, "ingressDataChangesInLastMinute": { "format": "int64", "description": "Data changes received in the last minute", "type": "integer" }, "ingressValueChangesInLastMinute": { "format": "int64", "description": "Value changes received in the last minute", "type": "integer" }, "ingressHeartbeats": { "format": "int64", "description": "Number of heartbeats of the total value changes", "type": "integer" }, "ingressCyclicReads": { "format": "int64", "description": "Number of cyclic reads of the total value changes", "type": "integer" } }, "additionalProperties": false }, "PublishStartRequestModel": { "description": "Publish request", "required": [ "item" ], "type": "object", "properties": { "item": { "$ref": "#/definitions/PublishedItemModel" }, "header": { "$ref": "#/definitions/RequestHeaderModel" } }, "additionalProperties": false }, "PublishStartRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/PublishStartRequestModel" } }, "additionalProperties": false }, "PublishStartResponseModel": { "description": "Result of publish request", "type": "object", "properties": { "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "PublishStopRequestModel": { "description": "Unpublish request", "required": [ "nodeId" ], "type": "object", "properties": { "nodeId": { "description": "Node of published item to unpublish", "minLength": 1, "type": "string" }, "header": { "$ref": "#/definitions/RequestHeaderModel" } }, "additionalProperties": false }, "PublishStopRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/PublishStopRequestModel" } }, "additionalProperties": false }, "PublishStopResponseModel": { "description": "Result of publish stop request", "type": "object", "properties": { "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "PublishedItemListRequestModel": { "description": "Request list of published items", "type": "object", "properties": { "continuationToken": { "description": "Continuation token or null to start", "type": "string" }, "header": { "$ref": "#/definitions/RequestHeaderModel" } }, "additionalProperties": false }, "PublishedItemListRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/PublishedItemListRequestModel" } }, "additionalProperties": false }, "PublishedItemListResponseModel": { "description": "List of published nodes", "type": "object", "properties": { "items": { "description": "Monitored items", "type": "array", "items": { "$ref": "#/definitions/PublishedItemModel" } }, "continuationToken": { "description": "Continuation or null if final", "type": "string" } }, "additionalProperties": false }, "PublishedItemModel": { "description": "A monitored and published item", "required": [ "nodeId" ], "type": "object", "properties": { "nodeId": { "description": "Variable node monitored", "minLength": 1, "type": "string" }, "displayName": { "description": "Display name of the variable node monitored", "type": "string" }, "publishingInterval": { "format": "date-span", "description": "Publishing interval to use", "type": "string" }, "samplingInterval": { "format": "date-span", "description": "Sampling interval to use", "type": "string" }, "heartbeatInterval": { "format": "date-span", "description": "Heartbeat interval to use", "type": "string" } }, "additionalProperties": false }, "PublishedNodeDeleteAssetRequestModel": { "description": "Contains entry in the published nodes configuration representing\r\nthe asset as well as an optional request header.", "required": [ "entry" ], "type": "object", "properties": { "header": { "$ref": "#/definitions/RequestHeaderModel" }, "entry": { "$ref": "#/definitions/PublishedNodesEntryModel" }, "force": { "description": "The asset on the server is deleted no matter whether\r\nthe removal in the publisher configuration was successful\r\nor not.", "type": "boolean" } }, "additionalProperties": false }, "PublishedNodeExpansionModel": { "description": "\r\nNode expansion configuration. Configures how an entry should\r\n be expanded into configuration. If a node is an object it is\r\n expanded to all contained variables.\r\n\r\nIf a node is an object type, all objects of that type are\r\n searched from the object root node. These found objects are\r\n then expanded into their variables.\r\n\r\nIf the node is a variable, the variable is expanded to include\r\n all contained variables or properties. All entries will have\r\n the data set field id configured as data set class id.\r\n\r\nIf a node is a variable type, then all variables of this type\r\n are found and added to a single writer entry. Note: That by\r\n themselves these variables are no further expanded.", "type": "object", "properties": { "header": { "$ref": "#/definitions/RequestHeaderModel" }, "createSingleWriter": { "description": "By default the api will create a new distinct\r\nwriter per expanded object. Objects that cannot\r\nbe expanded are part of the originally provided\r\nwriter. The writer id is then post fixed with\r\nthe data set field id of the object node field.\r\nIf true, all variables of all expanded nodes are\r\nadded to the originally provided entry.", "type": "boolean" }, "maxLevelsToExpand": { "format": "int64", "description": "Max number of levels to expand an instance node\r\nsuch as an object or variable into resulting\r\nvariables.\r\nIf the node is a variable instance to start with\r\nbut the Azure.IIoT.OpcUa.Publisher.Models.PublishedNodeExpansionModel.ExcludeRootIfInstanceNode\r\nproperty is set to excluded it, then setting this\r\nvalue to 0 is equivalent to a value of 1 to get\r\nthe first level of variables contained in the\r\nvariable, but not the variable itself. Otherwise\r\nonly the variable itelf is returned. If the node\r\nis an object instance, 0 is equivalent to\r\ninfinite and all levels are expanded.", "type": "integer" }, "noSubTypesOfTypeNodes": { "description": "Do not consider subtypes of an object type when\r\nsearching for instances of the type.", "type": "boolean" }, "excludeRootIfInstanceNode": { "description": "If the node is an object or variable instance do\r\nnot include it but only the instances underneath\r\nthem.", "type": "boolean" }, "maxDepth": { "format": "int64", "description": "Max browse depth for object search operation or\r\nwhen searching for an instance of a type.\r\nTo only expand an object to its variables set\r\nthis value to 0. The depth of expansion of a\r\nvariable itself can be controlled via the\r\nAzure.IIoT.OpcUa.Publisher.Models.PublishedNodeExpansionModel.MaxLevelsToExpand\" property.\r\nIf the root object is excluded a value of 0 is\r\nequivalent to a value of 1 to get the first level\r\nof objects contained in the object but not the\r\nobject itself, e.g. a folder object.", "type": "integer" }, "flattenTypeInstance": { "description": "If false, treats instance nodes found just like\r\nobjects that need to be expanded. In case of a\r\ncompanion spec object type this could be set to\r\ntrue, flattening the structure into a single\r\nwriter that represents the object in its entirety.\r\nHowever, when using generic interfaces that can\r\nbe implemented across objects in the address\r\nspace and only its variables are important, it\r\nmight be useful to set this to false.", "type": "boolean" }, "includeMethods": { "description": "Include not just variables and events but also\r\nmethods when expanding an object.", "type": "boolean" }, "discardErrors": { "description": "Errors are silently discarded and only\r\nsuccessfully expanded nodes are returned.", "type": "boolean" }, "useBrowseNameAsDisplayName": { "description": "Use the browse name as display name for nodes. The\r\ndisplay name is rooted in the parent node from\r\nwhich browsing occurs, or just the browse name if\r\nthe browse root is not a parent.", "type": "boolean" } }, "additionalProperties": false }, "PublishedNodeExpansionModelPublishedNodesEntryRequestModel": { "description": "Wraps a request and a published nodes entry to bind to a\r\nbody more easily for api that requires an entry and additional\r\nconfiguration", "required": [ "entry" ], "type": "object", "properties": { "entry": { "$ref": "#/definitions/PublishedNodesEntryModel" }, "request": { "$ref": "#/definitions/PublishedNodeExpansionModel" } }, "additionalProperties": false }, "PublishedNodesEntryModel": { "description": "\r\nConfiguration model for OPC UA Publisher that defines how\r\n OPC UA nodes are published to messaging systems. Used to\r\n configure connections to OPC UA servers, setup node\r\n monitoring, and control message publishing.\r\n\r\nKey features:\r\n - Endpoint configuration and security settings\r\n - Writer group and dataset organization\r\n - Publishing intervals and sampling controls\r\n - Message batching and triggering\r\n - Subscription and monitoring options\r\n - Heartbeat and watchdog behaviors\r\n - Security modes and authentication\r\n\r\nFor detailed configuration options, see individual\r\n properties.", "required": [ "EndpointUrl" ], "type": "object", "properties": { "Version": { "format": "int64", "description": "A monotonically increasing number identifying the change\r\nversion. At this point the version number is informational\r\nonly, but should be provided in API requests if available.\r\nNot used inside file based configuration.", "type": "integer" }, "LastChangeDateTime": { "format": "date-time", "description": "The time the Publisher configuration was last updated.\r\nRead only and informational only.", "type": "string" }, "DataSetWriterId": { "description": "The unique identifier for a data set writer used to collect\r\nOPC UA nodes to be semantically grouped and published with\r\nthe same publishing interval. When not specified, uses a\r\nstring representing the common publishing interval of the\r\nnodes in the data set collection. This attribute uniquely\r\nidentifies a data set within a DataSetWriterGroup. The\r\nuniqueness is determined using the provided DataSetWriterId\r\nand the publishing interval of the grouped OpcNodes.", "type": "string" }, "DataSetWriterGroup": { "description": "The data set writer group collecting datasets defined for a\r\ncertain endpoint. This attribute is used to identify the\r\nsession opened into the server. The default value consists\r\nof the EndpointUrl string, followed by a deterministic hash\r\ncomposed of the EndpointUrl, UseSecurity,\r\nOpcAuthenticationMode, UserName and Password attributes.", "type": "string" }, "OpcNodes": { "description": "The DataSet collection grouping the nodes to be published\r\nfor the specific DataSetWriter. Each node can specify\r\nmonitoring parameters including sampling intervals, deadband\r\nsettings, and event filtering options. Contains variable\r\nnodes or event notifiers to monitor.", "type": "array", "items": { "$ref": "#/definitions/OpcNodeModel" } }, "DataSetClassId": { "format": "uuid", "description": "The optional dataset class id as it shall appear in dataset\r\nmessages and dataset metadata. Used to uniquely identify the\r\ntype of dataset being published. Default: Guid.Empty", "type": "string" }, "DataSetName": { "description": "The optional name of the dataset as it will appear in the\r\ndataset metadata. Used for identification and organization\r\nof datasets.", "type": "string" }, "DataSetPublishingInterval": { "format": "int32", "description": "The publishing interval used for a grouped set of nodes\r\nunder a certain DataSetWriter, expressed in milliseconds.\r\nWhen a specific node underneath DataSetWriter defines\r\nOpcPublishingInterval (or Timespan), its value will\r\noverwrite this interval and potentially split the data set\r\nwriter into more than one subscription. Ignored when\r\nDataSetPublishingIntervalTimespan is present.", "type": "integer" }, "DataSetPublishingIntervalTimespan": { "format": "date-span", "description": "The publishing interval for a dataset writer, expressed as a\r\nTimeSpan value. Takes precedence over\r\nDataSetPublishingInterval if defined. Provides more precise\r\ncontrol over timing than milliseconds. When overridden by\r\nnode-specific intervals, the writer may split into multiple\r\nsubscriptions.", "type": "string" }, "DataSetKeyFrameCount": { "format": "int64", "description": "Controls key frame insertion frequency in the message\r\nstream. A key frame contains all current values, while\r\ndelta frames only contain changes. Setting this ensures\r\nperiodic complete state updates, useful for late-joining\r\nconsumers or state synchronization. Key frames can also\r\ninclude configured DataSetExtensionFields for additional\r\ncontext. Default: 0 (key frames disabled)", "type": "integer" }, "MetaDataUpdateTime": { "format": "int32", "description": "The interval in milliseconds at which metadata messages are\r\nsent, even when the metadata has not changed. Only applies\r\nwhen metadata messaging is supported or explicitly enabled.\r\nIgnored when MetaDataUpdateTimeTimespan is defined.", "type": "integer" }, "MetaDataUpdateTimeTimespan": { "format": "date-span", "description": "The interval as TimeSpan at which metadata messages are\r\nsent, even when metadata has not changed. Takes precedence\r\nover MetaDataUpdateTime if both are defined. Only applies\r\nwhen metadata messaging is supported or explicitly enabled.", "type": "string" }, "SendKeepAliveDataSetMessages": { "description": "Controls whether to send keep alive messages for this\r\ndataset when a subscription keep alive notification is\r\nreceived. Keep alive messages help maintain connection\r\nstatus awareness. Only valid if the messaging mode supports\r\nkeep alive messages. Default: false", "type": "boolean" }, "EndpointUrl": { "description": "The required OPC UA server endpoint URL to connect to. This\r\nis the only required field in the configuration. Format:\r\n\"opc.tcp://host:port/path\"", "minLength": 1, "type": "string" }, "MaxKeepAliveCount": { "format": "int64", "description": "Defines how many publishing timer expirations to wait\r\nbefore sending a keep-alive message when no notifications\r\nare pending. Works with SendKeepAliveDataSetMessages to\r\nmaintain connection awareness. Keep-alive messages help\r\ndetect connection issues even when no data changes are\r\noccurring.", "type": "integer" }, "DataSetDescription": { "description": "The optional description of the dataset.", "type": "string" }, "Priority": { "format": "int32", "description": "Priority of the writer subscription.", "type": "integer" }, "DataSetExtensionFields": { "description": "Optional key-value pairs inserted into key frame and\r\nmetadata messages in the same data set. Values are\r\nformatted using OPC UA Variant JSON encoding. Used to add\r\ncontextual information to datasets.", "type": "object", "additionalProperties": { "description": "A variant which can be represented by any value including null.", "type": "object" } }, "EndpointSecurityMode": { "$ref": "#/definitions/SecurityMode" }, "EndpointSecurityPolicy": { "description": "The security policy URI to use for the endpoint connection.\r\nOverrides UseSecurity setting and refines\r\nEndpointSecurityMode choice. Examples include\r\n\"http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256\".\r\nIf the specified policy is not available with the chosen\r\nsecurity mode, connectivity will fail. This allows enforcing\r\nspecific security requirements.", "type": "string" }, "MessagingMode": { "$ref": "#/definitions/MessagingMode" }, "MessageEncoding": { "$ref": "#/definitions/MessageEncoding" }, "BatchSize": { "format": "int64", "description": "The number of notifications that are queued before a\r\nnetwork message is generated. Controls message batching for\r\noptimizing network traffic vs latency. For historic reasons\r\nthe default value is 50 unless otherwise configured via the\r\n--bs command line option.", "type": "integer" }, "BatchTriggerInterval": { "format": "int32", "description": "The interval at which batched network messages are\r\npublished, in milliseconds. Messages are published when\r\nthis interval elapses or when BatchSize is reached. For\r\nhistoric reasons the default is 10 seconds unless\r\nconfigured via --bi. Ignored when\r\nBatchTriggerIntervalTimespan is specified. Used with\r\nBatchSize to optimize network traffic vs latency.", "type": "integer" }, "BatchTriggerIntervalTimespan": { "format": "date-span", "description": "The interval at which batched network messages are\r\npublished, as a TimeSpan. Takes precedence over\r\nBatchTriggerInterval if both are defined. Messages are\r\npublished when this interval elapses or when BatchSize is\r\nreached. Provides more precise control over publishing\r\ntiming than millisecond interval. Used with BatchSize to\r\noptimize network traffic vs latency.", "type": "string" }, "UseReverseConnect": { "description": "Use reverse connect to connect ot the endpoint", "type": "boolean" }, "DataSetRouting": { "$ref": "#/definitions/DataSetRoutingMode" }, "WriterGroupQueueName": { "description": "Overrides the default writer group topic template for\r\nmessage routing. Used to customize where messages from this\r\nwriter group are published. Particularly useful when\r\npublishing to MQTT topics or message queues where specific\r\nrouting patterns are needed.", "type": "string" }, "WriterGroupQualityOfService": { "$ref": "#/definitions/QoS" }, "WriterGroupTransport": { "$ref": "#/definitions/WriterGroupTransport" }, "UseSecurity": { "description": "Controls whether to use a secure OPC UA transport mode to\r\nestablish a session. When true, defaults to\r\nSecurityMode.NotNone which requires signed or encrypted\r\ncommunication. When false, uses SecurityMode.None with no\r\nsecurity. Can be overridden by EndpointSecurityMode and\r\nEndpointSecurityPolicy settings. Use encrypted\r\ncommunication whenever possible to protect credentials and\r\ndata.", "type": "boolean" }, "OpcAuthenticationMode": { "$ref": "#/definitions/OpcAuthenticationMode" }, "EncryptedAuthUsername": { "description": "The encrypted username for authentication when\r\nOpcAuthenticationMode is UsernamePassword. Encrypted\r\ncredentials at rest can be enforced using the --fce command\r\nline option. Version 2.6+ stores credentials in plain text\r\nby default, while 2.5 and below always encrypted them.", "type": "string" }, "EncryptedAuthPassword": { "description": "The encrypted password for authentication when\r\nOpcAuthenticationMode is UsernamePassword. For certificate\r\nauthentication, contains the password to access the private\r\nkey. Encrypted credentials at rest can be enforced using\r\nthe --fce command line option. Version 2.6+ stores\r\ncredentials in plain text by default, while 2.5 and below\r\nalways encrypted them.", "type": "string" }, "OpcAuthenticationUsername": { "description": "The plaintext username for UsernamePassword authentication,\r\nor the subject name of the certificate for Certificate\r\nauthentication. When using Certificate mode, this refers to\r\na certificate in the User certificate store of the PKI\r\nconfiguration.", "type": "string" }, "OpcAuthenticationPassword": { "description": "The plaintext password for UsernamePassword authentication,\r\nor the password protecting the private key for Certificate\r\nauthentication. For Certificate mode, this must match the\r\npassword used when adding the certificate to the PKI store.", "type": "string" }, "QueueName": { "description": "Overrides the writer group queue name at the individual\r\nwriter level. When specified, causes network messages to be\r\nsplit across different queues. The split also takes QoS\r\nsettings into account, allowing fine-grained control over\r\nmessage routing and delivery guarantees.", "type": "string" }, "MetaDataQueueName": { "description": "The queue name to use for metadata messages from this\r\nwriter. Overrides the default metadata topic template.\r\nAllows routing metadata to specific destinations separate\r\nfrom data messages.", "type": "string" }, "QualityOfService": { "$ref": "#/definitions/QoS" }, "WriterGroupPartitions": { "format": "int32", "description": "Specifies how many partitions to split the writer group\r\ninto when publishing to target topics. Used to distribute\r\nmessage load and enable parallel processing by consumers.\r\nDefault is 1 partition. Particularly useful for\r\nhigh-throughput scenarios or when using partitioned\r\nqueues/topics in the messaging system.", "type": "integer" }, "DisableSubscriptionTransfer": { "description": "Controls whether subscription transfer is disabled during\r\nreconnect. When false (default), attempts to transfer\r\nsubscriptions on reconnect to maintain data continuity. Set\r\nto true to fix interoperability issues with servers that\r\ndon't support subscription transfer. Can be configured\r\nglobally via command line options.", "type": "boolean" }, "RepublishAfterTransfer": { "description": "Controls whether to republish missed values after a\r\nsubscription is transferred during reconnect handling. Only\r\napplies when DisableSubscriptionTransfer is false. Helps\r\nensure no data is lost during connection interruptions.\r\nDefault: true", "type": "boolean" }, "OpcNodeWatchdogTimespan": { "format": "date-span", "description": "The timeout duration used to monitor whether monitored\r\nitems in the subscription are continuously reporting fresh\r\ndata. This watchdog mechanism helps detect stale data or\r\nconnectivity issues. When this timeout expires, the\r\nconfigured DataSetWriterWatchdogBehavior is triggered based\r\non OpcNodeWatchdogCondition. Expressed as a TimeSpan value.", "type": "string" }, "DataSetWriterWatchdogBehavior": { "$ref": "#/definitions/SubscriptionWatchdogBehavior" }, "OpcNodeWatchdogCondition": { "$ref": "#/definitions/MonitoredItemWatchdogCondition" }, "DataSetSamplingInterval": { "format": "int32", "description": "Default sampling interval in milliseconds for all monitored\r\nitems in the dataset. Used if individual nodes don't\r\nspecify their own sampling interval. Follows OPC UA\r\nspecification for sampling behavior. Ignored when\r\nDataSetSamplingIntervalTimespan is present. Defaults to\r\nvalue configured via --oi command line option.", "type": "integer" }, "DataSetSamplingIntervalTimespan": { "format": "date-span", "description": "Default sampling interval as TimeSpan for all monitored\r\nitems in the dataset. Takes precedence over\r\nDataSetSamplingInterval if both are defined. Used if\r\nindividual nodes don't specify their own sampling interval.\r\nProvides more precise control over sampling timing. Follows\r\nOPC UA specification for sampling behavior.", "type": "string" }, "DataSetFetchDisplayNames": { "description": "Controls whether to fetch display names of monitored\r\nvariable nodes and use those inside messages as field\r\nnames. When true, fetches display names for all nodes. If\r\nfalse, uses DisplayName value if provided; if not provided,\r\nuses the node id. Can be configured via --fd command line\r\noption.", "type": "boolean" }, "WriterGroupMessageTtlTimepan": { "format": "date-span", "description": "Time-to-live duration for messages sent through the writer\r\ngroup. Only applied if the transport technology supports\r\nmessage TTL. After this duration expires, messages may be\r\ndiscarded by the messaging system. Used to prevent stale\r\ndata from being processed by consumers.", "type": "string" }, "WriterGroupMessageRetention": { "description": "Controls whether messages should be retained by the\r\nmessaging system. Only applied if the transport technology\r\nsupports message retention. When true, messages are kept by\r\nthe broker even after delivery. Useful for late-joining\r\nsubscribers to receive the last known values.", "type": "boolean" }, "MessageTtlTimespan": { "format": "date-span", "description": "Time-to-live duration for messages sent by this specific\r\nwriter. Overrides WriterGroupMessageTtlTimespan at the\r\nindividual writer level. Only applied if the transport\r\ntechnology supports message TTL. Allows different TTL\r\nsettings for different types of data.", "type": "string" }, "MessageRetention": { "description": "Controls message retention for this specific writer.\r\nOverrides WriterGroupMessageRetention at the individual\r\nwriter level. Only applied if the transport technology\r\nsupports retention. Together with QueueName, allows\r\nsplitting messages across different queues with different\r\nretention policies.", "type": "boolean" }, "DefaultHeartbeatInterval": { "format": "int32", "description": "The interval in milliseconds at which to publish heartbeat\r\nmessages. Heartbeat acts like a watchdog that fires after\r\nthis interval has passed and no new value has been\r\nreceived. A value of 0 disables heartbeat. Ignored when\r\nDefaultHeartbeatIntervalTimespan is defined. See\r\nheartbeat.md for detailed behavior documentation.", "type": "integer" }, "DefaultHeartbeatIntervalTimespan": { "format": "date-span", "description": "The heartbeat interval as TimeSpan for all nodes in this\r\ndataset. Takes precedence over DefaultHeartbeatInterval if\r\ndefined. Controls how often heartbeat messages are\r\npublished when no value changes occur.", "type": "string" }, "DefaultHeartbeatBehavior": { "$ref": "#/definitions/HeartbeatBehavior" }, "DataSetSourceUri": { "description": "Contains an uri identifier that allows correlation of the writer\r\ndata set source into other systems. Will be used as part of\r\ncloud events header if enabled.", "type": "string" }, "DataSetSubject": { "description": "Contains an identifier that allows correlation of the writer\r\ngroup into other systems in the context of the source. Will be\r\nused as part of cloud events header if enabled.", "type": "string" }, "WriterGroupProperties": { "description": "Additional properties of the writer group that should be retained\r\nwith the configuration.", "type": "object", "additionalProperties": { "description": "A variant which can be represented by any value including null.", "type": "object" } }, "DataSetType": { "description": "A type definition id that references a well known opc ua type\r\ndefinition node for the dataset represented by this entry.\r\nIf set it is used in context of cloud events to specify a concrete\r\ntype of dataset message in the cloud events type header.", "type": "string" }, "DataSetRootNodeId": { "description": "A root node that all nodes that use a non rooted browse paths in the\r\ndataset should start from.", "type": "string" }, "WriterGroupRootNodeId": { "description": "A node that represents the writer group in the server address space.\r\nThis is the instance id of the root node from which all datasets\r\noriginate. It is informational only and would not need to be\r\nconfigured", "type": "string" }, "WriterGroupType": { "description": "A type that is attached to the writer group and explains the shape\r\nof the writer group. It is the type definition id of the writer\r\ngroup root node id. It is informational only and would not need\r\nto be configured", "type": "string" }, "MetaDataRetention": { "description": "Metadata retention setting for the dataset writer.", "type": "boolean" }, "MetaDataTtlTimespan": { "format": "date-span", "description": "Metadata time-to-live duration for the dataset writer.", "type": "string" }, "SendKeepAliveAsKeyFrameMessages": { "description": "When sending of keep alive messages is enabled, this\r\nflag controls whether the keep alive messages are sent\r\nas key frames. Key frames contain all current values.", "type": "boolean" }, "PublisherId": { "description": "Set a publisher id to use that is different form the\r\nglobal publisher identity.", "type": "string" }, "WriterGroupTransportConfiguration": { "description": "Pass connection string for the transport layer. This works\r\nfor transports that support connection strings such as\r\nIoT Hub or Event Hubs. It enables overriding the default\r\nconnection string configured for the publisher. The transport\r\nmust be configured using the command line options first, and\r\ncan be overriden here. If it is not configured on the command\r\nline first, the setting here is ignored.", "type": "string" }, "DumpConnectionDiagnostics": { "description": "Enables detailed server diagnostics logging for the\r\nconnection. When enabled, provides additional diagnostic\r\ninformation useful for troubleshooting connectivity,\r\nauthentication, and subscription issues. The diagnostics\r\ndata is included in the publisher's logs. Default: false", "type": "boolean" }, "NodeId": { "$ref": "#/definitions/NodeIdModel" } }, "additionalProperties": false }, "PublishedNodesEntryModelServiceResponse": { "description": "Response envelope", "type": "object", "properties": { "result": { "$ref": "#/definitions/PublishedNodesEntryModel" }, "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "PublishedNodesEntryModelServiceResponseIAsyncEnumerable": { "type": "object", "additionalProperties": false }, "PublishedNodesResponseModel": { "description": "PublishNodes direct method response", "type": "object", "additionalProperties": false }, "QoS": { "enum": [ "AtMostOnce", "AtLeastOnce", "ExactlyOnce" ], "type": "string", "x-ms-enum": { "name": "QoS", "modelAsString": false } }, "QueryCompilationRequestModel": { "description": "Query compiler request model", "required": [ "query" ], "type": "object", "properties": { "header": { "$ref": "#/definitions/RequestHeaderModel" }, "query": { "description": "The query to compile.", "minLength": 1, "type": "string" }, "queryType": { "$ref": "#/definitions/QueryType" } }, "additionalProperties": false }, "QueryCompilationRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/QueryCompilationRequestModel" } }, "additionalProperties": false }, "QueryCompilationResponseModel": { "description": "Query compiler response model", "type": "object", "properties": { "errorInfo": { "$ref": "#/definitions/ServiceResultModel" }, "eventFilter": { "$ref": "#/definitions/EventFilterModel" } }, "additionalProperties": false }, "QueryType": { "description": "Query type", "enum": [ "Event", "Query" ], "type": "string", "x-ms-enum": { "name": "QueryType", "modelAsString": false } }, "ReadEventsDetailsModel": { "description": "Read event data", "type": "object", "properties": { "startTime": { "format": "date-time", "description": "Start time to read from", "type": "string" }, "endTime": { "format": "date-time", "description": "End time to read to", "type": "string" }, "numEvents": { "format": "int64", "description": "Number of events to read", "type": "integer" }, "filter": { "$ref": "#/definitions/EventFilterModel" } }, "additionalProperties": false }, "ReadEventsDetailsModelHistoryReadRequestModel": { "description": "Request node history read", "required": [ "details" ], "type": "object", "properties": { "nodeId": { "description": "Node to read from (mandatory without browse path)", "type": "string" }, "browsePath": { "description": "An optional path from NodeId instance to\r\nthe actual node.", "type": "array", "items": { "type": "string" } }, "details": { "$ref": "#/definitions/ReadEventsDetailsModel" }, "indexRange": { "description": "Index range to read, e.g. 1:2,0:1 for 2 slices\r\nout of a matrix or 0:1 for the first item in\r\nan array, string or bytestring.\r\nSee 7.22 of part 4: NumericRange.", "type": "string" }, "header": { "$ref": "#/definitions/RequestHeaderModel" }, "timestampsToReturn": { "$ref": "#/definitions/TimestampsToReturn" } }, "additionalProperties": false }, "ReadEventsDetailsModelHistoryReadRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/ReadEventsDetailsModelHistoryReadRequestModel" } }, "additionalProperties": false }, "ReadModifiedValuesDetailsModel": { "description": "Read modified data", "type": "object", "properties": { "startTime": { "format": "date-time", "description": "The start time to read from", "type": "string" }, "endTime": { "format": "date-time", "description": "The end time to read to", "type": "string" }, "numValues": { "format": "int64", "description": "The number of values to read", "type": "integer" } }, "additionalProperties": false }, "ReadModifiedValuesDetailsModelHistoryReadRequestModel": { "description": "Request node history read", "required": [ "details" ], "type": "object", "properties": { "nodeId": { "description": "Node to read from (mandatory without browse path)", "type": "string" }, "browsePath": { "description": "An optional path from NodeId instance to\r\nthe actual node.", "type": "array", "items": { "type": "string" } }, "details": { "$ref": "#/definitions/ReadModifiedValuesDetailsModel" }, "indexRange": { "description": "Index range to read, e.g. 1:2,0:1 for 2 slices\r\nout of a matrix or 0:1 for the first item in\r\nan array, string or bytestring.\r\nSee 7.22 of part 4: NumericRange.", "type": "string" }, "header": { "$ref": "#/definitions/RequestHeaderModel" }, "timestampsToReturn": { "$ref": "#/definitions/TimestampsToReturn" } }, "additionalProperties": false }, "ReadModifiedValuesDetailsModelHistoryReadRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/ReadModifiedValuesDetailsModelHistoryReadRequestModel" } }, "additionalProperties": false }, "ReadProcessedValuesDetailsModel": { "description": "Read processed historic data", "type": "object", "properties": { "startTime": { "format": "date-time", "description": "Start time to read from.", "type": "string" }, "endTime": { "format": "date-time", "description": "End time to read until", "type": "string" }, "processingInterval": { "format": "date-span", "description": "Interval to process", "type": "string" }, "aggregateType": { "description": "The aggregate type to apply. Can be the name of\r\nthe aggregate if available in the history server\r\ncapabilities, or otherwise will be used as a node\r\nid referring to the aggregate.", "type": "string" }, "aggregateConfiguration": { "$ref": "#/definitions/AggregateConfigurationModel" } }, "additionalProperties": false }, "ReadProcessedValuesDetailsModelHistoryReadRequestModel": { "description": "Request node history read", "required": [ "details" ], "type": "object", "properties": { "nodeId": { "description": "Node to read from (mandatory without browse path)", "type": "string" }, "browsePath": { "description": "An optional path from NodeId instance to\r\nthe actual node.", "type": "array", "items": { "type": "string" } }, "details": { "$ref": "#/definitions/ReadProcessedValuesDetailsModel" }, "indexRange": { "description": "Index range to read, e.g. 1:2,0:1 for 2 slices\r\nout of a matrix or 0:1 for the first item in\r\nan array, string or bytestring.\r\nSee 7.22 of part 4: NumericRange.", "type": "string" }, "header": { "$ref": "#/definitions/RequestHeaderModel" }, "timestampsToReturn": { "$ref": "#/definitions/TimestampsToReturn" } }, "additionalProperties": false }, "ReadProcessedValuesDetailsModelHistoryReadRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/ReadProcessedValuesDetailsModelHistoryReadRequestModel" } }, "additionalProperties": false }, "ReadRequestModel": { "description": "Request node attribute read", "required": [ "attributes" ], "type": "object", "properties": { "attributes": { "description": "Attributes to read", "type": "array", "items": { "$ref": "#/definitions/AttributeReadRequestModel" } }, "header": { "$ref": "#/definitions/RequestHeaderModel" } }, "additionalProperties": false }, "ReadRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/ReadRequestModel" } }, "additionalProperties": false }, "ReadResponseModel": { "description": "Result of attribute reads", "required": [ "results" ], "type": "object", "properties": { "results": { "description": "All results of attribute reads", "type": "array", "items": { "$ref": "#/definitions/AttributeReadResponseModel" } }, "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "ReadValuesAtTimesDetailsModel": { "description": "Read data at specified times", "required": [ "reqTimes" ], "type": "object", "properties": { "reqTimes": { "description": "Requested datums", "type": "array", "items": { "format": "date-time", "type": "string" } }, "useSimpleBounds": { "description": "Whether to use simple bounds", "type": "boolean" } }, "additionalProperties": false }, "ReadValuesAtTimesDetailsModelHistoryReadRequestModel": { "description": "Request node history read", "required": [ "details" ], "type": "object", "properties": { "nodeId": { "description": "Node to read from (mandatory without browse path)", "type": "string" }, "browsePath": { "description": "An optional path from NodeId instance to\r\nthe actual node.", "type": "array", "items": { "type": "string" } }, "details": { "$ref": "#/definitions/ReadValuesAtTimesDetailsModel" }, "indexRange": { "description": "Index range to read, e.g. 1:2,0:1 for 2 slices\r\nout of a matrix or 0:1 for the first item in\r\nan array, string or bytestring.\r\nSee 7.22 of part 4: NumericRange.", "type": "string" }, "header": { "$ref": "#/definitions/RequestHeaderModel" }, "timestampsToReturn": { "$ref": "#/definitions/TimestampsToReturn" } }, "additionalProperties": false }, "ReadValuesAtTimesDetailsModelHistoryReadRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/ReadValuesAtTimesDetailsModelHistoryReadRequestModel" } }, "additionalProperties": false }, "ReadValuesDetailsModel": { "description": "Read historic values", "type": "object", "properties": { "startTime": { "format": "date-time", "description": "Beginning of period to read. Set to null\r\nif no specific start time is specified.", "type": "string" }, "endTime": { "format": "date-time", "description": "End of period to read. Set to null if no\r\nspecific end time is specified.", "type": "string" }, "numValues": { "format": "int64", "description": "The maximum number of values returned for any Node\r\nover the time range. If only one time is specified,\r\nthe time range shall extend to return this number\r\nof values. 0 or null indicates that there is no\r\nmaximum.", "type": "integer" }, "returnBounds": { "description": "Whether to return the bounding values or not.", "type": "boolean" } }, "additionalProperties": false }, "ReadValuesDetailsModelHistoryReadRequestModel": { "description": "Request node history read", "required": [ "details" ], "type": "object", "properties": { "nodeId": { "description": "Node to read from (mandatory without browse path)", "type": "string" }, "browsePath": { "description": "An optional path from NodeId instance to\r\nthe actual node.", "type": "array", "items": { "type": "string" } }, "details": { "$ref": "#/definitions/ReadValuesDetailsModel" }, "indexRange": { "description": "Index range to read, e.g. 1:2,0:1 for 2 slices\r\nout of a matrix or 0:1 for the first item in\r\nan array, string or bytestring.\r\nSee 7.22 of part 4: NumericRange.", "type": "string" }, "header": { "$ref": "#/definitions/RequestHeaderModel" }, "timestampsToReturn": { "$ref": "#/definitions/TimestampsToReturn" } }, "additionalProperties": false }, "ReadValuesDetailsModelHistoryReadRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/ReadValuesDetailsModelHistoryReadRequestModel" } }, "additionalProperties": false }, "RequestHeaderModel": { "description": "Request header model", "type": "object", "properties": { "elevation": { "$ref": "#/definitions/CredentialModel" }, "locales": { "description": "Optional list of preferred locales in preference\r\norder to be used during connecting the session.\r\nWe suggest to use the connection object to set\r\nthe locales", "type": "array", "items": { "type": "string" } }, "diagnostics": { "$ref": "#/definitions/DiagnosticsModel" }, "namespaceFormat": { "$ref": "#/definitions/NamespaceFormat" }, "operationTimeout": { "format": "int32", "description": "Operation timeout in ms. This applies to every\r\noperation that is invoked, not to the entire\r\ntransaction and overrides the configured operation\r\ntimeout.", "type": "integer" }, "serviceCallTimeout": { "format": "int32", "description": "Service call timeout in ms. As opposed to the\r\noperation timeout this terminates the entire\r\ntransaction if it takes longer than the timeout to\r\ncomplete. Note that a connect and reconnect during\r\nthe service call is gated by the connect timeout\r\nsetting. If a connect timeout is not specified\r\nthis timeout is used also for connect timeout.", "type": "integer" }, "connectTimeout": { "format": "int32", "description": "Connect timeout in ms. As opposed to the service call\r\ntimeout this terminates the entire transaction if\r\nit takes longer than the timeout to connect a session\r\nA connect and reconnect during the service call\r\nresets the timeout therefore the overall time for\r\nthe call to complete can be longer than specified.", "type": "integer" } }, "additionalProperties": false }, "RequestHeaderModelPublishedNodesEntryRequestModel": { "description": "Wraps a request and a published nodes entry to bind to a\r\nbody more easily for api that requires an entry and additional\r\nconfiguration", "required": [ "entry" ], "type": "object", "properties": { "entry": { "$ref": "#/definitions/PublishedNodesEntryModel" }, "request": { "$ref": "#/definitions/RequestHeaderModel" } }, "additionalProperties": false }, "RequestHeaderModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/RequestHeaderModel" } }, "additionalProperties": false }, "RolePermissionModel": { "description": "Role permission model", "required": [ "roleId" ], "type": "object", "properties": { "roleId": { "description": "Identifier of the role object.", "minLength": 1, "type": "string" }, "permissions": { "$ref": "#/definitions/RolePermissions" } }, "additionalProperties": false }, "RolePermissions": { "description": "Individual permissions assigned to a role", "enum": [ "None", "Browse", "ReadRolePermissions", "WriteAttribute", "WriteRolePermissions", "WriteHistorizing", "Read", "Write", "ReadHistory", "InsertHistory", "ModifyHistory", "DeleteHistory", "ReceiveEvents", "Call", "AddReference", "RemoveReference", "DeleteNode", "AddNode" ], "type": "string", "x-ms-enum": { "name": "RolePermissions", "modelAsString": false } }, "SecurityMode": { "description": "Specifies the security mode for OPC UA endpoint connections.\r\nDetermines how messages are protected during transmission between\r\nthe Publisher and OPC UA servers. Proper security mode selection\r\nis crucial for protecting sensitive data and credentials.", "enum": [ "Best", "Sign", "SignAndEncrypt", "None", "NotNone" ], "type": "string", "x-ms-enum": { "name": "SecurityMode", "modelAsString": false } }, "ServerCapabilitiesModel": { "description": "Server capabilities", "required": [ "operationLimits" ], "type": "object", "properties": { "operationLimits": { "$ref": "#/definitions/OperationLimitsModel" }, "supportedLocales": { "description": "Supported locales", "type": "array", "items": { "type": "string" } }, "serverProfileArray": { "description": "Server profiles", "type": "array", "items": { "type": "string" } }, "modellingRules": { "description": "Supported modelling rules", "type": "object", "additionalProperties": { "type": "string" } }, "aggregateFunctions": { "description": "Supported aggregate functions", "type": "object", "additionalProperties": { "type": "string" } }, "MaxSessions": { "format": "int64", "description": "Supported aggregate functions", "type": "integer" }, "MaxSubscriptions": { "format": "int64", "description": "Supported aggregate functions", "type": "integer" }, "MaxMonitoredItems": { "format": "int64", "description": "Supported aggregate functions", "type": "integer" }, "MaxSubscriptionsPerSession": { "format": "int64", "description": "Supported aggregate functions", "type": "integer" }, "MaxMonitoredItemsPerSubscription": { "format": "int64", "description": "Supported aggregate functions", "type": "integer" }, "MaxSelectClauseParameters": { "format": "int64", "description": "Supported aggregate functions", "type": "integer" }, "MaxWhereClauseParameters": { "format": "int64", "description": "Supported aggregate functions", "type": "integer" }, "MaxMonitoredItemsQueueSize": { "format": "int64", "description": "Supported aggregate functions", "type": "integer" }, "conformanceUnits": { "description": "Supported aggregate functions", "type": "array", "items": { "type": "string" } } }, "additionalProperties": false }, "ServerEndpointQueryModel": { "description": "Endpoint model", "type": "object", "properties": { "discoveryUrl": { "description": "Discovery url to use to query", "type": "string" }, "url": { "description": "Endpoint url that should match the found endpoint", "type": "string" }, "securityMode": { "$ref": "#/definitions/SecurityMode" }, "securityPolicy": { "description": "Endpoint must support this Security policy.", "type": "string" }, "certificate": { "description": "Endpoint must match with this certificate thumbprint", "type": "string" } }, "additionalProperties": false }, "ServerRegistrationRequestModel": { "description": "Server registration request", "required": [ "discoveryUrl" ], "type": "object", "properties": { "discoveryUrl": { "description": "Discovery url to use for registration", "minLength": 1, "type": "string" }, "id": { "description": "User defined request id", "type": "string" }, "context": { "$ref": "#/definitions/OperationContextModel" } }, "additionalProperties": false }, "ServiceResultModel": { "description": "Service result", "type": "object", "properties": { "statusCode": { "format": "int64", "description": "Error code - if null operation succeeded.", "type": "integer" }, "errorMessage": { "description": "Error message in case of error or null.", "type": "string" }, "symbolicId": { "description": "Symbolic identifier", "type": "string" }, "locale": { "description": "Locale of the error message", "type": "string" }, "additionalInfo": { "description": "Additional information if available", "type": "string" }, "namespaceUri": { "description": "Namespace uri", "type": "string" }, "inner": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "SetConfiguredEndpointsRequestModel": { "description": "Set configured endpoints request call", "type": "object", "properties": { "endpoints": { "description": "Endpoints and nodes that make up the configuration", "type": "array", "items": { "$ref": "#/definitions/PublishedNodesEntryModel" } } }, "additionalProperties": false }, "SimpleAttributeOperandModel": { "description": "Simple attribute operand model", "type": "object", "properties": { "typeDefinitionId": { "description": "Type definition node id if operand is\r\nsimple or full attribute operand.", "type": "string" }, "browsePath": { "description": "Browse path of attribute operand", "type": "array", "items": { "type": "string" } }, "attributeId": { "$ref": "#/definitions/NodeAttribute" }, "indexRange": { "description": "Index range of attribute operand", "type": "string" }, "displayName": { "description": "Optional display name", "type": "string" }, "dataSetClassFieldId": { "format": "uuid", "description": "Optional data set class field id (Publisher extension)", "type": "string" } }, "additionalProperties": false }, "SubscriptionWatchdogBehavior": { "description": "Defines how the publisher responds when monitored items stop reporting data.\r\nThe watchdog triggers when items are late according to OpcNodeWatchdogTimespan\r\nand OpcNodeWatchdogCondition settings. Can be configured globally via the\r\n--dwb command line option.", "enum": [ "Diagnostic", "Reset", "FailFast", "ExitProcess" ], "type": "string", "x-ms-enum": { "name": "SubscriptionWatchdogBehavior", "modelAsString": false } }, "TestConnectionRequestModel": { "description": "Test connection request", "type": "object", "properties": { "header": { "$ref": "#/definitions/RequestHeaderModel" } }, "additionalProperties": false }, "TestConnectionRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/TestConnectionRequestModel" } }, "additionalProperties": false }, "TestConnectionResponseModel": { "description": "Test connection response", "type": "object", "properties": { "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "TimestampsToReturn": { "description": "Timestamps", "enum": [ "Both", "Source", "Server", "None" ], "type": "string", "x-ms-enum": { "name": "TimestampsToReturn", "modelAsString": false } }, "TypeDefinitionModel": { "description": "Type definition", "required": [ "typeDefinitionId" ], "type": "object", "properties": { "typeDefinitionId": { "description": "The node id of the type of the node", "minLength": 1, "type": "string" }, "nodeType": { "$ref": "#/definitions/NodeType" }, "displayName": { "description": "Display name", "type": "string" }, "browseName": { "description": "Browse name", "type": "string" }, "description": { "description": "Description if any", "type": "string" }, "typeHierarchy": { "description": "Super types hierarchy starting from base type\r\nup to Azure.IIoT.OpcUa.Publisher.Models.TypeDefinitionModel.TypeDefinitionId which is\r\nnot included.", "type": "array", "items": { "$ref": "#/definitions/NodeModel" } }, "typeMembers": { "description": "Fully inherited instance declarations of the type\r\nof the node.", "type": "array", "items": { "$ref": "#/definitions/InstanceDeclarationModel" } } }, "additionalProperties": false }, "UpdateEventsDetailsModel": { "description": "Insert, upsert or replace historic events", "required": [ "events" ], "type": "object", "properties": { "filter": { "$ref": "#/definitions/EventFilterModel" }, "events": { "description": "The new events to insert", "type": "array", "items": { "$ref": "#/definitions/HistoricEventModel" } } }, "additionalProperties": false }, "UpdateEventsDetailsModelHistoryUpdateRequestModel": { "description": "Request node history update", "required": [ "details" ], "type": "object", "properties": { "nodeId": { "description": "Node to update (mandatory without browse path)", "type": "string" }, "browsePath": { "description": "An optional path from NodeId instance to\r\nthe actual node.", "type": "array", "items": { "type": "string" } }, "details": { "$ref": "#/definitions/UpdateEventsDetailsModel" }, "header": { "$ref": "#/definitions/RequestHeaderModel" } }, "additionalProperties": false }, "UpdateEventsDetailsModelHistoryUpdateRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/UpdateEventsDetailsModelHistoryUpdateRequestModel" } }, "additionalProperties": false }, "UpdateValuesDetailsModel": { "description": "Insert, upsert, or update historic values", "required": [ "values" ], "type": "object", "properties": { "values": { "description": "Values to insert", "type": "array", "items": { "$ref": "#/definitions/HistoricValueModel" } } }, "additionalProperties": false }, "UpdateValuesDetailsModelHistoryUpdateRequestModel": { "description": "Request node history update", "required": [ "details" ], "type": "object", "properties": { "nodeId": { "description": "Node to update (mandatory without browse path)", "type": "string" }, "browsePath": { "description": "An optional path from NodeId instance to\r\nthe actual node.", "type": "array", "items": { "type": "string" } }, "details": { "$ref": "#/definitions/UpdateValuesDetailsModel" }, "header": { "$ref": "#/definitions/RequestHeaderModel" } }, "additionalProperties": false }, "UpdateValuesDetailsModelHistoryUpdateRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/UpdateValuesDetailsModelHistoryUpdateRequestModel" } }, "additionalProperties": false }, "UserIdentityModel": { "description": "User identity model", "type": "object", "properties": { "user": { "description": "\r\nFor Azure.IIoT.OpcUa.Publisher.Models.CredentialType.UserName authentication\r\n this is the name of the user.\r\n\r\nFor Azure.IIoT.OpcUa.Publisher.Models.CredentialType.X509Certificate authentication\r\n this is the subject name of the certificate that has been\r\n configured.\r\n Either Azure.IIoT.OpcUa.Publisher.Models.UserIdentityModel.User or Azure.IIoT.OpcUa.Publisher.Models.UserIdentityModel.Thumbprint must be\r\n used to select the certificate in the user certificate store.\r\n\r\nNot used for the other authentication types.", "type": "string" }, "password": { "description": "\r\nFor Azure.IIoT.OpcUa.Publisher.Models.CredentialType.UserName authentication\r\n this is the password of the user.\r\n\r\nFor Azure.IIoT.OpcUa.Publisher.Models.CredentialType.X509Certificate authentication\r\n this is the passcode to export the configured certificate's\r\n private key.\r\n\r\nNot used for the other authentication types.", "type": "string" }, "thumbprint": { "description": "\r\nFor Azure.IIoT.OpcUa.Publisher.Models.CredentialType.X509Certificate authentication\r\n this is the thumbprint of the configured certificate to use.\r\n Either Azure.IIoT.OpcUa.Publisher.Models.UserIdentityModel.User or Azure.IIoT.OpcUa.Publisher.Models.UserIdentityModel.Thumbprint must be\r\n used to select the certificate in the user certificate store.\r\n\r\nNot used for the other authentication types.", "type": "string" } }, "additionalProperties": false }, "ValueReadRequestModel": { "description": "Request node value read", "type": "object", "properties": { "nodeId": { "description": "Node to read from (mandatory)", "type": "string" }, "browsePath": { "description": "An optional path from NodeId instance to\r\nan actual node.", "type": "array", "items": { "type": "string" } }, "indexRange": { "description": "Index range to read, e.g. 1:2,0:1 for 2 slices\r\nout of a matrix or 0:1 for the first item in\r\nan array, string or bytestring.\r\nSee 7.22 of part 4: NumericRange.", "type": "string" }, "header": { "$ref": "#/definitions/RequestHeaderModel" }, "maxAge": { "format": "date-span", "description": "Maximum age of the value to be read in milliseconds.\r\nThe age of the value is based on the difference\r\nbetween the ServerTimestamp and the time when\r\nthe Server starts processing the request.\r\nIf not supplied, the Server shall attempt to read\r\na new value from the data source.", "type": "string" }, "timestampsToReturn": { "$ref": "#/definitions/TimestampsToReturn" } }, "additionalProperties": false }, "ValueReadRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/ValueReadRequestModel" } }, "additionalProperties": false }, "ValueReadResponseModel": { "description": "Value read response model", "type": "object", "properties": { "value": { "description": "Value read", "type": "object" }, "dataType": { "description": "Built in data type of the value read.", "type": "string" }, "sourcePicoseconds": { "format": "int32", "description": "Pico seconds part of when value was read at source.", "type": "integer" }, "sourceTimestamp": { "format": "date-time", "description": "Timestamp of when value was read at source.", "type": "string" }, "serverPicoseconds": { "format": "int32", "description": "Pico seconds part of when value was read at server.", "type": "integer" }, "serverTimestamp": { "format": "date-time", "description": "Timestamp of when value was read at server.", "type": "string" }, "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "ValueWriteRequestModel": { "description": "Value write request model", "required": [ "value" ], "type": "object", "properties": { "nodeId": { "description": "Node id to write value to.", "type": "string" }, "browsePath": { "description": "An optional path from NodeId instance to\r\nthe actual node.", "type": "array", "items": { "type": "string" } }, "value": { "description": "Value to write. The system tries to convert\r\nthe value according to the data type value,\r\ne.g. convert comma seperated value strings\r\ninto arrays. (Mandatory)", "type": "object" }, "dataType": { "description": "A built in datatype for the value. This can\r\nbe a data type from browse, or a built in\r\ntype.\r\n(default: best effort)", "type": "string" }, "indexRange": { "description": "Index range to write", "type": "string" }, "header": { "$ref": "#/definitions/RequestHeaderModel" } }, "additionalProperties": false }, "ValueWriteRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/ValueWriteRequestModel" } }, "additionalProperties": false }, "ValueWriteResponseModel": { "description": "Value write response model", "type": "object", "properties": { "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "VariableMetadataModel": { "description": "Variable metadata model", "type": "object", "properties": { "dataType": { "$ref": "#/definitions/DataTypeMetadataModel" }, "valueRank": { "$ref": "#/definitions/NodeValueRank" }, "arrayDimensions": { "format": "int64", "description": "Array dimensions of the variable.", "type": "integer", "items": { "format": "int64", "type": "integer" } } }, "additionalProperties": false }, "VariantValueHistoryReadNextResponseModel": { "description": "History read continuation result", "required": [ "history" ], "type": "object", "properties": { "history": { "description": "History as json encoded extension object", "type": "object" }, "continuationToken": { "description": "Continuation token if more results pending.", "type": "string" }, "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "VariantValueHistoryReadRequestModel": { "description": "Request node history read", "required": [ "details" ], "type": "object", "properties": { "nodeId": { "description": "Node to read from (mandatory without browse path)", "type": "string" }, "browsePath": { "description": "An optional path from NodeId instance to\r\nthe actual node.", "type": "array", "items": { "type": "string" } }, "details": { "description": "The HistoryReadDetailsType extension object\r\nencoded in json and containing the tunneled\r\nHistorian reader request.", "type": "object" }, "indexRange": { "description": "Index range to read, e.g. 1:2,0:1 for 2 slices\r\nout of a matrix or 0:1 for the first item in\r\nan array, string or bytestring.\r\nSee 7.22 of part 4: NumericRange.", "type": "string" }, "header": { "$ref": "#/definitions/RequestHeaderModel" }, "timestampsToReturn": { "$ref": "#/definitions/TimestampsToReturn" } }, "additionalProperties": false }, "VariantValueHistoryReadRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/VariantValueHistoryReadRequestModel" } }, "additionalProperties": false }, "VariantValueHistoryReadResponseModel": { "description": "History read results", "required": [ "history" ], "type": "object", "properties": { "history": { "description": "History as json encoded extension object", "type": "object" }, "continuationToken": { "description": "Continuation token if more results pending.", "type": "string" }, "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "VariantValueHistoryUpdateRequestModel": { "description": "Request node history update", "required": [ "details" ], "type": "object", "properties": { "nodeId": { "description": "Node to update (mandatory without browse path)", "type": "string" }, "browsePath": { "description": "An optional path from NodeId instance to\r\nthe actual node.", "type": "array", "items": { "type": "string" } }, "details": { "description": "The HistoryUpdateDetailsType extension object\r\nencoded as json Variant and containing the tunneled\r\nupdate request for the Historian server. The value\r\nis updated at edge using above node address.", "type": "object" }, "header": { "$ref": "#/definitions/RequestHeaderModel" } }, "additionalProperties": false }, "VariantValueHistoryUpdateRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/VariantValueHistoryUpdateRequestModel" } }, "additionalProperties": false }, "VariantValuePublishedNodeCreateAssetRequestModel": { "description": "Request to create an asset in the configuration api", "required": [ "configuration", "entry" ], "type": "object", "properties": { "header": { "$ref": "#/definitions/RequestHeaderModel" }, "entry": { "$ref": "#/definitions/PublishedNodesEntryModel" }, "configuration": { "description": "The asset configuration to use when creating the asset.", "type": "object" }, "waitTime": { "format": "date-span", "description": "Time to wait after the configuration is applied to perform\r\nthe configuration of the asset in the configuration api.\r\nThis is to let the server settle.", "type": "string" } }, "additionalProperties": false }, "WriteRequestModel": { "description": "Request node attribute write", "required": [ "attributes" ], "type": "object", "properties": { "attributes": { "description": "Attributes to update", "type": "array", "items": { "$ref": "#/definitions/AttributeWriteRequestModel" } }, "header": { "$ref": "#/definitions/RequestHeaderModel" } }, "additionalProperties": false }, "WriteRequestModelRequestEnvelope": { "description": "Wraps a request and a connection to bind to a\r\nbody more easily for api that requires a\r\nconnection endpoint", "required": [ "connection" ], "type": "object", "properties": { "connection": { "$ref": "#/definitions/ConnectionModel" }, "request": { "$ref": "#/definitions/WriteRequestModel" } }, "additionalProperties": false }, "WriteResponseModel": { "description": "Result of attribute write", "required": [ "results" ], "type": "object", "properties": { "results": { "description": "All results of attribute writes", "type": "array", "items": { "$ref": "#/definitions/AttributeWriteResponseModel" } }, "errorInfo": { "$ref": "#/definitions/ServiceResultModel" } }, "additionalProperties": false }, "WriterGroupTransport": { "description": "Specifies the transport technology used to publish messages from OPC Publisher.\r\nEach transport offers different capabilities for message delivery, routing,\r\nand quality of service. The transport choice affects how messages are delivered\r\nand what features are available.", "enum": [ "IoTHub", "Mqtt", "EventHub", "Dapr", "Http", "FileSystem", "AioMqtt", "AioDss", "Null" ], "type": "string", "x-ms-enum": { "name": "WriterGroupTransport", "modelAsString": false } }, "X509CertificateChainModel": { "description": "Certificate chain", "type": "object", "properties": { "chain": { "description": "Chain", "type": "array", "items": { "$ref": "#/definitions/X509CertificateModel" } }, "status": { "description": "Chain validation status if validated", "enum": [ "NotTimeValid", "Revoked", "NotSignatureValid", "NotValidForUsage", "UntrustedRoot", "RevocationStatusUnknown", "Cyclic", "InvalidExtension", "InvalidPolicyConstraints", "InvalidBasicConstraints", "InvalidNameConstraints", "HasNotSupportedNameConstraint", "HasNotDefinedNameConstraint", "HasNotPermittedNameConstraint", "HasExcludedNameConstraint", "PartialChain", "CtlNotTimeValid", "CtlNotSignatureValid", "CtlNotValidForUsage", "HasWeakSignature", "OfflineRevocation", "NoIssuanceChainPolicy", "ExplicitDistrust", "HasNotSupportedCriticalExtension" ], "type": "string", "items": { "$ref": "#/definitions/X509ChainStatus" }, "x-ms-enum": { "name": "X509ChainStatus", "modelAsString": false } } }, "additionalProperties": false }, "X509CertificateModel": { "description": "Certificate model", "type": "object", "properties": { "subject": { "description": "Subject", "type": "string" }, "thumbprint": { "description": "Thumbprint", "type": "string" }, "serialNumber": { "description": "Serial number", "type": "string" }, "notBeforeUtc": { "format": "date-time", "description": "Not before validity", "type": "string" }, "notAfterUtc": { "format": "date-time", "description": "Not after validity", "type": "string" }, "selfSigned": { "description": "Self signed certificate", "type": "boolean" }, "pfx": { "description": "Certificate as Pkcs12", "type": "array", "items": { "format": "int32", "type": "integer" } }, "hasPrivateKey": { "description": "Contains private key", "type": "boolean" } }, "additionalProperties": false }, "X509ChainStatus": { "description": "Status of x509 chain", "enum": [ "NotTimeValid", "Revoked", "NotSignatureValid", "NotValidForUsage", "UntrustedRoot", "RevocationStatusUnknown", "Cyclic", "InvalidExtension", "InvalidPolicyConstraints", "InvalidBasicConstraints", "InvalidNameConstraints", "HasNotSupportedNameConstraint", "HasNotDefinedNameConstraint", "HasNotPermittedNameConstraint", "HasExcludedNameConstraint", "PartialChain", "CtlNotTimeValid", "CtlNotSignatureValid", "CtlNotValidForUsage", "HasWeakSignature", "OfflineRevocation", "NoIssuanceChainPolicy", "ExplicitDistrust", "HasNotSupportedCriticalExtension" ], "type": "string", "x-ms-enum": { "name": "X509ChainStatus", "modelAsString": false } } }, "tags": [ { "name": "Certificates", "description": "\r\nThis section lists the certificate APi provided by OPC Publisher providing\r\n all public and private key infrastructure (PKI) related API methods.\r\n\r\nThe method name for all transports other than HTTP (which uses the shown\r\n HTTP methods and resource uris) is the name of the subsection header.\r\n To use the version specific method append \"_V1\" or \"_V2\" to the method\r\n name." }, { "name": "Configuration", "description": "\r\nThis section contains the API to configure OPC Publisher.\r\n\r\nThe method name for all transports other than HTTP (which uses the shown\r\n HTTP methods and resource uris) is the name of the subsection header.\r\n To use the version specific method append \"_V1\" or \"_V2\" to the method\r\n name." }, { "name": "Diagnostics", "description": "\r\nThis section lists the diagnostics APi provided by OPC Publisher providing\r\n connection related diagnostics API methods.\r\n\r\nThe method name for all transports other than HTTP (which uses the shown\r\n HTTP methods and resource uris) is the name of the subsection header.\r\n To use the version specific method append \"_V1\" or \"_V2\" to the method\r\n name." }, { "name": "Discovery", "description": "\r\nOPC UA and network discovery related API.\r\n\r\nThe method name for all transports other than HTTP (which uses the shown\r\n HTTP methods and resource uris) is the name of the subsection header.\r\n To use the version specific method append \"_V1\" or \"_V2\" to the method" }, { "name": "FileSystem", "description": "\r\nThis section lists the file transfer API provided by OPC Publisher providing\r\n access to file transfer services to move files in and out of a server\r\n using the File transfer specification.\r\n\r\nThe method name for all transports other than HTTP (which uses the shown\r\n HTTP methods and resource uris) is the name of the subsection header.\r\n To use the version specific method append \"_V1\" or \"_V2\" to the method\r\n name." }, { "name": "General", "description": "\r\nThis section lists the general APi provided by OPC Publisher providing\r\n all connection, endpoint and address space related API methods.\r\n\r\nThe method name for all transports other than HTTP (which uses the shown\r\n HTTP methods and resource uris) is the name of the subsection header.\r\n To use the version specific method append \"_V1\" or \"_V2\" to the method\r\n name." }, { "name": "History", "description": "\r\nThis section lists all OPC UA HDA or Historian related API provided by\r\n OPC Publisher.\r\n\r\nThe method name for all transports other than HTTP (which uses the shown\r\n HTTP methods and resource uris) is the name of the subsection header.\r\n To use the version specific method append \"_V1\" or \"_V2\" to the method\r\n name." }, { "name": "Writer", "description": "\r\nThis section contains the API to configure data set writers and writer\r\n groups inside OPC Publisher. It supersedes the configuration API.\r\n Applications should use one or the other, but not both at the same\r\n time.\r\n\r\nThe method name for all transports other than HTTP (which uses the shown\r\n HTTP methods and resource uris) is the name of the subsection header.\r\n To use the version specific method append \"_V1\" or \"_V2\" to the method\r\n name." } ] } ================================================ FILE: docs/opc-publisher/publishednodes_2.5.json ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ [ { // example for an EnpointUrl is: opc.tcp://192.168.178.26:62541/Quickstarts/ReferenceServer "EndpointUrl": "opc.tcp://:/", // allows to access the endpoint with SecurityPolicy.None when set to 'false' (no signing and encryption applied to the OPC UA communication), default is true "UseSecurity": true, "OpcNodes": [ { // identifies the OPC node to publish in either NodeId format (contains "ns=") or ExpandedNodeId format (contains "nsu=") "Id": "i=2258", // specifies the sampling interval OPC Publisher requests the server to sample the node value "OpcSamplingInterval": 2000, // specifies the publishing interval OPC Publisher requests the server to publish the node value, it will only be published if the value has changed "OpcPublishingInterval": 5000, // specifies that there should be a heartbeat generated by OPC Publisher, this means that after the given interval the last message will be sent again with an updated SourceTimestamp value. "HeartbeatInterval": 3600, // specifies that the first event will not generate a telemetry event, this is useful when publishing a large amount of data to prevent a event flood at startup of OPC Publisher "SkipFirst": false } ] }, { // example for an EnpointUrl is: opc.tcp://192.168.178.26:62541/Quickstarts/ReferenceServer "EndpointUrl": "opc.tcp://:/", // allows to access the endpoint with SecurityPolicy.None when set to 'false' (no signing and encryption applied to the OPC UA communication), default is true "UseSecurity": true, "OpcNodes": [ { // identifies the OPC node to publish using string based addressing e.g. for Siemens S7 "TCP".PLC_1.Motor_Simulation.M1.Motor_Drehzahl "Id": "ns=2;s=Siemens S7 \"TCP\".PLC_1.Motor_Simulation.M1.Motor_Drehzahl", // specifies the sampling interval OPC Publisher requests the server to sample the node value "OpcSamplingInterval": 2000, // specifies the publishing interval OPC Publisher requests the server to publish the node value, it will only be published if the value has changed "OpcPublishingInterval": 5000, // specifies that there should be a heartbeat generated by OPC Publisher, this means that after the given interval the last message will be sent again with an updated SourceTimestamp value. "HeartbeatInterval": 3600, // specifies that the first event will not generate a telemetry event, this is useful when publishing a large amount of data to prevent a event flood at startup of OPC Publisher "SkipFirst": false } ] }, // // For completeness you will find the documentation of legacy formats below. // { // example for an EnpointUrl is: opc.tcp://win10iot:51210/UA/SampleServer "EndpointUrl": "opc.tcp://:/", // Allows to access the endpoint with SecurityPolicy.None when set to 'false' (no signing and encryption applied to the OPC UA communication), default is true "UseSecurity": true, "OpcNodes": [ // Publisher will request the server at EndpointUrl to sample the node with the OPC sampling interval specified on command line (or the default value: OPC publishing interval) // and the subscription will publish the node value with the OPC publishing interval specified on command line (or the default value: server revised publishing interval). { // The identifier specifies the NamespaceUri and the node identifier in XML notation as specified in Part 6 of the OPC UA specification in the XML Mapping section. "ExpandedNodeId": "nsu=http://opcfoundation.org/UA/;i=2258" }, // Publisher will request the server at EndpointUrl to sample the node with the OPC sampling interval specified on command line (or the default value: OPC publishing interval) // and the subscription will publish the node value with an OPC publishing interval of 4 seconds. // Publisher will use for each dinstinct publishing interval (of nodes on the same EndpointUrl) a separate subscription. All nodes without a publishing interval setting, // will be on the same subscription and the OPC UA stack will publish with the lowest sampling interval of a node. { "ExpandedNodeId": "nsu=http://opcfoundation.org/UA/;i=2258", "OpcPublishingInterval": 4000 }, // Publisher will request the server at EndpointUrl to sample the node with the given sampling interval of 1 second // and the subscription will publish the node value with the OPC publishing interval specified on command line (or the default value: server revised interval). // If the OPC publishing interval is set to a lower value, Publisher will adjust the OPC publishing interval of the subscription to the OPC sampling interval value. { "ExpandedNodeId": "nsu=http://opcfoundation.org/UA/;i=2258", // the OPC sampling interval to use for this node. "OpcSamplingInterval": 1000 } ] }, // the format below (NodeId format) is only supported for backward compatibility. you need to ensure that the // OPC UA server on the configured EndpointUrl has the namespaceindex you expect with your configuration. // please use the ExpandedNodeId format as in the examples above instead. { "EndpointUrl": "opc.tcp://:/", "NodeId": { "Identifier": "ns=0;i=2258" } } // please consult the OPC UA specification for details on how OPC monitored node sampling interval and OPC subscription publishing interval settings are handled by the OPC UA stack. // the publishing interval of the data to Azure IoTHub is controlled by the command line settings (or the default: publish data to IoTHub at least each 1 second). ] ================================================ FILE: docs/opc-publisher/publishednodes_2.8.json ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ [ { // Example for an EnpointUrl is: opc.tcp://192.168.178.26:62541/Quickstarts/ReferenceServer "EndpointUrl": "opc.tcp://:/", // Allows to access the endpoint with SecurityPolicy.None when set to false (no signing and encryption applied to the OPC UA communication), default is false. "UseSecurity": false, "OpcNodes": [ { // Identifies the OPC node to publish in either NodeId format (contains "ns=") or ExpandedNodeId format (contains "nsu=") "Id": "i=2258", // Specifies the sampling interval OPC Publisher requests the server to sample the node value. // Value expressed in milliseconds. "OpcSamplingInterval": 1000, // Specifies the publishing interval OPC Publisher requests the server to publish the node value, it will only be published if the value has changed. // Value expressed in milliseconds. "OpcPublishingInterval": 5000, // Specifies that there should be a heartbeat generated by OPC Publisher, this means that after the given interval the last message will be sent again with an updated SourceTimestamp value. // Value expressed in seconds. "HeartbeatInterval": 3600, // specifies that the first event will not generate a telemetry event, this is useful when publishing a large amount of data to prevent a event flood at startup of OPC Publisher "SkipFirst": false } ] }, { // Example for an EnpointUrl is: opc.tcp://192.168.178.26:62541/Quickstarts/ReferenceServer "EndpointUrl": "opc.tcp://:/", // The data set writer group collecting datasets defined for a certain endpoint. "DataSetWriterGroup": "Asset0", // The unique identifier for a data set writer used to collect OPC UA nodes to be semantically grouped and published with the same publishing interval. "DataSetWriterId": "DataFlow0", // Controls whether to use a secure OPC UA mode to establish a session to the OPC UA server endpoint. "UseSecurity": true, // Enum to specify the session authentication. Options: "Anonymous", "UsernamePassword" "OpcAuthenticationMode": "UsernamePassword", // The username for the session authentication. Mandatory if OpcAuthentication mode is "UsernamePassword". "OpcAuthenticationUsername": "username", // The password for the session authentication. Mandatory if OpcAuthentication mode is "UsernamePassword". "OpcAuthenticationPassword": "password", // The DataSet collection grouping the nodes to be published for the specific DataSetWriter defined above. "OpcNodes": [ { // Identifies the OPC node to publish using string based addressing e.g. for Siemens S7 "TCP".PLC_1.Motor_Simulation.M1.Motor_Drehzahl "Id": "ns=2;s=Siemens S7 \"TCP\".PLC_1.Motor_Simulation.M1.Motor_Drehzahl", // Specifies the sampling interval OPC Publisher requests the server to sample the node value. // Value expressed in Timespan string({d.hh:mm:dd.fff}). "OpcSamplingIntervalTimespan": "00:00:02", // Specifies the publishing interval OPC Publisher requests the server to publish the node value, it will only be published if the value has changed. // Value expressed in Timespan string({d.hh:mm:dd.fff}). "OpcPublishingIntervalTimespan": "00:00:05", // Specifies that there should be a heartbeat generated by OPC Publisher, this means that after the given interval the last message will be sent again with an updated SourceTimestamp value. // Value expressed in Timespan string({d.hh:mm:dd.fff}). "HeartbeatIntervalTimespan": "00:01:00", // The desired QueueSize for the monitored item to be published. "QueueSize": 10, // Report a notification on status, value or timestamp node change. It can take the values // "Status", "StatusValue" and "StatusValueTimestamp". If null, the OPC UA Specification defaults to "StatusValue". "DataChangeTrigger": "StatusValueTimestamp" } ] }, { // example for an EnpointUrl is: opc.tcp://192.168.178.26:62541/Quickstarts/ReferenceServer "EndpointUrl": "opc.tcp://:/", // The data set writer group collecting datasets defined for a certain endpoint. "DataSetWriterGroup": "Asset0", // The unique identifier for a data set writer used to collect OPC UA nodes to be semantically grouped and published with the same publishing interval. "DataSetWriterId": "DataFlow1", // Controls whether to use a secure OPC UA mode to establish a session to the OPC UA server endpoint. "UseSecurity": false, // Enum to specify the session authentication. Options: "Anonymous", "UsernamePassword" "OpcAuthenticationMode": "Anonymous", // The publishing interval used for a grouped set of nodes under a certain DataSetWriter. // Value expressed as a Timespan string ({d.hh:mm:dd.fff}). "DataSetPublishingIntervalTimespan": "00:00:05", // The DataSet collection grouping the nodes to be published for the specific DataSetWriter defined above. "OpcNodes": [ { // Identifies the OPC node to publish in either NodeId format (contains "ns=") or ExpandedNodeId format (contains "nsu=") "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=StepUp", // A user defined tag to be added to the telemetry message when publisher runs in Samples message mode. "DisplayName":"StepUp" } ] }, { // Example for an EnpointUrl is: opc.tcp://win10iot:51210/UA/SampleServer "EndpointUrl": "opc.tcp://:/", // Allows to access the endpoint with SecurityPolicy.None when set to 'false' (no signing and encryption applied to the OPC UA communication), default is false. "UseSecurity": true, "OpcNodes": [ // Publisher will request the server at EndpointUrl to sample the node with the OPC sampling interval specified on command line (or the default value: OPC publishing interval) // and the subscription will publish the node value with the OPC publishing interval specified on command line (or the default value: server revised publishing interval). { // The identifier specifies the NamespaceUri and the node identifier in XML notation as specified in Part 6 of the OPC UA specification in the XML Mapping section. "ExpandedNodeId": "nsu=http://opcfoundation.org/UA/;i=2258" }, // Publisher will request the server at EndpointUrl to sample the node with the OPC sampling interval specified on command line (or the default value: OPC publishing interval) // and the subscription will publish the node value with an OPC publishing interval of 4 seconds. // Publisher will use for each dinstinct publishing interval (of nodes on the same EndpointUrl) a separate subscription. All nodes without a publishing interval setting, // will be on the same subscription and the OPC UA stack will publish with the lowest sampling interval of a node. { "ExpandedNodeId": "nsu=http://opcfoundation.org/UA/;i=2258", "OpcPublishingInterval": 4000 }, // Publisher will request the server at EndpointUrl to sample the node with the given sampling interval of 1 second // and the subscription will publish the node value with the OPC publishing interval specified on command line (or the default value: server revised interval). // If the OPC publishing interval is set to a lower value, Publisher will adjust the OPC publishing interval of the subscription to the OPC sampling interval value. { "ExpandedNodeId": "nsu=http://opcfoundation.org/UA/;i=2258", // the OPC sampling interval to use for this node. "OpcSamplingInterval": 1000 } ] } ] ================================================ FILE: docs/opc-publisher/readme.md ================================================ # Microsoft OPC Publisher [Home](../readme.md) OPC Publisher is a module that runs on [Azure IoT Edge](https://azure.microsoft.com/services/iot-edge/) and bridges the gap between industrial assets and the Microsoft Azure cloud. It connects to OPC UA server systems and publishes telemetry data to [Azure IoT Hub](https://azure.microsoft.com/services/iot-hub/) in various formats, including IEC62541 OPC UA PubSub standard format (*not supported in versions < 2.7.x*). > This documentation applies to version 2.9 or higher. Here you find information about ## Table Of Contents - [Overview](#overview) - [Getting Started](#getting-started) - [Install IoT Edge](#install-iot-edge) - [Deploy OPC Publisher from Azure Marketplace](#deploy-opc-publisher-from-azure-marketplace) - [Specifying Container Create Options in the Azure portal](#specifying-container-create-options-in-the-azure-portal) - [Deploy OPC Publisher using Azure CLI](#deploy-opc-publisher-using-azure-cli) - [Deploy OPC Publisher using the Azure Portal](#deploy-opc-publisher-using-the-azure-portal) - [How OPC Publisher works](#how-opc-publisher-works) - [Configuring OPC Publisher](#configuring-opc-publisher) - [Configuration via Configuration File](#configuration-via-configuration-file) - [Configuration Schema](#configuration-schema) - [Writer group configuration](#writer-group-configuration) - [Configuration via init file](#configuration-via-init-file) - [Sampling and Publishing Interval configuration](#sampling-and-publishing-interval-configuration) - [Key frames, delta frames and extension fields](#key-frames-delta-frames-and-extension-fields) - [Status codes](#status-codes) - [Heartbeat](#heartbeat) - [Timestamps](#timestamps) - [Legacy behavior](#legacy-behavior) - [Cyclic reading (Client side sampling)](#cyclic-reading-client-side-sampling) - [Overcoming server limits and interop limitations](#overcoming-server-limits-and-interop-limitations) - [Configuring Security](#configuring-security) - [Using OPC UA reverse connect](#using-opc-ua-reverse-connect) - [Configuring event subscriptions](#configuring-event-subscriptions) - [Simple event filter](#simple-event-filter) - [Advanced event filter configuration](#advanced-event-filter-configuration) - [Condition handling options](#condition-handling-options) - [Publish to a Unified Namespace](#publish-to-a-unified-namespace) - [OPC Publisher Telemetry Formats](#opc-publisher-telemetry-formats) - [Programming against OPC Publisher using the OPC Publisher API](#programming-against-opc-publisher-using-the-opc-publisher-api) - [Using IoT Edge Simulation environment](#using-iot-edge-simulation-environment) - [Calling the Direct Methods API](#calling-the-direct-methods-api) - [Calling the API over HTTP](#calling-the-api-over-http) - [JSON encoding](#json-encoding) - [Node Ids](#node-ids) - [Browse paths](#browse-paths) - [Discovering OPC UA servers with OPC Publisher](#discovering-opc-ua-servers-with-opc-publisher) - [Discovery Configuration](#discovery-configuration) - [One-time discovery](#one-time-discovery) - [Discovery Progress](#discovery-progress) - [OPC UA command and control (OPC Twin)](#opc-ua-command-and-control-opc-twin) - [OPC UA Certificates](#opc-ua-certificates) - [PKI management](#pki-management) - [Auto Accept server certificates](#auto-accept-server-certificates) - [OPC UA stack](#opc-ua-stack) - [Performance and Memory Tuning OPC Publisher](#performance-and-memory-tuning-opc-publisher) ## Overview Microsoft OPC Publisher runs on Azure [IoT Edge](https://docs.microsoft.com/azure/iot-edge/module-edgeagent-edgehub) and connects OPC UA-enabled servers to Azure. It can be [configured](#configuring-opc-publisher) using Azure IoT Hub, through MQTT/HTTPS locally (Preview) or via configuration file. OPC Publisher is a [feature rich OPC UA client/server to OPC UA Pub/Sub translator](./features.md). Per configuration it sets up OPC UA subscriptions to monitor data (OPC UA nodes) using an integrated [OPC UA stack](#opc-ua-stack). When a data value change or event of an OPC UA node is reported, it transcodes the OPC UA notification using the configured encoding and publishes it to IoT Hub or MQTT broker of choice. With OPC Publisher you can also browse a server's data model, read and write ad-hoc data, or call methods on your assets. This [capability](#opc-ua-command-and-control-opc-twin) can be accessed programmatically from the cloud or through other applications running alongside. OPC Publisher also supports [discovering](#discovering-opc-ua-servers-with-opc-publisher) OPC UA-enabled assets on the shop floor. When it finds an asset either through a discovery url or (optionally) active network scanning, it queries the assets endpoints (including its security configuration) and reports the results to IoT Hub or returns them from the respective [API call as response](api.md#find-server-with-endpoint). Azure IoT Edge gateways support nested ISA 95 (Purdue) topologies. It needs to be placed where it has access to all industrial assets that are to be connected, and a IoT Edge device needs to be placed at every layer leading to the internet. Using OPC UA [reverse connect](#using-opc-ua-reverse-connect) is another option to bridge network layer. > Note that this might require configuring a specific route from IoT Edge to the public Internet through several on-premise routers. In terms of firewall configuration, IoT Edge just needs a single outbound port to operate, i.e., port 443. ## Getting Started ### Install IoT Edge The industrial assets (machines and systems) are connected to Azure through modules running on an [Azure IoT Edge](https://azure.microsoft.com/services/iot-edge/) industrial gateway. > While OPC Publisher can run outside of Azure IoT Edge, the only Microsoft supported hosting environment is Azure IoT Edge. If you want to use OPC Publisher outside of Azure IoT Edge, support is through GitHub issues and community only. You can purchase industrial gateways compatible with IoT Edge. Please see our [Azure Device Catalog](https://catalog.azureiotsolutions.com/alldevices?filters={"3":["2","9"],"18":["1"]}) for a selection of industrial-grade gateways. Alternatively, you can setup a local VM. You can also manually [create an IoT Edge instance for an IoT Hub](https://docs.microsoft.com/azure/iot-edge/how-to-register-device) and install the IoT Edge runtime following the [IoT Edge setup documentation](https://docs.microsoft.com/azure/iot-edge/). The IoT Edge Runtime can be installed on [Linux](https://docs.microsoft.com/azure/iot-edge/how-to-install-iot-edge-linux) or [Windows](https://docs.microsoft.com/azure/iot-edge/iot-edge-for-linux-on-windows). You can find out more about Azure IoT Edge here: - [Deploy and monitor Edge modules at scale](https://docs.microsoft.com/azure/iot-edge/how-to-deploy-monitor) - [Learn more about Azure IoT Edge for Visual Studio Code](https://github.com/microsoft/vscode-azure-iot-edge) - [Run IoT Edge on Kubernetes](https://github.com/Azure-Samples/IoT-Edge-K8s-KubeVirt-Deployment/) ### Deploy OPC Publisher from Azure Marketplace Use the Microsoft supported docker containers for OPC Publisher available in the Microsoft Container Registry rather than building from sources: ``` bash docker pull mcr.microsoft.com/iotedge/opc-publisher:latest ``` > We recommend to use a floating version tag ("2.9") when deploying the OPC Publisher container images instead of "latest". You can also use a fixed tag such as "2.9.11" but this will require you to manually update your edge deployment to keep up with the latest secure and supported version. The easiest way to deploy OPC Publisher is through the [Azure Marketplace](https://azuremarketplace.microsoft.com/marketplace/apps/microsoft_iot.iotedge-opc-publisher). Select the "Get It Now" button to log into the [Azure portal](https://portal.azure.com) and deploy OPC Publisher. The following steps are required: 1. Pick the Azure subscription to use. If no Azure subscription is available, one must be created. 2. Pick the IoT Hub the OPC Publisher is supposed to send data to. If no IoT Hub is available, one must be created. 3. Pick the IoT Edge device OPC Publisher is supposed to run on. If no IoT Edge device exists, one must be created). 4. Select "Create". The "Set modules on Device" page for the selected IoT Edge device opens. 5. Select on "OPCPublisher" to open the OPC Publisher's "Update IoT Edge Module" page and then select "Container Create Options". 6. Validate "container create options" based on your usage of OPC Publisher. For more information, see next section. ### Specifying Container Create Options in the Azure portal Container create options are used to specify the container and configuration [command line arguments](./commandline.md) of OPC Publisher. The docker create options can be specified in the "Update IoT Edge Module" page of OPC Publisher and must be in JSON format. Specifically the OPC Publisher command line arguments can be specified via the "Cmd" key. Here an example for a configuration on a Linux host system: ``` json { "Cmd": [ "-c", // 2.9+ only "--cl=5", // 2.9+ only "--PkiRootPath=/mount/pki", "--pf=/mount/published_nodes.json", "--cf", // 2.9+ only "--mm=PubSub", "--me=Json", "--fd=false", "--bs=100", "--bi=1000", "--aa" ], "HostConfig": { "Binds": [ "/opcpublisher:/mount" ], "CapDrop": [ "CHOWN", "SETUID" ] } } ``` To not loose the OPC Publisher configuration across restarts all configuration files should be persisted. This requires a bind mount. A bind mound makes folders in the IoT Edge host file system available to the OPC Publisher. In above example the **Mounts** section maps the `/mount` folder inside the container to the folder `/opcpublisher` on the host file system. Without it all configuration changes will be applied to the container file system which lives in memory and thus will be lost when the OPC Publisher module is restarted. With above options specified however, OPC Publisher will use the configuration file `published_nodes.json` inside the `/mount` folder and thus on the `/opcpublisher` folder on IoT Edge host. The `CertificateStores` directory (used for OPC UA certificates) will also be created in the `pki` directory of the `/mount` folder. > IMPORTANT: The `/opcpublisher` directory must be present on the host file system, otherwise OPC Publisher will fail to start. Also, the folder contains security sensitive information. Any username and password configured inside the configuration are stored in plain text. It must be ensured that the configuration file is protected by the file system access control of the host file system. The same must be ensured for the file system based certificate store, since it contains the certificate and private key of OPC Publisher. The `CapDrop` option drops the CHOWN (user can’t makes arbitrary changes to file UIDs and GIDs) and SETUID (user can’t makes arbitrary manipulations of process UIDs) capabilities for security reason. A connection to an OPC UA server using its hostname without a DNS server configured on the network can be achieved by adding an `ExtraHosts` entry to the `HostConfig` section: ``` json "HostConfig": { "ExtraHosts": [ "opctestsvr:192.168.178.26" ] } ``` ### Deploy OPC Publisher using Azure CLI 1. Obtain the IoT Hub name and device id of the [installed IoT Edge](#install-iot-edge) Gateway. 1. Install the [Azure CLI](https://docs.microsoft.com/cli/azure/install-azure-cli). You must have at least `v2.0.24`, which you can verify with `az --version`. 1. Add the [IoT Edge Extension](https://github.com/Azure/azure-iot-cli-extension/) with the following commands: ```bash az extension add --name azure-cli-iot-ext ``` To deploy all required modules using Az... 1. Save the following content into a `deployment.json` file: ```json { "modulesContent": { "$edgeAgent": { "properties.desired": { "schemaVersion": "1.1", "runtime": { "type": "docker", "settings": { "minDockerVersion": "v1.25", "loggingOptions": "", "registryCredentials": {} } }, "systemModules": { "edgeAgent": { "type": "docker", "settings": { "image": "mcr.microsoft.com/azureiotedge-agent:1.4", "createOptions": "" } }, "edgeHub": { "type": "docker", "status": "running", "restartPolicy": "always", "settings": { "image": "mcr.microsoft.com/azureiotedge-hub:1.4", "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"5671/tcp\":[{\"HostPort\":\"5671\"}], \"8883/tcp\":[{\"HostPort\":\"8883\"}],\"443/tcp\":[{\"HostPort\":\"443\"}]}}}" }, "env": { "SslProtocols": { "value": "tls1.2" } } } }, "modules": { "publisher": { "version": "1.0", "type": "docker", "status": "running", "restartPolicy": "always", "settings": { "image": "mcr.microsoft.com/iotedge/opc-publisher:2.9", "createOptions": "{\"HostConfig\":{\"CapDrop\":[\"CHOWN\",\"SETUID\"]}}" } } } } }, "$edgeHub": { "properties.desired": { "schemaVersion": "1.0", "routes": { "publisherToUpstream": "FROM /messages/modules/publisher/* INTO $upstream", "leafToUpstream": "FROM /messages/* WHERE NOT IS_DEFINED($connectionModuleId) INTO $upstream" }, "storeAndForwardConfiguration": { "timeToLiveSecs": 7200 } } } } } ``` 1. Use the following command to apply the configuration to an IoT Edge device: ```bash az iot edge set-modules --device-id [device id] --hub-name [hub name] --content ./deployment.json ``` The `device id` parameter is case-sensitive. The content parameter points to the deployment manifest file that you saved. ![az iot edge set-modules output](https://docs.microsoft.com/azure/iot-edge/media/how-to-deploy-cli/set-modules.png) 1. Once you've deployed modules to your device, you can view all of them with the following command: ```bash az iot hub module-identity list --device-id [device id] --hub-name [hub name] ``` The device id parameter is case-sensitive. ![az iot hub module-identity list output](https://docs.microsoft.com/azure/iot-edge/media/how-to-deploy-cli/list-modules.png) More information about az and IoT Edge can be found [here](https://docs.microsoft.com/en-us/azure/iot-edge/how-to-deploy-monitor-cli). ### Deploy OPC Publisher using the Azure Portal To deploy OPC Puublisher to the IoT Edge Gateway using the Azure Portal... 1. Sign in to the [Azure portal](https://portal.azure.com/) and navigate to the IoT Hub deployed earlier. 1. Select **IoT Edge** from the left-hand menu. 1. Click on the ID of the target device from the list of devices. 1. Select **Set Modules**. 1. In the **Deployment modules** section of the page, select **Add** and **IoT Edge Module.** 1. In the **IoT Edge Custom Module** dialog use `publisher` as name for the module, then specify the container *image URI* as ```bash mcr.microsoft.com/iotedge/opc-publisher:2.9 ``` On Linux use the following *create options* if you intend to use the network scanning capabilities of the module: ```json {"NetworkingConfig":{"EndpointsConfig":{"host":{}}},"HostConfig":{"NetworkMode":"host","CapAdd":["NET_ADMIN"], "CapDrop":["CHOWN", "SETUID"]}} ``` Fill out the optional fields if necessary. For more information about container create options, restart policy, and desired status see [EdgeAgent desired properties](https://docs.microsoft.com/azure/iot-edge/module-edgeagent-edgehub#edgeagent-desired-properties). For more information about the module twin see [Define or update desired properties](https://docs.microsoft.com/azure/iot-edge/module-composition#define-or-update-desired-properties). 1. Select **Save** and then **Next** to continue to the routes section. 1. In the routes tab, paste the following ```json { "routes": { "publisherToUpstream": "FROM /messages/modules/publisher/* INTO $upstream", "leafToUpstream": "FROM /messages/* WHERE NOT IS_DEFINED($connectionModuleId) INTO $upstream" } } ``` and select **Next** 1. Review your deployment information and manifest. It should look like the deployment manifest found in the [previous section](#deploy-opc-publisher-using-azure-cli). Select **Submit**. 1. Once you've deployed modules to your device, you can view all of them in the **Device details** page of the portal. This page displays the name of each deployed module, as well as useful information like the deployment status and exit code. 1. Add your own or other modules from the Azure Marketplace using the steps above. For more in depth information check out [the Azure IoT Edge Portal documentation](https://docs.microsoft.com/en-us/azure/iot-edge/how-to-deploy-modules-portal). ## How OPC Publisher works The following diagram courtesy of the OPC Foundation's [Part 14 of the OPC UA specification](https://reference.opcfoundation.org/Core/Part14/v105/docs/5) illustrates the inner workings of the OPC Publisher process: ![Publisher](https://reference.opcfoundation.org/api/image/get/413/image006.png) Publishing OPC UA telemetry from an OPC UA server works as follows: 1. An OPC UA server exposes variable nodes (also sometimes called "tags") which make sensor readings accessible, or nodes that allow a client to subscribe to events. 1. The OPC Publisher can be configured to connect to one or more selected OPC UA server endpoints. Based on the configuration the OPC Publisher OPC UA client creates subscriptions requesting to be notified when the value of the specified nodes change or an event occurs. 1. The publisher groups nodes in the configuration into groups of `Dataset Writers` called [`Writer Groups`](https://reference.opcfoundation.org/Core/Part14/v105/docs/5) which are akin to OPC UA subscriptions. These subscriptions refer to node ids (in OPC UA also called monitored items). Nodes can be configured with `SamplingInterval`, `PublishingInterval`, `DataSetWriterId`, and `DataSetWriterGroup`. - `DataSetWriterId`: A logical name of a subscription to an endpoint on a OPC UA server. A writer can only have 1 publishing interval and in case of event subscription, 1 event node. Should multiple be specified then the writer is broken into smaller writers. A data set writer writes data sets, which are a set of OPC UA data values or events inside a OPC UA PubSub network message. - `DataSetWriterGroup`: A logical group of data set writers. These define the content of a OPC UA PubSub network message. - `SamplingInterval`: The cyclic time in milliseconds, in which a node in a writer is sampled for updates. This is not applicable for events. - `PublishingInterval`: The cyclic time in milliseconds, in which changes to a set of nodes (notifications) are sent to the subscriber (OPC Publisher). A small interval minimizes latency at the cost of network traffic and server load. For low latency it should be set to the smallest sampling interval and appropriate queue size values should be configured to avoid message loss. 1. Data change notifications or event notifications are published by the OPC UA server to OPC Publisher. OPC UA only sends value changes, that means, if a value has not changed in the publishing cycle it is not send. If you need all values in a message you can use the `DataSetKeyFrameCount` or `HeartbeatInterval` options or read the values using `UseCyclicRead` [options](#configuration-schema) instead of subscriptions. OPC Publisher also emits meta data messages for all configured data sets inside a data set writer group unless disabled or not supported by the chosen [message format](./messageformats.md). 1. The OPC Publisher can be configured to send notifications as soon as they arrive or batch them before sending which saves bandwidth and increases throughput. Sending a batch is triggered by exceeding the threshold of a specified number of messages or by exceeding a specified time interval. 1. OPC Publisher groups and encodes the telemetry events using the specified messaging mode and message encoding format. More information can be found [here](./messageformats.md). 1. The encoded telemetry events are sent over the configured [transport](./transports.md) as OPC UA network messages. The default transport is Azure IoT which has a message limit of 256kB. The publisher tries to split messages to avoid loosing data, but has a runtime cost. In case of PubSub encoding when strict mode is used (`--strict`) or when `--dm=false` is set, OPC Publisher also emits Metadata messages which can be used to learn more about the message content and support decoding in some cases. 1. Azure IoT Hub stores messages using a configured retention time (default: 1 day, max: 7 days, dependent on the size of the ingested messages as well, see [here](https://docs.microsoft.com/azure/iot-hub/iot-hub-devguide-messages-read-builtin) for more details). Messages can be consumed by applications or other services from IoT Hub. ## Configuring OPC Publisher OPC Publisher has several interfaces that can be used to configure it. - [Configuration via configuration file](#configuration-via-configuration-file) - [Command Line options configuration](./commandline.md) - [Configuration via API](./directmethods.md) - [Configuration via init file](#configuration-via-init-file) - [How to migrate from previous versions of OPC Publisher](./migrationpath.md) ### Configuration via Configuration File The simplest way to configure OPC Publisher is via a file. A basic configuration file looks like this: ``` json [ { "EndpointUrl": "opc.tcp://testserver:62541/Quickstarts/ReferenceServer", "UseSecurity": true, "OpcNodes": [ { "Id": "i=2258", "OpcSamplingInterval": 2000, "OpcPublishingInterval": 5000, "DisplayName": "Current time" } ] } ] ``` This configuration can be placed in a JSON file, typically named publishednodes.json, and provided to OPC Publisher using the [command line](./commandline.md) argument `-f, --pf, --publishfile`, e.g. `--pf=/app/publishednodes.json`. > Environment variables can also be used to configure OPC Publisher. This method is particularly useful when deploying at scale or in environments where you want to externalize configuration from the container image. An example is `PublishedNodesFile`. Example configuration files are [here](publishednodes_2.5.json?raw=1) and [here](publishednodes_2.8.json?raw=1). ### Configuration Schema The configuration schema is used with the file based configuration, but also with the [Api based configuration](./directmethods.md). The configuration consists a JSON array of [entries](./definitions.md#publishednodesentrymodel) containing arrays of [nodes](./definitions.md#opcnodemodel): ```json { "EndpointUrl": "string", "UseSecurity": "boolean", "DataSetWriterGroup": "string", "DataSetWriterId": "string", "WriterGroupTransport": "string", "WriterGroupQueueName":_ "string", "WriterGroupQualityOfService": "string", "WriterGroupMessageRetention": "boolean", "WriterGroupMessageTtlTimespan": "string", "WriterGroupPartitions": "integer", "EndpointSecurityMode": "string", "EndpointSecurityPolicy": "string", "OpcAuthenticationMode": "string", "OpcAuthenticationUsername": "string", "OpcAuthenticationPassword": "string", "DataSetClassId": "guid", "DataSetName": "string", "DataSetDescription": "string", "DataSetPublishingInterval": "integer", "DataSetPublishingIntervalTimespan": "string", "DataSetSamplingInterval": "integer", "DataSetSamplingIntervalTimespan": "string", "DataSetKeyFrameCount": "integer", "DataSetExtensionFields": "object", "DataSetFetchDisplayNames": "boolean", "DataSetWriterWatchdogBehavior": "string", "OpcNodeWatchdogTimespan": "string", "OpcNodeWatchdogCondition": "string", "UseReverseConnect": "boolean", "DisableSubscriptionTransfer": "boolean", "RepublishAfterTransfer": "boolean", "QueueName": "string", "MetaDataQueueName": "string", "MetaDataUpdateTime": "integer", "MetaDataUpdateTimeTimespan": "string", "SendKeepAliveDataSetMessages": "boolean", "QualityOfService": "string", "MessageRetention": "boolean", "MessageTtlTimespan": "string", "MessageEncoding": "string", "MessagingMode": "string", "BatchSize": "integer", "BatchTriggerInterval": "integer", "BatchTriggerIntervalTimespan": "string", "MaxKeepAliveCount": "integer", "Priority": "integer", "OpcNodes": [ { "Id": "string", "ExpandedNodeId": "string", "BrowsePath": [ "string" ], "AttributeId": "string", "IndexRange": "string", "UseCyclicRead": "boolean", "RegisterNode": "boolean", "FetchDisplayName": "boolean", "OpcSamplingInterval": "integer", "OpcSamplingIntervalTimespan": "string", "OpcPublishingInterval": "integer", "OpcPublishingIntervalTimespan": "string", "DataSetFieldId ": "string", "DataSetClassFieldId ": "Guid", "DisplayName": "string", "SkipFirst": "boolean", "DiscardNew": "boolean", "HeartbeatInterval": "integer", "HeartbeatIntervalTimespan": "string", "QueueSize": "integer", "DataChangeTrigger": "string", "DeadbandType": "string", "DeadbandValue": "decimal", "ModelChangeHandling": { "RebrowseIntervalTimespan": "string" }, "ConditionHandling": { "UpdateInterval": "integer", "SnapshotInterval": "integer" }, "EventFilter": { (*) } } ], "Version": "integer", "LastChangeTimespan": "string", } ``` (*) To subscribe to OPC UA Alarms and Events you must configure the `EventFilter` attribute in `OpcNodes` as [described here](./readme.md#configuring-event-subscriptions). Each [published nodes entry model](./definitions.md#publishednodesentrymodel) has the following attributes: | Attribute | Mandatory | Type | Default | Description | | ----------| --------- | -----| ------- | ----------- | | `Version` | No | Integer | `null` | A monotonically increasing number identifying the change version.
NOTE: At this point the version number is informational only, but should be provided in API requests if available. It is not used inside file based configuration. | | `LastChangeTimespan` | No | String | `null` | The time the Publisher configuration was last updated.
Read only and informational only. | | `EndpointUrl` | Yes | String | N/A | The OPC UA server endpoint URL | | `UseReverseConnect` | No | Boolean | `false` | Controls whether to use OPC UA reverse connect to connect to the OPC UA server.
A publisher wide default value can be set using the [command line](./commandline.md) | | `DisableSubscriptionTransfer` | No | Boolean | `false` | This setting allows you to disable subscription transfer on reconnect to fix interoperability issues with servers that do not support it.
A publisher wide default value can be set using the [command line](./commandline.md) | | `UseSecurity` | No | Boolean | `false` | Controls whether to use a secure OPC UA mode to establish a session to the OPC UA server endpoint.
`true` corresponds to `EndpointSecurityMode` = `SignAndEncrypt`, `false` to `EndpointSecurityMode` = `None` | | `EndpointSecurityMode` | No | Enum | `null` | Enum to specify a requested security mode of the chosen session endpoint. Overrides `UseSecurity` value.
Options: `Sign`, `SignAndEncrypt`, `None`, and `Best` (security mode possible which might include `None`) | | `EndpointSecurityPolicy` | No | String | `null` | String to specify a security policy the chosen endpoint must meet. Refines the endpoint chosen through `EndpointSecurityMode` and overrides `UseSecurity` value. | | `OpcAuthenticationMode` | No | Enum | `Anonymous` | Enum to specify the session authentication.
Options: `Anonymous`, `UsernamePassword`, `Certificate` | | `OpcAuthenticationUsername` | No | String | `null` | The username for the session authentication if OpcAuthentication mode is `UsernamePassword`. Otherwise the subject name of a x509 certificate in the user certificate store. Ignored if the mode is `Anonymous`. | | `OpcAuthenticationPassword` | No | String | `null` | The password for the session authentication if OpcAuthentication mode is `UsernamePassword`. Otherwise the password to access the private key of the referenced certificate in the user certificate store. Ignored if the mode is `Anonymous`.| | `DataSetWriterGroup` | No | String | `"<>"` | The data set writer group collecting datasets defined for a certain
endpoint uniquely identified by the above attributes.
This attribute is used to identify the session opened into the
server. The default value consists of the EndpointUrl string,
followed by a deterministic hash composed of the
EndpointUrl, UseSecurity, OpcAuthenticationMode, UserName and Password attributes. | | `DataSetWriterId` | No | String | `"<>"` | The unique identifier for a data set writer used to collect
OPC UA nodes to be semantically grouped and published with
the same publishing interval.
When not specified a string representing the common
publishing interval of the nodes in the data set collection.
This attribute uniquely identifies a data set
within a DataSetWriterGroup. The uniqueness is determined
using the provided DataSetWriterId and the publishing
interval of the grouped OpcNodes. An individual
subscription is created for each DataSetWriterId. | | `DataSetName` | No | String | `null` | The optional name of the data set as it will appear in the dataset metadata. | | `DataSetDescription` | No | String | `null` | The optional description for the data set as it will appear in the dataset metadata. | | `DataSetClassId` | No | Guid | `Guid.Empty` | The optional dataset class id as it shall appear in dataset messages and dataset metadata. | | `DataSetExtensionFields` | No | Object | `null` | An optional JSON object with key value pairs where the value is a Variant in JSON encoding. This can be used to [contextualize data set messages](#key-frames-delta-frames-and-extension-fields) produced by the writer.
Each item is added to key frame and meta data messages in the same data set, or in the extension section of samples messages (in samples messages the value is stringified). | | `DataSetPublishingInterval` | No | Integer | `null` | The publishing interval used for a grouped set of nodes under a certain DataSetWriter.
Value expressed in milliseconds.
Ignored when `DataSetPublishingIntervalTimespan` is present.
*Note*: When a specific node underneath DataSetWriter defines `OpcPublishingInterval` (or Timespan),
its value will overwrite publishing interval and potentially split the data set writer into more than one subscription. | | `DataSetPublishingIntervalTimespan` | No | String | `null` | The publishing interval used for a grouped set of nodes under a certain DataSetWriter.
Value expressed as a Timespan string ({d.hh:mm:dd.fff}).
When both Intervals are specified, the Timespan will win and be used for the configuration.
*Note*: When a specific node underneath DataSetWriter defines `OpcPublishingInterval` (or Timespan),
its value will overwrite publishing interval and potentially split the data set writer into more than one subscription. | | `DataSetSamplingInterval` | No | Integer | `null` | A default sampling interval for all monitored items that are sampled in the data set.
Value expressed in milliseconds.
This value will be overwritten if a sampling interval is defined for a node.
The value is used as defined in the OPC UA specification.
Ignored when `DataSetSamplingIntervalTimespan` is present.
Defaults to the value configured via `--oi` command line option. | | `DataSetSamplingIntervalTimespan` | No | String | `null` | The default sampling interval for all monitored items that are sampled in the data set.
Value expressed as Timespan string ({d.hh:mm:dd.fff}).
This value is used if the sampling interval is not configured on an individual node.
The value is used as defined in the OPC UA specification. | | `DataSetKeyFrameCount` | No | Integer | `null` | The optional number of messages until a key frame is inserted.
Only valid if messaging mode supports key frames. | | `DataSetFetchDisplayNames` | No | Boolean | `null` | Whether to fetch the display name and use it as
data set id for all opc node items in the data set.
Defaults to the value configured via `--fd` command line option. | | `MetaDataUpdateTime` | No | Integer | `null` | The optional interval at which meta data messages should be sent even if the meta data has not changed.
Only valid if messaging mode supports metadata or metadata is explicitly enabled. | | `MetaDataUpdateTimeTimespan` | No | String | `null` | Same as `MetaDataUpdateTime` but expressed as duration string.
Takes precedence over the Integer value. | | `SendKeepAliveDataSetMessages` | No | Boolean | `false` | Whether to send keep alive data set messages for this data set when a subscription keep alive notification is received.
Only valid if messaging mode supports keep alive messages. | | `MessageEncoding` | No | String | `null` | The message encoding to use when publishing the data sets.
For the list of supported message type names see [here](./messageformats.md#messaging-profiles-supported-by-opc-publisher) | | `MessagingMode` | No | String | `null` | The messaging mode to use when publishing the data sets.
For the list of supported messaging mode names see [here](./messageformats.md#messaging-profiles-supported-by-opc-publisher) | | `WriterGroupTransport` | No | String | `null` | The transport technology to use when publishing messages.
For the list of supported transport names see [here](./transports.md) | | `WriterGroupPartitions` | No | Integer | `1` | Number of partitions to split the writer group into when publishing to target topics. | | `WriterGroupQueueName` | No | String | `null` | Writer group queue overrides the default writer group topic template to use. | | `WriterGroupMessageRetention` | No | Boolean | `null` | Message retention flag value for all messages sent through the writer group if the transport supports it. | | `WriterGroupMessageTtlTimespan` | No | String | `null` | Message time to live expressed as duration string for messages sent through the writer group if the transport supports it. | | `WriterGroupQualityOfService` | No | String | `null` | The quality of service for telemetry messages (if supported by transport).
One of `AtMostOnce`, `AtLeastOnce`, or `ExactlyOnce`.
Defaults to the value configured via `--qos` command line option or if not provided `AtLeastOnce` (QOS 1). | | `Priority` | No | Integer | `null` | Priority of the writer subscription. | | `BatchSize` | No | Integer | `null` | The optional number of notifications that are queued before a network message is generated.
For historic reasons the default value is 50 unless otherwise configured via `--bs` command line option. | | `BatchTriggerInterval` | No | Integer | `null` | The network message publishing interval. Network and meta data messages are published cyclically from the notification queue when the specified duration has passed (or when the batch size configuration triggered a network message).
For historic reasons the default value is 10 seconds unless otherwise configured via the `--bi` command line option. | | `BatchTriggerIntervalTimespan` | No | String | `null` | Same as `BatchTriggerInterval` but expressed as duration string.
Takes precedence over the Integer value. | | `DisableSubscriptionTransfer` | No | Boolean | `false` | Disable subscription transfer on reconnect to override the default behavior per endpoint. | | `RepublishAfterTransfer` | No | Boolean | `true` | Republishes any missing values after a subscription is transferred on reconnect. | | `MaxKeepAliveCount` | No | Integer | `null` | When the publishing timer has expired this number of times without requiring any Notification to be sent, to the writer a keep-alive message is sent. | | `QueueName` | No | String | `null` | Writer queue overrides the writer group queue name.
Network messages are split by different Qos settings. | | `MessageRetention` | No | Boolean | `null` | Message retention setting for messages sent by the writer if the transport supports it
Network messages are split by differing retention flag values. | | `MessageTtlTimespan` | No | String | `null` | Message time to live expressed as duration string for messages sent by the writer.
Network messages are split across different Ttl settings. | | `QualityOfService` | No | String | `null` | Quality of service to use for the writer.
One of `AtMostOnce`, `AtLeastOnce`, or `ExactlyOnce`.
Overrides the Writer group quality of service and together with queue name causes network messages to be split.. | | `MetaDataQueueName` | No | String | `null` | Meta data queue name to use for the writer.
Overrides the default metadata topic template. | | `DataSetWriterWatchdogBehavior` | No | String | `null` | Determines what to do when the data set writer watchdog triggers.
One of `Diagnostic`, `Reset`, `FailFast`, or `ExitProcess`.
Defaults to the value configured via `--dwb` command line option. | | `OpcNodeWatchdogTimespan` | No | String | `null` | Determines the timeout of the monitored item watchdog that triggers the `DataSetWriterWatchdogBehavior`.
Value is expressed as Timespan string ({d.hh:mm:dd.fff}).
Defaults to the value configured via `--mwt` command line option. | | `OpcNodeWatchdogCondition` | No | String | `null` | Run the watchdog behavior for the writer subscription `WhenAllAreLate` or `WhenAllAreLate`.
Defaults to the value configured via `--mwc` command line option. | | `OpcNodes` | No (see notes) | `List` | empty | The DataSet collection grouping the nodes to be published for
the specific DataSetWriter defined above. | *Note*: `OpcNodes` field is mandatory for `PublishNodes_V1`. It is optional for `CreateOrUpdateDataSetWriterEntry_V2`, `UnpublishNodes_V1` and `AddOrUpdateEndpoints_V1`. The `OpcNodes` field shouldn't be specified for the rest of the direct methods taking an entry object. Each [OpcNode](./definitions.md#opcnodemodel) has the following attributes: | Attribute | Mandatory | Type | Default | Description | | --------- | --------- | ---- | ------- | ----------- | | `Id` | Yes* | String | N/A | The OPC UA [NodeId](#node-ids) in the OPC UA server whose data value changes should be published.
Can be specified as NodeId or ExpandedNodeId as per OPC UA specification,
or as ExpandedNodeId IIoT format {NamespaceUi}#{NodeIdentifier}.
**Note*: `Id` field may be omitted when `ExpandedNodeId` is present. | | `ExpandedNodeId` | No | String | `null` | Enables backwards compatibility.
Must be specified as ExpandedNodeId as per OPC UA specification.
**Note*: when `ExpandedNodeId` is present `Id` field may be omitted. | | `BrowsePath` | No | `List` | `null` | The [browse path](#browse-paths) from the Node configured in `Id` to the actual node to monitor.
**Note*: if the node `Id` is not provided, `i=84` (root node) is assumed. | | `AttributeId` | No | String | `Value` | The node attribute to sample in case the node is a variable value (data item).
The allowed values are defined in the OPC UA specification.
Ignored when subscribing to events. | | `IndexRange` | No | String | `null` | The index range of the value to publish.
Value expressed as a numeric range as defined in the OPC UA specification.
Ignored when subscribing to events. | | `OpcSamplingInterval` | No | Integer | `1000` | The sampling interval for the monitored item to be published.
Value expressed in milliseconds.
The value is used as defined in the OPC UA specification.
Ignored when `OpcSamplingIntervalTimespan` is present. | | `OpcSamplingIntervalTimespan` | No | String | `null` | The sampling interval for the monitored item to be published.
Value expressed in Timespan string({d.hh:mm:dd.fff}).
The value is used as defined in the OPC UA specification. | | `OpcPublishingInterval` | No | Integer | `null` | The publishing interval for the monitored item to be published.
Value expressed in milliseconds.
This value will overwrite the publishing interval defined in the DataSetWriter for the specified node.
The value is used as defined in the OPC UA specification.
Ignored when `OpcPublishingIntervalTimespan` is present. | | `OpcPublishingIntervalTimespan` | No | String | `null` | The publishing interval for the monitored item to be published.
Value expressed in Timespan string ({d.hh:mm:dd.fff}).
This value will overwrite the publishing interval defined in the DataSetWriter for the specified node.
The value is used as defined in the OPC UA specification. | | `DataSetFieldId` | No | String | `null` | A user defined tag used to identify the field in the
DataSet telemetry message when publisher runs in
PubSub message mode. | | `DataSetClassFieldId` | No | Guid | `Guid.Empty` | A user defined Guid that identifies the field in the data set class of the
DataSet telemetry message when publisher runs in
PubSub message mode.
This value is ignored when subscribing to events, in which case a `DataSetClassFieldId` can be applied to each select clause that select the content of the event dataset. | | `DisplayName` | No | String | `null` | A user defined tag to be added to the telemetry message
when publisher runs in Samples message mode. | | `HeartbeatInterval` | No | Integer | `0` | The interval used for the node to publish a value (a publisher
cached one) even if the value hasn't been changed at the source.
Value expressed in seconds.
0 means the heartbeat mechanism is disabled.
This value is ignored when `HeartbeatIntervalTimespan` is present. | | `HeartbeatIntervalTimespan` | No | String | `null` | The interval used for the node to publish a value (a publisher
cached one) even if the value hasn't been changed at the source.
Value expressed in Timespan string ({d.hh:mm:dd.fff}). | | `SkipFirst` | No | Boolean | `false` | Whether the first received data change for the monitored item should not be sent. This can avoid large initial messages since all values are sent by a server as the first notification.
If an `EventFilter` is specified, this value is ignored | | `QueueSize` | No | Integer | `1` | The desired QueueSize for the monitored item to be published. | | `FetchDisplayName` | No | Boolean | `false` | Whether the server shall fetch display names of monitored variable nodes and use those inside messages as field names. Default is to use the `DisplayName` value if provided even if this option is set to `true`, if not provided or `false`, and no `DisplayName` specified, the node id is used. | | `DiscardNew` | No | Boolean | `false` | Whether the server shall discard new values when the queue is full. Default is false, it will discard values that have not been sent yet. | | `UseCyclicRead` | No | Boolean | `false` | Read the value periodically at the sampling rate instead of subscribing through subscriptions.
Ignored when subscribing to events. | | `RegisterNode` | No | Boolean | `false` | Register the node to sample using the Register service call before accessing. Some servers then support faster reads, but this is not guaranteed.
The service is defined in the OPC UA specification.
Ignored when subscribing to events. | | `DataChangeTrigger` | No | String | `null` | The data change trigger to use.
The default is `"StatusValue"` causing telemetry to be sent when value or statusCode of the DataValue change.
`"Status"` causes messages to be sent only when the status code changes and
`"StatusValueTimestamp"` causes a message to be sent when value, statusCode, or the source timestamp of the value change. A publisher wide default value can be set using the [command line](./commandline.md). This value is ignored if an EventFilter is configured. | | `DeadbandType` | No | String | `1` | The type of dead band filter to apply.
`"Percent"` means that the `DeadbandValue` specified is a percentage of the EURange of the value. The value then is clamped to a value between 0.0 and 100.0
`"Absolute"` means the value is an absolute deadband range. Negative values are interpreted as 0.0. This value is ignored if an `EventFilter` is present. | | `DeadbandValue` | No | Decimal | `1` | The deaad band value to use. If the `DeadbandType` is not specified or an `EventFilter` is specified, this value is ignored. | | `EventFilter` | No | [EventFilter](./definitions.md#eventfiltermodel) | `null` | An [event filter](./readme.md#configuring-event-subscriptions) configuration to use when subscribing to events instead of data changes. | | `ConditionHandling` | No | [ConditionHandlingOptions](./definitions.md#conditionhandlingoptionsmodel) | `null` | Configures the special [condition handling logic](./readme.md#condition-handling-options) when subscribing to events. | | `ModelChangeHandling` | No | [ModelChangeHandlingOptions](./definitions.md#modelchangehandlingoptionsmodel) | `null` | Configures model change tracking through this node (Experimental). | > The configuration file syntax has been enhanced over time. OPC Publisher reads old formats and converts them into the current format when persisting the configuration. OPC Publisher regularly persists the configuration file. ### Writer group configuration **DataSets** are a group of nodes within one OPC UA server. Datasets contain data value changes for nodes that all share a common [publishing interval](#sampling-and-publishing-interval-configuration). A `DataSetWriter` emits **DataSetMessages** containing a DataSet. The Writer has all information to establish a connection to an OPC UA server. A `DataSetWriterGroup` is used to group several DataSetWriter's for a specific OPC UA server. A DataSetWriterGroup emits what is called a **NetworkMessage** containing the **DataSetMessages**. The following diagram courtesy of the OPC Foundation reference specification hows the relationship between these concepts and the messages emitted over the specified transport protocol: ![Messages](https://reference.opcfoundation.org/api/image/get/307/image023.png) In the implementation of OPC Publisher, a Writer group is defined by the `DataSetWriterGroup` name attribute in the configuration. Due to the limitations of the configuration schema, for attributes that apply to the Writer group the value of the first configuration entry object will be used. All other values in further entries with the same `DataSetWriterGroup` value are discarded. It is recommended to use the same values for all writer group related attributes in all entries for a consistent and deterministic behavior. The following configuration properties of the published nodes entry model apply to the Writer group: - Messaging profile (`MessageEncoding`, `MessagingMode`) - Batch size and batch publishing interval (`BatchSize`, `BatchTriggerIntervalTimespan`) - Desired transport (`WriterGroupTransport`) > IMPORTANT: It is important to set a unique `DataSetWriterGroup` name when configuring the above settings. Not doing so will yield unexpected behavior as all configurations with the same writer group name are collated into a single one with differing settings being clobbered. A `DataSetWriter` is defined by its `DataSetWriterId` and the effective `DataSetPublishingInterval` of the writer. A group of nodes with the same [publishing interval](#sampling-and-publishing-interval-configuration) becomes a writer inside a writer group, regardless of using the same `DataSetWriterId`. If the same `DataSetWriterId` is used but with nodes that have different effective publishing intervals, then a postfix string is added to the name to further disambiguate. > IMPORTANT: Just like the writer group configuration, it is important to set a unique `DataSetWriterId` name when configuring multiple writers with different settings (publishing interval excluded). Not doing so will yield unexpected behavior as all configurations with the same dataset writer name are collated into a single one with differing settings being clobbered. Due to historic reasons, by default a session is scoped to a writer group. That means for each endpoint url and security configuration inside a single writer group a single session is opened and the subscriptions are established inside the session. If you use more than one writer group in your configuration and each contain writers with the same endpoint information, multiple sessions will be created. This can be overridden using command line options. OPC Publisher will try to re-use an existing OPC UA subscription or create a new one per `DataSetWriter`. ### Configuration via init file OPC Publisher can be configured remotely using its [writer](./api.md#writer) and [node](./api.md#configuration) configuration API. This API can be invoked via HTTP, MQTT (RPC), in many cases through IoT Hub direct methods, but also using OPC Publisher's init file feature. The init file can be specified using the [command line option](./commandline.md) `--pi, --initfile`. The file can be updated while OPC Publisher is running, in which case the new file content will be executed. The file will not be run if it has not changed. This applies also across restarts. However, this requires that the response file (see the `--il, --initlog` [argument](./commandline.md)) is writeable. The init file format follows the [.http file format](https://learn.microsoft.com/aspnet/core/test/http-files) with the additional exception that scripting, variables, and `{{ }}` templates are not supported. While the [method line](https://learn.microsoft.com/aspnet/core/test/http-files#requests) can start with a `HTTPMethod` and end with a `HTTPVersion`, they are effectively discarded at the moment. The `URL` must be a direct method name as specified in the API documentation, e.g. `AddOrUpdateEndpoint_V1`. While headers can be provided, the only relevant one is `Content-Type` which defaults to `application/json`. In addition to the documented format, the init file format supported by OPC Publisher supports the following additional request directives which can be provided after a comment (# or //): | Directive | Description | | --------- | ----------- | | **@no-log** | Disable logging for this request after this directive.
This directive must be applied for every request and on the first line so that nothing is emitted to the init log. | | **@timeout** | Timeout for the request.
If the request times out it will be an error and all further requests are not sent. | | **@retries** | Retry this number of times in case of an error.
An error is any request that returns with status code >= 400. | | **@delay** | Delay before executing a request.
If retries are specified the delay applies again before every retry. | | **@on-error** | Invoke the request only when the previous request failed.
If the previous request has **@continue-on-error** directive this request will not be executed. If the request succeeds the next request after is run. | | **@continue-on-error** | Continue to next request even if the request failed.
The default behavior is to stop execution of requests except for the next request with **@on-error** directive. | The **@on-error** condition can be used as an error handler e.g. to call the [Shutdown](./directmethods.md#shutdown_v2) method. If the restart is immediate, the init file will be execute again after restart. A delay can throttle these restarts. An example init file is shown here: ``` json ### // 3 retries in case of failure, with a delay of 5 seconds between // @delay 5 // @retries 3 // Creates writer entries for all objects that implement the // machine tool object type or one of its subtypes on this server ExpandAndCreateOrUpdateDataSetWriterEntries_V2 { "entry": { "EndpointUrl": "opc.tcp://opcua.umati.app:4840", "UseSecurity": false, "DataSetWriterGroup": "MachineTools", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/MachineTool/;i=13" } ] } } ### // Shutdown the publisher in case the expansion failed // and let docker restart it. The Fail fast argument // provided as json payload. # @on-error Shutdown_V2 true ### ``` More init file examples with explanations can be found [here](./intfilesamples.md). ### Sampling and Publishing Interval configuration The OPC UA reference specification provides a detailed overview of the OPC UA [monitored item](https://reference.opcfoundation.org/Core/Part4/v104/docs/5.12) and [subscription](https://reference.opcfoundation.org/Core/Part4/v104/docs/5.13.1) service model. A `DataSetWriter` is a group of (variable or event notifier) nodes inside an OPC UA server that constitute a data set. Several parameters can be configured for each node that tell the Server how the node is to be sampled, evaluated and reported. These [attributes](#configuration-schema) include - Sampling interval (`OpcSamplingInterval` or `OpcSamplingIntervalTimespan` or `DataSetSamplingIntervalTimespan` at the entry level) - Filter definition (`DeadbandValue`, `DeadbandType`, and `DataChangeTrigger` for variables, or [EventFilter](./definitions.md#eventfiltermodel) in case the monitored item is an event notifier) - Queue mode (`DiscardNew`) and - Queue length (`QueueSize`) The following overview diagram courtesy of the OPC Foundation shows how the server operates based on the configuration: ![Reference](https://reference.opcfoundation.org/api/image/get/407/image018.png) A subscription is created for a `DataSetWriter` if none with the same subscription settings already exists. The publishing interval (configured using the `DataSetPublishingInterval` or `OpcPublishingInterval` values) is an attribute of the subscription (hence multiple writers are instantiated if there are multiple different publishing intervals nodes under a data set writer configured). The publishing interval defines the cyclic rate at which it collects values from the monitored item queues. Each time it attempts to send a Notification Message to OPC Publisher containing new values or events of its monitored items. A default OPC Publisher wide publishing interval can be provided using the [command line option](./commandline.md) (`--op`) which is used when the interval is not configured. The default publishing interval used by OPC Publisher is 1 second. It is also possible to override all publishing intervals configured in the OPC Publisher configuration using the `--ipi` command line option. Setting the publishing interval to `0` instructs the server to choose the fastest publishing interval cycle it can manage. This can be useful if you have existing configuration specifying multiple publishing intervals but would like to avoid separate subscriptions to be created for each interval, or just put the server in charge. Note though that the `--npd` command line will still split a data set writer if more nodes than the configured amount are specified in the configuration file. The diagnostics output and metrics contain a `Server queue overflows` instrument which captures the number of data values with overflow bit set and indicates data changes were lost. Increase the `QueueSize` of frequently sampled items until the instrument stays `0`. You can also configure the publisher with the `--aq` command line option and let it calculate an appropriate queue size taking into account the (revised) publishing interval and sampling interval for a monitored item. Notifications received by the writers in the writer group inside OPC Publisher are batched and encoded and published to the chosen [transport sink](./transports.md). The OPC UA server always sends the first data value to OPC Publisher when a monitored item is added to a subscription. To prevent publishing all of these values during startup, the `SkipFirst` value can be specified in the data item's configuration: ``` json "SkipFirst": true, ``` #### Key frames, delta frames and extension fields OPC UA optimizes network bandwidth by only sending changes to OPC Publisher when the data item's value has changed. These messages are sent as `ua-deltaframe` messages by the data set writer, and the resulting data set messages are sparse. It is desirable to send all other values that have not changed together with a value that changed as a key frame (`ua-keyframe`). To accomplish this a writer can be configured with a `DataSetKeyFrameCount` value other than 0. If this is the case, all values are sent in the first message, and then every `DataSetKeyFrameCount` number of messages later. The `DataSetExtensionFields` object in the [configuration](#configuration-schema) can be used to insert additional fixed fields into these key frame messages which allows you to contextualize messages with data that is available in external systems only, or that allows your application to understand the context in which the message is produced. An example configuration is shown here: ```json [ { ... "MessagingMode": "PubSub", "DataSetExtensionFields": { "EngineeringUnits": "mm/sec", "AssetId": 5, "Important": false, "Variance": { "Value": 0.4, "DataType": "Single" } }, "DataSetKeyFrameCount": 3, "OpcNodes": [ ... ] } ] ``` Values are formatted using the extended OPC UA Variant [JSON format](#json-encoding). This encoding is compliant with OPC UA Part 6, however it also allows to use simple JSON types which will be interpreted as Variant values using a simple heuristic, mapping the best OPC UA type possible to it. > IMPORTANT: Extension fields are only sent as part of key frame messages when using Pub Sub encoding. You must configure a key frame count for key frames to be sent as the default key frame count value is 0 and therefore key frames are disabled. #### Status codes The status code `value` is the integer received over the wire from the server (full one including all bits). StatusCode "Good" is defined as 0 in OPC UA, which is omitted in JSON encoding (as per Part 6). The `symbol` in the encoding is what OPC Publisher is looking up from the standard defined codes (using the code bits which are the 16 bits defining the error code part of the status code). The symbol can be `Good` and still show up in the message when other bits are set in the `value`, e.g., overflow status, or additional information status, etc. One such example is the value `1152` which indicates the overflow bit (the server monitored item queue was in an overflow condition, which means the queue size should be increased): ``` bash CodeBits = Value & 0xFFFF0000; --> This is used to look up the symbol which is "Good". FlagBits = Value & 0x0000FFFF; 1152 == 0x480 == DataValueInfo | OverflowBit ``` You can find more information in [Part 4](https://reference.opcfoundation.org/v105/Core/docs/Part4/7.39.1) of the OPC UA reference. #### Heartbeat Some use cases require to publish data values in constant intervals. OPC Publisher has always supported a "heartbeat" option on the configured monitored node item. Heartbeat acts like a watchdog which fires after the heartbeat interval has passed and no new value has yet been received. It can be enabled by specifying the `HeartbeatInterval` key in an item's configuration. The interval is specified in seconds (but can also be specified as a Timespan value): ``` json "HeartbeatInterval": 60, ``` The behavior of heartbeat can be fine tuned using the `--hbb, --heartbeatbehavior` [command line options](./commandline.md) or the ``` json "HeartbeatBehavior": "...", ``` option of the node entry. The behavior can be set to watch dog behavior with Last Known Value (`WatchdogLKV`, which is the default) or Last Known Good (`WatchdogLKG`) semantics. A last known good value has either a status code of `Good` or a valid value (!= Null) and not a bad status code (which covers other Good or Uncertain status codes). Bad values are not causing heartbeat messages in LKG mode. A continuous periodic sending of the last known value (`PeriodicLKV`) or last good value (`PeriodicLKG`) can also be selected. In some cases periodic reporting is all that is needed, and the actual value read that is reported out of period should be dropped. Use the `PeriodicLKVDropValue` or `PeriodicLKGDropValue` behavior to achieve this behavior. The outcome is similar to the [cyclic read](#cyclic-reading-client-side-sampling) mode but using a periodic timer over server side sampled nodes. The heartbeat behavior `WatchdogLKVDiagnosticsOnly` is special, it allows you to log heartbeat in the diagnostics output without sending heartbeats as part of the outgoing messages. ##### Timestamps The OPC UA data value contains a source and server timestamp. These are reported by the server and are based on the OPC UA server clock. The server is free to send whatever timestamp it wants, including none even though the OPC Publisher is setting up all monitored items to report both timestamps. When you want to analyze time series of data sets (where the value timestamps of every field in the data set will be different) or when you want to use Heartbeats (where the LKG or LKV are re-sent with the original timestamps), the `Timestamp` of the message should be used instead of the `SourceTimestamp` or `ServerTimestamp` values. > NOTE: The Timestamp property is not part of the regular legacy samples messages. You must set `--fm=True` for them to be included. The timestamp of the message is the time the notification *was received from the OPC UA server*. Using the `--mts` [command line options](./commandline.md) other sources for this timestamp can be chosen, e.g., the time of encoding (which is shortly before sending to the data sink), or the `PublishTime` property of the subscription notification received from the server (provided by OPC UA server). > Note that if the `PublishTime` is selected as message timestamp, heartbeat messages will not have a message timestamp as they are generated locally and not as a result of a publish operation. ##### Legacy behavior We still support a heartbeat behavior that mimics the behavior of heartbeat in 2.8 and below. Here the source timestamp of the value will be shifted by the time passed since receiving it. This behavior can be enabled by specifying `--hbb=WatchdogLKVWithUpdatedTimestamps` as [command line argument](./commandline.md) during deployment. This behavior only mimics the old behavior. In past versions of OPC Publisher the heartbeat option layered on top of the Keep Alive mechanism of the subscription and was similar to `WatchdogLKVWithUpdatedTimestamps`. In 2.9 and higher the heartbeat is emitted every heartbeat interval from the last received value until a new value is received following a watchdog pattern. Given that the previous mechanism resulted in unexpected behavior, the new mechanism has a simpler and more reliable pattern leading to the desired outcome. It is also better because heartbeats are also sent when OPC Publisher is not connected to the server (during intermittent disconnects). > Please be aware that when analyzing using `SourceTimestamp` or `ServerTimestamp` properties, the values are provided by the server, not by OPC Publisher. They are therefore only as reliable as the server implementation. This also extends to heartbeats when `WatchdogLKVWithUpdatedTimestamps` behavior is used. When the server sends a data value without or invalid timestamps, these timestamps are shifted and can result in garbage. The best solution is to primarily rely on the message timestamp and only `SourceTimestamp` as secondary information. #### Cyclic reading (Client side sampling) Similar use cases require cyclic read based sampling using read service calls on a periodic timer. The `UseCyclicRead` property of a configured node tells OPC Publisher to sample the value periodically when the timer expires. Note that read operations of all nodes at the same sampling rate are batched together for efficiency. They only execute when no previous read operation is in progress when the period expires. While the sampler configures a timeout of half the sampling rate in case of high frequency sampling a value every time the sampling rate expires cannot be guaranteed. ``` json "UseCyclicRead": true, ``` The diagnostics output and metrics contain a `Server queue overflows` instrument. In the case of cyclic reads these are the number of skipped value reads because a cycle was missed due to delays reading from the server. For example when configuring a 1 second sampling interval and the read operation takes 2.5 seconds, then 1 cycle will be missed and 1 overflow per value will be reported. Either set a less aggressive sampling interval (e.g., 3 seconds in the above case) or configure less items in the data set writer (if latency is due to the # of read operations in a single read request or the operation limits of the server). Note that reads are batched into a single service call. Therefore slow nodes can impact other nodes that can be read faster. You can configure the caching mode and cache age to use when reading the node value using the `CyclicReadMaxAgeTimespan` property which must be below or equal the cyclic sampling rate chosen for the node. Set the duration to 0 (which is the default) to always use *uncached* reads. In addition it is possible to combine cyclic reads with registering the node to read ("registered read") by setting the `RegisterNode` property of the node to `true`. This way some servers can optimize reading values from the backend for these nodes, however only a limited number of "registered nodes" are supported in such servers. The OPC UA subscription/monitored items service due to its async model (server side sampling, queuing and publishing) is by far way more efficient than cyclically reading nodes from the server. Limits are reached relatively quickly compared to regular operation and heavily depend on the OPC UA server implementation and vendor. ### Overcoming server limits and interop limitations OPC UA servers can be limited with regards to the amount of sessions, subscriptions or publishing requests they support. By default OPC Publisher tries to bundle as many writers with the same subscription configuration (including the publishing interval) into a OPC UA subscription inside a (writer group) session. It uses the `MaxMonitoredItemsPerSubscription` limit provided by in the Server capabilities object read by OPC Publisher when the session is created to create the right number of subscriptions that hold as many monitored items as possible. If the limit a not provided by the server or is 0, OPC Publisher uses a default value of `65536`. This value can be overridden using the `--xmi --maxmonitoreditems` [command line](./commandline.md) option. OPC Publisher has several options to overcome additional server limitations and that can be used to tune and overcome interoperability issues. - To minimize the number of sessions against a server, the default behavior of creating a session per writer group can be overridden using the `--dsg, --disablesessionpergroup` command line option which results in a *session per endpoint* spanning multiple writer groups with the same endpoint url and configuration. - To further limit the number of subscriptions avoid specifying different publishing intervals for the `OpcNodes` items in the OPC Publisher [configuration](#configuration-schema). Each publishing interval will result in a subscription with the server inside the (writer group) session. - You can use the `--ipi, --ignorepublishingintervals` command line option to *ignore publishing interval configuration* in the JSON configuration and use the publishing interval configured using the `--op` command line option (default: 1 second). - In addition you can set the `--op=0` to let the server decide the smallest publishing interval it offers. - You can also use the `--aq, --autosetqueuesize` option to let OPC Publisher calculate the best queue size for monitored items in the subscription to limit data loss. - By default OPC Publisher tries to dispatch as many publishing requests to a server session as there are subscriptions in the session up to a maximum of `10`. The OPC UA stack tries to gradually lower the number based on feedback from the server (`BadTooManyPublishRequests`). This behavior is not tolerated by some servers. To set a lower maximum that OPC Publisher should never exceed use the `--xpr` command line option. ### Configuring Security IoT Edge automatically provides OPC Publisher with a secure configuration to access IoT Hub. OPC UA does use [X.509 certificates](#opc-ua-certificates) fo mutual authentication of both OPC Publisher clients and the OPC UA server and to establish a secure channel between both. OPC Publisher can be configured to [store these certificates](#pki-management) in a file system based certificate store which root can be configured using the `--pki` [command line argument](./commandline.md). During startup, OPC Publisher checks if there's already a private certificate it should use as its identity. If it cannot find one, a self-signed certificate is created. > Self-signed certificates don't provide any trust value and we don't recommend using them in production. Encrypted communication between OPC Publisher and the OPC UA server can be enabled per endpoint via the `"UseSecurity": true,` flag in the [configuration](#configuration-schema). In addition, a specific security mode and policy can be chosen using the `EndpointSecurityMode` and `EndpointSecurityPolicy` configuration properties which possibly override the `UseSecurity` value. If none of these are specified then OPC Publisher will connect to the endpoint URL using **no security** at all to support backwards compatibility to previous versions of OPC Publisher. > Use encrypted communication whenever possible. Do not use `Best` as `EndpointSecurityMode` as this can mean that `None` could be chosen if the server does not returns any secure endpoint descriptors during discovery. In this case it is better to fail connecting. By default OPC Publisher connects to the endpoint using anonymous authentication. However, OPC Publisher also supports user authentication using username and password. These credentials can be specified using the configuration file as follows: ``` json "OpcAuthenticationMode": "UsernamePassword", "OpcAuthenticationUsername": "usr", "OpcAuthenticationPassword": "pwd", ``` OPC Publisher also supports X.509 Certificate based user authentication. A user certificate with private key must be added to the `User` certificate store of the [PKI](#pki-management). The user name then refers to the subject name of the certificate and the password to the password that was used to protect the pfx blob representing the user certificate. For example: ``` json "OpcAuthenticationMode": "Certificate", "OpcAuthenticationUsername": "certificate-subject-name", "OpcAuthenticationPassword": "certificate-password", ``` > If user credentials are configured you should always enable encrypted communication to ensure the secrets are not leaked. OPC Publisher does not force encrypted authentication if a password is specified. OPC Publisher version 2.5 and below encrypts the username and password in the configuration file. Version 2.6 and above stores them in plain text. 2.9 allows you to force encryption of credentials at rest (`--fce`) or otherwise cause OPC Publisher to exit. ### Using OPC UA reverse connect You can let servers connect to OPC Publisher using the OPC UA reverse connect mode. This allows an OPC UA server to connect to OPC Publisher located in a higher layer network instead of opening up inbound ports to let OPC Publisher connect to it. Consequently only an outbound port needs to be opened in the lower layer network. You can find more information in [OPC UA standard Part 6](https://reference.opcfoundation.org/v104/Core/docs/Part6/7.1.3/). Reverse connect mode can be enabled per endpoint. This can be done using the `UseReverseConnect` property inside the published nodes configuration entry. An OPC Publisher-wide default for the case the property is missing can be configured using the `--urc` [command line options](./commandline.md). Reverse connect is only supported for the opc.tcp scheme of endpoint urls. Reverse connecting other transports is not supported. If OPC Publisher cannot find a Url candidate with the opc.tcp scheme to use when reverse connecting it will try to establish a regular connection to any of the other candidate endpoints instead (see [ConnectionModel](./definitions.md#connectionmodel) for more information). OPC Publisher will listen for reverse connect requests on port 4840, unless a different port is configured through the `--rcp` [command line options](./commandline.md). You must open the port on the OPC Publisher docker container for external OPC UA servers to be able to access it. This must be done in the IoT Edge deployment manifest's create options. Add a port binding entry for port 4840 (or otherwise chosen port) container port and the host port you want to open (e.g., 4840): ```json "createOptions": "{\"User\":\"root\",\"HostConfig\":{\"PortBindings\":{\"4840/tcp\":[{\"HostPort\":\"4840\"}], ... ``` OPC Publisher opens the outbound port when the first reverse connection is required. This happens when at a published nodes entry with a reverse connected endpoint causes a subscription to be created, or by making an API call with a reverse connection model passed as part of the request, whichever happens first. Otherwise the port stays closed. It is also important to note that the Endpoint URL presented by the server in the RHEL packet must match exactly the endpoint url used to create the OPC UA client inside OPC Publisher (either the `EndpointUrl` property in the published nodes entry or the Url inside the [ConnectionModel](./definitions.md#connectionmodel)). Otherwise connections from the server will be rejected by OPC Publisher. This is important because some OPC UA servers do not use a FQDN host name in the endpoint Url in the RHEL packet they send. In this case, do not specify the FQDN in the Endpoint Url either. Follow instructions to [trouble shoot](./troubleshooting.md) OPC Publisher and in particular enable stack logging using `--sl` to see the endpoint url presented by the server when the server connection is rejected, then update the OPC Publisher configuration to match. ### Configuring event subscriptions OPC Publisher supports two types of event filter configurations you can specify: - [Simple event filter](#simple-event-filter) configuration mode, where you specify the source node and the event type you want to filter on and then the OPC Publisher constructs the select and where clauses for you. - [Advanced event filter](#advanced-event-filter-configuration) configuration mode where you explicitly specify the select and where clauses. In the configuration file you can specify how many event configurations as you like and you can also combine events and data nodes for a single endpoint. In addition you can configure optional [Condition](#condition-handling-options) reporting where OPC Publisher reports retained conditions at a configured time periodic rate in seconds. #### Simple event filter As highlighted in the example above you can specify namespaces both by using the index or the full name for the namespace. Also look at how the [BrowsePath](#browse-paths) can be configured. Here is an example of a configuration file in simple mode: ```json [ { "EndpointUrl": "opc.tcp://testserver:62563/Quickstarts/SimpleEventsServer", "OpcNodes": [ { "Id": "i=2253", "DisplayName": "SimpleEventServerEvents", "EventFilter": { "TypeDefinitionId": "ns=2;i=235" } } ] } ] ``` To subscribe to an event you specify the source node (in this case the server node which has node id `i=2253`) and the event type to monitor (in this case `ns=2;i=235`). When you use the simple configuration option above, the OPC Publisher does two things: - It looks at the TypeDefinitionId of the event type to monitor and traverses the inheritance tree for that event type, collecting all fields. Then it constructs a select clause with all the fields it finds. - It creates a where clause that is OfType(TypeDefinitionId) to filter the events to just the selected event type. #### Advanced event filter configuration To configure an advanced event filter you have to specify a full event filter which at minimum consists of three things: - The source node you want to receive events for (in the example below again the server node which has node id `i=2253`). - A select clause specifying which fields should be in the reported event. This can include a data set class field id that is then used as identifier in the dataset metadata for the dataset class. - A where clause specifying the filter AST. Here is an example of a configuration file that selects events using an advanced event filter: ```json [ { "EndpointUrl": "opc.tcp://testserver:62563/Quickstarts/SimpleEventsServer", "OpcNodes": [ { "Id": "i=2253", "DisplayName": "SimpleEventServerEvents", "EventFilter": { "SelectClauses": [ { "TypeDefinitionId": "i=2041", "DataSetClassFieldId ": "D3EB3722-E956-4E5E-925B-FB727B737520", "BrowsePath": [ "EventId" ] }, { "TypeDefinitionId": "i=2041", "DataSetClassFieldId ": "A435F616-CE1E-4FBD-A819-03175EB49231", "BrowsePath": [ "Message" ] }, { "TypeDefinitionId": "ns=2;i=235", "DataSetClassFieldId ": "BD236A98-8DA3-40A1-B8E8-00AB23A6B5E9", "BrowsePath": [ "/2:CycleId" ] }, { "TypeDefinitionId": "nsu=http://opcfoundation.org/Quickstarts/SimpleEvents;i=235", "DataSetClassFieldId ": "9F9A420B-509E-488B-A7A4-F320F8223E9E", "BrowsePath": [ "/http://opcfoundation.org/Quickstarts/SimpleEvents#CurrentStep" ] } ], "WhereClause": { "Elements": [ { "FilterOperator": "OfType", "FilterOperands": [ { "Value": "ns=2;i=235" } ] } ] } } } ] } ] ``` The exact syntax allowed can be found in the [OPC UA reference documentation](https://reference.opcfoundation.org/Core/Part4/v105/docs/7.22.3). Note that not all servers support all filter capabilities. You can [troubleshoot](./troubleshooting.md) issues using the OPC Publisher logs. #### Condition handling options > This feature is in preview In addition to event subscription, you can also configure events to enable condition handling. When configured, OPC Publisher listens to ConditionType derived events, records unique occurrences of them and periodically sends out all condition events that have the Retain property set to True. This enables you to continuously get a snapshot view of all active alarms and conditions which can be very useful for dashboard-like scenarios. Here is an example of a configuration for condition handling: ```json [ { "EndpointUrl": "opc.tcp://testserver:62563/Quickstarts/AlarmConditionServer", "OpcNodes": [ { "DisplayName": "AlarmConditions", "Id": "i=2253", "EventFilter": { "TypeDefinitionId": "i=2915" }, "ConditionHandling": { "UpdateInterval": 10, "SnapshotInterval": 20 } } ] } ] ``` The `ConditionHandling` section consists of the following properties: - `UpdateInterval` - the interval, in seconds, which a message is sent if anything has been updated during this interval. - `SnapshotInterval` - the interval, in seconds, that triggers a message to be sent regardless of if there has been an update or not. One or both of these must be set for condition handling to be in effect. You can use the condition handling configuration regardless if you are using advanced or simple event filters. If you specify the`ConditionHandling` option property without an `EventFilter` property it is ignored, as condition handling has no effect for data change subscriptions. Conditions are sent as `ua-condition` data set messages. This is a message type not part of the official standard but allows separating condition snapshots from regular `ua-event` data set messages. ## Publish to a Unified Namespace > This feature is in preview OPC Publisher allows you to map values and events obtained from the OPC UA address space to MQTT topics up to the granularity of the subscribed node id (monitored item). Specify topic templates at the level of `WriterGroup`, `DataSetWriter` or `Node` as part of the [configuration](#configuration-schema) to configure routing that meets your needs. Topic templates can apply not just to MQTT but to any transport supporting topic or queue name based routing, however, the default templates that apply use the MQTT topic format with `/` path delimiter and escape only MQTT topic reserved characters (using `\x`). For extra convenience use the automatic routing feature which leverages the OPC UA browse paths inside the address space to automatically create the topic structure. The [browse paths](#browse-paths) from the root folder (`i=84`) is used as it maps well with how clients visualize the address space. To use this feature, configure the `DataSetRouting` option in the configuration or set a default on the [command line](./commandline.md). For example when configuring the `UseBrowseNames` option all Events and data changes are routed to topics that match the browse path of the source node effectively mapping the address space into the MQTT topic structure with limited configuration overhead. When publishing value changes to topics best choose a [Message format](./messageformats.md) that has limited overhead, e.g., `SingleRawDataSet` or `SingleDataSetMessage`. ## OPC Publisher Telemetry Formats OPC Publisher version 2.6 and above supports standardized OPC UA PubSub network messages in JSON format as specified in [part 14 of the OPC UA specification](https://opcfoundation.org/developer-tools/specifications-unified-architecture/part-14-pubsub/). An example OPC UA PubSub message emitted by OPC Publisher version 2.9 and higher looks as follows: ``` json { "MessageId": "18", "MessageType": "ua-data", "PublisherId": "uat46f9f8f82fd5c1b42a7de31b5dc2c11ef418a62f", "DataSetClassId": "78c4e91c-82cb-444e-a8e0-6bbacc9a946d", "Messages": [ { "DataSetWriterId": 2, "SequenceNumber": 18, "MetaDataVersion": { "MajorVersion": 452345324, "MinorVersion": 234523542 }, "Timestamp": "2020-03-24T23:30:56.9597112Z", "Status": 0, "Payload": { "Temperature": { "Value": 99, "SourceTimestamp": "2020-03-24T23:30:55.9891469Z", "ServerTimestamp": "2020-03-24T23:30:55.9891469Z" }, "Counter": { "Value": 251, "SourceTimestamp": "2020-03-24T23:30:55.9891469Z", "ServerTimestamp": "2020-03-24T23:30:55.9891469Z" } }, "DataSetWriterName": "uat46f9f8f82fd5c1b42a7de31b5dc2c11ef418a62f" } ] } ``` OPC Publisher 2.9 and above supports strict adherence to Part 6 and Part 14 of the OPC UA specification when it comes to network message encoding. To enable strict mode use the `-c` or `--strict` [command line options](./commandline.md). For backwards compatibility this option is off by default. Strict mode automatically enables all OPC UA Pub Sub features, including metadata messages. To disable metadata messages use the `--dm=true` flag. To enable metadata messages when strict mode is not used (compatible to 2.8), use `--dm=false`. > It is highly recommended to always run OPC Publisher with strict adherence turned on. All versions of OPC Publisher also support a non-standard, simple JSON telemetry format (typically referred to as "Samples" format and which is the default setting). Samples mode is compatible with [Azure Time Series Insights](https://azure.microsoft.com/services/time-series-insights/): ``` json [ { "EndpointUrl": "opc.tcp://192.168.178.3:49320/", "NodeId": "ns=2;s=Pump\\234754a-c63-b9601", "MonitoredItem": { "ApplicationUri": "urn:myfirstOPCServer" }, "Value": { "Value": 973, "SourceTimestamp": "2020-11-30T07:21:31.2604024Z", "StatusCode": 0, "Status": "Good" } }, { "EndpointUrl": "opc.tcp://192.168.178.4:49320/", "NodeId": "ns=2;s=Boiler\\234754a-c63-b9601", "MonitoredItem": { "ApplicationUri": "urn:mySecondOPCServer" }, "Value": { "Value": 974, "SourceTimestamp": "2020-11-30T07:21:32.2625062Z", "StatusCode": 0, "Status": "Good" } } ] ``` **Warning: The `Samples` format changed over time and is now deprecated** More detailed information about the supported message formats can be found [here](./messageformats.md) ## Programming against OPC Publisher using the OPC Publisher API OPC Publisher supports remote configuration through Azure IoT Hub [direct methods](./directmethods.md). In addition to the configuration API, OPC Publisher 2.9 also supports additional [APIs](./api.md) and [a number of different transports](./transports.md) that can be used to receive messages or invoke these API services. The transports can be configured using the [command line arguments](./commandline.md). - The API can be invoked through Azure [**IoT Hub direct methods**](#calling-the-direct-methods-api) from the cloud or from another IoT Edge module running alongside of OPC Publisher or inside a higher layer of a Purdue network setup. The method name is the operation name and request payload as documented in the API documentation. - The same API is exposed as [REST API](#calling-the-api-over-http) via the Http**HTTP Server** [built into OPC Publisher](./transports.md#built-in-http-api-server) (Preview). The API supports browse and historian access streaming, which the other transports do not provide. All calls must be authenticated through an API Key which must be provided as a Api Key token in the Authorization header (`ApiKey `). The API key is generated at start up and [can be read from the OPC Publisher module's module twin](#using-iot-edge-simulation-environment) (`__apikey__` property). - The API can also be invoked through **MQTT v5 RPC calls** (Preview). The API is mounted on top of the method template (configured using the `--mtt` [command line argument](./commandline.md)). The method name follows the topic. The caller provides the topic that receives the response in the topic specified in the corresponding MQTTv5 PUBLISH packet property. ### Using IoT Edge Simulation environment A handy way to program against OPC Publisher is inside the IoT Edge Development simulator. You can also use [Azure IoT Edge for Visual Studio Code](https://github.com/microsoft/vscode-azure-iot-edge) to program against OPC Publisher which provides an integrated development experience. > NOTE: [IoTEdgeHubDev](https://github.com/Azure/iotedgehubdev) is a development tool and in maintenance mode. If you encounter issues please file an issue and we will aim to address. Follow the instructions to install [IoTEdgeHubDev](https://github.com/Azure/iotedgehubdev). Make sure the docker daemon is started and accessible. You can now use the official OPC Publisher images on Microsoft container registry (mcr.microsoft.com/iotedge/opc-publisher:latest) or build a local version from the root of this repository as follows: ```bash dotnet publish src/Azure.IIoT.OpcUa.Publisher.Module/src/Azure.IIoT.OpcUa.Publisher.Module.csproj --os linux --arch x64 /p:ContainerImageTags=debug ``` Doing this will produce the container image `iotedge/opc-publisher:debug`. The [sample deployment manifest](deployment.json?raw=1) already points to the local container image. If you would like to use a different container image (e.g., the official one on MCR or from your private Azure Container Registry) update the image name in the manifest accordingly. To start the IoT Edge simulation run ```bash iotedgehubdev start -d docs/opc-publisher/deployment.json -v ``` > If you omit the `-v` command line argument the simulation will run in the background. You can now interact with OPC Publisher the same way as if it was running on a production IoT Edge. #### Calling the Direct Methods API IoT Edge Hub Development simulator can be used to deploy other modules side by side with OPC Publisher which can then invoke OPC Publisher [direct methods](https://learn.microsoft.com/azure/iot-hub/iot-hub-devguide-direct-methods). The API Payload is described in the [API](./api.md) and [configuration](./directmethods.md) documentation. While the API documentation is based on the OPC Publisher [openapi.json](openapi.json?raw=1) (Swagger), the direct method API uses the same [definitions](./definitions.md) for requests and responses. The operation name in the the Open API JSON which is also the heading of the individual entry in the API documentation (e.g., [AddOrUpdateEndpoint](./api.md#addorupdateendpoints) or [GetConfiguredEndpoints](./api.md#getconfiguredendpoints)) is the direct method name that must be placed into the IoT Edge / IoT Hub method call. You can try this using the `az iot hub invoke-module-method` command, e.g., ```bash az iot hub invoke-module-method -m publisher -n -d --method-name GetConfiguredEndpoints { "payload": { "endpoints": [] }, "status": 200 } ``` Direct methods have a payload size limit of 256KB. This means large requests or responses will fail if they are larger than the max payload allowed. It is therefore recommended to use MQTT or HTTP to access the API (locally) or use the SDK project inside this repository which supports transmitting and receiving payloads that are larger than the 256 KB payload limitation of Azure IoT Hub through compression and request/response chunking. #### Calling the API over HTTP > This feature is in preview You can now send HTTP requests to the publisher module http server at `https://localhost` (use port 8081 when not running as container). The unsecure endpoint is mounted at `http://localhost` for testing purposes (use port 8080 when not running as container). E.g. to get the swagger definition run: ```bash curl http://localhost/swagger/v2/openapi.json ``` When you run inside IoT Edge and want to expose the REST API endpoint on the host network so other applications on the network or on the host sysytem can access it, you must configure port bindings. For example - as can be seen in the sample [deployment manifest](./deployment.json): ```bash ... "HostConfig\":{\"PortBindings\": ... \"443/tcp\":[{\"HostPort\":\"8081\"}]}, ... ``` WIth this setting the API can be securely accessed at `https://localhost:8081` (replace localhost with the host name of the IoT Edge server). > NOTE: Do not expose port 80 on the host side as traffic over port 80 is unencrypted and insecure. It should only be used for testing and during development. To call the API you must authenticate to the [built in HTTP server](./transports.md#built-in-http-api-server) endpoint using an API Key. You can obtain the API key needed to authenticate from the publisher module twin. e.g., using the [AZ CLI](https://learn.microsoft.com/azure/iot-edge/how-to-monitor-module-twins?view=iotedge-1.4#monitor-module-twins-in-azure-cli) tool you can run ```bash az iot hub module-twin show -m publisher -n -d ``` If the OPC Publisher has successfully started then this will produce e.g., output as follows: ```json ... "$version": 3, "__apikey__": "", "__certificate__": "...", "__type__": "OpcPublisher", "__version__": "2.9.11" ... ``` You can now send HTTP requests to the publisher module http server at `https://localhost:8081` with the Authorization header `ApiKey `. E.g., to call this API with the previously retrieved API Key run ```bash curl -H "Authorization: ApiKey " https://localhost:8081/v2/configuration {"endpoints":[]} ``` > The API key is a secret just like passwords or decryption keys. Therefore always use HTTPS in production scenarios since using HTTP endpoint makes the secret visible to everyone and verify the server certificate against the "certificate" value provided in the twin. It is also recommended to continuously update the API key (Rolling) which can be done by writing a new key to the module twin or deleting the entry so it is re-generated. ### JSON encoding The REST API uses OPC UA JSON reversible encoding as per standard defined in [OPC UA](../readme.md#what-is-opc-ua) specification 1.04, Part 6, with the exception that default scalar values and `null` values are not encoded except when inside of an array. A missing value implies `null` or the default of the scalar data type. All *primitive built-in* values (`integer`, `string`, `int32`, `double`, etc.) and *Arrays* of them can be passed as JSON encoded Variant objects (as per standard) or as JSON Token. The twin module attempts to coerce the JSON Token in the payload to the expected built-in type of the Variable or Input argument. The decoder will match JSON variable names case-**in**sensitively. This means you can write a JSON object property name as `"tyPeiD": ""`, `"typeid": ""`, or `"TYPEID": ""` and all are decoded into a OPC UA structure's `"TypeId"` member. #### Node Ids In addition to the standard string encoding using a namespace `Index` (e.g. `ns=4;i=3`) or the `Expanded` format (e.g. `nsu=http://opcfoundation.org/UA/;i=3523`). OPC Publisher also supports the use of (non-standards compliant) `Uri` encoded Node Ids and Qualified Names (see [RFC 3986](http://tools.ietf.org/html/rfc3986)). ```bash #= ``` Examples are: `http://opcfoundation.org/UA/#i=3523` or `http://opcfoundation.org/UA/#s=tag1`. While the API supports any input format for node ids and qualified names (e.g., such as in [browse paths](#browse-paths)), you can select the desired output namespace format through the [header in the request](./definitions.md#requestheadermodel) and its property `NamespaceFormat`. You can also set a default on the [command line](./commandline.md) using `--nf`. If the publisher is started in `--strict` the namespace format is `Expanded`, otherwise defaults to `Uri`. > The use of the `Uri` format is discouraged because it is not standards compliant. The use of the `Index` format is also discouraged as it does not allow configuring stable identifiers (the namespace table can change between sessions or when the server is updated, in which case the index might then point to a different namespace). Use the `Expanded` format when possible. [browse paths](#browse-paths) Non Uri namespace Uri's must always be encoded using the `Index` or `Expanded` syntax (e.g. `nsu=taglist;i=3523`). Expanded Node Identifiers should be encoded using the OPC UA `Index` or `Expanded` syntax (e.g. `svu=opc.tcp://test;nsu=http://opcfoundation.org/UA/;i=3523`). However, the `Uri` format is also possible. In this case the server URI is appended as ```bash &srv=#= ``` #### Browse paths A browse path is a set of browse names that the server should follow inside the address space to get to a node. The browse name is an attribute of a node and is a qualified name. Qualified Names are encoded as a single string the same way as Node Ids, where the name is the ID element of the URI. Examples of qualified names in `Expanded` format is `nsu=http://microsoft.com/;Browse%20Name`, in `Index` format `3:Browse%20Name` and in `Uri` format `http://opcfoundation.org/UA/#Browse%20Name`. The browse path starts by default from the root node. If this is not desired, the starting node id must also be provided. The browse path format follows the documented browse path format in the OPC UA reference normative section. In all API and configuration the browse path is a JSON array containing the individual relative path element. The simplest example when using a browse path with browse names in the default namespace is: ```json [ "Objects", "Server", "ServerStatus", "CurrentTime" ] ``` In this example, the default `References` reference type is assumed linking the objects named by the browse path. The paths are forward traversed. The relative path element by default must be a browse name formatted using one of the namespace formatting options (`Index`, `Expanded`, or `Uri`), e.g., the following are equivalent: ```json [ // Expanded "Objects", "nsu=http://opcfoundation.org/UA/Plc/Applications;OpcPlc", "nsu=http://opcfoundation.org/UA/Plc/Applications;Telemetry", "nsu=http://opcfoundation.org/UA/Plc/Applications;Fast", "nsu=http://opcfoundation.org/UA/Plc/Applications;FastUIntScalar1" ], [ // Index "Objects", "17:OpcPlc", "17:Telemetry", "17:Fast", "17:FastUIntScalar1" ], [ // Uri "Objects", "http://opcfoundation.org/UA/Plc/Applications#OpcPlc", "http://opcfoundation.org/UA/Plc/Applications#Telemetry", "http://opcfoundation.org/UA/Plc/Applications#Fast", "http://opcfoundation.org/UA/Plc/Applications#FastUIntScalar1" ] ``` The first option is the preferred and recommended model because it is the official formatting defined in the specification, and it is stable compared to the second option of using a namespace index, which can point to a different namespace in the namespace table than intended. In addition each path element can be prefixed to narrow the reference or describe whether the path follow an inverse reference: - `.`: Short for `Aggregates` reference to select a property of a variable. - `/`: Short for a `HierarchicalReference` reference. - `#`: Whether to use the explicitly defined reference and do not consider subtypes of the reference type linking the elements. - `!`: Whether the inverse of the reference should be used - `<{ReferenceTypeId}>`: An explicit reference type to use, the well known reference types can be specified by name, otherwise use the node id of the reference type. If the prefix is a valid character of the browse name it can be escaped by prefixing it with a `&` ampersand character, e.g. `&<, &>, &/, &., &:, &&`. > Note that in a filter query string the browse path is not specified as a JSON array but as a concatenation of the elements. In this case a prefix must be used. In addition the target can be then escaped by specifying it with brackets `[` and `]`. However, this only applies to the [query parser API](./api.md#compilequery). ### Discovering OPC UA servers with OPC Publisher > This feature is in preview Starting from version 2.9 OPC Publisher provides discovery services (formerly [OPC Discovery](https://github.com/Azure/Industrial-IoT/tree/release/2.8.6)) to find assets (OPC UA servers) on the local shop floor network where the IoT Edge device is deployed. This can be programmatically controlled using API calls documented [here](./api.md). The optional [Web service](../web-api/readme.md) subscribes to the events and registers the discovered assets in Azure IoT Hub as device identities. Example use cases: - An industrial solution wants to detect assets which are unknown by its asset management system. - A customer wants to access an asset without looking up the connectivity information in his asset management database or Excel spreadsheet printout from 10 years ago! - A customer wants to onboard an asset which was recently added to a production line without causing additional network load. Discovery supports two modes of operation: - Active Scan mode: The local network is actively scanned by the Discovery module. - Targeted discovery mode: A list of asset addresses can be specified to be checked. Discovery is based on native OPC UA server functionality as specified in the OPC UA specification, which allows discovery of endpoint information including security profile information without establishing an OPC UA authenticated and encrypted OPC UA session. The results of the discovery process are sent to cloud via the IoT Edge Hub’s and IoT Hub’s telemetry path. The optional cloud web service processes the results and onboard the discovered entities as IoT Hub identities. The Discovery can be configured via the OPC Registry REST API and allows a fine-grained configuration of the discovery process for recurring as well as one-time scans. #### Discovery Configuration The Discovery capability of OPC Publisher can be configured to do active network and port scanning. The following parameters can be configured for active scanning: - address ranges (needed when hosted in a Docker context where the host interfaces are not visible) - port ranges (to narrow or widen scanning to a list of known ports) - number of workers and time between scans (Advanced) > Active scanning should be used with care since it causes load on the local network and might be identified by network security software as a threat. For a targeted discovery, the configuration requires a specific list of discovery URLs. Please note that targeted discovery disables the use of address and port ranges as only the specific list of discovery URLs are checked. #### One-time discovery One-time discovery is supported by the OPC Publisher module and can be initiated through a API call over IoT Hub direct methods or MQTT/HTTPS (Preview). The API is documented [here](./api.md). A discovery configuration is part of the API request payload. All one-time discovery requests are serialized in the Discovery module at the edge, i.e. will be performed one by one. Using the targeted discovery mode, servers can be registered using a well-known discovery URL without active scanning. #### Discovery Progress The discovery progress as well as current request queue size is reported via the telemetry path and available in the cloud for applications by the Registry services REST interface. ### OPC UA command and control (OPC Twin) > This feature is in preview The control services (formerly [OPC Twin services](https://github.com/Azure/Industrial-IoT/tree/release/2.8.6)) are provided using IoT Hub device method API as well as Web API and MQTT based request response API (Preview). Example use cases: - A customer wants to gather the configuration of an asset by reading configuration parameters of the asset. - A customer wants to browse an OPC UA server’s information model/address space for telemetry selection. - An industrial solution wants to react on a condition detected in an asset by changing a configuration parameter in the asset. The API enables you to write applications that invoke OPC UA server functionality on OPC server endpoints. The Payload is transcoded from JSON to OPC UA binary and passed on through the OPC UA stack to the OPC UA server. The response is re-encoded to JSON and passed back to the cloud service. This includes [Variant](#json-encoding) encoding and decoding in a consistent JSON format. Payloads that are larger than the Azure IoT Hub supported Device Method payload size are chunked, compressed, sent, then decompressed and reassembled for both request and response. This allows fast and large value writes and reads, as well as returning large browse results. A single session is opened on demand per endpoint so the OPC UA server is not overburdened with 100’s of simultaneous requests. The client linger option can be configured using the [command line](./commandline.md) option `--cl` so that clients stay open for a while after the service call completes avoiding re-establishment of the session. ## OPC UA Certificates OPC Publisher connects to OPC UA servers built into machines or industrial systems via OPC UA client/server. There is an OPC UA client built into the OPC Publisher Edge module. OPC UA Client/server uses an OPC UA Secure Channel to secure this connection. The OPC UA Secure Channel in turn uses X.509 certificates to establish *trust* between the client and the server. This is done through *mutual* authentication, i.e. the certificates must be "accepted" (or trusted) by both the client and the server. The pki path of OPC Publisher can be configured using the `PkiRootPath` or `--pki` [command line argument](./commandline.md) (the default folder is `/pki`). It is usually a good idea to specify a volume that is mounted to the host operating system and therefore persists during restarts of the OPC Publisher container. The individual stores are found under the PKI root path. These by default follow the layout guidance of the [OPC UA standard](https://reference.opcfoundation.org/GDS/v105/docs/F.1). By default, the OPC Publisher module will create a self signed x509 *Application certificate* with a 1 year expiration in the `own` store. This default, self signed cert includes the Subject `Microsoft.Azure.IIoT`. This certificate is fine as a demonstration, but for production systems customers may want to [use their own certificate](#pki-management). The biggest hurdle most OT admins need to overcome when deploying OPC Publisher is to configure the OPC UA server (equipment) to accept the OPC Publisher X.509 certificate (the other side of mutual trust). There is usually a configuration tool that comes with the built-in OPC UA server where certificates can be trusted. For example for KepServerEx, configure the trusted Client certificate as discussed [here]( https://www.kepware.com/getattachment/ccefc1a5-9b13-41e6-99d9-2b00cc85373e/opc-ua-client-server-easy-guide.pdf). To use the [OPC PLC Server Simulator](https://docs.microsoft.com/samples/azure-samples/iot-edge-opc-plc) with mutual trust you can use the `–-aa` switch on the simulator to accept OPC Publisher's certificate or copy the server certificate from the simulator to the pki `trusted` folder of OPC Publisher. ### PKI management The `certificate stores` in OPC Publisher live in the file system. They can be managed remotely using the `Certificates` [Api](./api.md#certificate) (Preview). This API enables an application or user to [list all certificates](./api.md#listcertificates) and [add](./api.md#addcertificate) and [remove certificates](./api.md#removecertificate). There is also an API to move rejected certificates from the rejected store to the trusted store and list, add, remove [certificate revocation lists](./api.md#listcertificaterevocationlists). By default, the OPC Publisher module will create a self signed x509 certificate with a 1 year expiration which is fine for demonstration. For real applications, customers may want to use their own certificate. You can use `openssl` to create your own self-signed certificate, e.g., with a 2 year expiration and a custom subject. In the following example script, replace `` and `` with the application name and subject name you desire: ```bash # Create cert.pem and key.pem openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -sha256 -days 730 -nodes \ -subj "/CN=/O=/DC=localhost" \ -addext "subjectAltName=URI:urn:localhost::microsoft:,DNS:" \ -addext "keyUsage=nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment, keyCertSign" \ -addext "extendedKeyUsage=clientAuth" # Transform cert.pem to cert.der openssl x509 -outform der -in cert.pem -out cert.der # Transform key.pem and cert.pem to cert.pfx openssl pkcs12 -export -out cert.pfx -inkey key.pem -in cert.pem # Clean up keys rm -f cert.pem rm -f key.pem ``` The resulting .pfx file can now be copied to the `own/private` folder under pki root (or to an alternative application certificate folder configured) and the .der file to the `own/certs` and `trusted/certs` folders. Alternatively you can also push the pfx file content to OPC Publisher's PKI through the [OPC Publisher API](./api.md#addcertificate). As part of above script you will be prompted to enter and verify an export password to protect the PFX file. If you are copying the PFX file into the `own` folder, then by default the password should be blank (hit enter), unless you specify the password using the `--apw=` [command line options](./commandline.md). In this case the password should be the same password. OPC Publisher can retrieve the application Uri, application name, subject Name and Host name (DNS Domain name) from the first certificate found in the `own/certs` folder under the PKI root folder if you start it with the `--cfa` [command line argument](./commandline.md). If you need to select a specific certificate in the `own/certs` store (e.g., because you configured more than one) or would like to have OPC Publisher generate a self-signed certificate with different content than the default, a application name can be provided using the `--an` command line argument (The default is `Microsoft.Azure.IIoT`). If you desire a different subject name than the default, the OPC Publisher must be started with `--sn` command line providing the desired subject name (for example `CN=,O=mycompany`). If you desire a different application Uri than the default, it can be specified using the `--au` command line option. In this case, do not set the `--cfa` command line argument or it will override these settings from the first certificate found. > TIP: Using the `--cfa` command line option simplifies setting up OPC Publisher and also enables easier version to version upgrade without chances that a new application certificate is generated after the update because the desired certificate is not found. If you intend to provide the certificate using the [OPC Publisher API](./api.md#addcertificate) you must provide any password you choose as part of the API call so that the API server in OPC Publisher is able to export the key from the PFX blob. If the OPC Publisher was started using the `--tm` command line option any certificate added to the `own` store will also be added to the `trusted` store. ### Auto Accept server certificates To simplify the getting started experience, the OPC Publisher Edge module has a setting to automatically trust all *untrusted* server certificates presented to OPC Publisher (`--aa`). This does not mean OPC Publisher will accept any certificate presented. If Certificates are malformed or if certificates chains cannot be validated the certificate is considered broken (and not untrusted) and will be rejected as per OPC Foundation Security guidelines. In particular if a server does not provide a full chain it should be configured to do so, or the entire chain must be pre-provisioned in the OPC Publishers `pki` folder structure. > WARNING: Automatically trusting any server certificate provided by an endpoint exposes OPC Publisher to man in the middle attacks. Do not use OPC Publisher with auto accept mode in production. ## OPC UA stack The OPC UA .NET Standard reference stack of the OPC Foundation (contributed by Microsoft) is used for OPC UA secure communications by OPC Publisher. Modules and services consume the re-distributable NuGet package licensed by the OPC Foundation. The open source for the reference implementation is provided by the OPC Foundation on GitHub in [this public repository](https://github.com/OPCFoundation/UA-.NETStandard). ## Performance and Memory Tuning OPC Publisher In production setups, network performance requirements (throughput and latency) and memory resources must be considered. OPC Publisher exposes the following command line parameters to help meet these requirements: - Message queue capacity (`om` since version 2.7) - IoT Hub send interval (`si`) The `om` parameter controls the upper limit of the capacity of the internal message queue. This queue buffers all messages before they're sent to IoT Hub. The default size of the queue is 4000 IoT Hub messages (for example: if the setting for the IoT Hub message size is 256 KB, the size of the queue will be up to 1 GB). If OPC Publisher isn't able to send messages to IoT Hub fast enough, the number of items in this queue increases. In this case, one or both of the following can be done to mitigate: - Decrease the IoT Hub send interval (`si`) - Use latest OPC Publisher in standalone mode - Use PubSub format (`--mm=PubSub`). - Choose the smallest message providing the information you need. E.g., instead of `--mm=PubSub` use `--mm=DataSetMessages`, or event `--mm=RawDataSets`. You can find sample messages [here](./messageformats.md). - If you are able to decompress messages back to json at the receiver side, use `--me=JsonGzip` or `--me=JsonReversibleGzip` encoding. - If you are able to decode binary network messages at the receiver side, choose `--me=Uadp` instead of `--me=Json`, `--me=JsonReversible` or a compressed form of Json - When Samples format (`--mm=Samples`) is required - Don't use FullFeaturedMessage (`--mm=FullSamples` or `--mm=Samples` with `--fm=false`). You can find a sample of full featured telemetry message [here](messageformats.md). - Use batching (`--bs=600`) in combination with batch publishing interval (`--si=20`). - Increase Monitored Items Queue capacity (e.g., `--mq=10`) - Don't use "fetch display name" (`--fd=false`) - General recommendations - Try to use less different publishing intervals, rather aim to use the same for all nodes. - Experiment with the command line and configuration. E.g., depending on the IoT Hub connectivity it seems to be better to have fewer messages with more OPC UA value changes in it (check OPC Publisher logs) but it could also be better to have more messages with fewer OPC UA value changes, this is specific to every application. If the queue keeps growing even though the parameters have been adjusted, eventually the maximum queue capacity will be reached and messages will be lost. This is because all parameters have physical limits and the Internet connection between OPC Publisher and IoT Hub isn't fast enough for the number of messages that must be sent in a given scenario. In that case, only setting up several, parallel OPC Publishers will help. The `om` parameter also has the biggest impact on the memory consumption by OPC Publisher. It must be noted that IoT Hub also has limits in terms of how many messages it will accept, that is, there are quotas for a given IoT Hub SKU defined [here](https://docs.microsoft.com/azure/iot-hub/iot-hub-devguide-quotas-throttling). If this quota is exceeded, OPC Publisher will generate an error trying to send the message to IoT Hub and the message will be lost. The `si` or `bi` parameter forces OPC Publisher to send messages to IoT Hub at the specified interval. A message is sent either when the maximum IoT Hub message size of 256 KB of data is available (triggering the send interval to reset) or when the specified interval time has passed. The `bs` parameter enables batching of incoming OPC UA data change messages. When used without batching interval (`bi`), a message is sent to IoT Hub only once OPC Publisher receives specified number of incoming messages. That is why it is recommended to use batching together with batching interval to achieve consistent message delivery cadence to IoT Hub. The `ms` parameter enables batching of messages sent to IoT Hub. In most network setups, the latency of sending a single message to IoT Hub is high, compared to the time it takes to transmit the payload. This is due to Quality of Service (QoS) requirements, since messages are acknowledged only once they've been processed by IoT Hub). Therefore, if a delay for the data to arrive at IoT Hub is acceptable, OPC Publisher should be configured to use the maximal message size of 256 KB by setting the `ms` parameter to 0. It's also the most cost-effective way to use OPC Publisher. The metric `monitored item notifications enqueue failure` in OPC Publisher version 2.5 and below and `messages lost` in OPC Publisher version 2.7 shows how many messages were lost. When both `si` and `ms` parameters are set to 0, OPC Publisher sends a message to IoT Hub as soon as data is available. This results in an average IoT Hub message size of just over 200 bytes. However, the advantage of this configuration is that OPC Publisher sends the data from the connected asset without delay. The number of lost messages will be high for use cases where a large amount of data must be published and hence this isn't recommended for these scenarios. ================================================ FILE: docs/opc-publisher/security.md ================================================ ## Security ### oauth2 Implicit oauth2 token flow. *Type* : oauth2 *Flow* : implicit ================================================ FILE: docs/opc-publisher/transports.md ================================================ # OPC Publisher Transports [Home](./readme.md) OPC Publisher translates these northbound transport protocols to and from OPC UA with different levels of fidelity. > Except for the fully supported Azure IoT transport, other northbound transports here are currently provided in preview or experimental form and are by default disabled. ## Table Of Contents - [Azure IoT Hub and Azure IoT Edge](#azure-iot-hub-and-azure-iot-edge) - [MQTT](#mqtt) - [Azure EventHub](#azure-eventhub) - [Dapr](#dapr) - [HTTP](#http) - [Built-in HTTP API server](#built-in-http-api-server) - [Publishing to a Webhook](#publishing-to-a-webhook) - [Other transports](#other-transports) - [File System](#file-system) ## Azure IoT Hub and Azure IoT Edge When deployed into Azure IoT Edge OPC Publisher is automatically configured and connects securely to the Edge Hub component. This is the officially supported configuration of OPC Publisher. In addition to the automatic configuration during deployment in IoT Edge it is also possible to start the OPC Publisher with an Azure IoT Hub connection using the [command line](./commandline.md) argument `--ec` or by setting the `EdgeHubConnectionString` environment variable to the Azure IoT connection string. > Providing Azure IoT connection strings is supported for debugging only. Azure IoT connection strings contain access keys. You must ensure they are properly secured in your development environment. The following table shows the supported features of the Azure IoT Edge and IoT Hub transport implementations inside OPC Publisher: | Feature | Supported | Notes | | ------------------------ | ---------- | ----- | | State store | Yes | Using Device Twin desired and reported properties | | Configuration API | Yes | | | Twin and Discovery | Yes | | | Streaming (Browse/HDA) | No | | | Payload size limits | 256 kb (*) | | | Telemetry publishing | Yes | | | Discovery Events | Yes | | | Operational Events | Yes | | | Message size limits | 256 kb | | IoT Edge is used as the default transport unless the Azure IoT related configuration cannot be found at startup time. By default all discovery and runtime events are sent through IoT Edge. Using the `-t` command line argument a different transport can be chosen to publish network messages with. The writer group (network message) transport can also be individually overridden for a writer group using the OPC Publisher [configuration schema's](./readme.md#configuration-schema) `WriterGroupTransport` attribute. Direct methods can be used to interact with the OPC Publisher configuration, discovery, and general (fka. OPC Twin) [API](./api.md). Direct method calls have a payload limit of 256 KB. High frequency interaction such as browsing through direct methods is naturally slow. ## MQTT > This transport is in preview OPC Publisher 2.9 can be connected to an MQTT broker using MQTT 3.11 and MQTT 5 protocols. The connection information is provided in the form of a connection string through the [command line](./commandline.md) argument `--mqc`. > The MQTT broker connection string typically contains the user name and password to access the MQTT broker. Ensure that you properly secure this secret in your production environment. MQTT v5 supports RPC which allows a client to call the OPC Publisher [API](./api.md) over MQTT. Like in the case of [IoT Edge](#azure-iot-hub-and-azure-iot-edge), streaming HDA and browse results are not supported. OPC Publisher supports rich configuration of topic templates that are used when publishing data to MQTT broker, or to specify the root of the RPC server endpoint on which API requests are received. For more information how to configure MQTT topic trees see the [command line](./commandline.md) documentation for the `--rtt`, `--mtt`, `--ett`, `--ttt` and `--mdt` arguments. OPC Publisher will subscribe to the configured RPC server topic and handle method calls. The sub topic name is the name of the method. The response topic is specified as part of the MQTTv5 message header. Upon handling the method call the response payload will be published to the response topic. The request and response payload as well as the method name are defined in the API documentation. The following table shows the supported features of the MQTT transport implementation inside OPC Publisher: | Feature | Supported | Notes | | ------------------------ | ---------- | ----- | | State store | No | | | Configuration API | Yes | | | Twin and Discovery | Yes | | | Streaming (Browse/HDA) | No | | | Payload size limits | 512 MB | Actual limits depend on MQTT broker and can be configured using the connection string. | | Telemetry publishing | Yes | | | Discovery Events | Yes | Only if IoT Hub transport was not configured | | Operational Events | Yes | Only if IoT Hub transport was not configured | | Message size limits | 512 MB | Actual limits depend on MQTT broker and can be configured using the connection string. | To configure MQTT as the default transport for telemetry publishing specify the `-t=Mqtt` command line argument. This default choice can be individually overridden for a writer group in the OPC Publisher [configuration](./readme.md#configuration-schema) using the `WriterGroupTransport` attribute. The message schema can optionally be published to a schema topic, a schema topic template can be configured using the `--stt` [command line options](./commandline.md). This feature is currently experimental. ## Azure EventHub > This transport is in preview OPC Publisher can be configured to publish to [Azure EventHubs](https://dapr.io/). The event hub connectivity information can be configured in OPC Publisher using a connection string using the `--eh, --eventhubnamespaceconnectionstring` [command line options](./commandline.md). The connection string can be obtained from the Azure portal. The following table shows the supported features of the Azure EventHub transport implementation inside OPC Publisher: | Feature | Supported | Notes | | ------------------------ | ---------- | ----- | | State store | No | | | Configuration API | No | | | Twin and Discovery | No | | | Streaming (Browse/HDA) | No | | | Payload size limits | No | | | Telemetry publishing | Yes | | | Discovery Events | Yes | | | Operational Events | Yes | | | Message size limits | Yes | | In addition, OPC Publisher can publish message schemas to the Azure schema registry (Experimental). The schema group can be selected using the `--sg, --schemagroup` [command line options](./commandline.md). Publishing to the schema registry requires OPC Publisher to authenticate using an Azure identity e.g., a managed service identity, user or service principal. ## Dapr > This transport is experimental OPC Publisher can be configured to use [Dapr](https://dapr.io/) to publish to a supported [Dapr Pub Sub component](https://docs.dapr.io/reference/components-reference/supported-pubsub/) via a side car. To get started with Dapr follow the documentation on the [Dapr web site](https://docs.dapr.io/getting-started/). The following table shows the supported features of the Dapr transport implementation inside OPC Publisher: | Feature | Supported | Notes | | ------------------------ | ---------- | ----- | | State store | Yes | Only if IoT Hub transport was not configured | | Configuration API | Yes | Via [Dapr Service invoke](https://docs.dapr.io/developing-applications/building-blocks/service-invocation/howto-invoke-discover-services/) of the [REST API](#http) | | Twin and Discovery | Yes | Via [Dapr Service invoke](https://docs.dapr.io/developing-applications/building-blocks/service-invocation/howto-invoke-discover-services/) of the [REST API](#http) | | Streaming (Browse/HDA) | Yes | Via [Dapr Service invoke](https://docs.dapr.io/developing-applications/building-blocks/service-invocation/howto-invoke-discover-services/) of the [REST API](#http) | | Payload size limits | No | | | Telemetry publishing | Yes | | | Discovery Events | Yes | Only if IoT Hub and MQTT transport were not configured | | Operational Events | Yes | Only if IoT Hub and MQTT transport were not configured | | Message size limits | No (*) | Actual limits depend on the chosen Pub Sub component. Limits can be configured using the connection string | Whether the Dapr transport is enabled is determined by whether the Dapr Pub Sub component and Api Token are configured. The Pub sub component name and Api token can be provided through the `-d` connection string using the [command line](./commandline.md). The Api Token is automatically provided by the Dapr runtime through the `DAPR_API_TOKEN` environment variable. Whether the component was configured in your Dapr environment is not validated. The Dapr transport will add all user properties into the meta data of the published event. For retained messages the `retain` metadata variable is set to `true`. To configure Dapr as the default transport for telemetry publishing specify the `-t=Dapr` command line argument. This default choice can be individually overridden for a writer group in the OPC Publisher [configuration](./readme.md#configuration-schema) using the `WriterGroupTransport` attribute. ## HTTP The HTTP transports is split into two parts: The [built in HTTP server](#built-in-http-api-server) and the [Http event publisher](#publishing-to-a-webhook) that can be configured to publish to another HTTP server (Web Hook). The following features are supported: | Feature | Supported | Notes | | ------------------------ | ---------- | ----- | | State store | No | | | Configuration API | Yes | | | Twin and Discovery | Yes | | | Streaming (Browse/HDA) | Yes | | | Payload size limits | No | | | Telemetry publishing | Yes | | | Discovery Events | Yes | Only if IoT Hub, MQTT, and Dapr transports were not configured | | Operational Events | Yes | Only if IoT Hub, MQTT, and Dapr transports were not configured | | Message size limits | No | | ### Built-in HTTP API server > This transport is in preview The built in HTTP server eposes the OPC Publisher [API](./api.md). The API is secured by an API Key. The API key is generated at startup if it is not found inside the state store. The default state store is the IoT Hub device twin. Therefore the API key can be read from the device registry in IoT Hub. The API key must be provided in every request in the HTTP `Authorization` header using the `ApiKey ` scheme. The HTTP server is exposed at port 80 (no encryption) and 443 (with encryption). The SSL channel is secured using a IoT Edge generated server certificate, just like Edge Hub's endpoints. The API can be further secured using a [Dapr](#dapr) side car providing mtls based security on top of the generic API surface. The built in HTTP server can be disabled using the `--dh` [command line](./commandline.md) argument. > Never expose the OPC Publisher HTTP port outside of the Edge Gateway's docker network. The HTTP server should only be accessible by other docker containers. ### Publishing to a Webhook > This transport is experimental The other part of the HTTP support in OPC Publisher is the ability to publish network messages to a HTTP server (Web Hook). The web server information is provided on the [command line](./commandline.md) using the `-r` argument in the form of a connection string. > The HTTP Connection string can contain an API Key. Ensure that you properly secure the connection string. ## Other transports ### File System > This transport is experimental Sometimes it is important for troubleshooting and debugging to dump the network messages to files. The File system transport can be used to reflect the network messages in their topic structure inside the file system. The file system Transport is intended for debugging only and not for production scenarios. You can configure a root folder on the bind mount of OPC Publisher using the `-o` [command line](./commandline.md) argument and inspect the results using a file viewer of choice. ================================================ FILE: docs/opc-publisher/troubleshooting.md ================================================ # Troubleshooting OPC Publisher [Home](./readme.md) In this document you find information about ## Table Of Contents - [Debugging Telemetry data issues](#debugging-telemetry-data-issues) - [Check OPC UA server](#check-opc-ua-server) - [Check IoT Edge](#check-iot-edge) - [Check OPC Publisher](#check-opc-publisher) - [BadNodeIdUnknown](#badnodeidunknown) - [Check EdgeHub](#check-edgehub) - [Check data arriving in IoT Hub](#check-data-arriving-in-iot-hub) - [IoT Hub Metrics](#iot-hub-metrics) - [Use Azure IoT Explorer](#use-azure-iot-explorer) - [Restart the module](#restart-the-module) - [Analyzing network capture files](#analyzing-network-capture-files) - [Netcap](#netcap) - [Session and Subscription diagnostics](#session-and-subscription-diagnostics) - [Limits and contributing factors](#limits-and-contributing-factors) - [Debugging Discovery](#debugging-discovery) ## Debugging Telemetry data issues Follow the data from the source and check where it stops: 1. Check the [OPC UA server](#check-opc-ua-server) 1. Check [IoT Edge](#check-iot-edge) 1. Check [OPC Publisher](#check-opc-publisher) 1. Check [EdgeHub](#check-edgehub) 1. Check data arriving in [IoT Hub](#check-data-arriving-in-iot-hub) 1. Finally check your application that is consuming from IoT Hub is running and operating correctly. ### Check OPC UA server Microsoft OPC Publisher connects to OPC UA servers built into machines or industrial systems via OPC UA client/server. There is an OPC UA client built into the OPC Publisher Edge module. OPC UA Client/server uses an OPC UA Secure Channel to secure this connection. The OPC UA Secure Channel in turn uses X.509 certificates to establish trust between the client and the server. This is done through mutual authentication, i.e. the certificates must be "accepted" (or trusted) by both the client and the server. To simplify setup, the OPC Publisher Edge module has a setting enabled to automatically accept all server certificates ("--aa" in the case of the OPC Publisher, see example below). However, the biggest hurdle most OT admins need to overcome when deploying OPC Publisher is to accept the module's X.509 certificate in the OPC UA server the platform tries to connect to. There is usually a configuration tool that comes with the built-in OPC UA server where certificates can be trusted. Here is a screenshot of this dialog from PTC’s KepServerEx industrial connectivity software configuration tool: ![OPC UA Configuration](./media/image26.png) In the dialog above, it can be seen that the certificate **Microsoft.Azure.IIoT** is trusted by Kepware `KepServerEx`. This is only done once and then the data can be exchanged between the OPC UA server (in this case `KepServerEx`) and OPC Publisher Edge module. The OPC UA certificate used by the OPC Publisher Edge module is a self-signed certificates generated when the modules start up when a certificate doesn’t exist. However, each time a Docker container starts up, all previous state of the container is removed. To avoid re-establishing trust by each OPC UA server on-premises after each restart the certificates can be persisted to the local filesystem of the host (where IoT Edge as well as the Docker containers `EdgeHub` and `EdgeAgent` and of course OPC Publisher module runs on). To do this, the filesystem directory within the container needs to be mapped to an existing filesystem directory on the host through a [bind mount](https://docs.docker.com/storage/bind-mounts). See [here](readme.md) for more information on how to accomplish this. Another feature of OPC UA that is often turned off by OT administrators is user authentication. User authentication is another authentication layer on top of the client/server authentication described above. Most OPC UA servers only support anonymous user authentication but some support user authentication based on username and password. If this is the case, a username and password must be supplied to the OPC Publisher’s API or set in the `publishednodes.json` file (properties `OpcAuthenticationUsername` and `OpcAuthenticationPassword`). ### Check IoT Edge To troubleshoot an IoT Edge device run the following commands in a terminal session on the IoT Edge device or over a remote SSH session: - `sudo iotedge check` to check the state of the installation. - `systemctl status iotedge` to view the status of the IoT Edge security manager. - `systemctl restart iotedge` to restart the IoT Edge Security Daemon. - `iotedge logs ` to check the logs. - `iotedge restart ` to restart OPC Publisher. - `iotedge restart edgeAgent && iotedge restart edgeHub` to restart the IoT Edge runtime containers. - `docker stats` to retrieve statistics from the docker runtime. For more detailed description on how to troubleshoot IoT Edge device, please refer to [here](https://docs.microsoft.com/azure/iot-edge/troubleshoot-common-errors) and [here](https://docs.microsoft.com/azure/iot-edge/troubleshoot). For a complete overview of all production deployment settings for IoT Edge, see [here](https://docs.microsoft.com/azure/iot-edge/production-checklist). ### Check OPC Publisher [Retrieve the logs](./observability.md) from publisher and examine. If you disabled console output of the logs and are not monitoring metrics, enable diagnostics output to the console using the `--di` [command line options](./commandline.md). Using the logs: - Observe data throughput and make sure that the data changes over time are as you are expecting. - Check whether all endpoints are connected. This can be seen during session establishment and in the periodic diagnostic logs. - When OPC Publisher cannot subscribe to a node in the OPC UA server address space the number of failing nodes are logged in the metrics. To understand what happened you need to look at the logs that are emitted during connect. - The diagnostic output and metrics include an indicator of how many publishing requests are in flight between publisher and the OPC UA server and how many of these were returned with errors which reflects the health of the session and subscriptions in the writer group. - Observe the keep alive notification count in the periodic diagnostics output. If it counts up periodically it shows that while the connection and subscription is active, the server is not providing any data to OPC Publisher. The keep alive is sent by the server after `(keep alive count) * (publishing interval of subscription)` time has past. - Check how many data points were logged as dropped or whether data is queued up in the internal pipeline of the publisher (buffering, encoder, sending). To log notifications received on a subscription to the log you can use the `--ln` switch. To increase the log level and see debug logs use the `--ll Debug` switch. To log informational an debug messages of the OPC UA stack to the log, use the `--sl` switch. To diagnose throughput issues see the [limits and monitoring](#limits-and-contributing-factors) section. #### BadNodeIdUnknown A typical error shown in the log is `BadNodeIdUnknown` which means the server could not resolve the node id to a node in its address space to subscribe to. Reasons why the node id specified in the configuration cannot be resolved inside the server during connect can be as follows: - The Node Id string in the configuration is incorrect, e.g., escaping of characters, extra spaces, missing semicolon. - Use an OPC UA Client like UA Expert or other to connect to the server with exactly the same security configuration (same user name, encryption settings, etc. that OPC Publisher uses, if you do not know, default to SecurityMode = none and anonymous user). Find the node by browsing and copy the node id exactly from the tool. - If it still does not work, please send the node id string. - The namespace id in the node id has changed from last time. Namespace ids are typically always static, but that is not guaranteed by the spec, quite the opposite. se the nsu= format of node id (expanded node id) to specify the namespace string instead of the id then. - The node is a dynamic node and comes and goes. You can configure OPC Publisher to re-evaluate periodically. - The node is only accessible to a particular user or user with role or on a particular endpoint with a special security profile. If we know what that is, then I can make suggestion what to do next, but might require upgrading to 2.9 ### Check EdgeHub To verify that a module or device has connectivity with the IoT Hub service, Microsoft provides a tool that is described here: If the `edgeHub` module fails to start, you may see a message like this in the logs: ```bash One or more errors occurred. (Docker API responded with status code=InternalServerError, response= {\\"message\\":\\"driver failed programming external connectivity on endpoint edgeHub (6a82e5e994bab5187939049684fb64efe07606d2bb8a4cc5655b2a9bad5f8c80): Error starting userland proxy: Bind for 0.0.0.0:443 failed: port is already allocated\\"}\\n) ``` Or ```powershell info: edgelet_docker::runtime -- Starting module edgeHub... warn: edgelet_utils::logging -- Could not start module edgeHub warn: edgelet_utils::logging -- caused by: failed to create endpoint edgeHub on network nat: hnsCall failed in Win32: The process cannot access the file because it is being used by another process. (0x20) ``` To find the root cause and resolution, please refer [here](https://docs.microsoft.com/azure/iot-edge/troubleshoot-common-errors). ### Check data arriving in IoT Hub #### IoT Hub Metrics To verify that the data is arriving in IoT Hub the Metrics of the IoT Hub can be checked. Particularly, select Metrics from the pane on the left side of your Azure IoT Hub resource page in the Azure Portal and select the **Telemetry messages sent** from the **IoT Hub standard metrics** namespace. This page gives an overview on the number of IoT Hub messages that have been sent from the OPC Publisher and from other custom edge modules. Please keep in mind that each of those messages have a size of up to 256KB. If buffering is enabled for the OPC Publisher module, then each IoT Hub message may contain several batches of data changes, where each batch contains a set of OPC value changes. ![IoT Hub](./media/image31.png) Another option to troubleshoot the issues in IoT Hub is by checking the "_Diagnose and solve problems"_ section of the IoT Hub resource page on the Azure Portal as shown below: ![IoT Hub](./media/image32.png) Moreover, enabling the diagnostic settings provides more data to troubleshoot and how to choose where to store that data is shown below: ![IoT Hub](./media/image33.png) ##### Use Azure IoT Explorer As a next step the Azure IoT Explorer can be used to validate that messages for a particular Publisher job are delivered to IoT Hub. To install Azure IoT Explorer, please follow the steps here: - [Install and use Azure IoT Explorer](https://docs.microsoft.com/azure/iot-pnp/howto-use-iot-explorer) To view the telemetry of OPC Publisher in Azure IoT Explorer, go to its Telemetry and start monitoring telemetry from that publisher module of choice. If you do not receive any messages for that device after a long period since starting monitoring, then there is a problem which causes telemetry messages not to be delivered to IoT Hub. ![Azure IoT Explorer](./media/image34.png) ## Restart the module To restart a module, the `iotedge` command line utility can be used as well. The command is: ​```bash iotedge restart ​​``` The name of the module can be retrieved via ​```bash iotedge list ​​``` You can also troubleshoot the OPC Publisher module remotely through the Azure Portal. Select the module inside the respective IoT Edge device in the IoT Edge blade and click on the Troubleshooting button to see logs and restart the module remotely. ## Analyzing network capture files The issue might be between the OPC Publisher OPC UA client and the OPC UA server you are using. A network capture provides the definitive answer as to where the issue lies. To capture network traffic you can use [Wireshark](https://www.wireshark.org/) or [tshark](https://tshark.dev/setup/install/) (aka. command line wireshark) and capture a .pcap file for analysis. An example of how to capture network traces in a docker environment can be found [here](../../deploy/docker/with-pcap-capture.yaml). To analyze OPC UA traffic, you must load the .pcap or .pcapng file you captured in Wireshark. Follow [these instructions](https://opcconnect.opcfoundation.org/2017/02/analyzing-opc-ua-communications-with-wireshark/#:~:text=Wireshark%20has%20a%20built-in%20filter%20for%20OPC%20UA%2C,fairly%20easy%20to%20capture%20and%20analyze%20the%20conversation.) to visualize the OPC UA traffic between OPC Publisher and your OPC UA server. If your connection to the OPC UA server is encrypted (using security) you must use Wireshark 4.3 (not the stable version!). You will also need to capture the client and server keys. You can start OPC Publisher with the `-ksf` [command line argument](./commandline.md), providing an optional folder path that can be accessed after running OPC Publisher (volume mount). The folder is structured like this: ![Key Set Log Folder](./media/keyset.png) You can open the `log.md` markdown file in the `opcua_debug` folder and find the connection and session you want to decrypt. ![Key Set Log File](./media/keyset1.png) The log file shows the remote and local endpoints as well as a summary of the connection configuration that was used to connect OPC Publisher. Each keyset log can be found in a subfolder that starts with the port number, because the port number needs to be configured in the OPC UA protocol page in Wireshark. ![Wireshark configuration](./media/keyset2.png) Once you have found the right folder, load the `opcua_debug.txt` file in it using the protocol page, then save and Wireshark will be able to decrypt traffic. ![Wireshark Analysis](./media/keyset3.png) > IMPORTANT: While the keys that are logged are scoped to the connection and cannot be re-used, it still presents a security risk, therefore, ensure to properly delete the `opcua_debug` folder and all its content when you are done. Do not use the feature in production. ### Netcap To simplify capturing network traces you can try out the [Netcap](../../samples/Netcap/readme.md) sample tool. It enables you to capture network traffic for an OPC Publisher module deployed to Azure IoT Edge. ## Session and Subscription diagnostics To enable client diagnostics output to the console use the `--di` [command line options](./commandline.md). The OPC Publisher can be configured to dump a the server diagnostics information for a session (connection) at an interval. The diagnostic information contains the session diagnostics and subscription diagnostics the server maintains provided it is enabled on the server. The OPC Publisher tries to enable the diagnostics information if it is disabled. Use it to see how the server sees the OPC Publisher and identify issues like leaked subscriptions (not cleaned up and causing resource exhaustion) or monitored items not being reflected on the server's view of the subscription. To enable a connection to dump its diagnostics, add a `"DumpConnectionDiagnostics": true` entry into the JSON configuration entry you want to diagnose. > Dumping diagnostics info is additional heavy load on the server. Use only sparingly, temporarily, and as a diagnostics tool only. ## Limits and contributing factors IoT Edge runs on various distributions of Linux and leverages Docker containers for all workloads, including the built-in IoT Edge modules `edgeAgent` and `edgeHub`. Docker has settings for the maximum host resources that each container can consume. These can be displayed by the Docker command "stats" (run "docker stats" from the terminal on the gateway host): ![Docker stats](./media/image9.png) Furthermore, the speed at which OPC UA telemetry messages can be sent to the cloud is dependent on the network resources available between the IoT Edge gateway and the Azure cloud data center. Here is a high-level data flow diagram: ![DataFlow](./media/image10.png) Customers often require "at least once" delivery of each telemetry message to the cloud, so Quality of Service - QoS must be enabled, in this case. As flow control is a big part of QoS, this significantly increases latency of each message delivered to the cloud. This is countered by packing as many telemetry "tags" as possible into a single message, called "batching." Using batching, between 300 to 475 telemetry tags can be packaged into a single IoT Hub message of maximum size (256KB). The reason for the range stems from the fact that each JSON encoded telemetry tag is not always the same length. It is dependent on tag names, the tag types and OPC UA server URI. Such an IoT Hub message takes about 150 ms to be delivered from Edge Hub to IoT Hub on a typical DSL connection and is much faster when Azure Express Route is leveraged. For a list of practical latency figures, please see [here](https://docs.microsoft.com/azure/expressroute/expressroute-troubleshooting-network-performance#latencybandwidth-results). The calculation for the maximum end-to-end latency is: ![Latency](./media/image11.png) For example, for 10,000 telemetry tags per second, the maximum latency allowed is 30 ms: ![Latency](./media/image12.png) Latency limitations can be mitigated by deploying several parallel IoT Edge gateways, i.e. for a typical DSL Internet connection with 150 ms latency, **up to 5 (150/30) parallel IoT Edge gateways** must be deployed in order to achieve 10,000 telemetry tags per second. Bandwidth is another important constraint, although usually more straightforward to address than latency. The calculation for bandwidth is: ![Bandwidth](./media/image13.png) For example, for 10,000 telemetry tags per second, the minimum bandwidth required is 69.91 Mbps: ![Bandwidth](./media/image14.png) Bandwidth limitations can be mitigated through a larger Internet connection (or a dedicated line like Express Route). Please also note that this ignores overhead of other consumers of bandwidth on the same connection and bandwidth fluctuations. Increasing the number of telemetry tags sent in a single message can also be achieved through picking a binary or compressed telemetry encoding. This is possible by specifying a different telemetry format or encoding during deployment of the system. The open standard OPC UA PubSub telemetry format, which Azure Industrial IoT leverages, supports both JSON and binary encodings. JSON has the advantage that many cloud databases can parse the data directly without the need for a separate telemetry processor being hosted in front of the database (which needs to be built, deployed, and maintained). A telemetry processor translates the telemetry message back to JSON. ## Debugging Discovery To be able to perform active network scanning on a network interface of the host device you must attach OPC Publisher to the host network using the docker create options. Make sure to validate the host network is available: ```bash docker network ls NETWORK ID NAME DRIVER SCOPE beceb3bd61c4 azure-iot-edge bridge local 97eccb2b9f82 bridge bridge local 758d949c5343 host host local 72fb3597ef74 none null local ``` Update the create options to attach the OPC Publisher module to the host network: ```json ``` ================================================ FILE: docs/readme.md ================================================ # Azure Industrial IoT [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) > This documentation applies to version 2.9 ## Table Of Contents - [Features](#features) - [Use Cases](#use-cases) - [What is OPC UA?](#what-is-opc-ua) - [Why did Microsoft choose OPC UA as Industrial IoT Protocol?](#why-did-microsoft-choose-opc-ua-as-industrial-iot-protocol) - [How can I learn more?](#how-can-i-learn-more) - [Next steps](#next-steps) ## Features Azure [OPC Publisher](./opc-publisher/readme.md) allows plant operators to discover [OPC UA](#what-is-opc-ua) enabled servers in a factory network and register them in Azure IoT Hub. Operations personnel can subscribe to and react to events on the factory floor from anywhere in the world. The APIs mirror the [OPC UA](#what-is-opc-ua) services and are secured through IoT Hub or optionally using OAUTH authentication and authorization backed by Azure Active Directory (AAD). This enables your applications to browse server address spaces or read/write variables and execute methods using IoT Hub, MQTT or HTTPS with simple JSON payloads. The following diagram shows how the OPC Publisher and optional REST Api integrate with Azure IoT Hub, Azure IoT Edge and other Azure services: ![Architecture](./media/architecture.png) The [OPC Publisher API](./opc-publisher/readme.md) can be used with any programming language through its exposed Open API specification (Swagger). This means when integrating OPC UA into cloud management solutions, developers are free to choose technology that matches their skills, interests, and architecture choices. For example, a full stack web developer who develops an application for an alarm and event dashboard can write logic to respond to events in JavaScript or TypeScript without ramping up on a OPC UA SDK, C, C++, Java or C#. ## Use Cases OPC Publisher has fully embraced openness (an open platform, open source, open industrial standards and an open data model is used). Specifically, we leverage Azure's managed Platform as a Service (PaaS) offering, open-source software licensed via MIT license, open international standards for communication (OPC UA, AMQP, MQTT, HTTP) and interfaces (Open API) and open industrial data models (OPC UA) on the edge and in the cloud. OPC Publisher covers industrial connectivity of shop floor assets (including discovery of OPC UA-enabled assets), normalizes their data into OPC UA format and transmits asset telemetry data to Azure in OPC UA PubSub format. There, it stores the telemetry data in a cloud database. In addition, the platform enables secure access to the shop floor assets via OPC UA from the cloud. Device management capabilities (including security configuration) is also built in. The OPC UA functionality has been built using Docker container technology for easy deployment and management. For non-OPC UA-enabled assets, we have partnered with the leading industrial connectivity providers and helped them port their OPC UA adapter software to Azure IoT Edge. These adapters are available in the [Azure Marketplace](https://azuremarketplace.microsoft.com/marketplace/apps/category/internet-of-things?page=1&subcategories=iot-edge-modules). ## What is OPC UA? OPC Unified Architecture (UA), released in 2008, is a platform-independent, service-oriented interoperability standard. OPC UA is used by various industrial systems and devices such as industry PCs, PLCs, and sensors. OPC UA integrates the functionality of the OPC Classic specifications into one extensible framework with built-in security. It is a standard that is driven by the OPC Foundation. The [OPC Foundation](https://opcfoundation.org/) is a not-for-profit organization with more than 440 members. The goal of the organization is to use OPC specifications to facilitate multi-vendor, multi-platform, secure and reliable interoperability through: - Infrastructure - Specifications - Technology - Processes ### Why did Microsoft choose OPC UA as Industrial IoT Protocol? Microsoft chose OPC UA because it is an open, non-proprietary, platform independent, industry-recognized, and proven standard. It is a requirement for Industry 4.0 (RAMI4.0) reference architecture solutions ensuring interoperability between a broad set of manufacturing processes and equipment. Microsoft sees demand from its customers to build Industry 4.0 solutions. Support for OPC UA helps lower the barrier for customers to achieve their goals and provides immediate business value to them. ### How can I learn more? - Visit the OPC Foundation [Website](https://opcfoundation.org/). - Browse version [1.04 of the OPC UA specification](https://reference.opcfoundation.org/v104/). ## Next steps - [Learn more about OPC Publisher](./opc-publisher/readme.md) - [Release announcements](./release-announcement.md) ================================================ FILE: docs/release-announcement.md ================================================ # Release announcement ## Table Of Contents - [Azure Industrial IoT OPC Publisher 2.9.15](#azure-industrial-iot-opc-publisher-2915) - [Breaking changes](#breaking-changes) - [Changes in 2.9.15](#changes-in-2915) - [Azure Industrial IoT OPC Publisher 2.9.14](#azure-industrial-iot-opc-publisher-2914) - [Changes in 2.9.14](#changes-in-2914) - [Azure Industrial IoT OPC Publisher 2.9.13](#azure-industrial-iot-opc-publisher-2913) - [Changes in 2.9.13](#changes-in-2913) - [Azure Industrial IoT OPC Publisher 2.9.12](#azure-industrial-iot-opc-publisher-2912) - [Significant changes made in 2.9.12](#significant-changes-made-in-2912) - [Other changes in 2.9.12](#other-changes-in-2912) - [Azure Industrial IoT OPC Publisher 2.9.11](#azure-industrial-iot-opc-publisher-2911) - [Changes in 2.9.11](#changes-in-2911) - [Azure Industrial IoT OPC Publisher 2.9.10](#azure-industrial-iot-opc-publisher-2910) - [Changes in 2.9.10](#changes-in-2910) - [Azure Industrial IoT OPC Publisher 2.9.9](#azure-industrial-iot-opc-publisher-299) - [Changes in 2.9.9](#changes-in-299) - [Azure Industrial IoT OPC Publisher 2.9.8](#azure-industrial-iot-opc-publisher-298) - [Changes in 2.9.8](#changes-in-298) - [Azure Industrial IoT OPC Publisher 2.9.7](#azure-industrial-iot-opc-publisher-297) - [Changes in 2.9.7](#changes-in-297) - [Azure Industrial IoT OPC Publisher 2.9.6](#azure-industrial-iot-opc-publisher-296) - [Changes in 2.9.6](#changes-in-296) - [Azure Industrial IoT OPC Publisher 2.9.5](#azure-industrial-iot-opc-publisher-295) - [Changes in 2.9.5](#changes-in-295) - [Azure Industrial IoT OPC Publisher 2.9.4](#azure-industrial-iot-opc-publisher-294) - [Breaking changes in 2.9.4](#breaking-changes-in-294) - [Changes in 2.9.4](#changes-in-294) - [Azure Industrial IoT OPC Publisher 2.9.3](#azure-industrial-iot-opc-publisher-293) - [Breaking changes in 2.9.3](#breaking-changes-in-293) - [New features in 2.9.3](#new-features-in-293) - [Bug fixes in 2.9.3](#bug-fixes-in-293) - [Azure Industrial IoT OPC Publisher 2.9.2](#azure-industrial-iot-opc-publisher-292) - [Changes in 2.9.2](#changes-in-292) - [Azure Industrial IoT OPC Publisher 2.9.1](#azure-industrial-iot-opc-publisher-291) - [Changes in 2.9.1](#changes-in-291) - [Azure Industrial IoT OPC Publisher 2.9.0](#azure-industrial-iot-opc-publisher-290) - [Changes in 2.9.0](#changes-in-290) - [Azure Industrial IoT OPC Publisher 2.9.0 Community Preview 4](#azure-industrial-iot-opc-publisher-290-community-preview-4) - [Changes in 2.9.0 Preview 4](#changes-in-290-preview-4) - [Azure Industrial IoT OPC Publisher 2.9.0 Community Preview 3](#azure-industrial-iot-opc-publisher-290-community-preview-3) - [Changes in 2.9.0 Preview 3](#changes-in-290-preview-3) - [Azure Industrial IoT OPC Publisher 2.9.0 Community Preview 2](#azure-industrial-iot-opc-publisher-290-community-preview-2) - [Changes in 2.9.0 Preview 2](#changes-in-290-preview-2) - [Azure Industrial IoT OPC Publisher 2.9.0 Community Preview 1](#azure-industrial-iot-opc-publisher-290-community-preview-1) - [Changes in 2.9.0 Preview 1](#changes-in-290-preview-1) - [Azure Industrial IoT Platform Release 2.8.6](#azure-industrial-iot-platform-release-286) - [Changes in 2.8.6](#changes-in-286) - [Azure Industrial IoT Platform Release 2.8.5](#azure-industrial-iot-platform-release-285) - [Changes in 2.8.5](#changes-in-285) - [Azure Industrial IoT Platform Release 2.8.4](#azure-industrial-iot-platform-release-284) - [IMPORTANT - PLEASE READ](#important---please-read) - [Changes in 2.8.4](#changes-in-284) - [Known issues](#known-issues) - [Azure Industrial IoT Platform Release 2.8.3](#azure-industrial-iot-platform-release-283) - [Security related fixes in 2.8.3](#security-related-fixes-in-283) - [Fundamentals related fixes in 2.8.3](#fundamentals-related-fixes-in-283) - [Bug fixes in 2.8.3](#bug-fixes-in-283) - [Azure Industrial IoT Platform Release 2.8.2](#azure-industrial-iot-platform-release-282) - [Fundamentals related fixes in 2.8.2](#fundamentals-related-fixes-in-282) - [Backwards Compatibility Notes for release 2.8.2](#backwards-compatibility-notes-for-release-282) - [Azure Industrial IoT Platform Release 2.8.1](#azure-industrial-iot-platform-release-281) - [Azure Industrial IoT Platform Release 2.8](#azure-industrial-iot-platform-release-28) ## Azure Industrial IoT OPC Publisher 2.9.15 We are pleased to announce the release of version 2.9.15 of OPC Publisher. This monthly patch release comes with several bug and security fixes and is the latest supported release. Older releases below are no longer supported. ### Breaking changes - The companion web app and API are no longer supported or included (#2370) - OPC Publisher container by default runs root-less (non-root user). To run as root, start the OPC Publisher using the --user root command line option. (#2428) ### Changes in 2.9.15 - call of ISA95 JobOrderReceiver "Store" method fails decoding "JobOrderParameters" "ISA95ParameterDataType" (2424) - OPC Publisher does not re-establish connection to OPC UA server, if the OPC UA server is restarted. (#2416) - Updates to all dependencies (.net and OPC UA stack) ## Azure Industrial IoT OPC Publisher 2.9.14 We are pleased to announce the release of version 2.9.14 This monthly patch release updates dependencies to fix security vulnerabilities and bugs in them and is the latest supported release. Older releases below are no longer supported. ### Changes in 2.9.14 - Updates to all dependencies (.net 9.0.5 and OPC UA stack) - Additional diagnostic instruments to monitor session keep alive counters ## Azure Industrial IoT OPC Publisher 2.9.13 We are pleased to announce the release of version 2.9.13 of OPC Publisher and the companion web api service. This monthly patch release comes with several bug and security fixes and is the latest supported release. Older releases below are no longer supported. ### Changes in 2.9.13 - Resiliency fixes based on new manual chaos testing. - Recover a dead subscription that is missing keep alive results for the configured keep alive and life time count. - Recover sessions that fail to be established due to various errors including session closed unexpectedly in server. - Fix typo in DefaultDataChangeTrigger environment variable name (breaking change) (#2393) - Events with arrays of complex data types are not encoded at all (#2381) - Updates to all dependencies (.net 9.0.4 and OPC UA stack) ## Azure Industrial IoT OPC Publisher 2.9.12 We are pleased to announce the release of version 2.9.12 of OPC Publisher and the companion web api service. This monthly patch release comes with several bug and security fixes and is the latest supported release. Older releases below are no longer supported. ### Significant changes made in 2.9.12 This release makes significant changes under the hood of OPC Publisher. These changes include: - The 1:1 relationship between writers and session/subscription has been removed. Instead the concept of a virtual subscription that bundles multiple writers was added to remove load on some servers that only allow a small number of subscriptions. (#2295) - Instead of trying to reconnect to the old session in the server, the OPC UA client will now always reconnect a new session and recreate all subscriptions if the secure channel drops (#2368, #2373, #2361, #2344) - Update to .net 9 and update of all packages to latest version. This includes update to MQTT.net v5. - New preview feature to initialize publisher from a init file that automates the OPC Publisher config api. This enables for example - Publishing all nodes of a connected OPC server (#2354, #2341) - Support subscribing to Nodes where NodeClass is Object (recursively to all HasComponent variables underneath) (#1320) ### Other changes in 2.9.12 - Fix a NullReferenceException when Cyclic read monitored items are recreated/connected or when heartbeat notifications are to be sent while disconnected (#2367) - And related - ConditionHandling stops working after some time (#2288) - Extension Fields are now part of all messages (#2360) - Fix changing entry from SignAndEncrypt to None fails to connect until restarted (#2351) - Fix Kepserver restart leads to ArgumentException: Timeout must be greater than zero. (#2346) - Configuring MaxPublishRequests via command line and environment variable now works correctly (#2289) - Enable Response Compression in Publisher Rest API (Accept-Encoding gzip) (#2350) - Allow setting security policy only using the anchor name (e.g. "None"), not the entire url (#2337) - Ability to specify cache age for cyclic reads (#2328) - Add Endpoint url and application uri to PubSub messages (#2329) - New Heartbeat behavior to send values periodically but not send freshly received values. (#2327) - Support close and commit instead of just close when closing a file using the file API (#2322) ## Azure Industrial IoT OPC Publisher 2.9.11 We are pleased to announce the release of version 2.9.11 of OPC Publisher and the companion web api service. This monthly patch release comes with several bug and security fixes and is the latest supported release. Older releases below are no longer supported. ### Changes in 2.9.11 - Fixes an issue when using amqp as transport combined with batching, some batches are not sent successfully (#2321) - Dependency updates to fix critical vulnerabilities as well as bugs such as proper support for cgroup v2 is used bug (#2261) - Resiliency and fixes of critical bugs in reconnect scenarios: - Fix for "Item was disposed or moved to another subscription" (#2317) - Fix for heartbeat and condition timers stopping and not recovering - Subscriptions behavior now extends to subscriptions whose lifetime counter has expired (default: reset) (#2301) - Fix an issue with a runaway Heartbeat timer causing publishing wrong values at wrong time (#2313) - API addition allowing selecting which OPC Publisher to use for discovery feature request (#2302) ## Azure Industrial IoT OPC Publisher 2.9.10 We are pleased to announce the release of version 2.9.10 of OPC Publisher and the companion web api service. This monthly patch release comes with several bug and security fixes and is the latest supported release. Older releases below are no longer supported. ### Changes in 2.9.10 - Update OPC UA .net stack to the latest 1.05 version and move forward other dependencies - API to get the server session, channel and subscription diagnostics for connections (#2303) - New --aq command line option to calculate queue sizes automatically from publishing interval and sampling interval (#2300) - New --ipi option to ignore publishing intervals in JSON configuration and use the default configured with --op (#2299) - New --spw option to configure creating a session per dataset writer (#2298) - Provide example and documentation for Browse Path definition. Allow browse path without node id in configuration (#2296) - New defaults for Keep alive counter and lifetime counters set to 0 to let server decide (#2294) - Updates and additions to writer API to manage writers and writer groups with data set fields (#2257, #2285, #2269, #2293, #2269) - Fix setting Heartbeat Interval with API is using milliseconds instead of seconds (#2292) - Fix issue that after calling reset API (/v2/reset) publisher stops receiving data changes (#2291) - Fix bug where ConditionHandling and Heartbeat timers stop working after reconnects (#2288) - Fix bug where Complex types are not decoded in initial messages (#2281) - Allow configuring message TTL on DatasetWriterGroup level (#2280) - Add ability to set Timestamp in UserProperties of message when using MQTT Transport (#2277) - JSON Configuration now provides the ability to set a (default) sampling interval for a writer (#2271) - Show log message when namespace table changes inside a client and between session reconnects (#2263) - Return ProblemDetails JSON for all error responses (#2201) - Fix incompatibility when generating SDK from openapi.json using Autorest (#2199) ## Azure Industrial IoT OPC Publisher 2.9.9 We are pleased to announce the release of version 2.9.9 of OPC Publisher and the companion web api service. This release comes with several bug and security fixes and is the latest supported release. We recommend strongly to update from 2.9.8 due to several security fixes and overall instability in 2.9.8 and before in reconnect situations. ### Changes in 2.9.9 - Update OPC UA .net stack to the latest 1.05 version and move forward other dependencies - Monitored item state is not properly cleaned up after a hard reconnect which leads to heartbeat timers still being alive. - Allow configuring a watchdog for monitored items and set behavior when watchdog expires (#2164) - Limit number of publish requests to 10, allow override using command line argument (#2215) - Fix issue where count of bad and good monitored items is incorrect (#2202) - Return better error messages in responses (#2195) - Fix issue where publisher stops respecting reconnect period after initial successful connection (#2189) - Added sample to show using NodeRead to read attributes (#2226) - New command line option to read configuration from first certificate found in own folder addresses several backward compatibility breaks when migrating between OPCPublisher versions (#2166) - Added call timeouts that can be overridden in request header and automatically cancel after timeout (#2203, #2219, #2213) - Fix an issue where linger does not work when reference continuation token between calls is the same (#2227) - Add a command line option to disable runtime metrics (#2200, #2197) - Added ability to write encoded messages to stdout/stderr for debugging (#2259) - Add ability to disable resource monitoring via command line option to work around any incompatibility with host systems (related to #2261) - Improved documentation. ## Azure Industrial IoT OPC Publisher 2.9.8 We are pleased to announce the release of version 2.9.8 of OPC Publisher and the companion web api service. This release comes with several bug and security fixes and is the latest supported release. ### Changes in 2.9.8 - Update OPC UA .net stack to the latest 1.05 version and move forward other dependencies - Telemetry messages are sent with non default (0) ttl now to support DAPR >= 1.13 (#2243) - Elevation property in request header does work now when service calls are sent using edge API (#2218) - Add more Info to Logs in case of publishing errors, e.g. "Too many publish request error" (#2229) - New Security mode "NotNone" reflecting the legacy "UseSecurity":true setting in nodes. "Best" (any) is persisting after Opc Publisher is restarted (#2228) - Latest OPC UA .net stack fixes "CRL with zero revoked certificates fails to be decoded (#2214) - Enable the definition of the GRPC endpoint host name for DAPR (#2235) - Diagnostic info API returns incorrect information (#2230) - Make TransferSubscriptionsOnReconnect configurable (via publishednodes.json) (#2205) - Ability to disable Complex type system loading (#2185) - Several improvements for cyclic read (#2169) - Only submit publish requests for active subscriptions rather than any subscription. (#2184) - Better diagnostic messages of number of cyclic read, heartbeat, events per minute (#2175) - Track # of missed intervals / samples due to latency of read (#2174) - BadNodeIdUnknown not re-evaluated despite short retry delays? (#2188) - Additional information in diagnostic messages including resource consumption (total) - Persistency of published nodes file now uses .net storage provider which supports enabling file change polling via command line option (needed on some linux setups) ## Azure Industrial IoT OPC Publisher 2.9.7 ### Changes in 2.9.7 - Added additional diagnostic logging option to capture the encoded notifications as well ## Azure Industrial IoT OPC Publisher 2.9.6 We are pleased to announce the release of version 2.9.6 of OPC Publisher and the companion web api service. This release comes with several bug and security fixes and is the latest supported release. ### Changes in 2.9.6 - Update OPC UA .net stack to the latest 1.05 version and move forward other dependencies fixing several reported CVE vulnerabilities. - Additional option to log encoded notifications to trace data all the way to send path. - Hardened code paths that made it possible that no more publishing requests are enqueued after a while. Continuously ensure minimum amount of publish requests are in progress when receiving good session keep alives. ## Azure Industrial IoT OPC Publisher 2.9.5 We are pleased to announce the release of version 2.9.5 of OPC Publisher and the companion web api service. This release comes with several bug and security fixes and is the latest supported release. ### Changes in 2.9.5 - Update OPC UA .net stack to the latest 1.05 version and move forward other dependencies - Fixed a bug where OPC Publisher could not connect when the port provided in the endpoint during discovery is different than the port in of the discovery URL. ## Azure Industrial IoT OPC Publisher 2.9.4 We are pleased to announce the release of version 2.9.4 of OPC Publisher and the companion web api service. This release comes with several bug and security fixes and is the latest supported release. ### Breaking changes in 2.9.4 > IMPORTANT. Please read when updating from previous versions of OPC Publisher - Arm64 and AMD64 container images are published now with Mariner (Azure) Linux (distroless) as base images instead of Alpine. - Arm32 (v7) images of OPC Publisher continue to use Alpine as base image. Support transitions to the same model as for "preview" features. Security updates are released as a result of updates to the AMD64 and ARM64 version of OPC Publisher. - Swagger UI has been removed without replacement. ### Changes in 2.9.4 - Update OPC UA .net stack to the 1.05 version including latest node set and fixing numerous issues. (#2162) - ApiKey and other secrets can now be provided ahead of time through docker secrets (or command line) in addition to being only available in the Module Twin. (#2181) - Send the error of CreateMonitoredItem as part of the keyframe field and in heartbeats if WatchdogLKV heartbeat behavior is used (#2150). - Credential based authentication uses concrete types for credentials now which are documented in openapi.json (#2152) - OPC Publisher can now obtain TLS certificates from IoT Edge workload API to secure the HTTPS API (#2101) - Fix release build issue which broke support for ARM64 images running on RPi4 (#2145). - Update console diagnostics output to provide better naming, additional diagnostics and reflect other transports than IoT Edge Hub (#2141) - Add keep alive notification counts to Diagnostics output and messages - Better diagnostics messages of cyclic reads, heartbeats and events including per minute and second reporting (#2175, #2174) - Experimental feature to allow publishing model changes in the underlying server address space (change feed) (#2158) - Add a full version that includes runtime, framework and full version string to runtime state message, twin, diagnostic object, and in console output. - When only using cyclic reads, the underlying dummy subscription should stay disabled (#2139) - Recreate session if it expires on server (#2138) - Log subscription keep alive error only when session is connected (#2137) - Added the ability to switch publisher to emit logs in syslog or systemd format using --lfm command line option. - Fix issue where certain publish errors cause reconnect state machine to fail (#2104, #2136) - Fix issues with cyclic reads not working as expected, subscribing to nodes > 300 not working (#2160, #2165) - Metric names are not like they were in 2.8, some metrics are missing (#2149) - SiteId placeholder is not working in TelemetryTopicTemplate (#2161) - Messaging mode can now be overridden in Strict mode to use a non-compliant mode. (#2167) ## Azure Industrial IoT OPC Publisher 2.9.3 We are pleased to announce the release of version 2.9.3 of OPC Publisher and the companion web api. This release moves OPC Publisher to .net 8 which is the latest LTS version of .net and comes with several new features, bug and security fixes. 2.9.3 is the latest supported release. ### Breaking changes in 2.9.3 > IMPORTANT. Please read when updating from previous versions of OPC Publisher - Arm64 and AMD64 container images are published now with (Azure) Mariner Linux (distroless) as base images instead of Alpine. - Arm32 (v7) images of OPC Publisher continue to use Alpine as base image. Support transitions to the same model as for "preview" features. Security updates are released as a result of updates to the AMD64 and ARM64 version of OPC Publisher. - Metadata collection has shown to be very taxing on OPC UA servers. When 2.9 was dropped in to replace 2.8 in production, memory consumption was too large and connections would drop. OPC Publisher now defaults to `--dm=true` in 2.9.3 to disable metadata messages to be compatible with 2.8 when `--strict` / `-c` is not specified. If you need meta data messages but do not use strict mode (not recommended) you must explicitly enable it using `--dm=false`. ### New features in 2.9.3 - For security the OPC Publisher Web API container now runs root-less. (#2114) - New configuration option to specify quality of service. This allows setting QOS0 as alternative to QOS1 (#2085) - Diagnostic info can now also be periodically published to a topic or IoT Edge output name using new `--dtt` diagnostics topic template. (#2068) - New Module to module method to get REST endpoint info and API key so that other modules can access the REST API (#2096) - Fixed Publisher HTTPS API returning SSL_ERROR_SYSCALL error. Now a self signed certificate is the fallback if workload api cannot produce a certificate with private key (#2101) - Restart announcement now includes additional information, including version, timestamp of (re-)start, module and device ids. - X509 User Authentication support using secrets reference feature request (#2005) - New API to manage the PKI infrastructure of the OPC Publisher (certificate stores). You can now list, add and remove certificates from the OPC UA certificate stores remotely. (#1996) - You can now configure OPC Publisher to re-use a session across writer groups with the same endpoint url and security settings. (#2065) - Subscription Watchdog monitors keep alive notifications and generates metric and logs when subscription keep alive is missing (#2060) - Added samples to show how to call OPC Publisher API over MQTT, HTTP and IoT Hub. ### Bug fixes in 2.9.3 - 2.8 Start instrument was missing on 2.9 prometheus endpoint (#2110) - Fix Publisher cannot get ssl cert from workload api, HTTPS API returning SSL_ERROR_SYSCALL error (#2101) - Harden when OPC UA server sometimes reports monitored items samples changes unordered in subscription notification and thus samples messages are also unordered (#2108) - Need to have timestamp information and other information in runtime state reporting message, need to have a special routing path for runtime state messages feature request. Restart announcement now includes additional information, including version, timestamp of (re-)start, module and device ids. (#2111) - Optimize metadata collection, do not collect metadata from servers for built in types (#2105) - Fix that it was not possible to configure event subscriptions for multiple events on the same node id (#2098) - Fix complex type encoding where Json message encoding has value in Binary encoding for complex (multilevel structure) (#2090) - Dapr now works without requiring state component. Dapr now runs over http instead of https by default. New option to select the url scheme (#2102, #2119, #2117, #2109 - It is now possible to disable retrying subscription re-creation by configuring a value of 0. (#2100) - Fix that extension field values show up wrong in samples mode. (#2092) - Fix Event subscription using the REST Api fails with: "The request field is required." (#2078) - The configuration of the OpcPublisher 2.9.2 fails using the REST Api bug (#2066) - For each configured in pn.json Dataset publisher must try to reuse an existing session for this EndpointUrl with the identical security settings (if exists). feature request - Address issues deploying the web api, e.g., getting error when trying to use option 2 to deploy Azure IIoT Deployment and ./aad-register.ps1 errors with "A parameter cannot be found that matches the parameter name 'ReplyUrl'." (#2063, #2064) - Update documentation, including breaking changes, Add Azure Storage, Azure Key Vault services, and Application Insights to arch diagram, how to setup the OPCPublisher edge module with X.509 certificates documentation, and how to emit ExtensionFields in Pub sub mode using key frame counter. (#1917, #2091, #2083) - Fix incorrect API definitions in OpenAPI JSON for OPC publisher - FileSystem target now appends data instead of updating the file content. FileSystem target now supports arbitrary chars in topics. ## Azure Industrial IoT OPC Publisher 2.9.2 We are pleased to announce the release of version 2.9.2 of OPC Publisher. This release comes with several bug and security fixes and is the latest supported release. ### Changes in 2.9.2 - Update to version 1.4.372 of the OPC UA .net stack and updated to latest secure version of nuget dependencies. - Fixed a bug where data stopped flowing in OPC Publisher bug on reconnect when subscription ids do not match server state (#2055) - Ability to select the message timestamp and behavior of Heartbeat - Ability to generate heartbeats with different sourceTimestamp and serverTimestamp (#2049) - Added a behavior option to update the source timestamp relative to the LKV to mimic previous behavior (#2048) - First Heartbeat message now dows not send anymore GoodNoData status when the monitored item is not yet live (#2041) - MQTT reconnect and disconnect reasons are now logged as errors (#2025) - Fixed an issue where Publisher failed to subscribe to a node because namespace table entry was not available during connect/subscribe (#2042) (Thank you @quality-leftovers for contributing this fix) - The default application name used to create certs is now the same as in 2.8 (#2047) - Batch size and Batch trigger have same defaults now than 2.8 (#2045) - Fix a bug where the user was not added correctly as owner in the aad_register.ps1 script (Thank you @0o001 for contributing this fix) ## Azure Industrial IoT OPC Publisher 2.9.1 We are pleased to announce the release of version 2.9.1 of OPC Publisher. 2.9.1 comes with several bug and security fixes and is the latest supported release. ### Changes in 2.9.1 - Update all dependencies to latest version, in particular latest opc ua .net stack release 372 - MQTT samples and making MQTT method calls over RPC working with Mqtt.net (#2039) - IoT Hub direct method samples (#2032) - The CLI switches using the environment variable names do no work (#2021) - New command line setting to select which clock is chosen for message timestamp (publish time or publisher current time) (#2035) - Fix negative count shown in diagnostics (#2031) - Documentation updates and fixes ## Azure Industrial IoT OPC Publisher 2.9.0 We are pleased to announce the release of version 2.9.0 of OPC Publisher. This release adds several new features including support for reverse connect. ### Changes in 2.9.0 For the list of changes released so far in preview releases please see: - [Changes in 2.9.0 Preview 4](#changes-in-290-preview-4) - [Changes in 2.9.0 Preview 3](#changes-in-290-preview-3) - [Changes in 2.9.0 Preview 2](#changes-in-290-preview-2) - [Changes in 2.9.0 Preview 1](#changes-in-290-preview-1) The final release contains the following changes: - Restart announcement tests are disabled and need to work again #1988 - Event item filter errors should be an error condition and re-evaluated periodically. #2014 - Feedback / Message / Metric on OPC Server down or wrong credentials provided in OPC Publisher 2.8+ #1445 - Option to directly enable subscription during create rather than using SetPublishingMode request. (BadNodeIdUnkown OPCPublisher) #1773 - Option to enable swagger UI in release build publishers. (OPCPublisher:latest API Server not working) #2009 - Publisher should try first to select the endpoint matching the configured url in Connection model. #2013 - Select security mode and profile in configuration #2008 - Using G8/17 to serialize float/double for precision Float/Double Serializer #1709 - Send extension fields as part of datasetmessage and enable free form configuration of extension fields (move to Variant value) #1940 - Command line option to disable complex type loading. #1953 - publishednodes.json: When OpcAuthenticationUsername is set but OpcAuthenticationPassword is erroneously not, a misleading error message appears #1059 - OPC Publisher REST API and Direct Methods Reference (Publish, Twin, Discovery) documentation #1976/#1504 - AAD-Register fails on converting System.String to type "System.Security.SecureString" #2015 ## Azure Industrial IoT OPC Publisher 2.9.0 Community Preview 4 We are pleased to announce the fourth **preview** release of version 2.9.0 of OPC Publisher. This release adds several new features including support for reverse connect. > IMPORTANT: Preview releases are only supported through GitHub issues. This particular release due to the number of changes included might have backward compatibility breaks that have not yet been documented. Please file issues and we will try to address them ahead of GA release. ### Changes in 2.9.0 Preview 4 - [OPC Publisher] Better documentation for REST API call with API Key #1991 - [OPC Publisher] Fix Can't run OPC UA Publisher standalone module inside IoT Edge Simulator environment (iotedgehubdev) #1708 - [OPC Publisher] No BypassCertVerification required in Simulation with VS Code / iotedgehubdev #1922 - [OPC Publisher] Fix standalone OPC-Publisher in Edge Simulator doesn't work #1999 - [OPC Publisher] Fix 2.9 preview 3 not supporting iot edge decrypt of passwords #1998 - [OPC Publisher] Application uri of the publisher should be unique for the deployment. #1986 - [OPC Publisher] Better documentation for --strict mode in OPC Publisher, Better documentation for all other message profiles. #1938 - [OPC Publisher] A way to node id in nsu and ns index format like ns=1;s=CycleCounter using API and telemetry #1057 - [OPC Publisher] Support for Reverse Connect # 1586 ## Azure Industrial IoT OPC Publisher 2.9.0 Community Preview 3 We are pleased to announce the third **preview** release of version 2.9.0 of OPC Publisher. This release adds several new features including support for cyclic reads. > IMPORTANT: Preview releases are only supported through GitHub issues. This particular release due to the number of changes included might have backward compatibility breaks that have not yet been documented. Please file issues and we will try to address them ahead of GA release. ### Changes in 2.9.0 Preview 3 - [OPC Publisher] Heartbeat behavior is not deterministic - implement heartbeat as value change watchdog. #1993 - [OPC Publisher] When enabling client linger in preview2 a failing connection retries forever #1985 - [OPC Publisher] Alarm condition integration tests have been partially disabled and need to enable again #1989 - [OPC Publisher] Need OPC Publisher to poll data from server periodically rather than subscribing. #1934 - [OPC Publisher] Polling mechanism instead of PubSub in OPCPublisher #605 - [OPC Publisher] Configuration of the published nodes by browse path #47 - [OPC Publisher] deploy.ps1 fails upon deploying "platform" #1981 [OPC Publisher] Updated documentation and nuget dependencies ## Azure Industrial IoT OPC Publisher 2.9.0 Community Preview 2 We are pleased to announce the second **preview** release of version 2.9.0 of OPC Publisher. This release marks a large change for the Industrial IoT components and features. We have combined all edge functionality into the OPC Publisher edge module which now boasts not just MQTT and IoT Hub direct method access, but a full HTTP REST endpoint that can be used to configure its functionality. The cloud components also have been combined into a single Web API, which we recommend to deploy into Azure App Service for reduced cost and simplified operations. > IMPORTANT: Preview releases are only supported through GitHub issues. This particular release due to the number of changes included might have backward compatibility breaks that have not yet been documented. Please file issues and we will try to address them ahead of GA release. ### Changes in 2.9.0 Preview 2 - New Namespaces for all projects and simplified code structure. There are now 2 SDK projects, one for the OPC Publisher module, and another for the optional cloud WebAPI companion service. - Ability to run platform (modules, services) "standalone" on the edge #464 - [OPC Discovery] has been included into the OPC Publisher module, the container name must be updated to refer to OPC Publisher. - [OPC Discovery] A new synchronous FindServer API has been added to allow discovery by discovery url through a single API call. - [OPC Twin] has been included into the OPC Publisher module, the container name must be updated to refer to OPC Publisher. - [OPC Twin] we removed the Activate and Deactivate calls. - [OPC Twin] OPC TWIN Method call #996 - Support for opc-twin module api direct method calls with input arguments (not requiring OPC Twin micro services) #1512 - Support for a new TestConnection API to test a connection to a server and receiving detailed error information back. - [OPC Publisher] (breaking change) The publisher id in each message is now always the same value across all writer groups rather than previously where a random guid was used per writer group when a publisher id was not configured. - [OPC Publisher] Several bug fixes for preview 1 (#1964) - [OPC Publisher] DatasetMessage SequenceNumber is now correctly incremented (preview) (#1961) - [OPC Publisher] Enabling using DisplayNames defined for the event fields in pn.json as keys in the payload of dataset messages (#1963) - [OPC Publisher] Request opc server's nodes information #1960 - [OPC Publisher] dotnet publish can be used to build a docker container for OPC Publisher #1949 - [OPC Publisher] Metrics output and log output showing number of sessions currently active (related to #1923) - [OPC Publisher] Added new OPC UA stack which addressess #1937 and latest CVE's - [All micro services] Have been combined into a single WebAPI with the same resource paths as the 2.8 AKS deployment and all-in-one service. - [OPC Registry service] Supervisor, Discoverer entities have been removed, but the API has been layered on top of the publisher entity for backwards compatibiltiy. Do not use these API's anymore. - [OPC Registry service] A new RegisterEndpoint API has been added that calls the new sync FindServer API and adds the result into the registry in one call. - [Telemetry processor] The telemetry and onboarding processors have been integrated into the WebAPI, but only forwards to SignalR. The secondary event hub has been removed. If you need to post process telemetry you must read telemetry data directly from IoT Hub. - Document the diagnostics output and troubleshooting guide #1952 ## Azure Industrial IoT OPC Publisher 2.9.0 Community Preview 1 We are pleased to announce the first **preview** release of version 2.9.0 of OPC Publisher. This release contains several requested features and fixes issues discovered. > IMPORTANT: Preview releases are only supported through GitHub issues. ### Changes in 2.9.0 Preview 1 - [OPC Publisher] [Alarms and Events](./opc-publisher/readme.md#configuring-event-subscriptions) support to OPC Publisher. You can now subscribe to events in addition to value changes and in the familar ways using the published nodes json configuration and direct methods. - [OPC Publisher] Full Deadband filtering. We introduced data change triggers in 2.8.4 and are now supporting the full data change filter configuration to configure percent and absolute deadband as defined in OPC UA. - [OPC Publisher] Support setting discard new configuration on command line. - [OPC Publisher] Full support for UADP network message encoding, as well as reversible Json profiles (JsonReversible) - [OPC Publisher] Support for smaller network messages by removing network message and dataset message headers (adding new MessageType.RawDataset and MessageType.DataSetMessages). - [OPC Publisher] Support for gzip encoded Json (MessageEncoding.JsonGzip and MessageEncoding.JsonReversibleGzip) - [OPC Publihser] Strict mode to adhere to OPC UA Part 14 and Part 6, including message formats and data type serialization. - [OPC Publisher] Adding back support for --sf and SkipFirst property to skip the first data change notification to be sent when subscription is created. - [All IoT Edge modules] Configuration to optionally enable MQTT topic publishing and command control via an MQTT broker instead of IoT Edge EdgeHub. - [All IoT Edge modules] Update OPC UA stack to latest .371 version. ## Azure Industrial IoT Platform Release 2.8.6 We are pleased to announce the release of version 2.8.6 of our Industrial IoT Platform components as latest patch update of the 2.8 Long-Term Support (LTS) release. This release contains important security updates fixes, performance optimizations and bugfixes. ### Changes in 2.8.6 - [All] Update to latest JSON.net nuget dependency. - [All] Use latest OPC UA .net stack 371. - Update all images to use latest version of Alpine base image ## Azure Industrial IoT Platform Release 2.8.5 We are pleased to announce the release of version 2.8.5 of our Industrial IoT Platform components as latest patch update of the 2.8 Long-Term Support (LTS) release. This release contains important security updates fixes, performance optimizations and bugfixes. ### Changes in 2.8.5 - [All] Update to latest dependencies. - [All] Use latest OPC UA .net stack 371. - [OPC Publisher] Fix a crash in the diagnostics output timer in orchestrated mode when endpoint url is reported null. (#1955) ## Azure Industrial IoT Platform Release 2.8.4 We are pleased to announce the release of version 2.8.4 of our Industrial IoT Platform components as latest patch update of the 2.8 Long-Term Support (LTS) release. This release contains important security updates fixes, performance optimizations and bugfixes. ### IMPORTANT - PLEASE READ - IoT Edge 1.1 LTS will be going out of support on 12/13/2022, please [update your IoT Edge gateways to IoT Edge 1.4 LTS](https://learn.microsoft.com/azure/iot-edge/how-to-update-iot-edge). > To continue deploying the 1.1 LTS modules to your environment follow [these instructions](./opc-publisher/readme.md#getting-started). - Windows container images are no longer supported in IoT Edge 1.4 and consequentially have been removed from this release. Please use [IoT Edge for Linux on Windows (EFLOW) 1.4](https://learn.microsoft.com/windows/iot/iot-enterprise/azure-iot-edge-for-linux-on-windows) as your IoT Edge environment on Windows. > IoT Edge 1.4 LTS EFLOW is supported as a Preview Feature in this release. - You must update your Windows based IoT Edge environment to EFLOW **ahead of deploying the platform**. - Simulation deployed as part of the ./deploy.ps1 script now deploys EFLOW on a Windows VM Host (Preview Feature). This requires nested virtualization. The Azure subscription and chosen region must support Standard_D4_v4 VM which supports nested virtualization or deployment of simulated Windows gateway will be skipped. - Network scanning on IoT Edge 1.4 LTS EFLOW using OPC Discovery is not supported yet. This applies to the deployed [simulation environment](./web-api/readme.md#getting-started) and engineering tool. You can register servers using a discovery url using the [registry service's registration REST API](./web-api/api.md). ### Changes in 2.8.4 - Updated .net to .net 6.0 LTS from .net core 3.1 LTS which will be going out of support on 12/13/2022. - Updated nuget dependencies to their .net 6 counterpart or to their latest compatible release. - [All IoT Edge modules] Updated IoT Edge dependency to IoT Edge 1.4 LTS from 1.1 LTS which will be going out of support on 12/13/2022. - [All IoT Edge modules] (Preview) Support for [IoT Edge EFLOW 1.4 LTS](https://learn.microsoft.com/windows/iot/iot-enterprise/azure-iot-edge-for-linux-on-windows) - [OPC Publisher] Fix for orchestrator infinite loop on publisher worker document update (#1870) - [OPC Publisher] Rate limit OPC Publisher orchestrator requests. - [OPC Publisher] More explicit error logs in orchestrated mode, also showing transient exceptions in logs for better troubleshooting. - [OPC Publisher] Add --bi / --batchtriggerinterval command line option to define interval in milliseconds. (#1893) - [Deployment] IAI: Upgraded Kubernetes version in AKS from 1.22.6 to 1.23.12. (#1885) - [Deployment] Increased proxy-connect-timeout of NGINX from default 5 seconds to 30. (#1871) - [OPC Publisher] (Preview) User can set the Data change trigger value of the Data change filter type either as a default for all or per subscription (#1830). - [OPC Publisher] (Preview) Allow comment in OpcPublisher Configuration when Validation is used (#1892) - [All IoT Edge modules] Add a configuration option to set security option RejectUnknownRevocationStatus (#1777) - [All IoT Edge modules] Add mandatory field for edgeHub in the base deployment template to support cloning deployments (#1764) - [OPC Discovery] Ensure duplicate discovery urls override previous url instead of causing exception (#1903, #1902) - [OPC Discovery] Enginering tool ad hoc discovery fails with "capacity must be non negative" error found during bug bash. (#1907) - [OPC Twin] Fix sessions in Twin are not closed when endpoint is deactivated. (#1910) For features that are marked as Preview, please report any issues through GitHub issues. ### Known issues - Under EFLOW, by default the Application instance certificate is generated by each module and not automatically shared. To work around this, configure EFLOW and modules deployed manually to use a [shared host volume](https://learn.microsoft.com/azure/iot-edge/how-to-share-windows-folder-to-vm?view=iotedge-2018-06) to map the pki folders. - Discovering using IP Address and port ranges is not supported on EFLOW. ## Azure Industrial IoT Platform Release 2.8.3 We are pleased to announce the release of version 2.8.3 of our Industrial IoT Platform components as a third patch update of the 2.8 Long-Term Support (LTS) release. This release contains important security updates fixes, performance optimizations and bugfixes. > IMPORTANT > We suggest updating from the version 2.5 or later to ensure secure operations of your deployment. OPC Publisher 2.8.3 addresses backwards compatibilities issues with version 2.5.x. ### Security related fixes in 2.8.3 - Updated OPC UA Stack NuGet to the latest (1.4.368.58) addressing various security issues - Upgraded SSH.NET package to 2020.0.2 to address [CVE-2022-29245](https://nvd.nist.gov/vuln/detail/CVE-2022-29245). ### Fundamentals related fixes in 2.8.3 - [OPC Publisher] option to route telemetry to a specific output route was added ### Bug fixes in 2.8.3 - [OPC Publisher] Removed timestamps from metrics and updated the affected dashboard queries - [OPC Publisher] Fixed issue with large configurations when publisher running in orchestrated mode related to CosmosDB continuation tokens handling - [OPC Publisher] Publisher 2.8.2: Could not send worker heartbeat - eventually crashing and not restarting #1701 - [OPC Publisher] Fix for false alarm sequence number mismatch warning in case of keep-alive messages - [Deployment] TLS certificate broken after upgrading of the AKS cluster #1389 - [Registry API] Number of MaxWorker not returned while reading publisher configuration ## Azure Industrial IoT Platform Release 2.8.2 We are pleased to announce the release of version 2.8.2 of our Industrial IoT Platform components as a second patch update of the 2.8 Long-Term Support (LTS) release. This release contains important backward compatibility fixes with version 2.5.x, performance optimizations as well as security updates and bugfixes. > IMPORTANT > We suggest to update from version 2.5 or later to ensure secure operations of your deployment. OPC Publisher 2.8.2 addresses backwards compatibilities issues with version 2.5.x. ### Fundamentals related fixes in 2.8.2 - [OPC Publisher] Implemented the backwards compatible [Direct Methods API](./opc-publisher/directmethods.md) of 2.5.x publisher. The migration path is documented [here](./opc-publisher/migrationpath.md) - [OPC Publisher] Optimizations in opc subscriptions/monitored items management in case of configuration changes. Only incremental changes are applied to a subscription. - [OPC Publisher] Added support for setting QueueSize on monitored items for publisher in standalone mode. - [OPC Publisher] Hardened the retry mechanism for activating monitored items. ### Backwards Compatibility Notes for release 2.8.2 - [OPC Publisher] NodeId shows up now in telemetry in the exact format as specified in the configuration. Before 2.8.2, the NodeId was always reported as `Namespace#NodeId` > E.g. : When configuring in pn.json file a NodeId like `nsu=http://mynamespace.com/;i=1` > > - OPC Publisher 2.8.1 telemetry reports `http://mynamespace.com/#i=1` > - OPC Publisher 2.8.2 telemetry reports `nsu=http://mynamespace.com/;i=1` > - [OPC Publisher] configuration of duplicate nodeIds in the same data set writer, respectively same subscription is no longer allowed. ## Azure Industrial IoT Platform Release 2.8.1 We are pleased to announce the release of version 2.8.1 of our Industrial IoT Platform components as the first patch update of the 2.8 Long-Term Support (LTS) release. This release contains important security updates, bugfixes and performance optimizations. > IMPORTANT: Please note that OPC Publisher 2.8.1 is not backwards compatible with version 2.5.x. ## Azure Industrial IoT Platform Release 2.8 We are pleased to announce the release of version 2.8 of our Industrial IoT Platform as well as the declaration of Long-Term Support (LTS) for this version. While we continue to develop and release updates to our ongoing projects on GitHub, we now also offer a branch that will only get critical bug fixes and security updates starting in July 2021. Customers can rely upon a longer-term support lifecycle for these LTS builds, providing stability and assurance for the planning on longer time horizons our customers require. The LTS branch offers customers a guarantee that they will benefit from any necessary security or critical bug fixes with minimal impact to their deployments and module interactions. At the same time, customers can access the latest updates in the main branch to keep pace with the latest developments and fastest cycle time for product updates. > IMPORTANT: We suggest to update from the version 2.6 or later to ensure secure operations of your deployment. 2.8.0 is not backwards compatible with version 2.5.x Version 2.8.0 includes an updated version of the IoT Edge Runtime, a new Linux base image for all Linux deployments, and several bug fixes. The detailed changes can be found [here](https://github.com/Azure/Industrial-IoT/releases/tag/2.8.0). ================================================ FILE: e2e-tests/.gitignore ================================================ .env ================================================ FILE: e2e-tests/Directory.Build.props ================================================  ================================================ FILE: e2e-tests/IIoTPlatform-E2E-Tests.slnx ================================================ ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/Config/IContainerRegistryConfig.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.Config { /// /// Container registry client configuration /// public interface IContainerRegistryConfig { /// /// Server url /// string ContainerRegistryServer { get; } /// /// Namespace /// string ImagesNamespace { get; } /// /// User /// string ContainerRegistryUser { get; } /// /// Password /// string ContainerRegistryPassword { get; } /// /// Version /// string ImagesTag { get; } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/Config/IDeviceConfig.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.Config { /// /// IoT Edge device configuration /// public interface IDeviceConfig { /// /// IoT Edge device id /// string DeviceId { get; } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/Config/IIoTEdgeConfig.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.Config { /// /// IoT Edge configuration /// public interface IIoTEdgeConfig { /// /// IoT Edge version /// string EdgeVersion { get; } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/Config/IIoTHubConfig.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.Config { /// /// IoT Hub configuration /// public interface IIoTHubConfig { /// /// IoT Hub connection string /// string IoTHubConnectionString { get; } /// /// The connection string of the EventHub-compatible endpoint of the IoTHub /// string IoTHubEventHubConnectionString { get; } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/Config/IOpcPlcConfig.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.Config { public interface IOpcPlcConfig { /// /// Semicolon separated URLs to load published_nodes.json from OPC-PLCs /// string Urls { get; } /// /// Semicolon separated ip addresses of the OPC-PLCs /// string Ips { get; } /// /// TenantId for SP /// string TenantId { get; } /// /// Resource Group /// string ResourceGroupName { get; } /// /// Subscription Id /// string SubscriptionId { get; } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/Config/ISshConfig.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.Config { public interface ISshConfig { /// /// Username used for ssh authentication /// string Username { get; } /// /// Public key used for ssh authentication /// string PublicKey { get; } /// /// Private key used for ssh authentication /// string PrivateKey { get; } /// /// DNS Host name of machine to ssh into /// string Host { get; } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/GlobalSuppressions.cs ================================================ // This file is used by Code Analysis to maintain SuppressMessage // attributes that are applied to this project. // Project-level suppressions either have no target or are given // a specific target and scoped to a namespace, type, member, etc. using System.Diagnostics.CodeAnalysis; [assembly: SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "xunit")] ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/MessagingMode.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests { /// /// Message modes /// public enum MessagingMode { /// /// Network and dataset messages (default) /// PubSub, /// /// Monitored item samples /// Samples } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/OpcPublisher-AE-E2E-Tests.csproj ================================================  net9.0 OpcPublisherAEE2ETests false runtime; build; native; contentfiles; analyzers; buildtransitive all runtime; build; native; contentfiles; analyzers; buildtransitive all PreserveNewest PreserveNewest ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/Properties/AssemblyInfo.cs ================================================ using System.Runtime.InteropServices; using Xunit; // In SDK-style projects such as this one, several assembly attributes that were historically // defined in this file are now automatically added during build and populated with // values defined in project properties. For details of which attributes are included // and how to customise this process see: https://aka.ms/assembly-info-properties // Setting ComVisible to false makes the types in this assembly not visible to COM // components. If you need to access a type in this assembly from COM, set the ComVisible // attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM. [assembly: Guid("275eb2f6-3c8c-42e3-b3a7-d793b0363134")] // deactivate run of test in parallel [assembly: CollectionBehavior(DisableTestParallelization = true)] ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/PublishedNodesConfigurations.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests { using Newtonsoft.Json.Linq; internal static partial class TestConstants { internal static class PublishedNodesConfigurations { public static string SimpleEvents(string host, uint port, string writerId) { return $$""" [ { "EndpointUrl": "opc.tcp://{{host}}:{{port}}", "UseSecurity": true, "DataSetWriterId":"{{writerId}}", "OpcNodes": [ { "Id": "ns=0;i=2253", "QueueSize": 10, "DisplayName": "SimpleEvents", "EventFilter": { "SelectClauses": [ { "TypeDefinitionId": "i=2041", "BrowsePath": [ "EventId" ] }, { "TypeDefinitionId": "i=2041", "BrowsePath": [ "Message" ] }, { "TypeDefinitionId": "nsu=http://microsoft.com/Opc/OpcPlc/SimpleEvents;i=2", "BrowsePath": [ "http://microsoft.com/Opc/OpcPlc/SimpleEvents#CycleId" ] }, { "TypeDefinitionId": "nsu=http://microsoft.com/Opc/OpcPlc/SimpleEvents;i=2", "BrowsePath": [ "http://microsoft.com/Opc/OpcPlc/SimpleEvents#CurrentStep" ] } ], "WhereClause": { "Elements": [ { "FilterOperator": "OfType", "FilterOperands": [ { "Value": "nsu=http://microsoft.com/Opc/OpcPlc/SimpleEvents;i=2" } ] } ] } } } ] } ] """; } public static JArray SimpleEventFilter( string typeDefinitionId = "i=2782") { return new JArray( new JObject( new JProperty("Id", "i=2253"), new JProperty("QueueSize", 1000), new JProperty("EventFilter", new JObject( new JProperty("TypeDefinitionId", typeDefinitionId))))); } public static JArray PendingConditionForAlarmsView() { return new JArray( new JObject( new JProperty("Id", "i=2253"), new JProperty("QueueSize", 10), new JProperty("EventFilter", new JObject( new JProperty("TypeDefinitionId", "i=2915"))), new JProperty("ConditionHandling", new JObject( new JProperty("UpdateInterval", 10), new JProperty("SnapshotInterval", 20) )))); } } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/RegistryHelper.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests { using OpcPublisherAEE2ETests.Deploy; using OpcPublisherAEE2ETests.TestExtensions; using Azure.IIoT.OpcUa.Publisher.Models; using Microsoft.Azure.Devices; using Microsoft.Azure.Devices.Common.Exceptions; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Xunit; /// /// Helper for managing IoT Hub device registry. /// public sealed class RegistryHelper : IDisposable { /// /// Constructor of RegistryHelper class. /// /// Shared context for E2E tests public RegistryHelper(IIoTPlatformTestContext context) { _context = context ?? throw new ArgumentNullException(nameof(context)); RegistryManager = RegistryManager.CreateFromConnectionString(context.IoTHubConfig.IoTHubConnectionString); } /// /// Wait until IIoT modules are in Connected state. /// /// IoT Edge device id /// Cancellation token /// List of modules to wait for, defaults to ModuleNamesDefault if not specified /// public async Task WaitForIIoTModulesConnectedAsync( string deviceId, CancellationToken ct, IReadOnlyList moduleNames = null ) { moduleNames ??= ModuleNamesDefault; var sw = Stopwatch.StartNew(); try { while (true) { var modules = (await RegistryManager.GetModulesOnDeviceAsync(deviceId, ct).ConfigureAwait(false)).ToList(); var connectedModulesCount = modules .Where(m => moduleNames.Contains(m.Id)) .Count(m => m.ConnectionState == DeviceConnectionState.Connected); if (connectedModulesCount == moduleNames.Count) { _context.OutputHelper.WriteLine($"All required IoT Edge modules are connected! (took {sw.Elapsed})"); return; } var m = modules.Count == 0 ? "No modules" : modules .Select(m => $"{m.Id}({m.ConnectionState})") .Aggregate((a, b) => a + ", " + b); //_context.OutputHelper.WriteLine($"Waiting for IoT Edge modules: {m} on {deviceId}"); await Task.Delay(TestConstants.DefaultDelayMilliseconds, ct).ConfigureAwait(false); } } catch (OperationCanceledException) { _context.OutputHelper.WriteLine($"Waiting for IoT Edge modules to be loaded timeout timeout after {sw.Elapsed} - please check iot edge device for details"); throw; } catch (Exception e) { _context.OutputHelper.WriteLine($"Error {e.Message} occurred while waiting for edge Modules to be loaded after {sw.Elapsed}"); throw; } } /// /// Wait until IIoT modules do not exist anymore on edge device /// /// IoT Edge device id /// Cancellation token /// List of modules to wait for, defaults to ModuleNamesDefault if not specified /// public async Task WaitForIIoTModulesRemovedAsync( string deviceId, CancellationToken ct, IReadOnlyList moduleNames = null ) { moduleNames ??= ModuleNamesDefault; var sw = Stopwatch.StartNew(); try { while (!ct.IsCancellationRequested) { var modules = (await RegistryManager.GetModulesOnDeviceAsync(deviceId, ct).ConfigureAwait(false)).ToList(); if (!modules.Any(m => moduleNames.Contains(m.Id))) { _context.OutputHelper.WriteLine($"All IoT Edge modules were removed (took {sw.Elapsed})"); return; } var m = modules .Select(m => $"{m.Id}({m.ConnectionState})") .Aggregate((a, b) => a + ", " + b); _context.OutputHelper.WriteLine($"Waiting for IoT Edge modules to undeploy: {m} on {deviceId}"); await Task.Delay(TestConstants.DefaultDelayMilliseconds, ct).ConfigureAwait(false); } } catch (OperationCanceledException) { _context.OutputHelper.WriteLine($"Waiting for IoT Edge modules to be removed timeout timeout after {sw.Elapsed} - please check iot edge device for details"); throw; } catch (Exception e) { _context.OutputHelper.WriteLine($"Error {e.Message} occurred while waiting for edge Modules to be removed after {sw.Elapsed}"); throw; } } /// /// Undeploy publisher /// /// /// /// /// public async Task RestartStandalonePublisherAsync( MessagingMode messagingMode = MessagingMode.Samples, bool fullRedeploy = false, CancellationToken ct = default) { var publisher = new IoTHubPublisherDeployment(_context, messagingMode); if (fullRedeploy) { // Delete layered edge deployment. await publisher.DeleteLayeredDeploymentAsync(ct); await TestHelper.SwitchToStandaloneModeAndPublishNodesAsync("[]", _context, ct); await _context.RegistryHelper.WaitForIIoTModulesRemovedAsync(_context.DeviceConfig.DeviceId, ct, new string[] { publisher.ModuleName }); } else { await TestHelper.SwitchToStandaloneModeAndPublishNodesAsync("[]", _context, ct); await TestHelper.RestartAsync(_context, publisher.ModuleName, ct); } } /// /// Create publisher deployment /// /// /// /// public async Task DeployStandalonePublisherAsync( MessagingMode messagingMode = MessagingMode.Samples, CancellationToken ct = default) { // Create base edge deployment. var edgeBase = new IoTHubEdgeBaseDeployment(_context); var baseDeploymentResult = await edgeBase.CreateOrUpdateLayeredDeploymentAsync(ct); Assert.True(baseDeploymentResult, "Failed to create/update new edge base deployment."); _context.OutputHelper.WriteLine("Created/Updated new edge base deployment."); await RestartStandalonePublisherAsync(messagingMode, false, ct); await TestHelper.SwitchToStandaloneModeAsync(_context, ct); await TestHelper.CleanPublishedNodesJsonFilesAsync(_context, ct); // Create new layered edge deployment. var publisher = new IoTHubPublisherDeployment(_context, messagingMode); var layeredDeploymentResult = await publisher.CreateOrUpdateLayeredDeploymentAsync(ct); Assert.True(layeredDeploymentResult, "Failed to create/update layered deployment for publisher module."); _context.OutputHelper.WriteLine("Created/Updated layered deployment for publisher module."); // We will wait for module to be deployed. await _context.RegistryHelper.WaitForSuccessfulDeploymentAsync(publisher.GetDeploymentConfiguration(), ct); await _context.RegistryHelper.WaitForIIoTModulesConnectedAsync(_context.DeviceConfig.DeviceId, ct, new string[] { publisher.ModuleName }); // We've observed situations when even after the above waits the module did not yet restart. // That leads to situations where the publishing of nodes happens just before the restart to apply // new container creation options. After restart persisted nodes are picked up, but on the telemetry side // the restart causes dropped messages to be detected. That happens because just before the restart OPC Publisher // manages to send some telemetry. This wait makes sure that we do not run the test while restart is happening. // await Task.Delay(TestConstants.AwaitInitInMilliseconds, ct); _context.OutputHelper.WriteLine("OPC Publisher module is up and running."); return publisher.ModuleName; } /// /// Wait until one successful deployment is reported. /// /// /// public async Task WaitForSuccessfulDeploymentAsync( Configuration deploymentConfiguration, CancellationToken ct) { var sw = Stopwatch.StartNew(); Configuration lastConfiguration = null; try { while (true) { ct.ThrowIfCancellationRequested(); var activeConfiguration = await RegistryManager.GetConfigurationAsync(deploymentConfiguration.Id, ct) .ConfigureAwait(false); if (activeConfiguration != null) { lastConfiguration = activeConfiguration; if (Equals(activeConfiguration, deploymentConfiguration) #if SYSTEM_METRICS_BUG && activeConfiguration.SystemMetrics.Results.TryGetValue("reportedSuccessfulCount", out var value) && value >= 1 #endif ) { _context.OutputHelper.WriteLine($"All required IoT Edge modules are deployed! (took {sw.Elapsed})"); return; } } await Task.Delay(TestConstants.DefaultDelayMilliseconds, ct).ConfigureAwait(false); } } catch (OperationCanceledException) { _context.OutputHelper.WriteLine($"Waiting for IoT Edge modules to be loaded timeout after {sw.Elapsed} - please check iot edge device for details"); throw; } catch (Exception e) { _context.OutputHelper.WriteLine($"Error {e.Message} occurred while waiting for edge Modules after {sw.Elapsed}"); throw; } finally { _context.OutputHelper.WriteLine($"Waiting for IoT Edge module got configuration: {JsonSerializer.Serialize(lastConfiguration, kIndented)}..."); } } private static readonly JsonSerializerOptions kIndented = new() { WriteIndented = true }; /// /// Delete deployment configuration /// /// /// Cancellation token public async Task DeleteConfigurationAsync(string configurationId, CancellationToken ct = default) { while (true) { var getConfig = await RegistryManager.GetConfigurationAsync(configurationId, ct).ConfigureAwait(false); if (getConfig == null) { return; } // First try create configuration try { await RegistryManager.RemoveConfigurationAsync(configurationId, ct).ConfigureAwait(false); _context.OutputHelper.WriteLine($"Deleted configuration {configurationId}"); } catch { } } } /// /// Create or update deployment configuration /// /// /// Cancellation token public async Task CreateOrUpdateConfigurationAsync( Configuration configuration, CancellationToken ct = default ) { try { var getConfig = await RegistryManager.GetConfigurationAsync(configuration.Id, ct).ConfigureAwait(false); if (getConfig == null) { // First try create configuration try { _context.OutputHelper.WriteLine("Add new IoT Hub device configuration"); return await RegistryManager.AddConfigurationAsync(configuration, ct).ConfigureAwait(false); } catch (DeviceAlreadyExistsException) { // Technically update below should now work but for some reason it does not. // Remove and re-add in case we are forcing updates. _context.OutputHelper.WriteLine("IoT Hub device configuration already existed, remove and recreate it"); await RegistryManager.RemoveConfigurationAsync(configuration.Id, ct).ConfigureAwait(false); return await RegistryManager.AddConfigurationAsync(configuration, ct).ConfigureAwait(false); } } if (Equals(configuration, getConfig)) { return getConfig; } _context. OutputHelper.WriteLine("Existing IoT Hub device configuration is different, remove and recreate it"); await RegistryManager.RemoveConfigurationAsync(configuration.Id, ct).ConfigureAwait(false); return await RegistryManager.AddConfigurationAsync(configuration, ct).ConfigureAwait(false); } catch (Exception e) { _context.OutputHelper.WriteLine("Error while creating or updating IoT Hub device configuration! {0}", e.Message); throw; } } /// /// Check equality of two deployment configurations. /// /// /// public static bool Equals(Configuration c0, Configuration c1) { if (c0.Id != c1.Id) { return false; } if (c0.TargetCondition != c1.TargetCondition) { return false; } if (c0.Priority != c1.Priority) { return false; } var c0ModulesContentCount = c0.Content?.ModulesContent?.Count ?? 0; var c1ModulesContentCount = c1.Content?.ModulesContent?.Count ?? 0; if (c0ModulesContentCount == 0 && c1ModulesContentCount == 0) { return true; } else if (c0ModulesContentCount != c1ModulesContentCount) { return false; } // After the previous checks we know that both have the same non-zero number of module contents. foreach (var moduleName in c1.Content.ModulesContent.Keys) { if (c0.Content.ModulesContent.TryGetValue(moduleName, out var moduleContent0)) { var moduleContent1 = c1.Content.ModulesContent[moduleName]; var diffCount = moduleContent0 .Count(entry => moduleContent1[entry.Key].ToString() != entry.Value.ToString()); if (diffCount > 0) { return false; } } else { return false; } } return true; } /// public void Dispose() { RegistryManager.Dispose(); } /// /// Access To Registry Manager /// public RegistryManager RegistryManager { get; } /// /// Default value for IIoT module names. /// public static IReadOnlyList ModuleNamesDefault { get; } = new string[] { "publisher", "twin", "discovery" }; private readonly IIoTPlatformTestContext _context; } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/Standalone/C_EventNamespaceTestTheory.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.Standalone { using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using TestExtensions; using TestModels; using Xunit; using Xunit.Abstractions; /// /// The test theory using different (ordered) test cases to go thru all required steps of publishing OPC UA node /// [TestCaseOrderer(TestCaseOrderer.FullName, TestConstants.TestAssemblyName)] [Trait(TestConstants.TraitConstants.PublisherModeTraitName, TestConstants.TraitConstants.PublisherModeTraitValue)] public class CEventNamespaceTestTheory : DynamicAciTestBase, IClassFixture { public CEventNamespaceTestTheory(IIoTStandaloneTestContext context, ITestOutputHelper output) : base(context, output) { } [Fact, PriorityOrder(10)] public Task TestDeployAci() { return TestHelper.CreateSimulationContainerAsync(_context, new List { "/bin/sh", "-c", "./opcplc --autoaccept --ses --pn=50000" }, _timeoutToken); } [Fact, PriorityOrder(11)] public async Task TestVerifyIntegerNamespaceExpectSimpleEventsInHub() { // Arrange var pnJson = SimpleEvents( "ns=0;i=2041", "0:Message", "ns=6;i=2", "6:CycleId", "ns=6;i=2"); await TestHelper.SwitchToStandaloneModeAndPublishNodesAsync(pnJson, _context, _timeoutToken); var messages = _consumer.ReadMessagesFromWriterIdAsync(_writerId, 1, _timeoutToken); // Act var payloads = await messages.Select(v => v.Payload).ToListAsync(_timeoutToken); // Assert VerifyPayloads(payloads); } [Fact, PriorityOrder(12)] public async Task TestVerifyStringNamespaceExpectSimpleEventsInHub() { // Arrange var pnJson = SimpleEvents( "i=2041", "Message", "nsu=http://microsoft.com/Opc/OpcPlc/SimpleEvents;i=2", "http://microsoft.com/Opc/OpcPlc/SimpleEvents#CycleId", "nsu=http://microsoft.com/Opc/OpcPlc/SimpleEvents;i=2"); await TestHelper.SwitchToStandaloneModeAndPublishNodesAsync(pnJson, _context, _timeoutToken); var messages = _consumer.ReadMessagesFromWriterIdAsync(_writerId, 1, _timeoutToken); // Act var payloads = await messages.Select(v => v.Payload).ToListAsync(_timeoutToken); // Assert VerifyPayloads(payloads); } [Fact, PriorityOrder(13)] public async Task TestVerifyIntegerNamespaceExpectFilteredSimpleEventsInHub() { // Arrange var pnJson = _context.PublishedNodesJson( 50000, _writerId, TestConstants.PublishedNodesConfigurations.SimpleEventFilter("ns=6;i=2")); await TestHelper.SwitchToStandaloneModeAndPublishNodesAsync(pnJson, _context, _timeoutToken); var messages = _consumer.ReadMessagesFromWriterIdAsync(_writerId, 1, _timeoutToken); // Act var payloads = await messages.Select(v => v.Payload).ToListAsync(_timeoutToken); // Assert VerifyPayloads(payloads); } [Fact, PriorityOrder(14)] public async Task TestVerifyStringNamespaceExpectFilteredSimpleEventsInHub() { // Arrange var pnJson = _context.PublishedNodesJson( 50000, _writerId, TestConstants.PublishedNodesConfigurations.SimpleEventFilter("nsu=http://microsoft.com/Opc/OpcPlc/SimpleEvents;i=2")); await TestHelper.SwitchToStandaloneModeAndPublishNodesAsync(pnJson, _context, _timeoutToken); var messages = _consumer.ReadMessagesFromWriterIdAsync(_writerId, 1, _timeoutToken); // Act var payloads = await messages.Select(v => v.Payload).ToListAsync(_timeoutToken); // Assert VerifyPayloads(payloads); } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/Standalone/C_EventsStressTestTheory.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.Standalone { using FluentAssertions; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using static System.TimeSpan; using TestExtensions; using TestModels; using Xunit; using Xunit.Abstractions; /// /// The test theory submitting a high load of event messages /// [TestCaseOrderer(TestCaseOrderer.FullName, TestConstants.TestAssemblyName)] [Trait(TestConstants.TraitConstants.PublisherModeTraitName, TestConstants.TraitConstants.PublisherModeTraitValue)] public class CEventsStressTestTheory : DynamicAciTestBase, IClassFixture { public CEventsStressTestTheory(IIoTStandaloneTestContext context, ITestOutputHelper output) : base(context, output) { } [Fact, PriorityOrder(10)] public async Task TestACIVerifyEnd2EndThroughputAndLatency() { // Settings const int eventIntervalPerInstanceMs = 400; const int eventInstances = 40; const int instances = 10; const int nSeconds = 20; const int nSecondSkipFirst = 10; const int nSecondSkipLast = 6; // Arrange await TestHelper.CreateSimulationContainerAsync(_context, new List { "/bin/sh", "-c", $"./opcplc --autoaccept --ei={eventInstances} --er={eventIntervalPerInstanceMs} --pn=50000" }, _timeoutToken, numInstances: instances); var messages = _consumer.ReadMessagesFromWriterIdAsync(_writerId, -1, _timeoutToken); // Act var pnJson = _context.PublishedNodesJson( 50000, _writerId, TestConstants.PublishedNodesConfigurations.SimpleEventFilter("i=2041")); // OPC-UA BaseEventType await TestHelper.SwitchToStandaloneModeAndPublishNodesAsync(pnJson, _context, _timeoutToken); const int nSecondsTotal = nSeconds + nSecondSkipFirst + nSecondSkipLast; var fullData = await messages .TakeWhile(_context, (first, current) => current.EnqueuedTime - first.EnqueuedTime <= FromSeconds(nSecondsTotal)) // Get time of event attached Server node .Select(e => (e.EnqueuedTime, SourceTimestamp: e.Payload.ReceiveTime.Value)) .ToListAsync(_timeoutToken); // Assert throughput // Trim first few and last seconds of data, since Publisher polls PLCs // at different times var intervalStart = fullData.Min(d => d.SourceTimestamp) + FromSeconds(nSecondSkipFirst); var intervalEnd = fullData.Max(d => d.SourceTimestamp) - FromSeconds(nSecondSkipLast); var intervalDuration = intervalEnd - intervalStart; var eventData = fullData.Where(d => d.SourceTimestamp > intervalStart && d.SourceTimestamp < intervalEnd).ToList(); // Bin events by 1-second interval to compute event rate histogram var eventRatesBySecond = eventData .GroupBy(s => s.SourceTimestamp.Value.Truncate(FromSeconds(1))) .Select(g => g.Count()) .ToArray()[1..^1]; const int expectedEventsPerSecond = instances * eventInstances * 1000 / eventIntervalPerInstanceMs; _context.OutputHelper.WriteLine($"Event rates per second, by second: {string.Join(',', eventRatesBySecond)} e/s (expected {expectedEventsPerSecond} e/s)"); // Assert latency var end2EndLatency = eventData .ConvertAll(v => v.EnqueuedTime - v.SourceTimestamp); end2EndLatency.Min().Should().BePositive(); end2EndLatency.Average(v => v.Value.TotalMilliseconds).Should().BeLessThan(8000); // var eventRate = eventData.Count / intervalDuration.Value.TotalSeconds; var eventRate = eventRatesBySecond.Average(); intervalDuration.Should().BeGreaterThan(FromSeconds(nSeconds)); eventData.Count.Should().BeGreaterThan(nSeconds * expectedEventsPerSecond, "Publisher should produce data continuously"); eventRate.Should().BeApproximately( expectedEventsPerSecond, expectedEventsPerSecond / 10d, "Publisher should match PLC event rate"); var (average, stDev) = DescriptiveStats(eventRatesBySecond); average.Should().BeApproximately( expectedEventsPerSecond, expectedEventsPerSecond / 10d, "Publisher should match PLC event rate"); stDev.Should().BeLessThan(expectedEventsPerSecond / 3d, "Publisher should sustain PLC event rate"); } private static (double average, double stDev) DescriptiveStats(IReadOnlyCollection population) { var average = population.Average(); var stDev = Math.Sqrt(population.Sum(v => (v - average) * (v - average)) / population.Count); return (average, stDev); } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/Standalone/C_PendingConditionsTestTheory.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.Standalone { using OpcPublisherAEE2ETests.TestExtensions; using OpcPublisherAEE2ETests.TestModels; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; /// /// The test theory using different (ordered) test cases to go thru all required steps of publishing OPC UA node /// [TestCaseOrderer(TestCaseOrderer.FullName, TestConstants.TestAssemblyName)] [Trait(TestConstants.TraitConstants.PublisherModeTraitName, TestConstants.TraitConstants.PublisherModeTraitValue)] public class CPendingConditionsTestTheory : DynamicAciTestBase, IClassFixture { public CPendingConditionsTestTheory(IIoTStandaloneTestContext context, ITestOutputHelper output) : base(context, output) { } [Fact, PriorityOrder(10)] public async Task TestVerifyDataAvailableAtIoTHubExpectPendingAlarmsView() { // Arrange await TestHelper.CreateSimulationContainerAsync(_context, new List {"/bin/sh", "-c", "./opcplc --autoaccept --alm --pn=50000"}, _timeoutToken); var messages = _consumer.ReadConditionMessagesFromWriterIdAsync(_writerId, 1, _timeoutToken); // Act var pnJson = _context.PublishedNodesJson( 50000, _writerId, TestConstants.PublishedNodesConfigurations.PendingConditionForAlarmsView()); await TestHelper.SwitchToStandaloneModeAndPublishNodesAsync(pnJson, _context, _timeoutToken); // Act var payloads = await messages.Select(v => v.Payload).ToListAsync(_timeoutToken); // Assert ValidatePendingConditionsView(payloads); } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/Standalone/C_PublishConditionsTestTheory.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.Standalone { using FluentAssertions; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using static System.TimeSpan; using TestExtensions; using TestModels; using Xunit; using Xunit.Abstractions; /// /// The test theory using different (ordered) test cases to go thru all required steps of publishing OPC UA node /// [TestCaseOrderer(TestCaseOrderer.FullName, TestConstants.TestAssemblyName)] [Trait(TestConstants.TraitConstants.PublisherModeTraitName, TestConstants.TraitConstants.PublisherModeTraitValue)] public class CPublishConditionsTestTheory : DynamicAciTestBase, IClassFixture { private static readonly TimeSpan Precision = FromMilliseconds(500); public CPublishConditionsTestTheory(IIoTStandaloneTestContext context, ITestOutputHelper output) : base(context, output) { } [Fact, PriorityOrder(11)] public async Task TestACIVerifyDataAvailableAtIoTHubExpectNumberOfEventsGreaterThanZero() { // Arrange await TestHelper.CreateSimulationContainerAsync(_context, new List {"/bin/sh", "-c", "./opcplc --autoaccept --dalm=files/sc001.json --pn=50000"}, _timeoutToken, "opc-plc-files/sc001.json"); var messages = _consumer.ReadMessagesFromWriterIdAsync(_writerId, 10000, _timeoutToken, _context); // Act var pnJson = _context.PublishedNodesJson( 50000, _writerId, TestConstants.PublishedNodesConfigurations.SimpleEventFilter()); await TestHelper.SwitchToStandaloneModeAndPublishNodesAsync(pnJson, _context, _timeoutToken); const int nMessages = 6; var payloads = await messages .Select(e => e.Payload) .Skip(nMessages) // First batch of alarms are from a ConditionRefresh, therefore not in order .SkipWhile(c => !c.Message.Value.Contains("LAST EVENT IN LOOP", StringComparison.Ordinal)) .Skip(1) .Take(nMessages) .ToListAsync(_timeoutToken); // Assert var i = -1; var doorOpen = new ConditionTypePayload { ConditionName = DataValueObject.Create("VendingMachine1_DoorOpen"), EnabledState = DataValueObject.Create("Enabled"), EnabledStateEffectiveDisplayName = DataValueObject.Create("Active | Unacknowledged"), EnabledStateId = DataValueObject.Create(true), EventType = DataValueObject.Create("i=10751"), LastSeverity = DataValueObject.Create(500), Message = DataValueObject.Create("Door Open"), Retain = DataValueObject.Create(true), Severity = DataValueObject.Create(900), SourceName = DataValueObject.Create("VendingMachine1"), SourceNode = DataValueObject.Create("http://microsoft.com/Opc/OpcPlc/DetermAlarmsInstance#s=VendingMachine1") }; VerifyPayload(payloads, ++i, null, doorOpen); VerifyPayload(payloads, ++i, FromSeconds(5), new ConditionTypePayload { ConditionName = DataValueObject.Create("VendingMachine2_LightOff"), EnabledState = DataValueObject.Create("Enabled"), EnabledStateEffectiveDisplayName = DataValueObject.Create("Active | Unacknowledged"), EnabledStateId = DataValueObject.Create(true), EventType = DataValueObject.Create("i=10637"), LastSeverity = DataValueObject.Create(500), Message = DataValueObject.Create("Light Off in machine"), Retain = DataValueObject.Create(true), Severity = DataValueObject.Create(500), SourceName = DataValueObject.Create("VendingMachine2"), SourceNode = DataValueObject.Create("http://microsoft.com/Opc/OpcPlc/DetermAlarmsInstance#s=VendingMachine2") }); VerifyPayload(payloads, ++i, Zero, new ConditionTypePayload { ConditionName = DataValueObject.Create("VendingMachine1_AD_Lamp_Off"), EnabledState = DataValueObject.Create("Enabled"), EnabledStateEffectiveDisplayName = DataValueObject.Create("Enabled"), EnabledStateId = DataValueObject.Create(true), EventType = DataValueObject.Create("i=2782"), LastSeverity = DataValueObject.Create(500), Message = DataValueObject.Create("AD Lamp Off"), Retain = DataValueObject.Create(true), Severity = DataValueObject.Create(500), SourceName = DataValueObject.Create("VendingMachine1"), SourceNode = DataValueObject.Create("http://microsoft.com/Opc/OpcPlc/DetermAlarmsInstance#s=VendingMachine1") }); VerifyPayload(payloads, ++i, FromSeconds(5), new ConditionTypePayload { ConditionName = DataValueObject.Create("VendingMachine1_DoorOpen"), EnabledState = DataValueObject.Create("Enabled"), EnabledStateEffectiveDisplayName = DataValueObject.Create("Inactive | Unacknowledged"), EnabledStateId = DataValueObject.Create(true), EventType = DataValueObject.Create("i=10751"), LastSeverity = DataValueObject.Create(900), Message = DataValueObject.Create("Door Closed"), Retain = DataValueObject.Create(false), Severity = DataValueObject.Create(500), SourceName = DataValueObject.Create("VendingMachine1"), SourceNode = DataValueObject.Create("http://microsoft.com/Opc/OpcPlc/DetermAlarmsInstance#s=VendingMachine1") }); VerifyPayload(payloads, ++i, FromSeconds(4), new ConditionTypePayload { ConditionName = DataValueObject.Create("VendingMachine1_TemperatureHigh"), EnabledState = DataValueObject.Create("Enabled"), EnabledStateEffectiveDisplayName = DataValueObject.Create("Active | Unacknowledged"), EnabledStateId = DataValueObject.Create(true), EventType = DataValueObject.Create("i=2955"), LastSeverity = DataValueObject.Create(900), Message = DataValueObject.Create("Temperature is HIGH (LAST EVENT IN LOOP)"), Retain = DataValueObject.Create(true), Severity = DataValueObject.Create(900), SourceName = DataValueObject.Create("VendingMachine1"), SourceNode = DataValueObject.Create("http://microsoft.com/Opc/OpcPlc/DetermAlarmsInstance#s=VendingMachine1") }); VerifyPayload(payloads, ++i, Zero, doorOpen); // cycling back to first message } private static void VerifyPayload(IReadOnlyList payloads, int i, TimeSpan? expectedDelay, ConditionTypePayload expectedPayload) { var p = payloads[i]; p.ConditionName.Value.Should().BeEquivalentTo(expectedPayload.ConditionName.Value); p.EventType.Value.Should().BeEquivalentTo(expectedPayload.EventType.Value); p.EnabledState.Value.Should().BeEquivalentTo(expectedPayload.EnabledState.Value); p.EnabledStateId.Value.Should().Be(expectedPayload.EnabledStateId.Value); p.EnabledStateEffectiveDisplayName.Value.Should().BeEquivalentTo(expectedPayload.EnabledStateEffectiveDisplayName.Value); p.LastSeverity.Value.Should().Be(expectedPayload.LastSeverity.Value); p.Retain.Value.Should().Be(expectedPayload.Retain.Value); p.SourceName.Value.Should().BeEquivalentTo(expectedPayload.SourceName.Value); p.SourceNode.Value.Should().BeEquivalentTo(expectedPayload.SourceNode.Value); p.ConditionId.Value.Should().StartWith("http://microsoft.com/Opc/OpcPlc/DetermAlarmsInstance#i="); p.EnabledStateEffectiveTransitionTime.Value.Should().BeCloseTo(p.ReceiveTime.Value.Value, Precision); p.EnabledStateTransitionTime.Value.Should().BeCloseTo(p.ReceiveTime.Value.Value, Precision); if (expectedDelay != null) { i.Should().BeGreaterThan(0); var transitionTime = p.EnabledStateEffectiveTransitionTime.Value - payloads[i - 1].EnabledStateEffectiveTransitionTime.Value; // TODO there is no difference in the transition time... // transitionTime.Should().BeCloseTo(expectedDelay.Value, Precision); } } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/Standalone/C_WhereClauseTestTheory.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.Standalone { using OpcPublisherAEE2ETests.TestExtensions; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; /// /// The test theory using different (ordered) test cases to go thru all required steps of publishing OPC UA node /// [TestCaseOrderer(TestCaseOrderer.FullName, TestConstants.TestAssemblyName)] [Trait(TestConstants.TraitConstants.PublisherModeTraitName, TestConstants.TraitConstants.PublisherModeTraitValue)] public class CWhereClauseTestTheory : DynamicAciTestBase, IClassFixture { public CWhereClauseTestTheory(IIoTStandaloneTestContext context, ITestOutputHelper output) : base(context, output) { } [Fact, PriorityOrder(10)] public async Task TestVerifyDataAvailableAtIoTHubExpectFieldsToMatchSimpleFilter() { // Arrange await TestHelper.CreateSimulationContainerAsync(_context, new List {"/bin/sh", "-c", "./opcplc --autoaccept --ses --pn=50000"}, _timeoutToken); var messages = _consumer.ReadMessagesFromWriterIdAsync(_writerId, -1, null, _timeoutToken); // Act var pnJson = _context.PublishedNodesJson( 50000, _writerId, TestConstants.PublishedNodesConfigurations.SimpleEventFilter("i=2041")); // OPC-UA BaseEventType await TestHelper.SwitchToStandaloneModeAndPublishNodesAsync(pnJson, _context, _timeoutToken); // take any message var (_, _, payload, _) = await messages.FirstAsync(_timeoutToken); // Assert ValidateBaseEventTypeFields(payload); } [Fact, PriorityOrder(11)] public async Task TestVerifyDataAvailableAtIoTHubExpectFieldsToMatchEventFilter() { // Arrange await TestHelper.CreateSimulationContainerAsync(_context, new List {"/bin/sh", "-c", "./opcplc --autoaccept --ses --pn=50000"}, _timeoutToken); var messages = _consumer.ReadMessagesFromWriterIdAsync(_writerId, -1, null, _timeoutToken); // Act var pnJson = _context.PublishedNodesJson( 50000, _writerId, TestConstants.PublishedNodesConfigurations.SimpleEventFilter("i=2041")); // OPC-UA BaseEventType await TestHelper.SwitchToStandaloneModeAndPublishNodesAsync(pnJson, _context, _timeoutToken); // take any message var (_, _, payload, _) = await messages .FirstAsync(_timeoutToken); // Assert ValidateBaseEventTypeFields(payload); } [Fact, PriorityOrder(12)] public async Task TestVerifyDataAvailableAtIoTHubExpectFieldsToSimpleEvents() { // Arrange await TestHelper.CreateSimulationContainerAsync(_context, new List {"/bin/sh", "-c", "./opcplc --autoaccept --ses --pn=50000"}, _timeoutToken); var messages = _consumer.ReadMessagesFromWriterIdAsync(_writerId, -1, null, _timeoutToken); // Act var pnJson = TestConstants.PublishedNodesConfigurations.SimpleEvents(_context.PlcAciDynamicUrls[0], 50000, _writerId); await TestHelper.SwitchToStandaloneModeAndPublishNodesAsync(pnJson, _context, _timeoutToken); // take any message var (_, _, payload, _) = await messages .FirstAsync(_timeoutToken); // Assert ValidateSimpleEventFields(payload); } private static void ValidateBaseEventTypeFields(JObject ev) { // navigate to the event fields (nested several layers) var fields = ev.Children().ToList(); Assert.Equal(13, fields.Count); Assert.Contains(fields, x => x.Path.EndsWith("EventId", StringComparison.Ordinal)); Assert.Contains(fields, x => x.Path.EndsWith("EventType", StringComparison.Ordinal)); Assert.Contains(fields, x => x.Path.EndsWith("SourceNode", StringComparison.Ordinal)); Assert.Contains(fields, x => x.Path.EndsWith("SourceName", StringComparison.Ordinal)); Assert.Contains(fields, x => x.Path.EndsWith("Time", StringComparison.Ordinal)); Assert.Contains(fields, x => x.Path.EndsWith("ReceiveTime", StringComparison.Ordinal)); Assert.Contains(fields, x => x.Path.EndsWith("LocalTime", StringComparison.Ordinal)); Assert.Contains(fields, x => x.Path.EndsWith("Message", StringComparison.Ordinal)); Assert.Contains(fields, x => x.Path.EndsWith("Severity", StringComparison.Ordinal)); Assert.Contains(fields, x => x.Path.EndsWith("ConditionClassId", StringComparison.Ordinal)); Assert.Contains(fields, x => x.Path.EndsWith("ConditionClassName", StringComparison.Ordinal)); Assert.Contains(fields, x => x.Path.EndsWith("ConditionSubClassId", StringComparison.Ordinal)); Assert.Contains(fields, x => x.Path.EndsWith("ConditionSubClassName", StringComparison.Ordinal)); } private static void ValidateSimpleEventFields(JObject ev) { // navigate to the event fields (nested several layers) var fields = ev.Children(); Assert.Equal(4, fields.Count()); Assert.Contains(fields, x => x.Path.EndsWith("EventId", StringComparison.Ordinal)); Assert.Contains(fields, x => x.Path.EndsWith("Message", StringComparison.Ordinal)); Assert.Contains(fields, x => x.Path.Contains("http://microsoft.com/Opc/OpcPlc/SimpleEvents#CycleId", StringComparison.Ordinal)); Assert.Contains(fields, x => x.Path.Contains("http://microsoft.com/Opc/OpcPlc/SimpleEvents#CurrentStep", StringComparison.Ordinal)); } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/Standalone/D_AlarmDirectMethodTestTheory.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.Standalone { using OpcPublisherAEE2ETests.TestExtensions; using OpcPublisherAEE2ETests.TestModels; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; /// /// The test theory using different (ordered) test cases to go thru all required steps of publishing OPC UA node /// [TestCaseOrderer(TestCaseOrderer.FullName, TestConstants.TestAssemblyName)] [Trait(TestConstants.TraitConstants.PublisherModeTraitName, TestConstants.TraitConstants.PublisherModeTraitValue)] public class DAlarmDirectMethodTestTheory : DynamicAciTestBase, IClassFixture { public DAlarmDirectMethodTestTheory(IIoTStandaloneTestContext context, ITestOutputHelper output) : base(context, output) { } [Fact, PriorityOrder(10)] public async Task TestVerifyDataAvailableAtIoTHubExpectPendingConditionsView() { // Arrange await TestHelper.CreateSimulationContainerAsync(_context, new List {"/bin/sh", "-c", "./opcplc --autoaccept --alm --pn=50000"}, _timeoutToken); var messages = _consumer.ReadConditionMessagesFromWriterIdAsync(_writerId, 1, _timeoutToken); // Act var pnJson = _context.PublishedNodesJson( 50000, _writerId, TestConstants.PublishedNodesConfigurations.PendingConditionForAlarmsView()); await PublishNodesAsync(pnJson, _timeoutToken); // take any message var payloads = await messages.Select(v => v.Payload).ToListAsync(_timeoutToken); await UnpublishAllNodesAsync(_timeoutToken); // Assert ValidatePendingConditionsView(payloads); } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/Standalone/D_EventDirectMethodTestTheory.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.Standalone { using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using TestExtensions; using TestModels; using Xunit; using Xunit.Abstractions; /// /// The test theory using different (ordered) test cases to go thru all required steps of publishing OPC UA node /// [TestCaseOrderer(TestCaseOrderer.FullName, TestConstants.TestAssemblyName)] [Trait(TestConstants.TraitConstants.PublisherModeTraitName, TestConstants.TraitConstants.PublisherModeTraitValue)] public class DEventDirectMethodTestTheory : DynamicAciTestBase, IClassFixture { public DEventDirectMethodTestTheory(IIoTStandaloneTestContext context, ITestOutputHelper output) : base(context, output) { } [Fact, PriorityOrder(10)] public Task TestDeployAci() { return TestHelper.CreateSimulationContainerAsync(_context, new List { "/bin/sh", "-c", "./opcplc --autoaccept --ses --pn=50000" }, _timeoutToken); } [Fact, PriorityOrder(11)] public async Task TestVerifyIntegerNamespaceExpectSimpleEventsInHub() { // Arrange var pnJson = SimpleEvents( "ns=0;i=2041", "0:Message", "ns=6;i=2", "6:CycleId", "ns=6;i=2"); await PublishNodesAsync(pnJson, _timeoutToken); var messages = _consumer.ReadMessagesFromWriterIdAsync(_writerId, 1, _timeoutToken); // Act var payloads = await messages.Select(v => v.Payload).ToListAsync(_timeoutToken); await UnpublishAllNodesAsync(_timeoutToken); // Assert VerifyPayloads(payloads); } [Fact, PriorityOrder(12)] public async Task TestVerifyStringNamespaceExpectSimpleEventsInHub() { // Arrange var pnJson = SimpleEvents( "i=2041", "Message", "nsu=http://microsoft.com/Opc/OpcPlc/SimpleEvents;i=2", "http://microsoft.com/Opc/OpcPlc/SimpleEvents#CycleId", "nsu=http://microsoft.com/Opc/OpcPlc/SimpleEvents;i=2"); await PublishNodesAsync(pnJson, _timeoutToken); var messages = _consumer.ReadMessagesFromWriterIdAsync(_writerId, 1, _timeoutToken); // Act var payloads = await messages.Select(v => v.Payload).ToListAsync(_timeoutToken); await UnpublishAllNodesAsync(_timeoutToken); // Assert VerifyPayloads(payloads); } [Fact, PriorityOrder(13)] public async Task TestVerifyIntegerNamespaceExpectFilteredSimpleEventsInHub() { // Arrange var pnJson = _context.PublishedNodesJson( 50000, _writerId, TestConstants.PublishedNodesConfigurations.SimpleEventFilter("ns=6;i=2")); await PublishNodesAsync(pnJson, _timeoutToken); var messages = _consumer.ReadMessagesFromWriterIdAsync(_writerId, 1, _timeoutToken); // Act var payloads = await messages.Select(v => v.Payload).ToListAsync(_timeoutToken); await UnpublishAllNodesAsync(_timeoutToken); // Assert VerifyPayloads(payloads); } [Fact, PriorityOrder(14)] public async Task TestVerifyStringNamespaceExpectFilteredSimpleEventsInHub() { // Arrange var pnJson = _context.PublishedNodesJson( 50000, _writerId, TestConstants.PublishedNodesConfigurations.SimpleEventFilter("nsu=http://microsoft.com/Opc/OpcPlc/SimpleEvents;i=2")); await PublishNodesAsync(pnJson, _timeoutToken); var messages = _consumer.ReadMessagesFromWriterIdAsync(_writerId, 1, _timeoutToken); // Act var payloads = await messages.Select(v => v.Payload).ToListAsync(_timeoutToken); await UnpublishAllNodesAsync(_timeoutToken); // Assert VerifyPayloads(payloads); } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/Standalone/DynamicAciTestBase.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.Standalone { using OpcPublisherAEE2ETests.TestExtensions; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.Messaging.EventHubs.Consumer; using FluentAssertions; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Microsoft.Azure.Devices; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Net; using System.Threading; using System.Threading.Tasks; using TestModels; using Xunit; using Xunit.Abstractions; /// /// Base class for standalone tests using dynamic ACI /// [TestCaseOrderer(TestCaseOrderer.FullName, TestConstants.TestAssemblyName)] [Trait(TestConstants.TraitConstants.PublisherModeTraitName, TestConstants.TraitConstants.PublisherModeTraitValue)] public abstract class DynamicAciTestBase : IDisposable { protected readonly IIoTStandaloneTestContext _context; protected readonly CancellationToken _timeoutToken; protected readonly EventHubConsumerClient _consumer; protected readonly string _writerId; private readonly ISerializer _serializer; private readonly ServiceClient _iotHubClient; private readonly CancellationTokenSource _timeoutTokenSource; private readonly string _iotHubPublisherDeviceName; private readonly string _iotHubPublisherModuleName; protected DynamicAciTestBase(IIoTStandaloneTestContext context, ITestOutputHelper output) { _context = context ?? throw new ArgumentNullException(nameof(context)); _context.SetOutputHelper(output); _timeoutTokenSource = new CancellationTokenSource(TestConstants.MaxTestTimeoutMilliseconds); _timeoutToken = _timeoutTokenSource.Token; _iotHubPublisherDeviceName = _context.DeviceConfig.DeviceId; _iotHubPublisherModuleName = _context.IoTHubPublisherDeployment.ModuleName; _consumer = _context.GetEventHubConsumerClient(); _writerId = Guid.NewGuid().ToString(); _serializer = new NewtonsoftJsonSerializer(); // Initialize DeviceServiceClient from IoT Hub connection string. _iotHubClient = TestHelper.DeviceServiceClient( _context.IoTHubConfig.IoTHubConnectionString, Microsoft.Azure.Devices.TransportType.Amqp_WebSocket_Only ); } protected virtual void Dispose(bool disposing) { if (disposing) { if (_consumer != null) { _consumer.CloseAsync(CancellationToken.None).GetAwaiter().GetResult(); _consumer.DisposeAsync().AsTask().GetAwaiter().GetResult(); _iotHubClient.Dispose(); } _timeoutTokenSource?.Dispose(); } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } [Fact, PriorityOrder(1)] public async Task TestDeployStandalonePublisher() { await _context.RegistryHelper.DeployStandalonePublisherAsync( OpcPublisherAEE2ETests.MessagingMode.PubSub, _timeoutToken); } [Fact, PriorityOrder(998)] public async Task TestRestartStandalonePublisher() { await _context.RegistryHelper.RestartStandalonePublisherAsync( OpcPublisherAEE2ETests.MessagingMode.PubSub, false, _timeoutToken); } [Fact, PriorityOrder(999)] public async Task TestDeleteAci() { await TestHelper.DeleteSimulationContainerAsync(_context, _timeoutToken); } /// /// Perform direct method call. /// /// Direct method parameters. /// Cancellation token. /// protected async Task CallMethodAsync( MethodParameterModel parameters, CancellationToken ct ) { return await TestHelper.CallMethodAsync( _iotHubClient, _iotHubPublisherDeviceName, _iotHubPublisherModuleName, parameters, _context, ct ).ConfigureAwait(false); } protected async Task PublishNodesAsync(string json, CancellationToken ct) { await UnpublishAllNodesAsync(ct).ConfigureAwait(false); var entries = _serializer.Deserialize(json); foreach (var entry in entries) { // Call PublishNodes direct method var result = await CallMethodAsync( new MethodParameterModel { Name = TestConstants.DirectMethodNames.PublishNodes, JsonPayload = _serializer.SerializeToString(entry) }, ct ).ConfigureAwait(false); Assert.Equal((int)HttpStatusCode.OK, result.Status); } var result1 = await CallMethodAsync( new MethodParameterModel { Name = TestConstants.DirectMethodNames.GetConfiguredEndpoints }, ct ).ConfigureAwait(false); Assert.Equal((int)HttpStatusCode.OK, result1.Status); var response = _serializer.Deserialize(result1.JsonPayload); Assert.Equal(entries.Length, response.Endpoints.Count); } protected async Task UnpublishAllNodesAsync(CancellationToken ct = default) { MethodResultModel result = null; for (var i = 0; i < 5; i++) { result = await CallMethodAsync( new MethodParameterModel { Name = TestConstants.DirectMethodNames.UnpublishAllNodes, // TODO: Remove this line to test fix for null request crash JsonPayload = "null" }, ct ).ConfigureAwait(false); if (result.Status == 405) { // Retry if method not yet mounted _context.OutputHelper?.WriteLine(result.JsonPayload); await Task.Delay(TestConstants.DefaultDelayMilliseconds, ct); continue; } break; } Assert.Equal((int)HttpStatusCode.OK, result?.Status); var result1 = await CallMethodAsync( new MethodParameterModel { Name = TestConstants.DirectMethodNames.GetConfiguredEndpoints }, ct ).ConfigureAwait(false); Assert.Equal((int)HttpStatusCode.OK, result1.Status); var response = _serializer.Deserialize(result1.JsonPayload); Assert.Empty(response.Endpoints); } protected string SimpleEvents(string messageTypeDefinitionId, string messageBrowsePath, string cycleIdDefinitionId, string cycleIdBrowsePath, string filterTypeDefinitionId) { return _context.PublishedNodesJson( 50000, _writerId, new JArray( new JObject( new JProperty("Id", "ns=0;i=2253"), new JProperty("QueueSize", 10), new JProperty("DisplayName", "SimpleEvents"), new JProperty("EventFilter", new JObject( new JProperty("SelectClauses", new JArray( new JObject( new JProperty("TypeDefinitionId", messageTypeDefinitionId), new JProperty("BrowsePath", new JArray( new JValue(messageBrowsePath)))), new JObject( new JProperty("TypeDefinitionId", cycleIdDefinitionId), new JProperty("BrowsePath", new JArray( new JValue(cycleIdBrowsePath)))))), new JProperty("WhereClause", new JObject( new JProperty("Elements", new JArray( new JObject( new JProperty("FilterOperator", new JValue("OfType")), new JProperty("FilterOperands", new JArray( new JObject( new JProperty("Value", filterTypeDefinitionId)))))))))))))); } protected static void VerifyPayloads(IEnumerable payloads) { foreach (var payload in payloads) { payload.Message.Value.Should().Match("The system cycle '*' has started."); payload.CycleId.Value.Should().MatchRegex("^\\d+$"); } } protected static void ValidatePendingConditionsView(IEnumerable eventData) { foreach (var pendingMessage in eventData) { pendingMessage.ConditionId.Value.Should().StartWith("http://microsoft.com/Opc/OpcPlc/AlarmsInstance#"); pendingMessage.Retain.Value.Should().BeTrue(); } } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/TestConstants.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests { /// /// Contains constants using for End 2 End testing /// internal static partial class TestConstants { /// /// Character that need to be used when split value of "PLC_SIMULATION_XYZ" environment variables /// public static char SimulationUrlsSeparator = ';'; /// /// Name of the test assembly /// public const string TestAssemblyName = "OpcPublisher-AE-E2E-Tests"; /// /// Default timeout of web calls /// public const int DefaultTimeoutInMilliseconds = 90 * 1000; /// /// Default delay interval in milliseconds /// public const int DefaultDelayMilliseconds = 5 * 1000; /// /// Maximum timeout for a test case /// public const int MaxTestTimeoutMilliseconds = 10 * 60 * 1000; /// /// Name of Published Nodes Json used by publisher module /// public const string PublishedNodesFilename = "published_nodes.json"; /// /// Folder to store published_nodes.json file /// public const string PublishedNodesFolder = "/mount/opc_publisher"; /// /// The full name of the publishednodes.json on the Edge /// public static readonly string PublishedNodesFullName = PublishedNodesFolder.TrimEnd('/') + "/" + PublishedNodesFilename; /// /// Default Microsoft Container Registry /// public const string MicrosoftContainerRegistry = "mcr.microsoft.com"; /// /// IoT Hub Event Hubs endpoint consumer group for tests /// public const string TestConsumerGroupName = "TestConsumer"; /// /// Contains constants for OPC PLC /// internal static class OpcSimulation { /// /// Default port of OPC UA Server endpoint of OPC PLC /// public const ushort Port = 50000; /// /// Name of Published Nodes Json file generated by OPC PLC, containing information /// of provided (simulated) OPC UA Nodes /// public const string PublishedNodesFile = "pn.json"; /// /// The share that is created in the pipeline /// public const string FileShareName = "acishare"; /// /// This is the first part of the Azure Storage name that is created in pipeline /// public const string AzureStorageNameWithoutSuffix = "e2etestingstorage"; /// /// Name of Tag in Resource Group /// public const string TestingResourcesSuffixName = "TestingResourcesSuffix"; } /// /// Contains names of Environment variables available for tests /// internal static class EnvironmentVariablesNames { /// /// Tenant name used for authentication of Industrial IoT Platform /// public const string PCS_AUTH_TENANT = "PCS_AUTH_TENANT"; /// /// Client App ID used for authentication of Industrial IoT Platform /// public const string PCS_AUTH_CLIENT_APPID = "PCS_AUTH_CLIENT_APPID"; /// /// Client Secrete used for authentication of Industrial IoT Platform /// public const string PCS_AUTH_CLIENT_SECRET = "PCS_AUTH_CLIENT_SECRET"; /// /// Semicolon separated URLs to load published_nodes.json from OPC-PLCs /// public const string PLC_SIMULATION_URLS = "PLC_SIMULATION_URLS"; /// /// Semicolon separated ip addresses of OPC Plcs /// public const string PLC_SIMULATION_IPS = "PLC_SIMULATION_IPS"; /// /// IoTEdge version /// public const string IOT_EDGE_VERSION = "IOT_EDGE_VERSION"; /// /// Device identity of edge device at IoT Hub /// public const string IOT_EDGE_DEVICE_ID = "IOT_EDGE_DEVICE_ID"; /// /// DNS name of edge device /// public const string IOT_EDGE_DEVICE_DNSNAME = "IOT_EDGE_DEVICE_DNSNAME"; /// /// User name of vm that hosting edge device /// public const string IOT_EDGE_VM_USERNAME = "IOT_EDGE_VM_USERNAME"; /// /// SSH public key of vm that hosting edge device /// public const string IOT_EDGE_VM_PUBLICKEY = "IOT_EDGE_VM_PUBLICKEY"; /// /// SSH private key of vm that hosting edge device /// public const string IOT_EDGE_VM_PRIVATEKEY = "IOT_EDGE_VM_PRIVATEKEY"; /// /// IoT Hub connection string /// public const string PCS_IOTHUB_CONNSTRING = "PCS_IOTHUB_CONNSTRING"; /// /// The connection string of the event-hub compatible endpoint of IoT Hub. /// public const string IOTHUB_EVENTHUB_CONNECTIONSTRING = "IOTHUB_EVENTHUB_CONNECTIONSTRING"; /// /// Container Registry server /// public const string PCS_DOCKER_SERVER = "PCS_DOCKER_SERVER"; /// /// Container Registry user name /// public const string PCS_DOCKER_USER = "PCS_DOCKER_USER"; /// /// Container Registry password /// public const string PCS_DOCKER_PASSWORD = "PCS_DOCKER_PASSWORD"; /// ///Images namespace /// public const string PCS_IMAGES_NAMESPACE = "PCS_IMAGES_NAMESPACE"; /// /// Images tag /// public const string PCS_IMAGES_TAG = "PCS_IMAGES_TAG"; /// /// Resource group /// public const string PCS_RESOURCE_GROUP = "PCS_RESOURCE_GROUP"; /// /// Subscription Id /// public const string PCS_SUBSCRIPTION_ID = "PCS_SUBSCRIPTION_ID"; } /// /// Constants related to xUnit traits /// internal static class TraitConstants { /// /// The trait name of the Publisher Mode /// public const string PublisherModeTraitName = "PublisherMode"; /// /// The trait value for PublisherMode = AE /// public const string PublisherModeTraitValue = "AE"; /// /// The trait value for PublisherMode = standalone /// public const string PublisherModeStandaloneTraitValue = "standaloneX"; } /// /// Direct Method names /// internal static class DirectMethodNames { /// /// Publish Nodes /// public const string PublishNodes = "PublishNodes_V1"; /// /// Unpublish Nodes /// public const string UnpublishNodes = "UnpublishNodes_V1"; /// /// GetConfiguredNodesOnEndpoint /// public const string GetConfiguredNodesOnEndpoint = "GetConfiguredNodesOnEndpoint_V1"; /// /// GetConfiguredEndpoints /// public const string GetConfiguredEndpoints = "GetConfiguredEndpoints_V1"; /// /// UnpublishAllNodes /// public const string UnpublishAllNodes = "UnpublishAllNodes_V1"; /// /// GetDiagnosticInfo /// public const string GetDiagnosticInfo = "GetDiagnosticInfo_V1"; /// /// AddOrUpdateEndpoints /// public const string AddOrUpdateEndpoints = "AddOrUpdateEndpoints_V1"; } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/TestExtensions/IIoTPlatformTestContext.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.TestExtensions { using Azure.ResourceManager.Resources; using Config; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Neovolve.Logging.Xunit; using System; using System.Collections.Generic; using Xunit.Abstractions; /// /// Context to pass data between test cases /// public class IIoTPlatformTestContext : IDisposable, IDeviceConfig, IIoTHubConfig, IIoTEdgeConfig, ISshConfig, IOpcPlcConfig, IContainerRegistryConfig { private ITestOutputHelper _outputHelper = new DummyOutput(); /// /// Configuration /// private IConfiguration Configuration { get; } public IIoTPlatformTestContext() { Configuration = GetConfiguration(); RegistryHelper = new RegistryHelper(this); } /// /// Helper to write output, need to be set from constructor of test class /// public ITestOutputHelper OutputHelper => _outputHelper; /// /// Helper to write output, need to be set from constructor of test class /// /// public void SetOutputHelper(ITestOutputHelper output) { ArgumentNullException.ThrowIfNull(output); LogEnvironment(output); _outputHelper = output; _logFactory?.Dispose(); _logFactory = LogFactory.Create(_outputHelper); } public ILogger CreateLogger() { return _logFactory?.CreateLogger(); } private sealed class DummyOutput : ITestOutputHelper { public void WriteLine(string message) { Console.WriteLine(message); } public void WriteLine(string format, params object[] args) { Console.WriteLine(format, args); } } /// /// IoT Device Configuration /// public IDeviceConfig DeviceConfig { get { return this; } } /// /// IoT Hub Configuration /// public IIoTHubConfig IoTHubConfig { get { return this; } } /// /// IoT Edge Configuration /// public IIoTEdgeConfig IoTEdgeConfig { get { return this; } } /// /// SSH Configuration /// public ISshConfig SshConfig { get { return this; } } /// /// OpcPlc Configuration /// public IOpcPlcConfig OpcPlcConfig { get { return this; } } /// /// ContainerRegistry Configuration /// public IContainerRegistryConfig ContainerRegistryConfig { get { return this; } } /// /// Helper to work with Azure.Devices.RegistryManager /// public RegistryHelper RegistryHelper { get; } /// /// Resource group object /// public ResourceGroupResource ResourceGroup { get; set; } /// /// Urls for the dynamic ACI containers /// public IReadOnlyList PlcAciDynamicUrls { get; set; } /// /// Azure Storage Name /// public string AzureStorageName { get; set; } /// /// Azure Storage Key /// public string AzureStorageKey { get; set; } /// /// Image that are used for PLC ACI /// public string PLCImage { get; set; } /// /// Testing suffix for this environment /// public string TestingSuffix { get; set; } /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Override for disposing /// /// Indicates if called from protected virtual void Dispose(bool disposing) { if (disposing) { RegistryHelper.Dispose(); _logFactory?.Dispose(); } } /// /// Read configuration variable /// /// /// /// private string GetStringOrDefault(string key, Func defaultValue) { var value = Configuration.GetValue(key); if (string.IsNullOrEmpty(value)) { return defaultValue?.Invoke() ?? string.Empty; } return value.Trim(); } /// /// Get configuration that reads from: /// - environment variables /// - environment variables from user target /// - environment variables from .env file /// /// private static IConfigurationRoot GetConfiguration() { return new ConfigurationBuilder() .AddEnvironmentVariables() .AddFromDotEnvFile() .Build(); } public string DeviceId => GetStringOrDefault(TestConstants.EnvironmentVariablesNames.IOT_EDGE_DEVICE_ID, () => throw new InvalidOperationException("IoT Edge device id is not provided.")); public string IoTHubConnectionString => GetStringOrDefault(TestConstants.EnvironmentVariablesNames.PCS_IOTHUB_CONNSTRING, () => throw new InvalidOperationException("IoT Hub connection string is not provided.")); public string IoTHubEventHubConnectionString => GetStringOrDefault(TestConstants.EnvironmentVariablesNames.IOTHUB_EVENTHUB_CONNECTIONSTRING, () => throw new InvalidOperationException("IoT Hub EventHub connection string is not provided.")); public string EdgeVersion => GetStringOrDefault(TestConstants.EnvironmentVariablesNames.IOT_EDGE_VERSION, () => "1.4"); public string Username => GetStringOrDefault(TestConstants.EnvironmentVariablesNames.IOT_EDGE_VM_USERNAME, () => throw new InvalidOperationException("Username of iot edge device is not provided.")); public string PublicKey => GetStringOrDefault(TestConstants.EnvironmentVariablesNames.IOT_EDGE_VM_PUBLICKEY, () => throw new InvalidOperationException("Public key of iot edge device is not provided.")); public string PrivateKey => GetStringOrDefault(TestConstants.EnvironmentVariablesNames.IOT_EDGE_VM_PRIVATEKEY, () => throw new InvalidOperationException("Private key of iot edge device is not provided.")); public string Host => GetStringOrDefault(TestConstants.EnvironmentVariablesNames.IOT_EDGE_DEVICE_DNSNAME, () => throw new InvalidOperationException("DNS name of iot edge device is not provided.")); public string Urls => GetStringOrDefault(TestConstants.EnvironmentVariablesNames.PLC_SIMULATION_URLS, () => throw new InvalidOperationException("Semicolon separated list of URLs of OPC-PLCs is not provided.")); public string Ips => GetStringOrDefault(TestConstants.EnvironmentVariablesNames.PLC_SIMULATION_IPS, () => throw new InvalidOperationException("Semicolon separated list of ip addresses of OPC-PLCs is not provided.")); public string TenantId => GetStringOrDefault(TestConstants.EnvironmentVariablesNames.PCS_AUTH_TENANT, () => GetStringOrDefault("AZURE_TENANT_ID", () => throw new InvalidOperationException("Tenant Id is not provided."))); public string ResourceGroupName => GetStringOrDefault(TestConstants.EnvironmentVariablesNames.PCS_RESOURCE_GROUP, () => throw new InvalidOperationException("Resource Group Name is not provided.")); public string SubscriptionId => GetStringOrDefault(TestConstants.EnvironmentVariablesNames.PCS_SUBSCRIPTION_ID, () => string.Empty); public string ContainerRegistryServer => GetStringOrDefault(TestConstants.EnvironmentVariablesNames.PCS_DOCKER_SERVER, () => string.Empty); public string ContainerRegistryUser => GetStringOrDefault(TestConstants.EnvironmentVariablesNames.PCS_DOCKER_USER, () => string.Empty); public string ContainerRegistryPassword => GetStringOrDefault(TestConstants.EnvironmentVariablesNames.PCS_DOCKER_PASSWORD, () => string.Empty); public string ImagesNamespace => GetStringOrDefault(TestConstants.EnvironmentVariablesNames.PCS_IMAGES_NAMESPACE, () => string.Empty); public string ImagesTag => GetStringOrDefault(TestConstants.EnvironmentVariablesNames.PCS_IMAGES_TAG, () => "latest"); public void LogEnvironment(ITestOutputHelper output) { if (output == null || _logged || output is DummyOutput) { return; } _logged = true; Log("ApplicationName"); Log("PCS_IMAGES_TAG"); Log("PCS_DOCKER_SERVER"); Log("PCS_DOCKER_USER"); Log("PCS_DOCKER_PASSWORD"); Log("PCS_IMAGES_NAMESPACE"); Log("PCS_SUBSCRIPTION_ID"); Log("PCS_RESOURCE_GROUP"); Log("PCS_SERVICE_URL"); Log("PLC_SIMULATION_URLS"); Log("IOT_EDGE_VERSION"); Log("IOT_EDGE_DEVICE_ID"); Log("IOT_EDGE_DEVICE_DNSNAME"); Log("IOT_EDGE_VM_USERNAME"); Log("PCS_IOTHUB_CONNSTRING"); Log("IOTHUB_EVENTHUB_CONNECTIONSTRING"); void Log(string envVar) => output.WriteLine($"{envVar}: '{Environment.GetEnvironmentVariable(envVar)}'"); } private bool _logged; private ILoggerFactory _logFactory; } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/TestExtensions/IIoTStandaloneTestContext.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.TestExtensions { using OpcPublisherAEE2ETests.Deploy; /// /// Test context to pass data between test cases for standalone tests. /// public class IIoTStandaloneTestContext : IIoTPlatformTestContext { /// /// Deployment for edgeHub and edgeAgent so called "base deployment" /// public readonly IIoTHubEdgeDeployment IoTHubEdgeBaseDeployment; /// /// Deployment for OPC Publisher as standalone /// public readonly ModuleDeploymentConfiguration IoTHubPublisherDeployment; /// /// Constructor of test context. /// public IIoTStandaloneTestContext() { // Create deployments. IoTHubEdgeBaseDeployment = new IoTHubEdgeBaseDeployment(this); IoTHubPublisherDeployment = new IoTHubPublisherDeployment(this, MessagingMode.PubSub); } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/TestExtensions/PriorityOrderAttribute.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.TestExtensions { using System; /// /// Attribute to define ordering between xUnit tests /// [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public sealed class PriorityOrderAttribute : Attribute { /// /// Constructor to create instance of priority order attribute /// /// public PriorityOrderAttribute(uint order) { Order = order; } /// /// The order in which the test should be executed /// public uint Order { get; } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/TestExtensions/TestCaseOrderer.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.TestExtensions { using System; using System.Collections.Generic; using System.Linq; using Xunit.Abstractions; using Xunit.Sdk; /// /// Orderer to order use test cases based on /// public class TestCaseOrderer : ITestCaseOrderer { /// /// Fullname of the TestCollectionOrderer, as constant to be used in assembly info /// public const string FullName = "OpcPublisherAEE2ETests.TestExtensions.TestCaseOrderer"; /// public IEnumerable OrderTestCases(IEnumerable testCases) where TTestCase : ITestCase { var sortedMethods = new SortedDictionary>(); foreach (var testCase in testCases) { uint order = 0; foreach (var attr in testCase.TestMethod.Method.GetCustomAttributes(typeof(PriorityOrderAttribute).AssemblyQualifiedName)) { order = attr.GetNamedArgument("Order"); } GetOrCreate(sortedMethods, order).Add(testCase); } foreach (var list in sortedMethods.Keys.Select(priority => sortedMethods[priority])) { list.Sort((x, y) => StringComparer.OrdinalIgnoreCase.Compare(x.TestMethod.Method.Name, y.TestMethod.Method.Name)); foreach (var testCase in list) { yield return testCase; } } } private static TValue GetOrCreate(SortedDictionary dictionary, TKey key) where TValue : new() { if (dictionary.TryGetValue(key, out var result)) { return result; } result = new TValue(); dictionary[key] = result; return result; } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/TestHelper.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests { using OpcPublisherAEE2ETests.Config; using Azure; using Azure.Core; using Azure.Identity; using Azure.Messaging.EventHubs.Consumer; using Azure.ResourceManager; using Azure.ResourceManager.ContainerInstance; using Azure.ResourceManager.ContainerInstance.Models; using Azure.ResourceManager.Resources; using Azure.ResourceManager.Storage; using Azure.Storage; using Azure.Storage.Files.Shares; using Microsoft.Azure.Devices; using Microsoft.Azure.Devices.Common.Exceptions; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Renci.SshNet; using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Linq; using System.Net.Sockets; using System.Runtime.CompilerServices; using System.Text; using System.Threading; using System.Threading.Tasks; using TestExtensions; using TestModels; using Xunit; using Xunit.Abstractions; using Microsoft.Extensions.Options; public record class MethodResultModel(string JsonPayload, int Status); public record class MethodParameterModel { public string Name { get; set; } public string JsonPayload { get; set; } } internal static class TestHelper { /// /// Update Device Twin tag /// /// Name of deployed Industrial IoT /// Shared Context for E2E testing Industrial IoT Platform /// Cancellation token public static async Task UpdateTagAsync( string patch, IIoTPlatformTestContext context, CancellationToken ct = default ) { var registryManager = context.RegistryHelper.RegistryManager; var twin = await registryManager.GetTwinAsync(context.DeviceConfig.DeviceId, ct).ConfigureAwait(false); await registryManager.UpdateTwinAsync(twin.DeviceId, patch, twin.ETag, ct).ConfigureAwait(false); } /// /// Transfer the content of published_nodes.json file into the OPC Publisher edge module /// /// String for published_nodes.json /// Shared Context for E2E testing Industrial IoT Platform /// Cancellation token public static async Task SwitchToStandaloneModeAndPublishNodesAsync( string json, IIoTPlatformTestContext context, CancellationToken ct = default ) { context.OutputHelper.WriteLine("Write published_nodes.json to IoT Edge"); context.OutputHelper.WriteLine(json); await PublishNodesAsync(json, context, ct).ConfigureAwait(false); await SwitchToStandaloneModeAsync(context, ct).ConfigureAwait(false); } /// /// Transfer the content of published_nodes.json file into the OPC Publisher edge module /// /// String for published_nodes.json /// Shared Context for E2E testing Industrial IoT Platform /// Cancellation token public static async Task PublishNodesAsync( string json, IIoTPlatformTestContext context, CancellationToken ct = default ) { for (var attempt = 0; ; attempt++) { try { await CreateFolderOnEdgeVMAsync(TestConstants.PublishedNodesFolder, context, ct).ConfigureAwait(false); using var scpClient = await CreateScpClientAndConnectAsync(context, ct).ConfigureAwait(false); await using var stream = new MemoryStream(Encoding.UTF8.GetBytes(json)); scpClient.Upload(stream, TestConstants.PublishedNodesFullName); return; } catch (Exception ex) when (attempt < 60) { context.OutputHelper.WriteLine($"Failed to write {TestConstants.PublishedNodesFullName} to {TestConstants.PublishedNodesFolder} on host {context.SshConfig.Host} with username {context.SshConfig.Username} ({ex.Message})"); await Task.Delay(1000, ct).ConfigureAwait(false); } } } /// /// Clean published nodes JSON files. /// /// /// /// public static async Task CleanPublishedNodesJsonFilesAsync(IIoTPlatformTestContext context, CancellationToken ct = default) { for (var attempt = 0; ; attempt++) { try { // Make sure directories exist. using (var sshCient = await CreateSshClientAndConnectAsync(context, ct).ConfigureAwait(false)) { sshCient.RunCommand($"[ ! -d {TestConstants.PublishedNodesFolder} ]" + $" && sudo mkdir -m 777 -p {TestConstants.PublishedNodesFolder}"); } break; } catch (Exception ex) when (attempt < 60) { context.OutputHelper.WriteLine($"Failed to create folder on host {context.SshConfig.Host} with username {context.SshConfig.Username} ({ex.Message})"); await Task.Delay(1000, ct).ConfigureAwait(false); } } await PublishNodesAsync("[]", context, ct).ConfigureAwait(false); } /// /// Sets the unmanaged-Tag to "true" to enable Standalone-Mode /// /// Shared Context for E2E testing Industrial IoT Platform /// Cancellation token /// public static async Task SwitchToStandaloneModeAsync( IIoTPlatformTestContext context, CancellationToken ct = default ) { const string patch = @"{ tags: { unmanaged: true } }"; await UpdateTagAsync(patch, context, ct).ConfigureAwait(false); } /// /// Create a new SshClient based on SshConfig and directly connects to host /// /// Shared Context for E2E testing Industrial IoT Platform /// /// Instance of SshClient, that need to be disposed private static async Task CreateSshClientAndConnectAsync(IIoTPlatformTestContext context, CancellationToken ct = default) { var privateKeyFile = GetPrivateSshKey(context); try { var client = new SshClient( context.SshConfig.Host, context.SshConfig.Username, privateKeyFile); var connectAttempt = 0; while (true) { try { await client.ConnectAsync(ct); return client; } catch (SocketException) when (++connectAttempt < 10) { await Task.Delay(3000, ct).ConfigureAwait(false); } } } catch (Exception ex) { context.OutputHelper.WriteLine($"Failed to open ssh connection to host {context.SshConfig.Host} with username {context.SshConfig.Username} ({ex.Message})"); throw; } } /// /// Create a new ScpClient based on SshConfig and directly connects to host /// /// Shared Context for E2E testing Industrial IoT Platform /// /// Instance of SshClient, that need to be disposed private static async Task CreateScpClientAndConnectAsync(IIoTPlatformTestContext context, CancellationToken ct = default) { var privateKeyFile = GetPrivateSshKey(context); try { var client = new ScpClient( context.SshConfig.Host, context.SshConfig.Username, privateKeyFile); var connectAttempt = 0; while (true) { try { await client.ConnectAsync(ct); return client; } catch (SocketException) when (++connectAttempt < 10) { await Task.Delay(3000, ct).ConfigureAwait(false); } } } catch (Exception ex) { context.OutputHelper.WriteLine("Failed to open scp connection to host {0} with username {1} ({2})", context.SshConfig.Host, context.SshConfig.Username, ex.Message); throw; } } /// /// Gets the private SSH key from the configuration to connect to the Edge VM /// /// Shared Context for E2E testing Industrial IoT Platform /// private static PrivateKeyFile GetPrivateSshKey(IIoTPlatformTestContext context) { var buffer = Encoding.Default.GetBytes(context.SshConfig.PrivateKey); var privateKeyStream = new MemoryStream(buffer); return new PrivateKeyFile(privateKeyStream); } /// /// Delete a file on the Edge VM /// /// Filename of the file to delete /// Shared Context for E2E testing Industrial IoT Platform /// public static async Task DeleteFileOnEdgeVMAsync(string fileName, IIoTPlatformTestContext context, CancellationToken ct = default) { var isSuccessful = false; using var client = await CreateSshClientAndConnectAsync(context, ct).ConfigureAwait(false); var terminal = client.RunCommand("rm " + fileName); if (string.IsNullOrEmpty(terminal.Error) || terminal.Error.Contains("no such file", StringComparison.OrdinalIgnoreCase)) { isSuccessful = true; } Assert.True(isSuccessful, "Delete file was not successful"); } /// /// Create a folder on Edge VM (if not exists) /// /// Name of the folder to create. /// Shared Context for E2E testing Industrial IoT Platform /// private static async Task CreateFolderOnEdgeVMAsync(string folderPath, IIoTPlatformTestContext context, CancellationToken ct = default) { Assert.False(string.IsNullOrWhiteSpace(folderPath)); var isSuccessful = false; using var client = await CreateSshClientAndConnectAsync(context, ct).ConfigureAwait(false); var terminal = client.RunCommand("sudo mkdir -p " + folderPath + ";cd " + folderPath + "; sudo chmod 777 " + folderPath); if (string.IsNullOrEmpty(terminal.Error) || terminal.Error.Contains("File exists", StringComparison.Ordinal)) { isSuccessful = true; } Assert.True(isSuccessful, $"Folder creation was not successful because of {terminal.Error}"); } /// /// Serialize a published nodes json file. /// /// Shared Context for E2E testing Industrial IoT Platform /// Port of OPC UA server /// DataSetWriterId to set /// OPC UA nodes public static string PublishedNodesJson(this IIoTStandaloneTestContext context, uint port, string writerId, JArray opcNodes) { return JsonConvert.SerializeObject( new JArray( context.PlcAciDynamicUrls.Select(host => new JObject( new JProperty("EndpointUrl", $"opc.tcp://{host}:{port}"), new JProperty("UseSecurity", true), new JProperty("DataSetWriterGroup", Guid.NewGuid().ToString()), new JProperty("DataSetWriterId", writerId), new JProperty("OpcNodes", opcNodes))) ), Formatting.Indented); } /// /// Create an ACI /// /// Shared Context for E2E testing Industrial IoT Platform /// Command line for container /// Cancellation token /// File to upload to the container /// Number of instances public static async Task CreateSimulationContainerAsync(IIoTPlatformTestContext context, List commandLine, CancellationToken cancellationToken, string fileToUpload = null, int numInstances = 1) { var resourceGroup = await GetResourceGroupAsync(context, cancellationToken).ConfigureAwait(false); if (fileToUpload != null) { await UploadFileToStorageAccountAsync(context, fileToUpload, cancellationToken).ConfigureAwait(false); } context.PlcAciDynamicUrls = await Task.WhenAll( Enumerable.Range(0, numInstances) .Select(i => CreatePlcContainerGroupAsync(resourceGroup, $"e2etesting-simulation-aci-{i}-{context.TestingSuffix}-dynamic", context, commandLine[0], commandLine.GetRange(1, commandLine.Count - 1).ToArray(), TestConstants.OpcSimulation.FileShareName, cancellationToken))).ConfigureAwait(false); } /// /// Upload a file to a storage account /// /// /// File name /// private async static Task UploadFileToStorageAccountAsync(IIoTPlatformTestContext context, string fileName, CancellationToken ct = default) { var share = new ShareClient( new Uri($"https://{context.AzureStorageName}.file.core.windows.net/{TestConstants.OpcSimulation.FileShareName}"), new StorageSharedKeyCredential(context.AzureStorageName, context.AzureStorageKey)); var directory = share.GetRootDirectoryClient(); Assert.False(fileName.Contains('\\', StringComparison.Ordinal), "\\ can't be used for file path"); // if fileName contains '/' we will extract the filename string onlyFileName; if (fileName.Contains('/', StringComparison.Ordinal)) { onlyFileName = fileName[(fileName.LastIndexOf('/') + 1)..]; } else { onlyFileName = fileName; } var cf = directory.GetFileClient(onlyFileName); try { await cf.DeleteIfExistsAsync(cancellationToken: ct); await using var stream = new FileStream(fileName, FileMode.Open); await cf.CreateAsync(stream.Length, cancellationToken: ct); await cf.UploadAsync(stream, cancellationToken: ct); } catch (Exception ex) { context.OutputHelper.WriteLine($"Failed to upload file {fileName} to storage " + $"account {context.AzureStorageName} as {onlyFileName} ({ex.Message})"); throw; } } /// /// Create a container group /// /// Resource group /// Container group name /// /// Starting command line /// Additional command line options /// File share name /// private static async Task CreatePlcContainerGroupAsync(ResourceGroupResource resGroup, string containerGroupName, IIoTPlatformTestContext context, string executable, string[] commandLine, string fileShareName, CancellationToken cancellationToken) { var container = new ContainerInstanceContainer(containerGroupName, context.PLCImage, new ContainerResourceRequirements(new ContainerResourceRequestsContent(0.5, 0.5))); container.Command.Add(executable); container.Command.AddRange(commandLine); container.Ports.Add(new ContainerPort(50000)); container.VolumeMounts.Add(new ContainerVolumeMount("share", "/app/files")); var containerGroup = new ContainerGroupData(resGroup.Data.Location, container.YieldReturn(), ContainerInstanceOperatingSystemType.Linux) { IPAddress = new ContainerGroupIPAddress(new ContainerGroupPort(50000).YieldReturn(), ContainerGroupIPAddressType.Public) { DnsNameLabel = containerGroupName } }; containerGroup.Volumes.Add(new ContainerVolume("share") { AzureFile = new ContainerInstanceAzureFileVolume(fileShareName, context.AzureStorageName) { StorageAccountKey = context.AzureStorageKey, IsReadOnly = false } }); var operation = await resGroup.GetContainerGroups().CreateOrUpdateAsync(WaitUntil.Completed, containerGroupName, containerGroup, cancellationToken); return Validate(context, operation).Data.IPAddress.Fqdn; } /// /// Delete an ACI /// /// Shared Context for E2E testing Industrial IoT Platform /// public static async Task DeleteSimulationContainerAsync(IIoTPlatformTestContext context, CancellationToken ct) { if (context.PlcAciDynamicUrls == null || context.PlcAciDynamicUrls.Count == 0) { return; } var resourceGroup = await GetResourceGroupAsync(context, ct); await Task.WhenAll(context.PlcAciDynamicUrls .Select(url => url.Split(".")[0]) .Select(async n => { var response = await resourceGroup.GetContainerGroupAsync(n); var group = Validate(context, response); return await group.DeleteAsync(WaitUntil.Completed); }) ).ConfigureAwait(false); } /// /// Get an azure context /// /// Shared Context for E2E testing Industrial IoT Platform /// Cancellation token /// internal async static Task GetResourceGroupAsync(IIoTPlatformTestContext context, CancellationToken cancellationToken) { if (context.ResourceGroup != null) { return context.ResourceGroup; } var armClient = await GetArmClientAsync(context, cancellationToken); SubscriptionResource subscription = null; if (!string.IsNullOrEmpty(context.OpcPlcConfig.SubscriptionId)) { subscription = await armClient.GetSubscriptions() .FirstOrDefaultAsync(s => s.Data.SubscriptionId == context.OpcPlcConfig.SubscriptionId, cancellationToken); } subscription ??= await armClient.GetDefaultSubscriptionAsync(cancellationToken); var response = await subscription.GetResourceGroupAsync(context.OpcPlcConfig.ResourceGroupName, cancellationToken); var rg = Validate(context, response); var tags = await rg.GetTagResource().GetAsync(cancellationToken); context.OutputHelper.WriteLine($"Get tag from tags {tags}"); var testingSuffix = Validate(context, tags).Data.TagValues[TestConstants.OpcSimulation.TestingResourcesSuffixName]; context.TestingSuffix = testingSuffix; context.AzureStorageName = TestConstants.OpcSimulation.AzureStorageNameWithoutSuffix + testingSuffix; context.OutputHelper.WriteLine($"Get storage keys from {rg}"); var storageAccount = await rg.GetStorageAccountAsync(context.AzureStorageName, cancellationToken: cancellationToken).ConfigureAwait(false); var keys = await Validate(context, storageAccount).GetKeysAsync(cancellationToken: cancellationToken).ToListAsync(cancellationToken); if (keys.Count == 0) { throw new InvalidOperationException($"No keys found for storage account {context.AzureStorageName}"); } context.AzureStorageKey = keys[0].Value; context.OutputHelper.WriteLine($"Get container groups from {rg}"); var firstAciIpAddress = context.OpcPlcConfig.Ips.Split(";")[0]; var containerGroups = await rg.GetContainerGroups().ToListAsync(cancellationToken); context.OutputHelper.WriteLine($"Get container from groups {containerGroups}"); var containerGroup = containerGroups.Find(g => g.Data?.IPAddress?.IP?.ToString() == firstAciIpAddress); if (containerGroup == null) { throw new InvalidOperationException($"Container group with IP address {firstAciIpAddress} not found"); } context.OutputHelper.WriteLine($"Get image from group {containerGroup}"); if (containerGroup.Data.Containers.Count == 0) { throw new InvalidOperationException($"Container group with IP address {firstAciIpAddress} is empty"); } context.PLCImage = containerGroup.Data.Containers[0].Image; context.ResourceGroup = rg; return rg; } /// /// Get an arm client /// /// /// /// private static async Task GetArmClientAsync(IIoTPlatformTestContext context, CancellationToken cancellationToken) { context.OutputHelper.WriteLine($"Accessing resource manager in tenant {context.OpcPlcConfig.TenantId}..."); try { var systemAccessToken = Environment.GetEnvironmentVariable("SYSTEM_ACCESSTOKEN"); var serviceConnection = Environment.GetEnvironmentVariable("AzureSubscription"); var clientId = Environment.GetEnvironmentVariable("AZURE_CLIENT_ID"); if (!string.IsNullOrEmpty(systemAccessToken) && !string.IsNullOrEmpty(serviceConnection)) { context.OutputHelper.WriteLine( $"Using service connection {serviceConnection} with client {clientId}..."); var armClient = new ArmClient(new AzurePipelinesCredential( context.OpcPlcConfig.TenantId, clientId, serviceConnection, systemAccessToken)); await armClient.GetDefaultSubscriptionAsync(cancellationToken); return armClient; } } catch (Exception ex) { context.OutputHelper.WriteLine($"Failed to access resource manager using pipeline service connection: {ex.Message}"); } try { context.OutputHelper.WriteLine($"AZURE_CLIENT_ID: {Environment.GetEnvironmentVariable("AZURE_CLIENT_ID")}"); context.OutputHelper.WriteLine($"AZURE_TENANT_ID: {Environment.GetEnvironmentVariable("AZURE_TENANT_ID")}"); context.OutputHelper.WriteLine($"AZURE_CLIENT_SECRET: {Environment.GetEnvironmentVariable("AZURE_CLIENT_SECRET")}"); var options = new DefaultAzureCredentialOptions { TenantId = context.OpcPlcConfig.TenantId }; //options.AdditionallyAllowedTenants.Add("*"); var armClient = new ArmClient(new DefaultAzureCredential(options)); await armClient.GetDefaultSubscriptionAsync(cancellationToken); return armClient; } catch (Exception ex) { context.OutputHelper.WriteLine($"Failed to access resource manager using default credentials: {ex.Message}"); } try { var armClient = new ArmClient(new AzureCliCredential()); var subscription = await armClient.GetDefaultSubscriptionAsync(cancellationToken); return armClient; } catch (Exception ex) { context.OutputHelper.WriteLine($"Failed to access resource manager using azure cli: {ex.Message}"); throw; } } private static T Validate(IIoTPlatformTestContext context, Response response) { if (!response.HasValue) { context.OutputHelper.WriteLine($"Get tags from {response}"); throw new InvalidOperationException(response.ToString()); } return response.Value; } private static T Validate(IIoTPlatformTestContext context, Operation response) { if (!response.HasValue) { context.OutputHelper.WriteLine($"Get tags from {response}"); throw new InvalidOperationException(response.ToString()); } return response.Value; } /// /// Deserializes the JSON structure contained by the specified /// into an instance of the specified type. /// /// The containing the object. /// The type of the object to deserialize. /// The instance of being deserialized. public static T DeserializeJson(this PartitionEvent partitionEvent) { using var sr = new StreamReader(partitionEvent.Data.BodyAsStream); using var reader = new JsonTextReader(sr); return kSerializer.Deserialize(reader); } /// /// Get an Event Hub consumer /// /// Configuration for IoT Hub /// public static EventHubConsumerClient GetEventHubConsumerClient(this IIoTHubConfig config, string consumerGroup = null) { return new EventHubConsumerClient( consumerGroup ?? TestConstants.TestConsumerGroupName, config.IoTHubEventHubConnectionString); } /// /// /// Reads events from all partitions of the IoT Hub Event Hubs endpoint as an asynchronous enumerable, allowing events to be iterated as they /// become available on the partition, waiting as necessary should there be no events available. /// /// Reading begins at the end of each partition seeing only new events as they are published. /// /// Breaks up the batched messages contained in the event, and returns only messages for the provided /// DataSetWriterId. /// /// /// This enumerator may block for an indeterminate amount of time for an await if events are not available on the partition, requiring /// cancellation via the to be requested in order to return control. /// /// /// /// The Event Hubs consumer. /// /// /// An optional instance to signal the request to cancel the operation. /// /// An to be used for iterating over messages. public static IAsyncEnumerable> ReadMessagesFromWriterIdAsync(this EventHubConsumerClient consumer, string dataSetWriterId, int numberOfBatchesToRead, CancellationToken cancellationToken, IIoTPlatformTestContext context = null) where T : BaseEventTypePayload { return ReadMessagesFromWriterIdAsync(consumer, dataSetWriterId, numberOfBatchesToRead, context, cancellationToken) .Select(x => new EventData { EnqueuedTime = x.enqueuedTime, WriterGroupId = x.writerGroupId, Payload = x.payload.ToObject() }); } /// /// /// Reads events from all partitions of the IoT Hub Event Hubs endpoint as an asynchronous enumerable, allowing events to be iterated as they /// become available on the partition, waiting as necessary should there be no events available. /// /// Reading begins at the end of each partition seeing only new events as they are published. /// /// Breaks up the batched messages contained in the event, and returns only messages for the provided /// DataSetWriterId. /// /// /// This enumerator may block for an indeterminate amount of time for an await if events are not available on the partition, requiring /// cancellation via the to be requested in order to return control. /// /// /// /// The Event Hubs consumer. /// /// /// An optional instance to signal the request to cancel the operation. /// /// An to be used for iterating over messages. public static IAsyncEnumerable> ReadConditionMessagesFromWriterIdAsync(this EventHubConsumerClient consumer, string dataSetWriterId, int numberOfBatchesToRead, CancellationToken cancellationToken, IIoTPlatformTestContext context = null) where T : BaseEventTypePayload { return ReadMessagesFromWriterIdAsync(consumer, dataSetWriterId, numberOfBatchesToRead, context, cancellationToken) .Select(x => new PendingConditionEventData { IsPayloadCompressed = x.isPayloadCompressed, Payload = x.payload.ToObject() } ); } /// /// /// Reads events from all partitions of the IoT Hub Event Hubs endpoint as an asynchronous enumerable, allowing events to be iterated as they /// become available on the partition, waiting as necessary should there be no events available. /// /// Reading begins at the end of each partition seeing only new events as they are published. /// /// Breaks up the batched messages contained in the event, and returns only messages for the provided /// DataSetWriterId. /// /// /// This enumerator may block for an indeterminate amount of time for an await if events are not available on the partition, requiring /// cancellation via the to be requested in order to return control. /// /// /// The Event Hubs consumer. /// /// /// /// An optional instance to signal the request to cancel the operation. /// An to be used for iterating over messages. public static async IAsyncEnumerable<(DateTime enqueuedTime, string writerGroupId, JObject payload, bool isPayloadCompressed)> ReadMessagesFromWriterIdAsync(this EventHubConsumerClient consumer, string dataSetWriterId, int numberOfBatchesToRead, IIoTPlatformTestContext context, [EnumeratorCancellation] CancellationToken cancellationToken) { var events = consumer.ReadEventsAsync(false, cancellationToken: cancellationToken); await foreach (var partitionEvent in events.WithCancellation(cancellationToken)) { var enqueuedTime = (DateTime)partitionEvent.Data.SystemProperties[MessageSystemPropertyNames.EnqueuedTime]; JToken json = null; if (!partitionEvent.Data.Properties.TryGetValue("$$ContentType", out var contentType)) { // Assert.Fail($"Missing $$ContentType property in message {partitionEvent.DeserializeJson()}"); continue; } var isPayloadCompressed = (string)contentType == "application/json+gzip"; if (isPayloadCompressed) { var compressedPayload = Convert.FromBase64String(partitionEvent.Data.EventBody.ToString()); await using (var input = new MemoryStream(compressedPayload)) { await using (var gs = new GZipStream(input, CompressionMode.Decompress)) { using (var textReader = new StreamReader(gs)) { json = JsonConvert.DeserializeObject(await textReader.ReadToEndAsync(cancellationToken).ConfigureAwait(false)); } } } } else { json = partitionEvent.DeserializeJson(); } if (context?.OutputHelper != null) { context.OutputHelper.WriteLine(json.ToString(Formatting.Indented)); } List batchedMessages; if (json is JArray array) { batchedMessages = array.Cast().ToList(); } else { batchedMessages = new List { json }; } // Expect all messages to be the same var messageIds = new HashSet(); foreach (var message in batchedMessages) { Assert.NotNull(message.MessageId.Value); Assert.True(messageIds.Add(message.MessageId.Value)); var writerGroupId = (string)message.DataSetWriterGroup.Value; Assert.NotNull(writerGroupId); Assert.Equal("ua-data", message.MessageType.Value); var innerMessages = (JArray)message.Messages; Assert.True(innerMessages.Any(), "Json doesn't contain any messages"); foreach (dynamic innerMessage in innerMessages) { var messageWriterId = (string)innerMessage.DataSetWriterId.Value; if (!messageWriterId.StartsWith(dataSetWriterId, StringComparison.Ordinal)) { continue; } // Metadata disabled, always sending version 1 Assert.Equal(1, innerMessage.MetaDataVersion.MajorVersion.Value); yield return (enqueuedTime, writerGroupId, (JObject)innerMessage.Payload, isPayloadCompressed); } } if (batchedMessages.Count > 0 && --numberOfBatchesToRead == 0) { break; } } } /// /// Returns elements from an async-enumerable sequence for a given time duration. /// /// The type of the elements in the source sequence. /// A sequence to return elements from. /// While condition. /// An async-enumerable sequence that contains the elements from the input sequence for the given time period, starting when the first element is retrieved. /// is null. private static IAsyncEnumerable TakeWhile(this IAsyncEnumerable source, Func predicate) { _ = source ?? throw new ArgumentNullException(nameof(source)); object firstSeen = null; return source.TakeWhile(predicate: s => { firstSeen ??= s; return predicate((TSource)firstSeen, s); }); } /// /// Bypasses elements in an async-enumerable sequence as long as a number of distinct items has not been seen, and then returns the remaining elements. /// /// The type of the elements in the source sequence. /// The type of the elements to be compared for distinct values. /// An async-enumerable sequence to return elements from. /// A function to generate the value to test for uniqueness, for each element. /// Number of distinct values for valueFunc output to observe until elements should be passed. /// An optional action to execute when the first element is observed. /// An optional action to execute when the last bypassed element is observed. /// An async-enumerable sequence that contains the elements from the input sequence starting at the first element in the linear series at which the number of distinct values has been observed. /// or is null. private static IAsyncEnumerable SkipUntilDistinctCountReached( this IAsyncEnumerable source, Func valueFunc, int distinctCountToReach, Action before = default, Action after = default ) { _ = source ?? throw new ArgumentNullException(nameof(source)); _ = valueFunc ?? throw new ArgumentNullException(nameof(valueFunc)); var seenValues = new HashSet(); return source.SkipWhile(m => { if (seenValues.Count == 0) { before?.Invoke(); } seenValues.Add(valueFunc(m)); if (seenValues.Count < distinctCountToReach) { return true; } after?.Invoke(); return false; }); } /// /// Returns elements from an async-enumerable sequence for a given time duration, /// starting when one message has been published from every publishing source (PLC simulator). /// /// The type of the elements in the source sequence. /// A sequence to return elements from. /// Shared Context for E2E testing Industrial IoT Platform /// A function to extract the Data Source ID from a message payload. /// While condition. /// An async-enumerable sequence that contains the elements from the input sequence for the given time period, starting when the first element is retrieved. /// is null. private static IAsyncEnumerable TakeWhile( this IAsyncEnumerable source, IIoTPlatformTestContext context, Func writerGroupIdFunc, Func predicate ) { // When the first message has been received for each simulator, the system is up and we // "let the flag fall" to start computing event rates. return source .SkipUntilDistinctCountReached( writerGroupIdFunc, context.PlcAciDynamicUrls.Count, () => context.OutputHelper.WriteLine("Waiting for first message for PLC"), () => context.OutputHelper.WriteLine("Consuming messages...") ) .TakeWhile(predicate); } /// /// Returns elements from an async-enumerable sequence for a given time duration, /// starting when one message has been published from every publishing source (PLC simulator). /// /// The type of the payloads in the Publisher messages. /// A sequence to return elements from. /// Shared Context for E2E testing Industrial IoT Platform /// A while condition. /// An async-enumerable sequence that contains the elements from the input sequence for the given time period, starting when the first element is retrieved. /// is null. public static IAsyncEnumerable> TakeWhile( this IAsyncEnumerable> source, IIoTPlatformTestContext context, Func, EventData, bool> predicate ) where TPayload : BaseEventTypePayload { return source.TakeWhile(context, m => m.WriterGroupId, predicate); } /// /// Truncate a date time /// /// Date time top truncate /// Time span public static DateTime Truncate(this DateTime dateTime, TimeSpan timeSpan) { if (timeSpan == TimeSpan.Zero) { return dateTime; } if (dateTime == DateTime.MinValue || dateTime == DateTime.MaxValue) { return dateTime; } return dateTime.AddTicks(-(dateTime.Ticks % timeSpan.Ticks)); } /// /// Initialize DeviceServiceClient from IoT Hub connection string. /// /// /// /// public static ServiceClient DeviceServiceClient( string iotHubConnectionString, TransportType transportType = TransportType.Amqp_WebSocket_Only ) { if (string.IsNullOrWhiteSpace(iotHubConnectionString)) { throw new ArgumentNullException(nameof(iotHubConnectionString)); } return ServiceClient.CreateFromConnectionString( iotHubConnectionString, transportType ); } /// /// Restart module /// /// /// /// /// public static async Task RestartAsync(IIoTPlatformTestContext context, string moduleName, CancellationToken ct) { using var client = TestHelper.DeviceServiceClient(context.IoTHubConfig.IoTHubConnectionString, TransportType.Amqp_WebSocket_Only); var method = new CloudToDeviceMethod("Shutdown"); method.SetPayloadJson("false"); try { await client.InvokeDeviceMethodAsync(context.DeviceId, moduleName, method, ct); } catch { } // Expected, since device will have disconnected now } /// /// Prints the exception message and stacktrace for exception (and all inner exceptions) in test output /// /// Exception to be printed /// XUnit Test OutputHelper instance or null (no print in this case) private static void PrettyPrintException(Exception e, ITestOutputHelper outputHelper) { var exception = e; while (exception != null) { outputHelper.WriteLine(exception.Message); outputHelper.WriteLine(exception.StackTrace); outputHelper.WriteLine(""); exception = exception.InnerException; } } /// /// Call a direct method /// /// Device service client /// Device Id /// Module Id /// Method parameter /// Shared Context for E2E testing Industrial IoT Platform /// Cancellation token public static async Task CallMethodAsync(ServiceClient serviceClient, string deviceId, string moduleId, MethodParameterModel parameters, IIoTPlatformTestContext context, CancellationToken ct) { for (var attempt = 0; ; attempt++) { try { var i = 0;// Retry twice to call with error 500 while (true) { var methodInfo = new CloudToDeviceMethod(parameters.Name); methodInfo.SetPayloadJson(parameters.JsonPayload); var result = await (string.IsNullOrEmpty(moduleId) ? serviceClient.InvokeDeviceMethodAsync(deviceId, methodInfo, ct) : serviceClient.InvokeDeviceMethodAsync(deviceId, moduleId, methodInfo, ct)).ConfigureAwait(false); context.OutputHelper.WriteLine($"Called method {parameters.Name}."); var methodCallResult = new MethodResultModel(result.GetPayloadAsJson(), result.Status); if (methodCallResult.Status >= 500 && ++i < 3) { context.OutputHelper.WriteLine($"Got internal error {methodCallResult.Status} ({methodCallResult.JsonPayload}), trying again to call publisher after delay..."); await Task.Delay(2000, ct).ConfigureAwait(false); continue; } return methodCallResult; } } catch (DeviceNotFoundException de) when (attempt < 60) { context.OutputHelper.WriteLine($"Failed to call method {parameters.Name} with {parameters.JsonPayload} due to {de.Message}"); await Task.Delay(TestConstants.DefaultDelayMilliseconds, ct).ConfigureAwait(false); } catch (Exception e) { context.OutputHelper.WriteLine($"Failed to call method {parameters.Name} with {parameters.JsonPayload}"); if (e.Message.Contains("The operation failed because the requested device isn't online", StringComparison.Ordinal) && attempt < 60) { context.OutputHelper.WriteLine("Device is not online, trying again to call device after delay..."); await Task.Delay(TestConstants.DefaultDelayMilliseconds, ct).ConfigureAwait(false); continue; } PrettyPrintException(e, context.OutputHelper); throw; } } } private static readonly JsonSerializer kSerializer = new(); } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/TestModels/BaseEventTypePayload.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.TestModels { using Newtonsoft.Json; using System; /// Base class for payload types. public class BaseEventTypePayload { /// Gets or sets event id. /// "V1_DoorOpen(294)" represented as JSON base-64 encoded string "VjFfRG9vck9wZW4oMjk0KQ==". [JsonProperty(nameof(EventId))] public DataValueObject EventId { get; set; } /// Gets or sets message. /// "The system cycle '29813' has started." [JsonProperty(nameof(Message))] public DataValueObject Message { get; set; } /// Gets or sets the severity. /// 900 [JsonProperty(nameof(Severity))] public DataValueObject Severity { get; set; } /// Gets or sets the source name. /// "VendingMachine1" [JsonProperty(nameof(SourceName))] public DataValueObject SourceName { get; set; } /// Gets or sets the source node. /// "http://microsoft.com/Opc/OpcPlc/DetermAlarmsInstance#s=VendingMachine1" [JsonProperty(nameof(SourceNode))] public DataValueObject SourceNode { get; set; } /// Gets or sets the event type. /// "i=10751" [JsonProperty(nameof(EventType))] public DataValueObject EventType { get; set; } /// Gets or sets the receive time. [JsonProperty(nameof(ReceiveTime))] public DataValueObject ReceiveTime { get; set; } /// Gets or sets the local time. [JsonProperty(nameof(LocalTime))] public DataValueObject LocalTime { get; set; } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/TestModels/ConditionTypePayload.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.TestModels { using Newtonsoft.Json; using System; /// Payload for conditions and alarms. public class ConditionTypePayload : BaseEventTypePayload { /// Gets or sets Condition Id. /// "http://microsoft.com/Opc/OpcPlc/DetermAlarmsInstance#i=1" [JsonProperty(nameof(ConditionId))] public DataValueObject ConditionId { get; set; } /// Gets or sets comment source timestamp. [JsonProperty(nameof(Comment))] public DataValueObject Comment { get; set; } /// Gets or sets the condition name. /// "VendingMachine1_DoorOpen" [JsonProperty(nameof(ConditionName))] public DataValueObject ConditionName { get; set; } /// Gets or sets the enabled state. /// "Enabled" [JsonProperty(nameof(EnabledState))] public DataValueObject EnabledState { get; set; } /// Gets or sets the enabled state effective display name. /// "Active | Unacknowledged" [JsonProperty("EnabledState/EffectiveDisplayName")] public DataValueObject EnabledStateEffectiveDisplayName { get; set; } /// Gets or sets the enabled state effective transition time. [JsonProperty("EnabledState/EffectiveTransitionTime")] public DataValueObject EnabledStateEffectiveTransitionTime { get; set; } /// Gets or sets the enabled state Id. /// true [JsonProperty("EnabledState/Id")] public DataValueObject EnabledStateId { get; set; } /// Gets or sets the enabled state transition time. [JsonProperty("EnabledState/TransitionTime")] public DataValueObject EnabledStateTransitionTime { get; set; } /// Gets or sets the event last severity. /// 500 [JsonProperty(nameof(LastSeverity))] public DataValueObject LastSeverity { get; set; } /// Gets or sets the quality. [JsonProperty(nameof(Quality))] public DataValueObject Quality { get; set; } /// Gets or sets the retain flag. [JsonProperty(nameof(Retain))] public DataValueObject Retain { get; set; } /// Gets or sets the time. [JsonProperty(nameof(Time))] public DataValueObject Time { get; set; } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/TestModels/DataValueObject.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.TestModels { using Newtonsoft.Json; using System; public static class DataValueObject { public static DataValueObject Create(T value) { return new() { Value = value }; } } public class DataValueObject { /// /// Value /// [JsonProperty] public T Value { get; set; } [JsonProperty] public DateTime? SourceTimestamp { get; set; } [JsonProperty] public DateTime? ServerTimestamp { get; set; } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/TestModels/EventData.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.TestModels { using System; /// Event data with IoT Hub message enqueued time metadata. /// Payload type. public class EventData where T : BaseEventTypePayload { /// IoT Hub message enqueued time. public DateTime EnqueuedTime { get; set; } /// Message origin host. public string WriterGroupId { get; set; } /// Payload public T Payload { get; set; } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/TestModels/PendingConditionEventData.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.TestModels { public class PendingConditionEventData where T : BaseEventTypePayload { public bool IsPayloadCompressed { get; set; } public T Payload { get; set; } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/TestModels/SimpleEventsStep.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.TestModels { /// Simple event step. public class SimpleEventsStep { /// Gets or sets the step name. /// "Step 1" public string Name { get; set; } /// Gets or sets the step duration in milliseconds. /// 1000.0 public double Duration { get; set; } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/TestModels/SystemCycleStatusEventTypePayload.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.TestModels { using Newtonsoft.Json; /// Payload for simple events. public class SystemCycleStatusEventTypePayload : SystemEventTypePayload { /// Gets or sets the cycle id. /// "29813" [JsonProperty("http://microsoft.com/Opc/OpcPlc/SimpleEvents#CycleId")] public DataValueObject CycleId { get; set; } /// Gets or sets the current step. [JsonProperty("http://microsoft.com/Opc/OpcPlc/SimpleEvents#CurrentStep")] public DataValueObject CurrentStep { get; set; } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/TestModels/SystemEventTypePayload.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.TestModels { using Newtonsoft.Json; using System; /// Base class for system events types. public class SystemEventTypePayload : BaseEventTypePayload { /// Gets or sets the time. [JsonProperty(nameof(Time))] public DataValueObject Time { get; set; } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/deploy/DeploymentConfiguration.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.Deploy { using Microsoft.Azure.Devices; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using TestExtensions; public abstract class DeploymentConfiguration : IIoTHubEdgeDeployment { protected DeploymentConfiguration(IIoTPlatformTestContext context) { _context = context ?? throw new ArgumentNullException(nameof(context)); } /// public async Task CreateOrUpdateLayeredDeploymentAsync(CancellationToken token) { var deploymentConfiguration = GetDeploymentConfiguration(); var configuration = await _context.RegistryHelper .CreateOrUpdateConfigurationAsync(deploymentConfiguration, token).ConfigureAwait(false); _context.OutputHelper.WriteLine($"Created deployment {configuration.Id}."); return configuration != null; } /// public async Task DeleteLayeredDeploymentAsync(CancellationToken token) { var deploymentConfiguration = GetDeploymentConfiguration(); await _context.RegistryHelper .DeleteConfigurationAsync(deploymentConfiguration.Id, token).ConfigureAwait(false); } /// public Configuration GetDeploymentConfiguration() { return new Configuration(DeploymentName) { Content = new ConfigurationContent { ModulesContent = CreateDeploymentModules() }, TargetCondition = TargetCondition, Priority = Priority }; } protected readonly IIoTPlatformTestContext _context; /// /// Create a deployment modules object /// protected abstract IDictionary> CreateDeploymentModules(); /// /// The desired rank of deployment /// protected abstract int Priority { get; } /// /// Identifier of deployment /// protected abstract string DeploymentName { get; } /// /// Target condition for applying the deployment /// protected abstract string TargetCondition { get; } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/deploy/IIoTHubEdgeDeployment.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.Deploy { using Microsoft.Azure.Devices; using System.Threading; using System.Threading.Tasks; public interface IIoTHubEdgeDeployment { /// /// Create a new layered deployment or update an existing one. /// /// The token to cancel the async task /// true if create or update was successful otherwise false Task CreateOrUpdateLayeredDeploymentAsync(CancellationToken token); /// /// Get deployment configuration. /// Configuration GetDeploymentConfiguration(); } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/deploy/IoTHubEdgeBaseDeployment.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.Deploy { using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Globalization; using TestExtensions; /// /// Default edge base deployment configuration /// public sealed class IoTHubEdgeBaseDeployment : DeploymentConfiguration { /// /// Create edge base deployer /// /// public IoTHubEdgeBaseDeployment(IIoTPlatformTestContext context) : base(context) { } /// protected override int Priority => 0; /// protected override string DeploymentName => kDeploymentName; /// protected override string TargetCondition => kTargetCondition; /// protected override IDictionary> CreateDeploymentModules() { // We should always consume edgeAgent and edgeHub from mcr.microsoft.com. const string server = TestConstants.MicrosoftContainerRegistry; var version = _context.IoTEdgeConfig.EdgeVersion; return JsonConvert.DeserializeObject>>(""" { "$edgeAgent": { "properties.desired": { "schemaVersion": " """ + kDefaultSchemaVersion + """ ", "runtime": { "type": "docker", "settings": { "minDockerVersion": "v1.25", "loggingOptions": "", "registryCredentials": { } } }, "systemModules": { "edgeAgent": { "type": "docker", "settings": { "image": " """ + server + "/azureiotedge-agent:" + version + """ ", "createOptions": "{}" }, "env": { "ExperimentalFeatures__Enabled": { "value": "true" }, "ExperimentalFeatures__EnableGetLogs": { "value": "true" }, "ExperimentalFeatures__EnableUploadLogs": { "value": "true" }, "ExperimentalFeatures__EnableMetrics": { "value": "true" } } }, "edgeHub": { "type": "docker", "status": "running", "restartPolicy": "always", "settings": { "image": " """ + server + "/azureiotedge-hub:" + version + """ ", "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"443/tcp\":[{\"HostPort\":\"443\"}],\"5671/tcp\":[{\"HostPort\":\"5671\"}],\"8883/tcp\":[{\"HostPort\":\"8883\"}],\"9600/tcp\":[{\"HostPort\":\"9600\"}]}},\"ExposedPorts\":{\"5671/tcp\":{},\"8883/tcp\":{},\"9600/tcp\":{}}}" }, "env": { "experimentalFeatures:enabled": { "value": "true" }, "SslProtocols": { "value": "tls1.2" } } } }, "modules": { } } }, "$edgeHub": { "properties.desired": { "routes": { }, "schemaVersion": " """ + kDefaultSchemaVersion + """ ", "storeAndForwardConfiguration": { "timeToLiveSecs": 7200 } } } } """); } private const string kDefaultSchemaVersion = "1.0"; private const string kDeploymentName = "iiotedge"; /// /// for E2E testing we use "unmanaged" for standalone testing /// base deployment need to be valid for both (managed and unmanaged) /// private const string kTargetCondition = "tags.__type__ = 'iiotedge'"; } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/deploy/IoTHubPublisherDeployment.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.Deploy { using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Globalization; using TestExtensions; public sealed class IoTHubPublisherDeployment : ModuleDeploymentConfiguration { /// /// MessagingMode that will be used for configuration of OPC Publisher. /// public readonly MessagingMode MessagingMode; /// /// Create deployment /// /// /// public IoTHubPublisherDeployment(IIoTPlatformTestContext context, MessagingMode messagingMode) : base(context) { MessagingMode = messagingMode; DeploymentName = kDeploymentName; } /// protected override int Priority => 1; /// protected override string DeploymentName { get; } protected override string TargetCondition => kTargetCondition; /// public override string ModuleName => kModuleName; /// protected override IDictionary> CreateDeploymentModules() { var registryCredentials = ""; //should only be provided if the different container registry require username and password if (!string.IsNullOrEmpty(_context.ContainerRegistryConfig.ContainerRegistryServer) && _context.ContainerRegistryConfig.ContainerRegistryServer != TestConstants.MicrosoftContainerRegistry && !string.IsNullOrEmpty(_context.ContainerRegistryConfig.ContainerRegistryPassword) && !string.IsNullOrEmpty(_context.ContainerRegistryConfig.ContainerRegistryUser)) { var registryId = _context.ContainerRegistryConfig.ContainerRegistryServer.Split('.')[0]; registryCredentials = """ "properties.desired.runtime.settings.registryCredentials. """ + registryId + """ ": { "address": " """ + _context.ContainerRegistryConfig.ContainerRegistryServer + """ ", "password": " """ + _context.ContainerRegistryConfig.ContainerRegistryPassword + """ ", "username": " """ + _context.ContainerRegistryConfig.ContainerRegistryUser + """ " }, """; } // Configure create options per os specified var createOptions = JsonConvert.SerializeObject(new { Hostname = ModuleName, User = "root", Cmd = new[] { "--pki=" + TestConstants.PublishedNodesFolder + "/pki", "--dm", // Disable metadata support "--aa", "--pf=" + TestConstants.PublishedNodesFullName, "--mm=" + MessagingMode.ToString(), "--fm=true", "--RuntimeStateReporting=true" }, HostConfig = new { Binds = new[] { TestConstants.PublishedNodesFolder + "/:" + TestConstants.PublishedNodesFolder }, CapDrop = new[] { "CHOWN", "SETUID" } } }).Replace("\"", "\\\"", StringComparison.Ordinal); var server = string.IsNullOrEmpty(_context.ContainerRegistryConfig.ContainerRegistryServer) ? TestConstants.MicrosoftContainerRegistry : _context.ContainerRegistryConfig.ContainerRegistryServer; var ns = string.IsNullOrEmpty(_context.ContainerRegistryConfig.ImagesNamespace) ? "" : _context.ContainerRegistryConfig.ImagesNamespace.TrimEnd('/') + "/"; var version = _context.ContainerRegistryConfig.ImagesTag ?? "latest"; var image = $"{server}/{ns}iotedge/opc-publisher:{version}"; _context. OutputHelper.WriteLine($"Deploying {image} as {ModuleName}"); // Return deployment modules object var content = """ { "$edgeAgent": { """ + registryCredentials + """ "properties.desired.modules. """ + ModuleName + """ ": { "settings": { "image": " """ + image + """ ", "createOptions": " """ + createOptions + """ " }, "type": "docker", "status": "running", "restartPolicy": "always", "version": " """ + (version == "latest" ? "1.0" : version) + """ " } }, "$edgeHub": { "properties.desired.routes. """ + ModuleName + @"ToUpstream"": ""FROM /messages/modules/" + ModuleName + """ /* INTO $upstream", "properties.desired.routes.leafToUpstream": "FROM /messages/* WHERE NOT IS_DEFINED($connectionModuleId) INTO $upstream" } } """; return JsonConvert.DeserializeObject>>(content); } private const string kModuleName = "publisher_standalone"; private const string kDeploymentName = "__default-opcpublisher-standalone"; private const string kTargetCondition = "(tags.__type__ = 'iiotedge' AND IS_DEFINED(tags.unmanaged))"; } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/deploy/ModuleDeploymentConfiguration.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace OpcPublisherAEE2ETests.Deploy { using TestExtensions; /// /// Configuration that corresponds to a module deployment. /// public abstract class ModuleDeploymentConfiguration : DeploymentConfiguration { /// /// Name of the module that is being deployed by this configuration. /// public abstract string ModuleName { get; } /// /// Constructor that delegates to the base DeploymentConfiguration. /// /// protected ModuleDeploymentConfiguration(IIoTPlatformTestContext context) : base(context) { } } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/opc-plc-files/sc001.json ================================================ { "folders": [ { "name": "VendingMachines", "sources": [ { "objectType": "BaseObjectState", "name": "VendingMachine1", "alarms": [ { "objectType": "TripAlarmType", "name": "VendingMachine1_DoorOpen", "id": "V1_DoorOpen" }, { "objectType": "LimitAlarmType", "name": "VendingMachine1_TemperatureHigh", "id": "V1_TemperatureHigh" }, { "objectType": "ConditionType", "name": "VendingMachine1_AD_Lamp_Off", "id": "V1_AD_Lamp_Off" } ] }, { "objectType": "BaseObjectState", "name": "VendingMachine2", "alarms": [ { "objectType": "TripAlarmType", "name": "VendingMachine2_DoorOpen", "id": "V2_DoorOpen" }, { "objectType": "OffNormalAlarmType", "name": "VendingMachine2_LightOff", "id": "V2_LightOff" } ] } ] } ], "script": { "waitUntilStartInSeconds": 10, "isScriptInRepeatingLoop": true, "runningForSeconds": 86400, "steps": [ { "event": { "alarmId": "V1_DoorOpen", "reason": "Door Open", "severity": "High", "eventId": "V1_DoorOpen-1", "stateChanges": [ { "stateType": "Enabled", "state": true }, { "stateType": "Activated", "state": true } ] } }, { "sleepInSeconds": 5 }, { "event": { "alarmId": "V2_LightOff", "reason": "Light Off in machine", "severity": "Medium", "eventId": "V2_LightOff-1", "stateChanges": [ { "stateType": "Enabled", "state": true }, { "stateType": "Activated", "state": true } ] } }, { "event": { "alarmId": "V1_AD_Lamp_Off", "reason": "AD Lamp Off", "severity": "Medium", "eventId": "V1_AD_Lamp_Off-1", "stateChanges": [ { "stateType": "Enabled", "state": true } ] } }, { "sleepInSeconds": 5 }, { "event": { "alarmId": "V1_DoorOpen", "reason": "Door Closed", "severity": "Medium", "eventId": "V1_DoorOpen-2", "stateChanges": [ { "stateType": "Activated", "state": false } ] } }, { "sleepInSeconds": 4 }, { "event": { "alarmId": "V1_TemperatureHigh", "reason": "Temperature is HIGH (LAST EVENT IN LOOP)", "severity": "High", "eventId": "V1_TemperatureHigh-1", "stateChanges": [ { "stateType": "Activated", "state": true }, { "stateType": "Enabled", "state": true } ] } } ] } } ================================================ FILE: e2e-tests/OpcPublisher-E2E-Tests/xunit.runner.json ================================================ { "parallelizeTestCollections": false } ================================================ FILE: e2e-tests/readme.md ================================================ # E2E test ## Background Poperties of E2E tests: * black-box * end-to-end * high cost tests (long preparation / execution times) Goal of E2E tests: * check the customer point of view (validate) * cover the most important scenarios ## How to write E2E tests ### Preparation Use the `TestCaseOrderer` attribute with `TestCaseOrderer.FullName` parameter on your test class, and `PriorityOrder` on your test methods to order them. Use the `Collection` attribute on your test class to share the context between test methods. Use the `Trait` attribute on your test class to distinguish between orchestrated and standalone mode: * for orchestrated mode use the `Trait` with the name `TestConstants.TraitConstants.PublisherModeTraitName` and the value `TestConstants.TraitConstants.PublisherModeOrchestratedTraitValue`, * for standalone mode use the `Trait` with the name `TestConstants.TraitConstants.PublisherModeTraitName` and the value `TestConstants.TraitConstants.PublisherModeStandaloneTraitValue`. The test class gets the context as a parameter of its constructor. Use one of the following context types: * `IIoTPlatformTestContext` - for orchestrated mode * `IIoTStandaloneTestContext` - for standalone mode In order for the context to log information the `OutputHelper` of the context needs to be set to the `IOutputHelper` the test class gets as a constructor parameter. If necessary you can clean the context by calling its `Reset` method, otherwise it's state is shared between test methods, and even between test classes of the same `Collection`. It is recommended to call `Reset` on the context in the first test method of a test class. All test collections should start by setting the desired mode as a first step. E.g.
`await TestHelper.SwitchToOrchestratedModeAsync(_context);` Use and extend the `TestHelper` class. `TestEventProcessor` listens to IoT Hub and analyzes the value changes. ## Executing tests in Visual Studio You can reuse a test deployment to speed up test development. Follow these steps: * Start new E2E pipeline build with `Cleanup` variable set to `false`. * Find the `ResourceGroupName` in the pipeline logs. * Navigate to the given resource group on the Azure portal. * Change tags: * add or edit tag named `owner` where the value identifies you, * add the tag `DoNotDelete` with the value `true`. * Add yourself to the KeyVault: * open "Access policies" on the azure portal, * click "Add Access Policy", * at "Configure from template" select "Key & Secret Management", * at "Select principal" select your principal, * press the "Add" button, * press the "Save" button. * Execute /tools/e2etesting/GetSecrets.ps1 -KeyVaultName <YourKeyVaultName>. You will be asked whether you want to overwrite the .env file or not. * if you choose 'yes' just wait for the script to finish and no further steps are needed * if you choose 'no' copy the script output to *reporoot*/e2etests/.env > The .env file is excluded from git, but double check you are not committing secrets. * Now you can use Visual Studio to execute your tests. * Don't forget to clean up by executing the pipeline with these variables set: * `Cleanup = false` * `UseExisting = true` * `ResourceGroupName = $[format('')]` ### To debug publisher messages and message validation issues * Stop the app service instance in the resource group. * Start the TestEventProcessor service from the tools\e2etesting\TestEventProcessor\TestEventProcessor.slnx solution file * Change the .env file generated from KeyVault and change the TESTEVENTPROCESSOR_* variables to the default values found in the TestEventProcessor's appsettings.json and launchSettings.json files. "TESTEVENTPROCESSOR_BASEURL": "https://localhost:49450", "TESTEVENTPROCESSOR_USERNAME": "username", "TESTEVENTPROCESSOR_PASSWORD": "password", * Start the unit test (development) ================================================ FILE: readme.md ================================================ # Microsoft OPC Publisher Edge Module [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Build Status](https://msazure.visualstudio.com/One/_apis/build/status%2FOneBranch%2FIndustrial-IoT%2FIndustrial-IoT-Buddy?repoName=Industrial-IoT&branchName=main)](https://msazure.visualstudio.com/One/_build/latest?definitionId=364946&repoName=Industrial-IoT&branchName=main) ## Discover, register and manage your OPC UA enabled Assets with Azure Microsoft [OPC Publisher](docs/opc-publisher/readme.md) allows you to discover and operate OPC UA enabled industrial assets. With OPC Publisher you can harness the power of OPC UA and Azure IoT. OPC Publisher is a fully compliant OPC UA PubSub telemetry publisher (supporting JSON, JSON+Gzip, and UADP binary encoding) and provides a large subset of the OPC UA services through its control plane. OPC Publisher is an Azure IoT Edge module that runs on on-premises. OPC Publisher API can be accessed via HTTP(s) (Preview), an MQTT Broker (Preview) or through Azure IoT Hub device methods. Microsoft provides pre-built Docker containers in the Microsoft Container Registry (MCR) for OPC Publisher and the other tools included in this repository. ## Get started * Learn about [OPC Publisher](docs/opc-publisher/readme.md) and how to use it. * See all [Features](docs/opc-publisher/features.md) of OPC Publisher and their support level. * More [Industrial IoT documentation](docs/readme.md). * Find [release announcements](docs/release-announcement.md) and all [releases of the platform](https://github.com/Azure/Industrial-IoT/releases). ## Get support Please report any security related issues by following our [security process](./SECURITY.md). If you are an Azure customer, please create an Azure Support Request. More information can be found [here](https://azure.microsoft.com/support/create-ticket/). (Azure Support SLA applies). Otherwise, please report bugs, feature requests, or suggestions as [GitHub issues](https://github.com/Azure/Industrial-IoT/issues) (No SLA available). ### Supported releases and support policy Our releases are tagged following semantic versioning (“semver”) conventions. Minor and patch releases do not break backwards compatibility. Releases not shown in the table (e.g., 2.4.x, 2.5.x, 2.6.x, or 2.7.x) are out of support already. | Release (tag) | Last release (tag) | End of support | Successor (tag) | Update instructions | |--------------------|--------------------|----------------|-----------------------|---------------------| | Industrial IoT 2.8 | [2.8.6](https://github.com/Azure/Industrial-IoT/tree/release/2.8.6) | 7/15/2023 | OPC Publisher 2.9 | [Migration Path](docs/opc-publisher/migrationpath.md) | | OPC Publisher 2.8 | [2.8.7](https://github.com/Azure/Industrial-IoT/tree/release/2.8.7) | 12/15/2023 | OPC Publisher 2.9 | N/A | | OPC Publisher 2.9 | [2.9.15](https://github.com/Azure/Industrial-IoT/tree/release/2.9.15) | 11/10/2026 | TBA | [Migration Path](docs/opc-publisher/migrationpath.md) | We only support the latest patch version of a release which per semantic versioning convention is identified by the 3rd part of the version string. Preview releases, preview and experimental features are only supported through GitHub issues. If you are using a container image with a major.minor version tag that is supported per above table, but a patch version lower than the latest patch version, you need to update your images to the latest version to ensure secure operation and take advantage of the latest fixes. If you unexpectedly encounter bugs and require help, please ensure you are running the latest patch release as we might already have addressed the issue you are seeing. If you are not, please update first and try to reproduce the issue on the latest patch version. Security-critical updates are made to the last patch version of the major.minor release containing the vulnerability. Bug fixes that are not security related are made only to the main branch and to the last supported release. The version the fix will be in can be found in the version.json file of the respective branch. Our [official Microsoft support](https://azure.microsoft.com/support/create-ticket/) and any related SLA only covers officially released docker containers obtained from MCR (Microsoft Container Registry) and deployed to Azure in Azure App Services (Web API container) or IoT Edge (OPC Publisher module container) using the documentation and deployment scripts provided as part of the latest release. Experimental and Preview features are excluded. Also, all Azure services deployed, the installed IoT Edge runtime, as well as Operating System and other middleware and combinations thereof must be officially supported as per their published support policy and SLA. In all other cases, support is provided on a best effort basis through [GitHub issues](https://github.com/Azure/Industrial-IoT/issues). We aim to release patch releases on a regular cadence (approximately every 1-2 months), so if you are blocked, and you can suggest or contribute fixes, the chances of getting it into the next patch release are high. ## Contribute This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. If you want/plan to contribute, we ask you to sign a [CLA](https://cla.microsoft.com/) (Contribution License Agreement) and follow the project 's [code submission guidelines](./contributing.md). A friendly bot will remind you about it when you submit a pull-request. ## License Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the [MIT](LICENSE) License. ================================================ FILE: samples/.gitignore ================================================ /**/launchSettings.json ================================================ FILE: samples/Http/BrowseAll/BrowseAll.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using System.Text.Json; using System.Net.Http.Json; Console.WriteLine("Press key to exit"); Console.WriteLine(); using var cts = new CancellationTokenSource(); _ = Task.Run(() => { Console.ReadKey(); cts.Cancel(); }); using var parameters = await Parameters.Parse(args).ConfigureAwait(false); // Connect to publisher using var httpClient = parameters.CreateHttpClientWithAuth(); var request = new HttpRequestMessage(HttpMethod.Post, parameters.OpcPublisher + "/v2/browse") { Content = JsonContent.Create(new { connection = new { endpoint = new { url = parameters.OpcPlc, securityMode = "SignAndEncrypt" } }, request = new { } }), }; using var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cts.Token).ConfigureAwait(false); response.EnsureSuccessStatusCode(); await foreach (var result in JsonSerializer.DeserializeAsyncEnumerable(response.Content.ReadAsStream(), cancellationToken: cts.Token)!) { var browseElementJson = JsonSerializer.Serialize(result, Parameters.Indented); Console.WriteLine(browseElementJson); } ================================================ FILE: samples/Http/BrowseAll/BrowseAll.csproj ================================================  Exe net9.0 enable enable ================================================ FILE: samples/Http/GetConfiguration/GetConfiguration.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using System.Text.Json; using System.Net.Http.Json; Console.WriteLine("Press key to exit"); Console.WriteLine(); using var cts = new CancellationTokenSource(); _ = Task.Run(() => { Console.ReadKey(); cts.Cancel(); }); using var parameters = await Parameters.Parse(args).ConfigureAwait(false); // Connect to publisher using var httpClient = parameters.CreateHttpClientWithAuth(); var configuration = await httpClient.GetFromJsonAsync(parameters.OpcPublisher + "/v2/configuration", JsonSerializerOptions.Default, cts.Token).ConfigureAwait(false); var endpoints = configuration.GetProperty("endpoints").EnumerateArray(); foreach (var endpoint in endpoints) { var endpointJson = JsonSerializer.Serialize(endpoint, Parameters.Indented); Console.WriteLine(endpointJson); var response = await httpClient.PostAsJsonAsync(parameters.OpcPublisher + "/v2/configuration/endpoints/list/nodes", endpoint, cts.Token).ConfigureAwait(false); var nodesJson = JsonSerializer.Serialize(JsonSerializer.Deserialize( await response.Content.ReadAsStringAsync(cts.Token).ConfigureAwait(false)), Parameters.Indented); Console.WriteLine(nodesJson); } ================================================ FILE: samples/Http/GetConfiguration/GetConfiguration.csproj ================================================  Exe net9.0 enable enable ================================================ FILE: samples/Http/GetDiagnostics/GetDiagnostics.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using System.Text.Json; using System.Net.Http.Json; using var cts = new CancellationTokenSource(); _ = Task.Run(() => { Console.ReadKey(); cts.Cancel(); }); using var parameters = await Parameters.Parse(args).ConfigureAwait(false); // Connect to publisher using var httpClient = parameters.CreateHttpClientWithAuth(); while (!cts.IsCancellationRequested) { Console.Clear(); try { await foreach (var info in httpClient.GetFromJsonAsAsyncEnumerable( parameters.OpcPublisher + "/v2/diagnostics/clients", cts.Token)) { var str = JsonSerializer.Serialize(info, Parameters.Indented); Console.WriteLine(str); } Console.WriteLine(); Console.WriteLine("Press key to exit"); Console.SetCursorPosition(0, 0); await Task.Delay(TimeSpan.FromSeconds(1), cts.Token).ConfigureAwait(false); } catch (OperationCanceledException) { break; } catch (Exception ex) { Console.WriteLine(ex); } } ================================================ FILE: samples/Http/GetDiagnostics/GetDiagnostics.csproj ================================================  Exe net9.0 enable enable ================================================ FILE: samples/Http/HttpSamples.slnx ================================================ ================================================ FILE: samples/Http/Parameters.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using CommandLine; using Microsoft.Azure.Devices; using System.Diagnostics; using System.Net.Http.Headers; using System.Security.Cryptography.X509Certificates; using System.Text.Json; /// /// Command line parameters /// internal sealed class Parameters : IDisposable { [Option( 'c', "IoTHubOwnerConnectionString", Required = false, HelpText = "The IoT hub connection string. This is available under the 'Shared access policies' in the Azure portal." + "\nDefaults to value of environment variable 'IoTHubOwnerConnectionString'.")] public string? IoTHubOwnerConnectionString { get; set; } = Environment.GetEnvironmentVariable("IoTHubOwnerConnectionString"); [Option( 'e', "EdgeHubConnectionString", Required = false, HelpText = "The edge hub connection string that OPC Publisher is using mainly for the module and device id values." + "\nDefaults to value of environment variable 'EdgeHubConnectionString'.")] public string? EdgeHubConnectionString { get; set; } = Environment.GetEnvironmentVariable("EdgeHubConnectionString"); const string HttpEndpoint = "http://localhost:9071"; const string HttpsEndpoint = "https://localhost:9072"; /// /// Publisher Endpoint /// public string OpcPublisher => ApiKey == null ? HttpEndpoint : HttpsEndpoint; /// /// Plc endpoint /// public string OpcPlc { get; } = "opc.tcp://opcplc:50000"; /// /// Certificate /// public X509Certificate2? Certificate { get; private set; } /// /// Api key /// public string? ApiKey { get; private set; } internal static readonly JsonSerializerOptions Indented = new() { WriteIndented = true }; /// /// Create client /// /// public HttpClient CreateHttpClientWithAuth() { if (ApiKey == null) { return new HttpClient(); } var httpClient = new HttpClient(new HttpClientHandler { ServerCertificateCustomValidationCallback = (_, cert, _, _) => cert != null && Certificate?.Thumbprint == cert?.Thumbprint }); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("ApiKey", ApiKey); return httpClient; } public void Dispose() { Certificate?.Dispose(); ApiKey = null; } /// /// Parse parameters /// /// /// public static async Task Parse(string[] args) { Parameters? parameters = null; ParserResult result = Parser.Default.ParseArguments(args) .WithParsed(parsedParams => parameters = parsedParams) .WithNotParsed(errors => Environment.Exit(1)); Debug.Assert(parameters != null); var deviceId = string.Empty; var moduleId = string.Empty; try { var ehc = IotHubConnectionStringBuilder.Create(parameters.EdgeHubConnectionString); deviceId = ehc.DeviceId; moduleId = ehc.ModuleId; // Create a ServiceClient to communicate with service-facing endpoint on your hub. using var registryManager = RegistryManager.CreateFromConnectionString( parameters.IoTHubOwnerConnectionString); var twin = await registryManager.GetTwinAsync(deviceId, moduleId).ConfigureAwait(false); parameters.ApiKey = (string)twin.Properties.Reported["__apikey__"]; var cert = (byte[])twin.Properties.Reported["__certificate__"]; parameters.Certificate = new X509Certificate2(cert, parameters.ApiKey); return parameters; } catch (Exception ex) { Console.WriteLine("Error occurred trying to access api key and certificate."); // In production this should be thrown and not continued. Console.WriteLine(ex.Message); } Console.WriteLine("Specify connection strings to use the secure endpoint."); Console.WriteLine("The unsecure endpoint will be used for demonstration purposes."); Console.WriteLine("This is a security risk and should not be used in production!!!"); return parameters; } } ================================================ FILE: samples/Http/ReadCurrentTime/ReadCurrentTime.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using System.Text.Json; using System.Net.Http.Json; Console.WriteLine("Press key to exit"); Console.WriteLine(); using var cts = new CancellationTokenSource(); _ = Task.Run(() => { Console.ReadKey(); cts.Cancel(); }); using var parameters = await Parameters.Parse(args).ConfigureAwait(false); // Connect to publisher using var httpClient = parameters.CreateHttpClientWithAuth(); while (true) { // Read current time from server - see /read api in api.md using var response = await httpClient.PostAsJsonAsync(parameters.OpcPublisher + "/v2/read", new { connection = new { endpoint = new { url = parameters.OpcPlc, securityMode = "SignAndEncrypt" } }, request = new { nodeId = "i=2258" } }).ConfigureAwait(false); response.EnsureSuccessStatusCode(); var responseJson = await response.Content.ReadFromJsonAsync().ConfigureAwait(false); Console.WriteLine("Current time on server:" + responseJson.GetProperty("value").GetString()); } ================================================ FILE: samples/Http/ReadCurrentTime/ReadCurrentTime.csproj ================================================  Exe net9.0 enable enable ================================================ FILE: samples/Http/SetConfiguration/SetConfiguration.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using System.Text.Json; using System.Net.Http.Json; Console.WriteLine("Press key to exit"); Console.WriteLine(); using var cts = new CancellationTokenSource(); _ = Task.Run(() => { Console.ReadKey(); cts.Cancel(); }); using var parameters = await Parameters.Parse(args).ConfigureAwait(false); // Connect to publisher using var httpClient = parameters.CreateHttpClientWithAuth(); // Get original published nodes json configuration var original = await httpClient.GetFromJsonAsync(parameters.OpcPublisher + "/v2/configuration?IncludeNodes=true", JsonSerializerOptions.Default, cts.Token).ConfigureAwait(false); var json = JsonSerializer.Serialize(original, Parameters.Indented); Console.WriteLine("Original configuration: " + json); // Clear all using var clear = await httpClient.PutAsJsonAsync(parameters.OpcPublisher + "/v2/configuration", new { }, JsonSerializerOptions.Default, cts.Token).ConfigureAwait(false); clear.EnsureSuccessStatusCode(); var empty = await httpClient.GetFromJsonAsync(parameters.OpcPublisher + "/v2/configuration?IncludeNodes=true", JsonSerializerOptions.Default, cts.Token).ConfigureAwait(false); json = JsonSerializer.Serialize(empty, Parameters.Indented); Console.WriteLine("Cleared to: " + json); // Patch configuration to add new one using var addOrUpdate = await httpClient.PatchAsJsonAsync(parameters.OpcPublisher + "/v2/configuration", new[] { new { EndpointUrl = parameters.OpcPlc, DataSetWriterGroup = "Asset1", DataSetWriterId = "DataFlow1", DataSetPublishingInterval = 5000, OpcNodes = new [] { new { Id = "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt0" } } } }, JsonSerializerOptions.Default, cts.Token).ConfigureAwait(false); addOrUpdate.EnsureSuccessStatusCode(); var configuration = await httpClient.GetFromJsonAsync(parameters.OpcPublisher + "/v2/configuration?IncludeNodes=true", JsonSerializerOptions.Default, cts.Token).ConfigureAwait(false); json = JsonSerializer.Serialize(configuration, Parameters.Indented); Console.WriteLine("Patched to: " + json); // Remove the endpoint and all its nodes again using var unpublish = await httpClient.PostAsJsonAsync(parameters.OpcPublisher + "/v2/configuration/nodes/unpublish", new { EndpointUrl = parameters.OpcPlc, DataSetWriterGroup = "Asset1", DataSetWriterId = "DataFlow1" }, JsonSerializerOptions.Default, cts.Token).ConfigureAwait(false); unpublish.EnsureSuccessStatusCode(); configuration = await httpClient.GetFromJsonAsync(parameters.OpcPublisher + "/v2/configuration?IncludeNodes=true", JsonSerializerOptions.Default, cts.Token).ConfigureAwait(false); json = JsonSerializer.Serialize(configuration, Parameters.Indented); Console.WriteLine("Now cleared again: " + json); // Re-apply original published nodes json configuration to the publisher using var reset = await httpClient.PutAsJsonAsync(parameters.OpcPublisher + "/v2/configuration", original, JsonSerializerOptions.Default, cts.Token).ConfigureAwait(false); reset.EnsureSuccessStatusCode(); configuration = await httpClient.GetFromJsonAsync(parameters.OpcPublisher + "/v2/configuration?IncludeNodes=true", JsonSerializerOptions.Default, cts.Token).ConfigureAwait(false); json = JsonSerializer.Serialize(configuration, Parameters.Indented); Console.WriteLine("Now reset back to: " + json); ================================================ FILE: samples/Http/SetConfiguration/SetConfiguration.csproj ================================================  Exe net9.0 enable enable ================================================ FILE: samples/Http/WriteReadbackValue/WriteReadbackValue.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using System.Text.Json; using System.Net.Http.Json; Console.WriteLine("Press key to exit"); Console.WriteLine(); using var cts = new CancellationTokenSource(); _ = Task.Run(() => { Console.ReadKey(); cts.Cancel(); }); using var parameters = await Parameters.Parse(args).ConfigureAwait(false); // Connect to publisher using var httpClient = parameters.CreateHttpClientWithAuth(); // // Perform a couple write and readback operations: // var originalValue = await ReadSlowNumberOfUpdatesValueAsync().ConfigureAwait(false); Console.WriteLine("Original value is: " + originalValue); await WriteSlowNumberOfUpdatesValueAsync(33).ConfigureAwait(false); var updatedValue = await ReadSlowNumberOfUpdatesValueAsync().ConfigureAwait(false); Console.WriteLine("Value updated to : " + updatedValue); await WriteSlowNumberOfUpdatesValueAsync(44).ConfigureAwait(false); updatedValue = await ReadSlowNumberOfUpdatesValueAsync().ConfigureAwait(false); Console.WriteLine("Value updated to : " + updatedValue); await WriteSlowNumberOfUpdatesValueAsync(originalValue).ConfigureAwait(false); originalValue = await ReadSlowNumberOfUpdatesValueAsync().ConfigureAwait(false); Console.WriteLine("Now reset back to: " + originalValue); // // Helpers functions // // Read value of the slow number of updates configuration node async ValueTask ReadSlowNumberOfUpdatesValueAsync() { using var response = await httpClient.PostAsJsonAsync(parameters.OpcPublisher + "/v2/read", new { connection = new { endpoint = new { url = parameters.OpcPlc, securityMode = "SignAndEncrypt" } }, request = new { nodeId = "nsu=http://microsoft.com/Opc/OpcPlc/;s=SlowNumberOfUpdates", } }).ConfigureAwait(false); response.EnsureSuccessStatusCode(); var responseJson = await response.Content.ReadFromJsonAsync().ConfigureAwait(false); return responseJson.GetProperty("value").GetInt32(); } // Write value to the slow number of updates configuration node async ValueTask WriteSlowNumberOfUpdatesValueAsync(int value) { using var response = await httpClient.PostAsJsonAsync(parameters.OpcPublisher + "/v2/write", new { connection = new { endpoint = new { url = parameters.OpcPlc, securityMode = "SignAndEncrypt" } }, request = new { nodeId = "nsu=http://microsoft.com/Opc/OpcPlc/;s=SlowNumberOfUpdates", value } }).ConfigureAwait(false); response.EnsureSuccessStatusCode(); } ================================================ FILE: samples/Http/WriteReadbackValue/WriteReadbackValue.csproj ================================================  Exe net9.0 enable enable ================================================ FILE: samples/Http/readme.md ================================================ # HTTP REST Samples This folder contains several samples that show how to interact with the OPC Publisher over HTTPS. The samples show how to read values or update configuration using the HTTP REST API of OPC Publisher. To run the samples, first start OPC Publisher: ```bash cd deploy cd docker set EdgeHubConnectionString= docker compose up ``` Another option is to deploy both into IoT Edge or run them inside the simulation environment as explained [here](../../docs/opc-publisher/opc-publisher.md#using-iot-edge-simulation-environment). You also need to set both the `EdgeHubConnectionString` and the Azure IoT Hub connection string in your environment before running the samples: ```bash set EdgeHubConnectionString= set IoTHubConnectionString= ``` > IMPORTANT: The connection strings contain secrets, ensure you clear them and don't share them outside of your environment. > Restart Visual Studio to pick up the environment variables. The environment variables are used to access IoT Hub and pull the API key (used as bearer authentication) and the certificate used to secure the REST endpoint. The certificate contains the private key. In production it should be downloaded and only the certificate itself should be made available to other applications. > Note: The Environment variables are not required to run the samples. > The samples will fall back to use the unsecure HTTP (port 80) endpoint of OPC Publisher. > However, this is not recommended for production. > In production scenarios the HTTP port (80) should not be exposed like it is done in the compose samples. ================================================ FILE: samples/IoTHub/ApproveRejected/ApproveRejected.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using System.Globalization; using System.Text.Json; using CommandLine; using InvokeDeviceMethod; using Microsoft.Azure.Devices; Parameters? parameters = null; var result = Parser.Default.ParseArguments(args) .WithParsed(parsedParams => parameters = parsedParams) .WithNotParsed(errors => Environment.Exit(1)); // This sample accepts the service connection string as a parameter, if present. Parameters.ValidateConnectionStrings(parameters?.IoTHubOwnerConnectionString, parameters?.EdgeHubConnectionString, out var deviceId, out var moduleId); // Create a ServiceClient to communicate with service-facing endpoint on your hub. using var serviceClient = ServiceClient.CreateFromConnectionString(parameters!.IoTHubOwnerConnectionString); // List rejected certs var methodInvocation = new CloudToDeviceMethod("ListCertificates") { ResponseTimeout = TimeSpan.FromSeconds(30), }; methodInvocation.SetPayloadJson(JsonSerializer.Serialize("Rejected")); var response = await serviceClient.InvokeDeviceMethodAsync(deviceId, moduleId, methodInvocation).ConfigureAwait(false); var certificates = JsonSerializer.Deserialize(response.GetPayloadAsJson()).EnumerateArray() .Select(c => (Thumbprint: c.GetProperty("thumbprint").GetString(), Subject: c.GetProperty("subject").GetString())) .ToList(); for (var i = 0; i < certificates.Count; i++) { var (Thumbprint, Subject) = certificates[i]; Console.WriteLine($"[{i}] {Subject} [{Thumbprint}]"); } Console.WriteLine("Select index of rejected certificate to approve:"); var selected = certificates[int.Parse(Console.ReadLine()!, CultureInfo.CurrentCulture)]; // Approve methodInvocation = new CloudToDeviceMethod("ApproveRejectedCertificate") { ResponseTimeout = TimeSpan.FromSeconds(30), }; methodInvocation.SetPayloadJson(JsonSerializer.Serialize(selected.Thumbprint)); await serviceClient.InvokeDeviceMethodAsync(deviceId, moduleId, methodInvocation).ConfigureAwait(false); ================================================ FILE: samples/IoTHub/ApproveRejected/ApproveRejected.csproj ================================================  Exe net9.0 enable enable ================================================ FILE: samples/IoTHub/BrowseCertificates/BrowseCertificates.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using System.Text.Json; using CommandLine; using InvokeDeviceMethod; using Microsoft.Azure.Devices; Parameters? parameters = null; ParserResult result = Parser.Default.ParseArguments(args) .WithParsed(parsedParams => parameters = parsedParams) .WithNotParsed(errors => Environment.Exit(1)); // This sample accepts the service connection string as a parameter, if present. Parameters.ValidateConnectionStrings(parameters?.IoTHubOwnerConnectionString, parameters?.EdgeHubConnectionString, out var deviceId, out var moduleId); // Create a ServiceClient to communicate with service-facing endpoint on your hub. using var serviceClient = ServiceClient.CreateFromConnectionString(parameters!.IoTHubOwnerConnectionString); foreach (var store in new[] { "Application", "Trusted", "Rejected", "Issuer", "User", "UserIssuer" }) { var methodInvocation = new CloudToDeviceMethod("ListCertificates") { ResponseTimeout = TimeSpan.FromSeconds(30), }; // Get the application certificate and write to stdout methodInvocation.SetPayloadJson(JsonSerializer.Serialize(store)); var response = await serviceClient.InvokeDeviceMethodAsync(deviceId, moduleId, methodInvocation).ConfigureAwait(false); Console.WriteLine($"Certificates in {store} store:"); Console.WriteLine("=============================="); var certificates = JsonSerializer.Deserialize(response.GetPayloadAsJson()).EnumerateArray().ToList(); for (var i = 0; i < certificates.Count; i++) { var certificate = certificates[i]; var thumbprint = certificate.GetProperty("thumbprint").GetString(); var subject = certificate.GetProperty("subject").GetString(); var notAfterUtc = certificate.GetProperty("notAfterUtc").GetDateTime(); var notBeforeUtc = certificate.GetProperty("notBeforeUtc").GetDateTime(); var serialNumber = certificate.GetProperty("serialNumber").GetString(); var selfSigned = certificate.GetProperty("selfSigned").GetBoolean(); Console.WriteLine($"[{thumbprint}] {subject} [SN:{serialNumber}] [Valid: {notBeforeUtc}-{notAfterUtc}] {(selfSigned ? "(Self-signed)" : "")}"); } Console.WriteLine("=============================="); } ================================================ FILE: samples/IoTHub/BrowseCertificates/BrowseCertificates.csproj ================================================  Exe net9.0 enable enable ================================================ FILE: samples/IoTHub/GetCertificate/GetApplicationCert.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using System.Text.Json; using CommandLine; using InvokeDeviceMethod; using Microsoft.Azure.Devices; Parameters? parameters = null; ParserResult result = Parser.Default.ParseArguments(args) .WithParsed(parsedParams => parameters = parsedParams) .WithNotParsed(errors => Environment.Exit(1)); // This sample accepts the service connection string as a parameter, if present. Parameters.ValidateConnectionStrings(parameters?.IoTHubOwnerConnectionString, parameters?.EdgeHubConnectionString, out var deviceId, out var moduleId); // Create a ServiceClient to communicate with service-facing endpoint on your hub. using var serviceClient = ServiceClient.CreateFromConnectionString(parameters!.IoTHubOwnerConnectionString); // Get the application certificate and write to stdout var methodInvocation = new CloudToDeviceMethod("ListCertificates") { ResponseTimeout = TimeSpan.FromSeconds(30), }; methodInvocation.SetPayloadJson(JsonSerializer.Serialize("Application")); var response = await serviceClient.InvokeDeviceMethodAsync(deviceId, moduleId, methodInvocation).ConfigureAwait(false); var certificate = JsonSerializer.Deserialize(response.GetPayloadAsJson()).EnumerateArray().FirstOrDefault(); if (certificate.ValueKind != JsonValueKind.Null) { var pfx = certificate.GetProperty("pfx").GetBytesFromBase64(); using (var stream = Console.OpenStandardOutput(pfx.Length)) { stream.Write(pfx); } } ================================================ FILE: samples/IoTHub/GetCertificate/GetApplicationCert.csproj ================================================  Exe net9.0 enable enable ================================================ FILE: samples/IoTHub/GetConfiguration/GetConfiguration.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using System.Text.Json; using CommandLine; using InvokeDeviceMethod; using Microsoft.Azure.Devices; Parameters? parameters = null; ParserResult result = Parser.Default.ParseArguments(args) .WithParsed(parsedParams => parameters = parsedParams) .WithNotParsed(errors => Environment.Exit(1)); // This sample accepts the service connection string as a parameter, if present. Parameters.ValidateConnectionStrings(parameters?.IoTHubOwnerConnectionString, parameters?.EdgeHubConnectionString, out var deviceId, out var moduleId); // Create a ServiceClient to communicate with service-facing endpoint on your hub. using var serviceClient = ServiceClient.CreateFromConnectionString(parameters!.IoTHubOwnerConnectionString); // Get configured endpoints and then the nodes for each one of it var methodInvocation = new CloudToDeviceMethod("GetConfiguredEndpoints") { ResponseTimeout = TimeSpan.FromSeconds(30), }; var response = await serviceClient.InvokeDeviceMethodAsync(deviceId, moduleId, methodInvocation).ConfigureAwait(false); var endpoints = JsonSerializer.Deserialize(response.GetPayloadAsJson()).GetProperty("endpoints").EnumerateArray(); foreach (var endpoint in endpoints) { var endpointJson = JsonSerializer.Serialize(endpoint, Parameters.Indented); Console.WriteLine(endpointJson); methodInvocation = new CloudToDeviceMethod("GetConfiguredNodesOnEndpoint") { ResponseTimeout = TimeSpan.FromSeconds(30), }; methodInvocation.SetPayloadJson(endpointJson); response = await serviceClient.InvokeDeviceMethodAsync(deviceId, moduleId, methodInvocation).ConfigureAwait(false); // Response is too large, this will generate 413 when run against OPC PLC. var nodesJson = JsonSerializer.Serialize(JsonSerializer.Deserialize(response.GetPayloadAsJson()), Parameters.Indented); Console.WriteLine(nodesJson); } ================================================ FILE: samples/IoTHub/GetConfiguration/GetConfiguration.csproj ================================================  Exe net9.0 enable enable ================================================ FILE: samples/IoTHub/IoTHubSamples.slnx ================================================ ================================================ FILE: samples/IoTHub/ManageWriter/ManageWriter.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using System.Text.Json; using CommandLine; using InvokeDeviceMethod; using Microsoft.Azure.Devices; Parameters? parameters = null; ParserResult result = Parser.Default.ParseArguments(args) .WithParsed(parsedParams => parameters = parsedParams) .WithNotParsed(errors => Environment.Exit(1)); // This sample accepts the service connection string as a parameter, if present. Parameters.ValidateConnectionStrings(parameters?.IoTHubOwnerConnectionString, parameters?.EdgeHubConnectionString, out var deviceId, out var moduleId); // Create a ServiceClient to communicate with service-facing endpoint on your hub. using var serviceClient = ServiceClient.CreateFromConnectionString(parameters!.IoTHubOwnerConnectionString); // Create a writer var methodInvocation = new CloudToDeviceMethod("CreateOrUpdateDataSetWriterEntry") { ResponseTimeout = TimeSpan.FromSeconds(30), }; methodInvocation.SetPayloadJson(JsonSerializer.Serialize(new { endpointUrl = "opc.tcp://opcplc:50000", securityMode = "SignAndEncrypt", dataSetWriterId = "MyWriterId", dataSetWriterGroup = "MyWriterGroup", dataSetPublishingInterval = 2000, OpcNodes = new[] { new { id = "i=2258", dataSetFieldId = "Time0", opcSamplingInterval = 1000 }, } })); await serviceClient.InvokeDeviceMethodAsync(deviceId, moduleId, methodInvocation).ConfigureAwait(false); // Update the writer and add additional nodes for (var i = 0; i < 10; i++) { methodInvocation = new CloudToDeviceMethod("AddOrUpdateNodes") { ResponseTimeout = TimeSpan.FromSeconds(30), }; methodInvocation.SetPayloadJson(JsonSerializer.Serialize(new { dataSetWriterId = "MyWriterId", dataSetWriterGroup = "MyWriterGroup", opcNodes = new[] { new { id = "i=2258", dataSetFieldId = "Time" + i, opcSamplingInterval = 1000 } } })); await serviceClient.InvokeDeviceMethodAsync(deviceId, moduleId, methodInvocation).ConfigureAwait(false); } // Show the nodes in the writer methodInvocation = new CloudToDeviceMethod("GetNodes") { ResponseTimeout = TimeSpan.FromSeconds(30), }; methodInvocation.SetPayloadJson(JsonSerializer.Serialize(new { dataSetWriterId = "MyWriterId", dataSetWriterGroup = "MyWriterGroup" })); var response = await serviceClient.InvokeDeviceMethodAsync(deviceId, moduleId, methodInvocation).ConfigureAwait(false); var nodesJson = JsonSerializer.Serialize(JsonSerializer.Deserialize(response.GetPayloadAsJson()), Parameters.Indented); Console.WriteLine(nodesJson); ================================================ FILE: samples/IoTHub/ManageWriter/ManageWriter.csproj ================================================  Exe net9.0 enable enable ================================================ FILE: samples/IoTHub/MonitorMessages/MonitorMessages.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using System.Text; using Azure.Messaging.EventHubs.Consumer; using CommandLine; Parameters? parameters = null; // Parse application parameters var result = Parser.Default.ParseArguments(args) .WithParsed(parsedParams => parameters = parsedParams) .WithNotParsed(errors => Environment.Exit(1)); // Either the connection string must be supplied, or the set of endpoint, name, and shared access key must be. if (string.IsNullOrWhiteSpace(parameters?.EventHubConnectionString) && (string.IsNullOrWhiteSpace(parameters?.EventHubCompatibleEndpoint) || string.IsNullOrWhiteSpace(parameters.EventHubName) || string.IsNullOrWhiteSpace(parameters.SharedAccessKey))) { Console.WriteLine(CommandLine.Text.HelpText.AutoBuild(result, null, null)); Environment.Exit(1); } Console.WriteLine("Read all messages from IoT Hub. Ctrl-C to exit.\n"); // Set up a way for the user to gracefully shutdown using var cts = new CancellationTokenSource(); Console.CancelKeyPress += (sender, eventArgs) => { eventArgs.Cancel = true; cts.Cancel(); Console.WriteLine("Exiting..."); }; await ReceiveMessagesFromDeviceAsync(parameters, cts.Token).ConfigureAwait(false); // Asynchronously create a PartitionReceiver for a partition and then start // reading any messages sent from the simulated client. static async Task ReceiveMessagesFromDeviceAsync(Parameters parameters, CancellationToken ct) { var connectionString = parameters.GetEventHubConnectionString(); // Create the consumer using the default consumer group using a direct connection to the service. // Information on using the client with a proxy can be found in the README for this quick start, here: // https://github.com/Azure-Samples/azure-iot-samples-csharp/tree/main/iot-hub/Quickstarts/ReadD2cMessages/README.md#websocket-and-proxy-support var consumer = new EventHubConsumerClient( EventHubConsumerClient.DefaultConsumerGroupName, connectionString, parameters.EventHubName); await using (consumer.ConfigureAwait(false)) { Console.WriteLine("Listening for messages on all partitions."); try { // Begin reading events for all partitions, starting with the first event in each partition and waiting indefinitely for // events to become available. Reading can be canceled by breaking out of the loop when an event is processed or by // signaling the cancellation token. // // The "ReadEventsAsync" method on the consumer is a good starting point for consuming events for prototypes // and samples. For real-world production scenarios, it is strongly recommended that you consider using the // "EventProcessorClient" from the "Azure.Messaging.EventHubs.Processor" package. // // More information on the "EventProcessorClient" and its benefits can be found here: // https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/eventhub/Azure.Messaging.EventHubs.Processor/README.md await foreach (PartitionEvent partitionEvent in consumer.ReadEventsAsync(ct).ConfigureAwait(false)) { Console.WriteLine($"\nMessage received on partition {partitionEvent.Partition.PartitionId}:"); var data = Encoding.UTF8.GetString(partitionEvent.Data.Body.ToArray()); Console.WriteLine($"\tMessage body: {data}"); Console.WriteLine("\tApplication properties (set by device):"); foreach (var prop in partitionEvent.Data.Properties) { PrintProperties(prop); } Console.WriteLine("\tSystem properties (set by IoT hub):"); foreach (var prop in partitionEvent.Data.SystemProperties) { PrintProperties(prop); } } } catch (TaskCanceledException) { // This is expected when the token is signaled; it should not be considered an // error in this scenario. } } } static void PrintProperties(KeyValuePair prop) { var propValue = prop.Value is DateTime time ? time.ToString("O") // using a built-in date format here that includes milliseconds : prop.Value.ToString(); Console.WriteLine($"\t\t{prop.Key}: {propValue}"); } /// /// Parameters for the application. /// internal sealed class Parameters { [Option( 'e', "EventHubCompatibleEndpoint", HelpText = "The event hub-compatible endpoint from your IoT hub instance. Use `az iot hub show --query properties.eventHubEndpoints.events.endpoint --name {your IoT hub name}` to fetch via the Azure CLI.")] public string? EventHubCompatibleEndpoint { get; set; } [Option( 'n', "EventHubName", HelpText = "The event hub-compatible name of your IoT hub instance. Use `az iot hub show --query properties.eventHubEndpoints.events.path --name {your IoT hub name}` to fetch via the Azure CLI.")] public string? EventHubName { get; set; } [Option( 's', "SharedAccessKey", HelpText = "A primary or shared access key from your IoT hub instance, with the 'service' permission. Use `az iot hub policy show --name service --query primaryKey --hub-name {your IoT hub name}` to fetch via the Azure CLI.")] public string? SharedAccessKey { get; set; } [Option( 'c', "EventHubConnectionString", HelpText = "The connection string to the event hub-compatible endpoint. Use the Azure portal to get this parameter. If this value is provided, all the others are not necessary.")] public string? EventHubConnectionString { get; set; } internal string GetEventHubConnectionString() { const string iotHubSharedAccessKeyName = "service"; return EventHubConnectionString ?? $"Endpoint={EventHubCompatibleEndpoint};SharedAccessKeyName={iotHubSharedAccessKeyName};SharedAccessKey={SharedAccessKey}"; } } ================================================ FILE: samples/IoTHub/MonitorMessages/MonitorMessages.csproj ================================================  Exe net9.0 enable enable ================================================ FILE: samples/IoTHub/Parameters.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace InvokeDeviceMethod; using CommandLine; using Microsoft.Azure.Devices; using System.Text.Json; /// /// Command line parameters /// internal sealed class Parameters { [Option( 'c', "IoTHubOwnerConnectionString", Required = false, HelpText = "The IoT hub connection string. This is available under the 'Shared access policies' in the Azure portal." + "\nDefaults to value of environment variable 'IoTHubOwnerConnectionString'.")] public string? IoTHubOwnerConnectionString { get; set; } = Environment.GetEnvironmentVariable("IoTHubOwnerConnectionString"); [Option( 'e', "EdgeHubConnectionString", Required = false, HelpText = "The edge hub connection string that OPC Publisher is using mainly for the module and device id values." + "\nDefaults to value of environment variable 'EdgeHubConnectionString'.")] public string? EdgeHubConnectionString { get; set; } = Environment.GetEnvironmentVariable("EdgeHubConnectionString"); internal static readonly JsonSerializerOptions Indented = new() { WriteIndented = true }; public static void ValidateConnectionStrings(string? hubConnectionString, string? edgeConnectionString, out string deviceId, out string moduleId) { deviceId = string.Empty; moduleId = string.Empty; try { _ = IotHubConnectionStringBuilder.Create(hubConnectionString); } catch (Exception) { Console.WriteLine("An IoT hub connection string needs to be specified, " + "please set the environment variable \"IoTHubOwnerConnectionString\" " + "or pass in \"-c | --IoTHubOwnerConnectionString\" through command line."); Environment.Exit(1); } try { var ehc = IotHubConnectionStringBuilder.Create(edgeConnectionString); deviceId = ehc.DeviceId; moduleId = ehc.ModuleId; } catch (Exception) { Console.WriteLine("An Edge hub connection string needs to be specified, " + "please set the environment variable \"EdgeHubConnectionString\" " + "or pass in \"-e | --EdgeHubConnectionString\" through command line."); Environment.Exit(1); } } } ================================================ FILE: samples/IoTHub/ReadCurrentTime/ReadCurrentTime.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using System.Text.Json; using CommandLine; using InvokeDeviceMethod; using Microsoft.Azure.Devices; Parameters? parameters = null; ParserResult result = Parser.Default.ParseArguments(args) .WithParsed(parsedParams => parameters = parsedParams) .WithNotParsed(errors => Environment.Exit(1)); // This sample accepts the service connection string as a parameter, if present. Parameters.ValidateConnectionStrings(parameters?.IoTHubOwnerConnectionString, parameters?.EdgeHubConnectionString, out var deviceId, out var moduleId); // Create a ServiceClient to communicate with service-facing endpoint on your hub. using var serviceClient = ServiceClient.CreateFromConnectionString(parameters!.IoTHubOwnerConnectionString); while (true) { var methodInvocation = new CloudToDeviceMethod("ValueRead_V2") { ResponseTimeout = TimeSpan.FromSeconds(30), }; methodInvocation.SetPayloadJson(JsonSerializer.Serialize(new { connection = new { endpoint = new { url = "opc.tcp://opcplc:50000", securityMode = "SignAndEncrypt" } }, request = new { nodeId = "i=2258" } })); var response = await serviceClient.InvokeDeviceMethodAsync(deviceId, moduleId, methodInvocation).ConfigureAwait(false); var resopnseJson = JsonSerializer.Deserialize(response.GetPayloadAsJson()); Console.WriteLine("Current time on server:" + resopnseJson.GetProperty("value").GetString()); } ================================================ FILE: samples/IoTHub/ReadCurrentTime/ReadCurrentTime.csproj ================================================  Exe net9.0 enable enable ================================================ FILE: samples/IoTHub/ResetClients/GetAndResetConnections.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using CommandLine; using InvokeDeviceMethod; using Microsoft.Azure.Devices; using System.Net; using System.Text.Json; Parameters? parameters = null; ParserResult result = Parser.Default.ParseArguments(args) .WithParsed(parsedParams => parameters = parsedParams) .WithNotParsed(errors => Environment.Exit(1)); // This sample accepts the service connection string as a parameter, if present. Parameters.ValidateConnectionStrings(parameters?.IoTHubOwnerConnectionString, parameters?.EdgeHubConnectionString, out var deviceId, out var moduleId); // Create a ServiceClient to communicate with service-facing endpoint on your hub. using var serviceClient = ServiceClient.CreateFromConnectionString(parameters!.IoTHubOwnerConnectionString); Console.WriteLine("Active connections:"); var methodInvocation = new CloudToDeviceMethod("GetActiveConnections_V2") { ResponseTimeout = TimeSpan.FromSeconds(30), }; var response = await serviceClient.InvokeDeviceMethodAsync(deviceId, moduleId, methodInvocation).ConfigureAwait(false); var connections = JsonSerializer.Serialize(JsonSerializer.Deserialize(response.GetPayloadAsJson()), Parameters.Indented); Console.WriteLine(connections); Console.WriteLine("Resetting all connections..."); methodInvocation = new CloudToDeviceMethod("ResetAllConnections_V2") { ResponseTimeout = TimeSpan.FromSeconds(30), }; response = await serviceClient.InvokeDeviceMethodAsync(deviceId, moduleId, methodInvocation).ConfigureAwait(false); Console.WriteLine(response.Status); ================================================ FILE: samples/IoTHub/ResetClients/GetAndResetConnections.csproj ================================================  Exe net9.0 enable enable ================================================ FILE: samples/IoTHub/WriteReadbackValue/WriteReadbackValue.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using System.Text.Json; using CommandLine; using InvokeDeviceMethod; using Microsoft.Azure.Devices; Parameters? parameters = null; ParserResult result = Parser.Default.ParseArguments(args) .WithParsed(parsedParams => parameters = parsedParams) .WithNotParsed(errors => Environment.Exit(1)); // This sample accepts the service connection string as a parameter, if present. Parameters.ValidateConnectionStrings(parameters?.IoTHubOwnerConnectionString, parameters?.EdgeHubConnectionString, out var deviceId, out var moduleId); // Create a ServiceClient to communicate with service-facing endpoint on your hub. using var serviceClient = ServiceClient.CreateFromConnectionString(parameters!.IoTHubOwnerConnectionString); // // Perform a couple write and readback operations: // var originalValue = await ReadSlowNumberOfUpdatesValueAsync().ConfigureAwait(false); Console.WriteLine("Original value is: " + originalValue); await WriteSlowNumberOfUpdatesValueAsync(33).ConfigureAwait(false); var updatedValue = await ReadSlowNumberOfUpdatesValueAsync().ConfigureAwait(false); Console.WriteLine("Value updated to : " + updatedValue); await WriteSlowNumberOfUpdatesValueAsync(44).ConfigureAwait(false); updatedValue = await ReadSlowNumberOfUpdatesValueAsync().ConfigureAwait(false); Console.WriteLine("Value updated to : " + updatedValue); await WriteSlowNumberOfUpdatesValueAsync(originalValue).ConfigureAwait(false); originalValue = await ReadSlowNumberOfUpdatesValueAsync().ConfigureAwait(false); Console.WriteLine("Now reset back to: " + originalValue); // // Helpers functions // // Read value of the slow number of updates configuration node async ValueTask ReadSlowNumberOfUpdatesValueAsync() { var methodInvocation = new CloudToDeviceMethod("ValueRead") { ResponseTimeout = TimeSpan.FromSeconds(30), }; methodInvocation.SetPayloadJson(JsonSerializer.Serialize(new { connection = new { endpoint = new { url = "opc.tcp://opcplc:50000", securityMode = "SignAndEncrypt" } }, request = new { nodeId = "nsu=http://microsoft.com/Opc/OpcPlc/;s=SlowNumberOfUpdates" } })); var response = await serviceClient.InvokeDeviceMethodAsync(deviceId, moduleId, methodInvocation).ConfigureAwait(false); var resopnseJson = JsonSerializer.Deserialize(response.GetPayloadAsJson()); return resopnseJson.GetProperty("value").GetInt32(); } // Write value to the slow number of updates configuration node async ValueTask WriteSlowNumberOfUpdatesValueAsync(int value) { var methodInvocation = new CloudToDeviceMethod("ValueWrite") { ResponseTimeout = TimeSpan.FromSeconds(30), }; methodInvocation.SetPayloadJson(JsonSerializer.Serialize(new { connection = new { endpoint = new { url = "opc.tcp://opcplc:50000", securityMode = "SignAndEncrypt" } }, request = new { nodeId = "nsu=http://microsoft.com/Opc/OpcPlc/;s=SlowNumberOfUpdates", value } })); await serviceClient.InvokeDeviceMethodAsync(deviceId, moduleId, methodInvocation).ConfigureAwait(false); } ================================================ FILE: samples/IoTHub/WriteReadbackValue/WriteReadbackValue.csproj ================================================  Exe net9.0 enable enable ================================================ FILE: samples/IoTHub/readme.md ================================================ # Azure IoT Hub Samples This folder contains several samples that show how to interact with the OPC Publisher through Azure IoT Hub service and show for example how to read or write values. To run the samples, first start OPC Publisher and OPC PLC simulation server: ```bash cd deploy cd docker set EdgeHubConnectionString= docker compose up ``` Another option is to deploy both into IoT Edge or run them inside the simulation environment as explained [here](../../docs/opc-publisher/opc-publisher.md#using-iot-edge-simulation-environment). You also need to set both the `EdgeHubConnectionString` and the Azure IoT Hub connection string in your environment before running the samples: ```bash set EdgeHubConnectionString= set IoTHubConnectionString= ``` > Restart Visual Studio to pick up the environment variables. > IMPORTANT: The connection strings contain secrets, ensure you clear them and don't share them outside of your environment. ================================================ FILE: samples/Mqtt/GetConfiguration/GetConfiguration.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using MQTTnet.Protocol; using MQTTnet.Formatter; using MQTTnet; using MQTTnet.Extensions.Rpc; using System.Text.Json; using System.Text; // Connect to mqtt broker var mqttFactory = new MqttClientFactory(); using var mqttClient = mqttFactory.CreateMqttClient(); var mqttClientOptions = new MqttClientOptionsBuilder() .WithProtocolVersion(MqttProtocolVersion.V500) // Important!! .WithTcpServer("localhost", 1883) .Build(); await mqttClient.ConnectAsync(mqttClientOptions).ConfigureAwait(false); using var mqttRpcClient = mqttFactory.CreateMqttRpcClient(mqttClient, new MqttRpcClientOptionsBuilder().WithTopicGenerationStrategy(new PublisherTopicGenerationStrategy()).Build()); var response = await mqttRpcClient.ExecuteAsync(TimeSpan.FromSeconds(60), "GetConfiguredEndpoints", default, MqttQualityOfServiceLevel.AtMostOnce).ConfigureAwait(false); try { var endpoints = JsonSerializer.Deserialize(response).GetProperty("endpoints").EnumerateArray(); var indented = new JsonSerializerOptions { WriteIndented = true }; foreach (var endpoint in endpoints) { var endpointJson = JsonSerializer.Serialize(endpoint, indented); Console.WriteLine(endpointJson); response = await mqttRpcClient.ExecuteAsync(TimeSpan.FromSeconds(60), "GetConfiguredNodesOnEndpoint", endpointJson, MqttQualityOfServiceLevel.AtMostOnce).ConfigureAwait(false); var nodesJson = JsonSerializer.Serialize(JsonSerializer.Deserialize(response), indented); Console.WriteLine(nodesJson); } } catch { var error = Encoding.UTF8.GetString(response); Console.WriteLine(error); } public sealed class PublisherTopicGenerationStrategy : IMqttRpcClientTopicGenerationStrategy { // Both are configured in with-mosquitto.yaml const string PublisherId = "Microsoft"; public MqttRpcTopicPair CreateRpcTopics(TopicGenerationContext context) { // THe default method topic root is var methodTopicRoot = $"{PublisherId}/methods"; return new MqttRpcTopicPair { RequestTopic = $"{methodTopicRoot}/{context.MethodName}", ResponseTopic = $"{methodTopicRoot}/{context.MethodName}/response" }; } } ================================================ FILE: samples/Mqtt/GetConfiguration/GetConfiguration.csproj ================================================  Exe net9.0 enable enable ================================================ FILE: samples/Mqtt/ManageWriter/ManageWriter.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using MQTTnet.Protocol; using MQTTnet.Formatter; using MQTTnet; using MQTTnet.Extensions.Rpc; using System.Text.Json; using System.Text; // Connect to mqtt broker var mqttFactory = new MqttClientFactory(); using var mqttClient = mqttFactory.CreateMqttClient(); var mqttClientOptions = new MqttClientOptionsBuilder() .WithProtocolVersion(MqttProtocolVersion.V500) // Important!! .WithTcpServer("localhost", 1883) .Build(); await mqttClient.ConnectAsync(mqttClientOptions).ConfigureAwait(false); using var mqttRpcClient = mqttFactory.CreateMqttRpcClient(mqttClient, new MqttRpcClientOptionsBuilder().WithTopicGenerationStrategy(new PublisherTopicGenerationStrategy()).Build()); // Delete old writers var response = await mqttRpcClient.ExecuteAsync(TimeSpan.FromSeconds(60), "RemoveDataSetWriterEntry", JsonSerializer.Serialize(new { dataSetWriterId = "MyWriterId", dataSetWriterGroup = "MyWriterGroup" }), MqttQualityOfServiceLevel.AtMostOnce).ConfigureAwait(false); if (response.Length > 1) { var error = Encoding.UTF8.GetString(response); Console.WriteLine(error); } // For payload see PublishedNodesEntryModel format response = await mqttRpcClient.ExecuteAsync(TimeSpan.FromSeconds(60), "CreateOrUpdateDataSetWriterEntry", JsonSerializer.Serialize(new { endpointUrl = "opc.tcp://opcplc:50000", endpointSecurityMode = "SignAndEncrypt", dataSetWriterId = "MyWriterId", dataSetWriterGroup = "MyWriterGroup", dataSetPublishingInterval = 2000, opcNodes = new[] { new { id = "i=2258", dataSetFieldId = "Time0", opcSamplingInterval = 1000 }, } }), MqttQualityOfServiceLevel.AtMostOnce).ConfigureAwait(false); if (response.Length > 1) { var error = Encoding.UTF8.GetString(response); Console.WriteLine(error); } // Update the writer and add additional nodes for (var i = 0; i < 10; i++) { response = await mqttRpcClient.ExecuteAsync(TimeSpan.FromSeconds(60), "AddOrUpdateNodes", JsonSerializer.Serialize(new { dataSetWriterId = "MyWriterId", dataSetWriterGroup = "MyWriterGroup", opcNodes = new[] { new { id = "i=2258", dataSetFieldId = "Time" + i, opcSamplingInterval = 1000 } } }), MqttQualityOfServiceLevel.AtMostOnce).ConfigureAwait(false); if (response.Length > 1) { var error = Encoding.UTF8.GetString(response); Console.WriteLine(error); } } // Show the nodes in the writer response = await mqttRpcClient.ExecuteAsync(TimeSpan.FromSeconds(60), "GetNodes", JsonSerializer.Serialize(new { dataSetWriterGroup = "MyWriterGroup", dataSetWriterId = "MyWriterId" }), MqttQualityOfServiceLevel.AtMostOnce).ConfigureAwait(false); try { var indented = new JsonSerializerOptions { WriteIndented = true }; var nodesJson = JsonSerializer.Serialize(JsonSerializer.Deserialize(response), indented); Console.WriteLine(nodesJson); } catch { var error = Encoding.UTF8.GetString(response); Console.WriteLine(error); } public sealed class PublisherTopicGenerationStrategy : IMqttRpcClientTopicGenerationStrategy { // Both are configured in with-mosquitto.yaml const string PublisherId = "Microsoft"; public MqttRpcTopicPair CreateRpcTopics(TopicGenerationContext context) { // THe default method topic root is var methodTopicRoot = $"{PublisherId}/methods"; return new MqttRpcTopicPair { RequestTopic = $"{methodTopicRoot}/{context.MethodName}", ResponseTopic = $"{methodTopicRoot}/{context.MethodName}/response" }; } } ================================================ FILE: samples/Mqtt/ManageWriter/ManageWriter.csproj ================================================  Exe net9.0 enable enable ================================================ FILE: samples/Mqtt/MonitorMessages/MonitorMessages.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using MQTTnet.Formatter; using MQTTnet; using System.Text.Json; using System.Buffers; // Connect to mqtt broker var mqttFactory = new MqttClientFactory(); using var mqttClient = mqttFactory.CreateMqttClient(); var mqttClientOptions = new MqttClientOptionsBuilder() .WithProtocolVersion(MqttProtocolVersion.V500) // Important!! .WithTcpServer("localhost", 1883) .Build(); await mqttClient.ConnectAsync(mqttClientOptions).ConfigureAwait(false); var indented = new JsonSerializerOptions() { WriteIndented = true }; mqttClient.ApplicationMessageReceivedAsync += args => { var reader = new Utf8JsonReader(args.ApplicationMessage.Payload); var json = JsonSerializer.Serialize(JsonSerializer.Deserialize(ref reader), indented); Console.WriteLine($"{args.ApplicationMessage.Topic}:{json}"); return Task.CompletedTask; }; Console.WriteLine("Press key to exit"); Console.WriteLine(); const string PublisherId = "Microsoft"; await mqttClient.SubscribeAsync(new MqttClientSubscribeOptionsBuilder() .WithTopicFilter(new MqttTopicFilterBuilder() .WithTopic($"{PublisherId}/#") .Build()) .Build()).ConfigureAwait(false); Console.ReadKey(); ================================================ FILE: samples/Mqtt/MonitorMessages/MonitorMessages.csproj ================================================  Exe net9.0 enable enable ================================================ FILE: samples/Mqtt/MqttSamples.slnx ================================================ ================================================ FILE: samples/Mqtt/ReadAttributes/ReadAttributes.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using MQTTnet.Protocol; using MQTTnet.Formatter; using MQTTnet; using MQTTnet.Extensions.Rpc; using System.Text.Json; using System.Text; // Connect to mqtt broker var mqttFactory = new MqttClientFactory(); using var mqttClient = mqttFactory.CreateMqttClient(); var mqttClientOptions = new MqttClientOptionsBuilder() .WithProtocolVersion(MqttProtocolVersion.V500) // Important!! .WithTcpServer("localhost", 1883) .Build(); await mqttClient.ConnectAsync(mqttClientOptions).ConfigureAwait(false); using var mqttRpcClient = mqttFactory.CreateMqttRpcClient(mqttClient, new MqttRpcClientOptionsBuilder().WithTopicGenerationStrategy(new PublisherTopicGenerationStrategy()).Build()); while (true) { // Read attributes from server - see NodeRead api in api.md var response = await mqttRpcClient.ExecuteAsync(TimeSpan.FromSeconds(60), "NodeRead_V2", JsonSerializer.SerializeToUtf8Bytes(new { connection = new { endpoint = new { url = "opc.tcp://opcplc:50000", securityMode = 2, securityPolicy = "http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256" } }, request = new { attributes = new[] { new { nodeId = "i=2258", attribute = 3 }, new { nodeId = "i=2258", attribute = 4 }, new { nodeId = "i=2258", attribute = 5 }, new { nodeId = "i=2258", attribute = 13 }, new { nodeId = "i=2258", attribute = 14 }, new { nodeId = "i=2258", attribute = 15 } } } }), MqttQualityOfServiceLevel.AtMostOnce).ConfigureAwait(false); try { var resopnseJson = JsonSerializer.Deserialize(response); Console.WriteLine(); foreach (var item in resopnseJson.GetProperty("results").EnumerateArray()) { Console.WriteLine(item.GetProperty("value").ToString()); } } catch { Console.WriteLine(Encoding.UTF8.GetString(response)); } } public sealed class PublisherTopicGenerationStrategy : IMqttRpcClientTopicGenerationStrategy { // Both are configured in with-mosquitto.yaml const string PublisherId = "Microsoft"; public MqttRpcTopicPair CreateRpcTopics(TopicGenerationContext context) { // THe default method topic root is var methodTopicRoot = $"{PublisherId}/methods"; return new MqttRpcTopicPair { RequestTopic = $"{methodTopicRoot}/{context.MethodName}", ResponseTopic = $"{methodTopicRoot}/{context.MethodName}/response" }; } } ================================================ FILE: samples/Mqtt/ReadAttributes/ReadAttributes.csproj ================================================  Exe net9.0 enable enable ================================================ FILE: samples/Mqtt/ReadCurrentTime/ReadCurrentTime.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using MQTTnet.Protocol; using MQTTnet.Formatter; using MQTTnet; using MQTTnet.Extensions.Rpc; using System.Text.Json; // Connect to mqtt broker var mqttFactory = new MqttClientFactory(); using var mqttClient = mqttFactory.CreateMqttClient(); var mqttClientOptions = new MqttClientOptionsBuilder() .WithProtocolVersion(MqttProtocolVersion.V500) // Important!! .WithTcpServer("localhost", 1883) .Build(); await mqttClient.ConnectAsync(mqttClientOptions).ConfigureAwait(false); using var mqttRpcClient = mqttFactory.CreateMqttRpcClient(mqttClient, new MqttRpcClientOptionsBuilder().WithTopicGenerationStrategy(new PublisherTopicGenerationStrategy()).Build()); while (true) { // Read current time from server - see ValueRead api in api.md var response = await mqttRpcClient.ExecuteAsync(TimeSpan.FromSeconds(60), "ValueRead_V2", JsonSerializer.SerializeToUtf8Bytes(new { connection = new { endpoint = new { url = "opc.tcp://opcplc:50000", securityMode = "SignAndEncrypt" } }, request = new { nodeId = "i=2258" } }), MqttQualityOfServiceLevel.AtMostOnce).ConfigureAwait(false); var resopnseJson = JsonSerializer.Deserialize(response); Console.WriteLine("Current time on server:" + resopnseJson.GetProperty("value").GetString()); } public sealed class PublisherTopicGenerationStrategy : IMqttRpcClientTopicGenerationStrategy { // Both are configured in with-mosquitto.yaml const string PublisherId = "Microsoft"; public MqttRpcTopicPair CreateRpcTopics(TopicGenerationContext context) { // THe default method topic root is var methodTopicRoot = $"{PublisherId}/methods"; return new MqttRpcTopicPair { RequestTopic = $"{methodTopicRoot}/{context.MethodName}", ResponseTopic = $"{methodTopicRoot}/{context.MethodName}/response" }; } } ================================================ FILE: samples/Mqtt/ReadCurrentTime/ReadCurrentTime.csproj ================================================  Exe net9.0 enable enable ================================================ FILE: samples/Mqtt/WriteReadbackValue/WriteReadbackValue.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using MQTTnet.Protocol; using MQTTnet.Formatter; using MQTTnet; using MQTTnet.Extensions.Rpc; using System.Text.Json; // Connect to mqtt broker var mqttFactory = new MqttClientFactory(); using var mqttClient = mqttFactory.CreateMqttClient(); var mqttClientOptions = new MqttClientOptionsBuilder() .WithProtocolVersion(MqttProtocolVersion.V500) // Important!! .WithTcpServer("localhost", 1883) .Build(); await mqttClient.ConnectAsync(mqttClientOptions).ConfigureAwait(false); using var mqttRpcClient = mqttFactory.CreateMqttRpcClient(mqttClient, new MqttRpcClientOptionsBuilder().WithTopicGenerationStrategy(new PublisherTopicGenerationStrategy()).Build()); // // Perform a couple write and readback operations: // var originalValue = await ReadSlowNumberOfUpdatesValueAsync().ConfigureAwait(false); Console.WriteLine("Original value is: " + originalValue); await WriteSlowNumberOfUpdatesValueAsync(33).ConfigureAwait(false); var updatedValue = await ReadSlowNumberOfUpdatesValueAsync().ConfigureAwait(false); Console.WriteLine("Value updated to : " + updatedValue); await WriteSlowNumberOfUpdatesValueAsync(44).ConfigureAwait(false); updatedValue = await ReadSlowNumberOfUpdatesValueAsync().ConfigureAwait(false); Console.WriteLine("Value updated to : " + updatedValue); await WriteSlowNumberOfUpdatesValueAsync(originalValue).ConfigureAwait(false); originalValue = await ReadSlowNumberOfUpdatesValueAsync().ConfigureAwait(false); Console.WriteLine("Now reset back to: " + originalValue); // // Helpers functions // // Read value of the slow number of updates configuration node async ValueTask ReadSlowNumberOfUpdatesValueAsync() { var response = await mqttRpcClient.ExecuteAsync(TimeSpan.FromSeconds(60), "ValueRead", JsonSerializer.SerializeToUtf8Bytes(new { connection = new { endpoint = new { url = "opc.tcp://opcplc:50000", securityMode = "SignAndEncrypt" } }, request = new { nodeId = "nsu=http://microsoft.com/Opc/OpcPlc/;s=SlowNumberOfUpdates", } }), MqttQualityOfServiceLevel.AtMostOnce).ConfigureAwait(false); var resopnseJson = JsonSerializer.Deserialize(response); return resopnseJson.GetProperty("value").GetInt32(); } // Write value to the slow number of updates configuration node async ValueTask WriteSlowNumberOfUpdatesValueAsync(int value) { await mqttRpcClient.ExecuteAsync(TimeSpan.FromSeconds(60), "ValueWrite", JsonSerializer.SerializeToUtf8Bytes(new { connection = new { endpoint = new { url = "opc.tcp://opcplc:50000", securityMode = "SignAndEncrypt" } }, request = new { nodeId = "nsu=http://microsoft.com/Opc/OpcPlc/;s=SlowNumberOfUpdates", value } }), MqttQualityOfServiceLevel.AtMostOnce).ConfigureAwait(false); } public sealed class PublisherTopicGenerationStrategy : IMqttRpcClientTopicGenerationStrategy { // Both are configured in with-mosquitto.yaml const string PublisherId = "Microsoft"; public MqttRpcTopicPair CreateRpcTopics(TopicGenerationContext context) { // THe default method topic root is var methodTopicRoot = $"{PublisherId}/methods"; return new MqttRpcTopicPair { RequestTopic = $"{methodTopicRoot}/{context.MethodName}", ResponseTopic = $"{methodTopicRoot}/{context.MethodName}/response" }; } } ================================================ FILE: samples/Mqtt/WriteReadbackValue/WriteReadbackValue.csproj ================================================  Exe net9.0 enable enable ================================================ FILE: samples/Mqtt/readme.md ================================================ # MQTT Samples This folder contains several samples that show how to interact with the OPC Publisher over MQTT and show how to read values or subscribe to telemetry sent by the OPC Publisher. To run the samples, first start OPC Publisher and Mosquitto MQTT broker: ````bash cd deploy cd docker docker compose -f docker-compose.yaml -f with-mosquitto.yaml up ``` The samples will communicate through the mosquitto broker which runs at localhost:1883. > For simplicity of the same, the broker is listening on port 1883 and thus an unencrypted connection is used. In production, ensure to use TLS. The sample uses the MQTT.net RPC library. The MQTT.net RPC libary does not support error conditions, and the ExecuteAsync call returns just the response buffer and no additional context of the MQTT message. OPC Publisher will return a status code as part of the user properties of the response message which can be read via other MQTT libraries. ================================================ FILE: samples/Netcap/Directory.Build.props ================================================  ================================================ FILE: samples/Netcap/Netcap.slnx ================================================ ================================================ FILE: samples/Netcap/build.sh ================================================ #!/bin/bash set -e cd src docker build -t netcap:latest . docker run -it --cap-add=NET_ADMIN netcap:latest $@ ================================================ FILE: samples/Netcap/readme.md ================================================ # Netcap Diagnostic Tool > **This tool is provided as a sample, as-is and without any support and warranty. When used in production please be aware that it is invasive and should be used with care.** The Netcap tool is designed to help diagnose interop issues with OPC UA servers that OPC Publisher connects to and which the normal logs of OPC Publisher fail to diagnose. To support diagnosis, Netcap collects network traces remotely from a OPC Publisher deployment and then makes the traces available for download and analysis. It is implemented as a sidecar to OPC Publisher that must be running in the same network as OPC Publisher (and see the same endpoints). > Netcap can only diagnose OPC Publisher versions 2.9.10 or higher! The Netcap tool has three modes of operation: 1. **Install Mode**: Allows installation of Netcap on a remote Azure IoT Edge device as side car of a running OPC Publisher module. Installation provisions a storage account and container registry in the same resource group as the IoT Hub the device is connected to, then builds and deploys Netcap to the IoT Edge device. If installed with an output path (`-o`) it will also download the network traces (.pcap files) during the capture session and then remove the Netcap module from the IoT Edge device once capture is cancelled (key press). 2. **Remote Mode**: Netcap connects to the OPC Publisher and starts to capture tcp dumps filtered to the OPC Publisher IP addresses. The capture traces are chunked to (by default) 5 minutes or 100 MB whichever is reached first, and then the traces are uploaded. There will not be gaps between traces. This happens as long as the Netcap module is deployed. 3. **Proxy Mode**: Netcap captures traces on a different network than OPC Publisher is connected to, e.g. the host network. It then exposes a remote API to allow the OPC Publisher side car to retrieve and upload the traces. 4. **Uninstall Mode**: Removes the Netcap module from the IoT Edge device. This leaves the storage account and container registry in place which must can be removed in Cleanup mode. Installation and un-installation require administrator rights to the subscription in which the Azure IoT Hub resides that OPC Publisher is connected to. Rights must include access to the Azure IoT Hub resource as well as the permission to create storage and container registry resources in the same resource group as the IoT Hub instance. If you do not have permissions to create resources in the subscription and/or resource group, you must build Netcap and deploy it manually. ## Getting started In the `src` sub folder run ``` bash dotnet run -- install -o ``` or if you want to use docker you can also run ``` bash docker build -t netcap . docker run -it -v :/tmp netcap install -d -o /tmp ``` > Do not forget to specify the `-d` option to force authorizing with Azure Resource Manager (ARM) using the device code flow. Follow the instructions to select a OPC Publisher you want to diagnose. When you are done, cancel capture by pressing any key. The folder you specified now contains the key set logs and a capture file (`capture.pcap`) which you can open in Wireshark. In the `Preferences` view under `Edit` select the page for the OPC UA protocol. You must enter the port of the OPC UA server there. You can consult the session `*.log` file you are interested in the download folder. The file name starts with the port number (or the log contains it). You can also provide the key set to decrypt encrypted traffic which is the corresponding `*.txt` file with the same name as the `*.log` file (requires Wireshark 4.3 RC builds). Once saved, you can filter the traces using the `opcua` filter in the filter edit box on the main screen. Tip: right click on the traces and you can select the OPC UA protocol configuration directly from there. ## Advanced install options For installation and un-installation you might want to narrow down where Netcap looks for OPC Publisher deployments it should consider presenting to you. Use the `-s` option to specify the subscription. If you are working in multiple tenants, specify the tenant ID using the `-t` command line option. During installation the Netcap tool is built using the deployed Azure Container Registry (ACR) instance using the source found in the main branch of this repository. If you want to use a different branch, you must specify this branch using the `-b` option during installation. All captured files are stored in the storage account provisioned during installation. The storage account contains sensitive data that must be handled with care, e.g. in addition to the OPC Publisher configuration it also contains key/token material that can be used in Wireshark 4.3 to decrypt secure channel communication inside the network traces. ================================================ FILE: samples/Netcap/src/.dockerignore ================================================ **/.dockerignore **/.env **/.gitignore **/.project **/.settings **/.toolstarget **/.vs **/.vscode **/*.sh **/*.bat **/*.cmd **/*.props **/*.*proj.user **/*.dbmdl **/*.jfm **/azds.yaml **/charts **/docker-compose* **/Dockerfile* **/obj **/bin **/secrets.dev.yaml **/values.dev.yaml LICENSE README.md !**/.gitignore !.git/HEAD !.git/config !.git/packed-refs !.git/refs/heads/** ================================================ FILE: samples/Netcap/src/Dockerfile ================================================ FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base ARG BRANCH=main ARG VERSION RUN apt update -y \ && apt install -y apt-utils \ && echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections \ && apt install -y libpcap-dev bash net-tools USER root:root ENV BRANCH=${BRANCH} ENV VERSION=${VERSION} WORKDIR /app FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build ARG BUILD_CONFIGURATION=Release WORKDIR /src COPY ["Netcap.csproj", "."] RUN dotnet restore "./Netcap.csproj" COPY . . WORKDIR "/src/." RUN dotnet build "./Netcap.csproj" -c $BUILD_CONFIGURATION -o /app/build FROM build AS publish ARG BUILD_CONFIGURATION=Release RUN dotnet publish "./Netcap.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false FROM base AS final WORKDIR /app COPY --from=publish /app/publish . ENTRYPOINT ["dotnet", "Netcap.dll"] ================================================ FILE: samples/Netcap/src/Extensions.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Netcap; using Microsoft.Azure.Devices.Shared; using System.Buffers; using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Text.Json; using System.Text.RegularExpressions; /// /// Various extensions /// internal static partial class Extensions { /// /// Stop property /// /// /// /// /// /// [return: NotNullIfNotNull(nameof(defaultValue))] public static string? GetProperty(this Twin twin, string name, string? defaultValue = null, bool desired = true) { var bag = desired ? twin.Properties.Desired : twin.Properties.Reported; if (!bag.Contains(name)) { return defaultValue; } var value = bag[name]; var result = (string?)value?.ToString(); if (string.IsNullOrEmpty(result)) { return defaultValue; } return result; } /// /// Stop tag /// /// /// /// /// [return: NotNullIfNotNull(nameof(defaultValue))] public static string? GetTag(this Twin twin, string name, string? defaultValue = null) { if (!twin.Tags.Contains(name)) { return defaultValue; } var value = twin.Tags[name]; var result = (string?)value?.ToString(); if (string.IsNullOrEmpty(result)) { return defaultValue; } return result; } /// /// Stop bytes /// /// /// /// public static bool TryGetBytes(this JsonElement elem, [NotNullWhen(true)] out byte[]? value) { if (elem.ValueKind == JsonValueKind.Array) { value = elem.EnumerateArray().Select(d => d.GetByte()).ToArray(); return true; } if (elem.ValueKind == JsonValueKind.String) { return elem.TryGetBytesFromBase64(out value); } value = default; return false; } /// /// Fix a unique name for a resource /// /// /// public static string FixUpResourceName(string name) { name = AlphaNumOnly().Replace(name, ""); if (name.Length > 24) { name = name[..24]; } return name; } /// /// Stop assembly version /// /// public static string GetVersion(this Assembly assembly) { var branch = Environment.GetEnvironmentVariable("BRANCH"); branch = !string.IsNullOrEmpty(branch) ? "-" + branch : string.Empty; var ver = assembly.GetCustomAttribute()?.Version; if (ver == null || !Version.TryParse(ver, out var assemblyVersion)) { ver = Environment.GetEnvironmentVariable("VERSION"); if (ver == null || !Version.TryParse(ver, out assemblyVersion)) { assemblyVersion = new Version(); } } return assemblyVersion + branch; } /// /// Fix file name /// /// /// public static string FixFileName(string name) { return string.Join('_', name.Split(Path.GetInvalidFileNameChars(), StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)); } /// /// Fix folder name /// /// /// public static string FixFolderName(string name) { return string.Join('_', name.Split(Path.GetInvalidPathChars(), StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)); } /// /// Replace invalid chars in a storage entity name /// /// /// public static string FixUpStorageName(string name) { // Remove any invalid characters var containerName = AlphaNumAndDashOnly().Replace(name, ""); containerName = containerName.Trim('-'); // Check length if (containerName.Length < 3) { containerName = containerName.PadRight(3, 'x'); } else if (containerName.Length > 63) { containerName = containerName[..63]; } #pragma warning disable CA1308 // Normalize strings to uppercase return containerName.ToLowerInvariant(); #pragma warning restore CA1308 // Normalize strings to uppercase } /// /// Copy stream without /// /// /// /// /// public static async Task CopyAsync(this Stream source, Stream destination, CancellationToken ct = default) { var copied = 0; var buffer = ArrayPool.Shared.Rent(8 * 1024); try { while (!ct.IsCancellationRequested) { var bytesRead = await source.ReadAsync(new Memory(buffer), ct).ConfigureAwait(false); if (bytesRead == 0) { break; } copied += bytesRead; await destination.WriteAsync(new ReadOnlyMemory( buffer, 0, bytesRead), ct).ConfigureAwait(false); } } finally { ArrayPool.Shared.Return(buffer); } return copied; } /// /// Returns true if running in container. /// /// public static bool IsRunningInContainer() { return Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") != null; } public static readonly JsonSerializerOptions Indented = new() { WriteIndented = true }; [GeneratedRegex("[^a-zA-Z0-9-]")] private static partial Regex AlphaNumAndDashOnly(); [GeneratedRegex("[^a-zA-Z0-9]")] private static partial Regex AlphaNumOnly(); } ================================================ FILE: samples/Netcap/src/Gateway.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Netcap; using Azure; using Azure.ResourceManager; using Azure.ResourceManager.Storage; using Azure.ResourceManager.Storage.Models; using Azure.ResourceManager.ContainerRegistry.Models; using Azure.ResourceManager.ContainerRegistry; using Azure.ResourceManager.IotHub; using Azure.ResourceManager.Resources; using Azure.ResourceManager.IotHub.Models; using Azure.Storage.Blobs; using Azure.Storage.Blobs.Models; using Microsoft.Azure.Devices; using Microsoft.Extensions.Logging; using Microsoft.Azure.Devices.Common.Exceptions; using Microsoft.Azure.Devices.Shared; using System.Diagnostics; using System.Runtime.CompilerServices; using Newtonsoft.Json; using Newtonsoft.Json.Linq; /// /// Represents and edge gateway that can be accessed from /// cloud. /// internal sealed record class Gateway { /// /// Stop image /// /// public NetcapImage Netcap { get; } /// /// Stop storage /// /// public NetcapStorage Storage { get; } /// /// Create gateway /// /// /// /// public Gateway(ArmClient client, ILogger logger, string? branch = null) { _client = client; _logger = logger; Netcap = new NetcapImage(this, branch, logger); Storage = new NetcapStorage(this, logger); } /// /// Select publisher /// /// /// /// /// /// public async ValueTask SelectPublisherAsync(string? subscriptionId = null, bool netcapMonitored = false, CancellationToken ct = default) { while (!ct.IsCancellationRequested) { // Stop target publishers in iot hubs var deployments = await GetPublisherDeploymentsAsync(subscriptionId, netcapMonitored, ct).ToListAsync(ct).ConfigureAwait(false); // Select IoT Hub with publisher modules deployed if (deployments.Count == 0) { if (!Extensions.IsRunningInContainer()) { Console.WriteLine("No publishers found. Check again? [Y/N]"); var key = Console.ReadKey(); Console.WriteLine(); if (key.Key != ConsoleKey.Y) { break; } } else { _logger.LogInformation("No publishers found. Trying again..."); await Task.Delay(TimeSpan.FromSeconds(5), ct).ConfigureAwait(false); } continue; } var selected = deployments[0]; if (deployments.Count > 1) { Console.Clear(); Console.WriteLine($"Found {deployments.Count} publishers:"); for (var index = 0; index < deployments.Count; index++) { Console.WriteLine($"{index + 1}: {deployments[index]}"); } int i; Console.WriteLine("Select publisher index: "); while (true) { if (int.TryParse(Console.ReadLine(), out i) && i <= deployments.Count && i > 0) { break; } } Console.WriteLine(); selected = deployments[i - 1]; } else if (!Extensions.IsRunningInContainer()) { Console.WriteLine("Found 1 publisher."); var action = netcapMonitored ? "Detach from" : "Attach to"; Console.WriteLine($"{action} {selected}? [Y/N]"); var key = Console.ReadKey(); Console.WriteLine(); if (key.Key != ConsoleKey.Y) { _logger.LogInformation( "Trying again to find other publishers..."); continue; } } _subscription = selected.Subscription; _deploymentConfigId = selected.DeploymentConfigId; _resourceGroupName = selected.ResourceGroupName; _connectionString = selected.ConnectionString; _iotHubName = selected.IoTHub.Name; _publisher = selected.Publisher; return true; } return false; } /// /// Stop resource group /// /// /// /// public async Task GetResourceGroupAsync( CancellationToken ct = default) { if (_resourceGroupName == null || _subscription == null) { throw new NetcapException("Hub not selected"); } return await _subscription.GetResourceGroupAsync(_resourceGroupName, ct).ConfigureAwait(false); } /// /// Stop storage /// /// /// public Storage GetStorage() { if (_publisher == null || _subscription == null) { throw new NetcapException("Publisher not selected"); } return new Storage(_publisher.DeviceId, _publisher.Id, Storage.ConnectionString, _logger); } /// /// Deploy netcap module and wait until it is connected /// /// /// /// public async ValueTask DeployNetcapModuleAsync(CancellationToken ct = default) { if (_publisher == null || _connectionString == null) { throw new NetcapException("Publisher not selected"); } // Remove storage await GetStorage().DeleteAsync(ct).ConfigureAwait(false); // Deploy the module using manifest to device with the chosen publisher using var registryManager = RegistryManager.CreateFromConnectionString( _connectionString); var ncModuleId = _publisher.Id + kPostFix; _deploymentConfigId = Extensions.FixUpStorageName( _publisher.DeviceId + ncModuleId); try { await registryManager.RemoveConfigurationAsync(_deploymentConfigId, ct).ConfigureAwait(false); } catch (ConfigurationNotFoundException) { } var publisherTwin = await registryManager.GetTwinAsync(_publisher.DeviceId, _publisher.Id, ct).ConfigureAwait(false); var hostname = publisherTwin.GetProperty("__hostname__", desired: false); var port = publisherTwin.GetProperty("__port__", desired: false); // Stop the create options of the publisher var agent = await registryManager.GetTwinAsync(_publisher.DeviceId, "$edgeAgent", ct).ConfigureAwait(false); if (agent?.Properties.Desired.Contains("modules") == true) { var publisherDeployment = agent.Properties.Desired["modules"][_publisher.Id]; if (publisherDeployment != null) { var settings = publisherDeployment["settings"]; var options = (string?)settings["createOptions"]; if (options != null) { var createOptions = JObject.Parse(options .Replace("\\\"", "\"", StringComparison.Ordinal)); if (createOptions.TryGetValue("Hostname", out var hn) && hn.Type == JTokenType.String) { hostname = hn.Value(); } if (createOptions.TryGetValue("HostConfig", out var cfg) && cfg is JObject hostConfig && hostConfig.TryGetValue("PortBindings", out var bd) && bd is JObject bindings) { // Looks like {\"443/tcp\":[{\"HostPort\":\"8081\"}]} foreach (var pm in bindings) { if (pm.Key.StartsWith("443", StringComparison.Ordinal) && pm.Value is JArray arr && arr.Count > 0 && arr[0] is JObject o && o.TryGetValue("HostPort", out var p)) { port = p.Value(); hostname = "localhost"; // Connect to host port } } } } } } await registryManager.AddConfigurationAsync( new Configuration(_deploymentConfigId) { TargetCondition = $"deviceId = '{_publisher.DeviceId}'", Content = new ConfigurationContent { ModulesContent = CreateSidecarDeployment(_publisher.DeviceId, ncModuleId, _publisher.Id, Netcap.LoginServer, Netcap.Username, Netcap.Password, Netcap.Name, Storage.ConnectionString, publisherTwin.GetProperty("__apikey__", desired: false), publisherTwin.GetProperty("__certificate__", desired: false), publisherTwin.GetProperty("__scheme__", desired: false), publisherTwin.GetProperty("__ip__", desired: false), hostname, port) } }, ct).ConfigureAwait(false); await registryManager.UpdateTwinAsync(_publisher.DeviceId, _publisher.Id, new Twin { Tags = new TwinCollection { [kDeploymentTag] = _deploymentConfigId } }, publisherTwin.ETag, ct).ConfigureAwait(false); _logger.LogInformation("Deploying netcap module to {DeviceId}...", _publisher.DeviceId); // Wait until connected var connected = false; for (var i = 1; !connected && !ct.IsCancellationRequested; i++) { await Task.Delay(TimeSpan.FromSeconds(Math.Min(i, 10)), ct).ConfigureAwait(false); var modules = await registryManager.GetModulesOnDeviceAsync( _publisher.DeviceId, ct).ConfigureAwait(false); connected = modules.Any(m => m.Id == ncModuleId && m.ConnectionState == DeviceConnectionState.Connected); } _logger.LogInformation("Netcap module deployed to {DeviceId}.", _publisher.DeviceId); } /// /// Remove deployment /// /// /// /// public async ValueTask RemoveNetcapModuleAsync(CancellationToken ct = default) { if (_publisher == null || _connectionString == null || _deploymentConfigId == null) { throw new NetcapException("Publisher not selected"); } using var registryManager = RegistryManager.CreateFromConnectionString( _connectionString); var ncModuleId = _publisher.Id + kPostFix; await registryManager.UpdateTwinAsync(_publisher.DeviceId, _publisher.Id, new Twin { Tags = new TwinCollection { [kDeploymentTag] = null } }, etag: "*", ct).ConfigureAwait(false); await registryManager.RemoveConfigurationAsync( _deploymentConfigId, ct).ConfigureAwait(false); // Uninstalled _deploymentConfigId = null; _logger.LogInformation("Removing netcap module from {DeviceId}...", _publisher.DeviceId); // Wait until netcap is not connected anymore var connected = true; for (var i = 1; connected && !ct.IsCancellationRequested; i++) { await Task.Delay(TimeSpan.FromSeconds(Math.Min(i, 10)), ct).ConfigureAwait(false); var modules = await registryManager.GetModulesOnDeviceAsync( _publisher.DeviceId, ct).ConfigureAwait(false); connected = modules.Any(m => m.Id == ncModuleId); } _logger.LogInformation("Netcap module removed from {DeviceId}.", _publisher.DeviceId); } /// /// Publisher deployment /// /// /// /// /// /// /// /// internal sealed record class PublisherDeployment(SubscriptionResource Subscription, string ResourceGroupName, IotHubDescriptionData IoTHub, string ConnectionString, Module Publisher, bool Connected, string? DeploymentConfigId) { public override string? ToString() { return $"[{Subscription.Data.DisplayName}/{ResourceGroupName}/" + $"{IoTHub.Name}] {Publisher.DeviceId}/modules/{Publisher.Id}" + $"{(Connected ? "" : " [Disconnected]")}"; } } /// /// Stop deployments /// /// /// /// /// private async IAsyncEnumerable GetPublisherDeploymentsAsync( string? subscriptionId = null, bool netcapMonitored = false, [EnumeratorCancellation] CancellationToken ct = default) { _logger.LogInformation("Finding publishers..."); await foreach (var sub in _client.GetSubscriptions().GetAllAsync(ct).ConfigureAwait(false)) { if (subscriptionId != null && sub.Data.DisplayName != subscriptionId && sub.Id.SubscriptionId != subscriptionId) { continue; } await foreach (var hub in sub.GetIotHubDescriptionsAsync(cancellationToken: ct).ConfigureAwait(false)) { Response keys; try { keys = await hub.GetKeysForKeyNameAsync("iothubowner", ct).ConfigureAwait(false); } catch (Exception ex) { _logger.LogDebug(ex, "Failed to get keys for hub {Hub}.", hub.Data.Name); continue; } var cs = IotHubConnectionStringBuilder.Create(hub.Data.Properties.HostName, new ServiceAuthenticationWithSharedAccessPolicyKey("iothubowner", keys.Value.PrimaryKey)); Debug.Assert(hub.Id.ResourceGroupName != null); var publishers = await GetPublishersAsync(sub, hub.Id.ResourceGroupName, hub.Data, cs.ToString(), netcapMonitored, ct) .ToListAsync(ct) .ConfigureAwait(false); foreach (var pub in publishers) { yield return pub; } } } static async IAsyncEnumerable GetPublishersAsync( SubscriptionResource sub, string resourceGroupName, IotHubDescriptionData hub, string connectionString, bool netcapMonitored, [EnumeratorCancellation] CancellationToken ct = default) { using var registry = RegistryManager.CreateFromConnectionString(connectionString); var query = registry.CreateQuery( "SELECT * FROM devices.modules WHERE properties.reported.__type__ = 'OpcPublisher'"); string? continuationToken = null; while (query.HasMoreResults) { ct.ThrowIfCancellationRequested(); QueryResponse results; try { results = await query.GetNextAsTwinAsync(new QueryOptions { ContinuationToken = continuationToken }).ConfigureAwait(false); } catch (UnauthorizedException) { yield break; } continuationToken = results.ContinuationToken; foreach (var result in results) { var version = result.GetProperty("__version__", desired: false); if (version?.StartsWith("2.9.", StringComparison.Ordinal) != true || !int.TryParse(version.Split('.')[2], out var patch) || patch < 10) { // Not supported continue; } var configId = result.GetTag(kDeploymentTag); if (!netcapMonitored) { if (configId != null) { // Select only publishers without netcap enabled continue; } if (result.ConnectionState != DeviceConnectionState.Connected) { // Select only connected publishers continue; } } else if (configId == null) { // Select only publisher with netcap enabled // Disconnected are ok, we want to uninstall those too continue; } var device = await registry.GetDeviceAsync(result.DeviceId, ct).ConfigureAwait(false); var connected = device.ConnectionState == DeviceConnectionState.Connected; yield return new PublisherDeployment(sub, resourceGroupName, hub, connectionString, new Module(result.DeviceId, result.ModuleId), connected, configId); } } } } /// /// Create Sidecar Deployment deployment /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// private static IDictionary>? CreateSidecarDeployment( string deviceId, string netcapModuleId, string publisherModuleId, string server, string userName, string password, string image, string storageConnectionString, string? apiKey, string? certificate, string? scheme, string? ipAddresses, string? hostName, string? port) { var args = new List { "-d", deviceId, "-m", publisherModuleId, "-s", storageConnectionString }; if (ipAddresses != null) { args.Add("-i"); args.Add(ipAddresses); } if (apiKey != null) { args.Add("-a"); args.Add(apiKey); } if (certificate != null) { args.Add("-p"); args.Add(certificate); } if (hostName != null) { scheme ??= "https"; var url = $"{scheme}://{hostName}"; if (port != null) { url += $":{port}"; } args.Add("-r"); args.Add(url); } var createOptions = JsonConvert.SerializeObject(new { User = "root", Cmd = args.ToArray(), NetworkingConfig = new { EndpointsConfig = new { host = new { } } }, HostConfig = new { NetworkMode = "host", // $"container:{hostName ?? publisherModuleId}", CapAdd = new[] { "NET_ADMIN" } } }).Replace("\"", "\\\"", StringComparison.Ordinal); // Return deployment modules object return JsonConvert.DeserializeObject>>($$""" { "$edgeAgent": { "properties.desired.runtime.settings.registryCredentials.{{netcapModuleId}}": { "address": "{{server}}", "password": "{{password}}", "username": "{{userName}}" }, "properties.desired.modules.{{netcapModuleId}}": { "settings": { "image": "{{image}}", "createOptions": "{{createOptions}}" }, "type": "docker", "status": "running", "restartPolicy": "always", "version": "1.0" } }, "$edgeHub": { "properties.desired.routes.netcapToUpstream": { "route": "FROM /messages/modules/{{netcapModuleId}}/* INTO $upstream" } } } """); } /// /// Create resource name /// /// /// private string GetResourceName(string postfix) { return Extensions.FixUpResourceName(_iotHubName + postfix); } /// /// Container image /// internal sealed record class NetcapImage { public string LoginServer { get; private set; } = null!; public string Username { get; private set; } = null!; public string Password { get; private set; } = null!; public string Name { get; private set; } = null!; /// /// Create image /// /// /// /// public NetcapImage(Gateway gateway, string? branch, ILogger logger) { _gateway = gateway; _branch = branch ?? "main"; _logger = logger; } /// /// Create or update /// /// /// public async Task CreateOrUpdateAsync(CancellationToken ct = default) { // Create container registry or update if it already exists in rg var regName = _gateway.GetResourceName(kResourceName); var rg = await _gateway.GetResourceGroupAsync(ct).ConfigureAwait(false); _logger.LogInformation( "Create netcap module image in {Registry} inside {ResourceGroup}.", regName, rg.Data.Name); var registryResponse = await rg.GetContainerRegistries() .CreateOrUpdateAsync(WaitUntil.Completed, regName, new ContainerRegistryData(rg.Data.Location, new ContainerRegistrySku(ContainerRegistrySkuName.Basic)) { IsAdminUserEnabled = true, PublicNetworkAccess = ContainerRegistryPublicNetworkAccess.Enabled }, ct).ConfigureAwait(false); var registryKeys = await registryResponse.Value.GetCredentialsAsync(ct) .ConfigureAwait(false); LoginServer = registryResponse.Value.Data.LoginServer; Username = registryKeys.Value.Username; Password = registryKeys.Value.Passwords[0].Value; Name = LoginServer + "/netcap:" + GetType().Assembly.GetVersion(); _logger.LogInformation("Building Image {Image} ...", Name); // Build the image and push to the registry var quickBuild = new ContainerRegistryDockerBuildContent("Dockerfile", new ContainerRegistryPlatformProperties("linux") { Architecture = "amd64" }) { SourceLocation = $"https://github.com/Azure/Industrial-IoT.git#{_branch}:samples/Netcap/src", IsPushEnabled = true }; quickBuild.ImageNames.Add(Name); quickBuild.Arguments.Add( new ContainerRegistryRunArgument("VERSION", GetType().Assembly.GetVersion())); quickBuild.Arguments.Add( new ContainerRegistryRunArgument("BRANCH", _branch)); var taskName = Extensions.FixUpResourceName(kTaskName + DateTime.UtcNow.ToBinary()); var buildResponse = await registryResponse.Value.GetContainerRegistryTaskRuns() .CreateOrUpdateAsync(WaitUntil.Started, taskName, new ContainerRegistryTaskRunData { RunRequest = quickBuild }, ct).ConfigureAwait(false); var runs = await registryResponse.Value.GetContainerRegistryTaskRuns() .GetAsync(taskName, ct).ConfigureAwait(false); var run = await registryResponse.Value.GetContainerRegistryRuns().GetAsync( runs.Value.Data.RunResult.RunId, ct).ConfigureAwait(false); using var cts = new CancellationTokenSource(); var copyTask = LogRunLog(run.Value, cts.Token); async Task LogRunLog(ContainerRegistryRunResource run, CancellationToken ct) { var position = 0; var url = await run.GetLogSasUrlAsync(ct).ConfigureAwait(false); while (!ct.IsCancellationRequested) { try { var client = new BlobClient(new Uri(url.Value.LogLink)); #pragma warning disable RCS1261 // Resource can be disposed asynchronously using var os = Console.OpenStandardOutput(); using var source = await client.OpenReadAsync(new BlobOpenReadOptions(true) { Position = position }, ct).ConfigureAwait(false); #pragma warning restore RCS1261 // Resource can be disposed asynchronously position += await source.CopyAsync(os, ct).ConfigureAwait(false); } catch (OperationCanceledException) { } catch (Exception ex) { _logger.LogDebug(ex, "Download from {Url} failed.", url.Value.LogLink); } } } await buildResponse.WaitForCompletionAsync(ct).ConfigureAwait(false); await cts.CancelAsync().ConfigureAwait(false); try { await copyTask.ConfigureAwait(false); } catch { } _logger.LogInformation("Image {Image} built with {Result}", Name, buildResponse.Value.Data.RunResult.Status.ToString()); } /// /// Create or update /// /// /// public async Task DeleteAsync(CancellationToken ct) { var regName = _gateway.GetResourceName(kResourceName); var rg = await _gateway.GetResourceGroupAsync(ct).ConfigureAwait(false); var registryCollection = rg.GetContainerRegistries(); if (!await registryCollection.ExistsAsync(regName, ct).ConfigureAwait(false)) { return; } var registryResponse = await rg.GetContainerRegistryAsync(regName, ct).ConfigureAwait(false); await registryResponse.Value.DeleteAsync(WaitUntil.Completed, ct).ConfigureAwait(false); LoginServer = null!; Username = null!; Password = null!; Name = null!; } private const string kResourceName = "acr"; private const string kTaskName = "nc"; private readonly Gateway _gateway; private readonly string _branch; private readonly ILogger _logger; } /// /// NetcapException storage controller /// internal sealed record class NetcapStorage { public string ConnectionString { get; private set; } = null!; /// /// Create storage /// /// /// public NetcapStorage(Gateway gateway, ILogger logger) { _gateway = gateway; _logger = logger; } /// /// Create or update /// /// /// /// /// public async ValueTask CreateOrUpdateAsync(CancellationToken ct) { var stgName = _gateway.GetResourceName(kResourceName); var rg = await _gateway.GetResourceGroupAsync(ct).ConfigureAwait(false); _logger.LogInformation("Create Storage {Storage} for netcap module in {Rg}.", stgName, rg.Data.Name); var storageResponse = await rg.GetStorageAccounts() .CreateOrUpdateAsync(WaitUntil.Completed, stgName, new StorageAccountCreateOrUpdateContent( new StorageSku(StorageSkuName.StandardGrs), StorageKind.StorageV2, rg.Data.Location) { AllowSharedKeyAccess = true, EnableHttpsTrafficOnly = true, PublicNetworkAccess = StoragePublicNetworkAccess.Enabled }, ct).ConfigureAwait(false); var storageName = storageResponse.Value.Data.Name; var endpoints = storageResponse.Value.Data.PrimaryEndpoints; var keys = await storageResponse.Value.GetKeysAsync( cancellationToken: ct).ToListAsync(ct).ConfigureAwait(false); if (keys.Count == 0) { throw new NetcapException( $"No keys found for storage account {storageName}"); } // Create connection string for storage account ConnectionString = "DefaultEndpointsProtocol=https;" + $"BlobEndpoint={endpoints.BlobUri};" + $"QueueEndpoint={endpoints.QueueUri};" + $"FileEndpoint={endpoints.FileUri};" + $"TableEndpoint={endpoints.TableUri};" + $"AccountName={storageName};AccountKey={keys[0].Value}"; _logger.LogInformation("Storage {Name} for netcap module created.", storageName); } /// /// Stop /// /// /// public async ValueTask DeleteAsync(CancellationToken ct) { var stgName = _gateway.GetResourceName(kResourceName); var rg = await _gateway.GetResourceGroupAsync(ct).ConfigureAwait(false); var storageCollection = rg.GetStorageAccounts(); if (!await storageCollection.ExistsAsync(stgName, cancellationToken: ct).ConfigureAwait(false)) { return; } var storageResponse = await rg.GetStorageAccountAsync(stgName, cancellationToken: ct).ConfigureAwait(false); await storageResponse.Value.DeleteAsync(WaitUntil.Completed, ct).ConfigureAwait(false); ConnectionString = null!; } private const string kResourceName = "stg"; private readonly Gateway _gateway; private readonly ILogger _logger; } private const string kDeploymentTag = "netcapdeployment"; private const string kPostFix = "-nc"; private Module? _publisher; private SubscriptionResource? _subscription; private string? _iotHubName; private string? _deploymentConfigId; private string? _resourceGroupName; private string? _connectionString; private readonly ILogger _logger; private readonly ArmClient _client; } ================================================ FILE: samples/Netcap/src/Netcap.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Netcap; using Azure.Core; using Azure.Identity; using Azure.ResourceManager; using CommandLine; using Microsoft.AspNetCore.Authentication; using Microsoft.Azure.Devices.Client; using Microsoft.Azure.Devices.Common.Exceptions; using Microsoft.Azure.Devices.Shared; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System.Diagnostics; using System.Net; using System.Net.Http.Headers; using System.Security.Claims; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Text.Encodings.Web; using System.Text.Json; /// /// Netcap exception /// public class NetcapException : Exception { public NetcapException(string message) : base(message) { } public NetcapException(string message, Exception innerException) : base(message, innerException) { } } /// /// Netcap application /// internal sealed class App : IDisposable { [Verb("run", isDefault: true, HelpText = "Run netcap to capture diagnostics.")] public sealed class RunOptions { [Option('s', nameof(StorageConnectionString), Required = false, HelpText = "The storage connection string to use to upload files.")] public string? StorageConnectionString { get; set; } = Environment.GetEnvironmentVariable(nameof(StorageConnectionString)); [Option('m', nameof(PublisherModuleId), Required = false, HelpText = "The module id of the opc publisher.")] public string PublisherModuleId { get; set; } = Environment.GetEnvironmentVariable(nameof(PublisherModuleId)) ?? "publisher"; [Option('d', nameof(PublisherDeviceId), Required = false, HelpText = "The device id of the opc publisher.")] public string? PublisherDeviceId { get; set; } = Environment.GetEnvironmentVariable(nameof(PublisherDeviceId)); [Option('a', nameof(PublisherRestApiKey), Required = false, HelpText = "The api key of the opc publisher.")] public string? PublisherRestApiKey { get; set; } = Environment.GetEnvironmentVariable(nameof(PublisherRestApiKey)); [Option('p', nameof(PublisherRestCertificate), Required = false, HelpText = "The tls certificate of the opc publisher.")] public string? PublisherRestCertificate { get; set; } [Option('r', nameof(PublisherRestApiEndpoint), Required = false, HelpText = "The Rest api endpoint of the opc publisher.")] public string? PublisherRestApiEndpoint { get; set; } = Environment.GetEnvironmentVariable(nameof(PublisherRestApiEndpoint)); [Option('i', nameof(PublisherIpAddresses), Required = false, HelpText = "The endpoint of the opc publisher.")] public string? PublisherIpAddresses { get; set; } [Option('t', nameof(CaptureDuration), Required = false, HelpText = "The capture duration.")] public TimeSpan? CaptureDuration { get; set; } = TimeSpan.TryParse( Environment.GetEnvironmentVariable(nameof(CaptureDuration)), out var t) ? t : null; [Option('f', nameof(CaptureFileSize), Required = false, HelpText = "The max file size of pcap in bytes.")] public int? CaptureFileSize { get; set; } = int.TryParse( Environment.GetEnvironmentVariable(nameof(CaptureFileSize)), out var f) ? f : null; [Option('I', nameof(CaptureInterfaces), Required = false, HelpText = "The network interfaces to capture from.")] public Pcap.InterfaceType CaptureInterfaces { get; set; } = Pcap.InterfaceType.AnyIfAvailable; [Option('E', nameof(HostCaptureEndpointUrl), Required = false, HelpText = "The remote capture endpoint to use.")] public string? HostCaptureEndpointUrl { get; internal set; } [Option('C', nameof(HostCaptureCertificate), Required = false, HelpText = "The remote capture endpoint certificate.")] public string? HostCaptureCertificate { get; internal set; } [Option('A', nameof(HostCaptureApiKey), Required = false, HelpText = "The remote capture endpoint api key.")] public string? HostCaptureApiKey { get; internal set; } public RunOptions() { PublisherRestCertificate = Environment.GetEnvironmentVariable(nameof(PublisherRestCertificate)); } /// /// Stop configuration from twin /// /// /// public void ConfigureFromTwin(Twin twin) { // Set any missing info from the netcap twin PublisherIpAddresses = twin.GetProperty( nameof(PublisherIpAddresses), PublisherIpAddresses); PublisherRestApiEndpoint = twin.GetProperty( nameof(PublisherRestApiEndpoint), PublisherRestApiEndpoint); PublisherRestApiKey = twin.GetProperty( nameof(PublisherRestApiKey), PublisherRestApiKey); PublisherRestCertificate = twin.GetProperty( nameof(PublisherRestCertificate), PublisherRestCertificate); HostCaptureEndpointUrl = twin.GetProperty( nameof(HostCaptureEndpointUrl), HostCaptureEndpointUrl); HostCaptureCertificate = twin.GetProperty( nameof(HostCaptureCertificate), HostCaptureCertificate); HostCaptureApiKey = twin.GetProperty( nameof(HostCaptureApiKey), HostCaptureApiKey); StorageConnectionString = twin.GetProperty( nameof(StorageConnectionString), StorageConnectionString); var captureDuration = twin.GetProperty(nameof(CaptureDuration)); if (!string.IsNullOrWhiteSpace(captureDuration) && TimeSpan.TryParse(captureDuration, out var duration)) { CaptureDuration = duration; } var captureFileSize = twin.GetProperty(nameof(CaptureFileSize)); if (!string.IsNullOrWhiteSpace(captureFileSize) && int.TryParse(captureFileSize, out var filesize)) { CaptureFileSize = filesize; } } } [Verb("sidecar", HelpText = "Run netcap as capture host.")] public sealed class SidecarOptions; [Verb("install", HelpText = "Install netcap into a publisher.")] public sealed class InstallOptions { [Option('t', nameof(TenantId), Required = false, HelpText = "The tenant to use to filter subscriptions down." + "\nDefault uses all tenants accessible.")] public string? TenantId { get; set; } = Environment.GetEnvironmentVariable("AZURE_TENANT_ID"); [Option('d', nameof(UseDeviceCode), Required = false, HelpText = "Use device code authentication.")] public bool UseDeviceCode { get; set; } [Option('s', nameof(SubscriptionId), Required = false, HelpText = "The subscription to use to install to." + "\nDefault uses all subscriptions accessible.")] public string? SubscriptionId { get; set; } [Option('o', nameof(OutputPath), Required = false, HelpText = "The output path to capture to.")] public string? OutputPath { get; set; } [Option('b', nameof(Branch), Required = false, HelpText = "The branch to build netcap from." + "\nDefaults to main branch.")] public string? Branch { get; set; } = "main"; } [Verb("uninstall", HelpText = "Uninstall netcap from one or all publishers.")] public sealed class UninstallOptions { [Option('t', nameof(TenantId), Required = false, HelpText = "The tenant to use to filter subscriptions down." + "\nDefault uses all tenants accessible.")] public string? TenantId { get; set; } = Environment.GetEnvironmentVariable("AZURE_TENANT_ID"); [Option('d', nameof(UseDeviceCode), Required = false, HelpText = "Use device code authentication.")] public bool UseDeviceCode { get; set; } [Option('s', nameof(SubscriptionId), Required = false, HelpText = "The subscription to use to install to." + "\nDefault uses all subscriptions accessible.")] public string? SubscriptionId { get; set; } } /// /// Create netcap application /// public App() { _publisherHttpClient = new HttpClient(); _loggerFactory = new LoggerFactory(); _logger = UpdateLogger(); } /// public void Dispose() { _loggerFactory.Dispose(); _publisherHttpClient.Dispose(); _publisherCertificate?.Dispose(); _sidecarHttpClient?.Dispose(); _sidecarCertificate?.Dispose(); } /// /// Parse parameters /// /// /// /// public static async ValueTask RunAsync(string[] args, CancellationToken ct = default) { var cmd = new App(); await cmd.ParseAsync(args, ct).ConfigureAwait(false); return cmd; } /// /// Parse parameters /// /// /// /// private async ValueTask ParseAsync(string[] args, CancellationToken ct = default) { Parser.Default.ParseArguments(args) .WithParsed(parsedParams => _run = parsedParams) .WithParsed(parsedParams => _install = parsedParams) .WithParsed(parsedParams => _sidecar = parsedParams) .WithParsed(parsedParams => _uninstall = parsedParams) .WithNotParsed(errors => { errors.ToList().ForEach(Console.WriteLine); Environment.Exit(1); }); _logger = UpdateLogger(); var iothubConnectionString = Environment.GetEnvironmentVariable("IoTHubOwnerConnectionString") ?? Environment.GetEnvironmentVariable("_HUB_CS"); if (_install != null) { await InstallAsync(ct).ConfigureAwait(false); } else if (_uninstall != null) { await UninstallAsync(ct).ConfigureAwait(false); } else if (_sidecar != null) { await RunAsSidecarModuleAsync(ct).ConfigureAwait(false); } else if (!string.IsNullOrEmpty(iothubConnectionString)) { await RunAsIoTHubConnectedModuleAsync( iothubConnectionString, ct).ConfigureAwait(false); } else { await RunAsModuleAsync(ct).ConfigureAwait(false); } } /// /// Run netcap /// /// /// /// private async Task RunAsync(CancellationToken ct = default) { _run ??= new RunOptions(); if (string.IsNullOrEmpty(_run.StorageConnectionString)) { throw new NetcapException("Storage must be provided"); } using var cts = CancellationTokenSource.CreateLinkedTokenSource(ct); if (!Extensions.IsRunningInContainer()) { while (Console.KeyAvailable) { Console.ReadKey(); } _ = Task.Run(() => { Console.ReadKey(); cts.Cancel(); }, ct); Console.WriteLine("Press any key to exit"); Console.WriteLine(); } try { // Connect to publisher using var publisher = new Publisher(_publisherHttpClient, _run.PublisherIpAddresses, _loggerFactory.CreateLogger("Publisher")); var storage = new Storage(_run.PublisherDeviceId ?? "unknown", _run.PublisherModuleId, _run.StorageConnectionString, _loggerFactory.CreateLogger("Upload")); for (var i = 0; !cts.IsCancellationRequested; i++) { // Update endpoint urls and addresses to monitor if not set if (await publisher.TryUploadEndpointsAsync(storage, cts.Token).ConfigureAwait(false)) { break; } _logger.LogInformation("waiting ....."); await Task.Delay(TimeSpan.FromMinutes(1), cts.Token).ConfigureAwait(false); continue; } cts.Token.ThrowIfCancellationRequested(); // Start capture and upload capture files and channel information var configuration = publisher.GetCaptureConfiguration(_run.CaptureInterfaces, _run.CaptureFileSize, _run.CaptureDuration); using (Pcap.Capture(configuration, storage, _loggerFactory.CreateLogger("Capture"), _sidecarHttpClient)) { await publisher.UploadChannelLogsAsync(storage, cts.Token).ConfigureAwait(false); } } catch (OperationCanceledException) { } catch (Exception ex) { _logger.LogError(ex, "Failed to run."); } } /// /// Install /// /// /// private async Task InstallAsync(CancellationToken ct = default) { _install ??= new InstallOptions(); // Login to azure var armClient = new ArmClient( GetAzureCredentials(_install.TenantId, _install.UseDeviceCode)); _logger.LogInformation("Installing netcap module..."); var gateway = new Gateway(armClient, _logger, _install.Branch); try { // Stop publishers var found = await gateway.SelectPublisherAsync(_install.SubscriptionId, false, ct).ConfigureAwait(false); if (!found) { return; } // Create storage account or update if it already exists in the rg await gateway.Storage.CreateOrUpdateAsync(ct).ConfigureAwait(false); // Create container registry or update and build netcap module await gateway.Netcap.CreateOrUpdateAsync(ct).ConfigureAwait(false); // Deploy the module using manifest to device with the chosen publisher await gateway.DeployNetcapModuleAsync(ct).ConfigureAwait(false); if (!string.IsNullOrWhiteSpace(_install.OutputPath)) { using var cts = CancellationTokenSource.CreateLinkedTokenSource(ct); while (Console.KeyAvailable) { Console.ReadKey(); } _ = Task.Run(() => { Console.ReadKey(); cts.Cancel(); }, ct); Console.WriteLine("Press any key to exit"); Console.WriteLine(); try { // Stop the logs from the module, when cancelled undeploy var downloader = gateway.GetStorage(); await downloader.DownloadAsync(_install.OutputPath, cts.Token).ConfigureAwait(false); } catch (OperationCanceledException) { } finally { await gateway.RemoveNetcapModuleAsync(ct).ConfigureAwait(false); } // Merge capture files for convinience foreach (var d in Directory.GetDirectories(_install.OutputPath)) { var merged = Path.Combine(d, "capture.pcap"); if (!File.Exists(merged)) { _logger.LogInformation( "Merging capture files in {Directory} into {File}", d, merged); Pcap.Merge(d, merged); } } } } catch (Exception ex) { _logger.LogError("Failed to install netcap module with error: {Error}", ex.Message); throw; } } /// /// Uninstall /// /// /// private async Task UninstallAsync(CancellationToken ct = default) { _uninstall ??= new UninstallOptions(); // Login to azure var armClient = new ArmClient(GetAzureCredentials(_uninstall.TenantId, _uninstall.UseDeviceCode)); _logger.LogInformation("Uninstalling netcap module..."); var gateway = new Gateway(armClient, _logger); try { // Select netcap modules var found = await gateway.SelectPublisherAsync(_uninstall.SubscriptionId, true, ct).ConfigureAwait(false); if (!found) { return; } // Add guard here // Stop storage account or update if it already exists in the rg // await gateway.Storage.DeleteAsync(ct).ConfigureAwait(false); // Stop container registry // await gateway.NetcapException.DeleteAsync(ct).ConfigureAwait(false); // Deploy the module using manifest to device with the chosen publisher await gateway.RemoveNetcapModuleAsync(ct).ConfigureAwait(false); } catch (Exception ex) { _logger.LogError("Failed to uninstall netcap module with error: {Error}", ex.Message); throw; } } /// /// Connect module to edge hub /// /// /// private async ValueTask RunAsModuleAsync(CancellationToken ct = default) { if (string.IsNullOrWhiteSpace(_run?.PublisherRestApiKey) && string.IsNullOrWhiteSpace(_run?.PublisherRestCertificate) && string.IsNullOrWhiteSpace(_run?.PublisherRestApiEndpoint)) { await InstallAsync(ct).ConfigureAwait(false); } _run ??= new RunOptions(); var moduleClient = await CreateModuleClientAsync().ConfigureAwait(false); try { // Call the "GetApiKey" and "GetServerCertificate" methods on the publisher module await moduleClient.OpenAsync(ct).ConfigureAwait(false); await moduleClient.UpdateReportedPropertiesAsync(new TwinCollection { ["__type__"] = "OpcNetcap", ["__version__"] = GetType().Assembly.GetVersion() }, ct).ConfigureAwait(false); var twin = await moduleClient.GetTwinAsync(ct).ConfigureAwait(false); var deviceId = twin.DeviceId ?? Environment.GetEnvironmentVariable("IOTEDGE_DEVICEID"); // var moduleId = twin.ModuleId ?? Environment.GetEnvironmentVariable("IOTEDGE_MODULEID"); _run.PublisherModuleId = twin.GetProperty(nameof(_run.PublisherModuleId), _run.PublisherModuleId); _run.PublisherDeviceId = deviceId; // Override as we must be in the same device Debug.Assert(_run.PublisherModuleId != null); Debug.Assert(_run.PublisherDeviceId != null); _run.ConfigureFromTwin(twin); _logger.LogInformation( "Connecting to OPC Publisher Module {PublisherModuleId} on {PublisherDeviceId}...", _run.PublisherModuleId, _run.PublisherDeviceId); if (_run.PublisherRestApiKey == null || _run.PublisherRestCertificate == null) { if (_run.PublisherRestApiKey == null) { var apiKeyResponse = await moduleClient.InvokeMethodAsync( _run.PublisherDeviceId, _run.PublisherModuleId, new MethodRequest("GetApiKey"), ct).ConfigureAwait(false); _run.PublisherRestApiKey = JsonSerializer.Deserialize(apiKeyResponse.Result); } if (_run.PublisherRestCertificate == null) { var certResponse = await moduleClient.InvokeMethodAsync( _run.PublisherDeviceId, _run.PublisherModuleId, new MethodRequest("GetServerCertificate"), ct).ConfigureAwait(false); _run.PublisherRestCertificate = JsonSerializer.Deserialize(certResponse.Result); } } await CreatePublisherHttpClientAsync().ConfigureAwait(false); CreateSidecarHttpClientIfRequired(); await RunAsync(ct).ConfigureAwait(false); } finally { await moduleClient.CloseAsync(ct).ConfigureAwait(false); await moduleClient.DisposeAsync().ConfigureAwait(false); } } /// /// Run the side car providing the host side capture capabilities /// /// /// private async Task RunAsSidecarModuleAsync(CancellationToken ct = default) { _sidecar ??= new SidecarOptions(); var moduleClient = await CreateModuleClientAsync().ConfigureAwait(false); try { await moduleClient.OpenAsync(ct).ConfigureAwait(false); await moduleClient.UpdateReportedPropertiesAsync(new TwinCollection { ["__type__"] = "OpcNetcapSidecar", ["__version__"] = GetType().Assembly.GetVersion() }, ct).ConfigureAwait(false); var twin = await moduleClient.GetTwinAsync(ct).ConfigureAwait(false); var cert = twin.GetProperty("__certificate__", desired: false); var apiKey = twin.GetProperty("__apikey__", desired: false); if (cert != null && apiKey != null) { _sidecarCertificate = X509CertificateLoader.LoadPkcs12( Convert.FromBase64String(cert.Trim()), apiKey); } else { _sidecarCertificate = CreateCertificate(twin); apiKey = Guid.NewGuid().ToString(); cert = Convert.ToBase64String(_sidecarCertificate.Export( X509ContentType.Pfx, apiKey)); await moduleClient.UpdateReportedPropertiesAsync(new TwinCollection { ["__certificate__"] = cert, ["__apikey__"] = apiKey }, ct).ConfigureAwait(false); } var builder = WebApplication.CreateBuilder(); builder.WebHost.ConfigureKestrel((_, serverOptions) => serverOptions.ListenAnyIP(443, options => options.UseHttps(_sidecarCertificate))); builder.Services.AddHttpContextAccessor(); builder.Services.TryAddSingleton(_sidecar); builder.Services.AddLogging(builder => builder .AddSimpleConsole(options => options.SingleLine = true)); builder.Services.AddAuthentication(nameof(ApiKeyProvider.ApiKey)) .AddScheme( nameof(ApiKeyProvider.ApiKey), null); builder.Services.AddAuthentication(); var app = builder.Build(); app.UseCors(); app.UseAuthentication(); app.UseAuthorization(); app.UseHttpsRedirection(); using var server = new Pcap.Server(app, _logger); await app.RunAsync(ct).ConfigureAwait(false); } finally { if (moduleClient != null) { await moduleClient.CloseAsync(ct).ConfigureAwait(false); await moduleClient.DisposeAsync().ConfigureAwait(false); } } static X509Certificate2 CreateCertificate(Twin twin) { var dnsName = Dns.GetHostName(); using var ecdsa = ECDsa.Create(); var req = new CertificateRequest("DC=" + dnsName, ecdsa, HashAlgorithmName.SHA256); var san = new SubjectAlternativeNameBuilder(); san.AddDnsName(dnsName); var altDns = twin?.ModuleId ?? twin?.DeviceId; if (!string.IsNullOrEmpty(altDns) && !string.Equals(altDns, dnsName, StringComparison.OrdinalIgnoreCase)) { san.AddDnsName(altDns); } req.CertificateExtensions.Add(san.Build()); var certificate = req.CreateSelfSigned(DateTimeOffset.Now, DateTimeOffset.Now + TimeSpan.FromDays(90)); Debug.Assert(certificate.HasPrivateKey); return certificate; } } /// /// Connect with iot hub connection string /// /// /// /// private async ValueTask RunAsIoTHubConnectedModuleAsync( string iothubConnectionString, CancellationToken ct = default) { // NOTE: This is for local testing against IoT Hub string deviceId; const string ncModuleId = "netcap"; _run ??= new RunOptions(); var edgeHubConnectionString = Environment.GetEnvironmentVariable("EdgeHubConnectionString"); if (!string.IsNullOrWhiteSpace(edgeHubConnectionString)) { // Update device and module id from edge hub connection string provided var ehc = IotHubConnectionStringBuilder.Create(edgeHubConnectionString); deviceId = ehc.DeviceId; _run.PublisherModuleId = ehc.ModuleId ?? ncModuleId; } else { // Default device to host name just like we do it in our publisher CLI #pragma warning disable CA1308 // Normalize strings to uppercase deviceId = Dns.GetHostName().ToLowerInvariant(); #pragma warning restore CA1308 // Normalize strings to uppercase } using var rm = Microsoft.Azure.Devices.RegistryManager .CreateFromConnectionString(iothubConnectionString); // Create module if not exist try { await rm.AddDeviceAsync(new Microsoft.Azure.Devices.Device(deviceId), ct) .ConfigureAwait(false); } catch (DeviceAlreadyExistsException) { } try { await rm.AddModuleAsync(new Microsoft.Azure.Devices.Module( deviceId, ncModuleId), ct).ConfigureAwait(false); } catch (ModuleAlreadyExistsException) { } var twin = await rm.GetTwinAsync(deviceId, ncModuleId, ct).ConfigureAwait(false); twin = await rm.UpdateTwinAsync(deviceId, ncModuleId, new Twin { Properties = new TwinProperties { Reported = new TwinCollection { ["__type__"] = "OpcNetcap", ["__version__"] = GetType().Assembly.GetVersion() } } }, twin.ETag, ct).ConfigureAwait(false); // Update publisher id from twin if not configured _run.PublisherModuleId = twin.GetProperty(nameof(_run.PublisherModuleId), _run.PublisherModuleId); _run.PublisherDeviceId ??= deviceId; Debug.Assert(_run.PublisherModuleId != null); Debug.Assert(_run.PublisherDeviceId != null); _run.ConfigureFromTwin(twin); _logger.LogInformation("Connecting to OPC Publisher Module {PublisherModuleId} " + "on {PublisherDeviceId} via IoTHub...", _run.PublisherModuleId, _run.PublisherDeviceId); var publisherTwin = await rm.GetTwinAsync(_run.PublisherDeviceId, _run.PublisherModuleId, ct).ConfigureAwait(false); _run.PublisherRestApiKey ??= publisherTwin.GetProperty("__apikey__", desired: false); _run.PublisherRestCertificate ??= publisherTwin.GetProperty("__certificate__", desired: false); _run.PublisherIpAddresses ??= publisherTwin.GetProperty("__ip__", desired: false); var scheme = publisherTwin.GetProperty("__scheme__", desired: false); var hostName = publisherTwin.GetProperty("__hostname__", desired: false); var port = publisherTwin.GetProperty("__port__", desired: false); if (hostName != null) { scheme ??= "https"; var url = $"{scheme}://{hostName}"; if (port != null) { url += $":{port}"; } _run.PublisherRestApiEndpoint ??= url; } if (_run.PublisherRestApiKey == null || _run.PublisherRestCertificate == null) { using var serviceClient = Microsoft.Azure.Devices.ServiceClient .CreateFromConnectionString(iothubConnectionString); if (_run.PublisherRestApiKey == null) { var apiKeyResponse = await serviceClient.InvokeDeviceMethodAsync( _run.PublisherDeviceId, _run.PublisherModuleId, new Microsoft.Azure.Devices.CloudToDeviceMethod( "GetApiKey"), ct).ConfigureAwait(false); _run.PublisherRestApiKey = JsonSerializer.Deserialize(apiKeyResponse.GetPayloadAsJson()); } if (_run.PublisherRestCertificate == null) { var certResponse = await serviceClient.InvokeDeviceMethodAsync( _run.PublisherDeviceId, _run.PublisherModuleId, new Microsoft.Azure.Devices.CloudToDeviceMethod( "GetServerCertificate"), ct).ConfigureAwait(false); _run.PublisherRestCertificate = JsonSerializer.Deserialize(certResponse.GetPayloadAsJson()); } } await CreatePublisherHttpClientAsync().ConfigureAwait(false); CreateSidecarHttpClientIfRequired(); await RunAsync(ct).ConfigureAwait(false); } /// /// Create sidecar client /// /// private void CreateSidecarHttpClientIfRequired() { if (_run?.HostCaptureEndpointUrl == null || _run?.HostCaptureApiKey == null || _run?.HostCaptureCertificate == null) { return; } var cert = Convert.FromBase64String(_run.HostCaptureCertificate.Trim()); _sidecarCertificate = X509CertificateLoader.LoadPkcs12(cert, _run.HostCaptureApiKey); _sidecarHttpClient?.Dispose(); #pragma warning disable CA2000 // Dispose objects before losing scope _sidecarHttpClient = new HttpClient(new HttpClientHandler { ServerCertificateCustomValidationCallback = (_, cert, _, _) => { if (_sidecarCertificate?.Thumbprint != cert?.Thumbprint) { _logger.LogWarning( "Certificate thumbprint mismatch: {Expected} != {Actual}", _sidecarCertificate?.Thumbprint, cert?.Thumbprint); return false; } return true; } }) { BaseAddress = new Uri(_run.HostCaptureEndpointUrl) }; #pragma warning restore CA2000 // Dispose objects before losing scope _sidecarHttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("ApiKey", _run?.HostCaptureApiKey); } /// /// Create publisher client /// /// private async ValueTask CreatePublisherHttpClientAsync() { if (_run?.PublisherRestApiKey != null) { // Load the certificate of the publisher if not exist if (!string.IsNullOrWhiteSpace(_run?.PublisherRestCertificate) && _publisherCertificate == null) { try { _publisherCertificate = X509Certificate2.CreateFromPem( _run.PublisherRestCertificate.Trim()); } catch { var cert = Convert.FromBase64String( _run.PublisherRestCertificate.Trim()); _publisherCertificate = X509CertificateLoader.LoadPkcs12( cert!, _run.PublisherRestApiKey); } } _publisherHttpClient.Dispose(); #pragma warning disable CA2000 // Dispose objects before losing scope _publisherHttpClient = new HttpClient(new HttpClientHandler { ServerCertificateCustomValidationCallback = (_, cert, _, _) => { if (_publisherCertificate?.Thumbprint != cert?.Thumbprint) { _logger.LogWarning( "Certificate thumbprint mismatch: {Expected} != {Actual}", _publisherCertificate?.Thumbprint, cert?.Thumbprint); return false; } return true; } }) { #pragma warning restore CA2000 // Dispose objects before losing scope BaseAddress = await GetOpcPublisherRestEndpoint().ConfigureAwait(false) }; _publisherHttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("ApiKey", _run?.PublisherRestApiKey); } /// /// Publisher Endpoint /// async ValueTask GetOpcPublisherRestEndpoint() { if (_run?.PublisherRestApiEndpoint != null && Uri.TryCreate(_run.PublisherRestApiEndpoint, UriKind.Absolute, out var u)) { return u; } var host = _run?.PublisherModuleId; if (host != null) { // Poor man ping try { var result = await Dns.GetHostEntryAsync(host).ConfigureAwait(false); if (result.AddressList.Length == 0) { host = null; } } catch { host = null; } } host ??= "localhost"; var isLocal = host == null; var uri = new UriBuilder { Scheme = "https", Port = !isLocal ? 8081 : 443, Host = host }; if (_run?.PublisherRestApiKey == null) { uri.Scheme = "http"; uri.Port = !isLocal ? 8080 : 80; } return uri.Uri; } } /// /// Update logger /// private ILogger UpdateLogger() { _loggerFactory.Dispose(); _loggerFactory = LoggerFactory.Create(builder => builder .AddSimpleConsole(options => options.SingleLine = true)); return _loggerFactory.CreateLogger("Netcap"); } /// /// Create module client /// /// private static async ValueTask CreateModuleClientAsync() { var edgeHubConnectionString = Environment.GetEnvironmentVariable("EdgeHubConnectionString"); if (!string.IsNullOrWhiteSpace(edgeHubConnectionString)) { #pragma warning disable CA2000 // Dispose objects before losing scope return ModuleClient.CreateFromConnectionString(edgeHubConnectionString); #pragma warning restore CA2000 // Dispose objects before losing scope } return await ModuleClient.CreateFromEnvironmentAsync().ConfigureAwait(false); } /// /// Injected apikey /// /// public sealed record class ApiKeyProvider(string ApiKey); /// /// Api key authentication handler /// /// /// Create authentication handler /// /// /// /// /// /// internal sealed class ApiKeyHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, IHttpContextAccessor context, App.ApiKeyProvider apiKeyProvider) : AuthenticationHandler(options, logger, encoder) { public const string SchemeName = "ApiKey"; /// protected override Task HandleAuthenticateAsync() { var httpContext = _context.HttpContext; if (httpContext == null) { return Task.FromResult(AuthenticateResult.Fail( "No request.")); } var authorization = httpContext.Request.Headers.Authorization; if (authorization.Count == 0 || string.IsNullOrEmpty(authorization[0])) { return Task.FromResult(AuthenticateResult.Fail( "Missing Authorization header.")); } try { var header = AuthenticationHeaderValue.Parse(authorization[0]!); if (header.Scheme != nameof(ApiKeyProvider.ApiKey)) { return Task.FromResult(AuthenticateResult.NoResult()); } if (_apiKeyProvider.ApiKey != header.Parameter?.Trim()) { throw new UnauthorizedAccessException(); } var claims = new[] { new Claim(ClaimTypes.NameIdentifier, nameof(ApiKeyProvider.ApiKey)) }; var identity = new ClaimsIdentity(claims, Scheme.Name); var principal = new ClaimsPrincipal(identity); var ticket = new AuthenticationTicket(principal, Scheme.Name); return Task.FromResult(AuthenticateResult.Success(ticket)); } catch (Exception ex) { return Task.FromResult(AuthenticateResult.Fail(ex)); } } private readonly IHttpContextAccessor _context = context; private readonly ApiKeyProvider _apiKeyProvider = apiKeyProvider; } private static TokenCredential GetAzureCredentials(string? tenantId, bool useDeviceCode = false) { if (useDeviceCode) { return new DeviceCodeCredential(new DeviceCodeCredentialOptions { TenantId = tenantId }); } return new DefaultAzureCredential( new DefaultAzureCredentialOptions { TenantId = tenantId }); } private HttpClient _publisherHttpClient; private X509Certificate2? _publisherCertificate; private HttpClient? _sidecarHttpClient; private X509Certificate2? _sidecarCertificate; private ILoggerFactory _loggerFactory = null!; private ILogger _logger; private InstallOptions? _install; private UninstallOptions? _uninstall; private RunOptions? _run; private SidecarOptions? _sidecar; } ================================================ FILE: samples/Netcap/src/Netcap.csproj ================================================  Exe net9.0 enable enable true true Linux . ================================================ FILE: samples/Netcap/src/Pcap.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Netcap; using SharpPcap; using SharpPcap.LibPcap; using Microsoft.Extensions.Logging; using PacketDotNet; using System.Collections.Generic; using System.Linq; using System.Diagnostics; using System; using System.Threading.Channels; using System.Collections.Concurrent; internal abstract class Pcap { /// /// Pcap configuration /// /// /// /// /// public sealed record class CaptureConfiguration( InterfaceType InterfaceType, string? Filter = null, int? MaxFileSize = null, TimeSpan? MaxDuration = null); public enum InterfaceType { AnyIfAvailable, AllButAny, EthernetOnly } /// /// Local /// /// /// /// /// /// public static IDisposable Capture(CaptureConfiguration configuration, Storage storage, ILogger logger, HttpClient? httpClient = null) { if (httpClient == null) { return new Local(logger, configuration, storage); } return new Remote(logger, configuration, storage, httpClient); } /// /// Merge files /// /// /// public static void Merge(string folder, string outputFile) { if (File.Exists(outputFile)) { File.Delete(outputFile); } var files = Directory.GetFiles(folder, "*.pcap"); if (files.Length == 0) { return; } using var writer = new CaptureFileWriterDevice(outputFile); foreach (var file in files.Order()) { using var reader = new CaptureFileReaderDevice(file); reader.Open(); if (!writer.Opened) { writer.Open(new DeviceConfiguration { LinkLayerType = reader.LinkType }); } while (reader.GetNextPacket(out var packet) == GetPacketStatus.PacketRead) { writer.Write(packet.GetPacket()); } } } /// /// Get file path /// /// /// /// private static string GetFilePath(string folder, int index) { return Path.Combine(folder, $"capture{index}.pcap"); } /// /// Pcap capture /// internal abstract class Base : IDisposable { /// /// Handle /// public int Handle { get; } /// /// Reader /// protected ChannelReader Reader => _channel.Reader; /// /// Create pcap /// /// /// protected Base(ILogger logger, CaptureConfiguration configuration) { _logger = logger; _configuration = configuration; _folder = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); Directory.CreateDirectory(_folder); _maxPcapSize = configuration.MaxFileSize ?? kMaxPcapSize; _maxPcapDuration = configuration.MaxDuration.HasValue ? (long)configuration.MaxDuration.Value.TotalMilliseconds : kMaxPcapDuration; _channel = Channel.CreateUnbounded(); Handle = Interlocked.Increment(ref _handles); _logger.LogInformation( "Using SharpPcap {Version}", SharpPcap.Pcap.SharpPcapVersion); if (LibPcapLiveDeviceList.Instance.Count == 0) { throw new NetcapException("Cannot run capture without devices."); } _devices = [.. LibPcapLiveDeviceList.New()]; // Open devices var open = _devices .Where(d => { try { _logger.LogInformation("Opening {Device} in promiscuous mode...", d); d.Open(mode: DeviceModes.Promiscuous, 1000); } catch { try { _logger.LogInformation("Fall back to normal mode..."); d.Open(mode: DeviceModes.None, 1000); } catch (Exception ex2) { _logger.LogInformation( "Failed to open {Device} ({Description}): {Message}", d.Name, d.Description, ex2.Message); } } return d.Opened; }) .ToList(); var capturing = Array.Empty(); var linkType = PacketDotNet.LinkLayers.Null; var itf = _configuration.InterfaceType; if (itf == InterfaceType.AnyIfAvailable) { // Try to capture from cooked mode (https://wiki.wireshark.org/SLL) linkType = PacketDotNet.LinkLayers.LinuxSll; capturing = Capture(open.Where(d => d.LinkType == linkType)); if (capturing.Length == 0) { itf = InterfaceType.AllButAny; } } if (itf == InterfaceType.EthernetOnly) { linkType = PacketDotNet.LinkLayers.Ethernet; capturing = Capture(open.Where(d => d.LinkType != linkType)); if (capturing.Length == 0) { itf = InterfaceType.AllButAny; } } if (itf == InterfaceType.AllButAny) { linkType = PacketDotNet.LinkLayers.Null; capturing = Capture(open.Where(d => d.LinkType != PacketDotNet.LinkLayers.LinuxSll)); } if (capturing.Length == 0) { // Base from all interfaces that are open linkType = PacketDotNet.LinkLayers.Null; capturing = Capture(open); } _linkType = linkType; _writer = CreateWriter(_index); if (capturing.Length != 0) { foreach (var device in capturing) { device.StartCapture(); _logger.LogInformation("Capturing {Device} ({Description})...", device.Name, device.Description); } _logger.LogInformation(" ... with {Filter}.", _configuration.Filter ?? "No filter"); _captureWatch.Start(); } else { _logger.LogWarning("No capture devices found to capture from."); } LibPcapLiveDevice[] Capture(IEnumerable candidates) { var capturing = new List(); foreach (var device in candidates) { try { // Open the device for capturing Debug.Assert(device.Opened); if (_configuration.Filter != null) { device.Filter = _configuration.Filter; } device.OnPacketArrival += WritePacket; capturing.Add(device); } catch (Exception ex) { _logger.LogError( "Failed to capture {Device} ({Description}): {Message}", device.Name, device.Description, ex.Message); } } return [.. capturing]; } } /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Dispose /// /// protected virtual void Dispose(bool disposing) { if (disposing) { try { StopCapture(); } catch (OperationCanceledException) { } catch (Exception ex) { _logger.LogError(ex, "Failed to complete capture."); } finally { _writer.Dispose(); Directory.Delete(_folder, true); } } } /// /// StopCapture /// protected void StopCapture() { if (_devices != null) { _devices.ForEach(d => { try { d.StopCapture(); _logger.LogInformation( "Capturing {Description} completed. ({Statistics}).", d.Description, d.Statistics.ToString()); } catch { } }); _devices.ForEach(d => d.Dispose()); _logger.LogInformation("Completed capture."); _devices = null; if (_captureCount > 0) { _writer.Close(); _captureCount = 0; _channel.Writer.TryWrite(_index); _channel.Writer.TryComplete(); } } } /// /// Callback to write packet /// /// /// private void WritePacket(object sender, PacketCapture e) { var pkt = e.GetPacket(); _captureCount += pkt.PacketLength; if (_captureCount >= _maxPcapSize || _captureWatch.ElapsedMilliseconds > kMaxPcapDuration) { UpdateWriter(); } _writer.Write(pkt); } /// /// Locked update of writer /// private void UpdateWriter() { lock (_lock) { if (_captureCount >= _maxPcapSize || _captureWatch.ElapsedMilliseconds > kMaxPcapDuration) { var finished = _index; _writer.Dispose(); _writer = CreateWriter(_index + 1); _index++; _captureCount = 0; _captureWatch.Restart(); _channel.Writer.TryWrite(finished); } } } /// /// Create next writer /// /// /// private CaptureFileWriterDevice CreateWriter(int index) { var writer = new CaptureFileWriterDevice(GetFilePath(_folder, index)); writer.Open(new DeviceConfiguration { LinkLayerType = _linkType }); return writer; } /// 100MB private const long kMaxPcapSize = 100 * 1024 * 1024; /// 5 minutes private const long kMaxPcapDuration = 5 * 60 * 1000; private static int _handles; private int _index; private long _captureCount; private readonly Stopwatch _captureWatch = new (); private readonly Lock _lock = new(); private readonly CaptureConfiguration _configuration; private List? _devices; private CaptureFileWriterDevice _writer; private readonly long _maxPcapSize; private readonly long _maxPcapDuration; private readonly Channel _channel; private readonly LinkLayers _linkType; protected readonly string _folder; protected readonly ILogger _logger; } /// /// Local capture /// internal sealed class Local : Base { /// /// Handle local capture /// /// /// /// public Local(ILogger logger, CaptureConfiguration configuration, Storage storage) : base(logger, configuration) { _storage = storage; _runner = RunAsync(); } /// protected override void Dispose(bool disposing) { if (disposing) { StopCapture(); try { // Will exit after stop capture as channel is completed _runner.GetAwaiter().GetResult(); } catch (OperationCanceledException) { } catch (Exception ex) { _logger.LogError(ex, "Failed to stop capture."); } } base.Dispose(disposing); } /// /// Service the file handler /// /// /// private async Task RunAsync(CancellationToken ct = default) { await foreach (var index in Reader.ReadAllAsync(ct).ConfigureAwait(false)) { var file = GetFilePath(_folder, index); await _storage.UploadAsync(file, ct).ConfigureAwait(false); File.Delete(file); } } private readonly Storage _storage; private readonly Task _runner; } /// /// Remote client /// private sealed class Remote : IDisposable { /// /// Create client /// /// /// /// /// public Remote(ILogger logger, CaptureConfiguration configuration, Storage storage, HttpClient client) { _logger = logger; _folder = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); Directory.CreateDirectory(_folder); _client = client; _storage = storage; _handle = StartAsync(configuration).GetAwaiter().GetResult(); _cts = new CancellationTokenSource(); _runner = RunAsync(_cts.Token); } /// public void Dispose() { try { StopAsync().GetAwaiter().GetResult(); _cts.Cancel(); _runner.GetAwaiter().GetResult(); } catch (OperationCanceledException) { } catch (Exception ex) { _logger.LogError(ex, "Failed to stop"); } finally { _cts.Dispose(); Directory.Delete(_folder, true); } } /// /// Start /// /// /// private async Task StartAsync(CaptureConfiguration configuration, CancellationToken ct = default) { var response = await _client.PutAsJsonAsync("/", configuration, ct).ConfigureAwait(false); response.EnsureSuccessStatusCode(); return await response.Content.ReadFromJsonAsync( ct).ConfigureAwait(false); } /// /// Service the file handler /// /// /// private async Task RunAsync(CancellationToken ct) { while (!ct.IsCancellationRequested) { try { await foreach (var index in _client .GetFromJsonAsAsyncEnumerable(new Uri($"/{_handle}"), ct).ConfigureAwait(false)) { var s = await _client.GetStreamAsync(new Uri($"/{_handle}/{index}"), ct).ConfigureAwait(false); var file = GetFilePath(_folder, index); var f = System.IO.File.Create(file); await using var sd = s.ConfigureAwait(false); await using var fd = f.ConfigureAwait(false); await s.CopyToAsync(f, ct).ConfigureAwait(false); await _storage.UploadAsync(file, ct).ConfigureAwait(false); File.Delete(file); } } catch (OperationCanceledException) { } catch (Exception ex) { _logger.LogError(ex, "Failed to download."); } } } /// /// Stop /// /// /// public async Task StopAsync(CancellationToken ct = default) { var response = await _client.DeleteAsync(new Uri($"/{_handle}"), ct).ConfigureAwait(false); response.EnsureSuccessStatusCode(); } private readonly int _handle; private readonly HttpClient _client; private readonly CancellationTokenSource _cts; private readonly Storage _storage; private readonly Task _runner; private readonly ILogger _logger; private readonly string _folder; } /// /// Remote capture server /// public sealed record Server : IDisposable { /// /// Create server /// /// /// public Server(WebApplication app, ILogger logger) { _logger = logger; app.MapPut("/", Start) .RequireAuthorization(nameof(App.ApiKeyProvider.ApiKey)) .Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status404NotFound); app.MapGet("/{handle}", WaitAsync) .RequireAuthorization(nameof(App.ApiKeyProvider.ApiKey)) .Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status404NotFound); app.MapGet("/{handle}/{index}", Download) .RequireAuthorization(nameof(App.ApiKeyProvider.ApiKey)) .Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status404NotFound); app.MapDelete("/{handle}", Stop) .RequireAuthorization(nameof(App.ApiKeyProvider.ApiKey)) .Produces(StatusCodes.Status200OK) .Produces(StatusCodes.Status404NotFound); } /// public void Dispose() { foreach (var capture in _captures.Values) { capture.Dispose(); } _captures.Clear(); } /// /// Start /// /// internal int Start(CaptureConfiguration configuration) { var pcap = new CaptureAdapter(_logger, configuration); _captures.TryAdd(pcap.Handle, pcap); return pcap.Handle; } /// /// Read next index to download /// /// /// /// /// internal IAsyncEnumerable WaitAsync(int handle, CancellationToken ct = default) { if (!_captures.TryGetValue(handle, out var capture)) { throw new NetcapException("Capture not found"); } return capture.ReadAllAsync(ct); } /// /// Download /// /// /// /// /// internal IResult Download(int handle, int index) { if (!_captures.TryGetValue(handle, out var capture)) { throw new NetcapException("Capture not found"); } return capture.Download(index); } /// /// get metadata and cleanup /// /// /// /// internal void Stop(int handle) { if (!_captures.TryRemove(handle, out var capture)) { throw new NetcapException("Capture not found"); } capture.Dispose(); } /// /// Remote capture /// /// /// private sealed class CaptureAdapter(ILogger logger, Pcap.CaptureConfiguration configuration) : Base(logger, configuration) { /// /// Download /// /// /// public IResult Download(int index) { if (index > 0) { // Clean up previous file File.Delete(GetFilePath(_folder, index - 1)); } return Results.File(GetFilePath(_folder, index)); } /// /// Read indexes /// /// /// public IAsyncEnumerable ReadAllAsync(CancellationToken ct = default) { return Reader.ReadAllAsync(ct); } } private readonly ConcurrentDictionary _captures = new(); private readonly ILogger _logger; } } ================================================ FILE: samples/Netcap/src/Program.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using Netcap; using var cts = new CancellationTokenSource(); Console.WriteLine($@" ____ _____ _____ _ _ _ / __ \| __ \ / ____| | \ | | | | | | | | |__) | | | \| | ___| |_ ___ __ _ _ __ | | | | ___/| | | . ` |/ _ \ __/ __/ _` | '_ \ | |__| | | | |____ | |\ | __/ || (_| (_| | |_) | \____/|_| \_____| |_| \_|\___|\__\___\__,_| .__/ | | |_| {typeof(Extensions).Assembly.GetVersion()} "); using var cmdLine = await App.RunAsync(args, cts.Token).ConfigureAwait(false); ================================================ FILE: samples/Netcap/src/Publisher.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Netcap; using Microsoft.Extensions.Logging; using System.Net; using System.Net.Http; using System.Net.Http.Json; using System.Text.Json; /// /// Publisher interaction /// internal sealed class Publisher : IDisposable { /// /// Endpoint urls /// public HashSet Endpoints { get; } = []; /// /// Addresses of the publisher on the network /// public HashSet Addresses { get; } = []; /// /// Create publisher /// /// /// /// public Publisher(HttpClient httpClient, string? publisherIpAddresses, ILogger logger) { _logger = logger; _httpClient = httpClient; _folder = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); Directory.CreateDirectory(_folder); if (!string.IsNullOrWhiteSpace(publisherIpAddresses)) { foreach (var address in publisherIpAddresses.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)) { if (IPAddress.TryParse(address, out var ip)) { Addresses.Add(ip); } } } } /// public void Dispose() { Directory.Delete(_folder, true); } /// /// Collect traces /// /// /// /// /// public Pcap.CaptureConfiguration GetCaptureConfiguration( Pcap.InterfaceType itf = Pcap.InterfaceType.AnyIfAvailable, int? maxPcapFileSize = null, TimeSpan? maxPcapDuration = null) { // Base filter // https://www.wireshark.org/docs/man-pages/pcap-filter.html // src or dst host 192.168.80.2 // "ip and tcp and not port 80 and not port 25"; // TODO: Filter on src/dst of publisher ip var addresses = Addresses .Where(a => a.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) .ToList(); if (addresses.Count == 0) { return new Pcap.CaptureConfiguration(itf, "ip and tcp", maxPcapFileSize, maxPcapDuration); } var filter = "src or dst host " + ((addresses.Count == 1) ? addresses[0] : ("(" + string.Join(" or ", addresses.Select(a => $"{a}")) + ")")); return new Pcap.CaptureConfiguration(itf, filter, maxPcapFileSize, maxPcapDuration); } /// /// Monitor publisher /// /// /// /// public async ValueTask UploadChannelLogsAsync(Storage storage, CancellationToken ct = default) { while (!ct.IsCancellationRequested) { // Watch session diagnostics while we capture try { _logger.LogInformation("Monitoring channels at {Url}...", _httpClient.BaseAddress); await foreach (var diagnostic in _httpClient.GetFromJsonAsAsyncEnumerable( "v2/diagnostics/channels/watch", cancellationToken: ct).ConfigureAwait(false)) { try { await UploadSessionKeysFromDiagnosticsAsync(storage, diagnostic, ct).ConfigureAwait(false); } catch (OperationCanceledException) { } catch (Exception ex) { _logger.LogError(ex, "Error uploading session keys."); } } _logger.LogInformation("Restart monitoring channel diagnostics..."); } catch (OperationCanceledException) { } // Done catch (Exception ex) { _logger.LogError(ex, "Error monitoring channel diagnostics - restarting..."); } } } /// /// Try update the endpoints and addresses from the publisher. /// /// /// /// public async ValueTask TryUploadEndpointsAsync(Storage storage, CancellationToken ct = default) { try { _logger.LogInformation("Retrieving endpoints from publisher on {Url}...", _httpClient.BaseAddress); // Stop and endpoint url to monitor if not set var configuration = await _httpClient.GetFromJsonAsync( "v2/configuration?includeNodes=true", JsonSerializerOptions.Default, ct).ConfigureAwait(false); var pnJson = JsonSerializer.Serialize(configuration, Extensions.Indented); foreach (var endpoint in configuration.GetProperty("endpoints").EnumerateArray()) { var endpointUrl = endpoint.GetProperty("EndpointUrl").GetString(); if (!string.IsNullOrWhiteSpace(endpointUrl)) { Endpoints.Add(endpointUrl); } } if (Endpoints.Count == 0) { _logger.LogInformation("No endpoints found in configuration - waiting...."); return false; } _logger.LogInformation("Retrieved {Count} endpoints from publisher.", Endpoints.Count); var pnJsonFile = Path.Combine(_folder, "pn.json"); await File.WriteAllTextAsync(pnJsonFile, pnJson, ct).ConfigureAwait(false); await storage.UploadAsync(pnJsonFile, ct).ConfigureAwait(false); return true; } catch (OperationCanceledException) { } catch (Exception ex) { _logger.LogError(ex, "Failed to update endpoints from publisher."); } return false; } /// /// Upload session keys to storage from publisher diagnostics /// /// /// /// /// private async Task UploadSessionKeysFromDiagnosticsAsync(Storage storage, JsonElement diagnostic, CancellationToken ct = default) { var diagnosticJson = JsonSerializer.Serialize(diagnostic, Extensions.Indented); if (diagnostic.TryGetProperty("connection", out var conn) && conn.TryGetProperty("endpoint", out var ep) && ep.TryGetProperty("url", out _) && diagnostic.TryGetProperty("sessionCreated", out var sessionCreatedToken) && sessionCreatedToken.TryGetDateTimeOffset(out var sessionCreated) && diagnostic.TryGetProperty("sessionId", out var sessionId) && sessionId.GetString() != null && diagnostic.TryGetProperty("remotePort", out var remotePortToken) && remotePortToken.TryGetInt32(out var remotePort)) { var name = Extensions.FixFileName(sessionId.GetString() + sessionCreated); var filePath = Path.Combine(_folder, $"{remotePort}_{name}"); var logFile = filePath + ".log"; await File.AppendAllTextAsync(logFile, diagnosticJson, ct) .ConfigureAwait(false); await storage.UploadAsync(logFile, ct).ConfigureAwait(false); if (diagnostic.TryGetProperty("channelId", out var channelIdToken) && channelIdToken.TryGetUInt32(out var channelId) && diagnostic.TryGetProperty("tokenId", out var tokenIdToken) && tokenIdToken.TryGetUInt32(out var tokenId) && diagnostic.TryGetProperty("client", out var clientToken) && clientToken.TryGetProperty("iv", out var clientIvToken) && clientIvToken.TryGetBytes(out var clientIv) && clientToken.TryGetProperty("key", out var clientKeyToken) && clientKeyToken.TryGetBytes(out var clientKey) && clientToken.TryGetProperty("sigLen", out var clientSigLenToken) && clientSigLenToken.TryGetInt32(out var clientSigLen) && diagnostic.TryGetProperty("server", out var serverToken) && serverToken.TryGetProperty("iv", out var serverIvToken) && serverIvToken.TryGetBytes(out var serverIv) && serverToken.TryGetProperty("key", out var serverKeyToken) && serverKeyToken.TryGetBytes(out var serverKey) && serverToken.TryGetProperty("sigLen", out var serverSigLenToken) && serverSigLenToken.TryGetInt32(out var serverSigLen)) { // Add session keys to the endpoint capture _logger.LogInformation( "Logging session keys for channel {ChannelId} token {TokenId}", channelId, tokenId); var keyFile = filePath + ".txt"; await AddSessionKeysAsync(keyFile, channelId, tokenId, clientIv, clientKey, clientSigLen, serverIv, serverKey, serverSigLen, ct).ConfigureAwait(false); await storage.UploadAsync(keyFile, ct).ConfigureAwait(false); static async ValueTask AddSessionKeysAsync(string fileName, uint channelId, uint tokenId, byte[] clientIv, byte[] clientKey, int clientSigLen, byte[] serverIv, byte[] serverKey, int serverSigLen, CancellationToken ct = default) { var keysets = File.AppendText(fileName); await using var _ = keysets.ConfigureAwait(false); await keysets.WriteLineAsync( $"client_iv_{channelId}_{tokenId}: {Convert.ToHexString(clientIv)}").ConfigureAwait(false); await keysets.WriteLineAsync( $"client_key_{channelId}_{tokenId}: {Convert.ToHexString(clientKey)}").ConfigureAwait(false); await keysets.WriteLineAsync( $"client_siglen_{channelId}_{tokenId}: {clientSigLen}").ConfigureAwait(false); await keysets.WriteLineAsync( $"server_iv_{channelId}_{tokenId}: {Convert.ToHexString(serverIv)}").ConfigureAwait(false); await keysets.WriteLineAsync( $"server_key_{channelId}_{tokenId}: {Convert.ToHexString(serverKey)}").ConfigureAwait(false); await keysets.WriteLineAsync( $"server_siglen_{channelId}_{tokenId}: {serverSigLen}").ConfigureAwait(false); await keysets.FlushAsync(ct).ConfigureAwait(false); } } else { _logger.LogInformation("No key information logged."); } } else { _logger.LogInformation("Received invalid diagnostic: {Diagnostic}", diagnosticJson); } } private readonly ILogger _logger; private readonly HttpClient _httpClient; private readonly string _folder; } ================================================ FILE: samples/Netcap/src/Storage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Netcap; using Azure; using Azure.Storage.Blobs; using Azure.Storage.Queues; using Azure.Storage.Blobs.Models; using Microsoft.Extensions.Logging; using System.Text.Json; using System.IO; using System.Globalization; using System; using Azure.Storage; /// /// Upload and download files /// /// /// Create capture sync /// /// /// /// /// /// internal sealed class Storage(string deviceId, string moduleId, string connectionString, ILogger logger, string? runName = null) { /// /// Download files /// /// /// /// public async Task DownloadAsync(string path, CancellationToken ct = default) { var queueName = Extensions.FixUpStorageName($"{_deviceId}_{_moduleId}"); var queueClient = new QueueClient(_connectionString, queueName); await EnsureQueueAsync(queueClient, ct).ConfigureAwait(false); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } _logger.LogInformation("Downloading files to {Path}.", path); while (!ct.IsCancellationRequested) { try { // Receive message var message = await queueClient.ReceiveMessageAsync( cancellationToken: ct).ConfigureAwait(false); if (!message.HasValue || message.Value?.Body == null) { continue; } var notification = JsonSerializer.Deserialize(message.Value.Body); if (notification == null) { continue; } try { var containerClient = new BlobContainerClient(_connectionString, notification.ContainerName); var blobClient = containerClient.GetBlobClient(notification.BlobName); var blobProperties = await blobClient.GetPropertiesAsync( cancellationToken: ct).ConfigureAwait(false); var metadata = blobProperties.Value.Metadata; if (!metadata.TryGetValue("File", out var f) || !metadata.TryGetValue("Date", out var d)) { continue; } var c = Extensions.FixFolderName(notification.ContainerName); var folder = Path.Combine(path, c); if (!Directory.Exists(folder)) { Directory.CreateDirectory(folder); } var file = Path.Combine(folder, Extensions.FixFileName(f)); _logger.LogInformation("Downloading {Blob}...", notification.BlobName); await blobClient.DownloadToAsync(file, new BlobDownloadToOptions { TransferOptions = new StorageTransferOptions { MaximumConcurrency = 4, InitialTransferSize = 8 * 1024 * 1024, MaximumTransferSize = 8 * 1024 * 1024 } }, default).ConfigureAwait(false); _logger.LogInformation("Downloaded {Blob} to file {File}.", notification.BlobName, file); } catch (OperationCanceledException) { } catch (Exception ex) { _logger.LogError(ex, "Failed to download file from blob {BlobName}.", notification.BlobName); } finally { if (message.Value?.MessageId != null) { await queueClient.DeleteMessageAsync(message.Value.MessageId, message.Value.PopReceipt, ct).ConfigureAwait(false); } } } catch (OperationCanceledException) { } catch (Exception ex) { _logger.LogError(ex, "Error receiving download notification."); } } } /// /// Upload file /// /// /// /// public async ValueTask UploadAsync(string file, CancellationToken ct = default) { try { _logger.LogInformation("Uploading file {File}.", file); var containerName = Extensions.FixUpStorageName($"{_deviceId}_{_moduleId}_{_runName}"); var containerClient = new BlobContainerClient(_connectionString, containerName); var queueName = Extensions.FixUpStorageName($"{_deviceId}_{_moduleId}"); var queueClient = new QueueClient(_connectionString, queueName); await EnsureQueueAsync(queueClient, ct).ConfigureAwait(false); await containerClient.CreateIfNotExistsAsync(PublicAccessType.None, GetClientMetadata(), cancellationToken: ct).ConfigureAwait(false); // Upload file var blobName = Extensions.FixUpStorageName(Path.GetFileName(file)); var blobClient = containerClient.GetBlobClient(blobName); var blobMetadata = new Dictionary() { ["Date"] = DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture), ["File"] = Path.GetFileName(file) }; await blobClient.UploadAsync(file, new BlobUploadOptions { TransferOptions = new StorageTransferOptions { MaximumConcurrency = 2, InitialTransferSize = 8 * 1024 * 1024, MaximumTransferSize = 8 * 1024 * 1024 }, Metadata = blobMetadata, ProgressHandler = new ProgressLogger(_logger, blobName) }, ct).ConfigureAwait(false); // Send completion notification var message = JsonSerializer.Serialize(new Notification( containerClient.Uri, blobClient.Uri, blobClient.BlobContainerName, blobClient.Name)); await queueClient.SendMessageAsync(message, ct).ConfigureAwait(false); _logger.LogInformation("Completed upload of file {File} to {BlobName}.", file, blobName); } catch (Exception ex) { _logger.LogError(ex, "Failed to upload file {File}.", file); throw; } } /// /// Delete storage /// /// /// public async Task DeleteAsync(CancellationToken ct) { var containerName = Extensions.FixUpStorageName($"{_deviceId}_{_moduleId}_{_runName}"); _logger.LogInformation("Delete storage {Name}...", containerName); var containerClient = new BlobContainerClient(_connectionString, containerName); if (await containerClient.ExistsAsync(ct).ConfigureAwait(false)) { // leave // await containerClient.DeleteAsync(cancellationToken: ct).ConfigureAwait(false); } var queueName = Extensions.FixUpStorageName($"{_deviceId}_{_moduleId}"); var queueClient = new QueueClient(_connectionString, queueName); if (await queueClient.ExistsAsync(ct).ConfigureAwait(false)) { await queueClient.DeleteAsync(ct).ConfigureAwait(false); } } /// /// Ensure queue exists and can be used /// /// /// /// private async Task EnsureQueueAsync(QueueClient queueClient, CancellationToken ct) { while (!ct.IsCancellationRequested) { try { await queueClient.CreateIfNotExistsAsync(GetClientMetadata(), ct).ConfigureAwait(false); break; } catch (RequestFailedException ex) when (ex.Status == 409 && ex.ErrorCode == "QueueBeingDeleted") { await Task.Delay(TimeSpan.FromSeconds(1), ct).ConfigureAwait(false); } } } private Dictionary GetClientMetadata() { return new Dictionary { ["DeviceId"] = _deviceId, ["ModuleId"] = _moduleId }; } private sealed record class ProgressLogger(ILogger Logger, string BlobName) : IProgress { /// public void Report(long value) { if (value > _lastProgress) { _lastProgress = value; Logger.LogInformation( "Uploading {Blob} - {Progress} bytes", BlobName, value); } } private long _lastProgress; } internal sealed record class Notification(Uri ContainerUri, Uri BlobUri, string ContainerName, string BlobName); private readonly string _deviceId = deviceId; private readonly string _moduleId = moduleId; private readonly string _runName = runName ?? DateTime.UtcNow.ToBinary() .ToString(CultureInfo.InvariantCulture); private readonly string _connectionString = connectionString; private readonly ILogger _logger = logger; } ================================================ FILE: src/.gitignore ================================================ /**/launchSettings.json ================================================ FILE: src/Azure.IIoT.OpcUa/src/Azure.IIoT.OpcUa.csproj ================================================  net9.0 true Azure OPC Publisher shared code enable ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/AvroBinaryReader.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Opc.Ua; using System; using System.Buffers; using System.Buffers.Binary; using System.IO; using System.Text; /// /// Reads from a Avro Binary encoded stream. /// public sealed class AvroBinaryReader : IDisposable { private readonly bool _leaveOpen; /// /// Underlying stream /// public Stream Stream { get; } /// /// Max string /// public int MaxStringLength { get; set; } = 64 * 1024; /// /// Max bytes /// public int MaxBytesLength { get; set; } = 64 * 1024; /// /// Create avro reader /// /// /// public AvroBinaryReader(Stream stream, bool leaveOpen = false) { Stream = stream; _leaveOpen = leaveOpen; } /// public void Dispose() { if (!_leaveOpen) { Stream.Dispose(); } } /// public bool ReadBoolean() { var b = ReadByte(); switch (b) { case 0: return false; case 1: return true; default: throw new DecodingException( "Not a boolean value in the stream: " + b); } } /// public long ReadInteger() { var b = ReadByte(); var n = b & 0x7FUL; var shift = 7; while ((b & 0x80) != 0) { b = ReadByte(); n |= (b & 0x7FUL) << shift; shift += 7; } var value = (long)n; return (-(value & 0x01L)) ^ ((value >> 1) & 0x7fffffffffffffffL); } /// public void ReadFixed(Span buffer) { while (!buffer.IsEmpty) { var n = Stream.Read(buffer); if (n <= 0) { throw new DecodingException(StatusCodes.BadEndOfStream, "End of stream reached."); } buffer = buffer[n..]; } } /// public float ReadFloat() { Span bytes = stackalloc byte[sizeof(float)]; ReadFixed(bytes); return BinaryPrimitives.ReadSingleLittleEndian(bytes); } /// public double ReadDouble() { Span bytes = stackalloc byte[sizeof(double)]; ReadFixed(bytes); return BinaryPrimitives.ReadDoubleLittleEndian(bytes); } /// public byte[] ReadBytes() { var length = ReadInteger(); if (length == 0) { return []; } if (MaxBytesLength > 0 && MaxBytesLength < length) { throw new DecodingException(StatusCodes.BadEncodingLimitsExceeded, $"MaxByteStringLength {MaxBytesLength} < {length}."); } var buffer = new byte[(int)length]; ReadFixed(buffer.AsSpan()); return buffer; } /// public string ReadString() { var length = ReadInteger(); if (length == 0) { return string.Empty; } if (MaxStringLength > 0 && MaxStringLength < length) { throw new DecodingException(StatusCodes.BadEncodingLimitsExceeded, $"MaxStringLength {MaxStringLength} < {length}."); } if (length <= 256) { Span buffer = stackalloc byte[(int)length]; ReadFixed(buffer); return GetString(buffer); } else if (length <= 4096) { var bufferArray = ArrayPool.Shared.Rent((int)length); try { var buffer = bufferArray.AsSpan(0, (int)length); ReadFixed(buffer); return GetString(buffer); } finally { ArrayPool.Shared.Return(bufferArray); } } else { using var binaryReader = new BinaryReader(Stream, Encoding.UTF8, true); var bytes = binaryReader.ReadBytes((int)length); if (bytes.Length != length) { throw new DecodingException( "Could not read as many bytes from stream as expected!"); } return GetString(bytes); } static string GetString(ReadOnlySpan bytes) { if (bytes[^1] == 0) { // If 0 terminated, decrease length by one // before converting to string bytes = bytes[..^1]; } return Encoding.UTF8.GetString(bytes); } } private byte ReadByte() { var n = Stream.ReadByte(); if (n >= 0) { return (byte)n; } throw new DecodingException(StatusCodes.BadEndOfStream, "Stream reached its end."); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/AvroBinaryWriter.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using System; using System.Buffers.Binary; using System.IO; using System.Text; /// /// Encodes objects in a stream using Avro binary encoding. /// public sealed class AvroBinaryWriter : IDisposable { /// /// Underlying stream /// public Stream Stream { get; } /// /// Creates a writer that writes avro binary to /// the stream. /// /// The stream to which the /// encoder writes. /// If the stream should /// be left open on dispose. public AvroBinaryWriter(Stream stream, bool leaveOpen = true) { Stream = stream; _leaveOpen = leaveOpen; } /// public void Dispose() { if (!_leaveOpen) { Stream.Dispose(); } } /// public void WriteBoolean(bool value) { Stream.WriteByte((byte)(value ? 0x1 : 0x0)); } /// public void WriteInteger(int value) { var encoded = (uint)((value << 1) ^ (value >> 31)); do { var current = encoded & 0x7FU; encoded >>= 7; if (encoded != 0) { current |= 0x80U; } Stream.WriteByte((byte)current); } while (encoded != 0U); } /// public void WriteInteger(long value) { var encoded = (ulong)((value << 1) ^ (value >> 63)); do { var current = encoded & 0x7FUL; encoded >>= 7; if (encoded != 0) { current |= 0x80UL; } Stream.WriteByte((byte)current); } while (encoded != 0UL); } /// public void WriteFloat(float value) { Span bytes = stackalloc byte[sizeof(float)]; BinaryPrimitives.WriteSingleLittleEndian(bytes, value); WriteFixed(bytes); } /// public void WriteDouble(double value) { Span bytes = stackalloc byte[sizeof(double)]; BinaryPrimitives.WriteDoubleLittleEndian(bytes, value); WriteFixed(bytes); } /// public void WriteFixed(ReadOnlySpan buffer) { Stream.Write(buffer); } /// internal void WriteBytes(ReadOnlySpan value) { WriteInteger(value.Length); WriteFixed(value); } /// public void WriteString(string value) { WriteBytes(Encoding.UTF8.GetBytes(value)); } private readonly bool _leaveOpen; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/AvroDecoder.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Azure.IIoT.OpcUa.Encoders.Models; using Azure.IIoT.OpcUa.Encoders.Schemas; using Azure.IIoT.OpcUa.Encoders.Schemas.Avro; using Azure.IIoT.OpcUa.Publisher.Models; using Avro; using Opc.Ua; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Xml; /// /// Decodes objects from underlying decoder using a provided /// Avro schema. Validation errors throw. /// public sealed class AvroDecoder : BaseAvroDecoder { /// /// Schema to use /// public Schema Schema { get; } /// /// Schema to use /// public Schema Current => _schema.Current; /// /// Creates a decoder that decodes the data from the /// passed in stream. /// /// The stream to which the /// encoder writes. /// /// The message context to /// use for the encoding. /// public AvroDecoder(Stream stream, Schema schema, IServiceMessageContext context, bool leaveOpen = false) : base(stream, context, leaveOpen) { Schema = schema; _schema = new AvroSchemaTraverser(schema); } /// public override bool ReadBoolean(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.Boolean, base.ReadBoolean); } /// public override sbyte ReadSByte(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.SByte, base.ReadSByte); } /// public override byte ReadByte(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.Byte, base.ReadByte); } /// public override short ReadInt16(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.Int16, base.ReadInt16); } /// public override ushort ReadUInt16(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.UInt16, base.ReadUInt16); } /// public override int ReadInt32(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.Int32, base.ReadInt32); } /// public override uint ReadUInt32(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.UInt32, base.ReadUInt32); } /// public override long ReadInt64(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.Int64, base.ReadInt64); } /// public override float ReadFloat(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.Float, base.ReadFloat); } /// public override double ReadDouble(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.Double, base.ReadDouble); } /// public override Uuid ReadGuid(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.Guid, base.ReadGuid); } /// public override string? ReadString(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.String, base.ReadString); } /// public override ulong ReadUInt64(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.UInt64, base.ReadUInt64); } /// public override DateTime ReadDateTime(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.DateTime, base.ReadDateTime); } /// public override byte[] ReadByteString(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.ByteString, base.ReadByteString); } /// public override XmlElement ReadXmlElement(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.XmlElement, base.ReadXmlElement); } /// public override StatusCode ReadStatusCode(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.StatusCode, base.ReadStatusCode); } /// public override NodeId ReadNodeId(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.NodeId, base.ReadNodeId); } /// public override ExpandedNodeId ReadExpandedNodeId(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.ExpandedNodeId, base.ReadExpandedNodeId); } /// public override QualifiedName ReadQualifiedName(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.QualifiedName, base.ReadQualifiedName); } /// public override LocalizedText ReadLocalizedText(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.LocalizedText, base.ReadLocalizedText); } /// public override DataValue ReadDataValue(string? fieldName) { // Get current field schema var currentSchema = GetFieldSchema(fieldName); // Should be data value compatible if (!currentSchema.IsDataValue()) { throw new DecodingException( $"Schema {currentSchema.Fullname} is not " + $"as expected {currentSchema.ToJson()}.", Schema.ToJson()); } // Read type per schema var result = base.ReadDataValue(fieldName); ValidatedPop(currentSchema); return result; } /// public override Variant ReadVariant(string? fieldName) { var currentSchema = GetFieldSchema(fieldName); var result = ReadVariant(fieldName, currentSchema); ValidatedPop(currentSchema); return result; Variant ReadVariant(string? fieldName, Schema currentSchema) { var expectedType = _builtIns.GetSchemaForBuiltInType( BuiltInType.Variant, SchemaRank.Scalar); if (currentSchema.Fullname == expectedType.Fullname) { // Read as variant return base.ReadVariant(fieldName); } // Alternatively the schema could be nullable if (currentSchema is UnionSchema u) { // Read as nullable return ReadWithSchema(u, () => ReadNullable(fieldName, _ => ReadVariantValueWithSchema(u.Schemas[1]))); } return ReadVariantValueWithSchema(currentSchema); Variant ReadVariantValueWithSchema(Schema currentSchema) { // Read as built in type if (currentSchema.IsBuiltInType(out var builtInType, out var rank)) { return ReadWithSchema(currentSchema, () => ReadVariantValue(builtInType, rank)); } // Read as encodeable var typeId = currentSchema.GetDataTypeId(Context); var systemType = Context.Factory.GetSystemType(typeId); if (systemType != null) { return new Variant(ReadWithSchema(currentSchema, () => ReadEncodeable(null, systemType, typeId))); } throw new DecodingException( $"Variant schema {currentSchema.ToJson()} of " + $"field {fieldName ?? "unnamed"} is neither variant nor built " + "in type schema.", Schema.ToJson()); } } } /// public override DataSet ReadDataSet(string? fieldName) { var currentSchema = GetFieldSchema(fieldName); var result = ReadDataSet(currentSchema); ValidatedPop(currentSchema); return result; DataSet ReadDataSet(Schema currentSchema) { if (currentSchema is not RecordSchema r) { throw new DecodingException( $"Invalid schema {currentSchema.ToJson()}. " + "Data sets must be records or maps.", Schema.ToJson()); } var dataSet = new List<(string, DataValue?)>(); var isRaw = false; // Run through the fields and read either using variant or data values foreach (var field in r.Fields) { var dataValue = ReadDataSetField(field.Name); if (dataValue?.StatusCode == (StatusCode)uint.MaxValue) { isRaw = true; dataValue.StatusCode = StatusCodes.Good; } dataSet.Add((SchemaUtils.Unescape(field.Name), dataValue)); } var dataSetFieldContentFlags = isRaw ? DataSetFieldContentFlags.RawData : 0; return new DataSet(dataSet, dataSetFieldContentFlags); } } /// /// Read data set field /// /// /// /// private DataValue? ReadDataSetField(string? fieldName) { var currentSchema = GetFieldSchema(fieldName); var result = ReadDataSetField(currentSchema); ValidatedPop(currentSchema); return result; DataValue? ReadDataSetFieldValue() { var isRaw = true; if (Current is RecordSchema fieldRecord && fieldRecord.IsDataValue()) { var dataValue = new DataValue(); foreach (var dvf in fieldRecord.Fields) { switch (dvf.Name) { case nameof(DataValue.Value): dataValue.Value = ReadVariant(nameof(DataValue.Value)); break; case nameof(DataValue.SourceTimestamp): isRaw = false; dataValue.SourceTimestamp = ReadDateTime(nameof(DataValue.SourceTimestamp)); break; case nameof(DataValue.SourcePicoseconds): isRaw = false; dataValue.SourcePicoseconds = ReadUInt16(nameof(DataValue.SourcePicoseconds)); break; case nameof(DataValue.ServerTimestamp): isRaw = false; dataValue.ServerTimestamp = ReadDateTime(nameof(DataValue.ServerTimestamp)); break; case nameof(DataValue.ServerPicoseconds): isRaw = false; dataValue.ServerPicoseconds = ReadUInt16(nameof(DataValue.ServerPicoseconds)); break; case nameof(DataValue.StatusCode): isRaw = false; dataValue.StatusCode = ReadStatusCode(nameof(DataValue.StatusCode)); break; default: throw new DecodingException( $"Unknown field {dvf.Name} in dataset field.", Schema.ToJson()); } } if (isRaw) { dataValue.StatusCode = (StatusCode)uint.MaxValue; } return dataValue; } // Read value as variant var value = ReadWithSchema(currentSchema, () => ReadVariant(null)); if (value == Variant.Null) { return null; } return new DataValue(value, (StatusCode)uint.MaxValue); } DataValue? ReadDataSetField(Schema currentSchema) { if (currentSchema is UnionSchema u) { return ReadWithSchema(u, () => ReadNullable(null, _ => { _schema.Push(((UnionSchema)Current).Schemas[1]); var v = ReadDataSetFieldValue(); _schema.Pop(); return v!; })); } return ReadDataSetFieldValue(); } } /// public override IEncodeable ReadEncodeable(string? fieldName, Type systemType, ExpandedNodeId? encodeableTypeId = null) { if (Activator.CreateInstance(systemType) is not IEncodeable encodeable) { throw new DecodingException( $"Cannot decode type '{systemType.FullName}'."); } var fullName = encodeable.TypeId.GetFullName(systemType.Name, Context); return ValidatedRead(fieldName, fullName ?? systemType.Name, f => base.ReadEncodeable(f, systemType, encodeableTypeId), fullName != null); } /// public override ExtensionObject? ReadExtensionObject(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.ExtensionObject, base.ReadExtensionObject); } /// protected override ExtensionObject ReadEncodedDataType(string? fieldName) { return ValidatedRead(fieldName, SchemaUtils.NamespaceZeroName + ".EncodedDataType", base.ReadEncodedDataType); } /// public override int ReadEnumerated(string? fieldName) { var currentSchema = GetFieldSchema(fieldName); var result = ReadEnumerated(fieldName, currentSchema); ValidatedPop(currentSchema); return result; int ReadEnumerated(string? fieldName, Schema currentSchema) { if (currentSchema.IsBuiltInType(out var builtInType, out var rank) && rank == SchemaRank.Scalar && (builtInType == BuiltInType.Int32 || builtInType == BuiltInType.Enumeration)) { return ReadWithSchema(currentSchema, () => base.ReadEnumerated(fieldName)); } throw new EncodingException( $"Invalid schema {currentSchema.ToJson()}. " + "Enumerated values must be enums.", Schema.ToJson()); } } /// public override BooleanCollection ReadBooleanArray(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.Boolean, base.ReadBooleanArray, SchemaRank.Collection); } /// public override SByteCollection ReadSByteArray(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.SByte, base.ReadSByteArray, SchemaRank.Collection); } /// public override ByteCollection ReadByteArray(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.ByteString, base.ReadByteArray, SchemaRank.Scalar); } /// public override Int16Collection ReadInt16Array(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.Int16, base.ReadInt16Array, SchemaRank.Collection); } /// public override UInt16Collection ReadUInt16Array(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.UInt16, base.ReadUInt16Array, SchemaRank.Collection); } /// public override Int32Collection ReadInt32Array(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.Int32, base.ReadInt32Array, SchemaRank.Collection); } /// public override UInt32Collection ReadUInt32Array(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.UInt32, base.ReadUInt32Array, SchemaRank.Collection); } /// public override Int64Collection ReadInt64Array(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.Int64, base.ReadInt64Array, SchemaRank.Collection); } /// public override UInt64Collection ReadUInt64Array(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.UInt64, base.ReadUInt64Array, SchemaRank.Collection); } /// public override FloatCollection ReadFloatArray(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.Float, base.ReadFloatArray, SchemaRank.Collection); } /// public override DoubleCollection ReadDoubleArray(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.Double, base.ReadDoubleArray, SchemaRank.Collection); } /// public override StringCollection ReadStringArray(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.String, base.ReadStringArray, SchemaRank.Collection); } /// public override DateTimeCollection ReadDateTimeArray(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.DateTime, base.ReadDateTimeArray, SchemaRank.Collection); } /// public override UuidCollection ReadGuidArray(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.Guid, base.ReadGuidArray, SchemaRank.Collection); } /// public override ByteStringCollection ReadByteStringArray(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.ByteString, base.ReadByteStringArray, SchemaRank.Collection); } /// public override XmlElementCollection ReadXmlElementArray(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.XmlElement, base.ReadXmlElementArray, SchemaRank.Collection); } /// public override NodeIdCollection ReadNodeIdArray(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.NodeId, base.ReadNodeIdArray, SchemaRank.Collection); } /// public override ExpandedNodeIdCollection ReadExpandedNodeIdArray(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.ExpandedNodeId, base.ReadExpandedNodeIdArray, SchemaRank.Collection); } /// public override StatusCodeCollection ReadStatusCodeArray(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.StatusCode, base.ReadStatusCodeArray, SchemaRank.Collection); } /// public override DiagnosticInfoCollection ReadDiagnosticInfoArray(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.DiagnosticInfo, base.ReadDiagnosticInfoArray, SchemaRank.Collection); } /// public override QualifiedNameCollection ReadQualifiedNameArray(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.QualifiedName, base.ReadQualifiedNameArray, SchemaRank.Collection); } /// public override LocalizedTextCollection ReadLocalizedTextArray(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.LocalizedText, base.ReadLocalizedTextArray, SchemaRank.Collection); } /// public override VariantCollection ReadVariantArray(string? fieldName) { var currentSchema = GetFieldSchema(fieldName); var result = ReadVariantArray(fieldName, currentSchema); ValidatedPop(currentSchema); return result; VariantCollection ReadVariantArray(string? fieldName, Schema currentSchema) { var expectedType = _builtIns.GetSchemaForBuiltInType(BuiltInType.Variant, SchemaRank.Collection); // Write as variant collection if (currentSchema.Fullname == expectedType.Fullname) { return base.ReadVariantArray(fieldName); } // Write as built in type if (currentSchema.IsBuiltInType(out var builtInType, out var rank)) { // When written in concise mode we get an array of bytes as byte string if (builtInType == BuiltInType.ByteString && rank == SchemaRank.Scalar) { var result = ReadWithSchema(currentSchema, () => ReadScalar(null, builtInType)); return (result.Value as byte[])? .Select(o => new Variant(o)) .ToArray(); } // // Otherwise rank should be collection, and all values to write should be // scalar and of the built in type // if (rank == SchemaRank.Collection) { var result = ReadWithSchema(currentSchema, () => ReadArray(null, builtInType, null, null)); if (result == null || result.Length == 0) { return Array.Empty(); } return result.Cast() .Select(o => new Variant(o)) .ToArray(); } throw new DecodingException( $"Wrong schema {currentSchema.ToJson()} " + $"of field {fieldName ?? "unnamed"} to write variants.", Schema.ToJson()); } throw new DecodingException( $"Variant schema {currentSchema.ToJson()} of " + $"field {fieldName ?? "unnamed"} is neither variant collection " + "nor built in type collection schema.", Schema.ToJson()); } } /// public override DataValueCollection ReadDataValueArray(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.DataValue, base.ReadDataValueArray, SchemaRank.Collection); } /// public override ExtensionObjectCollection ReadExtensionObjectArray(string? fieldName) { return ValidatedRead(fieldName, BuiltInType.ExtensionObject, base.ReadExtensionObjectArray, SchemaRank.Collection); } /// public override Array? ReadEncodeableArray(string? fieldName, Type systemType, ExpandedNodeId? encodeableTypeId) { return base.ReadEncodeableArray(fieldName, systemType, encodeableTypeId); } /// public override Array? ReadEnumeratedArray(string? fieldName, Type enumType) { var currentSchema = GetFieldSchema(fieldName); var result = ReadEnumeratedArray(fieldName, currentSchema); ValidatedPop(currentSchema); return result; Array? ReadEnumeratedArray(string? fieldName, Schema currentSchema) { if (currentSchema is ArraySchema a && a.ItemSchema is EnumSchema e) { return ReadWithSchema(currentSchema, () => base.ReadEnumeratedArray(fieldName, enumType)); } else if (currentSchema.IsBuiltInType(out var builtInType, out var rank) && rank == SchemaRank.Collection && (builtInType == BuiltInType.Int32 || builtInType == BuiltInType.Enumeration)) { return base.ReadEnumeratedArray(fieldName, enumType); } else { throw new EncodingException($"Invalid schema {currentSchema.ToJson()}. " + "Enumerated values must be arrays of enums.", Schema.ToJson()); } } } /// public override int[] ReadEnumeratedArray(string? fieldName) { var currentSchema = GetFieldSchema(fieldName); var result = ReadEnumeratedArray(fieldName, currentSchema); ValidatedPop(currentSchema); return result; int[] ReadEnumeratedArray(string? fieldName, Schema currentSchema) { if (currentSchema is ArraySchema a && a.ItemSchema is EnumSchema e) { return ReadWithSchema(currentSchema, () => base.ReadEnumeratedArray(fieldName)); } else if (currentSchema.IsBuiltInType(out var builtInType, out var rank) && rank == SchemaRank.Collection && (builtInType == BuiltInType.Int32 || builtInType == BuiltInType.Enumeration)) { return base.ReadEnumeratedArray(fieldName); } else { throw new EncodingException( $"Invalid schema {currentSchema.ToJson()}. " + "Enumerated values must be arrays of enums.", Schema.ToJson()); } } } /// public override T? ReadNull(string? fieldName) where T : default { return ValidatedRead(fieldName, BuiltInType.Null, base.ReadNull, SchemaRank.Scalar); } /// protected override T? ReadNullable(string? fieldName, Func reader) where T : default { return ReadUnion(fieldName, id => { // Check the schema is a nullable union schema if (Current is not UnionSchema u || u.Count != 2 || u.Schemas[0].Tag != Schema.Type.Null) { throw new DecodingException( $"Union schema {Current.ToJson()} of nullable " + $"field {fieldName ?? "unnamed"} does not match.", Schema.ToJson()); } switch (id) { case 0: return ReadNull(null); case 1: return reader(null); default: throw new DecodingException( $"Unexpected union discriminator {id}."); } }); } /// public override Array? ReadArray(string? fieldName, int valueRank, BuiltInType builtInType, Type? systemType = null, ExpandedNodeId? encodeableTypeId = null) { var currentSchema = GetFieldSchema(null); if (!currentSchema.IsBuiltInType(out var expectedType, out var rank)) { throw new DecodingException( $"Schema {currentSchema.ToJson()} is not an array schema.", Schema.ToJson()); } if (rank != SchemaUtils.GetRank(valueRank) || builtInType != expectedType) { throw new DecodingException( $"Schema {currentSchema.ToJson()} does not match expected rank and type.", Schema.ToJson()); } var result = ReadWithSchema(currentSchema, () => base.ReadArray(fieldName, valueRank, builtInType, systemType, encodeableTypeId)); ValidatedPop(currentSchema); return result; } /// protected override Array ReadArray(string? fieldName, Func reader, Type type) { return ValidatedReadArray(() => base.ReadArray(fieldName, reader, type)); } /// public override T[] ReadArray(string? fieldName, Func reader) { return ValidatedReadArray(() => base.ReadArray(fieldName, () => reader())); } /// public override T ReadObject(string? fieldName, Func reader) { var currentSchema = GetFieldSchema(fieldName); var result = reader(currentSchema); ValidatedPop(currentSchema); return result; } /// public void Push(Schema schema) { _schema.Push(schema); } /// protected override DiagnosticInfo ReadDiagnosticInfo(string? fieldName, int depth) { return ValidatedRead(fieldName, BuiltInType.DiagnosticInfo, f => base.ReadDiagnosticInfo(f, depth)); } /// public override T ReadUnion(string? fieldName, Func reader) { // Get the union schema var currentSchema = GetFieldSchema(fieldName); if (currentSchema is not UnionSchema) { throw new DecodingException( $"Union field {fieldName ?? "unnamed"} must be a union " + $"schema but is {currentSchema.ToJson()} schema.", Schema.ToJson()); } return base.ReadUnion(fieldName, reader); } /// protected override int StartUnion() { var index = base.StartUnion(); _schema.ExpectUnionItem = u => { if (index < u.Schemas.Count && index >= 0) { return u.Schemas[index]; } throw new DecodingException( $"Union index {index} not found in union {u.ToJson()}.", Schema.ToJson()); }; return index; } /// protected override void EndUnion() { var unionSchema = _schema.Pop(); if (unionSchema is not UnionSchema) { throw new DecodingException( $"Expected union schema but got {unionSchema.ToJson()} after " + "completing union.", Schema.ToJson()); } base.EndUnion(); } /// protected override IEncodeable ReadEncodeableInExtensionObject(int unionId) { var schema = _schema.Current; // Selected through union id // Get the type id directly from the schema and load the system type var typeId = schema.GetDataTypeId(Context); if (NodeId.IsNull(typeId)) { throw new DecodingException( $"Schema {schema.ToJson()} does not reference a valid type " + "id to look up system type.", Schema.ToJson()); } var systemType = Context.Factory.GetSystemType(typeId); if (systemType == null) { throw new DecodingException( $"A system type for schema {schema} could not befound using " + $"the typeid {typeId}."); } return ReadEncodeable(null, systemType, typeId); } /// /// Perform the read of the built in type after validating the /// operation against the schema of the field if there is a field. /// /// /// /// /// /// /// /// private T ValidatedRead(string? fieldName, BuiltInType builtInType, Func value, SchemaRank valueRank = SchemaRank.Scalar) { // Get expected schema var expectedType = _builtIns.GetSchemaForBuiltInType(builtInType, valueRank); var expectedName = expectedType.Fullname; return ValidatedRead(fieldName, expectedName, value); } /// /// Validates reading a value against the schema /// /// /// /// /// /// /// /// private T ValidatedRead(string? fieldName, string expectedSchemaName, Func value, bool isFullName = true) { // Get current field schema var currentSchema = GetFieldSchema(fieldName); // Should be the same var curName = isFullName ? currentSchema.Fullname : currentSchema.Name; if (curName != expectedSchemaName) { throw new DecodingException( $"Schema {currentSchema.Fullname} is not as " + $"expected {expectedSchemaName}.", Schema.ToJson()); } // Read type per schema var result = value(fieldName); ValidatedPop(currentSchema); return result; } /// /// Validated array reader /// /// /// /// /// private T ValidatedReadArray(Func reader) { var currentSchema = GetFieldSchema(null); if (currentSchema is not ArraySchema) { throw new DecodingException( $"Reading array field but schema {currentSchema.ToJson()} is not " + "array schema.", Schema.ToJson()); } var result = reader(); ValidatedPop(currentSchema); return result; } /// /// Use specified schema by pushing it on top for reading /// /// /// /// private T ReadWithSchema(Schema schema, Func reader) { var top = schema.AsArray(); _schema.Push(top); var result = reader(); ValidatedPop(top); return result; } /// /// Validate pop from stack should be expected schema /// /// /// private void ValidatedPop(Schema expectedSchema) { // Pop array from stack var completedSchema = _schema.Pop(); if (completedSchema != expectedSchema) { throw new DecodingException( $"Failed to pop schema. Expected {expectedSchema.ToJson()} " + $"but got {completedSchema.ToJson()}.", Schema.ToJson()); } } /// /// Get next schema /// /// /// /// private Schema GetFieldSchema(string? fieldName) { _schema.ExpectedFieldName = fieldName; var current = _schema.Current; if (!_schema.TryMoveNext()) { throw new DecodingException( $"No schema for field {fieldName ?? "unnamed"} " + $"found in {current.ToJson()}.", Schema.ToJson()); } return _schema.Current; } private readonly AvroBuiltInSchemas _builtIns = new(); private readonly AvroSchemaTraverser _schema; } /// /// Schemaless avro decoder /// internal sealed class SchemalessAvroDecoder : BaseAvroDecoder { /// public SchemalessAvroDecoder(Stream stream, IServiceMessageContext context, bool leaveOpen = false) : base(stream, context, leaveOpen) { } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/AvroEncoder.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Azure.IIoT.OpcUa.Encoders.Models; using Azure.IIoT.OpcUa.Encoders.Schemas; using Azure.IIoT.OpcUa.Encoders.Schemas.Avro; using Avro; using Opc.Ua; using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Xml; /// /// Encodes objects via Avro schema using underlying encoder. /// public sealed class AvroEncoder : BaseAvroEncoder { /// /// Schema to use /// public Schema Schema { get; } /// /// Current schema /// public Schema Current => _schema.Current; /// /// Creates an encoder that writes to the stream. /// /// The stream to which the /// encoder writes. /// /// The message context to /// use for the encoding. /// If the stream should /// be left open on dispose. public AvroEncoder(Stream stream, Schema schema, IServiceMessageContext context, bool leaveOpen = true) : base(stream, context, leaveOpen) { Schema = schema; _schema = new AvroSchemaTraverser(schema); } /// public override void WriteBoolean(string? fieldName, bool value) { ValidatedWrite(fieldName, BuiltInType.Boolean, value, base.WriteBoolean); } /// public override void WriteSByte(string? fieldName, sbyte value) { ValidatedWrite(fieldName, BuiltInType.SByte, value, base.WriteSByte); } /// public override void WriteByte(string? fieldName, byte value) { ValidatedWrite(fieldName, BuiltInType.Byte, value, base.WriteByte); } /// public override void WriteInt16(string? fieldName, short value) { ValidatedWrite(fieldName, BuiltInType.Int16, value, base.WriteInt16); } /// public override void WriteUInt16(string? fieldName, ushort value) { ValidatedWrite(fieldName, BuiltInType.UInt16, value, base.WriteUInt16); } /// public override void WriteInt32(string? fieldName, int value) { ValidatedWrite(fieldName, BuiltInType.Int32, value, base.WriteInt32); } /// public override void WriteUInt32(string? fieldName, uint value) { ValidatedWrite(fieldName, BuiltInType.UInt32, value, base.WriteUInt32); } /// public override void WriteInt64(string? fieldName, long value) { ValidatedWrite(fieldName, BuiltInType.Int64, value, base.WriteInt64); } /// public override void WriteUInt64(string? fieldName, ulong value) { ValidatedWrite(fieldName, BuiltInType.UInt64, value, base.WriteUInt64); } /// public override void WriteFloat(string? fieldName, float value) { ValidatedWrite(fieldName, BuiltInType.Float, value, base.WriteFloat); } /// public override void WriteDouble(string? fieldName, double value) { ValidatedWrite(fieldName, BuiltInType.Double, value, base.WriteDouble); } /// public override void WriteString(string? fieldName, string? value) { ValidatedWrite(fieldName, BuiltInType.String, value, base.WriteString); } /// public override void WriteDateTime(string? fieldName, DateTime value) { ValidatedWrite(fieldName, BuiltInType.DateTime, value, base.WriteDateTime); } /// public override void WriteGuid(string? fieldName, Uuid value) { ValidatedWrite(fieldName, BuiltInType.Guid, value, base.WriteGuid); } /// public override void WriteGuid(string? fieldName, Guid value) { ValidatedWrite(fieldName, BuiltInType.Guid, value, base.WriteGuid); } /// public override void WriteByteString(string? fieldName, byte[]? value) { ValidatedWrite(fieldName, BuiltInType.ByteString, value, base.WriteByteString); } /// public override void WriteXmlElement(string? fieldName, XmlElement? value) { ValidatedWrite(fieldName, BuiltInType.XmlElement, value, base.WriteXmlElement); } /// public override void WriteNodeId(string? fieldName, NodeId? value) { ValidatedWrite(fieldName, BuiltInType.NodeId, value, base.WriteNodeId); } /// public override void WriteExpandedNodeId(string? fieldName, ExpandedNodeId? value) { ValidatedWrite(fieldName, BuiltInType.ExpandedNodeId, value, base.WriteExpandedNodeId); } /// public override void WriteStatusCode(string? fieldName, StatusCode value) { ValidatedWrite(fieldName, BuiltInType.StatusCode, value, base.WriteStatusCode); } /// public override void WriteQualifiedName(string? fieldName, QualifiedName? value) { ValidatedWrite(fieldName, BuiltInType.QualifiedName, value, base.WriteQualifiedName); } /// public override void WriteLocalizedText(string? fieldName, LocalizedText? value) { ValidatedWrite(fieldName, BuiltInType.LocalizedText, value, base.WriteLocalizedText); } /// public override void WriteDataValue(string? fieldName, DataValue? value) { // Get current field schema var currentSchema = GetFieldSchema(fieldName); // Should be the same if (!currentSchema.IsDataValue()) { throw new EncodingException( $"Schema {currentSchema.Fullname} is not " + $"as expected {currentSchema.ToJson()}.", Schema.ToJson()); } // Write type per schema base.WriteDataValue(fieldName, value); ValidatedPop(currentSchema); } /// public override void WriteExtensionObject(string? fieldName, ExtensionObject? value) { ValidatedWrite(fieldName, BuiltInType.ExtensionObject, value, base.WriteExtensionObject); } /// public override void WriteEncodeable(string? fieldName, IEncodeable? value, Type? systemType) { var fullName = GetFullNameOfEncodeable(value, systemType, out var typeName, out var typeId); if (typeName == null) { // Perform unvalidated write. TODO: Throw? var currentSchema = GetFieldSchema(fieldName); base.WriteEncodeable(fieldName, value, systemType); ValidatedPop(currentSchema); return; } ValidatedWrite(fieldName, fullName ?? typeName, value, (f, v) => base.WriteEncodeable(f, v, systemType), fullName != null); } /// public override void WriteVariant(string? fieldName, Variant value) { var currentSchema = GetFieldSchema(fieldName); WriteVariant(value, currentSchema); ValidatedPop(currentSchema); void WriteVariant(Variant value, Schema currentSchema) { var expectedType = _builtIns.GetSchemaForBuiltInType( BuiltInType.Variant, SchemaRank.Scalar); // Write as variant if (currentSchema.Fullname == expectedType.Fullname) { base.WriteVariant(null, value); return; } // Alternatively the schema could be nullable if (currentSchema is UnionSchema u) { WriteWithSchema(u, () => WriteNullable(null, value.Value, (_, _) => WriteVariantValueWithSchema(value, u.Schemas[1]))); return; } WriteVariantValueWithSchema(value, currentSchema); void WriteVariantValueWithSchema(Variant value, Schema currentSchema) { // Write as built in type if (currentSchema.IsBuiltInType(out var builtInType, out var rank)) { if (value.TypeInfo != null) { if (SchemaUtils.GetRank(value.TypeInfo.ValueRank) != rank) { throw new EncodingException( $"Wrong schema {currentSchema.ToJson()} " + $"of field {fieldName ?? "unnamed"} for variant has wrong " + $"rank {rank} vs. {value.TypeInfo}.", Schema.ToJson()); } if (builtInType == BuiltInType.Enumeration) // or int? { if (value.TypeInfo.BuiltInType != BuiltInType.Int32 && value.TypeInfo.BuiltInType != BuiltInType.Enumeration) { throw new EncodingException( $"Schema {currentSchema.ToJson()} " + $"of field {fieldName ?? "unnamed"} should be enumeration" + $"or int32 to support {value.TypeInfo}.", Schema.ToJson()); } } else if (value.TypeInfo.BuiltInType != builtInType) { throw new EncodingException( $"Wrong schema {currentSchema.ToJson()} " + $"of field {fieldName ?? "unnamed"} for variant of type" + $"{value.TypeInfo}.", Schema.ToJson()); } } WriteWithSchema(currentSchema, () => WriteVariantValue(value, builtInType, rank)); return; } var typeId = currentSchema.GetDataTypeId(Context); var encodeable = (value.Value as ExtensionObject)?.Body as IEncodeable; var systemType = encodeable?.GetType() ?? Context.Factory.GetSystemType(typeId); if (systemType != null) { WriteWithSchema(currentSchema, () => WriteEncodeable(null, encodeable, systemType)); return; } throw new EncodingException( $"Variant schema {currentSchema.ToJson()} of " + $"field {fieldName ?? "unnamed"} is neither variant nor built " + "in type schema.", Schema.ToJson()); } } } /// public override void WriteEnumerated(string? fieldName, Enum? value) { WriteEnumerated(fieldName, Convert.ToInt32(value, CultureInfo.InvariantCulture)); } /// public override void WriteEnumerated(string? fieldName, int value) { var currentSchema = GetFieldSchema(fieldName); WriteEnumeratedValue(fieldName, value, currentSchema); ValidatedPop(currentSchema); void WriteEnumeratedValue(string? fieldName, int value, Schema currentSchema) { if (currentSchema.IsBuiltInType(out var builtInType, out var rank) && rank == SchemaRank.Scalar && (builtInType == BuiltInType.Int32 || builtInType == BuiltInType.Enumeration)) { WriteWithSchema(currentSchema, () => base.WriteEnumerated(fieldName, value)); } else { throw new EncodingException( $"Invalid schema {currentSchema.ToJson()}. " + "Enumerated values must be enums.", Schema.ToJson()); } } } /// public override void WriteBooleanArray(string? fieldName, IList? values) { ValidatedWrite(fieldName, BuiltInType.Boolean, values, base.WriteBooleanArray, SchemaRank.Collection); } /// public override void WriteSByteArray(string? fieldName, IList? values) { ValidatedWrite(fieldName, BuiltInType.SByte, values, base.WriteSByteArray, SchemaRank.Collection); } /// public override void WriteByteArray(string? fieldName, IList? values) { ValidatedWrite(fieldName, BuiltInType.ByteString, values, base.WriteByteArray, SchemaRank.Scalar); } /// public override void WriteInt16Array(string? fieldName, IList? values) { ValidatedWrite(fieldName, BuiltInType.Int16, values, base.WriteInt16Array, SchemaRank.Collection); } /// public override void WriteUInt16Array(string? fieldName, IList? values) { ValidatedWrite(fieldName, BuiltInType.UInt16, values, base.WriteUInt16Array, SchemaRank.Collection); } /// public override void WriteInt32Array(string? fieldName, IList? values) { ValidatedWrite(fieldName, BuiltInType.Int32, values, base.WriteInt32Array, SchemaRank.Collection); } /// public override void WriteUInt32Array(string? fieldName, IList? values) { ValidatedWrite(fieldName, BuiltInType.UInt32, values, base.WriteUInt32Array, SchemaRank.Collection); } /// public override void WriteInt64Array(string? fieldName, IList? values) { ValidatedWrite(fieldName, BuiltInType.Int64, values, base.WriteInt64Array, SchemaRank.Collection); } /// public override void WriteUInt64Array(string? fieldName, IList? values) { ValidatedWrite(fieldName, BuiltInType.UInt64, values, base.WriteUInt64Array, SchemaRank.Collection); } /// public override void WriteFloatArray(string? fieldName, IList? values) { ValidatedWrite(fieldName, BuiltInType.Float, values, base.WriteFloatArray, SchemaRank.Collection); } /// public override void WriteDoubleArray(string? fieldName, IList? values) { ValidatedWrite(fieldName, BuiltInType.Double, values, base.WriteDoubleArray, SchemaRank.Collection); } /// public override void WriteStringArray(string? fieldName, IList? values) { ValidatedWrite(fieldName, BuiltInType.String, values, base.WriteStringArray, SchemaRank.Collection); } /// public override void WriteDateTimeArray(string? fieldName, IList? values) { ValidatedWrite(fieldName, BuiltInType.DateTime, values, base.WriteDateTimeArray, SchemaRank.Collection); } /// public override void WriteGuidArray(string? fieldName, IList? values) { ValidatedWrite(fieldName, BuiltInType.Guid, values, base.WriteGuidArray, SchemaRank.Collection); } /// public override void WriteGuidArray(string? fieldName, IList? values) { ValidatedWrite(fieldName, BuiltInType.Guid, values, base.WriteGuidArray, SchemaRank.Collection); } /// public override void WriteByteStringArray(string? fieldName, IList? values) { ValidatedWrite(fieldName, BuiltInType.ByteString, values, base.WriteByteStringArray, SchemaRank.Collection); } /// public override void WriteXmlElementArray(string? fieldName, IList? values) { ValidatedWrite(fieldName, BuiltInType.XmlElement, values, base.WriteXmlElementArray, SchemaRank.Collection); } /// public override void WriteNodeIdArray(string? fieldName, IList? values) { ValidatedWrite(fieldName, BuiltInType.NodeId, values, base.WriteNodeIdArray, SchemaRank.Collection); } /// public override void WriteExpandedNodeIdArray(string? fieldName, IList? values) { ValidatedWrite(fieldName, BuiltInType.ExpandedNodeId, values, base.WriteExpandedNodeIdArray, SchemaRank.Collection); } /// public override void WriteStatusCodeArray(string? fieldName, IList? values) { ValidatedWrite(fieldName, BuiltInType.StatusCode, values, base.WriteStatusCodeArray, SchemaRank.Collection); } /// public override void WriteDiagnosticInfoArray(string? fieldName, IList? values) { ValidatedWrite(fieldName, BuiltInType.DiagnosticInfo, values, base.WriteDiagnosticInfoArray, SchemaRank.Collection); } /// public override void WriteQualifiedNameArray(string? fieldName, IList? values) { ValidatedWrite(fieldName, BuiltInType.QualifiedName, values, base.WriteQualifiedNameArray, SchemaRank.Collection); } /// public override void WriteLocalizedTextArray(string? fieldName, IList? values) { ValidatedWrite(fieldName, BuiltInType.LocalizedText, values, base.WriteLocalizedTextArray, SchemaRank.Collection); } /// public override void WriteVariantArray(string? fieldName, IList? values) { var currentSchema = GetFieldSchema(fieldName); WriteVariantArray(fieldName, values, currentSchema); ValidatedPop(currentSchema); void WriteVariantArray(string? fieldName, IList? values, Schema currentSchema) { var expectedType = _builtIns.GetSchemaForBuiltInType( BuiltInType.Variant, SchemaRank.Collection); // Write as variant collection if (currentSchema.Fullname == expectedType.Fullname) { base.WriteVariantArray(fieldName, values); return; } // Write as built in type if (currentSchema.IsBuiltInType(out var builtInType, out var rank)) { // When written in concise mode we get an array of bytes as byte string if (builtInType == BuiltInType.ByteString && rank == SchemaRank.Scalar) { WriteWithSchema(currentSchema, () => WriteScalar(builtInType, values?.Select(v => v.Value).Cast().ToArray() ?? [])); return; } // // Rank should be collection, and all values to write should be // scalar and of the built in type // if (rank == SchemaRank.Collection) { WriteWithSchema(currentSchema, () => WriteArray(builtInType, values?.Select(v => v.Value).ToArray() ?? [])); return; } throw new EncodingException( $"Wrong schema {currentSchema.ToJson()} " + $"of field {fieldName ?? "unnamed"} to write variants.", Schema.ToJson()); } throw new EncodingException( $"Variant schema {currentSchema.ToJson()} of " + $"field {fieldName ?? "unnamed"} is neither variant collection " + "nor built in type collection schema.", Schema.ToJson()); } } /// public override void WriteDataValueArray(string? fieldName, IList? values) { ValidatedWrite(fieldName, BuiltInType.DataValue, values, base.WriteDataValueArray, SchemaRank.Collection); } /// public override void WriteExtensionObjectArray(string? fieldName, IList? values) { ValidatedWrite(fieldName, BuiltInType.ExtensionObject, values, base.WriteExtensionObjectArray, SchemaRank.Collection); } /// public override void WriteEnumeratedArray(string? fieldName, Array? values, Type? systemType) { var ints = values == null ? [] : Enumerable .Range(0, values.GetLength(0)) .Select(i => Convert.ToInt32((Enum?)values.GetValue(i), CultureInfo.InvariantCulture)) .ToArray(); WriteEnumeratedArray(fieldName, ints, systemType); } /// public override void WriteEnumeratedArray(string? fieldName, int[] values, Type? enumType) { var currentSchema = GetFieldSchema(fieldName); WriteEnumeratedArray(fieldName, currentSchema); ValidatedPop(currentSchema); void WriteEnumeratedArray(string? fieldName, Schema currentSchema) { if (currentSchema is ArraySchema a && a.ItemSchema is EnumSchema e) { WriteWithSchema(currentSchema, () => base.WriteEnumeratedArray(fieldName, values, enumType)); } else if (currentSchema.IsBuiltInType(out var builtInType, out var rank) && rank == SchemaRank.Collection && (builtInType == BuiltInType.Int32 || builtInType == BuiltInType.Enumeration)) { base.WriteEnumeratedArray(fieldName, values, enumType); } else { throw new EncodingException( $"Invalid schema {currentSchema.ToJson()}. " + "Enumerated values must be arrays of enums.", Schema.ToJson()); } } } /// public override void WriteDataSet(string? fieldName, DataSet dataSet) { var currentSchema = GetFieldSchema(fieldName); WriteDataSet(dataSet, currentSchema); ValidatedPop(currentSchema); void WriteDataSet(DataSet dataSet, Schema currentSchema) { if (currentSchema is not RecordSchema r) { throw new EncodingException( $"Invalid schema {currentSchema.ToJson()}. " + "Data sets must be records or maps.", Schema.ToJson()); } // Serialize the fields in the schema var lookup = dataSet.DataSetFields.ToDictionary(f => f.Name, f => f.Value); foreach (var field in r.Fields) { if (!lookup.TryGetValue(SchemaUtils.Unescape(field.Name), out var dataValue)) { dataValue = null; } WriteDataSetField(field.Name, dataValue, field.Schema); } } } /// /// Write data set field /// /// /// /// /// private void WriteDataSetField(string? fieldName, DataValue? dataValue, Schema schema) { if (schema is not UnionSchema u) { WriteVariant(fieldName, dataValue?.WrappedValue ?? default); } else if ((u.Schemas.Count > 1 && u.Schemas[1].IsDataValue()) || dataValue == null) { WriteNullable(fieldName, dataValue, (_, v) => { var currentSchema = GetFieldSchema(fieldName); WriteDataSetFieldValue(v, currentSchema); ValidatedPop(currentSchema); }); } else { WriteNullable(fieldName, dataValue.Value, (_, _) => { var currentSchema = GetFieldSchema(fieldName); WriteDataSetFieldValue(dataValue, currentSchema); ValidatedPop(currentSchema); }); } void WriteDataSetFieldValue(DataValue value, Schema currentSchema) { // The field is a record that should contain the data value fields if (currentSchema is RecordSchema fieldRecord && fieldRecord.IsDataValue()) { foreach (var dvf in fieldRecord.Fields) { switch (dvf.Name) { case nameof(value.Value): WriteVariant(nameof(value.Value), value.WrappedValue); break; case nameof(value.SourceTimestamp): WriteDateTime(nameof(value.SourceTimestamp), value.SourceTimestamp); break; case nameof(value.SourcePicoseconds): WriteUInt16(nameof(value.SourcePicoseconds), value.SourcePicoseconds); break; case nameof(value.ServerTimestamp): WriteDateTime(nameof(value.ServerTimestamp), value.ServerTimestamp); break; case nameof(value.ServerPicoseconds): WriteUInt16(nameof(value.ServerPicoseconds), value.ServerPicoseconds); break; case nameof(value.StatusCode): WriteStatusCode(nameof(value.StatusCode), value.StatusCode); break; default: throw new EncodingException( $"Unknown field {dvf.Name} in dataset field."); } } return; } // Write value as variant WriteWithSchema(currentSchema, () => WriteVariant(null, value.WrappedValue)); } } /// public override void WriteObject(string? fieldName, string? typeName, Action writer) { var currentSchema = GetFieldSchema(fieldName); if (currentSchema is not RecordSchema r) { throw new EncodingException( "Objects must be records or maps.", Schema.ToJson()); } if (typeName != null && r.Name != typeName) { throw new EncodingException( $"Object has type {r.Name} but expected {typeName}.", Schema.ToJson()); } base.WriteObject(fieldName, typeName, writer); ValidatedPop(currentSchema); } /// protected override void WriteDiagnosticInfo(string? fieldName, DiagnosticInfo value, int depth) { ValidatedWrite(fieldName, BuiltInType.DiagnosticInfo, value, (f, v) => base.WriteDiagnosticInfo(f, v, depth)); } /// protected override void WriteEncodedDataType(string? fieldName, ExtensionObject value) { ValidatedWrite(fieldName, SchemaUtils.NamespaceZeroName + ".EncodedDataType", value, base.WriteEncodedDataType); } /// public override void WriteArray(string? fieldName, object array, int valueRank, BuiltInType builtInType) { var currentSchema = GetFieldSchema(null); if (!currentSchema.IsBuiltInType(out var expectedType, out var rank)) { throw new EncodingException( $"Schema {currentSchema.ToJson()} is not an array schema.", Schema.ToJson()); } if (rank != SchemaUtils.GetRank(valueRank) || builtInType != expectedType) { throw new EncodingException( $"Schema {currentSchema.ToJson()} does not match expected rank and type.", Schema.ToJson()); } base.WriteArray(fieldName, array, valueRank, builtInType); ValidatedPop(currentSchema); } /// public override void WriteArray(string? fieldName, IList? values, Action writer, string? typeName = null) { ValidatedWriteArray( () => base.WriteArray(fieldName, values, writer, typeName)); } /// protected override void WriteArray(string? fieldName, Array? values, Action writer) { ValidatedWriteArray( () => base.WriteArray(fieldName, values, writer)); } /// public override void WriteNull(string? fieldName, T? value) where T : default { ValidatedWrite(fieldName, BuiltInType.Null, value, base.WriteNull, SchemaRank.Scalar); } /// protected override void WriteNull(BuiltInType builtInType, SchemaRank valueRank) { var currentSchema = GetFieldSchema(null); // Should be the same if (currentSchema.Tag != Schema.Type.Null && (!currentSchema.IsBuiltInType(out _, out var rank) || rank != valueRank)) { throw new EncodingException( $"Schema {currentSchema.Fullname} is not expected variant null type.", Schema.ToJson()); } base.WriteNull(builtInType, valueRank); ValidatedPop(currentSchema); } /// protected override void WriteNullable(string? fieldName, T? value, Action writer) where T : class { base.WriteNullable(fieldName, value, (f, v) => { // Check the schema is a nullable union schema if (Current is not UnionSchema u || u.Count != 2 || u.Schemas[0].Tag != Schema.Type.Null) { throw new EncodingException( $"Union schema {Current.ToJson()} of nullable " + $"field {fieldName ?? "unnamed"} does not match.", Schema.ToJson()); } writer(f, v); }); } /// public override void WriteUnion(string? fieldName, int index, Action writer) { // Get the union schema var currentSchema = GetFieldSchema(fieldName); if (currentSchema is not UnionSchema) { throw new EncodingException( $"Union field {fieldName ?? "unnamed"} must be a union " + $"schema but is {currentSchema.ToJson()} schema.", Schema.ToJson()); } base.WriteUnion(fieldName, index, writer); } /// protected override void StartUnion(int index) { base.StartUnion(index); _schema.ExpectUnionItem = u => { if (index < u.Schemas.Count && index >= 0) { return u.Schemas[index]; } throw new EncodingException( $"Union index {index} not found in union {u.ToJson()}.", Schema.ToJson()); }; } /// protected override void EndUnion() { var unionSchema = _schema.Pop(); if (unionSchema is not UnionSchema) { throw new EncodingException( $"Expected union schema but got {unionSchema.ToJson()} after " + "completing union.", Schema.ToJson()); } base.EndUnion(); } /// /// Perform the read of the built in type after validating the /// operation against the schema of the field if there is a field. /// /// /// /// /// /// /// /// /// private void ValidatedWrite(string? fieldName, BuiltInType builtInType, T value, Action writer, SchemaRank valueRank = SchemaRank.Scalar) { // Get expected schema var expectedType = _builtIns.GetSchemaForBuiltInType(builtInType, valueRank); var expectedName = expectedType.Fullname; ValidatedWrite(fieldName, expectedName, value, writer); } /// /// Validates reading a value against the schema /// /// /// /// /// /// /// /// /// private void ValidatedWrite(string? fieldName, string expectedSchemaName, T value, Action writer, bool isFullName = true) { // Get current field schema var currentSchema = GetFieldSchema(fieldName); // Should be the same var curName = isFullName ? currentSchema.Fullname : currentSchema.Name; if (curName != expectedSchemaName) { throw new EncodingException( $"Schema {currentSchema.Fullname} is not as " + $"expected {expectedSchemaName}.", Schema.ToJson()); } // Write type per schema writer(fieldName, value); ValidatedPop(currentSchema); } /// /// Validated array writer /// /// /// /// private void ValidatedWriteArray(Action writer) { var currentSchema = GetFieldSchema(null); if (currentSchema is not ArraySchema) { throw new EncodingException( $"Writing array field but schema {currentSchema.ToJson()} is not " + "array schema.", Schema.ToJson()); } writer(); ValidatedPop(currentSchema); } /// /// Use specified schema by pushing it on top for writing /// /// /// private void WriteWithSchema(Schema schema, Action writer) { var top = schema.AsArray(); _schema.Push(top); writer(); ValidatedPop(top); } /// /// Validate pop from stack should be expected schema /// /// /// private void ValidatedPop(Schema expectedSchema) { // Pop array from stack var completedSchema = _schema.Pop(); if (completedSchema != expectedSchema) { throw new EncodingException( $"Failed to pop schema. Expected {expectedSchema.ToJson()} " + $"but got {completedSchema.ToJson()}.", Schema.ToJson()); } } /// /// Get next schema /// /// /// /// private Schema GetFieldSchema(string? fieldName) { _schema.ExpectedFieldName = fieldName; var current = _schema.Current; if (!_schema.TryMoveNext()) { throw new EncodingException( $"No schema for field {fieldName ?? "unnamed"} " + $"found in {current.ToJson()}.", Schema.ToJson()); } return _schema.Current; } private readonly AvroBuiltInSchemas _builtIns = new(); private readonly AvroSchemaTraverser _schema; } /// /// Schemaless encoder /// internal sealed class SchemalessAvroEncoder : BaseAvroEncoder { /// public SchemalessAvroEncoder(Stream stream, IServiceMessageContext context, bool leaveOpen = true) : base(stream, context, leaveOpen) { } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/AvroFileReader.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Avro; using Avro.File; using Avro.IO; using System; using System.Collections.Generic; using System.IO; using System.Linq; /// /// Read avro files /// public sealed class AvroFileReader : IDisposable { /// /// Read avro file /// /// public AvroFileReader(string fileName) { if (!fileName.EndsWith(".avro", StringComparison.InvariantCulture)) { fileName += ".avro"; } _leaveOpen = false; fileName = fileName.SanitizeFileName(); _stream = new FileStream(fileName, FileMode.Open); try { _decoder = new BinaryDecoder(_stream); _codec = ReadHeader(); } catch { _stream.Dispose(); throw; } } /// /// Read from stream /// /// public AvroFileReader(Stream stream) { _leaveOpen = true; _stream = stream; try { _decoder = new BinaryDecoder(_stream); _codec = ReadHeader(); } catch { _stream.Dispose(); throw; } } /// public IEnumerable Stream(Func reader) { while (HasMore()) { yield return Read(reader); } } /// public T Read(Func reader) { if (!HasMore() || _currentBlockStream == null) { throw new EndOfStreamException("No more objects remaining!"); } var result = reader(_header.Schema, _currentBlockStream); _blockRemaining--; if (_blockRemaining == 0) { _currentBlockStream.Dispose(); _currentBlockStream = null; } return result; } /// public bool HasMore() { return _blockRemaining != 0 || TryMoveToNextBlock(); } /// public void Dispose() { _currentBlockStream?.Dispose(); if (!_leaveOpen) { _stream.Dispose(); } } /// /// Try moving to next block /// /// /// private bool TryMoveToNextBlock() { // check to ensure still data to read var currentPosition = _stream.Position; if (_stream.ReadByte() == -1) { return false; } _stream.Position = currentPosition; // read block count _blockRemaining = _decoder.ReadLong(); // read block size _blockSize = _decoder.ReadLong(); if (_blockSize > int.MaxValue || _blockSize < 0) { throw new FormatException( $"Block size {_blockSize} invalid or too large."); } // Read and decompress block var buffer = new byte[_blockSize]; _decoder.ReadFixed(buffer, 0, buffer.Length); _currentBlockStream = AvroFileWriter.Streams.GetStream( _codec.Decompress(buffer, (int)_blockSize)); // Read sync marker var marker = new byte[16]; _decoder.ReadFixed(marker); if (!marker.SequenceEqual(_header.SyncData)) { throw new FormatException("Invalid sync marker found!"); } return true; } /// /// Read header /// /// private Codec ReadHeader() { ReadMagicBytes(); ReadMetaData(); _decoder.ReadFixed(_header.SyncData); var schema = GetString(_header, DataFileConstants.MetaDataSchema); _header.Schema = Schema.Parse(schema); var codec = GetString(_header, DataFileConstants.MetaDataCodec); return codec == null ? Codec.CreateCodec(Codec.Type.Null) : Codec.CreateCodecFromString(codec); } /// /// Read magic /// /// private void ReadMagicBytes() { var firstBytes = new byte[DataFileConstants.Magic.Length]; try { _decoder.ReadFixed(firstBytes); } catch (Exception e) { throw new FormatException("Not a valid data file!", e); } if (!firstBytes.SequenceEqual(DataFileConstants.Magic)) { throw new FormatException("Not a valid data file!"); } } /// /// Read metadata /// private void ReadMetaData() { // read meta data var len = _decoder.ReadMapStart(); if (len > 0) { do { for (long i = 0; i < len; i++) { var key = _decoder.ReadString(); var val = _decoder.ReadBytes(); _header.MetaData.Add(key, val); } } while ((len = _decoder.ReadMapNext()) != 0); } } /// private static string? GetString(Header header, string key) { if (!header.MetaData.TryGetValue(key, out var value)) { return null; } return System.Text.Encoding.UTF8.GetString(value); } private readonly Codec _codec; private readonly bool _leaveOpen; private readonly Stream _stream; private readonly Header _header = new(); private Stream? _currentBlockStream; private long _blockRemaining; private long _blockSize; private readonly BinaryDecoder _decoder; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/AvroFileWriter.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Avro.File; using Avro.IO; using Furly.Extensions.Messaging; using Furly.Extensions.Storage; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.IO; using System; using System.Buffers; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; /// /// Write avro files /// public sealed class AvroFileWriter : IFileWriter, IDisposable { /// /// Memory manager /// internal static RecyclableMemoryStreamManager Streams { get; } = new(); /// public bool SupportsContentType(string contentType) { if (_options.Value.Disabled) { return false; } return contentType.Equals(ContentType.Avro, StringComparison.OrdinalIgnoreCase) || contentType.Equals(ContentType.AvroGzip, StringComparison.OrdinalIgnoreCase); } /// /// Create writer /// /// /// public AvroFileWriter(IOptions options, ILogger logger) { _options = options; _logger = logger; } /// public ValueTask WriteAsync(string fileName, DateTimeOffset timestamp, IEnumerable> buffers, IReadOnlyDictionary? metadata, IEventSchema? schema, string contentType, CancellationToken ct = default) { if (schema?.Id != null) { fileName = fileName.SanitizeFileName(); var file = _files.GetOrAdd(fileName + schema.Id + contentType, _ => AvroFile.Create(fileName, schema.Schema, metadata, _logger, contentType.Equals(ContentType.AvroGzip, StringComparison.OrdinalIgnoreCase))); file.Write(buffers); } return ValueTask.CompletedTask; } /// public void Dispose() { foreach (var file in _files.Values) { file.Dispose(); } } /// /// The avro file being written /// internal sealed class AvroFile : IDisposable { /// /// Create avro file /// /// /// /// /// /// /// /// private AvroFile(string fileName, Stream stream, string schema, IReadOnlyDictionary? metadata, ILogger logger, bool leaveOpen, bool isGzip) { _logger = logger; _leaveOpen = leaveOpen; _isGzip = isGzip; _codec = Codec.CreateCodec(Codec.Type.Deflate); _fileName = fileName; _stream = stream; _encoder = new BinaryEncoder(_stream); _blockStream = Streams.GetStream(); _compressedBlockStream = Streams.GetStream(); _syncMarker = new byte[16]; #pragma warning disable CA5394 // Do not use insecure randomness Random.Shared.NextBytes(_syncMarker); #pragma warning restore CA5394 // Do not use insecure randomness // Write header _encoder.WriteFixed(DataFileConstants.Magic); WriteMetaData(schema, metadata? .Where(kv => !IsReservedMeta(kv.Key) && kv.Value != null) .ToDictionary(kv => kv.Key, kv => Encoding.UTF8.GetBytes(kv.Value!))); _encoder.WriteFixed(_syncMarker); } /// /// Create file from file name /// /// /// /// /// /// /// public static AvroFile Create(string fileName, string schema, IReadOnlyDictionary? metadata, ILogger logger, bool isGzip = false) { fileName = fileName.ReplaceLineEndings(); var fs = new FileStream(fileName + ".avro", FileMode.OpenOrCreate); return new AvroFile(fileName, fs, schema, metadata, logger, false, isGzip); } /// /// Create file from stream /// /// /// /// /// /// /// public static AvroFile CreateFromStream(Stream stream, string schema, IReadOnlyDictionary? metadata, ILogger logger, bool isGzip = false) { return new AvroFile(string.Empty, stream, schema, metadata, logger, true, isGzip); } /// /// Write to file /// /// /// public void Write(IEnumerable> buffers) { foreach (var buffer in buffers) { foreach (var memory in _isGzip ? buffer.GzipDecompress() : buffer) { _blockStream.Write(memory.Span); } _blockCount++; if (_blockStream.Position >= kBlockSize) { WriteBlocks(); } } } /// public void Dispose() { WriteBlocks(); _stream.Flush(); _blockStream.Dispose(); _compressedBlockStream.Dispose(); if (!_leaveOpen) { _stream.Dispose(); } } /// /// Writes the blocks. /// private void WriteBlocks() { if (_blockCount <= 0) { return; } // write count _encoder.WriteLong(_blockCount); // write data _codec.Compress(_blockStream, _compressedBlockStream); _encoder.WriteBytes(_compressedBlockStream.GetBuffer(), 0, (int)_compressedBlockStream.Length); // write sync marker _encoder.WriteFixed(_syncMarker); _encoder.Flush(); _logger.BlocksWritten(_blockCount, _compressedBlockStream.Length, _fileName); // reset / re-init block _blockCount = 0; _blockStream.SetLength(0); } /// /// Writes the meta data. /// /// /// private void WriteMetaData(string schema, Dictionary? metadata) { metadata ??= []; metadata.Add(DataFileConstants.MetaDataCodec, Encoding.UTF8.GetBytes(_codec.GetName())); metadata.Add(DataFileConstants.MetaDataSchema, Encoding.UTF8.GetBytes(schema)); // write metadata var size = metadata.Count; _encoder.WriteMapStart(); _encoder.SetItemCount(size); foreach (var metaPair in metadata) { _encoder.WriteString(metaPair.Key); _encoder.WriteBytes(metaPair.Value); } _encoder.WriteMapEnd(); } /// private static bool IsReservedMeta(string key) { return key.StartsWith( DataFileConstants.MetaDataReserved, StringComparison.Ordinal); } private int _blockCount; private readonly Codec _codec; private readonly string _fileName; private readonly Stream _stream; private readonly MemoryStream _blockStream; private readonly MemoryStream _compressedBlockStream; private readonly byte[] _syncMarker; private readonly BinaryEncoder _encoder; private readonly ILogger _logger; private readonly bool _leaveOpen; private readonly bool _isGzip; } private const int kBlockSize = 16000; private readonly ConcurrentDictionary _files = new(); private readonly IOptions _options; private readonly ILogger _logger; } /// /// Source-generated logging definitions for AvroFileWriter /// internal static partial class AvroFileWriterLogging { private const int EventClass = 0; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Information, Message = "{BlockCount} blocks ({Size} bytes) written to {FileName}...")] public static partial void BlocksWritten(this ILogger logger, int blockCount, long size, string fileName); } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/AvroFileWriterOptions.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { /// /// Options /// public sealed class AvroFileWriterOptions { /// /// Do not write avro files /// public bool Disabled { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/AvroSchemaBuilder.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Azure.IIoT.OpcUa.Encoders.Models; using Azure.IIoT.OpcUa.Encoders.Schemas; using Azure.IIoT.OpcUa.Encoders.Schemas.Avro; using Azure.IIoT.OpcUa.Publisher.Models; using Avro; using Opc.Ua; using Opc.Ua.Extensions; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.Serialization; using System.Xml; /// /// Encodes objects and inline builds the schema from it /// This type exists mainly for testing. /// public sealed class AvroSchemaBuilder : BaseAvroEncoder { /// /// Schema to use /// public Schema Schema => _schemas.Peek().Unwrap(); /// /// Creates an encoder that writes to the stream. /// /// The stream to which the encoder writes. /// /// The message context to use for the /// encoding. /// If the stream should be left open on /// dispose. /// If the builder should avoid /// creating large union schemas public AvroSchemaBuilder(Stream stream, IServiceMessageContext context, bool leaveOpen = true, bool emitConciseSchemas = false) : base(stream, context, leaveOpen) { _emitConciseSchemas = emitConciseSchemas; } /// public override void WriteBoolean(string? fieldName, bool value) { using var _ = Add(fieldName, BuiltInType.Boolean); base.WriteBoolean(fieldName, value); } /// public override void WriteSByte(string? fieldName, sbyte value) { using var _ = Add(fieldName, BuiltInType.SByte); base.WriteSByte(fieldName, value); } /// public override void WriteByte(string? fieldName, byte value) { using var _ = Add(fieldName, BuiltInType.Byte); base.WriteByte(fieldName, value); } /// public override void WriteInt16(string? fieldName, short value) { using var _ = Add(fieldName, BuiltInType.Int16); base.WriteInt16(fieldName, value); } /// public override void WriteUInt16(string? fieldName, ushort value) { using var _ = Add(fieldName, BuiltInType.UInt16); base.WriteUInt16(fieldName, value); } /// public override void WriteInt32(string? fieldName, int value) { using var _ = Add(fieldName, BuiltInType.Int32); base.WriteInt32(fieldName, value); } /// public override void WriteUInt32(string? fieldName, uint value) { using var _ = Add(fieldName, BuiltInType.UInt32); base.WriteUInt32(fieldName, value); } /// public override void WriteInt64(string? fieldName, long value) { using var _ = Add(fieldName, BuiltInType.Int64); base.WriteInt64(fieldName, value); } /// public override void WriteUInt64(string? fieldName, ulong value) { using var _ = Add(fieldName, BuiltInType.UInt64); base.WriteUInt64(fieldName, value); } /// public override void WriteFloat(string? fieldName, float value) { using var _ = Add(fieldName, BuiltInType.Float); base.WriteFloat(fieldName, value); } /// public override void WriteDouble(string? fieldName, double value) { using var _ = Add(fieldName, BuiltInType.Double); base.WriteDouble(fieldName, value); } /// public override void WriteString(string? fieldName, string? value) { using var _ = Add(fieldName, BuiltInType.String); base.WriteString(fieldName, value); } /// public override void WriteDateTime(string? fieldName, DateTime value) { using var _ = Add(fieldName, BuiltInType.DateTime); base.WriteDateTime(fieldName, value); } /// public override void WriteGuid(string? fieldName, Uuid value) { using var _ = Add(fieldName, BuiltInType.Guid); base.WriteGuid(fieldName, value); } /// public override void WriteGuid(string? fieldName, Guid value) { using var _ = Add(fieldName, BuiltInType.Guid); base.WriteGuid(fieldName, value); } /// public override void WriteByteString(string? fieldName, byte[]? value) { using var _ = Add(fieldName, BuiltInType.ByteString); base.WriteByteString(fieldName, value); } /// public override void WriteXmlElement(string? fieldName, XmlElement? value) { using var _ = Add(fieldName, BuiltInType.XmlElement); base.WriteXmlElement(fieldName, value); } /// public override void WriteNodeId(string? fieldName, NodeId? value) { using var _ = Add(fieldName, BuiltInType.NodeId); base.WriteNodeId(fieldName, value); } /// public override void WriteExpandedNodeId(string? fieldName, ExpandedNodeId? value) { using var _ = Add(fieldName, BuiltInType.ExpandedNodeId); base.WriteExpandedNodeId(fieldName, value); } /// public override void WriteStatusCode(string? fieldName, StatusCode value) { using var _ = Add(fieldName, BuiltInType.StatusCode); base.WriteStatusCode(fieldName, value); } /// public override void WriteDiagnosticInfo(string? fieldName, DiagnosticInfo? value) { using var _ = Add(fieldName, BuiltInType.DiagnosticInfo); base.WriteDiagnosticInfo(fieldName, value); } /// public override void WriteQualifiedName(string? fieldName, QualifiedName? value) { using var _ = Add(fieldName, BuiltInType.QualifiedName); base.WriteQualifiedName(fieldName, value); } /// public override void WriteLocalizedText(string? fieldName, LocalizedText? value) { using var _ = Add(fieldName, BuiltInType.LocalizedText); base.WriteLocalizedText(fieldName, value); } /// public override void WriteVariant(string? fieldName, Variant value) { if (_emitConciseSchemas && value != Variant.Null && !_skipInnerSchemas) { if (value.Value is ExtensionObject eo && eo.Body is IEncodeable e) { WriteEncodeable(fieldName, e, e.GetType()); return; } var rank = SchemaUtils.GetRank(value.TypeInfo.ValueRank); using var __ = Add(fieldName, value.TypeInfo.BuiltInType, SchemaUtils.GetRank(value.TypeInfo.ValueRank)); WriteVariantValue(value, value.TypeInfo.BuiltInType, rank); return; } using var _ = Add(fieldName, BuiltInType.Variant); base.WriteVariant(fieldName, value); } /// public override void WriteDataValue(string? fieldName, DataValue? value) { if (_emitConciseSchemas && value != null && value.WrappedValue != Variant.Null) { using var __ = Record(fieldName, value.WrappedValue.TypeInfo.BuiltInType + "DataValue"); base.WriteDataValue(fieldName, value); return; } using var _ = Add(fieldName, BuiltInType.DataValue); base.WriteDataValue(fieldName, value); } /// public override void WriteExtensionObject(string? fieldName, ExtensionObject? value) { using var _ = Add(fieldName, BuiltInType.ExtensionObject); base.WriteExtensionObject(fieldName, value); } /// public override void WriteEncodeable(string? fieldName, IEncodeable? value, Type? systemType) { var fullName = GetFullNameOfEncodeable(value, systemType, out var typeName, out var typeId); if (typeName == null) { throw new EncodingException( "Failed to encode a encodeable without system type"); } using var _ = Record(fieldName, fullName ?? typeName, typeId: typeId); base.WriteEncodeable(fieldName, value, systemType); } /// public override void WriteObject(string? fieldName, string? typeName, Action writer) { using var _ = Record(fieldName, typeName ?? fieldName ?? "unknown"); base.WriteObject(fieldName, typeName, writer); } /// public override void WriteEnumerated(string? fieldName, Enum? value) { using var _ = value == null ? Add(fieldName, BuiltInType.Enumeration) : Enumeration(fieldName, value.GetType()); base.WriteEnumerated(fieldName, value); } /// public override void WriteEnumerated(string? fieldName, int value) { using var _ = Add(fieldName, BuiltInType.Enumeration); base.WriteEnumerated(fieldName, value); } /// public override void WriteBooleanArray(string? fieldName, IList? values) { using var _ = Add(fieldName, BuiltInType.Boolean, SchemaRank.Collection); base.WriteBooleanArray(fieldName, values); } /// public override void WriteSByteArray(string? fieldName, IList? values) { using var _ = Add(fieldName, BuiltInType.SByte, SchemaRank.Collection); base.WriteSByteArray(fieldName, values); } /// public override void WriteByteArray(string? fieldName, IList? values) { using var _ = Add(fieldName, BuiltInType.ByteString, SchemaRank.Scalar); base.WriteByteArray(fieldName, values); } /// public override void WriteInt16Array(string? fieldName, IList? values) { using var _ = Add(fieldName, BuiltInType.Int16, SchemaRank.Collection); base.WriteInt16Array(fieldName, values); } /// public override void WriteUInt16Array(string? fieldName, IList? values) { using var _ = Add(fieldName, BuiltInType.UInt16, SchemaRank.Collection); base.WriteUInt16Array(fieldName, values); } /// public override void WriteInt32Array(string? fieldName, IList? values) { using var _ = Add(fieldName, BuiltInType.Int32, SchemaRank.Collection); base.WriteInt32Array(fieldName, values); } /// public override void WriteUInt32Array(string? fieldName, IList? values) { using var _ = Add(fieldName, BuiltInType.UInt32, SchemaRank.Collection); base.WriteUInt32Array(fieldName, values); } /// public override void WriteInt64Array(string? fieldName, IList? values) { using var _ = Add(fieldName, BuiltInType.Int64, SchemaRank.Collection); base.WriteInt64Array(fieldName, values); } /// public override void WriteUInt64Array(string? fieldName, IList? values) { using var _ = Add(fieldName, BuiltInType.UInt64, SchemaRank.Collection); base.WriteUInt64Array(fieldName, values); } /// public override void WriteFloatArray(string? fieldName, IList? values) { using var _ = Add(fieldName, BuiltInType.Float, SchemaRank.Collection); base.WriteFloatArray(fieldName, values); } /// public override void WriteDoubleArray(string? fieldName, IList? values) { using var _ = Add(fieldName, BuiltInType.Double, SchemaRank.Collection); base.WriteDoubleArray(fieldName, values); } /// public override void WriteStringArray(string? fieldName, IList? values) { using var _ = Add(fieldName, BuiltInType.String, SchemaRank.Collection); base.WriteStringArray(fieldName, values); } /// public override void WriteDateTimeArray(string? fieldName, IList? values) { using var _ = Add(fieldName, BuiltInType.DateTime, SchemaRank.Collection); base.WriteDateTimeArray(fieldName, values); } /// public override void WriteGuidArray(string? fieldName, IList? values) { using var _ = Add(fieldName, BuiltInType.Guid, SchemaRank.Collection); base.WriteGuidArray(fieldName, values); } /// public override void WriteGuidArray(string? fieldName, IList? values) { using var _ = Add(fieldName, BuiltInType.Guid, SchemaRank.Collection); base.WriteGuidArray(fieldName, values); } /// public override void WriteByteStringArray(string? fieldName, IList? values) { using var _ = Add(fieldName, BuiltInType.ByteString, SchemaRank.Collection); base.WriteByteStringArray(fieldName, values); } /// public override void WriteXmlElementArray(string? fieldName, IList? values) { using var _ = Add(fieldName, BuiltInType.XmlElement, SchemaRank.Collection); base.WriteXmlElementArray(fieldName, values); } /// public override void WriteNodeIdArray(string? fieldName, IList? values) { using var _ = Add(fieldName, BuiltInType.NodeId, SchemaRank.Collection); base.WriteNodeIdArray(fieldName, values); } /// public override void WriteExpandedNodeIdArray(string? fieldName, IList? values) { using var _ = Add(fieldName, BuiltInType.ExpandedNodeId, SchemaRank.Collection); base.WriteExpandedNodeIdArray(fieldName, values); } /// public override void WriteStatusCodeArray(string? fieldName, IList? values) { using var _ = Add(fieldName, BuiltInType.StatusCode, SchemaRank.Collection); base.WriteStatusCodeArray(fieldName, values); } /// public override void WriteDiagnosticInfoArray(string? fieldName, IList? values) { using var _ = Add(fieldName, BuiltInType.DiagnosticInfo, SchemaRank.Collection); base.WriteDiagnosticInfoArray(fieldName, values); } /// public override void WriteQualifiedNameArray(string? fieldName, IList? values) { using var _ = Add(fieldName, BuiltInType.QualifiedName, SchemaRank.Collection); base.WriteQualifiedNameArray(fieldName, values); } /// public override void WriteLocalizedTextArray(string? fieldName, IList? values) { using var _ = Add(fieldName, BuiltInType.LocalizedText, SchemaRank.Collection); base.WriteLocalizedTextArray(fieldName, values); } /// public override void WriteVariantArray(string? fieldName, IList? values) { if (_emitConciseSchemas && values?.Count > 0 && !_skipInnerSchemas) { var typeInfo = values[0].TypeInfo; if (typeInfo.ValueRank == ValueRanks.Scalar && values.All(v => typeInfo.Equals(v.TypeInfo))) { WriteArray(typeInfo.BuiltInType, values.Select(v => v.Value).ToArray()); return; } } using var _ = Add(fieldName, BuiltInType.Variant, SchemaRank.Collection); base.WriteVariantArray(fieldName, values); } /// public override void WriteDataValueArray(string? fieldName, IList? values) { using var _ = Add(fieldName, BuiltInType.DataValue, SchemaRank.Collection); base.WriteDataValueArray(fieldName, values); } /// public override void WriteExtensionObjectArray(string? fieldName, IList? values) { using var _ = Add(fieldName, BuiltInType.ExtensionObject, SchemaRank.Collection); base.WriteExtensionObjectArray(fieldName, values); } /// public override void WriteEncodeableArray(string? fieldName, IList? values, Type? systemType) { base.WriteEncodeableArray(fieldName, values, systemType); } /// public override void WriteEnumeratedArray(string? fieldName, Array? values, Type? systemType) { var enumType = values?.GetType().GetElementType() ?? systemType; using var _ = enumType == null ? Add(fieldName, BuiltInType.Enumeration, SchemaRank.Collection) : Enumeration(fieldName, enumType, SchemaRank.Collection); base.WriteEnumeratedArray(fieldName, values, systemType); } /// public override void WriteEnumeratedArray(string? fieldName, int[] values, Type? enumType) { using var _ = Add(fieldName, BuiltInType.Enumeration, SchemaRank.Collection); base.WriteEnumeratedArray(fieldName, values, enumType); } /// public override void WriteArray(string? fieldName, object array, int valueRank, BuiltInType builtInType) { using var _ = Add(fieldName, builtInType, SchemaUtils.GetRank(valueRank)); base.WriteArray(fieldName, array, valueRank, builtInType); } /// public override void WriteDataSet(string? fieldName, DataSet dataSet) { using var _ = Record(fieldName, fieldName + nameof(DataSet)); base.WriteDataSet(fieldName, dataSet); } /// public override void WriteArray(string? fieldName, IList? values, Action writer, string? typeName = null) { using var _ = Array(fieldName); base.WriteArray(fieldName, values, writer); } /// protected override void WriteNullable(string? fieldName, T? value, Action writer) where T : class { using var _ = Union(fieldName, true); base.WriteNullable(fieldName, value, writer); if (value == null) { // // We need to add the type to the schema even in case of // null value. // Try to be generic enough, but this will not work for // everything at this point. Need to update if tests fail. // Today we use this for DiagnosticInfo and DataValue // SchemaRank rank; var type = typeof(T); if (typeof(T).IsArray) { rank = SchemaRank.Collection; type = type.GetElementType(); } else { rank = SchemaRank.Scalar; } var builtInType = Enum.Parse(type!.Name); using var __ = Add(fieldName, builtInType, rank); } } /// /// Add field /// /// /// /// /// private IDisposable Add(string? fieldName, BuiltInType builtInType, SchemaRank valueRanks = SchemaRank.Scalar) { if (_skipInnerSchemas) { return Nothing.ToDo; } _skipInnerSchemas = true; var schema = _builtIns.GetSchemaForBuiltInType(builtInType, valueRanks); if (!_schemas.TryPeek(out var top)) { _schemas.Push(schema.CreateRoot(fieldName)); } else if (top is ArraySchema arr) { arr.ItemSchema = schema; } else if (top is UnionSchema u) { u.Schemas.Add(schema); } else if (top is RecordSchema r) { r.Fields.Add(new Field(schema, fieldName ?? kDefaultFieldName, r.Fields.Count)); } else { throw new EncodingException("No record schema to push to", Schema.ToJson()); } return new Skip(this); } /// /// Push enum schema /// /// /// /// /// private IDisposable Enumeration(string? fieldName, Type enumType, SchemaRank rank = SchemaRank.Scalar) { if (_skipInnerSchemas) { return Nothing.ToDo; } // Get enum types from DataMemberAttribute var names = enumType.GetProperties() .Select(p => p.GetCustomAttribute()!) .Where(a => a?.Name != null) .OrderBy(a => a.Order) .Select(a => a.Name!) .ToArray(); if (names.Length == 0) { names = Enum.GetNames(enumType); } Schema schema = EnumSchema.Create(enumType.Name, names); if (rank == SchemaRank.Collection) { schema = schema.AsArray(); } return PushSchema(fieldName, schema); } /// /// Push a new record schema as field /// /// /// /// /// private IDisposable Record(string? fieldName, string typeName, ExpandedNodeId? typeId = null) { if (_skipInnerSchemas) { return Nothing.ToDo; } var schema = RecordSchema.Create(typeName, [], customProperties: AvroSchema.Properties( typeId?.AsString(Context, NamespaceFormat.Uri))); return PushSchema(fieldName, schema); } /// /// Push a new array schema as field /// /// /// private IDisposable Array(string? fieldName) { if (_skipInnerSchemas) { return Nothing.ToDo; } return PushSchema(fieldName, AvroSchema.CreatePlaceHolder("Dummy", "").AsArray( )); } /// /// Push a union /// /// /// /// private IDisposable Union(string? fieldName, bool nullable = false) { if (_skipInnerSchemas) { return Nothing.ToDo; } var schema = UnionSchema.Create([]); if (nullable) { schema.Schemas.Add(AvroSchema.Null); } return PushSchema(fieldName, schema); } /// /// Push schema /// /// /// /// /// private Pop PushSchema(string? fieldName, Schema schema) { if (!_schemas.TryPeek(out var top)) { _schemas.Push(schema.CreateRoot(fieldName)); } else if (top is ArraySchema arr) { arr.ItemSchema = schema; } else if (top is UnionSchema u) { u.Schemas.Add(schema); } else if (top is RecordSchema r) { r.Fields.Add(new Field(schema, fieldName ?? kDefaultFieldName, r.Fields.Count)); } else { throw new EncodingException("No record schema to push to.", Schema.ToJson()); } _schemas.Push(schema); return new Pop(this); } private sealed record Pop(AvroSchemaBuilder Outer) : IDisposable { public void Dispose() { Outer._schemas.Pop(); } } private sealed record Skip(AvroSchemaBuilder Outer) : IDisposable { public void Dispose() { Outer._skipInnerSchemas = false; } } private sealed class Nothing : IDisposable { public static readonly Nothing ToDo = new(); public void Dispose() { } } private readonly Stack _schemas = new(); private readonly AvroBuiltInSchemas _builtIns = new(); private readonly bool _emitConciseSchemas; private bool _skipInnerSchemas; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/AvroSchemaTraverser.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Azure.IIoT.OpcUa.Encoders.Schemas; using Azure.IIoT.OpcUa.Encoders.Schemas.Avro; using Avro; using System; using System.Collections.Generic; using System.Diagnostics; /// /// Allows a encoder or decoder to follow the schema /// internal sealed class AvroSchemaTraverser { /// /// Current schema /// public Schema Current => _schemas.Peek().Schema; /// /// Set Expected field name /// public string? ExpectedFieldName { get; set; } /// /// Set union selector /// public Func? ExpectUnionItem { get; set; } /// /// Create traversal /// /// public AvroSchemaTraverser(Schema schema) { // // We need to push a root schema to start traversal // Either this is already a root schema for example // if the value was not a record or a record on a // field or we create an artificial one using array // schema to start moving to the actual schema the // first time move next is called. // Push(schema.IsRoot() ? schema : schema.AsArray()); } /// /// Try to continue traversal to next schema /// /// public bool TryMoveNext() { return _schemas.TryPeek(out var s) && s.TryMoveNext(); } /// /// Push schema on stack /// /// public void Push(Schema schema) { if (_types.TryGetValue(schema.Fullname, out var seen)) { // // Partial types must be replaced with full type // to handle recursive declarations correctly. // schema = seen; } else if (schema is RecordSchema record) { // Add the record to the list of types _types.AddOrUpdate(record.Fullname, record); } _schemas.Push(schema switch { RecordSchema r => new RecordTraverser(this, r), ArraySchema a => new ArrayTraverser(this, a), UnionSchema u => new UnionTraverser(this, u), _ => new Traverser(this, schema) }); } /// /// Validate we completed traversal /// public bool IsDone() { Debug.Assert(_schemas.Count > 0); if (_schemas.Count == 1) { // See constructor var root = _schemas.Peek(); return root.Schema is ArraySchema || root.Schema.IsRoot(); } return false; } /// /// Allows to pop top traverser from stack /// public Schema Pop() { var traverser = _schemas.Pop(); return traverser.Schema; } /// /// Generic traversal /// private class Traverser { /// /// Schema /// public Schema Schema { get; } /// /// Create record traverers /// /// /// public Traverser(AvroSchemaTraverser outer, Schema schema) { _outer = outer; Schema = schema; } /// public virtual bool TryMoveNext() { if (_outer.ExpectedFieldName != null) { // There are no fields in here return false; } return true; } protected readonly AvroSchemaTraverser _outer; } /// /// Array traversal /// private class ArrayTraverser : Traverser { /// /// Create record traverers /// /// /// public ArrayTraverser(AvroSchemaTraverser outer, ArraySchema schema) : base(outer, schema) { _array = schema; } /// public override bool TryMoveNext() { if (_outer.ExpectedFieldName != null) { // There are no fields in here return false; } _outer.Push(_array.ItemSchema); return true; } private readonly ArraySchema _array; } /// /// Array traversal /// private class UnionTraverser : Traverser { /// /// Create union traverser /// /// /// public UnionTraverser(AvroSchemaTraverser outer, UnionSchema schema) : base(outer, schema) { _union = schema; } /// public override bool TryMoveNext() { if (_outer.ExpectUnionItem == null) { return false; } var selected = _outer.ExpectUnionItem(_union); if (selected == null) { return false; } _outer.Push(selected); return true; } private readonly UnionSchema _union; } /// /// Record traverser /// private sealed class RecordTraverser : Traverser { /// /// Create record traverers /// /// /// public RecordTraverser(AvroSchemaTraverser outer, RecordSchema schema) : base(outer, schema) { _record = schema; } /// public override bool TryMoveNext() { Debug.Assert(_pos >= 0); if (_pos == _record.Count) { _pos = 0; } var field = _record.Fields[_pos]; var fieldName = _outer.ExpectedFieldName; _outer.ExpectedFieldName = null; if (fieldName != null && field.Name != fieldName) { var schemaField = SchemaUtils.Escape(fieldName); if (!_record.TryGetField(schemaField, out field) && !_record.TryGetFieldAlias(schemaField, out field)) { return false; } _pos = field.Pos - 1; } _outer.Push(field.Schema); _pos++; return true; } private readonly RecordSchema _record; private int _pos; } private readonly Dictionary _types = []; private readonly Stack _schemas = new(); } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/BaseAvroDecoder.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Azure.IIoT.OpcUa.Encoders.Models; using Azure.IIoT.OpcUa.Encoders.Schemas; using Azure.IIoT.OpcUa.Publisher.Models; using Opc.Ua; using System; using System.Buffers.Binary; using System.Collections.Generic; using System.IO; using System.Text; using System.Xml; /// /// Decodes objects from a Avro Binary encoded stream. /// public abstract class BaseAvroDecoder : IDecoder { /// public virtual EncodingType EncodingType => (EncodingType)3; /// public virtual IServiceMessageContext Context { get; } /// /// Create avro decoder /// /// /// /// protected BaseAvroDecoder(Stream stream, IServiceMessageContext context, bool leaveOpen = false) { _reader = new AvroBinaryReader(stream, leaveOpen) { MaxBytesLength = context.MaxByteStringLength, MaxStringLength = context.MaxStringLength }; Context = context; _nestingLevel = 0; } /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Dispose /// /// protected virtual void Dispose(bool disposing) { if (disposing) { _reader.Dispose(); } } /// public virtual void Close() { // Dispose } /// public virtual void PushNamespace(string namespaceUri) { // not used in the binary encoding. } /// public virtual void PopNamespace() { // not used in the binary encoding. } /// public virtual void SetMappingTables(NamespaceTable? namespaceUris, StringTable? serverUris) { _namespaceMappings = null; if (namespaceUris != null && Context.NamespaceUris != null) { _namespaceMappings = Context.NamespaceUris.CreateMapping( namespaceUris, false); } _serverMappings = null; if (serverUris != null && Context.ServerUris != null) { _serverMappings = Context.ServerUris.CreateMapping( serverUris, false); } } /// public IEncodeable DecodeMessage(Type expectedType) { throw ServiceResultException.Create(StatusCodes.BadNotSupported, "Not supported in this decoder."); } /// public uint ReadSwitchField(IList switches, out string fieldName) { fieldName = switches[0]; return 0; // TODO } /// public uint ReadEncodingMask(IList masks) { return 0; // TODO } /// public virtual bool ReadBoolean(string? fieldName) { return _reader.ReadBoolean(); } /// public virtual sbyte ReadSByte(string? fieldName) { return (sbyte)_reader.ReadInteger(); } /// public virtual byte ReadByte(string? fieldName) { return (byte)_reader.ReadInteger(); } /// public virtual short ReadInt16(string? fieldName) { return (short)_reader.ReadInteger(); } /// public virtual ushort ReadUInt16(string? fieldName) { return (ushort)_reader.ReadInteger(); } /// public virtual int ReadInt32(string? fieldName) { return (int)_reader.ReadInteger(); } /// public virtual uint ReadUInt32(string? fieldName) { return (uint)_reader.ReadInteger(); } /// public virtual long ReadInt64(string? fieldName) { return _reader.ReadInteger(); } /// public virtual ulong ReadUInt64(string? fieldName) { // ulong is a union of long and fixed (> long.max) var index = _reader.ReadInteger(); if (index == 0) { return (ulong)_reader.ReadInteger(); } Span bytes = stackalloc byte[sizeof(ulong)]; _reader.ReadFixed(bytes); return BinaryPrimitives.ReadUInt64LittleEndian(bytes); } /// public virtual float ReadFloat(string? fieldName) { return _reader.ReadFloat(); } /// public virtual double ReadDouble(string? fieldName) { return _reader.ReadDouble(); } /// public virtual Uuid ReadGuid(string? fieldName) { #if UUID_FIXED Span bytes = stackalloc byte[16]; _reader.ReadFixed(bytes); return new Uuid(new Guid(bytes)); #else var uuid = _reader.ReadString(); return new Uuid(Guid.Parse(uuid)); #endif } /// public virtual string? ReadString(string? fieldName) { return _reader.ReadString(); } /// public virtual DateTime ReadDateTime(string? fieldName) { var ticks = _reader.ReadInteger(); if (ticks >= (long.MaxValue - Opc.Ua.Utils.TimeBase.Ticks)) { return DateTime.MaxValue; } ticks += Opc.Ua.Utils.TimeBase.Ticks; if (ticks >= DateTime.MaxValue.Ticks) { return DateTime.MaxValue; } if (ticks <= Opc.Ua.Utils.TimeBase.Ticks) { return DateTime.MinValue; } return new DateTime(ticks, DateTimeKind.Utc); } /// public virtual byte[] ReadByteString(string? fieldName) { return _reader.ReadBytes(); } /// public virtual XmlElement ReadXmlElement(string? fieldName) { var xmlString = _reader.ReadString(); var document = new XmlDocument(); try { using var stream = new StringReader(xmlString); using var reader = XmlReader.Create(stream, Opc.Ua.Utils.DefaultXmlReaderSettings()); document.Load(reader); } catch (XmlException ex) { throw new DecodingException("Xml element invalid", ex); } return document.DocumentElement!; } /// public virtual NodeId ReadNodeId(string? fieldName) { // // Node id is a record, with namespace and union of // the id. The IdType value represents the union // discriminator. // // Node id is not nullable, i=0 is a null node id. // var namespaceUri = ReadString("Namespace"); var namespaceIndex = string.IsNullOrEmpty(namespaceUri) ? (ushort)0 : Context.NamespaceUris.GetIndexOrAppend(namespaceUri); if (_namespaceMappings != null && _namespaceMappings.Length > namespaceIndex) { namespaceIndex = _namespaceMappings[namespaceIndex]; } return ReadNodeId(namespaceIndex); } /// public virtual ExpandedNodeId ReadExpandedNodeId(string? fieldName) { // // Expanded Node id is a record extending NodeId. // Namespace, and union of via IdType which represents // the union discriminator. After that we write the // namespace uri and then server index. // // ExpandedNode id is not nullable, i=0 is a null node id. // var namespaceUri = ReadString("Namespace"); var namespaceIndex = string.IsNullOrEmpty(namespaceUri) ? (ushort)0 : Context.NamespaceUris.GetIndexOrAppend(namespaceUri); if (_namespaceMappings != null && _namespaceMappings.Length > namespaceIndex) { namespaceIndex = _namespaceMappings[namespaceIndex]; } var innerNodeId = ReadNodeId(namespaceIndex); var serverUri = ReadString("ServerUri"); if (NodeId.IsNull(innerNodeId)) { return ExpandedNodeId.Null; } var serverIndex = string.IsNullOrEmpty(serverUri) ? 0u : Context.ServerUris.GetIndexOrAppend(serverUri); if (_serverMappings != null && _serverMappings.Length > serverIndex) { serverIndex = _serverMappings[serverIndex]; } return new ExpandedNodeId(innerNodeId, namespaceUri, serverIndex); } /// public virtual StatusCode ReadStatusCode(string? fieldName) { return (StatusCode)_reader.ReadInteger(); } /// public virtual DiagnosticInfo ReadDiagnosticInfo(string? fieldName) { return ReadDiagnosticInfo(fieldName, 0); } /// public virtual QualifiedName ReadQualifiedName(string? fieldName) { var namespaceUri = ReadString("Namespace"); var name = ReadString(nameof(QualifiedName.Name)); var namespaceIndex = string.IsNullOrEmpty(namespaceUri) ? (ushort)0 : Context.NamespaceUris.GetIndexOrAppend(namespaceUri); if (_namespaceMappings != null && _namespaceMappings.Length > namespaceIndex) { namespaceIndex = _namespaceMappings[namespaceIndex]; } return new QualifiedName(name, namespaceIndex); } /// public virtual LocalizedText ReadLocalizedText(string? fieldName) { return new LocalizedText( ReadString(nameof(LocalizedText.Locale)), ReadString(nameof(LocalizedText.Text))); } /// public virtual Variant ReadVariant(string? fieldName) { CheckAndIncrementNestingLevel(); try { // Read Union discriminator for the variant return ReadUnion(fieldName, fieldId => { if (fieldId < 0 || fieldId >= VariantUnionFieldIds.Length) { throw new DecodingException( $"Cannot decode unknown variant union field {fieldId}."); } var (valueRank, builtInType) = VariantUnionFieldIds[fieldId]; return ReadVariantValue(builtInType, valueRank); }); } finally { _nestingLevel--; } } /// public virtual DataValue ReadDataValue(string? fieldName) { return new DataValue { WrappedValue = ReadVariant(nameof(DataValue.Value)), StatusCode = ReadStatusCode(nameof(DataValue.StatusCode)), SourceTimestamp = ReadDateTime(nameof(DataValue.SourceTimestamp)), SourcePicoseconds = ReadUInt16(nameof(DataValue.SourcePicoseconds)), ServerTimestamp = ReadDateTime(nameof(DataValue.ServerTimestamp)), ServerPicoseconds = ReadUInt16(nameof(DataValue.ServerPicoseconds)) }; } /// public virtual T ReadObject(string? fieldName, Func reader) { return reader(null); } /// public virtual DataSet ReadDataSet(string? fieldName) { return ReadUnion(fieldName, avroFieldContent => { var fieldNames = Array.Empty(); var dataSet = new List<(string, DataValue?)>(); var dataSetFieldContentMask = avroFieldContent == 0 ? 0 : DataSetFieldContentFlags.RawData; if (avroFieldContent == 1) // Raw mode { // // Read map of raw variant // var variants = ReadVariantArray(null); // TODO: Read map if (variants == null && fieldNames.Length == 0) { return new DataSet(dataSet, dataSetFieldContentMask); } if (variants == null || variants.Count != fieldNames.Length) { throw new DecodingException( "Unexpected number of fields in data set"); } for (var index = 0; index < fieldNames.Length; index++) { dataSet.Add((fieldNames[index], new DataValue(variants[index]))); } } else if (avroFieldContent == 0) { // // Read map of data values // var dataValues = ReadDataValueArray(null); // TODO: Read map if (dataValues == null && fieldNames.Length == 0) { return new DataSet(dataSet, dataSetFieldContentMask); } if (dataValues == null || dataValues.Count != fieldNames.Length) { throw new DecodingException( "Unexpected number of fields in data set"); } for (var index = 0; index < fieldNames.Length; index++) { dataSet.Add((fieldNames[index], dataValues[index])); } } return new DataSet(dataSet, dataSetFieldContentMask); }); } /// public virtual ExtensionObject? ReadExtensionObject(string? fieldName) { return ReadUnion(fieldName, unionId => { if (unionId != 0) { return new ExtensionObject(ReadEncodeableInExtensionObject(unionId)); } return ReadEncodedDataType(fieldName); }); } /// public virtual IEncodeable ReadEncodeable(string? fieldName, Type systemType, ExpandedNodeId? encodeableTypeId = null) { if (Activator.CreateInstance(systemType) is not IEncodeable encodeable) { throw new DecodingException( $"Cannot decode type '{systemType.FullName}'."); } if (encodeableTypeId != null) { // set type identifier for custom complex data types before decode. if (encodeable is IComplexTypeInstance complexTypeInstance) { complexTypeInstance.TypeId = encodeableTypeId; } } CheckAndIncrementNestingLevel(); try { encodeable.Decode(this); } finally { _nestingLevel--; } return encodeable; } /// public virtual Enum ReadEnumerated(string? fieldName, Type enumType) { return (Enum)Enum.ToObject(enumType, ReadEnumerated(fieldName)); } /// public virtual int ReadEnumerated(string? fieldName) { return (int)_reader.ReadInteger(); } /// public virtual T ReadEnumerated(string? fieldName) where T : Enum { return (T)ReadEnumerated(fieldName, typeof(T)); } /// public virtual BooleanCollection ReadBooleanArray(string? fieldName) { return ReadArray(fieldName, () => ReadBoolean(null)); } /// public virtual SByteCollection ReadSByteArray(string? fieldName) { return ReadArray(fieldName, () => ReadSByte(null)); } /// public virtual ByteCollection ReadByteArray(string? fieldName) { return _reader.ReadBytes(); } /// public virtual Int16Collection ReadInt16Array(string? fieldName) { return ReadArray(fieldName, () => ReadInt16(null)); } /// public virtual UInt16Collection ReadUInt16Array(string? fieldName) { return ReadArray(fieldName, () => ReadUInt16(null)); } /// public virtual Int32Collection ReadInt32Array(string? fieldName) { return ReadArray(fieldName, () => ReadInt32(null)); } /// public virtual UInt32Collection ReadUInt32Array(string? fieldName) { return ReadArray(fieldName, () => ReadUInt32(null)); } /// public virtual Int64Collection ReadInt64Array(string? fieldName) { return ReadArray(fieldName, () => ReadInt64(null)); } /// public virtual UInt64Collection ReadUInt64Array(string? fieldName) { return ReadArray(fieldName, () => ReadUInt64(null)); } /// public virtual FloatCollection ReadFloatArray(string? fieldName) { return ReadArray(fieldName, () => ReadFloat(null)); } /// public virtual DoubleCollection ReadDoubleArray(string? fieldName) { return ReadArray(fieldName, () => ReadDouble(null)); } /// public virtual StringCollection ReadStringArray(string? fieldName) { return ReadArray(fieldName, () => ReadString(null)); } /// public virtual DateTimeCollection ReadDateTimeArray(string? fieldName) { return ReadArray(fieldName, () => ReadDateTime(null)); } /// public virtual UuidCollection ReadGuidArray(string? fieldName) { return ReadArray(fieldName, () => ReadGuid(null)); } /// public virtual ByteStringCollection ReadByteStringArray(string? fieldName) { return ReadArray(fieldName, () => ReadByteString(null)); } /// public virtual XmlElementCollection ReadXmlElementArray(string? fieldName) { return ReadArray(fieldName, () => ReadXmlElement(null)); } /// public virtual NodeIdCollection ReadNodeIdArray(string? fieldName) { return ReadArray(fieldName, () => ReadNodeId(null)); } /// public virtual ExpandedNodeIdCollection ReadExpandedNodeIdArray(string? fieldName) { return ReadArray(fieldName, () => ReadExpandedNodeId(null)); } /// public virtual StatusCodeCollection ReadStatusCodeArray(string? fieldName) { return ReadArray(fieldName, () => ReadStatusCode(null)); } /// public virtual DiagnosticInfoCollection ReadDiagnosticInfoArray(string? fieldName) { return ReadArray(fieldName, () => ReadDiagnosticInfo(null)); } /// public virtual QualifiedNameCollection ReadQualifiedNameArray(string? fieldName) { return ReadArray(fieldName, () => ReadQualifiedName(null)); } /// public virtual LocalizedTextCollection ReadLocalizedTextArray(string? fieldName) { return ReadArray(fieldName, () => ReadLocalizedText(null)); } /// public virtual VariantCollection ReadVariantArray(string? fieldName) { return ReadArray(fieldName, () => ReadVariant(null)); } /// public virtual DataValueCollection ReadDataValueArray(string? fieldName) { return ReadArray(fieldName, () => ReadDataValue(null)); } /// public virtual ExtensionObjectCollection ReadExtensionObjectArray(string? fieldName) { return ReadArray(fieldName, () => ReadExtensionObject(null)); } /// public virtual Array? ReadEncodeableArray(string? fieldName, Type systemType, ExpandedNodeId? encodeableTypeId = null) { return ReadArray(fieldName, () => ReadEncodeable(null, systemType, encodeableTypeId), systemType); } /// public virtual Array? ReadEnumeratedArray(string? fieldName, Type enumType) { return ReadArray(fieldName, () => ReadEnumerated(null, enumType), enumType); } /// public virtual int[] ReadEnumeratedArray(string? fieldName) { return ReadArray(fieldName, () => ReadEnumerated(null)); } /// public virtual T[]? ReadEnumeratedArray(string? fieldName) where T : Enum { return (T[]?)ReadEnumeratedArray(fieldName, typeof(T)); } /// public virtual Array? ReadArray(string? fieldName, int valueRank, BuiltInType builtInType, Type? systemType = null, ExpandedNodeId? encodeableTypeId = null) { var rank = SchemaUtils.GetRank(valueRank); if (rank == SchemaRank.Scalar) { return null; } var array = ReadArray(fieldName, builtInType, systemType, encodeableTypeId); if (array == null || rank == SchemaRank.Collection) { return array; } // read as matrix var dimensions = ReadInt32Array(null); if (dimensions?.Count > 0) { Matrix.ValidateDimensions(false, dimensions, Context.MaxArrayLength); return new Matrix(array, builtInType, [.. dimensions]).ToArray(); } throw new DecodingException( "Unexpected null or empty Dimensions for multidimensional matrix."); } /// /// Reads a DiagnosticInfo from the stream. /// Limits the InnerDiagnosticInfo nesting level. /// /// /// /// protected virtual DiagnosticInfo ReadDiagnosticInfo(string? fieldName, int depth) { if (depth >= DiagnosticInfo.MaxInnerDepth) { throw new DecodingException(StatusCodes.BadEncodingLimitsExceeded, "Maximum nesting level of InnerDiagnosticInfo was exceeded."); } CheckAndIncrementNestingLevel(); try { return new DiagnosticInfo { SymbolicId = ReadInt32(nameof(DiagnosticInfo.SymbolicId)), NamespaceUri = ReadInt32(nameof(DiagnosticInfo.NamespaceUri)), Locale = ReadInt32(nameof(DiagnosticInfo.Locale)), LocalizedText = ReadInt32(nameof(DiagnosticInfo.LocalizedText)), AdditionalInfo = ReadString(nameof(DiagnosticInfo.AdditionalInfo)), InnerStatusCode = ReadStatusCode(nameof(DiagnosticInfo.InnerStatusCode)), InnerDiagnosticInfo = ReadNullable(nameof(DiagnosticInfo.InnerDiagnosticInfo), f => ReadDiagnosticInfo(f, depth + 1)) }; } finally { _nestingLevel--; } } /// /// Read null /// /// /// public virtual T? ReadNull(string? fieldName) { // Nothing to do return default; } /// /// Read nullable /// /// /// /// protected virtual T? ReadNullable(string? fieldName, Func reader) { return ReadUnion(fieldName, id => { switch (id) { case 0: return ReadNull(fieldName); case 1: return reader(fieldName); default: throw new DecodingException( $"Unexpected union discriminator {id}."); } }); } /// /// Read array using specified element reader /// /// /// /// /// public virtual T[] ReadArray(string? fieldName, Func reader) { return [.. ReadArray(reader)]; } /// /// Read array using specified element reader /// /// /// /// /// protected virtual Array ReadArray(string? fieldName, Func reader, Type type) { var result = ReadArray(reader); var array = Array.CreateInstance(type, result.Count); // TODO: Can we just cast to Array? for (var i = 0; i < result.Count; i++) { array.SetValue(result[i], i); } return array; } /// /// Read array using specified element reader /// /// /// /// /// private List ReadArray(Func reader) { var result = new List(); var length = _reader.ReadInteger(); do { var newLength = length + result.Count; if (newLength < 0 || newLength > int.MaxValue || (Context.MaxArrayLength > 0 && Context.MaxArrayLength < newLength)) { throw new DecodingException(StatusCodes.BadEncodingLimitsExceeded, $"MaxArrayLength {Context.MaxArrayLength} < {length}."); } result.EnsureCapacity((int)newLength); for (var i = 0; i < length; i++) { result.Add(reader()); } // Either another length or last block indicator length = _reader.ReadInteger(); } while (length > 0); return result; } /// /// Read union /// /// /// /// public virtual T ReadUnion(string? fieldName, Func reader) { var id = StartUnion(); var result = reader(id); EndUnion(); return result; } /// /// Read union selector /// /// protected virtual int StartUnion() { return (int)_reader.ReadInteger(); } /// /// End union /// protected virtual void EndUnion() { } /// /// Get the system type from the type factory if not specified by caller. /// /// The reference to the system type, or null /// The encodeable type id of the system type. /// If the system type is assignable to private bool DetermineIEncodeableSystemType(ref Type systemType, ExpandedNodeId encodeableTypeId) { if (encodeableTypeId != null && systemType == null) { systemType = Context.Factory.GetSystemType(encodeableTypeId); } return typeof(IEncodeable).IsAssignableFrom(systemType); } /// /// Read extension object /// /// /// /// protected virtual IEncodeable ReadEncodeableInExtensionObject(int unionId) { throw new DecodingException( "Cannot decode extensible object structures without schema"); } /// /// Read an encoded extension object /// /// /// /// protected virtual ExtensionObject ReadEncodedDataType(string? fieldName) { var typeId = ReadNodeId("TypeId"); var body = ReadByteString("Body"); // convert to absolute node id. var expandedTypeId = NodeId.ToExpandedNodeId(typeId, Context.NamespaceUris); if (!NodeId.IsNull(typeId) && NodeId.IsNull(expandedTypeId)) { throw new DecodingException( "Cannot de-serialized extension objects if the NamespaceUri " + $"is not in the NamespaceTable: Type = {typeId}"); } var systemType = Context.Factory.GetSystemType(expandedTypeId); if (systemType != null) { var encodeable = Activator.CreateInstance(systemType) as IEncodeable; // set type identifier for custom complex data types before decode. if (encodeable is IComplexTypeInstance complexTypeInstance) { complexTypeInstance.TypeId = expandedTypeId; } if (encodeable != null) { if (encodeable.XmlEncodingId == expandedTypeId) { var document = new XmlDocument { InnerXml = Encoding.UTF8.GetString(body) }; using var decoder = new XmlDecoder(document.DocumentElement, Context); encodeable.Decode(decoder); return new ExtensionObject(expandedTypeId, encodeable); } else if (encodeable.BinaryEncodingId == expandedTypeId) { using var decoder = new BinaryDecoder(body, Context); encodeable.Decode(decoder); return new ExtensionObject(expandedTypeId, encodeable); } else if (encodeable is IJsonEncodeable je && je.JsonEncodingId == expandedTypeId) { using var stream = new MemoryStream(body); using var decoder = new JsonDecoderEx(stream, Context); encodeable.Decode(decoder); return new ExtensionObject(expandedTypeId, encodeable); } } } return new ExtensionObject(expandedTypeId, body); } /// /// Read variant body /// /// /// /// /// protected virtual Variant ReadVariantValue(BuiltInType builtInType, SchemaRank valueRank = SchemaRank.Scalar) { if (valueRank == SchemaRank.Scalar) { return ReadScalar(null, builtInType); } // Read array var array = ReadArray(null, builtInType, null, null); if (array == null) { return new Variant(StatusCodes.BadDecodingError); } if (valueRank == SchemaRank.Collection) { return new Variant(array, new TypeInfo(builtInType, ValueRanks.OneDimension)); } // Read matrix var dimensions = ReadArray("Dimensions", () => ReadInt32(null)); (var valid, var matrixLength) = Matrix.ValidateDimensions( dimensions, array.Length, Context.MaxArrayLength); if (!valid || (matrixLength != array.Length)) { throw new DecodingException( "ArrayDimensions does not match with the ArrayLength " + "in Variant object."); } return new Variant(new Matrix(array, builtInType, dimensions)); } /// /// Read scalar element /// /// /// /// /// protected Variant ReadScalar(string? fieldName, BuiltInType builtInType) { var value = new Variant(); switch (builtInType) { case BuiltInType.Null: value.Value = ReadNull(fieldName); break; case BuiltInType.Boolean: value.Set(ReadBoolean(fieldName)); break; case BuiltInType.SByte: value.Set(ReadSByte(fieldName)); break; case BuiltInType.Byte: value.Set(ReadByte(fieldName)); break; case BuiltInType.Int16: value.Set(ReadInt16(fieldName)); break; case BuiltInType.UInt16: value.Set(ReadUInt16(fieldName)); break; case BuiltInType.Int32: value.Set(ReadInt32(fieldName)); break; case BuiltInType.Enumeration: value.Set(ReadEnumerated(fieldName)); break; case BuiltInType.UInt32: value.Set(ReadUInt32(fieldName)); break; case BuiltInType.Int64: value.Set(ReadInt64(fieldName)); break; case BuiltInType.UInt64: value.Set(ReadUInt64(fieldName)); break; case BuiltInType.Float: value.Set(ReadFloat(fieldName)); break; case BuiltInType.Double: value.Set(ReadDouble(fieldName)); break; case BuiltInType.String: value.Set(ReadString(fieldName)); break; case BuiltInType.DateTime: value.Set(ReadDateTime(fieldName)); break; case BuiltInType.Guid: value.Set(ReadGuid(fieldName)); break; case BuiltInType.ByteString: value.Set(ReadByteString(fieldName)); break; case BuiltInType.XmlElement: try { value.Set(ReadXmlElement(fieldName)); } catch { value.Set(StatusCodes.BadDecodingError); } break; case BuiltInType.NodeId: value.Set(ReadNodeId(fieldName)); break; case BuiltInType.ExpandedNodeId: value.Set(ReadExpandedNodeId(fieldName)); break; case BuiltInType.StatusCode: value.Set(ReadStatusCode(fieldName)); break; case BuiltInType.QualifiedName: value.Set(ReadQualifiedName(fieldName)); break; case BuiltInType.LocalizedText: value.Set(ReadLocalizedText(fieldName)); break; case BuiltInType.ExtensionObject: value.Set(ReadExtensionObject(fieldName)); break; case BuiltInType.DataValue: value.Set(ReadDataValue(fieldName)); break; default: throw new DecodingException( $"Cannot decode unknown type in Variant object (0x{builtInType:X2})."); } return value; } /// /// Read array /// /// /// /// /// /// /// protected Array? ReadArray(string? fieldName, BuiltInType builtInType, Type? systemType = null, ExpandedNodeId? encodeableTypeId = null) { switch (builtInType) { case BuiltInType.Boolean: return ReadBooleanArray(fieldName)?.ToArray(); case BuiltInType.SByte: return ReadSByteArray(fieldName)?.ToArray(); case BuiltInType.Byte: return ReadByteArray(fieldName)?.ToArray(); case BuiltInType.Int16: return ReadInt16Array(fieldName)?.ToArray(); case BuiltInType.UInt16: return ReadUInt16Array(fieldName)?.ToArray(); case BuiltInType.Enumeration: if (systemType != null && encodeableTypeId != null) { DetermineIEncodeableSystemType(ref systemType, encodeableTypeId); if (systemType?.IsEnum == true) { return ReadEnumeratedArray(fieldName, systemType); } } return ReadEnumeratedArray(fieldName); case BuiltInType.Int32: return ReadInt32Array(fieldName)?.ToArray(); case BuiltInType.UInt32: return ReadUInt32Array(fieldName)?.ToArray(); case BuiltInType.Int64: return ReadInt64Array(fieldName)?.ToArray(); case BuiltInType.UInt64: return ReadUInt64Array(fieldName)?.ToArray(); case BuiltInType.Float: return ReadFloatArray(fieldName)?.ToArray(); case BuiltInType.Double: return ReadDoubleArray(fieldName)?.ToArray(); case BuiltInType.String: return ReadStringArray(fieldName)?.ToArray(); case BuiltInType.DateTime: return ReadDateTimeArray(fieldName)?.ToArray(); case BuiltInType.Guid: return ReadGuidArray(fieldName)?.ToArray(); case BuiltInType.ByteString: return ReadByteStringArray(fieldName)?.ToArray(); case BuiltInType.XmlElement: return ReadXmlElementArray(fieldName)?.ToArray(); case BuiltInType.NodeId: return ReadNodeIdArray(fieldName)?.ToArray(); case BuiltInType.ExpandedNodeId: return ReadExpandedNodeIdArray(fieldName)?.ToArray(); case BuiltInType.StatusCode: return ReadStatusCodeArray(fieldName)?.ToArray(); case BuiltInType.QualifiedName: return ReadQualifiedNameArray(fieldName)?.ToArray(); case BuiltInType.LocalizedText: return ReadLocalizedTextArray(fieldName)?.ToArray(); case BuiltInType.DataValue: return ReadDataValueArray(fieldName)?.ToArray(); case BuiltInType.Variant: if (systemType != null && encodeableTypeId != null && DetermineIEncodeableSystemType(ref systemType, encodeableTypeId)) { return ReadEncodeableArray(fieldName, systemType, encodeableTypeId); } return ReadVariantArray(fieldName)?.ToArray(); case BuiltInType.ExtensionObject: return ReadExtensionObjectArray(fieldName)?.ToArray(); case BuiltInType.DiagnosticInfo: return ReadDiagnosticInfoArray(fieldName)?.ToArray(); default: if (systemType != null && encodeableTypeId != null && DetermineIEncodeableSystemType(ref systemType, encodeableTypeId)) { return ReadEncodeableArray(fieldName, systemType, encodeableTypeId); } throw new DecodingException( $"Cannot decode unknown type in Array object with BuiltInType: {builtInType}."); } } // TODO: Decide whether the opc ua types are records with single field internal static ReadOnlySpan<(SchemaRank, BuiltInType)> VariantUnionFieldIds => new (SchemaRank, BuiltInType)[] { (SchemaRank.Scalar, BuiltInType.Null), (SchemaRank.Scalar, BuiltInType.Boolean), (SchemaRank.Scalar, BuiltInType.SByte), (SchemaRank.Scalar, BuiltInType.Byte), (SchemaRank.Scalar, BuiltInType.Int16), (SchemaRank.Scalar, BuiltInType.UInt16), (SchemaRank.Scalar, BuiltInType.Int32), (SchemaRank.Scalar, BuiltInType.UInt32), (SchemaRank.Scalar, BuiltInType.Int64), (SchemaRank.Scalar, BuiltInType.UInt64), (SchemaRank.Scalar, BuiltInType.Float), (SchemaRank.Scalar, BuiltInType.Double), (SchemaRank.Scalar, BuiltInType.String), (SchemaRank.Scalar, BuiltInType.DateTime), (SchemaRank.Scalar, BuiltInType.Guid), (SchemaRank.Scalar, BuiltInType.ByteString), (SchemaRank.Scalar, BuiltInType.XmlElement), (SchemaRank.Scalar, BuiltInType.NodeId), (SchemaRank.Scalar, BuiltInType.ExpandedNodeId), (SchemaRank.Scalar, BuiltInType.StatusCode), (SchemaRank.Scalar, BuiltInType.QualifiedName), (SchemaRank.Scalar, BuiltInType.LocalizedText), (SchemaRank.Scalar, BuiltInType.ExtensionObject), (SchemaRank.Scalar, BuiltInType.DataValue), // (ValueRanks.Scalar, BuiltInType.Number), // (ValueRanks.Scalar, BuiltInType.Integer), // (ValueRanks.Scalar, BuiltInType.UInteger), (SchemaRank.Scalar, BuiltInType.Enumeration), (SchemaRank.Collection, BuiltInType.Boolean), (SchemaRank.Collection, BuiltInType.SByte), // (SchemaRank.Collection, BuiltInType.Byte), (SchemaRank.Collection, BuiltInType.Int16), (SchemaRank.Collection, BuiltInType.UInt16), (SchemaRank.Collection, BuiltInType.Int32), (SchemaRank.Collection, BuiltInType.UInt32), (SchemaRank.Collection, BuiltInType.Int64), (SchemaRank.Collection, BuiltInType.UInt64), (SchemaRank.Collection, BuiltInType.Float), (SchemaRank.Collection, BuiltInType.Double), (SchemaRank.Collection, BuiltInType.String), (SchemaRank.Collection, BuiltInType.DateTime), (SchemaRank.Collection, BuiltInType.Guid), (SchemaRank.Collection, BuiltInType.ByteString), (SchemaRank.Collection, BuiltInType.XmlElement), (SchemaRank.Collection, BuiltInType.NodeId), (SchemaRank.Collection, BuiltInType.ExpandedNodeId), (SchemaRank.Collection, BuiltInType.StatusCode), (SchemaRank.Collection, BuiltInType.QualifiedName), (SchemaRank.Collection, BuiltInType.LocalizedText), (SchemaRank.Collection, BuiltInType.ExtensionObject), (SchemaRank.Collection, BuiltInType.DataValue), (SchemaRank.Collection, BuiltInType.Variant), //(SchemaRank.Collection, BuiltInType.Number), //(SchemaRank.Collection, BuiltInType.Integer), //(SchemaRank.Collection, BuiltInType.UInteger), (SchemaRank.Collection, BuiltInType.Enumeration), (SchemaRank.Matrix, BuiltInType.Boolean), (SchemaRank.Matrix, BuiltInType.SByte), (SchemaRank.Matrix, BuiltInType.Byte), (SchemaRank.Matrix, BuiltInType.Int16), (SchemaRank.Matrix, BuiltInType.UInt16), (SchemaRank.Matrix, BuiltInType.Int32), (SchemaRank.Matrix, BuiltInType.UInt32), (SchemaRank.Matrix, BuiltInType.Int64), (SchemaRank.Matrix, BuiltInType.UInt64), (SchemaRank.Matrix, BuiltInType.Float), (SchemaRank.Matrix, BuiltInType.Double), (SchemaRank.Matrix, BuiltInType.String), (SchemaRank.Matrix, BuiltInType.DateTime), (SchemaRank.Matrix, BuiltInType.Guid), (SchemaRank.Matrix, BuiltInType.ByteString), (SchemaRank.Matrix, BuiltInType.XmlElement), (SchemaRank.Matrix, BuiltInType.NodeId), (SchemaRank.Matrix, BuiltInType.ExpandedNodeId), (SchemaRank.Matrix, BuiltInType.StatusCode), (SchemaRank.Matrix, BuiltInType.QualifiedName), (SchemaRank.Matrix, BuiltInType.LocalizedText), (SchemaRank.Matrix, BuiltInType.ExtensionObject), (SchemaRank.Matrix, BuiltInType.DataValue), (SchemaRank.Matrix, BuiltInType.Variant), //(SchemaRank.Matrix, BuiltInType.Number), //(SchemaRank.Matrix, BuiltInType.Integer), //(SchemaRank.Matrix, BuiltInType.UInteger), (SchemaRank.Matrix, BuiltInType.Enumeration) }; /// /// Read node id /// /// /// /// private NodeId ReadNodeId(ushort namespaceIndex) { const string kIdentifierName = "Identifier"; return ReadUnion(kIdentifierName, idType => { switch ((IdType)idType) { case IdType.Numeric: return new NodeId(ReadUInt32(kIdentifierName), namespaceIndex); case IdType.String: return new NodeId(ReadString(kIdentifierName), namespaceIndex); case IdType.Guid: return new NodeId(ReadGuid(kIdentifierName), namespaceIndex); case IdType.Opaque: return new NodeId(ReadByteString(kIdentifierName), namespaceIndex); default: throw new DecodingException("Unknown node id type"); } }); } /// /// Test and increment the nesting level. /// /// private void CheckAndIncrementNestingLevel() { if (_nestingLevel > Context.MaxEncodingNestingLevels) { throw new DecodingException(StatusCodes.BadEncodingLimitsExceeded, $"Maximum nesting level of {Context.MaxEncodingNestingLevels} was exceeded."); } _nestingLevel++; } private readonly AvroBinaryReader _reader; private ushort[]? _namespaceMappings; private ushort[]? _serverMappings; private uint _nestingLevel; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/BaseAvroEncoder.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Azure.IIoT.OpcUa.Encoders.Models; using Azure.IIoT.OpcUa.Encoders.Schemas; using Azure.IIoT.OpcUa.Publisher.Models; using Opc.Ua; using Opc.Ua.Extensions; using System; using System.Buffers.Binary; using System.Collections.Frozen; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Xml; /// /// Encodes objects in a stream using Avro binary encoding. /// public abstract class BaseAvroEncoder : IEncoder { /// public EncodingType EncodingType => (EncodingType)3; /// public IServiceMessageContext Context { get; } /// public bool UseReversibleEncoding => true; /// /// Creates an encoder that writes to the stream. /// /// The stream to which the /// encoder writes. /// The message context to /// use for the encoding. /// If the stream should /// be left open on dispose. protected BaseAvroEncoder(Stream stream, IServiceMessageContext context, bool leaveOpen = true) { _writer = new AvroBinaryWriter(stream, leaveOpen); Context = context; _nestingLevel = 0; } /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// protected virtual void Dispose(bool disposing) { if (disposing) { _writer.Dispose(); } } /// public void SetMappingTables(NamespaceTable? namespaceUris, StringTable? serverUris) { _namespaceMappings = null; if (namespaceUris != null && Context.NamespaceUris != null) { _namespaceMappings = namespaceUris.CreateMapping( Context.NamespaceUris, false); } _serverMappings = null; if (serverUris != null && Context.ServerUris != null) { _serverMappings = serverUris.CreateMapping( Context.ServerUris, false); } } /// public string? CloseAndReturnText() { throw new NotSupportedException("Unsupported"); } /// public void PushNamespace(string namespaceUri) { // not used in the binary encoding. } /// public void PopNamespace() { // not used in the binary encoding. } /// public int Close() { var position = (int)_writer.Stream.Position; _writer.Stream.Flush(); return position; } /// public void WriteSwitchField(uint switchField, out string fieldName) { fieldName = string.Empty; // TODO } /// public void WriteEncodingMask(uint encodingMask) { } /// public virtual void WriteBoolean(string? fieldName, bool value) { _writer.WriteBoolean(value); } /// public virtual void WriteSByte(string? fieldName, sbyte value) { _writer.WriteInteger(value); } /// public virtual void WriteByte(string? fieldName, byte value) { _writer.WriteInteger(value); } /// public virtual void WriteInt16(string? fieldName, short value) { _writer.WriteInteger(value); } /// public virtual void WriteUInt16(string? fieldName, ushort value) { _writer.WriteInteger(value); } /// public virtual void WriteInt32(string? fieldName, int value) { _writer.WriteInteger(value); } /// public virtual void WriteUInt32(string? fieldName, uint value) { _writer.WriteInteger(value); } /// public virtual void WriteInt64(string? fieldName, long value) { _writer.WriteInteger(value); } /// public virtual void WriteUInt64(string? fieldName, ulong value) { // ulong is a union of long and fixed (> long.max) var unionSelector = value < long.MaxValue ? 0 : 1; _writer.WriteInteger(unionSelector); if (unionSelector == 0) { _writer.WriteInteger((long)value); } else { Span bytes = stackalloc byte[sizeof(ulong)]; BinaryPrimitives.WriteUInt64LittleEndian(bytes, value); _writer.WriteFixed(bytes); } } /// public virtual void WriteFloat(string? fieldName, float value) { _writer.WriteFloat(value); } /// public virtual void WriteDouble(string? fieldName, double value) { _writer.WriteDouble(value); } /// public virtual void WriteDateTime(string? fieldName, DateTime value) { value = Opc.Ua.Utils.ToOpcUaUniversalTime(value); var ticks = value.Ticks; // check for max value. if (ticks >= DateTime.MaxValue.Ticks) { ticks = long.MaxValue; } // check for min value. else { ticks -= Opc.Ua.Utils.TimeBase.Ticks; if (ticks <= 0) { ticks = 0; } } _writer.WriteInteger(ticks); } /// public virtual void WriteGuid(string? fieldName, Uuid value) { #if UUID_FIXED _writer.WriteFixed(((Guid)value).ToByteArray()); #else _writer.WriteString(((Guid)value).ToString()); #endif } /// public virtual void WriteGuid(string? fieldName, Guid value) { #if UUID_FIXED _writer.WriteFixed(value.ToByteArray()); #else _writer.WriteString(value.ToString()); #endif } /// public virtual void WriteString(string? fieldName, string? value) { if (value == null) { _writer.WriteInteger(0); return; } _writer.WriteString(value); } /// public virtual void WriteByteString(string? fieldName, byte[]? value) { if (value == null) { _writer.WriteInteger(0); return; } if (Context.MaxByteStringLength > 0 && Context.MaxByteStringLength < value.Length) { throw new EncodingException(StatusCodes.BadEncodingLimitsExceeded, $"MaxByteStringLength {Context.MaxByteStringLength} < {value.Length}."); } _writer.WriteBytes(value); } /// public void WriteByteString(string? fieldName, ReadOnlySpan value) { WriteByteString(fieldName, value.ToArray()); } /// public void WriteByteString(string? fieldName, byte[] value, int index, int count) { WriteByteString(fieldName, value.AsSpan().Slice(index, count)); } /// public virtual void WriteXmlElement(string? fieldName, XmlElement? value) { _writer.WriteString(value?.OuterXml ?? string.Empty); } /// public virtual void WriteDataSet(string? fieldName, DataSet dataSet) { var fieldContentMask = dataSet.DataSetFieldContentMask; if (fieldContentMask.HasFlag(DataSetFieldContentFlags.RawData) || fieldContentMask == 0) { foreach (var (Name, Value) in dataSet.DataSetFields) { WriteVariant(Name, Value?.WrappedValue ?? default); } } else { foreach (var (Name, Value) in dataSet.DataSetFields) { WriteNullable(Name, Value, WriteDataValue); } } } /// public virtual void WriteObject(string? fieldName, string? typeName, Action writer) { writer(); } /// public virtual void WriteNodeId(string? fieldName, NodeId? value) { // // Node id is a record, with namespace and union of // the id. The IdType value represents the union // discriminator. // // Node id is not nullable, i=0 is a null node id. // var namespaceIndex = value?.NamespaceIndex ?? 0; if (_namespaceMappings != null && _namespaceMappings.Length > namespaceIndex) { namespaceIndex = _namespaceMappings[namespaceIndex]; } var namespaceUri = namespaceIndex == 0 ? null : Context.NamespaceUris.GetString(namespaceIndex); WriteNodeId(value, namespaceUri ?? string.Empty); } /// /// Write node id /// /// /// private void WriteNodeId(NodeId? value, string namespaceUri) { const string kIdentifierName = "Identifier"; WriteString("Namespace", namespaceUri); // Numeric = 0, // String = 1 // Guid = 2 // Opaque = 3 var idUnionIndex = (int)(value?.IdType ?? IdType.Numeric); WriteUnion(kIdentifierName, idUnionIndex, id => { switch ((IdType)id) { case IdType.Numeric: WriteUInt32(kIdentifierName, (uint)(value?.Identifier ?? 0u)); break; case IdType.String: WriteString(kIdentifierName, (string)value!.Identifier); break; case IdType.Guid: WriteGuid(kIdentifierName, (Guid)value!.Identifier); break; case IdType.Opaque: WriteByteString(kIdentifierName, (byte[])value!.Identifier); break; } }); } /// public virtual void WriteExpandedNodeId(string? fieldName, ExpandedNodeId? value) { var serverIndex = value?.ServerIndex ?? 0; if (_serverMappings != null && _serverMappings.Length > serverIndex) { serverIndex = _serverMappings[serverIndex]; } var serverUri = serverIndex == 0 ? null : Context.ServerUris.GetString(serverIndex); var namespaceUri = value?.NamespaceUri; if (namespaceUri == null && value != null && value.NamespaceIndex != 0) { var namespaceIndex = value.NamespaceIndex; if (_namespaceMappings != null && _namespaceMappings.Length > namespaceIndex) { namespaceIndex = _namespaceMappings[namespaceIndex]; } namespaceUri = namespaceIndex == 0 ? null : Context.NamespaceUris.GetString(namespaceIndex); } // // Expanded Node id is a record extending NodeId. // Namespace, and union of via IdType which represents // the union discriminator. After that we write the // namespace uri and then server index. // WriteNodeId(value.ToNodeId(Context.NamespaceUris, true), namespaceUri ?? string.Empty); WriteString("ServerUri", serverUri); } /// public virtual void WriteStatusCode(string? fieldName, StatusCode value) { _writer.WriteInteger(value.Code); } /// public virtual void WriteDiagnosticInfo(string? fieldName, DiagnosticInfo? value) { WriteDiagnosticInfo(fieldName, value ?? new DiagnosticInfo(), 0); } /// public virtual void WriteQualifiedName(string? fieldName, QualifiedName? value) { var namespaceIndex = value?.NamespaceIndex ?? 0; if (_namespaceMappings != null && _namespaceMappings.Length > namespaceIndex) { namespaceIndex = _namespaceMappings[namespaceIndex]; } var namespaceUri = namespaceIndex == 0 ? null : Context.NamespaceUris.GetString(namespaceIndex); _writer.WriteString(namespaceUri ?? string.Empty); _writer.WriteString(value?.Name ?? string.Empty); } /// public virtual void WriteLocalizedText(string? fieldName, LocalizedText? value) { _writer.WriteString(value?.Locale ?? string.Empty); _writer.WriteString(value?.Text ?? string.Empty); } /// public virtual void WriteVariant(string? fieldName, Variant value) { CheckAndIncrementNestingLevel(); try { // Write union index int unionId; var rank = SchemaRank.Scalar; if (value.Value == null) { unionId = 0; } else { rank = SchemaUtils.GetRank(value.TypeInfo!.ValueRank); unionId = ToUnionId(value.TypeInfo.BuiltInType, rank); } WriteUnion(fieldName, unionId, _ => WriteVariantValue(value, value.TypeInfo?.BuiltInType ?? BuiltInType.Null, rank)); } finally { _nestingLevel--; } static int ToUnionId(BuiltInType builtInType, SchemaRank valueRank) { if (!_variableUnionId.TryGetValue((valueRank, builtInType), out var unionId)) { throw new EncodingException( "Invalid built in type or value rank for variant"); } return unionId; } } /// public virtual void WriteDataValue(string? fieldName, DataValue? value) { // record of fields value ??= new DataValue(); WriteVariant(nameof(value.Value), value.WrappedValue); WriteStatusCode(nameof(value.StatusCode), value.StatusCode); WriteDateTime(nameof(value.SourceTimestamp), value.SourceTimestamp); WriteUInt16(nameof(value.SourcePicoseconds), value.SourcePicoseconds); WriteDateTime(nameof(value.ServerTimestamp), value.ServerTimestamp); WriteUInt16(nameof(value.ServerPicoseconds), value.ServerPicoseconds); } /// public virtual void WriteExtensionObject(string? fieldName, ExtensionObject? value) { value ??= new ExtensionObject(); // Write a raw encoded data type of the schema union WriteUnion(fieldName, 0, _ => WriteEncodedDataType(fieldName, value)); } /// public void EncodeMessage(IEncodeable message) { message.Encode(this); } /// public virtual void WriteEncodeable(string? fieldName, IEncodeable? value, Type? systemType) { CheckAndIncrementNestingLevel(); try { // create a default object if a null object specified. if (value == null && systemType != null) { value = Activator.CreateInstance(systemType) as IEncodeable; } // encode the object. value?.Encode(this); } finally { _nestingLevel--; } } /// public virtual void WriteEnumerated(string? fieldName, Enum? value) { _writer.WriteInteger(Convert.ToInt32(value, CultureInfo.InvariantCulture)); } /// public virtual void WriteEnumerated(string? fieldName, int value) { _writer.WriteInteger(value); } /// public virtual void WriteBooleanArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteBoolean(null, v)); } /// public virtual void WriteSByteArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteSByte(null, v)); } /// public virtual void WriteByteArray(string? fieldName, IList? values) { if (values == null || values.Count == 0) { _writer.WriteInteger(0); return; } if (Context.MaxByteStringLength > 0 && Context.MaxByteStringLength < values.Count) { throw new EncodingException(StatusCodes.BadEncodingLimitsExceeded, $"MaxByteStringLength {Context.MaxByteStringLength} < {values.Count}."); } // Byte array is written as byte string _writer.WriteBytes(values.ToArray()); } /// public virtual void WriteInt16Array(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteInt16(null, v)); } /// public virtual void WriteUInt16Array(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteUInt16(null, v)); } /// public virtual void WriteInt32Array(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteInt32(null, v)); } /// public virtual void WriteUInt32Array(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteUInt32(null, v)); } /// public virtual void WriteInt64Array(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteInt64(null, v)); } /// public virtual void WriteUInt64Array(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteUInt64(null, v)); } /// public virtual void WriteFloatArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteFloat(null, v)); } /// public virtual void WriteDoubleArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteDouble(null, v)); } /// public virtual void WriteStringArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteString(null, v)); } /// public virtual void WriteDateTimeArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteDateTime(null, v)); } /// public virtual void WriteGuidArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteGuid(null, v)); } /// public virtual void WriteGuidArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteGuid(null, v)); } /// public virtual void WriteByteStringArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteByteString(null, v)); } /// public virtual void WriteXmlElementArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteXmlElement(null, v)); } /// public virtual void WriteNodeIdArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteNodeId(null, v)); } /// public virtual void WriteExpandedNodeIdArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteExpandedNodeId(null, v)); } /// public virtual void WriteStatusCodeArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteStatusCode(null, v)); } /// public virtual void WriteDiagnosticInfoArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteDiagnosticInfo(null, v)); } /// public virtual void WriteQualifiedNameArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteQualifiedName(null, v)); } /// public virtual void WriteLocalizedTextArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteLocalizedText(null, v)); } /// public virtual void WriteVariantArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteVariant(null, v)); } /// public virtual void WriteDataValueArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteDataValue(null, v)); } /// public virtual void WriteExtensionObjectArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteExtensionObject(null, v)); } /// public virtual void WriteEncodeableArray(string? fieldName, IList? values, Type? systemType) { WriteArray(fieldName, values, v => WriteEncodeable(null, v, systemType), systemType?.Name); } /// public virtual void WriteEnumeratedArray(string? fieldName, Array? values, Type? systemType) { WriteArray(fieldName, values, v => WriteEnumerated(null, (Enum?)v)); } /// public virtual void WriteEnumeratedArray(string? fieldName, int[] values, Type? enumType) { WriteArray(fieldName, values, v => WriteEnumerated(null, v)); } /// public virtual void WriteArray(string? fieldName, object array, int valueRank, BuiltInType builtInType) { var rank = SchemaUtils.GetRank(valueRank); if (rank == SchemaRank.Collection) { switch (builtInType) { case BuiltInType.Boolean: WriteArray(fieldName, (bool[])array, v => WriteBoolean(null, v)); break; case BuiltInType.SByte: WriteArray(fieldName, (sbyte[])array, v => WriteSByte(null, v)); break; case BuiltInType.Byte: WriteArray(fieldName, (byte[])array, v => WriteByte(null, v)); break; case BuiltInType.Int16: WriteArray(fieldName, (short[])array, v => WriteInt16(null, v)); break; case BuiltInType.UInt16: WriteArray(fieldName, (ushort[])array, v => WriteUInt16(null, v)); break; case BuiltInType.Int32: WriteArray(fieldName, (int[])array, v => WriteInt32(null, v)); break; case BuiltInType.UInt32: WriteArray(fieldName, (uint[])array, v => WriteUInt32(null, v)); break; case BuiltInType.Int64: WriteArray(fieldName, (long[])array, v => WriteInt64(null, v)); break; case BuiltInType.UInt64: WriteArray(fieldName, (ulong[])array, v => WriteUInt64(null, v)); break; case BuiltInType.Float: WriteArray(fieldName, (float[])array, v => WriteFloat(null, v)); break; case BuiltInType.Double: WriteArray(fieldName, (double[])array, v => WriteDouble(null, v)); break; case BuiltInType.DateTime: WriteArray(fieldName, (DateTime[])array, v => WriteDateTime(null, v)); break; case BuiltInType.Guid: WriteArray(fieldName, (Uuid[])array, v => WriteGuid(null, v)); break; case BuiltInType.String: WriteArray(fieldName, (string[])array, v => WriteString(null, v)); break; case BuiltInType.ByteString: WriteArray(fieldName, (byte[][])array, v => WriteByteString(null, v)); break; case BuiltInType.QualifiedName: WriteArray(fieldName, (QualifiedName[])array, v => WriteQualifiedName(null, v)); break; case BuiltInType.LocalizedText: WriteArray(fieldName, (LocalizedText[])array, v => WriteLocalizedText(null, v)); break; case BuiltInType.NodeId: WriteArray(fieldName, (NodeId[])array, v => WriteNodeId(null, v)); break; case BuiltInType.ExpandedNodeId: WriteArray(fieldName, (ExpandedNodeId[])array, v => WriteExpandedNodeId(null, v)); break; case BuiltInType.StatusCode: WriteArray(fieldName, (StatusCode[])array, v => WriteStatusCode(null, v)); break; case BuiltInType.XmlElement: WriteArray(fieldName, (XmlElement[])array, v => WriteXmlElement(null, v)); break; case BuiltInType.Variant: // try to write IEncodeable Array if (array is IEncodeable[] encodeableArray) { WriteEncodeableArray(fieldName, encodeableArray, array.GetType().GetElementType()); return; } WriteVariantArray(null, (Variant[])array); break; case BuiltInType.Enumeration: if (array is Enum[] enums) { WriteArray(fieldName, enums, v => WriteEnumerated(null, v)); break; } else if (array is int[] values) { WriteArray(fieldName, values, v => WriteEnumerated(null, v)); break; } throw new EncodingException( "Unexpected type encountered while encoding an Enumeration Array."); case BuiltInType.ExtensionObject: WriteArray(fieldName, (ExtensionObject[])array, v => WriteExtensionObject(null, v)); break; case BuiltInType.DiagnosticInfo: WriteArray(fieldName, (DiagnosticInfo[])array, v => WriteDiagnosticInfo(null, v)); break; case BuiltInType.DataValue: WriteArray(fieldName, (DataValue[])array, v => WriteDataValue(null, v)); break; default: // try to write IEncodeable Array if (array is IEncodeable[] encodeableArray2) { WriteEncodeableArray(fieldName, encodeableArray2, array.GetType().GetElementType()); return; } if (array == null) { // write zero dimension WriteInt32(null, -1); return; } throw new EncodingException( "Unexpected type encountered while encoding an Array with " + $"BuiltInType: {builtInType}"); } } else if (rank == SchemaRank.Matrix) { /* Multi-dimensional Arrays are encoded as an Int32 Array containing the dimensions followed by * a list of all the values in the Array. The total number of values is equal to the * product of the dimensions. * The number of values is 0 if one or more dimension is less than or equal to 0.*/ var matrix = array as Matrix; if (matrix == null) { if (array is not Array multiArray || multiArray.Rank != valueRank) { // there is no Dimensions to write WriteInt32("Dimensions", -1); return; } matrix = new Matrix(multiArray, builtInType); } // Write the Dimensions WriteInt32Array(null, matrix.Dimensions); switch (matrix.TypeInfo.BuiltInType) { case BuiltInType.Boolean: { var values = (bool[])matrix.Elements; for (var ii = 0; ii < values.Length; ii++) { WriteBoolean(null, values[ii]); } break; } case BuiltInType.SByte: { var values = (sbyte[])matrix.Elements; for (var ii = 0; ii < values.Length; ii++) { WriteSByte(null, values[ii]); } break; } case BuiltInType.Byte: { var values = (byte[])matrix.Elements; for (var ii = 0; ii < values.Length; ii++) { WriteByte(null, values[ii]); } break; } case BuiltInType.Int16: { var values = (short[])matrix.Elements; for (var ii = 0; ii < values.Length; ii++) { WriteInt16(null, values[ii]); } break; } case BuiltInType.UInt16: { var values = (ushort[])matrix.Elements; for (var ii = 0; ii < values.Length; ii++) { WriteUInt16(null, values[ii]); } break; } case BuiltInType.Enumeration: { if (matrix.Elements is Enum[] values) { for (var ii = 0; ii < values.Length; ii++) { WriteEnumerated(null, values[ii]); } break; } } { if (matrix.Elements is int[] values) { for (var ii = 0; ii < values.Length; ii++) { WriteEnumerated(null, values[ii]); } break; } } throw new EncodingException( "Unexpected type encountered while encoding an Enumeration Matrix."); case BuiltInType.Int32: { var values = (int[])matrix.Elements; for (var ii = 0; ii < values.Length; ii++) { WriteInt32(null, values[ii]); } break; } case BuiltInType.UInt32: { var values = (uint[])matrix.Elements; for (var ii = 0; ii < values.Length; ii++) { WriteUInt32(null, values[ii]); } break; } case BuiltInType.Int64: { var values = (long[])matrix.Elements; for (var ii = 0; ii < values.Length; ii++) { WriteInt64(null, values[ii]); } break; } case BuiltInType.UInt64: { var values = (ulong[])matrix.Elements; for (var ii = 0; ii < values.Length; ii++) { WriteUInt64(null, values[ii]); } break; } case BuiltInType.Float: { var values = (float[])matrix.Elements; for (var ii = 0; ii < values.Length; ii++) { WriteFloat(null, values[ii]); } break; } case BuiltInType.Double: { var values = (double[])matrix.Elements; for (var ii = 0; ii < values.Length; ii++) { WriteDouble(null, values[ii]); } break; } case BuiltInType.String: { var values = (string[])matrix.Elements; for (var ii = 0; ii < values.Length; ii++) { WriteString(null, values[ii]); } break; } case BuiltInType.DateTime: { var values = (DateTime[])matrix.Elements; for (var ii = 0; ii < values.Length; ii++) { WriteDateTime(null, values[ii]); } break; } case BuiltInType.Guid: { var values = (Uuid[])matrix.Elements; for (var ii = 0; ii < values.Length; ii++) { WriteGuid(null, values[ii]); } break; } case BuiltInType.ByteString: { var values = (byte[][])matrix.Elements; for (var ii = 0; ii < values.Length; ii++) { WriteByteString(null, values[ii]); } break; } case BuiltInType.XmlElement: { var values = (XmlElement[])matrix.Elements; for (var ii = 0; ii < values.Length; ii++) { WriteXmlElement(null, values[ii]); } break; } case BuiltInType.NodeId: { var values = (NodeId[])matrix.Elements; for (var ii = 0; ii < values.Length; ii++) { WriteNodeId(null, values[ii]); } break; } case BuiltInType.ExpandedNodeId: { var values = (ExpandedNodeId[])matrix.Elements; for (var ii = 0; ii < values.Length; ii++) { WriteExpandedNodeId(null, values[ii]); } break; } case BuiltInType.StatusCode: { var values = (StatusCode[])matrix.Elements; for (var ii = 0; ii < values.Length; ii++) { WriteStatusCode(null, values[ii]); } break; } case BuiltInType.QualifiedName: { var values = (QualifiedName[])matrix.Elements; for (var ii = 0; ii < values.Length; ii++) { WriteQualifiedName(null, values[ii]); } break; } case BuiltInType.LocalizedText: { var values = (LocalizedText[])matrix.Elements; for (var ii = 0; ii < values.Length; ii++) { WriteLocalizedText(null, values[ii]); } break; } case BuiltInType.ExtensionObject: { var values = (ExtensionObject[])matrix.Elements; for (var ii = 0; ii < values.Length; ii++) { WriteExtensionObject(null, values[ii]); } break; } case BuiltInType.DataValue: { var values = (DataValue[])matrix.Elements; for (var ii = 0; ii < values.Length; ii++) { WriteDataValue(null, values[ii]); } break; } case BuiltInType.Variant: { if (matrix.Elements is Variant[] variants) { for (var ii = 0; ii < variants.Length; ii++) { WriteVariant(null, variants[ii]); } break; } // try to write IEncodeable Array if (matrix.Elements is IEncodeable[] encodeableArray) { for (var ii = 0; ii < encodeableArray.Length; ii++) { WriteEncodeable(null, encodeableArray[ii], null); } break; } if (matrix.Elements is object[] objects) { for (var ii = 0; ii < objects.Length; ii++) { WriteVariant(null, new Variant(objects[ii])); } break; } throw new EncodingException( "Unexpected type encountered while encoding a Matrix."); } case BuiltInType.DiagnosticInfo: { var values = (DiagnosticInfo[])matrix.Elements; for (var ii = 0; ii < values.Length; ii++) { WriteDiagnosticInfo(null, values[ii]); } break; } default: { // try to write IEncodeable Array if (matrix.Elements is IEncodeable[] encodeableArray) { for (var ii = 0; ii < encodeableArray.Length; ii++) { WriteEncodeable(null, encodeableArray[ii], null); } break; } throw new EncodingException( "Unexpected type encountered while encoding a Matrix " + $"with BuiltInType: {matrix.TypeInfo.BuiltInType}"); } } } } /// public virtual void WriteNull(string? fieldName, T? value) { } /// /// Write nullable /// /// /// /// /// protected virtual void WriteNullable(string? fieldName, T? value, Action writer) where T : class { // Union index, first is "null" WriteUnion(fieldName, value == null ? 0 : 1, id => { switch (id) { case 0: WriteNull(null, value); break; default: Debug.Assert(value != null); writer(null, value); break; } }); } /// /// Write union /// /// /// /// public virtual void WriteUnion(string? fieldName, int index, Action writer) { StartUnion(index); writer(index); EndUnion(); } /// /// Start union /// /// protected virtual void StartUnion(int index) { _writer.WriteInteger(index); } /// protected virtual void EndUnion() { } /// /// Write encoded data type /// /// /// /// protected virtual void WriteEncodedDataType(string? fieldName, ExtensionObject value) { // write the type id. var typeId = value.TypeId; var body = value.Body; if (body is IEncodeable encodeable) { if (body is IJsonEncodeable je) { typeId = je.JsonEncodingId; body = encodeable.AsJson(Context); } else if (value.Encoding == ExtensionObjectEncoding.Xml) { typeId = encodeable.XmlEncodingId; body = encodeable.AsXmlElement(Context); } else { typeId = encodeable.BinaryEncodingId; body = encodeable.AsBinary(Context); } } var localTypeId = ExpandedNodeId.ToNodeId(typeId, Context.NamespaceUris); if (NodeId.IsNull(localTypeId) && !NodeId.IsNull(typeId)) { if (value.Body is IEncodeable e) { throw new EncodingException( $"Cannot encode bodies of type '{e.GetType().FullName}' in " + $"ExtensionObject unless the NamespaceUri ({typeId.NamespaceUri}) " + "is in the encoder's NamespaceTable."); } localTypeId = NodeId.Null; } switch (body) { case byte[]: break; case XmlElement xml: body = Encoding.UTF8.GetBytes( xml.OuterXml ?? string.Empty); break; case string str: body = Encoding.UTF8.GetBytes(str); break; default: Debug.Fail("Should not get here"); break; } // Write a raw encoded data type of the schema union WriteNodeId("TypeId", localTypeId); WriteByteString("Body", (byte[])body); } /// /// Writes a DiagnosticInfo to the stream. /// Ignores InnerDiagnosticInfo field if the nesting level /// is exceeded. /// /// /// /// protected virtual void WriteDiagnosticInfoNullable(string? fieldName, DiagnosticInfo? value, int depth) { if (depth >= DiagnosticInfo.MaxInnerDepth) { value = null; } WriteNullable(fieldName, value, (f, v) => WriteDiagnosticInfo(f, v, depth)); } /// /// Write as non nullable /// /// /// /// protected virtual void WriteDiagnosticInfo(string? fieldName, DiagnosticInfo value, int depth) { CheckAndIncrementNestingLevel(); try { WriteInt32(nameof(value.SymbolicId), value.SymbolicId); WriteInt32(nameof(value.NamespaceUri), value.NamespaceUri); WriteInt32(nameof(value.Locale), value.Locale); WriteInt32(nameof(value.LocalizedText), value.LocalizedText); WriteString(nameof(value.AdditionalInfo), value.AdditionalInfo); WriteStatusCode(nameof(value.InnerStatusCode), value.InnerStatusCode); WriteDiagnosticInfoNullable(nameof(value.InnerDiagnosticInfo), value.InnerDiagnosticInfo, depth + 1); } finally { _nestingLevel--; } } /// /// Writes an Variant value to the stream. /// /// /// /// protected void WriteVariantValue(Variant value, BuiltInType builtInType, SchemaRank valueRank) { var valueToEncode = value.Value; if (valueToEncode == null) { WriteNull(builtInType, valueRank); } else if (valueRank == SchemaRank.Scalar) { WriteScalar(builtInType, valueToEncode); } else if (valueToEncode is not Matrix m) { Debug.Assert(valueRank == SchemaRank.Collection); WriteArray(builtInType, valueToEncode); } else { Debug.Assert(valueRank == SchemaRank.Matrix); WriteMatrix("Body", m); } } /// /// Lookup /// internal static readonly FrozenDictionary<(SchemaRank, BuiltInType), int> _variableUnionId = BaseAvroDecoder.VariantUnionFieldIds .ToArray() .Select((f, i) => System.Collections.Generic.KeyValuePair.Create(f, i)) .ToFrozenDictionary(); /// /// Write null value of variant /// /// /// protected virtual void WriteNull(BuiltInType builtInType, SchemaRank valueRank) { // Nothing to do } /// /// Write array of variant /// /// /// /// protected virtual void WriteArray(BuiltInType builtInType, object valueToEncode) { static T[] Cast(object objects) { if (objects is T[] r) { return r; } if (objects is object[] o) { return o.Cast().ToArray(); } if (objects is T t) { return new[] { t }; } return Array.Empty(); } switch (builtInType) { case BuiltInType.Boolean: WriteBooleanArray(null, Cast(valueToEncode)); break; case BuiltInType.SByte: WriteSByteArray(null, Cast(valueToEncode)); break; case BuiltInType.Byte: WriteByteArray(null, Cast(valueToEncode)); break; case BuiltInType.Int16: WriteInt16Array(null, Cast(valueToEncode)); break; case BuiltInType.UInt16: WriteUInt16Array(null, Cast(valueToEncode)); break; case BuiltInType.Int32: WriteInt32Array(null, Cast(valueToEncode)); break; case BuiltInType.UInt32: WriteUInt32Array(null, Cast(valueToEncode)); break; case BuiltInType.Int64: WriteInt64Array(null, Cast(valueToEncode)); break; case BuiltInType.UInt64: WriteUInt64Array(null, Cast(valueToEncode)); break; case BuiltInType.Float: WriteFloatArray(null, Cast(valueToEncode)); break; case BuiltInType.Double: WriteDoubleArray(null, Cast(valueToEncode)); break; case BuiltInType.String: WriteStringArray(null, Cast(valueToEncode)); break; case BuiltInType.DateTime: WriteDateTimeArray(null, Cast(valueToEncode)); break; case BuiltInType.Guid: WriteGuidArray(null, Cast(valueToEncode)); break; case BuiltInType.ByteString: WriteByteStringArray(null, Cast(valueToEncode)); break; case BuiltInType.XmlElement: WriteXmlElementArray(null, Cast(valueToEncode)); break; case BuiltInType.NodeId: WriteNodeIdArray(null, Cast(valueToEncode)); break; case BuiltInType.ExpandedNodeId: WriteExpandedNodeIdArray(null, Cast(valueToEncode)); break; case BuiltInType.StatusCode: WriteStatusCodeArray(null, Cast(valueToEncode)); break; case BuiltInType.QualifiedName: WriteQualifiedNameArray(null, Cast(valueToEncode)); break; case BuiltInType.LocalizedText: WriteLocalizedTextArray(null, Cast(valueToEncode)); break; case BuiltInType.ExtensionObject: WriteExtensionObjectArray(null, Cast(valueToEncode)); break; case BuiltInType.DataValue: WriteDataValueArray(null, Cast(valueToEncode)); break; case BuiltInType.Enumeration: // Check whether the value to encode is int array. if (valueToEncode is int[] ints) { WriteEnumeratedArray(null, ints, null); break; } var enums = Cast(valueToEncode); WriteEnumeratedArray(null, enums, null); break; case BuiltInType.Variant: if (valueToEncode is Variant[] variants) { WriteVariantArray(null, variants); break; } if (valueToEncode is object[] objects) { WriteVariantArray(null, objects.Select(v => new Variant(v)).ToArray()); break; } throw new EncodingException( $"Unexpected type encountered while encoding array: {valueToEncode.GetType()}"); case BuiltInType.DiagnosticInfo: WriteDiagnosticInfoArray(null, Cast(valueToEncode)); break; default: throw new EncodingException( $"Unexpected type encountered while encoding a Variant: {builtInType}"); } } /// /// Write scalar value /// /// /// /// protected virtual void WriteScalar(BuiltInType builtInType, object valueToEncode) { switch (builtInType) { case BuiltInType.Null: WriteNull(null, valueToEncode); return; case BuiltInType.Boolean: WriteBoolean(null, (bool)valueToEncode); return; case BuiltInType.SByte: WriteSByte(null, (sbyte)valueToEncode); return; case BuiltInType.Byte: WriteByte(null, (byte)valueToEncode); return; case BuiltInType.Int16: WriteInt16(null, (short)valueToEncode); return; case BuiltInType.UInt16: WriteUInt16(null, (ushort)valueToEncode); return; case BuiltInType.Int32: WriteInt32(null, (int)valueToEncode); return; case BuiltInType.UInt32: WriteUInt32(null, (uint)valueToEncode); return; case BuiltInType.Int64: WriteInt64(null, (long)valueToEncode); return; case BuiltInType.UInt64: WriteUInt64(null, (ulong)valueToEncode); return; case BuiltInType.Float: WriteFloat(null, (float)valueToEncode); return; case BuiltInType.Double: WriteDouble(null, (double)valueToEncode); return; case BuiltInType.String: WriteString(null, (string)valueToEncode); return; case BuiltInType.DateTime: WriteDateTime(null, (DateTime)valueToEncode); return; case BuiltInType.Guid: WriteGuid(null, (Uuid)valueToEncode); return; case BuiltInType.ByteString: WriteByteString(null, (byte[])valueToEncode); return; case BuiltInType.XmlElement: WriteXmlElement(null, (XmlElement)valueToEncode); return; case BuiltInType.NodeId: WriteNodeId(null, (NodeId)valueToEncode); return; case BuiltInType.ExpandedNodeId: WriteExpandedNodeId(null, (ExpandedNodeId)valueToEncode); return; case BuiltInType.StatusCode: WriteStatusCode(null, (StatusCode)valueToEncode); return; case BuiltInType.QualifiedName: WriteQualifiedName(null, (QualifiedName)valueToEncode); return; case BuiltInType.LocalizedText: WriteLocalizedText(null, (LocalizedText)valueToEncode); return; case BuiltInType.ExtensionObject: WriteExtensionObject(null, (ExtensionObject)valueToEncode); return; case BuiltInType.DataValue: WriteDataValue(null, (DataValue)valueToEncode); return; case BuiltInType.Enumeration: WriteEnumerated(null, Convert.ToInt32(valueToEncode, CultureInfo.InvariantCulture)); return; //case BuiltInType.DiagnosticInfo: // WriteDiagnosticInfo((DiagnosticInfo)valueToEncode); // return; } throw new EncodingException( $"Unexpected type encountered while encoding a Variant: {builtInType}"); } /// public virtual void WriteArray(string? fieldName, IList? values, Action writer, string? typeName = null) { if (values == null || values.Count == 0) { _writer.WriteInteger(0); } else if (Context.MaxArrayLength > 0 && Context.MaxArrayLength < values.Count) { throw new EncodingException(StatusCodes.BadEncodingLimitsExceeded, $"MaxArrayLength {Context.MaxArrayLength} < {values.Count}."); } else { _writer.WriteInteger(values.Count); foreach (var value in values) { writer(value); } } // Array block ends with 0 length _writer.WriteInteger(0); } /// protected virtual void WriteArray(string? fieldName, Array? values, Action writer) { if (values == null || values.Length == 0) { _writer.WriteInteger(0); } else if (Context.MaxArrayLength > 0 && Context.MaxArrayLength < values.Length) { throw new EncodingException(StatusCodes.BadEncodingLimitsExceeded, $"MaxArrayLength {Context.MaxArrayLength} < {values.Length}."); } else { // write length _writer.WriteInteger(values.Length); for (var index = 0; index < values.Length; index++) { writer(values.GetValue(index)); } } // Array block ends with 0 length _writer.WriteInteger(0); } /// protected virtual void WriteMatrix(string? fieldName, IList? values, int[] dimensions, Action writer, string? typeName = null) { WriteArray(nameof(Matrix.Dimensions), dimensions, v => WriteInt32(null, v)); WriteArray(kDefaultFieldName, values, writer, typeName); } /// protected virtual void WriteMatrix(string? fieldName, Matrix matrix, string? typeName = null) { WriteArray(nameof(Matrix.Dimensions), matrix.Dimensions, v => WriteInt32(null, v)); WriteArray(kDefaultFieldName, matrix.Elements, matrix.TypeInfo.ValueRank, matrix.TypeInfo.BuiltInType); } /// /// Detect full name of the encodeable object /// /// /// /// /// /// protected string? GetFullNameOfEncodeable(IEncodeable? value, Type? systemType, out string? typeName, out ExpandedNodeId? typeId) { typeName = systemType?.Name ?? value?.GetType().Name; typeId = value?.TypeId; if (string.IsNullOrEmpty(typeName)) { return null; } var fullName = typeId?.GetFullName(typeName, Context); if (string.IsNullOrEmpty(fullName) && systemType != null) { value = (IEncodeable?)Activator.CreateInstance(systemType); typeId ??= value?.TypeId; fullName = typeId?.GetFullName(typeName, Context); } return fullName; } /// /// Test and increment the nesting level. /// /// private void CheckAndIncrementNestingLevel() { if (_nestingLevel > Context.MaxEncodingNestingLevels) { throw new EncodingException(StatusCodes.BadEncodingLimitsExceeded, $"Maximum nesting level of {Context.MaxEncodingNestingLevels} was exceeded."); } _nestingLevel++; } /// /// Default name when field name is not provided /// protected const string kDefaultFieldName = "Value"; private readonly AvroBinaryWriter _writer; private ushort[]? _namespaceMappings; private ushort[]? _serverMappings; private uint _nestingLevel; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/ConsoleWriter.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Furly; using Furly.Extensions.Messaging; using Furly.Extensions.Storage; using Microsoft.Extensions.Options; using System; using System.Buffers; using System.Collections.Generic; using System.IO; using System.Text.Json; using System.Threading; using System.Threading.Tasks; /// /// Debug output writer /// public sealed class ConsoleWriter : IFileWriter, IDisposable { /// public bool SupportsContentType(string contentType) { return _options.Value.Enabled; } /// /// Create writer /// /// public ConsoleWriter(IOptions options) { _options = options; } /// public async ValueTask WriteAsync(string fileName, DateTimeOffset timestamp, IEnumerable> buffers, IReadOnlyDictionary metadata, IEventSchema? schema, string contentType, CancellationToken ct = default) { Stream fs; if (fileName.Contains("stdout", StringComparison.InvariantCulture)) { fs = _stdout ??= Console.OpenStandardOutput(); } else if (fileName.Contains("stderr", StringComparison.InvariantCulture)) { fs = _stderr ??= Console.OpenStandardError(); } else { return; } switch (contentType) { case ContentMimeType.Json: foreach (var buffer in buffers) { await fs.WriteAsync(GetIndentedJson(buffer), ct).ConfigureAwait(false); } break; default: foreach (var buffer in buffers) { foreach (var memory in buffer) { await fs.WriteAsync(memory, ct).ConfigureAwait(false); } } break; } static ReadOnlyMemory GetIndentedJson(ReadOnlySequence buffer) { var reader = new Utf8JsonReader(buffer); var json = JsonSerializer.Deserialize(ref reader); return JsonSerializer.SerializeToUtf8Bytes(json, kIndented); } } /// public void Dispose() { _stdout?.Dispose(); _stderr?.Dispose(); } private static readonly JsonSerializerOptions kIndented = new() { WriteIndented = true }; private readonly IOptions _options; private Stream? _stdout; private Stream? _stderr; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/ConsoleWriterOptions.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { /// /// Options /// public sealed class ConsoleWriterOptions { /// /// Whether to write debug /// public bool Enabled { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/ContentType.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { /// /// Content types /// public static class ContentType { /// /// Json+Gzip encoding /// public const string JsonGzip = "application/json+gzip"; /// /// Avro encoding /// public const string Avro = "application/avro"; /// /// Avro+Gzip encoding /// public const string AvroGzip = "application/avro+gzip"; /// /// OPC UA json encoding as per OPC UA part 6 /// public const string UaJson = "application/ua+json"; /// /// OPC UA json encoding but non reversible /// public const string UaNonReversibleJson = "application/ua+json+nr"; /// /// OPC UA UADP binary encoding /// public const string Uadp = "application/opcua+uadp"; /// /// For backwards compatibility with legacy publisher /// public const string UaLegacyPublisher = "application/opcua+uajson"; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/DecodingException.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Opc.Ua; using System; /// [Serializable] public sealed class DecodingException : ServiceResultException { /// /// Additional information /// public string? AdditionalInformation { get; set; } /// public DecodingException(string message) : base(StatusCodes.BadDecodingError, message) { } /// public DecodingException(string message, Exception innerException) : base(StatusCodes.BadDecodingError, message, innerException) { } /// public DecodingException(string message, string additionalInformation) : base(StatusCodes.BadDecodingError, message) { AdditionalInformation = additionalInformation; } /// public DecodingException(uint statusCode, string message) : base(statusCode, message) { } /// public override string ToString() { var message = "Failed to decode. " + base.ToString(); if (AdditionalInformation != null) { message += "\n" + AdditionalInformation; } return message; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/EncodingException.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Opc.Ua; using System; /// [Serializable] public sealed class EncodingException : ServiceResultException { /// /// Additional information /// public string? AdditionalInformation { get; set; } /// public EncodingException(string message) : base(StatusCodes.BadEncodingError, message) { } /// public EncodingException(string message, Exception innerException) : base(StatusCodes.BadEncodingError, message, innerException) { } /// public EncodingException(string message, string additionalInformation) : base(StatusCodes.BadEncodingError, message) { AdditionalInformation = additionalInformation; } /// public EncodingException(uint statusCode, string message) : base(statusCode, message) { } /// public override string ToString() { var message = "Failed to encode. " + base.ToString(); if (AdditionalInformation != null) { message += "\n" + AdditionalInformation; } return message; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Extensions/EncodeableEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Opc.Ua.Extensions { using Azure.IIoT.OpcUa.Encoders; using System.IO; using System.Text; using System.Xml; /// /// Encodeable extensions /// public static class EncodeableEx { /// /// Convert encodeable to xml /// /// /// /// public static XmlElement? AsXmlElement(this IEncodeable encodeable, IServiceMessageContext context) { // Bug in stack, do not dispose as we close below #pragma warning disable CA2000 // Dispose objects before losing scope var encoder = new XmlEncoder(context); #pragma warning restore CA2000 // Dispose objects before losing scope encoder.WriteExtensionObjectBody(encodeable); var document = new XmlDocument { InnerXml = encoder.CloseAndReturnText() }; return document.DocumentElement; } /// /// Convert encodeable to binary /// /// /// /// public static byte[] AsBinary(this IEncodeable encodeable, IServiceMessageContext context) { using var stream = new MemoryStream(); using (var encoder = new BinaryEncoder(stream, context, true)) { encodeable.Encode(encoder); } return stream.ToArray(); } /// /// Convert encodeable to json /// /// /// /// public static string AsJson(this IEncodeable encodeable, IServiceMessageContext context) { using var stream = new MemoryStream(); using (var encoder = new JsonEncoderEx(stream, context, leaveOpen: true)) { encodeable.Encode(encoder); } return Encoding.UTF8.GetString(stream.ToArray()); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Extensions/Extensions.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Opc.Ua.Extensions { using Azure.IIoT.OpcUa.Publisher.Models; using UaStructureType = StructureType; /// /// Pub sub related opc ua extensions /// public static class Extensions { /// /// Convert structure type /// /// /// public static UaStructureType ToStackType(this StructureType? type) { switch (type) { case StructureType.StructureWithOptionalFields: return UaStructureType.StructureWithOptionalFields; case StructureType.Union: return UaStructureType.Union; case StructureType.StructureWithSubtypedValues: return UaStructureType.StructureWithSubtypedValues; case StructureType.UnionWithSubtypedValues: return UaStructureType.UnionWithSubtypedValues; default: return UaStructureType.Structure; } } /// /// Convert structure type /// /// /// public static StructureType ToServiceType(this UaStructureType type) { switch (type) { case UaStructureType.StructureWithOptionalFields: return StructureType.StructureWithOptionalFields; case UaStructureType.Union: return StructureType.Union; case UaStructureType.StructureWithSubtypedValues: return StructureType.StructureWithSubtypedValues; case UaStructureType.UnionWithSubtypedValues: return StructureType.UnionWithSubtypedValues; default: return StructureType.Structure; } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Extensions/JsonSerializerUtcEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Opc.Ua; using System; using System.Globalization; /// /// Json serializer settings extensions /// public static class JsonSerializerUtcEx { /// /// Constant for OpcUa JSON encoded DateTime.MinValue. /// public const string OpcUaDateTimeMinValue = "0001-01-01T00:00:00Z"; /// /// Constant for OpcUa JSON encoded DateTime.MaxValue. /// public const string OpcUaDateTimeMaxValue = "9999-12-31T23:59:59Z"; /// /// DateTime value of: 9999-12-31T23:59:59Z /// private static readonly DateTime kDateTimeMaxJsonValue = new(3155378975990000000); /// /// Convert to OpcUa JSON Encoded Utc string. /// /// public static string ToOpcUaJsonEncodedTime(this DateTime dateTime) { if (dateTime <= DateTime.MinValue) { return OpcUaDateTimeMinValue; } else if (dateTime >= kDateTimeMaxJsonValue) { return OpcUaDateTimeMaxValue; } else { return dateTime.ToUniversalTime().ToString("yyyy-MM-dd'T'HH:mm:ss.FFFFFFFK", CultureInfo.InvariantCulture); } } /// /// Convert DataValue timestamps to OpcUa Encoded Utc. /// /// public static DataValue ToOpcUaUniversalTime(this DataValue dataValue) { dataValue.SourceTimestamp = dataValue.SourceTimestamp.ToOpcUaUniversalTime(); dataValue.ServerTimestamp = dataValue.ServerTimestamp.ToOpcUaUniversalTime(); return dataValue; } /// /// Converter from OpcUa encoded Utc to DateTime. /// The result is DateTime.MinValue, DateTime.MaxValue or /// the Utc kind. /// /// public static DateTime ToOpcUaUniversalTime(this DateTime dateTime) { if (dateTime <= DateTime.MinValue) { return DateTime.MinValue; } else if (dateTime >= kDateTimeMaxJsonValue) { return DateTime.MaxValue; } else { if (dateTime.Kind != DateTimeKind.Utc) { return dateTime.ToUniversalTime(); } } return dateTime; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Extensions/LocalizedTextEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Opc.Ua.Extensions { /// /// Localized text extensions /// public static class LocalizedTextEx { /// /// Convert localized text to string /// /// /// public static string? AsString(this LocalizedText? value) { if (value == null || value.Text == null) { return null; } var full = value.Text; if (!string.IsNullOrEmpty(value.Locale)) { return full + "@" + value.Locale; } return full; } /// /// Convert string to localized text /// /// /// public static LocalizedText ToLocalizedText(this string str) { if (string.IsNullOrEmpty(str)) { return new LocalizedText(string.Empty); } var delim = str.LastIndexOf('@'); if (delim == -1) { return new LocalizedText(str); } return new LocalizedText(str[(delim + 1)..], str[..delim]); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Extensions/NodeIdEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Opc.Ua.Extensions { using Azure.IIoT.OpcUa.Encoders.Utils; using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Text; using System.Text.RegularExpressions; /// /// Node id extensions /// public static class NodeIdEx { /// /// Creates an expanded node id from node id. /// /// /// /// /// public static ExpandedNodeId ToExpandedNodeId(this NodeId nodeId, NamespaceTable? namespaces) { if (NodeId.IsNull(nodeId)) { return ExpandedNodeId.Null; } string? ns = null; if (nodeId.NamespaceIndex > 0) { ArgumentNullException.ThrowIfNull(namespaces); ns = namespaces.GetString(nodeId.NamespaceIndex); } return new ExpandedNodeId(nodeId.Identifier, nodeId.NamespaceIndex, ns, 0); } /// /// Convert an expanded node id to a node id. /// /// /// /// /// /// /// public static NodeId ToNodeId(this ExpandedNodeId? nodeId, NamespaceTable namespaces, bool allowUnknownNamespace = false) { if (nodeId?.IsNull != false) { return NodeId.Null; } if (nodeId.NamespaceIndex > 0 && namespaces == null) { throw new ArgumentNullException(nameof(namespaces)); } int index = nodeId.NamespaceIndex; if (!string.IsNullOrEmpty(nodeId.NamespaceUri)) { index = namespaces.GetIndex(nodeId.NamespaceUri); if (index < 0) { if (!allowUnknownNamespace) { throw new ArgumentException( $"Namespace '{nodeId.NamespaceUri}' was not found in NamespaceTable.", nameof(nodeId)); } index = 0; } } return new NodeId(nodeId.Identifier, (ushort)index); } /// /// Returns a uri that identifies the node id uniquely. If the server /// uri information is provided, and the it contains a server name at /// index 0, the node id will be formatted as an expanded node id uri /// (see below). Otherwise, the resource is the namespace and not the /// server. /// /// /// /// /// public static string? AsString(this NodeId nodeId, IServiceMessageContext context, NamespaceFormat namespaceFormat) { if (NodeId.IsNull(nodeId)) { return null; } return nodeId .ToExpandedNodeId(context.NamespaceUris) .AsString(context, namespaceFormat); } /// /// Returns a node uri from an expanded node id. /// /// /// /// /// public static string? AsString(this ExpandedNodeId nodeId, IServiceMessageContext context, NamespaceFormat namespaceFormat) { if (NodeId.IsNull(nodeId)) { return null; } var nsUri = nodeId.NamespaceUri; if (string.IsNullOrEmpty(nsUri) && (namespaceFormat == NamespaceFormat.ExpandedWithNamespace0 || nodeId.NamespaceIndex != 0)) { nsUri = context.NamespaceUris.GetString(nodeId.NamespaceIndex); if (string.IsNullOrEmpty(nsUri)) { nsUri = null; } } string? srvUri = null; if (context.ServerUris != null && (namespaceFormat == NamespaceFormat.ExpandedWithNamespace0 || nodeId.ServerIndex != 0)) { srvUri = context.ServerUris.GetString(nodeId.ServerIndex); if (string.IsNullOrEmpty(srvUri)) { srvUri = null; } } switch (namespaceFormat) { default: if (nsUri != null && !Uri.IsWellFormedUriString(nsUri, UriKind.Absolute)) { // Fall back to nsu= format - but strip indexes return FormatNodeIdExpanded(nsUri, 0u, nodeId.IdType, nodeId.Identifier); } return FormatNodeIdUri(nsUri, srvUri, nodeId.IdType, nodeId.Identifier); case NamespaceFormat.Expanded: case NamespaceFormat.ExpandedWithNamespace0: return FormatNodeIdExpanded(nsUri, nodeId.ServerIndex, nodeId.IdType, nodeId.Identifier); case NamespaceFormat.Index: return new ExpandedNodeId(nodeId.Identifier, nodeId.NamespaceIndex, null, nodeId.ServerIndex).ToString(); } } /// /// Returns a node from a string /// /// /// /// public static NodeId ToNodeId(this string? value, IServiceMessageContext context) { if (value == null) { return NodeId.Null; } var parts = value.Split(';'); if (parts.Any(s => s.StartsWith("ns=", StringComparison.CurrentCulture))) { return NodeId.Parse(value); } if (parts.Any(s => s.StartsWith("nsu=", StringComparison.CurrentCulture))) { return ExpandedNodeId.Parse(value).ToNodeId(context.NamespaceUris); } var identifier = ParseNodeIdUri(value, out var nsUri, out var srvUri); return new NodeId(identifier, context.NamespaceUris.GetIndexOrAppend(nsUri)); } /// /// Returns an expanded node id from a node uri. /// /// /// /// public static ExpandedNodeId ToExpandedNodeId(this string? value, IServiceMessageContext context) { if (value == null) { return ExpandedNodeId.Null; } var parts = value.Split(';'); if (parts.Any(s => s.StartsWith("ns=", StringComparison.CurrentCulture) || s.StartsWith("nsu=", StringComparison.CurrentCulture))) { return ExpandedNodeId.Parse(value); } var identifier = ParseNodeIdUri(value, out var nsUri, out var srvUri); // Allocate entry in context if does not exist var nsIndex = context.NamespaceUris.GetIndexOrAppend(nsUri); if (!string.IsNullOrEmpty(srvUri)) { return new ExpandedNodeId(identifier, 0, nsUri == Namespaces.OpcUa ? null : nsUri, context.ServerUris.GetIndexOrAppend(srvUri)); } return new ExpandedNodeId(identifier, 0, nsUri == Namespaces.OpcUa ? null : nsUri, 0); } /// /// Format node id components into a uri string /// /// /// /// /// /// /// private static string FormatNodeIdUri(string? nsUri, string? srvUri, IdType idType, object? identifier) { var buffer = new StringBuilder(); if (nsUri != null) { // Append node id as fragment buffer = buffer.Append(nsUri) .Append('#'); } switch (idType) { case IdType.Numeric: if (srvUri == null && nsUri == null && TryGetDataTypeName(identifier, out var typeName)) { // For readability use data type name here if possible return typeName; } buffer = buffer.Append("i="); if (identifier == null) { buffer.Append('0'); // null break; } buffer = buffer.AppendFormat(CultureInfo.InvariantCulture, "{0}", identifier); break; case IdType.String: buffer = buffer.Append("s="); if (identifier == null) { break; // null } buffer = buffer.Append(identifier.ToString()?.UrlEncode()); break; case IdType.Guid: buffer = buffer.Append("g="); if (identifier == null) { buffer.Append(Guid.Empty); // null break; } buffer = buffer.Append(((Guid)identifier).ToString("D").UrlEncode()); break; case IdType.Opaque: buffer = buffer.Append("b="); if (identifier == null) { break; // null } buffer = buffer.AppendFormat(CultureInfo.InvariantCulture, "{0}", ((byte[])identifier).ToBase64String().UrlEncode()); break; default: throw new FormatException($"Node id type {idType} is unknown!"); } if (srvUri != null) { // Pack server in front of identifier buffer = buffer.Append("&srv=") .Append(srvUri); } return buffer.ToString(); } private static string FormatNodeIdExpanded(string? nsUri, uint serverIndex, IdType idType, object? identifier) { var buffer = new StringBuilder(); if (serverIndex != 0) { buffer = buffer .Append("svr=") .Append(serverIndex) .Append(';'); } if (!string.IsNullOrEmpty(nsUri)) { buffer = buffer .Append("nsu=") .Append(nsUri.Replace(";", "%3b", StringComparison.Ordinal)) .Append(';'); } switch (idType) { case IdType.Numeric: buffer = buffer.Append("i=") .Append(identifier == null ? 0 : (uint)identifier); break; case IdType.Guid: buffer = buffer.Append("g=") .Append(identifier == null ? Guid.Empty : (Guid)identifier); break; case IdType.Opaque: buffer = buffer.Append("b=") .Append(identifier == null ? string.Empty : Convert.ToBase64String((byte[])identifier)); break; default: buffer = buffer.Append("s=") .Append(identifier == null ? string.Empty : identifier.ToString()); break; } return buffer.ToString(); } /// /// Parses a node uri and returns components. The format of the uri is /// namespaceuri(?srv=serverurn)#idtype_idasstring. Avoid url /// encoding due to the problem of storage encoding again. /// /// /// /// /// /// private static object? ParseNodeIdUri(string value, out string nsUri, out string? srvUri) { // Get resource uri if (!Uri.TryCreate(value, UriKind.Absolute, out var uri)) { // Not a absolute uri, try to mitigate a potentially nonstandard namespace string const string sepPattern = @"(.+)#([isgb]{1}\=.*)"; #pragma warning disable SYSLIB1045 // Convert to 'GeneratedRegexAttribute'. var match = Regex.Match(value, sepPattern); #pragma warning restore SYSLIB1045 // Convert to 'GeneratedRegexAttribute'. if (match.Success) { nsUri = match.Groups[1].Value; value = match.Groups[2].Value; } else { nsUri = Namespaces.OpcUa; } } else { if (string.IsNullOrEmpty(uri.Fragment)) { throw new FormatException("Bad fragment - should contain identifier."); } var idStart = value.IndexOf('#', StringComparison.Ordinal); nsUri = idStart >= 0 ? value[..idStart] : uri.NoQueryAndFragment().AbsoluteUri; value = uri.Fragment.TrimStart('#'); } var and = value?.IndexOf('&', StringComparison.Ordinal) ?? -1; if (and != -1) { var remainder = value![and..]; // See if the query contains the server identfier if (remainder.StartsWith("&srv=", StringComparison.Ordinal)) { // The uri denotes an id in a namespace on a server srvUri = remainder[5..]; } else { throw new FormatException($"{value} does not contain ?srv="); } return ParseIdentifier(value[..and]); } srvUri = null; return ParseIdentifier(value); } /// /// Parse identfier from string /// /// /// private static object? ParseIdentifier(string? text) { if (text == null) { return null; } if (text.Length > 1 && text[1] is '=' or '_') { try { return ParseIdentifier(text[0], text[2..]); } catch (FormatException) { } } // Try to retrieve data type identifier from text if (TryGetDataTypeId(text, out var id)) { return id; } return null; } /// /// Parse identfier from string /// /// /// /// /// private static object ParseIdentifier(char type, string text) { switch (type) { case 'i': try { return Convert.ToUInt32(text.UrlDecode(), CultureInfo.InvariantCulture); } catch { return Convert.ToUInt32(text, CultureInfo.InvariantCulture); } case 'b': try { return Convert.FromBase64String(text.UrlDecode()); } catch { return Convert.FromBase64String(text); } case 'g': if (!Guid.TryParse(text.UrlDecode(), out var guid)) { return Guid.Parse(text); } return guid; case 's': return text.UrlDecode(); } throw new FormatException($"{type} is not a known node id type"); } /// /// Returns a data type id for the name /// /// /// /// private static bool TryGetDataTypeId(string text, out uint id) { if (Enum.TryParse(text, true, out var type)) { id = (uint)type; return true; } if (TypeMaps.DataTypes.Value.TryGetIdentifier(text, out id)) { return true; } return false; } /// /// Returns data type name for identifier /// /// /// /// private static bool TryGetDataTypeName(object? identifier, [NotNullWhen(true)] out string? name) { name = null; try { if (identifier is not uint uid) { return false; } if (uid <= int.MaxValue) { var id = (int)uid; if (Enum.IsDefined(typeof(BuiltInType), id)) { name = Enum.GetName(typeof(BuiltInType), id); if (StringComparer.OrdinalIgnoreCase.Equals(name, nameof(BuiltInType.Null))) { name = null; } } } if (!string.IsNullOrEmpty(name)) { return true; } if (TypeMaps.DataTypes.Value.TryGetBrowseName(uid, out name) && StringComparer.OrdinalIgnoreCase.Equals(name, nameof(BuiltInType.Null))) { name = null; } return !string.IsNullOrEmpty(name); } catch { return false; } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Extensions/QualifiedNameEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Opc.Ua.Extensions { using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.Text; /// /// Qualified name extensions /// public static class QualifiedNameEx { /// /// Returns a uri that identifies the qualified name uniquely. /// /// /// /// /// public static string AsString(this QualifiedName qn, IServiceMessageContext context, NamespaceFormat namespaceFormat) { if (qn == null || qn == QualifiedName.Null) { return string.Empty; } var qnName = qn.Name ?? string.Empty; var buffer = new StringBuilder(); if (namespaceFormat == NamespaceFormat.ExpandedWithNamespace0 || qn.NamespaceIndex != 0 || qnName.Contains(':', StringComparison.Ordinal)) { switch (namespaceFormat) { default: var nsUri = context.NamespaceUris.GetString(qn.NamespaceIndex); if (!string.IsNullOrEmpty(nsUri)) { buffer.Append(nsUri); // Append name as fragment if (!string.IsNullOrEmpty(qnName)) { buffer.Append('#'); } } break; case NamespaceFormat.ExpandedWithNamespace0: case NamespaceFormat.Expanded: var nsUri2 = context.NamespaceUris.GetString(qn.NamespaceIndex); if (!string.IsNullOrEmpty(nsUri2)) { buffer.Append("nsu=").Append(nsUri2).Append(';'); } break; case NamespaceFormat.Index: buffer.Append(qn.NamespaceIndex).Append(':'); break; } } buffer.Append(qnName.UrlEncode()); return buffer.ToString(); } /// /// Returns a qualified name from a string /// /// /// /// public static QualifiedName ToQualifiedName(this string? value, IServiceMessageContext context) { if (string.IsNullOrEmpty(value)) { return QualifiedName.Null; } string? nsUri = null; // Try to parse the index format var parts = value.Split(':'); if (ushort.TryParse(parts[0], out var nsIndex)) { value = value[(parts[0].Length + 1)..]; return new QualifiedName( string.IsNullOrEmpty(value) ? null : value.UrlDecode(), nsIndex); } // Try to parse the expanded format if (value.StartsWith("nsu=", StringComparison.Ordinal)) { parts = value.Split(';'); value = value[(parts[0].Length + 1)..]; return new QualifiedName( string.IsNullOrEmpty(value) ? null : value.UrlDecode(), context.NamespaceUris.GetIndexOrAppend(parts[0][4..])); } // Try to parse as uri with fragment if (Uri.TryCreate(value, UriKind.Absolute, out var uri)) { if (string.IsNullOrEmpty(uri.Fragment)) { value = string.Empty; } else { value = uri.Fragment.TrimStart('#'); } nsUri = uri.NoQueryAndFragment().AbsoluteUri; } else { // Not a real namespace uri - split and decode parts = value.Split('#'); if (parts.Length == 2) { nsUri = parts[0]; value = parts[1]; } } if (nsUri != null) { return new QualifiedName( string.IsNullOrEmpty(value) ? null : value.UrlDecode(), context.NamespaceUris.GetIndexOrAppend(nsUri)); } try { return QualifiedName.Parse(value.UrlDecode()); } catch { // Give up return new QualifiedName(value); } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Extensions/StatusCodeEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Opc.Ua { using Azure.IIoT.OpcUa.Encoders.Utils; /// /// Status code extensions /// public static class StatusCodeEx { /// /// Get symbolic name - fast /// /// /// public static string AsString(this StatusCode code) { if (!TypeMaps.StatusCodes.Value.TryGetBrowseName(code.CodeBits, out var name)) { return string.Empty; } return name; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Extensions/TypeInfoEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Opc.Ua { using System; using System.Collections.Generic; /// /// Typeinfo extensions /// public static class TypeInfoEx { /// /// Returns default value for type /// /// /// public static object GetDefaultValue(this TypeInfo typeInfo) { var builtInType = typeInfo.BuiltInType; if (typeInfo.ValueRank == ValueRanks.Scalar) { // For scalar values, try to retrieve a default. return TypeInfo.GetDefaultValue(builtInType); } if (typeInfo.ValueRank <= 1) { return Array.CreateInstance( TypeInfo.GetSystemType(builtInType, -1) ?? typeof(object), 0); } return new Matrix( Array.CreateInstance( TypeInfo.GetSystemType(builtInType, -1) ?? typeof(object), new int[typeInfo.ValueRank]), builtInType); } /// /// Create Variant /// /// /// /// /// public static Variant CreateVariant(this TypeInfo typeInfo, object value) { value ??= typeInfo.GetDefaultValue(); if (value is not Variant var) { var aex = new List(); if (typeInfo.BuiltInType == BuiltInType.Enumeration) { typeInfo = new TypeInfo(BuiltInType.Int32, typeInfo.ValueRank); } var systemType = TypeInfo.GetSystemType(typeInfo.BuiltInType, typeInfo.ValueRank); if (typeInfo.BuiltInType == BuiltInType.Null) { if (typeInfo.ValueRank == 1) { systemType = typeof(object[]); } else { return Variant.Null; // Matrix or scalar } } else if (value is Array arr) { try { var unboxed = Array.CreateInstance( TypeInfo.GetSystemType(typeInfo.BuiltInType, -1), arr.Length); Array.Copy(arr, unboxed, arr.Length); value = unboxed; } catch (Exception ex) { aex.Add(ex); value = arr; } } if (typeInfo.ValueRank >= 2) { systemType = typeof(Matrix); } var constructor = typeof(Variant).GetConstructor([ systemType ]); try { if (constructor != null) { return (Variant)constructor.Invoke([value]); } } catch (Exception ex) { aex.Add(ex); } try { return new Variant(value, typeInfo); } catch (Exception ex) { aex.Add(ex); throw new ArgumentException($"Cannot convert {value} " + $"({value.GetType()}/{systemType}/{typeInfo}) to Variant.", new AggregateException(aex)); } } return var; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Extensions.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using System; using System.Buffers; using System.IO; using System.IO.Compression; using System.Linq; internal static class Extensions { /// /// Sanitize file name /// /// /// public static string SanitizeFileName(this string fileName) { if (fileName.Length > 250) { fileName = new string(fileName.AsSpan()[..230]); fileName += fileName.ToSha1Hash(); } return fileName; } /// /// Decompress /// /// /// public static ReadOnlySequence GzipDecompress(this ReadOnlySequence data) { using var compressedStream = new MemoryStream(data.ToArray()); using var gzip = new GZipStream(compressedStream, CompressionMode.Decompress); return new ReadOnlySequence(gzip.ReadAsBuffer()); } /// /// Compress /// /// /// public static ReadOnlySequence GzipCompress(this ReadOnlySequence data) { using var compressedStream = new MemoryStream(); using (var gzip = new GZipStream(compressedStream, CompressionMode.Compress)) { foreach (var buffer in data) { gzip.Write(buffer.Span); } } return new ReadOnlySequence(compressedStream.ToArray()); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/IVariantEncoder.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Furly.Extensions.Serializers; using Opc.Ua; /// /// Variant codec /// public interface IVariantEncoder { /// /// Get context /// IServiceMessageContext Context { get; } /// /// Format variant as string /// /// /// /// VariantValue Encode(Variant? value, out BuiltInType builtinType); /// /// Parse token to variant /// /// /// /// Variant Decode(VariantValue value, BuiltInType builtinType); } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/JsonDecoderEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Azure.IIoT.OpcUa.Encoders.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Opc.Ua; using Opc.Ua.Extensions; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Text; using System.Xml; /// /// Reads objects from reader or string /// public sealed class JsonDecoderEx : IDecoder { /// public EncodingType EncodingType => EncodingType.Json; /// public IServiceMessageContext Context { get; } /// /// Create decoder /// /// /// /// public JsonDecoderEx(Stream stream, IServiceMessageContext? context = null, bool useJsonLoader = true) : this(new JsonTextReader(new StreamReader(stream)) { FloatParseHandling = FloatParseHandling.Double }, context, useJsonLoader) { } /// /// Create decoder /// /// /// /// internal JsonDecoderEx(JsonReader reader, IServiceMessageContext? context, bool useJsonLoader = true) { Context = context ?? new ServiceMessageContext(); _reader = !useJsonLoader ? reader : new JsonLoader( reader ?? throw new ArgumentNullException(nameof(reader))); } /// public void Dispose() { if (_reader is JsonLoader loader) { loader.Dispose(); } } /// public void Close() { // No op } /// public void PushNamespace(string namespaceUri) { // No op } /// public void PopNamespace() { // No op } /// public void SetMappingTables(NamespaceTable namespaceUris, StringTable serverUris) { // No op } /// public IEncodeable DecodeMessage(Type expectedType) { throw ServiceResultException.Create(StatusCodes.BadNotSupported, "Not supported in this decoder."); } /// public uint ReadSwitchField(IList switches, out string? fieldName) { var index = ReadUInt32("SwitchField"); if (switches == null) { fieldName = null; return 0; } if (index >= switches.Count) { fieldName = null; return index; } fieldName = switches[(int)index]; return index; } /// public uint ReadEncodingMask(IList masks) { return ReadUInt32("EncodingMask"); } /// public bool ReadBoolean(string? fieldName) { return TryGetToken(fieldName, out var value) && (bool)value; } /// public sbyte ReadSByte(string? fieldName) { return ReadValue(fieldName); } /// public byte ReadByte(string? fieldName) { return ReadValue(fieldName); } /// public short ReadInt16(string? fieldName) { return ReadValue(fieldName); } /// public ushort ReadUInt16(string? fieldName) { return ReadValue(fieldName); } /// public int ReadInt32(string? fieldName) { return ReadValue(fieldName); } /// public uint ReadUInt32(string? fieldName) { return ReadValue(fieldName); } /// public long ReadInt64(string? fieldName) { return ReadValue(fieldName); } /// public ulong ReadUInt64(string? fieldName) { return ReadValue(fieldName); } /// public float ReadFloat(string? fieldName) { return ReadValue(fieldName); } /// public double ReadDouble(string? fieldName) { return ReadValue(fieldName); } /// public byte[]? ReadByteString(string? fieldName) { return ReadValue(fieldName); } /// public string? ReadString(string? fieldName) { if (!TryGetToken(fieldName, out var token)) { return null; } if (token.Type == JTokenType.String) { return (string?)token; } return token.ToString(); // Return json string of token. } /// public Uuid ReadGuid(string? fieldName) { if (!TryGetToken(fieldName, out var token)) { return Uuid.Empty; } switch (token.Type) { case JTokenType.String: if (Guid.TryParse((string?)token, out var guid)) { return new Uuid(guid); } return new Uuid((string?)token); case JTokenType.Guid: return new Uuid((Guid)token); case JTokenType.Bytes: var bytes = (byte[]?)token; if (bytes == null || bytes.Length != 16) { break; } return new Uuid(new Guid(bytes)); } return Uuid.Empty; } /// public DateTime ReadDateTime(string? fieldName) { if (!TryGetToken(fieldName, out var token)) { return DateTime.MinValue; } if (token.Type == JTokenType.String) { var dateTimeString = (string?)token; return XmlConvert.ToDateTime(dateTimeString!, XmlDateTimeSerializationMode.Utc).ToOpcUaUniversalTime(); } var value = token.ToObject(); if (value != null) { return value.Value.ToOpcUaUniversalTime(); } return DateTime.MinValue; } /// public XmlElement? ReadXmlElement(string? fieldName) { var bytes = ReadByteString(fieldName); if (bytes?.Length > 0) { var document = new XmlDocument { InnerXml = Encoding.UTF8.GetString(bytes) }; return document.DocumentElement; } // Fallback if (TryGetToken(fieldName, out var token)) { return token.ToObject(); } return null; } /// public NodeId? ReadNodeId(string? fieldName) { if (!TryGetToken(fieldName, out var token)) { return null; } if (token is JObject o) { _stack.Push(o); // Read non reversable encoding ushort namespaceIndex = 0; NodeId? nodeId = null; if (TryGetToken("Namespace", out var namespaceToken)) { switch (namespaceToken.Type) { case JTokenType.String: var namespaceString = ReadString("Namespace"); if (namespaceString != null) { namespaceIndex = Context.NamespaceUris.GetIndexOrAppend(namespaceString); } break; case JTokenType.Integer: namespaceIndex = ReadUInt16("Namespace"); break; } } switch ((IdType)ReadByte("IdType")) { case IdType.Numeric: nodeId = new NodeId(ReadUInt32("Id"), namespaceIndex); break; case IdType.String: nodeId = new NodeId(ReadString("Id"), namespaceIndex); break; case IdType.Guid: nodeId = new NodeId(ReadGuid("Id"), namespaceIndex); break; case IdType.Opaque: nodeId = new NodeId(ReadByteString("Id"), namespaceIndex); break; } if (NodeId.IsNull(nodeId)) { var id = ReadString("Id"); _stack.Pop(); nodeId = id.ToNodeId(Context); if (!NodeId.IsNull(nodeId)) { return nodeId; } return NodeId.Parse(id); } _stack.Pop(); return nodeId; } if (token.Type == JTokenType.String) { var id = (string?)token; var nodeId = id.ToNodeId(Context); if (!NodeId.IsNull(nodeId)) { return nodeId; } return NodeId.Parse(id); } return null; } /// public ExpandedNodeId? ReadExpandedNodeId(string? fieldName) { if (!TryGetToken(fieldName, out var token)) { return null; } if (token is JObject o) { _stack.Push(o); // Read non reversable encoding ushort namespaceIndex = 0; string? namespaceUri = null; if (TryGetToken("Namespace", out var namespaceToken)) { switch (namespaceToken.Type) { case JTokenType.String: namespaceUri = ReadString("Namespace"); if (namespaceUri != null) { namespaceIndex = Context.NamespaceUris.GetIndexOrAppend(namespaceUri); } break; case JTokenType.Integer: namespaceIndex = ReadUInt16("Namespace"); break; } } uint serverIndex = 0; if (TryGetToken("ServerUri", out var serverToken)) { switch (serverToken.Type) { case JTokenType.String: var serverUri = ReadString("ServerUri"); if (serverUri != null) { serverIndex = Context.ServerUris.GetIndexOrAppend(serverUri); } break; case JTokenType.Integer: serverIndex = ReadUInt32("ServerUri"); break; } } var idType = (IdType)ReadByte("IdType"); NodeId? nodeId = null; switch (idType) { case IdType.Numeric: nodeId = new NodeId(ReadUInt32("Id"), namespaceIndex); break; case IdType.String: nodeId = new NodeId(ReadString("Id"), namespaceIndex); break; case IdType.Guid: nodeId = new NodeId(ReadGuid("Id"), namespaceIndex); break; case IdType.Opaque: nodeId = new NodeId(ReadByteString("Id"), namespaceIndex); break; } if (NodeId.IsNull(nodeId)) { var id = ReadString("Id"); _stack.Pop(); var expandedNodeId = id.ToExpandedNodeId(Context); if (!NodeId.IsNull(expandedNodeId)) { return expandedNodeId; } return ExpandedNodeId.Parse(id); } _stack.Pop(); return new ExpandedNodeId(nodeId, namespaceUri, serverIndex); } if (token.Type == JTokenType.String) { var id = (string?)token; var nodeId = id.ToExpandedNodeId(Context); if (!NodeId.IsNull(nodeId)) { return nodeId; } return ExpandedNodeId.Parse(id); } return null; } /// public StatusCode ReadStatusCode(string? fieldName) { if (!TryGetToken(fieldName, out var token)) { return 0; } if (token is JObject o) { _stack.Push(o); // Read non reversable encoding var code = new StatusCode(ReadUInt32("Code")); // var status = ReadString("Symbol"); _stack.Pop(); return code; } return ReadValue(fieldName); } /// public DiagnosticInfo? ReadDiagnosticInfo(string? fieldName) { if (!TryGetToken(fieldName, out var token)) { return null; } if (token is JObject o) { _stack.Push(o); var di = new DiagnosticInfo { SymbolicId = ReadInt32( "SymbolicId"), NamespaceUri = ReadInt32( "NamespaceUri"), Locale = ReadInt32( "Locale"), LocalizedText = ReadInt32( "LocalizedText"), AdditionalInfo = ReadString( "AdditionalInfo"), InnerStatusCode = ReadStatusCode( "InnerStatusCode"), InnerDiagnosticInfo = ReadDiagnosticInfo( "InnerDiagnosticInfo") }; _stack.Pop(); return di; } return null; } /// public QualifiedName? ReadQualifiedName(string? fieldName) { if (!TryGetToken(fieldName, out var token)) { return null; } if (token is JObject o) { _stack.Push(o); try { var name = ReadString("Name"); if (string.IsNullOrEmpty(name)) { return null; } uint index; if (TryGetToken("Uri", out var uri)) { if (uri.Type == JTokenType.Integer) { index = (uint)uri; } else if (uri.Type == JTokenType.String) { // Reversible index = Context.NamespaceUris .GetIndexOrAppend((string?)uri); } else { // Bad uri return null; } } else { index = ReadUInt32("Index"); } return new QualifiedName(name, (ushort)index); } finally { _stack.Pop(); } } if (token.Type == JTokenType.String) { var id = (string?)token; var qn = id.ToQualifiedName(Context); if (!QualifiedName.IsNull(qn)) { return qn; } return QualifiedName.Parse(id); } return null; } /// public LocalizedText? ReadLocalizedText(string? fieldName) { if (!TryGetToken(fieldName, out var token)) { return null; } if (token is JObject o) { _stack.Push(o); var text = ReadString("Text"); var locale = ReadString("Locale"); _stack.Pop(); return new LocalizedText(locale, text); } if (token.Type == JTokenType.String) { var text = (string?)token; if (!string.IsNullOrEmpty(text)) { return text.ToLocalizedText(); } } return null; } /// public Variant ReadVariant(string? fieldName) { if (!TryGetToken(fieldName, out var token)) { return Variant.Null; } if (token is JObject o) { return TryReadVariant(o, out _); } return ReadVariantFromToken(token); } /// public DataValue? ReadDataValue(string? fieldName) { if (!TryGetToken(fieldName, out var token)) { return null; } if (token is JObject o) { if (HasAnyOf(o, "Value", "StatusCode", "SourceTimestamp", "ServerTimestamp")) { _stack.Push(o); var dv = new DataValue { WrappedValue = ReadVariant("Value"), StatusCode = ReadStatusCode("StatusCode"), SourceTimestamp = ReadDateTime("SourceTimestamp"), SourcePicoseconds = ReadUInt16("SourcePicoseconds"), ServerTimestamp = ReadDateTime("ServerTimestamp"), ServerPicoseconds = ReadUInt16("ServerPicoseconds") }; _stack.Pop(); return dv; } var objectVariant = TryReadVariant(o, out _); if (objectVariant != Variant.Null) { return new DataValue(objectVariant); } return null; } var tokenVariant = ReadVariantFromToken(token); if (tokenVariant == Variant.Null) { return null; } return new DataValue(tokenVariant); } /// public ExtensionObject? ReadExtensionObject(string? fieldName) { if (!TryGetToken(fieldName, out var token)) { return null; } if (token is JObject o && HasAnyOf(o, "Body", "TypeId")) { _stack.Push(o); var typeId = ReadExpandedNodeId("TypeId"); var encoding = ReadEncoding("Encoding"); var extensionObject = ReadExtensionObjectBody("Body", encoding, typeId); _stack.Pop(); return extensionObject; } return null; } /// public IEncodeable? ReadEncodeable(string? fieldName, Type systemType, ExpandedNodeId? encodeableTypeId = null) { ArgumentNullException.ThrowIfNull(systemType); if (!TryGetToken(fieldName, out var token)) { return null; } if (Activator.CreateInstance(systemType) is not IEncodeable value) { return null; } if (token is JObject o) { _stack.Push(o); value.Decode(this); _stack.Pop(); return value; } return null; // or value? } /// public Enum? ReadEnumerated(string? fieldName, Type enumType) { ArgumentNullException.ThrowIfNull(enumType); if (!enumType.IsEnum) { throw new ArgumentException("Not an enum type", nameof(enumType)); } if (!TryGetToken(fieldName, out var token)) { return (Enum)Enum.ToObject(enumType, 0); // or null? } if (token.Type == JTokenType.String) { var val = (string?)token; var index = val?.LastIndexOf('_') ?? -1; if (index != -1 && int.TryParse(val![(index + 1)..], out var numeric)) { return (Enum)Enum.ToObject(enumType, numeric); } if (Enum.TryParse(enumType, val, true, out var o)) { return o as Enum; } return null; } if (token.Type == JTokenType.Integer) { return (Enum)Enum.ToObject(enumType, (int)token); } return null; } /// public Array? ReadArray(string? fieldName, int valueRank, BuiltInType builtInType, Type? systemType, ExpandedNodeId? encodeableTypeId) { if (valueRank == ValueRanks.OneDimension) { switch (builtInType) { case BuiltInType.Boolean: return ReadBooleanArray(fieldName).ToArray(); case BuiltInType.SByte: return ReadSByteArray(fieldName).ToArray(); case BuiltInType.Byte: return ReadByteArray(fieldName).ToArray(); case BuiltInType.Int16: return ReadInt16Array(fieldName).ToArray(); case BuiltInType.UInt16: return ReadUInt16Array(fieldName).ToArray(); case BuiltInType.Int32: return ReadInt32Array(fieldName).ToArray(); case BuiltInType.UInt32: return ReadUInt32Array(fieldName).ToArray(); case BuiltInType.Int64: return ReadInt64Array(fieldName).ToArray(); case BuiltInType.UInt64: return ReadUInt64Array(fieldName).ToArray(); case BuiltInType.Float: return ReadFloatArray(fieldName).ToArray(); case BuiltInType.Double: return ReadDoubleArray(fieldName).ToArray(); case BuiltInType.String: return ReadStringArray(fieldName).ToArray(); case BuiltInType.DateTime: return ReadDateTimeArray(fieldName).ToArray(); case BuiltInType.Guid: return ReadGuidArray(fieldName).ToArray(); case BuiltInType.ByteString: return ReadByteStringArray(fieldName).ToArray(); case BuiltInType.XmlElement: return ReadXmlElementArray(fieldName).ToArray(); case BuiltInType.NodeId: return ReadNodeIdArray(fieldName).ToArray(); case BuiltInType.ExpandedNodeId: return ReadExpandedNodeIdArray(fieldName).ToArray(); case BuiltInType.StatusCode: return ReadStatusCodeArray(fieldName).ToArray(); case BuiltInType.QualifiedName: return ReadQualifiedNameArray(fieldName).ToArray(); case BuiltInType.LocalizedText: return ReadLocalizedTextArray(fieldName).ToArray(); case BuiltInType.DataValue: return ReadDataValueArray(fieldName).ToArray(); case BuiltInType.Enumeration: return ReadInt32Array(fieldName).ToArray(); case BuiltInType.Variant: return ReadVariantArray(fieldName).ToArray(); case BuiltInType.ExtensionObject: return ReadExtensionObjectArray(fieldName).ToArray(); case BuiltInType.DiagnosticInfo: return ReadDiagnosticInfoArray(fieldName).ToArray(); case BuiltInType.Null: ArgumentNullException.ThrowIfNull(systemType); return ReadEncodeableArray(fieldName, systemType); default: throw new DecodingException( $"Cannot decode unknown type in Array object with BuiltInType: {builtInType}."); } } else if (valueRank > ValueRanks.OneDimension) { if (!ReadArrayField(fieldName, out var array)) { return null; } var elements = new List(); var dimensions = new List(); ReadMatrixPart(fieldName, array, builtInType, ref elements, ref dimensions, 0); switch (builtInType) { case BuiltInType.Boolean: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); case BuiltInType.SByte: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); case BuiltInType.Byte: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); case BuiltInType.Int16: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); case BuiltInType.UInt16: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); case BuiltInType.Int32: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); case BuiltInType.UInt32: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); case BuiltInType.Int64: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); case BuiltInType.UInt64: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); case BuiltInType.Float: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); case BuiltInType.Double: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); case BuiltInType.String: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); case BuiltInType.DateTime: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); case BuiltInType.Guid: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); case BuiltInType.ByteString: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); case BuiltInType.XmlElement: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); case BuiltInType.NodeId: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); case BuiltInType.ExpandedNodeId: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); case BuiltInType.StatusCode: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); case BuiltInType.QualifiedName: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); case BuiltInType.LocalizedText: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); case BuiltInType.DataValue: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); case BuiltInType.Enumeration: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); case BuiltInType.Variant: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); case BuiltInType.ExtensionObject: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); case BuiltInType.DiagnosticInfo: return new Matrix(elements.Cast().ToArray(), builtInType, [.. dimensions]).ToArray(); } } return null; } /// public BooleanCollection ReadBooleanArray(string? fieldName) { return ReadArray(fieldName, () => ReadBoolean(null)); } /// public Int16Collection ReadInt16Array(string? fieldName) { return ReadArray(fieldName, () => ReadInt16(null)); } /// public UInt16Collection ReadUInt16Array(string? fieldName) { return ReadArray(fieldName, () => ReadUInt16(null)); } /// public Int32Collection ReadInt32Array(string? fieldName) { return ReadArray(fieldName, () => ReadInt32(null)); } /// public UInt32Collection ReadUInt32Array(string? fieldName) { return ReadArray(fieldName, () => ReadUInt32(null)); } /// public Int64Collection ReadInt64Array(string? fieldName) { return ReadArray(fieldName, () => ReadInt64(null)); } /// public UInt64Collection ReadUInt64Array(string? fieldName) { return ReadArray(fieldName, () => ReadUInt64(null)); } /// public FloatCollection ReadFloatArray(string? fieldName) { return ReadArray(fieldName, () => ReadFloat(null)); } /// public DoubleCollection ReadDoubleArray(string? fieldName) { return ReadArray(fieldName, () => ReadDouble(null)); } /// public StringCollection ReadStringArray(string? fieldName) { return ReadArray(fieldName, () => ReadString(null)); } /// public IReadOnlyList<(string, string?)>? ReadStringDictionary(string? property) { return ReadDictionary(property, () => ReadString(null)); } /// public DateTimeCollection ReadDateTimeArray(string? fieldName) { return ReadArray(fieldName, () => ReadDateTime(null)); } /// public UuidCollection ReadGuidArray(string? fieldName) { return ReadArray(fieldName, () => ReadGuid(null)); } /// public ByteStringCollection ReadByteStringArray(string? fieldName) { return ReadArray(fieldName, () => ReadByteString(null)); } /// public XmlElementCollection ReadXmlElementArray(string? fieldName) { return ReadArray(fieldName, () => ReadXmlElement(null)); } /// public NodeIdCollection ReadNodeIdArray(string? fieldName) { return ReadArray(fieldName, () => ReadNodeId(null)); } /// public ExpandedNodeIdCollection ReadExpandedNodeIdArray(string? fieldName) { return ReadArray(fieldName, () => ReadExpandedNodeId(null)); } /// public StatusCodeCollection ReadStatusCodeArray(string? fieldName) { return ReadArray(fieldName, () => ReadStatusCode(null)); } /// public DiagnosticInfoCollection ReadDiagnosticInfoArray(string? fieldName) { return ReadArray(fieldName, () => ReadDiagnosticInfo(null)); } /// public QualifiedNameCollection ReadQualifiedNameArray(string? fieldName) { return ReadArray(fieldName, () => ReadQualifiedName(null)); } /// public LocalizedTextCollection ReadLocalizedTextArray(string? fieldName) { return ReadArray(fieldName, () => ReadLocalizedText(null)); } /// public VariantCollection ReadVariantArray(string? fieldName) { return ReadArray(fieldName, () => ReadVariant(null)); } /// public DataValueCollection ReadDataValueArray(string? fieldName) { return ReadArray(fieldName, () => ReadDataValue(null)); } /// public DataSet? ReadDataSet(string? property) { DataSetFieldContentFlags fieldMask = 0u; var couldBeRawData = false; var dictionary = ReadDictionary(property, () => { if (TryGetToken(property, out var token)) { if (token is JObject o) { if (HasAnyOf(o, "StatusCode")) { fieldMask |= DataSetFieldContentFlags.StatusCode; } if (HasAnyOf(o, "SourceTimestamp")) { fieldMask |= DataSetFieldContentFlags.SourceTimestamp; } if (HasAnyOf(o, "ServerTimestamp")) { fieldMask |= DataSetFieldContentFlags.ServerTimestamp; } if (HasAnyOf(o, "SourcePicoseconds")) { fieldMask |= DataSetFieldContentFlags.SourcePicoSeconds; } if (HasAnyOf(o, "ServerPicoseconds")) { fieldMask |= DataSetFieldContentFlags.ServerPicoSeconds; } } else if (token is JValue) { // Could be raw data couldBeRawData = true; } } return ReadDataValue(null); }); fieldMask = ((uint)fieldMask != 0 || !couldBeRawData) ? fieldMask : DataSetFieldContentFlags.RawData; return dictionary == null ? null : new DataSet(dictionary, fieldMask); } /// public ExtensionObjectCollection ReadExtensionObjectArray(string? fieldName) { return ReadArray(fieldName, () => ReadExtensionObject(null)); } /// public ByteCollection ReadByteArray(string? fieldName) { if (!TryGetToken(fieldName, out var token)) { return []; } if (token.Type is JTokenType.Bytes or JTokenType.String) { var s = (string?)token; if (s == null) { return []; } return Convert.FromBase64String(s); } if (token is JArray a) { return a.Select(t => ReadToken(t, () => ReadByte(null))).ToArray(); } return [ ReadToken(token, () => ReadByte(null)) ]; } /// public SByteCollection ReadSByteArray(string? fieldName) { if (!TryGetToken(fieldName, out var token)) { return []; } if (token.Type is JTokenType.Bytes or JTokenType.String) { var s = (string?)token; if (s == null) { return []; } return Convert.FromBase64String(s) .Select(b => (sbyte)b).ToArray(); } if (token is JArray a) { return a.Select(t => ReadToken(t, () => ReadSByte(null))).ToArray(); } return [ ReadToken(token, () => ReadSByte(null)) ]; } /// public Array ReadEncodeableArray(string? fieldName, Type systemType, ExpandedNodeId? encodeableTypeId = null) { var values = ReadArray(fieldName, () => ReadEncodeable( null, systemType, encodeableTypeId))? .ToList(); if (values == null) { return Array.CreateInstance(systemType, 0); } var array = Array.CreateInstance(systemType, values.Count); values.CopyTo((IEncodeable[])array); return array; } /// public Array? ReadEnumeratedArray(string? fieldName, Type enumType) { var values = ReadArray(fieldName, () => ReadEnumerated(null, enumType))? .ToList(); if (values == null) { return null; } var array = Array.CreateInstance(enumType, values.Count); values.CopyTo((Enum[])array); return array; } /// /// Read integers /// /// /// public VariantCollection ReadIntegerArray(string? property) { return ReadArray(property, () => ReadInteger(null)); } /// /// Read integer variant value /// /// /// public Variant ReadInteger(string? property) { if (!TryGetToken(property, out var token)) { return Variant.Null; } Variant number; if (token is JObject o) { number = TryReadVariant(o, out _); } else { number = ReadVariantFromToken(token, false); } var builtInType = number.TypeInfo.BuiltInType; if (builtInType is (>= BuiltInType.SByte and <= BuiltInType.UInt64) or BuiltInType.Integer) { return number; } return Variant.Null; } /// /// Read unsigned integers /// /// /// public VariantCollection ReadUIntegerArray(string? property) { return ReadArray(property, () => ReadUInteger(null)); } /// /// Read unsigned integer variant value /// /// /// public Variant ReadUInteger(string? property) { if (!TryGetToken(property, out var token)) { return Variant.Null; } Variant number; if (token is JObject o) { number = TryReadVariant(o, out _); } else { number = ReadVariantFromToken(token, true); } var builtInType = number.TypeInfo.BuiltInType; if (builtInType is (>= BuiltInType.Byte and <= BuiltInType.UInt64) or BuiltInType.UInteger) { return number; } return Variant.Null; } /// /// Read numeric values /// /// /// public VariantCollection ReadNumberArray(string? property) { return ReadArray(property, () => ReadNumber(null)); } /// /// Read numeric variant value /// /// /// public Variant ReadNumber(string? property) { if (!TryGetToken(property, out var token)) { return Variant.Null; } Variant number; if (token is JObject o) { number = TryReadVariant(o, out _); } else { number = ReadVariantFromToken(token); } if (TypeInfo.IsNumericType(number.TypeInfo.BuiltInType)) { return number; } return Variant.Null; } /// /// Read extension object body /// /// /// /// /// private ExtensionObject? ReadExtensionObjectBody(string? property, ExtensionObjectEncoding encoding, ExpandedNodeId? typeId) { if (!TryGetToken(property, out var body)) { return null; } var systemType = Context.Factory.GetSystemType(typeId) ?? TypeInfo.GetSystemType(typeId.ToNodeId(Context.NamespaceUris), Context.Factory); if (body.Type == JTokenType.String && encoding != ExtensionObjectEncoding.Xml) { // Assume binary encoding = ExtensionObjectEncoding.Binary; } switch (encoding) { case ExtensionObjectEncoding.Binary: var bytes = ReadByteString(property); if (bytes != null && systemType != null) { using var decoder = new BinaryDecoder(bytes, Context); var encodeable = decoder.ReadEncodeable(null, systemType); if (encodeable != null) { return new ExtensionObject(encodeable.TypeId, encodeable); } } // // Unknown type, or empty then return raw bytes. We return the // data type encoding as type id, we dont know otherwise // return new ExtensionObject(NodeId.IsNull(typeId) ? DataTypeIds.ByteString : typeId, bytes); case ExtensionObjectEncoding.Xml: var encoded = ReadByteString(property); XmlElement? element = null; if (encoded != null) { var xml = Encoding.UTF8.GetString(encoded); if (xml != null) { if (systemType != null) { using var stringReader = new StringReader(xml); using var reader = XmlReader.Create(stringReader); using var decoder = new XmlDecoder(systemType, reader, Context); var encodeable = decoder.ReadEncodeable(null, systemType); if (encodeable != null) { return new ExtensionObject(encodeable.TypeId, encodeable); } } // // Unknown type, return as xmlelement // var doc = new XmlDocument(); doc.LoadXml(xml); element = doc.DocumentElement; } } // // Unknown type, or empty then return the xml elemtn. We return the // data type encoding as type id, we dont know otherwise // return new ExtensionObject(NodeId.IsNull(typeId) ? DataTypeIds.XmlElement : typeId, element); default: if (systemType != null) { var encodeable = ReadEncodeable(property, systemType); if (encodeable != null) { return new ExtensionObject(encodeable.TypeId, encodeable); } } // // Return json token, update once stack supports json extension objects. // var wrapper = new EncodeableJToken(body, typeId ?? ExpandedNodeId.Null); return new ExtensionObject(wrapper.TypeId, wrapper); } } /// /// Convert a token to variant /// /// /// /// private Variant ReadVariantFromToken(JToken token, bool unsigned = false) { try { switch (token.Type) { case JTokenType.Integer: try { return !unsigned ? new Variant((long)token) : new Variant((ulong)token); } catch (OverflowException) { return new Variant((ulong)token); } case JTokenType.Boolean: return new Variant((bool)token); case JTokenType.Bytes: return new Variant((byte[]?)token); case JTokenType.Date: return new Variant((DateTime)token); case JTokenType.TimeSpan: return new Variant(((TimeSpan)token).TotalMilliseconds); case JTokenType.Float: return new Variant((double)token); case JTokenType.Guid: return new Variant((Guid)token); case JTokenType.String: return new Variant((string?)token); case JTokenType.Object: var variant = TryReadVariant((JObject)token, out var found); if (found) { return variant; } try { return new Variant(token.ToObject()); } catch { // TODO: Try to read other structures // ... // return Variant.Null; // Give up } case JTokenType.Array: return ReadVariantFromArray((JArray)token); default: // TODO Log or throw for bad type return Variant.Null; } } catch { return Variant.Null; // Give up } } /// /// Read variant from token /// /// /// Force integers to be unsigned /// private Variant ReadVariantFromArray(JArray array, bool unsigned = false) { if (array.Count == 0) { return Variant.Null; // Give up } // Try to decode non reversible encoding first. var dimensions = GetDimensions(array, out var type); if (dimensions.Length > 1) { var builtInType = BuiltInType.Variant; switch (type) { case JTokenType.Integer: builtInType = BuiltInType.Int64; break; case JTokenType.Boolean: builtInType = BuiltInType.Boolean; break; case JTokenType.Bytes: builtInType = BuiltInType.ByteString; break; case JTokenType.Date: case JTokenType.TimeSpan: builtInType = BuiltInType.DateTime; break; case JTokenType.Float: builtInType = BuiltInType.Double; break; case JTokenType.Guid: builtInType = BuiltInType.Guid; break; case JTokenType.String: builtInType = BuiltInType.String; break; } return ReadVariantMatrixBody(array, dimensions, builtInType); } if (type != JTokenType.Object && array.All(j => j.Type == type)) { try { switch (array[0].Type) { case JTokenType.Integer: return !unsigned ? new Variant(array .Select(t => (long)t) .ToArray()) : new Variant(array .Select(t => (ulong)t) .ToArray()); case JTokenType.Boolean: return new Variant(array .Select(t => (bool)t) .ToArray()); case JTokenType.Bytes: return new Variant(array .Select(t => (byte[]?)t) .ToArray()); case JTokenType.Date: return new Variant(array .Select(t => (DateTime)t) .ToArray()); case JTokenType.TimeSpan: return new Variant(array .Select(t => ((TimeSpan)t).TotalMilliseconds) .ToArray()); case JTokenType.Float: return new Variant(array .Select(t => (double)t) .ToArray()); case JTokenType.Guid: return new Variant(array .Select(t => (Guid)t) .ToArray()); case JTokenType.String: return new Variant(array .Select(t => (string?)t) .ToArray()); } } catch { // TODO Log or throw for bad type return Variant.Null; // Give up } } var result = array .Select(t => ReadVariantFromToken(t, unsigned)) .ToArray(); var validBuiltInType = Array.Find(result, v => v.TypeInfo?.BuiltInType != null).TypeInfo?.BuiltInType; if (validBuiltInType == null) { return Variant.Null; } if (result .Where(v => v != Variant.Null) .All(v => v.TypeInfo.BuiltInType == validBuiltInType)) { // TODO: This needs tests as it should not work. return new Variant(result.Select(v => v.Value).ToArray()); } return new Variant(result); } /// /// Read variant /// /// /// /// private Variant TryReadVariant(JObject o, out bool success) { Variant variant; _stack.Push(o); if (TryReadBuiltInType("Type", out var type)) { variant = ReadVariantBody("Body", type); success = true; } else if (TryReadBuiltInType("DataType", out type)) { variant = ReadVariantBody("Value", type); success = true; } else { variant = Variant.Null; success = false; } _stack.Pop(); return variant; } /// /// Read variant body /// /// /// /// private Variant ReadVariantBody(string? property, BuiltInType type) { if (!TryGetToken(property, out var token)) { return Variant.Null; } if (token is JArray jarray) { // Check array dimensions var dimensions = GetDimensions(jarray, out _); if (dimensions.Length > 1) { return ReadVariantMatrixBody(jarray, dimensions, type); } // Read body as array return ReadVariantArrayBody(property, type); } if ((token.Type == JTokenType.Bytes || token.Type == JTokenType.String) && (type == BuiltInType.Byte || type == BuiltInType.SByte)) { // Read body as array return ReadVariantArrayBody(property, type); } switch (type) { case BuiltInType.Boolean: return new Variant(ReadBoolean(property), TypeInfo.Scalars.Boolean); case BuiltInType.SByte: return new Variant(ReadSByte(property), TypeInfo.Scalars.SByte); case BuiltInType.Byte: return new Variant(ReadByte(property), TypeInfo.Scalars.Byte); case BuiltInType.Int16: return new Variant(ReadInt16(property), TypeInfo.Scalars.Int16); case BuiltInType.UInt16: return new Variant(ReadUInt16(property), TypeInfo.Scalars.UInt16); case BuiltInType.Enumeration: case BuiltInType.Int32: return new Variant(ReadInt32(property), TypeInfo.Scalars.Int32); case BuiltInType.UInt32: return new Variant(ReadUInt32(property), TypeInfo.Scalars.UInt32); case BuiltInType.Int64: return new Variant(ReadInt64(property), TypeInfo.Scalars.Int64); case BuiltInType.UInt64: return new Variant(ReadUInt64(property), TypeInfo.Scalars.UInt64); case BuiltInType.Float: return new Variant(ReadFloat(property), TypeInfo.Scalars.Float); case BuiltInType.Double: return new Variant(ReadDouble(property), TypeInfo.Scalars.Double); case BuiltInType.String: return new Variant(ReadString(property), TypeInfo.Scalars.String); case BuiltInType.ByteString: return new Variant(ReadByteString(property), TypeInfo.Scalars.ByteString); case BuiltInType.DateTime: return new Variant(ReadDateTime(property), TypeInfo.Scalars.DateTime); case BuiltInType.Guid: return new Variant(ReadGuid(property), TypeInfo.Scalars.Guid); case BuiltInType.NodeId: return new Variant(ReadNodeId(property), TypeInfo.Scalars.NodeId); case BuiltInType.ExpandedNodeId: return new Variant(ReadExpandedNodeId(property), TypeInfo.Scalars.ExpandedNodeId); case BuiltInType.QualifiedName: return new Variant(ReadQualifiedName(property), TypeInfo.Scalars.QualifiedName); case BuiltInType.LocalizedText: return new Variant(ReadLocalizedText(property), TypeInfo.Scalars.LocalizedText); case BuiltInType.StatusCode: return new Variant(ReadStatusCode(property), TypeInfo.Scalars.StatusCode); case BuiltInType.XmlElement: return new Variant(ReadXmlElement(property), TypeInfo.Scalars.XmlElement); case BuiltInType.ExtensionObject: return new Variant(ReadExtensionObject(property), TypeInfo.Scalars.ExtensionObject); case BuiltInType.Number: case BuiltInType.UInteger: case BuiltInType.Integer: case BuiltInType.Variant: return ReadVariant(property); default: return Variant.Null; } } /// /// Read variant matrix /// /// /// /// /// /// private Variant ReadVariantMatrixBody(JArray array, int[] dimensions, BuiltInType type) { var length = 1; foreach (var dim in dimensions) { length *= dim; } var flatArray = TypeInfo.CreateArray(type, length); var index = 0; CopyToMatrixFlatArray(array, flatArray, ref index, type); if (index < length) { throw new DecodingException( "Read matrix is smaller than array dimensions."); } return new Variant(new Matrix(flatArray, type, dimensions)); } /// /// Copy from array to flat matrix array /// /// /// /// /// /// private void CopyToMatrixFlatArray(JArray array, Array target, ref int index, BuiltInType type) { foreach (var item in array) { if (item is JArray next) { // Recurse into inner array until we hit individual items CopyToMatrixFlatArray(next, target, ref index, type); } else if (index < target.GetLength(0)) { // Read item at top of stack _stack.Push(item); switch (type) { case BuiltInType.Boolean: target.SetValue(ReadBoolean(null), index++); break; case BuiltInType.SByte: target.SetValue(ReadSByte(null), index++); break; case BuiltInType.Byte: target.SetValue(ReadByte(null), index++); break; case BuiltInType.Int16: target.SetValue(ReadInt16(null), index++); break; case BuiltInType.UInt16: target.SetValue(ReadUInt16(null), index++); break; case BuiltInType.Enumeration: case BuiltInType.Int32: target.SetValue(ReadInt32(null), index++); break; case BuiltInType.UInt32: target.SetValue(ReadUInt32(null), index++); break; case BuiltInType.Int64: target.SetValue(ReadInt64(null), index++); break; case BuiltInType.UInt64: target.SetValue(ReadUInt64(null), index++); break; case BuiltInType.Float: target.SetValue(ReadFloat(null), index++); break; case BuiltInType.Double: target.SetValue(ReadDouble(null), index++); break; case BuiltInType.String: target.SetValue(ReadString(null), index++); break; case BuiltInType.ByteString: target.SetValue(ReadByteString(null), index++); break; case BuiltInType.DateTime: target.SetValue(ReadDateTime(null), index++); break; case BuiltInType.Guid: target.SetValue(ReadGuid(null), index++); break; case BuiltInType.NodeId: target.SetValue(ReadNodeId(null), index++); break; case BuiltInType.ExpandedNodeId: target.SetValue(ReadExpandedNodeId(null), index++); break; case BuiltInType.QualifiedName: target.SetValue(ReadQualifiedName(null), index++); break; case BuiltInType.LocalizedText: target.SetValue(ReadLocalizedText(null), index++); break; case BuiltInType.StatusCode: target.SetValue(ReadStatusCode(null), index++); break; case BuiltInType.XmlElement: target.SetValue(ReadXmlElement(null), index++); break; case BuiltInType.ExtensionObject: target.SetValue(ReadExtensionObject(null), index++); break; case BuiltInType.UInteger: target.SetValue(ReadUInteger(null), index++); break; case BuiltInType.Integer: target.SetValue(ReadInteger(null), index++); break; case BuiltInType.Number: target.SetValue(ReadNumber(null), index++); break; case BuiltInType.Variant: target.SetValue(ReadVariant(null), index++); break; default: target.SetValue(null, index++); break; } _stack.Pop(); } else { throw new DecodingException( "Read matrix is larger than array dimensions."); } } } /// /// Read variant array /// /// /// /// private Variant ReadVariantArrayBody(string? property, BuiltInType type) { switch (type) { case BuiltInType.Boolean: return new Variant(ReadBooleanArray(property), TypeInfo.Arrays.Boolean); case BuiltInType.SByte: return new Variant(ReadSByteArray(property), TypeInfo.Arrays.SByte); case BuiltInType.Byte: return new Variant(ReadByteArray(property), TypeInfo.Arrays.Byte); case BuiltInType.Int16: return new Variant(ReadInt16Array(property), TypeInfo.Arrays.Int16); case BuiltInType.UInt16: return new Variant(ReadUInt16Array(property), TypeInfo.Arrays.UInt16); case BuiltInType.Enumeration: case BuiltInType.Int32: return new Variant(ReadInt32Array(property), TypeInfo.Arrays.Int32); case BuiltInType.UInt32: return new Variant(ReadUInt32Array(property), TypeInfo.Arrays.UInt32); case BuiltInType.Int64: return new Variant(ReadInt64Array(property), TypeInfo.Arrays.Int64); case BuiltInType.UInt64: return new Variant(ReadUInt64Array(property), TypeInfo.Arrays.UInt64); case BuiltInType.Float: return new Variant(ReadFloatArray(property), TypeInfo.Arrays.Float); case BuiltInType.Double: return new Variant(ReadDoubleArray(property), TypeInfo.Arrays.Double); case BuiltInType.String: return new Variant(ReadStringArray(property), TypeInfo.Arrays.String); case BuiltInType.ByteString: return new Variant(ReadByteStringArray(property), TypeInfo.Arrays.ByteString); case BuiltInType.DateTime: return new Variant(ReadDateTimeArray(property), TypeInfo.Arrays.DateTime); case BuiltInType.Guid: return new Variant(ReadGuidArray(property), TypeInfo.Arrays.Guid); case BuiltInType.NodeId: return new Variant(ReadNodeIdArray(property), TypeInfo.Arrays.NodeId); case BuiltInType.ExpandedNodeId: return new Variant(ReadExpandedNodeIdArray(property), TypeInfo.Arrays.ExpandedNodeId); case BuiltInType.QualifiedName: return new Variant(ReadQualifiedNameArray(property), TypeInfo.Arrays.QualifiedName); case BuiltInType.LocalizedText: return new Variant(ReadLocalizedTextArray(property), TypeInfo.Arrays.LocalizedText); case BuiltInType.StatusCode: return new Variant(ReadStatusCodeArray(property), TypeInfo.Arrays.StatusCode); case BuiltInType.XmlElement: return new Variant(ReadXmlElementArray(property), TypeInfo.Arrays.XmlElement); case BuiltInType.ExtensionObject: return new Variant(ReadExtensionObjectArray(property), TypeInfo.Arrays.ExtensionObject); case BuiltInType.UInteger: return new Variant(ReadUIntegerArray(property), TypeInfo.Arrays.Variant); case BuiltInType.Integer: return new Variant(ReadIntegerArray(property), TypeInfo.Arrays.Variant); case BuiltInType.Number: return new Variant(ReadNumberArray(property), TypeInfo.Arrays.Variant); case BuiltInType.Variant: return new Variant(ReadVariantArray(property), TypeInfo.Arrays.Variant); default: return Variant.Null; } } /// /// Read value with check /// /// /// /// private T? ReadValue(string? property) { if (!TryGetToken(property, out var token)) { return default; } try { return token.ToObject(); } catch { return default; } } /// /// Read built in type value /// /// /// /// private bool TryReadBuiltInType(string? property, out BuiltInType type) { type = BuiltInType.Null; if (!TryGetToken(property, out var token)) { return false; } if (token.Type == JTokenType.String) { return Enum.TryParse((string?)token, true, out type); } try { type = (BuiltInType)token.ToObject(); return true; } catch { return false; } } /// /// Read encoding value /// /// /// private ExtensionObjectEncoding ReadEncoding(string? property) { if (!TryGetToken(property, out var token)) { return ExtensionObjectEncoding.None; } if (token.Type == JTokenType.String && Enum.TryParse((string?)token, true, out var encoding)) { return encoding; } try { return (ExtensionObjectEncoding)token.ToObject(); } catch { return ExtensionObjectEncoding.None; } } /// /// Read array using specified element reader /// /// /// /// /// internal T[]? ReadArray(string? property, Func reader) { if (!TryGetToken(property, out var token)) { return null; } if (token is JArray a) { return a.Select(t => ReadToken(t, reader)).ToArray(); } return ReadToken(token, reader).YieldReturn().ToArray(); } /// /// Read dictionary /// /// /// /// /// private List<(string, T?)>? ReadDictionary(string? property, Func reader) { if (!TryGetToken(property, out var token) || token is not JObject o) { return null; } var dictionary = new List<(string, T?)>(); foreach (var p in o.Properties()) { dictionary.Add((p.Name, ReadToken(p.Value, reader))); } return dictionary; } /// /// Read token using a specified reader /// /// /// /// /// private T ReadToken(JToken token, Func reader) { try { _stack.Push(token); return reader(); } finally { _stack.Pop(); } } /// /// Test whether the object contains any of the properties /// /// /// /// internal static bool HasAnyOf(JObject o, params string[] properties) { foreach (var property in properties) { if (o.TryGetValue(property, StringComparison.InvariantCultureIgnoreCase, out _)) { return true; } } return false; } /// /// Try get top token or named token from object /// /// /// /// /// internal bool TryGetToken(string? property, [NotNullWhen(true)] out JToken? token) { JToken? top; if (_stack.Count == 0) { top = ReadNextToken(); // // Check whether we read a property from the top object. // If so, push the top object for reading. Otherwise, we // are reading from an array of object so we do not push // which means our stack will reset to 0. // if (top != null && (property != null || _reader is not JsonLoader)) { _stack.Push(top); } } else { top = _stack.Peek(); } if (top == null) { // Hit end of file. token = null; return false; } if (property == null) { // Read top token token = top; return true; } if (top is JObject o) { if (!o.TryGetValue(property, out token) && !o.TryGetValue(property, StringComparison.InvariantCultureIgnoreCase, out token)) { return false; } switch (token.Type) { case JTokenType.Comment: case JTokenType.Constructor: case JTokenType.None: case JTokenType.Property: case JTokenType.Raw: case JTokenType.Undefined: case JTokenType.Null: return false; } return true; } throw new DecodingException("Expected object at top of stack"); } /// /// Read next root token from reader /// /// private JToken? ReadNextToken() { if (_reader == null) { return null; } if (_reader.TokenType == JsonToken.EndObject && string.IsNullOrEmpty(_reader.Path)) { return null; } if (_reader is JsonLoader loader) { loader.Reset(); } return JToken.ReadFrom(_reader, new JsonLoadSettings { CommentHandling = CommentHandling.Ignore, LineInfoHandling = LineInfoHandling.Ignore }); } /// /// Read array field /// /// /// /// /// private bool ReadArrayField(string? fieldName, [NotNullWhen(true)] out List? array) { object? token; if (!string.IsNullOrEmpty(fieldName)) { var context = _stack.Peek().ToObject>(); if (context == null || !context.TryGetValue(fieldName, out token)) { array = null; return false; } } else { token = _stack.Peek(); } array = token as List; if (array == null) { return false; } if (Context.MaxArrayLength > 0 && Context.MaxArrayLength < array.Count) { throw new DecodingException(StatusCodes.BadEncodingLimitsExceeded, $"Maximum nesting level of {Context.MaxEncodingNestingLevels} was exceeded."); } return true; } /// /// Read the Matrix part (simple array or array of arrays) /// /// /// /// /// /// /// /// private void ReadMatrixPart(string? fieldName, List? currentArray, BuiltInType builtInType, ref List elements, ref List dimensions, int level) { try { if (currentArray?.Count > 0) { var hasInnerArray = false; for (var i = 0; i < currentArray.Count; i++) { if (i == 0 && dimensions.Count <= level) { // remember dimension length dimensions.Add(currentArray.Count); } if (currentArray[i] is List) { hasInnerArray = true; if (!TryGetToken(fieldName, out var token)) { return; } _stack.Push(token); ReadMatrixPart(null, currentArray[i] as List, builtInType, ref elements, ref dimensions, level + 1); _stack.Pop(); } else { break; // do not continue reading array of array } } if (!hasInnerArray) { // read array from one dimension if (ReadArray(null, ValueRanks.OneDimension, builtInType, null, null) is System.Collections.IList part && part.Count > 0) { // add part elements to final list foreach (var item in part) { elements.Add(item); } } } } } catch (Exception ex) { throw new DecodingException(ex.Message, ex); } } /// /// Returns dimensions of the multi dimensional array assuming /// it is not jagged. /// /// /// /// private static int[] GetDimensions(JArray token, out JTokenType type) { var dimensions = new List(); type = JTokenType.Undefined; var array = token; while (array != null && array.Count != 0) { dimensions.Add(array.Count); type = array[0].Type; array = array[0] as JArray; } return [.. dimensions]; } /// /// Works around missing object endings, etc. /// private class JsonLoader : JsonReader { /// public override string Path => _reader.Path; /// public override object? Value => _reader.Value; /// public override JsonToken TokenType { get { if (_eofDepth >= 0) { return JsonToken.EndObject; } if (_eos) { return JsonToken.Null; } if (_reset) { return JsonToken.None; } return _reader.TokenType; } } /// public override int Depth { get { if (_eofDepth >= 0) { return --_eofDepth; } if (_reader.Depth > 0 && _inArray) { return _reader.Depth - 1; } return _reader.Depth; } } /// /// Create loader /// /// public JsonLoader(JsonReader reader) { _reader = reader; _eofDepth = -1; } /// public override bool Read() { if (!_reader.Read()) { _eofDepth = Depth; return true; } // Handle streaming if (_reader.Depth == 0 && ((_inArray && _reader.TokenType == JsonToken.EndArray) || (!_inArray && _reader.TokenType == JsonToken.StartArray))) { _inArray = !_inArray; _eos |= !_inArray && _reset; // Skip to start object _reader.Read(); } // Next token is start of object _reset = false; return true; } /// public void Dispose() { _reader.Close(); } /// /// Reset loader /// public void Reset() { _reset = true; } private readonly JsonReader _reader; private int _eofDepth; private bool _inArray; private bool _reset; private bool _eos; } private readonly JsonReader? _reader; private readonly Stack _stack = new(); } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/JsonEncoderEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Azure.IIoT.OpcUa.Encoders.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Newtonsoft.Json; using Opc.Ua; using Opc.Ua.Extensions; using System; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Xml; /// /// Writes objects to a json /// public sealed class JsonEncoderEx : IEncoder { /// public EncodingType EncodingType => EncodingType.Json; /// public IServiceMessageContext Context { get; } /// public bool UseReversibleEncoding { get; set; } = true; /// /// Encode nodes as uri /// public bool UseUriEncoding { get; set; } = true; /// /// Namespace format to use /// public NamespaceFormat NamespaceFormat { get; set; } = Publisher.Models.NamespaceFormat.Uri; // backcompat /// /// Encode using microsoft variant /// public bool UseAdvancedEncoding { get; set; } /// /// Ignore null values /// public bool IgnoreNullValues { get; set; } /// /// Ignore default primitive values /// public bool IgnoreDefaultValues { get; set; } /// /// State of the writer /// public enum JsonEncoding { /// /// Start writing object (default) /// StartObject, /// /// Start writing array /// Array, /// /// Assume object or array already written /// Token } /// /// Create encoder /// /// /// /// /// /// public JsonEncoderEx(Stream stream, IServiceMessageContext? context = null, JsonEncoding encoding = JsonEncoding.StartObject, Newtonsoft.Json.Formatting formatting = Newtonsoft.Json.Formatting.None, bool leaveOpen = true) : this(new StreamWriter(stream, new UTF8Encoding(false), leaveOpen: leaveOpen), context, encoding, formatting, leaveOpen) { } /// /// Create encoder /// /// /// /// /// /// public JsonEncoderEx(TextWriter writer, IServiceMessageContext? context = null, JsonEncoding encoding = JsonEncoding.StartObject, Newtonsoft.Json.Formatting formatting = Newtonsoft.Json.Formatting.None, bool leaveOpen = true) : this(new JsonTextWriter(writer) { AutoCompleteOnClose = true, DateFormatHandling = DateFormatHandling.IsoDateFormat, FloatFormatHandling = FloatFormatHandling.String, Formatting = formatting, CloseOutput = !leaveOpen }, context, encoding, true) { } /// /// Create encoder /// /// /// /// /// public JsonEncoderEx(JsonWriter writer, IServiceMessageContext? context = null, JsonEncoding encoding = JsonEncoding.StartObject, bool ownedWriter = false) { _namespaces = new Stack(); Context = context ?? new ServiceMessageContext(); _ownedWriter = ownedWriter; _writer = writer ?? throw new ArgumentNullException(nameof(writer)); _encoding = encoding; switch (encoding) { case JsonEncoding.StartObject: _writer.WriteStartObject(); break; case JsonEncoding.Array: _writer.WriteStartArray(); break; } } /// public int Close() { if (_writer != null) { switch (_encoding) { case JsonEncoding.StartObject: _writer.WriteEndObject(); break; case JsonEncoding.Array: _writer.WriteEndArray(); break; } _writer.Flush(); if (_ownedWriter) { _writer.Close(); } _writer = null; } return -1; // Not supported } /// public string? CloseAndReturnText() { throw new NotSupportedException(); } /// public void Dispose() { Close(); } /// public void SetMappingTables(NamespaceTable namespaceUris, StringTable serverUris) { _namespaceMappings = null; if (namespaceUris != null && Context.NamespaceUris != null) { _namespaceMappings = namespaceUris.CreateMapping( Context.NamespaceUris, false); } } /// public void PushNamespace(string namespaceUri) { _namespaces.Push(namespaceUri); } /// public void PopNamespace() { _namespaces.Pop(); } /// public void WriteSwitchField(uint switchField, out string? fieldName) { fieldName = null; WriteUInt32("SwitchField", switchField); } /// public void WriteEncodingMask(uint encodingMask) { WriteUInt32("EncodingMask", encodingMask); } /// public void WriteSByte(string? fieldName, sbyte value) { if (PreWriteValue(fieldName, value)) { _writer?.WriteValue(value); } } /// public void WriteByte(string? fieldName, byte value) { if (PreWriteValue(fieldName, value)) { _writer?.WriteValue(value); } } /// public void WriteInt16(string? fieldName, short value) { if (PreWriteValue(fieldName, value)) { _writer?.WriteValue(value); } } /// public void WriteUInt16(string? fieldName, ushort value) { if (PreWriteValue(fieldName, value)) { _writer?.WriteValue(value); } } /// public void WriteInt32(string? fieldName, int value) { if (PreWriteValue(fieldName, value)) { _writer?.WriteValue(value); } } /// public void WriteUInt32(string? fieldName, uint value) { if (PreWriteValue(fieldName, value)) { _writer?.WriteValue(value); } } /// public void WriteInt64(string? fieldName, long value) { if (PreWriteValue(fieldName, value)) { if (UseAdvancedEncoding) { _writer?.WriteValue(value); } else { _writer?.WriteValue(value.ToString(CultureInfo.InvariantCulture)); } } } /// public void WriteUInt64(string? fieldName, ulong value) { if (PreWriteValue(fieldName, value)) { if (UseAdvancedEncoding) { _writer?.WriteValue(value); } else { _writer?.WriteValue(value.ToString(CultureInfo.InvariantCulture)); } } } /// public void WriteBoolean(string? fieldName, bool value) { if (PreWriteValue(fieldName, value)) { _writer?.WriteValue(value); } } /// public void WriteString(string? fieldName, string? value) { if (value == null) { WriteNull(fieldName); } else { if (!string.IsNullOrEmpty(fieldName)) { _writer?.WritePropertyName(fieldName); } _writer?.WriteValue(value); } } /// public void WriteFloat(string? fieldName, float value) { if (!string.IsNullOrEmpty(fieldName)) { if (IgnoreDefaultValues && Math.Abs(value) < float.Epsilon) { return; } _writer?.WritePropertyName(fieldName); } if (float.IsPositiveInfinity(value)) { _writer?.WriteValue("Infinity"); } else if (float.IsNegativeInfinity(value)) { _writer?.WriteValue("-Infinity"); } else if (float.IsNaN(value)) { _writer?.WriteValue("NaN"); } else { _writer?.WriteRawValue(value.ToString("G9", CultureInfo.InvariantCulture)); } } /// public void WriteDouble(string? fieldName, double value) { if (!string.IsNullOrEmpty(fieldName)) { if (IgnoreDefaultValues && Math.Abs(value) < double.Epsilon) { return; } _writer?.WritePropertyName(fieldName); } if (double.IsPositiveInfinity(value)) { _writer?.WriteValue("Infinity"); } else if (double.IsNegativeInfinity(value)) { _writer?.WriteValue("-Infinity"); } else if (double.IsNaN(value)) { _writer?.WriteValue("NaN"); } else { _writer?.WriteRawValue(value.ToString("G17", CultureInfo.InvariantCulture)); } } /// public void WriteDateTime(string? fieldName, DateTime value) { if (value == default) { WriteNull(fieldName); } else { if (!string.IsNullOrEmpty(fieldName)) { _writer?.WritePropertyName(fieldName); } _writer?.WriteValue(value.ToOpcUaJsonEncodedTime()); } } /// public void WriteGuid(string? fieldName, Uuid value) { if (value == default) { WriteNull(fieldName); } else { if (!string.IsNullOrEmpty(fieldName)) { _writer?.WritePropertyName(fieldName); } _writer?.WriteValue(value); } } /// public void WriteGuid(string? fieldName, Guid value) { if (value == default) { WriteNull(fieldName); } else { if (!string.IsNullOrEmpty(fieldName)) { _writer?.WritePropertyName(fieldName); } _writer?.WriteValue(value); } } /// public void WriteByteString(string? fieldName, byte[]? value) { if (value == null || value.Length == 0) { WriteNull(fieldName); } else { if (!string.IsNullOrEmpty(fieldName)) { _writer?.WritePropertyName(fieldName); } // check the length. if (Context.MaxByteStringLength > 0 && Context.MaxByteStringLength < value.Length) { throw new EncodingException(StatusCodes.BadEncodingLimitsExceeded, $"Maximum nesting level of {Context.MaxEncodingNestingLevels} was exceeded."); } _writer?.WriteValue(value); } } /// public void WriteByteString(string? fieldName, ReadOnlySpan value) { WriteByteString(fieldName, value.ToArray()); } /// public void WriteByteString(string? fieldName, byte[] value, int index, int count) { WriteByteString(fieldName, value.AsSpan().Slice(index, count)); } /// public void WriteXmlElement(string? fieldName, XmlElement? value) { if (value == null) { WriteNull(fieldName); } else { if (!string.IsNullOrEmpty(fieldName)) { _writer?.WritePropertyName(fieldName); } _writer?.WriteValue(Encoding.UTF8.GetBytes(value.OuterXml)); } } /// public void WriteNodeId(string? fieldName, NodeId? value) { if (value == null || NodeId.IsNull(value)) { WriteNull(fieldName); } else if (UseAdvancedEncoding) { if (UseUriEncoding || UseReversibleEncoding) { WriteString(fieldName, value.AsString(Context, NamespaceFormat)); } else { WriteString(fieldName, value.ToString()); } } else { PushObject(fieldName); if (value.IdType != IdType.Numeric) { WriteByte("IdType", (byte)value.IdType); } switch (value.IdType) { case IdType.Numeric: WriteUInt32("Id", (uint)value.Identifier); break; case IdType.String: WriteString("Id", (string)value.Identifier); break; case IdType.Guid: WriteGuid("Id", (Guid)value.Identifier); break; case IdType.Opaque: WriteByteString("Id", (byte[])value.Identifier); break; } switch (value.NamespaceIndex) { case 0: // default namespace - nothing to do break; case 1: // always as integer WriteUInt16("Namespace", value.NamespaceIndex); break; default: var namespaceUri = Context.NamespaceUris.GetString(value.NamespaceIndex); if (namespaceUri != null && !UseReversibleEncoding) { WriteString("Namespace", namespaceUri); } else { WriteUInt16("Namespace", value.NamespaceIndex); } break; } PopObject(); } } /// public void WriteExpandedNodeId(string? fieldName, ExpandedNodeId? value) { if (value == null || NodeId.IsNull(value)) { WriteNull(fieldName); } else if (UseAdvancedEncoding) { if (UseUriEncoding || UseReversibleEncoding) { WriteString(fieldName, value.AsString(Context, NamespaceFormat)); } else { WriteString(fieldName, value.ToString()); } } else { PushObject(fieldName); if (value.IdType != IdType.Numeric) { WriteByte("IdType", (byte)value.IdType); } switch (value.IdType) { case IdType.Numeric: WriteUInt32("Id", (uint)value.Identifier); break; case IdType.String: WriteString("Id", (string)value.Identifier); break; case IdType.Guid: WriteGuid("Id", (Guid)value.Identifier); break; case IdType.Opaque: WriteByteString("Id", (byte[])value.Identifier); break; } var namespaceIndex = value.NamespaceIndex; if (namespaceIndex == 0 && !string.IsNullOrEmpty(value.NamespaceUri)) { namespaceIndex = (ushort)Context.NamespaceUris.GetIndexOrAppend(value.NamespaceUri); } switch (namespaceIndex) { case 0: // default namespace - nothing to do break; case 1: // namespace 1 always as integer WriteUInt16("Namespace", namespaceIndex); break; default: var namespaceUri = UseReversibleEncoding ? null : Context.NamespaceUris.GetString(namespaceIndex); if (namespaceUri != null) { WriteString("Namespace", namespaceUri); } else { WriteUInt16("Namespace", namespaceIndex); } break; } if (value.ServerIndex != 0) { var serverUri = Context.ServerUris.GetString(value.ServerIndex); if (serverUri != null) { WriteString("ServerUri", serverUri); } else { WriteUInt32("ServerUri", value.ServerIndex); } } PopObject(); } } /// public void WriteStatusCode(string? fieldName, StatusCode value) { if (value == StatusCodes.Good) { WriteNull(fieldName); } else { var symbol = string.Empty; if (!UseReversibleEncoding || UseAdvancedEncoding) { symbol = value.AsString(); } if (!UseReversibleEncoding || !string.IsNullOrEmpty(symbol)) { PushObject(fieldName); WriteString("Symbol", symbol); WriteUInt32("Code", value.Code); PopObject(); } else { WriteUInt32(fieldName, value.Code); } } } /// public void WriteDiagnosticInfo(string? fieldName, DiagnosticInfo value) { if (value == null) { WriteNull(fieldName); } else { PushObject(fieldName); if (value.SymbolicId >= 0) { WriteInt32("SymbolicId", value.SymbolicId); } if (value.NamespaceUri >= 0) { WriteInt32("NamespaceUri", value.NamespaceUri); } if (value.Locale >= 0) { WriteInt32("Locale", value.Locale); } if (value.LocalizedText >= 0) { WriteInt32("LocalizedText", value.LocalizedText); } if (value.AdditionalInfo != null) { WriteString("AdditionalInfo", value.AdditionalInfo); } if (value.InnerStatusCode != StatusCodes.Good) { WriteStatusCode("InnerStatusCode", value.InnerStatusCode); } if (value.InnerDiagnosticInfo != null) { WriteDiagnosticInfo("InnerDiagnosticInfo", value.InnerDiagnosticInfo); } PopObject(); } } /// public void WriteQualifiedName(string? fieldName, QualifiedName? value) { if (value == null || QualifiedName.IsNull(value)) { WriteNull(fieldName); } else if (UseReversibleEncoding) { if (UseUriEncoding && UseAdvancedEncoding) { WriteString(fieldName, value.AsString(Context, NamespaceFormat)); } else { // Back compat to json encoding PushObject(fieldName); WriteString("Name", value.Name); if (value.NamespaceIndex > 0) { WriteUInt16("Uri", value.NamespaceIndex); } PopObject(); } } else { PushObject(fieldName); WriteString("Name", value.Name); WriteNamespaceIndex(value.NamespaceIndex); PopObject(); } } /// public void WriteLocalizedText(string? fieldName, LocalizedText? value) { if (value == null || LocalizedText.IsNullOrEmpty(value)) { WriteNull(fieldName); } else if (UseReversibleEncoding) { PushObject(fieldName); WriteString("Text", value.Text); if (!string.IsNullOrEmpty(value.Locale)) { WriteString("Locale", value.Locale); } PopObject(); } else { WriteString(fieldName, value.Text); } } /// public void WriteVariant(string? fieldName, Variant value) { var variant = value; if (UseAdvancedEncoding && value.Value is Variant[] vararray && value.TypeInfo.ValueRank == 1 && vararray.Length > 0) { var type = vararray[0].TypeInfo?.BuiltInType; var rank = vararray[0].TypeInfo?.ValueRank; if (vararray.All(v => v.TypeInfo?.BuiltInType == type)) { try { // Demote and encode as simple array variant = new TypeInfo(type ?? BuiltInType.Null, 1) .CreateVariant(vararray .Select(v => v.Value) .ToArray()); } catch { // Fails when different ranks are in use in array variant = value; } } } var valueRank = variant.TypeInfo?.ValueRank ?? -1; var builtInType = variant.TypeInfo?.BuiltInType ?? BuiltInType.Null; if (UseReversibleEncoding) { PushObject(fieldName); WriteBuiltInType("Type", builtInType); fieldName = "Body"; } if (!string.IsNullOrEmpty(fieldName)) { _writer?.WritePropertyName(fieldName); } WriteVariantContents(variant.Value, valueRank, builtInType); if (UseReversibleEncoding) { PopObject(); } } /// public void WriteDataValue(string? fieldName, DataValue? value) { if (value == null) { WriteNull(fieldName); } else { if (value.StatusCode != StatusCodes.Good || value.SourceTimestamp != DateTime.MinValue || value.ServerTimestamp != DateTime.MinValue || value.SourcePicoseconds != 0 || value.ServerPicoseconds != 0) { PushObject(fieldName); if (value.WrappedValue.TypeInfo != null && value.WrappedValue.TypeInfo.BuiltInType != BuiltInType.Null) { WriteVariant("Value", value.WrappedValue); } if (value.StatusCode != StatusCodes.Good) { WriteStatusCode("StatusCode", value.StatusCode); } if (value.SourceTimestamp != DateTime.MinValue) { WriteDateTime("SourceTimestamp", value.SourceTimestamp); if (value.SourcePicoseconds != 0) { WriteUInt16("SourcePicoseconds", value.SourcePicoseconds); } } if (value.ServerTimestamp != DateTime.MinValue) { WriteDateTime("ServerTimestamp", value.ServerTimestamp); if (value.ServerPicoseconds != 0) { WriteUInt16("ServerPicoseconds", value.ServerPicoseconds); } } PopObject(); } else { // raw value if (value.WrappedValue.TypeInfo != null && value.WrappedValue.TypeInfo.BuiltInType != BuiltInType.Null) { WriteVariant(fieldName, value.WrappedValue); } } } } /// public void WriteExtensionObject(string? fieldName, ExtensionObject? value) { if (value == null) { WriteNull(fieldName); return; } var body = value.Body; if (UseReversibleEncoding) { PushObject(fieldName); var typeId = value.TypeId; if (body is IJsonEncodeable withType) { typeId = withType.JsonEncodingId; } if (!NodeId.IsNull(typeId)) { WriteExpandedNodeId("TypeId", typeId); } else if (!UseAdvancedEncoding) { throw new EncodingException( "Cannot encode extension object without type id."); } if (UseAdvancedEncoding) { // Backcompat if (body is XmlElement) { WriteString("Encoding", nameof(ExtensionObjectEncoding.Xml)); } else if (body is not byte[] and not null) { WriteString("Encoding", nameof(ExtensionObjectEncoding.Json)); } } else { // https://reference.opcfoundation.org/Core/Part6/v105/docs/5.4.2.16 WriteInt32("Encoding", body switch { byte[] => 1, // Byte string XmlElement => 2, // Xml _ => 0, // Structure - omitted in default encoding. }); } fieldName = "Body"; } switch (body) { case EncodeableJToken jt: if (!string.IsNullOrEmpty(fieldName)) { _writer?.WritePropertyName(fieldName); } _writer?.WriteRaw(jt.JToken.ToString()); break; case IEncodeable encodeable: PushObject(fieldName); encodeable.Encode(this); PopObject(); break; case XmlElement xml: WriteXmlElement(fieldName, xml); break; case byte[] buffer: WriteByteString(fieldName, buffer); break; case null: WriteNull(fieldName); break; default: throw new EncodingException("Unexpected value encountered while " + $"encoding body:{body}"); } if (UseReversibleEncoding) { PopObject(); } } /// public void EncodeMessage(IEncodeable message) { message.Encode(this); } /// public void WriteEncodeable(string? fieldName, IEncodeable? value, Type systemType) { if (value == null) { WriteNull(fieldName); } else { PushObject(fieldName); value.Encode(this); PopObject(); } } /// public void WriteEnumerated(string? fieldName, Enum value) { if (value == null) { WriteNull(fieldName); } else { var numeric = Convert.ToInt32(value, CultureInfo.InvariantCulture); if (UseReversibleEncoding) { if (PreWriteValue(fieldName, numeric)) { _writer?.WriteValue(numeric); } } else { WriteString(fieldName, $"{value}_{numeric}"); } } } /// public void WriteBooleanArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => _writer?.WriteValue(v)); } /// public void WriteSByteArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => _writer?.WriteValue(v)); } /// public void WriteByteArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => _writer?.WriteValue(v)); } /// public void WriteInt16Array(string? fieldName, IList? values) { WriteArray(fieldName, values, v => _writer?.WriteValue(v)); } /// public void WriteUInt16Array(string? fieldName, IList? values) { WriteArray(fieldName, values, v => _writer?.WriteValue(v)); } /// public void WriteInt32Array(string? fieldName, IList? values) { WriteArray(fieldName, values, v => _writer?.WriteValue(v)); } /// public void WriteUInt32Array(string? fieldName, IList? values) { WriteArray(fieldName, values, v => _writer?.WriteValue(v)); } /// public void WriteInt64Array(string? fieldName, IList? values) { WriteArray(fieldName, values, v => _writer?.WriteValue(v)); } /// public void WriteUInt64Array(string? fieldName, IList? values) { WriteArray(fieldName, values, v => _writer?.WriteValue(v)); } /// public void WriteFloatArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => _writer?.WriteValue(v)); } /// public void WriteDoubleArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => _writer?.WriteValue(v)); } /// public void WriteStringArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => _writer?.WriteValue(v)); } /// public void WriteStringDictionary(string? property, IEnumerable<(string, string?)> values) { WriteDictionary(property, values, WriteString); } /// public void WriteDateTimeArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteDateTime(null, v)); } /// public void WriteGuidArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteGuid(null, v)); } /// public void WriteGuidArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteGuid(null, v)); } /// public void WriteByteStringArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteByteString(null, v)); } /// public void WriteXmlElementArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteXmlElement(null, v)); } /// public void WriteNodeIdArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteNodeId(null, v)); } /// public void WriteExpandedNodeIdArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteExpandedNodeId(null, v)); } /// public void WriteStatusCodeArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteStatusCode(null, v)); } /// public void WriteDiagnosticInfoArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteDiagnosticInfo(null, v)); } /// public void WriteQualifiedNameArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteQualifiedName(null, v)); } /// public void WriteLocalizedTextArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteLocalizedText(null, v)); } /// public void WriteVariantArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteVariant(null, v)); } /// public void WriteDataValueArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteDataValue(null, v)); } /// public void WriteExtensionObjectArray(string? fieldName, IList? values) { WriteArray(fieldName, values, v => WriteExtensionObject(null, v)); } /// public void WriteEncodeableArray(string? fieldName, IList? values, Type systemType) { WriteArray(fieldName, values, v => WriteEncodeable(null, v, systemType)); } /// public void WriteDataSet(string? property, DataSet? dataSet) { if (dataSet == null) { WriteNull(property); return; } var useUriEncoding = UseUriEncoding; var useReversibleEncoding = UseReversibleEncoding; try { var fieldContentMask = dataSet.DataSetFieldContentMask; var writeSingleValue = (dataSet.DataSetFields.Count == 1) && fieldContentMask.HasFlag(DataSetFieldContentFlags.SingleFieldDegradeToValue); if (fieldContentMask.HasFlag(DataSetFieldContentFlags.RawData)) { // // If the DataSetFieldContentMask results in a RawData representation, // the field value is a Variant encoded using the non-reversible OPC UA // JSON Data Encoding defined in OPC 10000-6 // UseUriEncoding = true; UseReversibleEncoding = false; Write(property, dataSet.DataSetFields, (k, v) => WriteVariant(k, v?.WrappedValue ?? default), writeSingleValue); } else if (fieldContentMask == 0) { // // If the DataSetFieldContentMask results in a Variant representation, // the field value is encoded as a Variant encoded using the reversible // OPC UA JSON Data Encoding defined in OPC 10000-6. // UseUriEncoding = false; UseReversibleEncoding = true; Write(property, dataSet.DataSetFields, (k, v) => WriteVariant(k, v?.WrappedValue ?? default), writeSingleValue); } else { // // If the DataSetFieldContentMask results in a DataValue representation, // the field value is a DataValue encoded using the non-reversible OPC UA // JSON Data Encoding or reversible depending on encoder configuration. // Write(property, dataSet.DataSetFields, (k, value) => { PushObject(k); try { WriteVariant("Value", value?.WrappedValue ?? default); if (value != null) { if (fieldContentMask.HasFlag(DataSetFieldContentFlags.StatusCode)) { WriteStatusCode("StatusCode", value.StatusCode); } if (fieldContentMask.HasFlag(DataSetFieldContentFlags.SourceTimestamp)) { WriteDateTime("SourceTimestamp", value.SourceTimestamp); if (fieldContentMask.HasFlag(DataSetFieldContentFlags.SourcePicoSeconds)) { WriteUInt16("SourcePicoseconds", value.SourcePicoseconds); } } if (fieldContentMask.HasFlag(DataSetFieldContentFlags.ServerTimestamp)) { WriteDateTime("ServerTimestamp", value.ServerTimestamp); if (fieldContentMask.HasFlag(DataSetFieldContentFlags.ServerPicoSeconds)) { WriteUInt16("ServerPicoseconds", value.ServerPicoseconds); } } } } finally { PopObject(); } }, writeSingleValue); } void Write(string? property, IEnumerable<(string, T)> values, Action writer, bool writeSingleValue) { if (writeSingleValue) { writer(property, values.Single().Item2); } else { WriteDictionary(property, values, writer); } } } finally { UseUriEncoding = useUriEncoding; UseReversibleEncoding = useReversibleEncoding; } } /// public void WriteObjectArray(string? property, IList? values) { PushArray(property, values?.Count ?? 0); if (values != null) { foreach (var value in values) { WriteVariant("Variant", new Variant(value)); } } PopArray(); } /// public void WriteEnumeratedArray(string? fieldName, Array? values, Type systemType) { if (values == null) { WriteNull(fieldName); } else { PushArray(fieldName, values.Length); // encode each element in the array. if (systemType.IsEnum) { foreach (Enum value in values) { WriteEnumerated(null, value); } } else if (systemType == typeof(int)) { foreach (int value in values) { WriteInt32(null, value); } } else { throw new ArgumentException("Not an enum type", nameof(systemType)); } PopArray(); } } /// /// Writes the contents of an Variant to the stream. /// /// /// /// /// private void WriteVariantContents(object value, int valueRank, BuiltInType builtInType) { // Handle special value ranks if (valueRank is <= (-2) or 0) { if (valueRank < -3) { throw new EncodingException( $"Bad variant: Value rank '{valueRank}' is invalid."); } // Cannot deduce rank - write null if (value == null) { WriteNull(null); return; } // Handle one or more (0), Any (-2) or scalar or one dimension (-3) if (value.GetType().IsArray) { var rank = value.GetType().GetArrayRank(); if (valueRank == -3 && rank != 1) { throw new EncodingException( "Bad variant: Scalar or one dimension with matrix value."); } // Write as array or matrix valueRank = rank; } else { if (valueRank == 0) { throw new EncodingException( "Bad variant: One or more dimension rank with scalar value."); } // Force write as scalar valueRank = -1; } } // write scalar. if (valueRank == -1) { switch (builtInType) { case BuiltInType.Null: WriteNull(null); return; case BuiltInType.Boolean: WriteBoolean(null, ToTypedScalar(value)); return; case BuiltInType.SByte: WriteSByte(null, ToTypedScalar(value)); return; case BuiltInType.Byte: WriteByte(null, ToTypedScalar(value)); return; case BuiltInType.Int16: WriteInt16(null, ToTypedScalar(value)); return; case BuiltInType.UInt16: WriteUInt16(null, ToTypedScalar(value)); return; case BuiltInType.Int32: WriteInt32(null, ToTypedScalar(value)); return; case BuiltInType.UInt32: WriteUInt32(null, ToTypedScalar(value)); return; case BuiltInType.Int64: WriteInt64(null, ToTypedScalar(value)); return; case BuiltInType.UInt64: WriteUInt64(null, ToTypedScalar(value)); return; case BuiltInType.Float: WriteFloat(null, ToTypedScalar(value)); return; case BuiltInType.Double: WriteDouble(null, ToTypedScalar(value)); return; case BuiltInType.String: WriteString(null, ToTypedScalar(value, null)); return; case BuiltInType.DateTime: WriteDateTime(null, ToTypedScalar(value)); return; case BuiltInType.Guid: WriteGuid(null, ToTypedScalar(value)); return; case BuiltInType.ByteString: WriteByteString(null, ToTypedScalar(value, Array.Empty())); return; case BuiltInType.XmlElement: WriteXmlElement(null, ToTypedScalar(value, null)); return; case BuiltInType.NodeId: WriteNodeId(null, ToTypedScalar(value, null)); return; case BuiltInType.ExpandedNodeId: WriteExpandedNodeId(null, ToTypedScalar(value, null)); return; case BuiltInType.StatusCode: WriteStatusCode(null, ToTypedScalar(value)); return; case BuiltInType.QualifiedName: WriteQualifiedName(null, ToTypedScalar(value, null)); return; case BuiltInType.LocalizedText: WriteLocalizedText(null, ToTypedScalar(value, null)); return; case BuiltInType.ExtensionObject: WriteExtensionObject(null, ToTypedScalar(value, null)); return; case BuiltInType.DataValue: WriteDataValue(null, ToTypedScalar(value, null)); return; case BuiltInType.Enumeration: WriteInt32(null, ToTypedScalar(value)); return; case BuiltInType.Number: case BuiltInType.Integer: case BuiltInType.UInteger: case BuiltInType.Variant: throw new EncodingException( "Bad variant: Unexpected type encountered while encoding " + value.GetType()); } } // write array. if (valueRank == 1) { switch (builtInType) { case BuiltInType.Null: WriteNull(null); return; case BuiltInType.Boolean: WriteBooleanArray(null, ToTypedArray(value)); return; case BuiltInType.SByte: WriteSByteArray(null, ToTypedArray(value)); return; case BuiltInType.Byte: WriteByteArray(null, ToTypedArray(value)); return; case BuiltInType.Int16: WriteInt16Array(null, ToTypedArray(value)); return; case BuiltInType.UInt16: WriteUInt16Array(null, ToTypedArray(value)); return; case BuiltInType.Int32: WriteInt32Array(null, ToTypedArray(value)); return; case BuiltInType.UInt32: WriteUInt32Array(null, ToTypedArray(value)); return; case BuiltInType.Int64: WriteInt64Array(null, ToTypedArray(value)); return; case BuiltInType.UInt64: WriteUInt64Array(null, ToTypedArray(value)); return; case BuiltInType.Float: WriteFloatArray(null, ToTypedArray(value)); return; case BuiltInType.Double: WriteDoubleArray(null, ToTypedArray(value)); return; case BuiltInType.String: WriteStringArray(null, ToTypedArray(value, null)); return; case BuiltInType.DateTime: WriteDateTimeArray(null, ToTypedArray(value)); return; case BuiltInType.Guid: WriteGuidArray(null, ToTypedArray(value)); return; case BuiltInType.ByteString: WriteByteStringArray(null, ToTypedArray(value, null)); return; case BuiltInType.XmlElement: WriteXmlElementArray(null, ToTypedArray(value, null)); return; case BuiltInType.NodeId: WriteNodeIdArray(null, ToTypedArray(value, null)); return; case BuiltInType.ExpandedNodeId: WriteExpandedNodeIdArray(null, ToTypedArray(value, null)); return; case BuiltInType.StatusCode: WriteStatusCodeArray(null, ToTypedArray(value)); return; case BuiltInType.QualifiedName: WriteQualifiedNameArray(null, ToTypedArray(value, null)); return; case BuiltInType.LocalizedText: WriteLocalizedTextArray(null, ToTypedArray(value, null)); return; case BuiltInType.ExtensionObject: WriteExtensionObjectArray(null, ToTypedArray(value, null)); return; case BuiltInType.DataValue: WriteDataValueArray(null, ToTypedArray(value, null)); return; case BuiltInType.Enumeration: if (value is not Enum[] enums) { throw new EncodingException( "Bad enum: Unexpected type encountered while encoding " + $"enumeration type: {value.GetType()}"); } var values = new string[enums.Length]; for (var index = 0; index < enums.Length; index++) { var text = enums[index].ToString(); text += "_"; text += ((int)(object)enums[index]) .ToString(CultureInfo.InvariantCulture); values[index] = text; } WriteStringArray(null, values); return; case BuiltInType.Number: case BuiltInType.UInteger: case BuiltInType.Integer: case BuiltInType.Variant: if (value is Variant[] variants) { WriteVariantArray(null, variants); return; } if (value is object[] objects) { WriteObjectArray(null, objects); return; } throw new EncodingException( "Bad variant: Unexpected type encountered while encoding an array" + $" of Variants: {value.GetType()}"); } } if (valueRank > 1) { // Write matrix if (value == null) { WriteNull(null); return; } // TODO: JSON array encoding only for // non reversible encoding, otherwise // flatten array and add Dimension. // if (!UseReversibleEncoding) { if (value is Matrix matrix) { var index = 0; WriteMatrix(matrix, 0, ref index, builtInType); return; } } // Should never happen. throw new EncodingException( $"Bad variant: Type '{value.GetType().FullName}' is not allowed in Variant."); } /// /// Cast to array /// /// /// /// private static IList ToTypedArray(object value) where T : struct { return ToTypedArray(value, default(T)); } /// /// Cast to array /// /// /// /// /// /// /// private static IList ToTypedArray(object? value, T? defaultValue, Func? outerException = null) { if (value == null) { return []; } if (value is T[] t) { return t; } if (value is not Array arr) { return ToTypedScalar(value, defaultValue).YieldReturn().ToArray(); } if (arr.Length == 0) { return []; } var result = new T?[arr.Length]; for (var index = 0; index < arr.Length; index++) { var item = arr.GetValue(index); if (item == null) { result[index] = defaultValue; continue; } if (item is not byte[] and Array itemArray) { return ToTypedArray(itemArray, defaultValue, ex => GetException(value, arr, item, ex)); } try { result[index] = (T?)item; } catch { try { result[index] = item.As(); } catch (Exception ex) { if (outerException != null) { ex = outerException(ex); } throw GetException(value, arr, item, ex); } } } return result; static EncodingException GetException(object value, Array arr, object item, Exception ex) { return new EncodingException("Bad variant: " + $"Value '{value}' with length {arr.Length} of type '{value.GetType().FullName}'" + $" with item '{item}' of type '{item.GetType().FullName}' is not of type " + $"'{typeof(T).GetType().FullName}'.", ex); } } /// /// Cast to primitive scalar /// /// /// /// private static T ToTypedScalar(object value) where T : struct { return ToTypedScalar(value, default(T)); } /// /// Cast to array /// /// /// /// /// /// [return: NotNullIfNotNull(nameof(defaultValue))] private static T? ToTypedScalar(object? value, T? defaultValue) { try { if (value == null) { return defaultValue; } if (value is T t) { return t; } return (T)value; } catch (Exception ex) { throw new EncodingException( $"Bad variant: Value '{value}' of type '{value?.GetType().FullName}' " + $"is not a scalar of type '{typeof(T).GetType().FullName}'.", ex); } } /// /// Write multi dimensional array /// /// /// /// /// private void WriteMatrix(Matrix matrix, int dim, ref int index, BuiltInType builtInType) { var arrayLen = matrix.Dimensions[dim]; if (dim == matrix.Dimensions.Length - 1) { // Create a slice of values for the top dimension var copy = Array.CreateInstance( matrix.Elements.GetType()!.GetElementType()!, arrayLen); Array.Copy(matrix.Elements, index, copy, 0, arrayLen); // Write slice as value rank WriteVariantContents(copy, 1, builtInType); index += arrayLen; } else { PushArray(null, arrayLen); for (var i = 0; i < arrayLen; i++) { WriteMatrix(matrix, dim + 1, ref index, builtInType); } PopArray(); } } /// /// Write multi dimensional array in structure. /// /// /// /// /// /// /// private void WriteStructureMatrix(string? fieldName, Matrix matrix, int dim, ref int index, TypeInfo typeInfo) { // check the nesting level for avoiding a stack overflow. if (_nestingLevel > Context.MaxEncodingNestingLevels) { throw new EncodingException(StatusCodes.BadEncodingLimitsExceeded, $"Maximum nesting level of {Context.MaxEncodingNestingLevels} was exceeded."); } _nestingLevel++; try { var arrayLen = matrix.Dimensions[dim]; if (dim == matrix.Dimensions.Length - 1) { // Create a slice of values for the top dimension var copy = Array.CreateInstance( matrix.Elements.GetType()!.GetElementType()!, arrayLen); Array.Copy(matrix.Elements, index, copy, 0, arrayLen); // Write slice as value rank WriteVariantContents(copy, 1, typeInfo.BuiltInType); index += arrayLen; } else { PushArray(fieldName, arrayLen); for (var i = 0; i < arrayLen; i++) { WriteStructureMatrix(null, matrix, dim + 1, ref index, typeInfo); } PopArray(); } } finally { _nestingLevel--; } } /// /// Write type /// /// /// private void WriteBuiltInType(string? property, BuiltInType type) { if (UseAdvancedEncoding) { WriteString(property, type.ToString()); } else { WriteByte(property, (byte)type); } } /// /// Writes namespace /// /// private void WriteNamespaceIndex(ushort namespaceIndex) { if (namespaceIndex > 1) { var uri = Context.NamespaceUris.GetString(namespaceIndex); if (!string.IsNullOrEmpty(uri)) { WriteString("Uri", uri); return; } } if (_namespaceMappings != null && _namespaceMappings.Length > namespaceIndex) { namespaceIndex = _namespaceMappings[namespaceIndex]; } if (namespaceIndex != 0) { WriteUInt32("Index", namespaceIndex); } } /// /// Encode an array according to its valueRank and BuiltInType /// /// /// /// /// /// public void WriteArray(string fieldName, object array, int valueRank, BuiltInType builtInType) { // write array. if (valueRank == ValueRanks.OneDimension) { switch (builtInType) { case BuiltInType.Boolean: WriteBooleanArray(fieldName, (bool[])array); return; case BuiltInType.SByte: WriteSByteArray(fieldName, (sbyte[])array); return; case BuiltInType.Byte: WriteByteArray(fieldName, (byte[])array); return; case BuiltInType.Int16: WriteInt16Array(fieldName, (short[])array); return; case BuiltInType.UInt16: WriteUInt16Array(fieldName, (ushort[])array); return; case BuiltInType.Int32: WriteInt32Array(fieldName, (int[])array); return; case BuiltInType.UInt32: WriteUInt32Array(fieldName, (uint[])array); return; case BuiltInType.Int64: WriteInt64Array(fieldName, (long[])array); return; case BuiltInType.UInt64: WriteUInt64Array(fieldName, (ulong[])array); return; case BuiltInType.Float: WriteFloatArray(fieldName, (float[])array); return; case BuiltInType.Double: WriteDoubleArray(fieldName, (double[])array); return; case BuiltInType.String: WriteStringArray(fieldName, (string[])array); return; case BuiltInType.DateTime: WriteDateTimeArray(fieldName, (DateTime[])array); return; case BuiltInType.Guid: WriteGuidArray(fieldName, (Uuid[])array); return; case BuiltInType.ByteString: WriteByteStringArray(fieldName, (byte[][])array); return; case BuiltInType.XmlElement: WriteXmlElementArray(fieldName, (XmlElement[])array); return; case BuiltInType.NodeId: WriteNodeIdArray(fieldName, (NodeId[])array); return; case BuiltInType.ExpandedNodeId: WriteExpandedNodeIdArray(fieldName, (ExpandedNodeId[])array); return; case BuiltInType.StatusCode: WriteStatusCodeArray(fieldName, (StatusCode[])array); return; case BuiltInType.QualifiedName: WriteQualifiedNameArray(fieldName, (QualifiedName[])array); return; case BuiltInType.LocalizedText: WriteLocalizedTextArray(fieldName, (LocalizedText[])array); return; case BuiltInType.ExtensionObject: WriteExtensionObjectArray(fieldName, (ExtensionObject[])array); return; case BuiltInType.DataValue: WriteDataValueArray(fieldName, (DataValue[])array); return; case BuiltInType.DiagnosticInfo: WriteDiagnosticInfoArray(fieldName, (DiagnosticInfo[])array); return; case BuiltInType.Enumeration: if (array is not Array enumArray) { throw new EncodingException( "Unexpected non Array type encountered while encoding an array of enumeration."); } var enumType = enumArray.GetType().GetElementType(); Debug.Assert(enumType != null); WriteEnumeratedArray(fieldName, enumArray, enumType); return; // case BuiltInType.Variant: default: if (array is IEncodeable[] encodeables) { var elementType = array.GetType().GetElementType(); if (elementType != null) { WriteEncodeableArray(fieldName, encodeables, elementType); return; } } switch (array) { case Variant[] variants: WriteVariantArray(fieldName, variants); return; case object[] objects: WriteObjectArray(fieldName, objects); return; case null: WriteObjectArray(fieldName, null); return; } throw new EncodingException("Unexpected type encountered " + $"while encoding an array of Variants: {array.GetType()}"); } } // write matrix. else if (valueRank > ValueRanks.OneDimension) { if (array is Matrix matrix) { var index = 0; WriteStructureMatrix(fieldName, matrix, 0, ref index, matrix.TypeInfo); return; } } } /// /// Write array to stream /// /// /// /// /// internal void WriteArray(string? property, IList? values, Action writer) { if (values == null) { WriteNull(property); } else { PushArray(property, values.Count); foreach (var value in values) { writer(value); } PopArray(); } } /// internal void WriteObject(string? property, T value, Action writer) where T : class { if (value == null) { WriteNull(property); } else { PushObject(property); writer(value); PopObject(); } } /// /// Write array to stream /// /// /// /// /// private void WriteDictionary(string? property, IEnumerable<(string Key, T Value)>? values, Action writer) { if (values == null) { WriteNull(property); } else { PushObject(property); foreach (var (Key, Value) in values) { writer(Key, Value); } PopObject(); } } /// /// Check whether to write the simple value. If so /// andthis is not called in the context of array /// write (property == null) write property. /// /// /// /// /// true if should write value. private bool PreWriteValue(string? property, T value) where T : struct { if (!string.IsNullOrEmpty(property)) { if (IgnoreDefaultValues && EqualityComparer.Default.Equals(value, default)) { return false; } _writer?.WritePropertyName(property); } return true; } /// /// Write null /// /// private void WriteNull(string? property) { if (!string.IsNullOrEmpty(property)) { if (IgnoreNullValues || IgnoreDefaultValues) { // only skip null if not in array context. return; } _writer?.WritePropertyName(property); } _writer?.WriteNull(); } /// /// Push new object /// /// /// private void PushObject(string? property) { if (_nestingLevel > Context.MaxEncodingNestingLevels) { throw new EncodingException(StatusCodes.BadEncodingLimitsExceeded, $"Maximum nesting level of {Context.MaxEncodingNestingLevels} was exceeded"); } if (!string.IsNullOrEmpty(property)) { _writer?.WritePropertyName(property); } _writer?.WriteStartObject(); _nestingLevel++; } /// /// Pop structure /// private void PopObject() { _writer?.WriteEndObject(); _nestingLevel--; } /// /// Push new array /// /// /// /// private void PushArray(string? property, int count) { if (Context.MaxArrayLength > 0 && Context.MaxArrayLength < count) { throw new EncodingException(StatusCodes.BadEncodingLimitsExceeded, $"MaxArrayLength {Context.MaxArrayLength} < {count}."); } if (!string.IsNullOrEmpty(property)) { _writer?.WritePropertyName(property); } _writer?.WriteStartArray(); } /// /// Pop array /// private void PopArray() { _writer?.WriteEndArray(); } private JsonWriter? _writer; private readonly JsonEncoding _encoding; private readonly Stack _namespaces; private ushort[]? _namespaceMappings; private readonly bool _ownedWriter; private uint _nestingLevel; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/JsonVariantEncoder.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Furly.Extensions.Serializers; using Furly.Extensions.Utils; using Opc.Ua; using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; /// /// Variant encoder implementation /// public sealed class JsonVariantEncoder : IVariantEncoder { /// public IServiceMessageContext Context { get; } /// /// Create encoder /// /// /// public JsonVariantEncoder(IServiceMessageContext context, IJsonSerializer serializer) { Context = context; _serializer = serializer; } /// public VariantValue Encode(Variant? value, out BuiltInType builtinType) { if (value == null || value == Variant.Null) { builtinType = BuiltInType.Null; return VariantValue.Null; } using var stream = new MemoryStream(); using (var encoder = new JsonEncoderEx(stream, Context) { UseAdvancedEncoding = true }) { encoder.WriteVariant(nameof(value), value.Value); } var token = _serializer.Parse(stream.ToArray()); Enum.TryParse((string?)token.GetByPath("value.Type"), true, out builtinType); return token.GetByPath("value.Body"); } /// public Variant Decode(VariantValue value, BuiltInType builtinType) { if (value.IsNull()) { return Variant.Null; } // // Sanitize json input from user // value = Sanitize(value, builtinType == BuiltInType.String); string json; if (builtinType == BuiltInType.Null || (builtinType == BuiltInType.Variant && value.IsObject)) { // // Let the decoder try and decode the json variant. // json = _serializer.SerializeToString(new { value }); } else { // // Give decoder a hint as to the type to use to decode. // json = _serializer.SerializeToString(new { value = new { Body = value, Type = (byte)builtinType } }); } // // Decode json to a real variant // using var text = new StringReader(json); using var reader = new Newtonsoft.Json.JsonTextReader(text); using var decoder = new JsonDecoderEx(reader, Context); return decoder.ReadVariant(nameof(value)); } /// /// Sanitizes user input by removing quotes around non strings, /// or adding array brackets to comma seperated values that are /// not string type and recursing through arrays to do the same. /// The output is a pure json token that can be passed to the /// json decoder. /// /// /// /// internal VariantValue Sanitize(VariantValue value, bool isString) { if (value.IsNull()) { return value; } if (!value.TryGetString(out var asString, true, CultureInfo.InvariantCulture)) { asString = _serializer.SerializeToString(value); } if (!value.IsObject && !value.IsListOfValues && !value.IsString) { // // If this should be a string - return as such // return isString ? asString : value; } if (string.IsNullOrWhiteSpace(asString)) { return value; } // // Try to parse string as json // if (!value.IsString) { asString = asString.Replace("\\\"", "\"", StringComparison.Ordinal); } var token = Try.Op(() => _serializer.Parse(asString)); if (token is not null) { value = token; } if (value.IsString) { // // try to split the string as comma seperated list // var elements = asString.Split(','); if (isString) { // // If all elements are quoted, then this is a // string array // if (elements.Length > 1) { var array = new List(); foreach (var element in elements) { var trimmed = element.Trim().TrimQuotes(); if (trimmed == element) { // Treat entire string as value return value; } array.Add(trimmed); } // No need to sanitize contents return _serializer.FromObject(array); } } else { // // First trim any quotes from string before splitting. // if (elements.Length > 1) { // // Parse as array // var trimmed = elements.Select(e => e.TrimQuotes()).ToArray(); try { value = _serializer.Parse( "[" + trimmed.Aggregate((x, y) => x + "," + y) + "]"); } catch { value = _serializer.Parse( "[\"" + trimmed.Aggregate((x, y) => x + "\",\"" + y) + "\"]"); } } else { // // Try to remove next layer of quotes and try again. // var trimmed = asString.Trim().TrimQuotes(); if (trimmed != asString) { return Sanitize(trimmed, isString); } } } } if (value.IsListOfValues) { // // Sanitize each element accordingly // return _serializer.FromObject(value.Values .Select(t => Sanitize(t, isString))); } return value; } private readonly IJsonSerializer _serializer; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/MessageSchemaTypes.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { /// /// Publisher related message schemas /// public static class MessageSchemaTypes { /// /// Monitored item message /// public const string MonitoredItemMessageJson = "application/x-monitored-item-json-v1"; /// /// Json network message /// public const string NetworkMessageJson = "application/x-network-message-json-v1"; /// /// Uadp network message /// public const string NetworkMessageUadp = "application/x-network-message-uadp-v1"; /// /// Avro network message /// public const string NetworkMessageAvro = "application/x-network-message-avro-v0"; /// /// Message contains discovery events /// public const string DiscoveryEvents = "application/x-discovery-event-v2-json"; /// /// Message contains discovery progress messages /// public const string DiscoveryMessage = "application/x-discovery-message-v2-json"; /// /// Runtime state message /// public const string RuntimeStateMessage = "application/x-runtimestate-message-v2-json"; /// /// Writer group diagnostics message /// public const string WriterGroupDiagnosticsMessage = "application/x-writergroup-diagnostics-message-v2-json"; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Models/DataSet.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Models { using Azure.IIoT.OpcUa.Encoders.PubSub; using Azure.IIoT.OpcUa.Publisher.Models; using Opc.Ua; using System; using System.Collections.Generic; using System.Linq; /// /// Encodable dataset message payload /// public class DataSet { /// /// Field mask /// public DataSetFieldContentFlags DataSetFieldContentMask { get; set; } /// /// Entries /// public IReadOnlyList<(string Name, DataValue? Value)> DataSetFields { get; } /// /// Create payload /// /// /// public DataSet(IDictionary values, DataSetFieldContentFlags? fieldContentMask = null) : this(fieldContentMask) { DataSetFields = values.Select(kv => (kv.Key, kv.Value)).ToList(); } /// /// Create payload /// /// /// public DataSet(IReadOnlyList<(string, DataValue?)> values, DataSetFieldContentFlags? fieldContentMask) : this(fieldContentMask) { DataSetFields = values; } /// /// Create payload /// /// /// /// public DataSet(string field, DataValue? value, DataSetFieldContentFlags? fieldContentMask) : this(fieldContentMask) { DataSetFields = new[] { (field, value) }; } /// /// Create default dataset /// /// public DataSet(DataSetFieldContentFlags? fieldContentMask = null) { DataSetFieldContentMask = fieldContentMask ?? PubSubMessage.DefaultDataSetFieldContentFlags; DataSetFields = Array.Empty<(string, DataValue?)>(); } /// public override bool Equals(object? obj) { if (obj is not DataSet set) { return false; } if (!DataSetFields.SequenceEqualsSafe(set.DataSetFields, (x, y) => x.Name == y.Name && Utils.IsEqual(x.Value?.Value, y.Value?.Value))) { return false; } return true; } /// public override int GetHashCode() { return HashCode.Combine(DataSetFields.Select(s => s.Name)); } /// /// Remove field from dataset /// /// /// internal DataSet Remove(string field) { return new DataSet(DataSetFields .Where(b => b.Name != field) .ToList(), DataSetFieldContentMask); } /// /// Set field from dataset to different value /// /// /// /// internal DataSet Set(string field, DataValue? value) { return new DataSet(DataSetFields .Select(b => (b.Name, b.Name == field ? value : b.Value)) .ToList(), DataSetFieldContentMask); } /// /// Set field from dataset to different value /// /// /// /// /// internal DataSet Add(string field, DataValue? value, DataSetFieldContentFlags? additionalFlags = null) { var fieldContentMask = DataSetFieldContentMask; if (additionalFlags.HasValue) { fieldContentMask |= additionalFlags.Value; } return new DataSet(DataSetFields .Append((field, value)) .ToList(), fieldContentMask); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Models/EncodeableDictionary.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Models { using Azure.IIoT.OpcUa.Encoders; using Opc.Ua; using System; using System.Collections.Generic; using System.Linq; /// /// Encodeable dictionary carrying field names and values /// public class EncodeableDictionary : List, IEncodeable, IJsonEncodeable { /// public ExpandedNodeId TypeId => "s=" + nameof(EncodeableDictionary); /// public ExpandedNodeId BinaryEncodingId => "s=" + nameof(EncodeableDictionary) + "_Encoding_DefaultBinary"; /// public ExpandedNodeId XmlEncodingId => "s=" + nameof(EncodeableDictionary) + "_Encoding_DefaultXml"; /// public ExpandedNodeId JsonEncodingId => "s=" + nameof(EncodeableDictionary) + "_Encoding_DefaultJson"; /// /// Initializes the dictionary with default values. /// public EncodeableDictionary() { } /// /// Initializes the dictionary with an initial capacity. /// /// public EncodeableDictionary(int capacity) : base(capacity) { } /// /// Initializes the dictionary with another collection. /// /// public EncodeableDictionary(IEnumerable collection) : base(collection) { } /// public virtual void Encode(IEncoder encoder) { // Get valid dictionary for encoding. var dictionary = this .Where(x => !string.IsNullOrEmpty(x.Key) && x.Value?.Value != null && (x.Value.Value is not LocalizedText lt || lt.Locale != null || lt.Text != null)) .ToDictionary(x => x.Key, x => x.Value); foreach (var keyValuePair in dictionary) { encoder.WriteDataValue(keyValuePair.Key, keyValuePair.Value); } } /// public virtual void Decode(IDecoder decoder) { // Only JSON decoder that can decode a dictionary is supported. if (decoder is not JsonDecoderEx jsonDecoder) { throw new FormatException( $"Cannot decode using the decoder: {decoder.GetType()}."); } var dataSet = jsonDecoder.ReadDataSet(null); if (dataSet != null) { foreach (var (Name, Value) in dataSet.DataSetFields) { Add(new KeyDataValuePair { Key = Name, Value = Value }); } } } /// public virtual bool IsEqual(IEncodeable encodeable) { if (this == encodeable) { return true; } if (encodeable is not EncodeableDictionary encodableDictionary) { return false; } if (!Utils.IsEqual(this, encodableDictionary)) { return false; } return true; } /// public object Clone() { return new EncodeableDictionary(this); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Models/EncodeableJToken.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Models { using Newtonsoft.Json.Linq; using Opc.Ua; using System; /// /// Encodeable wrapper for Json tokens /// public sealed class EncodeableJToken : IEncodeable, IJsonEncodeable { /// /// The encoded object /// public JToken JToken { get; private set; } /// /// Create encodeable token /// /// /// public EncodeableJToken(JToken jToken, ExpandedNodeId typeId) { JToken = jToken ?? throw new ArgumentNullException(nameof(jToken)); TypeId = typeId; } /// public ExpandedNodeId TypeId { get; private set; } /// public ExpandedNodeId JsonEncodingId => "s=" + nameof(EncodeableJToken) + "_Encoding_DefaultJson"; /// public ExpandedNodeId BinaryEncodingId => "s=" + nameof(EncodeableJToken) + "_Encoding_DefaultBinary"; /// public ExpandedNodeId XmlEncodingId => "s=" + nameof(EncodeableJToken) + "_Encoding_DefaultXml"; /// public void Decode(IDecoder decoder) { TypeId = decoder.ReadExpandedNodeId(nameof(TypeId)); JToken = JToken.Parse(decoder.ReadString(nameof(JToken))); } /// public void Encode(IEncoder encoder) { encoder.WriteExpandedNodeId(nameof(TypeId), TypeId); encoder.WriteString(nameof(JToken), JToken.ToString()); } /// public bool IsEqual(IEncodeable encodeable) { if (encodeable is EncodeableJToken wrapper) { return TypeId == wrapper.TypeId && JToken.EqualityComparer.Equals(wrapper.JToken, JToken); } return false; } /// public object Clone() { return new EncodeableJToken(JToken, TypeId); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Models/EncodeableVariantValue.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Models { using Furly.Extensions.Serializers; using Opc.Ua; using System; /// /// Encodeable wrapper for Json tokens /// public sealed class EncodeableVariantValue : IEncodeable, IJsonEncodeable { /// /// The encoded object /// public VariantValue Value { get; private set; } /// /// Create encodeable token /// /// /// public EncodeableVariantValue(IJsonSerializer serializer, VariantValue? value = null) { _serializer = serializer ?? throw new ArgumentNullException(nameof(serializer)); Value = value ?? VariantValue.Null; } /// public ExpandedNodeId TypeId => "s=" + nameof(EncodeableVariantValue); /// public ExpandedNodeId BinaryEncodingId => "s=" + nameof(EncodeableVariantValue) + "_Encoding_DefaultBinary"; /// public ExpandedNodeId XmlEncodingId => "s=" + nameof(EncodeableVariantValue) + "_Encoding_DefaultXml"; /// public ExpandedNodeId JsonEncodingId => "s=" + nameof(EncodeableVariantValue) + "_Encoding_DefaultJson"; /// public void Decode(IDecoder decoder) { Value = _serializer.Parse(decoder.ReadString(nameof(Value))); } /// public void Encode(IEncoder encoder) { encoder.WriteString(nameof(Value), _serializer.SerializeToString(Value)); } /// public bool IsEqual(IEncodeable encodeable) { if (encodeable is EncodeableVariantValue wrapper) { return wrapper.Value == Value; } return false; } /// public object Clone() { return new EncodeableVariantValue(_serializer, Value); } private readonly IJsonSerializer _serializer; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Models/KeyDataValuePair.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Models { using Opc.Ua; using System.Collections.Generic; using System.Runtime.Serialization; /// /// Encodable Key DataValue Pair /// public class KeyDataValuePair : IEncodeable, IJsonEncodeable { /// /// Constructor only to be used when deserializing. /// public KeyDataValuePair() : this(string.Empty, null) { } /// /// The default constructor. /// /// /// public KeyDataValuePair(string key, DataValue? value) { Key = key; Value = value; } /// /// Key /// [DataMember(Name = "Key", IsRequired = true, Order = 1)] public string Key { get; set; } /// /// Value /// [DataMember(Name = "Value", IsRequired = true, Order = 2)] public DataValue? Value { get; set; } /// public virtual ExpandedNodeId? TypeId { get; } /// public virtual ExpandedNodeId? BinaryEncodingId { get; } /// public virtual ExpandedNodeId? XmlEncodingId { get; } /// public virtual ExpandedNodeId? JsonEncodingId { get; } /// public virtual void Encode(IEncoder encoder) { encoder.WriteString("Key", Key); encoder.WriteDataValue(Key, Value); } /// public virtual void Decode(IDecoder decoder) { Key = decoder.ReadString("Key"); Value = decoder.ReadDataValue(Key); } /// public virtual bool IsEqual(IEncodeable encodeable) { if (ReferenceEquals(this, encodeable)) { return true; } if (encodeable is not KeyDataValuePair value) { return false; } if (!Utils.IsEqual(Key, value.Key)) { return false; } if (!Utils.IsEqual(Value, value.Value)) { return false; } return true; } /// public object Clone() { var clone = (KeyDataValuePair)MemberwiseClone(); clone.Key = Utils.Clone(Key); clone.Value = Utils.Clone(Value); return clone; } } /// /// A collection of KeyDataValuePair objects. /// public class KeyDataValuePairCollection : List { /// /// Initializes the collection with default values. /// public KeyDataValuePairCollection() { } /// /// Initializes the collection with an initial capacity. /// /// public KeyDataValuePairCollection(int capacity) : base(capacity) { } /// /// Initializes the collection with another collection. /// /// public KeyDataValuePairCollection(IEnumerable collection) : base(collection) { } /// /// Converts an array to a collection. /// /// public static implicit operator KeyDataValuePairCollection(KeyDataValuePair[] values) { if (values != null) { return new KeyDataValuePairCollection(values); } return []; } /// /// Converts a collection to an array. /// /// public static explicit operator KeyDataValuePair[]?(KeyDataValuePairCollection values) { if (values != null) { return [.. values]; } return null; } /// public new object MemberwiseClone() { var clone = new KeyDataValuePairCollection(Count); for (var ii = 0; ii < Count; ii++) { clone.Add((KeyDataValuePair)Utils.Clone(this[ii])); } return clone; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/PubSub/AvroDataSetMessage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.PubSub { using Azure.IIoT.OpcUa.Encoders; using Avro; using System; using System.Linq; /// /// Avro binary data set message /// public class AvroDataSetMessage : BaseDataSetMessage { /// /// Dataset writer name /// public string? DataSetWriterName { get; set; } /// /// Dataset name /// public string? DataSetName { get; set; } /// /// Dataset header /// internal bool WithDataSetHeader { get; set; } /// public override bool Equals(object? obj) { if (ReferenceEquals(this, obj)) { return true; } if (obj is not AvroDataSetMessage wrapper) { return false; } if (!base.Equals(obj)) { return false; } if (!Opc.Ua.Utils.IsEqual(wrapper.DataSetWriterName, DataSetWriterName)) { return false; } if (!Opc.Ua.Utils.IsEqual(wrapper.DataSetName, DataSetName)) { return false; } return true; } /// public override int GetHashCode() { var hash = new HashCode(); hash.Add(base.GetHashCode()); hash.Add(DataSetWriterName); return hash.ToHashCode(); } /// internal virtual void Encode(BaseAvroEncoder encoder, bool withDataSetHeader) { WithDataSetHeader = withDataSetHeader; // // Messages can be either written in the context of an array // or as a single message or as one of a union of possible // messages. Only if we are in a union we need to write the // union index. Also, we need to get the type name from the // schema so that we can properly validate we are writing the // type. This can be optimized in the future. // var typeName = DataSetName ?? nameof(AvroDataSetMessage); if (encoder is AvroEncoder schemas) { var currentSchema = schemas.Current; if (currentSchema is ArraySchema arr) { // Writing an array of messages currentSchema = arr.ItemSchema; } if (currentSchema is UnionSchema u) { if (DataSetWriterId < u.Count) { typeName = u[DataSetWriterId].Name; } encoder.WriteUnion(null, DataSetWriterId, _ => Encode(typeName)); } else { Encode(currentSchema.Name); } } else { Encode(typeName); } void Encode(string typeName) { if (!WithDataSetHeader) { // If no header, write payload record directly encoder.WriteDataSet(null, Payload); return; } // If header, write data set message encoder.WriteObject(null, typeName, () => { WriteDataSetMessageHeader(encoder); // Write payload encoder.WriteDataSet(nameof(Payload), Payload); }); } } /// internal virtual bool TryDecode(AvroDecoder decoder, bool withDataSetHeader) { // Reset content DataSetMessageContentMask = 0; MessageType = MessageType.KeyFrame; DataSetWriterId = 0; DataSetWriterName = null; SequenceNumber = 0; MetaDataVersion = null; Timestamp = DateTimeOffset.MinValue; WithDataSetHeader = withDataSetHeader; // // Messages can be either written in the context of an array // or as a single message or as one of a union of possible // messages. Only if we are in a union we need to write the // union index. Also, we need to get the type name from the // schema so that we can properly validate we are writing the // type. This can be optimized in the future. // var current = decoder.Current; if (current is ArraySchema arr) { // Reading in the context of an array schema current = arr.ItemSchema; } if (current is UnionSchema union) { return decoder.ReadUnion(null, unionId => { DataSetWriterId = (ushort)unionId; if (!TryDecodeWithHeader()) { return TryDecodeAsDataSet(); } return true; }); } if (!TryDecodeWithHeader()) { return TryDecodeAsDataSet(); } return true; bool TryDecodeAsDataSet() { // Fall back to read the current schema as data set WithDataSetHeader = false; Payload = decoder.ReadDataSet(null); return true; } bool TryDecodeWithHeader() { return decoder.ReadObject(null, schema => { if (schema is not RecordSchema recordSchema) { return false; } // Try first to read the object with header if (recordSchema.Fields.Count > 0 && recordSchema.Fields[0].Name == nameof(MessageType)) { WithDataSetHeader = true; DataSetName = recordSchema.Name; if (DataSetName == nameof(AvroDataSetMessage)) { DataSetName = null; } if (!TryReadDataSetMessageHeader(decoder)) { return false; } // Read payload Payload = decoder.ReadDataSet(nameof(Payload)); return true; } return false; }); } } /// /// Write data set message header /// /// private void WriteDataSetMessageHeader(BaseAvroEncoder encoder) { switch (MessageType) { case MessageType.KeyFrame: encoder.WriteString(nameof(MessageType), "ua-keyframe"); break; case MessageType.Event: encoder.WriteString(nameof(MessageType), "ua-event"); break; case MessageType.KeepAlive: encoder.WriteString(nameof(MessageType), "ua-keepalive"); break; case MessageType.Condition: encoder.WriteString(nameof(MessageType), "ua-condition"); break; case MessageType.DeltaFrame: encoder.WriteString(nameof(MessageType), "ua-deltaframe"); break; } encoder.WriteString(nameof(DataSetWriterName), DataSetWriterName); encoder.WriteUInt16(nameof(DataSetWriterId), DataSetWriterId); // Do we need this? encoder.WriteUInt32(nameof(SequenceNumber), SequenceNumber); encoder.WriteEncodeable(nameof(MetaDataVersion), MetaDataVersion, typeof(Opc.Ua.ConfigurationVersionDataType)); encoder.WriteDateTime(nameof(Timestamp), Timestamp?.UtcDateTime ?? default); var status = Status ?? Payload.DataSetFields .FirstOrDefault(s => Opc.Ua.StatusCode.IsNotGood( s.Value?.StatusCode ?? Opc.Ua.StatusCodes.BadNoData)).Value?.StatusCode ?? Opc.Ua.StatusCodes.Good; encoder.WriteStatusCode(nameof(Status), status); } /// /// Read the data set message header /// /// /// private bool TryReadDataSetMessageHeader(AvroDecoder decoder) { var messageType = decoder.ReadString(nameof(MessageType)); if (messageType != null) { if (messageType.Equals("ua-deltaframe", StringComparison.Ordinal)) { MessageType = MessageType.DeltaFrame; } else if (messageType.Equals("ua-event", StringComparison.Ordinal)) { MessageType = MessageType.Event; } else if (messageType.Equals("ua-keepalive", StringComparison.Ordinal)) { MessageType = MessageType.KeepAlive; } else if (messageType.Equals("ua-condition", StringComparison.Ordinal)) { MessageType = MessageType.Condition; } else if (messageType.Equals("ua-keyframe", StringComparison.Ordinal)) { MessageType = MessageType.KeyFrame; } else { // Continue and treat this as payload. return false; } } DataSetWriterName = decoder.ReadString(nameof(DataSetWriterName)); DataSetWriterId = decoder.ReadUInt16(nameof(DataSetWriterId));// Do we need this? SequenceNumber = decoder.ReadUInt32(nameof(SequenceNumber)); MetaDataVersion = (Opc.Ua.ConfigurationVersionDataType?)decoder.ReadEncodeable( nameof(MetaDataVersion), typeof(Opc.Ua.ConfigurationVersionDataType)); Timestamp = decoder.ReadDateTime(nameof(Timestamp)); Status = decoder.ReadStatusCode(nameof(Status)); return true; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/PubSub/AvroNetworkMessage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.PubSub { using Azure.IIoT.OpcUa.Encoders; using Azure.IIoT.OpcUa.Publisher.Models; using Avro; using System; using System.Buffers; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Linq; using System.Text; /// /// Avro Network message /// public class AvroNetworkMessage : BaseNetworkMessage { /// public override string MessageSchema => MessageSchemaTypes.NetworkMessageAvro; /// public override string ContentType => UseGzipCompression ? Encoders.ContentType.AvroGzip : Encoders.ContentType.Avro; /// public override string ContentEncoding => Encoding.UTF8.WebName; /// /// Ua data message type /// public const string MessageTypeUaData = "ua-data"; /// /// Message schema /// public Schema? Schema { get; set; } /// /// Message id /// public Func MessageId { get; set; } = () => Guid.NewGuid().ToString(); /// /// Message type /// internal string MessageType { get; set; } = MessageTypeUaData; /// /// Get flag that indicates if message has network message header /// public bool HasNetworkMessageHeader => (NetworkMessageContentMask & NetworkMessageContentFlags.NetworkMessageHeader) != 0; /// /// Flag that indicates if the Network message contains a single dataset message /// public bool HasSingleDataSetMessage => (NetworkMessageContentMask & NetworkMessageContentFlags.SingleDataSetMessage) != 0; /// /// Flag that indicates if the Network message dataSets have header /// public bool HasDataSetMessageHeader => (NetworkMessageContentMask & NetworkMessageContentFlags.DataSetMessageHeader) != 0; /// /// Use gzip compression /// public bool UseGzipCompression { get; set; } /// /// Setting to generate concise schemas during encoding /// internal bool EmitConciseSchema { get; set; } /// public override bool Equals(object? obj) { if (ReferenceEquals(this, obj)) { return true; } if (obj is not AvroNetworkMessage wrapper) { return false; } if (!base.Equals(obj)) { return false; } if (!Opc.Ua.Utils.IsEqual(wrapper.MessageId(), MessageId()) || !Opc.Ua.Utils.IsEqual(wrapper.DataSetWriterGroup, DataSetWriterGroup)) { return false; } return true; } /// public override int GetHashCode() { var hash = new HashCode(); hash.Add(base.GetHashCode()); hash.Add(MessageId); hash.Add(DataSetWriterGroup); return hash.ToHashCode(); } /// public override bool TryDecode(Opc.Ua.IServiceMessageContext context, Stream stream, IDataSetMetaDataResolver? resolver) { if (Schema == null) { return false; } var compression = UseGzipCompression ? new GZipStream(stream, CompressionMode.Decompress, leaveOpen: true) : null; try { using var decoder = new AvroDecoder((Stream?)compression ?? stream, Schema, context, true); return TryReadNetworkMessage(decoder); } finally { compression?.Dispose(); } } /// public override bool TryDecode(Opc.Ua.IServiceMessageContext context, Queue> reader, IDataSetMetaDataResolver? resolver) { // Decodes a single buffer if (Schema == null) { return false; } if (reader.TryPeek(out var buffer)) { using var memoryStream = buffer.IsSingleSegment ? Memory.GetStream(buffer.FirstSpan) : Memory.GetStream(buffer.ToArray()); var compression = UseGzipCompression ? new GZipStream(memoryStream, CompressionMode.Decompress, leaveOpen: true) : null; try { using var decoder = new AvroDecoder((Stream?)compression ?? memoryStream, Schema, context); if (!TryReadNetworkMessage(decoder) || memoryStream.Position != memoryStream.Length) { return false; } // Complete the buffer reader.Dequeue(); return true; } finally { compression?.Dispose(); } } return false; } /// public override IReadOnlyList> Encode( Opc.Ua.IServiceMessageContext context, int maxChunkSize, IDataSetMetaDataResolver? resolver = null) { var chunks = new List>(); var messages = Messages.OfType().ToArray().AsSpan(); var messageId = MessageId; try { if (HasSingleDataSetMessage) { for (var i = 0; i < messages.Length; i++) { EncodeMessages(messages.Slice(i, 1)); } } else { EncodeMessages(messages); } } finally { MessageId = messageId; } return chunks; void EncodeMessages(Span messages) { ReadOnlySequence messageBuffer; using (var memoryStream = Memory.GetStream()) { var compression = UseGzipCompression ? new GZipStream(memoryStream, CompressionLevel.Optimal, leaveOpen: true) : null; try { var stream = (Stream?)compression ?? memoryStream; if (Schema == null) { using var encoder = new AvroSchemaBuilder(stream, context, emitConciseSchemas: EmitConciseSchema); WriteMessages(encoder, messages); Schema = encoder.Schema; } else { using var encoder = new AvroEncoder(stream, Schema, context); WriteMessages(encoder, messages); } } finally { compression?.Dispose(); } messageBuffer = memoryStream.GetReadOnlySequence(); // TODO: instead of copy using ToArray we shall include the // stream with the message and dispose it later when it is // consumed. messageBuffer = new ReadOnlySequence(messageBuffer.ToArray()); } if (messageBuffer.Length < maxChunkSize) { chunks.Add(messageBuffer); } else if (messages.Length == 1) { chunks.Add(default); } else { // Split var len = messages.Length / 2; var first = messages[..len]; var second = messages[len..]; EncodeMessages(first); EncodeMessages(second); } } } /// /// Write message span /// /// /// private void WriteMessages(BaseAvroEncoder encoder, Span messages) { var messagesToInclude = messages.ToArray(); WriteNetworkMessage(encoder, messagesToInclude); } /// /// Try decode /// /// /// private bool TryReadNetworkMessage(AvroDecoder decoder) { // Reset DataSetWriterGroup = null; DataSetClassId = default; NetworkMessageContentMask = NetworkMessageContentFlags.DataSetMessageHeader; MessageId = () => Guid.NewGuid().ToString(); PublisherId = null; Messages.Clear(); var current = decoder.Current; var result = decoder.ReadObject(null, schema => { if (schema is not RecordSchema recordSchema) { // Should always be a record at the start return (bool?)null; } if (recordSchema.Fields.Count == 6 && recordSchema.Fields[0].Name == nameof(MessageId) && recordSchema.Fields[5].Name == nameof(Messages)) { // Read network message header NetworkMessageContentMask |= NetworkMessageContentFlags.NetworkMessageHeader; var messageId = decoder.ReadString(nameof(MessageId)); if (messageId != null) { MessageId = () => messageId; } var messageType = decoder.ReadString(nameof(MessageType)); if (!string.Equals(messageType, MessageTypeUaData, StringComparison.OrdinalIgnoreCase)) { // Not a dataset network message return false; } PublisherId = decoder.ReadString(nameof(PublisherId)); DataSetClassId = decoder.ReadGuid(nameof(DataSetClassId)); DataSetWriterGroup = decoder.ReadString(nameof(DataSetWriterGroup)); // Header and content is array of messages return TryReadDataSetMessageArray(decoder, nameof(Messages)); } if (recordSchema.Fields.Count == 1 && recordSchema.Fields[0].Name == nameof(Messages)) { // No header and content is array of messages return TryReadDataSetMessageArray(decoder, nameof(Messages)); } // No header thus content must be single data set message NetworkMessageContentMask |= NetworkMessageContentFlags.SingleDataSetMessage; return null; }); if (!result.HasValue) { // Reposition the schema decoder.Push(current); return TryReadDataSetMessage(decoder); } return result.Value; bool TryReadDataSetMessageArray(AvroDecoder decoder, string fieldName) { // Read objects from field name var result = decoder.ReadArray(fieldName, () => TryReadDataSetMessage(decoder)); if (result.Length == 1) { NetworkMessageContentMask |= NetworkMessageContentFlags.SingleDataSetMessage; } return result.All(s => s); } bool TryReadDataSetMessage(AvroDecoder decoder) { var message = new AvroDataSetMessage(); if (message.TryDecode(decoder, HasDataSetMessageHeader)) { if (!message.WithDataSetHeader) { NetworkMessageContentMask &= ~NetworkMessageContentFlags.DataSetMessageHeader; } Messages.Add(message); return true; } return false; } } /// /// Encode with set messages /// /// /// private void WriteNetworkMessage(BaseAvroEncoder encoder, AvroDataSetMessage[] messages) { if (!HasNetworkMessageHeader && HasSingleDataSetMessage) { Debug.Assert(messages.Length == 1); // Writes data set message or just data set messages[0].Encode(encoder, HasDataSetMessageHeader); return; } var typeName = nameof(AvroNetworkMessage); if (encoder is AvroEncoder schemas) { var schema = schemas.Current; if (schema is ArraySchema arr) { schema = arr.ItemSchema; } typeName = schema.Name; } // Write network message encoder.WriteObject(null, typeName, () => { if (HasNetworkMessageHeader) { encoder.WriteString(nameof(MessageId), MessageId()); encoder.WriteString(nameof(MessageType), MessageType); encoder.WriteString(nameof(PublisherId), PublisherId); encoder.WriteGuid(nameof(DataSetClassId), DataSetClassId); encoder.WriteString(nameof(DataSetWriterGroup), DataSetWriterGroup); } // We write array regardless of single or multi message encoder.WriteArray(nameof(Messages), messages, v => v.Encode(encoder, HasDataSetMessageHeader)); }); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/PubSub/BaseDataSetMessage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.PubSub { using Azure.IIoT.OpcUa.Encoders.Models; using Azure.IIoT.OpcUa.Publisher.Models; using System; /// /// Data set message /// public abstract class BaseDataSetMessage { /// /// Content mask /// public DataSetMessageContentFlags DataSetMessageContentMask { get; set; } /// /// Dataset message type /// public MessageType MessageType { get; set; } /// /// Dataset writer id /// public ushort DataSetWriterId { get; set; } /// /// Metadata version /// public Opc.Ua.ConfigurationVersionDataType? MetaDataVersion { get; set; } /// /// Sequence number /// public uint SequenceNumber { get; set; } /// /// Timestamp /// public DateTimeOffset? Timestamp { get; set; } /// /// Picoseconds /// public uint Picoseconds { get; set; } /// /// Status /// public Opc.Ua.StatusCode? Status { get; set; } /// /// Payload /// public DataSet Payload { get; set; } = new DataSet(); /// /// Endpoint url /// public string? EndpointUrl { get; set; } /// /// Application uri /// public string? ApplicationUri { get; set; } /// public override bool Equals(object? obj) { if (ReferenceEquals(this, obj)) { return true; } if (obj is not BaseDataSetMessage wrapper) { return false; } if (!Opc.Ua.Utils.IsEqual(wrapper.DataSetWriterId, DataSetWriterId) || !Opc.Ua.Utils.IsEqual(wrapper.SequenceNumber, SequenceNumber) || !Opc.Ua.Utils.IsEqual(wrapper.Status ?? Opc.Ua.StatusCodes.Good, Status ?? Opc.Ua.StatusCodes.Good) || !Opc.Ua.Utils.IsEqual(wrapper.Timestamp, Timestamp) || !Opc.Ua.Utils.IsEqual(wrapper.MessageType, MessageType) || !Opc.Ua.Utils.IsEqual(wrapper.MetaDataVersion, MetaDataVersion) || !Opc.Ua.Utils.IsEqual(wrapper.EndpointUrl, EndpointUrl) || !Opc.Ua.Utils.IsEqual(wrapper.ApplicationUri, ApplicationUri)) { return false; } if (wrapper.Payload == null || Payload == null) { return wrapper.Payload == Payload; } return wrapper.Payload.Equals(Payload); } /// public override int GetHashCode() { var hash = new HashCode(); hash.Add(MessageType); hash.Add(DataSetWriterId); hash.Add(SequenceNumber); hash.Add(MetaDataVersion); hash.Add(Timestamp); hash.Add(Picoseconds); hash.Add(Status); hash.Add(Payload); hash.Add(EndpointUrl); hash.Add(ApplicationUri); return hash.ToHashCode(); } internal const string MessageTypeName = "DataSetMessage"; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/PubSub/BaseNetworkMessage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.PubSub { using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.Collections.Generic; /// /// Encodeable Network message /// /// public abstract class BaseNetworkMessage : PubSubMessage { /// /// Message content /// public NetworkMessageContentFlags NetworkMessageContentMask { get; set; } /// /// Dataset class id in case of ua-data message /// public Guid DataSetClassId { get; set; } /// /// Data set metadata in case this is a metadata message /// public PublishedDataSetMetaDataModel? MetaData { get; set; } /// /// DataSet Messages /// #pragma warning disable CA2227 // Collection properties should be read only public IList Messages { get; set; } = []; #pragma warning restore CA2227 // Collection properties should be read only /// public override bool Equals(object? obj) { if (ReferenceEquals(this, obj)) { return true; } if (obj is not BaseNetworkMessage wrapper) { return false; } if (!base.Equals(obj)) { return false; } if (!Opc.Ua.Utils.IsEqual(wrapper.DataSetClassId, DataSetClassId) || !Opc.Ua.Utils.IsEqual(wrapper.Messages, Messages)) { return false; } return true; } /// public override int GetHashCode() { var hash = new HashCode(); hash.Add(base.GetHashCode()); hash.Add(DataSetClassId); foreach (var item in Messages) { hash.Add(item); } return hash.ToHashCode(); } internal const string MessageTypeName = "NetworkMessage"; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/PubSub/EncoderExtensions.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.PubSub { using Azure.IIoT.OpcUa.Encoders; using Newtonsoft.Json.Linq; using System; /// /// Encoder extensions /// internal static class EncoderExtensions { /// /// Test for /// /// /// /// public static bool HasField(this JsonDecoderEx decoder, string property) { if (!decoder.TryGetToken(null, out var token)) { return false; } if (token is JObject o && o.TryGetValue(property, StringComparison.InvariantCultureIgnoreCase, out _)) { return true; } return false; } /// /// Test for array /// /// /// /// public static bool IsArray(this JsonDecoderEx decoder, string? property) { if (!decoder.TryGetToken(property, out var token)) { return false; } return token is JArray; } /// /// Test for array /// /// /// /// public static bool IsObject(this JsonDecoderEx decoder, string? property) { if (!decoder.TryGetToken(property, out var token)) { return false; } return token is JObject; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/PubSub/IDataSetMetaDataResolver.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.PubSub { using Azure.IIoT.OpcUa.Publisher.Models; /// /// Resolve metadata during encoding and decoding /// public interface IDataSetMetaDataResolver { /// /// Find data set metadata or return null if not found. /// /// /// /// /// PublishedDataSetMetaDataModel Find(ushort writerId, uint majorVersion = 0, uint minorVersion = 0); } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/PubSub/JsonDataSetMessage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.PubSub { using Azure.IIoT.OpcUa.Encoders; using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.Linq; /// /// Data set message /// public class JsonDataSetMessage : BaseDataSetMessage { /// /// Compatibility with 2.8 when encoding and decoding /// public bool UseCompatibilityMode { get; set; } /// /// Dataset writer name /// public string? DataSetWriterName { get; set; } /// public override bool Equals(object? obj) { if (ReferenceEquals(this, obj)) { return true; } if (obj is not JsonDataSetMessage wrapper) { return false; } if (!base.Equals(obj)) { return false; } if (!Opc.Ua.Utils.IsEqual(wrapper.DataSetWriterName, DataSetWriterName)) { return false; } return true; } /// public override int GetHashCode() { var hash = new HashCode(); hash.Add(base.GetHashCode()); hash.Add(DataSetWriterName); return hash.ToHashCode(); } /// internal virtual void Encode(JsonEncoderEx encoder, string? publisherId, bool withHeader, string? property) { if (withHeader) { if ((DataSetMessageContentMask & DataSetMessageContentFlags.DataSetWriterId) != 0) { if (!UseCompatibilityMode) { encoder.WriteUInt16(nameof(DataSetWriterId), DataSetWriterId); } else { // Up to version 2.8 we wrote the string id as id which is not per standard encoder.WriteString(nameof(DataSetWriterId), DataSetWriterName); } } if ((DataSetMessageContentMask & DataSetMessageContentFlags.SequenceNumber) != 0) { encoder.WriteUInt32(nameof(SequenceNumber), SequenceNumber); } if ((DataSetMessageContentMask & DataSetMessageContentFlags.MetaDataVersion) != 0) { encoder.WriteEncodeable(nameof(MetaDataVersion), MetaDataVersion, typeof(Opc.Ua.ConfigurationVersionDataType)); } if ((DataSetMessageContentMask & DataSetMessageContentFlags.Timestamp) != 0) { encoder.WriteDateTime(nameof(Timestamp), Timestamp?.UtcDateTime ?? default); } if ((DataSetMessageContentMask & DataSetMessageContentFlags.Status) != 0) { var status = Status ?? Payload.DataSetFields .FirstOrDefault(s => Opc.Ua.StatusCode.IsNotGood(s.Value?.StatusCode ?? Opc.Ua.StatusCodes.BadNoData)).Value?.StatusCode ?? Opc.Ua.StatusCodes.Good; if (!UseCompatibilityMode) { encoder.WriteUInt32(nameof(Status), status.Code); } else { // Up to version 2.8 we wrote the full status code encoder.WriteStatusCode(nameof(Status), status); } } if ((DataSetMessageContentMask & DataSetMessageContentFlags.MessageType) != 0) { switch (MessageType) { case MessageType.KeyFrame: encoder.WriteString(nameof(MessageType), "ua-keyframe"); break; case MessageType.Event: encoder.WriteString(nameof(MessageType), "ua-event"); break; case MessageType.KeepAlive: encoder.WriteString(nameof(MessageType), "ua-keepalive"); break; case MessageType.Condition: encoder.WriteString(nameof(MessageType), "ua-condition"); break; case MessageType.DeltaFrame: encoder.WriteString(nameof(MessageType), "ua-deltaframe"); break; } } if (!UseCompatibilityMode && (DataSetMessageContentMask & DataSetMessageContentFlags.DataSetWriterName) != 0) { encoder.WriteString(nameof(DataSetWriterName), DataSetWriterName); } WritePayload(encoder, nameof(Payload)); } else { WritePayload(encoder, property); } void WritePayload(JsonEncoderEx jsonEncoder, string? propertyName = null) { var useReversibleEncoding = (DataSetMessageContentMask & DataSetMessageContentFlags.ReversibleFieldEncoding) != 0; var prevReversibleEncoding = jsonEncoder.UseReversibleEncoding; try { jsonEncoder.UseReversibleEncoding = useReversibleEncoding; // if propertyname is null we are already inside the object jsonEncoder.WriteDataSet(propertyName, Payload); } finally { // Restore original reversible setting jsonEncoder.UseReversibleEncoding = prevReversibleEncoding; } } } /// internal virtual bool TryDecode(JsonDecoderEx jsonDecoder, string? property, ref bool withHeader, ref string? publisherId) { if (TryReadDataSetMessageHeader(jsonDecoder, out var dataSetMessageContentMask)) { withHeader |= true; DataSetMessageContentMask = dataSetMessageContentMask; var payload = jsonDecoder.ReadDataSet(nameof(Payload)); if (payload != null) { Payload = payload; } return true; } else if (withHeader) { // Previously we found a header, not now, we fail here return false; } else { // Reset content DataSetMessageContentMask = 0; MessageType = MessageType.KeyFrame; DataSetWriterId = 0; DataSetWriterName = null; SequenceNumber = 0; MetaDataVersion = null; Timestamp = DateTimeOffset.MinValue; var payload = property != null && jsonDecoder.HasField(property) ? // Read payload off of the property name jsonDecoder.ReadDataSet(property) : // Read the current object as dataset jsonDecoder.ReadDataSet(null); if (payload != null) { Payload = payload; } return true; } // Read the data set message header bool TryReadDataSetMessageHeader(JsonDecoderEx jsonDecoder, out DataSetMessageContentFlags dataSetMessageContentMask) { dataSetMessageContentMask = 0; if (jsonDecoder.HasField(nameof(DataSetWriterId))) { DataSetWriterId = jsonDecoder.ReadUInt16(nameof(DataSetWriterId)); if (DataSetWriterId == 0) { // Up to version 2.8 we wrote the string id as id which is not per standard DataSetWriterName = jsonDecoder.ReadString(nameof(DataSetWriterId)); if (DataSetWriterName != null) { UseCompatibilityMode = true; dataSetMessageContentMask |= DataSetMessageContentFlags.DataSetWriterId; dataSetMessageContentMask |= DataSetMessageContentFlags.DataSetWriterName; } else { // Continue and treat all of this as payload. return false; } } else { dataSetMessageContentMask |= DataSetMessageContentFlags.DataSetWriterId; } } if (jsonDecoder.HasField(nameof(MetaDataVersion))) { MetaDataVersion = (Opc.Ua.ConfigurationVersionDataType?)jsonDecoder.ReadEncodeable( nameof(MetaDataVersion), typeof(Opc.Ua.ConfigurationVersionDataType)); if (MetaDataVersion != null) { dataSetMessageContentMask |= DataSetMessageContentFlags.MetaDataVersion; } else { // Continue and treat all of this as payload. return false; } } if (jsonDecoder.HasField(nameof(SequenceNumber))) { SequenceNumber = jsonDecoder.ReadUInt32(nameof(SequenceNumber)); dataSetMessageContentMask |= DataSetMessageContentFlags.SequenceNumber; } if (jsonDecoder.HasField(nameof(Timestamp))) { Timestamp = jsonDecoder.ReadDateTime(nameof(Timestamp)); dataSetMessageContentMask |= DataSetMessageContentFlags.Timestamp; } if (jsonDecoder.HasField(nameof(Status))) { UseCompatibilityMode = jsonDecoder.IsObject(nameof(Status)); dataSetMessageContentMask |= DataSetMessageContentFlags.Status; if (!UseCompatibilityMode) { Status = jsonDecoder.ReadUInt32(nameof(Status)); } else { // Up to version 2.8 we wrote the string id as id which is not per standard Status = jsonDecoder.ReadStatusCode(nameof(Status)); } } if (jsonDecoder.HasField(nameof(MessageType))) { var messageType = jsonDecoder.ReadString(nameof(MessageType)); dataSetMessageContentMask |= DataSetMessageContentFlags.MessageType; if (messageType != null) { if (messageType.Equals("ua-deltaframe", StringComparison.Ordinal)) { MessageType = MessageType.DeltaFrame; } else if (messageType.Equals("ua-event", StringComparison.Ordinal)) { MessageType = MessageType.Event; } else if (messageType.Equals("ua-keepalive", StringComparison.Ordinal)) { MessageType = MessageType.KeepAlive; } else if (messageType.Equals("ua-condition", StringComparison.Ordinal)) { MessageType = MessageType.Condition; } else if (messageType.Equals("ua-keyframe", StringComparison.Ordinal)) { MessageType = MessageType.KeyFrame; } else { // Continue and treat this as payload. return false; } } } if (jsonDecoder.HasField(nameof(DataSetWriterName))) { DataSetWriterName = jsonDecoder.ReadString(nameof(DataSetWriterName)); dataSetMessageContentMask |= DataSetMessageContentFlags.DataSetWriterName; } return jsonDecoder.HasField(nameof(Payload)); } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/PubSub/JsonMetadataMessage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.PubSub { using Azure.IIoT.OpcUa.Encoders; using Azure.IIoT.OpcUa.Publisher.Models; using Furly; using System; using System.Buffers; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Text; /// /// Json discovery metdata message /// /// public class JsonMetaDataMessage : PubSubMessage { /// public override string MessageSchema => MessageSchemaTypes.NetworkMessageJson; /// public override string ContentType => UseGzipCompression ? Encoders.ContentType.JsonGzip : ContentMimeType.Json; /// public override string ContentEncoding => Encoding.UTF8.WebName; /// /// Ua meta data message type /// public const string MessageTypeUaMetadata = "ua-metadata"; /// /// Message type /// internal string MessageType { get; set; } = MessageTypeUaMetadata; /// /// Flag that indicates if advanced encoding should be used /// public bool UseAdvancedEncoding { get; set; } /// /// Namespace format to use /// public NamespaceFormat NamespaceFormat { get; set; } /// /// Use gzip compression /// public bool UseGzipCompression { get; set; } /// /// Message id /// public string? MessageId { get; set; } /// /// Data set writer name in case of ua-metadata message /// public ushort DataSetWriterId { get; set; } /// /// Data set writer name in case of ua-metadata message /// public string? DataSetWriterName { get; set; } /// /// Data set metadata in case this is a metadata message /// public PublishedDataSetMetaDataModel? MetaData { get; set; } /// public override bool Equals(object? obj) { if (!base.Equals(obj)) { return false; } if (obj is not JsonMetaDataMessage wrapper) { return false; } if (!Opc.Ua.Utils.IsEqual(wrapper.MessageId, MessageId) || !Opc.Ua.Utils.IsEqual(wrapper.DataSetWriterGroup, DataSetWriterGroup) || !Opc.Ua.Utils.IsEqual(wrapper.DataSetWriterName, DataSetWriterName) || !wrapper.MetaData.IsSameAs(MetaData) || !Opc.Ua.Utils.IsEqual(wrapper.DataSetWriterId, DataSetWriterId)) { return false; } return true; } /// public override int GetHashCode() { var hash = new HashCode(); hash.Add(base.GetHashCode()); hash.Add(MessageId); hash.Add(DataSetWriterGroup); hash.Add(DataSetWriterName); hash.Add(DataSetWriterId); hash.Add(MetaData); return hash.ToHashCode(); } /// public override bool TryDecode(Opc.Ua.IServiceMessageContext context, Stream stream, IDataSetMetaDataResolver? resolver) { throw new NotImplementedException(); } /// public override bool TryDecode(Opc.Ua.IServiceMessageContext context, Queue> reader, IDataSetMetaDataResolver? resolver) { if (reader.TryPeek(out var buffer)) { using var memoryStream = buffer.IsSingleSegment ? Memory.GetStream(buffer.FirstSpan) : Memory.GetStream(buffer.ToArray()); var compression = UseGzipCompression ? new GZipStream(memoryStream, CompressionMode.Decompress, leaveOpen: true) : null; try { using var decoder = new JsonDecoderEx( (Stream?)compression ?? memoryStream, context, useJsonLoader: false); if (TryDecode(decoder)) { reader.Dequeue(); } } finally { compression?.Dispose(); } } return false; } /// public override IReadOnlyList> Encode( Opc.Ua.IServiceMessageContext context, int maxChunkSize, IDataSetMetaDataResolver? resolver) { var chunks = new List>(); using var memoryStream = Memory.GetStream(); var compression = UseGzipCompression ? new GZipStream(memoryStream, CompressionLevel.Optimal, leaveOpen: true) : null; try { using var encoder = new JsonEncoderEx( (Stream?)compression ?? memoryStream, context) { UseAdvancedEncoding = UseAdvancedEncoding, NamespaceFormat = NamespaceFormat, UseUriEncoding = UseAdvancedEncoding, IgnoreDefaultValues = true, IgnoreNullValues = true, UseReversibleEncoding = false }; Encode(encoder); } finally { compression?.Dispose(); } var messageBuffer = memoryStream.GetReadOnlySequence(); if (messageBuffer.Length < maxChunkSize) { // TODO: instead of copy using ToArray we shall include the // stream with the message and dispose it later when it is // consumed. chunks.Add(new ReadOnlySequence(messageBuffer.ToArray())); } else { chunks.Add(default); } return chunks; } /// /// Encode metadata /// /// /// internal void Encode(Opc.Ua.IEncoder encoder) { if (MetaData == null) { throw new EncodingException("No metadata to encode."); } encoder.WriteString(nameof(MessageId), MessageId); encoder.WriteString(nameof(MessageType), MessageType); if (!string.IsNullOrEmpty(PublisherId)) { encoder.WriteString(nameof(PublisherId), PublisherId); } if (DataSetWriterId != 0) { encoder.WriteUInt16(nameof(DataSetWriterId), DataSetWriterId); } if (!string.IsNullOrEmpty(DataSetWriterGroup)) { encoder.WriteString(nameof(DataSetWriterGroup), DataSetWriterGroup); } var dataSetMetaData = MetaData.ToStackModel(encoder.Context); encoder.WriteEncodeable(nameof(MetaData), dataSetMetaData, typeof(Opc.Ua.DataSetMetaDataType)); if (!string.IsNullOrEmpty(DataSetWriterName)) { encoder.WriteString(nameof(DataSetWriterName), DataSetWriterName); } } /// internal bool TryDecode(Opc.Ua.IDecoder decoder) { MessageId = decoder.ReadString(nameof(MessageId)); var messageType = decoder.ReadString(nameof(MessageType)); if (!messageType.Equals(MessageTypeUaMetadata, StringComparison.OrdinalIgnoreCase)) { return false; } PublisherId = decoder.ReadString(nameof(PublisherId)); DataSetWriterId = decoder.ReadUInt16(nameof(DataSetWriterId)); var dataSetMetaData = (Opc.Ua.DataSetMetaDataType)decoder.ReadEncodeable( nameof(MetaData), typeof(Opc.Ua.DataSetMetaDataType)); MetaData = dataSetMetaData.ToServiceModel(decoder.Context); DataSetWriterName = decoder.ReadString(nameof(DataSetWriterName)); return true; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/PubSub/JsonNetworkMessage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.PubSub { using Azure.IIoT.OpcUa.Encoders; using Azure.IIoT.OpcUa.Publisher.Models; using Furly; using System; using System.Buffers; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Linq; using System.Text; /// /// Json Network message /// /// public class JsonNetworkMessage : BaseNetworkMessage { /// public override string MessageSchema => HasSamplesPayload ? MessageSchemaTypes.MonitoredItemMessageJson : MessageSchemaTypes.NetworkMessageJson; /// public override string ContentType => UseGzipCompression ? Encoders.ContentType.JsonGzip : ContentMimeType.Json; /// public override string ContentEncoding => Encoding.UTF8.WebName; /// /// Ua data message type /// public const string MessageTypeUaData = "ua-data"; /// /// Message id /// public Func MessageId { get; set; } = () => Guid.NewGuid().ToString(); /// /// Message type /// internal string MessageType { get; set; } = MessageTypeUaData; /// /// Get flag that indicates if message has network message header /// public bool HasNetworkMessageHeader => (NetworkMessageContentMask & NetworkMessageContentFlags.NetworkMessageHeader) != 0; /// /// Flag that indicates if the Network message contains a single dataset message /// public bool HasSingleDataSetMessage => (NetworkMessageContentMask & NetworkMessageContentFlags.SingleDataSetMessage) != 0; /// /// Flag that indicates if the Network message dataSets have header /// public bool HasDataSetMessageHeader => (NetworkMessageContentMask & NetworkMessageContentFlags.DataSetMessageHeader) != 0; /// /// Flag that indicates if the Network message payload is monitored item samples /// public bool HasSamplesPayload { get { if (_hasSamplesPayload == null) { if (Messages.Count > 0) { _hasSamplesPayload = Messages.Any(m => m is MonitoredItemMessage); } else { return false; } } return _hasSamplesPayload.Value; } set => _hasSamplesPayload = value; } /// /// Sets the message schema to use /// internal string? MessageSchemaToUse { get => MessageSchema; set { HasSamplesPayload = value?.Equals( MessageSchemaTypes.MonitoredItemMessageJson, StringComparison.OrdinalIgnoreCase) == true; } } /// /// Flag that indicates if advanced encoding should be used /// public bool UseAdvancedEncoding { get; set; } /// /// Namespace format to use /// public NamespaceFormat NamespaceFormat { get; set; } /// /// Wrap the resulting message into an array. This is for legacy compatiblity /// where we used to encode a set of network messages in arrays. This is the /// default in OPC Publisher 2.+ if strict compliance with standard is not /// enabled. /// public bool UseArrayEnvelope { get; set; } /// /// Use gzip compression /// public bool UseGzipCompression { get; set; } /// /// Returns the starting state of the json encoder /// private JsonEncoderEx.JsonEncoding JsonEncoderStartingState { get { if (!HasNetworkMessageHeader) { if (!HasSingleDataSetMessage || UseArrayEnvelope) { return JsonEncoderEx.JsonEncoding.Array; } if (!HasDataSetMessageHeader) { return JsonEncoderEx.JsonEncoding.Token; } } if (UseArrayEnvelope) { return JsonEncoderEx.JsonEncoding.Array; } return JsonEncoderEx.JsonEncoding.StartObject; } } /// public override bool Equals(object? obj) { if (ReferenceEquals(this, obj)) { return true; } if (obj is not JsonNetworkMessage wrapper) { return false; } if (!base.Equals(obj)) { return false; } if (!Opc.Ua.Utils.IsEqual(wrapper.MessageId(), MessageId()) || !Opc.Ua.Utils.IsEqual(wrapper.DataSetWriterGroup, DataSetWriterGroup)) { return false; } return true; } /// public override int GetHashCode() { var hash = new HashCode(); hash.Add(base.GetHashCode()); hash.Add(MessageId); hash.Add(DataSetWriterGroup); return hash.ToHashCode(); } /// public override bool TryDecode(Opc.Ua.IServiceMessageContext context, Stream stream, IDataSetMetaDataResolver? resolver) { var compression = UseGzipCompression ? new GZipStream(stream, CompressionMode.Decompress, leaveOpen: true) : null; try { using var decoder = new JsonDecoderEx((Stream?)compression ?? stream, context, useJsonLoader: false); var readArray = decoder.ReadArray(null, () => TryReadNetworkMessage(decoder)); if (readArray?.All(s => s) != true || stream.Length != stream.Position) { return false; } return true; } finally { compression?.Dispose(); } } /// public override bool TryDecode(Opc.Ua.IServiceMessageContext context, Queue> reader, IDataSetMetaDataResolver? resolver = null) { // Decodes a single buffer if (reader.TryPeek(out var buffer)) { using var memoryStream = buffer.IsSingleSegment ? Memory.GetStream(buffer.FirstSpan) : Memory.GetStream(buffer.ToArray()); var compression = UseGzipCompression ? new GZipStream(memoryStream, CompressionMode.Decompress, leaveOpen: true) : null; try { using var decoder = new JsonDecoderEx((Stream?)compression ?? memoryStream, context, useJsonLoader: false); var readArray = decoder.ReadArray(null, () => TryReadNetworkMessage(decoder)); if (readArray?.All(s => s) != true) { return false; } // Complete the buffer reader.Dequeue(); return true; } finally { compression?.Dispose(); } } return false; } /// public override IReadOnlyList> Encode(Opc.Ua.IServiceMessageContext context, int maxChunkSize, IDataSetMetaDataResolver? resolver = null) { var chunks = new List>(); var messages = Messages.OfType().ToArray().AsSpan(); var messageId = MessageId; try { if (HasSingleDataSetMessage && !UseArrayEnvelope) { for (var i = 0; i < messages.Length; i++) { EncodeMessages(messages.Slice(i, 1)); } } else { EncodeMessages(messages); } } finally { MessageId = messageId; } return chunks; void EncodeMessages(Span messages) { ReadOnlySequence messageBuffer; using (var memoryStream = Memory.GetStream()) { var compression = UseGzipCompression ? new GZipStream(memoryStream, CompressionLevel.Optimal, leaveOpen: true) : null; try { using var encoder = new JsonEncoderEx( (Stream?)compression ?? memoryStream, context, JsonEncoderStartingState) { UseAdvancedEncoding = UseAdvancedEncoding, UseUriEncoding = UseAdvancedEncoding, NamespaceFormat = NamespaceFormat, IgnoreDefaultValues = true, IgnoreNullValues = true, UseReversibleEncoding = false }; WriteMessages(encoder, messages); } finally { compression?.Dispose(); } messageBuffer = memoryStream.GetReadOnlySequence(); // TODO: instead of copy using ToArray we shall include the // stream with the message and dispose it later when it is // consumed. messageBuffer = new ReadOnlySequence(messageBuffer.ToArray()); } if (messageBuffer.Length < maxChunkSize) { chunks.Add(messageBuffer); } else if (messages.Length == 1) { chunks.Add(default); } else { // Split var len = messages.Length / 2; var first = messages[..len]; var second = messages[len..]; EncodeMessages(first); EncodeMessages(second); } } } /// /// Write message span /// /// /// private void WriteMessages(JsonEncoderEx encoder, Span messages) { var messagesToInclude = messages.ToArray(); if (UseArrayEnvelope) { if (HasSingleDataSetMessage || HasNetworkMessageHeader) { // Legacy compatibility - n network messages with 1 message each inside array for (var i = 0; i < messages.Length; i++) { var single = messages.Slice(i, 1).ToArray(); if (HasDataSetMessageHeader || HasNetworkMessageHeader) { encoder.WriteObject(null, Messages, _ => WriteNetworkMessage(encoder, single)); } else { // Write single messages into the array envelope WriteNetworkMessage(encoder, single); } } } else { // Write all messages into the array envelope WriteNetworkMessage(encoder, messagesToInclude); } } else { WriteNetworkMessage(encoder, messagesToInclude); } } /// /// Try decode /// /// /// private bool TryReadNetworkMessage(JsonDecoderEx decoder) { if (!HasSamplesPayload && TryReadNetworkMessageHeader(decoder, out var networkMessageContentMask)) { if (decoder.IsObject(nameof(Messages))) { // Single message networkMessageContentMask |= NetworkMessageContentFlags.SingleDataSetMessage; } else if (!decoder.IsArray(nameof(Messages))) { // Messages property is neither object nor array. We might be inside a single dataset // TODO: Should we throw? return false; } NetworkMessageContentMask = networkMessageContentMask; return TryReadDataSetMessages(decoder, nameof(Messages)); } // Reset NetworkMessageContentMask = 0; DataSetWriterGroup = null; DataSetClassId = default; MessageId = () => Guid.NewGuid().ToString(); PublisherId = null; if (decoder.IsObject(null)) { // Treat this object as the single message NetworkMessageContentMask |= NetworkMessageContentFlags.SingleDataSetMessage; } else if (!decoder.IsArray(null)) { // This object we are reading is neither an object nor array return false; } return TryReadDataSetMessages(decoder, null); bool TryReadDataSetMessages(JsonDecoderEx decoder, string? property) { var hasDataSetMessageHeader = false; string? publisherId = null; var messages = decoder.ReadArray(property, () => { var message = !HasSamplesPayload ? new JsonDataSetMessage() : new MonitoredItemMessage(); if (!message.TryDecode(decoder, property, ref hasDataSetMessageHeader, ref publisherId)) { return null; } return message; }); if (messages == null) { return false; } // Add decoded messages to messages array foreach (var message in messages) { if (message == null) { // Reset Messages.Clear(); return false; } Messages.Add(message); } if (hasDataSetMessageHeader) { NetworkMessageContentMask |= NetworkMessageContentFlags.DataSetMessageHeader; } if (publisherId != null) { NetworkMessageContentMask |= NetworkMessageContentFlags.PublisherId; PublisherId = null; } return true; } } /// /// Encode with set messages /// /// /// private void WriteNetworkMessage(JsonEncoderEx encoder, JsonDataSetMessage[] messages) { var publisherId = (NetworkMessageContentMask & NetworkMessageContentFlags.PublisherId) == 0 ? null : PublisherId; if (HasNetworkMessageHeader) { WriteNetworkMessageHeader(encoder); if (HasSingleDataSetMessage) { if (HasDataSetMessageHeader) { // Write as a single object under messages property encoder.WriteObject(nameof(Messages), messages[0], v => v.Encode(encoder, publisherId, true, null)); } else { // Write raw data set object under messages property messages[0].Encode(encoder, publisherId, false, nameof(Messages)); } } else if (HasDataSetMessageHeader) { // Write as array of objects encoder.WriteArray(nameof(Messages), messages, v => encoder.WriteObject(null, v, v => v.Encode(encoder, publisherId, true, null))); } else { // Write as array of dataset payload tokens encoder.WriteArray(nameof(Messages), messages, v => v.Encode(encoder, publisherId, false, null)); } } else { // The encoder was set up as array or object beforehand if (HasSingleDataSetMessage) { // Write object content to current object messages[0].Encode(encoder, publisherId, HasDataSetMessageHeader, null); } else if (HasDataSetMessageHeader) { // Write each object to the array that is the initial state of the encoder foreach (var message in messages) { // Write as array of dataset messages with payload encoder.WriteObject(null, message, v => v.Encode(encoder, publisherId, true, null)); } } else { // Writes dataset directly the encoder was set up as token foreach (var message in messages) { message.Encode(encoder, publisherId, false, null); } } } } /// /// Read network message header /// /// /// /// private bool TryReadNetworkMessageHeader(JsonDecoderEx decoder, out NetworkMessageContentFlags networkMessageContentMask) { networkMessageContentMask = 0; if (!decoder.HasField(nameof(MessageId)) || HasSamplesPayload) { return false; } var messageId = decoder.ReadString(nameof(MessageId)); if (messageId == null) { // Field is there but not of type string, cannot be a network message header return false; } MessageId = () => messageId; var messageType = decoder.ReadString(nameof(MessageType)); if (!string.Equals(messageType, MessageTypeUaData, StringComparison.OrdinalIgnoreCase)) { // Not a dataset network message return false; } networkMessageContentMask |= NetworkMessageContentFlags.NetworkMessageHeader; if (decoder.HasField(nameof(PublisherId))) { PublisherId = decoder.ReadString(nameof(PublisherId)); if (PublisherId != null) { networkMessageContentMask |= NetworkMessageContentFlags.PublisherId; } else { // publisher is not string type, // TODO return false; } } if (decoder.HasField(nameof(DataSetClassId))) { var dataSetClassId = decoder.ReadString(nameof(DataSetClassId)); if (dataSetClassId != null && Guid.TryParse(dataSetClassId, out var result)) { DataSetClassId = result; networkMessageContentMask |= NetworkMessageContentFlags.DataSetClassId; } else { // class id is not guid or string return false; } } if (decoder.HasField(nameof(DataSetWriterGroup))) { DataSetWriterGroup = decoder.ReadString(nameof(DataSetWriterGroup)); if (DataSetWriterGroup == null) { // writer group is not string type // TODO return false; } } return decoder.HasField(nameof(Messages)); } /// /// Write network message header /// /// private void WriteNetworkMessageHeader(JsonEncoderEx encoder) { // The encoder was set up as object beforehand based on IsJsonArray result encoder.WriteString(nameof(MessageId), MessageId()); encoder.WriteString(nameof(MessageType), MessageType); if ((NetworkMessageContentMask & NetworkMessageContentFlags.PublisherId) != 0) { encoder.WriteString(nameof(PublisherId), PublisherId); } if ((NetworkMessageContentMask & NetworkMessageContentFlags.DataSetClassId) != 0 && DataSetClassId != Guid.Empty) { encoder.WriteString(nameof(DataSetClassId), DataSetClassId.ToString()); } if (!string.IsNullOrEmpty(DataSetWriterGroup)) { encoder.WriteString(nameof(DataSetWriterGroup), DataSetWriterGroup); } } private bool? _hasSamplesPayload; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/PubSub/MessageType.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.PubSub { /// /// Message type /// public enum MessageType { /// /// Delta frame /// DeltaFrame, /// /// Key frame /// KeyFrame, /// /// Event /// Event, /// /// Keep alive /// KeepAlive, /// /// Condition /// Condition, /// /// Metadata /// Metadata, /// /// Close notification /// Closed } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/PubSub/MonitoredItemMessage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.PubSub { using Azure.IIoT.OpcUa.Encoders; using Azure.IIoT.OpcUa.Encoders.Utils; using Azure.IIoT.OpcUa.Publisher.Models; using Opc.Ua; using System; using System.Collections.Generic; using System.Linq; /// /// Samples message /// public class MonitoredItemMessage : JsonDataSetMessage { /// /// Node Id in string format as configured /// public string? NodeId { get; set; } /// /// Writer group name (dont change then name for backcompat) /// public string? WriterGroupId { get; set; } /// /// Display name /// public string? DisplayName => Payload.DataSetFields.SingleOrDefault().Name; /// /// Data value for variable change notification /// public Opc.Ua.DataValue? Value => Payload.DataSetFields.SingleOrDefault().Value; /// /// Extension fields /// public IReadOnlyList? ExtensionFields { get; set; } /// public override bool Equals(object? obj) { if (ReferenceEquals(this, obj)) { return true; } if (obj is not MonitoredItemMessage wrapper) { return false; } if (!base.Equals(obj)) { return false; } if (!Opc.Ua.Utils.IsEqual(wrapper.NodeId, NodeId)) { return false; } if (!wrapper.ExtensionFields.SetEqualsSafe(ExtensionFields, (a, b) => a?.Equals(b) ?? b == null)) { return false; } return true; } /// public override int GetHashCode() { var hash = new HashCode(); hash.Add(base.GetHashCode()); hash.Add(NodeId); hash.Add(ExtensionFields); return hash.ToHashCode(); } /// internal override void Encode(JsonEncoderEx encoder, string? publisherId, bool withHeader, string? property) { // // If not writing with samples header or writing to a property we fail. This is a // configuration error, rather than throwing constantly we just do not emit anything // instead. // if (!withHeader || property != null) { return; } if (Payload.DataSetFieldContentMask.HasFlag(DataSetFieldContentFlags.NodeId)) { encoder.WriteString(nameof(NodeId), NodeId); } if (Payload.DataSetFieldContentMask.HasFlag(DataSetFieldContentFlags.EndpointUrl)) { encoder.WriteString(nameof(EndpointUrl), EndpointUrl); } if (Payload.DataSetFieldContentMask.HasFlag(DataSetFieldContentFlags.ApplicationUri)) { encoder.WriteString(nameof(ApplicationUri), ApplicationUri); } if (Payload.DataSetFieldContentMask.HasFlag(DataSetFieldContentFlags.DisplayName) && !string.IsNullOrEmpty(DisplayName)) { encoder.WriteString(nameof(DisplayName), DisplayName); } if (DataSetMessageContentMask.HasFlag(DataSetMessageContentFlags.Timestamp)) { encoder.WriteDateTime(nameof(Timestamp), Timestamp?.UtcDateTime ?? default); } var valuePayload = Value; if (DataSetMessageContentMask.HasFlag(DataSetMessageContentFlags.Status)) { var status = Status; if (status == null) { status = valuePayload != null ? Opc.Ua.StatusCode.IsNotGood(valuePayload.StatusCode) ? valuePayload.StatusCode : Opc.Ua.StatusCodes.Good : (Opc.Ua.StatusCode?)Opc.Ua.StatusCodes.BadNoData; } encoder.WriteString(nameof(Status), status.Value.AsString()); } // Create a copy of the data value and update the timestamps and status var value = new Opc.Ua.DataValue(valuePayload?.WrappedValue ?? Opc.Ua.Variant.Null); if (DataSetMessageContentMask.HasFlag(DataSetMessageContentFlags.Status) || Payload.DataSetFieldContentMask.HasFlag(DataSetFieldContentFlags.StatusCode)) { value.StatusCode = valuePayload?.StatusCode ?? Opc.Ua.StatusCodes.BadNoData; } if (Payload.DataSetFieldContentMask.HasFlag(DataSetFieldContentFlags.SourceTimestamp)) { value.SourceTimestamp = valuePayload?.SourceTimestamp ?? DateTime.MinValue; if (Payload.DataSetFieldContentMask.HasFlag(DataSetFieldContentFlags.SourcePicoSeconds)) { value.SourcePicoseconds = valuePayload?.SourcePicoseconds ?? 0; } } if (Payload.DataSetFieldContentMask.HasFlag(DataSetFieldContentFlags.ServerTimestamp)) { value.ServerTimestamp = valuePayload?.ServerTimestamp ?? DateTime.MinValue; if (Payload.DataSetFieldContentMask.HasFlag(DataSetFieldContentFlags.ServerPicoSeconds)) { value.ServerPicoseconds = valuePayload?.ServerPicoseconds ?? 0; } } var reversibleMode = encoder.UseReversibleEncoding; try { encoder.UseReversibleEncoding = DataSetMessageContentMask.HasFlag(DataSetMessageContentFlags.ReversibleFieldEncoding); encoder.WriteDataValue(nameof(Value), value); } finally { encoder.UseReversibleEncoding = reversibleMode; } if (DataSetMessageContentMask.HasFlag(DataSetMessageContentFlags.SequenceNumber)) { encoder.WriteUInt32(nameof(SequenceNumber), SequenceNumber); } if (Payload.DataSetFieldContentMask.HasFlag(DataSetFieldContentFlags.ExtensionFields)) { var extensionFields = (nameof(DataSetWriterId), DataSetWriterName) .YieldReturn(); if (publisherId != null) { extensionFields = extensionFields .Append((nameof(JsonNetworkMessage.PublisherId), publisherId)); } if (WriterGroupId != null) { extensionFields = extensionFields .Append((nameof(WriterGroupId), WriterGroupId)); } if (ExtensionFields != null) { extensionFields = extensionFields.Concat(ExtensionFields .Where(e => e.DataSetFieldName is not (nameof(DataSetWriterId)) and not (nameof(EndpointUrl)) and not (nameof(ApplicationUri)) and not (nameof(WriterGroupId)) and not (nameof(JsonNetworkMessage.PublisherId))) .Select(e => (e.DataSetFieldName, e.Value.Value?.ToString()))); } // We already wrote application uri and endpoint uri, so do not write again encoder.WriteStringDictionary(nameof(ExtensionFields), extensionFields); } } /// internal override bool TryDecode(JsonDecoderEx decoder, string? property, ref bool withHeader, ref string? publisherId) { // If reading from property return false as this means we are a standard dataset message if (property != null) { return false; } var value = decoder.ReadDataValue(nameof(Value)); DataSetFieldContentFlags dataSetFieldContentMask = 0u; if (value != null) { if (value.ServerTimestamp != DateTime.MinValue) { dataSetFieldContentMask |= DataSetFieldContentFlags.ServerTimestamp; } if (value.ServerPicoseconds != 0) { dataSetFieldContentMask |= DataSetFieldContentFlags.ServerPicoSeconds; } if (value.SourceTimestamp != DateTime.MinValue) { dataSetFieldContentMask |= DataSetFieldContentFlags.SourceTimestamp; } if (value.SourcePicoseconds != 0) { dataSetFieldContentMask |= DataSetFieldContentFlags.SourcePicoSeconds; } if (value.StatusCode != 0) { dataSetFieldContentMask |= DataSetFieldContentFlags.StatusCode; } } // Read header DataSetMessageContentMask = 0u; var displayName = decoder.ReadString(nameof(DisplayName)); if (displayName != null) { dataSetFieldContentMask |= DataSetFieldContentFlags.DisplayName; } NodeId = decoder.ReadString(nameof(NodeId)); if (NodeId != null) { dataSetFieldContentMask |= DataSetFieldContentFlags.NodeId; } EndpointUrl = decoder.ReadString(nameof(EndpointUrl)); if (EndpointUrl != null) { dataSetFieldContentMask |= DataSetFieldContentFlags.EndpointUrl; } ApplicationUri = decoder.ReadString(nameof(ApplicationUri)); if (ApplicationUri != null) { dataSetFieldContentMask |= DataSetFieldContentFlags.ApplicationUri; } var timestamp = decoder.ReadDateTime(nameof(Timestamp)); if (timestamp != DateTime.MinValue) { Timestamp = timestamp; DataSetMessageContentMask |= DataSetMessageContentFlags.Timestamp; } var status = decoder.ReadString(nameof(Status)); if (status != null) { if (TypeMaps.StatusCodes.Value.TryGetIdentifier(status, out var statusCode)) { Status = statusCode; } else { Status = status == "Good" ? Opc.Ua.StatusCodes.Good : Opc.Ua.StatusCodes.Bad; } } SequenceNumber = decoder.ReadUInt32(nameof(SequenceNumber)); if (SequenceNumber != 0) { DataSetMessageContentMask |= DataSetMessageContentFlags.SequenceNumber; } var stringDictionary = decoder.ReadStringDictionary(nameof(ExtensionFields)); if (stringDictionary?.Count > 0) { dataSetFieldContentMask |= DataSetFieldContentFlags.ExtensionFields; var extensionFields = new List(); foreach (var (name, v) in stringDictionary) { if (name == nameof(DataSetWriterId)) { DataSetWriterName = v; } else if (name == nameof(JsonNetworkMessage.PublisherId)) { publisherId = v; } else if (name == nameof(WriterGroupId)) { WriterGroupId = v; } else { extensionFields.Add(new ExtensionFieldModel { DataSetFieldName = name, Value = v }); } } ExtensionFields = extensionFields; } else { ExtensionFields = null; } withHeader |= DataSetMessageContentMask != 0; if (value != null || dataSetFieldContentMask != 0) { Payload = Payload.Add(displayName ?? string.Empty, value, dataSetFieldContentMask); return true; } // Only return true if we otherwise read a header value return withHeader; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/PubSub/PubSubMessage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.PubSub { using Azure.IIoT.OpcUa.Encoders.Models; using Azure.IIoT.OpcUa.Encoders.Schemas; using Azure.IIoT.OpcUa.Publisher.Models; using Furly; using Furly.Extensions.Messaging; using Microsoft.IO; using System; using System.Buffers; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; /// /// Encodeable PubSub messages /// /// public abstract class PubSubMessage { /// /// Network message defaults /// public const NetworkMessageContentFlags DefaultNetworkMessageContentFlags = NetworkMessageContentFlags.NetworkMessageHeader | NetworkMessageContentFlags.NetworkMessageNumber | NetworkMessageContentFlags.DataSetMessageHeader | NetworkMessageContentFlags.PublisherId | NetworkMessageContentFlags.DataSetClassId; /// /// Default field mask /// public const DataSetFieldContentFlags DefaultDataSetFieldContentFlags = DataSetFieldContentFlags.StatusCode | DataSetFieldContentFlags.SourcePicoSeconds | DataSetFieldContentFlags.SourceTimestamp | DataSetFieldContentFlags.ServerPicoSeconds | DataSetFieldContentFlags.ServerTimestamp; /// /// Default message flags /// public const DataSetMessageContentFlags DefaultDataSetMessageContentFlags = DataSetMessageContentFlags.DataSetWriterId | DataSetMessageContentFlags.DataSetWriterName | DataSetMessageContentFlags.MetaDataVersion | DataSetMessageContentFlags.MajorVersion | DataSetMessageContentFlags.MinorVersion | DataSetMessageContentFlags.SequenceNumber | DataSetMessageContentFlags.Timestamp | DataSetMessageContentFlags.MessageType | DataSetMessageContentFlags.Status; /// /// Message schema /// public abstract string MessageSchema { get; } /// /// Content type /// public abstract string ContentType { get; } /// /// Content encoding /// public abstract string? ContentEncoding { get; } /// /// Publisher identifier /// public string? PublisherId { get; set; } /// /// Dataset writerGroup /// public string? DataSetWriterGroup { get; set; } /// /// Memory stream manager /// protected static RecyclableMemoryStreamManager Memory { get; } = new RecyclableMemoryStreamManager(); /// /// Decode the network message from the wire representation /// /// /// /// public abstract bool TryDecode(Opc.Ua.IServiceMessageContext context, Queue> reader, IDataSetMetaDataResolver? resolver = null); /// /// Decode the network message from the wire representation /// /// /// /// public abstract bool TryDecode(Opc.Ua.IServiceMessageContext context, Stream stream, IDataSetMetaDataResolver? resolver = null); /// /// Encode the network message into network message chunks /// wire representation. /// /// /// /// /// public abstract IReadOnlyList> Encode( Opc.Ua.IServiceMessageContext context, int maxChunkSize, IDataSetMetaDataResolver? resolver = null); /// /// Create metadata message /// /// /// /// /// /// /// /// /// /// /// public static bool TryCreateMetaDataMessage(MessageEncoding encoding, string? publisherId, string writerGroupName, string dataSetWriterName, ushort dataSetWriterId, PublishedDataSetMetaDataModel metaData, NamespaceFormat namespaceFormat, bool standardsCompliant, [NotNullWhen(true)] out PubSubMessage? message) { if (encoding.HasFlag(MessageEncoding.Json)) { message = new JsonMetaDataMessage { UseAdvancedEncoding = !standardsCompliant, NamespaceFormat = namespaceFormat, UseGzipCompression = encoding.HasFlag(MessageEncoding.IsGzipCompressed), DataSetWriterId = dataSetWriterId, MetaData = metaData, MessageId = Guid.NewGuid().ToString(), DataSetWriterName = dataSetWriterName, PublisherId = publisherId, DataSetWriterGroup = writerGroupName }; } else if (encoding.HasFlag(MessageEncoding.Uadp)) { message = new UadpMetaDataMessage { DataSetWriterId = dataSetWriterId, MetaData = metaData, PublisherId = publisherId, DataSetWriterGroup = writerGroupName }; } else { message = default; return false; } return true; } /// /// Create dataset message /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// public static bool TryCreateDataSetMessage(MessageEncoding encoding, string dataSetWriterName, ushort dataSetWriterId, DataSetMessageContentFlags? dataSetMessageContentFlags, MessageType messageType, DataSet payload, DateTimeOffset? timestamp, uint sequenceNumber, bool standardsCompliant, string? endpointUrl, string? applicationUri, PublishedDataSetMetaDataModel? metaData, [NotNullWhen(true)] out BaseDataSetMessage? message) { dataSetMessageContentFlags ??= DefaultDataSetMessageContentFlags; var version = new Opc.Ua.ConfigurationVersionDataType { MajorVersion = metaData?.DataSetMetaData.MajorVersion ?? 1, MinorVersion = metaData?.MinorVersion ?? 0 }; if (encoding.HasFlag(MessageEncoding.Json)) { message = new JsonDataSetMessage { UseCompatibilityMode = !standardsCompliant, DataSetWriterName = dataSetWriterName, DataSetWriterId = dataSetWriterId, MessageType = messageType, MetaDataVersion = version, ApplicationUri = applicationUri, EndpointUrl = endpointUrl, DataSetMessageContentMask = dataSetMessageContentFlags.Value, Timestamp = timestamp, SequenceNumber = sequenceNumber, Payload = payload }; } else if (encoding.HasFlag(MessageEncoding.Avro)) { message = new AvroDataSetMessage { DataSetWriterName = dataSetWriterName, DataSetWriterId = dataSetWriterId, MessageType = messageType, MetaDataVersion = version, DataSetMessageContentMask = dataSetMessageContentFlags.Value, Timestamp = timestamp, SequenceNumber = sequenceNumber, Payload = payload }; } else if (encoding.HasFlag(MessageEncoding.Uadp)) { message = new UadpDataSetMessage { DataSetWriterId = dataSetWriterId, MessageType = messageType, MetaDataVersion = version, DataSetMessageContentMask = dataSetMessageContentFlags.Value, Timestamp = timestamp, SequenceNumber = sequenceNumber, Payload = payload }; } else { message = default; return false; } return true; } /// /// Create monitored item message /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// public static bool TryCreateMonitoredItemMessage(MessageEncoding encoding, string? writerGroupName, DataSetMessageContentFlags? dataSetMessageContentFlags, MessageType messageType, DateTimeOffset? timestamp, uint sequenceNumber, DataSet payload, string? nodeId, string? endpointUrl, string? applicationUri, bool standardsCompliant, IReadOnlyList? extensionFields, [NotNullWhen(true)] out BaseDataSetMessage? message) { if (encoding.HasFlag(MessageEncoding.Json)) { message = new MonitoredItemMessage { UseCompatibilityMode = !standardsCompliant, ApplicationUri = applicationUri, EndpointUrl = endpointUrl, NodeId = nodeId, ExtensionFields = extensionFields, WriterGroupId = writerGroupName, MessageType = messageType, DataSetMessageContentMask = dataSetMessageContentFlags ?? DefaultDataSetMessageContentFlags, Timestamp = timestamp, SequenceNumber = sequenceNumber, Payload = payload }; } else { message = default; return false; } return true; } /// /// Create network message /// /// /// /// /// /// /// /// /// /// /// /// /// /// public static bool TryCreateNetworkMessage(MessageEncoding encoding, string publisherId, string writerGroupName, NetworkMessageContentFlags? networkMessageContentFlags, Guid dataSetClassId, Func sequenceNumber, DateTimeOffset timestamp, NamespaceFormat namespaceFormat, bool standardsCompliant, bool isBatched, IEventSchema? schema, [NotNullWhen(true)] out BaseNetworkMessage? message) { if (encoding.HasFlag(MessageEncoding.Json)) { message = new JsonNetworkMessage { UseAdvancedEncoding = !standardsCompliant, UseGzipCompression = encoding.HasFlag(MessageEncoding.IsGzipCompressed), NamespaceFormat = namespaceFormat, UseArrayEnvelope = !standardsCompliant && isBatched, MessageId = () => Guid.NewGuid().ToString(), NetworkMessageContentMask = networkMessageContentFlags ?? DefaultNetworkMessageContentFlags, PublisherId = publisherId, DataSetClassId = dataSetClassId, DataSetWriterGroup = writerGroupName }; } else if (encoding.HasFlag(MessageEncoding.Avro)) { message = new AvroNetworkMessage { Schema = (schema is Schemas.Avro.IAvroSchema s) ? s.Schema : schema == null ? null : Avro.Schema.Parse(schema.Schema), UseGzipCompression = encoding.HasFlag(MessageEncoding.IsGzipCompressed), MessageId = () => Guid.NewGuid().ToString(), NetworkMessageContentMask = networkMessageContentFlags ?? DefaultNetworkMessageContentFlags, PublisherId = publisherId, DataSetClassId = dataSetClassId, DataSetWriterGroup = writerGroupName }; } else if (encoding.HasFlag(MessageEncoding.Uadp)) { message = new UadpNetworkMessage { // WriterGroupId = writerGroup.Index, // GroupVersion = writerGroup.Version, SequenceNumber = sequenceNumber, Timestamp = timestamp, PicoSeconds = 0, NetworkMessageContentMask = networkMessageContentFlags ?? DefaultNetworkMessageContentFlags, PublisherId = publisherId, DataSetClassId = dataSetClassId, DataSetWriterGroup = writerGroupName }; } else { message = default; return false; } return true; } /// /// Create network message schema /// /// /// /// /// /// public static bool TryCreateNetworkMessageSchema(MessageEncoding encoding, PublishedNetworkMessageSchemaModel networkMessage, [NotNullWhen(true)] out IEventSchema? schema, SchemaOptions? options = null) { if (encoding.HasFlag(MessageEncoding.Json) && options?.PreferAvroOverJsonSchema == true) { schema = new Schemas.Avro.JsonNetworkMessage(networkMessage, options); } else if (encoding.HasFlag(MessageEncoding.Json)) { schema = new Schemas.Json.JsonNetworkMessage(networkMessage, options); } else if (encoding.HasFlag(MessageEncoding.Avro)) { schema = new Schemas.Avro.AvroNetworkMessage(networkMessage, options); } else if (encoding.HasFlag(MessageEncoding.Uadp)) { schema = new Schemas.Uadp.UadpNetworkMessage(networkMessage); } else { schema = default; return false; } return true; } /// /// Decode pub sub messages from a single network buffer. If the message /// was chunked, the message might not be fully reconstituted. /// /// /// /// /// /// /// public static PubSubMessage? Decode(ReadOnlySequence buffer, string contentType, Opc.Ua.IServiceMessageContext context, IDataSetMetaDataResolver? resolver = null, string? messageSchema = null) { var reader = new Queue>(); reader.Enqueue(buffer); return DecodeOne(reader, contentType, context, resolver, messageSchema); } /// /// Decode all messages from the provided chunk reader. The reader /// is a queue of byte sequences, each representing a network buffer. /// /// /// /// /// /// /// public static IEnumerable Decode(Queue> reader, string contentType, Opc.Ua.IServiceMessageContext context, IDataSetMetaDataResolver? resolver = null, string? messageSchema = null) { while (true) { var message = DecodeOne(reader, contentType, context, resolver, messageSchema); if (message == null) { yield break; } else { yield return message; } } } /// /// Decode messages from stream. The stream will be read until the /// entire message has been loaded. UADP messages can be chunked /// the stream therefore must include all chunks to decode successfully. /// /// /// /// /// /// /// public static IEnumerable Decode(Stream stream, string contentType, Opc.Ua.IServiceMessageContext context, IDataSetMetaDataResolver? resolver = null, string? messageSchema = null) { while (stream.Position != stream.Length) { PubSubMessage message; long pos; #pragma warning disable CA1308 // Normalize strings to uppercase switch (contentType.ToLowerInvariant()) { case Encoders.ContentType.JsonGzip: case ContentMimeType.Json: case Encoders.ContentType.UaJson: case Encoders.ContentType.UaLegacyPublisher: case Encoders.ContentType.UaNonReversibleJson: message = new JsonNetworkMessage { MessageSchemaToUse = messageSchema, UseGzipCompression = contentType.Equals( Encoders.ContentType.JsonGzip, StringComparison.OrdinalIgnoreCase) }; pos = stream.Position; if (message.TryDecode(context, stream, resolver)) { yield return message; } else { stream.Position = pos; message = new JsonMetaDataMessage(); if (message.TryDecode(context, stream, resolver)) { yield return message; } else { yield break; } } break; case ContentMimeType.Binary: case Encoders.ContentType.Uadp: message = new UadpNetworkMessage(); pos = stream.Position; if (message.TryDecode(context, stream, resolver)) { yield return message; } else { stream.Position = pos; message = new UadpDiscoveryMessage(); if (message.TryDecode(context, stream, resolver)) { yield return message; } else { yield break; } } break; case Encoders.ContentType.Avro: case Encoders.ContentType.AvroGzip: case ContentMimeType.AvroBinary: message = new AvroNetworkMessage { Schema = Avro.Schema.Parse(messageSchema), UseGzipCompression = contentType.Equals( Encoders.ContentType.AvroGzip, StringComparison.OrdinalIgnoreCase) }; if (message.TryDecode(context, stream, resolver)) { yield return message; } else { yield break; } break; default: break; } #pragma warning restore CA1308 // Normalize strings to uppercase } } /// /// Decode one pub sub messages from the chunks provided by the reader /// Avro and JSON do not support chunking hence only ever one chunk is /// pulled from the reader. /// /// /// /// /// /// /// internal static PubSubMessage? DecodeOne(Queue> reader, string contentType, Opc.Ua.IServiceMessageContext context, IDataSetMetaDataResolver? resolver, string? messageSchema = null) { if (reader.Count == 0) { return null; } PubSubMessage message; #pragma warning disable CA1308 // Normalize strings to uppercase switch (contentType.ToLowerInvariant()) { case Encoders.ContentType.JsonGzip: case ContentMimeType.Json: case Encoders.ContentType.UaJson: case Encoders.ContentType.UaLegacyPublisher: case Encoders.ContentType.UaNonReversibleJson: message = new JsonNetworkMessage { MessageSchemaToUse = messageSchema, UseGzipCompression = contentType.Equals( Encoders.ContentType.JsonGzip, StringComparison.OrdinalIgnoreCase) }; if (message.TryDecode(context, reader, resolver)) { return message; } if (reader.Count == 0) { return null; } message = new JsonMetaDataMessage(); if (message.TryDecode(context, reader, resolver)) { return message; } break; case ContentMimeType.Binary: case Encoders.ContentType.Uadp: message = new UadpNetworkMessage(); if (message.TryDecode(context, reader, resolver)) { return message; } if (reader.Count == 0) { return null; } message = new UadpDiscoveryMessage(); if (message.TryDecode(context, reader, resolver)) { return message; } break; case Encoders.ContentType.Avro: case Encoders.ContentType.AvroGzip: case ContentMimeType.AvroBinary: message = new AvroNetworkMessage { Schema = Avro.Schema.Parse(messageSchema), UseGzipCompression = contentType.Equals( Encoders.ContentType.AvroGzip, StringComparison.OrdinalIgnoreCase) }; if (message.TryDecode(context, reader, resolver)) { return message; } if (reader.Count == 0) { return null; } break; default: break; } #pragma warning restore CA1308 // Normalize strings to uppercase // Failed return null; } /// public override bool Equals(object? obj) { if (ReferenceEquals(this, obj)) { return true; } if (obj is not PubSubMessage wrapper) { return false; } if (!Opc.Ua.Utils.IsEqual(wrapper.PublisherId, PublisherId)) { return false; } return true; } /// public override int GetHashCode() { var hash = new HashCode(); hash.Add(PublisherId); return hash.ToHashCode(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/PubSub/StackExtensions.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.PubSub { using Azure.IIoT.OpcUa.Publisher.Models; using Opc.Ua; using Opc.Ua.Extensions; using System; using System.Collections.Generic; using System.Linq; /// /// Metadata extensions /// internal static class StackExtensions { /// /// Compare /// /// /// /// public static bool IsSameAs(this PublishedDataSetMetaDataModel? model, PublishedDataSetMetaDataModel? that) { if (model == null && that == null) { return true; } if (model == null || that == null) { return false; } return model.DataSetMetaData.IsSameAs(that.DataSetMetaData) && model.MinorVersion == that.MinorVersion && model.StructureDataTypes.SequenceEqualsSafe(that.StructureDataTypes, IsSameAs) && model.EnumDataTypes.SequenceEqualsSafe(that.EnumDataTypes, IsSameAs) && model.SimpleDataTypes.SequenceEqualsSafe(that.SimpleDataTypes, IsSameAs) && model.Fields.SequenceEqualsSafe(that.Fields, IsSameAs) ; } /// /// Convert to stack model /// /// /// /// public static DataSetMetaDataType ToStackModel( this PublishedDataSetMetaDataModel model, IServiceMessageContext context) { return new DataSetMetaDataType { Name = model.DataSetMetaData.Name, Description = model.DataSetMetaData.Description, DataSetClassId = (Uuid)model.DataSetMetaData.DataSetClassId, Namespaces = context.NamespaceUris.ToArray(), StructureDataTypes = model.StructureDataTypes? .Select(s => s.ToStackModel(context)).ToArray(), EnumDataTypes = model.EnumDataTypes? .Select(e => e.ToStackModel(context)).ToArray(), SimpleDataTypes = model.SimpleDataTypes? .Select(e => e.ToStackModel(context)).ToArray(), Fields = model.Fields .Select(e => e.ToStackModel(context)).ToArray(), ConfigurationVersion = new ConfigurationVersionDataType { MajorVersion = model.DataSetMetaData.MajorVersion ?? 1, MinorVersion = model.MinorVersion } }; } /// /// Convert to stack model /// /// /// /// public static PublishedDataSetMetaDataModel? ToServiceModel( this DataSetMetaDataType? model, IServiceMessageContext? context = null) { if (model == null) { return null; } var localContext = new ServiceMessageContext(); if (model.Namespaces != null) { foreach (var ns in model.Namespaces) { localContext.NamespaceUris.GetIndexOrAppend(ns); } } if (context != null) { for (var i = 0; i < context.NamespaceUris.Count; i++) { localContext.NamespaceUris.GetIndexOrAppend( context.NamespaceUris.GetString((uint)i)); } } context = localContext; return new PublishedDataSetMetaDataModel { DataSetMetaData = new DataSetMetaDataModel { Name = model.Name, Description = model.Description.AsString(), DataSetClassId = model.DataSetClassId, MajorVersion = model.ConfigurationVersion.MajorVersion }, MinorVersion = model.ConfigurationVersion.MinorVersion, StructureDataTypes = model.StructureDataTypes? .Select(s => s.ToServiceModel(context)).ToArray(), EnumDataTypes = model.EnumDataTypes? .Select(e => e.ToServiceModel(context)).ToArray(), SimpleDataTypes = model.SimpleDataTypes? .Select(e => e.ToServiceModel(context)).ToArray(), Fields = model.Fields .Select(e => e.ToServiceModel(context)).ToArray() }; } /// /// Compare /// /// /// /// private static bool IsSameAs(this EnumDescriptionModel? model, EnumDescriptionModel? that) { if (model == null && that == null) { return true; } if (model == null || that == null) { return false; } return model.BuiltInType == that.BuiltInType && model.DataTypeId == that.DataTypeId && model.Name == that.Name && model.IsOptionSet == that.IsOptionSet && model.Fields.SequenceEqualsSafe(that.Fields, IsSameAs) ; } /// /// Convert to type description /// /// /// /// private static EnumDescription ToStackModel(this EnumDescriptionModel model, IServiceMessageContext context) { return new EnumDescription { BuiltInType = model.BuiltInType ?? (byte)BuiltInType.Null, DataTypeId = model.DataTypeId.ToNodeId(context), Name = model.Name.ToQualifiedName(context), EnumDefinition = new EnumDefinition { Fields = model.Fields.Select(f => f.ToStackModel()).ToArray(), IsOptionSet = model.IsOptionSet } }; } /// /// Convert to type description /// /// /// /// private static EnumDescriptionModel ToServiceModel(this EnumDescription model, IServiceMessageContext context) { ArgumentNullException.ThrowIfNull(model.EnumDefinition); return new EnumDescriptionModel { BuiltInType = model.BuiltInType, DataTypeId = (model.DataTypeId .AsString(context, NamespaceFormat.Expanded)) ?? string.Empty, Name = model.Name .AsString(context, NamespaceFormat.Expanded), Fields = model.EnumDefinition.Fields .Select(f => f.ToServiceModel()).ToArray(), IsOptionSet = model.EnumDefinition.IsOptionSet }; } /// /// Compare /// /// /// /// private static bool IsSameAs(this EnumFieldDescriptionModel? model, EnumFieldDescriptionModel? that) { if (model == null && that == null) { return true; } if (model == null || that == null) { return false; } return model.Name == that.Name && model.DisplayName == that.DisplayName && model.Value == that.Value; } /// /// Convert to field /// /// /// private static EnumField ToStackModel(this EnumFieldDescriptionModel model) { return new EnumField { Name = model.Name, DisplayName = model.DisplayName, Value = model.Value }; } /// /// Convert to field /// /// /// private static EnumFieldDescriptionModel ToServiceModel(this EnumField model) { return new EnumFieldDescriptionModel { Name = model.Name, DisplayName = model.DisplayName.AsString(), Value = model.Value }; } /// /// Compare /// /// /// /// private static bool IsSameAs(this StructureDescriptionModel? model, StructureDescriptionModel? that) { if (model == null && that == null) { return true; } if (model == null || that == null) { return false; } return model.Name == that.Name && model.DataTypeId == that.DataTypeId && model.BaseDataType == that.BaseDataType && model.DefaultEncodingId == that.DefaultEncodingId && model.StructureType == that.StructureType && model.Fields.SequenceEqualsSafe(that.Fields, IsSameAs); } /// /// Convert to type description /// /// /// /// private static StructureDescription ToStackModel( this StructureDescriptionModel model, IServiceMessageContext context) { return new StructureDescription { Name = model.Name.ToQualifiedName(context), DataTypeId = model.DataTypeId.ToNodeId(context), StructureDefinition = new StructureDefinition { BaseDataType = model.BaseDataType.ToNodeId(context), DefaultEncodingId = model.DefaultEncodingId.ToNodeId(context), FirstExplicitFieldIndex = 0, StructureType = model.StructureType.ToStackType(), Fields = model.Fields.Select(f => f.ToStackModel(context)).ToArray() } }; } /// /// Convert to type description /// /// /// /// private static StructureDescriptionModel ToServiceModel( this StructureDescription model, IServiceMessageContext context) { ArgumentNullException.ThrowIfNull(model.StructureDefinition); return new StructureDescriptionModel { Name = model.Name .AsString(context, NamespaceFormat.Expanded), DataTypeId = (model.DataTypeId .AsString(context, NamespaceFormat.Expanded)) ?? string.Empty, BaseDataType = model.StructureDefinition.BaseDataType .AsString(context, NamespaceFormat.Expanded), DefaultEncodingId = model.StructureDefinition.DefaultEncodingId .AsString(context, NamespaceFormat.Expanded), // FirstExplicitFieldIndex = 0, StructureType = model.StructureDefinition.StructureType.ToServiceType(), Fields = model.StructureDefinition.Fields .Select(f => f.ToServiceModel(context)).ToArray() }; } /// /// Compare /// /// /// /// private static bool IsSameAs(this StructureFieldDescriptionModel? model, StructureFieldDescriptionModel? that) { if (model == null && that == null) { return true; } if (model == null || that == null) { return false; } return model.Name == that.Name && model.ArrayDimensions.SequenceEqualsSafe(that.ArrayDimensions) && model.IsOptional == that.IsOptional && model.DataType == that.DataType && model.Description == that.Description && model.MaxStringLength == that.MaxStringLength && model.ValueRank == that.ValueRank; } /// /// Convert to field /// /// /// /// private static StructureField ToStackModel( this StructureFieldDescriptionModel model, IServiceMessageContext context) { return new StructureField { Name = model.Name, ArrayDimensions = model.ArrayDimensions? .ToArray(), IsOptional = model.IsOptional, DataType = model.DataType .ToNodeId(context), Description = model.Description, MaxStringLength = model.MaxStringLength, ValueRank = model.ValueRank }; } /// /// Convert to field /// /// /// /// private static StructureFieldDescriptionModel ToServiceModel( this StructureField model, IServiceMessageContext context) { return new StructureFieldDescriptionModel { Name = model.Name, ArrayDimensions = model.ArrayDimensions? .ToArray(), IsOptional = model.IsOptional, DataType = (model.DataType .AsString(context, NamespaceFormat.Expanded)) ?? string.Empty, Description = model.Description.AsString(), MaxStringLength = model.MaxStringLength, ValueRank = model.ValueRank }; } /// /// Compare /// /// /// /// private static bool IsSameAs(this SimpleTypeDescriptionModel? model, SimpleTypeDescriptionModel? that) { if (model == null && that == null) { return true; } if (model == null || that == null) { return false; } return model.BaseDataType == that.BaseDataType && model.BuiltInType == that.BuiltInType && model.DataTypeId == that.DataTypeId && model.Name == that.Name; } /// /// Convert to type description /// /// /// /// private static SimpleTypeDescription ToStackModel( this SimpleTypeDescriptionModel model, IServiceMessageContext context) { return new SimpleTypeDescription { BaseDataType = model.BaseDataType.ToNodeId(context), BuiltInType = model.BuiltInType ?? (byte)BuiltInType.Null, Name = model.Name.ToQualifiedName(context), DataTypeId = model.DataTypeId.ToNodeId(context) }; } /// /// Convert to type description /// /// /// /// private static SimpleTypeDescriptionModel ToServiceModel( this SimpleTypeDescription model, IServiceMessageContext context) { return new SimpleTypeDescriptionModel { BaseDataType = model.BaseDataType .AsString(context, NamespaceFormat.Expanded), BuiltInType = model.BuiltInType, Name = model.Name .AsString(context, NamespaceFormat.Expanded), DataTypeId = (model.DataTypeId .AsString(context, NamespaceFormat.Expanded)) ?? string.Empty }; } /// /// Compare /// /// /// /// private static bool IsSameAs(this PublishedFieldMetaDataModel? model, PublishedFieldMetaDataModel? that) { if (model == null && that == null) { return true; } if (model == null || that == null) { return false; } return model.Name == that.Name && model.Id == that.Id && model.ArrayDimensions.SequenceEqualsSafe(that.ArrayDimensions) && model.BuiltInType == that.BuiltInType && model.DataType == that.DataType && model.Description == that.Description && model.MaxStringLength == that.MaxStringLength && model.ValueRank == that.ValueRank && model.Flags == that.Flags; } /// /// Convert to field metadata /// /// /// /// private static FieldMetaData ToStackModel( this PublishedFieldMetaDataModel field, IServiceMessageContext context) { return new FieldMetaData { Name = field.Name, DataSetFieldId = (Uuid)field.Id, ArrayDimensions = field.ArrayDimensions? .ToArray(), BuiltInType = field.BuiltInType, DataType = field.DataType .ToNodeId(context), Description = field.Description, MaxStringLength = field.MaxStringLength, ValueRank = field.ValueRank, FieldFlags = field.Flags, Properties = null // TODO }; } /// /// Convert to field metadata /// /// /// /// private static PublishedFieldMetaDataModel ToServiceModel( this FieldMetaData field, IServiceMessageContext context) { return new PublishedFieldMetaDataModel { Name = field.Name, Id = field.DataSetFieldId, ArrayDimensions = field.ArrayDimensions? .ToArray(), BuiltInType = field.BuiltInType, DataType = field.DataType .AsString(context, NamespaceFormat.Expanded), Description = field.Description.AsString(), MaxStringLength = field.MaxStringLength, ValueRank = field.ValueRank, Flags = field.FieldFlags, Properties = null // TODO }; } /// /// Compare /// /// /// /// private static bool IsSameAs(this DataSetMetaDataModel? model, DataSetMetaDataModel? that) { if (model == null && that == null) { return true; } if (model == null || that == null) { return false; } return model.Name == that.Name && model.Description == that.Description && model.DataSetClassId == that.DataSetClassId && model.MajorVersion == that.MajorVersion; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/PubSub/UadpDataSetMessage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.PubSub { using Azure.IIoT.OpcUa.Publisher.Models; using Opc.Ua; using System; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Xml; /// /// Data set message /// public class UadpDataSetMessage : BaseDataSetMessage { /// /// Get and set the configured size of the message /// public ushort ConfiguredSize { get; set; } /// /// Get and set the DataSetOffset of the message /// public ushort DataSetOffset { get; set; } /// /// Get or set decoded payload size (hold it here for now) /// internal ushort PayloadSizeInStream { get; set; } /// /// Get and Set the startPosition in decoder /// internal int StartPositionInStream { get; set; } /// /// Get or set timestamp pico seconds /// public ushort PicoSeconds { get; set; } /// /// The possible values for the DataSetFlags1 encoding byte. /// [Flags] internal enum DataSetFlags1EncodingMask : byte { None = 0, MessageIsValid = 1, FieldTypeRawData = 2, FieldTypeDataValue = 4, FieldTypeUsedBits = FieldTypeRawData | FieldTypeDataValue, DataSetMessageSequenceNumber = 8, Status = 16, ConfigurationVersionMajorVersion = 32, ConfigurationVersionMinorVersion = 64, DataSetFlags2 = 128, DataSetFlags1UsedBits = MessageIsValid | DataSetMessageSequenceNumber | Status | ConfigurationVersionMajorVersion | ConfigurationVersionMinorVersion | DataSetFlags2 } /// /// The possible values for the DataSetFlags2 encoding byte. /// [Flags] internal enum DataSetFlags2EncodingMask : byte { DataKeyFrame = 0, DataDeltaFrame = 1, Event = 2, KeepAlive = DataDeltaFrame | Event, Reserved1 = 4, MessageTypeBits = KeepAlive | Reserved1, Timestamp = 16, PicoSeconds = 32, Reserved2 = 64, ReservedForExtendedFlags = 128 } /// /// Get DataSetFlags1 /// internal DataSetFlags1EncodingMask DataSetFlags1 { get { if (_dataSetFlags1 == null) { _dataSetFlags1 = DataSetFlags1EncodingMask.MessageIsValid; // DataSetFlags1: Bit range 1-2: Field Encoding _dataSetFlags1 &= ~DataSetFlags1EncodingMask.FieldTypeUsedBits; if ((Payload.DataSetFieldContentMask & DataSetFieldContentFlags.RawData) != 0) { _dataSetFlags1 |= DataSetFlags1EncodingMask.FieldTypeRawData; } else if (Payload.DataSetFieldContentMask != 0) { _dataSetFlags1 |= DataSetFlags1EncodingMask.FieldTypeDataValue; } if ((DataSetMessageContentMask & DataSetMessageContentFlags.SequenceNumber) != 0) { // DataSetFlags1: Bit range 3: sequence _dataSetFlags1 |= DataSetFlags1EncodingMask.DataSetMessageSequenceNumber; } if ((DataSetMessageContentMask & DataSetMessageContentFlags.Status) != 0) { // DataSetFlags1: Bit range 4: status _dataSetFlags1 |= DataSetFlags1EncodingMask.Status; } if ((DataSetMessageContentMask & DataSetMessageContentFlags.MajorVersion) != 0) { // DataSetFlags1: Bit range 5: major version _dataSetFlags1 |= DataSetFlags1EncodingMask.ConfigurationVersionMajorVersion; } if ((DataSetMessageContentMask & DataSetMessageContentFlags.MinorVersion) != 0) { // DataSetFlags1: Bit range 6: minor version _dataSetFlags1 |= DataSetFlags1EncodingMask.ConfigurationVersionMinorVersion; } // DataSetFlags1: Bit 7 if needed if ((DataSetMessageContentMask & (DataSetMessageContentFlags.Timestamp | DataSetMessageContentFlags.PicoSeconds)) != 0) { _dataSetFlags1 |= DataSetFlags1EncodingMask.DataSetFlags2; } if (MessageType != MessageType.KeyFrame) { _dataSetFlags1 |= DataSetFlags1EncodingMask.DataSetFlags2; } } return _dataSetFlags1.Value; } private set { _dataSetFlags1 = value; if ((value & DataSetFlags1EncodingMask.MessageIsValid) != 0) { // DataSetFlags1: Bit range 1-2: Field Encoding if ((value & DataSetFlags1EncodingMask.FieldTypeRawData) != 0) { Payload.DataSetFieldContentMask = DataSetFieldContentFlags.RawData; } else if ((value & DataSetFlags1EncodingMask.FieldTypeDataValue) != 0) { Payload.DataSetFieldContentMask = DataSetFieldContentFlags.StatusCode | DataSetFieldContentFlags.SourceTimestamp | DataSetFieldContentFlags.ServerTimestamp | DataSetFieldContentFlags.SourcePicoSeconds | DataSetFieldContentFlags.ServerPicoSeconds; } else { Payload.DataSetFieldContentMask = 0; } // DataSetFlags1: Bit range 3: sequence if ((value & DataSetFlags1EncodingMask.DataSetMessageSequenceNumber) != 0) { DataSetMessageContentMask |= DataSetMessageContentFlags.SequenceNumber; } if ((value & DataSetFlags1EncodingMask.Status) != 0) { // DataSetFlags1: Bit range 4: status DataSetMessageContentMask |= DataSetMessageContentFlags.Status; } if ((value & DataSetFlags1EncodingMask.ConfigurationVersionMajorVersion) != 0) { // DataSetFlags1: Bit range 5: major version DataSetMessageContentMask |= DataSetMessageContentFlags.MajorVersion; } if ((value & DataSetFlags1EncodingMask.ConfigurationVersionMinorVersion) != 0) { // DataSetFlags1: Bit range 6: minor version DataSetMessageContentMask |= DataSetMessageContentFlags.MinorVersion; } } } } /// /// Get DataSetFlags2 /// /// internal DataSetFlags2EncodingMask DataSetFlags2 { get { if (_dataSetFlags2 == null) { _dataSetFlags2 = 0; // Bit range 0-3: DataSetMessage type switch (MessageType) { case MessageType.DeltaFrame: _dataSetFlags2 |= DataSetFlags2EncodingMask.DataDeltaFrame; break; case MessageType.Event: _dataSetFlags2 |= DataSetFlags2EncodingMask.Event; break; case MessageType.KeepAlive: _dataSetFlags2 |= DataSetFlags2EncodingMask.KeepAlive; break; case MessageType.Condition: _dataSetFlags2 |= DataSetFlags2EncodingMask.Event | DataSetFlags2EncodingMask.Reserved1; break; case MessageType.KeyFrame: // Default is key frame break; default: throw new EncodingException( $"Message type {MessageType} not valid for data set messages."); } // Bit range 4-5: timestamp if ((DataSetMessageContentMask & DataSetMessageContentFlags.Timestamp) != 0) { _dataSetFlags2 |= DataSetFlags2EncodingMask.Timestamp; } if ((DataSetMessageContentMask & DataSetMessageContentFlags.PicoSeconds) != 0) { _dataSetFlags2 |= DataSetFlags2EncodingMask.PicoSeconds; } } return _dataSetFlags2.Value; } private set { _dataSetFlags2 = value; // Bit range 0-3: DataSetMessage type switch (value & DataSetFlags2EncodingMask.MessageTypeBits) { case DataSetFlags2EncodingMask.DataDeltaFrame: MessageType = MessageType.DeltaFrame; break; case DataSetFlags2EncodingMask.Event: MessageType = MessageType.Event; break; case DataSetFlags2EncodingMask.KeepAlive: MessageType = MessageType.KeepAlive; break; default: // Default is key frame MessageType = MessageType.KeyFrame; break; } // Bit range 4-5: timestamp if ((value & DataSetFlags2EncodingMask.Timestamp) != 0) { DataSetMessageContentMask |= DataSetMessageContentFlags.Timestamp; } if ((value & DataSetFlags2EncodingMask.PicoSeconds) != 0) { DataSetMessageContentMask |= DataSetMessageContentFlags.PicoSeconds; } } } /// internal void Encode(BinaryEncoder binaryEncoder, IDataSetMetaDataResolver? resolver) { StartPositionInStream = binaryEncoder.Position; if (DataSetOffset > 0 && StartPositionInStream < DataSetOffset) { StartPositionInStream = DataSetOffset; binaryEncoder.Position = DataSetOffset; } WriteDataSetMessageHeader(binaryEncoder); var metadata = resolver?.Find(DataSetWriterId, MetaDataVersion?.MajorVersion ?? 1, MetaDataVersion?.MinorVersion ?? 0); if ((DataSetFlags2 & DataSetFlags2EncodingMask.DataDeltaFrame) != 0) { WritePayloadDeltaFrame(binaryEncoder, metadata); } else { // // Every other type is encoded as key frame. Technically we should also encode // as keyframe if delta frame would be larger, but we skip this for now. // WritePayloadKeyFrame(binaryEncoder, metadata); } PayloadSizeInStream = (ushort)(binaryEncoder.Position - StartPositionInStream); if (ConfiguredSize > 0 && PayloadSizeInStream < ConfiguredSize) { PayloadSizeInStream = ConfiguredSize; binaryEncoder.Position = StartPositionInStream + PayloadSizeInStream; } } /// /// Decode data set message /// /// /// /// internal bool TryDecode(BinaryDecoder decoder, IDataSetMetaDataResolver? resolver) { if (decoder is not BinaryDecoder binaryDecoder) { throw new DecodingException("Must use Binary decoder here"); } try { if (!TryReadDataSetMessageHeader(binaryDecoder)) { return false; } var metadata = resolver?.Find(DataSetWriterId, MetaDataVersion?.MajorVersion ?? 1, MetaDataVersion?.MinorVersion ?? 0); if ((DataSetFlags2 & DataSetFlags2EncodingMask.DataDeltaFrame) != 0) { ReadPayloadDeltaFrame(binaryDecoder, metadata); } else { ReadPayloadKeyFrame(binaryDecoder, metadata); } return true; } catch (EndOfStreamException) { return false; } } /// /// Read DataSet message header /// /// private bool TryReadDataSetMessageHeader(BinaryDecoder decoder) { DataSetFlags1 = (DataSetFlags1EncodingMask)decoder.ReadByte(null); if ((DataSetFlags1 & DataSetFlags1EncodingMask.MessageIsValid) == 0) { // Invalid message return false; } if ((DataSetFlags1 & DataSetFlags1EncodingMask.DataSetFlags2) != 0) { DataSetFlags2 = (DataSetFlags2EncodingMask)decoder.ReadByte(null); } if ((DataSetFlags1 & DataSetFlags1EncodingMask.DataSetMessageSequenceNumber) != 0) { SequenceNumber = decoder.ReadUInt16(null); } if ((DataSetFlags2 & DataSetFlags2EncodingMask.Timestamp) != 0) { Timestamp = decoder.ReadDateTime(null); } if ((DataSetFlags2 & DataSetFlags2EncodingMask.PicoSeconds) != 0) { PicoSeconds = decoder.ReadUInt16(null); } if ((DataSetFlags1 & DataSetFlags1EncodingMask.Status) != 0) { // This is the high order 16 bits of the StatusCode DataType representing // the numeric value of the Severity and SubCode of the StatusCode DataType. var code = decoder.ReadUInt16(null); Status = (uint)code << 16; } uint minorVersion = 1; uint majorVersion = 0; if ((DataSetFlags1 & DataSetFlags1EncodingMask.ConfigurationVersionMajorVersion) != 0) { majorVersion = decoder.ReadUInt32(null); } if ((DataSetFlags1 & DataSetFlags1EncodingMask.ConfigurationVersionMinorVersion) != 0) { minorVersion = decoder.ReadUInt32(null); } MetaDataVersion = new ConfigurationVersionDataType() { MinorVersion = minorVersion, MajorVersion = majorVersion }; return true; } /// /// Write DataSet message header /// /// private void WriteDataSetMessageHeader(BinaryEncoder encoder) { if ((DataSetFlags1 & DataSetFlags1EncodingMask.MessageIsValid) != 0) { encoder.WriteByte(null, (byte)DataSetFlags1); } if ((DataSetFlags1 & DataSetFlags1EncodingMask.DataSetFlags2) != 0) { encoder.WriteByte(null, (byte)DataSetFlags2); } if ((DataSetFlags1 & DataSetFlags1EncodingMask.DataSetMessageSequenceNumber) != 0) { encoder.WriteUInt16(null, (ushort)SequenceNumber); } if ((DataSetFlags2 & DataSetFlags2EncodingMask.Timestamp) != 0) { encoder.WriteDateTime(null, Timestamp?.UtcDateTime ?? default); } if ((DataSetFlags2 & DataSetFlags2EncodingMask.PicoSeconds) != 0) { encoder.WriteUInt16(null, PicoSeconds); } if ((DataSetFlags1 & DataSetFlags1EncodingMask.Status) != 0) { // This is the high order 16 bits of the StatusCode DataType representing // the numeric value of the Severity and SubCode of the StatusCode DataType. var status = Status ?? Payload.DataSetFields .FirstOrDefault(s => StatusCode.IsNotGood(s.Value?.StatusCode ?? StatusCodes.BadNoData)).Value? .StatusCode ?? StatusCodes.Good; encoder.WriteUInt16(null, (ushort)(status.Code >> 16)); } if ((DataSetFlags1 & DataSetFlags1EncodingMask.ConfigurationVersionMajorVersion) != 0) { encoder.WriteUInt32(null, MetaDataVersion?.MajorVersion ?? 1); } if ((DataSetFlags1 & DataSetFlags1EncodingMask.ConfigurationVersionMinorVersion) != 0) { encoder.WriteUInt32(null, MetaDataVersion?.MinorVersion ?? 0); } } /// /// Read message data key frame from decoder /// /// /// /// /// private void ReadPayloadKeyFrame(BinaryDecoder binaryDecoder, PublishedDataSetMetaDataModel? metadata) { var fieldType = DataSetFlags1 & DataSetFlags1EncodingMask.FieldTypeUsedBits; ushort dataSetFieldCount; if (fieldType == DataSetFlags1EncodingMask.FieldTypeRawData) { if (metadata != null) { // metadata should provide field count dataSetFieldCount = (ushort)metadata.Fields.Count; } else { throw new DecodingException("Requires metadata to decode"); } } else { dataSetFieldCount = binaryDecoder.ReadUInt16(null); } // check configuration version var fields = Payload.DataSetFields.ToList(); switch (fieldType) { case 0: for (var i = 0; i < dataSetFieldCount; i++) { var fieldMetaData = GetFieldMetadata(metadata, i); fields.Add((fieldMetaData?.Name ?? i.ToString(CultureInfo.InvariantCulture), new DataValue(binaryDecoder.ReadVariant(null)))); } break; case DataSetFlags1EncodingMask.FieldTypeDataValue: for (var i = 0; i < dataSetFieldCount; i++) { var fieldMetaData = GetFieldMetadata(metadata, i); fields.Add((fieldMetaData?.Name ?? i.ToString(CultureInfo.InvariantCulture), binaryDecoder.ReadDataValue(null))); } break; case DataSetFlags1EncodingMask.FieldTypeRawData: for (var i = 0; i < dataSetFieldCount; i++) { var fieldMetaData = GetFieldMetadata(metadata, i); if (fieldMetaData != null) { var decodedValue = ReadRawData(binaryDecoder, fieldMetaData); fields.Add((fieldMetaData.Name, new DataValue(new Variant(decodedValue)))); } } break; default: throw new DecodingException($"Reserved field type {fieldType} not allowed."); } Payload = new Models.DataSet(fields, Payload.DataSetFieldContentMask); } /// /// Write payload data /// /// /// /// private void WritePayloadKeyFrame(BinaryEncoder binaryEncoder, PublishedDataSetMetaDataModel? metadata) { var fieldType = DataSetFlags1 & DataSetFlags1EncodingMask.FieldTypeUsedBits; switch (fieldType) { case 0: Debug.Assert(Payload.DataSetFields.Count <= ushort.MaxValue); binaryEncoder.WriteUInt16(null, (ushort)Payload.DataSetFields.Count); foreach (var (_, Value) in Payload.DataSetFields) { binaryEncoder.WriteVariant(null, Value?.WrappedValue ?? default); } break; case DataSetFlags1EncodingMask.FieldTypeDataValue: Debug.Assert(Payload.DataSetFields.Count <= ushort.MaxValue); binaryEncoder.WriteUInt16(null, (ushort)Payload.DataSetFields.Count); foreach (var (_, Value) in Payload.DataSetFields) { binaryEncoder.WriteDataValue(null, Value); } break; case DataSetFlags1EncodingMask.FieldTypeRawData: // DataSetFieldCount is not written for RawData var values = Payload.DataSetFields.ToList(); for (var i = 0; i < values.Count; i++) { var fieldMetaData = GetFieldMetadata(metadata, i); WriteFieldAsRawData(binaryEncoder, values[i].Value?.WrappedValue ?? default, fieldMetaData); } break; default: throw new EncodingException( $"Reserved field type {fieldType} not allowed."); } } /// /// Read message data delta frame from decoder /// /// /// /// /// private void ReadPayloadDeltaFrame(BinaryDecoder binaryDecoder, PublishedDataSetMetaDataModel? metadata) { var fieldType = DataSetFlags1 & DataSetFlags1EncodingMask.FieldTypeUsedBits; var fieldCount = binaryDecoder.ReadUInt16(null); var fields = Payload.DataSetFields.ToList(); for (var i = 0; i < fieldCount; i++) { var fieldIndex = binaryDecoder.ReadUInt16(null); var fieldMetaData = GetFieldMetadata(metadata, fieldIndex); switch (fieldType) { case 0: fields.Add((fieldMetaData?.Name ?? fieldIndex.ToString(CultureInfo.InvariantCulture), new DataValue(binaryDecoder.ReadVariant(null)))); break; case DataSetFlags1EncodingMask.FieldTypeDataValue: fields.Add((fieldMetaData?.Name ?? fieldIndex.ToString(CultureInfo.InvariantCulture), binaryDecoder.ReadDataValue(null))); break; case DataSetFlags1EncodingMask.FieldTypeRawData: if (fieldMetaData != null) { var decodedValue = ReadRawData(binaryDecoder, fieldMetaData); fields.Add((fieldMetaData.Name, new DataValue(new Variant(decodedValue)))); } break; default: throw new DecodingException($"Reserved field type {fieldType} not allowed."); } } Payload = new Models.DataSet(fields, Payload.DataSetFieldContentMask); } /// /// Write payload data delta frame /// /// /// /// private void WritePayloadDeltaFrame(BinaryEncoder binaryEncoder, PublishedDataSetMetaDataModel? metadata) { // ignore null fields var fieldCount = Payload.DataSetFields.Count(value => value.Value?.Value != null); Debug.Assert(fieldCount <= ushort.MaxValue); binaryEncoder.WriteUInt16(null, (ushort)fieldCount); var fieldType = DataSetFlags1 & DataSetFlags1EncodingMask.FieldTypeUsedBits; var values = Payload.DataSetFields.ToList(); for (var i = 0; i < values.Count; i++) { var (Name, Value) = values[i]; if (Value?.Value == null) { continue; } // write field index corresponding to metadata var fieldIndex = GetFieldIndex(metadata, Name, i); binaryEncoder.WriteUInt16(null, fieldIndex); switch (fieldType) { case 0: binaryEncoder.WriteVariant(null, Value.WrappedValue); break; case DataSetFlags1EncodingMask.FieldTypeDataValue: binaryEncoder.WriteDataValue(null, Value); break; case DataSetFlags1EncodingMask.FieldTypeRawData: var fieldMetadata = GetFieldMetadata(metadata, fieldIndex); WriteFieldAsRawData(binaryEncoder, Value.WrappedValue, fieldMetadata); break; default: throw new EncodingException($"Reserved field type {fieldType} not allowed."); } } } /// /// Get field index in metadata if metadata was provided. /// /// /// /// /// private static ushort GetFieldIndex(PublishedDataSetMetaDataModel? metadata, string key, int pos) { if (metadata?.Fields != null) { for (var i = 0; i < metadata.Fields.Count; i++) { if (metadata.Fields[i].Name == key) { return (ushort)i; } } // Assign a unique new one after the fields in metadata var idx = metadata.Fields.Count + pos; Debug.Assert(idx <= ushort.MaxValue); return (ushort)idx; } return (ushort)pos; } /// /// Get field metadata for the index /// /// /// /// private static PublishedFieldMetaDataModel? GetFieldMetadata(PublishedDataSetMetaDataModel? metadata, int fieldIndex) { if (metadata?.Fields == null) { return null; } if (fieldIndex < 0 || fieldIndex >= metadata.Fields.Count) { return null; } return metadata.Fields[fieldIndex]; } /// /// Encodes field value as RawData /// /// /// /// private static void WriteFieldAsRawData(BinaryEncoder binaryEncoder, Variant variant, PublishedFieldMetaDataModel? fieldMetaData) { var builtInType = (BuiltInType?)fieldMetaData?.BuiltInType ?? variant.TypeInfo?.BuiltInType ?? BuiltInType.Null; var valueRank = fieldMetaData?.ValueRank ?? variant.TypeInfo?.ValueRank ?? 0; if (builtInType == BuiltInType.Null) { return; } var valueToEncode = variant.Value; if (valueRank == ValueRanks.Scalar) { switch (builtInType) { case BuiltInType.Boolean: binaryEncoder.WriteBoolean(null, Convert.ToBoolean(valueToEncode, CultureInfo.InvariantCulture)); break; case BuiltInType.SByte: binaryEncoder.WriteSByte(null, Convert.ToSByte(valueToEncode, CultureInfo.InvariantCulture)); break; case BuiltInType.Byte: binaryEncoder.WriteByte(null, Convert.ToByte(valueToEncode, CultureInfo.InvariantCulture)); break; case BuiltInType.Int16: binaryEncoder.WriteInt16(null, Convert.ToInt16(valueToEncode, CultureInfo.InvariantCulture)); break; case BuiltInType.UInt16: binaryEncoder.WriteUInt16(null, Convert.ToUInt16(valueToEncode, CultureInfo.InvariantCulture)); break; case BuiltInType.Int32: binaryEncoder.WriteInt32(null, Convert.ToInt32(valueToEncode, CultureInfo.InvariantCulture)); break; case BuiltInType.UInt32: binaryEncoder.WriteUInt32(null, Convert.ToUInt32(valueToEncode, CultureInfo.InvariantCulture)); break; case BuiltInType.Int64: binaryEncoder.WriteInt64(null, Convert.ToInt64(valueToEncode, CultureInfo.InvariantCulture)); break; case BuiltInType.UInt64: binaryEncoder.WriteUInt64(null, Convert.ToUInt64(valueToEncode, CultureInfo.InvariantCulture)); break; case BuiltInType.Float: binaryEncoder.WriteFloat(null, Convert.ToSingle(valueToEncode, CultureInfo.InvariantCulture)); break; case BuiltInType.Double: binaryEncoder.WriteDouble(null, Convert.ToDouble(valueToEncode, CultureInfo.InvariantCulture)); break; case BuiltInType.DateTime: binaryEncoder.WriteDateTime(null, Convert.ToDateTime(valueToEncode, CultureInfo.InvariantCulture)); break; case BuiltInType.Enumeration: binaryEncoder.WriteInt32(null, Convert.ToInt32(valueToEncode, CultureInfo.InvariantCulture)); break; case BuiltInType.Guid: binaryEncoder.WriteGuid(null, (Uuid)valueToEncode); break; case BuiltInType.String: binaryEncoder.WriteString(null, valueToEncode as string); break; case BuiltInType.ByteString: binaryEncoder.WriteByteString(null, (byte[])valueToEncode); break; case BuiltInType.QualifiedName: binaryEncoder.WriteQualifiedName(null, valueToEncode as QualifiedName); break; case BuiltInType.LocalizedText: binaryEncoder.WriteLocalizedText(null, valueToEncode as LocalizedText); break; case BuiltInType.NodeId: binaryEncoder.WriteNodeId(null, valueToEncode as NodeId); break; case BuiltInType.ExpandedNodeId: binaryEncoder.WriteExpandedNodeId(null, valueToEncode as ExpandedNodeId); break; case BuiltInType.StatusCode: binaryEncoder.WriteStatusCode(null, (StatusCode)valueToEncode); break; case BuiltInType.XmlElement: binaryEncoder.WriteXmlElement(null, valueToEncode as XmlElement); break; case BuiltInType.ExtensionObject: binaryEncoder.WriteExtensionObject(null, valueToEncode as ExtensionObject); break; } } else if (valueRank >= ValueRanks.OneDimension) { binaryEncoder.WriteArray(null, valueToEncode, valueRank, builtInType); } } /// /// Decode RawData type (for SimpleTypeDescription!?) /// /// /// /// private static object? ReadRawData(BinaryDecoder binaryDecoder, PublishedFieldMetaDataModel fieldMetaData) { if (fieldMetaData.BuiltInType != (byte)BuiltInType.Null) { try { switch (fieldMetaData.ValueRank) { case ValueRanks.Scalar: return ReadRawScalar(binaryDecoder, fieldMetaData.BuiltInType); case ValueRanks.OneDimension: case ValueRanks.TwoDimensions: return binaryDecoder.ReadArray(null, fieldMetaData.ValueRank, (BuiltInType)fieldMetaData.BuiltInType); case ValueRanks.OneOrMoreDimensions: case ValueRanks.Any:// Scalar or Array with any number of dimensions case ValueRanks.ScalarOrOneDimension: // not implemented return StatusCodes.BadNotSupported; default: // not implemented return StatusCodes.BadNotSupported; } } catch (ServiceResultException sre) { return sre.StatusCode; } catch { return StatusCodes.BadDecodingError; } } return null; } /// /// Read a scalar type /// /// /// /// The decoded object private static object? ReadRawScalar(BinaryDecoder binaryDecoder, byte builtInType) { switch ((BuiltInType)builtInType) { case BuiltInType.Boolean: return binaryDecoder.ReadBoolean(null); case BuiltInType.SByte: return binaryDecoder.ReadSByte(null); case BuiltInType.Byte: return binaryDecoder.ReadByte(null); case BuiltInType.Int16: return binaryDecoder.ReadInt16(null); case BuiltInType.UInt16: return binaryDecoder.ReadUInt16(null); case BuiltInType.Int32: return binaryDecoder.ReadInt32(null); case BuiltInType.UInt32: return binaryDecoder.ReadUInt32(null); case BuiltInType.Int64: return binaryDecoder.ReadInt64(null); case BuiltInType.UInt64: return binaryDecoder.ReadUInt64(null); case BuiltInType.Float: return binaryDecoder.ReadFloat(null); case BuiltInType.Double: return binaryDecoder.ReadDouble(null); case BuiltInType.String: return binaryDecoder.ReadString(null); case BuiltInType.DateTime: return binaryDecoder.ReadDateTime(null); case BuiltInType.Guid: return binaryDecoder.ReadGuid(null); case BuiltInType.ByteString: return binaryDecoder.ReadByteString(null); case BuiltInType.XmlElement: return binaryDecoder.ReadXmlElement(null); case BuiltInType.NodeId: return binaryDecoder.ReadNodeId(null); case BuiltInType.ExpandedNodeId: return binaryDecoder.ReadExpandedNodeId(null); case BuiltInType.StatusCode: return binaryDecoder.ReadStatusCode(null); case BuiltInType.QualifiedName: return binaryDecoder.ReadQualifiedName(null); case BuiltInType.LocalizedText: return binaryDecoder.ReadLocalizedText(null); case BuiltInType.DataValue: return binaryDecoder.ReadDataValue(null); case BuiltInType.Enumeration: return binaryDecoder.ReadInt32(null); case BuiltInType.Variant: return binaryDecoder.ReadVariant(null); case BuiltInType.ExtensionObject: return binaryDecoder.ReadExtensionObject(null); default: return null; } } private DataSetFlags1EncodingMask? _dataSetFlags1; private DataSetFlags2EncodingMask? _dataSetFlags2; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/PubSub/UadpDiscoveryMessage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.PubSub { using System; using System.Buffers; using System.Collections.Generic; using System.Diagnostics; /// /// Discovery announcements and probes base class /// /// public class UadpDiscoveryMessage : UadpNetworkMessage { /// /// Whether this is a discovery probe /// internal bool IsProbe { get; set; } /// /// Data set writer name in case of ua-metadata message /// public ushort DataSetWriterId { get; set; } /// /// If discovery request /// internal ushort[]? DataSetWriterIds { get; set; } /// /// Discovery type /// internal byte DiscoveryType { get; set; } /// /// The possible types of UADP network discovery announcement types /// [Flags] internal enum UADPDiscoveryAnnouncementType { Reserved = 0, PublisherEndpoints = 1, DataSetMetaData = 2, DataSetWriterConfiguration = PublisherEndpoints | DataSetMetaData, PubSubConnectionsConfiguration = 4, ApplicationInformation = PublisherEndpoints | PubSubConnectionsConfiguration } /// /// The possible types of UADP discovery probe types /// [Flags] internal enum UADPDiscoveryProbeType { Reserved = 0, PublisherInformationProbe = 1, FindApplicationsProbe = 2 } /// /// The possible types of UADP publisher info probe message /// [Flags] internal enum PublisherInformationProbeMessageType { Reserved = 0, PublisherServerEndpoints = 1, DataSetMetaData = 2, DataSetWriterConfiguration = PublisherServerEndpoints | DataSetMetaData, WriterGroupConfiguration = 4, PubSubConnectionsConfiguration = PublisherServerEndpoints | WriterGroupConfiguration } /// public override IReadOnlyList> Encode(Opc.Ua.IServiceMessageContext context, int maxChunkSize, IDataSetMetaDataResolver? resolver) { var messages = new List>(); var isChunkMessage = false; var remainingChunks = EncodePayloadChunks(context, resolver).AsSpan(); // Re-evaluate flags every go around UadpFlags = UADPFlagsEncodingMask.PublisherId | UADPFlagsEncodingMask.ExtendedFlags1; ExtendedFlags1 = ExtendedFlags1EncodingMask.Security | ExtendedFlags1EncodingMask.PublisherIdTypeString | ExtendedFlags1EncodingMask.ExtendedFlags2; ExtendedFlags2 = IsProbe ? ExtendedFlags2EncodingMask.DiscoveryProbe : ExtendedFlags2EncodingMask.DiscoveryAnnouncement; while (remainingChunks.Length == 1) { using var stream = Memory.GetStream(); using var encoder = new Opc.Ua.BinaryEncoder(stream, context, leaveOpen: true); var writeSpan = remainingChunks; while (true) { WriteNetworkMessageHeaderFlags(encoder, isChunkMessage); WriteNetworkMessageHeader(encoder); if (!TryWritePayload(encoder, maxChunkSize, ref writeSpan, ref remainingChunks, ref isChunkMessage)) { encoder.Position = 0; // Restart writing continue; } WriteSecurityFooter(encoder); WriteSignature(encoder); break; } stream.SetLength(encoder.Position); var messageBuffer = stream.GetReadOnlySequence(); // TODO: instead of copy using ToArray we shall include the // stream with the message and dispose it later when it is // consumed. To get here the bug in BinaryEncoder that it // disposes the underlying stream even if leaveOpen: true // is set must be fixed. messages.Add(new ReadOnlySequence(messageBuffer.ToArray())); } Debug.Assert(remainingChunks.Length == 0); return messages; } /// protected override bool TryReadNetworkMessageHeader(Opc.Ua.BinaryDecoder binaryDecoder, bool isFirstChunk) { if ((ExtendedFlags2 & ExtendedFlags2EncodingMask.DiscoveryProbe) != 0) { // Read probetype DiscoveryType = binaryDecoder.ReadByte(null); DataSetWriterIds = [.. binaryDecoder.ReadUInt16Array(null)]; IsProbe = true; return true; } if ((ExtendedFlags2 & ExtendedFlags2EncodingMask.DiscoveryAnnouncement) != 0) { // Read announcement type DiscoveryType = binaryDecoder.ReadByte(null); _sequenceNumber = binaryDecoder.ReadUInt16(null); IsProbe = false; return true; } // Not a discovery message return false; } /// /// Write discovery header /// /// private void WriteNetworkMessageHeader(Opc.Ua.BinaryEncoder encoder) { if (IsProbe) { // Write probe type encoder.WriteByte(null, DiscoveryType); encoder.WriteUInt16Array(null, DataSetWriterIds ?? []); ExtendedFlags2 &= ~ExtendedFlags2EncodingMask.DiscoveryAnnouncement; ExtendedFlags2 |= ExtendedFlags2EncodingMask.DiscoveryProbe; } else { // Write announcement type encoder.WriteByte(null, DiscoveryType); encoder.WriteUInt16(null, SequenceNumber()); ExtendedFlags2 &= ~ExtendedFlags2EncodingMask.DiscoveryProbe; ExtendedFlags2 |= ExtendedFlags2EncodingMask.DiscoveryAnnouncement; } } /// protected override Message[] EncodePayloadChunks(Opc.Ua.IServiceMessageContext context, IDataSetMetaDataResolver? resolver) { if (MetaData == null) { throw new InvalidOperationException("Metadata is null or empty"); } using var stream = Memory.GetStream(); using var encoder = new Opc.Ua.BinaryEncoder(stream, context, leaveOpen: true); if (!IsProbe) { switch ((UADPDiscoveryAnnouncementType)DiscoveryType) { case UADPDiscoveryAnnouncementType.DataSetMetaData: encoder.WriteUInt16(null, DataSetWriterId); encoder.WriteEncodeable(null, MetaData.ToStackModel(context), typeof(Opc.Ua.DataSetMetaDataType)); // temporary write StatusCode.Good encoder.WriteStatusCode(null, Opc.Ua.StatusCodes.Good); break; case UADPDiscoveryAnnouncementType.DataSetWriterConfiguration: case UADPDiscoveryAnnouncementType.PublisherEndpoints: case UADPDiscoveryAnnouncementType.PubSubConnectionsConfiguration: case UADPDiscoveryAnnouncementType.ApplicationInformation: // not implemented break; } } else { switch ((UADPDiscoveryProbeType)DiscoveryType) { case UADPDiscoveryProbeType.PublisherInformationProbe: case UADPDiscoveryProbeType.FindApplicationsProbe: // not implemented break; } } // TODO: instead of copy using ToArray we shall include the // stream with the message and dispose it later when it is // consumed. To get here the bug in BinaryEncoder that it // disposes the underlying stream even if leaveOpen: true // is set must be fixed. return [new Message(stream.ToArray(), DataSetWriterId)]; } /// protected override void DecodePayloadChunks(Opc.Ua.IServiceMessageContext context, IReadOnlyList buffers, IDataSetMetaDataResolver? resolver) { if (buffers.Count == 0) { return; } Debug.Assert(buffers.Count == 1); using var stream = Memory.GetStream(buffers[0]); using var decoder = new Opc.Ua.BinaryDecoder(stream, context); if ((ExtendedFlags2 & ExtendedFlags2EncodingMask.DiscoveryAnnouncement) != 0) { switch ((UADPDiscoveryAnnouncementType)DiscoveryType) { case UADPDiscoveryAnnouncementType.DataSetMetaData: DataSetWriterId = decoder.ReadUInt16(null); var metaData = (Opc.Ua.DataSetMetaDataType)decoder.ReadEncodeable(null, typeof(Opc.Ua.DataSetMetaDataType)); MetaData = metaData.ToServiceModel(context); // temporary read var status = decoder.ReadStatusCode(null); break; case UADPDiscoveryAnnouncementType.DataSetWriterConfiguration: case UADPDiscoveryAnnouncementType.PublisherEndpoints: case UADPDiscoveryAnnouncementType.PubSubConnectionsConfiguration: case UADPDiscoveryAnnouncementType.ApplicationInformation: // not implemented break; } } else if ((ExtendedFlags2 & ExtendedFlags2EncodingMask.DiscoveryProbe) != 0) { switch ((UADPDiscoveryProbeType)DiscoveryType) { case UADPDiscoveryProbeType.PublisherInformationProbe: case UADPDiscoveryProbeType.FindApplicationsProbe: // not implemented break; } } } /// public override bool Equals(object? obj) { if (ReferenceEquals(this, obj)) { return true; } if (obj is not UadpDiscoveryMessage wrapper) { return false; } if (!base.Equals(obj)) { return false; } if (!Opc.Ua.Utils.IsEqual(wrapper.DataSetWriterId, DataSetWriterId) || !Opc.Ua.Utils.IsEqual(wrapper.MetaData, MetaData)) { return false; } return true; } /// public override int GetHashCode() { var hash = new HashCode(); hash.Add(base.GetHashCode()); hash.Add(DataSetWriterId); hash.Add(MetaData); return hash.ToHashCode(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/PubSub/UadpMetadataMessage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.PubSub { /// /// Data set metadata announcement /// /// public class UadpMetaDataMessage : UadpDiscoveryMessage { /// /// Create metadata message /// public UadpMetaDataMessage() { IsProbe = false; DiscoveryType = (byte)UADPDiscoveryAnnouncementType.DataSetMetaData; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/PubSub/UadpNetworkMessage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.PubSub { using Azure.IIoT.OpcUa.Publisher.Models; using Furly; using Microsoft.IO; using System; using System.Buffers; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; /// /// Encodeable Network message /// /// public class UadpNetworkMessage : BaseNetworkMessage { /// public override string MessageSchema => MessageSchemaTypes.NetworkMessageUadp; /// public override string ContentType => ContentMimeType.Binary; /// public override string? ContentEncoding => null; /// /// Writer group id /// public ushort WriterGroupId { get; set; } /// /// Get and Set VersionTime type: it represents the time in seconds since the year 2000 /// public uint GroupVersion { get; set; } /// /// Get and Set NetworkMessageNumber /// public ushort NetworkMessageNumber { get; set; } /// /// Get and Set SequenceNumber /// public Func SequenceNumber { get; set; } /// /// Get and Set Timestamp /// public DateTimeOffset Timestamp { get; set; } /// /// PicoSeconds /// public ushort PicoSeconds { get; set; } /// /// Get and Set SecurityFlags /// internal SecurityFlagsEncodingMask SecurityFlags { get; set; } /// /// Get and Set SecurityTokenId has IntegerId type /// public uint SecurityTokenId { get; set; } /// /// Get and Set NonceLength /// public byte NonceLength { get; set; } /// /// Get and Set MessageNonce contains [NonceLength] /// public ReadOnlyMemory MessageNonce { get; set; } /// /// Get and Set SecurityFooterSize /// public ushort SecurityFooterSize { get; set; } /// /// Get and Set SecurityFooter /// public ReadOnlyMemory SecurityFooter { get; set; } /// /// Get and Set Signature /// public ReadOnlyMemory Signature { get; set; } /// /// The possible values for the NetworkMessage UADPFlags encoding byte. /// [Flags] internal enum UADPFlagsEncodingMask : byte { None = 0, VersionBit1 = 1, VersionBit2 = 2, VersionBit3 = 4, VersionBit4 = 8, VersionMask = VersionBit1 | VersionBit2 | VersionBit3 | VersionBit4, PublisherId = 16, GroupHeader = 32, PayloadHeader = 64, ExtendedFlags1 = 128, } /// /// The possible values for the NetworkMessage ExtendedFlags1 encoding byte. /// [Flags] internal enum ExtendedFlags1EncodingMask : byte { None = 0, PublisherIdTypeByte = None, PublisherIdTypeUInt16 = 1, PublisherIdTypeUInt32 = 2, PublisherIdTypeUInt64 = PublisherIdTypeUInt16 | PublisherIdTypeUInt32, PublisherIdTypeString = 4, PublisherIdTypeBits = PublisherIdTypeUInt64 | PublisherIdTypeString, DataSetClassId = 8, Security = 16, Timestamp = 32, PicoSeconds = 64, ExtendedFlags2 = 128, } /// /// The possible values for the NetworkMessage ExtendedFlags2 encoding byte. /// [Flags] internal enum ExtendedFlags2EncodingMask : byte { None = 0, ChunkMessage = 1, PromotedFields = 2, DiscoveryProbe = 4, DiscoveryAnnouncement = 8, DiscoveryTypeBit3 = 16, DiscoveryTypeBits = DiscoveryProbe | DiscoveryAnnouncement | DiscoveryTypeBit3, ActionHeaderEnabled = 32 } /// /// The possible values for the NetworkMessage GroupFlags encoding byte. /// [Flags] internal enum GroupFlagsEncodingMask : byte { None = 0, WriterGroupId = 1, GroupVersion = 2, NetworkMessageNumber = 4, SequenceNumber = 8 } /// /// The possible values for the NetworkMessage SecurityFlags encoding byte. /// [Flags] internal enum SecurityFlagsEncodingMask : byte { None = 0, NetworkMessageSigned = 1, NetworkMessageEncrypted = 2, SecurityFooter = 4, ForceKeyReset = 8, Reserved = 16 } /// /// Set All flags before encode/decode for a NetworkMessage that contains DataSet messages /// internal UADPFlagsEncodingMask UadpFlags { get { if (_uadpFlags == null) { // Bit range 0-3: Version of the UADP NetworkMessage, always 1. _uadpFlags = UADPFlagsEncodingMask.VersionBit1; if ((NetworkMessageContentMask & NetworkMessageContentFlags.PublisherId) != 0) { // UADPFlags: Bit 4: PublisherId enabled _uadpFlags |= UADPFlagsEncodingMask.PublisherId; } if ((NetworkMessageContentMask & (NetworkMessageContentFlags.GroupHeader | NetworkMessageContentFlags.WriterGroupId | NetworkMessageContentFlags.GroupVersion | NetworkMessageContentFlags.NetworkMessageNumber | NetworkMessageContentFlags.SequenceNumber)) != 0) { // UADPFlags: Bit 5: GroupHeader enabled _uadpFlags |= UADPFlagsEncodingMask.GroupHeader; } if ((NetworkMessageContentMask & NetworkMessageContentFlags.PayloadHeader) != 0) { // UADPFlags: Bit 6: PayloadHeader enabled _uadpFlags |= UADPFlagsEncodingMask.PayloadHeader; } if ((NetworkMessageContentMask & (NetworkMessageContentFlags.DataSetClassId | NetworkMessageContentFlags.Timestamp | NetworkMessageContentFlags.Picoseconds | NetworkMessageContentFlags.PromotedFields)) != 0) { // UADPFlags: Bit 7: Enable ExtendedFlags1 _uadpFlags |= UADPFlagsEncodingMask.ExtendedFlags1; } if (!string.IsNullOrEmpty(PublisherId) && (NetworkMessageContentMask & NetworkMessageContentFlags.PublisherId) != 0) { // UADPFlags: Bit 7: Enable ExtendedFlags1 _uadpFlags |= UADPFlagsEncodingMask.ExtendedFlags1; } } return _uadpFlags.Value; } set { _uadpFlags = value; // UADPFlags: Bit 4: PublisherId enabled if ((value & UADPFlagsEncodingMask.PublisherId) != 0) { NetworkMessageContentMask |= NetworkMessageContentFlags.PublisherId; } // UADPFlags: Bit 6: PayloadHeader enabled if ((value & UADPFlagsEncodingMask.PayloadHeader) != 0) { NetworkMessageContentMask |= NetworkMessageContentFlags.PayloadHeader; } } } /// /// Get and Set GroupFlags /// internal GroupFlagsEncodingMask GroupFlags { get { if (_groupFlags == null) { _groupFlags = 0; if ((NetworkMessageContentMask & NetworkMessageContentFlags.WriterGroupId) != 0) { // GroupFlags: Bit 0: WriterGroupId enabled _groupFlags |= GroupFlagsEncodingMask.WriterGroupId; } if ((NetworkMessageContentMask & NetworkMessageContentFlags.GroupVersion) != 0) { // GroupFlags: Bit 1: GroupVersion enabled _groupFlags |= GroupFlagsEncodingMask.GroupVersion; } if ((NetworkMessageContentMask & NetworkMessageContentFlags.NetworkMessageNumber) != 0) { // GroupFlags: Bit 2: NetworkMessageNumber enabled _groupFlags |= GroupFlagsEncodingMask.NetworkMessageNumber; } if ((NetworkMessageContentMask & NetworkMessageContentFlags.SequenceNumber) != 0) { // GroupFlags: Bit 3: SequenceNumber enabled _groupFlags |= GroupFlagsEncodingMask.SequenceNumber; } } return _groupFlags.Value; } set { _groupFlags = value; // GroupFlags: Bit 0: WriterGroupId enabled if ((value & GroupFlagsEncodingMask.WriterGroupId) != 0) { NetworkMessageContentMask |= NetworkMessageContentFlags.WriterGroupId; } // GroupFlags: Bit 1: GroupVersion enabled if ((value & GroupFlagsEncodingMask.GroupVersion) != 0) { NetworkMessageContentMask |= NetworkMessageContentFlags.GroupVersion; } // GroupFlags: Bit 2: NetworkMessageNumber enabled if ((value & GroupFlagsEncodingMask.NetworkMessageNumber) != 0) { NetworkMessageContentMask |= NetworkMessageContentFlags.NetworkMessageNumber; } // GroupFlags: Bit 3: SequenceNumber enabled if ((value & GroupFlagsEncodingMask.SequenceNumber) != 0) { NetworkMessageContentMask |= NetworkMessageContentFlags.SequenceNumber; } } } /// /// Get and set ExtendedFlags2 /// internal ExtendedFlags2EncodingMask ExtendedFlags2 { get { if (_extendedFlags2 == null) { _extendedFlags2 = 0; if ((NetworkMessageContentMask & NetworkMessageContentFlags.PromotedFields) != 0) { // ExtendedFlags2: Bit 1: PromotedFields enabled _extendedFlags2 |= ExtendedFlags2EncodingMask.PromotedFields; } // Bit range 2-4: UADP NetworkMessage type // 000 NetworkMessage with DataSetMessage payload for now } return _extendedFlags2.Value; } set { _extendedFlags2 = value; // ExtendedFlags2: Bit 1: PromotedFields enabled if ((value & ExtendedFlags2EncodingMask.PromotedFields) != 0) { NetworkMessageContentMask |= NetworkMessageContentFlags.PromotedFields; } // Bit range 2-4: UADP NetworkMessage type // 000 NetworkMessage with DataSetMessage payload for now } } /// /// Set All flags before encode/decode for a NetworkMessage that contains DataSet messages /// internal ExtendedFlags1EncodingMask ExtendedFlags1 { get { if (_extendedFlags1 == null) { _extendedFlags1 = 0; // ExtendedFlags1: Bit range 0-2: PublisherId Type if (!string.IsNullOrEmpty(PublisherId) && (NetworkMessageContentMask & NetworkMessageContentFlags.PublisherId) != 0) { if (byte.TryParse(PublisherId, out _)) { _extendedFlags1 |= ExtendedFlags1EncodingMask.PublisherIdTypeByte; } else if (ushort.TryParse(PublisherId, out _)) { _extendedFlags1 |= ExtendedFlags1EncodingMask.PublisherIdTypeUInt16; } else if (uint.TryParse(PublisherId, out _)) { _extendedFlags1 |= ExtendedFlags1EncodingMask.PublisherIdTypeUInt32; } else if (ulong.TryParse(PublisherId, out _)) { _extendedFlags1 |= ExtendedFlags1EncodingMask.PublisherIdTypeUInt64; } else { _extendedFlags1 |= ExtendedFlags1EncodingMask.PublisherIdTypeString; } } if ((NetworkMessageContentMask & NetworkMessageContentFlags.DataSetClassId) != 0) { // ExtendedFlags1 Bit 3: DataSetClassId enabled _extendedFlags1 |= ExtendedFlags1EncodingMask.DataSetClassId; } if ((NetworkMessageContentMask & NetworkMessageContentFlags.Timestamp) != 0) { // ExtendedFlags1: Bit 5: Timestamp enabled _extendedFlags1 |= ExtendedFlags1EncodingMask.Timestamp; } if ((NetworkMessageContentMask & NetworkMessageContentFlags.Picoseconds) != 0) { // ExtendedFlags1: Bit 6: PicoSeconds enabled _extendedFlags1 |= ExtendedFlags1EncodingMask.PicoSeconds; } if ((NetworkMessageContentMask & NetworkMessageContentFlags.PromotedFields) != 0) { // ExtendedFlags1: Bit 7: ExtendedFlags2 enabled _extendedFlags1 |= ExtendedFlags1EncodingMask.ExtendedFlags2; // Bit range 2-4: UADP NetworkMessage type // 000 NetworkMessage with DataSetMessage payload for now } // ExtendedFlags1: Bit 4: Security enabled // Disable security for now _extendedFlags1 &= ~ExtendedFlags1EncodingMask.Security; // The security footer size shall be omitted if bit 2 of the SecurityFlags is false. SecurityFlags &= ~SecurityFlagsEncodingMask.SecurityFooter; } return _extendedFlags1.Value; } set { _extendedFlags1 = value; // ExtendedFlags1: Bit range 0-2: PublisherId Type // ExtendedFlags1 Bit 3: DataSetClassId enabled if ((value & ExtendedFlags1EncodingMask.DataSetClassId) != 0) { NetworkMessageContentMask |= NetworkMessageContentFlags.DataSetClassId; } // ExtendedFlags1 Bit 5: Timestamp enabled if ((value & ExtendedFlags1EncodingMask.Timestamp) != 0) { NetworkMessageContentMask |= NetworkMessageContentFlags.Timestamp; } // ExtendedFlags1 Bit 6: PicoSeconds enabled if ((value & ExtendedFlags1EncodingMask.PicoSeconds) != 0) { NetworkMessageContentMask |= NetworkMessageContentFlags.Picoseconds; } } } /// /// Create message /// public UadpNetworkMessage() { SequenceNumber = () => _sequenceNumber; } /// public override bool TryDecode(Opc.Ua.IServiceMessageContext context, Stream stream, IDataSetMetaDataResolver? resolver) { var chunks = new List(); while (stream.Position != stream.Length) { using var binaryDecoder = new Opc.Ua.BinaryDecoder(stream, context); ReadNetworkMessageHeaderFlags(binaryDecoder); // decode network message header according to the header flags if (!TryReadNetworkMessageHeader(binaryDecoder, chunks.Count == 0)) { return false; } var buffers = ReadPayload(binaryDecoder, chunks).ToArray(); ReadSecurityFooter(binaryDecoder); ReadSignature(binaryDecoder); // Processing completed if (buffers.Length != 0 || chunks.Count == 0) { if (buffers.Length > 0) { DecodePayloadChunks(context, buffers, resolver); // Process all messages in the buffer } break; } // Still not processed all chunks, continue reading continue; } return true; } /// public override bool TryDecode(Opc.Ua.IServiceMessageContext context, Queue> reader, IDataSetMetaDataResolver? resolver) { var chunks = new List(); while (reader.TryPeek(out var buffer)) { using var binaryDecoder = new Opc.Ua.BinaryDecoder(buffer.ToArray(), context); ReadNetworkMessageHeaderFlags(binaryDecoder); // decode network message header according to the header flags if (!TryReadNetworkMessageHeader(binaryDecoder, chunks.Count == 0)) { return false; } var buffers = ReadPayload(binaryDecoder, chunks).ToArray(); ReadSecurityFooter(binaryDecoder); ReadSignature(binaryDecoder); // Processing completed reader.Dequeue(); if (buffers.Length != 0 || chunks.Count == 0) { if (buffers.Length > 0) { DecodePayloadChunks(context, buffers, resolver); // Process all messages in the buffer } break; } // Still not processed all chunks, continue reading continue; } return true; } /// public override IReadOnlyList> Encode( Opc.Ua.IServiceMessageContext context, int maxChunkSize, IDataSetMetaDataResolver? resolver) { var messages = new List>(); var isChunkMessage = false; var remainingChunks = EncodePayloadChunks(context, resolver).AsSpan(); // Write one message even if it does not contain anything (heartbeat) do { // Re-evaluate flags every go around _uadpFlags = null; _groupFlags = null; _extendedFlags1 = null; _extendedFlags2 = null; var networkMessageNumber = NetworkMessageNumber++; using var stream = Memory.GetStream(); using var encoder = new Opc.Ua.BinaryEncoder(stream, context, leaveOpen: true); // // Try to write all unless we are writing chunk messages. // Write span is the span of chunks that should go into // the current message. We start with all remaining chunks // and then limit it when trying to write payload. // var writeSpan = remainingChunks; // // There is a maximum of 256 messages per network message // due to the payload header count field being just a byte. // if (writeSpan.Length > byte.MaxValue) { writeSpan = writeSpan[..byte.MaxValue]; } #if DEBUG var remaining = remainingChunks.Length; #endif while (true) { WriteNetworkMessageHeaderFlags(encoder, isChunkMessage); WriteGroupMessageHeader(encoder, networkMessageNumber); WritePayloadHeader(encoder, writeSpan, isChunkMessage); WriteExtendedNetworkMessageHeader(encoder); WriteSecurityHeader(encoder); if (!TryWritePayload(encoder, maxChunkSize, ref writeSpan, ref remainingChunks, ref isChunkMessage)) { encoder.Position = 0; // Restart writing continue; } WriteSecurityFooter(encoder); WriteSignature(encoder); #if DEBUG // // Now remaining chunks should be equal (in case we are // writing a chunk message) or less than when we started. // Debug.Assert( (isChunkMessage && remaining == remainingChunks.Length) || (!isChunkMessage && remaining > remainingChunks.Length)); #endif break; } stream.SetLength(encoder.Position); var messageBuffer = stream.GetReadOnlySequence(); // TODO: instead of copy using ToArray we shall include the // stream with the message and dispose it later when it is // consumed. To get here the bug in BinaryEncoder that it // disposes the underlying stream even if leaveOpen: true // is set must be fixed. messages.Add(new ReadOnlySequence(messageBuffer.ToArray())); } while (remainingChunks.Length > 0); Debug.Assert(!isChunkMessage); return messages; } /// /// Try read network message /// /// /// /// protected virtual bool TryReadNetworkMessageHeader(Opc.Ua.BinaryDecoder binaryDecoder, bool isFirstChunk) { if ((ExtendedFlags2 & ExtendedFlags2EncodingMask.DiscoveryTypeBits) != 0) { return false; } if (!TryReadGroupMessageHeader(binaryDecoder) || !TryReadPayloadHeader(binaryDecoder, isFirstChunk) || !TryReadExtendedNetworkMessageHeader(binaryDecoder) || !TryReadSecurityHeader(binaryDecoder)) { return false; } return true; } /// /// Decode payload buffers /// /// /// /// protected virtual void DecodePayloadChunks(Opc.Ua.IServiceMessageContext context, IReadOnlyList buffers, IDataSetMetaDataResolver? resolver) { var payloadLength = buffers.Sum(b => b.Length); using var stream = new RecyclableMemoryStream(Memory, Guid.NewGuid(), PublisherId + _sequenceNumber, payloadLength); foreach (var buffer in buffers) { stream.Write(buffer); } stream.Position = 0; using var decoder = new Opc.Ua.BinaryDecoder(stream, context); foreach (var message in Messages.Cast()) { if (!message.TryDecode(decoder, resolver)) { return; } } // // Read remaining messages from buffer if possible. // This is the case if the payload header was missing // and we must use the data set message decoder to // sort out the offset and lengths of the encoding. // while (decoder.Position < payloadLength) { var extra = new UadpDataSetMessage(); if (!extra.TryDecode(decoder, resolver)) { break; } Messages.Add(extra); } } /// /// Encode payload buffers /// /// /// /// protected virtual Message[] EncodePayloadChunks(Opc.Ua.IServiceMessageContext context, IDataSetMetaDataResolver? resolver) { var chunks = new Message[Messages.Count]; for (var i = 0; i < Messages.Count; i++) { var message = (UadpDataSetMessage)Messages[i]; using var stream = Memory.GetStream(); using var encoder = new Opc.Ua.BinaryEncoder(stream, context, leaveOpen: true); message.Encode(encoder, resolver); // TODO: instead of copy using ToArray we shall include the // stream with the message and dispose it later when it is // consumed. To get here the bug in BinaryEncoder that it // disposes the underlying stream even if leaveOpen: true // is set must be fixed. chunks[i] = new Message(stream.ToArray(), message.DataSetWriterId); } return chunks; } /// /// Read Network Message Header /// /// private void ReadNetworkMessageHeaderFlags(Opc.Ua.BinaryDecoder decoder) { UadpFlags = (UADPFlagsEncodingMask)decoder.ReadByte(null); // Decode the ExtendedFlags1 if ((UadpFlags & UADPFlagsEncodingMask.ExtendedFlags1) != 0) { ExtendedFlags1 = (ExtendedFlags1EncodingMask)decoder.ReadByte(null); } // Decode the ExtendedFlags2 if ((ExtendedFlags1 & ExtendedFlags1EncodingMask.ExtendedFlags2) != 0) { ExtendedFlags2 = (ExtendedFlags2EncodingMask)decoder.ReadByte(null); } // Decode PublisherId if ((UadpFlags & UADPFlagsEncodingMask.PublisherId) != 0) { switch (ExtendedFlags1 & ExtendedFlags1EncodingMask.PublisherIdTypeBits) { case ExtendedFlags1EncodingMask.PublisherIdTypeUInt16: PublisherId = decoder.ReadUInt16(null).ToString(CultureInfo.InvariantCulture); break; case ExtendedFlags1EncodingMask.PublisherIdTypeUInt32: PublisherId = decoder.ReadUInt32(null).ToString(CultureInfo.InvariantCulture); break; case ExtendedFlags1EncodingMask.PublisherIdTypeUInt64: PublisherId = decoder.ReadUInt64(null).ToString(CultureInfo.InvariantCulture); break; case ExtendedFlags1EncodingMask.PublisherIdTypeString: PublisherId = decoder.ReadString(null); break; case ExtendedFlags1EncodingMask.PublisherIdTypeByte: PublisherId = decoder.ReadByte(null).ToString(CultureInfo.InvariantCulture); break; } } // Decode DataSetClassId if ((ExtendedFlags1 & ExtendedFlags1EncodingMask.DataSetClassId) != 0) { DataSetClassId = decoder.ReadGuid(null); } } /// /// Write Network Message Header /// /// /// /// protected void WriteNetworkMessageHeaderFlags(Opc.Ua.BinaryEncoder encoder, bool isChunkMessage) { if (isChunkMessage) { UadpFlags |= UADPFlagsEncodingMask.ExtendedFlags1; ExtendedFlags1 |= ExtendedFlags1EncodingMask.ExtendedFlags2; ExtendedFlags2 |= ExtendedFlags2EncodingMask.ChunkMessage; } encoder.WriteByte(null, (byte)UadpFlags); if ((UadpFlags & UADPFlagsEncodingMask.ExtendedFlags1) != 0) { encoder.WriteByte(null, (byte)ExtendedFlags1); } if ((ExtendedFlags1 & ExtendedFlags1EncodingMask.ExtendedFlags2) != 0) { encoder.WriteByte(null, (byte)ExtendedFlags2); } if ((UadpFlags & UADPFlagsEncodingMask.PublisherId) != 0) { if (PublisherId == null) { throw new EncodingException("NetworkMessageHeader cannot be encoded. PublisherId " + "is null but it is expected to be encoded."); } switch (ExtendedFlags1 & ExtendedFlags1EncodingMask.PublisherIdTypeBits) { case ExtendedFlags1EncodingMask.PublisherIdTypeByte: encoder.WriteByte(null, byte.Parse(PublisherId, CultureInfo.InvariantCulture)); break; case ExtendedFlags1EncodingMask.PublisherIdTypeUInt16: encoder.WriteUInt16(null, ushort.Parse(PublisherId, CultureInfo.InvariantCulture)); break; case ExtendedFlags1EncodingMask.PublisherIdTypeUInt32: encoder.WriteUInt32(null, uint.Parse(PublisherId, CultureInfo.InvariantCulture)); break; case ExtendedFlags1EncodingMask.PublisherIdTypeUInt64: encoder.WriteUInt64(null, ulong.Parse(PublisherId, CultureInfo.InvariantCulture)); break; case ExtendedFlags1EncodingMask.PublisherIdTypeString: encoder.WriteString(null, PublisherId); break; default: // Reserved - no type provided break; } } if ((NetworkMessageContentMask & NetworkMessageContentFlags.DataSetClassId) != 0) { encoder.WriteGuid(null, DataSetClassId); } } /// /// Read Group Message Header /// /// private bool TryReadGroupMessageHeader(Opc.Ua.BinaryDecoder decoder) { // Decode GroupHeader (that holds GroupFlags) if ((UadpFlags & UADPFlagsEncodingMask.GroupHeader) != 0) { GroupFlags = (GroupFlagsEncodingMask)decoder.ReadByte(null); } // Decode WriterGroupId if ((GroupFlags & GroupFlagsEncodingMask.WriterGroupId) != 0) { WriterGroupId = decoder.ReadUInt16(null); } // Decode GroupVersion if ((GroupFlags & GroupFlagsEncodingMask.GroupVersion) != 0) { GroupVersion = decoder.ReadUInt32(null); } // Decode NetworkMessageNumber if ((GroupFlags & GroupFlagsEncodingMask.NetworkMessageNumber) != 0) { NetworkMessageNumber = decoder.ReadUInt16(null); } // Decode SequenceNumber if ((GroupFlags & GroupFlagsEncodingMask.SequenceNumber) != 0) { _sequenceNumber = decoder.ReadUInt16(null); } return true; } /// /// Write Group Message Header /// /// /// private void WriteGroupMessageHeader(Opc.Ua.BinaryEncoder encoder, ushort networkMessageNumber) { if ((NetworkMessageContentMask & (NetworkMessageContentFlags.GroupHeader | NetworkMessageContentFlags.WriterGroupId | NetworkMessageContentFlags.GroupVersion | NetworkMessageContentFlags.NetworkMessageNumber | NetworkMessageContentFlags.SequenceNumber)) != 0) { encoder.WriteByte(null, (byte)GroupFlags); } if ((NetworkMessageContentMask & NetworkMessageContentFlags.WriterGroupId) != 0) { encoder.WriteUInt16(null, WriterGroupId); } if ((NetworkMessageContentMask & NetworkMessageContentFlags.GroupVersion) != 0) { encoder.WriteUInt32(null, GroupVersion); } if ((NetworkMessageContentMask & NetworkMessageContentFlags.NetworkMessageNumber) != 0) { encoder.WriteUInt16(null, networkMessageNumber); } if ((NetworkMessageContentMask & NetworkMessageContentFlags.SequenceNumber) != 0) { encoder.WriteUInt16(null, SequenceNumber()); } } /// /// Read Payload Header /// /// /// private bool TryReadPayloadHeader(Opc.Ua.BinaryDecoder decoder, bool isFirstChunk) { // Decode PayloadHeader if ((UadpFlags & UADPFlagsEncodingMask.PayloadHeader) != 0) { if ((ExtendedFlags2 & ExtendedFlags2EncodingMask.ChunkMessage) != 0) { var dataSetWriterId = decoder.ReadUInt16(null); // https://reference.opcfoundation.org/Core/Part14/v104/docs/7.2.2.2.4 if (isFirstChunk) { Messages.Add(new UadpDataSetMessage { DataSetWriterId = dataSetWriterId }); } } else { var count = decoder.ReadByte(null); for (var i = 0; i < count; i++) { Messages.Add(new UadpDataSetMessage { DataSetWriterId = decoder.ReadUInt16(null) }); } } } return true; } /// /// Write Payload Header /// /// /// /// private void WritePayloadHeader(Opc.Ua.BinaryEncoder encoder, ReadOnlySpan messages, bool isChunkMessage) { if ((NetworkMessageContentMask & NetworkMessageContentFlags.PayloadHeader) != 0) { // Write data set message payload header if (isChunkMessage) { Debug.Assert(messages.Length >= 1); // https://reference.opcfoundation.org/Core/Part14/v104/docs/7.2.2.2.4 // Write chunked NetworkMessage Payload Header (Table 77) encoder.WriteUInt16(null, messages[0].DataSetWriterId); } else { Debug.Assert(messages.Length <= byte.MaxValue); encoder.WriteByte(null, (byte)messages.Length); // Collect DataSetSetMessages headers foreach (var message in messages) { encoder.WriteUInt16(null, message.DataSetWriterId); } } } } /// /// Read extended network message header /// /// private bool TryReadExtendedNetworkMessageHeader(Opc.Ua.BinaryDecoder decoder) { // Decode Timestamp if ((ExtendedFlags1 & ExtendedFlags1EncodingMask.Timestamp) != 0) { Timestamp = decoder.ReadDateTime(null); } // Decode PicoSeconds if ((ExtendedFlags1 & ExtendedFlags1EncodingMask.PicoSeconds) != 0) { PicoSeconds = decoder.ReadUInt16(null); } return true; } /// /// Write extended network message header /// /// private void WriteExtendedNetworkMessageHeader(Opc.Ua.BinaryEncoder encoder) { if ((NetworkMessageContentMask & NetworkMessageContentFlags.Timestamp) != 0) { encoder.WriteDateTime(null, Timestamp.UtcDateTime); } if ((NetworkMessageContentMask & NetworkMessageContentFlags.Picoseconds) != 0) { encoder.WriteUInt16(null, PicoSeconds); } } /// /// Read security header /// /// private bool TryReadSecurityHeader(Opc.Ua.BinaryDecoder decoder) { if ((ExtendedFlags1 & ExtendedFlags1EncodingMask.Security) != 0) { SecurityFlags = (SecurityFlagsEncodingMask)decoder.ReadByte(null); SecurityTokenId = decoder.ReadUInt32(null); NonceLength = decoder.ReadByte(null); MessageNonce = decoder.ReadByteArray(null).ToArray(); if ((SecurityFlags & SecurityFlagsEncodingMask.SecurityFooter) != 0) { SecurityFooterSize = decoder.ReadUInt16(null); } } return true; } /// /// Write security header /// /// private void WriteSecurityHeader(Opc.Ua.BinaryEncoder encoder) { if ((ExtendedFlags1 & ExtendedFlags1EncodingMask.Security) != 0) { encoder.WriteByte(null, (byte)SecurityFlags); encoder.WriteUInt32(null, SecurityTokenId); encoder.WriteByte(null, NonceLength); MessageNonce = new byte[NonceLength]; encoder.WriteByteArray(null, MessageNonce.ToArray()); if ((SecurityFlags & SecurityFlagsEncodingMask.SecurityFooter) != 0) { encoder.WriteUInt16(null, SecurityFooterSize); } } } /// /// Decode payload size and prepare for decoding payload /// /// /// private List ReadPayload(Opc.Ua.BinaryDecoder decoder, List chunks) { var messages = new List(); if ((ExtendedFlags2 & ExtendedFlags2EncodingMask.ChunkMessage) != 0) { // Write Chunked NetworkMessage Payload Fields (Table 78) // https://reference.opcfoundation.org/Core/Part14/v104/docs/7.2.2.2.4 var messageSequenceNumber = decoder.ReadUInt16(null); var chunkOffset = decoder.ReadUInt32(null); var totalSize = decoder.ReadUInt32(null); var buffer = decoder.ReadByteString(null); var chunk = new Message(buffer, Messages.Count > 0 ? Messages[0].DataSetWriterId : (ushort)0) { ChunkOffset = chunkOffset, TotalSize = totalSize, MessageSequenceNumber = messageSequenceNumber }; chunks.Add(chunk); var messageBuffer = Message.GetMessageBufferFromChunks(chunks); if (messageBuffer == null) { return messages; } messages.Add(messageBuffer); } else { if ((UadpFlags & UADPFlagsEncodingMask.PayloadHeader) != 0) { // Read PayloadHeader Sizes for (var i = 0; i < Messages.Count; i++) { var messageSize = decoder.ReadUInt16(null); messages.Add(new byte[messageSize]); } foreach (var buffer in messages) { var read = decoder.BaseStream.Read(buffer); Debug.Assert(read == buffer.Length); } } else { var buffer = decoder.BaseStream.ReadAsBuffer().Array; if (buffer != null) { Messages.Add(new UadpDataSetMessage()); messages.Add(buffer); } } } return messages; } /// /// Write payload. The approach is to try and write everything into a single message /// first. If we get here and find we could not do it we split the messages into /// either a smaller set (writeSpan) or into a single message we write as chunked /// messages. If we return false we restart the entire encoding process. /// /// /// /// The sequence to write to the current message /// The remaining chunks to write after this /// message returns true /// Sets chunk mode on or off /// /// protected bool TryWritePayload(Opc.Ua.BinaryEncoder encoder, int maxMessageSize, ref Span writeSpan, ref Span remainingChunks, ref bool isChunkMessage) { const int kChunkHeaderSize = 2 // MessageSequenceNumber + 4 // ChunkOffset + 4 // TotalOffset + 4 // ByteString Length ; var payloadOffset = encoder.Position; var available = maxMessageSize - payloadOffset - SecurityFooterSize - Signature.Length - kChunkHeaderSize; if (available < 0) { if (writeSpan.Length <= 1) { // Nothing fits. We should not be here - fail catastrophically... throw new EncodingException( "Max message size too small for header for single message"); } // Try to limit the number of messages by half writeSpan = writeSpan[..(writeSpan.Length / 2)]; return false; } if (writeSpan.Length == 0) { // Nothing to do return true; } var hasHeader = (NetworkMessageContentMask & NetworkMessageContentFlags.PayloadHeader) != 0; var headerSize = hasHeader ? 2 : 0; var chunk = writeSpan[0]; // // We break any message into chunks that a) does not fit in available space, // or b) exceeds the ushort size fields. We count the header size in here to // avoid dropping into the else and failing to fit the first chunk. // if (isChunkMessage || (chunk.Remaining + headerSize) > available || chunk.Remaining > ushort.MaxValue) { if (!isChunkMessage) { isChunkMessage = true; writeSpan = writeSpan[..1]; // Restart writing the complete buffer now in chunk message mode return false; } available = Math.Min(available, ushort.MaxValue); // Write Chunked NetworkMessage Payload Fields (Table 78) // https://reference.opcfoundation.org/Core/Part14/v104/docs/7.2.2.2.4 encoder.WriteUInt16(null, chunk.MessageSequenceNumber); encoder.WriteUInt32(null, chunk.ChunkOffset); encoder.WriteUInt32(null, (uint)chunk.ChunkData.Length); var chunkLength = Math.Min(chunk.Remaining, available); encoder.WriteInt32(null, chunkLength); // Write byte string encoder.WriteRawBytes(chunk.ChunkData.ToArray(), (int)chunk.ChunkOffset, chunkLength); chunk.ChunkOffset += (uint)chunkLength; if (chunk.Remaining == 0) { // Completed writeSpan = remainingChunks = remainingChunks[1..]; isChunkMessage = false; } else { // Write more into next message chunk.MessageSequenceNumber++; } } else { var writeCount = 0; for (; writeCount < writeSpan.Length; writeCount++) { var currentChunk = writeSpan[writeCount]; if ((currentChunk.Remaining + headerSize) > available) { break; } available -= currentChunk.Remaining + headerSize; } if (writeSpan.Length != writeCount) { // Restart by limiting the number of chunks we will write to this message to what fits writeSpan = remainingChunks[..writeCount]; return false; } // https://reference.opcfoundation.org/Core/Part14/v104/docs/7.2.2.3.3 if (hasHeader) { foreach (var buffer in writeSpan) { Debug.Assert(buffer.ChunkData.Length <= ushort.MaxValue); encoder.WriteUInt16(null, (ushort)buffer.ChunkData.Length); } } foreach (var buffer in writeSpan) { encoder.WriteRawBytes(buffer.ChunkData.ToArray(), 0, buffer.ChunkData.Length); } remainingChunks = remainingChunks[writeCount..]; writeSpan = default; } // Write security header after and finish message return true; } /// /// Read security footer /// /// protected void ReadSecurityFooter(Opc.Ua.BinaryDecoder decoder) { if ((SecurityFlags & SecurityFlagsEncodingMask.SecurityFooter) != 0) { SecurityFooter = decoder.ReadByteArray(null).ToArray().AsMemory(); } } /// /// Write security footer /// /// protected void WriteSecurityFooter(Opc.Ua.BinaryEncoder encoder) { if ((SecurityFlags & SecurityFlagsEncodingMask.SecurityFooter) != 0) { encoder.WriteByteArray(null, SecurityFooter.ToArray()); } } /// /// Read signature /// /// protected void ReadSignature(Opc.Ua.BinaryDecoder decoder) { if ((SecurityFlags & SecurityFlagsEncodingMask.SecurityFooter) != 0) { Signature = decoder.ReadByteArray(null).ToArray(); } } /// /// Write signature /// /// protected void WriteSignature(Opc.Ua.BinaryEncoder encoder) { if ((SecurityFlags & SecurityFlagsEncodingMask.SecurityFooter) != 0 && Signature.Length > 0) { encoder.WriteByteArray(null, Signature.ToArray()); } } /// /// Track messages /// protected sealed class Message { /// /// Data set writer of the dataset message /// public ushort DataSetWriterId { get; } /// /// Current message sequence number /// public ushort MessageSequenceNumber { get; set; } /// /// Chunk offset /// public uint ChunkOffset { get; set; } /// /// Full message buffer /// public uint TotalSize { get; set; } /// /// Chunk length /// public int Remaining => ChunkData.Length - (int)ChunkOffset; /// /// Full message buffer /// public ReadOnlyMemory ChunkData { get; } /// /// Get message buffer from chunk list /// /// /// public static byte[]? GetMessageBufferFromChunks(IList chunks) { if (chunks.Count == 0) { return null; } var totalSize = chunks[0].TotalSize; if (!chunks.All(a => a.TotalSize == totalSize)) { chunks.Clear(); return []; } var total = chunks.Sum(c => c.ChunkData.Length); if (total >= totalSize) { var message = new byte[total]; int? firstIndex = null; foreach (var c in chunks.OrderBy(a => a.MessageSequenceNumber)) { if (firstIndex == null) { firstIndex = c.MessageSequenceNumber; } else { firstIndex++; if (c.MessageSequenceNumber != firstIndex) { chunks.Clear(); return []; } } Array.Copy(c.ChunkData.ToArray(), 0, message, c.ChunkOffset, c.ChunkData.Length); } chunks.Clear(); return message; } return null; } /// /// Create chunk /// /// /// public Message(byte[] buffer, ushort dataSetWriterId) { ChunkData = buffer; TotalSize = (uint)buffer.Length; ChunkOffset = 0; DataSetWriterId = dataSetWriterId; MessageSequenceNumber = 0; } } private UADPFlagsEncodingMask? _uadpFlags; private GroupFlagsEncodingMask? _groupFlags; private ExtendedFlags2EncodingMask? _extendedFlags2; private ExtendedFlags1EncodingMask? _extendedFlags1; /// To update sequence number protected ushort _sequenceNumber; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/Avro/AvroBuiltInSchemas.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas.Avro { using global::Avro; using Opc.Ua; using System; using System.Collections.Generic; using System.Linq; /// /// Provides the Avro schemas of built in types and objects /// for the Avro binary encoding /// internal class AvroBuiltInSchemas : BaseBuiltInSchemas { private static Schema EnumerationSchema { get { // Enumeration is a record of type int return Primitive((int)BuiltInType.Enumeration, nameof(BuiltInType.Enumeration), "int"); } } private Schema DiagnosticInfoSchema { get { return RecordSchema.Create(nameof(BuiltInType.DiagnosticInfo), [ new (GetSchemaForBuiltInType(BuiltInType.Int32), "SymbolicId", 0), new (GetSchemaForBuiltInType(BuiltInType.Int32), "NamespaceUri", 1), new (GetSchemaForBuiltInType(BuiltInType.Int32), "Locale", 2), new (GetSchemaForBuiltInType(BuiltInType.Int32), "LocalizedText", 3), new (GetSchemaForBuiltInType(BuiltInType.String), "AdditionalInfo", 4), new (GetSchemaForBuiltInType(BuiltInType.StatusCode), "InnerStatusCode", 5), new (GetSchemaForBuiltInType(BuiltInType.DiagnosticInfo).AsNullable(), "InnerDiagnosticInfo", 6) ], SchemaUtils.NamespaceZeroName, new[] { GetDataTypeId(BuiltInType.DiagnosticInfo) }); } } private Schema VariantSchema { get { var types = AvroSchema.Null.YieldReturn() .Concat(GetPossibleTypes(SchemaRank.Scalar)) .Concat(GetPossibleTypes(SchemaRank.Collection)) .Concat(GetPossibleTypes(SchemaRank.Matrix)) .ToList(); return RecordSchema.Create(nameof(BuiltInType.Variant), [ new (UnionSchema.Create(types), kSingleFieldName, 0) ], SchemaUtils.NamespaceZeroName, new[] { GetDataTypeId(BuiltInType.Variant) }); IEnumerable GetPossibleTypes(SchemaRank valueRank) { for (var i = 1; i <= 29; i++) { if (i == (int)BuiltInType.DiagnosticInfo) { continue; } if (i == 26 || i == 27 || i == 28) { continue; } if (i == (int)BuiltInType.Variant && valueRank == SchemaRank.Scalar) { continue; // Array of variant is allowed } if (i == (int)BuiltInType.Byte && valueRank == SchemaRank.Collection) { continue; // Array of bytes is not allowed } yield return GetSchemaForBuiltInType((BuiltInType)i, valueRank); } } } } private Schema ExtensionObjectSchema { get { return RecordSchema.Create(nameof(BuiltInType.ExtensionObject), [ new (AvroSchema.AsUnion(RecordSchema.Create("EncodedDataType", [ new (GetSchemaForBuiltInType(BuiltInType.NodeId), "TypeId", 0), new (GetSchemaForBuiltInType(BuiltInType.ByteString), "Body", 1) ], SchemaUtils.NamespaceZeroName)), kSingleFieldName, 0) // ... ], SchemaUtils.NamespaceZeroName, new[] { GetDataTypeId(BuiltInType.ExtensionObject) }); } } private Schema QualifiedNameSchema { get { return RecordSchema.Create(nameof(BuiltInType.QualifiedName), [ new (GetSchemaForBuiltInType(BuiltInType.String), "Namespace", 0), new (GetSchemaForBuiltInType(BuiltInType.String), "Name", 1) ], SchemaUtils.NamespaceZeroName, new[] { GetDataTypeId(BuiltInType.QualifiedName) }); } } private Schema LocalizedTextSchema { get { return RecordSchema.Create(nameof(BuiltInType.LocalizedText), [ new (GetSchemaForBuiltInType(BuiltInType.String), "Locale", 0), new (GetSchemaForBuiltInType(BuiltInType.String), "Text", 1) ], SchemaUtils.NamespaceZeroName, new[] { GetDataTypeId(BuiltInType.LocalizedText) }); } } private Schema NodeIdSchema { get { var idType = AvroSchema.AsUnion( GetSchemaForBuiltInType(BuiltInType.UInt32), GetSchemaForBuiltInType(BuiltInType.String), GetSchemaForBuiltInType(BuiltInType.Guid), GetSchemaForBuiltInType(BuiltInType.ByteString)); return RecordSchema.Create(nameof(BuiltInType.NodeId), [ new (GetSchemaForBuiltInType(BuiltInType.String), "Namespace", 0), new (idType, "Identifier", 1) ], SchemaUtils.NamespaceZeroName, new[] { GetDataTypeId(BuiltInType.NodeId) }); } } private Schema ExpandedNodeIdSchema { get { var idType = AvroSchema.AsUnion( GetSchemaForBuiltInType(BuiltInType.UInt32), GetSchemaForBuiltInType(BuiltInType.String), GetSchemaForBuiltInType(BuiltInType.Guid), GetSchemaForBuiltInType(BuiltInType.ByteString)); return RecordSchema.Create(nameof(BuiltInType.ExpandedNodeId), [ new (GetSchemaForBuiltInType(BuiltInType.String), "Namespace", 0), new (idType, "Identifier", 1), new (GetSchemaForBuiltInType(BuiltInType.String), "ServerUri", 3) ], SchemaUtils.NamespaceZeroName, new[] { GetDataTypeId(BuiltInType.ExpandedNodeId) }); } } private Schema DataValueSchema { get { return RecordSchema.Create(nameof(BuiltInType.DataValue), [ new (GetSchemaForBuiltInType(BuiltInType.Variant), "Value", 0), new (GetSchemaForBuiltInType(BuiltInType.StatusCode), "StatusCode", 1), new (GetSchemaForBuiltInType(BuiltInType.DateTime), "SourceTimestamp", 2), new (GetSchemaForBuiltInType(BuiltInType.UInt16), "SourcePicoseconds", 3), new (GetSchemaForBuiltInType(BuiltInType.DateTime), "ServerTimestamp", 4), new (GetSchemaForBuiltInType(BuiltInType.UInt16), "ServerPicoseconds", 5) ], SchemaUtils.NamespaceZeroName, new[] { GetDataTypeId(BuiltInType.DataValue) }); } } private static Schema UlongSchema { get { return RecordSchema.Create(nameof(BuiltInType.UInt64), [ new (UnionSchema.Create( [ PrimitiveSchema.NewInstance("int"), FixedSchema.Create("ulong", 8, SchemaUtils.NamespaceZeroName) ]), kSingleFieldName, 0) ], SchemaUtils.NamespaceZeroName, new[] { GetDataTypeId(BuiltInType.DataValue) }); } } /// public override Schema GetSchemaForBuiltInType(BuiltInType builtInType, SchemaRank rank = SchemaRank.Scalar) { // Always use byte string for byte arrays if (builtInType == BuiltInType.Byte && rank == SchemaRank.Collection) { builtInType = BuiltInType.ByteString; rank = SchemaRank.Scalar; } // TODO: Placeholder caching is needed to avoid stack overflow // However we should clear the cache every time we completed the // api lookup, to avoid getting placeholder items leaking out // to an outside caller. if (!_builtIn.TryGetValue((builtInType, rank), out var schema)) { // Before we create the schema add a place // holder here to break any recursin. _builtIn.Add((builtInType, rank), PlaceHolder(builtInType, rank)); switch (rank) { case SchemaRank.Matrix: schema = MatrixType((int)builtInType, builtInType.ToString()); break; case SchemaRank.Collection: schema = CollectionType((int)builtInType, builtInType.ToString()); break; default: schema = Get((int)builtInType); break; } _builtIn[(builtInType, rank)] = schema; } return schema; Schema Get(int id) => id switch { 0 => AvroSchema.Null, 1 => Primitive(id, "Boolean", "boolean"), 2 => Primitive(id, "SByte", "int"), 3 => Primitive(id, "Byte", "int"), 4 => Primitive(id, "Int16", "int"), 5 => Primitive(id, "UInt16", "int"), 6 => Primitive(id, "Int32", "int"), 7 => Primitive(id, "UInt32", "int"), 8 => Primitive(id, "Int64", "int"), 9 => UlongSchema, 10 => Primitive(id, "Float", "float"), 11 => Primitive(id, "Double", "double"), 12 => Primitive(id, "String", "string"), 13 => Primitive(id, "DateTime", "long"), #if UUID_FIXED 14 => Fixed(id, "Guid", "uuid", 16), #else 14 => Primitive(id, "Guid", "string", "uuid"), #endif 15 => Primitive(id, "ByteString", "bytes"), 16 => Primitive(id, "XmlElement", "string"), 17 => NodeIdSchema, 18 => ExpandedNodeIdSchema, 19 => Primitive(id, "StatusCode", "long"), 20 => QualifiedNameSchema, 21 => LocalizedTextSchema, 22 => ExtensionObjectSchema, 23 => DataValueSchema, 24 => VariantSchema, 25 => DiagnosticInfoSchema, 26 => VariantSchema, // Primitive(id, "Number", "string"), 27 => VariantSchema, // Primitive(id, "Integer", "string"), 28 => VariantSchema, // Primitive(id, "UInteger", "string"), 29 => EnumerationSchema, _ => throw new ArgumentException($"Built in type {id} unknown") }; } /// public override Schema GetSchemaForExtendableType(string name, string ns, string dataTypeId, Schema bodyType) { // Extension objects are records of fields // 1. Encoding Node Id // 2. A union of // 1. null // 2. A encodeable type // 3. A record with // 1. ExtensionObjectEncoding type enum // 2. bytes that are either binary opc ua or xml/json utf 8 var encodingType = EnumSchema.Create("ExtensionObjectEncoding", new string[] { "None", "Binary", "Xml", "Reserved1", "ByteString" }); return RecordSchema.Create(name + nameof(BuiltInType.ExtensionObject), [ new (GetSchemaForBuiltInType(BuiltInType.NodeId), "TypeId", 0), new (UnionSchema.Create( [ AvroSchema.Null, bodyType, RecordSchema.Create("Encoded", [ new (encodingType, "Encoding", 0), new (GetSchemaForBuiltInType(BuiltInType.ByteString), "Bytes", 1) ]) ]), "Body", 1) ], ns, new[] { dataTypeId }); } /// public override Schema GetSchemaForDataSetField(string ns, bool asDataValue, Schema valueSchema, BuiltInType builtInType) { var variantSchema = GetSchemaForBuiltInType(BuiltInType.Variant); #if USE_VARIANT_FOR_DATAVALUE valueSchema = variantSchema; #endif var schemaName = string.Empty; var space = SchemaUtils.NamespaceZeroName; if (valueSchema.Fullname != variantSchema.Fullname) { // Variant is by default already nullable schemaName = valueSchema.Name; space = ns; valueSchema = valueSchema.AsNullable(); } if (asDataValue) { return RecordSchema.Create(schemaName + nameof(BuiltInType.DataValue), [ new (valueSchema, "Value", 0), new (GetSchemaForBuiltInType(BuiltInType.StatusCode), "StatusCode", 1), new (GetSchemaForBuiltInType(BuiltInType.DateTime), "SourceTimestamp", 2), new (GetSchemaForBuiltInType(BuiltInType.UInt16), "SourcePicoseconds", 3), new (GetSchemaForBuiltInType(BuiltInType.DateTime), "ServerTimestamp", 4), new (GetSchemaForBuiltInType(BuiltInType.UInt16), "ServerPicoseconds", 5) ], space).AsNullable(); } return valueSchema; } /// public override Schema GetSchemaForRank(Schema schema, SchemaRank rank) { switch (rank) { case SchemaRank.Matrix: return MatrixType(schema); case SchemaRank.Collection: return CollectionType(schema); default: return schema; } } /// /// Get data typeid /// /// /// private static string GetDataTypeId(BuiltInType builtInType) { return "i_" + (int)builtInType; } /// /// Create primitive opc ua built in type /// /// /// /// /// /// internal static Schema Primitive(int builtInType, string name, string type, string? logicalType = null) { var baseType = logicalType == null ? PrimitiveSchema.NewInstance(type) : Schema.Parse( $$"""{"type": "{{type}}", "logicalType": "{{logicalType}}"}"""); return RecordSchema.Create(name, [ new (baseType, kSingleFieldName, 0) ], SchemaUtils.NamespaceZeroName, new[] { GetDataTypeId((BuiltInType)builtInType) }); } /// /// Create primitive opc ua built in type /// /// /// /// /// /// internal static Schema Fixed(int builtInType, string name, string baseName, int size) { var baseType = FixedSchema.Create(baseName, size); return RecordSchema.Create(name, [ new (baseType, kSingleFieldName, 0) ], SchemaUtils.NamespaceZeroName, new[] { GetDataTypeId((BuiltInType)builtInType) }); } /// /// Create collection opc ua built in type /// /// /// /// internal Schema CollectionType(int builtInType, string name) { var baseType = GetSchemaForBuiltInType((BuiltInType)builtInType); return CollectionType(baseType, name, SchemaUtils.NamespaceZeroName); } /// /// Create collection type /// /// /// /// /// private static RecordSchema CollectionType(Schema baseType, string? name = null, string? space = null) { name ??= baseType.Name; if (space == null && baseType is NamedSchema n) { space = n.Namespace; } space ??= SchemaUtils.PublisherNamespace; return RecordSchema.Create(name + nameof(SchemaRank.Collection), [ new (baseType.AsArray(), kSingleFieldName, 0) ], space); } /// /// Create matrix opc ua built in type /// /// /// /// internal Schema MatrixType(int builtInType, string name) { var baseType = GetSchemaForBuiltInType((BuiltInType)builtInType); return MatrixType(baseType, name, SchemaUtils.NamespaceZeroName); } /// /// Create matrix type /// /// /// /// /// private RecordSchema MatrixType(Schema baseType, string? name = null, string? space = null) { name ??= baseType.Name; if (space == null && baseType is NamedSchema n) { space = n.Namespace; } space ??= SchemaUtils.PublisherNamespace; return RecordSchema.Create(name + nameof(SchemaRank.Matrix), [ new (GetSchemaForBuiltInType(BuiltInType.Int32, SchemaRank.Collection), "Dimensions", 0), new (baseType.AsArray(), kSingleFieldName, 0) ], space); } /// /// Create a place holder /// /// /// /// private static AvroSchema.PlaceHolder PlaceHolder(BuiltInType builtInType, SchemaRank rank) { var name = builtInType.ToString(); if (rank != SchemaRank.Scalar) { name += rank; } return AvroSchema.CreatePlaceHolder(name, SchemaUtils.NamespaceZeroName); } private const string kSingleFieldName = "Value"; private readonly Dictionary<(BuiltInType, SchemaRank), Schema> _builtIn = []; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/Avro/AvroDataSet.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas.Avro { using Azure.IIoT.OpcUa.Encoders; using Azure.IIoT.OpcUa.Publisher.Models; using Furly; using Furly.Extensions.Messaging; using global::Avro; using System.Collections.Generic; using System.Linq; /// /// Extensions to convert metadata into avro schema. Note that this class /// generates a schema that complies with the avro representation in /// . /// public class AvroDataSet : BaseDataSetSchema, IAvroSchema, IEventSchema { /// public string Type => ContentMimeType.AvroSchema; /// public string Name => Schema.Fullname; /// public ulong Version { get; } /// string IEventSchema.Schema => Schema.ToString(); /// public string Id { get; } /// public override Schema Schema { get; } /// /// Get avro schema for a dataset /// /// /// /// /// /// public AvroDataSet(string id, PublishedDataSetMetaDataModel dataSet, DataSetFieldContentFlags? dataSetFieldContentFlags = null, SchemaOptions? options = null, HashSet? uniqueNames = null) : base(dataSetFieldContentFlags, new AvroBuiltInSchemas(), options) { Id = id; Schema = Compile(dataSet.DataSetMetaData?.Name, dataSet, uniqueNames) ?? AvroSchema.Null; } /// public override string? ToString() { return Schema.ToString(); } /// protected override IEnumerable GetDataSetFieldSchemas(string? name, PublishedDataSetMetaDataModel dataSet, HashSet? uniqueNames) { var singleValue = dataSet.Fields.Count == 1; GetEncodingMode(out var omitFieldName, out var fieldsAreDataValues, singleValue); if (omitFieldName) { var set = new HashSet(); foreach (var fieldMetadata in dataSet.Fields) { if (fieldMetadata?.DataType != null) { set.Add(LookupSchema(fieldMetadata.DataType, SchemaUtils.GetRank(fieldMetadata.ValueRank), fieldMetadata.ArrayDimensions)); } } return set.Select(s => s.AsNullable()); } var ns = _options.Namespace != null ? SchemaUtils.NamespaceUriToNamespace(_options.Namespace) : SchemaUtils.PublisherNamespace; var fields = new List(); var pos = 0; foreach (var fieldMetadata in dataSet.Fields) { // Now collect the fields of the payload pos++; if (fieldMetadata?.DataType != null) { var schema = LookupSchema(fieldMetadata.DataType, SchemaUtils.GetRank(fieldMetadata.ValueRank), fieldMetadata.ArrayDimensions); if (fieldMetadata.Name != null) { // TODO: Add properties to the field type schema = Encoding.GetSchemaForDataSetField(ns, fieldsAreDataValues, schema, (Opc.Ua.BuiltInType)fieldMetadata.BuiltInType); fields.Add(new Field(schema, SchemaUtils.Escape(fieldMetadata.Name), pos)); } } } // Type name of the message record name ??= dataSet.DataSetMetaData.Name; if (string.IsNullOrEmpty(name)) { // Type name of the message record name = "DataSet"; } else { name = SchemaUtils.Escape(name); } return RecordSchema.Create(MakeUnique(name, uniqueNames), fields).YieldReturn(); } /// protected override Schema CreateStructureSchema(StructureDescriptionModel description, SchemaRank rank, Schema? baseTypeSchema) { // // |---------------|------------|----------------| // | Field Value | Reversible | Non-Reversible | // |---------------|------------|----------------| // | NULL | Omitted | JSON null | // | Default Value | Omitted | Default Value | // |---------------|------------|----------------| // var fields = new List(); var pos = 0; if (baseTypeSchema is RecordSchema b) { foreach (var field in b.Fields) { fields.Add(new Field(field.Schema, field.Name, pos++, field.Aliases, field.Documentation, field.DefaultValue)); // Can we copy type property to the field to show inheritance } } foreach (var field in description.Fields) { var schema = LookupSchema(field.DataType, SchemaUtils.GetRank(field.ValueRank), field.ArrayDimensions); if (field.IsOptional) { schema = schema.AsNullable(); } fields.Add(new Field(schema, SchemaUtils.Escape(field.Name), pos++)); } var (ns1, dt) = SchemaUtils.SplitNodeId(description.DataTypeId, Context, true); var name = SchemaUtils.SplitQualifiedName(description.Name, Context, ns1); var scalar = RecordSchema.Create(name, fields, ns1, new[] { dt }, customProperties: AvroSchema.Properties(description.DataTypeId)); return Encoding.GetSchemaForRank(scalar, rank); } /// protected override Schema CreateEnumSchema(EnumDescriptionModel description, SchemaRank rank) { var (ns, dt) = SchemaUtils.SplitNodeId(description.DataTypeId, Context, true); var symbols = description.Fields .Select(e => SchemaUtils.Escape(e.Name)) .ToList(); var scalar = EnumSchema.Create( SchemaUtils.SplitQualifiedName(description.Name, Context, ns), symbols, ns, new[] { dt }, customProperties: AvroSchema.Properties(description.DataTypeId), defaultSymbol: symbols[0]); // TODO: Build doc from fields descriptions return Encoding.GetSchemaForRank(scalar, rank); } /// protected override Schema CreateUnionSchema(IReadOnlyList schemas) { return schemas.AsUnion(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/Avro/AvroDataSetMessage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas.Avro { using Azure.IIoT.OpcUa.Encoders.Schemas; using Azure.IIoT.OpcUa.Encoders.PubSub; using Azure.IIoT.OpcUa.Publisher.Models; using global::Avro; using Opc.Ua; using System.Collections.Generic; /// /// Avro Dataset message avro schema /// public sealed class AvroDataSetMessage : BaseDataSetMessage { /// public override Schema Schema { get; } /// protected override BaseDataSetSchema DataSetSchema { get; } /// /// Get avro schema for a dataset /// /// /// /// /// /// internal AvroDataSetMessage(PublishedDataSetMessageSchemaModel dataSetMessage, NetworkMessageContentFlags networkMessageContentFlags, SchemaOptions options, HashSet uniqueNames) : base(dataSetMessage.Id) { DataSetSchema = new AvroDataSet(dataSetMessage.Id, dataSetMessage.MetaData, dataSetMessage.DataSetFieldContentFlags, options, uniqueNames); Schema = Compile(dataSetMessage.TypeName, dataSetMessage.DataSetMessageContentFlags ?? PubSubMessage.DefaultDataSetMessageContentFlags, uniqueNames, networkMessageContentFlags, options); } /// protected override IEnumerable CollectFields( DataSetMessageContentFlags dataSetMessageContentFlags, NetworkMessageContentFlags networkMessageContentFlags, Schema valueSchema) { var encoding = new AvroBuiltInSchemas(); var version = RecordSchema.Create(nameof(ConfigurationVersionDataType), [ new(encoding.GetSchemaForBuiltInType(BuiltInType.UInt32), "MajorVersion", 0), new(encoding.GetSchemaForBuiltInType(BuiltInType.UInt32), "MinorVersion", 1) ], SchemaUtils.NamespaceZeroName, new[] { "i_" + DataTypes.ConfigurationVersionDataType }); return new List { new(encoding.GetSchemaForBuiltInType(BuiltInType.String), nameof(DataSetMessageContentFlags.MessageType), 0), new(encoding.GetSchemaForBuiltInType(BuiltInType.String), nameof(DataSetMessageContentFlags.DataSetWriterName), 1), new(encoding.GetSchemaForBuiltInType(BuiltInType.UInt16), nameof(DataSetMessageContentFlags.DataSetWriterId), 2), new(encoding.GetSchemaForBuiltInType(BuiltInType.UInt32), nameof(DataSetMessageContentFlags.SequenceNumber), 3), new(version, nameof(DataSetMessageContentFlags.MetaDataVersion), 4), new(encoding.GetSchemaForBuiltInType(BuiltInType.DateTime), nameof(DataSetMessageContentFlags.Timestamp), 5), new(encoding.GetSchemaForBuiltInType(BuiltInType.StatusCode), nameof(DataSetMessageContentFlags.Status), 6), new(valueSchema, nameof(PubSub.AvroDataSetMessage.Payload), 7) }; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/Avro/AvroNetworkMessage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas.Avro { using Azure.IIoT.OpcUa.Encoders.Schemas; using Azure.IIoT.OpcUa.Publisher.Models; using global::Avro; using Opc.Ua; using System.Collections.Generic; /// /// Network message avro schema /// public sealed class AvroNetworkMessage : BaseNetworkMessage { /// public override Schema Schema { get; } /// /// Get avro schema for a writer group /// /// /// /// public AvroNetworkMessage(PublishedNetworkMessageSchemaModel networkMessage, SchemaOptions? options = null) : base(networkMessage.Id, networkMessage.Version) { Schema = Compile(networkMessage, options); } /// protected override Schema Compile(PublishedDataSetMessageSchemaModel dataSetMessage, NetworkMessageContentFlags networkMessageContentFlags, SchemaOptions options, HashSet uniqueNames) { return new AvroDataSetMessage(dataSetMessage, networkMessageContentFlags, options, uniqueNames).Schema; } /// protected override IEnumerable CollectFields( NetworkMessageContentFlags contentMask, Schema payloadType) { var HasNetworkMessageHeader = contentMask .HasFlag(NetworkMessageContentFlags.NetworkMessageHeader); var encoding = new AvroBuiltInSchemas(); return HasNetworkMessageHeader ? [ new(encoding.GetSchemaForBuiltInType(BuiltInType.String), nameof(PubSub.AvroNetworkMessage.MessageId), 0), new(encoding.GetSchemaForBuiltInType(BuiltInType.String), nameof(PubSub.AvroNetworkMessage.MessageType), 1), new(encoding.GetSchemaForBuiltInType(BuiltInType.String), nameof(PubSub.AvroNetworkMessage.PublisherId), 2), new(encoding.GetSchemaForBuiltInType(BuiltInType.Guid), nameof(PubSub.AvroNetworkMessage.DataSetClassId), 3), new(encoding.GetSchemaForBuiltInType(BuiltInType.String), nameof(PubSub.AvroNetworkMessage.DataSetWriterGroup), 4), new(payloadType, nameof(PubSub.AvroNetworkMessage.Messages), 5) ] : [ new(payloadType, nameof(PubSub.AvroNetworkMessage.Messages), 0) ]; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/Avro/AvroSchema.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas.Avro { using Azure.IIoT.OpcUa.Encoders.Schemas; using global::Avro; using Opc.Ua; using Opc.Ua.Extensions; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text.Json; /// /// Avro schema extensions /// internal static class AvroSchema { /// /// Null schema /// public static Schema Null { get; } = PrimitiveSchema.NewInstance("null"); /// /// Set data type /// /// /// public static PropertyMap Properties(string? dataTypeId) { return new PropertyMap() .AddProperty(kUaDataTypeIdKey, dataTypeId); } /// /// Get the property map /// /// /// /// /// public static PropertyMap AddProperty(this PropertyMap properties, string key, string? value) { if (value != null) { // Need to add json strings properties.Add(key, "\"" + value + "\""); } return properties; } /// /// Get the data type id /// /// /// /// public static ExpandedNodeId GetDataTypeId(this Schema schema, IServiceMessageContext context) { var type = schema.GetProperty(kUaDataTypeIdKey); if (type == null && schema is NamedSchema ns && context.NamespaceUris.TryFindNamespace(ns.Namespace, out var namespaceIndex, out var namespaceUri)) { return new ExpandedNodeId(ns.Name, (ushort)namespaceIndex, namespaceUri, 0); } if (type == null) { return ExpandedNodeId.Null; } return type.TrimQuotes().ToExpandedNodeId(context); } /// /// Create nullable /// /// /// public static Schema AsNullable(this Schema schema) { if (schema == Null) { return schema; } if (schema is UnionSchema u) { if (!u.Schemas.Contains(Null)) { u.Schemas.Insert(0, Null); } else { Debug.Assert(u.Schemas[0] == Null); } return u; } return UnionSchema.Create( [ Null, schema ]); } /// /// Returns the schema as formatted json /// /// /// /// public static string ToJson(this Schema schema, JsonSerializerOptions? options = null) { var json = schema.ToString(); var document = JsonDocument.Parse(json); return JsonSerializer.Serialize(document, options ?? kIndented); } /// /// Is data value /// /// /// public static bool IsDataValue(this Schema schema) { if (schema is not RecordSchema r) { return false; } return r.Fields.Count == 6 && r.Fields .Select(r => r.Name).SequenceEqual(new[] { "Value", "StatusCode", "SourceTimestamp", "SourcePicoseconds", "ServerTimestamp", "ServerPicoseconds" }); } /// /// Test for built in type /// /// /// /// /// public static bool IsBuiltInType(this Schema schema, out BuiltInType builtInType, out SchemaRank valueRank) { valueRank = SchemaRank.Scalar; if (schema is RecordSchema ns && ns.SchemaName.Namespace == SchemaUtils.NamespaceZeroName) { var name = ns.Name; if (name.EndsWith(nameof(SchemaRank.Collection), StringComparison.InvariantCulture)) { valueRank = SchemaRank.Collection; name = name[..^nameof(SchemaRank.Collection).Length]; } else if (name.EndsWith(nameof(SchemaRank.Matrix), StringComparison.InvariantCulture)) { valueRank = SchemaRank.Matrix; name = name[..^nameof(SchemaRank.Matrix).Length]; } if (Enum.TryParse(name, out builtInType)) { return true; } } if (schema is ArraySchema a) { valueRank = SchemaRank.Collection; schema = a.ItemSchema; } if (schema is EnumSchema) { builtInType = BuiltInType.Enumeration; return true; } builtInType = BuiltInType.Null; return false; } /// /// Create array /// /// /// /// public static Schema AsArray(this Schema itemSchema, bool isRoot = false) { var schema = ArraySchema.Create(itemSchema, isRoot ? new PropertyMap { ["root"] = "true" } : null); if (isRoot) { schema.CreateRoot(); } return schema; } /// /// Create /// /// /// public static Schema AsUnion(params Schema[] schemas) { return schemas.AsUnion(customProperties: null); } /// /// Create /// /// /// /// public static UnionSchema AsUnion(this IEnumerable schemas, PropertyMap? customProperties = null) { var types = schemas.Distinct( Compare.Using((a, b) => a?.Fullname == b?.Fullname)).ToList(); return UnionSchema.Create(types, customProperties); } /// /// Create root schema for a schema or field at the root /// /// /// /// public static RecordSchema CreateRoot(this Schema schema, string? fieldName = null) { return RecordSchema.Create(kRootSchemaName, [ new (schema, fieldName ?? kRootFieldName, 0) ], kRootNamespace); } /// /// Check whether to skip the dummy root during validation /// /// /// public static bool IsRoot(this Schema schema) { return schema is RecordSchema r && r.Name == kRootSchemaName && r.Fields.Count == 1 && r.Namespace == kRootNamespace; } /// /// Unwrap a root place holder /// /// /// public static Schema Unwrap(this Schema schema) { if (schema.IsRoot()) { var root = (RecordSchema)schema; if (root.Fields.Count == 1 && root.Fields[0].Name == kRootFieldName) { root = root.Fields[0].Schema as RecordSchema; if (root != null) { return root; } } } return schema; } /// /// Create derived schema /// /// /// /// public static PlaceHolder CreatePlaceHolder(string name, string ns) { return new PlaceHolder(Schema.Type.Record, new SchemaName(name, ns, null, null)); } /// /// Derived schema /// public class PlaceHolder : NamedSchema { /// public PlaceHolder(Type type, SchemaName name, IList? aliases = null, PropertyMap? props = null, SchemaNames? names = null, string? doc = null) : base(type, name, GetSchemaNames(aliases, name), props, names ?? new SchemaNames(), doc) { } internal static IList? GetSchemaNames( IEnumerable? aliases, SchemaName typeName) { if (aliases == null) { return null; } return aliases.Select(alias => new SchemaName( alias, typeName.Namespace, null, null)).ToList(); } } private const string kRootFieldName = "Value"; private const string kRootSchemaName = "Type"; private const string kRootNamespace = "org.apache.avro"; private const string kUaDataTypeIdKey = "uaDataTypeId"; private static readonly JsonSerializerOptions kIndented = new() { WriteIndented = true }; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/Avro/BaseDataSetMessage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas.Avro { using Azure.IIoT.OpcUa.Encoders.Schemas; using Azure.IIoT.OpcUa.Publisher.Models; using Furly; using Furly.Extensions.Messaging; using global::Avro; using System.Collections.Generic; using System.Linq; /// /// Base Dataset message avro schema /// public abstract class BaseDataSetMessage : IEventSchema, IAvroSchema { /// public string Type => ContentMimeType.AvroSchema; /// public string Name => Schema.Fullname; /// public ulong Version { get; } /// string IEventSchema.Schema => Schema.ToString(); /// public string Id { get; } /// public abstract Schema Schema { get; } /// /// The data set schema /// protected abstract BaseDataSetSchema DataSetSchema { get; } /// /// Create based dataset message /// /// protected BaseDataSetMessage(string id) { Id = id; } /// public override string? ToString() { return Schema.ToString(); } /// /// Compile the data set message schema /// /// /// /// /// /// /// protected virtual Schema Compile(string? typeName, DataSetMessageContentFlags dataSetMessageContentFlags, HashSet uniqueNames, NetworkMessageContentFlags networkMessageContentFlags, SchemaOptions options) { if (!networkMessageContentFlags.HasFlag(NetworkMessageContentFlags.DataSetMessageHeader)) { // Not a data set message return DataSetSchema.Schema; } var fields = CollectFields(dataSetMessageContentFlags, networkMessageContentFlags, DataSetSchema.Schema); typeName = GetTypeName(typeName, uniqueNames); var ns = options.Namespace != null ? SchemaUtils.NamespaceUriToNamespace(options.Namespace) : SchemaUtils.PublisherNamespace; return RecordSchema.Create(typeName, fields.ToList(), ns); } /// /// Collect fields of the message schema /// /// /// /// /// protected abstract IEnumerable CollectFields( DataSetMessageContentFlags dataSetMessageContentFlags, NetworkMessageContentFlags networkMessageContentFlags, Schema valueSchema); /// /// Create a type name /// /// /// /// /// protected static string GetTypeName(string? typeName, HashSet? uniqueNames, string? defaultName = null) { // Type name of the message record typeName ??= string.Empty; typeName = SchemaUtils.Escape(typeName) + (defaultName ?? PubSub.BaseDataSetMessage.MessageTypeName); if (uniqueNames != null) { var uniqueName = typeName; for (var index = 1; uniqueNames.Contains(uniqueName); index++) { uniqueName = typeName + index; } uniqueNames.Add(uniqueName); typeName = uniqueName; } return typeName; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/Avro/BaseNetworkMessage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas.Avro { using Azure.IIoT.OpcUa.Encoders.Schemas; using Azure.IIoT.OpcUa.Encoders.PubSub; using Azure.IIoT.OpcUa.Publisher.Models; using Furly; using Furly.Extensions.Messaging; using global::Avro; using System.Collections.Generic; using System.Linq; /// /// Network message avro schema /// public abstract class BaseNetworkMessage : IEventSchema, IAvroSchema { /// public string Type => ContentMimeType.AvroSchema; /// public string Name => Schema.Fullname; /// public ulong Version { get; } /// string IEventSchema.Schema => Schema.ToString(); /// public string Id { get; } /// public abstract Schema Schema { get; } /// public override string? ToString() { return Schema.ToString(); } /// /// Create network message schema /// /// /// protected BaseNetworkMessage(string id, ulong version) { Version = version; Id = id; } /// /// Compile the schema for the data sets /// /// /// /// protected virtual Schema Compile(PublishedNetworkMessageSchemaModel networkMessage, SchemaOptions? options = null) { options ??= new SchemaOptions(); var networkMessageContentFlags = networkMessage.NetworkMessageContentFlags ?? PubSubMessage.DefaultNetworkMessageContentFlags; var dataSetMessages = networkMessage.DataSetMessages; var typeName = networkMessage.TypeName; var MonitoredItemMessage = networkMessageContentFlags .HasFlag(NetworkMessageContentFlags.MonitoredItemMessage); if (MonitoredItemMessage) { networkMessageContentFlags &= ~NetworkMessageContentFlags.NetworkMessageHeader; } var dataSetMessageSchemas = dataSetMessages .Select((dataSet, i) => dataSet != null ? Compile(dataSet, networkMessageContentFlags, options, _uniqueNames) : AvroSchema.CreatePlaceHolder("Empty" + i, SchemaUtils.PublisherNamespace)) .ToList(); if (dataSetMessageSchemas.Count == 0) { return AvroSchema.Null; } Schema? payloadType; if (networkMessageContentFlags.HasFlag(NetworkMessageContentFlags.MonitoredItemMessage)) { return dataSetMessageSchemas .SelectMany(kv => kv is UnionSchema u ? u.Schemas : kv.YieldReturn()) .AsUnion(); } if (dataSetMessageSchemas.Count > 1) { payloadType = dataSetMessageSchemas.AsUnion(); } else { payloadType = dataSetMessageSchemas[0]; } var HasSingleDataSetMessage = networkMessageContentFlags .HasFlag(NetworkMessageContentFlags.SingleDataSetMessage); var HasNetworkMessageHeader = networkMessageContentFlags .HasFlag(NetworkMessageContentFlags.NetworkMessageHeader); if (!HasNetworkMessageHeader && HasSingleDataSetMessage) { // No network message header return payloadType; } payloadType = payloadType.AsArray(); var fields = CollectFields(networkMessageContentFlags, payloadType); var ns = options.Namespace != null ? SchemaUtils.NamespaceUriToNamespace(options.Namespace) : SchemaUtils.PublisherNamespace; return RecordSchema.Create(GetName(typeName), fields.ToList(), ns); } /// /// Collect fields /// /// /// /// protected abstract IEnumerable CollectFields( NetworkMessageContentFlags contentMask, Schema payloadType); /// /// Get schema /// /// /// /// /// /// protected abstract Schema Compile(PublishedDataSetMessageSchemaModel dataSetMessage, NetworkMessageContentFlags networkMessageContentFlags, SchemaOptions options, HashSet uniqueNames); /// /// Get name of the type /// /// /// private string GetName(string? typeName) { // Type name of the message record typeName ??= string.Empty; typeName = SchemaUtils.Escape(typeName) + PubSub.BaseNetworkMessage.MessageTypeName; return MakeUnique(typeName); } /// /// Make unique /// /// /// private string MakeUnique(string name) { var uniqueName = name; for (var index = 1; _uniqueNames.Contains(uniqueName); index++) { uniqueName = name + index; } _uniqueNames.Add(uniqueName); return uniqueName; } private readonly HashSet _uniqueNames = []; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/Avro/IAvroSchema.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas.Avro { using global::Avro; /// /// Avro schema /// public interface IAvroSchema { /// /// The avro schema /// Schema Schema { get; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/Avro/JsonBuiltInSchemas.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas.Avro { using global::Avro; using Opc.Ua; using DataSetFieldContentFlags = Publisher.Models.DataSetFieldContentFlags; using System; using System.Collections.Generic; using System.Linq; /// /// Provides the json encodings of built in types and objects in Avro schema /// internal class JsonBuiltInSchemas : BaseBuiltInSchemas { private Schema EnumerationSchema { get { if (_reversibleEncoding) { // Enumeration values shall be encoded as a JSON number // for the reversible encoding. return PrimitiveType("int"); } // For the non - reversible form, Enumeration values are // encoded as a JSON string with the following format: // _ return PrimitiveType("string"); } } private Schema DiagnosticInfoSchema { get { return RecordSchema.Create(nameof(BuiltInType.DiagnosticInfo), [ new (GetSchemaForBuiltInType(BuiltInType.Int32), "SymbolicId", 0), new (GetSchemaForBuiltInType(BuiltInType.Int32), "NamespaceUri", 1), new (GetSchemaForBuiltInType(BuiltInType.Int32), "Locale", 2), new (GetSchemaForBuiltInType(BuiltInType.Int32), "LocalizedText", 3), new (GetSchemaForBuiltInType(BuiltInType.String), "AdditionalInfo", 4), new (GetSchemaForBuiltInType(BuiltInType.StatusCode), "InnerStatusCode", 5), new (GetSchemaForBuiltInType(BuiltInType.DiagnosticInfo).AsNullable(), "InnerDiagnosticInfo", 6) ], SchemaUtils.NamespaceZeroName, new[] { GetDataTypeId(BuiltInType.DiagnosticInfo) }); } } private Schema VariantSchema { get { if (!_reversibleEncoding) { // For the non-reversible form, Variant values shall be // encoded as a JSON value containing only the value of // the Body field. The Type and Dimensions fields are // dropped. Multi-dimensional arrays are encoded as a // multi-dimensional JSON array as described in 5.4.5. // TODO } var types = AvroSchema.Null.YieldReturn() .Concat(GetPossibleTypes(SchemaRank.Scalar)) .Concat(GetPossibleTypes(SchemaRank.Collection)) .Concat(GetPossibleTypes(SchemaRank.Matrix)) .ToList(); return RecordSchema.Create(nameof(BuiltInType.Variant), [ new (types.AsUnion(), "Value", 0) ], SchemaUtils.NamespaceZeroName, new[] { GetDataTypeId(BuiltInType.Variant) }); IEnumerable GetPossibleTypes(SchemaRank valueRank) { for (var i = 1; i <= 29; i++) { if (i == (int)BuiltInType.DiagnosticInfo) { continue; } if (i == (int)BuiltInType.Variant && valueRank == SchemaRank.Scalar) { continue; // Array of variant is allowed } yield return GetSchemaForBuiltInType((BuiltInType)i, valueRank); } } } } private Schema ExtensionObjectSchema { get { if (!_reversibleEncoding) { // For the non-reversible form, ExtensionObject values // shall be encoded as a JSON value containing only the // value of the Body field. The TypeId and Encoding // fields are dropped. // TODO } var bodyType = AvroSchema.AsUnion( GetSchemaForBuiltInType(BuiltInType.Null), GetSchemaForBuiltInType(BuiltInType.String), GetSchemaForBuiltInType(BuiltInType.XmlElement), GetSchemaForBuiltInType(BuiltInType.ByteString)); var encodingType = EnumSchema.Create("Encoding", new string[] { "Structure", "ByteString", "XmlElement" }); return RecordSchema.Create(nameof(BuiltInType.ExtensionObject), [ new (GetSchemaForBuiltInType(BuiltInType.NodeId), "TypeId", 0), new (encodingType, "Encoding", 1), new (bodyType, "Body", 2) ], SchemaUtils.NamespaceZeroName, new[] { GetDataTypeId(BuiltInType.ExtensionObject) }); } } private Schema StatusCodeSchema { get { if (_reversibleEncoding) { // // StatusCode values shall be encoded as a JSON number for // the reversible encoding. If the StatusCode is Good (0) // it is only encoded if it is an element of a JSON array. // #if !DERIVE_PRIMITIVE return PrimitiveType("int"); #else return DerivedSchema.Create(nameof(BuiltInType.StatusCode), GetSchemaForBuiltInType(BuiltInType.UInt32), SchemaUtils.NamespaceZeroName, new[] { GetDataTypeId(BuiltInType.StatusCode) }); #endif } // For the non - reversible form, StatusCode values // shall be encoded as a JSON object with the fields // defined here. return RecordSchema.Create(nameof(BuiltInType.StatusCode), [ new (GetSchemaForBuiltInType(BuiltInType.UInt32), "Code", 0), new (GetSchemaForBuiltInType(BuiltInType.String), "Symbol", 1) ], SchemaUtils.NamespaceZeroName); } } private Schema QualifiedNameSchema { get { Field field; if (_reversibleEncoding) { // For reversible encoding this field is a JSON number // with the NamespaceIndex. The field is omitted if the // NamespaceIndex is 0. field = new(GetSchemaForBuiltInType(BuiltInType.UInt32), "Uri", 1); } else { // For non-reversible encoding this field is the JSON // string containing the NamespaceUri associated with // the NamespaceIndex unless the NamespaceIndex is 0. // If the NamespaceIndex is 0 the field is omitted. field = new(GetSchemaForBuiltInType(BuiltInType.String), "Uri", 1); } return RecordSchema.Create(nameof(BuiltInType.QualifiedName), [ new (GetSchemaForBuiltInType(BuiltInType.String), "Name", 0), field ], SchemaUtils.NamespaceZeroName, new[] { GetDataTypeId(BuiltInType.QualifiedName) }); } } private Schema LocalizedTextSchema { get { if (_reversibleEncoding) { return RecordSchema.Create(nameof(BuiltInType.LocalizedText), [ new (GetSchemaForBuiltInType(BuiltInType.String), "Locale", 0), new (GetSchemaForBuiltInType(BuiltInType.String), "Text", 1) ], SchemaUtils.NamespaceZeroName, new[] { GetDataTypeId(BuiltInType.LocalizedText) }); } // For the non-reversible form, LocalizedText value shall // be encoded as a JSON string containing the Text component. #if !DERIVE_PRIMITIVE return PrimitiveType("string"); #else return DerivedSchema.Create(nameof(BuiltInType.LocalizedText), GetSchemaForBuiltInType(BuiltInType.String), SchemaUtils.NamespaceZeroName, new[] { GetDataTypeId(BuiltInType.LocalizedText) }); #endif } } private Schema NodeIdSchema { get { var idType = AvroSchema.AsUnion( GetSchemaForBuiltInType(BuiltInType.UInt32), GetSchemaForBuiltInType(BuiltInType.String), GetSchemaForBuiltInType(BuiltInType.Guid), GetSchemaForBuiltInType(BuiltInType.ByteString)); var idTypeType = EnumSchema.Create("IdentifierType", new string[] { "UInt32", "String", "Guid", "ByteString" }, SchemaUtils.NamespaceZeroName); Field field; if (_reversibleEncoding) { // For reversible encoding this field is a JSON number // with the NamespaceIndex. The field is omitted if the // NamespaceIndex is 0. field = new(GetSchemaForBuiltInType(BuiltInType.UInt32), "Namespace", 2); } else { // For non-reversible encoding this field is the JSON // string containing the NamespaceUri associated with // the NamespaceIndex unless the NamespaceIndex is 0. // If the NamespaceIndex is 0 the field is omitted. field = new(GetSchemaForBuiltInType(BuiltInType.String), "Namespace", 2); } return RecordSchema.Create(nameof(BuiltInType.NodeId), [ new (idTypeType, "IdType", 0), new (idType, "Id", 1), field ], SchemaUtils.NamespaceZeroName, new[] { GetDataTypeId(BuiltInType.NodeId) }); } } private Schema ExpandedNodeIdSchema { get { var idType = AvroSchema.AsUnion( GetSchemaForBuiltInType(BuiltInType.UInt32), GetSchemaForBuiltInType(BuiltInType.String), GetSchemaForBuiltInType(BuiltInType.Guid), GetSchemaForBuiltInType(BuiltInType.ByteString)); var idTypeType = EnumSchema.Create("IdentifierType", new string[] { "UInt32", "String", "Guid", "ByteString" }, SchemaUtils.NamespaceZeroName); Field field; if (_reversibleEncoding) { // For reversible encoding this field is a JSON number with // the ServerIndex. The field is omitted if the ServerIndex // is 0. field = new(GetSchemaForBuiltInType(BuiltInType.UInt16), "ServerUri", 3); } else { // For non-reversible encoding this field is the JSON string // containing the ServerUri associated with the ServerIndex // unless the ServerIndex is 0. If the ServerIndex is 0 the // field is omitted. field = new(GetSchemaForBuiltInType(BuiltInType.String), "ServerUri", 3); } return RecordSchema.Create(nameof(BuiltInType.ExpandedNodeId), [ new (idTypeType, "IdType", 0), new (idType, "Id", 1), // For reversible encoding this field is a JSON string // with the NamespaceUri if the NamespaceUri is specified. // Otherwise, it is a JSON number with the NamespaceIndex. // The field is omitted if the NamespaceIndex is 0. // For non-reversible encoding this field is the JSON string // containing the NamespaceUri or the NamespaceUri associated // with the NamespaceIndex unless the NamespaceIndex is 0 // or 1. If the NamespaceIndex is 0 the field is omitted. new(AvroSchema.AsUnion( GetSchemaForBuiltInType(BuiltInType.UInt32), GetSchemaForBuiltInType(BuiltInType.String)), "Namespace", 2), field ], SchemaUtils.NamespaceZeroName, new[] { GetDataTypeId(BuiltInType.ExpandedNodeId) }); } } private Schema DataValueSchema { get { return RecordSchema.Create(nameof(BuiltInType.DataValue), [ new (GetSchemaForBuiltInType(BuiltInType.Variant), "Value", 0), new (GetSchemaForBuiltInType(BuiltInType.StatusCode), "Status", 1), new (GetSchemaForBuiltInType(BuiltInType.DateTime), "SourceTimestamp", 2), new (GetSchemaForBuiltInType(BuiltInType.UInt16), "SourcePicoSeconds", 3), new (GetSchemaForBuiltInType(BuiltInType.DateTime), "ServerTimestamp", 4), new (GetSchemaForBuiltInType(BuiltInType.UInt16), "ServerPicoSeconds", 5) ], SchemaUtils.NamespaceZeroName, new[] { GetDataTypeId(BuiltInType.DataValue) }); } } /// /// Create avro schema for json encoder /// /// /// public JsonBuiltInSchemas(bool reversibleEncoding, bool useUriEncoding) { _reversibleEncoding = reversibleEncoding; _useUriEncoding = useUriEncoding; } /// /// Create encoding schema /// /// public JsonBuiltInSchemas(DataSetFieldContentFlags fieldContentMask) { if ((fieldContentMask & DataSetFieldContentFlags.RawData) != 0) { // // If the DataSetFieldContentMask results in a RawData // representation, the field value is a Variant encoded // using the non-reversible OPC UA JSON Data Encoding // defined in OPC 10000-6 // _useUriEncoding = true; _reversibleEncoding = false; } else if (fieldContentMask == 0) { // // If the DataSetFieldContentMask results in a Variant // representation, the field value is encoded as a Variant // encoded using the reversible OPC UA JSON Data Encoding // defined in OPC 10000-6. // _useUriEncoding = false; _reversibleEncoding = true; } else { // // If the DataSetFieldContentMask results in a DataValue // representation, the field value is a DataValue encoded // using the non-reversible OPC UA JSON Data Encoding or // reversible depending on encoder configuration. // _reversibleEncoding = false; _useUriEncoding = false; } } /// /// Get built in schema. See /// https://reference.opcfoundation.org/Core/Part6/v104/docs/5.1.2#_Ref131507956 /// /// /// /// /// public override Schema GetSchemaForBuiltInType(BuiltInType builtInType, SchemaRank rank = SchemaRank.Scalar) { // Always use byte string for byte arrays if (builtInType == BuiltInType.Byte && rank == SchemaRank.Collection) { builtInType = BuiltInType.ByteString; rank = SchemaRank.Scalar; } if (!_builtIn.TryGetValue(builtInType, out var schema)) { // Before we create the schema add a place // holder here to break any recursion. _builtIn.Add(builtInType, PlaceHolder(builtInType)); schema = Get((int)builtInType); _builtIn[builtInType] = schema; } if (rank != SchemaRank.Scalar) { schema = schema.AsArray(); } return schema; Schema Get(int id) => id switch { 0 => AvroSchema.Null, 1 => PrimitiveType("boolean"), 2 => PrimitiveType("int"), 3 => PrimitiveType("int"), 4 => PrimitiveType("int"), 5 => PrimitiveType("int"), 6 => PrimitiveType("int"), 7 => PrimitiveType("int"), // As per part 6 encoding, long is encoded as string 8 => PrimitiveType("string"), 9 => PrimitiveType("string"), 10 => PrimitiveType("float"), 11 => PrimitiveType("double"), 12 => PrimitiveType("string"), 13 => PrimitiveType("string"), 14 => LogicalType("string", "uuid"), 15 => PrimitiveType("bytes"), 16 => PrimitiveType("string"), 17 => NodeIdSchema, 18 => ExpandedNodeIdSchema, 19 => StatusCodeSchema, 20 => QualifiedNameSchema, 21 => LocalizedTextSchema, 22 => ExtensionObjectSchema, 23 => DataValueSchema, 24 => VariantSchema, 25 => DiagnosticInfoSchema, 26 => PrimitiveType("string"), // Should this be string? As per json encoding, long is string 27 => PrimitiveType("string"), 28 => PrimitiveType("string"), 29 => EnumerationSchema, _ => throw new ArgumentException($"Built in type {id} unknown") }; } /// public override Schema GetSchemaForExtendableType(string name, string ns, string dataTypeId, Schema bodyType) { var encodingType = EnumSchema.Create("Encoding", new string[] { "Structure", "ByteString", "XmlElement" }); return RecordSchema.Create(name + nameof(BuiltInType.ExtensionObject), [ new (GetSchemaForBuiltInType(BuiltInType.NodeId), "TypeId", 0), new (encodingType, "Encoding", 1), new (bodyType, "Body", 2) ], ns, new[] { dataTypeId }); } /// public override Schema GetSchemaForDataSetField(string ns, bool asDataValue, Schema valueSchema, BuiltInType builtInType) { if (asDataValue) { return RecordSchema.Create(valueSchema.Name + nameof(BuiltInType.DataValue), [ new (valueSchema, "Value", 0), new (GetSchemaForBuiltInType(BuiltInType.StatusCode), "Status", 1), new (GetSchemaForBuiltInType(BuiltInType.DateTime), "SourceTimestamp", 2), new (GetSchemaForBuiltInType(BuiltInType.UInt16), "SourcePicoseconds", 3), new (GetSchemaForBuiltInType(BuiltInType.DateTime), "ServerTimestamp", 4), new (GetSchemaForBuiltInType(BuiltInType.UInt16), "ServerPicoseconds", 5) ], ns).AsNullable(); } return valueSchema; } /// public override Schema GetSchemaForRank(Schema schema, SchemaRank rank) { switch (rank) { case SchemaRank.Matrix: // Variant schema return GetSchemaForBuiltInType(BuiltInType.Variant); case SchemaRank.Collection: return schema.AsArray(); default: return schema; } } /// /// Get data typeid /// /// /// private static string GetDataTypeId(BuiltInType builtInType) { return "i_" + (int)builtInType; } /// /// Create logical opc ua derived type /// /// /// /// internal static Schema LogicalType(string type, string logicalType) { return Schema.Parse( $$"""{"type": "{{type}}", "logicalType": "{{logicalType}}"}"""); } /// /// Create primitive opc ua built in type /// /// /// internal static Schema PrimitiveType(string type) { return PrimitiveSchema.NewInstance(type); } /// /// Create a place holder /// /// /// private static AvroSchema.PlaceHolder PlaceHolder(BuiltInType builtInType) { return AvroSchema.CreatePlaceHolder(builtInType.ToString(), SchemaUtils.NamespaceZeroName); } private readonly Dictionary _builtIn = []; private readonly bool _reversibleEncoding; #pragma warning disable IDE0052 // Remove unread private members private readonly bool _useUriEncoding; #pragma warning restore IDE0052 // Remove unread private members } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/Avro/JsonDataSet.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas.Avro { using Azure.IIoT.OpcUa.Encoders; using Azure.IIoT.OpcUa.Publisher.Models; using Furly; using Furly.Extensions.Messaging; using global::Avro; using System.Collections.Generic; using System.Linq; /// /// Extensions to convert metadata into avro schema. Note that this class /// generates a schema that complies with the json representation in /// .WriteDataSet. /// This depends on the network settings and reversible vs. nonreversible /// encoding mode. /// public class JsonDataSet : BaseDataSetSchema, IAvroSchema, IEventSchema { /// public string Type => ContentMimeType.AvroSchema; /// public string Name => Schema.Fullname; /// public ulong Version { get; } /// string IEventSchema.Schema => Schema.ToString(); /// public string Id { get; } /// public override Schema Schema { get; } /// /// Get avro schema for a dataset /// /// /// /// /// /// /// public JsonDataSet(string id, PublishedDataSetMetaDataModel dataSet, DataSetFieldContentFlags? dataSetFieldContentMask = null, SchemaOptions? options = null, HashSet? uniqueNames = null) : base(dataSetFieldContentMask, new JsonBuiltInSchemas( dataSetFieldContentMask ?? default), options) { Id = id; Schema = Compile(dataSet.DataSetMetaData?.Name, dataSet, uniqueNames) ?? AvroSchema.Null; } /// public override string? ToString() { return Schema.ToString(); } /// protected override IEnumerable GetDataSetFieldSchemas(string? name, PublishedDataSetMetaDataModel dataSet, HashSet? uniqueNames) { var singleValue = dataSet.Fields.Count == 1; GetEncodingMode(out var omitFieldName, out var fieldsAreDataValues, singleValue); if (omitFieldName) { var set = new HashSet(); foreach (var fieldMetadata in dataSet.Fields) { if (fieldMetadata?.DataType != null) { set.Add(LookupSchema(fieldMetadata.DataType, SchemaUtils.GetRank(fieldMetadata.ValueRank), fieldMetadata.ArrayDimensions)); } } return set.Select(s => s.AsNullable()); } var ns = _options.Namespace != null ? SchemaUtils.NamespaceUriToNamespace(_options.Namespace) : SchemaUtils.PublisherNamespace; var fields = new List(); var pos = 0; foreach (var fieldMetadata in dataSet.Fields) { // Now collect the fields of the payload pos++; if (fieldMetadata?.DataType != null) { var schema = LookupSchema(fieldMetadata.DataType, SchemaUtils.GetRank(fieldMetadata.ValueRank), fieldMetadata.ArrayDimensions); if (fieldMetadata.Name != null) { // TODO: Add properties to the field type schema = Encoding.GetSchemaForDataSetField(ns, fieldsAreDataValues, schema, (Opc.Ua.BuiltInType)fieldMetadata.BuiltInType); fields.Add(new Field(schema, SchemaUtils.Escape(fieldMetadata.Name), pos)); } } } if (fields.Count == 0) { return []; } // Type name of the message record name ??= dataSet.DataSetMetaData.Name; if (string.IsNullOrEmpty(name)) { // Type name of the message record name = "DataSet"; } else { name = SchemaUtils.Escape(name); } return RecordSchema.Create(MakeUnique(name, uniqueNames), fields).YieldReturn(); } /// protected override Schema CreateStructureSchema(StructureDescriptionModel description, SchemaRank rank, Schema? baseTypeSchema) { // // |---------------|------------|----------------| // | Field Value | Reversible | Non-Reversible | // |---------------|------------|----------------| // | NULL | Omitted | JSON null | // | Default Value | Omitted | Default Value | // |---------------|------------|----------------| // var fields = new List(); var pos = 0; if (baseTypeSchema is RecordSchema b) { foreach (var field in b.Fields) { fields.Add(new Field(field.Schema, field.Name, pos++, field.Aliases, field.Documentation, field.DefaultValue)); // Can we copy type property to the field to show inheritance } } foreach (var field in description.Fields) { var schema = LookupSchema(field.DataType, SchemaUtils.GetRank(field.ValueRank), field.ArrayDimensions); if (field.IsOptional) { schema = schema.AsNullable(); } fields.Add(new Field(schema, SchemaUtils.Escape(field.Name), pos++)); } var (ns1, dt) = SchemaUtils.SplitNodeId(description.DataTypeId, Context, true); var scalar = RecordSchema.Create( SchemaUtils.SplitQualifiedName(description.Name, Context, ns1), fields, ns1, new[] { dt }, customProperties: AvroSchema.Properties(description.DataTypeId)); return Encoding.GetSchemaForRank(scalar, rank); } /// protected override Schema CreateEnumSchema(EnumDescriptionModel description, SchemaRank rank) { var (ns, dt) = SchemaUtils.SplitNodeId(description.DataTypeId, Context, true); var symbols = description.Fields .Select(e => SchemaUtils.Escape(e.Name)) .ToList(); var scalar = EnumSchema.Create( SchemaUtils.SplitQualifiedName(description.Name, Context, ns), symbols, ns, new[] { dt }, customProperties: AvroSchema.Properties(description.DataTypeId), defaultSymbol: symbols[0]); // TODO: Build doc from fields descriptions return Encoding.GetSchemaForRank(scalar, rank); } /// protected override Schema CreateUnionSchema(IReadOnlyList schemas) { return schemas.AsUnion(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/Avro/JsonDataSetMessage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas.Avro { using Azure.IIoT.OpcUa.Encoders.Schemas; using Azure.IIoT.OpcUa.Encoders.PubSub; using Azure.IIoT.OpcUa.Publisher.Models; using global::Avro; using Opc.Ua; using System.Collections.Generic; /// /// Dataset message avro schema /// public sealed class JsonDataSetMessage : BaseDataSetMessage { /// public override Schema Schema { get; } /// protected override BaseDataSetSchema DataSetSchema { get; } /// /// Get avro schema for a writer /// /// /// /// /// /// internal JsonDataSetMessage(PublishedDataSetMessageSchemaModel dataSetMessage, NetworkMessageContentFlags networkMessageContentFlags, SchemaOptions options, HashSet uniqueNames) : base(dataSetMessage.Id) { DataSetSchema = new JsonDataSet(dataSetMessage.Id, dataSetMessage.MetaData, dataSetMessage.DataSetFieldContentFlags, options, uniqueNames); Schema = Compile(dataSetMessage.TypeName, dataSetMessage.DataSetMessageContentFlags ?? PubSubMessage.DefaultDataSetMessageContentFlags, uniqueNames, networkMessageContentFlags, options); } /// protected override IEnumerable CollectFields( DataSetMessageContentFlags dataSetMessageContentFlags, NetworkMessageContentFlags networkMessageContentFlags, Schema valueSchema) { var useCompatibilityMode = networkMessageContentFlags .HasFlag(NetworkMessageContentFlags.UseCompatibilityMode); var encoding = new JsonBuiltInSchemas(true, true); var pos = 0; var fields = new List(); if (dataSetMessageContentFlags.HasFlag(DataSetMessageContentFlags.DataSetWriterId)) { if (!useCompatibilityMode) { fields.Add( new(encoding.GetSchemaForBuiltInType(BuiltInType.UInt16), nameof(DataSetMessageContentFlags.DataSetWriterId), pos++)); } else { // Up to version 2.8 we wrote the string id as id which is not per standard fields.Add( new(encoding.GetSchemaForBuiltInType(BuiltInType.String), nameof(DataSetMessageContentFlags.DataSetWriterId), pos++)); } } if (dataSetMessageContentFlags.HasFlag(DataSetMessageContentFlags.SequenceNumber)) { fields.Add( new(encoding.GetSchemaForBuiltInType(BuiltInType.UInt32), nameof(DataSetMessageContentFlags.SequenceNumber), pos++)); } if (dataSetMessageContentFlags.HasFlag(DataSetMessageContentFlags.MetaDataVersion)) { var version = RecordSchema.Create(nameof(ConfigurationVersionDataType), [ new(encoding.GetSchemaForBuiltInType(BuiltInType.UInt32), "MajorVersion", 0), new(encoding.GetSchemaForBuiltInType(BuiltInType.UInt32), "MinorVersion", 1) ], SchemaUtils.NamespaceZeroName, new[] { "i_" + DataTypes.ConfigurationVersionDataType }); fields.Add(new(version, nameof(DataSetMessageContentFlags.MetaDataVersion), pos++)); } if (dataSetMessageContentFlags.HasFlag(DataSetMessageContentFlags.Timestamp)) { fields.Add(new(encoding.GetSchemaForBuiltInType(BuiltInType.DateTime), nameof(DataSetMessageContentFlags.Timestamp), pos++)); } if (dataSetMessageContentFlags.HasFlag(DataSetMessageContentFlags.Status)) { if (!useCompatibilityMode) { fields.Add(new(encoding.GetSchemaForBuiltInType(BuiltInType.StatusCode), nameof(DataSetMessageContentFlags.Status), pos++)); } else { // Up to version 2.8 we wrote the full status code fields.Add(new(new JsonBuiltInSchemas(false, false) .GetSchemaForBuiltInType(BuiltInType.StatusCode), nameof(DataSetMessageContentFlags.Status), pos++)); } } if (dataSetMessageContentFlags.HasFlag(DataSetMessageContentFlags.MessageType)) { fields.Add( new(encoding.GetSchemaForBuiltInType(BuiltInType.String), nameof(DataSetMessageContentFlags.MessageType), pos++)); } if (!useCompatibilityMode && dataSetMessageContentFlags.HasFlag(DataSetMessageContentFlags.DataSetWriterName)) { fields.Add( new(encoding.GetSchemaForBuiltInType(BuiltInType.String), nameof(DataSetMessageContentFlags.DataSetWriterName), pos++)); } fields.Add(new(valueSchema, nameof(PubSub.JsonDataSetMessage.Payload), pos++)); return fields; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/Avro/JsonNetworkMessage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas.Avro { using Azure.IIoT.OpcUa.Encoders.Schemas; using Azure.IIoT.OpcUa.Publisher.Models; using global::Avro; using Opc.Ua; using System.Collections.Generic; /// /// Json Network message avro schema /// public sealed class JsonNetworkMessage : BaseNetworkMessage { /// public override Schema Schema { get; } /// /// Get avro schema for a network message /// /// /// /// /// public JsonNetworkMessage(PublishedNetworkMessageSchemaModel networkMessage, SchemaOptions? options = null, bool useCompatibilityMode = false, bool useArrayEnvelope = false) : base(networkMessage.Id, networkMessage.Version) { networkMessage = SetAdditionalFlags(networkMessage, useCompatibilityMode, useArrayEnvelope); Schema = Compile(networkMessage, options); } /// protected override Schema Compile(PublishedDataSetMessageSchemaModel dataSetMessage, NetworkMessageContentFlags networkMessageContentFlags, SchemaOptions options, HashSet uniqueNames) { if (networkMessageContentFlags.HasFlag(NetworkMessageContentFlags.MonitoredItemMessage)) { return new MonitoredItemMessage(dataSetMessage, networkMessageContentFlags, options, uniqueNames).Schema; } return new JsonDataSetMessage(dataSetMessage, networkMessageContentFlags, options, uniqueNames).Schema; } /// protected override Schema Compile(PublishedNetworkMessageSchemaModel networkMessage, SchemaOptions? options) { var messageSchema = base.Compile(networkMessage, options); if (networkMessage.NetworkMessageContentFlags? .HasFlag(NetworkMessageContentFlags.UseArrayEnvelope) ?? false) { // set array as root return messageSchema.AsArray(true); } return messageSchema; } /// protected override IEnumerable CollectFields( NetworkMessageContentFlags contentMask, Schema payloadType) { var encoding = new JsonBuiltInSchemas(true, false); var pos = 0; var fields = new List { new(encoding.GetSchemaForBuiltInType(BuiltInType.String), nameof(PubSub.JsonNetworkMessage.MessageId), pos++), new(encoding.GetSchemaForBuiltInType(BuiltInType.String), nameof(PubSub.JsonNetworkMessage.MessageType), pos++) }; if (contentMask.HasFlag(NetworkMessageContentFlags.PublisherId)) { fields.Add(new(encoding.GetSchemaForBuiltInType(BuiltInType.String), nameof(PubSub.JsonNetworkMessage.PublisherId), pos++)); } if (contentMask.HasFlag(NetworkMessageContentFlags.DataSetClassId)) { fields.Add(new(encoding.GetSchemaForBuiltInType(BuiltInType.Guid), nameof(PubSub.JsonNetworkMessage.DataSetClassId), pos++)); } fields.Add(new(encoding.GetSchemaForBuiltInType(BuiltInType.String), nameof(PubSub.JsonNetworkMessage.DataSetWriterGroup), pos++)); // Now write messages - this is either one of or array of one of fields.Add(new(payloadType, nameof(PubSub.JsonNetworkMessage.Messages), pos++)); return fields; } /// /// Set additional flags /// /// /// /// /// private static PublishedNetworkMessageSchemaModel SetAdditionalFlags( PublishedNetworkMessageSchemaModel networkMessage, bool useCompatibilityMode, bool useArrayEnvelope) { var networkMessageContentFlags = networkMessage.NetworkMessageContentFlags; if (useCompatibilityMode) { networkMessageContentFlags |= NetworkMessageContentFlags.UseCompatibilityMode; } if (useArrayEnvelope) { networkMessageContentFlags |= NetworkMessageContentFlags.UseArrayEnvelope; } return networkMessage with { NetworkMessageContentFlags = networkMessageContentFlags }; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/Avro/MonitoredItemMessage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas.Avro { using Azure.IIoT.OpcUa.Encoders.Schemas; using Azure.IIoT.OpcUa.Encoders.PubSub; using Azure.IIoT.OpcUa.Publisher.Models; using global::Avro; using System.Collections.Generic; using System.Linq; /// /// Monitored item message avro schema /// public sealed class MonitoredItemMessage : BaseDataSetMessage { /// public override Schema Schema { get; } /// protected override BaseDataSetSchema DataSetSchema { get; } /// /// Get avro schema for a monitored item message /// /// /// /// /// /// internal MonitoredItemMessage(PublishedDataSetMessageSchemaModel dataSetMessage, NetworkMessageContentFlags networkMessageContentFlags, SchemaOptions options, HashSet uniqueNames) : base(dataSetMessage.Id) { DataSetSchema = new JsonDataSet(dataSetMessage.Id, dataSetMessage.MetaData, dataSetMessage.DataSetFieldContentFlags, options, uniqueNames); _dataSetFieldContentMask = dataSetMessage.DataSetFieldContentFlags ?? PubSubMessage.DefaultDataSetFieldContentFlags; Schema = Compile(dataSetMessage.TypeName, dataSetMessage.DataSetMessageContentFlags ?? PubSubMessage.DefaultDataSetMessageContentFlags, uniqueNames, networkMessageContentFlags, options); } /// protected override Schema Compile(string? typeName, DataSetMessageContentFlags dataSetMessageContentFlags, HashSet uniqueNames, NetworkMessageContentFlags networkMessageContentFlags, SchemaOptions options) { if (DataSetSchema.Schema is not RecordSchema dataSetSchema) { return AvroSchema.Null; } // TODO: Events are encoded as dictionary, not single values // For each value in the data set, compile a message from it var items = new List(); foreach (var property in dataSetSchema.Fields) { var fields = CollectFields(dataSetMessageContentFlags, networkMessageContentFlags, property.Schema); var name = GetTypeName(typeName, uniqueNames, nameof(PubSub.MonitoredItemMessage)); var ns = options.Namespace != null ? SchemaUtils.NamespaceUriToNamespace(options.Namespace) : SchemaUtils.PublisherNamespace; items.Add(RecordSchema.Create(name, fields.ToList(), ns)); } return items.AsUnion(); } /// protected override IEnumerable CollectFields( DataSetMessageContentFlags dataSetMessageContentFlags, NetworkMessageContentFlags networkMessageContentFlags, Schema valueSchema) { var encoding = new JsonBuiltInSchemas(false, true); var pos = 0; var fields = new List(); if (_dataSetFieldContentMask.HasFlag(DataSetFieldContentFlags.NodeId)) { fields.Add( new(encoding.GetSchemaForBuiltInType(Opc.Ua.BuiltInType.String).AsNullable(), nameof(PubSub.MonitoredItemMessage.NodeId), pos++)); } if (_dataSetFieldContentMask.HasFlag(DataSetFieldContentFlags.EndpointUrl)) { fields.Add( new(encoding.GetSchemaForBuiltInType(Opc.Ua.BuiltInType.String).AsNullable(), nameof(PubSub.MonitoredItemMessage.EndpointUrl), pos++)); } if (_dataSetFieldContentMask.HasFlag(DataSetFieldContentFlags.ApplicationUri)) { fields.Add( new(encoding.GetSchemaForBuiltInType(Opc.Ua.BuiltInType.String).AsNullable(), nameof(PubSub.MonitoredItemMessage.ApplicationUri), pos++)); } if (_dataSetFieldContentMask.HasFlag(DataSetFieldContentFlags.DisplayName)) { fields.Add( new(encoding.GetSchemaForBuiltInType(Opc.Ua.BuiltInType.String).AsNullable(), nameof(PubSub.MonitoredItemMessage.DisplayName), pos++)); } if (dataSetMessageContentFlags.HasFlag(DataSetMessageContentFlags.Timestamp)) { fields.Add( new(encoding.GetSchemaForBuiltInType(Opc.Ua.BuiltInType.DateTime).AsNullable(), nameof(PubSub.MonitoredItemMessage.Timestamp), pos++)); } if (dataSetMessageContentFlags.HasFlag(DataSetMessageContentFlags.Status)) { fields.Add( new(encoding.GetSchemaForBuiltInType(Opc.Ua.BuiltInType.String).AsNullable(), nameof(PubSub.MonitoredItemMessage.Status), pos++)); } fields.Add(new(valueSchema, nameof(PubSub.MonitoredItemMessage.Value), pos++)); if (dataSetMessageContentFlags.HasFlag(DataSetMessageContentFlags.SequenceNumber)) { fields.Add( new(encoding.GetSchemaForBuiltInType(Opc.Ua.BuiltInType.UInt32).AsNullable(), nameof(PubSub.MonitoredItemMessage.SequenceNumber), pos++)); } if (_dataSetFieldContentMask.HasFlag(DataSetFieldContentFlags.ExtensionFields)) { fields.Add( new(MapSchema.CreateMap( encoding.GetSchemaForBuiltInType(Opc.Ua.BuiltInType.Variant)).AsNullable(), nameof(PubSub.MonitoredItemMessage.ExtensionFields), pos++)); } return fields; } private readonly DataSetFieldContentFlags _dataSetFieldContentMask; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/BaseBuiltInSchemas.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas { using Opc.Ua; /// /// Represents schemas for the encoding of the built in types /// as per part 6 of the OPC UA specification. /// /// public abstract class BaseBuiltInSchemas { /// /// Get schema for built in type /// /// /// /// public abstract T GetSchemaForBuiltInType( BuiltInType builtInType, SchemaRank rank = SchemaRank.Scalar); /// /// Get a schema for a data value field with the /// specified value schema. The union field in the /// value variant will then be made a reserved /// identifer /// /// /// /// /// /// public abstract T GetSchemaForDataSetField(string ns, bool asDataValue, T valueSchema, BuiltInType builtInType); /// /// Get the schema definition for a type that can /// be any type in a hierarchy extension object /// schema /// /// /// /// /// /// public abstract T GetSchemaForExtendableType( string name, string ns, string dataTypeId, T bodyType); /// /// Get schema for specified value rank /// schema /// /// /// /// public abstract T GetSchemaForRank(T schema, SchemaRank rank); } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/BaseDataSetSchema.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas { using Azure.IIoT.OpcUa.Encoders; using Azure.IIoT.OpcUa.Publisher.Models; using Opc.Ua; using Opc.Ua.Extensions; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; /// /// Extensions to convert metadata into avro schema. Note that this class /// generates a schema that complies with the json representation in /// .WriteDataSet. /// This depends on the network settings and reversible vs. nonreversible /// encoding mode. /// /// public abstract class BaseDataSetSchema where T : class { /// /// The schema of the data set /// public abstract T Schema { get; } /// /// Encoding schema for the data set /// protected BaseBuiltInSchemas Encoding { get; } /// /// Message context /// internal ServiceMessageContext Context { get; } /// /// Get avro schema for a dataset /// /// /// /// /// protected BaseDataSetSchema( DataSetFieldContentFlags? dataSetFieldContentMask, BaseBuiltInSchemas encoding, SchemaOptions? options = null) { _dataSetFieldContentMask = dataSetFieldContentMask ?? default; _options = options ?? new SchemaOptions(); Context = new ServiceMessageContext { NamespaceUris = new NamespaceTable() }; Encoding = encoding; } /// /// Compile /// /// /// /// /// protected T? Compile(string? name, PublishedDataSetMetaDataModel dataSet, HashSet? uniqueNames) { // Collect types CollectTypes(dataSet); var schemas = GetDataSetFieldSchemas(name, dataSet, uniqueNames).ToList(); if (schemas.Count == 0) { return default; } if (schemas.Count != 1) { return CreateUnionSchema(schemas); } return schemas[0]; } /// /// Create data set schemas /// /// /// /// /// protected abstract IEnumerable GetDataSetFieldSchemas(string? name, PublishedDataSetMetaDataModel dataSet, HashSet? uniqueNames); /// /// Create record schema for the structure /// /// /// /// /// protected abstract T CreateStructureSchema( StructureDescriptionModel description, SchemaRank rank, T? baseTypeSchema = default); /// /// Create enum schema for the enum description /// /// /// /// protected abstract T CreateEnumSchema(EnumDescriptionModel description, SchemaRank rank); /// /// Create union schema /// /// /// protected abstract T CreateUnionSchema(IReadOnlyList schemas); /// /// Collect types from data set /// /// private void CollectTypes(PublishedDataSetMetaDataModel dataSet) { if (dataSet.StructureDataTypes != null) { foreach (var t in dataSet.StructureDataTypes) { if (!_types.ContainsKey(t.DataTypeId)) { _types.Add(t.DataTypeId, new StructureType(t)); } } } if (dataSet.SimpleDataTypes != null) { foreach (var t in dataSet.SimpleDataTypes) { if (!_types.ContainsKey(t.DataTypeId)) { _types.Add(t.DataTypeId, new SimpleType(t)); } } } if (dataSet.EnumDataTypes != null) { foreach (var t in dataSet.EnumDataTypes) { if (!_types.ContainsKey(t.DataTypeId)) { _types.Add(t.DataTypeId, new EnumType(t)); } } } } /// /// Lookup the schema for the data type and make the type an array if /// it has such value rank. Make the resulting schema nullable. /// Return the name of the root schema. /// /// /// /// /// /// protected T LookupSchema(string dataType, SchemaRank valueRank = SchemaRank.Scalar, IReadOnlyList? arrayDimensions = null) { T? schema = null; if (arrayDimensions?.Count > 1) { valueRank = SchemaRank.Matrix; } if (_types.TryGetValue(dataType, out var description)) { schema = description.GetSchema(this, valueRank); } schema ??= GetBuiltInDataTypeSchema(dataType, valueRank); return schema ?? throw new ArgumentException($"No Schema found for {dataType}"); T? GetBuiltInDataTypeSchema(string dataType, SchemaRank valueRank) { var nodeId = dataType.ToExpandedNodeId(Context); if (nodeId.IdType == IdType.Numeric) { var id = nodeId.Identifier as uint?; if (id >= 0 && id <= 29) { return Encoding.GetSchemaForBuiltInType((BuiltInType)id, valueRank); } } return null; } } /// /// Create a type name /// /// /// /// protected static string MakeUnique(string typeName, HashSet? uniqueNames) { if (uniqueNames != null) { var uniqueName = typeName; for (var index = 1; uniqueNames.Contains(uniqueName); index++) { uniqueName = typeName + index; } uniqueNames.Add(uniqueName); typeName = uniqueName; } return typeName; } /// /// Avro type /// private abstract record class TypedDescription { /// /// Get schema /// /// /// /// public abstract T? GetSchema(BaseDataSetSchema schema, SchemaRank rank); } /// /// Simple type /// /// private record class SimpleType(SimpleTypeDescriptionModel Description) : TypedDescription { /// public override T? GetSchema(BaseDataSetSchema schemas, SchemaRank rank) { if (Description.DataTypeId == "i=" + Description.BuiltInType) { // Emit the built in type definition here instead Debug.Assert(Description.BuiltInType.HasValue); return schemas.Encoding.GetSchemaForBuiltInType( (BuiltInType)Description.BuiltInType.Value, rank); } // Derive from base type or built in type if (Description.BaseDataType != null) { // Derive from base type or built in type return schemas.LookupSchema(Description.BaseDataType, rank); } // Derive from base type or built in type return schemas.Encoding.GetSchemaForBuiltInType((BuiltInType) (Description.BuiltInType ?? (byte?)BuiltInType.String), rank); } } /// /// Record /// /// private record class StructureType(StructureDescriptionModel Description) : TypedDescription { /// public override T? GetSchema(BaseDataSetSchema schemas, SchemaRank rank) { if (_cache[(int)rank] != null) { return _cache[(int)rank]; } // Get super types T? baseSchema = default; if (Description.BaseDataType != null && schemas._types.TryGetValue(Description.BaseDataType, out var def) && def is StructureType baseDescription) { baseSchema = baseDescription.GetSchema(schemas, rank); } _cache[(int)rank] = schemas.CreateStructureSchema(Description, rank, baseSchema); return _cache[(int)rank]; } private readonly T?[] _cache = new T?[3]; } /// /// Enum type /// /// private record class EnumType(EnumDescriptionModel Description) : TypedDescription { /// public override T? GetSchema(BaseDataSetSchema schemas, SchemaRank rank) { if (_cache[(int)rank] != null) { return _cache[(int)rank]; } if (Description.IsOptionSet) { // Flags // ... } _cache[(int)rank] = schemas.CreateEnumSchema(Description, rank); return _cache[(int)rank]; } private readonly T?[] _cache = new T?[3]; } /// /// Determine field encoding /// /// /// /// protected void GetEncodingMode(out bool writeSingleValue, out bool dataValueRepresentation, bool isSingleFieldDataSet) { writeSingleValue = isSingleFieldDataSet && _dataSetFieldContentMask .HasFlag(Publisher.Models.DataSetFieldContentFlags.SingleFieldDegradeToValue); dataValueRepresentation = !_dataSetFieldContentMask .HasFlag(Publisher.Models.DataSetFieldContentFlags.RawData) && _dataSetFieldContentMask != 0; } /// Schema options protected readonly SchemaOptions _options; private readonly DataSetFieldContentFlags _dataSetFieldContentMask; private readonly Dictionary _types = []; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/Json/JsonBuiltInSchemas.cs ================================================ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas.Json { using Opc.Ua; using DataSetFieldContentFlags = Publisher.Models.DataSetFieldContentFlags; using System; using System.Collections.Generic; /// /// Provides the json encodings of built in types and objects in Avro schema /// internal class JsonBuiltInSchemas : BaseBuiltInSchemas { /// /// Schema definitions /// public Dictionary Schemas { get; } private JsonSchema EnumerationSchema { get { if (_reversibleEncoding) { // Enumeration values shall be encoded as a JSON number // for the reversible encoding. return Simple((int)BuiltInType.Enumeration, SchemaType.Integer, "int32"); } // For the non - reversible form, Enumeration values are // encoded as a JSON string with the following format: // _ return Simple((int)BuiltInType.Enumeration, SchemaType.String); } } private JsonSchema DiagnosticInfoSchema { get { return new JsonSchema { Title = GetTitle(BuiltInType.DiagnosticInfo), Id = GetId(BuiltInType.DiagnosticInfo), Type = SchemaType.Object, Properties = new Dictionary { ["SymbolicId"] = GetSchemaForBuiltInType(BuiltInType.Int32), ["NamespaceUri"] = GetSchemaForBuiltInType(BuiltInType.Int32), ["Locale"] = GetSchemaForBuiltInType(BuiltInType.Int32), ["LocalizedText"] = GetSchemaForBuiltInType(BuiltInType.Int32), ["AdditionalInfo"] = GetSchemaForBuiltInType(BuiltInType.String), ["InnerStatusCode"] = GetSchemaForBuiltInType(BuiltInType.StatusCode), ["InnerDiagnosticInfo"] = new JsonSchema { // Self reference Reference = UriOrFragment.Self } }, AdditionalProperties = new JsonSchema { Allowed = false } }; } } private JsonSchema VariantSchema { get { var any = new JsonSchema { Title = "Any", Types = new[] { SchemaType.Number, SchemaType.Null, SchemaType.Object, SchemaType.Array, SchemaType.String, SchemaType.Integer, SchemaType.Boolean } }; if (!_reversibleEncoding) { // For the non-reversible form, Variant values shall be // encoded as a JSON value containing only the value of // the Body field. The Type and Dimensions fields are // dropped. Multi-dimensional arrays are encoded as a // multi-dimensional JSON array as described in 5.4.5. return any; } return new JsonSchema { Id = GetId(BuiltInType.Variant), Type = SchemaType.Object, Title = GetTitle(BuiltInType.Variant), Properties = new Dictionary { ["Type"] = GetSchemaForBuiltInType(BuiltInType.Byte), ["Body"] = any, ["Dimensions"] = GetSchemaForBuiltInType(BuiltInType.UInt32, SchemaRank.Collection) }, AdditionalProperties = new JsonSchema { Allowed = false } }; } } private JsonSchema ExtensionObjectSchema { get { if (!_reversibleEncoding) { // For the non-reversible form, ExtensionObject values // shall be encoded as a JSON value containing only the // value of the Body field. The TypeId and Encoding // fields are dropped. return new JsonSchema { Types = new[] { SchemaType.Object } }; } return new JsonSchema { Id = GetId(BuiltInType.ExtensionObject), Type = SchemaType.Object, Title = GetTitle(BuiltInType.ExtensionObject), Properties = new Dictionary { ["TypeId"] = GetSchemaForBuiltInType(BuiltInType.NodeId), ["Encoding"] = GetSchemaForBuiltInType(BuiltInType.Byte), ["Body"] = new JsonSchema { Types = new[] { SchemaType.Object } } }, AdditionalProperties = new JsonSchema { Allowed = false } }; } } private JsonSchema StatusCodeSchema { get { if (_reversibleEncoding) { // // StatusCode values shall be encoded as a JSON number for // the reversible encoding. If the StatusCode is Good (0) // it is only encoded if it is an element of a JSON array. // return Simple((int)BuiltInType.StatusCode, SchemaType.Integer, "uint32"); } // For the non - reversible form, StatusCode values // shall be encoded as a JSON object with the fields // defined here. return new JsonSchema { Id = GetId(BuiltInType.StatusCode), Type = SchemaType.Object, Title = GetTitle(BuiltInType.StatusCode), Properties = new Dictionary { ["Code"] = GetSchemaForBuiltInType(BuiltInType.UInt32), ["Symbol"] = GetSchemaForBuiltInType(BuiltInType.String) }, AdditionalProperties = new JsonSchema { Allowed = false } }; } } private JsonSchema QualifiedNameSchema { get { if (_encodeNamespacedValuesAsUri) { return Simple((int)BuiltInType.QualifiedName, SchemaType.String, "opcuaQualifiedName"); } // For non-reversible encoding this field is the JSON // string containing the NamespaceUri associated with // the NamespaceIndex unless the NamespaceIndex is 0. // If the NamespaceIndex is 0 the field is omitted. return new JsonSchema { Title = GetTitle(BuiltInType.QualifiedName), Id = GetId(BuiltInType.QualifiedName), Properties = new Dictionary { ["Name"] = GetSchemaForBuiltInType(BuiltInType.String), ["Uri"] = GetSchemaForBuiltInType( _reversibleEncoding ? BuiltInType.UInt32 : BuiltInType.String) }, Required = new[] { "Name" }, AdditionalProperties = new JsonSchema { Allowed = false } }; } } private JsonSchema LocalizedTextSchema { get { if (!_reversibleEncoding) { // For the non-reversible form, LocalizedText value shall // be encoded as a JSON string containing the Text component. return Simple((int)BuiltInType.LocalizedText, SchemaType.String); } return new JsonSchema { Title = GetTitle(BuiltInType.LocalizedText), Type = SchemaType.Object, Id = GetId(BuiltInType.LocalizedText), Properties = new Dictionary { ["Locale"] = new JsonSchema { Title = GetTitle(BuiltInType.String), Type = SchemaType.String, Format = "rfc3066" }, ["Text"] = GetSchemaForBuiltInType(BuiltInType.String) }, AdditionalProperties = new JsonSchema { Allowed = false } }; } } private JsonSchema NodeIdSchema { get { if (_encodeNamespacedValuesAsUri) { return Simple((int)BuiltInType.NodeId, SchemaType.String, "opcuaNodeId"); } return new JsonSchema { Title = GetTitle(BuiltInType.NodeId), Type = SchemaType.Object, Id = GetId(BuiltInType.NodeId), Properties = new Dictionary { ["IdentifierType"] = GetSchemaForBuiltInType(BuiltInType.Byte), ["Id"] = new[] { GetSchemaForBuiltInType(BuiltInType.UInt32), GetSchemaForBuiltInType(BuiltInType.ByteString), GetSchemaForBuiltInType(BuiltInType.Guid), GetSchemaForBuiltInType(BuiltInType.String) } .AsUnion(Schemas, "NodeIdentifer"), // // For reversible encoding this field is a JSON number // with the NamespaceIndex. The field is omitted if the // NamespaceIndex is 0. // // For non-reversible encoding this field is the JSON // string containing the NamespaceUri associated with // the NamespaceIndex unless the NamespaceIndex is 0. // If the NamespaceIndex is 0 the field is omitted. // ["Namespace"] = GetSchemaForBuiltInType( _reversibleEncoding ? BuiltInType.UInt32 : BuiltInType.String) }, Required = new[] { "IdentifierType" }, AdditionalProperties = new JsonSchema { Allowed = false } }; } } private JsonSchema ExpandedNodeIdSchema { get { if (_encodeNamespacedValuesAsUri) { return Simple((int)BuiltInType.ExpandedNodeId, SchemaType.String, "opcuaExpandedNodeId"); } return new JsonSchema { Title = GetTitle(BuiltInType.ExpandedNodeId), Type = SchemaType.Object, Id = GetId(BuiltInType.ExpandedNodeId), Properties = new Dictionary { ["IdentifierType"] = GetSchemaForBuiltInType(BuiltInType.Byte), ["Id"] = new[] { GetSchemaForBuiltInType(BuiltInType.UInt32), GetSchemaForBuiltInType(BuiltInType.ByteString), GetSchemaForBuiltInType(BuiltInType.Guid), GetSchemaForBuiltInType(BuiltInType.String) } .AsUnion(Schemas, "NodeIdentifer"), // // For reversible encoding this field is a JSON number // with the NamespaceIndex. The field is omitted if the // NamespaceIndex is 0. // // For non-reversible encoding this field is the JSON // string containing the NamespaceUri associated with // the NamespaceIndex unless the NamespaceIndex is 0. // If the NamespaceIndex is 0 the field is omitted. // ["Namespace"] = GetSchemaForBuiltInType( _reversibleEncoding ? BuiltInType.UInt32 : BuiltInType.String), // // For reversible encoding this field is a JSON string // with the NamespaceUri if the NamespaceUri is specified. // Otherwise, it is a JSON number with the NamespaceIndex. // The field is omitted if the NamespaceIndex is 0. // // For non-reversible encoding this field is the JSON string // containing the NamespaceUri or the NamespaceUri associated // with the NamespaceIndex unless the NamespaceIndex is 0 // or 1. If the NamespaceIndex is 0 the field is omitted. // ["ServerUri"] = GetSchemaForBuiltInType( _reversibleEncoding ? BuiltInType.UInt16 : BuiltInType.String) }, Required = new[] { "IdentifierType" }, AdditionalProperties = new JsonSchema { Allowed = false } }; } } private JsonSchema DataValueSchema { get { return new JsonSchema { Title = GetTitle(BuiltInType.DataValue), Type = SchemaType.Object, Id = GetId(BuiltInType.DataValue), Properties = new Dictionary { ["Value"] = GetSchemaForBuiltInType(BuiltInType.Variant), ["Status"] = GetSchemaForBuiltInType(BuiltInType.StatusCode), ["SourceTimestamp"] = GetSchemaForBuiltInType(BuiltInType.DateTime), ["SourcePicoSeconds"] = GetSchemaForBuiltInType(BuiltInType.UInt16), ["ServerTimestamp"] = GetSchemaForBuiltInType(BuiltInType.DateTime), ["ServerPicoSeconds"] = GetSchemaForBuiltInType(BuiltInType.UInt16) }, AdditionalProperties = new JsonSchema { Allowed = false } }; } } /// /// Create avro schema for json encoder /// /// /// /// public JsonBuiltInSchemas(bool reversibleEncoding, bool useUriEncoding, Dictionary? definitions) { Schemas = definitions ?? []; _reversibleEncoding = reversibleEncoding; _encodeNamespacedValuesAsUri = useUriEncoding; } /// /// Create encoding schema /// /// /// public JsonBuiltInSchemas(DataSetFieldContentFlags fieldContentMask, Dictionary? definitions = null) { Schemas = definitions ?? []; _encodeNamespacedValuesAsUri = true; if ((fieldContentMask & DataSetFieldContentFlags.RawData) != 0) { // // If the DataSetFieldContentMask results in a RawData // representation, the field value is a Variant encoded // using the non-reversible OPC UA JSON Data Encoding // defined in OPC 10000-6 // _reversibleEncoding = false; } else if (fieldContentMask == 0) { // // If the DataSetFieldContentMask results in a Variant // representation, the field value is encoded as a Variant // encoded using the reversible OPC UA JSON Data Encoding // defined in OPC 10000-6. // _reversibleEncoding = true; } else { // // If the DataSetFieldContentMask results in a DataValue // representation, the field value is a DataValue encoded // using the non-reversible OPC UA JSON Data Encoding or // reversible depending on encoder configuration. // _reversibleEncoding = false; } } /// /// Get built in schema. See /// https://reference.opcfoundation.org/Core/Part6/v104/docs/5.1.2#_Ref131507956 /// /// /// /// /// public override JsonSchema GetSchemaForBuiltInType(BuiltInType builtInType, SchemaRank rank = SchemaRank.Scalar) { if (rank == SchemaRank.Matrix) { return GetSchemaForBuiltInType(BuiltInType.Variant); } // Always use byte string for byte arrays if (builtInType == BuiltInType.Byte && rank == SchemaRank.Collection) { builtInType = BuiltInType.ByteString; rank = SchemaRank.Scalar; } var typeDefinitionName = GetDefinitionName(builtInType); if (!Schemas.TryGetValue(typeDefinitionName, out var schema)) { schema = CreateSchemaForBuiltInType((int)builtInType); Schemas.Add(typeDefinitionName, schema); } if (schema.Id != null) { schema = Reference(builtInType); } if (rank != SchemaRank.Scalar) { return new JsonSchema { Type = SchemaType.Array, Items = new[] { schema } }; } return schema; JsonSchema CreateSchemaForBuiltInType(int id) => id switch { 1 => Simple(id, SchemaType.Boolean), 2 => Simple(id, SchemaType.Integer, "int8", Limit.From(sbyte.MinValue), Limit.From(sbyte.MaxValue), Const.From(0)), 3 => Simple(id, SchemaType.Integer, "byte", Limit.From(byte.MinValue), Limit.From(byte.MaxValue), Const.From(0)), 4 => Simple(id, SchemaType.Integer, "int16", Limit.From(short.MinValue), Limit.From(short.MaxValue), Const.From(0)), 5 => Simple(id, SchemaType.Integer, "uint16", Limit.From(ushort.MinValue), Limit.From(ushort.MaxValue), Const.From(0)), 6 => Simple(id, SchemaType.Integer, "int32", Limit.From(int.MinValue), Limit.From(int.MaxValue), Const.From(0)), 7 => Simple(id, SchemaType.Integer, "uint32", Limit.From(uint.MinValue), Limit.From(uint.MaxValue), Const.From(0)), // As per part 6 encoding, long is encoded as string 8 => Simple(id, SchemaType.String, "int64"), 9 => Simple(id, SchemaType.String, "uint64"), 10 => Simple(id, SchemaType.Number, "float", Limit.From(float.MinValue), Limit.From(float.MaxValue), Const.From(0f)), 11 => Simple(id, SchemaType.Number, "double", Limit.From(double.MinValue), Limit.From(double.MaxValue), Const.From(0d)), 12 => Simple(id, SchemaType.String), 13 => Simple(id, SchemaType.String, "date-time"), 14 => Simple(id, SchemaType.String, "uuid"), 15 => Simple(id, SchemaType.String, "byte"), 16 => Simple(id, SchemaType.String, "xmlelement"), 17 => NodeIdSchema, 18 => ExpandedNodeIdSchema, 19 => StatusCodeSchema, 20 => QualifiedNameSchema, 21 => LocalizedTextSchema, 22 => ExtensionObjectSchema, 23 => DataValueSchema, 24 => VariantSchema, 25 => DiagnosticInfoSchema, 26 => Simple(id, SchemaType.Number), // Should this be string? As per json encoding, long is string 27 => Simple(id, SchemaType.Integer), 28 => Simple(id, SchemaType.Integer, "unsigned", Limit.From(0)), 29 => EnumerationSchema, _ => throw new ArgumentException($"Built in type {id} unknown") }; } /// public override JsonSchema GetSchemaForExtendableType(string name, string ns, string dataTypeId, JsonSchema bodyType) { return GetSchemaForBuiltInType(BuiltInType.ExtensionObject); } /// public override JsonSchema GetSchemaForDataSetField(string ns, bool asDataValue, JsonSchema valueSchema, BuiltInType builtInType) { var fieldSchema = valueSchema.Resolve(Schemas); var isArray = fieldSchema.Type == SchemaType.Array && fieldSchema.Items?.Count == 1; if (isArray) { fieldSchema = fieldSchema.Items![0].Resolve(Schemas); } var type = fieldSchema.Id?.Fragment ?? fieldSchema.Format ?? fieldSchema.Type.ToString(); if (isArray) { type += "Array"; } if (_reversibleEncoding) { // For reversible encoding, the field is a variant formatted object valueSchema = GetSchemaForTypedVariant(ns, type, valueSchema, builtInType); } if (!asDataValue) { // Raw mode return valueSchema; } var id = new UriOrFragment(type + nameof(DataValue), ns); return Schemas.Reference(id, id => { return new JsonSchema { Id = id, Title = $"Dataset Field of Type {type}", Type = SchemaType.Object, Properties = new Dictionary { ["Value"] = valueSchema, ["Status"] = GetSchemaForBuiltInType(BuiltInType.StatusCode), ["SourceTimestamp"] = GetSchemaForBuiltInType(BuiltInType.DateTime), ["SourcePicoSeconds"] = GetSchemaForBuiltInType(BuiltInType.UInt16), ["ServerTimestamp"] = GetSchemaForBuiltInType(BuiltInType.DateTime), ["ServerPicoSeconds"] = GetSchemaForBuiltInType(BuiltInType.UInt16) }, AdditionalProperties = new JsonSchema { Allowed = false } }; }); } /// public override JsonSchema GetSchemaForRank(JsonSchema schema, SchemaRank rank) { switch (rank) { case SchemaRank.Matrix: // Variant schema return GetSchemaForBuiltInType(BuiltInType.Variant); case SchemaRank.Collection: return schema.AsArray(); default: return schema; } } /// /// Generate a typed variant /// /// /// /// /// /// private JsonSchema GetSchemaForTypedVariant(string ns, string name, JsonSchema valueSchema, BuiltInType builtInType) { var id = new UriOrFragment(name + nameof(Variant), ns); return Schemas.Reference(id, id => { return new JsonSchema { Id = id, Title = $"Variant Field of Type {name}", Type = SchemaType.Object, Properties = new Dictionary { ["Type"] = new JsonSchema { Type = SchemaType.Integer, Const = Const.From((int)builtInType) }, ["Body"] = valueSchema }, AdditionalProperties = new JsonSchema { Allowed = false } }; }); } /// /// Get data typeid /// /// /// private static UriOrFragment GetId(BuiltInType builtInType) { return new UriOrFragment(builtInType.ToString(), Namespaces.OpcUa); } /// /// Create a definition name /// /// /// private static string GetDefinitionName(BuiltInType builtInType) { return SchemaUtils.NamespaceZeroName + "." + builtInType; } /// /// Create primitive opc ua built in type /// /// /// /// /// /// /// /// private static JsonSchema Simple(int builtInType, SchemaType type, string? format = null, Limit? minValue = null, Limit? maxValue = null, Const? defaultValue = null) { return new JsonSchema { Title = GetTitle((BuiltInType)builtInType), Id = GetId((BuiltInType)builtInType), Minimum = minValue, Maximum = maxValue, Default = defaultValue, Type = type, Format = format }; } /// /// Create a reference /// /// /// private static JsonSchema Reference(BuiltInType builtInType) { return new JsonSchema { Reference = new UriOrFragment(GetDefinitionName(builtInType)) }; } /// /// Create a title /// /// /// private static string GetTitle(BuiltInType builtInType) { return $"OPC UA built in type {builtInType}"; } private readonly bool _reversibleEncoding; private readonly bool _encodeNamespacedValuesAsUri; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/Json/JsonDataSet.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas.Json { using Azure.IIoT.OpcUa.Encoders; using Azure.IIoT.OpcUa.Publisher.Models; using Furly; using Furly.Extensions.Messaging; using System.Collections.Generic; using System.Linq; /// /// Extensions to convert metadata into json schema. Note that this class /// generates a schema that complies with the json representation in /// .WriteDataSet. /// This depends on the network settings and reversible vs. nonreversible /// encoding mode. /// public sealed class JsonDataSet : BaseDataSetSchema, IEventSchema { /// public string Type => ContentMimeType.Json; /// public string Name { get; } /// public ulong Version { get; } /// public string Id { get; } /// string IEventSchema.Schema => Schema.ToJsonString(); /// public override JsonSchema Schema => new() { Definitions = Definitions, Type = Ref == null ? SchemaType.Null : SchemaType.None, Reference = Ref?.Reference }; /// /// Schema reference /// public JsonSchema? Ref { get; } /// /// Definitions /// internal Dictionary Definitions => ((JsonBuiltInSchemas)Encoding).Schemas; /// /// Get json schema for a dataset /// /// /// /// /// /// /// /// public JsonDataSet(string id, PublishedDataSetMetaDataModel dataSet, DataSetFieldContentFlags? dataSetFieldContentFlags = null, SchemaOptions? options = null, Dictionary? def = null, HashSet? uniqueNames = null) : base(dataSetFieldContentFlags, new JsonBuiltInSchemas( dataSetFieldContentFlags ?? default, def), options) { var name = dataSet.DataSetMetaData?.Name; Id = id; Name = name ?? "DataSet"; Ref = Compile(name, dataSet, uniqueNames); } /// public override string? ToString() { return Schema.ToJsonString(); } /// protected override IEnumerable GetDataSetFieldSchemas(string? name, PublishedDataSetMetaDataModel dataSet, HashSet? uniqueNames) { var singleValue = dataSet.Fields.Count == 1; GetEncodingMode(out var omitFieldName, out var fieldsAreDataValues, singleValue); if (omitFieldName) { var set = new HashSet(); foreach (var fieldMetadata in dataSet.Fields) { if (fieldMetadata?.DataType != null) { var schema = LookupSchema(fieldMetadata.DataType, SchemaUtils.GetRank(fieldMetadata.ValueRank), fieldMetadata.ArrayDimensions); set.Add(schema); } } return set; } var ns = _options.GetNamespaceUri(); var properties = new Dictionary(); var required = new List(); foreach (var fieldMetadata in dataSet.Fields) { if (fieldMetadata?.DataType != null) { var schema = LookupSchema(fieldMetadata.DataType, SchemaUtils.GetRank(fieldMetadata.ValueRank), fieldMetadata.ArrayDimensions); if (fieldMetadata.Name != null) { // TODO: Add properties to the field type schema = Encoding.GetSchemaForDataSetField(ns, fieldsAreDataValues, schema, (Opc.Ua.BuiltInType)fieldMetadata.BuiltInType); schema.Description = fieldMetadata.Description; properties.Add(fieldMetadata.Name, schema); } } } var type = MakeUnique(name ?? dataSet.DataSetMetaData.Name ?? "DataSet", uniqueNames); return Definitions.Reference(_options.GetSchemaId(type), id => new JsonSchema { Id = id, Title = type, Type = SchemaType.Object, Properties = properties, Required = required }).YieldReturn(); } /// protected override JsonSchema CreateStructureSchema(StructureDescriptionModel description, SchemaRank rank, JsonSchema? baseTypeSchema) { var scalar = Definitions.Reference(description.DataTypeId .GetSchemaId(description.Name, Context), id => { // // |---------------|------------|----------------| // | Field Value | Reversible | Non-Reversible | // |---------------|------------|----------------| // | NULL | Omitted | JSON null | // | Default Value | Omitted | Default Value | // |---------------|------------|----------------| // var properties = new Dictionary(); var required = new List(); for (var i = 0; i < description.Fields.Count; i++) { var field = description.Fields[i]; var schema = LookupSchema(field.DataType, SchemaUtils.GetRank(field.ValueRank), field.ArrayDimensions); if (!field.IsOptional) { required.Add(field.Name); } schema.Description = field.Description; properties.Add(field.Name, schema); } return new JsonSchema { Id = id, Title = description.Name, Type = SchemaType.Object, AllOf = baseTypeSchema == null ? null : new[] { baseTypeSchema }, Properties = properties, Required = required, AdditionalProperties = new JsonSchema { Allowed = false } }; }); return Encoding.GetSchemaForRank(scalar, rank); } /// protected override JsonSchema CreateEnumSchema(EnumDescriptionModel description, SchemaRank rank) { var scalar = Definitions.Reference(description.DataTypeId .GetSchemaId(description.Name, Context), id => { var fields = description.Fields .Select(f => new Const(f.Value)).ToArray(); // TODO: Build doc from fields descriptions return new JsonSchema { Id = id, Title = description.Name, Enum = fields, Type = SchemaType.Integer, Format = "int32" }; }); return Encoding.GetSchemaForRank(scalar, rank); } /// protected override JsonSchema CreateUnionSchema(IReadOnlyList schemas) { return schemas.AsUnion(Definitions); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/Json/JsonDataSetMessage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas.Json { using Azure.IIoT.OpcUa.Encoders.Schemas; using Azure.IIoT.OpcUa.Encoders.PubSub; using Azure.IIoT.OpcUa.Publisher.Models; using Furly; using Furly.Extensions.Messaging; using Opc.Ua; using System.Collections.Generic; using System.Linq; /// /// DataSet message Json schema /// public sealed class JsonDataSetMessage : IEventSchema { /// public string Type => ContentMimeType.Json; /// public string Name { get; } /// public ulong Version { get; } /// public string Id { get; } /// string IEventSchema.Schema => ToString()!; /// /// Compatibility with 2.8 when encoding and decoding /// public bool UseCompatibilityMode { get; } /// /// Schema reference /// public JsonSchema? Ref { get; } /// /// Definitions /// internal Dictionary Definitions => _dataSet.Definitions; /// /// Definitions /// internal ServiceMessageContext Context => _dataSet.Context; /// /// Get json schema for a writer /// /// /// /// /// /// /// /// internal JsonDataSetMessage(PublishedDataSetMessageSchemaModel dataSetMessage, bool withDataSetMessageHeader, SchemaOptions options, Dictionary definitions, bool useCompatibilityMode, HashSet uniqueNames) { _options = options; _withDataSetMessageHeader = withDataSetMessageHeader; _dataSet = new JsonDataSet(dataSetMessage.Id, dataSetMessage.MetaData, dataSetMessage.DataSetFieldContentFlags, options, definitions, uniqueNames); UseCompatibilityMode = useCompatibilityMode; Id = dataSetMessage.Id; Name = GetName(dataSetMessage.TypeName, uniqueNames); Ref = Compile(dataSetMessage.DataSetMessageContentFlags ?? PubSubMessage.DefaultDataSetMessageContentFlags); } /// public override string? ToString() { return new JsonSchema { Type = Ref == null ? SchemaType.Null : SchemaType.None, Definitions = Definitions, Reference = Ref?.Reference }.ToJsonString(); } /// /// Compile the data set message schema /// /// /// private JsonSchema? Compile(DataSetMessageContentFlags dataSetMessageContentMask) { if (_dataSet.Ref == null) { return null; } if (!_withDataSetMessageHeader) { // Not a data set message return _dataSet.Ref; } var encoding = new JsonBuiltInSchemas(true, true, Definitions); var properties = new Dictionary(); if (dataSetMessageContentMask.HasFlag(DataSetMessageContentFlags.DataSetWriterId)) { if (!UseCompatibilityMode) { properties.Add(nameof(DataSetMessageContentFlags.DataSetWriterId), encoding.GetSchemaForBuiltInType(BuiltInType.UInt16)); } else { // Up to version 2.8 we wrote the string id as id which is not per standard properties.Add(nameof(DataSetMessageContentFlags.DataSetWriterId), encoding.GetSchemaForBuiltInType(BuiltInType.String)); } } if (dataSetMessageContentMask.HasFlag(DataSetMessageContentFlags.SequenceNumber)) { properties.Add(nameof(DataSetMessageContentFlags.SequenceNumber), encoding.GetSchemaForBuiltInType(BuiltInType.UInt32)); } if (dataSetMessageContentMask.HasFlag(DataSetMessageContentFlags.MetaDataVersion)) { var version = Definitions.Reference( DataTypeIds.ConfigurationVersionDataType.GetSchemaId(Context), id => new JsonSchema { Id = id, Type = SchemaType.Object, Properties = new Dictionary { ["MajorVersion"] = encoding.GetSchemaForBuiltInType(BuiltInType.UInt32), ["MinorVersion"] = encoding.GetSchemaForBuiltInType(BuiltInType.UInt32) } }); properties.Add(nameof(DataSetMessageContentFlags.MetaDataVersion), version); } if (dataSetMessageContentMask.HasFlag(DataSetMessageContentFlags.Timestamp)) { properties.Add(nameof(DataSetMessageContentFlags.Timestamp), encoding.GetSchemaForBuiltInType(BuiltInType.DateTime)); } if (dataSetMessageContentMask.HasFlag(DataSetMessageContentFlags.Status)) { if (!UseCompatibilityMode) { properties.Add(nameof(DataSetMessageContentFlags.Status), encoding.GetSchemaForBuiltInType(BuiltInType.StatusCode)); } else { // Up to version 2.8 we wrote the full status code properties.Add(nameof(DataSetMessageContentFlags.Status), new JsonBuiltInSchemas(false, false, Definitions) .GetSchemaForBuiltInType(BuiltInType.StatusCode)); } } if (dataSetMessageContentMask.HasFlag(DataSetMessageContentFlags.MessageType)) { properties.Add(nameof(DataSetMessageContentFlags.MessageType), encoding.GetSchemaForBuiltInType(BuiltInType.String)); } if (!UseCompatibilityMode && dataSetMessageContentMask.HasFlag(DataSetMessageContentFlags.DataSetWriterName)) { properties.Add(nameof(DataSetMessageContentFlags.DataSetWriterName), encoding.GetSchemaForBuiltInType(BuiltInType.String)); } properties.Add(nameof(PubSub.JsonDataSetMessage.Payload), _dataSet.Ref); return Definitions.Reference(_options.GetSchemaId(Name), id => new JsonSchema { Id = id, Type = SchemaType.Object, AdditionalProperties = new JsonSchema { Allowed = false }, Properties = properties, Required = properties.Keys.ToList() }); } /// /// Get name of the type /// /// /// /// private static string GetName(string? typeName, HashSet? uniqueNames) { // Type name of the message record typeName ??= string.Empty; typeName += BaseDataSetMessage.MessageTypeName; if (uniqueNames != null) { var uniqueName = typeName; for (var index = 1; uniqueNames.Contains(uniqueName); index++) { uniqueName = typeName + index; } uniqueNames.Add(uniqueName); typeName = uniqueName; } return typeName; } private readonly JsonDataSet _dataSet; private readonly SchemaOptions _options; private readonly bool _withDataSetMessageHeader; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/Json/JsonNetworkMessage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas.Json { using Azure.IIoT.OpcUa.Encoders.Schemas; using Azure.IIoT.OpcUa.Encoders.PubSub; using Azure.IIoT.OpcUa.Publisher.Models; using Furly; using Furly.Extensions.Messaging; using Opc.Ua; using System; using System.Collections.Generic; using System.Linq; /// /// Network message json schema /// public sealed class JsonNetworkMessage : IEventSchema { /// public string Type => ContentMimeType.JsonSchema; /// public string Name { get; } /// public ulong Version { get; } /// public string Id { get; } /// string IEventSchema.Schema => ToString()!; /// /// Schema reference /// public JsonSchema? Ref { get; } /// /// Definitions /// internal Dictionary Definitions { get; } /// /// Compatibility with 2.8 when encoding and decoding /// public bool UseCompatibilityMode { get; } /// /// Get avro schema for a writer group /// /// /// /// /// public JsonNetworkMessage(PublishedNetworkMessageSchemaModel networkMessage, SchemaOptions? options = null, bool useCompatibilityMode = false, Dictionary? definitions = null) { ArgumentNullException.ThrowIfNull(networkMessage); UseCompatibilityMode = useCompatibilityMode; Definitions = definitions ?? []; _options = options ?? new SchemaOptions(); Version = networkMessage.Version; Id = networkMessage.Id; Name = GetName(networkMessage.TypeName); Ref = Compile(networkMessage); } /// public override string? ToString() { return new JsonSchema { Type = Ref == null ? SchemaType.Null : Ref.Type, Items = Ref?.Items, Definitions = Definitions, Reference = Ref?.Reference }.ToJsonString(); } /// /// Compile the schema for the data sets /// /// /// private JsonSchema? Compile(PublishedNetworkMessageSchemaModel networkMessage) { var dataSetMessages = networkMessage.DataSetMessages; var networkMessageContentFlags = networkMessage.NetworkMessageContentFlags ?? PubSubMessage.DefaultNetworkMessageContentFlags; var MonitoredItemMessage = networkMessageContentFlags .HasFlag(NetworkMessageContentFlags.MonitoredItemMessage); if (MonitoredItemMessage) { networkMessageContentFlags &= ~NetworkMessageContentFlags.NetworkMessageHeader; } var dataSetSchemas = dataSetMessages .Where(dataSet => dataSet != null) .Select(dataSet => GetSchema(dataSet!, networkMessageContentFlags)) .Where(r => r != null) .ToList(); if (dataSetSchemas.Count == 0) { return null; } if (MonitoredItemMessage) { return CollapseUnions(dataSetSchemas); } var dataSetMessageSchemas = dataSetSchemas.Count > 1 ? dataSetSchemas.AsUnion(Definitions, id: _options.GetSchemaId(MakeUnique("DataSets"))) : dataSetSchemas[0]; var HasSingleDataSetMessage = networkMessageContentFlags .HasFlag(NetworkMessageContentFlags.SingleDataSetMessage); var payloadType = HasSingleDataSetMessage ? dataSetMessageSchemas : dataSetMessageSchemas.AsArray(); if ((networkMessageContentFlags & ~(NetworkMessageContentFlags.SingleDataSetMessage | NetworkMessageContentFlags.DataSetMessageHeader | NetworkMessageContentFlags.MonitoredItemMessage)) == 0u) { // No network message header return payloadType; } var encoding = new JsonBuiltInSchemas(true, false, Definitions); var properties = new Dictionary { [nameof(PubSub.JsonNetworkMessage.MessageId)] = encoding.GetSchemaForBuiltInType(BuiltInType.String), [nameof(PubSub.JsonNetworkMessage.MessageType)] = encoding.GetSchemaForBuiltInType(BuiltInType.String) }; if (networkMessageContentFlags.HasFlag(NetworkMessageContentFlags.PublisherId)) { properties.Add(nameof(PubSub.JsonNetworkMessage.PublisherId), encoding.GetSchemaForBuiltInType(BuiltInType.String)); } if (networkMessageContentFlags.HasFlag(NetworkMessageContentFlags.DataSetClassId)) { properties.Add(nameof(PubSub.JsonNetworkMessage.DataSetClassId), encoding.GetSchemaForBuiltInType(BuiltInType.Guid)); } properties.Add(nameof(PubSub.JsonNetworkMessage.DataSetWriterGroup), encoding.GetSchemaForBuiltInType(BuiltInType.String)); // Now write messages - this is either one of or array of one of properties.Add(nameof(PubSub.JsonNetworkMessage.Messages), payloadType); var messageSchema = Definitions.Reference(_options.GetSchemaId(Name), id => new JsonSchema { Id = id, Type = Ref == null ? SchemaType.Null : SchemaType.None, AdditionalProperties = new JsonSchema { Allowed = false }, Properties = properties, Required = properties.Keys.ToList() }); if (networkMessageContentFlags .HasFlag(NetworkMessageContentFlags.UseArrayEnvelope)) { return messageSchema.AsArray(BaseNetworkMessage.MessageTypeName + "s"); } return messageSchema; } /// /// Collapse the unions into one /// /// /// private JsonSchema CollapseUnions(List dataSets) { // Collapse all unions into one var messages = new List(); foreach (var dataSet in dataSets) { if (dataSet.OneOf == null) { messages.Add(dataSet); continue; } // Remove dataset schema from definitions messages.AddRange(dataSet.OneOf); if (dataSet.Reference?.Fragment != null) { Definitions.Remove(dataSet.Reference.Fragment); } } return messages.AsUnion(Definitions, id: _options.GetSchemaId( MakeUnique(nameof(MonitoredItemMessage) + "s"))); } /// /// Get data set message schema /// /// /// /// private JsonSchema GetSchema(PublishedDataSetMessageSchemaModel dataSetMessage, NetworkMessageContentFlags networkMessageContentFlags) { if (networkMessageContentFlags.HasFlag(NetworkMessageContentFlags.MonitoredItemMessage)) { return new MonitoredItemMessage(dataSetMessage, networkMessageContentFlags.HasFlag(NetworkMessageContentFlags.DataSetMessageHeader), _options, Definitions, _uniqueNames).Ref!; } return new JsonDataSetMessage(dataSetMessage, networkMessageContentFlags.HasFlag(NetworkMessageContentFlags.DataSetMessageHeader), _options, Definitions, UseCompatibilityMode, _uniqueNames).Ref!; } /// /// Get name of the type /// /// /// private string GetName(string? typeName) { // Type name of the message record typeName ??= string.Empty; typeName += BaseNetworkMessage.MessageTypeName; return MakeUnique(typeName); } /// /// Make unique /// /// /// private string MakeUnique(string name) { var uniqueName = name; for (var index = 1; _uniqueNames.Contains(uniqueName); index++) { uniqueName = name + index; } _uniqueNames.Add(uniqueName); return uniqueName; } private readonly SchemaOptions _options; private readonly HashSet _uniqueNames = []; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/Json/JsonSchema.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas.Json { using System; using System.Collections.Generic; using System.Linq; using System.Text.Json; /// /// Json Schema object - constraints for a schema with the defined /// types. see https://www.learnjsonschema.com/2020-12/ /// public record class JsonSchema { /// /// Allows everything, serializes to true /// public bool? Allowed { get; set; } /// /// The absolute id of the schema /// public UriOrFragment? Id { get; set; } /// /// Schema version /// public string? SchemaVersion { get; set; } /// /// Title annotation /// public string? Title { get; set; } /// /// Description annotation /// public string? Description { get; set; } /// /// Comment annotation /// public string? Comment { get; set; } /// /// Examples /// public IReadOnlyList? Examples { get; set; } /// /// Schema types /// public IReadOnlyList Types { get; set; } = Array.Empty(); /// /// Enum values /// public IReadOnlyList? Enum { get; set; } /// /// Gets or sets the maximum valid number of properties. /// public int? MaxProperties { get; set; } /// /// Gets or sets the maximum valid number of properties. /// public int? MinProperties { get; set; } /// /// ReadOnly annotation /// public bool? ReadOnly { get; set; } /// /// WriteOnly annotation /// public bool? WriteOnly { get; set; } /// /// The schemas for the fields of the object /// public IReadOnlyDictionary? Properties { get; set; } /// /// The schemas for the fields of the object /// public JsonSchema? PropertyNames { get; set; } /// /// Required properties /// public IReadOnlyList? Required { get; set; } /// /// Required properties /// public IReadOnlyList? Contains { get; set; } /// /// Gets or sets a dictionary that maps property names to the conditions /// that an instance containing those property names must satisfy. /// public IReadOnlyDictionary? Dependencies { get; set; } /// /// Additional properties (allowed or schema) /// public JsonSchema? AdditionalProperties { get; set; } /// /// Gets or sets a set of schemas against all of which /// the instance must validate successfully. /// public IReadOnlyList? AllOf { get; set; } /// /// Gets or sets a set of schemas against any of which /// the instance must validate successfully. /// public IReadOnlyList? AnyOf { get; set; } /// /// Gets or sets a set of schemas against exactly one of /// which the instance must validate successfully. /// public IReadOnlyList? OneOf { get; set; } /// /// Gets or sets a schemas against which the instance /// must not validate successfully. /// public JsonSchema? Not { get; set; } /// /// Array items allowed /// public IReadOnlyList? Items { get; set; } /// /// Additional items /// public JsonSchema? AdditionalItems { get; set; } /// /// Gets or sets the maximum length of a string /// public int? MaxLength { get; set; } /// /// Gets or sets the minimum length of a string /// public int? MinLength { get; set; } /// /// Gets or sets the default value. /// public Const? Default { get; set; } /// /// Gets or sets a const value. /// public Const? Const { get; set; } /// /// Gets or sets a regular expression which string must match /// public string? Pattern { get; set; } /// /// Gets or sets a value of which a numeric schema /// instance must be a multiple. /// public Const? MultipleOf { get; set; } /// /// Gets or sets the maximum valid value of integer /// or number schema. /// public Limit? Maximum { get; set; } /// /// Gets or sets the minimum valid value. /// public Limit? Minimum { get; set; } /// /// Gets or sets the minimum valid number of elements /// in an array. /// public int? MinItems { get; set; } /// /// Gets or sets the maximum valid elements in an array. /// public int? MaxItems { get; set; } /// /// Gets or sets a value that specifies elements must be unique. /// public bool? UniqueItems { get; set; } /// /// Gets or sets the URI of a schema that is incorporated /// by reference into the current schema. /// public UriOrFragment? Reference { get; set; } /// /// Gets or sets a string specifying the required format /// of a string-valued property. /// public string? Format { get; set; } /// /// Gets or sets a dictionary mapping schema names /// to sub-schemas which can be referenced by properties /// defined elsewhere in the current schema. /// public IReadOnlyDictionary? Definitions { get; set; } /// /// Get Schema type /// /// public SchemaType Type { get => Types?.Count > 0 ? Types[0] : SchemaType.None; set => Types = value == SchemaType.None ? Array.Empty() : [value]; } } /// /// Represents the valid values for the "type" keyword in a JSON schema. /// public enum SchemaType { /// /// Invalid /// None, #pragma warning disable CA1720 // Identifier contains type name /// /// Array /// Array, /// /// Boolean /// Boolean, /// /// Integer /// Integer, /// /// Number /// Number, /// /// Null /// Null, /// /// Object /// Object, /// /// String /// String, #pragma warning restore CA1720 // Identifier contains type name } /// /// Const base class /// public abstract record Const { /// /// Write value to writer /// /// internal abstract void Write(Utf8JsonWriter writer); /// /// Create const /// /// /// /// public static Const From(T value) { return new Const(value); } } /// /// Limit value /// /// /// public record class Limit(Const Value, bool Exclusive = false) { /// /// Create limit /// /// /// /// /// public static Limit From(T value, bool exclusive = false) { return new Limit(Const.From(value), exclusive); } } /// /// Const value /// /// /// public record class Const(T Value) : Const { /// internal override void Write(Utf8JsonWriter writer) { JsonSerializer.Serialize(writer, Value); } } /// /// Describes that conditions that must be satisfied when an object contains /// a property with the specified name. /// public record class Dependency { /// /// Gets the schema against which an instance must validate successfully if it /// has a property of the name associated with this dependency. /// public JsonSchema? SchemaDependency { get; } /// /// Gets the set of property names which an instance must also have if it has a /// property of the name associated with this dependency. /// public IReadOnlyList? PropertyDependencies { get; } /// /// Initializes a new instance of the class from the /// specified schema dependency. /// /// /// The schema against which an instance must validate successfully if it /// has a property of the name associated with this dependency. /// public Dependency(JsonSchema schemaDependency) { SchemaDependency = schemaDependency; } /// /// Initializes a new instance of the class from the /// specified property dependencies. /// /// /// The set of property names which an instance must also have if it has a /// property of the name associated with this dependency. /// public Dependency(IList propertyDependencies) { PropertyDependencies = propertyDependencies.ToList(); } } /// /// Represents a value that is either a URI reference according to /// RFC 2396, or a bare fragment. /// public record class UriOrFragment { /// /// Value /// public string Fragment { get; } /// /// Value /// public string? Namespace { get; } /// /// Self reference /// public static readonly UriOrFragment Self = new("#"); /// /// Create a fragment /// /// /// public UriOrFragment(string fragment, string? @namespace = null) { Fragment = fragment; Namespace = @namespace; } /// /// Value /// public override string ToString() { if (Namespace != null) { return Namespace + "#" + Fragment.UrlEncode(); } return Fragment.UrlEncode(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/Json/JsonSchemaExtensions.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas.Json { using Azure.IIoT.OpcUa.Publisher.Models; using Opc.Ua; using Opc.Ua.Extensions; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; /// /// Extensions /// internal static class JsonSchemaExtensions { /// /// Create a reference /// /// /// /// /// public static JsonSchema Reference(this Dictionary definitions, UriOrFragment id, Func schema) { var name = ToFragment(id); if (!definitions.ContainsKey(name)) { definitions.Add(name, schema(id)); } return new JsonSchema { Reference = new UriOrFragment(name) }; } /// /// Convert to fragment /// /// /// public static string ToFragment(this UriOrFragment id) { if (id.Namespace == null) { return id.Fragment; } return SchemaUtils.NamespaceUriToNamespace(id.Namespace) + "." + SchemaUtils.Escape(id.Fragment); } /// /// Make union type from schemas /// /// /// /// /// /// /// public static JsonSchema AsUnion(this IEnumerable schemas, Dictionary definitions, string? title = null, UriOrFragment? id = null) { var s = schemas.ToList(); if (s.Count == 0) { throw new ArgumentException("Union must have at least one schema", nameof(schemas)); } if (id == null) { return Create(definitions, title, s, null); } return definitions.Reference(id, id => Create(definitions, title, s, id)); static JsonSchema Create(Dictionary definitions, string? title, List s, UriOrFragment? id) { return new JsonSchema { Id = id, Title = title, Types = s .Select(s => Resolve(s, definitions).Type) .Distinct() .ToArray(), OneOf = s }; } } /// /// Make array from schema /// /// /// /// public static JsonSchema AsArray(this JsonSchema schema, string? title = null) { return new JsonSchema { Title = title, Type = SchemaType.Array, Items = new[] { schema } }; } /// /// Make array from schema /// /// /// /// public static JsonSchema Resolve(this JsonSchema schema, Dictionary definitions) { if (schema.Reference == null) { Debug.Assert(schema.Type != SchemaType.None); return schema; } if (schema.Reference.Namespace == null) { return definitions[schema.Reference.Fragment]; } return definitions.Values.First(d => d.Id == schema.Reference); } /// /// Convert to string /// /// /// /// public static string ToJsonString(this JsonSchema schema, bool indented = false) { return JsonSchemaWriter.SerializeAsString(schema, indented); } /// /// Get namespace /// /// /// public static string GetNamespaceUri(this SchemaOptions options) { return options.Namespace ?? SchemaUtils.PublisherNamespaceUri; } /// /// Create identifier of a schema in the namespace /// configured in the options /// /// /// /// public static UriOrFragment GetSchemaId(this SchemaOptions options, string fragment) { return new UriOrFragment(fragment, options.GetNamespaceUri()); } /// /// Create identifier of a schema /// /// /// /// public static UriOrFragment GetSchemaId(this NodeId nodeId, IServiceMessageContext context) { return nodeId.AsString(context, NamespaceFormat.Uri).GetSchemaId(context); } /// /// Create identifier of a schema /// /// /// /// public static UriOrFragment GetSchemaId(this string? nodeId, IServiceMessageContext context) { var (ns, n) = SchemaUtils.SplitNodeId(nodeId, context, false); return new UriOrFragment(n, ns); } /// /// Get schema id from a node with a display name as name /// /// /// /// /// public static UriOrFragment GetSchemaId(this string? nodeId, string name, IServiceMessageContext context) { var qn = name.ToQualifiedName(context); var ns = qn.NamespaceIndex != 0 ? context.NamespaceUris.GetString(qn.NamespaceIndex) : SchemaUtils.SplitNodeId(nodeId, context, false).Namespace; return new UriOrFragment(qn.Name, ns); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/Json/JsonSchemaVersion.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas.Json { /// /// Versions /// public static class JsonSchemaVersion { /// /// http://json-schema.org/draft-04/schema# /// public const string Draft4 = "http://json-schema.org/draft-04/schema#"; /// /// http://json-schema.org/draft-06/schema# /// public const string Draft6 = "http://json-schema.org/draft-06/schema#"; /// /// http://json-schema.org/draft-07/schema# /// public const string Draft7 = "http://json-schema.org/draft-07/schema#"; /// /// http://json-schema.org/draft/2020-12/schema#" /// public const string Draft202012 = "http://json-schema.org/draft/2020-12/schema#"; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/Json/JsonSchemaVocabulary.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas.Json { using System; /// /// Schema vocabulary /// internal static class JsonSchemaVocabulary { public static ReadOnlySpan Schema => "$schema"u8; public static ReadOnlySpan Id => "$id"u8; public static ReadOnlySpan IdPreDraft6 => "id"u8; public static ReadOnlySpan Defs => "$defs"u8; public static ReadOnlySpan Definitions => "definitions"u8; public static ReadOnlySpan Ref => "$ref"u8; public static ReadOnlySpan Title => "title"u8; public static ReadOnlySpan Type => "type"u8; public static ReadOnlySpan Enum => "enum"u8; public static ReadOnlySpan Description => "description"u8; public static ReadOnlySpan Examples => "examples"u8; public static ReadOnlySpan Comment => "$comment"u8; public static ReadOnlySpan Items => "items"u8; public static ReadOnlySpan Format => "format"u8; public static ReadOnlySpan Const => "const"u8; public static ReadOnlySpan ReadOnly => "readOnly"u8; public static ReadOnlySpan WriteOnly => "writeOnly"u8; public static ReadOnlySpan Default => "default"u8; public static ReadOnlySpan Minimum => "minimum"u8; public static ReadOnlySpan Maximum => "maximum"u8; public static ReadOnlySpan MultipleOf => "multipleOf"u8; public static ReadOnlySpan ExclusiveMinimum => "exclusiveMinimum"u8; public static ReadOnlySpan ExclusiveMaximum => "exclusiveMaximum"u8; public static ReadOnlySpan Required => "required"u8; public static ReadOnlySpan Properties => "properties"u8; public static ReadOnlySpan MinProperties => "minProperties"u8; public static ReadOnlySpan MaxProperties => "maxProperties"u8; public static ReadOnlySpan Dependencies => "dependencies"u8; public static ReadOnlySpan PropertyNames => "propertyNames"u8; public static ReadOnlySpan AdditionalProperties => "additionalProperties"u8; public static ReadOnlySpan MinLength => "minLength"u8; public static ReadOnlySpan MaxLength => "maxLength"u8; public static ReadOnlySpan MinItems => "minItems"u8; public static ReadOnlySpan MaxItems => "maxItems"u8; public static ReadOnlySpan UniqueItems => "uniqueItems"u8; public static ReadOnlySpan AdditionalItems => "additionalItems"u8; public static ReadOnlySpan Contains => "contains"u8; public static ReadOnlySpan AllOf => "allOf"u8; public static ReadOnlySpan OneOf => "oneOf"u8; public static ReadOnlySpan AnyOf => "anyOf"u8; public static ReadOnlySpan Not => "not"u8; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/Json/JsonSchemaWriter.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas.Json { using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Text.Json; /// /// Json Schema writer /// public sealed class JsonSchemaWriter : IDisposable { /// /// Create writer /// /// /// public JsonSchemaWriter(Stream stream, JsonWriterOptions options) { _writer = new Utf8JsonWriter(stream, options); } /// public void Dispose() { _writer.Dispose(); } /// /// Convert to string /// /// /// /// public static string SerializeAsString(JsonSchema schema, bool indented = false) { schema.SchemaVersion ??= JsonSchemaVersion.Draft7; using var stream = new MemoryStream(); using (var writer = new JsonSchemaWriter(stream, new JsonWriterOptions { Indented = indented })) { writer.Write(schema); } return Encoding.UTF8.GetString(stream.ToArray()); } /// /// Write schema /// /// public void Write(JsonSchema schema) { Write(schema, Current != JsonSchemaVersion.Draft4); } /// /// Write schema /// /// /// private void Write(JsonSchema schema, bool allowTrueSchema) { if (schema.Allowed != null && allowTrueSchema) // TODO: should we throw here? { // From draft6 on // // booleans as schemas allowable anywhere, not just // "additionalProperties" and "additionalItems" true is // equivalent to {}, false is equivalent to {"not": {}}, // but the intent is more clear and implementations can // optimize these cases more easily // _writer.WriteBooleanValue(schema.Allowed.Value); return; } _writer.WriteStartObject(); var pop = false; if (schema.SchemaVersion != null && Current != schema.SchemaVersion) { _schemaVersion.Push(schema.SchemaVersion!); _writer.WriteString(JsonSchemaVocabulary.Schema, schema.SchemaVersion); pop = true; } try { try { if (schema.Reference != null) { // Write the reference Write(JsonSchemaVocabulary.Ref, schema.Reference); return; } if (schema.Id != null) { Write(Current != JsonSchemaVersion.Draft4 ? JsonSchemaVocabulary.Id : JsonSchemaVocabulary.IdPreDraft6, schema.Id); } Write(JsonSchemaVocabulary.Title, schema.Title); Write(JsonSchemaVocabulary.Description, schema.Description); if (Current != JsonSchemaVersion.Draft4) { Write(JsonSchemaVocabulary.Examples, schema.Examples); if (Current != JsonSchemaVersion.Draft6) { Write(JsonSchemaVocabulary.Comment, schema.Comment); } } Write(JsonSchemaVocabulary.Type, schema.Types); Write(JsonSchemaVocabulary.Enum, schema.Enum); Write(JsonSchemaVocabulary.Items, schema.Items, true); Write(JsonSchemaVocabulary.MinItems, schema.MinItems); Write(JsonSchemaVocabulary.MaxItems, schema.MaxItems); Write(JsonSchemaVocabulary.UniqueItems, schema.UniqueItems); Write(JsonSchemaVocabulary.AdditionalItems, schema.AdditionalItems, true); if (Current != JsonSchemaVersion.Draft4) { Write(JsonSchemaVocabulary.Contains, schema.Contains); } Write(JsonSchemaVocabulary.AllOf, schema.AllOf); Write(JsonSchemaVocabulary.OneOf, schema.OneOf); Write(JsonSchemaVocabulary.AnyOf, schema.AnyOf); Write(JsonSchemaVocabulary.Not, schema.Not, Current != JsonSchemaVersion.Draft4); Write(JsonSchemaVocabulary.Properties, schema.Properties); Write(JsonSchemaVocabulary.MinProperties, schema.MinProperties); Write(JsonSchemaVocabulary.MaxProperties, schema.MaxProperties); Write(JsonSchemaVocabulary.Required, schema.Required); Write(JsonSchemaVocabulary.AdditionalProperties, schema.AdditionalProperties, true); Write(JsonSchemaVocabulary.Dependencies, schema.Dependencies); if (Current != JsonSchemaVersion.Draft4) { Write(JsonSchemaVocabulary.PropertyNames, schema.PropertyNames, true); } Write(JsonSchemaVocabulary.Minimum, schema.Minimum); Write(JsonSchemaVocabulary.Maximum, schema.Maximum); Write(JsonSchemaVocabulary.Default, schema.Default); Write(JsonSchemaVocabulary.Format, schema.Format); Write(JsonSchemaVocabulary.MultipleOf, schema.MultipleOf); if (Current != JsonSchemaVersion.Draft4) { Write(JsonSchemaVocabulary.Const, schema.Const); if (Current != JsonSchemaVersion.Draft6) { if (schema.ReadOnly.HasValue) { Write(JsonSchemaVocabulary.ReadOnly, schema.ReadOnly); } else { Write(JsonSchemaVocabulary.WriteOnly, schema.WriteOnly); } } } Write(JsonSchemaVocabulary.MinLength, schema.MinLength); Write(JsonSchemaVocabulary.MaxLength, schema.MaxLength); } finally { Write(Current != JsonSchemaVersion.Draft202012 ? JsonSchemaVocabulary.Definitions : JsonSchemaVocabulary.Defs, schema.Definitions); } } finally { _writer.WriteEndObject(); if (pop) { _schemaVersion.Pop(); } } } /// /// Write schema /// /// /// private void Write(ReadOnlySpan name, JsonSchema schema) { if (name.Length != 0) { _writer.WritePropertyName(name); } Write(schema); } /// /// Write schema /// /// /// /// private void Write(ReadOnlySpan name, JsonSchema? schema, bool allowTrueSchema) { if (schema == null) { return; } if (name.Length != 0) { _writer.WritePropertyName(name); } Write(schema, allowTrueSchema); } /// /// Write schemas /// /// /// private void Write(ReadOnlySpan name, IReadOnlyDictionary? schemas) { if (schemas == null || schemas.Count == 0) { return; } if (name.Length != 0) { _writer.WritePropertyName(name); } _writer.WriteStartObject(); try { foreach (var kv in schemas) { Write(kv.Key, kv.Value); } } finally { _writer.WriteEndObject(); } } /// /// Write schemas /// /// /// /// private void Write(ReadOnlySpan name, IReadOnlyList? schemas, bool allowSingleItem = false) { if (schemas == null) { return; } if (name.Length != 0) { _writer.WritePropertyName(name); } if (schemas.Count == 1 && allowSingleItem) { Write(schemas[0], Current != JsonSchemaVersion.Draft4); return; } _writer.WriteStartArray(); try { foreach (var schema in schemas) { Write(schema); } } finally { _writer.WriteEndArray(); } } /// /// Write limit /// /// /// private void Write(ReadOnlySpan name, Limit? limit) { if (limit == null) { return; } if (limit.Exclusive) { if (name.SequenceCompareTo(JsonSchemaVocabulary.Minimum) == 0) { if (Current != JsonSchemaVersion.Draft4) { name = JsonSchemaVocabulary.ExclusiveMinimum; } else { Write(JsonSchemaVocabulary.ExclusiveMinimum, limit.Exclusive); } } else if (name.SequenceCompareTo(JsonSchemaVocabulary.Maximum) == 0) { if (Current != JsonSchemaVersion.Draft4) { name = JsonSchemaVocabulary.ExclusiveMaximum; } else { Write(JsonSchemaVocabulary.ExclusiveMaximum, limit.Exclusive); } } } Write(name, limit.Value); } /// /// Write const /// /// /// private void Write(ReadOnlySpan name, Const? constValue) { if (constValue == null) { return; } if (name.Length != 0) { _writer.WritePropertyName(name); } constValue.Write(_writer); } /// /// Write enum /// /// /// private void Write(ReadOnlySpan name, IReadOnlyList? constValues) { if (constValues == null) { return; } if (name.Length != 0) { _writer.WritePropertyName(name); } _writer.WriteStartArray(); foreach (var constValue in constValues) { constValue.Write(_writer); } _writer.WriteEndArray(); } /// /// Write uri or fragment /// /// /// private void Write(ReadOnlySpan name, UriOrFragment? uriOrFragment) { if (uriOrFragment == null) { return; } if (uriOrFragment.Fragment == "#") { _writer.WriteString(name, "#"); } else if (uriOrFragment.Namespace != null) { _writer.WriteString(name, uriOrFragment.ToString()); } else if (Current != JsonSchemaVersion.Draft202012) { _writer.WriteString(name, "#/definitions/" + uriOrFragment.Fragment); } else { _writer.WriteString(name, "#/$defs/" + uriOrFragment.Fragment); } } /// /// Write dependencies /// /// /// private void Write(ReadOnlySpan name, IReadOnlyDictionary? dependencies) { if (dependencies == null || dependencies.Count == 0) // Draft6 allows empty array { return; } _writer.WritePropertyName(name); _writer.WriteStartObject(); foreach (var kv in dependencies) { Write(kv.Key, kv.Value); } _writer.WriteEndObject(); } /// /// Write dependency /// /// /// private void Write(ReadOnlySpan name, Dependency dependency) { _writer.WritePropertyName(name); if (dependency.SchemaDependency != null) { Write(dependency.SchemaDependency); } else if (dependency.PropertyDependencies != null) { _writer.WriteStartArray(); foreach (var arrayElement in dependency.PropertyDependencies) { _writer.WriteStringValue(arrayElement); } _writer.WriteEndArray(); } } /// /// Write schema types /// /// /// private void Write(ReadOnlySpan name, IReadOnlyList? schemaType) { if (schemaType == null) { return; } #pragma warning disable CA1308 // Normalize strings to uppercase var types = schemaType.Select(st => st.ToString().ToLowerInvariant()).ToArray(); #pragma warning restore CA1308 // Normalize strings to uppercase if (types.Length == 1) { _writer.WriteString(name, types[0]); return; } if (name.Length > 0) { _writer.WritePropertyName(name); } _writer.WriteStartArray(); foreach (var type in types) { _writer.WriteStringValue(type); } _writer.WriteEndArray(); } /// /// Write value /// /// /// private void Write(ReadOnlySpan name, string? value) { if (value == null) { return; } _writer.WriteString(name, value); } /// /// Write values /// /// /// private void Write(ReadOnlySpan name, IReadOnlyList? values) { if (values == null || values.Count == 0) // Draft8 allows empty array { return; } if (name.Length > 0) { _writer.WritePropertyName(name); } _writer.WriteStartArray(); foreach (var type in values) { _writer.WriteStringValue(type); } _writer.WriteEndArray(); } /// /// Write value /// /// /// private void Write(ReadOnlySpan name, int? value) { if (value == null) { return; } _writer.WriteNumber(name, value.Value); } /// /// Write value /// /// /// private void Write(ReadOnlySpan name, bool? value) { if (value == null) { return; } _writer.WriteBoolean(name, value.Value); } private string Current => _schemaVersion.Count == 0 ? string.Empty : _schemaVersion.Peek(); private readonly Stack _schemaVersion = new(); private readonly Utf8JsonWriter _writer; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/Json/MonitoredItemMessage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas.Json { using Azure.IIoT.OpcUa.Encoders.Schemas; using Azure.IIoT.OpcUa.Encoders.PubSub; using Azure.IIoT.OpcUa.Publisher.Models; using Furly; using Furly.Extensions.Messaging; using System.Collections.Generic; /// /// Monitored item message json schema /// public sealed class MonitoredItemMessage : IEventSchema { /// public string Type => ContentMimeType.Json; /// public string Name { get; } /// public ulong Version { get; } /// public string Id { get; } /// string IEventSchema.Schema => ToString()!; /// /// Schema reference /// public JsonSchema? Ref { get; } /// /// Definitions /// internal Dictionary Definitions { get; } /// /// Get json schema for monitored item message /// /// /// /// /// /// internal MonitoredItemMessage(PublishedDataSetMessageSchemaModel dataSetMessage, bool withDataSetMessageHeader, SchemaOptions options, Dictionary definitions, HashSet uniqueNames) { _options = options; _withDataSetMessageHeader = withDataSetMessageHeader; _dataSet = new JsonDataSet(dataSetMessage.Id, dataSetMessage.MetaData, dataSetMessage.DataSetFieldContentFlags, options, definitions, uniqueNames); Definitions = definitions ?? []; Id = dataSetMessage.Id; Name = GetName(dataSetMessage.TypeName, uniqueNames); _dataSetFieldContentMask = dataSetMessage.DataSetFieldContentFlags ?? PubSubMessage.DefaultDataSetFieldContentFlags; Ref = Compile(dataSetMessage.TypeName, dataSetMessage.DataSetMessageContentFlags ?? PubSubMessage.DefaultDataSetMessageContentFlags, uniqueNames); } /// public override string? ToString() { return new JsonSchema { Type = Ref == null ? SchemaType.Null : SchemaType.None, Definitions = Definitions, Reference = Ref?.Reference }.ToJsonString(); } /// /// Compile the message schemas into a union of messages /// /// /// /// /// private JsonSchema? Compile(string? typeName, DataSetMessageContentFlags dataSetContentMask, HashSet uniqueNames) { // TODO: Events are encoded as dictionary, not single values if (_dataSet.Ref?.Reference?.Fragment == null) { return null; } // Resolve the data set schema var dataSetSchema = _dataSet.Ref.Resolve(_dataSet.Definitions); if (dataSetSchema?.Properties == null) { return null; } // Remove dataset schema from definitions _dataSet.Definitions.Remove(_dataSet.Ref.Reference.Fragment); // For each value in the data set, compile a message from it var items = new List(); foreach (var property in dataSetSchema.Properties) { var name = GetName(typeName, uniqueNames); var valueSchema = Compile(name, dataSetContentMask, property.Value); if (valueSchema != null) { items.Add(valueSchema); } } return items.AsUnion(_dataSet.Definitions, Name); } /// /// Compile the message schema for the value /// /// /// /// /// private JsonSchema? Compile(string name, DataSetMessageContentFlags dataSetMessageContentMask, JsonSchema valueSchema) { var encoding = new JsonBuiltInSchemas(true, true, Definitions); var properties = new Dictionary(); if (_dataSetFieldContentMask.HasFlag(DataSetFieldContentFlags.NodeId)) { properties.Add(nameof(PubSub.MonitoredItemMessage.NodeId), encoding.GetSchemaForBuiltInType(Opc.Ua.BuiltInType.String)); } if (_dataSetFieldContentMask.HasFlag(DataSetFieldContentFlags.EndpointUrl)) { properties.Add(nameof(PubSub.MonitoredItemMessage.EndpointUrl), encoding.GetSchemaForBuiltInType(Opc.Ua.BuiltInType.String)); } if (_dataSetFieldContentMask.HasFlag(DataSetFieldContentFlags.ApplicationUri)) { properties.Add(nameof(PubSub.MonitoredItemMessage.ApplicationUri), encoding.GetSchemaForBuiltInType(Opc.Ua.BuiltInType.String)); } if (_dataSetFieldContentMask.HasFlag(DataSetFieldContentFlags.DisplayName)) { properties.Add(nameof(PubSub.MonitoredItemMessage.DisplayName), encoding.GetSchemaForBuiltInType(Opc.Ua.BuiltInType.String)); } if (dataSetMessageContentMask.HasFlag(DataSetMessageContentFlags.Timestamp)) { properties.Add(nameof(PubSub.MonitoredItemMessage.Timestamp), encoding.GetSchemaForBuiltInType(Opc.Ua.BuiltInType.DateTime)); } if (dataSetMessageContentMask.HasFlag(DataSetMessageContentFlags.Status)) { properties.Add(nameof(PubSub.MonitoredItemMessage.Status), encoding.GetSchemaForBuiltInType(Opc.Ua.BuiltInType.String)); } properties.Add(nameof(PubSub.MonitoredItemMessage.Value), valueSchema); if (dataSetMessageContentMask.HasFlag(DataSetMessageContentFlags.SequenceNumber)) { properties.Add(nameof(PubSub.MonitoredItemMessage.SequenceNumber), encoding.GetSchemaForBuiltInType(Opc.Ua.BuiltInType.UInt32)); } if (_dataSetFieldContentMask.HasFlag(DataSetFieldContentFlags.ExtensionFields)) { properties.Add(nameof(PubSub.MonitoredItemMessage.ExtensionFields), new JsonSchema { Type = SchemaType.Object, AdditionalProperties = new JsonSchema { Allowed = true } }); } return Definitions.Reference(_options.GetSchemaId(name), id => new JsonSchema { Id = id, Type = SchemaType.Object, AdditionalProperties = new JsonSchema { Allowed = false }, Properties = properties }); } /// /// Get name of the type /// /// /// /// private static string GetName(string? typeName, HashSet? uniqueNames) { // Type name of the message record typeName ??= string.Empty; typeName += nameof(PubSub.MonitoredItemMessage); if (uniqueNames != null) { var uniqueName = typeName; for (var index = 1; uniqueNames.Contains(uniqueName); index++) { uniqueName = typeName + index; } uniqueNames.Add(uniqueName); typeName = uniqueName; } return typeName; } private readonly DataSetFieldContentFlags _dataSetFieldContentMask; private readonly SchemaOptions _options; private readonly bool _withDataSetMessageHeader; private readonly JsonDataSet _dataSet; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/SchemaOptions.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas { /// /// Options for the schema generation /// public record class SchemaOptions { /// /// Namespace to use as root for the schema /// public string? Namespace { get; set; } /// /// Prefer generating avro schema over json schema /// public bool? PreferAvroOverJsonSchema { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/SchemaRank.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas { /// /// Schema rank /// public enum SchemaRank { /// /// Schema is scalar /// Scalar = 0, /// /// Schema is array /// Collection = 1, /// /// Schema is matrix /// Matrix = 2, } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/SchemaUtils.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas { using Azure.IIoT.OpcUa.Publisher.Models; using Opc.Ua; using Opc.Ua.Extensions; using System; using System.Globalization; using System.Linq; using System.Text.RegularExpressions; /// /// Schema utils /// internal static partial class SchemaUtils { /// /// Namespace zero /// public const string NamespaceZeroName = "org.opcfoundation.UA"; /// /// Publisher namespace /// public const string PublisherNamespace = "org.github.microsoft.opc.publisher"; /// /// Publisher namespace uri /// public const string PublisherNamespaceUri = "http://github.org/microsoft/opcpublisher"; /// /// Safely Convert a uri to a namespace /// /// /// public static string NamespaceUriToNamespace(string ns) { if (Uri.TryCreate(ns, new UriCreationOptions { DangerousDisablePathAndQueryCanonicalization = false }, out var result)) { #pragma warning disable CA1308 // Normalize strings to uppercase return result.Host.Split('.', StringSplitOptions.RemoveEmptyEntries) .Reverse() .Where(c => c != "www") .Select(s => s.ToLowerInvariant()) .Concat(result.AbsolutePath.Split('/', StringSplitOptions.RemoveEmptyEntries)) .Select(Escape) .Aggregate((a, b) => $"{a}.{b}"); #pragma warning restore CA1308 // Normalize strings to uppercase } else { return ns.Split('/', StringSplitOptions.RemoveEmptyEntries) .Select(Escape) .Aggregate((a, b) => $"{a}.{b}"); } } /// /// Get schema rank /// /// /// public static SchemaRank GetRank(int valueRank) { switch (valueRank) { case ValueRanks.Scalar: return SchemaRank.Scalar; case ValueRanks.OneDimension: case ValueRanks.ScalarOrOneDimension: return SchemaRank.Collection; default: return SchemaRank.Matrix; } } /// /// Find index in namespace table /// /// /// /// /// /// public static bool TryFindNamespace(this NamespaceTable namespaces, string avroNamespace, out uint index, out string? namespaceUri) { if (avroNamespace == NamespaceZeroName) { namespaceUri = Namespaces.OpcUa; index = 0; return true; } for (var i = 1u; i < namespaces.Count; i++) { namespaceUri = namespaces.GetString(i); var converted = NamespaceUriToNamespace(namespaceUri); if (converted == avroNamespace) { index = i; return true; } } index = 0; namespaceUri = null; return false; } /// /// Create namespace /// /// /// /// /// public static (string Namespace, string Id) SplitNodeId(string? nodeId, IServiceMessageContext context, bool escape) { var id = nodeId.ToExpandedNodeId(context); string ns; if (id.NamespaceIndex == 0 && id.NamespaceUri == null) { ns = escape ? NamespaceZeroName : Namespaces.OpcUa; } else { ns = id.NamespaceUri; if (escape) { ns = NamespaceUriToNamespace(ns); } } var c = escape ? '_' : '='; var name = id.IdType switch { IdType.Opaque => "b", IdType.Guid => "g", IdType.String => "s", _ => "i" } + c + id.Identifier; if (escape) { name = Escape(name); } return (ns, name); } /// /// Create namespace /// /// /// /// /// public static string SplitQualifiedName(string qualifiedName, IServiceMessageContext context, string? outerNamespace = null) { var qn = qualifiedName.ToQualifiedName(context); string avroStyleNamespace; if (qn.NamespaceIndex == 0) { avroStyleNamespace = NamespaceZeroName; } else { var uri = context.NamespaceUris.GetString(qn.NamespaceIndex); avroStyleNamespace = NamespaceUriToNamespace(uri); } var name = Escape(qn.Name); if (!string.Equals(outerNamespace, avroStyleNamespace, StringComparison.OrdinalIgnoreCase)) { // Qualify if the name is in a different namespace name = $"{avroStyleNamespace}.{name}"; } return name; } /// /// Create identifier of a schema /// /// /// /// /// public static string? GetFullName(this ExpandedNodeId? typeId, string name, IServiceMessageContext context) { if (typeId == null) { return null; } if (string.IsNullOrEmpty(typeId.NamespaceUri)) { typeId = new ExpandedNodeId(typeId.Identifier, 0, Namespaces.OpcUa, 0); } var typeIdString = typeId.AsString(context, NamespaceFormat.Uri); var qn = name.ToQualifiedName(context); var ns = qn.NamespaceIndex != 0 ? context.NamespaceUris.GetString(qn.NamespaceIndex) : SplitNodeId(typeIdString, context, false).Namespace; return NamespaceUriToNamespace(ns) + "." + Escape(qn.Name); } /// /// Escape a name to only contain asciinumeric and escape /// underscore and other characters with _ and the /// ascii code of the character. /// /// /// public static string Escape(string name) { return EscapeAvroRegex().Replace(name, match => $"_x{((int)match.Value[0]).ToString(CultureInfo.InvariantCulture)}_"); } /// /// Unesacpe /// /// /// public static string Unescape(string name) { return UnescapeAvroRegex().Replace(name, match => ((char)int.Parse(match.Groups[1].ValueSpan, CultureInfo.InvariantCulture)).ToString()); } [GeneratedRegex("[^a-zA-Z0-9]")] private static partial Regex EscapeAvroRegex(); [GeneratedRegex("_x([0-9]*)_")] private static partial Regex UnescapeAvroRegex(); } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Schemas/Uadp/UadpNetworkMessage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas.Uadp { using Azure.IIoT.OpcUa.Publisher.Models; using Furly; using Furly.Extensions.Messaging; using System; using System.Linq; using System.Text.Json; /// /// Network message schema for uadp. Enables a consumer /// to decode a network message using a resolver /// public sealed class UadpNetworkMessage : IEventSchema { /// public string Type => ContentMimeType.Json; /// public string Name { get; } /// public ulong Version { get; } /// public string Id { get; } /// public string Schema { get; } /// /// Get avro schema for a writer group /// /// public UadpNetworkMessage(PublishedNetworkMessageSchemaModel networkMessage) { ArgumentNullException.ThrowIfNull(networkMessage); Schema = JsonSerializer.Serialize(networkMessage); var minor = networkMessage.DataSetMessages? .Max(dataSet => dataSet?.MetaData?.MinorVersion ?? 0) ?? 0; var major = networkMessage.DataSetMessages? .Max(dataSet => dataSet?.MetaData?.DataSetMetaData.MajorVersion ?? 0) ?? 0; Id = networkMessage.Id; Version = ((ulong)major << 32) + minor; Name = networkMessage.TypeName ?? string.Empty; } /// public override string? ToString() { return Schema; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/Utils/TypeMaps.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Utils { using Opc.Ua; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Reflection; /// /// Caches constant identifier definitions of a generated type /// public sealed class TypeMaps { /// /// Data types type map /// public static Lazy DataTypes { get; } = new Lazy(() => new TypeMaps(typeof(DataTypes)), true); /// /// Reference types type map /// public static Lazy ReferenceTypes { get; } = new Lazy(() => new TypeMaps(typeof(ReferenceTypes)), true); /// /// Object types type map /// public static Lazy ObjectTypes { get; } = new Lazy(() => new TypeMaps(typeof(ObjectTypes)), true); /// /// Attributes type map /// public static Lazy Attributes { get; } = new Lazy(() => new TypeMaps(typeof(Attributes)), true); /// /// Attributes type map /// public static Lazy StatusCodes { get; } = new Lazy(() => new TypeMaps(typeof(StatusCodes)), true); /// /// Identifiers /// public IEnumerable Identifiers => _forward.Keys; /// /// Identifiers /// public IEnumerable BrowseNames => _reverse.Keys; /// /// Initialize map /// /// private TypeMaps(Type type) { var fields = type.GetFields( BindingFlags.Public | BindingFlags.Static); foreach (var field in fields) { try { var value = (uint?)field.GetValue(type); if (value.HasValue) { _reverse.Add(field.Name, value.Value); _forward.Add(value.Value, field.Name); } } catch { continue; } } } /// /// Get browse name /// /// /// /// public bool TryGetBrowseName(uint id, [NotNullWhen(true)] out string? value) { if (_forward.TryGetValue(id, out value) && value != null) { return true; } return false; } /// /// Get identifier /// /// /// /// public bool TryGetIdentifier(string value, out uint id) { return _reverse.TryGetValue(value, out id); } private readonly SortedDictionary _forward = []; private readonly SortedDictionary _reverse = []; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/ZipFileReader.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Text; /// /// Read zip files /// public sealed class ZipFileReader : IDisposable { /// /// Read zip file /// /// public ZipFileReader(string fileName) { if (!fileName.EndsWith(ZipFileWriter.FileSuffix, StringComparison.InvariantCulture)) { fileName += ZipFileWriter.FileSuffix; } fileName = fileName.SanitizeFileName(); var stream = new FileStream(fileName, FileMode.Open); try { _zip = new ZipArchive(stream, ZipArchiveMode.Read, false); } catch (Exception ex) { stream.Dispose(); throw new FormatException("Bad zip file", ex); } try { _schema = ReadHeader(out _contentType); _suffix = ZipFileWriter.Suffix(_contentType); } catch { _zip.Dispose(); throw; } } /// /// Read from stream /// /// public ZipFileReader(Stream stream) { try { _zip = new ZipArchive(stream, ZipArchiveMode.Read, false); } catch (Exception ex) { throw new FormatException("Bad zip file", ex); } try { _schema = ReadHeader(out _contentType); _suffix = ZipFileWriter.Suffix(_contentType); } catch { _zip.Dispose(); throw; } } /// public IEnumerable Stream(Func reader) { while (HasMore()) { yield return Read(reader); } } /// public T Read(Func reader) { var entry = GetEntry(); if (entry == null) { throw new EndOfStreamException("No more entries in zip file"); } using var stream = entry.Open(); var result = reader(_schema, stream); _sequenceNumber++; return result; } private ZipArchiveEntry? GetEntry() { return _zip.GetEntry(_sequenceNumber + _suffix); } /// public bool HasMore() { return GetEntry() != null; } /// public void Dispose() { _zip.Dispose(); } /// /// Writes the schema. /// /// /// private string? ReadHeader(out ZipFileWriter.ContentType contentType) { var entry = _zip.GetEntry(ZipFileWriter.ContentTypeFile); if (entry == null || entry.Length != 1) { throw new FormatException("Not a valid zip file with stream data"); } using var contentTypeStream = entry.Open(); contentType = (ZipFileWriter.ContentType)contentTypeStream.ReadByte(); switch (contentType) { case ZipFileWriter.ContentType.Json: case ZipFileWriter.ContentType.JsonGzip: case ZipFileWriter.ContentType.Binary: break; default: throw new FormatException("Content type of zip file is invalid."); } entry = _zip.GetEntry(ZipFileWriter.MessageSchemaFile); if (entry != null) { using var schemaStream = entry.Open(); return schemaStream.ReadAsString(Encoding.UTF8); } return null; } private int _sequenceNumber = 1; private readonly ZipArchive _zip; private readonly string? _schema; private readonly string _suffix; private readonly ZipFileWriter.ContentType _contentType; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Encoders/ZipFileWriter.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Furly; using Furly.Extensions.Messaging; using Furly.Extensions.Storage; using System; using System.Buffers; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Text; using System.Threading; using System.Threading.Tasks; /// /// Write messages as zip files /// public sealed class ZipFileWriter : IFileWriter, IDisposable { /// public bool SupportsContentType(string contentType) { return GetContentType(contentType) != ContentType.None; } /// public ValueTask WriteAsync(string fileName, DateTimeOffset timestamp, IEnumerable> buffers, IReadOnlyDictionary metadata, IEventSchema? schema, string contentType, CancellationToken ct = default) { fileName = fileName.SanitizeFileName(); var file = _files.GetOrAdd(fileName + schema?.Id + contentType, _ => ZipFile.Create(fileName, schema?.Schema, GetContentType(contentType))); file.Write(timestamp, buffers); return ValueTask.CompletedTask; } /// public void Dispose() { foreach (var file in _files.Values) { file.Dispose(); } } /// /// The zip file being written /// internal sealed class ZipFile : IDisposable { /// /// Create zip file /// /// /// /// /// private ZipFile(Stream stream, string? schema, bool leaveOpen, ContentType contentType) { _zip = new ZipArchive(stream, ZipArchiveMode.Create, leaveOpen); _contentType = contentType; WriteHeader(schema, contentType); _suffix = Suffix(contentType); } /// /// Create file from file name /// /// /// /// /// public static ZipFile Create(string fileName, string? schema, ContentType contentType) { fileName = fileName.ReplaceLineEndings(); var fs = new FileStream(fileName + FileSuffix, FileMode.OpenOrCreate); return new ZipFile(fs, schema, false, contentType); } /// /// Create file from stream /// /// /// /// /// public static ZipFile CreateFromStream(Stream stream, string? schema, ContentType contentType) { return new ZipFile(stream, schema, true, contentType); } /// /// Write to file /// /// /// /// public void Write(DateTimeOffset timestamp, IEnumerable> buffers) { foreach (var buffer in buffers) { var entry = _zip.CreateEntry(Interlocked.Increment(ref _sequenceNumber) + _suffix, CompressionLevel.Optimal); entry.LastWriteTime = timestamp; using var stream = entry.Open(); foreach (var memory in _contentType == ContentType.JsonGzip ? buffer.GzipDecompress() : buffer) { stream.Write(memory.Span); } } } /// public void Dispose() { _zip.Dispose(); } /// /// Writes the schema. /// /// /// private void WriteHeader(string? schema, ContentType contentType) { if (schema is not null) { var entry = _zip.CreateEntry(MessageSchemaFile, CompressionLevel.Optimal); using var stream = entry.Open(); stream.Write(Encoding.UTF8.GetBytes(schema)); } { var entry = _zip.CreateEntry(ContentTypeFile, CompressionLevel.NoCompression); using var stream = entry.Open(); stream.WriteByte((byte)contentType); } } private int _sequenceNumber; private readonly string _suffix; private readonly ZipArchive _zip; private readonly ContentType _contentType; } internal enum ContentType { None, Json, JsonGzip, Binary } /// /// Return type /// /// /// internal static ContentType GetContentType(string contentType) { #pragma warning disable CA1308 // Normalize strings to uppercase switch (contentType.ToLowerInvariant()) { case Encoders.ContentType.JsonGzip: return ContentType.JsonGzip; case ContentMimeType.Json: case Encoders.ContentType.UaJson: case Encoders.ContentType.UaLegacyPublisher: case Encoders.ContentType.UaNonReversibleJson: return ContentType.Json; case ContentMimeType.Binary: case Encoders.ContentType.Uadp: return ContentType.Binary; } #pragma warning restore CA1308 // Normalize strings to uppercase return ContentType.None; } /// /// Get suffix for content type /// /// /// /// internal static string Suffix(ContentType contentType) { return contentType switch { ContentType.Json or ContentType.JsonGzip => ".json", ContentType.Binary => ".bin", _ => throw new FormatException("Invalid content type") }; } internal const string FileSuffix = ".zip"; internal const string MessageSchemaFile = "schema.json"; internal const string ContentTypeFile = "content-type"; private readonly ConcurrentDictionary _files = new(); } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Exceptions/ConnectionException.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Exceptions { using System; using System.IO; /// /// Thrown when failing to connect to resource /// public class ConnectionException : IOException { /// public ConnectionException(string message) : base(message) { } /// public ConnectionException(string message, Exception innerException) : base(message, innerException) { } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Exceptions/ServerBusyException.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Exceptions { using Furly.Exceptions; using System; /// /// Thrown when failing to connect to resource /// public class ServerBusyException : ExternalDependencyException { /// public ServerBusyException(string message) : base(message) { } /// public ServerBusyException(string message, Exception innerException) : base(message, innerException) { } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Extensions/LinqEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace System.Linq { using System.Collections; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; /// /// Enumerable extensions /// public static class LinqEx2 { /// /// Merge enumerable b into set a. /// /// /// /// /// [return: NotNullIfNotNull(nameof(a))] public static IReadOnlySet? MergeWith(this IReadOnlySet? a, IEnumerable? b) { if (b?.Any() ?? false) { if (a == null) { return b.ToHashSetSafe(); } return a.Concat(b).ToHashSet(); } return a; } /// /// Creates a hash set from enumerable or null if enumerable is null. /// /// /// /// [return: NotNullIfNotNull(nameof(enumerable))] public static HashSet? ToHashSetSafe(this IEnumerable? enumerable) { if (enumerable == null) { return null; } return new HashSet(enumerable); } /// /// Flattens a enumerable of enumerables /// /// /// public static IEnumerable Flatten(this IEnumerable obj) { foreach (var item in obj) { if (item is IEnumerable contained) { contained = contained.Flatten(); foreach (var cont in contained) { yield return cont; } yield break; } yield return item; } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Extensions/StreamEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace System.IO { using System.Text; /// /// Stream extensions /// public static class StreamEx { /// /// Helper extension to convert an entire stream into a string... /// /// /// /// public static string ReadAsString(this Stream stream, Encoding encoder) { // Try to read as much as possible var buffer = stream.ReadAsBuffer(); if (buffer.Array == null) { return string.Empty; } return encoder.GetString(buffer.Array, 0, buffer.Count); } /// /// Helper extension to convert an entire stream into a buffer... /// /// /// public static ArraySegment ReadAsBuffer(this Stream stream) { // Try to read as much as possible var body = new byte[1024]; var offset = 0; try { while (true) { var read = stream.Read(body, offset, body.Length - offset); if (read <= 0) { break; } offset += read; if (offset == body.Length) { // Grow var newbuf = new byte[body.Length * 2]; Buffer.BlockCopy(body, 0, newbuf, 0, body.Length); body = newbuf; } } } catch (IOException) { } return new ArraySegment(body, 0, offset); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Extensions/StringEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace System { using System.Security.Cryptography; using System.Text; /// /// String helper extensions /// public static class StringEx { /// /// Hashes the string /// /// string to hash /// public static string ToSha1Hash(this string str) { return Encoding.UTF8.GetBytes(str).ToSha1Hash(); } /// /// Hashes the string /// /// string to hash /// [Diagnostics.CodeAnalysis.SuppressMessage("Security", "CA5350:Do Not Use Weak Cryptographic Algorithms", Justification = "SHA1 not used for crypto operation.")] public static string ToSha1Hash(this byte[] bytestr) { var hash = SHA1.HashData(bytestr); return hash.ToBase16String(false); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Extensions/TimerEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa { using System; using System.Diagnostics; using System.Threading; /// /// Timer expired event argument /// public class ElapsedEventArgs : EventArgs { /// /// Signal time /// public DateTimeOffset SignalTime { get; } internal ElapsedEventArgs(DateTimeOffset localTime) { SignalTime = localTime; } } /// /// Handles recurring events in an application. This is a simplfied /// version of the System.Timers.Timer class but uses a TimeProvider /// provided ITimer instead of the default System.Threading.Timer. /// public sealed class TimerEx : IDisposable { /// /// Gets or sets a value indicating whether the Timer raises /// the Tick event each time the specified Interval has elapsed, /// when Enabled is set to true. /// public bool AutoReset { get => _autoReset; set { if (_autoReset != value) { _autoReset = value; if (_timer != null) { UpdateTimer(); } } } } /// /// Gets or sets a value indicating whether the Timer /// is able to raise events at a defined interval. /// The default value by design is false, don't change it. /// public bool Enabled { get => _enabled; set { if (_enabled != value) { if (!value) { if (_timer != null) { _cookie = null; _timer.Dispose(); _timer = null; } _enabled = value; } else { _enabled = value; if (_timer == null) { ObjectDisposedException.ThrowIf(_disposed, this); _cookie = new object(); _timer = _timeProvider.CreateTimer(_callback, _cookie, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); _timer.Change(_interval, _autoReset ? _interval : Timeout.InfiniteTimeSpan); } else { UpdateTimer(); } } } } } /// /// Create new timer /// /// public TimerEx(TimeProvider? timeProvider = null) { _interval = Timeout.InfiniteTimeSpan; _enabled = false; _autoReset = true; _timeProvider = timeProvider ?? TimeProvider.System; _callback = new TimerCallback(MyTimerCallback); } /// /// Create timer with interval /// /// /// The time between events. The value in milliseconds must be greater /// than zero and less than or equal to . /// /// public TimerEx(TimeSpan interval, TimeProvider? timeProvider = null) : this(timeProvider) { _interval = interval; } /// public void Dispose() { Close(); _disposed = true; } private void UpdateTimer() { Debug.Assert(_timer != null, $"{nameof(_timer)} was expected not to be null"); _timer.Change(_interval, _autoReset ? _interval : Timeout.InfiniteTimeSpan); } /// /// Gets or sets the interval on which to raise events. /// /// public TimeSpan Interval { get => _interval; set { if (value <= TimeSpan.Zero) { throw new ArgumentException("Bad interval"); } _interval = value; if (_timer != null) { UpdateTimer(); } } } /// /// Occurs when the Interval> has elapsed. /// public event EventHandler Elapsed { add => _onIntervalElapsed += value; remove => _onIntervalElapsed -= value; } /// /// Closes the current timer object. /// public void Close() { _enabled = false; if (_timer != null) { _timer.Dispose(); _timer = null; } } /// /// Starts the timing by setting Enabled property. /// public void Start() { Enabled = true; } /// /// Stops the timing by setting the Enabled property. /// public void Stop() { Enabled = false; } private void MyTimerCallback(object? state) { // System.Threading.Timer will not cancel the work item queued before the timer is stopped. // We don't want to handle the callback after a timer is stopped. if (state != _cookie) { return; } if (!_autoReset) { _enabled = false; } var elapsedEventArgs = new ElapsedEventArgs(_timeProvider.GetUtcNow()); try { // To avoid race between remove handler and raising the event _onIntervalElapsed?.Invoke(this, elapsedEventArgs); } catch { // Silently eat user exception } } private TimeSpan _interval; private bool _enabled; private readonly TimeProvider _timeProvider; private EventHandler? _onIntervalElapsed; private bool _autoReset; private bool _disposed; private ITimer? _timer; private readonly TimerCallback _callback; private object? _cookie; } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/IMetricsContext.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa { using System.Diagnostics; /// /// Metrics context /// public interface IMetricsContext { /// /// Tag list /// TagList TagList { get; } /// /// Null metrics context /// public static IMetricsContext Empty { get; } = new EmptyContext(); /// /// Empty context /// private sealed class EmptyContext : IMetricsContext { /// public TagList TagList { get; } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Properties/AssemblyInfo.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Azure.IIoT.OpcUa.Tests")] ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Diagnostics.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using System.Diagnostics; using System.Diagnostics.Metrics; /// /// Industrial iot diagnostics /// public sealed class Diagnostics : IMeterFactory { /// /// Version /// public const string Version = "2.9"; /// /// namespace /// public const string Namespace = "Azure.Industrial-IoT"; /// /// Metrics /// public static readonly Meter Meter = NewMeter(); /// /// Metrics /// public static Meter NewMeter() { return new(Namespace, Version); } /// /// Tracing /// public static ActivitySource NewActivitySource() { return new(Namespace, Version); } /// public Meter Create(MeterOptions options) { return Diagnostics.NewMeter(); } /// public void Dispose() { } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/AggregateConfigurationModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { /// /// Aggregate configuration model extensions /// public static class AggregateConfigurationModelEx { /// /// Compare filters /// /// /// /// public static bool IsSameAs(this AggregateConfigurationModel? model, AggregateConfigurationModel? other) { if (ReferenceEquals(model, other)) { return true; } if (model is null || other is null) { return false; } if (model.PercentDataBad != other.PercentDataBad) { return false; } if (model.PercentDataGood != other.PercentDataGood) { return false; } if (model.TreatUncertainAsBad != other.TreatUncertainAsBad) { return false; } if (model.UseSlopedExtrapolation != other.UseSlopedExtrapolation) { return false; } return true; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/AggregateFilterModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { /// /// Aggregate filter model extensions /// public static class AggregateFilterModelEx { /// /// Compare filters /// /// /// /// public static bool IsSameAs(this AggregateFilterModel? model, AggregateFilterModel? other) { if (ReferenceEquals(model, other)) { return true; } if (model is null || other is null) { return false; } if (model.AggregateTypeId != other.AggregateTypeId) { return false; } if (model.ProcessingInterval != other.ProcessingInterval) { return false; } if (model.StartTime != other.StartTime) { return false; } if (!model.AggregateConfiguration.IsSameAs(other.AggregateConfiguration)) { return false; } return true; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/ApplicationInfoModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Diagnostics.CodeAnalysis; /// /// Service model extensions for discovery service /// public static class ApplicationInfoModelEx { /// /// Create unique application id /// /// /// /// /// [return: NotNullIfNotNull(nameof(applicationUri))] public static string? CreateApplicationId(string? siteOrGatewayId, string? applicationUri, ApplicationType? applicationType) { if (string.IsNullOrEmpty(applicationUri)) { return null; } #pragma warning disable CA1308 // Normalize strings to uppercase applicationUri = applicationUri.ToLowerInvariant(); #pragma warning restore CA1308 // Normalize strings to uppercase var type = applicationType ?? ApplicationType.Server; var id = $"{siteOrGatewayId ?? ""}-{type}-{applicationUri}"; var prefix = applicationType == ApplicationType.Client ? "uac" : "uas"; return prefix + id.ToSha1Hash(); } /// /// Equality comparison /// /// /// /// public static bool IsSameAs(this ApplicationInfoModel? model, ApplicationInfoModel? that) { if (ReferenceEquals(model, that)) { return true; } if (model is null || that is null) { return false; } return StringComparer.OrdinalIgnoreCase.Equals(that.ApplicationUri, model.ApplicationUri) && that.ApplicationType == model.ApplicationType; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/ApplicationRegistrationModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Azure.IIoT.OpcUa.Publisher.Models; using System.Collections.Generic; using System.Linq; /// /// Service model extensions for discovery service /// public static class ApplicationRegistrationModelEx { /// /// Add or update a server list /// /// /// public static void AddOrUpdate(this List discovered, ApplicationRegistrationModel server) { var actual = discovered .Find(s => s.Application.IsSameAs(server.Application)); if (actual != null) { // Merge server info actual.UnionWith(server); } else { discovered.Add(server); } } /// /// Create Union with server /// /// /// public static void UnionWith(this ApplicationRegistrationModel model, ApplicationRegistrationModel server) { if (model.Application == null) { model.Application = server.Application; } else { model.Application.Capabilities = model.Application.Capabilities.MergeWith( server?.Application?.Capabilities); model.Application.DiscoveryUrls = model.Application.DiscoveryUrls.MergeWith( server?.Application?.DiscoveryUrls); model.Application.HostAddresses = model.Application.HostAddresses.MergeWith( server?.Application?.HostAddresses); } if (server?.Endpoints?.Any() ?? false) { if (model.Endpoints == null) { model.Endpoints = server.Endpoints; } else { foreach (var ep in server.Endpoints) { var found = model.Endpoints.Where(ep.IsSameAs).ToList(); if (found.Count == 0) { model.Endpoints = model.Endpoints.Append(ep).ToList(); } foreach (var existing in found) { if (existing.Endpoint == null) { existing.Endpoint = ep.Endpoint; continue; } existing.Endpoint?.UnionWith(ep.Endpoint); } } } } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/AuthenticationMethodModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Furly.Extensions.Serializers; using System.Collections.Generic; using System.Linq; /// /// Authentication method model extensions /// public static class AuthenticationMethodModelEx { /// /// Equality comparison /// /// /// /// public static bool IsSameAs(this IReadOnlyList? model, IReadOnlyList? that) { if (ReferenceEquals(model, that)) { return true; } if (model is null || that is null) { return false; } if (model.Count != that.Count) { return false; } foreach (var a in model) { if (!that.Any(b => b.IsSameAs(a))) { return false; } } return true; } /// /// Equality comparison /// /// /// /// public static bool IsSameAs(this AuthenticationMethodModel? model, AuthenticationMethodModel? that) { if (ReferenceEquals(model, that)) { return true; } if (model is null || that is null) { return false; } if (model.Configuration != null && that.Configuration != null && !VariantValue.DeepEquals(model.Configuration, that.Configuration)) { return false; } return model.Id == that.Id && model.SecurityPolicy == that.SecurityPolicy && model.CredentialType == that.CredentialType; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/ConditionHandlingOptionsModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Diagnostics.CodeAnalysis; /// /// Condition options extensions /// public static class ConditionHandlingOptionsModelEx { /// /// Clone /// /// /// [return: NotNullIfNotNull(nameof(model))] public static ConditionHandlingOptionsModel? Clone(this ConditionHandlingOptionsModel? model) { return model == null ? null : (model with { }); } /// /// Check if models are equal /// /// /// public static bool IsSameAs(this ConditionHandlingOptionsModel? model, ConditionHandlingOptionsModel? that) { if (ReferenceEquals(model, that)) { return true; } if (model is null || that is null) { return false; } if (model.SnapshotInterval != that.SnapshotInterval) { return false; } if (model.UpdateInterval != that.UpdateInterval) { return false; } return true; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/ConnectionModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; /// /// Connection endpoint model extensions /// public static class ConnectionModelEx { /// /// Equality comparison /// /// /// /// public static bool IsSameAs(this ConnectionModel? model, ConnectionModel? that) { if (ReferenceEquals(model, that)) { return true; } if (model is null || that is null) { return false; } if (that.Group != model.Group) { return false; } if (that.Options != model.Options) { return false; } if (!that.Endpoint.IsSameAs(model.Endpoint)) { return false; } if (that.Diagnostics?.AuditId != model.Diagnostics?.AuditId) { return false; } if (!that.User.IsSameAs(model.User)) { return false; } if (!that.Locales.SequenceEqualsSafe(model.Locales)) { return false; } return true; } /// /// Is this reverse connected /// /// /// public static bool IsReverseConnect(this ConnectionModel connection) { return connection.Options.HasFlag(ConnectionOptions.UseReverseConnect) && connection.GetEndpointUrls().Any(); } /// /// Get endpont urls to try from connection /// /// /// public static IEnumerable GetEndpointUrls(this ConnectionModel connection) { if (connection.Endpoint?.Url == null) { return []; } var endpoints = new Uri(connection.Endpoint.Url).YieldReturn(); if (connection.Endpoint.AlternativeUrls != null) { endpoints = endpoints.Concat(connection.Endpoint.AlternativeUrls .Where(u => !string.IsNullOrEmpty(u)) .Select(u => new Uri(u))); } return endpoints.Where(u => !connection.Options.HasFlag(ConnectionOptions.UseReverseConnect) || string.Equals(u.Scheme, "opc.tcp", // Only allow tcp scheme StringComparison.OrdinalIgnoreCase)); } /// /// Create unique hash /// /// /// public static int CreateConsistentHash(this ConnectionModel model) { var hashCode = HashCode.Combine( model.Endpoint?.CreateConsistentHash() ?? 0, model.User ?? new CredentialModel(), model.Diagnostics?.AuditId ?? string.Empty, model.Group ?? string.Empty, model.Options); foreach (var l in model.Locales ?? Enumerable.Empty()) { hashCode = HashCode.Combine(hashCode, l); } return hashCode; } /// /// Clone /// /// /// [return: NotNullIfNotNull(nameof(model))] public static ConnectionModel? Clone(this ConnectionModel? model) { return model == null ? null : (model with { Endpoint = model.Endpoint.Clone(), User = model.User.Clone(), Diagnostics = model.Diagnostics.Clone() }); } /// /// Returns a string that uniquiely identifies the connection based on /// endpoint url, hash and associated group /// /// public static string? CreateConnectionId(this ConnectionModel? model) { if (string.IsNullOrEmpty(model?.Endpoint?.Url)) { return null; } return !string.IsNullOrEmpty(model.Group) ? $"{model.Endpoint?.Url}_{CreateConsistentHash(model):X8}_{model.Group}" : $"{model.Endpoint?.Url}_{CreateConsistentHash(model):X8}"; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/ContentFilterElementModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; /// /// Content filter element extensions /// public static class ContentFilterElementModelEx { /// /// Clone /// /// /// [return: NotNullIfNotNull(nameof(model))] public static ContentFilterElementModel? Clone(this ContentFilterElementModel? model) { return model == null ? null : (model with { FilterOperands = model.FilterOperands? .Select(f => f.Clone()) .ToList() }); } /// /// Compare elements /// /// /// /// public static bool IsSameAs(this ContentFilterElementModel? model, ContentFilterElementModel? other) { if (ReferenceEquals(model, other)) { return true; } if (model is null || other is null) { return false; } if (model.FilterOperator != other.FilterOperator) { return false; } if (!model.FilterOperands.SetEqualsSafe(other.FilterOperands, (x, y) => x.IsSameAs(y))) { return false; } return true; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/ContentFilterModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; /// /// Content filter extensions /// public static class ContentFilterModelEx { /// /// Clone /// /// /// [return: NotNullIfNotNull(nameof(model))] public static ContentFilterModel? Clone(this ContentFilterModel? model) { return model == null ? null : (model with { Elements = model.Elements? .Select(e => e.Clone()) .ToList() }); } /// /// Compare operands /// /// /// /// public static bool IsSameAs(this ContentFilterModel? model, ContentFilterModel? other) { if (ReferenceEquals(model, other)) { return true; } if (model is null || other is null) { return false; } if (!model.Elements.SetEqualsSafe(other.Elements, (x, y) => x.IsSameAs(y))) { return false; } return true; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/CredentialModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Diagnostics.CodeAnalysis; /// /// Credential model extensions /// public static class CredentialModelEx { /// /// Get password /// /// /// public static string? GetPassword(this CredentialModel? model) { if (model?.Type == CredentialType.UserName && model.Value != null) { return model.Value.Password; } return null; } /// /// Get user name /// /// /// public static string? GetUserName(this CredentialModel? model) { if (model?.Type == CredentialType.UserName && model.Value != null) { return model.Value.User; } return null; } /// /// Equality comparison /// /// /// /// public static bool IsSameAs(this CredentialModel? model, CredentialModel? that) { if (ReferenceEquals(model, that)) { return true; } model ??= new CredentialModel(); that ??= new CredentialModel(); if (that.Type != model.Type) { return false; } if (!that.Value.IsSameAs(model.Value)) { return false; } return true; } /// /// Deep clone /// /// /// [return: NotNullIfNotNull(nameof(model))] public static CredentialModel? Clone(this CredentialModel? model) { return model == null ? null : (model with { Value = model.Value.Clone() }); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/DataChangeFilterModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { /// /// Data change filter model extensions /// public static class DataChangeFilterModelEx { /// /// Compare filters /// /// /// /// public static bool IsSameAs(this DataChangeFilterModel? model, DataChangeFilterModel? other) { if (ReferenceEquals(model, other)) { return true; } if (model is null || other is null) { return false; } // // Null is default and equals to StatusValue, but we allow StatusValue == 1 // to be set specifically to enable a user to force a data filter to be // applied (otherwise it is not if nothing else is set) // if (model.DataChangeTrigger != other.DataChangeTrigger) { return false; } // Null is None == no deadband if (model.DeadbandType != other.DeadbandType) { return false; } if (model.DeadbandValue != other.DeadbandValue) { return false; } return true; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/DataSetMetaDataModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Diagnostics.CodeAnalysis; /// /// Dataset metadata extensions /// public static class DataSetMetaDataModelEx { /// /// Clone /// /// /// [return: NotNullIfNotNull(nameof(model))] public static DataSetMetaDataModel? Clone(this DataSetMetaDataModel? model) { return model == null ? null : (model with { }); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/DataSetWriterModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Diagnostics.CodeAnalysis; /// /// Dataset writer model ex /// public static class DataSetWriterModelEx { /// /// Clone /// /// /// [return: NotNullIfNotNull(nameof(model))] public static DataSetWriterModel? Clone(this DataSetWriterModel? model) { return model == null ? null : (model with { DataSet = model.DataSet.Clone(), MessageSettings = model.MessageSettings.Clone() }); } /// /// Clone /// /// /// [return: NotNullIfNotNull(nameof(model))] private static DataSetWriterMessageSettingsModel? Clone(this DataSetWriterMessageSettingsModel? model) { return model == null ? null : (model with { }); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/DiagnosticsModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Diagnostics.CodeAnalysis; /// /// Diagnostics model extensions /// public static class DiagnosticsModelEx { /// /// Clone /// /// /// [return: NotNullIfNotNull(nameof(model))] public static DiagnosticsModel? Clone(this DiagnosticsModel? model) { return model == null ? null : (model with { }); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/DiscoveryConfigModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Diagnostics.CodeAnalysis; using System.Linq; /// /// Discovery configuration model extensions /// public static class DiscoveryConfigModelEx { /// /// Clone /// /// /// [return: NotNullIfNotNull(nameof(model))] public static DiscoveryConfigModel? Clone(this DiscoveryConfigModel? model) { return model == null ? null : (model with { DiscoveryUrls = model.DiscoveryUrls?.Count > 0 ? model.DiscoveryUrls.ToList() : null, Locales = model.Locales?.Count > 0 ? model.Locales.ToList() : null, PortRangesToScan = string.IsNullOrEmpty(model.PortRangesToScan) ? null : model.PortRangesToScan, AddressRangesToScan = string.IsNullOrEmpty(model.AddressRangesToScan) ? null : model.AddressRangesToScan, IdleTimeBetweenScans = model.IdleTimeBetweenScans < TimeSpan.Zero ? null : model.IdleTimeBetweenScans, MaxNetworkProbes = model.MaxNetworkProbes <= 0 ? null : model.MaxNetworkProbes, MaxPortProbes = model.MaxPortProbes <= 0 ? null : model.MaxPortProbes, MinPortProbesPercent = model.MinPortProbesPercent <= 0 ? null : model.MinPortProbesPercent, NetworkProbeTimeout = model.NetworkProbeTimeout <= TimeSpan.Zero ? null : model.NetworkProbeTimeout, PortProbeTimeout = model.PortProbeTimeout <= TimeSpan.Zero ? null : model.PortProbeTimeout }); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/DiscoveryRequestModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Diagnostics.CodeAnalysis; /// /// Discovery request model extensions /// public static class DiscoveryRequestModelEx { /// /// Clone /// /// /// /// [return: NotNullIfNotNull(nameof(model))] public static DiscoveryRequestModel? Clone(this DiscoveryRequestModel? model, TimeProvider timeProvider) { return model == null ? null : (model with { Configuration = model.Configuration.Clone(), Context = model.Context?.Clone(timeProvider) }); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/EndpointModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; /// /// Endpoint model extensions /// public static class EndpointModelEx { /// /// Equality comparison /// /// /// /// public static bool IsSameAs(this EndpointModel? model, EndpointModel? that) { if (ReferenceEquals(model, that)) { return true; } if (model is null || that is null) { return false; } if (!that.HasSameSecurityProperties(model)) { return false; } if (!that.GetAllUrls().SequenceEqualsSafe(model.GetAllUrls())) { return false; } return true; } /// /// Equality comparison /// /// /// /// public static bool HasSameSecurityProperties(this EndpointModel? model, EndpointModel? that) { if (ReferenceEquals(model, that)) { return true; } if (model is null || that is null) { return false; } if (!that.Certificate.SequenceEqualsSafe(model.Certificate)) { return false; } if (that.SecurityPolicy != model.SecurityPolicy && that.SecurityPolicy != null && model.SecurityPolicy != null) { return false; } if ((that.SecurityMode ?? SecurityMode.NotNone) != (model.SecurityMode ?? SecurityMode.NotNone)) { return false; } return true; } /// /// Create unique hash /// /// /// public static int CreateConsistentHash(this EndpointModel endpoint) { var hashCode = -1971667340; hashCode = (hashCode * -1521134295) + endpoint.GetAllUrls().SequenceGetHashSafe(); hashCode = (hashCode * -1521134295) + endpoint.Certificate.SequenceGetHashSafe(); hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode( endpoint.SecurityPolicy ?? string.Empty); hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode( endpoint.SecurityMode ?? SecurityMode.NotNone); return hashCode; } /// /// Get all urls /// /// /// public static IEnumerable GetAllUrls(this EndpointModel? model) { if (model != null) { if (model.Url != null) { yield return model.Url; } if (model.AlternativeUrls != null) { foreach (var url in model.AlternativeUrls) { yield return url; } } } } /// /// Create Union with endpoint /// /// /// public static void UnionWith(this EndpointModel model, EndpointModel? endpoint) { if (endpoint == null) { return; } var alternativeUrls = model.AlternativeUrls.MergeWith( endpoint.AlternativeUrls)?.ToHashSet() ?? []; if (model.Url != null) { if (endpoint.Url != null) { alternativeUrls.Add(endpoint.Url); } alternativeUrls.Remove(model.Url); } else { model.Url = endpoint.Url; } model.AlternativeUrls = alternativeUrls; } /// /// Deep clone /// /// /// [return: NotNullIfNotNull(nameof(model))] public static EndpointModel? Clone(this EndpointModel? model) { return model == null ? null : (model with { AlternativeUrls = model.AlternativeUrls.ToHashSetSafe() }); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/EndpointRegistrationModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { /// /// Service model extensions for discovery service /// public static class EndpointRegistrationModelEx { /// /// Equality comparison /// /// /// /// public static bool IsSameAs(this EndpointRegistrationModel? model, EndpointRegistrationModel? that) { if (ReferenceEquals(model, that)) { return true; } if (model is null || that is null) { return false; } if (!model.Endpoint.HasSameSecurityProperties(that.Endpoint)) { return false; } if (!model.AuthenticationMethods.IsSameAs(that.AuthenticationMethods)) { return false; } return model.EndpointUrl == that.EndpointUrl && model.SiteId == that.SiteId && model.DiscovererId == that.DiscovererId && model.SecurityLevel == that.SecurityLevel; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/EventFilterModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; /// /// Event filter extensions /// public static class EventFilterModelEx { /// /// Compare filters /// /// /// /// public static bool IsSameAs(this EventFilterModel? model, EventFilterModel? other) { if (ReferenceEquals(model, other)) { return true; } if (model is null || other is null) { return false; } if (!model.SelectClauses.SetEqualsSafe(other.SelectClauses, (x, y) => x.IsSameAs(y))) { return false; } if (!model.WhereClause.IsSameAs(other.WhereClause)) { return false; } if (model.TypeDefinitionId != other.TypeDefinitionId) { return false; } return true; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/FileSystemServicesEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Models; using System.Diagnostics; using System.IO; using System.Threading; using System.Threading.Tasks; /// /// File system services extensions /// public static class FileSystemServicesEx { /// /// Copy from server to provided stream (e.g. file) /// /// /// /// /// /// /// /// public static async Task CopyToAsync(this IFileSystemServices service, T endpoint, FileSystemObjectModel file, Stream stream, CancellationToken ct = default) { var open = await service.OpenReadAsync(endpoint, file, ct).ConfigureAwait(false); if (open.ErrorInfo != null) { Debug.Assert(open.Result == null); return open.ErrorInfo; } Debug.Assert(open.Result != null); await using (var _ = open.Result.ConfigureAwait(false)) { await open.Result.CopyToAsync(stream, ct).ConfigureAwait(false); } return new ServiceResultModel(); } /// /// Copy from stream (e.g. file) to file on server /// /// /// /// /// /// /// /// /// public static async Task CopyFromAsync(this IFileSystemServices service, T endpoint, FileSystemObjectModel file, Stream stream, FileOpenWriteOptionsModel? options = null, CancellationToken ct = default) { var open = await service.OpenWriteAsync(endpoint, file, options, ct).ConfigureAwait(false); if (open.ErrorInfo != null) { Debug.Assert(open.Result == null); return open.ErrorInfo; } Debug.Assert(open.Result != null); await using (var _ = open.Result.ConfigureAwait(false)) { await stream.CopyToAsync(open.Result, ct).ConfigureAwait(false); } return new ServiceResultModel(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/FilterOperandModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Furly.Extensions.Serializers; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; /// /// Content filter element extensions /// public static class FilterOperandModelEx { /// /// Clone /// /// /// [return: NotNullIfNotNull(nameof(model))] public static FilterOperandModel? Clone(this FilterOperandModel? model) { return model == null ? null : (model with { }); } /// /// Compare operands /// /// /// /// public static bool IsSameAs(this FilterOperandModel? model, FilterOperandModel? other) { if (ReferenceEquals(model, other)) { return true; } if (model is null || other is null) { return false; } if (model.AttributeId != other.AttributeId) { return false; } if (model.Index != other.Index) { return false; } if (!VariantValue.DeepEquals(model.Value, other.Value)) { return false; } if (!model.BrowsePath.SequenceEqualsSafe(other.BrowsePath)) { return false; } if (model.IndexRange != other.IndexRange) { return false; } if (model.NodeId != other.NodeId) { return false; } return true; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/ModelChangeHandlingOptionsModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Diagnostics.CodeAnalysis; /// /// Published model change items extensions /// public static class ModelChangeHandlingOptionsModelEx { /// /// Clone /// /// /// [return: NotNullIfNotNull(nameof(model))] public static ModelChangeHandlingOptionsModel? Clone(this ModelChangeHandlingOptionsModel? model) { return model == null ? null : (model with { }); } /// /// Check if models are equal /// /// /// public static bool IsSameAs(this ModelChangeHandlingOptionsModel? model, ModelChangeHandlingOptionsModel? that) { if (ReferenceEquals(model, that)) { return true; } if (model is null || that is null) { return false; } if (model.RebrowseIntervalTimespan != that.RebrowseIntervalTimespan) { return false; } return true; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/NodeServicesEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Extensions.Utils; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; /// /// Node services extensions /// public static class NodeServicesEx { /// /// Browse all references if max references is null and user /// wants all. If user has requested maximum to return use /// /// /// /// /// /// /// /// /// public static async Task BrowseAsync( this INodeServices service, T connection, BrowseFirstRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(service); ArgumentNullException.ThrowIfNull(request); if (request.MaxReferencesToReturn != null) { return await service.BrowseFirstAsync(connection, request, ct).ConfigureAwait(false); } var result = await service.BrowseFirstAsync(connection, request, ct).ConfigureAwait(false); var references = new List(); if (result.References != null) { references.AddRange(result.References); } var continuationToken = result.ContinuationToken; while (continuationToken != null) { try { var next = await service.BrowseNextAsync(connection, new BrowseNextRequestModel { ContinuationToken = continuationToken, Header = request.Header, NodeIdsOnly = request.NodeIdsOnly, ReadVariableValues = request.ReadVariableValues, TargetNodesOnly = request.TargetNodesOnly }, ct).ConfigureAwait(false); if (next.References != null) { references.AddRange(next.References); } continuationToken = next.ContinuationToken; } catch (Exception) when (continuationToken != null) { await Try.Async(() => service.BrowseNextAsync(connection, new BrowseNextRequestModel { ContinuationToken = continuationToken, Abort = true })).ConfigureAwait(false); throw; } } return result with { References = references, ContinuationToken = null }; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/OpcNodeModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Config.Models { using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Extensions.Messaging; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; /// /// Dataset source extensions /// public static class OpcNodeModelEx { /// /// Get comparer class for OpcNodeModel objects. /// public static EqualityComparer Comparer { get; } = new OpcNodeModelComparer(); /// /// Try get the id element of the node /// /// /// /// public static bool TryGetId(this OpcNodeModel node, [NotNullWhen(true)] out string? id) { id = !string.IsNullOrWhiteSpace(node.Id) ? node.Id : !string.IsNullOrWhiteSpace(node.ExpandedNodeId) ? node.ExpandedNodeId : node.BrowsePath?.Count > 0 ? Opc.Ua.ObjectIds.RootFolder.ToString() : node.ModelChangeHandling != null ? Opc.Ua.ObjectIds.Server.ToString() : null; return id != null; } /// /// Check if nodes are equal /// /// /// /// public static bool IsSame(this OpcNodeModel? model, OpcNodeModel? that, bool includeTriggeredNodes = true) { if (ReferenceEquals(model, that)) { return true; } if (model is null || that is null) { return false; } if (!string.Equals(model.Id ?? string.Empty, that.Id ?? string.Empty, StringComparison.OrdinalIgnoreCase)) { return false; } if (!string.Equals(model.DisplayName ?? string.Empty, that.DisplayName ?? string.Empty, StringComparison.OrdinalIgnoreCase)) { return false; } if (!string.Equals(model.Topic ?? string.Empty, that.Topic ?? string.Empty, StringComparison.OrdinalIgnoreCase)) { return false; } if ((model.QualityOfService ?? QoS.AtLeastOnce) != (that.QualityOfService ?? QoS.AtLeastOnce)) { return false; } if (!string.Equals(model.DataSetFieldId ?? string.Empty, that.DataSetFieldId ?? string.Empty, StringComparison.OrdinalIgnoreCase)) { return false; } if (model.DataSetClassFieldId != that.DataSetClassFieldId) { return false; } if (!string.Equals(model.ExpandedNodeId, that.ExpandedNodeId, StringComparison.OrdinalIgnoreCase)) { return false; } if (model.GetNormalizedPublishingInterval() != that.GetNormalizedPublishingInterval()) { return false; } if (model.GetNormalizedSamplingInterval() != that.GetNormalizedSamplingInterval()) { return false; } if (model.GetNormalizedHeartbeatInterval() != that.GetNormalizedHeartbeatInterval()) { return false; } if ((model.HeartbeatBehavior ?? HeartbeatBehavior.WatchdogLKV) != (that.HeartbeatBehavior ?? HeartbeatBehavior.WatchdogLKV)) { return false; } if ((model.SkipFirst ?? false) != (that.SkipFirst ?? false)) { return false; } if ((model.DiscardNew ?? false) != (that.DiscardNew ?? false)) { return false; } if (model.QueueSize != that.QueueSize) { return false; } // // Null is default and equals to StatusValue, but we allow StatusValue == 1 // to be set specifically to enable a user to force a data filter to be // applied (otherwise it is not if nothing else is set) // if (model.DataChangeTrigger != that.DataChangeTrigger) { return false; } // Null is None == no deadband if (model.DeadbandType != that.DeadbandType) { return false; } if (model.DeadbandValue != that.DeadbandValue) { return false; } if (!model.EventFilter.IsSameAs(that.EventFilter)) { return false; } if (!model.ModelChangeHandling.IsSameAs(that.ModelChangeHandling)) { return false; } if (!model.ConditionHandling.IsSameAs(that.ConditionHandling)) { return false; } if ((model.UseCyclicRead ?? false) != (that.UseCyclicRead ?? false)) { return false; } if (model.GetNormalizedCyclicReadMaxAge() != that.GetNormalizedCyclicReadMaxAge()) { return false; } if ((model.RegisterNode ?? false) != (that.RegisterNode ?? false)) { return false; } if (includeTriggeredNodes && model.TriggeredNodes?.SetEqualsSafe(that.TriggeredNodes, (a, b) => a.IsSame(b, false)) == false) { return false; } return true; } /// /// Returns the hashcode for a node /// /// /// public static int GetHashCode(this OpcNodeModel model, bool includeTriggerNodes = true) { var hash = new HashCode(); hash.Add(model.Id); hash.Add(model.DisplayName); hash.Add(model.DataSetFieldId); hash.Add(model.DataSetClassFieldId); hash.Add(model.ExpandedNodeId); hash.Add(model.QualityOfService); hash.Add(model.Topic); hash.Add(model.GetNormalizedPublishingInterval()); hash.Add(model.GetNormalizedSamplingInterval()); hash.Add(model.GetNormalizedHeartbeatInterval()); hash.Add(model.HeartbeatBehavior ?? HeartbeatBehavior.WatchdogLKV); hash.Add(model.SkipFirst ?? false); hash.Add(model.DiscardNew ?? false); hash.Add(model.QueueSize); if (model.DataChangeTrigger == null) { // // Null is default and equals to StatusValue, but we allow StatusValue == 1 // to be set specifically to enable a user to force a data filter to be // applied (otherwise it is not if nothing else is set) // hash.Add(-1); } else { hash.Add(model.DataChangeTrigger); } hash.Add(model.DeadbandValue); if (model.DeadbandType == null) { // Null is None == no deadband hash.Add(-1); } else { hash.Add(model.DeadbandType); } hash.Add(model.ModelChangeHandling?.RebrowseIntervalTimespan); hash.Add(model.ConditionHandling?.UpdateInterval); hash.Add(model.ConditionHandling?.SnapshotInterval); hash.Add(model.UseCyclicRead); hash.Add(model.GetNormalizedCyclicReadMaxAge()); hash.Add(model.RegisterNode); if (includeTriggerNodes) { model.TriggeredNodes?.ForEach(n => hash.Add(GetHashCode(n, false))); } return hash.ToHashCode(); } /// /// Retrieves the timespan flavor of a node's HeartbeatInterval /// /// /// /// public static TimeSpan? GetNormalizedHeartbeatInterval( this OpcNodeModel model, TimeSpan? defaultHeatbeatTimespan = null) { return model.HeartbeatIntervalTimespan .GetTimeSpanFromSeconds(model.HeartbeatInterval, defaultHeatbeatTimespan); } /// /// Retrieves the timespan flavor of a node's PublishingInterval /// /// /// public static TimeSpan? GetNormalizedPublishingInterval( this OpcNodeModel model, TimeSpan? defaultPublishingTimespan = null) { return model.OpcPublishingIntervalTimespan .GetTimeSpanFromMiliseconds(model.OpcPublishingInterval, defaultPublishingTimespan); } /// /// Retrieves the timespan flavor of a node's SamplingInterval /// /// /// public static TimeSpan? GetNormalizedSamplingInterval( this OpcNodeModel model, TimeSpan? defaultSamplingTimespan = null) { return model.OpcSamplingIntervalTimespan .GetTimeSpanFromMiliseconds(model.OpcSamplingInterval, defaultSamplingTimespan); } /// /// Retrieves the timespan flavor of a node's CyclicReadMaxAge /// /// /// public static TimeSpan? GetNormalizedCyclicReadMaxAge( this OpcNodeModel model, TimeSpan? defaultCyclicReadMaxAgeTimespan = null) { return model.CyclicReadMaxAgeTimespan .GetTimeSpanFromMiliseconds(model.CyclicReadMaxAge, defaultCyclicReadMaxAgeTimespan); } /// /// Returns a the timespan value from the timespan when defined, respectively from /// the seconds representing integer. The Timespan value wins when provided /// /// /// /// public static TimeSpan? GetTimeSpanFromSeconds( this TimeSpan? timespan, int? seconds, TimeSpan? defaultTimespan = null) { return timespan ?? (seconds.HasValue ? TimeSpan.FromSeconds(seconds.Value) : defaultTimespan); } /// /// Returns a the timespan value from the timespan when defined, respectively from /// the miliseconds representing integer. The Timespan value wins when provided /// /// /// /// public static TimeSpan? GetTimeSpanFromMiliseconds( this TimeSpan? timespan, int? miliseconds, TimeSpan? defaultTimespan = null) { return timespan ?? (miliseconds.HasValue ? TimeSpan.FromMilliseconds(miliseconds.Value) : defaultTimespan); } /// /// Equality comparer for OpcNodeModel objects. /// private class OpcNodeModelComparer : EqualityComparer { /// public override bool Equals(OpcNodeModel? node1, OpcNodeModel? node2) { return node1.IsSame(node2); } /// public override int GetHashCode(OpcNodeModel node) { return OpcNodeModelEx.GetHashCode(node); } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/PublishedDataItemsModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Diagnostics.CodeAnalysis; using System.Linq; /// /// Data items extensions /// public static class PublishedDataItemsModelEx { /// /// Clone /// /// /// [return: NotNullIfNotNull(nameof(model))] public static PublishedDataItemsModel? Clone(this PublishedDataItemsModel? model) { return model == null ? null : (model with { PublishedData = model.PublishedData?.Select(d => d.Clone()).ToList() }); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/PublishedDataSetEventModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Diagnostics.CodeAnalysis; using System.Linq; /// /// Events extensions /// public static class PublishedDataSetEventModelEx { /// /// Clone /// /// /// [return: NotNullIfNotNull(nameof(model))] public static PublishedDataSetEventModel? Clone(this PublishedDataSetEventModel? model) { return model == null ? null : (model with { Filter = model.Filter.Clone(), Triggering = model.Triggering.Clone(), SelectedFields = model.SelectedFields? .Select(f => f.Clone()) .ToList(), ConditionHandling = model.ConditionHandling.Clone() }); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/PublishedDataSetModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Diagnostics.CodeAnalysis; /// /// Published dataset extensions /// public static class PublishedDataSetModelEx { /// /// Clone /// /// /// [return: NotNullIfNotNull(nameof(model))] public static PublishedDataSetModel? Clone(this PublishedDataSetModel? model) { return model == null ? null : (model with { DataSetMetaData = model.DataSetMetaData.Clone(), DataSetSource = model.DataSetSource.Clone(), }); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/PublishedDataSetSettingsModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { /// /// Settings extensions /// public static class PublishedDataSetSettingsModelEx { /// /// Clone /// /// /// public static PublishedDataSetSettingsModel? Clone(this PublishedDataSetSettingsModel? model) { return model == null ? null : (model with { }); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/PublishedDataSetSourceModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Diagnostics.CodeAnalysis; /// /// Dataset source extensions /// public static class PublishedDataSetSourceModelEx { /// /// Clone /// /// /// [return: NotNullIfNotNull(nameof(model))] public static PublishedDataSetSourceModel? Clone(this PublishedDataSetSourceModel? model) { return model == null ? null : (model with { PublishedEvents = model.PublishedEvents.Clone(), PublishedVariables = model.PublishedVariables.Clone(), Connection = model.Connection.Clone(), SubscriptionSettings = model.SubscriptionSettings.Clone() }); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/PublishedDataSetTriggerModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Diagnostics.CodeAnalysis; /// /// trigger models extensions /// public static class PublishedDataSetTriggerModelEx { /// /// Clone /// /// /// [return: NotNullIfNotNull(nameof(model))] public static PublishedDataSetTriggerModel? Clone(this PublishedDataSetTriggerModel? model) { return model == null ? null : (model with { PublishedVariables = model.PublishedVariables.Clone(), PublishedEvents = model.PublishedEvents.Clone() }); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/PublishedDataSetVariableModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Diagnostics.CodeAnalysis; /// /// Events extensions /// public static class PublishedDataSetVariableModelEx { /// /// Clone /// /// /// [return: NotNullIfNotNull(nameof(model))] public static PublishedDataSetVariableModel? Clone(this PublishedDataSetVariableModel? model) { return model == null ? null : (model with { Triggering = model.Triggering.Clone(), SubstituteValue = model.SubstituteValue?.Copy() }); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/PublishedEventItemsModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Diagnostics.CodeAnalysis; using System.Linq; /// /// Data items extensions /// public static class PublishedEventItemsModelEx { /// /// Clone /// /// /// [return: NotNullIfNotNull(nameof(model))] public static PublishedEventItemsModel? Clone(this PublishedEventItemsModel? model) { return model == null ? null : (model with { PublishedData = model.PublishedData?.Select(d => d.Clone()).ToList() }); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/PublishedNodesEntryModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Config.Models { using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Text; /// /// PublishedNodesEntryModel extensions /// public static class PublishedNodesEntryModelEx { /// /// Get unique identifier for the group /// /// /// public static string GetUniqueWriterGroupId(this PublishedNodesEntryModel model) { var id = new StringBuilder(); if (!string.IsNullOrEmpty(model.PublisherId)) { id.Append(model.PublisherId); } if (!string.IsNullOrEmpty(model.DataSetWriterGroup)) { id.Append(model.DataSetWriterGroup); } if (!string.IsNullOrEmpty(model.WriterGroupRootNodeId)) { id.Append(model.WriterGroupRootNodeId); } if (!string.IsNullOrEmpty(model.WriterGroupType)) { id.Append(model.WriterGroupType); } if (model.WriterGroupTransport != null) { id.Append(model.WriterGroupTransport); } if (!string.IsNullOrEmpty(model.WriterGroupTransportConfiguration)) { id.Append(model.WriterGroupTransportConfiguration); } if (model.WriterGroupQualityOfService != null) { id.Append(model.WriterGroupQualityOfService.Value); } if (!string.IsNullOrEmpty(model.WriterGroupQueueName)) { id.Append(model.WriterGroupQueueName); } if (model.MessageEncoding != null) { id.Append(model.MessageEncoding.Value); } if (model.MessagingMode != null) { id.Append(model.MessagingMode.Value); } if (model.BatchSize != null) { id.Append(model.BatchSize.Value); } var batchTriggerInterval = model.GetNormalizedBatchTriggerInterval(); if (batchTriggerInterval != null) { id.Append(batchTriggerInterval.Value.TotalMilliseconds); } if (model.WriterGroupPartitions != null) { id.Append(model.WriterGroupPartitions.Value); } if (model.WriterGroupMessageTtlTimepan != null) { id.Append(model.WriterGroupMessageTtlTimepan.Value); } if (model.WriterGroupMessageRetention == true) { id.AppendLine(); } return id.ToString().ToSha1Hash(); } /// /// Validates if the entry has same group as the model /// /// /// public static bool HasSameWriterGroup(this PublishedNodesEntryModel model, PublishedNodesEntryModel that) { if (ReferenceEquals(model, that)) { return true; } if (!string.Equals(model.PublisherId ?? string.Empty, that.PublisherId ?? string.Empty, StringComparison.Ordinal)) { return false; } if (!string.Equals(model.DataSetWriterGroup, that.DataSetWriterGroup, StringComparison.Ordinal)) { return false; } if (!string.Equals(model.WriterGroupType ?? string.Empty, that.WriterGroupType ?? string.Empty, StringComparison.Ordinal)) { return false; } if (!string.Equals(model.WriterGroupRootNodeId ?? string.Empty, that.WriterGroupRootNodeId ?? string.Empty, StringComparison.Ordinal)) { return false; } if (model.WriterGroupTransport != that.WriterGroupTransport) { return false; } if (!string.Equals(model.WriterGroupTransportConfiguration ?? string.Empty, that.WriterGroupTransportConfiguration ?? string.Empty, StringComparison.Ordinal)) { return false; } if (model.WriterGroupQualityOfService != that.WriterGroupQualityOfService) { return false; } if (!string.Equals(model.WriterGroupQueueName ?? string.Empty, that.WriterGroupQueueName ?? string.Empty, StringComparison.Ordinal)) { return false; } if (model.MessageEncoding != that.MessageEncoding) { return false; } if (model.MessagingMode != that.MessagingMode) { return false; } if (model.BatchSize != that.BatchSize) { return false; } if (model.GetNormalizedBatchTriggerInterval() != that.GetNormalizedBatchTriggerInterval()) { return false; } if (model.WriterGroupPartitions != that.WriterGroupPartitions) { return false; } if (model.WriterGroupMessageRetention != that.WriterGroupMessageRetention) { return false; } if (model.WriterGroupMessageTtlTimepan != that.WriterGroupMessageTtlTimepan) { return false; } return true; } /// /// Create connection from entry /// /// /// /// public static ConnectionModel ToConnectionModel(this PublishedNodesEntryModel entry, Func? credential = null) { credential ??= e => e.ToCredentialModel(); return new ConnectionModel { Options = (entry.UseReverseConnect == true ? ConnectionOptions.UseReverseConnect : ConnectionOptions.None) | (entry.DisableSubscriptionTransfer == true ? ConnectionOptions.NoSubscriptionTransfer : ConnectionOptions.None) | (entry.DumpConnectionDiagnostics == true ? ConnectionOptions.DumpDiagnostics : ConnectionOptions.None), Endpoint = new EndpointModel { Url = entry.EndpointUrl, SecurityPolicy = entry.EndpointSecurityPolicy, SecurityMode = entry.EndpointSecurityMode ?? ((entry.UseSecurity ?? false) ? // Default for backcompat is no security SecurityMode.NotNone : SecurityMode.None) }, User = entry.OpcAuthenticationMode == OpcAuthenticationMode.UsernamePassword || entry.OpcAuthenticationMode == OpcAuthenticationMode.Certificate ? credential(entry) : null }; } /// /// Create a new published nodes entry model. This is used only for the legacy /// API to start, stop, bulk and list nodes. If the connection model uses the /// group field it is used as writer group identifier. /// /// /// [return: NotNullIfNotNull(nameof(model))] public static PublishedNodesEntryModel? ToPublishedNodesEntry(this ConnectionModel model) { if (model?.Endpoint is null) { return null; } var useSecurity = model.Endpoint.SecurityMode == SecurityMode.None ? false : model.Endpoint.SecurityMode == SecurityMode.NotNone ? true : (bool?)null; return new PublishedNodesEntryModel { EndpointUrl = model.Endpoint.Url, UseSecurity = useSecurity, EndpointSecurityMode = !useSecurity.HasValue ? model.Endpoint.SecurityMode : null, EndpointSecurityPolicy = model.Endpoint.SecurityPolicy, OpcAuthenticationMode = ToOpcAuthenticationMode(model.User?.Type), OpcAuthenticationPassword = model.User.GetPassword(), OpcAuthenticationUsername = model.User.GetUserName(), DataSetWriterGroup = model.Group, UseReverseConnect = model.Options.HasFlag(ConnectionOptions.UseReverseConnect) ? true : null, DisableSubscriptionTransfer = model.Options.HasFlag(ConnectionOptions.NoSubscriptionTransfer) ? true : null, MessageEncoding = MessageEncoding.Json, MessagingMode = MessagingMode.FullSamples, OpcNodes = [] }; } /// /// Convert to mode /// /// /// internal static OpcAuthenticationMode ToOpcAuthenticationMode(this CredentialType? type) { switch (type) { case CredentialType.UserName: return OpcAuthenticationMode.UsernamePassword; case CredentialType.X509Certificate: return OpcAuthenticationMode.Certificate; default: return OpcAuthenticationMode.Anonymous; } } /// /// Convert to credential model /// /// /// internal static CredentialModel ToCredentialModel(this PublishedNodesEntryModel entry) { switch (entry.OpcAuthenticationMode) { case OpcAuthenticationMode.UsernamePassword: case OpcAuthenticationMode.Certificate: var user = entry.OpcAuthenticationUsername ?? string.Empty; var password = entry.OpcAuthenticationPassword ?? string.Empty; if ((!string.IsNullOrEmpty(entry.EncryptedAuthUsername) && string.IsNullOrEmpty(user)) || (!string.IsNullOrEmpty(entry.EncryptedAuthPassword) && string.IsNullOrEmpty(password))) { throw new NotSupportedException("No crypto provider to decrypt encrypted username."); } return new CredentialModel { Type = entry.OpcAuthenticationMode == OpcAuthenticationMode.Certificate ? CredentialType.X509Certificate : CredentialType.UserName, Value = new UserIdentityModel { User = user, Password = password } }; } return new CredentialModel { Type = CredentialType.None }; } /// /// Return a cloaked published nodes entry that can be used as lookup input to /// /// /// /// [return: NotNullIfNotNull(nameof(model))] public static PublishedNodesEntryModel? ToDataSetEntry(this PublishedNodesEntryModel? model) { if (model is null) { return null; } return model with { NodeId = null, EncryptedAuthPassword = null, OpcAuthenticationPassword = null, OpcNodes = null }; } /// /// Get a unique data set writer id from the entry model. Excludes the /// writer group which is assumed be scoping this id already. /// /// /// /// public static string GetUniqueDataSetWriterId(this PublishedNodesEntryModel model, TimeSpan? publishingInterval = null) { var id = new StringBuilder(); if (!string.IsNullOrEmpty(model.DataSetWriterId)) { id.Append(model.DataSetWriterId); } if (!string.IsNullOrEmpty(model.EndpointUrl)) { id.Append(model.EndpointUrl); } if (model.UseReverseConnect == true) { id.AppendLine(); } if (model.DisableSubscriptionTransfer == true) { id.AppendLine(); } var securityMode = model.EndpointSecurityMode ?? ((model.UseSecurity ?? false) ? SecurityMode.NotNone : SecurityMode.None); if (securityMode != SecurityMode.None) { id.Append(securityMode); } if (!string.IsNullOrEmpty(model.EndpointSecurityPolicy)) { id.Append(model.EndpointSecurityPolicy); } if (model.OpcAuthenticationMode != OpcAuthenticationMode.Anonymous) { id.Append(model.OpcAuthenticationMode); } if (!string.IsNullOrEmpty(model.OpcAuthenticationUsername)) { id.Append(model.OpcAuthenticationUsername); } if (!string.IsNullOrEmpty(model.OpcAuthenticationPassword)) { id.Append(model.OpcAuthenticationPassword.ToSha1Hash()); } if (!string.IsNullOrEmpty(model.EncryptedAuthUsername)) { id.Append(model.EncryptedAuthUsername); } if (!string.IsNullOrEmpty(model.EncryptedAuthPassword)) { id.Append(model.EncryptedAuthPassword.ToSha1Hash()); } if (!string.IsNullOrEmpty(model.DataSetName)) { id.Append(model.DataSetName); } var publishingIntervalResolved = publishingInterval ?? model.GetNormalizedDataSetPublishingInterval(); if (publishingIntervalResolved != null) { id.Append(publishingIntervalResolved.Value.TotalMilliseconds); } if (model.DataSetClassId != Guid.Empty) { id.Append(model.DataSetClassId); } if (model.DataSetKeyFrameCount != null) { id.Append(model.DataSetKeyFrameCount.Value); } if (model.DataSetType != null) { id.Append(model.DataSetType); } if (model.DataSetRootNodeId != null) { id.Append(model.DataSetRootNodeId); } if (model.DisableSubscriptionTransfer != null) { id.Append(model.DisableSubscriptionTransfer.Value); } if (model.SendKeepAliveDataSetMessages == true) { id.AppendLine(); } if (model.SendKeepAliveAsKeyFrameMessages == true) { id.AppendLine(); } if (model.Priority != null) { id.Append(model.Priority.Value); } if (model.MaxKeepAliveCount != null) { id.Append(model.MaxKeepAliveCount.Value); } var metadataUpdateTime = model.GetNormalizedMetaDataUpdateTime(); if (metadataUpdateTime != null) { id.Append(metadataUpdateTime.Value.TotalMilliseconds); } var samplingInterval = model.GetNormalizedDataSetSamplingInterval(); if (samplingInterval != null) { id.Append(samplingInterval.Value.TotalMilliseconds); } var heartbeatInterval = model.GetNormalizedDefaultHeartbeatInterval(); if (heartbeatInterval != null) { id.Append(heartbeatInterval.Value.TotalMilliseconds); } if (model.DefaultHeartbeatBehavior != null) { id.Append(model.DefaultHeartbeatBehavior.Value); } if (model.QualityOfService != null) { id.Append(model.QualityOfService.Value); } if (!string.IsNullOrEmpty(model.QueueName)) { id.Append(model.QueueName); } if (!string.IsNullOrEmpty(model.MetaDataQueueName)) { id.Append(model.MetaDataQueueName); } if ((model.DataSetRouting ?? DataSetRoutingMode.None) != DataSetRoutingMode.None) { id.Append(model.DataSetRouting.ToString()); } if (model.RepublishAfterTransfer != null) { id.Append(model.RepublishAfterTransfer.Value); } if (model.OpcNodeWatchdogTimespan != null) { id.Append(model.OpcNodeWatchdogTimespan.Value); } if (model.DataSetWriterWatchdogBehavior != null) { id.Append(model.DataSetWriterWatchdogBehavior.Value); } if (model.OpcNodeWatchdogCondition != null) { id.Append(model.OpcNodeWatchdogCondition.Value); } if (model.DataSetFetchDisplayNames != null) { id.Append(model.DataSetFetchDisplayNames.Value); } if (model.MessageTtlTimespan != null) { id.Append(model.MessageTtlTimespan.Value); } if (model.MessageRetention == true) { id.AppendLine(); } if (!string.IsNullOrEmpty(model.DataSetSourceUri)) { id.Append(model.DataSetSourceUri); } if (!string.IsNullOrEmpty(model.DataSetSubject)) { id.Append(model.DataSetSubject); } Debug.Assert(id.Length != 0); // Should always have an endpoint mixed in return id.ToString().ToSha1Hash(); } /// /// Validates if the entry has same data set definition as the model. /// Comarison excludes OpcNodes and publishing intervals. /// /// /// public static bool HasSameDataSet(this PublishedNodesEntryModel model, PublishedNodesEntryModel that) { if (!model.HasSameWriterGroup(that)) { return false; } if (model.EndpointUrl != that.EndpointUrl) { return false; } if ((model.UseReverseConnect ?? false) != (that.UseReverseConnect ?? false)) { return false; } if ((model.DisableSubscriptionTransfer ?? false) != (that.DisableSubscriptionTransfer ?? false)) { return false; } if ((model.UseSecurity ?? false) != (that.UseSecurity ?? false)) { return false; } if ((model.EndpointSecurityMode ?? ((model.UseSecurity ?? false) ? SecurityMode.NotNone : SecurityMode.None)) != (that.EndpointSecurityMode ?? ((that.UseSecurity ?? false) ? SecurityMode.NotNone : SecurityMode.None))) { return false; } if (model.EndpointSecurityPolicy != that.EndpointSecurityPolicy) { return false; } if (model.OpcAuthenticationMode != that.OpcAuthenticationMode) { return false; } if (!string.Equals(model.OpcAuthenticationUsername ?? string.Empty, that.OpcAuthenticationUsername ?? string.Empty, StringComparison.Ordinal)) { return false; } if (!string.Equals(model.OpcAuthenticationPassword ?? string.Empty, that.OpcAuthenticationPassword ?? string.Empty, StringComparison.Ordinal)) { return false; } if (!string.Equals(model.EncryptedAuthUsername ?? string.Empty, that.EncryptedAuthUsername ?? string.Empty, StringComparison.Ordinal)) { return false; } if (!string.Equals(model.EncryptedAuthPassword ?? string.Empty, that.EncryptedAuthPassword ?? string.Empty, StringComparison.Ordinal)) { return false; } if (model.MaxKeepAliveCount != that.MaxKeepAliveCount) { return false; } if (!string.Equals(model.DataSetWriterId ?? string.Empty, that.DataSetWriterId ?? string.Empty, StringComparison.Ordinal)) { return false; } if (!string.Equals(model.DataSetName ?? string.Empty, that.DataSetName ?? string.Empty, StringComparison.Ordinal)) { return false; } if (!string.Equals(model.DataSetType ?? string.Empty, that.DataSetType ?? string.Empty, StringComparison.Ordinal)) { return false; } if (!string.Equals(model.DataSetRootNodeId ?? string.Empty, that.DataSetRootNodeId ?? string.Empty, StringComparison.Ordinal)) { return false; } if (!string.Equals(model.DataSetSourceUri ?? string.Empty, that.DataSetSourceUri ?? string.Empty, StringComparison.Ordinal)) { return false; } if (!string.Equals(model.DataSetSubject ?? string.Empty, that.DataSetSubject ?? string.Empty, StringComparison.Ordinal)) { return false; } if (model.DataSetClassId != that.DataSetClassId) { return false; } if (model.DataSetKeyFrameCount != that.DataSetKeyFrameCount) { return false; } if (model.DisableSubscriptionTransfer != that.DisableSubscriptionTransfer) { return false; } if ((model.SendKeepAliveDataSetMessages ?? false) != (that.SendKeepAliveDataSetMessages ?? false)) { return false; } if ((model.SendKeepAliveAsKeyFrameMessages ?? false) != (that.SendKeepAliveAsKeyFrameMessages ?? false)) { return false; } if (model.Priority != that.Priority) { return false; } if (model.GetNormalizedMetaDataUpdateTime() != that.GetNormalizedMetaDataUpdateTime()) { return false; } if (model.GetNormalizedDataSetSamplingInterval() != that.GetNormalizedDataSetSamplingInterval()) { return false; } if (model.GetNormalizedDefaultHeartbeatInterval() != that.GetNormalizedDefaultHeartbeatInterval()) { return false; } if (model.DefaultHeartbeatBehavior != that.DefaultHeartbeatBehavior) { return false; } if (model.QualityOfService != that.QualityOfService) { return false; } if (!string.Equals(model.QueueName ?? string.Empty, that.QueueName ?? string.Empty, StringComparison.Ordinal)) { return false; } if (!string.Equals(model.MetaDataQueueName ?? string.Empty, that.MetaDataQueueName ?? string.Empty, StringComparison.Ordinal)) { return false; } if ((model.DataSetRouting ?? DataSetRoutingMode.None) != (that.DataSetRouting ?? DataSetRoutingMode.None)) { return false; } if (model.RepublishAfterTransfer != that.RepublishAfterTransfer) { return false; } if (model.OpcNodeWatchdogTimespan != that.OpcNodeWatchdogTimespan) { return false; } if (model.DataSetWriterWatchdogBehavior != that.DataSetWriterWatchdogBehavior) { return false; } if (model.OpcNodeWatchdogCondition != that.OpcNodeWatchdogCondition) { return false; } if (model.DataSetFetchDisplayNames != that.DataSetFetchDisplayNames) { return false; } if (model.MessageRetention != that.MessageRetention) { return false; } if (model.MessageTtlTimespan != that.MessageTtlTimespan) { return false; } return true; } /// /// Retrieves the timespan flavor of a PublishedNodesEntryModel's MetaDataUpdateTime /// /// public static TimeSpan? GetNormalizedMetaDataUpdateTime( this PublishedNodesEntryModel model) { return model.MetaDataUpdateTimeTimespan .GetTimeSpanFromMiliseconds(model.MetaDataUpdateTime); } /// /// Retrieves the timespan flavor of a PublishedNodesEntryModel's BatchTriggerInterval /// /// public static TimeSpan? GetNormalizedBatchTriggerInterval( this PublishedNodesEntryModel model) { return model.BatchTriggerIntervalTimespan .GetTimeSpanFromMiliseconds(model.BatchTriggerInterval); } /// /// Retrieves the timespan flavor of a PublishedNodesEntryModel's SamplingInterval /// /// public static TimeSpan? GetNormalizedDataSetSamplingInterval( this PublishedNodesEntryModel model) { return model.DataSetSamplingIntervalTimespan .GetTimeSpanFromMiliseconds(model.DataSetSamplingInterval); } /// /// Retrieves the timespan flavor of a PublishedNodesEntryModel's DefaultHeartbeatInterval /// /// public static TimeSpan? GetNormalizedDefaultHeartbeatInterval( this PublishedNodesEntryModel model) { return model.DefaultHeartbeatIntervalTimespan .GetTimeSpanFromMiliseconds(model.DefaultHeartbeatInterval); } /// /// Retrieves the timespan flavor of a PublishedNodesEntryModel's DataSetPublishingInterval /// /// /// public static TimeSpan? GetNormalizedDataSetPublishingInterval( this PublishedNodesEntryModel model, TimeSpan? defaultPublishingTimespan = null) { return model.DataSetPublishingIntervalTimespan .GetTimeSpanFromMiliseconds(model.DataSetPublishingInterval, defaultPublishingTimespan); } /// /// Promote the default publishing interval of the model to all of /// its nodes to support apples to apples comparison. /// /// public static PublishedNodesEntryModel PropagatePublishingIntervalToNodes( this PublishedNodesEntryModel model) { if (model.OpcNodes != null && model.OpcNodes.Count != 0) { var rootInterval = model.GetNormalizedDataSetPublishingInterval(); if (rootInterval == null) { return model; } foreach (var node in model.OpcNodes) { var nodeInterval = node.GetNormalizedPublishingInterval(); if (nodeInterval == null) { // Set publishing interval from root node.OpcPublishingIntervalTimespan = rootInterval; } } } // Remove root interval model.DataSetPublishingInterval = null; model.DataSetPublishingIntervalTimespan = null; return model; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/RegistryOperationContextModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; /// /// Operation extensions /// public static class RegistryOperationContextModelEx { /// /// Clone /// /// /// /// public static OperationContextModel? Clone( this OperationContextModel? model, TimeProvider timeProvider) { model = model.Validate(timeProvider); return new OperationContextModel { AuthorityId = model.AuthorityId, Time = model.Time }; } /// /// Clone /// /// /// /// public static OperationContextModel Validate( this OperationContextModel? context, TimeProvider timeProvider) { if (context == null) { context = new OperationContextModel { AuthorityId = null, // Should throw if configured Time = timeProvider.GetUtcNow() }; } return context; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/SimpleAttributeOperandModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; /// /// Attribute operand extensions /// public static class SimpleAttributeOperandModelEx { /// /// Clone /// /// /// [return: NotNullIfNotNull(nameof(model))] public static SimpleAttributeOperandModel? Clone(this SimpleAttributeOperandModel? model) { return model == null ? null : (model with { }); } /// /// Compare operands /// /// /// /// public static bool IsSameAs(this SimpleAttributeOperandModel? model, SimpleAttributeOperandModel? other) { if (ReferenceEquals(model, other)) { return true; } if (model is null || other is null) { return false; } if (model.AttributeId != other.AttributeId) { return false; } if (!model.BrowsePath.SequenceEqualsSafe(other.BrowsePath)) { return false; } if (model.IndexRange != other.IndexRange) { return false; } if (model.TypeDefinitionId != other.TypeDefinitionId) { return false; } if (model.DisplayName != other.DisplayName) { return false; } if (model.DataSetClassFieldId != other.DataSetClassFieldId) { return false; } return true; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/UserIdentityModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Diagnostics.CodeAnalysis; /// /// User Identity model extensions /// public static class UserIdentityModelEx { /// /// Equality comparison /// /// /// /// public static bool IsSameAs(this UserIdentityModel? model, UserIdentityModel? that) { if (ReferenceEquals(model, that)) { return true; } model ??= new UserIdentityModel(); that ??= new UserIdentityModel(); if ((that.User ?? string.Empty) != (model.User ?? string.Empty)) { return false; } if ((that.Password ?? string.Empty) != (model.Password ?? string.Empty)) { return false; } if ((that.Thumbprint ?? string.Empty) != (model.Thumbprint ?? string.Empty)) { return false; } return true; } /// /// Deep clone /// /// /// [return: NotNullIfNotNull(nameof(model))] public static UserIdentityModel? Clone(this UserIdentityModel? model) { return model == null ? null : (model with { }); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/X509CertificateChainModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Collections.Generic; using System.Security.Cryptography.X509Certificates; /// /// Certificate Chain extensions /// public static class X509CertificateChainModelEx { /// /// Convert raw buffer to certificate chain /// /// /// public static X509CertificateChainModel ToCertificateChain( this byte[] rawCertificates) { var certificates = new List(); try { while (true) { var cur = X509CertificateLoader.LoadCertificate(rawCertificates); certificates.Add(cur); if (cur.RawData.Length >= rawCertificates.Length) { break; } rawCertificates = rawCertificates.AsSpan()[cur.RawData.Length..] .ToArray(); } return new X509CertificateChainModel { Chain = certificates .ConvertAll(c => c.ToServiceModel()) }; } finally { certificates.ForEach(c => c.Dispose()); } } /// /// Gets the leaf thumprint /// /// /// public static string? ToThumbprint(this byte[] rawCertificates) { try { var chain = rawCertificates.ToCertificateChain()?.Chain; if (chain?.Count > 0) { return chain[chain.Count - 1]?.Thumbprint; } return null; } catch { // Fall back to sha1 which was the previous thumprint algorithm return rawCertificates.ToSha1Hash(); } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Extensions/X509CertificateModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Security.Cryptography.X509Certificates; /// /// Certificate extension /// public static class X509CertificateModelEx { /// /// To service model /// /// /// public static X509CertificateModel ToServiceModel(this X509Certificate2 cert) { return new X509CertificateModel { Pfx = cert.Export(X509ContentType.Pfx), NotAfterUtc = cert.NotAfter, NotBeforeUtc = cert.NotBefore, SerialNumber = cert.GetSerialNumberString(), Subject = cert.Subject, HasPrivateKey = cert.HasPrivateKey, Thumbprint = cert.Thumbprint, SelfSigned = IsSelfIssued(cert) ? true : null }; } /// /// Test self issued - no validation is done on signature. /// /// /// private static bool IsSelfIssued(this X509Certificate2 cert) { return cert.IssuerName.RawData .SequenceEqualsSafe(cert.SubjectName.RawData); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/ICertificateServices.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Models; using System.Threading; using System.Threading.Tasks; /// /// Get endpoint certificate /// /// public interface ICertificateServices { /// /// Get endpoint certificate /// /// Server endpoint to talk to /// /// Task GetEndpointCertificateAsync( T endpoint, CancellationToken ct = default); } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/IConnectionServices.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Models; using System.Threading; using System.Threading.Tasks; /// /// Connection services /// /// public interface IConnectionServices { /// /// Test connection /// /// /// /// /// Task TestConnectionAsync(T endpoint, TestConnectionRequestModel request, CancellationToken ct = default); } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/IFileSystemServices.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Models; using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; /// /// File system services expose services as per the file transfer specification /// https://reference.opcfoundation.org/Core/Part20/v105/docs/#4.3.3. /// /// public interface IFileSystemServices { /// /// Get all file systems on the server /// /// /// /// IAsyncEnumerable> GetFileSystemsAsync( T endpoint, CancellationToken ct = default); /// /// Get all directories under a filesystem or directory /// /// /// /// /// Task>> GetDirectoriesAsync( T endpoint, FileSystemObjectModel fileSystemOrDirectory, CancellationToken ct = default); /// /// Get all files in a directory or filesystem /// /// /// /// /// Task>> GetFilesAsync( T endpoint, FileSystemObjectModel fileSystemOrDirectory, CancellationToken ct = default); /// /// Get parent directory or filesystem /// /// /// /// /// Task> GetParentAsync(T endpoint, FileSystemObjectModel fileOrDirectoryObject, CancellationToken ct = default); /// /// Get file information for a file /// /// /// /// /// Task> GetFileInfoAsync(T endpoint, FileSystemObjectModel file, CancellationToken ct = default); /// /// Opens the file for reading. Closing the stream will close the file. /// /// /// /// /// Task> OpenReadAsync(T endpoint, FileSystemObjectModel file, CancellationToken ct = default); /// /// Opens the file for writing, closing the stream will close the file. /// Optionally options can be provided to control the write mode and /// alternative close methods to use. /// /// /// /// /// /// Task> OpenWriteAsync(T endpoint, FileSystemObjectModel file, FileOpenWriteOptionsModel? options = null, CancellationToken ct = default); /// /// Create parent directory under a file system or directory. /// /// /// /// /// /// Task> CreateDirectoryAsync(T endpoint, FileSystemObjectModel fileSystemOrDirectory, string name, CancellationToken ct = default); /// /// Create a file in the directory /// /// /// /// /// /// Task> CreateFileAsync(T endpoint, FileSystemObjectModel fileSystemOrDirectory, string name, CancellationToken ct = default); /// /// Delete a file or directory with the name from the directory /// or filesystem. If the name is omitted the object is itself /// deleted from its parent object. /// /// /// /// /// /// Task DeleteFileSystemObjectAsync(T endpoint, FileSystemObjectModel fileOrDirectoryObject, FileSystemObjectModel? parentFileSystemOrDirectory = null, CancellationToken ct = default); } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/IHistoryServices.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Models; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; /// /// Historian services /// /// public interface IHistoryServices { /// /// Replace events /// /// Server endpoint to talk to /// /// /// Task HistoryReplaceEventsAsync(T endpoint, HistoryUpdateRequestModel request, CancellationToken ct = default); /// /// Insert events /// /// Server endpoint to talk to /// /// /// Task HistoryInsertEventsAsync(T endpoint, HistoryUpdateRequestModel request, CancellationToken ct = default); /// /// Update or replace events /// /// Server endpoint to talk to /// /// /// Task HistoryUpsertEventsAsync(T endpoint, HistoryUpdateRequestModel request, CancellationToken ct = default); /// /// Delete events /// /// Server endpoint to talk to /// /// /// Task HistoryDeleteEventsAsync(T endpoint, HistoryUpdateRequestModel request, CancellationToken ct = default); /// /// Delete values at specified times /// /// Server endpoint to talk to /// /// /// Task HistoryDeleteValuesAtTimesAsync(T endpoint, HistoryUpdateRequestModel request, CancellationToken ct = default); /// /// Delete modified values /// /// Server endpoint to talk to /// /// /// Task HistoryDeleteModifiedValuesAsync(T endpoint, HistoryUpdateRequestModel request, CancellationToken ct = default); /// /// Delete values /// /// Server endpoint to talk to /// /// /// Task HistoryDeleteValuesAsync(T endpoint, HistoryUpdateRequestModel request, CancellationToken ct = default); /// /// Replace values /// /// Server endpoint to talk to /// /// /// Task HistoryReplaceValuesAsync(T endpoint, HistoryUpdateRequestModel request, CancellationToken ct = default); /// /// Insert values /// /// Server endpoint to talk to /// /// /// Task HistoryInsertValuesAsync(T endpoint, HistoryUpdateRequestModel request, CancellationToken ct = default); /// /// Update or replace values /// /// Server endpoint to talk to /// /// /// Task HistoryUpsertValuesAsync(T endpoint, HistoryUpdateRequestModel request, CancellationToken ct = default); /// /// Read historic events /// /// Server endpoint to talk to /// /// /// Task> HistoryReadEventsAsync( T endpoint, HistoryReadRequestModel request, CancellationToken ct = default); /// /// Read next set of events /// /// Server endpoint to talk to /// /// /// Task> HistoryReadEventsNextAsync( T endpoint, HistoryReadNextRequestModel request, CancellationToken ct = default); /// /// Read historic values /// /// Server endpoint to talk to /// /// /// Task> HistoryReadValuesAsync( T endpoint, HistoryReadRequestModel request, CancellationToken ct = default); /// /// Read historic values at times /// /// Server endpoint to talk to /// /// /// Task> HistoryReadValuesAtTimesAsync( T endpoint, HistoryReadRequestModel request, CancellationToken ct = default); /// /// Read processed historic values /// /// Server endpoint to talk to /// /// /// Task> HistoryReadProcessedValuesAsync( T endpoint, HistoryReadRequestModel request, CancellationToken ct = default); /// /// Read modified values /// /// Server endpoint to talk to /// /// /// Task> HistoryReadModifiedValuesAsync( T endpoint, HistoryReadRequestModel request, CancellationToken ct = default); /// /// Read next set of historic values /// /// Server endpoint to talk to /// /// /// Task> HistoryReadValuesNextAsync( T endpoint, HistoryReadNextRequestModel request, CancellationToken ct = default); /// /// Stream values /// /// /// /// /// IAsyncEnumerable HistoryStreamValuesAsync(T endpoint, HistoryReadRequestModel request, CancellationToken ct = default); /// /// Stream modified historic values /// /// /// /// /// IAsyncEnumerable HistoryStreamModifiedValuesAsync(T endpoint, HistoryReadRequestModel request, CancellationToken ct = default); /// /// Stream historic values at times /// /// /// /// /// IAsyncEnumerable HistoryStreamValuesAtTimesAsync(T endpoint, HistoryReadRequestModel request, CancellationToken ct = default); /// /// Stream processed historic values /// /// /// /// /// IAsyncEnumerable HistoryStreamProcessedValuesAsync(T endpoint, HistoryReadRequestModel request, CancellationToken ct = default); /// /// Stream modified historic events /// /// /// /// /// IAsyncEnumerable HistoryStreamEventsAsync(T endpoint, HistoryReadRequestModel request, CancellationToken ct = default); } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/INetworkDiscovery.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Models; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; /// /// Network discovery services /// public interface INetworkDiscovery { /// /// Discovery server in network with discovery url. /// /// /// /// Task RegisterAsync(ServerRegistrationRequestModel request, CancellationToken ct = default); /// /// Start a discovery run for servers in network. /// /// /// /// Task DiscoverAsync(DiscoveryRequestModel request, CancellationToken ct = default); /// /// Cancel a discovery run that is ongoing /// /// /// /// Task CancelAsync(DiscoveryCancelRequestModel request, CancellationToken ct = default); } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/INodeServices.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Extensions.Serializers; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; /// /// Node services expose the OPC UA service sets /// /// public interface INodeServices { /// /// Get the capabilities of the server /// /// Server endpoint to talk to /// /// /// Task GetServerCapabilitiesAsync(T endpoint, RequestHeaderModel? header, CancellationToken ct = default); /// /// Browse nodes on server /// /// Server endpoint to talk to /// Browse request /// /// Task BrowseFirstAsync(T endpoint, BrowseFirstRequestModel request, CancellationToken ct = default); /// /// Browse remainder of references /// /// Server endpoint to talk to /// Continuation token /// /// Task BrowseNextAsync(T endpoint, BrowseNextRequestModel request, CancellationToken ct = default); /// /// Stream node and references /// /// Server endpoint to talk to /// Continuation token /// /// IAsyncEnumerable BrowseAsync(T endpoint, BrowseStreamRequestModel request, CancellationToken ct = default); /// /// Browse by path /// /// Server endpoint to talk to /// /// /// Task BrowsePathAsync(T endpoint, BrowsePathRequestModel request, CancellationToken ct = default); /// /// Get the node metadata which includes the fields /// and meta data of the type and can be used when constructing /// event filters or calling methods to pass the correct arguments. /// /// Server endpoint to talk to /// /// /// Task GetMetadataAsync(T endpoint, NodeMetadataRequestModel request, CancellationToken ct = default); /// /// Compile a query into a filter /// /// Server endpoint to talk to /// The query to compile /// /// The compiled query Task CompileQueryAsync(T endpoint, QueryCompilationRequestModel request, CancellationToken ct = default); /// /// Read node value /// /// Server endpoint to talk to /// /// /// Task ValueReadAsync(T endpoint, ValueReadRequestModel request, CancellationToken ct = default); /// /// Write node value /// /// Server endpoint to talk to /// /// /// Task ValueWriteAsync(T endpoint, ValueWriteRequestModel request, CancellationToken ct = default); /// /// Get meta data for method call (input and output arguments) /// /// Server endpoint to talk to /// /// /// Task GetMethodMetadataAsync( T endpoint, MethodMetadataRequestModel request, CancellationToken ct = default); /// /// Call method /// /// Server endpoint to talk to /// /// /// Task MethodCallAsync(T endpoint, MethodCallRequestModel request, CancellationToken ct = default); /// /// Read node attributes in batch /// /// Server endpoint to talk to /// /// /// Task ReadAsync(T endpoint, ReadRequestModel request, CancellationToken ct = default); /// /// Write node attributes in batch /// /// Server endpoint to talk to /// /// /// Task WriteAsync(T endpoint, WriteRequestModel request, CancellationToken ct = default); /// /// Get history server capabilities /// /// Server endpoint to talk to /// /// /// Task HistoryGetServerCapabilitiesAsync( T endpoint, RequestHeaderModel? header, CancellationToken ct = default); /// /// Get a node's history configuration /// /// Server endpoint to talk to /// /// /// Task HistoryGetConfigurationAsync( T endpoint, HistoryConfigurationRequestModel request, CancellationToken ct = default); /// /// Read node history /// /// Server endpoint to talk to /// /// /// Task> HistoryReadAsync(T endpoint, HistoryReadRequestModel request, CancellationToken ct = default); /// /// Read node history continuation /// /// Server endpoint to talk to /// /// /// Task> HistoryReadNextAsync( T endpoint, HistoryReadNextRequestModel request, CancellationToken ct = default); /// /// Update node history /// /// Server endpoint to talk to /// /// /// Task HistoryUpdateAsync(T endpoint, HistoryUpdateRequestModel request, CancellationToken ct = default); } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/IPublishServices.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Models; using System.Threading; using System.Threading.Tasks; /// /// Publish services /// /// public interface IPublishServices { /// /// Start publishing values from a node /// /// Server endpoint to talk to /// /// /// Task PublishStartAsync(T endpoint, PublishStartRequestModel request, CancellationToken ct = default); /// /// Stop publishing values from a node /// /// Server endpoint to talk to /// /// /// Task PublishStopAsync(T endpoint, PublishStopRequestModel request, CancellationToken ct = default); /// /// Configure node values to publish and unpublish in bulk /// /// Server endpoint to talk to /// /// /// Task PublishBulkAsync(T endpoint, PublishBulkRequestModel request, CancellationToken ct = default); /// /// Get all published nodes for a server endpoint. /// /// Server endpoint to talk to /// /// /// Task PublishListAsync(T endpoint, PublishedItemListRequestModel request, CancellationToken ct = default); } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/IServerDiscovery.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Models; using System.Threading; using System.Threading.Tasks; /// /// Server discovery interface /// public interface IServerDiscovery { /// /// Find a server using the endpoint url in the query /// object. Returns a application registration object only /// if the endpoint is part of the application's endpoint /// list. /// /// /// /// Task FindServerAsync( ServerEndpointQueryModel query, CancellationToken ct = default); } } ================================================ FILE: src/Azure.IIoT.OpcUa/src/Publisher/Runtime.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using System; /// /// Runtime operations /// public static class Runtime { /// /// Crash the process with optional exception /// public static Action FailFast { get; set; } = Environment.FailFast; /// /// Exit process /// public static Action Exit { get; set; } = Environment.Exit; } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Azure.IIoT.OpcUa.Tests.csproj ================================================  net9.0 aggressive all runtime; build; native; contentfiles; analyzers; buildtransitive all runtime; build; native; contentfiles; analyzers Always Always ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/AvroBaseTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Opc.Ua; using System; using System.Buffers; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Xml; using Xunit; /// /// Tests for the Json encoder and decoder class. /// public sealed class AvroBaseTests { [Theory] [InlineData(true)] [InlineData(false)] public void TestBoolean(bool value) { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteBoolean(null, value); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(value, decoder.ReadBoolean(null)); } [Theory] [InlineData(0u)] [InlineData(1000u)] [InlineData(long.MaxValue)] public void TestLong(long value) { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteInt64(null, value); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(value, decoder.ReadInt64(null)); } [Theory] [InlineData(0.0)] [InlineData(Math.PI)] [InlineData(double.MaxValue)] public void TestDouble(double value) { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteDouble(null, value); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(value, decoder.ReadDouble(null)); } [Theory] [InlineData(0.0f)] [InlineData((float)Math.PI)] [InlineData(float.MaxValue)] public void TestFloat(float value) { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteFloat(null, value); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(value, decoder.ReadFloat(null)); } [Theory] [InlineData("test")] [InlineData("12345")] [InlineData("12345678901234567890123456789012345678901234567890123456789012345678901234567890")] public void TestString(string value) { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteString(null, value); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(value, decoder.ReadString(null)); } [Theory] [InlineData("test")] [InlineData("12345")] public void TestByteString(string value) { var context = new ServiceMessageContext(); var expected = Encoding.UTF8.GetBytes(value); using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteByteString(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadByteString(null)); } [Theory] [InlineData(0u)] [InlineData(1000u)] [InlineData(long.MaxValue)] [InlineData(ulong.MaxValue)] public void TestULong(ulong value) { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteUInt64(null, value); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(value, decoder.ReadUInt64(null)); } [Theory] [InlineData(StatusCodes.Good)] [InlineData(StatusCodes.Bad)] [InlineData(StatusCodes.Uncertain)] public void TestStatusCode(uint value) { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteStatusCode(null, value); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(value, decoder.ReadStatusCode(null)); } [Theory] [InlineData(StatusCodes.Good)] [InlineData("test")] [InlineData(12345)] public void TestVariant(object value) { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteVariant(null, new Variant(value)); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(value, decoder.ReadVariant(null).Value); } [Theory] [InlineData(DiagnosticsLevel.Advanced)] [InlineData(BuiltInType.Int32)] public void TestVariantWithEnumeration(object value) { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteVariant(null, new Variant(value)); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(Convert.ToInt32(value, CultureInfo.InvariantCulture), decoder.ReadVariant(null).Value); } public static TheoryData GetValues() { return new TheoryData(VariantVariants.GetValues().Select(v => new VariantHolder(v))); } [Theory] [MemberData(nameof(GetValues))] public void TestVariantVariants(VariantHolder value) { var expected = value.Variant; var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteVariant(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadVariant(null)); } [Theory] [InlineData("test")] [InlineData(12345u)] public void TestNodeId(object value) { var context = new ServiceMessageContext(); var ns = context.NamespaceUris.GetIndexOrAppend("test.org"); using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); var expected = new NodeId(value, ns); encoder.WriteNodeId(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadNodeId(null)); } [Theory] [InlineData("test")] [InlineData(12345u)] public void TestExpandedNodeId(object value) { var context = new ServiceMessageContext(); context.NamespaceUris.GetIndexOrAppend("test.org"); var srv = context.ServerUris.GetIndexOrAppend("Super"); using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); var expected = new ExpandedNodeId(value, 0, "test.org", srv); encoder.WriteExpandedNodeId(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadExpandedNodeId(null)); } [Fact] public void TestDataValue() { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); var expected = new DataValue(); encoder.WriteDataValue(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadDataValue(null)); } [Fact] public void TestDataValueNull() { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteDataValue(null, null); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.True(Opc.Ua.Utils.IsEqual(new DataValue(), decoder.ReadDataValue(null))); } [Fact] public void TestGuid() { var context = new ServiceMessageContext(); var expected = Guid.NewGuid(); using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteGuid(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadGuid(null)); } [Fact] public void TestDateTime() { var context = new ServiceMessageContext(); var expected = DateTime.UtcNow; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteDateTime(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadDateTime(null)); } [Fact] public void TestXmlElement() { var context = new ServiceMessageContext(); var expected = new XmlDocument(); expected.LoadXml(""); using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteXmlElement(null, expected.DocumentElement); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); var actual = new XmlDocument(); actual.Load(decoder.ReadXmlElement(null).CreateNavigator().ReadSubtree()); Assert.Equal(expected.OuterXml, actual.OuterXml); } [Fact] public void TestQualifiedName() { var context = new ServiceMessageContext(); var ns = context.NamespaceUris.GetIndexOrAppend("test.org"); var expected = new QualifiedName("test", ns); using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteQualifiedName(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadQualifiedName(null)); } [Fact] public void TestLocalizedText() { var context = new ServiceMessageContext(); var expected = new LocalizedText("test", "en"); using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteLocalizedText(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadLocalizedText(null)); } [Fact] public void TestExtensionObject() { var context = new ServiceMessageContext(); var expected = new ExtensionObject(new NodeId(1234), new byte[] { 0, 1, 2, 3 }); using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteExtensionObject(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); var actual = decoder.ReadExtensionObject(null); Assert.Equal(expected.TypeId, actual.TypeId); Assert.Equal(expected.Body, actual.Body); } [Fact] public void TestStatusCodeArray() { var context = new ServiceMessageContext(); var expected = new StatusCode[] { StatusCodes.Good, StatusCodes.Bad }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteStatusCodeArray(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); var actual = decoder.ReadStatusCodeArray(null); Assert.Equal(expected, actual); } [Fact] public void TestNodeIdArray() { var context = new ServiceMessageContext(); var ns = context.NamespaceUris.GetIndexOrAppend("test.org"); var expected = new NodeId[] { new(123, ns), new(456, ns) }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteNodeIdArray(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); var actual = decoder.ReadNodeIdArray(null); Assert.Equal(expected, actual); } [Fact] public void TestExpandedNodeIdArray() { var context = new ServiceMessageContext(); context.NamespaceUris.GetIndexOrAppend("test.org"); var srv = context.ServerUris.GetIndexOrAppend("Super"); var expected = new ExpandedNodeId[] { new(123u, 0, "test.org", srv), new(456u, 0, "test.org", srv) }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteExpandedNodeIdArray(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); var actual = decoder.ReadExpandedNodeIdArray(null); Assert.Equal(expected, actual); } [Fact] public void TestInt16() { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteInt16(null, 123); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(123, decoder.ReadInt16(null)); } [Fact] public void TestSByte() { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteSByte(null, 123); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(123, decoder.ReadSByte(null)); } [Fact] public void TestByte() { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteByte(null, 123); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(123, decoder.ReadByte(null)); } [Fact] public void TestDiagnosticInfo() { var context = new ServiceMessageContext(); var expected = new DiagnosticInfo() { AdditionalInfo = "dd" }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteDiagnosticInfo(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); var result = decoder.ReadDiagnosticInfo(null); AssertEqual(expected, result); } [Fact] public void TestEnum() { var context = new ServiceMessageContext(); const DiagnosticsLevel expected = DiagnosticsLevel.Basic; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteEnumerated(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); var result = decoder.ReadEnumerated(null); Assert.Equal(expected, result); } [Fact] public void TestEnumArray() { var context = new ServiceMessageContext(); var expected = new DiagnosticsLevel[] { DiagnosticsLevel.Basic, DiagnosticsLevel.Advanced }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteEnumeratedArray(null, expected, null); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); var actual = decoder.ReadEnumeratedArray(null); Assert.Equal(expected, actual); } [Fact] public void TestDiagnosticInfoArray() { var context = new ServiceMessageContext(); var expected = new DiagnosticInfo[] { new() { AdditionalInfo = "dd" }, new() { AdditionalInfo = string.Empty } }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteDiagnosticInfoArray(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); var actual = decoder.ReadDiagnosticInfoArray(null); Assert.Equal(expected.Length, actual.Count); for (var i = 0; i < expected.Length; i++) { var result = actual[i]; AssertEqual(expected[i], result); } } private static void AssertEqual(DiagnosticInfo x, DiagnosticInfo y) { if (x == y) { return; } Assert.NotNull(x); Assert.NotNull(y); Assert.Equal(x.NamespaceUri, y.NamespaceUri); Assert.Equal(x.LocalizedText, y.LocalizedText); Assert.Equal(x.Locale, y.Locale); Assert.Equal(x.AdditionalInfo, y.AdditionalInfo); Assert.Equal(x.InnerStatusCode, y.InnerStatusCode); Assert.Equal(x.NamespaceUri, y.NamespaceUri); AssertEqual(x.InnerDiagnosticInfo, y.InnerDiagnosticInfo); } [Fact] public void TestBooleanArray() { var context = new ServiceMessageContext(); var expected = new bool[] { true, false }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteBooleanArray(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadBooleanArray(null)); } [Fact] public void TestSByteArray() { var context = new ServiceMessageContext(); var expected = new sbyte[] { 1, 2, 3 }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteSByteArray(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadSByteArray(null)); } [Fact] public void TestByteArray() { var context = new ServiceMessageContext(); var expected = new byte[] { 1, 2, 3 }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteByteArray(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadByteArray(null)); } [Fact] public void TestInt16Array() { var context = new ServiceMessageContext(); var expected = new short[] { 1, 2, 3 }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteInt16Array(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadInt16Array(null)); } [Fact] public void TestUInt16Array() { var context = new ServiceMessageContext(); var expected = new ushort[] { 1, 2, 3 }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteUInt16Array(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadUInt16Array(null)); } [Fact] public void TestInt32Array() { var context = new ServiceMessageContext(); var expected = new int[] { 1, 2, 3 }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteInt32Array(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadInt32Array(null)); } [Fact] public void TestUInt32Array() { var context = new ServiceMessageContext(); var expected = new uint[] { 1, 2, 3 }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteUInt32Array(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadUInt32Array(null)); } [Fact] public void TestInt64Array() { var context = new ServiceMessageContext(); var expected = new long[] { 1, 2, 3 }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteInt64Array(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadInt64Array(null)); } [Fact] public void TestUInt64Array() { var context = new ServiceMessageContext(); var expected = new ulong[] { 1, 2, 3 }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteUInt64Array(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadUInt64Array(null)); } [Fact] public void TestFloatArray() { var context = new ServiceMessageContext(); var expected = new float[] { 1, 2, 3 }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteFloatArray(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadFloatArray(null)); } [Fact] public void TestDoubleArray() { var context = new ServiceMessageContext(); var expected = new double[] { 1, 2, 3 }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteDoubleArray(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadDoubleArray(null)); } [Fact] public void TestStringArray() { var context = new ServiceMessageContext(); var expected = new string[] { "1", "2", "3" }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteStringArray(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadStringArray(null)); } [Fact] public void TestDateTimeArray() { var context = new ServiceMessageContext(); var expected = new DateTime[] { DateTime.UtcNow, DateTime.UtcNow, DateTime.UtcNow }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteDateTimeArray(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadDateTimeArray(null)); } [Fact] public void TestGuidArray() { var context = new ServiceMessageContext(); var expected = new Uuid[] { (Uuid)Guid.NewGuid(), (Uuid)Guid.NewGuid(), (Uuid)Guid.NewGuid() }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteGuidArray(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadGuidArray(null)); } [Fact] public void TestXmlElementArray() { var context = new ServiceMessageContext(); var expected = new XmlDocument(); expected.LoadXml(""); var expectedArray = new XmlElement[] { expected.DocumentElement, expected.DocumentElement }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteXmlElementArray(null, expectedArray); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); var actualArray = decoder.ReadXmlElementArray(null); Assert.Equal(expectedArray.Length, actualArray.Count); for (var i = 0; i < expectedArray.Length; i++) { var actual = new XmlDocument(); actual.Load(actualArray[i].CreateNavigator().ReadSubtree()); Assert.Equal(expected.OuterXml, actual.OuterXml); } } [Fact] public void TestQualifiedNameArray() { var context = new ServiceMessageContext(); var ns = context.NamespaceUris.GetIndexOrAppend("test.org"); var expected = new QualifiedName[] { new("test", ns), new("test", ns) }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteQualifiedNameArray(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadQualifiedNameArray(null)); } [Fact] public void TestLocalizedTextArray1() { var context = new ServiceMessageContext(); var expected = new LocalizedText[] { new("test", "en"), new("test", "en") }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteLocalizedTextArray(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadLocalizedTextArray(null)); } [Fact] public void TestLocalizedTextArray2() { var context = new ServiceMessageContext(); var expected = new LocalizedText[] { new("test", "en"), new("test", "en") }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteArray(null, expected, ValueRanks.OneDimension, BuiltInType.LocalizedText); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); var result = decoder.ReadArray(null, ValueRanks.OneDimension, BuiltInType.LocalizedText); Assert.Equal(expected, result); } [Fact] public void TestExtensionObjectArray() { var context = new ServiceMessageContext(); var expected = new ExtensionObject[] { new(new NodeId(1234), new byte[] { 0, 1, 2, 3 }), new(new NodeId(1234), new byte[] { 0, 1, 2, 3 }) }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteExtensionObjectArray(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); var actual = decoder.ReadExtensionObjectArray(null); Assert.Equal(expected.Length, actual.Count); for (var i = 0; i < expected.Length; i++) { Assert.Equal(expected[i].TypeId, actual[i].TypeId); Assert.Equal(expected[i].Body, actual[i].Body); } } [Fact] public void TestDataValueArray() { var context = new ServiceMessageContext(); var expected = new DataValue[] { new(), new() }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteDataValueArray(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); var actual = decoder.ReadDataValueArray(null); Assert.Equal(expected.Length, actual.Count); for (var i = 0; i < expected.Length; i++) { Assert.Equal(expected[i], actual[i]); } } [Fact] public void TestVariantArray() { var context = new ServiceMessageContext(); var expected = new Variant[] { new(123), new("test") }; using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteVariantArray(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); var actual = decoder.ReadVariantArray(null); Assert.Equal(expected.Length, actual.Count); for (var i = 0; i < expected.Length; i++) { Assert.Equal(expected[i].Value, actual[i].Value); } } public static TheoryData GetVariantArrays() { return new TheoryData(VariantVariants.GetValues() .Select(v => new VariantsHolder(Enumerable.Repeat(v, 3).ToArray(), v.TypeInfo))); } [Theory] [MemberData(nameof(GetVariantArrays))] public void TestVariantArrayVariants(VariantsHolder value) { var expected = value.Variants.ToArray(); var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteVariantArray(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); Assert.Equal(expected, decoder.ReadVariantArray(null)); } [Fact] public void TestVariantWithEnumerations() { var context = new ServiceMessageContext(); var expected = new Variant(new[] { DiagnosticsLevel.Advanced, DiagnosticsLevel.Advanced }); using var stream = new MemoryStream(); using var encoder = new SchemalessAvroEncoder(stream, context, true); encoder.WriteVariant(null, expected); stream.Position = 0; using var decoder = new SchemalessAvroDecoder(stream, context); var result = decoder.ReadVariant(null).Value; Assert.Equal(new int[] { 1, 1 }, result); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/AvroDataSetTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Azure.IIoT.OpcUa.Encoders.Models; using Azure.IIoT.OpcUa.Encoders.Schemas.Avro; using Azure.IIoT.OpcUa.Publisher.Models; using Avro; using Opc.Ua; using Opc.Ua.Extensions; using System; using System.Collections.Generic; using System.IO; using System.Linq; using Xunit; public class AvroDataSetTests { [Fact] public void ReadWriteProgramDiagnostic2DataTypeStream() { // Create dummy type var expected = VariantVariants.Complex; const int count = 100; byte[] buffer; var context = new ServiceMessageContext(); using (var stream = new MemoryStream()) { using (var encoder = new SchemalessAvroEncoder(stream, context)) { for (var i = 0; i < count; i++) { encoder.WriteEncodeable(null, expected, expected.GetType()); } } buffer = stream.ToArray(); } using (var stream = new MemoryStream(buffer)) using (var decoder = new SchemalessAvroDecoder(stream, context)) { for (var i = 0; i < count; i++) { var result = decoder.ReadEncodeable(null, expected.GetType()); Assert.True(result.IsEqual(expected)); } } } [Fact] public void ReadWriteDataValueWithIntStream() { // Create dummy var expected = new DataValue(new Variant(12345)); const int count = 10000; byte[] buffer; var context = new ServiceMessageContext(); using (var stream = new MemoryStream()) { using (var encoder = new SchemalessAvroEncoder(stream, context)) { for (var i = 0; i < count; i++) { encoder.WriteDataValue(null, expected); } } buffer = stream.ToArray(); } using (var stream = new MemoryStream(buffer)) using (var decoder = new SchemalessAvroDecoder(stream, context)) { for (var i = 0; i < count; i++) { var result = decoder.ReadDataValue(null); Assert.Equal(expected, result); } } } [Fact] public void ReadWriteDataValueWithStringStream() { // Create dummy var expected = new DataValue(new Variant("TestTestTestTest" + Guid.NewGuid())); const int count = 10000; byte[] buffer; var context = new ServiceMessageContext(); using (var stream = new MemoryStream()) { using (var encoder = new SchemalessAvroEncoder(stream, context)) { for (var i = 0; i < count; i++) { encoder.WriteDataValue(null, expected); } } buffer = stream.ToArray(); } using (var stream = new MemoryStream(buffer)) using (var decoder = new SchemalessAvroDecoder(stream, context)) { for (var i = 0; i < count; i++) { var result = decoder.ReadDataValue(null); Assert.Equal(expected, result); } } } [Theory] [InlineData(true)] [InlineData(false)] public void ReadWriteProgramDiagnostic2DataTypeSchema(bool concise) { // Create dummy type var expected = VariantVariants.Complex; const int count = 100; byte[] buffer; var context = new ServiceMessageContext(); Schema schema; using (var stream = new MemoryStream()) { using (var encoder = new AvroSchemaBuilder(stream, context, emitConciseSchemas: concise)) { encoder.WriteArray(null, Enumerable .Repeat(expected, count) .ToList(), v => encoder.WriteEncodeable(null, v, v.GetType())); schema = encoder.Schema; } buffer = stream.ToArray(); } using (var stream = new MemoryStream(buffer)) { var json = schema.ToJson(); Assert.NotNull(json); using var decoder = new AvroDecoder(stream, schema, context); var results = decoder.ReadArray(null, () => decoder.ReadEncodeable(null, expected.GetType())); Assert.Equal(count, results.Length); for (var i = 0; i < count; i++) { Assert.True(results[i].IsEqual(expected)); } } } [Theory] [InlineData(true)] [InlineData(false)] public void ReadWriteDataValueArrayWithIntAndSchema(bool concise) { // Create dummy var expected = new DataValue(new Variant(12345)); const int count = 10000; byte[] buffer; var context = new ServiceMessageContext(); Schema schema; using (var stream = new MemoryStream()) { using (var encoder = new AvroSchemaBuilder(stream, context, emitConciseSchemas: concise)) { encoder.WriteArray(null, Enumerable .Repeat(expected, count) .ToList(), v => encoder.WriteDataValue(null, v)); schema = encoder.Schema; } buffer = stream.ToArray(); } using (var stream = new MemoryStream(buffer)) using (var decoder = new AvroDecoder(stream, schema, context)) { var results = decoder.ReadArray(null, () => decoder.ReadDataValue(null)); Assert.Equal(count, results.Length); for (var i = 0; i < count; i++) { Assert.Equal(expected, results[i]); } } } [Theory] [InlineData(true)] [InlineData(false)] public void ReadWriteDataValueArrayWithStringAndSchema(bool concise) { // Create dummy var expected = new DataValue(new Variant("TestTestTestTest" + Guid.NewGuid())); const int count = 10000; byte[] buffer; var context = new ServiceMessageContext(); Schema schema; using (var stream = new MemoryStream()) { using (var encoder = new AvroSchemaBuilder(stream, context, emitConciseSchemas: concise)) { encoder.WriteArray(null, Enumerable .Repeat(expected, count) .ToList(), v => encoder.WriteDataValue(null, v)); schema = encoder.Schema; } buffer = stream.ToArray(); } using (var stream = new MemoryStream(buffer)) using (var decoder = new AvroDecoder(stream, schema, context)) { var results = decoder.ReadArray(null, () => decoder.ReadDataValue(null)); Assert.Equal(count, results.Length); for (var i = 0; i < count; i++) { Assert.Equal(expected, results[i]); } } } [Theory] [InlineData(true)] [InlineData(false)] public void ReadWriteDataSetTest1(bool concise) { // Create dummy var expected = new DataSet(new Dictionary { ["abcd"] = new DataValue(new Variant(1234), StatusCodes.Good, DateTime.UtcNow, DateTime.UtcNow), ["http://microsoft.com"] = new DataValue(new Variant(-222222222), StatusCodes.Bad, DateTime.MinValue, DateTime.UtcNow), ["1111111111111111111111111"] = new DataValue(new Variant(false), StatusCodes.Bad, DateTime.UtcNow, DateTime.MinValue), ["@#$%^&*()_+~!@#$%^*(){}"] = new DataValue(new Variant(new byte[] { 0, 2, 4, 6 }), StatusCodes.Good), ["1245"] = new DataValue(new Variant("hello"), StatusCodes.Bad, DateTime.UtcNow, DateTime.MinValue), ["..."] = new DataValue(new Variant("imbricated")) }); byte[] buffer; var context = new ServiceMessageContext(); Schema schema; using (var stream = new MemoryStream()) { using (var encoder = new AvroSchemaBuilder(stream, context, emitConciseSchemas: concise)) { encoder.WriteDataSet(null, expected); schema = encoder.Schema; } buffer = stream.ToArray(); } var json = schema.ToJson(); Assert.NotNull(json); using (var stream = new MemoryStream(buffer)) using (var decoder = new AvroDecoder(stream, schema, context)) { var result = decoder.ReadDataSet(null); Assert.True(expected.Equals(result)); } } [Theory] [InlineData(true)] [InlineData(false)] public void ReadWriteDataSetTest2(bool concise) { // Create dummy var expected = new DataSet(new Dictionary { ["abcd"] = new DataValue(new Variant(1234), StatusCodes.Good, DateTime.UtcNow, DateTime.UtcNow), ["http://microsoft.com"] = null, ["1111111111111111111111111"] = new DataValue(new Variant(false), StatusCodes.Bad, DateTime.UtcNow, DateTime.MinValue), ["@#$%^&*()_+~!@#$%^*(){}"] = new DataValue(new Variant(new byte[] { 0, 2, 4, 6 }), StatusCodes.Good), ["1245"] = null, ["..."] = new DataValue(new Variant("imbricated")) }); byte[] buffer; var context = new ServiceMessageContext(); Schema schema; using (var stream = new MemoryStream()) { using (var encoder = new AvroSchemaBuilder(stream, context, emitConciseSchemas: concise)) { encoder.WriteDataSet(null, expected); schema = encoder.Schema; } buffer = stream.ToArray(); } var json = schema.ToJson(); Assert.NotNull(json); using (var stream = new MemoryStream(buffer)) using (var decoder = new AvroDecoder(stream, schema, context)) { var result = decoder.ReadDataSet(null); Assert.True(expected.Equals(result)); } } [Theory] [InlineData(true)] [InlineData(false)] public void ReadWriteDataSetArrayRawTest1(bool concise) { // Create dummy var expected = new DataSet(new Dictionary { ["abcd"] = new DataValue(new Variant(1234), StatusCodes.Good, DateTime.UtcNow, DateTime.UtcNow), ["http://microsoft.com"] = new DataValue(new Variant(-222222222), StatusCodes.Bad, DateTime.MinValue, DateTime.UtcNow), ["1111111111111111111111111"] = new DataValue(new Variant(false), StatusCodes.Bad, DateTime.UtcNow, DateTime.MinValue), ["@#$%^&*()_+~!@#$%^*(){}"] = new DataValue(new Variant(new byte[] { 0, 2, 4, 6 }), StatusCodes.Good), ["1245"] = new DataValue(new Variant("hello"), StatusCodes.Bad, DateTime.UtcNow, DateTime.MinValue), ["..."] = new DataValue(new Variant("imbricated")) }, DataSetFieldContentFlags.RawData); byte[] buffer; var context = new ServiceMessageContext(); Schema schema; using (var stream = new MemoryStream()) { using (var encoder = new AvroSchemaBuilder(stream, context, emitConciseSchemas: concise)) { encoder.WriteDataSet(null, expected); schema = encoder.Schema; } buffer = stream.ToArray(); } using (var stream = new MemoryStream(buffer)) using (var decoder = new AvroDecoder(stream, schema, context)) { var result = decoder.ReadDataSet(null); Assert.True(expected.Equals(result)); } } [Theory] [InlineData(true)] [InlineData(false)] public void ReadWriteDataSetArrayRawTest2(bool concise) { // Create dummy var expected = new DataSet(new Dictionary { ["abcd"] = null, ["http://microsoft.com"] = new DataValue(new Variant(-222222222), StatusCodes.Bad, DateTime.MinValue, DateTime.UtcNow), ["1111111111111111111111111"] = null, ["@#$%^&*()_+~!@#$%^*(){}"] = new DataValue(new Variant(new byte[] { 0, 2, 4, 6 }), StatusCodes.Good), ["1245"] = new DataValue(new Variant("hello"), StatusCodes.Bad, DateTime.UtcNow, DateTime.MinValue), ["..."] = null }, DataSetFieldContentFlags.RawData); byte[] buffer; var context = new ServiceMessageContext(); Schema schema; using (var stream = new MemoryStream()) { using (var encoder = new AvroSchemaBuilder(stream, context, emitConciseSchemas: concise)) { encoder.WriteDataSet(null, expected); schema = encoder.Schema; } buffer = stream.ToArray(); } using (var stream = new MemoryStream(buffer)) using (var decoder = new AvroDecoder(stream, schema, context)) { var result = decoder.ReadDataSet(null); Assert.True(expected.Equals(result)); } } [Theory] [InlineData(true)] [InlineData(false)] public void ReadWriteDataSetWithSingleEntryTest(bool concise) { // Create dummy var expected = new DataSet(new Dictionary { ["abcd"] = new DataValue(new Variant(1234), StatusCodes.Good, DateTime.UtcNow, DateTime.UtcNow) }); byte[] buffer; var context = new ServiceMessageContext(); Schema schema; using (var stream = new MemoryStream()) { using (var encoder = new AvroSchemaBuilder(stream, context, emitConciseSchemas: concise)) { encoder.WriteDataSet(null, expected); schema = encoder.Schema; } buffer = stream.ToArray(); } using (var stream = new MemoryStream(buffer)) using (var decoder = new AvroDecoder(stream, schema, context)) { var result = decoder.ReadDataSet(null); Assert.Equal(expected.DataSetFields.FirstOrDefault(f => f.Name == "abcd").Value, result.DataSetFields.FirstOrDefault(f => f.Name == "abcd").Value); } } [Theory] [InlineData(true)] [InlineData(false)] public void ReadWriteDataSetWithSingleComplexEntryTest(bool concise) { // Create dummy var expected = new DataSet(new Dictionary { ["abcd"] = new DataValue(new Variant(VariantVariants.Complex), StatusCodes.Good, DateTime.UtcNow, DateTime.UtcNow) }); byte[] buffer; var context = new ServiceMessageContext(); Schema schema; using (var stream = new MemoryStream()) { using (var encoder = new AvroSchemaBuilder(stream, context, emitConciseSchemas: concise)) { encoder.WriteDataSet(null, expected); schema = encoder.Schema; } buffer = stream.ToArray(); } using (var stream = new MemoryStream(buffer)) using (var decoder = new AvroDecoder(stream, schema, context)) { var result = decoder.ReadDataSet(null); Assert.True(result.DataSetFields.FirstOrDefault(f => f.Name == "abcd").Value.Value is ExtensionObject); var eo = (ExtensionObject)result.DataSetFields.FirstOrDefault(f => f.Name == "abcd").Value.Value; Assert.True(eo.Body is IEncodeable); var e = (IEncodeable)eo.Body; Assert.Equal(VariantVariants.Complex.AsJson(context), e.AsJson(context)); } } [Theory] [InlineData(true)] [InlineData(false)] public void ReadWriteDataSetWithSingleValueRawTest(bool concise) { // Create dummy var expected = new DataSet(new Dictionary { ["abcd"] = new DataValue(new Variant(1234), StatusCodes.Good, DateTime.UtcNow, DateTime.UtcNow) }, DataSetFieldContentFlags.RawData); byte[] buffer; var context = new ServiceMessageContext(); Schema schema; using (var stream = new MemoryStream()) { using (var encoder = new AvroSchemaBuilder(stream, context, emitConciseSchemas: concise)) { encoder.WriteDataSet(null, expected); schema = encoder.Schema; } buffer = stream.ToArray(); } using (var stream = new MemoryStream(buffer)) using (var decoder = new AvroDecoder(stream, schema, context)) { var result = decoder.ReadDataSet(null); Assert.Equal(expected.DataSetFields.FirstOrDefault(f => f.Name == "abcd").Value.Value, result.DataSetFields.FirstOrDefault(f => f.Name == "abcd").Value.Value); } } [Theory] [InlineData(true)] [InlineData(false)] public void ReadWriteDataSetWithSingleComplexValueRawTest(bool concise) { // Create dummy var expected = new DataSet(new Dictionary { ["abcd"] = new DataValue(new Variant(VariantVariants.Complex), StatusCodes.Good, DateTime.UtcNow, DateTime.UtcNow) }, DataSetFieldContentFlags.RawData); byte[] buffer; var context = new ServiceMessageContext(); Schema schema; using (var stream = new MemoryStream()) { using (var encoder = new AvroSchemaBuilder(stream, context, emitConciseSchemas: concise)) { encoder.WriteDataSet(null, expected); schema = encoder.Schema; } buffer = stream.ToArray(); } using (var stream = new MemoryStream(buffer)) using (var decoder = new AvroDecoder(stream, schema, context)) { var result = decoder.ReadDataSet(null); Assert.True(result.DataSetFields.FirstOrDefault(f => f.Name == "abcd").Value.Value is ExtensionObject); var eo = (ExtensionObject)result.DataSetFields.FirstOrDefault(f => f.Name == "abcd").Value.Value; Assert.True(eo.Body is IEncodeable); var e = (IEncodeable)eo.Body; Assert.Equal(VariantVariants.Complex.AsJson(context), e.AsJson(context)); } } [Theory] [InlineData(true)] [InlineData(false)] public void ReadWriteDataSetArrayRawStreamTest(bool concise) { // Create dummy var expected = new DataSet(new Dictionary { ["abcd"] = new DataValue(new Variant(1234), StatusCodes.Good, DateTime.UtcNow, DateTime.UtcNow), ["http://microsoft.com"] = new DataValue(new Variant(-222222222), StatusCodes.Bad, DateTime.MinValue, DateTime.UtcNow), ["1111111111111111111111111"] = new DataValue(new Variant(false), StatusCodes.Bad, DateTime.UtcNow, DateTime.MinValue), ["@#$%^&*()_+~!@#$%^*(){}"] = new DataValue(new Variant(new byte[] { 0, 2, 4, 6 }), StatusCodes.Good), ["1245"] = new DataValue(new Variant("hello"), StatusCodes.Bad, DateTime.UtcNow, DateTime.MinValue), ["..."] = new DataValue(new Variant("imbricated")) }, DataSetFieldContentFlags.RawData); const int count = 10000; byte[] buffer; var context = new ServiceMessageContext(); Schema schema; using (var stream = new MemoryStream()) { using (var encoder = new AvroSchemaBuilder(stream, context, emitConciseSchemas: concise)) { encoder.WriteArray(null, Enumerable .Repeat(expected, count) .ToList(), v => encoder.WriteDataSet(null, v)); schema = encoder.Schema; } buffer = stream.ToArray(); } using (var stream = new MemoryStream(buffer)) using (var decoder = new AvroDecoder(stream, schema, context)) { var results = decoder.ReadArray(null, () => decoder.ReadDataSet(null)); Assert.Equal(count, results.Length); for (var i = 0; i < count; i++) { Assert.True(expected.Equals(results[i])); } } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/AvroEncoderTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Azure.IIoT.OpcUa.Encoders.Schemas; using Azure.IIoT.OpcUa.Encoders.Schemas.Avro; using Opc.Ua; using Opc.Ua.Extensions; using System; using System.Globalization; using System.IO; using System.Linq; using System.Xml; using Xunit; /// /// Tests for the Json builder and decoder class. /// public sealed class AvroEncoderTests { [Theory] [InlineData(true)] [InlineData(false)] public void TestBoolean(bool value) { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteBoolean(null, value); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteBoolean(null, value); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(value, decoder.ReadBoolean(null)); } [Theory] [InlineData(0u)] [InlineData(1000u)] [InlineData(long.MaxValue)] public void TestLong(long value) { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteInt64(null, value); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteInt64(null, value); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(value, decoder.ReadInt64(null)); } [Theory] [InlineData(0.0)] [InlineData(Math.PI)] [InlineData(double.MaxValue)] public void TestDouble(double value) { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteDouble(null, value); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteDouble(null, value); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(value, decoder.ReadDouble(null)); } [Theory] [InlineData(0.0f)] [InlineData((float)Math.PI)] [InlineData(float.MaxValue)] public void TestFloat(float value) { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteFloat(null, value); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteFloat(null, value); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(value, decoder.ReadFloat(null)); } [Theory] [InlineData("")] [InlineData("test")] [InlineData("12345")] [InlineData("12345678901234567890123456789012345678901234567890123456789012345678901234567890")] public void TestString(string value) { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteString(null, value); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteString(null, value); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(value, decoder.ReadString(null)); } [Theory] [InlineData(1096)] [InlineData(4096)] [InlineData(65535)] public void TestStringLengths(int length) { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); var buffer = new char[length]; buffer.AsSpan().Fill('a'); var value = new string(buffer); builder.WriteString(null, value); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteString(null, value); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(value, decoder.ReadString(null)); } [Fact] public void TestLargeStringLengthThrows() { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); var buffer = new char[80000]; buffer.AsSpan().Fill('a'); var value = new string(buffer); builder.WriteString(null, value); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteString(null, value); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Throws(() => decoder.ReadString(null)); } [Fact] public void TestStringWithZeroTerminator() { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); const string value = "teststring"; builder.WriteString(null, value + '\0'); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteString(null, value + '\0'); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(value, decoder.ReadString(null)); } [Theory] [InlineData(0)] [InlineData(1)] [InlineData(127)] [InlineData(257)] [InlineData(5000)] [InlineData(100000)] public void TestByteString(int length) { var context = new ServiceMessageContext(); var expected = new byte[length]; #pragma warning disable CA5394 // Do not use insecure randomness Random.Shared.NextBytes(expected); #pragma warning restore CA5394 // Do not use insecure randomness using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteByteString(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteByteString(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadByteString(null)); } [Theory] [InlineData(0u)] [InlineData(1000u)] [InlineData(long.MaxValue)] [InlineData(ulong.MaxValue)] public void TestULong(ulong value) { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteUInt64(null, value); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteUInt64(null, value); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(value, decoder.ReadUInt64(null)); } [Theory] [InlineData(StatusCodes.Good)] [InlineData(StatusCodes.Bad)] [InlineData(StatusCodes.Uncertain)] public void TestStatusCode(uint value) { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteStatusCode(null, value); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteStatusCode(null, value); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(value, decoder.ReadStatusCode(null)); } [Theory] [InlineData(false, StatusCodes.Good)] [InlineData(false, "test")] [InlineData(false, 12345)] [InlineData(true, StatusCodes.Good)] [InlineData(true, "test")] [InlineData(true, 12345)] public void TestVariant(bool concise, object value) { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true, concise); builder.WriteVariant(null, new Variant(value)); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteVariant(null, new Variant(value)); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(value, decoder.ReadVariant(null).Value); } [Theory] [InlineData(StatusCodes.Good)] [InlineData("test")] [InlineData(12345)] public void TestVariantWithNullableValue(object value) { var context = new ServiceMessageContext(); var expected = new Variant(value); var schemas = new AvroBuiltInSchemas(); var valueSchema = schemas.GetSchemaForBuiltInType(expected.TypeInfo.BuiltInType); var schema = valueSchema.AsNullable().CreateRoot(); using (var stream = new MemoryStream()) using (var encoder = new AvroEncoder(stream, schema, context, true)) { encoder.WriteVariant(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, schema, context); var variant = decoder.ReadVariant(null); Assert.Equal(expected, variant); } using (var stream = new MemoryStream()) using (var encoder = new AvroEncoder(stream, schema, context, true)) { encoder.WriteVariant(null, Variant.Null); stream.Position = 0; using var decoder = new AvroDecoder(stream, schema, context); var variant = decoder.ReadVariant(null); Assert.Equal(Variant.Null, variant); } } public static TheoryData GetValues() { return new TheoryData(VariantVariants.GetValues().Select(v => new VariantHolder(v))); } [Theory] [MemberData(nameof(GetValues))] public void TestVariantVariants(VariantHolder value) { var expected = value.Variant; var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true, false); builder.WriteVariant(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteVariant(null, expected); stream.Position = 0; var json = builder.Schema.ToJson(); Assert.NotNull(json); using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected.Value, decoder.ReadVariant(null).Value); } [Theory] [InlineData(true)] [InlineData(false)] public void TestVariantWithComplexEncodeable(bool concise) { var expected = new Variant(VariantVariants.Complex); var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true, concise); builder.WriteVariant(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteVariant(null, expected); stream.Position = 0; var json = builder.Schema.ToJson(); Assert.NotNull(json); using var decoder = new AvroDecoder(stream, builder.Schema, context); var value = decoder.ReadVariant(null).Value; Assert.True(value is ExtensionObject); var eo = (ExtensionObject)value; Assert.True(eo.Body is IEncodeable); var e = (IEncodeable)eo.Body; Assert.Equal(VariantVariants.Complex.AsJson(context), e.AsJson(context)); } [Theory] [MemberData(nameof(GetValues))] public void TestVariantVariantsConcise(VariantHolder value) { var expected = value.Variant; var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true, true); builder.WriteVariant(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteVariant(null, expected); stream.Position = 0; var json = builder.Schema.ToJson(); Assert.NotNull(json); using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadVariant(null)); } [Theory] [InlineData("test")] [InlineData(12345u)] public void TestNodeId(object value) { var context = new ServiceMessageContext(); var ns = context.NamespaceUris.GetIndexOrAppend("test.org"); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); var expected = new NodeId(value, ns); builder.WriteNodeId(null, expected); stream.Position = 0; var json = builder.Schema.ToJson(); Assert.NotNull(json); using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteNodeId(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadNodeId(null)); } [Fact] public void TestNodeIdOpaque() { var context = new ServiceMessageContext(); var ns = context.NamespaceUris.GetIndexOrAppend("test.org"); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); var expected = new NodeId(Guid.NewGuid().ToByteArray(), ns); builder.WriteNodeId(null, expected); stream.Position = 0; var json = builder.Schema.ToJson(); Assert.NotNull(json); using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteNodeId(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadNodeId(null)); } [Fact] public void TestNodeIdGuid() { var context = new ServiceMessageContext(); var ns = context.NamespaceUris.GetIndexOrAppend("test.org"); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); var expected = new NodeId(Guid.NewGuid(), ns); builder.WriteNodeId(null, expected); stream.Position = 0; var json = builder.Schema.ToJson(); Assert.NotNull(json); using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteNodeId(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadNodeId(null)); } [Fact] public void TestExpandedNodeIdOpaque() { var context = new ServiceMessageContext(); context.NamespaceUris.GetIndexOrAppend("test.org"); var srv = context.ServerUris.GetIndexOrAppend("Super"); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); var expected = new ExpandedNodeId(Guid.NewGuid().ToByteArray(), 0, "test.org", srv); builder.WriteExpandedNodeId(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteExpandedNodeId(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadExpandedNodeId(null)); } [Theory] [InlineData(false, StatusCodes.Good)] [InlineData(false, "test")] [InlineData(false, 12345)] [InlineData(true, StatusCodes.Good)] [InlineData(true, "test")] [InlineData(true, 12345)] public void TestDataValue(bool concise, object value) { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true, concise); var expected = new DataValue { Value = value, StatusCode = StatusCodes.Bad, ServerPicoseconds = 10, ServerTimestamp = DateTime.UtcNow }; builder.WriteDataValue(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteDataValue(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadDataValue(null)); } [Theory] [InlineData(false)] [InlineData(true)] public void TestDataValueEmpty(bool concise) { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true, concise); var expected = new DataValue(); builder.WriteDataValue(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteDataValue(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadDataValue(null)); } [Theory] [InlineData(false)] [InlineData(true)] public void TestDataValueNull(bool concise) { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true, concise); builder.WriteDataValue(null, null); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteDataValue(null, null); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.True(Opc.Ua.Utils.IsEqual(new DataValue(), decoder.ReadDataValue(null))); } [Fact] public void TestGuid() { var context = new ServiceMessageContext(); var expected = Guid.NewGuid(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteGuid(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteGuid(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadGuid(null)); } [Fact] public void TestDateTime() { var context = new ServiceMessageContext(); var expected = DateTime.UtcNow; using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteDateTime(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteDateTime(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadDateTime(null)); } [Fact] public void TestXmlElement1() { var context = new ServiceMessageContext(); var expected = new XmlDocument(); expected.LoadXml(""); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteXmlElement(null, expected.DocumentElement); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteXmlElement(null, expected.DocumentElement); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); var actual = new XmlDocument(); actual.Load(decoder.ReadXmlElement(null).CreateNavigator().ReadSubtree()); Assert.Equal(expected.OuterXml, actual.OuterXml); } [Theory] [InlineData(false)] [InlineData(true)] public void TestXmlElement2(bool concise) { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, concise); var expected = VariantVariants.XmlElement; builder.WriteXmlElement(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteXmlElement(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); var actual = new XmlDocument(); actual.Load(decoder.ReadXmlElement(null).CreateNavigator().ReadSubtree()); Assert.Equal(expected.OuterXml, actual.OuterXml); } [Fact] public void TestQualifiedName() { var context = new ServiceMessageContext(); var ns = context.NamespaceUris.GetIndexOrAppend("test.org"); var expected = new QualifiedName("test", ns); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteQualifiedName(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteQualifiedName(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadQualifiedName(null)); } [Fact] public void TestLocalizedText() { var context = new ServiceMessageContext(); var expected = new LocalizedText("test", "en"); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteLocalizedText(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteLocalizedText(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadLocalizedText(null)); } [Fact] public void TestExtensionObject() { var context = new ServiceMessageContext(); var expected = new ExtensionObject(new NodeId(1234), new byte[] { 0, 1, 2, 3 }); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteExtensionObject(null, expected); stream.Position = 0; var json = builder.Schema.ToJson(); Assert.NotNull(json); using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteExtensionObject(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); var actual = decoder.ReadExtensionObject(null); Assert.Equal(expected.TypeId, actual.TypeId); Assert.Equal(expected.Body, actual.Body); } [Fact] public void TestStatusCodeArray() { var context = new ServiceMessageContext(); var expected = new StatusCode[] { StatusCodes.Good, StatusCodes.Bad }; using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteStatusCodeArray(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteStatusCodeArray(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); var actual = decoder.ReadStatusCodeArray(null); Assert.Equal(expected, actual); } [Fact] public void TestNodeIdArray() { var context = new ServiceMessageContext(); var ns = context.NamespaceUris.GetIndexOrAppend("test.org"); var expected = new NodeId[] { new(123, ns), new(456, ns) }; using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteNodeIdArray(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteNodeIdArray(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); var actual = decoder.ReadNodeIdArray(null); Assert.Equal(expected, actual); } [Fact] public void TestExpandedNodeIdArray() { var context = new ServiceMessageContext(); context.NamespaceUris.GetIndexOrAppend("test.org"); var srv = context.ServerUris.GetIndexOrAppend("Super"); var expected = new ExpandedNodeId[] { new(123u, 0, "test.org", srv), new(456u, 0, "test.org", srv) }; using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteExpandedNodeIdArray(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteExpandedNodeIdArray(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); var actual = decoder.ReadExpandedNodeIdArray(null); Assert.Equal(expected, actual); } [Fact] public void TestInt16() { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteInt16(null, 123); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteInt16(null, 123); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(123, decoder.ReadInt16(null)); } [Fact] public void TestSByte() { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteSByte(null, 123); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteSByte(null, 123); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(123, decoder.ReadSByte(null)); } [Fact] public void TestByte() { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteByte(null, 123); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteByte(null, 123); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(123, decoder.ReadByte(null)); } [Fact] public void TestDiagnosticInfo() { var context = new ServiceMessageContext(); var expected = new DiagnosticInfo { AdditionalInfo = "dd" }; using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteDiagnosticInfo(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteDiagnosticInfo(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); var result = decoder.ReadDiagnosticInfo(null); AssertEqual(expected, result); } [Fact] public void TestDiagnosticInfoWithInner() { var context = new ServiceMessageContext(); var expected = new DiagnosticInfo { AdditionalInfo = "outer", InnerDiagnosticInfo = new DiagnosticInfo { AdditionalInfo = "inner" } }; using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteDiagnosticInfo(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteDiagnosticInfo(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); var result = decoder.ReadDiagnosticInfo(null); AssertEqual(expected, result); } [Fact] public void TestEnum() { var context = new ServiceMessageContext(); const DiagnosticsLevel expected = DiagnosticsLevel.Basic; using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteEnumerated(null, expected); stream.Position = 0; var json = builder.Schema.ToJson(); Assert.NotNull(json); using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteEnumerated(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); var result = decoder.ReadEnumerated(null); Assert.Equal(expected, result); } [Fact] public void TestEnumAsInteger() { var context = new ServiceMessageContext(); using var stream = new MemoryStream(); const int expected = 1; using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteEnumerated(null, expected); stream.Position = 0; var json = builder.Schema.ToJson(); Assert.NotNull(json); using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteEnumerated(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); var result = decoder.ReadEnumerated(null); Assert.Equal((DiagnosticsLevel)expected, result); } [Fact] public void TestEnumArray() { var context = new ServiceMessageContext(); var expected = new DiagnosticsLevel[] { DiagnosticsLevel.Basic, DiagnosticsLevel.Advanced }; using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteEnumeratedArray(null, expected, null); stream.Position = 0; var json = builder.Schema.ToJson(); Assert.NotNull(json); using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteEnumeratedArray(null, expected, null); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); var actual = decoder.ReadEnumeratedArray(null); Assert.Equal(expected, actual); } [Fact] public void TestDiagnosticInfoArray() { var context = new ServiceMessageContext(); var expected = new DiagnosticInfo[] { new() { AdditionalInfo = "dd" }, new() { AdditionalInfo = string.Empty } }; using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteDiagnosticInfoArray(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteDiagnosticInfoArray(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); var actual = decoder.ReadDiagnosticInfoArray(null); Assert.Equal(expected.Length, actual.Count); for (var i = 0; i < expected.Length; i++) { var result = actual[i]; AssertEqual(expected[i], result); } } [Theory] [InlineData(0)] [InlineData(1)] [InlineData(3)] [InlineData(4096)] public void TestBooleanArray(int length) { var context = new ServiceMessageContext(); var expected = Enumerable.Range(0, length).Select(v => v % 2 == 0).ToArray(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteBooleanArray(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteBooleanArray(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadBooleanArray(null)); } [Theory] [InlineData(0)] [InlineData(1)] [InlineData(3)] [InlineData(4096)] public void TestSByteArray(int length) { var context = new ServiceMessageContext(); var expected = Enumerable.Range(0, length).Select(v => (sbyte)v).ToArray(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteSByteArray(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteSByteArray(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadSByteArray(null)); } [Theory] [InlineData(0)] [InlineData(1)] [InlineData(3)] [InlineData(4096)] public void TestByteArray(int length) { var context = new ServiceMessageContext(); var expected = Enumerable.Range(0, length).Select(v => (byte)v).ToArray(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteByteArray(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteByteArray(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadByteArray(null)); } [Theory] [InlineData(0)] [InlineData(1)] [InlineData(3)] [InlineData(4096)] public void TestInt16Array(int length) { var context = new ServiceMessageContext(); var expected = Enumerable.Range(0, length).Select(v => (short)v).ToArray(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteInt16Array(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteInt16Array(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadInt16Array(null)); } [Theory] [InlineData(0)] [InlineData(1)] [InlineData(3)] [InlineData(4096)] public void TestUInt16Array(int length) { var context = new ServiceMessageContext(); var expected = Enumerable.Range(0, length).Select(v => (ushort)v).ToArray(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteUInt16Array(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteUInt16Array(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadUInt16Array(null)); } [Theory] [InlineData(0)] [InlineData(1)] [InlineData(3)] [InlineData(4096)] public void TestInt32Array(int length) { var context = new ServiceMessageContext(); var expected = Enumerable.Range(0, length).ToArray(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteInt32Array(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteInt32Array(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadInt32Array(null)); } [Theory] [InlineData(0)] [InlineData(1)] [InlineData(3)] [InlineData(4096)] public void TestUInt32Array(int length) { var context = new ServiceMessageContext(); var expected = Enumerable.Range(0, length).Select(v => (uint)v).ToArray(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteUInt32Array(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteUInt32Array(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadUInt32Array(null)); } [Theory] [InlineData(0)] [InlineData(1)] [InlineData(3)] [InlineData(4096)] public void TestInt64Array(int length) { var context = new ServiceMessageContext(); var expected = Enumerable.Range(0, length).Select(v => uint.MaxValue + v).ToArray(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteInt64Array(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteInt64Array(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadInt64Array(null)); } [Theory] [InlineData(0)] [InlineData(1)] [InlineData(3)] [InlineData(4096)] public void TestUInt64Array(int length) { var context = new ServiceMessageContext(); var expected = Enumerable.Range(0, length).Select(v => (ulong)(long.MaxValue + v)).ToArray(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteUInt64Array(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteUInt64Array(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadUInt64Array(null)); } [Theory] [InlineData(0)] [InlineData(1)] [InlineData(3)] [InlineData(4096)] public void TestFloatArray(int length) { var context = new ServiceMessageContext(); var expected = Enumerable.Range(0, length).Select(v => (float)v).ToArray(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteFloatArray(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteFloatArray(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadFloatArray(null)); } [Theory] [InlineData(0)] [InlineData(1)] [InlineData(3)] [InlineData(4096)] public void TestDoubleArray(int length) { var context = new ServiceMessageContext(); var expected = Enumerable.Range(0, length).Select(v => (double)v).ToArray(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteDoubleArray(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteDoubleArray(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadDoubleArray(null)); } [Theory] [InlineData(0)] [InlineData(1)] [InlineData(3)] [InlineData(4096)] public void TestStringArray(int length) { var context = new ServiceMessageContext(); var expected = Enumerable.Range(0, length) .Select(v => v.ToString(CultureInfo.InvariantCulture)).ToArray(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteStringArray(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteStringArray(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadStringArray(null)); } [Theory] [InlineData(0, 0)] [InlineData(1, 1)] [InlineData(3, 0)] [InlineData(3, 3)] [InlineData(4096, 0)] [InlineData(4096, 4096)] public void TestByteStringArray(int length, int bytestringLength) { var context = new ServiceMessageContext(); var buffer = new byte[bytestringLength]; #pragma warning disable CA5394 // Do not use insecure randomness Random.Shared.NextBytes(buffer); #pragma warning restore CA5394 // Do not use insecure randomness var expected = Enumerable.Range(0, length).Select(_ => buffer).ToArray(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteByteStringArray(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteByteStringArray(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadByteStringArray(null)); } [Theory] [InlineData(0)] [InlineData(1)] [InlineData(3)] [InlineData(4096)] public void TestDateTimeArray(int length) { var context = new ServiceMessageContext(); var expected = Enumerable.Range(0, length).Select(_ => DateTime.UtcNow).ToArray(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteDateTimeArray(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteDateTimeArray(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadDateTimeArray(null)); } [Theory] [InlineData(0)] [InlineData(1)] [InlineData(3)] [InlineData(4096)] public void TestUuidArray(int length) { var context = new ServiceMessageContext(); var expected = Enumerable.Range(0, length).Select(_ => (Uuid)Guid.NewGuid()).ToArray(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteGuidArray(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteGuidArray(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadGuidArray(null)); } [Theory] [InlineData(0)] [InlineData(1)] [InlineData(3)] [InlineData(4096)] public void TestGuidArray(int length) { var context = new ServiceMessageContext(); var expected = Enumerable.Range(0, length).Select(_ => Guid.NewGuid()).ToArray(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteGuidArray(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteGuidArray(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadGuidArray(null).Select(g => (Guid)g).ToArray()); } [Fact] public void TestXmlElementArray1() { var context = new ServiceMessageContext(); var expected = new XmlDocument(); expected.LoadXml(""); var expectedArray = new XmlElement[] { expected.DocumentElement, expected.DocumentElement }; using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteXmlElementArray(null, expectedArray); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteXmlElementArray(null, expectedArray); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); var actualArray = decoder.ReadXmlElementArray(null); Assert.Equal(expectedArray.Length, actualArray.Count); for (var i = 0; i < expectedArray.Length; i++) { var actual = new XmlDocument(); actual.Load(actualArray[i].CreateNavigator().ReadSubtree()); Assert.Equal(expected.OuterXml, actual.OuterXml); } } [Fact] public void TestXmlElementArray2() { var context = new ServiceMessageContext(); var expected = VariantVariants.XmlElement; var expectedArray = new XmlElement[] { expected, expected }; using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteXmlElementArray(null, expectedArray); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteXmlElementArray(null, expectedArray); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); var actualArray = decoder.ReadXmlElementArray(null); Assert.Equal(expectedArray.Length, actualArray.Count); for (var i = 0; i < expectedArray.Length; i++) { var actual = new XmlDocument(); actual.Load(actualArray[i].CreateNavigator().ReadSubtree()); Assert.Equal(expected.OuterXml, actual.OuterXml); } } [Theory] [InlineData(0)] [InlineData(1)] [InlineData(3)] [InlineData(4096)] public void TestQualifiedNameArray(int length) { var context = new ServiceMessageContext(); var ns = context.NamespaceUris.GetIndexOrAppend("test.org"); var expected = Enumerable.Range(0, length).Select(v => new QualifiedName("test" + v, ns)).ToArray(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteQualifiedNameArray(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteQualifiedNameArray(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadQualifiedNameArray(null)); } [Theory] [InlineData(false, 0)] [InlineData(false, 1)] [InlineData(false, 3)] [InlineData(false, 4096)] [InlineData(true, 0)] [InlineData(true, 1)] [InlineData(true, 3)] [InlineData(true, 4096)] public void TestLocalizedTextArray1(bool concise, int length) { var context = new ServiceMessageContext(); var expected = Enumerable.Range(0, length).Select(v => new LocalizedText("test" + v, "en")).ToArray(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true, concise); builder.WriteLocalizedTextArray(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteLocalizedTextArray(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); Assert.Equal(expected, decoder.ReadLocalizedTextArray(null)); } [Theory] [InlineData(false, 0)] [InlineData(false, 1)] [InlineData(false, 3)] [InlineData(false, 4096)] [InlineData(true, 0)] [InlineData(true, 1)] [InlineData(true, 3)] [InlineData(true, 4096)] public void TestLocalizedTextArray2(bool concise, int length) { var context = new ServiceMessageContext(); var expected = Enumerable.Range(0, length).Select(v => new LocalizedText("test" + v, "en")).ToArray(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true, concise); builder.WriteArray(null, expected, ValueRanks.OneDimension, BuiltInType.LocalizedText); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteArray(null, expected, ValueRanks.OneDimension, BuiltInType.LocalizedText); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); var result = decoder.ReadArray(null, ValueRanks.OneDimension, BuiltInType.LocalizedText); Assert.Equal(expected, result); } [Fact] public void TestExtensionObjectArray() { var context = new ServiceMessageContext(); var expected = new ExtensionObject[] { new(new NodeId(1234), new byte[] { 0, 1, 2, 3 }), new(new NodeId(1234), new byte[] { 0, 1, 2, 3 }) }; using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true); builder.WriteExtensionObjectArray(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteExtensionObjectArray(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); var actual = decoder.ReadExtensionObjectArray(null); Assert.Equal(expected.Length, actual.Count); for (var i = 0; i < expected.Length; i++) { Assert.Equal(expected[i].TypeId, actual[i].TypeId); Assert.Equal(expected[i].Body, actual[i].Body); } } [Theory] [InlineData(false)] [InlineData(true)] public void TestDataValueArray1(bool concise) { var context = new ServiceMessageContext(); var expected = new DataValue[] { new(), new() }; using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true, concise); builder.WriteDataValueArray(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteDataValueArray(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); var actual = decoder.ReadDataValueArray(null); Assert.Equal(expected.Length, actual.Count); for (var i = 0; i < expected.Length; i++) { Assert.Equal(expected[i], actual[i]); } } [Theory] [InlineData(false)] [InlineData(true)] public void TestDataValueArray2(bool concise) { var context = new ServiceMessageContext(); var expected = new DataValue[] { new() { Value = new Variant(100) }, new() { Value = new Variant(200) } }; using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true, concise); builder.WriteDataValueArray(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteDataValueArray(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); var actual = decoder.ReadDataValueArray(null); Assert.Equal(expected.Length, actual.Count); for (var i = 0; i < expected.Length; i++) { Assert.Equal(expected[i], actual[i]); } } [Theory] [InlineData(true)] [InlineData(false)] public void TestVariantArrayWithDifferentTypes1(bool concise) { var context = new ServiceMessageContext(); var expected = new Variant[] { new(123), new("test") }; using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true, concise); builder.WriteVariantArray(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteVariantArray(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); var json = builder.Schema.ToJson(); Assert.NotNull(json); var actual = decoder.ReadVariantArray(null); Assert.Equal(expected.Length, actual.Count); for (var i = 0; i < expected.Length; i++) { Assert.Equal(expected[i].Value, actual[i].Value); } } [Theory] [InlineData(true)] [InlineData(false)] public void TestVariantArrayWithDifferentTypes2(bool concise) { var context = new ServiceMessageContext(); var expected = new VariantCollection { new Variant(4L), new Variant("test"), new Variant(new long[] {1, 2, 3, 4, 5 }), new Variant(["1", "2", "3", "4", "5"]) }; using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true, concise); builder.WriteVariantArray(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteVariantArray(null, expected); stream.Position = 0; var json = builder.Schema.ToJson(); Assert.NotNull(json); using var decoder = new AvroDecoder(stream, builder.Schema, context); var actual = decoder.ReadVariantArray(null); Assert.Equal(expected.Count, actual.Count); for (var i = 0; i < expected.Count; i++) { Assert.Equal(expected[i].Value, actual[i].Value); } } [Theory] [InlineData(true)] [InlineData(false)] public void TestVariantArrayWithDifferentTypes3(bool concise) { var context = new ServiceMessageContext(); var expected = new VariantCollection { new Variant(new VariantCollection { new Variant(4L), new Variant("test"), new Variant(new long[] {1, 2, 3, 4, 5 }), new Variant(["1", "2", "3", "4", "5"]) }) }; using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true, concise); builder.WriteVariantArray(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteVariantArray(null, expected); stream.Position = 0; var json = builder.Schema.ToJson(); Assert.NotNull(json); using var decoder = new AvroDecoder(stream, builder.Schema, context); var actual = decoder.ReadVariantArray(null); Assert.Equal(expected.Count, actual.Count); for (var i = 0; i < expected.Count; i++) { Assert.Equal(expected[i].Value, actual[i].Value); } } [Theory] [InlineData(true)] [InlineData(false)] public void TestVariantArrayWithSameTypes(bool concise) { var context = new ServiceMessageContext(); var expected = new Variant[] { new(123), new(321), new(0) }; using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true, concise); builder.WriteVariantArray(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteVariantArray(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); var json = builder.Schema.ToJson(); Assert.NotNull(json); var actual = decoder.ReadVariantArray(null); Assert.Equal(expected.Length, actual.Count); for (var i = 0; i < expected.Length; i++) { Assert.Equal(expected[i].Value, actual[i].Value); } } public static TheoryData GetVariantArrays() { return new TheoryData(VariantVariants.GetValues() .Select(v => new VariantsHolder(Enumerable.Repeat(v, 3).ToArray(), v.TypeInfo))); } [Theory] [MemberData(nameof(GetVariantArrays))] public void TestVariantArrayVariants(VariantsHolder value) { var expected = value.Variants.ToArray(); var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true, false); builder.WriteVariantArray(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteVariantArray(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); var json = builder.Schema.ToJson(); Assert.NotNull(json); var actual = decoder.ReadVariantArray(null); Assert.Equal(expected.Length, actual.Count); for (var i = 0; i < expected.Length; i++) { Assert.Equal(expected[i].Value, actual[i].Value); } } [Theory] [MemberData(nameof(GetVariantArrays))] public void TestVariantArrayVariantsConcise(VariantsHolder value) { var expected = value.Variants.ToArray(); var context = new ServiceMessageContext(); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true, true); builder.WriteVariantArray(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteVariantArray(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); var json = builder.Schema.ToJson(); Assert.NotNull(json); var actual = decoder.ReadVariantArray(null); Assert.Equal(expected.Length, actual.Count); for (var i = 0; i < expected.Length; i++) { var result = actual[i]; if (result.Value is not null && expected[i].Value is null) { switch (result.TypeInfo.BuiltInType) { case BuiltInType.String: Assert.Equal(string.Empty, result.Value); return; case BuiltInType.ByteString: Assert.Equal(Array.Empty(), result.Value); return; case BuiltInType.NodeId: Assert.Equal(NodeId.Null, result.Value); return; case BuiltInType.ExpandedNodeId: Assert.Equal(ExpandedNodeId.Null, result.Value); return; case BuiltInType.QualifiedName: Assert.Equal(QualifiedName.Null, result.Value); return; case BuiltInType.LocalizedText: Assert.Equal(new LocalizedText(string.Empty, string.Empty), result.Value); return; case BuiltInType.ExtensionObject: Assert.Equal(ExtensionObject.Null, result.Value); return; case BuiltInType.DataValue: Assert.Equal(new DataValue(), result.Value); return; } } Assert.Equal(expected[i].Value, result.Value); } } [Fact] public void TestVariantWithArray1() { var context = new ServiceMessageContext(); var expected = new Variant(Enumerable.Repeat("test", 3).ToArray()); var schemas = new AvroBuiltInSchemas(); var valueSchema = schemas.GetSchemaForBuiltInType(expected.TypeInfo.BuiltInType, SchemaRank.Collection); var schema = valueSchema.AsNullable().CreateRoot(); using (var stream = new MemoryStream()) using (var encoder = new AvroEncoder(stream, schema, context, true)) { encoder.WriteVariant(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, schema, context); var variant = decoder.ReadVariant(null); Assert.Equal(expected, variant); } using (var stream = new MemoryStream()) using (var encoder = new AvroEncoder(stream, schema, context, true)) { encoder.WriteVariant(null, Variant.Null); stream.Position = 0; using var decoder = new AvroDecoder(stream, schema, context); var variant = decoder.ReadVariant(null); Assert.Equal(Variant.Null, variant); } } [Fact] public void TestVariantWithArray2() { var context = new ServiceMessageContext(); var expected = new Variant(Enumerable.Repeat("test", 3).ToArray()); var schemas = new AvroBuiltInSchemas(); var valueSchema = schemas.GetSchemaForBuiltInType(expected.TypeInfo.BuiltInType, SchemaRank.Collection); var schema = valueSchema.CreateRoot(); using var stream = new MemoryStream(); using var encoder = new AvroEncoder(stream, schema, context, true); encoder.WriteVariant(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, schema, context); var variant = decoder.ReadVariant(null); Assert.Equal(expected, variant); } [Theory] [InlineData(DiagnosticsLevel.Advanced)] [InlineData(BuiltInType.Int32)] public void TestVariantWithEnumeration(object value) { var context = new ServiceMessageContext(); var expected = new Variant(value); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true, true); builder.WriteVariant(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteVariant(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); var json = builder.Schema.ToJson(); Assert.NotNull(json); var result = decoder.ReadVariant(null); Assert.Equal(Convert.ToInt32(value, CultureInfo.InvariantCulture), result.Value); } [Fact] public void TestVariantWithEnumerations() { var context = new ServiceMessageContext(); var expected = new Variant(new[] { DiagnosticsLevel.Advanced, DiagnosticsLevel.Advanced }); using var stream = new MemoryStream(); using var builder = new AvroSchemaBuilder(stream, context, true, true); builder.WriteVariant(null, expected); stream.Position = 0; using var encoder = new AvroEncoder(stream, builder.Schema, context, true); encoder.WriteVariant(null, expected); stream.Position = 0; using var decoder = new AvroDecoder(stream, builder.Schema, context); var json = builder.Schema.ToJson(); Assert.NotNull(json); var result = decoder.ReadVariant(null); Assert.Equal(new int[] { 1, 1 }, result); } private static void AssertEqual(DiagnosticInfo x, DiagnosticInfo y) { if (x == y) { return; } Assert.NotNull(x); Assert.NotNull(y); Assert.Equal(x.NamespaceUri, y.NamespaceUri); Assert.Equal(x.LocalizedText, y.LocalizedText); Assert.Equal(x.Locale, y.Locale); Assert.Equal(x.AdditionalInfo, y.AdditionalInfo); Assert.Equal(x.InnerStatusCode, y.InnerStatusCode); Assert.Equal(x.NamespaceUri, y.NamespaceUri); AssertEqual(x.InnerDiagnosticInfo, y.InnerDiagnosticInfo); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/AvroFileWriterTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Avro; using Furly; using Furly.Extensions.Logging; using Furly.Extensions.Messaging; using Microsoft.Extensions.Options; using System; using System.Buffers; using System.Collections.Generic; using System.IO; using System.Text; using System.Threading.Tasks; using Xunit; /// /// Test avro file writer /// public sealed class AvroFileWriterTests { [Fact] public void SupportsContentTypeTests() { using var writer = new AvroFileWriter(Options.Create(new AvroFileWriterOptions()), Log.Console()); Assert.True(writer.SupportsContentType(ContentType.Avro)); Assert.True(writer.SupportsContentType(ContentType.AvroGzip)); Assert.False(writer.SupportsContentType(ContentType.Uadp)); Assert.False(writer.SupportsContentType(ContentMimeType.Binary)); } [Fact] public void SupportsNothingWhenDisabledTests() { using var writer = new AvroFileWriter(Options.Create( new AvroFileWriterOptions { Disabled = true }), Log.Console()); Assert.False(writer.SupportsContentType(ContentType.Avro)); Assert.False(writer.SupportsContentType(ContentType.AvroGzip)); Assert.False(writer.SupportsContentType(ContentType.Uadp)); } [Fact] public async Task TestAvroFileWriter1Async() { var file = Path.GetTempFileName(); try { using (var writer = new AvroFileWriter(Options.Create(new AvroFileWriterOptions()), Log.Console())) { await writer.WriteAsync(file, DateTime.UtcNow, new[] { new ReadOnlySequence([1, 2, 3]) }, null, new DummyEventSchema(), ContentType.Avro); } Assert.True(File.Exists(file + ".avro")); using var reader = new AvroFileReader(file); Assert.True(reader.HasMore()); var result = reader.Read((s, t) => { var buffer = t.ReadAsBuffer(); Assert.Equal(1, buffer[0]); Assert.Equal(2, buffer[1]); Assert.Equal(3, buffer[2]); Assert.Equal(3, buffer.Count); Assert.True(s is UnionSchema); return 123; }); Assert.False(reader.HasMore()); Assert.Equal(123, result); } finally { File.Delete(file + ".avro"); } } [Fact] public async Task TestAvroFileWriter2Async() { var file = Path.GetTempFileName(); try { using (var writer = new AvroFileWriter(Options.Create(new AvroFileWriterOptions()), Log.Console())) { await writer.WriteAsync(file, DateTime.UtcNow, new[] { new ReadOnlySequence([1, 2, 3]), new ReadOnlySequence([1, 2, 3]), new ReadOnlySequence([1, 2, 3]) }, null, new DummyEventSchema(), ContentType.Avro); } using var reader = new AvroFileReader(file); for (var i = 0; i < 3; i++) { Assert.True(reader.HasMore()); var result = reader.Read((s, t) => { Assert.Equal(1, t.ReadByte()); Assert.Equal(2, t.ReadByte()); Assert.Equal(3, t.ReadByte()); Assert.True(s is UnionSchema); return 123; }); Assert.Equal(123, result); } Assert.False(reader.HasMore()); } finally { File.Delete(file + ".avro"); } } [Fact] public async Task TestAvroFileWriter3Async() { var file = Path.GetTempFileName(); try { using (var writer = new AvroFileWriter(Options.Create(new AvroFileWriterOptions()), Log.Console())) { await writer.WriteAsync(file, DateTime.UtcNow, Array.Empty>(), null, new DummyEventSchema(), ContentType.Avro); } Assert.True(File.Exists(file + ".avro")); using var reader = new AvroFileReader(file); Assert.False(reader.HasMore()); Assert.Throws(() => reader.Read((s, t) => 123)); } finally { File.Delete(file + ".avro"); } } [Fact] public async Task TestAvroFileWriter4Async() { var file = Path.GetTempFileName(); try { const string expected = "teststring"; var buffer = new ReadOnlySequence(Encoding.UTF8.GetBytes(expected)); using (var writer = new AvroFileWriter(Options.Create(new AvroFileWriterOptions()), Log.Console())) { await writer.WriteAsync(file, DateTime.UtcNow, new[] { buffer.GzipCompress() }, new Dictionary { ["testmeta"] = "mtest" }, new DummyEventSchema(), ContentType.AvroGzip); } Assert.True(File.Exists(file + ".avro")); using var reader = new AvroFileReader(file); Assert.True(reader.HasMore()); var result = reader.Read((s, t) => { var buffer = t.ReadAsBuffer(); Assert.Equal(expected, Encoding.UTF8.GetString(buffer)); return 123; }); Assert.False(reader.HasMore()); Assert.Equal(123, result); } finally { File.Delete(file + ".avro"); } } [Fact] public async Task TestAvroFileWriter5Async() { var file = Path.GetTempFileName(); try { const string expected = "teststring"; var buffer = new ReadOnlySequence(Encoding.UTF8.GetBytes(expected)); using (var writer = new AvroFileWriter(Options.Create(new AvroFileWriterOptions()), Log.Console())) { await writer.WriteAsync(file, DateTime.UtcNow, new[] { buffer.GzipCompress(), buffer.GzipCompress(), buffer.GzipCompress() }, null, new DummyEventSchema(), ContentType.AvroGzip); } Assert.True(File.Exists(file + ".avro")); using var reader = new AvroFileReader(file); Assert.True(reader.HasMore()); var result = reader.Read((s, t) => { var buffer = t.ReadAsBuffer(); Assert.Equal(expected + expected + expected, Encoding.UTF8.GetString(buffer)); return 123; }); Assert.Equal(123, result); Assert.True(reader.HasMore()); } finally { File.Delete(file + ".avro"); } } [Theory] [InlineData("")] [InlineData("ab")] [InlineData("badheader")] public async Task TestBadHeader1Async(string data) { var file = Path.GetTempFileName(); try { await File.WriteAllTextAsync(file + ".avro", data); Assert.Throws(() => new AvroFileReader(file)); } finally { File.Delete(file + ".avro"); } } private sealed class DummyEventSchema : IEventSchema { public string Id => "test"; public string Schema => "[]"; public string Type => "test"; public string Name => "test"; public ulong Version => 1; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Extensions/ExpandedNodeIdExTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Opc.Ua.Extensions { using Azure.IIoT.OpcUa.Publisher.Models; using System; using Xunit; public class ExpandedNodeIdExTests { [Fact] public void DecodeExpandedNodeIdFromStringNoUri() { var context = new ServiceMessageContext(); const string expected = " space tests /(%)§;#;;#;()§$\"))\"\")(§"; var result = ("s=" + expected).ToExpandedNodeId(context); Assert.Equal(expected, result.Identifier); result = ("s_" + expected).ToExpandedNodeId(context); Assert.Equal(expected, result.Identifier); } [Fact] public void DecodeExpandedNodeIdFromStringUrlEncodedNoUri() { var context = new ServiceMessageContext(); const string expected = " space tests /(%)§;#;;#;()§$\"))\"\")(§"; var result = ("s=" + expected.UrlEncode()).ToExpandedNodeId(context); Assert.Equal(expected, result.Identifier); } [Fact] public void DecodeExpandedNodeIdFromString() { var context = new ServiceMessageContext(); const string expected = " space tests /(%)§;#;;#;()§$\"))\"\")(§"; const string uri = "http://contosos.com/UA"; var result = (uri + "#s=" + expected).ToExpandedNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(0, result.NamespaceIndex); } [Fact] public void DecodeExpandedNodeIdFromStringUrnNamespace() { var context = new ServiceMessageContext(); const string expected = " space tests /(%)§;#;;#;()§$\"))\"\")(§"; const string uri = "urn:contosos"; var result = (uri + "#s=" + expected).ToExpandedNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(0, result.NamespaceIndex); } [Fact] public void DecodeExpandedNodeIdFromStringInvalidUri() { var context = new ServiceMessageContext(); const string expected = " space tests /(%)§;#;;#;()§$\"))\"\")(§"; const string uri = "invalidUri"; var result = (uri + "#s=" + expected).ToExpandedNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(0, result.NamespaceIndex); } [Fact] public void DecodeExpandedNodeIdFromStringWithNamespaceIndex() { var context = new ServiceMessageContext(); const string expected = " space tests /(%)§;#;;#;()§$\"))\"\")(§"; const string uri = "http://contosos.com/UA"; var result = ("ns=" + context.NamespaceUris.GetIndexOrAppend(uri) + ";s=" + expected) .ToExpandedNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(1, result.NamespaceIndex); } [Fact] public void DecodeExpandedNodeIdFromStringWithNsu() { var context = new ServiceMessageContext(); const string expected = " space tests /(%)§;#;;#;()§$\"))\"\")(§"; const string uri = "http://contosos.com/UA"; var index = context.NamespaceUris.GetIndexOrAppend(uri); var result = ("nsu=" + uri + ";s=" + expected) .ToExpandedNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(uri, result.NamespaceUri); Assert.Equal(0, result.NamespaceIndex); Assert.Equal(1, index); } [Fact] public void DecodeExpandedNodeIdFromStringWithNsuBadNamespace() { var context = new ServiceMessageContext(); const string expected = " space tests /(%)§;#;;#;()§$\"))\"\")(§"; const string uri = "contosos"; var index = context.NamespaceUris.GetIndexOrAppend(uri); var result = ("nsu=" + uri + ";s=" + expected) .ToExpandedNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(uri, result.NamespaceUri); Assert.Equal(0, result.NamespaceIndex); Assert.Equal(1, index); } [Fact] public void DecodeExpandedNodeIdFromStringWithNsuUrnNamespace() { var context = new ServiceMessageContext(); const string expected = " space tests /(%)§;#;;#;()§$\"))\"\")(§"; const string uri = "urn:contosos"; var index = context.NamespaceUris.GetIndexOrAppend(uri); var result = ("nsu=" + uri + ";s=" + expected) .ToExpandedNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(uri, result.NamespaceUri); Assert.Equal(0, result.NamespaceIndex); Assert.Equal(1, index); } [Fact] public void DecodeExpandedNodeIdFromStringUrlEncoded() { var context = new ServiceMessageContext(); const string expected = " space tests /(%)§;#;;#;()§$\"))\"\")(§"; const string uri = "http://contosos.com/UA"; var result = (uri + "#s=" + expected.UrlEncode()).ToExpandedNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(0, result.NamespaceIndex); } [Fact] public void DecodeExpandedNodeIdFromBufferNoUri() { var context = new ServiceMessageContext(); var expected = new byte[] { 0, 34, 23, 255, 6, 34, 65, 0, 0, 2, 0 }; var result = ("b=" + expected.ToBase64String()).ToExpandedNodeId(context); Assert.Equal(expected, result.Identifier); result = ("b_" + expected.ToBase64String()).ToExpandedNodeId(context); Assert.Equal(expected, result.Identifier); } [Fact] public void DecodeExpandedNodeIdFromBufferUrlEncodedNoUri() { var context = new ServiceMessageContext(); var expected = new byte[] { 0, 34, 23, 255, 6, 34, 65, 0, 0, 2, 0 }; var result = ("b=" + expected.ToBase64String().UrlEncode()).ToExpandedNodeId(context); Assert.Equal(expected, result.Identifier); } [Fact] public void DecodeExpandedNodeIdFromBuffer() { var context = new ServiceMessageContext(); var expected = new byte[] { 0, 34, 23, 255, 6, 34, 65, 0, 0, 2, 0 }; const string uri = "http://contosos.com/UA"; var result = (uri + "#b=" + expected.ToBase64String()).ToExpandedNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(0, result.NamespaceIndex); } [Fact] public void DecodeExpandedNodeIdFromBufferUrlEncoded() { var context = new ServiceMessageContext(); var expected = new byte[] { 0, 34, 23, 255, 6, 34, 65, 0, 0, 2, 0 }; const string uri = "http://contosos.com/UA"; var result = (uri + "#b=" + expected.ToBase64String().UrlEncode()).ToExpandedNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(0, result.NamespaceIndex); } [Fact] public void DecodeExpandedNodeIdFromBufferWithNamespaceIndex() { var context = new ServiceMessageContext(); var expected = Guid.NewGuid().ToByteArray(); const string uri = "http://contosos.com/UA"; var result = ("ns=" + context.NamespaceUris.GetIndexOrAppend(uri) + ";b=" + expected.ToBase64String()) .ToExpandedNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(1, result.NamespaceIndex); } [Fact] public void DecodeExpandedNodeIdFromBufferWithNsu() { var context = new ServiceMessageContext(); var expected = Guid.NewGuid().ToByteArray(); const string uri = "http://contosos.com/UA"; var index = context.NamespaceUris.GetIndexOrAppend(uri); var result = ("nsu=" + uri + ";b=" + expected.ToBase64String()) .ToExpandedNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(uri, result.NamespaceUri); Assert.Equal(0, result.NamespaceIndex); Assert.Equal(1, index); } [Fact] public void DecodeExpandedNodeIdFromGuidNoUri() { var context = new ServiceMessageContext(); var expected = Guid.NewGuid(); var result = ("g=" + expected).ToExpandedNodeId(context); Assert.Equal(expected, result.Identifier); result = ("g_" + expected).ToExpandedNodeId(context); Assert.Equal(expected, result.Identifier); } [Fact] public void DecodeExpandedNodeIdFromGuidUrlEncodedNoUri() { var context = new ServiceMessageContext(); var expected = Guid.NewGuid(); var result = ("g=" + expected.ToString().UrlEncode()).ToExpandedNodeId(context); Assert.Equal(expected, result.Identifier); } [Fact] public void DecodeExpandedNodeIdFromGuid() { var context = new ServiceMessageContext(); var expected = Guid.NewGuid(); const string uri = "http://contosos.com/UA/"; var result = (uri + "#g=" + expected).ToExpandedNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(0, result.NamespaceIndex); } [Fact] public void DecodeExpandedNodeIdFromGuidUrlEncoded() { var context = new ServiceMessageContext(); var expected = Guid.NewGuid(); const string uri = "http://contosos.com/UA/"; var result = (uri + "#g=" + expected.ToString().UrlEncode()).ToExpandedNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(0, result.NamespaceIndex); } [Fact] public void DecodeExpandedNodeIdFromGuidWithNamespaceIndex() { var context = new ServiceMessageContext(); var expected = Guid.NewGuid(); const string uri = "http://contosos.com/UA"; var result = ("ns=" + context.NamespaceUris.GetIndexOrAppend(uri) + ";g=" + expected) .ToExpandedNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(1, result.NamespaceIndex); } [Fact] public void DecodeExpandedNodeIdFromGuidWithNsu() { var context = new ServiceMessageContext(); var expected = Guid.NewGuid(); const string uri = "http://contosos.com/UA"; var index = context.NamespaceUris.GetIndexOrAppend(uri); var result = ("nsu=" + uri + ";g=" + expected) .ToExpandedNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(uri, result.NamespaceUri); Assert.Equal(0, result.NamespaceIndex); Assert.Equal(1, index); } [Fact] public void EncodeDecodeExpandedNodeIdWithString() { var context = new ServiceMessageContext(); const string uri = "http://contoso.com/UA"; context.NamespaceUris.GetIndexOrAppend(uri); var expected = new ExpandedNodeId(" space tests /(%)§;#;;#;()§$\"))\"\")(§", 0, uri, 0); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToExpandedNodeId(context); var result2 = s2.ToExpandedNodeId(context); AssertEqual(expected, result1, result2); } [Fact] public void EncodeDecodeExpandedNodeIdWithStringAndDefaultUri() { var context = new ServiceMessageContext(); var expected = new ExpandedNodeId(" space tests /(%)§;#;;#;()§$\"))\"\")(§", 0); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToExpandedNodeId(context); var result2 = s2.ToExpandedNodeId(context); AssertEqual(expected, result1, result2); } [Fact] public void EncodeDecodeExpandedNodeIdWithGuid() { var context = new ServiceMessageContext(); const string uri = "http://contoso.com/UA"; var expected = new ExpandedNodeId(Guid.NewGuid(), 0, uri, 0); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToExpandedNodeId(context); var result2 = s2.ToExpandedNodeId(context); AssertEqual(expected, result1, result2); } [Fact] public void EncodeDecodeExpandedNodeIdWithGuidAndDefaultUri() { var context = new ServiceMessageContext(); var expected = new ExpandedNodeId(Guid.NewGuid()); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToExpandedNodeId(context); var result2 = s2.ToExpandedNodeId(context); AssertEqual(expected, result1, result2); } [Fact] public void EncodeDecodeExpandedNodeIdWithInt() { var context = new ServiceMessageContext(); const string uri = "http://contoso.com/UA"; context.NamespaceUris.GetIndexOrAppend(uri); var expected = new ExpandedNodeId(1u, 0, uri, 0); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToExpandedNodeId(context); var result2 = s2.ToExpandedNodeId(context); AssertEqual(expected, result1, result2); } [Fact] public void EncodeDecodeExpandedNodeIdWithIntAndDefaultUri() { var context = new ServiceMessageContext(); var expected = new ExpandedNodeId(111111111, 0); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToExpandedNodeId(context); var result2 = s2.ToExpandedNodeId(context); AssertEqual(expected, result1, result2); } [Fact] public void EncodeDecodeExpandedNodeIdWithBuffer() { var context = new ServiceMessageContext(); const string uri = "http://contoso.com/UA"; context.NamespaceUris.GetIndexOrAppend(uri); var expected = new ExpandedNodeId(Guid.NewGuid().ToByteArray(), 0, uri, 0); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToExpandedNodeId(context); var result2 = s2.ToExpandedNodeId(context); AssertEqual(expected, result1, result2); } [Fact] public void EncodeDecodeExpandedNodeIdWithBufferAndDefaultUri() { var context = new ServiceMessageContext(); var expected = new ExpandedNodeId(Guid.NewGuid().ToByteArray(), 0); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToExpandedNodeId(context); var result2 = s2.ToExpandedNodeId(context); AssertEqual(expected, result1, result2); } [Fact] public void EncodeDecodeExpandedNodeIdWithEmptyString() { var context = new ServiceMessageContext(); const string uri = "http://contoso.com/UA"; context.NamespaceUris.GetIndexOrAppend(uri); var expected = new ExpandedNodeId("", 0, uri, 0); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToExpandedNodeId(context); var result2 = s2.ToExpandedNodeId(context); AssertEqual(expected, result1, result2); } [Fact] public void EncodeDecodeExpandedNodeIdWithEmptyStringAndDefaultUri() { var context = new ServiceMessageContext(); var expected = new ExpandedNodeId("", 0); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToExpandedNodeId(context); var result2 = s2.ToExpandedNodeId(context); AssertEqual(ExpandedNodeId.Null, result1, result2); } [Fact] public void EncodeDecodeExpandedNodeIdWithNullString() { var context = new ServiceMessageContext(); const string uri = "http://contoso.com/UA"; context.NamespaceUris.GetIndexOrAppend(uri); var expected = new ExpandedNodeId(null, 0, uri, 0); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToExpandedNodeId(context); var result2 = s2.ToExpandedNodeId(context); Assert.Equal(expected, result1); Assert.Equal(expected, result2); Assert.True(Utils.IsEqual(result1, result2)); Assert.Equal(string.Empty, result1.Identifier); Assert.Equal(expected.NamespaceIndex, result1.NamespaceIndex); Assert.Equal(string.Empty, result2.Identifier); Assert.Equal(expected.NamespaceIndex, result2.NamespaceIndex); } [Fact] public void EncodeDecodeExpandedNodeIdWithNullStringAndDefaultUri() { var context = new ServiceMessageContext(); var expected = new ExpandedNodeId((string)null, 0); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToExpandedNodeId(context); var result2 = s2.ToExpandedNodeId(context); Assert.Equal(ExpandedNodeId.Null, result1); Assert.Equal(ExpandedNodeId.Null, result2); Assert.True(Utils.IsEqual(result1, result2)); } [Fact] public void EncodeDecodeNullExpandedNodeId() { var context = new ServiceMessageContext(); var expected = ExpandedNodeId.Null; var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToExpandedNodeId(context); var result2 = s2.ToExpandedNodeId(context); Assert.Equal(expected, result1); Assert.Equal(expected, result2); Assert.True(Utils.IsEqual(result1, result2)); } private static void AssertEqual(ExpandedNodeId expected, ExpandedNodeId result1, ExpandedNodeId result2) { Assert.Equal(expected.Identifier, result1.Identifier); Assert.Equal(expected.Identifier, result2.Identifier); Assert.Equal(expected, result1); Assert.Equal(expected, result2); Assert.True(Utils.IsEqual(result1, result2)); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Extensions/LocalizedTextExTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Opc.Ua.Extensions { using Xunit; public class LocalizedTextExTests { [Fact] public void DecodeLocalizedTextWithLocale() { var expected = new LocalizedText("en-US", "text"); var result = "text@en-US".ToLocalizedText(); Assert.Equal(expected, result); } [Fact] public void DecodeLocalizedTextWithLocale2() { var expected = new LocalizedText("en-US", "text@"); var result = "text@@en-US".ToLocalizedText(); Assert.Equal(expected, result); } [Fact] public void DecodeLocalizedTextWithoutLocale() { var expected = new LocalizedText("text"); var result = "text".ToLocalizedText(); Assert.Equal(expected, result); } [Fact] public void DecodeLocalizedTextWithoutLocale1() { var expected = new LocalizedText("text"); var result = "text@".ToLocalizedText(); Assert.Equal(expected, result); } [Fact] public void DecodeLocalizedTextWithTwoAtAndLocale() { var expected = new LocalizedText("en-US", "text@contoso.org"); var result = "text@contoso.org@en-US".ToLocalizedText(); Assert.Equal(expected, result); } [Fact] public void DecodeLocalizedTextWithTwoAtAndWithoutLocale() { var expected = new LocalizedText("text@contoso.org"); var result = "text@contoso.org@".ToLocalizedText(); Assert.Equal(expected, result); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Extensions/NodeIdExTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Opc.Ua.Extensions { using Azure.IIoT.OpcUa.Publisher.Models; using System; using Xunit; public class NodeIdExTests { [Fact] public void DecodeNodeIdFromStringNoUri() { var context = new ServiceMessageContext(); const string expected = " space tests /(%)§;#;;#;()§$\"))\"\")(§"; var result = ("s=" + expected).ToNodeId(context); Assert.Equal(expected, result.Identifier); result = ("s_" + expected).ToNodeId(context); Assert.Equal(expected, result.Identifier); } [Fact] public void DecodeNodeIdFromStringUrlEncodedNoUri() { var context = new ServiceMessageContext(); const string expected = " space tests /(%)§;#;;#;()§$\"))\"\")(§"; var result = ("s=" + expected.UrlEncode()).ToNodeId(context); Assert.Equal(expected, result.Identifier); } [Fact] public void DecodeNodeIdFromString() { var context = new ServiceMessageContext(); const string expected = " space tests /(%)§;#;;#;()§$\"))\"\")(§"; const string uri = "http://contosos.com/UA"; var result = (uri + "#s=" + expected).ToNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(1, result.NamespaceIndex); } [Fact] public void DecodeNodeIdFromStringInvalidUri() { var context = new ServiceMessageContext(); const string expected = " space tests /(%)§;#;;#;()§$\"))\"\")(§"; const string uri = "invalidUri"; var result = (uri + "#s=" + expected).ToNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(1, result.NamespaceIndex); } [Fact] public void DecodeNodeIdFromStringUrnUri() { var context = new ServiceMessageContext(); const string expected = " space tests /(%)§;#;;#;()§$\"))\"\")(§"; const string uri = "urn:contosos"; var result = (uri + "#s=" + expected).ToNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(1, result.NamespaceIndex); } [Fact] public void DecodeNodeIdFromStringWithNamespaceIndex() { var context = new ServiceMessageContext(); const string expected = " space tests /(%)§;#;;#;()§$\"))\"\")(§"; const string uri = "http://contosos.com/UA"; var result = ("ns=" + context.NamespaceUris.GetIndexOrAppend(uri) + ";s=" + expected) .ToNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(1, result.NamespaceIndex); } [Fact] public void DecodeNodeIdFromStringWithNsu() { var context = new ServiceMessageContext(); const string expected = " space tests /(%)§;#;;#;()§$\"))\"\")(§"; const string uri = "http://contosos.com/UA"; var index = context.NamespaceUris.GetIndexOrAppend(uri); var result = ("nsu=" + uri + ";s=" + expected) .ToNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(1, result.NamespaceIndex); Assert.Equal(1, index); } [Fact] public void DecodeNodeIdFromStringUrlEncoded() { var context = new ServiceMessageContext(); const string expected = " space tests /(%)§;#;;#;()§$\"))\"\")(§"; const string uri = "http://contosos.com/UA"; var result = (uri + "#s=" + expected.UrlEncode()).ToNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(1, result.NamespaceIndex); } [Fact] public void DecodeNodeIdFromIntUrl() { var context = new ServiceMessageContext(); const string uri = "http://contosos.com#i=1"; var result = uri.ToExpandedNodeId(context); Assert.Equal("http://contosos.com", result.NamespaceUri); } [Fact] public void ParseNodeIdUsingAbsoluteUri() { const string value = "http://contosos.com#i=1"; Uri.TryCreate(value, UriKind.Absolute, out var uri); Assert.NotEqual("http://contosos.com", uri.NoQueryAndFragment().AbsoluteUri); } [Fact] public void DecodeNodeIdFromBufferNoUri() { var context = new ServiceMessageContext(); var expected = new byte[] { 0, 34, 23, 255, 6, 34, 65, 0, 0, 2, 0 }; var result = ("b=" + expected.ToBase64String()).ToNodeId(context); Assert.Equal(expected, result.Identifier); result = ("b_" + expected.ToBase64String()).ToNodeId(context); Assert.Equal(expected, result.Identifier); } [Fact] public void DecodeNodeIdFromBufferUrlEncodedNoUri() { var context = new ServiceMessageContext(); var expected = new byte[] { 0, 34, 23, 255, 6, 34, 65, 0, 0, 2, 0 }; var result = ("b=" + expected.ToBase64String().UrlEncode()).ToNodeId(context); Assert.Equal(expected, result.Identifier); } [Fact] public void DecodeNodeIdFromBuffer() { var context = new ServiceMessageContext(); var expected = new byte[] { 0, 34, 23, 255, 6, 34, 65, 0, 0, 2, 0 }; const string uri = "http://contosos.com/UA"; var result = (uri + "#b=" + expected.ToBase64String()).ToNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(1, result.NamespaceIndex); } [Fact] public void DecodeNodeIdFromBufferUrlEncoded() { var context = new ServiceMessageContext(); var expected = new byte[] { 0, 34, 23, 255, 6, 34, 65, 0, 0, 2, 0 }; const string uri = "http://contosos.com/UA"; var result = (uri + "#b=" + expected.ToBase64String().UrlEncode()).ToNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(1, result.NamespaceIndex); } [Fact] public void DecodeNodeIdFromBufferWithNamespaceIndex() { var context = new ServiceMessageContext(); var expected = Guid.NewGuid().ToByteArray(); const string uri = "http://contosos.com/UA"; var result = ("ns=" + context.NamespaceUris.GetIndexOrAppend(uri) + ";b=" + expected.ToBase64String()) .ToNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(1, result.NamespaceIndex); } [Fact] public void DecodeNodeIdFromBufferWithNsu() { var context = new ServiceMessageContext(); var expected = Guid.NewGuid().ToByteArray(); const string uri = "http://contosos.com/UA"; var index = context.NamespaceUris.GetIndexOrAppend(uri); var result = ("nsu=" + uri + ";b=" + expected.ToBase64String()) .ToNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(1, result.NamespaceIndex); Assert.Equal(1, index); } [Fact] public void DecodeNodeIdFromGuidNoUri() { var context = new ServiceMessageContext(); var expected = Guid.NewGuid(); var result = ("g=" + expected).ToNodeId(context); Assert.Equal(expected, result.Identifier); result = ("g_" + expected).ToNodeId(context); Assert.Equal(expected, result.Identifier); } [Fact] public void DecodeNodeIdFromGuidUrlEncodedNoUri() { var context = new ServiceMessageContext(); var expected = Guid.NewGuid(); var result = ("g=" + expected.ToString().UrlEncode()).ToNodeId(context); Assert.Equal(expected, result.Identifier); } [Fact] public void DecodeNodeIdFromGuid() { var context = new ServiceMessageContext(); var expected = Guid.NewGuid(); const string uri = "http://contosos.com/UA/"; var result = (uri + "#g=" + expected).ToNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(1, result.NamespaceIndex); } [Fact] public void DecodeNodeIdFromGuidUrlEncoded() { var context = new ServiceMessageContext(); var expected = Guid.NewGuid(); const string uri = "http://contosos.com/UA/"; var result = (uri + "#g=" + expected.ToString().UrlEncode()).ToNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(1, result.NamespaceIndex); } [Fact] public void DecodeNodeIdFromGuidWithNamespaceIndex() { var context = new ServiceMessageContext(); var expected = Guid.NewGuid(); const string uri = "http://contosos.com/UA"; var result = ("ns=" + context.NamespaceUris.GetIndexOrAppend(uri) + ";g=" + expected) .ToNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(1, result.NamespaceIndex); } [Fact] public void DecodeNodeIdFromGuidWithNsu() { var context = new ServiceMessageContext(); var expected = Guid.NewGuid(); const string uri = "http://contosos.com/UA"; var index = context.NamespaceUris.GetIndexOrAppend(uri); var result = ("nsu=" + uri + ";g=" + expected) .ToNodeId(context); Assert.Equal(expected, result.Identifier); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(1, result.NamespaceIndex); Assert.Equal(1, index); } [Fact] public void EncodeDecodeNodeIdWithString() { var context = new ServiceMessageContext(); var expected = new NodeId(" space tests /(%)§;#;;#;()§$\"))\"\")(§", context.NamespaceUris.GetIndexOrAppend("http://contoso.com/UA")); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToNodeId(context); var result2 = s2.ToNodeId(context); AssertEqual(expected, result1, result2); } [Fact] public void EncodeDecodeNodeIdWithStringAndInvalidUri() { var context = new ServiceMessageContext(); var expected = new NodeId(" space tests /(%)§;#;;#;()§$\"))\"\")(§", context.NamespaceUris.GetIndexOrAppend("contoso")); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToNodeId(context); var result2 = s2.ToNodeId(context); Assert.Equal(s1, s2); Assert.Contains("nsu=", s2, StringComparison.Ordinal); Assert.DoesNotContain("ns=", s2, StringComparison.Ordinal); AssertEqual(expected, result1, result2); } [Fact] public void EncodeDecodeNodeIdWithStringAndDefaultUri() { var context = new ServiceMessageContext(); var expected = new NodeId(" space tests /(%)§;#;;#;()§$\"))\"\")(§", 0); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToNodeId(context); var result2 = s2.ToNodeId(context); AssertEqual(expected, result1, result2); } [Fact] public void EncodeDecodeNodeIdWithGuid() { var context = new ServiceMessageContext(); var expected = new NodeId(Guid.NewGuid(), context.NamespaceUris.GetIndexOrAppend("http://contoso.com/UA")); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToNodeId(context); var result2 = s2.ToNodeId(context); AssertEqual(expected, result1, result2); } [Fact] public void EncodeDecodeNodeIdWithGuidAndDefaultUri() { var context = new ServiceMessageContext(); var expected = new NodeId(Guid.NewGuid(), 0); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToNodeId(context); var result2 = s2.ToNodeId(context); AssertEqual(expected, result1, result2); } [Fact] public void EncodeDecodeNodeIdWithInt() { var context = new ServiceMessageContext(); var expected = new NodeId(1, context.NamespaceUris.GetIndexOrAppend("http://contoso.com/UA")); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToNodeId(context); var result2 = s2.ToNodeId(context); AssertEqual(expected, result1, result2); } [Fact] public void EncodeDecodeNodeIdWithIntAndDefaultUri() { var context = new ServiceMessageContext(); var expected = new NodeId(111111111, 0); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToNodeId(context); var result2 = s2.ToNodeId(context); AssertEqual(expected, result1, result2); } [Fact] public void EncodeDecodeNodeIdWithBuffer() { var context = new ServiceMessageContext(); var expected = new NodeId(Guid.NewGuid().ToByteArray(), context.NamespaceUris.GetIndexOrAppend("http://contoso.com/UA")); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToNodeId(context); var result2 = s2.ToNodeId(context); AssertEqual(expected, result1, result2); } [Fact] public void EncodeDecodeNodeIdWithBufferAndDefaultUri() { var context = new ServiceMessageContext(); var expected = new NodeId(Guid.NewGuid().ToByteArray(), 0); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToNodeId(context); var result2 = s2.ToNodeId(context); AssertEqual(expected, result1, result2); } [Fact] public void EncodeDecodeNodeIdWithEmptyString() { var context = new ServiceMessageContext(); var expected = new NodeId("", context.NamespaceUris.GetIndexOrAppend("http://contoso.com/UA")); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToNodeId(context); var result2 = s2.ToNodeId(context); AssertEqual(expected, result1, result2); } [Fact] public void EncodeDecodeNodeIdWithEmptyStringAndDefaultUri() { var context = new ServiceMessageContext(); var input = new NodeId("", 0); var s1 = input.AsString(context, NamespaceFormat.Uri); var s2 = input.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToNodeId(context); var result2 = s2.ToNodeId(context); AssertEqual(NodeId.Null, result1, result2); } [Fact] public void EncodeDecodeNodeIdWithNullStringAndDefaultUri() { var context = new ServiceMessageContext(); var input = new NodeId((string)null, 0); // == NodeId.Null var s1 = input.AsString(context, NamespaceFormat.Uri); var s2 = input.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToNodeId(context); var result2 = s2.ToNodeId(context); AssertEqual(NodeId.Null, result1, result2); } [Fact] public void EncodeDecodeNullNodeId() { var context = new ServiceMessageContext(); var expected = NodeId.Null; var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToNodeId(context); var result2 = s2.ToNodeId(context); AssertEqual(expected, result1, result2); } private static void AssertEqual(NodeId expected, NodeId result1, NodeId result2) { Assert.Equal(expected.Identifier, result1.Identifier); Assert.Equal(expected.NamespaceIndex, result1.NamespaceIndex); Assert.Equal(expected.Identifier, result2.Identifier); Assert.Equal(expected.NamespaceIndex, result2.NamespaceIndex); Assert.Equal(expected, result1); Assert.Equal(expected, result2); Assert.True(Utils.IsEqual(result1, result2)); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Extensions/QualifiedNameExTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Opc.Ua.Extensions { using Azure.IIoT.OpcUa.Publisher.Models; using System; using Xunit; public class QualifiedNameExTests { [Fact] public void DecodeQnFromStringNoUri() { var context = new ServiceMessageContext(); const string expected = " space tests /(%)§;#;;#;()§$\"))\"\")(§"; var result = expected.ToQualifiedName(context); Assert.Equal(expected, result.Name); } [Fact] public void DecodeQnFromStringUrlEncodedNoUri() { var context = new ServiceMessageContext(); const string expected = " space tests /(%)§;#;;#;()§$\"))\"\")(§"; var result = expected.UrlEncode().ToQualifiedName(context); Assert.Equal(expected, result.Name); } [Fact] public void DecodeQnFromString() { var context = new ServiceMessageContext(); const string expected = " space tests /(%)§;#;;#;()§$\"))\"\")(§"; const string uri = "http://contosos.com/UA"; var result = (uri + "#" + expected).ToQualifiedName(context); Assert.Equal(expected, result.Name); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(1, result.NamespaceIndex); } [Fact] public void DecodeQnFromStringUrlEncoded() { var context = new ServiceMessageContext(); const string expected = " space tests /(%)§;#;;#;()§$\"))\"\")(§"; const string uri = "http://contosos.com/UA"; var result = (uri + "#" + expected.UrlEncode()).ToQualifiedName(context); Assert.Equal(expected, result.Name); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(1, result.NamespaceIndex); } [Fact] public void DecodeQnFromStringUrlEncodedBadNamespaceUri() { var context = new ServiceMessageContext(); const string expected = " space tests /(%)§;#;;#;()§$\"))\"\")(§"; const string uri = "contosos"; var result = (uri + "#" + expected.UrlEncode()).ToQualifiedName(context); Assert.Equal(expected, result.Name); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(1, result.NamespaceIndex); } [Fact] public void DecodeQnFromStringUrnNamespaceUri() { var context = new ServiceMessageContext(); const string expected = " space tests /(%)§;#;;#;()§$\"))\"\")(§"; const string uri = "urn:contosos"; var result = (uri + "#" + expected).ToQualifiedName(context); Assert.Equal(expected, result.Name); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(1, result.NamespaceIndex); } [Fact] public void DecodeQnFromStringUrlEncodedUrnNamespaceUri() { var context = new ServiceMessageContext(); const string expected = " space tests /(%)§;#;;#;()§$\"))\"\")(§"; const string uri = "urn:contosos"; var result = (uri + "#" + expected.UrlEncode()).ToQualifiedName(context); Assert.Equal(expected, result.Name); Assert.Equal(uri, context.NamespaceUris.GetString(1)); Assert.Equal(1, result.NamespaceIndex); } [Fact] public void EncodeDecodeQualifiedName() { var context = new ServiceMessageContext(); var expected = new QualifiedName(" space tests /(%)§;#;;#;()§$\"))\"\")(§", context.NamespaceUris.GetIndexOrAppend("http://contoso.com/UA")); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToQualifiedName(context); var result2 = s2.ToQualifiedName(context); Assert.Equal(expected, result1); Assert.Equal(result1, result2); } [Fact] public void EncodeDecodeQualifiedNameDefaultUri() { var context = new ServiceMessageContext(); var expected = new QualifiedName(" space tests /(%)§;#;;#;()§$\"))\"\")(§", 0); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToQualifiedName(context); var result2 = s2.ToQualifiedName(context); Assert.Equal(expected, result1); Assert.Equal(result1, result2); } [Fact] public void EncodeDecodeQualifiedNameWithEmptyString() { var context = new ServiceMessageContext(); var expected = new QualifiedName("", context.NamespaceUris.GetIndexOrAppend("http://contoso.com/UA")); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToQualifiedName(context); var result2 = s2.ToQualifiedName(context); // BUG IN Stack: Assert.Equal(expected, result1); Assert.Null(result1.Name); Assert.Equal(expected.NamespaceIndex, result1.NamespaceIndex); // BUG IN Stack: Assert.Equal(expected, result2); Assert.Null(result2.Name); Assert.Equal(expected.NamespaceIndex, result2.NamespaceIndex); // BUG IN Stack: Assert.True(Utils.IsEqual(result1, result2)); } [Fact] public void EncodeDecodeQualifiedNameWithEmptyStringDefaultUri() { var context = new ServiceMessageContext(); var expected = new QualifiedName("", 0); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToQualifiedName(context); var result2 = s2.ToQualifiedName(context); // BUG IN Stack: Assert.Equal(expected, result1); Assert.Null(result1.Name); Assert.Equal(expected.NamespaceIndex, result1.NamespaceIndex); // BUG IN Stack: Assert.Equal(expected, result2); Assert.Null(result2.Name); Assert.Equal(expected.NamespaceIndex, result2.NamespaceIndex); // BUG IN Stack: Assert.True(Utils.IsEqual(result1, result2)); } [Fact] public void EncodeDecodeQualifiedNameWithNullString() { var context = new ServiceMessageContext(); var expected = new QualifiedName(null, context.NamespaceUris.GetIndexOrAppend("http://contoso.com/UA")); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToQualifiedName(context); var result2 = s2.ToQualifiedName(context); // BUG IN Stack: Assert.Equal(expected, result1); Assert.Equal(expected.Name, result1.Name); Assert.Equal(expected.NamespaceIndex, result1.NamespaceIndex); // BUG IN Stack: Assert.Equal(expected, result2); Assert.Equal(expected.Name, result2.Name); Assert.Equal(expected.NamespaceIndex, result2.NamespaceIndex); // BUG IN Stack: Assert.True(Utils.IsEqual(result1, result2)); } [Fact] public void EncodeDecodeQualifiedNameWithNullStringDefaultUri() { var context = new ServiceMessageContext(); var expected = new QualifiedName(null, 0); var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToQualifiedName(context); var result2 = s2.ToQualifiedName(context); // BUG IN Stack: Assert.Equal(expected, result1); Assert.Equal(expected.Name, result1.Name); Assert.Equal(expected.NamespaceIndex, result1.NamespaceIndex); // BUG IN Stack: Assert.Equal(expected, result2); Assert.Equal(expected.Name, result2.Name); Assert.Equal(expected.NamespaceIndex, result2.NamespaceIndex); // BUG IN Stack: Assert.True(Utils.IsEqual(result1, result2)); } [Fact] public void EncodeDecodeNullQualifiedName() { var context = new ServiceMessageContext(); var expected = QualifiedName.Null; var s1 = expected.AsString(context, NamespaceFormat.Uri); var s2 = expected.AsString(context, NamespaceFormat.Expanded); var result1 = s1.ToQualifiedName(context); var result2 = s2.ToQualifiedName(context); Assert.Equal(expected, result1); // BUG IN Stack: Assert.Equal(expected, result2); Assert.Equal(expected.Name, result2.Name); Assert.Equal(expected.NamespaceIndex, result2.NamespaceIndex); // BUG IN Stack: Assert.True(Utils.IsEqual(result1, result2)); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Extensions/TypeInfoExTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Opc.Ua.Extensions { using Xunit; public class TypeInfoExTests { [Fact] public void ScalarBoolNullTest1() { var variant = TypeInfo.Scalars.Boolean.CreateVariant(null); Assert.Equal(false, variant.Value); } [Fact] public void ScalarBoolTest1() { var variant = TypeInfo.Scalars.Boolean.CreateVariant(true); Assert.Equal(true, variant.Value); } [Fact] public void ScalarByteTest1() { var variant = TypeInfo.Scalars.Byte.CreateVariant((byte)5); Assert.Equal((byte)5, variant.Value); } [Fact] public void ScalarByteNullTest1() { var variant = TypeInfo.Scalars.Byte.CreateVariant(null); Assert.Equal((byte)0, variant.Value); } [Fact] public void ScalarStringTest1() { var variant = TypeInfo.Scalars.String.CreateVariant("test"); Assert.Equal("test", variant.Value); } [Fact] public void ScalarExtensionObjectTest1() { var variant = TypeInfo.Scalars.ExtensionObject.CreateVariant(new ExtensionObject("s=test")); Assert.Equal(new ExtensionObject("s=test"), variant.Value); } [Fact] public void ArrayBoolNullTest1() { var variant = TypeInfo.Arrays.Boolean.CreateVariant(null); Assert.Equal(System.Array.Empty(), variant.Value); } [Fact] public void ArrayByteTest1() { var variant = TypeInfo.Arrays.Byte.CreateVariant(new byte[] { 1, 2, 3 }); Assert.Equal(new byte[] { 1, 2, 3 }, variant.Value); } [Fact] public void ArrayStringTest1() { var variant = TypeInfo.Arrays.String.CreateVariant(new string[] { "", "", "" }); Assert.Equal(new string[] { "", "", "" }, variant.Value); } [Fact] public void ArrayStringNullTest1() { var variant = TypeInfo.Arrays.String.CreateVariant(null); Assert.Equal(System.Array.Empty(), variant.Value); } [Fact] public void ArrayExtensionObjectTest1() { var expected = new[] { new ExtensionObject(new ExpandedNodeId("test1", 0)), new ExtensionObject(new ExpandedNodeId("test2", 0)), new ExtensionObject(new ExpandedNodeId("test3", 0)), new ExtensionObject(new ExpandedNodeId("test4", 0)) }; var variant = TypeInfo.Arrays.ExtensionObject.CreateVariant(expected); Assert.Equal(expected, variant.Value); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/JsonDataSetTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Azure.IIoT.OpcUa.Encoders.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Opc.Ua; using System; using System.Collections.Generic; using System.IO; using System.Linq; using Xunit; public class JsonDataSetTests { [Fact] public void ReadWriteProgramDiagnostic2DataTypeStream() { // Create dummy type var expected = VariantVariants.Complex; const int count = 100; byte[] buffer; var context = new ServiceMessageContext(); using (var stream = new MemoryStream()) { using (var encoder = new JsonEncoderEx(stream, context, JsonEncoderEx.JsonEncoding.Array)) { for (var i = 0; i < count; i++) { encoder.WriteEncodeable(null, expected, expected.GetType()); } } buffer = stream.ToArray(); } using (var stream = new MemoryStream(buffer)) using (var decoder = new JsonDecoderEx(stream, context)) { for (var i = 0; i < count; i++) { var result = decoder.ReadEncodeable(null, expected.GetType()); Assert.True(result.IsEqual(expected)); } var eof = decoder.ReadEncodeable(null, expected.GetType()); Assert.Null(eof); } } [Fact] public void ReadWriteDataValueWithIntStream() { // Create dummy var expected = new DataValue(new Variant(12345)); const int count = 10000; byte[] buffer; var context = new ServiceMessageContext(); using (var stream = new MemoryStream()) { using (var encoder = new JsonEncoderEx(stream, context, JsonEncoderEx.JsonEncoding.Array)) { for (var i = 0; i < count; i++) { encoder.WriteDataValue(null, expected); } } buffer = stream.ToArray(); } using (var stream = new MemoryStream(buffer)) using (var decoder = new JsonDecoderEx(stream, context)) { for (var i = 0; i < count; i++) { var result = decoder.ReadDataValue(null); Assert.Equal(expected, result); } var eof = decoder.ReadDataValue(null); Assert.Null(eof); } } [Fact] public void ReadWriteDataValueWithStringStream() { // Create dummy var expected = new DataValue(new Variant("TestTestTestTest" + Guid.NewGuid())); const int count = 10000; byte[] buffer; var context = new ServiceMessageContext(); using (var stream = new MemoryStream()) { using (var encoder = new JsonEncoderEx(stream, context, JsonEncoderEx.JsonEncoding.Array)) { for (var i = 0; i < count; i++) { encoder.WriteDataValue(null, expected); } } buffer = stream.ToArray(); } using (var stream = new MemoryStream(buffer)) using (var decoder = new JsonDecoderEx(stream, context)) { for (var i = 0; i < count; i++) { var result = decoder.ReadDataValue(null); Assert.Equal(expected, result); } var eof = decoder.ReadDataValue(null); Assert.Null(eof); } } [Fact] public void ReadWriteDataSetArrayTest() { // Create dummy var expected = new DataSet(new Dictionary { ["abcd"] = new DataValue(new Variant(1234), StatusCodes.Good, DateTime.UtcNow, DateTime.UtcNow), ["http://microsoft.com"] = new DataValue(new Variant(-222222222), StatusCodes.Bad, DateTime.MinValue, DateTime.UtcNow), ["1111111111111111111111111"] = new DataValue(new Variant(false), StatusCodes.Bad, DateTime.UtcNow, DateTime.MinValue), ["@#$%^&*()_+~!@#$%^*(){}"] = new DataValue(new Variant(new byte[] { 0, 2, 4, 6 }), StatusCodes.Good), ["1245"] = new DataValue(new Variant("hello"), StatusCodes.Bad, DateTime.UtcNow, DateTime.MinValue), ["..."] = new DataValue(new Variant("imbricated")) }); const int count = 10000; byte[] buffer; var context = new ServiceMessageContext(); using (var stream = new MemoryStream()) { using (var encoder = new JsonEncoderEx(stream, context, JsonEncoderEx.JsonEncoding.Array)) { for (var i = 0; i < count; i++) { encoder.WriteDataSet(null, expected); } } buffer = stream.ToArray(); } using (var stream = new MemoryStream(buffer)) using (var decoder = new JsonDecoderEx(stream, context)) { for (var i = 0; i < count; i++) { var result = decoder.ReadDataSet(null); Assert.Equal(expected, result); } var eof = decoder.ReadDataSet(null); Assert.Null(eof); } } [Fact] public void ReadWriteDataSetWithSingleEntryTest() { // Create dummy var expected = new DataSet(new Dictionary { ["abcd"] = new DataValue(new Variant(1234), StatusCodes.Good, DateTime.UtcNow, DateTime.UtcNow) }); expected.DataSetFieldContentMask |= DataSetFieldContentFlags.SingleFieldDegradeToValue; byte[] buffer; var context = new ServiceMessageContext(); using (var stream = new MemoryStream()) { using (var encoder = new JsonEncoderEx(stream, context, JsonEncoderEx.JsonEncoding.Array)) { encoder.WriteDataSet(null, expected); } buffer = stream.ToArray(); } using (var stream = new MemoryStream(buffer)) using (var decoder = new JsonDecoderEx(stream, context)) { var result = decoder.ReadDataValue(null); Assert.Equal(expected.DataSetFields.FirstOrDefault(f => f.Name == "abcd").Value, result); } } [Fact] public void ReadWriteDataSetWithSingleValueRawTest() { // Create dummy var expected = new DataSet(new Dictionary { ["abcd"] = new DataValue(new Variant(1234), StatusCodes.Good, DateTime.UtcNow, DateTime.UtcNow) }); expected.DataSetFieldContentMask |= DataSetFieldContentFlags.SingleFieldDegradeToValue; expected.DataSetFieldContentMask |= DataSetFieldContentFlags.RawData; byte[] buffer; var context = new ServiceMessageContext(); using (var stream = new MemoryStream()) { using (var encoder = new JsonEncoderEx(stream, context, JsonEncoderEx.JsonEncoding.Array)) { encoder.WriteDataSet(null, expected); } buffer = stream.ToArray(); } using (var stream = new MemoryStream(buffer)) using (var decoder = new JsonDecoderEx(stream, context)) { var result = decoder.ReadInt32(null); Assert.Equal(expected.DataSetFields.FirstOrDefault(f => f.Name == "abcd").Value.Value, result); } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Models/EncodeableDictionaryTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Models { using Opc.Ua; using System.IO; using Xunit; public class EncodeableDictionaryTests { [Fact] public void WriteReadKeyDataValuePairs() { const string expectedKey1 = "Key1"; const string expectedKey2 = "Key2"; const string expectedKey3 = "Key3"; var expectedValue1 = new DataValue(new Variant(123)); var expectedValue2 = new DataValue(new Variant(456)); var expectedValue3 = new DataValue(new Variant(789)); var encodeableDictionary = new EncodeableDictionary { new KeyDataValuePair { Key = expectedKey1, Value = expectedValue1 }, new KeyDataValuePair { Key = expectedKey2, Value = expectedValue2 }, new KeyDataValuePair { Key = expectedKey3, Value = expectedValue3 } }; byte[] buffer; var context = new ServiceMessageContext(); using (var stream = new MemoryStream()) { using (var encoder = new JsonEncoderEx(stream, context, JsonEncoderEx.JsonEncoding.StartObject)) { encodeableDictionary.Encode(encoder); } // Encoder must be closed before getting buffer. buffer = stream.ToArray(); } using (var stream = new MemoryStream(buffer)) { using var decoder = new JsonDecoderEx(stream, context); var actual = new EncodeableDictionary(); actual.Decode(decoder); Assert.Equal(3, actual.Count); Assert.Equal(expectedKey1, actual[0].Key); Assert.Equal(expectedValue1, actual[0].Value); Assert.Equal(expectedKey2, actual[1].Key); Assert.Equal(expectedValue2, actual[1].Value); Assert.Equal(expectedKey3, actual[2].Key); Assert.Equal(expectedValue3, actual[2].Value); var eof = decoder.ReadDataValue(null); Assert.Null(eof); } } [Fact] public void WriteReadNoKeyDataValuePairs() { var encodeableDictionary = new EncodeableDictionary(); byte[] buffer; var context = new ServiceMessageContext(); using (var stream = new MemoryStream()) { using (var encoder = new JsonEncoderEx(stream, context, JsonEncoderEx.JsonEncoding.StartObject)) { encodeableDictionary.Encode(encoder); } // Encoder must be closed before getting buffer. buffer = stream.ToArray(); } using (var stream = new MemoryStream(buffer)) { using var decoder = new JsonDecoderEx(stream, context); var actual = new EncodeableDictionary(); actual.Decode(decoder); Assert.Empty(actual); var eof = decoder.ReadDataValue(null); Assert.Null(eof); } } [Fact] public void WriteReadEmptyKeyDataValuePairs() { var value = new DataValue(new Variant(123)); var encodeableDictionary = new EncodeableDictionary { new KeyDataValuePair { Key = string.Empty, Value = value }, new KeyDataValuePair { Key = string.Empty, Value = value }, new KeyDataValuePair { Key = string.Empty, Value = value } }; byte[] buffer; var context = new ServiceMessageContext(); using (var stream = new MemoryStream()) { using (var encoder = new JsonEncoderEx(stream, context, JsonEncoderEx.JsonEncoding.StartObject)) { encodeableDictionary.Encode(encoder); } // Encoder must be closed before getting buffer. buffer = stream.ToArray(); } using (var stream = new MemoryStream(buffer)) { using var decoder = new JsonDecoderEx(stream, context); var actual = new EncodeableDictionary(); actual.Decode(decoder); Assert.Empty(actual); var eof = decoder.ReadDataValue(null); Assert.Null(eof); } } [Fact] public void WriteReadNoNullKeyDataValuePairs() { const string expectedKey1 = "Key1"; const string expectedKey2 = "Key2"; const string expectedKey3 = "Key3"; var encodeableDictionary = new EncodeableDictionary { new KeyDataValuePair { Key = expectedKey1, Value = null }, new KeyDataValuePair { Key = expectedKey2, Value = null }, new KeyDataValuePair { Key = expectedKey3, Value = null } }; byte[] buffer; var context = new ServiceMessageContext(); using (var stream = new MemoryStream()) { using (var encoder = new JsonEncoderEx(stream, context, JsonEncoderEx.JsonEncoding.StartObject)) { encodeableDictionary.Encode(encoder); } // Encoder must be closed before getting buffer. buffer = stream.ToArray(); } using (var stream = new MemoryStream(buffer)) { using var decoder = new JsonDecoderEx(stream, context); var actual = new EncodeableDictionary(); actual.Decode(decoder); Assert.Empty(actual); var eof = decoder.ReadDataValue(null); Assert.Null(eof); } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/PubSub/AvroNetworkMessageEncoderDecoderTests1.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.PubSub { using Azure.IIoT.OpcUa.Encoders.Models; using Azure.IIoT.OpcUa.Encoders.Schemas.Avro; using Azure.IIoT.OpcUa.Publisher.Models; using Avro; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Opc.Ua; using System; using System.Collections.Generic; using System.Linq; using Xunit; /// /// Avro encoder decoder tests /// public class AvroNetworkMessageEncoderDecoderTests1 { public const NetworkMessageContentFlags NetworkMessageContentMaskDefault = NetworkMessageContentFlags.NetworkMessageHeader | NetworkMessageContentFlags.DataSetMessageHeader; public const DataSetFieldContentFlags DataSetFieldContentFlagsDefault = DataSetFieldContentFlags.SourceTimestamp | DataSetFieldContentFlags.ServerTimestamp | DataSetFieldContentFlags.SourcePicoSeconds | DataSetFieldContentFlags.ServerPicoSeconds | DataSetFieldContentFlags.StatusCode; [Theory] [InlineData(false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1, MessageType.KeyFrame)] [InlineData(false, NetworkMessageContentMaskDefault, 3, MessageType.Condition)] [InlineData(false, NetworkMessageContentMaskDefault, 1, MessageType.DeltaFrame)] [InlineData(true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1, MessageType.KeyFrame)] [InlineData(true, NetworkMessageContentMaskDefault, 3, MessageType.KeepAlive)] [InlineData(true, NetworkMessageContentMaskDefault, 1, MessageType.Event)] public void EncodeDecodeNetworkMessage(bool compress, NetworkMessageContentFlags contentMask, int numberOfMessages, MessageType messageType) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(sequenceNumber, messageType: messageType, statusCode: StatusCodes.Good)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask, messages); networkMessage.UseGzipCompression = compress; var context = new ServiceMessageContext(); var buffer = Assert.Single(networkMessage.Encode(context, 256 * 1000)); var schema = networkMessage.Schema; Assert.NotNull(schema); var json = schema.ToJson(); context = new ServiceMessageContext(); buffer = Assert.Single(networkMessage.Encode(context, 256 * 1000)); Assert.Equal(schema, networkMessage.Schema); ConvertToOpcUaUniversalTime(networkMessage); var result = PubSubMessage.Decode(buffer, networkMessage.ContentType, context, messageSchema: json); Assert.Equal(networkMessage, result); } [Theory] [InlineData(false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1, MessageType.KeyFrame)] [InlineData(false, NetworkMessageContentMaskDefault, 3, MessageType.Condition)] [InlineData(false, NetworkMessageContentMaskDefault, 1, MessageType.DeltaFrame)] [InlineData(true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1, MessageType.KeyFrame)] [InlineData(true, NetworkMessageContentMaskDefault, 3, MessageType.KeepAlive)] [InlineData(true, NetworkMessageContentMaskDefault, 1, MessageType.Event)] public void EncodeDecodeNetworkMessageWithNullableDataValue(bool compress, NetworkMessageContentFlags contentMask, int numberOfMessages, MessageType messageType) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(sequenceNumber, messageType: messageType, statusCode: null)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask, messages); networkMessage.UseGzipCompression = compress; var context = new ServiceMessageContext(); var buffer = Assert.Single(networkMessage.Encode(context, 256 * 1000)); var schema = networkMessage.Schema; Assert.NotNull(schema); var json = schema.ToJson(); // Set null data value messages.ForEach(messages => messages.Payload = messages.Payload.Set("6", null)); // Reencode with the schema context = new ServiceMessageContext(); buffer = Assert.Single(networkMessage.Encode(context, 256 * 1000)); Assert.Equal(schema, networkMessage.Schema); ConvertToOpcUaUniversalTime(networkMessage); var result = PubSubMessage.Decode(buffer, networkMessage.ContentType, context, messageSchema: json); Assert.Equal(networkMessage, result); } [Theory] [InlineData(false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1, MessageType.KeyFrame)] [InlineData(false, NetworkMessageContentMaskDefault, 3, MessageType.Condition)] [InlineData(false, NetworkMessageContentMaskDefault, 1, MessageType.DeltaFrame)] [InlineData(true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1, MessageType.KeyFrame)] [InlineData(true, NetworkMessageContentMaskDefault, 3, MessageType.KeepAlive)] [InlineData(true, NetworkMessageContentMaskDefault, 1, MessageType.Event)] public void EncodeDecodeNetworkMessageWithMissingDataValue(bool compress, NetworkMessageContentFlags contentMask, int numberOfMessages, MessageType messageType) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(sequenceNumber, messageType: messageType, statusCode: null)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask, messages); networkMessage.UseGzipCompression = compress; var context = new ServiceMessageContext(); var buffer = Assert.Single(networkMessage.Encode(context, 256 * 1000)); var schema = networkMessage.Schema; Assert.NotNull(schema); var json = schema.ToJson(); // Set null data value messages.ForEach(messages => messages.Payload = messages.Payload.Remove("6")); // Reencode with the schema context = new ServiceMessageContext(); buffer = Assert.Single(networkMessage.Encode(context, 256 * 1000)); Assert.Equal(schema, networkMessage.Schema); ConvertToOpcUaUniversalTime(networkMessage); var result = PubSubMessage.Decode(buffer, networkMessage.ContentType, context, messageSchema: json); // Result will contain the removed field in the data set as it was serialized as null ((BaseNetworkMessage)result).Messages.ToList().ForEach(m => { Assert.Null(m.Payload.DataSetFields.FirstOrDefault(f => f.Name == "6").Value); m.Payload = m.Payload.Remove("6"); }); Assert.Equal(networkMessage, result); } [Theory] [InlineData(false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(false, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(false, NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(false, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(true, NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(true, NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(true, NetworkMessageContentMaskDefault, 15, 1024)] public void EncodeDecodeNetworkMessages(bool compress, NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(sequenceNumber, messageType: MessageType.DeltaFrame)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask, messages); networkMessage.UseGzipCompression = compress; var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); var schema = networkMessage.Schema; Assert.NotNull(schema); var json = schema.ToJson(); ConvertToOpcUaUniversalTime(networkMessage); var m = buffers .Select(buffer => (BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context, messageSchema: json)) .ToList(); var result = m[0]; result.Messages = m.SelectMany(m => m.Messages).ToList(); Assert.Equal(networkMessage, result); } [Theory] [InlineData(false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(false, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(false, NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(false, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(true, NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(true, NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(true, NetworkMessageContentMaskDefault, 15, 1024)] public void EncodeDecodeNetworkMessagesWithNullableDataValue(bool compress, NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(sequenceNumber, messageType: MessageType.DeltaFrame)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask, messages); networkMessage.UseGzipCompression = compress; var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); var schema = networkMessage.Schema; Assert.NotNull(schema); var json = schema.ToJson(); // Set null data value messages.ForEach(messages => messages.Payload = messages.Payload.Set("6", null)); // Reencode with the schema context = new ServiceMessageContext(); buffers = networkMessage.Encode(context, maxMessageSize); Assert.Equal(schema, networkMessage.Schema); ConvertToOpcUaUniversalTime(networkMessage); var m = buffers .Select(buffer => (BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context, messageSchema: json)) .ToList(); var result = m[0]; result.Messages = m.SelectMany(m => m.Messages).ToList(); Assert.Equal(networkMessage, result); } [Theory] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 1024)] public void EncodeDecodeNetworkMessagesNoNetworkMessageHeader( NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(sequenceNumber, messageType: MessageType.Event)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask & ~NetworkMessageContentFlags.NetworkMessageHeader, messages); var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); var schema = networkMessage.Schema; Assert.NotNull(schema); var json = schema.ToJson(); ConvertToOpcUaUniversalTime(networkMessage); var result = buffers .SelectMany(buffer => ((BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context, messageSchema: json)).Messages) .ToList(); Assert.Equal(networkMessage.Messages, result); } [Theory] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 1024)] public void EncodeDecodeNetworkMessagesNoNetworkMessageHeaderRaw( NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(sequenceNumber, dataSetFieldContentMask: DataSetFieldContentFlags.RawData, messageType: MessageType.Condition)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask & ~NetworkMessageContentFlags.NetworkMessageHeader, messages); var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); var schema = networkMessage.Schema; Assert.NotNull(schema); var json = schema.ToJson(); ConvertToOpcUaUniversalTime(networkMessage); var result = buffers .SelectMany(buffer => ((BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context, messageSchema: json)).Messages) .SelectMany(m => m.Payload.DataSetFields) .Select(v => (v.Name, v.Value?.Value)) .ToList(); var serializer = new NewtonsoftJsonSerializer(); var expected = serializer.Parse(serializer.SerializeToString(messages .SelectMany(m => m.Payload.DataSetFields) .Select(v => (v.Name, v.Value?.Value)) .ToList())); } [Theory] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 1024)] public void EncodeDecodeNetworkMessagesNoDataSetMessageHeader( NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(sequenceNumber)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask & ~NetworkMessageContentFlags.DataSetMessageHeader, messages); var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); var schema = networkMessage.Schema; Assert.NotNull(schema); var json = schema.ToJson(); ConvertToOpcUaUniversalTime(networkMessage); var result = buffers .SelectMany(buffer => ((BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context, messageSchema: json)).Messages) .Select(m => m.Payload) .ToList(); Assert.All(networkMessage.Messages.Select(m => m.Payload), (p, i) => Assert.True(result[i].Equals(p))); } [Theory] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 1024)] public void EncodeDecodeNetworkMessagesNoDataSetMessageHeaderWithNullableDataValues( NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(sequenceNumber)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask & ~NetworkMessageContentFlags.DataSetMessageHeader, messages); var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); var schema = networkMessage.Schema; Assert.NotNull(schema); var json = schema.ToJson(); // Set null data value messages.ForEach(messages => messages.Payload = messages.Payload.Set("6", null)); // Reencode with the schema context = new ServiceMessageContext(); buffers = networkMessage.Encode(context, maxMessageSize); Assert.Equal(schema, networkMessage.Schema); ConvertToOpcUaUniversalTime(networkMessage); var result = buffers .SelectMany(buffer => ((BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context, messageSchema: json)).Messages) .Select(m => m.Payload) .ToList(); Assert.All(networkMessage.Messages.Select(m => m.Payload), (p, i) => Assert.True(result[i].Equals(p))); } [Theory] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 1024)] public void EncodeDecodeNetworkMessagesNoDataSetMessageHeaderRaw( NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(sequenceNumber, dataSetFieldContentMask: DataSetFieldContentFlags.RawData)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask & ~NetworkMessageContentFlags.DataSetMessageHeader, messages); var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); var schema = networkMessage.Schema; Assert.NotNull(schema); var json = schema.ToJson(); ConvertToOpcUaUniversalTime(networkMessage); var result = buffers .SelectMany(buffer => ((BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context, messageSchema: json)).Messages) .SelectMany(m => m.Payload.DataSetFields) .Select(v => (v.Name, v.Value?.Value)) .ToList(); var serializer = new NewtonsoftJsonSerializer(); var expected = serializer.Parse(serializer.SerializeToString(messages .SelectMany(m => m.Payload.DataSetFields) .Select(v => (v.Name, v.Value?.Value)) .ToList())); } [Theory] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 1024)] public void EncodeDecodeNetworkMessagesNoHeader( NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(sequenceNumber)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask & ~(NetworkMessageContentFlags.NetworkMessageHeader | NetworkMessageContentFlags.DataSetMessageHeader), messages); var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); var schema = networkMessage.Schema; Assert.NotNull(schema); var json = schema.ToJson(); ConvertToOpcUaUniversalTime(networkMessage); var result = buffers .SelectMany(buffer => ((BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context, messageSchema: json)).Messages) .Select(m => m.Payload) .ToList(); Assert.All(networkMessage.Messages.Select(m => m.Payload), (p, i) => Assert.True(result[i].Equals(p))); } [Theory] [InlineData(5, 256 * 1024)] [InlineData(10, 256 * 1024)] [InlineData(15, 256 * 1024)] [InlineData(5, 1024)] [InlineData(10, 1024)] [InlineData(15, 1024)] public void EncodeDecodeSingleMessageWithUnionSchemas(int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(sequenceNumber)) .ToList(); var networkMessage = CreateNetworkMessage(NetworkMessageContentFlags.SingleDataSetMessage, messages); var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); var schema = networkMessage.Schema; var json = schema.ToJson(); var union = UnionSchema.Create(Enumerable.Range(0, 4) .Select(i => Schema.Parse(schema.ToJson().Replace("\"DataSet\"", $"\"DataSet{i}\"", StringComparison.InvariantCulture))) .ToList()); json = union.ToJson(); // Re-encode networkMessage.Schema = union; buffers = networkMessage.Encode(context, maxMessageSize); ConvertToOpcUaUniversalTime(networkMessage); var result = buffers .SelectMany(buffer => ((BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context, messageSchema: json)).Messages) .Select(m => m.Payload) .ToList(); Assert.All(networkMessage.Messages.Select(m => m.Payload), (p, i) => Assert.True(result[i].Equals(p))); } [Theory] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 1024)] public void EncodeDecodeNetworkMessagesNoHeaderRaw( NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(sequenceNumber, dataSetFieldContentMask: DataSetFieldContentFlags.RawData)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask & ~(NetworkMessageContentFlags.NetworkMessageHeader | NetworkMessageContentFlags.DataSetMessageHeader), messages); var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); var schema = networkMessage.Schema; Assert.NotNull(schema); var json = schema.ToJson(); ConvertToOpcUaUniversalTime(networkMessage); // Compare payload as raw data equivalent var serializer = new NewtonsoftJsonSerializer(); var result = serializer.Parse(serializer.SerializeToString(buffers .SelectMany(buffer => ((BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context, messageSchema: json)).Messages) .SelectMany(m => m.Payload.DataSetFields) .Select(v => (v.Name, v.Value?.Value)) .ToList())); var expected = serializer.Parse(serializer.SerializeToString(messages .SelectMany(m => m.Payload.DataSetFields) .Select(v => (v.Name, v.Value?.Value)) .ToList())); Assert.Equal(expected, result); } [Theory] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 1024)] public void EncodeDecodeNetworkMessagesNoHeaderRawAndNullableDataValue( NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(sequenceNumber, dataSetFieldContentMask: DataSetFieldContentFlags.RawData)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask & ~(NetworkMessageContentFlags.NetworkMessageHeader | NetworkMessageContentFlags.DataSetMessageHeader), messages); var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); var schema = networkMessage.Schema; Assert.NotNull(schema); var json = schema.ToJson(); // Set null data value messages.ForEach(messages => messages.Payload = messages.Payload.Set("6", null)); // Reencode with the schema context = new ServiceMessageContext(); buffers = networkMessage.Encode(context, maxMessageSize); Assert.Equal(schema, networkMessage.Schema); ConvertToOpcUaUniversalTime(networkMessage); // Compare payload as raw data equivalent var serializer = new NewtonsoftJsonSerializer(); var result = serializer.Parse(serializer.SerializeToString(buffers .SelectMany(buffer => ((BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context, messageSchema: json)).Messages) .SelectMany(m => m.Payload.DataSetFields) .Select(v => (v.Name, v.Value?.Value)) .ToList())); var expected = serializer.Parse(serializer.SerializeToString(messages .SelectMany(m => m.Payload.DataSetFields) .Select(v => (v.Name, v.Value?.Value)) .ToList())); Assert.Equal(expected, result); } [Theory] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 1024)] public void EncodeDecodeNetworkMessagesNoHeaderRawAndMissingDataValue( NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(sequenceNumber, dataSetFieldContentMask: DataSetFieldContentFlags.RawData)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask & ~(NetworkMessageContentFlags.NetworkMessageHeader | NetworkMessageContentFlags.DataSetMessageHeader), messages); var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); var schema = networkMessage.Schema; Assert.NotNull(schema); var json = schema.ToJson(); // Set null data value messages.ForEach(messages => messages.Payload = messages.Payload.Remove("6")); // Reencode with the schema context = new ServiceMessageContext(); buffers = networkMessage.Encode(context, maxMessageSize); Assert.Equal(schema, networkMessage.Schema); ConvertToOpcUaUniversalTime(networkMessage); // Compare payload as raw data equivalent var serializer = new NewtonsoftJsonSerializer(); var result = serializer.Parse(serializer.SerializeToString(buffers .SelectMany(buffer => ((BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context, messageSchema: json)).Messages) .SelectMany(m => m.Payload.DataSetFields) .Where(m => m.Name != "6") .Select(v => (v.Name, v.Value?.Value)) .ToList())); var expected = serializer.Parse(serializer.SerializeToString(messages .SelectMany(m => m.Payload.DataSetFields) .Select(v => (v.Name, v.Value?.Value)) .ToList())); Assert.Equal(expected, result); } /// /// Convert timestamps of payload to OpcUa Utc. /// /// private static void ConvertToOpcUaUniversalTime(BaseNetworkMessage networkMessage) { // convert DataSet Payload DataValue timestamps to OpcUa Utc foreach (var dataSetMessage in networkMessage.Messages) { var expectedPayload = new Dictionary(); foreach (var (Name, Value) in dataSetMessage.Payload.DataSetFields) { expectedPayload[Name] = Value == null ? null : new DataValue(Value).ToOpcUaUniversalTime(); } dataSetMessage.Payload = new DataSet(expectedPayload, DataSetFieldContentFlags.StatusCode | DataSetFieldContentFlags.SourceTimestamp); } } /// /// Create network message /// /// /// private static AvroNetworkMessage CreateNetworkMessage( NetworkMessageContentFlags contentMask, List messages) { return new AvroNetworkMessage { MessageId = () => "9279C0B3-DA88-45A4-AF74-451CEBF82DB0", Messages = messages, DataSetWriterGroup = "group", DataSetClassId = Guid.NewGuid(), PublisherId = "PublisherId", NetworkMessageContentMask = contentMask }; } /// /// Create dataset message /// /// /// /// /// private static AvroDataSetMessage CreateDataSetMessage(int sequenceNumber, DataSetFieldContentFlags dataSetFieldContentMask = DataSetFieldContentFlagsDefault, MessageType messageType = MessageType.KeyFrame, uint? statusCode = StatusCodes.Bad) { return new AvroDataSetMessage { DataSetWriterName = "WriterId", DataSetWriterId = 3, MetaDataVersion = new ConfigurationVersionDataType { MajorVersion = 1, MinorVersion = 1 }, SequenceNumber = (ushort)sequenceNumber, Status = statusCode, Timestamp = DateTimeOffset.UtcNow, MessageType = messageType, Picoseconds = 1, Payload = CreateDataSet(dataSetFieldContentMask) }; } /// /// Create dataset /// /// private static DataSet CreateDataSet(DataSetFieldContentFlags dataSetFieldContentMask = DataSetFieldContentFlagsDefault) { return new DataSet(new Dictionary { { "1", new DataValue(new Variant(true), StatusCodes.Good, DateTime.Now, DateTime.UtcNow) }, { "2", new DataValue(new Variant(0.5), StatusCodes.Good, DateTime.Now) }, { "3", new DataValue(Variant.Null, StatusCodes.Good, DateTime.Now) }, { "4", new DataValue(new Variant(["test", "Test"]), StatusCodes.Good, DateTime.Now) }, { "5", new DataValue(new Variant(Array.Empty()), StatusCodes.Good, DateTime.Now) }, { "6", new DataValue() }, { "7", new DataValue("abcd") } }, dataSetFieldContentMask); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/PubSub/AvroNetworkMessageEncoderDecoderTests2.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.PubSub { using Azure.IIoT.OpcUa.Encoders.Models; using Azure.IIoT.OpcUa.Encoders.Schemas.Avro; using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Opc.Ua; using System; using System.Collections.Generic; using System.Linq; using Xunit; /// /// Avro encoder decoder tests /// public class AvroNetworkMessageEncoderDecoderTests2 { public const NetworkMessageContentFlags NetworkMessageContentMaskDefault = NetworkMessageContentFlags.NetworkMessageHeader | NetworkMessageContentFlags.DataSetMessageHeader; public const DataSetFieldContentFlags DataSetFieldContentFlagsDefault = DataSetFieldContentFlags.SourceTimestamp | DataSetFieldContentFlags.ServerTimestamp | DataSetFieldContentFlags.SourcePicoSeconds | DataSetFieldContentFlags.ServerPicoSeconds | DataSetFieldContentFlags.StatusCode; [Theory] [InlineData(false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(false, NetworkMessageContentMaskDefault, 3)] [InlineData(false, NetworkMessageContentMaskDefault, 1)] [InlineData(true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(true, NetworkMessageContentMaskDefault, 3)] [InlineData(true, NetworkMessageContentMaskDefault, 1)] public void EncodeDecodeNetworkMessage(bool compress, NetworkMessageContentFlags contentMask, int numberOfMessages) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(sequenceNumber)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask, messages); networkMessage.UseGzipCompression = compress; var context = new ServiceMessageContext(); var buffer = Assert.Single(networkMessage.Encode(context, 256 * 1000)); var schema = networkMessage.Schema; Assert.NotNull(schema); var json = schema.ToJson(); context = new ServiceMessageContext(); buffer = Assert.Single(networkMessage.Encode(context, 256 * 1000)); Assert.Equal(schema, networkMessage.Schema); ConvertToOpcUaUniversalTime(networkMessage); var result = PubSubMessage.Decode(buffer, networkMessage.ContentType, context, messageSchema: json); Assert.Equal(networkMessage, result); } [Theory] [InlineData(false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(false, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(false, NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(false, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(true, NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(true, NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(true, NetworkMessageContentMaskDefault, 15, 1024)] public void EncodeDecodeNetworkMessages(bool compress, NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(sequenceNumber)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask, messages); networkMessage.UseGzipCompression = compress; var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); var schema = networkMessage.Schema; Assert.NotNull(schema); var json = schema.ToJson(); ConvertToOpcUaUniversalTime(networkMessage); var m = buffers .Select(buffer => (BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context, messageSchema: json)) .ToList(); var result = m[0]; result.Messages = m.SelectMany(m => m.Messages).ToList(); Assert.Equal(networkMessage, result); } [Theory] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 1024)] public void EncodeDecodeNetworkMessagesNoNetworkMessageHeader( NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(sequenceNumber)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask & ~NetworkMessageContentFlags.NetworkMessageHeader, messages); var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); var schema = networkMessage.Schema; Assert.NotNull(schema); var json = schema.ToJson(); ConvertToOpcUaUniversalTime(networkMessage); var result = buffers .SelectMany(buffer => ((BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context, messageSchema: json)).Messages) .ToList(); Assert.Equal(networkMessage.Messages, result); } [Theory] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 1024)] public void EncodeDecodeNetworkMessagesNoDataSetMessageHeader( NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(sequenceNumber)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask & ~NetworkMessageContentFlags.DataSetMessageHeader, messages); var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); var schema = networkMessage.Schema; Assert.NotNull(schema); var json = schema.ToJson(); ConvertToOpcUaUniversalTime(networkMessage); var result = buffers .SelectMany(buffer => ((BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context, messageSchema: json)).Messages) .Select(m => m.Payload) .ToList(); Assert.All(networkMessage.Messages.Select(m => m.Payload), (p, i) => Assert.True(result[i].Equals(p))); } [Theory] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 1024)] public void EncodeDecodeNetworkMessagesNoHeader( NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(sequenceNumber)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask & ~(NetworkMessageContentFlags.NetworkMessageHeader | NetworkMessageContentFlags.DataSetMessageHeader), messages); var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); var schema = networkMessage.Schema; Assert.NotNull(schema); var json = schema.ToJson(); ConvertToOpcUaUniversalTime(networkMessage); var result = buffers .SelectMany(buffer => ((BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context, messageSchema: json)).Messages) .Select(m => m.Payload) .ToList(); Assert.All(networkMessage.Messages.Select(m => m.Payload), (p, i) => Assert.True(result[i].Equals(p))); } [Theory] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 1024)] public void EncodeDecodeNetworkMessagesNoHeaderRaw( NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(sequenceNumber, dataSetFieldContentMask: DataSetFieldContentFlags.RawData)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask & ~(NetworkMessageContentFlags.NetworkMessageHeader | NetworkMessageContentFlags.DataSetMessageHeader), messages); var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); var schema = networkMessage.Schema; Assert.NotNull(schema); var json = schema.ToJson(); ConvertToOpcUaUniversalTime(networkMessage); // Compare payload as raw data equivalent var serializer = new NewtonsoftJsonSerializer(); var result = serializer.Parse(serializer.SerializeToString(buffers .SelectMany(buffer => ((BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context, messageSchema: json)).Messages) .SelectMany(m => m.Payload.DataSetFields) .Select(v => (v.Name, v.Value.Value)) .ToList())); var expected = serializer.Parse(serializer.SerializeToString(messages .SelectMany(m => m.Payload.DataSetFields) .Select(v => (v.Name, v.Value.Value)) .ToList())); Assert.Equal(expected, result); } /// /// Convert timestamps of payload to OpcUa Utc. /// /// private static void ConvertToOpcUaUniversalTime(BaseNetworkMessage networkMessage) { // convert DataSet Payload DataValue timestamps to OpcUa Utc foreach (var dataSetMessage in networkMessage.Messages) { var expectedPayload = new Dictionary(); foreach (var (Name, Value) in dataSetMessage.Payload.DataSetFields) { expectedPayload[Name] = new DataValue(Value).ToOpcUaUniversalTime(); } dataSetMessage.Payload = new DataSet(expectedPayload, DataSetFieldContentFlags.StatusCode | DataSetFieldContentFlags.SourceTimestamp); } } /// /// Create network message /// /// /// private static AvroNetworkMessage CreateNetworkMessage( NetworkMessageContentFlags contentMask, List messages) { return new AvroNetworkMessage { MessageId = () => "9279C0B3-DA88-45A4-AF74-451CEBF82DB0", Messages = messages, DataSetWriterGroup = "group", DataSetClassId = Guid.NewGuid(), PublisherId = "PublisherId", EmitConciseSchema = true, NetworkMessageContentMask = contentMask }; } /// /// Create dataset message /// /// /// private static AvroDataSetMessage CreateDataSetMessage(int sequenceNumber, DataSetFieldContentFlags dataSetFieldContentMask = DataSetFieldContentFlagsDefault) { return new AvroDataSetMessage { DataSetWriterName = "WriterId", DataSetWriterId = 3, MetaDataVersion = new ConfigurationVersionDataType { MajorVersion = 1, MinorVersion = 1 }, SequenceNumber = (ushort)sequenceNumber, Status = StatusCodes.Bad, Timestamp = DateTimeOffset.UtcNow, MessageType = MessageType.KeyFrame, Picoseconds = 1, Payload = CreateDataSet(dataSetFieldContentMask) }; } /// /// Create dataset /// /// private static DataSet CreateDataSet(DataSetFieldContentFlags dataSetFieldContentMask = DataSetFieldContentFlagsDefault) { return new DataSet(new Dictionary { { "1", new DataValue(new Variant(true), StatusCodes.Good, DateTime.Now, DateTime.UtcNow) }, { "2", new DataValue(new Variant(0.5), StatusCodes.Good, DateTime.Now) }, { "3", new DataValue("abcd") } }, dataSetFieldContentMask); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/PubSub/AvroNetworkMessageFileWriterReaderTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.PubSub { using Azure.IIoT.OpcUa.Encoders.Models; using Azure.IIoT.OpcUa.Encoders.Schemas.Avro; using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Extensions.Logging; using Opc.Ua; using System; using System.Collections.Generic; using System.IO; using System.Linq; using Xunit; /// /// Avro file reader/writer tests /// public class AvroNetworkMessageFileWriterReaderTests { public const NetworkMessageContentFlags NetworkMessageContentMaskDefault = NetworkMessageContentFlags.NetworkMessageHeader | NetworkMessageContentFlags.DataSetMessageHeader; public const DataSetFieldContentFlags DataSetFieldContentFlagsDefault = DataSetFieldContentFlags.SourceTimestamp | DataSetFieldContentFlags.ServerTimestamp | DataSetFieldContentFlags.SourcePicoSeconds | DataSetFieldContentFlags.ServerPicoSeconds | DataSetFieldContentFlags.StatusCode; [Theory] [InlineData(false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(false, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(false, NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(false, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(true, NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(true, NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(true, NetworkMessageContentMaskDefault, 15, 1024)] public void ReadWriteNetworkMessages(bool compress, NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(sequenceNumber)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask, messages); networkMessage.UseGzipCompression = compress; var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); using var file = new MemoryStream(); using (var writer = AvroFileWriter.AvroFile.CreateFromStream( file, networkMessage.Schema.ToJson(), new Dictionary(), Log.Console("test"), compress)) { writer.Write(buffers); } ConvertToOpcUaUniversalTime(networkMessage); networkMessage.UseGzipCompression = false; // Unset compression flag now as we are reading the file file.Seek(0, SeekOrigin.Begin); using (var reader = new AvroFileReader(file)) { var m = reader .Stream((schema, stream) => PubSubMessage.Decode(stream, networkMessage.ContentType, context, messageSchema: schema.ToJson()).ToList()) .SelectMany(m => m.Cast()) .ToList(); var result = m[0]; result.Messages = m.SelectMany(m => m.Messages).ToList(); Assert.Equal(networkMessage, result); } } [Theory] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 1024)] public void ReadWriteNetworkMessagesNoNetworkMessageHeader( NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(sequenceNumber)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask & ~NetworkMessageContentFlags.NetworkMessageHeader, messages); var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); using var file = new MemoryStream(); using (var writer = AvroFileWriter.AvroFile.CreateFromStream( file, networkMessage.Schema.ToJson(), new Dictionary(), Log.Console("test"))) { writer.Write(buffers); } ConvertToOpcUaUniversalTime(networkMessage); file.Seek(0, SeekOrigin.Begin); using var reader = new AvroFileReader(file); var result = reader .Stream((schema, stream) => PubSubMessage.Decode(stream, networkMessage.ContentType, context, messageSchema: schema.ToJson()).ToList()) .SelectMany(m => m.Cast().ToList()) .SelectMany(m => m.Messages) .ToList(); Assert.Equal(networkMessage.Messages, result); } [Theory] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 1024)] public void ReadWriteNetworkMessagesNoDataSetMessageHeader( NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(sequenceNumber)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask & ~NetworkMessageContentFlags.DataSetMessageHeader, messages); var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); using var file = new MemoryStream(); using (var writer = AvroFileWriter.AvroFile.CreateFromStream( file, networkMessage.Schema.ToJson(), new Dictionary(), Log.Console("test"))) { writer.Write(buffers); } ConvertToOpcUaUniversalTime(networkMessage); file.Seek(0, SeekOrigin.Begin); using var reader = new AvroFileReader(file); var result = reader .Stream((schema, stream) => PubSubMessage.Decode(stream, networkMessage.ContentType, context, messageSchema: schema.ToJson()).ToList()) .SelectMany(m => m.Cast().ToList()) .SelectMany(m => m.Messages).Select(m => m.Payload) .ToList(); Assert.All(networkMessage.Messages.Select(m => m.Payload), (p, i) => Assert.True(result[i].Equals(p))); } [Theory] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(NetworkMessageContentMaskDefault, 15, 1024)] public void ReadWriteNetworkMessagesNoHeader( NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(sequenceNumber)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask & ~(NetworkMessageContentFlags.NetworkMessageHeader | NetworkMessageContentFlags.DataSetMessageHeader), messages); var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); using var file = new MemoryStream(); using (var writer = AvroFileWriter.AvroFile.CreateFromStream( file, networkMessage.Schema.ToJson(), new Dictionary(), Log.Console("test"))) { writer.Write(buffers); } ConvertToOpcUaUniversalTime(networkMessage); file.Seek(0, SeekOrigin.Begin); using var reader = new AvroFileReader(file); var result = reader .Stream((schema, stream) => PubSubMessage.Decode(stream, networkMessage.ContentType, context, messageSchema: schema.ToJson()).ToList()) .SelectMany(m => m.Cast()) .SelectMany(m => m.Messages.Select(m => m.Payload)) .ToList(); var expected = networkMessage.Messages.Select(m => m.Payload).ToList(); Assert.All(expected, (p, i) => Assert.True(result[i].Equals(p))); } /// /// Convert timestamps of payload to OpcUa Utc. /// /// private static void ConvertToOpcUaUniversalTime(BaseNetworkMessage networkMessage) { // convert DataSet Payload DataValue timestamps to OpcUa Utc foreach (var dataSetMessage in networkMessage.Messages) { var expectedPayload = new Dictionary(); foreach (var (Name, Value) in dataSetMessage.Payload.DataSetFields) { expectedPayload[Name] = new DataValue(Value).ToOpcUaUniversalTime(); } dataSetMessage.Payload = new DataSet(expectedPayload, DataSetFieldContentFlags.StatusCode | DataSetFieldContentFlags.SourceTimestamp); } } /// /// Create network message /// /// /// private static AvroNetworkMessage CreateNetworkMessage( NetworkMessageContentFlags contentMask, List messages) { return new AvroNetworkMessage { MessageId = () => "9279C0B3-DA88-45A4-AF74-451CEBF82DB0", Messages = messages, DataSetWriterGroup = "group", DataSetClassId = Guid.NewGuid(), PublisherId = "PublisherId", EmitConciseSchema = true, NetworkMessageContentMask = contentMask }; } /// /// Create dataset message /// /// /// private static AvroDataSetMessage CreateDataSetMessage(int sequenceNumber, DataSetFieldContentFlags dataSetFieldContentMask = DataSetFieldContentFlagsDefault) { return new AvroDataSetMessage { DataSetWriterName = "WriterId", DataSetWriterId = 3, MetaDataVersion = new ConfigurationVersionDataType { MajorVersion = 1, MinorVersion = 1 }, SequenceNumber = (ushort)sequenceNumber, Status = StatusCodes.Bad, Timestamp = DateTimeOffset.UtcNow, MessageType = MessageType.KeyFrame, Picoseconds = 1, Payload = CreateDataSet(dataSetFieldContentMask) }; } /// /// Create dataset /// /// private static DataSet CreateDataSet(DataSetFieldContentFlags dataSetFieldContentMask = DataSetFieldContentFlagsDefault) { return new DataSet(new Dictionary { { "1", new DataValue(new Variant(true), StatusCodes.Good, DateTime.Now, DateTime.UtcNow) }, { "2", new DataValue(new Variant(0.5), StatusCodes.Good, DateTime.Now) }, { "3", new DataValue("abcd") } }, dataSetFieldContentMask); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/PubSub/JsonNetworkMessageEncoderDecoderTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.PubSub { using Azure.IIoT.OpcUa.Encoders.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Opc.Ua; using System; using System.Collections.Generic; using System.Linq; using Xunit; /// /// Json encoder decoder tests /// public class JsonNetworkMessageEncoderDecoderTests { public const NetworkMessageContentFlags NetworkMessageContentMaskDefault = NetworkMessageContentFlags.PublisherId | NetworkMessageContentFlags.NetworkMessageHeader | NetworkMessageContentFlags.DataSetMessageHeader | NetworkMessageContentFlags.DataSetClassId; public const DataSetMessageContentFlags DataSetMessageContentMaskDefault = DataSetMessageContentFlags.DataSetWriterName | DataSetMessageContentFlags.MessageType | DataSetMessageContentFlags.DataSetWriterId | DataSetMessageContentFlags.SequenceNumber | DataSetMessageContentFlags.MetaDataVersion | DataSetMessageContentFlags.Timestamp | DataSetMessageContentFlags.Status; public const DataSetFieldContentFlags DataSetFieldContentFlagsDefault = DataSetFieldContentFlags.SourceTimestamp | DataSetFieldContentFlags.ServerTimestamp | DataSetFieldContentFlags.SourcePicoSeconds | DataSetFieldContentFlags.ServerPicoSeconds | DataSetFieldContentFlags.StatusCode; [Theory] [InlineData(false, false, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(false, false, false, NetworkMessageContentMaskDefault, 3)] [InlineData(false, false, false, NetworkMessageContentMaskDefault, 1)] [InlineData(false, false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(false, false, true, NetworkMessageContentMaskDefault, 3)] [InlineData(true, false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(true, false, true, NetworkMessageContentMaskDefault, 3)] [InlineData(false, true, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(false, true, false, NetworkMessageContentMaskDefault, 3)] [InlineData(false, true, false, NetworkMessageContentMaskDefault, 1)] [InlineData(false, true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(false, true, true, NetworkMessageContentMaskDefault, 3)] [InlineData(true, true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(true, true, true, NetworkMessageContentMaskDefault, 3)] public void EncodeDecodeNetworkMessage(bool useArrayEnvelope, bool compress, bool useCompatibilityMode, NetworkMessageContentFlags contentMask, int numberOfMessages) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(useCompatibilityMode, sequenceNumber)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask, messages); networkMessage.UseGzipCompression = compress; networkMessage.UseArrayEnvelope = useArrayEnvelope; var context = new ServiceMessageContext(); var buffer = Assert.Single(networkMessage.Encode(context, 256 * 1000)); ConvertToOpcUaUniversalTime(networkMessage); var result = PubSubMessage.Decode(buffer, networkMessage.ContentType, context); Assert.Equal(networkMessage, result); } [Theory] [InlineData(false, false, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(false, false, false, NetworkMessageContentMaskDefault, 3)] [InlineData(false, false, false, NetworkMessageContentMaskDefault, 1)] [InlineData(false, false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(false, false, true, NetworkMessageContentMaskDefault, 3)] [InlineData(true, false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(true, false, true, NetworkMessageContentMaskDefault, 3)] [InlineData(false, true, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(false, true, false, NetworkMessageContentMaskDefault, 3)] [InlineData(false, true, false, NetworkMessageContentMaskDefault, 1)] [InlineData(false, true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(false, true, true, NetworkMessageContentMaskDefault, 3)] [InlineData(true, true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(true, true, true, NetworkMessageContentMaskDefault, 3)] public void EncodeDecodeNetworkMessageReversible(bool useArrayEnvelope, bool compress, bool useCompatibilityMode, NetworkMessageContentFlags contentMask, int numberOfMessages) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(useCompatibilityMode, sequenceNumber, DataSetMessageContentMaskDefault | DataSetMessageContentFlags.ReversibleFieldEncoding)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask, messages); networkMessage.UseGzipCompression = compress; networkMessage.UseArrayEnvelope = useArrayEnvelope; var context = new ServiceMessageContext(); var buffer = Assert.Single(networkMessage.Encode(context, 256 * 1000)); ConvertToOpcUaUniversalTime(networkMessage); var result = PubSubMessage.Decode(buffer, networkMessage.ContentType, context); Assert.Equal(networkMessage, result); } [Theory] [InlineData(false, false, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, false, false, NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(false, false, true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(false, false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(true, false, true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(true, false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, false, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(false, false, false, NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(false, false, true, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(false, false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(true, false, true, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(true, false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(false, true, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, true, false, NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(false, true, true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(false, true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(true, true, true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(true, true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, true, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(false, true, false, NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(false, true, true, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(false, true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(true, true, true, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(true, true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] public void EncodeDecodeNetworkMessages(bool useArrayEnvelope, bool compress, bool useCompatibilityMode, NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(useCompatibilityMode, sequenceNumber)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask, messages); networkMessage.UseGzipCompression = compress; networkMessage.UseArrayEnvelope = useArrayEnvelope; var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); ConvertToOpcUaUniversalTime(networkMessage); var m = buffers .Select(buffer => (BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context)) .ToList(); var result = m[0]; result.Messages = m.SelectMany(m => m.Messages).ToList(); Assert.Equal(networkMessage, result); } [Theory] [InlineData(false, false, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, false, false, NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(false, false, true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(false, false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(true, false, true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(true, false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, false, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(false, false, false, NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(false, false, true, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(false, false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(true, false, true, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(true, false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(false, true, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, true, false, NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(false, true, true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(false, true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(true, true, true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(true, true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, true, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(false, true, false, NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(false, true, true, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(false, true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(true, true, true, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(true, true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] public void EncodeDecodeNetworkMessagesReversible(bool useArrayEnvelope, bool compress, bool useCompatibilityMode, NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(useCompatibilityMode, sequenceNumber, DataSetMessageContentMaskDefault | DataSetMessageContentFlags.ReversibleFieldEncoding)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask, messages); networkMessage.UseGzipCompression = compress; networkMessage.UseArrayEnvelope = useArrayEnvelope; var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); ConvertToOpcUaUniversalTime(networkMessage); var m = buffers .Select(buffer => (BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context)) .ToList(); var result = m[0]; result.Messages = m.SelectMany(m => m.Messages).ToList(); Assert.Equal(networkMessage, result); } [Theory] [InlineData(false, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, false, NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(false, true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(true, true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(false, false, NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(false, true, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(true, true, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] public void EncodeDecodeNetworkMessagesNoNetworkMessageHeader(bool useArrayEnvelope, bool useCompatibilityMode, NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(useCompatibilityMode, sequenceNumber)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask & ~NetworkMessageContentFlags.NetworkMessageHeader, messages); networkMessage.UseArrayEnvelope = useArrayEnvelope; var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); ConvertToOpcUaUniversalTime(networkMessage); var result = buffers .SelectMany(buffer => ((BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context)).Messages) .ToList(); Assert.Equal(networkMessage.Messages, result); } [Theory] [InlineData(false, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, false, NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(false, true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(true, true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(false, false, NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(false, true, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(true, true, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] public void EncodeDecodeNetworkMessagesNoDataSetMessageHeader(bool useArrayEnvelope, bool useCompatibilityMode, NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(useCompatibilityMode, sequenceNumber)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask & ~NetworkMessageContentFlags.DataSetMessageHeader, messages); networkMessage.UseArrayEnvelope = useArrayEnvelope; var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); ConvertToOpcUaUniversalTime(networkMessage); var result = buffers .SelectMany(buffer => ((BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context)).Messages) .Select(m => m.Payload) .ToList(); Assert.All(networkMessage.Messages.Select(m => m.Payload), (p, i) => Assert.True(result[i].Equals(p))); } [Theory] [InlineData(false, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, false, NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(false, true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(true, true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(false, false, NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(false, true, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(true, true, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] public void EncodeDecodeNetworkMessagesNoHeader(bool useArrayEnvelope, bool useCompatibilityMode, NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(useCompatibilityMode, sequenceNumber)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask & ~(NetworkMessageContentFlags.NetworkMessageHeader | NetworkMessageContentFlags.DataSetMessageHeader), messages); networkMessage.UseArrayEnvelope = useArrayEnvelope; var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); ConvertToOpcUaUniversalTime(networkMessage); var result = buffers .SelectMany(buffer => ((BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context)).Messages) .Select(m => m.Payload) .ToList(); Assert.All(networkMessage.Messages.Select(m => m.Payload), (p, i) => Assert.True(result[i].Equals(p))); } [Theory] [InlineData(false, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, false, NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(false, true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(true, true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(false, false, NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(false, true, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(true, true, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] public void EncodeDecodeNetworkMessagesNoHeaderRaw(bool useArrayEnvelope, bool useCompatibilityMode, NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(useCompatibilityMode, sequenceNumber, dataSetFieldContentMask: DataSetFieldContentFlags.RawData)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask & ~(NetworkMessageContentFlags.NetworkMessageHeader | NetworkMessageContentFlags.DataSetMessageHeader), messages); networkMessage.UseArrayEnvelope = useArrayEnvelope; var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); ConvertToOpcUaUniversalTime(networkMessage); // Compare payload as raw data equivalent var serializer = new NewtonsoftJsonSerializer(); var result = serializer.Parse(serializer.SerializeToString(buffers .SelectMany(buffer => ((BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context)).Messages) .SelectMany(m => m.Payload.DataSetFields) .Select(v => (v.Name, v.Value.Value)) .ToList())); var expected = serializer.Parse(serializer.SerializeToString(messages .SelectMany(m => m.Payload.DataSetFields) .Select(v => (v.Name, v.Value.Value)) .ToList())); Assert.Equal(expected, result); } /// /// Convert timestamps of payload to OpcUa Utc. /// /// private static void ConvertToOpcUaUniversalTime(BaseNetworkMessage networkMessage) { // convert DataSet Payload DataValue timestamps to OpcUa Utc foreach (var dataSetMessage in networkMessage.Messages) { var expectedPayload = new Dictionary(); foreach (var (Name, Value) in dataSetMessage.Payload.DataSetFields) { expectedPayload[Name] = new DataValue(Value).ToOpcUaUniversalTime(); } dataSetMessage.Payload = new DataSet(expectedPayload, DataSetFieldContentFlags.StatusCode | DataSetFieldContentFlags.SourceTimestamp); } } /// /// Create network message /// /// /// private static JsonNetworkMessage CreateNetworkMessage( NetworkMessageContentFlags contentMask, List messages) { return new JsonNetworkMessage { MessageId = () => "9279C0B3-DA88-45A4-AF74-451CEBF82DB0", Messages = messages, DataSetWriterGroup = "group", DataSetClassId = Guid.NewGuid(), PublisherId = "PublisherId", NetworkMessageContentMask = contentMask }; } /// /// Create dataset message /// /// /// /// /// private static JsonDataSetMessage CreateDataSetMessage(bool useCompatibilityMode, int sequenceNumber, DataSetMessageContentFlags dataSetMessageContentMask = DataSetMessageContentMaskDefault, DataSetFieldContentFlags dataSetFieldContentMask = DataSetFieldContentFlagsDefault) { return new JsonDataSetMessage { DataSetWriterName = "WriterId", DataSetWriterId = (ushort)(useCompatibilityMode ? 0 : 3), MetaDataVersion = new ConfigurationVersionDataType { MajorVersion = 1, MinorVersion = 1 }, SequenceNumber = (ushort)sequenceNumber, Status = StatusCodes.Bad, Timestamp = DateTimeOffset.UtcNow, UseCompatibilityMode = useCompatibilityMode, MessageType = MessageType.KeyFrame, Picoseconds = 1, Payload = CreateDataSet(dataSetFieldContentMask), DataSetMessageContentMask = dataSetMessageContentMask }; } /// /// Create dataset /// /// private static DataSet CreateDataSet(DataSetFieldContentFlags dataSetFieldContentMask = DataSetFieldContentFlagsDefault) { return new DataSet(new Dictionary { { "1", new DataValue(new Variant(true), StatusCodes.Good, DateTime.Now, DateTime.UtcNow) }, { "2", new DataValue(new Variant(0.5), StatusCodes.Good, DateTime.Now) }, { "3", new DataValue("abcd") } }, dataSetFieldContentMask); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/PubSub/JsonNetworkMessageEncoderTests1.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.PubSub { using Azure.IIoT.OpcUa.Encoders.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Opc.Ua; using System; using System.Collections.Generic; using System.Globalization; using Xunit; public class JsonNetworkMessageEncoderTests1 { [Theory] [InlineData(false)] [InlineData(true)] public void MultipleMessagesNoNetworkMessageHeaderAndNoDataSetMessageHeaderRawEncoding(bool useArrayEnvelope) { var simple = CreateMessage(0x18, 0x62, 0x3f); simple.UseArrayEnvelope = useArrayEnvelope; var buffers = simple.Encode(new ServiceMessageContext(), 1024); var buffer = Assert.Single(buffers); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" [ { "Temperature":25, "Pressure":1013, "Humidity":42 } ] """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Theory] [InlineData(false)] [InlineData(true)] public void MultipleMessagesNoNetworkMessageHeaderAndNoDataSetMessageHeaderVariantEncoding(bool useArrayEnvelope) { var simple = CreateMessage(0x18, 0x62, 0); simple.UseArrayEnvelope = useArrayEnvelope; var buffers = simple.Encode(new ServiceMessageContext(), 1024); var buffer = Assert.Single(buffers); // TODO: According to spec if no datavalue fields are selected, // the value is encoded as variant using reversible encoding // Even if the datatset mask flag is not set. This is not logical. // The pub sub formatter behaves differently, it uses raw encoding. Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" [ { "Temperature":{"Type":6,"Body":25}, "Pressure":{"Type":6,"Body":1013}, "Humidity":{"Type":6,"Body":42} } ] """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Theory] [InlineData(false)] [InlineData(true)] public void MultipleMessagesNoNetworkMessageHeaderAndNoDataSetMessageHeader(bool useArrayEnvelope) { var simple = CreateMessage(0x18, 0x62, 0x1f); simple.UseArrayEnvelope = useArrayEnvelope; var buffers = simple.Encode(new ServiceMessageContext(), 1024); var buffer = Assert.Single(buffers); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" [ { "Temperature":{"Value":25,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Pressure":{"Value":1013,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Humidity":{"Value":42,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"} } ] """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Theory] [InlineData(false)] [InlineData(true)] public void MultipleMessagesNoNetworkMessageHeaderAndSubsetofDataSetMessageContent(bool useArrayEnvelope) { var simple = CreateMessage(0x1a, 0x62, 0x1f); simple.UseArrayEnvelope = useArrayEnvelope; var buffers = simple.Encode(new ServiceMessageContext(), 1024); var buffer = Assert.Single(buffers); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" [ { "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "MessageType":"ua-keyframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":25,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Pressure":{"Value":1013,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Humidity":{"Value":42,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"} } } ] """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Fact] public void MultipleMessagesAllSwitchesSelectedAndReversableFieldEncoding() { var simple = CreateMessage(0x1b, 0xff, 0x1f); var buffers = simple.Encode(new ServiceMessageContext(), 1024); var buffer = Assert.Single(buffers); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" { "MessageId":"9279C0B3-DA88-45A4-AF74-451CEBF82DB0", "MessageType":"ua-data", "PublisherId":"MyPublisher", "DataSetClassId":"5ae1a63a-9757-4aa7-ab71-0d88931266fc", "Messages": [ { "DataSetWriterId":100, "SequenceNumber":29766, "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "Timestamp":"2021-09-27T18:45:19.555Z", "Status":1073741824, "MessageType":"ua-keyframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":{"Type":6,"Body":25},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Pressure":{"Value":{"Type":6,"Body":1013},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Humidity":{"Value":{"Type":6,"Body":42},"StatusCode":1073741824,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"} } } ] } """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Fact] public void MultipleMessagesAllSwitchesSelectedAndReversableFieldEncodingWithArrayEnvelope() { var simple = CreateMessage(0x1b, 0xff, 0x1f); simple.UseArrayEnvelope = true; var buffers = simple.Encode(new ServiceMessageContext(), 1024); var buffer = Assert.Single(buffers); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" [ { "MessageId":"9279C0B3-DA88-45A4-AF74-451CEBF82DB0", "MessageType":"ua-data", "PublisherId":"MyPublisher", "DataSetClassId":"5ae1a63a-9757-4aa7-ab71-0d88931266fc", "Messages": [ { "DataSetWriterId":100, "SequenceNumber":29766, "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "Timestamp":"2021-09-27T18:45:19.555Z", "Status":1073741824, "MessageType":"ua-keyframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":{"Type":6,"Body":25},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Pressure":{"Value":{"Type":6,"Body":1013},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Humidity":{"Value":{"Type":6,"Body":42},"StatusCode":1073741824,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"} } } ] } ] """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Fact] public void MultipleMessagesAllSwitchesSelectedNoReversableFieldEncoding() { var simple = CreateMessage(0x1b, 0x7f, 0x1f); var buffers = simple.Encode(new ServiceMessageContext(), 1024); var buffer = Assert.Single(buffers); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" { "MessageId":"9279C0B3-DA88-45A4-AF74-451CEBF82DB0", "MessageType":"ua-data", "PublisherId":"MyPublisher", "DataSetClassId":"5ae1a63a-9757-4aa7-ab71-0d88931266fc", "Messages": [ { "DataSetWriterId":100, "SequenceNumber":29766, "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "Timestamp":"2021-09-27T18:45:19.555Z", "Status":1073741824, "MessageType":"ua-keyframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":25,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Pressure":{"Value":1013,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Humidity":{"Value":42,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"} } } ] } """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Fact] public void SingleMessageNoNetworkMessageHeaderAndNoDataSetMessageHeader() { var simple = CreateMessage(0x1c, 0x62, 0x1f); var buffers = simple.Encode(new ServiceMessageContext(), 1024); var buffer = Assert.Single(buffers); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" { "Temperature":{"Value":25,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Pressure":{"Value":1013,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Humidity":{"Value":42,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"} } """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Fact] public void SingleMessageNoNetworkMessageHeaderAndSubsetofDataSetMessageContent() { var simple = CreateMessage(0x1e, 0x62, 0x1f); var buffers = simple.Encode(new ServiceMessageContext(), 1024); var buffer = Assert.Single(buffers); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" { "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "MessageType":"ua-keyframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":25,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Pressure":{"Value":1013,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Humidity":{"Value":42,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"} } } """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Fact] public void SingleMessageAllSwitchesSelectedAndReversableFieldEncoding() { var simple = CreateMessage(0x1f, 0xff, 0x1f); var buffers = simple.Encode(new ServiceMessageContext(), 1024); var buffer = Assert.Single(buffers); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" { "MessageId":"9279C0B3-DA88-45A4-AF74-451CEBF82DB0", "MessageType":"ua-data", "PublisherId":"MyPublisher", "DataSetClassId":"5ae1a63a-9757-4aa7-ab71-0d88931266fc", "Messages": { "DataSetWriterId":100, "SequenceNumber":29766, "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "Timestamp":"2021-09-27T18:45:19.555Z", "Status":1073741824, "MessageType":"ua-keyframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":{"Type":6,"Body":25},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Pressure":{"Value":{"Type":6,"Body":1013},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Humidity":{"Value":{"Type":6,"Body":42},"StatusCode":1073741824,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"} } } } """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Fact] public void SingleMessageAllSwitchesSelectedNoReversableFieldEncoding() { var simple = CreateMessage(0x1f, 0x7f, 0x1f); var buffers = simple.Encode(new ServiceMessageContext(), 1024); var buffer = Assert.Single(buffers); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" { "MessageId":"9279C0B3-DA88-45A4-AF74-451CEBF82DB0", "MessageType":"ua-data", "PublisherId":"MyPublisher", "DataSetClassId":"5ae1a63a-9757-4aa7-ab71-0d88931266fc", "Messages": { "DataSetWriterId":100, "SequenceNumber":29766, "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "Timestamp":"2021-09-27T18:45:19.555Z", "Status":1073741824, "MessageType":"ua-keyframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":25,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Pressure":{"Value":1013,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Humidity":{"Value":42,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"} } } } """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Fact] public void SingleMessageAllSwitchesSelectedRawValueEncoding() { var simple = CreateMessage(0x1f, 0x7f, 0x3f); var buffers = simple.Encode(new ServiceMessageContext(), 1024); var buffer = Assert.Single(buffers); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" { "MessageId":"9279C0B3-DA88-45A4-AF74-451CEBF82DB0", "MessageType":"ua-data", "PublisherId":"MyPublisher", "DataSetClassId":"5ae1a63a-9757-4aa7-ab71-0d88931266fc", "Messages": { "DataSetWriterId":100, "SequenceNumber":29766, "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "Timestamp":"2021-09-27T18:45:19.555Z", "Status":1073741824, "MessageType":"ua-keyframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":25, "Pressure":1013, "Humidity":42 } } } """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Fact] public void SingleMessageAllSwitchesSelectedJustStatusFieldAndArrayEnvelope() { var simple = CreateMessage(0x1f, 0x7f, 0x1); simple.UseArrayEnvelope = true; var buffers = simple.Encode(new ServiceMessageContext(), 1024); var buffer = Assert.Single(buffers); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" [ { "MessageId":"9279C0B3-DA88-45A4-AF74-451CEBF82DB0", "MessageType":"ua-data", "PublisherId":"MyPublisher", "DataSetClassId":"5ae1a63a-9757-4aa7-ab71-0d88931266fc", "Messages": { "DataSetWriterId":100, "SequenceNumber":29766, "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "Timestamp":"2021-09-27T18:45:19.555Z", "Status":1073741824, "MessageType":"ua-keyframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":25}, "Pressure":{"Value":1013}, "Humidity":{"Value":42,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"}} } } } ] """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Fact] public void SingleMessageAllSwitchesSelectedNoReversableFieldEncodingWithArrayEnvelope() { var simple = CreateMessage(0x1f, 0x7f, 0x1f); simple.UseArrayEnvelope = true; var buffers = simple.Encode(new ServiceMessageContext(), 1024); var buffer = Assert.Single(buffers); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" [ { "MessageId":"9279C0B3-DA88-45A4-AF74-451CEBF82DB0", "MessageType":"ua-data", "PublisherId":"MyPublisher", "DataSetClassId":"5ae1a63a-9757-4aa7-ab71-0d88931266fc", "Messages": { "DataSetWriterId":100, "SequenceNumber":29766, "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "Timestamp":"2021-09-27T18:45:19.555Z", "Status":1073741824, "MessageType":"ua-keyframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":25,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Pressure":{"Value":1013,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Humidity":{"Value":42,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"} } } } ] """), new NewtonsoftJsonSerializer().Parse(buffer)); } private static JsonNetworkMessage CreateMessage(uint messageMask, uint datasetMask, uint fieldMask) { return new JsonNetworkMessage { DataSetClassId = Guid.Parse("5ae1a63a-9757-4aa7-ab71-0d88931266fc"), NetworkMessageContentMask = PubSubMessageContentFlagHelper.StackToNetworkMessageContentFlags(messageMask), MessageId = () => "9279C0B3-DA88-45A4-AF74-451CEBF82DB0", PublisherId = "MyPublisher", Messages = [ new JsonDataSetMessage { DataSetMessageContentMask = PubSubMessageContentFlagHelper.StackToDataSetMessageContentFlags(datasetMask), DataSetWriterId = 100, SequenceNumber = 29766, MetaDataVersion = new ConfigurationVersionDataType { MajorVersion = 672338910, MinorVersion = 672341762 }, Timestamp = DateTime.Parse("2021-09-27T18:45:19.555Z", CultureInfo.InvariantCulture), Status = 1073741824, MessageType = MessageType.KeyFrame, DataSetWriterName = "Writer100", Payload = new DataSet(new Dictionary { ["Temperature"] = new DataValue(25, StatusCodes.Good, DateTime.Parse("2021-09-27T18:45:19.555Z", CultureInfo.InvariantCulture), DateTime.Parse("2021-09-27T18:45:19.555Z", CultureInfo.InvariantCulture)), ["Pressure"] = new DataValue(1013, StatusCodes.Good, DateTime.Parse("2021-09-27T18:45:19.555Z", CultureInfo.InvariantCulture), DateTime.Parse("2021-09-27T18:45:19.555Z", CultureInfo.InvariantCulture)), ["Humidiy"] = new DataValue(42, StatusCodes.Uncertain, DateTime.Parse("2021-09-27T18:45:19.555Z", CultureInfo.InvariantCulture), DateTime.Parse("2021-09-27T18:45:19.555Z", CultureInfo.InvariantCulture)) }, PubSubMessageContentFlagHelper.StackToDataSetFieldContentFlags(fieldMask)) } ] }; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/PubSub/JsonNetworkMessageEncoderTests2.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.PubSub { using Azure.IIoT.OpcUa.Encoders.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Opc.Ua; using System; using System.Collections.Generic; using System.Globalization; using Xunit; public class JsonNetworkMessageEncoderTests2 { [Theory] [InlineData(false)] [InlineData(true)] public void MultipleMessagesNoNetworkMessageHeaderAndNoDataSetMessageHeaderRawEncoding(bool useArrayEnvelope) { var simple = CreateMessage(0x18, 0x62, 0x3f); simple.UseArrayEnvelope = useArrayEnvelope; var buffers = simple.Encode(new ServiceMessageContext(), 4096); var buffer = Assert.Single(buffers); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" [ { "Temperature":25, "Pressure":1013, "Humidity":42 }, { "Temperature":26, "Pressure":1014, "Humidity":43 } ] """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Theory] [InlineData(false)] [InlineData(true)] public void MultipleMessagesNoNetworkMessageHeaderAndNoDataSetMessageHeaderVariantEncoding(bool useArrayEnvelope) { var simple = CreateMessage(0x18, 0x62, 0); simple.UseArrayEnvelope = useArrayEnvelope; var buffers = simple.Encode(new ServiceMessageContext(), 4096); var buffer = Assert.Single(buffers); // TODO: According to spec if no datavalue fields are selected, // the value is encoded as variant using reversible encoding // Even if the datatset mask flag is not set. This is not logical. // The pub sub formatter behaves differently, it uses raw encoding. Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" [ { "Temperature":{"Type":6,"Body":25}, "Pressure":{"Type":6,"Body":1013}, "Humidity":{"Type":6,"Body":42} }, { "Temperature":{"Type":6,"Body":26}, "Pressure":{"Type":6,"Body":1014}, "Humidity":{"Type":6,"Body":43} } ] """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Theory] [InlineData(false)] [InlineData(true)] public void MultipleMessagesNoNetworkMessageHeaderAndNoDataSetMessageHeader(bool useArrayEnvelope) { var simple = CreateMessage(0x18, 0x62, 0x1f); simple.UseArrayEnvelope = useArrayEnvelope; var buffers = simple.Encode(new ServiceMessageContext(), 4096); var buffer = Assert.Single(buffers); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" [ { "Temperature":{"Value":25,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Pressure":{"Value":1013,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Humidity":{"Value":42,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"} }, { "Temperature":{"Value":26,"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"}, "Pressure":{"Value":1014,"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"}, "Humidity":{"Value":43,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"},"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"} } ] """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Theory] [InlineData(false)] [InlineData(true)] public void MultipleMessagesNoNetworkMessageHeaderAndSubsetofDataSetMessageContent(bool useArrayEnvelope) { var simple = CreateMessage(0x1a, 0x62, 0x1f); simple.UseArrayEnvelope = useArrayEnvelope; var buffers = simple.Encode(new ServiceMessageContext(), 4096); var buffer = Assert.Single(buffers); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" [ { "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "MessageType":"ua-keyframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":25,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Pressure":{"Value":1013,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Humidity":{"Value":42,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"} } }, { "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "MessageType":"ua-deltaframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":26,"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"}, "Pressure":{"Value":1014,"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"}, "Humidity":{"Value":43,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"},"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"} } } ] """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Fact] public void MultipleMessagesAllSwitchesSelectedAndReversableFieldEncoding() { var simple = CreateMessage(0x1b, 0xff, 0x1f); var buffers = simple.Encode(new ServiceMessageContext(), 4096); var buffer = Assert.Single(buffers); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" { "MessageId":"9279C0B3-DA88-45A4-AF74-451CEBF82DB0", "MessageType":"ua-data", "PublisherId":"MyPublisher", "DataSetClassId":"5ae1a63a-9757-4aa7-ab71-0d88931266fc", "Messages": [ { "DataSetWriterId":100, "SequenceNumber":29766, "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "Timestamp":"2021-09-27T18:45:19.555Z", "Status":1073741824, "MessageType":"ua-keyframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":{"Type":6,"Body":25},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Pressure":{"Value":{"Type":6,"Body":1013},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Humidity":{"Value":{"Type":6,"Body":42},"StatusCode":1073741824,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"} } }, { "DataSetWriterId":100, "SequenceNumber":29767, "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "Timestamp":"2021-09-27T18:45:19.556Z", "Status":1073741824, "MessageType":"ua-deltaframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":{"Type":6,"Body":26},"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"}, "Pressure":{"Value":{"Type":6,"Body":1014},"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"}, "Humidity":{"Value":{"Type":6,"Body":43},"StatusCode":1073741824,"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"} } } ] } """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Fact] public void MultipleMessagesWithNetworkMessageHeaderButNoDataMessageHeaderAndReversableFieldEncoding() { var simple = CreateMessage(0x19, 0x80, 0x1f); var buffers = simple.Encode(new ServiceMessageContext(), 4096); var buffer = Assert.Single(buffers); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" { "MessageId":"9279C0B3-DA88-45A4-AF74-451CEBF82DB0", "MessageType":"ua-data", "PublisherId":"MyPublisher", "DataSetClassId":"5ae1a63a-9757-4aa7-ab71-0d88931266fc", "Messages": [ { "Temperature":{"Value":{"Type":6,"Body":25},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Pressure":{"Value":{"Type":6,"Body":1013},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Humidity":{"Value":{"Type":6,"Body":42},"StatusCode":1073741824,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"} }, { "Temperature":{"Value":{"Type":6,"Body":26},"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"}, "Pressure":{"Value":{"Type":6,"Body":1014},"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"}, "Humidity":{"Value":{"Type":6,"Body":43},"StatusCode":1073741824,"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"} } ] } """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Fact] public void MultipleMessagesAllSwitchesSelectedAndReversableFieldEncodingWithArrayEnvelope() { var simple = CreateMessage(0x1b, 0xff, 0x1f); simple.UseArrayEnvelope = true; var buffers = simple.Encode(new ServiceMessageContext(), 4096); var buffer = Assert.Single(buffers); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" [ { "MessageId":"9279C0B3-DA88-45A4-AF74-451CEBF82DB0", "MessageType":"ua-data", "PublisherId":"MyPublisher", "DataSetClassId":"5ae1a63a-9757-4aa7-ab71-0d88931266fc", "Messages": [ { "DataSetWriterId":100, "SequenceNumber":29766, "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "Timestamp":"2021-09-27T18:45:19.555Z", "Status":1073741824, "MessageType":"ua-keyframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":{"Type":6,"Body":25},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Pressure":{"Value":{"Type":6,"Body":1013},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Humidity":{"Value":{"Type":6,"Body":42},"StatusCode":1073741824,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"} } } ] }, { "MessageId":"9279C0B3-DA88-45A4-AF74-451CEBF82DB0", "MessageType":"ua-data", "PublisherId":"MyPublisher", "DataSetClassId":"5ae1a63a-9757-4aa7-ab71-0d88931266fc", "Messages": [ { "DataSetWriterId":100, "SequenceNumber":29767, "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "Timestamp":"2021-09-27T18:45:19.556Z", "Status":1073741824, "MessageType":"ua-deltaframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":{"Type":6,"Body":26},"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"}, "Pressure":{"Value":{"Type":6,"Body":1014},"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"}, "Humidity":{"Value":{"Type":6,"Body":43},"StatusCode":1073741824,"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"} } } ] } ] """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Fact] public void MultipleMessagesAllSwitchesSelectedNoReversableFieldEncoding() { var simple = CreateMessage(0x1b, 0x7f, 0x1f); var buffers = simple.Encode(new ServiceMessageContext(), 4096); var buffer = Assert.Single(buffers); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" { "MessageId":"9279C0B3-DA88-45A4-AF74-451CEBF82DB0", "MessageType":"ua-data", "PublisherId":"MyPublisher", "DataSetClassId":"5ae1a63a-9757-4aa7-ab71-0d88931266fc", "Messages": [ { "DataSetWriterId":100, "SequenceNumber":29766, "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "Timestamp":"2021-09-27T18:45:19.555Z", "Status":1073741824, "MessageType":"ua-keyframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":25,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Pressure":{"Value":1013,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Humidity":{"Value":42,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"} } }, { "DataSetWriterId":100, "SequenceNumber":29767, "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "Timestamp":"2021-09-27T18:45:19.556Z", "Status":1073741824, "MessageType":"ua-deltaframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":26,"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"}, "Pressure":{"Value":1014,"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"}, "Humidity":{"Value":43,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"},"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"} } } ] } """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Fact] public void SingleMessageNoNetworkMessageHeaderAndNoDataSetMessageHeader() { var simple = CreateMessage(0x1c, 0x62, 0x1f); var buffers = simple.Encode(new ServiceMessageContext(), 4096); Assert.Equal(2, buffers.Count); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" { "Temperature":{"Value":25,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Pressure":{"Value":1013,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Humidity":{"Value":42,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"} } """), new NewtonsoftJsonSerializer().Parse(buffers[0])); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" { "Temperature":{"Value":26,"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"}, "Pressure":{"Value":1014,"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"}, "Humidity":{"Value":43,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"},"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"} } """), new NewtonsoftJsonSerializer().Parse(buffers[1])); } [Fact] public void SingleMessageNoNetworkMessageHeaderAndNoDataSetMessageHeaderWithArrayEnvelope() { var simple = CreateMessage(0x1c, 0x62, 0x1f); simple.UseArrayEnvelope = true; var buffers = simple.Encode(new ServiceMessageContext(), 4096); var buffer = Assert.Single(buffers); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" [ { "Temperature":{"Value":25,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Pressure":{"Value":1013,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Humidity":{"Value":42,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"} }, { "Temperature":{"Value":26,"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"}, "Pressure":{"Value":1014,"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"}, "Humidity":{"Value":43,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"},"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"} } ] """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Fact] public void SingleMessageNoNetworkMessageHeaderAndSubsetofDataSetMessageContent() { var simple = CreateMessage(0x1e, 0x62, 0x1f); var buffers = simple.Encode(new ServiceMessageContext(), 4096); Assert.Equal(2, buffers.Count); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" { "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "MessageType":"ua-keyframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":25,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Pressure":{"Value":1013,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Humidity":{"Value":42,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"} } } """), new NewtonsoftJsonSerializer().Parse(buffers[0])); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" { "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "MessageType":"ua-deltaframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":26,"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"}, "Pressure":{"Value":1014,"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"}, "Humidity":{"Value":43,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"},"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"} } } """), new NewtonsoftJsonSerializer().Parse(buffers[1])); } [Fact] public void SingleMessageNoNetworkMessageHeaderAndSubsetofDataSetMessageContentWithArrayEnvelope() { var simple = CreateMessage(0x1e, 0x62, 0x1f); simple.UseArrayEnvelope = true; var buffers = simple.Encode(new ServiceMessageContext(), 4096); var buffer = Assert.Single(buffers); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" [ { "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "MessageType":"ua-keyframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":25,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Pressure":{"Value":1013,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Humidity":{"Value":42,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"} } }, { "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "MessageType":"ua-deltaframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":26,"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"}, "Pressure":{"Value":1014,"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"}, "Humidity":{"Value":43,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"},"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"} } } ] """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Fact] public void SingleMessageAllSwitchesSelectedAndReversableFieldEncoding() { var simple = CreateMessage(0x1f, 0xff, 0x1f); var buffers = simple.Encode(new ServiceMessageContext(), 4096); Assert.Equal(2, buffers.Count); var buffer = buffers[0]; Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" { "MessageId":"9279C0B3-DA88-45A4-AF74-451CEBF82DB0", "MessageType":"ua-data", "PublisherId":"MyPublisher", "DataSetClassId":"5ae1a63a-9757-4aa7-ab71-0d88931266fc", "Messages": { "DataSetWriterId":100, "SequenceNumber":29766, "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "Timestamp":"2021-09-27T18:45:19.555Z", "Status":1073741824, "MessageType":"ua-keyframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":{"Type":6,"Body":25},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Pressure":{"Value":{"Type":6,"Body":1013},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Humidity":{"Value":{"Type":6,"Body":42},"StatusCode":1073741824,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"} } } } """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Fact] public void SingleMessageWithNetworkButNoDataSetMessageHeaderAndReversableFieldEncoding() { var simple = CreateMessage(0x1d, 0x80, 0x1f); var buffers = simple.Encode(new ServiceMessageContext(), 4096); Assert.Equal(2, buffers.Count); var buffer = buffers[0]; Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" { "MessageId":"9279C0B3-DA88-45A4-AF74-451CEBF82DB0", "MessageType":"ua-data", "PublisherId":"MyPublisher", "DataSetClassId":"5ae1a63a-9757-4aa7-ab71-0d88931266fc", "Messages": { "Temperature":{"Value":{"Type":6,"Body":25},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Pressure":{"Value":{"Type":6,"Body":1013},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Humidity":{"Value":{"Type":6,"Body":42},"StatusCode":1073741824,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"} } } """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Fact] public void SingleMessageAllSwitchesSelectedNoReversableFieldEncoding() { var simple = CreateMessage(0x1f, 0x7f, 0x1f); var buffers = simple.Encode(new ServiceMessageContext(), 4096); Assert.Equal(2, buffers.Count); var buffer = buffers[0]; Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" { "MessageId":"9279C0B3-DA88-45A4-AF74-451CEBF82DB0", "MessageType":"ua-data", "PublisherId":"MyPublisher", "DataSetClassId":"5ae1a63a-9757-4aa7-ab71-0d88931266fc", "Messages": { "DataSetWriterId":100, "SequenceNumber":29766, "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "Timestamp":"2021-09-27T18:45:19.555Z", "Status":1073741824, "MessageType":"ua-keyframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":25,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Pressure":{"Value":1013,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Humidity":{"Value":42,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"} } } } """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Fact] public void SingleMessageAllSwitchesSelectedRawValueEncoding() { var simple = CreateMessage(0x1f, 0x7f, 0x3f); var buffers = simple.Encode(new ServiceMessageContext(), 4096); Assert.Equal(2, buffers.Count); var buffer = buffers[0]; Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" { "MessageId":"9279C0B3-DA88-45A4-AF74-451CEBF82DB0", "MessageType":"ua-data", "PublisherId":"MyPublisher", "DataSetClassId":"5ae1a63a-9757-4aa7-ab71-0d88931266fc", "Messages": { "DataSetWriterId":100, "SequenceNumber":29766, "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "Timestamp":"2021-09-27T18:45:19.555Z", "Status":1073741824, "MessageType":"ua-keyframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":25, "Pressure":1013, "Humidity":42 } } } """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Fact] public void SingleMessageAllSwitchesSelectedJustStatusFieldAndArrayEnvelope() { var simple = CreateMessage(0x1f, 0x7f, 0x1); simple.UseArrayEnvelope = true; var buffers = simple.Encode(new ServiceMessageContext(), 4096); var buffer = Assert.Single(buffers); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" [ { "MessageId":"9279C0B3-DA88-45A4-AF74-451CEBF82DB0", "MessageType":"ua-data", "PublisherId":"MyPublisher", "DataSetClassId":"5ae1a63a-9757-4aa7-ab71-0d88931266fc", "Messages": { "DataSetWriterId":100, "SequenceNumber":29766, "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "Timestamp":"2021-09-27T18:45:19.555Z", "Status":1073741824, "MessageType":"ua-keyframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":25}, "Pressure":{"Value":1013}, "Humidity":{"Value":42,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"}} } } }, { "MessageId":"9279C0B3-DA88-45A4-AF74-451CEBF82DB0", "MessageType":"ua-data", "PublisherId":"MyPublisher", "DataSetClassId":"5ae1a63a-9757-4aa7-ab71-0d88931266fc", "Messages": { "DataSetWriterId":100, "SequenceNumber":29767, "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "Timestamp":"2021-09-27T18:45:19.556Z", "Status":1073741824, "MessageType":"ua-deltaframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":26}, "Pressure":{"Value":1014}, "Humidity":{"Value":43,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"}} } } } ] """), new NewtonsoftJsonSerializer().Parse(buffer)); } [Fact] public void SingleMessageAllSwitchesSelectedNoReversableFieldEncodingWithArrayEnvelope() { var simple = CreateMessage(0x1f, 0x7f, 0x1f); simple.UseArrayEnvelope = true; var buffers = simple.Encode(new ServiceMessageContext(), 4096); var buffer = Assert.Single(buffers); Assert.Equal(new NewtonsoftJsonSerializer().Parse(""" [ { "MessageId":"9279C0B3-DA88-45A4-AF74-451CEBF82DB0", "MessageType":"ua-data", "PublisherId":"MyPublisher", "DataSetClassId":"5ae1a63a-9757-4aa7-ab71-0d88931266fc", "Messages": { "DataSetWriterId":100, "SequenceNumber":29766, "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "Timestamp":"2021-09-27T18:45:19.555Z", "Status":1073741824, "MessageType":"ua-keyframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":25,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Pressure":{"Value":1013,"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"}, "Humidity":{"Value":42,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"},"SourceTimestamp":"2021-09-27T18:45:19.555Z","ServerTimestamp":"2021-09-27T18:45:19.555Z"} } } }, { "MessageId":"9279C0B3-DA88-45A4-AF74-451CEBF82DB0", "MessageType":"ua-data", "PublisherId":"MyPublisher", "DataSetClassId":"5ae1a63a-9757-4aa7-ab71-0d88931266fc", "Messages": { "DataSetWriterId":100, "SequenceNumber":29767, "MetaDataVersion":{"MajorVersion":672338910,"MinorVersion":672341762}, "Timestamp":"2021-09-27T18:45:19.556Z", "Status":1073741824, "MessageType":"ua-deltaframe", "DataSetWriterName":"Writer100", "Payload": { "Temperature":{"Value":26,"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"}, "Pressure":{"Value":1014,"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"}, "Humidity":{"Value":43,"StatusCode":{"Code":1073741824,"Symbol":"Uncertain"},"SourceTimestamp":"2021-09-27T18:45:19.556Z","ServerTimestamp":"2021-09-27T18:45:19.556Z"} } } } ] """), new NewtonsoftJsonSerializer().Parse(buffer)); } private static JsonNetworkMessage CreateMessage(uint messageMask, uint datasetMask, uint fieldMask) { return new JsonNetworkMessage { DataSetClassId = Guid.Parse("5ae1a63a-9757-4aa7-ab71-0d88931266fc"), NetworkMessageContentMask = PubSubMessageContentFlagHelper.StackToNetworkMessageContentFlags(messageMask), MessageId = () => "9279C0B3-DA88-45A4-AF74-451CEBF82DB0", PublisherId = "MyPublisher", Messages = [ new JsonDataSetMessage { DataSetMessageContentMask = PubSubMessageContentFlagHelper.StackToDataSetMessageContentFlags(datasetMask), DataSetWriterId = 100, SequenceNumber = 29766, MetaDataVersion = new ConfigurationVersionDataType { MajorVersion = 672338910, MinorVersion = 672341762 }, Timestamp = DateTime.Parse("2021-09-27T18:45:19.555Z", CultureInfo.InvariantCulture), Status = 1073741824, MessageType = MessageType.KeyFrame, DataSetWriterName = "Writer100", Payload = new DataSet(new Dictionary { ["Temperature"] = new DataValue(25, StatusCodes.Good, DateTime.Parse("2021-09-27T18:45:19.555Z", CultureInfo.InvariantCulture), DateTime.Parse("2021-09-27T18:45:19.555Z", CultureInfo.InvariantCulture)), ["Pressure"] = new DataValue(1013, StatusCodes.Good, DateTime.Parse("2021-09-27T18:45:19.555Z", CultureInfo.InvariantCulture), DateTime.Parse("2021-09-27T18:45:19.555Z", CultureInfo.InvariantCulture)), ["Humidiy"] = new DataValue(42, StatusCodes.Uncertain, DateTime.Parse("2021-09-27T18:45:19.555Z", CultureInfo.InvariantCulture), DateTime.Parse("2021-09-27T18:45:19.555Z", CultureInfo.InvariantCulture)) }, (DataSetFieldContentFlags)fieldMask) }, new JsonDataSetMessage { DataSetMessageContentMask = PubSubMessageContentFlagHelper.StackToDataSetMessageContentFlags(datasetMask), DataSetWriterId = 100, SequenceNumber = 29767, MetaDataVersion = new ConfigurationVersionDataType { MajorVersion = 672338910, MinorVersion = 672341762 }, Timestamp = DateTime.Parse("2021-09-27T18:45:19.556Z", CultureInfo.InvariantCulture), Status = 1073741824, MessageType = MessageType.DeltaFrame, DataSetWriterName = "Writer100", Payload = new DataSet(new Dictionary { ["Temperature"] = new DataValue(26, StatusCodes.Good, DateTime.Parse("2021-09-27T18:45:19.556Z", CultureInfo.InvariantCulture), DateTime.Parse("2021-09-27T18:45:19.556Z", CultureInfo.InvariantCulture)), ["Pressure"] = new DataValue(1014, StatusCodes.Good, DateTime.Parse("2021-09-27T18:45:19.556Z", CultureInfo.InvariantCulture), DateTime.Parse("2021-09-27T18:45:19.556Z", CultureInfo.InvariantCulture)), ["Humidiy"] = new DataValue(43, StatusCodes.Uncertain, DateTime.Parse("2021-09-27T18:45:19.556Z", CultureInfo.InvariantCulture), DateTime.Parse("2021-09-27T18:45:19.556Z", CultureInfo.InvariantCulture)) }, PubSubMessageContentFlagHelper.StackToDataSetFieldContentFlags(fieldMask)) } ] }; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/PubSub/MonitoredItemMessageEncoderDecoderTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.PubSub { using Azure.IIoT.OpcUa.Encoders.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Opc.Ua; using System; using System.Collections.Generic; using System.Linq; using Xunit; /// /// Monitored item json encoder decoder tests /// public class MonitoredItemMessageEncoderDecoderTests { public const NetworkMessageContentFlags NetworkMessageContentMaskDefault = NetworkMessageContentFlags.PublisherId | // Important: No NetworkMessageContentFlags.NetworkMessageHeader | NetworkMessageContentFlags.DataSetMessageHeader | NetworkMessageContentFlags.DataSetClassId; public const DataSetMessageContentFlags DataSetMessageContentMaskDefault = DataSetMessageContentFlags.MessageType | DataSetMessageContentFlags.DataSetWriterId | DataSetMessageContentFlags.SequenceNumber | DataSetMessageContentFlags.MetaDataVersion | DataSetMessageContentFlags.Timestamp | DataSetMessageContentFlags.Status; public const DataSetFieldContentFlags DataSetFieldContentFlagsDefault = DataSetFieldContentFlags.ApplicationUri | // Important DataSetFieldContentFlags.EndpointUrl | // Important DataSetFieldContentFlags.NodeId | // Important DataSetFieldContentFlags.DisplayName | // Important DataSetFieldContentFlags.SourceTimestamp | DataSetFieldContentFlags.ServerTimestamp | DataSetFieldContentFlags.SourcePicoSeconds | DataSetFieldContentFlags.ServerPicoSeconds | DataSetFieldContentFlags.StatusCode; [Theory] [InlineData(false, false, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(false, false, false, NetworkMessageContentMaskDefault, 3)] [InlineData(false, false, false, NetworkMessageContentMaskDefault, 1)] [InlineData(false, false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(false, false, true, NetworkMessageContentMaskDefault, 3)] [InlineData(true, false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(true, false, true, NetworkMessageContentMaskDefault, 3)] [InlineData(false, true, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(false, true, false, NetworkMessageContentMaskDefault, 3)] [InlineData(false, true, false, NetworkMessageContentMaskDefault, 1)] [InlineData(false, true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(false, true, true, NetworkMessageContentMaskDefault, 3)] [InlineData(true, true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(true, true, true, NetworkMessageContentMaskDefault, 3)] public void EncodeDecodeNetworkMessage(bool useArrayEnvelope, bool compress, bool useCompatibilityMode, NetworkMessageContentFlags contentMask, int numberOfMessages) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(useCompatibilityMode, sequenceNumber)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask, messages); networkMessage.UseGzipCompression = compress; networkMessage.UseArrayEnvelope = useArrayEnvelope; var context = new ServiceMessageContext(); var buffer = Assert.Single(networkMessage.Encode(context, 256 * 1000)); ConvertToOpcUaUniversalTime(networkMessage); var result = ((BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context, messageSchema: networkMessage.MessageSchema)).Messages; Assert.Equal(messages, result); } [Theory] [InlineData(false, false, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(false, false, false, NetworkMessageContentMaskDefault, 3)] [InlineData(false, false, false, NetworkMessageContentMaskDefault, 1)] [InlineData(false, false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(false, false, true, NetworkMessageContentMaskDefault, 3)] [InlineData(true, false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(true, false, true, NetworkMessageContentMaskDefault, 3)] [InlineData(false, true, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(false, true, false, NetworkMessageContentMaskDefault, 3)] [InlineData(false, true, false, NetworkMessageContentMaskDefault, 1)] [InlineData(false, true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(false, true, true, NetworkMessageContentMaskDefault, 3)] [InlineData(true, true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 1)] [InlineData(true, true, true, NetworkMessageContentMaskDefault, 3)] public void EncodeDecodeNetworkMessageReversible(bool useArrayEnvelope, bool compress, bool useCompatibilityMode, NetworkMessageContentFlags contentMask, int numberOfMessages) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(useCompatibilityMode, sequenceNumber, DataSetMessageContentMaskDefault | DataSetMessageContentFlags.ReversibleFieldEncoding)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask, messages); networkMessage.UseGzipCompression = compress; networkMessage.UseArrayEnvelope = useArrayEnvelope; var context = new ServiceMessageContext(); var buffer = Assert.Single(networkMessage.Encode(context, 256 * 1000)); ConvertToOpcUaUniversalTime(networkMessage); var result = ((BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context, messageSchema: networkMessage.MessageSchema)).Messages; Assert.Equal(messages, result); } [Theory] [InlineData(false, false, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, false, false, NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(false, false, true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(false, false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(true, false, true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(true, false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, false, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(false, false, false, NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(false, false, true, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(false, false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(true, false, true, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(true, false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(false, true, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, true, false, NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(false, true, true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(false, true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(true, true, true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(true, true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, true, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(false, true, false, NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(false, true, true, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(false, true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(true, true, true, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(true, true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] public void EncodeDecodeNetworkMessages(bool useArrayEnvelope, bool compress, bool useCompatibilityMode, NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(useCompatibilityMode, sequenceNumber)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask, messages); networkMessage.UseGzipCompression = compress; networkMessage.UseArrayEnvelope = useArrayEnvelope; var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); ConvertToOpcUaUniversalTime(networkMessage); var result = buffers .Select(buffer => (BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context, messageSchema: networkMessage.MessageSchema)) .SelectMany(m => m.Messages).ToList(); Assert.Equal(messages, result); } [Theory] [InlineData(false, false, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, false, false, NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(false, false, true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(false, false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(true, false, true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(true, false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, false, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(false, false, false, NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(false, false, true, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(false, false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(true, false, true, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(true, false, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(false, true, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, true, false, NetworkMessageContentMaskDefault, 10, 256 * 1024)] [InlineData(false, true, true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(false, true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(true, true, true, NetworkMessageContentMaskDefault, 15, 256 * 1024)] [InlineData(true, true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 256 * 1024)] [InlineData(false, true, false, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(false, true, false, NetworkMessageContentMaskDefault, 10, 1024)] [InlineData(false, true, true, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(false, true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] [InlineData(true, true, true, NetworkMessageContentMaskDefault, 15, 1024)] [InlineData(true, true, true, NetworkMessageContentMaskDefault | NetworkMessageContentFlags.SingleDataSetMessage, 5, 1024)] public void EncodeDecodeNetworkMessagesReversible(bool useArrayEnvelope, bool compress, bool useCompatibilityMode, NetworkMessageContentFlags contentMask, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(useCompatibilityMode, sequenceNumber, DataSetMessageContentMaskDefault | DataSetMessageContentFlags.ReversibleFieldEncoding)) .ToList(); var networkMessage = CreateNetworkMessage(contentMask, messages); networkMessage.UseGzipCompression = compress; networkMessage.UseArrayEnvelope = useArrayEnvelope; var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize); ConvertToOpcUaUniversalTime(networkMessage); var result = buffers .Select(buffer => (BaseNetworkMessage)PubSubMessage .Decode(buffer, networkMessage.ContentType, context, messageSchema: networkMessage.MessageSchema)) .SelectMany(m => m.Messages).ToList(); Assert.Equal(messages, result); } /// /// Convert timestamps of payload to OpcUa Utc. /// /// private static void ConvertToOpcUaUniversalTime(BaseNetworkMessage networkMessage) { // convert DataSet Payload DataValue timestamps to OpcUa Utc foreach (var dataSetMessage in networkMessage.Messages) { var expectedPayload = new Dictionary(); foreach (var (Name, Value) in dataSetMessage.Payload.DataSetFields) { expectedPayload[Name] = new DataValue(Value).ToOpcUaUniversalTime(); } dataSetMessage.Payload = new DataSet(expectedPayload, DataSetFieldContentFlags.ApplicationUri | // Important DataSetFieldContentFlags.EndpointUrl | // Important DataSetFieldContentFlags.NodeId | // Important DataSetFieldContentFlags.DisplayName | // Important DataSetFieldContentFlags.StatusCode | DataSetFieldContentFlags.SourceTimestamp); } } /// /// Create network message /// /// /// private static JsonNetworkMessage CreateNetworkMessage( NetworkMessageContentFlags contentMask, List messages) { return new JsonNetworkMessage { MessageId = () => "9279C0B3-DA88-45A4-AF74-451CEBF82DB0", Messages = messages, DataSetWriterGroup = "group", DataSetClassId = Guid.NewGuid(), PublisherId = "PublisherId", NetworkMessageContentMask = contentMask }; } /// /// Create dataset message /// /// /// /// /// private static MonitoredItemMessage CreateDataSetMessage(bool useCompatibilityMode, int sequenceNumber, DataSetMessageContentFlags dataSetMessageContentMask = DataSetMessageContentMaskDefault, DataSetFieldContentFlags dataSetFieldContentMask = DataSetFieldContentFlagsDefault) { return new MonitoredItemMessage { EndpointUrl = "EndpointUrl", ApplicationUri = "ApplicationUrl", NodeId = "NodeId", SequenceNumber = (ushort)sequenceNumber, UseCompatibilityMode = useCompatibilityMode, Status = StatusCodes.Bad, Timestamp = DateTimeOffset.UtcNow, Payload = CreateDataSet(dataSetFieldContentMask), DataSetMessageContentMask = dataSetMessageContentMask }; } /// /// Create dataset /// /// private static DataSet CreateDataSet(DataSetFieldContentFlags dataSetFieldContentMask = DataSetFieldContentFlagsDefault) { return new DataSet(new Dictionary { { "1", new DataValue(new Variant("test"), StatusCodes.Good, DateTime.Now, DateTime.UtcNow) } }, dataSetFieldContentMask); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/PubSub/PubSubMessageContentFlagHelper.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { using Azure.IIoT.OpcUa.Publisher.Models; using Opc.Ua; /// /// Stack types conversions /// internal static class PubSubMessageContentFlagHelper { /// /// Get network message content mask /// /// /// public static NetworkMessageContentFlags StackToNetworkMessageContentFlags(uint mask) { NetworkMessageContentFlags result = 0u; if ((mask & (uint)JsonNetworkMessageContentMask.PublisherId) != 0) { result |= NetworkMessageContentFlags.PublisherId; } if ((mask & (uint)JsonNetworkMessageContentMask.DataSetClassId) != 0) { result |= NetworkMessageContentFlags.DataSetClassId; } if ((mask & (uint)JsonNetworkMessageContentMask.ReplyTo) != 0) { result |= NetworkMessageContentFlags.ReplyTo; } if ((mask & (uint)JsonNetworkMessageContentMask.NetworkMessageHeader) != 0) { result |= NetworkMessageContentFlags.NetworkMessageHeader; } else { // If not set, bits 3, 4 and 5 can also not be set result = 0; } if ((mask & 0x8000000) != 0) { // If monitored item message, then no network message header result = 0; } if ((mask & (uint)JsonNetworkMessageContentMask.DataSetMessageHeader) != 0) { result |= NetworkMessageContentFlags.DataSetMessageHeader; } if ((mask & (uint)JsonNetworkMessageContentMask.SingleDataSetMessage) != 0) { result |= NetworkMessageContentFlags.SingleDataSetMessage; } return result; } /// /// Get dataset message content mask /// /// /// public static DataSetMessageContentFlags StackToDataSetMessageContentFlags(uint mask) { DataSetMessageContentFlags result = 0u; if ((mask & (uint)JsonDataSetMessageContentMask.Timestamp) != 0) { result |= DataSetMessageContentFlags.Timestamp; } if ((mask & (uint)JsonDataSetMessageContentMask.Status) != 0) { result |= DataSetMessageContentFlags.Status; } if ((mask & (uint)JsonDataSetMessageContentMask.MetaDataVersion) != 0) { result |= DataSetMessageContentFlags.MetaDataVersion; } if ((mask & (uint)JsonDataSetMessageContentMask.SequenceNumber) != 0) { result |= DataSetMessageContentFlags.SequenceNumber; } if ((mask & (uint)JsonDataSetMessageContentMask.DataSetWriterId) != 0) { result |= DataSetMessageContentFlags.DataSetWriterId; } if ((mask & (uint)JsonDataSetMessageContentMask.MessageType) != 0) { result |= DataSetMessageContentFlags.MessageType; } if ((mask & (uint)JsonDataSetMessageContentMask.DataSetWriterName) != 0) { result |= DataSetMessageContentFlags.DataSetWriterName; } if ((mask & (uint)JsonDataSetMessageContentMask.FieldEncoding1) != 0) { result |= DataSetMessageContentFlags.ReversibleFieldEncoding; } // if (fieldMask != null) // { // if ((fieldMask & DataSetFieldContentFlags.NodeId) != 0) // { // result |= JsonDataSetMessageContentMaskEx.NodeId; // } // if ((fieldMask & DataSetFieldContentFlags.DisplayName) != 0) // { // result |= JsonDataSetMessageContentMaskEx.DisplayName; // } // if ((fieldMask & DataSetFieldContentFlags.ExtensionFields) != 0) // { // result |= JsonDataSetMessageContentMaskEx.ExtensionFields; // } // if ((fieldMask & DataSetFieldContentFlags.EndpointUrl) != 0) // { // result |= JsonDataSetMessageContentMaskEx.EndpointUrl; // } // if ((fieldMask & DataSetFieldContentFlags.ApplicationUri) != 0) // { // result |= JsonDataSetMessageContentMaskEx.ApplicationUri; // } // } return result; } /// /// Get dataset message content mask /// /// /// public static DataSetFieldContentFlags StackToDataSetFieldContentFlags(uint mask) { DataSetFieldContentFlags result = 0; if ((mask & (uint)DataSetFieldContentMask.StatusCode) != 0) { result |= DataSetFieldContentFlags.StatusCode; } if ((mask & (uint)DataSetFieldContentMask.SourceTimestamp) != 0) { result |= DataSetFieldContentFlags.SourceTimestamp; } if ((mask & (uint)DataSetFieldContentMask.ServerTimestamp) != 0) { result |= DataSetFieldContentFlags.ServerTimestamp; } if ((mask & (uint)DataSetFieldContentMask.SourcePicoSeconds) != 0) { result |= DataSetFieldContentFlags.SourcePicoSeconds; } if ((mask & (uint)DataSetFieldContentMask.ServerPicoSeconds) != 0) { result |= DataSetFieldContentFlags.ServerPicoSeconds; } if ((mask & (uint)DataSetFieldContentMask.RawData) != 0) { result |= DataSetFieldContentFlags.RawData; } if ((mask & 64) != 0) { result |= DataSetFieldContentFlags.SingleFieldDegradeToValue; } return result; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/PubSub/UadpNetworkMessageEncoderDecoderTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.PubSub { using Azure.IIoT.OpcUa.Encoders.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Opc.Ua; using System; using System.Buffers; using System.Collections.Generic; using System.Linq; using Xunit; /// /// Uadp encoder decoder tests /// public class UadpNetworkMessageEncoderDecoderTests : IDataSetMetaDataResolver { /// /// All /// public const NetworkMessageContentFlags NetworkMessageContentMaskDefault = NetworkMessageContentFlags.PublisherId | NetworkMessageContentFlags.GroupHeader | NetworkMessageContentFlags.WriterGroupId | NetworkMessageContentFlags.GroupVersion | NetworkMessageContentFlags.NetworkMessageNumber | NetworkMessageContentFlags.SequenceNumber | NetworkMessageContentFlags.PayloadHeader | NetworkMessageContentFlags.Timestamp | NetworkMessageContentFlags.Picoseconds | NetworkMessageContentFlags.DataSetClassId | NetworkMessageContentFlags.PromotedFields; public const DataSetMessageContentFlags DataSetMessageContentMaskDefault = DataSetMessageContentFlags.PicoSeconds | DataSetMessageContentFlags.SequenceNumber | DataSetMessageContentFlags.MajorVersion | DataSetMessageContentFlags.MinorVersion | DataSetMessageContentFlags.Timestamp | DataSetMessageContentFlags.Status; public const DataSetFieldContentFlags DataSetFieldContentFlagsDefault = DataSetFieldContentFlags.SourceTimestamp | DataSetFieldContentFlags.ServerTimestamp | DataSetFieldContentFlags.SourcePicoSeconds | DataSetFieldContentFlags.ServerPicoSeconds | DataSetFieldContentFlags.StatusCode; [Theory] [InlineData(MessageType.KeyFrame, 1)] [InlineData(MessageType.KeyFrame, 3)] [InlineData(MessageType.KeyFrame, 10)] [InlineData(MessageType.Event, 1)] [InlineData(MessageType.Event, 3)] [InlineData(MessageType.Event, 10)] [InlineData(MessageType.DeltaFrame, 1)] [InlineData(MessageType.DeltaFrame, 3)] [InlineData(MessageType.DeltaFrame, 10)] public void EncodeDecodeNetworkMessage(MessageType type, int numberOfMessages) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(type, sequenceNumber)) .ToList(); var networkMessage = CreateNetworkMessage(NetworkMessageContentMaskDefault, messages); var context = new ServiceMessageContext(); var buffer = Assert.Single(networkMessage.Encode(context, 256 * 1000, this)); ConvertToOpcUaUniversalTime(networkMessage); var result = PubSubMessage.Decode(buffer, networkMessage.ContentType, context, this); Assert.Equal(networkMessage, result); } [Theory] [InlineData(MessageType.KeyFrame, 8, 100)] [InlineData(MessageType.KeyFrame, 10, 100)] [InlineData(MessageType.KeyFrame, 100, 100)] [InlineData(MessageType.KeyFrame, 1000, 100)] [InlineData(MessageType.KeyFrame, 194, 100)] [InlineData(MessageType.KeyFrame, 8, 1024)] [InlineData(MessageType.KeyFrame, 10, 1024)] [InlineData(MessageType.KeyFrame, 100, 1024)] [InlineData(MessageType.KeyFrame, 1000, 1024)] [InlineData(MessageType.KeyFrame, 194, 1024)] [InlineData(MessageType.KeyFrame, 8, 256 * 1024)] [InlineData(MessageType.KeyFrame, 10, 256 * 1024)] [InlineData(MessageType.KeyFrame, 100, 256 * 1024)] [InlineData(MessageType.KeyFrame, 1000, 256 * 1024)] [InlineData(MessageType.KeyFrame, 194, 256 * 1024)] [InlineData(MessageType.Event, 1, 100)] [InlineData(MessageType.Event, 5, 100)] [InlineData(MessageType.Event, 194, 100)] [InlineData(MessageType.Event, 1, 1024)] [InlineData(MessageType.Event, 5, 1024)] [InlineData(MessageType.Event, 194, 1024)] [InlineData(MessageType.Event, 1, 256 * 1024)] [InlineData(MessageType.Event, 5, 256 * 1024)] [InlineData(MessageType.Event, 194, 256 * 1024)] [InlineData(MessageType.DeltaFrame, 1, 100)] [InlineData(MessageType.DeltaFrame, 5, 100)] [InlineData(MessageType.DeltaFrame, 194, 100)] [InlineData(MessageType.DeltaFrame, 1, 1024)] [InlineData(MessageType.DeltaFrame, 5, 1024)] [InlineData(MessageType.DeltaFrame, 194, 1024)] [InlineData(MessageType.DeltaFrame, 1, 256 * 1024)] [InlineData(MessageType.DeltaFrame, 5, 256 * 1024)] [InlineData(MessageType.DeltaFrame, 194, 256 * 1024)] public void EncodeDecodeNetworkMessages(MessageType type, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(type, sequenceNumber)) .ToList(); var networkMessage = CreateNetworkMessage(NetworkMessageContentMaskDefault, messages); var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize, this); ConvertToOpcUaUniversalTime(networkMessage); var decodedMessages = PubSubMessage .Decode(CreateReader(buffers), networkMessage.ContentType, context, this) .OfType() .ToList(); var result = decodedMessages[0]; result.Messages = decodedMessages.SelectMany(m => m.Messages).ToList(); Assert.Equal(networkMessage, result); } [Theory] [InlineData(MessageType.KeyFrame, 1, 100)] [InlineData(MessageType.KeyFrame, 5, 100)] [InlineData(MessageType.KeyFrame, 194, 100)] [InlineData(MessageType.KeyFrame, 1, 1024)] [InlineData(MessageType.KeyFrame, 5, 1024)] [InlineData(MessageType.KeyFrame, 194, 1024)] [InlineData(MessageType.KeyFrame, 1, 256 * 1024)] [InlineData(MessageType.KeyFrame, 5, 256 * 1024)] [InlineData(MessageType.KeyFrame, 194, 256 * 1024)] [InlineData(MessageType.DeltaFrame, 1, 100)] [InlineData(MessageType.DeltaFrame, 5, 100)] [InlineData(MessageType.DeltaFrame, 194, 100)] [InlineData(MessageType.DeltaFrame, 1, 1024)] [InlineData(MessageType.DeltaFrame, 5, 1024)] [InlineData(MessageType.DeltaFrame, 194, 1024)] [InlineData(MessageType.DeltaFrame, 1, 256 * 1024)] [InlineData(MessageType.DeltaFrame, 5, 256 * 1024)] [InlineData(MessageType.DeltaFrame, 194, 256 * 1024)] [InlineData(MessageType.Event, 1, 100)] [InlineData(MessageType.Event, 194, 100)] [InlineData(MessageType.Event, 1, 1024)] [InlineData(MessageType.Event, 194, 1024)] [InlineData(MessageType.Event, 194, 256 * 1024)] public void EncodeDecodeNetworkMessagesNoGroupHeader(MessageType type, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(type, sequenceNumber)) .ToList(); var networkMessage = CreateNetworkMessage( NetworkMessageContentMaskDefault & ~NetworkMessageContentFlags.GroupHeader, messages); var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize, this); ConvertToOpcUaUniversalTime(networkMessage); var m = PubSubMessage .Decode(CreateReader(buffers), networkMessage.ContentType, context, this) .OfType() .ToList(); var result = m[0]; result.Messages = m.SelectMany(m => m.Messages).ToList(); Assert.Equal(networkMessage, result); } [Theory] [InlineData(MessageType.KeyFrame, 1, 100)] [InlineData(MessageType.KeyFrame, 5, 100)] [InlineData(MessageType.KeyFrame, 194, 100)] [InlineData(MessageType.KeyFrame, 1, 1024)] [InlineData(MessageType.KeyFrame, 5, 1024)] [InlineData(MessageType.KeyFrame, 194, 1024)] [InlineData(MessageType.KeyFrame, 1, 256 * 1024)] [InlineData(MessageType.KeyFrame, 5, 256 * 1024)] [InlineData(MessageType.KeyFrame, 194, 256 * 1024)] [InlineData(MessageType.DeltaFrame, 1, 100)] [InlineData(MessageType.DeltaFrame, 5, 100)] [InlineData(MessageType.DeltaFrame, 194, 100)] [InlineData(MessageType.DeltaFrame, 1, 1024)] [InlineData(MessageType.DeltaFrame, 5, 1024)] [InlineData(MessageType.DeltaFrame, 194, 1024)] [InlineData(MessageType.DeltaFrame, 1, 256 * 1024)] [InlineData(MessageType.DeltaFrame, 5, 256 * 1024)] [InlineData(MessageType.DeltaFrame, 194, 256 * 1024)] [InlineData(MessageType.Event, 1, 100)] [InlineData(MessageType.Event, 194, 100)] [InlineData(MessageType.Event, 1, 1024)] [InlineData(MessageType.Event, 194, 1024)] [InlineData(MessageType.Event, 194, 256 * 1024)] public void EncodeDecodeNetworkMessagesNoPayloadHeader(MessageType type, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(type, sequenceNumber)) .ToList(); var networkMessage = CreateNetworkMessage( NetworkMessageContentMaskDefault & ~NetworkMessageContentFlags.PayloadHeader, messages); var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize, this); ConvertToOpcUaUniversalTime(networkMessage); var m = PubSubMessage .Decode(CreateReader(buffers), networkMessage.ContentType, context, this) .OfType() .ToList(); var result = m.SelectMany(m => m.Messages).Select(m => m.Payload).ToList(); Assert.All(networkMessage.Messages.Select(m => m.Payload), (p, i) => Assert.True(result[i].Equals(p))); } [Theory] [InlineData(MessageType.KeyFrame, 1, 100)] [InlineData(MessageType.KeyFrame, 5, 100)] [InlineData(MessageType.KeyFrame, 194, 100)] [InlineData(MessageType.KeyFrame, 1, 1024)] [InlineData(MessageType.KeyFrame, 5, 1024)] [InlineData(MessageType.KeyFrame, 194, 1024)] [InlineData(MessageType.KeyFrame, 1, 256 * 1024)] [InlineData(MessageType.KeyFrame, 5, 256 * 1024)] [InlineData(MessageType.KeyFrame, 194, 256 * 1024)] [InlineData(MessageType.DeltaFrame, 1, 100)] [InlineData(MessageType.DeltaFrame, 5, 100)] [InlineData(MessageType.DeltaFrame, 194, 100)] [InlineData(MessageType.DeltaFrame, 1, 1024)] [InlineData(MessageType.DeltaFrame, 5, 1024)] [InlineData(MessageType.DeltaFrame, 194, 1024)] [InlineData(MessageType.DeltaFrame, 1, 256 * 1024)] [InlineData(MessageType.DeltaFrame, 5, 256 * 1024)] [InlineData(MessageType.DeltaFrame, 194, 256 * 1024)] [InlineData(MessageType.Event, 1, 100)] [InlineData(MessageType.Event, 194, 100)] [InlineData(MessageType.Event, 1, 1024)] [InlineData(MessageType.Event, 194, 1024)] [InlineData(MessageType.Event, 194, 256 * 1024)] public void EncodeDecodeNetworkMessagesNoHeaders(MessageType type, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(type, sequenceNumber)) .ToList(); var networkMessage = CreateNetworkMessage(NetworkMessageContentMaskDefault & ~(NetworkMessageContentFlags.GroupHeader | NetworkMessageContentFlags.PayloadHeader), messages); var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize, this); ConvertToOpcUaUniversalTime(networkMessage); var m = PubSubMessage .Decode(CreateReader(buffers), networkMessage.ContentType, context, this) .OfType() .ToList(); var result = m.SelectMany(m => m.Messages).Select(m => m.Payload).ToList(); Assert.All(networkMessage.Messages.Select(m => m.Payload), (p, i) => Assert.True(result[i].Equals(p))); } [Theory] [InlineData(MessageType.KeyFrame, 1, 100)] [InlineData(MessageType.KeyFrame, 5, 100)] [InlineData(MessageType.KeyFrame, 194, 100)] [InlineData(MessageType.KeyFrame, 1, 1024)] [InlineData(MessageType.KeyFrame, 5, 1024)] [InlineData(MessageType.KeyFrame, 194, 1024)] [InlineData(MessageType.KeyFrame, 1, 256 * 1024)] [InlineData(MessageType.KeyFrame, 5, 256 * 1024)] [InlineData(MessageType.KeyFrame, 194, 256 * 1024)] [InlineData(MessageType.DeltaFrame, 1, 100)] [InlineData(MessageType.DeltaFrame, 5, 100)] [InlineData(MessageType.DeltaFrame, 194, 100)] [InlineData(MessageType.DeltaFrame, 1, 1024)] [InlineData(MessageType.DeltaFrame, 5, 1024)] [InlineData(MessageType.DeltaFrame, 194, 1024)] [InlineData(MessageType.DeltaFrame, 1, 256 * 1024)] [InlineData(MessageType.DeltaFrame, 5, 256 * 1024)] [InlineData(MessageType.DeltaFrame, 194, 256 * 1024)] [InlineData(MessageType.Event, 1, 100)] [InlineData(MessageType.Event, 194, 100)] [InlineData(MessageType.Event, 1, 1024)] [InlineData(MessageType.Event, 194, 1024)] [InlineData(MessageType.Event, 194, 256 * 1024)] public void EncodeDecodeNetworkMessagesNoHeaderRaw(MessageType type, int numberOfMessages, int maxMessageSize) { var messages = Enumerable .Range(3, numberOfMessages) .Select(sequenceNumber => (BaseDataSetMessage)CreateDataSetMessage(type, sequenceNumber, dataSetFieldContentMask: DataSetFieldContentFlags.RawData)) .ToList(); var networkMessage = CreateNetworkMessage(NetworkMessageContentMaskDefault & ~(NetworkMessageContentFlags.GroupHeader | NetworkMessageContentFlags.PayloadHeader), messages); var context = new ServiceMessageContext(); var buffers = networkMessage.Encode(context, maxMessageSize, this); ConvertToOpcUaUniversalTime(networkMessage); // Compare payload as raw data equivalent var serializer = new NewtonsoftJsonSerializer(); var decodedMessages = PubSubMessage .Decode(CreateReader(buffers), networkMessage.ContentType, context, this) .OfType() .SelectMany(m => m.Messages) .ToList(); var result = serializer.Parse(serializer.SerializeToString(decodedMessages .SelectMany(m => m.Payload.DataSetFields) .Select(v => (v.Name, v.Value.Value)) .ToList())); var expected = serializer.Parse(serializer.SerializeToString(messages .SelectMany(m => m.Payload.DataSetFields) .Select(v => (v.Name, v.Value.Value)) .ToList())); Assert.Equal(expected, result); } /// /// Convert timestamps of payload to OpcUa Utc. /// /// private static void ConvertToOpcUaUniversalTime(BaseNetworkMessage networkMessage) { // convert DataSet Payload DataValue timestamps to OpcUa Utc foreach (var dataSetMessage in networkMessage.Messages) { var expectedPayload = new Dictionary(); foreach (var (Name, Value) in dataSetMessage.Payload.DataSetFields) { expectedPayload[Name] = new DataValue(Value).ToOpcUaUniversalTime(); } dataSetMessage.Payload = new DataSet(expectedPayload, DataSetFieldContentFlags.StatusCode | DataSetFieldContentFlags.SourceTimestamp); } } /// /// Create network message /// /// /// private UadpNetworkMessage CreateNetworkMessage( NetworkMessageContentFlags contentMask, List messages) { return new UadpNetworkMessage { Messages = messages, WriterGroupId = 4, Timestamp = DateTimeOffset.UtcNow, PicoSeconds = 65, SequenceNumber = () => _lastSequenceNumber++, DataSetClassId = Guid.NewGuid(), PublisherId = "PublisherId", NetworkMessageContentMask = contentMask }; } private ushort _lastSequenceNumber; /// /// Create dataset message /// /// /// /// /// private static UadpDataSetMessage CreateDataSetMessage(MessageType type, int sequenceNumber, DataSetMessageContentFlags dataSetMessageContentMask = DataSetMessageContentMaskDefault, DataSetFieldContentFlags dataSetFieldContentMask = DataSetFieldContentFlagsDefault) { return new UadpDataSetMessage { DataSetWriterId = 3, MetaDataVersion = new ConfigurationVersionDataType { MajorVersion = 1, MinorVersion = 1 }, SequenceNumber = (ushort)sequenceNumber, Status = StatusCodes.Bad, Timestamp = DateTimeOffset.UtcNow, MessageType = type, Picoseconds = 1, Payload = CreateDataSet(type == MessageType.DeltaFrame, dataSetFieldContentMask), DataSetMessageContentMask = dataSetMessageContentMask }; } public PublishedDataSetMetaDataModel Find(ushort writerId, uint majorVersion = 0, uint minorVersion = 0) { // Return independent on whether we receive valid writer id or major minor versions // In raw mode without payload headers there is no way to decode key frames without // preconfigured writer id and versioning, so we assume we have it by some means return new PublishedDataSetMetaDataModel { DataSetMetaData = new DataSetMetaDataModel(), Fields = new[] { new PublishedFieldMetaDataModel { Name = "1", BuiltInType = (byte)BuiltInType.Int32, ValueRank = ValueRanks.Scalar }, new PublishedFieldMetaDataModel { Name = "2", BuiltInType = (byte)BuiltInType.Float, ValueRank = ValueRanks.Scalar }, new PublishedFieldMetaDataModel { Name = "3", BuiltInType = (byte)BuiltInType.String, ValueRank = ValueRanks.Scalar } } }; } /// /// Create dataset /// /// /// private static DataSet CreateDataSet(bool deltaFrame, DataSetFieldContentFlags dataSetFieldContentMask = DataSetFieldContentFlagsDefault) { return !deltaFrame ? new DataSet(new Dictionary { { "1", new DataValue(new Variant(5), StatusCodes.Good, DateTime.Now, DateTime.UtcNow) }, { "2", new DataValue(new Variant(0.5), StatusCodes.Good, DateTime.Now) }, { "3", new DataValue("abcd") } }, dataSetFieldContentMask) : new DataSet(new Dictionary { { "3", new DataValue("abcd") } }, dataSetFieldContentMask); } private static Queue> CreateReader(IReadOnlyList> buffers) { var reader = new Queue>(); foreach (var buffer in buffers) { reader.Enqueue(buffer); } return reader; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/SchemaUtilsTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas { using System.Linq; using Xunit; public class SchemaUtilsTests { [Theory] [InlineData("Test")] [InlineData("")] [InlineData("Test.Test")] [InlineData("Test.Test.Test")] [InlineData("%§$%&/()=?")] [InlineData(" ")] [InlineData(" sd ")] [InlineData("a ac d")] [InlineData("a/b/c/d")] [InlineData("§$§§\"\"§")] [InlineData("黄色) 黄色] 桃子{ 黑色 狗[ 紫色 桃子] 狗 红色 葡萄% 桃子? 猫 猴子 绵羊")] [InlineData("蓝色 紫色 蓝色 红色$")] [InlineData("_x84_")] [InlineData("_x8432")] [InlineData("x8$x8")] public void TestEscapeUnespace(string value) { var escaped = SchemaUtils.Escape(value); Assert.True(escaped.All(c => c.Equals('_') || char.IsLetterOrDigit(c))); var unsescaped = SchemaUtils.Unescape(escaped); Assert.Equal(value, unsescaped); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroNetworkMessageAvroSchemaTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas { using Azure.IIoT.OpcUa.Encoders.Schemas.Avro; using Azure.IIoT.OpcUa.Publisher.Models; using System.IO; using System.Linq; using System.Text.Json; using System.Threading.Tasks; using Xunit; public class AvroNetworkMessageAvroSchemaTests { [Theory] [MemberData(nameof(GetMessageMetaDataFiles))] public async Task CreateAvroNetworkMessageSchemasAsync(string messageMetaDataFile) { var message = await LoadAsync(messageMetaDataFile); var schema = new AvroNetworkMessage(message); var json = schema.ToString(); var document = JsonDocument.Parse(json); json = JsonSerializer.Serialize(document, kIndented); Assert.NotNull(json); await AssertAsync("NetworkMessageDefault", messageMetaDataFile, json); var schema2 = global::Avro.Schema.Parse(json); Assert.NotNull(schema2); //Assert.Equal(schema.Schema, schema2); } [Theory] [MemberData(nameof(GetMessageMetaDataFiles))] public async Task CreateAvroNetworkMessageWithNsAsync(string messageMetaDataFile) { var message = await LoadAsync(messageMetaDataFile); var schema = new AvroNetworkMessage(message, new SchemaOptions { Namespace = "http://www.microsoft.com" }); var json = schema.ToString(); await AssertAsync("NetworkMessage", messageMetaDataFile, json); var schema2 = global::Avro.Schema.Parse(json); Assert.NotNull(schema2); //Assert.Equal(schema.Schema, schema2); } [Theory] [MemberData(nameof(GetMessageMetaDataFiles))] public async Task CreateMessageSchemaWithoutNetworkHeaderAsync(string messageMetaDataFile) { var message = await LoadAsync(messageMetaDataFile); message = message with { NetworkMessageContentFlags = NetworkMessageContentFlags.DataSetMessageHeader }; var schema = new AvroNetworkMessage(message); var json = schema.ToString(); await AssertAsync("Multiple", messageMetaDataFile, json); var schema2 = global::Avro.Schema.Parse(json); Assert.NotNull(schema2); //Assert.Equal(schema.Schema, schema2); } [Theory] [MemberData(nameof(GetMessageMetaDataFiles))] public async Task CreateSingleMessageSchemaAsync(string messageMetaDataFile) { var message = await LoadAsync(messageMetaDataFile); message = message with { NetworkMessageContentFlags = NetworkMessageContentFlags.DataSetMessageHeader | NetworkMessageContentFlags.SingleDataSetMessage }; var schema = new AvroNetworkMessage(message); var json = schema.ToString(); await AssertAsync("Single", messageMetaDataFile, json); var schema2 = global::Avro.Schema.Parse(json); Assert.NotNull(schema2); //Assert.Equal(schema.Schema, schema2); } [Theory] [MemberData(nameof(GetMessageMetaDataFiles))] public async Task CreateSingleMessageSchemaWithoutHeaderAsync(string messageMetaDataFile) { var message = await LoadAsync(messageMetaDataFile); message = message with { NetworkMessageContentFlags = NetworkMessageContentFlags.SingleDataSetMessage }; var schema = new AvroNetworkMessage(message); var json = schema.ToString(); await AssertAsync("Default", messageMetaDataFile, json); var schema2 = global::Avro.Schema.Parse(json); Assert.NotNull(schema2); //Assert.Equal(schema.Schema, schema2); } [Theory] [MemberData(nameof(GetMessageMetaDataFiles))] public async Task CreateRawMessageSchemaAsync(string messageMetaDataFile) { var message = await LoadAsync(messageMetaDataFile); message = message with { NetworkMessageContentFlags = NetworkMessageContentFlags.SingleDataSetMessage, DataSetMessages = message.DataSetMessages.Select(d => d with { DataSetMessageContentFlags = 0u, DataSetFieldContentFlags = DataSetFieldContentFlags.RawData }).ToList() }; var schema = new AvroNetworkMessage(message); var json = schema.ToString(); await AssertAsync("Raw", messageMetaDataFile, json); var schema2 = global::Avro.Schema.Parse(json); Assert.NotNull(schema2); //Assert.Equal(schema.Schema, schema2); } [Theory] [MemberData(nameof(GetMessageMetaDataFiles))] public async Task CreateRawMessageSchemaReversibleAsync(string messageMetaDataFile) { var message = await LoadAsync(messageMetaDataFile); message = message with { NetworkMessageContentFlags = NetworkMessageContentFlags.SingleDataSetMessage, DataSetMessages = message.DataSetMessages.Select(d => d with { DataSetMessageContentFlags = DataSetMessageContentFlags.ReversibleFieldEncoding, DataSetFieldContentFlags = 0u }).ToList() }; var schema = new AvroNetworkMessage(message); var json = schema.ToString(); await AssertAsync("RawReversible", messageMetaDataFile, json); var schema2 = global::Avro.Schema.Parse(json); Assert.NotNull(schema2); //Assert.Equal(schema.Schema, schema2); } private static async ValueTask LoadAsync(string file) { await using var fs = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read); return await JsonSerializer.DeserializeAsync(fs); } private static readonly JsonSerializerOptions kIndented = new() { WriteIndented = true }; private static async Task AssertAsync(string name, string messageMetaDataFile, string json) { var document = JsonDocument.Parse(json); json = JsonSerializer.Serialize(document, kIndented).ReplaceLineEndings(); Assert.NotNull(json); #if WRITE var folder = Path.Combine(".", "AvroSchema", name); if (!Directory.Exists(folder)) { Directory.CreateDirectory(folder); } await File.WriteAllTextAsync(Path.Combine(folder, Path.GetFileName(messageMetaDataFile)), json); #else var folder = Path.Combine(".", "Encoders", "Schemas", "AvroSchema", name); var expected = await File.ReadAllTextAsync(Path.Combine(folder, Path.GetFileName(messageMetaDataFile))); Assert.Equal(expected.ReplaceLineEndings(), json); #endif } public static TheoryData GetMessageMetaDataFiles() { var resources = Directory.GetFiles(Path.Combine(".", "Resources"), "*.json"); return new TheoryData(resources); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/Default/CyclicReads.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "i_x61_2258", "type": [ "null", { "type": "record", "name": "DateTimeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } ] }, { "name": "StatusCode", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": [ "null", { "type": "record", "name": "UInt32DataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": [ "null", { "type": "record", "name": "BooleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": [ "null", { "type": "record", "name": "Int32DataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Int32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_6" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": [ "null", { "type": "record", "name": "DoubleDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.DoubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.DoubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": [ "null", "org.github.microsoft.opc.publisher.DoubleDataValue" ] }, { "name": "ns_x61_23_x59_i_x61_1259", "type": [ "null", { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "Boolean", { "type": "record", "name": "SByte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_2" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Byte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_3" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Int16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_4" ], "fields": [ { "name": "Value", "type": "int" } ] }, "UInt16", "Int32", "UInt32", { "type": "record", "name": "Int64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_8" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "UInt64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": [ "int", { "type": "fixed", "name": "ulong", "namespace": "org.opcfoundation.UA", "size": 8 } ] } ] }, { "type": "record", "name": "Float", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_10" ], "fields": [ { "name": "Value", "type": "float" } ] }, "Double", { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] }, "DateTime", { "type": "record", "name": "Guid", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14" ], "fields": [ { "name": "Value", "type": { "type": "string", "logicalType": "uuid" } } ] }, { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] }, { "type": "record", "name": "XmlElement", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_16" ], "fields": [ { "name": "Value", "type": "string" } ] }, { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] }, { "name": "ServerUri", "type": "String" } ] }, "StatusCode", { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Name", "type": "String" } ] }, { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "String" }, { "name": "Text", "type": "String" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "Value", "type": [ { "type": "record", "name": "EncodedDataType", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Body", "type": "ByteString" } ] } ] } ] }, "DataValue", { "type": "record", "name": "Enumeration", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_29" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "BooleanCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "Int16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] }, { "type": "record", "name": "BooleanMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "ByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Byte" } } ] }, { "type": "record", "name": "Int16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] } ] } ] } }, { "name": "StatusCode", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "DateTime" }, { "name": "SourcePicoseconds", "type": "UInt16" }, { "name": "ServerTimestamp", "type": "DateTime" }, { "name": "ServerPicoseconds", "type": "UInt16" } ] } ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/Default/KeepAlive.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "State", "type": [ "null", { "type": "record", "name": "ServerStateDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "enum", "name": "ServerState", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_852" ], "symbols": [ "Running", "Failed", "NoConfiguration", "Suspended", "Shutdown", "Test", "CommunicationFault", "Unknown" ], "default": "Running", "uaDataTypeId": "i=852" } ] }, { "name": "StatusCode", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "SourceTimestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "SourcePicoseconds", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/Default/KeyFrames.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "CurrentTime", "type": [ "null", { "type": "record", "name": "DateTimeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } ] }, { "name": "StatusCode", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "EngineeringUnits", "type": [ "null", { "type": "record", "name": "StringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "AssetId", "type": [ "null", { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] }, { "type": "record", "name": "SByte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_2" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Byte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_3" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Int16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_4" ], "fields": [ { "name": "Value", "type": "int" } ] }, "UInt16", { "type": "record", "name": "Int32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_6" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Int64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_8" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "UInt64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": [ "int", { "type": "fixed", "name": "ulong", "namespace": "org.opcfoundation.UA", "size": 8 } ] } ] }, { "type": "record", "name": "Float", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_10" ], "fields": [ { "name": "Value", "type": "float" } ] }, { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] }, "String", "DateTime", { "type": "record", "name": "Guid", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14" ], "fields": [ { "name": "Value", "type": { "type": "string", "logicalType": "uuid" } } ] }, { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] }, { "type": "record", "name": "XmlElement", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_16" ], "fields": [ { "name": "Value", "type": "string" } ] }, { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] }, { "name": "ServerUri", "type": "String" } ] }, "StatusCode", { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Name", "type": "String" } ] }, { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "String" }, { "name": "Text", "type": "String" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "Value", "type": [ { "type": "record", "name": "EncodedDataType", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Body", "type": "ByteString" } ] } ] } ] }, "DataValue", { "type": "record", "name": "Enumeration", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_29" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "BooleanCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "Int16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] }, { "type": "record", "name": "BooleanMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "ByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Byte" } } ] }, { "type": "record", "name": "Int16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] } ] } ] } }, { "name": "StatusCode", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "DateTime" }, { "name": "SourcePicoseconds", "type": "UInt16" }, { "name": "ServerTimestamp", "type": "DateTime" }, { "name": "ServerPicoseconds", "type": "UInt16" } ] } ] }, { "name": "Important", "type": [ "null", { "type": "record", "name": "BooleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.Boolean" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "Variance", "type": [ "null", { "type": "record", "name": "FloatDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.Float" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/Default/PendingAlarms.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "ConditionClassId", "type": [ "null", { "type": "record", "name": "NodeIdDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "Namespace", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "Identifier", "type": [ { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] }, "String", { "type": "record", "name": "Guid", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14" ], "fields": [ { "name": "Value", "type": { "type": "string", "logicalType": "uuid" } } ] }, { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] } ] } ] } ] }, { "name": "StatusCode", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "SourceTimestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "SourcePicoseconds", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "ConditionClassName", "type": [ "null", { "type": "record", "name": "LocalizedTextDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "String" }, { "name": "Text", "type": "String" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "ConditionSubClassId", "type": [ "null", { "type": "record", "name": "NodeIdCollectionDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "NodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "ConditionSubClassName", "type": [ "null", { "type": "record", "name": "LocalizedTextCollectionDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "LocalizedTextCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "EventId", "type": [ "null", { "type": "record", "name": "ByteStringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.ByteString" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "EventType", "type": [ "null", "org.github.microsoft.opc.publisher.NodeIdDataValue" ] }, { "name": "LocalTime", "type": [ "null", { "type": "record", "name": "TimeZoneDataTypeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "TimeZoneDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_8912" ], "fields": [ { "name": "Offset", "type": { "type": "record", "name": "Int16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_4" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "DaylightSavingInOffset", "type": { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] } } ], "uaDataTypeId": "i=8912" } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "Message", "type": [ "null", "org.github.microsoft.opc.publisher.LocalizedTextDataValue" ] }, { "name": "ReceiveTime", "type": [ "null", { "type": "record", "name": "DateTimeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.DateTime" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "Severity", "type": [ "null", { "type": "record", "name": "UInt16DataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.UInt16" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "SourceName", "type": [ "null", { "type": "record", "name": "StringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.String" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "SourceNode", "type": [ "null", "org.github.microsoft.opc.publisher.NodeIdDataValue" ] }, { "name": "Time", "type": [ "null", "org.github.microsoft.opc.publisher.DateTimeDataValue" ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/Default/PlcSimulation.json ================================================ [ { "type": "record", "name": "DataSet", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": [ "null", { "type": "record", "name": "UInt32DataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "StatusCode", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "SourceTimestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "SourcePicoseconds", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": [ "null", { "type": "record", "name": "BooleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": [ "null", { "type": "record", "name": "Int32DataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Int32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_6" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": [ "null", { "type": "record", "name": "DoubleDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.DoubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.DoubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": [ "null", "org.github.microsoft.opc.publisher.DoubleDataValue" ] } ] }, { "type": "record", "name": "DataSet1", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/Default/SimpleEvents.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "EventId", "type": [ "null", { "type": "record", "name": "ByteStringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] } ] }, { "name": "StatusCode", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "SourceTimestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "SourcePicoseconds", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "Message", "type": [ "null", { "type": "record", "name": "LocalizedTextDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "Text", "type": "String" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CycleId", "type": [ "null", { "type": "record", "name": "StringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.String" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CurrentStep", "type": [ "null", { "type": "record", "name": "CycleStepDataTypeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "CycleStepDataType", "namespace": "org.opcfoundation.SimpleEvents", "aliases": [ "org.opcfoundation.SimpleEvents.i_x95_183" ], "fields": [ { "name": "Name", "type": "org.opcfoundation.UA.String" }, { "name": "Duration", "type": { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] } } ], "uaDataTypeId": "nsu=http://opcfoundation.org/SimpleEvents;i=183" } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/Multiple/CyclicReads.json ================================================ { "type": "record", "name": "NetworkMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Messages", "type": { "type": "array", "items": { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageType", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "DataSetWriterName", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetWriterId", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "SequenceNumber", "type": { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "MetaDataVersion", "type": { "type": "record", "name": "ConfigurationVersionDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14593" ], "fields": [ { "name": "MajorVersion", "type": "UInt32" }, { "name": "MinorVersion", "type": "UInt32" } ] } }, { "name": "Timestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "i_x61_2258", "type": [ "null", { "type": "record", "name": "DateTimeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.DateTime" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": [ "null", { "type": "record", "name": "UInt32DataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": [ "null", { "type": "record", "name": "BooleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": [ "null", { "type": "record", "name": "Int32DataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Int32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_6" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": [ "null", { "type": "record", "name": "DoubleDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.DoubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.DoubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": [ "null", "org.github.microsoft.opc.publisher.DoubleDataValue" ] }, { "name": "ns_x61_23_x59_i_x61_1259", "type": [ "null", { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "Boolean", { "type": "record", "name": "SByte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_2" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Byte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_3" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Int16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_4" ], "fields": [ { "name": "Value", "type": "int" } ] }, "UInt16", "Int32", "UInt32", { "type": "record", "name": "Int64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_8" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "UInt64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": [ "int", { "type": "fixed", "name": "ulong", "namespace": "org.opcfoundation.UA", "size": 8 } ] } ] }, { "type": "record", "name": "Float", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_10" ], "fields": [ { "name": "Value", "type": "float" } ] }, "Double", "String", "DateTime", { "type": "record", "name": "Guid", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14" ], "fields": [ { "name": "Value", "type": { "type": "string", "logicalType": "uuid" } } ] }, { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] }, { "type": "record", "name": "XmlElement", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_16" ], "fields": [ { "name": "Value", "type": "string" } ] }, { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] }, { "name": "ServerUri", "type": "String" } ] }, "StatusCode", { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Name", "type": "String" } ] }, { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "String" }, { "name": "Text", "type": "String" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "Value", "type": [ { "type": "record", "name": "EncodedDataType", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Body", "type": "ByteString" } ] } ] } ] }, "DataValue", { "type": "record", "name": "Enumeration", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_29" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "BooleanCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "Int16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] }, { "type": "record", "name": "BooleanMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "ByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Byte" } } ] }, { "type": "record", "name": "Int16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] } ] } ] } }, { "name": "StatusCode", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "DateTime" }, { "name": "SourcePicoseconds", "type": "UInt16" }, { "name": "ServerTimestamp", "type": "DateTime" }, { "name": "ServerPicoseconds", "type": "UInt16" } ] } ] } ] } } ] } } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/Multiple/KeepAlive.json ================================================ { "type": "record", "name": "NetworkMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Messages", "type": { "type": "array", "items": { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageType", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "DataSetWriterName", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetWriterId", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "SequenceNumber", "type": { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "MetaDataVersion", "type": { "type": "record", "name": "ConfigurationVersionDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14593" ], "fields": [ { "name": "MajorVersion", "type": "UInt32" }, { "name": "MinorVersion", "type": "UInt32" } ] } }, { "name": "Timestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "State", "type": [ "null", { "type": "record", "name": "ServerStateDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "enum", "name": "ServerState", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_852" ], "symbols": [ "Running", "Failed", "NoConfiguration", "Suspended", "Shutdown", "Test", "CommunicationFault", "Unknown" ], "default": "Running", "uaDataTypeId": "i=852" } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] } ] } } ] } } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/Multiple/KeyFrames.json ================================================ { "type": "record", "name": "NetworkMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Messages", "type": { "type": "array", "items": { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageType", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "DataSetWriterName", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetWriterId", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "SequenceNumber", "type": { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "MetaDataVersion", "type": { "type": "record", "name": "ConfigurationVersionDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14593" ], "fields": [ { "name": "MajorVersion", "type": "UInt32" }, { "name": "MinorVersion", "type": "UInt32" } ] } }, { "name": "Timestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "CurrentTime", "type": [ "null", { "type": "record", "name": "DateTimeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.DateTime" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "EngineeringUnits", "type": [ "null", { "type": "record", "name": "StringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.String" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "AssetId", "type": [ "null", { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] }, { "type": "record", "name": "SByte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_2" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Byte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_3" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Int16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_4" ], "fields": [ { "name": "Value", "type": "int" } ] }, "UInt16", { "type": "record", "name": "Int32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_6" ], "fields": [ { "name": "Value", "type": "int" } ] }, "UInt32", { "type": "record", "name": "Int64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_8" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "UInt64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": [ "int", { "type": "fixed", "name": "ulong", "namespace": "org.opcfoundation.UA", "size": 8 } ] } ] }, { "type": "record", "name": "Float", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_10" ], "fields": [ { "name": "Value", "type": "float" } ] }, { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] }, "String", "DateTime", { "type": "record", "name": "Guid", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14" ], "fields": [ { "name": "Value", "type": { "type": "string", "logicalType": "uuid" } } ] }, { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] }, { "type": "record", "name": "XmlElement", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_16" ], "fields": [ { "name": "Value", "type": "string" } ] }, { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] }, { "name": "ServerUri", "type": "String" } ] }, "StatusCode", { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Name", "type": "String" } ] }, { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "String" }, { "name": "Text", "type": "String" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "Value", "type": [ { "type": "record", "name": "EncodedDataType", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Body", "type": "ByteString" } ] } ] } ] }, "DataValue", { "type": "record", "name": "Enumeration", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_29" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "BooleanCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "Int16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] }, { "type": "record", "name": "BooleanMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "ByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Byte" } } ] }, { "type": "record", "name": "Int16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] } ] } ] } }, { "name": "StatusCode", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "DateTime" }, { "name": "SourcePicoseconds", "type": "UInt16" }, { "name": "ServerTimestamp", "type": "DateTime" }, { "name": "ServerPicoseconds", "type": "UInt16" } ] } ] }, { "name": "Important", "type": [ "null", { "type": "record", "name": "BooleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.Boolean" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "Variance", "type": [ "null", { "type": "record", "name": "FloatDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.Float" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] } ] } } ] } } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/Multiple/PendingAlarms.json ================================================ { "type": "record", "name": "NetworkMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Messages", "type": { "type": "array", "items": { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageType", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "DataSetWriterName", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetWriterId", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "SequenceNumber", "type": { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "MetaDataVersion", "type": { "type": "record", "name": "ConfigurationVersionDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14593" ], "fields": [ { "name": "MajorVersion", "type": "UInt32" }, { "name": "MinorVersion", "type": "UInt32" } ] } }, { "name": "Timestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "ConditionClassId", "type": [ "null", { "type": "record", "name": "NodeIdDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", { "type": "record", "name": "Guid", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14" ], "fields": [ { "name": "Value", "type": { "type": "string", "logicalType": "uuid" } } ] }, { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] } ] } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "ConditionClassName", "type": [ "null", { "type": "record", "name": "LocalizedTextDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "String" }, { "name": "Text", "type": "String" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "ConditionSubClassId", "type": [ "null", { "type": "record", "name": "NodeIdCollectionDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "NodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "ConditionSubClassName", "type": [ "null", { "type": "record", "name": "LocalizedTextCollectionDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "LocalizedTextCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "EventId", "type": [ "null", { "type": "record", "name": "ByteStringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.ByteString" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "EventType", "type": [ "null", "org.github.microsoft.opc.publisher.NodeIdDataValue" ] }, { "name": "LocalTime", "type": [ "null", { "type": "record", "name": "TimeZoneDataTypeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "TimeZoneDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_8912" ], "fields": [ { "name": "Offset", "type": { "type": "record", "name": "Int16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_4" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "DaylightSavingInOffset", "type": { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] } } ], "uaDataTypeId": "i=8912" } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "Message", "type": [ "null", "org.github.microsoft.opc.publisher.LocalizedTextDataValue" ] }, { "name": "ReceiveTime", "type": [ "null", { "type": "record", "name": "DateTimeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.DateTime" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "Severity", "type": [ "null", { "type": "record", "name": "UInt16DataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.UInt16" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "SourceName", "type": [ "null", { "type": "record", "name": "StringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.String" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "SourceNode", "type": [ "null", "org.github.microsoft.opc.publisher.NodeIdDataValue" ] }, { "name": "Time", "type": [ "null", "org.github.microsoft.opc.publisher.DateTimeDataValue" ] } ] } } ] } } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/Multiple/PlcSimulation.json ================================================ { "type": "record", "name": "NetworkMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Messages", "type": { "type": "array", "items": [ { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageType", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "DataSetWriterName", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetWriterId", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "SequenceNumber", "type": { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "MetaDataVersion", "type": { "type": "record", "name": "ConfigurationVersionDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14593" ], "fields": [ { "name": "MajorVersion", "type": "UInt32" }, { "name": "MinorVersion", "type": "UInt32" } ] } }, { "name": "Timestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": [ "null", { "type": "record", "name": "UInt32DataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": [ "null", { "type": "record", "name": "BooleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": [ "null", { "type": "record", "name": "Int32DataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Int32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_6" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": [ "null", { "type": "record", "name": "DoubleDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.DoubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.DoubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": [ "null", "org.github.microsoft.opc.publisher.DoubleDataValue" ] } ] } } ] }, { "type": "record", "name": "DataSetMessage1", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageType", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetWriterName", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetWriterId", "type": "org.opcfoundation.UA.UInt16" }, { "name": "SequenceNumber", "type": "org.opcfoundation.UA.UInt32" }, { "name": "MetaDataVersion", "type": "org.opcfoundation.UA.ConfigurationVersionDataType" }, { "name": "Timestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "Payload", "type": { "type": "record", "name": "DataSet1", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] } ] } } ] } ] } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/Multiple/SimpleEvents.json ================================================ { "type": "record", "name": "NetworkMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Messages", "type": { "type": "array", "items": { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageType", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "DataSetWriterName", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetWriterId", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "SequenceNumber", "type": { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "MetaDataVersion", "type": { "type": "record", "name": "ConfigurationVersionDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14593" ], "fields": [ { "name": "MajorVersion", "type": "UInt32" }, { "name": "MinorVersion", "type": "UInt32" } ] } }, { "name": "Timestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "EventId", "type": [ "null", { "type": "record", "name": "ByteStringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "Message", "type": [ "null", { "type": "record", "name": "LocalizedTextDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "String" }, { "name": "Text", "type": "String" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CycleId", "type": [ "null", { "type": "record", "name": "StringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.String" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CurrentStep", "type": [ "null", { "type": "record", "name": "CycleStepDataTypeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "CycleStepDataType", "namespace": "org.opcfoundation.SimpleEvents", "aliases": [ "org.opcfoundation.SimpleEvents.i_x95_183" ], "fields": [ { "name": "Name", "type": "org.opcfoundation.UA.String" }, { "name": "Duration", "type": { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] } } ], "uaDataTypeId": "nsu=http://opcfoundation.org/SimpleEvents;i=183" } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] } ] } } ] } } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/NetworkMessage/CyclicReads.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "i_x61_2258", "type": [ "null", { "type": "record", "name": "DateTimeDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } ] }, { "name": "StatusCode", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": [ "null", { "type": "record", "name": "UInt32DataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": [ "null", { "type": "record", "name": "BooleanDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": [ "null", { "type": "record", "name": "Int32DataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Int32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_6" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": [ "null", { "type": "record", "name": "DoubleDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": [ "null", "com.microsoft.DoubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": [ "null", "com.microsoft.DoubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": [ "null", "com.microsoft.DoubleDataValue" ] }, { "name": "ns_x61_23_x59_i_x61_1259", "type": [ "null", { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "Boolean", { "type": "record", "name": "SByte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_2" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Byte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_3" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Int16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_4" ], "fields": [ { "name": "Value", "type": "int" } ] }, "UInt16", "Int32", "UInt32", { "type": "record", "name": "Int64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_8" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "UInt64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": [ "int", { "type": "fixed", "name": "ulong", "namespace": "org.opcfoundation.UA", "size": 8 } ] } ] }, { "type": "record", "name": "Float", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_10" ], "fields": [ { "name": "Value", "type": "float" } ] }, "Double", { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] }, "DateTime", { "type": "record", "name": "Guid", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14" ], "fields": [ { "name": "Value", "type": { "type": "string", "logicalType": "uuid" } } ] }, { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] }, { "type": "record", "name": "XmlElement", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_16" ], "fields": [ { "name": "Value", "type": "string" } ] }, { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] }, { "name": "ServerUri", "type": "String" } ] }, "StatusCode", { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Name", "type": "String" } ] }, { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "String" }, { "name": "Text", "type": "String" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "Value", "type": [ { "type": "record", "name": "EncodedDataType", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Body", "type": "ByteString" } ] } ] } ] }, "DataValue", { "type": "record", "name": "Enumeration", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_29" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "BooleanCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "Int16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] }, { "type": "record", "name": "BooleanMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "ByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Byte" } } ] }, { "type": "record", "name": "Int16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] } ] } ] } }, { "name": "StatusCode", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "DateTime" }, { "name": "SourcePicoseconds", "type": "UInt16" }, { "name": "ServerTimestamp", "type": "DateTime" }, { "name": "ServerPicoseconds", "type": "UInt16" } ] } ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/NetworkMessage/KeepAlive.json ================================================ { "type": "record", "name": "NetworkMessage", "namespace": "com.microsoft", "fields": [ { "name": "MessageId", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "MessageType", "type": "org.opcfoundation.UA.String" }, { "name": "PublisherId", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetClassId", "type": { "type": "record", "name": "Guid", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14" ], "fields": [ { "name": "Value", "type": { "type": "string", "logicalType": "uuid" } } ] } }, { "name": "DataSetWriterGroup", "type": "org.opcfoundation.UA.String" }, { "name": "Messages", "type": { "type": "array", "items": { "type": "record", "name": "DataSetMessage", "namespace": "com.microsoft", "fields": [ { "name": "MessageType", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetWriterName", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetWriterId", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "SequenceNumber", "type": { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "MetaDataVersion", "type": { "type": "record", "name": "ConfigurationVersionDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14593" ], "fields": [ { "name": "MajorVersion", "type": "UInt32" }, { "name": "MinorVersion", "type": "UInt32" } ] } }, { "name": "Timestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "State", "type": [ "null", { "type": "record", "name": "ServerStateDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", { "type": "enum", "name": "ServerState", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_852" ], "symbols": [ "Running", "Failed", "NoConfiguration", "Suspended", "Shutdown", "Test", "CommunicationFault", "Unknown" ], "default": "Running", "uaDataTypeId": "i=852" } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] } ] } } ] } } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/NetworkMessage/KeyFrames.json ================================================ { "type": "record", "name": "NetworkMessage", "namespace": "com.microsoft", "fields": [ { "name": "MessageId", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "MessageType", "type": "org.opcfoundation.UA.String" }, { "name": "PublisherId", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetClassId", "type": { "type": "record", "name": "Guid", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14" ], "fields": [ { "name": "Value", "type": { "type": "string", "logicalType": "uuid" } } ] } }, { "name": "DataSetWriterGroup", "type": "org.opcfoundation.UA.String" }, { "name": "Messages", "type": { "type": "array", "items": { "type": "record", "name": "DataSetMessage", "namespace": "com.microsoft", "fields": [ { "name": "MessageType", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetWriterName", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetWriterId", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "SequenceNumber", "type": { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "MetaDataVersion", "type": { "type": "record", "name": "ConfigurationVersionDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14593" ], "fields": [ { "name": "MajorVersion", "type": "UInt32" }, { "name": "MinorVersion", "type": "UInt32" } ] } }, { "name": "Timestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "CurrentTime", "type": [ "null", { "type": "record", "name": "DateTimeDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.DateTime" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "EngineeringUnits", "type": [ "null", { "type": "record", "name": "StringDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.String" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "AssetId", "type": [ "null", { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] }, { "type": "record", "name": "SByte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_2" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Byte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_3" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Int16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_4" ], "fields": [ { "name": "Value", "type": "int" } ] }, "UInt16", { "type": "record", "name": "Int32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_6" ], "fields": [ { "name": "Value", "type": "int" } ] }, "UInt32", { "type": "record", "name": "Int64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_8" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "UInt64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": [ "int", { "type": "fixed", "name": "ulong", "namespace": "org.opcfoundation.UA", "size": 8 } ] } ] }, { "type": "record", "name": "Float", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_10" ], "fields": [ { "name": "Value", "type": "float" } ] }, { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] }, "String", "DateTime", "Guid", { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] }, { "type": "record", "name": "XmlElement", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_16" ], "fields": [ { "name": "Value", "type": "string" } ] }, { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] }, { "name": "ServerUri", "type": "String" } ] }, "StatusCode", { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Name", "type": "String" } ] }, { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "String" }, { "name": "Text", "type": "String" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "Value", "type": [ { "type": "record", "name": "EncodedDataType", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Body", "type": "ByteString" } ] } ] } ] }, "DataValue", { "type": "record", "name": "Enumeration", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_29" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "BooleanCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "Int16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] }, { "type": "record", "name": "BooleanMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "ByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Byte" } } ] }, { "type": "record", "name": "Int16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] } ] } ] } }, { "name": "StatusCode", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "DateTime" }, { "name": "SourcePicoseconds", "type": "UInt16" }, { "name": "ServerTimestamp", "type": "DateTime" }, { "name": "ServerPicoseconds", "type": "UInt16" } ] } ] }, { "name": "Important", "type": [ "null", { "type": "record", "name": "BooleanDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.Boolean" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "Variance", "type": [ "null", { "type": "record", "name": "FloatDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.Float" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] } ] } } ] } } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/NetworkMessage/PendingAlarms.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "ConditionClassId", "type": [ "null", { "type": "record", "name": "NodeIdDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "Namespace", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "Identifier", "type": [ { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] }, "String", { "type": "record", "name": "Guid", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14" ], "fields": [ { "name": "Value", "type": { "type": "string", "logicalType": "uuid" } } ] }, { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] } ] } ] } ] }, { "name": "StatusCode", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "SourceTimestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "SourcePicoseconds", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "ConditionClassName", "type": [ "null", { "type": "record", "name": "LocalizedTextDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "String" }, { "name": "Text", "type": "String" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "ConditionSubClassId", "type": [ "null", { "type": "record", "name": "NodeIdCollectionDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "NodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "ConditionSubClassName", "type": [ "null", { "type": "record", "name": "LocalizedTextCollectionDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "LocalizedTextCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "EventId", "type": [ "null", { "type": "record", "name": "ByteStringDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.ByteString" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "EventType", "type": [ "null", "com.microsoft.NodeIdDataValue" ] }, { "name": "LocalTime", "type": [ "null", { "type": "record", "name": "TimeZoneDataTypeDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "TimeZoneDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_8912" ], "fields": [ { "name": "Offset", "type": { "type": "record", "name": "Int16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_4" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "DaylightSavingInOffset", "type": { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] } } ], "uaDataTypeId": "i=8912" } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "Message", "type": [ "null", "com.microsoft.LocalizedTextDataValue" ] }, { "name": "ReceiveTime", "type": [ "null", { "type": "record", "name": "DateTimeDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.DateTime" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "Severity", "type": [ "null", { "type": "record", "name": "UInt16DataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.UInt16" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "SourceName", "type": [ "null", { "type": "record", "name": "StringDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.String" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "SourceNode", "type": [ "null", "com.microsoft.NodeIdDataValue" ] }, { "name": "Time", "type": [ "null", "com.microsoft.DateTimeDataValue" ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/NetworkMessage/PlcSimulation.json ================================================ [ { "type": "record", "name": "DataSet", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": [ "null", { "type": "record", "name": "UInt32DataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "StatusCode", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "SourceTimestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "SourcePicoseconds", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": [ "null", { "type": "record", "name": "BooleanDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": [ "null", { "type": "record", "name": "Int32DataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Int32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_6" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": [ "null", { "type": "record", "name": "DoubleDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": [ "null", "com.microsoft.DoubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": [ "null", "com.microsoft.DoubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": [ "null", "com.microsoft.DoubleDataValue" ] } ] }, { "type": "record", "name": "DataSet1", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": [ "null", "com.microsoft.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": [ "null", "com.microsoft.UInt32DataValue" ] } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/NetworkMessage/SimpleEvents.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "EventId", "type": [ "null", { "type": "record", "name": "ByteStringDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] } ] }, { "name": "StatusCode", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "SourceTimestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "SourcePicoseconds", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "Message", "type": [ "null", { "type": "record", "name": "LocalizedTextDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "Text", "type": "String" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CycleId", "type": [ "null", { "type": "record", "name": "StringDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.String" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CurrentStep", "type": [ "null", { "type": "record", "name": "CycleStepDataTypeDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "CycleStepDataType", "namespace": "org.opcfoundation.SimpleEvents", "aliases": [ "org.opcfoundation.SimpleEvents.i_x95_183" ], "fields": [ { "name": "Name", "type": "org.opcfoundation.UA.String" }, { "name": "Duration", "type": { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] } } ], "uaDataTypeId": "nsu=http://opcfoundation.org/SimpleEvents;i=183" } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/NetworkMessageDefault/CyclicReads.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "i_x61_2258", "type": [ "null", { "type": "record", "name": "DateTimeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } ] }, { "name": "StatusCode", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": [ "null", { "type": "record", "name": "UInt32DataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": [ "null", { "type": "record", "name": "BooleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": [ "null", { "type": "record", "name": "Int32DataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Int32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_6" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": [ "null", { "type": "record", "name": "DoubleDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.DoubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.DoubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": [ "null", "org.github.microsoft.opc.publisher.DoubleDataValue" ] }, { "name": "ns_x61_23_x59_i_x61_1259", "type": [ "null", { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "Boolean", { "type": "record", "name": "SByte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_2" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Byte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_3" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Int16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_4" ], "fields": [ { "name": "Value", "type": "int" } ] }, "UInt16", "Int32", "UInt32", { "type": "record", "name": "Int64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_8" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "UInt64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": [ "int", { "type": "fixed", "name": "ulong", "namespace": "org.opcfoundation.UA", "size": 8 } ] } ] }, { "type": "record", "name": "Float", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_10" ], "fields": [ { "name": "Value", "type": "float" } ] }, "Double", { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] }, "DateTime", { "type": "record", "name": "Guid", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14" ], "fields": [ { "name": "Value", "type": { "type": "string", "logicalType": "uuid" } } ] }, { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] }, { "type": "record", "name": "XmlElement", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_16" ], "fields": [ { "name": "Value", "type": "string" } ] }, { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] }, { "name": "ServerUri", "type": "String" } ] }, "StatusCode", { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Name", "type": "String" } ] }, { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "String" }, { "name": "Text", "type": "String" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "Value", "type": [ { "type": "record", "name": "EncodedDataType", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Body", "type": "ByteString" } ] } ] } ] }, "DataValue", { "type": "record", "name": "Enumeration", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_29" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "BooleanCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "Int16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] }, { "type": "record", "name": "BooleanMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "ByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Byte" } } ] }, { "type": "record", "name": "Int16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] } ] } ] } }, { "name": "StatusCode", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "DateTime" }, { "name": "SourcePicoseconds", "type": "UInt16" }, { "name": "ServerTimestamp", "type": "DateTime" }, { "name": "ServerPicoseconds", "type": "UInt16" } ] } ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/NetworkMessageDefault/KeepAlive.json ================================================ { "type": "record", "name": "NetworkMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageId", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "MessageType", "type": "org.opcfoundation.UA.String" }, { "name": "PublisherId", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetClassId", "type": { "type": "record", "name": "Guid", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14" ], "fields": [ { "name": "Value", "type": { "type": "string", "logicalType": "uuid" } } ] } }, { "name": "DataSetWriterGroup", "type": "org.opcfoundation.UA.String" }, { "name": "Messages", "type": { "type": "array", "items": { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageType", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetWriterName", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetWriterId", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "SequenceNumber", "type": { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "MetaDataVersion", "type": { "type": "record", "name": "ConfigurationVersionDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14593" ], "fields": [ { "name": "MajorVersion", "type": "UInt32" }, { "name": "MinorVersion", "type": "UInt32" } ] } }, { "name": "Timestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "State", "type": [ "null", { "type": "record", "name": "ServerStateDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "enum", "name": "ServerState", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_852" ], "symbols": [ "Running", "Failed", "NoConfiguration", "Suspended", "Shutdown", "Test", "CommunicationFault", "Unknown" ], "default": "Running", "uaDataTypeId": "i=852" } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] } ] } } ] } } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/NetworkMessageDefault/KeyFrames.json ================================================ { "type": "record", "name": "NetworkMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageId", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "MessageType", "type": "org.opcfoundation.UA.String" }, { "name": "PublisherId", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetClassId", "type": { "type": "record", "name": "Guid", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14" ], "fields": [ { "name": "Value", "type": { "type": "string", "logicalType": "uuid" } } ] } }, { "name": "DataSetWriterGroup", "type": "org.opcfoundation.UA.String" }, { "name": "Messages", "type": { "type": "array", "items": { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageType", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetWriterName", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetWriterId", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "SequenceNumber", "type": { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "MetaDataVersion", "type": { "type": "record", "name": "ConfigurationVersionDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14593" ], "fields": [ { "name": "MajorVersion", "type": "UInt32" }, { "name": "MinorVersion", "type": "UInt32" } ] } }, { "name": "Timestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "CurrentTime", "type": [ "null", { "type": "record", "name": "DateTimeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.DateTime" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "EngineeringUnits", "type": [ "null", { "type": "record", "name": "StringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.String" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "AssetId", "type": [ "null", { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] }, { "type": "record", "name": "SByte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_2" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Byte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_3" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Int16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_4" ], "fields": [ { "name": "Value", "type": "int" } ] }, "UInt16", { "type": "record", "name": "Int32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_6" ], "fields": [ { "name": "Value", "type": "int" } ] }, "UInt32", { "type": "record", "name": "Int64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_8" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "UInt64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": [ "int", { "type": "fixed", "name": "ulong", "namespace": "org.opcfoundation.UA", "size": 8 } ] } ] }, { "type": "record", "name": "Float", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_10" ], "fields": [ { "name": "Value", "type": "float" } ] }, { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] }, "String", "DateTime", "Guid", { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] }, { "type": "record", "name": "XmlElement", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_16" ], "fields": [ { "name": "Value", "type": "string" } ] }, { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] }, { "name": "ServerUri", "type": "String" } ] }, "StatusCode", { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Name", "type": "String" } ] }, { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "String" }, { "name": "Text", "type": "String" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "Value", "type": [ { "type": "record", "name": "EncodedDataType", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Body", "type": "ByteString" } ] } ] } ] }, "DataValue", { "type": "record", "name": "Enumeration", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_29" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "BooleanCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "Int16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] }, { "type": "record", "name": "BooleanMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "ByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Byte" } } ] }, { "type": "record", "name": "Int16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] } ] } ] } }, { "name": "StatusCode", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "DateTime" }, { "name": "SourcePicoseconds", "type": "UInt16" }, { "name": "ServerTimestamp", "type": "DateTime" }, { "name": "ServerPicoseconds", "type": "UInt16" } ] } ] }, { "name": "Important", "type": [ "null", { "type": "record", "name": "BooleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.Boolean" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "Variance", "type": [ "null", { "type": "record", "name": "FloatDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.Float" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] } ] } } ] } } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/NetworkMessageDefault/PendingAlarms.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "ConditionClassId", "type": [ "null", { "type": "record", "name": "NodeIdDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "Namespace", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "Identifier", "type": [ { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] }, "String", { "type": "record", "name": "Guid", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14" ], "fields": [ { "name": "Value", "type": { "type": "string", "logicalType": "uuid" } } ] }, { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] } ] } ] } ] }, { "name": "StatusCode", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "SourceTimestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "SourcePicoseconds", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "ConditionClassName", "type": [ "null", { "type": "record", "name": "LocalizedTextDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "String" }, { "name": "Text", "type": "String" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "ConditionSubClassId", "type": [ "null", { "type": "record", "name": "NodeIdCollectionDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "NodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "ConditionSubClassName", "type": [ "null", { "type": "record", "name": "LocalizedTextCollectionDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "LocalizedTextCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "EventId", "type": [ "null", { "type": "record", "name": "ByteStringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.ByteString" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "EventType", "type": [ "null", "org.github.microsoft.opc.publisher.NodeIdDataValue" ] }, { "name": "LocalTime", "type": [ "null", { "type": "record", "name": "TimeZoneDataTypeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "TimeZoneDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_8912" ], "fields": [ { "name": "Offset", "type": { "type": "record", "name": "Int16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_4" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "DaylightSavingInOffset", "type": { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] } } ], "uaDataTypeId": "i=8912" } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "Message", "type": [ "null", "org.github.microsoft.opc.publisher.LocalizedTextDataValue" ] }, { "name": "ReceiveTime", "type": [ "null", { "type": "record", "name": "DateTimeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.DateTime" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "Severity", "type": [ "null", { "type": "record", "name": "UInt16DataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.UInt16" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "SourceName", "type": [ "null", { "type": "record", "name": "StringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.String" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "SourceNode", "type": [ "null", "org.github.microsoft.opc.publisher.NodeIdDataValue" ] }, { "name": "Time", "type": [ "null", "org.github.microsoft.opc.publisher.DateTimeDataValue" ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/NetworkMessageDefault/PlcSimulation.json ================================================ [ { "type": "record", "name": "DataSet", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": [ "null", { "type": "record", "name": "UInt32DataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "StatusCode", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "SourceTimestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "SourcePicoseconds", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": [ "null", { "type": "record", "name": "BooleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": [ "null", { "type": "record", "name": "Int32DataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Int32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_6" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": [ "null", { "type": "record", "name": "DoubleDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.DoubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.DoubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": [ "null", "org.github.microsoft.opc.publisher.DoubleDataValue" ] } ] }, { "type": "record", "name": "DataSet1", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/NetworkMessageDefault/SimpleEvents.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "EventId", "type": [ "null", { "type": "record", "name": "ByteStringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] } ] }, { "name": "StatusCode", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "SourceTimestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "SourcePicoseconds", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "Message", "type": [ "null", { "type": "record", "name": "LocalizedTextDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "Text", "type": "String" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CycleId", "type": [ "null", { "type": "record", "name": "StringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.String" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CurrentStep", "type": [ "null", { "type": "record", "name": "CycleStepDataTypeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "CycleStepDataType", "namespace": "org.opcfoundation.SimpleEvents", "aliases": [ "org.opcfoundation.SimpleEvents.i_x95_183" ], "fields": [ { "name": "Name", "type": "org.opcfoundation.UA.String" }, { "name": "Duration", "type": { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] } } ], "uaDataTypeId": "nsu=http://opcfoundation.org/SimpleEvents;i=183" } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/Raw/CyclicReads.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "i_x61_2258", "type": [ "null", { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": [ "null", { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": [ "null", { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": [ "null", { "type": "record", "name": "Int32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_6" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": [ "null", { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": [ "null", "org.opcfoundation.UA.Double" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": [ "null", "org.opcfoundation.UA.Double" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": [ "null", "org.opcfoundation.UA.Double" ] }, { "name": "ns_x61_23_x59_i_x61_1259", "type": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "Boolean", { "type": "record", "name": "SByte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_2" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Byte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_3" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Int16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_4" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] }, "Int32", "UInt32", { "type": "record", "name": "Int64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_8" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "UInt64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": [ "int", { "type": "fixed", "name": "ulong", "namespace": "org.opcfoundation.UA", "size": 8 } ] } ] }, { "type": "record", "name": "Float", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_10" ], "fields": [ { "name": "Value", "type": "float" } ] }, "Double", { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] }, "DateTime", { "type": "record", "name": "Guid", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14" ], "fields": [ { "name": "Value", "type": { "type": "string", "logicalType": "uuid" } } ] }, { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] }, { "type": "record", "name": "XmlElement", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_16" ], "fields": [ { "name": "Value", "type": "string" } ] }, { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] }, { "name": "ServerUri", "type": "String" } ] }, { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] }, { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Name", "type": "String" } ] }, { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "String" }, { "name": "Text", "type": "String" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "Value", "type": [ { "type": "record", "name": "EncodedDataType", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Body", "type": "ByteString" } ] } ] } ] }, { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": "Variant" }, { "name": "StatusCode", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "DateTime" }, { "name": "SourcePicoseconds", "type": "UInt16" }, { "name": "ServerTimestamp", "type": "DateTime" }, { "name": "ServerPicoseconds", "type": "UInt16" } ] }, { "type": "record", "name": "Enumeration", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_29" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "BooleanCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "Int16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] }, { "type": "record", "name": "BooleanMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "ByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Byte" } } ] }, { "type": "record", "name": "Int16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] } ] } ] } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/Raw/KeepAlive.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "State", "type": [ "null", { "type": "enum", "name": "ServerState", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_852" ], "symbols": [ "Running", "Failed", "NoConfiguration", "Suspended", "Shutdown", "Test", "CommunicationFault", "Unknown" ], "default": "Running", "uaDataTypeId": "i=852" } ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/Raw/KeyFrames.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "CurrentTime", "type": [ "null", { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } ] }, { "name": "EngineeringUnits", "type": [ "null", { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } ] }, { "name": "AssetId", "type": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] }, { "type": "record", "name": "SByte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_2" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Byte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_3" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Int16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_4" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Int32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_6" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Int64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_8" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "UInt64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": [ "int", { "type": "fixed", "name": "ulong", "namespace": "org.opcfoundation.UA", "size": 8 } ] } ] }, { "type": "record", "name": "Float", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_10" ], "fields": [ { "name": "Value", "type": "float" } ] }, { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] }, "String", "DateTime", { "type": "record", "name": "Guid", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14" ], "fields": [ { "name": "Value", "type": { "type": "string", "logicalType": "uuid" } } ] }, { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] }, { "type": "record", "name": "XmlElement", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_16" ], "fields": [ { "name": "Value", "type": "string" } ] }, { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] }, { "name": "ServerUri", "type": "String" } ] }, { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] }, { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Name", "type": "String" } ] }, { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "String" }, { "name": "Text", "type": "String" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "Value", "type": [ { "type": "record", "name": "EncodedDataType", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Body", "type": "ByteString" } ] } ] } ] }, { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": "Variant" }, { "name": "StatusCode", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "DateTime" }, { "name": "SourcePicoseconds", "type": "UInt16" }, { "name": "ServerTimestamp", "type": "DateTime" }, { "name": "ServerPicoseconds", "type": "UInt16" } ] }, { "type": "record", "name": "Enumeration", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_29" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "BooleanCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "Int16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] }, { "type": "record", "name": "BooleanMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "ByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Byte" } } ] }, { "type": "record", "name": "Int16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] } ] } ] } }, { "name": "Important", "type": [ "null", "org.opcfoundation.UA.Boolean" ] }, { "name": "Variance", "type": [ "null", "org.opcfoundation.UA.Float" ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/Raw/PendingAlarms.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "ConditionClassId", "type": [ "null", { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "Namespace", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "Identifier", "type": [ { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] }, "String", { "type": "record", "name": "Guid", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14" ], "fields": [ { "name": "Value", "type": { "type": "string", "logicalType": "uuid" } } ] }, { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] } ] } ] } ] }, { "name": "ConditionClassName", "type": [ "null", { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "String" }, { "name": "Text", "type": "String" } ] } ] }, { "name": "ConditionSubClassId", "type": [ "null", { "type": "record", "name": "NodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] } ] }, { "name": "ConditionSubClassName", "type": [ "null", { "type": "record", "name": "LocalizedTextCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] } ] }, { "name": "EventId", "type": [ "null", "org.opcfoundation.UA.ByteString" ] }, { "name": "EventType", "type": [ "null", "org.opcfoundation.UA.NodeId" ] }, { "name": "LocalTime", "type": [ "null", { "type": "record", "name": "TimeZoneDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_8912" ], "fields": [ { "name": "Offset", "type": { "type": "record", "name": "Int16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_4" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "DaylightSavingInOffset", "type": { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] } } ], "uaDataTypeId": "i=8912" } ] }, { "name": "Message", "type": [ "null", "org.opcfoundation.UA.LocalizedText" ] }, { "name": "ReceiveTime", "type": [ "null", { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } ] }, { "name": "Severity", "type": [ "null", { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "SourceName", "type": [ "null", "org.opcfoundation.UA.String" ] }, { "name": "SourceNode", "type": [ "null", "org.opcfoundation.UA.NodeId" ] }, { "name": "Time", "type": [ "null", "org.opcfoundation.UA.DateTime" ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/Raw/PlcSimulation.json ================================================ [ { "type": "record", "name": "DataSet", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": [ "null", { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": [ "null", { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": [ "null", { "type": "record", "name": "Int32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_6" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": [ "null", { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": [ "null", "org.opcfoundation.UA.Double" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": [ "null", "org.opcfoundation.UA.Double" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": [ "null", "org.opcfoundation.UA.Double" ] } ] }, { "type": "record", "name": "DataSet1", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": [ "null", "org.opcfoundation.UA.UInt32" ] } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/Raw/SimpleEvents.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "EventId", "type": [ "null", { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] } ] }, { "name": "Message", "type": [ "null", { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "Text", "type": "String" } ] } ] }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CycleId", "type": [ "null", "org.opcfoundation.UA.String" ] }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CurrentStep", "type": [ "null", { "type": "record", "name": "CycleStepDataType", "namespace": "org.opcfoundation.SimpleEvents", "aliases": [ "org.opcfoundation.SimpleEvents.i_x95_183" ], "fields": [ { "name": "Name", "type": "org.opcfoundation.UA.String" }, { "name": "Duration", "type": { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] } } ], "uaDataTypeId": "nsu=http://opcfoundation.org/SimpleEvents;i=183" } ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/RawReversible/CyclicReads.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "i_x61_2258", "type": [ "null", { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": [ "null", { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": [ "null", { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": [ "null", { "type": "record", "name": "Int32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_6" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": [ "null", { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": [ "null", "org.opcfoundation.UA.Double" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": [ "null", "org.opcfoundation.UA.Double" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": [ "null", "org.opcfoundation.UA.Double" ] }, { "name": "ns_x61_23_x59_i_x61_1259", "type": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "Boolean", { "type": "record", "name": "SByte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_2" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Byte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_3" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Int16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_4" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] }, "Int32", "UInt32", { "type": "record", "name": "Int64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_8" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "UInt64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": [ "int", { "type": "fixed", "name": "ulong", "namespace": "org.opcfoundation.UA", "size": 8 } ] } ] }, { "type": "record", "name": "Float", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_10" ], "fields": [ { "name": "Value", "type": "float" } ] }, "Double", { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] }, "DateTime", { "type": "record", "name": "Guid", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14" ], "fields": [ { "name": "Value", "type": { "type": "string", "logicalType": "uuid" } } ] }, { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] }, { "type": "record", "name": "XmlElement", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_16" ], "fields": [ { "name": "Value", "type": "string" } ] }, { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] }, { "name": "ServerUri", "type": "String" } ] }, { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] }, { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Name", "type": "String" } ] }, { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "String" }, { "name": "Text", "type": "String" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "Value", "type": [ { "type": "record", "name": "EncodedDataType", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Body", "type": "ByteString" } ] } ] } ] }, { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": "Variant" }, { "name": "StatusCode", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "DateTime" }, { "name": "SourcePicoseconds", "type": "UInt16" }, { "name": "ServerTimestamp", "type": "DateTime" }, { "name": "ServerPicoseconds", "type": "UInt16" } ] }, { "type": "record", "name": "Enumeration", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_29" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "BooleanCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "Int16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] }, { "type": "record", "name": "BooleanMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "ByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Byte" } } ] }, { "type": "record", "name": "Int16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] } ] } ] } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/RawReversible/KeepAlive.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "State", "type": [ "null", { "type": "enum", "name": "ServerState", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_852" ], "symbols": [ "Running", "Failed", "NoConfiguration", "Suspended", "Shutdown", "Test", "CommunicationFault", "Unknown" ], "default": "Running", "uaDataTypeId": "i=852" } ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/RawReversible/KeyFrames.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "CurrentTime", "type": [ "null", { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } ] }, { "name": "EngineeringUnits", "type": [ "null", { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } ] }, { "name": "AssetId", "type": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] }, { "type": "record", "name": "SByte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_2" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Byte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_3" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Int16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_4" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Int32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_6" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Int64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_8" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "UInt64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": [ "int", { "type": "fixed", "name": "ulong", "namespace": "org.opcfoundation.UA", "size": 8 } ] } ] }, { "type": "record", "name": "Float", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_10" ], "fields": [ { "name": "Value", "type": "float" } ] }, { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] }, "String", "DateTime", { "type": "record", "name": "Guid", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14" ], "fields": [ { "name": "Value", "type": { "type": "string", "logicalType": "uuid" } } ] }, { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] }, { "type": "record", "name": "XmlElement", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_16" ], "fields": [ { "name": "Value", "type": "string" } ] }, { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] }, { "name": "ServerUri", "type": "String" } ] }, { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] }, { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Name", "type": "String" } ] }, { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "String" }, { "name": "Text", "type": "String" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "Value", "type": [ { "type": "record", "name": "EncodedDataType", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Body", "type": "ByteString" } ] } ] } ] }, { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": "Variant" }, { "name": "StatusCode", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "DateTime" }, { "name": "SourcePicoseconds", "type": "UInt16" }, { "name": "ServerTimestamp", "type": "DateTime" }, { "name": "ServerPicoseconds", "type": "UInt16" } ] }, { "type": "record", "name": "Enumeration", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_29" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "BooleanCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "Int16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] }, { "type": "record", "name": "BooleanMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "ByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Byte" } } ] }, { "type": "record", "name": "Int16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] } ] } ] } }, { "name": "Important", "type": [ "null", "org.opcfoundation.UA.Boolean" ] }, { "name": "Variance", "type": [ "null", "org.opcfoundation.UA.Float" ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/RawReversible/PendingAlarms.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "ConditionClassId", "type": [ "null", { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "Namespace", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "Identifier", "type": [ { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] }, "String", { "type": "record", "name": "Guid", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14" ], "fields": [ { "name": "Value", "type": { "type": "string", "logicalType": "uuid" } } ] }, { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] } ] } ] } ] }, { "name": "ConditionClassName", "type": [ "null", { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "String" }, { "name": "Text", "type": "String" } ] } ] }, { "name": "ConditionSubClassId", "type": [ "null", { "type": "record", "name": "NodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] } ] }, { "name": "ConditionSubClassName", "type": [ "null", { "type": "record", "name": "LocalizedTextCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] } ] }, { "name": "EventId", "type": [ "null", "org.opcfoundation.UA.ByteString" ] }, { "name": "EventType", "type": [ "null", "org.opcfoundation.UA.NodeId" ] }, { "name": "LocalTime", "type": [ "null", { "type": "record", "name": "TimeZoneDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_8912" ], "fields": [ { "name": "Offset", "type": { "type": "record", "name": "Int16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_4" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "DaylightSavingInOffset", "type": { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] } } ], "uaDataTypeId": "i=8912" } ] }, { "name": "Message", "type": [ "null", "org.opcfoundation.UA.LocalizedText" ] }, { "name": "ReceiveTime", "type": [ "null", { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } ] }, { "name": "Severity", "type": [ "null", { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "SourceName", "type": [ "null", "org.opcfoundation.UA.String" ] }, { "name": "SourceNode", "type": [ "null", "org.opcfoundation.UA.NodeId" ] }, { "name": "Time", "type": [ "null", "org.opcfoundation.UA.DateTime" ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/RawReversible/PlcSimulation.json ================================================ [ { "type": "record", "name": "DataSet", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": [ "null", { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": [ "null", { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": [ "null", { "type": "record", "name": "Int32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_6" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": [ "null", { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": [ "null", "org.opcfoundation.UA.Double" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": [ "null", "org.opcfoundation.UA.Double" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": [ "null", "org.opcfoundation.UA.Double" ] } ] }, { "type": "record", "name": "DataSet1", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": [ "null", "org.opcfoundation.UA.UInt32" ] } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/RawReversible/SimpleEvents.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "EventId", "type": [ "null", { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] } ] }, { "name": "Message", "type": [ "null", { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "Text", "type": "String" } ] } ] }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CycleId", "type": [ "null", "org.opcfoundation.UA.String" ] }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CurrentStep", "type": [ "null", { "type": "record", "name": "CycleStepDataType", "namespace": "org.opcfoundation.SimpleEvents", "aliases": [ "org.opcfoundation.SimpleEvents.i_x95_183" ], "fields": [ { "name": "Name", "type": "org.opcfoundation.UA.String" }, { "name": "Duration", "type": { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] } } ], "uaDataTypeId": "nsu=http://opcfoundation.org/SimpleEvents;i=183" } ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/Single/CyclicReads.json ================================================ { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageType", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "DataSetWriterName", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetWriterId", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "SequenceNumber", "type": { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "MetaDataVersion", "type": { "type": "record", "name": "ConfigurationVersionDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14593" ], "fields": [ { "name": "MajorVersion", "type": "UInt32" }, { "name": "MinorVersion", "type": "UInt32" } ] } }, { "name": "Timestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "i_x61_2258", "type": [ "null", { "type": "record", "name": "DateTimeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.DateTime" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": [ "null", { "type": "record", "name": "UInt32DataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": [ "null", { "type": "record", "name": "BooleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": [ "null", { "type": "record", "name": "Int32DataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Int32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_6" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": [ "null", { "type": "record", "name": "DoubleDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.DoubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.DoubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": [ "null", "org.github.microsoft.opc.publisher.DoubleDataValue" ] }, { "name": "ns_x61_23_x59_i_x61_1259", "type": [ "null", { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "Boolean", { "type": "record", "name": "SByte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_2" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Byte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_3" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Int16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_4" ], "fields": [ { "name": "Value", "type": "int" } ] }, "UInt16", "Int32", "UInt32", { "type": "record", "name": "Int64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_8" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "UInt64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": [ "int", { "type": "fixed", "name": "ulong", "namespace": "org.opcfoundation.UA", "size": 8 } ] } ] }, { "type": "record", "name": "Float", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_10" ], "fields": [ { "name": "Value", "type": "float" } ] }, "Double", "String", "DateTime", { "type": "record", "name": "Guid", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14" ], "fields": [ { "name": "Value", "type": { "type": "string", "logicalType": "uuid" } } ] }, { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] }, { "type": "record", "name": "XmlElement", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_16" ], "fields": [ { "name": "Value", "type": "string" } ] }, { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] }, { "name": "ServerUri", "type": "String" } ] }, "StatusCode", { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Name", "type": "String" } ] }, { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "String" }, { "name": "Text", "type": "String" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "Value", "type": [ { "type": "record", "name": "EncodedDataType", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Body", "type": "ByteString" } ] } ] } ] }, "DataValue", { "type": "record", "name": "Enumeration", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_29" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "BooleanCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "Int16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] }, { "type": "record", "name": "BooleanMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "ByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Byte" } } ] }, { "type": "record", "name": "Int16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] } ] } ] } }, { "name": "StatusCode", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "DateTime" }, { "name": "SourcePicoseconds", "type": "UInt16" }, { "name": "ServerTimestamp", "type": "DateTime" }, { "name": "ServerPicoseconds", "type": "UInt16" } ] } ] } ] } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/Single/KeepAlive.json ================================================ { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageType", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "DataSetWriterName", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetWriterId", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "SequenceNumber", "type": { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "MetaDataVersion", "type": { "type": "record", "name": "ConfigurationVersionDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14593" ], "fields": [ { "name": "MajorVersion", "type": "UInt32" }, { "name": "MinorVersion", "type": "UInt32" } ] } }, { "name": "Timestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "State", "type": [ "null", { "type": "record", "name": "ServerStateDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "enum", "name": "ServerState", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_852" ], "symbols": [ "Running", "Failed", "NoConfiguration", "Suspended", "Shutdown", "Test", "CommunicationFault", "Unknown" ], "default": "Running", "uaDataTypeId": "i=852" } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] } ] } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/Single/KeyFrames.json ================================================ { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageType", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "DataSetWriterName", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetWriterId", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "SequenceNumber", "type": { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "MetaDataVersion", "type": { "type": "record", "name": "ConfigurationVersionDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14593" ], "fields": [ { "name": "MajorVersion", "type": "UInt32" }, { "name": "MinorVersion", "type": "UInt32" } ] } }, { "name": "Timestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "CurrentTime", "type": [ "null", { "type": "record", "name": "DateTimeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.DateTime" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "EngineeringUnits", "type": [ "null", { "type": "record", "name": "StringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.String" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "AssetId", "type": [ "null", { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] }, { "type": "record", "name": "SByte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_2" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Byte", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_3" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "Int16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_4" ], "fields": [ { "name": "Value", "type": "int" } ] }, "UInt16", { "type": "record", "name": "Int32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_6" ], "fields": [ { "name": "Value", "type": "int" } ] }, "UInt32", { "type": "record", "name": "Int64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_8" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "UInt64", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": [ "int", { "type": "fixed", "name": "ulong", "namespace": "org.opcfoundation.UA", "size": 8 } ] } ] }, { "type": "record", "name": "Float", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_10" ], "fields": [ { "name": "Value", "type": "float" } ] }, { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] }, "String", "DateTime", { "type": "record", "name": "Guid", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14" ], "fields": [ { "name": "Value", "type": { "type": "string", "logicalType": "uuid" } } ] }, { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] }, { "type": "record", "name": "XmlElement", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_16" ], "fields": [ { "name": "Value", "type": "string" } ] }, { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", "Guid", "ByteString" ] }, { "name": "ServerUri", "type": "String" } ] }, "StatusCode", { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Name", "type": "String" } ] }, { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "String" }, { "name": "Text", "type": "String" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "Value", "type": [ { "type": "record", "name": "EncodedDataType", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Body", "type": "ByteString" } ] } ] } ] }, "DataValue", { "type": "record", "name": "Enumeration", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_29" ], "fields": [ { "name": "Value", "type": "int" } ] }, { "type": "record", "name": "BooleanCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "Int16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Collection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] }, { "type": "record", "name": "BooleanMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Boolean" } } ] }, { "type": "record", "name": "SByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "SByte" } } ] }, { "type": "record", "name": "ByteMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Byte" } } ] }, { "type": "record", "name": "Int16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int16" } } ] }, { "type": "record", "name": "UInt16Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt16" } } ] }, { "type": "record", "name": "Int32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int32" } } ] }, { "type": "record", "name": "UInt32Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt32" } } ] }, { "type": "record", "name": "Int64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Int64" } } ] }, { "type": "record", "name": "UInt64Matrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "UInt64" } } ] }, { "type": "record", "name": "FloatMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Float" } } ] }, { "type": "record", "name": "DoubleMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Double" } } ] }, { "type": "record", "name": "StringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "String" } } ] }, { "type": "record", "name": "DateTimeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DateTime" } } ] }, { "type": "record", "name": "GuidMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Guid" } } ] }, { "type": "record", "name": "ByteStringMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ByteString" } } ] }, { "type": "record", "name": "XmlElementMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "XmlElement" } } ] }, { "type": "record", "name": "NodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] }, { "type": "record", "name": "ExpandedNodeIdMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExpandedNodeId" } } ] }, { "type": "record", "name": "StatusCodeMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "StatusCode" } } ] }, { "type": "record", "name": "QualifiedNameMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "QualifiedName" } } ] }, { "type": "record", "name": "LocalizedTextMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] }, { "type": "record", "name": "ExtensionObjectMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "ExtensionObject" } } ] }, { "type": "record", "name": "DataValueMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "DataValue" } } ] }, { "type": "record", "name": "VariantMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Variant" } } ] }, { "type": "record", "name": "EnumerationMatrix", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Dimensions", "type": "Int32Collection" }, { "name": "Value", "type": { "type": "array", "items": "Enumeration" } } ] } ] } ] } }, { "name": "StatusCode", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "DateTime" }, { "name": "SourcePicoseconds", "type": "UInt16" }, { "name": "ServerTimestamp", "type": "DateTime" }, { "name": "ServerPicoseconds", "type": "UInt16" } ] } ] }, { "name": "Important", "type": [ "null", { "type": "record", "name": "BooleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.Boolean" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "Variance", "type": [ "null", { "type": "record", "name": "FloatDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.Float" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] } ] } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/Single/PendingAlarms.json ================================================ { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageType", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "DataSetWriterName", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetWriterId", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "SequenceNumber", "type": { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "MetaDataVersion", "type": { "type": "record", "name": "ConfigurationVersionDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14593" ], "fields": [ { "name": "MajorVersion", "type": "UInt32" }, { "name": "MinorVersion", "type": "UInt32" } ] } }, { "name": "Timestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "ConditionClassId", "type": [ "null", { "type": "record", "name": "NodeIdDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "Namespace", "type": "String" }, { "name": "Identifier", "type": [ "UInt32", "String", { "type": "record", "name": "Guid", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14" ], "fields": [ { "name": "Value", "type": { "type": "string", "logicalType": "uuid" } } ] }, { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] } ] } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "ConditionClassName", "type": [ "null", { "type": "record", "name": "LocalizedTextDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "String" }, { "name": "Text", "type": "String" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "ConditionSubClassId", "type": [ "null", { "type": "record", "name": "NodeIdCollectionDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "NodeIdCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "NodeId" } } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "ConditionSubClassName", "type": [ "null", { "type": "record", "name": "LocalizedTextCollectionDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "LocalizedTextCollection", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Value", "type": { "type": "array", "items": "LocalizedText" } } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "EventId", "type": [ "null", { "type": "record", "name": "ByteStringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.ByteString" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "EventType", "type": [ "null", "org.github.microsoft.opc.publisher.NodeIdDataValue" ] }, { "name": "LocalTime", "type": [ "null", { "type": "record", "name": "TimeZoneDataTypeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "TimeZoneDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_8912" ], "fields": [ { "name": "Offset", "type": { "type": "record", "name": "Int16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_4" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "DaylightSavingInOffset", "type": { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] } } ], "uaDataTypeId": "i=8912" } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "Message", "type": [ "null", "org.github.microsoft.opc.publisher.LocalizedTextDataValue" ] }, { "name": "ReceiveTime", "type": [ "null", { "type": "record", "name": "DateTimeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.DateTime" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "Severity", "type": [ "null", { "type": "record", "name": "UInt16DataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.UInt16" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "SourceName", "type": [ "null", { "type": "record", "name": "StringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.String" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "SourceNode", "type": [ "null", "org.github.microsoft.opc.publisher.NodeIdDataValue" ] }, { "name": "Time", "type": [ "null", "org.github.microsoft.opc.publisher.DateTimeDataValue" ] } ] } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/Single/PlcSimulation.json ================================================ [ { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageType", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "DataSetWriterName", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetWriterId", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "SequenceNumber", "type": { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "MetaDataVersion", "type": { "type": "record", "name": "ConfigurationVersionDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14593" ], "fields": [ { "name": "MajorVersion", "type": "UInt32" }, { "name": "MinorVersion", "type": "UInt32" } ] } }, { "name": "Timestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": [ "null", { "type": "record", "name": "UInt32DataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.UInt32" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": [ "null", { "type": "record", "name": "BooleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Boolean", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_1" ], "fields": [ { "name": "Value", "type": "boolean" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": [ "null", { "type": "record", "name": "Int32DataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Int32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_6" ], "fields": [ { "name": "Value", "type": "int" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": [ "null", { "type": "record", "name": "DoubleDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.DoubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.DoubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": [ "null", "org.github.microsoft.opc.publisher.DoubleDataValue" ] } ] } } ] }, { "type": "record", "name": "DataSetMessage1", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageType", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetWriterName", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetWriterId", "type": "org.opcfoundation.UA.UInt16" }, { "name": "SequenceNumber", "type": "org.opcfoundation.UA.UInt32" }, { "name": "MetaDataVersion", "type": "org.opcfoundation.UA.ConfigurationVersionDataType" }, { "name": "Timestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "Payload", "type": { "type": "record", "name": "DataSet1", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.UInt32DataValue" ] } ] } } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/AvroSchema/Single/SimpleEvents.json ================================================ { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageType", "type": { "type": "record", "name": "String", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_12" ], "fields": [ { "name": "Value", "type": "string" } ] } }, { "name": "DataSetWriterName", "type": "org.opcfoundation.UA.String" }, { "name": "DataSetWriterId", "type": { "type": "record", "name": "UInt16", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_5" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "SequenceNumber", "type": { "type": "record", "name": "UInt32", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_7" ], "fields": [ { "name": "Value", "type": "int" } ] } }, { "name": "MetaDataVersion", "type": { "type": "record", "name": "ConfigurationVersionDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14593" ], "fields": [ { "name": "MajorVersion", "type": "UInt32" }, { "name": "MinorVersion", "type": "UInt32" } ] } }, { "name": "Timestamp", "type": { "type": "record", "name": "DateTime", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_13" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_19" ], "fields": [ { "name": "Value", "type": "long" } ] } }, { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "EventId", "type": [ "null", { "type": "record", "name": "ByteStringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "ByteString", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_15" ], "fields": [ { "name": "Value", "type": "bytes" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "Message", "type": [ "null", { "type": "record", "name": "LocalizedTextDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "String" }, { "name": "Text", "type": "String" } ] } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CycleId", "type": [ "null", { "type": "record", "name": "StringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", "org.opcfoundation.UA.String" ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CurrentStep", "type": [ "null", { "type": "record", "name": "CycleStepDataTypeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": [ "null", { "type": "record", "name": "CycleStepDataType", "namespace": "org.opcfoundation.SimpleEvents", "aliases": [ "org.opcfoundation.SimpleEvents.i_x95_183" ], "fields": [ { "name": "Name", "type": "org.opcfoundation.UA.String" }, { "name": "Duration", "type": { "type": "record", "name": "Double", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_11" ], "fields": [ { "name": "Value", "type": "double" } ] } } ], "uaDataTypeId": "nsu=http://opcfoundation.org/SimpleEvents;i=183" } ] }, { "name": "StatusCode", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "SourcePicoseconds", "type": "org.opcfoundation.UA.UInt16" }, { "name": "ServerTimestamp", "type": "org.opcfoundation.UA.DateTime" }, { "name": "ServerPicoseconds", "type": "org.opcfoundation.UA.UInt16" } ] } ] } ] } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Default/CyclicReads.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "i_x61_2258", "type": [ "null", { "type": "record", "name": "stringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "string" }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": [ "null", { "type": "record", "name": "intDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "int" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": [ "null", { "type": "record", "name": "booleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "boolean" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": [ "null", { "type": "record", "name": "doubleDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "double" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.doubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.doubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": [ "null", "org.github.microsoft.opc.publisher.doubleDataValue" ] }, { "name": "ns_x61_23_x59_i_x61_1259", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Default/KeepAlive.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "State", "type": [ "null", { "type": "record", "name": "ServerStateDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "enum", "name": "ServerState", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_852" ], "symbols": [ "Running", "Failed", "NoConfiguration", "Suspended", "Shutdown", "Test", "CommunicationFault", "Unknown" ], "default": "Running", "uaDataTypeId": "i=852" } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Default/KeyFrames.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "CurrentTime", "type": [ "null", { "type": "record", "name": "stringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "string" }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "EngineeringUnits", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] }, { "name": "AssetId", "type": [ "null", { "type": "record", "name": "VariantDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "boolean", "int", "string", "float", "double", "bytes", { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "string" } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "IdType", "type": "IdentifierType" }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": [ "int", "string" ] }, { "name": "ServerUri", "type": "string" } ] }, "StatusCode", { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Uri", "type": "string" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Encoding", "type": { "type": "enum", "name": "Encoding", "symbols": [ "Structure", "ByteString", "XmlElement" ] } }, { "name": "Body", "type": [ "null", "string", "bytes" ] } ] }, { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": "Variant" }, { "name": "Status", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoSeconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoSeconds", "type": "int" } ] }, { "type": "array", "items": "boolean" } ] } ] } }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "Important", "type": [ "null", { "type": "record", "name": "booleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "boolean" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "Variance", "type": [ "null", { "type": "record", "name": "floatDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "float" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Default/PendingAlarms.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "ConditionClassId", "type": [ "null", { "type": "record", "name": "NodeIdDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "string" } ] } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "ConditionClassName", "type": [ "null", { "type": "record", "name": "stringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "string" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "ConditionSubClassId", "type": [ "null", { "type": "record", "name": "arrayDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "array", "items": "org.opcfoundation.UA.NodeId" } }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "ConditionSubClassName", "type": [ "null", "org.github.microsoft.opc.publisher.arrayDataValue" ] }, { "name": "EventId", "type": [ "null", { "type": "record", "name": "bytesDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "bytes" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "EventType", "type": [ "null", "org.github.microsoft.opc.publisher.NodeIdDataValue" ] }, { "name": "LocalTime", "type": [ "null", { "type": "record", "name": "TimeZoneDataTypeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "record", "name": "TimeZoneDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_8912" ], "fields": [ { "name": "Offset", "type": "int" }, { "name": "DaylightSavingInOffset", "type": "boolean" } ], "uaDataTypeId": "i=8912" } }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "Message", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] }, { "name": "ReceiveTime", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] }, { "name": "Severity", "type": [ "null", { "type": "record", "name": "intDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "int" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SourceName", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] }, { "name": "SourceNode", "type": [ "null", "org.github.microsoft.opc.publisher.NodeIdDataValue" ] }, { "name": "Time", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Default/PlcSimulation.json ================================================ [ { "type": "record", "name": "DataSet", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": [ "null", { "type": "record", "name": "intDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "int" }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": [ "null", { "type": "record", "name": "booleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "boolean" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": [ "null", { "type": "record", "name": "doubleDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "double" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.doubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.doubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": [ "null", "org.github.microsoft.opc.publisher.doubleDataValue" ] } ] }, { "type": "record", "name": "DataSet1", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Default/SimpleEvents.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "EventId", "type": [ "null", { "type": "record", "name": "bytesDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "bytes" }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "Message", "type": [ "null", { "type": "record", "name": "stringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "string" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CycleId", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CurrentStep", "type": [ "null", { "type": "record", "name": "CycleStepDataTypeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "record", "name": "CycleStepDataType", "namespace": "org.opcfoundation.SimpleEvents", "aliases": [ "org.opcfoundation.SimpleEvents.i_x95_183" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Duration", "type": "double" } ], "uaDataTypeId": "nsu=http://opcfoundation.org/SimpleEvents;i=183" } }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Multiple/CyclicReads.json ================================================ { "type": "record", "name": "NetworkMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageId", "type": "string" }, { "name": "MessageType", "type": "string" }, { "name": "DataSetWriterGroup", "type": "string" }, { "name": "Messages", "type": { "type": "array", "items": { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "i_x61_2258", "type": [ "null", { "type": "record", "name": "stringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "string" }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": [ "null", { "type": "record", "name": "intDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "int" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": [ "null", { "type": "record", "name": "booleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "boolean" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": [ "null", { "type": "record", "name": "doubleDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "double" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.doubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.doubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": [ "null", "org.github.microsoft.opc.publisher.doubleDataValue" ] }, { "name": "ns_x61_23_x59_i_x61_1259", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] } ] } } ] } } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Multiple/KeepAlive.json ================================================ { "type": "record", "name": "NetworkMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageId", "type": "string" }, { "name": "MessageType", "type": "string" }, { "name": "DataSetWriterGroup", "type": "string" }, { "name": "Messages", "type": { "type": "array", "items": { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MetaDataVersion", "type": { "type": "record", "name": "ConfigurationVersionDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14593" ], "fields": [ { "name": "MajorVersion", "type": "int" }, { "name": "MinorVersion", "type": "int" } ] } }, { "name": "MessageType", "type": "string" }, { "name": "DataSetWriterName", "type": "string" }, { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "State", "type": [ "null", { "type": "record", "name": "ServerStateDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "enum", "name": "ServerState", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_852" ], "symbols": [ "Running", "Failed", "NoConfiguration", "Suspended", "Shutdown", "Test", "CommunicationFault", "Unknown" ], "default": "Running", "uaDataTypeId": "i=852" } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] } ] } } ] } } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Multiple/KeyFrames.json ================================================ { "type": "record", "name": "NetworkMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageId", "type": "string" }, { "name": "MessageType", "type": "string" }, { "name": "DataSetWriterGroup", "type": "string" }, { "name": "Messages", "type": { "type": "array", "items": { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MetaDataVersion", "type": { "type": "record", "name": "ConfigurationVersionDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14593" ], "fields": [ { "name": "MajorVersion", "type": "int" }, { "name": "MinorVersion", "type": "int" } ] } }, { "name": "MessageType", "type": "string" }, { "name": "DataSetWriterName", "type": "string" }, { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "CurrentTime", "type": [ "null", { "type": "record", "name": "stringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "string" }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "EngineeringUnits", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] }, { "name": "AssetId", "type": [ "null", { "type": "record", "name": "VariantDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "boolean", "int", "string", "float", "double", "bytes", { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "string" } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "IdType", "type": "IdentifierType" }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": [ "int", "string" ] }, { "name": "ServerUri", "type": "string" } ] }, "StatusCode", { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Uri", "type": "string" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Encoding", "type": { "type": "enum", "name": "Encoding", "symbols": [ "Structure", "ByteString", "XmlElement" ] } }, { "name": "Body", "type": [ "null", "string", "bytes" ] } ] }, { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": "Variant" }, { "name": "Status", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoSeconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoSeconds", "type": "int" } ] }, { "type": "array", "items": "boolean" } ] } ] } }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "Important", "type": [ "null", { "type": "record", "name": "booleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "boolean" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "Variance", "type": [ "null", { "type": "record", "name": "floatDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "float" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] } ] } } ] } } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Multiple/PendingAlarms.json ================================================ { "type": "record", "name": "NetworkMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageId", "type": "string" }, { "name": "MessageType", "type": "string" }, { "name": "DataSetWriterGroup", "type": "string" }, { "name": "Messages", "type": { "type": "array", "items": { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "ConditionClassId", "type": [ "null", { "type": "record", "name": "NodeIdDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "string" } ] } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "ConditionClassName", "type": [ "null", { "type": "record", "name": "stringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "string" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "ConditionSubClassId", "type": [ "null", { "type": "record", "name": "arrayDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "array", "items": "org.opcfoundation.UA.NodeId" } }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "ConditionSubClassName", "type": [ "null", "org.github.microsoft.opc.publisher.arrayDataValue" ] }, { "name": "EventId", "type": [ "null", { "type": "record", "name": "bytesDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "bytes" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "EventType", "type": [ "null", "org.github.microsoft.opc.publisher.NodeIdDataValue" ] }, { "name": "LocalTime", "type": [ "null", { "type": "record", "name": "TimeZoneDataTypeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "record", "name": "TimeZoneDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_8912" ], "fields": [ { "name": "Offset", "type": "int" }, { "name": "DaylightSavingInOffset", "type": "boolean" } ], "uaDataTypeId": "i=8912" } }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "Message", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] }, { "name": "ReceiveTime", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] }, { "name": "Severity", "type": [ "null", { "type": "record", "name": "intDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "int" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SourceName", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] }, { "name": "SourceNode", "type": [ "null", "org.github.microsoft.opc.publisher.NodeIdDataValue" ] }, { "name": "Time", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] } ] } } ] } } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Multiple/PlcSimulation.json ================================================ { "type": "record", "name": "NetworkMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageId", "type": "string" }, { "name": "MessageType", "type": "string" }, { "name": "DataSetWriterGroup", "type": "string" }, { "name": "Messages", "type": { "type": "array", "items": [ { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": [ "null", { "type": "record", "name": "intDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "int" }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": [ "null", { "type": "record", "name": "booleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "boolean" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": [ "null", { "type": "record", "name": "doubleDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "double" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.doubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.doubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": [ "null", "org.github.microsoft.opc.publisher.doubleDataValue" ] } ] } } ] }, { "type": "record", "name": "DataSetMessage1", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Payload", "type": { "type": "record", "name": "DataSet1", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] } ] } } ] } ] } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Multiple/SimpleEvents.json ================================================ { "type": "record", "name": "NetworkMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageId", "type": "string" }, { "name": "MessageType", "type": "string" }, { "name": "DataSetWriterGroup", "type": "string" }, { "name": "Messages", "type": { "type": "array", "items": { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "EventId", "type": [ "null", { "type": "record", "name": "bytesDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "bytes" }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "Message", "type": [ "null", { "type": "record", "name": "stringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "string" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CycleId", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CurrentStep", "type": [ "null", { "type": "record", "name": "CycleStepDataTypeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "record", "name": "CycleStepDataType", "namespace": "org.opcfoundation.SimpleEvents", "aliases": [ "org.opcfoundation.SimpleEvents.i_x95_183" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Duration", "type": "double" } ], "uaDataTypeId": "nsu=http://opcfoundation.org/SimpleEvents;i=183" } }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] } ] } } ] } } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/NetworkMessage/CyclicReads.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "i_x61_2258", "type": [ "null", { "type": "record", "name": "stringDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": "string" }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": [ "null", { "type": "record", "name": "intDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": "int" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": [ "null", { "type": "record", "name": "booleanDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": "boolean" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": [ "null", { "type": "record", "name": "doubleDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": "double" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": [ "null", "com.microsoft.doubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": [ "null", "com.microsoft.doubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": [ "null", "com.microsoft.doubleDataValue" ] }, { "name": "ns_x61_23_x59_i_x61_1259", "type": [ "null", "com.microsoft.stringDataValue" ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/NetworkMessage/KeepAlive.json ================================================ { "type": "record", "name": "NetworkMessage", "namespace": "com.microsoft", "fields": [ { "name": "MessageId", "type": "string" }, { "name": "MessageType", "type": "string" }, { "name": "PublisherId", "type": "string" }, { "name": "DataSetClassId", "type": { "type": "string", "logicalType": "uuid" } }, { "name": "DataSetWriterGroup", "type": "string" }, { "name": "Messages", "type": { "type": "array", "items": { "type": "record", "name": "DataSetMessage", "namespace": "com.microsoft", "fields": [ { "name": "MetaDataVersion", "type": { "type": "record", "name": "ConfigurationVersionDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14593" ], "fields": [ { "name": "MajorVersion", "type": "int" }, { "name": "MinorVersion", "type": "int" } ] } }, { "name": "MessageType", "type": "string" }, { "name": "DataSetWriterName", "type": "string" }, { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "State", "type": [ "null", { "type": "record", "name": "ServerStateDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": { "type": "enum", "name": "ServerState", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_852" ], "symbols": [ "Running", "Failed", "NoConfiguration", "Suspended", "Shutdown", "Test", "CommunicationFault", "Unknown" ], "default": "Running", "uaDataTypeId": "i=852" } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] } ] } } ] } } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/NetworkMessage/KeyFrames.json ================================================ { "type": "record", "name": "NetworkMessage", "namespace": "com.microsoft", "fields": [ { "name": "MessageId", "type": "string" }, { "name": "MessageType", "type": "string" }, { "name": "PublisherId", "type": "string" }, { "name": "DataSetClassId", "type": { "type": "string", "logicalType": "uuid" } }, { "name": "DataSetWriterGroup", "type": "string" }, { "name": "Messages", "type": { "type": "array", "items": { "type": "record", "name": "DataSetMessage", "namespace": "com.microsoft", "fields": [ { "name": "MetaDataVersion", "type": { "type": "record", "name": "ConfigurationVersionDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14593" ], "fields": [ { "name": "MajorVersion", "type": "int" }, { "name": "MinorVersion", "type": "int" } ] } }, { "name": "MessageType", "type": "string" }, { "name": "DataSetWriterName", "type": "string" }, { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "CurrentTime", "type": [ "null", { "type": "record", "name": "stringDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": "string" }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "EngineeringUnits", "type": [ "null", "com.microsoft.stringDataValue" ] }, { "name": "AssetId", "type": [ "null", { "type": "record", "name": "VariantDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "boolean", "int", "string", "float", "double", "bytes", { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "string" } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "IdType", "type": "IdentifierType" }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": [ "int", "string" ] }, { "name": "ServerUri", "type": "string" } ] }, "StatusCode", { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Uri", "type": "string" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Encoding", "type": { "type": "enum", "name": "Encoding", "symbols": [ "Structure", "ByteString", "XmlElement" ] } }, { "name": "Body", "type": [ "null", "string", "bytes" ] } ] }, { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": "Variant" }, { "name": "Status", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoSeconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoSeconds", "type": "int" } ] }, { "type": "array", "items": "boolean" } ] } ] } }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "Important", "type": [ "null", { "type": "record", "name": "booleanDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": "boolean" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "Variance", "type": [ "null", { "type": "record", "name": "floatDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": "float" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] } ] } } ] } } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/NetworkMessage/PendingAlarms.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "ConditionClassId", "type": [ "null", { "type": "record", "name": "NodeIdDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "string" } ] } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "ConditionClassName", "type": [ "null", { "type": "record", "name": "stringDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": "string" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "ConditionSubClassId", "type": [ "null", { "type": "record", "name": "arrayDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": { "type": "array", "items": "org.opcfoundation.UA.NodeId" } }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "ConditionSubClassName", "type": [ "null", "com.microsoft.arrayDataValue" ] }, { "name": "EventId", "type": [ "null", { "type": "record", "name": "bytesDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": "bytes" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "EventType", "type": [ "null", "com.microsoft.NodeIdDataValue" ] }, { "name": "LocalTime", "type": [ "null", { "type": "record", "name": "TimeZoneDataTypeDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": { "type": "record", "name": "TimeZoneDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_8912" ], "fields": [ { "name": "Offset", "type": "int" }, { "name": "DaylightSavingInOffset", "type": "boolean" } ], "uaDataTypeId": "i=8912" } }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "Message", "type": [ "null", "com.microsoft.stringDataValue" ] }, { "name": "ReceiveTime", "type": [ "null", "com.microsoft.stringDataValue" ] }, { "name": "Severity", "type": [ "null", { "type": "record", "name": "intDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": "int" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SourceName", "type": [ "null", "com.microsoft.stringDataValue" ] }, { "name": "SourceNode", "type": [ "null", "com.microsoft.NodeIdDataValue" ] }, { "name": "Time", "type": [ "null", "com.microsoft.stringDataValue" ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/NetworkMessage/PlcSimulation.json ================================================ [ { "type": "record", "name": "DataSet", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": [ "null", { "type": "record", "name": "intDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": "int" }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": [ "null", { "type": "record", "name": "booleanDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": "boolean" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": [ "null", { "type": "record", "name": "doubleDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": "double" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": [ "null", "com.microsoft.doubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": [ "null", "com.microsoft.doubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": [ "null", "com.microsoft.doubleDataValue" ] } ] }, { "type": "record", "name": "DataSet1", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": [ "null", "com.microsoft.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": [ "null", "com.microsoft.intDataValue" ] } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/NetworkMessage/SimpleEvents.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "EventId", "type": [ "null", { "type": "record", "name": "bytesDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": "bytes" }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "Message", "type": [ "null", { "type": "record", "name": "stringDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": "string" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CycleId", "type": [ "null", "com.microsoft.stringDataValue" ] }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CurrentStep", "type": [ "null", { "type": "record", "name": "CycleStepDataTypeDataValue", "namespace": "com.microsoft", "fields": [ { "name": "Value", "type": { "type": "record", "name": "CycleStepDataType", "namespace": "org.opcfoundation.SimpleEvents", "aliases": [ "org.opcfoundation.SimpleEvents.i_x95_183" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Duration", "type": "double" } ], "uaDataTypeId": "nsu=http://opcfoundation.org/SimpleEvents;i=183" } }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/NetworkMessageDefault/CyclicReads.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "i_x61_2258", "type": [ "null", { "type": "record", "name": "stringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "string" }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": [ "null", { "type": "record", "name": "intDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "int" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": [ "null", { "type": "record", "name": "booleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "boolean" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": [ "null", { "type": "record", "name": "doubleDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "double" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.doubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.doubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": [ "null", "org.github.microsoft.opc.publisher.doubleDataValue" ] }, { "name": "ns_x61_23_x59_i_x61_1259", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/NetworkMessageDefault/KeepAlive.json ================================================ { "type": "record", "name": "NetworkMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageId", "type": "string" }, { "name": "MessageType", "type": "string" }, { "name": "PublisherId", "type": "string" }, { "name": "DataSetClassId", "type": { "type": "string", "logicalType": "uuid" } }, { "name": "DataSetWriterGroup", "type": "string" }, { "name": "Messages", "type": { "type": "array", "items": { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MetaDataVersion", "type": { "type": "record", "name": "ConfigurationVersionDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14593" ], "fields": [ { "name": "MajorVersion", "type": "int" }, { "name": "MinorVersion", "type": "int" } ] } }, { "name": "MessageType", "type": "string" }, { "name": "DataSetWriterName", "type": "string" }, { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "State", "type": [ "null", { "type": "record", "name": "ServerStateDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "enum", "name": "ServerState", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_852" ], "symbols": [ "Running", "Failed", "NoConfiguration", "Suspended", "Shutdown", "Test", "CommunicationFault", "Unknown" ], "default": "Running", "uaDataTypeId": "i=852" } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] } ] } } ] } } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/NetworkMessageDefault/KeyFrames.json ================================================ { "type": "record", "name": "NetworkMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MessageId", "type": "string" }, { "name": "MessageType", "type": "string" }, { "name": "PublisherId", "type": "string" }, { "name": "DataSetClassId", "type": { "type": "string", "logicalType": "uuid" } }, { "name": "DataSetWriterGroup", "type": "string" }, { "name": "Messages", "type": { "type": "array", "items": { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MetaDataVersion", "type": { "type": "record", "name": "ConfigurationVersionDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14593" ], "fields": [ { "name": "MajorVersion", "type": "int" }, { "name": "MinorVersion", "type": "int" } ] } }, { "name": "MessageType", "type": "string" }, { "name": "DataSetWriterName", "type": "string" }, { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "CurrentTime", "type": [ "null", { "type": "record", "name": "stringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "string" }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "EngineeringUnits", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] }, { "name": "AssetId", "type": [ "null", { "type": "record", "name": "VariantDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "boolean", "int", "string", "float", "double", "bytes", { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "string" } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "IdType", "type": "IdentifierType" }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": [ "int", "string" ] }, { "name": "ServerUri", "type": "string" } ] }, "StatusCode", { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Uri", "type": "string" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Encoding", "type": { "type": "enum", "name": "Encoding", "symbols": [ "Structure", "ByteString", "XmlElement" ] } }, { "name": "Body", "type": [ "null", "string", "bytes" ] } ] }, { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": "Variant" }, { "name": "Status", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoSeconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoSeconds", "type": "int" } ] }, { "type": "array", "items": "boolean" } ] } ] } }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "Important", "type": [ "null", { "type": "record", "name": "booleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "boolean" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "Variance", "type": [ "null", { "type": "record", "name": "floatDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "float" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] } ] } } ] } } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/NetworkMessageDefault/PendingAlarms.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "ConditionClassId", "type": [ "null", { "type": "record", "name": "NodeIdDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "string" } ] } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "ConditionClassName", "type": [ "null", { "type": "record", "name": "stringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "string" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "ConditionSubClassId", "type": [ "null", { "type": "record", "name": "arrayDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "array", "items": "org.opcfoundation.UA.NodeId" } }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "ConditionSubClassName", "type": [ "null", "org.github.microsoft.opc.publisher.arrayDataValue" ] }, { "name": "EventId", "type": [ "null", { "type": "record", "name": "bytesDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "bytes" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "EventType", "type": [ "null", "org.github.microsoft.opc.publisher.NodeIdDataValue" ] }, { "name": "LocalTime", "type": [ "null", { "type": "record", "name": "TimeZoneDataTypeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "record", "name": "TimeZoneDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_8912" ], "fields": [ { "name": "Offset", "type": "int" }, { "name": "DaylightSavingInOffset", "type": "boolean" } ], "uaDataTypeId": "i=8912" } }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "Message", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] }, { "name": "ReceiveTime", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] }, { "name": "Severity", "type": [ "null", { "type": "record", "name": "intDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "int" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SourceName", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] }, { "name": "SourceNode", "type": [ "null", "org.github.microsoft.opc.publisher.NodeIdDataValue" ] }, { "name": "Time", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/NetworkMessageDefault/PlcSimulation.json ================================================ [ { "type": "record", "name": "DataSet", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": [ "null", { "type": "record", "name": "intDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "int" }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": [ "null", { "type": "record", "name": "booleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "boolean" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": [ "null", { "type": "record", "name": "doubleDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "double" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.doubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.doubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": [ "null", "org.github.microsoft.opc.publisher.doubleDataValue" ] } ] }, { "type": "record", "name": "DataSet1", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/NetworkMessageDefault/SimpleEvents.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "EventId", "type": [ "null", { "type": "record", "name": "bytesDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "bytes" }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "Message", "type": [ "null", { "type": "record", "name": "stringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "string" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CycleId", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CurrentStep", "type": [ "null", { "type": "record", "name": "CycleStepDataTypeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "record", "name": "CycleStepDataType", "namespace": "org.opcfoundation.SimpleEvents", "aliases": [ "org.opcfoundation.SimpleEvents.i_x95_183" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Duration", "type": "double" } ], "uaDataTypeId": "nsu=http://opcfoundation.org/SimpleEvents;i=183" } }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Raw/CyclicReads.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "i_x61_2258", "type": "string" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": "boolean" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": "double" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": "double" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": "double" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": "double" }, { "name": "ns_x61_23_x59_i_x61_1259", "type": "string" } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Raw/KeepAlive.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "State", "type": { "type": "enum", "name": "ServerState", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_852" ], "symbols": [ "Running", "Failed", "NoConfiguration", "Suspended", "Shutdown", "Test", "CommunicationFault", "Unknown" ], "default": "Running", "uaDataTypeId": "i=852" } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Raw/KeyFrames.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "CurrentTime", "type": "string" }, { "name": "EngineeringUnits", "type": "string" }, { "name": "AssetId", "type": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "boolean", "int", "string", "float", "double", "bytes", { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "string" } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "IdType", "type": "IdentifierType" }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": [ "int", "string" ] }, { "name": "ServerUri", "type": "string" } ] }, { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] }, { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Uri", "type": "string" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Encoding", "type": { "type": "enum", "name": "Encoding", "symbols": [ "Structure", "ByteString", "XmlElement" ] } }, { "name": "Body", "type": [ "null", "string", "bytes" ] } ] }, { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": "Variant" }, { "name": "Status", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoSeconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoSeconds", "type": "int" } ] }, { "type": "array", "items": "boolean" } ] } ] } }, { "name": "Important", "type": "boolean" }, { "name": "Variance", "type": "float" } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Raw/PendingAlarms.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "ConditionClassId", "type": { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "string" } ] } }, { "name": "ConditionClassName", "type": "string" }, { "name": "ConditionSubClassId", "type": { "type": "array", "items": "org.opcfoundation.UA.NodeId" } }, { "name": "ConditionSubClassName", "type": { "type": "array", "items": "string" } }, { "name": "EventId", "type": "bytes" }, { "name": "EventType", "type": "org.opcfoundation.UA.NodeId" }, { "name": "LocalTime", "type": { "type": "record", "name": "TimeZoneDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_8912" ], "fields": [ { "name": "Offset", "type": "int" }, { "name": "DaylightSavingInOffset", "type": "boolean" } ], "uaDataTypeId": "i=8912" } }, { "name": "Message", "type": "string" }, { "name": "ReceiveTime", "type": "string" }, { "name": "Severity", "type": "int" }, { "name": "SourceName", "type": "string" }, { "name": "SourceNode", "type": "org.opcfoundation.UA.NodeId" }, { "name": "Time", "type": "string" } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Raw/PlcSimulation.json ================================================ [ { "type": "record", "name": "DataSet", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": "boolean" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": "double" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": "double" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": "double" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": "double" } ] }, { "type": "record", "name": "DataSet1", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": "int" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Raw/SimpleEvents.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "EventId", "type": "bytes" }, { "name": "Message", "type": "string" }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CycleId", "type": "string" }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CurrentStep", "type": { "type": "record", "name": "CycleStepDataType", "namespace": "org.opcfoundation.SimpleEvents", "aliases": [ "org.opcfoundation.SimpleEvents.i_x95_183" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Duration", "type": "double" } ], "uaDataTypeId": "nsu=http://opcfoundation.org/SimpleEvents;i=183" } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/RawReversible/CyclicReads.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "i_x61_2258", "type": "string" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": "boolean" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": "double" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": "double" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": "double" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": "double" }, { "name": "ns_x61_23_x59_i_x61_1259", "type": "string" } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/RawReversible/KeepAlive.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "State", "type": { "type": "enum", "name": "ServerState", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_852" ], "symbols": [ "Running", "Failed", "NoConfiguration", "Suspended", "Shutdown", "Test", "CommunicationFault", "Unknown" ], "default": "Running", "uaDataTypeId": "i=852" } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/RawReversible/KeyFrames.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "CurrentTime", "type": "string" }, { "name": "EngineeringUnits", "type": "string" }, { "name": "AssetId", "type": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "boolean", "int", "string", "float", "double", "bytes", { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "int" } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "IdType", "type": "IdentifierType" }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": [ "int", "string" ] }, { "name": "ServerUri", "type": "int" } ] }, { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Uri", "type": "int" } ] }, { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "string" }, { "name": "Text", "type": "string" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Encoding", "type": { "type": "enum", "name": "Encoding", "symbols": [ "Structure", "ByteString", "XmlElement" ] } }, { "name": "Body", "type": [ "null", "string", "bytes" ] } ] }, { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": "Variant" }, { "name": "Status", "type": "int" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoSeconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoSeconds", "type": "int" } ] }, { "type": "array", "items": "boolean" } ] } ] } }, { "name": "Important", "type": "boolean" }, { "name": "Variance", "type": "float" } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/RawReversible/PendingAlarms.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "ConditionClassId", "type": { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "int" } ] } }, { "name": "ConditionClassName", "type": { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "string" }, { "name": "Text", "type": "string" } ] } }, { "name": "ConditionSubClassId", "type": { "type": "array", "items": "org.opcfoundation.UA.NodeId" } }, { "name": "ConditionSubClassName", "type": { "type": "array", "items": "org.opcfoundation.UA.LocalizedText" } }, { "name": "EventId", "type": "bytes" }, { "name": "EventType", "type": "org.opcfoundation.UA.NodeId" }, { "name": "LocalTime", "type": { "type": "record", "name": "TimeZoneDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_8912" ], "fields": [ { "name": "Offset", "type": "int" }, { "name": "DaylightSavingInOffset", "type": "boolean" } ], "uaDataTypeId": "i=8912" } }, { "name": "Message", "type": "org.opcfoundation.UA.LocalizedText" }, { "name": "ReceiveTime", "type": "string" }, { "name": "Severity", "type": "int" }, { "name": "SourceName", "type": "string" }, { "name": "SourceNode", "type": "org.opcfoundation.UA.NodeId" }, { "name": "Time", "type": "string" } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/RawReversible/PlcSimulation.json ================================================ [ { "type": "record", "name": "DataSet", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": "boolean" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": "double" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": "double" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": "double" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": "double" } ] }, { "type": "record", "name": "DataSet1", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": "int" }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": "int" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/RawReversible/SimpleEvents.json ================================================ { "type": "record", "name": "DataSet", "fields": [ { "name": "EventId", "type": "bytes" }, { "name": "Message", "type": { "type": "record", "name": "LocalizedText", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_21" ], "fields": [ { "name": "Locale", "type": "string" }, { "name": "Text", "type": "string" } ] } }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CycleId", "type": "string" }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CurrentStep", "type": { "type": "record", "name": "CycleStepDataType", "namespace": "org.opcfoundation.SimpleEvents", "aliases": [ "org.opcfoundation.SimpleEvents.i_x95_183" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Duration", "type": "double" } ], "uaDataTypeId": "nsu=http://opcfoundation.org/SimpleEvents;i=183" } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Samples/CyclicReads.json ================================================ [ { "type": "record", "name": "MonitoredItemMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", { "type": "record", "name": "stringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "string" }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "boolean", "int", "string", "float", "double", "bytes", { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "string" } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "IdType", "type": "IdentifierType" }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": [ "int", "string" ] }, { "name": "ServerUri", "type": "string" } ] }, "StatusCode", { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Uri", "type": "string" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Encoding", "type": { "type": "enum", "name": "Encoding", "symbols": [ "Structure", "ByteString", "XmlElement" ] } }, { "name": "Body", "type": [ "null", "string", "bytes" ] } ] }, { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": "Variant" }, { "name": "Status", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoSeconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoSeconds", "type": "int" } ] }, { "type": "array", "items": "boolean" } ] } ] } } ] } ] }, { "type": "record", "name": "MonitoredItemMessage1", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", { "type": "record", "name": "intDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "int" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage2", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", { "type": "record", "name": "booleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "boolean" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage3", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage4", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage5", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", { "type": "record", "name": "doubleDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "double" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage6", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage7", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage8", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage9", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage10", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage11", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage12", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "doubleDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage13", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "doubleDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage14", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage15", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage16", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage17", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage18", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage19", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage20", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage21", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage22", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "doubleDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage23", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "stringDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Samples/KeepAlive.json ================================================ [ { "type": "record", "name": "MonitoredItemMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", { "type": "record", "name": "ServerStateDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "enum", "name": "ServerState", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_852" ], "symbols": [ "Running", "Failed", "NoConfiguration", "Suspended", "Shutdown", "Test", "CommunicationFault", "Unknown" ], "default": "Running", "uaDataTypeId": "i=852" } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "boolean", "int", "string", "float", "double", "bytes", { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "string" } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "IdType", "type": "IdentifierType" }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": [ "int", "string" ] }, { "name": "ServerUri", "type": "string" } ] }, "StatusCode", { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Uri", "type": "string" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Encoding", "type": { "type": "enum", "name": "Encoding", "symbols": [ "Structure", "ByteString", "XmlElement" ] } }, { "name": "Body", "type": [ "null", "string", "bytes" ] } ] }, { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": "Variant" }, { "name": "Status", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoSeconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoSeconds", "type": "int" } ] }, { "type": "array", "items": "boolean" } ] } ] } } ] } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Samples/KeyFrames.json ================================================ [ { "type": "record", "name": "MonitoredItemMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", { "type": "record", "name": "stringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "string" }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "boolean", "int", "string", "float", "double", "bytes", { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "string" } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "IdType", "type": "IdentifierType" }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": [ "int", "string" ] }, { "name": "ServerUri", "type": "string" } ] }, "StatusCode", { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Uri", "type": "string" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Encoding", "type": { "type": "enum", "name": "Encoding", "symbols": [ "Structure", "ByteString", "XmlElement" ] } }, { "name": "Body", "type": [ "null", "string", "bytes" ] } ] }, { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": "Variant" }, { "name": "Status", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoSeconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoSeconds", "type": "int" } ] }, { "type": "array", "items": "boolean" } ] } ] } } ] } ] }, { "type": "record", "name": "MonitoredItemMessage1", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "stringDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage2", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", { "type": "record", "name": "VariantDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "org.opcfoundation.UA.Variant" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage3", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", { "type": "record", "name": "booleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "boolean" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage4", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", { "type": "record", "name": "floatDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "float" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Samples/PendingAlarms.json ================================================ [ { "type": "record", "name": "MonitoredItemMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", { "type": "record", "name": "NodeIdDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "string" } ] } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "boolean", "int", "string", "float", "double", "bytes", "NodeId", { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "IdType", "type": "IdentifierType" }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": [ "int", "string" ] }, { "name": "ServerUri", "type": "string" } ] }, "StatusCode", { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Uri", "type": "string" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Encoding", "type": { "type": "enum", "name": "Encoding", "symbols": [ "Structure", "ByteString", "XmlElement" ] } }, { "name": "Body", "type": [ "null", "string", "bytes" ] } ] }, { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": "Variant" }, { "name": "Status", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoSeconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoSeconds", "type": "int" } ] }, { "type": "array", "items": "boolean" } ] } ] } } ] } ] }, { "type": "record", "name": "MonitoredItemMessage1", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", { "type": "record", "name": "stringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "string" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage2", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", { "type": "record", "name": "arrayDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "array", "items": "org.opcfoundation.UA.NodeId" } }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage3", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "arrayDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage4", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", { "type": "record", "name": "bytesDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "bytes" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage5", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "NodeIdDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage6", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", { "type": "record", "name": "TimeZoneDataTypeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "record", "name": "TimeZoneDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_8912" ], "fields": [ { "name": "Offset", "type": "int" }, { "name": "DaylightSavingInOffset", "type": "boolean" } ], "uaDataTypeId": "i=8912" } }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage7", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "stringDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage8", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "stringDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage9", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", { "type": "record", "name": "intDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "int" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage10", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "stringDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage11", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "NodeIdDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage12", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "stringDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Samples/PlcSimulation.json ================================================ [ { "type": "record", "name": "MonitoredItemMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", { "type": "record", "name": "intDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "int" }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "boolean", "int", "string", "float", "double", "bytes", { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "string" } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "IdType", "type": "IdentifierType" }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": [ "int", "string" ] }, { "name": "ServerUri", "type": "string" } ] }, "StatusCode", { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Uri", "type": "string" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Encoding", "type": { "type": "enum", "name": "Encoding", "symbols": [ "Structure", "ByteString", "XmlElement" ] } }, { "name": "Body", "type": [ "null", "string", "bytes" ] } ] }, { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": "Variant" }, { "name": "Status", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoSeconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoSeconds", "type": "int" } ] }, { "type": "array", "items": "boolean" } ] } ] } } ] } ] }, { "type": "record", "name": "MonitoredItemMessage1", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", { "type": "record", "name": "booleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "boolean" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage2", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage3", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage4", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", { "type": "record", "name": "doubleDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "double" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage5", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage6", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage7", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage8", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage9", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage10", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage11", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "doubleDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage12", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "doubleDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage13", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "doubleDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage14", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage15", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage16", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage17", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage18", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage19", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage20", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage21", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "intDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Samples/SimpleEvents.json ================================================ [ { "type": "record", "name": "MonitoredItemMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", { "type": "record", "name": "bytesDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "bytes" }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "boolean", "int", "string", "float", "double", "bytes", { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "string" } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "IdType", "type": "IdentifierType" }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": [ "int", "string" ] }, { "name": "ServerUri", "type": "string" } ] }, "StatusCode", { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Uri", "type": "string" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Encoding", "type": { "type": "enum", "name": "Encoding", "symbols": [ "Structure", "ByteString", "XmlElement" ] } }, { "name": "Body", "type": [ "null", "string", "bytes" ] } ] }, { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": "Variant" }, { "name": "Status", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoSeconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoSeconds", "type": "int" } ] }, { "type": "array", "items": "boolean" } ] } ] } } ] } ] }, { "type": "record", "name": "MonitoredItemMessage1", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", { "type": "record", "name": "stringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "string" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage2", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", "stringDataValue" ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage3", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": [ "null", { "type": "record", "name": "CycleStepDataTypeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "record", "name": "CycleStepDataType", "namespace": "org.opcfoundation.SimpleEvents", "aliases": [ "org.opcfoundation.SimpleEvents.i_x95_183" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Duration", "type": "double" } ], "uaDataTypeId": "nsu=http://opcfoundation.org/SimpleEvents;i=183" } }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/SamplesRaw/CyclicReads.json ================================================ [ { "type": "record", "name": "MonitoredItemMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "string" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "boolean", "int", "string", "float", "double", "bytes", { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "string" } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "IdType", "type": "IdentifierType" }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": [ "int", "string" ] }, { "name": "ServerUri", "type": "string" } ] }, { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] }, { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Uri", "type": "string" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Encoding", "type": { "type": "enum", "name": "Encoding", "symbols": [ "Structure", "ByteString", "XmlElement" ] } }, { "name": "Body", "type": [ "null", "string", "bytes" ] } ] }, { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": "Variant" }, { "name": "Status", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoSeconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoSeconds", "type": "int" } ] }, { "type": "array", "items": "boolean" } ] } ] } } ] } ] }, { "type": "record", "name": "MonitoredItemMessage1", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage2", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "boolean" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage3", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage4", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage5", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "double" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage6", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage7", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage8", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage9", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage10", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage11", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage12", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "double" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage13", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "double" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage14", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage15", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage16", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage17", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage18", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage19", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage20", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage21", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage22", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "double" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage23", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "string" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/SamplesRaw/KeepAlive.json ================================================ [ { "type": "record", "name": "MonitoredItemMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": { "type": "enum", "name": "ServerState", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_852" ], "symbols": [ "Running", "Failed", "NoConfiguration", "Suspended", "Shutdown", "Test", "CommunicationFault", "Unknown" ], "default": "Running", "uaDataTypeId": "i=852" } }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "boolean", "int", "string", "float", "double", "bytes", { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "string" } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "IdType", "type": "IdentifierType" }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": [ "int", "string" ] }, { "name": "ServerUri", "type": "string" } ] }, { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] }, { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Uri", "type": "string" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Encoding", "type": { "type": "enum", "name": "Encoding", "symbols": [ "Structure", "ByteString", "XmlElement" ] } }, { "name": "Body", "type": [ "null", "string", "bytes" ] } ] }, { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": "Variant" }, { "name": "Status", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoSeconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoSeconds", "type": "int" } ] }, { "type": "array", "items": "boolean" } ] } ] } } ] } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/SamplesRaw/KeyFrames.json ================================================ [ { "type": "record", "name": "MonitoredItemMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "string" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "boolean", "int", "string", "float", "double", "bytes", { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "string" } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "IdType", "type": "IdentifierType" }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": [ "int", "string" ] }, { "name": "ServerUri", "type": "string" } ] }, { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] }, { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Uri", "type": "string" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Encoding", "type": { "type": "enum", "name": "Encoding", "symbols": [ "Structure", "ByteString", "XmlElement" ] } }, { "name": "Body", "type": [ "null", "string", "bytes" ] } ] }, { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": "Variant" }, { "name": "Status", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoSeconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoSeconds", "type": "int" } ] }, { "type": "array", "items": "boolean" } ] } ] } } ] } ] }, { "type": "record", "name": "MonitoredItemMessage1", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "string" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage2", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "org.opcfoundation.UA.Variant" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage3", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "boolean" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage4", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "float" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/SamplesRaw/PendingAlarms.json ================================================ [ { "type": "record", "name": "MonitoredItemMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "string" } ] } }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "boolean", "int", "string", "float", "double", "bytes", "NodeId", { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "IdType", "type": "IdentifierType" }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": [ "int", "string" ] }, { "name": "ServerUri", "type": "string" } ] }, { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] }, { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Uri", "type": "string" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Encoding", "type": { "type": "enum", "name": "Encoding", "symbols": [ "Structure", "ByteString", "XmlElement" ] } }, { "name": "Body", "type": [ "null", "string", "bytes" ] } ] }, { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": "Variant" }, { "name": "Status", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoSeconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoSeconds", "type": "int" } ] }, { "type": "array", "items": "boolean" } ] } ] } } ] } ] }, { "type": "record", "name": "MonitoredItemMessage1", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "string" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage2", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": { "type": "array", "items": "org.opcfoundation.UA.NodeId" } }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage3", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": { "type": "array", "items": "string" } }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage4", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "bytes" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage5", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "org.opcfoundation.UA.NodeId" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage6", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": { "type": "record", "name": "TimeZoneDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_8912" ], "fields": [ { "name": "Offset", "type": "int" }, { "name": "DaylightSavingInOffset", "type": "boolean" } ], "uaDataTypeId": "i=8912" } }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage7", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "string" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage8", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "string" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage9", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage10", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "string" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage11", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "org.opcfoundation.UA.NodeId" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage12", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "string" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/SamplesRaw/PlcSimulation.json ================================================ [ { "type": "record", "name": "MonitoredItemMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "boolean", "int", "string", "float", "double", "bytes", { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "string" } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "IdType", "type": "IdentifierType" }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": [ "int", "string" ] }, { "name": "ServerUri", "type": "string" } ] }, { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] }, { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Uri", "type": "string" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Encoding", "type": { "type": "enum", "name": "Encoding", "symbols": [ "Structure", "ByteString", "XmlElement" ] } }, { "name": "Body", "type": [ "null", "string", "bytes" ] } ] }, { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": "Variant" }, { "name": "Status", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoSeconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoSeconds", "type": "int" } ] }, { "type": "array", "items": "boolean" } ] } ] } } ] } ] }, { "type": "record", "name": "MonitoredItemMessage1", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "boolean" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage2", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage3", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage4", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "double" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage5", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage6", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage7", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage8", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage9", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage10", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage11", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "double" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage12", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "double" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage13", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "double" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage14", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage15", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage16", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage17", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage18", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage19", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage20", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage21", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "int" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/SamplesRaw/SimpleEvents.json ================================================ [ { "type": "record", "name": "MonitoredItemMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "bytes" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "boolean", "int", "string", "float", "double", "bytes", { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "string" } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "IdType", "type": "IdentifierType" }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": [ "int", "string" ] }, { "name": "ServerUri", "type": "string" } ] }, { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] }, { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Uri", "type": "string" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Encoding", "type": { "type": "enum", "name": "Encoding", "symbols": [ "Structure", "ByteString", "XmlElement" ] } }, { "name": "Body", "type": [ "null", "string", "bytes" ] } ] }, { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": "Variant" }, { "name": "Status", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoSeconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoSeconds", "type": "int" } ] }, { "type": "array", "items": "boolean" } ] } ] } } ] } ] }, { "type": "record", "name": "MonitoredItemMessage1", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "string" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage2", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": "string" }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] }, { "type": "record", "name": "MonitoredItemMessage3", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "NodeId", "type": [ "null", "string" ] }, { "name": "EndpointUrl", "type": [ "null", "string" ] }, { "name": "ApplicationUri", "type": [ "null", "string" ] }, { "name": "DisplayName", "type": [ "null", "string" ] }, { "name": "Timestamp", "type": [ "null", "string" ] }, { "name": "Value", "type": { "type": "record", "name": "CycleStepDataType", "namespace": "org.opcfoundation.SimpleEvents", "aliases": [ "org.opcfoundation.SimpleEvents.i_x95_183" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Duration", "type": "double" } ], "uaDataTypeId": "nsu=http://opcfoundation.org/SimpleEvents;i=183" } }, { "name": "SequenceNumber", "type": [ "null", "int" ] }, { "name": "ExtensionFields", "type": [ "null", { "type": "map", "values": "org.opcfoundation.UA.Variant" } ] } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Single/CyclicReads.json ================================================ { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "i_x61_2258", "type": [ "null", { "type": "record", "name": "stringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "string" }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": [ "null", { "type": "record", "name": "intDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "int" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": [ "null", { "type": "record", "name": "booleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "boolean" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": [ "null", { "type": "record", "name": "doubleDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "double" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.doubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.doubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": [ "null", "org.github.microsoft.opc.publisher.doubleDataValue" ] }, { "name": "ns_x61_23_x59_i_x61_1259", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] } ] } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Single/KeepAlive.json ================================================ { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MetaDataVersion", "type": { "type": "record", "name": "ConfigurationVersionDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14593" ], "fields": [ { "name": "MajorVersion", "type": "int" }, { "name": "MinorVersion", "type": "int" } ] } }, { "name": "MessageType", "type": "string" }, { "name": "DataSetWriterName", "type": "string" }, { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "State", "type": [ "null", { "type": "record", "name": "ServerStateDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "enum", "name": "ServerState", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_852" ], "symbols": [ "Running", "Failed", "NoConfiguration", "Suspended", "Shutdown", "Test", "CommunicationFault", "Unknown" ], "default": "Running", "uaDataTypeId": "i=852" } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] } ] } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Single/KeyFrames.json ================================================ { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "MetaDataVersion", "type": { "type": "record", "name": "ConfigurationVersionDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_14593" ], "fields": [ { "name": "MajorVersion", "type": "int" }, { "name": "MinorVersion", "type": "int" } ] } }, { "name": "MessageType", "type": "string" }, { "name": "DataSetWriterName", "type": "string" }, { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "CurrentTime", "type": [ "null", { "type": "record", "name": "stringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "string" }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "EngineeringUnits", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] }, { "name": "AssetId", "type": [ "null", { "type": "record", "name": "VariantDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "record", "name": "Variant", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_24" ], "fields": [ { "name": "Value", "type": [ "null", "boolean", "int", "string", "float", "double", "bytes", { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "string" } ] }, { "type": "record", "name": "ExpandedNodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_18" ], "fields": [ { "name": "IdType", "type": "IdentifierType" }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": [ "int", "string" ] }, { "name": "ServerUri", "type": "string" } ] }, "StatusCode", { "type": "record", "name": "QualifiedName", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_20" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Uri", "type": "string" } ] }, { "type": "record", "name": "ExtensionObject", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_22" ], "fields": [ { "name": "TypeId", "type": "NodeId" }, { "name": "Encoding", "type": { "type": "enum", "name": "Encoding", "symbols": [ "Structure", "ByteString", "XmlElement" ] } }, { "name": "Body", "type": [ "null", "string", "bytes" ] } ] }, { "type": "record", "name": "DataValue", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_23" ], "fields": [ { "name": "Value", "type": "Variant" }, { "name": "Status", "type": "StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoSeconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoSeconds", "type": "int" } ] }, { "type": "array", "items": "boolean" } ] } ] } }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "Important", "type": [ "null", { "type": "record", "name": "booleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "boolean" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "Variance", "type": [ "null", { "type": "record", "name": "floatDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "float" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] } ] } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Single/PendingAlarms.json ================================================ { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "ConditionClassId", "type": [ "null", { "type": "record", "name": "NodeIdDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "record", "name": "NodeId", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_17" ], "fields": [ { "name": "IdType", "type": { "type": "enum", "name": "IdentifierType", "namespace": "org.opcfoundation.UA", "symbols": [ "UInt32", "String", "Guid", "ByteString" ] } }, { "name": "Id", "type": [ "int", "string", "bytes" ] }, { "name": "Namespace", "type": "string" } ] } }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "ConditionClassName", "type": [ "null", { "type": "record", "name": "stringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "string" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "ConditionSubClassId", "type": [ "null", { "type": "record", "name": "arrayDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "array", "items": "org.opcfoundation.UA.NodeId" } }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "ConditionSubClassName", "type": [ "null", "org.github.microsoft.opc.publisher.arrayDataValue" ] }, { "name": "EventId", "type": [ "null", { "type": "record", "name": "bytesDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "bytes" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "EventType", "type": [ "null", "org.github.microsoft.opc.publisher.NodeIdDataValue" ] }, { "name": "LocalTime", "type": [ "null", { "type": "record", "name": "TimeZoneDataTypeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "record", "name": "TimeZoneDataType", "namespace": "org.opcfoundation.UA", "aliases": [ "org.opcfoundation.UA.i_x95_8912" ], "fields": [ { "name": "Offset", "type": "int" }, { "name": "DaylightSavingInOffset", "type": "boolean" } ], "uaDataTypeId": "i=8912" } }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "Message", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] }, { "name": "ReceiveTime", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] }, { "name": "Severity", "type": [ "null", { "type": "record", "name": "intDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "int" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "SourceName", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] }, { "name": "SourceNode", "type": [ "null", "org.github.microsoft.opc.publisher.NodeIdDataValue" ] }, { "name": "Time", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] } ] } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Single/PlcSimulation.json ================================================ [ { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_StepUp", "type": [ "null", { "type": "record", "name": "intDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "int" }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_AlternatingBoolean", "type": [ "null", { "type": "record", "name": "booleanDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "boolean" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomSignedInt32", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_RandomUnsignedInt32", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_DipData", "type": [ "null", { "type": "record", "name": "doubleDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "double" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_FastRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_NegativeTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.doubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_PositiveTrendData", "type": [ "null", "org.github.microsoft.opc.publisher.doubleDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SpikeData", "type": [ "null", "org.github.microsoft.opc.publisher.doubleDataValue" ] } ] } } ] }, { "type": "record", "name": "DataSetMessage1", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Payload", "type": { "type": "record", "name": "DataSet1", "fields": [ { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar2", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_SlowRandomUIntScalar3", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] }, { "name": "nsu_x61_http_x58__x47__x47_opcfoundation_x46_org_x47_UA_x47_Plc_x47_Applications_x59_s_x61_BadSlowRandomUIntScalar1", "type": [ "null", "org.github.microsoft.opc.publisher.intDataValue" ] } ] } } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JavroSchema/Single/SimpleEvents.json ================================================ { "type": "record", "name": "DataSetMessage", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Payload", "type": { "type": "record", "name": "DataSet", "fields": [ { "name": "EventId", "type": [ "null", { "type": "record", "name": "bytesDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "bytes" }, { "name": "Status", "type": { "type": "record", "name": "StatusCode", "namespace": "org.opcfoundation.UA", "fields": [ { "name": "Code", "type": "int" }, { "name": "Symbol", "type": "string" } ] } }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "Message", "type": [ "null", { "type": "record", "name": "stringDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": "string" }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CycleId", "type": [ "null", "org.github.microsoft.opc.publisher.stringDataValue" ] }, { "name": "http_x58__x47__x47_opcfoundation_x46_org_x47_SimpleEvents_x35_CurrentStep", "type": [ "null", { "type": "record", "name": "CycleStepDataTypeDataValue", "namespace": "org.github.microsoft.opc.publisher", "fields": [ { "name": "Value", "type": { "type": "record", "name": "CycleStepDataType", "namespace": "org.opcfoundation.SimpleEvents", "aliases": [ "org.opcfoundation.SimpleEvents.i_x95_183" ], "fields": [ { "name": "Name", "type": "string" }, { "name": "Duration", "type": "double" } ], "uaDataTypeId": "nsu=http://opcfoundation.org/SimpleEvents;i=183" } }, { "name": "Status", "type": "org.opcfoundation.UA.StatusCode" }, { "name": "SourceTimestamp", "type": "string" }, { "name": "SourcePicoseconds", "type": "int" }, { "name": "ServerTimestamp", "type": "string" }, { "name": "ServerPicoseconds", "type": "int" } ] } ] } ] } } ] } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonNetworkMessageAvroSchemaTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas { using Azure.IIoT.OpcUa.Encoders.Schemas.Avro; using Azure.IIoT.OpcUa.Publisher.Models; using System.IO; using System.Linq; using System.Text.Json; using System.Threading.Tasks; using Xunit; public class JsonNetworkMessageAvroSchemaTests { [Theory] [MemberData(nameof(GetMessageMetaDataFiles))] public async Task CreateJsonNetworkMessageSchemasAsync(string messageMetaDataFile) { var messageMetaData = await LoadAsync(messageMetaDataFile); var schema = new JsonNetworkMessage(messageMetaData); var json = schema.ToString(); var document = JsonDocument.Parse(json); json = JsonSerializer.Serialize(document, kIndented); Assert.NotNull(json); await AssertAsync("NetworkMessageDefault", messageMetaDataFile, json); var schema2 = global::Avro.Schema.Parse(json); Assert.NotNull(schema2); //Assert.Equal(schema.Schema, schema2); } [Theory] [MemberData(nameof(GetMessageMetaDataFiles))] public async Task CreateJsonNetworkMessageWithNsAsync(string messageMetaDataFile) { var messageMetaData = await LoadAsync(messageMetaDataFile); var schema = new JsonNetworkMessage(messageMetaData, new SchemaOptions { Namespace = "http://www.microsoft.com" }); var json = schema.ToString(); await AssertAsync("NetworkMessage", messageMetaDataFile, json); var schema2 = global::Avro.Schema.Parse(json); Assert.NotNull(schema2); //Assert.Equal(schema.Schema, schema2); } [Theory] [MemberData(nameof(GetMessageMetaDataFiles))] public async Task CreateMessageSchemaWithoutNetworkHeaderAsync(string messageMetaDataFile) { var messageMetaData = await LoadAsync(messageMetaDataFile); messageMetaData = messageMetaData with { NetworkMessageContentFlags = NetworkMessageContentFlags.DataSetMessageHeader }; var schema = new JsonNetworkMessage(messageMetaData); var json = schema.ToString(); await AssertAsync("Multiple", messageMetaDataFile, json); var schema2 = global::Avro.Schema.Parse(json); Assert.NotNull(schema2); //Assert.Equal(schema.Schema, schema2); } [Theory] [MemberData(nameof(GetMessageMetaDataFiles))] public async Task CreateSingleMessageSchemaAsync(string messageMetaDataFile) { var messageMetaData = await LoadAsync(messageMetaDataFile); messageMetaData = messageMetaData with { NetworkMessageContentFlags = NetworkMessageContentFlags.DataSetMessageHeader | NetworkMessageContentFlags.SingleDataSetMessage }; var schema = new JsonNetworkMessage(messageMetaData); var json = schema.ToString(); await AssertAsync("Single", messageMetaDataFile, json); var schema2 = global::Avro.Schema.Parse(json); Assert.NotNull(schema2); //Assert.Equal(schema.Schema, schema2); } [Theory] [MemberData(nameof(GetMessageMetaDataFiles))] public async Task CreateSingleMessageSchemaWithoutHeaderAsync(string messageMetaDataFile) { var messageMetaData = await LoadAsync(messageMetaDataFile); messageMetaData = messageMetaData with { NetworkMessageContentFlags = NetworkMessageContentFlags.SingleDataSetMessage }; var schema = new JsonNetworkMessage(messageMetaData); var json = schema.ToString(); await AssertAsync("Default", messageMetaDataFile, json); var schema2 = global::Avro.Schema.Parse(json); Assert.NotNull(schema2); //Assert.Equal(schema.Schema, schema2); } [Theory] [MemberData(nameof(GetMessageMetaDataFiles))] public async Task CreateRawMessageSchemaAsync(string messageMetaDataFile) { var messageMetaData = await LoadAsync(messageMetaDataFile); messageMetaData = messageMetaData with { NetworkMessageContentFlags = NetworkMessageContentFlags.SingleDataSetMessage, DataSetMessages = messageMetaData.DataSetMessages.Select(d => d with { DataSetMessageContentFlags = 0u, DataSetFieldContentFlags = DataSetFieldContentFlags.RawData }).ToList() }; var schema = new JsonNetworkMessage(messageMetaData); var json = schema.ToString(); await AssertAsync("Raw", messageMetaDataFile, json); var schema2 = global::Avro.Schema.Parse(json); Assert.NotNull(schema2); //Assert.Equal(schema.Schema, schema2); } [Theory] [MemberData(nameof(GetMessageMetaDataFiles))] public async Task CreateRawMessageSchemaReversibleAsync(string messageMetaDataFile) { var messageMetaData = await LoadAsync(messageMetaDataFile); messageMetaData = messageMetaData with { NetworkMessageContentFlags = NetworkMessageContentFlags.SingleDataSetMessage, DataSetMessages = messageMetaData.DataSetMessages.Select(d => d with { DataSetMessageContentFlags = DataSetMessageContentFlags.ReversibleFieldEncoding, DataSetFieldContentFlags = 0u }).ToList() }; var schema = new JsonNetworkMessage(messageMetaData); var json = schema.ToString(); await AssertAsync("RawReversible", messageMetaDataFile, json); var schema2 = global::Avro.Schema.Parse(json); Assert.NotNull(schema2); //Assert.Equal(schema.Schema, schema2); } [Theory] [MemberData(nameof(GetMessageMetaDataFiles))] public async Task CreateSamplesMessageSchemaAsync(string messageMetaDataFile) { var messageMetaData = await LoadAsync(messageMetaDataFile); messageMetaData = messageMetaData with { NetworkMessageContentFlags = NetworkMessageContentFlags.MonitoredItemMessage | NetworkMessageContentFlags.DataSetMessageHeader, DataSetMessages = messageMetaData.DataSetMessages.Select(d => d with { DataSetMessageContentFlags = DataSetMessageContentFlags.Timestamp | DataSetMessageContentFlags.DataSetWriterId | DataSetMessageContentFlags.SequenceNumber, DataSetFieldContentFlags = DataSetFieldContentFlags.StatusCode | DataSetFieldContentFlags.SourceTimestamp | DataSetFieldContentFlags.ServerTimestamp | DataSetFieldContentFlags.ApplicationUri | DataSetFieldContentFlags.ExtensionFields | DataSetFieldContentFlags.NodeId | DataSetFieldContentFlags.DisplayName | DataSetFieldContentFlags.EndpointUrl }).ToList() }; var schema = new JsonNetworkMessage(messageMetaData); var json = schema.ToString(); await AssertAsync("Samples", messageMetaDataFile, json); var schema2 = global::Avro.Schema.Parse(json); Assert.NotNull(schema2); //Assert.Equal(schema.Schema, schema2); } [Theory] [MemberData(nameof(GetMessageMetaDataFiles))] public async Task CreateSamplesMessageSchemaRawAsync(string messageMetaDataFile) { var messageMetaData = await LoadAsync(messageMetaDataFile); messageMetaData = messageMetaData with { NetworkMessageContentFlags = NetworkMessageContentFlags.MonitoredItemMessage | NetworkMessageContentFlags.DataSetMessageHeader, DataSetMessages = messageMetaData.DataSetMessages.Select(d => d with { DataSetMessageContentFlags = DataSetMessageContentFlags.Timestamp | DataSetMessageContentFlags.SequenceNumber, DataSetFieldContentFlags = DataSetFieldContentFlags.ApplicationUri | DataSetFieldContentFlags.ExtensionFields | DataSetFieldContentFlags.NodeId | DataSetFieldContentFlags.DisplayName | DataSetFieldContentFlags.EndpointUrl | DataSetFieldContentFlags.RawData }).ToList() }; var schema = new JsonNetworkMessage(messageMetaData); var json = schema.ToString(); await AssertAsync("SamplesRaw", messageMetaDataFile, json); var schema2 = global::Avro.Schema.Parse(json); Assert.NotNull(schema2); //Assert.Equal(schema.Schema, schema2); } private static async ValueTask LoadAsync(string file) { await using var fs = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read); return await JsonSerializer.DeserializeAsync(fs); } private static readonly JsonSerializerOptions kIndented = new() { WriteIndented = true }; private static async Task AssertAsync(string name, string messageMetaDataFile, string json) { var document = JsonDocument.Parse(json); json = JsonSerializer.Serialize(document, kIndented).ReplaceLineEndings(); Assert.NotNull(json); #if WRITE var folder = Path.Combine(".", "JavroSchema", name); if (!Directory.Exists(folder)) { Directory.CreateDirectory(folder); } await File.WriteAllTextAsync(Path.Combine(folder, Path.GetFileName(messageMetaDataFile)), json); #else var folder = Path.Combine(".", "Encoders", "Schemas", "JavroSchema", name); var expected = await File.ReadAllTextAsync(Path.Combine(folder, Path.GetFileName(messageMetaDataFile))); Assert.Equal(expected.ReplaceLineEndings(), json); #endif } public static TheoryData GetMessageMetaDataFiles() { var resources = Directory.GetFiles(Path.Combine(".", "Resources"), "*.json"); return new TheoryData(resources); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonNetworkMessageJsonSchemaTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders.Schemas { using Azure.IIoT.OpcUa.Encoders.Schemas.Json; using Azure.IIoT.OpcUa.Publisher.Models; using Microsoft.Json.Schema; using System.IO; using System.Linq; using System.Text.Json; using System.Threading.Tasks; using Xunit; public class JsonNetworkMessageJsonSchemaTests { [Theory] [MemberData(nameof(GetMessageMetaDataFiles))] public async Task CreateNetworkMessageJsonSchemasAsync(string messageMetaDataFile) { var messageMetaData = await LoadAsync(messageMetaDataFile); var schema = new JsonNetworkMessage(messageMetaData); var json = schema.ToString(); var document = JsonDocument.Parse(json); json = JsonSerializer.Serialize(document, kIndented); Assert.NotNull(json); await AssertAsync("NetworkMessageDefault", messageMetaDataFile, json); var schema2 = SchemaReader.ReadSchema(json, "."); Assert.NotNull(schema2); // var schema2 = global::Json.Schema.JsonSchema.FromText(json); //Assert.Equal(schema.Schema, schema2); // var instance = JsonNode.Parse("{\"foo\":\"a value\",\"bar\":42}"); // var results = schema2.Evaluate(instance); // Assert.True(results.IsValid); // Assert.False(results.HasErrors); } [Theory] [MemberData(nameof(GetMessageMetaDataFiles))] public async Task CreateJsonNetworkMessageWithNsAsync(string messageMetaDataFile) { var messageMetaData = await LoadAsync(messageMetaDataFile); var schema = new JsonNetworkMessage(messageMetaData, new SchemaOptions { Namespace = "http://www.microsoft.com" }); var json = schema.ToString(); await AssertAsync("NetworkMessage", messageMetaDataFile, json); var schema2 = SchemaReader.ReadSchema(json, "."); Assert.NotNull(schema2); // var schema2 = global::Json.Schema.JsonSchema.FromText(json); //Assert.Equal(schema.Schema, schema2); } [Theory] [MemberData(nameof(GetMessageMetaDataFiles))] public async Task CreateMessageSchemaWithoutNetworkHeaderAsync(string messageMetaDataFile) { var messageMetaData = await LoadAsync(messageMetaDataFile); messageMetaData = messageMetaData with { NetworkMessageContentFlags = NetworkMessageContentFlags.DataSetMessageHeader }; var schema = new JsonNetworkMessage(messageMetaData); var json = schema.ToString(); await AssertAsync("Multiple", messageMetaDataFile, json); var schema2 = SchemaReader.ReadSchema(json, "."); Assert.NotNull(schema2); // var schema2 = global::Json.Schema.JsonSchema.FromText(json); //Assert.Equal(schema.Schema, schema2); } [Theory] [MemberData(nameof(GetMessageMetaDataFiles))] public async Task CreateSingleMessageSchemaAsync(string messageMetaDataFile) { var messageMetaData = await LoadAsync(messageMetaDataFile); messageMetaData = messageMetaData with { NetworkMessageContentFlags = NetworkMessageContentFlags.DataSetMessageHeader | NetworkMessageContentFlags.SingleDataSetMessage }; var schema = new JsonNetworkMessage(messageMetaData); var json = schema.ToString(); await AssertAsync("Single", messageMetaDataFile, json); var schema2 = SchemaReader.ReadSchema(json, "."); Assert.NotNull(schema2); // var schema2 = global::Json.Schema.JsonSchema.FromText(json); //Assert.Equal(schema.Schema, schema2); } [Theory] [MemberData(nameof(GetMessageMetaDataFiles))] public async Task CreateSingleMessageSchemaWithoutHeaderAsync(string messageMetaDataFile) { var messageMetaData = await LoadAsync(messageMetaDataFile); messageMetaData = messageMetaData with { NetworkMessageContentFlags = NetworkMessageContentFlags.SingleDataSetMessage }; var schema = new JsonNetworkMessage(messageMetaData); var json = schema.ToString(); await AssertAsync("Default", messageMetaDataFile, json); var schema2 = SchemaReader.ReadSchema(json, "."); Assert.NotNull(schema2); // var schema2 = global::Json.Schema.JsonSchema.FromText(json); //Assert.Equal(schema.Schema, schema2); } [Theory] [MemberData(nameof(GetMessageMetaDataFiles))] public async Task CreateRawMessageSchemaAsync(string messageMetaDataFile) { var messageMetaData = await LoadAsync(messageMetaDataFile); messageMetaData = messageMetaData with { NetworkMessageContentFlags = NetworkMessageContentFlags.SingleDataSetMessage, DataSetMessages = messageMetaData.DataSetMessages.Select(d => d with { DataSetMessageContentFlags = 0u, DataSetFieldContentFlags = DataSetFieldContentFlags.RawData }).ToList() }; var schema = new JsonNetworkMessage(messageMetaData); var json = schema.ToString(); await AssertAsync("Raw", messageMetaDataFile, json); var schema2 = SchemaReader.ReadSchema(json, "."); Assert.NotNull(schema2); // var schema2 = global::Json.Schema.JsonSchema.FromText(json); //Assert.Equal(schema.Schema, schema2); } [Theory] [MemberData(nameof(GetMessageMetaDataFiles))] public async Task CreateRawMessageSchemaReversibleAsync(string messageMetaDataFile) { var messageMetaData = await LoadAsync(messageMetaDataFile); messageMetaData = messageMetaData with { NetworkMessageContentFlags = NetworkMessageContentFlags.SingleDataSetMessage, DataSetMessages = messageMetaData.DataSetMessages.Select(d => d with { DataSetMessageContentFlags = DataSetMessageContentFlags.ReversibleFieldEncoding, DataSetFieldContentFlags = 0u }).ToList() }; var schema = new JsonNetworkMessage(messageMetaData); var json = schema.ToString(); await AssertAsync("RawReversible", messageMetaDataFile, json); var schema2 = SchemaReader.ReadSchema(json, "."); Assert.NotNull(schema2); // var schema2 = global::Json.Schema.JsonSchema.FromText(json); //Assert.Equal(schema.Schema, schema2); } [Theory] [MemberData(nameof(GetMessageMetaDataFiles))] public async Task CreateSamplesMessageSchemaAsync(string messageMetaDataFile) { var messageMetaData = await LoadAsync(messageMetaDataFile); messageMetaData = messageMetaData with { NetworkMessageContentFlags = NetworkMessageContentFlags.MonitoredItemMessage | NetworkMessageContentFlags.DataSetMessageHeader, DataSetMessages = messageMetaData.DataSetMessages.Select(d => d with { DataSetMessageContentFlags = DataSetMessageContentFlags.Timestamp | DataSetMessageContentFlags.DataSetWriterId | DataSetMessageContentFlags.SequenceNumber, DataSetFieldContentFlags = DataSetFieldContentFlags.StatusCode | DataSetFieldContentFlags.SourceTimestamp | DataSetFieldContentFlags.ServerTimestamp | DataSetFieldContentFlags.ApplicationUri | DataSetFieldContentFlags.ExtensionFields | DataSetFieldContentFlags.NodeId | DataSetFieldContentFlags.DisplayName | DataSetFieldContentFlags.EndpointUrl }).ToList() }; var schema = new JsonNetworkMessage(messageMetaData); var json = schema.ToString(); await AssertAsync("Samples", messageMetaDataFile, json); var schema2 = SchemaReader.ReadSchema(json, "."); Assert.NotNull(schema2); // var schema2 = global::Json.Schema.JsonSchema.FromText(json); //Assert.Equal(schema.Schema, schema2); } [Theory] [MemberData(nameof(GetMessageMetaDataFiles))] public async Task CreateSamplesMessageSchemaRawAsync(string messageMetaDataFile) { var messageMetaData = await LoadAsync(messageMetaDataFile); messageMetaData = messageMetaData with { NetworkMessageContentFlags = NetworkMessageContentFlags.MonitoredItemMessage | NetworkMessageContentFlags.DataSetMessageHeader, DataSetMessages = messageMetaData.DataSetMessages.Select(d => d with { DataSetMessageContentFlags = DataSetMessageContentFlags.Timestamp | DataSetMessageContentFlags.SequenceNumber, DataSetFieldContentFlags = DataSetFieldContentFlags.ApplicationUri | DataSetFieldContentFlags.ExtensionFields | DataSetFieldContentFlags.NodeId | DataSetFieldContentFlags.DisplayName | DataSetFieldContentFlags.EndpointUrl | DataSetFieldContentFlags.RawData }).ToList() }; var schema = new JsonNetworkMessage(messageMetaData); var json = schema.ToString(); await AssertAsync("SamplesRaw", messageMetaDataFile, json); var schema2 = SchemaReader.ReadSchema(json, "."); Assert.NotNull(schema2); // var schema2 = global::Json.Schema.JsonSchema.FromText(json); //Assert.Equal(schema.Schema, schema2); } private static async ValueTask LoadAsync(string file) { await using var fs = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read); return await JsonSerializer.DeserializeAsync(fs); } private static readonly JsonSerializerOptions kIndented = new() { WriteIndented = true }; private static async Task AssertAsync(string name, string messageMetaDataFile, string json) { var document = JsonDocument.Parse(json); json = JsonSerializer.Serialize(document, kIndented).ReplaceLineEndings(); Assert.NotNull(json); #if WRITE var folder = Path.Combine(".", "JsonSchema", name); if (!Directory.Exists(folder)) { Directory.CreateDirectory(folder); } await File.WriteAllTextAsync(Path.Combine(folder, Path.GetFileName(messageMetaDataFile)), json); #else var folder = Path.Combine(".", "Encoders", "Schemas", "JsonSchema", name); var expected = await File.ReadAllTextAsync(Path.Combine(folder, Path.GetFileName(messageMetaDataFile))); Assert.Equal(expected.ReplaceLineEndings(), json); #endif } public static TheoryData GetMessageMetaDataFiles() { var resources = Directory.GetFiles(Path.Combine(".", "Resources"), "*.json"); return new TheoryData(resources); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Default/CyclicReads.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet", "definitions": { "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.DateTimeDataValue": { "$id": "http://github.org/microsoft/opcpublisher#DateTimeDataValue", "title": "Dataset Field of Type DateTime", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.UInt32DataValue": { "$id": "http://github.org/microsoft/opcpublisher#UInt32DataValue", "title": "Dataset Field of Type UInt32", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.github.microsoft.opcpublisher.BooleanDataValue": { "$id": "http://github.org/microsoft/opcpublisher#BooleanDataValue", "title": "Dataset Field of Type Boolean", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Int32": { "$id": "http://opcfoundation.org/UA/#Int32", "title": "OPC UA built in type Int32", "type": "integer", "minimum": -2147483648, "maximum": 2147483647, "default": 0, "format": "int32" }, "org.github.microsoft.opcpublisher.Int32DataValue": { "$id": "http://github.org/microsoft/opcpublisher#Int32DataValue", "title": "Dataset Field of Type Int32", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Int32" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "org.github.microsoft.opcpublisher.DoubleDataValue": { "$id": "http://github.org/microsoft/opcpublisher#DoubleDataValue", "title": "Dataset Field of Type Double", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Number": { "$id": "http://opcfoundation.org/UA/#Number", "title": "OPC UA built in type Number", "type": "number" }, "org.github.microsoft.opcpublisher.NumberDataValue": { "$id": "http://github.org/microsoft/opcpublisher#NumberDataValue", "title": "Dataset Field of Type Number", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Number" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "i=2258": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DateTimeDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=StepUp": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.BooleanDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.Int32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "ns=23;i=1259": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NumberDataValue" } } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Default/KeepAlive.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet", "definitions": { "org.opcfoundation.UA.ServerState": { "$id": "http://opcfoundation.org/UA/#ServerState", "title": "ServerState", "type": "integer", "enum": [ 0, 1, 2, 3, 4, 5, 6, 7 ], "format": "int32" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.ServerStateDataValue": { "$id": "http://github.org/microsoft/opcpublisher#ServerStateDataValue", "title": "Dataset Field of Type ServerState", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.ServerState" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "State": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.ServerStateDataValue" } } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Default/KeyFrames.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet", "definitions": { "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.DateTimeDataValue": { "$id": "http://github.org/microsoft/opcpublisher#DateTimeDataValue", "title": "Dataset Field of Type DateTime", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.StringDataValue": { "$id": "http://github.org/microsoft/opcpublisher#StringDataValue", "title": "Dataset Field of Type String", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Variant": { "title": "Any", "type": [ "number", "null", "object", "array", "string", "integer", "boolean" ] }, "org.github.microsoft.opcpublisher.NumberDataValue": { "$id": "http://github.org/microsoft/opcpublisher#NumberDataValue", "title": "Dataset Field of Type Number", "type": "object", "properties": { "Value": { "title": "Any", "type": [ "number", "null", "object", "array", "string", "integer", "boolean" ] }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.github.microsoft.opcpublisher.BooleanDataValue": { "$id": "http://github.org/microsoft/opcpublisher#BooleanDataValue", "title": "Dataset Field of Type Boolean", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Float": { "$id": "http://opcfoundation.org/UA/#Float", "title": "OPC UA built in type Float", "type": "number", "minimum": -3.4028235E+38, "maximum": 3.4028235E+38, "default": 0, "format": "float" }, "org.github.microsoft.opcpublisher.FloatDataValue": { "$id": "http://github.org/microsoft/opcpublisher#FloatDataValue", "title": "Dataset Field of Type Float", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Float" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "CurrentTime": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DateTimeDataValue" }, "EngineeringUnits": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.StringDataValue" }, "AssetId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NumberDataValue" }, "Important": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.BooleanDataValue" }, "Variance": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.FloatDataValue" } } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Default/PendingAlarms.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet", "definitions": { "org.opcfoundation.UA.NodeId": { "$id": "http://opcfoundation.org/UA/#NodeId", "title": "OPC UA built in type NodeId", "type": "string", "format": "opcuaNodeId" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.NodeIdDataValue": { "$id": "http://github.org/microsoft/opcpublisher#NodeIdDataValue", "title": "Dataset Field of Type NodeId", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.NodeId" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.LocalizedText": { "$id": "http://opcfoundation.org/UA/#LocalizedText", "title": "OPC UA built in type LocalizedText", "type": "string" }, "org.github.microsoft.opcpublisher.LocalizedTextDataValue": { "$id": "http://github.org/microsoft/opcpublisher#LocalizedTextDataValue", "title": "Dataset Field of Type LocalizedText", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.NodeIdArrayDataValue": { "$id": "http://github.org/microsoft/opcpublisher#NodeIdArrayDataValue", "title": "Dataset Field of Type NodeIdArray", "type": "object", "properties": { "Value": { "type": "array", "items": { "$ref": "#/definitions/org.opcfoundation.UA.NodeId" } }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.LocalizedTextArrayDataValue": { "$id": "http://github.org/microsoft/opcpublisher#LocalizedTextArrayDataValue", "title": "Dataset Field of Type LocalizedTextArray", "type": "object", "properties": { "Value": { "type": "array", "items": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" } }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.ByteString": { "$id": "http://opcfoundation.org/UA/#ByteString", "title": "OPC UA built in type ByteString", "type": "string", "format": "byte" }, "org.github.microsoft.opcpublisher.ByteStringDataValue": { "$id": "http://github.org/microsoft/opcpublisher#ByteStringDataValue", "title": "Dataset Field of Type ByteString", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.ByteString" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Int16": { "$id": "http://opcfoundation.org/UA/#Int16", "title": "OPC UA built in type Int16", "type": "integer", "minimum": -32768, "maximum": 32767, "default": 0, "format": "int16" }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.opcfoundation.UA.TimeZoneDataType": { "$id": "http://opcfoundation.org/UA/#TimeZoneDataType", "title": "TimeZoneDataType", "type": "object", "properties": { "Offset": { "$ref": "#/definitions/org.opcfoundation.UA.Int16" }, "DaylightSavingInOffset": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" } }, "required": [ "Offset", "DaylightSavingInOffset" ], "additionalProperties": false }, "org.github.microsoft.opcpublisher.TimeZoneDataTypeDataValue": { "$id": "http://github.org/microsoft/opcpublisher#TimeZoneDataTypeDataValue", "title": "Dataset Field of Type TimeZoneDataType", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.TimeZoneDataType" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DateTimeDataValue": { "$id": "http://github.org/microsoft/opcpublisher#DateTimeDataValue", "title": "Dataset Field of Type DateTime", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.UInt16DataValue": { "$id": "http://github.org/microsoft/opcpublisher#UInt16DataValue", "title": "Dataset Field of Type UInt16", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.StringDataValue": { "$id": "http://github.org/microsoft/opcpublisher#StringDataValue", "title": "Dataset Field of Type String", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "ConditionClassId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NodeIdDataValue" }, "ConditionClassName": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.LocalizedTextDataValue" }, "ConditionSubClassId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NodeIdArrayDataValue" }, "ConditionSubClassName": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.LocalizedTextArrayDataValue" }, "EventId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.ByteStringDataValue" }, "EventType": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NodeIdDataValue" }, "LocalTime": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.TimeZoneDataTypeDataValue" }, "Message": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.LocalizedTextDataValue" }, "ReceiveTime": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DateTimeDataValue" }, "Severity": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt16DataValue" }, "SourceName": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.StringDataValue" }, "SourceNode": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NodeIdDataValue" }, "Time": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DateTimeDataValue" } } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Default/PlcSimulation.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSets", "definitions": { "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.UInt32DataValue": { "$id": "http://github.org/microsoft/opcpublisher#UInt32DataValue", "title": "Dataset Field of Type UInt32", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.github.microsoft.opcpublisher.BooleanDataValue": { "$id": "http://github.org/microsoft/opcpublisher#BooleanDataValue", "title": "Dataset Field of Type Boolean", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Int32": { "$id": "http://opcfoundation.org/UA/#Int32", "title": "OPC UA built in type Int32", "type": "integer", "minimum": -2147483648, "maximum": 2147483647, "default": 0, "format": "int32" }, "org.github.microsoft.opcpublisher.Int32DataValue": { "$id": "http://github.org/microsoft/opcpublisher#Int32DataValue", "title": "Dataset Field of Type Int32", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Int32" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "org.github.microsoft.opcpublisher.DoubleDataValue": { "$id": "http://github.org/microsoft/opcpublisher#DoubleDataValue", "title": "Dataset Field of Type Double", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "nsu=http://opcfoundation.org/UA/Plc/Applications;s=StepUp": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.BooleanDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.Int32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" } } }, "org.github.microsoft.opcpublisher.DataSet1": { "$id": "http://github.org/microsoft/opcpublisher#DataSet1", "title": "DataSet1", "type": "object", "properties": { "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" } } }, "org.github.microsoft.opcpublisher.DataSets": { "$id": "http://github.org/microsoft/opcpublisher#DataSets", "type": "object", "oneOf": [ { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet1" } ] } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Default/SimpleEvents.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet", "definitions": { "org.opcfoundation.UA.ByteString": { "$id": "http://opcfoundation.org/UA/#ByteString", "title": "OPC UA built in type ByteString", "type": "string", "format": "byte" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.ByteStringDataValue": { "$id": "http://github.org/microsoft/opcpublisher#ByteStringDataValue", "title": "Dataset Field of Type ByteString", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.ByteString" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.LocalizedText": { "$id": "http://opcfoundation.org/UA/#LocalizedText", "title": "OPC UA built in type LocalizedText", "type": "string" }, "org.github.microsoft.opcpublisher.LocalizedTextDataValue": { "$id": "http://github.org/microsoft/opcpublisher#LocalizedTextDataValue", "title": "Dataset Field of Type LocalizedText", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.StringDataValue": { "$id": "http://github.org/microsoft/opcpublisher#StringDataValue", "title": "Dataset Field of Type String", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "org.opcfoundation.SimpleEvents.CycleStepDataType": { "$id": "http://opcfoundation.org/SimpleEvents#CycleStepDataType", "title": "nsu=http://opcfoundation.org/SimpleEvents;CycleStepDataType", "type": "object", "properties": { "Name": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Duration": { "$ref": "#/definitions/org.opcfoundation.UA.Double" } }, "required": [ "Name", "Duration" ], "additionalProperties": false }, "org.github.microsoft.opcpublisher.CycleStepDataTypeDataValue": { "$id": "http://github.org/microsoft/opcpublisher#CycleStepDataTypeDataValue", "title": "Dataset Field of Type CycleStepDataType", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.SimpleEvents.CycleStepDataType" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "EventId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.ByteStringDataValue" }, "Message": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.LocalizedTextDataValue" }, "http://opcfoundation.org/SimpleEvents#CycleId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.StringDataValue" }, "http://opcfoundation.org/SimpleEvents#CurrentStep": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.CycleStepDataTypeDataValue" } } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Multiple/CyclicReads.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "type": "array", "items": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSetMessage" }, "definitions": { "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.DateTimeDataValue": { "$id": "http://github.org/microsoft/opcpublisher#DateTimeDataValue", "title": "Dataset Field of Type DateTime", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.UInt32DataValue": { "$id": "http://github.org/microsoft/opcpublisher#UInt32DataValue", "title": "Dataset Field of Type UInt32", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.github.microsoft.opcpublisher.BooleanDataValue": { "$id": "http://github.org/microsoft/opcpublisher#BooleanDataValue", "title": "Dataset Field of Type Boolean", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Int32": { "$id": "http://opcfoundation.org/UA/#Int32", "title": "OPC UA built in type Int32", "type": "integer", "minimum": -2147483648, "maximum": 2147483647, "default": 0, "format": "int32" }, "org.github.microsoft.opcpublisher.Int32DataValue": { "$id": "http://github.org/microsoft/opcpublisher#Int32DataValue", "title": "Dataset Field of Type Int32", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Int32" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "org.github.microsoft.opcpublisher.DoubleDataValue": { "$id": "http://github.org/microsoft/opcpublisher#DoubleDataValue", "title": "Dataset Field of Type Double", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Number": { "$id": "http://opcfoundation.org/UA/#Number", "title": "OPC UA built in type Number", "type": "number" }, "org.github.microsoft.opcpublisher.NumberDataValue": { "$id": "http://github.org/microsoft/opcpublisher#NumberDataValue", "title": "Dataset Field of Type Number", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Number" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "i=2258": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DateTimeDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=StepUp": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.BooleanDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.Int32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "ns=23;i=1259": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NumberDataValue" } } }, "org.github.microsoft.opcpublisher.DataSetMessage": { "$id": "http://github.org/microsoft/opcpublisher#DataSetMessage", "type": "object", "properties": { "Payload": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet" } }, "required": [ "Payload" ], "additionalProperties": false } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Multiple/KeepAlive.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "type": "array", "items": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSetMessage" }, "definitions": { "org.opcfoundation.UA.ServerState": { "$id": "http://opcfoundation.org/UA/#ServerState", "title": "ServerState", "type": "integer", "enum": [ 0, 1, 2, 3, 4, 5, 6, 7 ], "format": "int32" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.ServerStateDataValue": { "$id": "http://github.org/microsoft/opcpublisher#ServerStateDataValue", "title": "Dataset Field of Type ServerState", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.ServerState" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "State": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.ServerStateDataValue" } } }, "org.opcfoundation.UA.i_x61_14593": { "$id": "http://opcfoundation.org/UA/#i%3d14593", "type": "object", "properties": { "MajorVersion": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "MinorVersion": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" } } }, "org.github.microsoft.opcpublisher.DataSetMessage": { "$id": "http://github.org/microsoft/opcpublisher#DataSetMessage", "type": "object", "properties": { "MetaDataVersion": { "$ref": "#/definitions/org.opcfoundation.UA.i_x61_14593" }, "MessageType": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DataSetWriterName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Payload": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet" } }, "required": [ "MetaDataVersion", "MessageType", "DataSetWriterName", "Payload" ], "additionalProperties": false } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Multiple/KeyFrames.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "type": "array", "items": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSetMessage" }, "definitions": { "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.DateTimeDataValue": { "$id": "http://github.org/microsoft/opcpublisher#DateTimeDataValue", "title": "Dataset Field of Type DateTime", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.StringDataValue": { "$id": "http://github.org/microsoft/opcpublisher#StringDataValue", "title": "Dataset Field of Type String", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Variant": { "title": "Any", "type": [ "number", "null", "object", "array", "string", "integer", "boolean" ] }, "org.github.microsoft.opcpublisher.NumberDataValue": { "$id": "http://github.org/microsoft/opcpublisher#NumberDataValue", "title": "Dataset Field of Type Number", "type": "object", "properties": { "Value": { "title": "Any", "type": [ "number", "null", "object", "array", "string", "integer", "boolean" ] }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.github.microsoft.opcpublisher.BooleanDataValue": { "$id": "http://github.org/microsoft/opcpublisher#BooleanDataValue", "title": "Dataset Field of Type Boolean", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Float": { "$id": "http://opcfoundation.org/UA/#Float", "title": "OPC UA built in type Float", "type": "number", "minimum": -3.4028235E+38, "maximum": 3.4028235E+38, "default": 0, "format": "float" }, "org.github.microsoft.opcpublisher.FloatDataValue": { "$id": "http://github.org/microsoft/opcpublisher#FloatDataValue", "title": "Dataset Field of Type Float", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Float" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "CurrentTime": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DateTimeDataValue" }, "EngineeringUnits": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.StringDataValue" }, "AssetId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NumberDataValue" }, "Important": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.BooleanDataValue" }, "Variance": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.FloatDataValue" } } }, "org.opcfoundation.UA.i_x61_14593": { "$id": "http://opcfoundation.org/UA/#i%3d14593", "type": "object", "properties": { "MajorVersion": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "MinorVersion": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" } } }, "org.github.microsoft.opcpublisher.DataSetMessage": { "$id": "http://github.org/microsoft/opcpublisher#DataSetMessage", "type": "object", "properties": { "MetaDataVersion": { "$ref": "#/definitions/org.opcfoundation.UA.i_x61_14593" }, "MessageType": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DataSetWriterName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Payload": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet" } }, "required": [ "MetaDataVersion", "MessageType", "DataSetWriterName", "Payload" ], "additionalProperties": false } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Multiple/PendingAlarms.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "type": "array", "items": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSetMessage" }, "definitions": { "org.opcfoundation.UA.NodeId": { "$id": "http://opcfoundation.org/UA/#NodeId", "title": "OPC UA built in type NodeId", "type": "string", "format": "opcuaNodeId" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.NodeIdDataValue": { "$id": "http://github.org/microsoft/opcpublisher#NodeIdDataValue", "title": "Dataset Field of Type NodeId", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.NodeId" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.LocalizedText": { "$id": "http://opcfoundation.org/UA/#LocalizedText", "title": "OPC UA built in type LocalizedText", "type": "string" }, "org.github.microsoft.opcpublisher.LocalizedTextDataValue": { "$id": "http://github.org/microsoft/opcpublisher#LocalizedTextDataValue", "title": "Dataset Field of Type LocalizedText", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.NodeIdArrayDataValue": { "$id": "http://github.org/microsoft/opcpublisher#NodeIdArrayDataValue", "title": "Dataset Field of Type NodeIdArray", "type": "object", "properties": { "Value": { "type": "array", "items": { "$ref": "#/definitions/org.opcfoundation.UA.NodeId" } }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.LocalizedTextArrayDataValue": { "$id": "http://github.org/microsoft/opcpublisher#LocalizedTextArrayDataValue", "title": "Dataset Field of Type LocalizedTextArray", "type": "object", "properties": { "Value": { "type": "array", "items": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" } }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.ByteString": { "$id": "http://opcfoundation.org/UA/#ByteString", "title": "OPC UA built in type ByteString", "type": "string", "format": "byte" }, "org.github.microsoft.opcpublisher.ByteStringDataValue": { "$id": "http://github.org/microsoft/opcpublisher#ByteStringDataValue", "title": "Dataset Field of Type ByteString", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.ByteString" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Int16": { "$id": "http://opcfoundation.org/UA/#Int16", "title": "OPC UA built in type Int16", "type": "integer", "minimum": -32768, "maximum": 32767, "default": 0, "format": "int16" }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.opcfoundation.UA.TimeZoneDataType": { "$id": "http://opcfoundation.org/UA/#TimeZoneDataType", "title": "TimeZoneDataType", "type": "object", "properties": { "Offset": { "$ref": "#/definitions/org.opcfoundation.UA.Int16" }, "DaylightSavingInOffset": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" } }, "required": [ "Offset", "DaylightSavingInOffset" ], "additionalProperties": false }, "org.github.microsoft.opcpublisher.TimeZoneDataTypeDataValue": { "$id": "http://github.org/microsoft/opcpublisher#TimeZoneDataTypeDataValue", "title": "Dataset Field of Type TimeZoneDataType", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.TimeZoneDataType" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DateTimeDataValue": { "$id": "http://github.org/microsoft/opcpublisher#DateTimeDataValue", "title": "Dataset Field of Type DateTime", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.UInt16DataValue": { "$id": "http://github.org/microsoft/opcpublisher#UInt16DataValue", "title": "Dataset Field of Type UInt16", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.StringDataValue": { "$id": "http://github.org/microsoft/opcpublisher#StringDataValue", "title": "Dataset Field of Type String", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "ConditionClassId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NodeIdDataValue" }, "ConditionClassName": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.LocalizedTextDataValue" }, "ConditionSubClassId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NodeIdArrayDataValue" }, "ConditionSubClassName": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.LocalizedTextArrayDataValue" }, "EventId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.ByteStringDataValue" }, "EventType": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NodeIdDataValue" }, "LocalTime": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.TimeZoneDataTypeDataValue" }, "Message": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.LocalizedTextDataValue" }, "ReceiveTime": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DateTimeDataValue" }, "Severity": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt16DataValue" }, "SourceName": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.StringDataValue" }, "SourceNode": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NodeIdDataValue" }, "Time": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DateTimeDataValue" } } }, "org.github.microsoft.opcpublisher.DataSetMessage": { "$id": "http://github.org/microsoft/opcpublisher#DataSetMessage", "type": "object", "properties": { "Payload": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet" } }, "required": [ "Payload" ], "additionalProperties": false } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Multiple/PlcSimulation.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "type": "array", "items": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSets" }, "definitions": { "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.UInt32DataValue": { "$id": "http://github.org/microsoft/opcpublisher#UInt32DataValue", "title": "Dataset Field of Type UInt32", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.github.microsoft.opcpublisher.BooleanDataValue": { "$id": "http://github.org/microsoft/opcpublisher#BooleanDataValue", "title": "Dataset Field of Type Boolean", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Int32": { "$id": "http://opcfoundation.org/UA/#Int32", "title": "OPC UA built in type Int32", "type": "integer", "minimum": -2147483648, "maximum": 2147483647, "default": 0, "format": "int32" }, "org.github.microsoft.opcpublisher.Int32DataValue": { "$id": "http://github.org/microsoft/opcpublisher#Int32DataValue", "title": "Dataset Field of Type Int32", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Int32" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "org.github.microsoft.opcpublisher.DoubleDataValue": { "$id": "http://github.org/microsoft/opcpublisher#DoubleDataValue", "title": "Dataset Field of Type Double", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "nsu=http://opcfoundation.org/UA/Plc/Applications;s=StepUp": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.BooleanDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.Int32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" } } }, "org.github.microsoft.opcpublisher.DataSetMessage": { "$id": "http://github.org/microsoft/opcpublisher#DataSetMessage", "type": "object", "properties": { "Payload": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet" } }, "required": [ "Payload" ], "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet1": { "$id": "http://github.org/microsoft/opcpublisher#DataSet1", "title": "DataSet1", "type": "object", "properties": { "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" } } }, "org.github.microsoft.opcpublisher.DataSetMessage1": { "$id": "http://github.org/microsoft/opcpublisher#DataSetMessage1", "type": "object", "properties": { "Payload": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet1" } }, "required": [ "Payload" ], "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSets": { "$id": "http://github.org/microsoft/opcpublisher#DataSets", "type": "object", "oneOf": [ { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSetMessage" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSetMessage1" } ] } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Multiple/SimpleEvents.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "type": "array", "items": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSetMessage" }, "definitions": { "org.opcfoundation.UA.ByteString": { "$id": "http://opcfoundation.org/UA/#ByteString", "title": "OPC UA built in type ByteString", "type": "string", "format": "byte" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.ByteStringDataValue": { "$id": "http://github.org/microsoft/opcpublisher#ByteStringDataValue", "title": "Dataset Field of Type ByteString", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.ByteString" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.LocalizedText": { "$id": "http://opcfoundation.org/UA/#LocalizedText", "title": "OPC UA built in type LocalizedText", "type": "string" }, "org.github.microsoft.opcpublisher.LocalizedTextDataValue": { "$id": "http://github.org/microsoft/opcpublisher#LocalizedTextDataValue", "title": "Dataset Field of Type LocalizedText", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.StringDataValue": { "$id": "http://github.org/microsoft/opcpublisher#StringDataValue", "title": "Dataset Field of Type String", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "org.opcfoundation.SimpleEvents.CycleStepDataType": { "$id": "http://opcfoundation.org/SimpleEvents#CycleStepDataType", "title": "nsu=http://opcfoundation.org/SimpleEvents;CycleStepDataType", "type": "object", "properties": { "Name": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Duration": { "$ref": "#/definitions/org.opcfoundation.UA.Double" } }, "required": [ "Name", "Duration" ], "additionalProperties": false }, "org.github.microsoft.opcpublisher.CycleStepDataTypeDataValue": { "$id": "http://github.org/microsoft/opcpublisher#CycleStepDataTypeDataValue", "title": "Dataset Field of Type CycleStepDataType", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.SimpleEvents.CycleStepDataType" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "EventId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.ByteStringDataValue" }, "Message": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.LocalizedTextDataValue" }, "http://opcfoundation.org/SimpleEvents#CycleId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.StringDataValue" }, "http://opcfoundation.org/SimpleEvents#CurrentStep": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.CycleStepDataTypeDataValue" } } }, "org.github.microsoft.opcpublisher.DataSetMessage": { "$id": "http://github.org/microsoft/opcpublisher#DataSetMessage", "type": "object", "properties": { "Payload": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet" } }, "required": [ "Payload" ], "additionalProperties": false } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/NetworkMessage/CyclicReads.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/com.microsoft.DataSet", "definitions": { "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "com.microsoft.DateTimeDataValue": { "$id": "http://www.microsoft.com#DateTimeDataValue", "title": "Dataset Field of Type DateTime", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "com.microsoft.UInt32DataValue": { "$id": "http://www.microsoft.com#UInt32DataValue", "title": "Dataset Field of Type UInt32", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "com.microsoft.BooleanDataValue": { "$id": "http://www.microsoft.com#BooleanDataValue", "title": "Dataset Field of Type Boolean", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Int32": { "$id": "http://opcfoundation.org/UA/#Int32", "title": "OPC UA built in type Int32", "type": "integer", "minimum": -2147483648, "maximum": 2147483647, "default": 0, "format": "int32" }, "com.microsoft.Int32DataValue": { "$id": "http://www.microsoft.com#Int32DataValue", "title": "Dataset Field of Type Int32", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Int32" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "com.microsoft.DoubleDataValue": { "$id": "http://www.microsoft.com#DoubleDataValue", "title": "Dataset Field of Type Double", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Number": { "$id": "http://opcfoundation.org/UA/#Number", "title": "OPC UA built in type Number", "type": "number" }, "com.microsoft.NumberDataValue": { "$id": "http://www.microsoft.com#NumberDataValue", "title": "Dataset Field of Type Number", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Number" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "com.microsoft.DataSet": { "$id": "http://www.microsoft.com#DataSet", "title": "DataSet", "type": "object", "properties": { "i=2258": { "$ref": "#/definitions/com.microsoft.DateTimeDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=StepUp": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean": { "$ref": "#/definitions/com.microsoft.BooleanDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32": { "$ref": "#/definitions/com.microsoft.Int32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData": { "$ref": "#/definitions/com.microsoft.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData": { "$ref": "#/definitions/com.microsoft.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData": { "$ref": "#/definitions/com.microsoft.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData": { "$ref": "#/definitions/com.microsoft.DoubleDataValue" }, "ns=23;i=1259": { "$ref": "#/definitions/com.microsoft.NumberDataValue" } } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/NetworkMessage/KeepAlive.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/com.microsoft.NetworkMessage", "definitions": { "org.opcfoundation.UA.ServerState": { "$id": "http://opcfoundation.org/UA/#ServerState", "title": "ServerState", "type": "integer", "enum": [ 0, 1, 2, 3, 4, 5, 6, 7 ], "format": "int32" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "com.microsoft.ServerStateDataValue": { "$id": "http://www.microsoft.com#ServerStateDataValue", "title": "Dataset Field of Type ServerState", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.ServerState" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "com.microsoft.DataSet": { "$id": "http://www.microsoft.com#DataSet", "title": "DataSet", "type": "object", "properties": { "State": { "$ref": "#/definitions/com.microsoft.ServerStateDataValue" } } }, "org.opcfoundation.UA.i_x61_14593": { "$id": "http://opcfoundation.org/UA/#i%3d14593", "type": "object", "properties": { "MajorVersion": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "MinorVersion": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" } } }, "com.microsoft.DataSetMessage": { "$id": "http://www.microsoft.com#DataSetMessage", "type": "object", "properties": { "MetaDataVersion": { "$ref": "#/definitions/org.opcfoundation.UA.i_x61_14593" }, "MessageType": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DataSetWriterName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Payload": { "$ref": "#/definitions/com.microsoft.DataSet" } }, "required": [ "MetaDataVersion", "MessageType", "DataSetWriterName", "Payload" ], "additionalProperties": false }, "org.opcfoundation.UA.Guid": { "$id": "http://opcfoundation.org/UA/#Guid", "title": "OPC UA built in type Guid", "type": "string", "format": "uuid" }, "com.microsoft.NetworkMessage": { "$id": "http://www.microsoft.com#NetworkMessage", "type": "null", "properties": { "MessageId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "MessageType": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "PublisherId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DataSetClassId": { "$ref": "#/definitions/org.opcfoundation.UA.Guid" }, "DataSetWriterGroup": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Messages": { "type": "array", "items": { "$ref": "#/definitions/com.microsoft.DataSetMessage" } } }, "required": [ "MessageId", "MessageType", "PublisherId", "DataSetClassId", "DataSetWriterGroup", "Messages" ], "additionalProperties": false } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/NetworkMessage/KeyFrames.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/com.microsoft.NetworkMessage", "definitions": { "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "com.microsoft.DateTimeDataValue": { "$id": "http://www.microsoft.com#DateTimeDataValue", "title": "Dataset Field of Type DateTime", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "com.microsoft.StringDataValue": { "$id": "http://www.microsoft.com#StringDataValue", "title": "Dataset Field of Type String", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Variant": { "title": "Any", "type": [ "number", "null", "object", "array", "string", "integer", "boolean" ] }, "com.microsoft.NumberDataValue": { "$id": "http://www.microsoft.com#NumberDataValue", "title": "Dataset Field of Type Number", "type": "object", "properties": { "Value": { "title": "Any", "type": [ "number", "null", "object", "array", "string", "integer", "boolean" ] }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "com.microsoft.BooleanDataValue": { "$id": "http://www.microsoft.com#BooleanDataValue", "title": "Dataset Field of Type Boolean", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Float": { "$id": "http://opcfoundation.org/UA/#Float", "title": "OPC UA built in type Float", "type": "number", "minimum": -3.4028235E+38, "maximum": 3.4028235E+38, "default": 0, "format": "float" }, "com.microsoft.FloatDataValue": { "$id": "http://www.microsoft.com#FloatDataValue", "title": "Dataset Field of Type Float", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Float" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "com.microsoft.DataSet": { "$id": "http://www.microsoft.com#DataSet", "title": "DataSet", "type": "object", "properties": { "CurrentTime": { "$ref": "#/definitions/com.microsoft.DateTimeDataValue" }, "EngineeringUnits": { "$ref": "#/definitions/com.microsoft.StringDataValue" }, "AssetId": { "$ref": "#/definitions/com.microsoft.NumberDataValue" }, "Important": { "$ref": "#/definitions/com.microsoft.BooleanDataValue" }, "Variance": { "$ref": "#/definitions/com.microsoft.FloatDataValue" } } }, "org.opcfoundation.UA.i_x61_14593": { "$id": "http://opcfoundation.org/UA/#i%3d14593", "type": "object", "properties": { "MajorVersion": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "MinorVersion": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" } } }, "com.microsoft.DataSetMessage": { "$id": "http://www.microsoft.com#DataSetMessage", "type": "object", "properties": { "MetaDataVersion": { "$ref": "#/definitions/org.opcfoundation.UA.i_x61_14593" }, "MessageType": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DataSetWriterName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Payload": { "$ref": "#/definitions/com.microsoft.DataSet" } }, "required": [ "MetaDataVersion", "MessageType", "DataSetWriterName", "Payload" ], "additionalProperties": false }, "org.opcfoundation.UA.Guid": { "$id": "http://opcfoundation.org/UA/#Guid", "title": "OPC UA built in type Guid", "type": "string", "format": "uuid" }, "com.microsoft.NetworkMessage": { "$id": "http://www.microsoft.com#NetworkMessage", "type": "null", "properties": { "MessageId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "MessageType": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "PublisherId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DataSetClassId": { "$ref": "#/definitions/org.opcfoundation.UA.Guid" }, "DataSetWriterGroup": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Messages": { "type": "array", "items": { "$ref": "#/definitions/com.microsoft.DataSetMessage" } } }, "required": [ "MessageId", "MessageType", "PublisherId", "DataSetClassId", "DataSetWriterGroup", "Messages" ], "additionalProperties": false } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/NetworkMessage/PendingAlarms.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/com.microsoft.DataSet", "definitions": { "org.opcfoundation.UA.NodeId": { "$id": "http://opcfoundation.org/UA/#NodeId", "title": "OPC UA built in type NodeId", "type": "string", "format": "opcuaNodeId" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "com.microsoft.NodeIdDataValue": { "$id": "http://www.microsoft.com#NodeIdDataValue", "title": "Dataset Field of Type NodeId", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.NodeId" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.LocalizedText": { "$id": "http://opcfoundation.org/UA/#LocalizedText", "title": "OPC UA built in type LocalizedText", "type": "string" }, "com.microsoft.LocalizedTextDataValue": { "$id": "http://www.microsoft.com#LocalizedTextDataValue", "title": "Dataset Field of Type LocalizedText", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "com.microsoft.NodeIdArrayDataValue": { "$id": "http://www.microsoft.com#NodeIdArrayDataValue", "title": "Dataset Field of Type NodeIdArray", "type": "object", "properties": { "Value": { "type": "array", "items": { "$ref": "#/definitions/org.opcfoundation.UA.NodeId" } }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "com.microsoft.LocalizedTextArrayDataValue": { "$id": "http://www.microsoft.com#LocalizedTextArrayDataValue", "title": "Dataset Field of Type LocalizedTextArray", "type": "object", "properties": { "Value": { "type": "array", "items": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" } }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.ByteString": { "$id": "http://opcfoundation.org/UA/#ByteString", "title": "OPC UA built in type ByteString", "type": "string", "format": "byte" }, "com.microsoft.ByteStringDataValue": { "$id": "http://www.microsoft.com#ByteStringDataValue", "title": "Dataset Field of Type ByteString", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.ByteString" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Int16": { "$id": "http://opcfoundation.org/UA/#Int16", "title": "OPC UA built in type Int16", "type": "integer", "minimum": -32768, "maximum": 32767, "default": 0, "format": "int16" }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.opcfoundation.UA.TimeZoneDataType": { "$id": "http://opcfoundation.org/UA/#TimeZoneDataType", "title": "TimeZoneDataType", "type": "object", "properties": { "Offset": { "$ref": "#/definitions/org.opcfoundation.UA.Int16" }, "DaylightSavingInOffset": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" } }, "required": [ "Offset", "DaylightSavingInOffset" ], "additionalProperties": false }, "com.microsoft.TimeZoneDataTypeDataValue": { "$id": "http://www.microsoft.com#TimeZoneDataTypeDataValue", "title": "Dataset Field of Type TimeZoneDataType", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.TimeZoneDataType" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "com.microsoft.DateTimeDataValue": { "$id": "http://www.microsoft.com#DateTimeDataValue", "title": "Dataset Field of Type DateTime", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "com.microsoft.UInt16DataValue": { "$id": "http://www.microsoft.com#UInt16DataValue", "title": "Dataset Field of Type UInt16", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "com.microsoft.StringDataValue": { "$id": "http://www.microsoft.com#StringDataValue", "title": "Dataset Field of Type String", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "com.microsoft.DataSet": { "$id": "http://www.microsoft.com#DataSet", "title": "DataSet", "type": "object", "properties": { "ConditionClassId": { "$ref": "#/definitions/com.microsoft.NodeIdDataValue" }, "ConditionClassName": { "$ref": "#/definitions/com.microsoft.LocalizedTextDataValue" }, "ConditionSubClassId": { "$ref": "#/definitions/com.microsoft.NodeIdArrayDataValue" }, "ConditionSubClassName": { "$ref": "#/definitions/com.microsoft.LocalizedTextArrayDataValue" }, "EventId": { "$ref": "#/definitions/com.microsoft.ByteStringDataValue" }, "EventType": { "$ref": "#/definitions/com.microsoft.NodeIdDataValue" }, "LocalTime": { "$ref": "#/definitions/com.microsoft.TimeZoneDataTypeDataValue" }, "Message": { "$ref": "#/definitions/com.microsoft.LocalizedTextDataValue" }, "ReceiveTime": { "$ref": "#/definitions/com.microsoft.DateTimeDataValue" }, "Severity": { "$ref": "#/definitions/com.microsoft.UInt16DataValue" }, "SourceName": { "$ref": "#/definitions/com.microsoft.StringDataValue" }, "SourceNode": { "$ref": "#/definitions/com.microsoft.NodeIdDataValue" }, "Time": { "$ref": "#/definitions/com.microsoft.DateTimeDataValue" } } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/NetworkMessage/PlcSimulation.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/com.microsoft.DataSets", "definitions": { "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "com.microsoft.UInt32DataValue": { "$id": "http://www.microsoft.com#UInt32DataValue", "title": "Dataset Field of Type UInt32", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "com.microsoft.BooleanDataValue": { "$id": "http://www.microsoft.com#BooleanDataValue", "title": "Dataset Field of Type Boolean", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Int32": { "$id": "http://opcfoundation.org/UA/#Int32", "title": "OPC UA built in type Int32", "type": "integer", "minimum": -2147483648, "maximum": 2147483647, "default": 0, "format": "int32" }, "com.microsoft.Int32DataValue": { "$id": "http://www.microsoft.com#Int32DataValue", "title": "Dataset Field of Type Int32", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Int32" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "com.microsoft.DoubleDataValue": { "$id": "http://www.microsoft.com#DoubleDataValue", "title": "Dataset Field of Type Double", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "com.microsoft.DataSet": { "$id": "http://www.microsoft.com#DataSet", "title": "DataSet", "type": "object", "properties": { "nsu=http://opcfoundation.org/UA/Plc/Applications;s=StepUp": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean": { "$ref": "#/definitions/com.microsoft.BooleanDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32": { "$ref": "#/definitions/com.microsoft.Int32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData": { "$ref": "#/definitions/com.microsoft.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData": { "$ref": "#/definitions/com.microsoft.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData": { "$ref": "#/definitions/com.microsoft.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData": { "$ref": "#/definitions/com.microsoft.DoubleDataValue" } } }, "com.microsoft.DataSet1": { "$id": "http://www.microsoft.com#DataSet1", "title": "DataSet1", "type": "object", "properties": { "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1": { "$ref": "#/definitions/com.microsoft.UInt32DataValue" } } }, "com.microsoft.DataSets": { "$id": "http://www.microsoft.com#DataSets", "type": "object", "oneOf": [ { "$ref": "#/definitions/com.microsoft.DataSet" }, { "$ref": "#/definitions/com.microsoft.DataSet1" } ] } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/NetworkMessage/SimpleEvents.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/com.microsoft.DataSet", "definitions": { "org.opcfoundation.UA.ByteString": { "$id": "http://opcfoundation.org/UA/#ByteString", "title": "OPC UA built in type ByteString", "type": "string", "format": "byte" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "com.microsoft.ByteStringDataValue": { "$id": "http://www.microsoft.com#ByteStringDataValue", "title": "Dataset Field of Type ByteString", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.ByteString" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.LocalizedText": { "$id": "http://opcfoundation.org/UA/#LocalizedText", "title": "OPC UA built in type LocalizedText", "type": "string" }, "com.microsoft.LocalizedTextDataValue": { "$id": "http://www.microsoft.com#LocalizedTextDataValue", "title": "Dataset Field of Type LocalizedText", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "com.microsoft.StringDataValue": { "$id": "http://www.microsoft.com#StringDataValue", "title": "Dataset Field of Type String", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "org.opcfoundation.SimpleEvents.CycleStepDataType": { "$id": "http://opcfoundation.org/SimpleEvents#CycleStepDataType", "title": "nsu=http://opcfoundation.org/SimpleEvents;CycleStepDataType", "type": "object", "properties": { "Name": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Duration": { "$ref": "#/definitions/org.opcfoundation.UA.Double" } }, "required": [ "Name", "Duration" ], "additionalProperties": false }, "com.microsoft.CycleStepDataTypeDataValue": { "$id": "http://www.microsoft.com#CycleStepDataTypeDataValue", "title": "Dataset Field of Type CycleStepDataType", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.SimpleEvents.CycleStepDataType" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "com.microsoft.DataSet": { "$id": "http://www.microsoft.com#DataSet", "title": "DataSet", "type": "object", "properties": { "EventId": { "$ref": "#/definitions/com.microsoft.ByteStringDataValue" }, "Message": { "$ref": "#/definitions/com.microsoft.LocalizedTextDataValue" }, "http://opcfoundation.org/SimpleEvents#CycleId": { "$ref": "#/definitions/com.microsoft.StringDataValue" }, "http://opcfoundation.org/SimpleEvents#CurrentStep": { "$ref": "#/definitions/com.microsoft.CycleStepDataTypeDataValue" } } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/NetworkMessageDefault/CyclicReads.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet", "definitions": { "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.DateTimeDataValue": { "$id": "http://github.org/microsoft/opcpublisher#DateTimeDataValue", "title": "Dataset Field of Type DateTime", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.UInt32DataValue": { "$id": "http://github.org/microsoft/opcpublisher#UInt32DataValue", "title": "Dataset Field of Type UInt32", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.github.microsoft.opcpublisher.BooleanDataValue": { "$id": "http://github.org/microsoft/opcpublisher#BooleanDataValue", "title": "Dataset Field of Type Boolean", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Int32": { "$id": "http://opcfoundation.org/UA/#Int32", "title": "OPC UA built in type Int32", "type": "integer", "minimum": -2147483648, "maximum": 2147483647, "default": 0, "format": "int32" }, "org.github.microsoft.opcpublisher.Int32DataValue": { "$id": "http://github.org/microsoft/opcpublisher#Int32DataValue", "title": "Dataset Field of Type Int32", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Int32" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "org.github.microsoft.opcpublisher.DoubleDataValue": { "$id": "http://github.org/microsoft/opcpublisher#DoubleDataValue", "title": "Dataset Field of Type Double", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Number": { "$id": "http://opcfoundation.org/UA/#Number", "title": "OPC UA built in type Number", "type": "number" }, "org.github.microsoft.opcpublisher.NumberDataValue": { "$id": "http://github.org/microsoft/opcpublisher#NumberDataValue", "title": "Dataset Field of Type Number", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Number" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "i=2258": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DateTimeDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=StepUp": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.BooleanDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.Int32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "ns=23;i=1259": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NumberDataValue" } } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/NetworkMessageDefault/KeepAlive.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.NetworkMessage", "definitions": { "org.opcfoundation.UA.ServerState": { "$id": "http://opcfoundation.org/UA/#ServerState", "title": "ServerState", "type": "integer", "enum": [ 0, 1, 2, 3, 4, 5, 6, 7 ], "format": "int32" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.ServerStateDataValue": { "$id": "http://github.org/microsoft/opcpublisher#ServerStateDataValue", "title": "Dataset Field of Type ServerState", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.ServerState" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "State": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.ServerStateDataValue" } } }, "org.opcfoundation.UA.i_x61_14593": { "$id": "http://opcfoundation.org/UA/#i%3d14593", "type": "object", "properties": { "MajorVersion": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "MinorVersion": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" } } }, "org.github.microsoft.opcpublisher.DataSetMessage": { "$id": "http://github.org/microsoft/opcpublisher#DataSetMessage", "type": "object", "properties": { "MetaDataVersion": { "$ref": "#/definitions/org.opcfoundation.UA.i_x61_14593" }, "MessageType": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DataSetWriterName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Payload": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet" } }, "required": [ "MetaDataVersion", "MessageType", "DataSetWriterName", "Payload" ], "additionalProperties": false }, "org.opcfoundation.UA.Guid": { "$id": "http://opcfoundation.org/UA/#Guid", "title": "OPC UA built in type Guid", "type": "string", "format": "uuid" }, "org.github.microsoft.opcpublisher.NetworkMessage": { "$id": "http://github.org/microsoft/opcpublisher#NetworkMessage", "type": "null", "properties": { "MessageId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "MessageType": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "PublisherId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DataSetClassId": { "$ref": "#/definitions/org.opcfoundation.UA.Guid" }, "DataSetWriterGroup": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Messages": { "type": "array", "items": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSetMessage" } } }, "required": [ "MessageId", "MessageType", "PublisherId", "DataSetClassId", "DataSetWriterGroup", "Messages" ], "additionalProperties": false } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/NetworkMessageDefault/KeyFrames.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.NetworkMessage", "definitions": { "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.DateTimeDataValue": { "$id": "http://github.org/microsoft/opcpublisher#DateTimeDataValue", "title": "Dataset Field of Type DateTime", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.StringDataValue": { "$id": "http://github.org/microsoft/opcpublisher#StringDataValue", "title": "Dataset Field of Type String", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Variant": { "title": "Any", "type": [ "number", "null", "object", "array", "string", "integer", "boolean" ] }, "org.github.microsoft.opcpublisher.NumberDataValue": { "$id": "http://github.org/microsoft/opcpublisher#NumberDataValue", "title": "Dataset Field of Type Number", "type": "object", "properties": { "Value": { "title": "Any", "type": [ "number", "null", "object", "array", "string", "integer", "boolean" ] }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.github.microsoft.opcpublisher.BooleanDataValue": { "$id": "http://github.org/microsoft/opcpublisher#BooleanDataValue", "title": "Dataset Field of Type Boolean", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Float": { "$id": "http://opcfoundation.org/UA/#Float", "title": "OPC UA built in type Float", "type": "number", "minimum": -3.4028235E+38, "maximum": 3.4028235E+38, "default": 0, "format": "float" }, "org.github.microsoft.opcpublisher.FloatDataValue": { "$id": "http://github.org/microsoft/opcpublisher#FloatDataValue", "title": "Dataset Field of Type Float", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Float" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "CurrentTime": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DateTimeDataValue" }, "EngineeringUnits": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.StringDataValue" }, "AssetId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NumberDataValue" }, "Important": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.BooleanDataValue" }, "Variance": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.FloatDataValue" } } }, "org.opcfoundation.UA.i_x61_14593": { "$id": "http://opcfoundation.org/UA/#i%3d14593", "type": "object", "properties": { "MajorVersion": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "MinorVersion": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" } } }, "org.github.microsoft.opcpublisher.DataSetMessage": { "$id": "http://github.org/microsoft/opcpublisher#DataSetMessage", "type": "object", "properties": { "MetaDataVersion": { "$ref": "#/definitions/org.opcfoundation.UA.i_x61_14593" }, "MessageType": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DataSetWriterName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Payload": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet" } }, "required": [ "MetaDataVersion", "MessageType", "DataSetWriterName", "Payload" ], "additionalProperties": false }, "org.opcfoundation.UA.Guid": { "$id": "http://opcfoundation.org/UA/#Guid", "title": "OPC UA built in type Guid", "type": "string", "format": "uuid" }, "org.github.microsoft.opcpublisher.NetworkMessage": { "$id": "http://github.org/microsoft/opcpublisher#NetworkMessage", "type": "null", "properties": { "MessageId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "MessageType": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "PublisherId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DataSetClassId": { "$ref": "#/definitions/org.opcfoundation.UA.Guid" }, "DataSetWriterGroup": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Messages": { "type": "array", "items": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSetMessage" } } }, "required": [ "MessageId", "MessageType", "PublisherId", "DataSetClassId", "DataSetWriterGroup", "Messages" ], "additionalProperties": false } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/NetworkMessageDefault/PendingAlarms.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet", "definitions": { "org.opcfoundation.UA.NodeId": { "$id": "http://opcfoundation.org/UA/#NodeId", "title": "OPC UA built in type NodeId", "type": "string", "format": "opcuaNodeId" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.NodeIdDataValue": { "$id": "http://github.org/microsoft/opcpublisher#NodeIdDataValue", "title": "Dataset Field of Type NodeId", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.NodeId" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.LocalizedText": { "$id": "http://opcfoundation.org/UA/#LocalizedText", "title": "OPC UA built in type LocalizedText", "type": "string" }, "org.github.microsoft.opcpublisher.LocalizedTextDataValue": { "$id": "http://github.org/microsoft/opcpublisher#LocalizedTextDataValue", "title": "Dataset Field of Type LocalizedText", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.NodeIdArrayDataValue": { "$id": "http://github.org/microsoft/opcpublisher#NodeIdArrayDataValue", "title": "Dataset Field of Type NodeIdArray", "type": "object", "properties": { "Value": { "type": "array", "items": { "$ref": "#/definitions/org.opcfoundation.UA.NodeId" } }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.LocalizedTextArrayDataValue": { "$id": "http://github.org/microsoft/opcpublisher#LocalizedTextArrayDataValue", "title": "Dataset Field of Type LocalizedTextArray", "type": "object", "properties": { "Value": { "type": "array", "items": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" } }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.ByteString": { "$id": "http://opcfoundation.org/UA/#ByteString", "title": "OPC UA built in type ByteString", "type": "string", "format": "byte" }, "org.github.microsoft.opcpublisher.ByteStringDataValue": { "$id": "http://github.org/microsoft/opcpublisher#ByteStringDataValue", "title": "Dataset Field of Type ByteString", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.ByteString" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Int16": { "$id": "http://opcfoundation.org/UA/#Int16", "title": "OPC UA built in type Int16", "type": "integer", "minimum": -32768, "maximum": 32767, "default": 0, "format": "int16" }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.opcfoundation.UA.TimeZoneDataType": { "$id": "http://opcfoundation.org/UA/#TimeZoneDataType", "title": "TimeZoneDataType", "type": "object", "properties": { "Offset": { "$ref": "#/definitions/org.opcfoundation.UA.Int16" }, "DaylightSavingInOffset": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" } }, "required": [ "Offset", "DaylightSavingInOffset" ], "additionalProperties": false }, "org.github.microsoft.opcpublisher.TimeZoneDataTypeDataValue": { "$id": "http://github.org/microsoft/opcpublisher#TimeZoneDataTypeDataValue", "title": "Dataset Field of Type TimeZoneDataType", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.TimeZoneDataType" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DateTimeDataValue": { "$id": "http://github.org/microsoft/opcpublisher#DateTimeDataValue", "title": "Dataset Field of Type DateTime", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.UInt16DataValue": { "$id": "http://github.org/microsoft/opcpublisher#UInt16DataValue", "title": "Dataset Field of Type UInt16", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.StringDataValue": { "$id": "http://github.org/microsoft/opcpublisher#StringDataValue", "title": "Dataset Field of Type String", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "ConditionClassId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NodeIdDataValue" }, "ConditionClassName": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.LocalizedTextDataValue" }, "ConditionSubClassId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NodeIdArrayDataValue" }, "ConditionSubClassName": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.LocalizedTextArrayDataValue" }, "EventId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.ByteStringDataValue" }, "EventType": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NodeIdDataValue" }, "LocalTime": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.TimeZoneDataTypeDataValue" }, "Message": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.LocalizedTextDataValue" }, "ReceiveTime": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DateTimeDataValue" }, "Severity": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt16DataValue" }, "SourceName": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.StringDataValue" }, "SourceNode": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NodeIdDataValue" }, "Time": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DateTimeDataValue" } } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/NetworkMessageDefault/PlcSimulation.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSets", "definitions": { "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.UInt32DataValue": { "$id": "http://github.org/microsoft/opcpublisher#UInt32DataValue", "title": "Dataset Field of Type UInt32", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.github.microsoft.opcpublisher.BooleanDataValue": { "$id": "http://github.org/microsoft/opcpublisher#BooleanDataValue", "title": "Dataset Field of Type Boolean", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Int32": { "$id": "http://opcfoundation.org/UA/#Int32", "title": "OPC UA built in type Int32", "type": "integer", "minimum": -2147483648, "maximum": 2147483647, "default": 0, "format": "int32" }, "org.github.microsoft.opcpublisher.Int32DataValue": { "$id": "http://github.org/microsoft/opcpublisher#Int32DataValue", "title": "Dataset Field of Type Int32", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Int32" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "org.github.microsoft.opcpublisher.DoubleDataValue": { "$id": "http://github.org/microsoft/opcpublisher#DoubleDataValue", "title": "Dataset Field of Type Double", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "nsu=http://opcfoundation.org/UA/Plc/Applications;s=StepUp": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.BooleanDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.Int32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" } } }, "org.github.microsoft.opcpublisher.DataSet1": { "$id": "http://github.org/microsoft/opcpublisher#DataSet1", "title": "DataSet1", "type": "object", "properties": { "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" } } }, "org.github.microsoft.opcpublisher.DataSets": { "$id": "http://github.org/microsoft/opcpublisher#DataSets", "type": "object", "oneOf": [ { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet1" } ] } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/NetworkMessageDefault/SimpleEvents.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet", "definitions": { "org.opcfoundation.UA.ByteString": { "$id": "http://opcfoundation.org/UA/#ByteString", "title": "OPC UA built in type ByteString", "type": "string", "format": "byte" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.ByteStringDataValue": { "$id": "http://github.org/microsoft/opcpublisher#ByteStringDataValue", "title": "Dataset Field of Type ByteString", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.ByteString" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.LocalizedText": { "$id": "http://opcfoundation.org/UA/#LocalizedText", "title": "OPC UA built in type LocalizedText", "type": "string" }, "org.github.microsoft.opcpublisher.LocalizedTextDataValue": { "$id": "http://github.org/microsoft/opcpublisher#LocalizedTextDataValue", "title": "Dataset Field of Type LocalizedText", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.StringDataValue": { "$id": "http://github.org/microsoft/opcpublisher#StringDataValue", "title": "Dataset Field of Type String", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "org.opcfoundation.SimpleEvents.CycleStepDataType": { "$id": "http://opcfoundation.org/SimpleEvents#CycleStepDataType", "title": "nsu=http://opcfoundation.org/SimpleEvents;CycleStepDataType", "type": "object", "properties": { "Name": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Duration": { "$ref": "#/definitions/org.opcfoundation.UA.Double" } }, "required": [ "Name", "Duration" ], "additionalProperties": false }, "org.github.microsoft.opcpublisher.CycleStepDataTypeDataValue": { "$id": "http://github.org/microsoft/opcpublisher#CycleStepDataTypeDataValue", "title": "Dataset Field of Type CycleStepDataType", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.SimpleEvents.CycleStepDataType" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "EventId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.ByteStringDataValue" }, "Message": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.LocalizedTextDataValue" }, "http://opcfoundation.org/SimpleEvents#CycleId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.StringDataValue" }, "http://opcfoundation.org/SimpleEvents#CurrentStep": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.CycleStepDataTypeDataValue" } } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Raw/CyclicReads.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet", "definitions": { "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.opcfoundation.UA.Int32": { "$id": "http://opcfoundation.org/UA/#Int32", "title": "OPC UA built in type Int32", "type": "integer", "minimum": -2147483648, "maximum": 2147483647, "default": 0, "format": "int32" }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "org.opcfoundation.UA.Number": { "$id": "http://opcfoundation.org/UA/#Number", "title": "OPC UA built in type Number", "type": "number" }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "i=2258": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=StepUp": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32": { "$ref": "#/definitions/org.opcfoundation.UA.Int32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "ns=23;i=1259": { "$ref": "#/definitions/org.opcfoundation.UA.Number" } } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Raw/KeepAlive.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet", "definitions": { "org.opcfoundation.UA.ServerState": { "$id": "http://opcfoundation.org/UA/#ServerState", "title": "ServerState", "type": "integer", "enum": [ 0, 1, 2, 3, 4, 5, 6, 7 ], "format": "int32" }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "State": { "$ref": "#/definitions/org.opcfoundation.UA.ServerState" } } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Raw/KeyFrames.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet", "definitions": { "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.Variant": { "title": "Any", "type": [ "number", "null", "object", "array", "string", "integer", "boolean" ] }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.opcfoundation.UA.Float": { "$id": "http://opcfoundation.org/UA/#Float", "title": "OPC UA built in type Float", "type": "number", "minimum": -3.4028235E+38, "maximum": 3.4028235E+38, "default": 0, "format": "float" }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "CurrentTime": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "EngineeringUnits": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "AssetId": { "title": "Any", "type": [ "number", "null", "object", "array", "string", "integer", "boolean" ] }, "Important": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" }, "Variance": { "$ref": "#/definitions/org.opcfoundation.UA.Float" } } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Raw/PendingAlarms.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet", "definitions": { "org.opcfoundation.UA.NodeId": { "$id": "http://opcfoundation.org/UA/#NodeId", "title": "OPC UA built in type NodeId", "type": "string", "format": "opcuaNodeId" }, "org.opcfoundation.UA.LocalizedText": { "$id": "http://opcfoundation.org/UA/#LocalizedText", "title": "OPC UA built in type LocalizedText", "type": "string" }, "org.opcfoundation.UA.ByteString": { "$id": "http://opcfoundation.org/UA/#ByteString", "title": "OPC UA built in type ByteString", "type": "string", "format": "byte" }, "org.opcfoundation.UA.Int16": { "$id": "http://opcfoundation.org/UA/#Int16", "title": "OPC UA built in type Int16", "type": "integer", "minimum": -32768, "maximum": 32767, "default": 0, "format": "int16" }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.opcfoundation.UA.TimeZoneDataType": { "$id": "http://opcfoundation.org/UA/#TimeZoneDataType", "title": "TimeZoneDataType", "type": "object", "properties": { "Offset": { "$ref": "#/definitions/org.opcfoundation.UA.Int16" }, "DaylightSavingInOffset": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" } }, "required": [ "Offset", "DaylightSavingInOffset" ], "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "ConditionClassId": { "$ref": "#/definitions/org.opcfoundation.UA.NodeId" }, "ConditionClassName": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" }, "ConditionSubClassId": { "type": "array", "items": { "$ref": "#/definitions/org.opcfoundation.UA.NodeId" } }, "ConditionSubClassName": { "type": "array", "items": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" } }, "EventId": { "$ref": "#/definitions/org.opcfoundation.UA.ByteString" }, "EventType": { "$ref": "#/definitions/org.opcfoundation.UA.NodeId" }, "LocalTime": { "$ref": "#/definitions/org.opcfoundation.UA.TimeZoneDataType" }, "Message": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" }, "ReceiveTime": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Severity": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "SourceName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "SourceNode": { "$ref": "#/definitions/org.opcfoundation.UA.NodeId" }, "Time": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" } } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Raw/PlcSimulation.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSets", "definitions": { "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.opcfoundation.UA.Int32": { "$id": "http://opcfoundation.org/UA/#Int32", "title": "OPC UA built in type Int32", "type": "integer", "minimum": -2147483648, "maximum": 2147483647, "default": 0, "format": "int32" }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "nsu=http://opcfoundation.org/UA/Plc/Applications;s=StepUp": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32": { "$ref": "#/definitions/org.opcfoundation.UA.Int32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData": { "$ref": "#/definitions/org.opcfoundation.UA.Double" } } }, "org.github.microsoft.opcpublisher.DataSet1": { "$id": "http://github.org/microsoft/opcpublisher#DataSet1", "title": "DataSet1", "type": "object", "properties": { "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" } } }, "org.github.microsoft.opcpublisher.DataSets": { "$id": "http://github.org/microsoft/opcpublisher#DataSets", "type": "object", "oneOf": [ { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet1" } ] } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Raw/SimpleEvents.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet", "definitions": { "org.opcfoundation.UA.ByteString": { "$id": "http://opcfoundation.org/UA/#ByteString", "title": "OPC UA built in type ByteString", "type": "string", "format": "byte" }, "org.opcfoundation.UA.LocalizedText": { "$id": "http://opcfoundation.org/UA/#LocalizedText", "title": "OPC UA built in type LocalizedText", "type": "string" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "org.opcfoundation.SimpleEvents.CycleStepDataType": { "$id": "http://opcfoundation.org/SimpleEvents#CycleStepDataType", "title": "nsu=http://opcfoundation.org/SimpleEvents;CycleStepDataType", "type": "object", "properties": { "Name": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Duration": { "$ref": "#/definitions/org.opcfoundation.UA.Double" } }, "required": [ "Name", "Duration" ], "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "EventId": { "$ref": "#/definitions/org.opcfoundation.UA.ByteString" }, "Message": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" }, "http://opcfoundation.org/SimpleEvents#CycleId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "http://opcfoundation.org/SimpleEvents#CurrentStep": { "$ref": "#/definitions/org.opcfoundation.SimpleEvents.CycleStepDataType" } } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/RawReversible/CyclicReads.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet", "definitions": { "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.github.microsoft.opcpublisher.DateTimeVariant": { "$id": "http://github.org/microsoft/opcpublisher#DateTimeVariant", "title": "Variant Field of Type DateTime", "type": "object", "properties": { "Type": { "type": "integer", "const": 13 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" } }, "additionalProperties": false }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.github.microsoft.opcpublisher.UInt32Variant": { "$id": "http://github.org/microsoft/opcpublisher#UInt32Variant", "title": "Variant Field of Type UInt32", "type": "object", "properties": { "Type": { "type": "integer", "const": 7 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" } }, "additionalProperties": false }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.github.microsoft.opcpublisher.BooleanVariant": { "$id": "http://github.org/microsoft/opcpublisher#BooleanVariant", "title": "Variant Field of Type Boolean", "type": "object", "properties": { "Type": { "type": "integer", "const": 1 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" } }, "additionalProperties": false }, "org.opcfoundation.UA.Int32": { "$id": "http://opcfoundation.org/UA/#Int32", "title": "OPC UA built in type Int32", "type": "integer", "minimum": -2147483648, "maximum": 2147483647, "default": 0, "format": "int32" }, "org.github.microsoft.opcpublisher.Int32Variant": { "$id": "http://github.org/microsoft/opcpublisher#Int32Variant", "title": "Variant Field of Type Int32", "type": "object", "properties": { "Type": { "type": "integer", "const": 6 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.Int32" } }, "additionalProperties": false }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "org.github.microsoft.opcpublisher.DoubleVariant": { "$id": "http://github.org/microsoft/opcpublisher#DoubleVariant", "title": "Variant Field of Type Double", "type": "object", "properties": { "Type": { "type": "integer", "const": 11 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.Double" } }, "additionalProperties": false }, "org.opcfoundation.UA.Number": { "$id": "http://opcfoundation.org/UA/#Number", "title": "OPC UA built in type Number", "type": "number" }, "org.github.microsoft.opcpublisher.NumberVariant": { "$id": "http://github.org/microsoft/opcpublisher#NumberVariant", "title": "Variant Field of Type Number", "type": "object", "properties": { "Type": { "type": "integer", "const": 26 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.Number" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "i=2258": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DateTimeVariant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=StepUp": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.BooleanVariant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.Int32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleVariant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleVariant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleVariant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleVariant" }, "ns=23;i=1259": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NumberVariant" } } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/RawReversible/KeepAlive.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet", "definitions": { "org.opcfoundation.UA.ServerState": { "$id": "http://opcfoundation.org/UA/#ServerState", "title": "ServerState", "type": "integer", "enum": [ 0, 1, 2, 3, 4, 5, 6, 7 ], "format": "int32" }, "org.github.microsoft.opcpublisher.ServerStateVariant": { "$id": "http://github.org/microsoft/opcpublisher#ServerStateVariant", "title": "Variant Field of Type ServerState", "type": "object", "properties": { "Type": { "type": "integer", "const": 29 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.ServerState" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "State": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.ServerStateVariant" } } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/RawReversible/KeyFrames.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet", "definitions": { "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.github.microsoft.opcpublisher.DateTimeVariant": { "$id": "http://github.org/microsoft/opcpublisher#DateTimeVariant", "title": "Variant Field of Type DateTime", "type": "object", "properties": { "Type": { "type": "integer", "const": 13 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" } }, "additionalProperties": false }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.github.microsoft.opcpublisher.StringVariant": { "$id": "http://github.org/microsoft/opcpublisher#StringVariant", "title": "Variant Field of Type String", "type": "object", "properties": { "Type": { "type": "integer", "const": 12 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.Byte": { "$id": "http://opcfoundation.org/UA/#Byte", "title": "OPC UA built in type Byte", "type": "integer", "minimum": 0, "maximum": 255, "default": 0, "format": "byte" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.Variant": { "$id": "http://opcfoundation.org/UA/#Variant", "title": "OPC UA built in type Variant", "type": "object", "properties": { "Type": { "$ref": "#/definitions/org.opcfoundation.UA.Byte" }, "Body": { "title": "Any", "type": [ "number", "null", "object", "array", "string", "integer", "boolean" ] }, "Dimensions": { "type": "array", "items": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" } } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.VariantVariant": { "$id": "http://github.org/microsoft/opcpublisher#VariantVariant", "title": "Variant Field of Type Variant", "type": "object", "properties": { "Type": { "type": "integer", "const": 24 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.Variant" } }, "additionalProperties": false }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.github.microsoft.opcpublisher.BooleanVariant": { "$id": "http://github.org/microsoft/opcpublisher#BooleanVariant", "title": "Variant Field of Type Boolean", "type": "object", "properties": { "Type": { "type": "integer", "const": 1 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" } }, "additionalProperties": false }, "org.opcfoundation.UA.Float": { "$id": "http://opcfoundation.org/UA/#Float", "title": "OPC UA built in type Float", "type": "number", "minimum": -3.4028235E+38, "maximum": 3.4028235E+38, "default": 0, "format": "float" }, "org.github.microsoft.opcpublisher.FloatVariant": { "$id": "http://github.org/microsoft/opcpublisher#FloatVariant", "title": "Variant Field of Type Float", "type": "object", "properties": { "Type": { "type": "integer", "const": 10 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.Float" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "CurrentTime": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DateTimeVariant" }, "EngineeringUnits": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.StringVariant" }, "AssetId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.VariantVariant" }, "Important": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.BooleanVariant" }, "Variance": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.FloatVariant" } } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/RawReversible/PendingAlarms.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet", "definitions": { "org.opcfoundation.UA.NodeId": { "$id": "http://opcfoundation.org/UA/#NodeId", "title": "OPC UA built in type NodeId", "type": "string", "format": "opcuaNodeId" }, "org.github.microsoft.opcpublisher.NodeIdVariant": { "$id": "http://github.org/microsoft/opcpublisher#NodeIdVariant", "title": "Variant Field of Type NodeId", "type": "object", "properties": { "Type": { "type": "integer", "const": 17 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.NodeId" } }, "additionalProperties": false }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.LocalizedText": { "$id": "http://opcfoundation.org/UA/#LocalizedText", "title": "OPC UA built in type LocalizedText", "type": "object", "properties": { "Locale": { "title": "OPC UA built in type String", "type": "string", "format": "rfc3066" }, "Text": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.LocalizedTextVariant": { "$id": "http://github.org/microsoft/opcpublisher#LocalizedTextVariant", "title": "Variant Field of Type LocalizedText", "type": "object", "properties": { "Type": { "type": "integer", "const": 21 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.NodeIdArrayVariant": { "$id": "http://github.org/microsoft/opcpublisher#NodeIdArrayVariant", "title": "Variant Field of Type NodeIdArray", "type": "object", "properties": { "Type": { "type": "integer", "const": 17 }, "Body": { "type": "array", "items": { "$ref": "#/definitions/org.opcfoundation.UA.NodeId" } } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.LocalizedTextArrayVariant": { "$id": "http://github.org/microsoft/opcpublisher#LocalizedTextArrayVariant", "title": "Variant Field of Type LocalizedTextArray", "type": "object", "properties": { "Type": { "type": "integer", "const": 21 }, "Body": { "type": "array", "items": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" } } }, "additionalProperties": false }, "org.opcfoundation.UA.ByteString": { "$id": "http://opcfoundation.org/UA/#ByteString", "title": "OPC UA built in type ByteString", "type": "string", "format": "byte" }, "org.github.microsoft.opcpublisher.ByteStringVariant": { "$id": "http://github.org/microsoft/opcpublisher#ByteStringVariant", "title": "Variant Field of Type ByteString", "type": "object", "properties": { "Type": { "type": "integer", "const": 15 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.ByteString" } }, "additionalProperties": false }, "org.opcfoundation.UA.Int16": { "$id": "http://opcfoundation.org/UA/#Int16", "title": "OPC UA built in type Int16", "type": "integer", "minimum": -32768, "maximum": 32767, "default": 0, "format": "int16" }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.opcfoundation.UA.TimeZoneDataType": { "$id": "http://opcfoundation.org/UA/#TimeZoneDataType", "title": "TimeZoneDataType", "type": "object", "properties": { "Offset": { "$ref": "#/definitions/org.opcfoundation.UA.Int16" }, "DaylightSavingInOffset": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" } }, "required": [ "Offset", "DaylightSavingInOffset" ], "additionalProperties": false }, "org.github.microsoft.opcpublisher.TimeZoneDataTypeVariant": { "$id": "http://github.org/microsoft/opcpublisher#TimeZoneDataTypeVariant", "title": "Variant Field of Type TimeZoneDataType", "type": "object", "properties": { "Type": { "type": "integer", "const": 22 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.TimeZoneDataType" } }, "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.github.microsoft.opcpublisher.DateTimeVariant": { "$id": "http://github.org/microsoft/opcpublisher#DateTimeVariant", "title": "Variant Field of Type DateTime", "type": "object", "properties": { "Type": { "type": "integer", "const": 13 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" } }, "additionalProperties": false }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.UInt16Variant": { "$id": "http://github.org/microsoft/opcpublisher#UInt16Variant", "title": "Variant Field of Type UInt16", "type": "object", "properties": { "Type": { "type": "integer", "const": 5 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.StringVariant": { "$id": "http://github.org/microsoft/opcpublisher#StringVariant", "title": "Variant Field of Type String", "type": "object", "properties": { "Type": { "type": "integer", "const": 12 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "ConditionClassId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NodeIdVariant" }, "ConditionClassName": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.LocalizedTextVariant" }, "ConditionSubClassId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NodeIdArrayVariant" }, "ConditionSubClassName": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.LocalizedTextArrayVariant" }, "EventId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.ByteStringVariant" }, "EventType": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NodeIdVariant" }, "LocalTime": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.TimeZoneDataTypeVariant" }, "Message": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.LocalizedTextVariant" }, "ReceiveTime": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DateTimeVariant" }, "Severity": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt16Variant" }, "SourceName": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.StringVariant" }, "SourceNode": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NodeIdVariant" }, "Time": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DateTimeVariant" } } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/RawReversible/PlcSimulation.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSets", "definitions": { "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.github.microsoft.opcpublisher.UInt32Variant": { "$id": "http://github.org/microsoft/opcpublisher#UInt32Variant", "title": "Variant Field of Type UInt32", "type": "object", "properties": { "Type": { "type": "integer", "const": 7 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" } }, "additionalProperties": false }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.github.microsoft.opcpublisher.BooleanVariant": { "$id": "http://github.org/microsoft/opcpublisher#BooleanVariant", "title": "Variant Field of Type Boolean", "type": "object", "properties": { "Type": { "type": "integer", "const": 1 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" } }, "additionalProperties": false }, "org.opcfoundation.UA.Int32": { "$id": "http://opcfoundation.org/UA/#Int32", "title": "OPC UA built in type Int32", "type": "integer", "minimum": -2147483648, "maximum": 2147483647, "default": 0, "format": "int32" }, "org.github.microsoft.opcpublisher.Int32Variant": { "$id": "http://github.org/microsoft/opcpublisher#Int32Variant", "title": "Variant Field of Type Int32", "type": "object", "properties": { "Type": { "type": "integer", "const": 6 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.Int32" } }, "additionalProperties": false }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "org.github.microsoft.opcpublisher.DoubleVariant": { "$id": "http://github.org/microsoft/opcpublisher#DoubleVariant", "title": "Variant Field of Type Double", "type": "object", "properties": { "Type": { "type": "integer", "const": 11 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.Double" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "nsu=http://opcfoundation.org/UA/Plc/Applications;s=StepUp": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.BooleanVariant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.Int32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleVariant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleVariant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleVariant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleVariant" } } }, "org.github.microsoft.opcpublisher.DataSet1": { "$id": "http://github.org/microsoft/opcpublisher#DataSet1", "title": "DataSet1", "type": "object", "properties": { "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32Variant" } } }, "org.github.microsoft.opcpublisher.DataSets": { "$id": "http://github.org/microsoft/opcpublisher#DataSets", "type": "object", "oneOf": [ { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet1" } ] } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/RawReversible/SimpleEvents.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet", "definitions": { "org.opcfoundation.UA.ByteString": { "$id": "http://opcfoundation.org/UA/#ByteString", "title": "OPC UA built in type ByteString", "type": "string", "format": "byte" }, "org.github.microsoft.opcpublisher.ByteStringVariant": { "$id": "http://github.org/microsoft/opcpublisher#ByteStringVariant", "title": "Variant Field of Type ByteString", "type": "object", "properties": { "Type": { "type": "integer", "const": 15 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.ByteString" } }, "additionalProperties": false }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.LocalizedText": { "$id": "http://opcfoundation.org/UA/#LocalizedText", "title": "OPC UA built in type LocalizedText", "type": "object", "properties": { "Locale": { "title": "OPC UA built in type String", "type": "string", "format": "rfc3066" }, "Text": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.LocalizedTextVariant": { "$id": "http://github.org/microsoft/opcpublisher#LocalizedTextVariant", "title": "Variant Field of Type LocalizedText", "type": "object", "properties": { "Type": { "type": "integer", "const": 21 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.StringVariant": { "$id": "http://github.org/microsoft/opcpublisher#StringVariant", "title": "Variant Field of Type String", "type": "object", "properties": { "Type": { "type": "integer", "const": 12 }, "Body": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "org.opcfoundation.SimpleEvents.CycleStepDataType": { "$id": "http://opcfoundation.org/SimpleEvents#CycleStepDataType", "title": "nsu=http://opcfoundation.org/SimpleEvents;CycleStepDataType", "type": "object", "properties": { "Name": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Duration": { "$ref": "#/definitions/org.opcfoundation.UA.Double" } }, "required": [ "Name", "Duration" ], "additionalProperties": false }, "org.github.microsoft.opcpublisher.CycleStepDataTypeVariant": { "$id": "http://github.org/microsoft/opcpublisher#CycleStepDataTypeVariant", "title": "Variant Field of Type CycleStepDataType", "type": "object", "properties": { "Type": { "type": "integer", "const": 22 }, "Body": { "$ref": "#/definitions/org.opcfoundation.SimpleEvents.CycleStepDataType" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "EventId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.ByteStringVariant" }, "Message": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.LocalizedTextVariant" }, "http://opcfoundation.org/SimpleEvents#CycleId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.StringVariant" }, "http://opcfoundation.org/SimpleEvents#CurrentStep": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.CycleStepDataTypeVariant" } } } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Samples/CyclicReads.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessages", "definitions": { "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.DateTimeDataValue": { "$id": "http://github.org/microsoft/opcpublisher#DateTimeDataValue", "title": "Dataset Field of Type DateTime", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.UInt32DataValue": { "$id": "http://github.org/microsoft/opcpublisher#UInt32DataValue", "title": "Dataset Field of Type UInt32", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.github.microsoft.opcpublisher.BooleanDataValue": { "$id": "http://github.org/microsoft/opcpublisher#BooleanDataValue", "title": "Dataset Field of Type Boolean", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Int32": { "$id": "http://opcfoundation.org/UA/#Int32", "title": "OPC UA built in type Int32", "type": "integer", "minimum": -2147483648, "maximum": 2147483647, "default": 0, "format": "int32" }, "org.github.microsoft.opcpublisher.Int32DataValue": { "$id": "http://github.org/microsoft/opcpublisher#Int32DataValue", "title": "Dataset Field of Type Int32", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Int32" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "org.github.microsoft.opcpublisher.DoubleDataValue": { "$id": "http://github.org/microsoft/opcpublisher#DoubleDataValue", "title": "Dataset Field of Type Double", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Number": { "$id": "http://opcfoundation.org/UA/#Number", "title": "OPC UA built in type Number", "type": "number" }, "org.github.microsoft.opcpublisher.NumberDataValue": { "$id": "http://github.org/microsoft/opcpublisher#NumberDataValue", "title": "Dataset Field of Type Number", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Number" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage1": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage1", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DateTimeDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage2": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage2", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage3": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage3", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.BooleanDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage4": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage4", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.Int32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage5": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage5", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage6": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage6", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage7": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage7", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage8": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage8", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage9": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage9", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage10": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage10", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage11": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage11", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage12": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage12", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage13": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage13", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage14": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage14", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage15": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage15", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage16": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage16", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage17": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage17", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage18": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage18", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage19": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage19", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage20": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage20", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage21": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage21", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage22": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage22", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage23": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage23", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage24": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage24", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NumberDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessages": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessages", "type": "object", "oneOf": [ { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage1" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage2" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage3" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage4" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage5" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage6" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage7" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage8" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage9" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage10" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage11" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage12" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage13" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage14" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage15" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage16" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage17" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage18" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage19" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage20" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage21" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage22" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage23" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage24" } ] } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Samples/KeepAlive.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessages", "definitions": { "org.opcfoundation.UA.ServerState": { "$id": "http://opcfoundation.org/UA/#ServerState", "title": "ServerState", "type": "integer", "enum": [ 0, 1, 2, 3, 4, 5, 6, 7 ], "format": "int32" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.ServerStateDataValue": { "$id": "http://github.org/microsoft/opcpublisher#ServerStateDataValue", "title": "Dataset Field of Type ServerState", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.ServerState" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage1": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage1", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.ServerStateDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessages": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessages", "type": "object", "oneOf": [ { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage1" } ] } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Samples/KeyFrames.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessages", "definitions": { "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.DateTimeDataValue": { "$id": "http://github.org/microsoft/opcpublisher#DateTimeDataValue", "title": "Dataset Field of Type DateTime", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.StringDataValue": { "$id": "http://github.org/microsoft/opcpublisher#StringDataValue", "title": "Dataset Field of Type String", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Variant": { "title": "Any", "type": [ "number", "null", "object", "array", "string", "integer", "boolean" ] }, "org.github.microsoft.opcpublisher.NumberDataValue": { "$id": "http://github.org/microsoft/opcpublisher#NumberDataValue", "title": "Dataset Field of Type Number", "type": "object", "properties": { "Value": { "title": "Any", "type": [ "number", "null", "object", "array", "string", "integer", "boolean" ] }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.github.microsoft.opcpublisher.BooleanDataValue": { "$id": "http://github.org/microsoft/opcpublisher#BooleanDataValue", "title": "Dataset Field of Type Boolean", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Float": { "$id": "http://opcfoundation.org/UA/#Float", "title": "OPC UA built in type Float", "type": "number", "minimum": -3.4028235E+38, "maximum": 3.4028235E+38, "default": 0, "format": "float" }, "org.github.microsoft.opcpublisher.FloatDataValue": { "$id": "http://github.org/microsoft/opcpublisher#FloatDataValue", "title": "Dataset Field of Type Float", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Float" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage1": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage1", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DateTimeDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage2": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage2", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.StringDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage3": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage3", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NumberDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage4": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage4", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.BooleanDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage5": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage5", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.FloatDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessages": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessages", "type": "object", "oneOf": [ { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage1" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage2" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage3" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage4" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage5" } ] } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Samples/PendingAlarms.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessages", "definitions": { "org.opcfoundation.UA.NodeId": { "$id": "http://opcfoundation.org/UA/#NodeId", "title": "OPC UA built in type NodeId", "type": "string", "format": "opcuaNodeId" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.NodeIdDataValue": { "$id": "http://github.org/microsoft/opcpublisher#NodeIdDataValue", "title": "Dataset Field of Type NodeId", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.NodeId" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.LocalizedText": { "$id": "http://opcfoundation.org/UA/#LocalizedText", "title": "OPC UA built in type LocalizedText", "type": "string" }, "org.github.microsoft.opcpublisher.LocalizedTextDataValue": { "$id": "http://github.org/microsoft/opcpublisher#LocalizedTextDataValue", "title": "Dataset Field of Type LocalizedText", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.NodeIdArrayDataValue": { "$id": "http://github.org/microsoft/opcpublisher#NodeIdArrayDataValue", "title": "Dataset Field of Type NodeIdArray", "type": "object", "properties": { "Value": { "type": "array", "items": { "$ref": "#/definitions/org.opcfoundation.UA.NodeId" } }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.LocalizedTextArrayDataValue": { "$id": "http://github.org/microsoft/opcpublisher#LocalizedTextArrayDataValue", "title": "Dataset Field of Type LocalizedTextArray", "type": "object", "properties": { "Value": { "type": "array", "items": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" } }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.ByteString": { "$id": "http://opcfoundation.org/UA/#ByteString", "title": "OPC UA built in type ByteString", "type": "string", "format": "byte" }, "org.github.microsoft.opcpublisher.ByteStringDataValue": { "$id": "http://github.org/microsoft/opcpublisher#ByteStringDataValue", "title": "Dataset Field of Type ByteString", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.ByteString" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Int16": { "$id": "http://opcfoundation.org/UA/#Int16", "title": "OPC UA built in type Int16", "type": "integer", "minimum": -32768, "maximum": 32767, "default": 0, "format": "int16" }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.opcfoundation.UA.TimeZoneDataType": { "$id": "http://opcfoundation.org/UA/#TimeZoneDataType", "title": "TimeZoneDataType", "type": "object", "properties": { "Offset": { "$ref": "#/definitions/org.opcfoundation.UA.Int16" }, "DaylightSavingInOffset": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" } }, "required": [ "Offset", "DaylightSavingInOffset" ], "additionalProperties": false }, "org.github.microsoft.opcpublisher.TimeZoneDataTypeDataValue": { "$id": "http://github.org/microsoft/opcpublisher#TimeZoneDataTypeDataValue", "title": "Dataset Field of Type TimeZoneDataType", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.TimeZoneDataType" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DateTimeDataValue": { "$id": "http://github.org/microsoft/opcpublisher#DateTimeDataValue", "title": "Dataset Field of Type DateTime", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.UInt16DataValue": { "$id": "http://github.org/microsoft/opcpublisher#UInt16DataValue", "title": "Dataset Field of Type UInt16", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.StringDataValue": { "$id": "http://github.org/microsoft/opcpublisher#StringDataValue", "title": "Dataset Field of Type String", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage1": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage1", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NodeIdDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage2": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage2", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.LocalizedTextDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage3": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage3", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NodeIdArrayDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage4": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage4", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.LocalizedTextArrayDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage5": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage5", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.ByteStringDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage6": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage6", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NodeIdDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage7": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage7", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.TimeZoneDataTypeDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage8": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage8", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.LocalizedTextDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage9": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage9", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DateTimeDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage10": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage10", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt16DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage11": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage11", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.StringDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage12": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage12", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NodeIdDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage13": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage13", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DateTimeDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessages": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessages", "type": "object", "oneOf": [ { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage1" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage2" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage3" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage4" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage5" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage6" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage7" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage8" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage9" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage10" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage11" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage12" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage13" } ] } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Samples/PlcSimulation.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessages", "definitions": { "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.UInt32DataValue": { "$id": "http://github.org/microsoft/opcpublisher#UInt32DataValue", "title": "Dataset Field of Type UInt32", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.github.microsoft.opcpublisher.BooleanDataValue": { "$id": "http://github.org/microsoft/opcpublisher#BooleanDataValue", "title": "Dataset Field of Type Boolean", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Int32": { "$id": "http://opcfoundation.org/UA/#Int32", "title": "OPC UA built in type Int32", "type": "integer", "minimum": -2147483648, "maximum": 2147483647, "default": 0, "format": "int32" }, "org.github.microsoft.opcpublisher.Int32DataValue": { "$id": "http://github.org/microsoft/opcpublisher#Int32DataValue", "title": "Dataset Field of Type Int32", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Int32" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "org.github.microsoft.opcpublisher.DoubleDataValue": { "$id": "http://github.org/microsoft/opcpublisher#DoubleDataValue", "title": "Dataset Field of Type Double", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage1": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage1", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage2": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage2", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.BooleanDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage3": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage3", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.Int32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage4": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage4", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage5": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage5", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage6": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage6", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage7": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage7", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage8": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage8", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage9": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage9", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage10": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage10", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage11": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage11", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage12": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage12", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage13": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage13", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage14": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage14", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage16": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage16", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage17": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage17", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage18": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage18", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage19": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage19", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage20": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage20", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage21": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage21", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage22": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage22", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage23": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage23", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessages": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessages", "type": "object", "oneOf": [ { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage1" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage2" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage3" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage4" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage5" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage6" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage7" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage8" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage9" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage10" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage11" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage12" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage13" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage14" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage16" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage17" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage18" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage19" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage20" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage21" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage22" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage23" } ] } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Samples/SimpleEvents.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessages", "definitions": { "org.opcfoundation.UA.ByteString": { "$id": "http://opcfoundation.org/UA/#ByteString", "title": "OPC UA built in type ByteString", "type": "string", "format": "byte" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.ByteStringDataValue": { "$id": "http://github.org/microsoft/opcpublisher#ByteStringDataValue", "title": "Dataset Field of Type ByteString", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.ByteString" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.LocalizedText": { "$id": "http://opcfoundation.org/UA/#LocalizedText", "title": "OPC UA built in type LocalizedText", "type": "string" }, "org.github.microsoft.opcpublisher.LocalizedTextDataValue": { "$id": "http://github.org/microsoft/opcpublisher#LocalizedTextDataValue", "title": "Dataset Field of Type LocalizedText", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.StringDataValue": { "$id": "http://github.org/microsoft/opcpublisher#StringDataValue", "title": "Dataset Field of Type String", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "org.opcfoundation.SimpleEvents.CycleStepDataType": { "$id": "http://opcfoundation.org/SimpleEvents#CycleStepDataType", "title": "nsu=http://opcfoundation.org/SimpleEvents;CycleStepDataType", "type": "object", "properties": { "Name": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Duration": { "$ref": "#/definitions/org.opcfoundation.UA.Double" } }, "required": [ "Name", "Duration" ], "additionalProperties": false }, "org.github.microsoft.opcpublisher.CycleStepDataTypeDataValue": { "$id": "http://github.org/microsoft/opcpublisher#CycleStepDataTypeDataValue", "title": "Dataset Field of Type CycleStepDataType", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.SimpleEvents.CycleStepDataType" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage1": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage1", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.ByteStringDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage2": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage2", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.LocalizedTextDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage3": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage3", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.StringDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage4": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage4", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.CycleStepDataTypeDataValue" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessages": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessages", "type": "object", "oneOf": [ { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage1" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage2" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage3" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage4" } ] } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/SamplesRaw/CyclicReads.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessages", "definitions": { "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.opcfoundation.UA.Int32": { "$id": "http://opcfoundation.org/UA/#Int32", "title": "OPC UA built in type Int32", "type": "integer", "minimum": -2147483648, "maximum": 2147483647, "default": 0, "format": "int32" }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "org.opcfoundation.UA.Number": { "$id": "http://opcfoundation.org/UA/#Number", "title": "OPC UA built in type Number", "type": "number" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.github.microsoft.opcpublisher.MonitoredItemMessage1": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage1", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage2": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage2", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage3": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage3", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage4": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage4", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Int32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage5": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage5", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage6": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage6", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage7": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage7", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage8": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage8", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage9": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage9", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage10": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage10", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage11": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage11", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage12": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage12", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage13": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage13", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage14": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage14", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage15": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage15", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage16": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage16", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage17": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage17", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage18": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage18", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage19": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage19", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage20": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage20", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage21": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage21", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage22": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage22", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage23": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage23", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage24": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage24", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Number" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessages": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessages", "type": "object", "oneOf": [ { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage1" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage2" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage3" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage4" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage5" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage6" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage7" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage8" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage9" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage10" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage11" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage12" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage13" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage14" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage15" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage16" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage17" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage18" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage19" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage20" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage21" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage22" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage23" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage24" } ] } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/SamplesRaw/KeepAlive.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessages", "definitions": { "org.opcfoundation.UA.ServerState": { "$id": "http://opcfoundation.org/UA/#ServerState", "title": "ServerState", "type": "integer", "enum": [ 0, 1, 2, 3, 4, 5, 6, 7 ], "format": "int32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.github.microsoft.opcpublisher.MonitoredItemMessage1": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage1", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.ServerState" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessages": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessages", "type": "object", "oneOf": [ { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage1" } ] } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/SamplesRaw/KeyFrames.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessages", "definitions": { "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.Variant": { "title": "Any", "type": [ "number", "null", "object", "array", "string", "integer", "boolean" ] }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.opcfoundation.UA.Float": { "$id": "http://opcfoundation.org/UA/#Float", "title": "OPC UA built in type Float", "type": "number", "minimum": -3.4028235E+38, "maximum": 3.4028235E+38, "default": 0, "format": "float" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.github.microsoft.opcpublisher.MonitoredItemMessage1": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage1", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage2": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage2", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage3": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage3", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "title": "Any", "type": [ "number", "null", "object", "array", "string", "integer", "boolean" ] }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage4": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage4", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage5": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage5", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Float" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessages": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessages", "type": "object", "oneOf": [ { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage1" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage2" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage3" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage4" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage5" } ] } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/SamplesRaw/PendingAlarms.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessages", "definitions": { "org.opcfoundation.UA.NodeId": { "$id": "http://opcfoundation.org/UA/#NodeId", "title": "OPC UA built in type NodeId", "type": "string", "format": "opcuaNodeId" }, "org.opcfoundation.UA.LocalizedText": { "$id": "http://opcfoundation.org/UA/#LocalizedText", "title": "OPC UA built in type LocalizedText", "type": "string" }, "org.opcfoundation.UA.ByteString": { "$id": "http://opcfoundation.org/UA/#ByteString", "title": "OPC UA built in type ByteString", "type": "string", "format": "byte" }, "org.opcfoundation.UA.Int16": { "$id": "http://opcfoundation.org/UA/#Int16", "title": "OPC UA built in type Int16", "type": "integer", "minimum": -32768, "maximum": 32767, "default": 0, "format": "int16" }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.opcfoundation.UA.TimeZoneDataType": { "$id": "http://opcfoundation.org/UA/#TimeZoneDataType", "title": "TimeZoneDataType", "type": "object", "properties": { "Offset": { "$ref": "#/definitions/org.opcfoundation.UA.Int16" }, "DaylightSavingInOffset": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" } }, "required": [ "Offset", "DaylightSavingInOffset" ], "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.github.microsoft.opcpublisher.MonitoredItemMessage1": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage1", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.NodeId" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage2": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage2", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage3": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage3", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "type": "array", "items": { "$ref": "#/definitions/org.opcfoundation.UA.NodeId" } }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage4": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage4", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "type": "array", "items": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" } }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage5": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage5", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.ByteString" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage6": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage6", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.NodeId" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage7": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage7", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.TimeZoneDataType" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage8": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage8", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage9": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage9", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage10": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage10", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage11": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage11", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage12": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage12", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.NodeId" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage13": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage13", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessages": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessages", "type": "object", "oneOf": [ { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage1" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage2" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage3" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage4" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage5" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage6" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage7" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage8" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage9" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage10" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage11" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage12" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage13" } ] } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/SamplesRaw/PlcSimulation.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessages", "definitions": { "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.opcfoundation.UA.Int32": { "$id": "http://opcfoundation.org/UA/#Int32", "title": "OPC UA built in type Int32", "type": "integer", "minimum": -2147483648, "maximum": 2147483647, "default": 0, "format": "int32" }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.github.microsoft.opcpublisher.MonitoredItemMessage1": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage1", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage2": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage2", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage3": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage3", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Int32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage4": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage4", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage5": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage5", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage6": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage6", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage7": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage7", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage8": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage8", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage9": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage9", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage10": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage10", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage11": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage11", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage12": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage12", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage13": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage13", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage14": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage14", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage16": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage16", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage17": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage17", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage18": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage18", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage19": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage19", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage20": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage20", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage21": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage21", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage22": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage22", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage23": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage23", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessages": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessages", "type": "object", "oneOf": [ { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage1" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage2" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage3" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage4" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage5" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage6" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage7" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage8" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage9" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage10" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage11" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage12" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage13" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage14" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage16" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage17" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage18" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage19" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage20" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage21" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage22" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage23" } ] } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/SamplesRaw/SimpleEvents.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessages", "definitions": { "org.opcfoundation.UA.ByteString": { "$id": "http://opcfoundation.org/UA/#ByteString", "title": "OPC UA built in type ByteString", "type": "string", "format": "byte" }, "org.opcfoundation.UA.LocalizedText": { "$id": "http://opcfoundation.org/UA/#LocalizedText", "title": "OPC UA built in type LocalizedText", "type": "string" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "org.opcfoundation.SimpleEvents.CycleStepDataType": { "$id": "http://opcfoundation.org/SimpleEvents#CycleStepDataType", "title": "nsu=http://opcfoundation.org/SimpleEvents;CycleStepDataType", "type": "object", "properties": { "Name": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Duration": { "$ref": "#/definitions/org.opcfoundation.UA.Double" } }, "required": [ "Name", "Duration" ], "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.github.microsoft.opcpublisher.MonitoredItemMessage1": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage1", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.ByteString" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage2": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage2", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage3": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage3", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessage4": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessage4", "type": "object", "properties": { "NodeId": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "EndpointUrl": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "ApplicationUri": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DisplayName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Timestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Value": { "$ref": "#/definitions/org.opcfoundation.SimpleEvents.CycleStepDataType" }, "SequenceNumber": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "ExtensionFields": { "type": "object", "additionalProperties": true } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.MonitoredItemMessages": { "$id": "http://github.org/microsoft/opcpublisher#MonitoredItemMessages", "type": "object", "oneOf": [ { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage1" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage2" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage3" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.MonitoredItemMessage4" } ] } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Single/CyclicReads.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSetMessage", "definitions": { "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.DateTimeDataValue": { "$id": "http://github.org/microsoft/opcpublisher#DateTimeDataValue", "title": "Dataset Field of Type DateTime", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.UInt32DataValue": { "$id": "http://github.org/microsoft/opcpublisher#UInt32DataValue", "title": "Dataset Field of Type UInt32", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.github.microsoft.opcpublisher.BooleanDataValue": { "$id": "http://github.org/microsoft/opcpublisher#BooleanDataValue", "title": "Dataset Field of Type Boolean", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Int32": { "$id": "http://opcfoundation.org/UA/#Int32", "title": "OPC UA built in type Int32", "type": "integer", "minimum": -2147483648, "maximum": 2147483647, "default": 0, "format": "int32" }, "org.github.microsoft.opcpublisher.Int32DataValue": { "$id": "http://github.org/microsoft/opcpublisher#Int32DataValue", "title": "Dataset Field of Type Int32", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Int32" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "org.github.microsoft.opcpublisher.DoubleDataValue": { "$id": "http://github.org/microsoft/opcpublisher#DoubleDataValue", "title": "Dataset Field of Type Double", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Number": { "$id": "http://opcfoundation.org/UA/#Number", "title": "OPC UA built in type Number", "type": "number" }, "org.github.microsoft.opcpublisher.NumberDataValue": { "$id": "http://github.org/microsoft/opcpublisher#NumberDataValue", "title": "Dataset Field of Type Number", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Number" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "i=2258": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DateTimeDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=StepUp": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.BooleanDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.Int32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "ns=23;i=1259": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NumberDataValue" } } }, "org.github.microsoft.opcpublisher.DataSetMessage": { "$id": "http://github.org/microsoft/opcpublisher#DataSetMessage", "type": "object", "properties": { "Payload": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet" } }, "required": [ "Payload" ], "additionalProperties": false } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Single/KeepAlive.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSetMessage", "definitions": { "org.opcfoundation.UA.ServerState": { "$id": "http://opcfoundation.org/UA/#ServerState", "title": "ServerState", "type": "integer", "enum": [ 0, 1, 2, 3, 4, 5, 6, 7 ], "format": "int32" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.ServerStateDataValue": { "$id": "http://github.org/microsoft/opcpublisher#ServerStateDataValue", "title": "Dataset Field of Type ServerState", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.ServerState" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "State": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.ServerStateDataValue" } } }, "org.opcfoundation.UA.i_x61_14593": { "$id": "http://opcfoundation.org/UA/#i%3d14593", "type": "object", "properties": { "MajorVersion": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "MinorVersion": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" } } }, "org.github.microsoft.opcpublisher.DataSetMessage": { "$id": "http://github.org/microsoft/opcpublisher#DataSetMessage", "type": "object", "properties": { "MetaDataVersion": { "$ref": "#/definitions/org.opcfoundation.UA.i_x61_14593" }, "MessageType": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DataSetWriterName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Payload": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet" } }, "required": [ "MetaDataVersion", "MessageType", "DataSetWriterName", "Payload" ], "additionalProperties": false } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Single/KeyFrames.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSetMessage", "definitions": { "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.DateTimeDataValue": { "$id": "http://github.org/microsoft/opcpublisher#DateTimeDataValue", "title": "Dataset Field of Type DateTime", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.StringDataValue": { "$id": "http://github.org/microsoft/opcpublisher#StringDataValue", "title": "Dataset Field of Type String", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Variant": { "title": "Any", "type": [ "number", "null", "object", "array", "string", "integer", "boolean" ] }, "org.github.microsoft.opcpublisher.NumberDataValue": { "$id": "http://github.org/microsoft/opcpublisher#NumberDataValue", "title": "Dataset Field of Type Number", "type": "object", "properties": { "Value": { "title": "Any", "type": [ "number", "null", "object", "array", "string", "integer", "boolean" ] }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.github.microsoft.opcpublisher.BooleanDataValue": { "$id": "http://github.org/microsoft/opcpublisher#BooleanDataValue", "title": "Dataset Field of Type Boolean", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Float": { "$id": "http://opcfoundation.org/UA/#Float", "title": "OPC UA built in type Float", "type": "number", "minimum": -3.4028235E+38, "maximum": 3.4028235E+38, "default": 0, "format": "float" }, "org.github.microsoft.opcpublisher.FloatDataValue": { "$id": "http://github.org/microsoft/opcpublisher#FloatDataValue", "title": "Dataset Field of Type Float", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Float" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "CurrentTime": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DateTimeDataValue" }, "EngineeringUnits": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.StringDataValue" }, "AssetId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NumberDataValue" }, "Important": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.BooleanDataValue" }, "Variance": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.FloatDataValue" } } }, "org.opcfoundation.UA.i_x61_14593": { "$id": "http://opcfoundation.org/UA/#i%3d14593", "type": "object", "properties": { "MajorVersion": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "MinorVersion": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" } } }, "org.github.microsoft.opcpublisher.DataSetMessage": { "$id": "http://github.org/microsoft/opcpublisher#DataSetMessage", "type": "object", "properties": { "MetaDataVersion": { "$ref": "#/definitions/org.opcfoundation.UA.i_x61_14593" }, "MessageType": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "DataSetWriterName": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Payload": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet" } }, "required": [ "MetaDataVersion", "MessageType", "DataSetWriterName", "Payload" ], "additionalProperties": false } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Single/PendingAlarms.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSetMessage", "definitions": { "org.opcfoundation.UA.NodeId": { "$id": "http://opcfoundation.org/UA/#NodeId", "title": "OPC UA built in type NodeId", "type": "string", "format": "opcuaNodeId" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.NodeIdDataValue": { "$id": "http://github.org/microsoft/opcpublisher#NodeIdDataValue", "title": "Dataset Field of Type NodeId", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.NodeId" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.LocalizedText": { "$id": "http://opcfoundation.org/UA/#LocalizedText", "title": "OPC UA built in type LocalizedText", "type": "string" }, "org.github.microsoft.opcpublisher.LocalizedTextDataValue": { "$id": "http://github.org/microsoft/opcpublisher#LocalizedTextDataValue", "title": "Dataset Field of Type LocalizedText", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.NodeIdArrayDataValue": { "$id": "http://github.org/microsoft/opcpublisher#NodeIdArrayDataValue", "title": "Dataset Field of Type NodeIdArray", "type": "object", "properties": { "Value": { "type": "array", "items": { "$ref": "#/definitions/org.opcfoundation.UA.NodeId" } }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.LocalizedTextArrayDataValue": { "$id": "http://github.org/microsoft/opcpublisher#LocalizedTextArrayDataValue", "title": "Dataset Field of Type LocalizedTextArray", "type": "object", "properties": { "Value": { "type": "array", "items": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" } }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.ByteString": { "$id": "http://opcfoundation.org/UA/#ByteString", "title": "OPC UA built in type ByteString", "type": "string", "format": "byte" }, "org.github.microsoft.opcpublisher.ByteStringDataValue": { "$id": "http://github.org/microsoft/opcpublisher#ByteStringDataValue", "title": "Dataset Field of Type ByteString", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.ByteString" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Int16": { "$id": "http://opcfoundation.org/UA/#Int16", "title": "OPC UA built in type Int16", "type": "integer", "minimum": -32768, "maximum": 32767, "default": 0, "format": "int16" }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.opcfoundation.UA.TimeZoneDataType": { "$id": "http://opcfoundation.org/UA/#TimeZoneDataType", "title": "TimeZoneDataType", "type": "object", "properties": { "Offset": { "$ref": "#/definitions/org.opcfoundation.UA.Int16" }, "DaylightSavingInOffset": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" } }, "required": [ "Offset", "DaylightSavingInOffset" ], "additionalProperties": false }, "org.github.microsoft.opcpublisher.TimeZoneDataTypeDataValue": { "$id": "http://github.org/microsoft/opcpublisher#TimeZoneDataTypeDataValue", "title": "Dataset Field of Type TimeZoneDataType", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.TimeZoneDataType" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DateTimeDataValue": { "$id": "http://github.org/microsoft/opcpublisher#DateTimeDataValue", "title": "Dataset Field of Type DateTime", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.UInt16DataValue": { "$id": "http://github.org/microsoft/opcpublisher#UInt16DataValue", "title": "Dataset Field of Type UInt16", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.StringDataValue": { "$id": "http://github.org/microsoft/opcpublisher#StringDataValue", "title": "Dataset Field of Type String", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "ConditionClassId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NodeIdDataValue" }, "ConditionClassName": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.LocalizedTextDataValue" }, "ConditionSubClassId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NodeIdArrayDataValue" }, "ConditionSubClassName": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.LocalizedTextArrayDataValue" }, "EventId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.ByteStringDataValue" }, "EventType": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NodeIdDataValue" }, "LocalTime": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.TimeZoneDataTypeDataValue" }, "Message": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.LocalizedTextDataValue" }, "ReceiveTime": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DateTimeDataValue" }, "Severity": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt16DataValue" }, "SourceName": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.StringDataValue" }, "SourceNode": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.NodeIdDataValue" }, "Time": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DateTimeDataValue" } } }, "org.github.microsoft.opcpublisher.DataSetMessage": { "$id": "http://github.org/microsoft/opcpublisher#DataSetMessage", "type": "object", "properties": { "Payload": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet" } }, "required": [ "Payload" ], "additionalProperties": false } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Single/PlcSimulation.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSets", "definitions": { "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.UInt32DataValue": { "$id": "http://github.org/microsoft/opcpublisher#UInt32DataValue", "title": "Dataset Field of Type UInt32", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Boolean": { "$id": "http://opcfoundation.org/UA/#Boolean", "title": "OPC UA built in type Boolean", "type": "boolean" }, "org.github.microsoft.opcpublisher.BooleanDataValue": { "$id": "http://github.org/microsoft/opcpublisher#BooleanDataValue", "title": "Dataset Field of Type Boolean", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Boolean" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Int32": { "$id": "http://opcfoundation.org/UA/#Int32", "title": "OPC UA built in type Int32", "type": "integer", "minimum": -2147483648, "maximum": 2147483647, "default": 0, "format": "int32" }, "org.github.microsoft.opcpublisher.Int32DataValue": { "$id": "http://github.org/microsoft/opcpublisher#Int32DataValue", "title": "Dataset Field of Type Int32", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Int32" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "org.github.microsoft.opcpublisher.DoubleDataValue": { "$id": "http://github.org/microsoft/opcpublisher#DoubleDataValue", "title": "Dataset Field of Type Double", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.Double" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "nsu=http://opcfoundation.org/UA/Plc/Applications;s=StepUp": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.BooleanDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.Int32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DoubleDataValue" } } }, "org.github.microsoft.opcpublisher.DataSetMessage": { "$id": "http://github.org/microsoft/opcpublisher#DataSetMessage", "type": "object", "properties": { "Payload": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet" } }, "required": [ "Payload" ], "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet1": { "$id": "http://github.org/microsoft/opcpublisher#DataSet1", "title": "DataSet1", "type": "object", "properties": { "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" }, "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.UInt32DataValue" } } }, "org.github.microsoft.opcpublisher.DataSetMessage1": { "$id": "http://github.org/microsoft/opcpublisher#DataSetMessage1", "type": "object", "properties": { "Payload": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet1" } }, "required": [ "Payload" ], "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSets": { "$id": "http://github.org/microsoft/opcpublisher#DataSets", "type": "object", "oneOf": [ { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSetMessage" }, { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSetMessage1" } ] } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Schemas/JsonSchema/Single/SimpleEvents.json ================================================ { "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSetMessage", "definitions": { "org.opcfoundation.UA.ByteString": { "$id": "http://opcfoundation.org/UA/#ByteString", "title": "OPC UA built in type ByteString", "type": "string", "format": "byte" }, "org.opcfoundation.UA.UInt32": { "$id": "http://opcfoundation.org/UA/#UInt32", "title": "OPC UA built in type UInt32", "type": "integer", "minimum": 0, "maximum": 4294967295, "default": 0, "format": "uint32" }, "org.opcfoundation.UA.String": { "$id": "http://opcfoundation.org/UA/#String", "title": "OPC UA built in type String", "type": "string" }, "org.opcfoundation.UA.StatusCode": { "$id": "http://opcfoundation.org/UA/#StatusCode", "title": "OPC UA built in type StatusCode", "type": "object", "properties": { "Code": { "$ref": "#/definitions/org.opcfoundation.UA.UInt32" }, "Symbol": { "$ref": "#/definitions/org.opcfoundation.UA.String" } }, "additionalProperties": false }, "org.opcfoundation.UA.DateTime": { "$id": "http://opcfoundation.org/UA/#DateTime", "title": "OPC UA built in type DateTime", "type": "string", "format": "date-time" }, "org.opcfoundation.UA.UInt16": { "$id": "http://opcfoundation.org/UA/#UInt16", "title": "OPC UA built in type UInt16", "type": "integer", "minimum": 0, "maximum": 65535, "default": 0, "format": "uint16" }, "org.github.microsoft.opcpublisher.ByteStringDataValue": { "$id": "http://github.org/microsoft/opcpublisher#ByteStringDataValue", "title": "Dataset Field of Type ByteString", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.ByteString" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.LocalizedText": { "$id": "http://opcfoundation.org/UA/#LocalizedText", "title": "OPC UA built in type LocalizedText", "type": "string" }, "org.github.microsoft.opcpublisher.LocalizedTextDataValue": { "$id": "http://github.org/microsoft/opcpublisher#LocalizedTextDataValue", "title": "Dataset Field of Type LocalizedText", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.LocalizedText" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.StringDataValue": { "$id": "http://github.org/microsoft/opcpublisher#StringDataValue", "title": "Dataset Field of Type String", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.opcfoundation.UA.Double": { "$id": "http://opcfoundation.org/UA/#Double", "title": "OPC UA built in type Double", "type": "number", "minimum": -1.7976931348623157E+308, "maximum": 1.7976931348623157E+308, "default": 0, "format": "double" }, "org.opcfoundation.SimpleEvents.CycleStepDataType": { "$id": "http://opcfoundation.org/SimpleEvents#CycleStepDataType", "title": "nsu=http://opcfoundation.org/SimpleEvents;CycleStepDataType", "type": "object", "properties": { "Name": { "$ref": "#/definitions/org.opcfoundation.UA.String" }, "Duration": { "$ref": "#/definitions/org.opcfoundation.UA.Double" } }, "required": [ "Name", "Duration" ], "additionalProperties": false }, "org.github.microsoft.opcpublisher.CycleStepDataTypeDataValue": { "$id": "http://github.org/microsoft/opcpublisher#CycleStepDataTypeDataValue", "title": "Dataset Field of Type CycleStepDataType", "type": "object", "properties": { "Value": { "$ref": "#/definitions/org.opcfoundation.SimpleEvents.CycleStepDataType" }, "Status": { "$ref": "#/definitions/org.opcfoundation.UA.StatusCode" }, "SourceTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "SourcePicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" }, "ServerTimestamp": { "$ref": "#/definitions/org.opcfoundation.UA.DateTime" }, "ServerPicoSeconds": { "$ref": "#/definitions/org.opcfoundation.UA.UInt16" } }, "additionalProperties": false }, "org.github.microsoft.opcpublisher.DataSet": { "$id": "http://github.org/microsoft/opcpublisher#DataSet", "title": "DataSet", "type": "object", "properties": { "EventId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.ByteStringDataValue" }, "Message": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.LocalizedTextDataValue" }, "http://opcfoundation.org/SimpleEvents#CycleId": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.StringDataValue" }, "http://opcfoundation.org/SimpleEvents#CurrentStep": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.CycleStepDataTypeDataValue" } } }, "org.github.microsoft.opcpublisher.DataSetMessage": { "$id": "http://github.org/microsoft/opcpublisher#DataSetMessage", "type": "object", "properties": { "Payload": { "$ref": "#/definitions/org.github.microsoft.opcpublisher.DataSet" } }, "required": [ "Payload" ], "additionalProperties": false } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Services/VariantEncoderBooleanTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Opc.Ua; using Xunit; public class VariantEncoderBooleanTests { [Fact] public void DecodeEncodeBooleanFromJValue() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(true); var variant = codec.Decode(str, BuiltInType.Boolean); var expected = new Variant(true); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeBooleanArrayFromJArray() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromArray(true, true, false); var variant = codec.Decode(str, BuiltInType.Boolean); var expected = new Variant([true, true, false]); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeBooleanFromJValueTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(true); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(true); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeBooleanArrayFromJArrayTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromArray(true, true, false); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant([true, true, false]); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeBooleanFromString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "true"; var variant = codec.Decode(str, BuiltInType.Boolean); var expected = new Variant(true); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(true), encoded); } [Fact] public void DecodeEncodeBooleanArrayFromString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "true, true, false"; var variant = codec.Decode(str, BuiltInType.Boolean); var expected = new Variant([true, true, false]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(true, true, false), encoded); } [Fact] public void DecodeEncodeBooleanArrayFromString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[true, true, false]"; var variant = codec.Decode(str, BuiltInType.Boolean); var expected = new Variant([true, true, false]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(true, true, false), encoded); } [Fact] public void DecodeEncodeBooleanArrayFromString3() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Boolean); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeBooleanFromStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "true"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(true); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(true), encoded); } [Fact] public void DecodeEncodeBooleanArrayFromStringTypeNull1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "true, true, false"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant([true, true, false]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(true, true, false), encoded); } [Fact] public void DecodeEncodeBooleanArrayFromStringTypeNull2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[true, true, false]"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant([true, true, false]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(true, true, false), encoded); } [Fact] public void DecodeEncodeBooleanArrayFromStringTypeNullIsNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Null); var expected = Variant.Null; var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.Equal(expected, variant); } [Fact] public void DecodeEncodeBooleanFromQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"true\""; var variant = codec.Decode(str, BuiltInType.Boolean); var expected = new Variant(true); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(true), encoded); } [Fact] public void DecodeEncodeBooleanFromSinglyQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = " 'true'"; var variant = codec.Decode(str, BuiltInType.Boolean); var expected = new Variant(true); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(true), encoded); } [Fact] public void DecodeEncodeBooleanArrayFromQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"true\",'true',\"false\""; var variant = codec.Decode(str, BuiltInType.Boolean); var expected = new Variant([true, true, false]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(true, true, false), encoded); } [Fact] public void DecodeEncodeBooleanArrayFromQuotedString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = " [\"true\",'true',\"false\"] "; var variant = codec.Decode(str, BuiltInType.Boolean); var expected = new Variant([true, true, false]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(true, true, false), encoded); } [Fact] public void DecodeEncodeBooleanFromVariantJsonTokenTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Boolean", Body = true }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(true); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(true), encoded); } [Fact] public void DecodeEncodeBooleanArrayFromVariantJsonTokenTypeVariant1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Boolean", Body = new bool[] { true, true, false } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant([true, true, false]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(true, true, false), encoded); } [Fact] public void DecodeEncodeBooleanArrayFromVariantJsonTokenTypeVariant2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Boolean", Body = System.Array.Empty() }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeBooleanFromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "Boolean", Body = true }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(true); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(true), encoded); } [Fact] public void DecodeEncodeBooleanArrayFromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "Boolean", Body = new bool[] { true, true, false } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant([true, true, false]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(true, true, false), encoded); } [Fact] public void DecodeEncodeBooleanFromVariantJsonTokenTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Boolean", Body = true }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(true); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(true), encoded); } [Fact] public void DecodeEncodeBooleanArrayFromVariantJsonTokenTypeNull1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { TYPE = "BOOLEAN", BODY = new bool[] { true, true, false } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant([true, true, false]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(true, true, false), encoded); } [Fact] public void DecodeEncodeBooleanArrayFromVariantJsonTokenTypeNull2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Boolean", Body = System.Array.Empty() }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeBooleanFromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "boolean", Body = true }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(true); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(true), encoded); } [Fact] public void DecodeEncodeBooleanArrayFromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "Boolean", body = new bool[] { true, true, false } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant([true, true, false]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(true, true, false), encoded); } [Fact] public void DecodeEncodeBooleanFromVariantJsonTokenTypeNullMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { DataType = "Boolean", Value = true }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(true); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(true), encoded); } [Fact] public void DecodeEncodeBooleanFromVariantJsonStringTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { DataType = "Boolean", Value = true }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(true); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(true), encoded); } [Fact] public void DecodeEncodeBooleanArrayFromVariantJsonTokenTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { dataType = "Boolean", value = new bool[] { true, true, false } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant([true, true, false]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(true, true, false), encoded); } #pragma warning disable CA1814 // Prefer jagged arrays over multidimensional [Fact] public void DecodeEncodeBooleanMatrixFromStringJsonTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new bool[,,] { { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((object)new bool[,,] { { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeBooleanMatrixFromStringJsonTypeBoolean() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new bool[,,] { { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } } }); var variant = codec.Decode(str, BuiltInType.Boolean); var expected = new Variant((object)new bool[,,] { { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeBooleanMatrixFromVariantJsonTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "Boolean", body = new bool[,,] { { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } } } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((object)new bool[,,] { { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeBooleanMatrixFromVariantJsonTokenTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { dataType = "Boolean", value = new bool[,,] { { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } } } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((object)new bool[,,] { { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeBooleanMatrixFromVariantJsonTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "Boolean", body = new bool[,,] { { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } } } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((object)new bool[,,] { { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeBooleanMatrixFromVariantJsonTokenTypeNullMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { dataType = "Boolean", value = new bool[,,] { { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } } } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((object)new bool[,,] { { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } }, { { true, false, true }, { true, false, true }, { true, false, true } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } #pragma warning restore CA1814 // Prefer jagged arrays over multidimensional private readonly NewtonsoftJsonSerializer _serializer = new(); } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Services/VariantEncoderByteTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Opc.Ua; using Xunit; public class VariantEncoderByteTests { [Fact] public void DecodeEncodeByteFromJValue() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(123); var variant = codec.Decode(str, BuiltInType.Byte); var expected = new Variant((byte)123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeByteArrayFromJArray() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromArray((byte)123, (byte)124, (byte)125); var variant = codec.Decode(str, BuiltInType.Byte); var expected = new Variant("{|}"u8.ToArray()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeByteArrayTypeByteStringFromJArray() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject("{|}"u8.ToArray()); var variant = codec.Decode(str, BuiltInType.ByteString); var expected = new Variant("{|}"u8.ToArray()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeByteFromJValueTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(123); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeByteArrayFromJArrayTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromArray((byte)123, (byte)124, (byte)125); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new long[] { 123, 124, 125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeByteFromString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123"; var variant = codec.Decode(str, BuiltInType.Byte); var expected = new Variant((byte)123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeByteArrayFromString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123, 124, 125"; var variant = codec.Decode(str, BuiltInType.Byte); var expected = new Variant("{|}"u8.ToArray()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((byte)123, (byte)124, (byte)125), encoded); } [Fact] public void DecodeEncodeByteArrayFromString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[123, 124, 125]"; var variant = codec.Decode(str, BuiltInType.Byte); var expected = new Variant("{|}"u8.ToArray()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((byte)123, (byte)124, (byte)125), encoded); } [Fact] public void DecodeEncodeByteArrayFromString3() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Byte); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeByteFromStringTypeIntegerIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123"; var variant = codec.Decode(str, BuiltInType.Integer); var expected = new Variant(123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeByteArrayFromStringTypeIntegerIsInt641() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[123, 124, 125]"; var variant = codec.Decode(str, BuiltInType.Integer); var expected = new Variant(new Variant[] { new(123L), new(124L), new(125L) }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((byte)123, (byte)124, (byte)125), encoded); } [Fact] public void DecodeEncodeByteArrayFromStringTypeIntegerIsInt642() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Integer); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeByteFromStringTypeNumberIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123"; var variant = codec.Decode(str, BuiltInType.Number); var expected = new Variant(123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeByteArrayFromStringTypeNumberIsInt641() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[123, 124, 125]"; var variant = codec.Decode(str, BuiltInType.Number); var expected = new Variant(new Variant[] { new(123L), new(124L), new(125L) }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((byte)123, (byte)124, (byte)125), encoded); } [Fact] public void DecodeEncodeByteArrayFromStringTypeNumberIsInt642() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Number); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeByteFromStringTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeByteArrayFromStringTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123, 124, 125"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new long[] { 123, 124, 125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((byte)123, (byte)124, (byte)125), encoded); } [Fact] public void DecodeEncodeByteArrayFromStringTypeNullIsInt642() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[123, 124, 125]"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new long[] { 123, 124, 125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((byte)123, (byte)124, (byte)125), encoded); } [Fact] public void DecodeEncodeByteArrayFromStringTypeNullIsNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Null); var expected = Variant.Null; var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.Equal(expected, variant); } [Fact] public void DecodeEncodeByteFromQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"123\""; var variant = codec.Decode(str, BuiltInType.Byte); var expected = new Variant((byte)123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeByteFromSinglyQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = " '123'"; var variant = codec.Decode(str, BuiltInType.Byte); var expected = new Variant((byte)123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeByteArrayFromQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"123\",'124',\"125\""; var variant = codec.Decode(str, BuiltInType.Byte); var expected = new Variant("{|}"u8.ToArray()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((byte)123, (byte)124, (byte)125), encoded); } [Fact] public void DecodeEncodeByteArrayFromQuotedString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = " [\"123\",'124',\"125\"] "; var variant = codec.Decode(str, BuiltInType.Byte); var expected = new Variant("{|}"u8.ToArray()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((byte)123, (byte)124, (byte)125), encoded); } [Fact] public void DecodeEncodeByteFromVariantJsonTokenTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Byte", Body = 123 }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((byte)123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeByteArrayFromVariantJsonTokenTypeVariant1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Byte", Body = "{|}"u8.ToArray() }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant("{|}"u8.ToArray()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((byte)123, (byte)124, (byte)125), encoded); } [Fact] public void DecodeEncodeByteArrayFromVariantJsonTokenTypeVariant2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Byte", Body = System.Array.Empty() }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeByteArrayFromVariantJsonTokenTypeVariant3() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "ByteString", Body = "{|}"u8.ToArray() }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant("{|}"u8.ToArray()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject("{|}"u8.ToArray()), encoded); } [Fact] public void DecodeEncodeByteFromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "Byte", Body = 123 }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((byte)123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeByteArrayFromVariantJsonStringTypeVariant1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "Byte", Body = "{|}"u8.ToArray() }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant("{|}"u8.ToArray()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((byte)123, (byte)124, (byte)125), encoded); } [Fact] public void DecodeEncodeByteArrayFromVariantJsonStringTypeVariant2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "ByteString", Body = "{|}"u8.ToArray() }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant("{|}"u8.ToArray()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject("{|}"u8.ToArray()), encoded); } [Fact] public void DecodeEncodeByteFromVariantJsonTokenTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Byte", Body = (byte)123 }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((byte)123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeByteArrayFromVariantJsonTokenTypeNull1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { TYPE = "BYTE", BODY = "{|}"u8.ToArray() }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant("{|}"u8.ToArray()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((byte)123, (byte)124, (byte)125), encoded); } [Fact] public void DecodeEncodeByteArrayFromVariantJsonTokenTypeNull2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Byte", Body = System.Array.Empty() }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeByteFromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "byte", Body = (byte)123 }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((byte)123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeByteArrayFromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "Byte", body = "{|}"u8.ToArray() }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant("{|}"u8.ToArray()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((byte)123, (byte)124, (byte)125), encoded); } [Fact] public void DecodeEncodeByteFromVariantJsonTokenTypeNullMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { DataType = "Byte", Value = 123 }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((byte)123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeByteFromVariantJsonStringTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { DataType = "Byte", Value = (byte)123 }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((byte)123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeByteArrayFromVariantJsonTokenTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { dataType = "Byte", value = "{|}"u8.ToArray() }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant("{|}"u8.ToArray()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((byte)123, (byte)124, (byte)125), encoded); } #pragma warning disable CA1814 // Prefer jagged arrays over multidimensional [Fact] public void DecodeEncodeByteMatrixFromStringJsonTypeByte() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new byte[,,] { { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } } }); var variant = codec.Decode(str, BuiltInType.Byte); var expected = new Variant((object)new byte[,,] { { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeByteMatrixFromVariantJsonTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "Byte", body = new byte[,,] { { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } } } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((object)new byte[,,] { { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeByteMatrixFromVariantJsonTokenTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { dataType = "Byte", value = new byte[,,] { { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } } } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((object)new byte[,,] { { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeByteMatrixFromVariantJsonTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "Byte", body = new byte[,,] { { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } } } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((object)new byte[,,] { { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeByteMatrixFromVariantJsonTokenTypeNullMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { dataType = "Byte", value = new byte[,,] { { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } } } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((object)new byte[,,] { { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } #pragma warning restore CA1814 // Prefer jagged arrays over multidimensional private readonly NewtonsoftJsonSerializer _serializer = new(); } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Services/VariantEncoderDoubleTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Opc.Ua; using Xunit; public class VariantEncoderDoubleTests { [Fact] public void DecodeEncodeDoubleFromJValue() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(-123.123); var variant = codec.Decode(str, BuiltInType.Double); var expected = new Variant(-123.123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeDoubleArrayFromJArray() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromArray(-123.123, 124.124, 0.0); var variant = codec.Decode(str, BuiltInType.Double); var expected = new Variant([-123.123, 124.124, 0.0]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeDoubleFromJValueTypeNullIsDouble() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(-123.123); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(-123.123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeDoubleArrayFromJArrayTypeNullIsDouble() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromArray(-123.123, 124.124, 0.0); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant([-123.123, 124.124, 0.0]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeDoubleFromString1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123.123"; var variant = codec.Decode(str, BuiltInType.Double); var expected = new Variant(-123.123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123.123), encoded); } [Fact] public void DecodeEncodeDoubleFromString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123"; var variant = codec.Decode(str, BuiltInType.Double); var expected = new Variant(-123.0); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123.0), encoded); } [Fact] public void DecodeEncodeDoubleArrayFromString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123.123, 124.124, 0.0"; var variant = codec.Decode(str, BuiltInType.Double); var expected = new Variant([-123.123, 124.124, 0.0]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123.123, 124.124, 0.0), encoded); } [Fact] public void DecodeEncodeDoubleArrayFromString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[-123.123, 124.124, 0.0]"; var variant = codec.Decode(str, BuiltInType.Double); var expected = new Variant([-123.123, 124.124, 0.0]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123.123, 124.124, 0.0), encoded); } [Fact] public void DecodeEncodeDoubleArrayFromString3() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Double); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeDoubleFromStringTypeNumberIsDouble() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123.123"; var variant = codec.Decode(str, BuiltInType.Number); var expected = new Variant(-123.123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123.123), encoded); } [Fact] public void DecodeEncodeDoubleArrayFromStringTypeNumberIsDouble1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[-123.123, 124.124, 0.0]"; var variant = codec.Decode(str, BuiltInType.Number); var expected = new Variant(new Variant[] { new(-123.123), new(124.124), new(0.0) }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123.123, 124.124, 0.0), encoded); } [Fact] public void DecodeEncodeDoubleArrayFromStringTypeNumberIsDouble2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Number); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeDoubleFromStringTypeNullIsDouble() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123.123"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(-123.123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123.123), encoded); } [Fact] public void DecodeEncodeDoubleArrayFromStringTypeNullIsDouble() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123.123, 124.124, 0.0"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant([-123.123, 124.124, 0.0]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123.123, 124.124, 0.0), encoded); } [Fact] public void DecodeEncodeDoubleArrayFromStringTypeNullIsDouble2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[-123.123, 124.124, 0.0]"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant([-123.123, 124.124, 0.0]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123.123, 124.124, 0.0), encoded); } [Fact] public void DecodeEncodeDoubleArrayFromStringTypeNullIsNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Null); var expected = Variant.Null; var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.Equal(expected, variant); } [Fact] public void DecodeEncodeDoubleFromQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"-123.123\""; var variant = codec.Decode(str, BuiltInType.Double); var expected = new Variant(-123.123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123.123), encoded); } [Fact] public void DecodeEncodeDoubleFromSinglyQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = " '-123.123'"; var variant = codec.Decode(str, BuiltInType.Double); var expected = new Variant(-123.123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123.123), encoded); } [Fact] public void DecodeEncodeDoubleArrayFromQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"-123.123\",'124.124',\"0.0\""; var variant = codec.Decode(str, BuiltInType.Double); var expected = new Variant([-123.123, 124.124, 0.0]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123.123, 124.124, 0.0), encoded); } [Fact] public void DecodeEncodeDoubleArrayFromQuotedString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = " [\"-123.123\",'124.124',\"0.0\"] "; var variant = codec.Decode(str, BuiltInType.Double); var expected = new Variant([-123.123, 124.124, 0.0]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123.123, 124.124, 0.0), encoded); } [Fact] public void DecodeEncodeDoubleFromVariantJsonTokenTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Double", Body = -123.123f }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(-123.123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123.123), encoded); } [Fact] public void DecodeEncodeDoubleArrayFromVariantJsonTokenTypeVariant1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Double", Body = new double[] { -123.123, 124.124, 0.0 } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant([-123.123, 124.124, 0.0]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123.123, 124.124, 0.0), encoded); } [Fact] public void DecodeEncodeDoubleArrayFromVariantJsonTokenTypeVariant2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Double", Body = System.Array.Empty() }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeDoubleFromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "Double", Body = -123.123f }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(-123.123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123.123), encoded); } [Fact] public void DecodeEncodeDoubleArrayFromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "Double", Body = new double[] { -123.123, 124.124, 0.0 } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant([-123.123, 124.124, 0.0]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123.123, 124.124, 0.0), encoded); } [Fact] public void DecodeEncodeDoubleFromVariantJsonTokenTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Double", Body = -123.123f }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(-123.123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123.123), encoded); } [Fact] public void DecodeEncodeDoubleArrayFromVariantJsonTokenTypeNull1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { TYPE = "DOUBLE", BODY = new double[] { -123.123, 124.124, 0.0 } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant([-123.123, 124.124, 0.0]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123.123, 124.124, 0.0), encoded); } [Fact] public void DecodeEncodeDoubleArrayFromVariantJsonTokenTypeNull2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Double", Body = System.Array.Empty() }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeDoubleFromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "double", Body = -123.123f }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(-123.123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123.123), encoded); } [Fact] public void DecodeEncodeDoubleArrayFromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "Double", body = new double[] { -123.123, 124.124, 0.0 } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant([-123.123, 124.124, 0.0]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123.123, 124.124, 0.0), encoded); } [Fact] public void DecodeEncodeDoubleFromVariantJsonTokenTypeNullMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { DataType = "Double", Value = -123.123f }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(-123.123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123.123), encoded); } [Fact] public void DecodeEncodeDoubleFromVariantJsonStringTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { DataType = "Double", Value = -123.123f }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(-123.123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123.123), encoded); } [Fact] public void DecodeEncodeDoubleArrayFromVariantJsonTokenTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { dataType = "Double", value = new double[] { -123.123, 124.124, 0.0 } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant([-123.123, 124.124, 0.0]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123.123, 124.124, 0.0), encoded); } #pragma warning disable CA1814 // Prefer jagged arrays over multidimensional [Fact] public void DecodeEncodeDoubleMatrixFromStringJsonTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new double[,,] { { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((object)new double[,,] { { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeDoubleMatrixFromStringJsonTypeDouble() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new double[,,] { { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } } }); var variant = codec.Decode(str, BuiltInType.Double); var expected = new Variant((object)new double[,,] { { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeDoubleMatrixFromVariantJsonTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "Double", body = new double[,,] { { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } } } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((object)new double[,,] { { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeDoubleMatrixFromVariantJsonTokenTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { dataType = "Double", value = new double[,,] { { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } } } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((object)new double[,,] { { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeDoubleMatrixFromVariantJsonTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "Double", body = new double[,,] { { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } } } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((object)new double[,,] { { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeDoubleMatrixFromVariantJsonTokenTypeNullMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { dataType = "Double", value = new double[,,] { { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } } } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((object)new double[,,] { { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } }, { { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 }, { 123.456, 124.567, 125.0 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } #pragma warning restore CA1814 // Prefer jagged arrays over multidimensional private readonly NewtonsoftJsonSerializer _serializer = new(); } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Services/VariantEncoderEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Furly.Extensions.Serializers; using Opc.Ua; /// /// Variant encoder extensions /// public static class Extensions { /// /// Format variant as string /// /// /// /// public static VariantValue Encode(this IVariantEncoder encoder, Variant value) { return encoder.Encode(value, out _); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Services/VariantEncoderFloatTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Opc.Ua; using Xunit; public class VariantEncoderFloatTests { [Fact] public void DecodeEncodeFloatFromJValue() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(-123.123f); var variant = codec.Decode(str, BuiltInType.Float); var expected = new Variant(-123.123f); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeFloatArrayFromJArray() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromArray(-123.123f, 124.124f, 0.0f); var variant = codec.Decode(str, BuiltInType.Float); var expected = new Variant([-123.123f, 124.124f, 0.0f]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeFloatArrayFromJArrayTypeNullIsDouble() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromArray(-123.123f, 124.124f, 0.0f); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant([-123.123, 124.124, 0.0]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeFloatFromString1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123.123"; var variant = codec.Decode(str, BuiltInType.Float); var expected = new Variant(-123.123f); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123.123f), encoded); } [Fact] public void DecodeEncodeFloatFromString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123"; var variant = codec.Decode(str, BuiltInType.Float); var expected = new Variant(-123f); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123f), encoded); } [Fact] public void DecodeEncodeFloatArrayFromString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123.123, 124.124, 0.0"; var variant = codec.Decode(str, BuiltInType.Float); var expected = new Variant([-123.123f, 124.124f, 0.0f]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123.123f, 124.124f, 0.0f), encoded); } [Fact] public void DecodeEncodeFloatArrayFromString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[-123.123, 124.124, 0.0]"; var variant = codec.Decode(str, BuiltInType.Float); var expected = new Variant([-123.123f, 124.124f, 0.0f]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123.123f, 124.124f, 0.0f), encoded); } [Fact] public void DecodeEncodeFloatArrayFromString3() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Float); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeFloatFromStringTypeNumberIsDouble() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123.123"; var variant = codec.Decode(str, BuiltInType.Number); var expected = new Variant(-123.123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123.123), encoded); } [Fact] public void DecodeEncodeFloatArrayFromStringTypeNumberIsDouble1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[-123.123, 124.124, 0.0]"; var variant = codec.Decode(str, BuiltInType.Number); var expected = new Variant(new Variant[] { new(-123.123), new(124.124), new(0.0) }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123.123, 124.124, 0.0), encoded); } [Fact] public void DecodeEncodeFloatArrayFromStringTypeNumberIsDouble2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Number); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeFloatFromStringTypeNullIsDouble() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123.123"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(-123.123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123.123), encoded); } [Fact] public void DecodeEncodeFloatArrayFromStringTypeNullIsDouble() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123.123, 124.124, 0.0"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant([-123.123, 124.124, 0.0]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123.123, 124.124, 0.0), encoded); } [Fact] public void DecodeEncodeFloatArrayFromStringTypeNullIsDouble2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[-123.123, 124.124, 0.0]"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant([-123.123, 124.124, 0.0]); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123.123, 124.124, 0.0), encoded); } [Fact] public void DecodeEncodeFloatArrayFromStringTypeNullIsNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Null); var expected = Variant.Null; var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.Equal(expected, variant); } [Fact] public void DecodeEncodeFloatFromQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"-123.123\""; var variant = codec.Decode(str, BuiltInType.Float); var expected = new Variant(-123.123f); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123.123f), encoded); } [Fact] public void DecodeEncodeFloatFromSinglyQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = " '-123.123'"; var variant = codec.Decode(str, BuiltInType.Float); var expected = new Variant(-123.123f); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123.123f), encoded); } [Fact] public void DecodeEncodeFloatArrayFromQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"-123.123\",'124.124',\"0.0\""; var variant = codec.Decode(str, BuiltInType.Float); var expected = new Variant([-123.123f, 124.124f, 0.0f]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123.123f, 124.124f, 0.0f), encoded); } [Fact] public void DecodeEncodeFloatArrayFromQuotedString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = " [\"-123.123\",'124.124',\"0.0\"] "; var variant = codec.Decode(str, BuiltInType.Float); var expected = new Variant([-123.123f, 124.124f, 0.0f]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123.123f, 124.124f, 0.0f), encoded); } [Fact] public void DecodeEncodeFloatFromVariantJsonTokenTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Float", Body = -123.123f }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(-123.123f); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123.123f), encoded); } [Fact] public void DecodeEncodeFloatArrayFromVariantJsonTokenTypeVariant1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Float", Body = new float[] { -123.123f, 124.124f, 0.0f } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant([-123.123f, 124.124f, 0.0f]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123.123f, 124.124f, 0.0f), encoded); } [Fact] public void DecodeEncodeFloatArrayFromVariantJsonTokenTypeVariant2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Float", Body = System.Array.Empty() }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeFloatFromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "Float", Body = -123.123f }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(-123.123f); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123.123f), encoded); } [Fact] public void DecodeEncodeFloatArrayFromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "Float", Body = new float[] { -123.123f, 124.124f, 0.0f } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant([-123.123f, 124.124f, 0.0f]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123.123f, 124.124f, 0.0f), encoded); } [Fact] public void DecodeEncodeFloatFromVariantJsonTokenTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Float", Body = -123.123f }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(-123.123f); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123.123f), encoded); } [Fact] public void DecodeEncodeFloatArrayFromVariantJsonTokenTypeNull1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { TYPE = "FLOAT", BODY = new float[] { -123.123f, 124.124f, 0.0f } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant([-123.123f, 124.124f, 0.0f]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123.123f, 124.124f, 0.0f), encoded); } [Fact] public void DecodeEncodeFloatArrayFromVariantJsonTokenTypeNull2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Float", Body = System.Array.Empty() }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeFloatFromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "float", Body = -123.123f }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(-123.123f); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123.123f), encoded); } [Fact] public void DecodeEncodeFloatArrayFromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "Float", body = new float[] { -123.123f, 124.124f, 0.0f } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant([-123.123f, 124.124f, 0.0f]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123.123f, 124.124f, 0.0f), encoded); } [Fact] public void DecodeEncodeFloatFromVariantJsonTokenTypeNullMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { DataType = "Float", Value = -123.123f }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(-123.123f); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123.123f), encoded); } [Fact] public void DecodeEncodeFloatFromVariantJsonStringTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { DataType = "Float", Value = -123.123f }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(-123.123f); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123.123f), encoded); } [Fact] public void DecodeEncodeFloatArrayFromVariantJsonTokenTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { dataType = "Float", value = new float[] { -123.123f, 124.124f, 0.0f } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant([-123.123f, 124.124f, 0.0f]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123.123f, 124.124f, 0.0f), encoded); } #pragma warning disable CA1814 // Prefer jagged arrays over multidimensional [Fact] public void DecodeEncodeFloatMatrixFromStringJsonTypeFloat() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new float[,,] { { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } } }); var variant = codec.Decode(str, BuiltInType.Float); var expected = new Variant((object)new float[,,] { { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeFloatMatrixFromVariantJsonTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "Float", body = new float[,,] { { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } } } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((object)new float[,,] { { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeFloatMatrixFromVariantJsonTokenTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { dataType = "Float", value = new float[,,] { { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } } } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((object)new float[,,] { { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeFloatMatrixFromVariantJsonTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "Float", body = new float[,,] { { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } } } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((object)new float[,,] { { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeFloatMatrixFromVariantJsonTokenTypeNullMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { dataType = "Float", value = new float[,,] { { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } } } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((object)new float[,,] { { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } }, { { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f }, { -123.456f, 124.567f, -125.0f } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } #pragma warning restore CA1814 // Prefer jagged arrays over multidimensional private readonly NewtonsoftJsonSerializer _serializer = new(); } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Services/VariantEncoderInt16Tests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Opc.Ua; using Xunit; public class VariantEncoderInt16Tests { [Fact] public void DecodeEncodeInt16FromJValue() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(-123); var variant = codec.Decode(str, BuiltInType.Int16); var expected = new Variant((short)-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeInt16ArrayFromJArray() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromArray((short)-123, (short)-124, (short)-125); var variant = codec.Decode(str, BuiltInType.Int16); var expected = new Variant(new short[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeInt16FromJValueTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(-123); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt16ArrayFromJArrayTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromArray((short)-123, (short)-124, (short)-125); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new long[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeInt16FromString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123"; var variant = codec.Decode(str, BuiltInType.Int16); var expected = new Variant((short)-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt16ArrayFromString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123, -124, -125"; var variant = codec.Decode(str, BuiltInType.Int16); var expected = new Variant(new short[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((short)-123, (short)-124, (short)-125), encoded); } [Fact] public void DecodeEncodeInt16ArrayFromString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[-123, -124, -125]"; var variant = codec.Decode(str, BuiltInType.Int16); var expected = new Variant(new short[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((short)-123, (short)-124, (short)-125), encoded); } [Fact] public void DecodeEncodeInt16ArrayFromString3() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Int16); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeInt16FromStringTypeIntegerIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123"; var variant = codec.Decode(str, BuiltInType.Integer); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt16ArrayFromStringTypeIntegerIsInt641() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[-123, -124, -125]"; var variant = codec.Decode(str, BuiltInType.Integer); var expected = new Variant(new Variant[] { new(-123L), new(-124L), new(-125L) }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((short)-123, (short)-124, (short)-125), encoded); } [Fact] public void DecodeEncodeInt16ArrayFromStringTypeIntegerIsInt642() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Integer); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeInt16FromStringTypeNumberIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123"; var variant = codec.Decode(str, BuiltInType.Number); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt16ArrayFromStringTypeNumberIsInt641() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[-123, -124, -125]"; var variant = codec.Decode(str, BuiltInType.Number); var expected = new Variant(new Variant[] { new(-123L), new(-124L), new(-125L) }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((short)-123, (short)-124, (short)-125), encoded); } [Fact] public void DecodeEncodeInt16ArrayFromStringTypeNumberIsInt642() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Number); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeInt16FromStringTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt16ArrayFromStringTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123, -124, -125"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new long[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((short)-123, (short)-124, (short)-125), encoded); } [Fact] public void DecodeEncodeInt16ArrayFromStringTypeNullIsInt642() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[-123, -124, -125]"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new long[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((short)-123, (short)-124, (short)-125), encoded); } [Fact] public void DecodeEncodeInt16ArrayFromStringTypeNullIsNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Null); var expected = Variant.Null; var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.Equal(expected, variant); } [Fact] public void DecodeEncodeInt16FromQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"-123\""; var variant = codec.Decode(str, BuiltInType.Int16); var expected = new Variant((short)-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt16FromSinglyQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = " '-123'"; var variant = codec.Decode(str, BuiltInType.Int16); var expected = new Variant((short)-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt16ArrayFromQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"-123\",'-124',\"-125\""; var variant = codec.Decode(str, BuiltInType.Int16); var expected = new Variant(new short[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((short)-123, (short)-124, (short)-125), encoded); } [Fact] public void DecodeEncodeInt16ArrayFromQuotedString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = " [\"-123\",'-124',\"-125\"] "; var variant = codec.Decode(str, BuiltInType.Int16); var expected = new Variant(new short[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((short)-123, (short)-124, (short)-125), encoded); } [Fact] public void DecodeEncodeInt16FromVariantJsonTokenTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Int16", Body = -123 }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((short)-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt16ArrayFromVariantJsonTokenTypeVariant1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Int16", Body = new short[] { -123, -124, -125 } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(new short[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((short)-123, (short)-124, (short)-125), encoded); } [Fact] public void DecodeEncodeInt16ArrayFromVariantJsonTokenTypeVariant2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Int16", Body = System.Array.Empty() }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeInt16FromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "Int16", Body = -123 }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((short)-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt16ArrayFromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "Int16", Body = new short[] { -123, -124, -125 } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(new short[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((short)-123, (short)-124, (short)-125), encoded); } [Fact] public void DecodeEncodeInt16FromVariantJsonTokenTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Int16", Body = (short)-123 }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((short)-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt16ArrayFromVariantJsonTokenTypeNull1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { TYPE = "INT16", BODY = new short[] { -123, -124, -125 } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new short[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((short)-123, (short)-124, (short)-125), encoded); } [Fact] public void DecodeEncodeInt16ArrayFromVariantJsonTokenTypeNull2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Int16", Body = System.Array.Empty() }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeInt16FromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "int16", Body = (short)-123 }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((short)-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt16ArrayFromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "Int16", body = new short[] { -123, -124, -125 } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new short[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((short)-123, (short)-124, (short)-125), encoded); } [Fact] public void DecodeEncodeInt16FromVariantJsonTokenTypeNullMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { DataType = "Int16", Value = -123 }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((short)-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt16FromVariantJsonStringTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { DataType = "Int16", Value = (short)-123 }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((short)-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt16ArrayFromVariantJsonTokenTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { dataType = "Int16", value = new short[] { -123, -124, -125 } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(new short[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((short)-123, (short)-124, (short)-125), encoded); } #pragma warning disable CA1814 // Prefer jagged arrays over multidimensional [Fact] public void DecodeEncodeInt16MatrixFromStringJsonTypeInt16() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new short[,,] { { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } } }); var variant = codec.Decode(str, BuiltInType.Int16); var expected = new Variant((object)new short[,,] { { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeInt16MatrixFromVariantJsonTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "Int16", body = new short[,,] { { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } } } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((object)new short[,,] { { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeInt16MatrixFromVariantJsonTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { dataType = "Int16", value = new short[,,] { { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } } } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((object)new short[,,] { { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeInt16MatrixFromVariantJsonTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "Int16", body = new short[,,] { { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } } } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((object)new short[,,] { { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeInt16MatrixFromVariantJsonTypeNullMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { dataType = "Int16", value = new short[,,] { { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } } } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((object)new short[,,] { { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } }, { { -123, 124, -125 }, { -123, 124, -125 }, { -123, 124, -125 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } #pragma warning restore CA1814 // Prefer jagged arrays over multidimensional private readonly NewtonsoftJsonSerializer _serializer = new(); } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Services/VariantEncoderInt32Tests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Opc.Ua; using Xunit; public class VariantEncoderInt32Tests { [Fact] public void DecodeEncodeInt32FromJValue() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(-123); var variant = codec.Decode(str, BuiltInType.Int32); var expected = new Variant(-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeInt32ArrayFromJArray() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromArray(-123, -124, -125); var variant = codec.Decode(str, BuiltInType.Int32); var expected = new Variant([-123, -124, -125]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeInt32FromJValueTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(-123); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt32ArrayFromJArrayTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromArray(-123, -124, -125); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new long[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeInt32FromString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123"; var variant = codec.Decode(str, BuiltInType.Int32); var expected = new Variant(-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt32ArrayFromString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123, -124, -125"; var variant = codec.Decode(str, BuiltInType.Int32); var expected = new Variant([-123, -124, -125]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123, -124, -125), encoded); } [Fact] public void DecodeEncodeInt32ArrayFromString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[-123, -124, -125]"; var variant = codec.Decode(str, BuiltInType.Int32); var expected = new Variant([-123, -124, -125]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123, -124, -125), encoded); } [Fact] public void DecodeEncodeInt32ArrayFromString3() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Int32); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeInt32FromStringTypeIntegerIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123"; var variant = codec.Decode(str, BuiltInType.Integer); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt32ArrayFromStringTypeIntegerIsInt641() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[-123, -124, -125]"; var variant = codec.Decode(str, BuiltInType.Integer); var expected = new Variant(new Variant[] { new(-123L), new(-124L), new(-125L) }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123, -124, -125), encoded); } [Fact] public void DecodeEncodeInt32ArrayFromStringTypeIntegerIsInt642() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Integer); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeInt32FromStringTypeNumberIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123"; var variant = codec.Decode(str, BuiltInType.Number); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt32ArrayFromStringTypeNumberIsInt641() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[-123, -124, -125]"; var variant = codec.Decode(str, BuiltInType.Number); var expected = new Variant(new Variant[] { new(-123L), new(-124L), new(-125L) }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123, -124, -125), encoded); } [Fact] public void DecodeEncodeInt32ArrayFromStringTypeNumberIsInt642() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Number); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeInt32FromStringTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt32ArrayFromStringTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123, -124, -125"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new long[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123, -124, -125), encoded); } [Fact] public void DecodeEncodeInt32ArrayFromStringTypeNullIsInt642() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[-123, -124, -125]"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new long[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123, -124, -125), encoded); } [Fact] public void DecodeEncodeInt32ArrayFromStringTypeNullIsNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Null); var expected = Variant.Null; var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.Equal(expected, variant); } [Fact] public void DecodeEncodeInt32FromQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"-123\""; var variant = codec.Decode(str, BuiltInType.Int32); var expected = new Variant(-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt32FromSinglyQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = " '-123'"; var variant = codec.Decode(str, BuiltInType.Int32); var expected = new Variant(-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt32ArrayFromQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"-123\",'-124',\"-125\""; var variant = codec.Decode(str, BuiltInType.Int32); var expected = new Variant([-123, -124, -125]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123, -124, -125), encoded); } [Fact] public void DecodeEncodeInt32ArrayFromQuotedString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = " [\"-123\",'-124',\"-125\"] "; var variant = codec.Decode(str, BuiltInType.Int32); var expected = new Variant([-123, -124, -125]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123, -124, -125), encoded); } [Fact] public void DecodeEncodeInt32FromVariantJsonTokenTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Int32", Body = -123 }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt32ArrayFromVariantJsonTokenTypeVariant1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Int32", Body = new int[] { -123, -124, -125 } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant([-123, -124, -125]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123, -124, -125), encoded); } [Fact] public void DecodeEncodeInt32ArrayFromVariantJsonTokenTypeVariant2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Int32", Body = System.Array.Empty() }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeInt32FromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "Int32", Body = -123 }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt32ArrayFromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "Int32", Body = new int[] { -123, -124, -125 } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant([-123, -124, -125]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123, -124, -125), encoded); } [Fact] public void DecodeEncodeInt32FromVariantJsonTokenTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Int32", Body = -123 }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt32ArrayFromVariantJsonTokenTypeNull1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { TYPE = "INT32", BODY = new int[] { -123, -124, -125 } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant([-123, -124, -125]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123, -124, -125), encoded); } [Fact] public void DecodeEncodeInt32ArrayFromVariantJsonTokenTypeNull2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Int32", Body = System.Array.Empty() }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeInt32FromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "int32", Body = -123 }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt32ArrayFromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "Int32", body = new int[] { -123, -124, -125 } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant([-123, -124, -125]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123, -124, -125), encoded); } [Fact] public void DecodeEncodeInt32FromVariantJsonTokenTypeNullMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { DataType = "Int32", Value = -123 }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt32FromVariantJsonStringTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { DataType = "Int32", Value = -123 }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeInt32ArrayFromVariantJsonTokenTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { dataType = "Int32", value = new int[] { -123, -124, -125 } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant([-123, -124, -125]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123, -124, -125), encoded); } #pragma warning disable CA1814 // Prefer jagged arrays over multidimensional [Fact] public void DecodeEncodeInt32MatrixFromStringJsonStringTypeInt32() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new int[,,] { { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } } }); var variant = codec.Decode(str, BuiltInType.Int32); var expected = new Variant((object)new int[,,] { { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeInt32MatrixFromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "Int32", body = new int[,,] { { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } } } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((object)new int[,,] { { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeInt32MatrixFromVariantJsonTokenTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { dataType = "Int32", value = new int[,,] { { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } } } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((object)new int[,,] { { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeInt32MatrixFromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "Int32", body = new int[,,] { { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } } } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((object)new int[,,] { { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeInt32MatrixFromVariantJsonTokenTypeNullMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { dataType = "Int32", value = new int[,,] { { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } } } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((object)new int[,,] { { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } }, { { 123, -124, 125 }, { 123, -124, 125 }, { 123, -124, 125 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } #pragma warning restore CA1814 // Prefer jagged arrays over multidimensional private readonly NewtonsoftJsonSerializer _serializer = new(); } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Services/VariantEncoderInt64Tests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Opc.Ua; using Xunit; public class VariantEncoderInt64Tests { [Fact] public void DecodeEncodeInt64FromJValue() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(-123L); var variant = codec.Decode(str, BuiltInType.Int64); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeInt64ArrayFromJArray() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromArray(-123L, -124L, -125L); var variant = codec.Decode(str, BuiltInType.Int64); var expected = new Variant(new long[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeInt64FromJValueTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(-123L); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123L), encoded); } [Fact] public void DecodeEncodeInt64ArrayFromJArrayTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromArray(-123L, -124L, -125L); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new long[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeInt64FromString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123"; var variant = codec.Decode(str, BuiltInType.Int64); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123L), encoded); } [Fact] public void DecodeEncodeInt64ArrayFromString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123, -124, -125"; var variant = codec.Decode(str, BuiltInType.Int64); var expected = new Variant(new long[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123L, -124L, -125L), encoded); } [Fact] public void DecodeEncodeInt64ArrayFromString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[-123, -124, -125]"; var variant = codec.Decode(str, BuiltInType.Int64); var expected = new Variant(new long[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123L, -124L, -125L), encoded); } [Fact] public void DecodeEncodeInt64ArrayFromString3() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Int64); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeInt64FromStringTypeIntegerIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123"; var variant = codec.Decode(str, BuiltInType.Integer); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123L), encoded); } [Fact] public void DecodeEncodeInt64ArrayFromStringTypeIntegerIsInt641() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[-123, -124, -125]"; var variant = codec.Decode(str, BuiltInType.Integer); var expected = new Variant(new Variant[] { new(-123L), new(-124L), new(-125L) }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123L, -124L, -125L), encoded); } [Fact] public void DecodeEncodeInt64ArrayFromStringTypeIntegerIsInt642() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Integer); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeInt64FromStringTypeNumberIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123"; var variant = codec.Decode(str, BuiltInType.Number); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123L), encoded); } [Fact] public void DecodeEncodeInt64ArrayFromStringTypeNumberIsInt641() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[-123, -124, -125]"; var variant = codec.Decode(str, BuiltInType.Number); var expected = new Variant(new Variant[] { new(-123L), new(-124L), new(-125L) }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123L, -124L, -125L), encoded); } [Fact] public void DecodeEncodeInt64ArrayFromStringTypeNumberIsInt642() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Number); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeInt64FromStringTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123L), encoded); } [Fact] public void DecodeEncodeInt64ArrayFromStringTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123, -124, -125"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new long[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123L, -124L, -125L), encoded); } [Fact] public void DecodeEncodeInt64ArrayFromStringTypeNullIsInt642() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[-123, -124, -125]"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new long[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123L, -124L, -125L), encoded); } [Fact] public void DecodeEncodeInt64ArrayFromStringTypeNullIsNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Null); var expected = Variant.Null; var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.Equal(expected, variant); } [Fact] public void DecodeEncodeInt64FromQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"-123\""; var variant = codec.Decode(str, BuiltInType.Int64); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123L), encoded); } [Fact] public void DecodeEncodeInt64FromSinglyQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = " '-123'"; var variant = codec.Decode(str, BuiltInType.Int64); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123L), encoded); } [Fact] public void DecodeEncodeInt64ArrayFromQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"-123\",'-124',\"-125\""; var variant = codec.Decode(str, BuiltInType.Int64); var expected = new Variant(new long[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123L, -124L, -125L), encoded); } [Fact] public void DecodeEncodeInt64ArrayFromQuotedString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = " [\"-123\",'-124',\"-125\"] "; var variant = codec.Decode(str, BuiltInType.Int64); var expected = new Variant(new long[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123L, -124L, -125L), encoded); } [Fact] public void DecodeEncodeInt64FromVariantJsonTokenTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Int64", Body = -123 }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123L), encoded); } [Fact] public void DecodeEncodeInt64ArrayFromVariantJsonTokenTypeVariant1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Int64", Body = new long[] { -123, -124, -125 } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(new long[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123L, -124L, -125L), encoded); } [Fact] public void DecodeEncodeInt64ArrayFromVariantJsonTokenTypeVariant2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Int64", Body = System.Array.Empty() }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeInt64FromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "Int64", Body = -123 }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123L), encoded); } [Fact] public void DecodeEncodeInt64ArrayFromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "Int64", Body = new long[] { -123, -124, -125 } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(new long[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123L, -124L, -125L), encoded); } [Fact] public void DecodeEncodeInt64FromVariantJsonTokenTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Int64", Body = -123 }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123L), encoded); } [Fact] public void DecodeEncodeInt64ArrayFromVariantJsonTokenTypeNull1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { TYPE = "INT64", BODY = new long[] { -123, -124, -125 } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new long[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123L, -124L, -125L), encoded); } [Fact] public void DecodeEncodeInt64ArrayFromVariantJsonTokenTypeNull2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "Int64", Body = System.Array.Empty() }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeInt64FromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "int64", Body = -123 }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123L), encoded); } [Fact] public void DecodeEncodeInt64ArrayFromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "Int64", body = new long[] { -123, -124, -125 } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new long[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123L, -124L, -125L), encoded); } [Fact] public void DecodeEncodeInt64FromVariantJsonTokenTypeNullMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { DataType = "Int64", Value = -123 }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123L), encoded); } [Fact] public void DecodeEncodeInt64FromVariantJsonStringTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { DataType = "Int64", Value = -123 }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123L), encoded); } [Fact] public void DecodeEncodeInt64ArrayFromVariantJsonTokenTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { dataType = "Int64", value = new long[] { -123, -124, -125 } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(new long[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(-123L, -124L, -125L), encoded); } #pragma warning disable CA1814 // Prefer jagged arrays over multidimensional [Fact] public void DecodeEncodeInt64MatrixFromStringJsonTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new long[,,] { { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((object)new long[,,] { { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeInt64MatrixFromStringJsonTypeInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new long[,,] { { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } } }); var variant = codec.Decode(str, BuiltInType.Int64); var expected = new Variant((object)new long[,,] { { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeInt64MatrixFromVariantJsonTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "Int64", body = new long[,,] { { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } } } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((object)new long[,,] { { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeInt64MatrixFromVariantJsonTokenTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { dataType = "Int64", value = new long[,,] { { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } } } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((object)new long[,,] { { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeInt64MatrixFromVariantJsonTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "Int64", body = new long[,,] { { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } } } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((object)new long[,,] { { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeInt64MatrixFromVariantJsonTokenTypeNullMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { dataType = "Int64", value = new long[,,] { { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } } } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((object)new long[,,] { { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } }, { { 123L, -124L, -125L }, { 123L, -124L, -125L }, { 123L, -124L, -125L } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } #pragma warning restore CA1814 // Prefer jagged arrays over multidimensional private readonly NewtonsoftJsonSerializer _serializer = new(); } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Services/VariantEncoderMiscTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Opc.Ua; using Opc.Ua.Extensions; using System.Xml; using Xunit; public class VariantEncoderMiscTests { [Fact] public void DecodeEncodeStringAsUInt32() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123"; var variant = codec.Decode(str, BuiltInType.UInt32); var expected = new Variant(123u); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeStringAsInt32() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-1"; var variant = codec.Decode(str, BuiltInType.Int32); var expected = new Variant(-1); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeStringAsSbyte() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-12"; var variant = codec.Decode(str, BuiltInType.SByte); var expected = new Variant((sbyte)-12); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeStringAsByte() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "1"; var variant = codec.Decode(str, BuiltInType.Byte); var expected = new Variant((byte)1); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeString1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\\\"fffffffff\\\""; var variant = codec.Decode(str, BuiltInType.String); var expected = new Variant(str); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "fffffffff"; var variant = codec.Decode(str, BuiltInType.String); var expected = new Variant(str); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeString3() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"fffffffff\""; var variant = codec.Decode(str, BuiltInType.String); var expected = new Variant("fffffffff"); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal("fffffffff", encoded); } [Fact] public void DecodeEncodeIntArray1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "1,2,3,4,5,6"; var variant = codec.Decode(str, BuiltInType.Int32); var expected = new Variant([1, 2, 3, 4, 5, 6]); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.Equal(expected, variant); } [Fact] public void DecodeEncodeIntArray2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[1,2,3,4,5,6]"; var variant = codec.Decode(str, BuiltInType.Int32); var expected = new Variant([1, 2, 3, 4, 5, 6]); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.Equal(expected, variant); } [Fact] public void DecodeEncodeStringArray() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"test1\", \"test2\""; var variant = codec.Decode(str, BuiltInType.String); var expected = new Variant(["test1", "test2"]); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.Equal(expected, variant); } [Fact] public void DecodeEmptyStringArray() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.String); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.True(encoded.Equals(str)); Assert.Equal(str, encoded); } [Fact] public void DecodeEmptyShortArray() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Int16); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.True(encoded.Equals(str)); Assert.Equal(str, encoded); } [Fact] public void EncodeDecodeXmlElement() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var doc = new XmlDocument(); doc.LoadXml( """ Tove Jani Reminder Don't forget me this weekend! """ ); var expected = new Variant(doc.DocumentElement); var encoded = codec.Encode(expected); var variant = codec.Decode(encoded, BuiltInType.XmlElement); Assert.Equal(expected, variant); } [Fact] public void EncodeDecodeLocalizedText() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var expected = new Variant(new LocalizedText("en-US", "text")); var encoded = codec.Encode(expected); var variant = codec.Decode(encoded, BuiltInType.LocalizedText); Assert.Equal(expected, variant); } [Fact] public void EncodeDecodeLocalizedTextFromString1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "text@en-US"; var expected = new Variant(new LocalizedText("en-US", "text")); var variant = codec.Decode(str, BuiltInType.LocalizedText); var encoded = codec.Encode(expected); Assert.NotNull(encoded); Assert.Equal(expected, variant); } [Fact] public void EncodeDecodeLocalizedTextFromString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "text"; var expected = new Variant(new LocalizedText("text")); var variant = codec.Decode(str, BuiltInType.LocalizedText); var encoded = codec.Encode(expected); Assert.NotNull(encoded); Assert.Equal(expected, variant); } [Fact] public void EncodeDecodeNodeId() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var expected = new Variant(new NodeId(2354)); var encoded = codec.Encode(expected); var variant = codec.Decode(encoded, BuiltInType.NodeId); Assert.Equal(expected, variant); } [Fact] public void EncodeDecodeExpandedNodeId1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var expected = new Variant(new ExpandedNodeId(2354u, 0, "http://test.org/test", 0)); var encoded = codec.Encode(expected); var variant = codec.Decode(encoded, BuiltInType.ExpandedNodeId); Assert.Equal(expected, variant); } [Fact] public void EncodeDecodeExpandedNodeId2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var expected = new Variant(new ExpandedNodeId(2354u, 0, "http://test/", 0)); var encoded = codec.Encode(expected); var variant = codec.Decode(encoded, BuiltInType.ExpandedNodeId); Assert.Equal(expected, variant); } [Fact] public void EncodeDecodeExpandedNodeId3() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var expected1 = new Variant(new ExpandedNodeId(2354u, 0, "http://test/", 0)); var expected2 = new Variant(new ExpandedNodeId(2354u, 0, "http://test/UA", 0)); var expected3 = new Variant(new ExpandedNodeId(2355u, 0, "http://test/", 0)); var expected4 = new Variant(new ExpandedNodeId(2355u, 0, null, 0)); var expected5 = new Variant(new ExpandedNodeId(new NodeId(2355u, 1), "http://test/", 0)); var encoded1 = codec.Encode(expected1); var encoded2 = codec.Encode(expected2); var encoded3 = codec.Encode(expected3); var encoded4 = codec.Encode(expected4); var encoded5 = codec.Encode(expected5); var variant1 = codec.Decode(encoded1, BuiltInType.ExpandedNodeId); var variant2 = codec.Decode(encoded2, BuiltInType.ExpandedNodeId); var variant3 = codec.Decode(encoded3, BuiltInType.ExpandedNodeId); var variant4 = codec.Decode(encoded4, BuiltInType.ExpandedNodeId); var variant5 = codec.Decode(encoded5, BuiltInType.ExpandedNodeId); Assert.Equal(expected1, variant1); Assert.Equal(expected2, variant2); Assert.Equal(expected3, variant3); Assert.Equal(expected4, variant4); Assert.Equal(expected5, variant5); } [Fact] public void EncodeDecodeArgument1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var expected = new Variant(new ExtensionObject { Body = new Argument("something1", new NodeId(2354), -1, "somedesciroeioi") { ArrayDimensions = System.Array.Empty() }, TypeId = DataTypeIds.Argument }); var encoded = codec.Encode(expected); var variant = codec.Decode(encoded, BuiltInType.ExtensionObject); var obj = variant.Value as ExtensionObject; Assert.NotNull(obj); Assert.Equal(ExtensionObjectEncoding.EncodeableObject, obj.Encoding); Assert.True(obj.Body is Argument); Assert.Equal(expected, variant); } [Fact] public void EncodeDecodeArgument2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var expected = new Variant(new ExtensionObject { Body = new Argument("something2", new NodeId(2334), -1, "asdfsadfffd") { ArrayDimensions = System.Array.Empty() }.AsXmlElement(ServiceMessageContext.GlobalContext), TypeId = new ExpandedNodeId(444444, "http://test.org") }); var encoded = codec.Encode(expected); var variant = codec.Decode(encoded, BuiltInType.ExtensionObject); var obj = variant.Value as ExtensionObject; Assert.NotNull(obj); Assert.Equal(ExtensionObjectEncoding.Xml, obj.Encoding); Assert.True(obj.Body is XmlElement); Assert.Equal(expected, variant); } [Fact] public void EncodeDecodeArgument3() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var expected = new Variant(new ExtensionObject { Body = new Argument("something3", new NodeId(2364), -1, "dd f s fdd fd") { ArrayDimensions = System.Array.Empty() }.AsBinary(ServiceMessageContext.GlobalContext), TypeId = new ExpandedNodeId(444445, "http://test.org/") }); var encoded = codec.Encode(expected); var variant = codec.Decode(encoded, BuiltInType.ExtensionObject); var obj = variant.Value as ExtensionObject; Assert.NotNull(obj); Assert.Equal(ExtensionObjectEncoding.Binary, obj.Encoding); Assert.True(obj.Body is byte[]); Assert.Equal(expected, variant); } private readonly IJsonSerializer _serializer = new NewtonsoftJsonSerializer(); } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Services/VariantEncoderSByteTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Opc.Ua; using Xunit; public class VariantEncoderSByteTests { [Fact] public void DecodeEncodeSByteFromJValue() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(-123); var variant = codec.Decode(str, BuiltInType.SByte); var expected = new Variant((sbyte)-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeSByteArrayFromJArray() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromArray((sbyte)-123, (sbyte)-124, (sbyte)-125); var variant = codec.Decode(str, BuiltInType.SByte); var expected = new Variant(new sbyte[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeSByteFromJValueTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(-123); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeSByteArrayFromJArrayTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromArray((sbyte)-123, (sbyte)-124, (sbyte)-125); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new long[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeSByteFromString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123"; var variant = codec.Decode(str, BuiltInType.SByte); var expected = new Variant((sbyte)-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeSByteArrayFromString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123, -124, -125"; var variant = codec.Decode(str, BuiltInType.SByte); var expected = new Variant(new sbyte[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((sbyte)-123, (sbyte)-124, (sbyte)-125), encoded); } [Fact] public void DecodeEncodeSByteArrayFromString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[-123, -124, -125]"; var variant = codec.Decode(str, BuiltInType.SByte); var expected = new Variant(new sbyte[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((sbyte)-123, (sbyte)-124, (sbyte)-125), encoded); } [Fact] public void DecodeEncodeSByteArrayFromString3() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.SByte); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeSByteFromStringTypeIntegerIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123"; var variant = codec.Decode(str, BuiltInType.Integer); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeSByteArrayFromStringTypeIntegerIsInt641() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[-123, -124, -125]"; var variant = codec.Decode(str, BuiltInType.Integer); var expected = new Variant(new Variant[] { new(-123L), new(-124L), new(-125L) }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((sbyte)-123, (sbyte)-124, (sbyte)-125), encoded); } [Fact] public void DecodeEncodeSByteArrayFromStringTypeIntegerIsInt642() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Integer); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeSByteFromStringTypeNumberIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123"; var variant = codec.Decode(str, BuiltInType.Number); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeSByteArrayFromStringTypeNumberIsInt641() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[-123, -124, -125]"; var variant = codec.Decode(str, BuiltInType.Number); var expected = new Variant(new Variant[] { new(-123L), new(-124L), new(-125L) }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((sbyte)-123, (sbyte)-124, (sbyte)-125), encoded); } [Fact] public void DecodeEncodeSByteArrayFromStringTypeNumberIsInt642() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Number); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeSByteFromStringTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(-123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeSByteArrayFromStringTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "-123, -124, -125"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new long[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((sbyte)-123, (sbyte)-124, (sbyte)-125), encoded); } [Fact] public void DecodeEncodeSByteArrayFromStringTypeNullIsInt642() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[-123, -124, -125]"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new long[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((sbyte)-123, (sbyte)-124, (sbyte)-125), encoded); } [Fact] public void DecodeEncodeSByteArrayFromStringTypeNullIsNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Null); var expected = Variant.Null; var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.Equal(expected, variant); } [Fact] public void DecodeEncodeSByteFromQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"-123\""; var variant = codec.Decode(str, BuiltInType.SByte); var expected = new Variant((sbyte)-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeSByteFromSinglyQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = " '-123'"; var variant = codec.Decode(str, BuiltInType.SByte); var expected = new Variant((sbyte)-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeSByteArrayFromQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"-123\",'-124',\"-125\""; var variant = codec.Decode(str, BuiltInType.SByte); var expected = new Variant(new sbyte[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((sbyte)-123, (sbyte)-124, (sbyte)-125), encoded); } [Fact] public void DecodeEncodeSByteArrayFromQuotedString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = " [\"-123\",'-124',\"-125\"] "; var variant = codec.Decode(str, BuiltInType.SByte); var expected = new Variant(new sbyte[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((sbyte)-123, (sbyte)-124, (sbyte)-125), encoded); } [Fact] public void DecodeEncodeSByteFromVariantJsonTokenTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "SByte", Body = -123 }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((sbyte)-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeSByteArrayFromVariantJsonTokenTypeVariant1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "SByte", Body = new sbyte[] { -123, -124, -125 } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(new sbyte[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((sbyte)-123, (sbyte)-124, (sbyte)-125), encoded); } [Fact] public void DecodeEncodeSByteArrayFromVariantJsonTokenTypeVariant2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "SByte", Body = System.Array.Empty() }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeSByteFromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "SByte", Body = -123 }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((sbyte)-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeSByteArrayFromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "SByte", Body = new sbyte[] { -123, -124, -125 } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(new sbyte[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((sbyte)-123, (sbyte)-124, (sbyte)-125), encoded); } [Fact] public void DecodeEncodeSByteFromVariantJsonTokenTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "SByte", Body = (sbyte)-123 }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((sbyte)-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeSByteArrayFromVariantJsonTokenTypeNull1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { TYPE = "SBYTE", BODY = new sbyte[] { -123, -124, -125 } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new sbyte[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((sbyte)-123, (sbyte)-124, (sbyte)-125), encoded); } [Fact] public void DecodeEncodeSByteArrayFromVariantJsonTokenTypeNull2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "SByte", Body = System.Array.Empty() }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeSByteFromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "sbyte", Body = (sbyte)-123 }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((sbyte)-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeSByteArrayFromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "SByte", body = new sbyte[] { -123, -124, -125 } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new sbyte[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((sbyte)-123, (sbyte)-124, (sbyte)-125), encoded); } [Fact] public void DecodeEncodeSByteFromVariantJsonTokenTypeNullMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { DataType = "SByte", Value = -123 }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((sbyte)-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeSByteFromVariantJsonStringTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { DataType = "SByte", Value = (sbyte)-123 }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((sbyte)-123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(-123), encoded); } [Fact] public void DecodeEncodeSByteArrayFromVariantJsonTokenTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { dataType = "SByte", value = new sbyte[] { -123, -124, -125 } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(new sbyte[] { -123, -124, -125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((sbyte)-123, (sbyte)-124, (sbyte)-125), encoded); } #pragma warning disable CA1814 // Prefer jagged arrays over multidimensional [Fact] public void DecodeEncodeSByteMatrixFromStringJsonTypeSByte() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new sbyte[,,] { { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } } }); var variant = codec.Decode(str, BuiltInType.SByte); var expected = new Variant((object)new sbyte[,,] { { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeSByteMatrixFromVariantJsonTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "SByte", body = new sbyte[,,] { { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } } } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((object)new sbyte[,,] { { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeSByteMatrixFromVariantJsonTokenTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { dataType = "SByte", value = new sbyte[,,] { { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } } } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((object)new sbyte[,,] { { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeSByteMatrixFromVariantJsonTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "SByte", body = new sbyte[,,] { { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } } } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((object)new sbyte[,,] { { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeSByteMatrixFromVariantJsonTokenTypeNullMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { dataType = "SByte", value = new sbyte[,,] { { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } } } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((object)new sbyte[,,] { { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } }, { { 123, -124, -125 }, { 123, -124, -125 }, { 123, -124, -125 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } #pragma warning restore CA1814 // Prefer jagged arrays over multidimensional private readonly NewtonsoftJsonSerializer _serializer = new(); } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Services/VariantEncoderStringTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Opc.Ua; using Xunit; public class VariantEncoderStringTests { [Fact] public void DecodeEncodeStringFromJValue() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(""); var variant = codec.Decode(str, BuiltInType.String); var expected = new Variant(""); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeStringArrayFromJArray() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromArray("", "", ""); var variant = codec.Decode(str, BuiltInType.String); var expected = new Variant(["", "", ""]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeStringFromJValueTypeNullIsString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(""); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(""); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(""), encoded); } [Fact] public void DecodeEncodeStringArrayFromJArrayTypeNullIsString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromArray("", "", ""); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(["", "", ""]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeStringFromString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123"; var variant = codec.Decode(str, BuiltInType.String); var expected = new Variant("123"); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject("123"), encoded); } [Fact] public void DecodeEncodeStringFromString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123, 124, 125"; var variant = codec.Decode(str, BuiltInType.String); var expected = new Variant("123, 124, 125"); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeStringFromString3() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[test, test, test]"; var variant = codec.Decode(str, BuiltInType.String); var expected = new Variant(str); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeStringArrayFromString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[123, 124, 125]"; var variant = codec.Decode(str, BuiltInType.String); var expected = new Variant(["123", "124", "125"]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray("123", "124", "125"), encoded); } [Fact] public void DecodeEncodeStringArrayFromString4() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.String); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeStringFromStringTypeNullIsString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "test"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant("test"); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject("test"), encoded); } [Fact] public void DecodeEncodeStringArrayFromStringTypeNullIsString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "test, test, test"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(["test", "test", "test"]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray("test", "test", "test"), encoded); } [Fact] public void DecodeEncodeStringArrayFromStringTypeNullIsString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[\"test\", \"test\", \"test\"]"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(["test", "test", "test"]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray("test", "test", "test"), encoded); } [Fact] public void DecodeEncodeStringArrayFromStringTypeNullIsString3() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[test, test, test]"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(["[test", "test", "test]"]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray("[test", "test", "test]"), encoded); } [Fact] public void DecodeEncodeStringArrayFromStringTypeNullIsNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Null); var expected = Variant.Null; var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.Equal(expected, variant); } [Fact] public void DecodeEncodeStringFromQuotedString1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"test\""; var variant = codec.Decode(str, BuiltInType.String); var expected = new Variant("test"); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject("test"), encoded); } [Fact] public void DecodeEncodeStringFromQuotedString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"\\\"test\\\"\""; var variant = codec.Decode(str, BuiltInType.String); var expected = new Variant("\"test\""); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject("\"test\""), encoded); } [Fact] public void DecodeEncodeStringFromSinglyQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = " 'test'"; var variant = codec.Decode(str, BuiltInType.String); var expected = new Variant("test"); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject("test"), encoded); } [Fact] public void DecodeEncodeStringArrayFromQuotedString1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"test\",'test',\"test\""; var variant = codec.Decode(str, BuiltInType.String); var expected = new Variant(["test", "test", "test"]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray("test", "test", "test"), encoded); } [Fact] public void DecodeEncodeStringArrayFromQuotedString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = " [\"test\",'test',\"test\"] "; var variant = codec.Decode(str, BuiltInType.String); var expected = new Variant(["test", "test", "test"]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray("test", "test", "test"), encoded); } [Fact] public void DecodeEncodeStringArrayFromQuotedString3() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = " [\"\\\"test\\\"\",'\\\"test\\\"',\"\\\"test\\\"\"] "; var variant = codec.Decode(str, BuiltInType.String); var expected = new Variant(["test", "test", "test"]); // TODO: var expected = new Variant(new string[] { "\"test\"", "\"test\"", "\"test\"" }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); // TODO: Assert.Equal(_serializer.FromArray("\"test\"", "\"test\"", "\"test\""), encoded); Assert.Equal(_serializer.FromArray("test", "test", "test"), encoded); } [Fact] public void DecodeEncodeStringFromVariantJsonTokenTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "String", Body = "" }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(""); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(""), encoded); } [Fact] public void DecodeEncodeStringArrayFromVariantJsonTokenTypeVariant1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "String", Body = new string[] { "", "", "" } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(["", "", ""]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray("", "", ""), encoded); } [Fact] public void DecodeEncodeStringArrayFromVariantJsonTokenTypeVariant2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "String", Body = System.Array.Empty() }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeStringFromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "String", Body = "" }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(""); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(""), encoded); } [Fact] public void DecodeEncodeStringArrayFromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "String", Body = new string[] { "", "", "" } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(["", "", ""]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray("", "", ""), encoded); } [Fact] public void DecodeEncodeStringFromVariantJsonTokenTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "String", Body = "" }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(""); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(""), encoded); } [Fact] public void DecodeEncodeStringArrayFromVariantJsonTokenTypeNull1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { TYPE = "STRING", BODY = new string[] { "", "", "" } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(["", "", ""]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray("", "", ""), encoded); } [Fact] public void DecodeEncodeStringArrayFromVariantJsonTokenTypeNull2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "String", Body = System.Array.Empty() }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeStringFromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "string", Body = "" }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(""); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(""), encoded); } [Fact] public void DecodeEncodeStringArrayFromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "String", body = new string[] { "", "", "" } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(["", "", ""]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray("", "", ""), encoded); } [Fact] public void DecodeEncodeStringFromVariantJsonTokenTypeNullMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { DataType = "String", Value = "" }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(""); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(""), encoded); } [Fact] public void DecodeEncodeStringFromVariantJsonStringTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { DataType = "String", Value = "" }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(""); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(""), encoded); } [Fact] public void DecodeEncodeStringArrayFromVariantJsonTokenTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { dataType = "String", value = new string[] { "", "", "" } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(["", "", ""]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray("", "", ""), encoded); } #pragma warning disable CA1814 // Prefer jagged arrays over multidimensional [Fact] public void DecodeEncodeStringMatrixFromStringJsonTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new string[,,] { { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((object)new string[,,] { { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeStringMatrixFromStringJsonTypeString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new string[,,] { { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } } }); var variant = codec.Decode(str, BuiltInType.String); var expected = new Variant((object)new string[,,] { { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeStringMatrixFromVariantJsonTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "String", body = new string[,,] { { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } } } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((object)new string[,,] { { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeStringMatrixFromVariantJsonTokenTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { dataType = "String", value = new string[,,] { { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } } } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((object)new string[,,] { { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeStringMatrixFromVariantJsonTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "String", body = new string[,,] { { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } } } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((object)new string[,,] { { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeStringMatrixFromVariantJsonTokenTypeNullMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { dataType = "String", value = new string[,,] { { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } } } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((object)new string[,,] { { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } }, { { "test", "zhf", "33" }, { "test", "zhf", "33" }, { "test", "zhf", "33" } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } #pragma warning restore CA1814 // Prefer jagged arrays over multidimensional private readonly NewtonsoftJsonSerializer _serializer = new(); } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Services/VariantEncoderUInt16Tests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Opc.Ua; using Xunit; public class VariantEncoderUInt16Tests { [Fact] public void DecodeEncodeUInt16FromJValue() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(123); var variant = codec.Decode(str, BuiltInType.UInt16); var expected = new Variant((ushort)123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeUInt16ArrayFromJArray() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromArray((ushort)123, (ushort)124, (ushort)125); var variant = codec.Decode(str, BuiltInType.UInt16); var expected = new Variant(new ushort[] { 123, 124, 125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeUInt16FromJValueTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(123); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeUInt16ArrayFromJArrayTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromArray((ushort)123, (ushort)124, (ushort)125); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new long[] { 123, 124, 125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeUInt16FromString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123"; var variant = codec.Decode(str, BuiltInType.UInt16); var expected = new Variant((ushort)123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeUInt16ArrayFromString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123, 124, 125"; var variant = codec.Decode(str, BuiltInType.UInt16); var expected = new Variant(new ushort[] { 123, 124, 125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((ushort)123, (ushort)124, (ushort)125), encoded); } [Fact] public void DecodeEncodeUInt16ArrayFromString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[123, 124, 125]"; var variant = codec.Decode(str, BuiltInType.UInt16); var expected = new Variant(new ushort[] { 123, 124, 125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((ushort)123, (ushort)124, (ushort)125), encoded); } [Fact] public void DecodeEncodeUInt16ArrayFromString3() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.UInt16); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeUInt16FromStringTypeIntegerIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123"; var variant = codec.Decode(str, BuiltInType.Integer); var expected = new Variant(123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeUInt16ArrayFromStringTypeIntegerIsInt641() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[123, 124, 125]"; var variant = codec.Decode(str, BuiltInType.Integer); var expected = new Variant(new Variant[] { new(123L), new(124L), new(125L) }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((ushort)123, (ushort)124, (ushort)125), encoded); } [Fact] public void DecodeEncodeUInt16ArrayFromStringTypeIntegerIsInt642() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Integer); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeUInt16FromStringTypeNumberIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123"; var variant = codec.Decode(str, BuiltInType.Number); var expected = new Variant(123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeUInt16ArrayFromStringTypeNumberIsInt641() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[123, 124, 125]"; var variant = codec.Decode(str, BuiltInType.Number); var expected = new Variant(new Variant[] { new(123L), new(124L), new(125L) }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((ushort)123, (ushort)124, (ushort)125), encoded); } [Fact] public void DecodeEncodeUInt16ArrayFromStringTypeNumberIsInt642() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Number); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeUInt16FromStringTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeUInt16ArrayFromStringTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123, 124, 125"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new long[] { 123, 124, 125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((ushort)123, (ushort)124, (ushort)125), encoded); } [Fact] public void DecodeEncodeUInt16ArrayFromStringTypeNullIsInt642() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[123, 124, 125]"; var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new long[] { 123, 124, 125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((ushort)123, (ushort)124, (ushort)125), encoded); } [Fact] public void DecodeEncodeUInt16ArrayFromStringTypeNullIsNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(str, BuiltInType.Null); var expected = Variant.Null; var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.Equal(expected, variant); } [Fact] public void DecodeEncodeUInt16FromQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"123\""; var variant = codec.Decode(str, BuiltInType.UInt16); var expected = new Variant((ushort)123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeUInt16FromSinglyQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = " '123'"; var variant = codec.Decode(str, BuiltInType.UInt16); var expected = new Variant((ushort)123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeUInt16ArrayFromQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"123\",'124',\"125\""; var variant = codec.Decode(str, BuiltInType.UInt16); var expected = new Variant(new ushort[] { 123, 124, 125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((ushort)123, (ushort)124, (ushort)125), encoded); } [Fact] public void DecodeEncodeUInt16ArrayFromQuotedString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = " [\"123\",'124',\"125\"] "; var variant = codec.Decode(str, BuiltInType.UInt16); var expected = new Variant(new ushort[] { 123, 124, 125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((ushort)123, (ushort)124, (ushort)125), encoded); } [Fact] public void DecodeEncodeUInt16FromVariantJsonTokenTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "UInt16", Body = 123 }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((ushort)123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeUInt16ArrayFromVariantJsonTokenTypeVariant1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "UInt16", Body = new ushort[] { 123, 124, 125 } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(new ushort[] { 123, 124, 125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((ushort)123, (ushort)124, (ushort)125), encoded); } [Fact] public void DecodeEncodeUInt16ArrayFromVariantJsonTokenTypeVariant2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "UInt16", Body = System.Array.Empty() }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeUInt16FromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "UInt16", Body = 123 }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant((ushort)123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeUInt16ArrayFromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "UInt16", Body = new ushort[] { 123, 124, 125 } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(new ushort[] { 123, 124, 125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((ushort)123, (ushort)124, (ushort)125), encoded); } [Fact] public void DecodeEncodeUInt16FromVariantJsonTokenTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "UInt16", Body = (ushort)123 }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((ushort)123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeUInt16ArrayFromVariantJsonTokenTypeNull1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { TYPE = "UINT16", BODY = new ushort[] { 123, 124, 125 } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new ushort[] { 123, 124, 125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((ushort)123, (ushort)124, (ushort)125), encoded); } [Fact] public void DecodeEncodeUInt16ArrayFromVariantJsonTokenTypeNull2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "UInt16", Body = System.Array.Empty() }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeUInt16FromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "uint16", Body = (ushort)123 }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((ushort)123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeUInt16ArrayFromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "UInt16", body = new ushort[] { 123, 124, 125 } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new ushort[] { 123, 124, 125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((ushort)123, (ushort)124, (ushort)125), encoded); } [Fact] public void DecodeEncodeUInt16FromVariantJsonTokenTypeNullMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { DataType = "UInt16", Value = 123 }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant((ushort)123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeUInt16FromVariantJsonStringTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { DataType = "UInt16", Value = (ushort)123 }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Variant); var expected = new Variant((ushort)123); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123), encoded); } [Fact] public void DecodeEncodeUInt16ArrayFromVariantJsonTokenTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { dataType = "UInt16", value = new ushort[] { 123, 124, 125 } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(new ushort[] { 123, 124, 125 }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray((ushort)123, (ushort)124, (ushort)125), encoded); } #pragma warning disable CA1814 // Prefer jagged arrays over multidimensional [Fact] public void DecodeEncodeUInt16MatrixFromStringJsonStringTypeUInt16() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new ushort[,,] { { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } } }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.UInt16); var expected = new Variant((object)new ushort[,,] { { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeUInt16MatrixFromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "UInt16", body = new ushort[,,] { { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } } } }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Variant); var expected = new Variant((object)new ushort[,,] { { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeUInt16MatrixFromVariantJsonTokenTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { dataType = "UInt16", value = new ushort[,,] { { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } } } }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Variant); var expected = new Variant((object)new ushort[,,] { { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeUInt16MatrixFromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "UInt16", body = new ushort[,,] { { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } } } }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Null); var expected = new Variant((object)new ushort[,,] { { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeUInt16MatrixFromVariantJsonTokenTypeNullMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { dataType = "UInt16", value = new ushort[,,] { { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } } } }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Null); var expected = new Variant((object)new ushort[,,] { { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } }, { { 123, 124, 125 }, { 123, 124, 125 }, { 123, 124, 125 } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } #pragma warning restore CA1814 // Prefer jagged arrays over multidimensional private readonly NewtonsoftJsonSerializer _serializer = new(); } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Services/VariantEncoderUInt32Tests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Opc.Ua; using Xunit; public class VariantEncoderUInt32Tests { [Fact] public void DecodeEncodeUInt32FromJValue() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(123u); var variant = codec.Decode(str, BuiltInType.UInt32); var expected = new Variant(123u); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeUInt32ArrayFromJArray() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromArray(123u, 124u, 125u); var variant = codec.Decode(str, BuiltInType.UInt32); var expected = new Variant([123u, 124u, 125u]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeUInt32FromJValueTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(123u); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123u), encoded); } [Fact] public void DecodeEncodeUInt32ArrayFromJArrayTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromArray(123u, 124u, 125u); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(new long[] { 123u, 124u, 125u }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeUInt32FromString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.UInt32); var expected = new Variant(123u); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123u), encoded); } [Fact] public void DecodeEncodeUInt32ArrayFromString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123, 124, 125"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.UInt32); var expected = new Variant([123u, 124u, 125u]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123u, 124u, 125u), encoded); } [Fact] public void DecodeEncodeUInt32ArrayFromString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[123, 124, 125]"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.UInt32); var expected = new Variant([123u, 124u, 125u]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123u, 124u, 125u), encoded); } [Fact] public void DecodeEncodeUInt32ArrayFromString3() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.UInt32); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeUInt32FromStringTypeIntegerIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Integer); var expected = new Variant(123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123u), encoded); } [Fact] public void DecodeEncodeUInt32ArrayFromStringTypeIntegerIsInt641() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[123, 124, 125]"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Integer); var expected = new Variant(new Variant[] { new(123L), new(124L), new(125L) }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123u, 124u, 125u), encoded); } [Fact] public void DecodeEncodeUInt32ArrayFromStringTypeIntegerIsInt642() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Integer); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeUInt32FromStringTypeNumberIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Number); var expected = new Variant(123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123u), encoded); } [Fact] public void DecodeEncodeUInt32ArrayFromStringTypeNumberIsInt641() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[123, 124, 125]"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Number); var expected = new Variant(new Variant[] { new(123L), new(124L), new(125L) }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123u, 124u, 125u), encoded); } [Fact] public void DecodeEncodeUInt32ArrayFromStringTypeNumberIsInt642() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Number); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeUInt32FromStringTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Null); var expected = new Variant(123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123u), encoded); } [Fact] public void DecodeEncodeUInt32ArrayFromStringTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123, 124, 125"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Null); var expected = new Variant(new long[] { 123u, 124u, 125u }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123u, 124u, 125u), encoded); } [Fact] public void DecodeEncodeUInt32ArrayFromStringTypeNullIsInt642() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[123, 124, 125]"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Null); var expected = new Variant(new long[] { 123u, 124u, 125u }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123u, 124u, 125u), encoded); } [Fact] public void DecodeEncodeUInt32ArrayFromStringTypeNullIsNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Null); var expected = Variant.Null; var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.Equal(expected, variant); } [Fact] public void DecodeEncodeUInt32FromQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"123\""; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.UInt32); var expected = new Variant(123u); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123u), encoded); } [Fact] public void DecodeEncodeUInt32FromSinglyQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = " '123'"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.UInt32); var expected = new Variant(123u); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123u), encoded); } [Fact] public void DecodeEncodeUInt32ArrayFromQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"123\",'124',\"125\""; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.UInt32); var expected = new Variant([123u, 124u, 125u]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123u, 124u, 125u), encoded); } [Fact] public void DecodeEncodeUInt32ArrayFromQuotedString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = " [\"123\",'124',\"125\"] "; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.UInt32); var expected = new Variant([123u, 124u, 125u]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123u, 124u, 125u), encoded); } [Fact] public void DecodeEncodeUInt32FromVariantJsonTokenTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "UInt32", Body = 123u }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(123u); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123u), encoded); } [Fact] public void DecodeEncodeUInt32ArrayFromVariantJsonTokenTypeVariant1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "UInt32", Body = new uint[] { 123u, 124u, 125u } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant([123u, 124u, 125u]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123u, 124u, 125u), encoded); } [Fact] public void DecodeEncodeUInt32ArrayFromVariantJsonTokenTypeVariant2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "UInt32", Body = System.Array.Empty() }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeUInt32FromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "UInt32", Body = 123u }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Variant); var expected = new Variant(123u); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123u), encoded); } [Fact] public void DecodeEncodeUInt32ArrayFromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "UInt32", Body = new uint[] { 123u, 124u, 125u } }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Variant); var expected = new Variant([123u, 124u, 125u]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123u, 124u, 125u), encoded); } [Fact] public void DecodeEncodeUInt32FromVariantJsonTokenTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "UInt32", Body = 123u }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(123u); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123u), encoded); } [Fact] public void DecodeEncodeUInt32ArrayFromVariantJsonTokenTypeNull1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { TYPE = "UINT32", BODY = new uint[] { 123u, 124u, 125u } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant([123u, 124u, 125u]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123u, 124u, 125u), encoded); } [Fact] public void DecodeEncodeUInt32ArrayFromVariantJsonTokenTypeNull2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "UInt32", Body = System.Array.Empty() }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeUInt32FromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "uint32", Body = 123u }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Null); var expected = new Variant(123u); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123u), encoded); } [Fact] public void DecodeEncodeUInt32ArrayFromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "UInt32", body = new uint[] { 123u, 124u, 125u } }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Null); var expected = new Variant([123u, 124u, 125u]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123u, 124u, 125u), encoded); } [Fact] public void DecodeEncodeUInt32FromVariantJsonTokenTypeNullMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { DataType = "UInt32", Value = 123u }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(123u); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123u), encoded); } [Fact] public void DecodeEncodeUInt32FromVariantJsonStringTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { DataType = "UInt32", Value = 123u }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Variant); var expected = new Variant(123u); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123u), encoded); } [Fact] public void DecodeEncodeUInt32ArrayFromVariantJsonTokenTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { dataType = "UInt32", value = new uint[] { 123u, 124u, 125u } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant([123u, 124u, 125u]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123u, 124u, 125u), encoded); } #pragma warning disable CA1814 // Prefer jagged arrays over multidimensional [Fact] public void DecodeEncodeUInt32MatrixFromStringJsonStringTypeUInt32() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new uint[,,] { { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } } }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.UInt32); var expected = new Variant((object)new uint[,,] { { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeUInt32MatrixFromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "UInt32", body = new uint[,,] { { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } } } }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Variant); var expected = new Variant((object)new uint[,,] { { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeUInt32MatrixFromVariantJsonTokenTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { dataType = "UInt32", value = new uint[,,] { { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } } } }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Variant); var expected = new Variant((object)new uint[,,] { { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeUInt32MatrixFromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "UInt32", body = new uint[,,] { { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } } } }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Null); var expected = new Variant((object)new uint[,,] { { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeUInt32MatrixFromVariantJsonTokenTypeNullMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { dataType = "UInt32", value = new uint[,,] { { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } } } }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Null); var expected = new Variant((object)new uint[,,] { { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } }, { { 123u, 124u, 125u }, { 123u, 124u, 125u }, { 123u, 124u, 125u } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } #pragma warning restore CA1814 // Prefer jagged arrays over multidimensional private readonly NewtonsoftJsonSerializer _serializer = new(); } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/Services/VariantEncoderUInt64Tests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Opc.Ua; using Xunit; public class VariantEncoderUInt64Tests { [Fact] public void DecodeEncodeUInt64FromJValue() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(123Lu); var variant = codec.Decode(str, BuiltInType.UInt64); var expected = new Variant(123Lu); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeUInt64ArrayFromJArray() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromArray(123Lu, 124Lu, 125Lu); var variant = codec.Decode(str, BuiltInType.UInt64); var expected = new Variant([123Lu, 124Lu, 125Lu]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeUInt64FromJValueTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(123Lu); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123Lu), encoded); } [Fact] public void DecodeEncodeUInt64ArrayFromJArrayTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromArray(123Lu, 124Lu, 125Lu); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant([123L, 124L, 125L]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(str, encoded); } [Fact] public void DecodeEncodeUInt64FromString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.UInt64); var expected = new Variant(123Lu); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123Lu), encoded); } [Fact] public void DecodeEncodeUInt64ArrayFromString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123, 124, 125"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.UInt64); var expected = new Variant([123Lu, 124Lu, 125Lu]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123Lu, 124Lu, 125Lu), encoded); } [Fact] public void DecodeEncodeUInt64ArrayFromString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[123, 124, 125]"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.UInt64); var expected = new Variant([123Lu, 124Lu, 125Lu]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123Lu, 124Lu, 125Lu), encoded); } [Fact] public void DecodeEncodeUInt64ArrayFromString3() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.UInt64); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeUInt64FromStringTypeIntegerIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Integer); var expected = new Variant(123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123Lu), encoded); } [Fact] public void DecodeEncodeUInt64ArrayFromStringTypeIntegerIsInt641() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[123, 124, 125]"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Integer); var expected = new Variant(new Variant[] { new(123L), new(124L), new(125L) }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123Lu, 124Lu, 125Lu), encoded); } [Fact] public void DecodeEncodeUInt64ArrayFromStringTypeIntegerIsInt642() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Integer); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeUInt64FromStringTypeNumberIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Number); var expected = new Variant(123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123Lu), encoded); } [Fact] public void DecodeEncodeUInt64ArrayFromStringTypeNumberIsInt641() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[123, 124, 125]"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Number); var expected = new Variant(new Variant[] { new(123L), new(124L), new(125L) }); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123Lu, 124Lu, 125Lu), encoded); } [Fact] public void DecodeEncodeUInt64ArrayFromStringTypeNumberIsInt642() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Number); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeUInt64FromStringTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Null); var expected = new Variant(123L); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123Lu), encoded); } [Fact] public void DecodeEncodeUInt64ArrayFromStringTypeNullIsInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "123, 124, 125"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Null); var expected = new Variant([123L, 124L, 125L]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123Lu, 124Lu, 125Lu), encoded); } [Fact] public void DecodeEncodeUInt64ArrayFromStringTypeNullIsInt642() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[123, 124, 125]"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Null); var expected = new Variant([123L, 124L, 125L]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123Lu, 124Lu, 125Lu), encoded); } [Fact] public void DecodeEncodeUInt64ArrayFromStringTypeNullIsNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "[]"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Null); var expected = Variant.Null; var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.Equal(expected, variant); } [Fact] public void DecodeEncodeUInt64FromQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"123\""; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.UInt64); var expected = new Variant(123Lu); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123Lu), encoded); } [Fact] public void DecodeEncodeUInt64FromSinglyQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = " '123'"; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.UInt64); var expected = new Variant(123Lu); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123Lu), encoded); } [Fact] public void DecodeEncodeUInt64ArrayFromQuotedString() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = "\"123\",'124',\"125\""; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.UInt64); var expected = new Variant([123Lu, 124Lu, 125Lu]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123Lu, 124Lu, 125Lu), encoded); } [Fact] public void DecodeEncodeUInt64ArrayFromQuotedString2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); const string str = " [\"123\",'124',\"125\"] "; var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.UInt64); var expected = new Variant([123Lu, 124Lu, 125Lu]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123Lu, 124Lu, 125Lu), encoded); } [Fact] public void DecodeEncodeUInt64FromVariantJsonTokenTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "UInt64", Body = 123Lu }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(123Lu); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123Lu), encoded); } [Fact] public void DecodeEncodeUInt64ArrayFromVariantJsonTokenTypeVariant1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "UInt64", Body = new ulong[] { 123Lu, 124Lu, 125Lu } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant([123Lu, 124Lu, 125Lu]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123Lu, 124Lu, 125Lu), encoded); } [Fact] public void DecodeEncodeUInt64ArrayFromVariantJsonTokenTypeVariant2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "UInt64", Body = System.Array.Empty() }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeUInt64FromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "UInt64", Body = 123Lu }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Variant); var expected = new Variant(123Lu); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123Lu), encoded); } [Fact] public void DecodeEncodeUInt64ArrayFromVariantJsonStringTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "UInt64", Body = new ulong[] { 123Lu, 124Lu, 125Lu } }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Variant); var expected = new Variant([123Lu, 124Lu, 125Lu]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123Lu, 124Lu, 125Lu), encoded); } [Fact] public void DecodeEncodeUInt64FromVariantJsonTokenTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "UInt64", Body = 123Lu }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Null); var expected = new Variant(123Lu); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123Lu), encoded); } [Fact] public void DecodeEncodeUInt64ArrayFromVariantJsonTokenTypeNull1() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { TYPE = "UINT64", BODY = new ulong[] { 123Lu, 124Lu, 125Lu } }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant([123Lu, 124Lu, 125Lu]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123Lu, 124Lu, 125Lu), encoded); } [Fact] public void DecodeEncodeUInt64ArrayFromVariantJsonTokenTypeNull2() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { Type = "UInt64", Body = System.Array.Empty() }); var variant = codec.Decode(str, BuiltInType.Null); var expected = new Variant(System.Array.Empty()); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(), encoded); } [Fact] public void DecodeEncodeUInt64FromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { Type = "uint64", Body = 123Lu }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Null); var expected = new Variant(123Lu); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123Lu), encoded); } [Fact] public void DecodeEncodeUInt64ArrayFromVariantJsonStringTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "UInt64", body = new ulong[] { 123Lu, 124Lu, 125Lu } }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Null); var expected = new Variant([123Lu, 124Lu, 125Lu]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123Lu, 124Lu, 125Lu), encoded); } [Fact] public void DecodeEncodeUInt64FromVariantJsonTokenTypeNullMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { DataType = "UInt64", Value = 123Lu }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Null); var expected = new Variant(123Lu); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123Lu), encoded); } [Fact] public void DecodeEncodeUInt64FromVariantJsonStringTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { DataType = "UInt64", Value = 123Lu }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Variant); var expected = new Variant(123Lu); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromObject(123Lu), encoded); } [Fact] public void DecodeEncodeUInt64ArrayFromVariantJsonTokenTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.FromObject(new { dataType = "UInt64", value = new ulong[] { 123Lu, 124Lu, 125Lu } }); var variant = codec.Decode(str, BuiltInType.Variant); var expected = new Variant([123Lu, 124Lu, 125Lu]); var encoded = codec.Encode(variant); Assert.Equal(expected, variant); Assert.Equal(_serializer.FromArray(123Lu, 124Lu, 125Lu), encoded); } #pragma warning disable CA1814 // Prefer jagged arrays over multidimensional [Fact] public void DecodeEncodeUInt64MatrixFromStringJsonTypeUInt64() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new ulong[,,] { { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } } } ); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.UInt64); var expected = new Variant((object)new ulong[,,] { { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeUInt64MatrixFromVariantJsonTypeVariant() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "UInt64", body = new ulong[,,] { { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } } } }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Variant); var expected = new Variant((object)new ulong[,,] { { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeUInt64MatrixFromVariantJsonTokenTypeVariantMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { dataType = "UInt64", value = new ulong[,,] { { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } } } }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Variant); var expected = new Variant((object)new ulong[,,] { { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeUInt64MatrixFromVariantJsonTypeNull() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { type = "UInt64", body = new ulong[,,] { { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } } } }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Null); var expected = new Variant((object)new ulong[,,] { { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } [Fact] public void DecodeEncodeUInt64MatrixFromVariantJsonTokenTypeNullMsftEncoding() { var codec = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var str = _serializer.SerializeToString(new { dataType = "UInt64", value = new ulong[,,] { { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } } } }); var variant = codec.Decode(_serializer.FromObject(str), BuiltInType.Null); var expected = new Variant((object)new ulong[,,] { { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } }, { { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu }, { 123Lu, 124Lu, 125Lu } } }); var encoded = codec.Encode(variant); Assert.NotNull(encoded); Assert.True(expected.Value is Matrix); Assert.True(variant.Value is Matrix); Assert.Equal(((Matrix)expected.Value).Elements, ((Matrix)variant.Value).Elements); Assert.Equal(((Matrix)expected.Value).Dimensions, ((Matrix)variant.Value).Dimensions); } #pragma warning restore CA1814 // Prefer jagged arrays over multidimensional private readonly NewtonsoftJsonSerializer _serializer = new(); } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/VariantVariants.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Opc.Ua; using System; using System.Collections.Generic; using System.Security.Cryptography; using System.Text; using System.Xml; public sealed record class VariantsHolder( IReadOnlyList Variants, TypeInfo TypeInfo) { public override string ToString() { return TypeInfo.ToString(); } } public sealed record class VariantHolder(Variant Variant) { public override string ToString() { return Variant.TypeInfo.ToString(); } } public static class VariantVariants { public static IEnumerable GetValues() { yield return new Variant(true); yield return new Variant(false); yield return new Variant((sbyte)1); yield return new Variant((sbyte)-1); yield return new Variant((sbyte)0); yield return new Variant(sbyte.MaxValue); yield return new Variant(sbyte.MinValue); yield return new Variant((short)1); yield return new Variant((short)-1); yield return new Variant((short)0); yield return new Variant(short.MaxValue); yield return new Variant(short.MinValue); yield return new Variant(1); yield return new Variant(-1); yield return new Variant(0); yield return new Variant(int.MaxValue); yield return new Variant(int.MinValue); yield return new Variant(1L); yield return new Variant(-1L); yield return new Variant(0L); yield return new Variant(long.MaxValue); yield return new Variant(long.MinValue); yield return new Variant(1UL); yield return new Variant(0UL); yield return new Variant(ulong.MaxValue); yield return new Variant(11790719998462990154); yield return new Variant(10042278942021613161); yield return new Variant(1u); yield return new Variant(0u); yield return new Variant(uint.MaxValue); yield return new Variant((ushort)1); yield return new Variant((ushort)0); yield return new Variant(ushort.MaxValue); yield return new Variant((byte)1); yield return new Variant((byte)0); yield return new Variant(byte.MaxValue); yield return new Variant(1.0); yield return new Variant(-1.0); yield return new Variant(0.0); yield return new Variant(double.MaxValue); yield return new Variant(double.MinValue); yield return new Variant(double.PositiveInfinity); yield return new Variant(double.NegativeInfinity); yield return new Variant(1.0f); yield return new Variant(-1.0f); yield return new Variant(0.0f); yield return new Variant(float.MaxValue); yield return new Variant(float.MinValue); yield return new Variant(float.PositiveInfinity); yield return new Variant(float.NegativeInfinity); // yield return new Variant((decimal)1.0); // yield return new Variant((decimal)-1.0); // yield return new Variant((decimal)0.0); // yield return new Variant((decimal)1234567); // yield return new Variant(decimal.MaxValue); // yield return new Variant(decimal.MinValue); yield return new Variant(Guid.NewGuid()); yield return new Variant(Guid.Empty); yield return new Variant(DateTime.UtcNow); yield return new Variant(DateTime.MaxValue); yield return new Variant(DateTime.MinValue); yield return new Variant(string.Empty); yield return new Variant((string)null); yield return new Variant(" str ing"); yield return new Variant("zeroterminated" + '\0'); yield return new Variant(Array.Empty()); yield return new Variant((byte[])null); yield return new Variant(new byte[1000]); yield return new Variant(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }); yield return new Variant(Encoding.UTF8.GetBytes("utf-8-string")); yield return new Variant(new NodeId([1, 2, 3, 4, 5, 6, 7, 8], 0)); yield return new Variant(new NodeId("test", 0)); yield return new Variant(new NodeId(1u, 0)); yield return new Variant(new NodeId(Guid.NewGuid(), 0)); yield return new Variant(NodeId.Null); yield return new Variant((NodeId)null); yield return new Variant(new ExpandedNodeId([1, 2, 3, 4, 5, 6, 7, 8], 0)); yield return new Variant(new ExpandedNodeId("test", 0)); yield return new Variant(new ExpandedNodeId(1u, 0)); yield return new Variant(new ExpandedNodeId(Guid.NewGuid(), 0)); yield return new Variant((ExpandedNodeId)null); yield return new Variant(new LocalizedText("en", "text")); yield return new Variant(new LocalizedText("text2")); yield return new Variant(new LocalizedText(string.Empty)); yield return new Variant((LocalizedText)null); yield return new Variant(new QualifiedName("en", 0)); yield return new Variant(new QualifiedName(string.Empty, 0)); yield return new Variant((QualifiedName)null); yield return new Variant((StatusCode)StatusCodes.Bad); yield return new Variant((StatusCode)StatusCodes.UncertainDependentValueChanged); yield return new Variant(new DataValue(StatusCodes.BadNoCommunication)); yield return new Variant(new DataValue(new Variant(123))); yield return new Variant(XmlElement); } public static XmlElement XmlElement { get { var doc = new XmlDocument(); doc.LoadXml( """ Tove Jani Reminder Don't forget me this weekend! """ ); return doc.DocumentElement; } } public static readonly ProgramDiagnostic2DataType Complex = new() { CreateClientName = "Testname", CreateSessionId = new NodeId(Guid.NewGuid()), InvocationCreationTime = DateTime.UtcNow, LastMethodCall = "swappido", LastMethodCallTime = DateTime.UtcNow, LastMethodInputArguments = [ new Argument("something1", new NodeId(2354), -1, "somedesciroeioi") { ArrayDimensions = Array.Empty() }, new Argument("something2", new NodeId(23), -1, "fdsadfsdaf") { ArrayDimensions = Array.Empty() }, new Argument("something3", new NodeId(44), 1, "fsadf sadfsdfsadfsd") { ArrayDimensions = Array.Empty() }, new Argument("something4", new NodeId(23), 1, "dfad sdafdfdf fasdf") { ArrayDimensions = Array.Empty() } ], LastMethodInputValues = [ new Variant(4L), new Variant("test"), new Variant(new long[] {1, 2, 3, 4, 5 }), new Variant(["1", "2", "3", "4", "5"]) ], LastMethodOutputArguments = [ new Argument("foo1", new NodeId(2354), -1, "somedesciroeioi") { ArrayDimensions = Array.Empty() }, new Argument("foo2", new NodeId(33), -1, "fdsadfsdaf") { ArrayDimensions = Array.Empty() }, new Argument("adfsdafsdsdsafdsfa", new NodeId("absc", 0), 1, "fsadf sadfsdfsadfsd") { ArrayDimensions = Array.Empty() }, new Argument("ddddd", new NodeId(25), 1, "dfad sdafdfdf fasdf") { ArrayDimensions = Array.Empty() } ], LastMethodOutputValues = [ new Variant(4L), new Variant("test"), new Variant(new long[] {1, 2, 3, 4, 5 }), new Variant(["1", "2", "3", "4", "5"]) ], LastMethodReturnStatus = StatusCodes.BadAggregateConfigurationRejected, LastMethodSessionId = new NodeId(RandomNumberGenerator.GetBytes(32)), LastTransitionTime = DateTime.UtcNow - TimeSpan.FromDays(23) }; } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Encoders/ZipFileWriterTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Encoders { using Furly; using Furly.Extensions.Messaging; using System; using System.Buffers; using System.IO; using System.IO.Compression; using System.Linq; using System.Text; using System.Threading.Tasks; using Xunit; /// /// Test file writers /// public sealed class ZipFileWriterTests { [Fact] public void SupportsContentTypeTests() { using var writer = new ZipFileWriter(); Assert.False(writer.SupportsContentType(ContentType.Avro)); Assert.False(writer.SupportsContentType(ContentType.AvroGzip)); Assert.False(writer.SupportsContentType("test")); Assert.True(writer.SupportsContentType(ContentType.Uadp)); Assert.True(writer.SupportsContentType(ContentType.JsonGzip)); Assert.True(writer.SupportsContentType(ContentMimeType.Binary)); Assert.True(writer.SupportsContentType(ContentMimeType.UaNonReversibleJson)); Assert.True(writer.SupportsContentType(ContentMimeType.UaLegacyPublisher)); Assert.True(writer.SupportsContentType(ContentMimeType.UaJson)); Assert.Throws(() => ZipFileWriter.Suffix(ZipFileWriter.ContentType.None)); } [Fact] public async Task TestZipFileWriter1Async() { var file = Path.GetTempFileName(); try { using (var writer = new ZipFileWriter()) { await writer.WriteAsync(file, DateTime.UtcNow, new[] { new ReadOnlySequence([1, 2, 3]) }, null, new DummyEventSchema(), ContentType.Uadp); } Assert.True(File.Exists(file + ".zip")); using var reader = new ZipFileReader(file); Assert.True(reader.HasMore()); var result = reader.Read((s, t) => { var buffer = t.ReadAsBuffer(); Assert.Equal(1, buffer[0]); Assert.Equal(2, buffer[1]); Assert.Equal(3, buffer[2]); Assert.Equal(3, buffer.Count); Assert.Equal("[]", s); return 123; }); Assert.False(reader.HasMore()); Assert.Equal(123, result); } finally { File.Delete(file + ".zip"); } } [Fact] public async Task TestZipFileWriter2Async() { var file = Path.GetTempFileName(); try { using (var writer = new ZipFileWriter()) { await writer.WriteAsync(file, DateTime.UtcNow, new[] { new ReadOnlySequence([1, 2, 3]) }, null, new DummyEventSchema(), ContentType.Uadp); await writer.WriteAsync(file, DateTime.UtcNow, new[] { new ReadOnlySequence([1, 2, 3]) }, null, new DummyEventSchema(), ContentType.Uadp); await writer.WriteAsync(file, DateTime.UtcNow, new[] { new ReadOnlySequence([1, 2, 3]) }, null, new DummyEventSchema(), ContentType.Uadp); } using var reader = new ZipFileReader(file); for (var i = 0; i < 3; i++) { Assert.True(reader.HasMore()); var result = reader.Read((s, t) => { Assert.Equal(1, t.ReadByte()); Assert.Equal(2, t.ReadByte()); Assert.Equal(3, t.ReadByte()); Assert.Equal("[]", s); return 123; }); Assert.Equal(123, result); } Assert.False(reader.HasMore()); } finally { File.Delete(file + ".zip"); } } [Fact] public async Task TestZipFileWriter3Async() { var file = Path.GetTempFileName(); try { using (var writer = new ZipFileWriter()) { await writer.WriteAsync(file, DateTime.UtcNow, Array.Empty>(), null, null, ContentType.Uadp); } Assert.True(File.Exists(file + ".zip")); using var reader = new ZipFileReader(file); Assert.False(reader.HasMore()); Assert.Throws(() => reader.Read((s, t) => 123)); Assert.False(reader.HasMore()); } finally { File.Delete(file + ".zip"); } } [Fact] public async Task TestZipFileWriter4Async() { var file = Path.GetTempFileName(); try { const string expected = "{\"teststring\": 1}"; var buffer = new ReadOnlySequence(Encoding.UTF8.GetBytes(expected)); using (var writer = new ZipFileWriter()) { await writer.WriteAsync(file, DateTime.UtcNow, new[] { buffer.GzipCompress() }, null, new DummyEventSchema(), ContentType.JsonGzip); } Assert.True(File.Exists(file + ".zip")); using var reader = new ZipFileReader(file); Assert.True(reader.HasMore()); var result = reader.Read((s, t) => { var buffer = t.ReadAsBuffer(); Assert.Equal(expected, Encoding.UTF8.GetString(buffer)); return 123; }); Assert.False(reader.HasMore()); Assert.Equal(123, result); } finally { File.Delete(file + ".zip"); } } [Fact] public async Task TestZipFileWriter5Async() { var file = Path.GetTempFileName(); try { const string expected = "{\"teststring\": 1}"; var buffer = new ReadOnlySequence(Encoding.UTF8.GetBytes(expected)); using (var writer = new ZipFileWriter()) { await writer.WriteAsync(file, DateTime.UtcNow, new[] { buffer.GzipCompress() }, null, new DummyEventSchema(), ContentType.JsonGzip); await writer.WriteAsync(file, DateTime.UtcNow, new[] { buffer.GzipCompress() }, null, new DummyEventSchema(), ContentType.JsonGzip); await writer.WriteAsync(file, DateTime.UtcNow, new[] { buffer.GzipCompress() }, null, new DummyEventSchema(), ContentType.JsonGzip); } Assert.True(File.Exists(file + ".zip")); using var reader = new ZipFileReader(file); Assert.True(reader.HasMore()); var result = reader.Read((s, t) => { var buffer = t.ReadAsBuffer(); Assert.Equal(expected, Encoding.UTF8.GetString(buffer)); return 123; }); Assert.Equal(123, result); Assert.True(reader.HasMore()); } finally { File.Delete(file + ".zip"); } } [Fact] public async Task TestZipFileWriter6Async() { var file = Path.GetTempFileName(); try { const string expected = "{\"teststring\": 1}"; var buffer = new ReadOnlySequence(Encoding.UTF8.GetBytes(expected)); using (var writer = new ZipFileWriter()) { await writer.WriteAsync(file, DateTime.UtcNow, new[] { buffer }, null, new DummyEventSchema(), ContentMimeType.Json); await writer.WriteAsync(file, DateTime.UtcNow, new[] { buffer }, null, new DummyEventSchema(), ContentMimeType.Json); await writer.WriteAsync(file, DateTime.UtcNow, new[] { buffer }, null, new DummyEventSchema(), ContentMimeType.Json); } Assert.True(File.Exists(file + ".zip")); using var reader = new ZipFileReader(file); Assert.True(reader.HasMore()); var result = reader.Stream((s, t) => { var buffer = t.ReadAsBuffer(); Assert.Equal(expected, Encoding.UTF8.GetString(buffer)); return 123; }).ToList(); Assert.Equal(3, result.Count); Assert.All(result, a => Assert.Equal(123, a)); Assert.False(reader.HasMore()); } finally { File.Delete(file + ".zip"); } } [Theory] [InlineData("")] [InlineData("ab")] [InlineData("badheader")] public async Task TestBadHeader1Async(string data) { var file = Path.GetTempFileName(); try { await File.WriteAllTextAsync(file + ".zip", data); Assert.Throws(() => new ZipFileReader(file)); } finally { File.Delete(file + ".zip"); } } [Theory] [InlineData(null)] [InlineData("")] [InlineData("ab")] [InlineData("badcontentType")] public void TestBadHeader2(string data) { var file = Path.GetTempFileName(); try { using (var s = File.Open(file + ".zip", FileMode.Create)) using (var zip = new ZipArchive(s, ZipArchiveMode.Create)) { var entry = zip.CreateEntry(ZipFileWriter.ContentTypeFile); using var stream = entry.Open(); if (data == null) { stream.WriteByte(0); } else { stream.Write(Encoding.UTF8.GetBytes(data)); } } Assert.Throws(() => new ZipFileReader(file)); } finally { File.Delete(file + ".zip"); } } [Fact] public void TestBadHeader3() { var file = Path.GetTempFileName(); try { using (var s = File.Open(file + ".zip", FileMode.Create)) using (var zip = new ZipArchive(s, ZipArchiveMode.Create)) { var entry = zip.CreateEntry("1.json"); using var stream = entry.Open(); stream.Write(Encoding.UTF8.GetBytes("data")); } Assert.Throws(() => new ZipFileReader(file)); } finally { File.Delete(file + ".zip"); } } private sealed class DummyEventSchema : IEventSchema { public string Id => "test"; public string Schema => "[]"; public string Type => "test"; public string Name => "test"; public ulong Version => 1; } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/GlobalSuppressions.cs ================================================ // This file is used by Code Analysis to maintain SuppressMessage // attributes that are applied to this project. // Project-level suppressions either have no target or are given // a specific target and scoped to a namespace, type, member, etc. using System.Diagnostics.CodeAnalysis; [assembly: SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "xunit")] ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Publisher/Extensions/OpcNodeModelExTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Config.Models { using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.Globalization; using Xunit; public class OpcNodeModelExTests { [Fact] public void ComparerTest() { var comparer = OpcNodeModelEx.Comparer; var opcNode1 = new OpcNodeModel(); var opcNode2 = new OpcNodeModel(); Assert.True(comparer.Equals(opcNode1, opcNode2)); Assert.True(comparer.GetHashCode(opcNode1) == comparer.GetHashCode(opcNode2)); opcNode1 = new OpcNodeModel { Id = "id", OpcPublishingInterval = 1500, OpcSamplingInterval = 2500, HeartbeatInterval = 35, QueueSize = 123, DataChangeTrigger = DataChangeTriggerType.StatusValue, DeadbandType = DeadbandType.Absolute, DeadbandValue = 0.1 }; static OpcNodeModel NewNode() => new() { Id = "id", OpcPublishingIntervalTimespan = TimeSpan.Parse("00:00:01.5", CultureInfo.InvariantCulture), OpcSamplingIntervalTimespan = TimeSpan.Parse("00:00:02.500", CultureInfo.InvariantCulture), HeartbeatIntervalTimespan = TimeSpan.Parse("00:00:35", CultureInfo.InvariantCulture), SkipFirst = true, QueueSize = 123, DataChangeTrigger = DataChangeTriggerType.StatusValue, DeadbandType = DeadbandType.Absolute, DeadbandValue = 0.1 }; opcNode2 = NewNode(); opcNode2.SkipFirst = false; Assert.True(comparer.Equals(opcNode1, opcNode2)); Assert.True(comparer.GetHashCode(opcNode1) == comparer.GetHashCode(opcNode2)); // Set skip first to true like factory opcNode2 = NewNode(); opcNode1.SkipFirst = true; Assert.True(comparer.Equals(opcNode1, opcNode2)); Assert.True(comparer.GetHashCode(opcNode1) == comparer.GetHashCode(opcNode2)); opcNode2 = NewNode(); Assert.True(comparer.Equals(opcNode1, opcNode2)); Assert.True(comparer.GetHashCode(opcNode1) == comparer.GetHashCode(opcNode2)); opcNode2 = NewNode(); opcNode2.SkipFirst = false; opcNode2.QueueSize = 123; Assert.False(comparer.Equals(opcNode1, opcNode2)); Assert.False(comparer.GetHashCode(opcNode1) == comparer.GetHashCode(opcNode2)); opcNode2 = NewNode(); opcNode2.SkipFirst = true; opcNode2.QueueSize = 321; Assert.False(comparer.Equals(opcNode1, opcNode2)); Assert.False(comparer.GetHashCode(opcNode1) == comparer.GetHashCode(opcNode2)); opcNode2 = NewNode(); opcNode2.SkipFirst = true; opcNode2.QueueSize = 123; opcNode2.DataChangeTrigger = DataChangeTriggerType.Status; Assert.False(comparer.Equals(opcNode1, opcNode2)); Assert.False(comparer.GetHashCode(opcNode1) == comparer.GetHashCode(opcNode2)); opcNode2 = NewNode(); opcNode2.SkipFirst = null; opcNode2.QueueSize = null; opcNode2.DataChangeTrigger = null; Assert.False(comparer.Equals(opcNode1, opcNode2)); Assert.False(comparer.GetHashCode(opcNode1) == comparer.GetHashCode(opcNode2)); opcNode2 = NewNode(); opcNode2.DataChangeTrigger = null; Assert.False(comparer.Equals(opcNode1, opcNode2)); Assert.False(comparer.GetHashCode(opcNode1) == comparer.GetHashCode(opcNode2)); opcNode2 = NewNode(); opcNode2.DeadbandType = DeadbandType.Percent; Assert.False(comparer.Equals(opcNode1, opcNode2)); Assert.False(comparer.GetHashCode(opcNode1) == comparer.GetHashCode(opcNode2)); opcNode2 = NewNode(); opcNode2.DeadbandType = null; Assert.False(comparer.Equals(opcNode1, opcNode2)); Assert.False(comparer.GetHashCode(opcNode1) == comparer.GetHashCode(opcNode2)); opcNode2 = NewNode(); opcNode2.DeadbandValue = null; Assert.False(comparer.Equals(opcNode1, opcNode2)); Assert.False(comparer.GetHashCode(opcNode1) == comparer.GetHashCode(opcNode2)); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Publisher/Models/PublishedNodesEntryModelTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Config.Models { using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using System; using Xunit; public class PublishedNodesEntryModelTests { [Fact] public void UseSecurityDeserializationTest() { var newtonSoftJsonSerializer = new NewtonsoftJsonSerializer(); var modelJson = """ { "EndpointUrl": "opc.tcp://localhost:50002", "OpcNodes": [ { "Identifier": "ns=0;i=2261" } ] } """; var model = newtonSoftJsonSerializer.Deserialize(modelJson); Assert.Null(model.UseSecurity); modelJson = """ { "EndpointUrl": "opc.tcp://localhost:50002", "UseSecurity": false, "OpcNodes": [ { "Identifier": "ns=0;i=2261" } ] } """; model = newtonSoftJsonSerializer.Deserialize(modelJson); Assert.False(model.UseSecurity); modelJson = """ { "EndpointUrl": "opc.tcp://localhost:50002", "UseSecurity": true, "OpcNodes": [ { "Identifier": "ns=0;i=2261" } ] } """; model = newtonSoftJsonSerializer.Deserialize(modelJson); Assert.True(model.UseSecurity); } [Fact] public void UseSecuritySerializationTest() { var newtonSoftJsonSerializer = new NewtonsoftJsonSerializer(); var model = new PublishedNodesEntryModel { EndpointUrl = "opc.tcp://localhost:50000", OpcNodes = [ new() { Id = "i=2258" } ] }; var modeJson = newtonSoftJsonSerializer.SerializeToString(model); Assert.DoesNotContain("\"UseSecurity\":false", modeJson, StringComparison.Ordinal); model = new PublishedNodesEntryModel { EndpointUrl = "opc.tcp://localhost:50000", UseSecurity = false, OpcNodes = [ new() { Id = "i=2258" } ] }; modeJson = newtonSoftJsonSerializer.SerializeToString(model); Assert.Contains("\"UseSecurity\":false", modeJson, StringComparison.Ordinal); model = new PublishedNodesEntryModel { EndpointUrl = "opc.tcp://localhost:50000", UseSecurity = true, OpcNodes = [ new() { Id = "i=2258" } ] }; modeJson = newtonSoftJsonSerializer.SerializeToString(model); Assert.Contains("\"UseSecurity\":true", modeJson, StringComparison.Ordinal); } [Fact] public void OpcAuthenticationModeDeserializationTest() { var newtonSoftJsonSerializer = new NewtonsoftJsonSerializer(); var modelJson = """ { "EndpointUrl": "opc.tcp://localhost:50002", "OpcNodes": [ { "Identifier": "ns=0;i=2261" } ] } """; var model = newtonSoftJsonSerializer.Deserialize(modelJson); Assert.Equal(OpcAuthenticationMode.Anonymous, model.OpcAuthenticationMode); modelJson = """ { "EndpointUrl": "opc.tcp://localhost:50002", "OpcAuthenticationMode": "anonymous", "OpcNodes": [ { "Identifier": "ns=0;i=2261" } ] } """; model = newtonSoftJsonSerializer.Deserialize(modelJson); Assert.Equal(OpcAuthenticationMode.Anonymous, model.OpcAuthenticationMode); modelJson = """ { "EndpointUrl": "opc.tcp://localhost:50002", "OpcAuthenticationMode": "usernamePassword", "OpcNodes": [ { "Identifier": "ns=0;i=2261" } ] } """; model = newtonSoftJsonSerializer.Deserialize(modelJson); Assert.Equal(OpcAuthenticationMode.UsernamePassword, model.OpcAuthenticationMode); } [Fact] public void OpcAuthenticationModeSerializationTest() { var newtonSoftJsonSerializer = new NewtonsoftJsonSerializer(); var model = new PublishedNodesEntryModel { EndpointUrl = "opc.tcp://localhost:50000", OpcNodes = [ new() { Id = "i=2258" } ] }; var modeJson = newtonSoftJsonSerializer.SerializeToString(model); Assert.Contains("\"OpcAuthenticationMode\":\"Anonymous\"", modeJson, StringComparison.Ordinal); model = new PublishedNodesEntryModel { EndpointUrl = "opc.tcp://localhost:50000", OpcAuthenticationMode = OpcAuthenticationMode.Anonymous, OpcNodes = [ new() { Id = "i=2258" } ] }; modeJson = newtonSoftJsonSerializer.SerializeToString(model); Assert.Contains("\"OpcAuthenticationMode\":\"Anonymous\"", modeJson, StringComparison.Ordinal); model = new PublishedNodesEntryModel { EndpointUrl = "opc.tcp://localhost:50000", OpcAuthenticationMode = OpcAuthenticationMode.UsernamePassword, OpcNodes = [ new() { Id = "i=2258" } ] }; modeJson = newtonSoftJsonSerializer.SerializeToString(model); Assert.Contains("\"OpcAuthenticationMode\":\"UsernamePassword\"", modeJson, StringComparison.Ordinal); } } } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Resources/CyclicReads.json ================================================ { "Id": "c0b8f1a2-3e4f-4b5c-8d6e-7f8a9b0c1d2e", "Version": 1, "DataSetMessages": [ { "Id": "c0b8f1a2-3e4f-4b5c-8d6e-7f8a9b0c1d2e", "MetaData": { "MinorVersion": 2035898649, "DataSetMetaData": { "Name": null, "DataSetClassId": "00000000-0000-0000-0000-000000000000", "Description": null, "MajorVersion": null }, "Fields": [ { "Name": "i=2258", "Id": "0a8fa57d-53f1-4d36-a6bf-aea8c266236a", "Description": null, "Flags": 0, "BuiltInType": 13, "DataType": "i=294", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=StepUp", "Id": "b4966f7d-c3b8-456b-a34d-33375e96a44f", "Description": "Constantly increasing value", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean", "Id": "a0fbd59d-bf90-481d-8148-0cf3f95f72db", "Description": "Alternating boolean value", "Flags": 0, "BuiltInType": 1, "DataType": "i=1", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32", "Id": "2fd5d646-b318-4794-8f76-900a5349e473", "Description": "Random signed 32 bit integer value", "Flags": 0, "BuiltInType": 6, "DataType": "i=6", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32", "Id": "e18cd56a-62cd-4513-ac53-95acec4175d9", "Description": "Random unsigned 32 bit integer value", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData", "Id": "2a46ec59-56f8-4d48-a8a3-b3ae6fb2e416", "Description": "Value with random dips", "Flags": 0, "BuiltInType": 11, "DataType": "i=11", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1", "Id": "2031bf9e-d182-4ccf-86cf-0c41a2dda649", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2", "Id": "08d04674-0330-48ef-a0b8-e84d12305262", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3", "Id": "bc08ef8e-c316-496f-bbb8-3274530ccd17", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1", "Id": "02c26a87-ef62-4196-9cfd-4ea01f1fbb4a", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2", "Id": "43e3f216-61a4-4d59-801a-3d4e27e23c0a", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3", "Id": "c3130fd7-318f-4889-9c48-dd316341d300", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData", "Id": "baf8c090-104a-4b51-8e26-433258108cae", "Description": "Value with a slow negative trend", "Flags": 0, "BuiltInType": 11, "DataType": "i=11", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData", "Id": "2717fada-a74b-4277-923c-f759e29db569", "Description": "Value with a slow positive trend", "Flags": 0, "BuiltInType": 11, "DataType": "i=11", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1", "Id": "386cfed8-026d-44c2-8f93-ed615cb9c7c2", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2", "Id": "353428b9-10b9-4045-a1f4-cf8068b9010e", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3", "Id": "0df6f7e9-e2d9-4bcd-ae46-f068356a8f13", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1", "Id": "83d68c47-e6c2-4002-8d1c-1cfa80063c5a", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1", "Id": "208b6ac5-2996-47c9-a361-8f129d8cc1d1", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2", "Id": "99b85816-0e7e-4d14-adc2-ffbf47e9c344", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3", "Id": "9c9178c5-5037-42f8-8c5a-f70f51464270", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1", "Id": "1885cb44-3ebd-4246-b522-b3271c867e9b", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData", "Id": "03161fb9-a405-4950-b4d2-efdedf7c47a5", "Description": "Value with random spikes", "Flags": 0, "BuiltInType": 11, "DataType": "i=11", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "ns=23;i=1259", "Id": "bdc40f73-e20d-4102-8baa-ed171cbc4bd1", "Description": null, "Flags": 0, "BuiltInType": 26, "DataType": "i=26", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null } ], "StructureDataTypes": [], "EnumDataTypes": [], "SimpleDataTypes": [ { "DataTypeId": "i=294", "Name": "UtcTime", "BaseDataType": "i=13", "BuiltInType": 13 } ] }, "DataSetMessageContentFlags": 0, "DataSetFieldContentFlags": 3080199, "TypeName": null } ], "NetworkMessageContentFlags": 8192, "TypeName": null } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Resources/KeepAlive.json ================================================ { "Id": "c0b8f1a2-3e4f-4b5c-8d6e-7f8a9b0c1d2e", "Version": 1, "DataSetMessages": [ { "Id": "c0b8f1a2-3e4f-4b5c-8d6e-7f8a9b0c1d2e", "MetaData": { "MinorVersion": 3632325695, "DataSetMetaData": { "Name": null, "DataSetClassId": "00000000-0000-0000-0000-000000000000", "Description": null, "MajorVersion": null }, "Fields": [ { "Name": "State", "Id": "081ffb7a-b0e4-484a-a57e-8065c350ad1c", "Description": null, "Flags": 0, "BuiltInType": 29, "DataType": "i=852", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null } ], "StructureDataTypes": [], "EnumDataTypes": [ { "DataTypeId": "i=852", "Name": "ServerState", "Fields": [ { "Name": "Running", "Value": 0, "DisplayName": "Running", "Description": null }, { "Name": "Failed", "Value": 1, "DisplayName": "Failed", "Description": null }, { "Name": "NoConfiguration", "Value": 2, "DisplayName": "NoConfiguration", "Description": null }, { "Name": "Suspended", "Value": 3, "DisplayName": "Suspended", "Description": null }, { "Name": "Shutdown", "Value": 4, "DisplayName": "Shutdown", "Description": null }, { "Name": "Test", "Value": 5, "DisplayName": "Test", "Description": null }, { "Name": "CommunicationFault", "Value": 6, "DisplayName": "CommunicationFault", "Description": null }, { "Name": "Unknown", "Value": 7, "DisplayName": "Unknown", "Description": null } ], "BuiltInType": null, "IsOptionSet": false } ], "SimpleDataTypes": [] }, "DataSetMessageContentFlags": 868, "DataSetFieldContentFlags": 458755, "TypeName": null } ], "NetworkMessageContentFlags": 6901, "TypeName": null } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Resources/KeyFrames.json ================================================ { "Id": "c0b8f1a2-3e4f-4b5c-8d6e-7f8a9b0c1d2e", "Version": 1, "DataSetMessages": [ { "Id": "c0b8f1a2-3e4f-4b5c-8d6e-7f8a9b0c1d2e", "MetaData": { "MinorVersion": 275393594, "DataSetMetaData": { "Name": null, "DataSetClassId": "00000000-0000-0000-0000-000000000000", "Description": null, "MajorVersion": null }, "Fields": [ { "Name": "CurrentTime", "Id": "b94d9c20-63ef-419f-a76e-ffcb280a3b13", "Description": null, "Flags": 0, "BuiltInType": 13, "DataType": "i=294", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "EngineeringUnits", "Id": "6995a326-df96-4e00-9247-f7eea034f810", "Description": null, "Flags": 0, "BuiltInType": 12, "DataType": "i=12", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "AssetId", "Id": "9a647079-3f64-4ab4-9b86-437a3438b931", "Description": null, "Flags": 0, "BuiltInType": 24, "DataType": "i=24", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "Important", "Id": "3d8f7712-0d10-4390-b5bb-7c6484816c68", "Description": null, "Flags": 0, "BuiltInType": 1, "DataType": "i=1", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "Variance", "Id": "fa7707aa-4b5d-477e-a441-f5cd203b0523", "Description": null, "Flags": 0, "BuiltInType": 10, "DataType": "i=10", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null } ], "StructureDataTypes": [], "EnumDataTypes": [], "SimpleDataTypes": [ { "DataTypeId": "i=294", "Name": "UtcTime", "BaseDataType": "i=13", "BuiltInType": 13 } ] }, "DataSetMessageContentFlags": 868, "DataSetFieldContentFlags": 458755, "TypeName": null } ], "NetworkMessageContentFlags": 6901, "TypeName": null } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Resources/PendingAlarms.json ================================================ { "Id": "c0b8f1a2-3e4f-4b5c-8d6e-7f8a9b0c1d2e", "Version": 1, "DataSetMessages": [ { "Id": "c0b8f1a2-3e4f-4b5c-8d6e-7f8a9b0c1d2e", "MetaData": { "MinorVersion": 2585633434, "DataSetMetaData": { "Name": null, "DataSetClassId": "00000000-0000-0000-0000-000000000000", "Description": null, "MajorVersion": null }, "Fields": [ { "Name": "ConditionClassId", "Id": "d46eb7cd-98d4-4a82-bfd4-adfd098e982c", "Description": null, "Flags": 0, "BuiltInType": 17, "DataType": "i=17", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "ConditionClassName", "Id": "2da0aa36-960e-4409-b124-14dd6f668d29", "Description": null, "Flags": 0, "BuiltInType": 21, "DataType": "i=21", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "ConditionSubClassId", "Id": "3a16f3f9-7dab-482d-8330-41a5cf07e6cb", "Description": null, "Flags": 0, "BuiltInType": 17, "DataType": "i=17", "ValueRank": 1, "ArrayDimensions": [ 0 ], "MaxStringLength": 0, "Properties": null }, { "Name": "ConditionSubClassName", "Id": "3b995804-43a6-4ced-ba94-393a2ab458c1", "Description": null, "Flags": 0, "BuiltInType": 21, "DataType": "i=21", "ValueRank": 1, "ArrayDimensions": [ 0 ], "MaxStringLength": 0, "Properties": null }, { "Name": "EventId", "Id": "c6437e7e-02d5-4522-87cf-9191072e73f6", "Description": null, "Flags": 0, "BuiltInType": 15, "DataType": "i=15", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "EventType", "Id": "a13496e8-fb1d-482c-a624-80afc6482290", "Description": null, "Flags": 0, "BuiltInType": 17, "DataType": "i=17", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "LocalTime", "Id": "9a72a21a-9530-4049-ae24-253442ff2c56", "Description": null, "Flags": 0, "BuiltInType": 22, "DataType": "i=8912", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "Message", "Id": "06e2bdcd-889f-4383-b619-a64d03cb6736", "Description": null, "Flags": 0, "BuiltInType": 21, "DataType": "i=21", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "ReceiveTime", "Id": "5479a4b9-57ce-45e0-b1ad-c8656be69b7c", "Description": null, "Flags": 0, "BuiltInType": 13, "DataType": "i=294", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "Severity", "Id": "e98bb881-66b6-4bdd-8e07-0a0f8745f655", "Description": null, "Flags": 0, "BuiltInType": 5, "DataType": "i=5", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "SourceName", "Id": "9d7858f8-e9b1-486b-a4c3-675b04b94f0a", "Description": null, "Flags": 0, "BuiltInType": 12, "DataType": "i=12", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "SourceNode", "Id": "782a5509-524f-42da-9d10-273e69aa28db", "Description": null, "Flags": 0, "BuiltInType": 17, "DataType": "i=17", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "Time", "Id": "9e644e13-fe64-4969-8728-ec11ae75426c", "Description": null, "Flags": 0, "BuiltInType": 13, "DataType": "i=294", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null } ], "StructureDataTypes": [ { "DataTypeId": "i=8912", "Name": "TimeZoneDataType", "StructureType": 0, "Fields": [ { "Name": "Offset", "DataType": "i=4", "Description": null, "IsOptional": false, "ValueRank": -1, "ArrayDimensions": [], "MaxStringLength": 0 }, { "Name": "DaylightSavingInOffset", "DataType": "i=1", "Description": null, "IsOptional": false, "ValueRank": -1, "ArrayDimensions": [], "MaxStringLength": 0 } ], "BaseDataType": "i=22", "DefaultEncodingId": "i=8917" } ], "EnumDataTypes": [], "SimpleDataTypes": [ { "DataTypeId": "i=294", "Name": "UtcTime", "BaseDataType": "i=13", "BuiltInType": 13 } ] }, "DataSetMessageContentFlags": 0, "DataSetFieldContentFlags": 3080199, "TypeName": null } ], "NetworkMessageContentFlags": 8192, "TypeName": null } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Resources/PlcSimulation.json ================================================ { "Id": "c0b8f1a2-3e4f-4b5c-8d6e-7f8a9b0c1d2e", "Version": 1, "DataSetMessages": [ { "Id": "c0b8f1a2-3e4f-4b5c-8d6e-7f8a9b0c1d2e", "MetaData": { "MinorVersion": 3595526521, "DataSetMetaData": { "Name": null, "DataSetClassId": "00000000-0000-0000-0000-000000000000", "Description": null, "MajorVersion": null }, "Fields": [ { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=StepUp", "Id": "d18eeb8c-22a8-4d73-a8be-136895c965dd", "Description": "Constantly increasing value", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean", "Id": "45279d6e-f564-4a37-afa2-381d3d43cdba", "Description": "Alternating boolean value", "Flags": 0, "BuiltInType": 1, "DataType": "i=1", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32", "Id": "fbe38400-24f2-4e3a-898c-08dafe585df8", "Description": "Random signed 32 bit integer value", "Flags": 0, "BuiltInType": 6, "DataType": "i=6", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32", "Id": "5dacaaaf-803e-491d-a651-615229b3a511", "Description": "Random unsigned 32 bit integer value", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData", "Id": "3230161b-224a-45d4-b9ef-c859d024b447", "Description": "Value with random dips", "Flags": 0, "BuiltInType": 11, "DataType": "i=11", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1", "Id": "03433afc-8667-43fa-ba9c-4981eddd49d2", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2", "Id": "0a258a02-fb3d-4aa0-8ba5-d22c4d3e776a", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3", "Id": "73c1ea83-5206-46e0-9bae-3fb80970653a", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1", "Id": "4a304488-9b9f-4a2e-9dc2-fab34ef63f91", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2", "Id": "6c589007-ed13-40bf-a7d7-33ff19086ddf", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3", "Id": "6fda4154-e6ba-4bbf-a55a-06640d112384", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData", "Id": "52cb7518-a46c-4ff9-9a6b-da749a3224f2", "Description": "Value with a slow negative trend", "Flags": 0, "BuiltInType": 11, "DataType": "i=11", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData", "Id": "ff379c49-83d7-4358-be4c-a97b1942e793", "Description": "Value with a slow positive trend", "Flags": 0, "BuiltInType": 11, "DataType": "i=11", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData", "Id": "ed45d2b2-4514-46d3-8ff5-f02a858f1fa8", "Description": "Value with random spikes", "Flags": 0, "BuiltInType": 11, "DataType": "i=11", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null } ], "StructureDataTypes": [], "EnumDataTypes": [], "SimpleDataTypes": [] }, "DataSetMessageContentFlags": 0, "DataSetFieldContentFlags": 3080199, "TypeName": null }, { "Id": "754714A3-DF97-484D-BC95-66C48EB61B9A", "MetaData": { "MinorVersion": 3598940497, "DataSetMetaData": { "Name": null, "DataSetClassId": "00000000-0000-0000-0000-000000000000", "Description": null, "MajorVersion": null }, "Fields": [ { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1", "Id": "d1920dbc-c101-46e7-bd61-63441b370774", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2", "Id": "1df5f88a-e287-4949-a45b-a22d8cba9644", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3", "Id": "5d2028d7-74b6-4570-b4eb-17c77bdc1ad3", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1", "Id": "7965119c-90c0-4325-a327-c3dd355845e6", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1", "Id": "873b721b-8c5a-499c-bcf4-7435b1f35f45", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2", "Id": "8595fa98-23f3-4887-88c0-a58dbb019cab", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3", "Id": "2712a010-2aa4-4065-b00c-79ba068bbfa2", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1", "Id": "31fcd44e-3059-47fa-8eab-8cfea0c9173b", "Description": "Constantly increasing value(s)", "Flags": 0, "BuiltInType": 7, "DataType": "i=7", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null } ], "StructureDataTypes": [], "EnumDataTypes": [], "SimpleDataTypes": [] }, "DataSetMessageContentFlags": 0, "DataSetFieldContentFlags": 3080199, "TypeName": null } ], "NetworkMessageContentFlags": 8192, "TypeName": null } ================================================ FILE: src/Azure.IIoT.OpcUa/tests/Resources/SimpleEvents.json ================================================ { "Id": "c0b8f1a2-3e4f-4b5c-8d6e-7f8a9b0c1d2e", "Version": 1, "DataSetMessages": [ { "Id": "c0b8f1a2-3e4f-4b5c-8d6e-7f8a9b0c1d2e", "MetaData": { "MinorVersion": 173068024, "DataSetMetaData": { "Name": null, "DataSetClassId": "00000000-0000-0000-0000-000000000000", "Description": null, "MajorVersion": null }, "Fields": [ { "Name": "EventId", "Id": "0e461d96-defd-4b43-8414-c2e3676e440f", "Description": null, "Flags": 0, "BuiltInType": 15, "DataType": "i=15", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "Message", "Id": "df0e9f02-943a-41a3-9f16-e766dd0a7644", "Description": null, "Flags": 0, "BuiltInType": 21, "DataType": "i=21", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "http://opcfoundation.org/SimpleEvents#CycleId", "Id": "09377953-35be-4d90-ae56-010d9172adf9", "Description": null, "Flags": 0, "BuiltInType": 12, "DataType": "i=12", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null }, { "Name": "http://opcfoundation.org/SimpleEvents#CurrentStep", "Id": "505473a1-4a65-41d1-a451-68848a06bca6", "Description": null, "Flags": 0, "BuiltInType": 22, "DataType": "nsu=http://opcfoundation.org/SimpleEvents;i=183", "ValueRank": -1, "ArrayDimensions": null, "MaxStringLength": 0, "Properties": null } ], "StructureDataTypes": [ { "DataTypeId": "nsu=http://opcfoundation.org/SimpleEvents;i=183", "Name": "nsu=http://opcfoundation.org/SimpleEvents;CycleStepDataType", "StructureType": 0, "Fields": [ { "Name": "Name", "DataType": "i=12", "Description": null, "IsOptional": false, "ValueRank": -1, "ArrayDimensions": [], "MaxStringLength": 0 }, { "Name": "Duration", "DataType": "i=11", "Description": null, "IsOptional": false, "ValueRank": -1, "ArrayDimensions": [], "MaxStringLength": 0 } ], "BaseDataType": "i=22", "DefaultEncodingId": null } ], "EnumDataTypes": [], "SimpleDataTypes": [] }, "DataSetMessageContentFlags": 0, "DataSetFieldContentFlags": 3080199, "TypeName": null } ], "NetworkMessageContentFlags": 8192, "TypeName": null } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Azure.IIoT.OpcUa.Publisher.csproj ================================================  net9.0 true enable ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Constants.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { /// /// Constants for diagnostics /// internal static class Constants { /// /// Connection group identifier tag /// public const string ConnectionGroupTag = "connectionGroupId"; /// /// Default dataset writer id /// public const string DefaultDataSetWriterName = "<>"; /// /// Writer group identifier tag /// public const string WriterGroupNameTag = "writerGroupName"; /// /// Writer group identifier tag /// public const string WriterGroupIdTag = "writerGroupId"; /// /// Default writer group id /// public const string DefaultWriterGroupName = "<>"; /// /// Publisher identifier tag /// public const string PublisherIdTag = "publisherId"; /// /// Default publisher id /// public const string DefaultPublisherId = "<>"; /// /// Site identifier tag /// public const string SiteIdTag = "siteId"; /// /// Default Site id /// public const string DefaultSiteId = "<>"; /// /// Default event name /// public const string DefaultEventName = "<>"; /// /// Default context name /// public const string DefaultContextName = "<>"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Discovery/NetworkDiscovery.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Discovery { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Azure.IIoT.OpcUa.Publisher.Stack.Transport.Models; using Azure.IIoT.OpcUa.Publisher.Stack.Transport.Probe; using Azure.IIoT.OpcUa.Publisher.Stack.Transport.Scanner; using Azure.IIoT.OpcUa.Encoders; using Furly.Exceptions; using Furly.Extensions.Messaging; using Furly.Extensions.Serializers; using Furly.Extensions.Utils; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.Metrics; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; using Opc.Ua; /// /// Provides network discovery of endpoints /// public sealed class NetworkDiscovery : INetworkDiscovery, IDiscoveryServices, IDisposable { /// /// Running in container /// public static bool IsContainer => StringComparer.OrdinalIgnoreCase.Equals( Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") ?? string.Empty, "true"); /// /// Create services /// /// /// /// /// /// /// /// /// public NetworkDiscovery(IEndpointDiscovery client, IEventClient events, IJsonSerializer serializer, IOptions options, ILoggerFactory loggerFactory, IDiscoveryProgress? progress = null, IMetricsContext? metrics = null, TimeProvider? timeProvider = null) { _loggerFactory = loggerFactory; _serializer = serializer; _client = client; _events = events; _options = options; _metrics = metrics ?? IMetricsContext.Empty; _timeProvider = timeProvider ?? TimeProvider.System; _request = new DiscoveryRequest(progress ?? new ProgressLogger(loggerFactory.CreateLogger()), _timeProvider); _channel = Channel.CreateUnbounded(); _logger = loggerFactory.CreateLogger(); _topic = new TopicBuilder(options.Value).EventsTopic; _runner = Task.Run(() => ProcessDiscoveryRequestsAsync(_cts.Token)); _timer = _timeProvider.CreateTimer(_ => OnScanScheduling(), null, TimeSpan.FromSeconds(20), Timeout.InfiniteTimeSpan); } /// public Task RegisterAsync(ServerRegistrationRequestModel request, CancellationToken ct) { if (request.DiscoveryUrl == null) { throw new ArgumentException("Missing discovery url", nameof(request)); } return DiscoverAsync(new DiscoveryRequestModel { Id = request.Id, Discovery = DiscoveryMode.Off, Configuration = new DiscoveryConfigModel { DiscoveryUrls = new List { request.DiscoveryUrl } } }, ct); } /// public async Task DiscoverAsync(DiscoveryRequestModel request, CancellationToken ct) { kDiscoverAsync.Add(1, _metrics.TagList); ArgumentNullException.ThrowIfNull(request); var task = new DiscoveryRequest(request, _request.Progress, _timeProvider); var scheduled = _channel.Writer.TryWrite(task); if (!scheduled) { task.Dispose(); _logger.DiscoveryRequestNotScheduled(); var ex = new ResourceExhaustionException("Failed to schedule task"); task.Progress.OnDiscoveryError(request, ex); throw ex; } await _lock.WaitAsync(ct).ConfigureAwait(false); try { if (_pending.Count != 0) { task.Progress.OnDiscoveryPending(task.Request, _pending.Count); } _pending.Add(task); } finally { _lock.Release(); } } /// public async Task CancelAsync(DiscoveryCancelRequestModel request, CancellationToken ct) { kCancelAsync.Add(1, _metrics.TagList); ArgumentNullException.ThrowIfNull(request); await _lock.WaitAsync(ct).ConfigureAwait(false); try { foreach (var task in _pending.Where(r => r.Request.Id == request.Id)) { // Cancel the task task.Cancel(); } } finally { _lock.Release(); } } /// public async Task> FindServersAsync( DiscoveryRequestModel request, IDiscoveryProgress? progress, CancellationToken ct) { progress ??= _request.Progress; var task = new DiscoveryRequest(request, progress, _timeProvider, cancellationToken: ct); var results = await DiscoverServersAsync(task).ConfigureAwait(false); return results.Select(r => r.Discovered); } /// public Task> FindEndpointsAsync(Uri discoveryUrl, IReadOnlyList? locales, bool findServersOnNetwork, CancellationToken ct) { return _client.FindEndpointsAsync(discoveryUrl, locales, findServersOnNetwork, ct); } /// public void Dispose() { try { _timer.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); Try.Async(StopDiscoveryRequestProcessingAsync).Wait(); } finally { // Dispose _cts.Dispose(); _timer.Dispose(); _lock.Dispose(); _request.Dispose(); } } /// /// Scan timer expired /// private void OnScanScheduling() { try { _timer.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); _lock.Wait(); try { foreach (var task in _pending.Where(r => r.IsScan)) { // Cancel any current scan tasks if any task.Cancel(); } // Add new discovery request if (_request.Mode != DiscoveryMode.Off) { // Push request var task = _request.Clone(); if (_channel.Writer.TryWrite(task)) { _pending.Add(task); } else { task.Dispose(); } } } finally { _lock.Release(); } } catch (ObjectDisposedException ex) { _logger.ObjectDisposedTimerFiring(ex); } } /// /// Stop discovery request processing /// /// private async Task StopDiscoveryRequestProcessingAsync() { _channel.Writer.TryComplete(); _timer.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); await _lock.WaitAsync().ConfigureAwait(false); try { // Cancel all requests first foreach (var request in _pending) { request.Cancel(); } } finally { _lock.Release(); } // Try cancel discovery and wait for completion of runner Try.Op(() => _cts?.Cancel()); try { await _runner.ConfigureAwait(false); } catch (OperationCanceledException) { } catch (Exception ex) { _logger.UnexpectedExceptionStoppingProcessor(ex); } } /// /// Process discovery requests /// /// /// private async Task ProcessDiscoveryRequestsAsync(CancellationToken ct) { _logger.StartingDiscoveryProcessor(); // Process all discovery requests await foreach (var request in _channel.Reader.ReadAllAsync(ct).ConfigureAwait(false)) { try { try { // Update pending queue size await ReportPendingRequestsAsync().ConfigureAwait(false); await ProcessDiscoveryRequestAsync(request).ConfigureAwait(false); } finally { // If the request is scan request, schedule next one if (!ct.IsCancellationRequested && (request?.IsScan ?? false)) { // Re-schedule another scan when idle time expired _timer.Change( request.Request.Configuration?.IdleTimeBetweenScans ?? TimeSpan.FromHours(1), Timeout.InfiniteTimeSpan); } } } catch (OperationCanceledException) { } catch (Exception ex) { _logger.DiscoveryProcessorErrorOccurred(ex); } } // Send cancellation for all pending items await CancelPendingRequestsAsync().ConfigureAwait(false); _logger.StoppedDiscoveryProcessor(); } /// /// Process the provided discovery request /// /// private async Task ProcessDiscoveryRequestAsync(DiscoveryRequest request) { _logger.ProcessingDiscoveryRequest(); request.Progress.OnDiscoveryStarted(request.Request); object? diagnostics = null; // // Discover servers // try { var results = await DiscoverServersAsync(request).ConfigureAwait(false); // Merge results var registrations = results.ConvertAll(r => r.Discovered.ToServiceModel( r.Host, _options.Value.SiteId, _events.Identity, _serializer)); var discovered = new List (); foreach (var registration in registrations) { discovered.AddOrUpdate(registration); } request.Token.ThrowIfCancellationRequested(); // // Upload results // await SendDiscoveryResultsAsync(request, discovered, _timeProvider.GetUtcNow(), diagnostics, request.Token).ConfigureAwait(false); request.Progress.OnDiscoveryFinished(request.Request); } catch (OperationCanceledException) { request.Progress.OnDiscoveryCancelled(request.Request); } catch (Exception ex) { request.Progress.OnDiscoveryError(request.Request, ex); } finally { if (request != null) { await _lock.WaitAsync().ConfigureAwait(false); try { _pending.Remove(request); Try.Op(request.Dispose); } finally { _lock.Release(); } } } } /// /// Run a network discovery /// /// /// private async Task> DiscoverServersAsync( DiscoveryRequest request) { var discoveryUrls = await GetDiscoveryUrlsAsync(request.DiscoveryUrls).ConfigureAwait(false); if (request.Mode == DiscoveryMode.Off) { return await DiscoverServersAsync(request, discoveryUrls, request.Configuration.Locales).ConfigureAwait(false); } _logger.StartDiscoveryRun(request.Mode); var watch = Stopwatch.StartNew(); // // Set up scanner pipeline and start discovery // var local = request.Mode == DiscoveryMode.Local; #if !NO_WATCHDOG _counter = 0; #endif var addresses = new List(); request.Progress.OnNetScanStarted(request.Request, 0, 0, request.TotalAddresses); using (var netscanner = new NetworkScanner(_loggerFactory.CreateLogger(), (scanner, reply) => { request.Progress.OnNetScanResult(request.Request, scanner.ActiveProbes, scanner.ScanCount, request.TotalAddresses, addresses.Count, reply.Address); addresses.Add(reply.Address); }, local, local ? null : request.AddressRanges, request.NetworkClass, request.Configuration.MaxNetworkProbes, request.Configuration.NetworkProbeTimeout, request.Token)) { // Log progress var progress = _timeProvider.CreateTimer(_ => ProgressTimer( () => request.Progress.OnNetScanProgress(request.Request, netscanner.ActiveProbes, netscanner.ScanCount, request.TotalAddresses, addresses.Count)), null, kProgressInterval, kProgressInterval); await using (progress.ConfigureAwait(false)) { await netscanner.WaitToCompleteAsync().ConfigureAwait(false); } request.Progress.OnNetScanFinished(request.Request, netscanner.ActiveProbes, netscanner.ScanCount, request.TotalAddresses, addresses.Count); } request.Token.ThrowIfCancellationRequested(); await AddLoopbackAddressesAsync(addresses).ConfigureAwait(false); if (addresses.Count == 0) { return []; } var ports = new List(); var totalPorts = request.TotalPorts * addresses.Count; var probe = new ServerProbe(_logger); #if !NO_WATCHDOG _counter = 0; #endif request.Progress.OnPortScanStart(request.Request, 0, 0, totalPorts); using (var portscan = new PortScanner(_loggerFactory.CreateLogger(), addresses.SelectMany(address => { var ranges = request.PortRanges ?? PortRange.OpcUa; return ranges.SelectMany(x => x.GetEndpoints(address)); }), (scanner, ep) => { request.Progress.OnPortScanResult(request.Request, scanner.ActiveProbes, scanner.ScanCount, totalPorts, ports.Count, ep); ports.Add(ep); }, probe, request.Configuration.MaxPortProbes, request.Configuration.MinPortProbesPercent, request.Configuration.PortProbeTimeout, request.Token)) { var progress = _timeProvider.CreateTimer(_ => ProgressTimer( () => request.Progress.OnPortScanProgress(request.Request, portscan.ActiveProbes, portscan.ScanCount, totalPorts, ports.Count)), null, kProgressInterval, kProgressInterval); await using (progress.ConfigureAwait(false)) { await portscan.WaitToCompleteAsync().ConfigureAwait(false); } request.Progress.OnPortScanFinished(request.Request, portscan.ActiveProbes, portscan.ScanCount, totalPorts, ports.Count); } request.Token.ThrowIfCancellationRequested(); if (ports.Count == 0) { return []; } // // Collect discovery urls // foreach (var ep in ports) { request.Token.ThrowIfCancellationRequested(); var resolved = await ep.TryResolveAsync().ConfigureAwait(false); var url = new Uri("opc.tcp://" + resolved); discoveryUrls.AddOrUpdate(ep, url); } request.Token.ThrowIfCancellationRequested(); // // Create application model list from discovered endpoints... // var discovered = await DiscoverServersAsync(request, discoveryUrls, request.Configuration.Locales).ConfigureAwait(false); _logger.DiscoveryTookAndFoundServers(watch.Elapsed, discovered.Count); return discovered; } /// /// Discover servers using opcua discovery and filter by optional locale /// /// /// /// /// private async Task> DiscoverServersAsync( DiscoveryRequest request, Dictionary discoveryUrls, IReadOnlyList? locales) { kDiscoverServersAsync.Add(1, _metrics.TagList); var discovered = new List<(DiscoveredEndpointModel Discovered, string Host)> (); var count = 0; request.Progress.OnServerDiscoveryStarted(request.Request, 1, count, discoveryUrls.Count); foreach (var item in discoveryUrls) { request.Token.ThrowIfCancellationRequested(); var url = item.Value; request.Progress.OnFindEndpointsStarted(request.Request, 1, count, discoveryUrls.Count, discovered.Count, url, item.Key.Address); // Find endpoints at the real accessible ip address var eps = await _client.FindEndpointsAsync(new UriBuilder(url) { Host = item.Key.Address.ToString() }.Uri, locales, findServersOnNetwork: true, request.Token).ConfigureAwait(false); count++; var endpoints = 0; foreach (var ep in eps) { discovered.Add((ep, item.Key.ToString())); endpoints++; } request.Progress.OnFindEndpointsFinished(request.Request, 1, count, discoveryUrls.Count, discovered.Count, url, item.Key.Address, endpoints); } request.Progress.OnServerDiscoveryFinished(request.Request, 1, discoveryUrls.Count, discoveryUrls.Count, discovered.Count); request.Token.ThrowIfCancellationRequested(); return discovered; } /// /// Get all reachable addresses from urls /// /// /// private async Task> GetDiscoveryUrlsAsync( IEnumerable discoveryUrls) { var result = new Dictionary(); if (discoveryUrls?.Any() ?? false) { var results = await Task.WhenAll(discoveryUrls .Select(GetHostEntryAsync) .ToArray()).ConfigureAwait(false); foreach (var entry in results .SelectMany(v => v) .Where(a => a.Item2 != null)) { result.AddOrUpdate(entry.Item1, entry.Item2); } } return result; } /// /// Get a reachable host address from url /// /// /// private async Task>> GetHostEntryAsync( Uri discoveryUrl) { var list = new List>(); try { var host = discoveryUrl.DnsSafeHost; // check first if host is an IP Address since the Dns.GetHostEntryAsync // throws a socket exception when called with an IP address try { var hostIp = IPAddress.Parse(host); var ep = new IPEndPoint(hostIp, discoveryUrl.IsDefaultPort ? 4840 : discoveryUrl.Port); list.Add(Tuple.Create(ep, discoveryUrl)); return list; } catch { // Parsing failed, therefore not an IP address, continue with dns // resolution } while (!string.IsNullOrEmpty(host)) { try { var entry = await Dns.GetHostEntryAsync(host).ConfigureAwait(false); // only pick-up the IPV4 addresses var foundIpv4 = false; foreach (var address in entry.AddressList .Where(a => a.AddressFamily == AddressFamily.InterNetwork)) { var ep = new IPEndPoint(address, discoveryUrl.IsDefaultPort ? 4840 : discoveryUrl.Port); list.Add(Tuple.Create(ep, discoveryUrl)); foundIpv4 = true; } if (!foundIpv4) { // if no IPV4 responsive, try IPV6 as fallback foreach (var address in entry.AddressList .Where(a => a.AddressFamily != AddressFamily.InterNetwork)) { var ep = new IPEndPoint(address, discoveryUrl.IsDefaultPort ? 4840 : discoveryUrl.Port); list.Add(Tuple.Create(ep, discoveryUrl)); } } // Check local host if (StringComparer.OrdinalIgnoreCase.Equals(host, "localhost") && IsContainer) { // Also resolve docker internal since we are in a container host = Environment.GetEnvironmentVariable(kIoTEdgeGatewayHostNameEnvVar); continue; } break; } catch (SocketException se) { _logger.FailedToResolveHostForDiscoveryUrl(discoveryUrl, se.Message); return list; } catch (Exception e) { _logger.FailedToResolveHostForDiscoveryUrlException(e, discoveryUrl); return list; } } } catch (Exception ex) { _logger.FailedToGetHostEntry(ex); } return list; } /// /// Add localhost ip to list if not already in it. /// /// /// private async Task AddLoopbackAddressesAsync(List addresses) { // Check local host var hostName = Environment.GetEnvironmentVariable(kIoTEdgeGatewayHostNameEnvVar); try { if (IsContainer) { // Resolve docker host since we are running in a container if (string.IsNullOrEmpty(hostName)) { _logger.GatewayHostNameNotSet(); return; } _logger.ResolveIpForGatewayHostName(hostName); var entry = await Dns.GetHostEntryAsync(hostName).ConfigureAwait(false); foreach (var address in entry.AddressList .Where(a => a.AddressFamily == AddressFamily.InterNetwork) .Where(a => !addresses.Any(b => a.Equals(b)))) { _logger.IncludingGatewayHostAddress(address); addresses.Add(address); } } else { // Add loopback address addresses.Add(IPAddress.Loopback); } } catch (SocketException se) { _logger.FailedToAddAddressForGatewayHost(hostName, se.Message); } catch (Exception e) { _logger.FailedToAddAddressForGatewayHostException(e, hostName); } } /// /// Upload results /// /// /// /// /// /// /// private async Task SendDiscoveryResultsAsync(DiscoveryRequest request, List discovered, DateTimeOffset timestamp, object? diagnostics, CancellationToken ct) { _logger.UploadingResults(discovered.Count); var buffers = discovered .SelectMany(server => (server.Endpoints ?? Array.Empty()) .Select(registration => new DiscoveryEventModel { Application = server.Application, Registration = registration, TimeStamp = timestamp })) .Append(new DiscoveryEventModel { Registration = null, // last Result = new DiscoveryResultModel { DiscoveryConfig = request.Configuration, Id = request.Request.Id, Context = request.Request.Context, RegisterOnly = request.Mode == DiscoveryMode.Off, Diagnostics = diagnostics == null ? null : _serializer.FromObject(diagnostics) }, TimeStamp = timestamp }) .Select((discovery, i) => { discovery.Index = i; return _serializer.SerializeToMemory(discovery); }) .ToList(); await _events.SendEventAsync(_topic, buffers, _serializer.MimeType, Encoding.UTF8.WebName, e => e.AddProperty(OpcUa.Constants.MessagePropertySchemaKey, MessageSchemaTypes.DiscoveryEvents), ct: ct).ConfigureAwait(false); _logger.ResultsUploaded(discovered.Count); } /// /// Cancel all remaining pending requests /// /// private async Task CancelPendingRequestsAsync() { _logger.CancellingAllPendingRequests(); await _lock.WaitAsync().ConfigureAwait(false); try { foreach (var request in _pending) { request.Progress.OnDiscoveryCancelled(request.Request); Try.Op(request.Dispose); } _pending.Clear(); } finally { _lock.Release(); } _logger.PendingRequestsCancelled(); } /// /// Send pending queue size /// /// private async Task ReportPendingRequestsAsync() { // Notify all listeners about the request's place in queue await _lock.WaitAsync().ConfigureAwait(false); try { for (var pos = 0; pos < _pending.Count; pos++) { var item = _pending[pos]; if (!item.Token.IsCancellationRequested) { item.Progress.OnDiscoveryPending(item.Request, pos); } } } catch (Exception ex) { _logger.FailedToSendPendingEvent(ex); } finally { _lock.Release(); } } /// /// Called in intervals to check and log progress. /// /// /// private void ProgressTimer(Action log) { if ((_counter % 3) == 0) { _logger.GcMemWorkingSetPrivateMemHandles( GC.GetTotalMemory(false) / 1024, Process.GetCurrentProcess().WorkingSet64 / 1024, Process.GetCurrentProcess().PrivateMemorySize64 / 1024, Process.GetCurrentProcess().HandleCount); } ++_counter; #if !NO_WATCHDOG if ((_counter % 200) == 0 && _counter >= 2000) { throw new ThreadStateException("Stuck"); } #endif log(); } #if !NO_WATCHDOG private int _counter; #endif private static readonly Counter kDiscoverAsync = Diagnostics.Meter.CreateCounter( "iiot_edge_discovery_discover", "calls", "call to discover"); private static readonly Counter kCancelAsync = Diagnostics.Meter.CreateCounter( "iiot_edge_discovery_cancel", "calls", "call to cancel"); private static readonly Counter kDiscoverServersAsync = Diagnostics.Meter.CreateCounter( "iiot_edge_discovery_discover_servers", "calls", "call to discoverServersAsync"); /// Progress reporting every 3 seconds private static readonly TimeSpan kProgressInterval = TimeSpan.FromSeconds(3); private const string kIoTEdgeGatewayHostNameEnvVar = "IOTEDGE_GATEWAYHOSTNAME"; private readonly ILogger _logger; private readonly ILoggerFactory _loggerFactory; private readonly IJsonSerializer _serializer; private readonly IEventClient _events; private readonly IOptions _options; private readonly Channel _channel; private readonly IMetricsContext _metrics; private readonly IEndpointDiscovery _client; private readonly Task _runner; private readonly ITimer _timer; private readonly TimeProvider _timeProvider; private readonly string _topic; private readonly SemaphoreSlim _lock = new(1, 1); private readonly List _pending = []; private readonly CancellationTokenSource _cts = new(); private readonly DiscoveryRequest _request; } /// /// Source-generated logging extensions for NetworkDiscovery /// internal static partial class NetworkDiscoveryLogging { private const int EventClass = 0; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Error, Message = "Discovery request not scheduled, internal server error!")] public static partial void DiscoveryRequestNotScheduled(this ILogger logger); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Error, Message = "Object disposed but still timer is firing")] public static partial void ObjectDisposedTimerFiring(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Error, Message = "Unexpected exception stopping processor thread.")] public static partial void UnexpectedExceptionStoppingProcessor(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Information, Message = "Starting discovery processor...")] public static partial void StartingDiscoveryProcessor(this ILogger logger); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Error, Message = "Discovery processor error occurred - continue...")] public static partial void DiscoveryProcessorErrorOccurred(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Information, Message = "Stopped discovery processor.")] public static partial void StoppedDiscoveryProcessor(this ILogger logger); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Debug, Message = "Processing discovery request...")] public static partial void ProcessingDiscoveryRequest(this ILogger logger); [LoggerMessage(EventId = EventClass + 8, Level = LogLevel.Information, Message = "Start {Mode} discovery run...")] public static partial void StartDiscoveryRun(this ILogger logger, DiscoveryMode mode); [LoggerMessage(EventId = EventClass + 9, Level = LogLevel.Information, Message = "Discovery took {Elapsed} and found {Count} servers.")] public static partial void DiscoveryTookAndFoundServers(this ILogger logger, TimeSpan elapsed, int count); [LoggerMessage(EventId = EventClass + 10, Level = LogLevel.Information, Message = "Uploading {Count} results...")] public static partial void UploadingResults(this ILogger logger, int count); [LoggerMessage(EventId = EventClass + 11, Level = LogLevel.Information, Message = "{Count} results uploaded.")] public static partial void ResultsUploaded(this ILogger logger, int count); [LoggerMessage(EventId = EventClass + 12, Level = LogLevel.Information, Message = "Cancelling all pending requests...")] public static partial void CancellingAllPendingRequests(this ILogger logger); [LoggerMessage(EventId = EventClass + 13, Level = LogLevel.Information, Message = "Pending requests cancelled...")] public static partial void PendingRequestsCancelled(this ILogger logger); [LoggerMessage(EventId = EventClass + 14, Level = LogLevel.Information, Message = "Gateway host name not set")] public static partial void GatewayHostNameNotSet(this ILogger logger); [LoggerMessage(EventId = EventClass + 15, Level = LogLevel.Debug, Message = "Resolve IP for gateway host name: {Address}")] public static partial void ResolveIpForGatewayHostName(this ILogger logger, string address); [LoggerMessage(EventId = EventClass + 16, Level = LogLevel.Information, Message = "Including gateway host address {Address}")] public static partial void IncludingGatewayHostAddress(this ILogger logger, IPAddress address); [LoggerMessage(EventId = EventClass + 17, Level = LogLevel.Warning, Message = "Failed to add address for gateway host {HostName} due to {Error}.")] public static partial void FailedToAddAddressForGatewayHost(this ILogger logger, string? hostName, string error); [LoggerMessage(EventId = EventClass + 18, Level = LogLevel.Error, Message = "Failed to add address for gateway host {HostName}.")] public static partial void FailedToAddAddressForGatewayHostException(this ILogger logger, Exception ex, string? hostName); [LoggerMessage(EventId = EventClass + 19, Level = LogLevel.Warning, Message = "Failed to send pending event")] public static partial void FailedToSendPendingEvent(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 20, Level = LogLevel.Information, Message = "GC Mem: {Gcmem} kb, Working set / Private Mem: {Privmem} kb / {Privmemsize} kb, Handles: {Handles}")] public static partial void GcMemWorkingSetPrivateMemHandles(this ILogger logger, long gcmem, long privmem, long privmemsize, int handles); [LoggerMessage(EventId = EventClass + 21, Level = LogLevel.Warning, Message = "Failed to resolve the host for {DiscoveryUrl} due to {Message}")] public static partial void FailedToResolveHostForDiscoveryUrl(this ILogger logger, Uri discoveryUrl, string message); [LoggerMessage(EventId = EventClass + 22, Level = LogLevel.Error, Message = "Failed to resolve the host for {DiscoveryUrl}")] public static partial void FailedToResolveHostForDiscoveryUrlException(this ILogger logger, Exception ex, Uri discoveryUrl); [LoggerMessage(EventId = EventClass + 23, Level = LogLevel.Debug, Message = "Failed to get host entry.")] public static partial void FailedToGetHostEntry(this ILogger logger, Exception ex); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Discovery/ProgressLogger.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Discovery { using Azure.IIoT.OpcUa.Publisher.Models; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Globalization; using System.Net; /// /// Discovery progress logger /// public class ProgressLogger : IDiscoveryProgress { /// /// Create listener /// /// /// internal ProgressLogger(ILogger logger, TimeProvider? timeProvider = null) { _logger = logger; _timeProvider = timeProvider ?? TimeProvider.System; } /// public void OnDiscoveryPending(DiscoveryRequestModel request, int pending) { Send(new DiscoveryProgressModel { EventType = DiscoveryProgressType.Pending, Request = request, Total = pending }); } /// public void OnDiscoveryStarted(DiscoveryRequestModel request) { Send(new DiscoveryProgressModel { EventType = DiscoveryProgressType.Started, Request = request }); } /// public void OnDiscoveryCancelled(DiscoveryRequestModel request) { Send(new DiscoveryProgressModel { TimeStamp = _timeProvider.GetUtcNow(), EventType = DiscoveryProgressType.Cancelled, Request = request }); } /// public void OnDiscoveryError(DiscoveryRequestModel request, Exception ex) { Send(new DiscoveryProgressModel { TimeStamp = _timeProvider.GetUtcNow(), EventType = DiscoveryProgressType.Error, Request = request, Result = ex.Message, ResultDetails = new Dictionary { ["exception"] = ex.ToString() } }); } /// public void OnDiscoveryFinished(DiscoveryRequestModel request) { Send(new DiscoveryProgressModel { TimeStamp = _timeProvider.GetUtcNow(), EventType = DiscoveryProgressType.Finished, Request = request }); } /// public void OnNetScanStarted(DiscoveryRequestModel request, int workers, int progress, int total) { Send(new DiscoveryProgressModel { TimeStamp = _timeProvider.GetUtcNow(), EventType = DiscoveryProgressType.NetworkScanStarted, Workers = workers, Progress = progress, Total = total, Request = request }); } /// public void OnNetScanResult(DiscoveryRequestModel request, int workers, int progress, int total, int discovered, IPAddress address) { Send(new DiscoveryProgressModel { TimeStamp = _timeProvider.GetUtcNow(), EventType = DiscoveryProgressType.NetworkScanResult, Workers = workers, Progress = progress, Total = total, Discovered = discovered, Result = address.ToString(), Request = request }); } /// public void OnNetScanProgress(DiscoveryRequestModel request, int workers, int progress, int total, int discovered) { Send(new DiscoveryProgressModel { TimeStamp = _timeProvider.GetUtcNow(), EventType = DiscoveryProgressType.NetworkScanProgress, Workers = workers, Progress = progress, Total = total, Discovered = discovered, Request = request }); } /// public void OnNetScanFinished(DiscoveryRequestModel request, int workers, int progress, int total, int discovered) { Send(new DiscoveryProgressModel { TimeStamp = _timeProvider.GetUtcNow(), EventType = DiscoveryProgressType.NetworkScanFinished, Workers = workers, Progress = progress, Total = total, Discovered = discovered, Request = request }); } /// public void OnPortScanStart(DiscoveryRequestModel request, int workers, int progress, int total) { Send(new DiscoveryProgressModel { TimeStamp = _timeProvider.GetUtcNow(), EventType = DiscoveryProgressType.PortScanStarted, Workers = workers, Progress = progress, Total = total, Request = request }); } /// public void OnPortScanResult(DiscoveryRequestModel request, int workers, int progress, int total, int discovered, IPEndPoint ep) { Send(new DiscoveryProgressModel { TimeStamp = _timeProvider.GetUtcNow(), EventType = DiscoveryProgressType.PortScanResult, Workers = workers, Progress = progress, Total = total, Discovered = discovered, Result = ep.ToString(), Request = request }); } /// public void OnPortScanProgress(DiscoveryRequestModel request, int workers, int progress, int total, int discovered) { Send(new DiscoveryProgressModel { EventType = DiscoveryProgressType.PortScanProgress, Workers = workers, Progress = progress, Total = total, Discovered = discovered, Request = request }); } /// public void OnPortScanFinished(DiscoveryRequestModel request, int workers, int progress, int total, int discovered) { Send(new DiscoveryProgressModel { EventType = DiscoveryProgressType.PortScanFinished, Workers = workers, Progress = progress, Total = total, Discovered = discovered, Request = request }); } /// public void OnServerDiscoveryStarted(DiscoveryRequestModel request, int workers, int progress, int total) { Send(new DiscoveryProgressModel { EventType = DiscoveryProgressType.ServerDiscoveryStarted, Workers = workers, Progress = progress, Total = total, Request = request }); } /// public void OnFindEndpointsStarted(DiscoveryRequestModel request, int workers, int progress, int total, int discovered, Uri url, IPAddress address) { Send(new DiscoveryProgressModel { EventType = DiscoveryProgressType.EndpointsDiscoveryStarted, RequestDetails = new Dictionary { ["url"] = url.ToString(), ["address"] = address.ToString() }, Workers = workers, Progress = progress, Total = total, Discovered = discovered, Request = request.Clone(_timeProvider) }); } /// public void OnFindEndpointsFinished(DiscoveryRequestModel request, int workers, int progress, int total, int discovered, Uri url, IPAddress address, int endpoints) { Send(new DiscoveryProgressModel { EventType = DiscoveryProgressType.EndpointsDiscoveryFinished, RequestDetails = new Dictionary { ["url"] = url.ToString(), ["address"] = address.ToString() }, Workers = workers, Progress = progress, Total = total, Discovered = discovered, Result = endpoints.ToString(CultureInfo.InvariantCulture), Request = request }); } /// public void OnServerDiscoveryFinished(DiscoveryRequestModel request, int workers, int progress, int total, int discovered) { Send(new DiscoveryProgressModel { EventType = DiscoveryProgressType.ServerDiscoveryFinished, Workers = workers, Progress = progress, Total = total, Discovered = discovered, Request = request }); } /// /// Send progress /// /// protected virtual void Send(DiscoveryProgressModel progress) { progress.TimeStamp = _timeProvider.GetUtcNow(); var requestId = progress.Request?.Id; switch (progress.EventType) { case DiscoveryProgressType.Pending: _logger.DiscoveryPending(requestId); break; case DiscoveryProgressType.Started: _logger.DiscoveryStarted(requestId); break; case DiscoveryProgressType.Cancelled: _logger.DiscoveryCancelled(requestId); break; case DiscoveryProgressType.Error: _logger.DiscoveryError(requestId, progress.Result); break; case DiscoveryProgressType.Finished: _logger.DiscoveryFinished(requestId); break; case DiscoveryProgressType.NetworkScanStarted: _logger.NetworkScanStarted(requestId, progress.Workers); break; case DiscoveryProgressType.NetworkScanResult: _logger.NetworkScanResult(requestId, progress.Result, progress.Progress); break; case DiscoveryProgressType.NetworkScanProgress: _logger.NetworkScanProgress(requestId, progress.Progress, progress.Discovered, progress.Workers); break; case DiscoveryProgressType.NetworkScanFinished: _logger.NetworkScanFinished(requestId, progress.Discovered, progress.Progress); break; case DiscoveryProgressType.PortScanStarted: _logger.PortScanStarted(requestId, progress.Workers); break; case DiscoveryProgressType.PortScanResult: _logger.PortScanResult(requestId, progress.Result, progress.Progress); break; case DiscoveryProgressType.PortScanProgress: _logger.PortScanProgress(requestId, progress.Progress, progress.Discovered, progress.Workers); break; case DiscoveryProgressType.PortScanFinished: _logger.PortScanFinished(requestId, progress.Discovered, progress.Progress); break; case DiscoveryProgressType.ServerDiscoveryStarted: _logger.ServerDiscoveryStarted(requestId, progress.Total); break; case DiscoveryProgressType.EndpointsDiscoveryStarted: _logger.EndpointsDiscoveryStarted(requestId, progress.RequestDetails?["url"]); break; case DiscoveryProgressType.EndpointsDiscoveryFinished: if (!progress.Discovered.HasValue || progress.Discovered == 0) { _logger.NoEndpointsDiscovered(requestId, progress.RequestDetails?["url"]); } _logger.EndpointsDiscoveryFinished(requestId, progress.Discovered ?? 0, progress.RequestDetails?["url"]); break; case DiscoveryProgressType.ServerDiscoveryFinished: _logger.ServerDiscoveryFinished(requestId, progress.Discovered); break; } } private readonly ILogger _logger; private readonly TimeProvider _timeProvider; } /// /// Source-generated logging extensions for ProgressLogger /// internal static partial class ProgressLoggerLogging { private const int EventClass = 30; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Trace, Message = "{RequestId}: Discovery operations pending.")] internal static partial void DiscoveryPending(this ILogger logger, string? requestId); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Information, Message = "{RequestId}: Discovery operation started.")] internal static partial void DiscoveryStarted(this ILogger logger, string? requestId); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Information, Message = "{RequestId}: Discovery operation cancelled.")] internal static partial void DiscoveryCancelled(this ILogger logger, string? requestId); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Error, Message = "{RequestId}: Error {Error} during discovery run.")] internal static partial void DiscoveryError(this ILogger logger, string? requestId, string? error); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Information, Message = "{RequestId}: Discovery operation completed.")] internal static partial void DiscoveryFinished(this ILogger logger, string? requestId); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Information, Message = "{RequestId}: Starting network scan ({Active} probes active)...")] internal static partial void NetworkScanStarted(this ILogger logger, string? requestId, int? active); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Information, Message = "{RequestId}: Found address {Address} ({Scanned} scanned)...")] internal static partial void NetworkScanResult(this ILogger logger, string? requestId, string? address, int? scanned); [LoggerMessage(EventId = EventClass + 8, Level = LogLevel.Information, Message = "{RequestId}: {Scanned} addresses scanned - {Discovered} discovered ({Active} probes active)...")] internal static partial void NetworkScanProgress(this ILogger logger, string? requestId, int? scanned, int? discovered, int? active); [LoggerMessage(EventId = EventClass + 9, Level = LogLevel.Information, Message = "{RequestId}: Found {Count} addresses. ({Scanned} scanned)...")] internal static partial void NetworkScanFinished(this ILogger logger, string? requestId, int? count, int? scanned); [LoggerMessage(EventId = EventClass + 10, Level = LogLevel.Information, Message = "{RequestId}: Starting port scanning ({Active} probes active)...")] internal static partial void PortScanStarted(this ILogger logger, string? requestId, int? active); [LoggerMessage(EventId = EventClass + 11, Level = LogLevel.Information, Message = "{RequestId}: Found server {Endpoint} ({Scanned} scanned)...")] internal static partial void PortScanResult(this ILogger logger, string? requestId, string? endpoint, int? scanned); [LoggerMessage(EventId = EventClass + 12, Level = LogLevel.Information, Message = "{RequestId}: {Scanned} ports scanned - {Discovered} discovered ({Active} probes active)...")] internal static partial void PortScanProgress(this ILogger logger, string? requestId, int? scanned, int? discovered, int? active); [LoggerMessage(EventId = EventClass + 13, Level = LogLevel.Information, Message = "{RequestId}: Found {Count} ports on servers ({Scanned} scanned)...")] internal static partial void PortScanFinished(this ILogger logger, string? requestId, int? count, int? scanned); [LoggerMessage(EventId = EventClass + 14, Level = LogLevel.Information, Message = "{RequestId}: Searching {Count} discovery urls for endpoints...")] internal static partial void ServerDiscoveryStarted(this ILogger logger, string? requestId, int? count); [LoggerMessage(EventId = EventClass + 15, Level = LogLevel.Information, Message = "{RequestId}: Trying to find endpoints on {Details}...")] internal static partial void EndpointsDiscoveryStarted(this ILogger logger, string? requestId, string? details); [LoggerMessage(EventId = EventClass + 16, Level = LogLevel.Information, Message = "{RequestId}: No endpoints discovered on {Details}.")] internal static partial void NoEndpointsDiscovered(this ILogger logger, string? requestId, string? details); [LoggerMessage(EventId = EventClass + 17, Level = LogLevel.Information, Message = "{RequestId}: Found {Count} endpoints on {Details}.")] internal static partial void EndpointsDiscoveryFinished(this ILogger logger, string? requestId, int count, string? details); [LoggerMessage(EventId = EventClass + 18, Level = LogLevel.Information, Message = "{RequestId}: Found total of {Count} servers ...")] internal static partial void ServerDiscoveryFinished(this ILogger logger, string? requestId, int? count); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Discovery/ProgressPublisher.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Discovery { using Azure.IIoT.OpcUa.Encoders; using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Extensions.Messaging; using Furly.Extensions.Serializers; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Channels; using System.Threading.Tasks; /// /// Discovery progress message sender /// public sealed class ProgressPublisher : ProgressLogger, IDisposable { /// /// Create listener /// /// /// /// /// /// public ProgressPublisher(IEnumerable events, IJsonSerializer serializer, IOptions options, ILogger logger, TimeProvider? timeProvider = null) : base(logger, timeProvider) { _serializer = serializer ?? throw new ArgumentNullException(nameof(serializer)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _options = options; if (_options.Value.AllowedEventAndDiagnosticsTransports.Count > 0) { var allowed = _options.Value.AllowedEventAndDiagnosticsTransports .Select(t => t.ToString()) .ToHashSet(StringComparer.OrdinalIgnoreCase); events = events .Where(e => allowed.Contains(e.Name)) .ToList(); } _events = events.Reverse().ToList(); _channel = Channel.CreateUnbounded( new UnboundedChannelOptions { SingleReader = true, SingleWriter = false }); _sender = Task.Factory.StartNew(SendProgressAsync, default, TaskCreationOptions.LongRunning, TaskScheduler.Default).Unwrap(); } /// protected override void Send(DiscoveryProgressModel progress) { base.Send(progress); if (!_channel.Writer.TryWrite(progress)) { _logger.CannotSendIfProgressPublisherDisposed(); ObjectDisposedException.ThrowIf(true, this); } } /// public void Dispose() { if (!_sender.IsCompleted) { _channel.Writer.Complete(); _sender.GetAwaiter().GetResult(); } } /// /// Send progress /// /// private async Task SendProgressAsync() { await foreach (var progress in _channel.Reader.ReadAllAsync().ConfigureAwait(false)) { var eventsTopic = _topicCache.GetOrAdd( (progress.EventType.ToString(), progress.RequestId), id => new TopicBuilder(_options.Value, variables: new Dictionary { [PublisherConfig.EventNameVariableName] = id.Item1 ?? Constants.DefaultEventName, [PublisherConfig.EventContextVariableName] = id.Item2 ?? Constants.DefaultContextName, [PublisherConfig.EventSourceVariableName] = "discovery", [PublisherConfig.EncodingVariableName] = MessageEncoding.Json.ToString() // ... }).EventsTopic); await Task.WhenAll(_events.Select(SendOneEventAsync)).ConfigureAwait(false); async Task SendOneEventAsync(IEventClient events) { try { await events.SendEventAsync(eventsTopic, _serializer.SerializeToMemory(progress with { DiscovererId = events.Identity }), _serializer.MimeType, Encoding.UTF8.WebName, eventMessage => { if (_options.Value.EnableCloudEvents == true) { eventMessage = eventMessage.AsCloudEvent(new CloudEventHeader { Id = Guid.NewGuid().ToString("N"), Source = new Uri("urn:" + _options.Value.PublisherId), Subject = progress.EventType.ToString(), Type = MessageSchemaTypes.DiscoveryMessage }); } else { eventMessage.AddProperty(OpcUa.Constants.MessagePropertySchemaKey, MessageSchemaTypes.DiscoveryMessage); } }).ConfigureAwait(false); } catch (Exception ex) { _logger.FailedToSendDiscoveryProgress(ex); } } } } private readonly ILogger _logger; private readonly IJsonSerializer _serializer; private readonly Task _sender; private readonly Channel _channel; private readonly IOptions _options; private readonly ConcurrentDictionary<(string, string?), string> _topicCache = new(); private readonly List _events; } internal static partial class ProgressPublisherLogging { private const int EventClass = 60; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Error, Message = "Cannot send if progress publisher is already disposed.")] public static partial void CannotSendIfProgressPublisherDisposed(this ILogger logger); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Error, Message = "Failed to send discovery progress.")] public static partial void FailedToSendDiscoveryProgress(this ILogger logger, Exception ex); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Discovery/ServerDiscovery.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Discovery { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Furly.Exceptions; using Furly.Extensions.Serializers; using Microsoft.Extensions.Options; using System; using System.Threading; using System.Threading.Tasks; /// /// Server discovery on top of OPC UA endpoint discovery /// public sealed class ServerDiscovery : IServerDiscovery { /// /// Create services /// /// /// /// public ServerDiscovery(IEndpointDiscovery client, IJsonSerializer serializer, IOptions options) { _serializer = serializer ?? throw new ArgumentNullException(nameof(serializer)); _client = client ?? throw new ArgumentNullException(nameof(client)); _options = options ?? throw new ArgumentNullException(nameof(options)); } /// public async Task FindServerAsync( ServerEndpointQueryModel query, CancellationToken ct) { if (query?.DiscoveryUrl == null) { throw new ArgumentException("Discovery url missing", nameof(query)); } var discoveryUrl = new Uri(query.DiscoveryUrl); // Find endpoints at the real accessible ip address var eps = await _client.FindEndpointsAsync(discoveryUrl, findServersOnNetwork: true, ct: ct).ConfigureAwait(false); // Match endpoints foreach (var ep in eps) { if ((ep.Description.SecurityMode.ToServiceType() ?? SecurityMode.None) != (query.SecurityMode ?? SecurityMode.None)) { // no match continue; } if (query.SecurityPolicy != null && query.SecurityPolicy != ep.Description.SecurityPolicyUri) { // no match continue; } if (query.Certificate != null && query.Certificate != ep.Description.ServerCertificate.ToThumbprint()) { // no match continue; } return ep.ToServiceModel(discoveryUrl.Host, _options.Value.SiteId, _options.Value.PublisherId ?? Constants.DefaultPublisherId, _serializer); } throw new ResourceNotFoundException("Endpoints could not be found."); } private readonly IJsonSerializer _serializer; private readonly IOptions _options; private readonly IEndpointDiscovery _client; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Extensions/ContainerBuilderEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Discovery; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Storage; using Autofac; /// /// Container builder extensions /// public static class ContainerBuilderEx { /// /// Configure services /// /// public static void AddPublisherCore(this ContainerBuilder builder) { builder.AddOpcUaStack(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces().SingleInstance(); builder.RegisterType() .AsImplementedInterfaces().SingleInstance(); builder.RegisterType() .AsImplementedInterfaces().SingleInstance(); builder.RegisterType() .SingleInstance(); builder.RegisterType() .AsImplementedInterfaces().SingleInstance(); builder.RegisterType() .AsImplementedInterfaces().SingleInstance(); builder.RegisterType() .AsImplementedInterfaces().SingleInstance(); builder.RegisterType() .AsImplementedInterfaces().SingleInstance(); builder.RegisterType() .AsImplementedInterfaces().SingleInstance(); builder.RegisterType>() .AsImplementedInterfaces().InstancePerLifetimeScope(); builder.RegisterType() .AsImplementedInterfaces().InstancePerLifetimeScope(); builder.RegisterType>() .AsImplementedInterfaces().InstancePerLifetimeScope(); builder.RegisterType>() .AsImplementedInterfaces().InstancePerLifetimeScope(); builder.RegisterType() .AsImplementedInterfaces().InstancePerLifetimeScope(); builder.RegisterType() .AsImplementedInterfaces().InstancePerLifetimeScope(); builder.RegisterType() .AsImplementedInterfaces().InstancePerLifetimeScope(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Extensions/DataSetWriterModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Azure.IIoT.OpcUa.Publisher.Stack.Models; using System; /// /// Data set extensions /// internal static class DataSetWriterModelEx { /// /// Check whether there is anything the writer can publish /// /// /// public static bool HasDataToPublish(this DataSetWriterModel? writer) { var source = writer?.DataSet?.DataSetSource; if (source != null) { if (source.PublishedEvents?.PublishedData?.Count > 0 || source.PublishedVariables?.PublishedData?.Count > 0) { return true; } } return false; } /// /// Get connection to create subscription in /// /// /// /// /// /// public static ConnectionIdentifier GetConnection(this DataSetWriterModel dataSetWriter, string? writerGroupId, PublisherOptions options) { ArgumentNullException.ThrowIfNull(dataSetWriter); if (dataSetWriter.DataSet?.DataSetSource?.Connection == null) { throw new ArgumentException("Connection missing from data source", nameof(dataSetWriter)); } var connection = dataSetWriter.DataSet.DataSetSource.Connection; if (connection.Group == null && options.DisableSessionPerWriterGroup != true) { connection = connection with { Group = writerGroupId }; } if (!connection.Options.HasFlag(ConnectionOptions.UseReverseConnect) && options.DefaultUseReverseConnect == true) { connection = connection with { Options = connection.Options | ConnectionOptions.UseReverseConnect }; } if (!connection.Options.HasFlag(ConnectionOptions.NoComplexTypeSystem) && options.DisableComplexTypeSystem == true) { connection = connection with { Options = connection.Options | ConnectionOptions.NoComplexTypeSystem }; } if (!connection.Options.HasFlag(ConnectionOptions.NoSubscriptionTransfer) && options.DisableSubscriptionTransfer == true) { connection = connection with { Options = connection.Options | ConnectionOptions.NoSubscriptionTransfer }; } return new ConnectionIdentifier(connection); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Extensions/PublishedDataSetSourceModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Azure.IIoT.OpcUa.Publisher.Stack.Models; using System.Collections.Generic; using System.Linq; /// /// Source model extensions /// public static class PublishedDataSetSourceModelEx { /// /// Create subscription /// /// /// /// /// public static SubscriptionModel ToSubscriptionModel( this PublishedDataSetSettingsModel? subscriptionSettings, bool? fetchBrowsePathFromRootOverride, bool? ignoreConfiguredPublishingIntervals) { return new SubscriptionModel { Priority = subscriptionSettings?.Priority, MaxNotificationsPerPublish = subscriptionSettings?.MaxNotificationsPerPublish, LifetimeCount = subscriptionSettings?.LifeTimeCount, KeepAliveCount = subscriptionSettings?.MaxKeepAliveCount, PublishingInterval = ignoreConfiguredPublishingIntervals == true ? null : subscriptionSettings?.PublishingInterval, UseDeferredAcknoledgements = subscriptionSettings?.UseDeferredAcknoledgements, EnableImmediatePublishing = subscriptionSettings?.EnableImmediatePublishing, EnableSequentialPublishing = subscriptionSettings?.EnableSequentialPublishing, RepublishAfterTransfer = subscriptionSettings?.RepublishAfterTransfer, MonitoredItemWatchdogTimeout = subscriptionSettings?.MonitoredItemWatchdogTimeout, WatchdogCondition = subscriptionSettings?.MonitoredItemWatchdogCondition, WatchdogBehavior = subscriptionSettings?.WatchdogBehavior, ResolveBrowsePathFromRoot = fetchBrowsePathFromRootOverride }; } /// /// Convert dataset source to monitored item /// /// /// /// public static IReadOnlyList ToMonitoredItems( this PublishedDataSetSourceModel dataSetSource, NamespaceFormat namespaceFormat) { var monitoredItems = Enumerable.Empty(); if (dataSetSource.PublishedVariables?.PublishedData != null) { monitoredItems = monitoredItems .Concat(dataSetSource.PublishedVariables .ToMonitoredItems(dataSetSource.SubscriptionSettings, namespaceFormat)); } if (dataSetSource.PublishedEvents?.PublishedData != null) { monitoredItems = monitoredItems .Concat(dataSetSource.PublishedEvents .ToMonitoredItems(dataSetSource.SubscriptionSettings, namespaceFormat)); } return monitoredItems.ToList(); } /// /// Convert to monitored items including heartbeat handling. /// /// /// /// /// /// internal static IEnumerable ToMonitoredItems( this PublishedDataItemsModel dataItems, PublishedDataSetSettingsModel? settings, NamespaceFormat namespaceFormat, bool includeTriggering = true) { if (dataItems?.PublishedData != null) { foreach (var publishedData in dataItems.PublishedData) { var item = publishedData?.ToMonitoredItemTemplate(settings, namespaceFormat, includeTriggering); if (item != null) { yield return item; } } } } /// /// Convert to monitored items /// /// /// /// /// /// internal static IEnumerable ToMonitoredItems( this PublishedEventItemsModel eventItems, PublishedDataSetSettingsModel? settings, NamespaceFormat namespaceFormat, bool includeTriggering = true) { if (eventItems?.PublishedData != null) { foreach (var publishedData in eventItems.PublishedData) { var monitoredItem = publishedData?.ToMonitoredItemTemplate(settings, namespaceFormat, includeTriggering); if (monitoredItem == null) { continue; } yield return monitoredItem; } } } /// /// Convert to monitored item /// /// /// /// /// /// internal static BaseMonitoredItemModel? ToMonitoredItemTemplate( this PublishedDataSetEventModel publishedEvent, PublishedDataSetSettingsModel? settings, NamespaceFormat namespaceFormat, bool includeTriggering = true) { if (publishedEvent == null) { return null; } var eventNotifier = publishedEvent.EventNotifier ?? Opc.Ua.ObjectIds.Server.ToString(); if (publishedEvent.ModelChangeHandling != null) { return new MonitoredAddressSpaceModel { DataSetFieldId = publishedEvent.Id ?? eventNotifier, DataSetFieldName = publishedEvent.PublishedEventName ?? string.Empty, FetchDataSetFieldName = publishedEvent.ReadEventNameFromNode ?? settings?.ResolveDisplayName, RebrowsePeriod = publishedEvent.ModelChangeHandling.RebrowseIntervalTimespan, TriggeredItems = includeTriggering ? null : ToMonitoredItems( publishedEvent.Triggering, settings, namespaceFormat), AttributeId = null, DiscardNew = false, MonitoringMode = publishedEvent.MonitoringMode, StartNodeId = eventNotifier, NamespaceFormat = namespaceFormat, RootNodeId = Opc.Ua.ObjectIds.RootFolder.ToString() }; } return new EventMonitoredItemModel { DataSetFieldId = publishedEvent.Id ?? eventNotifier, DataSetFieldName = publishedEvent.PublishedEventName ?? string.Empty, EventFilter = new EventFilterModel { SelectClauses = publishedEvent.SelectedFields? .Select(s => s.Clone()!) .Where(s => s != null) .ToArray(), WhereClause = publishedEvent.Filter?.Clone(), TypeDefinitionId = publishedEvent.TypeDefinitionId }, DiscardNew = publishedEvent.DiscardNew, QueueSize = publishedEvent.QueueSize, AttributeId = null, MonitoringMode = publishedEvent.MonitoringMode, StartNodeId = eventNotifier, RelativePath = publishedEvent.BrowsePath, NamespaceFormat = namespaceFormat, FetchDataSetFieldName = publishedEvent.ReadEventNameFromNode ?? settings?.ResolveDisplayName, TriggeredItems = includeTriggering ? null : ToMonitoredItems( publishedEvent.Triggering, settings, namespaceFormat), ConditionHandling = publishedEvent.ConditionHandling.Clone() }; } /// /// Convert published dataset variable to monitored item /// /// /// /// /// /// internal static DataMonitoredItemModel? ToMonitoredItemTemplate( this PublishedDataSetVariableModel publishedVariable, PublishedDataSetSettingsModel? settings, NamespaceFormat namespaceFormat, bool includeTriggering = true) { if (string.IsNullOrEmpty(publishedVariable.PublishedVariableNodeId)) { return null; } return new DataMonitoredItemModel { DataSetFieldId = publishedVariable.Id ?? publishedVariable.PublishedVariableNodeId, DataSetClassFieldId = publishedVariable.DataSetClassFieldId, DataSetFieldName = publishedVariable.PublishedVariableDisplayName ?? string.Empty, DataChangeFilter = ToDataChangeFilter(publishedVariable), SamplingUsingCyclicRead = publishedVariable.SamplingUsingCyclicRead, CyclicReadMaxAge = publishedVariable.CyclicReadMaxAge, SkipFirst = publishedVariable.SkipFirst, DiscardNew = publishedVariable.DiscardNew, RegisterRead = publishedVariable.RegisterNodeForSampling, StartNodeId = publishedVariable.PublishedVariableNodeId, QueueSize = publishedVariable.ServerQueueSize, RelativePath = publishedVariable.BrowsePath, AttributeId = publishedVariable.Attribute, IndexRange = publishedVariable.IndexRange, MonitoringMode = publishedVariable.MonitoringMode, FetchDataSetFieldName = publishedVariable.ReadDisplayNameFromNode ?? settings?.ResolveDisplayName, SamplingInterval = publishedVariable.SamplingIntervalHint ?? settings?.DefaultSamplingInterval, HeartbeatInterval = publishedVariable.HeartbeatInterval ?? settings?.DefaultHeartbeatInterval, HeartbeatBehavior = publishedVariable.HeartbeatBehavior ?? settings?.DefaultHeartbeatBehavior, AggregateFilter = null, AutoSetQueueSize = null, NamespaceFormat = namespaceFormat, TriggeredItems = includeTriggering ? null : ToMonitoredItems( publishedVariable.Triggering, settings, namespaceFormat) }; } /// /// Convert triggering to monitored items /// /// /// /// /// private static List? ToMonitoredItems( this PublishedDataSetTriggerModel? triggering, PublishedDataSetSettingsModel? settings, NamespaceFormat namespaceFormat) { if (triggering?.PublishedVariables == null && triggering?.PublishedEvents == null) { return null; } var monitoredItems = Enumerable.Empty(); if (triggering.PublishedVariables?.PublishedData != null) { monitoredItems = monitoredItems .Concat(triggering.PublishedVariables .ToMonitoredItems(settings, namespaceFormat, false)); } if (triggering.PublishedEvents?.PublishedData != null) { monitoredItems = monitoredItems .Concat(triggering.PublishedEvents .ToMonitoredItems(settings, namespaceFormat, false)); } return monitoredItems.ToList(); } /// /// Convert to data change filter /// /// /// private static DataChangeFilterModel? ToDataChangeFilter( this PublishedDataSetVariableModel publishedVariable) { if (publishedVariable.DataChangeTrigger == null && publishedVariable.DeadbandType == null && publishedVariable.DeadbandValue == null) { return null; } return new DataChangeFilterModel { DataChangeTrigger = publishedVariable.DataChangeTrigger, DeadbandType = publishedVariable.DeadbandType, DeadbandValue = publishedVariable.DeadbandValue }; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Extensions/RequestHeaderModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Azure.IIoT.OpcUa.Publisher; using Azure.IIoT.OpcUa.Publisher.Parser; using Microsoft.Extensions.Options; using Opc.Ua; using Opc.Ua.Extensions; /// /// Helpers for request header /// public static class RequestHeaderModelEx { /// /// Get namespace format for the response /// /// /// /// public static NamespaceFormat GetNamespaceFormat(this RequestHeaderModel? header, IOptions? options = null) { return header?.NamespaceFormat ?? options?.Value.DefaultNamespaceFormat ?? NamespaceFormat.Uri; } /// /// Convert to string based on request header /// /// /// /// /// /// public static string AsString(this RequestHeaderModel? header, NodeId nodeId, IServiceMessageContext context, IOptions? options = null) { return nodeId.AsString(context, header.GetNamespaceFormat(options)) ?? string.Empty; } /// /// Convert to string based on request header /// /// /// /// /// /// public static string AsString(this RequestHeaderModel? header, ExpandedNodeId nodeId, IServiceMessageContext context, IOptions? options = null) { return nodeId.AsString(context, header.GetNamespaceFormat(options)) ?? string.Empty; } /// /// Convert to string based on request header /// /// /// /// /// /// public static string AsString(this RequestHeaderModel? header, QualifiedName qualifiedName, IServiceMessageContext context, IOptions? options = null) { return qualifiedName.AsString(context, header.GetNamespaceFormat(options)) ?? string.Empty; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/IApiKeyProvider.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { /// /// Provide api key /// public interface IApiKeyProvider { /// /// Api key /// string? ApiKey { get; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/IAssetConfiguration.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Models; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; /// /// Asset configuration services. Manages assets in the configuration /// /// public interface IAssetConfiguration { /// /// Create an asset from the entry and the configuration provided in the Web of /// Things Asset configuration file. The entry in the request object must contain /// a data set name which will be used as the asset name. The writer id can stay /// empty and will be the asset id on successful return. The server must support the /// WoT profile as per . /// The asset will be created and the configuration updated to reference it. A wait /// time can be provided in the request to have the server settle after uploading /// the configuration. /// /// /// /// Task> CreateOrUpdateAssetAsync( PublishedNodeCreateAssetRequestModel request, CancellationToken ct = default); /// /// Get a list of entries representing the assets in the server. This will not touch /// the configuration, it will obtain the list from the server. If the server does not /// support the /// result will be empty. /// /// /// /// /// IAsyncEnumerable> GetAllAssetsAsync( PublishedNodesEntryModel entry, RequestHeaderModel? header = null, CancellationToken ct = default); /// /// Delete the asset referenced by the entry. The entry in the request must contain /// the asset id to delete. The asset id is the data set writer id. /// /// /// /// Task DeleteAssetAsync(PublishedNodeDeleteAssetRequestModel request, CancellationToken ct = default); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/IClientDiagnostics.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Models; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; /// /// Control plane to reset client connections and retrieve /// diagnostics. /// public interface IClientDiagnostics { /// /// Get all active connections /// IReadOnlyList ActiveConnections { get; } /// /// Get diagnostic information of all channels. /// /// IReadOnlyList ChannelDiagnostics { get; } /// /// Reset all connections that are currently running /// /// /// Task ResetAllConnectionsAsync(CancellationToken ct = default); /// /// Watch diagnostic information of all connections. /// /// /// IAsyncEnumerable WatchChannelDiagnosticsAsync( CancellationToken ct = default); /// /// Get connection diagnostics /// /// /// IAsyncEnumerable GetConnectionDiagnosticsAsync( CancellationToken ct = default); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/IConfigurationServices.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Models; using System.Collections.Generic; using System.Threading; /// /// Configuration services using node services to explore and expand /// requests based on the server address space. /// public interface IConfigurationServices { /// /// Expand the provided entry into configuration entries and return them one /// by one with the error items last. The configuration is not updated but /// the resulting entries without error info can be added in a later call to /// the publisher configuration api. /// /// /// /// /// IAsyncEnumerable> ExpandAsync( PublishedNodesEntryModel entry, PublishedNodeExpansionModel request, CancellationToken ct = default); /// /// Create one or more writer entries by expanding the provided entry into the /// configuration. The expanded items are added to the configuration. /// /// /// /// /// IAsyncEnumerable> CreateOrUpdateAsync( PublishedNodesEntryModel entry, PublishedNodeExpansionModel request, CancellationToken ct = default); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/IDiagnosticCollector.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Models; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; /// /// Publisher collector collects metrics from for writer groups /// inside the publisher during runtime. /// public interface IDiagnosticCollector { /// /// Remove writer group from collector /// /// String with the id of the /// writer group or null for the default writer group /// bool RemoveWriterGroup(string writerGroupId); /// /// Reset collector diagnostic info /// /// String with the id of the /// writer group or null for the default writer group void ResetWriterGroup(string writerGroupId); /// /// Try get copy of diagnostics from collector. /// /// String with the id of the /// writer group or null for the default writer group /// /// bool TryGetDiagnosticsForWriterGroup(string writerGroupId, [NotNullWhen(true)] out WriterGroupDiagnosticModel? diagnostic); /// /// Enumerate diagnostics /// /// IEnumerable<(string, WriterGroupDiagnosticModel)> EnumerateDiagnostics(); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/IDiscoveryProgress.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using System; using System.Net; /// /// Discovery progress listener /// public interface IDiscoveryProgress { /// /// Pending requests ahead of this one. /// /// /// void OnDiscoveryPending(DiscoveryRequestModel request, int pending); /// /// Discovery started /// /// void OnDiscoveryStarted(DiscoveryRequestModel request); /// /// Network scanning completed /// /// /// /// /// /// void OnNetScanFinished(DiscoveryRequestModel request, int workers, int progress, int total, int discovered); /// /// Network scanning progress /// /// /// /// /// /// void OnNetScanProgress(DiscoveryRequestModel request, int workers, int progress, int total, int discovered); /// /// Network scanning result /// /// /// /// /// /// /// void OnNetScanResult(DiscoveryRequestModel request, int workers, int progress, int total, int discovered, IPAddress address); /// /// Network scanning started /// /// /// /// /// void OnNetScanStarted(DiscoveryRequestModel request, int workers, int progress, int total); /// /// Port scanning completed /// /// /// /// /// /// void OnPortScanFinished(DiscoveryRequestModel request, int workers, int progress, int total, int discovered); /// /// Port scanning progress /// /// /// /// /// /// void OnPortScanProgress(DiscoveryRequestModel request, int workers, int progress, int total, int discovered); /// /// Port scan result /// /// /// /// /// /// /// void OnPortScanResult(DiscoveryRequestModel request, int workers, int progress, int total, int discovered, IPEndPoint ep); /// /// Port scan started /// /// /// /// /// void OnPortScanStart(DiscoveryRequestModel request, int workers, int progress, int total); /// /// Server discovery started /// /// /// /// /// void OnServerDiscoveryStarted(DiscoveryRequestModel request, int workers, int progress, int total); /// /// Finding endpoints started /// /// /// /// /// /// /// /// void OnFindEndpointsStarted(DiscoveryRequestModel request, int workers, int progress, int total, int discovered, Uri url, IPAddress address); /// /// Finding endpoints completed /// /// /// /// /// /// /// /// /// void OnFindEndpointsFinished(DiscoveryRequestModel request, int workers, int progress, int total, int discovered, Uri url, IPAddress address, int endpoints); /// /// Server discovery complete /// /// /// /// /// /// void OnServerDiscoveryFinished(DiscoveryRequestModel request, int workers, int progress, int total, int discovered); /// /// Discovery cancelled /// /// void OnDiscoveryCancelled(DiscoveryRequestModel request); /// /// Discovery finished successfully /// /// void OnDiscoveryFinished(DiscoveryRequestModel request); /// /// Discovery finished with error /// /// /// void OnDiscoveryError(DiscoveryRequestModel request, Exception ex); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/IDiscoveryServices.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; /// /// Discovery service interface /// public interface IDiscoveryServices { /// /// Discover and return results of discovery run /// /// /// /// /// Task> FindServersAsync( DiscoveryRequestModel request, IDiscoveryProgress? progress = null, CancellationToken ct = default); /// /// Try get unique set of endpoints from all servers found on discovery /// server endpoint url, filtered by optional prioritized locale list. /// /// /// /// /// /// Task> FindEndpointsAsync( Uri discoveryUrl, IReadOnlyList? locales = null, bool findServersOnNetwork = true, CancellationToken ct = default); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/IMessageEncoder.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Furly.Extensions.Messaging; using System; using System.Collections.Generic; /// /// Encoder to encode data set writer messages /// public interface IMessageEncoder { /// /// Encodes the list of notifications into network messages to send /// /// Factory to create empty messages /// Notifications to encode /// Maximum size of messages /// Encode in batch mode IEnumerable<(IEvent Event, Action OnSent)> Encode(Func factory, IEnumerable notifications, int maxMessageSize, bool asBatch); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/IMessageSink.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Stack.Models; /// /// Message sink for a writer group /// public interface IMessageSink { /// /// Subscribe to writer messages /// /// void OnMessage(OpcUaSubscriptionNotification notification); /// /// Called when ValueChangesCount or DataChangesCount are resetted /// void OnCounterReset(); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/INodeServicesInternal.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Opc.Ua; using System; using System.Threading; using System.Threading.Tasks; /// /// Internal node services interface /// /// public interface INodeServicesInternal { /// /// Read node history /// /// /// /// /// /// /// /// /// Task> HistoryReadAsync( T connectionId, HistoryReadRequestModel request, Func decode, Func encode, CancellationToken ct = default) where TInput : class where TOutput : class; /// /// Read node history continuation /// /// /// /// /// /// /// Task> HistoryReadNextAsync( T connectionId, HistoryReadNextRequestModel request, Func encode, CancellationToken ct = default) where TOutput : class; /// /// Update node history /// /// /// /// /// /// /// Task HistoryUpdateAsync( T connectionId, HistoryUpdateRequestModel request, Func> decode, CancellationToken ct = default) where TInput : class; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/IProcessControl.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { /// /// Process control provider /// public interface IProcessControl { /// /// Shutdown publisher /// /// /// false if shutdown failed bool Shutdown(bool failFast); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/IPublishedNodesServices.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Models; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; /// /// Enables remote configuration of the publisher /// public interface IPublishedNodesServices : IPublishServices { /// /// Create a published nodes entry for a specific writer group /// and dataset writer. The entry must specify a unique writer /// group and dataset writer id. If the entry is found it is /// replaced, if it is not found, it is created. If more than /// one entry is found an error is returned. The entry can /// include nodes which will be the initial set. The entries /// must all specify a unique dataSetFieldId. /// /// The entry to create for the writer /// /// Task CreateOrUpdateDataSetWriterEntryAsync( PublishedNodesEntryModel entry, CancellationToken ct = default); /// /// Get the published nodes entry for a specific writer group /// and dataset writer. Dedicated errors are returned if no, /// or no unique entry could be found. THe entry does not /// contain the nodes /// /// The writer group /// The data set writer /// /// Task GetDataSetWriterEntryAsync( string writerGroupId, string dataSetWriterId, CancellationToken ct = default); /// /// Add Nodes to a dedicated data set writer in a writer group. /// Each node must have a unique DataSetFieldId. If the field /// already exists, the node is updated. If a node does not /// have a dataset field id an error is returned. /// /// The writer group /// The data set writer /// Nodes to add or update /// Field after which to /// insert the nodes. If not specified, nodes are added at the /// end of the entry /// /// Task AddOrUpdateNodesAsync(string writerGroupId, string dataSetWriterId, IReadOnlyList nodes, string? insertAfterFieldId = null, CancellationToken ct = default); /// /// Remove Nodes with the data set field ids from a data set /// writer in a writer group. If the field is not found, no /// error is returned. /// /// The writer group /// The data set writer /// Fields to add /// /// Task RemoveNodesAsync(string writerGroupId, string dataSetWriterId, IReadOnlyList dataSetFieldIds, CancellationToken ct = default); /// /// Get Nodes from a data set writer in a writer group. /// /// The writer group /// The data set writer /// the field id after which to start. /// If not specified, nodes from the beginning are returned. /// Number of nodes to return /// /// Task> GetNodesAsync(string writerGroupId, string dataSetWriterId, string? dataSetFieldId = null, int? count = null, CancellationToken ct = default); /// /// Get a node from a data set writer in a writer group. /// /// The writer group /// The data set writer /// the field id after which to start. /// If not specified, nodes from the beginning are returned. /// /// Task GetNodeAsync(string writerGroupId, string dataSetWriterId, string dataSetFieldId, CancellationToken ct = default); /// /// Remove the published nodes entry for a specific data set /// writer in a writer group. Dedicated errors are returned if no, /// or no unique entry could be found. /// /// The writer group /// The data set writer /// Force delete all writers even if more than /// one were found. Does not error when none were found. /// /// Task RemoveDataSetWriterEntryAsync(string writerGroupId, string dataSetWriterId, bool force = false, CancellationToken ct = default); /// /// Add nodes to be published to the configuration /// /// /// Task PublishNodesAsync(PublishedNodesEntryModel request, CancellationToken ct = default); /// /// Remove node from the actual configuration /// /// /// Task UnpublishNodesAsync(PublishedNodesEntryModel request, CancellationToken ct = default); /// /// Resets the configuration for an endpoint /// /// /// Task UnpublishAllNodesAsync(PublishedNodesEntryModel? request = null, CancellationToken ct = default); /// /// Replace all configured endpoints with the new set. /// Using an empty list will remove all entries. /// /// /// Task SetConfiguredEndpointsAsync(IReadOnlyList request, CancellationToken ct = default); /// /// Update nodes of endpoints in the published nodes configuration. /// /// /// Task AddOrUpdateEndpointsAsync(IReadOnlyList request, CancellationToken ct = default); /// /// returns the endpoints currently part of the configuration /// /// /// Task> GetConfiguredEndpointsAsync( bool includeNodes = false, CancellationToken ct = default); /// /// Get the configuration nodes for an endpoint /// /// /// Task> GetConfiguredNodesOnEndpointAsync( PublishedNodesEntryModel request, CancellationToken ct = default); /// /// Gets the diagnostic information for a specific endpoint /// /// Task> GetDiagnosticInfoAsync( CancellationToken ct = default); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/IPublisher.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Threading.Tasks; /// /// Publisher /// public interface IPublisher { /// /// Current version number of the configuration /// uint Version { get; } /// /// Last change time /// DateTimeOffset LastChange { get; } /// /// Gets a snapshot of the list of writer groups in publisher. /// ImmutableList WriterGroups { get; } /// /// Try update configuration /// /// /// bool TryUpdate(IEnumerable writerGroups); /// /// Update configuration /// /// /// Task UpdateAsync(IEnumerable writerGroups); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/IRuntimeStateReporter.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using System.Threading; using System.Threading.Tasks; /// /// Interface for runtime state reporting. /// public interface IRuntimeStateReporter { /// /// Send restart announcement. /// /// /// ValueTask SendRestartAnnouncementAsync(CancellationToken ct = default); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/ISslCertProvider.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using System.Security.Cryptography.X509Certificates; /// /// Ssl certificate provider /// public interface ISslCertProvider { /// /// Certificate /// X509Certificate2? Certificate { get; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/IStorageProvider.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using System; using System.IO; /// /// Interface for utilities provider for published nodes file. /// public interface IStorageProvider { /// /// Occurs when published nodes file is changed. /// event EventHandler Changed; /// /// Get last write time of published nodes file. /// DateTime GetLastWriteTime(); /// /// Read content of published nodes file as string. /// string ReadContent(); /// /// Write new content to published nodes file /// /// Content to be written. /// If set FileSystemWatcher /// notifications will be disabled while updating the file. void WriteContent(string content, bool disableRaisingEvents = false); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/IWriterGroupControl.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Models; using System.Threading; using System.Threading.Tasks; /// /// Writer group controller /// public interface IWriterGroupControl { /// /// Start group /// /// /// ValueTask StartAsync(CancellationToken ct); /// /// Update group /// /// /// /// ValueTask UpdateAsync(WriterGroupModel writerGroup, CancellationToken ct); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/IWriterGroupDiagnostics.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { /// /// Writer group diagnostics control /// public interface IWriterGroupDiagnostics { /// /// Reset diagnostics for writer group /// void ResetWriterGroupDiagnostics(); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/IWriterGroupScope.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using System; /// /// Writer group scope /// public interface IWriterGroupScope : IDisposable { /// /// Resolve writer group /// IWriterGroupControl WriterGroup { get; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/IWriterGroupScopeFactory.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Models; /// /// Creates writer group scopes /// public interface IWriterGroupScopeFactory { /// /// Create a writer group container containing everything /// needed to resolve the writer group processing engine. /// /// /// IWriterGroupScope Create(WriterGroupModel writerGroup); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Models/AssetDeviceConfiguration.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Collections.Generic; using System.Runtime.Serialization; /// /// Base data set and event model /// public abstract record class DataSetEventConfiguration { /// /// The encoding format to use for messages. Allowed values /// include: /// - Avro: Avro binary encoding /// - Json: Standard JSON encoding /// [DataMember(Name = "messageEncoding", Order = 1, EmitDefaultValue = false)] public MessageEncoding? MessageEncoding { get; set; } /// /// Priority of the writer subscription. /// [DataMember(Name = "priority", Order = 2, EmitDefaultValue = false)] public byte? Priority { get; set; } /// /// The optional dataset class id as it shall appear in dataset /// messages and dataset metadata. Used to uniquely identify the /// type of dataset being published. Default: Guid.Empty /// [DataMember(Name = "dataSetClassId", Order = 3, EmitDefaultValue = false)] public Guid DataSetClassId { get; set; } /// /// Adapt the sampling interval property /// [DataMember(Name = "samplingInterval", Order = 4, EmitDefaultValue = false)] public int? SamplingInterval { get; set; } /// /// Adapt the publishing interval property /// [DataMember(Name = "publishingInterval", Order = 5, EmitDefaultValue = false)] public int? PublishingInterval { get; set; } /// /// Adapt the key frame count property /// [DataMember(Name = "keyFrameCount", Order = 6, EmitDefaultValue = false)] public uint? KeyFrameCount { get; set; } /// /// Defines how many publishing timer expirations to wait /// before sending a keep-alive message when no notifications /// are pending. Works with SendKeepAliveDataSetMessages to /// maintain connection awareness. Keep-alive messages help /// detect connection issues even when no data changes are /// occurring. /// [DataMember(Name = "maxKeepAliveCount", Order = 7, EmitDefaultValue = false)] public uint? MaxKeepAliveCount { get; set; } /// /// Controls whether to send keep alive messages for this /// dataset when a subscription keep alive notification is /// received. Keep alive messages help maintain connection /// status awareness. Only valid if the messaging mode supports /// keep alive messages. Default: false /// [DataMember(Name = "sendKeepAliveDataSetMessages", Order = 8, EmitDefaultValue = false)] public bool? SendKeepAliveDataSetMessages { get; set; } /// /// When sending of keep alive messages is enabled, this /// flag controls whether the keep alive messages are sent /// as key frames. Key frames contain all current values. /// [DataMember(Name = "sendKeepAliveAsKeyFrameMessages", Order = 9, EmitDefaultValue = false)] public bool? SendKeepAliveAsKeyFrameMessages { get; set; } /// /// Defines what action to take when the watchdog timer /// triggers. Available behaviors: /// - Diagnostic: Log the event only /// - Reset: Reset the subscription /// - FailFast: Terminate the connection /// - ExitProcess: Shut down the publisher /// [DataMember(Name = "dataSetWriterWatchdogBehavior", Order = 10, EmitDefaultValue = false)] public SubscriptionWatchdogBehavior? DataSetWriterWatchdogBehavior { get; set; } /// /// Specifies the condition that triggers the watchdog /// behavior. Options: /// - WhenAnyAreLate: Execute when any monitored item is late /// (default) /// - WhenAllAreLate: Execute only when all items are late /// [DataMember(Name = "opcNodeWatchdogCondition", Order = 11, EmitDefaultValue = false)] public MonitoredItemWatchdogCondition? OpcNodeWatchdogCondition { get; set; } /// /// The timeout duration used to monitor whether monitored /// items in the subscription are continuously reporting fresh /// data. This watchdog mechanism helps detect stale data or /// connectivity issues. When this timeout expires, the /// configured DataSetWriterWatchdogBehavior is triggered based /// on OpcNodeWatchdogCondition. Expressed as a TimeSpan value. /// [DataMember(Name = "opcNodeWatchdogTimespan", Order = 12, EmitDefaultValue = false)] public TimeSpan? OpcNodeWatchdogTimespan { get; set; } /// /// Controls whether to republish missed values after a /// subscription is transferred during reconnect handling. Only /// applies when DisableSubscriptionTransfer is false. Helps /// ensure no data is lost during connection interruptions. /// Default: true /// [DataMember(Name = "republishAfterTransfer", Order = 13, EmitDefaultValue = false)] public bool? RepublishAfterTransfer { get; set; } } /// /// Dataset reource additional configuration model. /// [DataContract] public sealed record class DataSetConfiguration : DataSetEventConfiguration; /// /// Dataset Data point additional configuration model /// [DataContract] public sealed record class DataSetDataPointConfiguration : OpcNodeModel { /// /// Adapt the sampling interval property /// [DataMember(Name = "samplingInterval", Order = 100, EmitDefaultValue = false)] public int? SamplingInterval { get => OpcSamplingInterval; set => OpcSamplingInterval = value; } /// /// Adapt the publishing interval property /// [DataMember(Name = "publishingInterval", Order = 101, EmitDefaultValue = false)] public int? PublishingInterval { get => OpcPublishingInterval; set => OpcPublishingInterval = value; } } /// /// EventGroup reource additional configuration model. /// [DataContract] public sealed record class EventGroupConfiguration : DataSetEventConfiguration; /// /// Management group reource additional configuration model. /// [DataContract] public sealed record class ManagementGroupConfiguration { /// /// The encoding format to use for messages. Allowed values /// include: /// - Avro: Avro binary encoding /// - Json: Standard JSON encoding /// [DataMember(Name = "messageEncoding", Order = 1, EmitDefaultValue = false)] public MessageEncoding? MessageEncoding { get; set; } /// /// Priority of the writer subscription. /// [DataMember(Name = "priority", Order = 2, EmitDefaultValue = false)] public byte? Priority { get; set; } /// /// The optional dataset class id as it shall appear in dataset /// messages and dataset metadata. Used to uniquely identify the /// type of dataset being published. Default: Guid.Empty /// [DataMember(Name = "dataSetClassId", Order = 3, EmitDefaultValue = false)] public Guid DataSetClassId { get; set; } } /// /// Management group action reource additional configuration model. /// [DataContract] public sealed record class ActionConfiguration { /// /// Compiled method metadata /// [DataMember(Name = "_io", Order = 0, EmitDefaultValue = false)] public required byte[] CompiledMetadata { get; set; } } /// /// Event reource additional configuration model. /// [DataContract] public sealed record class EventConfiguration : DataSetEventConfiguration { /// /// Size of the server-side queue for this monitored item. /// Controls how many values can be buffered during slow /// connections. Values are discarded according to DiscardNew /// when queue is full. Default is 1 unless otherwise /// configured. Larger queues help prevent data loss but use /// more server memory. /// [DataMember(Name = "queueSize", Order = 105, EmitDefaultValue = false)] public uint? QueueSize { get; set; } /// /// Controls queue overflow behavior for monitored items. /// True: Discard newest values when queue is full (LIFO). /// False: Discard oldest values when queue is full (FIFO, /// default). Use True to preserve historical data during /// connection issues. Use False to maintain current value /// accuracy. /// [DataMember(Name = "discardNew", Order = 106, EmitDefaultValue = false)] public bool? DiscardNew { get; set; } /// /// Event Filter to apply. When specified the node is assmed /// to be an event notifier node to subscribe to. /// [DataMember(Name = "eventFilter", Order = 107, EmitDefaultValue = false)] public EventFilterModel? EventFilter { get; set; } /// /// Settings for pending condition handling /// [DataMember(Name = "conditionHandling", Order = 108, EmitDefaultValue = false)] public ConditionHandlingOptionsModel? ConditionHandling { get; set; } /// /// Controls handling of initial value notification. True: /// Suppress first value from monitored item. False: Publish /// initial value (default). Useful when only changes are /// relevant. Server always sends initial value on creation. /// [DataMember(Name = "skipFirst", Order = 109, EmitDefaultValue = false)] public bool? SkipFirst { get; set; } } /// /// Event data point configuration /// [DataContract] public sealed record class EventDataPointConfiguration : SimpleAttributeOperandModel; /// /// Endpoint additional configuration for devices. Property names are /// the same as in but this /// configuration is used when parsing device endpoint configuration /// from a ADR device resource. /// [DataContract] public sealed record class DeviceEndpointConfiguration { /// /// The specific security mode to use for the specified endpoint. /// If the security mode is not available with any configured /// security policy connectivity will fail. Default: /// /// [DataMember(Name = "endpointSecurityMode", Order = 0, EmitDefaultValue = false)] public SecurityMode? EndpointSecurityMode { get; set; } /// /// The security policy URI to use for the endpoint connection. /// Overrides UseSecurity setting and refines /// EndpointSecurityMode choice. Examples include /// "http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256". /// If the specified policy is not available with the chosen /// security mode, connectivity will fail. This allows enforcing /// specific security requirements. /// [DataMember(Name = "endpointSecurityPolicy", Order = 1, EmitDefaultValue = false)] public string? EndpointSecurityPolicy { get; set; } /// /// Use reverse connect to connect ot the endpoint /// [DataMember(Name = "useReverseConnect", Order = 2, EmitDefaultValue = false)] public bool? UseReverseConnect { get; set; } /// /// Specifies the authentication mode for connecting to the OPC /// UA server. Supported modes: /// - Anonymous: No authentication (default) /// - UsernamePassword: Username and password authentication /// - Certificate: Certificate-based authentication using X.509 /// certificates /// When using credentials or certificates, encrypted /// communication should be enabled via UseSecurity or /// EndpointSecurityMode to protect secrets. For certificate /// auth, the certificate must be in the User certificate /// store. /// [DataMember(Name = "opcAuthenticationMode", Order = 4)] public OpcAuthenticationMode OpcAuthenticationMode { get; set; } /// /// The plaintext username for UsernamePassword authentication, /// or the subject name of the certificate for Certificate /// authentication. When using Certificate mode, this refers to /// a certificate in the User certificate store of the PKI /// configuration. /// [DataMember(Name = "opcAuthenticationUsername", Order = 5, EmitDefaultValue = false)] public string? OpcAuthenticationUsername { get; set; } /// /// The plaintext password for UsernamePassword authentication, /// or the password protecting the private key for Certificate /// authentication. For Certificate mode, this must match the /// password used when adding the certificate to the PKI store. /// [DataMember(Name = "opcAuthenticationPassword", Order = 6, EmitDefaultValue = false)] public string? OpcAuthenticationPassword { get; set; } /// /// Enables detailed server diagnostics logging for the /// connection. When enabled, provides additional diagnostic /// information useful for troubleshooting connectivity, /// authentication, and subscription issues. The diagnostics /// data is included in the publisher's logs. Default: false /// [DataMember(Name = "dumpConnectionDiagnostics", Order = 10, EmitDefaultValue = false)] public bool? DumpConnectionDiagnostics { get; set; } /// /// Controls whether subscription transfer is disabled during /// reconnect. When false (default), attempts to transfer /// subscriptions on reconnect to maintain data continuity. Set /// to true to fix interoperability issues with servers that /// don't support subscription transfer. Can be configured /// globally via command line options. /// [DataMember(Name = "disableSubscriptionTransfer", Order = 11, EmitDefaultValue = false)] public bool? DisableSubscriptionTransfer { get; set; } /// /// Runs asset discovery on the endpoint /// [DataMember(Name = "runAssetDiscovery", Order = 13, EmitDefaultValue = false)] public bool? RunAssetDiscovery { get; set; } /// /// Finds assets for the selected types. /// [DataMember(Name = "assetTypes", Order = 14, EmitDefaultValue = false)] public IReadOnlyList? AssetTypes { get; set; } /// /// Source of this endpoint configuration /// [DataMember(Name = "source", Order = 15, EmitDefaultValue = false)] public string? Source { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Models/DataSetWriterContext.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Furly.Extensions.Messaging; using System; using System.Collections.Generic; /// /// Context to add to notification to convey data required for /// data set messages emitted by writer in a writer group. /// public record class DataSetWriterContext { /// /// The allocated identifier of the writer /// public required ushort DataSetWriterId { get; init; } /// /// Topic for the message /// public required string Topic { get; init; } /// /// Requested qos /// public required QoS? Qos { get; init; } /// /// Requested Retain /// public bool? Retain { get; init; } /// /// Requested Time to live /// public TimeSpan? Ttl { get; init; } /// /// Publisher id /// public required string PublisherId { get; init; } /// /// Dataset writer model reference /// public required DataSetWriterModel Writer { get; init; } /// /// Dataset writer name unique in the context of the group /// public required string WriterName { get; init; } /// /// Metadata for the dataset /// public required PublishedDataSetMessageSchemaModel? MetaData { get; init; } /// /// Extension fields /// public required IReadOnlyList<(string, Opc.Ua.DataValue?)> ExtensionFields { get; init; } /// /// Sequence number inside the writer /// public required Func NextWriterSequenceNumber { get; init; } /// /// Writer group model reference /// public required WriterGroupModel WriterGroup { get; init; } /// /// The applicable network message schema /// public required IEventSchema? Schema { get; init; } /// /// The cloud event header /// public required CloudEventHeader? CloudEvent { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Models/DiscoveryRequest.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Azure.IIoT.OpcUa.Publisher.Discovery; using Azure.IIoT.OpcUa.Publisher.Stack.Transport; using Azure.IIoT.OpcUa.Publisher.Stack.Transport.Models; using Furly.Extensions.Utils; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Threading; /// /// Discovery request wrapper /// internal sealed class DiscoveryRequest : IDisposable { /// /// Cancellation token to cancel request /// public CancellationToken Token => _cts.Token; /// /// Request is a scan request /// public bool IsScan { get; } /// /// Progress reporter /// public IDiscoveryProgress Progress { get; } /// /// Original discovery request model /// public DiscoveryRequestModel Request { get; } /// /// Network class /// public NetworkClass NetworkClass { get; } /// /// Address ranges to use or null to use from network info /// public IEnumerable? AddressRanges { get; } /// /// Total addresses to be scanned /// public int TotalAddresses { get; } /// /// Port ranges to use if not from discovery mode /// public IEnumerable? PortRanges { get; } /// /// Total ports to be scanned /// public int TotalPorts { get; } /// /// Discovery mode /// public DiscoveryMode Mode => Request.Discovery ?? DiscoveryMode.Off; /// /// Discovery configuration /// public DiscoveryConfigModel Configuration => Request.Configuration ?? new DiscoveryConfigModel(); /// /// Discovery urls /// public IEnumerable DiscoveryUrls => Configuration.DiscoveryUrls?.Select(s => new Uri(s)) ?? []; /// /// Create request wrapper /// /// /// public DiscoveryRequest(IDiscoveryProgress progress, TimeProvider timeProvider) : this(null, null, progress, timeProvider) { } /// /// Create request wrapper /// /// /// /// /// public DiscoveryRequest(DiscoveryMode? mode, DiscoveryConfigModel? configuration, IDiscoveryProgress progress, TimeProvider timeProvider) : this(new DiscoveryRequestModel { Id = string.Empty, Configuration = configuration.Clone(), Context = null, Discovery = mode }, progress, timeProvider, NetworkClass.Wired, true) { } /// /// Create request wrapper /// /// /// /// /// /// /// public DiscoveryRequest(DiscoveryRequestModel request, IDiscoveryProgress progress, TimeProvider timeProvider, NetworkClass networkClass = NetworkClass.Wired, bool isScan = false, CancellationToken cancellationToken = default) { _timeProvider = timeProvider; Progress = progress; Request = request?.Clone(_timeProvider) ?? throw new ArgumentNullException(nameof(request)); _cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); NetworkClass = networkClass; IsScan = isScan; if (Request.Configuration == null) { Request.Configuration = new DiscoveryConfigModel(); } if (Request.Discovery == null || Request.Discovery == DiscoveryMode.Off) { // Report empty configuration if off, but keep the // discovery urls details from the original request Request.Configuration = new DiscoveryConfigModel() { DiscoveryUrls = Request.Configuration.DiscoveryUrls?.ToList(), Locales = Request.Configuration.Locales?.ToList() }; Request.Discovery = DiscoveryMode.Off; return; } // Parse whatever provided if (!string.IsNullOrEmpty(Request.Configuration.PortRangesToScan) && PortRange.TryParse(Request.Configuration.PortRangesToScan, out var ports)) { PortRanges = ports; Request.Discovery = DiscoveryMode.Fast; } if (!string.IsNullOrEmpty(Request.Configuration.AddressRangesToScan) && AddressRange.TryParse(Request.Configuration.AddressRangesToScan, out var addresses)) { AddressRanges = addresses; Request.Discovery = DiscoveryMode.Fast; } // Set default ranges if (AddressRanges == null) { IEnumerable interfaces; switch (Request.Discovery) { case DiscoveryMode.Local: interfaces = NetworkInformationEx.GetAllNetInterfaces(NetworkClass); AddressRanges = AddLocalHost(interfaces .Select(t => new AddressRange(t, true))) .Distinct(); break; case DiscoveryMode.Fast: interfaces = NetworkInformationEx.GetAllNetInterfaces(NetworkClass.Wired); AddressRanges = AddLocalHost(interfaces .Select(t => new AddressRange(t, false, 24)) .Concat(interfaces .Where(t => t.Gateway?.Equals(IPAddress.Any) == false && !t.Gateway.Equals(IPAddress.None)) .Select(i => new AddressRange(i.Gateway!, 32))) .Distinct()); break; case DiscoveryMode.Network: case DiscoveryMode.Scan: interfaces = NetworkInformationEx.GetAllNetInterfaces(NetworkClass); AddressRanges = AddLocalHost(interfaces .Select(t => new AddressRange(t, false)) .Concat(interfaces .Where(t => t.Gateway?.Equals(IPAddress.Any) == false && !t.Gateway.Equals(IPAddress.None)) .Select(i => new AddressRange(i.Gateway!, 32))) .Distinct()); break; default: AddressRanges = []; break; } } if (PortRanges == null) { switch (Request.Discovery) { case DiscoveryMode.Local: PortRanges = PortRange.All; break; case DiscoveryMode.Fast: PortRanges = PortRange.WellKnown; break; case DiscoveryMode.Scan: PortRanges = PortRange.Unassigned; break; case DiscoveryMode.Network: PortRanges = PortRange.OpcUa; break; default: PortRanges = []; break; } } // Update reported configuration with used settings if (AddressRanges?.Any() == true) { Request.Configuration.AddressRangesToScan = AddressRange.Format(AddressRanges); TotalAddresses = AddressRanges?.Sum(r => r.Count) ?? 0; } if (PortRanges?.Any() == true) { Request.Configuration.PortRangesToScan = PortRange.Format(PortRanges); TotalPorts = PortRanges?.Sum(r => r.Count) ?? 0; } Request.Configuration.IdleTimeBetweenScans ??= kDefaultIdleTime; Request.Configuration.PortProbeTimeout ??= kDefaultPortProbeTimeout; Request.Configuration.NetworkProbeTimeout ??= kDefaultNetworkProbeTimeout; } /// /// Create request wrapper /// /// private DiscoveryRequest(DiscoveryRequest request) : this(request.Request, request.Progress, request._timeProvider, request.NetworkClass, request.IsScan) { } /// /// Cancel request /// public void Cancel() { Try.Op(_cts.Cancel); } /// public void Dispose() { _cts.Dispose(); } /// /// Clone options /// /// internal DiscoveryRequest Clone() { return new DiscoveryRequest(this); } /// /// Add hosta address as fake address range /// /// /// public static IEnumerable AddLocalHost(IEnumerable ranges) { if (NetworkDiscovery.IsContainer) { try { var addresses = Dns.GetHostAddresses("host.docker.internal"); var listedRanges = ranges.ToList(); return listedRanges.Concat(addresses // Select ip4 addresses only .Where(a => a.AddressFamily == AddressFamily.InterNetwork) .Select(a => new IPv4Address(a)) // Check we do not already have them in the existing ranges .Where(a => !listedRanges .Any(r => a >= r.Low && a <= r.High)) // Select either the local or a small subnet around it .Select(a => new AddressRange(a, 32, "localhost"))); } catch { } } return ranges; } /// Default idle time is 6 hours private static readonly TimeSpan kDefaultIdleTime = TimeSpan.FromHours(6); /// Default port probe timeout is 5 seconds private static readonly TimeSpan kDefaultPortProbeTimeout = TimeSpan.FromSeconds(5); /// Default icmp timeout is 3 seconds private static readonly TimeSpan kDefaultNetworkProbeTimeout = TimeSpan.FromSeconds(3); private readonly TimeProvider _timeProvider; private readonly CancellationTokenSource _cts; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Models/MessagingProfile.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Azure.IIoT.OpcUa.Publisher.Stack; using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; /// /// Messaging profiles supported by OPC Publisher /// public sealed class MessagingProfile { /// /// Messaging mode /// public MessagingMode MessagingMode { get; } /// /// Returns true if messaging profiles supports metadata /// public bool SupportsMetadata { get { switch (MessagingMode) { case MessagingMode.FullSamples: case MessagingMode.Samples: case MessagingMode.RawDataSets: return false; default: return true; } } } /// /// Returns true if messaging profiles supports keyframes /// public bool SupportsKeyFrames { get { switch (MessagingMode) { case MessagingMode.FullSamples: case MessagingMode.Samples: return false; default: return true; } } } /// /// Returns true if messaging profiles supports keep alive /// public bool SupportsKeepAlive { get { switch (MessagingMode) { case MessagingMode.FullSamples: case MessagingMode.Samples: return false; default: return true; } } } /// /// Messaging encoding /// public MessageEncoding MessageEncoding { get; } /// /// Dataset message content mask /// public DataSetMessageContentFlags DataSetMessageContentMask { get; } /// /// Network message content mask /// public NetworkMessageContentFlags NetworkMessageContentMask { get; } /// /// Content mask for data set message field /// public DataSetFieldContentFlags DataSetFieldContentMask { get; } /// /// Get supported options /// public static IEnumerable Supported => kProfiles.Values; /// /// Get encoding /// /// /// /// public static MessagingProfile Get(MessagingMode messageMode, MessageEncoding encoding) { var key = (messageMode, GetMessageEncoding(encoding)); return kProfiles[key]; } /// /// Find profile /// /// /// /// /// /// public static MessagingProfile? Find(MessageEncoding? messageType, NetworkMessageContentFlags? networkMessageContentMask, DataSetMessageContentFlags? dataSetMessageContentMask, DataSetFieldContentFlags? dataSetFieldContentMask) { // TODO: Use hash code from custom messaging profile? return kProfiles.Values .FirstOrDefault(p => (messageType == null || p.MessageEncoding == messageType) && (networkMessageContentMask == null || p.NetworkMessageContentMask == networkMessageContentMask) && (dataSetMessageContentMask == null || p.DataSetMessageContentMask == dataSetMessageContentMask) && (dataSetFieldContentMask == null || p.DataSetFieldContentMask == dataSetFieldContentMask)) ; } /// /// Is this configuration supported /// /// /// /// public static bool IsSupported(MessagingMode messageMode, MessageEncoding encoding) { var key = (messageMode, GetMessageEncoding(encoding)); return kProfiles.ContainsKey(key); } /// /// Create message encoding profile /// /// /// /// /// /// private MessagingProfile(MessagingMode messagingMode, MessageEncoding messageEncoding, DataSetMessageContentFlags dataSetMessageContentMask, NetworkMessageContentFlags networkMessageContentMask, DataSetFieldContentFlags dataSetFieldContentMask) { MessagingMode = messagingMode; MessageEncoding = messageEncoding; DataSetMessageContentMask = dataSetMessageContentMask; NetworkMessageContentMask = networkMessageContentMask; DataSetFieldContentMask = dataSetFieldContentMask; } /// public override bool Equals(object? obj) { return obj is MessagingProfile profile && DataSetMessageContentMask == profile.DataSetMessageContentMask && NetworkMessageContentMask == profile.NetworkMessageContentMask && DataSetFieldContentMask == profile.DataSetFieldContentMask; } /// public override int GetHashCode() { return HashCode.Combine( DataSetMessageContentMask, NetworkMessageContentMask, DataSetFieldContentMask); } /// public override string ToString() { return $"{MessagingMode}|{MessageEncoding}"; } /// public string ToExpandedString() { return new StringBuilder("| ") .Append(MessagingMode) .Append(" | ") .Append(MessageEncoding) .Append(" | ") .Append(NetworkMessageContentMask) .Append("
(") .AppendFormat(CultureInfo.InvariantCulture, "0x{0:X}", StackTypesEx.ToStackType( NetworkMessageContentMask, MessageEncoding)) .Append(") | ") .Append(DataSetMessageContentMask) .Append("
(") .AppendFormat(CultureInfo.InvariantCulture, "0x{0:X}", StackTypesEx.ToStackType( DataSetMessageContentMask, DataSetFieldContentMask, MessageEncoding)) .Append(") | ") .Append(DataSetFieldContentMask) .Append("
(") .AppendFormat(CultureInfo.InvariantCulture, "0x{0:X}", (uint)StackTypesEx.ToStackType( DataSetFieldContentMask)) .Append(") | ") .Append(SupportsMetadata ? "X" : " ") .Append(" | ") .Append(SupportsKeyFrames ? "X" : " ") .Append(" | ") .Append(SupportsKeepAlive ? "X" : " ") .AppendLine(" |") .ToString(); } static MessagingProfile() { // // New message profiles supported in 2.5 // // Sample mode AddProfile(MessagingMode.Samples, BuildDataSetContentMask(false, false, true), BuildNetworkMessageContentMask(true), BuildDataSetFieldContentMask(false, true), MessageEncoding.Json); AddProfile(MessagingMode.FullSamples, BuildDataSetContentMask(true, false, true), BuildNetworkMessageContentMask(true), BuildDataSetFieldContentMask(true, true), MessageEncoding.Json); // // New message profiles supported in 2.6 // // Pub sub AddProfile(MessagingMode.PubSub, BuildDataSetContentMask(), BuildNetworkMessageContentMask(), BuildDataSetFieldContentMask(), MessageEncoding.Json); AddProfile(MessagingMode.FullNetworkMessages, BuildDataSetContentMask(true), BuildNetworkMessageContentMask(), BuildDataSetFieldContentMask(true), MessageEncoding.Json); // // New message profiles supported in 2.9 // // Pub sub gzipped AddProfile(MessagingMode.PubSub, BuildDataSetContentMask(), BuildNetworkMessageContentMask(), BuildDataSetFieldContentMask(), MessageEncoding.JsonGzip); AddProfile(MessagingMode.FullNetworkMessages, BuildDataSetContentMask(true), BuildNetworkMessageContentMask(), BuildDataSetFieldContentMask(true), MessageEncoding.JsonGzip); // Reversible encodings AddProfile(MessagingMode.PubSub, BuildDataSetContentMask(false, true), BuildNetworkMessageContentMask(), BuildDataSetFieldContentMask(), MessageEncoding.JsonReversible, MessageEncoding.JsonReversibleGzip); AddProfile(MessagingMode.FullNetworkMessages, BuildDataSetContentMask(true, true), BuildNetworkMessageContentMask(), BuildDataSetFieldContentMask(true), MessageEncoding.JsonReversible, MessageEncoding.JsonReversibleGzip); AddProfile(MessagingMode.Samples, BuildDataSetContentMask(false, true, true), BuildNetworkMessageContentMask(true), BuildDataSetFieldContentMask(false, true), MessageEncoding.JsonReversible, MessageEncoding.JsonReversibleGzip); AddProfile(MessagingMode.FullSamples, BuildDataSetContentMask(true, true, true), BuildNetworkMessageContentMask(true), BuildDataSetFieldContentMask(true, true), MessageEncoding.JsonReversible, MessageEncoding.JsonReversibleGzip); // Without network message header AddProfile(MessagingMode.DataSetMessages, BuildDataSetContentMask(), NetworkMessageContentFlags.DataSetMessageHeader, BuildDataSetFieldContentMask(), MessageEncoding.Json, MessageEncoding.JsonGzip); AddProfile(MessagingMode.DataSetMessages, BuildDataSetContentMask(false, true), NetworkMessageContentFlags.DataSetMessageHeader, BuildDataSetFieldContentMask(), MessageEncoding.JsonReversible, MessageEncoding.JsonReversibleGzip); AddProfile(MessagingMode.SingleDataSetMessage, BuildDataSetContentMask(), NetworkMessageContentFlags.DataSetMessageHeader | NetworkMessageContentFlags.SingleDataSetMessage, BuildDataSetFieldContentMask(), MessageEncoding.Json, MessageEncoding.JsonGzip); AddProfile(MessagingMode.SingleDataSetMessage, BuildDataSetContentMask(false, true), NetworkMessageContentFlags.DataSetMessageHeader | NetworkMessageContentFlags.SingleDataSetMessage, BuildDataSetFieldContentMask(), MessageEncoding.JsonReversible, MessageEncoding.JsonReversibleGzip); AddProfile(MessagingMode.DataSets, 0, 0, BuildDataSetFieldContentMask(), MessageEncoding.Json, MessageEncoding.JsonGzip); AddProfile(MessagingMode.SingleDataSet, 0, NetworkMessageContentFlags.SingleDataSetMessage, BuildDataSetFieldContentMask(), MessageEncoding.Json, MessageEncoding.JsonGzip); AddProfile(MessagingMode.DataSets, 0, 0, BuildDataSetFieldContentMask(), MessageEncoding.JsonReversible, MessageEncoding.JsonReversibleGzip); AddProfile(MessagingMode.SingleDataSet, 0, NetworkMessageContentFlags.SingleDataSetMessage, BuildDataSetFieldContentMask(), MessageEncoding.JsonReversible, MessageEncoding.JsonReversibleGzip); AddProfile(MessagingMode.RawDataSets, 0, 0, DataSetFieldContentFlags.RawData, MessageEncoding.Json, MessageEncoding.JsonGzip); AddProfile(MessagingMode.SingleRawDataSet, 0, NetworkMessageContentFlags.SingleDataSetMessage, DataSetFieldContentFlags.RawData, MessageEncoding.Json, MessageEncoding.JsonGzip); AddProfile(MessagingMode.RawDataSets, 0, 0, DataSetFieldContentFlags.RawData, MessageEncoding.JsonReversible, MessageEncoding.JsonReversibleGzip); AddProfile(MessagingMode.SingleRawDataSet, 0, NetworkMessageContentFlags.SingleDataSetMessage, DataSetFieldContentFlags.RawData, MessageEncoding.JsonReversible, MessageEncoding.JsonReversibleGzip); // Uadp encoding AddProfile(MessagingMode.PubSub, BuildDataSetContentMask(), BuildNetworkMessageContentMask(), BuildDataSetFieldContentMask(), MessageEncoding.Uadp); AddProfile(MessagingMode.FullNetworkMessages, BuildDataSetContentMask(true), BuildNetworkMessageContentMask(), BuildDataSetFieldContentMask(), MessageEncoding.Uadp); AddProfile(MessagingMode.DataSetMessages, BuildDataSetContentMask(), NetworkMessageContentFlags.DataSetMessageHeader, BuildDataSetFieldContentMask(), MessageEncoding.Uadp); AddProfile(MessagingMode.SingleDataSetMessage, BuildDataSetContentMask(), NetworkMessageContentFlags.DataSetMessageHeader | NetworkMessageContentFlags.SingleDataSetMessage, BuildDataSetFieldContentMask(), MessageEncoding.Uadp); AddProfile(MessagingMode.RawDataSets, 0, 0, DataSetFieldContentFlags.RawData, MessageEncoding.Uadp); AddProfile(MessagingMode.SingleRawDataSet, 0, NetworkMessageContentFlags.SingleDataSetMessage, DataSetFieldContentFlags.RawData, MessageEncoding.Uadp); } /// /// Get a markdown compatible string of all message profiles /// /// public static string GetAllAsMarkdownTable() { var builder = new StringBuilder(); builder.Append( @"| Messaging Mode
(--mm) | Message Encoding
(--me) | NetworkMessageContentMask | DataSetMessageContentMask | DataSetFieldContentMask | Metadata supported | KeyFrames supported | KeepAlive supported | Schema publishing | |--------------------------|----------------------------|---------------------------|---------------------------|-------------------------|--------------------|---------------------|---------------------|-------------------| "); foreach (var profile in kProfiles) { builder.Append(profile.Value.ToExpandedString()); } return builder.ToString(); } /// /// Massage the message encoding /// /// /// private static MessageEncoding GetMessageEncoding(MessageEncoding encoding) { if (encoding == 0) { return MessageEncoding.Json; } return encoding; } private static void AddProfile(MessagingMode messagingMode, DataSetMessageContentFlags dataSetMessageContentMask, NetworkMessageContentFlags networkMessageContentMask, DataSetFieldContentFlags dataSetFieldContentMask, params MessageEncoding[] messageEncoding) { foreach (var encoding in messageEncoding) { kProfiles.Add((messagingMode, encoding), new MessagingProfile(messagingMode, encoding, dataSetMessageContentMask, networkMessageContentMask, dataSetFieldContentMask)); } } /// /// From published nodes jobs converter /// /// /// /// private static DataSetFieldContentFlags BuildDataSetFieldContentMask( bool fullFeaturedMessage = false, bool isSampleMessage = false) { return DataSetFieldContentFlags.StatusCode | DataSetFieldContentFlags.SourceTimestamp | (fullFeaturedMessage ? (DataSetFieldContentFlags.ServerTimestamp | DataSetFieldContentFlags.ApplicationUri | DataSetFieldContentFlags.EndpointUrl | DataSetFieldContentFlags.ExtensionFields) : 0) | (isSampleMessage ? (DataSetFieldContentFlags.NodeId | DataSetFieldContentFlags.DisplayName | DataSetFieldContentFlags.EndpointUrl) : DataSetFieldContentFlags.ServerTimestamp) ; } private static DataSetMessageContentFlags BuildDataSetContentMask( bool fullFeaturedMessage = false, bool reversibleEncoding = false, bool isSampleMessage = false) { return (reversibleEncoding ? DataSetMessageContentFlags.ReversibleFieldEncoding : 0) | (fullFeaturedMessage ? (DataSetMessageContentFlags.Timestamp | DataSetMessageContentFlags.DataSetWriterId | DataSetMessageContentFlags.SequenceNumber) : 0) | (!isSampleMessage ? (DataSetMessageContentFlags.Timestamp | DataSetMessageContentFlags.SequenceNumber) : 0) | DataSetMessageContentFlags.MetaDataVersion | DataSetMessageContentFlags.MajorVersion | DataSetMessageContentFlags.MinorVersion | DataSetMessageContentFlags.DataSetWriterName | DataSetMessageContentFlags.MessageType; } private static NetworkMessageContentFlags BuildNetworkMessageContentMask( bool isSampleMessage = false) { return (isSampleMessage ? NetworkMessageContentFlags.MonitoredItemMessage : (NetworkMessageContentFlags.NetworkMessageHeader | NetworkMessageContentFlags.PublisherId | NetworkMessageContentFlags.SequenceNumber | NetworkMessageContentFlags.Timestamp | NetworkMessageContentFlags.WriterGroupId | NetworkMessageContentFlags.PayloadHeader | NetworkMessageContentFlags.DataSetClassId | NetworkMessageContentFlags.NetworkMessageNumber)) | NetworkMessageContentFlags.DataSetMessageHeader; } private static readonly Dictionary<(MessagingMode, MessageEncoding), MessagingProfile> kProfiles = []; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Parser/Extensions/Extensions.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Irony.Parsing { using Azure.IIoT.OpcUa.Publisher.Parser; using System.Collections.Generic; using System.Linq; /// /// Parser extensions /// internal static class Extensions { /// /// Get children /// /// /// public static IEnumerable GetChildren( this ParseTreeNode? node) { if (node?.ChildNodes == null) { return []; } return node.ChildNodes; } /// /// Get children /// /// /// /// public static IEnumerable GetChildren( this ParseTreeNode? node, string name) { if (node?.ChildNodes == null) { return []; } return node.ChildNodes.Where( node => node.Term?.Name == name); } /// /// Get child at Index /// /// /// /// public static ParseTreeNode? GetChild( this ParseTreeNode? node, int index) { if (node?.ChildNodes == null || index >= node.ChildNodes.Count) { return null; } return node.ChildNodes[index]; } /// /// Get first node in the list /// /// /// /// /// public static ParseTreeNode? GetChild(this ParseTreeNode? node, string name, ref int expectedIndex) { if (node?.ChildNodes == null) { return null; } if (expectedIndex < node.ChildNodes.Count) { var found = node.ChildNodes[expectedIndex]; if (found.Term.Name == name) { expectedIndex++; return found; } } return node.ChildNodes.Find(node => node.Term?.Name == name); } /// /// Get first node in the list /// /// /// /// /// /// public static ParseTreeNode GetChild(this ParseTreeNode? node, string name, ref int expectedIndex, ParseTree syntaxTree) { var child = GetChild(node, name, ref expectedIndex); return child ?? throw ParserException.Create("Child node {name} not found in node.", syntaxTree, node); } /// /// Get child at Index /// /// /// /// /// public static ParseTreeNode GetChild(this ParseTreeNode? node, int index, ParseTree syntaxTree) { return GetChild(node, index) ?? throw ParserException.Create($"No Child at index {index} found in node.", syntaxTree, node); } /// /// Get child token text /// /// /// /// /// public static string GetChildTokenText(this ParseTreeNode? node, int index, ParseTree syntaxTree) { var child = GetChild(node, index, syntaxTree); var token = child?.FindTokenAndGetText(); return token ?? throw ParserException.Create($"No token value in node {node} at child {index}.", syntaxTree, node, child); } /// /// Get child token text /// /// /// /// /// public static string GetChildTokenText(this ParseTreeNode? node, int index, string defaultValue) { var child = GetChild(node, index); return child?.FindTokenAndGetText() ?? defaultValue; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Parser/FilterModelBuilder.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Parser { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Azure.IIoT.OpcUa.Encoders.Utils; using Furly.Extensions.Serializers; using Irony.Parsing; using System; using System.Buffers; using System.Collections.Generic; using System.Data; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; using System.Threading.Tasks; /// /// Builds event filter and query filters from a syntax tree. /// We do not bother with AST generation as the output of the /// parser is good enough for us to build the models /// internal sealed class FilterModelBuilder { /// /// Create event builder /// /// /// /// private FilterModelBuilder(ParseTree syntaxTree, IFilterParserContext context, IJsonSerializer serializer) { _serializer = serializer; _context = context; _syntaxTree = syntaxTree; var index = 0; var selectStmt = syntaxTree.Root .GetChild("selectStmt", ref index, _syntaxTree); index = 0; var prefixList = selectStmt .GetChild("prefixList", ref index); // // Get the prefix to namespace uri lookup table from // the prefix declarations. Prefixes are optional and // if not specified namespace indexes and node ids // are allowed to be used inline. // _prefixToNamespaceUri = prefixList .GetChildren() .ToDictionary( n => n.GetChildTokenText(0, _syntaxTree), // prefix n => ExpandNamespaceUri( n.GetChildTokenText(1, _syntaxTree))) // nsuri ?? []; var selList = selectStmt .GetChild("selList", ref index); _fromClauseOpt = selectStmt .GetChild("fromClauseOpt", ref index); _whereClauseOpt = selectStmt .GetChild("whereClauseOpt", ref index); // // Get the selected source type list. We maintain order // to ensure we pick the first declared one in case of // ambiguity. // index = 0; _typeToAliasOrdered = _fromClauseOpt .GetChild("typeList", ref index) .GetChildren("type") .Select(id => { var typeName = id .GetChildTokenText(0, _syntaxTree) .TrimMatchingChar('´'); var type = ExpandSimpleIdentifier(typeName, id, true); var alias = id.GetChildTokenText(1, string.Empty); return (type, alias); }) .ToList(); if (_typeToAliasOrdered.Count == 0) { // from clause is optional, default to BaseEventType. _typeToAliasOrdered = new List<(string, string)> { (Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), string.Empty) }; } index = 0; _fieldItemList = selList .GetChild("fieldItemList", ref index) .GetChildren() .ToList(); } /// /// Build the event filter model using the builder /// /// /// /// /// public static Task BuildEventFilterAsync( ParseTree syntaxTree, IFilterParserContext context, IJsonSerializer serializer, CancellationToken ct) { var builder = new FilterModelBuilder(syntaxTree, context, serializer); return builder.BuildEventFilterAsync(ct); } /// /// Build event filter model /// /// /// private async Task BuildEventFilterAsync( CancellationToken ct) { await LoadBuilderContextAsync(ct).ConfigureAwait(false); BuildSelectClauses(); BuildContentFilter(); var elements = GetContentFilterElements().ToList(); return new EventFilterModel { SelectClauses = _selectClauses.ToList(), WhereClause = elements.Count != 0 ? new ContentFilterModel { Elements = elements } : null }; } /// /// Load the builder context from the parser context /// /// /// private async Task LoadBuilderContextAsync(CancellationToken ct) { // Get valid identifier lookup table foreach (var typeId in _typeToAliasOrdered.Select(t => t.type).Distinct()) { var identifiers = await _context.GetIdentifiersAsync(typeId, ct).ConfigureAwait(false); var identifierTable = new Dictionary(); foreach (var identifier in identifiers) { // Ordered from super type to sub type so we override here identifierTable.AddOrUpdate(new ImmutableRelativePath(identifier.BrowsePath), identifier); } _validIdsForType.AddOrUpdate(typeId, identifierTable); } } /// /// Get content filter elements /// private IEnumerable GetContentFilterElements() { // Adjust all existing filter element indexes // Reverse the list _contentFilter.Reverse(); foreach (var filterElement in _contentFilter) { var element = filterElement.Element; if (element.FilterOperands?.Any(operand => operand.Index != null) != true) { yield return element; } else { var operands = new List(); foreach (var operand in element.FilterOperands) { if (operand.Index != null) { for (var index = 0; index < _contentFilter.Count; index++) { if (operand.Index == _contentFilter[index].Id) { operands.Add(operand with { Index = (uint)index }); break; } } } else { operands.Add(operand); } } yield return element with { FilterOperands = operands }; } } } /// /// Build select clauses /// /// private void BuildSelectClauses() { // Selected item indexed by name or alias if (_fieldItemList.Count != 0) { foreach (var item in _fieldItemList) { var index = 0; var fieldSource = item .GetChild("fieldSource", ref index, _syntaxTree) ; var path = ExpandPathIdentifier(fieldSource, out var type, out var displayName, out _, out var attribute); var operand = new SimpleAttributeOperandModel { AttributeId = attribute, BrowsePath = path, DisplayName = displayName, IndexRange = null, // TODO TypeDefinitionId = type }; var aliasOpt = item .GetChild("aliasOpt", ref index, _syntaxTree) .FindTokenAndGetText(); if (aliasOpt != null) { // // If an alias for later use was declared store it // for later lookup // _aliasForId.Add(aliasOpt, operand); } _selectClauses.Add(operand); } } else { // Select everything from every item foreach (var id in _validIdsForType.SelectMany(kv => kv.Value)) { _selectClauses.Add(new SimpleAttributeOperandModel { AttributeId = NodeAttribute.Value, BrowsePath = id.Value.BrowsePath, DisplayName = "/" + id.Value.DisplayName.Trim('/') + ".Value", TypeDefinitionId = id.Value.TypeDefinitionId }); } } } /// /// Build where clauses /// /// private void BuildContentFilter() { // Filter stack var expression = _whereClauseOpt.GetChild(0); if (expression == null) { return; } // Process first expression ProcessExpression(expression); } /// /// Process any filter expression /// /// /// /// private FilterOperandModel ProcessExpression(ParseTreeNode expression) { var index = 0; var exprName = expression.Term?.Name; switch (exprName) { case "unExpr": var unop = expression.GetChild("unOp", ref index, _syntaxTree); var unexpr = expression.GetChild(index, _syntaxTree); return ProcessExpression(unop, unexpr); case "binExpr": var lhs = expression.GetChild(index++, _syntaxTree); var binOp = expression.GetChild("binOp", ref index, _syntaxTree); var rhs = expression.GetChild(index, _syntaxTree); return ProcessExpression(binOp, lhs, rhs); case "fnExpr": var obj = expression.GetChild(index++, _syntaxTree); var fnOp = expression.GetChild("fnOp", ref index, _syntaxTree); var args = expression.GetChild("exprList", ref index, _syntaxTree); return ProcessExpression(fnOp, obj .YieldReturn() .Concat(args.GetChildren()) .ToArray()); case "literal": return ProcessLiteralOperand(expression); case "id": return ProcessIdentifierOperand(expression); case "parSelectStmt": throw ParserException.Create( "Unsupported expression found.", _syntaxTree, expression); default: throw ParserException.Create( $"Unsupported expression {exprName} found.", _syntaxTree, expression); } } /// /// Process element expression /// /// /// /// private FilterOperandModel ProcessExpression(ParseTreeNode op, params ParseTreeNode[] operandExpressions) { var filterOp = GetFilterOperator(op, out var negate, out var exprValidator); // Push the elements onto the stack // Process the children first and push each into the list var elements = new List(); foreach (var expression in operandExpressions) { var operand = ProcessExpression(expression); if (filterOp == FilterOperatorType.OfType && operand.AttributeId == NodeAttribute.NodeId) { // // Switch simple operand with NodeId attribute // into a literal with node type. // operand = new FilterOperandModel { Value = operand.NodeId, DataType = operand.AttributeId.ToString() }; } elements.Add(operand); } var error = exprValidator(elements); if (!string.IsNullOrEmpty(error)) { throw ParserException.Create(error, _syntaxTree, op.YieldReturn().Concat(operandExpressions).ToArray()); } _contentFilter.Add(new ContentFilterElement2Model(_contentFilter.Count + 1, new ContentFilterElementModel { FilterOperator = filterOp, FilterOperands = elements })); if (negate) { // Shift all indexes and insert another negating element _contentFilter.Add(new ContentFilterElement2Model(_contentFilter.Count + 1, new ContentFilterElementModel { FilterOperator = FilterOperatorType.Not, FilterOperands = new[] { new FilterOperandModel { Index = (uint)_contentFilter.Count } } })); } // Return an element used by others return new FilterOperandModel { Index = (uint)_contentFilter.Count }; } /// /// Process identifier expression and push onto the stack /// /// private FilterOperandModel ProcessIdentifierOperand( ParseTreeNode expression) { // a browse path identifier var path = ExpandPathIdentifier(expression, out var type, out _, out var alias, out var attribute); return new FilterOperandModel { AttributeId = attribute, BrowsePath = path, Alias = string.IsNullOrEmpty(alias) ? null : alias, IndexRange = null, // TODO NodeId = type }; } private FilterOperandModel ProcessLiteralOperand( ParseTreeNode expression) { var index = 0; var value = expression .GetChild("value", ref index, _syntaxTree) .GetChild(0, _syntaxTree); var dataType = expression .GetChild(index)? .FindTokenAndGetText()? .TrimMatchingChar('´'); var str = value.Term?.Name; if (value.Term is StringLiteral) { str = value.FindTokenAndGetText()?.TrimQuotes(); // Expand any namespaced simple identifiers if (dataType != null && str != null) { if (dataType.Equals("NodeId", StringComparison.OrdinalIgnoreCase) || dataType.Equals("ExpandedNodeId", StringComparison.OrdinalIgnoreCase)) { str = ExpandSimpleIdentifier(str, value, true); } else if (dataType.Equals("QualifiedName", StringComparison.OrdinalIgnoreCase)) { str = ExpandSimpleIdentifier(str, value, false); } } str = $"\"{str}\""; } else if (value.Term is NumberLiteral) { str = value.FindTokenAndGetText(); } if (string.IsNullOrEmpty(str)) { str = "null"; } return new FilterOperandModel { DataType = dataType, Value = _serializer.Parse(str) }; } /// /// Convert filter operator /// /// /// /// /// /// private FilterOperatorType GetFilterOperator(ParseTreeNode op, out bool negate, out Func, string?> validator) { negate = false; var opStr = op.FindTokenAndGetText(); FilterOperatorType filterOp; switch (opStr.ToUpperInvariant()) { case "NOT": case "!": filterOp = FilterOperatorType.Not; validator = l => ValidateExact(1, l); break; case "=": case "==": filterOp = FilterOperatorType.Equals; validator = l => ValidateExact(2, l); break; case ">": filterOp = FilterOperatorType.GreaterThan; validator = l => ValidateExact(2, l); break; case "<": filterOp = FilterOperatorType.LessThan; validator = l => ValidateExact(2, l); break; case ">=": filterOp = FilterOperatorType.GreaterThan; validator = l => ValidateExact(2, l); break; case "<=": filterOp = FilterOperatorType.LessThanOrEqual; validator = l => ValidateExact(2, l); break; case "LIKE": filterOp = FilterOperatorType.Like; validator = l => ValidateExact(2, l); break; case "<>": case "!=": negate = true; filterOp = FilterOperatorType.Equals; validator = l => ValidateExact(2, l); break; case "!<": negate = true; filterOp = FilterOperatorType.LessThan; validator = l => ValidateExact(2, l); break; case "!>": negate = true; filterOp = FilterOperatorType.GreaterThan; validator = l => ValidateExact(2, l); break; case "AND": filterOp = FilterOperatorType.And; validator = l => ValidateExact(2, l, true); break; case "OR": filterOp = FilterOperatorType.Or; validator = l => ValidateExact(2, l, true); break; case "CAST": filterOp = FilterOperatorType.Cast; validator = l => ValidateExact(2, l); break; case "&": filterOp = FilterOperatorType.BitwiseAnd; validator = l => ValidateExact(2, l); break; case "|": filterOp = FilterOperatorType.BitwiseOr; validator = l => ValidateExact(2, l); break; case "IN": filterOp = FilterOperatorType.InList; validator = l => ValidateMin(1, l); break; case "BETWEEN": filterOp = FilterOperatorType.Between; validator = l => ValidateExact(3, l); break; case "RELATEDTO": filterOp = FilterOperatorType.RelatedTo; validator = ValidateRelatedTo; break; case "ISNULL": filterOp = FilterOperatorType.IsNull; validator = l => ValidateExact(1, l); break; case "OFTYPE": filterOp = FilterOperatorType.OfType; validator = l => ValidateExact(1, l); break; case "INVIEW": filterOp = FilterOperatorType.InView; validator = l => ValidateExact(1, l); break; default: throw ParserException.Create($"Operand {opStr} not supported", _syntaxTree, op); } return filterOp; // // Generic expression validation. Validates the exact length of // provided operands. // string? ValidateExact(int exact, List operands, bool reverseOperands = false) { if (exact != operands.Count) { return $"Operator {opStr} ({filterOp}) requires {exact} " + $"operand(s) but only {operands.Count} provided."; } if (reverseOperands && operands.All(o => o.Index != null)) { // // Call reverse on the operands to match the specification // examples (validated in our tests) // operands.Reverse(); } return null; } // // Special case related to, which can have 3-6 operands // string? ValidateRelatedTo(IList operands) { if (operands.Count < 3) { return $"Operator {opStr} ({filterOp}) requires at least " + $"3 operands, but {operands.Count} provided."; } if (operands.Count > 6) { return $"Operator {opStr} ({filterOp}) requires at most " + $"6 operands, but {operands.Count} provided."; } return null; } // // Validate minimum operands are provided. // string? ValidateMin(int min, IList operands) { if (operands.Count < min) { return $"Operator {opStr} ({filterOp}) requires at least " + $"{min} operand(s), but {operands.Count} provided."; } return null; } } /// /// Fix up a namespace uri /// /// /// /// private static string ExpandNamespaceUri(string namespaceUri) { namespaceUri = namespaceUri.Trim(); if (namespaceUri[0] == '<' && namespaceUri[^1] == '>') { // Trim prefix quotes namespaceUri = namespaceUri[1..^1]; } return namespaceUri.TrimQuotes().TrimEnd('#'); } /// /// Expands a path identifier into the components of a simple or /// full operand identifier. /// /// /// /// /// /// /// /// private IReadOnlyList ExpandPathIdentifier(ParseTreeNode pathIdNode, out string typeDefinitionId, out string displayName, out string alias, out NodeAttribute attribute) { var pathId = pathIdNode.FindTokenAndGetText().TrimMatchingChar('´'); // Check first if the id is an alias for a selector. if (_aliasForId.TryGetValue(pathId, out var operand) && operand.BrowsePath != null && operand.DisplayName != null) { typeDefinitionId = operand.TypeDefinitionId!; displayName = operand.DisplayName; attribute = operand.AttributeId ?? NodeAttribute.Value; alias = pathId; return operand.BrowsePath; } // // A path can start with a type or type alias, if not the // default alias is assumed (empty string). If the path starts // with a aggregate, hierachical or other relationship, then // it is a path starting from an implicit type. // List pathElements; string typeOrTypeAlias; try { pathElements = pathId.ToRelativePath(out typeOrTypeAlias) .ToList(); } catch (FormatException formatException) { throw ParserException.Create(formatException.Message, formatException, _syntaxTree, pathIdNode); } // // Extract attribute. The attribute is appended using a . which // also stands for an aggregates reference element. // var last = pathElements.LastOrDefault(); NodeAttribute? nodeAttribute = null; if (last?.IsAggregatesReference() == true && last.NoSubtypes != true && last.IsInverse != true && Enum.TryParse(last.TargetName, true, out var attr)) { pathElements.Remove(last); nodeAttribute = attr; // Not an attribute - leave as is } // Check whether the alias points to a type var aliasedTypes = _typeToAliasOrdered .Where(typeAndAlias => typeAndAlias.alias == typeOrTypeAlias) ; if (!aliasedTypes.Any()) { if (string.IsNullOrEmpty(typeOrTypeAlias)) { // // Try to resolve the path from all specified types // with precedence of order of declaration. // aliasedTypes = _typeToAliasOrdered; } else { // // If the type alias is actually a valid type, then put // it first (without any alias). // var typeId = ExpandSimpleIdentifier(typeOrTypeAlias, pathIdNode, true); if (_typeToAliasOrdered .Any(typeAndAlias => typeAndAlias.type == typeId)) { aliasedTypes = (typeId, string.Empty).YieldReturn(); } } } if (pathElements.Count == 0) { // // There was only a type alias here. This is allowed // and means we want the type and an empty path after // We select node id of the type instead of value. // var aliasedType = aliasedTypes.FirstOrDefault(); if (!string.IsNullOrEmpty(aliasedType.type)) { attribute = nodeAttribute ?? NodeAttribute.NodeId; displayName = "/." + attribute.ToString(); typeDefinitionId = aliasedType.type; alias = aliasedType.alias; return Array.Empty(); } throw ParserException.Create("Could not find " + $"type {typeOrTypeAlias} in candidates declared in FROM.", _syntaxTree, pathIdNode, _fromClauseOpt); } // // The browse path is now pathElements. // We need to expand it to incorporate the prefixes // and resolve any session namespace indexes. // pathElements = pathElements.ConvertAll(element => element with { TargetName = ExpandSimpleIdentifier( element.TargetName, pathIdNode, false), ReferenceTypeId = ExpandSimpleIdentifier( element.ReferenceTypeId, pathIdNode, true), }); // // We now have candidate types in order of declaration // Try to resolve a valid identifier on these types. // // Try to uniquely identify the path in the valid ids var browsePath = new ImmutableRelativePath(pathElements.AsString()); foreach (var aliasedType in aliasedTypes) { var ids = _validIdsForType[aliasedType.type]; Debug.Assert(ids != null); if (ids.TryGetValue(browsePath, out var metadata)) { // Found it. attribute = nodeAttribute ?? NodeAttribute.Value; displayName = "/" + metadata.DisplayName.Trim('/') + "." + attribute; typeDefinitionId = metadata.TypeDefinitionId; alias = aliasedType.alias; return browsePath.Path; } // TODO: if we do not find it we could still use the context // to translate the browse path into a node etc. or just // return a stand in item. } var candidates = string.Join(", ", aliasedTypes.Select(a => a.type)); if (string.IsNullOrEmpty(candidates)) { throw ParserException.Create("Could not find " + $"candidate types that contain {browsePath}. " + "Make sure to declare a candidate type in FROM.", _syntaxTree, pathIdNode, _fromClauseOpt); } var available = string.Join(", ", aliasedTypes .SelectMany(a => _validIdsForType[a.type].Keys) .Distinct()); throw ParserException.Create( $"Could not find {browsePath} in one of the candidate types " + $"{candidates} provided in FROM.\nAvailable paths: {available}", _syntaxTree, pathIdNode, _fromClauseOpt); } /// /// Expand an identifier into a full string using lookup tables /// /// /// /// /// /// private string ExpandSimpleIdentifier(string id, ParseTreeNode? idNode, bool isNodeId) { if (id.Length > 1 && id[0] == '[' && id[^1] == ']') { id = id[1..^1]; } if (Uri.TryCreate(id, UriKind.Absolute, out var uri) && !string.IsNullOrEmpty(uri.Host)) { // Uri - keep as is return id; } var parts = id.Split(':', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries); if (parts.Length > 1) { if (!isNodeId && parts.Length > 2) { // We assume that a node id can contain > 1 colon throw ParserException.Create( $"Malformed identifier {id} contains > 1 colon character.", _syntaxTree, idNode); } id = id[(parts[0].Length + 1)..]; if (_prefixToNamespaceUri.TryGetValue(parts[0], out var namespaceUri) || TryGetNamespace(parts[0], out namespaceUri)) { if (string.IsNullOrEmpty(namespaceUri)) { return TranslateOpcUaIdentifier(id); // Default ua namespace } return namespaceUri + "#" + id; } if (!isNodeId) // We assume that a node id can contain 1..n colons { throw ParserException.Create("Failed to retrieve " + $"namespace for prefix {parts[0]} of identifier {id}.", _syntaxTree, idNode); } // // If this is a node id then let the resolver convert the string // later in the context of the session. Otherwise we assume that // if this is a path we have thrown earlier in case we could not // parse it here. // return id; // Custom node identifier bool TryGetNamespace(string prefix, out string? namespaceUri) { if (prefix.StartsWith("ns", StringComparison.InvariantCulture)) { prefix = prefix[2..]; } if (uint.TryParse(prefix, out var index)) { return _context.TryGetNamespaceUri(index, out namespaceUri); } namespaceUri = null; return false; } } return TranslateOpcUaIdentifier(id); static string TranslateOpcUaIdentifier(string id) { // Try convert object type identifiers if (TypeMaps.ObjectTypes.Value.TryGetIdentifier(id, out var identifier)) { return new Opc.Ua.NodeId(identifier).ToString(); } return id; } } /// /// Compare attribute operands. We have to use a comparer because reord /// do not compare arrays or read only lists by value. /// private sealed class SimpleAttributeOperandComperer : IEqualityComparer { /// public bool Equals(SimpleAttributeOperandModel? x, SimpleAttributeOperandModel? y) { return x.IsSameAs(y); } /// public int GetHashCode([DisallowNull] SimpleAttributeOperandModel obj) { return HashCode.Combine(obj.IndexRange, obj.AttributeId, obj.DisplayName, obj.DataSetClassFieldId, obj.TypeDefinitionId, obj.BrowsePath == null ? 0 : new ImmutableRelativePath(obj.BrowsePath).GetHashCode()); } } private record class ContentFilterElement2Model(int Id, ContentFilterElementModel Element); private readonly List _contentFilter = []; private readonly HashSet _selectClauses = new(new SimpleAttributeOperandComperer()); private readonly IJsonSerializer _serializer; private readonly IFilterParserContext _context; private readonly ParseTree _syntaxTree; private readonly List _fieldItemList; private readonly ParseTreeNode? _fromClauseOpt; private readonly ParseTreeNode? _whereClauseOpt; /// /// Lookup tables /// private readonly Dictionary _prefixToNamespaceUri; private readonly Dictionary _aliasForId = []; private readonly Dictionary> _validIdsForType = []; private readonly IReadOnlyList<(string type, string alias)> _typeToAliasOrdered; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Parser/FilterQueryGrammar.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Parser { using Irony.Parsing; /// /// Grammar to parse event filter sql into event filter models. /// Based on Irony sample which is loosely based on SQL89 grammar /// from Gold parser /// [Language("EventFilterGrammar", "1", "Sql grammar for OPC UA event filter construction.")] public class FilterQueryGrammar : Grammar { /// /// Create grammar /// public FilterQueryGrammar() : base(false) // SQL is case insensitive { // // Simple alpha numeric identifiers, e.g, prefixes or // namespace indexes. // var prefixId = new IdentifierTerminal("prefixId"); // Covers most node id and qualified name identifiers var id = new IdentifierTerminal("id", "=:/.;<>[]", "[/<."); // Allow quoting to support any character in the id var quoted = new StringLiteral("uaDefaultIdQuoted"); quoted.AddStartEnd("´", StringOptions.AllowsAllEscapes); quoted.SetOutputTerminal(this, id); // Filter statement var semiOpt = new NonTerminal("semiOpt") { Rule = Empty | ";" }; var stmt = new NonTerminal("stmt"); var stmtLine = new NonTerminal("stmtLine") { Rule = stmt + semiOpt }; var stmtList = new NonTerminal("stmtList"); stmtList.Rule = MakePlusRule(stmtList, stmtLine); Root = stmtList; // Set as root of parse tree var namespaceUri = new StringLiteral("namespaceUri"); namespaceUri.AddStartEnd("<", ">", StringOptions.NoEscapes); namespaceUri.AddStartEnd("http://", "#", StringOptions.NoEscapes); namespaceUri.AddStartEnd("https://", "#", StringOptions.NoEscapes); var PREFIX = ToTerm("PREFIX"); var prefixDecl = new NonTerminal("prefixDecl") { Rule = PREFIX + prefixId + namespaceUri }; var prefixList = new NonTerminal("prefixList"); prefixList.Rule = MakePlusRule(prefixList, prefixDecl); var prefixListOpt = new NonTerminal("prefixListOpt") { Rule = Empty | prefixList }; // // From selector which selects a type using the provided type // identifier and optionally assigns it an alias, e.g. from // BaseEventType E. It is optional, the default is assumed // to be "FROM BaseEventType". // var typeAliasOpt = new NonTerminal("typeAliasOpt") { Rule = Empty | prefixId }; var type = new NonTerminal("type") { Rule = id + typeAliasOpt }; var comma = ToTerm(","); var typeList = new NonTerminal("typeList"); typeList.Rule = MakePlusRule(typeList, comma, type); var FROM = ToTerm("FROM"); var fromClauseOpt = new NonTerminal("fromClauseOpt") { Rule = Empty | (FROM + typeList) }; // // Projection selector which selects fields by browse path // from the FROM selected type identifier. Field source is // either a simple browse path (default / first from statement) // Or qualified, e.g., E.f:path1/f:path2/x:path3 // var AS = ToTerm("AS"); var asOpt = new NonTerminal("asOpt") { Rule = Empty | AS }; var aliasOpt = new NonTerminal("aliasOpt") { Rule = Empty | (asOpt + prefixId) }; var fieldSource = new NonTerminal("fieldSource") { Rule = id }; var fieldItem = new NonTerminal("fieldItem") { Rule = fieldSource + aliasOpt }; var fieldItemList = new NonTerminal("fieldItemList"); fieldItemList.Rule = MakePlusRule(fieldItemList, comma, fieldItem); var selList = new NonTerminal("selList") { Rule = fieldItemList | "*" }; // // Where expression filter based on boolean logic. An expression // can be a unary, binary, or complex expression (related_to). // The expressions correspond to the defined filter operands // var WHERE = ToTerm("WHERE"); var expression = new NonTerminal("expression"); var whereClauseOpt = new NonTerminal("whereClauseOpt") { Rule = Empty | (WHERE + expression) }; // // Full select stmt which can be used inside filter // as expression (TODO) // var SELECT = ToTerm("SELECT"); var selectStmt = new NonTerminal("selectStmt") { Rule = prefixListOpt + SELECT + selList + fromClauseOpt + whereClauseOpt }; stmt.Rule = selectStmt; // // Unary expression // var NOT = ToTerm("NOT") | "!"; var unOp = new NonTerminal("unOp") { Rule = NOT // Not_7 | "ISNULL" // IsNull_1 | "INVIEW" // InView_13 | "OFTYPE" // OfType_14 }; var unExpr = new NonTerminal("unExpr") { Rule = unOp + expression }; RegisterOperators(10, NOT); RegisterOperators(9, "ISNULL", "INVIEW", "OFTYPE"); // // Binary expressions // var binOp = new NonTerminal("binOp") { Rule = ToTerm("=") | "==" // Equals_0 | ">" // GreaterThan_2 | "<" // LessThan_3 | ">=" // GreaterThanOrEqual_4 | "<=" // LessThanOrEqual_5 | "LIKE" // Like_6 | "<>" | "!=" // Not_7 + Equals_0 | "!<" // Not_7 + LessThan_3 | "!>" // Not_7 + GreaterThan_2 | "AND" // And_10 | "OR" // Or_11 | "&" // BitwiseAnd_16 | "|" // BitwiseOr_17 }; var binExpr = new NonTerminal("binExpr") { Rule = expression + binOp + expression }; // Operators RegisterOperators(9, "=", "==", ">", "<", ">=", "<=", "<>", "!=", "!<", "!>", "LIKE"); RegisterOperators(8, "&", "|"); RegisterOperators(5, "AND"); RegisterOperators(4, "OR"); // // Now cover any special functions including IN(...), // BETWEEN(...), RELATEDTO(...) // var fnOp = new NonTerminal("fnOp") { Rule = ToTerm("IN") // InList_9 | "CAST" // Cast_12 | "BETWEEN" // Between_8 | "RELATEDTO" // RelatedTo_15 }; var exprList = new NonTerminal("exprList"); exprList.Rule = MakePlusRule(exprList, comma, expression); var fnArgsList = new NonTerminal("fnArgsList") { Rule = "(" + exprList + ")" }; var fnExpr = new NonTerminal("fnExpr") { Rule = expression + fnOp + fnArgsList }; RegisterOperators(9, "IN", "BETWEEN", "RELATEDTO", "CAST"); // // Literal expression. A literal expression is essentially // a constant which can be a number, string, or a string // qualified by a type using the double hat operator. // var anyNumber = new NumberLiteral("number"); var anyString = new StringLiteral("string", "'", StringOptions.AllowsDoubledQuote); var anyBoolean = new NonTerminal("boolean") { Rule = ToTerm("true") | "false" }; var typeOpt = new NonTerminal("typeOpt") { Rule = Empty | ("^^" + id) }; var value = new NonTerminal("value") { Rule = anyNumber | anyString | anyBoolean }; var literal = new NonTerminal("literal") { Rule = value + typeOpt }; // // A selector selects a value either using a browse // path construct or a more complex select statement // var parSelectStmt = new NonTerminal("parSelectStmt") { Rule = "(" + selectStmt + ")" }; var parExpression = new NonTerminal("parExpression") { Rule = "(" + expression + ")" }; // // Expression is func, unary, binary, literal, inner // select or an expression in paranthesis // expression.Rule = unExpr | binExpr | fnExpr | literal | id | parSelectStmt | parExpression ; // // Support for sql comments // var comment = new CommentTerminal("comment", "/*", "*/"); var lineComment = new CommentTerminal("line_comment", "--", "\n", "\r\n"); NonGrammarTerminals.Add(comment); NonGrammarTerminals.Add(lineComment); MarkPunctuation(",", "(", ")", "*", "^^"); MarkPunctuation(semiOpt, asOpt, PREFIX, SELECT, FROM, WHERE); MarkTransient(stmt, parExpression, stmtLine, expression, typeAliasOpt, asOpt, typeOpt, prefixListOpt, fnArgsList); // // Set flag InheritPrecedence so that it inherits precedence // value from it's children, and this precedence is used // in conflict resolution when binOp node is sitting on the // stack // binOp.SetFlag(TermFlags.InheritPrecedence); unOp.SetFlag(TermFlags.InheritPrecedence); fnOp.SetFlag(TermFlags.InheritPrecedence); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Parser/FilterQueryParser.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Parser { using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Extensions.Serializers; using Irony.Parsing; using System.Threading; using System.Threading.Tasks; /// /// Parses strings into an event filter for simpler event /// subscription. /// public sealed class FilterQueryParser : IFilterParser { /// /// Create parser /// /// public FilterQueryParser(IJsonSerializer serializer) { _serializer = serializer; } /// public async Task ParseEventFilterAsync(string query, IFilterParserContext context, CancellationToken ct) { var parser = new Parser(_grammar); var syntaxTree = parser.Parse(query); if (syntaxTree.HasErrors()) { throw ParserException.Create("Parsing query failed.", syntaxTree); } // Build event filter from syntax tree return await FilterModelBuilder.BuildEventFilterAsync( syntaxTree, context, _serializer, ct).ConfigureAwait(false); } private readonly IJsonSerializer _serializer; private readonly FilterQueryGrammar _grammar = new(); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Parser/IFilterParser.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Parser { using Azure.IIoT.OpcUa.Publisher.Models; using System.Threading; using System.Threading.Tasks; /// /// Filter parser provides ability to convert filter query strings /// into content filters for query and subscription /// public interface IFilterParser { /// /// Parse query string into event filter model /// /// /// /// /// Task ParseEventFilterAsync(string query, IFilterParserContext context, CancellationToken ct = default); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Parser/IFilterParserContext.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Parser { using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; /// /// Identifier metadata /// /// /// /// public record IdentifierMetaData(string TypeDefinitionId, IReadOnlyList BrowsePath, string DisplayName); /// /// Event filter parser context /// public interface IFilterParserContext { /// /// Get valid identifiers /// /// /// /// Task> GetIdentifiersAsync( string typeId, CancellationToken ct = default); /// /// Resolve namespace uri /// /// /// /// bool TryGetNamespaceUri(uint index, out string? namespaceUri); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Parser/ParserException.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Parser { using Irony.Parsing; using System; using System.Collections.Generic; using System.Linq; using System.Text; /// /// Parser exception contains more information regarding source /// of the parser error than format exception provides /// public class ParserException : FormatException { /// public ParserException() { } /// public ParserException(string message) : base(message) { } /// public ParserException(string message, Exception innerException) : base(message, innerException) { } /// internal static Exception Create(string message, ParseTree syntaxTree, params ParseTreeNode?[] nodes) { return new ParserException(BuildMessage(message, syntaxTree, nodes)); } /// internal static Exception Create(string message, Exception innerException, ParseTree syntaxTree, params ParseTreeNode[] nodes) { return new ParserException(BuildMessage(message, syntaxTree, nodes), innerException); } /// /// Create message /// /// /// /// /// private static string BuildMessage(string message, ParseTree syntaxTree, ParseTreeNode?[] nodes) { var lines = syntaxTree.SourceText.Split("\n") .Select(line => line.Trim('\r')) .ToArray(); var errors = lines .Select(line => { var pointer = new char[line.Length + 10]; Array.Fill(pointer, ' '); return (pointer, new List()); }) .ToArray(); foreach (var msg in syntaxTree.ParserMessages) { var entry = errors[msg.Location.Line]; entry.pointer[msg.Location.Column] = '^'; var m = $"<--- (col:{msg.Location.Column}) {msg.Message} ----"; entry.Item2.Add(m.PadLeft(msg.Location.Column + m.Length)); } foreach (var node in nodes) { if (node == null) { continue; } var entry = errors[node.Span.Location.Line]; var len = node.Span.EndPosition - node.Span.Location.Position; for (var start = node.Span.Location.Column; start < node.Span.Location.Column + len && start < entry.pointer.Length; start++) { entry.pointer[start] = '~'; } var m = $"<--- (col:{node.Span.Location.Column}|len:{len}) ----"; entry.Item2.Add(m.PadLeft(node.Span.Location.Column + m.Length)); } var sb = new StringBuilder(message); sb.AppendLine(); for (var line = 0; line < lines.Length; line++) { sb.AppendLine(lines[line]); if (errors[line].Item2.Count > 0) { sb.AppendLine( new string(errors[line].pointer)); errors[line].Item2 .ForEach(e => sb.AppendLine(e)); } } return sb.ToString(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Parser/RelativePathParser.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Parser { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Encoders.Utils; using System; using System.Buffers; using System.Collections.Generic; using System.Text; /// /// Relative path parser according to /// https://reference.opcfoundation.org/v104/Core/docs/Part4/A.2/ /// internal static class RelativePathParser { /// /// Convert to path object /// /// /// /// public static IEnumerable ToRelativePath( this string path, out string prefix) { if (path.Length == 0) { prefix = string.Empty; return []; } var index = 0; prefix = ExtractTargetName(path, ref index); if (index == path.Length) { return []; } return Parse(path[index..]); } /// /// Format relative path element information /// /// /// /// public static IReadOnlyList AsString(this IEnumerable path, string? prefix = null) { var result = new List(); var value = new StringBuilder(prefix ?? string.Empty); foreach (var element in path) { var writeReference = false; if (element.IsAggregatesReference()) { value.Append('.'); } else if (element.IsHierarchicalReference()) { value.Append('/'); } else { value.Append('<'); writeReference = true; } if (element.IsInverse ?? false) { value.Append('!'); } if (element.NoSubtypes ?? false) { value.Append('#'); } if (writeReference) { if (!element.ReferenceTypeId.StartsWith("i=", StringComparison.InvariantCulture) || !uint.TryParse(element.ReferenceTypeId.AsSpan(2), out var id) || !TypeMaps.ReferenceTypes.Value.TryGetBrowseName(id, out var reference)) { reference = element.ReferenceTypeId; } value.Append(reference) .Append('>'); } var escape = element.TargetName.AsSpan().IndexOfAny(kAllowedChars) != -1; if (escape) { value.Append('['); } value.Append(element.TargetName); if (escape) { value.Append(']'); } result.Add(value.ToString()); value.Clear(); } return result; } /// /// Returns true if this is a aggregates reference. /// A aggregate is either HasComponent or HasProperty /// reference. Used to get components of an object /// or specifically properties of a variable. /// /// /// public static bool IsAggregatesReference(this RelativePathElementModel element) { return element.ReferenceTypeId == nameof(Opc.Ua.ReferenceTypes.Aggregates) || element.ReferenceTypeId == Opc.Ua.ReferenceTypeIds.Aggregates.ToString(); } /// /// Returns true if this is a hierachical reference. /// A hierarchical reference includes Aggregates but /// also Organizes (folder) or HasEventSource/HasNotifier /// and HasSubtype references /// /// /// public static bool IsHierarchicalReference(this RelativePathElementModel element) { return element.ReferenceTypeId == nameof(Opc.Ua.ReferenceTypes.HierarchicalReferences) || element.ReferenceTypeId == Opc.Ua.ReferenceTypeIds.HierarchicalReferences.ToString(); } /// /// Convert to path object /// /// /// /// private static IEnumerable Parse(string path) { var index = 0; while (index < path.Length) { // // Parse relative path reference information // This should allow // - "/targeturi" // - ".targeturi" // - "!.parenturi" // - "!/parenturi" // - "parenturi" // var parseReference = false; string? referenceTypeId = null; var inverse = false; var includeSubtypes = true; var exit = false; while (index < path.Length && !exit) { switch (path[index]) { case '<': if (referenceTypeId == null && !parseReference) { parseReference = true; break; } throw new FormatException("Reference type set."); case '!': inverse = true; break; case '#': includeSubtypes = false; break; case '/': if (referenceTypeId == null && !parseReference) { referenceTypeId = Opc.Ua.ReferenceTypeIds.HierarchicalReferences.ToString(); break; } throw new FormatException("Reference type set."); case '.': if (referenceTypeId == null && !parseReference) { referenceTypeId = Opc.Ua.ReferenceTypeIds.Aggregates.ToString(); break; } throw new FormatException("Reference type set."); default: if (referenceTypeId == null && !parseReference) { throw new FormatException( "No reference type specified."); } exit = true; break; } index++; } index--; // Parse the reference type if (parseReference) { var builder = new StringBuilder(); while (index < path.Length) { if (path[index] == '<' && path[index - 1] != '&') { throw new FormatException( "Reference contains a < which is not allowed."); } if (path[index] == '>' && path[index - 1] != '&') { if (index + 1 < path.Length && path[index + 1] == '>') { throw new FormatException( "Reference path ends in > followed by >."); } break; } if (path[index] != '&' || path[index - 1] == '&') { builder.Append(path[index]); } index++; if (index == path.Length) { throw new FormatException( "Reference path starts in < but does not end in >"); } } index++; // Skip > var reference = builder.ToString(); if (string.IsNullOrEmpty(reference)) { throw new FormatException( "Missed to provide a reference name between < and >."); } if (TypeMaps.ReferenceTypes.Value.TryGetIdentifier(reference, out var id)) { referenceTypeId = new Opc.Ua.NodeId(id).ToString(); } else { referenceTypeId = reference; } } // Parse target var target = ExtractTargetName(path, ref index); yield return new RelativePathElementModel { IsInverse = inverse ? true : null, NoSubtypes = includeSubtypes ? null : true, ReferenceTypeId = referenceTypeId ?? throw new FormatException("No reference type found"), TargetName = target }; } } /// /// Extracts a target name which can be escaped with [] /// /// /// /// /// private static string ExtractTargetName(string path, ref int index) { if (index >= path.Length) { return string.Empty; } var firstChar = path[index]; var lastChar = firstChar; var builder = new StringBuilder(); if (firstChar == '[') { index++; } while (index < path.Length) { switch (path[index]) { case '/': case '.': case '<': case '#': case '!': if (lastChar == '&') { builder.Append(path[index]); break; } // Check whether we are still escaping if (firstChar == '[' && lastChar != ']') { builder.Append(path[index]); break; } // No, we are done. return builder.ToString(); case ']': case '&': break; default: if (lastChar == ']') { builder.Append(lastChar); } builder.Append(path[index]); break; } lastChar = path[index]; index++; } if (firstChar == '[' && lastChar != ']') { throw new FormatException( "Sequence escaped with [ not closed with ]."); } // Not escaping and reaching the end return builder.ToString(); } private static readonly SearchValues kAllowedChars = SearchValues.Create("/#.<>!"); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Parser/SessionParserContext.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Parser { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Stack.Extensions; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Opc.Ua; using Opc.Ua.Extensions; using System.Collections.Generic; using System.Data; using System.Linq; using System.Threading; using System.Threading.Tasks; /// /// Parser context based on session filter /// public sealed class SessionParserContext : IFilterParserContext { /// /// Error occurred during validation /// public ServiceResultModel? ErrorInfo { get; private set; } /// /// Create context /// /// /// /// public SessionParserContext(IOpcUaSession session, RequestHeader header, NamespaceFormat format = NamespaceFormat.Index) { _session = session; _header = header; _format = format; } /// public async Task> GetIdentifiersAsync( string typeId, CancellationToken ct) { var map = new Dictionary(); var declarations = new List(); var nodeId = typeId.ToNodeId(_session.MessageContext); var hierarchy = new List<(NodeId, ReferenceDescription)>(); // If we failed before, fail again if (ErrorInfo != null) { return []; } await _session.CollectTypeHierarchyAsync(_header, nodeId, hierarchy, ct).ConfigureAwait(false); hierarchy.Reverse(); // Start from Root super type foreach (var (subType, superType) in hierarchy) { // Only request variables to resolve ErrorInfo = await _session.CollectInstanceDeclarationsAsync( _header, (NodeId)superType.NodeId, null, declarations, map, _format, Opc.Ua.NodeClass.Variable, ct).ConfigureAwait(false); if (ErrorInfo != null) { break; } } if (ErrorInfo == null) { // Collect the variables of the selected type. ErrorInfo = await _session.CollectInstanceDeclarationsAsync( _header, nodeId, null, declarations, map, _format, Opc.Ua.NodeClass.Variable, ct).ConfigureAwait(false); } if (ErrorInfo != null) { return []; } return declarations .Where(declaration => declaration.RootTypeId != null && declaration.BrowsePath != null) .Select(declaration => new IdentifierMetaData( declaration.RootTypeId!, declaration.BrowsePath!, declaration.DisplayPath ?? declaration.BrowseName!)); } /// public bool TryGetNamespaceUri(uint index, out string? namespaceUri) { namespaceUri = _session.MessageContext.NamespaceUris.GetString(index); return namespaceUri != null; } private readonly IOpcUaSession _session; private readonly RequestHeader _header; private readonly NamespaceFormat _format; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Properties/AssemblyInfo.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Azure.IIoT.OpcUa.Publisher.Tests")] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Runtime/PublisherConfig.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Encoders.Schemas; using Furly.Extensions.Configuration; using Furly.Extensions.Hosting; using Furly.Extensions.Messaging; using Microsoft.Extensions.Configuration; using Opc.Ua; using System; using System.Configuration; using System.Linq; using System.Net; using System.Runtime.InteropServices; using System.Text; /// /// Publisher configuration /// public sealed class PublisherConfig : PostConfigureOptionBase { /// /// Configuration /// public const string PublisherIdKey = "PublisherId"; #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public const string SiteIdKey = "SiteId"; public const string PublishedNodesFileKey = "PublishedNodesFile"; public const string UseFileChangePollingKey = "UseFileChangePolling"; public const string CreatePublishFileIfNotExistKey = "CreatePublishFileIfNotExist"; public const string MessagingModeKey = "MessagingMode"; public const string MessageEncodingKey = "MessageEncoding"; public const string FullFeaturedMessageKey = "FullFeaturedMessage"; public const string UseStandardsCompliantEncodingKey = "UseStandardsCompliantEncoding"; public const string MethodTopicTemplateKey = "MethodTopicTemplate"; public const string RootTopicTemplateKey = "RootTopicTemplate"; public const string TelemetryTopicTemplateKey = "TelemetryTopicTemplate"; public const string EventsTopicTemplateKey = "EventsTopicTemplate"; public const string DiagnosticsTopicTemplateKey = "DiagnosticsTopicTemplate"; public const string DataSetMetaDataTopicTemplateKey = "DataSetMetaDataTopicTemplate"; public const string SchemaTopicTemplateKey = "SchemaTopicTemplate"; public const string DefaultWriterGroupPartitionCountKey = "DefaultWriterGroupPartitionCount"; public const string DefaultMaxMessagesPerPublishKey = "DefaultMaxMessagesPerPublish"; public const string MaxNetworkMessageSendQueueSizeKey = "MaxNetworkMessageSendQueueSize"; public const string DiagnosticsIntervalKey = "DiagnosticsInterval"; public const string DiagnosticsTargetKey = "DiagnosticsTarget"; public const string BatchSizeKey = "BatchSize"; public const string BatchTriggerIntervalKey = "BatchTriggerInterval"; public const string RemoveDuplicatesFromBatchKey = "RemoveDuplicatesFromBatch"; public const string WriteValueWhenDataSetHasSingleEntryKey = "WriteValueWhenDataSetHasSingleEntry"; public const string IoTHubMaxMessageSizeKey = "IoTHubMaxMessageSize"; public const string DebugLogNotificationsKey = "DebugLogNotifications"; public const string DebugLogEncodedNotificationsKey = "DebugLogEncodedNotifications"; public const string DebugLogNotificationsFilterKey = "DebugLogNotificationsFilter"; public const string DebugLogNotificationsWithHeartbeatKey = "DebugLogNotificationsWithHeartbeat"; public const string MaxNodesPerDataSetKey = "MaxNodesPerDataSet"; public const string DisableDataSetMetaDataKey = "DisableDataSetMetaData"; public const string EnableDataSetKeepAlivesKey = "EnableDataSetKeepAlives"; public const string SendDataSetKeepAlivesAsKeyFrameKey = "SendDataSetKeepAlivesAsKeyFrame"; public const string DefaultKeyFrameCountKey = "DefaultKeyFrameCount"; public const string DisableComplexTypeSystemKey = "DisableComplexTypeSystem"; public const string DisableSessionPerWriterGroupKey = "DisableSessionPerWriterGroup"; public const string DefaultUseReverseConnectKey = "DefaultUseReverseConnect"; public const string DisableSubscriptionTransferKey = "DisableSubscriptionTransfer"; public const string DefaultMetaDataUpdateTimeKey = "DefaultMetaDataUpdateTime"; public const string ScaleTestCountKey = "ScaleTestCount"; public const string IgnoreConfiguredPublishingIntervalsKey = "IgnoreConfiguredPublishingIntervals"; public const string DisableOpenApiEndpointKey = "DisableOpenApiEndpoint"; public const string DefaultNamespaceFormatKey = "DefaultNamespaceFormat"; public const string MessageTimestampKey = "MessageTimestamp"; public const string EnableRuntimeStateReportingKey = "RuntimeStateReporting"; public const string RuntimeStateRoutingInfoKey = "RuntimeStateRoutingInfo"; public const string EnableDataSetRoutingInfoKey = "EnableRoutingInfo"; public const string EnableCloudEventsKey = "EnableCloudEvents"; public const string ForceCredentialEncryptionKey = "ForceCredentialEncryption"; public const string RenewTlsCertificateOnStartupKey = "RenewTlsCertificateOnStartup"; public const string DefaultTransportKey = "DefaultTransport"; public const string DefaultQualityOfServiceKey = "DefaultQualityOfService"; public const string DefaultMessageTimeToLiveKey = "DefaultMessageTimeToLive"; public const string DefaultMessageRetentionKey = "DefaultMessageRetention"; public const string DefaultDataSetRoutingKey = "DefaultDataSetRouting"; public const string ApiKeyOverrideKey = "ApiKey"; public const string PublishMessageSchemaKey = "PublishMessageSchema"; public const string AsyncMetaDataLoadTimeoutKey = "AsyncMetaDataLoadTimeout"; public const string PreferAvroOverJsonSchemaKey = "PreferAvroOverJsonSchema"; public const string SchemaNamespaceKey = "SchemaNamespace"; public const string DisableResourceMonitoringKey = "DisableResourceMonitoring"; public const string HttpServerPortKey = "HttpServerPort"; public const string UnsecureHttpServerPortKey = "UnsecureHttpServerPort"; #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member /// /// Variables in templates /// public const string PublisherIdVariableName = "PublisherId"; #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public const string RootTopicVariableName = "RootTopic"; public const string TelemetryTopicVariableName = "TelemetryTopic"; public const string DataSetWriterGroupVariableName = "DataSetWriterGroup"; public const string WriterGroupVariableName = "WriterGroup"; public const string WriterGroupIdVariableName = "WriterGroupId"; public const string DataSetWriterNameVariableName = "DataSetWriterName"; public const string DataSetWriterVariableName = "DataSetWriter"; public const string DataSetNameVariableName = "DataSetName"; public const string DataSetTopicPathVariableName = "DataSetTopicPath"; public const string DataSetWriterIdVariableName = "DataSetWriterId"; public const string DataSetFieldIdVariableName = "DataSetFieldId"; public const string DataSetClassIdVariableName = "DataSetClassId"; public const string EventNameVariableName = "EventName"; public const string EventContextVariableName = "EventContext"; public const string EventSourceVariableName = "EventSource"; public const string EncodingVariableName = "Encoding"; public const string ClusterNamespaceVariableName = "ClusterNamespace"; public const string ClusterHostVariableName = "ClusterHost"; #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member /// /// Default values /// public const string TelemetryTopicTemplateDefault = $"{{{RootTopicVariableName}}}/messages/{{{WriterGroupVariableName}}}"; #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public const string MethodTopicTemplateDefault = $"{{{RootTopicVariableName}}}/methods"; public const string EventsTopicTemplateDefault = $"{{{RootTopicVariableName}}}/{{{EventSourceVariableName}}}/{{{EventNameVariableName}}}"; public const string MetadataTopicTemplateDefault = $"{{{TelemetryTopicVariableName}}}/metadata"; public const string DiagnosticsTopicTemplateDefault = $"{{{RootTopicVariableName}}}/diagnostics/{{{WriterGroupVariableName}}}"; public const string RootTopicTemplateDefault = $"{{{PublisherIdVariableName}}}"; public const string RootTopicTemplateCluster = $"{{{ClusterNamespaceVariableName}}}/{{{PublisherIdVariableName}}}"; public const string SchemaTopicTemplateDefault = $"{{{TelemetryTopicVariableName}}}/schema"; public const string PublishedNodesFileDefault = "publishednodes.json"; public const string RuntimeStateRoutingInfoDefault = "runtimeinfo"; public const bool EnableRuntimeStateReportingDefault = false; public const bool UseStandardsCompliantEncodingDefault = false; public const bool EnableDataSetRoutingInfoDefault = false; public const bool EnableCloudEventsDefault = false; public const MessageEncoding MessageEncodingDefault = MessageEncoding.Json; public const int MaxNodesPerDataSetDefault = 1000; public const int BatchSizeLegacyDefault = 50; public const int MaxNetworkMessageSendQueueSizeDefault = 4096; public const int BatchTriggerIntervalLLegacyDefaultMillis = 10 * 1000; public const int AsyncMetaDataLoadTimeoutDefaultMillis = 5 * 1000; public const int DiagnosticsIntervalDefaultMillis = 60 * 1000; public const int ScaleTestCountDefault = 1; public const bool IgnoreConfiguredPublishingIntervalsDefault = false; public const bool DisableSessionPerWriterGroupDefault = false; public static readonly int UnsecureHttpServerPortDefault = IsContainer && IsRunningAsRoot ? 80 : 9071; public static readonly int HttpServerPortDefault = IsContainer && IsRunningAsRoot ? 443 : 9072; #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member /// public override void PostConfigure(string? name, PublisherOptions options) { options.DisableResourceMonitoring ??= GetBoolOrNull(DisableResourceMonitoringKey); options.PublisherId ??= GetStringOrDefault(PublisherIdKey, _identity?.Identity ?? Dns.GetHostName()); options.SiteId ??= GetStringOrDefault(SiteIdKey); options.PublishedNodesFile ??= GetStringOrDefault(PublishedNodesFileKey); options.UseFileChangePolling ??= GetBoolOrNull(UseFileChangePollingKey); if (options.DefaultTransport == null && Enum.TryParse( GetStringOrDefault(DefaultTransportKey), out var transport)) { options.DefaultTransport = transport; } options.UseStandardsCompliantEncoding ??= GetBoolOrDefault( UseStandardsCompliantEncodingKey, UseStandardsCompliantEncodingDefault); if (options.MessagingProfile == null) { if (!Enum.TryParse(GetStringOrDefault(MessagingModeKey), out var messagingMode)) { messagingMode = options.UseStandardsCompliantEncoding == true ? MessagingMode.PubSub : MessagingMode.Samples; } if (GetBoolOrDefault(FullFeaturedMessageKey, false)) { if (messagingMode == MessagingMode.PubSub) { messagingMode = MessagingMode.FullNetworkMessages; } if (messagingMode == MessagingMode.Samples) { messagingMode = MessagingMode.FullSamples; } } if (!Enum.TryParse(GetStringOrDefault(MessageEncodingKey), out var messageEncoding)) { messageEncoding = MessageEncodingDefault; } if (!MessagingProfile.IsSupported(messagingMode, messageEncoding)) { var supported = MessagingProfile.Supported .Select(p => $"\n(--mm {p.MessagingMode} and --me {p.MessageEncoding})") .Aggregate((a, b) => $"{a}, {b}"); throw new ConfigurationErrorsException( "The specified combination of --mm, and --me is not (yet) supported." + $" Currently supported combinations are: {supported}"); } options.MessagingProfile = MessagingProfile.Get(messagingMode, messageEncoding); } options.CreatePublishFileIfNotExist ??= GetBoolOrNull( CreatePublishFileIfNotExistKey); options.RenewTlsCertificateOnStartup ??= GetBoolOrNull( RenewTlsCertificateOnStartupKey); if (options.MaxNodesPerDataSet == 0) { options.MaxNodesPerDataSet = GetIntOrDefault(MaxNodesPerDataSetKey, MaxNodesPerDataSetDefault); } // // Default to batch size of 50 if not using strict encoding and a // transport was not specified to support backcompat with 2.8 // options.BatchSize ??= GetIntOrDefault(BatchSizeKey, options.UseStandardsCompliantEncoding == true || options.DefaultTransport != null ? 0 : BatchSizeLegacyDefault); if (options.BatchTriggerInterval == null) { // // Default to batch interval of 10 seconds if not using strict encoding // and a transport was not specified to support backcompat with 2.8 // options.BatchTriggerInterval = GetDurationOrNull(BatchTriggerIntervalKey) ?? TimeSpan.FromMilliseconds(GetIntOrDefault(BatchTriggerIntervalKey, options.UseStandardsCompliantEncoding == true || options.DefaultTransport != null ? 0 : BatchTriggerIntervalLLegacyDefaultMillis)); } options.WriteValueWhenDataSetHasSingleEntry ??= GetBoolOrNull(WriteValueWhenDataSetHasSingleEntryKey); options.RemoveDuplicatesFromBatch ??= GetBoolOrNull(RemoveDuplicatesFromBatchKey); options.MaxNetworkMessageSendQueueSize ??= GetIntOrDefault(MaxNetworkMessageSendQueueSizeKey, MaxNetworkMessageSendQueueSizeDefault); options.DefaultWriterGroupPartitions ??= GetIntOrNull(DefaultWriterGroupPartitionCountKey); options.IgnoreConfiguredPublishingIntervals ??= GetBoolOrDefault(IgnoreConfiguredPublishingIntervalsKey, IgnoreConfiguredPublishingIntervalsDefault); if (options.TopicTemplates.Root == null) { options.TopicTemplates.Root = GetStringOrDefault( RootTopicTemplateKey, options.IsAzureIoTOperationsConnector != null ? RootTopicTemplateCluster : RootTopicTemplateDefault); } if (options.TopicTemplates.Method == null) { options.TopicTemplates.Method = GetStringOrDefault( MethodTopicTemplateKey, MethodTopicTemplateDefault); } if (options.TopicTemplates.Events == null) { options.TopicTemplates.Events = GetStringOrDefault( EventsTopicTemplateKey, EventsTopicTemplateDefault); } if (options.TopicTemplates.Diagnostics == null) { options.TopicTemplates.Diagnostics = GetStringOrDefault( DiagnosticsTopicTemplateKey, DiagnosticsTopicTemplateDefault); } if (options.TopicTemplates.Telemetry == null) { options.TopicTemplates.Telemetry = GetStringOrDefault( TelemetryTopicTemplateKey, TelemetryTopicTemplateDefault); } if (options.TopicTemplates.DataSetMetaData == null) { options.TopicTemplates.DataSetMetaData = GetStringOrDefault( DataSetMetaDataTopicTemplateKey); } if (options.TopicTemplates.Schema == null) { options.TopicTemplates.Schema = GetStringOrDefault( SchemaTopicTemplateKey, SchemaTopicTemplateDefault); } options.DisableOpenApiEndpoint ??= GetBoolOrNull(DisableOpenApiEndpointKey); options.EnableRuntimeStateReporting ??= GetBoolOrDefault( EnableRuntimeStateReportingKey, EnableRuntimeStateReportingDefault); options.RuntimeStateRoutingInfo ??= GetStringOrDefault( RuntimeStateRoutingInfoKey, RuntimeStateRoutingInfoDefault); options.ScaleTestCount ??= GetIntOrDefault(ScaleTestCountKey, ScaleTestCountDefault); if (options.DebugLogNotificationsFilter == null) { options.DebugLogNotificationsFilter = GetStringOrDefault(DebugLogNotificationsFilterKey); options.DebugLogNotifications ??= (options.DebugLogNotificationsFilter != null ? true : null); } if (options.DebugLogNotificationsWithHeartbeat == null) { options.DebugLogNotificationsWithHeartbeat = GetBoolOrDefault(DebugLogNotificationsWithHeartbeatKey); options.DebugLogNotifications ??= options.DebugLogNotifications; } options.DebugLogNotifications ??= GetBoolOrDefault(DebugLogNotificationsKey); options.DebugLogEncodedNotifications ??= GetBoolOrDefault(DebugLogEncodedNotificationsKey); if (options.DiagnosticsInterval == null) { options.DiagnosticsInterval = GetDurationOrNull(DiagnosticsIntervalKey) ?? TimeSpan.FromMilliseconds(GetIntOrDefault(DiagnosticsIntervalKey, DiagnosticsIntervalDefaultMillis)); } if (options.DiagnosticsTarget == null) { if (!Enum.TryParse( GetStringOrDefault(DiagnosticsTargetKey), out var target)) { target = PublisherDiagnosticTargetType.Logger; } options.DiagnosticsTarget = target; } options.EnableCloudEvents ??= GetBoolOrDefault( EnableCloudEventsKey, EnableCloudEventsDefault); options.EnableDataSetRoutingInfo ??= GetBoolOrDefault( EnableDataSetRoutingInfoKey, EnableDataSetRoutingInfoDefault); options.ForceCredentialEncryption ??= GetBoolOrDefault( ForceCredentialEncryptionKey); options.MaxNetworkMessageSize ??= GetIntOrNull(IoTHubMaxMessageSizeKey); options.DefaultMaxDataSetMessagesPerPublish ??= (uint?)GetIntOrNull( DefaultMaxMessagesPerPublishKey); if (options.DefaultQualityOfService == null) { if (!Enum.TryParse(GetStringOrDefault(DefaultQualityOfServiceKey), out var qos)) { qos = QoS.AtLeastOnce; } options.DefaultQualityOfService = qos; } if (options.DefaultMessageTimeToLive == null) { var ttl = GetIntOrNull(DefaultMessageTimeToLiveKey); options.DefaultMessageTimeToLive = ttl.HasValue ? TimeSpan.FromMilliseconds(ttl.Value) : GetDurationOrNull( DefaultMessageTimeToLiveKey); } options.DefaultMessageRetention = GetBoolOrNull(DefaultMessageRetentionKey); if (options.MessageTimestamp == null) { if (!Enum.TryParse(GetStringOrDefault(MessageTimestampKey), out var messageTimestamp)) { messageTimestamp = MessageTimestamp.CurrentTimeUtc; } options.MessageTimestamp = messageTimestamp; } if (options.DefaultNamespaceFormat == null) { if (!Enum.TryParse(GetStringOrDefault(DefaultNamespaceFormatKey), out var namespaceFormat)) { namespaceFormat = options.UseStandardsCompliantEncoding == true ? NamespaceFormat.Expanded : NamespaceFormat.Uri; } options.DefaultNamespaceFormat = namespaceFormat; } options.UnsecureHttpServerPort ??= GetIntOrNull( UnsecureHttpServerPortKey, UnsecureHttpServerPortDefault); options.HttpServerPort ??= GetIntOrNull( HttpServerPortKey, HttpServerPortDefault); options.ApiKeyOverride ??= GetStringOrDefault(ApiKeyOverrideKey); if (options.DefaultDataSetRouting == null && Enum.TryParse(GetStringOrDefault(DefaultDataSetRoutingKey), out var routingMode)) { options.DefaultDataSetRouting = routingMode; } var schemaNamespace = GetStringOrDefault(SchemaNamespaceKey); var avroPreferred = GetBoolOrNull(PreferAvroOverJsonSchemaKey); if (schemaNamespace != null || avroPreferred != null || GetBoolOrDefault(PublishMessageSchemaKey)) { options.SchemaOptions ??= new SchemaOptions(); } if (options.SchemaOptions != null) { options.SchemaOptions.Namespace ??= schemaNamespace; options.SchemaOptions.PreferAvroOverJsonSchema ??= avroPreferred; } options.DisableComplexTypeSystem ??= GetBoolOrNull(DisableComplexTypeSystemKey); options.DisableDataSetMetaData = options.DisableComplexTypeSystem; // Set a default from the strict setting options.DisableDataSetMetaData ??= GetBoolOrDefault(DisableDataSetMetaDataKey, !(options.UseStandardsCompliantEncoding ?? false)); var metaDataEnabled = options.SchemaOptions != null || options.DisableDataSetMetaData != true; if (metaDataEnabled) { // Always turn on complex type system for schema publishing options.DisableComplexTypeSystem = false; } if (options.DefaultMetaDataUpdateTime == null && metaDataEnabled) { options.DefaultMetaDataUpdateTime = GetDurationOrNull(DefaultMetaDataUpdateTimeKey); } if (options.AsyncMetaDataLoadTimeout == null && metaDataEnabled) { options.AsyncMetaDataLoadTimeout = GetDurationOrDefault(AsyncMetaDataLoadTimeoutKey, TimeSpan.FromMilliseconds(AsyncMetaDataLoadTimeoutDefaultMillis)); } options.EnableDataSetKeepAlives ??= GetBoolOrDefault(EnableDataSetKeepAlivesKey); options.SendDataSetKeepAlivesAsKeyFrame ??= GetBoolOrDefault(SendDataSetKeepAlivesAsKeyFrameKey); options.DefaultKeyFrameCount ??= (uint?)GetIntOrNull(DefaultKeyFrameCountKey); options.DisableSessionPerWriterGroup ??= GetBoolOrDefault(DisableSessionPerWriterGroupKey, DisableSessionPerWriterGroupDefault); options.DefaultUseReverseConnect ??= GetBoolOrNull(DefaultUseReverseConnectKey); options.DisableSubscriptionTransfer ??= GetBoolOrNull(DisableSubscriptionTransferKey); } /// /// Running as root /// public static bool IsRunningAsRoot => StringComparer.OrdinalIgnoreCase.Equals( Environment.UserName, "root"); /// /// Running in container /// public static bool IsContainer => StringComparer.OrdinalIgnoreCase.Equals( Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") ?? string.Empty, "true"); /// /// Create configurator /// /// /// public PublisherConfig(IConfiguration configuration, IProcessIdentity? identity = null) : base(configuration) { _identity = identity; } /// /// Publisher version /// public static string Version { get; } = new StringBuilder(ThisAssembly.AssemblyInformationalVersion) #if DEBUG .Append(" [DEBUG]") #endif .Append(" (") .Append(RuntimeInformation.FrameworkDescription) .Append('/') .Append(AppContext.GetData("RUNTIME_IDENTIFIER") as string ?? RuntimeInformation.ProcessArchitecture.ToString()) .Append("/OPC Stack ") .Append(typeof(SessionChannel).Assembly.GetReleaseVersion().ToString()) .Append(')') .ToString(); private readonly IProcessIdentity? _identity; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Runtime/PublisherOptions.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Encoders.Schemas; using Furly.Extensions.Messaging; using System; using System.Collections.Generic; /// /// Publisher configuration /// public sealed class PublisherOptions { /// /// Publisher id /// public string? PublisherId { get; set; } /// /// Site of the publisher /// public string? SiteId { get; set; } /// /// Configuration file /// public string? PublishedNodesFile { get; set; } /// /// Poll changes instead of using file watcher /// public bool? UseFileChangePolling { get; set; } /// /// Create the configuration file if it does not exist /// public bool? CreatePublishFileIfNotExist { get; set; } /// /// Create a new ssl certificate on startup /// public bool? RenewTlsCertificateOnStartup { get; set; } /// /// Max number of nodes per data set (publishing /// endpoint inside the configuration of publisher) /// public int MaxNodesPerDataSet { get; set; } /// /// Messaging profile to use as default inside the /// publisher. /// public MessagingProfile? MessagingProfile { get; set; } /// /// Default max notifications to queue up until a /// network message is generated. Defaults to 1 if /// no writer group publishing interval is specified. /// Otherwise 4096 which is heuristically large enough /// to let the publishing interval clear the queue. /// public int? BatchSize { get; set; } /// /// Writer group publishing interval cycle. This is /// the timeout until a network message is generated /// from the queue of notifications. /// public TimeSpan? BatchTriggerInterval { get; set; } /// /// Whether to remove duplicate values from the batch /// of monitored item samples if samples mode is used. /// public bool? RemoveDuplicatesFromBatch { get; set; } /// /// Default maximum network message size to use. /// public int? MaxNetworkMessageSize { get; set; } /// /// ChannelDiagnostics interval /// public TimeSpan? DiagnosticsInterval { get; set; } /// /// How to emit diagnostics /// public PublisherDiagnosticTargetType? DiagnosticsTarget { get; set; } /// /// Log ingress notifications to informational log /// public bool? DebugLogNotifications { get; set; } /// /// Filter to apply to the notifications before adding to log /// public string? DebugLogNotificationsFilter { get; set; } /// /// Include heartbeats in ingess logs /// public bool? DebugLogNotificationsWithHeartbeat { get; set; } /// /// Log encoded notifications to informational log /// public bool? DebugLogEncodedNotifications { get; set; } /// /// Define the maximum number of network messages in the /// send part of the publish queue of the writer group. /// public int? MaxNetworkMessageSendQueueSize { get; set; } /// /// Max number of publish queue partitions the writer group /// should be split into. /// public int? DefaultWriterGroupPartitions { get; set; } /// /// Flag to use reversible encoding for messages /// public bool? UseStandardsCompliantEncoding { get; set; } /// /// Instead of a dataset with a single entry, Write only the /// value without key when possible. /// public bool? WriteValueWhenDataSetHasSingleEntry { get; set; } /// /// The message timestamp to use /// public MessageTimestamp? MessageTimestamp { get; set; } /// /// Default topic templates /// public TopicTemplatesOptions TopicTemplates { get; } = new TopicTemplatesOptions(); /// /// Allowed transports for all events and diagnostics targets. If empty all /// configured event clients are used. /// public HashSet AllowedEventAndDiagnosticsTransports { get; } = new(); /// /// Default transport to use if not found /// public WriterGroupTransport? DefaultTransport { get; set; } /// /// Default quality of service for messages /// public QoS? DefaultQualityOfService { get; set; } /// /// Default message time to live /// public TimeSpan? DefaultMessageTimeToLive { get; set; } /// /// Default whether to set message retain flag /// public bool? DefaultMessageRetention { get; set; } /// /// Default Max data set messages per published network /// message. /// public uint? DefaultMaxDataSetMessagesPerPublish { get; set; } /// /// Configuration flag for enabling/disabling /// runtime state reporting. /// public bool? EnableRuntimeStateReporting { get; set; } /// /// The routing info to add to the runtime state /// events. /// public string? RuntimeStateRoutingInfo { get; set; } /// /// Never load the complex type system from any session. /// This disables metadata loading capability but also /// the ability to encode complex types. /// public bool? DisableComplexTypeSystem { get; set; } /// /// Whether to enable or disable data set metadata explicitly /// public bool? DisableDataSetMetaData { get; set; } /// /// Default metadata send interval. /// public TimeSpan? DefaultMetaDataUpdateTime { get; set; } /// /// Timeout to block the first message after a metadata /// change is causing the load of the new metadata. /// public TimeSpan? AsyncMetaDataLoadTimeout { get; set; } /// /// Flag to send messages with cloud events header /// public bool? EnableCloudEvents { get; set; } /// /// Enable adding data set routing info to message headers /// Only applies if EnableCloudEvents is not true. /// public bool? EnableDataSetRoutingInfo { get; set; } /// /// Whether to enable or disable keep alive messages /// public bool? EnableDataSetKeepAlives { get; set; } /// /// Whether to send keep alive messages as key frames /// or as regular keep alive messages. /// public bool? SendDataSetKeepAlivesAsKeyFrame { get; set; } /// /// Default keyframe count /// public uint? DefaultKeyFrameCount { get; set; } /// /// Disable creating a separate session per writer group. This /// will re-use sessions across writer groups. Default is to /// create a seperate session. /// public bool? DisableSessionPerWriterGroup { get; set; } /// /// Always default to use or not use reverse connect /// unless overridden by the configuration. /// public bool? DefaultUseReverseConnect { get; set; } /// /// Disable subscription transfer on reconnect. /// public bool? DisableSubscriptionTransfer { get; set; } /// /// Force encryption of credentials in publisher configuration /// or dont store credentials. Default is false. /// public bool? ForceCredentialEncryption { get; set; } /// /// Optional default node id and qualified name namespace /// format to use when serializing nodes in messages and /// responses. /// public NamespaceFormat? DefaultNamespaceFormat { get; set; } /// /// Disable open api endpoint /// public bool? DisableOpenApiEndpoint { get; set; } /// /// Scale test option /// public int? ScaleTestCount { get; set; } /// /// Ignore all publishing intervals set in the configuration. /// public bool? IgnoreConfiguredPublishingIntervals { get; set; } /// /// Allow setting or overriding the current api key /// public string? ApiKeyOverride { get; set; } /// /// Use auto routing based on the opc ua address space /// browse paths. /// public DataSetRoutingMode? DefaultDataSetRouting { get; set; } /// /// Schema generation options if schema generation is /// enabled. /// public SchemaOptions? SchemaOptions { get; set; } /// /// Disable resource monitoring /// public bool? DisableResourceMonitoring { get; set; } /// /// Unsecure port /// public int? UnsecureHttpServerPort { get; set; } /// /// Secure port /// public int? HttpServerPort { get; set; } /// /// Publisher runs as Azure IoT Operations connector. /// If null, not running in Azure IoT Operations. /// public bool? IsAzureIoTOperationsConnector { get; set; } /// /// When discovering device endpoints this is the /// Endpoint type string that publisher should add /// to the endpoints. Default is Microsoft.OpcPublisher. /// Set this to Microsoft.OpcUa to let Azure IoT /// Operations handle the OPC UA discovered endpoints. /// public string? AioDiscoveredDeviceEndpointType { get; set; } /// /// When discovering device endpoints this is the /// Endpoint type version that publisher should add /// to the endpoints. /// public string? AioDiscoveredDeviceEndpointTypeVersion { get; set; } /// /// Enables discovery of OPC UA servers on the network /// and reporting as devices to Azure IoT Operations. /// If null, discovery is disabled. /// public DiscoveryMode? AioNetworkDiscoveryMode { get; set; } /// /// Discovery of OPC UA servers on the network and reporting /// as devices to Azure IoT Operations runs at the configured /// interval. If 0 or null, discovery runs once and /// exits. /// public TimeSpan? AioNetworkDiscoveryInterval { get; set; } /// /// Configure the discovery behavior of the publisher. /// public DiscoveryConfigModel AioNetworkDiscovery { get; } = new(); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Runtime/TopicBuilder.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { using Azure.IIoT.OpcUa.Publisher.Models; using k8s; using System; using System.Collections.Generic; using System.Text.RegularExpressions; /// /// Topic template support /// public sealed class TopicBuilder { /// /// Root topic /// public string RootTopic => Format(nameof(RootTopic), _templates.Root ?? _options.TopicTemplates.Root); /// /// Method topic /// public string MethodTopic => Format(nameof(MethodTopic), _templates.Method ?? _options.TopicTemplates.Method); /// /// Events topic /// public string EventsTopic => Format(nameof(EventsTopic), _templates.Events ?? _options.TopicTemplates.Events); /// /// ChannelDiagnostics topic /// public string DiagnosticsTopic => Format(nameof(DiagnosticsTopic), _templates.Diagnostics ?? _options.TopicTemplates.Diagnostics); /// /// Telemetry topic /// public string TelemetryTopic => Format(nameof(TelemetryTopic), _templates.Telemetry ?? _options.TopicTemplates.Telemetry); /// /// Default metadata topic /// public string DataSetMetaDataTopic => Format(nameof(DataSetMetaDataTopic), _templates.DataSetMetaData ?? _options.TopicTemplates.DataSetMetaData); /// /// Default schema topic /// public string SchemaTopic => Format(nameof(SchemaTopic), _templates.Schema ?? _options.TopicTemplates.Schema); /// /// Create builder /// /// /// /// /// public TopicBuilder(PublisherOptions options, MessageEncoding? encoding = null, TopicTemplatesOptions? templates = null, IEnumerable>? variables = null) { _options = options; _templates = templates ?? options.TopicTemplates; _variables = new Dictionary> { { nameof(TelemetryTopic), f => f.Format(_templates.Telemetry ?? _options.TopicTemplates.Telemetry) }, { nameof(RootTopic), f => f.Format(_templates.Root ?? _options.TopicTemplates.Root) }, { nameof(EventsTopic), f => f.Format(_templates.Events ?? _options.TopicTemplates.Events) }, { PublisherConfig.EncodingVariableName, _ => (encoding ?? MessageEncoding.Json).ToString() }, { nameof(options.SiteId), _ => options.SiteId ?? Constants.DefaultSiteId }, { nameof(options.PublisherId), _ => options.PublisherId ?? options.SiteId ?? Constants.DefaultPublisherId } }; if (KubernetesClientConfiguration.IsInCluster()) { _variables.AddOrUpdate(PublisherConfig.ClusterNamespaceVariableName, _ => KubernetesClientConfiguration.InClusterConfig().Namespace); _variables.AddOrUpdate(PublisherConfig.ClusterHostVariableName, _ => KubernetesClientConfiguration.InClusterConfig().Host); } if (variables != null) { foreach (var kv in variables) { _variables.AddOrUpdate(kv.Key, _ => kv.Value); } } } /// /// Format template /// /// /// /// internal string Format(string topicName, string? template) { return new Formatter(topicName, _variables).Format(template); } private sealed class Formatter { /// /// Unused variables /// public Dictionary> Variables { get; } public Formatter(string topicName, Dictionary> variables) { Variables = new Dictionary>(variables, StringComparer.OrdinalIgnoreCase); // Remove topic name from formatter resolver to not recurse into itself Variables.Remove(topicName); } /// /// Format topic /// /// /// public string Format(string? template) { if (template == null) { return string.Empty; } #pragma warning disable SYSLIB1045 // Convert to 'GeneratedRegexAttribute'. return Regex.Replace(template, "{([^}]+)}", m => { if (Variables.TryGetValue(m.Groups[1].Value, out var v)) { Variables.Remove(m.Groups[1].Value); return v.Invoke(this); } return m.Groups[1].Value; }); #pragma warning restore SYSLIB1045 // Convert to 'GeneratedRegexAttribute'. } } private readonly PublisherOptions _options; private readonly TopicTemplatesOptions _templates; private readonly Dictionary> _variables; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Runtime/TopicTemplatesOptions.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher { /// /// Topic templates /// public sealed record class TopicTemplatesOptions { /// /// Root topic template /// public string? Root { get; set; } /// /// Method topic template /// public string? Method { get; set; } /// /// Events topic template /// public string? Events { get; set; } /// /// Diagnostics topic template /// public string? Diagnostics { get; set; } /// /// Telemetry topic template /// public string? Telemetry { get; set; } /// /// Default metadata queue name /// public string? DataSetMetaData { get; set; } /// /// Default schema topic when schemas are published /// public string? Schema { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Services/AssetDeviceIntegration.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Services { using Azure.IIoT.OpcUa.Publisher.Config.Models; using Azure.IIoT.OpcUa.Publisher.Discovery; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Parser; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Azure.Iot.Operations.Connector; using Azure.Iot.Operations.Connector.Files; using Azure.Iot.Operations.Services.AssetAndDeviceRegistry.Models; using Azure.Iot.Operations.Services.SchemaRegistry.SchemaRegistry; using Furly.Azure.IoT.Operations.Services; using Furly.Extensions.Serializers; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Nito.AsyncEx; using Opc.Ua; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; /// /// Asset and device configuration integration with Azure iot operations. Converts asset /// and device notifications into published nodes representation and signals configuration /// status errors back. /// public sealed partial class AssetDeviceIntegration : IAioSrCallbacks, IAsyncDisposable, IDisposable { /// /// Currently known assets /// internal IEnumerable Assets => _assets.Values; /// /// Currently known devices /// internal IEnumerable Devices => _devices.Values; /// /// Create Akri and asset and device registry integration service /// /// /// /// /// /// /// /// /// /// public AssetDeviceIntegration(IAioAdrClient client, IAioSrClient schemaRegistry, IPublishedNodesServices publishedNodes, IConfigurationServices configurationServices, IConnectionServices connections, IDiscoveryServices discovery, IJsonSerializer serializer, IOptions options, ILogger logger) { _client = client; _publishedNodes = publishedNodes; _configurationServices = configurationServices; _connections = connections; _discovery = discovery; _serializer = serializer; _options = options; _logger = logger; _cts = new CancellationTokenSource(); _client.OnDeviceChanged += OnDeviceChanged; _client.OnAssetChanged += OnAssetChanged; _schemaRegistry = schemaRegistry; _srevents = schemaRegistry.Register(this); _changeFeed = Channel.CreateUnbounded<(string, Resource)>(new UnboundedChannelOptions { SingleReader = true, SingleWriter = false }); _processor = Task.Factory.StartNew(() => RunAsync(_cts.Token), _cts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default).Unwrap(); _trigger = new AsyncManualResetEvent(); _timer = new Timer(_ => _trigger.Set()); _assetDiscovery = Task.Factory.StartNew(() => RunAssetDiscoveryAsync(_cts.Token), _cts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default).Unwrap(); _deviceDiscovery = Task.Factory.StartNew(() => RunDeviceDiscoveryAsync(_cts.Token), _cts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default).Unwrap(); } /// public async ValueTask DisposeAsync() { if (_isDisposed) { return; } _isDisposed = true; try { await _cts.CancelAsync().ConfigureAwait(false); _changeFeed.Writer.TryComplete(); _timer.Dispose(); try { await _assetDiscovery.ConfigureAwait(false); } catch (OperationCanceledException) { } catch (Exception ex) { _logger.FailedToCloseDiscoveryRunner(ex); } try { await _processor.ConfigureAwait(false); } catch (OperationCanceledException) { } catch (Exception ex) { _logger.FailedToCloseConversionProcessor(ex); } try { await _deviceDiscovery.ConfigureAwait(false); } catch (OperationCanceledException) { } catch (Exception ex) { _logger.FailedToCloseDiscoveryRunner(ex); } } finally { _srevents.Dispose(); _cts.Dispose(); } } /// public void Dispose() { DisposeAsync().AsTask().GetAwaiter().GetResult(); } /// public async ValueTask OnSchemaRegisteredAsync( Furly.Extensions.Messaging.IEventSchema schema, Schema registration, CancellationToken ct) { if (registration.Name == null || registration.Namespace == null || registration.Version == null) { _logger.SchemaRegistrationInvalidValues(); return; } if (schema.Id == null) { _logger.CannotRegisterSchemaWithoutIdentifier(); return; } var pos = schema.Id.IndexOf('|', StringComparison.Ordinal); if (pos < 3) { _logger.MalformedSchemaId(schema.Id); return; } var assetName = schema.Id.Substring(0, pos); var resourceName = schema.Id.Substring(pos + 1); _logger.RegisteringSchema(registration.Name, registration.Version, resourceName, assetName, registration.Namespace); var reference = new MessageSchemaReference { SchemaName = registration.Name, SchemaRegistryNamespace = registration.Namespace, SchemaVersion = registration.Version }; var assetResource = _assets.Values .FirstOrDefault(a => a.Asset.DisplayName == assetName); if (assetResource == null) { // Fall backs - see below assetResource = _assets.Values.FirstOrDefault(a => a.Asset.Model == assetName) ?? _assets.Values.FirstOrDefault(a => a.AssetName == assetName); } if (assetResource == null) { _logger.NoAssetFoundForSchema(assetName, schema.Name); return; } assetName = assetResource.AssetName; // Set known asset name; var deviceName = assetResource.Asset.DeviceRef.DeviceName; var endpoint = assetResource.Asset.DeviceRef.EndpointName; Debug.Assert(deviceName != null); Debug.Assert(endpoint != null); AssetDatasetEventStreamStatus? dataSetStatus = null; AssetEventGroupStatus? eventGroupStatus = null; var dataSet = assetResource.Asset.Datasets?.Find(d => d.Name == resourceName); if (dataSet != null) { dataSetStatus = new AssetDatasetEventStreamStatus { Name = dataSet.Name, MessageSchemaReference = reference }; } else { var @event = assetResource.Asset.EventGroups? .Select(eg => (eg, eg.Events?.Find(e => e.Name == resourceName)!)) .FirstOrDefault(t => t.Item2 != null); if (@event != null) { eventGroupStatus = new AssetEventGroupStatus { Events = [ new AssetDatasetEventStreamStatus { Name = @event.Value.Item2.Name, MessageSchemaReference = reference } ] }; } } if (eventGroupStatus == null && dataSetStatus == null) { _logger.NoResourceFoundInAssetForSchema(resourceName, assetName, schema.Name); return; } try { for (var i = 0; ; i++) { try { await _client.UpdateAssetStatusAsync(deviceName, endpoint, assetName, new AssetStatus { Datasets = dataSetStatus != null ? [dataSetStatus] : null, EventGroups = eventGroupStatus != null ? [eventGroupStatus] : null }, ct: ct).ConfigureAwait(false); _logger.RegisteredSchema(registration.Name, registration.Version, resourceName, assetName, registration.Namespace); break; } catch (Exception e) when (i < 3 && !ct.IsCancellationRequested) { _logger.RegisteredSchemaErrorDebug(e, registration.Name, registration.Version, resourceName, assetName, registration.Namespace); } } } catch (Exception ex) when (!ct.IsCancellationRequested) { _logger.RegisteredSchemaError(ex, registration.Name, registration.Version, resourceName, assetName, registration.Namespace); throw; } } /// /// Asset change handler /// /// /// /// internal void OnAssetChanged(object? sender, AssetChangedEventArgs e) { if (string.IsNullOrEmpty(e.DeviceName) || string.IsNullOrEmpty(e.InboundEndpointName) || string.IsNullOrEmpty(e.AssetName)) { _logger.InvalidAssetChangeEventReceived(e.ChangeType, e.DeviceName, e.InboundEndpointName, e.AssetName); return; } switch (e.ChangeType) { case ChangeType.Created: OnAssetCreated(e.DeviceName, e.InboundEndpointName, e.AssetName, e.Asset!); break; case ChangeType.Updated: OnAssetUpdated(e.DeviceName, e.InboundEndpointName, e.AssetName, e.Asset!); break; case ChangeType.Deleted: OnAssetDeleted(e.DeviceName, e.InboundEndpointName, e.AssetName); break; default: throw new ArgumentOutOfRangeException(nameof(e), e.ChangeType, "Unknown asset change type"); } } /// /// Device change handler /// /// /// /// internal void OnDeviceChanged(object? sender, DeviceChangedEventArgs e) { if (string.IsNullOrEmpty(e.DeviceName) || string.IsNullOrEmpty(e.InboundEndpointName)) { _logger.InvalidDeviceChangeEventReceived(e.ChangeType, e.DeviceName, e.InboundEndpointName); return; } switch (e.ChangeType) { case ChangeType.Created: OnDeviceCreated(e.DeviceName, e.InboundEndpointName, e.Device!); break; case ChangeType.Updated: OnDeviceUpdated(e.DeviceName, e.InboundEndpointName, e.Device!); break; case ChangeType.Deleted: OnDeviceDeleted(e.DeviceName, e.InboundEndpointName); break; default: throw new ArgumentOutOfRangeException(nameof(e), e.ChangeType, "Unknown device change type"); } } /// /// Handle device created /// /// /// /// internal void OnDeviceCreated(string deviceName, string inboundEndpointName, Device device) { var name = CreateDeviceKey(deviceName, inboundEndpointName); var deviceResource = new DeviceResource(deviceName, device); var cur = _devices.AddOrUpdate(name, deviceResource, (_, cur) => device.Version == cur.Device.Version ? cur : deviceResource); if (!ReferenceEquals(cur, deviceResource)) { // Update has same version as what we already have return; } _logger.DeviceAdded(deviceName, inboundEndpointName); Interlocked.Increment(ref _lastDeviceListVersion); var success = _changeFeed.Writer.TryWrite((name, deviceResource)); ObjectDisposedException.ThrowIf(!success, $"Failed to process creation of device {name}"); } /// /// Handle device updated /// /// /// /// internal void OnDeviceUpdated(string deviceName, string inboundEndpointName, Device device) { var name = CreateDeviceKey(deviceName, inboundEndpointName); var deviceResource = new DeviceResource(deviceName, device); var cur = _devices.AddOrUpdate(name, deviceResource, (_, cur) => device.Version == cur.Device.Version ? cur : deviceResource); if (!ReferenceEquals(cur, deviceResource)) { // Update has same version as what we already have return; } _logger.DeviceUpdated(deviceName, inboundEndpointName); Interlocked.Increment(ref _lastDeviceListVersion); var success = _changeFeed.Writer.TryWrite((name, deviceResource)); ObjectDisposedException.ThrowIf(!success, $"Failed to process update of device {name}"); } /// /// Handle device deletion /// /// /// internal void OnDeviceDeleted(String deviceName, String inboundEndpointName) { var name = CreateDeviceKey(deviceName, inboundEndpointName); if (!_devices.TryRemove(name, out var deviceResource)) { _logger.ResourceDeletionNotFound(name); return; } _logger.DeviceRemoved(deviceName, inboundEndpointName); Interlocked.Increment(ref _lastDeviceListVersion); var success = _changeFeed.Writer.TryWrite((name, deviceResource)); ObjectDisposedException.ThrowIf(!success, $"Failed to publish deletion of {name}."); } /// /// Handle asset created /// /// /// /// /// internal void OnAssetCreated(string deviceName, string inboundEndpointName, string assetName, Asset asset) { var name = CreateAssetKey(deviceName, inboundEndpointName, assetName); var assetResource = new AssetResource(assetName, asset); var cur = _assets.AddOrUpdate(name, assetResource, (_, cur) => asset.Version == cur.Asset.Version ? cur : assetResource); if (!ReferenceEquals(cur, assetResource)) { // Update has same version as what we already have return; } _logger.AssetAdded(assetName, deviceName, inboundEndpointName); var success = _changeFeed.Writer.TryWrite((name, assetResource)); ObjectDisposedException.ThrowIf(!success, $"Failed to publish creation of asset {name}."); } /// /// Handle asset updated /// /// /// /// /// internal void OnAssetUpdated(string deviceName, string inboundEndpointName, string assetName, Asset asset) { var name = CreateAssetKey(deviceName, inboundEndpointName, assetName); var assetResource = new AssetResource(assetName, asset); var cur = _assets.AddOrUpdate(name, assetResource, (_, cur) => asset.Version == cur.Asset.Version ? cur : assetResource); if (!ReferenceEquals(cur, assetResource)) { // Update has same version as what we already have return; } _logger.AssetUpdated(assetName, deviceName, inboundEndpointName); var success = _changeFeed.Writer.TryWrite((name, assetResource)); ObjectDisposedException.ThrowIf(!success, $"Failed to publish update of asset {name}."); } /// /// Handle asset deletion /// /// /// /// internal void OnAssetDeleted(string deviceName, string inboundEndpointName, string assetName) { var name = CreateAssetKey(deviceName, inboundEndpointName, assetName); if (!_assets.TryRemove(name, out var asseteResource)) { _logger.ResourceDeletionNotFound(name); return; } _logger.AssetRemoved(assetName, deviceName, inboundEndpointName); var success = _changeFeed.Writer.TryWrite((name, asseteResource)); ObjectDisposedException.ThrowIf(!success, $"Failed to publish deletion of asset {name}."); } /// /// Monitors the change events produced as result of the notifications and then /// processes the current state. /// /// /// internal async Task RunAsync(CancellationToken ct) { try { // Read changes in batches while (!ct.IsCancellationRequested) { var updatesReceived = false; var deviceAddedOrUpdated = false; while (_changeFeed.Reader.TryRead(out var change)) { (var name, var resource) = change; switch (resource) { case AssetResource asset: if (!_assets.ContainsKey(name)) { await _client.StopMonitoringAssetsAsync( asset.Asset.DeviceRef.DeviceName, asset.Asset.DeviceRef.EndpointName, ct).ConfigureAwait(false); } else { await _client.StartMonitoringAssetsAsync( asset.Asset.DeviceRef.DeviceName, asset.Asset.DeviceRef.EndpointName, ct).ConfigureAwait(false); } break; case DeviceResource device: if (device.Device.Endpoints?.Inbound != null) { foreach (var endpoint in device.Device.Endpoints.Inbound.Keys) { if (!_devices.ContainsKey(name)) { // Removed, stop monitoring assets and clear asset list await _client.StopMonitoringAssetsAsync(device.DeviceName, endpoint, ct).ConfigureAwait(false); } else { await _client.StartMonitoringAssetsAsync(device.DeviceName, endpoint, ct).ConfigureAwait(false); deviceAddedOrUpdated = true; } } } break; default: Debug.Fail("Should not happen"); break; } updatesReceived = true; } // Process changes if (updatesReceived) { // Reconcile devices with assets - remove assets without devices or endpoints foreach (var (name, asset) in _assets) { var key = CreateDeviceKey( asset.Asset.DeviceRef.DeviceName, asset.Asset.DeviceRef.EndpointName); if (!_devices.ContainsKey(key)) { _logger.RemovingAssetWithoutDevice(name, key); _assets.TryRemove(name, out var _); await _client.StopMonitoringAssetsAsync( asset.Asset.DeviceRef.DeviceName, asset.Asset.DeviceRef.EndpointName, ct).ConfigureAwait(false); } } // Convert assets to published nodes entries and update configuration var assets = _assets.Values.ToList(); if (assets.Count > 0) { var errors = new ValidationErrors(this); var devices = _devices.Values.ToList(); _logger.ConvertingAssetsOnDevices(assets.Count, devices.Count); var entries = await ToPublishedNodesAsync(devices, assets, errors, ct).ConfigureAwait(false); // Report all errors await errors.ReportAsync(ct).ConfigureAwait(false); // Apply configuration await _publishedNodes.SetConfiguredEndpointsAsync(entries, ct).ConfigureAwait(false); if (_logger.IsDebugLogConfigurationEnabled()) { _logger.NewConfigurationApplied( _serializer.SerializeToString(entries, SerializeOption.Indented)); } _logger.AssetsAndDevicesUpdated(assets.Count, devices.Count); } } if (deviceAddedOrUpdated) { _logger.DevicesUpdatedStartingDiscovery(); // TODO Make period configurable _timer.Change(TimeSpan.Zero, kDefaultDeviceDiscoveryRefresh); } await _changeFeed.Reader.WaitToReadAsync(ct).ConfigureAwait(false); } } catch (OperationCanceledException) { } catch (ObjectDisposedException) { } catch (Exception ex) { _logger.UnexpectedErrorProcessingChanges(ex); throw; } } /// /// Discover assets /// /// /// /// /// /// internal async ValueTask RunDiscoveryUsingTypesAsync(DeviceEndpointResource resource, DeviceEndpointConfiguration endpointConfiguration, ValidationErrors errors, CancellationToken ct) { if (resource.Device.Endpoints == null || !TryGetInboundEndpoint(resource.Device.Endpoints, resource.EndpointName, out var endpoint)) { errors.OnError(resource, kDeviceNotFoundErrorCode, "Endpoint was not found"); return; // throw } Debug.Assert(endpointConfiguration.AssetTypes != null); // endpoint var assetEndpoint = new PublishedNodesEntryModel { EndpointUrl = GetEndpointUrl(endpoint.Address), EndpointSecurityMode = endpointConfiguration.EndpointSecurityMode, EndpointSecurityPolicy = endpointConfiguration.EndpointSecurityPolicy, DumpConnectionDiagnostics = endpointConfiguration.DumpConnectionDiagnostics, DisableSubscriptionTransfer = endpointConfiguration.DisableSubscriptionTransfer, UseReverseConnect = endpointConfiguration.UseReverseConnect }; var credentials = _client.GetEndpointCredentials(resource.DeviceName, resource.EndpointName, endpoint); assetEndpoint = AddEndpointCredentials(assetEndpoint, credentials, errors, resource); // Find all assets that comply with the provided types. var assetEntries = new List(); foreach (var type in endpointConfiguration.AssetTypes.Distinct()) { var template = assetEndpoint with { // Expand the type - TODO, we could also pass all types here at once OpcNodes = [new OpcNodeModel { Id = type }] }; await foreach (var found in _configurationServices.ExpandAsync(template, new PublishedNodeExpansionModel { CreateSingleWriter = false, // Writer per dataset ExcludeRootIfInstanceNode = false, DiscardErrors = true, IncludeMethods = true, FlattenTypeInstance = false, NoSubTypesOfTypeNodes = false, UseBrowseNameAsDisplayName = true }, ct).ConfigureAwait(false)) { if (found.ErrorInfo != null) { // Add to cumulative log errors.OnError(resource, kDiscoveryError, AsString(found.ErrorInfo)); continue; } if (found.Result?.OpcNodes == null || found.Result.OpcNodes.Count == 0 || found.Result.DataSetWriterGroup == null || found.Result.WriterGroupRootNodeId == null || found.Result.WriterGroupType == null) { if (_logger.IsDebugLogConfigurationEnabled()) { _logger.DroppingResultWithoutRequiredInformation( _serializer.SerializeToString(found.Result)); } else { _logger.DroppingResultWithoutRequiredInformation( found.Result?.DataSetName); } continue; } assetEntries.Add(found.Result); } } // Convert assets to dAsset and report them as found. We group the assets per name // and asset type ref. We resolve the duplicate names later from the hashset var uniqueAssetNames = new HashSet(); foreach (var (assetName, assetId, assetTypeRef, opcNodes) in assetEntries .GroupBy(e => ( AssetName: e.DataSetWriterGroup!, AssetId: e.WriterGroupRootNodeId!, AssetTypeRef: e.WriterGroupType! )) .Select(group => ( group.Key.AssetName, group.Key.AssetId, group.Key.AssetTypeRef, group.ToList()))) { var uniqueId = "-" + (resource.DeviceName + assetId).ToSha1Hash(); var assetResourceName = MakeValidArmResourceName(assetName, uniqueId).TrimEnd('-') + uniqueId; var uniqueAssetName = assetResourceName; // Ensure unique asset names for (var i = 1; !uniqueAssetNames.Add(uniqueAssetName); i++) { uniqueAssetName = assetResourceName + i; } // ensure no duplicate datasets and datapoints (names) are added into the asset var distinctEntries = opcNodes .GroupBy(entry => entry.DataSetName) .SelectMany(group => group.Select((d, i) => d with { DataSetName = i == 0 ? d.DataSetName : d.DataSetName + "." + i, OpcNodes = d.OpcNodes! .GroupBy(n => n.DisplayName) .SelectMany(group => group.Select((n, i) => n with { DisplayName = i == 0 ? n.DisplayName : n.DisplayName + "." + i })) .ToList() })) .ToList(); var distinctDatasets = distinctEntries .Select(entry => entry with { OpcNodes = entry.OpcNodes! .Where(n => n.AttributeId != NodeAttribute.EventNotifier && n.MethodMetadata == null) .ToList(), }) .Where(d => d.OpcNodes!.Count > 0) .ToList(); var distinctEventGroups = distinctEntries .Select(entry => entry with { OpcNodes = entry.OpcNodes! .Where(n => n.AttributeId == NodeAttribute.EventNotifier && n.MethodMetadata == null) .ToList(), }) .Where(d => d.OpcNodes!.Count > 0) .ToList(); var distinctManagementGroups = distinctEntries .Select(entry => entry with { OpcNodes = entry.OpcNodes! .Where(n => n.MethodMetadata != null) .ToList(), }) .Where(d => d.OpcNodes!.Count > 0) .ToList(); var dAsset = new DiscoveredAsset { DeviceRef = new AssetDeviceRef { DeviceName = resource.DeviceName, EndpointName = resource.EndpointName }, Attributes = new Dictionary { [kAssetIdAttribute] = assetId }, // AssetName = uniqueAssetName, ExternalAssetId = assetId, DisplayName = assetName, Model = assetName, Description = null, // TODO AssetTypeRefs = [assetTypeRef], DefaultDatasetsDestinations = [ new DatasetDestination { Target = DatasetTarget.Mqtt, Configuration = new DestinationConfiguration { Qos = _options.Value.DefaultQualityOfService == Furly.Extensions.Messaging.QoS.AtMostOnce ? QoS.Qos0 : QoS.Qos1, Topic = CreateTopic(), Retain = _options.Value.DefaultMessageRetention == true ? Retain.Keep : Retain.Never, Ttl = (ulong?)_options.Value.DefaultMessageTimeToLive?.TotalSeconds } } ], DefaultEventsDestinations = null, DefaultStreamsDestinations = null, DefaultDatasetsConfiguration = null, DefaultEventsConfiguration = null, DefaultStreamsConfiguration = null, DefaultManagementGroupsConfiguration = null, Datasets = distinctDatasets.ConvertAll(d => new DiscoveredAssetDataset { Name = GetAssetResourceName(d.DataSetName), TypeRef = d.DataSetType, DataSource = d.DataSetRootNodeId, DataSetConfiguration = null, DataPoints = d.OpcNodes!.Select(n => new DiscoveredAssetDatasetDataPoint { Name = n.DisplayName!, // Name of property in message/schema DataSource = n.Id!, DataPointConfiguration = null, TypeRef = n.TypeDefinitionId }).ToList() #if OLD ,Destinations = [ new DatasetDestination { Target = DatasetTarget.Mqtt, Configuration = new DestinationConfiguration { Qos = _options.Value.DefaultQualityOfService == Furly.Extensions.Messaging.QoS.AtMostOnce ? QoS.Qos0 : QoS.Qos1, Topic = CreateTopic(), Retain = _options.Value.DefaultMessageRetention == true ? Retain.Keep : Retain.Never, Ttl = (ulong?)_options.Value.DefaultMessageTimeToLive?.TotalSeconds } } ] #endif }), EventGroups = distinctEventGroups.ConvertAll(d => new DiscoveredAssetEventGroup { Name = GetAssetResourceName(d.DataSetName), TypeRef = d.DataSetType, DataSource = d.DataSetRootNodeId, EventGroupConfiguration = null, DefaultEventsDestinations = null, Events = d.OpcNodes!.Select(n => new DiscoveredAssetEvent { Name = n.DisplayName!, // Event name DataSource = n.Id!, // EventNotifier node id TypeRef = n.TypeDefinitionId, EventConfiguration = null, Destinations = [ new EventStreamDestination { Target = EventStreamTarget.Mqtt, Configuration = new DestinationConfiguration { Qos = _options.Value.DefaultQualityOfService == Furly.Extensions.Messaging.QoS.AtMostOnce ? QoS.Qos0 : QoS.Qos1, Topic = CreateTopic(n.DisplayName), Retain = _options.Value.DefaultMessageRetention == true ? Retain.Keep : Retain.Never, Ttl = (ulong?)_options.Value.DefaultMessageTimeToLive?.TotalSeconds } } ] }).ToList() }), ManagementGroups = distinctManagementGroups.ConvertAll(d => new DiscoveredAssetManagementGroup { Name = GetAssetResourceName(d.DataSetName), TypeRef = d.DataSetType, DefaultTimeoutInSeconds = null, DataSource = d.DataSetRootNodeId, DefaultTopic = null, ManagementGroupConfiguration = null, Actions = d.OpcNodes!.Select(n => new DiscoveredAssetManagementGroupAction { Name = n.DisplayName!, // Name of command in schema ActionType = AssetManagementGroupActionType.Call, TargetUri = n.Id!, // Method id of the instance declaration TypeRef = n.TypeDefinitionId, // Method type ref on the object type ref TimeoutInSeconds = null, Topic = CreateTopic(n.DisplayName), ActionConfiguration = ConvertActionConfiguration(n.MethodMetadata!) }).ToList() }), Streams = null }; // TODO: Add attributes and other information from properties if (_logger.IsDebugLogConfigurationEnabled()) { _logger.ReportingNewDiscoveredAsset(uniqueAssetName, assetId, assetTypeRef, JsonSerializer.Serialize(dAsset, kDebugSerializerOptions)); } await _client.ReportDiscoveredAssetAsync(resource.DeviceName, resource.EndpointName, uniqueAssetName, dAsset, cancellationToken: ct).ConfigureAwait(false); } static string GetAssetResourceName(string? resourceName, string? innerName = null) { innerName = string.IsNullOrEmpty(innerName) ? null : "." + innerName; resourceName = string.IsNullOrWhiteSpace(resourceName) ? "Default" : MakeValidName(resourceName, innerName); return innerName != null ? resourceName + innerName : resourceName; } } /// /// Run endpoint discovery for the given endpoint uri. /// /// /// /// /// private async ValueTask RunEndpointDiscoveryAsync(DeviceEndpointResource resource, Uri endpointUri, CancellationToken ct) { GetEndpointTypeAndVersion(out var endpointType, out var endpointTypeVersion); var dCurrentDevice = new DiscoveredDevice { ExternalDeviceId = resource.Device.ExternalDeviceId, Model = resource.Device.Model, Manufacturer = resource.Device.Manufacturer, OperatingSystem = resource.Device.OperatingSystem, OperatingSystemVersion = resource.Device.OperatingSystemVersion, Attributes = resource.Device.Attributes }; // First run endpoint discovery to find endpoints on the current device var endpoints = await _discovery.FindEndpointsAsync( endpointUri, findServersOnNetwork: false, ct: ct).ConfigureAwait(false); // Now report all endpoints on the network that are not part of current device var alreadyFound = endpoints .Select(e => e.Description?.Server?.ApplicationUri) .Where(uri => uri != null) .Distinct() .ToHashSet(); var servers = await _discovery.FindEndpointsAsync(endpointUri, findServersOnNetwork: true, ct: ct).ConfigureAwait(false); var currentDeviceIsDiscoveryServer = false; foreach (var server in servers .Where(ep => ep.Description?.Server?.ApplicationUri != null && !alreadyFound.Contains(ep.Description.Server.ApplicationUri)) .GroupBy(ep => ep.Description.Server.ApplicationUri)) { var serverEndpoints = server.ToList(); Debug.Assert(serverEndpoints.Count > 0); currentDeviceIsDiscoveryServer = true; var applicationDescription = serverEndpoints[0].Description.Server; var serverDeviceId = "-" + server.Key.ToSha1Hash(); var deviceName = MakeValidArmResourceName( applicationDescription.ApplicationName.ToString(), serverDeviceId) .TrimEnd('-') + serverDeviceId; var dServerDevice = new DiscoveredDevice { ExternalDeviceId = serverDeviceId, Model = applicationDescription.ProductUri }; try { await ReportDiscoveredDeviceAsync(deviceName, dServerDevice, serverEndpoints, endpointType, endpointTypeVersion, ct: ct).ConfigureAwait(false); } catch (Exception ex) { _logger.FailedToReportDiscoveredServer(ex, deviceName); } } // Now update our device dCurrentDevice.Attributes ??= new Dictionary(); dCurrentDevice.Attributes.AddOrUpdate("LDS", currentDeviceIsDiscoveryServer.ToString()); await ReportDiscoveredDeviceAsync(resource.DeviceName, dCurrentDevice, endpoints, endpointType, endpointTypeVersion, resource, ct).ConfigureAwait(false); } /// /// Get endpoint type and version for new endpoints /// /// /// private void GetEndpointTypeAndVersion(out string endpointType, out string? endpointTypeVersion) { var type = _options.Value.AioDiscoveredDeviceEndpointType; endpointTypeVersion = _options.Value.AioDiscoveredDeviceEndpointTypeVersion; if (type == null) { var releaseVersion = GetType().Assembly.GetReleaseVersion(); endpointType = "Microsoft.OpcPublisher"; endpointTypeVersion = $"{releaseVersion.Major}.{releaseVersion.Minor}"; } else { endpointType = type; } } /// /// Report a new discovered device with the given endpoints /// /// /// /// /// /// /// /// /// private async ValueTask ReportDiscoveredDeviceAsync(string deviceName, DiscoveredDevice dDevice, IEnumerable endpoints, string endpointType, string? endpointTypeVersion, DeviceEndpointResource? resource = null, CancellationToken ct = default) { var newEndpoints = new Dictionary( StringComparer.OrdinalIgnoreCase); dDevice.Attributes ??= new Dictionary(); var newEndpointCount = 0; foreach (var ep in endpoints) { var desc = ep.Description; dDevice.Attributes.AddOrUpdate(nameof(desc.Server.ApplicationType), desc.Server.ApplicationType.ToString()); if (desc.Server.ApplicationName?.Text != null) { dDevice.Attributes.AddOrUpdate(nameof(desc.Server.ApplicationName), desc.Server.ApplicationName.Text); } if (desc.Server.ApplicationUri != null) { dDevice.Attributes.AddOrUpdate(nameof(desc.Server.ApplicationUri), desc.Server.ApplicationUri); } if (desc.Server.ProductUri != null) { dDevice.Attributes.AddOrUpdate(nameof(desc.Server.ProductUri), desc.Server.ProductUri); } if (desc.Server.DiscoveryProfileUri != null) { dDevice.Attributes.AddOrUpdate(nameof(desc.Server.DiscoveryProfileUri), desc.Server.DiscoveryProfileUri); } if (desc.Server.DiscoveryUrls?.Count > 0) { dDevice.Attributes.AddOrUpdate(nameof(desc.Server.DiscoveryUrls), string.Join(',', desc.Server.DiscoveryUrls)); } if (desc.Server.GatewayServerUri != null) { dDevice.Attributes.AddOrUpdate(nameof(desc.Server.GatewayServerUri), desc.Server.GatewayServerUri); } if (ep.Capabilities != null) { foreach (var cap in ep.Capabilities) { dDevice.Attributes.AddOrUpdate(cap.ToUpperInvariant(), "True"); } } var name = desc.SecurityMode.ToString(); if (desc.SecurityMode != MessageSecurityMode.None) { name = $"l{desc.SecurityLevel}.{name}"; if (!Uri.TryCreate(desc.SecurityPolicyUri, UriKind.Absolute, out var securityProfileUri) || securityProfileUri.Fragment.Length == 0 || securityProfileUri.Fragment[0] != '#') { continue; } name += $".{securityProfileUri.Fragment.AsSpan(1)}"; } if (desc.TransportProfileUri != Profiles.UaTcpTransport) { if (!Uri.TryCreate(desc.TransportProfileUri, UriKind.Absolute, out var transportProfileUri)) { continue; } var pathParts = transportProfileUri.PathAndQuery.Split('/'); if (pathParts.Length == 0) { continue; } name += $".{pathParts[pathParts.Length - 1]}"; } // Add desc.ServerCertificate somewhere var epModel = new DeviceEndpointConfiguration { Source = "Discovery", EndpointSecurityMode = desc.SecurityMode.ToServiceType(), EndpointSecurityPolicy = desc.SecurityPolicyUri }; var supportedAuthenticationMethods = GetSupportedAuthenticationMethods(desc); var uniqueName = MakeValidArmResourceName(name); if (newEndpoints.ContainsKey(uniqueName)) { continue; } var existing = resource?.Device.Endpoints?.Inbound?.FirstOrDefault(e => e.Key.Equals(uniqueName, StringComparison.OrdinalIgnoreCase)); if (existing.HasValue && existing.Value.Key != null) { // Merge discovered into existing endpoint information if (!string.IsNullOrEmpty(existing.Value.Value.AdditionalConfiguration)) { // Deserialize existing configuration var errors = new ValidationErrors(this); var epModelExisting = Deserialize(existing.Value.Value.AdditionalConfiguration, () => new DeviceEndpointConfiguration(), errors, resource!); if (epModelExisting != null) { epModelExisting.EndpointSecurityMode ??= epModel.EndpointSecurityMode; epModelExisting.EndpointSecurityPolicy ??= epModel.EndpointSecurityPolicy; epModelExisting.Source = "Discovery"; epModel = epModelExisting; } } uniqueName = existing.Value.Key; // Keep casing #if SKIP_ADDRESS_MISMATCH if (existing.Value.Value.Address != ep.AccessibleEndpointUrl) { continue; // Ignore if address does not match } #endif #if SKIP_EXISTING_ENDPOINTS continue; #endif } var additionalConfiguration = _serializer.SerializeToString(epModel); if (additionalConfiguration.Length > 512) { _logger.EndpointConfigurationTooLong(uniqueName, deviceName, additionalConfiguration.Length); } newEndpoints.Add(uniqueName, new DiscoveredDeviceInboundEndpoint { Address = SetEndpointUrl(ep.AccessibleEndpointUrl), EndpointType = endpointType, Version = endpointTypeVersion, SupportedAuthenticationMethods = supportedAuthenticationMethods, AdditionalConfiguration = additionalConfiguration }); newEndpointCount++; } if (newEndpointCount == 0) { _logger.NoEndpointsFound(deviceName); return; } dDevice.Endpoints = new DiscoveredDeviceEndpoints { Inbound = newEndpoints }; if (_logger.IsDebugLogConfigurationEnabled()) { _logger.ReportingNewDiscoveredDevice(deviceName, endpointType, JsonSerializer.Serialize(dDevice, kDebugSerializerOptions)); } await _client.ReportDiscoveredDeviceAsync(deviceName, dDevice, endpointType, cancellationToken: ct).ConfigureAwait(false); static List? GetSupportedAuthenticationMethods(EndpointDescription desc) { if (desc.UserIdentityTokens == null || desc.UserIdentityTokens.Count == 0) { return null; } var methods = new HashSet(); foreach (var token in desc.UserIdentityTokens) { switch (token.TokenType) { case UserTokenType.Anonymous: methods.Add(nameof(Method.Anonymous)); break; case UserTokenType.UserName: methods.Add(nameof(Method.UsernamePassword)); break; case UserTokenType.Certificate: methods.Add(nameof(Method.Certificate)); break; case UserTokenType.IssuedToken: // Not supported break; } } return methods.ToList(); } } /// /// Convert an Asset to a collection of published nodes entries /// /// /// /// /// /// internal async ValueTask> ToPublishedNodesAsync( ICollection devices, ICollection assets, ValidationErrors errors, CancellationToken ct) { var entries = new List(); var deviceLookup = devices.ToLookup(k => k.DeviceName); foreach (var asset in assets) { // Find the device and endpoint referenced by this asset var deviceRef = asset.Asset.DeviceRef; DeviceResource? deviceResource = null; InboundEndpointSchemaMapValue? endpoint = null; foreach (var device in deviceLookup[deviceRef.DeviceName]) { deviceResource = device; if (string.Equals(device.DeviceName, deviceRef.DeviceName, StringComparison.OrdinalIgnoreCase) && TryGetInboundEndpoint(device?.Device?.Endpoints, deviceRef.EndpointName, out endpoint)) { break; } } if (deviceResource == null) { errors.OnError(asset, kDeviceNotFoundErrorCode, "Device referenced by asset was not found"); continue; } if (endpoint == null) { errors.OnError(asset, kDeviceNotFoundErrorCode, "Endpoint referenced by asset was not found"); continue; } var deviceEndpointResource = new DeviceEndpointResource(deviceResource.DeviceName, deviceResource.Device, deviceRef.EndpointName); var endpointConfiguration = Deserialize(endpoint.AdditionalConfiguration, () => new DeviceEndpointConfiguration(), errors, deviceEndpointResource); if (endpointConfiguration == null) { continue; } // Asset identification var assetEndpoint = new PublishedNodesEntryModel { EndpointUrl = GetEndpointUrl(endpoint.Address), EndpointSecurityMode = endpointConfiguration.EndpointSecurityMode, EndpointSecurityPolicy = endpointConfiguration.EndpointSecurityPolicy, DumpConnectionDiagnostics = endpointConfiguration.DumpConnectionDiagnostics, DisableSubscriptionTransfer = endpointConfiguration.DisableSubscriptionTransfer, UseReverseConnect = endpointConfiguration.UseReverseConnect, // We map asset name to writer group as it contains writers for each of its // entities. This will be split per destination, but this is ok as the name // is retained and the Id property receives the unique group name. DataSetWriterGroup = asset.Asset.DisplayName ?? asset.Asset.Model ?? asset.AssetName, PublisherId = deviceResource.DeviceName, WriterGroupType = asset.Asset.AssetTypeRefs?.Count == 1 ? asset.Asset.AssetTypeRefs[0] : null, WriterGroupRootNodeId = asset.Asset.Attributes == null ? null : asset.Asset.Attributes.TryGetValue(kAssetIdAttribute, out var rootNodeId) ? rootNodeId?.ToString() : null, // And stick all unknown properties and attributes into the new extension section WriterGroupProperties = CollectAssetAndDeviceProperties(asset, deviceResource) // TODO In WoT side DataSetName is the Asset name. This also needs // to be fixed over there! }; var credentials = _client.GetEndpointCredentials(asset.Asset.DeviceRef.DeviceName, asset.Asset.DeviceRef.EndpointName, endpoint); assetEndpoint = AddEndpointCredentials(assetEndpoint, credentials, errors, deviceEndpointResource); if (asset.Asset.Datasets != null) { var dataSetAdditionalConfiguration = Deserialize(asset.Asset.DefaultDatasetsConfiguration, () => new PublishedNodesEntryModel { EndpointUrl = string.Empty }, errors, asset); if (dataSetAdditionalConfiguration != null) { dataSetAdditionalConfiguration = WithEndpoint(dataSetAdditionalConfiguration, assetEndpoint); foreach (var dataset in asset.Asset.Datasets) { var datasetResource = new DataSetResource(asset.AssetName, asset.Asset, dataset); await AddEntryForDataSetAsync(dataSetAdditionalConfiguration, datasetResource, entries, errors, ct).ConfigureAwait(false); } } } if (asset.Asset.EventGroups != null) { var eventAdditionalConfiguration = Deserialize(asset.Asset.DefaultEventsConfiguration, () => new PublishedNodesEntryModel { EndpointUrl = string.Empty }, errors, asset); if (eventAdditionalConfiguration != null) { eventAdditionalConfiguration = WithEndpoint(eventAdditionalConfiguration, assetEndpoint); foreach (var eventGroup in asset.Asset.EventGroups) { var eventGroupResource = new EventGroupResource(asset.AssetName, asset.Asset, eventGroup); await AddEntryForEventGroupAsync(eventAdditionalConfiguration, eventGroupResource, entries, errors, ct).ConfigureAwait(false); } } } if (asset.Asset.ManagementGroups != null) { var managementGroupConfiguration = Deserialize(asset.Asset.DefaultManagementGroupsConfiguration, () => new PublishedNodesEntryModel { EndpointUrl = string.Empty }, errors, asset); if (managementGroupConfiguration != null) { managementGroupConfiguration = WithEndpoint(managementGroupConfiguration, assetEndpoint); foreach (var managementGroup in asset.Asset.ManagementGroups) { var managementGroupResource = new ManagementGroupResource(asset.AssetName, asset.Asset, managementGroup); await AddEntryForManagementGroupAsync(managementGroupConfiguration, managementGroupResource, entries, errors, ct).ConfigureAwait(false); } } } if (asset.Asset.Streams != null) { foreach (var stream in asset.Asset.Streams) { var streamResource = new StreamResource(asset.AssetName, asset.Asset, stream); errors.OnError(streamResource, kNotSupportedErrorCode, "Streams not supported yet"); } } } return entries; } /// /// Create extension fields for attributes and properties that do not exist in our models /// /// /// /// internal static Dictionary? CollectAssetAndDeviceProperties( AssetResource asset, DeviceResource device) { var fields = new Dictionary(); static void Add(Dictionary fields, string key, VariantValue? value) { if (!VariantValue.IsNullOrNullValue(value)) { fields.AddOrUpdate(key, value); } } if (device.Device.Attributes != null) { foreach (var attr in device.Device.Attributes) { Add(fields, attr.Key, attr.Value); } } Add(fields, nameof(Device.ExternalDeviceId), device.Device.ExternalDeviceId); Add(fields, nameof(Device.Model), device.Device.Model); Add(fields, nameof(Device.Manufacturer), device.Device.Manufacturer); Add(fields, nameof(Device.OperatingSystem), device.Device.OperatingSystem); Add(fields, nameof(Device.OperatingSystemVersion), device.Device.OperatingSystemVersion); Add(fields, nameof(Device.Version), device.Device.Version); if (asset.Asset.Attributes != null) { foreach (var attr in asset.Asset.Attributes) { Add(fields, attr.Key, attr.Value); } } Add(fields, nameof(Asset.ExternalAssetId), asset.Asset.ExternalAssetId); Add(fields, nameof(Asset.HardwareRevision), asset.Asset.HardwareRevision); Add(fields, nameof(Asset.Manufacturer), asset.Asset.Manufacturer); Add(fields, nameof(Asset.ManufacturerUri), asset.Asset.ManufacturerUri); Add(fields, nameof(Asset.Model), asset.Asset.Model); Add(fields, nameof(Asset.DisplayName), asset.Asset.DisplayName); Add(fields, nameof(Asset.ProductCode), asset.Asset.ProductCode); Add(fields, nameof(Asset.SerialNumber), asset.Asset.SerialNumber); Add(fields, nameof(Asset.SoftwareRevision), asset.Asset.SoftwareRevision); Add(fields, nameof(Asset.Version), asset.Asset.Version); Add(fields, nameof(Asset.DocumentationUri), asset.Asset.DocumentationUri); Add(fields, nameof(Asset.Description), asset.Asset.Description); if (fields.Count == 0) { return null; } return fields; } /// /// Add authentication for the endpoint to the entry /// /// /// /// /// private static PublishedNodesEntryModel AddEndpointCredentials( PublishedNodesEntryModel template, EndpointCredentials authentication, ValidationErrors errors, DeviceEndpointResource resource) { template.OpcAuthenticationMode = OpcAuthenticationMode.Anonymous; if (authentication == null) { return template; } switch (authentication.AuthenticationMethod) { case Method.Certificate: if (string.IsNullOrWhiteSpace(authentication.ClientCertificate)) { errors.OnError(resource, kAuthenticationValueMissing, "Client certificate missing"); break; } return template with { OpcAuthenticationMode = OpcAuthenticationMode.Certificate, OpcAuthenticationUsername = authentication.ClientCertificate }; case Method.UsernamePassword: if (string.IsNullOrWhiteSpace(authentication.Username) || string.IsNullOrWhiteSpace(authentication.Password)) { errors.OnError(resource, kAuthenticationValueMissing, "User name or password missing"); break; } return template with { OpcAuthenticationMode = OpcAuthenticationMode.UsernamePassword, OpcAuthenticationUsername = authentication.Username, OpcAuthenticationPassword = authentication.Password }; } return template; } /// /// Adds a new entry for a dataset. Will not add one if configuration parsing fails. /// This does not apply to opc nodes, if any fail to validate, there will still be /// an entry, but the status will reflect this error. /// /// /// /// /// /// private ValueTask AddEntryForDataSetAsync(PublishedNodesEntryModel template, DataSetResource resource, List entries, ValidationErrors errors, CancellationToken ct) { ct.ThrowIfCancellationRequested(); if (resource.DataSet.DataPoints == null || resource.DataSet.DataPoints.Count == 0) { // Nothing to do return ValueTask.CompletedTask; } // Map dataset configuration on top of entry var additionalConfiguration = Deserialize(resource.DataSet.DatasetConfiguration, () => new DataSetConfiguration(), errors, resource); if (additionalConfiguration == null) { return ValueTask.CompletedTask; } // TODO: Resolve typeref to ensure it exists var nodes = new List(); // Map datapoints to OPC nodes foreach (var datapoint in resource.DataSet.DataPoints) { var nodeFromAdditionalConfiguration = Deserialize( datapoint.DataPointConfiguration, () => new DataSetDataPointConfiguration(), errors, resource); if (nodeFromAdditionalConfiguration == null) { continue; } nodes.Add(nodeFromAdditionalConfiguration with { Id = datapoint.DataSource, DisplayName = datapoint.Name, DataSetFieldId = datapoint.Name, FetchDisplayName = false, TypeDefinitionId = datapoint.TypeRef }); } var entry = CreateEntryForAssetResource(template, additionalConfiguration, nodes); entry = AddDestination(entry, resource.Asset.DefaultDatasetsDestinations, resource.DataSet.Destinations, errors, resource); entries.Add(entry with { // Dataset writer id maps to name DataSetWriterId = resource.DataSet.Name, // Dataset name as well (-> source of the dataset) DataSetName = resource.DataSet.Name, // Root node id is the data source of the dataset DataSetRootNodeId = resource.DataSet.DataSource, // Type is the dataset typeref DataSetType = resource.DataSet.TypeRef, // Source is the data set source uri DataSetSourceUri = CreateSourceUri(resource.Asset, resource.DataSet.DataSource), // Subject is the asset uuid and dataset name DataSetSubject = CreateSubject(resource.Asset, resource.DataSet.Name), // Dataset configuration overrides DataSetKeyFrameCount = entry.DataSetKeyFrameCount ?? 10, SendKeepAliveDataSetMessages = entry.SendKeepAliveDataSetMessages ?? true, SendKeepAliveAsKeyFrameMessages = entry.SendKeepAliveAsKeyFrameMessages ?? true, MaxKeepAliveCount = entry.MaxKeepAliveCount ?? 30 }); return ValueTask.CompletedTask; } /// /// Add an entry for the event. Will not add one if validation of content fails. /// /// /// /// /// /// /// private ValueTask AddEntryForEventGroupAsync(PublishedNodesEntryModel template, EventGroupResource resource, List entries, ValidationErrors errors, CancellationToken ct) { ct.ThrowIfCancellationRequested(); if (resource.EventGroup.Events == null || resource.EventGroup.Events.Count == 0) { // Nothing to do return ValueTask.CompletedTask; } // Map dataset configuration on top of entry var additionalConfiguration = Deserialize(resource.EventGroup.EventGroupConfiguration, () => new EventGroupConfiguration(), errors, resource); if (additionalConfiguration == null) { return ValueTask.CompletedTask; } // TODO: Resolve typeref to ensure it exists // Group events by event notifier (data source) foreach (var @event in resource.EventGroup.Events) { var eventResource = new EventResource(resource.AssetName, resource.Asset, resource.EventGroup, @event); // Map event configuration on top of entry var eventConfiguration = Deserialize(@event.EventConfiguration, () => new EventConfiguration(), errors, eventResource); if (eventConfiguration == null) { continue; } var eventFilter = eventConfiguration.EventFilter ?? new EventFilterModel(); if (!string.IsNullOrEmpty(@event.TypeRef)) { // TODO: Resolve typeref to ensure it exists eventFilter.TypeDefinitionId = @event.TypeRef; } var node = new OpcNodeModel { Id = @event.DataSource, // Event notifier DisplayName = @event.Name, DataSetFieldId = @event.Name, TypeDefinitionId = @event.TypeRef, FetchDisplayName = false, EventFilter = eventFilter, ConditionHandling = eventConfiguration.ConditionHandling, SkipFirst = eventConfiguration.SkipFirst, QueueSize = eventConfiguration.QueueSize, DiscardNew = eventConfiguration.DiscardNew }; var entry = CreateEntryForAssetResource(template, additionalConfiguration, [node]); entry = AddDestination(entry, resource.Asset.DefaultEventsDestinations, resource.EventGroup.DefaultEventsDestinations, @event.Destinations, errors, resource); entries.Add(entry with { // Dataset writer id maps to event group name, but will be broken down later. DataSetWriterId = resource.EventGroup.Name, // Dataset name is the name of the object that is the subject of the event DataSetName = resource.EventGroup.Name, // Root node id is the object id that is the subject of the event DataSetRootNodeId = resource.EventGroup.DataSource, // Type ref is the typeref of the object that is the subject of the event DataSetType = resource.EventGroup.TypeRef, // Source is the device uuid and event notifier (emitting the event) DataSetSourceUri = CreateSourceUri(resource.Asset, @event.DataSource), // Subject is the asset uuid and event group name (object) DataSetSubject = CreateSubject(resource.Asset, resource.EventGroup.Name, @event.Name), // Event configuration overrides MaxKeepAliveCount = entry.MaxKeepAliveCount ?? 30 }); } return ValueTask.CompletedTask; } /// /// Add an entry for the event. Will not add one if validation of content fails. /// /// /// /// /// /// /// private ValueTask AddEntryForManagementGroupAsync(PublishedNodesEntryModel template, ManagementGroupResource resource, List entries, ValidationErrors errors, CancellationToken ct) { ct.ThrowIfCancellationRequested(); // Map event configuration on top of entry var additionalConfiguration = Deserialize( resource.ManagementGroup.ManagementGroupConfiguration, () => new ManagementGroupConfiguration(), errors, resource); if (additionalConfiguration == null) { return ValueTask.CompletedTask; } if (resource.ManagementGroup.Actions == null || resource.ManagementGroup.Actions.Count == 0) { return ValueTask.CompletedTask; } // map actions to nodes foreach (var action in resource.ManagementGroup.Actions .GroupBy(a => a.Topic ?? resource.ManagementGroup.DefaultTopic)) { var nodes = new List(); foreach (var a in action) { var actionResource = new ManagementActionResource(resource.AssetName, resource.Asset, resource.ManagementGroup, a); nodes.Add(new OpcNodeModel { Id = a.TargetUri, DisplayName = a.Name, DataSetFieldId = a.Name, TypeDefinitionId = a.TypeRef, FetchDisplayName = false, MethodMetadata = ConvertActionConfiguration(a.ActionConfiguration, errors, actionResource) }); } var entry = CreateEntryForAssetResource(template, additionalConfiguration, nodes); entries.Add(entry with { // Writer id maps to the name of the management group DataSetWriterId = resource.ManagementGroup.Name, // The name as well (target of the actions) DataSetName = resource.ManagementGroup.Name, // Root node id is the data source of the management group DataSetRootNodeId = resource.ManagementGroup.DataSource, // Type ref is the type of the object that has the methods DataSetType = resource.ManagementGroup.TypeRef, // Source is the data set source uri DataSetSourceUri = CreateSourceUri(resource.Asset, resource.ManagementGroup.DataSource), // Subject is the asset uuid and management group name DataSetSubject = CreateSubject(resource.Asset, resource.ManagementGroup.Name), // Add topic QueueName = action.Key }); } return ValueTask.CompletedTask; } /// /// Create entry for a management group in the asset /// /// /// /// /// private static PublishedNodesEntryModel CreateEntryForAssetResource( PublishedNodesEntryModel endpointTemplate, ManagementGroupConfiguration entityTemplate, List nodes) { return endpointTemplate with { // // Set defaults for iot operations, there will never be any different configuration // allowed in the resource of AIO // BatchSize = 0, BatchTriggerInterval = 0, BatchTriggerIntervalTimespan = null, MessagingMode = MessagingMode.SingleDataSet, DataSetFetchDisplayNames = false, MessageEncoding = entityTemplate.MessageEncoding == MessageEncoding.Avro ? MessageEncoding.Avro : MessageEncoding.Json, OpcNodes = nodes, DataSetClassId = entityTemplate.DataSetClassId, Priority = entityTemplate.Priority, }; } /// /// Create entry for a dataset in the asset /// /// /// /// /// private static PublishedNodesEntryModel CreateEntryForAssetResource( PublishedNodesEntryModel endpointTemplate, DataSetConfiguration additionalConfiguration, List nodes) { return endpointTemplate with { // // Set defaults for iot operations, there will never be any different configuration // allowed in the resource of AIO // BatchSize = 0, BatchTriggerInterval = 0, BatchTriggerIntervalTimespan = null, MessagingMode = MessagingMode.SingleDataSet, DataSetFetchDisplayNames = false, MessageEncoding = additionalConfiguration.MessageEncoding == MessageEncoding.Avro ? MessageEncoding.Avro : MessageEncoding.Json, OpcNodes = nodes, // Dataset configuration DataSetPublishingInterval = additionalConfiguration.PublishingInterval, DataSetSamplingInterval = additionalConfiguration.SamplingInterval, DataSetClassId = additionalConfiguration.DataSetClassId, DataSetKeyFrameCount = additionalConfiguration.KeyFrameCount, DataSetWriterWatchdogBehavior = additionalConfiguration.DataSetWriterWatchdogBehavior, SendKeepAliveDataSetMessages = additionalConfiguration.SendKeepAliveDataSetMessages, SendKeepAliveAsKeyFrameMessages = additionalConfiguration.SendKeepAliveAsKeyFrameMessages, MaxKeepAliveCount = additionalConfiguration.MaxKeepAliveCount, RepublishAfterTransfer = additionalConfiguration.RepublishAfterTransfer, Priority = additionalConfiguration.Priority }; } /// /// Create entry for an event in the asset /// /// /// /// /// private static PublishedNodesEntryModel CreateEntryForAssetResource( PublishedNodesEntryModel endpointTemplate, EventGroupConfiguration additionalConfiguration, List nodes) { return endpointTemplate with { // // Set defaults for iot operations, there will never be any different configuration // allowed in the resource of AIO // BatchSize = 0, BatchTriggerInterval = 0, BatchTriggerIntervalTimespan = null, MessagingMode = MessagingMode.SingleDataSet, DataSetFetchDisplayNames = false, MessageEncoding = additionalConfiguration.MessageEncoding == MessageEncoding.Avro ? MessageEncoding.Avro : MessageEncoding.Json, OpcNodes = nodes, // Dataset configuration DataSetPublishingInterval = additionalConfiguration.PublishingInterval, DataSetSamplingInterval = additionalConfiguration.SamplingInterval, DataSetKeyFrameCount = additionalConfiguration.KeyFrameCount, DataSetClassId = additionalConfiguration.DataSetClassId, DataSetWriterWatchdogBehavior = additionalConfiguration.DataSetWriterWatchdogBehavior, SendKeepAliveDataSetMessages = additionalConfiguration.SendKeepAliveDataSetMessages, SendKeepAliveAsKeyFrameMessages = additionalConfiguration.SendKeepAliveAsKeyFrameMessages, MaxKeepAliveCount = additionalConfiguration.MaxKeepAliveCount, RepublishAfterTransfer = additionalConfiguration.RepublishAfterTransfer, Priority = additionalConfiguration.Priority }; } /// /// Copy the device endpoint resource to the template and return a new entry /// /// /// /// /// Adds a new entry for a dataset. Will not add one if configuration parsing fails. /// This does not apply to opc nodes, if any fail to validate, there will still be /// an entry, but the status will reflect this error. /// private static PublishedNodesEntryModel WithEndpoint(PublishedNodesEntryModel template, PublishedNodesEntryModel deviceEndpoint) { return template with { // Map the configured endpoint configuration into the event/dataset template EndpointUrl = deviceEndpoint.EndpointUrl, EndpointSecurityMode = deviceEndpoint.EndpointSecurityMode, EndpointSecurityPolicy = deviceEndpoint.EndpointSecurityPolicy, DumpConnectionDiagnostics = deviceEndpoint.DumpConnectionDiagnostics, UseReverseConnect = deviceEndpoint.UseReverseConnect, OpcAuthenticationMode = deviceEndpoint.OpcAuthenticationMode, OpcAuthenticationPassword = deviceEndpoint.OpcAuthenticationPassword, OpcAuthenticationUsername = deviceEndpoint.OpcAuthenticationUsername, UseSecurity = null, EncryptedAuthPassword = null, EncryptedAuthUsername = null, // Add the fixed asset information DataSetWriterGroup = deviceEndpoint.DataSetWriterGroup, PublisherId = deviceEndpoint.PublisherId, WriterGroupType = deviceEndpoint.WriterGroupType, WriterGroupRootNodeId = deviceEndpoint.WriterGroupRootNodeId, WriterGroupProperties = deviceEndpoint.WriterGroupProperties }; } /// /// Add dataset destination configuration /// /// /// /// /// /// private static PublishedNodesEntryModel AddDestination(PublishedNodesEntryModel entry, List? defaultDestinations, List? destinations, ValidationErrors errors, Resource resource) { entry = WithoutDestinationConfiguration(entry); if (destinations?.Count > 1) { // TODO: We could generate 2 or more entries each with different destination errors.OnError(resource, kTooManyDestinationsError, "More than 1 destination is not allowed for datasets. Using Mqtt"); } var destination = destinations?.FirstOrDefault(); if (destination == null) { if (defaultDestinations?.Count > 1) { errors.OnError(resource, kTooManyDestinationsError, "More than 1 default destination is not allowed for datasets. Using Mqtt"); } destination = defaultDestinations? .FirstOrDefault(d => d.Target == DatasetTarget.Mqtt); } if (destination == null) { return entry with { WriterGroupTransport = WriterGroupTransport.AioMqtt }; } var configuration = destination.Configuration; switch (destination.Target) { case DatasetTarget.BrokerStateStore: return entry with { WriterGroupTransport = WriterGroupTransport.AioDss, QueueName = configuration.Key, MessageTtlTimespan = configuration.Ttl == null ? null : TimeSpan.FromSeconds(configuration.Ttl.Value), }; case DatasetTarget.Mqtt: return entry with { WriterGroupTransport = WriterGroupTransport.AioMqtt, QualityOfService = configuration.Qos switch { QoS.Qos0 => Furly.Extensions.Messaging.QoS.AtMostOnce, QoS.Qos1 => Furly.Extensions.Messaging.QoS.AtLeastOnce, _ => null }, MessageRetention = configuration.Retain switch { Retain.Keep => true, Retain.Never => false, _ => null }, QueueName = configuration.Topic, MessageTtlTimespan = configuration.Ttl == null ? null : TimeSpan.FromSeconds(configuration.Ttl.Value), MetaDataQueueName = configuration.Topic, MetaDataRetention = configuration.Retain switch { Retain.Keep => true, Retain.Never => false, _ => null }, MetaDataTtlTimespan = configuration.Ttl == null ? null : TimeSpan.FromSeconds(configuration.Ttl.Value) }; case DatasetTarget.Storage: return entry with { WriterGroupTransport = WriterGroupTransport.FileSystem, QueueName = configuration.Path }; } return entry; } /// /// Add event and stream destination configuration /// /// /// /// /// /// /// private static PublishedNodesEntryModel AddDestination(PublishedNodesEntryModel entry, List? defaultDestinations, List? groupDestinations, List? destinations, ValidationErrors errors, Resource resource) { entry = WithoutDestinationConfiguration(entry); if (destinations?.Count > 1) { errors.OnError(resource, kTooManyDestinationsError, "More than 1 destination is not allowed for events. Using Mqtt"); } var destination = destinations? .FirstOrDefault(d => d.Target == EventStreamTarget.Mqtt); if (destination == null) { if (groupDestinations?.Count > 1) { errors.OnError(resource, kTooManyDestinationsError, "More than 1 destination is not allowed for event groups. Using Mqtt"); } destination = groupDestinations? .FirstOrDefault(d => d.Target == EventStreamTarget.Mqtt); } if (destination == null) { if (defaultDestinations?.Count > 1) { errors.OnError(resource, kTooManyDestinationsError, "More than 1 default destination is not allowed for events. Using Mqtt"); } destination = defaultDestinations? .FirstOrDefault(d => d.Target == EventStreamTarget.Mqtt); } if (destination == null) { return entry with { WriterGroupTransport = WriterGroupTransport.AioMqtt }; } var configuration = destination.Configuration; switch (destination.Target) { case EventStreamTarget.Mqtt: return entry with { WriterGroupTransport = WriterGroupTransport.AioMqtt, QualityOfService = configuration.Qos switch { QoS.Qos0 => Furly.Extensions.Messaging.QoS.AtMostOnce, QoS.Qos1 => Furly.Extensions.Messaging.QoS.AtLeastOnce, _ => null }, MessageRetention = configuration.Retain switch { Retain.Keep => true, Retain.Never => false, _ => null }, QueueName = configuration.Topic, MessageTtlTimespan = configuration.Ttl == null ? null : TimeSpan.FromSeconds(configuration.Ttl.Value), MetaDataQueueName = configuration.Topic, MetaDataRetention = configuration.Retain switch { Retain.Keep => true, Retain.Never => false, _ => null }, MetaDataTtlTimespan = configuration.Ttl == null ? null : TimeSpan.FromSeconds(configuration.Ttl.Value) }; case EventStreamTarget.Storage: return entry with { WriterGroupTransport = WriterGroupTransport.FileSystem, QueueName = configuration.Path }; } return entry; } /// /// Remove the destination configuration /// /// /// private static PublishedNodesEntryModel WithoutDestinationConfiguration( PublishedNodesEntryModel entry) { return entry with { WriterGroupMessageRetention = null, WriterGroupMessageTtlTimepan = null, WriterGroupQualityOfService = null, WriterGroupQueueName = null, DataSetRouting = null, QualityOfService = null, MessageRetention = null, MessageTtlTimespan = null, QueueName = null, }; } /// /// Run network discovery if configured /// /// /// internal async Task RunDeviceDiscoveryAsync(CancellationToken ct) { if (_options.Value.AioNetworkDiscoveryMode == null || _options.Value.AioNetworkDiscoveryMode == DiscoveryMode.Off) { _logger.NetworkDiscoveryDisabled(); return; } var progress = new ProgressLogger(_logger); var request = new DiscoveryRequestModel { Discovery = _options.Value.AioNetworkDiscoveryMode.Value, Configuration = _options.Value.AioNetworkDiscovery }; GetEndpointTypeAndVersion(out var endpointType, out var endpointTypeVersion); while (!ct.IsCancellationRequested) { try { _logger.RunningNetworkDiscovery(); var servers = await _discovery.FindServersAsync(request, progress, ct) .ConfigureAwait(false); var set = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (var server in servers .Where(ep => ep.Description?.Server?.ApplicationUri != null) .GroupBy(ep => ep.Description.Server.ApplicationUri)) { if (!set.Add(server.Key) || _devices.Values.Any(d => d.Device.Attributes?.TryGetValue( nameof(ApplicationDescription.ApplicationUri), out var uri) == true && string.Equals(uri, server.Key, StringComparison.OrdinalIgnoreCase))) { _logger.DeviceAlreadyPresentSkipping(server.Key); continue; } var endpoints = server.ToList(); Debug.Assert(endpoints.Count > 0); var applicationDescription = endpoints[0].Description.Server; var serverDeviceId = "-" + server.Key.ToSha1Hash(); var deviceName = MakeValidArmResourceName( applicationDescription.ApplicationName.ToString(), serverDeviceId) .TrimEnd('-') + serverDeviceId; var dServerDevice = new DiscoveredDevice { ExternalDeviceId = serverDeviceId, Model = applicationDescription.ProductUri }; try { await ReportDiscoveredDeviceAsync(deviceName, dServerDevice, endpoints, endpointType, endpointTypeVersion, ct: ct).ConfigureAwait(false); } catch (Exception ex) { _logger.FailedToReportDiscoveredServer(ex, deviceName); } } _logger.NetworkDiscoveryComplete(); if (!(_options.Value.AioNetworkDiscoveryInterval > TimeSpan.Zero)) { _logger.NetworkDiscoveryConfiguredToOnlyRunOnce(); break; } await Task.Delay(_options.Value.AioNetworkDiscoveryInterval.Value, ct).ConfigureAwait(false); } catch (OperationCanceledException) { break; } catch (Exception ex) { _logger.UnexpectedErrorDuringNetworkDiscovery(ex); } } } /// /// Run discovery for all known devices /// /// /// internal async Task RunAssetDiscoveryAsync(CancellationToken ct) { while (!ct.IsCancellationRequested) { var lastListVersion = _lastDeviceListVersion; try { _logger.RunningDiscoveryForAllDevices(); var errors = new ValidationErrors(this); foreach (var device in _devices.Values.ToList()) { if ((device.Device.Endpoints?.Inbound) == null) { continue; } var deviceDiscoveryComplete = false; foreach (var endpoint in device.Device.Endpoints.Inbound) { var deviceEndpointResource = new DeviceEndpointResource(device.DeviceName, device.Device, endpoint.Key); var url = GetEndpointUrl(endpoint.Value.Address); if (!Uri.TryCreate(url, UriKind.Absolute, out var endpointUri)) { errors.OnError(deviceEndpointResource, kInvalidEndpointUrl, "Invalid endpoint URL: " + url); continue; } var endpointConfiguration = Deserialize(endpoint.Value.AdditionalConfiguration, () => new DeviceEndpointConfiguration(), errors, deviceEndpointResource); if (endpointConfiguration == null) { continue; } // Test connection var canConnectToEndpoint = await TestConnectionAsync(deviceEndpointResource, endpoint.Value, endpointConfiguration, errors, ct).ConfigureAwait(false); if (!canConnectToEndpoint) { continue; } if (endpointConfiguration.RunAssetDiscovery == true && endpointConfiguration.AssetTypes?.Count > 0) { // Run discovery try { await RunDiscoveryUsingTypesAsync(deviceEndpointResource, endpointConfiguration, errors, ct).ConfigureAwait(false); } catch (Exception ex) { errors.OnError(deviceEndpointResource, kDiscoveryError, ex.Message); _logger.FailedToRunDiscoveryForDevice(ex, device.DeviceName); } } if (endpointConfiguration.Source == null && endpointConfiguration.EndpointSecurityMode == SecurityMode.None && !deviceDiscoveryComplete) { try { await RunEndpointDiscoveryAsync(deviceEndpointResource, endpointUri, ct).ConfigureAwait(false); deviceDiscoveryComplete = true; } catch (Exception ex) { errors.OnError(deviceEndpointResource, kDiscoveryError, ex.Message); _logger.FailedToRunEndpointDiscoveryForDevice(ex, device.DeviceName); } } } // Compare last device list version, if version changed, stop and continue on // next timer fired. This will settle the changes and limit resource usage. if (_lastDeviceListVersion != lastListVersion) { _logger.RunningDiscoveryInterrupted(); break; } } await errors.ReportAsync(ct).ConfigureAwait(false); } catch (OperationCanceledException) { break; } catch (Exception ex) { _logger.UnexpectedErrorDuringDiscovery(ex); } if (_lastDeviceListVersion == lastListVersion) { _logger.RunningDiscoveryCompleted(); _trigger.Reset(); } try { await _trigger.WaitAsync(ct).ConfigureAwait(false); } catch (OperationCanceledException) { break; } catch (Exception ex) { _logger.UnexpectedErrorDuringDiscovery(ex); } } } /// /// Test connectivity /// /// /// /// /// /// /// private async Task TestConnectionAsync(DeviceEndpointResource deviceEndpointResource, InboundEndpointSchemaMapValue endpoint, DeviceEndpointConfiguration endpointConfiguration, ValidationErrors errors, CancellationToken ct) { var assetEndpoint = new PublishedNodesEntryModel { EndpointUrl = GetEndpointUrl(endpoint.Address), EndpointSecurityMode = endpointConfiguration.EndpointSecurityMode, EndpointSecurityPolicy = endpointConfiguration.EndpointSecurityPolicy, DumpConnectionDiagnostics = endpointConfiguration.DumpConnectionDiagnostics, DisableSubscriptionTransfer = endpointConfiguration.DisableSubscriptionTransfer, UseReverseConnect = endpointConfiguration.UseReverseConnect }; var credentials = _client.GetEndpointCredentials(deviceEndpointResource.DeviceName, deviceEndpointResource.EndpointName, endpoint); assetEndpoint = AddEndpointCredentials(assetEndpoint, credentials, errors, deviceEndpointResource); var testConnection = await _connections.TestConnectionAsync(assetEndpoint.ToConnectionModel(), new TestConnectionRequestModel(), ct).ConfigureAwait(false); if (testConnection.ErrorInfo != null) { errors.OnError(deviceEndpointResource, kDiscoveryError, "Failed to connect to endpoint: " + AsString(testConnection.ErrorInfo)); _logger.FailedToConnectToDeviceEndpoint(deviceEndpointResource.DeviceName, deviceEndpointResource.EndpointName, testConnection.ErrorInfo); return false; } return true; } /// /// Create a topic for the asset and dataset /// /// /// private static string CreateTopic(string? extra = null) { // /opcua/{Encoding}/{MessageType}"); var builder = new StringBuilder() .Append('/') .Append('{').Append(PublisherConfig.RootTopicVariableName).Append('}') .Append('/') .Append('{').Append(PublisherConfig.WriterGroupVariableName).Append('}') .Append('/') .Append('{').Append(PublisherConfig.DataSetTopicPathVariableName).Append('}'); if (!string.IsNullOrEmpty(extra)) { builder = builder.Append('/').Append(Furly.Extensions.Messaging.TopicFilter.Escape(extra)); } if (builder.Length > 128) // Topic length limit in adr is 128 { builder.Length = 128; } return builder.ToString(); } /// /// Create cloud event source uri as per specification for azure iot operations /// Identifies the context in which the event happened. /// /// /// /// /// private string CreateSourceUri(Asset asset, string? dataSource = null) { var key = CreateDeviceKey(asset.DeviceRef.DeviceName, asset.DeviceRef.EndpointName); if (!_devices.TryGetValue(key, out var device)) { throw new ArgumentException("Device not found for asset", nameof(asset)); } var builder = new StringBuilder("ms-aio:") .Append(device.Device.ExternalDeviceId) .Append('_') .Append(asset.DeviceRef.EndpointName); if (!string.IsNullOrEmpty(dataSource)) { builder = builder.Append('/').Append(dataSource.UrlEncode()); } return builder.ToString(); } /// /// Create cloud event subject as per specification for azure iot operations /// Identifies what the event is about. /// /// /// /// /// /// private string CreateSubject(Asset asset, string subjectName, string? subSubject = null) { var builder = new StringBuilder(asset.ExternalAssetId) .Append('/') .Append(subjectName); if (!string.IsNullOrEmpty(subSubject)) { builder = builder.Append('/').Append(subSubject); } return builder.ToString(); } /// /// Deserialize configuration /// /// /// /// /// /// /// private T? Deserialize(string? configuration, Func createDefault, ValidationErrors errors, Resource resource) { try { T? result = default; if (configuration != null) { result = _serializer.Deserialize(configuration); } return result ??= createDefault(); } catch (Exception ex) { errors.OnError(resource, kJsonSerializationErrorCode + "." + ex.HResult.ToString(CultureInfo.InvariantCulture), ex.Message); return default; } } private static bool TryGetInboundEndpoint(DeviceEndpoints? endpoints, string endpointName, [NotNullWhen(true)] out InboundEndpointSchemaMapValue? endpoint) { endpoint = endpoints?.Inbound?.FirstOrDefault( ep => string.Equals(ep.Key, endpointName, StringComparison.OrdinalIgnoreCase)).Value; return endpoint != null; } /// /// Compress method metadata /// /// /// /// internal string? ConvertActionConfiguration(MethodMetadataModel methodMetadata, int compressionLevel = 0) { byte[] compressed; using (var input = new MemoryStream( _serializer.SerializeToMemory(methodMetadata).ToArray())) using (var result = new MemoryStream()) { using (var gs = new GZipStream(result, CompressionMode.Compress)) { input.CopyTo(gs); } compressed = result.ToArray(); } var json = JsonSerializer.Serialize(new ActionConfiguration { CompiledMetadata = compressed }); if (Encoding.UTF8.GetByteCount(json) > 512) // 512 is max size but we are leaving some room here { if (compressionLevel > 2) { return null; } // We send the object id but compress or fully remove the argument information return ConvertActionConfiguration(methodMetadata with { InputArguments = compressionLevel > 1 ? null : methodMetadata.InputArguments? .Select(a => new MethodMetadataArgumentModel { Name = a.Name, Type = new NodeModel { NodeId = a.Type.NodeId } }) .ToList(), OutputArguments = compressionLevel > 1 ? null : methodMetadata.OutputArguments? .Select(a => new MethodMetadataArgumentModel { Name = a.Name, Type = new NodeModel { NodeId = a.Type.NodeId } }) .ToList() }, ++compressionLevel); } return json; } /// /// Decompress method metadata /// /// /// /// /// internal MethodMetadataModel ConvertActionConfiguration(string? actionConfigurationJson, ValidationErrors errors, Resource resource) { if (actionConfigurationJson == null) { return new MethodMetadataModel(); } try { var actionConfiguration = Deserialize(actionConfigurationJson, () => new ActionConfiguration { CompiledMetadata = [] }, errors, resource); if (actionConfiguration?.CompiledMetadata == null || actionConfiguration.CompiledMetadata.Length == 0) { return new MethodMetadataModel(); } byte[] decompressed; using (var input = new MemoryStream(actionConfiguration.CompiledMetadata)) using (var output = new MemoryStream()) { using (var gs = new GZipStream(input, CompressionMode.Decompress)) { gs.CopyTo(output); } decompressed = output.ToArray(); } return _serializer.Deserialize(decompressed) ?? new MethodMetadataModel(); } catch (Exception ex) { errors.OnError(resource, kJsonSerializationErrorCode + "." + ex.HResult.ToString(CultureInfo.InvariantCulture), ex.Message); return new MethodMetadataModel(); } } private static bool TryGetInboundEndpoint(DeviceStatusEndpoint? endpoints, string endpointName, [NotNullWhen(true)] out DeviceStatusInboundEndpointSchemaMapValue? endpoint) { endpoint = endpoints?.Inbound?.FirstOrDefault( ep => string.Equals(ep.Key, endpointName, StringComparison.OrdinalIgnoreCase)).Value; return endpoint != null; } private static string CreateDeviceKey(string deviceName, string inboundEndpointName) => $"{deviceName}_{inboundEndpointName}"; private static string CreateAssetKey(string deviceName, string inboundEndpointName, string assetName) => $"{deviceName}_{inboundEndpointName}_{assetName}"; private static string MakeValidArmResourceName(string input, string? postFix = null) { var leaveRoom = postFix == null ? 0 : Encoding.UTF8.GetByteCount(postFix); Debug.Assert(leaveRoom < 63); // Convert to lowercase string sanitized = input.ToLowerInvariant(); // Ascii escape invalid characters with '-' sanitized = EscapeInvalid().Replace(sanitized, "-"); // Ensure it starts and ends with an alphanumeric character sanitized = EnsureAlphaStart().Replace(sanitized, ""); // Truncate to characters if necessary (63 max) var maxChars = 63 - leaveRoom; if (sanitized.Length > maxChars) { sanitized = sanitized.Substring(0, maxChars); } return sanitized; } private static string MakeValidName(string input, string? postFix = null) { var leaveRoom = postFix == null ? 0 : Encoding.UTF8.GetByteCount(postFix); var length = Encoding.UTF8.GetByteCount(input); // Truncate to characters if necessary (128 max) var maxChars = leaveRoom > 128 ? 0 : 128 - leaveRoom; if (length > maxChars) { return input.ToSha1Hash(); } return input; } /// /// Create string from error /// /// /// private static string AsString(ServiceResultModel errorInfo) { var str = new StringBuilder(); Append(str, errorInfo); return str.ToString(); static StringBuilder Append(StringBuilder builder, ServiceResultModel error) { builder = builder .Append(error.SymbolicId ?? error.StatusCode.ToString(CultureInfo.InvariantCulture)) .Append(':') .Append(error.ErrorMessage); if (error.Inner != null) { builder = builder.AppendLine("=>"); builder = Append(builder, error.Inner); } return builder; } } [GeneratedRegex("[^a-z0-9-]")] private static partial Regex EscapeInvalid(); [GeneratedRegex("^-+|-+$")] private static partial Regex EnsureAlphaStart(); /// /// Base resoure and corresponding resources /// internal abstract record class Resource(); internal record class DeviceResource(string DeviceName, Device Device) : Resource; internal record class AssetResource(string AssetName, Asset Asset) : Resource; internal record class DeviceEndpointResource(string DeviceName, Device Device, string EndpointName) : DeviceResource(DeviceName, Device); internal record class DataSetResource(string AssetName, Asset Asset, AssetDataset DataSet) : AssetResource(AssetName, Asset); internal record class EventGroupResource(string AssetName, Asset Asset, AssetEventGroup EventGroup) : AssetResource(AssetName, Asset); internal record class EventResource(string AssetName, Asset Asset, AssetEventGroup EventGroup, AssetEvent Event) : EventGroupResource(AssetName, Asset, EventGroup); internal record class StreamResource(string AssetName, Asset Asset, AssetStream Stream) : AssetResource(AssetName, Asset); internal record class ManagementGroupResource(string AssetName, Asset Asset, AssetManagementGroup ManagementGroup) : AssetResource(AssetName, Asset); internal record class ManagementActionResource(string AssetName, Asset Asset, AssetManagementGroup ManagementGroup, AssetManagementGroupAction Action) : ManagementGroupResource(AssetName, Asset, ManagementGroup); /// /// Collects validation errors /// internal sealed class ValidationErrors { /// /// Create error collector /// /// public ValidationErrors(AssetDeviceIntegration outer) { _outer = outer; } /// /// Collect error for a particular resource such as asset, dataset /// or device. /// /// /// /// public void OnError(Resource resource, string code, string error) { _outer._logger.EncounteredError(code, error, resource); switch (resource) { case DeviceEndpointResource dr: Add(dr, code, error); return; case DeviceResource d: Add(d, code, error); return; case DataSetResource d: Add(d, code, error); return; case EventResource e: Add(e, code, error); return; case EventGroupResource eg: Add(eg, code, error); return; case StreamResource e: Add(e, code, error); return; case ManagementActionResource e: Add(e, code, error); return; case ManagementGroupResource e: Add(e, code, error); return; case AssetResource a: Add(a, code, error); return; default: return; } } /// /// Report what is to be reported /// /// /// public async ValueTask ReportAsync(CancellationToken ct) { if (_devices.Count > 0 || _assets.Count > 0) { _outer._logger.ReportingStatus(_assets.Count, _devices.Count); } var client = _outer._client; foreach (var (_, status) in _devices) { try { await client.UpdateDeviceStatusAsync(status.DeviceName, status.EndpointName, status.Status, ct: ct).ConfigureAwait(false); } catch (Exception ex) { _outer._logger.FailedToUpdateDeviceStatus(ex, status.DeviceName, status.EndpointName); } } foreach (var (_, status) in _assets) { try { await client.UpdateAssetStatusAsync(status.Asset.DeviceRef.DeviceName, status.Asset.DeviceRef.EndpointName, status.AssetName, status.Status, ct: ct).ConfigureAwait(false); } catch (Exception ex) { _outer._logger.FailedToUpdateAssetStatus(ex, status.AssetName, status.Asset.DeviceRef.DeviceName, status.Asset.DeviceRef.EndpointName); } } } /// /// Add the error to the device status for the device resource /// /// /// /// private void Add(DeviceResource resource, string code, string error) { var ep = resource.Device.Endpoints?.Inbound?.FirstOrDefault().Key; if (string.IsNullOrEmpty(ep)) { // Cannot find an endpoint but we need it to attach status return; } var status = GetDeviceEndpointStatusResource(new DeviceEndpointResource( resource.DeviceName, resource.Device, ep)); if (status.Status.Config == null) { status.Status.Config = new ConfigStatus { Error = new ConfigError { Code = code, Message = error } }; } } /// /// Add the error to the device endpoint resource /// /// /// /// private void Add(DeviceEndpointResource resource, string code, string error) { var status = GetDeviceEndpointStatusResource(resource); status.Status.Endpoints ??= new DeviceStatusEndpoint { Inbound = new Dictionary() }; Debug.Assert(status.Status.Endpoints.Inbound != null); if (!TryGetInboundEndpoint(status.Status.Endpoints, resource.EndpointName, out var entry)) { entry = new DeviceStatusInboundEndpointSchemaMapValue(); status.Status.Endpoints.Inbound.Add(resource.EndpointName, entry); } entry.Error = new ConfigError { Code = code, Message = error }; } /// /// Add error to asset resource /// /// /// /// private void Add(AssetResource resource, string code, string error) { var status = GetAssetStatusResource(resource); if (status.Status.Config == null) { status.Status.Config = new ConfigStatus { Error = new ConfigError { Code = code, Message = error } }; } } /// /// Add error to the dataset resource /// /// /// /// private void Add(DataSetResource resource, string code, string error) { var status = GetAssetStatusResource(resource); status.Status.Datasets ??= new List(); Debug.Assert(status.Status.Datasets != null); status.Status.Datasets.Add(new AssetDatasetEventStreamStatus { Name = resource.DataSet.Name, Error = new ConfigError { Code = code, Message = error } }); } /// /// Add error to the management group status based on management group resource /// /// /// /// private void Add(EventGroupResource resource, string code, string error) { if (resource.EventGroup.Events == null || resource.EventGroup.Events.Count == 0) { return; } var status = GetAssetStatusResource(resource); status.Status.EventGroups ??= new List(); Debug.Assert(status.Status.ManagementGroups != null); status.Status.EventGroups.Add(new AssetEventGroupStatus { Name = resource.EventGroup.Name, Events = resource.EventGroup.Events.ConvertAll(a => new AssetDatasetEventStreamStatus { Name = a.Name, Error = new ConfigError { Code = code, Message = error } } ) }); } /// /// Add error to the event status based on event resource /// /// /// /// private void Add(EventResource resource, string code, string error) { var status = GetAssetStatusResource(resource); status.Status.EventGroups ??= new List(); Debug.Assert(status.Status.EventGroups != null); status.Status.EventGroups.Add(new AssetEventGroupStatus { Name = resource.EventGroup.Name, Events = new List { new AssetDatasetEventStreamStatus { Name = resource.Event.Name, Error = new ConfigError { Code = code, Message = error } } } }); } /// /// Add error to the stream status based on stream resource /// /// /// /// private void Add(StreamResource resource, string code, string error) { var status = GetAssetStatusResource(resource); status.Status.Streams ??= new List(); Debug.Assert(status.Status.Streams != null); status.Status.Streams.Add(new AssetDatasetEventStreamStatus { Name = resource.Stream.Name, Error = new ConfigError { Code = code, Message = error } }); } /// /// Add error to the management group status based on management group resource /// /// /// /// private void Add(ManagementGroupResource resource, string code, string error) { if (resource.ManagementGroup.Actions == null || resource.ManagementGroup.Actions.Count == 0) { return; } var status = GetAssetStatusResource(resource); status.Status.ManagementGroups ??= new List(); Debug.Assert(status.Status.ManagementGroups != null); status.Status.ManagementGroups.Add(new AssetManagementGroupStatusSchemaElement { Name = resource.ManagementGroup.Name, Actions = resource.ManagementGroup.Actions.ConvertAll(a => new AssetManagementGroupActionStatusSchemaElement { Name = a.Name, Error = new ConfigError { Code = code, Message = error } } ) }); } /// /// Add error to the management action status based on management action resource /// /// /// /// private void Add(ManagementActionResource resource, string code, string error) { var status = GetAssetStatusResource(resource); status.Status.ManagementGroups ??= new List(); Debug.Assert(status.Status.ManagementGroups != null); status.Status.ManagementGroups.Add(new AssetManagementGroupStatusSchemaElement { Name = resource.ManagementGroup.Name, Actions = new List { new AssetManagementGroupActionStatusSchemaElement { Name = resource.Action.Name, Error = new ConfigError { Code = code, Message = error } } } }); } private DeviceEndpointStatusResource GetDeviceEndpointStatusResource(DeviceEndpointResource device) { var key = CreateDeviceKey(device.DeviceName, device.EndpointName); if (!_devices.TryGetValue(key, out var deviceStatus)) { deviceStatus = new DeviceEndpointStatusResource(device); _devices.Add(key, deviceStatus); } return deviceStatus; } private AssetStatusResource GetAssetStatusResource(AssetResource asset) { var key = CreateAssetKey(asset.Asset.DeviceRef.DeviceName, asset.Asset.DeviceRef.EndpointName, asset.AssetName); if (!_assets.TryGetValue(key, out var assetStatus)) { assetStatus = new AssetStatusResource(asset); _assets.Add(key, assetStatus); } return assetStatus; } internal record class AssetStatusResource(AssetResource resource) : AssetResource(resource.AssetName, resource.Asset) { public AssetStatus Status { get; } = new(); } internal record class DeviceEndpointStatusResource(DeviceEndpointResource resource) : DeviceEndpointResource(resource.DeviceName, resource.Device, resource.EndpointName) { public DeviceStatus Status { get; } = new(); } private readonly Dictionary _assets = new(); private readonly Dictionary _devices = new(); private readonly AssetDeviceIntegration _outer; } private const string kNotSupportedErrorCode = "500.0"; private const string kJsonSerializationErrorCode = "500.1"; private const string kDeviceNotFoundErrorCode = "500.2"; private const string kTooManyDestinationsError = "500.4"; private const string kAuthenticationValueMissing = "500.5"; private const string kDiscoveryError = "500.6"; private const string kInvalidEndpointUrl = "500.7"; private static readonly TimeSpan kDefaultDeviceDiscoveryRefresh = TimeSpan.FromHours(6); private static readonly JsonSerializerOptions kDebugSerializerOptions = new() { WriteIndented = true, Converters = { new JsonStringEnumConverter() }, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }; private const string kAssetIdAttribute = "AssetId"; private readonly ConcurrentDictionary _assets = new(); private readonly ConcurrentDictionary _devices = new(); private readonly IAioSrClient _schemaRegistry; private readonly IDisposable _srevents; private readonly Channel<(string, Resource)> _changeFeed; private readonly IConfigurationServices _configurationServices; private readonly IConnectionServices _connections; private readonly IDiscoveryServices _discovery; private readonly IAioAdrClient _client; private readonly IPublishedNodesServices _publishedNodes; private readonly IJsonSerializer _serializer; private readonly IOptions _options; private readonly ILogger _logger; private readonly CancellationTokenSource _cts; private readonly Task _processor; private readonly Task _assetDiscovery; private readonly Task _deviceDiscovery; private readonly AsyncManualResetEvent _trigger; private readonly Timer _timer; private int _lastDeviceListVersion; private bool _isDisposed; // TODO: START: Remove once adr is fixed private static string SetEndpointUrl(string endpointUrl) => $"{endpointUrl}{kAddressSplit}{Interlocked.Increment(ref _epindex)}"; private static int _epindex; private static string GetEndpointUrl(string address) => address.Contains(kAddressSplit, StringComparison.Ordinal) ? address.Split(kAddressSplit)[0] : address; private const string kAddressSplit = "?___"; // TODO: END Remove when adr is fixed } /// /// Source-generated logging extensions for AssetDeviceIntegration /// internal static partial class AssetDeviceIntegrationLogging { private const int EventClass = 2000; internal static bool IsDebugLogConfigurationEnabled(this ILogger logger) #if !DEBUG => logger.IsEnabled(LogLevel.Debug); #else => true; #endif [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Debug, Message = "Failed to close discovery runner.")] internal static partial void FailedToCloseDiscoveryRunner(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Debug, Message = "Failed to close conversion processor")] internal static partial void FailedToCloseConversionProcessor(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Information, Message = "Device {DeviceName} with endpoint {EndpointName} added.")] internal static partial void DeviceAdded(this ILogger logger, string deviceName, string endpointName); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Debug, Message = "Device {DeviceName} with endpoint {EndpointName} updated.")] internal static partial void DeviceUpdated(this ILogger logger, string deviceName, string endpointName); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Debug, Message = "Reported deletion for resource {Resource} which was not found.")] internal static partial void ResourceDeletionNotFound(this ILogger logger, string resource); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Debug, Message = "Device {DeviceName} with endpoint {EndpointName} removed.")] internal static partial void DeviceRemoved(this ILogger logger, string deviceName, string endpointName); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Information, Message = "Asset {AssetName} on device {DeviceName} with endpoint {EndpointName} added.")] internal static partial void AssetAdded(this ILogger logger, string assetName, string deviceName, string endpointName); [LoggerMessage(EventId = EventClass + 8, Level = LogLevel.Debug, Message = "Asset {AssetName} on device {DeviceName} with endpoint {EndpointName} updated.")] internal static partial void AssetUpdated(this ILogger logger, string assetName, string deviceName, string endpointName); [LoggerMessage(EventId = EventClass + 9, Level = LogLevel.Debug, Message = "Asset {AssetName} on device {DeviceName} with endpoint {EndpointName} removed.")] internal static partial void AssetRemoved(this ILogger logger, string assetName, string deviceName, string endpointName); [LoggerMessage(EventId = EventClass + 10, Level = LogLevel.Debug, Message = "Removing asset {Asset} without device {Device}")] internal static partial void RemovingAssetWithoutDevice(this ILogger logger, string asset, string device); [LoggerMessage(EventId = EventClass + 11, Level = LogLevel.Information, Message = "Converting {Assets} Assets on {Devices} devices...")] internal static partial void ConvertingAssetsOnDevices(this ILogger logger, int assets, int devices); [LoggerMessage(EventId = EventClass + 12, Level = LogLevel.Debug, SkipEnabledCheck = true, Message = "New configuration applied:\n{Configuration}")] internal static partial void NewConfigurationApplied(this ILogger logger, string configuration); [LoggerMessage(EventId = EventClass + 13, Level = LogLevel.Information, Message = "{Assets} Assets on {Devices} devices updated.")] internal static partial void AssetsAndDevicesUpdated(this ILogger logger, int assets, int devices); [LoggerMessage(EventId = EventClass + 14, Level = LogLevel.Information, Message = "Devices were updated, starting immediate discovery.")] internal static partial void DevicesUpdatedStartingDiscovery(this ILogger logger); [LoggerMessage(EventId = EventClass + 15, Level = LogLevel.Warning, Message = "Dropping result {Result} without required information.")] internal static partial void DroppingResultWithoutRequiredInformation( this ILogger logger, string? result); [LoggerMessage(EventId = EventClass + 16, Level = LogLevel.Debug, SkipEnabledCheck = true, Message = "Reporting new discovered asset {AssetName} with id " + "{AssetId} and type {AssetTypeRef}:\n{Asset}")] internal static partial void ReportingNewDiscoveredAsset(this ILogger logger, string assetName, string assetId, string assetTypeRef, string asset); [LoggerMessage(EventId = EventClass + 17, Level = LogLevel.Error, Message = "Additional configuration for endpoint {EndpointName} on " + "device {DeviceName} is too long ({Length} > 512). Skipping.")] internal static partial void EndpointConfigurationTooLong(this ILogger logger, string endpointName, string deviceName, int length); [LoggerMessage(EventId = EventClass + 18, Level = LogLevel.Debug, Message = "No endpoints found on device {DeviceName}.")] internal static partial void NoEndpointsFound(this ILogger logger, string deviceName); [LoggerMessage(EventId = EventClass + 19, Level = LogLevel.Debug, SkipEnabledCheck = true, Message = "Reporting new discovered device {DeviceName} with type {EndpointType}:\n{Device}")] internal static partial void ReportingNewDiscoveredDevice(this ILogger logger, string deviceName, string endpointType, string device); [LoggerMessage(EventId = EventClass + 20, Level = LogLevel.Information, Message = "Running discovery for all devices...")] internal static partial void RunningDiscoveryForAllDevices(this ILogger logger); [LoggerMessage(EventId = EventClass + 21, Level = LogLevel.Error, Message = "Failed to run discovery for device {Device}")] internal static partial void FailedToRunDiscoveryForDevice(this ILogger logger, Exception ex, string device); [LoggerMessage(EventId = EventClass + 22, Level = LogLevel.Error, Message = "Failed to run endpoint discovery for device {Device}")] internal static partial void FailedToRunEndpointDiscoveryForDevice(this ILogger logger, Exception ex, string device); [LoggerMessage(EventId = EventClass + 23, Level = LogLevel.Information, Message = "Running discovery for all devices interrupted.")] internal static partial void RunningDiscoveryInterrupted(this ILogger logger); [LoggerMessage(EventId = EventClass + 24, Level = LogLevel.Information, Message = "Running discovery for all devices completed.")] internal static partial void RunningDiscoveryCompleted(this ILogger logger); [LoggerMessage(EventId = EventClass + 25, Level = LogLevel.Information, Message = "Reporting status for {Assets} assets and {Devices} devices.")] internal static partial void ReportingStatus(this ILogger logger, int assets, int devices); [LoggerMessage(EventId = EventClass + 26, Level = LogLevel.Warning, Message = "Encountered Error {Code} {Error} for resource {Resource}.")] internal static partial void EncounteredError(this ILogger logger, string code, string error, AssetDeviceIntegration.Resource resource); [LoggerMessage(EventId = EventClass + 27, Level = LogLevel.Error, Message = "Failed to report new discovered server {Device}")] internal static partial void FailedToReportDiscoveredServer(this ILogger logger, Exception ex, string device); [LoggerMessage(EventId = EventClass + 28, Level = LogLevel.Error, Message = "Invalid device change event {ChangeType} received: {Device} {Endpoint}")] internal static partial void InvalidDeviceChangeEventReceived(this ILogger logger, ChangeType changeType, string device, string endpoint); [LoggerMessage(EventId = EventClass + 29, Level = LogLevel.Error, Message = "Invalid asset change event {ChangeType} received: {Device} {Endpoint} {Asset}")] internal static partial void InvalidAssetChangeEventReceived(this ILogger logger, ChangeType changeType, string device, string endpoint, string asset); [LoggerMessage(EventId = EventClass + 30, Level = LogLevel.Information, Message = "Testing connection with device {Device} on endpoint {Endpoint} resulted in {ErrorInfo}")] internal static partial void FailedToConnectToDeviceEndpoint(this ILogger logger, string device, string endpoint, ServiceResultModel errorInfo); [LoggerMessage(EventId = EventClass + 31, Level = LogLevel.Error, Message = "Unexpected error processing asset and device changes")] internal static partial void UnexpectedErrorProcessingChanges(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 32, Level = LogLevel.Error, Message = "Registration of schema has invalid values")] internal static partial void SchemaRegistrationInvalidValues(this ILogger logger); [LoggerMessage(EventId = EventClass + 33, Level = LogLevel.Debug, Message = "Cannot register schema without identifier")] internal static partial void CannotRegisterSchemaWithoutIdentifier(this ILogger logger); [LoggerMessage(EventId = EventClass + 34, Level = LogLevel.Debug, Message = "Malformed schema id {Id} cannot be used for lookup")] internal static partial void MalformedSchemaId(this ILogger logger, string id); [LoggerMessage(EventId = EventClass + 35, Level = LogLevel.Information, Message = "Registering schema '{Name}' with version '{Version}' for resource '{Resource}' " + "in asset '{Asset}' inside schema namespace '{Namespace}'")] internal static partial void RegisteringSchema(this ILogger logger, string name, string version, string resource, string asset, string @namespace); [LoggerMessage(EventId = EventClass + 36, Level = LogLevel.Information, Message = "No asset found with name {AssetName} to attach schema {Schema} to.")] internal static partial void NoAssetFoundForSchema(this ILogger logger, string assetName, string? schema); [LoggerMessage(EventId = EventClass + 37, Level = LogLevel.Information, Message = "No resource {Resource} found in Asset {Asset} to attach the schema {Schema} to.")] internal static partial void NoResourceFoundInAssetForSchema(this ILogger logger, string resource, string asset, string? schema); [LoggerMessage(EventId = EventClass + 39, Level = LogLevel.Error, Message = "Unexpected error during discovery.")] internal static partial void UnexpectedErrorDuringDiscovery(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 40, Level = LogLevel.Error, Message = "Failed to update asset status for asset {Asset} with device {Device} with endpoint {Endpoint}")] internal static partial void FailedToUpdateAssetStatus(this ILogger logger, Exception ex, string asset, string device, string endpoint); [LoggerMessage(EventId = EventClass + 41, Level = LogLevel.Error, Message = "Failed to update asset status for device {Device} with endpoint {Endpoint}")] internal static partial void FailedToUpdateDeviceStatus(this ILogger logger, Exception ex, string device, string endpoint); [LoggerMessage(EventId = EventClass + 42, Level = LogLevel.Information, Message = "Running network discovery ...")] internal static partial void RunningNetworkDiscovery(this ILogger logger); [LoggerMessage(EventId = EventClass + 43, Level = LogLevel.Information, Message = "Network discovery completed.")] internal static partial void NetworkDiscoveryComplete(this ILogger logger); [LoggerMessage(EventId = EventClass + 44, Level = LogLevel.Error, Message = "Unexpected error during network discovery.")] internal static partial void UnexpectedErrorDuringNetworkDiscovery(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 45, Level = LogLevel.Information, Message = "Device {Device} already present - skipping.")] internal static partial void DeviceAlreadyPresentSkipping(this ILogger logger, string device); [LoggerMessage(EventId = EventClass + 46, Level = LogLevel.Information, Message = "Network discovery disabled.")] internal static partial void NetworkDiscoveryDisabled(this ILogger logger); [LoggerMessage(EventId = EventClass + 47, Level = LogLevel.Information, Message = "Network discovery was configured to only run once - exiting.")] internal static partial void NetworkDiscoveryConfiguredToOnlyRunOnce(this ILogger logger); [LoggerMessage(EventId = EventClass + 48, Level = LogLevel.Information, Message = "Registered schema '{Name}' with version '{Version}' for resource '{Resource}' in asset " + "'{Asset}' inside schema namespace '{Namespace}'")] internal static partial void RegisteredSchema(this ILogger logger, string name, string version, string resource, string asset, string @namespace); [LoggerMessage(EventId = EventClass + 49, Level = LogLevel.Debug, Message = "Error registering schema '{Name}' with version '{Version}' for resource '{Resource}' in asset " + "'{Asset}' inside schema namespace '{Namespace}' - retrying ...")] internal static partial void RegisteredSchemaErrorDebug(this ILogger logger, Exception ex, string name, string version, string resource, string asset, string @namespace); [LoggerMessage(EventId = EventClass + 50, Level = LogLevel.Error, Message = "Error registering schema '{Name}' with version '{Version}' for resource '{Resource}' in asset " + "'{Asset}' inside schema namespace '{Namespace}'")] internal static partial void RegisteredSchemaError(this ILogger logger, Exception ex, string name, string version, string resource, string asset, string @namespace); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Services/AsyncEnumerableBrowser.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Services { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Microsoft.Extensions.Options; using Opc.Ua; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; /// /// Async enumerable browsing operation base class. Used in configuration /// and file system browse operations. /// /// internal abstract class AsyncEnumerableBrowser : AsyncEnumerableEnumerableStack where T : class { protected TimeProvider TimeProvider { get; } protected RequestHeaderModel? Header { get; } protected IOptions Options { get; } /// /// Create browser /// /// /// /// /// /// /// /// /// /// /// /// protected AsyncEnumerableBrowser(RequestHeaderModel? header, IOptions options, TimeProvider? timeProvider = null, BrowseFrame? root = null, NodeId? typeDefinitionId = null, bool includeTypeDefinitionSubtypes = true, uint? maxDepth = null, Opc.Ua.NodeClass nodeClass = Opc.Ua.NodeClass.Object, NodeId? referenceTypeId = null, bool includeReferenceTypeSubtypes = true, Opc.Ua.NodeClass? matchClass = null) { Header = header; Options = options; TimeProvider = timeProvider ?? TimeProvider.System; _root = null!; _referenceTypeId = null!; Initialize(maxDepth, root, nodeClass, typeDefinitionId, includeTypeDefinitionSubtypes, referenceTypeId, includeReferenceTypeSubtypes, matchClass); } /// public override void Dispose() { _activitySource.Dispose(); } /// public override void Reset() { base.Reset(); OnReset(); } /// /// Override to disable starting browsing /// protected virtual void OnReset() { Start(); } /// /// Restart browsing with different configuration /// /// /// /// /// /// /// /// /// protected void Restart(BrowseFrame? root = null, uint? maxDepth = null, NodeId? typeDefinitionId = null, bool includeTypeDefinitionSubtypes = true, NodeId? referenceTypeId = null, bool includeReferenceTypeSubtypes = true, Opc.Ua.NodeClass nodeClass = Opc.Ua.NodeClass.Object, Opc.Ua.NodeClass? matchClass = null) { Initialize(maxDepth, root, nodeClass, typeDefinitionId, includeTypeDefinitionSubtypes, referenceTypeId, includeReferenceTypeSubtypes, matchClass); Start(); } /// /// Handle error /// /// /// /// protected abstract IEnumerable HandleError( ServiceCallContext context, ServiceResultModel errorInfo); /// /// handle matches /// /// /// /// /// protected abstract IEnumerable HandleMatching( ServiceCallContext context, IReadOnlyList matching, List references); /// /// Handle browse completion /// /// /// protected virtual IEnumerable HandleCompletion(ServiceCallContext context) { return []; } /// /// Browse references /// /// /// private async ValueTask> BrowseAsync(ServiceCallContext context) { using var trace = _activitySource.StartActivity("Browse"); var frame = Pop(); if (frame == null) { return HandleCompletion(context); } var browseDescriptions = new BrowseDescriptionCollection { new BrowseDescription { BrowseDirection = Opc.Ua.BrowseDirection.Forward, NodeClassMask = (uint)_nodeClass | (uint)_matchClass, NodeId = frame.NodeId, ReferenceTypeId = _referenceTypeId, IncludeSubtypes = _includeReferenceTypeSubtypes, ResultMask = (uint)BrowseResultMask.All } }; // Browse and read children var response = await context.Session.Services.BrowseAsync( Header.ToRequestHeader(TimeProvider), null, 0, browseDescriptions, context.Ct).ConfigureAwait(false); var results = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, browseDescriptions); if (results.ErrorInfo != null) { return HandleError(context, results.ErrorInfo); } var refs = MatchReferences(frame, context, results[0].Result.References, results[0].ErrorInfo); var continuation = results[0].Result.ContinuationPoint ?? []; if (continuation.Length > 0) { Push(context => BrowseNextAsync(context, continuation, frame)); } else { Push(BrowseAsync); } return refs; } /// /// Browse remainder of references /// /// /// /// /// private async ValueTask> BrowseNextAsync(ServiceCallContext context, byte[] continuationPoint, BrowseFrame frame) { using var trace = _activitySource.StartActivity("BrowseNext"); var continuationPoints = new ByteStringCollection { continuationPoint }; var response = await context.Session.Services.BrowseNextAsync( Header.ToRequestHeader(TimeProvider), false, continuationPoints, context.Ct).ConfigureAwait(false); var results = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, continuationPoints); if (results.ErrorInfo != null) { return HandleError(context, results.ErrorInfo); } var refs = MatchReferences(frame, context, results[0].Result.References, results[0].ErrorInfo); var continuation = results[0].Result.ContinuationPoint ?? []; if (continuation.Length > 0) { Push(session => BrowseNextAsync(session, continuation, frame)); } else { Push(BrowseAsync); } return refs; } /// /// Collect references /// /// /// /// /// /// private IEnumerable MatchReferences(BrowseFrame frame, ServiceCallContext context, ReferenceDescriptionCollection refs, ServiceResultModel? errorInfo) { if (errorInfo != null) { return HandleError(context, errorInfo); } var matching = refs .Where(reference => ((int)reference.NodeClass & (int)_matchClass) != 0 && (reference.NodeId?.ServerIndex ?? 1u) == 0 && MatchTypeDefinitionId(context.Session, reference.TypeDefinition)) .Select(reference => new BrowseFrame((NodeId)reference.NodeId, reference.BrowseName, reference.DisplayName?.Text, reference.TypeDefinition, reference.NodeClass, frame, IsChildOf(context.Session, reference, frame))) .ToList(); var results = matching.Count != 0 ? HandleMatching(context, matching, refs) : []; // Browse deeper foreach (var reference in refs) { Push(reference.NodeId, reference.BrowseName, reference.DisplayName?.Text, reference.TypeDefinition, reference.NodeClass, frame, IsChildOf(context.Session, reference, frame)); } return results; bool? IsChildOf(IOpcUaSession session, ReferenceDescription reference, BrowseFrame parent) { var referenceTypeId = reference.ReferenceTypeId; var parentTypeDefinitionId = parent.TypeDefinitionId; if (NodeId.IsNull(parentTypeDefinitionId)) { return null; } if (session.LruNodeCache.IsTypeOf(referenceTypeId, ReferenceTypeIds.HasComponent) || session.LruNodeCache.IsTypeOf(referenceTypeId, ReferenceTypeIds.HasProperty)) { var parentIsFolder = session.LruNodeCache.IsTypeOf(parentTypeDefinitionId, ObjectTypeIds.FolderType); #if DEBUG Debug.WriteLine(parent.BrowseName + "(" + (parentIsFolder ? "Folder" : "Component") + ")--" + referenceTypeId + "-->" + reference.BrowseName); #endif return !parentIsFolder; } return false; } // Helper to match type definition to desired type definition id bool MatchTypeDefinitionId(IOpcUaSession session, ExpandedNodeId typeDefinition) { if (typeDefinition == _typeDefinitionId || _typeDefinitionId == null) { return true; } if (_includeTypeDefinitionSubtypes && !NodeId.IsNull(typeDefinition)) { var typeDefinitionId = ExpandedNodeId.ToNodeId(typeDefinition, session.MessageContext.NamespaceUris); return session.LruNodeCache.IsTypeOf(typeDefinitionId, _typeDefinitionId); } return false; } } /// /// Initialize /// private void Start() { // Initialize _visited.Clear(); _browseStack.Push(_root); Push(BrowseAsync); } /// /// Helper to push nodes onto the browse stack /// /// /// /// /// /// /// /// private void Push(ExpandedNodeId nodeId, QualifiedName? browseName, string? displayName, ExpandedNodeId typeDefinition, Opc.Ua.NodeClass nodeClass, BrowseFrame? parent, bool? isChildOfParent) { if ((nodeId?.ServerIndex ?? 1u) != 0) { return; } var local = (NodeId)nodeId; if (!NodeId.IsNull(local) && !_visited.Contains(local)) { var frame = new BrowseFrame(local, browseName, displayName, typeDefinition, nodeClass, parent, isChildOfParent); if (_maxDepth.HasValue && frame.Depth >= _maxDepth.Value) { return; } _browseStack.Push(frame); } } /// /// Helper to pop nodes from the browse stack /// /// private BrowseFrame? Pop() { while (_browseStack.TryPop(out var frame)) { if (!NodeId.IsNull(frame.NodeId) && !_visited.Contains(frame.NodeId)) { return frame; } } return null; } /// /// Tracks a reference to a node /// /// /// /// /// /// /// /// protected internal record class BrowseFrame(NodeId NodeId, QualifiedName? BrowseName = null, string? DisplayName = null, ExpandedNodeId? TypeDefinitionId = null, Opc.Ua.NodeClass? NodeClass = null, BrowseFrame? Parent = null, bool? IsChildOfParent = null) { /// /// Current depth of this frame /// public uint Depth { get { var depth = 0u; for (var parent = Parent; parent != null; parent = parent.Parent) { depth++; } return depth; } } /// /// Get the root frame that is not a child of anything /// public BrowseFrame? RootFrame { get { // // child, not child, child, child, not child (*), not child, not child. // (*) <- this is what we want to return here // BrowseFrame? found = null; for (var parent = this; parent != null; parent = parent.Parent) { if (parent.IsChildOfParent != true) { found ??= parent; // Set if not already set continue; } found = null; } return found; } } /// /// Browse path to the node from root /// public string BrowsePath { get { var path = BrowseName?.ToString() ?? string.Empty; for (var parent = Parent; parent?.BrowseName != null; parent = parent.Parent) { path = $"{parent.BrowseName}/{path}"; } return "/" + path; } } /// /// All browse frames to the root /// public IEnumerable AllFramesToRoot { get { for (var frame = this; frame != null; frame = frame.Parent) { yield return frame; } } } /// /// Create a name for the object that is rooted in a root browse frame, /// e.g. the writer group, structurally. We use . seperator to create /// names that can be reused in topics and paths. /// /// /// public string BrowseNameFromRootFrame(BrowseFrame? root) { var cur = this; if (cur.BrowseName?.Name == null || cur == root) { return "Default"; } var result = cur.BrowseName.Name; cur = cur.Parent; while (cur != root) { if (cur?.BrowseName?.Name == null) { // not rooted in root because we hit a null parent, // return cur browsename return BrowseName!.Name; } result = cur.BrowseName.Name + "." + result; cur = cur.Parent; } return result; } } /// /// Restart browsing with different configuration /// /// /// /// /// /// /// /// /// private void Initialize(uint? maxDepth, BrowseFrame? root, Opc.Ua.NodeClass nodeClass, NodeId? typeDefinitionId, bool includeTypeDefinitionSubtypes, NodeId? referenceTypeId, bool includeReferenceTypeSubtypes, Opc.Ua.NodeClass? matchClass) { _nodeClass = nodeClass; _matchClass = matchClass ?? nodeClass; _maxDepth = maxDepth; _root = root ?? new BrowseFrame(ObjectIds.ObjectsFolder); _typeDefinitionId = typeDefinitionId; _includeTypeDefinitionSubtypes = includeTypeDefinitionSubtypes; _referenceTypeId = referenceTypeId ?? ReferenceTypeIds.HierarchicalReferences; _includeReferenceTypeSubtypes = includeReferenceTypeSubtypes; } private Opc.Ua.NodeClass _nodeClass; private Opc.Ua.NodeClass _matchClass; private uint? _maxDepth; private BrowseFrame _root; private NodeId _referenceTypeId; private bool _includeReferenceTypeSubtypes; private NodeId? _typeDefinitionId; private bool _includeTypeDefinitionSubtypes; private readonly Stack _browseStack = new(); private readonly HashSet _visited = []; private readonly ActivitySource _activitySource = Diagnostics.NewActivitySource(); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Services/ConfigurationBrowser.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Services { using Azure.IIoT.OpcUa.Publisher; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Parser; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Stack.Extensions; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Furly.Extensions.Serializers; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Opc.Ua; using Opc.Ua.Extensions; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; /// /// Configuration browser /// internal sealed class ConfigurationBrowser : AsyncEnumerableBrowser> { /// public ConfigurationBrowser(PublishedNodesEntryModel entry, PublishedNodeExpansionModel request, IOptions options, IPublishedNodesServices? configuration, ILogger logger, TimeProvider? timeProvider = null, bool allowNoResolution = false) : base(request.Header, options, timeProvider) { _entry = entry; _request = request; _configuration = configuration; _logger = logger; _allowNoResolution = allowNoResolution; } /// public override void Reset() { base.Reset(); _nodeIndex = -1; _expanded.Clear(); Push(BeginAsync); } /// protected override void OnReset() { // We handle our own restarts } /// protected override IEnumerable> HandleError( ServiceCallContext context, ServiceResultModel errorInfo) { var node = _currentObject != null ? _currentObject.OriginalNode : CurrentNode; node.AddErrorInfo(errorInfo); _logger.HandleError(node, errorInfo); return []; } /// protected override IEnumerable> HandleMatching( ServiceCallContext context, IReadOnlyList matching, List references) { uint originalNodeClass; if (_currentObject == null) { // collect matching object instances originalNodeClass = CurrentNode.NodeClass; CurrentNode.AddObjectsOrVariables(matching); } else { originalNodeClass = _currentObject.OriginalNode.NodeClass; // collect matching variables under the current object instance var nodes = matching .Where(m => m.NodeClass is Opc.Ua.NodeClass.Variable or Opc.Ua.NodeClass.Method); var objects = matching .Where(m => m.NodeClass == Opc.Ua.NodeClass.Object); if (_currentObject.AddNodes(nodes)) { _logger.DroppedDuplicateItems(); } // Add components of the current object - these will be expanded // when we move to next object. _currentObject.OriginalNode.AddObjectsOrVariables(objects); if (originalNodeClass == (uint)Opc.Ua.NodeClass.ObjectType && !_request.FlattenTypeInstance) { // Only expand variables of current object in match loop references.RemoveAll(m => m.NodeClass == Opc.Ua.NodeClass.Object); } } if ((originalNodeClass == (uint)Opc.Ua.NodeClass.ObjectType && _request.FlattenTypeInstance) || originalNodeClass == (uint)Opc.Ua.NodeClass.VariableType) { // Browse deeper for other variables of the type var stop = matching.Select(r => r.NodeId).ToHashSet(); references.RemoveAll(r => stop.Contains((NodeId)r.NodeId)); } return []; } /// protected override IEnumerable> HandleCompletion( ServiceCallContext context) { Push(CompleteAsync); return []; } /// /// Complete the browse operation and resolve objects /// /// /// private async ValueTask>> CompleteAsync( ServiceCallContext context) { var results = new List>(); var currentObject = _currentObject; if (currentObject != null) { // Process current object await ProcessAsync(currentObject, context, results).ConfigureAwait(false); if (TryMoveToNextObject()) { // Kicked off the next expansion return results; } Debug.Assert(_currentObject == null); } else if (CurrentNode.Variables.ContainsVariables) { // Completing the browse operation for variables of variables await ProcessAsync(CurrentNode.Variables, context, results).ConfigureAwait(false); } else if (!CurrentNode.ContainsObjects) { // Completing a browse for objects if (!CurrentNode.HasErrors && !_allowNoResolution) { CurrentNode.AddErrorInfo(StatusCodes.BadNotFound, "No objects resolved."); } } if (!TryMoveToNextNode()) { // Complete results.AddRange(await EndAsync(context).ConfigureAwait(false)); } return results; async Task ProcessAsync(ObjectToExpand currentObject, ServiceCallContext context, List> results) { await currentObject.CompleteAsync(_request.Header.ToRequestHeader(TimeProvider), context).ConfigureAwait(false); if (!_request.CreateSingleWriter && (currentObject.ContainsVariables || currentObject.ContainsMethods || currentObject.ContainsEvents) && !currentObject.OriginalNode.HasErrors) { // Create a new writer entry for the object var root = currentObject.ObjectFromBrowse.RootFrame; var result = await SaveEntryAsync(new ServiceResponse { Result = _entry with { DataSetWriterId = currentObject.CreateWriterId(), // Unique DataSetWriterGroup = _entry.DataSetWriterGroup ?? root?.BrowseName?.Name, // Name of the dataset with DataSetWriterGroup as root DataSetName = currentObject.ObjectFromBrowse.BrowseNameFromRootFrame(root), DataSetRootNodeId = currentObject.ObjectFromBrowse.NodeId?.AsString( context.Session.MessageContext, NamespaceFormat.Expanded), // Type of the dataset DataSetType = currentObject.ObjectFromBrowse.TypeDefinitionId?.AsString( context.Session.MessageContext, NamespaceFormat.ExpandedWithNamespace0), // Type of the writer group WriterGroupType = root?.TypeDefinitionId?.AsString( context.Session.MessageContext, NamespaceFormat.ExpandedWithNamespace0), WriterGroupRootNodeId = root?.NodeId?.AsString( context.Session.MessageContext, NamespaceFormat.Expanded), OpcNodes = currentObject .GetOpcNodeModels( currentObject.OriginalNode.NodeFromConfiguration, context.Session.MessageContext, _request.UseBrowseNameAsDisplayName, createLongIds: false) .ToList() } }, context.Ct).ConfigureAwait(false); currentObject.EntriesAlreadyReturned = true; if (!_request.DiscardErrors || result.ErrorInfo == null) { // Add good entry to return _now_ results.Add(result); } } } } /// /// Start by resolving nodes and starting the browse operation /// /// /// private async ValueTask>> BeginAsync( ServiceCallContext context) { if (_entry.OpcNodes?.Count > 0) { // TODO: Could be done in one request for better efficiency foreach (var node in _entry.OpcNodes) { try { var nodeId = await context.Session.ResolveNodeIdAsync(_request.Header, node.Id, node.BrowsePath, nameof(node.BrowsePath), TimeProvider, context.Ct).ConfigureAwait(false); var readValueIds = new ReadValueIdCollection { new ReadValueId { NodeId = nodeId, AttributeId = Attributes.NodeClass }, new ReadValueId { NodeId = nodeId, AttributeId = Attributes.BrowseName }, new ReadValueId { NodeId = nodeId, AttributeId = Attributes.DisplayName } }; var response = await context.Session.Services.ReadAsync( _request.Header.ToRequestHeader(TimeProvider), 0, Opc.Ua.TimestampsToReturn.Neither, readValueIds, context.Ct).ConfigureAwait(false); var readResults = response.Validate(response.Results, s => s.StatusCode, response.DiagnosticInfos, readValueIds); var errorInfo = readResults.ErrorInfo ?? readResults[0].ErrorInfo; var nodeClass = errorInfo != null ? Opc.Ua.NodeClass.Unspecified : readResults[0].Result.GetValueOrDefaultEx(); var browseName = errorInfo != null ? null : readResults[1].Result.GetValueOrDefaultEx(); var displayName = errorInfo != null ? null : readResults[2].Result.GetValueOrDefaultEx(); ExpandedNodeId? typeDefinitionId = null; if (errorInfo == null) { switch (nodeClass) { case Opc.Ua.NodeClass.ObjectType: case Opc.Ua.NodeClass.VariableType: typeDefinitionId = nodeId; break; case Opc.Ua.NodeClass.Object: var (results, errorInfo2) = await context.Session.FindAsync( _request.Header.ToRequestHeader(TimeProvider), nodeId.YieldReturn(), ReferenceTypeIds.HasTypeDefinition, nodeClassMask: (uint)Opc.Ua.NodeClass.ObjectType, ct: context.Ct).ConfigureAwait(false); errorInfo = errorInfo2; if (errorInfo != null) { break; } Debug.Assert(results.Count == 1); typeDefinitionId = results[0].Node; break; } } _expanded.Add(new NodeToExpand(node, nodeId, nodeClass, browseName, displayName, typeDefinitionId, errorInfo)); } catch (Exception e) { _expanded.Add(new NodeToExpand(node, NodeId.Null, Opc.Ua.NodeClass.Unspecified, null, null, null, e.ToServiceResultModel())); } } if (!TryMoveToNextNode()) { // Complete return await EndAsync(context).ConfigureAwait(false); } } return []; } /// /// Return remaining entries /// /// /// private async ValueTask>> EndAsync( ServiceCallContext context) { var results = new List>(); var ids = new HashSet(); var goodNodes = _expanded .Where(e => !e.HasErrors) .SelectMany(r => r.GetAllOpcNodeModels(context.Session.MessageContext, _request.UseBrowseNameAsDisplayName, ids)) .ToList(); if (goodNodes.Count > 0) { var result = await SaveEntryAsync(new ServiceResponse { Result = _entry with { OpcNodes = goodNodes } }, context.Ct).ConfigureAwait(false); if (!_request.DiscardErrors || result.ErrorInfo == null) { // Add good entry results.Add(result); } } if (!_request.DiscardErrors) { var badNodes = _expanded .Where(e => e.HasErrors) .SelectMany(e => e.ErrorInfos .Select(error => (error, e .GetAllOpcNodeModels(context.Session.MessageContext, _request.UseBrowseNameAsDisplayName, ids, true) .ToList()))) .GroupBy(e => e.error) .SelectMany(r => r.Select(r => r)) .ToList(); foreach (var entry in badNodes) { // Return bad entries results.Add(new ServiceResponse { ErrorInfo = entry.error, Result = _entry with { OpcNodes = entry.Item2 } }); } } _nodeIndex = -1; _expanded.Clear(); return results; } /// /// Try move to next node /// /// private bool TryMoveToNextNode() { Debug.Assert(_currentObject == null); _nodeIndex++; for (; _nodeIndex < _expanded.Count; _nodeIndex++) { switch (CurrentNode.NodeClass) { case (uint)Opc.Ua.NodeClass.Object: // Resolve all objects under this object Debug.Assert(!NodeId.IsNull(CurrentNode.NodeId)); if (!_request.ExcludeRootIfInstanceNode) { // Add root CurrentNode.AddObjectsOrVariables( new BrowseFrame(CurrentNode.NodeId!).YieldReturn()); if (_request.MaxDepth == 0) { // We have the object - browse it now return TryMoveToNextObject(); } } var depth = _request.MaxDepth == 0 ? 1 : _request.MaxDepth; Restart( CurrentNode.NodeId == null ? null : new BrowseFrame(CurrentNode.NodeId), maxDepth: depth, referenceTypeId: ReferenceTypeIds.HierarchicalReferences); return true; case (uint)Opc.Ua.NodeClass.VariableType: case (uint)Opc.Ua.NodeClass.ObjectType: // Resolve all objects of this type Debug.Assert(!NodeId.IsNull(CurrentNode.NodeId)); var instanceClass = CurrentNode.NodeClass == (uint)Opc.Ua.NodeClass.ObjectType ? Opc.Ua.NodeClass.Object : Opc.Ua.NodeClass.Variable; Restart(null, maxDepth: _request.MaxDepth, typeDefinitionId: CurrentNode.NodeId, referenceTypeId: ReferenceTypeIds.HierarchicalReferences, matchClass: instanceClass); return true; case (uint)Opc.Ua.NodeClass.Variable: if (!_request.ExcludeRootIfInstanceNode) { // Add root CurrentNode.AddObjectsOrVariables( new BrowseFrame(CurrentNode.NodeId!).YieldReturn()); if (_request.MaxLevelsToExpand == 0) { // Done - already a variable - stays in the original entry break; } } // Now we expand the variable here Restart(CurrentNode.NodeId == null ? null : new BrowseFrame(CurrentNode.NodeId), _request.MaxLevelsToExpand == 0 ? 1 : _request.MaxLevelsToExpand, referenceTypeId: ReferenceTypeIds.Aggregates, nodeClass: Opc.Ua.NodeClass.Variable); return true; case (uint)Opc.Ua.NodeClass.Unspecified: // There should already be an error here if (CurrentNode.HasErrors) { break; } goto default; default: CurrentNode.AddErrorInfo(StatusCodes.BadNotSupported, $"Node class {CurrentNode.NodeClass} not supported."); break; } } return TryMoveToNextObject(); } /// /// Find next object to expand /// /// private bool TryMoveToNextObject() { foreach (var node in _expanded) { if (node.TryGetNextObject(out _currentObject)) { Debug.Assert(_currentObject != null); // // Now we are at the level where we expand the variables and optionally methods of // the object. This will match variables and variables in variables (properties). // as well as methods if included. // var nodeClass = Opc.Ua.NodeClass.Variable; var matchClass = Opc.Ua.NodeClass.Variable; var maxDepth = _request.MaxLevelsToExpand != 0 ? _request.MaxLevelsToExpand : (uint?)null; if (_request.IncludeMethods) { // Include methods in the match matchClass |= Opc.Ua.NodeClass.Method; } // // If the original node class was object type we also search for sub components // of the object found (other aggregates). We match variables if we flatten // and objects and variables when we want to create individual entries per object // if (_currentObject.OriginalNode.NodeClass == (uint)Opc.Ua.NodeClass.ObjectType) { nodeClass |= Opc.Ua.NodeClass.Object; if (!_request.FlattenTypeInstance) { // Match not just variables but also objects and expand them matchClass |= Opc.Ua.NodeClass.Object; } // maxDepth = null; } Restart(_currentObject.ObjectFromBrowse, maxDepth, referenceTypeId: ReferenceTypeIds.Aggregates, nodeClass: nodeClass, matchClass: matchClass); return true; } } return false; } /// /// Save entry if update is enabled /// /// /// /// private async ValueTask> SaveEntryAsync( ServiceResponse entry, CancellationToken ct) { Debug.Assert(entry.Result != null); Debug.Assert(entry.Result.OpcNodes != null); Debug.Assert(entry.ErrorInfo == null); try { ConfigurationServices.ValidateNodes(entry.Result.OpcNodes); if (_configuration != null) { await _configuration.CreateOrUpdateDataSetWriterEntryAsync(entry.Result, ct).ConfigureAwait(false); } return entry; } catch (Exception ex) { return entry with { ErrorInfo = ex.ToServiceResultModel() }; } } /// /// Get current node to expand /// private NodeToExpand CurrentNode { get { Debug.Assert(_nodeIndex < _expanded.Count); return _expanded[_nodeIndex]; } } /// /// Node that should be expanded /// internal record class NodeToExpand { public IEnumerable ErrorInfos => _errorInfos; public bool HasErrors => _errorInfos.Count > 0; public bool ContainsObjects => _objects.Count > 0; public ObjectToExpand Variables { get; } /// /// Original node from configuration /// public OpcNodeModel NodeFromConfiguration { get; } /// /// Node id that should be expanded /// public NodeId? NodeId { get; } /// /// Node class of the node /// public uint NodeClass { get; } /// /// Event Notifier of the node /// public byte EventNotifier { get; } /// /// Create node to expand /// /// /// /// /// /// /// /// public NodeToExpand(OpcNodeModel nodeFromConfiguration, NodeId? nodeId, Opc.Ua.NodeClass nodeClass, QualifiedName? browseName, LocalizedText? displayName, ExpandedNodeId? typeDefinitionId, ServiceResultModel? errorInfo) { NodeFromConfiguration = nodeFromConfiguration; NodeId = nodeId; NodeClass = (uint)nodeClass; if (errorInfo != null) { AddErrorInfo(errorInfo); } // Hold variables resolved from a variable or variable type Variables = new ObjectToExpand(new BrowseFrame( nodeId ?? NodeId.Null, browseName ?? "Variables", displayName?.Text ?? "Variables", typeDefinitionId, nodeClass), this); } /// /// Opc node model configurations over all objects /// /// /// /// /// /// public IEnumerable GetAllOpcNodeModels(IServiceMessageContext context, bool useBrowseNameAsDisplayName, HashSet? ids = null, bool error = false) { switch (NodeClass) { case (uint)Opc.Ua.NodeClass.VariableType: case (uint)Opc.Ua.NodeClass.Variable: if (Variables.EntriesAlreadyReturned) { break; } var variables = Variables.GetOpcNodeModels(NodeFromConfiguration, context, useBrowseNameAsDisplayName, ids, true); if ((!error && NodeClass == (uint)Opc.Ua.NodeClass.VariableType) || ids?.Contains(NodeFromConfiguration.DataSetFieldId) == true) { // Only variables, not the root variable return variables; } return variables.Prepend(NodeFromConfiguration); case (uint)Opc.Ua.NodeClass.Object: case (uint)Opc.Ua.NodeClass.ObjectType: var objects = _objects .Where(o => !o.EntriesAlreadyReturned) .SelectMany(o => o.GetOpcNodeModels(NodeFromConfiguration, context, useBrowseNameAsDisplayName, ids, true)); if (!error) { return objects; } return objects.Prepend(NodeFromConfiguration); } return error ? [NodeFromConfiguration] : Array.Empty(); } /// /// Add objects or variables depending on the node class that is expanded /// /// public void AddObjectsOrVariables(IEnumerable frames) { switch (NodeClass) { case (uint)Opc.Ua.NodeClass.VariableType: case (uint)Opc.Ua.NodeClass.Variable: Variables.AddNodes(frames); break; default: _objects.AddRange(frames .Where(f => !NodeId.IsNull(f.NodeId) && _knownIds.Add(f.NodeId)) .Select(f => new ObjectToExpand(f, this))); break; } } /// /// Add error info /// /// /// public void AddErrorInfo(uint statusCode, string message) { _errorInfos.Add(new ServiceResultModel { ErrorMessage = message, StatusCode = statusCode }); } /// /// Add error info /// /// public void AddErrorInfo(ServiceResultModel? errorInfo) { if (errorInfo != null) { _errorInfos.Add(errorInfo); } } /// /// Move to next object /// /// /// public bool TryGetNextObject(out ObjectToExpand? obj) { if (_objectIndex < _objects.Count) { obj = _objects[_objectIndex]; _objectIndex++; return true; } obj = null; return false; } private readonly List _errorInfos = []; private readonly List _objects = []; private readonly HashSet _knownIds = []; private int _objectIndex; } /// /// The object to expand /// internal class ObjectToExpand { public BrowseFrame ObjectFromBrowse { get; } public NodeToExpand OriginalNode { get; } /// /// Create object to expand /// /// /// public ObjectToExpand(BrowseFrame objectFromBrowse, NodeToExpand originalNode) { ObjectFromBrowse = objectFromBrowse; OriginalNode = originalNode; } public bool EntriesAlreadyReturned { get; internal set; } public bool ContainsVariables => _variables.Count > 0; public bool ContainsMethods => _methods.Count > 0; public bool ContainsEvents => _eventTypesGenerated.Count > 0; /// /// Add variables /// /// /// public bool AddNodes(IEnumerable frames) { var duplicates = false; foreach (var frame in frames) { if (NodeId.IsNull(frame.NodeId)) { continue; } if (!_knownIds.Add(frame.NodeId)) { duplicates |= true; continue; } if (frame.NodeClass == Opc.Ua.NodeClass.Method) { // Add methods duplicates |= !_methods.Add(frame); } else { if (frame.Parent?.NodeId != null) { // Collect input and output arguments for later use if (frame.BrowseName == BrowseNames.InputArguments) { _input.AddOrUpdate(frame.Parent.NodeId, new MethodArgument(frame)); break; } else if (frame.BrowseName == BrowseNames.OutputArguments) { _output.AddOrUpdate(frame.Parent.NodeId, new MethodArgument(frame)); break; } } // Add variable duplicates |= !_variables.Add(frame); } } return duplicates; } /// /// Get node models /// /// /// /// /// /// /// public IEnumerable GetOpcNodeModels(OpcNodeModel template, IServiceMessageContext context, bool useBrowseNameAsDisplayName, HashSet? ids = null, bool createLongIds = false) { ids ??= []; if (EntriesAlreadyReturned) { return []; } // Get variable nodes var nodeModels = _variables.Select(variableFrame => template with { // Use absolute nodes Id = variableFrame.NodeId.AsString(context, NamespaceFormat.Expanded), AttributeId = NodeAttribute.Value, DataSetFieldId = CreateUniqueIdFromFrame(variableFrame.BrowsePath), DisplayName = !useBrowseNameAsDisplayName || variableFrame.BrowseName == null ? variableFrame.DisplayName : variableFrame.BrowseNameFromRootFrame(ObjectFromBrowse), // TODO - use browse paths instead: // Id = ObjectFromBrowse.NodeId.AsString(context, NamespaceFormat.Expanded) // BrowsePath = frame.BrowsePath.ToRelativePath(out var prefix).AsString(prefix), TypeDefinitionId = variableFrame.TypeDefinitionId?.AsString(context, NamespaceFormat.ExpandedWithNamespace0) }); // Add methods if any if (_eventTypesGenerated.Count != 0) { nodeModels = nodeModels.Concat(_eventTypesGenerated .SelectMany(eventSource => eventSource.Value.Select(eventType => template with { Id = _eventNotifier.AsString(context, NamespaceFormat.Expanded), AttributeId = NodeAttribute.EventNotifier, // DataSetClassFieldId = CreateUniqueIdFromFrame(_eventNotifierBrowsePath, // evt.BrowseName), DataSetFieldId = CreateUniqueIdFromFrame(eventSource.Key.BrowsePath, eventType.BrowseName), DisplayName = eventType.BrowseName?.Name ?? eventType.DisplayName.Text, // TODO: Set up the event filter to filter the source node and event type // EventFilter = new EventFilterModel(), // TODO - use browse paths instead: // Id = ObjectFromBrowse.NodeId.AsString(context, NamespaceFormat.Expanded) // BrowsePath = frame.BrowsePath.ToRelativePath(out var prefix).AsString(prefix), TypeDefinitionId = eventType.NodeId.AsString(context, NamespaceFormat.ExpandedWithNamespace0) }))); } // Add methods if any if (_methods.Count != 0) { nodeModels = nodeModels.Concat(_methods.Select(methodFrame => template with { Id = methodFrame.NodeId.AsString(context, NamespaceFormat.Expanded), DataSetFieldId = CreateUniqueIdFromFrame(methodFrame.BrowsePath), DisplayName = !useBrowseNameAsDisplayName || methodFrame.BrowseName == null ? methodFrame.DisplayName : methodFrame.BrowseNameFromRootFrame(ObjectFromBrowse), // TODO - use browse paths instead: // Id = ObjectFromBrowse.NodeId.AsString(context, NamespaceFormat.Expanded) // BrowsePath = frame.BrowsePath.ToRelativePath(out var prefix).AsString(prefix), MethodMetadata = new MethodMetadataModel { InputArguments = _input.TryGetValue(methodFrame.NodeId, out var input) ? input.Arguments : [], OutputArguments = _output.TryGetValue(methodFrame.NodeId, out var output) ? output.Arguments : [], ObjectId = methodFrame.Parent?.NodeId?.AsString(context, NamespaceFormat.Expanded) }, TypeDefinitionId = methodFrame.TypeDefinitionId?.AsString(context, NamespaceFormat.ExpandedWithNamespace0) })); } string CreateUniqueIdFromFrame(string? browsePath, QualifiedName? extra = null) { var id = template.DataSetFieldId ?? string.Empty; id = createLongIds ? $"{id}{ObjectFromBrowse.BrowsePath}{browsePath ?? string.Empty}" : $"{id}{browsePath ?? string.Empty}"; if (extra != null) { id = $"{id}/{extra.Name}"; } var uniqueId = id; for (var index = 1; !ids.Add(uniqueId); index++) { uniqueId = $"{id}_{index}"; } return uniqueId; } return nodeModels; } /// /// Create writer id for the object /// /// public string CreateWriterId() { var sb = new StringBuilder(); if (OriginalNode.NodeFromConfiguration.DataSetFieldId != null) { sb = sb.Append(OriginalNode.NodeFromConfiguration.DataSetFieldId); } return sb.Append(ObjectFromBrowse.BrowsePath).ToString(); } /// /// Complete object /// /// /// /// internal async Task CompleteAsync(RequestHeader requestHeader, ServiceCallContext context) { // // Find events anything in this set generates, then find the event notifier for them // The SourceNode of GeneratesEvent and AlwaysGeneratesEvent is limited to ObjectType, // VariableType AND Method InstanceDeclaration Nodes on ObjectTypes (not objects!). // try { var browseDescriptions = _variables .Concat(_methods) .Append(ObjectFromBrowse) .Where(t => !NodeId.IsNull(t.TypeDefinitionId)) .Select(t => new BrowseDescription { Handle = t, NodeId = ExpandedNodeId.ToNodeId( t.TypeDefinitionId, context.Session.MessageContext.NamespaceUris)!, ReferenceTypeId = ReferenceTypeIds.GeneratesEvent, IncludeSubtypes = true, BrowseDirection = Opc.Ua.BrowseDirection.Forward, NodeClassMask = (uint)Opc.Ua.NodeClass.ObjectType, ResultMask = (uint)BrowseResultMask.All }) .ToArray(); _eventTypesGenerated.Clear(); if (browseDescriptions.Length != 0) { await foreach (var result in context.Session.BrowseAsync(requestHeader, null, browseDescriptions, context.Ct).ConfigureAwait(false)) { if (result.ErrorInfo != null) { OriginalNode.AddErrorInfo(result.ErrorInfo); continue; } Debug.Assert(result.References != null); Debug.Assert(result.Description != null); if (result.References.Count == 0) { // No events generated continue; } var originalFrame = (BrowseFrame)result.Description.Handle; if (!_eventTypesGenerated.TryGetValue(originalFrame, out var eventList)) { eventList = []; _eventTypesGenerated.Add(originalFrame, eventList); } eventList.AddRange(result.References); } } if (_eventTypesGenerated.Count > 0) { // Find the event notifier. This should use HasEventSource if possible, but we just // try and find it in the objects to the root here var readValueIds = ObjectFromBrowse.AllFramesToRoot .Where(f => f.NodeClass == Opc.Ua.NodeClass.Object && !NodeId.IsNull(f.NodeId)) .Select(f => new ReadValueId { Handle = f, NodeId = f.NodeId, AttributeId = Attributes.EventNotifier }) .ToArray(); _eventNotifier = ObjectIds.Server; _eventNotifierBrowsePath = null; if (readValueIds.Length != 0) { var response = await context.Session.Services.ReadAsync(requestHeader, 0, Opc.Ua.TimestampsToReturn.Neither, readValueIds, context.Ct).ConfigureAwait(false); var readResults = response.Validate(response.Results, s => s.StatusCode, response.DiagnosticInfos, readValueIds); if (readResults.ErrorInfo != null) { OriginalNode.AddErrorInfo(readResults.ErrorInfo); } else { var result = readResults.FirstOrDefault(IsSubscribeToEvents); if (result != null) { _eventNotifier = result.Request.NodeId; _eventNotifierBrowsePath = ((BrowseFrame)result.Request.Handle).BrowsePath; } } } static bool IsSubscribeToEvents(ServiceResponse.Operation operation) { if (operation.ErrorInfo != null) { return false; } var eventNotifier = operation.Result.GetValue(0); if ((eventNotifier & EventNotifiers.SubscribeToEvents) != 0) { return true; } return false; } } } catch (Exception ex) { OriginalNode.AddErrorInfo(ex.ToServiceResultModel()); } if (ContainsMethods) { foreach (var input in _input.Values) { await input.ExpandAsync(context, requestHeader).ConfigureAwait(false); if (input.ErrorInfo != null) { // If input argument cannot be resolved, we do not // return it as part of the metadata. _input.Remove(input.BrowseFrame.NodeId); OriginalNode.AddErrorInfo(input.ErrorInfo); } } foreach (var output in _output.Values) { await output.ExpandAsync(context, requestHeader).ConfigureAwait(false); if (output.ErrorInfo != null) { // If output argument cannot be resolved, we do not // return it as part of the metadata. _output.Remove(output.BrowseFrame.NodeId); OriginalNode.AddErrorInfo(output.ErrorInfo); } } } } private readonly HashSet _knownIds = []; private readonly HashSet _methods = []; private readonly Dictionary _input = []; private readonly Dictionary _output = []; private readonly HashSet _variables = []; private readonly Dictionary> _eventTypesGenerated = []; private NodeId _eventNotifier = ObjectIds.Server; private string? _eventNotifierBrowsePath; } /// /// Respresents a method argument. /// /// internal record MethodArgument(BrowseFrame BrowseFrame) { /// /// Error info if not resolvable /// public ServiceResultModel? ErrorInfo { get; private set; } = kDefaultError; /// /// The arguments in order /// public List Arguments { get; } = []; /// /// Resolve the argument /// /// /// /// public async ValueTask ExpandAsync(ServiceCallContext context, RequestHeader header) { var (value, errorInfo) = await context.Session.ReadValueAsync(header, BrowseFrame.NodeId, context.Ct).ConfigureAwait(false); if (errorInfo != null) { ErrorInfo = errorInfo; return; } ErrorInfo = null; // Mark as processed if (value?.Value is not ExtensionObject[] argumentsList) { return; } Arguments.Clear(); foreach (var argument in argumentsList.Select(a => (Argument)a.Body)) { var (dataTypeIdNode, errorInfo2) = await context.Session.ReadNodeAsync( header, argument.DataType, null, false, false, NamespaceFormat.Expanded, false, context.Ct).ConfigureAwait(false); var arg = new MethodMetadataArgumentModel { Name = argument.Name, DefaultValue = argument.Value == null ? VariantValue.Null : context.Session.Codec.Encode(new Variant(argument.Value), out var type), ValueRank = argument.ValueRank == ValueRanks.Scalar ? null : (global::Azure.IIoT.OpcUa.Publisher.Models.NodeValueRank)argument.ValueRank, ArrayDimensions = argument.ArrayDimensions?.Count > 0 ? argument.ArrayDimensions?.ToArray() : null, Description = string.IsNullOrEmpty(argument?.Description.Text) ? null : argument.Description.Text, ErrorInfo = errorInfo2, Type = dataTypeIdNode with { // Compress by removing non relevant fields WriteMask = null, UserAccessLevel = null, UserWriteMask = null, AccessLevel = null, Children = null, SourcePicoseconds = null, ServerPicoseconds = null, ServerTimestamp = null, SourceTimestamp = null, } }; Arguments.Add(arg); } } private static readonly ServiceResultModel kDefaultError = ((ServiceResult)StatusCodes.BadInternalError).ToServiceResultModel(); } private int _nodeIndex = -1; private ObjectToExpand? _currentObject; private readonly List _expanded = []; private readonly PublishedNodesEntryModel _entry; private readonly PublishedNodeExpansionModel _request; private readonly IPublishedNodesServices? _configuration; private readonly ILogger _logger; private readonly bool _allowNoResolution; } /// /// Source-generated logging extensions for ConfigurationBrowser /// internal static partial class ConfigurationBrowserLogging { private const int EventClass = 100; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Error, Message = "Error expanding node {Node}: {Error}")] public static partial void HandleError(this ILogger logger, ConfigurationBrowser.NodeToExpand node, ServiceResultModel error); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Debug, Message = "Dropped duplicate variables or methods found.")] public static partial void DroppedDuplicateItems(this ILogger logger); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Services/ConfigurationServices.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Services { using Azure.IIoT.OpcUa.Publisher; using Azure.IIoT.OpcUa.Publisher.Config.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Stack.Extensions; using Furly.Exceptions; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Opc.Ua; using Opc.Ua.Extensions; using System; using System.Buffers; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; /// /// Configuration services uses the address space and services of a connected server to /// configure the publisher. The configuration services allow interactive expansion of /// published nodes. /// public sealed class ConfigurationServices : IConfigurationServices, IAssetConfiguration, IAssetConfiguration, IDisposable { /// /// Create configuration services /// /// /// /// /// /// public ConfigurationServices(IPublishedNodesServices configuration, IOpcUaClientManager client, IOptions options, ILogger logger, TimeProvider? timeProvider = null) { _configuration = configuration; _client = client; _options = options; _logger = logger; _timeProvider = timeProvider ?? TimeProvider.System; } /// public IAsyncEnumerable> ExpandAsync( PublishedNodesEntryModel entry, PublishedNodeExpansionModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(entry); ArgumentNullException.ThrowIfNull(entry.OpcNodes); ValidateNodes(entry.OpcNodes); var browser = new ConfigurationBrowser(entry, request, _options, null, _logger, _timeProvider); return _client.ExecuteAsync(entry.ToConnectionModel(), browser, request.Header, ct); } /// public IAsyncEnumerable> CreateOrUpdateAsync( PublishedNodesEntryModel entry, PublishedNodeExpansionModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(entry); ArgumentNullException.ThrowIfNull(entry.OpcNodes); ValidateNodes(entry.OpcNodes); var browser = new ConfigurationBrowser(entry, request, _options, _configuration, _logger, _timeProvider); return _client.ExecuteAsync(entry.ToConnectionModel(), browser, request.Header, ct); } /// public async Task> CreateOrUpdateAssetAsync( PublishedNodeCreateAssetRequestModel request, CancellationToken ct) { var stream = new MemoryStream(request.Configuration); await using var _ = stream.ConfigureAwait(false); var requestWithStream = new PublishedNodeCreateAssetRequestModel { Configuration = stream, Entry = request.Entry, Header = request.Header, WaitTime = request.WaitTime }; return await CreateOrUpdateAssetAsync(requestWithStream, ct).ConfigureAwait(false); } /// public IAsyncEnumerable> GetAllAssetsAsync( PublishedNodesEntryModel entry, RequestHeaderModel? header, CancellationToken ct) { ArgumentNullException.ThrowIfNull(entry); return CoreAsync(ct); async IAsyncEnumerable> CoreAsync( [EnumeratorCancellation] CancellationToken ct) { // Expand the wot node one level and expand each level var expansion = new PublishedNodeExpansionModel { ExcludeRootIfInstanceNode = true, MaxDepth = 1, // There is one asset level underneath the root connection node Header = header }; var browser = new ConfigurationBrowser(entry with { // Named object in the address space of the server. OpcNodes = [new() { Id = AssetsEx.Root }] }, expansion, _options, null, _logger, _timeProvider, true); // Browse and swap the data set writer id and data set name to make an asset entry. await foreach (var result in _client.ExecuteAsync(entry.ToConnectionModel(), browser, header, ct).ConfigureAwait(false)) { yield return result with { Result = result.Result == null ? null : result.Result with { DataSetWriterGroup = entry.DataSetWriterGroup, DataSetWriterId = result.Result.DataSetName, DataSetName = result.Result.DataSetWriterId?.TrimStart('/') // Asset name } }; } } } /// public async Task> CreateOrUpdateAssetAsync( PublishedNodeCreateAssetRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Configuration); ArgumentNullException.ThrowIfNull(request.Entry); ArgumentNullException.ThrowIfNull(request.Entry.DataSetWriterGroup); ArgumentNullException.ThrowIfNull(request.Entry.DataSetName); // Asset name using var trace = _activitySource.StartActivity("CreateOrUpdateAsset"); var entry = request.Entry; var connection = entry.ToConnectionModel(); ServiceResultModel? errorInfo; (entry, errorInfo) = await _client.ExecuteAsync(connection, async context => { // 1) Create asset and get asset file object var (nodeId, errorInfo) = await context.Session.CreateAssetAsync( request.Header.ToRequestHeader(_timeProvider), request.Entry.DataSetName, context.Ct).ConfigureAwait(false); // Asset name if (errorInfo != null || nodeId is null || NodeId.IsNull(nodeId)) { // TOOD errorInfo?.StatusCode == // Opc.Ua.StatusCodes.BadBrowseNameDuplicated errorInfo ??= new ServiceResultModel { StatusCode = StatusCodes.BadNodeIdInvalid, ErrorMessage = "Failed to create asset." }; return (entry with { DataSetWriterId = null }, errorInfo); } var assetId = nodeId.AsString(context.Session.MessageContext, NamespaceFormat.Expanded); entry = entry with { DataSetWriterId = assetId, OpcNodes = [ new () { Id = assetId, DataSetFieldId = entry.DataSetName // Asset name } ] }; // Find the created asset file (nodeId, errorInfo) = await context.Session.GetAssetFileAsync( request.Header.ToRequestHeader(_timeProvider), nodeId!, context.Ct).ConfigureAwait(false); if (errorInfo != null || nodeId is null || NodeId.IsNull(nodeId)) { errorInfo ??= new ServiceResultModel { StatusCode = StatusCodes.BadNotFound, ErrorMessage = "Asset did not have a file component." }; return (entry, errorInfo); } // 2) upload asset file var bufferSize = await context.Session.GetBufferSizeAsync( request.Header.ToRequestHeader(_timeProvider), nodeId, context.Ct).ConfigureAwait(false); var (fileHandle, openError) = await context.Session.OpenAsync( request.Header.ToRequestHeader(_timeProvider), nodeId, 0x2 | 0x4, context.Ct).ConfigureAwait(false); if (openError != null || !fileHandle.HasValue || NodeId.IsNull(nodeId)) { openError ??= new ServiceResultModel { StatusCode = StatusCodes.BadUserAccessDenied, ErrorMessage = "Asset file could not be opened for write." }; return (entry, openError); } while (true) { // Copy buffers to server var buffer = ArrayPool.Shared.Rent(bufferSize); try { var read = await request.Configuration.ReadAsync( buffer.AsMemory(), context.Ct).ConfigureAwait(false); if (read == 0) { break; } errorInfo = await context.Session.WriteAsync( request.Header.ToRequestHeader(_timeProvider), nodeId, fileHandle.Value, buffer.AsMemory()[..read], context.Ct).ConfigureAwait(false); if (errorInfo != null) { return (entry, errorInfo); } } catch (Exception ex) { return (entry, ex.ToServiceResultModel()); } finally { ArrayPool.Shared.Return(buffer); } } errorInfo = await context.Session.CloseAndUpdateAsync( request.Header.ToRequestHeader(_timeProvider), nodeId, fileHandle.Value, context.Ct).ConfigureAwait(false); return (entry, errorInfo); }, request.Header, ct).ConfigureAwait(false); // From now on we need to revert by deleting the asset if (errorInfo != null && errorInfo.StatusCode != 0) { if (entry.DataSetWriterId != null) { // Delete the asset for good house keeping sake await DeleteAssetAsync(request.Header, entry, ct).ConfigureAwait(false); } return new ServiceResponse { Result = entry, ErrorInfo = errorInfo }; } try { if (request.WaitTime.HasValue) { // // The asset is uploaded the nodes are being created, potentially // the session is disconnected now and the server is restarting. // We wait a bit here to ensure all of this has happened correctly. // await _timeProvider.Delay(request.WaitTime.Value, ct).ConfigureAwait(false); } // 3) Collect all created tags under the asset var browser = new ConfigurationBrowser(entry, new PublishedNodeExpansionModel { CreateSingleWriter = true, MaxDepth = 0, Header = request.Header }, _options, _configuration, _logger, _timeProvider); var results = new List>(); await foreach (var configurationResult in _client.ExecuteAsync( entry.ToConnectionModel(), browser, request.Header, ct).ConfigureAwait(false)) { results.Add(configurationResult); } // We only expect a single writer here, else it is a failure. if (results.Count != 1 || (results[0].ErrorInfo != null && results[0].ErrorInfo!.StatusCode != 0)) { // Could not create tags - delete the asset errorInfo = results.Select(r => r.ErrorInfo) .FirstOrDefault(r => r != null); errorInfo ??= new ServiceResultModel { StatusCode = StatusCodes.BadUnexpectedError, ErrorMessage = "Failed to find any tags for the asset." }; await DeleteAssetAsync(request.Header, entry, ct).ConfigureAwait(false); return new ServiceResponse { Result = entry, ErrorInfo = errorInfo }; } return results[0]; } catch (Exception ex) { await DeleteAssetAsync(request.Header, entry, ct).ConfigureAwait(false); return new ServiceResponse { Result = entry, ErrorInfo = ex.ToServiceResultModel() }; } } /// public async Task DeleteAssetAsync( PublishedNodeDeleteAssetRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Entry); ArgumentNullException.ThrowIfNull(request.Entry.DataSetWriterId); ArgumentNullException.ThrowIfNull(request.Entry.DataSetWriterGroup); using var trace = _activitySource.StartActivity("DeleteAsset"); // First remove the entry try { await _configuration.RemoveDataSetWriterEntryAsync( request.Entry.DataSetWriterGroup, request.Entry.DataSetWriterId, ct: ct).ConfigureAwait(false); } catch (Exception ex) { if (!request.Force) { return ex.ToServiceResultModel(); } _logger.DiscardErrorBecauseForceWasSet(ex); } var errorInfo = await DeleteAssetAsync(request.Header, request.Entry, ct).ConfigureAwait(false); return errorInfo ?? new ServiceResultModel(); } /// public void Dispose() { _activitySource.Dispose(); } /// /// Delete the asset /// /// /// /// /// private async Task DeleteAssetAsync(RequestHeaderModel? header, PublishedNodesEntryModel entry, CancellationToken ct) { return await _client.ExecuteAsync(entry.ToConnectionModel(), async context => { var assetId = entry.DataSetWriterId.ToNodeId(context.Session.MessageContext); if (NodeId.IsNull(assetId)) { return new ServiceResultModel { StatusCode = StatusCodes.BadNodeIdInvalid, ErrorMessage = "Invalid node id and browse path in file system object" }; } return await context.Session.DeleteAssetAsync(header.ToRequestHeader(_timeProvider), assetId, ct).ConfigureAwait(false); }, header, ct).ConfigureAwait(false); } /// /// Validate nodes are valid /// /// /// /// internal static IList ValidateNodes(IList opcNodes) { var set = new HashSet(); foreach (var node in opcNodes) { if (!node.TryGetId(out var id)) { throw new BadRequestException("Node must contain a node ID"); } node.DataSetFieldId ??= id; set.Add(node.DataSetFieldId); if (node.OpcPublishingInterval != null || node.OpcPublishingIntervalTimespan != null) { throw new BadRequestException( "Publishing interval not allowed on node level. " + "Must be set at writer level."); } } if (set.Count != opcNodes.Count) { throw new BadRequestException("Field ids must be present and unique."); } return opcNodes; } private readonly IPublishedNodesServices _configuration; private readonly IOptions _options; private readonly IOpcUaClientManager _client; private readonly ILogger _logger; private readonly TimeProvider _timeProvider; private readonly ActivitySource _activitySource = Diagnostics.NewActivitySource(); } /// /// Source-generated logging extensions for ConfigurationServices /// internal static partial class ConfigurationServicesLogging { private const int EventClass = 100; [LoggerMessage(EventId = EventClass + 0, Level = LogLevel.Information, Message = "Discard error because force was set.")] public static partial void DiscardErrorBecauseForceWasSet(this ILogger logger, Exception ex); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Services/DataSetWriter.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Services { using Azure.IIoT.OpcUa.Encoders; using Azure.IIoT.OpcUa.Encoders.PubSub; using Azure.IIoT.OpcUa.Publisher; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Furly.Extensions.Messaging; using Furly.Extensions.Serializers; using Microsoft.Extensions.Logging; using Nito.AsyncEx; using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; public sealed partial class WriterGroupDataSource { /// /// Represents a data set writer which acts as a partitioning mechanism /// depending on how the writers should be set up from the configuration. /// The partitioning uses the publishing interval - because we always did, /// as well as the routing and topic configuration. The data set writer /// key has the topics already resolved, so that comparison is straight /// forward. This replaces the previously used SubscriptionIdentifier /// and works in a similar way to manage a table of unique writers in /// the writer group. /// internal sealed class DataSetWriter { /// /// Publishing interval which is used to split subscriptions for /// supporting legacy behavior of writer per subscription. /// public TimeSpan? PublishingInterval { get; } /// /// Routed topic /// public string Topic => Writer.Publishing?.QueueName ?? "/"; /// /// Quality of service to use /// public QoS? Qos => Writer.Publishing?.RequestedDeliveryGuarantee; /// /// Message time to live /// public TimeSpan? Ttl => Writer.Publishing?.Ttl; /// /// Retain support /// public bool? Retain => Writer.Publishing?.Retain; /// /// Topic to route metadata to /// public string MetadataTopic => Writer.MetaData?.QueueName ?? "/"; /// /// Quality of service to use /// public QoS MetadataQos => Writer.MetaData?.RequestedDeliveryGuarantee ?? QoS.AtLeastOnce; /// /// Message time to live /// public TimeSpan? MetadataTtl => Writer.MetaData?.Ttl ?? Writer.MetaDataUpdateTime; /// /// Retain support /// public bool MetadataRetain => Writer.MetaData?.Retain ?? true; /// /// Resolved routing /// public DataSetRoutingMode Routing { get; } /// /// Full cloned configuration /// public DataSetWriterModel Writer { get; } /// /// Data set /// public PublishedDataSetModel DataSet => Writer.DataSet!; /// /// Data set source /// public PublishedDataSetSourceModel Source => DataSet.DataSetSource!; /// /// Split the writer in the group in its writer partitions depending on the publish /// settings. /// /// /// /// /// public static IEnumerable GetDataSetWriters(WriterGroupDataSource group, DataSetWriterModel dataSetWriter) { var options = group._options.Value; if (dataSetWriter?.DataSet?.DataSetSource == null) { throw new ArgumentException("DataSet source missing", nameof(dataSetWriter)); } var dataset = dataSetWriter.DataSet; var source = dataset.DataSetSource; var routing = dataset.Routing ?? options.DefaultDataSetRouting ?? DataSetRoutingMode.None; var dataSetClassId = dataset.DataSetMetaData?.DataSetClassId ?? Guid.Empty; var escWriterName = TopicFilter.Escape( dataSetWriter.DataSetWriterName ?? Constants.DefaultDataSetWriterName); var escWriterGroup = TopicFilter.Escape( group._writerGroup.Name ?? Constants.DefaultWriterGroupName); var escPublisherId = TopicFilter.Escape( group._writerGroup.PublisherId ?? options.PublisherId ?? Constants.DefaultPublisherId); var escDataSetTopicPath = escWriterName; var escDataSetName = escWriterName; if (dataset.Name != null) { escDataSetName = TopicFilter.Escape(dataset.Name); escDataSetTopicPath = string.Empty; foreach (var element in dataset.Name.Split('.', StringSplitOptions.RemoveEmptyEntries)) { if (string.IsNullOrEmpty(escDataSetTopicPath)) { escDataSetTopicPath = TopicFilter.Escape(element); } else { escDataSetTopicPath += "/" + TopicFilter.Escape(element); } } } var variables = new Dictionary { [PublisherConfig.PublisherIdKey] = escPublisherId, [PublisherConfig.DataSetWriterIdVariableName] = dataSetWriter.Id, [PublisherConfig.DataSetWriterVariableName] = escWriterName, [PublisherConfig.DataSetNameVariableName] = escDataSetName, [PublisherConfig.DataSetTopicPathVariableName] = escDataSetTopicPath, [PublisherConfig.DataSetWriterNameVariableName] = escWriterName, [PublisherConfig.DataSetClassIdVariableName] = dataSetClassId.ToString(), [PublisherConfig.WriterGroupIdVariableName] = group.Id, [PublisherConfig.DataSetWriterGroupVariableName] = escWriterGroup, [PublisherConfig.WriterGroupVariableName] = escWriterGroup // ... }; // No auto routing - group variables and events by publish settings var data = source.PublishedVariables?.PublishedData? .GroupBy(d => Resolve(options, group._writerGroup, dataSetWriter, d.Publishing, d.Id, routing, variables)); if (data != null) { if (routing == DataSetRoutingMode.None) { foreach (var items in data) { var id = dataSetWriter.Id; yield return CreateDataSetWriter(id, items.Key, items.ToList()); } } else { foreach (var (p, item) in data.SelectMany(d => d.Select(i => (d.Key, i)))) { var id = $"{dataSetWriter.Id}_{item.Id ?? item.GetHashCode().ToString(CultureInfo.InvariantCulture)}"; yield return CreateDataSetWriter(id, p, new[] { item }); } } } var evts = source.PublishedEvents?.PublishedData? .GroupBy(d => Resolve(options, group._writerGroup, dataSetWriter, d.Publishing, d.Id, routing, variables)); if (evts != null) { if (routing == DataSetRoutingMode.None) { foreach (var items in evts) { var id = dataSetWriter.Id; yield return CreateEventWriter(id, items.Key, items.ToList()); } } else { foreach (var (p, item) in evts.SelectMany(d => d.Select(i => (d.Key, i)))) { var id = $"{dataSetWriter.Id}_{item.Id ?? item.GetHashCode().ToString(CultureInfo.InvariantCulture)}"; yield return CreateEventWriter(id, p, new[] { item }); } } } DataSetWriter CreateDataSetWriter(string id, (PublishingQueueSettingsModel? Metadata, PublishingQueueSettingsModel? Messages) publishSettings, IReadOnlyList data) { return new DataSetWriter(group, routing, dataSetWriter with { Id = id, MetaData = publishSettings.Metadata, Publishing = publishSettings.Messages, DataSet = dataset with { DataSetMetaData = dataset.DataSetMetaData.Clone(), DataSetSource = source with { Connection = source.Connection.Clone(), SubscriptionSettings = source.SubscriptionSettings.Clone(), PublishedEvents = null, PublishedVariables = new PublishedDataItemsModel { PublishedData = data } } } }); } DataSetWriter CreateEventWriter(string id, (PublishingQueueSettingsModel? Metadata, PublishingQueueSettingsModel? Messages) publishSettings, IReadOnlyList data) { return new DataSetWriter(group, routing, dataSetWriter with { Id = id, MetaData = publishSettings.Metadata, Publishing = publishSettings.Messages, DataSet = dataset with { DataSetMetaData = dataset.DataSetMetaData.Clone(), DataSetSource = source with { Connection = source.Connection.Clone(), SubscriptionSettings = source.SubscriptionSettings.Clone(), PublishedEvents = new PublishedEventItemsModel { PublishedData = data }, PublishedVariables = null } } }); } // Resolve the publish queue settings with the data set writer provided settings. static (PublishingQueueSettingsModel?, PublishingQueueSettingsModel?) Resolve( PublisherOptions options, WriterGroupModel group, DataSetWriterModel dataSetWriter, PublishingQueueSettingsModel? settings, string? fieldId, DataSetRoutingMode routing, Dictionary variables) { var builder = new TopicBuilder(options, group.MessageType, new TopicTemplatesOptions { Telemetry = settings?.QueueName ?? dataSetWriter.Publishing?.QueueName ?? group.Publishing?.QueueName, DataSetMetaData = dataSetWriter.MetaData?.QueueName }, variables .Append(KeyValuePair .Create(PublisherConfig.DataSetFieldIdVariableName, TopicFilter.Escape(fieldId ?? string.Empty)))); var telemetryTopic = builder.TelemetryTopic; var metadataTopic = builder.DataSetMetaDataTopic; if (string.IsNullOrWhiteSpace(metadataTopic) || routing != DataSetRoutingMode.None) { metadataTopic = telemetryTopic; } var publishing = new PublishingQueueSettingsModel { QueueName = telemetryTopic, Ttl = settings?.Ttl ?? dataSetWriter.Publishing?.Ttl ?? group.Publishing?.Ttl, RequestedDeliveryGuarantee = settings?.RequestedDeliveryGuarantee ?? dataSetWriter.Publishing?.RequestedDeliveryGuarantee ?? group.Publishing?.RequestedDeliveryGuarantee, Retain = settings?.Retain ?? dataSetWriter.Publishing?.Retain ?? group.Publishing?.Retain }; var metadata = new PublishingQueueSettingsModel { QueueName = metadataTopic, Ttl = dataSetWriter.MetaData?.Ttl ?? publishing.Ttl, RequestedDeliveryGuarantee = dataSetWriter.MetaData?.RequestedDeliveryGuarantee ?? publishing.RequestedDeliveryGuarantee, Retain = dataSetWriter.MetaData?.Retain ?? publishing.Retain }; return (metadata, publishing); } } /// /// Create id from a DataSetWriterModel template /// /// /// /// private DataSetWriter(WriterGroupDataSource group, DataSetRoutingMode routing, DataSetWriterModel dataSetWriter) { Writer = dataSetWriter; Routing = routing; PublishingInterval = group._options.Value.IgnoreConfiguredPublishingIntervals == true ? null : Source.SubscriptionSettings?.PublishingInterval; } /// public override bool Equals(object? obj) { if (obj is DataSetWriter writer && writer.Writer.Id == Writer.Id && writer.PublishingInterval == PublishingInterval && writer.Topic == Topic && writer.Qos == Qos && writer.Ttl == Ttl && writer.Retain == Retain && writer.MetadataTopic == MetadataTopic && writer.MetadataQos == MetadataQos && writer.MetadataTtl == MetadataTtl && writer.MetadataRetain == MetadataRetain && writer.Routing == Routing) { return true; } return false; } /// public override int GetHashCode() { // // By default we partition on publishing interval and the // output configuration binding. // return HashCode.Combine(Writer.Id, PublishingInterval, Topic, HashCode.Combine(Qos, Ttl, Retain), MetadataTopic, HashCode.Combine(MetadataQos, MetadataTtl, MetadataRetain), Routing); } /// public override string? ToString() { return $"Writer {Writer.Id}->{Topic}@{PublishingInterval}"; } } /// /// A data set writer subscription binding inside a writer group /// private sealed class DataSetWriterSubscription : ISubscriber, IAsyncDisposable { /// /// Name of the data set writer in the writer group (unique) /// public string Name { get; private set; } /// /// Topic assigned to the writer /// public string Topic => _writer.Topic; /// /// Writer id /// public string Id => _writer.Writer.Id; /// /// Index of the data set writer in the group /// public int Index { get; set; } /// /// Meta data /// internal PublishedDataSetMessageSchemaModel? MetaData => _metaDataLoader.IsValueCreated ? _metaDataLoader.Value.MetaData : null; /// /// Metadata disabled /// internal bool IsMetadataDisabled => !SendMetadata && _group._options.Value.SchemaOptions == null; /// /// Metadata disabled /// internal bool SendMetadata => _writer.DataSet?.DataSetMetaData != null && _group._options.Value.DisableDataSetMetaData != true; /// /// Subscription id /// public IEnumerable MonitoredItems { get; private set; } /// /// Active subscription /// public ISubscription? Subscription { get; private set; } /// /// Create subscription from a DataSetWriterModel template /// /// /// /// /// private DataSetWriterSubscription(WriterGroupDataSource group, DataSetWriter writer, HashSet writerNames, ILogger logger) { _group = group; _writer = writer; _logger = logger; _metaDataLoader = new Lazy(() => new MetaDataLoader(this), true); Name = CreateUniqueWriterName(writer.Writer.DataSetWriterName, writerNames); logger.CreatingNewWriter(Id, Name, _group.Id); // Create monitored items var namespaceFormat = _group._writerGroup.MessageSettings?.NamespaceFormat ?? _group._options.Value.DefaultNamespaceFormat ?? NamespaceFormat.Uri; MonitoredItems = _writer.Source.ToMonitoredItems(namespaceFormat); _extensionFields = new ExtensionFields(_group._serializer, _writer.DataSet.ExtensionFields, _writer.Writer.DataSetFieldContentMask); _template = _writer.Source.SubscriptionSettings.ToSubscriptionModel( _writer.Routing != DataSetRoutingMode.None, _group._options.Value.IgnoreConfiguredPublishingIntervals); _connection = _writer.Writer.GetConnection(_group.Id, _group._options.Value); } /// /// Create subscription /// /// /// /// /// /// /// public async static ValueTask CreateAsync(WriterGroupDataSource group, DataSetWriter dataSetWriter, ILoggerFactory loggerFactory, HashSet writerNames, CancellationToken ct) { var writer = new DataSetWriterSubscription(group, dataSetWriter, writerNames, loggerFactory.CreateLogger()); writer.Subscription = await group._clients.CreateSubscriptionAsync( writer._connection.Connection, writer._template, writer, ct).ConfigureAwait(false); writer.InitializeMetaDataTrigger(); writer.InitializeKeepAlive(); group._logger.CreatedWriter(writer.Id, group.Id); return writer; } /// /// Update subscription content /// /// /// /// /// public async ValueTask UpdateAsync(DataSetWriter dataSetWriter, HashSet writerNames, CancellationToken ct) { _logger.UpdatingWriter(Id, _group.Id); var previous = _writer; _writer = dataSetWriter; if (previous.Writer.DataSetWriterName != _writer.Writer.DataSetWriterName) { writerNames.Remove(Name); Name = CreateUniqueWriterName(_writer.Writer.DataSetWriterName, writerNames); } var namespaceFormat = _group._writerGroup.MessageSettings?.NamespaceFormat ?? _group._options.Value.DefaultNamespaceFormat ?? NamespaceFormat.Uri; MonitoredItems = _writer.Source.ToMonitoredItems(namespaceFormat); _extensionFields = new ExtensionFields(_group._serializer, _writer.DataSet.ExtensionFields, _writer.Writer.DataSetFieldContentMask); var template = _writer.Source.SubscriptionSettings.ToSubscriptionModel( _writer.Routing != DataSetRoutingMode.None, _group._options.Value.IgnoreConfiguredPublishingIntervals); var connection = _writer.Writer.GetConnection(_group.Id, _group._options.Value); if (template != _template || connection != _connection || Subscription == null) { _template = template; _connection = connection; // // Create or new subscription for the writer group. This will automatically // dispose our older subscription or update it to comply if possible. // Subscription = await _group._clients.CreateSubscriptionAsync( _connection.Connection, _template, this, ct).ConfigureAwait(false); _logger.RecreatedSubscription(Id, _group.Id); } else { // Trigger reevaluation Subscription.NotifyMonitoredItemsChanged(); _logger.UpdatedMonitoredItems(Id, _group.Id); } _frameCount = 0; InitializeMetaDataTrigger(); InitializeKeepAlive(); } /// public async ValueTask DisposeAsync() { try { if (_disposed) { return; } if (_metaDataLoader.IsValueCreated) { await _metaDataLoader.Value.DisposeAsync().ConfigureAwait(false); } // We are under the writer group lock here, so we cannot grab it SendCloseNotifications(); _disposed = true; _metadataTimer?.Stop(); if (Subscription != null) { await Subscription.DisposeAsync().ConfigureAwait(false); Subscription = null; } _logger.ClosedWriter(Id, _group.Id); } finally { _metadataTimer?.Dispose(); _metadataTimer = null; } } /// public async Task OnMonitoredItemSemanticsChangedAsync(CancellationToken ct) { if (!IsMetadataDisabled) { // Reload metadata _metaDataLoader.Value.Reload(); var timeout = _group._options.Value.AsyncMetaDataLoadTimeout ?? TimeSpan.FromMinutes(1); if (timeout != TimeSpan.Zero) { await _metaDataLoader.Value.BlockUntilLoadedAsync(timeout, ct).ConfigureAwait(false); } } } /// public void OnSubscriptionKeepAlive(OpcUaSubscriptionNotification notification) { Interlocked.Increment(ref _group._keepAliveCount); if (_sendKeepAlives) { if (_sendKeepAliveAsKeyFrame) { notification.TryUpgradeToKeyFrame(this); } CallMessageReceiverDelegates(notification); } } /// public void OnSubscriptionDataChangeReceived(OpcUaSubscriptionNotification notification) { CallMessageReceiverDelegates(ProcessKeyFrame(notification)); OpcUaSubscriptionNotification ProcessKeyFrame(OpcUaSubscriptionNotification notification) { var keyFrameCount = _writer.Writer.KeyFrameCount ?? _group._options.Value.DefaultKeyFrameCount ?? 0; if (keyFrameCount > 0) { var frameCount = Interlocked.Increment(ref _frameCount); if (((frameCount - 1) % keyFrameCount) == 0) { notification.TryUpgradeToKeyFrame(this); } } return notification; } } /// public void OnSubscriptionCyclicReadCompleted(OpcUaSubscriptionNotification notification) { CallMessageReceiverDelegates(notification); } /// public void OnSubscriptionEventReceived(OpcUaSubscriptionNotification notification) { CallMessageReceiverDelegates(notification); } /// public void OnSubscriptionDataDiagnosticsChange(bool liveData, int valueChanges, int overflow, int heartbeats) { lock (_lock) { _group._heartbeats.Count += heartbeats; _group._overflows.Count += overflow; if (liveData) { if (_group._dataChanges.Count >= kNumberOfInvokedMessagesResetThreshold || _group._valueChanges.Count >= kNumberOfInvokedMessagesResetThreshold) { _logger.NotificationsCounterReset((int)_group._dataChanges.Count, (int)_group._valueChanges.Count); _group._dataChanges.Count = 0; _group._valueChanges.Count = 0; _group._heartbeats.Count = 0; _group._sink.OnCounterReset(); } _group._valueChanges.Count += valueChanges; _group._dataChanges.Count++; } } } /// public void OnSubscriptionCyclicReadDiagnosticsChange(int valuesSampled, int overflow) { lock (_lock) { _group._overflows.Count += overflow; if (_group._dataChanges.Count >= kNumberOfInvokedMessagesResetThreshold || _group._sampledValues.Count >= kNumberOfInvokedMessagesResetThreshold) { _logger.NotificationsCounterResetRead((int)_group._cyclicReads.Count, (int)_group._sampledValues.Count); _group._cyclicReads.Count = 0; _group._sampledValues.Count = 0; _group._sink.OnCounterReset(); } _group._sampledValues.Count += valuesSampled; _group._cyclicReads.Count++; } } /// public void OnSubscriptionEventDiagnosticsChange(bool liveData, int events, int overflow, int modelChanges) { lock (_lock) { _group._modelChanges.Count += modelChanges; _group._overflows.Count += overflow; if (liveData) { if (_group._events.Count >= kNumberOfInvokedMessagesResetThreshold || _group._eventNotification.Count >= kNumberOfInvokedMessagesResetThreshold) { _logger.NotificationsCounterResetEvent((int)_group._events.Count, (int)_group._eventNotification.Count); _group._events.Count = 0; _group._eventNotification.Count = 0; _group._modelChanges.Count = 0; _group._sink.OnCounterReset(); } _group._eventNotification.Count += events; _group._events.Count++; } } } /// /// Initialize sending of keep alive messages /// private void InitializeKeepAlive() { _sendKeepAlives = _writer.DataSet?.SendKeepAlive ?? _group._options.Value.EnableDataSetKeepAlives == true; _sendKeepAliveAsKeyFrame = _sendKeepAlives && (_writer.DataSet?.KeepAliveAsKeyFrame ?? _group._options.Value.SendDataSetKeepAlivesAsKeyFrame == true); } /// /// Initializes the Metadata triggering mechanism from the cconfiguration model /// private void InitializeMetaDataTrigger() { var metaDataSendInterval = _writer.Writer.MetaDataUpdateTime ?? _group._options.Value.DefaultMetaDataUpdateTime ?? TimeSpan.Zero; if (metaDataSendInterval > TimeSpan.Zero && SendMetadata) { if (_metadataTimer == null) { _metadataTimer = new TimerEx(metaDataSendInterval, _group._timeProvider); _metadataTimer.Elapsed += MetadataTimerElapsed; _metadataTimer.Start(); } else { _metadataTimer.Interval = metaDataSendInterval; } } else { if (_metadataTimer != null) { _metadataTimer.Stop(); _metadataTimer.Dispose(); _metadataTimer = null; } } } /// /// Fired when metadata time elapsed /// /// /// private void MetadataTimerElapsed(object? sender, ElapsedEventArgs e) { try { var timer = _metadataTimer; if (timer == null) { return; } timer.Enabled = false; // Enabled again after calling message receiver delegate } catch (ObjectDisposedException) { // Disposed while being invoked return; } var notification = Subscription?.CreateKeepAlive(); if (notification != null) { // This call udpates the message type, so no need to do it here. CallMessageReceiverDelegates(notification, true); } else { // Failed to send, try again later InitializeMetaDataTrigger(); } } /// /// handle subscription change messages /// /// /// private void CallMessageReceiverDelegates(OpcUaSubscriptionNotification notification, bool sourceIsMetaDataTimer = false) { try { var metadata = GetMetadata(_group._options.Value.AsyncMetaDataLoadTimeout ?? TimeSpan.FromSeconds(1)); _group.GetSchemaAndWriterGroup(_writer.Topic, out var writerGroup, out var networkMessageSchema); lock (_lock) { var single = notification.Notifications?.Count == 1 ? notification.Notifications[0] : null; if (SendMetadata) { if (metadata != null) { var sendMetadata = sourceIsMetaDataTimer; // // Only send if called from metadata timer or if the metadata version changes. // if (_lastMajorVersion != metadata.MetaData.DataSetMetaData.MajorVersion || _lastMinorVersion != metadata.MetaData.MinorVersion) { _lastMajorVersion = metadata.MetaData.DataSetMetaData.MajorVersion; _lastMinorVersion = metadata.MetaData.MinorVersion; Interlocked.Increment(ref _group._metadataChanges); sendMetadata = true; } if (sendMetadata) { #pragma warning disable CA2000 // Dispose objects before losing scope var metadataFrame = new OpcUaSubscriptionNotification(notification) { MessageType = MessageType.Metadata, EventTypeName = null, Context = CreateMessageContext(writerGroup, notification, _writer.MetadataTopic, _writer.MetadataQos, _writer.MetadataRetain, _writer.MetadataTtl, () => Interlocked.Increment(ref _metadataSequenceNumber), true, null, single, metadata) }; #pragma warning restore CA2000 // Dispose objects before losing scope _group._sink.OnMessage(metadataFrame); InitializeMetaDataTrigger(); } } else { _logger.NoMetadataAvailable(_writer); Interlocked.Increment(ref _group._messagesWithoutMetadata); } } if (!sourceIsMetaDataTimer) { Debug.Assert(notification.Notifications != null); notification.Context = CreateMessageContext(writerGroup, notification, _writer.Topic, _writer.Qos, _writer.Retain, _writer.Ttl, () => Interlocked.Increment(ref _dataSetSequenceNumber), false, networkMessageSchema, single, metadata); _logger.EnqueuingNotification(notification.ToString()); _group._sink.OnMessage(notification); } } } catch (Exception ex) { _logger.FailedToProduceMessage(ex); } } /// /// Get metadata for the writer and block until it is available /// /// /// internal PublishedDataSetMessageSchemaModel? GetMetadata(TimeSpan timeout) { PublishedDataSetMessageSchemaModel? metadata; lock (_lock) { metadata = MetaData; if (metadata == null && !IsMetadataDisabled) { if (timeout != TimeSpan.Zero) { var sw = Stopwatch.StartNew(); // Block until we have metadata or just continue _metaDataLoader.Value.BlockUntilLoaded(timeout); _logger.BlockedMessageForMetadata(sw.Elapsed, _writer); } metadata = MetaData; } } return metadata; } /// /// Create message context for notification /// /// /// /// /// /// /// /// /// /// /// /// /// private DataSetWriterContext CreateMessageContext(WriterGroupModel writerGroup, OpcUaSubscriptionNotification notification, string topic, QoS? qos, bool? retain, TimeSpan? ttl, Func sequenceNumber, bool isMetadata, IEventSchema? networkMessageSchema = null, MonitoredItemNotificationModel? single = null, PublishedDataSetMessageSchemaModel? metadata = null) { return new DataSetWriterContext { PublisherId = writerGroup.PublisherId ?? _group._options.Value.PublisherId ?? Constants.DefaultPublisherId, DataSetWriterId = (ushort)Index, MetaData = metadata, Writer = _writer.Writer, ExtensionFields = _extensionFields.GetExtensionFieldData(notification), WriterName = Name, NextWriterSequenceNumber = sequenceNumber, WriterGroup = writerGroup, Schema = networkMessageSchema, CloudEvent = GetCloudEventHeader(writerGroup, notification, isMetadata), Topic = GetTopic(_writer.Routing, topic, single?.PathFromRoot), Retain = retain, Ttl = ttl, Qos = qos }; CloudEventHeader? GetCloudEventHeader(WriterGroupModel writerGroup, OpcUaSubscriptionNotification notification, bool isMetadata) { if (_group._options.Value.EnableCloudEvents != true) { return null; } var type = isMetadata ? "Metadata" : notification.MessageType == MessageType.Event ? "Event" : "Dataset"; var typeName = _writer.Writer.DataSet?.Type ?? notification.EventTypeName; if (!string.IsNullOrEmpty(typeName)) { type += "/" + typeName; } if (!Uri.TryCreate(_writer.Writer.DataSet?.DataSetSource?.Uri ?? notification.ApplicationUri ?? notification.EndpointUrl, UriKind.Absolute, out var source)) { // Set a default source source = new Uri("urn:" + _writer.Writer.DataSet?.DataSetSource?.Uri ?? writerGroup.PublisherId ?? _group._options.Value.PublisherId ?? "publisher"); } var messageId = Guid.CreateVersion7(_group._timeProvider.GetUtcNow()); return new CloudEventHeader { Id = $"{messageId:N}/{notification.SequenceNumber:X}", Time = notification.PublishTimestamp, Type = type, Source = source, Subject = _writer.Writer.DataSet?.Subject }; } static string GetTopic(DataSetRoutingMode routing, string topic, Opc.Ua.RelativePath? subpath) { if (subpath == null || routing == DataSetRoutingMode.None) { return topic; } // Append subpath to topic (use browse names with namespace index if requested var sb = new StringBuilder().Append(topic); foreach (var path in subpath.Elements) { sb.Append('/'); if (path.TargetName.NamespaceIndex != 0 && routing == DataSetRoutingMode.UseBrowseNamesWithNamespaceIndex) { sb.Append(path.TargetName.NamespaceIndex).Append(':'); } sb.Append(TopicFilter.Escape(path.TargetName.Name)); } return sb.ToString(); } } /// /// Send final close messages to sink. This happens under lock of writer group. /// This will trigger an empty message and cleanup of any messages stuck in the topic /// private void SendCloseNotifications() { Debug.Assert(_group._lock.CurrentCount == 0, "This happens under lock of writer group."); // Notify close to clean up the topic content if needed if (SendMetadata) { #pragma warning disable CA2000 // Dispose objects before losing scope var metadataFrame = new OpcUaSubscriptionNotification(_group._timeProvider.GetUtcNow()) { MessageType = MessageType.Closed }; #pragma warning restore CA2000 // Dispose objects before losing scope metadataFrame.Context = CreateMessageContext(_group._writerGroup, metadataFrame, _writer.MetadataTopic, _writer.MetadataQos, false, null, () => Interlocked.Increment(ref _metadataSequenceNumber), true); _group._sink.OnMessage(metadataFrame); } #pragma warning disable CA2000 // Dispose objects before losing scope var notification = new OpcUaSubscriptionNotification(_group._timeProvider.GetUtcNow()) { MessageType = MessageType.Closed }; #pragma warning restore CA2000 // Dispose objects before losing scope notification.Context = CreateMessageContext(_group._writerGroup, notification, _writer.Topic, _writer.Qos, false, null, () => Interlocked.Increment(ref _dataSetSequenceNumber), false); _group._sink.OnMessage(notification); } /// /// Make unique writer name /// /// /// /// private static string CreateUniqueWriterName(string? str, HashSet strings) { var originalName = str ?? Constants.DefaultDataSetWriterName; var uniqueName = originalName; for (var index = 1; ; index++) { if (strings.Add(uniqueName)) { return uniqueName; } uniqueName = $"{originalName}{index}"; } } /// /// Asynchronously load metadata after the subscription is created and metadata /// has changed event is received. /// private sealed class MetaDataLoader : IAsyncDisposable { /// /// Current meta data /// public PublishedDataSetMessageSchemaModel? MetaData { get; private set; } /// /// Create loader /// /// public MetaDataLoader(DataSetWriterSubscription subscription) { _writer = subscription; _tcs = new TaskCompletionSource(); _loader = Task.Factory.StartNew(() => StartAsync(_cts.Token), default, TaskCreationOptions.LongRunning, TaskScheduler.Default).Unwrap(); } /// public async ValueTask DisposeAsync() { try { await _cts.CancelAsync().ConfigureAwait(false); await _loader.ConfigureAwait(false); } catch (OperationCanceledException) { } finally { _cts.Dispose(); } } /// /// Load meta data /// public void Reload() { _trigger.Set(); } /// /// Wait for metadata to be loaded or timeout after timeout /// /// /// public bool BlockUntilLoaded(TimeSpan timeout) { try { return _tcs.Task.Wait(timeout); } catch { return false; } } /// /// Wait for metadata to be loaded or timeout after timeout /// /// /// /// public async Task BlockUntilLoadedAsync(TimeSpan timeout, CancellationToken ct) { try { await _tcs.Task.WaitAsync(timeout, ct).ConfigureAwait(false); return true; } catch { return false; } } /// /// Meta data loader task /// /// /// private async Task StartAsync(CancellationToken ct) { while (!ct.IsCancellationRequested) { try { await UpdateMetaDataAsync(ct).ConfigureAwait(false); _tcs.TrySetResult(); Interlocked.Increment(ref _writer._group._metadataLoadSuccess); } catch (OperationCanceledException) { _tcs.TrySetCanceled(ct); } catch (Exception ex) { _writer._logger.FailedToGetMetadata(_writer._writer, ex.Message); _tcs.TrySetException(ex); Interlocked.Increment(ref _writer._group._metadataLoadFailures); } Interlocked.Exchange(ref _tcs, new TaskCompletionSource()); await _trigger.WaitAsync(ct).ConfigureAwait(false); } } /// /// Update metadata /// /// /// internal async Task UpdateMetaDataAsync(CancellationToken ct = default) { var dataSetName = _writer._writer.Writer.DataSet?.Name ?? _writer._writer.Writer.DataSetWriterName ?? _writer.Id; var writerGroup = _writer._group._writerGroup.Name ?? _writer._group.Id; var dataSetMetaData = _writer._writer.DataSet?.DataSetMetaData; var subscription = _writer.Subscription; if (dataSetMetaData == null || subscription == null || dataSetName == null) { // Metadata disabled MetaData = null; return; } // // Use the date time to version across reboots. This could be done // more elegantly by saving the last version to persistent storage // such as twin, but this is ok for the sake of being able to have // an incremental version number defining metadata changes. // var minor = (uint)_writer._group._timeProvider.GetUtcNow() .UtcDateTime.ToBinary(); var sw = Stopwatch.StartNew(); var id = $"{writerGroup}|{dataSetName}"; _writer._logger.LoadingMetadata(dataSetMetaData.MajorVersion ?? 1, minor, id); var fieldMask = _writer._writer.Writer.DataSetFieldContentMask; var metaData = await subscription.CollectMetaDataAsync(_writer, fieldMask, dataSetMetaData, minor, ct).ConfigureAwait(false); _writer._logger.LoadingMetadataTook(dataSetMetaData.MajorVersion ?? 1, minor, id, sw.Elapsed); var msgMask = _writer._writer.Writer.MessageSettings?.DataSetMessageContentMask; MetaData = new PublishedDataSetMessageSchemaModel { Id = id, MetaData = metaData with { Fields = _writer._extensionFields.AddMetadata(metaData.Fields) }, TypeName = null, DataSetFieldContentFlags = fieldMask, DataSetMessageContentFlags = msgMask }; } private TaskCompletionSource _tcs; private readonly Task _loader; private readonly CancellationTokenSource _cts = new(); private readonly AsyncAutoResetEvent _trigger = new(); private readonly DataSetWriterSubscription _writer; } /// /// Extension fields of the writer /// private sealed class ExtensionFields { /// /// Get extension fields as configured /// /// public IReadOnlyList? Fields { get { if ((_fieldMask & (DataSetFieldContentFlags.EndpointUrl | DataSetFieldContentFlags.ApplicationUri)) == 0) { return _extensionFields; } var extensionFields = _extensionFields?.ToList() ?? []; if ((_fieldMask & DataSetFieldContentFlags.EndpointUrl) != 0 && !extensionFields .Any(f => f.DataSetFieldName == nameof(DataSetFieldContentFlags.EndpointUrl))) { extensionFields.Add(new ExtensionFieldModel { DataSetFieldName = nameof(DataSetFieldContentFlags.EndpointUrl), Value = "{{EndpointUrl}}", DataSetFieldDescription = "Endpoint Url of the data source." }); } if ((_fieldMask & DataSetFieldContentFlags.ApplicationUri) != 0 && !extensionFields .Any(f => f.DataSetFieldName == nameof(DataSetFieldContentFlags.ApplicationUri))) { extensionFields.Add(new ExtensionFieldModel { DataSetFieldName = nameof(DataSetFieldContentFlags.ApplicationUri), Value = "{{ApplicationUri}}", DataSetFieldDescription = "Application Uri of the data source." }); } return extensionFields; } } /// /// Create extension fields /// /// /// /// public ExtensionFields(IJsonSerializer serializer, IReadOnlyList? extensionFields, DataSetFieldContentFlags? dataSetFieldContentMask) { _serializer = serializer; _fieldMask = dataSetFieldContentMask ?? 0; _extensionFields = extensionFields; _data = GenerateExtensionFieldData(); } /// /// Get extension field data /// /// /// public IReadOnlyList<(string, Opc.Ua.DataValue?)> GetExtensionFieldData( OpcUaSubscriptionNotification notification) { if ((_fieldMask & (DataSetFieldContentFlags.EndpointUrl | DataSetFieldContentFlags.ApplicationUri)) == 0) { return _data; } return _data .Select(f => f.Item1 switch { nameof(DataSetFieldContentFlags.EndpointUrl) => (f.Item1, new Opc.Ua.DataValue(notification.EndpointUrl)), nameof(DataSetFieldContentFlags.ApplicationUri) => (f.Item1, new Opc.Ua.DataValue(notification.ApplicationUri)), _ => f }) .ToList(); } /// /// Add extension field metadata to the end of the metadata fields /// /// /// public IReadOnlyList AddMetadata( IReadOnlyList metadataFields) { var extensionFields = Fields; if (extensionFields == null || extensionFields.Count == 0) { return metadataFields; } var fields = new List(metadataFields); foreach (var field in extensionFields) { var builtInType = GetBuiltInType(field.Value); fields.Add(new PublishedFieldMetaDataModel { Flags = 0, // Set to 1 << 1 for PromotedField fields. Name = field.DataSetFieldName, Id = field.DataSetClassFieldId, Description = field.DataSetFieldDescription, ValueRank = (int)(field.Value.IsArray ? NodeValueRank.OneDimension : NodeValueRank.Scalar), ArrayDimensions = null, MaxStringLength = 0, // If the Property is EngineeringUnits, the unit of the Field Value // shall match the unit of the FieldMetaData. Properties = null, // TODO: Add engineering units etc. to properties BuiltInType = (byte)builtInType }); } return fields; } /// /// Generate extension field data values /// /// private IReadOnlyList<(string, Opc.Ua.DataValue?)> GenerateExtensionFieldData() { var extensionFields = Fields; if (extensionFields == null || extensionFields.Count == 0) { return Array.Empty<(string, Opc.Ua.DataValue?)>(); } var extensions = new List<(string, Opc.Ua.DataValue?)>(); var encoder = new JsonVariantEncoder(new Opc.Ua.ServiceMessageContext(), _serializer); foreach (var field in extensionFields) { extensions.Add((field.DataSetFieldName, new Opc.Ua.DataValue(encoder.Decode(field.Value, (Opc.Ua.BuiltInType)GetBuiltInType(field.Value))))); } return extensions; } private static byte GetBuiltInType(VariantValue value) { return value.GetTypeCode() switch { TypeCode.Empty => 0, TypeCode.Boolean => 1, TypeCode.SByte => 2, TypeCode.Byte => 3, TypeCode.Int16 => 4, TypeCode.UInt16 => 5, TypeCode.Int32 => 6, TypeCode.UInt32 => 7, TypeCode.Int64 => 8, TypeCode.UInt64 => 9, TypeCode.Single => 10, TypeCode.Double => 11, TypeCode.String or TypeCode.Char => 12, TypeCode.DateTime => 13, _ => 24 }; } private readonly IJsonSerializer _serializer; private readonly DataSetFieldContentFlags _fieldMask; private readonly IReadOnlyList? _extensionFields; private readonly IReadOnlyList<(string, Opc.Ua.DataValue?)> _data; } private readonly WriterGroupDataSource _group; private readonly ILogger _logger; private readonly Lock _lock = new(); private volatile uint _frameCount; private uint? _lastMajorVersion; private uint? _lastMinorVersion; private TimerEx? _metadataTimer; private SubscriptionModel _template; private ConnectionIdentifier _connection; private DataSetWriter _writer; private ExtensionFields _extensionFields; private readonly Lazy _metaDataLoader; private uint _dataSetSequenceNumber; private uint _metadataSequenceNumber; private bool _sendKeepAlives; private bool _sendKeepAliveAsKeyFrame; private bool _disposed; } } internal static partial class DataSetWriterSubscriptionLogging { private const int EventClass = 130; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Debug, Message = "Creating new writer {Id} ({Writer}) in writer group {WriterGroup}...")] internal static partial void CreatingNewWriter(this ILogger logger, string id, string writer, string writerGroup); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Information, Message = "Created writer {Id} in writer group {WriterGroup}.")] internal static partial void CreatedWriter(this ILogger logger, string id, string writerGroup); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Debug, Message = "Updating writer {Id} in writer group {WriterGroup}...")] internal static partial void UpdatingWriter(this ILogger logger, string id, string writerGroup); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Information, Message = "Recreated subscription for writer {Id} in writer group {WriterGroup}...")] internal static partial void RecreatedSubscription(this ILogger logger, string id, string writerGroup); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Debug, Message = "Updated monitored items for writer {Id} in writer group {WriterGroup}.")] internal static partial void UpdatedMonitoredItems(this ILogger logger, string id, string writerGroup); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Information, Message = "Closed writer {Id} in writer group {WriterGroup}.")] internal static partial void ClosedWriter(this ILogger logger, string id, string writerGroup); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Debug, Message = "Notifications counter has been reset to prevent overflow. So far, {DataChangesCount} " + "data changes and {ValueChangesCount} value changes were invoked by message source.")] internal static partial void NotificationsCounterReset(this ILogger logger, int dataChangesCount, int valueChangesCount); [LoggerMessage(EventId = EventClass + 8, Level = LogLevel.Debug, Message = "Notifications counter has been reset to prevent overflow. So far, {ReadCount} " + "data changes and {ValuesCount} value changes were invoked by message source.")] internal static partial void NotificationsCounterResetRead(this ILogger logger, int readCount, int valuesCount); [LoggerMessage(EventId = EventClass + 9, Level = LogLevel.Debug, Message = "Notifications counter has been reset to prevent overflow. So far, {EventChangesCount} " + "event changes and {EventValueChangesCount} event value changes were invoked by message source.")] internal static partial void NotificationsCounterResetEvent(this ILogger logger, int eventChangesCount, int eventValueChangesCount); [LoggerMessage(EventId = EventClass + 10, Level = LogLevel.Information, Message = "Blocked message for {Duration} until metadata was loaded for {Writer}.")] internal static partial void BlockedMessageForMetadata(this ILogger logger, TimeSpan duration, WriterGroupDataSource.DataSetWriter writer); [LoggerMessage(EventId = EventClass + 11, Level = LogLevel.Warning, Message = "No metadata available for {Writer} - dropping notification.")] internal static partial void NoMetadataAvailable(this ILogger logger, WriterGroupDataSource.DataSetWriter writer); [LoggerMessage(EventId = EventClass + 12, Level = LogLevel.Trace, Message = "Enqueuing notification: {Notification}")] internal static partial void EnqueuingNotification(this ILogger logger, string notification); [LoggerMessage(EventId = EventClass + 13, Level = LogLevel.Error, Message = "Failed to get metadata for {Writer} with error {Error}")] internal static partial void FailedToGetMetadata(this ILogger logger, WriterGroupDataSource.DataSetWriter writer, string error); [LoggerMessage(EventId = EventClass + 14, Level = LogLevel.Debug, Message = "Loading Metadata {Major}.{Minor} for {Writer}...")] internal static partial void LoadingMetadata(this ILogger logger, uint major, uint minor, string writer); [LoggerMessage(EventId = EventClass + 15, Level = LogLevel.Information, Message = "Loading Metadata {Major}.{Minor} for {Writer} took {Duration}.")] internal static partial void LoadingMetadataTook(this ILogger logger, uint major, uint minor, string writer, TimeSpan duration); [LoggerMessage(EventId = EventClass + 16, Level = LogLevel.Warning, Message = "Failed to produce message.")] internal static partial void FailedToProduceMessage(this ILogger logger, Exception ex); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Services/Extensions.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Services { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Parser; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Furly.Exceptions; using Opc.Ua; using Opc.Ua.Extensions; using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; /// /// Service Extensions /// internal static class Extensions { /// /// Resolve node id /// /// /// /// /// /// /// /// /// public static async Task ResolveNodeIdAsync(this IOpcUaSession session, RequestHeaderModel? header, string? rootId, IReadOnlyList? browsePath, string paramName, TimeProvider timeProvider, CancellationToken ct = default) { var resolvedNodeId = rootId.ToNodeId(session.MessageContext); if (browsePath?.Count > 0) { resolvedNodeId = await session.ResolveBrowsePathToNodeAsync(header, resolvedNodeId, [.. browsePath], paramName, timeProvider, ct).ConfigureAwait(false); } return resolvedNodeId; } /// /// Resolve provided path to node. /// /// /// /// /// /// /// /// /// /// /// public static async Task ResolveBrowsePathToNodeAsync( this IOpcUaSession session, RequestHeaderModel? header, NodeId rootId, string[] paths, string paramName, TimeProvider timeProvider, CancellationToken ct = default) { if (paths == null || paths.Length == 0) { return rootId; } if (NodeId.IsNull(rootId)) { rootId = ObjectIds.RootFolder; } var browsepaths = new BrowsePathCollection { new BrowsePath { StartingNode = rootId, RelativePath = paths.ToRelativePath(session.MessageContext) } }; var response = await session.Services.TranslateBrowsePathsToNodeIdsAsync( header.ToRequestHeader(timeProvider), browsepaths, ct).ConfigureAwait(false); Debug.Assert(response != null); var results = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, browsepaths); var count = results[0].Result.Targets?.Count ?? 0; if (count == 0) { throw new ResourceNotFoundException( $"{paramName} did not resolve to any node."); } if (count != 1) { throw new ResourceConflictException( $"{paramName} resolved to {count} nodes."); } return results[0].Result.Targets[0].TargetId .ToNodeId(session.MessageContext.NamespaceUris); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Services/FileSystemServices.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Services { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Parser; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Stack.Extensions; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Microsoft.Extensions.Options; using Opc.Ua; using Opc.Ua.Extensions; using System; using System.Buffers; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; /// /// This class provides foundational file transfer services. /// /// public sealed class FileSystemServices : IFileSystemServices, IDisposable { /// /// Create node service /// /// /// /// public FileSystemServices(IOpcUaClientManager client, IOptions options, TimeProvider? timeProvider = null) { _client = client; _options = options; _timeProvider = timeProvider ?? TimeProvider.System; } /// public void Dispose() { _activitySource.Dispose(); } /// public IAsyncEnumerable> GetFileSystemsAsync( T endpoint, CancellationToken ct) { using var trace = _activitySource.StartActivity("GetFileSystems"); var header = new RequestHeaderModel(); var browser = new FileSystemBrowser(header, _options, _timeProvider); return _client.ExecuteAsync(endpoint, browser, header, ct); } /// public async Task>> GetDirectoriesAsync( T endpoint, FileSystemObjectModel fileSystemOrDirectory, CancellationToken ct) { using var trace = _activitySource.StartActivity("GetDirectories"); var header = new RequestHeaderModel(); return await _client.ExecuteAsync(endpoint, async context => { var (nodeId, argInfo) = await GetFileSystemNodeIdAsync(context.Session, header, fileSystemOrDirectory, context.Ct).ConfigureAwait(false); if (argInfo != null) { return new ServiceResponse> { ErrorInfo = argInfo }; } var (references, errorInfo) = await context.Session.FindAsync( header.ToRequestHeader(_timeProvider), nodeId.YieldReturn(), ReferenceTypeIds.HasComponent, ct: context.Ct).ConfigureAwait(false); if (errorInfo == null && references.Count > 0 && references.All(r => r.ErrorInfo != null)) { errorInfo = references[0].ErrorInfo; } return new ServiceResponse> { ErrorInfo = errorInfo, Result = references .Where(r => r.TypeDefinition == Opc.Ua.ObjectTypes.FileDirectoryType && r.ErrorInfo == null) .Select(f => new FileSystemObjectModel { NodeId = header.AsString(f.Node, context.Session.MessageContext, _options), Name = f.DisplayName }) }; }, header, ct).ConfigureAwait(false); } /// public async Task>> GetFilesAsync( T endpoint, FileSystemObjectModel fileSystemOrDirectory, CancellationToken ct) { using var trace = _activitySource.StartActivity("GetFiles"); var header = new RequestHeaderModel(); return await _client.ExecuteAsync(endpoint, async context => { var (nodeId, argInfo) = await GetFileSystemNodeIdAsync(context.Session, header, fileSystemOrDirectory, context.Ct).ConfigureAwait(false); if (argInfo != null) { return new ServiceResponse> { ErrorInfo = argInfo }; } var (references, errorInfo) = await context.Session.FindAsync( header.ToRequestHeader(_timeProvider), nodeId.YieldReturn(), ReferenceTypeIds.HasComponent, ct: context.Ct).ConfigureAwait(false); if (errorInfo == null && references.Count > 0 && references.All(r => r.ErrorInfo != null)) { errorInfo = references[0].ErrorInfo; } return new ServiceResponse> { ErrorInfo = errorInfo, Result = references .Where(r => r.TypeDefinition == Opc.Ua.ObjectTypes.FileType && r.ErrorInfo == null) .Select(f => new FileSystemObjectModel { NodeId = header.AsString(f.Node, context.Session.MessageContext, _options), Name = f.DisplayName }) }; }, header, ct).ConfigureAwait(false); } /// public async Task> OpenReadAsync(T endpoint, FileSystemObjectModel file, CancellationToken ct) { using var trace = _activitySource.StartActivity("OpenRead"); var header = new RequestHeaderModel(); var (stream, errorInfo) = await FileTransferStream.OpenAsync(this, endpoint, header, file, null, ct).ConfigureAwait(false); return new ServiceResponse { ErrorInfo = errorInfo, Result = stream }; } /// public async Task> OpenWriteAsync(T endpoint, FileSystemObjectModel file, FileOpenWriteOptionsModel? options, CancellationToken ct) { using var trace = _activitySource.StartActivity("OpenWrite"); var header = new RequestHeaderModel(); var (stream, errorInfo) = await FileTransferStream.OpenAsync(this, endpoint, header, file, options ?? new FileOpenWriteOptionsModel(), ct).ConfigureAwait(false); return new ServiceResponse { ErrorInfo = errorInfo, Result = stream }; } /// public async Task> CreateDirectoryAsync(T endpoint, FileSystemObjectModel fileSystemOrDirectory, string name, CancellationToken ct) { using var trace = _activitySource.StartActivity("CreateDirectory"); var header = new RequestHeaderModel(); return await _client.ExecuteAsync(endpoint, async context => { var (nodeId, argInfo) = await GetFileSystemNodeIdAsync(context.Session, header, fileSystemOrDirectory, context.Ct).ConfigureAwait(false); if (argInfo != null) { return new ServiceResponse { ErrorInfo = argInfo }; } var requests = new CallMethodRequestCollection { new CallMethodRequest { ObjectId = nodeId, MethodId = Opc.Ua.MethodIds.FileDirectoryType_CreateDirectory, InputArguments = new [] { new Variant(name) } } }; // Call method var response = await context.Session.Services.CallAsync(header .ToRequestHeader(_timeProvider), requests, context.Ct).ConfigureAwait(false); var results = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, requests); if (results.ErrorInfo != null) { return new ServiceResponse { ErrorInfo = results.ErrorInfo }; } if (results[0].ErrorInfo != null || results[0].Result?.OutputArguments == null || results[0].Result.OutputArguments.Count == 0 || results[0].Result.OutputArguments[0].Value is not NodeId result) { return new ServiceResponse { ErrorInfo = results[0].ErrorInfo ?? new ServiceResultModel { ErrorMessage = "no node id returned" } }; } return new ServiceResponse { Result = new FileSystemObjectModel { NodeId = header.AsString(result, context.Session.MessageContext, _options), Name = name } }; }, header, ct).ConfigureAwait(false); } /// public async Task> CreateFileAsync(T endpoint, FileSystemObjectModel fileSystemOrDirectory, string name, CancellationToken ct) { using var trace = _activitySource.StartActivity("CreateFile"); var header = new RequestHeaderModel(); return await _client.ExecuteAsync(endpoint, async context => { var (nodeId, argInfo) = await GetFileSystemNodeIdAsync(context.Session, header, fileSystemOrDirectory, context.Ct).ConfigureAwait(false); if (argInfo != null) { return new ServiceResponse { ErrorInfo = argInfo }; } var requests = new CallMethodRequestCollection { new CallMethodRequest { ObjectId = nodeId, MethodId = Opc.Ua.MethodIds.FileDirectoryType_CreateFile, InputArguments = new [] { new Variant(name), new Variant(false) } } }; // Call method var response = await context.Session.Services.CallAsync(header .ToRequestHeader(_timeProvider), requests, context.Ct).ConfigureAwait(false); var results = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, requests); if (results.ErrorInfo != null) { return new ServiceResponse { ErrorInfo = results.ErrorInfo }; } if (results[0].ErrorInfo != null || results[0].Result?.OutputArguments == null || results[0].Result.OutputArguments.Count == 0 || results[0].Result.OutputArguments[0].Value is not NodeId result) { return new ServiceResponse { ErrorInfo = results[0].ErrorInfo ?? new ServiceResultModel { ErrorMessage = "no node id returned" } }; } return new ServiceResponse { Result = new FileSystemObjectModel { NodeId = header.AsString(result, context.Session.MessageContext, _options), Name = name } }; }, header, ct).ConfigureAwait(false); } /// public async Task> GetParentAsync(T endpoint, FileSystemObjectModel fileOrDirectoryObject, CancellationToken ct) { using var trace = _activitySource.StartActivity("GetParent"); var header = new RequestHeaderModel(); return await _client.ExecuteAsync(endpoint, async context => { var (nodeId, argInfo) = await GetFileSystemNodeIdAsync(context.Session, header, fileOrDirectoryObject, context.Ct).ConfigureAwait(false); if (argInfo != null) { return new ServiceResponse { ErrorInfo = argInfo }; } // Find parent var (parents, argInfo2) = await context.Session.FindAsync( header.ToRequestHeader(_timeProvider), nodeId.YieldReturn(), ReferenceTypeIds.HasComponent, isInverse: true, maxResults: 1, ct: context.Ct).ConfigureAwait(false); if (argInfo2 != null) { return new ServiceResponse { ErrorInfo = argInfo2 }; } var result = parents.Count > 0 ? parents[0] : default; nodeId = result.Node; if (NodeId.IsNull(nodeId) || result.TypeDefinition != Opc.Ua.ObjectTypeIds.FileDirectoryType) { return new ServiceResponse { ErrorInfo = new ServiceResultModel { StatusCode = StatusCodes.BadNodeIdInvalid, ErrorMessage = "Could not find a file directory object parent." } }; } return new ServiceResponse { Result = new FileSystemObjectModel { NodeId = header.AsString(nodeId, context.Session.MessageContext, _options), Name = result.DisplayName } }; }, header, ct).ConfigureAwait(false); } /// public async Task DeleteFileSystemObjectAsync(T endpoint, FileSystemObjectModel fileOrDirectoryObject, FileSystemObjectModel? parentFileSystemOrDirectory, CancellationToken ct) { using var trace = _activitySource.StartActivity("DeleteFileSystemObject"); var header = new RequestHeaderModel(); return await _client.ExecuteAsync(endpoint, async context => { var (nodeId, argInfo) = await GetFileSystemNodeIdAsync(context.Session, header, fileOrDirectoryObject, context.Ct).ConfigureAwait(false); if (argInfo != null) { return argInfo; } var targetId = nodeId; if (parentFileSystemOrDirectory != null) { (nodeId, argInfo) = await GetFileSystemNodeIdAsync(context.Session, header, parentFileSystemOrDirectory, context.Ct).ConfigureAwait(false); if (argInfo != null) { return argInfo; } } else { // Find parent var (parents, argInfo2) = await context.Session.FindAsync( header.ToRequestHeader(_timeProvider), targetId.YieldReturn(), ReferenceTypeIds.HasComponent, isInverse: true, maxResults: 1, ct: context.Ct).ConfigureAwait(false); if (argInfo2 != null) { return argInfo2; } var result = parents.Count > 0 ? parents[0] : default; nodeId = result.Node; if (NodeId.IsNull(nodeId) || result.TypeDefinition != Opc.Ua.ObjectTypeIds.FileDirectoryType) { return new ServiceResultModel { StatusCode = StatusCodes.BadNodeIdInvalid, ErrorMessage = "Could not find a file directory object parent." }; } } var requests = new CallMethodRequestCollection { new CallMethodRequest { ObjectId = nodeId, MethodId = Opc.Ua.MethodIds.FileDirectoryType_DeleteFileSystemObject, InputArguments = new [] { new Variant(targetId) } } }; // Call method var response = await context.Session.Services.CallAsync(header .ToRequestHeader(_timeProvider), requests, context.Ct).ConfigureAwait(false); var results = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, requests); return results.ErrorInfo ?? results[0].ErrorInfo ?? new ServiceResultModel(); }, header, ct).ConfigureAwait(false); } /// public async Task> GetFileInfoAsync(T endpoint, FileSystemObjectModel file, CancellationToken ct) { using var trace = _activitySource.StartActivity("GetFileInfo"); var header = new RequestHeaderModel(); return await _client.ExecuteAsync(endpoint, async context => { var (nodeId, argInfo) = await GetFileSystemNodeIdAsync(context.Session, header, file, context.Ct).ConfigureAwait(false); if (argInfo != null) { return new ServiceResponse { ErrorInfo = argInfo }; } var (fileInfo, errorInfo) = await context.Session.GetFileInfoAsync( header.ToRequestHeader(_timeProvider), nodeId, context.Ct).ConfigureAwait(false); return new ServiceResponse { ErrorInfo = errorInfo, Result = fileInfo }; }, header, ct).ConfigureAwait(false); } /// /// Get the node id for a file system object /// /// /// /// /// /// /// private async Task<(NodeId, ServiceResultModel?)> GetFileSystemNodeIdAsync(IOpcUaSession session, RequestHeaderModel header, FileSystemObjectModel fileSystemObject, CancellationToken ct) { var nodeId = fileSystemObject.NodeId.ToNodeId(session.MessageContext); if (fileSystemObject.BrowsePath?.Count > 0) { nodeId ??= ObjectIds.RootFolder; try { nodeId = await session.ResolveBrowsePathToNodeAsync(header, nodeId, fileSystemObject.BrowsePath.Select(b => "" + b).ToArray(), nameof(fileSystemObject.BrowsePath), _timeProvider, ct).ConfigureAwait(false); } catch (Exception ex) { return (NodeId.Null, ex.ToServiceResultModel()); } } if (NodeId.IsNull(nodeId)) { return (NodeId.Null, new ServiceResultModel { StatusCode = StatusCodes.BadNodeIdInvalid, ErrorMessage = "Invalid node id and browse path in file system object" }); } return (nodeId, null); } /// /// File system object browser browses from root all objects of file directory type. /// The browse operation stops at the first found and returns the result. /// private sealed class FileSystemBrowser : AsyncEnumerableBrowser> { /// public FileSystemBrowser(RequestHeaderModel? header, IOptions options, TimeProvider timeProvider) : base(header, options, timeProvider, null, ObjectTypeIds.FileDirectoryType) { } /// protected override IEnumerable> HandleError( ServiceCallContext context, ServiceResultModel errorInfo) { yield return new ServiceResponse { ErrorInfo = errorInfo }; } /// protected override IEnumerable> HandleMatching( ServiceCallContext context, IReadOnlyList matching, List references) { // Only add what we did not match to browse deeper var stop = matching.Select(r => r.NodeId).ToHashSet(); references.RemoveAll(r => stop.Contains((NodeId)r.NodeId)); return matching.Select(match => new ServiceResponse { Result = new FileSystemObjectModel { NodeId = Header.AsString(match.NodeId, context.Session.MessageContext, Options), Name = match.DisplayName } }); } } /// /// File transfer stream /// private sealed class FileTransferStream : Stream { /// public override bool CanRead => _options == null && _fileHandle.HasValue; /// public override bool CanWrite => _options != null && _fileHandle.HasValue; /// public override long Length => _fileInfo?.Size ?? Position; /// public override long Position { get; set; } /// public override bool CanSeek { get; } /// public override bool CanTimeout => true; /// public override int ReadTimeout { get => _header.OperationTimeout ?? 0; set => _header.OperationTimeout = value; } /// public override int WriteTimeout { get => _header.OperationTimeout ?? 0; set => _header.OperationTimeout = value; } /// /// Create stream /// /// /// /// /// /// /// /// /// public FileTransferStream(FileSystemServices outer, ISessionHandle handle, RequestHeaderModel header, NodeId nodeId, uint fileHandle, FileInfoModel? fileInfo, uint bufferSize, FileOpenWriteOptionsModel? options = null) { _handle = handle; _nodeId = nodeId; _fileHandle = fileHandle; _outer = outer; _header = header; _fileInfo = fileInfo; _bufferSize = bufferSize; _options = options; if (options?.Mode == FileWriteMode.Append) { Position = Length; } else { Position = 0; } CanSeek = false; } /// /// Open stream /// /// /// /// /// /// /// /// public static async Task<(Stream?, ServiceResultModel?)> OpenAsync( FileSystemServices outer, T endpoint, RequestHeaderModel header, FileSystemObjectModel file, FileOpenWriteOptionsModel? options = null, CancellationToken ct = default) { var handle = await outer._client.AcquireSessionAsync(endpoint, header, ct).ConfigureAwait(false); var closeHandle = handle; try { var (nodeId, argInfo) = await outer.GetFileSystemNodeIdAsync(handle.Session, header, file, ct).ConfigureAwait(false); if (argInfo != null) { return (null, argInfo); } var (fileInfo, errorInfo) = await handle.Session.GetFileInfoAsync( header.ToRequestHeader(outer._timeProvider), nodeId, ct).ConfigureAwait(false); var tryCreate = errorInfo != null; if (errorInfo != null) { // There should be file info return (null, errorInfo); } if (options != null && fileInfo?.Writable == false) { return (null, new ServiceResultModel { StatusCode = StatusCodes.BadNotWritable, ErrorMessage = "File is not writable." }); } var bufferSize = fileInfo?.MaxBufferSize; if (bufferSize == null || bufferSize == 0) { var caps = await handle.Session.GetOperationLimitsAsync( ct).ConfigureAwait(false); bufferSize = caps.MaxByteStringLength; if (bufferSize == null || bufferSize == 0) { bufferSize = 4096; } } var (fileHandle, errorInfo2) = await handle.Session.OpenAsync( header.ToRequestHeader(outer._timeProvider), nodeId, options?.Mode switch { FileWriteMode.Create => 0x2 | 0x4, // Write bit plus erase FileWriteMode.Append => 0x2 | 0x8, // Write bit plus append FileWriteMode.Write => 0x2, // Write bit _ => 0x1 // Read bit }, ct).ConfigureAwait(false); if (errorInfo2 != null) { return (null, errorInfo2); } Debug.Assert(fileHandle.HasValue); closeHandle = null; return (new FileTransferStream(outer, handle, header, nodeId, fileHandle.Value, fileInfo, bufferSize.Value, options), null); } finally { closeHandle?.Dispose(); } } /// public override void Flush() { // No op } /// public override Task FlushAsync(CancellationToken cancellationToken) { // No op return Task.CompletedTask; } /// public override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); // TODO } /// public override void SetLength(long value) { throw new NotSupportedException(); // TODO } /// public override async ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken) { ObjectDisposedException.ThrowIf(!_fileHandle.HasValue, this); if (!CanRead) { throw new IOException("Cannot read from write-only stream"); } var total = 0; while (!_isEoS) { var readCount = (int)Math.Min(buffer.Length, _bufferSize); if (readCount == 0) { break; } var (result, errorInfo) = await _handle.Session.ReadAsync( _header.ToRequestHeader(_outer._timeProvider), _nodeId, _fileHandle.Value, readCount, cancellationToken).ConfigureAwait(false); if (errorInfo != null) { throw new IOException(errorInfo.ErrorMessage); } Debug.Assert(result != null); if (result.Length == 0) { // eof _isEoS = true; break; } result.CopyTo(buffer.Span); Position += result.Length; total += result.Length; if (buffer.Length == readCount) { break; } buffer = buffer[readCount..]; } return total; } /// public override int Read(byte[] buffer, int offset, int count) { var memory = new Memory(buffer); return ReadAsync(memory.Slice(offset, count), default) .AsTask().GetAwaiter().GetResult(); } /// public override async ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken) { ObjectDisposedException.ThrowIf(!_fileHandle.HasValue, this); if (!CanWrite) { throw new IOException("Cannot write to read-only stream"); } while (true) { var writeCount = (int)Math.Min(buffer.Length, _bufferSize); if (writeCount == 0) { break; } var errorInfo = await _handle.Session.WriteAsync( _header.ToRequestHeader(_outer._timeProvider), _nodeId, _fileHandle.Value, buffer[..writeCount].ToArray(), cancellationToken).ConfigureAwait(false); if (errorInfo != null) { throw new IOException(errorInfo.ErrorMessage); } Position += writeCount; if (buffer.Length == writeCount) { break; } buffer = buffer[writeCount..]; } } /// public override void Write(byte[] buffer, int offset, int count) { var memory = new ReadOnlyMemory(buffer); WriteAsync(memory.Slice(offset, count), default) .AsTask().GetAwaiter().GetResult(); } /// public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) { ValidateCopyToArguments(destination, bufferSize); ObjectDisposedException.ThrowIf(!_fileHandle.HasValue, this); if (!CanRead) { throw new IOException("Cannot read from write-only stream"); } bufferSize = Math.Min(bufferSize, (int)_bufferSize); return Core(this, destination, bufferSize, cancellationToken); static async Task Core(Stream source, Stream destination, int bufferSize, CancellationToken cancellationToken) { var buffer = ArrayPool.Shared.Rent(bufferSize); try { int bytesRead; while ((bytesRead = await source.ReadAsync(new Memory(buffer), cancellationToken).ConfigureAwait(false)) != 0) { await destination.WriteAsync( new ReadOnlyMemory(buffer, 0, bytesRead), cancellationToken).ConfigureAwait(false); } } finally { ArrayPool.Shared.Return(buffer); } } } /// public override void CopyTo(Stream destination, int bufferSize) { CopyToAsync(destination, bufferSize, default).GetAwaiter().GetResult(); } /// public ValueTask CloseAsync(CancellationToken cancellationToken) { var alt = _options?.CloseAndCommitMethodId? .ToNodeId(_handle.Session.MessageContext); return CloseAsync(alt, cancellationToken); } /// /// Close with alternative method /// /// /// /// /// private async ValueTask CloseAsync(NodeId? alt, CancellationToken ct) { ObjectDisposedException.ThrowIf(!_fileHandle.HasValue, this); var errorInfo = await _handle.Session.CloseAsync( _header.ToRequestHeader(_outer._timeProvider), _nodeId, alt, _fileHandle.Value, ct).ConfigureAwait(false); if (errorInfo != null) { throw new IOException(errorInfo.ErrorMessage); } // Closed - now release handle _handle.Dispose(); _fileHandle = null; } /// public override async ValueTask DisposeAsync() { if (_fileHandle.HasValue) { try { await CloseAsync(null, default).ConfigureAwait(false); } catch { } // Best effort closing finally { if (_fileHandle.HasValue) { _handle.Dispose(); _fileHandle = null; // Mark disposed } } } await base.DisposeAsync().ConfigureAwait(false); } /// protected override void Dispose(bool disposing) { if (disposing && _fileHandle.HasValue) { DisposeAsync().AsTask().GetAwaiter().GetResult(); } base.Dispose(disposing); } private readonly RequestHeaderModel _header; private readonly ISessionHandle _handle; private readonly NodeId _nodeId; private readonly FileSystemServices _outer; private readonly FileInfoModel? _fileInfo; private readonly uint _bufferSize; private readonly FileOpenWriteOptionsModel? _options; private bool _isEoS; private uint? _fileHandle; } private readonly ActivitySource _activitySource = Diagnostics.NewActivitySource(); private readonly IOptions _options; private readonly TimeProvider _timeProvider; private readonly IOpcUaClientManager _client; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Services/HistoryServices.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Services { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Stack.Extensions; using Azure.IIoT.OpcUa.Encoders; using Furly.Extensions.Serializers; using Microsoft.Extensions.Options; using Opc.Ua; using Opc.Ua.Extensions; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; /// /// Implments history services on top of core services /// /// public sealed class HistoryServices : IHistoryServices { /// /// Create service /// /// /// /// public HistoryServices(IOptions options, INodeServicesInternal services, TimeProvider? timeProvider = null) { _services = services; _options = options; _timeProvider = timeProvider ?? TimeProvider.System; } /// public Task HistoryDeleteEventsAsync( T endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { return _services.HistoryUpdateAsync(endpoint, request, (nodeId, details, _) => { if (details.EventIds == null || details.EventIds.Count == 0) { throw new ArgumentException("Bad events", nameof(details)); } return Task.FromResult(new ExtensionObject(new DeleteEventDetails { NodeId = nodeId, EventIds = new ByteStringCollection(details.EventIds) })); }, ct); } /// public Task HistoryDeleteValuesAtTimesAsync( T endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { return _services.HistoryUpdateAsync(endpoint, request, (nodeId, details, _) => { if (details.ReqTimes == null || details.ReqTimes.Count == 0) { throw new ArgumentException("Bad requested times", nameof(details)); } return Task.FromResult(new ExtensionObject(new DeleteAtTimeDetails { NodeId = nodeId, ReqTimes = new DateTimeCollection(details.ReqTimes) })); }, ct); } /// public Task HistoryDeleteModifiedValuesAsync( T endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { return _services.HistoryUpdateAsync(endpoint, request, (nodeId, details, _) => { if (details.EndTime == null && details.StartTime == null) { throw new ArgumentException("Start time and end time cannot both be null", nameof(details)); } return Task.FromResult(new ExtensionObject(new DeleteRawModifiedDetails { NodeId = nodeId, EndTime = details.EndTime ?? DateTime.MinValue, StartTime = details.StartTime ?? DateTime.MinValue, IsDeleteModified = true })); }, ct); } /// public Task HistoryDeleteValuesAsync( T endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { return _services.HistoryUpdateAsync(endpoint, request, (nodeId, details, _) => { if (details.EndTime == null && details.StartTime == null) { throw new ArgumentException("Start time and end time cannot both be null", nameof(details)); } return Task.FromResult(new ExtensionObject(new DeleteRawModifiedDetails { NodeId = nodeId, EndTime = details.EndTime ?? DateTime.MinValue, StartTime = details.StartTime ?? DateTime.MinValue, IsDeleteModified = false })); }, ct); } /// public Task> HistoryReadEventsAsync( T endpoint, HistoryReadRequestModel request, CancellationToken ct) { return _services.HistoryReadAsync(endpoint, request, (details, session) => { if (details.EndTime == null && details.StartTime == null) { throw new ArgumentException("Start time and end time cannot both be null", nameof(details)); } if ((details.StartTime == null || details.EndTime == null) && ((details.NumEvents ?? 0) == 0)) { throw new ArgumentException("Value bound must be set", nameof(details)); } return new ExtensionObject(new ReadEventDetails { EndTime = details.EndTime ?? DateTime.MinValue, StartTime = details.StartTime ?? DateTime.MinValue, Filter = session.Codec.Decode(details.Filter), NumValuesPerNode = details.NumEvents ?? 0 }); }, DecodeEvents, ct); } /// public Task> HistoryReadEventsNextAsync( T endpoint, HistoryReadNextRequestModel request, CancellationToken ct) { return _services.HistoryReadNextAsync(endpoint, request, DecodeEvents, ct); } /// public async Task> HistoryReadValuesAsync( T endpoint, HistoryReadRequestModel request, CancellationToken ct) { return await _services.HistoryReadAsync(endpoint, request, (details, _) => { if (details.EndTime == null && details.StartTime == null) { throw new ArgumentException("Start time and end time cannot both be null", nameof(details)); } if ((details.StartTime == null || details.EndTime == null) && ((details.NumValues ?? 0) == 0)) { throw new ArgumentException("Value bound must be set", nameof(details)); } return new ExtensionObject(new ReadRawModifiedDetails { EndTime = details.EndTime ?? DateTime.MinValue, StartTime = details.StartTime ?? DateTime.MinValue, IsReadModified = false, ReturnBounds = details.ReturnBounds ?? false, NumValuesPerNode = details.NumValues ?? 0 }); }, DecodeValues, ct).ConfigureAwait(false); } /// public Task> HistoryReadValuesAtTimesAsync( T endpoint, HistoryReadRequestModel request, CancellationToken ct) { return _services.HistoryReadAsync(endpoint, request, (details, _) => { if (details.ReqTimes == null || details.ReqTimes.Count == 0) { throw new ArgumentException(nameof(details.ReqTimes)); } return new ExtensionObject(new ReadAtTimeDetails { ReqTimes = new DateTimeCollection(details.ReqTimes), UseSimpleBounds = details.UseSimpleBounds ?? false }); }, DecodeValues, ct); } /// public Task> HistoryReadProcessedValuesAsync( T endpoint, HistoryReadRequestModel request, CancellationToken ct) { return _services.HistoryReadAsync(endpoint, request, (details, session) => { if (details.EndTime == null && details.StartTime == null) { throw new ArgumentException("Start time and end time cannot both be null", nameof(details)); } var aggregateType = details.AggregateType; if (aggregateType != null) { // TODO: Should be async! var capabilities = session.GetHistoryCapabilitiesAsync( request.Header.GetNamespaceFormat(_options), ct).AsTask().Result; if (capabilities?.AggregateFunctions != null && capabilities.AggregateFunctions.TryGetValue(aggregateType, out var id)) { aggregateType = id; } } var aggregateId = aggregateType?.ToNodeId(session.MessageContext); return new ExtensionObject(new ReadProcessedDetails { EndTime = details.EndTime ?? DateTime.MinValue, StartTime = details.StartTime ?? DateTime.MinValue, AggregateType = aggregateId == null ? null : new NodeIdCollection(aggregateId.YieldReturn()), ProcessingInterval = details.ProcessingInterval == null ? 0 : details.ProcessingInterval.Value.TotalMilliseconds, AggregateConfiguration = details.AggregateConfiguration.ToStackModel() }); }, DecodeValues, ct); } /// public Task> HistoryReadModifiedValuesAsync( T endpoint, HistoryReadRequestModel request, CancellationToken ct) { return _services.HistoryReadAsync(endpoint, request, (details, _) => { if (details.EndTime == null && details.StartTime == null) { throw new ArgumentException("Start time and end time cannot both be null", nameof(details)); } if ((details.StartTime == null || details.EndTime == null) && ((details.NumValues ?? 0) == 0)) { throw new ArgumentException("Value bound must be set", nameof(details)); } return new ExtensionObject(new ReadRawModifiedDetails { EndTime = details.EndTime ?? DateTime.MinValue, StartTime = details.StartTime ?? DateTime.MinValue, IsReadModified = true, NumValuesPerNode = details.NumValues ?? 0 }); }, DecodeValues, ct); } /// public Task> HistoryReadValuesNextAsync( T endpoint, HistoryReadNextRequestModel request, CancellationToken ct) { return _services.HistoryReadNextAsync(endpoint, request, DecodeValues, ct); } /// public Task HistoryReplaceEventsAsync(T endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { return HistoryUpdateEventsAsync(endpoint, request, PerformUpdateType.Replace, ct); } /// public Task HistoryReplaceValuesAsync(T endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { return HistoryUpdateValuesAsync(endpoint, request, PerformUpdateType.Replace, ct); } /// public Task HistoryInsertEventsAsync(T endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { return HistoryUpdateEventsAsync(endpoint, request, PerformUpdateType.Insert, ct); } /// public Task HistoryInsertValuesAsync(T endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { return HistoryUpdateValuesAsync(endpoint, request, PerformUpdateType.Insert, ct); } /// public Task HistoryUpsertEventsAsync(T endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { return HistoryUpdateEventsAsync(endpoint, request, PerformUpdateType.Update, ct); } /// public Task HistoryUpsertValuesAsync(T endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { return HistoryUpdateValuesAsync(endpoint, request, PerformUpdateType.Update, ct); } /// public async IAsyncEnumerable HistoryStreamValuesAsync( T endpoint, HistoryReadRequestModel request, [EnumeratorCancellation] CancellationToken ct) { var result = await HistoryReadValuesAsync(endpoint, request, ct).ConfigureAwait(false); if (result.History != null) { foreach (var item in result.History) { yield return item; } } await foreach (var item in HistoryStreamRemainingValuesAsync( endpoint, request.Header, result.ContinuationToken, ct).ConfigureAwait(false)) { yield return item; } } /// public async IAsyncEnumerable HistoryStreamModifiedValuesAsync( T endpoint, HistoryReadRequestModel request, [EnumeratorCancellation] CancellationToken ct) { var result = await HistoryReadModifiedValuesAsync(endpoint, request, ct).ConfigureAwait(false); if (result.History != null) { foreach (var item in result.History) { yield return item; } } await foreach (var item in HistoryStreamRemainingValuesAsync( endpoint, request.Header, result.ContinuationToken, ct).ConfigureAwait(false)) { yield return item; } } /// public async IAsyncEnumerable HistoryStreamValuesAtTimesAsync( T endpoint, HistoryReadRequestModel request, [EnumeratorCancellation] CancellationToken ct) { var result = await HistoryReadValuesAtTimesAsync(endpoint, request, ct).ConfigureAwait(false); if (result.History != null) { foreach (var item in result.History) { yield return item; } } await foreach (var item in HistoryStreamRemainingValuesAsync( endpoint, request.Header, result.ContinuationToken, ct).ConfigureAwait(false)) { yield return item; } } /// public async IAsyncEnumerable HistoryStreamProcessedValuesAsync( T endpoint, HistoryReadRequestModel request, [EnumeratorCancellation] CancellationToken ct) { var result = await HistoryReadProcessedValuesAsync(endpoint, request, ct).ConfigureAwait(false); if (result.History != null) { foreach (var item in result.History) { yield return item; } } await foreach (var item in HistoryStreamRemainingValuesAsync( endpoint, request.Header, result.ContinuationToken, ct).ConfigureAwait(false)) { yield return item; } } /// public async IAsyncEnumerable HistoryStreamEventsAsync( T endpoint, HistoryReadRequestModel request, [EnumeratorCancellation] CancellationToken ct) { var result = await HistoryReadEventsAsync(endpoint, request, ct).ConfigureAwait(false); if (result.History != null) { foreach (var item in result.History) { yield return item; } } await foreach (var item in HistoryStreamRemainingEventsAsync( endpoint, request.Header, result.ContinuationToken, ct).ConfigureAwait(false)) { yield return item; } } /// /// Read all remaining values /// /// /// /// /// /// private async IAsyncEnumerable HistoryStreamRemainingValuesAsync( T connectionId, RequestHeaderModel? header, string? continuationToken, [EnumeratorCancellation] CancellationToken ct) { while (continuationToken != null) { var response = await HistoryReadValuesNextAsync(connectionId, new HistoryReadNextRequestModel { ContinuationToken = continuationToken, Header = header }, ct).ConfigureAwait(false); continuationToken = response.ContinuationToken; if (response.History != null) { foreach (var item in response.History) { yield return item; } } } } /// /// Read all remaining events /// /// /// /// /// /// private async IAsyncEnumerable HistoryStreamRemainingEventsAsync( T connectionId, RequestHeaderModel? header, string? continuationToken, [EnumeratorCancellation] CancellationToken ct) { while (continuationToken != null) { var response = await HistoryReadEventsNextAsync(connectionId, new HistoryReadNextRequestModel { ContinuationToken = continuationToken, Header = header }, ct).ConfigureAwait(false); continuationToken = response.ContinuationToken; if (response.History != null) { foreach (var item in response.History) { yield return item; } } } } /// /// Update events /// /// /// /// /// /// /// public Task HistoryUpdateEventsAsync( T connectionId, HistoryUpdateRequestModel request, PerformUpdateType action, CancellationToken ct) { return _services.HistoryUpdateAsync(connectionId, request, (nodeId, details, session) => { if (details.Events == null || details.Events.Count == 0) { throw new ArgumentException("Bad events", nameof(details)); } return Task.FromResult(new ExtensionObject(new UpdateEventDetails { NodeId = nodeId, PerformInsertReplace = action, Filter = session.Codec.Decode(details.Filter), EventData = new HistoryEventFieldListCollection(details.Events .Select(d => new HistoryEventFieldList { EventFields = new VariantCollection(d.EventFields .Select(f => session.Codec.Decode(f, BuiltInType.Variant))) })) })); }, ct); } /// /// Update values /// /// /// /// /// /// /// public Task HistoryUpdateValuesAsync( T connectionId, HistoryUpdateRequestModel request, PerformUpdateType action, CancellationToken ct) { return _services.HistoryUpdateAsync(connectionId, request, async (nodeId, details, session) => { if (details.Values == null || details.Values.Count == 0) { throw new ArgumentException("Bad values", nameof(details)); } var builtinType = await GetDataTypeAsync(session, request.Header, nodeId, details.Values, _timeProvider, ct).ConfigureAwait(false); return new ExtensionObject(new UpdateDataDetails { NodeId = nodeId, PerformInsertReplace = action, UpdateValues = new DataValueCollection(details.Values .Select(d => new DataValue { ServerPicoseconds = d.ServerPicoseconds ?? 0, SourcePicoseconds = d.SourcePicoseconds ?? 0, ServerTimestamp = d.ServerTimestamp ?? DateTime.MinValue, SourceTimestamp = d.SourceTimestamp ?? DateTime.MinValue, StatusCode = d.Status?.StatusCode ?? StatusCodes.Good, Value = session.Codec.Decode( d.Value ?? VariantValue.Null, builtinType) })) }); }, ct); } /// /// Convert to results /// /// /// /// private static HistoricEventModel[] DecodeEvents(ExtensionObject extensionObject, IOpcUaSession session) { if (extensionObject.Body is HistoryEvent ev) { return ev.Events.Select(d => new HistoricEventModel { EventFields = d.EventFields .Select(v => v == Variant.Null ? VariantValue.Null : session.Codec.Encode(v, out var builtInType)) .ToList() }).ToArray(); } return []; } /// /// Gets the data type of the values and falls back /// to reading from node /// /// /// /// /// /// /// /// /// private static async Task GetDataTypeAsync( IOpcUaSession session, RequestHeaderModel? requestHeader, NodeId nodeId, IEnumerable values, TimeProvider timeProvider, CancellationToken ct) { // Get data type var dataTypes = values .Select(v => v.DataType) .Where(v => v != null) .ToList(); var dataType = dataTypes.FirstOrDefault(); #if DEBUG if (dataType != null && !dataTypes.All(v => string.Equals(v, dataType, StringComparison.Ordinal))) { throw new ArgumentException( $"All values must have no or data type {dataType}."); } #endif var dataTypeId = dataType.ToNodeId(session.MessageContext); if (NodeId.IsNull(dataTypeId)) { // Read data type (dataTypeId, _) = await session.ReadAttributeAsync( requestHeader.ToRequestHeader(timeProvider), nodeId, Attributes.DataType, ct).ConfigureAwait(false); if (NodeId.IsNull(dataTypeId)) { throw new ArgumentException( $"{nodeId} does not have a data type to fall back on."); } } return await session.LruNodeCache.GetBuiltInTypeAsync(dataTypeId, ct).ConfigureAwait(false); } /// /// Decode values /// /// /// /// /// private static HistoricValueModel[] DecodeValues(ExtensionObject extensionObject, IOpcUaSession session) { if (extensionObject.Body is HistoryData data) { var modificationInfos = new List(); if (extensionObject.Body is HistoryModifiedData modified) { if (modified.ModificationInfos.Count != data.DataValues.Count) { throw new FormatException( "Modification infos and data value count is not the same"); } return data.DataValues .Zip(modified.ModificationInfos) .Select(d => EncodeDataValue(session.Codec, d.First, d.Second)) .ToArray(); } return data.DataValues .Select(d => EncodeDataValue(session.Codec, d, null)) .ToArray(); } return []; static HistoricValueModel EncodeDataValue(IVariantEncoder codec, DataValue dataValue, ModificationInfo? modification) { var builtInType = BuiltInType.Null; return new HistoricValueModel { ServerPicoseconds = dataValue.ServerPicoseconds == 0 ? null : dataValue.ServerPicoseconds, SourcePicoseconds = dataValue.SourcePicoseconds == 0 ? null : dataValue.SourcePicoseconds, ServerTimestamp = dataValue.ServerTimestamp == DateTime.MinValue ? null : dataValue.ServerTimestamp, SourceTimestamp = dataValue.SourceTimestamp == DateTime.MinValue ? null : dataValue.SourceTimestamp, Status = // Remove aggregate bits we are testing below. (dataValue.StatusCode.Code & ~0x041F) == StatusCodes.Good ? null : dataValue.StatusCode.CreateResultModel(), DataLocation = dataValue.StatusCode.AggregateBits.ToDataLocation(), AdditionalData = dataValue.StatusCode.AggregateBits.ToAdditionalData(), ModificationInfo = modification == null ? null : new ModificationInfoModel { ModificationTime = modification.ModificationTime == DateTime.MinValue ? null : modification.ModificationTime, UpdateType = (HistoryUpdateOperation)modification.UpdateType, UserName = modification.UserName }, Value = dataValue.WrappedValue == Variant.Null ? null : codec.Encode(dataValue.WrappedValue, out builtInType), DataType = builtInType == BuiltInType.Null ? null : builtInType.ToString() }; } } private readonly INodeServicesInternal _services; private readonly IOptions _options; private readonly TimeProvider _timeProvider; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Services/NetworkMessageEncoder.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Services { using Azure.IIoT.OpcUa.Publisher; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Azure.IIoT.OpcUa.Encoders.Models; using Azure.IIoT.OpcUa.Encoders.PubSub; using Furly.Extensions.Messaging; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Opc.Ua; using System; using System.Buffers; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.Metrics; using System.Globalization; using System.Linq; using System.Text; /// /// Creates PubSub encoded messages /// public sealed class NetworkMessageEncoder : IMessageEncoder, IDisposable { /// public long NotificationsDroppedCount { get; private set; } /// public long NotificationsProcessedCount { get; private set; } /// public long MessagesProcessedCount { get; private set; } /// public double AvgNotificationsPerMessage { get; private set; } /// public double AvgMessageSize { get; private set; } /// public double MaxMessageSplitRatio { get; private set; } /// /// Create instance of NetworkMessageEncoder. /// /// injected configuration. /// Metrics context /// Logger to be used for reporting. /// time to use for timestamps public NetworkMessageEncoder(IOptions options, IMetricsContext metrics, ILogger logger, TimeProvider? timeProvider = null) { ArgumentNullException.ThrowIfNull(metrics); _logger = logger; _timeProvider = timeProvider ?? TimeProvider.System; _options = options; InitializeMetrics(metrics); _logNotifications = _options.Value.DebugLogEncodedNotifications == true; } /// public void Dispose() { _meter.Dispose(); } /// public IEnumerable<(IEvent Event, Action OnSent)> Encode(Func factory, IEnumerable notifications, int maxMessageSize, bool asBatch) { try { var chunkedMessages = new List<(IEvent, Action)>(); foreach (var m in GetNetworkMessages(notifications, asBatch)) { if (m.NetworkMessage == null) { // Write an empty message to the topic to delete the items on the broker var chunkedMessage = factory() .SetTimestamp(_timeProvider.GetUtcNow()) .SetTopic(m.Queue.QueueName) .SetQoS(m.Queue.RequestedDeliveryGuarantee ?? QoS.AtLeastOnce) ; chunkedMessages.Add((chunkedMessage, m.OnSentCallback)); continue; } if (m.EncodingContext == null) { _logger.MissingServiceMessageContext(); NotificationsDroppedCount++; m.OnSentCallback(); continue; } var chunks = m.NetworkMessage.Encode(m.EncodingContext, maxMessageSize); var notificationsPerChunk = m.NotificationsPerMessage / (double)chunks.Count; var validChunks = 0; foreach (var body in chunks) { if (body.Length == 0) { _logger.ChunkTooLarge(); continue; } validChunks++; AvgMessageSize = ((AvgMessageSize * MessagesProcessedCount) + body.Length) / (MessagesProcessedCount + 1); AvgNotificationsPerMessage = ((AvgNotificationsPerMessage * MessagesProcessedCount) + notificationsPerChunk) / (MessagesProcessedCount + 1); MessagesProcessedCount++; } if (validChunks > 0) { var chunkedMessage = factory() .SetTimestamp(_timeProvider.GetUtcNow()) .SetContentEncoding(m.NetworkMessage.ContentEncoding) .SetContentType(m.NetworkMessage.ContentType) .SetTopic(m.Queue.QueueName) .SetRetain(m.Queue.Retain ?? false) .SetQoS(m.Queue.RequestedDeliveryGuarantee ?? QoS.AtLeastOnce) .AddBuffers(chunks) ; if (m.Queue.Ttl.HasValue) { chunkedMessage = chunkedMessage .SetTtl(m.Queue.Ttl.Value); } if (m.CloudEvent != null) { // Send as cloud event chunkedMessage = chunkedMessage.AsCloudEvent(m.CloudEvent with { // TODO: To be compliant this should be the message id // of the network message (json only). But it is already // encoded, so we do not get it here. . // Id = m.NetworkMessage.MessageId, DataContentType = m.NetworkMessage.ContentType }); } else { chunkedMessage = chunkedMessage .AddProperty(OpcUa.Constants.MessagePropertySchemaKey, m.NetworkMessage.MessageSchema); if (_options.Value.EnableDataSetRoutingInfo ?? false) { chunkedMessage.AddProperty(OpcUa.Constants.MessagePropertyRoutingKey, m.NetworkMessage.DataSetWriterGroup); } if (_options.Value.UseStandardsCompliantEncoding != true) { chunkedMessage = chunkedMessage .AddProperty("$$ContentType", m.NetworkMessage.ContentType) .AddProperty("$$ContentEncoding", m.NetworkMessage.ContentEncoding); } } if (m.Schema != null) { chunkedMessage = chunkedMessage.SetSchema(m.Schema); } _logger.NotificationsEncoded(m.NotificationsPerMessage, validChunks); chunkedMessages.Add((chunkedMessage, m.OnSentCallback)); } else { // Nothing to send, complete here m.OnSentCallback(); } // We dropped a number of notifications but processed the remainder successfully var tooBig = chunks.Count - validChunks; NotificationsDroppedCount += tooBig; if (m.NotificationsPerMessage > tooBig) { NotificationsProcessedCount += m.NotificationsPerMessage - tooBig; } // // how many notifications per message resulted in how many buffers. We track the // split size to provide users with an indication how many times chunks had to // be created so they can configure publisher to improve performance. // if (m.NotificationsPerMessage > 0 && m.NotificationsPerMessage < validChunks) { var splitSize = validChunks / m.NotificationsPerMessage; if (splitSize > MaxMessageSplitRatio) { MaxMessageSplitRatio = splitSize; } } } return chunkedMessages; } catch (ObjectDisposedException) { return []; } finally { #if DEBUG notifications.ToList().ForEach(a => a.DebugAssertProcessed()); #endif } } /// /// Encoded message /// /// /// /// /// /// /// /// private record struct EncodedMessage(int NotificationsPerMessage, PubSubMessage? NetworkMessage, PublishingQueueSettingsModel Queue, Action OnSentCallback, IEventSchema? Schema, CloudEventHeader? CloudEvent, IServiceMessageContext? EncodingContext = null); /// /// Produce network messages from the data set message model /// /// /// /// private List GetNetworkMessages( IEnumerable messages, bool isBatched) { var standardsCompliant = _options.Value.UseStandardsCompliantEncoding ?? false; var result = new List(); static PublishingQueueSettingsModel GetQueue(DataSetWriterContext context, PublisherOptions options) { return new PublishingQueueSettingsModel { RequestedDeliveryGuarantee = context.Qos, Retain = context.Retain, Ttl = context.Ttl, QueueName = context.Topic }; } // Group messages by topic and qos, then writer group and then by dataset class id foreach (var topics in messages .Select(m => (Notification: m, Context: (m.Context as DataSetWriterContext)!)) .Where(m => m.Context != null) .GroupBy(m => GetQueue(m.Context, _options.Value))) { var queue = topics.Key; foreach (var publishers in topics.GroupBy(m => m.Context.PublisherId)) { var publisherId = publishers.Key; foreach (var groups in publishers .GroupBy(m => (m.Context.WriterGroup, m.Context.Schema, m.Context.CloudEvent))) { var writerGroup = groups.Key.WriterGroup; var schema = groups.Key.Schema; var cloudEvent = groups.Key.CloudEvent; if (writerGroup?.MessageSettings == null) { // Must have a writer group Drop(groups.Select(m => m.Notification)); continue; } var encoding = writerGroup.MessageType ?? MessageEncoding.Json; var networkMessageContentMask = writerGroup.MessageSettings.NetworkMessageContentMask; var hasSamplesPayload = (networkMessageContentMask & NetworkMessageContentFlags.MonitoredItemMessage) != 0; if (hasSamplesPayload && !isBatched) { networkMessageContentMask |= NetworkMessageContentFlags.SingleDataSetMessage; } var namespaceFormat = writerGroup.MessageSettings?.NamespaceFormat ?? _options.Value.DefaultNamespaceFormat ?? NamespaceFormat.Uri; foreach (var dataSetClass in groups .GroupBy(m => m.Context.Writer?.DataSet?.DataSetMetaData?.DataSetClassId ?? Guid.Empty)) { var dataSetClassId = dataSetClass.Key; BaseNetworkMessage? currentMessage = null; var currentNotifications = new List(); foreach (var (Notification, Context) in dataSetClass) { if (Context.Writer == null || (hasSamplesPayload && !encoding.HasFlag(MessageEncoding.Json))) { // Must have a writer or if samples mode, must be json Drop(Notification.YieldReturn()); continue; } var dataSetMessageContentMask = Context.Writer.MessageSettings?.DataSetMessageContentMask; var dataSetFieldContentMask = Context.Writer.DataSetFieldContentMask; if (Notification.MessageType == MessageType.Metadata) { if (Context.MetaData?.MetaData != null && !hasSamplesPayload) { if (currentMessage?.Messages.Count > 0) { // Start a new message but first emit current result.Add(new EncodedMessage(currentNotifications.Count, currentMessage, queue, () => currentNotifications.ForEach(n => n.Dispose()), schema, cloudEvent, Notification.ServiceMessageContext)); #if DEBUG currentNotifications.ForEach(n => n.MarkProcessed()); #endif currentMessage = null; currentNotifications = new List(); } if (PubSubMessage.TryCreateMetaDataMessage(encoding, publisherId, writerGroup.Name ?? Constants.DefaultWriterGroupName, GetDataSetWriterName(Notification, Context), Context.DataSetWriterId, Context.MetaData.MetaData, namespaceFormat, standardsCompliant, out var metadataMessage)) { result.Add(new EncodedMessage(0, metadataMessage, queue, Notification.Dispose, schema, cloudEvent, Notification.ServiceMessageContext)); } #if DEBUG Notification.MarkProcessed(); #endif LogNotification(Notification, false); } } else if (Notification.MessageType == MessageType.Closed) { if (currentMessage?.Messages.Count > 0) { // Start a new message but first emit current result.Add(new EncodedMessage(currentNotifications.Count, currentMessage, queue, () => currentNotifications.ForEach(n => n.Dispose()), schema, cloudEvent, Notification.ServiceMessageContext)); #if DEBUG currentNotifications.ForEach(n => n.MarkProcessed()); #endif currentMessage = null; currentNotifications = new List(); } result.Add(new EncodedMessage(0, null, queue, Notification.Dispose, null, null, null)); #if DEBUG Notification.MarkProcessed(); #endif LogNotification(Notification, false); } else if (Notification.MessageType == MessageType.KeepAlive) { Debug.Assert(Notification.Notifications.Count == 0); if (hasSamplesPayload) { Drop(Notification.YieldReturn()); continue; } // Create regular data set messages if (!PubSubMessage.TryCreateDataSetMessage(encoding, GetDataSetWriterName(Notification, Context), Context.DataSetWriterId, dataSetMessageContentMask, MessageType.KeepAlive, #if KA_WITH_EX_FIELDS new DataSet(Context.ExtensionFields, dataSetFieldContentMask), #else new DataSet(), #endif GetTimestamp(Notification), Context.NextWriterSequenceNumber(), standardsCompliant, Notification.EndpointUrl, Notification.ApplicationUri, Context.MetaData?.MetaData, out var dataSetMessage)) { Drop(Notification.YieldReturn()); continue; } AddMessage(dataSetMessage); LogNotification(Notification, false); currentNotifications.Add(Notification); continue; } else { Debug.Assert(Notification.Notifications != null); var notificationQueues = Notification.Notifications .GroupBy(m => m.DataSetFieldName) .Select(c => new Queue( c .OrderBy(m => m.Value?.SourceTimestamp) .ToArray())) .ToArray(); var notComplete = notificationQueues.Any(q => q.Count > 0); if (!notComplete) { // Already completed so we cannot complete it as an encoded message. Drop(Notification.YieldReturn()); continue; } while (notComplete) { var orderedNotifications = notificationQueues .Select(q => q.Count > 0 ? q.Dequeue() : null!) .Where(s => s?.DataSetFieldName != null) .ToList() ; notComplete = notificationQueues.Any(q => q.Count > 0); if (!hasSamplesPayload) { // Create regular data set messages if (!PubSubMessage.TryCreateDataSetMessage(encoding, GetDataSetWriterName(Notification, Context), Context.DataSetWriterId, dataSetMessageContentMask, Notification.MessageType, new DataSet(orderedNotifications .Select(s => (s.DataSetFieldName!, s.Value)) .Concat(Context.ExtensionFields) .ToList(), dataSetFieldContentMask), GetTimestamp(Notification), Context.NextWriterSequenceNumber(), standardsCompliant, Notification.EndpointUrl, Notification.ApplicationUri, Context.MetaData?.MetaData, out var dataSetMessage)) { Drop(Notification.YieldReturn()); continue; } AddMessage(dataSetMessage); LogNotification(Notification, false); } else { // Add monitored item message payload to network message to handle backcompat foreach (var itemNotifications in orderedNotifications .GroupBy(f => f.Id + f.MessageId)) { var notificationsInGroup = itemNotifications.ToList(); Debug.Assert(notificationsInGroup.Count != 0); // // Special monitored item handling for events and conditions. Collate all // values into a single key value data dictionary extension object value. // Regular notifications we send as single messages. // if (notificationsInGroup.Count > 1) { if (Notification.MessageType == MessageType.Event || Notification.MessageType == MessageType.Condition) { Debug.Assert(notificationsInGroup .Select(n => n.DataSetFieldName).Distinct().Count() == notificationsInGroup.Count, "There should not be duplicates in fields in a group."); Debug.Assert(notificationsInGroup .All(n => n.SequenceNumber == notificationsInGroup[0].SequenceNumber), "All notifications in the group should have the same sequence number."); var eventNotification = notificationsInGroup[0] with { Value = new DataValue { Value = new EncodeableDictionary(notificationsInGroup .Select(n => new KeyDataValuePair(n.DataSetFieldName!, n.Value))) }, DataSetFieldName = notificationsInGroup[0].DataSetName }; notificationsInGroup = new List { eventNotification }; } else if (_options.Value.RemoveDuplicatesFromBatch ?? false) { var pruned = notificationsInGroup .OrderByDescending(k => k.Value?.SourceTimestamp) // Descend from latest .DistinctBy(k => k.DataSetFieldName) // Only leave the latest values .ToList(); if (pruned.Count != notificationsInGroup.Count) { if (_logNotifications) { _logger.RemovedDuplicates(notificationsInGroup.Count - pruned.Count); } notificationsInGroup = pruned; } } } foreach (var notification in notificationsInGroup) { if (notification.DataSetFieldName != null) { if (!PubSubMessage.TryCreateMonitoredItemMessage(encoding, writerGroup.Name, dataSetMessageContentMask, Notification.MessageType, GetTimestamp(Notification), Context.NextWriterSequenceNumber(), new DataSet(notification.DataSetFieldName, notification.Value, dataSetFieldContentMask), notification.NodeId, Notification.EndpointUrl, Notification.ApplicationUri, standardsCompliant, Context.Writer.DataSet?.ExtensionFields, out var dataSetMessage)) { LogNotification(notification, true); continue; } AddMessage(dataSetMessage); LogNotification(notification, false); } } } } } currentNotifications.Add(Notification); } // // Add message and number of notifications processed count to method result. // Checks current length and splits if max items reached if configured. // void AddMessage(BaseDataSetMessage dataSetMessage) { if (currentMessage == null) { if (!PubSubMessage.TryCreateNetworkMessage(encoding, publisherId, writerGroup.Name ?? Constants.DefaultWriterGroupName, networkMessageContentMask, dataSetClassId, () => SequenceNumber.Increment16(ref _sequenceNumber), GetTimestamp(Notification) ?? _timeProvider.GetUtcNow(), namespaceFormat, standardsCompliant, isBatched, schema, out var message)) { Drop(messages); return; } currentMessage = message; } currentMessage.Messages.Add(dataSetMessage); var maxMessagesToPublish = writerGroup.MessageSettings?.MaxDataSetMessagesPerPublish ?? _options.Value.DefaultMaxDataSetMessagesPerPublish; if (maxMessagesToPublish != null && currentMessage.Messages.Count >= maxMessagesToPublish) { result.Add(new EncodedMessage(currentNotifications.Count, currentMessage, queue, () => currentNotifications.ForEach(n => n.Dispose()), schema, cloudEvent, Notification.ServiceMessageContext)); #if DEBUG currentNotifications.ForEach(n => n.MarkProcessed()); #endif currentMessage = null; currentNotifications = new List(); } } } if (currentMessage?.Messages.Count > 0) { result.Add(new EncodedMessage(currentNotifications.Count, currentMessage, queue, () => currentNotifications.ForEach(n => n.Dispose()), schema, cloudEvent, currentNotifications.LastOrDefault()?.ServiceMessageContext)); #if DEBUG currentNotifications.ForEach(n => n.MarkProcessed()); #endif } else { Debug.Assert(currentNotifications.Count == 0); } static string GetDataSetWriterName(OpcUaSubscriptionNotification Notification, DataSetWriterContext Context) { var dataSetWriterName = Context.WriterName; var eventTypeName = Notification.EventTypeName; if (!string.IsNullOrWhiteSpace(eventTypeName)) { return dataSetWriterName + "|" + eventTypeName; } return dataSetWriterName; } DateTimeOffset? GetTimestamp(OpcUaSubscriptionNotification Notification) { switch (_options.Value.MessageTimestamp) { case MessageTimestamp.EncodingTimeUtc: return _timeProvider.GetUtcNow(); case MessageTimestamp.PublishTime: return Notification.PublishTimestamp; default: return Notification.CreatedTimestamp; } } } } } } return result; } /// /// Drop and log messages /// /// private void Drop(IEnumerable messages) { var totalNotifications = 0; foreach (var message in messages) { LogNotification(message, true); totalNotifications += message.Notifications?.Count ?? 0; #if DEBUG message.MarkProcessed(); #endif message.Dispose(); } if (totalNotifications > 0) { _logger.DroppedValues(totalNotifications); NotificationsDroppedCount += totalNotifications; } } /// /// Log notifications for debugging /// /// /// private void LogNotification(OpcUaSubscriptionNotification args, bool dropped) { if (!_logNotifications) { return; } // Filter fields to log var notifications = Stringify(args.Notifications); if (!string.IsNullOrEmpty(notifications)) { _logger.NotificationInfo( dropped ? "!!!! Dropped !!!! " : "Encoded", args.PublishTimestamp, args.SequenceNumber, args.PublishSequenceNumber?.ToString(CultureInfo.CurrentCulture) ?? "-", args.MessageType, args.EndpointUrl, notifications); } } /// /// Log notifications for debugging /// /// /// private void LogNotification(MonitoredItemNotificationModel args, bool dropped) { if (!_logNotifications) { return; } // Filter fields to log var notifications = Stringify(args.YieldReturn()); if (!string.IsNullOrEmpty(notifications)) { _logger.NotificationSample( dropped ? "!!!! Dropped !!!! " : "Encoded", notifications); } } private static string Stringify(IEnumerable notifications) { var sb = new StringBuilder(); foreach (var item in notifications .Where(n => (n.Flags & MonitoredItemSourceFlags.ModelChanges) == 0)) { sb .AppendLine() .Append(" |") .Append(item.Value?.ServerTimestamp .ToString("hh:mm:ss:ffffff", CultureInfo.CurrentCulture)) .Append('|') .Append(item.DataSetFieldName ?? item.DataSetName) .Append('|') .Append(item.Value?.SourceTimestamp .ToString("hh:mm:ss:ffffff", CultureInfo.CurrentCulture)) .Append('|') .Append(item.Value?.Value) .Append('|') .Append(item.Value?.StatusCode) .Append('|') ; } return sb.ToString(); } /// /// Create observable metric registrations /// /// private void InitializeMetrics(IMetricsContext metrics) { _meter.CreateObservableCounter("iiot_edge_publisher_encoded_notifications", () => new Measurement(NotificationsProcessedCount, metrics.TagList), description: "Number of successfully processed subscription notifications " + "received from OPC client."); _meter.CreateObservableCounter("iiot_edge_publisher_dropped_notifications", () => new Measurement(NotificationsDroppedCount, metrics.TagList), description: "Number of incoming subscription notifications that are too " + "big to be processed based " + "on the message size limits or other issues with the notification."); _meter.CreateObservableCounter("iiot_edge_publisher_processed_messages", () => new Measurement(MessagesProcessedCount, metrics.TagList), description: "Number of successfully generated messages that are to be " + "sent using the message sender"); _meter.CreateObservableGauge("iiot_edge_publisher_notifications_per_message_average", () => new Measurement(AvgNotificationsPerMessage, metrics.TagList), description: "Average subscription notifications packed into a message"); _meter.CreateObservableGauge("iiot_edge_publisher_encoded_message_size_average", () => new Measurement(AvgMessageSize, metrics.TagList), description: "Average size of a message through the lifetime of the encoder."); _meter.CreateObservableGauge("iiot_edge_publisher_chunk_size_average", () => new Measurement(AvgMessageSize / (4 * 1024), metrics.TagList), description: "IoT Hub chunk size average"); _meter.CreateObservableGauge("iiot_edge_publisher_message_split_ratio_max", () => new Measurement(MaxMessageSplitRatio, metrics.TagList), description: "The message split ration specifies into how many messages " + "a subscription notification had to be split. Less is better for " + "performance. If the number is large user should attempt to limit " + "the number of notifications in a message using configuration."); } private uint _sequenceNumber; // TODO: Use writer group context private readonly IOptions _options; private readonly ILogger _logger; private readonly TimeProvider _timeProvider; private readonly Meter _meter = Diagnostics.NewMeter(); private readonly bool _logNotifications; } /// /// Source-generated logging extensions for NetworkMessageEncoder /// internal static partial class NetworkMessageEncoderLogging { private const int EventClass = 170; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Error, Message = "Missing service message context for network message - dropping notification.")] public static partial void MissingServiceMessageContext(this ILogger logger); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Debug, Message = "Resulting chunk is too large, dropped a notification.")] public static partial void ChunkTooLarge(this ILogger logger); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Debug, Message = "{Count} Notifications encoded into a network message (chunks:{Chunks})...")] public static partial void NotificationsEncoded(this ILogger logger, int count, int chunks); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Warning, Message = "Dropped {TotalNotifications} values")] public static partial void DroppedValues(this ILogger logger, int totalNotifications); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Information, Message = "{Action}|{PublishTime:hh:mm:ss:ffffff}|#{Seq}:{PublishSeq}|{MessageType}|{Endpoint}|{Items}")] public static partial void NotificationInfo(this ILogger logger, string action, DateTimeOffset? publishTime, uint seq, string publishSeq, MessageType messageType, string? endpoint, string items); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Information, Message = "{Action}|Sample|{Items}")] public static partial void NotificationSample(this ILogger logger, string action, string items); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Information, Message = "Removed {Count} duplicates from batch.")] public static partial void RemovedDuplicates(this ILogger logger, int count); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Services/NetworkMessageSink.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Services { using Azure.IIoT.OpcUa.Encoders.PubSub; using Azure.IIoT.OpcUa.Publisher; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Furly.Extensions.Messaging; using Furly.Extensions.Messaging.Clients; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.Metrics; using System.Globalization; using System.Linq; using System.Runtime.ConstrainedExecution; using System.Security.Authentication; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Threading.Tasks.Dataflow; /// /// Network message sink connected to the source. The sink consists of /// publish queue which is a dataflow engine to handle batching and /// encoding and other egress concerns. The queues can be partitioned /// to handle multiple topics. /// public sealed class NetworkMessageSink : IMessageSink, IDisposable, IAsyncDisposable { /// /// Create writer group network message sink /// /// /// /// /// /// /// /// /// /// public NetworkMessageSink(WriterGroupModel writerGroup, IEnumerable eventClients, IEnumerable factories, IMessageEncoder encoder, IOptions options, ILogger logger, IMetricsContext metrics, IWriterGroupDiagnostics? diagnostics = null, TimeProvider? timeProvider = null) { _metrics = metrics ?? throw new ArgumentNullException(nameof(metrics)); _options = options ?? throw new ArgumentNullException(nameof(options)); _messageEncoder = encoder ?? throw new ArgumentNullException(nameof(encoder)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _diagnostics = diagnostics; _timeProvider = timeProvider ?? TimeProvider.System; // Reverse the registration to have highest prio first. _eventClients = eventClients?.Reverse().ToList() ?? throw new ArgumentNullException(nameof(eventClients)); if (_eventClients.Count == 0) { throw new ArgumentException("No transports registered.", nameof(eventClients)); } _factories = factories?.ToDictionary(f => f.Name, StringComparer.OrdinalIgnoreCase) ?? throw new ArgumentNullException(nameof(factories)); _logNotificationsFilter = _options.Value.DebugLogNotificationsFilter == null ? null : new Regex(_options.Value.DebugLogNotificationsFilter); _filterNotifications = _options.Value.DebugLogNotificationsWithHeartbeat == true ? Filter : FilterHeartbeat; _logNotifications = _options.Value.DebugLogNotifications ?? (_logNotificationsFilter != null); _transport = new TransportOptions(writerGroup, _eventClients, _factories, _options, _logger); _queue = _transport.MaxPublishQueuePartitions != 0 ? new PublishQueue(this, _transport.MaxPublishQueuePartitions) : new PublishQueuePartition(this, 0, _logger); InitializeMetrics(); _startTime = _timeProvider.GetTimestamp(); _transport.Log(writerGroup, _logger); } /// public void OnMessage(OpcUaSubscriptionNotification notification) { if (_dataFlowStartTime == 0) { _diagnostics?.ResetWriterGroupDiagnostics(); _dataFlowStartTime = _timeProvider.GetTimestamp(); } if (!_queue.TryPublish(notification)) { notification.Dispose(); } } /// public void OnCounterReset() { _dataFlowStartTime = 0; _queue.Reset(); } /// public async ValueTask UpdateAsync(WriterGroupModel writerGroup) { // TODO: Call update on sink var cur = _transport; var options = new TransportOptions(writerGroup, _eventClients, _factories, _options, _logger); if (options == _transport) { // Group change does not effect transport settings return; } _transport = options; cur.Dispose(); // Todo: only check queue update await _queue.DisposeAsync().ConfigureAwait(false); _queue = options.MaxPublishQueuePartitions != 0 ? new PublishQueue(this, options.MaxPublishQueuePartitions) : new PublishQueuePartition(this, 0, _logger); _transport.Log(writerGroup, _logger); } /// public async ValueTask DisposeAsync() { await _cts.CancelAsync().ConfigureAwait(false); await _queue.DisposeAsync().ConfigureAwait(false); _queue = new NullPublishQueue(); var cur = _transport; _transport = new TransportOptions(); cur.Dispose(); } /// public void Dispose() { try { _meter.Dispose(); } finally { DisposeAsync().AsTask().GetAwaiter().GetResult(); _cts.Dispose(); } } /// /// Publishing queue interface /// private interface IPublishQueue : IAsyncDisposable { int BufferOutput { get; } int EncodingInput { get; } int EncodingOutput { get; } int SendInput { get; } int PartitionCount { get; } int ActiveCount { get; } /// /// Reset the queue /// void Reset(); /// /// Publish to the queue /// /// /// bool TryPublish(OpcUaSubscriptionNotification args); } /// /// Dummy publish queue /// private sealed class NullPublishQueue : IPublishQueue { /// public int BufferOutput { get; } /// public int EncodingInput { get; } /// public int EncodingOutput { get; } /// public int SendInput { get; } /// public int PartitionCount { get; } /// public int ActiveCount { get; } /// public ValueTask DisposeAsync() { return ValueTask.CompletedTask; } /// public void Reset() { } /// public bool TryPublish(OpcUaSubscriptionNotification args) { return false; } } /// /// Partitioned publish queue /// private sealed class PublishQueue : IPublishQueue { /// public int EncodingInput => _partitions.Sum(p => p.EncodingInput); /// public int EncodingOutput => _partitions.Sum(p => p.EncodingOutput); /// public int SendInput => _partitions.Sum(p => p.SendInput); /// public int BufferOutput => _partitions.Sum(p => p.BufferOutput); /// public int PartitionCount => _partitions.Length; /// public int ActiveCount => _partitions.Sum(p => p.ActiveCount); /// /// Create publish queue partition /// /// /// public PublishQueue(NetworkMessageSink outer, int maxPartitions) { maxPartitions = Math.Min(32, Math.Max(1, maxPartitions)); _partitions = Enumerable .Range(0, maxPartitions) .Select(índex => new PublishQueuePartition(outer, índex, outer._logger)) .ToArray(); } /// public bool TryPublish(OpcUaSubscriptionNotification args) { var hash = (args.Context as DataSetWriterContext)? .Topic?.GetHashCode(StringComparison.Ordinal) ?? 0; return _partitions[(uint)hash % _partitions.Length].TryPublish(args); } /// public void Reset() { _partitions.ForEach(p => p.Reset()); } /// public async ValueTask DisposeAsync() { foreach (var partition in _partitions) { await partition.DisposeAsync().ConfigureAwait(false); } } private readonly PublishQueuePartition[] _partitions; } /// /// Partitioned publish queue /// private sealed class PublishQueuePartition : IPublishQueue { /// public int EncodingInput => _encodingBlock.InputCount; /// public int EncodingOutput => _encodingBlock.OutputCount; /// public int SendInput => _sendBlock.InputCount; /// public int BufferOutput => _notificationBufferBlock.OutputCount; /// public int PartitionCount => 1; /// public int ActiveCount => _started ? 1 : 0; /// /// Create publish queue partition /// /// /// /// public PublishQueuePartition(NetworkMessageSink outer, int índex, ILogger logger) { _outer = outer; _índex = índex; _logger = logger; var maxBufferBlockCap = (int)Math.BigMul(_outer._transport.MaxPublishQueueSize, _outer._transport.MaxNotificationsPerMessage); if (maxBufferBlockCap == 0) { maxBufferBlockCap = DataflowBlockOptions.Unbounded; } var maxEncodingBlockCap = (int)Math.BigMul(_outer._transport.MaxPublishQueueSize, _outer._options.Value.MaxNodesPerDataSet); if (maxEncodingBlockCap == 0) { maxEncodingBlockCap = DataflowBlockOptions.Unbounded; } _batchTriggerIntervalTimer = _outer._timeProvider.CreateTimer( BatchTriggerIntervalTimer_Elapsed, null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); _notificationBufferBlock = new BatchBlock( Math.Max(1, _outer._transport.MaxNotificationsPerMessage), new GroupingDataflowBlockOptions { // BoundedCapacity = maxBufferBlockCap }); _encodingBlock = new TransformManyBlock( EncodeSubscriptionNotifications, new ExecutionDataflowBlockOptions { // BoundedCapacity = maxEncodingBlockCap, MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded }); _sendBlock = new ActionBlock<(IEvent, Action)>( SendAsync, new ExecutionDataflowBlockOptions { BoundedCapacity = _outer._transport.MaxPublishQueueSize + 1, MaxDegreeOfParallelism = 1, EnsureOrdered = true }); _notificationBufferBlock.LinkTo(_encodingBlock); _encodingBlock.LinkTo(_sendBlock); } /// public void Reset() { _started = false; } /// public async ValueTask DisposeAsync() { try { await _cts.CancelAsync().ConfigureAwait(false); _batchTriggerIntervalTimer.Change( Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); _batchTriggerIntervalTimer.Dispose(); // // Do not change this it must be in the order of the data flow, // complete and wait data to flow out to the next block which // is then completed. If blocks are completed downstream first // previous blocks will hang. // _notificationBufferBlock.Complete(); await _notificationBufferBlock.Completion.ConfigureAwait(false); _encodingBlock.Complete(); await _encodingBlock.Completion.ConfigureAwait(false); _sendBlock.Complete(); await _sendBlock.Completion.ConfigureAwait(false); } finally { _cts.Dispose(); } } /// public bool TryPublish(OpcUaSubscriptionNotification args) { if (!_started) { _started = true; if (_outer._transport.BatchTriggerInterval > TimeSpan.Zero) { _batchTriggerIntervalTimer.Change(_outer._transport.BatchTriggerInterval, Timeout.InfiniteTimeSpan); } _logger.PartitionStarted(_índex, args.ApplicationUri ?? "", args.EndpointUrl ?? ""); } if (_sendBlock.InputCount >= _outer._transport.MaxPublishQueueSize) { Interlocked.Increment(ref _outer._sendBlockInputDroppedCount); if (_outer._logNotifications) { _outer.LogNotification(args, true); } return false; } if (_outer._logNotifications) { _outer.LogNotification(args); } Interlocked.Increment(ref _outer._notificationBufferInputCount); if (!_notificationBufferBlock.Post(args)) { Interlocked.Increment(ref _outer._dataflowInputDroppedCount); return false; } return true; } /// /// Send message /// /// /// private async Task SendAsync((IEvent Event, Action Complete) message) { if (_cts.IsCancellationRequested) { message.Complete(); message.Event.Dispose(); _outer._logger.MessageDropped(); return; } try { // Do not give up and try to send the message until cancelled. var sw = Stopwatch.StartNew(); for (var attempt = 1; !_cts.IsCancellationRequested; attempt++) { try { // Throws if cancelled await message.Event.SendAsync(_cts.Token).ConfigureAwait(false); _outer._logger.MessageSent(attempt); break; } catch (OperationCanceledException) { } catch (Exception e) when (e is not ObjectDisposedException) { _outer._errorCount++; // Fail fast for authentication exceptions var aux = e as AuthenticationException; if (aux == null && e is AggregateException ag) { aux = ag .Flatten().InnerExceptions .OfType() .FirstOrDefault(); } if (aux?.Message.Equals("TLS authentication error.", StringComparison.Ordinal) == true) { _logger.WrongCertificate(aux, attempt); Runtime.FailFast(aux.Message, aux); } var delay = TimeSpan.FromMilliseconds(attempt * 100); if (_logger.IsEnabled(LogLevel.Debug)) { _logger.SendErrorWithStack(e, attempt, e.Message, delay); } else if (attempt % 10 == 0) { _logger.SendErrorWithStackPeriodic(e, attempt, e.Message, delay); } else { _logger.SendError(attempt, e.Message, delay); } // Throws if cancelled await Task.Delay(delay, _cts.Token).ConfigureAwait(false); } } // Message successfully published. Interlocked.Increment(ref _outer._messagesSentCount); kSendingDuration.Record(sw.ElapsedMilliseconds, _outer._metrics.TagList); message.Complete(); message.Event.Dispose(); return; } catch (ObjectDisposedException) { } catch (OperationCanceledException) { } catch (Exception e) { _logger.UnexpectedSendError(e); } } /// /// Encode notifications /// /// /// private IEnumerable<(IEvent, Action)> EncodeSubscriptionNotifications( OpcUaSubscriptionNotification[] input) { try { Interlocked.Add(ref _outer._notificationBufferInputCount, -input.Length); return _outer._messageEncoder.Encode( _outer._transport.EventClient.CreateEvent, input, _outer._transport.MaxNetworkMessageSize, _outer._transport.MaxNotificationsPerMessage != 1); } catch (Exception e) { _logger.EncodingFailure(e, _índex); input.ForEach(a => a.Dispose()); return []; } } /// /// Batch trigger interval /// /// private void BatchTriggerIntervalTimer_Elapsed(object? state) { if (_outer._transport.BatchTriggerInterval > TimeSpan.Zero) { _batchTriggerIntervalTimer.Change(_outer._transport.BatchTriggerInterval, Timeout.InfiniteTimeSpan); } _logger.BatchTrigger(_outer._transport.BatchTriggerInterval); _notificationBufferBlock.TriggerBatch(); } private bool _started; private readonly ILogger _logger; private readonly NetworkMessageSink _outer; private readonly int _índex; private readonly ITimer _batchTriggerIntervalTimer; private readonly BatchBlock _notificationBufferBlock; private readonly TransformManyBlock _encodingBlock; private readonly ActionBlock<(IEvent, Action)> _sendBlock; private readonly CancellationTokenSource _cts = new(); } private static IEnumerable FilterHeartbeat( IList notifications) { // Filter heartbeats and model changes return notifications .Where(n => (n.Flags & (MonitoredItemSourceFlags.Heartbeat | MonitoredItemSourceFlags.ModelChanges)) == 0); } private static IEnumerable Filter( IList notifications) { // Filter model changes return notifications .Where(n => (n.Flags & MonitoredItemSourceFlags.ModelChanges) == 0); } /// /// Log notifications for debugging /// /// /// private void LogNotification(OpcUaSubscriptionNotification args, bool dropped = false) { // Filter fields to log if (_logNotificationsFilter != null) { var matched = args.EndpointUrl != null && _logNotificationsFilter.IsMatch(args.EndpointUrl); for (var i = 0; i < args.Notifications.Count && !matched; i++) { var itemName = args.Notifications[i].DataSetFieldName ?? args.Notifications[i].DataSetName; if (itemName != null) { matched = _logNotificationsFilter.IsMatch(itemName); } } if (!matched) { // Do not log anything return; } } var notifications = Stringify(_filterNotifications(args.Notifications)); if (!string.IsNullOrEmpty(notifications)) { _logger.NotificationLog( dropped ? "!!!! Dropped !!!! " : string.Empty, args.PublishTimestamp, args.SequenceNumber, args.PublishSequenceNumber?.ToString(CultureInfo.CurrentCulture) ?? "-", args.MessageType, args.EndpointUrl ?? string.Empty, notifications); } static string Stringify(IEnumerable notifications) { var sb = new StringBuilder(); foreach (var item in notifications) { sb .AppendLine() .Append(" |") .Append(item.Value?.ServerTimestamp .ToString("hh:mm:ss:ffffff", CultureInfo.CurrentCulture)) .Append('|') .Append(item.DataSetFieldName ?? item.DataSetName) .Append('|') .Append(item.Value?.SourceTimestamp .ToString("hh:mm:ss:ffffff", CultureInfo.CurrentCulture)) .Append('|') .Append(item.Value?.Value) .Append('|') .Append(item.Value?.StatusCode) .Append('|') ; } return sb.ToString(); } } /// /// Transport configuration /// internal record class TransportOptions : IDisposable { /// /// Event client selected /// public IEventClient EventClient { get; } /// /// Notifications per message /// public int MaxNotificationsPerMessage { get; } /// /// Max network messages /// public int MaxNetworkMessageSize { get; } /// /// Max publish queue size /// public int MaxPublishQueueSize { get; } /// /// Max batch trigger interval /// public TimeSpan BatchTriggerInterval { get; } /// /// Iot edge configured /// public bool IsIoTEdge => EventClient.Name.Equals(nameof(WriterGroupTransport.IoTHub), StringComparison.OrdinalIgnoreCase); /// /// Max publish queue partitions /// public int MaxPublishQueuePartitions { get; } /// /// Create null options /// public TransportOptions() { EventClient = new NullEventClient(); } /// public void Dispose() { _scope?.Dispose(); } /// /// Create options /// /// /// /// /// /// public TransportOptions(WriterGroupModel writerGroup, List eventClients, Dictionary factories, IOptions options, ILogger logger) { EventClient = eventClients .Find(e => e.Name.Equals(writerGroup.Transport?.ToString(), StringComparison.OrdinalIgnoreCase)) ?? eventClients .Find(e => e.Name.Equals(options.Value.DefaultTransport?.ToString(), StringComparison.OrdinalIgnoreCase)) ?? eventClients[0]; if (!string.IsNullOrEmpty(writerGroup.TransportConfiguration)) { if (!factories.TryGetValue(EventClient.Name, out var factory)) { logger.CustomWriterGroupConfigurationCouldNotBeApplied( EventClient.Name); } else { // Create event client with configuration from factory. try { _scope = factory.CreateEventClient( writerGroup.TransportConfiguration, out var client); EventClient = client; logger.UsingTransportWithCustomWriterGroupConfiguration( EventClient.Name); } catch (Exception e) { logger.CustomWriterGroupConfigurationCouldNotBeAppliedWithError( EventClient.Name, e.Message); } } } MaxNotificationsPerMessage = (int?)writerGroup.NotificationPublishThreshold ?? options.Value.BatchSize ?? 0; MaxNetworkMessageSize = (int?)writerGroup.MaxNetworkMessageSize ?? options.Value.MaxNetworkMessageSize ?? 0; if (MaxNetworkMessageSize <= 0) { MaxNetworkMessageSize = int.MaxValue; } if (MaxNetworkMessageSize > EventClient.MaxEventPayloadSizeInBytes) { MaxNetworkMessageSize = EventClient.MaxEventPayloadSizeInBytes; } BatchTriggerInterval = writerGroup.PublishingInterval ?? options.Value.BatchTriggerInterval ?? TimeSpan.Zero; // // If the max notification per message is 1 then there is no need to // have an interval publishing as the messages are emitted as soon // as they arrive anyway // if (MaxNotificationsPerMessage == 1) { BatchTriggerInterval = TimeSpan.Zero; } MaxPublishQueueSize = (int?)writerGroup.PublishQueueSize ?? options.Value.MaxNetworkMessageSendQueueSize ?? kMaxQueueSize; // // If undefined, set notification buffer to 1 if no publishing interval // otherwise queue as much as reasonable // if (MaxNotificationsPerMessage <= 0) { MaxNotificationsPerMessage = BatchTriggerInterval == TimeSpan.Zero ? 1 : MaxPublishQueueSize; } MaxPublishQueuePartitions = writerGroup.PublishQueuePartitions ?? options.Value.DefaultWriterGroupPartitions ?? 0; } /// /// Log the transportation options /// /// /// public void Log(WriterGroupModel writerGroup, ILogger logger) { var interval = BatchTriggerInterval == TimeSpan.Zero ? "as soon as they arrive" : $"every {BatchTriggerInterval} (hh:mm:ss)"; var batching = MaxNotificationsPerMessage == 1 ? "and individually" : $"or when a batch of {MaxNotificationsPerMessage} notifications is ready"; var maxSize = MaxNetworkMessageSize == int.MaxValue ? "unlimited size" : $"at most {MaxNetworkMessageSize / 1024} kb"; logger.WriterGroupSetup( writerGroup.Name ?? Constants.DefaultWriterGroupName, interval, batching, maxSize, EventClient.Name, writerGroup.HeaderLayoutUri ?? "unknown", writerGroup.MessageType ?? MessageEncoding.Json, MaxPublishQueueSize); } /// /// With 256k limit this is 1 GB. /// TODO: Must be related to the actual limit size /// private const int kMaxQueueSize = 4096; private readonly IDisposable? _scope; } /// /// Create observable metrics /// private void InitializeMetrics() { _meter.CreateObservableUpDownCounter("iiot_edge_publisher_partitions_count", () => new Measurement(_queue.PartitionCount, _metrics.TagList), description: "Partition count of the writer queue."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_partitions_active", () => new Measurement(_queue.ActiveCount, _metrics.TagList), description: "Active partitions pushing data inside the writer queue."); _meter.CreateObservableCounter("iiot_edge_publisher_send_queue_dropped_count", () => new Measurement(_sendBlockInputDroppedCount, _metrics.TagList), description: "Telemetry messages dropped due to overflow."); _meter.CreateObservableCounter("iiot_edge_publisher_publish_queue_dropped_count", () => new Measurement(_dataflowInputDroppedCount, _metrics.TagList), description: "Telemetry messages dropped due to overflow of the publish queue."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_send_queue_size", () => new Measurement(_queue.SendInput, _metrics.TagList), description: "Telemetry messages queued for sending upstream."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_batch_input_queue_size", () => new Measurement(_notificationBufferInputCount, _metrics.TagList), description: "Telemetry messages queued for sending upstream."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_encoding_input_queue_size", () => new Measurement(_queue.EncodingInput, _metrics.TagList), description: "Telemetry messages queued for sending upstream."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_encoding_output_queue_size", () => new Measurement(_queue.EncodingOutput, _metrics.TagList), description: "Telemetry messages queued for sending upstream."); _meter.CreateObservableCounter("iiot_edge_publisher_messages", () => new Measurement(_messagesSentCount, _metrics.TagList), description: "Number of IoT messages successfully sent via transport."); _meter.CreateObservableGauge("iiot_edge_publisher_messages_per_second", () => new Measurement(_messagesSentCount / UpTime, _metrics.TagList), description: "Messages/second sent via transport."); _meter.CreateObservableCounter("iiot_edge_publisher_message_send_failures", () => new Measurement(_errorCount, _metrics.TagList), description: "Number of failures sending a network message."); _meter.CreateObservableCounter("iiot_edge_publisher_sent_iot_messages", () => new Measurement(_transport.IsIoTEdge ? _messagesSentCount : 0, _metrics.TagList), description: "Number of IoT messages successfully sent via transport."); _meter.CreateObservableGauge("iiot_edge_publisher_sent_iot_messages_per_second", () => new Measurement(_transport.IsIoTEdge ? _messagesSentCount / UpTime : 0d, _metrics.TagList), description: "Messages/second sent via transport."); _meter.CreateObservableCounter("iiot_edge_publisher_iothub_queue_dropped_count", () => new Measurement(_transport.IsIoTEdge ? _sendBlockInputDroppedCount : 0, _metrics.TagList), description: "Telemetry messages dropped due to overflow of the send queue."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_iothub_queue_size", () => new Measurement(_transport.IsIoTEdge ? _queue.SendInput : 0, _metrics.TagList), description: "Telemetry messages queued for sending upstream."); _meter.CreateObservableCounter("iiot_edge_publisher_failed_iot_messages", () => new Measurement(_transport.IsIoTEdge ? _errorCount : 0, _metrics.TagList), description: "Number of failures sending a network message."); } private static readonly Histogram kSendingDuration = Diagnostics.Meter.CreateHistogram( "iiot_edge_publisher_messages_duration", description: "Histogram of message sending durations."); private double UpTime => _timeProvider.GetElapsedTime(_startTime).TotalSeconds; private long _messagesSentCount; private long _errorCount; private long _sendBlockInputDroppedCount; private long _dataflowInputDroppedCount; private long _notificationBufferInputCount; private readonly IOptions _options; private readonly IMessageEncoder _messageEncoder; private IPublishQueue _queue; private TransportOptions _transport; private readonly List _eventClients; private readonly ILogger _logger; private readonly TimeProvider _timeProvider; private readonly IWriterGroupDiagnostics? _diagnostics; private readonly bool _logNotifications; private readonly Dictionary _factories; private readonly Regex? _logNotificationsFilter; private readonly Func, IEnumerable> _filterNotifications; private readonly long _startTime; private long _dataFlowStartTime; private readonly CancellationTokenSource _cts = new(); private readonly IMetricsContext _metrics; private readonly Meter _meter = Diagnostics.NewMeter(); } /// /// Source-generated logging definitions for NetworkMessageSink /// internal static partial class NetworkMessageSinkLogging { private const int EventClass = 200; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Information, Message = "Partition #{Partition}: Started data flow with notification from server {Name} and endpoint {Endpoint}.")] public static partial void PartitionStarted(this ILogger logger, int partition, string name, string endpoint); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Debug, Message = "Closed. Network message dropped.")] public static partial void MessageDropped(this ILogger logger); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Debug, Message = "#{Attempt}: Network message sent.")] public static partial void MessageSent(this ILogger logger, int attempt); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Critical, Message = "#{Attempt}: Wrong TLS certificate trust list provisioned - trying to reset and reload configuration...")] public static partial void WrongCertificate(this ILogger logger, Exception ex, int attempt); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Debug, SkipEnabledCheck = true, Message = "#{Attempt}: Error '{Error}' during sending network message. Retrying in {Delay}...")] public static partial void SendErrorWithStack(this ILogger logger, Exception ex, int attempt, string error, TimeSpan delay); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Error, Message = "#{Attempt}: Error '{Error}' during sending network message. Retrying in {Delay}...")] public static partial void SendErrorWithStackPeriodic(this ILogger logger, Exception ex, int attempt, string error, TimeSpan delay); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Error, Message = "#{Attempt}: Error '{Error}' during sending network message. Retrying in {Delay}...")] public static partial void SendError(this ILogger logger, int attempt, string error, TimeSpan delay); [LoggerMessage(EventId = EventClass + 8, Level = LogLevel.Error, Message = "Encoding failure on partition #{Partition}.")] public static partial void EncodingFailure(this ILogger logger, Exception ex, int partition); [LoggerMessage(EventId = EventClass + 9, Level = LogLevel.Error, Message = "Unexpected error sending network message.")] public static partial void UnexpectedSendError(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 10, Level = LogLevel.Trace, Message = "Trigger notification batch (Interval:{Interval})...")] public static partial void BatchTrigger(this ILogger logger, TimeSpan interval); [LoggerMessage(EventId = EventClass + 11, Level = LogLevel.Information, Message = "{Action}|{PublishTime:hh:mm:ss:ffffff}|#{Seq}:{PublishSeq}|{MessageType}|{Endpoint}|{Items}")] public static partial void NotificationLog(this ILogger logger, string action, DateTimeOffset? publishTime, uint seq, string publishSeq, MessageType messageType, string endpoint, string items); [LoggerMessage(EventId = EventClass + 12, Level = LogLevel.Information, Message = "Writer group {WriterGroup} set up to publish notifications {Interval} {Batching} with {MaxSize} to" + " {Transport} with {HeaderLayout} layout and {MessageType} encoding (queuing at most {MaxQueueSize} subscription" + " notifications)...")] public static partial void WriterGroupSetup(this ILogger logger, string writerGroup, string interval, string batching, string maxSize, string transport, string headerLayout, MessageEncoding messageType, int maxQueueSize); [LoggerMessage(EventId = EventClass + 13, Level = LogLevel.Information, Message = "Using transport {Transport} with custom writer group configuration.")] public static partial void UsingTransportWithCustomWriterGroupConfiguration(this ILogger logger, string transport); [LoggerMessage(EventId = EventClass + 14, Level = LogLevel.Warning, Message = "Custom writer group configuration could not be applied to transport {Transport} " + "- using default.")] public static partial void CustomWriterGroupConfigurationCouldNotBeApplied(this ILogger logger, string transport); [LoggerMessage(EventId = EventClass + 15, Level = LogLevel.Error, Message = "Custom writer group configuration could not be applied to transport {Transport} " + "due to bad configuration (Error: {Error}) - using default.")] public static partial void CustomWriterGroupConfigurationCouldNotBeAppliedWithError(this ILogger logger, string transport, string error); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Services/NodeServices.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Services { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Parser; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Stack.Extensions; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Furly.Extensions.Serializers; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using BrowseDirection = Models.BrowseDirection; using NodeClass = Models.NodeClass; using Opc.Ua; using Opc.Ua.Extensions; using System; using System.Buffers; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; /// /// This class provides access to a servers address space providing node /// and browse services. It uses the OPC ua client interface to access /// the server. /// /// public sealed class NodeServices : INodeServices, INodeServicesInternal, IDisposable { /// /// Create node service /// /// /// /// /// /// public NodeServices(IOpcUaClientManager client, IFilterParser parser, ILogger> logger, IOptions options, TimeProvider? timeProvider = null) { _logger = logger; _client = client; _parser = parser; _options = options; _timeProvider = timeProvider ?? TimeProvider.System; } /// public void Dispose() { _activitySource.Dispose(); } /// public Task GetServerCapabilitiesAsync(T endpoint, RequestHeaderModel? header, CancellationToken ct) { return _client.ExecuteAsync(endpoint, async context => await context.Session.GetServerCapabilitiesAsync( header.GetNamespaceFormat(_options), ct).ConfigureAwait(false), header, ct); } /// public async Task BrowseFirstAsync(T endpoint, BrowseFirstRequestModel request, CancellationToken ct) { using var trace = _activitySource.StartActivity("BrowseFirst"); return await _client.ExecuteAsync(endpoint, async context => { var rootId = request.NodeId.ToNodeId(context.Session.MessageContext); if (NodeId.IsNull(rootId)) { rootId = ObjectIds.RootFolder; } var typeId = request.ReferenceTypeId.ToNodeId(context.Session.MessageContext); if (NodeId.IsNull(typeId)) { typeId = ReferenceTypeIds.HierarchicalReferences; } var view = request.View.ToStackModel(context.Session.MessageContext); var excludeReferences = false; var rawMode = request.NodeIdsOnly ?? false; if (!rawMode) { excludeReferences = request.MaxReferencesToReturn == 0; } var references = new List(); ServiceResultModel? errorInfo = null; if (!excludeReferences) { var direction = (request.Direction ?? BrowseDirection.Forward) .ToStackType(); var browseDescriptions = new BrowseDescriptionCollection { new BrowseDescription { BrowseDirection = direction, IncludeSubtypes = !(request.NoSubtypes ?? false), NodeClassMask = (uint)request.NodeClassFilter.ToStackMask(), NodeId = rootId, ReferenceTypeId = typeId, ResultMask = (uint)BrowseResultMask.All } }; // Browse and read children var response = await context.Session.Services.BrowseAsync( request.Header.ToRequestHeader(_timeProvider), ViewDescription.IsDefault(view) ? null : view, request.MaxReferencesToReturn ?? 0, browseDescriptions, ct).ConfigureAwait(false); var results = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, browseDescriptions); errorInfo = results.ErrorInfo; if (errorInfo == null) { errorInfo = results[0].ErrorInfo; context.TrackedToken = await AddReferencesToBrowseResultAsync(context.Session, request.Header, request.TargetNodesOnly ?? false, request.ReadVariableValues ?? false, rawMode, references, results[0].Result.ContinuationPoint, results[0].Result.References, ct).ConfigureAwait(false); } } var (node, nodeError) = await context.Session.ReadNodeAsync( request.Header.ToRequestHeader(_timeProvider), rootId, null, true, rawMode, request.Header.GetNamespaceFormat(_options), !excludeReferences ? references.Count != 0 : null, ct).ConfigureAwait(false); return new BrowseFirstResponseModel { // Read root node Node = node, References = excludeReferences ? Array.Empty() : references, ContinuationToken = context.TrackedToken, ErrorInfo = errorInfo ?? nodeError }; }, request.Header, ct).ConfigureAwait(false); } /// public async Task BrowseNextAsync(T endpoint, BrowseNextRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); if (string.IsNullOrEmpty(request.ContinuationToken)) { throw new ArgumentException("Missing continuation token", nameof(request)); } using var trace = _activitySource.StartActivity("BrowseNext"); var continuationPoint = Convert.FromBase64String(request.ContinuationToken); return await _client.ExecuteAsync(endpoint, async context => { var references = new List(); var continuationPoints = new ByteStringCollection { continuationPoint }; var response = await context.Session.Services.BrowseNextAsync( request.Header.ToRequestHeader(_timeProvider), request.Abort ?? false, continuationPoints, ct).ConfigureAwait(false); context.UntrackedToken = request.ContinuationToken; var results = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, continuationPoints); if (results.ErrorInfo != null) { return new BrowseNextResponseModel { References = references, ErrorInfo = results.ErrorInfo }; } context.TrackedToken = await AddReferencesToBrowseResultAsync(context.Session, request.Header, request.TargetNodesOnly ?? false, request.ReadVariableValues ?? false, request.NodeIdsOnly ?? false, references, results[0].Result.ContinuationPoint, results[0].Result.References, ct).ConfigureAwait(false); return new BrowseNextResponseModel { References = references, ContinuationToken = context.TrackedToken, ErrorInfo = results[0].ErrorInfo }; }, request.Header, ct).ConfigureAwait(false); } /// public IAsyncEnumerable BrowseAsync(T endpoint, BrowseStreamRequestModel request, CancellationToken ct) { var stream = new BrowseStream(request, _options, _activitySource, _logger, _timeProvider, ct); return _client.ExecuteAsync(endpoint, stream, request.Header, ct); } /// public async Task BrowsePathAsync(T endpoint, BrowsePathRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); if (request.BrowsePaths == null || request.BrowsePaths.Count == 0 || request.BrowsePaths.Any(p => p == null || p.Count == 0)) { throw new ArgumentException("Bad browse path", nameof(request)); } using var trace = _activitySource.StartActivity("BrowsePath"); return await _client.ExecuteAsync(endpoint, async context => { var rootId = request.NodeId.ToNodeId(context.Session.MessageContext); if (NodeId.IsNull(rootId)) { rootId = ObjectIds.RootFolder; } var targets = new List(); var requests = new BrowsePathCollection(request.BrowsePaths.Select(p => new BrowsePath { StartingNode = rootId, RelativePath = p.ToRelativePath(context.Session.MessageContext) })); var response = await context.Session.Services.TranslateBrowsePathsToNodeIdsAsync( request.Header.ToRequestHeader(_timeProvider), requests, context.Ct).ConfigureAwait(false); var results = response.Validate( response.Results, r => r.StatusCode, response.DiagnosticInfos, request.BrowsePaths); if (results.ErrorInfo != null) { return new BrowsePathResponseModel { ErrorInfo = results.ErrorInfo }; } foreach (var operation in results) { await AddTargetsToBrowseResultAsync(context.Session, request.Header, request.ReadVariableValues ?? false, request.NodeIdsOnly ?? false, targets, operation.Result.Targets, [.. operation.Request], context.Ct).ConfigureAwait(false); } return new BrowsePathResponseModel { Targets = targets, ErrorInfo = results[0].ErrorInfo }; }, request.Header, ct).ConfigureAwait(false); } /// public async Task GetMetadataAsync( T endpoint, NodeMetadataRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); if (string.IsNullOrEmpty(request.NodeId) && (request.BrowsePath == null || request.BrowsePath.Count == 0)) { throw new ArgumentException("Node id or browse path missing", nameof(request)); } using var trace = _activitySource.StartActivity("GetMetadata"); return await _client.ExecuteAsync(endpoint, async context => { var nodeId = await context.Session.ResolveNodeIdAsync(request.Header, request.NodeId, request.BrowsePath, nameof(request.BrowsePath), _timeProvider, context.Ct).ConfigureAwait(false); if (NodeId.IsNull(nodeId)) { throw new ArgumentException("Node id missing", nameof(request)); } var (node, errorInfo) = await context.Session.ReadNodeAsync( request.Header.ToRequestHeader(_timeProvider), nodeId, request.Header.GetNamespaceFormat(_options), ct: context.Ct).ConfigureAwait(false); if (errorInfo != null || node.NodeClass == null) { return new NodeMetadataResponseModel { ErrorInfo = errorInfo ?? ((StatusCode)StatusCodes.BadNodeIdUnknown) .CreateResultModel() }; } VariableMetadataModel? variableMetadata = null; MethodMetadataModel? methodMetadata = null; DataTypeMetadataModel? dataTypeMetadata = null; var typeId = nodeId; if (node.NodeClass == NodeClass.Method) { (methodMetadata, errorInfo) = await context.Session.GetMethodMetadataAsync( request.Header.ToRequestHeader(_timeProvider), nodeId, request.Header.GetNamespaceFormat(_options), context.Ct).ConfigureAwait(false); if (errorInfo != null) { return new NodeMetadataResponseModel { ErrorInfo = errorInfo }; } } else if (node.NodeClass == NodeClass.DataType) { // TODO dataTypeMetadata = null; } else if (node.NodeClass is NodeClass.Variable or NodeClass.Object) { // Get type definition var (references, ei) = await context.Session.FindAsync( request.Header.ToRequestHeader(_timeProvider), nodeId.YieldReturn(), ReferenceTypeIds.HasTypeDefinition, maxResults: 1, ct: context.Ct).ConfigureAwait(false); typeId = references.FirstOrDefault(r => r.ErrorInfo == null).Node; if (NodeId.IsNull(typeId)) { typeId = nodeId; } if (node.NodeClass == NodeClass.Variable) { (variableMetadata, errorInfo) = await context.Session.GetVariableMetadataAsync( request.Header.ToRequestHeader(_timeProvider), nodeId, request.Header.GetNamespaceFormat(_options), context.Ct).ConfigureAwait(false); if (errorInfo != null) { return new NodeMetadataResponseModel { ErrorInfo = errorInfo }; } } } var type = node; if (typeId != nodeId) { (type, errorInfo) = await context.Session.ReadNodeAsync( request.Header.ToRequestHeader(_timeProvider), typeId, request.Header.GetNamespaceFormat(_options), ct: context.Ct).ConfigureAwait(false); if (errorInfo != null || type.NodeClass == null) { return new NodeMetadataResponseModel { ErrorInfo = errorInfo ?? ((StatusCode)StatusCodes.BadTypeDefinitionInvalid) .CreateResultModel() }; } } // process the types starting from the top of the tree. var map = new Dictionary(); var declarations = new List(); var hierarchy = new List<(NodeId, ReferenceDescription)>(); await context.Session.CollectTypeHierarchyAsync(request.Header.ToRequestHeader(_timeProvider), typeId, hierarchy, context.Ct).ConfigureAwait(false); hierarchy.Reverse(); // Start from Root super type foreach (var (subType, superType) in hierarchy) { errorInfo = await context.Session.CollectInstanceDeclarationsAsync( request.Header.ToRequestHeader(_timeProvider), (NodeId)superType.NodeId, null, declarations, map, request.Header.GetNamespaceFormat(_options), ct: context.Ct).ConfigureAwait(false); if (errorInfo != null) { break; } } if (errorInfo == null) { // collect the fields for the selected type. errorInfo = await context.Session.CollectInstanceDeclarationsAsync( request.Header.ToRequestHeader(_timeProvider), typeId, null, declarations, map, request.Header.GetNamespaceFormat(_options), ct: context.Ct).ConfigureAwait(false); } return new NodeMetadataResponseModel { ErrorInfo = errorInfo, Description = node.Description, DisplayName = node.DisplayName, NodeClass = node.NodeClass.Value, NodeId = node.NodeId, MethodMetadata = methodMetadata, VariableMetadata = variableMetadata, DataTypeMetadata = dataTypeMetadata, TypeDefinition = errorInfo != null ? null : new TypeDefinitionModel { TypeDefinitionId = type.NodeId, DisplayName = type.DisplayName, BrowseName = type.BrowseName, Description = type.Description, TypeHierarchy = hierarchy.ConvertAll(e => new NodeModel { NodeId = request.Header.AsString(e.Item2.NodeId, context.Session.MessageContext, _options), DisplayName = e.Item2.DisplayName.AsString(), BrowseName = request.Header.AsString(e.Item2.BrowseName, context.Session.MessageContext, _options), NodeClass = e.Item2.NodeClass.ToServiceType() }), NodeType = GetNodeType(hierarchy .Select(r => (NodeId)r.Item2.NodeId) .Append(typeId) .ToList()), Declarations = declarations } }; }, request.Header, ct).ConfigureAwait(false); static NodeType GetNodeType(List hierarchy) { if (hierarchy.Count > 1) { if (hierarchy[1] == ObjectTypeIds.BaseEventType) { return NodeType.Event; } if (hierarchy[1] == ObjectTypeIds.BaseInterfaceType) { return NodeType.Interface; } if (hierarchy[1] == VariableTypeIds.PropertyType) { return NodeType.Property; } if (hierarchy[1] == VariableTypeIds.BaseDataVariableType) { return NodeType.DataVariable; } } if (hierarchy.Count > 0) { if (hierarchy[0] == VariableTypeIds.BaseVariableType) { return NodeType.Variable; } if (hierarchy[0] == ObjectTypeIds.BaseObjectType) { return NodeType.Object; } } return NodeType.Unknown; } } /// public async Task CompileQueryAsync(T endpoint, QueryCompilationRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); if (string.IsNullOrEmpty(request.Query)) { throw new ArgumentException("Query must not be empty", nameof(request)); } using var trace = _activitySource.StartActivity("CompileQuery"); try { return await _client.ExecuteAsync(endpoint, async context => { var parserContext = new SessionParserContext(context.Session, request.Header.ToRequestHeader(_timeProvider), request.Header.GetNamespaceFormat(_options)); var eventFilter = await _parser.ParseEventFilterAsync(request.Query, parserContext, context.Ct).ConfigureAwait(false); return new QueryCompilationResponseModel { EventFilter = eventFilter, ErrorInfo = parserContext.ErrorInfo }; }, request.Header, ct).ConfigureAwait(false); } catch (Exception ex) { // This is where the parser exceptions will end up return new QueryCompilationResponseModel { ErrorInfo = ex.ToServiceResultModel() }; } } /// public async Task GetMethodMetadataAsync( T endpoint, MethodMetadataRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); if (string.IsNullOrEmpty(request.MethodId) && (request.MethodBrowsePath == null || request.MethodBrowsePath.Count == 0)) { throw new ArgumentException("Node id missing", nameof(request)); } using var trace = _activitySource.StartActivity("GetMethodMetadata"); return await _client.ExecuteAsync(endpoint, async context => { var methodId = await context.Session.ResolveNodeIdAsync(request.Header, request.MethodId, request.MethodBrowsePath, nameof(request.MethodBrowsePath), _timeProvider, context.Ct).ConfigureAwait(false); if (NodeId.IsNull(methodId)) { throw new ArgumentException(nameof(request.MethodId)); } var browseDescriptions = new BrowseDescriptionCollection { new BrowseDescription { BrowseDirection = Opc.Ua.BrowseDirection.Both, IncludeSubtypes = true, NodeClassMask = 0, NodeId = methodId, ReferenceTypeId = ReferenceTypeIds.Aggregates, ResultMask = (uint)BrowseResultMask.All } }; // Get default input arguments and types var browse = await context.Session.Services.BrowseAsync( request.Header.ToRequestHeader(_timeProvider), null, 0, browseDescriptions, context.Ct).ConfigureAwait(false); var browseresults = browse.Validate(browse.Results, r => r.StatusCode, browse.DiagnosticInfos, browseDescriptions); if (browseresults.ErrorInfo != null) { return new MethodMetadataResponseModel { ErrorInfo = browseresults.ErrorInfo }; } var result = new MethodMetadataResponseModel(); foreach (var nodeReference in browseresults[0].Result.References) { if (result.OutputArguments != null && result.InputArguments != null && !string.IsNullOrEmpty(result.ObjectId)) { break; } if (!nodeReference.IsForward) { if (nodeReference.ReferenceTypeId == ReferenceTypeIds.HasComponent) { result.ObjectId = request.Header.AsString(nodeReference.NodeId, context.Session.MessageContext, _options); } continue; } var isInput = nodeReference.BrowseName == BrowseNames.InputArguments; if (!isInput && nodeReference.BrowseName != BrowseNames.OutputArguments) { continue; } var node = nodeReference.NodeId.ToNodeId(context.Session.MessageContext.NamespaceUris); var (value, errorInfo) = await context.Session.ReadValueAsync( request.Header.ToRequestHeader(_timeProvider), node, context.Ct).ConfigureAwait(false); if (errorInfo != null) { return new MethodMetadataResponseModel { ErrorInfo = errorInfo }; } if (value?.Value is not ExtensionObject[] argumentsList) { continue; } var argList = new List(); foreach (var argument in argumentsList.Select(a => (Argument)a.Body)) { var (dataTypeIdNode, errorInfo2) = await context.Session.ReadNodeAsync( request.Header.ToRequestHeader(_timeProvider), argument.DataType, null, false, false, request.Header.GetNamespaceFormat(_options), false, context.Ct).ConfigureAwait(false); var arg = new MethodMetadataArgumentModel { Name = argument.Name, DefaultValue = argument.Value == null ? VariantValue.Null : context.Session.Codec.Encode(new Variant(argument.Value), out var type), ValueRank = argument.ValueRank == ValueRanks.Scalar ? null : (global::Azure.IIoT.OpcUa.Publisher.Models.NodeValueRank)argument.ValueRank, ArrayDimensions = argument.ArrayDimensions?.ToArray(), Description = argument.Description?.ToString(), ErrorInfo = errorInfo2, Type = dataTypeIdNode }; argList.Add(arg); } if (isInput) { result.InputArguments = argList; } else { result.OutputArguments = argList; } } return result; }, request.Header, ct).ConfigureAwait(false); } /// public async Task MethodCallAsync(T endpoint, MethodCallRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); if (string.IsNullOrEmpty(request.ObjectId) && (request.ObjectBrowsePath == null || request.ObjectBrowsePath.Count == 0)) { throw new ArgumentException("Object id missing or bad browse path", nameof(request)); } using var trace = _activitySource.StartActivity("MethodCall"); return await _client.ExecuteAsync(endpoint, async context => { // // A method call request can specify the targets in several ways: // // * Specify methodId and optionally objectId node ids with null browse paths. // * Specify an objectBrowsePath to a real object node from the node specified // with objectId. If objectId is null, the root node is used. // * Specify a methodBrowsePath from the above object node to the actual // method node to call on the object. MethodId remains null. // * Like previously, but specify methodId and method browse path from it to a // real method node. // var objectId = await context.Session.ResolveNodeIdAsync(request.Header, request.ObjectId, request.ObjectBrowsePath, nameof(request.ObjectBrowsePath), _timeProvider, context.Ct).ConfigureAwait(false); if (NodeId.IsNull(objectId)) { throw new ArgumentException("Object id missing", nameof(request)); } var methodId = request.MethodId.ToNodeId(context.Session.MessageContext); if (request.MethodBrowsePath?.Count > 0) { if (NodeId.IsNull(methodId)) { // Browse from object id to method if possible methodId = objectId ?? throw new ArgumentException("Method id and object id missing", nameof(request)); } methodId = await context.Session.ResolveBrowsePathToNodeAsync(request.Header, methodId, [.. request.MethodBrowsePath], nameof(request.MethodBrowsePath), _timeProvider, context.Ct).ConfigureAwait(false); } else if (NodeId.IsNull(methodId)) { // Method is null and cannot browse to method from object throw new ArgumentException("Method id missing", nameof(request)); } var browseDescriptions = new BrowseDescriptionCollection { new BrowseDescription { BrowseDirection = Opc.Ua.BrowseDirection.Forward, IncludeSubtypes = true, NodeClassMask = 0, NodeId = methodId, ReferenceTypeId = ReferenceTypeIds.HasProperty, ResultMask = (uint)BrowseResultMask.All } }; // Get default input arguments and types var browse = await context.Session.Services.BrowseAsync( request.Header.ToRequestHeader(_timeProvider), null, 0, browseDescriptions, context.Ct).ConfigureAwait(false); var browseresults = browse.Validate(browse.Results, r => r.StatusCode, browse.DiagnosticInfos, browseDescriptions); List<(TypeInfo, object)>? inputs = null, outputs = null; if (browseresults.ErrorInfo == null) { foreach (var nodeReference in browseresults[0].Result.References) { List<(TypeInfo, object)>? temp = null; if (nodeReference.BrowseName == BrowseNames.InputArguments) { temp = inputs = []; } else if (nodeReference.BrowseName == BrowseNames.OutputArguments) { temp = outputs = []; } else { continue; } var node = nodeReference.NodeId.ToNodeId(context.Session.MessageContext.NamespaceUris); var (value, _) = await context.Session.ReadValueAsync( request.Header.ToRequestHeader(_timeProvider), node, context.Ct).ConfigureAwait(false); // value is also null if the type is not a variable node if (value?.Value is ExtensionObject[] argumentsList) { foreach (var argument in argumentsList.Select(a => (Argument)a.Body)) { var builtInType = TypeInfo.GetBuiltInType(argument.DataType); temp.Add((new TypeInfo(builtInType, argument.ValueRank), argument.Value)); } if (inputs != null && outputs != null) { break; } } } } if ((request.Arguments?.Count ?? 0) > (inputs?.Count ?? 0)) { // Too many arguments provided if (browseresults.ErrorInfo != null) { return new MethodCallResponseModel { Results = Array.Empty(), ErrorInfo = browseresults.ErrorInfo }; } throw new ArgumentException("Arguments missing", nameof(request)); } // Set default input arguments from meta data var requests = new CallMethodRequestCollection { new CallMethodRequest { ObjectId = objectId, MethodId = methodId, InputArguments = inputs == null ? [] : new VariantCollection(inputs .Select(arg => arg.Item1.CreateVariant(arg.Item2))) } }; // Update with input arguments provided in request payload if ((request.Arguments?.Count ?? 0) != 0) { Debug.Assert(request.Arguments != null); Debug.Assert(inputs != null); for (var i = 0; i < request.Arguments.Count; i++) { var arg = request.Arguments[i]; if (arg == null) { continue; } var builtinType = inputs[i].Item1.BuiltInType; if (!string.IsNullOrEmpty(arg.DataType)) { builtinType = await context.Session.LruNodeCache.GetBuiltInTypeAsync( arg.DataType.ToNodeId(context.Session.MessageContext), context.Ct).ConfigureAwait(false); } requests[0].InputArguments[i] = context.Session.Codec.Decode( arg.Value ?? VariantValue.Null, builtinType); } } // Call method var response = await context.Session.Services.CallAsync( request.Header.ToRequestHeader(_timeProvider), requests, context.Ct).ConfigureAwait(false); var results = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, requests); if (results.ErrorInfo != null) { return new MethodCallResponseModel { Results = Array.Empty(), ErrorInfo = results.ErrorInfo }; } // Create output argument list var arguments = new List(); var args = results[0].Result.OutputArguments?.Count ?? 0; for (var i = 0; i < args; i++) { var arg = results[0].Result.OutputArguments[i]; if (arg == Variant.Null && (outputs?.Count ?? 0) > i && outputs![i].Item2 != null) { // return default value arg = new Variant(outputs[i].Item2); } var value = context.Session.Codec.Encode(arg, out var type); if (type == BuiltInType.Null && (outputs?.Count ?? 0) > i) { // return default type from type info type = outputs![i].Item1.BuiltInType; } var dataType = type == BuiltInType.Null ? null : type.ToString(); arguments.Add(new MethodCallArgumentModel { Value = value, DataType = dataType }); } return new MethodCallResponseModel { Results = arguments, ErrorInfo = results[0].ErrorInfo }; }, request.Header, ct).ConfigureAwait(false); } /// public async Task ValueReadAsync(T endpoint, ValueReadRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); if (string.IsNullOrEmpty(request.NodeId) && (request.BrowsePath == null || request.BrowsePath.Count == 0)) { throw new ArgumentException("Bad node id or browse path missing", nameof(request)); } using var trace = _activitySource.StartActivity("ValueRead"); return await _client.ExecuteAsync(endpoint, async context => { var readNode = await context.Session.ResolveNodeIdAsync(request.Header, request.NodeId, request.BrowsePath, nameof(request.BrowsePath), _timeProvider, context.Ct).ConfigureAwait(false); if (NodeId.IsNull(readNode)) { throw new ArgumentException("Node id missing", nameof(request)); } var nodesToRead = new ReadValueIdCollection { new ReadValueId { NodeId = readNode, AttributeId = Attributes.Value, IndexRange = request.IndexRange, // // TODO: // A QualifiedName that specifies the data encoding to // be returned for the Value to be read. // Only works for "Structure" types, which we need to // check first. However, then we should specify Xml // and convert to json. // DataEncoding = null } }; var response = await context.Session.Services.ReadAsync( request.Header.ToRequestHeader(_timeProvider), request.MaxAge?.TotalMilliseconds ?? 0, request.TimestampsToReturn.ToStackType(), nodesToRead, context.Ct).ConfigureAwait(false); var values = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, nodesToRead); if (values.ErrorInfo != null) { return new ValueReadResponseModel { ErrorInfo = values.ErrorInfo }; } return new ValueReadResponseModel { ServerPicoseconds = values[0].Result.ServerPicoseconds != 0 ? values[0].Result.ServerPicoseconds : null, ServerTimestamp = values[0].Result.ServerTimestamp != DateTime.MinValue ? values[0].Result.ServerTimestamp : null, SourcePicoseconds = values[0].Result.SourcePicoseconds != 0 ? values[0].Result.SourcePicoseconds : null, SourceTimestamp = values[0].Result.SourceTimestamp != DateTime.MinValue ? values[0].Result.SourceTimestamp : null, Value = context.Session.Codec.Encode(values[0].Result.WrappedValue, out var type), DataType = type == BuiltInType.Null ? null : type.ToString(), ErrorInfo = values[0].ErrorInfo }; }, request.Header, ct).ConfigureAwait(false); } /// public async Task ValueWriteAsync(T endpoint, ValueWriteRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); if (request.Value is null) { throw new ArgumentException("Missing value", nameof(request)); } if (string.IsNullOrEmpty(request.NodeId) && (request.BrowsePath == null || request.BrowsePath.Count == 0)) { throw new ArgumentException("Bad node id or browse path missing", nameof(request)); } using var trace = _activitySource.StartActivity("ValueWrite"); return await _client.ExecuteAsync(endpoint, async context => { var writeNode = await context.Session.ResolveNodeIdAsync(request.Header, request.NodeId, request.BrowsePath, nameof(request.BrowsePath), _timeProvider, context.Ct).ConfigureAwait(false); if (NodeId.IsNull(writeNode)) { throw new ArgumentException("Node id missing", nameof(request)); } var dataTypeId = request.DataType.ToNodeId(context.Session.MessageContext); if (NodeId.IsNull(dataTypeId)) { // Read data type (dataTypeId, _) = await context.Session.ReadAttributeAsync( request.Header.ToRequestHeader(_timeProvider), writeNode, Attributes.DataType, context.Ct).ConfigureAwait(false); if (NodeId.IsNull(dataTypeId)) { throw new ArgumentException("Data type missing", nameof(request)); } } var builtinType = await context.Session.LruNodeCache.GetBuiltInTypeAsync(dataTypeId, context.Ct).ConfigureAwait(false); var value = context.Session.Codec.Decode(request.Value, builtinType); var nodesToWrite = new WriteValueCollection{ new WriteValue { NodeId = writeNode, AttributeId = Attributes.Value, Value = new DataValue(value), IndexRange = request.IndexRange } }; var result = new ValueWriteResponseModel(); var response = await context.Session.Services.WriteAsync( request.Header.ToRequestHeader(_timeProvider), nodesToWrite, context.Ct).ConfigureAwait(false); var values = response.Validate(response.Results, s => s, response.DiagnosticInfos, nodesToWrite); return new ValueWriteResponseModel { ErrorInfo = values.ErrorInfo ?? values[0].ErrorInfo }; }, request.Header, ct).ConfigureAwait(false); } /// public async Task ReadAsync(T endpoint, ReadRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); if (request.Attributes == null) { throw new ArgumentException("Missing attributes", nameof(request)); } if (request.Attributes.Any(a => string.IsNullOrEmpty(a.NodeId))) { throw new ArgumentException("Bad attributes", nameof(request)); } using var trace = _activitySource.StartActivity("Read"); return await _client.ExecuteAsync(endpoint, async context => { var requests = new ReadValueIdCollection(request.Attributes .Select(a => new ReadValueId { AttributeId = (uint)a.Attribute, NodeId = a.NodeId.ToNodeId(context.Session.MessageContext) })); var response = await context.Session.Services.ReadAsync( request.Header.ToRequestHeader(_timeProvider), 0, Opc.Ua.TimestampsToReturn.Both, requests, context.Ct).ConfigureAwait(false); var results = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, requests); if (results.ErrorInfo != null) { return new ReadResponseModel { Results = Array.Empty(), ErrorInfo = results.ErrorInfo }; } return new ReadResponseModel { Results = results .Select(result => { return new AttributeReadResponseModel { Value = context.Session.Codec.Encode(result.Result.WrappedValue, out var wellKnown), ErrorInfo = result.ErrorInfo }; }).ToList() }; }, request.Header, ct).ConfigureAwait(false); } /// public async Task WriteAsync(T endpoint, WriteRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); if (request.Attributes == null) { throw new ArgumentException("Missing attributes", nameof(request)); } if (request.Attributes.Any(a => string.IsNullOrEmpty(a.NodeId))) { throw new ArgumentException("Missing node id in attributes", nameof(request)); } using var trace = _activitySource.StartActivity("Write"); return await _client.ExecuteAsync(endpoint, async context => { var requests = new WriteValueCollection(request.Attributes .Select(a => new WriteValue { AttributeId = (uint)a.Attribute, NodeId = a.NodeId.ToNodeId(context.Session.MessageContext), Value = new DataValue(context.Session.Codec.Decode(a.Value ?? VariantValue.Null, AttributeMap.GetBuiltInType((uint)a.Attribute))) })); var response = await context.Session.Services.WriteAsync( request.Header.ToRequestHeader(_timeProvider), requests, context.Ct).ConfigureAwait(false); var results = response.Validate(response.Results, s => s, response.DiagnosticInfos, requests); if (results.ErrorInfo != null) { return new WriteResponseModel { Results = Array.Empty(), ErrorInfo = results.ErrorInfo }; } return new WriteResponseModel { Results = results .Select(result => { return new AttributeWriteResponseModel { ErrorInfo = result.ErrorInfo }; }).ToList() }; }, request.Header, ct).ConfigureAwait(false); } /// public Task HistoryGetServerCapabilitiesAsync( T endpoint, RequestHeaderModel? header, CancellationToken ct) { return _client.ExecuteAsync(endpoint, async context => await context.Session.GetHistoryCapabilitiesAsync(header.GetNamespaceFormat(_options), context.Ct).ConfigureAwait(false), header, ct); } /// public async Task HistoryGetConfigurationAsync( T endpoint, HistoryConfigurationRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); if (string.IsNullOrEmpty(request.NodeId)) { throw new ArgumentException("Bad node id missing", nameof(request)); } using var trace = _activitySource.StartActivity("HistoryGetConfiguration"); return await _client.ExecuteAsync(endpoint, async context => { var nodeId = request.NodeId.ToNodeId(context.Session.MessageContext); if (NodeId.IsNull(nodeId)) { throw new ArgumentException("Bad node id", nameof(request)); } // load the defaults for the historical configuration object. var config = new HistoricalDataConfigurationState(null); config.Definition = new PropertyState(config); config.MaxTimeInterval = new PropertyState(config); config.MinTimeInterval = new PropertyState(config); config.ExceptionDeviation = new PropertyState(config); config.ExceptionDeviationFormat = new PropertyState(config); config.StartOfArchive = new PropertyState(config); config.StartOfOnlineArchive = new PropertyState(config); config.Stepped = new PropertyState(config); config.ServerTimestampSupported = new PropertyState(config); config.AggregateFunctions = new FolderState(config); var aggregate = new AggregateConfigurationState(config); aggregate.TreatUncertainAsBad = new PropertyState(aggregate); aggregate.UseSlopedExtrapolation = new PropertyState(aggregate); aggregate.PercentDataBad = new PropertyState(aggregate); aggregate.PercentDataGood = new PropertyState(aggregate); config.AggregateConfiguration = aggregate; config.Create(context.Session.SystemContext, null, BrowseNames.HAConfiguration, null, false); var relativePath = new RelativePath(); relativePath.Elements.Add(new RelativePathElement { ReferenceTypeId = ReferenceTypeIds.HasHistoricalConfiguration, IsInverse = false, IncludeSubtypes = false, TargetName = BrowseNames.HAConfiguration }); var errorInfo = await context.Session.ReadNodeStateAsync( request.Header.ToRequestHeader(_timeProvider), config, nodeId, relativePath, context.Ct).ConfigureAwait(false); if (errorInfo != null) { return new HistoryConfigurationResponseModel { ErrorInfo = errorInfo }; } var startTime = config.StartOfOnlineArchive.GetValueOrDefaultEx() ?? config.StartOfArchive.GetValueOrDefaultEx(); if (startTime == null) { startTime = await HistoryReadTimestampAsync( context.Session, request.Header, nodeId, true, _timeProvider, context.Ct).ConfigureAwait(false); } DateTime? endTime = null; if (endTime == null) { endTime = await HistoryReadTimestampAsync( context.Session, request.Header, nodeId, false, _timeProvider, context.Ct).ConfigureAwait(false); } var children = new List(); config.AggregateFunctions.GetChildren(context.Session.SystemContext, children); var aggregateFunctions = children.OfType().ToDictionary( c => request.Header.AsString(c.BrowseName, context.Session.MessageContext, _options), c => request.Header.AsString(c.NodeId, context.Session.MessageContext, _options)); return new HistoryConfigurationResponseModel { Configuration = errorInfo != null ? null : new HistoryConfigurationModel { MinTimeInterval = config.MinTimeInterval.GetValueOrDefaultEx( v => v.HasValue && v.Value != 0 ? TimeSpan.FromMilliseconds(v.Value) : (TimeSpan?)null), MaxTimeInterval = config.MaxTimeInterval.GetValueOrDefaultEx( v => v.HasValue && v.Value != 0 ? TimeSpan.FromMilliseconds(v.Value) : (TimeSpan?)null), ExceptionDeviation = config.ExceptionDeviation.GetValueOrDefaultEx(), ExceptionDeviationType = config.ExceptionDeviationFormat.GetValueOrDefaultEx( v => v.ToExceptionDeviationType()), ServerTimestampSupported = config.ServerTimestampSupported.GetValueOrDefaultEx(), Stepped = config.Stepped.GetValueOrDefaultEx(), Definition = config.Definition.GetValueOrDefaultEx(), AggregateFunctions = aggregateFunctions.Count == 0 ? null : aggregateFunctions, AggregateConfiguration = new AggregateConfigurationModel { PercentDataBad = aggregate.PercentDataBad.GetValueOrDefaultEx(), PercentDataGood = aggregate.PercentDataGood.GetValueOrDefaultEx(), TreatUncertainAsBad = aggregate.TreatUncertainAsBad.GetValueOrDefaultEx(), UseSlopedExtrapolation = aggregate.UseSlopedExtrapolation.GetValueOrDefaultEx() }, StartOfOnlineArchive = startTime ?? config.StartOfOnlineArchive.GetValueOrDefaultEx( v => v == DateTime.MinValue ? startTime : v), StartOfArchive = config.StartOfArchive.GetValueOrDefaultEx( v => v == DateTime.MinValue ? startTime : v) ?? startTime, EndOfArchive = endTime } }; }, request.Header, ct).ConfigureAwait(false); } /// public Task> HistoryReadAsync(T endpoint, HistoryReadRequestModel request, CancellationToken ct) { return HistoryReadAsync(endpoint, request, (details, session) => { var variant = session.Codec.Decode(details, BuiltInType.ExtensionObject); if (variant.Value is not ExtensionObject extensionObject) { throw new ArgumentException("Bad details", nameof(request)); } return extensionObject; }, (details, session) => session.Codec.Encode(new Variant(details), out _), ct); } /// public Task> HistoryReadNextAsync( T endpoint, HistoryReadNextRequestModel request, CancellationToken ct) { return HistoryReadNextAsync(endpoint, request, (details, session) => session.Codec.Encode(new Variant(details), out _), ct); } /// public Task HistoryUpdateAsync(T endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { return HistoryUpdateAsync(endpoint, request, (nodeId, details, session) => { var variant = session.Codec.Decode(details, BuiltInType.ExtensionObject); if (variant.Value is not ExtensionObject extensionObject) { throw new ArgumentException("Bad details", nameof(request)); } if (extensionObject.Body is HistoryUpdateDetails updateDetails) { updateDetails.NodeId = nodeId; } return Task.FromResult(extensionObject); }, ct); } /// public async Task> HistoryReadAsync( T connectionId, HistoryReadRequestModel request, Func decode, Func encode, CancellationToken ct) where TInput : class where TResult : class { ArgumentNullException.ThrowIfNull(request); if (request.Details == null) { throw new ArgumentException("Missing details", nameof(request)); } if (string.IsNullOrEmpty(request.NodeId) && (request.BrowsePath == null || request.BrowsePath.Count == 0)) { throw new ArgumentException("Bad node id or browse path missing", nameof(request)); } using var trace = _activitySource.StartActivity("HistoryRead"); return await _client.ExecuteAsync(connectionId, async context => { var nodeId = await context.Session.ResolveNodeIdAsync(request.Header, request.NodeId, request.BrowsePath, nameof(request.BrowsePath), _timeProvider, context.Ct).ConfigureAwait(false); if (NodeId.IsNull(nodeId)) { throw new ArgumentException("Bad node id", nameof(request)); } var readDetails = decode(request.Details, context.Session); var historytoread = new HistoryReadValueIdCollection { new HistoryReadValueId { IndexRange = request.IndexRange, NodeId = nodeId, DataEncoding = null // TODO } }; var response = await context.Session.Services.HistoryReadAsync( request.Header.ToRequestHeader(_timeProvider), readDetails, request.TimestampsToReturn.ToStackType(), false, historytoread, context.Ct).ConfigureAwait(false); var results = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, historytoread); if (results.ErrorInfo != null) { return new HistoryReadResponseModel { History = null, ErrorInfo = results.ErrorInfo }; } var history = encode(results[0].Result.HistoryData, context.Session); var errorInfo = results[0].ErrorInfo; if (errorInfo?.StatusCode == StatusCodes.GoodNoData && history is Array array && array.Length > 0) { errorInfo = null; // There is data, so fix up error } context.TrackedToken = results[0].Result.ContinuationPoint == null || results[0].Result.ContinuationPoint.Length == 0 ? null : Convert.ToBase64String(results[0].Result.ContinuationPoint); return new HistoryReadResponseModel { ContinuationToken = context.TrackedToken, History = history, ErrorInfo = errorInfo }; }, request.Header, ct).ConfigureAwait(false); } /// public async Task> HistoryReadNextAsync( T connectionId, HistoryReadNextRequestModel request, Func encode, CancellationToken ct) where TResult : class { ArgumentNullException.ThrowIfNull(request); if (string.IsNullOrEmpty(request.ContinuationToken)) { throw new ArgumentException("Missing continuation", nameof(request)); } using var trace = _activitySource.StartActivity("HistoryReadNext"); return await _client.ExecuteAsync(connectionId, async context => { var historytoread = new HistoryReadValueIdCollection { new HistoryReadValueId { ContinuationPoint = Convert.FromBase64String(request.ContinuationToken), DataEncoding = null // TODO } }; var response = await context.Session.Services.HistoryReadAsync( request.Header.ToRequestHeader(_timeProvider), null, Opc.Ua.TimestampsToReturn.Both, request.Abort ?? false, historytoread, context.Ct).ConfigureAwait(false); context.UntrackedToken = request.ContinuationToken; var results = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, historytoread); if (results.ErrorInfo != null) { return new HistoryReadNextResponseModel { History = null, ErrorInfo = results.ErrorInfo }; } var history = encode(results[0].Result.HistoryData, context.Session); var errorInfo = results[0].ErrorInfo; if (errorInfo?.StatusCode == StatusCodes.GoodNoData && history is Array array && array.Length > 0) { errorInfo = null; // There is data, so fix up error } context.TrackedToken = results[0].Result.ContinuationPoint == null || results[0].Result.ContinuationPoint.Length == 0 ? null : Convert.ToBase64String(results[0].Result.ContinuationPoint); return new HistoryReadNextResponseModel { ContinuationToken = context.TrackedToken, History = history, ErrorInfo = errorInfo }; }, request.Header, ct).ConfigureAwait(false); } /// public async Task HistoryUpdateAsync( T connectionId, HistoryUpdateRequestModel request, Func> decode, CancellationToken ct) where TInput : class { ArgumentNullException.ThrowIfNull(request); if (request.Details == null) { throw new ArgumentException("Missing details", nameof(request)); } using var trace = _activitySource.StartActivity("HistoryUpdate"); return await _client.ExecuteAsync(connectionId, async context => { var nodeId = await context.Session.ResolveNodeIdAsync(request.Header, request.NodeId, request.BrowsePath, nameof(request.BrowsePath), _timeProvider, context.Ct).ConfigureAwait(false); // Update the node id to target based on the request if (NodeId.IsNull(nodeId)) { throw new ArgumentException("Missing node id", nameof(request)); } var details = await decode(nodeId, request.Details, context.Session).ConfigureAwait(false); if (details == null) { throw new ArgumentException("Bad details", nameof(request)); } var updates = new ExtensionObjectCollection { details }; var response = await context.Session.Services.HistoryUpdateAsync( request.Header.ToRequestHeader(_timeProvider), updates, context.Ct).ConfigureAwait(false); var results = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, updates); if (results.ErrorInfo != null) { return new HistoryUpdateResponseModel { ErrorInfo = results.ErrorInfo }; } var inner = response.Validate(response.Results[0].OperationResults, s => s, response.Results[0].DiagnosticInfos); return new HistoryUpdateResponseModel { Results = inner.Select(r => r.ResultInfo).ToList(), ErrorInfo = inner.ErrorInfo }; }, request.Header, ct).ConfigureAwait(false); } /// /// Add references /// /// /// /// /// /// /// /// /// /// /// private async Task AddReferencesToBrowseResultAsync(IOpcUaSession session, RequestHeaderModel? header, bool targetNodesOnly, bool readValues, bool rawMode, List result, byte[] continuationPoint, List references, CancellationToken ct) { if (references == null) { return null; } foreach (var reference in references) { try { var nodeId = reference.NodeId.ToNodeId(session.MessageContext.NamespaceUris); var id = header.AsString(nodeId, session.MessageContext, _options); if (targetNodesOnly && result.Any(r => r.Target.NodeId == id)) { continue; } bool? children = null; if (!rawMode) { // Check for children try { var browseDescriptions = new BrowseDescriptionCollection { new BrowseDescription { BrowseDirection = Opc.Ua.BrowseDirection.Forward, IncludeSubtypes = true, NodeClassMask = 0, NodeId = nodeId, ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences, ResultMask = (uint)BrowseResultMask.All } }; var response = await session.Services.BrowseAsync( header.ToRequestHeader(_timeProvider), null, 1, browseDescriptions, ct).ConfigureAwait(false); Debug.Assert(response != null); var results = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, browseDescriptions); if (results.ErrorInfo == null && results.Count > 0) { children = results[0].Result.References.Count != 0; if (results[0].Result.ContinuationPoint != null) { await session.Services.BrowseNextAsync(header.ToRequestHeader(_timeProvider), true, [ response.Results[0].ContinuationPoint ], ct: ct).ConfigureAwait(false); } } } catch (Exception ex) when (ex is not OperationCanceledException) { _logger.BrowseStreamChildInfoFailed(ex); } } var (model, _) = await session.ReadNodeAsync(header.ToRequestHeader(_timeProvider), nodeId, reference.NodeClass, !readValues, rawMode, header.GetNamespaceFormat(_options), children, ct).ConfigureAwait(false); if (rawMode) { model = model with { BrowseName = header.AsString(reference.BrowseName, session.MessageContext, _options), DisplayName = reference.DisplayName?.ToString() }; } model = model with { TypeDefinitionId = header.AsString(reference.TypeDefinition, session.MessageContext, _options) }; if (targetNodesOnly) { result.Add(new NodeReferenceModel { Target = model }); continue; } result.Add(new NodeReferenceModel { ReferenceTypeId = header.AsString(reference.ReferenceTypeId, session.MessageContext, _options), Direction = reference.IsForward ? BrowseDirection.Forward : BrowseDirection.Backward, Target = model }); } catch { // TODO: Add trace result for trace. } } return continuationPoint?.ToBase64String(); } /// /// Add targets /// /// /// /// /// /// /// /// /// /// private async Task AddTargetsToBrowseResultAsync(IOpcUaSession session, RequestHeaderModel? header, bool readValues, bool rawMode, List result, BrowsePathTargetCollection targets, string[] path, CancellationToken ct) { if (targets != null) { foreach (var target in targets) { try { var nodeId = target.TargetId.ToNodeId(session.MessageContext.NamespaceUris); var (model, _) = await session.ReadNodeAsync(header.ToRequestHeader(_timeProvider), nodeId, null, !readValues, rawMode, header.GetNamespaceFormat(_options), false, ct).ConfigureAwait(false); result.Add(new NodePathTargetModel { BrowsePath = path, Target = model, RemainingPathIndex = target.RemainingPathIndex == 0 ? null : (int)target.RemainingPathIndex }); } catch { // Skip node - TODO: Should we add a failure // reference into the yet unused trace instead? continue; } } } } /// /// Reads the first or last date of the archive /// (truncates milliseconds). /// /// /// /// /// /// /// /// private static async Task HistoryReadTimestampAsync( IOpcUaSession session, RequestHeaderModel? header, NodeId nodeId, bool first, TimeProvider timeProvider, CancellationToken ct) { // do it the hard way (may take a long time with some servers). var nodesToRead = new HistoryReadValueIdCollection { new HistoryReadValueId { NodeId = nodeId } }; var details = new ExtensionObject(new ReadRawModifiedDetails { StartTime = first ? new DateTime(1970, 1, 1) : DateTime.MinValue, EndTime = first ? DateTime.MinValue : timeProvider.GetUtcNow().AddDays(1).UtcDateTime, NumValuesPerNode = 1, IsReadModified = false, ReturnBounds = false }); var response = await session.Services.HistoryReadAsync(header.ToRequestHeader(timeProvider), details, Opc.Ua.TimestampsToReturn.Source, false, nodesToRead, ct).ConfigureAwait(false); var results = response.Validate(response.Results, s => s.StatusCode, response.DiagnosticInfos, nodesToRead); try { if (StatusCode.IsBad(results.StatusCode) || StatusCode.IsBad(results[0].StatusCode) || ExtensionObject.ToEncodeable(results[0].Result.HistoryData) is not HistoryData historyData) { return null; } var date = historyData.DataValues[0].SourceTimestamp; date = new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, 0, DateTimeKind.Utc); return !first ? date.AddSeconds(1) : date; } finally { // Abort read if needed if (results[0].Result.ContinuationPoint?.Length > 0) { nodesToRead = [ new HistoryReadValueId { NodeId = nodeId, ContinuationPoint = results[0].Result.ContinuationPoint } ]; await session.Services.HistoryReadAsync(header.ToRequestHeader(timeProvider), details, Opc.Ua.TimestampsToReturn.Source, true, nodesToRead, ct).ConfigureAwait(false); } } } /// /// Browse stream helper class /// internal sealed class BrowseStream : AsyncEnumerableEnumerableStack { /// /// Create browse stream helper /// /// /// /// /// /// /// public BrowseStream(BrowseStreamRequestModel request, IOptions options, ActivitySource activitySource, ILogger logger, TimeProvider timeProvider, CancellationToken ct) { _activitySource = activitySource; _sw = Stopwatch.StartNew(); _logger = logger; _timeProvider = timeProvider; _options = options; _ct = ct; _request = request; } /// public override void Reset() { base.Reset(); Push(ReadNodeAsync); } /// /// Read node /// /// /// private async ValueTask> ReadNodeAsync( ServiceCallContext context) { using var trace = _activitySource.StartActivity("ReadNode"); // Lazy initialize to capture session context if (_nodeIds == null) { // Initialize _nodeIds = _request.NodeIds == null ? [] : _request.NodeIds .Select(n => n.ToNodeId(context.Session.MessageContext)) .Where(n => !NodeId.IsNull(n)) .ToArray(); if (_nodeIds.Length == 0) { _browseStack.Push(ObjectIds.RootFolder); } else { foreach (var resolvedId in _nodeIds) { _browseStack.Push(resolvedId); } } } BrowseStreamChunkModel? chunk = null; var nodeId = PopNode(); if (nodeId == null) { // Done - no more nodes on the browse stack to browse _logger.BrowseStreamSummary(_nodes, _references, _sw.Elapsed); return []; } var (node, errorInfo) = await context.Session.ReadNodeAsync( _request.Header.ToRequestHeader(_timeProvider), nodeId, _request.Header.GetNamespaceFormat(_options), null, !(_request.ReadVariableValues ?? false), null, _ct).ConfigureAwait(false); _visited.Add(nodeId); // Mark as visited var id = _request.Header.AsString(nodeId, context.Session.MessageContext, _options); if (id == null) { return []; } chunk = new BrowseStreamChunkModel { SourceId = id, Attributes = node, Reference = null, ErrorInfo = errorInfo }; _nodes++; // Browse the node now Push(context => BrowseAsync(context, id, nodeId)); // Read another node from the browse stack Push(ReadNodeAsync); return chunk.YieldReturn(); } /// /// Browse references /// /// /// /// /// private async ValueTask> BrowseAsync( ServiceCallContext context, string sourceId, NodeId nodeId) { using var trace = _activitySource.StartActivity("Browse"); if (_typeId == null) { _typeId = _request.ReferenceTypeId.ToNodeId(context.Session.MessageContext); if (NodeId.IsNull(_typeId)) { _typeId = ReferenceTypeIds.HierarchicalReferences; } } _view ??= _request.View.ToStackModel(context.Session.MessageContext); var browseDescriptions = new BrowseDescriptionCollection { new BrowseDescription { BrowseDirection = (_request.Direction ?? BrowseDirection.Both) .ToStackType(), IncludeSubtypes = !(_request.NoSubtypes ?? false), NodeClassMask = (uint)_request.NodeClassFilter.ToStackMask(), NodeId = nodeId, ReferenceTypeId = _typeId, ResultMask = (uint)BrowseResultMask.All } }; // Browse and read children var response = await context.Session.Services.BrowseAsync( _request.Header.ToRequestHeader(_timeProvider), ViewDescription.IsDefault(_view) ? null : _view, 0, browseDescriptions, _ct).ConfigureAwait(false); var results = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, browseDescriptions); if (results.ErrorInfo != null) { var chunk = new BrowseStreamChunkModel { SourceId = sourceId, ErrorInfo = results.ErrorInfo }; return chunk.YieldReturn(); } var refs = CollectReferences(context.Session, sourceId, results[0].Result.References, results[0].ErrorInfo, _request.NoRecurse ?? false); var continuation = results[0].Result.ContinuationPoint ?? []; if (continuation.Length > 0) { Push(context => BrowseNextAsync(context, sourceId, continuation)); } else { // Read another node from the browse stack Push(ReadNodeAsync); } return refs; } /// /// Browse remainder of references /// /// /// /// /// private async ValueTask> BrowseNextAsync( ServiceCallContext context, string sourceId, byte[] continuationPoint) { using var trace = _activitySource.StartActivity("BrowseNext"); var continuationPoints = new ByteStringCollection { continuationPoint }; var response = await context.Session.Services.BrowseNextAsync( _request.Header.ToRequestHeader(_timeProvider), false, continuationPoints, _ct).ConfigureAwait(false); var results = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, continuationPoints); if (results.ErrorInfo != null) { var chunk = new BrowseStreamChunkModel { SourceId = sourceId, ErrorInfo = results.ErrorInfo }; return chunk.YieldReturn(); } var refs = CollectReferences(context.Session, sourceId, results[0].Result.References, results[0].ErrorInfo, _request.NoRecurse ?? false); var continuation = results[0].Result.ContinuationPoint ?? []; if (continuation.Length > 0) { Push(session => BrowseNextAsync(session, sourceId, continuation)); } else { // Read another node from the browse stack Push(ReadNodeAsync); } return refs; } /// /// Helper to push nodes onto the browse stack /// /// private void PushNode(ExpandedNodeId nodeId) { if ((nodeId?.ServerIndex ?? 1u) != 0) { return; } var local = (NodeId)nodeId; if (!NodeId.IsNull(local) && !_visited.Contains(local)) { _browseStack.Push(local); } } /// /// Helper to pop nodes from the browse stack /// /// private NodeId? PopNode() { while (_browseStack.TryPop(out var nodeId)) { if (!NodeId.IsNull(nodeId) && !_visited.Contains(nodeId)) { return nodeId; } } return null; } /// /// Collect references /// /// /// /// /// /// /// private IEnumerable CollectReferences( IOpcUaSession session, string sourceId, ReferenceDescriptionCollection refs, ServiceResultModel? errorInfo, bool noRecurse) { foreach (var reference in refs) { if (!noRecurse) { PushNode(reference.NodeId); PushNode(reference.ReferenceTypeId); PushNode(reference.TypeDefinition); } _references++; var id = _request.Header.AsString(reference.NodeId, session.MessageContext, _options); if (id == null) { continue; } yield return new BrowseStreamChunkModel { SourceId = sourceId, ErrorInfo = errorInfo, Reference = new NodeReferenceModel { ReferenceTypeId = _request.Header.AsString(reference.ReferenceTypeId, session.MessageContext, _options), Direction = reference.IsForward ? BrowseDirection.Forward : BrowseDirection.Backward, Target = new NodeModel { NodeId = id, DisplayName = reference.DisplayName?.ToString(), TypeDefinitionId = _request.Header.AsString(reference.TypeDefinition, session.MessageContext, _options), BrowseName = _request.Header.AsString(reference.BrowseName, session.MessageContext, _options) } } }; } } private readonly Stack _browseStack = new(); private readonly HashSet _visited = []; private int _nodes; private int _references; private NodeId? _typeId; private NodeId[]? _nodeIds; private ViewDescription? _view; private readonly Stopwatch _sw; private readonly BrowseStreamRequestModel _request; private readonly ILogger _logger; private readonly TimeProvider _timeProvider; private readonly IOptions _options; private readonly CancellationToken _ct; private readonly ActivitySource _activitySource; } private readonly ActivitySource _activitySource = Diagnostics.NewActivitySource(); private readonly IOptions _options; private readonly TimeProvider _timeProvider; private readonly IFilterParser _parser; private readonly IOpcUaClientManager _client; private readonly ILogger _logger; } internal static partial class NodeServicesLogging { private const int EventClass = 220; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Debug, Message = "Browsed {Nodes} nodes and {References} references in address space in {Elapsed}...")] public static partial void BrowseStreamSummary(this ILogger logger, int Nodes, int References, TimeSpan Elapsed); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Information, Message = "Failed to obtain child information")] public static partial void BrowseStreamChildInfoFailed(this ILogger logger, Exception exception); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Services/PublishedNodesJsonServices.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Services { using Azure.IIoT.OpcUa.Publisher; using Azure.IIoT.OpcUa.Publisher.Config.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Storage; using Autofac; using Furly; using Furly.Exceptions; using Furly.Extensions.Serializers; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; /// /// Provides configuration services for publisher using either published nodes /// configuration update or api services. /// public sealed class PublishedNodesJsonServices : IPublishedNodesServices, IAwaitable, IAsyncDisposable, IDisposable { /// /// Create publisher configuration services /// /// /// /// /// /// /// /// public PublishedNodesJsonServices(PublishedNodesConverter publishedNodesJobConverter, IPublisher publisherHost, ILogger logger, IStorageProvider publishedNodesProvider, IJsonSerializer jsonSerializer, IDiagnosticCollector? diagnostics = null, TimeProvider? timeProvider = null) { _publishedNodesJobConverter = publishedNodesJobConverter; _logger = logger; _publishedNodesProvider = publishedNodesProvider; _jsonSerializer = jsonSerializer; _publisherHost = publisherHost; _timeProvider = timeProvider ?? TimeProvider.System; _diagnostics = diagnostics; // Optional _started = new TaskCompletionSource(); _fileChanges = Channel.CreateUnbounded(new UnboundedChannelOptions { SingleReader = true, SingleWriter = false }); _fileChangeProcessor = Task.Factory.StartNew(ProcessFileChangesAsync, default, TaskCreationOptions.LongRunning, TaskScheduler.Default).Unwrap(); _fileChanges.Writer.TryWrite(false); // Read from file } /// public async Task CreateOrUpdateDataSetWriterEntryAsync( PublishedNodesEntryModel entry, CancellationToken ct = default) { if (string.IsNullOrWhiteSpace(entry.EndpointUrl)) { throw new BadRequestException(kNullOrEmptyEndpointUrl); } entry.DataSetWriterGroup ??= string.Empty; entry.DataSetWriterId ??= string.Empty; if (entry.OpcNodes != null) { entry.OpcNodes = ValidateNodes(entry.OpcNodes, true); } await _api.WaitAsync(ct).ConfigureAwait(false); try { var currentNodes = GetCurrentPublishedNodes().ToList(); var newNodes = currentNodes .Where(e => !((e.DataSetWriterGroup ?? string.Empty) == entry.DataSetWriterGroup && (e.DataSetWriterId ?? string.Empty) == entry.DataSetWriterId)) .ToList(); if (newNodes.Count >= currentNodes.Count - 1) { newNodes.Add(entry); } else { throw new ResourceInvalidStateException( kAmbiguousResultsMessage); } var jobs = _publishedNodesJobConverter.ToWriterGroups(newNodes); await _publisherHost.UpdateAsync(jobs).ConfigureAwait(false); await PersistPublishedNodesAsync().ConfigureAwait(false); } finally { _api.Release(); } } /// public async Task GetDataSetWriterEntryAsync( string writerGroupId, string dataSetWriterId, CancellationToken ct = default) { await _api.WaitAsync(ct).ConfigureAwait(false); try { return Find(writerGroupId, dataSetWriterId, GetCurrentPublishedNodes()) with { OpcNodes = null }; } finally { _api.Release(); } } /// public async Task AddOrUpdateNodesAsync(string writerGroupId, string dataSetWriterId, IReadOnlyList nodes, string? insertAfterFieldId = null, CancellationToken ct = default) { var opcNodes = ValidateNodes([.. nodes], true); await _api.WaitAsync(ct).ConfigureAwait(false); try { var currentNodes = GetCurrentPublishedNodes().ToList(); var entry = Find(writerGroupId, dataSetWriterId, currentNodes); entry.OpcNodes ??= []; var insertAt = -1; if (insertAfterFieldId != null) { var offset = entry.OpcNodes .FirstOrDefault(n => n.DataSetFieldId == insertAfterFieldId); if (offset == null) { throw new ResourceNotFoundException( "Field to insert after not found."); } insertAt = entry.OpcNodes.IndexOf(offset); if (++insertAt == entry.OpcNodes.Count) { insertAt = -1; } } foreach (var node in opcNodes) { var existing = entry.OpcNodes .FirstOrDefault(n => n.DataSetFieldId == node.DataSetFieldId); if (existing != null) { // Replace existing var index = entry.OpcNodes.IndexOf(existing); entry.OpcNodes[index] = node; } else if (insertAt != -1) { // Insert after entry.OpcNodes.Insert(insertAt++, node); } else { // at end entry.OpcNodes.Add(node); } } var jobs = _publishedNodesJobConverter.ToWriterGroups(currentNodes); await _publisherHost.UpdateAsync(jobs).ConfigureAwait(false); await PersistPublishedNodesAsync().ConfigureAwait(false); } finally { _api.Release(); } } /// public async Task RemoveNodesAsync(string writerGroupId, string dataSetWriterId, IReadOnlyList dataSetFieldIds, CancellationToken ct = default) { if (dataSetFieldIds.Count == 0) { throw new BadRequestException("Field ids must be specified."); } var set = dataSetFieldIds.ToHashSet(); if (set.Count != dataSetFieldIds.Count) { throw new BadRequestException("Field ids must be unique."); } await _api.WaitAsync(ct).ConfigureAwait(false); try { var currentNodes = GetCurrentPublishedNodes().ToList(); var entry = Find(writerGroupId, dataSetWriterId, currentNodes); if (entry.OpcNodes == null || entry.OpcNodes.Count == 0) { throw new ResourceNotFoundException("No nodes in dataset."); } var newNodes = entry.OpcNodes .Where(n => !set.Contains(n.DataSetFieldId ?? string.Empty)) .ToList(); if (newNodes.Count == entry.OpcNodes.Count) { throw new ResourceNotFoundException( $"Specified {(dataSetFieldIds.Count == 1 ? "node" : "nodes")} " + "not found in dataset"); } entry.OpcNodes = newNodes; var jobs = _publishedNodesJobConverter.ToWriterGroups(currentNodes); await _publisherHost.UpdateAsync(jobs).ConfigureAwait(false); await PersistPublishedNodesAsync().ConfigureAwait(false); } finally { _api.Release(); } } /// public async Task GetNodeAsync(string writerGroupId, string dataSetWriterId, string dataSetFieldId, CancellationToken ct = default) { await _api.WaitAsync(ct).ConfigureAwait(false); try { var currentNodes = GetCurrentPublishedNodes().ToList(); var entry = Find(writerGroupId, dataSetWriterId, currentNodes); var node = entry.OpcNodes?.FirstOrDefault(n => n.DataSetFieldId == dataSetFieldId); if (node == null) { throw new ResourceNotFoundException( $"Node with id {dataSetFieldId.ReplaceLineEndings()} not found."); } return node; } finally { _api.Release(); } } /// public async Task> GetNodesAsync(string writerGroupId, string dataSetWriterId, string? dataSetFieldId = null, int? count = null, CancellationToken ct = default) { await _api.WaitAsync(ct).ConfigureAwait(false); try { var currentNodes = GetCurrentPublishedNodes().ToList(); var entry = Find(writerGroupId, dataSetWriterId, currentNodes); if (entry.OpcNodes == null) { return Array.Empty(); } IEnumerable result = entry.OpcNodes; if (dataSetFieldId != null) { result = result .SkipWhile(n => dataSetFieldId != n.DataSetFieldId) .Skip(1); // Skip the found one and get the one after } if (count != null) { result = result.Take(count.Value); } return result.ToList(); } finally { _api.Release(); } } /// public async Task RemoveDataSetWriterEntryAsync(string writerGroupId, string dataSetWriterId, bool force = false, CancellationToken ct = default) { await _api.WaitAsync(ct).ConfigureAwait(false); try { var currentNodes = GetCurrentPublishedNodes().ToList(); if (!force) { var remove = Find(writerGroupId, dataSetWriterId, currentNodes); currentNodes.Remove(remove); } else { currentNodes.RemoveAll(e => (e.DataSetWriterGroup ?? string.Empty) == writerGroupId && (e.DataSetWriterId ?? string.Empty) == dataSetWriterId); } var jobs = _publishedNodesJobConverter.ToWriterGroups(currentNodes); await _publisherHost.UpdateAsync(jobs).ConfigureAwait(false); await PersistPublishedNodesAsync().ConfigureAwait(false); } finally { _api.Release(); } } /// public async Task PublishStartAsync(ConnectionModel endpoint, PublishStartRequestModel request, CancellationToken ct = default) { if (request.Item?.NodeId is null) { throw new BadRequestException(kNullOrEmptyOpcNodesMessage); } await _api.WaitAsync(ct).ConfigureAwait(false); try { var entry = endpoint.ToPublishedNodesEntry(); var currentNodes = GetCurrentPublishedNodes().ToList(); AddItem(currentNodes, entry, request.Item); var jobs = _publishedNodesJobConverter.ToWriterGroups(currentNodes); await _publisherHost.UpdateAsync(jobs).ConfigureAwait(false); await PersistPublishedNodesAsync().ConfigureAwait(false); return new PublishStartResponseModel(); } finally { _api.Release(); } } /// public async Task PublishStopAsync(ConnectionModel endpoint, PublishStopRequestModel request, CancellationToken ct = default) { if (request.NodeId is null) { throw new BadRequestException(kNullOrEmptyOpcNodesMessage); } await _api.WaitAsync(ct).ConfigureAwait(false); try { var currentNodes = GetCurrentPublishedNodes().ToList(); var entry = endpoint.ToPublishedNodesEntry(); foreach (var nodeset in currentNodes.Where(n => n.HasSameDataSet(entry))) { nodeset.OpcNodes = nodeset.OpcNodes?.Where(n => n.Id != request.NodeId).ToList(); } var jobs = _publishedNodesJobConverter.ToWriterGroups(currentNodes); await _publisherHost.UpdateAsync(jobs).ConfigureAwait(false); await PersistPublishedNodesAsync().ConfigureAwait(false); return new PublishStopResponseModel(); } finally { _api.Release(); } } /// public async Task PublishBulkAsync(ConnectionModel endpoint, PublishBulkRequestModel request, CancellationToken ct = default) { if (request.NodesToAdd is null && request.NodesToRemove is null) { throw new BadRequestException(kNullOrEmptyOpcNodesMessage); } if ((request.NodesToRemove?.Any(n => n == null) ?? false) || (request.NodesToAdd?.Any(n => n.NodeId == null) ?? false)) { throw new BadRequestException(kNullOrEmptyOpcNodesMessage); } await _api.WaitAsync(ct).ConfigureAwait(false); try { var currentNodes = GetCurrentPublishedNodes().ToList(); var entry = endpoint.ToPublishedNodesEntry(); // Remove all nodes if (request.NodesToRemove != null) { foreach (var nodeset in currentNodes.Where(n => n.HasSameDataSet(entry))) { nodeset.OpcNodes = nodeset.OpcNodes? .Where(n => !request.NodesToRemove.Contains(n.Id!)) .ToList(); } } if (request.NodesToAdd != null) { foreach (var item in request.NodesToAdd) { AddItem(currentNodes, entry, item); } } var jobs = _publishedNodesJobConverter.ToWriterGroups(currentNodes); await _publisherHost.UpdateAsync(jobs).ConfigureAwait(false); await PersistPublishedNodesAsync().ConfigureAwait(false); return new PublishBulkResponseModel(); } finally { _api.Release(); } } /// public async Task PublishListAsync(ConnectionModel endpoint, PublishedItemListRequestModel request, CancellationToken ct = default) { await _api.WaitAsync(ct).ConfigureAwait(false); try { var entry = endpoint.ToPublishedNodesEntry(); var entries = GetCurrentPublishedNodes().ToList(); return new PublishedItemListResponseModel { Items = entries .Where(n => n.HasSameDataSet(entry)) .SelectMany(n => n.OpcNodes ?? []) .Where(n => n.EventFilter == null) // Exclude event filtering .Select(n => new PublishedItemModel { NodeId = n.Id ?? string.Empty, DisplayName = n.DisplayName, HeartbeatInterval = n.HeartbeatIntervalTimespan, PublishingInterval = n.OpcPublishingIntervalTimespan, SamplingInterval = n.OpcSamplingIntervalTimespan }) .ToList() }; } finally { _api.Release(); } } /// public async Task PublishNodesAsync(PublishedNodesEntryModel request, CancellationToken ct = default) { if (request.OpcNodes is null || request.OpcNodes.Count == 0) { throw new BadRequestException(kNullOrEmptyOpcNodesMessage); } if (string.IsNullOrWhiteSpace(request.EndpointUrl)) { throw new BadRequestException(kNullOrEmptyEndpointUrl); } request.OpcNodes = ValidateNodes(request.OpcNodes, false); request.PropagatePublishingIntervalToNodes(); await _api.WaitAsync(ct).ConfigureAwait(false); try { var dataSetFound = false; var existingGroups = new List(); foreach (var entry in GetCurrentPublishedNodes()) { if (entry.HasSameWriterGroup(request)) { // We may have several entries with the same DataSetGroup definition, // so we will add nodes only if the whole DataSet definition matches. if (entry.HasSameDataSet(request)) { // Create HashSet of nodes for this entry. var existingNodesSet = new HashSet(OpcNodeModelEx.Comparer); entry.OpcNodes ??= []; existingNodesSet.UnionWith(entry.OpcNodes); foreach (var nodeToAdd in request.OpcNodes) { if (!existingNodesSet.Contains(nodeToAdd)) { entry.OpcNodes.Add(nodeToAdd); existingNodesSet.Add(nodeToAdd); } else { _logger.NodeAlreadyPresent(nodeToAdd.Id, entry.EndpointUrl); } } dataSetFound = true; } existingGroups.Add(entry); } } if (!dataSetFound) { existingGroups.Add(request); } var jobs = _publishedNodesJobConverter.ToWriterGroups(existingGroups); await _publisherHost.UpdateAsync(jobs).ConfigureAwait(false); await PersistPublishedNodesAsync().ConfigureAwait(false); } finally { _api.Release(); } } /// public async Task UnpublishNodesAsync(PublishedNodesEntryModel request, CancellationToken ct = default) { // // When no node is specified then remove the whole data set. // This behavior ensures backwards compatibility with UnpublishNodes // direct method of OPC Publisher 2.5.x. // request.PropagatePublishingIntervalToNodes(); var purgeDataSet = request.OpcNodes is null || request.OpcNodes.Count == 0; await _api.WaitAsync(ct).ConfigureAwait(false); try { // Create HashSet of nodes to remove. var nodesToRemoveSet = new HashSet(OpcNodeModelEx.Comparer); if (!purgeDataSet && request.OpcNodes != null) { nodesToRemoveSet.UnionWith(request.OpcNodes); } var currentNodes = GetCurrentPublishedNodes().ToList(); // Perform first pass to determine if we can find all nodes to remove. var matchingGroups = new List(); foreach (var entry in currentNodes) { // We may have several entries with the same DataSetGroup definition, // so we will remove nodes only if the whole DataSet definition matches. if (entry.HasSameDataSet(request)) { if (entry.OpcNodes != null) { foreach (var node in entry.OpcNodes) { nodesToRemoveSet.Remove(node); } } matchingGroups.Add(entry); } } // Report error if no matching endpoint was found. if (matchingGroups.Count == 0) { throw new ResourceNotFoundException($"Endpoint not found: {request.EndpointUrl}"); } // Report error if there were entries that we were not able to find. if (nodesToRemoveSet.Count != 0) { request.OpcNodes = [.. nodesToRemoveSet]; var entriesNotFoundJson = _jsonSerializer.SerializeToString(request); throw new ResourceNotFoundException($"Nodes not found: \n{entriesNotFoundJson}"); } // Create HashSet of nodes to remove again for the second pass. nodesToRemoveSet.Clear(); if (!purgeDataSet && request.OpcNodes != null) { nodesToRemoveSet.UnionWith(request.OpcNodes); } // Perform second pass and remove entries this time. var remainingEntries = new List(); foreach (var entry in currentNodes) { // We may have several entries with the same DataSetGroup definition, // so we will remove nodes only if the whole DataSet definition matches. if (entry.HasSameDataSet(request)) { if (purgeDataSet) { continue; } var updatedNodes = new List(); if (entry.OpcNodes != null) { foreach (var node in entry.OpcNodes) { if (!nodesToRemoveSet.Remove(node)) { updatedNodes.Add(node); } } } if (updatedNodes.Count == 0) { continue; } // Fall through to add to remaining entries entry.OpcNodes = updatedNodes; } // Even if DataSets did not match, we need to add this entry to existingGroups // so that generated job definition is complete. remainingEntries.Add(entry); } var jobs = _publishedNodesJobConverter.ToWriterGroups(remainingEntries); await _publisherHost.UpdateAsync(jobs).ConfigureAwait(false); await PersistPublishedNodesAsync().ConfigureAwait(false); } finally { _api.Release(); } } /// public async Task UnpublishAllNodesAsync(PublishedNodesEntryModel? request, CancellationToken ct = default) { // // when no endpoint is specified remove all the configuration // purge content feature is implemented to ensure the backwards compatibility // with V2.5.x of the publisher // var purge = request?.EndpointUrl == null; request?.PropagatePublishingIntervalToNodes(); await _api.WaitAsync(ct).ConfigureAwait(false); try { if (!purge) { Debug.Assert(request != null); var found = false; // Perform pass to determine existing groups var remainingEntries = new List(); foreach (var entry in GetCurrentPublishedNodes()) { if (entry.HasSameWriterGroup(request)) { // We may have several entries with the same DataSetGroup definition, // so we will remove nodes only if the whole DataSet definition matches. if (entry.HasSameDataSet(request)) { found = true; continue; } remainingEntries.Add(entry); } } // Report error if there were entries that did not have any nodes if (!found) { throw new ResourceNotFoundException($"Endpoint or node not found: {request.EndpointUrl}"); } var jobs = _publishedNodesJobConverter.ToWriterGroups(remainingEntries); await _publisherHost.UpdateAsync(jobs).ConfigureAwait(false); } else { await _publisherHost.UpdateAsync([]).ConfigureAwait(false); } await PersistPublishedNodesAsync().ConfigureAwait(false); } finally { _api.Release(); } } /// public async Task SetConfiguredEndpointsAsync(IReadOnlyList request, CancellationToken ct = default) { foreach (var entry in request) { if (entry.OpcNodes != null) { entry.OpcNodes = ValidateNodes(entry.OpcNodes, false); } } await _api.WaitAsync(ct).ConfigureAwait(false); try { var jobs = _publishedNodesJobConverter.ToWriterGroups(request); await _publisherHost.UpdateAsync(jobs).ConfigureAwait(false); await PersistPublishedNodesAsync().ConfigureAwait(false); } finally { _api.Release(); } } /// public async Task AddOrUpdateEndpointsAsync(IReadOnlyList request, CancellationToken ct = default) { // First, let's check that there are no 2 entries for the same endpoint in the request. if (request.Count > 0) { request[0].PropagatePublishingIntervalToNodes(); for (var itemIndex = 1; itemIndex < request.Count; itemIndex++) { for (var prevItemIndex = 0; prevItemIndex < itemIndex; prevItemIndex++) { request[itemIndex].PropagatePublishingIntervalToNodes(); if (request[itemIndex].HasSameDataSet(request[prevItemIndex])) { throw new BadRequestException( "Request contains two entries for the same endpoint " + $"at index {prevItemIndex} and {itemIndex}"); } } } } await _api.WaitAsync(ct).ConfigureAwait(false); try { var currentNodes = GetCurrentPublishedNodes().ToHashSet(); // Check that endpoints that we are asked to remove exist. foreach (var removeRequest in request.Where(e => (e.OpcNodes?.Count ?? 0) == 0)) { var removed = currentNodes.RemoveWhere(entry => entry.HasSameDataSet(removeRequest)); if (removed == 0) { throw new ResourceNotFoundException($"Endpoint not found: {removeRequest.EndpointUrl}"); } } foreach (var updateRequest in request.Where(e => e.OpcNodes?.Count > 0)) { ValidateNodes(updateRequest.OpcNodes!, false); // We will add the update request entry and clean up anything else matching. var found = currentNodes.FirstOrDefault(entry => entry.HasSameDataSet(updateRequest)); if (found != null) { currentNodes.RemoveWhere(entry => entry.HasSameDataSet(updateRequest)); found.OpcNodes = updateRequest.OpcNodes; currentNodes.Add(found); } else { // Nothing matching add here currentNodes.Add(updateRequest); } } var jobs = _publishedNodesJobConverter.ToWriterGroups(currentNodes); await _publisherHost.UpdateAsync(jobs).ConfigureAwait(false); await PersistPublishedNodesAsync().ConfigureAwait(false); } finally { _api.Release(); } } /// public async Task> GetConfiguredEndpointsAsync( bool includeNodes = false, CancellationToken ct = default) { await _api.WaitAsync(ct).ConfigureAwait(false); try { var endpoints = GetCurrentPublishedNodes(); if (!includeNodes) { endpoints = endpoints.Select(e => e.ToDataSetEntry()); } return endpoints.ToList(); } finally { _api.Release(); } } /// public async Task> GetConfiguredNodesOnEndpointAsync( PublishedNodesEntryModel request, CancellationToken ct = default) { if (string.IsNullOrWhiteSpace(request.EndpointUrl)) { throw new BadRequestException(kNullOrEmptyEndpointUrl); } request.PropagatePublishingIntervalToNodes(); var response = new List(); await _api.WaitAsync(ct).ConfigureAwait(false); try { var endpointFound = false; foreach (var entry in GetCurrentPublishedNodes()) { if (entry.HasSameDataSet(request)) { endpointFound = true; if (entry.OpcNodes != null) { response.AddRange(entry.OpcNodes); } } } if (!endpointFound) { throw new ResourceNotFoundException( $"Endpoint not found: {request.EndpointUrl}"); } } finally { _api.Release(); } return response; } /// public async Task> GetDiagnosticInfoAsync( CancellationToken ct = default) { await _api.WaitAsync(ct).ConfigureAwait(false); try { var result = new List(); if (_diagnostics == null) { // ChannelDiagnostics disabled throw new ResourceInvalidStateException("Diagnostics service is disabled."); } foreach (var nodes in GetCurrentPublishedNodes().GroupBy(k => k.GetUniqueWriterGroupId())) { if (!_diagnostics.TryGetDiagnosticsForWriterGroup(nodes.Key, out var model)) { continue; } result.Add(new PublishDiagnosticInfoModel { Endpoints = nodes.ToList(), SentMessagesPerSec = model.SentMessagesPerSec, IngestionDuration = _timeProvider.GetUtcNow() - model.IngestionStart, IngressDataChanges = model.IngressDataChanges, IngressValueChanges = model.IngressValueChanges, IngressBatchBlockBufferSize = model.IngressBatchBlockBufferSize, EncodingBlockInputSize = model.EncodingBlockInputSize, EncodingBlockOutputSize = model.EncodingBlockOutputSize, EncoderNotificationsProcessed = model.EncoderNotificationsProcessed, EncoderNotificationsDropped = model.EncoderNotificationsDropped, EncoderMaxMessageSplitRatio = model.EncoderMaxMessageSplitRatio, EncoderIoTMessagesProcessed = model.EncoderIoTMessagesProcessed, EncoderAvgNotificationsMessage = model.EncoderAvgNotificationsMessage, EncoderAvgIoTMessageBodySize = model.EncoderAvgIoTMessageBodySize, EncoderAvgIoTChunkUsage = model.EncoderAvgIoTChunkUsage, EstimatedIoTChunksPerDay = model.EstimatedIoTChunksPerDay, OutgressInputBufferCount = model.OutgressInputBufferCount, OutgressInputBufferDropped = model.OutgressInputBufferDropped, OutgressIoTMessageCount = model.OutgressIoTMessageCount, ConnectionRetries = model.ConnectionRetries, OpcEndpointConnected = model.OpcEndpointConnected, MonitoredOpcNodesSucceededCount = model.MonitoredOpcNodesSucceededCount, MonitoredOpcNodesFailedCount = model.MonitoredOpcNodesFailedCount, IngressEventNotifications = model.IngressEventNotifications, IngressCyclicReads = model.IngressCyclicReads, IngressHeartbeats = model.IngressHeartbeats, IngressDataChangesInLastMinute = model.IngressDataChangesInLastMinute, IngressValueChangesInLastMinute = model.IngressValueChangesInLastMinute, IngressEvents = model.IngressEvents }); } return result; } finally { _api.Release(); } } /// /// Persist Published nodes to published nodes file. /// private async Task PersistPublishedNodesAsync() { await _file.WaitAsync().ConfigureAwait(false); try { var currentNodes = GetCurrentPublishedNodes(preferTimespan: false); var updatedContent = _jsonSerializer.SerializeToString( currentNodes, SerializeOption.Indented) ?? string.Empty; _publishedNodesProvider.WriteContent(updatedContent, true); // Update _lastKnownFileHash _lastKnownFileHash = GetChecksum(updatedContent); } finally { _file.Release(); } } /// /// Get current published nodes from publisher /// /// /// private IEnumerable GetCurrentPublishedNodes( bool preferTimespan = true) { return _publishedNodesJobConverter .ToPublishedNodes(_publisherHost.Version, _publisherHost.LastChange, _publisherHost.WriterGroups, preferTimespan) .Select(p => p.PropagatePublishingIntervalToNodes()); } /// public IAwaiter GetAwaiter() { return (_started?.Task ?? Task.CompletedTask).AsAwaiter(this); } /// public async ValueTask DisposeAsync() { try { _fileChanges.Writer.TryComplete(); if (_started != null) { await _fileChangeProcessor.ConfigureAwait(false); } } catch (ObjectDisposedException) { } catch (OperationCanceledException) { } finally { _started = null; } } /// public void Dispose() { try { _fileChanges.Writer.TryComplete(); DisposeAsync().AsTask().GetAwaiter().GetResult(); } finally { _api.Dispose(); _file.Dispose(); } } /// /// Handle file changes /// /// /// private void OnChanged(object? sender, FileSystemEventArgs e) { _logger.FileChanged(e.ChangeType, e.Name); _fileChanges.Writer.TryWrite(e.ChangeType == WatcherChangeTypes.Deleted); } /// /// Refresh processor /// /// private async Task ProcessFileChangesAsync() { try { _publishedNodesProvider.Changed += OnChanged; var retryCount = 0; await foreach (var clear in _fileChanges.Reader.ReadAllAsync().ConfigureAwait(false)) { await _file.WaitAsync().ConfigureAwait(false); try { var lastWriteTime = _publishedNodesProvider.GetLastWriteTime(); try { // Force empty content when clearing but dont touch the deleted file var content = clear ? string.Empty : _publishedNodesProvider.ReadContent(); var lastValidFileHash = _lastKnownFileHash; var currentFileHash = GetChecksum(content); if (currentFileHash != _lastKnownFileHash) { var jobs = Enumerable.Empty(); if (!string.IsNullOrEmpty(content)) { if (string.IsNullOrEmpty(_lastKnownFileHash)) { _logger.FoundPublishedNodesFile(currentFileHash); } else { _logger.PublishedNodesFileChanged(_lastKnownFileHash, currentFileHash); } var entries = _publishedNodesJobConverter.Read(content).ToList(); TransformFromLegacyNodeId(entries); jobs = _publishedNodesJobConverter.ToWriterGroups(entries); } _logger.PublisherConfigurationCompleted(clear ? "Resetting" : "Refreshing"); try { await _publisherHost.UpdateAsync(jobs).ConfigureAwait(false); _lastKnownFileHash = currentFileHash; // Mark as started _started?.TrySetResult(); } catch (Exception ex) when (_started?.Task.IsCompletedSuccessfully ?? false) { if (_publisherHost.TryUpdate(jobs)) { _logger.NotInitializingUpdateWithoutWaiting(ex); _lastKnownFileHash = currentFileHash; } } // Otherwise throw and retry } else { // avoid double events from FileSystemWatcher if (lastWriteTime - _lastRead > TimeSpan.FromMilliseconds(10)) { _logger.PublishedNodesFileChangedContentHashEqual(); } } _lastRead = lastWriteTime; retryCount = 0; // Success } catch (IOException ex) { if (++retryCount <= 3) { Debug.Assert(!clear); _logger.ErrorLoadingJobFromFileAttempt(ex, retryCount); // Queue another one and wait a bit _fileChanges.Writer.TryWrite(false); await Task.Delay(500).ConfigureAwait(false); continue; } _logger.ErrorLoadingJobFromFileRetryExpired(ex); } catch (SerializerException sx) { Debug.Assert(!clear); const string error = "SerializerException while loading job from file."; if (_logger.IsEnabled(LogLevel.Debug)) { _logger.ErrorLoadingJobFromFileSerializer(sx, error); } else { _logger.ErrorLoadingJobFromFileSerializer(error); } retryCount = 0; _started?.TrySetResult(); } catch (Exception ex) when (ex is not ObjectDisposedException) { _logger.ErrorDuringPublisherAction(ex, clear ? "Reset" : "Update"); _fileChanges.Writer.TryWrite(clear); retryCount = 0; _started?.TrySetResult(); } } finally { _file.Release(); } } } finally { _publishedNodesProvider.Changed -= OnChanged; _started = null; } } /// /// Find writer entry /// /// /// /// /// /// /// /// private static PublishedNodesEntryModel Find(string writerGroupId, string dataSetWriterId, IEnumerable entries) { var found = entries .Where(e => (e.DataSetWriterGroup ?? string.Empty) == writerGroupId && (e.DataSetWriterId ?? string.Empty) == dataSetWriterId) .ToList(); if (found.Count == 1) { return EnsureUniqueDataSetFieldIds(found[0]); } else if (found.Count == 0) { throw new ResourceNotFoundException("Could not find entry " + "with provided writer id and writer group."); } else { throw new ResourceInvalidStateException(kAmbiguousResultsMessage); } static PublishedNodesEntryModel EnsureUniqueDataSetFieldIds( PublishedNodesEntryModel entry) { if (entry.OpcNodes != null) { var unique = entry.OpcNodes .Select(n => n.DataSetFieldId) .Distinct() .Count(); if (unique != entry.OpcNodes.Count) { throw new BadRequestException( "Field ids in writer entry must be present and unique."); } } return entry; } } /// /// Validate nodes are valid /// /// /// /// /// private static IList ValidateNodes(IList opcNodes, bool dataSetWriterApiRequirements = false) { var set = new HashSet(); foreach (var node in opcNodes) { if (!node.TryGetId(out var id)) { throw new BadRequestException("Node must contain a node ID"); } if (dataSetWriterApiRequirements) { node.DataSetFieldId ??= id; set.Add(node.DataSetFieldId); if (node.OpcPublishingInterval != null || node.OpcPublishingIntervalTimespan != null) { throw new BadRequestException( "Publishing interval not allowed on node level. " + "Must be set at writer level."); } } } if (dataSetWriterApiRequirements && set.Count != opcNodes.Count) { throw new BadRequestException("Field ids must be present and unique."); } return opcNodes; } /// /// Add item to nodes /// /// /// /// private static void AddItem(List currentNodes, PublishedNodesEntryModel entry, PublishedItemModel item) { var found = currentNodes.Find(n => n.HasSameDataSet(entry)); if (found == null) { currentNodes.Add(entry); found = entry; } found.MessageEncoding = MessageEncoding.Json; found.MessagingMode = MessagingMode.FullSamples; found.OpcNodes ??= []; var node = found.OpcNodes.FirstOrDefault(n => n.Id == item.NodeId); if (node == null) { found.OpcNodes.Add(new OpcNodeModel { DisplayName = item.DisplayName, Id = item.NodeId, OpcSamplingIntervalTimespan = item.SamplingInterval, HeartbeatIntervalTimespan = item.HeartbeatInterval, OpcPublishingIntervalTimespan = item.PublishingInterval }); } else { node.DisplayName = item.DisplayName; node.OpcSamplingIntervalTimespan = item.SamplingInterval; node.HeartbeatIntervalTimespan = item.HeartbeatInterval; node.OpcPublishingIntervalTimespan = item.PublishingInterval; } } /// /// Transforms legacy entries that use NodeId into ones using OpcNodes. /// The transformation will happen in-place. /// /// /// private static void TransformFromLegacyNodeId(List entries) { if (entries == null) { return; } foreach (var entry in entries) { if (!string.IsNullOrEmpty(entry.NodeId?.Identifier)) { entry.OpcNodes ??= []; if (entry.OpcNodes.Count != 0) { throw new SerializerException( "Published nodes file contains DataSetWriter entry which " + $"defines both {nameof(entry.OpcNodes)} and {nameof(entry.NodeId)}." + "This is not supported. Please fix published nodes file."); } entry.OpcNodes.Add(new OpcNodeModel { Id = entry.NodeId.Identifier }); entry.NodeId = null; } } } /// /// Create a checksum of the content /// /// /// private static string GetChecksum(string content) { var checksum = SHA256.HashData(Encoding.UTF8.GetBytes(content)); return Convert.ToHexString(checksum); } private const string kNullOrEmptyEndpointUrl = "Missing endpoint url in entry"; private const string kNullOrEmptyOpcNodesMessage = "null or empty OpcNodes is provided in request"; private const string kAmbiguousResultsMessage = "Trying to find entry with provided writer id produced ambigious results."; private readonly ILogger _logger; private readonly TimeProvider _timeProvider; private readonly PublishedNodesConverter _publishedNodesJobConverter; private readonly IStorageProvider _publishedNodesProvider; private readonly IJsonSerializer _jsonSerializer; private readonly IDiagnosticCollector? _diagnostics; private readonly IPublisher _publisherHost; private string _lastKnownFileHash = string.Empty; private DateTime _lastRead = DateTime.MinValue; private TaskCompletionSource? _started; private readonly Task _fileChangeProcessor; private readonly Channel _fileChanges; private readonly SemaphoreSlim _api = new(1, 1); private readonly SemaphoreSlim _file = new(1, 1); } /// /// Source-generated logging extensions for PublishedNodesJsonServices /// internal static partial class PublishedNodesJsonServicesLogging { private const int EventClass = 230; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Debug, Message = "File {File} {Action}. Triggering file refresh ...")] public static partial void FileChanged(this ILogger logger, WatcherChangeTypes action, string? file); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Debug, Message = "Error while loading job from file. Attempt #{Count}...")] public static partial void ErrorLoadingJobFromFileAttempt(this ILogger logger, Exception ex, int count); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Error, Message = "Error while loading job from file. Retry expired, giving up.")] public static partial void ErrorLoadingJobFromFileRetryExpired(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Error, SkipEnabledCheck = true, Message = "{Error}")] public static partial void ErrorLoadingJobFromFileSerializer(this ILogger logger, Exception ex, string error); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Error, Message = "{Error}")] public static partial void ErrorLoadingJobFromFileSerializer(this ILogger logger, string error); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Error, Message = "Error during publisher {Action}. Retrying...")] public static partial void ErrorDuringPublisherAction(this ILogger logger, Exception ex, string action); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Debug, Message = "Node \"{Node}\" is already present for entry with \"{Endpoint}\" endpoint.")] public static partial void NodeAlreadyPresent(this ILogger logger, string? node, string? endpoint); [LoggerMessage(EventId = EventClass + 8, Level = LogLevel.Information, Message = "Found published Nodes File with hash {NewHash}, loading...")] public static partial void FoundPublishedNodesFile(this ILogger logger, string? newHash); [LoggerMessage(EventId = EventClass + 9, Level = LogLevel.Information, Message = "Published Nodes File changed, last known hash {LastHash}, new hash {NewHash}, reloading...")] public static partial void PublishedNodesFileChanged(this ILogger logger, string? lastHash, string? newHash); [LoggerMessage(EventId = EventClass + 10, Level = LogLevel.Information, Message = "{Action} publisher configuration completed.")] public static partial void PublisherConfigurationCompleted(this ILogger logger, string action); [LoggerMessage(EventId = EventClass + 11, Level = LogLevel.Debug, Message = "Not initializing, update without waiting.")] public static partial void NotInitializingUpdateWithoutWaiting(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 12, Level = LogLevel.Debug, Message = "Published Nodes File changed but content-hash is equal to last one, nothing to do...")] public static partial void PublishedNodesFileChangedContentHashEqual(this ILogger logger); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Services/PublisherDiagnosticCollector.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Services { using Azure.IIoT.OpcUa.Publisher; using Azure.IIoT.OpcUa.Publisher.Models; using Autofac; using Microsoft.Extensions.Logging; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Metrics; /// /// Collects metrics from the writer groups inside the publisher using the .net Meter listener /// API. This must be kept in sync with the values we aim to track. This class should be seen /// as optional, i.e., it is possible to disable any of the legacy diagnostics api and rely /// solely on modern OTEL based telemetry collection. /// public sealed class PublisherDiagnosticCollector : IDiagnosticCollector, IStartable, IDisposable { /// /// Create collector /// /// /// public PublisherDiagnosticCollector(ILogger logger, TimeProvider? timeProvider = null) { _logger = logger; _timeProvider = timeProvider ?? TimeProvider.System; _meterListener = new MeterListener { InstrumentPublished = OnInstrumentPublished }; _meterListener.SetMeasurementEventCallback(OnMeasurementRecorded); _meterListener.SetMeasurementEventCallback(OnMeasurementRecorded); _meterListener.SetMeasurementEventCallback(OnMeasurementRecorded); _meterListener.SetMeasurementEventCallback(OnMeasurementRecorded); _meterListener.SetMeasurementEventCallback(OnMeasurementRecorded); _meterListener.SetMeasurementEventCallback(OnMeasurementRecorded); _meterListener.SetMeasurementEventCallback(OnMeasurementRecorded); } /// public void ResetWriterGroup(string writerGroupId) { var diag = new WriterGroupDiagnosticModel { PublisherVersion = PublisherConfig.Version, IngestionStart = _timeProvider.GetUtcNow() }; _diagnostics.AddOrUpdate(writerGroupId, _ => diag, (_, _) => diag); _logger.TrackingDiagnosticsRestarted(writerGroupId); } /// public bool TryGetDiagnosticsForWriterGroup(string writerGroupId, [NotNullWhen(true)] out WriterGroupDiagnosticModel? diagnostic) { if (_diagnostics.TryGetValue(writerGroupId, out var value)) { // // Ensure we collect all observable instruments then // return the aggregate model // _meterListener.RecordObservableInstruments(); var duration = _timeProvider.GetUtcNow() - value.IngestionStart; diagnostic = value with { IngestionDuration = duration, OpcEndpointConnected = value.NumberOfConnectedEndpoints != 0, MemoryLimitUtilization = _process.MemoryLimitUtilization, CpuLimitUtilization = _process.CpuLimitUtilization, CpuRequestUtilization = _process.CpuRequestUtilization, CpuUsedPercentage = _process.CpuUsedPercentage, MemoryUsedPercentage = _process.MemoryUsedPercentage, MemoryUsedInBytes = _process.MemoryUsedInBytes }; return true; } diagnostic = default; return false; } /// public IEnumerable<(string, WriterGroupDiagnosticModel)> EnumerateDiagnostics() { var now = _timeProvider.GetUtcNow(); _meterListener.RecordObservableInstruments(); foreach (var (writerGroupId, info) in _diagnostics) { var duration = now - info.IngestionStart; yield return (writerGroupId, info with { Timestamp = now, IngestionDuration = duration, OpcEndpointConnected = info.NumberOfConnectedEndpoints != 0, MemoryLimitUtilization = _process.MemoryLimitUtilization, CpuLimitUtilization = _process.CpuLimitUtilization, CpuRequestUtilization = _process.CpuRequestUtilization, CpuUsedPercentage = _process.CpuUsedPercentage, MemoryUsedPercentage = _process.MemoryUsedPercentage, MemoryUsedInBytes = _process.MemoryUsedInBytes }); } } /// public bool RemoveWriterGroup(string writerGroupId) { if (_diagnostics.TryRemove(writerGroupId, out _)) { _logger.TrackingDiagnosticsStopped(writerGroupId); return true; } return false; } /// public void Start() { _meterListener.Start(); } /// public void Dispose() { _meterListener.Dispose(); } /// /// Enable instrument if we need to hook /// /// /// private void OnInstrumentPublished(Instrument instrument, MeterListener listener) { if (_bindings.ContainsKey(instrument.Name)) { listener.EnableMeasurementEvents(instrument, this); } } /// /// Collect measurement /// /// /// /// /// /// private void OnMeasurementRecorded(Instrument instrument, T measurement, ReadOnlySpan> tags, object? state) { if (_bindings.TryGetValue(instrument.Name, out var binding)) { if (TryGetIds(tags, out var writerGroupId, out var writerGroupName) && _diagnostics.TryGetValue(writerGroupId, out var diag)) { if (writerGroupName != null) { diag.WriterGroupName = writerGroupName; } binding(diag, measurement!); } else { binding(_process, measurement!); } } static bool TryGetIds(ReadOnlySpan> tags, [NotNullWhen(true)] out string? writerGroupId, out string? writerGroupName) { writerGroupId = null; writerGroupName = null; for (var index = tags.Length; index > 0; index--) // Identifiers are at the end { var entry = tags[index - 1]; if (entry.Value is string id) { switch (entry.Key) { case Constants.WriterGroupIdTag: writerGroupId = id; break; case Constants.WriterGroupNameTag: writerGroupName = id; break; } } if (writerGroupId != null && writerGroupName != null) { return true; } } return writerGroupId != null; } } private readonly MeterListener _meterListener; private readonly ILogger _logger; private readonly TimeProvider _timeProvider; private readonly WriterGroupDiagnosticModel _process = new(); private readonly ConcurrentDictionary _diagnostics = new(); // TODO: Split this per measurement type to avoid boxing private readonly ConcurrentDictionary> _bindings = new() { ["iiot_edge_publisher_writer_count"] = (d, i) => d.NumberOfWriters = (int)i, ["iiot_edge_publisher_writer_nodes"] = (d, i) => d.MonitoredOpcNodesCount = (int)i, ["iiot_edge_publisher_writer_good_nodes"] = (d, i) => d.MonitoredOpcNodesSucceededCount = (int)i, ["iiot_edge_publisher_writer_bad_nodes"] = (d, i) => d.MonitoredOpcNodesFailedCount = (int)i, ["iiot_edge_publisher_writer_late_nodes"] = (d, i) => d.MonitoredOpcNodesLateCount = (int)i, ["iiot_edge_publisher_writer_heartbeat_enabled_nodes"] = (d, i) => d.ActiveHeartbeatCount = (int)i, ["iiot_edge_publisher_writer_condition_enabled_nodes"] = (d, i) => d.ActiveConditionCount = (int)i, ["iiot_edge_publisher_publish_requests_client_totals"] = (d, i) => d.TotalPublishRequests = (int)i, ["iiot_edge_publisher_good_publish_requests_client_totals"] = (d, i) => d.TotalGoodPublishRequests = (int)i, ["iiot_edge_publisher_bad_publish_requests_client_totals"] = (d, i) => d.TotalBadPublishRequests = (int)i, ["iiot_edge_publisher_min_publish_requests_client_totals"] = (d, i) => d.TotalMinPublishRequests = (int)i, ["iiot_edge_publisher_is_connection_ok"] = (d, i) => d.NumberOfConnectedEndpoints = (int)i, ["iiot_edge_publisher_is_disconnected"] = (d, i) => d.NumberOfDisconnectedEndpoints = (int)i, ["iiot_edge_publisher_connection_retries"] = (d, i) => d.ConnectionRetries = (long)i, ["iiot_edge_publisher_connection_reconnecting"] = (d, i) => d.ConnectionsReconnecting = (int)i, ["iiot_edge_publisher_connection_successful_keepalives"] = (d, i) => d.ConnectionKeepAlives = (long)i, ["iiot_edge_publisher_connection_total_keepalives"] = (d, i) => d.ConnectionKeepAlivesTotal = (long)i, ["iiot_edge_publisher_connections"] = (d, i) => d.ConnectionCount = (long)i, ["iiot_edge_publisher_keep_alive_notifications"] = (d, i) => d.IngressKeepAliveNotifications = (long)i, ["iiot_edge_publisher_queue_overflows"] = (d, i) => d.ServerQueueOverflows = (long)i, ["iiot_edge_publisher_queue_overflows_per_second_last_min"] = (d, i) => d.ServerQueueOverflowsInLastMinute = (long)i, ["iiot_edge_publisher_data_changes"] = (d, i) => d.IngressDataChanges = (long)i, ["iiot_edge_publisher_data_changes_per_second_last_min"] = (d, i) => d.IngressDataChangesInLastMinute = (long)i, ["iiot_edge_publisher_value_changes"] = (d, i) => d.IngressValueChanges = (long)i, ["iiot_edge_publisher_value_changes_per_second_last_min"] = (d, i) => d.IngressValueChangesInLastMinute = (long)i, ["iiot_edge_publisher_sampledvalues"] = (d, i) => d.IngressSampledValues = (long)i, ["iiot_edge_publisher_sampledvalues_per_second_last_min"] = (d, i) => d.IngressSampledValuesInLastMinute = (long)i, ["iiot_edge_publisher_events"] = (d, i) => d.IngressEvents = (long)i, ["iiot_edge_publisher_events_per_second_last_min"] = (d, i) => d.IngressEventsInLastMinute = (long)i, ["iiot_edge_publisher_heartbeats"] = (d, i) => d.IngressHeartbeats = (long)i, ["iiot_edge_publisher_heartbeats_per_second_last_min"] = (d, i) => d.IngressHeartbeatsInLastMinute = (long)i, ["iiot_edge_publisher_cyclicreads"] = (d, i) => d.IngressCyclicReads = (long)i, ["iiot_edge_publisher_cyclicreads_per_second_last_min"] = (d, i) => d.IngressCyclicReadsInLastMinute = (long)i, ["iiot_edge_publisher_modelchanges"] = (d, i) => d.IngressModelChanges = (long)i, ["iiot_edge_publisher_modelchanges_per_second_last_min"] = (d, i) => d.IngressModelChangesInLastMinute = (long)i, ["iiot_edge_publisher_event_notifications"] = (d, i) => d.IngressEventNotifications = (long)i, ["iiot_edge_publisher_event_notifications_per_second_last_min"] = (d, i) => d.IngressEventNotificationsInLastMinute = (long)i, ["iiot_edge_publisher_publish_queue_dropped_count"] = (d, i) => d.IngressNotificationsDropped = (long)i, ["iiot_edge_publisher_batch_input_queue_size"] = (d, i) => d.IngressBatchBlockBufferSize = (long)i, ["iiot_edge_publisher_send_queue_size"] = (d, i) => d.OutgressInputBufferCount = (long)i, ["iiot_edge_publisher_send_queue_dropped_count"] = (d, i) => d.OutgressInputBufferDropped = (long)i, ["iiot_edge_publisher_encoding_input_queue_size"] = (d, i) => d.EncodingBlockInputSize = (long)i, ["iiot_edge_publisher_encoding_output_queue_size"] = (d, i) => d.EncodingBlockOutputSize = (long)i, ["iiot_edge_publisher_encoded_notifications"] = (d, i) => d.EncoderNotificationsProcessed = (long)i, ["iiot_edge_publisher_message_split_ratio_max"] = (d, i) => d.EncoderMaxMessageSplitRatio = (double)i, ["iiot_edge_publisher_dropped_notifications"] = (d, i) => d.EncoderNotificationsDropped = (long)i, ["iiot_edge_publisher_processed_messages"] = (d, i) => d.EncoderIoTMessagesProcessed = (long)i, ["iiot_edge_publisher_notifications_per_message_average"] = (d, i) => d.EncoderAvgNotificationsMessage = (double)i, ["iiot_edge_publisher_encoded_message_size_average"] = (d, i) => d.EncoderAvgIoTMessageBodySize = (double)i, ["iiot_edge_publisher_chunk_size_average"] = (d, i) => d.EncoderAvgIoTChunkUsage = (double)i, ["iiot_edge_publisher_partitions_count"] = (d, i) => d.TotalPublishQueuePartitions = (int)i, ["iiot_edge_publisher_partitions_active"] = (d, i) => d.ActivePublishQueuePartitions = (int)i, ["iiot_edge_publisher_estimated_message_chunks_per_day"] = (d, i) => d.EstimatedIoTChunksPerDay = (double)i, ["iiot_edge_publisher_messages_per_second"] = (d, i) => d.SentMessagesPerSec = (double)i, ["iiot_edge_publisher_messages"] = (d, i) => d.OutgressIoTMessageCount = (long)i, ["iiot_edge_publisher_message_send_failures"] = (d, i) => d.OutgressIoTMessageFailedCount = (long)i, ["container.cpu.limit.utilization"] = (d, i) => d.CpuLimitUtilization = (double)i, ["container.cpu.request.utilization"] = (d, i) => d.CpuRequestUtilization = (double)i, ["process.cpu.utilization"] = (d, i) => d.CpuUsedPercentage = (double)i, ["container.memory.limit.utilization"] = (d, i) => d.MemoryLimitUtilization = (double)i, ["dotnet.process.memory.virtual.utilization"] = (d, i) => d.MemoryUsedPercentage = (double)i, ["dotnet.process.memory.working_set"] = (d, i) => d.MemoryUsedInBytes = (ulong)(long)i // ... Add here more items if needed }; } /// /// Source-generated logging extensions for PublisherDiagnosticCollector /// internal static partial class PublisherDiagnosticCollectorLogging { private const int EventClass = 260; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Information, Message = "Tracking diagnostics for {WriterGroup} was (re-)started.")] public static partial void TrackingDiagnosticsRestarted(this ILogger logger, string writerGroup); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Information, Message = "Stop tracking diagnostics for {WriterGroup}.")] public static partial void TrackingDiagnosticsStopped(this ILogger logger, string writerGroup); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Services/PublisherModule.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Services { using Autofac; using Furly; using Furly.Azure.IoT.Edge; using Furly.Extensions.Rpc; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.Loader; using System.Threading; using System.Threading.Tasks; /// /// Publisher module hosted service /// public class PublisherModule : IHostedService, IIoTEdgeClientState, IProcessControl { /// /// Running in container /// public static bool IsContainer => StringComparer.OrdinalIgnoreCase.Equals( Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") ?? string.Empty, "true"); /// /// Create hosted service for module operation /// /// /// /// /// public PublisherModule(ILifetimeScope scope, ILogger logger, TimeProvider? timeProvider = null) { _scope = scope ?? throw new ArgumentNullException(nameof(scope)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _timeProvider = timeProvider ?? TimeProvider.System; _exit = new TaskCompletionSource(); AssemblyLoadContext.Default.Unloading += _ => _exit.TrySetResult(true); } /// public async Task StartAsync(CancellationToken cancellationToken) { // Try a crash restart loop here if we are not in a container context. while (true) { try { await _scope.Resolve>().WhenAll().ConfigureAwait(false); var runtimeStateReporter = _scope.Resolve(); var version = GetType().Assembly.GetReleaseVersion().ToString(); _logger.Starting(version); // Start rpc servers foreach (var server in _scope.Resolve>()) { _logger.StartingServer(server.Name); server.Start(); } var aioIntegration = _scope.ResolveOptional(); if (aioIntegration != null) { _logger.EnabledAioIntegration(); } // Now report runtime state as restarted. This can crash and we will retry. await runtimeStateReporter.SendRestartAnnouncementAsync( cancellationToken).ConfigureAwait(false); _logger.Started(version); return; } catch (Exception ex) { _logger.StartError(ex); if (IsContainer) { _logger.ContainerRestart(ex); Process.GetCurrentProcess().Kill(); return; } _logger.RetryIn30Seconds(); await Task.Delay(TimeSpan.FromSeconds(30), cancellationToken).ConfigureAwait(false); } } } /// public void OnClosed(int counter, string deviceId, string? moduleId, string reason) { _logger.ModuleClosed(counter, moduleId ?? deviceId, reason); } /// public void OnConnected(int counter, string deviceId, string? moduleId, string reason) { _logger.ModuleReconnected(counter, moduleId ?? deviceId, reason); } /// public void OnDisconnected(int counter, string deviceId, string? moduleId, string reason) { _logger.ModuleDisconnected(counter, moduleId ?? deviceId, reason); } /// public void OnOpened(int counter, string deviceId, string? moduleId) { _logger.ModuleOpened(counter, moduleId ?? deviceId); } /// public void OnError(int counter, string deviceId, string? moduleId, string reason) { _logger.ModuleError(counter, moduleId ?? deviceId, reason); } /// public Task StopAsync(CancellationToken cancellationToken) { // Shut down gracefully. _exit.TrySetResult(true); if (IsContainer) { // Set timer to kill the entire process after 5 minutes. #pragma warning disable CA2000 // Dispose objects before losing scope _ = _timeProvider.CreateTimer(o => Process.GetCurrentProcess().Kill(), null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)); #pragma warning restore CA2000 // Dispose objects before losing scope } _logger.Stopped(); return Task.CompletedTask; } /// public bool Shutdown(bool failFast) { _logger.ShutdownRequested(); if (failFast) { Environment.FailFast("User shutdown of OPC Publisher due to error."); } else { Environment.Exit(0); } return false; } private readonly TaskCompletionSource _exit; private readonly ILifetimeScope _scope; private readonly ILogger _logger; private readonly TimeProvider _timeProvider; } /// /// Source-generated logging definitions for PublisherModule /// internal static partial class PublisherModuleLogging { private const int EventClass = 270; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Information, Message = "Starting OpcPublisher module version {Version}...")] public static partial void Starting(this ILogger logger, string version); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Information, Message = "... Starting Rpc {Server} server ...")] public static partial void StartingServer(this ILogger logger, string server); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Information, Message = "OpcPublisher module version {Version} started.")] public static partial void Started(this ILogger logger, string version); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Error, Message = "Error trying to start OpcPublisher module!")] public static partial void StartError(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Critical, Message = "Waiting for container restart - exiting...")] public static partial void ContainerRestart(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Information, Message = "Retrying in 30 seconds...")] public static partial void RetryIn30Seconds(this ILogger logger); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Information, Message = "{Counter}: Module {ModuleId} closed due to {Reason}.")] public static partial void ModuleClosed(this ILogger logger, int counter, string moduleId, string reason); [LoggerMessage(EventId = EventClass + 8, Level = LogLevel.Information, Message = "{Counter}: Module {ModuleId} reconnected due to {Reason}.")] public static partial void ModuleReconnected(this ILogger logger, int counter, string moduleId, string reason); [LoggerMessage(EventId = EventClass + 9, Level = LogLevel.Information, Message = "{Counter}: Module {ModuleId} disconnected due to {Reason}...")] public static partial void ModuleDisconnected(this ILogger logger, int counter, string moduleId, string reason); [LoggerMessage(EventId = EventClass + 10, Level = LogLevel.Information, Message = "{Counter}: Module {ModuleId} opened.")] public static partial void ModuleOpened(this ILogger logger, int counter, string moduleId); [LoggerMessage(EventId = EventClass + 11, Level = LogLevel.Error, Message = "{Counter}: Module {ModuleId} error {Reason}...")] public static partial void ModuleError(this ILogger logger, int counter, string moduleId, string reason); [LoggerMessage(EventId = EventClass + 12, Level = LogLevel.Information, Message = "Stopped module OpcPublisher.")] public static partial void Stopped(this ILogger logger); [LoggerMessage(EventId = EventClass + 13, Level = LogLevel.Information, Message = "Received request to shutdown publisher process.")] public static partial void ShutdownRequested(this ILogger logger); [LoggerMessage(EventId = EventClass + 14, Level = LogLevel.Information, Message = "Integration with Azure IoT Operations enabled...")] public static partial void EnabledAioIntegration(this ILogger logger); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Services/PublisherService.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Services { using Azure.IIoT.OpcUa.Publisher; using Azure.IIoT.OpcUa.Publisher.Models; using Autofac; using Furly.Exceptions; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; /// /// Publisher host. Manages updates to the state of the publisher through /// a queue model where a processor effects changes from the configuration in /// state changes of publishers subscription and session model. In return it /// supports aggregation of diagnostics and single sink console output of /// the diagnostics data. /// public sealed class PublisherService : IPublisher, IAsyncDisposable, IDisposable, IMetricsContext { /// public string PublisherId { get; } /// public ImmutableList WriterGroups { get; private set; } = []; /// public DateTimeOffset LastChange { get; private set; } /// public uint Version { get; private set; } /// public TagList TagList { get; } /// /// Create Job host /// /// /// /// /// /// public PublisherService(IWriterGroupScopeFactory factory, IOptions options, ILogger logger, TimeProvider? timeProvider = null) { PublisherId = options?.Value.PublisherId ?? throw new ArgumentNullException(nameof(options)); _factory = factory; _logger = logger; _timeProvider = timeProvider ?? TimeProvider.System; LastChange = _timeProvider.GetUtcNow(); _currentJobs = []; TagList = new TagList( [ new KeyValuePair(Constants.PublisherIdTag, PublisherId) ]); _completedTask = new TaskCompletionSource(); _cts = new CancellationTokenSource(); _changeFeed = Channel.CreateUnbounded<(TaskCompletionSource, List)>( new UnboundedChannelOptions { SingleReader = true, SingleWriter = false }); _processor = Task.Factory.StartNew(() => RunAsync(_cts.Token), _cts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default).Unwrap(); } /// public bool TryUpdate(IEnumerable writerGroups) { ObjectDisposedException.ThrowIf(_isDisposed, this); return _changeFeed.Writer.TryWrite((_completedTask, writerGroups.ToList())); } /// public Task UpdateAsync(IEnumerable writerGroups) { ObjectDisposedException.ThrowIf(_isDisposed, this); var tcs = new TaskCompletionSource( TaskCreationOptions.RunContinuationsAsynchronously); if (_changeFeed.Writer.TryWrite((tcs, writerGroups.ToList()))) { return tcs.Task; } return Task.FromException(new ResourceExhaustionException("Change feed full")); } /// public async ValueTask DisposeAsync() { if (_isDisposed) { return; } _isDisposed = true; try { _logger.ClosingPublisherService(); await _cts.CancelAsync().ConfigureAwait(false); _changeFeed.Writer.TryComplete(); try { await _processor.ConfigureAwait(false); } catch (OperationCanceledException) { } catch (Exception ex) { _logger.FailedToClosePublisherServiceProcessor(ex); } _logger.PublisherServiceClosedSuccessfully(); } finally { _cts.Dispose(); } } /// public void Dispose() { DisposeAsync().AsTask().GetAwaiter().GetResult(); } /// /// Process writer group changes /// /// /// private async Task RunAsync(CancellationToken ct) { try { await foreach (var (task, changes) in _changeFeed.Reader.ReadAllAsync(default).ConfigureAwait(false)) { if (ct.IsCancellationRequested) { task.SetCanceled(ct); continue; } try { await ProcessChangesAsync(task, changes, ct).ConfigureAwait(false); } catch (OperationCanceledException) { task.TrySetCanceled(ct); } catch (Exception ex) { Debug.Fail("We have not processed all exceptions."); task.TrySetException(ex); } } } catch (OperationCanceledException) { } finally { // Disposing - stop all groups before exiting foreach (var group in _currentJobs) { try { group.Value.Dispose(); _logger.WriterGroupJobStopped(group.Key); } catch (Exception ex) when (ex is not OperationCanceledException) { _logger.FailedToStopWriterGroupJob(ex, group.Key); } } } } /// /// Process the received changes /// /// /// /// /// private async ValueTask ProcessChangesAsync(TaskCompletionSource task, List changes, CancellationToken ct) { // Increment change number unchecked { Version++; } var exceptions = new List(); foreach (var writerGroup in changes) { ct.ThrowIfCancellationRequested(); var jobId = writerGroup.Id; if (writerGroup.DataSetWriters?.Any(/*w => w.HasDataToPublish()*/) ?? false) { try { if (_currentJobs.TryGetValue(jobId, out var currentJob)) { await currentJob.UpdateAsync(Version, writerGroup, ct).ConfigureAwait(false); } else { // Create new writer group job currentJob = await WriterGroupJob.CreateAsync(this, jobId, Version, writerGroup, ct).ConfigureAwait(false); _currentJobs.Add(currentJob.Id, currentJob); } } catch (Exception ex) when (ex is not OperationCanceledException) { exceptions.Add(ex); _logger.FailedToProcessChange(ex); } } } // Anything not having an updated version will be deleted foreach (var delete in _currentJobs.Values.Where(j => j.Version < Version).ToList()) { try { delete.Dispose(); } catch (Exception ex) when (ex is not OperationCanceledException) { exceptions.Add(ex); _logger.FailedToDisposeWriterGroupJobBeforeRemoval(ex); } _currentJobs.Remove(delete.Id); } if (exceptions.Count == 0) { // Update writer groups LastChange = _timeProvider.GetUtcNow(); WriterGroups = _currentJobs.Values .Select(j => j.WriterGroup) .ToImmutableList(); // Complete task.TrySetResult(); } else if (exceptions.Count == 1) { // Fail task.TrySetException(exceptions[0]); } else { // Fail task.TrySetException(new AggregateException( "Failed to process changes.", exceptions)); } } /// /// Job context /// private sealed class WriterGroupJob : IDisposable { /// /// Immutable writer group identifier /// public string Id { get; } /// /// Current writer group configuration /// public WriterGroupModel WriterGroup { get; private set; } /// /// Message source /// public IWriterGroupControl Controller { get; } /// /// Current writer group job version /// public uint Version { get; internal set; } /// /// Create context /// /// /// /// /// private WriterGroupJob(PublisherService outer, uint version, string id, WriterGroupModel writerGroup) { _outer = outer; Version = version; WriterGroup = writerGroup with { Id = id }; Id = id; _scope = _outer._factory.Create(WriterGroup); Controller = _scope.WriterGroup; } /// /// Create context /// /// /// /// /// /// /// public static async ValueTask CreateAsync(PublisherService outer, string id, uint version, WriterGroupModel writerGroup, CancellationToken ct) { var context = new WriterGroupJob(outer, version, id, writerGroup); try { await context.Controller.StartAsync(ct).ConfigureAwait(false); return context; } catch (Exception ex) { outer._logger.FailedToCreateWriterGroupJob(ex, context.Id); context.Dispose(); throw; } } /// /// Update writer group job /// /// /// /// /// public async ValueTask UpdateAsync(uint version, WriterGroupModel writerGroup, CancellationToken ct) { try { var newWriterGroup = writerGroup with { Id = Id }; await Controller.UpdateAsync(newWriterGroup, ct).ConfigureAwait(false); // Update inner state if successful WriterGroup = newWriterGroup; } catch (Exception ex) { _outer._logger.FailedToUpdateWriterGroupJob(ex, Id); throw; } finally { Version = version; // Even if we fail, we want to rev the version } } /// public void Dispose() { _scope.Dispose(); } private readonly IWriterGroupScope _scope; private readonly PublisherService _outer; } private bool _isDisposed; private readonly IWriterGroupScopeFactory _factory; private readonly ILogger _logger; private readonly TimeProvider _timeProvider; private readonly Task _processor; private readonly Dictionary _currentJobs; private readonly TaskCompletionSource _completedTask; private readonly CancellationTokenSource _cts; private readonly Channel<(TaskCompletionSource, List)> _changeFeed; } /// /// Source-generated logging extensions for PublisherService /// internal static partial class PublisherServiceLogging { private const int EventClass = 300; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Debug, Message = "Closing publisher service...")] public static partial void ClosingPublisherService(this ILogger logger); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Error, Message = "Failed to close publisher service processor.")] public static partial void FailedToClosePublisherServiceProcessor(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Information, Message = "Publisher service closed succesfully.")] public static partial void PublisherServiceClosedSuccessfully(this ILogger logger); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Information, Message = "Writer group job {Job} stopped.")] public static partial void WriterGroupJobStopped(this ILogger logger, string job); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Error, Message = "Failed to stop writer group job {Job}.")] public static partial void FailedToStopWriterGroupJob(this ILogger logger, Exception ex, string job); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Error, Message = "Failed to process change.")] public static partial void FailedToProcessChange(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Error, Message = "Failed to dispose writer group job before removal.")] public static partial void FailedToDisposeWriterGroupJobBeforeRemoval(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 8, Level = LogLevel.Error, Message = "Failed to create writer group job {Name}")] public static partial void FailedToCreateWriterGroupJob(this ILogger logger, Exception ex, string name); [LoggerMessage(EventId = EventClass + 9, Level = LogLevel.Error, Message = "Failed to update writer group job {Name}")] public static partial void FailedToUpdateWriterGroupJob(this ILogger logger, Exception ex, string name); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Services/RollingAverage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Services { using System; /// /// Rolling average calculator /// internal sealed class RollingAverage { /// /// Changes last minute /// public long LastMinute { get => CalculateSumForRingBuffer(_buffer, ref _lastPointer, kBucketWidth, _lastWriteTime); set => IncreaseRingBuffer(_buffer, ref _lastPointer, kBucketWidth, value, ref _lastWriteTime); } /// /// Changes total /// public long Count { get => _count; set { var difference = value - _count; _count = value; LastMinute = difference; } } public RollingAverage(TimeProvider timeProvider) { _timeProvider = timeProvider; } /// /// Iterates the array and add up all values /// /// /// /// /// private long CalculateSumForRingBuffer(long[] array, ref int lastPointer, int bucketWidth, DateTimeOffset lastWriteTime) { // if IncreaseRingBuffer wasn't called for some time, maybe some stale values are included UpdateRingBufferBuckets(array, ref lastPointer, bucketWidth, ref lastWriteTime); // with cleaned buffer, we can just accumulate all buckets long sum = 0; for (var index = 0; index < array.Length; index++) { sum += array[index]; } return sum; } /// /// Helper function to distribute values over array based on time /// /// /// /// /// /// private void IncreaseRingBuffer(long[] array, ref int lastPointer, int bucketWidth, long difference, ref DateTimeOffset lastWriteTime) { var indexPointer = UpdateRingBufferBuckets(array, ref lastPointer, bucketWidth, ref lastWriteTime); array[indexPointer] += difference; } /// /// Empty the ring buffer buckets if necessary /// /// /// /// /// private int UpdateRingBufferBuckets(long[] array, ref int lastPointer, int bucketWidth, ref DateTimeOffset lastWriteTime) { var now = _timeProvider.GetUtcNow(); var indexPointer = now.Second % bucketWidth; // if last update was > bucketsize seconds in the past delete whole array if (lastWriteTime != DateTimeOffset.MinValue) { var deleteWholeArray = (now - lastWriteTime).TotalSeconds >= bucketWidth; if (deleteWholeArray) { Array.Clear(array, 0, array.Length); lastPointer = indexPointer; } } // reset all buckets, between last write and now while (lastPointer != indexPointer) { lastPointer = (lastPointer + 1) % bucketWidth; array[lastPointer] = 0; } lastWriteTime = now; return indexPointer; } private int _lastPointer; private long _count; private DateTimeOffset _lastWriteTime = DateTimeOffset.MinValue; private readonly TimeProvider _timeProvider; private readonly long[] _buffer = new long[kBucketWidth]; private const int kBucketWidth = 60; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Services/RuntimeStateReporter.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Services { using Azure.IIoT.OpcUa.Publisher; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Encoders; using Furly.Azure.IoT.Edge; using Furly.Azure.IoT.Edge.Services; using Furly.Extensions.Messaging; using Furly.Extensions.Serializers; using Furly.Extensions.Storage; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.Metrics; using System.Globalization; using System.Linq; using System.Net; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading; using System.Threading.Tasks; using Azure.IIoT.OpcUa.Encoders.PubSub; /// /// This class manages reporting of runtime state. /// public sealed class RuntimeStateReporter : IRuntimeStateReporter, IApiKeyProvider, ISslCertProvider, IDisposable { /// public string? ApiKey { get; private set; } /// public X509Certificate2? Certificate { get; private set; } /// /// Constructor for runtime state reporter. /// /// /// /// /// /// /// /// /// /// /// public RuntimeStateReporter(IEnumerable events, IJsonSerializer serializer, IEnumerable stores, IOptions options, IDiagnosticCollector collector, ILogger logger, IMetricsContext? metrics = null, TimeProvider? timeProvider = null, IIoTEdgeDeviceIdentity? identity = null, IIoTEdgeWorkloadApi? workload = null) { _serializer = serializer ?? throw new ArgumentNullException(nameof(serializer)); _options = options ?? throw new ArgumentNullException(nameof(options)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _collector = collector ?? throw new ArgumentNullException(nameof(collector)); _metrics = metrics ?? IMetricsContext.Empty; _timeProvider = timeProvider ?? TimeProvider.System; _workload = workload; _identity = identity; _renewalTimer = _timeProvider.CreateTimer(OnRenewExpiredCertificateAsync, null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); ArgumentNullException.ThrowIfNull(stores); ArgumentNullException.ThrowIfNull(events); if (_options.Value.AllowedEventAndDiagnosticsTransports.Count > 0) { var allowed = _options.Value.AllowedEventAndDiagnosticsTransports .Select(t => t.ToString()) .ToHashSet(StringComparer.OrdinalIgnoreCase); events = events .Where(e => allowed.Contains(e.Name)) .ToList(); } _events = events.Reverse().ToList(); _stores = stores.Reverse().ToList(); if (_stores.Count == 0) { throw new ArgumentException("No key value stores configured.", nameof(stores)); } _runtimeState = RuntimeStateEventType.RestartAnnouncement; _diagnosticInterval = options.Value.DiagnosticsInterval ?? TimeSpan.Zero; _diagnostics = options.Value.DiagnosticsTarget ?? PublisherDiagnosticTargetType.Logger; if (_diagnosticInterval == TimeSpan.Zero) { _diagnosticInterval = Timeout.InfiniteTimeSpan; } _cts = new CancellationTokenSource(); _diagnosticsOutputTimer = new PeriodicTimer(_diagnosticInterval); _publisher = DiagnosticsOutputTimerAsync(_cts.Token); InitializeMetrics(); } /// public void Dispose() { try { _runtimeState = RuntimeStateEventType.Stopped; _cts.Cancel(); _publisher.GetAwaiter().GetResult(); Certificate?.Dispose(); } finally { _renewalTimer.Dispose(); _meter.Dispose(); _diagnosticsOutputTimer.Dispose(); _publisher = Task.CompletedTask; _cts.Dispose(); } } /// public async ValueTask SendRestartAnnouncementAsync(CancellationToken ct) { var hostAddresses = await GetHostAddressesAsync(ct).ConfigureAwait(false); // Set runtime state in state stores foreach (var store in _stores) { store.State[OpcUa.Constants.TwinPropertySiteKey] = _options.Value.SiteId; store.State[OpcUa.Constants.TwinPropertyTypeKey] = OpcUa.Constants.EntityTypePublisher; store.State[OpcUa.Constants.TwinPropertyVersionKey] = GetType().Assembly.GetReleaseVersion().ToString(); store.State[OpcUa.Constants.TwinPropertyFullVersionKey] = PublisherConfig.Version; store.State[OpcUa.Constants.TwinPropertyIpAddressesKey] = hostAddresses; if (_options.Value.HttpServerPort.HasValue) { store.State[OpcUa.Constants.TwinPropertySchemeKey] = "https"; store.State[OpcUa.Constants.TwinPropertyHostnameKey] = Dns.GetHostName(); store.State[OpcUa.Constants.TwinPropertyPortKey] = _options.Value.HttpServerPort; } else { store.State[OpcUa.Constants.TwinPropertySchemeKey] = VariantValue.Null; store.State[OpcUa.Constants.TwinPropertyHostnameKey] = VariantValue.Null; store.State[OpcUa.Constants.TwinPropertyPortKey] = VariantValue.Null; } } await UpdateApiKeyAndCertificateAsync().ConfigureAwait(false); if (_options.Value.EnableRuntimeStateReporting ?? false) { var body = new RuntimeStateEventModel { TimestampUtc = _timeProvider.GetUtcNow(), MessageVersion = 1, MessageType = RuntimeStateEventType.RestartAnnouncement, PublisherId = _options.Value.PublisherId, SemVer = GetType().Assembly.GetReleaseVersion().ToString(), Version = PublisherConfig.Version, Site = _options.Value.SiteId, DeviceId = _identity?.DeviceId, ModuleId = _identity?.ModuleId }; await SendRuntimeStateEventAsync(body, ct).ConfigureAwait(false); _logger.RestartAnnouncementSent(); } _runtimeState = RuntimeStateEventType.Running; } /// /// Get comma seperated host addresses /// /// /// private async Task GetHostAddressesAsync(CancellationToken ct) { try { var host = await Dns.GetHostEntryAsync(Dns.GetHostName(), ct).ConfigureAwait(false); return host.AddressList.Select(ip => ip.ToString()) .Aggregate((a, b) => a + ", " + b); } catch (Exception ex) { _logger.HostnameResolveFailed(ex); return VariantValue.Null; } } /// /// Update cached api key /// private async Task UpdateApiKeyAndCertificateAsync() { var apiKeyStore = _stores.Find(s => s.State.TryGetValue( OpcUa.Constants.TwinPropertyApiKeyKey, out var key) && key.IsString); if (apiKeyStore != null) { ApiKey = (string?)apiKeyStore.State[OpcUa.Constants.TwinPropertyApiKeyKey]; _logger.ApiKeyExists(apiKeyStore.Name); } if (!string.IsNullOrWhiteSpace(_options.Value.ApiKeyOverride) && ApiKey != _options.Value.ApiKeyOverride) { Debug.Assert(_stores.Count > 0); _logger.UsingConfigApiKey(); ApiKey = _options.Value.ApiKeyOverride; _stores[0].State.Add(OpcUa.Constants.TwinPropertyApiKeyKey, ApiKey); } if (string.IsNullOrWhiteSpace(ApiKey)) { Debug.Assert(_stores.Count > 0); _logger.GeneratingApiKey(_stores[0].Name); ApiKey = RandomNumberGenerator.GetBytes(20).ToBase64String(); _stores[0].State.Add(OpcUa.Constants.TwinPropertyApiKeyKey, ApiKey); } var dnsName = Dns.GetHostName(); // The certificate must be in the same store as the api key or else we generate a new one. if (!(_options.Value.RenewTlsCertificateOnStartup ?? false) && apiKeyStore != null && apiKeyStore.State.TryGetValue(OpcUa.Constants.TwinPropertyCertificateKey, out var cert) && cert.IsBytes) { try { // Load certificate Certificate?.Dispose(); Certificate = X509CertificateLoader.LoadPkcs12((byte[])cert!, ApiKey); var now = _timeProvider.GetUtcNow().AddDays(1); if (now < Certificate.NotAfter && Certificate.HasPrivateKey && Certificate.SubjectName.EnumerateRelativeDistinguishedNames() .Any(a => a.GetSingleElementValue() == dnsName)) { var renewalAfter = Certificate.NotAfter - now; _logger.UsingValidCertificate(apiKeyStore.Name, renewalAfter); _renewalTimer.Change(renewalAfter, Timeout.InfiniteTimeSpan); // Done return; } _logger.CertificateExpired(apiKeyStore.Name); } catch (Exception ex) { _logger.CertificateInvalid(ex); } } // Create new certificate var nowOffset = _timeProvider.GetUtcNow(); var expiration = nowOffset.AddDays(kCertificateLifetimeDays); Certificate?.Dispose(); Certificate = null; if (_workload != null) { try { var certificates = await _workload.CreateServerCertificateAsync( dnsName, expiration.Date).ConfigureAwait(false); Debug.Assert(certificates.Count > 0); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { using var certificate = certificates[0]; // // https://github.com/dotnet/runtime/issues/45680) // On Windows the certificate in 'result' gives an error // when used with kestrel: "No credentials are available" // Certificate = X509CertificateLoader.LoadCertificate( certificate.Export(X509ContentType.Pkcs12)); } else { Certificate = certificates[0]; } if (!Certificate.HasPrivateKey) { Certificate.Dispose(); Certificate = null; _logger.FailedToGetCertificateWithPrivateKey(); } else { _logger.UsingWorkloadApiCertificate(); } } catch (NotSupportedException nse) { _logger.WorkloadApiNotSupported(nse.Message); } catch (Exception ex) { _logger.WorkloadApiCertificateFailed(ex); } } if (Certificate == null) { using var ecdsa = ECDsa.Create(); var req = new CertificateRequest("DC=" + dnsName, ecdsa, HashAlgorithmName.SHA256); var san = new SubjectAlternativeNameBuilder(); san.AddDnsName(dnsName); var altDns = _identity?.ModuleId ?? _identity?.DeviceId; if (!string.IsNullOrEmpty(altDns) && !string.Equals(altDns, dnsName, StringComparison.OrdinalIgnoreCase)) { san.AddDnsName(altDns); } req.CertificateExtensions.Add(san.Build()); Certificate = req.CreateSelfSigned(DateTimeOffset.Now, expiration); Debug.Assert(Certificate.HasPrivateKey); _logger.CreatedSelfSignedCertificate(); } Debug.Assert(_stores.Count > 0); Debug.Assert(ApiKey != null); apiKeyStore ??= _stores[0]; var pfxCertificate = Certificate.Export(X509ContentType.Pfx, ApiKey); apiKeyStore.State.AddOrUpdate(OpcUa.Constants.TwinPropertyCertificateKey, pfxCertificate); var renewalDuration = Certificate.NotAfter - nowOffset.Date - TimeSpan.FromDays(1); _renewalTimer.Change(renewalDuration, Timeout.InfiniteTimeSpan); _logger.StoredNewCertificate(apiKeyStore.Name, renewalDuration); _certificateRenewals++; } /// /// Renew certificate /// /// private async void OnRenewExpiredCertificateAsync(object? state) { try { await UpdateApiKeyAndCertificateAsync().ConfigureAwait(false); } catch (Exception ex) { // Retry _logger.CertificateRenewalFailed(ex); _renewalTimer.Change(TimeSpan.FromHours(1), Timeout.InfiniteTimeSpan); } } /// /// Send runtime state events /// /// /// /// private async Task SendRuntimeStateEventAsync(RuntimeStateEventModel runtimeStateEvent, CancellationToken ct) { var eventsTopic = _topicCache.GetOrAdd( (runtimeStateEvent.MessageType.ToString(), runtimeStateEvent.DeviceId), id => new TopicBuilder(_options.Value, variables: new Dictionary { [PublisherConfig.EventNameVariableName] = id.Item1 ?? Constants.DefaultEventName, [PublisherConfig.EventContextVariableName] = id.Item2 ?? Constants.DefaultContextName, [PublisherConfig.EventSourceVariableName] = _options.Value.RuntimeStateRoutingInfo ?? "status", [PublisherConfig.EncodingVariableName] = MessageEncoding.Json.ToString() // ... }).EventsTopic); await Task.WhenAll(_events.Select(SendOneEventAsync)).ConfigureAwait(false); async Task SendOneEventAsync(IEventClient events) { try { await events.SendEventAsync(eventsTopic, _serializer.SerializeToMemory(runtimeStateEvent), _serializer.MimeType, Encoding.UTF8.WebName, configure: eventMessage => { eventMessage.SetRetain(true); if (_options.Value.EnableCloudEvents == true) { eventMessage = eventMessage.AsCloudEvent(new CloudEventHeader { Id = Guid.NewGuid().ToString("N"), Source = new Uri("urn:" + _options.Value.PublisherId), Subject = runtimeStateEvent.MessageType.ToString(), Type = MessageSchemaTypes.RuntimeStateMessage }); } else { eventMessage = eventMessage .AddProperty(OpcUa.Constants.MessagePropertySchemaKey, MessageSchemaTypes.RuntimeStateMessage); if (_options.Value.RuntimeStateRoutingInfo != null) { eventMessage = eventMessage .AddProperty(OpcUa.Constants.MessagePropertyRoutingKey, _options.Value.RuntimeStateRoutingInfo); } } }, ct).ConfigureAwait(false); _logger.EventSent(runtimeStateEvent.ToString(), events.Name); } catch (Exception ex) { _logger.SendEventFailed(ex, runtimeStateEvent.MessageType.ToString(), events.Name); } } } /// /// ChannelDiagnostics timer to dump out all diagnostics /// /// private async Task DiagnosticsOutputTimerAsync(CancellationToken ct) { while (!ct.IsCancellationRequested) { try { await _diagnosticsOutputTimer.WaitForNextTickAsync(ct).ConfigureAwait(false); var diagnostics = _collector.EnumerateDiagnostics(); switch (_diagnostics) { case PublisherDiagnosticTargetType.Events: await SendDiagnosticsAsync(diagnostics, ct).ConfigureAwait(false); break; // TODO: case PublisherDiagnosticTargetType.PubSub: // TODO: break; default: WriteDiagnosticsToConsole(diagnostics, _options.Value.DisableResourceMonitoring != true); break; } } catch (OperationCanceledException) { return; } catch (Exception ex) { _logger.DiagnosticsError(ex); } } } /// /// Send diagnostics /// /// /// /// private async ValueTask SendDiagnosticsAsync( IEnumerable<(string, WriterGroupDiagnosticModel)> diagnostics, CancellationToken ct) { foreach (var (writerGroupId, info) in diagnostics) { var diagnosticsTopic = _topicCache.GetOrAdd((writerGroupId, info.WriterGroupName), id => new TopicBuilder(_options.Value, variables: new Dictionary { [PublisherConfig.WriterGroupIdVariableName] = id.Item1 ?? Constants.DefaultWriterGroupName, [PublisherConfig.DataSetWriterGroupVariableName] = id.Item2 ?? Constants.DefaultWriterGroupName, [PublisherConfig.WriterGroupVariableName] = id.Item2 ?? Constants.DefaultWriterGroupName, [PublisherConfig.EncodingVariableName] = MessageEncoding.Json.ToString() // ... }).DiagnosticsTopic); await Task.WhenAll(_events.Select(SendOneEventAsync)).ConfigureAwait(false); async Task SendOneEventAsync(IEventClient events) { try { await events.SendEventAsync(diagnosticsTopic, _serializer.SerializeToMemory(info), _serializer.MimeType, Encoding.UTF8.WebName, configure: eventMessage => { eventMessage .SetRetain(true) .SetTtl(_diagnosticInterval + TimeSpan.FromSeconds(10)); if (_options.Value.EnableCloudEvents == true) { eventMessage = eventMessage.AsCloudEvent(new CloudEventHeader { Id = Guid.NewGuid().ToString("N"), Source = new Uri("urn:" + _options.Value.PublisherId), Subject = info.WriterGroupName, Type = MessageSchemaTypes.WriterGroupDiagnosticsMessage }); } else { eventMessage = eventMessage .AddProperty(OpcUa.Constants.MessagePropertySchemaKey, MessageSchemaTypes.WriterGroupDiagnosticsMessage); if (_options.Value.RuntimeStateRoutingInfo != null) { eventMessage = eventMessage .AddProperty(OpcUa.Constants.MessagePropertyRoutingKey, _options.Value.RuntimeStateRoutingInfo); } } }, ct).ConfigureAwait(false); } catch (Exception ex) { _logger.DiagnosticsSendFailed(ex, events.Name); } } } } /// /// Format diagnostics to console /// /// /// private static void WriteDiagnosticsToConsole( IEnumerable<(string, WriterGroupDiagnosticModel)> diagnostics, bool includeResourceInfo) { var builder = new StringBuilder(); foreach (var (writerGroupId, info) in diagnostics) { builder = Append(builder, writerGroupId, info, includeResourceInfo); } if (builder.Length > 0) { Console.Out.WriteLine(builder.ToString()); } static StringBuilder Append(StringBuilder builder, string writerGroupId, WriterGroupDiagnosticModel info, bool includeResourceInfo) { var s = info.IngestionDuration.TotalSeconds == 0 ? 1 : info.IngestionDuration.TotalSeconds; var min = info.IngestionDuration.TotalMinutes == 0 ? 1 : info.IngestionDuration.TotalMinutes; var eventsPerSec = info.IngressEvents / s; var eventNotificationsPerSec = info.IngressEventNotifications / s; var sentMessagesPerSecFormatted = info.OutgressIoTMessageCount > 0 ? $"({info.SentMessagesPerSec:n2}/s)" : string.Empty; var keepAliveChangesPerSecFormatted = info.IngressKeepAliveNotifications > 0 ? $"(All time ~{info.IngressKeepAliveNotifications / min:n2}/min)" : string.Empty; var dataChangesPerSecFormatted = Format(info.IngressDataChanges, info.IngressDataChangesInLastMinute, s); var valueChangesPerSecFormatted = Format(info.IngressValueChanges, info.IngressValueChangesInLastMinute, s); var eventsPerSecFormatted = Format(info.IngressEvents, info.IngressEventsInLastMinute, s); var eventNotificationsPerSecFormatted = Format(info.IngressEventNotifications, info.IngressEventNotificationsInLastMinute, s); var heartbeatsPerSecFormatted = Format(info.IngressHeartbeats, info.IngressHeartbeatsInLastMinute, s); var cyclicReadsPerSecFormatted = Format(info.IngressCyclicReads, info.IngressCyclicReadsInLastMinute, s); var sampledValuesPerSecFormatted = Format(info.IngressSampledValues, info.IngressSampledValuesInLastMinute, s); var modelChangesPerSecFormatted = Format(info.IngressModelChanges, info.IngressModelChangesInLastMinute, s); var serverQueueOverflowsPerSecFormatted = Format(info.ServerQueueOverflows, info.ServerQueueOverflowsInLastMinute, s); static string Format(long changes, long lastMinute, double s) { var dataChangesPerSecLastMin = lastMinute / Math.Min(s, 60d); return changes > 0 ? $"(All time ~{changes / s:n2}/s; {lastMinute:n0} in last 60s ~{dataChangesPerSecLastMin:n2}/s)" : string.Empty; } var chunkUsageFormatted = Math.Round(info.EncoderAvgIoTChunkUsage, 2) > 0 ? $"(Avg Chunk (4 KB) usage {info.EncoderAvgIoTChunkUsage:n2}; {info.EstimatedIoTChunksPerDay:n1}/day estimated)" : string.Empty; var connectivityState = info.NumberOfConnectedEndpoints > 0 ? (info.NumberOfDisconnectedEndpoints > 0 ? "(Partially Connected)" : "(Connected)") : "(Disconnected)"; var reconnectivityState = info.ConnectionsReconnecting > 0 ? $"({info.ConnectionsReconnecting} reconnecting)" : string.Empty; var sb = builder.AppendLine() .Append(" DIAGNOSTICS INFORMATION for : ") .Append(info.WriterGroupName ?? Constants.DefaultWriterGroupName) .Append(" (") .AppendFormat(CultureInfo.CurrentCulture, "{0:0}", writerGroupId) .AppendLine(")") .Append(" # OPC Publisher Version (Runtime) : ") .AppendLine(info.PublisherVersion) ; if (includeResourceInfo) { sb = sb .Append(" # Cpu (%limit/%req/%used) : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:p2}", info.CpuLimitUtilization) .Append(" | ") .AppendFormat(CultureInfo.CurrentCulture, "{0:p2}", info.CpuRequestUtilization) .Append(" (") .AppendFormat(CultureInfo.CurrentCulture, "{0:p2}", info.CpuUsedPercentage) .AppendLine(")") .Append(" # Memory (%limit/%used/total used) : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:p2}", info.MemoryLimitUtilization) .Append(" | ") .AppendFormat(CultureInfo.CurrentCulture, "{0:p2}", info.MemoryUsedPercentage) .Append(" (") .AppendFormat(CultureInfo.CurrentCulture, "{0:n0}", info.MemoryUsedInBytes / 1000d) .AppendLine(" KB)") ; } return sb .Append(" # Ingest duration (dd:hh:mm:ss)/Time : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:dd\\:hh\\:mm\\:ss}", info.IngestionDuration) .Append(" | ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:O}", info.Timestamp) .AppendLine() .Append(" # Number of writers in group : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:0}", info.NumberOfWriters) .AppendLine() .Append(" # Good/Total number of items : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:n0}", info.MonitoredOpcNodesSucceededCount).Append(" | ") .AppendFormat(CultureInfo.CurrentCulture, "{0:n0}", info.MonitoredOpcNodesCount) .AppendLine() .Append(" # Bad/Late number of items : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:n0}", info.MonitoredOpcNodesFailedCount).Append(" | ") .AppendFormat(CultureInfo.CurrentCulture, "{0:n0}", info.MonitoredOpcNodesLateCount) .AppendLine() .Append(" # Heartbeats/Condition items active : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:n0}", info.ActiveHeartbeatCount).Append(" | ") .AppendFormat(CultureInfo.CurrentCulture, "{0:n0}", info.ActiveConditionCount) .AppendLine() .Append(" # Endpoints connected/disconnected : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:0}", info.NumberOfConnectedEndpoints).Append(" | ") .AppendFormat(CultureInfo.CurrentCulture, "{0:0}", info.NumberOfDisconnectedEndpoints).Append(' ') .AppendLine(connectivityState) .Append(" # Connections created/retries : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:0}", info.ConnectionCount).Append(" | ") .AppendFormat(CultureInfo.CurrentCulture, "{0:0}", info.ConnectionRetries).Append(' ') .AppendLine(reconnectivityState) .Append(" # Connection keep alives / total : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:0.##}", info.ConnectionKeepAlives).Append(" | ") .AppendFormat(CultureInfo.CurrentCulture, "{0:0.##}", info.ConnectionKeepAlivesTotal) .AppendLine() .Append(" # Queued/Minimum request totals : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:0.##}", info.TotalPublishRequests).Append(" | ") .AppendFormat(CultureInfo.CurrentCulture, "{0:0.##}", info.TotalMinPublishRequests) .AppendLine() .Append(" # Good/Bad Publish request totals : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:0.##}", info.TotalGoodPublishRequests).Append(" | ") .AppendFormat(CultureInfo.CurrentCulture, "{0:0.##}", info.TotalBadPublishRequests) .AppendLine() .Append(" # Ingress value changes : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:n0}", info.IngressValueChanges).Append(' ') .AppendLine(valueChangesPerSecFormatted) .Append(" # Ingress sampled values : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:n0}", info.IngressSampledValues).Append(' ') .AppendLine(sampledValuesPerSecFormatted) .Append(" # Ingress events : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:n0}", info.IngressEvents).Append(' ') .AppendLine(eventsPerSecFormatted) .Append(" # Server queue overflows : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:n0}", info.ServerQueueOverflows).Append(' ') .AppendLine(serverQueueOverflowsPerSecFormatted) .Append(" # Received Data Change Notifications : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:n0}", info.IngressDataChanges).Append(' ') .AppendLine(dataChangesPerSecFormatted) .Append(" # Received Event Notifications : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:n0}", info.IngressEventNotifications).Append(' ') .AppendLine(eventNotificationsPerSecFormatted) .Append(" # Received Keep Alive Notifications : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:n0}", info.IngressKeepAliveNotifications).Append(' ') .AppendLine(keepAliveChangesPerSecFormatted) .Append(" # Received Cyclic read Notifications : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:n0}", info.IngressCyclicReads).Append(' ') .AppendLine(cyclicReadsPerSecFormatted) .Append(" # Generated Heartbeat Notifications : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:n0}", info.IngressHeartbeats).Append(' ') .AppendLine(heartbeatsPerSecFormatted) .Append(" # Generated Model Changes : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:n0}", info.IngressModelChanges).Append(' ') .AppendLine(modelChangesPerSecFormatted) .Append(" # Publish queue partitions/active : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:n0}", info.TotalPublishQueuePartitions).Append(" | ") .AppendFormat(CultureInfo.CurrentCulture, "{0:n0}", info.ActivePublishQueuePartitions) .AppendLine() .Append(" # Notifications buffered/dropped : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:n0}", info.IngressBatchBlockBufferSize).Append(" | ") .AppendFormat(CultureInfo.CurrentCulture, "{0:n0}", info.IngressNotificationsDropped) .AppendLine() .Append(" # Encoder input buffer size : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:n0}", info.EncodingBlockInputSize) .AppendLine() .Append(" # Encoder Notif. processed/dropped : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:n0}", info.EncoderNotificationsProcessed).Append(" | ") .AppendFormat(CultureInfo.CurrentCulture, "{0:n0}", info.EncoderNotificationsDropped) .AppendLine() .Append(" # Encoder Network Messages produced : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:n0}", info.EncoderIoTMessagesProcessed) .AppendLine() .Append(" # Encoder avg Notifications/Message : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:n0}", info.EncoderAvgNotificationsMessage) .AppendLine() .Append(" # Encoder worst Message split ratio : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:0.##}", info.EncoderMaxMessageSplitRatio) .AppendLine() .Append(" # Encoder avg Message body size : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:0.##}", info.EncoderAvgIoTMessageBodySize).Append(' ') .AppendLine(chunkUsageFormatted) .Append(" # Encoder output buffer size : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:n0}", info.EncodingBlockOutputSize) .AppendLine() .Append(" # Egress Messages queued/dropped : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:n0}", info.OutgressInputBufferCount).Append(" | ") .AppendFormat(CultureInfo.CurrentCulture, "{0:n0}", info.OutgressInputBufferDropped) .AppendLine() .Append(" # Egress Message send failures : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:n0}", info.OutgressIoTMessageFailedCount) .AppendLine() .Append(" # Egress Messages successfully sent : ") .AppendFormat(CultureInfo.CurrentCulture, "{0,14:n0}", info.OutgressIoTMessageCount) .Append(' ') .AppendLine(sentMessagesPerSecFormatted) ; } } /// /// Create observable metrics /// private void InitializeMetrics() { _meter.CreateObservableGauge("iiot_edge_publisher_module_start", () => new Measurement(_runtimeState == RuntimeStateEventType.RestartAnnouncement ? 0 : 1, _metrics.TagList), description: "Publisher module started."); _meter.CreateObservableGauge("iiot_edge_publisher_module_state", () => new Measurement((int)_runtimeState, _metrics.TagList), description: "Publisher module runtime state."); _meter.CreateObservableCounter("iiot_edge_publisher_certificate_renewal_count", () => new Measurement(_certificateRenewals, _metrics.TagList), description: "Publisher certificate renewals."); } private const int kCertificateLifetimeDays = 30; private readonly ConcurrentDictionary<(string, string?), string> _topicCache = new(); private readonly ILogger _logger; private readonly IIoTEdgeDeviceIdentity? _identity; private readonly IDiagnosticCollector _collector; private readonly IIoTEdgeWorkloadApi? _workload; private readonly ITimer _renewalTimer; private readonly TimeProvider _timeProvider; private readonly IJsonSerializer _serializer; private readonly IOptions _options; private readonly List _events; private readonly List _stores; private readonly Meter _meter = Diagnostics.NewMeter(); private readonly IMetricsContext _metrics; private readonly CancellationTokenSource _cts; private readonly PeriodicTimer _diagnosticsOutputTimer; private readonly TimeSpan _diagnosticInterval; private readonly PublisherDiagnosticTargetType _diagnostics; private RuntimeStateEventType _runtimeState; private Task _publisher; private int _certificateRenewals; } /// /// Source-generated logging definitions for RuntimeStateReporter /// internal static partial class RuntimeStateReporterLogging { private const int EventClass = 330; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Information, Message = "Restart announcement sent successfully.")] public static partial void RestartAnnouncementSent(this ILogger logger); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Error, Message = "Failed to resolve hostname.")] public static partial void HostnameResolveFailed(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Information, Message = "Api Key exists in {Store} store...")] public static partial void ApiKeyExists(this ILogger logger, string store); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Information, Message = "Using Api Key provided in configuration...")] public static partial void UsingConfigApiKey(this ILogger logger); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Information, Message = "Generating new Api Key in {Store} store...")] public static partial void GeneratingApiKey(this ILogger logger, string store); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Information, Message = "Using valid Certificate found in {Store} store (renewal in {Duration})...")] public static partial void UsingValidCertificate(this ILogger logger, string store, TimeSpan duration); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Information, Message = "Certificate found in {Store} store has expired. Generate new...")] public static partial void CertificateExpired(this ILogger logger, string store); [LoggerMessage(EventId = EventClass + 8, Level = LogLevel.Error, Message = "Provided Certificate invalid.")] public static partial void CertificateInvalid(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 9, Level = LogLevel.Information, Message = "Using server certificate with private key from workload API...")] public static partial void UsingWorkloadApiCertificate(this ILogger logger); [LoggerMessage(EventId = EventClass + 10, Level = LogLevel.Error, Message = "Failed to create certificate using workload API.")] public static partial void WorkloadApiCertificateFailed(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 11, Level = LogLevel.Information, Message = "Created self-signed ECC server certificate...")] public static partial void CreatedSelfSignedCertificate(this ILogger logger); [LoggerMessage(EventId = EventClass + 12, Level = LogLevel.Information, Message = "Stored new Certificate in {Store} store (and scheduled renewal after {Duration}).")] public static partial void StoredNewCertificate(this ILogger logger, string store, TimeSpan duration); [LoggerMessage(EventId = EventClass + 13, Level = LogLevel.Critical, Message = "Failed to renew certificate - retrying in 1 hour...")] public static partial void CertificateRenewalFailed(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 14, Level = LogLevel.Information, Message = "{Event} sent via {Transport}.")] public static partial void EventSent(this ILogger logger, string? @event, string transport); [LoggerMessage(EventId = EventClass + 15, Level = LogLevel.Error, Message = "Failed sending {MessageType} runtime state event through {Transport}.")] public static partial void SendEventFailed(this ILogger logger, Exception ex, string messageType, string transport); [LoggerMessage(EventId = EventClass + 16, Level = LogLevel.Error, Message = "Error during diagnostics processing.")] public static partial void DiagnosticsError(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 17, Level = LogLevel.Error, Message = "Failed sending Diagnostics event through {Transport}.")] public static partial void DiagnosticsSendFailed(this ILogger logger, Exception ex, string transport); [LoggerMessage(EventId = EventClass + 18, Level = LogLevel.Warning, Message = "Failed to get certificate with private key using workload API.")] public static partial void FailedToGetCertificateWithPrivateKey(this ILogger logger); [LoggerMessage(EventId = EventClass + 19, Level = LogLevel.Warning, Message = "Not supported: {Message}. Unable to use workload API to obtain the certificate!")] public static partial void WorkloadApiNotSupported(this ILogger logger, string message); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Services/WriterGroupDataSource.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Services { using Azure.IIoT.OpcUa.Publisher; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Encoders.PubSub; using Furly.Extensions.Messaging; using Furly.Extensions.Serializers; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.Metrics; using System.Linq; using System.Threading; using System.Threading.Tasks; /// /// Triggers dataset writer messages on subscription changes /// public sealed partial class WriterGroupDataSource : IWriterGroupControl, IDisposable, IAsyncDisposable { /// /// Id of the group /// public string Id => _writerGroup.Id; /// /// Create trigger from writer group /// /// /// /// /// /// /// /// /// public WriterGroupDataSource(IOpcUaClientManager clients, WriterGroupModel writerGroup, IMessageSink sink, IJsonSerializer serializer, IOptions options, IMetricsContext? metrics, ILoggerFactory loggerFactory, TimeProvider? timeProvider = null) { ArgumentNullException.ThrowIfNull(writerGroup, nameof(writerGroup)); _loggerFactory = loggerFactory; _serializer = serializer; _sink = sink; _options = options; _logger = loggerFactory.CreateLogger(); _timeProvider = timeProvider ?? TimeProvider.System; _metrics = metrics ?? IMetricsContext.Empty; _clients = clients; _startTime = _timeProvider.GetTimestamp(); _valueChanges = new RollingAverage(_timeProvider); _dataChanges = new RollingAverage(_timeProvider); _sampledValues = new RollingAverage(_timeProvider); _cyclicReads = new RollingAverage(_timeProvider); _eventNotification = new RollingAverage(_timeProvider); _events = new RollingAverage(_timeProvider); _modelChanges = new RollingAverage(_timeProvider); _heartbeats = new RollingAverage(_timeProvider); _overflows = new RollingAverage(_timeProvider); _writerGroup = Copy(writerGroup); InitializeMetrics(); } /// public async ValueTask StartAsync(CancellationToken ct) { await _lock.WaitAsync(ct).ConfigureAwait(false); try { Debug.Assert(_writers.IsEmpty); if (_writerGroup.DataSetWriters == null) { return; } // // We manage writers in the writer group using id, there should not // be duplicate writer ids here, if there are we throw an exception. // var index = 0; var writerNames = new HashSet(); foreach (var writer in _writerGroup.DataSetWriters) { // Create writer partitions foreach (var key in DataSetWriter.GetDataSetWriters(this, writer)) { var writerSubscription = await DataSetWriterSubscription.CreateAsync(this, key, _loggerFactory, writerNames, ct).ConfigureAwait(false); writerSubscription.Index = index++; if (!_writers.TryAdd(key, writerSubscription)) { throw new ArgumentException( $"Group {Id} contains duplicate writer {writer.Id}."); } } } } finally { _lock.Release(); } } /// public async ValueTask UpdateAsync(WriterGroupModel writerGroup, CancellationToken ct) { await _lock.WaitAsync(ct).ConfigureAwait(false); try { Interlocked.Increment(ref _metadataChanges); writerGroup = Copy(writerGroup); if (writerGroup.DataSetWriters == null || writerGroup.DataSetWriters.Count == 0) { // Fast path - just disopse it all. foreach (var subscription in _writers.Values) { await subscription.DisposeAsync().ConfigureAwait(false); } _logger.RemovedAllSubscriptions(writerGroup.Id); _writers.Clear(); _writerGroup = writerGroup; return; } // // We manage writers in the writer group using id, there should not // be duplicate writer ids here, if there are we throw an exception. // var writerKeySet = new HashSet(); foreach (var writer in writerGroup.DataSetWriters) { foreach (var key in DataSetWriter.GetDataSetWriters(this, writer)) { if (!writerKeySet.Add(key)) { throw new ArgumentException( $"Group {writerGroup.Id} contains duplicate writer {key}."); } } } // Update or removed ones that were updated or removed. var writerNames = _writers.Values.Select(w => w.Name).ToHashSet(); foreach (var key in _writers.Keys.ToList()) { if (!writerKeySet.TryGetValue(key, out var actualKey)) { if (_writers.Remove(key, out var s)) { await s.DisposeAsync().ConfigureAwait(false); } } else { // Update if (_writers.TryGetValue(key, out var s)) { await s.UpdateAsync(actualKey, writerNames, ct).ConfigureAwait(false); } } } // Create any newly added ones foreach (var key in writerKeySet) { if (_writers.ContainsKey(key)) { // Already processed continue; } // Add var writerSubscription = await DataSetWriterSubscription.CreateAsync(this, key, _loggerFactory, writerNames, ct).ConfigureAwait(false); if (!_writers.TryAdd(key, writerSubscription)) { throw new ArgumentException( $"Group {Id} contains duplicate writer {key}."); } } // Update indexes (even if they are moving around) var index = 0; foreach (var writer in _writers.Values) { writer.Index = index++; } _logger.UpdatedAllWriters(writerGroup.Id); _writerGroup = writerGroup; } finally { _lock.Release(); } } /// public void Dispose() { DisposeAsync().AsTask().GetAwaiter().GetResult(); } /// public async ValueTask DisposeAsync() { try { await _lock.WaitAsync().ConfigureAwait(false); try { foreach (var s in _writers.Values) { await s.DisposeAsync().ConfigureAwait(false); } } finally { _writers.Clear(); _lock.Release(); } } finally { _lock.Dispose(); _meter.Dispose(); } } /// /// Safe clone the writer group model /// /// /// private WriterGroupModel Copy(WriterGroupModel model) { var writerGroup = model with { DataSetWriters = model.DataSetWriters == null ? Array.Empty() : model.DataSetWriters .Where(w => w.HasDataToPublish()) .Select(f => f.Clone()) .ToList(), LocaleIds = model.LocaleIds?.ToList(), MessageSettings = model.MessageSettings == null ? null : model.MessageSettings with { }, SecurityKeyServices = model.SecurityKeyServices? .Select(c => c.Clone()) .ToList() }; // Set the messaging profile settings var defaultMessagingProfile = _options.Value.MessagingProfile ?? MessagingProfile.Get(MessagingMode.PubSub, MessageEncoding.Json); if (writerGroup.HeaderLayoutUri != null) { defaultMessagingProfile = MessagingProfile.Get( Enum.Parse(writerGroup.HeaderLayoutUri), writerGroup.MessageType ?? defaultMessagingProfile.MessageEncoding); } writerGroup.MessageType ??= defaultMessagingProfile.MessageEncoding; // Set the messaging settings for the encoder if (writerGroup.MessageSettings?.NetworkMessageContentMask == null) { writerGroup.MessageSettings ??= new WriterGroupMessageSettingsModel(); writerGroup.MessageSettings.NetworkMessageContentMask = defaultMessagingProfile.NetworkMessageContentMask; } foreach (var dataSetWriter in writerGroup.DataSetWriters) { if (dataSetWriter.MessageSettings?.DataSetMessageContentMask == null) { dataSetWriter.MessageSettings ??= new DataSetWriterMessageSettingsModel(); dataSetWriter.MessageSettings.DataSetMessageContentMask = defaultMessagingProfile.DataSetMessageContentMask; } dataSetWriter.DataSetFieldContentMask ??= defaultMessagingProfile.DataSetFieldContentMask; if (_options.Value.WriteValueWhenDataSetHasSingleEntry == true) { dataSetWriter.DataSetFieldContentMask |= Models.DataSetFieldContentFlags.SingleFieldDegradeToValue; } } return writerGroup; } /// /// Safely get the writer group /// /// /// /// private void GetSchemaAndWriterGroup(string topic, out WriterGroupModel writerGroup, out IEventSchema? schema) { if (_options.Value.SchemaOptions == null) { // No schema options, so no schema support writerGroup = _writerGroup; schema = null; return; } if (_schemaGroups.TryGetValue(topic, out var schemaGroup) && schemaGroup.Version == (ulong)_metadataChanges) { writerGroup = _writerGroup; schema = schemaGroup.Schema; return; } _lock.Wait(); try { writerGroup = _writerGroup; if (_schemaGroups.TryGetValue(topic, out schemaGroup) && schemaGroup.Version == (ulong)_metadataChanges) { schema = schemaGroup.Schema; return; } var id = writerGroup.Name ?? writerGroup.Id; var encoding = writerGroup.MessageType ?? MessageEncoding.Json; var datasetSchemaMetadata = _writers.Values .Where(s => s.Topic == topic) .Select(s => s.MetaData) .ToList(); if (datasetSchemaMetadata.Any(m => m == null)) { // If any of the dataset metadata is null, we cannot create a schema _logger.FailedToCreateSchemaMissingMetadata(encoding, writerGroup.Id); schema = null; return; } if (datasetSchemaMetadata.Count == 1) { id = datasetSchemaMetadata[0]!.Id ?? id; } else { _logger.MultiDataSetSchema(topic, writerGroup.Id); id = $"{id}|{topic.ToSha1Hash()}"; } var input = new PublishedNetworkMessageSchemaModel { Id = id, Version = (ulong)_metadataChanges, DataSetMessages = datasetSchemaMetadata, NetworkMessageContentFlags = writerGroup.MessageSettings?.NetworkMessageContentMask }; #if DUMP_METADATA #pragma warning disable CA1869 // Cache and reuse 'JsonSerializerOptions' instances System.IO.File.WriteAllText( $"md_{DateTimeOffset.UtcNow.ToBinary()}_{writerGroup.Id}_{_metadataChanges}.json", System.Text.Json.JsonSerializer.Serialize(input, new System.Text.Json.JsonSerializerOptions { WriteIndented = true })); #pragma warning restore CA1869 // Cache and reuse 'JsonSerializerOptions' instances #endif try { if (PubSubMessage.TryCreateNetworkMessageSchema(encoding, input, out schema, _options.Value.SchemaOptions)) { schemaGroup = new SchemaGroup(topic, (ulong)_metadataChanges, schema); _schemaGroups.AddOrUpdate(topic, schemaGroup, (_, _) => schemaGroup); return; } _logger.FailedToCreateSchema(encoding, writerGroup.Id); } catch (Exception ex) { _logger.FailedToCreateSchemaWithException(ex, encoding, writerGroup.Id); } schema = null; } finally { _lock.Release(); } } /// /// Manages a schema and metadata for a group of writers /// /// /// /// private sealed record class SchemaGroup(string Topic, ulong Version, IEventSchema Schema); /// /// Runtime duration /// private double UpTime => _timeProvider.GetElapsedTime(_startTime).TotalSeconds; private IEnumerable UsedClients => _writers.Values .Select(s => s.Subscription?.ClientDiagnostics!) .Where(s => s != null) .Distinct(); private IEnumerable UsedSubscriptions => _writers.Values .Select(s => s.Subscription?.Diagnostics!) .Where(s => s != null) .Distinct(); private int TotalItems => _writers.Values .SelectMany(s => s.MonitoredItems).Count(); private int ReconnectCount => UsedClients .Sum(s => s.ReconnectCount); private int ReconnectTriggered => UsedClients .Count(s => s.ReconnectTriggered); private int KeepAliveTotal => UsedClients .Sum(s => s.KeepAliveTotal); private int KeepAliveCounter => UsedClients .Sum(s => s.KeepAliveCounter); private int ConnectCount => UsedClients .Sum(s => s.ConnectCount); private int OutstandingRequestCount => UsedClients .Sum(s => s.OutstandingRequestCount); private int GoodPublishRequestCount => UsedClients .Sum(s => s.GoodPublishRequestCount); private int BadPublishRequestCount => UsedClients .Sum(s => s.BadPublishRequestCount); private int MinPublishRequestCount => UsedClients .Sum(s => s.MinPublishRequestCount); private int ConnectedClients => UsedClients .Count(s => s.State == EndpointConnectivityState.Ready); private int DisconnectedClients => UsedClients .Count(s => s.State != EndpointConnectivityState.Ready); private int GoodMonitoredItems => UsedSubscriptions .Sum(s => s.GoodMonitoredItems); private int BadMonitoredItems => UsedSubscriptions .Sum(s => s.BadMonitoredItems); private int LateMonitoredItems => UsedSubscriptions .Sum(s => s.LateMonitoredItems); private int HeartbeatsEnabled => UsedSubscriptions .Sum(s => s.HeartbeatsEnabled); private int ConditionsEnabled => UsedSubscriptions .Sum(s => s.ConditionsEnabled); /// /// Create observable metrics /// private void InitializeMetrics() { _meter.CreateObservableUpDownCounter("iiot_edge_publisher_metadata_changes", () => new Measurement(_metadataChanges, _metrics.TagList), description: "Number of metadata changes."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_good_metadata", () => new Measurement(_metadataLoadSuccess, _metrics.TagList), description: "Number of successful metadata load operations."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_bad_metadata", () => new Measurement(_metadataLoadFailures, _metrics.TagList), description: "Number of failed metadata load operations."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_messages_without_metadata", () => new Measurement(_messagesWithoutMetadata, _metrics.TagList), description: "Number of messages dropped because metadata was missing in time."); // --- collected by publisher collector: _meter.CreateObservableCounter("iiot_edge_publisher_heartbeats", () => new Measurement(_heartbeats.Count, _metrics.TagList), description: "Total Heartbeats delivered for processing."); _meter.CreateObservableGauge("iiot_edge_publisher_heartbeats_per_second", () => new Measurement(_heartbeats.Count / UpTime, _metrics.TagList), description: "Opc Cyclic reads/second delivered for processing."); _meter.CreateObservableGauge("iiot_edge_publisher_heartbeats_per_second_last_min", () => new Measurement(_heartbeats.LastMinute, _metrics.TagList), description: "Opc Cyclic reads/second delivered for processing in last 60s."); _meter.CreateObservableCounter("iiot_edge_publisher_sampledvalues", () => new Measurement(_sampledValues.Count, _metrics.TagList), description: "Total sampled values delivered for processing."); _meter.CreateObservableGauge("iiot_edge_publisher_sampledvalues_per_second", () => new Measurement(_sampledValues.Count / UpTime, _metrics.TagList), description: "Opc sampled values/second delivered for processing."); _meter.CreateObservableGauge("iiot_edge_publisher_sampledvalues_per_second_last_min", () => new Measurement(_sampledValues.LastMinute, _metrics.TagList), description: "Opc sampled values/second delivered for processing in last 60s."); _meter.CreateObservableCounter("iiot_edge_publisher_modelchanges", () => new Measurement(_modelChanges.Count, _metrics.TagList), description: "Total Number of changes found in the address spaces of the connected servers."); _meter.CreateObservableGauge("iiot_edge_publisher_modelchanges_per_second", () => new Measurement(_modelChanges.Count / UpTime, _metrics.TagList), description: "Address space Model changes/second delivered for processing."); _meter.CreateObservableGauge("iiot_edge_publisher_modelchanges_per_second_last_min", () => new Measurement(_modelChanges.LastMinute, _metrics.TagList), description: "Address space Model changes/second delivered for processing in last 60s."); _meter.CreateObservableCounter("iiot_edge_publisher_value_changes", () => new Measurement(_valueChanges.Count, _metrics.TagList), description: "Total Opc Value changes delivered for processing."); _meter.CreateObservableGauge("iiot_edge_publisher_value_changes_per_second", () => new Measurement(_valueChanges.Count / UpTime, _metrics.TagList), description: "Opc Value changes/second delivered for processing."); _meter.CreateObservableGauge("iiot_edge_publisher_value_changes_per_second_last_min", () => new Measurement(_valueChanges.LastMinute, _metrics.TagList), description: "Opc Value changes/second delivered for processing in last 60s."); _meter.CreateObservableCounter("iiot_edge_publisher_events", () => new Measurement(_events.Count, _metrics.TagList), description: "Total Opc Events delivered for processing."); _meter.CreateObservableGauge("iiot_edge_publisher_events_per_second", () => new Measurement(_events.Count / UpTime, _metrics.TagList), description: "Opc Events/second delivered for processing."); _meter.CreateObservableGauge("iiot_edge_publisher_events_per_second_last_min", () => new Measurement(_events.LastMinute, _metrics.TagList), description: "Opc Events/second delivered for processing in last 60s."); _meter.CreateObservableCounter("iiot_edge_publisher_event_notifications", () => new Measurement(_eventNotification.Count, _metrics.TagList), description: "Total Opc Event notifications delivered for processing."); _meter.CreateObservableGauge("iiot_edge_publisher_event_notifications_per_second", () => new Measurement(_eventNotification.Count / UpTime, _metrics.TagList), description: "Opc Event notifications/second delivered for processing."); _meter.CreateObservableGauge("iiot_edge_publisher_event_notifications_per_second_last_min", () => new Measurement(_eventNotification.LastMinute, _metrics.TagList), description: "Opc Event notifications/second delivered for processing in last 60s."); _meter.CreateObservableCounter("iiot_edge_publisher_data_changes", () => new Measurement(_dataChanges.Count, _metrics.TagList), description: "Total Opc Data change notifications delivered for processing."); _meter.CreateObservableGauge("iiot_edge_publisher_data_changes_per_second", () => new Measurement(_dataChanges.Count / UpTime, _metrics.TagList), description: "Opc Data change notifications/second delivered for processing."); _meter.CreateObservableGauge("iiot_edge_publisher_data_changes_per_second_last_min", () => new Measurement(_dataChanges.LastMinute, _metrics.TagList), description: "Opc Data change notifications/second delivered for processing in last 60s."); _meter.CreateObservableCounter("iiot_edge_publisher_cyclicreads", () => new Measurement(_cyclicReads.Count, _metrics.TagList), description: "Total Cyclic reads delivered for processing."); _meter.CreateObservableGauge("iiot_edge_publisher_cyclicreads_per_second", () => new Measurement(_cyclicReads.Count / UpTime, _metrics.TagList), description: "Opc Cyclic reads/second delivered for processing."); _meter.CreateObservableGauge("iiot_edge_publisher_cyclicreads_per_second_last_min", () => new Measurement(_cyclicReads.LastMinute, _metrics.TagList), description: "Opc Cyclic reads/second delivered for processing in last 60s."); _meter.CreateObservableCounter("iiot_edge_publisher_queue_overflows", () => new Measurement(_overflows.Count, _metrics.TagList), description: "Total values received with a queue overflow indicator."); _meter.CreateObservableGauge("iiot_edge_publisher_queue_overflows_per_second", () => new Measurement(_overflows.Count / UpTime, _metrics.TagList), description: "Values with overflow indicator/second received."); _meter.CreateObservableGauge("iiot_edge_publisher_queue_overflows_per_second_last_min", () => new Measurement(_overflows.LastMinute, _metrics.TagList), description: "Values with overflow indicator/second received in last 60s."); _meter.CreateObservableCounter("iiot_edge_publisher_keep_alive_notifications", () => new Measurement(_keepAliveCount, _metrics.TagList), description: "Total Opc keep alive notifications delivered for processing."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_connection_retries", () => new Measurement(ReconnectCount, _metrics.TagList), description: "OPC UA total connect retries."); _meter.CreateObservableGauge("iiot_edge_publisher_connection_reconnecting", () => new Measurement(ReconnectTriggered, _metrics.TagList), description: "OPC UA total connections reconnecting right now."); _meter.CreateObservableGauge("iiot_edge_publisher_connection_successful_keepalives", () => new Measurement(KeepAliveCounter, _metrics.TagList), description: "OPC UA keepalives on all connections since last reconnect."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_connection_total_keepalives", () => new Measurement(KeepAliveTotal, _metrics.TagList), description: "OPC UA total successful keep alives on all connections."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_connections", () => new Measurement(ConnectCount, _metrics.TagList), description: "OPC UA total connection success count."); _meter.CreateObservableGauge("iiot_edge_publisher_is_connection_ok", () => new Measurement(ConnectedClients, _metrics.TagList), description: "OPC UA endpoints that are successfully connected."); _meter.CreateObservableGauge("iiot_edge_publisher_is_disconnected", () => new Measurement(DisconnectedClients, _metrics.TagList), description: "OPC UA endpoints that are disconnected."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_writer_count", () => new Measurement(_writers.Count, _metrics.TagList), description: "Number of writers in the writer group."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_writer_nodes", () => new Measurement(TotalItems, _metrics.TagList), description: "Total monitored item count."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_writer_good_nodes", () => new Measurement(GoodMonitoredItems, _metrics.TagList), description: "Monitored items successfully created."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_writer_bad_nodes", () => new Measurement(BadMonitoredItems, _metrics.TagList), description: "Monitored items that were not successfully created."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_writer_late_nodes", () => new Measurement(LateMonitoredItems, _metrics.TagList), description: "Monitored items that are late reporting."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_writer_heartbeat_enabled_nodes", () => new Measurement(HeartbeatsEnabled, _metrics.TagList), description: "Monitored items with heartbeats enabled."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_writer_condition_enabled_nodes", () => new Measurement(ConditionsEnabled, _metrics.TagList), description: "Monitored items with condition monitoring enabled."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_publish_requests_client_totals", () => new Measurement(OutstandingRequestCount, _metrics.TagList), description: "Total good publish requests used by all clients used by the writer group."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_good_publish_requests_client_totals", () => new Measurement(GoodPublishRequestCount, _metrics.TagList), description: "Total good publish requests used by all clients used by the writer group."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_bad_publish_requests_client_totals", () => new Measurement(BadPublishRequestCount, _metrics.TagList), description: "Total bad publish requests used by all clients used by the writer group."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_min_publish_requests_client_totals", () => new Measurement(MinPublishRequestCount, _metrics.TagList), description: "Total min publish requests queued by all clients used by the writer group."); } private const long kNumberOfInvokedMessagesResetThreshold = long.MaxValue - 10000; private readonly ConcurrentDictionary _writers = new(); private readonly ConcurrentDictionary _schemaGroups = new(); private readonly Meter _meter = Diagnostics.NewMeter(); private readonly ILoggerFactory _loggerFactory; private readonly IJsonSerializer _serializer; private readonly IMessageSink _sink; private readonly ILogger _logger; private readonly TimeProvider _timeProvider; private readonly long _startTime; private readonly IOpcUaClientManager _clients; private readonly IMetricsContext _metrics; private readonly IOptions _options; private readonly SemaphoreSlim _lock = new(1, 1); private readonly RollingAverage _valueChanges; private readonly RollingAverage _dataChanges; private readonly RollingAverage _sampledValues; private readonly RollingAverage _cyclicReads; private readonly RollingAverage _eventNotification; private readonly RollingAverage _events; private readonly RollingAverage _modelChanges; private readonly RollingAverage _heartbeats; private readonly RollingAverage _overflows; private WriterGroupModel _writerGroup; private long _keepAliveCount; private int _messagesWithoutMetadata; private int _metadataLoadSuccess; private int _metadataLoadFailures; private int _metadataChanges; } /// /// Source-generated logging extensions for WriterGroupDataSource /// internal static partial class WriterGroupDataSourceLogging { private const int EventClass = 360; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Information, Message = "Removed all subscriptions from writer group {WriterGroup}.")] public static partial void RemovedAllSubscriptions(this ILogger logger, string writerGroup); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Debug, Message = "Successfully updated all writers inside the writer group {WriterGroup}.")] public static partial void UpdatedAllWriters(this ILogger logger, string writerGroup); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Warning, Message = "Failed to create schema for {Encoding} encoded messages for writer group {WriterGroup} because dataset metadata was null.")] public static partial void FailedToCreateSchemaMissingMetadata(this ILogger logger, MessageEncoding encoding, string writerGroup); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Warning, Message = "Failed to create schema for {Encoding} encoded messages for writer group {WriterGroup}.")] public static partial void FailedToCreateSchema(this ILogger logger, MessageEncoding encoding, string writerGroup); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Error, Message = "Failed to create schema for {Encoding} encoded messages for writer group {WriterGroup}.")] public static partial void FailedToCreateSchemaWithException(this ILogger logger, Exception ex, MessageEncoding encoding, string writerGroup); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Debug, Message = "Multiple dataset metadata found for topic {Topic} in writer group {WriterGroup}. Using hash to create unique id.")] public static partial void MultiDataSetSchema(this ILogger logger, string topic, string writerGroup); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Services/WriterGroupScopeFactory.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Services { using Azure.IIoT.OpcUa.Publisher; using Azure.IIoT.OpcUa.Publisher.Models; using Autofac; using Furly.Extensions.Serializers; using Microsoft.Extensions.Options; using System.Collections.Generic; using System.Diagnostics; /// /// Container builder for data set writer jobs /// public class WriterGroupScopeFactory : IWriterGroupScopeFactory { /// /// Create job scope factory /// /// /// /// /// public WriterGroupScopeFactory(ILifetimeScope lifetimeScope, IJsonSerializer serializer, IOptions? options = null, IDiagnosticCollector? collector = null) { _lifetimeScope = lifetimeScope; _serializer = serializer; _collector = collector; _options = options; } /// public IWriterGroupScope Create(WriterGroupModel writerGroup) { return new WriterGroupScope(this, writerGroup, _serializer); } /// /// Scope wrapper /// private sealed class WriterGroupScope : IWriterGroupScope, IMetricsContext, IWriterGroupDiagnostics { /// public IWriterGroupControl WriterGroup => _scope.Resolve(); /// public TagList TagList { get; } /// /// Create scope /// /// /// /// public WriterGroupScope(WriterGroupScopeFactory outer, WriterGroupModel writerGroup, IJsonSerializer serializer) { _outer = outer; _writerGroupId = writerGroup.Id; TagList = new TagList( [ new KeyValuePair(Constants.SiteIdTag, _outer._options?.Value.SiteId), new KeyValuePair(Constants.PublisherIdTag, writerGroup.PublisherId ?? _outer._options?.Value.PublisherId), new KeyValuePair(Constants.WriterGroupIdTag, _writerGroupId), new KeyValuePair(Constants.WriterGroupNameTag, writerGroup.Name) ]); _scope = _outer._lifetimeScope.BeginLifetimeScope(builder => { // Register writer group for the scope builder.RegisterInstance(writerGroup).As(); builder.RegisterInstance(this) .As() .As().SingleInstance(); builder.RegisterInstance(serializer) .As() .ExternallyOwned(); // Register data flow, source, encode builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); }); ResetWriterGroupDiagnostics(); } /// public void ResetWriterGroupDiagnostics() { _outer._collector?.ResetWriterGroup(_writerGroupId); } /// public void Dispose() { _outer._collector?.RemoveWriterGroup(_writerGroupId); _scope.Dispose(); } private readonly string _writerGroupId; private readonly WriterGroupScopeFactory _outer; private readonly ILifetimeScope _scope; } private readonly ILifetimeScope _lifetimeScope; private readonly IJsonSerializer _serializer; private readonly IDiagnosticCollector? _collector; private readonly IOptions? _options; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/AsyncEnumerableBase.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { using Azure.IIoT.OpcUa.Publisher.Stack.Models; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; /// /// Async enumerable operation /// /// public abstract class AsyncEnumerableBase { /// /// Returns whether the operation is completed /// public abstract bool HasMore { get; } /// /// Reset the enumeration /// public abstract void Reset(); /// /// Execute /// /// /// public virtual async ValueTask> ExecuteAsync( ServiceCallContext context) { var result = await RunAsync(context).ConfigureAwait(false); return result.YieldReturn(); } /// /// Execute /// /// /// protected abstract ValueTask RunAsync(ServiceCallContext context); /// /// Dispose /// public virtual void Dispose() { } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/AsyncEnumerableStack.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { using Azure.IIoT.OpcUa.Publisher.Stack.Models; using System; using System.Collections.Generic; using System.Threading.Tasks; /// /// Wraps a stack /// /// public abstract class AsyncEnumerableEnumerableStack : AsyncEnumerableBase { /// public override bool HasMore => _ops.Count > 0; /// public override void Reset() { _ops.Clear(); } /// public override async ValueTask> ExecuteAsync(ServiceCallContext context) { var func = _ops.Pop(); var cur = _ops.Count; try { return await func.Invoke(context).ConfigureAwait(false); } catch { if (_ops.Count == cur) { _ops.Push(func); } throw; } } /// protected void Push(Func>> value) { _ops.Push(value); } /// protected override ValueTask RunAsync(ServiceCallContext context) { throw new NotSupportedException(); } private readonly Stack>>> _ops = new(); } /// /// Wraps a stack /// /// public abstract class AsyncEnumerableStack : AsyncEnumerableBase { /// public override bool HasMore => _ops.Count > 0; /// public override void Reset() { _ops.Clear(); } /// protected void Push(Func> value) { _ops.Push(value); } /// protected override async ValueTask RunAsync(ServiceCallContext context) { var func = _ops.Pop(); var cur = _ops.Count; try { return await func.Invoke(context).ConfigureAwait(false); } catch { if (_ops.Count == cur) { _ops.Push(func); } throw; } } private readonly Stack>> _ops = new(); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/AssetsEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Extensions { using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Opc.Ua; using System; using System.Linq; using System.Threading; using System.Threading.Tasks; /// /// Asset and Web of things connectivity /// public static class AssetsEx { /// /// Create asset /// /// /// /// /// /// public static async Task<(NodeId?, ServiceResultModel?)> CreateAssetAsync( this IOpcUaSession session, RequestHeader header, string assetName, CancellationToken ct) { var nsIndex = session.MessageContext.NamespaceUris.GetIndex(kNamespace); if (nsIndex < 0) { return (null, new ServiceResultModel { StatusCode = StatusCodes.BadNotSupported, ErrorMessage = "Namespace not found - asset connectivity not supported." }); } try { // Call create method var request = new CallMethodRequestCollection { new CallMethodRequest { ObjectId = new NodeId(kAsset_Root, (ushort)nsIndex), MethodId = new NodeId(kAsset_CreateAsset, (ushort)nsIndex), InputArguments = new [] { new Variant(assetName) } } }; var response = await session.Services.CallAsync(header, request, ct).ConfigureAwait(false); var results = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, request); if (results.ErrorInfo != null) { return (null, results.ErrorInfo); } if (results[0].ErrorInfo != null || results[0].Result?.OutputArguments == null || results[0].Result.OutputArguments.Count == 0 || results[0].Result.OutputArguments[0].Value is not NodeId assetNodeId) { return (null, results[0].ErrorInfo ?? new ServiceResultModel { ErrorMessage = "no asset node id returned." }); } return (assetNodeId, null); } catch (Exception ex) { return (null, ex.ToServiceResultModel()); } } /// /// Get the node id of the asset file under the asset /// /// /// /// /// /// public static async Task<(NodeId?, ServiceResultModel?)> GetAssetFileAsync( this IOpcUaSession session, RequestHeader header, NodeId assetId, CancellationToken ct) { var nsIndex = session.MessageContext.NamespaceUris.GetIndex(kNamespace); if (nsIndex < 0) { return (null, new ServiceResultModel { StatusCode = StatusCodes.BadNotSupported, ErrorMessage = "Namespace not found - asset connectivity not supported." }); } var (results, errorInfo) = await session.FindAsync(header, assetId.YieldReturn(), ReferenceTypeIds.HasComponent, true, nodeClassMask: (uint)Opc.Ua.NodeClass.Object, ct: ct).ConfigureAwait(false); if (errorInfo != null) { return (null, errorInfo); } var fileNodeId = results .FirstOrDefault(f => f.ErrorInfo == null && f.TypeDefinition.NamespaceIndex == nsIndex && f.TypeDefinition.Identifier.Equals(kAssetFileType)); if (!NodeId.IsNull(fileNodeId.Node)) { return (fileNodeId.Node, null); } errorInfo = results.FirstOrDefault(d => d.ErrorInfo != null).ErrorInfo; errorInfo ??= new ServiceResultModel { StatusCode = StatusCodes.BadNotFound, ErrorMessage = "No file found for asset." }; return (null, errorInfo); } /// /// Delete asset /// /// /// /// /// /// public static async Task DeleteAssetAsync(this IOpcUaSession session, RequestHeader header, NodeId assetId, CancellationToken ct) { var nsIndex = session.MessageContext.NamespaceUris.GetIndex(kNamespace); if (nsIndex < 0) { return new ServiceResultModel { StatusCode = StatusCodes.BadNotSupported, ErrorMessage = "Namespace not found - asset connectivity not supported." }; } try { // Call create method var request = new CallMethodRequestCollection { new CallMethodRequest { ObjectId = new NodeId(kAsset_Root, (ushort)nsIndex), MethodId = new NodeId(kAsset_DeleteAsset, (ushort)nsIndex), InputArguments = new [] { new Variant(assetId) } } }; var response = await session.Services.CallAsync(header, request, ct).ConfigureAwait(false); var results = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, request); return results.ErrorInfo; } catch (Exception ex) { return ex.ToServiceResultModel(); } } /// /// Close file handle of file and kick off the update /// /// /// /// /// /// /// public static async Task CloseAndUpdateAsync(this IOpcUaSession session, RequestHeader header, NodeId fileNodeId, uint fileHandle, CancellationToken ct) { var nsIndex = session.MessageContext.NamespaceUris.GetIndex(kNamespace); if (nsIndex < 0) { return new ServiceResultModel { StatusCode = StatusCodes.BadNotSupported, ErrorMessage = "Namespace not found - asset connectivity not supported." }; } return await session.CloseAsync(header, fileNodeId, new NodeId( kAssetFileType_CloseAndUpdate, (ushort)nsIndex), fileHandle, ct).ConfigureAwait(false); } /// /// Get root asset node id /// public static string Root => $"nsu={kNamespace};i={kAsset_Root}"; private const string kNamespace = "http://opcfoundation.org/UA/WoT-Con/"; private const uint kAsset_Root = 31; private const uint kAsset_CreateAsset = 32; private const uint kAsset_DeleteAsset = 35; private const uint kAssetFileType = 110; private const uint kAssetFileType_CloseAndUpdate = 111; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/CertificateStoreEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Opc.Ua { using Azure.IIoT.OpcUa.Publisher.Stack; using Furly.Extensions.Utils; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; /// /// Certificate store extensions /// public static class CertificateStoreEx { /// /// Add to certificate store /// /// /// /// /// /// /// /// is null. public static async Task AddAsync(this ICertificateStore store, IEnumerable certificates, bool noCopy = false, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(certificates); foreach (var cert in certificates) { await Try.Async(() => store.DeleteAsync(cert.Thumbprint, ct)).ConfigureAwait(false); #pragma warning disable CA2000 // Dispose objects before losing scope await store.AddAsync(noCopy ? cert : new X509Certificate2(cert), ct: ct).ConfigureAwait(false); #pragma warning restore CA2000 // Dispose objects before losing scope } } /// /// Remove from certificate store /// /// /// /// /// /// /// is null. public static async Task RemoveAsync(this ICertificateStore store, IEnumerable certificates, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(certificates); foreach (var cert in certificates) { await store.DeleteAsync(cert.Thumbprint, ct).ConfigureAwait(false); } } /// /// Apply the configured settings provided via a CertificateStore to a /// CertificateTrustList. /// /// /// /// /// is null. public static void ApplyLocalConfig( this CertificateTrustList certificateTrustList, CertificateStore? certificateStore) { ArgumentNullException.ThrowIfNull(certificateTrustList); if (certificateStore == null) { return; } if (certificateTrustList.StorePath != certificateStore.StorePath) { certificateTrustList.StoreType = certificateStore.StoreType; certificateTrustList.StorePath = certificateStore.StorePath; } } /// /// Applies the configuration settings to the own app certificate. /// /// /// /// /// is null. public static void ApplyLocalConfig( this CertificateIdentifierCollection certificateIdentifiers, CertificateInfo? certificateStore) { ArgumentNullException.ThrowIfNull(certificateIdentifiers); if (certificateStore == null) { return; } foreach (var certificateIdentifier in certificateIdentifiers) { if (certificateIdentifier.StorePath != certificateStore.StorePath) { certificateIdentifier.StoreType = certificateStore.StoreType; certificateIdentifier.StorePath = certificateStore.StorePath; } } } /// /// Applies the configuration settings to the own app certificate. /// /// /// /// /// /// is null. public static ICertificateStore OpenStore( this CertificateIdentifierCollection certificateIdentifiers, SecurityOptions options, bool noPrivateKey = false) { ArgumentNullException.ThrowIfNull(certificateIdentifiers); if (certificateIdentifiers.Count > 0) { Debug.Assert(certificateIdentifiers .All(x => x.StorePath == certificateIdentifiers[0].StorePath)); Debug.Assert(certificateIdentifiers .All(x => x.StoreType == certificateIdentifiers[0].StoreType)); return certificateIdentifiers[0].OpenStore(); } ArgumentNullException.ThrowIfNull(options.ApplicationCertificates); return new CertificateStoreIdentifier(options.ApplicationCertificates.StorePath, options.ApplicationCertificates.StoreType, noPrivateKey).OpenStore(); } /// /// Apply the configured settings provided via a CertificateStore to a /// CertificateStoreIdentifier. Particularily used for rejected /// certificates store. /// /// /// /// /// is null. public static void ApplyLocalConfig( this CertificateStoreIdentifier certificateStoreIdentifier, CertificateStore? certificateStore) { ArgumentNullException.ThrowIfNull(certificateStoreIdentifier); if (certificateStore == null) { return; } if (certificateStoreIdentifier.StorePath != certificateStore.StorePath) { certificateStoreIdentifier.StoreType = certificateStore.StoreType; certificateStoreIdentifier.StorePath = certificateStore.StorePath; } } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/CertificateTrustListEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Opc.Ua { using System; using System.Collections.Generic; using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; /// /// Certificate trust list extensions /// public static class CertificateTrustListEx { /// /// Remove certficates /// /// /// /// /// /// is null. public static async Task RemoveAsync(this CertificateTrustList trustList, IEnumerable certificates, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(certificates); using var trustedStore = trustList.OpenStore(); await trustedStore.RemoveAsync(certificates, ct).ConfigureAwait(false); foreach (var cert in certificates) { trustList.TrustedCertificates.Remove(new CertificateIdentifier(cert)); } } /// /// Add to trust list /// /// /// /// /// /// /// is null. public static async Task AddAsync(this CertificateTrustList trustList, IEnumerable certificates, bool noCopy = false, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(certificates); using var trustedStore = trustList.OpenStore(); await trustedStore.AddAsync(certificates, noCopy, ct: ct).ConfigureAwait(false); foreach (var cert in certificates) { #pragma warning disable CA2000 // Dispose objects before losing scope trustList.TrustedCertificates.Add(new CertificateIdentifier( noCopy ? cert : new X509Certificate2(cert))); #pragma warning restore CA2000 // Dispose objects before losing scope } } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/ContainerBuilderEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { using Azure.IIoT.OpcUa.Publisher.Stack.Runtime; using Azure.IIoT.OpcUa.Publisher.Stack.Services; using Azure.IIoT.OpcUa.Publisher.Parser; using Azure.IIoT.OpcUa.Encoders; using Autofac; /// /// Container builder extensions /// public static class ContainerBuilderEx { /// /// Configure services /// /// public static void AddOpcUaStack(this ContainerBuilder builder) { builder.RegisterInstance(IMetricsContext.Empty) .AsImplementedInterfaces().IfNotRegistered(typeof(IMetricsContext)); builder.RegisterType() .AsImplementedInterfaces().SingleInstance().AutoActivate(); builder.RegisterType() .AsImplementedInterfaces().SingleInstance().AutoActivate(); builder.RegisterType() .AsImplementedInterfaces().SingleInstance(); builder.RegisterType() .AsImplementedInterfaces().SingleInstance(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/DataValueEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Opc.Ua.Extensions { using Opc.Ua; using System; using System.Diagnostics.CodeAnalysis; /// /// Datavalue extensions /// public static class DataValueEx { /// /// Unpack with a default value /// /// /// /// /// /// [return: NotNullIfNotNull(nameof(defaultValue))] public static T? GetValueOrDefaultEx(this DataValue dataValue, Func convert, T? defaultValue = default) { var result = GetValueOrDefaultEx(dataValue, defaultValue); return convert(result); } /// /// Unpack with a default value /// /// /// /// /// [return: NotNullIfNotNull(nameof(defaultValue))] public static T? GetValueOrDefaultEx(this DataValue dataValue, T? defaultValue = default) { if (dataValue == null) { return defaultValue; } var value = dataValue.Value; if (value == null) { return defaultValue; } while (typeof(T).IsEnum) { try { return (T)Enum.ToObject(typeof(T), value); } catch { break; } } while (!typeof(T).IsInstanceOfType(value)) { try { return value.As(); } catch { break; } } try { return (T)value; } catch { return defaultValue; } } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/DiscoveredEndpointModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Models { using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Extensions.Serializers; using System.Collections.Generic; /// /// Discovered Endpoint Model extensions /// public static class DiscoveredEndpointModelEx { /// /// Create server model /// /// /// /// /// /// /// public static ApplicationRegistrationModel ToServiceModel(this DiscoveredEndpointModel result, string hostAddress, string? siteId, string discovererId, IJsonSerializer serializer) { var type = result.Description.Server.ApplicationType.ToServiceType() ?? ApplicationType.Server; return new ApplicationRegistrationModel { Application = new ApplicationInfoModel { SiteId = siteId ?? discovererId, DiscovererId = discovererId, ApplicationType = type, ApplicationId = ApplicationInfoModelEx.CreateApplicationId(siteId ?? discovererId, result.Description.Server.ApplicationUri, type), ProductUri = result.Description.Server.ProductUri, ApplicationUri = result.Description.Server.ApplicationUri, DiscoveryUrls = new HashSet(result.Description.Server.DiscoveryUrls), DiscoveryProfileUri = result.Description.Server.DiscoveryProfileUri, HostAddresses = new HashSet { hostAddress }, ApplicationName = result.Description.Server.ApplicationName.Text, LocalizedNames = string.IsNullOrEmpty(result.Description.Server.ApplicationName.Locale) ? null : new Dictionary { [result.Description.Server.ApplicationName.Locale] = result.Description.Server.ApplicationName.Text }, NotSeenSince = null, Capabilities = new HashSet(result.Capabilities) }, Endpoints = new List { new() { SiteId = siteId, DiscovererId = discovererId, Id = string.Empty, SecurityLevel = result.Description.SecurityLevel, AuthenticationMethods = result.Description.UserIdentityTokens .ToServiceModel(serializer), EndpointUrl = result.Description.EndpointUrl, // Reported Endpoint = new EndpointModel { Url = result.AccessibleEndpointUrl, // Accessible AlternativeUrls = new HashSet { result.AccessibleEndpointUrl, result.Description.EndpointUrl }, Certificate = result.Description.ServerCertificate?.ToThumbprint(), SecurityMode = result.Description.SecurityMode.ToServiceType() ?? SecurityMode.None, SecurityPolicy = result.Description.SecurityPolicyUri } } } }; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/DiscoveryClientEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ // #define USE_TASK_RUN namespace Opc.Ua.Client { using System; using System.Threading.Tasks; /// /// Discovery Client async extensions /// public static class DiscoveryClientEx { /// /// Async find servers service /// /// /// /// /// /// /// public static Task FindServersAsync(this DiscoveryClient client, RequestHeader requestHeader, string endpointUrl, StringCollection? localeIds, StringCollection? serverUris) { #if !USE_TASK_RUN return Task.Factory.FromAsync( (callback, state) => client.BeginFindServers(requestHeader, endpointUrl, localeIds, serverUris, callback, state), result => { var response = client.EndFindServers(result, out var results); return NewFindServersResponse(response, results); }, TaskCreationOptions.DenyChildAttach); #else return Task.Run(() => { var response = client.FindServers(requestHeader, endpointUrl, localeIds, serverUris, out var results); return NewFindServersResponse(response, results); }); #endif } /// /// Async find servers on network service /// /// /// /// /// /// /// public static Task FindServersOnNetworkAsync( this DiscoveryClient client, RequestHeader requestHeader, uint startingRecordId, uint maxRecordsToReturn, StringCollection serverCapabilityFilter) { #if !USE_TASK_RUN return Task.Factory.FromAsync( (callback, state) => client.BeginFindServersOnNetwork(requestHeader, startingRecordId, maxRecordsToReturn, serverCapabilityFilter, callback, state), result => { var response = client.EndFindServersOnNetwork(result, out var lastCounterResetTime, out var servers); return NewFindServersOnNetworkResponse(response, lastCounterResetTime, servers); }, TaskCreationOptions.DenyChildAttach); #else return Task.Run(() => { var response = client.FindServersOnNetwork(requestHeader, startingRecordId, maxRecordsToReturn, serverCapabilityFilter, out var lastCounterResetTime, out var servers); return NewFindServersOnNetworkResponse(response, lastCounterResetTime, servers); }); #endif } /// /// Async get endpoints service /// /// /// /// /// /// /// public static Task GetEndpointsAsync( this DiscoveryClient client, RequestHeader requestHeader, string endpointUrl, StringCollection? localeIds, StringCollection? profileUris) { #if !USE_TASK_RUN return Task.Factory.FromAsync( (callback, state) => client.BeginGetEndpoints(requestHeader, endpointUrl, localeIds, profileUris, callback, state), result => { var response = client.EndGetEndpoints(result, out var endpoints); return NewGetEndpointsResponse(response, endpoints); }, TaskCreationOptions.DenyChildAttach); #else return Task.Run(() => { var response = client.GetEndpoints(requestHeader, endpointUrl, localeIds, profileUris, out var endpoints); return NewGetEndpointsResponse(response, endpoints); }); #endif } /// /// Get endpoints response constructor /// /// /// /// private static GetEndpointsResponse NewGetEndpointsResponse(ResponseHeader response, EndpointDescriptionCollection endpoints) { return new GetEndpointsResponse { Endpoints = endpoints, ResponseHeader = response }; } /// /// Find servers on network response constructor /// /// /// /// /// private static FindServersOnNetworkResponse NewFindServersOnNetworkResponse( ResponseHeader response, DateTime lastCounterResetTime, ServerOnNetworkCollection servers) { return new FindServersOnNetworkResponse { ResponseHeader = response, Servers = servers, LastCounterResetTime = lastCounterResetTime }; } /// /// Find servers response constructor /// /// /// /// private static FindServersResponse NewFindServersResponse(ResponseHeader response, ApplicationDescriptionCollection results) { return new FindServersResponse { ResponseHeader = response, Servers = results }; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/EndpointDescriptionEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Opc.Ua { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; /// /// Endpoint description extensions /// public static class EndpointDescriptionEx { /// /// Matches model /// /// /// /// public static bool IsSameAs(this EndpointDescription endpoint, EndpointModel model) { if (endpoint.SecurityMode.IsSame(model.SecurityMode ?? SecurityMode.SignAndEncrypt)) { return false; } if (string.IsNullOrEmpty(model.SecurityPolicy)) { return true; } return endpoint.SecurityPolicyUri == model.SecurityPolicy; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/FileSystemEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Extensions { using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Opc.Ua; using Opc.Ua.Extensions; using System; using System.Buffers; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; /// /// File system methods /// public static class FileSystemEx { /// /// Get file info /// /// /// /// /// /// public static async Task<(FileInfoModel?, ServiceResultModel?)> GetFileInfoAsync( this IOpcUaSession session, RequestHeader header, NodeId nodeId, CancellationToken ct = default) { try { var browsePaths = new string[] { BrowseNames.Size, BrowseNames.Writable, BrowseNames.UserWritable, BrowseNames.OpenCount, BrowseNames.MimeType, BrowseNames.MaxByteStringLength, BrowseNames.LastModifiedTime }; var response = await session.Services.TranslateBrowsePathsToNodeIdsAsync( header, browsePaths.Select(b => new BrowsePath { StartingNode = nodeId, RelativePath = new RelativePath(b) }).ToArray(), ct).ConfigureAwait(false); Debug.Assert(response != null); var results = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, browsePaths); if (results.ErrorInfo != null) { return (null, results.ErrorInfo); } if (results.All(r => r.ErrorInfo != null)) { return (null, new ServiceResultModel { StatusCode = StatusCodes.BadNotFound, ErrorMessage = "File info not found." }); } var read = await session.Services.ReadAsync(header, 0.0, Opc.Ua.TimestampsToReturn.Neither, results .Select(r => r.Result.Targets.Count > 0 ? r.Result.Targets[0].TargetId : ExpandedNodeId.Null) .Select(n => new ReadValueId { AttributeId = Attributes.Value, NodeId = n.ToNodeId(session.MessageContext.NamespaceUris) }) .ToArray(), ct).ConfigureAwait(false); var values = read.Validate(read.Results, r => r.StatusCode, read.DiagnosticInfos, browsePaths); if (values.ErrorInfo != null) { return (null, results.ErrorInfo); } return (new FileInfoModel { Size = values[0].Result?.Value as long? ?? 0, // Writable = values[2].Result?.Value as bool? ?? false, OpenCount = values[3].Result?.Value as ushort? ?? 0, MimeType = values[4].Result?.Value as string, MaxBufferSize = values[5].Result?.Value as uint?, LastModified = values[6].Result?.Value as DateTime? }, null); } catch (Exception ex) { return (null, ex.ToServiceResultModel()); } } /// /// Get buffer size /// /// /// /// /// /// public static async Task GetBufferSizeAsync(this IOpcUaSession session, RequestHeader header, NodeId nodeId, CancellationToken ct = default) { try { var (fileInfo, errorInfo) = await session.GetFileInfoAsync( header, nodeId, ct).ConfigureAwait(false); var bufferSize = fileInfo?.MaxBufferSize; if (errorInfo == null && bufferSize > 0 && bufferSize < int.MaxValue) { return (int)bufferSize.Value; } var caps = await session.GetOperationLimitsAsync( ct).ConfigureAwait(false); bufferSize = caps.MaxByteStringLength; if (bufferSize > 0 && bufferSize < int.MaxValue) { return (int)bufferSize.Value; } return 4096; } catch { return 4096; } } /// /// Open file /// /// /// /// /// /// /// public static async Task<(uint?, ServiceResultModel?)> OpenAsync(this IOpcUaSession session, RequestHeader header, NodeId nodeId, byte mode, CancellationToken ct) { try { // Call open method var request = new CallMethodRequestCollection { new CallMethodRequest { ObjectId = nodeId, MethodId = MethodIds.FileType_Open, InputArguments = new [] { new Variant(mode) } } }; var response = await session.Services.CallAsync(header, request, ct).ConfigureAwait(false); var results = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, request); if (results.ErrorInfo != null) { return (null, results.ErrorInfo); } if (results[0].ErrorInfo != null || results[0].Result?.OutputArguments == null || results[0].Result.OutputArguments.Count == 0 || results[0].Result.OutputArguments[0].Value is not uint fileHandle) { return (null, results[0].ErrorInfo ?? new ServiceResultModel { ErrorMessage = "no file handle returned" }); } return (fileHandle, null); } catch (Exception ex) { return (null, ex.ToServiceResultModel()); } } /// /// Write buffer at current position in file /// /// /// /// /// /// /// /// public static async Task WriteAsync(this IOpcUaSession session, RequestHeader header, NodeId nodeId, uint fileHandle, ReadOnlyMemory buffer, CancellationToken ct) { try { // Call write method var request = new CallMethodRequestCollection { new CallMethodRequest { ObjectId = nodeId, MethodId = MethodIds.FileType_Write, InputArguments = new [] { new Variant(fileHandle), new Variant(buffer.ToArray()) } } }; var response = await session.Services.CallAsync(header, request, ct).ConfigureAwait(false); var results = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, request); return results.ErrorInfo; } catch (Exception ex) { return ex.ToServiceResultModel(); } } /// /// Read from current position in file /// /// /// /// /// /// /// /// public static async Task<(byte[]?, ServiceResultModel?)> ReadAsync(this IOpcUaSession session, RequestHeader header, NodeId nodeId, uint fileHandle, int length, CancellationToken ct) { try { // Call read method var request = new CallMethodRequestCollection { new CallMethodRequest { ObjectId = nodeId, MethodId = MethodIds.FileType_Read, InputArguments = new [] { new Variant(fileHandle), new Variant(length) } } }; var response = await session.Services.CallAsync(header, request, ct).ConfigureAwait(false); var results = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, request); if (results.ErrorInfo != null) { return (null, results.ErrorInfo); } if (results[0].Result?.OutputArguments == null || results[0].Result.OutputArguments.Count == 0 || results[0].Result.OutputArguments[0].Value is not byte[] byteString) { byteString = []; } return (byteString, null); } catch (Exception ex) { return (null, ex.ToServiceResultModel()); } } /// /// Close file handle of file /// /// /// /// /// /// /// /// public static async Task CloseAsync(this IOpcUaSession session, RequestHeader header, NodeId nodeId, NodeId? alternativeCloseMethod, uint fileHandle, CancellationToken ct) { // Call close method try { var request = new CallMethodRequestCollection { new CallMethodRequest { ObjectId = nodeId, MethodId = alternativeCloseMethod ?? MethodIds.FileType_Close, InputArguments = new [] { new Variant(fileHandle) } } }; var response = await session.Services.CallAsync(header, request, ct).ConfigureAwait(false); var results = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, request); return results.ErrorInfo; } catch (Exception ex) { return ex.ToServiceResultModel(); } } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/FilterEncoderEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Encoders; using Opc.Ua; using Opc.Ua.Extensions; using System; using System.Diagnostics.CodeAnalysis; using System.Linq; /// /// Filter conversion /// public static class FilterEncoderEx { /// /// Gets a default event filter. /// /// public static EventFilter GetDefaultEventFilter() { var filter = new EventFilter(); filter.AddSelectClause(ObjectTypes.BaseEventType, BrowseNames.EventId); filter.AddSelectClause(ObjectTypes.BaseEventType, BrowseNames.EventType); filter.AddSelectClause(ObjectTypes.BaseEventType, BrowseNames.SourceNode); filter.AddSelectClause(ObjectTypes.BaseEventType, BrowseNames.SourceName); filter.AddSelectClause(ObjectTypes.BaseEventType, BrowseNames.Time); filter.AddSelectClause(ObjectTypes.BaseEventType, BrowseNames.ReceiveTime); filter.AddSelectClause(ObjectTypes.BaseEventType, BrowseNames.LocalTime); filter.AddSelectClause(ObjectTypes.BaseEventType, BrowseNames.Message); filter.AddSelectClause(ObjectTypes.BaseEventType, BrowseNames.Severity); return filter; } /// /// Convert to stack model /// /// /// /// /// /// [return: NotNullIfNotNull(nameof(model))] public static EventFilter? Decode(this IVariantEncoder encoder, EventFilterModel? model, bool noDefaultFilter = false) { if (model is null) { return noDefaultFilter ? null : GetDefaultEventFilter(); } if (!(model.SelectClauses?.Any() ?? false)) { return noDefaultFilter ? throw new ArgumentException("Missing select clause") : GetDefaultEventFilter(); } return new EventFilter { SelectClauses = new SimpleAttributeOperandCollection( model.SelectClauses == null ? [] : model.SelectClauses.Select(c => c.ToStackModel(encoder.Context))), // // Per Part 4 only allow simple attribute operands in where clause // elements of event filters. // WhereClause = encoder.Decode(model.WhereClause, true) }; } /// /// Convert to stack model /// /// /// /// /// [return: NotNullIfNotNull(nameof(model))] public static EventFilterModel? Encode(this IVariantEncoder encoder, EventFilter? model, NamespaceFormat namespaceFormat) { if (model is null) { return null; } return new EventFilterModel { SelectClauses = model.SelectClauses? .Select(c => c.ToServiceModel(encoder.Context, namespaceFormat)) .ToList(), WhereClause = encoder.Encode(model.WhereClause, namespaceFormat) }; } /// /// Convert to stack model /// /// /// /// /// public static ContentFilter Decode(this IVariantEncoder encoder, ContentFilterModel? model, bool onlySimpleAttributeOperands = false) { if (model is null) { return new ContentFilter(); } return new ContentFilter { Elements = new ContentFilterElementCollection(model.Elements == null ? [] : model.Elements .Select(e => encoder.Decode(e, onlySimpleAttributeOperands))) }; } /// /// Convert to service model /// /// /// /// /// [return: NotNullIfNotNull(nameof(model))] public static ContentFilterModel? Encode(this IVariantEncoder encoder, ContentFilter? model, NamespaceFormat namespaceFormat) { if (model is null) { return null; } return new ContentFilterModel { Elements = model.Elements? .Select(e => encoder.Encode(e, namespaceFormat)) .ToList() }; } /// /// Convert to stack model /// /// /// /// /// [return: NotNullIfNotNull(nameof(model))] public static ContentFilterElement? Decode(this IVariantEncoder encoder, ContentFilterElementModel? model, bool onlySimpleAttributeOperands = false) { if (model is null) { return null; } return new ContentFilterElement { FilterOperands = new ExtensionObjectCollection(model.FilterOperands == null ? [] : model.FilterOperands .Select(e => new ExtensionObject( encoder.Decode(e, onlySimpleAttributeOperands)))), FilterOperator = model.FilterOperator.ToStackType() }; } /// /// Convert to service model /// /// /// /// /// [return: NotNullIfNotNull(nameof(model))] public static ContentFilterElementModel? Encode(this IVariantEncoder encoder, ContentFilterElement? model, NamespaceFormat namespaceFormat) { if (model is null) { return null; } return new ContentFilterElementModel { FilterOperands = model.FilterOperands .Select(e => e.Body) .Cast() .Select(o => encoder.Encode(o, namespaceFormat)) .ToList(), FilterOperator = model.FilterOperator.ToServiceType() }; } /// /// Convert to stack model /// /// /// /// /// [return: NotNullIfNotNull(nameof(model))] public static FilterOperand? Decode(this IVariantEncoder encoder, FilterOperandModel? model, bool onlySimpleAttributeOperands = false) { if (model is null) { return null; } if (model.Index != null) { return new ElementOperand { Index = model.Index.Value }; } if (model.Value != null) { var typeInfo = new TypeInfo(BuiltInType.NodeId, ValueRanks.Scalar); try { // assume it's a node and try to parse it into correct namespace index // if it fails, it's ok it will go to the default route var nodeId = encoder.Decode(model.Value, null); var typeDefinitionId = nodeId.ToString().ToNodeId(encoder.Context); if (typeDefinitionId != null) { return new LiteralOperand(TypeInfo.Cast(typeDefinitionId, typeInfo.BuiltInType)); } } catch { } return new LiteralOperand(TypeInfo.Cast(encoder.Decode(model.Value, null), typeInfo.BuiltInType)); } if (model.Alias != null && !onlySimpleAttributeOperands) { return new AttributeOperand { Alias = model.Alias, NodeId = model.NodeId.ToNodeId(encoder.Context), AttributeId = (uint)(model.AttributeId ?? NodeAttribute.Value), BrowsePath = model.BrowsePath.ToRelativePath(encoder.Context), IndexRange = model.IndexRange }; } return new SimpleAttributeOperand { TypeDefinitionId = model.NodeId.ToNodeId(encoder.Context), AttributeId = (uint)(model.AttributeId ?? NodeAttribute.Value), BrowsePath = new QualifiedNameCollection(model.BrowsePath == null ? [] : model.BrowsePath.Select(n => n.ToQualifiedName(encoder.Context))), IndexRange = model.IndexRange }; } /// /// Convert to service model /// /// /// /// /// /// [return: NotNullIfNotNull(nameof(model))] public static FilterOperandModel? Encode(this IVariantEncoder encoder, FilterOperand? model, NamespaceFormat namespaceFormat) { if (model is null) { return null; } switch (model) { case ElementOperand elem: return new FilterOperandModel { Index = elem.Index }; case LiteralOperand lit: return new FilterOperandModel { Value = encoder.Encode(lit.Value, out _) }; case AttributeOperand attr: return new FilterOperandModel { NodeId = attr.NodeId.AsString(encoder.Context, namespaceFormat), AttributeId = (NodeAttribute)attr.AttributeId, BrowsePath = attr.BrowsePath.AsString(encoder.Context, namespaceFormat), IndexRange = attr.IndexRange, Alias = attr.Alias }; case SimpleAttributeOperand sattr: return new FilterOperandModel { NodeId = sattr.TypeDefinitionId.AsString(encoder.Context, namespaceFormat), AttributeId = (NodeAttribute)sattr.AttributeId, BrowsePath = sattr.BrowsePath? .Select(p => p.AsString(encoder.Context, namespaceFormat)) .ToArray(), IndexRange = sattr.IndexRange }; default: throw new NotSupportedException("Operand not supported"); } } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/MonitoredItemEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Models { using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.Linq; /// /// Base monitored item extensions /// internal static class MonitoredItemEx { /// /// Set defaults from configuration /// /// /// /// public static BaseMonitoredItemModel SetDefaults(this BaseMonitoredItemModel item, OpcUaSubscriptionOptions options) { switch (item) { case MonitoredAddressSpaceModel mas: return mas with { RebrowsePeriod = mas.RebrowsePeriod ?? options.DefaultRebrowsePeriod ?? TimeSpan.FromHours(12), // // see https://reference.opcfoundation.org/v104/Core/docs/Part4/7.16/ // 0 the Server returns the default queue size for Event Notifications // as revisedQueueSize for event monitored items. // QueueSize = item.QueueSize ?? options.DefaultQueueSize ?? 0, DiscardNew = item.DiscardNew ?? options.DefaultDiscardNew, MonitoringMode = item.MonitoringMode ?? MonitoringMode.Reporting, FetchDataSetFieldName = item.FetchDataSetFieldName ?? options.ResolveDisplayName, AutoSetQueueSize = item.AutoSetQueueSize ?? options.AutoSetQueueSizes, TriggeredItems = item.TriggeredItems? .Select(ti => ti.SetDefaults(options)) .ToList(), }; case DataMonitoredItemModel dmi: return dmi with { SamplingInterval = dmi.SamplingInterval ?? options.DefaultSamplingInterval, HeartbeatBehavior = dmi.HeartbeatBehavior ?? options.DefaultHeartbeatBehavior, HeartbeatInterval = dmi.HeartbeatInterval ?? options.DefaultHeartbeatInterval, SkipFirst = dmi.SkipFirst ?? options.DefaultSkipFirst, // // see https://reference.opcfoundation.org/v104/Core/docs/Part4/7.16/ // 0 or 1 the Server returns the default queue size which shall be 1 // as revisedQueueSize for data monitored items. The queue has a single // entry, effectively disabling queuing. This is the default behavior // since beginning of publisher time. // QueueSize = item.QueueSize ?? options.DefaultQueueSize ?? 1, DiscardNew = item.DiscardNew ?? options.DefaultDiscardNew, FetchDataSetFieldName = item.FetchDataSetFieldName ?? options.ResolveDisplayName, AutoSetQueueSize = item.AutoSetQueueSize ?? options.AutoSetQueueSizes, TriggeredItems = item.TriggeredItems? .Select(ti => ti.SetDefaults(options)) .ToList(), SamplingUsingCyclicRead = dmi.SamplingUsingCyclicRead ?? options.DefaultSamplingUsingCyclicRead, CyclicReadMaxAge = dmi.CyclicReadMaxAge ?? options.DefaultCyclicReadMaxAge, DataChangeFilter = dmi.DataChangeFilter.SetDefaults(options) }; case EventMonitoredItemModel emi: return emi with { // // see https://reference.opcfoundation.org/v104/Core/docs/Part4/7.16/ // 0 the Server returns the default queue size for Event Notifications // as revisedQueueSize for event monitored items. // QueueSize = item.QueueSize ?? options.DefaultQueueSize ?? 0, DiscardNew = item.DiscardNew ?? options.DefaultDiscardNew, FetchDataSetFieldName = item.FetchDataSetFieldName ?? options.ResolveDisplayName, AutoSetQueueSize = item.AutoSetQueueSize ?? options.AutoSetQueueSizes, TriggeredItems = item.TriggeredItems? .Select(ti => ti.SetDefaults(options)) .ToList(), }; default: return item; } } /// /// Set default data change filter /// /// /// /// private static DataChangeFilterModel? SetDefaults( this DataChangeFilterModel? filter, OpcUaSubscriptionOptions options) { if (filter == null && options.DefaultDataChangeTrigger == null) { return null; } filter ??= new DataChangeFilterModel(); return filter with { DataChangeTrigger = filter.DataChangeTrigger ?? options.DefaultDataChangeTrigger ?? DataChangeTriggerType.StatusValue, }; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/NodeStateEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Opc.Ua.Extensions { using Opc.Ua; using System; /// /// Node state extensions /// public static class NodeStateEx { /// /// Return value or update /// /// /// /// /// /// /// public static TResult? GetValueOrDefaultEx(this PropertyState state, Func convert, T? defaultValue = default) where T : struct { var result = GetValueOrDefaultEx(state, defaultValue); return convert(result); } /// /// Return value or update /// /// /// /// /// /// /// public static TResult? GetValueOrDefaultEx(this PropertyState state, Func convert, TValue? defaultValue = null) where TValue : class { var result = GetValueOrDefaultEx(state, defaultValue); return convert(result); } /// /// Return value or default /// /// /// /// /// public static T? GetValueOrDefaultEx(this PropertyState state, T? defaultValue = default) where T : struct { if (!StatusCode.IsGood(state.StatusCode)) { return defaultValue; } return state.Value; } /// /// Return value or default /// /// /// /// /// public static T? GetValueOrDefaultEx(this PropertyState state, T? defaultValue = null) where T : class { if (!StatusCode.IsGood(state.StatusCode)) { return defaultValue; } return state.Value; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/OperationLimitsEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Opc.Ua.Extensions { using Opc.Ua; using Azure.IIoT.OpcUa.Publisher.Models; using System; /// /// Operation limits extensions /// public static class OperationLimitsEx { /// /// Update limits /// /// /// /// public static OperationLimits Override(this OperationLimits limits, OperationLimits? update) { if (update == null) { return limits; } return new OperationLimits { MaxMonitoredItemsPerCall = Override(limits.MaxMonitoredItemsPerCall, update.MaxMonitoredItemsPerCall), MaxNodesPerBrowse = Override(limits.MaxNodesPerBrowse, update.MaxNodesPerBrowse), MaxNodesPerHistoryReadData = Override(limits.MaxNodesPerHistoryReadData, update.MaxNodesPerHistoryReadData), MaxNodesPerHistoryReadEvents = Override(limits.MaxNodesPerHistoryReadEvents, update.MaxNodesPerHistoryReadEvents), MaxNodesPerHistoryUpdateData = Override(limits.MaxNodesPerHistoryUpdateData, update.MaxNodesPerHistoryUpdateData), MaxNodesPerHistoryUpdateEvents = Override(limits.MaxNodesPerHistoryUpdateEvents, update.MaxNodesPerHistoryUpdateEvents), MaxNodesPerMethodCall = Override(limits.MaxNodesPerMethodCall, update.MaxNodesPerMethodCall), MaxNodesPerNodeManagement = Override(limits.MaxNodesPerNodeManagement, update.MaxNodesPerNodeManagement), MaxNodesPerRead = Override(limits.MaxNodesPerRead, update.MaxNodesPerRead), MaxNodesPerRegisterNodes = Override(limits.MaxNodesPerRegisterNodes, update.MaxNodesPerRegisterNodes), MaxNodesPerTranslateBrowsePathsToNodeIds = Override(limits.MaxNodesPerTranslateBrowsePathsToNodeIds, update.MaxNodesPerTranslateBrowsePathsToNodeIds), MaxNodesPerWrite = Override(limits.MaxNodesPerWrite, update.MaxNodesPerWrite) }; static uint Override(uint a, uint b) => b == 0u ? a : b < a ? b : a; } /// /// Max nodes per browse /// /// /// public static int GetMaxNodesPerBrowse(this OperationLimitsModel model) { var cur = model.MaxNodesPerBrowse ?? 0; return Math.Min(Math.Max((int)cur, 1), kMaxBrowseNodes); } /// /// Max continuation points per browse /// /// /// public static int GetMaxBrowseContinuationPoints(this OperationLimitsModel model) { var cur = model.MaxBrowseContinuationPoints ?? 0; return Math.Min(Math.Max((int)cur, 1), kMaxBrowseContinuationPoints); } /// /// Max nodes per read /// /// /// public static int GetMaxNodesPerRead(this OperationLimitsModel model) { var cur = model.MaxNodesPerRead ?? 0; return Math.Min(Math.Max((int)cur, 1), kMaxReadNodes); } /// /// Max nodes per translate /// /// /// public static int GetMaxNodesPerTranslatePathsToNodeIds(this OperationLimitsModel model) { var cur = model.MaxNodesPerTranslatePathsToNodeIds ?? 0; return Math.Min(Math.Max((int)cur, 1), kMaxNodesPerTranslate); } /// /// Max nodes per register /// /// /// public static int GetMaxNodesPerRegisterNodes(this OperationLimitsModel model) { var cur = model.MaxNodesPerRegisterNodes ?? 0; return Math.Min(Math.Max((int)cur, 1), kMaxNodesPerRegister); } /// /// Max monitored items /// /// /// public static int GetMaxMonitoredItemsPerCall(this OperationLimitsModel model) { var cur = model.MaxMonitoredItemsPerCall ?? 0; return Math.Min(Math.Max((int)cur, 1), kMaxMonitoredItemsPerCall); } private const int kMaxReadNodes = 10000; private const int kMaxNodesPerTranslate = 1000; private const int kMaxBrowseNodes = 10000; private const int kMaxNodesPerRegister = 10000; private const int kMaxMonitoredItemsPerCall = 10000; private const int kMaxBrowseContinuationPoints = 100; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/RelativePathEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Opc.Ua.Extensions { using Opc.Ua; using Azure.IIoT.OpcUa.Encoders.Utils; using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.Collections.Generic; using System.Linq; /// /// Relative path extensions /// public static class RelativePathEx { /// /// Convert to path object /// /// /// /// public static RelativePath ToRelativePath(this IReadOnlyList? path, IServiceMessageContext context) { if (path == null) { return new RelativePath(); } return new RelativePath { Elements = new RelativePathElementCollection(path .Where(p => !string.IsNullOrEmpty(p)) .Select(p => ParsePathElement(p, context))) }; } /// /// Convert a relative path to path strings /// /// /// /// /// public static IReadOnlyList? AsString(this RelativePath path, IServiceMessageContext context, NamespaceFormat namespaceFormat) { if (path == null) { return null; } return path.Elements .Select(p => FormatRelativePathElement(p, context, namespaceFormat)) .ToList(); } /// /// Convert to path element object /// /// /// /// /// /// private static RelativePathElement ParsePathElement(string element, IServiceMessageContext context) { if (string.IsNullOrEmpty(element)) { throw new ArgumentNullException(nameof(element)); } var pathElement = new RelativePathElement { IncludeSubtypes = true, IsInverse = false }; // // Parse relative path reference information // This should allow // - "targeturi" == "/targeturi" // - ".targeturi" // - "!.parenturi" // - "!/parenturi" // - "parenturi" // var index = 0; var exit = false; var parseReference = false; while (index < element.Length && !exit) { switch (element[index]) { case '<': if (pathElement.ReferenceTypeId == null) { parseReference = true; break; } throw new FormatException("Reference type set."); case '!': pathElement.IsInverse = true; break; case '#': pathElement.IncludeSubtypes = false; break; case '/': if (pathElement.ReferenceTypeId == null && !parseReference) { pathElement.ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences; break; } throw new FormatException("Reference type set."); case '.': if (pathElement.ReferenceTypeId == null && !parseReference) { pathElement.ReferenceTypeId = ReferenceTypeIds.Aggregates; break; } throw new FormatException("Reference type set."); default: if (element[index] == '&') { index++; } if (pathElement.ReferenceTypeId == null && !parseReference) { // Set to all references pathElement.ReferenceTypeId = ReferenceTypeIds.References; } exit = true; break; } index++; } index--; if (parseReference) { var to = index; while (to < element.Length) { if (element[to] == '>' && element[to - 1] != '&') { break; } to++; if (to == element.Length) { throw new FormatException( "Reference path starts in < but does not end in >"); } } var reference = element[index..to]; // TODO: Deescape &<, &>, &/, &., &:, && index = to + 1; pathElement.ReferenceTypeId = reference.ToNodeId(context); if (NodeId.IsNull(pathElement.ReferenceTypeId) && TypeMaps.ReferenceTypes.Value.TryGetIdentifier(reference, out var id)) { pathElement.ReferenceTypeId = id; } } var target = element[index..]; // TODO: Deescape &<, &>, &/, &., &:, && if (string.IsNullOrEmpty(target)) { throw new FormatException("Bad target name is empty"); } pathElement.TargetName = target.ToQualifiedName(context); return pathElement; } /// /// Format relative path element information /// /// /// /// /// private static string FormatRelativePathElement(RelativePathElement element, IServiceMessageContext context, NamespaceFormat namespaceFormat) { var value = string.Empty; var writeReference = false; if (element.ReferenceTypeId == ReferenceTypeIds.HierarchicalReferences) { value += "/"; } else if (element.ReferenceTypeId == ReferenceTypeIds.Aggregates) { value += "."; } else if (element.ReferenceTypeId != ReferenceTypeIds.References) { value += "<"; writeReference = true; } if (element.IsInverse) { value += "!"; } if (!element.IncludeSubtypes) { value += "#"; } if (writeReference) { string? reference = null; if (element.ReferenceTypeId.NamespaceIndex == 0 && element.ReferenceTypeId.Identifier is uint id) { TypeMaps.ReferenceTypes.Value.TryGetBrowseName(id, out reference); } if (string.IsNullOrEmpty(reference)) { reference = element.ReferenceTypeId.AsString(context, namespaceFormat); } // TODO: Escape <,>,/,:,&,. value += reference + ">"; } var target = element.TargetName.AsString(context, namespaceFormat); // TODO: Escape <,>,/,:,&,. value += target; return value; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/SequenceNumber.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Opc.Ua { using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Threading; /// /// A sequence number /// public static class SequenceNumber { /// /// Increment sequence number /// /// /// public static uint Increment32(ref uint seq) { while (true) { var result = Interlocked.Increment(ref seq); if (result != 0) { return result; } } } /// /// Increment sequence number /// /// /// public static ushort Increment16(ref uint seq) { while (true) { var result = (ushort)Interlocked.Increment(ref seq); if (result != 0) { return result; } } } /// /// Create a range of values missing between 2 sequence numbers /// Considers wrap around /// /// /// /// /// public static uint[] Missing(uint from, uint to, out bool dropped) { unchecked { var diff = Math.Abs((int)from - (int)to); if (diff > 1) { var (startAt, endAt) = (((int)from + diff) == (int)to) ? (from, to) : (to, from); dropped = from == startAt; var missing = new List(diff - 1); while (++startAt != endAt) { if (startAt != 0) { missing.Add(startAt); } } if (missing.Count > 0) { return [.. missing]; } } } dropped = false; return []; } /// /// Convert missing sequence numbers to string /// /// /// public static string ToString(uint[] missingSequenceNumbers) { switch (missingSequenceNumbers.Length) { case 0: return "none"; case 1: return missingSequenceNumbers[0].ToString(CultureInfo.InvariantCulture); default: var length = missingSequenceNumbers.Length; if (length > 6) { var last = missingSequenceNumbers[length - 1]; return $"{missingSequenceNumbers[0]}...{last}"; } return missingSequenceNumbers .Select(a => a.ToString(CultureInfo.InvariantCulture)) .Aggregate((a, b) => $"{a}, {b}"); } } /// /// Validate the sequence number and update the last to current /// /// /// /// /// /// public static bool Validate(uint sequenceNumber, ref uint lastSequenceNumber, out uint[] missing, out bool dropped) { try { // Allow duplicates as events and data changes can be in the same notification if (lastSequenceNumber != sequenceNumber) { var expected = lastSequenceNumber + 1 == 0 ? 1 : lastSequenceNumber + 1; var ok = sequenceNumber == expected; if (!ok) { missing = [.. Missing(lastSequenceNumber, sequenceNumber, out dropped)]; return false; } } missing = []; dropped = false; return true; } finally { lastSequenceNumber = sequenceNumber; } } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/ServiceResponseEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Models { using Azure.IIoT.OpcUa.Publisher.Models; using Opc.Ua; using System; using System.Collections.Generic; internal static class ServiceResponseEx { /// /// Validate response /// /// /// /// /// /// /// /// public static ServiceResponse Validate( this IServiceResponse response, IEnumerable? results, Func statusCode, DiagnosticInfoCollection? diagnostics, IEnumerable? requested) { return new ServiceResponse(response, results, statusCode, diagnostics, requested); } /// /// Validate response /// /// /// /// /// /// public static ServiceResponse Validate( this IServiceResponse response, IEnumerable? results, Func statusCode, DiagnosticInfoCollection? diagnostics) { return new ServiceResponse(response, results, statusCode, diagnostics, null); } /// /// Create a lookup table /// /// /// /// /// public static IDictionary AsLookupTable( this ServiceResponse response) where TRequest : struct { var lookup = new Dictionary(); foreach (var operation in response) { lookup.AddOrUpdate(operation.Request, (operation.Result, operation.ErrorInfo)); } return lookup; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/ServiceResultEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Furly.Exceptions; using Opc.Ua; using System; /// /// Service result model extensions /// internal static class ServiceResultEx { /// /// Convert exception to service result model /// /// /// public static ServiceResultModel ToServiceResultModel(this ServiceResult sr) { return new ServiceResultModel { StatusCode = sr.Code, ErrorMessage = sr.LocalizedText?.Text, Locale = sr.LocalizedText?.Locale, AdditionalInfo = sr.AdditionalInfo, NamespaceUri = sr.NamespaceUri, SymbolicId = sr.SymbolicId ?? sr.StatusCode.AsString(), Inner = sr.InnerResult == null || sr.InnerResult.StatusCode == StatusCodes.Good ? null : sr.InnerResult.ToServiceResultModel() }; } /// /// Convert exception to service result model /// /// /// public static ServiceResultModel ToServiceResultModel(this Exception e) { switch (e) { case ServiceResultException sre: return sre.Result.ToServiceResultModel(); case TimeoutException: return Create(StatusCodes.BadTimeout, e.Message); case OperationCanceledException: return Create(StatusCodes.BadRequestCancelledByClient, e.Message); case ResourceInvalidStateException: return Create(StatusCodes.BadInvalidState, e.Message); case ResourceNotFoundException: return Create(StatusCodes.BadNotFound, e.Message); case ResourceConflictException: return Create(StatusCodes.BadEntryExists, e.Message); case ArgumentNullException: return Create(StatusCodes.BadArgumentsMissing, e.Message); case ArgumentException: return Create(StatusCodes.BadInvalidArgument, e.Message); default: return Create(StatusCodes.Bad, e.Message); } static ServiceResultModel Create(StatusCode code, string message) => new() { ErrorMessage = message, SymbolicId = code.AsString(), StatusCode = code.Code }; } /// /// Create result recursively from diagnostics /// /// /// /// /// public static ServiceResultModel CreateResultModel(this StatusCode statusCode, DiagnosticInfo? diagnostics = null, StringCollection? stringTable = null) { return new ServiceResultModel { // The last operation result is the one that caused the service to fail. StatusCode = statusCode.Code, SymbolicId = stringTable?.GetStringFromTable(diagnostics?.SymbolicId) ?? statusCode.AsString(), ErrorMessage = stringTable?.GetStringFromTable(diagnostics?.LocalizedText), NamespaceUri = stringTable?.GetStringFromTable(diagnostics?.NamespaceUri), Locale = stringTable?.GetStringFromTable(diagnostics?.Locale), AdditionalInfo = diagnostics?.AdditionalInfo, Inner = diagnostics?.InnerStatusCode == null || diagnostics.InnerStatusCode == StatusCodes.Good ? null : diagnostics.InnerStatusCode.CreateResultModel( diagnostics?.InnerDiagnosticInfo, stringTable) }; } /// /// Get string from string table /// /// /// /// private static string? GetStringFromTable( this StringCollection stringTable, int? index) { if (index == null || stringTable == null || index.Value >= stringTable.Count || index.Value < 0) { return null; } var str = stringTable[index.Value]; if (string.IsNullOrWhiteSpace(str)) { return null; } return str; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/SessionEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Extensions { using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Encoders.Utils; using Furly.Extensions.Serializers; using Opc.Ua; using Opc.Ua.Extensions; using NodeClass = Publisher.Models.NodeClass; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; /// /// Session Handle extensions /// public static class SessionEx { /// /// Read attribute /// /// /// /// /// /// /// /// internal static async Task<(T?, ServiceResultModel?)> ReadAttributeAsync( this IOpcUaSession session, RequestHeader header, NodeId nodeId, uint attributeId, CancellationToken ct = default) { var attributes = await session.ReadAttributeAsync(header, nodeId.YieldReturn(), attributeId, ct).ConfigureAwait(false); return attributes.SingleOrDefault(); } /// /// Read attribute /// /// /// /// /// /// /// /// internal static async Task> ReadAttributeAsync( this IOpcUaSession session, RequestHeader header, IEnumerable nodeIds, uint attributeId, CancellationToken ct = default) { var itemsToRead = new ReadValueIdCollection(nodeIds.Select(nodeId => new ReadValueId { NodeId = nodeId, AttributeId = attributeId })); if (itemsToRead.Count == 0) { return []; } var response = await session.Services.ReadAsync(header, 0, Opc.Ua.TimestampsToReturn.Neither, itemsToRead, ct).ConfigureAwait(false); var results = response.Validate(response.Results, s => s.StatusCode, response.DiagnosticInfos, itemsToRead); if (results.ErrorInfo != null) { return (default(T), (ServiceResultModel?)results.ErrorInfo).YieldReturn(); } return results.Select(result => { var errorInfo = result.ErrorInfo; var value = result.ErrorInfo != null ? default : result.Result.GetValue(default); return (value, errorInfo); }); } /// /// Read attributes grouped by node id /// /// /// /// /// /// /// /// internal static async Task ReadAttributesAsync( this IOpcUaSession session, RequestHeader header, IEnumerable nodeIds, IEnumerable attributeIds, Dictionary> results, CancellationToken ct = default) { var itemsToRead = new ReadValueIdCollection(nodeIds .SelectMany(nodeId => attributeIds .Select(attributeId => new ReadValueId { NodeId = nodeId, AttributeId = attributeId }))); if (itemsToRead.Count == 0) { return null; } var response = await session.Services.ReadAsync(header, 0, Opc.Ua.TimestampsToReturn.Neither, itemsToRead, ct).ConfigureAwait(false); var readresults = response.Validate(response.Results, s => s.StatusCode, response.DiagnosticInfos, itemsToRead); if (readresults.ErrorInfo != null) { return readresults.ErrorInfo; } foreach (var group in readresults.GroupBy(g => g.Request.NodeId)) { results.AddOrUpdate(group.Key, group.ToDictionary(r => r.Request.AttributeId, r => r.Result)); } return null; } /// /// Read value /// /// /// /// /// /// /// public static async Task<(DataValue?, ServiceResultModel?)> ReadValueAsync( this IOpcUaSession session, RequestHeader header, NodeId nodeId, CancellationToken ct = default) { var itemsToRead = new ReadValueIdCollection { new ReadValueId { NodeId = nodeId, AttributeId = Attributes.Value } }; var response = await session.Services.ReadAsync(header, 0, Opc.Ua.TimestampsToReturn.Both, itemsToRead, ct).ConfigureAwait(false); var results = response.Validate(response.Results, s => s.StatusCode, response.DiagnosticInfos, itemsToRead); var errorInfo = results.ErrorInfo ?? results[0].ErrorInfo; var value = results.ErrorInfo != null ? null : results[0].Result; return (value, errorInfo); } /// /// Path result returned by browse path resolver. /// /// /// internal record class PathResult(RelativePath Path, ServiceResultModel? ErrorInfo); /// /// Get all browse paths for the nodes provided from the root folder object that /// organizes the address space. /// /// /// /// /// /// internal static async Task> GetBrowsePathsFromRootAsync( this IOpcUaSession session, RequestHeader requestHeader, IEnumerable nodes, CancellationToken ct = default) { // // The semantic of HierarchicalReferences is to denote that References of // HierarchicalReferences span a hierarchy. It means that it may be useful // to present Nodes related with References of this type in a hierarchical-like // way. HierarchicalReferences does not forbid loops. For example, starting // from Node A and following HierarchicalReferences it may be possible to // browse to Node A, again. Technically we only care about HasChild references // as well as Organizes, but we try and follow all paths to the root path // and backtrack if we do not get to it. // var browse = nodes.Select(nodeId => new BrowseDescription { BrowseDirection = Opc.Ua.BrowseDirection.Inverse, ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences, IncludeSubtypes = true, NodeId = nodeId, Handle = new PathResult(new RelativePath(), null), NodeClassMask = 0u, ResultMask = (uint)BrowseResultMask.BrowseName | (uint)BrowseResultMask.ReferenceTypeId }).ToList(); if (browse.Count == 0) { return Array.Empty(); } // Here we keep track of the paths we are exploring to allow us to backtrack var searchContext = browse.ToDictionary(b => b, _ => new Stack<(Queue Next, HashSet Seen)>()); var limits = await session.GetOperationLimitsAsync(ct).ConfigureAwait(false); foreach (var batch in searchContext.Keys.Batch(limits.GetMaxNodesPerRead())) { var response = await session.Services.ReadAsync(requestHeader, 0, Opc.Ua.TimestampsToReturn.Neither, new ReadValueIdCollection( batch.Select(b => new ReadValueId { NodeId = b.NodeId, AttributeId = (uint)NodeAttribute.BrowseName })), ct).ConfigureAwait(false); var readResults = response.Validate(response.Results, s => s.StatusCode, response.DiagnosticInfos, batch); // Fail all if (readResults.ErrorInfo != null) { return searchContext.Keys.Select(b => ((PathResult)b.Handle) with { ErrorInfo = readResults.ErrorInfo }).ToList(); } foreach (var result in readResults) { var path = (PathResult)result.Request.Handle; path.Path.Elements.Add(new RelativePathElement { IsInverse = false, IncludeSubtypes = false, TargetName = result.Result.Value as QualifiedName }); } } while (searchContext.Count != 0) { await foreach (var result in session.BrowseAsync(requestHeader, null, new BrowseDescriptionCollection(searchContext.Keys), ct).ConfigureAwait(false)) { if (result.Description == null) { // Fail all return browse.ConvertAll(b => ((PathResult)b.Handle) with { ErrorInfo = result.ErrorInfo ?? new ServiceResultModel { StatusCode = StatusCodes.BadNotFound } }); } var pathsFromNode = searchContext[result.Description]; var path = (PathResult)result.Description.Handle; ReferenceDescription? reference = null; if (result.References != null) { if (result.References.Any(r => r.NodeId == ObjectIds.RootFolder)) { // // we reached the root folder and are now done. There could be // alternative paths to the root but we do not care about those. // searchContext.Remove(result.Description); continue; } // // Filter any nodes we have already seen on our journey and then // filter any nodes that are external. Then we do some weighing, // e.g., prefer Organizes to HasChild (HasProperty, HasComponent) // to HasEventSource (HasNotifier) // var references = result.References .Where(r => r.NodeId.ServerIndex == 0 && !pathsFromNode.Any(p => p.Seen.Contains(r.NodeId))) .OrderBy(r => r.ReferenceTypeId) ; var queue = new Queue(references); if (queue.Count > 0) { pathsFromNode.Push((queue, new HashSet())); reference = pathsFromNode.Peek().Next.Dequeue(); pathsFromNode.Peek().Seen.Add(reference.NodeId); } } if (reference == null) { // // Wrong path taken see if there are alternatives to get to root // Backtrack the path elements and try to find a new route // path.Path.Elements.RemoveAt(0); while (pathsFromNode.Count > 0) { var alternativeReferences = pathsFromNode.Peek().Next; if (alternativeReferences.Count != 0) { reference = alternativeReferences.Dequeue(); pathsFromNode.Peek().Seen.Add(reference.NodeId); break; } // All paths at this level exhausted - backtrack a level. path.Path.Elements.RemoveAt(0); path.Path.Elements[0].ReferenceTypeId = null; pathsFromNode.Pop(); } if (reference == null) { // No way to get to root. This should not happen. searchContext.Remove(result.Description); result.Description.Handle = path with { ErrorInfo = result.ErrorInfo ?? new ServiceResultModel { StatusCode = StatusCodes.BadNotFound } }; continue; } } path.Path.Elements[0].ReferenceTypeId = reference.ReferenceTypeId; path.Path.Elements.Insert(0, new RelativePathElement { IsInverse = false, IncludeSubtypes = false, TargetName = reference.BrowseName }); result.Description.NodeId = reference.NodeId.ToNodeId( session.MessageContext.NamespaceUris); } } return browse.ConvertAll(b => (PathResult)b.Handle); } /// /// Read all attributes from node /// /// /// /// /// /// /// /// internal static async Task> ReadNodeAttributesAsync( this IOpcUaSession session, RequestHeader requestHeader, NodeId nodeId, bool skipValueRead = false, Opc.Ua.NodeClass? nodeClass = null, CancellationToken ct = default) { if (nodeClass == null || nodeClass.Value == Opc.Ua.NodeClass.Unspecified) { // First read node class var nodeClassRead = new ReadValueIdCollection { new ReadValueId { NodeId = nodeId, AttributeId = Attributes.NodeClass } }; var response = await session.Services.ReadAsync(requestHeader, 0, Opc.Ua.TimestampsToReturn.Both, nodeClassRead, ct).ConfigureAwait(false); var readResults = response.Validate(response.Results, s => s.StatusCode, response.DiagnosticInfos, nodeClassRead); nodeClass = readResults.ErrorInfo != null ? Opc.Ua.NodeClass.Unspecified : readResults[0].Result.GetValueOrDefaultEx(); } if (nodeClass == Opc.Ua.NodeClass.VariableType) { skipValueRead = false; // read default values } var attributes = TypeMaps.Attributes.Value.Identifiers .Where(a => !skipValueRead || a != Attributes.Value); var readValueCollection = new ReadValueIdCollection(attributes .Select(a => new ReadValueId { NodeId = nodeId, AttributeId = a })); var readResponse = await session.Services.ReadAsync(requestHeader, 0, Opc.Ua.TimestampsToReturn.Both, readValueCollection, ct).ConfigureAwait(false); var results = readResponse.Validate(readResponse.Results, s => s.StatusCode, readResponse.DiagnosticInfos, attributes); var errorInfo = results.ErrorInfo ?? results[0].ErrorInfo; if (errorInfo != null) { return results; } // Fix up responses based on node class for (var i = 0; i < results.Count; i++) { if (results[i].ErrorInfo?.StatusCode == StatusCodes.BadAttributeIdInvalid) { // Update result with default and set status to good. readResponse.Results[i].Value = AttributeMap.GetDefaultValue( nodeClass.Value, results[i].Request, true); readResponse.Results[i].StatusCode = StatusCodes.Good; } } return readResponse.Validate(readResponse.Results, s => s.StatusCode, readResponse.DiagnosticInfos, attributes); } /// /// Read node state /// /// /// /// /// /// /// /// internal static async Task ReadNodeStateAsync( this IOpcUaSession session, RequestHeader requestHeader, NodeState nodeState, NodeId rootId, RelativePath? relativePath = null, CancellationToken ct = default) { var valuesToRead = new List(); var objectsToBrowse = new List(); var resolveBrowsePaths = session.GetBrowsePathFromNodeState(rootId, nodeState, relativePath); if (resolveBrowsePaths.Count == 0) { // Nothing to do return ((StatusCode)StatusCodes.GoodNoData).CreateResultModel(); } var limits = await session.GetOperationLimitsAsync(ct).ConfigureAwait(false); var resolveBrowsePathsBatches = resolveBrowsePaths .Batch(limits.GetMaxNodesPerTranslatePathsToNodeIds()); foreach (var batch in resolveBrowsePathsBatches) { // translate browse paths. var response = await session.Services.TranslateBrowsePathsToNodeIdsAsync( requestHeader, new BrowsePathCollection(batch), ct).ConfigureAwait(false); var results = response.Validate(response.Results, s => s.StatusCode, response.DiagnosticInfos, batch); if (results.ErrorInfo != null) { return results.ErrorInfo; } foreach (var result in results) { if (result.Request.Handle is not NodeState node) { continue; } if (StatusCode.IsBad(result.StatusCode)) { if (result.StatusCode.Code is StatusCodes.BadNodeIdUnknown or StatusCodes.BadUnexpectedError) { return result.ErrorInfo; } if (node is BaseVariableState v) { // Initialize the variable v.Value = null; v.StatusCode = result.StatusCode; } continue; } if (result.Result.Targets.Count == 1 && result.Result.Targets[0].RemainingPathIndex == uint.MaxValue && !result.Result.Targets[0].TargetId.IsAbsolute) { node.NodeId = (NodeId)result.Result.Targets[0].TargetId; } else { if (node is BaseVariableState v) { // Initialize the variable v.Value = null; v.StatusCode = StatusCodes.BadNotSupported; } continue; } switch (node) { case BaseVariableState variable: // Initialize the variable variable.Value = null; variable.StatusCode = StatusCodes.BadNotSupported; valuesToRead.Add(new ReadValueId { NodeId = node.NodeId, AttributeId = Attributes.Value, Handle = node }); break; case FolderState folder: // Save for browsing objectsToBrowse.Add(new BrowseDescription { BrowseDirection = Opc.Ua.BrowseDirection.Forward, Handle = folder, IncludeSubtypes = true, ReferenceTypeId = ReferenceTypeIds.Organizes, NodeClassMask = (uint)Opc.Ua.NodeClass.Variable | (uint)Opc.Ua.NodeClass.Object, NodeId = node.NodeId, ResultMask = (uint)BrowseResultMask.All }); break; } } } if (objectsToBrowse.Count > 0) { foreach (var batch in objectsToBrowse.Batch(limits.GetMaxNodesPerBrowse())) { // Browse folders with objects and variables in it await foreach (var (description, references, errorInfo) in session.BrowseAsync( requestHeader, null, new BrowseDescriptionCollection(batch), ct).ConfigureAwait(false)) { var obj = (BaseObjectState?)description?.Handle; if (obj == null || references == null) { continue; } foreach (var reference in references) { switch (reference.NodeClass) { case Opc.Ua.NodeClass.Variable: // Add variable to the folder and set it to be read. var variable = new BaseDataVariableState(obj) { NodeId = (NodeId)reference.NodeId, BrowseName = reference.BrowseName, DisplayName = reference.DisplayName, StatusCode = StatusCodes.BadNotSupported, ReferenceTypeId = reference.ReferenceTypeId, Value = null }; obj.AddChild(variable); valuesToRead.Add(new ReadValueId { NodeId = variable.NodeId, AttributeId = Attributes.Value, Handle = variable }); break; case Opc.Ua.NodeClass.Object: // Add object #pragma warning disable CA2000 // Dispose objects before losing scope var child = new BaseObjectState(obj) { NodeId = (NodeId)reference.NodeId, BrowseName = reference.BrowseName, DisplayName = reference.DisplayName, ReferenceTypeId = reference.ReferenceTypeId }; #pragma warning restore CA2000 // Dispose objects before losing scope obj.AddChild(child); break; } } } } } if (valuesToRead.Count > 0) { foreach (var batch in valuesToRead.Batch(limits.GetMaxNodesPerRead())) { // read the values. var readResponse = await session.Services.ReadAsync( requestHeader, 0, Opc.Ua.TimestampsToReturn.Neither, new ReadValueIdCollection(batch), ct).ConfigureAwait(false); var readResults = readResponse.Validate(readResponse.Results, s => s.StatusCode, readResponse.DiagnosticInfos, batch); if (readResults.ErrorInfo != null) { return readResults.ErrorInfo; } foreach (var readResult in readResults) { var variable = (BaseVariableState)readResult.Request.Handle; variable.WrappedValue = readResult.Result.WrappedValue; variable.DataType = TypeInfo.GetDataTypeId(readResult.Result.Value); variable.StatusCode = readResult.Result.StatusCode; } } return null; } return ((StatusCode)StatusCodes.BadUnexpectedError).CreateResultModel(); } /// /// Browses the address space and returns all of the /// supertypes of the specified type node. /// /// /// /// /// /// /// internal static async Task CollectTypeHierarchyAsync(this IOpcUaSession session, RequestHeader header, NodeId typeId, IList<(NodeId, ReferenceDescription)> hierarchy, CancellationToken ct = default) { // find all of the children of the field. var nodeToBrowse = new BrowseDescriptionCollection { new BrowseDescription { NodeId = typeId, BrowseDirection = Opc.Ua.BrowseDirection.Inverse, ReferenceTypeId = ReferenceTypeIds.HasSubtype, IncludeSubtypes = false, NodeClassMask = 0, ResultMask = (uint)BrowseResultMask.All } }; while (true) { var response = await session.Services.BrowseAsync(header, null, 0, nodeToBrowse, ct).ConfigureAwait(false); var results = response.Validate(response.Results, s => s.StatusCode, response.DiagnosticInfos, nodeToBrowse); if (results.ErrorInfo != null) { break; } if (results[0].Result.References == null || results[0].Result.References.Count == 0) { // should never be more than one supertype. break; } var reference = results[0].Result.References[0]; if (reference.NodeId.IsAbsolute) { break; } hierarchy.Add((nodeToBrowse[0].NodeId, reference)); nodeToBrowse[0].NodeId = (NodeId)reference.NodeId; } } /// /// Collects the fields for the instance node. /// /// /// /// /// /// /// /// /// /// internal static async Task CollectInstanceDeclarationsAsync( this IOpcUaSession session, RequestHeader requestHeader, NodeId typeId, InstanceDeclarationModel? parent, List instances, IDictionary map, NamespaceFormat namespaceFormat, Opc.Ua.NodeClass? nodeClassMask = null, CancellationToken ct = default) { // find the children of the type. var nodeToBrowse = new BrowseDescriptionCollection { new BrowseDescription { NodeId = parent == null ? typeId : parent.NodeId.ToNodeId(session.MessageContext), BrowseDirection = Opc.Ua.BrowseDirection.Forward, ReferenceTypeId = ReferenceTypeIds.HasChild, IncludeSubtypes = true, NodeClassMask = (uint)Opc.Ua.NodeClass.Object | (((uint?)nodeClassMask) ?? (uint)Opc.Ua.NodeClass.Variable | (uint)Opc.Ua.NodeClass.Method), ResultMask = (uint)BrowseResultMask.All } }; await foreach (var result in session.BrowseAsync(requestHeader, null, nodeToBrowse, ct).ConfigureAwait(false)) { if (result.ErrorInfo != null) { return result.ErrorInfo; } if (result.References == null) { continue; } var references = result.References .Where(r => !r.NodeId.IsAbsolute) .ToList(); if (references.Count == 0) { continue; } // find the modelling rules. var (targets, errorInfo2) = await session.FindAsync(requestHeader, references.Select(r => (NodeId)r.NodeId), ReferenceTypeIds.HasModellingRule, maxResults: 1, ct: ct).ConfigureAwait(false); if (errorInfo2 != null) { return errorInfo2; } var referencesWithRules = targets .Zip(references) .ToList(); // Get the children. var children = new Dictionary(); foreach (var (modellingRule, reference) in referencesWithRules) { var browseName = reference.BrowseName.AsString(session.MessageContext, namespaceFormat); var relativePath = ImmutableRelativePath.Create(parent?.BrowsePath, "/" + browseName); var nodeClass = reference.NodeClass.ToServiceType(); if (NodeId.IsNull(modellingRule.Node) || nodeClass == null) { // if the modelling rule is null then the instance is not part // of the type declaration. map.Remove(relativePath); continue; } // create a new declaration. map.TryGetValue(relativePath, out var overriden); var displayName = LocalizedText.IsNullOrEmpty(reference.DisplayName?.Text) ? reference.BrowseName.Name : reference.DisplayName.AsString(); var child = new InstanceDeclarationModel { RootTypeId = typeId.AsString(session.MessageContext, namespaceFormat), NodeId = reference.NodeId.AsString(session.MessageContext, namespaceFormat), BrowseName = reference.BrowseName.AsString(session.MessageContext, namespaceFormat), NodeClass = nodeClass.Value, DisplayPath = parent == null ? displayName : $"{parent.DisplayPath}/{displayName}", DisplayName = displayName, BrowsePath = relativePath.Path, ModellingRule = modellingRule.Name.AsString(session.MessageContext, namespaceFormat), ModellingRuleId = modellingRule.Node.AsString(session.MessageContext, namespaceFormat), OverriddenDeclaration = overriden }; map[relativePath] = child; // add to list. children.Add((NodeId)reference.NodeId, child); } // check if nothing more to do. if (children.Count == 0) { return null; } // Add variable metadata var variables = children .Where(v => v.Value.NodeClass == NodeClass.Variable) .Select(v => v.Key); var variableMetadata = new List(); var errorInfo = await session.CollectVariableMetadataAsync(requestHeader, variables, variableMetadata, namespaceFormat, ct).ConfigureAwait(false); if (errorInfo != null) { return errorInfo; } foreach (var (nodeId, variable) in variables.Zip(variableMetadata)) { children[nodeId] = children[nodeId] with { VariableMetadata = variable }; } // Add method metadata var methods = children .Where(v => v.Value.NodeClass == NodeClass.Method) .Select(v => v.Key); var methodMetadata = new List(); errorInfo = await session.CollectMethodMetadataAsync(requestHeader, variables, methodMetadata, namespaceFormat, ct).ConfigureAwait(false); if (errorInfo != null) { return errorInfo; } foreach (var (nodeId, method) in methods.Zip(methodMetadata)) { children[nodeId] = children[nodeId] with { MethodMetadata = method }; } // Add descriptions var attributes = await session.ReadAttributeAsync(requestHeader, children.Keys, Attributes.Description, ct).ConfigureAwait(false); // TODO: Check attribute error info foreach (var (nodeId, description) in children.Keys.Zip(attributes)) { children[nodeId] = children[nodeId] with { Description = description.Item1.AsString() }; } // recusively collect instance declarations for the tree below. foreach (var child in children.Values) { instances.Add(child); await session.CollectInstanceDeclarationsAsync(requestHeader, typeId, child, instances, map, namespaceFormat, ct: ct).ConfigureAwait(false); } } return null; } /// /// Get method metadata /// /// /// /// /// /// /// internal static async Task<(VariableMetadataModel?, ServiceResultModel?)> GetVariableMetadataAsync( this IOpcUaSession session, RequestHeader requestHeader, NodeId nodeId, NamespaceFormat namespaceFormat, CancellationToken ct) { var results = new List(); var errorInfo = await session.CollectVariableMetadataAsync(requestHeader, nodeId.YieldReturn(), results, namespaceFormat, ct).ConfigureAwait(false); if (errorInfo != null) { return (null, errorInfo); } return (results.Single(), null); } /// /// Get method metadata /// /// /// /// /// /// /// /// internal static async Task CollectVariableMetadataAsync( this IOpcUaSession session, RequestHeader requestHeader, IEnumerable nodeIds, List metadata, NamespaceFormat namespaceFormat, CancellationToken ct) { if (!nodeIds.Any()) { return null; } var attributeIds = new uint[] { Attributes.DataType, Attributes.ArrayDimensions, Attributes.ValueRank }; var attributes = new Dictionary>(); var errorInfo = await session.ReadAttributesAsync(requestHeader, nodeIds, attributeIds, attributes, ct).ConfigureAwait(false); if (errorInfo != null) { return errorInfo; } metadata.AddRange(attributes.Select(node => new VariableMetadataModel { ArrayDimensions = node.Value[Attributes.ArrayDimensions] .GetValueOrDefaultEx()?.ToList(), DataType = new DataTypeMetadataModel { DataType = node.Value[Attributes.DataType].GetValueOrDefaultEx()? .AsString(session.MessageContext, namespaceFormat) }, ValueRank = (NodeValueRank?)node.Value[Attributes.ValueRank] .GetValueOrDefaultEx(v => v == ValueRanks.Any ? null : v) })); return null; } /// /// Get method metadata /// /// /// /// /// /// /// internal static async Task<(MethodMetadataModel?, ServiceResultModel?)> GetMethodMetadataAsync( this IOpcUaSession session, RequestHeader requestHeader, NodeId nodeId, NamespaceFormat namespaceFormat, CancellationToken ct) { var results = new List(); var errorInfo = await session.CollectMethodMetadataAsync(requestHeader, nodeId.YieldReturn(), results, namespaceFormat, ct).ConfigureAwait(false); if (errorInfo != null) { return (null, errorInfo); } return (results.Single(), null); } /// /// Get method metadata /// /// /// /// /// /// /// /// internal static async Task CollectMethodMetadataAsync( this IOpcUaSession session, RequestHeader requestHeader, IEnumerable nodeIds, List metadata, NamespaceFormat namespaceFormat, CancellationToken ct) { if (!nodeIds.Any()) { return null; } var browseDescriptions = new BrowseDescriptionCollection(nodeIds.Select(nodeId => new BrowseDescription { BrowseDirection = Opc.Ua.BrowseDirection.Both, IncludeSubtypes = true, NodeClassMask = 0, NodeId = nodeId, ReferenceTypeId = ReferenceTypeIds.Aggregates, ResultMask = (uint)BrowseResultMask.All } )); var response = await session.Services.BrowseAsync(requestHeader, null, 0, browseDescriptions, ct).ConfigureAwait(false); var results = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, browseDescriptions); if (results.ErrorInfo != null) { return results.ErrorInfo; } foreach (var result in results) { if (result.ErrorInfo != null) { return result.ErrorInfo; } var continuationPoint = result.Result.ContinuationPoint; var references = result.Result.References; IReadOnlyList? outputArguments = null; IReadOnlyList? inputArguments = null; string? objectId = null; foreach (var nodeReference in references) { if (outputArguments != null && inputArguments != null && !string.IsNullOrEmpty(objectId)) { break; } if (!nodeReference.IsForward) { if (nodeReference.ReferenceTypeId == ReferenceTypeIds.HasComponent) { objectId = nodeReference.NodeId.AsString(session.MessageContext, namespaceFormat); } continue; } var isInput = nodeReference.BrowseName == BrowseNames.InputArguments; if (!isInput && nodeReference.BrowseName != BrowseNames.OutputArguments) { continue; } var node = nodeReference.NodeId.ToNodeId(session.MessageContext.NamespaceUris); var (value, _) = await session.ReadValueAsync(requestHeader, node, ct).ConfigureAwait(false); if (value?.Value is not ExtensionObject[] argumentsList) { continue; } var argList = new List(); foreach (var argument in argumentsList.Select(a => (Argument)a.Body)) { var (dataTypeIdNode, _) = await session.ReadNodeAsync(requestHeader, argument.DataType, null, false, false, namespaceFormat, false, ct).ConfigureAwait(false); var arg = new MethodMetadataArgumentModel { Name = argument.Name, DefaultValue = argument.Value == null ? VariantValue.Null : session.Codec.Encode(new Variant(argument.Value), out var tmp), ValueRank = argument.ValueRank == ValueRanks.Scalar ? null : (NodeValueRank)argument.ValueRank, ArrayDimensions = argument.ArrayDimensions?.ToList(), Description = argument.Description?.ToString(), Type = dataTypeIdNode }; argList.Add(arg); } if (isInput) { inputArguments = argList; } else { outputArguments = argList; } } metadata.Add(new MethodMetadataModel { InputArguments = inputArguments, OutputArguments = outputArguments, ObjectId = objectId }); } return null; } /// /// Read node properties as node model /// /// /// /// /// /// /// /// /// /// /// internal static async Task<(NodeModel, ServiceResultModel?)> ReadNodeAsync( this IOpcUaSession session, RequestHeader header, NodeId nodeId, Opc.Ua.NodeClass? nodeClass, bool skipValue, bool rawMode, NamespaceFormat namespaceFormat, bool? children = null, CancellationToken ct = default) { if (rawMode) { var id = nodeId.AsString(session.MessageContext, namespaceFormat); System.Diagnostics.Debug.Assert(id != null); System.Diagnostics.Debug.Assert(!string.IsNullOrEmpty(id)); return (new NodeModel { NodeId = id, NodeClass = nodeClass?.ToServiceType() }, null); } return await session.ReadNodeAsync(header, nodeId, namespaceFormat, nodeClass, skipValue, children, ct).ConfigureAwait(false); } /// /// Read node model /// /// /// /// /// /// /// /// /// /// internal static async Task<(NodeModel, ServiceResultModel?)> ReadNodeAsync( this IOpcUaSession session, RequestHeader header, NodeId nodeId, NamespaceFormat namespaceFormat, Opc.Ua.NodeClass? nodeClass = null, bool skipValue = true, bool? children = null, CancellationToken ct = default) { var results = await session.ReadNodeAttributesAsync(header, nodeId, skipValue, nodeClass, ct).ConfigureAwait(false); var lookup = results.AsLookupTable(); var id = nodeId.AsString(session.MessageContext, namespaceFormat); System.Diagnostics.Debug.Assert(id != null); System.Diagnostics.Debug.Assert(!string.IsNullOrEmpty(id)); lookup.TryGetValue(Attributes.Value, out var value); var nodeModel = new NodeModel { Children = children, NodeId = id, Value = value.Item1 == null ? null : session.Codec.Encode( value.Item1.WrappedValue, out var type), SourceTimestamp = value.Item1?.SourceTimestamp, SourcePicoseconds = value.Item1?.SourcePicoseconds, ServerTimestamp = value.Item1?.ServerTimestamp, ServerPicoseconds = value.Item1?.ServerPicoseconds, ErrorInfo = value.Item2, BrowseName = lookup[Attributes.BrowseName].Item1? .GetValueOrDefaultEx()? .AsString(session.MessageContext, namespaceFormat), DisplayName = lookup[Attributes.DisplayName].Item1? .GetValueOrDefaultEx()? .ToString(), Description = lookup[Attributes.Description].Item1? .GetValueOrDefaultEx()? .ToString(), NodeClass = lookup[Attributes.NodeClass].Item1? .GetValueOrDefaultEx() .ToServiceType(), AccessRestrictions = (NodeAccessRestrictions?) lookup[Attributes.AccessRestrictions].Item1? .GetValueOrDefaultEx(v => v == 0 ? null : v), UserWriteMask = lookup[Attributes.UserWriteMask].Item1? .GetValueOrDefaultEx(), WriteMask = lookup[Attributes.WriteMask].Item1? .GetValueOrDefaultEx(), DataType = lookup[Attributes.DataType].Item1? .GetValueOrDefaultEx()? .AsString(session.MessageContext, namespaceFormat), ArrayDimensions = lookup[Attributes.ArrayDimensions].Item1? .GetValueOrDefaultEx(), ValueRank = (NodeValueRank?) lookup[Attributes.ValueRank].Item1? .GetValueOrDefaultEx(), AccessLevel = (NodeAccessLevel?) lookup[Attributes.AccessLevelEx].Item1? .GetValueOrDefaultEx(l => { // Or both if available var v = (l ?? 0) | lookup[Attributes.AccessLevel].Item1? .GetValueOrDefaultEx(b => b ?? 0); return v == 0 ? null : v; }), UserAccessLevel = (NodeAccessLevel?) lookup[Attributes.UserAccessLevel].Item1? .GetValueOrDefaultEx(), Historizing = lookup[Attributes.Historizing].Item1? .GetValueOrDefaultEx(), MinimumSamplingInterval = lookup[Attributes.MinimumSamplingInterval].Item1? .GetValueOrDefaultEx(), IsAbstract = lookup[Attributes.IsAbstract].Item1? .GetValueOrDefaultEx(), EventNotifier = (NodeEventNotifier?) lookup[Attributes.EventNotifier].Item1? .GetValueOrDefaultEx(v => v == 0 ? null : v), DataTypeDefinition = session.Codec.Encode( lookup[Attributes.DataTypeDefinition].Item1? .GetValueOrDefaultEx(), out _), InverseName = lookup[Attributes.InverseName].Item1? .GetValueOrDefaultEx()? .ToString(), Symmetric = lookup[Attributes.Symmetric].Item1? .GetValueOrDefaultEx(), ContainsNoLoops = lookup[Attributes.ContainsNoLoops].Item1? .GetValueOrDefaultEx(), Executable = lookup[Attributes.Executable].Item1? .GetValueOrDefaultEx(), UserExecutable = lookup[Attributes.UserExecutable].Item1? .GetValueOrDefaultEx(), UserRolePermissions = lookup[Attributes.UserRolePermissions].Item1? .GetValueOrDefaultEx()? .Select(ex => ex.Body) .OfType() .Select(p => p.ToServiceModel(session.MessageContext, namespaceFormat)).ToList(), RolePermissions = lookup[Attributes.RolePermissions].Item1? .GetValueOrDefaultEx()? .Select(ex => ex.Body) .OfType() .Select(p => p.ToServiceModel(session.MessageContext, namespaceFormat)).ToList() }; return (nodeModel, results.ErrorInfo ?? lookup[Attributes.NodeClass].Item2); } /// /// Find results /// /// /// /// /// /// /// internal record struct FindResult(QualifiedName Name, string? DisplayName, NodeId Node, ExpandedNodeId TypeDefinition, Opc.Ua.NodeClass NodeClass, ServiceResultModel? ErrorInfo = null); /// /// Finds the targets for the specified reference. /// /// /// /// /// /// /// /// /// /// /// internal static async Task<(IReadOnlyList, ServiceResultModel?)> FindAsync( this IOpcUaSession session, RequestHeader requestHeader, IEnumerable nodeIds, NodeId referenceTypeId, bool includeSubTypes = false, bool isInverse = false, uint nodeClassMask = 0, uint? maxResults = null, CancellationToken ct = default) { // construct browse request. var nodesToBrowse = new BrowseDescriptionCollection(nodeIds .Select(nodeId => new BrowseDescription { NodeId = nodeId, BrowseDirection = isInverse ? Opc.Ua.BrowseDirection.Inverse : Opc.Ua.BrowseDirection.Forward, ReferenceTypeId = referenceTypeId, IncludeSubtypes = includeSubTypes, NodeClassMask = nodeClassMask, ResultMask = (uint)BrowseResultMask.BrowseName | (uint)BrowseResultMask.DisplayName | (uint)BrowseResultMask.NodeClass | (uint)BrowseResultMask.TypeDefinition })); var continuationPoints = new ByteStringCollection(); try { var response = await session.Services.BrowseAsync(requestHeader, null, maxResults ?? 0u, nodesToBrowse, ct).ConfigureAwait(false); var results = response.Validate(response.Results, s => s.StatusCode, response.DiagnosticInfos, nodesToBrowse); var targetIds = new List(); if (results.ErrorInfo != null) { return (targetIds, results.ErrorInfo); } foreach (var result in results) { // check for error. if (result.ErrorInfo != null) { targetIds.Add(new FindResult(QualifiedName.Null, null, NodeId.Null, ExpandedNodeId.Null, Opc.Ua.NodeClass.Unspecified, result.ErrorInfo)); continue; } // check for continuation point. if (result.Result.ContinuationPoint?.Length > 0) { continuationPoints.Add(result.Result.ContinuationPoint); } if (!Extract(targetIds, result.Result.References)) { break; } } while (continuationPoints.Count > 0 && !maxResults.HasValue) { var next = await session.Services.BrowseNextAsync(requestHeader, false, continuationPoints, ct).ConfigureAwait(false); var nextResults = next.Validate(next.Results, s => s.StatusCode, next.DiagnosticInfos, continuationPoints); if (nextResults.ErrorInfo != null) { return (targetIds, nextResults.ErrorInfo); } continuationPoints = []; foreach (var result in nextResults) { // check for error. if (result.ErrorInfo != null) { targetIds.Add(new FindResult(QualifiedName.Null, null, NodeId.Null, ExpandedNodeId.Null, Opc.Ua.NodeClass.Unspecified, result.ErrorInfo)); continue; } // check for continuation point. if (result.Result.ContinuationPoint?.Length > 0) { continuationPoints.Add(result.Result.ContinuationPoint); } if (!Extract(targetIds, result.Result.References)) { break; } } } return (targetIds, null); } finally { // release continuation points. if (continuationPoints.Count > 0) { try { await session.Services.BrowseNextAsync(requestHeader, true, continuationPoints, ct).ConfigureAwait(false); } catch { } } } static bool Extract(List targetIds, ReferenceDescriptionCollection references) { // get the node ids. foreach (var reference in references) { if (NodeId.IsNull(reference.NodeId) || reference.NodeId.IsAbsolute) { targetIds.Add(new FindResult(QualifiedName.Null, null, NodeId.Null, ExpandedNodeId.Null, Opc.Ua.NodeClass.Unspecified, new ServiceResultModel { ErrorMessage = "Target node is null or absolute" })); continue; } targetIds.Add(new FindResult(reference.BrowseName, reference.DisplayName?.Text, (NodeId)reference.NodeId, reference.TypeDefinition, reference.NodeClass)); } return true; } } /// /// Helper struct return /// /// /// /// internal record struct BrowseResult(BrowseDescription? Description, ReferenceDescriptionCollection? References, ServiceResultModel? ErrorInfo); /// /// Enumerates browse results inline /// /// /// /// /// /// /// internal static async IAsyncEnumerable BrowseAsync( this IOpcUaSession session, RequestHeader requestHeader, ViewDescription? view, BrowseDescriptionCollection nodesToBrowse, [EnumeratorCancellation] CancellationToken ct = default) { var limits = await session.GetOperationLimitsAsync(ct).ConfigureAwait(false); var maxContinuationPoints = limits.GetMaxBrowseContinuationPoints(); foreach (var nodesToBrowseBatch in nodesToBrowse.Batch(limits.GetMaxNodesPerBrowse())) { var browseDescriptions = new BrowseDescriptionCollection(nodesToBrowseBatch); var firstResponse = await session.Services.BrowseAsync(requestHeader, view, 0, browseDescriptions, ct).ConfigureAwait(false); var firstResults = firstResponse.Validate(firstResponse.Results, s => s.StatusCode, firstResponse.DiagnosticInfos, browseDescriptions); if (firstResults.ErrorInfo != null) { yield return new BrowseResult(null, null, firstResults.ErrorInfo); } var continuationPoints = firstResults .Where(r => r.Result.ContinuationPoint?.Length > 0) .Select(r => (r.Request, r.Result.ContinuationPoint)); try { foreach (var result in firstResults) { yield return new BrowseResult(result.Request, result.Result.References, result.ErrorInfo); } while (true) { var next = continuationPoints.Take(maxContinuationPoints).ToList(); if (next.Count == 0) { break; } var nextResponse = await session.Services.BrowseNextAsync(requestHeader, false, new ByteStringCollection(next.Select(r => r.ContinuationPoint)), ct).ConfigureAwait(false); var nextResults = firstResponse.Validate(nextResponse.Results, s => s.StatusCode, nextResponse.DiagnosticInfos, next); if (nextResults.ErrorInfo != null) { yield return new BrowseResult(null, null, nextResults.ErrorInfo); } foreach (var result in nextResults) { yield return new BrowseResult( result.Request.Request, result.Result.References, result.ErrorInfo); } continuationPoints = continuationPoints.Concat(nextResults .Where(r => r.Result.ContinuationPoint?.Length > 0) .Select(r => (r.Request.Request, r.Result.ContinuationPoint))); } } finally { // Release any dangling continuation points foreach (var batch in continuationPoints .Select(r => r.ContinuationPoint) .Batch(maxContinuationPoints)) { await session.Services.BrowseNextAsync(requestHeader, true, new ByteStringCollection(batch), ct).ConfigureAwait(false); } } } } /// /// Recursively collects the variables in a NodeState and /// returns a collection of BrowsePaths. /// /// /// /// /// /// private static List GetBrowsePathFromNodeState( this IOpcUaSession session, NodeId rootId, NodeState parent, RelativePath? parentPath, List? browsePaths = null) { browsePaths ??= []; var children = new List(); parent.GetChildren(session.SystemContext, children); foreach (var child in children) { var browsePath = new BrowsePath { StartingNode = rootId, Handle = child }; if (parentPath != null) { browsePath.RelativePath.Elements.AddRange(parentPath.Elements); } var element = new RelativePathElement { ReferenceTypeId = child.ReferenceTypeId, IsInverse = false, IncludeSubtypes = false, TargetName = child.BrowseName }; browsePath.RelativePath.Elements.Add(element); browsePaths.Add(browsePath); browsePaths = session.GetBrowsePathFromNodeState(rootId, child, browsePath.RelativePath, browsePaths); } return browsePaths; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/StackModelsEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Extensions.Serializers; using Opc.Ua; using Opc.Ua.Extensions; using DiagnosticsLevel = Publisher.Models.DiagnosticsLevel; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading.Tasks; using System.Threading; /// /// Stack models extensions /// public static class StackModelsEx { /// /// Convert diagnostics to request header /// /// /// /// public static RequestHeader ToRequestHeader(this RequestHeaderModel? header, TimeProvider? timeProvider = null) { var timestamp = header?.Diagnostics?.TimeStamp ?? (timeProvider ?? TimeProvider.System).GetUtcNow().UtcDateTime; return new RequestHeader { AuditEntryId = header?.Diagnostics?.AuditId ?? Guid.NewGuid().ToString(), ReturnDiagnostics = (uint)(header?.Diagnostics?.Level ?? DiagnosticsLevel.Status) .ToStackType(), Timestamp = timestamp, TimeoutHint = (uint)(header?.OperationTimeout ?? 0), AdditionalHeader = null // TODO }; } /// /// Convert diagnostics to request header /// /// /// /// [return: NotNullIfNotNull(nameof(model))] public static ViewDescription? ToStackModel(this BrowseViewModel? model, IServiceMessageContext context) { if (model is null) { return null; } return new ViewDescription { Timestamp = model.Timestamp ?? DateTime.MinValue, ViewVersion = model.Version ?? 0, ViewId = model.ViewId.ToNodeId(context) }; } /// /// Convert role permission type to service model /// /// /// /// /// /// public static RolePermissionModel ToServiceModel(this RolePermissionType type, IServiceMessageContext context, NamespaceFormat namespaceFormat) { var roleId = type.RoleId.AsString(context, namespaceFormat); if (roleId == null) { throw new ArgumentException("Permission type not a valid node id"); } return new RolePermissionModel { RoleId = roleId, Permissions = ((PermissionType)type.Permissions).ToServiceType() }; } /// /// Convert to stack model /// /// /// [return: NotNullIfNotNull(nameof(model))] public static DataChangeFilter? ToStackModel(this DataChangeFilterModel? model) { if (model is null) { return null; } return new DataChangeFilter { DeadbandValue = model.DeadbandValue ?? 0.0, DeadbandType = (uint)model.DeadbandType.ToStackType(), Trigger = model.DataChangeTrigger.ToStackType() }; } /// /// Convert to stack model /// /// /// /// [return: NotNullIfNotNull(nameof(model))] public static AggregateFilter? ToStackModel(this AggregateFilterModel? model, IServiceMessageContext context) { if (model is null) { return null; } return new AggregateFilter { AggregateConfiguration = model.AggregateConfiguration.ToStackModel(), AggregateType = model.AggregateTypeId.ToNodeId(context), StartTime = model.StartTime ?? DateTime.MinValue, ProcessingInterval = (model.ProcessingInterval?.TotalMilliseconds) ?? 0.0 }; } /// /// Convert to stack model /// /// /// public static AggregateConfiguration ToStackModel( this AggregateConfigurationModel? model) { if (model is null) { return new AggregateConfiguration { UseServerCapabilitiesDefaults = true }; } return new AggregateConfiguration { PercentDataBad = model.PercentDataBad ?? 0, PercentDataGood = model.PercentDataGood ?? 0, TreatUncertainAsBad = model.TreatUncertainAsBad ?? true, UseSlopedExtrapolation = model.UseSlopedExtrapolation ?? true }; } /// /// Convert to stack model /// /// /// /// [return: NotNullIfNotNull(nameof(model))] public static SimpleAttributeOperand? ToStackModel(this SimpleAttributeOperandModel? model, IServiceMessageContext context) { if (model is null) { return null; } return new SimpleAttributeOperand { TypeDefinitionId = model.TypeDefinitionId.ToNodeId(context), AttributeId = (uint)(model.AttributeId ?? NodeAttribute.Value), BrowsePath = new QualifiedNameCollection(model.BrowsePath == null ? [] : model.BrowsePath.Select(n => n.ToQualifiedName(context))), IndexRange = model.IndexRange }; } /// /// Convert to service model /// /// /// /// /// [return: NotNullIfNotNull(nameof(model))] public static SimpleAttributeOperandModel? ToServiceModel(this SimpleAttributeOperand? model, IServiceMessageContext context, NamespaceFormat namespaceFormat) { if (model is null) { return null; } return new SimpleAttributeOperandModel { TypeDefinitionId = model.TypeDefinitionId .AsString(context, namespaceFormat), AttributeId = (NodeAttribute)model.AttributeId, BrowsePath = model.BrowsePath? .Select(p => p.AsString(context, namespaceFormat)) .ToArray(), IndexRange = model.IndexRange }; } /// /// Convert user token policies to service model /// /// /// /// public static IReadOnlyList ToServiceModel( this UserTokenPolicyCollection policies, IJsonSerializer serializer) { if (policies == null || policies.Count == 0) { return new List { new() { Id = "Anonymous", CredentialType = CredentialType.None } }; } return policies .Select(p => p.ToServiceModel(serializer)!) .Where(p => p != null) .Distinct() .ToList(); } /// /// Convert user token policy to service model /// /// /// /// public static AuthenticationMethodModel? ToServiceModel( this UserTokenPolicy? policy, IJsonSerializer serializer) { if (policy == null) { return null; } var configuration = VariantValue.Null; var credentialType = CredentialType.None; switch (policy.TokenType) { case UserTokenType.Anonymous: break; case UserTokenType.UserName: credentialType = CredentialType.UserName; break; case UserTokenType.Certificate: credentialType = CredentialType.X509Certificate; configuration = policy.IssuerEndpointUrl; break; case UserTokenType.IssuedToken: switch (policy.IssuedTokenType) { case "http://opcfoundation.org/UA/UserToken#JWT": credentialType = CredentialType.JwtToken; try { // See part 6 configuration = serializer.Parse(policy.IssuerEndpointUrl); } catch { // Store as string configuration = policy.IssuerEndpointUrl; } break; default: // TODO return null; } break; default: return null; } return new AuthenticationMethodModel { Id = policy.PolicyId, SecurityPolicy = policy.SecurityPolicyUri, Configuration = configuration, CredentialType = credentialType }; } /// /// Makes a user identity /// /// /// /// /// /// public static async ValueTask ToUserIdentityAsync(this CredentialModel? credential, ApplicationConfiguration configuration, CancellationToken ct = default) { if (credential == null || credential.Type == CredentialType.None) { return new UserIdentity(new AnonymousIdentityToken()); } var identity = credential.Value; if (identity == null) { throw new ServiceResultException(StatusCodes.BadInvalidArgument, $"Credential type {credential.Type} requires providing a credential value."); } switch (credential.Type) { case CredentialType.UserName: return new UserIdentity(identity.User, identity.Password); case CredentialType.X509Certificate: var subjectName = identity.User; var thumbprint = identity.Thumbprint; var passCode = identity.Password; if (thumbprint != null || subjectName != null) { using var users = configuration.SecurityConfiguration .TrustedUserCertificates.OpenStore(); var userCertWithPrivateKey = await users.LoadPrivateKeyAsync(thumbprint, subjectName, null, null /* TODO add rsa/ecc*/, passCode, ct).ConfigureAwait(false); if (userCertWithPrivateKey == null) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, $"User certificate for {subjectName ?? thumbprint} missing " + "or provided password invalid. Please configure the User " + "Certificate correctly in the User certificate store."); } return new UserIdentity(userCertWithPrivateKey); } throw new ServiceResultException(StatusCodes.BadNotSupported, "X509Certificate credential requires to set either a thumbprint or subject name (user)."); case CredentialType.None: return new UserIdentity(new AnonymousIdentityToken()); default: throw new ServiceResultException(StatusCodes.BadNotSupported, $"Credential type {credential!.Type} is not supported"); } } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/StackTypesEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { using Azure.IIoT.OpcUa.Publisher.Models; using UaAggregateBits = Opc.Ua.AggregateBits; using UaApplicationType = Opc.Ua.ApplicationType; using UaBrowseDirection = Opc.Ua.BrowseDirection; using UaDataChangeTrigger = Opc.Ua.DataChangeTrigger; using UaDataSetFieldContentMask = Opc.Ua.DataSetFieldContentMask; using UaDeadbandType = Opc.Ua.DeadbandType; using UaDiagnosticsLevel = Opc.Ua.DiagnosticsMasks; using UaExceptionDeviationFormat = Opc.Ua.ExceptionDeviationFormat; using UaFilterOperator = Opc.Ua.FilterOperator; using JsonDataSetMessageContentMask = Opc.Ua.JsonDataSetMessageContentMask; using JsonNetworkMessageContentMask = Opc.Ua.JsonNetworkMessageContentMask; using UaSecurityMode = Opc.Ua.MessageSecurityMode; using UaMonitoringMode = Opc.Ua.MonitoringMode; using UaNodeClass = Opc.Ua.NodeClass; using UaPermissionType = Opc.Ua.PermissionType; using UaTimestampsToReturn = Opc.Ua.TimestampsToReturn; using UadpDataSetMessageContentMask = Opc.Ua.UadpDataSetMessageContentMask; using UadpNetworkMessageContentMask = Opc.Ua.UadpNetworkMessageContentMask; using System; using System.Collections.Generic; /// /// Stack types conversions /// internal static class StackTypesEx { /// /// Convert node class /// /// /// public static NodeClass? ToServiceType(this UaNodeClass nodeClass) { switch (nodeClass) { case UaNodeClass.Object: return NodeClass.Object; case UaNodeClass.ObjectType: return NodeClass.ObjectType; case UaNodeClass.Variable: return NodeClass.Variable; case UaNodeClass.VariableType: return NodeClass.VariableType; case UaNodeClass.Method: return NodeClass.Method; case UaNodeClass.DataType: return NodeClass.DataType; case UaNodeClass.ReferenceType: return NodeClass.ReferenceType; case UaNodeClass.View: return NodeClass.View; default: return null; } } /// /// Convert node class /// /// /// public static UaNodeClass ToStackType(this NodeClass nodeClass) { switch (nodeClass) { case NodeClass.Object: return UaNodeClass.Object; case NodeClass.ObjectType: return UaNodeClass.ObjectType; case NodeClass.Variable: return UaNodeClass.Variable; case NodeClass.VariableType: return UaNodeClass.VariableType; case NodeClass.Method: return UaNodeClass.Method; case NodeClass.DataType: return UaNodeClass.DataType; case NodeClass.ReferenceType: return UaNodeClass.ReferenceType; case NodeClass.View: return UaNodeClass.View; default: return UaNodeClass.Unspecified; } } /// /// Convert mask to a list of node classes /// /// /// public static UaNodeClass ToStackMask(this IReadOnlyList? nodeClasses) { var mask = 0u; if (nodeClasses != null) { foreach (var nodeClass in nodeClasses) { mask |= (uint)nodeClass.ToStackType(); } } return (UaNodeClass)mask; } /// /// Convert browse direction /// /// /// public static UaBrowseDirection ToStackType(this BrowseDirection mode) { switch (mode) { case BrowseDirection.Forward: return UaBrowseDirection.Forward; case BrowseDirection.Backward: return UaBrowseDirection.Inverse; case BrowseDirection.Both: return UaBrowseDirection.Both; default: return UaBrowseDirection.Forward; } } /// /// Convert permissions /// /// /// public static RolePermissions? ToServiceType(this UaPermissionType permissions) { if (permissions == UaPermissionType.None) { return null; } return (RolePermissions)permissions; } /// /// Convert security mode /// /// /// public static SecurityMode? ToServiceType(this UaSecurityMode mode) { switch (mode) { case UaSecurityMode.None: return SecurityMode.None; case UaSecurityMode.Sign: return SecurityMode.Sign; case UaSecurityMode.SignAndEncrypt: return SecurityMode.SignAndEncrypt; default: return null; } } /// /// Match security model /// /// /// /// public static bool IsSame(this UaSecurityMode mode, SecurityMode securityMode) { switch (securityMode) { case SecurityMode.Best: return true; // Any security mode case SecurityMode.Sign: return mode == UaSecurityMode.Sign; case SecurityMode.SignAndEncrypt: return mode == UaSecurityMode.SignAndEncrypt; case SecurityMode.None: return mode == UaSecurityMode.None; case SecurityMode.NotNone: return mode != UaSecurityMode.None; default: return false; } } /// /// Convert application type /// /// /// public static ApplicationType? ToServiceType(this UaApplicationType type) { switch (type) { case UaApplicationType.Client: return ApplicationType.Client; case UaApplicationType.DiscoveryServer: return ApplicationType.DiscoveryServer; case UaApplicationType.Server: return ApplicationType.Server; case UaApplicationType.ClientAndServer: return ApplicationType.ClientAndServer; default: return null; } } /// /// Convert to diagnostics mask /// /// /// public static UaDiagnosticsLevel ToStackType(this DiagnosticsLevel level) { var result = UaDiagnosticsLevel.None; if (level == DiagnosticsLevel.None) { return result; } result |= UaDiagnosticsLevel.SymbolicIdAndText; if (level == DiagnosticsLevel.Status) { return result; } result |= UaDiagnosticsLevel.AdditionalInfo; if (level == DiagnosticsLevel.Information) { return result; } result |= UaDiagnosticsLevel.InnerStatusCode; result |= UaDiagnosticsLevel.InnerDiagnostics; if (level == DiagnosticsLevel.Debug) { return result; } result |= UaDiagnosticsLevel.All; return result; } /// /// Convert monitoring mode /// /// /// public static UaMonitoringMode? ToStackType(this MonitoringMode? mode) { if (mode == null) { return null; } switch (mode) { case MonitoringMode.Disabled: return UaMonitoringMode.Disabled; case MonitoringMode.Sampling: return UaMonitoringMode.Sampling; default: return UaMonitoringMode.Reporting; } } /// /// Convert timestamp to return /// /// /// public static UaTimestampsToReturn ToStackType(this TimestampsToReturn? mode) { switch (mode) { case TimestampsToReturn.None: return UaTimestampsToReturn.Neither; case TimestampsToReturn.Server: return UaTimestampsToReturn.Server; case TimestampsToReturn.Source: return UaTimestampsToReturn.Source; default: return UaTimestampsToReturn.Both; } } /// /// Convert deadband type /// /// /// public static UaDeadbandType ToStackType(this DeadbandType? mode) { if (mode == null) { return UaDeadbandType.None; } switch (mode.Value) { case DeadbandType.Absolute: return UaDeadbandType.Absolute; case DeadbandType.Percent: return UaDeadbandType.Percent; default: return UaDeadbandType.None; } } /// /// Convert deadband type /// /// /// public static UaDataChangeTrigger ToStackType(this DataChangeTriggerType? mode) { if (mode == null) { // Default is status and value change triggering return UaDataChangeTrigger.StatusValue; } switch (mode.Value) { case DataChangeTriggerType.Status: return UaDataChangeTrigger.Status; case DataChangeTriggerType.StatusValue: return UaDataChangeTrigger.StatusValue; case DataChangeTriggerType.StatusValueTimestamp: return UaDataChangeTrigger.StatusValueTimestamp; default: return UaDataChangeTrigger.StatusValue; } } /// /// Convert to stack type /// /// /// /// public static UaFilterOperator ToStackType(this FilterOperatorType type) { switch (type) { case FilterOperatorType.Equals: return UaFilterOperator.Equals; case FilterOperatorType.IsNull: return UaFilterOperator.IsNull; case FilterOperatorType.GreaterThan: return UaFilterOperator.GreaterThan; case FilterOperatorType.LessThan: return UaFilterOperator.LessThan; case FilterOperatorType.GreaterThanOrEqual: return UaFilterOperator.GreaterThanOrEqual; case FilterOperatorType.LessThanOrEqual: return UaFilterOperator.LessThanOrEqual; case FilterOperatorType.Like: return UaFilterOperator.Like; case FilterOperatorType.Not: return UaFilterOperator.Not; case FilterOperatorType.Between: return UaFilterOperator.Between; case FilterOperatorType.InList: return UaFilterOperator.InList; case FilterOperatorType.And: return UaFilterOperator.And; case FilterOperatorType.Or: return UaFilterOperator.Or; case FilterOperatorType.Cast: return UaFilterOperator.Cast; case FilterOperatorType.InView: return UaFilterOperator.InView; case FilterOperatorType.OfType: return UaFilterOperator.OfType; case FilterOperatorType.RelatedTo: return UaFilterOperator.RelatedTo; case FilterOperatorType.BitwiseAnd: return UaFilterOperator.BitwiseAnd; case FilterOperatorType.BitwiseOr: return UaFilterOperator.BitwiseOr; default: throw new NotSupportedException($"{type} not supported"); } } /// /// Convert to stack type /// /// /// /// public static FilterOperatorType ToServiceType(this UaFilterOperator type) { switch (type) { case UaFilterOperator.Equals: return FilterOperatorType.Equals; case UaFilterOperator.IsNull: return FilterOperatorType.IsNull; case UaFilterOperator.GreaterThan: return FilterOperatorType.GreaterThan; case UaFilterOperator.LessThan: return FilterOperatorType.LessThan; case UaFilterOperator.GreaterThanOrEqual: return FilterOperatorType.GreaterThanOrEqual; case UaFilterOperator.LessThanOrEqual: return FilterOperatorType.LessThanOrEqual; case UaFilterOperator.Like: return FilterOperatorType.Like; case UaFilterOperator.Not: return FilterOperatorType.Not; case UaFilterOperator.Between: return FilterOperatorType.Between; case UaFilterOperator.InList: return FilterOperatorType.InList; case UaFilterOperator.And: return FilterOperatorType.And; case UaFilterOperator.Or: return FilterOperatorType.Or; case UaFilterOperator.Cast: return FilterOperatorType.Cast; case UaFilterOperator.InView: return FilterOperatorType.InView; case UaFilterOperator.OfType: return FilterOperatorType.OfType; case UaFilterOperator.RelatedTo: return FilterOperatorType.RelatedTo; case UaFilterOperator.BitwiseAnd: return FilterOperatorType.BitwiseAnd; case UaFilterOperator.BitwiseOr: return FilterOperatorType.BitwiseOr; default: throw new NotSupportedException($"{type} not supported"); } } /// /// To service type /// /// /// public static ExceptionDeviationType? ToExceptionDeviationType( this UaExceptionDeviationFormat? format) { switch (format) { case UaExceptionDeviationFormat.AbsoluteValue: return ExceptionDeviationType.AbsoluteValue; case UaExceptionDeviationFormat.PercentOfValue: return ExceptionDeviationType.PercentOfValue; case UaExceptionDeviationFormat.PercentOfRange: return ExceptionDeviationType.PercentOfRange; case UaExceptionDeviationFormat.PercentOfEURange: return ExceptionDeviationType.PercentOfEURange; default: return null; } } /// /// Convert data location /// /// /// public static DataLocation? ToDataLocation(this UaAggregateBits aggregateBits) { if ((aggregateBits & UaAggregateBits.Calculated) != 0) { return DataLocation.Calculated; } else if ((aggregateBits & UaAggregateBits.Interpolated) != 0) { return DataLocation.Interpolated; } else { return null; } } /// /// Convert additional data /// /// /// public static AdditionalData? ToAdditionalData(this UaAggregateBits aggregateBits) { AdditionalData result = 0; if ((aggregateBits & UaAggregateBits.ExtraData) != 0) { result |= AdditionalData.ExtraData; } if ((aggregateBits & UaAggregateBits.MultipleValues) != 0) { result |= AdditionalData.MultipleValues; } if ((aggregateBits & UaAggregateBits.Partial) != 0) { result |= AdditionalData.Partial; } if (result == 0) { return null; } return result; } /// /// Get network message content mask /// /// /// /// public static uint ToStackType(this NetworkMessageContentFlags? mask, MessageEncoding? encoding) { mask ??= NetworkMessageContentFlags.NetworkMessageHeader | NetworkMessageContentFlags.NetworkMessageNumber | NetworkMessageContentFlags.DataSetMessageHeader | NetworkMessageContentFlags.PublisherId | NetworkMessageContentFlags.DataSetClassId; switch (encoding) { case MessageEncoding.Uadp: return (uint)ToUadpStackType(mask.Value); case MessageEncoding.Json: return (uint)ToJsonStackType(mask.Value); } return (uint)ToJsonStackType(mask.Value); } /// /// Get network message content mask /// /// /// /// /// public static uint ToStackType(this DataSetMessageContentFlags? mask, DataSetFieldContentFlags? fieldMask, MessageEncoding? encoding) { mask ??= DataSetMessageContentFlags.DataSetWriterId | DataSetMessageContentFlags.DataSetWriterName | DataSetMessageContentFlags.MetaDataVersion | DataSetMessageContentFlags.MajorVersion | DataSetMessageContentFlags.MinorVersion | DataSetMessageContentFlags.SequenceNumber | DataSetMessageContentFlags.Timestamp | DataSetMessageContentFlags.MessageType | DataSetMessageContentFlags.Status; switch (encoding) { case MessageEncoding.Uadp: return (uint)ToUadpStackType(mask.Value); case MessageEncoding.Json: return (uint)ToJsonStackType(mask.Value, fieldMask); } return (uint)ToJsonStackType(mask.Value, fieldMask); } /// /// Get network message content mask /// /// /// private static JsonNetworkMessageContentMask ToJsonStackType(this NetworkMessageContentFlags mask) { var result = JsonNetworkMessageContentMask.None; if ((mask & NetworkMessageContentFlags.PublisherId) != 0) { result |= JsonNetworkMessageContentMask.PublisherId; } if ((mask & NetworkMessageContentFlags.DataSetClassId) != 0) { result |= JsonNetworkMessageContentMask.DataSetClassId; } if ((mask & NetworkMessageContentFlags.ReplyTo) != 0) { result |= JsonNetworkMessageContentMask.ReplyTo; } if ((mask & NetworkMessageContentFlags.NetworkMessageHeader) != 0) { result |= JsonNetworkMessageContentMask.NetworkMessageHeader; } else { // If not set, bits 3, 4 and 5 can also not be set result = JsonNetworkMessageContentMask.None; } if ((mask & NetworkMessageContentFlags.MonitoredItemMessage) != 0) { // If monitored item message, then no network message header result = JsonNetworkMessageContentMask.None; } if ((mask & NetworkMessageContentFlags.DataSetMessageHeader) != 0) { result |= JsonNetworkMessageContentMask.DataSetMessageHeader; } if ((mask & NetworkMessageContentFlags.SingleDataSetMessage) != 0) { result |= JsonNetworkMessageContentMask.SingleDataSetMessage; } return result; } /// /// Get dataset message content mask /// /// /// /// private static JsonDataSetMessageContentMask ToJsonStackType(this DataSetMessageContentFlags mask, DataSetFieldContentFlags? fieldMask) { var result = JsonDataSetMessageContentMask.None; if ((mask & DataSetMessageContentFlags.Timestamp) != 0) { result |= JsonDataSetMessageContentMask.Timestamp; } if ((mask & DataSetMessageContentFlags.Status) != 0) { result |= JsonDataSetMessageContentMask.Status; } if ((mask & DataSetMessageContentFlags.MetaDataVersion) != 0) { result |= JsonDataSetMessageContentMask.MetaDataVersion; } if ((mask & DataSetMessageContentFlags.SequenceNumber) != 0) { result |= JsonDataSetMessageContentMask.SequenceNumber; } if ((mask & DataSetMessageContentFlags.DataSetWriterId) != 0) { result |= JsonDataSetMessageContentMask.DataSetWriterId; } if ((mask & DataSetMessageContentFlags.MessageType) != 0) { result |= JsonDataSetMessageContentMask.MessageType; } if ((mask & DataSetMessageContentFlags.DataSetWriterName) != 0) { result |= JsonDataSetMessageContentMask.DataSetWriterName; } if ((mask & DataSetMessageContentFlags.ReversibleFieldEncoding) != 0) { result |= JsonDataSetMessageContentMask.FieldEncoding1; } if (fieldMask != null) { if ((fieldMask & DataSetFieldContentFlags.NodeId) != 0) { result |= JsonDataSetMessageContentMaskEx.NodeId; } if ((fieldMask & DataSetFieldContentFlags.DisplayName) != 0) { result |= JsonDataSetMessageContentMaskEx.DisplayName; } if ((fieldMask & DataSetFieldContentFlags.ExtensionFields) != 0) { result |= JsonDataSetMessageContentMaskEx.ExtensionFields; } if ((fieldMask & DataSetFieldContentFlags.EndpointUrl) != 0) { result |= JsonDataSetMessageContentMaskEx.EndpointUrl; } if ((fieldMask & DataSetFieldContentFlags.ApplicationUri) != 0) { result |= JsonDataSetMessageContentMaskEx.ApplicationUri; } } return result; } /// /// Get network message content mask /// /// /// private static UadpNetworkMessageContentMask ToUadpStackType(this NetworkMessageContentFlags mask) { var result = UadpNetworkMessageContentMask.None; if ((mask & NetworkMessageContentFlags.PublisherId) != 0) { result |= UadpNetworkMessageContentMask.PublisherId; } if ((mask & NetworkMessageContentFlags.GroupHeader) != 0) { result |= UadpNetworkMessageContentMask.GroupHeader; } if ((mask & NetworkMessageContentFlags.WriterGroupId) != 0) { result |= UadpNetworkMessageContentMask.WriterGroupId; } if ((mask & NetworkMessageContentFlags.GroupVersion) != 0) { result |= UadpNetworkMessageContentMask.GroupVersion; } if ((mask & NetworkMessageContentFlags.NetworkMessageNumber) != 0) { result |= UadpNetworkMessageContentMask.NetworkMessageNumber; } if ((mask & NetworkMessageContentFlags.SequenceNumber) != 0) { result |= UadpNetworkMessageContentMask.SequenceNumber; } if ((mask & NetworkMessageContentFlags.PayloadHeader) != 0) { result |= UadpNetworkMessageContentMask.PayloadHeader; } if ((mask & NetworkMessageContentFlags.Timestamp) != 0) { result |= UadpNetworkMessageContentMask.Timestamp; } if ((mask & NetworkMessageContentFlags.Picoseconds) != 0) { result |= UadpNetworkMessageContentMask.PicoSeconds; } if ((mask & NetworkMessageContentFlags.DataSetClassId) != 0) { result |= UadpNetworkMessageContentMask.DataSetClassId; } if ((mask & NetworkMessageContentFlags.PromotedFields) != 0) { result |= UadpNetworkMessageContentMask.PromotedFields; } return result; } /// /// Get dataset message content mask /// /// /// private static UadpDataSetMessageContentMask ToUadpStackType(this DataSetMessageContentFlags mask) { var result = UadpDataSetMessageContentMask.None; if ((mask & DataSetMessageContentFlags.Timestamp) != 0) { result |= UadpDataSetMessageContentMask.Timestamp; } if ((mask & DataSetMessageContentFlags.PicoSeconds) != 0) { result |= UadpDataSetMessageContentMask.PicoSeconds; } if ((mask & DataSetMessageContentFlags.Status) != 0) { result |= UadpDataSetMessageContentMask.Status; } if ((mask & DataSetMessageContentFlags.SequenceNumber) != 0) { result |= UadpDataSetMessageContentMask.SequenceNumber; } if ((mask & DataSetMessageContentFlags.MinorVersion) != 0) { result |= UadpDataSetMessageContentMask.MinorVersion; } if ((mask & DataSetMessageContentFlags.MajorVersion) != 0) { result |= UadpDataSetMessageContentMask.MajorVersion; } return result; } /// /// Get dataset message content mask /// /// /// public static UaDataSetFieldContentMask ToStackType(this DataSetFieldContentFlags? mask) { mask ??= DataSetFieldContentFlags.StatusCode | DataSetFieldContentFlags.SourceTimestamp | DataSetFieldContentFlags.SourcePicoSeconds | DataSetFieldContentFlags.ServerPicoSeconds | DataSetFieldContentFlags.ServerTimestamp ; var result = UaDataSetFieldContentMask.None; if ((mask & DataSetFieldContentFlags.StatusCode) != 0) { result |= UaDataSetFieldContentMask.StatusCode; } if ((mask & DataSetFieldContentFlags.SourceTimestamp) != 0) { result |= UaDataSetFieldContentMask.SourceTimestamp; } if ((mask & DataSetFieldContentFlags.ServerTimestamp) != 0) { result |= UaDataSetFieldContentMask.ServerTimestamp; } if ((mask & DataSetFieldContentFlags.SourcePicoSeconds) != 0) { result |= UaDataSetFieldContentMask.SourcePicoSeconds; } if ((mask & DataSetFieldContentFlags.ServerPicoSeconds) != 0) { result |= UaDataSetFieldContentMask.ServerPicoSeconds; } if ((mask & DataSetFieldContentFlags.RawData) != 0) { result |= UaDataSetFieldContentMask.RawData; } if ((mask & DataSetFieldContentFlags.SingleFieldDegradeToValue) != 0) { result |= DataSetFieldContentMaskEx.SingleFieldDegradeToValue; } return result; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/SubscriptionModelEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Models { using System; /// /// Subscription model extensions /// internal static class SubscriptionModelEx { /// /// Returns a string that uniquely identifies the subscription based on /// the configuration /// /// public static string CreateSubscriptionId(this SubscriptionModel model) { return $"{model.ToString().ToSha1Hash()}[P{model.Priority ?? 0}" + $"@{(int)(model.PublishingInterval?.TotalMilliseconds ?? 0)}]"; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Extensions/VariantEncoderEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { using Azure.IIoT.OpcUa.Encoders; using Furly.Extensions.Serializers; using Opc.Ua; using Opc.Ua.Extensions; /// /// Variant encoder extensions /// public static class VariantEncoderEx { /// /// Decode with data type as string /// /// /// /// /// public static Variant Decode(this IVariantEncoder encoder, VariantValue value, string? type) { return encoder.Decode(value, string.IsNullOrEmpty(type) ? BuiltInType.Null : TypeInfo.GetBuiltInType(type.ToNodeId(encoder.Context))); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/IEndpointDiscovery.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { using Azure.IIoT.OpcUa.Publisher.Stack.Models; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; /// /// Endpoint discovery services extensions /// public interface IEndpointDiscovery { /// /// Try get unique set of endpoints from all servers found on discovery /// server endpoint url, filtered by optional prioritized locale list. /// /// /// /// /// /// Task> FindEndpointsAsync( Uri discoveryUrl, IReadOnlyList? locales = null, bool findServersOnNetwork = true, CancellationToken ct = default); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/IOpcUaBrowser.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { using Opc.Ua; using System; using System.Threading.Tasks; /// /// Represents changes in the address space /// /// /// /// /// /// /// /// public record struct Change(NodeId Source, RelativePath PathFromRoot, T? PreviousItem, T? ChangedItem, uint SequenceNumber, DateTimeOffset Timestamp) where T : class; /// /// This is an abstraction over a continous monitored address space /// inside a server. /// public interface IOpcUaBrowser { /// /// Called when a node changes /// event EventHandler>? OnNodeChange; /// /// Called when a reference changes /// event EventHandler>? OnReferenceChange; /// /// Trigger a rebrowsing of the address space /// void Rebrowse(); /// /// Close the browser /// /// ValueTask CloseAsync(); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/IOpcUaCertificates.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { using Azure.IIoT.OpcUa.Publisher.Models; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; /// /// Certificate api /// public interface IOpcUaCertificates { /// /// Enumerate certificates /// /// /// /// /// ValueTask> ListCertificatesAsync( CertificateStoreName store, bool includePrivateKey = false, CancellationToken ct = default); /// /// Add certificate pfx to store /// /// /// /// /// /// ValueTask AddCertificateAsync(CertificateStoreName store, byte[] pfxBlob, string? password = null, CancellationToken ct = default); /// /// Add certificate to trusted and issuer stores /// /// /// /// /// ValueTask AddCertificateChainAsync(byte[] certificateChain, bool isSslCertificate = false, CancellationToken ct = default); /// /// Remove certificate from store /// /// /// /// /// ValueTask RemoveCertificateAsync(CertificateStoreName store, string thumbprint, CancellationToken ct = default); /// /// Approve a rejected certificate /// /// /// /// ValueTask ApproveRejectedCertificateAsync(string thumbprint, CancellationToken ct = default); /// /// List certificate revocation lists /// /// /// /// ValueTask> ListCertificateRevocationListsAsync( CertificateStoreName store, CancellationToken ct = default); /// /// Add certificate revocation list to store /// /// /// /// /// ValueTask AddCertificateRevocationListAsync(CertificateStoreName store, byte[] crl, CancellationToken ct = default); /// /// Remove certificate revocation list from store /// /// /// /// /// ValueTask RemoveCertificateRevocationListAsync(CertificateStoreName store, byte[] crl, CancellationToken ct = default); /// /// Clean the certificate store /// /// /// /// ValueTask CleanAsync(CertificateStoreName store, CancellationToken ct = default); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/IOpcUaClientDiagnostics.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { using Azure.IIoT.OpcUa.Publisher.Models; /// /// Safely access client state for diagnostics /// public interface IOpcUaClientDiagnostics { /// /// Bad publish requests tracked by this client /// int BadPublishRequestCount { get; } /// /// Good publish requests tracked by this client /// int GoodPublishRequestCount { get; } /// /// Outstanding requests /// int OutstandingRequestCount { get; } /// /// Number of subscriptions tracked by client /// int SubscriptionCount { get; } /// /// Connectivity state /// EndpointConnectivityState State { get; } /// /// Total connection attempts /// int ReconnectCount { get; } /// /// Reconnect triggered /// bool ReconnectTriggered { get; } /// /// Total successful connections /// int ConnectCount { get; } /// /// Current min publish request count /// int MinPublishRequestCount { get; } /// /// Successful keep alives since last reconnect /// int KeepAliveCounter { get; } /// /// Total keep alive requests since last reconnect /// int KeepAliveTotal { get; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/IOpcUaClientManager.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; /// /// Connectivity state event /// public sealed class EndpointConnectivityStateEventArgs : EventArgs { /// /// State /// public EndpointConnectivityState State { get; } internal EndpointConnectivityStateEventArgs(EndpointConnectivityState state) { State = state; } } /// /// Client managers manages clients connected to servers and provides /// access to session services. /// /// public interface IOpcUaClientManager { /// /// Connectivity state change events /// event EventHandler OnConnectionStateChange; /// /// Acquire a session which will be usable until disposed. /// /// /// /// /// Task AcquireSessionAsync(T connection, RequestHeaderModel? header = null, CancellationToken ct = default); /// /// Execute the service on the provided session and /// return the result. /// /// /// /// /// /// /// Task ExecuteAsync(T connection, Func> func, RequestHeaderModel? header = null, CancellationToken ct = default); /// /// Execute the functions from stack on the provided /// session and stream the results. /// /// /// /// /// /// /// IAsyncEnumerable ExecuteAsync(T connection, AsyncEnumerableBase operation, RequestHeaderModel? header = null, CancellationToken ct = default); /// /// Create new subscription with the subscription configuration. /// The callback will have been called with the new subscription /// which then can be used to manage the subscription. /// /// The connection to use /// The subscription template /// Callbacks from the subscription /// /// ValueTask CreateSubscriptionAsync(T connection, SubscriptionModel subscription, ISubscriber callback, CancellationToken ct = default); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/IOpcUaConfiguration.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { using Opc.Ua; /// /// Provides application configuration /// public interface IOpcUaConfiguration { /// /// Validation events /// event CertificateValidationEventHandler Validate; /// /// Gets the configuration for the clients /// ApplicationConfiguration Value { get; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/IOpcUaSession.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Encoders; using Opc.Ua; using Opc.Ua.Client; using Opc.Ua.Client.ComplexTypes; using System.Threading; using System.Threading.Tasks; /// /// Represents a session handle. You acquire a handle from the session /// manager which will have the reference count incremented. Once the /// handle is disposed the reference count is decremented. The connection /// or disconnection states are handled through reference counting. The /// session is disconnected if the reference count is 0, and connected /// if it is higher than 0. The access to the underlying session is /// guarded through a readerwriter lock, the writer lock guards the /// session state in the handle and is aquired if the session is not /// connected. That means all callers are parked on the reader lock while /// the session is not connected and appropriate timeout cancellation must /// be used. /// public interface IOpcUaSession { /// /// Get services of the session /// ISessionServices Services { get; } /// /// Get the system context /// ISystemContext SystemContext { get; } /// /// Get the lru node cache /// ILruNodeCache LruNodeCache { get; } /// /// Get the message context /// IServiceMessageContext MessageContext { get; } /// /// Get the codec /// IVariantEncoder Codec { get; } /// /// Get complex type system for the session /// /// /// ValueTask GetComplexTypeSystemAsync( CancellationToken ct = default); /// /// Get operation limits /// /// /// ValueTask GetOperationLimitsAsync( CancellationToken ct = default); /// /// Get server diagnostics /// /// /// ValueTask GetServerDiagnosticAsync( CancellationToken ct = default); /// /// Get history capabilities of the server /// /// /// /// ValueTask GetHistoryCapabilitiesAsync( NamespaceFormat namespaceFormat, CancellationToken ct = default); /// /// Get server capabilities /// /// /// /// ValueTask GetServerCapabilitiesAsync( NamespaceFormat namespaceFormat, CancellationToken ct = default); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/ISessionHandle.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { using System; /// /// The session handle /// public interface ISessionHandle : IDisposable { /// /// Session /// public IOpcUaSession Session { get; } /// /// Service call timeout /// TimeSpan ServiceCallTimeout { get; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/ISessionServices.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { using Opc.Ua; using System.Threading; using System.Threading.Tasks; /// /// Session services provided by the client and referenced from the /// session handle. /// public interface ISessionServices { /// /// Add nodes /// /// /// /// /// ValueTask AddNodesAsync(RequestHeader requestHeader, AddNodesItemCollection nodesToAdd, CancellationToken ct); /// /// Add references /// /// /// /// /// ValueTask AddReferencesAsync(RequestHeader requestHeader, AddReferencesItemCollection referencesToAdd, CancellationToken ct); /// /// Browse first /// /// /// /// /// /// /// ValueTask BrowseAsync(RequestHeader requestHeader, ViewDescription? view, uint requestedMaxReferencesPerNode, BrowseDescriptionCollection nodesToBrowse, CancellationToken ct); /// /// Browse next /// /// /// /// /// /// ValueTask BrowseNextAsync(RequestHeader requestHeader, bool releaseContinuationPoints, ByteStringCollection continuationPoints, CancellationToken ct); /// /// Call /// /// /// /// /// ValueTask CallAsync(RequestHeader requestHeader, CallMethodRequestCollection methodsToCall, CancellationToken ct); /// /// Delete /// /// /// /// /// ValueTask DeleteNodesAsync(RequestHeader requestHeader, DeleteNodesItemCollection nodesToDelete, CancellationToken ct); /// /// Delete references /// /// /// /// /// ValueTask DeleteReferencesAsync(RequestHeader requestHeader, DeleteReferencesItemCollection referencesToDelete, CancellationToken ct); /// /// Read history /// /// /// /// /// /// /// /// ValueTask HistoryReadAsync(RequestHeader requestHeader, ExtensionObject? historyReadDetails, TimestampsToReturn timestampsToReturn, bool releaseContinuationPoints, HistoryReadValueIdCollection nodesToRead, CancellationToken ct); /// /// History update /// /// /// /// /// ValueTask HistoryUpdateAsync(RequestHeader requestHeader, ExtensionObjectCollection historyUpdateDetails, CancellationToken ct); /// /// Query first /// /// /// /// /// /// /// /// /// ValueTask QueryFirstAsync(RequestHeader requestHeader, ViewDescription view, NodeTypeDescriptionCollection nodeTypes, ContentFilter filter, uint maxDataSetsToReturn, uint maxReferencesToReturn, CancellationToken ct); /// /// Query next /// /// /// /// /// /// ValueTask QueryNextAsync(RequestHeader requestHeader, bool releaseContinuationPoint, byte[] continuationPoint, CancellationToken ct); /// /// Read node /// /// /// /// /// /// /// ValueTask ReadAsync(RequestHeader requestHeader, double maxAge, TimestampsToReturn timestampsToReturn, ReadValueIdCollection nodesToRead, CancellationToken ct); /// /// Register nodes /// /// /// /// /// ValueTask RegisterNodesAsync(RequestHeader requestHeader, NodeIdCollection nodesToRegister, CancellationToken ct); /// /// Unregister nodes /// /// /// /// /// ValueTask UnregisterNodesAsync(RequestHeader requestHeader, NodeIdCollection nodesToUnregister, CancellationToken ct); /// /// Translate browse paths /// /// /// /// /// ValueTask TranslateBrowsePathsToNodeIdsAsync( RequestHeader requestHeader, BrowsePathCollection browsePaths, CancellationToken ct); /// /// Write to node /// /// /// /// /// ValueTask WriteAsync(RequestHeader requestHeader, WriteValueCollection nodesToWrite, CancellationToken ct); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/ISubscriber.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { using Azure.IIoT.OpcUa.Publisher.Stack.Models; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; /// /// Lightweight subscription a client can create on /// a connection providing monitored items. /// public interface ISubscriber { /// /// The monitored items that shall be monitored in this /// subscription. If the list is updated the registration /// object must be updated and the list is read again. /// IEnumerable MonitoredItems { get; } /// /// The semantics of the desired monitored items /// changed, therefore the subscriber should update /// its information /// /// Task OnMonitoredItemSemanticsChangedAsync( CancellationToken ct = default); /// /// Called when a keep alive notification is received /// in the subscription. /// /// void OnSubscriptionKeepAlive( OpcUaSubscriptionNotification notification); /// /// Called when subscription data changes /// /// void OnSubscriptionDataChangeReceived( OpcUaSubscriptionNotification notification); /// /// Called when sampled values were received /// /// void OnSubscriptionCyclicReadCompleted( OpcUaSubscriptionNotification notification); /// /// Called when event changes /// /// void OnSubscriptionEventReceived( OpcUaSubscriptionNotification notification); /// /// ChannelDiagnostics for data change notifications /// /// /// /// /// void OnSubscriptionDataDiagnosticsChange(bool liveData, int valueChanges, int overflow, int heartbeats); /// /// ChannelDiagnostics for data change notifications /// /// /// void OnSubscriptionCyclicReadDiagnosticsChange( int valuesSampled, int overflow); /// /// Event diagnostics /// /// /// /// /// void OnSubscriptionEventDiagnosticsChange(bool liveData, int events, int overflow, int modelChanges); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/ISubscription.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.Threading; using System.Threading.Tasks; /// /// This interface represents a registration of a /// subscription on a connection to a server. The /// registration must be disposed when done which will /// release the reference on the client. /// public interface ISubscription : IAsyncDisposable { /// /// State of the underlying client /// IOpcUaClientDiagnostics ClientDiagnostics { get; } /// /// State of the underlying client /// ISubscriptionDiagnostics Diagnostics { get; } /// /// Collect metadata /// /// /// /// /// /// /// ValueTask CollectMetaDataAsync( ISubscriber owner, DataSetFieldContentFlags? fieldMask, DataSetMetaDataModel dataSetMetaData, uint minorVersion, CancellationToken ct = default); /// /// Create a keep alive notification /// /// OpcUaSubscriptionNotification? CreateKeepAlive(); /// /// Apply desired state of the subscription and its monitored items. /// This will attempt a differential update of the subscription /// and monitored items state. It is called periodically, when the /// configuration is updated or when a session is reconnected and /// the subscription needs to be recreated. /// void NotifyMonitoredItemsChanged(); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/ISubscriptionDiagnostics.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { /// /// Safely access subscription diagnostics /// public interface ISubscriptionDiagnostics { /// /// Get good monitored items /// int GoodMonitoredItems { get; } /// /// Get bad monitored items /// int BadMonitoredItems { get; } /// /// Late monitored items /// int LateMonitoredItems { get; } /// /// Heartbeats enabled /// int HeartbeatsEnabled { get; } /// /// Conditions enabled /// int ConditionsEnabled { get; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Models/AttributeMap.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Models { using Azure.IIoT.OpcUa.Encoders.Utils; using Opc.Ua; using System; using System.Collections.Generic; using System.Globalization; /// /// Represents validity and default value map for attributes /// public static class AttributeMap { internal const int Object = 0; internal const int Variable = 1; internal const int Method = 2; internal const int ObjectType = 3; internal const int VariableType = 4; internal const int ReferenceType = 5; internal const int DataType = 6; internal const int View = 7; /// /// Get built in type of attribute /// /// /// public static BuiltInType GetBuiltInType(uint attributeId) { switch (attributeId) { case Attributes.Value: return BuiltInType.Variant; case Attributes.DisplayName: case Attributes.Description: return BuiltInType.LocalizedText; case Attributes.WriteMask: case Attributes.UserWriteMask: return BuiltInType.UInt32; case Attributes.NodeId: return BuiltInType.NodeId; case Attributes.NodeClass: return BuiltInType.Int32; case Attributes.BrowseName: return BuiltInType.QualifiedName; case Attributes.IsAbstract: case Attributes.Symmetric: return BuiltInType.Boolean; case Attributes.InverseName: return BuiltInType.LocalizedText; case Attributes.ContainsNoLoops: return BuiltInType.Boolean; case Attributes.EventNotifier: return BuiltInType.Byte; case Attributes.DataType: return BuiltInType.NodeId; case Attributes.ValueRank: return BuiltInType.Int32; case Attributes.AccessLevel: case Attributes.UserAccessLevel: return BuiltInType.Byte; case Attributes.MinimumSamplingInterval: return BuiltInType.Double; case Attributes.Historizing: case Attributes.Executable: case Attributes.UserExecutable: return BuiltInType.Boolean; case Attributes.ArrayDimensions: return BuiltInType.UInt32; case Attributes.DataTypeDefinition: return BuiltInType.ExtensionObject; case Attributes.AccessLevelEx: return BuiltInType.UInt32; case Attributes.AccessRestrictions: return BuiltInType.UInt16; case Attributes.RolePermissions: case Attributes.UserRolePermissions: return BuiltInType.ExtensionObject; default: System.Diagnostics.Debug.Fail("Unknown attribute"); return BuiltInType.Null; } } /// /// Get browse name of attribute - speedier than in stack which uses /// reflection. /// /// /// public static string GetBrowseName(uint attributeId) { if (TypeMaps.Attributes.Value.TryGetBrowseName(attributeId, out var value)) { return value; } System.Diagnostics.Debug.Fail("Unknown attribute"); return attributeId.ToString(CultureInfo.InvariantCulture); } /// /// Get all valid attributes for the node class /// /// /// public static IEnumerable GetNodeClassAttributes(NodeClass nodeClass) { for (uint i = 0; i < 32; i++) { if (kMap[NodeClassId(nodeClass), i] != null) { yield return i; } } } /// /// Returns default value /// /// /// /// /// public static object? GetDefaultValue(NodeClass nodeClass, uint attributeId, bool returnNullIfOptional) { if (attributeId > 32) { return null; } var entry = kMap[NodeClassId(nodeClass), attributeId]; if (entry != null) { if (!entry.Optional || !returnNullIfOptional) { return entry.Value; } } return null; } /// /// Initialize attribute map /// See Part 3 Table 20 – Overview of Attributes /// static AttributeMap() { kMap[Variable, Attributes.AccessLevel] = new MapEntry((byte)1); kMap[Variable, Attributes.ArrayDimensions] = new MapEntry(Array.Empty(), true); kMap[Variable, Attributes.BrowseName] = new MapEntry(QualifiedName.Null); kMap[Variable, Attributes.DataType] = new MapEntry(NodeId.Null); kMap[Variable, Attributes.Description] = new MapEntry(LocalizedText.Null, true); kMap[Variable, Attributes.DisplayName] = new MapEntry(LocalizedText.Null); kMap[Variable, Attributes.Historizing] = new MapEntry(false); kMap[Variable, Attributes.MinimumSamplingInterval] = new MapEntry((double)-1, true); kMap[Variable, Attributes.NodeClass] = new MapEntry(NodeClass.Variable); kMap[Variable, Attributes.NodeId] = new MapEntry(NodeId.Null); kMap[Variable, Attributes.UserAccessLevel] = new MapEntry((byte)1, true); kMap[Variable, Attributes.AccessLevelEx] = new MapEntry((uint)0, true); kMap[Variable, Attributes.AccessRestrictions] = new MapEntry((ushort)0, true); kMap[Variable, Attributes.RolePermissions] = new MapEntry(Array.Empty(), true); kMap[Variable, Attributes.UserRolePermissions] = new MapEntry(Array.Empty(), true); kMap[Variable, Attributes.UserWriteMask] = new MapEntry((uint)0, true); kMap[Variable, Attributes.Value] = new MapEntry(Variant.Null); kMap[Variable, Attributes.ValueRank] = new MapEntry(ValueRanks.Scalar); kMap[Variable, Attributes.WriteMask] = new MapEntry((uint)0, true); kMap[VariableType, Attributes.ArrayDimensions] = new MapEntry(Array.Empty(), true); kMap[VariableType, Attributes.BrowseName] = new MapEntry(QualifiedName.Null); kMap[VariableType, Attributes.DataType] = new MapEntry(NodeId.Null); kMap[VariableType, Attributes.Description] = new MapEntry(LocalizedText.Null, true); kMap[VariableType, Attributes.DisplayName] = new MapEntry(LocalizedText.Null); kMap[VariableType, Attributes.IsAbstract] = new MapEntry(true); kMap[VariableType, Attributes.NodeClass] = new MapEntry(NodeClass.VariableType); kMap[VariableType, Attributes.NodeId] = new MapEntry(NodeId.Null); kMap[VariableType, Attributes.AccessRestrictions] = new MapEntry((ushort)0, true); kMap[VariableType, Attributes.RolePermissions] = new MapEntry(Array.Empty(), true); kMap[VariableType, Attributes.UserRolePermissions] = new MapEntry(Array.Empty(), true); kMap[VariableType, Attributes.UserWriteMask] = new MapEntry((uint)0, true); kMap[VariableType, Attributes.Value] = new MapEntry(Variant.Null, true); kMap[VariableType, Attributes.ValueRank] = new MapEntry(ValueRanks.Scalar); kMap[VariableType, Attributes.WriteMask] = new MapEntry((uint)0, true); kMap[Object, Attributes.BrowseName] = new MapEntry(QualifiedName.Null); kMap[Object, Attributes.Description] = new MapEntry(LocalizedText.Null, true); kMap[Object, Attributes.DisplayName] = new MapEntry(LocalizedText.Null); kMap[Object, Attributes.EventNotifier] = new MapEntry((byte)0); kMap[Object, Attributes.NodeClass] = new MapEntry(NodeClass.Object); kMap[Object, Attributes.NodeId] = new MapEntry(NodeId.Null); kMap[Object, Attributes.AccessRestrictions] = new MapEntry((ushort)0, true); kMap[Object, Attributes.RolePermissions] = new MapEntry(Array.Empty(), true); kMap[Object, Attributes.UserRolePermissions] = new MapEntry(Array.Empty(), true); kMap[Object, Attributes.UserWriteMask] = new MapEntry((uint)0, true); kMap[Object, Attributes.WriteMask] = new MapEntry((uint)0, true); kMap[ObjectType, Attributes.BrowseName] = new MapEntry(QualifiedName.Null); kMap[ObjectType, Attributes.Description] = new MapEntry(LocalizedText.Null, true); kMap[ObjectType, Attributes.DisplayName] = new MapEntry(LocalizedText.Null); kMap[ObjectType, Attributes.IsAbstract] = new MapEntry(true); kMap[ObjectType, Attributes.NodeClass] = new MapEntry(NodeClass.ObjectType); kMap[ObjectType, Attributes.NodeId] = new MapEntry(NodeId.Null); kMap[ObjectType, Attributes.AccessRestrictions] = new MapEntry((ushort)0, true); kMap[ObjectType, Attributes.RolePermissions] = new MapEntry(Array.Empty(), true); kMap[ObjectType, Attributes.UserRolePermissions] = new MapEntry(Array.Empty(), true); kMap[ObjectType, Attributes.UserWriteMask] = new MapEntry((uint)0, true); kMap[ObjectType, Attributes.WriteMask] = new MapEntry((uint)0, true); kMap[ReferenceType, Attributes.BrowseName] = new MapEntry(QualifiedName.Null); kMap[ReferenceType, Attributes.Description] = new MapEntry(LocalizedText.Null, true); kMap[ReferenceType, Attributes.DisplayName] = new MapEntry(LocalizedText.Null); kMap[ReferenceType, Attributes.InverseName] = new MapEntry(LocalizedText.Null, true); kMap[ReferenceType, Attributes.IsAbstract] = new MapEntry(true); kMap[ReferenceType, Attributes.NodeClass] = new MapEntry(NodeClass.ReferenceType); kMap[ReferenceType, Attributes.NodeId] = new MapEntry(NodeId.Null); kMap[ReferenceType, Attributes.Symmetric] = new MapEntry(true); kMap[ReferenceType, Attributes.AccessRestrictions] = new MapEntry((ushort)0, true); kMap[ReferenceType, Attributes.RolePermissions] = new MapEntry(Array.Empty(), true); kMap[ReferenceType, Attributes.UserRolePermissions] = new MapEntry(Array.Empty(), true); kMap[ReferenceType, Attributes.UserWriteMask] = new MapEntry((uint)0, true); kMap[ReferenceType, Attributes.WriteMask] = new MapEntry((uint)0, true); kMap[DataType, Attributes.BrowseName] = new MapEntry(QualifiedName.Null); kMap[DataType, Attributes.DataTypeDefinition] = new MapEntry(new ExtensionObject(), true); kMap[DataType, Attributes.Description] = new MapEntry(LocalizedText.Null, true); kMap[DataType, Attributes.DisplayName] = new MapEntry(LocalizedText.Null); kMap[DataType, Attributes.IsAbstract] = new MapEntry(true); kMap[DataType, Attributes.NodeClass] = new MapEntry(NodeClass.DataType); kMap[DataType, Attributes.NodeId] = new MapEntry(NodeId.Null); kMap[DataType, Attributes.AccessRestrictions] = new MapEntry((ushort)0, true); kMap[DataType, Attributes.RolePermissions] = new MapEntry(Array.Empty(), true); kMap[DataType, Attributes.UserRolePermissions] = new MapEntry(Array.Empty(), true); kMap[DataType, Attributes.UserWriteMask] = new MapEntry((uint)0, true); kMap[DataType, Attributes.WriteMask] = new MapEntry((uint)0, true); kMap[Method, Attributes.BrowseName] = new MapEntry(QualifiedName.Null); kMap[Method, Attributes.Description] = new MapEntry(LocalizedText.Null, true); kMap[Method, Attributes.DisplayName] = new MapEntry(LocalizedText.Null); kMap[Method, Attributes.Executable] = new MapEntry(false); kMap[Method, Attributes.NodeClass] = new MapEntry(NodeClass.Method); kMap[Method, Attributes.NodeId] = new MapEntry(NodeId.Null); kMap[Method, Attributes.UserExecutable] = new MapEntry(false); kMap[Method, Attributes.AccessRestrictions] = new MapEntry((ushort)0, true); kMap[Method, Attributes.RolePermissions] = new MapEntry(Array.Empty(), true); kMap[Method, Attributes.UserRolePermissions] = new MapEntry(Array.Empty(), true); kMap[Method, Attributes.UserWriteMask] = new MapEntry((uint)0, true); kMap[Method, Attributes.WriteMask] = new MapEntry((uint)0, true); kMap[View, Attributes.BrowseName] = new MapEntry(QualifiedName.Null); kMap[View, Attributes.ContainsNoLoops] = new MapEntry(true); kMap[View, Attributes.Description] = new MapEntry(LocalizedText.Null, true); kMap[View, Attributes.DisplayName] = new MapEntry(LocalizedText.Null); kMap[View, Attributes.EventNotifier] = new MapEntry((byte)0); kMap[View, Attributes.NodeClass] = new MapEntry(NodeClass.View); kMap[View, Attributes.NodeId] = new MapEntry(NodeId.Null); kMap[View, Attributes.AccessRestrictions] = new MapEntry((ushort)0, true); kMap[View, Attributes.RolePermissions] = new MapEntry(Array.Empty(), true); kMap[View, Attributes.UserRolePermissions] = new MapEntry(Array.Empty(), true); kMap[View, Attributes.UserWriteMask] = new MapEntry((uint)0, true); kMap[View, Attributes.WriteMask] = new MapEntry((uint)0, true); } /// /// Convert nodeclass to index /// /// /// /// private static int NodeClassId(NodeClass nodeClass) { switch (nodeClass) { case NodeClass.Object: return Object; case NodeClass.Variable: return Variable; case NodeClass.Method: return Method; case NodeClass.ObjectType: return ObjectType; case NodeClass.VariableType: return VariableType; case NodeClass.ReferenceType: return ReferenceType; case NodeClass.DataType: return DataType; case NodeClass.View: return View; } throw new ServiceResultException(StatusCodes.BadNodeClassInvalid); } private class MapEntry { /// /// Attribute map entry /// /// /// public MapEntry(object value, bool optional = false) { Value = value; Optional = optional; } /// /// Default value /// public object Value { get; } /// /// Whether the attribute is optional /// public bool Optional { get; } } #pragma warning disable CA1814 // Prefer jagged arrays over multidimensional private static readonly MapEntry[,] kMap = new MapEntry[8, 32]; #pragma warning restore CA1814 // Prefer jagged arrays over multidimensional } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Models/BaseMonitoredItemModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Models { using Azure.IIoT.OpcUa.Publisher.Models; using System.Collections.Generic; /// /// Base monitored item /// public abstract record class BaseMonitoredItemModel { /// /// Identifier for this monitored item /// Prio 1: Id = DataSetFieldId - if already configured /// Prio 2: Id = DataSetFieldName - if already configured /// Prio 3: NodeId as configured /// public string Id { get => !string.IsNullOrEmpty(DataSetFieldId) ? DataSetFieldId : !string.IsNullOrEmpty(DataSetFieldName) ? DataSetFieldName : StartNodeId; } /// /// Data set field id /// public string? DataSetFieldId { get; init; } /// /// Display name /// Prio 1: DisplayName = DataSetFieldName - if already configured /// Prio 2: DisplayName = DataSetFieldId - if already configured /// Prio 3: NodeId as configured /// public string DisplayName { get => !string.IsNullOrEmpty(DataSetFieldName) ? DataSetFieldName : !string.IsNullOrEmpty(DataSetFieldId) ? DataSetFieldId : StartNodeId; } /// /// Data set field name /// public string? DataSetFieldName { get; set; } /// /// Fetch dataset name /// public bool? FetchDataSetFieldName { get; init; } /// /// Node id /// public required string StartNodeId { get; init; } /// /// Path from node /// public IReadOnlyList? RelativePath { get; init; } /// /// Attribute /// public NodeAttribute? AttributeId { get; init; } /// /// Queue size /// public uint? QueueSize { get; init; } /// /// Auto calculate queue size using publishing interval /// public bool? AutoSetQueueSize { get; init; } /// /// Discard new values if queue is full /// public bool? DiscardNew { get; init; } /// /// Monitoring mode /// public MonitoringMode? MonitoringMode { get; init; } /// /// Namespace format to use /// public NamespaceFormat NamespaceFormat { get; init; } /// /// Triggered items /// public IList? TriggeredItems { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Models/ConnectionIdentifier.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Models { using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.Collections.Generic; /// /// Lookup key for connections /// internal sealed class ConnectionIdentifier { /// /// Create new key /// /// public ConnectionIdentifier(ConnectionModel connection) { Connection = connection?.Clone() ?? throw new ArgumentNullException(nameof(connection)); _hash = Connection.CreateConsistentHash(); } /// /// Create new key /// /// public ConnectionIdentifier(EndpointModel endpoint) { ArgumentNullException.ThrowIfNull(endpoint); Connection = new ConnectionModel { Endpoint = endpoint.Clone() }; _hash = Connection.CreateConsistentHash(); } /// /// The endpoint wrapped as key /// public ConnectionModel Connection { get; } /// public override bool Equals(object? obj) { if (obj is string s) { return s == ToString(); } if (obj is not ConnectionIdentifier key) { return false; } if (!Connection.IsSameAs(key.Connection)) { return false; } return true; } /// public static bool operator ==(ConnectionIdentifier r1, ConnectionIdentifier r2) => EqualityComparer.Default.Equals(r1, r2); /// public static bool operator !=(ConnectionIdentifier r1, ConnectionIdentifier r2) => !(r1 == r2); /// public override int GetHashCode() { return _hash; } /// public override string ToString() { return Connection.CreateConnectionId() ?? "Bad connection"; } private readonly int _hash; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Models/DataMonitoredItemModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Models { using Azure.IIoT.OpcUa.Publisher.Models; using System; /// /// Data monitored item /// public sealed record class DataMonitoredItemModel : BaseMonitoredItemModel { /// /// Sampling interval /// public TimeSpan? SamplingInterval { get; init; } /// /// Range of value to report /// public string? IndexRange { get; init; } /// /// Register read for this item. Registerd read is /// a hint, it can fail. /// public bool? RegisterRead { get; init; } /// /// Field id in class /// public Guid DataSetClassFieldId { get; init; } /// /// Data change filter /// public DataChangeFilterModel? DataChangeFilter { get; init; } /// /// Aggregate filter /// public AggregateFilterModel? AggregateFilter { get; init; } /// /// heartbeat interval not present if zero /// public TimeSpan? HeartbeatInterval { get; init; } /// /// heartbeat behavior /// public HeartbeatBehavior? HeartbeatBehavior { get; init; } /// /// Sample using cyclic reads /// public bool? SamplingUsingCyclicRead { get; set; } /// /// Max cache age to use for cyclic reads. /// Default is 0. /// public TimeSpan? CyclicReadMaxAge { get; init; } /// /// Skip first value /// public bool? SkipFirst { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Models/DiscoveredEndpointModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Models { using Opc.Ua; using System.Collections.Generic; /// /// Endpoint information returned from discover /// public sealed record class DiscoveredEndpointModel { /// /// Endpoint /// public required EndpointDescription Description { get; init; } /// /// Endpoint url that can be accessed /// public required string AccessibleEndpointUrl { get; init; } /// /// Capabilities of endpoint (server) /// public required HashSet Capabilities { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Models/EndpointIdentifier.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Models { using Azure.IIoT.OpcUa.Publisher.Models; using System; /// /// Lookup key for endpoint clients /// public sealed class EndpointIdentifier { /// /// Create new key /// /// public EndpointIdentifier(EndpointModel endpoint) { Endpoint = endpoint?.Clone() ?? throw new ArgumentNullException(nameof(endpoint)); _hash = Endpoint.CreateConsistentHash(); } /// /// The endpoint wrapped as key /// public EndpointModel Endpoint { get; } /// public override bool Equals(object? obj) { if (obj is string s) { return s == ToString(); } if (obj is not EndpointIdentifier key) { return false; } if (!Endpoint.IsSameAs(key.Endpoint)) { return false; } return true; } /// public override int GetHashCode() { return _hash; } /// public override string ToString() { return (Endpoint?.Url ?? "" + _hash).ToSha1Hash(); } private readonly int _hash; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Models/EventMonitoredItemModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Models { using Azure.IIoT.OpcUa.Publisher.Models; /// /// Event monitored item /// public sealed record class EventMonitoredItemModel : BaseMonitoredItemModel { /// /// Event filter /// public required EventFilterModel EventFilter { get; init; } /// /// Condition handling settings /// public ConditionHandlingOptionsModel? ConditionHandling { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Models/ImmutableRelativePath.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Models { using System; using System.Collections.Generic; using System.Linq; /// /// Immutable relative path for lookups /// internal readonly struct ImmutableRelativePath : IEquatable { /// /// Path /// public IReadOnlyList Path { get; } /// /// Create browse path /// /// public ImmutableRelativePath(IReadOnlyList path) { var result = new HashCode(); foreach (var element in path) { result.Add(element); } _hashCode = result.ToHashCode(); Path = path; } /// /// Create path from parent path and path entry /// /// /// /// public static ImmutableRelativePath Create(IReadOnlyList? parentPath, string browseName) { var browsePath = parentPath != null ? new List(parentPath) : []; browsePath.Add(browseName); return new ImmutableRelativePath(browsePath); } /// public override bool Equals(object? obj) { if (obj is ImmutableRelativePath path) { return Equals(path); } return false; } /// public bool Equals(ImmutableRelativePath other) { if (other.Path.Count != Path.Count) { return false; } for (var i = 0; i < Path.Count; i++) { if (Path[i] != other.Path[i]) { return false; } } return true; } /// public override int GetHashCode() { return _hashCode; } /// public override string? ToString() { return Path.Aggregate((a, b) => a + b); } private readonly int _hashCode; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Models/MonitoredAddressSpaceModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Models { using System; /// /// Monitor the address space /// public sealed record class MonitoredAddressSpaceModel : BaseMonitoredItemModel { /// /// Rebrowse period to use when monitoring /// public TimeSpan? RebrowsePeriod { get; set; } /// /// Root node to start browsing (optional) /// public string? RootNodeId { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Models/MonitoredItemNotificationModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Models { using Opc.Ua; /// /// Monitored item notification /// public sealed record class MonitoredItemNotificationModel { /// /// Identifier of the monitored item that originated the message /// public string? Id { get; set; } /// /// Identifier to relate notifications to a value /// public uint MessageId => SequenceNumber ?? (uint)GetHashCode(); /// /// Data set field identifier as configured /// public string? DataSetFieldName { get; set; } /// /// Display name of the data set this item is part of. /// public string? DataSetName { get; internal set; } /// /// Node Id in string format as configured /// public string? NodeId { get; internal set; } /// /// Browse path from root folder /// public RelativePath? PathFromRoot { get; internal set; } /// /// Sequence number /// public uint? SequenceNumber { get; set; } /// /// Overflow indicator counts the number of messages likely missed /// public int Overflow { get; set; } /// /// Value of variable change notification /// public DataValue? Value { get; set; } /// /// Source flags /// public MonitoredItemSourceFlags Flags { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Models/MonitoredItemSourceFlags.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Models { using System; /// /// Source flags /// [Flags] public enum MonitoredItemSourceFlags { /// /// Heartbeat is the source of the notification /// Heartbeat = 0x1, /// /// Condition is the source of the notification. /// Condition = 0x4, /// /// ModelChanges are the source of the notification. /// ModelChanges = 0x8, /// /// An error is the source of the notification /// Error = 0x10 } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Models/SampledDataValueModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Models { using Opc.Ua; /// /// Represents a sampled data value /// public class SampledDataValueModel : IEncodeable { /// /// Value /// public DataValue Value { get; } /// /// Client handle /// public uint ClientHandle { get; } /// /// Overflow /// public int Overflow { get; } /// /// Create change notification /// /// /// /// public SampledDataValueModel(DataValue value, uint clientHandle, int overflow) { Value = value; ClientHandle = clientHandle; Overflow = overflow; } /// public ExpandedNodeId TypeId => ExpandedNodeId.Null; /// public ExpandedNodeId BinaryEncodingId => ExpandedNodeId.Null; /// public ExpandedNodeId XmlEncodingId => ExpandedNodeId.Null; /// public object Clone() { return new SampledDataValueModel(Value, ClientHandle, Overflow); } /// public void Decode(IDecoder decoder) { throw new System.NotSupportedException(); } /// public void Encode(IEncoder encoder) { throw new System.NotSupportedException(); } /// public bool IsEqual(IEncodeable encodeable) { if (encodeable is not SampledDataValueModel notification) { return false; } return Utils.IsEqual(Value, notification.Value) && ClientHandle == notification.ClientHandle && Overflow == notification.Overflow; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Models/ServiceCallContext.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Models { using Azure.IIoT.OpcUa.Publisher.Stack.Services; using System; using System.Diagnostics; using System.Threading; /// /// Context for service call invocations /// public sealed record class ServiceCallContext : ISessionHandle { /// public IOpcUaSession Session { get; } /// public TimeSpan ServiceCallTimeout { get; } /// /// A continuation token to track after /// returning from the call. /// public string? TrackedToken { get; set; } /// /// A token to release from tracking after /// returning from the call. /// public string? UntrackedToken { get; set; } /// /// Cancel any calls on this token /// public CancellationToken Ct { get; } /// /// Create context /// /// /// /// internal ServiceCallContext(IOpcUaSession session, TimeSpan serviceCallTimeout, CancellationToken ct = default) { Session = session; ServiceCallTimeout = serviceCallTimeout; Ct = ct; } /// /// Create context /// /// /// /// /// /// internal ServiceCallContext(IOpcUaSession session, TimeSpan serviceCallTimeout, OpcUaClient client, IDisposable sessionLock, CancellationToken ct = default) : this(session, serviceCallTimeout, ct) { client.AddRef(); _client = client; _sessionLock = sessionLock; // TODO: we could timeout and dispose to catch leaks } /// public void Dispose() { if (_client != null) { Debug.Assert(_sessionLock != null); _sessionLock.Dispose(); _client.Release(); _client = null; } } private OpcUaClient? _client; private readonly IDisposable? _sessionLock; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Models/ServiceResponse.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Models { using Azure.IIoT.OpcUa.Publisher.Models; using Opc.Ua; using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; /// /// Helper to manage request and responses /// /// /// internal class ServiceResponse : IReadOnlyList.Operation> { /// /// Error info /// public ServiceResultModel? ErrorInfo { get { if (StatusCode == StatusCodes.Good) { return null; } return ResultInfo; } } /// /// Result info /// public ServiceResultModel ResultInfo { get { var diagnostics = _response.ResponseHeader.ServiceDiagnostics; var stringTable = _response.ResponseHeader.StringTable; return StatusCode.CreateResultModel(diagnostics, stringTable); } } /// /// Result info /// public StatusCode StatusCode => _response.ResponseHeader.ServiceResult; /// public int Count => _operations.Length; /// public Operation this[int index] => _operations[index]; /// /// Validates responses against requests /// /// /// /// /// /// internal ServiceResponse(IServiceResponse response, IEnumerable? results, Func statusCode, DiagnosticInfoCollection? diagnostics = null, IEnumerable? requested = null) { _response = response; Debug.Assert(_response.ResponseHeader != null, "Response header should have been checked by ValidateResponse."); _statusCode = statusCode; if (results == null) { if (!StatusCode.IsBad(response.ResponseHeader.ServiceResult)) { response.ResponseHeader.ServiceResult = StatusCodes.BadUnexpectedError; response.ResponseHeader.ServiceDiagnostics = new DiagnosticInfo { AdditionalInfo = "Response was good, but results were missing." }; } _results = []; } else { _results = results.ToArray(); } if (requested == null) { _requests = _results.Length == 0 ? [] : new TRequest[_results.Length]; } else { _requests = requested.ToArray(); } if (_results.Length != _requests.Length) { if (!StatusCode.IsBad(response.ResponseHeader.ServiceResult)) { response.ResponseHeader.ServiceResult = StatusCodes.BadUnexpectedError; response.ResponseHeader.ServiceDiagnostics = new DiagnosticInfo { AdditionalInfo = $"The server returned {_results.Length} results" + $" but {_requests.Length} elements were expected." }; } if (_results.Length > _requests.Length) { // Limit the results _results = _results[0.._requests.Length]; } else { _results = []; } } if (diagnostics == null || diagnostics.Count == 0) { _diagnostics = _results.Length == 0 ? [] : new DiagnosticInfo[_results.Length]; } else { _diagnostics = [.. diagnostics]; } if (_diagnostics.Length != _results.Length) { if (!StatusCode.IsBad(response.ResponseHeader.ServiceResult)) { response.ResponseHeader.ServiceResult = StatusCodes.BadUnexpectedError; response.ResponseHeader.ServiceDiagnostics = new DiagnosticInfo { AdditionalInfo = $"The server returned {_results.Length} diagnostic" + $" infos but {_requests.Length} were expected." }; } _diagnostics = new DiagnosticInfo[_results.Length]; } Activity.Current?.AddTag("Response", ErrorInfo); if (_results.Length > 0) { _operations = Enumerable.Range(0, _results.Length) .Select(i => new Operation(this, i)) .ToArray(); } else { _operations = []; } } /// /// Throw if error response /// /// public void ThrowIfError() { if (StatusCode.IsBad(StatusCode)) { throw new ServiceResultException(new ServiceResult( StatusCode, _response.ResponseHeader.ServiceDiagnostics, _response.ResponseHeader.StringTable)); } } /// public IEnumerator GetEnumerator() { return ((IEnumerable)_operations).GetEnumerator(); } /// IEnumerator IEnumerable.GetEnumerator() { return _operations.GetEnumerator(); } /// /// Service operation /// internal class Operation { /// /// Index /// public int Index { get; } /// /// Get result /// public DiagnosticInfo DiagnosticInfo => _outer._diagnostics[Index]; /// /// Get result /// public TRequest Request => _outer._requests[Index]; /// /// Get result /// public TResult Result => _outer._results[Index]; /// /// Get status code /// public StatusCode StatusCode { get { try { return _outer._statusCode(Result); } catch { return StatusCodes.BadUnknownResponse; } } } /// /// Error info /// public ServiceResultModel? ErrorInfo { get { if (StatusCode == StatusCodes.Good) { return null; } return ResultInfo; } } /// /// Result info /// public ServiceResultModel ResultInfo { get { var stringTable = _outer._response.ResponseHeader.StringTable; return StatusCode.CreateResultModel(DiagnosticInfo, stringTable); } } internal Operation(ServiceResponse outer, int i) { _outer = outer; Index = i; Activity.Current?.AddTag("Result_" + i, ErrorInfo); } private readonly ServiceResponse _outer; } private readonly TRequest[] _requests; private readonly TResult[] _results; private readonly DiagnosticInfo[] _diagnostics; private readonly Operation[] _operations; private readonly IServiceResponse _response; private readonly Func _statusCode; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Models/SubscriptionModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Models { using Azure.IIoT.OpcUa.Publisher.Models; using System; /// /// Configuration of a subscription /// public sealed record class SubscriptionModel { /// /// Publishing interval /// public TimeSpan? PublishingInterval { get; init; } /// /// Life time /// public uint? LifetimeCount { get; init; } /// /// Max keep alive count /// public uint? KeepAliveCount { get; init; } /// /// Priority /// public byte? Priority { get; init; } /// /// Max notification per publish /// public uint? MaxNotificationsPerPublish { get; init; } /// /// Use deferred acknoledgements /// public bool? UseDeferredAcknoledgements { get; init; } /// /// Use the sequential publishing feature in the stack. /// public bool? EnableSequentialPublishing { get; init; } /// /// Will set the subscription to have publishing /// enabled and every monitored item created to be /// in desired monitoring mode. /// public bool? EnableImmediatePublishing { get; init; } /// /// Republish after transfer /// public bool? RepublishAfterTransfer { get; init; } /// /// Subscription watchdog behavior /// public SubscriptionWatchdogBehavior? WatchdogBehavior { get; init; } /// /// Monitored item watchdog timeout /// public TimeSpan? MonitoredItemWatchdogTimeout { get; init; } /// /// Whether to run the watchdog action when any item /// is late or all items are late. /// public MonitoredItemWatchdogCondition? WatchdogCondition { get; init; } /// /// Retrieve paths from root for all monitored items /// in the subscription. /// public bool? ResolveBrowsePathFromRoot { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Runtime/CertificateInfo.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { /// /// Certificate information /// public class CertificateInfo : CertificateStore { /// /// Subject name /// public string? SubjectName { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Runtime/CertificateStore.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { /// /// Certificate store /// public class CertificateStore { /// /// Store type /// public string? StoreType { get; set; } /// /// Store path /// public string? StorePath { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Runtime/FlatCertificateStore.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack; using Opc.Ua; using Opc.Ua.Security.Certificates; using System; using System.IO; using System.Linq; using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; /// /// A flat certificate store option to use with a secret/volume mount /// public sealed class FlatCertificateStore : ICertificateStoreType { /// /// Identifier for flat directory certificate store. /// public const string StoreTypeName = "FlatDirectory"; /// /// Prefix for flat directory certificate store paths. /// public const string StoreTypePrefix = $"{StoreTypeName}:"; /// public ICertificateStore CreateStore() => new FlatDirectoryCertificateStore(); /// public bool SupportsStorePath(string storePath) => !string.IsNullOrEmpty(storePath) && storePath.StartsWith(StoreTypePrefix, StringComparison.InvariantCultureIgnoreCase); /// /// Flat directory certificate store that does not have internal /// hierarchy with certs/crl/private subdirectories. /// internal sealed class FlatDirectoryCertificateStore : ICertificateStore { private const string CrtExtension = ".crt"; private const string KeyExtension = ".key"; private readonly DirectoryCertificateStore _innerStore; /// /// Create certificate store /// public FlatDirectoryCertificateStore() { _innerStore = new DirectoryCertificateStore(noSubDirs: true); } /// public string StoreType => StoreTypeName; /// public string StorePath => _innerStore.StorePath; /// public bool SupportsLoadPrivateKey => _innerStore.SupportsLoadPrivateKey; /// public bool SupportsCRLs => _innerStore.SupportsCRLs; public bool NoPrivateKeys => _innerStore.NoPrivateKeys; /// public void Dispose() => _innerStore.Dispose(); /// public void Open(string location, bool noPrivateKeys = true) { ArgumentNullException.ThrowIfNullOrEmpty(location); if (!location.StartsWith(StoreTypePrefix, StringComparison.Ordinal)) { throw new ArgumentException( $"Expected argument {nameof(location)} starting with {StoreTypePrefix}", nameof(location)); } _innerStore.Open(location.Substring(StoreTypePrefix.Length), noPrivateKeys); } /// public void Close() => _innerStore.Close(); /// public Task AddAsync(X509Certificate2 certificate, string? password = null, CancellationToken ct = default) => _innerStore.AddAsync(certificate, password, ct); /// public Task AddRejectedAsync(X509Certificate2Collection certificates, int maxCertificates, CancellationToken ct = default) => _innerStore.AddRejectedAsync(certificates, maxCertificates, ct); /// public Task DeleteAsync(string thumbprint, CancellationToken ct = default) => _innerStore.DeleteAsync(thumbprint, ct); /// public async Task EnumerateAsync(CancellationToken ct = default) { var certificatesCollection = await _innerStore.EnumerateAsync(ct).ConfigureAwait(false); if (!_innerStore.Directory.Exists) { return certificatesCollection; } foreach (var file in _innerStore.Directory.GetFiles('*' + CrtExtension)) { try { var certificates = new X509Certificate2Collection(); certificates.ImportFromPemFile(file.FullName); certificatesCollection.AddRange(certificates); foreach (var certificate in certificates) { Utils.LogInfo("Enumerate certificates - certificate added {thumbprint}", certificate.Thumbprint); } } catch (Exception e) { Utils.LogError(e, "Could not load certificate from file: {fileName}", file.FullName); } } return certificatesCollection; } /// public Task AddCRLAsync(X509CRL crl, CancellationToken ct = default) => _innerStore.AddCRLAsync(crl, ct); /// public Task DeleteCRLAsync(X509CRL crl, CancellationToken ct = default) => _innerStore.DeleteCRLAsync(crl, ct); /// public Task EnumerateCRLsAsync(CancellationToken ct = default) => _innerStore.EnumerateCRLsAsync(ct); /// public Task EnumerateCRLsAsync(X509Certificate2 issuer, bool validateUpdateTime = true, CancellationToken ct = default) => _innerStore.EnumerateCRLsAsync(issuer, validateUpdateTime, ct); /// public async Task FindByThumbprintAsync( string thumbprint, CancellationToken ct = default) { var certificatesCollection = await _innerStore.FindByThumbprintAsync(thumbprint, ct).ConfigureAwait(false); if (!_innerStore.Directory.Exists) { return certificatesCollection; } foreach (var file in _innerStore.Directory.GetFiles('*' + CrtExtension)) { try { var certificates = new X509Certificate2Collection(); certificates.ImportFromPemFile(file.FullName); foreach (var certificate in certificates) { if (string.Equals(certificate.Thumbprint, thumbprint, StringComparison.OrdinalIgnoreCase)) { Utils.LogInfo("Find by thumbprint: {thumbprint} - found", thumbprint); certificatesCollection.Add(certificate); } } } catch (Exception e) { Utils.LogError(e, "Could not load certificate from file: {fileName}", file.FullName); } } return certificatesCollection; } /// public Task IsRevokedAsync(X509Certificate2 issuer, X509Certificate2 certificate, CancellationToken ct = default) => _innerStore.IsRevokedAsync(issuer, certificate, ct); /// public Task LoadPrivateKeyAsync(string thumbprint, string subjectName, string password, CancellationToken ct = default) => LoadPrivateKeyAsync(thumbprint, subjectName, applicationUri: null, certificateType: null, password, ct); /// public async Task LoadPrivateKeyAsync(string thumbprint, string subjectName, string? applicationUri, NodeId? certificateType, string password, CancellationToken ct = default) { if (!_innerStore.Directory.Exists) { return await _innerStore.LoadPrivateKeyAsync(thumbprint, subjectName, applicationUri, certificateType, password, ct).ConfigureAwait(false); } foreach (var file in _innerStore.Directory.GetFiles('*' + CrtExtension)) { try { var keyFile = new FileInfo(file.FullName.Replace(CrtExtension, KeyExtension, StringComparison.OrdinalIgnoreCase)); if (keyFile.Exists) { using var certificate = X509CertificateLoader.LoadCertificateFromFile( file.FullName); if (!MatchCertificate(certificate, thumbprint, subjectName, applicationUri, certificateType)) { continue; } var privateKeyCertificate = X509Certificate2.CreateFromPemFile( file.FullName, keyFile.FullName); Utils.LogInfo("Loading private key succeeded for {thumbprint} - {subjectName}", thumbprint, subjectName); return privateKeyCertificate; } } catch (Exception e) { Utils.LogError(e, "Could not load private key for certificate file: {fileName}", file.FullName); } } return await _innerStore.LoadPrivateKeyAsync(thumbprint, subjectName, applicationUri, certificateType, password, ct).ConfigureAwait(false); } private static bool MatchCertificate(X509Certificate2 certificate, string thumbprint, string subjectName, string? applicationUri, NodeId? certificateType) { if (certificateType == null || certificateType == ObjectTypeIds.RsaSha256ApplicationCertificateType || certificateType == ObjectTypeIds.RsaMinApplicationCertificateType || certificateType == ObjectTypeIds.ApplicationCertificateType) { if (!string.IsNullOrEmpty(thumbprint) && !string.Equals(certificate.Thumbprint, thumbprint, StringComparison.OrdinalIgnoreCase)) { return false; } if (!string.IsNullOrEmpty(subjectName) && !X509Utils.CompareDistinguishedName(subjectName, certificate.Subject) && ( subjectName.Contains('=', StringComparison.OrdinalIgnoreCase) || !X509Utils.ParseDistinguishedName(certificate.Subject) .Any(s => s.Equals("CN=" + subjectName, StringComparison.Ordinal)))) { return false; } // skip if not RSA certificate return X509Utils.GetRSAPublicKeySize(certificate) >= 0; } return false; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Runtime/OpcUaClientConfig.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Runtime { using Furly.Extensions.Configuration; using Microsoft.Extensions.Configuration; using Opc.Ua; using System; using System.Globalization; using System.IO; using System.Text; /// /// Default client configuration /// public sealed class OpcUaClientConfig : PostConfigureOptionBase { /// /// Configuration /// public const string PkiRootPathKey = "PkiRootPath"; #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public const string ApplicationNameKey = "ApplicationName"; public const string ApplicationUriKey = "ApplicationUri"; public const string ProductUriKey = "ProductUri"; public const string DefaultSessionTimeoutKey = "DefaultSessionTimeout"; public const string DefaultServiceCallTimeoutKey = "DefaultServiceCallTimeout"; public const string DefaultConnectTimeoutKey = "DefaultConnectTimeout"; public const string KeepAliveIntervalKey = "KeepAliveInterval"; public const string ApplicationCertificateStorePathKey = "ApplicationCertificateStorePath"; public const string ApplicationCertificateStoreTypeKey = "ApplicationCertificateStoreType"; public const string ApplicationCertificateSubjectNameKey = "ApplicationCertificateSubjectName"; public const string TrustedIssuerCertificatesPathKey = "TrustedIssuerCertificatesPath"; public const string TrustedIssuerCertificatesTypeKey = "TrustedIssuerCertificatesType"; public const string TrustedPeerCertificatesPathKey = "TrustedPeerCertificatesPath"; public const string TrustedPeerCertificatesTypeKey = "TrustedPeerCertificatesType"; public const string RejectedCertificateStorePathKey = "RejectedCertificateStorePath"; public const string RejectedCertificateStoreTypeKey = "RejectedCertificateStoreType"; public const string TrustedUserCertificatesTypeKey = "TrustedUserCertificatesType"; public const string TrustedUserCertificatesPathKey = "TrustedUserCertificatesPath"; public const string UserIssuerCertificatesTypeKey = "UserIssuerCertificatesType"; public const string UserIssuerCertificatesPathKey = "UserIssuerCertificatesPath"; public const string HttpsIssuerCertificatesTypeKey = "HttpsIssuerCertificatesType"; public const string HttpsIssuerCertificatesPathKey = "HttpsIssuerCertificatesPath"; public const string TrustedHttpsCertificatesTypeKey = "TrustedHttpsCertificatesType"; public const string TrustedHttpsCertificatesPathKey = "TrustedHttpsCertificatesPath"; public const string AutoAcceptUntrustedCertificatesKey = "AutoAcceptUntrustedCertificates"; public const string RejectSha1SignedCertificatesKey = "RejectSha1SignedCertificates"; public const string MinimumCertificateKeySizeKey = "MinimumCertificateKeySize"; public const string AddAppCertToTrustedStoreKey = "AddAppCertToTrustedStore"; public const string RejectUnknownRevocationStatusKey = "RejectUnknownRevocationStatus"; public const string SecurityTokenLifetimeKey = "SecurityTokenLifetime"; public const string EnableOpcUaStackLoggingKey = "EnableOpcUaStackLogging"; public const string OpcUaKeySetLogFolderNameKey = "OpcUaKeySetLogFolderName"; public const string ChannelLifetimeKey = "ChannelLifetime"; public const string MaxBufferSizeKey = "MaxBufferSize"; public const string MaxMessageSizeKey = "MaxMessageSize"; public const string MaxArrayLengthKey = "MaxArrayLength"; public const string MaxByteStringLengthKey = "MaxByteStringLength"; public const string MaxStringLengthKey = "MaxStringLength"; public const string OperationTimeoutKey = "OperationTimeout"; public const string CreateSessionTimeoutKey = "CreateSessionTimeout"; public const string MaxReconnectDelayKey = "MaxReconnectDelay"; public const string MinReconnectDelayKey = "MinReconnectDelay"; public const string LingerTimeoutSecondsKey = "LingerTimeoutSeconds"; public const string ApplicationCertificatePasswordKey = "ApplicationCertificatePassword"; public const string TryConfigureFromExistingAppCertKey = "TryConfigureFromExistingAppCert"; public const string ReverseConnectPortKey = "ReverseConnectPort"; public const string DisableComplexTypePreloadingKey = "DisableComplexTypePreloading"; public const string PublishRequestsPerSubscriptionPercentKey = "PublishRequestsPerSubscriptionPercent"; public const string MinPublishRequestsKey = "MinPublishRequests"; public const string MaxPublishRequestsKey = "MaxPublishRequests"; public const string MaxNodesPerBrowseOverrideKey = "MaxNodesPerBrowseOverride"; public const string MaxNodesPerReadOverrideKey = "MaxNodesPerReadOverride"; public const string NodeCacheCapacityKey = "NodeCacheCapacity"; public const string NodeCacheTimeoutKey = "NodeCacheTimeout"; #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member /// /// Default values for transport quotas. /// public const string ApplicationNameDefault = "Microsoft.Azure.IIoT"; #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public static readonly CompositeFormat ApplicationUriDefault = CompositeFormat.Parse("urn:localhost:{0}:microsoft:"); public const string ProductUriDefault = "https://www.github.com/Azure/Industrial-IoT"; public const string PkiRootPathDefault = "pki"; public const int SecurityTokenLifetimeDefault = 60 * 60 * 1000; public const int ChannelLifetimeDefault = 300 * 1000; public const int MaxBufferSizeDefault = (64 * 1024) - 1; public const int MaxMessageSizeDefault = 8 * 1024 * 1024; public const int MaxArrayLengthDefault = (64 * 1024) - 1; public const int MaxByteStringLengthDefault = 1024 * 1024; public const int MaxStringLengthDefault = (128 * 1024) - 256; public const int OperationTimeoutDefault = 120 * 1000; public const int DefaultSessionTimeoutDefaultSec = 60; public const int DefaultServiceCallTimeoutDefaultSec = 3 * 60; public const int KeepAliveIntervalDefaultSec = 10; public const int CreateSessionTimeoutDefaultSec = 5; public const int MaxReconnectDelayDefault = 60 * 1000; public const int MinReconnectDelayDefault = 1000; public const int ReverseConnectPortDefault = 4840; public const int MinimumCertificateKeySizeDefault = 1024; public const bool AutoAcceptUntrustedCertificatesDefault = false; public const bool RejectSha1SignedCertificatesDefault = false; public const bool AddAppCertToTrustedStoreDefault = true; public const bool RejectUnknownRevocationStatusDefault = true; public const int MinPublishRequestsDefault = 2; public const int MaxPublishRequestsDefault = 10; public const int PublishRequestsPerSubscriptionPercentDefault = 100; #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member /// public override void PostConfigure(string? name, OpcUaClientOptions options) { if (string.IsNullOrEmpty(options.ApplicationName)) { options.ApplicationName = GetStringOrDefault(ApplicationNameKey); if (string.IsNullOrEmpty(options.ApplicationName) || options.ApplicationName == "Azure.IIoT.OpcUa.Publisher.Module") { options.ApplicationName = ApplicationNameDefault; } } if (string.IsNullOrEmpty(options.ApplicationUri)) { options.ApplicationUri = GetStringOrDefault(ApplicationUriKey, string.Format(CultureInfo.InvariantCulture, ApplicationUriDefault, options.ApplicationName)); } if (string.IsNullOrEmpty(options.ProductUri)) { options.ProductUri = GetStringOrDefault(ProductUriKey, ProductUriDefault); } if (options.DefaultSessionTimeoutDuration == null) { var sessionTimeout = GetIntOrDefault(DefaultSessionTimeoutKey, DefaultSessionTimeoutDefaultSec); if (sessionTimeout > 0) { options.DefaultSessionTimeoutDuration = TimeSpan.FromSeconds(sessionTimeout); } } if (options.DefaultServiceCallTimeoutDuration == null) { var serviceCallTimeout = GetIntOrDefault(DefaultServiceCallTimeoutKey, DefaultServiceCallTimeoutDefaultSec); if (serviceCallTimeout > 0) { options.DefaultServiceCallTimeoutDuration = TimeSpan.FromSeconds(serviceCallTimeout); } } if (options.DefaultConnectTimeoutDuration == null) { var connectTimeout = GetIntOrNull(DefaultConnectTimeoutKey); if (connectTimeout > 0) { options.DefaultConnectTimeoutDuration = TimeSpan.FromSeconds(connectTimeout.Value); } } if (options.KeepAliveIntervalDuration == null) { var keepAliveInterval = GetIntOrDefault(KeepAliveIntervalKey, KeepAliveIntervalDefaultSec); if (keepAliveInterval > 0) { options.KeepAliveIntervalDuration = TimeSpan.FromSeconds(keepAliveInterval); } } if (options.CreateSessionTimeoutDuration == null) { var createSessionTimeout = GetIntOrDefault(CreateSessionTimeoutKey, CreateSessionTimeoutDefaultSec); if (createSessionTimeout > 0) { options.CreateSessionTimeoutDuration = TimeSpan.FromSeconds(createSessionTimeout); } } options.ReverseConnectPort ??= GetIntOrDefault(ReverseConnectPortKey, ReverseConnectPortDefault); if (options.MinReconnectDelayDuration == null) { var reconnectDelay = GetIntOrDefault(MinReconnectDelayKey, MinReconnectDelayDefault); if (reconnectDelay > 0) { options.MinReconnectDelayDuration = TimeSpan.FromMilliseconds(reconnectDelay); } } if (options.MaxReconnectDelayDuration == null) { var reconnectDelay = GetIntOrDefault(MaxReconnectDelayKey, MaxReconnectDelayDefault); if (reconnectDelay > 0) { options.MaxReconnectDelayDuration = TimeSpan.FromMilliseconds(reconnectDelay); } } if (options.LingerTimeoutDuration == null) { var lingerTimeout = GetIntOrDefault(LingerTimeoutSecondsKey); if (lingerTimeout > 0) { options.LingerTimeoutDuration = TimeSpan.FromSeconds(lingerTimeout); } } options.DisableComplexTypePreloading ??= GetBoolOrDefault(DisableComplexTypePreloadingKey); options.MinPublishRequests ??= GetIntOrNull(MinPublishRequestsKey); options.MaxPublishRequests ??= GetIntOrNull(MaxPublishRequestsKey); options.PublishRequestsPerSubscriptionPercent ??= GetIntOrNull( PublishRequestsPerSubscriptionPercentKey); options.MaxNodesPerReadOverride ??= GetIntOrNull(MaxNodesPerReadOverrideKey); options.MaxNodesPerBrowseOverride ??= GetIntOrNull(MaxNodesPerBrowseOverrideKey); options.NodeCacheCapacity ??= GetIntOrNull(NodeCacheCapacityKey); options.NodeCacheTimeout ??= GetDurationOrNull(NodeCacheTimeoutKey); if (options.Security.MinimumCertificateKeySize == 0) { options.Security.MinimumCertificateKeySize = (ushort)GetIntOrDefault( MinimumCertificateKeySizeKey, MinimumCertificateKeySizeDefault); } if (options.Security.AutoAcceptUntrustedCertificates == null) { options.Security.AutoAcceptUntrustedCertificates = GetBoolOrDefault( AutoAcceptUntrustedCertificatesKey, AutoAcceptUntrustedCertificatesDefault); } if (options.Security.RejectSha1SignedCertificates == null) { options.Security.RejectSha1SignedCertificates = GetBoolOrDefault( RejectSha1SignedCertificatesKey, RejectSha1SignedCertificatesDefault); } if (options.Security.AddAppCertToTrustedStore == null) { options.Security.AddAppCertToTrustedStore = GetBoolOrDefault( AddAppCertToTrustedStoreKey, AddAppCertToTrustedStoreDefault); } if (options.Security.RejectUnknownRevocationStatus == null) { options.Security.RejectUnknownRevocationStatus = GetBoolOrDefault( RejectUnknownRevocationStatusKey, RejectUnknownRevocationStatusDefault); } // https://github.com/OPCFoundation/UA-.NETStandard/blob/master/Docs/Certificates.md if (options.Security.PkiRootPath == null) { options.Security.PkiRootPath = GetStringOrDefault(PkiRootPathKey, PkiRootPathDefault); } if (options.Security.ApplicationCertificates == null) { var storeType = GetStringOrDefault(ApplicationCertificateStoreTypeKey, CertificateStoreType.Directory); options.Security.ApplicationCertificates = new() { StorePath = GetStringOrDefault(ApplicationCertificateStorePathKey, $"{GetStoreMoniker(storeType)}{options.Security.PkiRootPath}/own"), StoreType = storeType, SubjectName = GetStringOrDefault(ApplicationCertificateSubjectNameKey, $"CN={options.ApplicationName}, C=DE, S=Bav, O=Microsoft, DC=localhost") }; } if (options.Security.RejectedCertificateStore == null) { var storeType = GetStringOrDefault(RejectedCertificateStoreTypeKey, CertificateStoreType.Directory); options.Security.RejectedCertificateStore = new() { StorePath = GetStringOrDefault(RejectedCertificateStorePathKey, $"{GetStoreMoniker(storeType)}{options.Security.PkiRootPath}/rejected"), StoreType = storeType }; } if (options.Security.TrustedIssuerCertificates == null) { var storeType = GetStringOrDefault(TrustedIssuerCertificatesTypeKey, CertificateStoreType.Directory); // // Returns the legacy 'issuers' if folder already exists or per // specification. // var moniker = GetStoreMoniker(storeType); var legacyPath = $"{moniker}{options.Security.PkiRootPath}/issuers"; var path = moniker.Length == 0 && Directory.Exists(legacyPath) ? legacyPath : $"{moniker}{options.Security.PkiRootPath}/issuer"; options.Security.TrustedIssuerCertificates = new() { StorePath = GetStringOrDefault(TrustedIssuerCertificatesPathKey, path), StoreType = storeType }; } if (options.Security.TrustedPeerCertificates == null) { var storeType = GetStringOrDefault(TrustedPeerCertificatesTypeKey, CertificateStoreType.Directory); options.Security.TrustedPeerCertificates = new() { StorePath = GetStringOrDefault(TrustedPeerCertificatesPathKey, $"{GetStoreMoniker(storeType)}{options.Security.PkiRootPath}/trusted"), StoreType = storeType }; } if (options.Security.TrustedUserCertificates == null) { var storeType = GetStringOrDefault(TrustedUserCertificatesTypeKey, CertificateStoreType.Directory); options.Security.TrustedUserCertificates = new() { StorePath = GetStringOrDefault(TrustedUserCertificatesPathKey, $"{GetStoreMoniker(storeType)}{options.Security.PkiRootPath}/user"), StoreType = storeType }; } if (options.Security.TrustedHttpsCertificates == null) { var storeType = GetStringOrDefault(TrustedHttpsCertificatesTypeKey, CertificateStoreType.Directory); options.Security.TrustedHttpsCertificates = new() { StorePath = GetStringOrDefault(TrustedHttpsCertificatesPathKey, $"{GetStoreMoniker(storeType)}{options.Security.PkiRootPath}/https"), StoreType = storeType }; } if (options.Security.HttpsIssuerCertificates == null) { var storeType = GetStringOrDefault(HttpsIssuerCertificatesTypeKey, CertificateStoreType.Directory); options.Security.HttpsIssuerCertificates = new() { StorePath = GetStringOrDefault(HttpsIssuerCertificatesPathKey, $"{GetStoreMoniker(storeType)}{options.Security.PkiRootPath}/https/issuer"), StoreType = storeType }; } if (options.Security.UserIssuerCertificates == null) { var storeType = GetStringOrDefault(UserIssuerCertificatesTypeKey, CertificateStoreType.Directory); options.Security.UserIssuerCertificates = new() { StorePath = GetStringOrDefault(UserIssuerCertificatesPathKey, $"{GetStoreMoniker(storeType)}{options.Security.PkiRootPath}/user/issuer"), StoreType = storeType }; } if (options.Quotas.ChannelLifetime == 0) { options.Quotas.ChannelLifetime = GetIntOrDefault(ChannelLifetimeKey, ChannelLifetimeDefault); } if (options.Quotas.MaxArrayLength == 0) { options.Quotas.MaxArrayLength = GetIntOrDefault(MaxArrayLengthKey, MaxArrayLengthDefault); } if (options.Quotas.MaxBufferSize == 0) { options.Quotas.MaxBufferSize = GetIntOrDefault(MaxBufferSizeKey, MaxBufferSizeDefault); } if (options.Quotas.MaxByteStringLength == 0) { options.Quotas.MaxByteStringLength = GetIntOrDefault(MaxByteStringLengthKey, MaxByteStringLengthDefault); } if (options.Quotas.MaxMessageSize == 0) { options.Quotas.MaxMessageSize = GetIntOrDefault(MaxMessageSizeKey, MaxMessageSizeDefault); } if (options.Quotas.MaxStringLength == 0) { options.Quotas.MaxStringLength = GetIntOrDefault(MaxStringLengthKey, MaxStringLengthDefault); } if (options.Quotas.OperationTimeout == 0) { options.Quotas.OperationTimeout = GetIntOrDefault(OperationTimeoutKey, OperationTimeoutDefault); } if (options.Quotas.SecurityTokenLifetime == 0) { options.Quotas.SecurityTokenLifetime = GetIntOrDefault(SecurityTokenLifetimeKey, SecurityTokenLifetimeDefault); } options.OpcUaKeySetLogFolderName ??= GetStringOrDefault(OpcUaKeySetLogFolderNameKey); options.EnableOpcUaStackLogging ??= GetBoolOrNull(EnableOpcUaStackLoggingKey); if (options.Security.ApplicationCertificatePassword == null) { options.Security.ApplicationCertificatePassword = GetStringOrDefault(ApplicationCertificatePasswordKey); } if (options.Security.TryUseConfigurationFromExistingAppCert == null) { options.Security.TryUseConfigurationFromExistingAppCert = GetBoolOrNull(TryConfigureFromExistingAppCertKey); } static string GetStoreMoniker(string storeType) => storeType switch { CertificateStoreType.Directory or CertificateStoreType.X509Store => string.Empty, FlatCertificateStore.StoreTypePrefix => FlatCertificateStore.StoreTypePrefix, _ => throw new ArgumentOutOfRangeException(nameof(storeType), $"Unknown certificate store type '{storeType}'") }; } /// public OpcUaClientConfig(IConfiguration configuration) : base(configuration) { } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Runtime/OpcUaClientOptions.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { using System; /// /// Opc ua client options /// public sealed class OpcUaClientOptions { /// /// Application name /// public string? ApplicationName { get; set; } /// /// Application uri /// public string? ApplicationUri { get; set; } /// /// Product uri /// public string? ProductUri { get; set; } /// /// Default session timeout. This is the timoout used to /// establish a session with the server. /// public TimeSpan? DefaultSessionTimeoutDuration { get; set; } /// /// Default service call timeout duration. If the service /// call timeout is not specified in the request header and /// the this value is used. /// public TimeSpan? DefaultServiceCallTimeoutDuration { get; set; } /// /// Default connect timeout duration. If the connect timeout /// is not specified in the request header this value is used. /// If not specified the default service call timeout is used. /// public TimeSpan? DefaultConnectTimeoutDuration { get; set; } /// /// Keep alive interval. The client will send keep alives /// to the server at this interval and expect a response /// or initiate a session recovery / reconnect sequence. /// public TimeSpan? KeepAliveIntervalDuration { get; set; } /// /// How long to wait until connected or until /// reconnecting is attempted. /// public TimeSpan? CreateSessionTimeoutDuration { get; set; } /// /// Reverse connect port to use other than the /// default port 4840. /// public int? ReverseConnectPort { get; set; } /// /// Disable complex type preloading. The type system /// will still be lazily loaded when requested e.g., /// during subscription creation. /// public bool? DisableComplexTypePreloading { get; set; } /// /// How long to at least wait until reconnecting. /// public TimeSpan? MinReconnectDelayDuration { get; set; } /// /// How long to at most wait until reconnecting. /// public TimeSpan? MaxReconnectDelayDuration { get; set; } /// /// How long to keep clients around after a service call. /// public TimeSpan? LingerTimeoutDuration { get; set; } /// /// Transport quota /// public TransportOptions Quotas { get; } = new TransportOptions(); /// /// Security configuration /// public SecurityOptions Security { get; } = new SecurityOptions(); /// /// Enable traces in the stack beyond errors /// public bool? EnableOpcUaStackLogging { get; set; } /// /// Folder to write keysets to for later decryption /// of wireshark traces. /// public string? OpcUaKeySetLogFolderName { get; set; } /// /// Minimum number of publish requests to queue /// at all times. Default is 2. /// public int? MinPublishRequests { get; set; } /// /// The publish requests per subscription factor in /// percent, e.g., 120% means 1.2 requests per /// subscription. Use this to control network latency /// public int? PublishRequestsPerSubscriptionPercent { get; set; } /// /// Max number of publish requests to queue /// at all times. Default is 15. /// public int? MaxPublishRequests { get; set; } /// /// Limit max nodes to read in a batch operation /// public int? MaxNodesPerReadOverride { get; set; } /// /// Limit max nodes to browse in a batch operation /// public int? MaxNodesPerBrowseOverride { get; set; } /// /// Node cache timeout /// public TimeSpan? NodeCacheTimeout { get; set; } /// /// Node cache capacity /// public int? NodeCacheCapacity { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Runtime/OpcUaSubscriptionConfig.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Runtime { using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Extensions.Configuration; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Options; using System; /// /// Subscription options configuration /// public sealed class OpcUaSubscriptionConfig : PostConfigureOptionBase { /// /// Configuration /// #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public const string DefaultHeartbeatIntervalKey = "DefaultHeartbeatInterval"; public const string DefaultHeartbeatBehaviorKey = "DefaultHeartbeatBehavior"; public const string DefaultSkipFirstKey = "DefaultSkipFirst"; public const string DefaultRepublishAfterTransferKey = "RepublishAfterTransfer"; public const string DefaultDiscardNewKey = "DiscardNew"; public const string DefaultSamplingIntervalKey = "DefaultSamplingInterval"; public const string DefaultPublishingIntervalKey = "DefaultPublishingInterval"; public const string DefaultDataChangeTriggerKey = "DefaultDataChangeTrigger"; public const string FetchOpcNodeDisplayNameKey = "FetchOpcNodeDisplayName"; public const string FetchOpcBrowsePathFromRootKey = "FetchOpcBrowsePathFromRoot"; public const string DefaultQueueSizeKey = "DefaultQueueSize"; public const string AutoSetQueueSizesKey = "AutoSetQueueSizes"; public const string DefaultLifetimeCountKey = "DefaultLifetimeCount"; public const string DefaultKeepAliveCountKey = "DefaultKeepAliveCount"; public const string MaxMonitoredItemPerSubscriptionKey = "MaxMonitoredItemPerSubscription"; public const string UseDeferredAcknoledgementsKey = "UseDeferredAcknoledgements"; public const string DefaultSamplingUsingCyclicReadKey = "DefaultSamplingUsingCyclicRead"; public const string EnableImmediatePublishingKey = "EnableImmediatePublishing"; public const string EnableSequentialPublishingKey = "EnableSequentialPublishing"; public const string DefaultRebrowsePeriodKey = "DefaultRebrowsePeriod"; public const string DefaultWatchdogBehaviorKey = "DefaultWatchdogBehavior"; public const string DefaultMonitoredItemWatchdogConditionKey = "DefaultMonitoredItemWatchdogCondition"; public const string DefaultMonitoredItemWatchdogSecondsKey = "DefaultMonitoredItemWatchdogSeconds"; public const string SubscriptionErrorRetryDelaySecondsKey = "SubscriptionErrorRetryDelaySeconds"; public const string InvalidMonitoredItemRetryDelaySecondsKey = "InvalidMonitoredItemRetryDelaySeconds"; public const string BadMonitoredItemRetryDelaySecondsKey = "BadMonitoredItemRetryDelaySeconds"; public const string InvalidMonitoredItemRetryDelayMaxSecondsKey = "InvalidMonitoredItemRetryDelayMaxSeconds"; public const string BadMonitoredItemRetryDelayMaxSecondsKey = "BadMonitoredItemRetryDelayMaxSeconds"; public const string SubscriptionManagementIntervalSecondsKey = "SubscriptionManagementIntervalSeconds"; #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member /// /// Default values /// public const bool ResolveDisplayNameDefault = false; #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public const int DefaultSamplingIntervalDefaultMillis = 1000; public const int DefaultPublishingIntervalDefaultMillis = 1000; public const bool DefaultSkipFirstDefault = false; public const bool DefaultRepublishAfterTransferDefault = false; public const bool EnableSequentialPublishingDefault = true; public const bool UseDeferredAcknoledgementsDefault = false; public const int SubscriptionErrorRetryDelayDefaultSec = 2; public const int InvalidMonitoredItemRetryDelayDefaultSec = 5 * 60; public const int BadMonitoredItemRetryDelayDefaultSec = 30 * 60; public const bool DefaultDiscardNewDefault = false; public static readonly TimeSpan DefaultRebrowsePeriodDefault = TimeSpan.FromHours(12); #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member /// public override void PostConfigure(string? name, OpcUaSubscriptionOptions options) { options.UseDeferredAcknoledgements ??= GetBoolOrDefault( UseDeferredAcknoledgementsKey, UseDeferredAcknoledgementsDefault); if (options.DefaultHeartbeatInterval == null) { options.DefaultHeartbeatInterval = GetDurationOrNull( DefaultHeartbeatIntervalKey); } if (options.DefaultHeartbeatBehavior == null && Enum.TryParse(GetStringOrDefault(DefaultHeartbeatBehaviorKey), out var behavior)) { options.DefaultHeartbeatBehavior = behavior; } options.DefaultSamplingUsingCyclicRead ??= GetBoolOrNull(DefaultSamplingUsingCyclicReadKey); if (options.DefaultRebrowsePeriod == null) { options.DefaultRebrowsePeriod = GetDurationOrNull(DefaultRebrowsePeriodKey); } options.DefaultSkipFirst ??= GetBoolOrDefault(DefaultSkipFirstKey, DefaultSkipFirstDefault); options.DefaultRepublishAfterTransfer ??= GetBoolOrDefault(DefaultRepublishAfterTransferKey, DefaultRepublishAfterTransferDefault); options.DefaultDiscardNew ??= GetBoolOrDefault(DefaultDiscardNewKey, DefaultDiscardNewDefault); if (options.DefaultSamplingInterval == null) { options.DefaultSamplingInterval = GetDurationOrNull(DefaultSamplingIntervalKey) ?? TimeSpan.FromMilliseconds(GetIntOrDefault(DefaultSamplingIntervalKey, DefaultSamplingIntervalDefaultMillis)); } if (options.DefaultPublishingInterval == null) { options.DefaultPublishingInterval = GetDurationOrNull(DefaultPublishingIntervalKey) ?? TimeSpan.FromMilliseconds(GetIntOrDefault(DefaultPublishingIntervalKey, DefaultPublishingIntervalDefaultMillis)); } if (options.DefaultMonitoredItemWatchdogTimeout == null) { var watchdogInterval = GetIntOrNull(DefaultMonitoredItemWatchdogSecondsKey); if (watchdogInterval.HasValue) { options.DefaultMonitoredItemWatchdogTimeout = TimeSpan.FromSeconds(watchdogInterval.Value); } } if (options.DefaultMonitoredItemWatchdogCondition == null && Enum.TryParse( GetStringOrDefault(DefaultMonitoredItemWatchdogConditionKey), out var watchdogCondition)) { options.DefaultMonitoredItemWatchdogCondition = watchdogCondition; } if (options.DefaultWatchdogBehavior == null && Enum.TryParse( GetStringOrDefault(DefaultWatchdogBehaviorKey), out var watchdogBehavior)) { options.DefaultWatchdogBehavior = watchdogBehavior; } if (options.SubscriptionErrorRetryDelay == null) { var retryTimeout = GetIntOrNull(SubscriptionErrorRetryDelaySecondsKey); if (retryTimeout.HasValue) { options.SubscriptionErrorRetryDelay = TimeSpan.FromSeconds(retryTimeout.Value); } } if (options.BadMonitoredItemRetryDelayDuration == null) { var retryTimeout = GetIntOrNull(BadMonitoredItemRetryDelaySecondsKey); if (retryTimeout.HasValue) { options.BadMonitoredItemRetryDelayDuration = TimeSpan.FromSeconds(retryTimeout.Value); } } if (options.InvalidMonitoredItemRetryDelayDuration == null) { var retryTimeout = GetIntOrNull(InvalidMonitoredItemRetryDelaySecondsKey); if (retryTimeout.HasValue) { options.InvalidMonitoredItemRetryDelayDuration = TimeSpan.FromSeconds(retryTimeout.Value); } } if (options.BadMonitoredItemRetryDelayDurationMax == null) { var retryTimeout = GetIntOrNull(BadMonitoredItemRetryDelayMaxSecondsKey); if (retryTimeout.HasValue) { options.BadMonitoredItemRetryDelayDurationMax = TimeSpan.FromSeconds(retryTimeout.Value); if (options.BadMonitoredItemRetryDelayDuration == null) { options.BadMonitoredItemRetryDelayDuration = TimeSpan.FromSeconds(2); } } } if (options.InvalidMonitoredItemRetryDelayDurationMax == null) { var retryTimeout = GetIntOrNull(InvalidMonitoredItemRetryDelayMaxSecondsKey); if (retryTimeout.HasValue) { options.InvalidMonitoredItemRetryDelayDurationMax = TimeSpan.FromSeconds(retryTimeout.Value); if (options.InvalidMonitoredItemRetryDelayDuration == null) { options.InvalidMonitoredItemRetryDelayDuration = TimeSpan.FromSeconds(2); } } } if (options.SubscriptionManagementIntervalDuration == null) { var managementInterval = GetIntOrNull(SubscriptionManagementIntervalSecondsKey); if (managementInterval.HasValue) { options.SubscriptionManagementIntervalDuration = TimeSpan.FromSeconds(managementInterval.Value); } } options.DefaultKeepAliveCount ??= (uint?)GetIntOrNull(DefaultKeepAliveCountKey); options.DefaultLifeTimeCount ??= (uint?)GetIntOrNull(DefaultLifetimeCountKey); options.EnableImmediatePublishing ??= GetBoolOrNull(EnableImmediatePublishingKey); options.EnableSequentialPublishing ??= GetBoolOrDefault(EnableSequentialPublishingKey, EnableSequentialPublishingDefault); options.ResolveDisplayName ??= GetBoolOrDefault(FetchOpcNodeDisplayNameKey, ResolveDisplayNameDefault); options.DefaultQueueSize ??= (uint?)GetIntOrNull(DefaultQueueSizeKey); options.AutoSetQueueSizes ??= GetBoolOrNull(AutoSetQueueSizesKey); options.MaxMonitoredItemPerSubscription ??= (uint?)GetIntOrNull(MaxMonitoredItemPerSubscriptionKey); var unsMode = _options.Value.DefaultDataSetRouting ?? DataSetRoutingMode.None; options.FetchOpcBrowsePathFromRoot ??= unsMode != DataSetRoutingMode.None ? true : GetBoolOrNull(FetchOpcBrowsePathFromRootKey); if (options.DefaultDataChangeTrigger == null && Enum.TryParse(GetStringOrDefault(DefaultDataChangeTriggerKey), out var trigger)) { options.DefaultDataChangeTrigger = trigger; } } /// /// Create configurator /// /// /// public OpcUaSubscriptionConfig(IConfiguration configuration, IOptions options) : base(configuration) { _options = options; } private readonly IOptions _options; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Runtime/OpcUaSubscriptionOptions.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { using Azure.IIoT.OpcUa.Publisher.Models; using System; /// /// Subscription configuration /// public sealed class OpcUaSubscriptionOptions { /// /// The default behavior of heartbeat if not configured. /// public HeartbeatBehavior? DefaultHeartbeatBehavior { get; set; } /// /// The default interval for heartbeats if not configured. /// public TimeSpan? DefaultHeartbeatInterval { get; set; } /// /// The default flag whether to skip the first value if /// not set on node level. /// public bool? DefaultSkipFirst { get; set; } /// /// Republish messages after transfer /// public bool? DefaultRepublishAfterTransfer { get; set; } /// /// The default flag whether to descard new items in queue /// public bool? DefaultDiscardNew { get; set; } /// /// The default sampling interval. /// public TimeSpan? DefaultSamplingInterval { get; set; } /// /// The default publishing interval. /// public TimeSpan? DefaultPublishingInterval { get; set; } /// /// Allow max monitored item per subscription. If the server /// supports less, this value takes no effect. /// public uint? MaxMonitoredItemPerSubscription { get; set; } /// /// Default subscription keep alive counter /// public uint? DefaultKeepAliveCount { get; set; } /// /// Default subscription lifetime counter /// public uint? DefaultLifeTimeCount { get; set; } /// /// Enable publishing and monitored items when created /// rather than when publishing should start. /// public bool? EnableImmediatePublishing { get; set; } /// /// Enable sequential publishing feature in the stack. /// public bool? EnableSequentialPublishing { get; set; } /// /// Flag wether to grab the display name of nodes form /// the OPC UA Server. /// public bool? ResolveDisplayName { get; set; } /// /// set the default queue size for monitored items. If not /// set the default queue size will be configured (1 for /// data monitored items, and 0 for event monitoring). /// public uint? DefaultQueueSize { get; set; } /// /// Automatically calculate queue sizes based on the /// publishing interval and sampling interval as /// max(1, roundup(subscription pi / si)). /// public bool? AutoSetQueueSizes { get; set; } /// /// Use deferred acnkoledgement (experimental) /// public bool? UseDeferredAcknoledgements { get; set; } /// /// Always use cyclic reads for sampling /// public bool? DefaultSamplingUsingCyclicRead { get; set; } /// /// Default cache age to use for cyclic reads. /// Default is 0 (uncached) /// public TimeSpan DefaultCyclicReadMaxAge { get; set; } /// /// The default rebrowse period for model change event generation. /// public TimeSpan? DefaultRebrowsePeriod { get; set; } /// /// set the default data change filter for monitored items. Default is /// status and value change triggering. /// public DataChangeTriggerType? DefaultDataChangeTrigger { get; set; } /// /// Retrieve paths from root folder to enable automatic /// unified namespace publishing /// public bool? FetchOpcBrowsePathFromRoot { get; set; } /// /// The default watchdog behaviour of the subscription. /// public SubscriptionWatchdogBehavior? DefaultWatchdogBehavior { get; set; } /// /// Default monitored item watchdog timeout duration. /// public TimeSpan? DefaultMonitoredItemWatchdogTimeout { get; set; } /// /// The condition when to run the watchdog action in case /// of late monitored items. /// public MonitoredItemWatchdogCondition? DefaultMonitoredItemWatchdogCondition { get; set; } /// /// How long to wait until retrying on errors related /// to creating and modifying the subscription. /// public TimeSpan? SubscriptionErrorRetryDelay { get; set; } /// /// The watchdog period to kick off regular management /// of the subscription and reapply any state on failed /// nodes. /// public TimeSpan? SubscriptionManagementIntervalDuration { get; set; } /// /// At what interval should bad monitored items be retried. /// These are items that have been rejected by the server /// during subscription update or never successfully /// published. /// public TimeSpan? BadMonitoredItemRetryDelayDuration { get; set; } /// /// At what interval should invalid monitored items be /// retried. These are items that are potentially /// misconfigured. /// public TimeSpan? InvalidMonitoredItemRetryDelayDuration { get; set; } /// /// The max interval to use for bad monitored items. /// In this case exponential backoff is used. /// public TimeSpan? BadMonitoredItemRetryDelayDurationMax { get; set; } /// /// The max interval to use for invalid monitored items. /// In this case exponential backoff is used. /// public TimeSpan? InvalidMonitoredItemRetryDelayDurationMax { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Runtime/SecurityOptions.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { /// /// Security configuration /// public sealed class SecurityOptions { /// /// PkiRootPath /// public string? PkiRootPath { get; set; } /// /// Application certificate store and subject /// public CertificateInfo? ApplicationCertificates { get; set; } /// /// Whether to auto accept untrusted certificates /// public bool? AutoAcceptUntrustedCertificates { get; set; } /// /// Minimum key size /// public ushort MinimumCertificateKeySize { get; set; } /// /// Rejected store /// public CertificateStore? RejectedCertificateStore { get; set; } /// /// Whether to reject unsecure signatures /// public bool? RejectSha1SignedCertificates { get; set; } /// /// Trusted certificates /// public CertificateStore? TrustedIssuerCertificates { get; set; } /// /// Trusted peer certificates /// public CertificateStore? TrustedPeerCertificates { get; set; } /// /// Automatically add application certificate to the trusted store /// public bool? AddAppCertToTrustedStore { get; set; } /// /// Reject chain validation with CA certs with unknown revocation status, /// e.g.when the CRL is not available or the OCSP provider is offline. /// public bool? RejectUnknownRevocationStatus { get; set; } /// /// Trusted user certificates /// public CertificateStore? TrustedUserCertificates { get; set; } /// /// Trusted https certificates /// public CertificateStore? TrustedHttpsCertificates { get; set; } /// /// Http issuer certificates (certificate authority) /// public CertificateStore? HttpsIssuerCertificates { get; set; } /// /// User issuer certificates /// public CertificateStore? UserIssuerCertificates { get; set; } /// /// Password to secure the key of the application certificate /// in the private key infrastructure. /// public string? ApplicationCertificatePassword { get; set; } /// /// Try to use the configuration from the first application /// certificate found in the application certificate store /// configured above. /// public bool? TryUseConfigurationFromExistingAppCert { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Runtime/TransportOptions.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { /// /// Transport quota configuration /// public sealed class TransportOptions { /// /// Channel lifetime in milliseconds. /// public int ChannelLifetime { get; set; } /// /// Max array length /// public int MaxArrayLength { get; set; } /// /// Max buffer size /// public int MaxBufferSize { get; set; } /// /// Max string length /// public int MaxByteStringLength { get; set; } /// /// Max message size /// public int MaxMessageSize { get; set; } /// /// Max string length /// public int MaxStringLength { get; set; } /// /// Operation timeout in milliseconds. /// public int OperationTimeout { get; set; } /// /// Security token lifetime in milliseconds. /// public int SecurityTokenLifetime { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaApplication.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Services { using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Models; using Furly; using Furly.Exceptions; using Furly.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Opc.Ua; using Opc.Ua.Configuration; using Opc.Ua.Security.Certificates; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading; using System.Threading.Tasks; /// /// Client configuration /// public sealed class OpcUaApplication : IAwaitable, IOpcUaConfiguration, IOpcUaCertificates, ICertificatePasswordProvider, IDisposable { /// public ApplicationConfiguration Value => _configuration.Result; /// public event CertificateValidationEventHandler Validate { add => Value.CertificateValidator.CertificateValidation += value; remove => Value.CertificateValidator.CertificateValidation -= value; } private string Password => _options.Value.Security.ApplicationCertificatePassword ?? string.Empty; /// /// Create client manager /// /// /// /// /// public OpcUaApplication(IOptions options, ILogger logger, TimeProvider? timeProvider = null, IProcessIdentity? identity = null) { if (options.Value.Security == null) { throw new ArgumentException("Security options not provided", nameof(options)); } if (options.Value.Security.ApplicationCertificates?.SubjectName == null) { throw new ArgumentException("Application certificate missing", nameof(options)); } if (options.Value.Security.TrustedIssuerCertificates == null) { throw new ArgumentException("Trusted issuer certificates missing", nameof(options)); } if (options.Value.Security.TrustedPeerCertificates == null) { throw new ArgumentException("Trusted peer certificates missing", nameof(options)); } if (options.Value.Security.RejectedCertificateStore == null) { throw new ArgumentException("Rejected certificate store missing", nameof(options)); } if (options.Value.Security.TrustedUserCertificates == null) { throw new ArgumentException("Trusted user certificates store missing", nameof(options)); } if (options.Value.Security.HttpsIssuerCertificates == null) { throw new ArgumentException("Https issuer certificate store missing", nameof(options)); } if (options.Value.Security.TrustedHttpsCertificates == null) { throw new ArgumentException("Trusted https certificates store missing", nameof(options)); } if (options.Value.Security.UserIssuerCertificates == null) { throw new ArgumentException("User issuer certificates store missing", nameof(options)); } if (new[] { options.Value.Security.ApplicationCertificates.StoreType, options.Value.Security.TrustedIssuerCertificates.StoreType, options.Value.Security.TrustedPeerCertificates.StoreType, options.Value.Security.RejectedCertificateStore.StoreType, options.Value.Security.TrustedUserCertificates.StoreType, options.Value.Security.HttpsIssuerCertificates.StoreType, options.Value.Security.TrustedHttpsCertificates.StoreType, options.Value.Security.UserIssuerCertificates.StoreType }.Any(t => t?.Equals(FlatCertificateStore.StoreTypeName, StringComparison.OrdinalIgnoreCase) == true)) { // Register FlatCertificateStore as known certificate store type. var certStoreTypeName = CertificateStoreType.GetCertificateStoreTypeByName( FlatCertificateStore.StoreTypeName); if (certStoreTypeName is null) { CertificateStoreType.RegisterCertificateStoreType( FlatCertificateStore.StoreTypeName, new FlatCertificateStore()); } } _logger = logger; _options = options; _timeProvider = timeProvider ?? TimeProvider.System; _identity = identity?.Identity; _configuration = BuildAsync(); } /// public void Dispose() { _configuration.GetAwaiter().GetResult(); _disposed = true; } /// public IAwaiter GetAwaiter() { return _configuration.AsAwaiter(this); } /// public async ValueTask> ListCertificatesAsync( CertificateStoreName store, bool includePrivateKey, CancellationToken ct) { // show application certs using var certStore = await OpenAsync(store).ConfigureAwait(false); var certificates = new List(); foreach (var cert in await certStore.EnumerateAsync(ct).ConfigureAwait(false)) { switch (store) { case CertificateStoreName.Application: if (!includePrivateKey || !certStore.SupportsLoadPrivateKey) { goto default; } var certificateType = DetermineCertificateType(cert); var withPrivateKey = await certStore.LoadPrivateKeyAsync(cert.Thumbprint, cert.Subject, null, certificateType, Password, ct).ConfigureAwait(false); if (withPrivateKey == null) { goto default; } certificates.Add(withPrivateKey.ToServiceModel()); break; default: certificates.Add(cert.ToServiceModel()); break; } } return certificates; } /// public async ValueTask> ListCertificateRevocationListsAsync( CertificateStoreName store, CancellationToken ct) { using var certStore = await OpenAsync(store).ConfigureAwait(false); if (!certStore.SupportsCRLs) { return Array.Empty(); } var crls = await certStore.EnumerateCRLsAsync(ct).ConfigureAwait(false); return crls.Select(c => c.RawData).ToList(); } /// public async ValueTask AddCertificateAsync(CertificateStoreName store, byte[] pfxBlob, string? password, CancellationToken ct) { ObjectDisposedException.ThrowIf(_disposed, this); using var cert = X509CertificateLoader.LoadPkcs12(pfxBlob, password, X509KeyStorageFlags.Exportable); using var certStore = await OpenAsync(store).ConfigureAwait(false); try { _logger.AddCertificate(cert.Thumbprint, store.ToString()); var certCollection = await certStore.FindByThumbprintAsync(cert.Thumbprint, ct).ConfigureAwait(false); if (certCollection.Count != 0) { await certStore.DeleteAsync(cert.Thumbprint, ct).ConfigureAwait(false); } await certStore.AddAsync(cert, store == CertificateStoreName.Application ? Password : password, ct).ConfigureAwait(false); if (store == CertificateStoreName.Application) { // // Work around the bad API in the opc ua stack as certs should be a store // not list of identifiers. Update the list of identifiers here. // var existing = Value.SecurityConfiguration.ApplicationCertificates; var certId = new CertificateIdentifier(cert); certId.CertificateType = DetermineCertificateType(cert); certId.StorePath = certStore.StorePath; certId.StoreType = certStore.StoreType; existing.Insert(0, certId); Value.SecurityConfiguration.ApplicationCertificates = existing; if (_options.Value.Security.AddAppCertToTrustedStore == true) { using var trustedCert = new X509Certificate2(cert); using var trustedStore = await OpenAsync(CertificateStoreName.Trusted).ConfigureAwait(false); await trustedStore.AddAsync(trustedCert, ct: ct).ConfigureAwait(false); } } } catch (Exception ex) { _logger.AddCertificateFailed(ex, cert.Thumbprint, store.ToString()); throw; } } /// public async ValueTask AddCertificateRevocationListAsync(CertificateStoreName store, byte[] crl, CancellationToken ct) { ObjectDisposedException.ThrowIf(_disposed, this); using var certStore = await OpenAsync(store).ConfigureAwait(false); if (!certStore.SupportsCRLs) { throw new NotSupportedException("Store does not support revocation lists"); } try { _logger.AddCrl(store.ToString()); await certStore.AddCRLAsync(new X509CRL(crl), ct).ConfigureAwait(false); } catch (Exception ex) { _logger.AddCrlFailed(ex, store.ToString()); throw; } } /// public async ValueTask ApproveRejectedCertificateAsync(string thumbprint, CancellationToken ct) { ObjectDisposedException.ThrowIf(_disposed, this); thumbprint = SanitizeThumbprint(thumbprint); using var rejected = await OpenAsync(CertificateStoreName.Rejected).ConfigureAwait(false); var certCollection = await rejected.FindByThumbprintAsync(thumbprint, ct).ConfigureAwait(false); if (certCollection.Count == 0) { throw new ResourceNotFoundException("Certificate not found"); } var trustedCert = certCollection[0]; thumbprint = trustedCert.Thumbprint; try { using var trusted = await OpenAsync(CertificateStoreName.Trusted).ConfigureAwait(false); certCollection = await trusted.FindByThumbprintAsync(thumbprint, ct).ConfigureAwait(false); if (certCollection.Count != 0) { // This should not happen but maybe a previous approval aborted half-way. _logger.RejectedCertInTrustedStore(); await trusted.DeleteAsync(thumbprint, ct).ConfigureAwait(false); } // Add the trusted cert and remove from rejected await trusted.AddAsync(trustedCert, ct: ct).ConfigureAwait(false); if (!await rejected.DeleteAsync(thumbprint, ct).ConfigureAwait(false)) { // Try revert back... await trusted.DeleteAsync(thumbprint, ct).ConfigureAwait(false); } } catch (Exception ex) { _logger.ApproveCertificateFailed(ex, thumbprint); throw; } } /// public async ValueTask AddCertificateChainAsync(byte[] certificateChain, bool isSslCertificate, CancellationToken ct) { ObjectDisposedException.ThrowIf(_disposed, this); var chain = Utils.ParseCertificateChainBlob(certificateChain)? .Cast() .Reverse() .ToList(); if (chain == null || chain.Count == 0) { throw new ArgumentNullException(nameof(certificateChain)); } var configuration = await _configuration.ConfigureAwait(false); var x509Certificate = chain[0]; try { _logger.AddToTrustedStore(x509Certificate.Thumbprint, x509Certificate.Subject); if (isSslCertificate) { await configuration.SecurityConfiguration.TrustedHttpsCertificates .AddAsync(x509Certificate.YieldReturn(), ct: ct).ConfigureAwait(false); chain.RemoveAt(0); if (chain.Count > 0) { await configuration.SecurityConfiguration.HttpsIssuerCertificates .AddAsync(chain, ct: ct).ConfigureAwait(false); } } else { await configuration.SecurityConfiguration.TrustedPeerCertificates .AddAsync(x509Certificate.YieldReturn(), ct: ct).ConfigureAwait(false); chain.RemoveAt(0); if (chain.Count > 0) { await configuration.SecurityConfiguration.TrustedIssuerCertificates .AddAsync(chain, ct: ct).ConfigureAwait(false); } } } catch (Exception ex) { _logger.AddToTrustedStoreFailed(ex, x509Certificate.Thumbprint, x509Certificate.Subject); throw; } finally { chain?.ForEach(c => c?.Dispose()); } } /// public async ValueTask RemoveCertificateAsync(CertificateStoreName store, string thumbprint, CancellationToken ct) { ObjectDisposedException.ThrowIf(_disposed, this); thumbprint = SanitizeThumbprint(thumbprint); using var certStore = await OpenAsync(store).ConfigureAwait(false); try { _logger.RemoveCertificate(thumbprint, store.ToString()); var certCollection = await certStore.FindByThumbprintAsync(thumbprint, ct).ConfigureAwait(false); if (certCollection.Count == 0) { throw new ResourceNotFoundException("Certificate not found."); } // delete all CRLs signed by cert var crlsToDelete = new X509CRLCollection(); foreach (var crl in await certStore.EnumerateCRLsAsync(ct).ConfigureAwait(false) ) { foreach (var cert in certCollection) { if (X509Utils.CompareDistinguishedName(cert.SubjectName, crl.IssuerName) && crl.VerifySignature(cert, false)) { crlsToDelete.Add(crl); break; } } } if (store == CertificateStoreName.Application) { var existing = Value.SecurityConfiguration.ApplicationCertificates; existing.RemoveAll(c => c.Thumbprint == thumbprint); Value.SecurityConfiguration.ApplicationCertificates = existing; } if (!await certStore.DeleteAsync(thumbprint, ct).ConfigureAwait(false)) { throw new ResourceNotFoundException("Certificate not found."); } foreach (var crl in crlsToDelete) { if (!await certStore.DeleteCRLAsync(crl, ct).ConfigureAwait(false)) { // intentionally ignore errors, try best effort _logger.DeleteCrlFailed(crl.ToString()); } } } catch (Exception ex) { _logger.RemoveCertificateFailed(ex, thumbprint, store.ToString()); throw; } } /// public async ValueTask CleanAsync(CertificateStoreName store, CancellationToken ct) { ObjectDisposedException.ThrowIf(_disposed, this); using var certStore = await OpenAsync(store).ConfigureAwait(false); try { _logger.RemoveAllCertificates(store.ToString()); foreach (var certs in await certStore.EnumerateAsync(ct).ConfigureAwait(false)) { if (!await certStore.DeleteAsync(certs.Thumbprint, ct).ConfigureAwait(false)) { // intentionally ignore errors, try best effort _logger.DeleteCertificateFailed(certs.Thumbprint); } } foreach (var crl in await certStore.EnumerateCRLsAsync(ct).ConfigureAwait(false)) { if (!await certStore.DeleteCRLAsync(crl, ct).ConfigureAwait(false)) { // intentionally ignore errors, try best effort _logger.DeleteCrlFailed(crl.ToString()); } } } catch (Exception ex) { _logger.ClearStoreFailed(ex, store.ToString()); throw; } } /// public async ValueTask RemoveCertificateRevocationListAsync(CertificateStoreName store, byte[] crl, CancellationToken ct) { ObjectDisposedException.ThrowIf(_disposed, this); using var certStore = await OpenAsync(store).ConfigureAwait(false); if (!certStore.SupportsCRLs) { throw new NotSupportedException("Store does not support revocation lists"); } try { _logger.AddCrl(store.ToString()); await certStore.DeleteCRLAsync(new X509CRL(crl), ct).ConfigureAwait(false); } catch (Exception ex) { _logger.DeleteCrlStoreFailed(ex, store.ToString()); throw; } } /// public string GetPassword(CertificateIdentifier certificateIdentifier) { return Password; } /// /// Build application configuration /// /// /// /// private async Task BuildAsync() { Debug.Assert(!string.IsNullOrWhiteSpace(_options.Value.ApplicationName)); var appInstance = new ApplicationInstance { ApplicationName = _options.Value.ApplicationName, ApplicationType = Opc.Ua.ApplicationType.Client }; Exception innerException = new InvalidConfigurationException("Missing network."); for (var attempt = 0; attempt < 60; attempt++) { // wait with the configuration until network is up if (!NetworkInterface.GetIsNetworkAvailable()) { _logger.NetworkNotAvailable(); await Task.Delay(3000).ConfigureAwait(false); continue; } var hostname = !string.IsNullOrWhiteSpace(_identity) ? Uri.CheckHostName(_identity) != UriHostNameType.Unknown ? _identity : #pragma warning disable CA5350 // Do Not Use Weak Cryptographic Algorithms new IPAddress(SHA1.HashData(Encoding.UTF8.GetBytes(_identity)) .AsSpan()[..16], 0).ToString() : #pragma warning restore CA5350 // Do Not Use Weak Cryptographic Algorithms Utils.GetHostName(); var applicationUri = _options.Value.ApplicationUri; if (_options.Value.Security.TryUseConfigurationFromExistingAppCert == true) { (applicationUri, appInstance.ApplicationName, hostname) = await UpdateFromExistingCertificateAsync( applicationUri, appInstance.ApplicationName, hostname, _options.Value.Security).ConfigureAwait(false); } if (applicationUri == null) { applicationUri = $"urn:{hostname}:opc-publisher"; } else { applicationUri = applicationUri.Replace("urn:localhost", $"urn:{hostname}", StringComparison.Ordinal); } var appBuilder = appInstance.Build(applicationUri, _options.Value.ProductUri) .SetTransportQuotas(ToTransportQuotas(_options.Value.Quotas)) .AsClient(); try { var appConfig = await BuildSecurityConfigurationAsync(appBuilder, _options.Value.Security, appInstance.ApplicationConfiguration, hostname) .ConfigureAwait(false); var ownCertificate = appConfig.SecurityConfiguration.ApplicationCertificate.Certificate; if (ownCertificate == null) { _logger.CreateSelfSignedCert(); } else { _logger.OwnCertificateLoaded(ownCertificate.Subject, ownCertificate.Thumbprint); } var hasAppCertificate = await appInstance.CheckApplicationInstanceCertificatesAsync(true).ConfigureAwait(false); if (!hasAppCertificate || appConfig.SecurityConfiguration.ApplicationCertificate.Certificate == null) { _logger.LoadCertificateFailed(); throw new InvalidConfigurationException( "OPC UA application own certificate invalid"); } if (ownCertificate == null) { ownCertificate = appConfig.SecurityConfiguration.ApplicationCertificate.Certificate; _logger.OwnCertificateCreated(ownCertificate.Subject, ownCertificate.Thumbprint); } await ShowCertificateStoreInformationAsync(appConfig).ConfigureAwait(false); return appInstance.ApplicationConfiguration; } catch (Exception e) { _logger.ConfigureStackRetry(e.Message); _logger.ConfigureStackDebug(e); innerException = e; await Task.Delay(3000).ConfigureAwait(false); } } _logger.ConfigureStackFailed(); throw new InvalidProgramException("OPC UA stack configuration not possible.", innerException); async ValueTask<(string?, string, string)> UpdateFromExistingCertificateAsync( string? applicationUri, string appName, string hostName, SecurityOptions options) { try { var now = _timeProvider.GetUtcNow(); if (options.ApplicationCertificates?.StorePath != null && options.ApplicationCertificates.StoreType != null) { using var certStore = CertificateStoreIdentifier.CreateStore( options.ApplicationCertificates.StoreType); certStore.Open(options.ApplicationCertificates.StorePath, false); var certs = await certStore.EnumerateAsync().ConfigureAwait(false); var subjects = new List(); foreach (var cert in certs.Where(c => c != null).OrderBy(c => c.NotAfter)) { // Select first certificate that has valid information options.ApplicationCertificates.SubjectName = cert.Subject; var name = cert.SubjectName.EnumerateRelativeDistinguishedNames() .Where(dn => dn.GetSingleElementType().FriendlyName == "CN") .Select(dn => dn.GetSingleElementValue()) .FirstOrDefault(dn => dn != null); if (name != null) { appName = name; } var san = cert.FindExtension(); var uris = san?.Uris; var hostNames = san?.DomainNames; if (uris != null && hostNames != null && uris.Count > 0 && hostNames.Count > 0) { return (uris[0], appName, hostNames[0]); } _logger.InvalidCertFound(cert.Subject, cert.Thumbprint); } } _logger.NoCertFound(); } catch (Exception ex) { _logger.FindCertFailed(ex); } return (applicationUri, appName, hostName); } } /// /// Show all certificates in the certificate stores. /// /// private async ValueTask ShowCertificateStoreInformationAsync( ApplicationConfiguration appConfig) { // show application certs try { using var certStore = appConfig.SecurityConfiguration.ApplicationCertificate.OpenStore(); var certs = await certStore.EnumerateAsync().ConfigureAwait(false); var certNum = 1; _logger.OwnStoreCount(certs.Count); foreach (var cert in certs) { _logger.CertificateInfo(certNum++, cert.Subject, cert.Thumbprint); } } catch (Exception e) { _logger.ReadStoreFailed(e); } // show trusted issuer certs try { using var certStore = appConfig.SecurityConfiguration .TrustedIssuerCertificates.OpenStore(); var certs = await certStore.EnumerateAsync().ConfigureAwait(false); var certNum = 1; _logger.TrustedIssuerCount(certs.Count); foreach (var cert in certs) { _logger.CertificateInfo(certNum++, cert.Subject, cert.Thumbprint); } if (certStore.SupportsCRLs) { var crls = await certStore.EnumerateCRLsAsync().ConfigureAwait(false); var crlNum = 1; _logger.TrustedIssuerCrlCount(crls.Count); foreach (var crl in crls) { _logger.TrustedIssuerCrlInfo(crlNum++, crl.Issuer, crl.NextUpdate); } } } catch (Exception e) { _logger.TrustedIssuerStoreFailed(e); } // show trusted peer certs try { using var certStore = appConfig.SecurityConfiguration .TrustedPeerCertificates.OpenStore(); var certs = await certStore.EnumerateAsync().ConfigureAwait(false); var certNum = 1; _logger.TrustedPeerCount(certs.Count); foreach (var cert in certs) { _logger.CertificateInfo(certNum++, cert.Subject, cert.Thumbprint); } if (certStore.SupportsCRLs) { var crls = await certStore.EnumerateCRLsAsync().ConfigureAwait(false); var crlNum = 1; _logger.TrustedPeerCrlCount(crls.Count); foreach (var crl in crls) { _logger.TrustedPeerCrlInfo(crlNum++, crl.Issuer, crl.NextUpdate); } } } catch (Exception e) { _logger.TrustedPeerStoreFailed(e); } // show rejected peer certs try { using var certStore = appConfig.SecurityConfiguration .RejectedCertificateStore.OpenStore(); var certs = await certStore.EnumerateAsync().ConfigureAwait(false); var certNum = 1; _logger.RejectedStoreCount(certs.Count); foreach (var cert in certs) { _logger.CertificateInfo(certNum++, cert.Subject, cert.Thumbprint); } } catch (Exception e) { _logger.RejectedStoreFailed(e); } } /// /// Convert to transport quota /// /// /// private static TransportQuotas ToTransportQuotas(TransportOptions options) { return new TransportQuotas { OperationTimeout = options.OperationTimeout, MaxStringLength = options.MaxStringLength, MaxByteStringLength = options.MaxByteStringLength, MaxArrayLength = options.MaxArrayLength, MaxMessageSize = options.MaxMessageSize, MaxBufferSize = options.MaxBufferSize, ChannelLifetime = options.ChannelLifetime, SecurityTokenLifetime = options.SecurityTokenLifetime }; } /// /// Builds and applies the security configuration according to the local settings. /// Returns a the configuration application ready to use for initialization of /// the OPC UA SDK client object. /// /// /// Please note the input argument applicationConfiguration will /// be altered during execution with the locally provided security configuration /// and shall not be used after calling this method. /// /// /// /// /// /// /// private async ValueTask BuildSecurityConfigurationAsync( IApplicationConfigurationBuilderClientSelected applicationConfigurationBuilder, SecurityOptions securityOptions, ApplicationConfiguration applicationConfiguration, string? hostname = null) { var subjectName = securityOptions.ApplicationCertificates?.SubjectName; if (hostname != null && subjectName != null) { subjectName = subjectName.Replace("localhost", hostname, StringComparison.InvariantCulture); } var storeType = securityOptions.ApplicationCertificates?.StoreType; var storePath = securityOptions.ApplicationCertificates?.StorePath; var applicationCerts = new CertificateIdentifierCollection { new CertificateIdentifier { StoreType = storeType, StorePath = storePath, SubjectName = subjectName, CertificateType = ObjectTypeIds.RsaSha256ApplicationCertificateType }, new CertificateIdentifier { StoreType = storeType, StorePath = storePath, SubjectName = subjectName, CertificateType = ObjectTypeIds.EccNistP256ApplicationCertificateType }, new CertificateIdentifier { StoreType = storeType, StorePath = storePath, SubjectName = subjectName, CertificateType = ObjectTypeIds.EccNistP384ApplicationCertificateType #if NOT_LINUX // Not supported }, new CertificateIdentifier { StoreType = storeType, StorePath = storePath, SubjectName = subjectName, CertificateType = ObjectTypeIds.EccBrainpoolP256r1ApplicationCertificateType }, new CertificateIdentifier { StoreType = storeType, StorePath = storePath, SubjectName = subjectName, CertificateType = ObjectTypeIds.EccBrainpoolP384r1ApplicationCertificateType #endif } }; var options = applicationConfigurationBuilder .AddSecurityConfiguration(applicationCerts, securityOptions.PkiRootPath) .SetAutoAcceptUntrustedCertificates( securityOptions.AutoAcceptUntrustedCertificates ?? false) .SetRejectSHA1SignedCertificates( securityOptions.RejectSha1SignedCertificates ?? true) .SetMinimumCertificateKeySize( securityOptions.MinimumCertificateKeySize) .AddCertificatePasswordProvider(this) .SetAddAppCertToTrustedStore( securityOptions.AddAppCertToTrustedStore ?? true) .SetRejectUnknownRevocationStatus( securityOptions.RejectUnknownRevocationStatus ?? true); // Allow private keys in this store so user identities can be side loaded applicationConfiguration.SecurityConfiguration.TrustedUserCertificates = new TrustedUserCertificateStore(); applicationConfiguration.SecurityConfiguration.ApplicationCertificates .ApplyLocalConfig(securityOptions.ApplicationCertificates); applicationConfiguration.SecurityConfiguration.TrustedPeerCertificates .ApplyLocalConfig(securityOptions.TrustedPeerCertificates); applicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates .ApplyLocalConfig(securityOptions.TrustedIssuerCertificates); applicationConfiguration.SecurityConfiguration.RejectedCertificateStore .ApplyLocalConfig(securityOptions.RejectedCertificateStore); applicationConfiguration.SecurityConfiguration.TrustedUserCertificates .ApplyLocalConfig(securityOptions.TrustedUserCertificates); applicationConfiguration.SecurityConfiguration.TrustedHttpsCertificates .ApplyLocalConfig(securityOptions.TrustedHttpsCertificates); applicationConfiguration.SecurityConfiguration.HttpsIssuerCertificates .ApplyLocalConfig(securityOptions.HttpsIssuerCertificates); applicationConfiguration.SecurityConfiguration.UserIssuerCertificates .ApplyLocalConfig(securityOptions.UserIssuerCertificates); return await options.CreateAsync().ConfigureAwait(false); } /// /// Open store /// /// /// /// private async ValueTask OpenAsync(CertificateStoreName store) { var configuration = await _configuration.ConfigureAwait(false); var security = configuration.SecurityConfiguration; switch (store) { case CertificateStoreName.Application: return security.ApplicationCertificates.OpenStore(_options.Value.Security); case CertificateStoreName.Trusted: Debug.Assert(security.TrustedPeerCertificates != null); return security.TrustedPeerCertificates.OpenStore(); case CertificateStoreName.Rejected: Debug.Assert(security.RejectedCertificateStore != null); return security.RejectedCertificateStore.OpenStore(); case CertificateStoreName.Issuer: Debug.Assert(security.TrustedIssuerCertificates != null); return security.TrustedIssuerCertificates.OpenStore(); case CertificateStoreName.User: Debug.Assert(security.TrustedUserCertificates != null); return security.TrustedUserCertificates.OpenStore(); case CertificateStoreName.UserIssuer: Debug.Assert(security.UserIssuerCertificates != null); return security.UserIssuerCertificates.OpenStore(); case CertificateStoreName.Https: Debug.Assert(security.TrustedHttpsCertificates != null); return security.TrustedHttpsCertificates.OpenStore(); case CertificateStoreName.HttpsIssuer: Debug.Assert(security.HttpsIssuerCertificates != null); return security.HttpsIssuerCertificates.OpenStore(); default: throw new ArgumentException( $"Bad unknown certificate store {store} specified."); } } /// /// Try determining type of certificate /// /// /// private static NodeId? DetermineCertificateType(X509Certificate2 cert) { if (cert.GetRSAPublicKey() != null) { return ObjectTypeIds.RsaSha256ApplicationCertificateType; } var ecdsa = cert.GetECDsaPublicKey(); if (ecdsa != null) { var parameters = ecdsa.ExportParameters(false); if (parameters.Curve.Oid.Value == ECCurve.NamedCurves.nistP256.Oid.Value) { return ObjectTypeIds.EccNistP256ApplicationCertificateType; } else if (parameters.Curve.Oid.Value == ECCurve.NamedCurves.nistP384.Oid.Value) { return ObjectTypeIds.EccNistP384ApplicationCertificateType; } else if (parameters.Curve.Oid.Value == ECCurve.NamedCurves.brainpoolP256r1.Oid.Value) { return ObjectTypeIds.EccBrainpoolP256r1ApplicationCertificateType; } else if (parameters.Curve.Oid.Value == ECCurve.NamedCurves.brainpoolP384r1.Oid.Value) { return ObjectTypeIds.EccBrainpoolP384r1ApplicationCertificateType; } else { return ObjectTypeIds.EccApplicationCertificateType; } } return null; } private static string SanitizeThumbprint(string thumbprint) { if (thumbprint.Length > kMaxThumbprintLength) { throw new ArgumentException("Bad thumbprint", nameof(thumbprint)); } return thumbprint.ReplaceLineEndings(string.Empty); } /// /// Override to support private keys /// private class TrustedUserCertificateStore : CertificateTrustList { /// public override ICertificateStore OpenStore() { var store = CreateStore(StoreType); store.Open(StorePath, false); // Allow private keys return store; } } private const int kMaxThumbprintLength = 64; private readonly Task _configuration; private readonly ILogger _logger; private readonly IOptions _options; private readonly TimeProvider _timeProvider; private readonly string? _identity; private bool _disposed; } /// /// Source-generated logging definitions for OpcUaApplication /// internal static partial class OpcUaApplicationLogging { private const int EventClass = 400; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Information, Message = "Add Certificate {Thumbprint} to {Store}...")] public static partial void AddCertificate(this ILogger logger, string thumbprint, string store); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Error, Message = "Failed to add Certificate {Thumbprint} to {Store}...")] public static partial void AddCertificateFailed(this ILogger logger, Exception ex, string thumbprint, string store); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Information, Message = "Add Certificate revocation list to {Store}...")] public static partial void AddCrl(this ILogger logger, string store); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Error, Message = "Failed to add Certificate revocation to {Store}...")] public static partial void AddCrlFailed(this ILogger logger, Exception ex, string store); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Error, Message = "Found rejected cert already in trusted store. Deleting...")] public static partial void RejectedCertInTrustedStore(this ILogger logger); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Error, Message = "Failed to approve Certificate {Thumbprint}...")] public static partial void ApproveCertificateFailed(this ILogger logger, Exception ex, string thumbprint); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Information, Message = "Adding Certificate {Thumbprint}, {Subject} to trusted store...")] public static partial void AddToTrustedStore(this ILogger logger, string thumbprint, string subject); [LoggerMessage(EventId = EventClass + 8, Level = LogLevel.Error, Message = "Failed to add Certificate chain {Thumbprint}, {Subject} to trusted store.")] public static partial void AddToTrustedStoreFailed(this ILogger logger, Exception ex, string thumbprint, string subject); [LoggerMessage(EventId = EventClass + 9, Level = LogLevel.Information, Message = "Removing Certificate {Thumbprint} from {Store}...")] public static partial void RemoveCertificate(this ILogger logger, string thumbprint, string store); [LoggerMessage(EventId = EventClass + 10, Level = LogLevel.Error, Message = "Failed to delete {Crl}.")] public static partial void DeleteCrlFailed(this ILogger logger, string? crl); [LoggerMessage(EventId = EventClass + 11, Level = LogLevel.Error, Message = "Failed to remove Certificate {Thumbprint} from {Store}...")] public static partial void RemoveCertificateFailed(this ILogger logger, Exception ex, string thumbprint, string store); [LoggerMessage(EventId = EventClass + 12, Level = LogLevel.Information, Message = "Removing all Certificate from {Store}...")] public static partial void RemoveAllCertificates(this ILogger logger, string store); [LoggerMessage(EventId = EventClass + 13, Level = LogLevel.Error, Message = "Failed to clear {Store} store.")] public static partial void ClearStoreFailed(this ILogger logger, Exception ex, string store); [LoggerMessage(EventId = EventClass + 14, Level = LogLevel.Error, Message = "Failed to delete Certificate revocation in {Store}...")] public static partial void DeleteCrlStoreFailed(this ILogger logger, Exception ex, string store); [LoggerMessage(EventId = EventClass + 15, Level = LogLevel.Information, Message = "No application own certificate found. Creating a self-signed certificate.")] public static partial void CreateSelfSignedCert(this ILogger logger); [LoggerMessage(EventId = EventClass + 16, Level = LogLevel.Information, Message = "Own certificate Subject '{Subject}' (Thumbprint: {Thumbprint}) loaded.")] public static partial void OwnCertificateLoaded(this ILogger logger, string subject, string thumbprint); [LoggerMessage(EventId = EventClass + 17, Level = LogLevel.Error, Message = "Failed to load or create application own certificate.")] public static partial void LoadCertificateFailed(this ILogger logger); [LoggerMessage(EventId = EventClass + 18, Level = LogLevel.Information, Message = "Own certificate Subject '{Subject}' (Thumbprint: {Thumbprint}) created.")] public static partial void OwnCertificateCreated(this ILogger logger, string subject, string thumbprint); [LoggerMessage(EventId = EventClass + 19, Level = LogLevel.Information, Message = "Error {Message} while configuring OPC UA stack - retry...")] public static partial void ConfigureStackRetry(this ILogger logger, string message); [LoggerMessage(EventId = EventClass + 20, Level = LogLevel.Debug, Message = "Detailed error while configuring OPC UA stack.")] public static partial void ConfigureStackDebug(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 21, Level = LogLevel.Critical, Message = "Failed to configure OPC UA stack - exit.")] public static partial void ConfigureStackFailed(this ILogger logger); [LoggerMessage(EventId = EventClass + 22, Level = LogLevel.Debug, Message = "Found invalid certificate for {Subject} [{Thumbprint}].")] public static partial void InvalidCertFound(this ILogger logger, string subject, string thumbprint); [LoggerMessage(EventId = EventClass + 23, Level = LogLevel.Debug, Message = "Could not find a certificate to take information from.")] public static partial void NoCertFound(this ILogger logger); [LoggerMessage(EventId = EventClass + 24, Level = LogLevel.Debug, Message = "Failed to find a certificate to take information from.")] public static partial void FindCertFailed(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 25, Level = LogLevel.Information, Message = "Application own certificate store contains {Count} certs.")] public static partial void OwnStoreCount(this ILogger logger, int count); [LoggerMessage(EventId = EventClass + 26, Level = LogLevel.Information, Message = "{CertNum:D2}: Subject '{Subject}' (Thumbprint: {Thumbprint})")] public static partial void CertificateInfo(this ILogger logger, int certNum, string subject, string thumbprint); [LoggerMessage(EventId = EventClass + 27, Level = LogLevel.Error, Message = "Error while trying to read information from application store.")] public static partial void ReadStoreFailed(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 28, Level = LogLevel.Information, Message = "Trusted issuer store contains {Count} certs.")] public static partial void TrustedIssuerCount(this ILogger logger, int count); [LoggerMessage(EventId = EventClass + 29, Level = LogLevel.Information, Message = "Trusted issuer store has {Count} CRLs.")] public static partial void TrustedIssuerCrlCount(this ILogger logger, int count); [LoggerMessage(EventId = EventClass + 30, Level = LogLevel.Information, Message = "{CrlNum:D2}: Issuer '{Issuer}', Next update time '{NextUpdate}'")] public static partial void TrustedIssuerCrlInfo(this ILogger logger, int crlNum, string issuer, DateTime nextUpdate); [LoggerMessage(EventId = EventClass + 31, Level = LogLevel.Error, Message = "Error while trying to read information from trusted issuer store.")] public static partial void TrustedIssuerStoreFailed(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 32, Level = LogLevel.Information, Message = "Trusted peer store contains {Count} certs.")] public static partial void TrustedPeerCount(this ILogger logger, int count); [LoggerMessage(EventId = EventClass + 33, Level = LogLevel.Information, Message = "Trusted peer store has {Count} CRLs.")] public static partial void TrustedPeerCrlCount(this ILogger logger, int count); [LoggerMessage(EventId = EventClass + 34, Level = LogLevel.Information, Message = "{CrlNum:D2}: Issuer '{Issuer}', Next update time '{NextUpdate}'")] public static partial void TrustedPeerCrlInfo(this ILogger logger, int crlNum, string issuer, DateTime nextUpdate); [LoggerMessage(EventId = EventClass + 35, Level = LogLevel.Error, Message = "Error while trying to read information from trusted peer store.")] public static partial void TrustedPeerStoreFailed(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 36, Level = LogLevel.Information, Message = "Rejected certificate store contains {Count} certs.")] public static partial void RejectedStoreCount(this ILogger logger, int count); [LoggerMessage(EventId = EventClass + 37, Level = LogLevel.Error, Message = "Error while trying to read information from rejected certificate store.")] public static partial void RejectedStoreFailed(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 38, Level = LogLevel.Warning, Message = "Network not available...")] public static partial void NetworkNotAvailable(this ILogger logger); [LoggerMessage(EventId = EventClass + 39, Level = LogLevel.Error, Message = "Failed to delete {Certificate}.")] public static partial void DeleteCertificateFailed(this ILogger logger, string? certificate); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaClient.Browser.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Services { using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Models; using Microsoft.Extensions.Logging; using Opc.Ua; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; internal sealed partial class OpcUaClient { /// /// Create a browser to browse the address space and provide /// the differences from last browsing operation. /// /// /// /// internal IOpcUaBrowser Browse(TimeSpan rebrowsePeriod, string subscriptionName) { return Browser.Register(this, rebrowsePeriod, subscriptionName); } /// /// Browser utility class /// private sealed class Browser : IAsyncDisposable, IOpcUaBrowser { /// /// Reference changes /// public event EventHandler>? OnReferenceChange; /// /// Node changes /// public event EventHandler>? OnNodeChange; /// /// Create browser /// /// /// /// private Browser(OpcUaClient client, string subscriptionId, TimeSpan browseDelay) { _client = client; _logger = client._logger; _subscriptionId = subscriptionId; _browseDelay = browseDelay == TimeSpan.Zero ? Timeout.InfiniteTimeSpan : browseDelay; _channel = Channel.CreateUnbounded(); // Order is important _rebrowseTimer = _client._timeProvider.CreateTimer(_ => _channel.Writer.TryWrite(true), null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); _browser = RunAsync(_cts.Token); _channel.Writer.TryWrite(true); } /// public async ValueTask CloseAsync() { if (Release()) { await DisposeAsync().ConfigureAwait(false); } } /// public async ValueTask DisposeAsync() { if (!_disposed) { _disposed = true; try { _rebrowseTimer.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); _channel.Writer.TryComplete(); await _cts.CancelAsync().ConfigureAwait(false); await _browser.ConfigureAwait(false); } finally { _cts.Dispose(); _rebrowseTimer.Dispose(); } } } /// public void Rebrowse() { _channel.Writer.TryWrite(true); } /// /// Signal session connected /// public void OnConnected() { _channel.Writer.TryWrite(false); } /// /// Continously browse /// /// /// private async Task RunAsync(CancellationToken ct) { _logger.BrowserStartingContinuousBrowsing(); var sw = Stopwatch.StartNew(); try { await foreach (var result in _channel.Reader.ReadAllAsync(ct).ConfigureAwait(false)) { if (!result) { // Start browsing in 10 seconds _rebrowseTimer.Change(TimeSpan.FromSeconds(10), Timeout.InfiniteTimeSpan); continue; } _rebrowseTimer.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); try { var session = _client._session; if (session?.Connected != true) { continue; } _logger.BrowserBrowsingStarted(sw.Elapsed); sw.Restart(); await BrowseAddressSpaceAsync(session, ct).ConfigureAwait(false); _logger.BrowserBrowsingCompleted(sw.Elapsed, _referencesAdded, _referencesRemoved, _nodesAdded, _nodesChanged, _nodesRemoved, _errors); } catch (ServiceResultException sre) { _logger.BrowserBrowsingCompletedWithError(sre.Message, sw.Elapsed, _referencesAdded, _referencesRemoved, _nodesAdded, _nodesChanged, _nodesRemoved, _errors); if (!_client.IsConnected) { _logger.BrowserNotConnectedWaiting(); continue; } _logger.BrowserErrorOccurred(sre); } catch (OperationCanceledException) { break; } catch (Exception ex) { // Continue _logger.BrowserBrowsingException(ex, sw.Elapsed); } finally { sw.Restart(); _referencesAdded = _referencesRemoved = 0; _nodesAdded = _nodesChanged = _nodesRemoved = 0; _errors = 0; _rebrowseTimer.Change(_browseDelay, Timeout.InfiniteTimeSpan); } } _logger.BrowserProcessExited(); } catch (Exception e) { _logger.BrowserProcessExitedUnexpected(e); } } /// /// Browse address space /// /// /// /// private async Task BrowseAddressSpaceAsync(OpcUaSession session, CancellationToken ct) { var browseDescriptionCollection = CreateBrowseDescriptionCollection( (ObjectIds.RootFolder, new RelativePath()).YieldReturn()); // Browse var foundReferences = new Dictionary( Compare.Using(Utils.IsEqual)); var foundNodes = new Dictionary(); try { var searchDepth = 0; var maxNodesPerBrowse = session.OperationLimits.MaxNodesPerBrowse; while (browseDescriptionCollection.Count != 0 && searchDepth < kMaxSearchDepth) { searchDepth++; bool repeatBrowse; var allBrowseResults = new List<(NodeId, RelativePath, BrowseResult)>(); var unprocessedOperations = new BrowseDescriptionCollection(); BrowseResultCollection? browseResultCollection = null; do { var browseCollection = maxNodesPerBrowse == 0 ? browseDescriptionCollection : browseDescriptionCollection.Take((int)maxNodesPerBrowse).ToArray(); repeatBrowse = false; try { var browseResponse = await session.BrowseAsync(null, null, kMaxReferencesPerNode, browseCollection, ct).ConfigureAwait(false); browseResultCollection = browseResponse.Results; ClientBase.ValidateResponse(browseResultCollection, browseCollection); ClientBase.ValidateDiagnosticInfos( browseResponse.DiagnosticInfos, browseCollection); // seperate unprocessed nodes for later for (var index = 0; index < browseResultCollection.Count; index++) { var browseResult = browseResultCollection[index]; // check for error. var statusCode = browseResult.StatusCode; if (StatusCode.IsBad(statusCode)) { // // this error indicates that the server does not have enough // simultaneously active continuation points. This request will // need to be re-sent after the other operations have been // completed and their continuation points released. // if (statusCode == StatusCodes.BadNoContinuationPoints) { unprocessedOperations.Add(browseCollection[index]); continue; } } // save results. allBrowseResults.Add((browseCollection[index].NodeId, (RelativePath)browseCollection[index].Handle, browseResult)); } } catch (ServiceResultException sre) when (sre.StatusCode == StatusCodes.BadEncodingLimitsExceeded || sre.StatusCode == StatusCodes.BadResponseTooLarge) { // try to address by overriding operation limit maxNodesPerBrowse = maxNodesPerBrowse == 0 ? (uint)browseCollection.Count / 2 : maxNodesPerBrowse / 2; repeatBrowse = true; } } while (repeatBrowse); // Browse next Debug.Assert(browseResultCollection != null); var (nodeIds, continuationPoints) = PrepareBrowseNext( new NodeIdCollection(browseDescriptionCollection .Take(browseResultCollection.Count).Select(r => r.NodeId)), browseResultCollection); while (continuationPoints.Count != 0) { var browseNextResult = await session.BrowseNextAsync(null, false, continuationPoints, ct).ConfigureAwait(false); var browseNextResultCollection = browseNextResult.Results; ClientBase.ValidateResponse(browseNextResultCollection, continuationPoints); ClientBase.ValidateDiagnosticInfos( browseNextResult.DiagnosticInfos, continuationPoints); allBrowseResults.AddRange(browseNextResultCollection .Select((r, i) => (browseDescriptionCollection[i].NodeId, (RelativePath)browseDescriptionCollection[i].Handle, r))); (nodeIds, continuationPoints) = PrepareBrowseNext(nodeIds, browseNextResultCollection); } if (maxNodesPerBrowse == 0) { browseDescriptionCollection.Clear(); } else { browseDescriptionCollection = browseDescriptionCollection .Skip(browseResultCollection.Count) .ToArray(); } static (NodeIdCollection, ByteStringCollection) PrepareBrowseNext( NodeIdCollection browseSourceCollection, BrowseResultCollection results) { var continuationPoints = new ByteStringCollection(); var nodeIdCollection = new NodeIdCollection(); for (var i = 0; i < results.Count; i++) { var browseResult = results[i]; if (browseResult.ContinuationPoint != null) { nodeIdCollection.Add(browseSourceCollection[i]); continuationPoints.Add(browseResult.ContinuationPoint); } } return (nodeIdCollection, continuationPoints); } // Build browse request for next level var browseTable = new List<(NodeId, RelativePath)>(); foreach (var (source, path, browseResult) in allBrowseResults) { var nodesToRead = new List(); foreach (var reference in browseResult.References) { if (foundReferences.TryAdd(reference, (source, path))) { if (!_knownReferences.Remove(reference)) { // Send new reference _referencesAdded++; OnReferenceChange?.Invoke(session, CreateChange(source, path, null, reference)); } var targetNodeId = ExpandedNodeId.ToNodeId(reference.NodeId, session.NamespaceUris); var targetPath = new RelativePath { Elements = new RelativePathElementCollection(path.Elements .Append(new RelativePathElement { TargetName = reference.BrowseName, IsInverse = false, IncludeSubtypes = false, ReferenceTypeId = reference.ReferenceTypeId })) }; browseTable.Add((targetNodeId, targetPath)); await ReadNodeAsync(session, targetNodeId, targetPath, foundNodes, ct).ConfigureAwait(false); } } } browseDescriptionCollection.AddRange(CreateBrowseDescriptionCollection(browseTable)); // add unprocessed nodes if any browseDescriptionCollection.AddRange(unprocessedOperations); } _referencesRemoved += _knownReferences.Count; foreach (var (removedReference, (nodeId, path)) in _knownReferences) { OnReferenceChange?.Invoke(session, CreateChange(nodeId, path, removedReference, null)); } _knownReferences.Clear(); _nodesRemoved += _knownNodes.Count; foreach (var (removedNodeId, (path, removedNode)) in _knownNodes) { OnNodeChange?.Invoke(session, CreateChange(removedNodeId, path, removedNode, null)); } _knownNodes.Clear(); } catch (OperationCanceledException) { return; } catch (Exception ex) { HandleException(foundReferences, foundNodes, ex); throw; } finally { _knownReferences = foundReferences; _knownNodes = foundNodes; } static BrowseDescriptionCollection CreateBrowseDescriptionCollection( IEnumerable<(NodeId NodeId, RelativePath Position)> items) { return new BrowseDescriptionCollection(items.Select( item => new BrowseDescription { Handle = item.Position, BrowseDirection = Opc.Ua.BrowseDirection.Forward, ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences, IncludeSubtypes = true, NodeId = item.NodeId, NodeClassMask = 0, ResultMask = (uint)BrowseResultMask.All })); } void HandleException(Dictionary foundReferences, Dictionary foundNodes, Exception ex) { _logger.BrowserStoppingDueToError(ex); // Reset stream by resetting the sequence number to 0 _sequenceNumber = 0u; // // In case of exception we could not process the entire address space // We add the remainder of the remaining existing references and nodes // back to the currently known nodes and references and sort those out // next time around. // foreach (var removedReference in _knownReferences) { // Re-add foundReferences.AddOrUpdate(removedReference.Key, removedReference.Value); } _knownReferences.Clear(); foreach (var removedNode in _knownNodes) { // Re-add foundNodes.AddOrUpdate(removedNode.Key, removedNode.Value); } _knownNodes.Clear(); } } /// /// Read node and send add or change notification /// /// /// /// /// /// /// private async ValueTask ReadNodeAsync(OpcUaSession session, NodeId targetNodeId, RelativePath targetPath, Dictionary foundNodes, CancellationToken ct) { try { var node = await session.ReadNodeAsync(targetNodeId, ct).ConfigureAwait(false); if (NodeId.IsNull(node.NodeId)) { return; } if (_knownNodes.Remove(node.NodeId, out var existing) && !Utils.IsEqual(existing.Item2, node)) { // send updated node _nodesChanged++; OnNodeChange?.Invoke(session, CreateChange(targetNodeId, existing.Item1, existing.Item2, node)); } if (foundNodes.TryAdd(node.NodeId, (targetPath, node)) && existing.Item1 == null) { // Send added node _nodesAdded++; OnNodeChange?.Invoke(session, CreateChange(targetNodeId, targetPath, null, node)); } } catch (Exception) when (session.Connected) { // TODO: Notify error here, but we are anyway sending a removal... _errors++; } } /// /// Helper to create a change structure /// /// /// /// /// /// /// private Change CreateChange(NodeId source, RelativePath path, T? existing, T? New) where T : class { return new(source, path, existing, New, Interlocked.Increment(ref _sequenceNumber), _client._timeProvider.GetUtcNow()); } /// /// Register /// /// /// /// /// public static Browser Register(OpcUaClient outer, TimeSpan rebrowsePeriod, string subscriptionId) { lock (outer._browsers) { if (!outer._browsers.TryGetValue((subscriptionId, rebrowsePeriod), out var browser)) { browser = new Browser(outer, subscriptionId, rebrowsePeriod); outer._browsers.Add((subscriptionId, rebrowsePeriod), browser); } browser.AddRef(); return browser; } } /// /// Take a reference on this browser /// private void AddRef() { _refCount++; _channel.Writer.TryWrite(false); // Ensure we start a rebrowse in 10 } /// /// Release browser and remove from browser list /// /// private bool Release() { var cleanup = false; lock (_client._browsers) { if (--_refCount == 0 && _client._browsers.Remove((_subscriptionId, _browseDelay))) { cleanup = true; } } return cleanup; } private const int kMaxSearchDepth = 128; private const int kMaxReferencesPerNode = 1000; private bool _disposed; private uint _sequenceNumber; private int _refCount; private int _referencesAdded; private int _referencesRemoved; private int _nodesAdded; private int _nodesChanged; private int _nodesRemoved; private int _errors; private Dictionary _knownNodes = []; private Dictionary _knownReferences = new(Compare.Using(Utils.IsEqual)); private readonly string _subscriptionId; private readonly Task _browser; private readonly OpcUaClient _client; private readonly ILogger _logger; private readonly Channel _channel; private readonly ITimer _rebrowseTimer; private readonly CancellationTokenSource _cts = new(); private readonly TimeSpan _browseDelay; } } /// /// Source-generated logging definitions for OpcUaClient.Browser /// internal static partial class OpcUaClientBrowserLogging { private const int EventClass = 500; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Debug, Message = "Starting continous browsing process...")] public static partial void BrowserStartingContinuousBrowsing(this ILogger logger); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Information, Message = "Browsing started after {Elapsed}...")] public static partial void BrowserBrowsingStarted(this ILogger logger, TimeSpan elapsed); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Information, Message = "Browsing completed and took {Elapsed}. Added {AddedR}, " + "removed {RemovedR} References and added {AddedN}, changed {ChangedN}, " + "removed {RemovedN} Nodes with {Errors} errors.")] public static partial void BrowserBrowsingCompleted(this ILogger logger, TimeSpan elapsed, int addedR, int removedR, int addedN, int changedN, int removedN, int errors); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Information, Message = "Browsing completed due to error {Error} took {Elapsed}. Added {AddedR}, " + "removed {RemovedR} References and added {AddedN}, changed {ChangedN}, " + "removed {RemovedN} Nodes with {Errors} errors.")] public static partial void BrowserBrowsingCompletedWithError(this ILogger logger, string error, TimeSpan elapsed, int addedR, int removedR, int addedN, int changedN, int removedN, int errors); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Debug, Message = "Not connected - waiting to reconnect.")] public static partial void BrowserNotConnectedWaiting(this ILogger logger); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Error, Message = "Error occurred during browsing")] public static partial void BrowserErrorOccurred(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Error, Message = "Browsing completed due to an exception and took {Elapsed}.")] public static partial void BrowserBrowsingException(this ILogger logger, Exception ex, TimeSpan elapsed); [LoggerMessage(EventId = EventClass + 8, Level = LogLevel.Information, Message = "Browser process exited.")] public static partial void BrowserProcessExited(this ILogger logger); [LoggerMessage(EventId = EventClass + 9, Level = LogLevel.Critical, Message = "Browser process exited due to unexpected exception.")] public static partial void BrowserProcessExitedUnexpected(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 10, Level = LogLevel.Debug, Message = "Stopping browse due to error.")] public static partial void BrowserStoppingDueToError(this ILogger logger, Exception ex); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaClient.Sampler.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Services { using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Opc.Ua; using System; using System.Collections.Immutable; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; internal sealed partial class OpcUaClient { /// /// Registers a value to read with results pushed to the provided /// subscription callback /// /// /// /// /// /// /// internal IAsyncDisposable Sample(TimeSpan samplingRate, TimeSpan maxAge, ReadValueId nodeToRead, string subscriptionName, uint clientHandle) { return Sampler.Register(this, samplingRate, maxAge, nodeToRead, subscriptionName, clientHandle); } /// /// A set of client sampled values /// private sealed class Sampler : IAsyncDisposable { /// /// Creates the sampler /// /// /// /// /// /// private Sampler(OpcUaClient outer, TimeSpan samplingRate, TimeSpan maxAge, string subscription, SampledNodeId value) { _sampledNodes = ImmutableHashSet.Empty.Add(value); _client = outer; _cts = new CancellationTokenSource(); _samplingRate = samplingRate; _maxAge = maxAge; _subscription = subscription; _timer = new PeriodicTimer(_samplingRate); _sampler = RunAsync(_cts.Token); } /// public async ValueTask DisposeAsync() { try { await _cts.CancelAsync().ConfigureAwait(false); _timer.Dispose(); await _sampler.ConfigureAwait(false); } catch (OperationCanceledException) { } finally { _cts.Dispose(); } } /// /// Add sampler /// /// /// private Sampler Add(SampledNodeId node) { _sampledNodes = _sampledNodes.Add(node); return this; } /// /// Remove sampler /// /// /// private bool Remove(SampledNodeId value) { _sampledNodes = _sampledNodes.Remove(value); return _sampledNodes.Count == 0; } /// /// Run sampling of values on the periodic timer /// /// /// private async Task RunAsync(CancellationToken ct) { var sw = Stopwatch.StartNew(); for (var sequenceNumber = 1u; !ct.IsCancellationRequested; sequenceNumber++) { if (sequenceNumber == 0u) { continue; } var nodesToRead = new ReadValueIdCollection(_sampledNodes.Select(n => n.InitialValue)); try { // Wait until period completed if (!await _timer.WaitForNextTickAsync(ct).ConfigureAwait(false)) { continue; } sw.Restart(); // Grab the current session var session = _client._session; if (session == null) { NotifyAll(sequenceNumber, nodesToRead, StatusCodes.BadNotConnected, TimeSpan.Zero); continue; } // Ensure type system is loaded await session.GetComplexTypeSystemAsync(ct).ConfigureAwait(false); // Perform the read. var timeout = _samplingRate.TotalMilliseconds / 2; var response = await session.ReadAsync(new RequestHeader { Timestamp = _client._timeProvider.GetUtcNow().UtcDateTime, TimeoutHint = (uint)timeout, ReturnDiagnostics = 0 }, _maxAge.TotalMilliseconds, Opc.Ua.TimestampsToReturn.Both, nodesToRead, ct).ConfigureAwait(false); var values = response.Validate(response.Results, r => r.StatusCode, response.DiagnosticInfos, nodesToRead); if (values.ErrorInfo != null) { NotifyAll(sequenceNumber, nodesToRead, values.ErrorInfo.StatusCode, sw.Elapsed); continue; } // Notify clients of the values NotifyAll(sequenceNumber, values, sw.Elapsed); } catch (OperationCanceledException) { } catch (ServiceResultException sre) { NotifyAll(sequenceNumber, nodesToRead, sre.StatusCode, sw.Elapsed); } catch (Exception ex) { var error = new ServiceResult(ex).StatusCode; NotifyAll(sequenceNumber, nodesToRead, error.Code, sw.Elapsed); } } } /// /// Notify results /// /// /// /// private void NotifyAll(uint seq, ServiceResponse values, TimeSpan elapsed) { if (_client._session?.Subscriptions.FirstOrDefault(n => n.DisplayName == _subscription) is not OpcUaSubscription target) { return; } var missed = GetMissed(elapsed); target.OnSubscriptionCylicReadNotification(target, values .Select(i => new SampledDataValueModel( SetOverflow(i.Result, missed > 0), ((SampledNodeId)i.Request.Handle).ClientHandle, missed)) .ToList(), seq, _client._timeProvider.GetUtcNow().UtcDateTime); static DataValue SetOverflow(DataValue result, bool overflowBit) { result.StatusCode.SetOverflow(overflowBit); return result; } } /// /// Notify error status code /// /// /// /// /// private void NotifyAll(uint seq, ReadValueIdCollection nodesToRead, uint statusCode, TimeSpan elapsed) { if (_client._session?.Subscriptions.FirstOrDefault(n => n.DisplayName == _subscription) is not OpcUaSubscription target) { return; } var missed = GetMissed(elapsed); target.OnSubscriptionCylicReadNotification(target, nodesToRead .Select(i => new SampledDataValueModel( SetOverflow(statusCode, missed > 0), ((SampledNodeId)i.Handle).ClientHandle, missed)) .ToList(), seq, _client._timeProvider.GetUtcNow().UtcDateTime); static DataValue SetOverflow(uint statusCode, bool overflowBit) { var dataValue = new DataValue(statusCode); dataValue.StatusCode.SetOverflow(overflowBit); return dataValue; } } private int GetMissed(TimeSpan elapsed) { return (int)Math.Round(elapsed.TotalMilliseconds / _samplingRate.TotalMilliseconds); } /// /// A sampled node registered with a sampler /// private sealed class SampledNodeId : IAsyncDisposable { /// /// Sampler key /// public (string, TimeSpan, TimeSpan) Key { get; } /// /// Item to monito /// public ReadValueId InitialValue { get; } /// /// Client handle /// public uint ClientHandle { get; } /// /// Create node /// /// /// /// /// public SampledNodeId(OpcUaClient outer, (string, TimeSpan, TimeSpan) key, ReadValueId item, uint clientHandle) { _outer = outer; Key = key; InitialValue = item; ClientHandle = clientHandle; item.Handle = this; } /// public async ValueTask DisposeAsync() { Sampler? sampler; lock (_outer._samplers) { if (!_outer._samplers.TryGetValue(Key, out sampler) || !sampler.Remove(this)) { return; } _outer._samplers.Remove(Key); } await sampler.DisposeAsync().ConfigureAwait(false); } private readonly OpcUaClient _outer; } /// /// Register for sampling /// /// /// /// /// /// /// /// public static IAsyncDisposable Register(OpcUaClient outer, TimeSpan samplingRate, TimeSpan maxAge, ReadValueId item, string subscriptionName, uint clientHandle) { if (samplingRate <= TimeSpan.Zero) { samplingRate = TimeSpan.FromSeconds(1); } if (maxAge < TimeSpan.Zero) { maxAge = TimeSpan.Zero; } lock (outer._samplers) { var key = (subscriptionName, samplingRate, maxAge); #pragma warning disable CA2000 // Dispose objects before losing scope var sampledNode = new SampledNodeId(outer, key, item, clientHandle); #pragma warning restore CA2000 // Dispose objects before losing scope if (!outer._samplers.TryGetValue(key, out var sampler)) { sampler = new Sampler(outer, samplingRate, maxAge, subscriptionName, sampledNode); outer._samplers.Add(key, sampler); } else { sampler.Add(sampledNode); } return sampledNode; } } private ImmutableHashSet _sampledNodes; private readonly CancellationTokenSource _cts; private readonly Task _sampler; private readonly OpcUaClient _client; private readonly TimeSpan _samplingRate; private readonly TimeSpan _maxAge; private readonly string _subscription; private readonly PeriodicTimer _timer; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaClient.Subscription.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Services { using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Opc.Ua; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; using System.Threading.Tasks; internal sealed partial class OpcUaClient { /// /// Register a new subscriber for a subscription defined by the /// subscription template. /// /// /// /// internal async ValueTask RegisterAsync( SubscriptionModel subscription, ISubscriber subscriber, CancellationToken ct = default) { // Take a reference to the client for the lifetime of the subscription AddRef(); try { await _subscriptionLock.WaitAsync(ct).ConfigureAwait(false); AddRef(); try { OpcUaSubscription? existingSub = null; // // If subscriber is registered with a different subscription we either // update the subscription or dispose the old one and create a new one. // if (_registrations.TryGetValue(subscriber, out var existing) && existing.Subscription != subscription) { existing.RemoveAndReleaseNoLockInternal(); Debug.Assert(!_registrations.ContainsKey(subscriber)); // // We check if there are any other subscribers registered with the // same subscription configuration that we want to apply. If there // are not - we update the subscription (safely) with the new // desired template configuration. Essentially original behavior // before 2.9.12. // if ((!_s2r.TryGetValue(subscription, out var c) || c.Count == 0) && TryGetSubscription(existing.Subscription, out existingSub)) { existingSub.Update(subscription); } } var registration = new Registration(this, subscription, subscriber); TriggerSubscriptionSynchronization(existingSub); return registration; } finally { Release(); _subscriptionLock.Release(); } } finally { Release(); } } /// /// Get subscribers for a subscription template to get at the monitored /// items that should be created in the subscription or subscriptions. /// Called under the subscription lock as a result of synchronization. /// /// /// internal IEnumerable GetSubscribers(SubscriptionModel template) { Debug.Assert(_subscriptionLock.CurrentCount == 0, "Must be locked"); if (_s2r.TryGetValue(template, out var registrations)) { return registrations.Select(r => r.Owner); } return []; } /// /// Trigger the client to manage the subscription. This is a /// no op if the subscription is not registered or the client /// is not connected. /// /// internal void TriggerSubscriptionSynchronization( OpcUaSubscription? subscription = null) { if (subscription?.IsClosed == false) { TriggerConnectionEvent(ConnectionEvent.SubscriptionSyncOne, subscription); } else { TriggerConnectionEvent(ConnectionEvent.SubscriptionSyncAll); } } /// /// Called by subscription when newly created. This needs to be done /// here this way because the stack uses clone to clone the subscriptions /// just like it does with sessions and monitored items. This way we can /// hock the create and clone operations. /// /// internal void OnSubscriptionCreated(OpcUaSubscription subscription) { lock (_cache) { if (subscription.IsRoot) { _cache.AddOrUpdate(subscription.Template, subscription); } } } /// /// Called by subscription when closed or deleted. /// /// internal void OnSubscriptionClosed(OpcUaSubscription subscription) { // Remove all subscriptions from cache lock (_cache) { if (subscription.IsRoot) { _cache.Remove(subscription.Template); } } } /// /// Called when session is closed to remove all subscriptions /// /// internal void OnSessionClosing(OpcUaSession session) { // Remove all subscriptions from cache lock (_cache) { foreach (var subscription in session.SubscriptionHandles.Values .Where(s => s.IsRoot && !s.IsClosed)) { _cache.Remove(subscription.Template); } } } /// /// Try get subscription with subscription model /// /// /// /// private bool TryGetSubscription(SubscriptionModel template, [NotNullWhen(true)] out OpcUaSubscription? subscription) { // Fast lookup lock (_cache) { if (_cache.TryGetValue(template, out subscription)) { if (!subscription.IsClosed && subscription.IsRoot) { return true; } _cache.Remove(template); } subscription = _session?.SubscriptionHandles.Values .FirstOrDefault(s => s.IsRoot && s.Template == template); if (subscription != null) { _cache.AddOrUpdate(template, subscription); return true; } return false; } } /// /// Access to the subscription to sync state must go through the /// subscription lock. This just wraps the sync call on the /// subscription. /// /// /// /// internal async Task SyncAsync(OpcUaSubscription subscription, CancellationToken ct = default) { var session = _session; if (session == null) { return; } await _subscriptionLock.WaitAsync(ct).ConfigureAwait(false); try { // Get the max item per subscription as well as max var caps = await session.GetServerCapabilitiesAsync( NamespaceFormat.Uri, ct).ConfigureAwait(false); await subscription.SyncAsync(caps.MaxMonitoredItemsPerSubscription, caps.OperationLimits, ct).ConfigureAwait(false); } catch (Exception ex) { _logger.SyncSubscriptionError(ex, this, subscription); RescheduleSynchronization(TimeSpan.FromMinutes(1)); } finally { _subscriptionLock.Release(); } } /// /// Called by the management thread to synchronize the subscriptions /// within a session as a result of the trigger call or when a session /// is reconnected/recreated. /// /// /// internal async Task TrySyncAsync(CancellationToken ct = default) { var session = _session; if (session == null) { return false; } var sw = Stopwatch.StartNew(); var removals = 0; var additions = 0; var updates = 0; var existing = session.SubscriptionHandles .Where(s => s.Value.IsRoot) .ToDictionary(k => k.Value.Template, k => k.Value); _logger.PerformSync(this, session.SubscriptionHandles.Count); if (!await EnsureSessionIsReadyForSubscriptionsAsync(session, ct).ConfigureAwait(false)) { return false; } try { // Get the max item per subscription as well as max var caps = await session.GetServerCapabilitiesAsync( NamespaceFormat.Uri, ct).ConfigureAwait(false); var maxMonitoredItems = caps.MaxMonitoredItemsPerSubscription; var limits = caps.OperationLimits; var delay = TimeSpan.MaxValue; // // Take the subscription lock here! - we hold it all the way until we // have updated all subscription states. The subscriptions will access // the client again to obtain the monitored items from the subscribers // and we do not want any subscribers to be touched or removed while // we process the current registrations. Since the call to get the items // is frequent, we do not want to generate a copy every time but let // the subscriptions access the items directly. // await _subscriptionLock.WaitAsync(ct).ConfigureAwait(false); try { var s2r = _s2r.ToDictionary(kv => kv.Key, kv => kv.Value.ToList()); // Close and remove items that have no subscribers await Task.WhenAll(existing.Keys .Except(s2r.Keys) .Select(k => existing[k]) .Select(async close => { try { lock (_cache) { _cache.Remove(close.Template); } if (_s2r.TryRemove(close.Template, out var r)) { Debug.Assert(r.Count == 0, $"count of registrations {r.Count} > 0"); } // Removes the item from the session and dispose await close.DisposeAsync().ConfigureAwait(false); Interlocked.Increment(ref removals); Debug.Assert(close.IsClosed); Debug.Assert(close.Session == null); } catch (OperationCanceledException) { } catch (Exception ex) { _logger.CloseSubscriptionFailed(ex, this, close); } })).ConfigureAwait(false); // Add new subscription for items with subscribers var delays = await Task.WhenAll(s2r.Keys .Except(existing.Keys) .Select(async add => { try { // // Create a new subscription with the subscription // configuration template that as of yet has no // representation and add it to the session. // #pragma warning disable CA2000 // Dispose objects before losing scope var subscription = new OpcUaSubscription(this, add, _subscriptionOptions, _loggerFactory, new OpcUaClientTagList(_connection, _metrics), null, _timeProvider); #pragma warning restore CA2000 // Dispose objects before losing scope // Add the subscription to the session session.AddSubscription(subscription); // Sync the subscription which will get it to go live. await subscription.SyncAsync(maxMonitoredItems, caps.OperationLimits, ct).ConfigureAwait(false); Interlocked.Increment(ref additions); Debug.Assert(session == subscription.Session); s2r[add].ForEach(r => r.Dirty = false); return TimeSpan.MaxValue; } catch (OperationCanceledException) { return TimeSpan.MaxValue; } catch (Exception ex) { _logger.AddSubscriptionFailed(ex, this, add); return TimeSpan.FromMinutes(1); } })).ConfigureAwait(false); delay = delays.DefaultIfEmpty(TimeSpan.MaxValue).Min(); // Update any items where subscriber signalled the item was updated delays = await Task.WhenAll(s2r.Keys.Intersect(existing.Keys) .Where(u => s2r[u].Any(b => b.Dirty)) .Select(async update => { try { var subscription = existing[update]; await subscription.SyncAsync(maxMonitoredItems, caps.OperationLimits, ct).ConfigureAwait(false); Interlocked.Increment(ref updates); Debug.Assert(session == subscription.Session); s2r[update].ForEach(r => r.Dirty = false); return TimeSpan.MaxValue; } catch (OperationCanceledException) { return TimeSpan.MaxValue; } catch (Exception ex) { _logger.UpdateSubscriptionFailed(ex, this, update); return TimeSpan.FromMinutes(1); } })).ConfigureAwait(false); var delay2 = delays.DefaultIfEmpty(TimeSpan.MaxValue).Min(); RescheduleSynchronization(delay < delay2 ? delay : delay2); } catch (Exception ex) { _logger.SyncSubscriptionsError(ex, this); var delay2 = TimeSpan.FromMinutes(1); RescheduleSynchronization(delay < delay2 ? delay : delay2); } finally { _subscriptionLock.Release(); } // Finish session.UpdateOperationTimeout(false); UpdatePublishRequestCounts(); if (updates + removals + additions != 0) { _logger.SyncSummary(this, removals, additions, updates, session.SubscriptionHandles.Count, sw.ElapsedMilliseconds); } return true; } catch (Exception ex) { _logger.SyncSubscriptionsErrorMessage(this, ex.Message); return false; } } /// /// Check session is ready for subscriptions, which means we fetch the /// namespace table and type system needed for the encoders and metadata. /// /// /// /// private async Task EnsureSessionIsReadyForSubscriptionsAsync(OpcUaSession session, CancellationToken ct) { try { // Reload namespace tables should they have changed... var oldTable = session.NamespaceUris.ToArray(); await session.FetchNamespaceTablesAsync(ct).ConfigureAwait(false); var newTable = session.NamespaceUris.ToArray(); LogNamespaceTableChanges(oldTable, newTable); } catch (ServiceResultException sre) // anything else is not expected { _logger.FetchNamespaceTableFailed(sre, this); return false; } if (!DisableComplexTypeLoading && !session.IsTypeSystemLoaded) { // Ensure type system is loaded await session.GetComplexTypeSystemAsync(ct).ConfigureAwait(false); } return true; } /// /// Called under lock, schedule resynchronization of all subscriptions /// after the specified delay /// /// private void RescheduleSynchronization(TimeSpan delay) { Debug.Assert(_subscriptionLock.CurrentCount == 0, "Must be locked"); if (delay == TimeSpan.MaxValue || delay < TimeSpan.Zero) { // covers Timeout.Infinite too which is negative return; } var nextSync = _timeProvider.GetUtcNow() + delay; if (_nextSync == null || nextSync <= _nextSync) { _logger.RescheduleSync(nextSync, delay.TotalMilliseconds); _nextSync = nextSync; _resyncTimer.Change(delay, Timeout.InfiniteTimeSpan); } } /// /// Subscription registration /// private sealed record Registration : ISubscription, ISubscriptionDiagnostics { /// /// The subscription configuration /// public SubscriptionModel Subscription { get; } /// /// Monitored items on the subscriber /// internal ISubscriber Owner { get; } /// /// Mark the registration as dirty /// internal bool Dirty { get; set; } /// public IOpcUaClientDiagnostics ClientDiagnostics => _outer; /// public ISubscriptionDiagnostics Diagnostics => this; /// public int GoodMonitoredItems => _outer.TryGetSubscription(Subscription, out var subscription) ? subscription.GetGoodMonitoredItems(Owner) : 0; /// public int BadMonitoredItems => _outer.TryGetSubscription(Subscription, out var subscription) ? subscription.GetBadMonitoredItems(Owner) : 0; /// public int LateMonitoredItems => _outer.TryGetSubscription(Subscription, out var subscription) ? subscription.GetLateMonitoredItems(Owner) : 0; /// public int HeartbeatsEnabled => _outer.TryGetSubscription(Subscription, out var subscription) ? subscription.GetHeartbeatsEnabled(Owner) : 0; /// public int ConditionsEnabled => _outer.TryGetSubscription(Subscription, out var subscription) ? subscription.GetConditionsEnabled(Owner) : 0; /// /// Create subscription /// /// /// /// public Registration(OpcUaClient outer, SubscriptionModel subscription, ISubscriber owner) { Subscription = subscription; Owner = owner; _outer = outer; _outer.AddRef(); AddNoLockInternal(); } /// public async ValueTask DisposeAsync() { if (_outer._disposed) { // // Possibly the client has shut down before the owners of // the registration have disposed it. This is not an error. // It might however be better to order the clients to get // disposed before clients. // return; } // Remove registration await _outer._subscriptionLock.WaitAsync().ConfigureAwait(false); try { RemoveNoLockInternal(); _outer.TriggerSubscriptionSynchronization(null); } finally { _outer._subscriptionLock.Release(); _outer.Release(); } } /// public OpcUaSubscriptionNotification? CreateKeepAlive() { if (!_outer.TryGetSubscription(Subscription, out var subscription)) { return null; } return subscription.CreateKeepAlive(); } /// public void NotifyMonitoredItemsChanged() { Dirty = true; _outer.TryGetSubscription(Subscription, out var subscription); _outer.TriggerSubscriptionSynchronization(subscription); } /// public async ValueTask CollectMetaDataAsync( ISubscriber owner, DataSetFieldContentFlags? fieldMask, DataSetMetaDataModel dataSetMetaData, uint minorVersion, CancellationToken ct = default) { if (!_outer.TryGetSubscription(Subscription, out var subscription)) { throw new ServiceResultException(StatusCodes.BadNoSubscription, "Subscription not found"); } return await subscription.CollectMetaDataAsync(owner, fieldMask, dataSetMetaData, minorVersion, ct).ConfigureAwait(false); } /// /// Remove registration and release reference but not under /// lock (like user of the registration handle) and without /// triggering an update. /// internal void RemoveAndReleaseNoLockInternal() { RemoveNoLockInternal(); _outer.Release(); } private void AddNoLockInternal() { _outer._registrations.Add(Owner, this); _outer._s2r.AddOrUpdate(Subscription, _ => [this], (_, c) => { c.Add(this); return c; }); } private void RemoveNoLockInternal() { _outer._s2r.AddOrUpdate(Subscription, _ => { Debug.Fail("Unexpected"); return []; }, (_, c) => { c.Remove(this); return c; }); _outer._registrations.Remove(Owner); } private readonly OpcUaClient _outer; } private DateTimeOffset? _nextSync; #pragma warning disable CA2213 // Disposable fields should be disposed private readonly SemaphoreSlim _subscriptionLock = new(1, 1); private readonly ITimer _resyncTimer; #pragma warning restore CA2213 // Disposable fields should be disposed private readonly Dictionary _registrations = []; private readonly ConcurrentDictionary> _s2r = new(); private readonly Dictionary _cache = []; private readonly IOptions _subscriptionOptions; } /// /// Source-generated logging definitions for OpcUaClient.Subscription /// internal static partial class OpcUaClientSubscriptionLogging { private const int EventClass = 580; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Error, Message = "{Client}: Error trying to sync subscription {Subscription}")] public static partial void SyncSubscriptionError(this ILogger logger, Exception ex, OpcUaClient client, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Debug, Message = "{Client}: Perform synchronization of subscriptions (total: {Total})")] public static partial void PerformSync(this ILogger logger, OpcUaClient client, int total); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Error, Message = "{Client}: Failed to close subscription {Subscription} in session.")] public static partial void CloseSubscriptionFailed(this ILogger logger, Exception ex, OpcUaClient client, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Error, Message = "{Client}: Failed to add subscription {Subscription} in session.")] public static partial void AddSubscriptionFailed(this ILogger logger, Exception ex, OpcUaClient client, SubscriptionModel subscription); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Error, Message = "{Client}: Failed to update subscription {Subscription} in session.")] public static partial void UpdateSubscriptionFailed(this ILogger logger, Exception ex, OpcUaClient client, SubscriptionModel subscription); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Error, Message = "{Client}: Error trying to sync subscriptions.")] public static partial void SyncSubscriptionsError(this ILogger logger, Exception ex, OpcUaClient client); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Information, Message = "{Client}: Removed {Removals}, added {Additions}, and updated {Updates} " + "subscriptions (total: {Total}) took {Duration} ms.")] public static partial void SyncSummary(this ILogger logger, OpcUaClient client, int removals, int additions, int updates, int total, long duration); [LoggerMessage(EventId = EventClass + 8, Level = LogLevel.Error, Message = "{Client}: Error trying to sync subscriptions: {Error}")] public static partial void SyncSubscriptionsErrorMessage(this ILogger logger, OpcUaClient client, string error); [LoggerMessage(EventId = EventClass + 9, Level = LogLevel.Warning, Message = "{Client}: Failed to fetch namespace table...")] public static partial void FetchNamespaceTableFailed(this ILogger logger, Exception ex, OpcUaClient client); [LoggerMessage(EventId = EventClass + 10, Level = LogLevel.Information, Message = "Reschedule synchronization to {Time} in {Delay} ms")] public static partial void RescheduleSync(this ILogger logger, DateTimeOffset time, double delay); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaClient.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Services { using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Exceptions; using Furly.Extensions.Serializers; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Nito.AsyncEx; using Opc.Ua; using Opc.Ua.Bindings; using Opc.Ua.Client; using Opc.Ua.Extensions; using System; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.Metrics; using System.Globalization; using System.Linq; using System.Net; using System.Runtime.CompilerServices; using System.Security.Cryptography.X509Certificates; using System.Text.Json; using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; using System.Xml; /// /// OPC UA Client based on official ua client reference sample. /// internal sealed partial class OpcUaClient : DefaultSessionFactory, IOpcUaClientDiagnostics, IDisposable { /// /// Client namespace /// internal const string Namespace = "http://opcfoundation.org/UA/Client/Types.xsd"; /// /// Application uri or the client /// public string ApplicationUri => _configuration.ApplicationUri; /// /// The session keepalive interval to be used in ms. /// public TimeSpan? KeepAliveInterval { get; set; } /// /// Min time to wait until reconnect. /// public TimeSpan? MinReconnectDelay { get; set; } /// /// Timeout for session creation /// public TimeSpan? CreateSessionTimeout { get; set; } /// /// The session lifetime. /// public TimeSpan? SessionTimeout { get; set; } /// /// Session operation timeout /// public TimeSpan? OperationTimeout { get; set; } /// /// Service call timeout /// public TimeSpan? ServiceCallTimeout { get; set; } /// /// Connect timeout for service calls /// public TimeSpan? ConnectTimeout { get; set; } /// /// Minimum number of publish requests to queue /// public int? MinPublishRequests { get; set; } /// /// Max number of publish requests to ever queue /// public int? MaxPublishRequests { get; set; } /// /// Percentage ratio of publish requests per subscription /// public int? PublishRequestsPerSubscriptionPercent { get; set; } /// /// The linger timeout. /// public TimeSpan? LingerTimeout { get; set; } /// /// Disable complex type preloading. /// public bool DisableComplexTypePreloading { get; set; } /// /// Node cache timeout /// public TimeSpan NodeCacheTimeout { get; set; } = TimeSpan.FromMinutes(1); /// /// Node cache capacity /// public int NodeCacheCapacity { get; set; } = 4096; /// /// Operation limits to use in the sessions /// internal OperationLimits? LimitOverrides { get; set; } /// /// Last diagnostic information on this client /// internal ChannelDiagnosticModel LastDiagnostics => _lastDiagnostics; /// /// No complex type loading ever /// public bool DisableComplexTypeLoading => _connection.Options.HasFlag(ConnectionOptions.NoComplexTypeSystem); /// /// Transfer subscription on reconnect /// public bool DisableTransferSubscriptionOnReconnect => _connection.Options.HasFlag(ConnectionOptions.NoSubscriptionTransfer); /// /// Dump diagnostics for this client /// public bool DumpDiagnostics => _connection.Options.HasFlag(ConnectionOptions.DumpDiagnostics); /// /// Client is connected /// public bool IsConnected => _session?.Connected ?? false; /// public EndpointConnectivityState State => _lastState; /// public int BadPublishRequestCount => _session?.DefunctRequestCount ?? 0; /// public int GoodPublishRequestCount => _session?.GoodPublishRequestCount ?? 0; /// public int OutstandingRequestCount => _session?.OutstandingRequestCount ?? 0; /// public int SubscriptionCount => _session?.Subscriptions.Count(s => s.Created) ?? 0; /// public int MinPublishRequestCount => _session?.MinPublishRequestCount ?? 0; /// public int ReconnectCount => _numberOfConnectionRetries; /// public int ConnectCount => _numberofSuccessfulConnections; /// public int KeepAliveCounter => _keepAliveCounter; /// public int KeepAliveTotal => _keepAliveTotal; /// public bool ReconnectTriggered => _reconnectRequired != 0; /// /// Disconnected state /// internal static IOpcUaClientDiagnostics Disconnected { get; } = new DisconnectState(); /// /// Create client /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// public OpcUaClient(ApplicationConfiguration configuration, ConnectionIdentifier connection, IJsonSerializer serializer, ILoggerFactory loggerFactory, TimeProvider timeProvider, IMetricsContext metrics, Func onClose, EventHandler? notifier, ReverseConnectManager? reverseConnectManager, Action diagnosticsCallback, IOptions options, IOptions subscriptionOptions, string? sessionName = null) { _timeProvider = timeProvider; if (connection?.Connection?.Endpoint?.Url == null) { throw new ArgumentNullException(nameof(connection)); } _options = options; _onClose = onClose; _subscriptionOptions = subscriptionOptions; _connection = connection.Connection; _diagnosticsCb = diagnosticsCallback; _lastDiagnostics = new ChannelDiagnosticModel { Connection = _connection, TimeStamp = _timeProvider.GetUtcNow() }; Debug.Assert(_connection.GetEndpointUrls().Any()); _reverseConnectManager = reverseConnectManager; _metrics = metrics ?? throw new ArgumentNullException(nameof(metrics)); _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); _serializer = serializer ?? throw new ArgumentNullException(nameof(serializer)); _loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); _notifier = notifier; InitializeMetrics(); _logger = _loggerFactory.CreateLogger(); _tokens = []; _lastState = EndpointConnectivityState.Disconnected; _sessionName = sessionName ?? connection.ToString(); OperationTimeout = _options.Value.Quotas.OperationTimeout == 0 ? null : TimeSpan.FromMilliseconds(_options.Value.Quotas.OperationTimeout); NodeCacheTimeout = _options.Value.NodeCacheTimeout ?? TimeSpan.FromMinutes(1); NodeCacheCapacity = _options.Value.NodeCacheCapacity ?? 4096; DisableComplexTypePreloading = _options.Value.DisableComplexTypePreloading ?? false; MinReconnectDelay = _options.Value.MinReconnectDelayDuration; CreateSessionTimeout = _options.Value.CreateSessionTimeoutDuration; KeepAliveInterval = _options.Value.KeepAliveIntervalDuration; ServiceCallTimeout = _options.Value.DefaultServiceCallTimeoutDuration; ConnectTimeout = _options.Value.DefaultConnectTimeoutDuration; SessionTimeout = _options.Value.DefaultSessionTimeoutDuration; LingerTimeout = _options.Value.LingerTimeoutDuration; LimitOverrides = new OperationLimits { MaxNodesPerRead = (uint)(_options.Value.MaxNodesPerReadOverride ?? 0), MaxNodesPerBrowse = (uint)(_options.Value.MaxNodesPerBrowseOverride ?? 0) // ... }; MinPublishRequests = _options.Value.MinPublishRequests; MaxPublishRequests = _options.Value.MaxPublishRequests; PublishRequestsPerSubscriptionPercent = _options.Value.PublishRequestsPerSubscriptionPercent; _maxReconnectPeriod = options.Value.MaxReconnectDelayDuration ?? TimeSpan.Zero; if (_maxReconnectPeriod == TimeSpan.Zero) { _maxReconnectPeriod = TimeSpan.FromSeconds(30); } _reconnectHandler = new SessionReconnectHandler(true, (int)_maxReconnectPeriod.TotalMilliseconds); _cts = new CancellationTokenSource(); _channel = Channel.CreateUnbounded<(ConnectionEvent, object?)>(); _disconnectLock = _lock.WriterLock(_cts.Token); _channelMonitor = _timeProvider.CreateTimer(_ => OnUpdateConnectionDiagnostics(), null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); _resyncTimer = _timeProvider.CreateTimer(_ => TriggerSubscriptionSynchronization(), null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); _diagnosticsDumper = !DumpDiagnostics ? null : DumpDiagnosticsPeriodicallyAsync(_cts.Token); _sessionManager = ManageSessionStateMachineAsync(_cts.Token); } /// public void Dispose() { Release(); } /// public override string? ToString() { return $"{_sessionName} [state:{_lastState}|refs:{_refCount}]"; } /// public override async Task RecreateAsync(ISession sessionTemplate, ITransportWaitingConnection connection, CancellationToken ct) { // // We do not support recreation of sessions create a new session from scratch. // Then we add the desired subscriptions to the new session. // if (connection != null) { _logger.CreatingNewSessionWithConnection(this); return await CreateAsync(_configuration, connection, sessionTemplate.ConfiguredEndpoint, true, false, _sessionName, (uint)sessionTemplate.SessionTimeout, sessionTemplate.Identity, sessionTemplate.PreferredLocales, ct).ConfigureAwait(false); } _logger.CreatingNewSessionWithoutConnection(this); return await CreateAsync(_configuration, _reverseConnectManager, sessionTemplate.ConfiguredEndpoint, true, false, _sessionName, (uint)sessionTemplate.SessionTimeout, sessionTemplate.Identity, sessionTemplate.PreferredLocales, ct).ConfigureAwait(false); } /// public override async Task RecreateAsync(ISession sessionTemplate, ITransportChannel? transportChannel, CancellationToken ct) { // // We do not support recreation of sessions therefore we close // and reopen the transport channel as a regular creation operation. // Then we add the desired subscriptions to the new session // if (transportChannel != null) { _logger.CreatingNewSessionClosingChannel(this); transportChannel.Dispose(); } else { _logger.CreatingNewSession(this); } return await CreateAsync(_configuration, sessionTemplate.ConfiguredEndpoint, true, false, _sessionName, (uint)sessionTemplate.SessionTimeout, sessionTemplate.Identity, sessionTemplate.PreferredLocales, ct).ConfigureAwait(false); } /// public override Session Create(ISessionChannel channel, ApplicationConfiguration configuration, ConfiguredEndpoint endpoint) { return new OpcUaSession(this, _serializer, _loggerFactory.CreateLogger(), _timeProvider, (ITransportChannel)channel, configuration, endpoint); } /// public override Session Create(ITransportChannel channel, ApplicationConfiguration configuration, ConfiguredEndpoint endpoint, X509Certificate2? clientCertificate, EndpointDescriptionCollection? availableEndpoints, StringCollection? discoveryProfileUris) { return new OpcUaSession(this, _serializer, _loggerFactory.CreateLogger(), _timeProvider, channel, configuration, endpoint, clientCertificate, availableEndpoints, discoveryProfileUris); } /// public override Task CreateAsync(ApplicationConfiguration configuration, ConfiguredEndpoint endpoint, bool updateBeforeConnect, string sessionName, uint sessionTimeout, IUserIdentity identity, IList preferredLocales, CancellationToken ct) { return CreateAsync(configuration, endpoint, updateBeforeConnect, false, sessionName, sessionTimeout, identity, preferredLocales, ct); } /// public async override Task CreateAsync(ApplicationConfiguration configuration, ConfiguredEndpoint endpoint, bool updateBeforeConnect, bool checkDomain, string sessionName, uint sessionTimeout, IUserIdentity identity, IList preferredLocales, CancellationToken ct) { return await Session.CreateAsync(this, configuration, (ITransportWaitingConnection?)null, endpoint, updateBeforeConnect, checkDomain, sessionName, sessionTimeout, identity, preferredLocales, ct).ConfigureAwait(false); } /// public async override Task CreateAsync(ApplicationConfiguration configuration, ITransportWaitingConnection connection, ConfiguredEndpoint endpoint, bool updateBeforeConnect, bool checkDomain, string sessionName, uint sessionTimeout, IUserIdentity identity, IList preferredLocales, CancellationToken ct) { return await Session.CreateAsync(this, configuration, connection, endpoint, updateBeforeConnect, checkDomain, sessionName, sessionTimeout, identity, preferredLocales, ct).ConfigureAwait(false); } /// public async override Task CreateAsync(ApplicationConfiguration configuration, ReverseConnectManager? reverseConnectManager, ConfiguredEndpoint endpoint, bool updateBeforeConnect, bool checkDomain, string sessionName, uint sessionTimeout, IUserIdentity userIdentity, IList preferredLocales, CancellationToken ct) { if (reverseConnectManager == null) { return await CreateAsync(configuration, endpoint, updateBeforeConnect, checkDomain, sessionName, sessionTimeout, userIdentity, preferredLocales, ct).ConfigureAwait(false); } ITransportWaitingConnection? connection; do { connection = await reverseConnectManager.WaitForConnectionAsync(endpoint.EndpointUrl, endpoint.ReverseConnect?.ServerUri, ct).ConfigureAwait(false); if (updateBeforeConnect) { await endpoint.UpdateFromServerAsync(endpoint.EndpointUrl, connection, endpoint.Description.SecurityMode, endpoint.Description.SecurityPolicyUri, ct).ConfigureAwait(false); updateBeforeConnect = false; connection = null; } } while (connection == null); return await CreateAsync(configuration, connection, endpoint, false, checkDomain, sessionName, sessionTimeout, userIdentity, preferredLocales, ct).ConfigureAwait(false); } /// /// Reset the client /// /// /// internal async Task ResetAsync(CancellationToken ct) { ObjectDisposedException.ThrowIf(_disposed, this); var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); try { await using var registration = ct.Register(() => tcs.TrySetCanceled()).ConfigureAwait(false); _logger.Resetting(this); TriggerConnectionEvent(ConnectionEvent.Reset, tcs); } catch (Exception ex) { _logger.ResetFailed(ex, this); tcs.TrySetException(ex); } await tcs.Task.ConfigureAwait(false); } /// /// Get session diagnostics /// /// /// internal async Task GetSessionDiagnosticsAsync( CancellationToken ct = default) { if (_session?.Connected == true) { return await _session.GetServerDiagnosticAsync(ct).ConfigureAwait(false); } return null; } /// /// Close client /// /// /// internal async ValueTask CloseAsync(bool shutdown = false) { ObjectDisposedException.ThrowIf(_disposed, this); try { _disposed = true; _logger.Closing(this); await _cts.CancelAsync().ConfigureAwait(false); await _sessionManager.ConfigureAwait(false); _reconnectHandler.Dispose(); foreach (var sampler in _samplers.Values) { await sampler.DisposeAsync().ConfigureAwait(false); } _samplers.Clear(); foreach (var browser in _browsers.Values) { await browser.DisposeAsync().ConfigureAwait(false); } _browsers.Clear(); await CloseSessionAsync(shutdown).ConfigureAwait(false); _lastState = EndpointConnectivityState.Disconnected; if (_diagnosticsDumper != null) { await _diagnosticsDumper.ConfigureAwait(false); } _logger.ClosedSuccessfully(this); } catch (Exception ex) { _logger.CloseFailed(ex, this); } finally { _channelMonitor.Dispose(); _resyncTimer.Dispose(); _cts.Dispose(); _subscriptionLock.Dispose(); _meter.Dispose(); } } /// /// Acquire a session /// /// /// /// /// /// /// internal async Task AcquireAsync(int? connectTimeout, int? serviceCallTimeout, CancellationToken cancellationToken) { var timeout = GetConnectCallTimeout(connectTimeout, serviceCallTimeout); using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); var ct = cts.Token; cts.CancelAfter(timeout); // wait max timeout on the reader lock/session while (true) { if (_disposed) { throw new ConnectionException($"Session {_sessionName} was closed."); } cancellationToken.ThrowIfCancellationRequested(); try { var readerlock = await _lock.ReaderLockAsync(ct).ConfigureAwait(false); try { if (_session != null) { if (!DisableComplexTypeLoading && !_session.IsTypeSystemLoaded) { // Ensure type system is loaded cts.CancelAfter(timeout); await _session.GetComplexTypeSystemAsync(ct).ConfigureAwait(false); } // // Now clients can continue the operation with the session handle // which encapsulates the release of the reader lock as well as // the ref count to the client. // var sessionLock = readerlock; readerlock = null; // Do not dispose below but when handle is disposed return new ServiceCallContext(_session, GetServiceCallTimeout( serviceCallTimeout), this, sessionLock, cancellationToken); } } finally { readerlock?.Dispose(); } } catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested) { throw new TimeoutException("Connecting to the endpoint timed out."); } } } /// /// Safely invoke the service call and retry if the session /// disconnected during call. /// /// /// /// /// /// /// /// /// internal async Task RunAsync(Func> service, int? connectTimeout, int? serviceCallTimeout, CancellationToken cancellationToken) { var timeout = GetConnectCallTimeout(connectTimeout, serviceCallTimeout); using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); var ct = cts.Token; cts.CancelAfter(timeout); // wait max timeout on the reader lock/session while (true) { if (_disposed) { throw new ConnectionException($"Session {_sessionName} was closed."); } cancellationToken.ThrowIfCancellationRequested(); try { using var readerlock = await _lock.ReaderLockAsync(ct).ConfigureAwait(false); if (_session != null) { if (!DisableComplexTypeLoading && !_session.IsTypeSystemLoaded) { // Ensure type system is loaded cts.CancelAfter(timeout); await _session.GetComplexTypeSystemAsync(ct).ConfigureAwait(false); } var serviceTimeout = GetServiceCallTimeout(serviceCallTimeout); using var context = new ServiceCallContext(_session, serviceTimeout, ct: ct); cts.CancelAfter(serviceTimeout); var result = await service(context).ConfigureAwait(false); // // Check wether tracked and untracked token are the same. This is the case // with kepserver, which uses the same token for all continuations. If it // is the same, it is already tracked. If it is different, we need to untrack // and track the new one // if (context.TrackedToken != null && context.TrackedToken != context.UntrackedToken) { AddRef(context.TrackedToken); } else if (LingerTimeout != null) { AddRef(_sessionName, LingerTimeout); } if (context.UntrackedToken != null && context.TrackedToken != context.UntrackedToken) { Release(context.UntrackedToken); } return result; } // We are not resetting the timeout here since we have not yet been // able to obtain a session in the current timeout. } catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested) { throw new TimeoutException( "Connecting to the endpoint or the request itself timed out."); } catch (Exception ex) when (!IsConnected && !cancellationToken.IsCancellationRequested) { _logger.SessionDisconnected(this, ex.Message); cts.CancelAfter(timeout); // Reset timeout again to wait again for session } } } /// /// Safely invoke a streaming service and retry if the session /// disconnected during an operation. /// /// /// /// /// /// /// /// /// internal async IAsyncEnumerable RunAsync(AsyncEnumerableBase operation, int? connectTimeout, int? serviceCallTimeout, [EnumeratorCancellation] CancellationToken cancellationToken) { var timeout = GetConnectCallTimeout(connectTimeout, serviceCallTimeout); using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); var ct = cts.Token; cts.CancelAfter(timeout); // wait max timeout on the reader lock/session operation.Reset(); while (operation.HasMore) { if (_disposed) { throw new ConnectionException($"Session {_sessionName} was closed."); } cancellationToken.ThrowIfCancellationRequested(); if (_disposed) { throw new ConnectionException($"Session {_sessionName} was closed."); } IEnumerable results; try { using var readerlock = await _lock.ReaderLockAsync(ct).ConfigureAwait(false); if (_session != null) { // Ensure type system is loaded if (!DisableComplexTypeLoading && !_session.IsTypeSystemLoaded) { cts.CancelAfter(timeout); await _session.GetComplexTypeSystemAsync(ct).ConfigureAwait(false); } var serviceTimeout = GetServiceCallTimeout(serviceCallTimeout); using var context = new ServiceCallContext(_session, serviceTimeout, ct: ct); cts.CancelAfter(serviceTimeout); results = await operation.ExecuteAsync(context).ConfigureAwait(false); } else { // We are not resetting the timeout here since we have not yet been // able to obtain a session in the current timeout. continue; } } catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested) { throw new TimeoutException( "Connecting to the endpoint or a request operation timed out."); } catch (Exception ex) when (!IsConnected && !cancellationToken.IsCancellationRequested) { _logger.SessionDisconnected(this, ex.Message); cts.CancelAfter(timeout); // Reset timeout again to wait again for session continue; } foreach (var result in results) { yield return result; } cts.CancelAfter(timeout); // Reset timeout now to wait max timeout for session } } /// /// Connect /// /// /// /// internal void AddRef(string? token = null, TimeSpan? expiresAfter = null) { // If token provided create a registered release CancellationTokenSource? cts = null; if (token != null) { lock (_tokens) { // // Get any registered token and see if we can just re-arm // the timer (when the cancellation has not been requested // yet. If so we do not need to add ref at all and just // re-use the existing registered token. If there is a // token id collision then there is the potential that // tokens get removed too early using the release(token) // api. Since that is only used in the case of continuation // tokens we expect that not to happen on the same session. // if (_tokens.TryGetValue(token, out cts)) { cts.CancelAfter(expiresAfter ?? TimeSpan.FromSeconds(10)); if (!cts.IsCancellationRequested) { // Re-armed the current timer no need to add ref return; } _tokens.Remove(token); } cts = new CancellationTokenSource(); _tokens.Add(token, cts); } } if (Interlocked.Increment(ref _refCount) == 1) { // Post connection request TriggerConnectionEvent(ConnectionEvent.Connect); } if (cts != null) { // // Now that we took a reference register callback that removes // registered token source under lock if it is the current one // and then cancel and call release. After release dispose the // token source to free the timer. // cts.Token.Register(() => { Debug.Assert(token != null, "Captured token should not be null"); lock (_tokens) { if (_tokens.TryGetValue(token, out var registered) && registered == cts) { _tokens.Remove(token); } } Release(); cts.Dispose(); }); // // Start the cancellation token source timer now and // take a new reference. // cts.CancelAfter(expiresAfter ?? TimeSpan.FromSeconds(10)); } } /// /// Disconnect /// /// internal void Release(string? token = null) { if (token == null) { // Decrement reference count if (Interlocked.Decrement(ref _refCount) == 0) { // Post disconnect request TriggerConnectionEvent(ConnectionEvent.Disconnect); } } else if (_tokens.TryGetValue(token, out var cts)) { // // Cancel will callback back into here, unregister from // tokens cache, release the reference (above) and then // dispose the tracked cancellation token source. // cts.Cancel(); } // No token so we either expired or never registered // the first is expected, the second is a bug, we cannot // tell the difference though. } /// /// Manages the underlying session state machine. /// /// /// private async Task ManageSessionStateMachineAsync(CancellationToken ct) { var currentSessionState = SessionState.Disconnected; var reconnectPeriod = 0; var cleanup = false; var reconnectTimer = _timeProvider.CreateTimer( _ => TriggerConnectionEvent(ConnectionEvent.ConnectRetry), null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); try { await using (reconnectTimer.ConfigureAwait(false)) { try { await foreach (var (trigger, context) in _channel.Reader.ReadAllAsync(ct).ConfigureAwait(false)) { _logger.ProcessingEvent(this, trigger.ToString(), currentSessionState.ToString()); switch (trigger) { case ConnectionEvent.Reset: if (currentSessionState != SessionState.Connected) { (context as TaskCompletionSource)?.TrySetResult(); break; } // If currently reconnecting, dispose the reconnect handler _reconnectHandler.CancelReconnect(); // // Close bypassing everything but keep channel open then trigger a // reconnect. The reconnect will recreate the session and subscriptions // Debug.Assert(_session != null); await _session.CloseAsync(false, default).ConfigureAwait(false); goto case ConnectionEvent.StartReconnect; case ConnectionEvent.Connect: if (currentSessionState == SessionState.Disconnected) { // Start connecting cleanup = false; reconnectTimer.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); currentSessionState = SessionState.Connecting; reconnectPeriod = GetMinReconnectPeriod(); } goto case ConnectionEvent.ConnectRetry; case ConnectionEvent.ConnectRetry: switch (currentSessionState) { case SessionState.Connecting: Debug.Assert(_reconnectHandler.State == SessionReconnectHandler.ReconnectState.Ready); Debug.Assert(_disconnectLock != null); Debug.Assert(_session == null); if (!await TryConnectAsync(ct).ConfigureAwait(false) || !await TrySyncAsync(ct).ConfigureAwait(false)) { // Reschedule connecting await CloseSessionAsync(false).ConfigureAwait(false); Debug.Assert(reconnectPeriod != 0, "Reconnect period should not be 0."); var retryDelay = TimeSpan.FromMilliseconds( _reconnectHandler.CheckedReconnectPeriod(reconnectPeriod)); _logger.RetryingConnection(this, retryDelay); reconnectTimer.Change(retryDelay, Timeout.InfiniteTimeSpan); reconnectPeriod = _reconnectHandler.JitteredReconnectPeriod(reconnectPeriod); break; } Debug.Assert(_session != null); // Allow access to session now Debug.Assert(_disconnectLock != null); _disconnectLock.Dispose(); _disconnectLock = null; _reconnectRequired = 0; currentSessionState = SessionState.Connected; NotifySubscriptions(_session, false); break; case SessionState.Disconnected: // the client is disconnected and we scheduled it for cleanup if (cleanup) { return; } // Nothing to do, wait for connect break; case SessionState.Connected: // Nothing to do, already connected break; case SessionState.Reconnecting: Debug.Fail("Should not be connecting during reconnecting."); break; } break; case ConnectionEvent.SubscriptionSyncOne: var subscriptionToSync = context as OpcUaSubscription; Debug.Assert(subscriptionToSync != null); await SyncAsync(subscriptionToSync, ct).ConfigureAwait(false); break; case ConnectionEvent.SubscriptionSyncAll: await TrySyncAsync(ct).ConfigureAwait(false); break; case ConnectionEvent.StartReconnect: // sent by the keep alive timeout path switch (currentSessionState) { case SessionState.Connected: // only valid when connected. Debug.Assert(_reconnectHandler.State == SessionReconnectHandler.ReconnectState.Ready); _logger.ReconnectingSession(this, _sessionName, (context is ServiceResult sr) ? "error " + sr : "RESET"); // Ensure no more access to the session through reader locks Debug.Assert(_disconnectLock == null); _disconnectLock = await _lock.WriterLockAsync(ct); _logger.BeginReconnectingSession(this, _sessionName); Debug.Assert(_session != null); var state = _reconnectHandler.BeginReconnect(_session, _reverseConnectManager, GetMinReconnectPeriod(), (sender, evt) => { if (!ReferenceEquals(sender, _reconnectHandler)) { _logger.ReconnectHandlerMismatch(this); return; } TriggerConnectionEvent(ConnectionEvent.ReconnectComplete, _reconnectHandler.Session); }); // Save session while reconnecting. Debug.Assert(_reconnectingSession == null); _reconnectingSession = _session; _session = null; NotifyConnectivityStateChange(EndpointConnectivityState.Connecting); currentSessionState = SessionState.Reconnecting; NotifySubscriptions(_reconnectingSession, true); (context as TaskCompletionSource)?.TrySetResult(); break; case SessionState.Disconnected: case SessionState.Connecting: case SessionState.Reconnecting: // Nothing to do in this state break; } break; case ConnectionEvent.ReconnectComplete: // if session recovered, Session property is not null var reconnected = _reconnectHandler.Session as OpcUaSession; switch (currentSessionState) { case SessionState.Reconnecting: _logger.CompletedReconnectingSession(this, _sessionName); // // Behavior of the reconnect handler is as follows: // 1) newSession == null // => then the old session is still good, we missed keep alive. // 2) newSession != null but equal to previous session // => new channel was opened but the existing session was reactivated // 3) newSession != previous Session // => everything reconnected and new session was activated. // reconnected ??= _reconnectingSession; Debug.Assert(reconnected != null, "reconnected should never be null"); Debug.Assert(reconnected.Connected, "reconnected should always be connected"); // Handles all 3 cases above. var isNew = await UpdateSessionAsync(reconnected).ConfigureAwait(false); Debug.Assert(_session != null); Debug.Assert(_reconnectingSession == null); if (!isNew) { // Case 1) and 2) _logger.ClientRecovered(this); } else { // Case 3) _logger.ClientReconnected(this); _numberOfConnectionRetries++; } // If not already ready, signal we are ready again and ... NotifyConnectivityStateChange(EndpointConnectivityState.Ready); // ... allow access to the client again Debug.Assert(_disconnectLock != null); _disconnectLock.Dispose(); _disconnectLock = null; _reconnectRequired = 0; reconnectPeriod = GetMinReconnectPeriod(); currentSessionState = SessionState.Connected; if (!await TrySyncAsync(ct).ConfigureAwait(false)) { TriggerReconnect(StatusCodes.BadNotConnected, "Failed to synchronize subscriptions after reconnect."); break; } NotifySubscriptions(_session, false); break; case SessionState.Connected: Debug.Fail("Should not signal reconnected when already connected."); break; case SessionState.Connecting: case SessionState.Disconnected: Debug.Assert(_reconnectingSession == null); reconnected?.Dispose(); break; } break; case ConnectionEvent.Disconnect: if (currentSessionState != SessionState.Disconnected) { await HandleDisconnectEvent(ct).ConfigureAwait(false); currentSessionState = SessionState.Disconnected; // Set trigger to close in 1 minute if not reconnected cleanup = true; reconnectTimer.Change(TimeSpan.FromMinutes(1), Timeout.InfiniteTimeSpan); } break; } _logger.EventProcessed(this, trigger.ToString(), currentSessionState.ToString()); } } catch (OperationCanceledException) { } catch (Exception ex) { _logger.ConnectionManagerExited(ex, this); } finally { _reconnectHandler.CancelReconnect(); } } } catch (OperationCanceledException) { } catch (Exception ex) { _logger.ManagementLoopException(ex, this); throw; } finally { if (currentSessionState != SessionState.Disconnected) { _logger.DisconnectingDisposed(this); await HandleDisconnectEvent(default).ConfigureAwait(false); currentSessionState = SessionState.Disconnected; } _logger.ExitingManagementLoop(this); await _onClose().ConfigureAwait(false); } async ValueTask HandleDisconnectEvent(CancellationToken cancellationToken) { // If currently reconnecting, dispose the reconnect handler and stop timer _reconnectHandler.CancelReconnect(); reconnectTimer.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); // if not already disconnected, aquire writer lock _disconnectLock ??= await _lock.WriterLockAsync(cancellationToken); reconnectPeriod = 0; NotifyConnectivityStateChange(EndpointConnectivityState.Disconnected); NotifySubscriptions(_session, true); await CloseSessionAsync().ConfigureAwait(false); Debug.Assert(_session == null); } static void NotifySubscriptions(OpcUaSession? session, bool disconnected) { if (session == null) { return; } foreach (var h in session.SubscriptionHandles.Values) { h.NotifySessionConnectionState(disconnected); } } int GetMinReconnectPeriod() { var reconnectPeriod = MinReconnectDelay ?? TimeSpan.Zero; if (reconnectPeriod == TimeSpan.Zero) { reconnectPeriod = TimeSpan.FromSeconds(1); } if (reconnectPeriod > _maxReconnectPeriod) { reconnectPeriod = _maxReconnectPeriod; } return (int)reconnectPeriod.TotalMilliseconds; } } /// /// Log namespace table changes /// /// /// private void LogNamespaceTableChanges(string[] oldTable, string[] newTable) { var tableChanged = false; for (var i = 0; i < Math.Max(oldTable.Length, newTable.Length); i++) { if (i < oldTable.Length && i < newTable.Length) { if (oldTable[i] == newTable[i]) { continue; } tableChanged = true; _logger.NamespaceIndexChanged(this, i, oldTable[i], newTable[i]); } else if (i < oldTable.Length) { tableChanged = true; _logger.NamespaceIndexRemoved(this, i, oldTable[i]); } else { tableChanged = true; _logger.NamespaceIndexAdded(this, i, newTable[i]); } } if (tableChanged) { Interlocked.Increment(ref _namespaceTableChanges); } } private const int kMinPublishRequestCount = 2; private const int kMaxPublishRequestCount = 10; /// /// Ensure min publish requests are configured correctly /// private void UpdatePublishRequestCounts() { var session = _session; if (session == null) { return; } var minPublishRequests = MinPublishRequests ?? 0; if (minPublishRequests <= 0) { minPublishRequests = kMinPublishRequestCount; } var maxPublishRequests = MaxPublishRequests ?? kMaxPublishRequestCount; if (maxPublishRequests <= 0 || maxPublishRequests > ushort.MaxValue) { maxPublishRequests = ushort.MaxValue; } var createdSubscriptions = SubscriptionCount; if (PublishRequestsPerSubscriptionPercent.HasValue) { var percentage = PublishRequestsPerSubscriptionPercent ?? 100; var minPublishOverride = percentage == 100 || percentage <= 0 ? createdSubscriptions : (int)Math.Ceiling(createdSubscriptions * (percentage / 100.0)); if (minPublishRequests < minPublishOverride) { minPublishRequests = minPublishOverride; } } Debug.Assert(minPublishRequests > 0); Debug.Assert(maxPublishRequests > 0); if (minPublishRequests > maxPublishRequests) { // Dont allow min to be higher than max minPublishRequests = maxPublishRequests; } // // The stack will choose a value based on the subscription // count that is between min and max. // session.MinPublishRequestCount = minPublishRequests; session.MaxPublishRequestCount = maxPublishRequests; if (createdSubscriptions > 0 && minPublishRequests > OutstandingRequestCount) { session.StartPublishing(session.OperationTimeout, false); } } /// /// Connect client /// /// /// private async ValueTask TryConnectAsync(CancellationToken ct) { var timeout = CreateSessionTimeout ?? TimeSpan.FromSeconds(10); NotifyConnectivityStateChange(EndpointConnectivityState.Connecting); Debug.Assert(_connection.Endpoint != null); _logger.ConnectingToEndpoint(this, _connection.Endpoint.Url); var attempt = 0; foreach (var nextUrl in _connection.GetEndpointUrls()) { var endpointUrl = nextUrl; // Ensure any previous session is disposed here. await CloseSessionAsync().ConfigureAwait(false); ct.ThrowIfCancellationRequested(); try { ITransportWaitingConnection? connection = null; if (_reverseConnectManager != null) { connection = await _reverseConnectManager.WaitForConnectionAsync( endpointUrl, null, ct).ConfigureAwait(false); } // // Get the endpoint by connecting to server's discovery endpoint. // Try to find the first endpoint with security. // var securityMode = _connection.Endpoint.SecurityMode ?? SecurityMode.NotNone; var securityProfile = _connection.Endpoint.SecurityPolicy; var endpointDescription = await SelectEndpointAsync(_configuration, endpointUrl, connection, securityMode, securityProfile, _logger, this, ct: ct).ConfigureAwait(false); if (endpointDescription == null) { _logger.NoMatchingEndpoint(this, _sessionName); continue; } endpointUrl = Utils.ParseUri(endpointDescription.EndpointUrl); var endpointConfiguration = EndpointConfiguration.Create(_configuration); endpointConfiguration.OperationTimeout = (int)timeout.TotalMilliseconds; var endpoint = new ConfiguredEndpoint(null, endpointDescription, endpointConfiguration); var credential = _connection.User; if (securityMode == SecurityMode.Best && endpointDescription.SecurityMode == MessageSecurityMode.None) { _logger.NoSecurityEnabled(this, endpointUrl, _sessionName); credential = null; } var userIdentity = await credential.ToUserIdentityAsync( _configuration).ConfigureAwait(false); var identityPolicy = endpoint.Description.FindUserTokenPolicy( userIdentity.TokenType, userIdentity.IssuedTokenType, endpointDescription.SecurityPolicyUri); if (identityPolicy == null) { _logger.NoUserTokenPolicy(this, userIdentity.TokenType, userIdentity.IssuedTokenType, endpointUrl, _sessionName); continue; } _logger.CreatingSession(++attempt, this, _sessionName, endpointUrl); var preferredLocales = _connection.Locales?.ToList() ?? []; if (preferredLocales.Count == 0) { // Create the session with english as default preferredLocales.Add("en-US"); if (CultureInfo.CurrentCulture.Name != preferredLocales[0]) { // and current language locale as backup preferredLocales.Add(CultureInfo.CurrentCulture.Name); } } var sessionTimeout = SessionTimeout ?? TimeSpan.FromSeconds(30); var session = await CreateAsync(_configuration, _reverseConnectManager, endpoint, // Update endpoint through discovery updateBeforeConnect: _reverseConnectManager != null, checkDomain: false, // Domain must match on connect _sessionName, (uint)sessionTimeout.TotalMilliseconds, userIdentity, preferredLocales, ct).ConfigureAwait(false) as OpcUaSession; Debug.Assert(session != null); session.RenewUserIdentity += (_, _) => userIdentity; // Assign the session var isNew = await UpdateSessionAsync(session).ConfigureAwait(false); Debug.Assert(isNew); _logger.NewSessionCreated(this, _sessionName, endpointUrl, _connection.Endpoint.Url); _logger.ClientConnected(this, endpointUrl); return true; } catch (Exception ex) { NotifyConnectivityStateChange(ToConnectivityState(ex)); _numberOfConnectionRetries++; _logger.ConnectionFailed(++attempt, this, endpointUrl, ex.Message); } } return false; } /// /// Handle publish errors /// /// /// internal void Session_HandlePublishError(ISession session, PublishErrorEventArgs e) { if (!ReferenceEquals(session, _session)) { if (_session != null) { _logger.PublishErrorDifferentSession(this, session.ToString()); } return; } switch (e.Status.Code) { case StatusCodes.BadSessionIdInvalid: case StatusCodes.BadSecureChannelClosed: case StatusCodes.BadSessionClosed: case StatusCodes.BadConnectionClosed: case StatusCodes.BadServerHalted: case StatusCodes.BadNotConnected: case StatusCodes.BadNoCommunication: case StatusCodes.BadNoSubscription: // Never sent in current stack version TriggerReconnect(e.Status, "Publish"); return; default: _logger.PublishError(this, e.Status.ToString()); break; } } /// /// Feed back acknoledgements /// /// /// internal void Session_PublishSequenceNumbersToAcknowledge(ISession context, PublishSequenceNumbersToAcknowledgeEventArgs e) { if (context is not OpcUaSession session) { return; } // Reset timeout counter _publishTimeoutCounter = 0; var acks = e.AcknowledgementsToSend .Concat(e.DeferredAcknowledgementsToSend) .ToHashSet(); if (acks.Count == 0) { return; } e.AcknowledgementsToSend.Clear(); e.DeferredAcknowledgementsToSend.Clear(); foreach (var subscription in session.SubscriptionHandles.Values) { if (!subscription.TryGetCurrentPosition(out var sid, out var seq)) { // No deferrals e.AcknowledgementsToSend.AddRange(acks.Where(a => a.SubscriptionId == sid)); } else { // Ack all messages before this one for the subscriptoin e.AcknowledgementsToSend.AddRange(acks.Where(a => a.SubscriptionId == sid && (int)a.SequenceNumber <= (int)seq)); } } e.DeferredAcknowledgementsToSend.AddRange(acks.Except(e.AcknowledgementsToSend)); if (_logger.IsEnabled(LogLevel.Trace)) { _logger.SendingAcks(this, Environment.CurrentManagedThreadId, ToString(e.AcknowledgementsToSend), ToString(e.DeferredAcknowledgementsToSend), session.GoodPublishRequestCount); static string ToString(SubscriptionAcknowledgementCollection acks) { return acks.Count == 0 ? "no" : acks .OrderBy(a => a.SubscriptionId) .Select(a => $"{a.SubscriptionId}:{a.SequenceNumber}") .Aggregate((a, b) => $"{a}, {b}"); } } } /// /// Handles a keep alive event from a session and triggers a reconnect /// if necessary. /// /// /// internal void Session_KeepAlive(ISession session, KeepAliveEventArgs e) { if (_disposed) { return; } try { // check for events from discarded sessions. if (!ReferenceEquals(session, _session)) { if (_session != null) { _logger.KeepAliveErrorDifferentSession(this, session.ToString()); } return; } // start reconnect sequence on communication error. Interlocked.Increment(ref _keepAliveCounter); if (ServiceResult.IsBad(e.Status)) { _keepAliveCounter = 0; TriggerReconnect(e.Status, "Keep alive"); } else if (SubscriptionCount > 0 && GoodPublishRequestCount == 0) { UpdatePublishRequestCounts(); } Interlocked.Increment(ref _keepAliveTotal); } catch (Exception ex) { _logger.KeepAliveError(ex, this); } } /// /// Trigger reconnect /// /// /// void TriggerReconnect(ServiceResult sr, string action) { if (Interlocked.Increment(ref _reconnectRequired) == 1) { _logger.TriggerReconnect(this, sr.ToString(), action); // Ensure we reconnect TriggerConnectionEvent(ConnectionEvent.StartReconnect, sr); } } /// /// Trigger connection event /// /// /// private void TriggerConnectionEvent(ConnectionEvent evt, object? context = null) { _channel.Writer.TryWrite((evt, context)); } /// /// Update session state /// /// private async ValueTask UpdateSessionAsync(ISession session) { _publishTimeoutCounter = 0; Debug.Assert(session is OpcUaSession); if (_session == null) { _session = _reconnectingSession; _reconnectingSession = null; } var oldTable = _session?.NamespaceUris.ToArray(); Debug.Assert(_reconnectingSession == null); var isNewSession = false; if (!ReferenceEquals(_session, session)) { await CloseSessionAsync().ConfigureAwait(false); _session = (OpcUaSession)session; isNewSession = true; kSessions.Add(1, _metrics.TagList); _numberofSuccessfulConnections++; } UpdatePublishRequestCounts(); NotifyConnectivityStateChange(EndpointConnectivityState.Ready); UpdateNamespaceTableAndSessionDiagnostics(_session, oldTable); return isNewSession; void UpdateNamespaceTableAndSessionDiagnostics(OpcUaSession session, string[]? oldTable) { if (oldTable != null) { var newTable = session.NamespaceUris.ToArray(); LogNamespaceTableChanges(oldTable, newTable); } lock (_channelLock) { UpdateConnectionDiagnosticFromSession(session); } } } /// /// Update diagnostic if the channel has changed /// private void OnUpdateConnectionDiagnostics() { if (_session != null) { lock (_channelLock) { UpdateConnectionDiagnosticFromSession(_session); } } } /// /// Update session diagnostics /// /// private void UpdateConnectionDiagnosticFromSession(OpcUaSession session) { // Called under lock var channel = session.TransportChannel; var token = channel?.CurrentToken; var now = _timeProvider.GetUtcNow(); var lastDiagnostics = _lastDiagnostics; var elapsed = now - lastDiagnostics.TimeStamp; var channelChanged = false; if (token != null) { // // Monitor channel's token lifetime and update diagnostics // Check wether the token or channel changed. If so set a // timer to monitor the new token lifetime, if not then // try again after the remaining lifetime or every second // until it changed unless the token is then later gone. // channelChanged = !(lastDiagnostics != null && lastDiagnostics.ChannelId == token.ChannelId && lastDiagnostics.TokenId == token.TokenId && lastDiagnostics.CreatedAt == token.CreatedAt); var lifetime = TimeSpan.FromMilliseconds(Math.Min(token.Lifetime, _configuration.TransportQuotas.SecurityTokenLifetime)); if (channelChanged) { _channelMonitor.Change(lifetime, Timeout.InfiniteTimeSpan); _logger.ChannelGotNewToken( token.ChannelId.ToString(CultureInfo.InvariantCulture), token.TokenId.ToString(CultureInfo.InvariantCulture), token.CreatedAt); } else { // // Token has not yet been updated, let's retry later // It is also assumed that the port/ip are still the same // if (lifetime > elapsed) { _channelMonitor.Change(lifetime - elapsed, Timeout.InfiniteTimeSpan); } else { _channelMonitor.Change(TimeSpan.FromSeconds(1), Timeout.InfiniteTimeSpan); } } } var sessionId = session.SessionId?.AsString(session.MessageContext, NamespaceFormat.Index); // Get effective ip address and port var socket = (channel as UaSCUaBinaryTransportChannel)?.Socket; var remoteIpAddress = socket?.RemoteEndpoint?.GetIPAddress()?.ToString(); var remotePort = socket?.RemoteEndpoint?.GetPort(); var localIpAddress = socket?.LocalEndpoint?.GetIPAddress()?.ToString(); var localPort = socket?.LocalEndpoint?.GetPort(); if (_lastDiagnostics.SessionCreated == session.CreatedAt && _lastDiagnostics.SessionId == sessionId && _lastDiagnostics.RemoteIpAddress == remoteIpAddress && _lastDiagnostics.RemotePort == remotePort && _lastDiagnostics.LocalIpAddress == localIpAddress && _lastDiagnostics.LocalPort == localPort && !channelChanged) { return; } _lastDiagnostics = new ChannelDiagnosticModel { Connection = _connection, TimeStamp = now, SessionCreated = session.CreatedAt, SessionId = sessionId, RemoteIpAddress = remoteIpAddress, RemotePort = remotePort == -1 ? null : remotePort, LocalIpAddress = localIpAddress, LocalPort = localPort == -1 ? null : localPort, ChannelId = token?.ChannelId, TokenId = token?.TokenId, CreatedAt = token?.CreatedAt, Lifetime = token == null ? null : TimeSpan.FromMilliseconds(token.Lifetime), Client = ToChannelKey(token?.ClientInitializationVector, token?.ClientEncryptingKey, token?.ClientSigningKey), Server = ToChannelKey(token?.ServerInitializationVector, token?.ServerEncryptingKey, token?.ServerSigningKey) }; _diagnosticsCb(_lastDiagnostics); _logger.ChannelDiagnosticsUpdated(sessionId); static ChannelKeyModel? ToChannelKey(byte[]? iv, byte[]? key, byte[]? sk) { if (iv == null || key == null || sk == null || iv.Length == 0 || key.Length == 0 || sk.Length == 0) { return null; } return new ChannelKeyModel { Iv = iv, Key = key, SigLen = sk.Length }; } } /// /// Unset and dispose existing session /// /// /// private async ValueTask CloseSessionAsync(bool shutdown = false) { if (_reconnectingSession != null) { await DisposeAsync(_reconnectingSession).ConfigureAwait(false); _reconnectingSession = null; } if (_session != null) { await DisposeAsync(_session).ConfigureAwait(false); _session = null; } _publishTimeoutCounter = 0; async ValueTask DisposeAsync(OpcUaSession session) { try { if (shutdown) { // When shutting down, delete all subscriptions session.DeleteSubscriptionsOnClose = true; } session.UpdateOperationTimeout(true); await session.CloseAsync(CancellationToken.None).ConfigureAwait(false); _logger.SessionClosed(this, session); } catch (Exception ex) { _logger.SessionCloseFailed(ex, this, session); } finally { session.Dispose(); kSessions.Add(-1, _metrics.TagList); } Debug.Assert(session.SubscriptionCount == 0); } } /// /// Notify about new connectivity state using any status callback registered. /// /// /// private void NotifyConnectivityStateChange(EndpointConnectivityState state) { var previous = _lastState; if (previous == state) { return; } if (previous != EndpointConnectivityState.Connecting && previous != EndpointConnectivityState.Ready && state == EndpointConnectivityState.Error) { // Do not change state to generic error once we have // a specific error state already set... _logger.ErrorLeavingState(this, _connection.Endpoint!.Url, previous); return; } _lastState = state; if (state == EndpointConnectivityState.Ready) { lock (_browsers) { foreach (var browser in _browsers.Values) { browser.OnConnected(); } } } _logger.SessionStateChanged(this, _sessionName, _connection.Endpoint!.Url, previous, state); try { _notifier?.Invoke(this, new EndpointConnectivityStateEventArgs(state)); } catch (Exception ex) { _logger.ExceptionDuringStateCallback(ex, this); } } /// /// Select the endpoint to use /// /// /// /// /// /// /// /// /// /// /// internal static async Task SelectEndpointAsync( ApplicationConfiguration configuration, Uri? discoveryUrl, ITransportWaitingConnection? connection, SecurityMode securityMode, string? securityPolicy, ILogger logger, object? context, string? endpointUrl = null, CancellationToken ct = default) { var ctx = context?.ToString() ?? "null"; var endpointConfiguration = EndpointConfiguration.Create(); endpointConfiguration.OperationTimeout = (int)TimeSpan.FromSeconds(15).TotalMilliseconds; // needs to add the /discovery onto http urls if (connection == null) { if (discoveryUrl == null) { return null; } if (discoveryUrl.Scheme == Utils.UriSchemeHttp && !discoveryUrl.AbsolutePath.EndsWith("/discovery", StringComparison.OrdinalIgnoreCase)) { discoveryUrl = new UriBuilder(discoveryUrl) { Path = discoveryUrl.AbsolutePath.TrimEnd('/') + "/discovery" }.Uri; } } using var client = connection != null ? DiscoveryClient.Create(configuration, connection, endpointConfiguration) : DiscoveryClient.Create(configuration, discoveryUrl, endpointConfiguration); var uri = new Uri(endpointUrl ?? client.Endpoint.EndpointUrl); var endpoints = await client.GetEndpointsAsync(null, ct).ConfigureAwait(false); discoveryUrl ??= uri; logger.DiscoveryEndpointReturnedEndpoints(ctx, discoveryUrl, uri, securityMode, securityPolicy ?? "any", endpoints.Select( ep => " " + ToString(ep)).Aggregate((a, b) => $"{a}\n{b}")); var filtered = endpoints .Where(ep => SecurityPolicies.GetDisplayName(ep.SecurityPolicyUri) != null && ep.SecurityMode.IsSame(securityMode) && (securityPolicy == null || string.Equals(ep.SecurityPolicyUri, securityPolicy, StringComparison.OrdinalIgnoreCase) || string.Equals(ep.SecurityPolicyUri, "http://opcfoundation.org/UA/SecurityPolicy#" + securityPolicy, StringComparison.OrdinalIgnoreCase))) // // The security level is a relative measure assigned by the server // to the endpoints that it returns. Clients should always pick the // highest level unless they have a reason not too. Some servers // however, mess this up a bit. So group SecurityLevel also by // security mode and then pick the highest in that group. // .OrderByDescending(ep => ((int)ep.SecurityMode << 8) | ep.SecurityLevel) .ToList(); // // Try to find endpoint that matches scheme and endpoint url path // but fall back to match just the scheme. We need to match only // scheme to support the reverse connect (indicated by connection // being not null here). // var selected = filtered.Find(ep => Match(ep, uri, true, true)) ?? filtered.Find(ep => Match(ep, uri, true, false)); if (connection != null) { // // Only allow same uri scheme (which must also be opc.tcp) // for when reverse connection is used. // if (selected != null) { logger.EndpointSelectedViaReverseConnect(ctx, ToString(selected)); } return selected; } if (selected == null) { // // Fall back to first supported endpoint matching absolute path // then fall back to first endpoint (backwards compatibilty) // selected = filtered.Find(ep => Match(ep, uri, false, true)) ?? filtered.Find(ep => Match(ep, uri, false, false)); if (selected == null) { return null; } } // // Adjust the host name and port to the host name and port // that was use to successfully connect the discovery client // var selectedUrl = Utils.ParseUri(selected.EndpointUrl); if (selectedUrl != null && discoveryUrl != null && selectedUrl.Scheme == discoveryUrl.Scheme) { selected.EndpointUrl = new UriBuilder(selectedUrl) { Host = discoveryUrl.DnsSafeHost, Port = discoveryUrl.Port }.ToString(); } logger.EndpointSelected(ctx, ToString(selected)); return selected; static string ToString(EndpointDescription ep) => $"#{ep.SecurityLevel:000}: {ep.EndpointUrl}|{ep.SecurityMode} [{ep.SecurityPolicyUri}]"; // Match endpoint returned against desired endpoint url static bool Match(EndpointDescription endpointDescription, Uri endpointUrl, bool includeScheme, bool includePath) { var url = Utils.ParseUri(endpointDescription.EndpointUrl); return url != null && (!includeScheme || string.Equals(url.Scheme, endpointUrl.Scheme, StringComparison.OrdinalIgnoreCase)) && (!includePath || string.Equals(url.AbsolutePath, endpointUrl.AbsolutePath, StringComparison.OrdinalIgnoreCase)); } } /// /// Convert exception to connectivity state /// /// /// /// public EndpointConnectivityState ToConnectivityState(Exception ex, bool reconnecting = true) { EndpointConnectivityState state; switch (ex) { case ServiceResultException sre: switch (sre.StatusCode) { case StatusCodes.BadNoContinuationPoints: case StatusCodes.BadLicenseLimitsExceeded: case StatusCodes.BadTcpServerTooBusy: case StatusCodes.BadTooManySessions: case StatusCodes.BadTooManyOperations: state = EndpointConnectivityState.Busy; break; case StatusCodes.BadCertificateRevocationUnknown: case StatusCodes.BadCertificateIssuerRevocationUnknown: case StatusCodes.BadCertificateRevoked: case StatusCodes.BadCertificateIssuerRevoked: case StatusCodes.BadCertificateChainIncomplete: case StatusCodes.BadCertificateIssuerUseNotAllowed: case StatusCodes.BadCertificateUseNotAllowed: case StatusCodes.BadCertificateUriInvalid: case StatusCodes.BadCertificateTimeInvalid: case StatusCodes.BadCertificateIssuerTimeInvalid: case StatusCodes.BadCertificateInvalid: case StatusCodes.BadCertificateHostNameInvalid: case StatusCodes.BadNoValidCertificates: state = EndpointConnectivityState.CertificateInvalid; break; case StatusCodes.BadCertificateUntrusted: case StatusCodes.BadSecurityChecksFailed: state = EndpointConnectivityState.NoTrust; break; case StatusCodes.BadSecureChannelClosed: state = reconnecting ? EndpointConnectivityState.NoTrust : EndpointConnectivityState.Error; break; case StatusCodes.BadRequestTimeout: case StatusCodes.BadNotConnected: state = EndpointConnectivityState.NotReachable; break; case StatusCodes.BadUserAccessDenied: case StatusCodes.BadUserSignatureInvalid: state = EndpointConnectivityState.Unauthorized; break; default: state = EndpointConnectivityState.Error; break; } _logger.ServiceResultToState(sre.Result, state); break; default: state = EndpointConnectivityState.Error; _logger.ExceptionToState(ex.Message, state); break; } return state; } /// /// Get the real timeout for the service call /// /// /// private TimeSpan GetServiceCallTimeout(int? serviceCallTimeout) { if (serviceCallTimeout > 0) { return TimeSpan.FromMilliseconds(serviceCallTimeout.Value); } if (ServiceCallTimeout.HasValue) { return ServiceCallTimeout.Value; } if (OperationTimeout.HasValue && OperationTimeout > kDefaultServiceCallTimeout) { return OperationTimeout.Value; } return kDefaultServiceCallTimeout; } /// /// Get the real timeout for the connectivity of session /// /// /// /// private TimeSpan GetConnectCallTimeout(int? connectTimeout, int? serviceCallTimeout) { if (connectTimeout > 0) { return TimeSpan.FromMilliseconds(connectTimeout.Value); } if (ConnectTimeout.HasValue) { return ConnectTimeout.Value; } if (serviceCallTimeout > 0) { return TimeSpan.FromMilliseconds(serviceCallTimeout.Value); } return ServiceCallTimeout ?? kDefaultConnectTimeout; } /// /// Dump diagnostics /// /// /// private async Task DumpDiagnosticsPeriodicallyAsync(CancellationToken ct) { using var timer = new PeriodicTimer(TimeSpan.FromSeconds(10)); try { while (!ct.IsCancellationRequested) { await timer.WaitForNextTickAsync(ct).ConfigureAwait(false); if (_session != null) { var diagnostics = await _session.GetServerDiagnosticAsync( ct).ConfigureAwait(false); var str = JsonSerializer.Serialize(diagnostics, kIndented); Console.WriteLine(str); } } } catch (OperationCanceledException) { } } private static readonly JsonSerializerOptions kIndented = new() { WriteIndented = true }; private enum ConnectionEvent { Connect, ConnectRetry, Disconnect, StartReconnect, ReconnectComplete, Reset, SubscriptionSyncOne, SubscriptionSyncAll } private enum SessionState { Disconnected, Connecting, Connected, Reconnecting } /// /// Disconnected state /// private sealed class DisconnectState : IOpcUaClientDiagnostics { /// public int BadPublishRequestCount => 0; /// public int GoodPublishRequestCount => 0; /// public int OutstandingRequestCount => 0; /// public int SubscriptionCount => 0; /// public EndpointConnectivityState State => EndpointConnectivityState.Disconnected; /// public int ReconnectCount => 0; /// public int ConnectCount => 0; /// public int MinPublishRequestCount => 0; /// public bool ReconnectTriggered => false; /// public int KeepAliveCounter => 0; /// public int KeepAliveTotal => 0; } /// /// Create observable metrics /// private void InitializeMetrics() { _meter.CreateObservableGauge("iiot_edge_publisher_client_connectivity_state", () => new Measurement((int)_lastState, _metrics.TagList), description: "Client connectivity state."); _meter.CreateObservableGauge("iiot_edge_publisher_client_keep_alive_counter", () => new Measurement(_keepAliveCounter, _metrics.TagList), description: "Number of successful keep alives since last keep alive error."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_client_keep_alive_counter_count", () => new Measurement(_keepAliveTotal, _metrics.TagList), description: "Number of total successful keep alives of the client."); _meter.CreateObservableGauge("iiot_edge_publisher_client_reconnect_trigger", () => new Measurement(_reconnectRequired, _metrics.TagList), description: "Number of reconnect trigger actions."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_client_namespace_change_count", () => new Measurement(_namespaceTableChanges, _metrics.TagList), description: "Number of namespace table changes detected by the client."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_subscriptions", () => new Measurement(SubscriptionCount, _metrics.TagList), description: "Number of client managed subscriptions."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_client_sampler_count", () => new Measurement(_samplers.Count, _metrics.TagList), description: "Number of active client samplers."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_client_browser_count", () => new Measurement(_browsers.Count, _metrics.TagList), description: "Number of active browsers."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_client_connectivity_retry_count", () => new Measurement(_numberOfConnectionRetries, _metrics.TagList), description: "Number of connectivity retries on this connection."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_client_connectivity_count", () => new Measurement(_numberofSuccessfulConnections, _metrics.TagList), description: "Number of sessions established as a total for the client."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_client_ref_count", () => new Measurement(_refCount, _metrics.TagList), description: "Number of references to this client."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_client_good_publish_requests_count", () => new Measurement(GoodPublishRequestCount, _metrics.TagList), description: "Number of good publish requests."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_client_bad_publish_requests_count", () => new Measurement(BadPublishRequestCount, _metrics.TagList), description: "Number of bad publish requests."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_client_min_publish_requests_count", () => new Measurement(MinPublishRequestCount, _metrics.TagList), description: "Number of min publish requests that should be queued."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_client_outstanding_requests_count", () => new Measurement(OutstandingRequestCount, _metrics.TagList), description: "Number of outstanding requests."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_client_publish_timeout_count", () => new Measurement(_publishTimeoutCounter, _metrics.TagList), description: "Number of timed out requests."); } private static readonly UpDownCounter kSessions = Diagnostics.Meter.CreateUpDownCounter( "iiot_edge_publisher_session_count", description: "Number of active sessions."); private OpcUaSession? _reconnectingSession; private int _reconnectRequired; #pragma warning disable CA2213 // Disposable fields should be disposed private OpcUaSession? _session; private IDisposable? _disconnectLock; #pragma warning restore CA2213 // Disposable fields should be disposed private EndpointConnectivityState _lastState; private int _numberOfConnectionRetries; private int _numberofSuccessfulConnections; private bool _disposed; private int _refCount; private int _publishTimeoutCounter; private int _keepAliveCounter; private int _keepAliveTotal; private int _namespaceTableChanges; private ChannelDiagnosticModel _lastDiagnostics; private readonly ReverseConnectManager? _reverseConnectManager; private readonly AsyncReaderWriterLock _lock = new(); private readonly ApplicationConfiguration _configuration; private readonly IJsonSerializer _serializer; private readonly ILoggerFactory _loggerFactory; private readonly string _sessionName; private readonly IOptions _options; private readonly Func _onClose; private readonly ConnectionModel _connection; private readonly IMetricsContext _metrics; private readonly ILogger _logger; private readonly TimeProvider _timeProvider; private readonly Lock _channelLock = new(); #pragma warning disable CA2213 // Disposable fields should be disposed private readonly ITimer _channelMonitor; private readonly Task? _diagnosticsDumper; private readonly SessionReconnectHandler _reconnectHandler; private readonly CancellationTokenSource _cts; #pragma warning restore CA2213 // Disposable fields should be disposed private readonly Task _sessionManager; private readonly TimeSpan _maxReconnectPeriod; private readonly Channel<(ConnectionEvent, object?)> _channel; private readonly Action _diagnosticsCb; private readonly EventHandler? _notifier; private readonly Dictionary<(string, TimeSpan, TimeSpan), Sampler> _samplers = []; private readonly Dictionary<(string, TimeSpan), Browser> _browsers = []; private readonly Dictionary _tokens; private readonly Meter _meter = Diagnostics.NewMeter(); private static readonly TimeSpan kDefaultServiceCallTimeout = TimeSpan.FromMinutes(5); private static readonly TimeSpan kDefaultConnectTimeout = TimeSpan.FromMinutes(1); } /// /// Source-generated logging definitions for OpcUaClient /// internal static partial class OpcUaClientLogging { private const int EventClass = 520; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Information, Message = "{Client}: RECREATE: Creating new session with new waiting connection.")] public static partial void CreatingNewSessionWithConnection(this ILogger logger, OpcUaClient client); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Information, Message = "{Client}: RECREATE: Creating new session without connection.")] public static partial void CreatingNewSessionWithoutConnection(this ILogger logger, OpcUaClient client); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Information, Message = "{Client}: RECREATE: Closing channel and creating new session.")] public static partial void CreatingNewSessionClosingChannel(this ILogger logger, OpcUaClient client); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Information, Message = "{Client}: RECREATE: Creating new session.")] public static partial void CreatingNewSession(this ILogger logger, OpcUaClient client); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Debug, Message = "{Client}: Resetting...")] public static partial void Resetting(this ILogger logger, OpcUaClient client); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Error, Message = "{Client}: Failed to reset.")] public static partial void ResetFailed(this ILogger logger, Exception ex, OpcUaClient client); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Debug, Message = "{Client}: Closing...")] public static partial void Closing(this ILogger logger, OpcUaClient client); [LoggerMessage(EventId = EventClass + 8, Level = LogLevel.Information, Message = "{Client}: Successfully closed.")] public static partial void ClosedSuccessfully(this ILogger logger, OpcUaClient client); [LoggerMessage(EventId = EventClass + 9, Level = LogLevel.Error, Message = "{Client}: Failed to close.")] public static partial void CloseFailed(this ILogger logger, Exception ex, OpcUaClient client); [LoggerMessage(EventId = EventClass + 10, Level = LogLevel.Information, Message = "{Client}: Session disconnected during service call with message " + "{Message}, retrying.")] public static partial void SessionDisconnected(this ILogger logger, OpcUaClient client, string message); [LoggerMessage(EventId = EventClass + 11, Level = LogLevel.Debug, Message = "{Client}: Processing event {Event} in State {State}...")] public static partial void ProcessingEvent(this ILogger logger, OpcUaClient client, string @event, string state); [LoggerMessage(EventId = EventClass + 12, Level = LogLevel.Information, Message = "{Client}: Retrying connecting session in {RetryDelay}...")] public static partial void RetryingConnection(this ILogger logger, OpcUaClient client, TimeSpan retryDelay); [LoggerMessage(EventId = EventClass + 13, Level = LogLevel.Information, Message = "{Client}: Reconnecting session {Session} due to {Reason}...")] public static partial void ReconnectingSession(this ILogger logger, OpcUaClient client, string session, string reason); [LoggerMessage(EventId = EventClass + 14, Level = LogLevel.Information, Message = "{Client}: Begin reconnecting session {Session}...")] public static partial void BeginReconnectingSession(this ILogger logger, OpcUaClient client, string session); [LoggerMessage(EventId = EventClass + 15, Level = LogLevel.Error, Message = "{Client}: Reconnect handler mismatch.")] public static partial void ReconnectHandlerMismatch(this ILogger logger, OpcUaClient client); [LoggerMessage(EventId = EventClass + 16, Level = LogLevel.Information, Message = "{Client}: Completed reconnecting session {Session}...")] public static partial void CompletedReconnectingSession(this ILogger logger, OpcUaClient client, string session); [LoggerMessage(EventId = EventClass + 17, Level = LogLevel.Information, Message = "{Client}: Client RECOVERED!")] public static partial void ClientRecovered(this ILogger logger, OpcUaClient client); [LoggerMessage(EventId = EventClass + 18, Level = LogLevel.Information, Message = "{Client}: Client RECONNECTED!")] public static partial void ClientReconnected(this ILogger logger, OpcUaClient client); [LoggerMessage(EventId = EventClass + 19, Level = LogLevel.Debug, Message = "{Client}: Event {Event} in State {State} processed.")] public static partial void EventProcessed(this ILogger logger, OpcUaClient client, string @event, string state); [LoggerMessage(EventId = EventClass + 20, Level = LogLevel.Error, Message = "{Client}: Connection manager exited unexpectedly...")] public static partial void ConnectionManagerExited(this ILogger logger, Exception ex, OpcUaClient client); [LoggerMessage(EventId = EventClass + 21, Level = LogLevel.Error, Message = "{Client}: Exception in management loop.")] public static partial void ManagementLoopException(this ILogger logger, Exception ex, OpcUaClient client); [LoggerMessage(EventId = EventClass + 22, Level = LogLevel.Information, Message = "{Client}: Disconnect because client is disposed.")] public static partial void DisconnectingDisposed(this ILogger logger, OpcUaClient client); [LoggerMessage(EventId = EventClass + 23, Level = LogLevel.Information, Message = "{Client}: Exiting client management loop.")] public static partial void ExitingManagementLoop(this ILogger logger, OpcUaClient client); [LoggerMessage(EventId = EventClass + 24, Level = LogLevel.Information, Message = "{Client}: Connecting to {EndpointUrl}...")] public static partial void ConnectingToEndpoint(this ILogger logger, OpcUaClient client, string endpointUrl); [LoggerMessage(EventId = EventClass + 25, Level = LogLevel.Warning, Message = "{Client}: No endpoint found that matches connection of session {Name}.")] public static partial void NoMatchingEndpoint(this ILogger logger, OpcUaClient client, string name); [LoggerMessage(EventId = EventClass + 26, Level = LogLevel.Warning, Message = "{Client}: Although the use of best security was configured, there was no security-enabled " + "endpoint available at url {EndpointUrl}. An endpoint with no security will be used for session {Name} " + "but no credentials will be sent over it.")] public static partial void NoSecurityEnabled(this ILogger logger, OpcUaClient client, Uri endpointUrl, string name); [LoggerMessage(EventId = EventClass + 27, Level = LogLevel.Warning, Message = "{Client}: No UserTokenPolicy for {TokenType}/{IssuedTokenType} found on endpoint " + "{EndpointUrl} (session: {Name}).")] public static partial void NoUserTokenPolicy(this ILogger logger, OpcUaClient client, UserTokenType tokenType, XmlQualifiedName issuedTokenType, Uri endpointUrl, string name); [LoggerMessage(EventId = EventClass + 28, Level = LogLevel.Information, Message = "{Client}: #{Attempt} - Creating session {Name} with endpoint {EndpointUrl}...")] public static partial void CreatingSession(this ILogger logger, int attempt, OpcUaClient client, string name, Uri endpointUrl); [LoggerMessage(EventId = EventClass + 29, Level = LogLevel.Information, Message = "{Client}: New Session {Name} created with endpoint {EndpointUrl} ({Original}).")] public static partial void NewSessionCreated(this ILogger logger, OpcUaClient client, string name, Uri endpointUrl, string original); [LoggerMessage(EventId = EventClass + 30, Level = LogLevel.Information, Message = "{Client} Client CONNECTED to {EndpointUrl}!")] public static partial void ClientConnected(this ILogger logger, OpcUaClient client, Uri endpointUrl); [LoggerMessage(EventId = EventClass + 31, Level = LogLevel.Information, Message = "#{Attempt} - {Client}: Failed to connect to {EndpointUrl}: {Message}...")] public static partial void ConnectionFailed(this ILogger logger, int attempt, OpcUaClient client, Uri endpointUrl, string message); [LoggerMessage(EventId = EventClass + 32, Level = LogLevel.Error, Message = "{Client}: Received publish error for different session {Session}!")] public static partial void PublishErrorDifferentSession(this ILogger logger, OpcUaClient client, string? session); [LoggerMessage(EventId = EventClass + 33, Level = LogLevel.Information, Message = "{Client}: Publish error: {Error}...")] public static partial void PublishError(this ILogger logger, OpcUaClient client, string error); [LoggerMessage(EventId = EventClass + 34, Level = LogLevel.Trace, SkipEnabledCheck = true, Message = "{Client}: #{ThreadId} - Sending {Acks} acks and deferring {Deferrals} acks. ({Requests})")] public static partial void SendingAcks(this ILogger logger, OpcUaClient client, int threadId, string acks, string deferrals, int requests); [LoggerMessage(EventId = EventClass + 35, Level = LogLevel.Error, Message = "{Client}: Received keep alive for different session {Session}!")] public static partial void KeepAliveErrorDifferentSession(this ILogger logger, OpcUaClient client, string? session); [LoggerMessage(EventId = EventClass + 36, Level = LogLevel.Error, Message = "{Client}: Error in OnKeepAlive.")] public static partial void KeepAliveError(this ILogger logger, Exception ex, OpcUaClient client); [LoggerMessage(EventId = EventClass + 37, Level = LogLevel.Error, Message = "{Client}: Error {Error} during {Action} - triggering reconnect...")] public static partial void TriggerReconnect(this ILogger logger, OpcUaClient client, string error, string action); [LoggerMessage(EventId = EventClass + 38, Level = LogLevel.Warning, Message = "{Client}: Namespace index #{Index} changed from {OldValue} to {NewValue}")] public static partial void NamespaceIndexChanged(this ILogger logger, OpcUaClient client, int index, string oldValue, string newValue); [LoggerMessage(EventId = EventClass + 39, Level = LogLevel.Warning, Message = "{Client}: Namespace index #{Index} removed {OldValue}")] public static partial void NamespaceIndexRemoved(this ILogger logger, OpcUaClient client, int index, string oldValue); [LoggerMessage(EventId = EventClass + 40, Level = LogLevel.Warning, Message = "{Client}: Namespace index #{Index} added {NewValue}")] public static partial void NamespaceIndexAdded(this ILogger logger, OpcUaClient client, int index, string newValue); [LoggerMessage(EventId = EventClass + 41, Level = LogLevel.Information, Message = "Channel {Channel} got new token {TokenId} ({Created}).")] public static partial void ChannelGotNewToken(this ILogger logger, string channel, string tokenId, DateTime created); [LoggerMessage(EventId = EventClass + 42, Level = LogLevel.Information, Message = "Channel diagnostics for session {SessionId} updated.")] public static partial void ChannelDiagnosticsUpdated(this ILogger logger, string? sessionId); [LoggerMessage(EventId = EventClass + 43, Level = LogLevel.Information, Message = "{Client}: Session {Name} with {Endpoint} changed from {Previous} to {State}")] public static partial void SessionStateChanged(this ILogger logger, OpcUaClient client, string name, string endpoint, EndpointConnectivityState previous, EndpointConnectivityState state); [LoggerMessage(EventId = EventClass + 44, Level = LogLevel.Error, Message = "{Client}: Exception during state callback")] public static partial void ExceptionDuringStateCallback(this ILogger logger, Exception ex, OpcUaClient client); [LoggerMessage(EventId = EventClass + 1782, Level = LogLevel.Debug, Message = "{Client}: Error, connection to {Endpoint} - leaving state at {Previous}.")] public static partial void ErrorLeavingState(this ILogger logger, OpcUaClient client, string endpoint, EndpointConnectivityState previous); [LoggerMessage(EventId = EventClass + 48, Level = LogLevel.Debug, Message = "{Result} => {State}")] public static partial void ServiceResultToState(this ILogger logger, ServiceResult result, EndpointConnectivityState state); [LoggerMessage(EventId = EventClass + 49, Level = LogLevel.Debug, Message = "{Message} => {State}")] public static partial void ExceptionToState(this ILogger logger, string message, EndpointConnectivityState state); [LoggerMessage(EventId = EventClass + 50, Level = LogLevel.Debug, Message = "{Client}: Successfully closed session {Session}.")] public static partial void SessionClosed(this ILogger logger, OpcUaClient client, OpcUaSession session); [LoggerMessage(EventId = EventClass + 51, Level = LogLevel.Error, Message = "{Client}: Failed to close session {Session}.")] public static partial void SessionCloseFailed(this ILogger logger, Exception ex, OpcUaClient client, OpcUaSession session); [LoggerMessage(EventId = EventClass + 60, Level = LogLevel.Information, Message = "{Context}: Discovery endpoint {DiscoveryUrl} returned endpoints. Selecting endpoint {EndpointUri} " + "with SecurityMode {SecurityMode} and {SecurityPolicy} SecurityPolicyUri from:\n{Endpoints}")] public static partial void DiscoveryEndpointReturnedEndpoints(this ILogger logger, string? context, Uri discoveryUrl, Uri endpointUri, SecurityMode securityMode, string securityPolicy, string endpoints); [LoggerMessage(EventId = EventClass + 61, Level = LogLevel.Information, Message = "{Context}: Endpoint {Endpoint} selected via reverse connect!")] public static partial void EndpointSelectedViaReverseConnect(this ILogger logger, string? context, string endpoint); [LoggerMessage(EventId = EventClass + 62, Level = LogLevel.Information, Message = "{Context}: Endpoint {Endpoint} selected!")] public static partial void EndpointSelected(this ILogger logger, string? context, string endpoint); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaClientManager.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Services { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using BitFaster.Caching.Lru; using Furly.Exceptions; using Furly.Extensions.Serializers; using Furly.Extensions.Utils; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Nito.AsyncEx; using Opc.Ua; using Opc.Ua.Client; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.Metrics; using System.Linq; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; /// /// Client manager /// internal sealed class OpcUaClientManager : IOpcUaClientManager, IEndpointDiscovery, ICertificateServices, IClientDiagnostics, IConnectionServices, IDisposable { /// public event EventHandler? OnConnectionStateChange; /// IReadOnlyList IClientDiagnostics.ChannelDiagnostics => _clients.Values.Select(c => c.LastDiagnostics).ToList(); /// public IReadOnlyList ActiveConnections => _clients.Keys.Select(c => c.Connection).ToList(); /// /// Create kv manager /// /// /// /// /// /// /// /// public OpcUaClientManager(ILoggerFactory loggerFactory, IJsonSerializer serializer, IOpcUaConfiguration configuration, IOptions clientOptions, IOptions subscriptionOptions, TimeProvider? timeProvider = null, IMetricsContext? metrics = null) { _metrics = metrics ?? IMetricsContext.Empty; _timeProvider = timeProvider ?? TimeProvider.System; _clientOptions = clientOptions ?? throw new ArgumentNullException(nameof(clientOptions)); _subscriptionOptions = subscriptionOptions ?? throw new ArgumentNullException(nameof(subscriptionOptions)); _serializer = serializer ?? throw new ArgumentNullException(nameof(serializer)); _loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); _logger = _loggerFactory.CreateLogger(); _reverseConnectManager = new ReverseConnectManager(); _reverseConnectStartException = new Lazy( StartReverseConnectManager, isThreadSafe: true); _configuration.Validate += OnValidate; InitializeMetrics(); } /// public async ValueTask CreateSubscriptionAsync( ConnectionModel connection, SubscriptionModel subscription, ISubscriber callback, CancellationToken ct) { ObjectDisposedException.ThrowIf(_disposed, this); using var client = GetOrAddClient(connection); return await client.RegisterAsync( subscription, callback, ct).ConfigureAwait(false); } /// public async Task TestConnectionAsync( ConnectionModel endpoint, TestConnectionRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNullOrWhiteSpace(endpoint.Endpoint?.Url); var endpointUrl = new Uri(endpoint.Endpoint.Url); try { var endpointDescription = await OpcUaClient.SelectEndpointAsync( _configuration.Value, endpointUrl, null, endpoint.Endpoint.SecurityMode ?? SecurityMode.NotNone, endpoint.Endpoint.SecurityPolicy, _logger, endpoint.Endpoint, ct: ct).ConfigureAwait(false); var endpointConfiguration = EndpointConfiguration.Create( _configuration.Value); var configuredEndpoint = new ConfiguredEndpoint(null, endpointDescription, endpointConfiguration); var userIdentity = await endpoint.User.ToUserIdentityAsync( _configuration.Value).ConfigureAwait(false); using var session = await DefaultSessionFactory.Instance.CreateAsync( _configuration.Value, reverseConnectManager: null, configuredEndpoint, updateBeforeConnect: true, // Update endpoint through discovery checkDomain: false, // Domain must match on connect "Test" + Guid.NewGuid().ToString("N"), 10000, userIdentity, null, ct).ConfigureAwait(false); try { Debug.Assert(session != null); await session.CloseAsync(ct).ConfigureAwait(false); } catch { // We close as a courtesy to the server } return new TestConnectionResponseModel(); } catch (Exception ex) { return new TestConnectionResponseModel { ErrorInfo = ex.ToServiceResultModel() }; } } /// public Task ResetAllConnectionsAsync(CancellationToken ct) { return Task.WhenAll(_clients.Values.Select(c => c.ResetAsync(ct)).ToArray()); } /// public async IAsyncEnumerable GetConnectionDiagnosticsAsync( [EnumeratorCancellation] CancellationToken ct) { foreach (var kv in _clients.ToList()) { SessionDiagnosticsModel? server = null; try { server = await kv.Value.GetSessionDiagnosticsAsync(ct).ConfigureAwait(false); } catch (Exception ex) { _logger.GetDiagnosticsFailed(ex, kv.Value); } yield return new ConnectionDiagnosticsModel { Connection = kv.Key.Connection, // Client = kv.Value.Diagnostics, Server = server }; } } /// public async IAsyncEnumerable WatchChannelDiagnosticsAsync( [EnumeratorCancellation] CancellationToken ct) { var queue = new AsyncProducerConsumerQueue(); _listeners.TryAdd(queue, true); try { // Get all items from buffer var set = new HashSet( _clients.Values.Select(c => c.LastDiagnostics)); foreach (var item in set) { yield return item; } // Dequeue items we have not yet sent from current state from queue // until cancelled while (!ct.IsCancellationRequested) { // Get updates - handle fact that we have already sent the reference var item = await queue.DequeueAsync(ct).ConfigureAwait(false); if (!set.Contains(item)) { yield return item; } } } finally { _listeners.TryRemove(queue, out _); } } /// public async Task> FindEndpointsAsync( Uri discoveryUrl, IReadOnlyList? locales, bool findServersOnNetwork, CancellationToken ct) { var results = new HashSet(); var visitedUris = new HashSet { CreateDiscoveryUri(discoveryUrl.ToString(), 4840) }; var queue = new Queue>>(); var localeIds = locales != null ? new StringCollection(locales) : null; queue.Enqueue(Tuple.Create(discoveryUrl, new List())); ct.ThrowIfCancellationRequested(); while (queue.Count > 0) { var nextServer = queue.Dequeue(); discoveryUrl = nextServer.Item1; var sw = Stopwatch.StartNew(); _logger.FindingEndpoints(discoveryUrl); try { await Retry.Do(_logger, ct, () => DiscoverAsync(discoveryUrl, localeIds, nextServer.Item2, 20000, visitedUris, queue, results, findServersOnNetwork), _ => !ct.IsCancellationRequested, Retry.NoBackoff, kMaxDiscoveryAttempts - 1).ConfigureAwait(false); } catch (Exception ex) { _logger.FindEndpointsException(ex, discoveryUrl); _logger.FindEndpointsFailed(discoveryUrl, ex.Message, sw.Elapsed); return new HashSet(); } ct.ThrowIfCancellationRequested(); _logger.FindingEndpointsCompleted(discoveryUrl, sw.Elapsed); } return results; } /// public async Task GetEndpointCertificateAsync( EndpointModel endpoint, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); if (string.IsNullOrEmpty(endpoint.Url)) { throw new ArgumentException("Endpoint url is missing.", nameof(endpoint)); } var endpointConfiguration = EndpointConfiguration.Create(_configuration.Value); endpointConfiguration.OperationTimeout = 20000; var discoveryUrl = new Uri(endpoint.Url); using var client = DiscoveryClient.Create(discoveryUrl, endpointConfiguration); // Get endpoint descriptions from endpoint url var endpoints = await client.GetEndpointsAsync(new RequestHeader(), client.Endpoint.EndpointUrl, null, null).ConfigureAwait(false); // Match to provided endpoint info var ep = endpoints.Endpoints?.FirstOrDefault(e => e.IsSameAs(endpoint)); if (ep == null) { _logger.NoEndpoints(discoveryUrl); throw new ResourceNotFoundException("Endpoint not found"); } _logger.FoundEndpoint(discoveryUrl); return ep.ServerCertificate.ToCertificateChain(); } /// public async Task ExecuteAsync(ConnectionModel connection, Func> func, RequestHeaderModel? header, CancellationToken ct) { connection = UpdateConnectionFromHeader(connection, header); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Missing endpoint url", nameof(connection)); } using var client = GetOrAddClient(connection); return await client.RunAsync(func, header?.ConnectTimeout, header?.ServiceCallTimeout, ct).ConfigureAwait(false); } /// public IAsyncEnumerable ExecuteAsync(ConnectionModel connection, AsyncEnumerableBase operation, RequestHeaderModel? header, CancellationToken ct) { connection = UpdateConnectionFromHeader(connection, header); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { operation.Dispose(); throw new ArgumentException("Missing endpoint url", nameof(connection)); } return ExecuteAsyncCore(ct); async IAsyncEnumerable ExecuteAsyncCore( [EnumeratorCancellation] CancellationToken ct) { try { using var client = GetOrAddClient(connection); await foreach (var result in client.RunAsync(operation, header?.ConnectTimeout, header?.ServiceCallTimeout, ct).ConfigureAwait(false)) { yield return result; } } finally { operation.Dispose(); } } } /// public async Task AcquireSessionAsync(ConnectionModel connection, RequestHeaderModel? header, CancellationToken ct) { connection = UpdateConnectionFromHeader(connection, header); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Missing endpoint url", nameof(connection)); } using var client = GetOrAddClient(connection); return await client.AcquireAsync(header?.ConnectTimeout, header?.ServiceCallTimeout, ct).ConfigureAwait(false); } /// public void Dispose() { if (!_disposed) { _meter.Dispose(); DisposeAsync().AsTask().GetAwaiter().GetResult(); _reverseConnectManager.Dispose(); _configuration.Validate -= OnValidate; } } /// public async ValueTask DisposeAsync() { if (_disposed) { return; } _disposed = true; _logger.StoppingAllClients(_clients.Count); foreach (var client in _clients) { try { await client.Value.CloseAsync(true).ConfigureAwait(false); } catch (OperationCanceledException) { } catch (Exception ex) { _logger.DisposeClientFailed(ex, client.Key); } } _clients.Clear(); _logger.StoppedAllClients(); } /// /// Perform a single discovery using a discovery url /// /// /// /// /// /// /// /// /// private async Task DiscoverAsync(Uri discoveryUrl, StringCollection? localeIds, IEnumerable caps, int timeout, HashSet visitedUris, Queue>> queue, HashSet result, bool findServersOnNetwork) { var endpointConfiguration = EndpointConfiguration.Create(_configuration.Value); endpointConfiguration.OperationTimeout = timeout; using var client = DiscoveryClient.Create(discoveryUrl, endpointConfiguration); // // Get endpoints from current discovery server // var endpoints = await client.GetEndpointsAsync(new RequestHeader(), client.Endpoint.EndpointUrl, localeIds, null).ConfigureAwait(false); if (!(endpoints?.Endpoints?.Any() ?? false)) { _logger.NoEndpoints(discoveryUrl); return; } _logger.FoundEndpoints(discoveryUrl); foreach (var ep in endpoints.Endpoints.Where(ep => ep.Server.ApplicationType != Opc.Ua.ApplicationType.DiscoveryServer)) { result.Add(new DiscoveredEndpointModel { Description = ep, // Reported AccessibleEndpointUrl = new UriBuilder(ep.EndpointUrl) { Host = discoveryUrl.DnsSafeHost }.ToString(), Capabilities = new HashSet(caps) }); } if (!findServersOnNetwork) { return; } // // Now Find servers on network. This might fail for old lds // as well as reference servers, then we call FindServers... // try { var response = await client.FindServersOnNetworkAsync(new RequestHeader(), 0, 1000, []).ConfigureAwait(false); foreach (var server in response?.Servers ?? []) { var url = CreateDiscoveryUri(server.DiscoveryUrl, discoveryUrl.Port); if (!visitedUris.Contains(url)) { queue.Enqueue(Tuple.Create(discoveryUrl, server.ServerCapabilities.ToList())); visitedUris.Add(url); } } } catch { // Old lds, just continue... _logger.ExtensionNotSupported(discoveryUrl); } // // Call FindServers first to push more unique discovery urls // into the discovery queue // var found = await client.FindServersAsync(new RequestHeader(), client.Endpoint.EndpointUrl, localeIds, null).ConfigureAwait(false); if (found?.Servers != null) { foreach (var server in found.Servers.SelectMany(s => s.DiscoveryUrls)) { var url = CreateDiscoveryUri(server, discoveryUrl.Port); if (!visitedUris.Contains(url)) { queue.Enqueue(Tuple.Create(discoveryUrl, new List())); visitedUris.Add(url); } } } } /// /// Update connection from header /// /// /// /// private static ConnectionModel UpdateConnectionFromHeader(ConnectionModel connection, RequestHeaderModel? header) { if (header == null) { return connection; } if (header.Elevation != null) { connection = connection with { User = header.Elevation, }; } if (header.Locales != null) { connection = connection with { Locales = header.Locales }; } return connection; } /// /// Create discovery url from string /// /// /// private static string CreateDiscoveryUri(string uri, int defaultPort) { var url = new UriBuilder(uri); if (url.Port is 0 or (-1)) { url.Port = defaultPort; } url.Host = url.Host.Trim('.'); url.Path = url.Path.Trim('/'); return url.Uri.ToString(); } /// /// Load kv configuration /// /// /// /// private void OnValidate(CertificateValidator sender, CertificateValidationEventArgs e) { if (e.Accept || e.AcceptAll) { return; } if (e.Error.StatusCode == StatusCodes.BadCertificateUntrusted) { if (_configuration.Value.SecurityConfiguration.AutoAcceptUntrustedCertificates) { _logger.AcceptingUntrustedCert(e.Certificate.Thumbprint, e.Certificate.Subject); e.AcceptAll = true; e.Accept = true; } // Validate thumbprint else if (e.Certificate.RawData != null && !string.IsNullOrWhiteSpace(e.Certificate.Thumbprint) && _clients.Keys.Any(id => id?.Connection?.Endpoint?.Certificate != null && e.Certificate.Thumbprint == id.Connection.Endpoint.Certificate)) { e.Accept = true; _logger.AcceptingUntrustedCertByThumbprint(e.Certificate.Thumbprint, e.Certificate.Subject); // add the certificate to trusted store _configuration.Value.SecurityConfiguration .AddTrustedPeer(e.Certificate.RawData); try { var store = _configuration.Value. SecurityConfiguration.TrustedPeerCertificates.OpenStore(); try { store.DeleteAsync(e.Certificate.Thumbprint); store.AddAsync(e.Certificate); } finally { store.Close(); } } catch (Exception ex) { _logger.AddPeerCertToTrustedStoreFailed(ex, e.Certificate.Thumbprint, e.Certificate.Subject); } } } if (!e.Accept) { _logger.RejectingPeerCert(e.Certificate.Thumbprint, e.Certificate.Subject, e.Error.StatusCode); } } /// /// Get or add new kv /// /// /// private OpcUaClient GetOrAddClient(ConnectionModel connection) { // Lazy start connect manager var reverseConnect = connection.IsReverseConnect(); if (reverseConnect && _reverseConnectStartException.Value != null) { throw _reverseConnectStartException.Value; } // Find client and if not exists create var id = new ConnectionIdentifier(connection); // try to get an existing client var client = _clients.GetOrAdd(id, id => { var client = new OpcUaClient(_configuration.Value, id, _serializer, _loggerFactory, _timeProvider, _metrics, () => OnClientClosedAsync(id), OnConnectionStateChange, reverseConnect ? _reverseConnectManager : null, OnClientConnectionDiagnosticChange, _clientOptions, _subscriptionOptions); _logger.CreatedNewClient(client); return client; }); client.AddRef(); return client; } /// /// Called when the client closes /// /// /// private async Task OnClientClosedAsync(ConnectionIdentifier id) { if (_clients.TryRemove(id, out var client)) { try { await client.CloseAsync(false).ConfigureAwait(false); _logger.ClosedClient(client); } catch (OperationCanceledException) { } catch (Exception ex) { _logger.DisposeClientFailed(ex, id); } } } /// /// Start reverse connect manager service /// /// private Exception? StartReverseConnectManager() { var port = _clientOptions.Value.ReverseConnectPort ?? 4840; try { _reverseConnectManager.StartService(new ReverseConnectClientConfiguration { HoldTime = 120000, WaitTimeout = 120000, ClientEndpoints = [ new ReverseConnectClientEndpoint { EndpointUrl = $"opc.tcp://localhost:{port}" } ] }); return null; } catch (Exception ex) { return ex; } } /// /// Called by clients when their connection information changed /// /// private void OnClientConnectionDiagnosticChange(ChannelDiagnosticModel model) { foreach (var listener in _listeners.Keys) { listener.Enqueue(model); } } /// /// Create metrics /// private void InitializeMetrics() { _meter.CreateObservableUpDownCounter("iiot_edge_publisher_client_count", () => new Measurement(_clients.Count, _metrics.TagList), description: "Number of clients."); } private const int kMaxDiscoveryAttempts = 3; private bool _disposed; private readonly ILogger _logger; private readonly ILoggerFactory _loggerFactory; private readonly TimeProvider _timeProvider; private readonly IOpcUaConfiguration _configuration; private readonly IOptions _clientOptions; private readonly IOptions _subscriptionOptions; private readonly IJsonSerializer _serializer; private readonly ReverseConnectManager _reverseConnectManager; private readonly Lazy _reverseConnectStartException; private readonly ConcurrentDictionary< AsyncProducerConsumerQueue, bool> _listeners = new(); private readonly ConcurrentDictionary _clients = new(); private readonly IMetricsContext _metrics; private readonly Meter _meter = Diagnostics.NewMeter(); } /// /// Source-generated logging definitions for OpcUaClientManager /// internal static partial class OpcUaClientManagerLogging { private const int EventClass = 600; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Error, Message = "Failed to get diagnostics for client {Client}.")] public static partial void GetDiagnosticsFailed(this ILogger logger, Exception ex, OpcUaClient client); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Debug, Message = "Try finding endpoints at {DiscoveryUrl}...")] public static partial void FindingEndpoints(this ILogger logger, Uri discoveryUrl); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Debug, Message = "Exception occurred during FindEndpoints at {DiscoveryUrl}.")] public static partial void FindEndpointsException(this ILogger logger, Exception ex, Uri discoveryUrl); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Error, Message = "Could not find endpoints at {DiscoveryUrl} due to {Error} (after {Elapsed}).")] public static partial void FindEndpointsFailed(this ILogger logger, Uri discoveryUrl, string error, TimeSpan elapsed); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Debug, Message = "Finding endpoints at {DiscoveryUrl} completed in {Elapsed}.")] public static partial void FindingEndpointsCompleted(this ILogger logger, Uri discoveryUrl, TimeSpan elapsed); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Debug, Message = "No endpoints at {DiscoveryUrl}...")] public static partial void NoEndpoints(this ILogger logger, Uri discoveryUrl); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Debug, Message = "Found endpoint at {DiscoveryUrl}...")] public static partial void FoundEndpoint(this ILogger logger, Uri discoveryUrl); [LoggerMessage(EventId = EventClass + 8, Level = LogLevel.Debug, Message = "Found endpoints at {DiscoveryUrl}...")] public static partial void FoundEndpoints(this ILogger logger, Uri discoveryUrl); [LoggerMessage(EventId = EventClass + 9, Level = LogLevel.Debug, Message = "{DiscoveryUrl} does not support ME extension...")] public static partial void ExtensionNotSupported(this ILogger logger, Uri discoveryUrl); [LoggerMessage(EventId = EventClass + 10, Level = LogLevel.Information, Message = "Stopping all {Count} clients...")] public static partial void StoppingAllClients(this ILogger logger, int count); [LoggerMessage(EventId = EventClass + 11, Level = LogLevel.Error, Message = "Unexpected exception disposing client {Client}")] public static partial void DisposeClientFailed(this ILogger logger, Exception ex, ConnectionIdentifier client); [LoggerMessage(EventId = EventClass + 12, Level = LogLevel.Information, Message = "Stopped all clients, current number of clients is 0")] public static partial void StoppedAllClients(this ILogger logger); [LoggerMessage(EventId = EventClass + 13, Level = LogLevel.Warning, Message = "Accepting untrusted peer certificate {Thumbprint}, '{Subject}' " + "due to AutoAccept(UntrustedCertificates) set!")] public static partial void AcceptingUntrustedCert(this ILogger logger, string thumbprint, string subject); [LoggerMessage(EventId = EventClass + 14, Level = LogLevel.Information, Message = "Accepting untrusted peer certificate {Thumbprint}, '{Subject}' " + "since the same thumbprint was specified in the connection!")] public static partial void AcceptingUntrustedCertByThumbprint(this ILogger logger, string thumbprint, string subject); [LoggerMessage(EventId = EventClass + 15, Level = LogLevel.Error, Message = "Failed to add peer certificate {Thumbprint}, '{Subject}' to trusted store")] public static partial void AddPeerCertToTrustedStoreFailed(this ILogger logger, Exception ex, string thumbprint, string subject); [LoggerMessage(EventId = EventClass + 16, Level = LogLevel.Information, Message = "Rejecting peer certificate {Thumbprint}, '{Subject}' because of {Status}.")] public static partial void RejectingPeerCert(this ILogger logger, string thumbprint, string subject, StatusCode status); [LoggerMessage(EventId = EventClass + 17, Level = LogLevel.Information, Message = "{Client}: Created new client.")] public static partial void CreatedNewClient(this ILogger logger, OpcUaClient client); [LoggerMessage(EventId = EventClass + 18, Level = LogLevel.Information, Message = "{Client}: Closed client.")] public static partial void ClosedClient(this ILogger logger, OpcUaClient client); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaClientTagList.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Services { using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; /// /// Connection metric tags /// internal sealed class OpcUaClientTagList : IMetricsContext { /// public TagList TagList { get; } /// /// Parent context /// /// /// public OpcUaClientTagList(ConnectionModel connection, IMetricsContext? parent = null) { if (connection.Endpoint == null) { throw new ArgumentException("Missing endpoint", nameof(connection)); } var existing = parent?.TagList ?? default; var tags = existing.ToDictionary(kv => kv.Key, kv => kv.Value); TagList = new TagList([.. tags]) { new KeyValuePair("endpointUrl", connection.Endpoint.Url), new KeyValuePair("securityMode", connection.Endpoint.SecurityMode) }; if (connection.Group != null && !tags.ContainsKey(Constants.ConnectionGroupTag)) { TagList.Add(Constants.ConnectionGroupTag, connection.Group); } } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaMonitoredItem.Condition.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Services { using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Encoders.PubSub; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Client; using System; using System.Collections.Generic; using System.Data; using System.Diagnostics; using System.Linq; using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; internal abstract partial class OpcUaMonitoredItem { /// /// Condition item /// [DataContract(Namespace = Namespaces.OpcUaXsd)] [KnownType(typeof(DataChangeFilter))] [KnownType(typeof(EventFilter))] [KnownType(typeof(AggregateFilter))] internal class Condition : Event { /// /// Whether timer is enabled /// public bool TimerEnabled { get; set; } /// /// Create condition item /// /// /// /// /// public Condition(ISubscriber owner, EventMonitoredItemModel template, ILogger logger, TimeProvider timeProvider) : base(owner, template, logger, timeProvider) { _snapshotInterval = template.ConditionHandling?.SnapshotInterval ?? throw new ArgumentException("Invalid snapshot interval"); _updateInterval = template.ConditionHandling?.UpdateInterval ?? _snapshotInterval; _lastSentPendingConditions = timeProvider.GetUtcNow(); _conditionHandlingState = new ConditionHandlingState(); } /// /// Copy constructor /// /// /// /// private Condition(Condition item, bool copyEventHandlers, bool copyClientHandle) : base(item, copyEventHandlers, copyClientHandle) { _snapshotInterval = item._snapshotInterval; _updateInterval = item._updateInterval; _conditionHandlingState = item._conditionHandlingState; _lastSentPendingConditions = item._lastSentPendingConditions; if (item.TimerEnabled) { EnableConditionTimer(); } } /// public override MonitoredItem CloneMonitoredItem( bool copyEventHandlers, bool copyClientHandle) { return new Condition(this, copyEventHandlers, copyClientHandle); } /// public override bool Equals(object? obj) { if (obj is not Condition item) { return false; } return base.Equals(item); } /// public override int GetHashCode() { return 38138123 + base.GetHashCode(); } /// public override string ToString() { var str = $"Condition Item '{Template.StartNodeId}'"; if (RemoteId.HasValue) { str += $" with server id {RemoteId} ({(Status?.Created == true ? "" : "not ")}created)"; } return str; } /// protected override void Dispose(bool disposing) { if (disposing) { lock (_timerLock) { _disposed = true; if (_conditionTimer != null) { _conditionTimer.Elapsed -= OnConditionTimerElapsed; _conditionTimer.Dispose(); _conditionTimer = null; } } } base.Dispose(disposing); } /// protected override bool ProcessEventNotification(DateTimeOffset publishTime, EventFieldList eventFields, MonitoredItemNotifications notifications) { Debug.Assert(Valid); Debug.Assert(Template != null); if (_disposed) { return false; } var evFilter = Filter as EventFilter; var eventTypeIndex = evFilter?.SelectClauses.IndexOf( evFilter.SelectClauses .Find(x => x.TypeDefinitionId == ObjectTypeIds.BaseEventType && x.BrowsePath?.FirstOrDefault() == BrowseNames.EventType)); var state = _conditionHandlingState; // now, is this a regular event or RefreshStartEventType/RefreshEndEventType? if (eventTypeIndex.HasValue && eventTypeIndex.Value != -1) { var eventType = eventFields.EventFields[eventTypeIndex.Value].Value as NodeId; if (eventType == ObjectTypeIds.RefreshStartEventType) { // stop the timers during condition refresh DisableConditionTimer(); state.Active.Clear(); _logger.StoppedPendingAlarms(this); return true; } else if (eventType == ObjectTypeIds.RefreshEndEventType) { // restart the timers once condition refresh is done. EnableConditionTimer(); _logger.RestartedPendingAlarms(this); return true; } else if (eventType == ObjectTypeIds.RefreshRequiredEventType) { var noErrorFound = true; Debug.Assert(Subscription != null); // issue a condition refresh to make sure we are in a correct state _logger.IssuingConditionRefresh(this, Template.DisplayName, Subscription.DisplayName); try { Subscription.ConditionRefreshAsync(default).GetAwaiter().GetResult(); // TODO } catch (Exception e) { _logger.ConditionRefreshFailed(this, Template.DisplayName, Subscription.DisplayName, e.Message); noErrorFound = false; } if (noErrorFound) { _logger.ConditionRefreshCompleted(this, Template.DisplayName, Subscription.DisplayName); } return true; } } var monitoredItemNotifications = ToMonitoredItemNotifications( eventFields).ToList(); var conditionIdIndex = state.ConditionIdIndex; var retainIndex = state.RetainIndex; if (conditionIdIndex < monitoredItemNotifications.Count && retainIndex < monitoredItemNotifications.Count) { // Cache conditions var conditionId = monitoredItemNotifications[conditionIdIndex].Value? .Value?.ToString(); if (conditionId != null) { var retain = monitoredItemNotifications[retainIndex].Value? .GetValue(false) ?? false; if (state.Active.ContainsKey(conditionId) && !retain) { state.Active.Remove(conditionId, out _); state.Dirty = true; } else if (retain && !monitoredItemNotifications .All(m => m.Value?.Value == null)) { state.Dirty = true; monitoredItemNotifications.ForEach(n => { n.Value ??= new DataValue(StatusCodes.GoodNoData); // Set SourceTimestamp to publish time n.Value.SourceTimestamp = publishTime.UtcDateTime; }); state.Active.AddOrUpdate(conditionId, monitoredItemNotifications); } } } return true; } /// public override bool MergeWith(OpcUaMonitoredItem item, IOpcUaSession session, out bool metadataChanged) { metadataChanged = false; if (item is not Condition model || !Valid) { return false; } var itemChange = false; if (_snapshotInterval != model._snapshotInterval) { _logger.SnapshotIntervalChanged(this, TimeSpan.FromSeconds(_snapshotInterval).TotalMilliseconds, TimeSpan.FromSeconds(model._snapshotInterval).TotalMilliseconds); _snapshotInterval = model._snapshotInterval; itemChange = true; } if (_updateInterval != model._updateInterval) { _logger.UpdateIntervalChanged(this, TimeSpan.FromSeconds(_updateInterval).TotalMilliseconds, TimeSpan.FromSeconds(model._updateInterval).TotalMilliseconds); _updateInterval = model._updateInterval; itemChange = true; } itemChange |= base.MergeWith(model, session, out metadataChanged); return itemChange; } /// public override bool TryCompleteChanges(Subscription subscription, ref bool applyChanges) { var result = base.TryCompleteChanges(subscription, ref applyChanges); if (!AttachedToSubscription || !result) { DisableConditionTimer(); } else { EnableConditionTimer(); } return result; } /// /// Get event filter /// /// /// /// protected override async ValueTask GetEventFilterAsync(IOpcUaSession session, CancellationToken ct) { var (eventFilter, internalSelectClauses) = await BuildEventFilterAsync(session, ct).ConfigureAwait(false); var conditionHandlingState = InitializeConditionHandlingState( eventFilter, internalSelectClauses); UpdateFieldNames(session, eventFilter, internalSelectClauses); _conditionHandlingState = conditionHandlingState; EnableConditionTimer(); return eventFilter; } /// /// Initialize periodic pending condition handling state /// /// /// /// private static ConditionHandlingState InitializeConditionHandlingState( EventFilter eventFilter, List internalSelectClauses) { var conditionHandlingState = new ConditionHandlingState(); var conditionIdClause = eventFilter.SelectClauses .Find(x => x.TypeDefinitionId == ObjectTypeIds.ConditionType && x.AttributeId == Attributes.NodeId); if (conditionIdClause != null) { conditionHandlingState.ConditionIdIndex = eventFilter.SelectClauses.IndexOf(conditionIdClause); } else { conditionHandlingState.ConditionIdIndex = eventFilter.SelectClauses.Count; var selectClause = new SimpleAttributeOperand() { BrowsePath = [], TypeDefinitionId = ObjectTypeIds.ConditionType, AttributeId = Attributes.NodeId }; eventFilter.SelectClauses.Add(selectClause); internalSelectClauses.Add(selectClause); } var retainClause = eventFilter.SelectClauses .Find(x => x.TypeDefinitionId == ObjectTypeIds.ConditionType && x.BrowsePath?.FirstOrDefault() == BrowseNames.Retain); if (retainClause != null) { conditionHandlingState.RetainIndex = eventFilter.SelectClauses.IndexOf(retainClause); } else { conditionHandlingState.RetainIndex = eventFilter.SelectClauses.Count; var selectClause = new SimpleAttributeOperand( ObjectTypeIds.ConditionType, BrowseNames.Retain); eventFilter.SelectClauses.Add(selectClause); internalSelectClauses.Add(selectClause); } return conditionHandlingState; } /// /// Called when the condition timer fires /// /// /// private void OnConditionTimerElapsed(object? sender, ElapsedEventArgs e) { Debug.Assert(Template != null); var now = TimeProvider.GetUtcNow(); var state = _conditionHandlingState; try { if (!Created) { return; } // is it time to send anything? var sendPendingConditions = now > _lastSentPendingConditions + TimeSpan.FromSeconds(_snapshotInterval); if (!sendPendingConditions && state.Dirty) { sendPendingConditions = now > _lastSentPendingConditions + TimeSpan.FromSeconds(_updateInterval); } if (sendPendingConditions) { SendPendingConditions(); _lastSentPendingConditions = now; } } catch (Exception ex) { _logger.SendPendingConditionsFailed(ex, this); } finally { EnableConditionTimer(); } } /// /// Send pending conditions /// private void SendPendingConditions() { var state = _conditionHandlingState; var notifications = state.Active .Select(entry => entry.Value .Where(n => n.DataSetFieldName != null) .Select(n => n with { }) .ToList()) .ToList(); state.Dirty = false; foreach (var conditionNotification in notifications) { Publish(Owner, MessageType.Condition, conditionNotification, eventTypeName: EventTypeName); } } /// /// Enable timer /// private void EnableConditionTimer() { lock (_timerLock) { if (_disposed) { return; } if (_conditionTimer == null) { _conditionTimer = new(TimeProvider) { AutoReset = false }; _conditionTimer.Elapsed += OnConditionTimerElapsed; _logger.ConditionTimerReEnabled(); } _conditionTimer.Interval = TimeSpan.FromSeconds(1); _conditionTimer.Enabled = true; TimerEnabled = true; } } /// /// Disable timer /// private void DisableConditionTimer() { lock (_timerLock) { if (_conditionTimer != null) { _conditionTimer.Elapsed -= OnConditionTimerElapsed; _conditionTimer.Dispose(); _conditionTimer = null; _logger.ConditionTimerDisabled(); } TimerEnabled = false; } } private sealed class ConditionHandlingState { /// /// Index in the SelectClause array for Condition id field /// public int ConditionIdIndex { get; set; } /// /// Index in the SelectClause array for Retain field /// public int RetainIndex { get; set; } /// /// Has the pending alarms events been updated since las update message? /// public bool Dirty { get; set; } /// /// Cache of the latest events for the pending alarms optionally monitored /// public Dictionary> Active { get; } = []; } private ConditionHandlingState _conditionHandlingState; private DateTimeOffset _lastSentPendingConditions; private int _snapshotInterval; private int _updateInterval; private TimerEx? _conditionTimer; private readonly object _timerLock = new(); private bool _disposed; } } /// /// Source-generated logging definitions for OpcUaMonitoredItem Condition handling /// internal static partial class OpcUaMonitoredItemConditionLogging { private const int EventClass = 1000; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Debug, Message = "{Item}: Stopped pending alarm handling during condition refresh.")] public static partial void StoppedPendingAlarms(this ILogger logger, OpcUaMonitoredItem item); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Debug, Message = "{Item}: Restarted pending alarm handling after condition refresh.")] public static partial void RestartedPendingAlarms(this ILogger logger, OpcUaMonitoredItem item); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Information, Message = "{Item}: Issuing ConditionRefresh for item {Name} on subscription {Subscription} " + "due to receiving first notification.")] public static partial void IssuingConditionRefresh(this ILogger logger, OpcUaMonitoredItem item, string name, string subscription); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Information, Message = "{Item}: ConditionRefresh for item {Name} on subscription {Subscription} " + "failed with error '{Message}'")] public static partial void ConditionRefreshFailed(this ILogger logger, OpcUaMonitoredItem item, string name, string subscription, string message); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Information, Message = "{Item}: ConditionRefresh for item {Name} on subscription {Subscription} has completed")] public static partial void ConditionRefreshCompleted(this ILogger logger, OpcUaMonitoredItem item, string name, string subscription); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Debug, Message = "{Item}: Changing shptshot interval from {Old} to {New}")] public static partial void SnapshotIntervalChanged(this ILogger logger, OpcUaMonitoredItem item, double old, double @new); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Debug, Message = "{Item}: Changing update interval from {Old} to {New}")] public static partial void UpdateIntervalChanged(this ILogger logger, OpcUaMonitoredItem item, double old, double @new); [LoggerMessage(EventId = EventClass + 8, Level = LogLevel.Error, Message = "{Item}: SendPendingConditions failed.")] public static partial void SendPendingConditionsFailed(this ILogger logger, Exception ex, OpcUaMonitoredItem item); [LoggerMessage(EventId = EventClass + 9, Level = LogLevel.Debug, Message = "Re-enabled condition timer.")] public static partial void ConditionTimerReEnabled(this ILogger logger); [LoggerMessage(EventId = EventClass + 10, Level = LogLevel.Debug, Message = "Disabled condition timer.")] public static partial void ConditionTimerDisabled(this ILogger logger); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaMonitoredItem.CyclicRead.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Services { using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Client; using System; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; internal abstract partial class OpcUaMonitoredItem { /// /// Cyclic read items are part of a subscription but disabled. They /// execute through the client sampler periodically (at the configured /// sampling rate). /// [DataContract(Namespace = Namespaces.OpcUaXsd)] [KnownType(typeof(DataChangeFilter))] [KnownType(typeof(EventFilter))] [KnownType(typeof(AggregateFilter))] internal sealed class CyclicRead : DataChange { /// /// Create cyclic read item /// /// /// /// /// /// public CyclicRead(ISubscriber owner, OpcUaClient client, DataMonitoredItemModel template, ILogger logger, TimeProvider timeProvider) : base(owner, template with { // Always ensure item is disabled MonitoringMode = Publisher.Models.MonitoringMode.Disabled }, logger, timeProvider) { _client = client; LastReceivedValue = new MonitoredItemNotification { Value = new DataValue(StatusCodes.GoodNoData) }; } /// /// Copy constructor /// /// /// /// private CyclicRead(CyclicRead item, bool copyEventHandlers, bool copyClientHandle) : base(item, copyEventHandlers, copyClientHandle) { _client = item._client; _subscriptionName = item._subscriptionName; if (_subscriptionName != null) { EnsureSamplerRunning(); } } /// public override MonitoredItem CloneMonitoredItem( bool copyEventHandlers, bool copyClientHandle) { return new CyclicRead(this, copyEventHandlers, copyClientHandle); } /// protected override void Dispose(bool disposing) { // Cleanup var sampler = _sampler; lock (_lock) { _disposed = true; _sampler = null; } sampler?.DisposeAsync().AsTask().GetAwaiter().GetResult(); base.Dispose(disposing); } /// public override bool Equals(object? obj) { if (obj is not CyclicRead cyclicRead) { return false; } if (_client != cyclicRead._client) { return false; } if ((Template.SamplingInterval ?? TimeSpan.FromSeconds(1)) != (cyclicRead.Template.SamplingInterval ?? TimeSpan.FromSeconds(1))) { return false; } if ((Template.CyclicReadMaxAge ?? TimeSpan.Zero) != (cyclicRead.Template.CyclicReadMaxAge ?? TimeSpan.Zero)) { return false; } return base.Equals(obj); } /// public override int GetHashCode() { var hashCode = base.GetHashCode(); hashCode = (hashCode * -1521134295) + _client.GetHashCode(); hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode( Template.SamplingInterval ?? TimeSpan.FromSeconds(1)); hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode( Template.CyclicReadMaxAge ?? TimeSpan.Zero); return hashCode; } /// public override string ToString() { return $"Cyclic read '{Template.StartNodeId}' every {Template.SamplingInterval ?? TimeSpan.FromSeconds(1)}"; } /// public override bool MergeWith(OpcUaMonitoredItem item, IOpcUaSession session, out bool metadataChanged) { if (item is not CyclicRead) { metadataChanged = false; return false; } return base.MergeWith(item, session, out metadataChanged); } /// public override Func? FinalizeMonitoringModeChange => async _ => { if (!AttachedToSubscription) { // Disabling sampling await StopSamplerAsync().ConfigureAwait(false); } else { Debug.Assert(Subscription != null); _subscriptionName = Subscription.DisplayName; Debug.Assert(MonitoringMode == MonitoringMode.Disabled); EnsureSamplerRunning(); } }; /// /// Ensure sampler is started /// private void EnsureSamplerRunning() { lock (_lock) { if (_disposed) { return; } if (_sampler == null) { Debug.Assert(_subscriptionName != null); _sampler = _client.Sample( TimeSpan.FromMilliseconds(SamplingInterval), Template.CyclicReadMaxAge ?? TimeSpan.Zero, new ReadValueId { AttributeId = AttributeId, IndexRange = IndexRange, NodeId = ResolvedNodeId }, _subscriptionName, ClientHandle); _logger.ItemRegistered(this); } } } /// /// Stop sampling /// /// private async Task StopSamplerAsync() { var sampler = _sampler; lock (_lock) { _sampler = null; _subscriptionName = null; } if (sampler != null) { await sampler.DisposeAsync().ConfigureAwait(false); _logger.ItemUnregistered(this); } } /// public override bool TryGetMonitoredItemNotifications(DateTimeOffset timestamp, IEncodeable encodeablePayload, MonitoredItemNotifications notifications) { if (!Valid || encodeablePayload is not SampledDataValueModel cyclicReadNotification) { return false; } LastReceivedValue = cyclicReadNotification; LastReceivedTime = LastActivityTime = TimeProvider.GetUtcNow(); notifications.Add(Owner, ToMonitoredItemNotification( cyclicReadNotification.Value, cyclicReadNotification.Overflow)); return true; } private readonly OpcUaClient _client; private IAsyncDisposable? _sampler; private string? _subscriptionName; private readonly object _lock = new(); private bool _disposed; } } /// /// Source-generated logging definitions for OpcUaMonitoredItem CyclicRead handling /// internal static partial class OpcUaMonitoredItemCyclicReadLogging { private const int EventClass = 1050; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Debug, Message = "Item {Item} successfully registered with sampler.")] public static partial void ItemRegistered(this ILogger logger, OpcUaMonitoredItem.CyclicRead item); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Debug, Message = "Item {Item} unregistered from sampler.")] public static partial void ItemUnregistered(this ILogger logger, OpcUaMonitoredItem.CyclicRead item); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaMonitoredItem.DataChange.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Services { using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Client; using Opc.Ua.Client.ComplexTypes; using Opc.Ua.Extensions; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; internal abstract partial class OpcUaMonitoredItem { /// /// Data item /// [DataContract(Namespace = Namespaces.OpcUaXsd)] [KnownType(typeof(DataChangeFilter))] [KnownType(typeof(EventFilter))] [KnownType(typeof(AggregateFilter))] internal class DataChange : OpcUaMonitoredItem { /// public override (string NodeId, string[] Path, UpdateNodeId Update)? Resolve => Template.RelativePath != null && (TheResolvedNodeId == Template.StartNodeId || string.IsNullOrEmpty(TheResolvedNodeId)) ? (Template.StartNodeId, Template.RelativePath.ToArray(), (v, context) => TheResolvedNodeId = NodeId = v.AsString(context, Template.NamespaceFormat) ?? string.Empty) : null; /// public override (string NodeId, UpdateNodeId Update)? Register => Template.RegisterRead == true && !_registeredForReading && !string.IsNullOrEmpty(TheResolvedNodeId) ? (TheResolvedNodeId, (v, context) => { NodeId = v.AsString(context, Template.NamespaceFormat) ?? string.Empty; // We only want to register the node once for reading inside a session _registeredForReading = true; } ) : null; /// public override (string NodeId, UpdateString Update)? GetDisplayName => Template.FetchDataSetFieldName == true && Template.DataSetFieldName != null && !string.IsNullOrEmpty(NodeId) ? (NodeId, v => Template = Template with { DataSetFieldName = v }) : null; /// public override (string NodeId, UpdateRelativePath Update)? GetPath => TheResolvedRelativePath == null && !string.IsNullOrEmpty(TheResolvedNodeId) ? (TheResolvedNodeId, (path, context) => { if (path == null) { NodeId = string.Empty; } TheResolvedRelativePath = path; } ) : null; /// /// Monitored item as data /// public DataMonitoredItemModel Template { get; protected internal set; } /// /// Resolved node id /// protected string TheResolvedNodeId { get; private set; } /// /// Relative path /// protected RelativePath? TheResolvedRelativePath { get; private set; } /// /// Field identifier either configured or randomly assigned /// for data change items. /// public Guid DataSetClassFieldId => Template?.DataSetClassFieldId == Guid.Empty ? _fieldId : Template?.DataSetClassFieldId ?? Guid.Empty; /// /// Create wrapper /// /// /// /// /// public DataChange(ISubscriber owner, DataMonitoredItemModel template, ILogger logger, TimeProvider timeProvider) : base(owner, logger, template.StartNodeId, timeProvider) { Template = template; // // We also track the resolved node id so we distinguish it // from the registered and thus effective node id // TheResolvedNodeId = template.StartNodeId; } /// /// Copy constructor /// /// /// /// protected DataChange(DataChange item, bool copyEventHandlers, bool copyClientHandle) : base(item, copyEventHandlers, copyClientHandle) { TheResolvedNodeId = item.TheResolvedNodeId; TheResolvedRelativePath = item.TheResolvedRelativePath; Template = item.Template; _fieldId = item._fieldId; _skipDataChangeNotification = item._skipDataChangeNotification; _registeredForReading = false; } /// public override MonitoredItem CloneMonitoredItem( bool copyEventHandlers, bool copyClientHandle) { return new DataChange(this, copyEventHandlers, copyClientHandle); } /// public override bool Equals(object? obj) { if (obj is not DataChange dataItem) { return false; } if ((Template.DataSetFieldId ?? string.Empty) != (dataItem.Template.DataSetFieldId ?? string.Empty)) { return false; } if (!Template.RelativePath.SequenceEqualsSafe( dataItem.Template.RelativePath)) { return false; } if (Template.StartNodeId != dataItem.Template.StartNodeId) { return false; } if (Template.RegisterRead != dataItem.Template.RegisterRead) { return false; } if (Template.IndexRange != dataItem.Template.IndexRange) { return false; } if (Template.AttributeId != dataItem.Template.AttributeId) { return false; } return true; } /// public override int GetHashCode() { var hashCode = 81523234 + base.GetHashCode(); hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode( Template.DataSetFieldId ?? string.Empty); hashCode = (hashCode * -1521134295) + EqualityComparer>.Default.GetHashCode( Template.RelativePath ?? Array.Empty()); hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(Template.StartNodeId); hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(Template.IndexRange ?? string.Empty); hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(Template.RegisterRead ?? false); hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode( Template.AttributeId ?? NodeAttribute.NodeId); return hashCode; } /// public override string ToString() { var str = $"Data Item '{Template.StartNodeId}'"; if (RemoteId.HasValue) { str += $" with server id {RemoteId} ({(Status?.Created == true ? "" : "not ")}created)"; } return str; } /// public override async ValueTask GetMetaDataAsync(IOpcUaSession session, ComplexTypeSystem? typeSystem, List fields, NodeIdDictionary dataTypes, CancellationToken ct) { var nodeId = NodeId.ToExpandedNodeId(session.MessageContext); if (Opc.Ua.NodeId.IsNull(nodeId)) { // Failed. return; } try { var node = await session.LruNodeCache.GetNodeAsync(nodeId, ct).ConfigureAwait(false); if (node is VariableNode variable) { await AddVariableFieldAsync(fields, dataTypes, session, typeSystem, variable, Template.DisplayName, (Uuid)DataSetClassFieldId, ct).ConfigureAwait(false); } } catch (Exception ex) when (ex is not OperationCanceledException) { _logger.GetMetadataFailed(this, Template.DisplayName, nodeId, ex.Message); } } /// public override bool AddTo(Subscription subscription, IOpcUaSession session, out bool metadataChanged) { var nodeId = NodeId.ToNodeId(session.MessageContext); if (Opc.Ua.NodeId.IsNull(nodeId)) { metadataChanged = false; return false; } DisplayName = Template.DisplayName; AttributeId = (uint)(Template.AttributeId ?? (NodeAttribute)Attributes.Value); IndexRange = Template.IndexRange; StartNodeId = nodeId; MonitoringMode = Template.MonitoringMode.ToStackType() ?? Opc.Ua.MonitoringMode.Reporting; SamplingInterval = (int)Template.SamplingInterval. GetValueOrDefault(TimeSpan.FromSeconds(1)).TotalMilliseconds; UpdateQueueSize(subscription, Template); Filter = Template.DataChangeFilter.ToStackModel() ?? (MonitoringFilter?)Template.AggregateFilter.ToStackModel( session.MessageContext); DiscardOldest = !(Template.DiscardNew ?? false); Valid = true; if (!TrySetSkipFirst(Template.SkipFirst ?? false)) { Debug.Fail("Unexpected: Failed to set skip first setting."); } return base.AddTo(subscription, session, out metadataChanged); } /// public override bool TryCompleteChanges(Subscription subscription, ref bool applyChanges) { var msgContext = subscription.Session?.MessageContext; if (Filter is AggregateFilter && Status?.FilterResult is AggregateFilterResult afr && msgContext != null) { if (Status.Error != null && ServiceResult.IsNotGood(Status.Error)) { _logger.AggregateFilterError(afr.AsJson(msgContext), this); } else if (_logger.IsEnabled(LogLevel.Debug)) { _logger.AggregateFilterApplied(afr.AsJson(msgContext), this); } } return base.TryCompleteChanges(subscription, ref applyChanges); } /// public override bool TryGetMonitoredItemNotifications( DateTimeOffset publishTime, IEncodeable evt, MonitoredItemNotifications notifications) { if (evt is not MonitoredItemNotification min) { _logger.UnexpectedEventType(this, evt?.GetType().Name ?? "null"); return false; } if (!base.TryGetMonitoredItemNotifications(publishTime, evt, notifications)) { return false; } return ProcessMonitoredItemNotification(publishTime, min, notifications); } /// public override bool MergeWith(OpcUaMonitoredItem item, IOpcUaSession session, out bool metadataChanged) { metadataChanged = false; if (item is not DataChange model || !Valid) { return false; } var itemChange = MergeWith(Template, model.Template, out var updated, out metadataChanged); if (itemChange) { Template = updated; } if ((Template.SamplingInterval ?? TimeSpan.FromSeconds(1)) != (Template.SamplingInterval ?? TimeSpan.FromSeconds(1))) { _logger.SamplingIntervalChanged(this, Template.SamplingInterval.GetValueOrDefault( TimeSpan.FromSeconds(1)).TotalMilliseconds, model.Template.SamplingInterval.GetValueOrDefault( TimeSpan.FromSeconds(1)).TotalMilliseconds); Template = Template with { SamplingInterval = model.Template.SamplingInterval }; SamplingInterval = (int)Template.SamplingInterval.GetValueOrDefault( TimeSpan.FromSeconds(1)).TotalMilliseconds; itemChange = true; } if (Template.DataSetClassFieldId != model.Template.DataSetClassFieldId) { var previous = DataSetClassFieldId; Template = Template with { DataSetClassFieldId = model.Template.DataSetClassFieldId }; _logger.DatasetClassFieldIdChanged(this, previous, DataSetClassFieldId); metadataChanged = true; } // Update change filter if (!model.Template.DataChangeFilter.IsSameAs(Template.DataChangeFilter)) { Template = Template with { DataChangeFilter = model.Template.DataChangeFilter }; _logger.DataChangeFilterChanged(this); Filter = Template.DataChangeFilter.ToStackModel(); itemChange = true; } // Update AggregateFilter else if (!model.Template.AggregateFilter.IsSameAs(Template.AggregateFilter)) { Template = Template with { AggregateFilter = model.Template.AggregateFilter }; _logger.AggregateChangeFilterChanged(this); Filter = Template.AggregateFilter.ToStackModel(session.MessageContext); itemChange = true; } if ((model.Template.SkipFirst ?? false) != (Template.SkipFirst ?? false)) { Template = Template with { SkipFirst = model.Template.SkipFirst }; if (model.TrySetSkipFirst(model.Template.SkipFirst ?? false)) { _logger.SkipFirstChanged(this, model.Template.SkipFirst); } else { _logger.SkipFirstAlreadySet(this); } // No change, just updated internal state } return itemChange; } /// protected override bool OnSamplingIntervalOrQueueSizeRevised( bool samplingIntervalChanged, bool queueSizeChanged) { Debug.Assert(Subscription != null); var applyChanges = base.OnSamplingIntervalOrQueueSizeRevised( samplingIntervalChanged, queueSizeChanged); if (samplingIntervalChanged) { applyChanges |= UpdateQueueSize(Subscription, Template); } return applyChanges; } /// public override bool TryGetLastMonitoredItemNotifications( MonitoredItemNotifications notifications) { SkipMonitoredItemNotification(); // Key frames should always be sent return base.TryGetLastMonitoredItemNotifications(notifications); } /// protected override IEnumerable CreateTriggeredItems( ILoggerFactory factory, OpcUaClient client) { if (Template.TriggeredItems != null) { return Create(client, Template.TriggeredItems.Select(i => (Owner, i)), factory, TimeProvider); } return []; } /// protected override bool TryGetErrorMonitoredItemNotifications( StatusCode statusCode, MonitoredItemNotifications notifications) { notifications.Add(Owner, ToMonitoredItemNotification(new DataValue(statusCode))); return true; } /// /// Process monitored item notification /// /// /// /// /// protected virtual bool ProcessMonitoredItemNotification(DateTimeOffset publishTime, MonitoredItemNotification monitoredItemNotification, MonitoredItemNotifications notifications) { if (!SkipMonitoredItemNotification()) { notifications.Add(Owner, ToMonitoredItemNotification( monitoredItemNotification.Value)); return true; } return false; } /// /// Convert to monitored item notifications /// /// /// /// protected MonitoredItemNotificationModel ToMonitoredItemNotification( DataValue dataValue, int? overflow = null) { Debug.Assert(Valid); Debug.Assert(Template != null); return new MonitoredItemNotificationModel { Id = Template.DataSetFieldId ?? string.Empty, DataSetFieldName = Template.DisplayName, DataSetName = Template.DisplayName, NodeId = NodeId, PathFromRoot = TheResolvedRelativePath, Value = dataValue, Flags = 0, Overflow = overflow ?? (dataValue.StatusCode.Overflow ? 1 : 0), SequenceNumber = GetNextSequenceNumber() }; } /// /// Whether to skip monitored item notification /// /// public virtual bool SkipMonitoredItemNotification() { // This will update that first value has been processed. var last = Interlocked.Exchange(ref _skipDataChangeNotification, (int)SkipSetting.DontSkip); return last == (int)SkipSetting.Skip; } /// /// Try set skip first setting. We allow updating while first value /// is not yet processed, which is the case if skip setting is unconfigured. /// /// /// public bool TrySetSkipFirst(bool skipFirst) { if (skipFirst) { // We only allow updating first skip setting while unconfigured return Interlocked.CompareExchange(ref _skipDataChangeNotification, (int)SkipSetting.Skip, (int)SkipSetting.Unconfigured) == (int)SkipSetting.Unconfigured; } // Unset skip setting if it was configured but first message was not yet processed Interlocked.CompareExchange(ref _skipDataChangeNotification, (int)SkipSetting.Unconfigured, (int)SkipSetting.Skip); return true; } enum SkipSetting { /// Default DontSkip, /// Skip first value Skip, /// Configuration not applied yet Unconfigured, } private volatile int _skipDataChangeNotification = (int)SkipSetting.Unconfigured; private readonly Guid _fieldId = Guid.NewGuid(); private bool _registeredForReading; } } /// /// Source-generated logging definitions for OpcUaMonitoredItem DataChange handling /// internal static partial class OpcUaMonitoredItemDataChangeLogging { private const int EventClass = 1060; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Debug, Message = "{Item}: Failed to get meta data for field {Field} with node {NodeId} with message {Message}.")] public static partial void GetMetadataFailed(this ILogger logger, OpcUaMonitoredItem.DataChange item, string field, ExpandedNodeId nodeId, string message); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Error, Message = "Aggregate filter applied with result {Result} for {Item}")] public static partial void AggregateFilterError(this ILogger logger, string result, OpcUaMonitoredItem.DataChange item); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Debug, SkipEnabledCheck = true, Message = "Aggregate filter applied with result {Result} for {Item}")] public static partial void AggregateFilterApplied(this ILogger logger, string result, OpcUaMonitoredItem.DataChange item); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Debug, Message = "{Item}: Unexpected event type {Type} received.")] public static partial void UnexpectedEventType(this ILogger logger, OpcUaMonitoredItem.DataChange item, string type); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Debug, Message = "{Item}: Changing sampling interval from {Old} to {New}")] public static partial void SamplingIntervalChanged(this ILogger logger, OpcUaMonitoredItem.DataChange item, double old, double @new); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Debug, Message = "{Item}: Changing dataset class field id from {Old} to {New}")] public static partial void DatasetClassFieldIdChanged(this ILogger logger, OpcUaMonitoredItem.DataChange item, Guid old, Guid @new); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Debug, Message = "{Item}: Changing data change filter.")] public static partial void DataChangeFilterChanged(this ILogger logger, OpcUaMonitoredItem.DataChange item); [LoggerMessage(EventId = EventClass + 8, Level = LogLevel.Debug, Message = "{Item}: Changing aggregate change filter.")] public static partial void AggregateChangeFilterChanged(this ILogger logger, OpcUaMonitoredItem.DataChange item); [LoggerMessage(EventId = EventClass + 9, Level = LogLevel.Debug, Message = "{Item}: Setting skip first setting to {New}")] public static partial void SkipFirstChanged(this ILogger logger, OpcUaMonitoredItem.DataChange item, bool? @new); [LoggerMessage(EventId = EventClass + 10, Level = LogLevel.Information, Message = "{Item}: Tried to set SkipFirst but it was set previously or first value was already processed.")] public static partial void SkipFirstAlreadySet(this ILogger logger, OpcUaMonitoredItem.DataChange item); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaMonitoredItem.Event.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Services { using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Client; using Opc.Ua.Client.ComplexTypes; using Opc.Ua.Extensions; using System; using System.Collections.Generic; using System.Data; using System.Diagnostics; using System.Linq; using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; internal abstract partial class OpcUaMonitoredItem { /// /// Event monitored item /// [DataContract(Namespace = Namespaces.OpcUaXsd)] [KnownType(typeof(DataChangeFilter))] [KnownType(typeof(EventFilter))] [KnownType(typeof(AggregateFilter))] internal class Event : OpcUaMonitoredItem { /// public override (string NodeId, UpdateString Update)? GetDisplayName => Template.FetchDataSetFieldName == true && !string.IsNullOrEmpty(Template.EventFilter.TypeDefinitionId) && Template.DataSetFieldName == null ? (Template.EventFilter.TypeDefinitionId!, v => Template = Template with { DataSetFieldName = v }) : null; /// public override (string NodeId, string[] Path, UpdateNodeId Update)? Resolve => Template.RelativePath != null && (NodeId == Template.StartNodeId || string.IsNullOrEmpty(NodeId)) ? (Template.StartNodeId, Template.RelativePath.ToArray(), (v, context) => NodeId = v.AsString(context, Template.NamespaceFormat) ?? string.Empty) : null; /// public override (string NodeId, UpdateRelativePath Update)? GetPath => TheResolvedRelativePath == null && !string.IsNullOrEmpty(NodeId) ? (NodeId, (path, context) => { if (path == null) { NodeId = string.Empty; } TheResolvedRelativePath = path; } ) : null; /// public override string? EventTypeName => Template.DisplayName; /// /// Relative path /// protected RelativePath? TheResolvedRelativePath { get; private set; } /// /// Monitored item as event /// public EventMonitoredItemModel Template { get; protected internal set; } /// /// List of field names. /// public List<(string? Name, Guid DataSetFieldId)> Fields { get; } = []; /// /// Create wrapper /// /// /// /// /// public Event(ISubscriber owner, EventMonitoredItemModel template, ILogger logger, TimeProvider timeProvider) : base(owner, logger, template.StartNodeId, timeProvider) { Template = template; } /// /// Copy constructor /// /// /// /// protected Event(Event item, bool copyEventHandlers, bool copyClientHandle) : base(item, copyEventHandlers, copyClientHandle) { Fields = item.Fields; TheResolvedRelativePath = item.TheResolvedRelativePath; Template = item.Template; } /// public override MonitoredItem CloneMonitoredItem( bool copyEventHandlers, bool copyClientHandle) { return new Event(this, copyEventHandlers, copyClientHandle); } /// public override bool Equals(object? obj) { if (obj is not Event eventItem) { return false; } if ((Template.DataSetFieldId ?? string.Empty) != (eventItem.Template.DataSetFieldId ?? string.Empty)) { return false; } if ((Template.DataSetFieldName ?? string.Empty) != (eventItem.Template.DataSetFieldName ?? string.Empty)) { return false; } if (!Template.RelativePath.SequenceEqualsSafe(eventItem.Template.RelativePath)) { return false; } if (Template.StartNodeId != eventItem.Template.StartNodeId) { return false; } if (Template.AttributeId != eventItem.Template.AttributeId) { return false; } return true; } /// public override int GetHashCode() { var hashCode = 423444443 + base.GetHashCode(); hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode( Template.DataSetFieldName ?? string.Empty); hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode( Template.DataSetFieldId ?? string.Empty); hashCode = (hashCode * -1521134295) + EqualityComparer>.Default.GetHashCode( Template.RelativePath ?? Array.Empty()); hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode( Template.StartNodeId); hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode( Template.AttributeId ?? NodeAttribute.NodeId); return hashCode; } /// public override string ToString() { var str = $"Event Item '{Template.StartNodeId}'"; if (RemoteId.HasValue) { str += $" with server id {RemoteId} ({(Status?.Created == true ? "" : "not ")}created)"; } return str; } /// public override async ValueTask GetMetaDataAsync(IOpcUaSession session, ComplexTypeSystem? typeSystem, List fields, NodeIdDictionary dataTypes, CancellationToken ct) { if (Filter is not EventFilter eventFilter) { return; } try { Debug.Assert(Fields.Count == eventFilter.SelectClauses.Count); for (var i = 0; i < eventFilter.SelectClauses.Count; i++) { var selectClause = eventFilter.SelectClauses[i]; var fieldName = Fields[i].Name; if (fieldName == null) { continue; } var dataSetClassFieldId = (Uuid)Fields[i].DataSetFieldId; var targetNode = await FindNodeWithBrowsePathAsync(session, selectClause.BrowsePath, selectClause.TypeDefinitionId, ct).ConfigureAwait(false); if (targetNode is VariableNode variable) { await AddVariableFieldAsync(fields, dataTypes, session, typeSystem, variable, fieldName, dataSetClassFieldId, ct).ConfigureAwait(false); } else { // Should this happen? await AddVariableFieldAsync(fields, dataTypes, session, typeSystem, new VariableNode { DataType = (int)BuiltInType.Variant }, fieldName, dataSetClassFieldId, ct).ConfigureAwait(false); } } } catch (Exception e) { _logger.GetMetadataFailed(e, this); throw; } } public override Func? FinalizeAddTo => async (session, ct) => Filter = await GetEventFilterAsync(session, ct).ConfigureAwait(false); /// public override bool AddTo(Subscription subscription, IOpcUaSession session, out bool metadataChanged) { var nodeId = NodeId.ToNodeId(session.MessageContext); if (Opc.Ua.NodeId.IsNull(nodeId)) { metadataChanged = false; return false; } DisplayName = Template.DisplayName; AttributeId = (uint)(Template.AttributeId ?? (NodeAttribute)Attributes.EventNotifier); MonitoringMode = Template.MonitoringMode.ToStackType() ?? Opc.Ua.MonitoringMode.Reporting; StartNodeId = nodeId; SamplingInterval = 0; UpdateQueueSize(subscription, Template); DiscardOldest = !(Template.DiscardNew ?? false); Valid = true; return base.AddTo(subscription, session, out metadataChanged); } /// public override bool MergeWith(OpcUaMonitoredItem item, IOpcUaSession session, out bool metadataChanged) { metadataChanged = false; if (item is not Event model || !Valid) { return false; } var itemChange = MergeWith(Template, model.Template, out var updated, out metadataChanged); if (itemChange) { Template = updated; } // Update event filter if (!model.Template.EventFilter.IsSameAs(Template.EventFilter)) { Template = Template with { EventFilter = model.Template.EventFilter }; _logger.ChangingEventFilter(this); metadataChanged = true; itemChange = true; } return itemChange; } /// public override bool TryCompleteChanges(Subscription subscription, ref bool applyChanges) { var msgContext = subscription.Session?.MessageContext; if (Status?.FilterResult is EventFilterResult evr && msgContext != null) { if (Status.Error != null && ServiceResult.IsNotGood(Status.Error)) { _logger.EventFilterAppliedWithError(evr.AsJson(msgContext), this); } else if (_logger.IsEnabled(LogLevel.Debug)) { _logger.EventFilterApplied(evr.AsJson(msgContext), this); } } return base.TryCompleteChanges(subscription, ref applyChanges); } /// protected override bool OnSamplingIntervalOrQueueSizeRevised( bool samplingIntervalChanged, bool queueSizeChanged) { Debug.Assert(Subscription != null); var applyChanges = base.OnSamplingIntervalOrQueueSizeRevised( samplingIntervalChanged, queueSizeChanged); if (samplingIntervalChanged && Status.SamplingInterval != 0) { // Not necessary as sampling interval will likely always stay 0 applyChanges |= UpdateQueueSize(Subscription, Template); } return applyChanges; } public override Func? FinalizeMergeWith => async (session, ct) => Filter = await GetEventFilterAsync(session, ct).ConfigureAwait(false); /// public override bool TryGetMonitoredItemNotifications(DateTimeOffset publishTime, IEncodeable evt, MonitoredItemNotifications notifications) { if (evt is EventFieldList eventFields && base.TryGetMonitoredItemNotifications(publishTime, evt, notifications)) { return ProcessEventNotification(publishTime, eventFields, notifications); } return false; } /// protected override IEnumerable CreateTriggeredItems( ILoggerFactory factory, OpcUaClient client) { if (Template.TriggeredItems != null) { return Create(client, Template.TriggeredItems.Select(i => (Owner, i)), factory, TimeProvider); } return []; } /// protected override bool TryGetErrorMonitoredItemNotifications( StatusCode statusCode, MonitoredItemNotifications notifications) { foreach (var (Name, _) in Fields) { if (Name == null) { continue; } notifications.Add(Owner, new MonitoredItemNotificationModel { Id = Template.Id ?? string.Empty, DataSetName = Template.DisplayName, DataSetFieldName = Name, NodeId = Template.StartNodeId, PathFromRoot = TheResolvedRelativePath, Value = new DataValue(statusCode), Flags = MonitoredItemSourceFlags.Error, SequenceNumber = GetNextSequenceNumber() }); } return true; } /// /// Process event notifications /// /// /// /// /// protected virtual bool ProcessEventNotification(DateTimeOffset timestamp, EventFieldList eventFields, MonitoredItemNotifications notifications) { // Send notifications as event foreach (var n in ToMonitoredItemNotifications(eventFields) .Where(n => n.DataSetFieldName != null)) { notifications.Add(Owner, n); } return true; } /// /// Convert to monitored item notifications /// /// /// protected IEnumerable ToMonitoredItemNotifications( EventFieldList eventFields) { Debug.Assert(Valid); Debug.Assert(Template != null); // // Important - so the event is properly batched during encoding the same // sequence number must be used for all monitored item notifications ! // var sequenceNumber = GetNextSequenceNumber(); if (Fields.Count >= eventFields.EventFields.Count) { for (var i = 0; i < eventFields.EventFields.Count; i++) { yield return new MonitoredItemNotificationModel { Id = Template.Id ?? string.Empty, DataSetName = Template.DisplayName, DataSetFieldName = Fields[i].Name, NodeId = Template.StartNodeId, PathFromRoot = TheResolvedRelativePath, Flags = 0, Value = new DataValue(eventFields.EventFields[i]), SequenceNumber = sequenceNumber }; } } } /// /// Get event filter /// /// /// /// protected virtual async ValueTask GetEventFilterAsync(IOpcUaSession session, CancellationToken ct) { var (eventFilter, internalSelectClauses) = await BuildEventFilterAsync(session, ct).ConfigureAwait(false); UpdateFieldNames(session, eventFilter, internalSelectClauses); return eventFilter; } /// /// Update field names /// /// /// /// protected void UpdateFieldNames(IOpcUaSession session, EventFilter eventFilter, List internalSelectClauses) { // let's loop thru the final set of select clauses and setup the field names used Fields.Clear(); foreach (var selectClause in eventFilter.SelectClauses) { if (!internalSelectClauses.Any(x => x == selectClause)) { var fieldName = string.Empty; var definedSelectClause = Template.EventFilter.SelectClauses? .ElementAtOrDefault(eventFilter.SelectClauses.IndexOf(selectClause)); if (!string.IsNullOrEmpty(definedSelectClause?.DisplayName)) { fieldName = definedSelectClause.DisplayName; } else if (selectClause.BrowsePath != null && selectClause.BrowsePath.Count != 0) { // Format as relative path string fieldName = selectClause.BrowsePath .Select(q => q.AsString(session.MessageContext, Template.NamespaceFormat)) .Aggregate((a, b) => $"{a}/{b}"); } if (fieldName.Length == 0 && selectClause.TypeDefinitionId == ObjectTypeIds.ConditionType && selectClause.AttributeId == Attributes.NodeId) { fieldName = "ConditionId"; } Fields.Add((fieldName, Guid.NewGuid())); } else { // if a field's nameis empty, it's not written to the output Fields.Add((null, Guid.Empty)); } } Debug.Assert(Fields.Count == eventFilter.SelectClauses.Count); } /// /// Build event filter /// /// /// /// protected async ValueTask<(EventFilter, List)> BuildEventFilterAsync( IOpcUaSession session, CancellationToken ct) { EventFilter? eventFilter; if (!string.IsNullOrEmpty(Template.EventFilter.TypeDefinitionId)) { eventFilter = await GetSimpleEventFilterAsync(session, ct).ConfigureAwait(false); } else { eventFilter = session.Codec.Decode(Template.EventFilter); } // let's keep track of the internal fields we add so that they don't show up in the output var selectClauses = new List(); if (!eventFilter.SelectClauses.Any(x => x.TypeDefinitionId == ObjectTypeIds.BaseEventType && x.BrowsePath?.FirstOrDefault() == BrowseNames.EventType)) { var selectClause = new SimpleAttributeOperand(ObjectTypeIds.BaseEventType, BrowseNames.EventType); eventFilter.SelectClauses.Add(selectClause); selectClauses.Add(selectClause); } if (_logger.IsEnabled(LogLevel.Debug)) { _logger.GeneratedEventFilter(this, eventFilter.AsJson(session.MessageContext)); } return (eventFilter, selectClauses); } /// /// Builds select clause and where clause by using OPC UA reflection /// /// /// /// private async ValueTask GetSimpleEventFilterAsync(IOpcUaSession session, CancellationToken ct) { Debug.Assert(Template != null); var typeDefinitionId = Template.EventFilter.TypeDefinitionId.ToNodeId( session.MessageContext); var nodes = new List(); NodeId? superType = null; var typeDefinitionNode = await session.LruNodeCache.GetNodeAsync(typeDefinitionId, ct).ConfigureAwait(false); nodes.Insert(0, typeDefinitionNode); while (true) { superType = await session.LruNodeCache.GetSuperTypeAsync(nodes[0].NodeId, ct) .ConfigureAwait(false); if (Opc.Ua.NodeId.IsNull(superType)) { break; } typeDefinitionNode = await session.LruNodeCache.GetNodeAsync(superType, ct).ConfigureAwait(false); nodes.Insert(0, typeDefinitionNode); } var fieldNames = new List(); foreach (var node in nodes) { await ParseFieldsAsync(session, fieldNames, node, string.Empty, ct).ConfigureAwait(false); } fieldNames = [.. fieldNames .Distinct() .OrderBy(x => x.Name)]; var eventFilter = new EventFilter(); // Let's add ConditionId manually first if event is derived from ConditionType if (nodes.Any(x => x.NodeId == ObjectTypeIds.ConditionType)) { eventFilter.SelectClauses.Add(new SimpleAttributeOperand() { BrowsePath = [], TypeDefinitionId = ObjectTypeIds.ConditionType, AttributeId = Attributes.NodeId }); } foreach (var fieldName in fieldNames) { var selectClause = new SimpleAttributeOperand() { TypeDefinitionId = ObjectTypeIds.BaseEventType, AttributeId = Attributes.Value, BrowsePath = fieldName.Name .Split('|') .Select(x => new QualifiedName(x, fieldName.NamespaceIndex)) .ToArray() }; eventFilter.SelectClauses.Add(selectClause); } eventFilter.WhereClause = new ContentFilter(); eventFilter.WhereClause.Push(FilterOperator.OfType, typeDefinitionId); return eventFilter; } /// /// Find node by browse path /// /// /// /// /// /// private static async ValueTask FindNodeWithBrowsePathAsync(IOpcUaSession session, QualifiedNameCollection browsePath, NodeId nodeId, CancellationToken ct) { INode? found = null; foreach (var browseName in browsePath) { found = null; while (found == null) { found = await session.LruNodeCache.GetNodeAsync(nodeId, ct).ConfigureAwait(false); // // Get all hierarchical references of the node and match browse name // var references = await session.LruNodeCache.GetReferencesAsync(nodeId, ReferenceTypeIds.HierarchicalReferences, false, true, ct).ConfigureAwait(false); foreach (var reference in references) { var target = await session.LruNodeCache.GetNodeAsync(reference.NodeId, ct).ConfigureAwait(false); if (target?.BrowseName == browseName) { found = target; break; } } if (found == null) { // Try super type nodeId = await session.LruNodeCache.GetSuperTypeAsync(nodeId, ct).ConfigureAwait(false); if (Opc.Ua.NodeId.IsNull(nodeId)) { // Nothing can be found since there is no more super type return null; } } } nodeId = ExpandedNodeId.ToNodeId(found.NodeId, session.MessageContext.NamespaceUris); } return found; } /// /// Get all the fields of a type definition node to build the /// select clause. /// /// /// /// /// /// protected static async ValueTask ParseFieldsAsync(IOpcUaSession session, List fieldNames, INode node, string browsePathPrefix, CancellationToken ct) { var references = await session.LruNodeCache.GetReferencesAsync(node.NodeId, ReferenceTypeIds.HasComponent, false, true, ct).ConfigureAwait(false); foreach (var reference in references) { var componentNode = await session.LruNodeCache.GetNodeAsync(reference.NodeId, ct).ConfigureAwait(false); if (componentNode.NodeClass == Opc.Ua.NodeClass.Variable) { var fieldName = browsePathPrefix + componentNode.BrowseName.Name; fieldNames.Add(new QualifiedName( fieldName, componentNode.BrowseName.NamespaceIndex)); await ParseFieldsAsync(session, fieldNames, componentNode, $"{fieldName}|", ct).ConfigureAwait(false); } } references = await session.LruNodeCache.GetReferencesAsync(node.NodeId, ReferenceTypeIds.HasProperty, false, false, ct).ConfigureAwait(false); foreach (var reference in references) { var propertyNode = await session.LruNodeCache.GetNodeAsync(reference.NodeId, ct).ConfigureAwait(false); var fieldName = browsePathPrefix + propertyNode.BrowseName.Name; fieldNames.Add(new QualifiedName( fieldName, propertyNode.BrowseName.NamespaceIndex)); } } } } /// /// Source-generated logging definitions for OpcUaMonitoredItem Event handling /// internal static partial class OpcUaMonitoredItemEventLogging { private const int EventClass = 1080; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Debug, Message = "{Item}: Failed to get metadata for event.")] public static partial void GetMetadataFailed(this ILogger logger, Exception ex, OpcUaMonitoredItem item); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Debug, Message = "{Item}: Changing event filter.")] public static partial void ChangingEventFilter(this ILogger logger, OpcUaMonitoredItem item); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Error, Message = "Event filter applied with result {Result} for {Item}")] public static partial void EventFilterAppliedWithError(this ILogger logger, string result, OpcUaMonitoredItem item); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Debug, SkipEnabledCheck = true, Message = "Event filter applied with result {Result} for {Item}")] public static partial void EventFilterApplied(this ILogger logger, string result, OpcUaMonitoredItem item); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Debug, SkipEnabledCheck = true, Message = "Generated event filter for {Item}: '{Filter}'")] public static partial void GeneratedEventFilter(this ILogger logger, OpcUaMonitoredItem item, string filter); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaMonitoredItem.Heartbeat.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Services { using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Encoders.PubSub; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Client; using System; using System.Diagnostics; using System.Linq; using System.Runtime.Serialization; using System.Threading; internal abstract partial class OpcUaMonitoredItem { /// /// /// Data monitored item with heartbeat handling. If no data is sent /// within the heartbeat interval the previously received data is /// sent instead. Heartbeat is not a cyclic read. /// /// /// Heartbeat is now implemented as a watchdog of the notification /// which is reset every time a new value arrives. This is different /// from past implementation where the keep alive was driving heartbeats. /// This caused issues and was ineffective due to the use of the value /// cache on the subscription object caching _all_ values received. /// /// [DataContract(Namespace = Namespaces.OpcUaXsd)] [KnownType(typeof(DataChangeFilter))] [KnownType(typeof(EventFilter))] [KnownType(typeof(AggregateFilter))] internal sealed class Heartbeat : DataChange { /// /// Whether timer is enabled /// public bool TimerEnabled { get; set; } /// /// Create data item with heartbeat /// /// /// /// /// public Heartbeat(ISubscriber owner, DataMonitoredItemModel dataTemplate, ILogger logger, TimeProvider timeProvider) : base(owner, dataTemplate, logger, timeProvider) { _heartbeatInterval = dataTemplate.HeartbeatInterval ?? dataTemplate.SamplingInterval ?? TimeSpan.FromSeconds(1); _heartbeatBehavior = dataTemplate.HeartbeatBehavior ?? HeartbeatBehavior.WatchdogLKV; } /// /// Copy constructor /// /// /// /// private Heartbeat(Heartbeat item, bool copyEventHandlers, bool copyClientHandle) : base(item, copyEventHandlers, copyClientHandle) { _heartbeatInterval = item._heartbeatInterval; _heartbeatBehavior = item._heartbeatBehavior; if (item.TimerEnabled) { EnableHeartbeatTimer(); } } /// public override MonitoredItem CloneMonitoredItem( bool copyEventHandlers, bool copyClientHandle) { return new Heartbeat(this, copyEventHandlers, copyClientHandle); } /// public override bool Equals(object? obj) { if (obj is not Heartbeat) { return false; } return base.Equals(obj); } /// public override int GetHashCode() { return HashCode.Combine(base.GetHashCode(), nameof(Heartbeat)); } /// public override string ToString() { var str = $"Data Item '{Template.StartNodeId}' " + $"(with {Template.HeartbeatBehavior ?? HeartbeatBehavior.WatchdogLKV} Heartbeat) "; if (RemoteId.HasValue) { str += $" with server id {RemoteId} ({(Status?.Created == true ? "" : "not ")}created)"; } return str; } /// protected override void Dispose(bool disposing) { if (disposing) { lock (_timerLock) { _disposed = true; if (_heartbeatTimer != null) { _heartbeatTimer.Elapsed -= SendHeartbeatNotifications; _heartbeatTimer.Dispose(); _heartbeatTimer = null; } } } base.Dispose(disposing); } /// protected override bool ProcessMonitoredItemNotification(DateTimeOffset publishTime, MonitoredItemNotification monitoredItemNotification, MonitoredItemNotifications notifications) { Debug.Assert(Valid); var result = base.ProcessMonitoredItemNotification(publishTime, monitoredItemNotification, notifications); if (!_disposed && (_heartbeatBehavior & HeartbeatBehavior.PeriodicLKV) == 0) { EnableHeartbeatTimer(); } return result; } /// public override bool MergeWith(OpcUaMonitoredItem item, IOpcUaSession session, out bool metadataChanged) { metadataChanged = false; if (item is not Heartbeat model || !Valid) { return false; } var itemChange = false; if (_heartbeatInterval != model._heartbeatInterval) { _logger.HeartbeatIntervalChanged(this, _heartbeatInterval, model._heartbeatInterval); _heartbeatInterval = model._heartbeatInterval; itemChange = true; } if (_heartbeatBehavior != model._heartbeatBehavior) { _logger.HeartbeatBehaviorChanged(this, _heartbeatBehavior, model._heartbeatBehavior); _heartbeatBehavior = model._heartbeatBehavior; itemChange = true; } itemChange |= base.MergeWith(model, session, out metadataChanged); return itemChange; } /// public override bool TryCompleteChanges(Subscription subscription, ref bool applyChanges) { if (_disposed) { _logger.ItemMovedToAnotherSubscription(this); return false; } var result = base.TryCompleteChanges(subscription, ref applyChanges); { var lkg = (_heartbeatBehavior & HeartbeatBehavior.WatchdogLKG) == HeartbeatBehavior.WatchdogLKG; if (!AttachedToSubscription || (!result && lkg)) { // Stop heartbeat DisableHeartbeatTimer(); } else { Debug.Assert(AttachedToSubscription); EnableHeartbeatTimer(); } } return result; } /// public override bool TryGetMonitoredItemNotifications(DateTimeOffset publishTime, IEncodeable evt, MonitoredItemNotifications notifications) { _lastSequenceNumber = GetNextSequenceNumber(); if (!_disposed && (_heartbeatBehavior & HeartbeatBehavior.PeriodicLKV) == 0) { EnableHeartbeatTimer(); } return base.TryGetMonitoredItemNotifications(publishTime, evt, notifications); } /// public override bool SkipMonitoredItemNotification() { var dropValue = (_heartbeatBehavior & HeartbeatBehavior.Reserved) != 0; return dropValue || base.SkipMonitoredItemNotification(); } /// public override void NotifySessionConnectionState(bool disconnected) { // // We change the reference here - we cloned the value and if it has been // updated while we are doing this, a new value will be in in place and we // should be connected again or we would not have received it. // var lastValue = LastReceivedValue as MonitoredItemNotification; if (lastValue?.Value != null) { if (disconnected) { _lastStatusCode = lastValue.Value.StatusCode; if (IsGoodDataValue(lastValue.Value)) { lastValue.Value.StatusCode = StatusCodes.UncertainNoCommunicationLastUsableValue; } else { lastValue.Value.StatusCode = StatusCodes.BadNoCommunication; } } else if (_lastStatusCode.HasValue) { lastValue.Value.StatusCode = _lastStatusCode.Value; _lastStatusCode = null; // This is safe as we are called from the client thread } } } /// /// TODO: What is a Good value? Right now we say that it must either be full good or /// have a value and not a bad status code (to cover Good_, and Uncertain_ as well) /// /// /// private static bool IsGoodDataValue(DataValue? value) { if (value == null) { return false; } return value.StatusCode == StatusCodes.Good || (value.WrappedValue != Variant.Null && !StatusCode.IsBad(value.StatusCode)); } /// /// Send heartbeat /// /// /// private void SendHeartbeatNotifications(object? sender, ElapsedEventArgs e) { if (!Valid) { return; } if (!AttachedToSubscription) { _logger.MissingSubscription(this); return; } var lastSequenceNumber = _lastSequenceNumber; var lastNotification = LastReceivedValue as MonitoredItemNotification; if ((_heartbeatBehavior & HeartbeatBehavior.WatchdogLKG) == HeartbeatBehavior.WatchdogLKG && !IsGoodDataValue(lastNotification?.Value)) { // Currently no last known good value (LKG) to send _logger.NoLastKnownGoodValue(this); return; } var lastValue = lastNotification?.Value; if (lastValue == null && ServiceResult.IsNotGood(Status.Error)) { lastValue = new DataValue(Status.Error?.StatusCode ?? StatusCodes.BadNotConnected); } if (lastValue == null) { // Currently no last known value (LKV) to send _logger.NoLastKnownValue(this); return; } if ((_heartbeatBehavior & HeartbeatBehavior.WatchdogLKVWithUpdatedTimestamps) == HeartbeatBehavior.WatchdogLKVWithUpdatedTimestamps) { // Adjust to the diff between now and received if desired // Should not be possible that last value received is null, nevertheless. var diffTime = LastReceivedTime.HasValue ? e.SignalTime - LastReceivedTime.Value : TimeSpan.Zero; lastValue = new DataValue(lastValue) { SourceTimestamp = lastValue.SourceTimestamp == DateTime.MinValue ? DateTime.MinValue : lastValue.SourceTimestamp.Add(diffTime), ServerTimestamp = lastValue.ServerTimestamp == DateTime.MinValue ? DateTime.MinValue : lastValue.ServerTimestamp.Add(diffTime) }; } // If last value is null create a error value. var heartbeat = new MonitoredItemNotificationModel { Id = Template.Id, DataSetFieldName = Template.DisplayName, DataSetName = Template.DisplayName, NodeId = TheResolvedNodeId, PathFromRoot = TheResolvedRelativePath, Value = lastValue, Flags = MonitoredItemSourceFlags.Heartbeat, SequenceNumber = lastSequenceNumber }; if (lastSequenceNumber != _lastSequenceNumber) { // New value came in while running the timer callback - no need to send heartbeat return; } Publish(Owner, MessageType.DeltaFrame, heartbeat.YieldReturn().ToList(), diagnosticsOnly: (_heartbeatBehavior & HeartbeatBehavior.WatchdogLKVDiagnosticsOnly) == HeartbeatBehavior.WatchdogLKVDiagnosticsOnly, timestamp: e.SignalTime); } /// /// Enable timer /// private void EnableHeartbeatTimer() { lock (_timerLock) { if (_disposed) { return; } if (_heartbeatTimer == null) { _heartbeatTimer = new(TimeProvider) { AutoReset = true }; _heartbeatTimer.Elapsed += SendHeartbeatNotifications; _logger.HeartbeatTimerEnabled(); } _heartbeatTimer.Interval = _heartbeatInterval; _heartbeatTimer.Enabled = true; TimerEnabled = true; } } /// /// Disable timer /// private void DisableHeartbeatTimer() { lock (_timerLock) { if (_heartbeatTimer != null) { _heartbeatTimer.Elapsed -= SendHeartbeatNotifications; _heartbeatTimer.Dispose(); _heartbeatTimer = null; _logger.HeartbeatTimerDisabled(); } TimerEnabled = false; } } private TimerEx? _heartbeatTimer; private HeartbeatBehavior _heartbeatBehavior; private TimeSpan _heartbeatInterval; private StatusCode? _lastStatusCode; private uint _lastSequenceNumber; private readonly Lock _timerLock = new(); private bool _disposed; } } /// /// Source-generated logging definitions for OpcUaMonitoredItem Heartbeat handling /// internal static partial class OpcUaMonitoredItemHeartbeatLogging { private const int EventClass = 1180; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Debug, Message = "{Item}: Changing heartbeat from {Old} to {New}")] public static partial void HeartbeatIntervalChanged(this ILogger logger, OpcUaMonitoredItem item, TimeSpan old, TimeSpan @new); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Debug, Message = "{Item}: Changing heartbeat behavior from {Old} to {New}")] public static partial void HeartbeatBehaviorChanged(this ILogger logger, OpcUaMonitoredItem item, HeartbeatBehavior old, HeartbeatBehavior @new); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Error, Message = "{Item}: Item was moved to another subscription and the timer is handled by the new subscription now.")] public static partial void ItemMovedToAnotherSubscription(this ILogger logger, OpcUaMonitoredItem item); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Debug, Message = "Disabled heartbeat timer")] public static partial void HeartbeatTimerDisabled(this ILogger logger); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Information, Message = "{Item}: No last known good value to send.")] public static partial void NoLastKnownGoodValue(this ILogger logger, OpcUaMonitoredItem item); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Information, Message = "{Item}: No last known value to send.")] public static partial void NoLastKnownValue(this ILogger logger, OpcUaMonitoredItem item); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Debug, Message = "Enabled heartbeat timer")] public static partial void HeartbeatTimerEnabled(this ILogger logger); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaMonitoredItem.ModelChange.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Services { using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Encoders.PubSub; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Client; using Opc.Ua.Client.ComplexTypes; using Opc.Ua.Extensions; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; internal abstract partial class OpcUaMonitoredItem { /// /// Model Change item /// [DataContract(Namespace = Namespaces.OpcUaXsd)] internal class ModelChangeEventItem : OpcUaMonitoredItem { /// /// Monitored item as event /// public MonitoredAddressSpaceModel Template { get; protected internal set; } /// /// Create model change item /// /// /// /// /// /// public ModelChangeEventItem(ISubscriber owner, MonitoredAddressSpaceModel template, OpcUaClient client, ILogger logger, TimeProvider timeProvider) : base(owner, logger, template.StartNodeId, timeProvider) { Template = template; _client = client; _fields = GetEventFields().ToArray(); } /// /// Copy constructor /// /// /// /// private ModelChangeEventItem(ModelChangeEventItem item, bool copyEventHandlers, bool copyClientHandle) : base(item, copyEventHandlers, copyClientHandle) { Template = item.Template; _client = item._client; _fields = item._fields; } /// public override MonitoredItem CloneMonitoredItem( bool copyEventHandlers, bool copyClientHandle) { return new ModelChangeEventItem(this, copyEventHandlers, copyClientHandle); } /// protected override void Dispose(bool disposing) { // Cleanup var browser = _browser; lock (_lock) { _disposed = true; _browser = null; if (browser != null) { browser.OnReferenceChange -= OnReferenceChange; browser.OnNodeChange -= OnNodeChange; browser.CloseAsync().AsTask().GetAwaiter().GetResult(); } } base.Dispose(disposing); } /// public override bool Equals(object? obj) { if (obj is not ModelChangeEventItem modelChange) { return false; } if ((Template.DataSetFieldId ?? string.Empty) != (modelChange.Template.DataSetFieldId ?? string.Empty)) { return false; } if ((Template.DataSetFieldName ?? string.Empty) != (modelChange.Template.DataSetFieldName ?? string.Empty)) { return false; } if (_client != modelChange._client) { return false; } return true; } /// public override int GetHashCode() { var hashCode = 435243663 + base.GetHashCode(); hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode( Template.DataSetFieldName ?? string.Empty); hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode( Template.DataSetFieldId ?? string.Empty); hashCode = (hashCode * -1521134295) + _client.GetHashCode(); return hashCode; } /// public override string ToString() { var str = "Model Change Item"; if (RemoteId.HasValue) { str += $" with server id {RemoteId} ({(Status?.Created == true ? "" : "not ")}created)"; } return str; } /// public override bool MergeWith(OpcUaMonitoredItem item, IOpcUaSession session, out bool metadataChanged) { metadataChanged = false; if (item is not ModelChangeEventItem || !Valid) { return false; } return true; } /// public override ValueTask GetMetaDataAsync(IOpcUaSession session, ComplexTypeSystem? typeSystem, List fields, NodeIdDictionary dataTypes, CancellationToken ct) { fields.AddRange(_fields); return ValueTask.CompletedTask; } /// public override Func? FinalizeCompleteChanges => async _ => { if (!AttachedToSubscription) { await StopBrowserAsync().ConfigureAwait(false); } else { EnsureBrowserStarted(); } }; /// public override bool AddTo(Subscription subscription, IOpcUaSession session, out bool metadataChanged) { var nodeId = NodeId.ToNodeId(session.MessageContext); if (Opc.Ua.NodeId.IsNull(nodeId)) { metadataChanged = false; return false; } DisplayName = Template.DisplayName; AttributeId = Attributes.EventNotifier; MonitoringMode = Opc.Ua.MonitoringMode.Reporting; StartNodeId = nodeId; SamplingInterval = 0; UpdateQueueSize(subscription, Template); Filter = GetEventFilter(); DiscardOldest = !(Template.DiscardNew ?? false); Valid = true; return base.AddTo(subscription, session, out metadataChanged); static MonitoringFilter GetEventFilter() { var eventFilter = new EventFilter(); eventFilter.SelectClauses.Add(new SimpleAttributeOperand() { BrowsePath = [BrowseNames.EventType], TypeDefinitionId = ObjectTypeIds.BaseModelChangeEventType, AttributeId = Attributes.NodeId }); eventFilter.SelectClauses.Add(new SimpleAttributeOperand() { BrowsePath = [BrowseNames.Changes], TypeDefinitionId = ObjectTypeIds.GeneralModelChangeEventType, AttributeId = Attributes.Value }); eventFilter.WhereClause = new ContentFilter(); eventFilter.WhereClause.Push(FilterOperator.OfType, ObjectTypeIds.BaseModelChangeEventType); return eventFilter; } } /// public override bool TryGetMonitoredItemNotifications(DateTimeOffset publishTime, IEncodeable evt, MonitoredItemNotifications notifications) { if (evt is not EventFieldList eventFields || !base.TryGetMonitoredItemNotifications(publishTime, evt, notifications)) { return false; } // Rebrowse and find changes or just process and send the changes Debug.Assert(Valid); Debug.Assert(Template != null); var evFilter = Filter as EventFilter; var eventTypeIndex = evFilter?.SelectClauses.IndexOf( evFilter.SelectClauses .Find(x => x.TypeDefinitionId == ObjectTypeIds.BaseEventType && x.BrowsePath?.FirstOrDefault() == BrowseNames.EventType)); if (eventTypeIndex.HasValue && eventTypeIndex.Value != -1) { var eventType = eventFields.EventFields[eventTypeIndex.Value].Value as NodeId; if (eventType == ObjectTypeIds.GeneralModelChangeEventType) { // Find what changed and refresh only that // return true; } else { Debug.Assert(eventType == ObjectTypeIds.BaseModelChangeEventType); } } // The model changed, trigger Rebrowse EnsureBrowserStarted(); _browser?.Rebrowse(); return true; } /// protected override bool TryGetErrorMonitoredItemNotifications( StatusCode statusCode, MonitoredItemNotifications notifications) { return true; } /// protected override IEnumerable CreateTriggeredItems( ILoggerFactory factory, OpcUaClient client) { if (Template.TriggeredItems != null) { return Create(client, Template.TriggeredItems.Select(i => (Owner, i)), factory, TimeProvider); } return []; } /// protected override bool OnSamplingIntervalOrQueueSizeRevised( bool samplingIntervalChanged, bool queueSizeChanged) { Debug.Assert(Subscription != null); var applyChanges = base.OnSamplingIntervalOrQueueSizeRevised( samplingIntervalChanged, queueSizeChanged); if (samplingIntervalChanged && Status.SamplingInterval != 0) { // Not necessary as sampling interval will likely always stay 0 applyChanges |= UpdateQueueSize(Subscription, Template); } return applyChanges; } /// /// Called when node changed /// /// /// private void OnNodeChange(object? sender, Change e) { Publish(Owner, MessageType.Event, CreateEvent(_nodeChangeType, e).ToList(), eventTypeName: EventTypeName); } /// /// Called when reference changes /// /// /// private void OnReferenceChange(object? sender, Change e) { Publish(Owner, MessageType.Event, CreateEvent(_refChangeType, e).ToList(), eventTypeName: EventTypeName); } /// /// Create the event /// /// /// /// /// private IEnumerable CreateEvent(ExpandedNodeId eventType, Change changeFeedNotification) where T : class { for (var i = 0; i < _fields.Length; i++) { Variant? value = null; var field = _fields[i]; switch (i) { case 0: value = new Variant((Uuid)Guid.NewGuid()); break; case 1: value = eventType; break; case 2: value = new Variant(changeFeedNotification.Source); break; case 3: value = new Variant(changeFeedNotification.Timestamp.UtcDateTime); break; case 4: value = changeFeedNotification.ChangedItem == null ? Variant.Null : new Variant(changeFeedNotification.ChangedItem); break; } if (value == null) { continue; } yield return new MonitoredItemNotificationModel { Id = Template.Id ?? string.Empty, DataSetName = Template.DisplayName, DataSetFieldName = field.Name, PathFromRoot = changeFeedNotification.PathFromRoot, NodeId = Template.StartNodeId, Value = new DataValue(value.Value), Flags = MonitoredItemSourceFlags.ModelChanges, SequenceNumber = changeFeedNotification.SequenceNumber }; } } private static IEnumerable GetEventFields() { yield return Create(BrowseNames.EventId, builtInType: BuiltInType.ByteString); yield return Create(BrowseNames.EventType, builtInType: BuiltInType.NodeId); yield return Create(BrowseNames.SourceNode, builtInType: BuiltInType.NodeId); yield return Create(BrowseNames.Time, builtInType: BuiltInType.NodeId); yield return Create("Change", builtInType: BuiltInType.ExtensionObject); static PublishedFieldMetaDataModel Create(string fieldName, NodeId? dataType = null, BuiltInType builtInType = BuiltInType.ExtensionObject) { return new PublishedFieldMetaDataModel { Id = (Uuid)Guid.NewGuid(), DataType = "i=" + (uint)builtInType, Name = fieldName, ValueRank = ValueRanks.Scalar, // ArrayDimensions = BuiltInType = (byte)builtInType }; } } /// /// Start browser /// private void EnsureBrowserStarted() { lock (_lock) { if (_disposed) { return; } // Start the browser if (_browser == null && Subscription != null) { _browser = _client.Browse(Template.RebrowsePeriod ?? TimeSpan.FromHours(12), Subscription.DisplayName); _browser.OnReferenceChange += OnReferenceChange; _browser.OnNodeChange += OnNodeChange; _logger.ItemRegistered(this); } } } /// /// Stop browser /// /// private async Task StopBrowserAsync() { // Stop the browser IOpcUaBrowser? browser; lock (_lock) { browser = _browser; if (browser != null) { browser.OnReferenceChange -= OnReferenceChange; browser.OnNodeChange -= OnNodeChange; } _browser = null; } if (browser != null) { await browser.CloseAsync().ConfigureAwait(false); _logger.ItemUnregistered(this); } } private static readonly ExpandedNodeId _refChangeType = new("ReferenceChange", "http://www.microsoft.com/opc-publisher"); private static readonly ExpandedNodeId _nodeChangeType = new("NodeChange", "http://www.microsoft.com/opc-publisher"); private readonly PublishedFieldMetaDataModel[] _fields; private readonly OpcUaClient _client; private readonly Lock _lock = new(); private IOpcUaBrowser? _browser; private bool _disposed; } } /// /// Source-generated logging definitions for OpcUaMonitoredItem ModelChange handling /// internal static partial class OpcUaMonitoredItemModelChangeLogging { private const int EventClass = 1130; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Information, Message = "Item {Item} registered with browser.")] public static partial void ItemRegistered(this ILogger logger, OpcUaMonitoredItem.ModelChangeEventItem item); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Information, Message = "Item {Item} unregistered from browser.")] public static partial void ItemUnregistered(this ILogger logger, OpcUaMonitoredItem.ModelChangeEventItem item); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaMonitoredItem.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Services { using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Encoders.PubSub; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Client; using Opc.Ua.Client.ComplexTypes; using Opc.Ua.Extensions; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; /// /// Update display name /// /// public delegate void UpdateString(string displayName); /// /// Update node id /// /// /// public delegate void UpdateNodeId(NodeId nodeId, IServiceMessageContext messageContext); /// /// Update relative path /// /// /// public delegate void UpdateRelativePath(RelativePath path, IServiceMessageContext messageContext); /// /// Monitored item /// internal abstract partial class OpcUaMonitoredItem : MonitoredItem, IDisposable { /// /// Assigned monitored item id on server /// public uint? RemoteId => Created ? Status.Id : null; /// /// The item is valid once added to the subscription. Contract: /// The item will be invalid until the subscription calls /// /// to add it to the subscription. After removal the item /// is still Valid, but not Created. The item is /// again invalid after is /// called. /// public bool Valid { get; protected internal set; } /// /// Item is good /// public bool IsGood => Created && StatusCode.IsGood(StatusCode); /// /// Item is bad /// public bool IsBad => !Created || StatusCode.IsBad(StatusCode); /// /// Item is late /// public bool IsLate { get; private set; } /// /// Status code /// public StatusCode StatusCode => Status == null ? StatusCodes.BadNotConnected : (Status.Error?.StatusCode ?? StatusCodes.Good); /// /// Event name /// public virtual string? EventTypeName { get; } /// /// The owner of the item that is to be notified of changes /// public ISubscriber Owner { get; } /// /// Whether the item is part of a subscription or not /// public bool AttachedToSubscription => Subscription != null; /// /// Registered read node updater. If this property is null then /// the node does not need to be registered. /// public virtual (string NodeId, UpdateNodeId Update)? Register => null; /// /// Get the relative path from root for the node. This is called /// after the node is resolved but not yet registered /// public virtual (string NodeId, UpdateRelativePath Update)? GetPath => null; /// /// Get the display name for the node. This is called after /// the node is resolved and registered as applicable. /// public virtual (string NodeId, UpdateString Update)? GetDisplayName => null; /// /// Resolve relative path first. If this returns null /// the relative path either does not exist or we let /// subscription take care of resolving the path. /// public virtual (string NodeId, string[] Path, UpdateNodeId Update)? Resolve => null; /// /// Effective node id /// protected string NodeId { get; set; } /// /// Time provider to use /// protected TimeProvider TimeProvider { get; } /// /// Last saved value /// public IEncodeable? LastReceivedValue { get; private set; } /// /// Last value received /// public DateTimeOffset? LastReceivedTime { get; private set; } /// /// Last keep alive sent or value received /// public DateTimeOffset LastActivityTime { get; set; } /// /// Error already reported /// public bool ErrorReported { get; set; } /// /// Create item /// /// /// /// /// protected OpcUaMonitoredItem(ISubscriber owner, ILogger logger, string nodeId, TimeProvider timeProvider) { Owner = owner; NodeId = nodeId; TimeProvider = timeProvider; LastActivityTime = timeProvider.GetUtcNow(); _logger = logger; } /// /// Copy constructor /// /// /// /// protected OpcUaMonitoredItem(OpcUaMonitoredItem item, bool copyEventHandlers, bool copyClientHandle) : base(item, copyEventHandlers, copyClientHandle) { Owner = item.Owner; NodeId = item.NodeId; TimeProvider = item.TimeProvider; _logger = item._logger; LastReceivedTime = item.LastReceivedTime; LastActivityTime = item.LastActivityTime; LastReceivedValue = item.LastReceivedValue; Valid = item.Valid; } /// public override abstract MonitoredItem CloneMonitoredItem( bool copyEventHandlers, bool copyClientHandle); /// public override object Clone() { return CloneMonitoredItem(true, true); } /// public override int GetHashCode() { return Owner.GetHashCode(); } /// /// Create items /// /// /// /// /// /// public static IEnumerable Create(OpcUaClient client, IEnumerable<(ISubscriber, BaseMonitoredItemModel)> items, ILoggerFactory factory, TimeProvider timeProvider) { foreach (var (owner, item) in items) { switch (item) { case DataMonitoredItemModel dmi: if (dmi.SamplingUsingCyclicRead == true && client != null) { yield return new CyclicRead(owner, client, dmi, factory.CreateLogger(), timeProvider); } else if (dmi.HeartbeatInterval != null) { yield return new Heartbeat(owner, dmi, factory.CreateLogger(), timeProvider); } else { yield return new DataChange(owner, dmi, factory.CreateLogger(), timeProvider); } break; case EventMonitoredItemModel emi: if (emi.ConditionHandling?.SnapshotInterval != null) { yield return new Condition(owner, emi, factory.CreateLogger(), timeProvider); } else { yield return new Event(owner, emi, factory.CreateLogger(), timeProvider); } break; case MonitoredAddressSpaceModel mam: if (client != null) { yield return new ModelChangeEventItem(owner, mam, client, factory.CreateLogger(), timeProvider); } break; default: Debug.Fail($"Unexpected type of item {item}"); break; } } } /// public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } /// public override string ToString() { return base.ToString()!; } /// /// Try and get metadata for the item /// /// /// /// /// /// public abstract ValueTask GetMetaDataAsync(IOpcUaSession session, ComplexTypeSystem? typeSystem, List fields, NodeIdDictionary dataTypes, CancellationToken ct); /// /// Called when the underlying session is disconnected /// /// public virtual void NotifySessionConnectionState(bool disconnected) { } /// /// Check whether the monitored item is late /// /// /// public virtual bool WasLastValueReceivedBefore(DateTimeOffset dateTime) { if (!Valid || !AttachedToSubscription) { return IsLate = false; } return IsLate = !LastReceivedTime.HasValue || LastReceivedTime.Value < dateTime; } /// /// Dispose /// /// protected virtual void Dispose(bool disposing) { if (disposing && Valid) { Valid = false; } } /// /// Add the item to the subscription /// /// /// /// /// public virtual bool AddTo(Subscription subscription, IOpcUaSession session, out bool metadataChanged) { if (Valid) { subscription.AddItem(this); _logger.ItemAdded(this, subscription.Id); metadataChanged = true; return true; } metadataChanged = false; return false; } /// /// Finalize add /// public virtual Func? FinalizeAddTo { get; } /// /// Merge item in the subscription with this item /// /// /// /// /// public abstract bool MergeWith(OpcUaMonitoredItem item, IOpcUaSession session, out bool metadataChanged); /// /// Finalize merge /// public virtual Func? FinalizeMergeWith { get; } /// /// Remove from subscription /// /// /// /// public virtual bool RemoveFrom(Subscription subscription, out bool metadataChanged) { if (AttachedToSubscription) { subscription.RemoveItem(this); _logger.ItemRemoved(this, subscription.Id); metadataChanged = true; return true; } metadataChanged = false; return false; } /// /// Complete changes previously made and provide callback /// /// /// /// public virtual bool TryCompleteChanges(Subscription subscription, ref bool applyChanges) { if (!Valid) { _logger.ItemDisposed(this); return false; } if (!AttachedToSubscription) { _logger.ItemRemovedWithStatus(this, subscription.Id, Status.Error); // Complete removal ErrorReported = false; return true; } Debug.Assert(subscription == Subscription); if (Status.MonitoringMode == Opc.Ua.MonitoringMode.Disabled) { _logger.ItemDisabled(this); ErrorReported = false; return true; } if (Status.Error != null && StatusCode.IsNotGood(Status.Error.StatusCode)) { _logger.AddMonitoredItemError(this, subscription.Id, Status.Error); // Not needed, mode changes applied after // applyChanges = true; return false; } if (OnSamplingIntervalOrQueueSizeRevised( SamplingInterval != Status.SamplingInterval, QueueSize != Status.QueueSize)) { applyChanges = true; } ErrorReported = false; return true; } /// /// Log revised sampling rate and queue size /// public void LogRevisedSamplingRateAndQueueSize() { if (!AttachedToSubscription || SamplingInterval < 0) { return; } Debug.Assert(Subscription != null); if (SamplingInterval != Status.SamplingInterval && QueueSize != Status.QueueSize && Status.QueueSize != 0) { if (Status.SamplingInterval > SamplingInterval || Status.QueueSize < QueueSize) { _logger.StatusRevisedInfo( SamplingInterval, Status.SamplingInterval, QueueSize, Status.QueueSize, Subscription.Id, StartNodeId, DisplayName); } else { _logger.StatusRevisedDebug( SamplingInterval, Status.SamplingInterval, QueueSize, Status.QueueSize, Subscription.Id, StartNodeId, DisplayName); } } else if (SamplingInterval != Status.SamplingInterval) { if (Status.SamplingInterval < SamplingInterval) { _logger.SamplingIntervalRevisedDown(SamplingInterval, Status.SamplingInterval, Subscription.Id, StartNodeId, DisplayName); } else { _logger.SamplingIntervalRevisedUp(SamplingInterval, Status.SamplingInterval, Subscription.Id, StartNodeId, DisplayName); } } else if (QueueSize != Status.QueueSize && Status.QueueSize != 0) { if (Status.QueueSize < QueueSize) { _logger.QueueSizeRevisedDown(QueueSize, Status.QueueSize, Subscription.Id, StartNodeId, DisplayName); } else { _logger.QueueSizeRevisedUp(QueueSize, Status.QueueSize, Subscription.Id, StartNodeId, DisplayName); } } else { _logger.ConfigurationAccepted(Subscription.Id, StartNodeId, DisplayName); } _logger.ConfigurationSet(Status.SamplingInterval, Status.QueueSize, Subscription.Id, StartNodeId, DisplayName); } /// /// Called on all items after monitoring mode was changed /// successfully. /// /// public virtual Func? FinalizeCompleteChanges { get; } /// /// Get any changes in the monitoring mode to apply if any. /// Otherwise the returned value is null. /// public virtual Opc.Ua.MonitoringMode? GetMonitoringModeChange() { if (!AttachedToSubscription || !Valid) { return null; } var currentMode = Status?.MonitoringMode ?? Opc.Ua.MonitoringMode.Disabled; var desiredMode = MonitoringMode; return currentMode != desiredMode ? desiredMode : null; } /// /// Called on all items after monitoring mode was changed /// successfully. /// /// public virtual Func? FinalizeMonitoringModeChange { get; } /// /// Try get monitored item notifications from /// the subscription's monitored item event payload. /// /// /// /// /// public virtual bool TryGetMonitoredItemNotifications( DateTimeOffset publishTime, IEncodeable encodeablePayload, MonitoredItemNotifications notifications) { if (!Valid) { return false; } try { LastReceivedValue = (IEncodeable)encodeablePayload.Clone(); } catch (Exception ex) { _logger.CloneValueFailed(ex, this); LastReceivedValue = encodeablePayload; } LastReceivedTime = LastActivityTime = TimeProvider.GetUtcNow(); return true; } /// /// Get last monitored item notification saved /// /// /// public virtual bool TryGetLastMonitoredItemNotifications( MonitoredItemNotifications notifications) { var lastValue = LastReceivedValue; if (lastValue == null) { return TryGetErrorMonitoredItemNotifications( StatusCodes.BadNoData, notifications); } if (Status.Error != null && ServiceResult.IsNotGood(Status.Error)) { return TryGetErrorMonitoredItemNotifications( Status.Error.StatusCode, notifications); } return TryGetMonitoredItemNotifications(TimeProvider.GetUtcNow(), lastValue, notifications); } /// /// Create triggered items /// /// /// /// protected abstract IEnumerable CreateTriggeredItems( ILoggerFactory factory, OpcUaClient client); /// /// Add error to notification list /// /// /// /// protected abstract bool TryGetErrorMonitoredItemNotifications( StatusCode statusCode, MonitoredItemNotifications notifications); /// /// Notify queue size or sampling interval changed /// /// /// /// protected virtual bool OnSamplingIntervalOrQueueSizeRevised( bool samplingIntervalChanged, bool queueSizeChanged) { return false; } /// /// Get next sequence number /// /// protected uint GetNextSequenceNumber() { return SequenceNumber.Increment32(ref _sequenceNumber); } /// /// Merge item /// /// /// /// /// /// /// protected bool MergeWith(T template, T desired, out T updated, out bool metadataChanged) where T : BaseMonitoredItemModel { metadataChanged = false; updated = template; if (!Valid) { return false; } var itemChange = false; if ((updated.DiscardNew ?? false) != (desired.DiscardNew ?? false)) { _logger.DiscardNewModeChanged(this, updated.DiscardNew ?? false, desired.DiscardNew ?? false); updated = updated with { DiscardNew = desired.DiscardNew }; DiscardOldest = !(updated.DiscardNew ?? false); itemChange = true; } if (updated.QueueSize != desired.QueueSize || updated.AutoSetQueueSize != desired.AutoSetQueueSize) { _logger.QueueSizeChanged(this, updated.QueueSize, updated.AutoSetQueueSize, desired.QueueSize, desired.AutoSetQueueSize); updated = updated with { QueueSize = desired.QueueSize, AutoSetQueueSize = desired.AutoSetQueueSize }; if (Subscription != null) { itemChange = UpdateQueueSize(Subscription, updated); } } if ((updated.MonitoringMode ?? Publisher.Models.MonitoringMode.Reporting) != (desired.MonitoringMode ?? Publisher.Models.MonitoringMode.Reporting)) { _logger.MonitoringModeChanged( this, updated.MonitoringMode ?? Publisher.Models.MonitoringMode.Reporting, desired.MonitoringMode ?? Publisher.Models.MonitoringMode.Reporting); updated = updated with { MonitoringMode = desired.MonitoringMode }; MonitoringMode = updated.MonitoringMode.ToStackType() ?? Opc.Ua.MonitoringMode.Reporting; // Not a change yet, will be done as bulk update // itemChange = true; } if (updated.FetchDataSetFieldName != desired.FetchDataSetFieldName) { updated = updated with { FetchDataSetFieldName = desired.FetchDataSetFieldName, DataSetFieldName = desired.FetchDataSetFieldName == true ? null : updated.DataSetFieldName }; // Not a change yet, will be done as display name fetching or below // itemChange = true; } if (updated.FetchDataSetFieldName != true && updated.DisplayName != desired.DisplayName) { updated = updated with { DataSetFieldName = desired.DataSetFieldName }; DisplayName = updated.DisplayName; metadataChanged = true; itemChange = true; } return itemChange; } /// /// Add veriable field metadata /// /// /// /// /// /// /// /// /// protected async ValueTask AddVariableFieldAsync(List fields, NodeIdDictionary dataTypes, IOpcUaSession session, ComplexTypeSystem? typeSystem, VariableNode variable, string fieldName, Uuid dataSetClassFieldId, CancellationToken ct) { byte builtInType = 0; try { builtInType = (byte)await session.LruNodeCache.GetBuiltInTypeAsync(variable.DataType, ct).ConfigureAwait(false); } catch (Exception ex) { _logger.BuiltInTypeFailed(this, variable.DataType.ToString(), ex.Message); } fields.Add(new PublishedFieldMetaDataModel { Flags = 0, // Set to 1 << 1 for PromotedField fields. Name = fieldName, Id = dataSetClassFieldId, DataType = variable.DataType.AsString(session.MessageContext, NamespaceFormat.Expanded), ArrayDimensions = variable.ArrayDimensions?.Count > 0 ? variable.ArrayDimensions : null, Description = variable.Description.AsString(), ValueRank = variable.ValueRank, MaxStringLength = 0, // If the Property is EngineeringUnits, the unit of the Field Value // shall match the unit of the FieldMetaData. Properties = null, // TODO: Add engineering units etc. to properties BuiltInType = builtInType }); await AddDataTypesAsync(dataTypes, variable.DataType, session, typeSystem, ct).ConfigureAwait(false); } /// /// Add data types to the metadata /// /// /// /// /// /// /// private async ValueTask AddDataTypesAsync(NodeIdDictionary dataTypes, NodeId dataTypeId, IOpcUaSession session, ComplexTypeSystem? typeSystem, CancellationToken ct) { if (IsBuiltInType(dataTypeId)) { return; } var typesToResolve = new Queue(); typesToResolve.Enqueue(dataTypeId); while (typesToResolve.Count > 0) { var baseType = typesToResolve.Dequeue(); while (!Opc.Ua.NodeId.IsNull(baseType)) { try { var dataType = await session.LruNodeCache.GetNodeAsync(baseType, ct).ConfigureAwait(false); if (dataType == null) { _logger.DataTypeNodeNotFound(this, baseType.ToString()); break; } dataTypeId = ExpandedNodeId.ToNodeId(dataType.NodeId, session.MessageContext.NamespaceUris); Debug.Assert(!Opc.Ua.NodeId.IsNull(dataTypeId)); if (IsBuiltInType(dataTypeId)) { // Do not add builtin types - we are done here now break; } var builtInType = await session.LruNodeCache.GetBuiltInTypeAsync( dataTypeId, ct).ConfigureAwait(false); baseType = await session.LruNodeCache.GetSuperTypeAsync(dataTypeId, ct).ConfigureAwait(false); var browseName = dataType.BrowseName .AsString(session.MessageContext, NamespaceFormat.Expanded); var typeName = dataType.NodeId .AsString(session.MessageContext, NamespaceFormat.Expanded); if (typeName == null) { // No type name - that should not happen throw new ServiceResultException(StatusCodes.BadDataTypeIdUnknown, $"Failed to get metadata type name for {dataType.NodeId}."); } switch (builtInType) { case BuiltInType.Enumeration: case BuiltInType.ExtensionObject: var types = typeSystem?.GetDataTypeDefinitionsForDataType( dataType.NodeId); if (types == null || types.Count == 0) { var dtNode = await session.LruNodeCache.GetNodeAsync(dataTypeId, ct).ConfigureAwait(false); if (dtNode is DataTypeNode v && v.DataTypeDefinition?.Body is DataTypeDefinition t) { types ??= []; types.Add(dataTypeId, t); } else { dataTypes.AddOrUpdate( ExpandedNodeId.ToNodeId(dataType.NodeId, session.MessageContext.NamespaceUris), GetDefault(dataType, builtInType, session.MessageContext)); break; } } foreach (var type in types) { if (!dataTypes.ContainsKey(type.Key)) { var description = type.Value switch { StructureDefinition s => new StructureDescriptionModel { DataTypeId = typeName, Name = browseName, BaseDataType = s.BaseDataType.AsString( session.MessageContext, NamespaceFormat.Expanded), DefaultEncodingId = s.DefaultEncodingId.AsString( session.MessageContext, NamespaceFormat.Expanded), StructureType = s.StructureType.ToServiceType(), Fields = GetFields(s.Fields, typesToResolve, session.MessageContext, NamespaceFormat.Expanded) .ToList() }, EnumDefinition e => new EnumDescriptionModel { DataTypeId = typeName, Name = browseName, BuiltInType = null, IsOptionSet = e.IsOptionSet, Fields = e.Fields .Select(f => new EnumFieldDescriptionModel { Value = f.Value, DisplayName = f.DisplayName.AsString(), Name = f.Name, Description = f.Description.AsString() }) .ToList() }, _ => GetDefault(dataType, builtInType, session.MessageContext), }; dataTypes.AddOrUpdate(type.Key, description); } } break; default: var baseName = baseType .AsString(session.MessageContext, NamespaceFormat.Expanded); dataTypes.AddOrUpdate(dataTypeId, new SimpleTypeDescriptionModel { DataTypeId = typeName, Name = browseName, BaseDataType = baseName, BuiltInType = (byte)builtInType }); break; } } catch (Exception ex) when (ex is not OperationCanceledException) { _logger.MetaDataFailed(this, dataTypeId, baseType, ex.Message); break; } } object GetDefault(INode dataType, BuiltInType builtInType, IServiceMessageContext context) { _logger.TypeDefinitionNotFound(this, dataType.NodeId, builtInType); var name = dataType.BrowseName.AsString(context, NamespaceFormat.Expanded); var dataTypeId = dataType.NodeId.AsString(context, NamespaceFormat.Expanded); return dataTypeId == null ? throw new ServiceResultException(StatusCodes.BadConfigurationError) : builtInType == BuiltInType.Enumeration ? new EnumDescriptionModel { Fields = new List(), DataTypeId = dataTypeId, Name = name } : new StructureDescriptionModel { Fields = new List(), DataTypeId = dataTypeId, Name = name }; } static IEnumerable GetFields( StructureFieldCollection? fields, Queue typesToResolve, IServiceMessageContext context, NamespaceFormat namespaceFormat) { if (fields == null) { yield break; } foreach (var f in fields) { if (!IsBuiltInType(f.DataType)) { typesToResolve.Enqueue(f.DataType); } yield return new StructureFieldDescriptionModel { IsOptional = f.IsOptional, MaxStringLength = f.MaxStringLength, ValueRank = f.ValueRank, ArrayDimensions = f.ArrayDimensions, DataType = f.DataType.AsString(context, namespaceFormat) ?? string.Empty, Name = f.Name, Description = f.Description.AsString() }; } } } static bool IsBuiltInType(NodeId dataTypeId) { if (dataTypeId.NamespaceIndex == 0 && dataTypeId.IdType == IdType.Numeric) { var id = (BuiltInType)(int)(uint)dataTypeId.Identifier; if (id >= BuiltInType.Null && id <= BuiltInType.Enumeration) { return true; } } return false; } } /// /// Update queue size using sampling rate and publishing interval /// /// /// protected bool UpdateQueueSize(Subscription subscription, BaseMonitoredItemModel item) { var queueSize = item.QueueSize ?? 1; if (item.AutoSetQueueSize == true) { var publishingInterval = subscription.CurrentPublishingInterval; if (publishingInterval == 0) { publishingInterval = subscription.PublishingInterval; } var samplingInterval = Status.SamplingInterval; if (samplingInterval == 0) { samplingInterval = SamplingInterval; } if (samplingInterval > 0) { queueSize = Math.Max(queueSize, (uint)Math.Ceiling( (double)publishingInterval / SamplingInterval)) + 1; if (queueSize != QueueSize && item.QueueSize != queueSize) { _logger.QueueSizeAutoSet(this, queueSize); } } else { _logger.NoSamplingInterval(this); } } var itemChanged = QueueSize != queueSize; QueueSize = queueSize; return itemChanged; } internal sealed class MonitoredItemNotifications { /// /// Notifications collected /// public Dictionary> Notifications { get; } = []; /// /// Add notification /// /// /// public void Add(ISubscriber callback, MonitoredItemNotificationModel notification) { if (!Notifications.TryGetValue(callback, out var list)) { list = []; Notifications.Add(callback, list); } list.Add(notification); } } /// /// Callback /// /// /// /// /// /// /// protected void Publish(ISubscriber owner, MessageType messageType, IList notifications, string? eventTypeName = null, bool diagnosticsOnly = false, DateTimeOffset? timestamp = null) { if (Subscription is not OpcUaSubscription subscription) { _logger.MissingSubscription(this); return; } subscription.SendNotification(owner, messageType, notifications, eventTypeName, diagnosticsOnly, timestamp); } /// /// Logger /// protected readonly ILogger _logger; private uint _sequenceNumber; } /// /// Source-generated logging definitions for OpcUaMonitoredItem /// internal static partial class OpcUaMonitoredItemLogging { private const int EventClass = 1030; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Debug, Message = "Added monitored item {Item} to subscription #{SubscriptionId}.")] public static partial void ItemAdded(this ILogger logger, OpcUaMonitoredItem item, uint subscriptionId); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Debug, Message = "Removed monitored item {Item} from subscription #{SubscriptionId}.")] public static partial void ItemRemoved(this ILogger logger, OpcUaMonitoredItem item, uint subscriptionId); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Error, Message = "{Item}: Item was disposed or moved to another subscription")] public static partial void ItemDisposed(this ILogger logger, OpcUaMonitoredItem item); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Debug, Message = "Item {Item} removed from subscription #{SubscriptionId} with {Status}.")] public static partial void ItemRemovedWithStatus(this ILogger logger, OpcUaMonitoredItem item, uint subscriptionId, ServiceResult status); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Debug, Message = "{Item}: Item is disabled while trying to complete.")] public static partial void ItemDisabled(this ILogger logger, OpcUaMonitoredItem item); [LoggerMessage(EventId = EventClass + 9, Level = LogLevel.Debug, Message = "Server accepted configuration unchanged for #{SubscriptionId}|{Item}('{Name}').")] public static partial void ConfigurationAccepted(this ILogger logger, uint subscriptionId, NodeId item, string name); [LoggerMessage(EventId = EventClass + 10, Level = LogLevel.Debug, Message = "SamplingInterval set to {SamplingInterval} and QueueSize to {QueueSize} " + "for #{SubscriptionId}|{Item}('{Name}').")] public static partial void ConfigurationSet(this ILogger logger, double samplingInterval, uint queueSize, uint subscriptionId, NodeId item, string name); [LoggerMessage(EventId = EventClass + 11, Level = LogLevel.Debug, Message = "{Item}: Could not clone last value.")] public static partial void CloneValueFailed(this ILogger logger, Exception ex, OpcUaMonitoredItem item); [LoggerMessage(EventId = EventClass + 12, Level = LogLevel.Debug, Message = "{Item}: Changing discard new mode from {Old} to {New}")] public static partial void DiscardNewModeChanged(this ILogger logger, OpcUaMonitoredItem item, bool old, bool @new); [LoggerMessage(EventId = EventClass + 13, Level = LogLevel.Debug, Message = "{Item}: Changing queue size from {Old} ({OldAuto}) to {New} ({NewAuto})")] public static partial void QueueSizeChanged(this ILogger logger, OpcUaMonitoredItem item, uint? old, bool? oldAuto, uint? @new, bool? newAuto); [LoggerMessage(EventId = EventClass + 14, Level = LogLevel.Debug, Message = "{Item}: Changing monitoring mode from {Old} to {New}")] public static partial void MonitoringModeChanged(this ILogger logger, OpcUaMonitoredItem item, Publisher.Models.MonitoringMode old, Publisher.Models.MonitoringMode @new); [LoggerMessage(EventId = EventClass + 15, Level = LogLevel.Information, Message = "{Item}: Failed to get built in type for type {DataType} with message: {Message}")] public static partial void BuiltInTypeFailed(this ILogger logger, OpcUaMonitoredItem item, string dataType, string message); [LoggerMessage(EventId = EventClass + 16, Level = LogLevel.Error, Message = "{Item}: Failed to find node for data type {BaseType}!")] public static partial void DataTypeNodeNotFound(this ILogger logger, OpcUaMonitoredItem item, string baseType); [LoggerMessage(EventId = EventClass + 17, Level = LogLevel.Information, Message = "{Item}: Failed to get meta data for type {DataType} (base: {BaseType}) with message: {Message}")] public static partial void MetaDataFailed(this ILogger logger, OpcUaMonitoredItem item, NodeId dataType, NodeId? baseType, string message); [LoggerMessage(EventId = EventClass + 18, Level = LogLevel.Error, Message = "{Item}: Could not find a valid type definition for {Type} ({BuiltInType}). " + "Adding a default placeholder with no fields instead.")] public static partial void TypeDefinitionNotFound(this ILogger logger, OpcUaMonitoredItem item, ExpandedNodeId type, BuiltInType builtInType); [LoggerMessage(EventId = EventClass + 19, Level = LogLevel.Debug, Message = "Auto-set queue size for {Item} to '{QueueSize}'.")] public static partial void QueueSizeAutoSet(this ILogger logger, OpcUaMonitoredItem item, uint queueSize); [LoggerMessage(EventId = EventClass + 20, Level = LogLevel.Debug, Message = "No sampling interval set - cannot calculate queue size for {Item}.")] public static partial void NoSamplingInterval(this ILogger logger, OpcUaMonitoredItem item); [LoggerMessage(EventId = EventClass + 21, Level = LogLevel.Debug, Message = "Cannot publish notification. Missing subscription for {Item}.")] public static partial void MissingSubscription(this ILogger logger, OpcUaMonitoredItem item); [LoggerMessage(EventId = EventClass + 22, Level = LogLevel.Debug, Message = "Error adding monitored item {Item} to subscription #{SubscriptionId} due to {Status}.")] internal static partial void AddMonitoredItemError(this ILogger logger, OpcUaMonitoredItem item, uint subscriptionId, ServiceResult status); [LoggerMessage(EventId = EventClass + 23, Level = LogLevel.Debug, Message = "Server revised SamplingInterval from {SamplingInterval} to {CurrentSamplingInterval} and " + "QueueSize from {QueueSize} to {CurrentQueueSize} for #{SubscriptionId}|{Item}('{Name}').")] public static partial void StatusRevisedDebug(this ILogger logger, double samplingInterval, double currentSamplingInterval, uint queueSize, uint currentQueueSize, uint subscriptionId, NodeId item, string name); [LoggerMessage(EventId = EventClass + 24, Level = LogLevel.Debug, Message = "Server revised SamplingInterval from {SamplingInterval} to {CurrentSamplingInterval} " + "for #{SubscriptionId}|{Item}('{Name}').")] public static partial void SamplingIntervalRevisedDown(this ILogger logger, double samplingInterval, double currentSamplingInterval, uint subscriptionId, NodeId item, string name); [LoggerMessage(EventId = EventClass + 25, Level = LogLevel.Information, Message = "Server revised QueueSize from {QueueSize} to {CurrentQueueSize} " + "for #{SubscriptionId}|{Item}('{Name}').")] public static partial void QueueSizeRevisedDown(this ILogger logger, uint queueSize, uint currentQueueSize, uint subscriptionId, NodeId item, string name); [LoggerMessage(EventId = EventClass + 26, Level = LogLevel.Information, Message = "Server revised SamplingInterval from {SamplingInterval} to {CurrentSamplingInterval} and " + "QueueSize from {QueueSize} to {CurrentQueueSize} for #{SubscriptionId}|{Item}('{Name}').")] public static partial void StatusRevisedInfo(this ILogger logger, double samplingInterval, double currentSamplingInterval, uint queueSize, uint currentQueueSize, uint subscriptionId, NodeId item, string name); [LoggerMessage(EventId = EventClass + 27, Level = LogLevel.Information, Message = "Server revised SamplingInterval from {SamplingInterval} to {CurrentSamplingInterval} " + "for #{SubscriptionId}|{Item}('{Name}').")] public static partial void SamplingIntervalRevisedUp(this ILogger logger, double samplingInterval, double currentSamplingInterval, uint subscriptionId, NodeId item, string name); [LoggerMessage(EventId = EventClass + 28, Level = LogLevel.Debug, Message = "Server revised QueueSize from {QueueSize} to {CurrentQueueSize} " + "for #{SubscriptionId}|{Item}('{Name}').")] public static partial void QueueSizeRevisedUp(this ILogger logger, uint queueSize, uint currentQueueSize, uint subscriptionId, NodeId item, string name); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaSession.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Services { using Azure.IIoT.OpcUa.Publisher.Stack.Extensions; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Encoders; using Furly.Extensions.Utils; using Furly.Extensions.Serializers; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Client; using Opc.Ua.Client.ComplexTypes; using Opc.Ua.Extensions; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Runtime.Serialization; using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; /// /// OPC UA session extends the SDK session /// [DataContract(Namespace = OpcUaClient.Namespace)] [KnownType(typeof(OpcUaSubscription))] [KnownType(typeof(OpcUaMonitoredItem))] internal sealed class OpcUaSession : Session, IOpcUaSession, ISessionServices { /// public IVariantEncoder Codec { get; } /// public ISessionServices Services => this; /// public ILruNodeCache LruNodeCache { get; } /// /// Time the session was created /// internal DateTimeOffset CreatedAt { get; } /// /// Type system has loaded /// internal bool IsTypeSystemLoaded => _complexTypeSystem?.IsCompletedSuccessfully ?? false; /// /// Get list of subscription handles registered in the session /// internal Dictionary SubscriptionHandles { get { lock (SyncRoot) { return Subscriptions .OfType() .ToDictionary(k => k.SubscriptionId); } } } /// /// Enable or disable ChannelDiagnostics /// public bool DiagnosticsEnabled { get => _diagnosticsEnabled != false; set => _diagnosticsEnabled = value ? null : false; } /// /// Create session /// /// /// /// /// /// /// /// /// /// /// public OpcUaSession(OpcUaClient client, IJsonSerializer serializer, ILogger logger, TimeProvider timeProvider, ITransportChannel channel, ApplicationConfiguration configuration, ConfiguredEndpoint endpoint, X509Certificate2? clientCertificate = null, EndpointDescriptionCollection? availableEndpoints = null, StringCollection? discoveryProfileUris = null) : base(channel, configuration, endpoint, clientCertificate, availableEndpoints, discoveryProfileUris) { _logger = logger; _client = client; _serializer = serializer; _timeProvider = timeProvider; LruNodeCache = new LruNodeCache(this, client.NodeCacheTimeout, client.NodeCacheCapacity, true); CreatedAt = _timeProvider.GetUtcNow(); Initialize(); Codec = new JsonVariantEncoder(MessageContext, serializer); } /// /// Copy constructor /// /// /// /// /// private OpcUaSession(OpcUaSession session, ITransportChannel channel, Session template, bool copyEventHandlers) : base(channel, template, copyEventHandlers) { _logger = session._logger; _client = session._client; _serializer = session._serializer; _timeProvider = session._timeProvider; LruNodeCache = session.LruNodeCache; CreatedAt = _timeProvider.GetUtcNow(); _complexTypeSystem = session._complexTypeSystem; _history = session._history; _limits = session._limits; _server = session._server; Initialize(); Codec = new JsonVariantEncoder(MessageContext, _serializer); } /// protected override void Dispose(bool disposing) { if (_disposed) { return; } _disposed = true; if (disposing) { NodeCache?.Clear(); LruNodeCache.Clear(); _client.OnSessionClosing(this); } // Disposes all contained subscriptions base.Dispose(disposing); if (disposing) { var sessionName = SessionName; PublishError -= _client.Session_HandlePublishError; PublishSequenceNumbersToAcknowledge -= _client.Session_PublishSequenceNumbersToAcknowledge; KeepAlive -= _client.Session_KeepAlive; SessionConfigurationChanged -= Session_SessionConfigurationChanged; CloseChannel(); // Ensure channel is closed try { _cts.Cancel(); if (_complexTypeSystem != null) { Try.Op(() => _complexTypeSystem.Wait(TimeSpan.FromSeconds(5))); } _logger.SessionDisposed(sessionName); } finally { _activitySource.Dispose(); _cts.Dispose(); } } Debug.Assert(SubscriptionHandles.Count == 0); } /// public override Session CloneSession(ITransportChannel channel, bool copyEventHandlers) { return new OpcUaSession(this, channel, this, copyEventHandlers); } /// public override string? ToString() { return SessionName; } /// public async ValueTask GetServerDiagnosticAsync( CancellationToken ct = default) { try { _lastDiagnostics = await FetchServerDiagnosticAsync(new RequestHeader(), ct).ConfigureAwait(false); } catch (ServiceResultException sre) { _logger.ServerDiagnosticsFetchFailed(sre); } return _lastDiagnostics ?? new SessionDiagnosticsModel(); } /// public async ValueTask GetOperationLimitsAsync( CancellationToken ct = default) { if (_limits != null) { return _limits; } _limits = await FetchOperationLimitsAsync(new RequestHeader(), ct).ConfigureAwait(false); return _limits ?? new OperationLimitsModel(); } /// public async ValueTask GetServerCapabilitiesAsync( NamespaceFormat namespaceFormat, CancellationToken ct = default) { if (_server != null && namespaceFormat == NamespaceFormat.Uri) { return _server; } if (_limits == null) { _limits = await FetchOperationLimitsAsync(new RequestHeader(), ct).ConfigureAwait(false); } var server = await FetchServerCapabilitiesAsync(new RequestHeader(), namespaceFormat, ct).ConfigureAwait(false); if (namespaceFormat == NamespaceFormat.Uri) { _server = server; } return server ?? new ServerCapabilitiesModel { OperationLimits = _limits ?? new OperationLimitsModel() }; } /// public async ValueTask GetHistoryCapabilitiesAsync( NamespaceFormat namespaceFormat, CancellationToken ct = default) { if (_history != null && namespaceFormat == NamespaceFormat.Uri) { return _history; } var history = await FetchHistoryCapabilitiesAsync(new RequestHeader(), namespaceFormat, ct).ConfigureAwait(false); if (namespaceFormat == NamespaceFormat.Uri) { _history = history; } return history ?? new HistoryServerCapabilitiesModel(); } /// public async ValueTask GetComplexTypeSystemAsync(CancellationToken ct) { if (_client.DisableComplexTypeLoading) { return null; } for (var attempt = 0; attempt < 2; attempt++) { try { Debug.Assert(_complexTypeSystem != null); return await _complexTypeSystem.WaitAsync(ct).ConfigureAwait(false); } catch (OperationCanceledException) when (ct.IsCancellationRequested) { // Throw any cancellation token exception throw; } catch (Exception ex) { _logger.ComplexTypeSystemFailed(this, attempt, ex); // Try again. TODO: Throttle using a timer or so... _complexTypeSystem = LoadComplexTypeSystemAsync(); } } return null; } /// async ValueTask ISessionServices.AddNodesAsync(RequestHeader requestHeader, AddNodesItemCollection nodesToAdd, CancellationToken ct) { using var activity = Begin(requestHeader); if (activity.Error != null) { return activity.Error; } var request = new AddNodesRequest { RequestHeader = requestHeader, NodesToAdd = nodesToAdd }; var response = await TransportChannel.SendRequestAsync( request, ct).ConfigureAwait(false); return activity.ValidateResponse(response); } /// async ValueTask ISessionServices.AddReferencesAsync( RequestHeader requestHeader, AddReferencesItemCollection referencesToAdd, CancellationToken ct) { using var activity = Begin(requestHeader); if (activity.Error != null) { return activity.Error; } var request = new AddReferencesRequest { RequestHeader = requestHeader, ReferencesToAdd = referencesToAdd }; var response = await TransportChannel.SendRequestAsync( request, ct).ConfigureAwait(false); return activity.ValidateResponse(response); } /// async ValueTask ISessionServices.DeleteNodesAsync( RequestHeader requestHeader, DeleteNodesItemCollection nodesToDelete, CancellationToken ct) { using var activity = Begin(requestHeader); if (activity.Error != null) { return activity.Error; } var request = new DeleteNodesRequest { RequestHeader = requestHeader, NodesToDelete = nodesToDelete }; var response = await TransportChannel.SendRequestAsync( request, ct).ConfigureAwait(false); return activity.ValidateResponse(response); } /// async ValueTask ISessionServices.DeleteReferencesAsync( RequestHeader requestHeader, DeleteReferencesItemCollection referencesToDelete, CancellationToken ct) { using var activity = Begin(requestHeader); if (activity.Error != null) { return activity.Error; } var request = new DeleteReferencesRequest { RequestHeader = requestHeader, ReferencesToDelete = referencesToDelete }; var response = await TransportChannel.SendRequestAsync( request, ct).ConfigureAwait(false); return activity.ValidateResponse(response); } /// async ValueTask ISessionServices.BrowseAsync( RequestHeader requestHeader, ViewDescription? view, uint requestedMaxReferencesPerNode, BrowseDescriptionCollection nodesToBrowse, CancellationToken ct) { using var activity = Begin(requestHeader); if (activity.Error != null) { return activity.Error; } var request = new BrowseRequest { RequestHeader = requestHeader, View = view, RequestedMaxReferencesPerNode = requestedMaxReferencesPerNode, NodesToBrowse = nodesToBrowse }; var response = await TransportChannel.SendRequestAsync( request, ct).ConfigureAwait(false); return activity.ValidateResponse(response); } /// async ValueTask ISessionServices.BrowseNextAsync( RequestHeader requestHeader, bool releaseContinuationPoints, ByteStringCollection continuationPoints, CancellationToken ct) { using var activity = Begin(requestHeader); if (activity.Error != null) { return activity.Error; } var request = new BrowseNextRequest { RequestHeader = requestHeader, ReleaseContinuationPoints = releaseContinuationPoints, ContinuationPoints = continuationPoints }; var response = await TransportChannel.SendRequestAsync( request, ct).ConfigureAwait(false); return activity.ValidateResponse(response); } /// async ValueTask ISessionServices.TranslateBrowsePathsToNodeIdsAsync( RequestHeader requestHeader, BrowsePathCollection browsePaths, CancellationToken ct) { using var activity = Begin( requestHeader); if (activity.Error != null) { return activity.Error; } var request = new TranslateBrowsePathsToNodeIdsRequest { RequestHeader = requestHeader, BrowsePaths = browsePaths }; var response = await TransportChannel.SendRequestAsync( request, ct).ConfigureAwait(false); return activity.ValidateResponse(response); } /// async ValueTask ISessionServices.RegisterNodesAsync( RequestHeader requestHeader, NodeIdCollection nodesToRegister, CancellationToken ct) { using var activity = Begin(requestHeader); if (activity.Error != null) { return activity.Error; } var request = new RegisterNodesRequest { RequestHeader = requestHeader, NodesToRegister = nodesToRegister }; var response = await TransportChannel.SendRequestAsync( request, ct).ConfigureAwait(false); return activity.ValidateResponse(response); } /// async ValueTask ISessionServices.UnregisterNodesAsync( RequestHeader requestHeader, NodeIdCollection nodesToUnregister, CancellationToken ct) { using var activity = Begin(requestHeader); if (activity.Error != null) { return activity.Error; } var request = new UnregisterNodesRequest { RequestHeader = requestHeader, NodesToUnregister = nodesToUnregister }; var response = await TransportChannel.SendRequestAsync( request, ct).ConfigureAwait(false); return activity.ValidateResponse(response); } /// async ValueTask ISessionServices.QueryFirstAsync( RequestHeader requestHeader, ViewDescription view, NodeTypeDescriptionCollection nodeTypes, ContentFilter filter, uint maxDataSetsToReturn, uint maxReferencesToReturn, CancellationToken ct) { using var activity = Begin(requestHeader); if (activity.Error != null) { return activity.Error; } var request = new QueryFirstRequest { RequestHeader = requestHeader, View = view, NodeTypes = nodeTypes, Filter = filter, MaxDataSetsToReturn = maxDataSetsToReturn, MaxReferencesToReturn = maxReferencesToReturn }; var response = await TransportChannel.SendRequestAsync( request, ct).ConfigureAwait(false); return activity.ValidateResponse(response); } /// async ValueTask ISessionServices.QueryNextAsync( RequestHeader requestHeader, bool releaseContinuationPoint, byte[] continuationPoint, CancellationToken ct) { using var activity = Begin(requestHeader); if (activity.Error != null) { return activity.Error; } var request = new QueryNextRequest { RequestHeader = requestHeader, ReleaseContinuationPoint = releaseContinuationPoint, ContinuationPoint = continuationPoint }; var response = await TransportChannel.SendRequestAsync( request, ct).ConfigureAwait(false); return activity.ValidateResponse(response); } /// async ValueTask ISessionServices.ReadAsync(RequestHeader requestHeader, double maxAge, Opc.Ua.TimestampsToReturn timestampsToReturn, ReadValueIdCollection nodesToRead, CancellationToken ct) { using var activity = Begin(requestHeader); if (activity.Error != null) { return activity.Error; } var request = new ReadRequest { RequestHeader = requestHeader, MaxAge = maxAge, TimestampsToReturn = timestampsToReturn, NodesToRead = nodesToRead }; var response = await TransportChannel.SendRequestAsync( request, ct).ConfigureAwait(false); return activity.ValidateResponse(response); } /// async ValueTask ISessionServices.HistoryReadAsync( RequestHeader requestHeader, ExtensionObject? historyReadDetails, Opc.Ua.TimestampsToReturn timestampsToReturn, bool releaseContinuationPoints, HistoryReadValueIdCollection nodesToRead, CancellationToken ct) { using var activity = Begin(requestHeader); if (activity.Error != null) { return activity.Error; } var request = new HistoryReadRequest { RequestHeader = requestHeader, HistoryReadDetails = historyReadDetails, TimestampsToReturn = timestampsToReturn, ReleaseContinuationPoints = releaseContinuationPoints, NodesToRead = nodesToRead }; var response = await TransportChannel.SendRequestAsync( request, ct).ConfigureAwait(false); return activity.ValidateResponse(response); } /// async ValueTask ISessionServices.WriteAsync(RequestHeader requestHeader, WriteValueCollection nodesToWrite, CancellationToken ct) { using var activity = Begin(requestHeader); if (activity.Error != null) { return activity.Error; } var request = new WriteRequest { RequestHeader = requestHeader, NodesToWrite = nodesToWrite }; var response = await TransportChannel.SendRequestAsync( request, ct).ConfigureAwait(false); return activity.ValidateResponse(response); } /// async ValueTask ISessionServices.HistoryUpdateAsync( RequestHeader requestHeader, ExtensionObjectCollection historyUpdateDetails, CancellationToken ct) { using var activity = Begin(requestHeader); if (activity.Error != null) { return activity.Error; } var request = new HistoryUpdateRequest { RequestHeader = requestHeader, HistoryUpdateDetails = historyUpdateDetails }; var response = await TransportChannel.SendRequestAsync( request, ct).ConfigureAwait(false); return activity.ValidateResponse(response); } /// async ValueTask ISessionServices.CallAsync(RequestHeader requestHeader, CallMethodRequestCollection methodsToCall, CancellationToken ct) { using var activity = Begin(requestHeader); if (activity.Error != null) { return activity.Error; } var request = new CallRequest { RequestHeader = requestHeader, MethodsToCall = methodsToCall }; var response = await TransportChannel.SendRequestAsync( request, ct).ConfigureAwait(false); return activity.ValidateResponse(response); } /// /// Called when session is created /// /// /// public override void SessionCreated(NodeId sessionId, NodeId sessionCookie) { base.SessionCreated(sessionId, sessionCookie); if (NodeId.IsNull(sessionId)) { // Also called when session closes return; } Debug.Assert(!NodeId.IsNull(sessionCookie)); // Update operation limits with configuration provided overrides OperationLimits.Override(_client.LimitOverrides); PreloadComplexTypeSystem(); } /// /// Called when session configuration changed /// /// /// private void Session_SessionConfigurationChanged(object? sender, EventArgs e) { PreloadComplexTypeSystem(); } /// /// Preload type system /// private void PreloadComplexTypeSystem() { if (_complexTypeSystem == null && Connected && !_client.DisableComplexTypeLoading && !_client.DisableComplexTypePreloading) { _complexTypeSystem = LoadComplexTypeSystemAsync(); } } /// /// Initialize session settings from client configuration /// private void Initialize() { SessionFactory = _client; TransferSubscriptionsOnReconnect = !_client.DisableTransferSubscriptionOnReconnect; DeleteSubscriptionsOnClose = !TransferSubscriptionsOnReconnect; PublishError += _client.Session_HandlePublishError; PublishSequenceNumbersToAcknowledge += _client.Session_PublishSequenceNumbersToAcknowledge; KeepAlive += _client.Session_KeepAlive; SessionConfigurationChanged += Session_SessionConfigurationChanged; var keepAliveInterval = (int)(_client.KeepAliveInterval ?? kDefaultKeepAliveInterval).TotalMilliseconds; if (keepAliveInterval <= 0) { keepAliveInterval = kDefaultKeepAliveInterval.Milliseconds; } var operationTimeout = (int)(_client.OperationTimeout ?? kDefaultOperationTimeout).TotalMilliseconds; if (operationTimeout <= 0) { operationTimeout = kDefaultOperationTimeout.Milliseconds; } KeepAliveInterval = keepAliveInterval; OperationTimeout = operationTimeout; _defaultOperationTimeout = operationTimeout; } /// /// Fetch server diagnostics /// /// /// /// private async Task FetchServerDiagnosticAsync(RequestHeader header, CancellationToken ct) { if (_diagnosticsEnabled == false) { return null; } if (!_diagnosticsEnabled.HasValue) { // Check whether enabled and if not enabled enable it var diagnosticsEnabled = await ReadValueAsync( VariableIds.Server_ServerDiagnostics_EnabledFlag, ct).ConfigureAwait(false); _diagnosticsEnabled = diagnosticsEnabled.Value as bool?; if (_diagnosticsEnabled == false) { var enableResponse = await WriteAsync(header, new[] { new WriteValue { AttributeId = Attributes.Value, NodeId = VariableIds.Server_ServerDiagnostics_EnabledFlag, Value = new DataValue(true) } }, ct).ConfigureAwait(false); if (ServiceResult.IsBad(enableResponse.Results[0])) { _logger.DiagnosticsEnableFailed(enableResponse.Results[0].ToString()); return null; } _diagnosticsEnabled = true; } } var response = await ReadAsync(header, 0.0, Opc.Ua.TimestampsToReturn.Neither, new[] { new ReadValueId { AttributeId = Attributes.Value, NodeId = VariableIds.Server_ServerDiagnostics_SessionsDiagnosticsSummary_SessionDiagnosticsArray }, new ReadValueId { AttributeId = Attributes.Value, NodeId = VariableIds.Server_ServerDiagnostics_SubscriptionDiagnosticsArray } }, ct).ConfigureAwait(false); if (ServiceResult.IsBad(response.Results[0].StatusCode)) { _logger.DiagnosticsNotRetrievable(response.Results[0].StatusCode.ToString(), response.Results[1].StatusCode.ToString()); return null; } var sessionDiagnosticsArray = response.Results[0].Value as ExtensionObject[]; var sessionDiagnostics = sessionDiagnosticsArray? .Select(o => o.Body) .OfType() .FirstOrDefault(d => d.SessionId == SessionId); if (sessionDiagnostics == null) { _logger.DiagnosticsNotFound(response.Results[0].StatusCode.ToString()); return null; } List? subscriptions = null; if (!ServiceResult.IsBad(response.Results[1].StatusCode) && response.Results[1].Value is ExtensionObject[] subscriptionDiagnosticsArray) { subscriptions = subscriptionDiagnosticsArray .Select(o => o.Body) .OfType() .Where(d => d.SessionId == SessionId) .Select(diag => new SubscriptionDiagnosticsModel { SubscriptionId = diag.SubscriptionId, Priority = diag.Priority, PublishingInterval = diag.PublishingInterval, MaxKeepAliveCount = diag.MaxKeepAliveCount, MaxLifetimeCount = diag.MaxLifetimeCount, MaxNotificationsPerPublish = diag.MaxNotificationsPerPublish, PublishingEnabled = diag.PublishingEnabled, ModifyCount = diag.ModifyCount, EnableCount = diag.EnableCount, DisableCount = diag.DisableCount, RepublishRequestCount = diag.RepublishRequestCount, RepublishMessageRequestCount = diag.RepublishMessageRequestCount, RepublishMessageCount = diag.RepublishMessageCount, TransferRequestCount = diag.TransferRequestCount, TransferredToAltClientCount = diag.TransferredToAltClientCount, TransferredToSameClientCount = diag.TransferredToSameClientCount, PublishRequestCount = diag.PublishRequestCount, DataChangeNotificationsCount = diag.DataChangeNotificationsCount, EventNotificationsCount = diag.EventNotificationsCount, NotificationsCount = diag.NotificationsCount, LatePublishRequestCount = diag.LatePublishRequestCount, CurrentKeepAliveCount = diag.CurrentKeepAliveCount, CurrentLifetimeCount = diag.CurrentLifetimeCount, UnacknowledgedMessageCount = diag.UnacknowledgedMessageCount, DiscardedMessageCount = diag.DiscardedMessageCount, MonitoredItemCount = diag.MonitoredItemCount, DisabledMonitoredItemCount = diag.DisabledMonitoredItemCount, MonitoringQueueOverflowCount = diag.MonitoringQueueOverflowCount, NextSequenceNumber = diag.NextSequenceNumber, EventQueueOverFlowCount = diag.EventQueueOverflowCount }) .ToList(); } else { _logger.SubscriptionDiagnosticsNotRetrievable(response.Results[1].StatusCode.ToString()); } return new SessionDiagnosticsModel { SessionId = sessionDiagnostics.SessionId.AsString(MessageContext, NamespaceFormat.Expanded), TranslateBrowsePathsToNodeIdsCount = ToCounter(sessionDiagnostics.TranslateBrowsePathsToNodeIdsCount), AddNodesCount = ToCounter(sessionDiagnostics.AddNodesCount), AddReferencesCount = ToCounter(sessionDiagnostics.AddReferencesCount), BrowseCount = ToCounter(sessionDiagnostics.BrowseCount), BrowseNextCount = ToCounter(sessionDiagnostics.BrowseNextCount), CreateMonitoredItemsCount = ToCounter(sessionDiagnostics.CreateMonitoredItemsCount), CreateSubscriptionCount = ToCounter(sessionDiagnostics.CreateSubscriptionCount), DeleteMonitoredItemsCount = ToCounter(sessionDiagnostics.DeleteMonitoredItemsCount), DeleteNodesCount = ToCounter(sessionDiagnostics.DeleteNodesCount), DeleteReferencesCount = ToCounter(sessionDiagnostics.DeleteReferencesCount), DeleteSubscriptionsCount = ToCounter(sessionDiagnostics.DeleteSubscriptionsCount), CallCount = ToCounter(sessionDiagnostics.CallCount), HistoryReadCount = ToCounter(sessionDiagnostics.HistoryReadCount), HistoryUpdateCount = ToCounter(sessionDiagnostics.HistoryUpdateCount), ModifyMonitoredItemsCount = ToCounter(sessionDiagnostics.ModifyMonitoredItemsCount), ModifySubscriptionCount = ToCounter(sessionDiagnostics.ModifySubscriptionCount), PublishCount = ToCounter(sessionDiagnostics.PublishCount), RegisterNodesCount = ToCounter(sessionDiagnostics.RegisterNodesCount), RepublishCount = ToCounter(sessionDiagnostics.RepublishCount), SetMonitoringModeCount = ToCounter(sessionDiagnostics.SetMonitoringModeCount), SetPublishingModeCount = ToCounter(sessionDiagnostics.SetPublishingModeCount), UnregisterNodesCount = ToCounter(sessionDiagnostics.UnregisterNodesCount), QueryFirstCount = ToCounter(sessionDiagnostics.QueryFirstCount), QueryNextCount = ToCounter(sessionDiagnostics.QueryNextCount), ReadCount = ToCounter(sessionDiagnostics.ReadCount), WriteCount = ToCounter(sessionDiagnostics.WriteCount), SetTriggeringCount = ToCounter(sessionDiagnostics.SetTriggeringCount), TotalRequestCount = ToCounter(sessionDiagnostics.TotalRequestCount), TransferSubscriptionsCount = ToCounter(sessionDiagnostics.TransferSubscriptionsCount), ServerUri = sessionDiagnostics.ServerUri, SessionName = sessionDiagnostics.SessionName, ActualSessionTimeout = sessionDiagnostics.ActualSessionTimeout, MaxResponseMessageSize = sessionDiagnostics.MaxResponseMessageSize, UnauthorizedRequestCount = sessionDiagnostics.UnauthorizedRequestCount, ConnectTime = sessionDiagnostics.ClientConnectionTime, LastContactTime = sessionDiagnostics.ClientLastContactTime, CurrentSubscriptionsCount = sessionDiagnostics.CurrentSubscriptionsCount, CurrentMonitoredItemsCount = sessionDiagnostics.CurrentMonitoredItemsCount, CurrentPublishRequestsInQueue = sessionDiagnostics.CurrentPublishRequestsInQueue, Subscriptions = subscriptions }; static ServiceCounterModel? ToCounter(ServiceCounterDataType counter) { if (counter.TotalCount == 0 && counter.ErrorCount == 0) { return null; } return new ServiceCounterModel { TotalCount = counter.TotalCount, ErrorCount = counter.ErrorCount }; } } /// /// Read operation limits /// /// /// /// private async Task FetchOperationLimitsAsync(RequestHeader header, CancellationToken ct) { // Fetch limits into the session using the new api var maxNodesPerRead = OperationLimits.MaxNodesPerRead; // Read once more to ensure we have all we need and also correctly show what is not provided. var nodes = new[] { Variables.Server_ServerCapabilities_MaxArrayLength, Variables.Server_ServerCapabilities_MaxBrowseContinuationPoints, Variables.Server_ServerCapabilities_MaxByteStringLength, Variables.Server_ServerCapabilities_MaxHistoryContinuationPoints, Variables.Server_ServerCapabilities_MaxQueryContinuationPoints, Variables.Server_ServerCapabilities_MaxStringLength, Variables.Server_ServerCapabilities_MinSupportedSampleRate, Variables.Server_ServerCapabilities_OperationLimits_MaxNodesPerHistoryReadData, Variables.Server_ServerCapabilities_OperationLimits_MaxNodesPerHistoryReadEvents, Variables.Server_ServerCapabilities_OperationLimits_MaxNodesPerWrite, Variables.Server_ServerCapabilities_OperationLimits_MaxNodesPerRead, Variables.Server_ServerCapabilities_OperationLimits_MaxNodesPerHistoryUpdateData, Variables.Server_ServerCapabilities_OperationLimits_MaxNodesPerHistoryUpdateEvents, Variables.Server_ServerCapabilities_OperationLimits_MaxNodesPerMethodCall, Variables.Server_ServerCapabilities_OperationLimits_MaxNodesPerBrowse, Variables.Server_ServerCapabilities_OperationLimits_MaxNodesPerRegisterNodes, Variables.Server_ServerCapabilities_OperationLimits_MaxNodesPerTranslateBrowsePathsToNodeIds, Variables.Server_ServerCapabilities_OperationLimits_MaxNodesPerNodeManagement, Variables.Server_ServerCapabilities_OperationLimits_MaxMonitoredItemsPerCall }; var values = Enumerable.Empty(); foreach (var chunk in nodes.Batch(Math.Max(1, (int)maxNodesPerRead))) { // Group the reads var requests = new ReadValueIdCollection(chunk .Select(n => new ReadValueId { NodeId = n, AttributeId = Attributes.Value })); var response = await ReadAsync(header, 0, Opc.Ua.TimestampsToReturn.Both, requests, ct).ConfigureAwait(false); var results = response.Validate(response.Results, d => d.StatusCode, response.DiagnosticInfos, requests); results.ThrowIfError(); values = values.Concat(results.Select(r => r.Result)); } var value = values.ToList(); return new OperationLimitsModel { MaxArrayLength = Validate32(value[0].GetValueOrDefaultEx()), MaxBrowseContinuationPoints = Validate16(value[1].GetValueOrDefaultEx()), MaxByteStringLength = Validate32(value[2].GetValueOrDefaultEx()), MaxHistoryContinuationPoints = Validate16(value[3].GetValueOrDefaultEx()), MaxQueryContinuationPoints = Validate16(value[4].GetValueOrDefaultEx()), MaxStringLength = Validate32(value[5].GetValueOrDefaultEx()), MinSupportedSampleRate = Validate64(value[6].GetValueOrDefaultEx()), MaxNodesPerHistoryReadData = Validate32(value[7].GetValueOrDefaultEx()), MaxNodesPerHistoryReadEvents = Validate32(value[8].GetValueOrDefaultEx()), MaxNodesPerWrite = Validate32(value[9].GetValueOrDefaultEx()), MaxNodesPerRead = Validate32(value[9].GetValueOrDefaultEx(), OperationLimits.MaxNodesPerRead), MaxNodesPerHistoryUpdateData = Validate32(value[10].GetValueOrDefaultEx()), MaxNodesPerHistoryUpdateEvents = Validate32(value[11].GetValueOrDefaultEx()), MaxNodesPerMethodCall = Validate32(value[12].GetValueOrDefaultEx()), MaxNodesPerBrowse = Validate32(value[13].GetValueOrDefaultEx(), OperationLimits.MaxNodesPerBrowse), MaxNodesPerRegisterNodes = Validate32(value[14].GetValueOrDefaultEx()), MaxNodesPerTranslatePathsToNodeIds = Validate32(value[15].GetValueOrDefaultEx()), MaxNodesPerNodeManagement = Validate32(value[16].GetValueOrDefaultEx()), MaxMonitoredItemsPerCall = Validate32(value[17].GetValueOrDefaultEx()) }; static uint? Validate32(uint? v, uint max = 0) => v == null || v == 0 ? null : Math.Min(max == 0 ? int.MaxValue : max, v is > 0 and < int.MaxValue ? v.Value : int.MaxValue); static ushort? Validate16(ushort? v, ushort max = 0) => v == null || v == 0 ? null : Math.Min(max == 0 ? ushort.MaxValue : max, v > 0 ? v.Value : ushort.MaxValue); static double? Validate64(double? v, double max = 0) => v == null || v == 0 ? null : Math.Min(max == 0 ? double.MaxValue : max, v > 0 ? v.Value : double.MaxValue); } /// /// Read the server capabilities if available /// /// /// /// /// /// private async Task FetchServerCapabilitiesAsync( RequestHeader requestHeader, NamespaceFormat namespaceFormat, CancellationToken ct) { // load the defaults for the historical capabilities object. #pragma warning disable CA2000 // Dispose objects before losing scope var config = new ServerCapabilitiesState(null); #pragma warning restore CA2000 // Dispose objects before losing scope config.ServerProfileArray = new PropertyState(config); config.LocaleIdArray = new PropertyState(config); config.SoftwareCertificates = new PropertyState(config); config.ModellingRules = new FolderState(config); config.AggregateFunctions = new FolderState(config); config.Create(SystemContext, null, BrowseNames.ServerCapabilities, null, false); var relativePath = new RelativePath(); relativePath.Elements.Add(new RelativePathElement { ReferenceTypeId = ReferenceTypeIds.HasComponent, IsInverse = false, IncludeSubtypes = false, TargetName = BrowseNames.ServerCapabilities }); var errorInfo = await this.ReadNodeStateAsync(requestHeader, config, Objects.Server, relativePath, ct).ConfigureAwait(false); if (errorInfo != null) { return null; } var functions = new List(); config.AggregateFunctions.GetChildren(SystemContext, functions); var aggregateFunctions = functions.OfType().ToDictionary( c => c.BrowseName.AsString(MessageContext, namespaceFormat), c => c.NodeId.AsString(MessageContext, namespaceFormat) ?? string.Empty); var rules = new List(); config.ModellingRules.GetChildren(SystemContext, rules); var modellingRules = rules.OfType().ToDictionary( c => c.BrowseName.AsString(MessageContext, namespaceFormat), c => c.NodeId.AsString(MessageContext, namespaceFormat) ?? string.Empty); var conformanceUnits = config.ConformanceUnits.GetValueOrDefaultEx( v => v == null || v.Length == 0 ? null : v.Select(q => q.AsString(MessageContext, namespaceFormat)).ToList()); return new ServerCapabilitiesModel { OperationLimits = _limits ?? new OperationLimitsModel(), ModellingRules = modellingRules.Count == 0 ? null : modellingRules, SupportedLocales = config.LocaleIdArray.GetValueOrDefaultEx( v => v == null || v.Length == 0 ? null : v), ServerProfiles = config.ServerProfileArray.GetValueOrDefaultEx( v => v == null || v.Length == 0 ? null : v), AggregateFunctions = aggregateFunctions.Count == 0 ? null : aggregateFunctions, MaxSessions = config.MaxSessions.GetValueOrDefaultEx(), MaxSubscriptions = config.MaxSubscriptions.GetValueOrDefaultEx(), MaxMonitoredItems = config.MaxMonitoredItems.GetValueOrDefaultEx(), MaxMonitoredItemsPerSubscription = config.MaxMonitoredItemsPerSubscription.GetValueOrDefaultEx(), MaxMonitoredItemsQueueSize = config.MaxMonitoredItemsQueueSize.GetValueOrDefaultEx(), MaxSubscriptionsPerSession = config.MaxSubscriptionsPerSession.GetValueOrDefaultEx(), MaxWhereClauseParameters = config.MaxWhereClauseParameters.GetValueOrDefaultEx(), MaxSelectClauseParameters = config.MaxSelectClauseParameters.GetValueOrDefaultEx(), ConformanceUnits = conformanceUnits }; } /// /// Read the history server capabilities if available /// /// /// /// /// /// private async Task FetchHistoryCapabilitiesAsync( RequestHeader requestHeader, NamespaceFormat namespaceFormat, CancellationToken ct) { // load the defaults for the historical capabilities object. #pragma warning disable CA2000 // Dispose objects before losing scope var config = new HistoryServerCapabilitiesState(null); #pragma warning restore CA2000 // Dispose objects before losing scope config.AccessHistoryDataCapability = new PropertyState(config); config.AccessHistoryEventsCapability = new PropertyState(config); config.MaxReturnDataValues = new PropertyState(config); config.MaxReturnEventValues = new PropertyState(config); config.InsertDataCapability = new PropertyState(config); config.ReplaceDataCapability = new PropertyState(config); config.UpdateDataCapability = new PropertyState(config); config.DeleteRawCapability = new PropertyState(config); config.DeleteAtTimeCapability = new PropertyState(config); config.InsertEventCapability = new PropertyState(config); config.ReplaceEventCapability = new PropertyState(config); config.UpdateEventCapability = new PropertyState(config); config.DeleteEventCapability = new PropertyState(config); config.InsertAnnotationCapability = new PropertyState(config); config.ServerTimestampSupported = new PropertyState(config); config.AggregateFunctions = new FolderState(config); config.Create(SystemContext, null, BrowseNames.HistoryServerCapabilities, null, false); var relativePath = new RelativePath(); relativePath.Elements.Add(new RelativePathElement { ReferenceTypeId = ReferenceTypeIds.HasComponent, IsInverse = false, IncludeSubtypes = false, TargetName = BrowseNames.HistoryServerCapabilities }); var errorInfo = await this.ReadNodeStateAsync(requestHeader, config, Objects.Server_ServerCapabilities, relativePath, ct).ConfigureAwait(false); if (errorInfo != null) { return null; } var supportsValues = config.AccessHistoryDataCapability.GetValueOrDefaultEx() ?? false; var supportsEvents = config.AccessHistoryEventsCapability.GetValueOrDefaultEx() ?? false; Dictionary? aggregateFunctions = null; if (supportsEvents || supportsValues) { var children = new List(); config.AggregateFunctions.GetChildren(SystemContext, children); aggregateFunctions = children.OfType().ToDictionary( c => c.BrowseName.AsString(MessageContext, namespaceFormat), c => c.NodeId.AsString(MessageContext, namespaceFormat) ?? string.Empty); } return new HistoryServerCapabilitiesModel { AccessHistoryDataCapability = supportsValues, AccessHistoryEventsCapability = supportsEvents, MaxReturnDataValues = config.MaxReturnDataValues.GetValueOrDefaultEx( v => !supportsValues ? null : v == 0 ? uint.MaxValue : v), MaxReturnEventValues = config.MaxReturnEventValues.GetValueOrDefaultEx( v => !supportsEvents ? null : v == 0 ? uint.MaxValue : v), InsertDataCapability = config.InsertDataCapability.GetValueOrDefaultEx(), ReplaceDataCapability = config.ReplaceDataCapability.GetValueOrDefaultEx(), UpdateDataCapability = config.UpdateDataCapability.GetValueOrDefaultEx(), DeleteRawCapability = config.DeleteRawCapability.GetValueOrDefaultEx(), DeleteAtTimeCapability = config.DeleteAtTimeCapability.GetValueOrDefaultEx(), InsertEventCapability = config.InsertEventCapability.GetValueOrDefaultEx(), ReplaceEventCapability = config.ReplaceEventCapability.GetValueOrDefaultEx(), UpdateEventCapability = config.UpdateEventCapability.GetValueOrDefaultEx(), DeleteEventCapability = config.DeleteEventCapability.GetValueOrDefaultEx(), InsertAnnotationCapability = config.InsertAnnotationCapability.GetValueOrDefaultEx(), ServerTimestampSupported = config.ServerTimestampSupported.GetValueOrDefaultEx(), AggregateFunctions = aggregateFunctions == null || aggregateFunctions.Count == 0 ? null : aggregateFunctions }; } /// /// Set appropriate operation timeouts /// /// internal void UpdateOperationTimeout(bool closing) { // // The OperationTimeout while publishing should be twice the // value for PublishingInterval * KeepAliveCount // if (closing) { OperationTimeout = 2000; // Update to 2 seconds for closing return; } var timeout = Subscriptions .Select(s => s.CurrentPublishingInterval * s.CurrentKeepAliveCount) .DefaultIfEmpty(0) .Max() * 2; if (timeout < _defaultOperationTimeout) { timeout = _defaultOperationTimeout; } if (timeout > kMaxOperationTimeout.TotalMilliseconds) { timeout = kMaxOperationTimeout.TotalMilliseconds; } if (OperationTimeout != timeout) { OperationTimeout = (int)timeout; _logger.OperationTimeoutUpdated(TimeSpan.FromMilliseconds(timeout)); } } /// /// Load complex type system /// /// private Task LoadComplexTypeSystemAsync() { Debug.Assert(!_client.DisableComplexTypeLoading); return Task.Run(async () => { if (Connected) { var complexTypeSystem = new ComplexTypeSystem(new NodeCacheResolver(LruNodeCache)); await complexTypeSystem.LoadAsync(ct: _cts.Token).ConfigureAwait(false); if (Connected) { _logger.ComplexTypeSystemLoaded(this); // Clear cache to release memory. // TODO: we should have a real node cache here return complexTypeSystem; } } throw new ServiceResultException(StatusCodes.BadNotConnected); }, _cts.Token); } /// /// Begin request /// /// /// /// private SessionActivity Begin(RequestHeader header) where T : IServiceResponse, new() { var activity = new SessionActivity(this, typeof(T).Name[0..^8]); if (!Connected) { var error = new T(); error.ResponseHeader.ServiceResult = StatusCodes.BadNotConnected; error.ResponseHeader.Timestamp = _timeProvider.GetUtcNow().UtcDateTime; var text = error.ResponseHeader.StringTable.Count; error.ResponseHeader.StringTable.Add("Session not connected."); var locale = error.ResponseHeader.StringTable.Count; error.ResponseHeader.StringTable.Add("en-US"); var symbol = error.ResponseHeader.StringTable.Count; error.ResponseHeader.StringTable.Add("BadNotConnected"); error.ResponseHeader.ServiceDiagnostics = new DiagnosticInfo { SymbolicId = symbol, Locale = locale, LocalizedText = text }; activity.Error = error; } else { header.RequestHandle = NewRequestHandle(); header.AuthenticationToken = AuthenticationToken; header.Timestamp = _timeProvider.GetUtcNow().UtcDateTime; } return activity; } /// /// Session activity /// /// private sealed class SessionActivity : IDisposable where T : IServiceResponse, new() { /// /// Any error to convey /// public T? Error { get; set; } /// public SessionActivity(OpcUaSession outer, string activity) { _activity = outer._activitySource.StartActivity(activity); if (outer._logger.IsEnabled(LogLevel.Debug)) { _logScope = new LogScope(activity, Stopwatch.StartNew(), outer._logger); _logScope.logger.LogDebug("Session activity {Activity} started...", _logScope.name); } } /// public void Dispose() { _activity?.Dispose(); _logScope?.logger.LogDebug( "Session activity {Activity} completed in {Elapsed} with {Status}.", _logScope.name, _logScope.sw.Elapsed, Error?.ResponseHeader?.ServiceResult == null ? "Good" : StatusCodes.GetBrowseName(Error.ResponseHeader.ServiceResult.CodeBits)); } /// /// Gets the response /// /// /// /// public T ValidateResponse(IServiceResponse response) { if (response?.ResponseHeader == null) { // Throw - this is likely an issue in the transport. throw new ServiceResultException(StatusCodes.BadUnknownResponse); } if (response is not T result) { // Received a response, but not the type we expected. // Promote to expected Type. result = new T(); result.ResponseHeader.ServiceResult = response.ResponseHeader.ServiceResult; result.ResponseHeader.StringTable = response.ResponseHeader.StringTable; result.ResponseHeader.AdditionalHeader = response.ResponseHeader.AdditionalHeader; result.ResponseHeader.RequestHandle = response.ResponseHeader.RequestHandle; result.ResponseHeader.ServiceDiagnostics = response.ResponseHeader.ServiceDiagnostics; result.ResponseHeader.Timestamp = response.ResponseHeader.Timestamp; } if (StatusCode.IsBad(result.ResponseHeader.ServiceResult)) { Error = result; } return result; } private sealed record class LogScope(string name, Stopwatch sw, ILogger logger); private readonly Activity? _activity; private readonly LogScope? _logScope; } private ServerCapabilitiesModel? _server; private OperationLimitsModel? _limits; private SessionDiagnosticsModel? _lastDiagnostics; private HistoryServerCapabilitiesModel? _history; private Task? _complexTypeSystem; private bool _disposed; private bool? _diagnosticsEnabled; private int _defaultOperationTimeout; private readonly CancellationTokenSource _cts = new(); private readonly ILogger _logger; private readonly OpcUaClient _client; private readonly IJsonSerializer _serializer; private readonly TimeProvider _timeProvider; private readonly ActivitySource _activitySource = Diagnostics.NewActivitySource(); private static readonly TimeSpan kDefaultOperationTimeout = TimeSpan.FromMinutes(1); private static readonly TimeSpan kDefaultKeepAliveInterval = TimeSpan.FromSeconds(30); private static readonly TimeSpan kMaxOperationTimeout = TimeSpan.FromMinutes(30); } /// /// Source-generated logging definitions for OpcUaSession /// internal static partial class OpcUaSessionLogging { private const int EventClass = 1200; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Debug, Message = "{Session}: Session disposed.")] public static partial void SessionDisposed(this ILogger logger, string session); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Debug, Message = "Failed to fetch server diagnostics.")] public static partial void ServerDiagnosticsFetchFailed(this ILogger logger, ServiceResultException sre); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Error, Message = "{Session}: Attempt #{Attempt}. Failed to get complex type system.")] public static partial void ComplexTypeSystemFailed(this ILogger logger, OpcUaSession session, int attempt, Exception ex); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Error, Message = "Session diagnostics disabled and failed to enable ({Error}).")] public static partial void DiagnosticsEnableFailed(this ILogger logger, string error); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Information, Message = "Session diagnostics not retrievable ({Error1}/{Error2}).")] public static partial void DiagnosticsNotRetrievable(this ILogger logger, string error1, string error2); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Error, Message = "Failed to find diagnostics for this session ({Error}).")] public static partial void DiagnosticsNotFound(this ILogger logger, string error); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Information, Message = "Subscription diagnostics not retrievable ({Error}).")] public static partial void SubscriptionDiagnosticsNotRetrievable(this ILogger logger, string error); [LoggerMessage(EventId = EventClass + 8, Level = LogLevel.Information, Message = "Operation timeout updated to {Timeout}.")] public static partial void OperationTimeoutUpdated(this ILogger logger, TimeSpan timeout); [LoggerMessage(EventId = EventClass + 9, Level = LogLevel.Information, Message = "{Session}: Complex type system loaded into client.")] public static partial void ComplexTypeSystemLoaded(this ILogger logger, OpcUaSession session); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaStack.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Services { using Autofac; using Furly.Extensions.Logging; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Opc.Ua; using System; /// /// Injectable service that registers a logger with stack /// public sealed class OpcUaStack : IStartable, IDisposable { /// /// Create stack logger /// /// /// public OpcUaStack(ILogger logger, IOptions options) { var enabled = options.Value.EnableOpcUaStackLogging ?? false; Utils.SetLogger(enabled ? logger : new ErrorLogger(logger)); } /// public void Start() { // No op } /// public void Dispose() { Utils.SetLogger(Log.Console()); } /// /// Just log at error level (disabled) /// private sealed class ErrorLogger : ILogger { /// public ErrorLogger(ILogger logger) { _logger = logger; } /// public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) { if (logLevel >= LogLevel.Error) { _logger.StackMessage(exception, formatter(state, exception)); } } /// public bool IsEnabled(LogLevel logLevel) { return logLevel >= LogLevel.Error; } /// public IDisposable? BeginScope(TState state) where TState : notnull { return _logger.BeginScope(state); } private readonly ILogger _logger; } } /// /// Source-generated logging extensions for OpcUaStack /// internal static partial class OpcUaStackLogging { private const int EventClass = 1200; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Error, Message = "{message}")] public static partial void StackMessage(this ILogger logger, Exception? exception, string message); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaStackKeySetLogger.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Services { using Azure.IIoT.OpcUa.Publisher.Models; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System; using System.Globalization; using System.IO; using System.Threading; using System.Threading.Tasks; /// /// /// Wireshark 4.3 now allows decryption of the UA binary protocol using a keyset log /// (opc ua debug file). The file contains records in the following format: /// /// /// client_iv_%channel_id%_%token_id%: %hex-string% /// client_key_%channel_id%_%token_id%: %hex-string% /// client_siglen_%channel_id%_%token_id%: 32 /// server_iv_%channel_id%_%token_id%: %hex-string% /// server_key_%channel_id%_%token_id%: %hex-string% /// server_siglen_%channel_id%_%token_id%: 16|24|32 /// ... /// /// /// This class writes the file to disk if a file was configured /// See: https://gitlab.com/wireshark/wireshark/-/blob/master/plugins/epan/opcua/opcua.c#L232 /// /// public sealed class OpcUaStackKeySetLogger : IDisposable { /// /// Create logger /// /// /// /// public OpcUaStackKeySetLogger(IOptions options, IClientDiagnostics diagnostics, ILogger logger) { _diagnostics = diagnostics; _logger = logger; _cts = new CancellationTokenSource(); if (options.Value.OpcUaKeySetLogFolderName == null) { _task = Task.CompletedTask; return; } _task = WriteDebugFileAsync(options.Value.OpcUaKeySetLogFolderName, _cts.Token); } /// public void Dispose() { try { _cts.Cancel(); _task.GetAwaiter().GetResult(); } catch { _cts.Dispose(); } } /// /// Log debug file to disk /// /// /// /// public async Task WriteDebugFileAsync(string folderName, CancellationToken ct) { var rootFolder = Path.Combine(folderName, "opcua_debug"); if (Directory.Exists(rootFolder)) { Directory.Delete(rootFolder, true); } await foreach (var change in _diagnostics.WatchChannelDiagnosticsAsync( ct).ConfigureAwait(false)) { try { await WriteDebugLogFileAsync(rootFolder, change, ct).ConfigureAwait(false); } catch (Exception ex) { _logger.FailedToWriteDebugLogFile(ex); } } } /// /// Write diagnostic change to log file /// /// /// /// /// private static async Task WriteDebugLogFileAsync(string rootFolder, ChannelDiagnosticModel change, CancellationToken ct) { if (change?.Client == null || change?.Server == null || change.SessionCreated == null || change.RemotePort == null) { // Not a valid change, channel without keys return; } var keySetLogPath = Path.Combine(rootFolder, "ports", change.RemotePort.Value.ToString(CultureInfo.InvariantCulture), "connection", change.Connection.CreateConsistentHash() .ToString("X", CultureInfo.InvariantCulture), change.SessionCreated.Value.UtcDateTime.ToBinary() .ToString(CultureInfo.InvariantCulture)); if (!Directory.Exists(keySetLogPath)) { Directory.CreateDirectory(keySetLogPath); } var keysetsFileName = Path.Combine(keySetLogPath, "opcua_debug.txt"); var keysetFileRoot = keysetsFileName.Replace(rootFolder, ".", StringComparison.OrdinalIgnoreCase); var log = File.AppendText(Path.Combine(rootFolder, "log.md")); await using (var _ = log.ConfigureAwait(false)) { await log.WriteLineAsync($"# {change.TimeStamp}") .ConfigureAwait(false); await log.WriteLineAsync($"[KeySetFile]({keysetFileRoot})") .ConfigureAwait(false); await log.WriteLineAsync($"EndpointUrl: {change.Connection.Endpoint?.Url}") .ConfigureAwait(false); await log.WriteLineAsync($"RemoteEP: {change.RemoteIpAddress}:{change.RemotePort}") .ConfigureAwait(false); await log.WriteLineAsync($"LocalEP: {change.LocalIpAddress}:{change.LocalPort}") .ConfigureAwait(false); await log.WriteLineAsync($"ChannelId: {change.ChannelId}") .ConfigureAwait(false); await log.WriteLineAsync($"TokenId: {change.TokenId}") .ConfigureAwait(false); await log.WriteLineAsync($"Session: {change.SessionId}") .ConfigureAwait(false); await log.WriteLineAsync($"Created: {change.SessionCreated}") .ConfigureAwait(false); await log.WriteLineAsync($"SecurityMode: {change.Connection.Endpoint?.SecurityMode}") .ConfigureAwait(false); await log.WriteLineAsync($"SecurityProfile: {change.Connection.Endpoint?.SecurityPolicy}") .ConfigureAwait(false); await log.FlushAsync(ct).ConfigureAwait(false); } var keysets = File.AppendText(keysetsFileName); await using (var _ = keysets.ConfigureAwait(false)) { await keysets.WriteAsync($"client_iv_{change.ChannelId}_{change.TokenId}: ") .ConfigureAwait(false); await keysets.WriteLineAsync(Convert.ToHexString([.. change.Client.Iv])) .ConfigureAwait(false); await keysets.WriteAsync($"client_key_{change.ChannelId}_{change.TokenId}: ") .ConfigureAwait(false); await keysets.WriteLineAsync(Convert.ToHexString([.. change.Client.Key])) .ConfigureAwait(false); await keysets.WriteAsync($"client_siglen_{change.ChannelId}_{change.TokenId}: ") .ConfigureAwait(false); await keysets.WriteLineAsync(change.Client.SigLen.ToString(CultureInfo.InvariantCulture)) .ConfigureAwait(false); await keysets.WriteAsync($"server_iv_{change.ChannelId}_{change.TokenId}: ") .ConfigureAwait(false); await keysets.WriteLineAsync(Convert.ToHexString([.. change.Server.Iv])) .ConfigureAwait(false); await keysets.WriteAsync($"server_key_{change.ChannelId}_{change.TokenId}: ") .ConfigureAwait(false); await keysets.WriteLineAsync(Convert.ToHexString([.. change.Server.Key])) .ConfigureAwait(false); await keysets.WriteAsync($"server_siglen_{change.ChannelId}_{change.TokenId}: ") .ConfigureAwait(false); await keysets.WriteLineAsync(change.Server.SigLen.ToString(CultureInfo.InvariantCulture)) .ConfigureAwait(false); await keysets.FlushAsync(ct).ConfigureAwait(false); } } private readonly Task _task; private readonly CancellationTokenSource _cts; private readonly IClientDiagnostics _diagnostics; private readonly ILogger _logger; } /// /// Source-generated logging extensions for OpcUaStackKeySetLogger /// internal static partial class OpcUaStackKeySetLoggerLogging { private const int EventClass = 1300; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Error, Message = "Failed to write changes to debug log file.")] public static partial void FailedToWriteDebugLogFile(this ILogger logger, Exception ex); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaSubscription.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Services { using Azure.IIoT.OpcUa.Publisher.Stack.Extensions; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Encoders.PubSub; using Furly.Extensions.Utils; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Opc.Ua; using Opc.Ua.Client; using Opc.Ua.Client.ComplexTypes; using Opc.Ua.Extensions; using System; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Metrics; using System.Linq; using System.Runtime.Serialization; using System.Text; using System.Threading; using System.Threading.Tasks; /// /// Subscription implementation /// [DataContract(Namespace = OpcUaClient.Namespace)] [KnownType(typeof(OpcUaMonitoredItem))] [KnownType(typeof(OpcUaMonitoredItem.DataChange))] [KnownType(typeof(OpcUaMonitoredItem.CyclicRead))] [KnownType(typeof(OpcUaMonitoredItem.Heartbeat))] [KnownType(typeof(OpcUaMonitoredItem.ModelChangeEventItem))] [KnownType(typeof(OpcUaMonitoredItem.Event))] [KnownType(typeof(OpcUaMonitoredItem.Condition))] internal sealed class OpcUaSubscription : Subscription, IAsyncDisposable, IEquatable { /// /// Template for subscription /// public SubscriptionModel Template { get; private set; } /// /// Is root subscription /// public bool IsRoot => _parentId == null; /// /// Unique subscription identifier in the process /// public uint SubscriptionId { get; } /// /// The name of the subscription /// public string Name { get; private set; } /// /// Whether the subscription is online /// internal bool IsOnline => Session?.Connected == true && !IsClosed; /// /// Whether subscription is closed /// internal bool IsClosed => _disposed || Session == null; /// /// Currently monitored but unordered /// private IEnumerable CurrentlyMonitored => MonitoredItems.OfType(); public byte DesiredPriority => Template.Priority ?? Session?.DefaultSubscription?.Priority ?? 0; public uint DesiredMaxNotificationsPerPublish => Template.MaxNotificationsPerPublish ?? Session?.DefaultSubscription?.MaxNotificationsPerPublish ?? 0; public uint DesiredLifetimeCount => Template.LifetimeCount ?? _options.Value.DefaultLifeTimeCount ?? DefaultLifetimeCount; public uint DefaultLifetimeCount { get { var desiredPublishingInterval = DesiredPublishingInterval; if (desiredPublishingInterval >= TimeSpan.FromSeconds(60)) { // If greater than a minute we request a lifetime count // of 2 (min 2 mins). That means we allow the subscription // to recover in another cycle. This could be faster than // when the publishing interval was set to 55 seconds. return 2; } else if (desiredPublishingInterval >= TimeSpan.FromSeconds(30)) { // If between 30 and 60 seconds, allow 3 times keep alive // interval (min 90 seconds, up to 3 minutes) until // we declare the subscription dead. This means the // subscription will take min 7.5 minutes, max 15 minutes // to get reset if it is defunct. return 3; } else if (desiredPublishingInterval >= TimeSpan.FromSeconds(5)) { // If between 5 and 60 seconds, allow 5 times keep alive // interval (min 10 seconds, up to 2 minutes) until // we declare the subscription dead. This means the // subscription will take min 50 seconds, max 10 minutes // to get reset if it is defunct. return 5; } else { // Otherwise let the server decide the lifetime count return 0; } } } public uint DesiredKeepAliveCount => Template.KeepAliveCount ?? _options.Value.DefaultKeepAliveCount ?? DefaultKeepAliveCount; public uint DefaultKeepAliveCount { get { var desiredPublishingInterval = DesiredPublishingInterval; if (desiredPublishingInterval >= TimeSpan.FromSeconds(60)) { // If greater than a minute we force a keep alive count of 1 // We see this setting is used by users to get messages every // publishing interval duration, but then nothing recovers. return 1; } else if (desiredPublishingInterval >= TimeSpan.FromSeconds(5)) { // Limit the keep alive timeout to twice the publishing // interval (min 10 seconds, up to 2 minutes). return 2; } else { // Otherwise let the server decide the keep alive count return 0; } } } public TimeSpan DesiredPublishingInterval => Template.PublishingInterval ?? _options.Value.DefaultPublishingInterval ?? TimeSpan.FromSeconds(1); public bool UseDeferredAcknoledgements => Template.UseDeferredAcknoledgements ?? _options.Value.UseDeferredAcknoledgements ?? false; public bool EnableImmediatePublishing => Template.EnableImmediatePublishing ?? _options.Value.EnableImmediatePublishing ?? false; public bool EnableSequentialPublishing => Template.EnableSequentialPublishing ?? _options.Value.EnableSequentialPublishing ?? true; public bool DesiredRepublishAfterTransfer => Template.RepublishAfterTransfer ?? _options.Value.DefaultRepublishAfterTransfer ?? false; public TimeSpan MonitoredItemWatchdogTimeout => Template.MonitoredItemWatchdogTimeout ?? _options.Value.DefaultMonitoredItemWatchdogTimeout ?? TimeSpan.Zero; public MonitoredItemWatchdogCondition WatchdogCondition => Template.WatchdogCondition ?? _options.Value.DefaultMonitoredItemWatchdogCondition ?? MonitoredItemWatchdogCondition.WhenAnyIsLate; public SubscriptionWatchdogBehavior? WatchdogBehavior => Template.WatchdogBehavior ?? _options.Value.DefaultWatchdogBehavior; public bool ResolveBrowsePathFromRoot => Template.ResolveBrowsePathFromRoot ?? _options.Value.FetchOpcBrowsePathFromRoot ?? false; /// /// Keep alive timeout /// internal TimeSpan KeepAliveTimeout => TimeSpan.FromMilliseconds( (CurrentPublishingInterval * CurrentKeepAliveCount) + 1000); /// /// Subscription /// /// /// /// /// /// /// /// internal OpcUaSubscription(OpcUaClient client, SubscriptionModel template, IOptions options, ILoggerFactory loggerFactory, IMetricsContext metrics, uint? parentId = null, TimeProvider? timeProvider = null) { _client = client; _options = options; _loggerFactory = loggerFactory; _metrics = metrics; _parentId = parentId; _timeProvider = timeProvider ?? TimeProvider.System; Template = template; Name = Template.CreateSubscriptionId(); SubscriptionId = Opc.Ua.SequenceNumber.Increment32(ref _lastIndex); _logger = _loggerFactory.CreateLogger(); Initialize(); _keepAliveWatcher = _timeProvider.CreateTimer(OnKeepAliveMissing, null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); _monitoredItemWatcher = _timeProvider.CreateTimer(OnMonitoredItemWatchdog, null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); _resyncTimer = _timeProvider.CreateTimer(OnResync, null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); InitializeMetrics(); _client.OnSubscriptionCreated(this); ResetMonitoredItemWatchdogTimer(PublishingEnabled); } /// /// Copy constructor /// /// /// private OpcUaSubscription(OpcUaSubscription subscription, bool copyEventHandlers) : base(subscription, copyEventHandlers) { _options = subscription._options; _loggerFactory = subscription._loggerFactory; _timeProvider = subscription._timeProvider; _metrics = subscription._metrics; _firstDataChangeReceived = subscription._firstDataChangeReceived; Template = subscription.Template; Name = subscription.Name; SubscriptionId = subscription.SubscriptionId; _parentId = subscription._parentId; _client = subscription._client; _logger = subscription._logger; _sequenceNumber = subscription._sequenceNumber; _goodMonitoredItems = subscription._goodMonitoredItems; _badMonitoredItems = subscription._badMonitoredItems; _lateMonitoredItems = subscription._lateMonitoredItems; _reportingItems = subscription._reportingItems; _disabledItems = subscription._disabledItems; _samplingItems = subscription._samplingItems; _notAppliedItems = subscription._notAppliedItems; _missingKeepAlives = subscription._missingKeepAlives; _unassignedNotifications = subscription._unassignedNotifications; _continuouslyMissingKeepAlives = subscription._continuouslyMissingKeepAlives; Initialize(); _keepAliveWatcher = _timeProvider.CreateTimer(OnKeepAliveMissing, null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); _monitoredItemWatcher = _timeProvider.CreateTimer(OnMonitoredItemWatchdog, null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); _resyncTimer = _timeProvider.CreateTimer(OnResync, null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); InitializeMetrics(); _client.OnSubscriptionCreated(this); } /// /// Copy constructor /// /// /// private OpcUaSubscription(OpcUaSubscription subscription, uint parentId) { _options = subscription._options; _loggerFactory = subscription._loggerFactory; _timeProvider = subscription._timeProvider; _client = subscription._client; _metrics = subscription._metrics; _parentId = parentId; Template = subscription.Template; Name = subscription.Name; SubscriptionId = Opc.Ua.SequenceNumber.Increment32(ref _lastIndex); _logger = _loggerFactory.CreateLogger(); Initialize(); _keepAliveWatcher = _timeProvider.CreateTimer(OnKeepAliveMissing, null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); _monitoredItemWatcher = _timeProvider.CreateTimer(OnMonitoredItemWatchdog, null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); _resyncTimer = _timeProvider.CreateTimer(OnResync, null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); InitializeMetrics(); ResetMonitoredItemWatchdogTimer(PublishingEnabled); } /// public override object Clone() { return new OpcUaSubscription(this, true); } /// public override Subscription CloneSubscription(bool copyEventHandlers) { return new OpcUaSubscription(this, copyEventHandlers); } /// public override string? ToString() { var sb = new StringBuilder() .Append(Id) .Append(':') .Append(SubscriptionId) .Append(':'); if (_parentId != null) { sb = sb .Append(_parentId.Value) .Append("->"); } sb = sb.Append(Name); if (_childId != null) { sb = sb .Append("->") .Append(_childId.Value); } return sb.ToString(); } /// public override bool Equals(object? obj) { if (obj is OpcUaSubscription subscription) { return subscription.Template.Equals(Template) && subscription.SubscriptionId == SubscriptionId; } return false; } /// public bool Equals(OpcUaSubscription? other) { if (other is null) { return false; } return other.Template.Equals(Template) && other.SubscriptionId == SubscriptionId; } /// public override int GetHashCode() { return Template.GetHashCode(); } /// protected override void Dispose(bool disposing) { if (disposing && !_disposed) { try { _resyncTimer.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); ResetMonitoredItemWatchdogTimer(false); _keepAliveWatcher.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); FastDataChangeCallback = null; FastEventCallback = null; FastKeepAliveCallback = null; PublishStatusChanged -= OnPublishStatusChange; StateChanged -= OnStateChange; var items = CurrentlyMonitored.ToList(); if (items.Count != 0) { // // When the entire session is disposed and recreated we must // still dispose all monitored items that are remaining // items.ForEach(item => item.Dispose()); RemoveItems(MonitoredItems); Debug.Assert(!CurrentlyMonitored.Any()); _logger.SubscriptionDisposedWithItems(this, items.Count); } else { _logger.SubscriptionDisposed(this); } } catch (Exception ex) { _logger.DisposalError(ex, this); // Eat the error } finally { _disposed = true; _keepAliveWatcher.Dispose(); _monitoredItemWatcher.Dispose(); _resyncTimer.Dispose(); _meter.Dispose(); Handle = null; } } base.Dispose(disposing); } /// public async ValueTask DisposeAsync() { // // Called by the management thread to "close" the subscription and dispose it. // Note that the session calls dispose again or when it is closed or // reconnected. This here is called when the management thread determines // to gracefully close the subscription. // try { // first close the children var child = GetChildSubscription(); if (child != null) { await child.DisposeAsync().ConfigureAwait(false); } if (IsClosed) { return; } Debug.Assert(Session != null); ResetKeepAliveTimer(); ResetMonitoredItemWatchdogTimer(false); // Does not throw await CloseCurrentSubscriptionAsync().ConfigureAwait(false); _logger.SubscriptionClosed(this); Debug.Assert(Session == null); } finally { Dispose(); } } /// /// Try get the current position in the out stream. This is called /// on all subscriptions in the session and takes child subscriptions /// into account /// /// /// /// internal bool TryGetCurrentPosition(out uint subscriptionId, out uint sequenceNumber) { subscriptionId = Id; sequenceNumber = _currentSequenceNumber; return UseDeferredAcknoledgements; } /// /// Notify session disconnected/reconnecting. This is called /// on all subscriptions in the session and takes child subscriptions /// into account /// /// /// internal void NotifySessionConnectionState(bool disconnected) { foreach (var item in CurrentlyMonitored) { item.NotifySessionConnectionState(disconnected); } } /// /// Create a keep alive message /// /// internal OpcUaSubscriptionNotification? CreateKeepAlive() { Debug.Assert(IsRoot); if (IsClosed) { _logger.SubscriptionClosedError(this); return null; } try { var session = Session; if (session == null) { return null; } return new OpcUaSubscriptionNotification(this, session.MessageContext, Array.Empty(), _timeProvider) { ApplicationUri = session.Endpoint.Server.ApplicationUri ?? _client.ApplicationUri, EndpointUrl = session.Endpoint.EndpointUrl, SequenceNumber = Opc.Ua.SequenceNumber.Increment32(ref _sequenceNumber), MessageType = MessageType.KeepAlive }; } catch (Exception ex) { _logger.KeepAliveCreateFailed(ex, this); return null; } } /// /// Get number of good monitored item for the subscriber across /// this and all child subscriptions /// /// /// internal int GetGoodMonitoredItems(ISubscriber owner) { Debug.Assert(IsRoot); return GetAllMonitoredItems().Count(r => r is OpcUaMonitoredItem h && h.Owner == owner && h.IsGood); } /// /// Get number of bad monitored item for the subscriber across /// this and all child subscriptions /// /// /// internal int GetBadMonitoredItems(ISubscriber owner) { Debug.Assert(IsRoot); return GetAllMonitoredItems().Count(r => r is OpcUaMonitoredItem h && h.Owner == owner && h.IsBad); } /// /// Get number of late monitored item for the subscriber across /// this and all child subscriptions /// /// /// internal int GetLateMonitoredItems(ISubscriber owner) { Debug.Assert(IsRoot); return GetAllMonitoredItems().Count(r => r is OpcUaMonitoredItem h && h.Owner == owner && h.IsLate); } /// /// Get number of enabled heartbeats for the subscriber across /// this and all child subscriptions /// /// /// internal int GetHeartbeatsEnabled(ISubscriber owner) { Debug.Assert(IsRoot); return GetAllMonitoredItems().Count(r => r is OpcUaMonitoredItem.Heartbeat h && h.Owner == owner && h.TimerEnabled); } /// /// Get number of conditions enabled for the subscriber across /// this and all child subscriptions /// /// /// internal int GetConditionsEnabled(ISubscriber owner) { Debug.Assert(IsRoot); return GetAllMonitoredItems().Count(r => r is OpcUaMonitoredItem.Condition h && h.Owner == owner && h.TimerEnabled); } /// /// Collect metadata for the subscriber across this and all child /// subscriptions /// /// /// /// /// /// /// /// internal async ValueTask CollectMetaDataAsync( ISubscriber owner, DataSetFieldContentFlags? dataSetFieldContentMask, DataSetMetaDataModel dataSetMetaData, uint minorVersion, CancellationToken ct) { Debug.Assert(IsRoot); if (Session is not OpcUaSession session) { throw ServiceResultException.Create(StatusCodes.BadSessionIdInvalid, "Session not connected."); } var typeSystem = await session.GetComplexTypeSystemAsync(ct).ConfigureAwait(false); var dataTypes = new NodeIdDictionary(); var fields = new List(); await CollectMetaDataAsync(owner, session, typeSystem, dataTypes, fields, ct).ConfigureAwait(false); return new PublishedDataSetMetaDataModel { DataSetMetaData = dataSetMetaData, EnumDataTypes = dataTypes.Values.OfType().ToList(), StructureDataTypes = dataTypes.Values.OfType().ToList(), SimpleDataTypes = dataTypes.Values.OfType().ToList(), Fields = fields, MinorVersion = minorVersion }; } /// /// Update subscription configuration and apply changes later during /// synchronization. This is used when the subscription is owned by a /// single subscriber and the configuration is updated. /// /// internal void Update(SubscriptionModel template) { // Debug.Assert(IsRoot); -- called recursively down to all children. Template = template; Name = Template.CreateSubscriptionId(); GetChildSubscription()?.Update(template); } /// /// Create or update the subscription now using the currently configured /// subscription configuration template. /// /// /// /// /// /// internal async ValueTask SyncAsync(uint? maxMonitoredItemsPerSubscription, OperationLimitsModel limits, CancellationToken ct) { Debug.Assert(IsRoot); if (_disposed) { throw ServiceResultException.Create(StatusCodes.BadUnexpectedError, "Subscription was disposed."); } var maxMonitoredItems = maxMonitoredItemsPerSubscription ?? 0u; if (maxMonitoredItems <= 0) { maxMonitoredItems = _options.Value.MaxMonitoredItemPerSubscription ?? kMaxMonitoredItemPerSubscriptionDefault; } Debug.Assert(Session != null); if (Session is not OpcUaSession session) { throw ServiceResultException.Create(StatusCodes.BadUnexpectedError, "Session not of expected type."); } var retryDelay = TimeSpan.MaxValue; // Force recreate all subscriptions in the chain if needed await ForceRecreateIfNeededAsync(session).ConfigureAwait(false); // Parition the monitored items across subscriptions var partitions = Partition.Create(_client.GetSubscribers(Template), maxMonitoredItems, _options.Value); var subscriptionPartition = this; // The root is the default for (var partitionIdx = 0; partitionIdx < partitions.Count; partitionIdx++) { // Synchronize the subscription of this partition await subscriptionPartition.SynchronizeSubscriptionAsync( ct).ConfigureAwait(false); // Add partitioned items var partition = partitions[partitionIdx]; var delay = await subscriptionPartition.SynchronizeMonitoredItemsAsync( partition, limits, ct).ConfigureAwait(false); if (retryDelay > delay) { retryDelay = delay; } if (partitionIdx == partitions.Count - 1) { break; } // Get or create a child subscription subscriptionPartition = subscriptionPartition.GetChildSubscription(true); if (subscriptionPartition == null) { throw ServiceResultException.Create(StatusCodes.BadUnexpectedError, "Failed to create child subscription."); } } // // subscription now is the tail or head subscription. We remove // all child subscriptions below it as they are not needed anymore. // var tail = subscriptionPartition; while (tail != null) { tail = tail.GetChildSubscription(); if (tail != null) { await tail.DisposeAsync().ConfigureAwait(false); } } // Snip off here subscriptionPartition._childId = null; // Force finalize all subscriptions in the (new) chain if needed await FinalizeSyncAsync(ct).ConfigureAwait(false); if (IsRoot && retryDelay > TimeSpan.Zero && retryDelay != TimeSpan.MaxValue) { _resyncTimer.Change(retryDelay, Timeout.InfiniteTimeSpan); _logger.ResyncTimerArmed(retryDelay, this); } } /// /// Force recreate all subscriptions in the chain if needed /// /// /// private async Task ForceRecreateIfNeededAsync(OpcUaSession session) { var child = GetChildSubscription(); if (child != null) { await child.ForceRecreateIfNeededAsync(session).ConfigureAwait(false); } if (!_forceRecreate) { return; } _forceRecreate = false; _logger.ClosingAndRecreatingSubscription(this); // Does not throw await CloseCurrentSubscriptionAsync().ConfigureAwait(false); Debug.Assert(Session == null); session.AddSubscription(this); // Re-add the subscription now Debug.Assert(Session == session); } /// /// Finalize sync of all subscriptions in the chain if needed /// /// /// private async Task FinalizeSyncAsync(CancellationToken ct) { var child = GetChildSubscription(); if (child != null) { await child.FinalizeSyncAsync(ct).ConfigureAwait(false); } if (ChangesPending) { await ApplyChangesAsync(ct).ConfigureAwait(false); } var shouldEnable = MonitoredItems .OfType() .Any(m => m.AttachedToSubscription && m.MonitoringMode != Opc.Ua.MonitoringMode.Disabled); if (PublishingEnabled ^ shouldEnable) { await SetPublishingModeAsync(shouldEnable, ct).ConfigureAwait(false); _logger.StateSubscriptionSession( shouldEnable ? "Enabled" : "Disabled", this, (OpcUaSession)Session); ResetMonitoredItemWatchdogTimer(shouldEnable); } } /// /// Get a subscription with the supplied configuration (no lock) /// /// /// /// private async ValueTask SynchronizeSubscriptionAsync(CancellationToken ct) { if (Handle == null) { Handle = SubscriptionId; // Initialized for the first time DisplayName = Name + SubscriptionId; PublishingEnabled = EnableImmediatePublishing; KeepAliveCount = DesiredKeepAliveCount; PublishingInterval = (int)DesiredPublishingInterval.TotalMilliseconds; MaxNotificationsPerPublish = DesiredMaxNotificationsPerPublish; LifetimeCount = DesiredLifetimeCount; Priority = DesiredPriority; // TODO: use a channel and reorder task before calling OnMessage // to order or else republish is called too often RepublishAfterTransfer = DesiredRepublishAfterTransfer; SequentialPublishing = EnableSequentialPublishing; _logger.CreatingSubscription( PublishingEnabled ? "enabled" : "disabled", this, (OpcUaSession)Session); Debug.Assert(Session != null); await CreateAsync(ct).ConfigureAwait(false); if (!Created) { Handle = null; var session = Session; await session.RemoveSubscriptionAsync(this, ct).ConfigureAwait(false); Debug.Assert(Session == null); throw new ServiceResultException(StatusCodes.BadSubscriptionIdInvalid, $"Failed to create subscription {this} in session {session}"); } ResetMonitoredItemWatchdogTimer(PublishingEnabled); _logger.RevisedValuesDuringCreate(this, CurrentPublishingEnabled, PublishingEnabled, (int)CurrentPublishingInterval, (int)PublishingInterval, CurrentKeepAliveCount, KeepAliveCount, CurrentLifetimeCount, LifetimeCount); Debug.Assert(Id != 0); Debug.Assert(Created); _firstDataChangeReceived = false; } else { // // Only needed when we reconfiguring a subscription with a single subscriber // This is not yet implemented. // TODO: Consider removing... // // Apply new configuration on configuration on original subscription var modifySubscription = false; if (DesiredKeepAliveCount != KeepAliveCount) { _logger.KeepAliveCountChanged(DesiredKeepAliveCount, this); KeepAliveCount = DesiredKeepAliveCount; modifySubscription = true; } if (PublishingInterval != (int)DesiredPublishingInterval.TotalMilliseconds) { _logger.PublishingIntervalChanged(DesiredPublishingInterval, this); PublishingInterval = (int)DesiredPublishingInterval.TotalMilliseconds; modifySubscription = true; } if (MaxNotificationsPerPublish != DesiredMaxNotificationsPerPublish) { _logger.MaxNotificationsPerPublishChanged(DesiredMaxNotificationsPerPublish, this); MaxNotificationsPerPublish = DesiredMaxNotificationsPerPublish; modifySubscription = true; } if (LifetimeCount != DesiredLifetimeCount) { _logger.LifetimeCountChanged( DesiredLifetimeCount, this); LifetimeCount = DesiredLifetimeCount; modifySubscription = true; } if (Priority != DesiredPriority) { _logger.PriorityChanged( DesiredPriority, this); Priority = DesiredPriority; modifySubscription = true; } if (modifySubscription) { await ModifyAsync(ct).ConfigureAwait(false); _logger.SubscriptionModified(this, (OpcUaSession)Session); _logger.RevisedValuesDuringModify(this, CurrentPublishingEnabled, PublishingEnabled, (int)CurrentPublishingInterval, (int)PublishingInterval, CurrentKeepAliveCount, KeepAliveCount, CurrentLifetimeCount, LifetimeCount); ResetMonitoredItemWatchdogTimer(PublishingEnabled); } } ResetKeepAliveTimer(); } /// /// Synchronize partition of monitored items into this subscription /// /// /// /// /// private async ValueTask SynchronizeMonitoredItemsAsync( Partition partition, OperationLimitsModel operationLimits, CancellationToken ct) { if (Session is not OpcUaSession session) { throw ServiceResultException.Create(StatusCodes.BadSessionIdInvalid, "Session not connected."); } // Get the items assigned to this subscription. #pragma warning disable CA2000 // Dispose objects before losing scope var desired = OpcUaMonitoredItem .Create(_client, partition.Items, _loggerFactory, _timeProvider) .ToHashSet(); #pragma warning restore CA2000 // Dispose objects before losing scope var previouslyMonitored = CurrentlyMonitored.ToHashSet(); var remove = previouslyMonitored.Except(desired).ToHashSet(); var add = desired.Except(previouslyMonitored).ToHashSet(); var same = previouslyMonitored.ToHashSet(); var errorsDuringSync = 0; same.IntersectWith(desired); // // Resolve the browse paths for all nodes first. // // We shortcut this only through the added items since the identity (hash) // of the monitored item is dependent on the node and browse path, so any // update of either results in a newly added monitored item and the old // one removed. // var allResolvers = add .Select(a => a.Resolve) .Where(a => a != null); foreach (var resolvers in allResolvers.Batch( operationLimits.GetMaxNodesPerTranslatePathsToNodeIds())) { var response = await session.Services.TranslateBrowsePathsToNodeIdsAsync( new RequestHeader(), new BrowsePathCollection(resolvers .Select(a => new BrowsePath { StartingNode = a!.Value.NodeId.ToNodeId( session.MessageContext), RelativePath = a.Value.Path.ToRelativePath( session.MessageContext) })), ct).ConfigureAwait(false); var results = response.Validate(response.Results, s => s.StatusCode, response.DiagnosticInfos, resolvers); if (results.ErrorInfo != null) { // Could not do anything... _logger.BrowsePathResolveFailed(this, results.ErrorInfo); throw ServiceResultException.Create(results.ErrorInfo.StatusCode, results.ErrorInfo.ErrorMessage ?? "Failed to resolve browse paths"); } foreach (var result in results) { var resolvedId = NodeId.Null; if (result.ErrorInfo == null && result.Result.Targets.Count == 1) { resolvedId = result.Result.Targets[0].TargetId.ToNodeId( session.MessageContext.NamespaceUris); result.Request!.Value.Update(resolvedId, session.MessageContext); } else { _logger.BrowsePathForNodeResolveFailed(result.Request!.Value.NodeId, this, result.ErrorInfo); errorsDuringSync++; } } } // // If retrieving paths for all the items from the root folder was configured do so // now. All items that fail here should be retried later. // if (ResolveBrowsePathFromRoot) { var allGetPaths = add .Select(a => a.GetPath) .Where(a => a != null); var pathsRetrieved = 0; foreach (var getPathsBatch in allGetPaths.Batch(10000)) { var getPath = getPathsBatch.ToList(); var paths = await session.GetBrowsePathsFromRootAsync(new RequestHeader(), getPath.Select(n => n!.Value.NodeId.ToNodeId(session.MessageContext)), ct).ConfigureAwait(false); for (var index = 0; index < paths.Count; index++) { getPath[index]!.Value.Update(paths[index].Path, session.MessageContext); if (paths[index].ErrorInfo != null) { _logger.RootPathResolveFailed(getPath[index]!.Value.NodeId, this, paths[index].ErrorInfo); } else { pathsRetrieved++; } } } if (pathsRetrieved > 0) { _logger.PathsRetrieved(pathsRetrieved, this); } } // // Register nodes for reading if needed. This is needed anytime the session // changes as the registration is only valid in the context of the session // var allRegistrations = add.Concat(same) .Select(a => a.Register) .Where(a => a != null); foreach (var registrations in allRegistrations.Batch( operationLimits.GetMaxNodesPerRegisterNodes())) { var response = await session.Services.RegisterNodesAsync( new RequestHeader(), new NodeIdCollection(registrations .Select(a => a!.Value.NodeId.ToNodeId(session.MessageContext))), ct).ConfigureAwait(false); foreach (var (First, Second) in response.RegisteredNodeIds.Zip(registrations)) { Debug.Assert(Second != null); if (!NodeId.IsNull(First)) { Second.Value.Update(First, session.MessageContext); } } } var metadataChanged = new HashSet(); var applyChanges = false; var updated = 0; foreach (var toUpdate in same) { if (!desired.TryGetValue(toUpdate, out var theDesiredUpdate)) { errorsDuringSync++; continue; } desired.Remove(theDesiredUpdate); Debug.Assert(toUpdate.GetType() == theDesiredUpdate.GetType()); Debug.Assert(toUpdate.Subscription == this); try { if (toUpdate.MergeWith(theDesiredUpdate, session, out var metadata)) { _logger.UpdatingMonitoredItem(toUpdate, this); if (toUpdate.FinalizeMergeWith != null && metadata) { await toUpdate.FinalizeMergeWith(session, ct).ConfigureAwait(false); } updated++; applyChanges = true; } if (metadata) { metadataChanged.Add(toUpdate.Owner); } } catch (Exception ex) { _logger.MonitoredItemUpdateFailed(ex, toUpdate, this); errorsDuringSync++; } finally { theDesiredUpdate.Dispose(); } } var removed = 0; foreach (var toRemove in remove) { Debug.Assert(toRemove.Subscription == this); try { if (toRemove.RemoveFrom(this, out var metadata)) { _logger.RemovingMonitoredItem(toRemove, this); removed++; applyChanges = true; } if (metadata) { metadataChanged.Add(toRemove.Owner); } } catch (Exception ex) { _logger.MonitoredItemRemoveFailed(ex, toRemove, this); errorsDuringSync++; } } var added = 0; foreach (var toAdd in add) { desired.Remove(toAdd); Debug.Assert(toAdd.Subscription == null); try { if (toAdd.AddTo(this, session, out var metadata)) { _logger.AddingMonitoredItem(toAdd, this); if (toAdd.FinalizeAddTo != null && metadata) { await toAdd.FinalizeAddTo(session, ct).ConfigureAwait(false); } added++; applyChanges = true; } if (metadata) { metadataChanged.Add(toAdd.Owner); } } catch (Exception ex) { _logger.MonitoredItemAddFailed(ex, toAdd, this); errorsDuringSync++; } } Debug.Assert(desired.Count == 0, "We should have processed all desired updates."); if (applyChanges) { await ApplyChangesAsync(ct).ConfigureAwait(false); if (MonitoredItemCount == 0 && !EnableImmediatePublishing) { await SetPublishingModeAsync(false, ct).ConfigureAwait(false); _logger.DisabledEmptySubscription(this, session); ResetMonitoredItemWatchdogTimer(false); } } // Perform second pass over all monitored items and complete. applyChanges = false; var badMonitoredItems = 0; var desiredMonitoredItems = same; desiredMonitoredItems.UnionWith(add); // // Resolve display names for all nodes that still require a name // other than the node id string. // // Note that we use the desired set here and update the display // name after AddTo/MergeWith as it only effects the messages // and metadata emitted and not the item as it is set up in the // subscription (like what we do when resolving nodes). This // supports the scenario where the user sets a desired display // name of null to force reading the display name from the node // and updating the existing display name (previously set) and // at the same time is quite effective to only update what is // necessary. // var allDisplayNameUpdates = desiredMonitoredItems .Select(a => (a.Owner, a.GetDisplayName)) .Where(a => a.GetDisplayName.HasValue) .ToList(); if (allDisplayNameUpdates.Count > 0) { foreach (var displayNameUpdates in allDisplayNameUpdates.Batch( operationLimits.GetMaxNodesPerRead())) { var response = await session.Services.ReadAsync(new RequestHeader(), 0, Opc.Ua.TimestampsToReturn.Neither, new ReadValueIdCollection( displayNameUpdates.Select(a => new ReadValueId { NodeId = a.GetDisplayName!.Value.NodeId.ToNodeId(session.MessageContext), AttributeId = (uint)NodeAttribute.DisplayName })), ct).ConfigureAwait(false); var results = response.Validate(response.Results, s => s.StatusCode, response.DiagnosticInfos, displayNameUpdates); if (results.ErrorInfo != null) { _logger.DisplayNameResolveFailed(this, results.ErrorInfo); // We will retry later. errorsDuringSync++; } else { foreach (var result in results) { string? displayName = null; if (result.Result.Value is not null) { displayName = (result.Result.Value as LocalizedText)?.ToString(); metadataChanged.Add(result.Request.Owner); } else { _logger.DisplayNameReadFailed( result.Request.GetDisplayName!.Value.NodeId, this, result.ErrorInfo); } result.Request.GetDisplayName!.Value.Update( displayName ?? string.Empty); } } } } _logger.CompletingItems(desiredMonitoredItems.Count, remove.Count, this); var errors = new List<(string Item, StatusCode Error, bool Report)>(); foreach (var monitoredItem in desiredMonitoredItems.Concat(remove)) { if (!monitoredItem.TryCompleteChanges(this, ref applyChanges)) { if (add.Contains(monitoredItem) || same.Contains(monitoredItem)) { errors.Add((monitoredItem.ToString(), monitoredItem.Status?.Error?.StatusCode ?? StatusCodes.BadMonitoredItemIdInvalid, !monitoredItem.ErrorReported)); monitoredItem.ErrorReported = true; } // Apply more changes in future passes badMonitoredItems++; } } // Dump errors in a concise way all at once foreach (var errorGroup in errors.GroupBy(e => e.Error)) { var errorItems = errorGroup .Where(e => e.Report) .Select(e => e.Item) .ToArray(); if (errorItems.Length > 0) { _logger.ErrorAddingMonitoredItemsWithErrors(errorGroup.Key.ToString(), errorGroup.Count(), SubscriptionId, string.Join("\n ", errorItems)); } else { _logger.ErrorAddingMonitoredItems(errorGroup.Key.ToString(), errorGroup.Count(), SubscriptionId); } } Debug.Assert(remove.All(m => !m.AttachedToSubscription), "All removed items should be detached now"); var set = desiredMonitoredItems.Where(m => m.Valid).ToList(); _logger.ItemCompletionStats(set.Count, desiredMonitoredItems.Count - set.Count, this); var finalize = set .Where(i => i.FinalizeCompleteChanges != null) .Select(i => i.FinalizeCompleteChanges!(ct)) .ToArray(); if (finalize.Length > 0) { await Task.WhenAll(finalize).ConfigureAwait(false); } _sendFakeKeepAlives = partition.Items.Select(m => m.Item1).Distinct().Count() > 1; if (applyChanges) { // Apply any additional changes await ApplyChangesAsync(ct).ConfigureAwait(false); } Debug.Assert(set.Select(m => m.ClientHandle).Distinct().Count() == set.Count, "Client handles are not distinct or one of the items is null"); _logger.SettingMonitoringMode(set.Count, this); // // Finally change the monitoring mode as required. Batch the requests // on the update of monitored item state from monitored items. On AddTo // the monitoring mode was already configured. This is for updates as // they are not applied through ApplyChanges // foreach (var change in set.GroupBy(i => i.GetMonitoringModeChange())) { if (change.Key == null) { // Not a valid item continue; } foreach (var itemsBatch in change.Batch( operationLimits.GetMaxMonitoredItemsPerCall())) { var itemsToChange = itemsBatch.Cast().ToList(); _logger.MonitoringModeSet(change.Key.Value, itemsToChange.Count, this); var results = await SetMonitoringModeAsync(change.Key.Value, itemsToChange, ct).ConfigureAwait(false); if (results != null) { var erroneousResultsCount = results .Count(r => r != null && StatusCode.IsNotGood(r.StatusCode)); // Check the number of erroneous results and log. if (erroneousResultsCount > 0) { _logger.MonitoringSetFailed(erroneousResultsCount, this); for (var i = 0; i < results.Count && i < itemsToChange.Count; ++i) { if (StatusCode.IsNotGood(results[i].StatusCode)) { _logger.MonitoringSetFailedForItem(itemsToChange[i].StartNodeId, this, results[i].StatusCode); } } // Retry later errorsDuringSync++; } } } } finalize = set .Where(i => i.FinalizeMonitoringModeChange != null) .Select(i => i.FinalizeMonitoringModeChange!(ct)) .ToArray(); if (finalize.Length > 0) { await Task.WhenAll(finalize).ConfigureAwait(false); } // Cleanup all items that are not in the currently monitoring list var dispose = previouslyMonitored .Except(set) .ToList(); dispose.ForEach(m => m.Dispose()); // Notify semantic change now that we have update the monitored items var notifySemanticChange = metadataChanged .Select(o => o.OnMonitoredItemSemanticsChangedAsync(ct)) .ToArray(); if (notifySemanticChange.Length > 0) { await Task.WhenAll(notifySemanticChange).ConfigureAwait(false); } // Refresh condition if (set.OfType().Any()) { _logger.IssuingConditionRefresh(this); try { await ConditionRefreshAsync(ct).ConfigureAwait(false); _logger.ConditionRefreshCompleted(this); } catch (Exception e) { _logger.ConditionRefreshFailed(this, e.Message); errorsDuringSync++; } } set.ForEach(item => item.LogRevisedSamplingRateAndQueueSize()); var goodMonitoredItems = Math.Max(set.Count - badMonitoredItems, 0); var reportingItems = set .Count(r => r.Status?.MonitoringMode == Opc.Ua.MonitoringMode.Reporting); var disabledItems = set .Count(r => r.Status?.MonitoringMode == Opc.Ua.MonitoringMode.Disabled); var samplingItems = set .Count(r => r.Status?.MonitoringMode == Opc.Ua.MonitoringMode.Sampling); var notAppliedItems = set .Count(r => r.Status?.MonitoringMode != r.MonitoringMode); var heartbeatItems = set .Count(r => r is OpcUaMonitoredItem.Heartbeat); var conditionItems = set .Count(r => r is OpcUaMonitoredItem.Condition); var heartbeatsEnabled = set .Count(r => r is OpcUaMonitoredItem.Heartbeat h && h.TimerEnabled); var conditionsEnabled = set .Count(r => r is OpcUaMonitoredItem.Condition h && h.TimerEnabled); var resyncCounter = Interlocked.Increment(ref _resyncCounter); var resyncTotal = Interlocked.Increment(ref _resyncTotal); ReportMonitoredItemChanges(set.Count, goodMonitoredItems, badMonitoredItems, errorsDuringSync, notAppliedItems, reportingItems, disabledItems, heartbeatItems, heartbeatsEnabled, conditionItems, conditionsEnabled, samplingItems, dispose.Count, resyncCounter, resyncTotal); // Set up subscription management trigger if (badMonitoredItems != 0 || errorsDuringSync != 0) { // There were items that could not be added to subscription return Delay(_options.Value.InvalidMonitoredItemRetryDelayDuration, TimeSpan.FromMinutes(5), _options.Value.InvalidMonitoredItemRetryDelayDurationMax, resyncCounter); } else if (desiredMonitoredItems.Count != set.Count) { // There were items !Valid but desired. return Delay(_options.Value.BadMonitoredItemRetryDelayDuration, TimeSpan.FromMinutes(30), _options.Value.InvalidMonitoredItemRetryDelayDurationMax, resyncCounter); } else { // Nothing to do resyncCounter = 0; return Delay(_options.Value.SubscriptionManagementIntervalDuration, TimeSpan.MaxValue); } } /// /// Initialize state /// private void Initialize() { FastKeepAliveCallback = OnSubscriptionKeepAliveNotification; FastDataChangeCallback = OnSubscriptionDataChangeNotification; FastEventCallback = OnSubscriptionEventNotificationList; PublishStatusChanged += OnPublishStatusChange; StateChanged += OnStateChange; TimestampsToReturn = Opc.Ua.TimestampsToReturn.Both; DisableMonitoredItemCache = true; } /// /// Get child subscription /// /// /// private OpcUaSubscription? GetChildSubscription(bool createIfNotExist = false) { if (Session is OpcUaSession session) { if (_childId.HasValue && session.SubscriptionHandles.TryGetValue(_childId.Value, out var subscription)) { // Found entry return subscription; } if (createIfNotExist) { subscription = new OpcUaSubscription(this, parentId: SubscriptionId); _childId = subscription.SubscriptionId; session.AddSubscription(subscription); return subscription; } if (_childId != null) { _logger.ChildSubscriptionNotFound(_childId, session); } _childId = null; } return null; } /// /// Get all monitored items încluding all child subscriptions. /// This call is used to collect all items recursively. /// /// /// private IEnumerable GetAllMonitoredItems( IEnumerable? parent = null) { parent ??= []; parent = parent.Concat(CurrentlyMonitored); var child = GetChildSubscription(); if (child != null) { // Recursively concat the items of all children parent = child.GetAllMonitoredItems(parent); } return parent; } /// /// Collect metadata across this and all child subscriptions /// recursively from parent to child to child and so on. /// /// /// /// /// /// /// /// private async Task CollectMetaDataAsync(ISubscriber owner, OpcUaSession session, ComplexTypeSystem? typeSystem, NodeIdDictionary dataTypes, List fields, CancellationToken ct) { foreach (var monitoredItem in CurrentlyMonitored.Where(m => m.Owner == owner)) { await monitoredItem.GetMetaDataAsync(session, typeSystem, fields, dataTypes, ct).ConfigureAwait(false); } var child = GetChildSubscription(); if (child != null) { await child.CollectMetaDataAsync(owner, session, typeSystem, dataTypes, fields, ct).ConfigureAwait(false); } } /// /// Close subscription /// /// private async Task CloseCurrentSubscriptionAsync() { ResetKeepAliveTimer(); try { Handle = null; // Mark as closed _logger.ClosingSubscription(this); // Dispose all monitored items var items = CurrentlyMonitored.ToList(); RemoveItems(MonitoredItems); _currentSequenceNumber = 0; _goodMonitoredItems = 0; _badMonitoredItems = 0; _resyncCounter = 0; _reportingItems = 0; _disabledItems = 0; _samplingItems = 0; _notAppliedItems = 0; ResetMonitoredItemWatchdogTimer(false); await Try.Async(() => SetPublishingModeAsync(false, default)).ConfigureAwait(false); await Try.Async(() => DeleteItemsAsync(default)).ConfigureAwait(false); await Try.Async(() => ApplyChangesAsync(default)).ConfigureAwait(false); items.ForEach(item => item.Dispose()); _logger.DeletedMonitoredItems(items.Count, this); await Try.Async(() => DeleteAsync(true, default)).ConfigureAwait(false); if (Session != null) { await Session.RemoveSubscriptionAsync(this).ConfigureAwait(false); } Debug.Assert(Session == null, "Subscription should not be part of session"); Debug.Assert(!CurrentlyMonitored.Any(), "Not all items removed."); _client.OnSubscriptionClosed(this); _logger.SubscriptionClosed2(this); } catch (Exception e) { _logger.FailedToClose(e, this); } } /// /// Report monitored item changes /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// private void ReportMonitoredItemChanges(int count, int goodMonitoredItems, int badMonitoredItems, int errorsDuringSync, int notAppliedItems, int reportingItems, int disabledItems, int heartbeatItems, int heartbeatsEnabled, int conditionItems, int conditionsEnabled, int samplingItems, int disposed, int resyncCounter, int resyncTotal) { if (_badMonitoredItems != badMonitoredItems || _errorsDuringSync != errorsDuringSync || _goodMonitoredItems != goodMonitoredItems || _reportingItems != reportingItems || _disabledItems != disabledItems || _samplingItems != samplingItems || _notAppliedItems != notAppliedItems || _heartbeatItems != heartbeatItems || _conditionItems != conditionItems) { if (samplingItems == 0 && heartbeatItems == 0 && conditionItems == 0 && notAppliedItems == 0) { if (errorsDuringSync == 0 && disabledItems == 0) { _logger.SubscriptionReportState(this, resyncCounter, resyncTotal, disposed, count, goodMonitoredItems, badMonitoredItems, reportingItems); } else { _logger.SubscriptionReportStateWithErrors(this, resyncCounter, resyncTotal, disposed, count, goodMonitoredItems, badMonitoredItems, reportingItems, disabledItems, errorsDuringSync); } } else { _logger.SubscriptionReportStateFull(this, resyncCounter, resyncTotal, disposed, count, goodMonitoredItems, badMonitoredItems, reportingItems, disabledItems, errorsDuringSync, notAppliedItems, samplingItems, heartbeatItems, heartbeatsEnabled, conditionItems, conditionsEnabled); } } else { _logger.SubscriptionNoMonitoredItemChange(this, resyncCounter, resyncTotal); } _badMonitoredItems = badMonitoredItems; _errorsDuringSync = errorsDuringSync; _goodMonitoredItems = goodMonitoredItems; _reportingItems = reportingItems; _disabledItems = disabledItems; _samplingItems = samplingItems; _notAppliedItems = notAppliedItems; _heartbeatItems = heartbeatItems; _conditionItems = conditionItems; } /// /// Calculate delay /// /// /// /// /// /// private static TimeSpan Delay(TimeSpan? delay, TimeSpan defaultDelay, TimeSpan? maxDelay = null, int counter = 1) { if (delay == null) { return defaultDelay; } if (delay == TimeSpan.Zero) { return TimeSpan.MaxValue; } var minDelay = delay.Value; // If the delay is negative we consider it to mean exponential backoff if (minDelay < TimeSpan.Zero) { minDelay = TimeSpan.FromMilliseconds(-minDelay.TotalMilliseconds); } // // Otherwise if the max delay is not set, and min delay larger than 10 // seconds we consider it to mean constant retry (old behavior) // else if (maxDelay == null && minDelay > kMaxExponentialRetryDelayDefault) { return minDelay; } var max = maxDelay ?? defaultDelay; // // If the max configured is below the delay configured then we also // consider this to mean retry every x seconds (we do not need to calc // an exponential retry // if (max <= minDelay) { return minDelay; } // // If the max delay is smaller than 10 seconds, we set it to 10 seconds // to avoid constant thrashing // if (max < kMaxExponentialRetryDelayDefault) { // Do not allow a max below 10 seconds max = kMaxExponentialRetryDelayDefault; } // Calculate the exponential backoff - no need to add jitter. var backoff = (int)Math.Pow(2, Math.Min(counter, 10)); var calculated = TimeSpan.FromTicks(minDelay.Ticks * backoff); return calculated > max ? max : calculated; } /// /// Send notification /// /// /// /// /// /// /// internal void SendNotification(ISubscriber callback, MessageType messageType, IList notifications, string? eventTypeName, bool diagnosticsOnly, DateTimeOffset? timestamp) { var curSession = Session; var messageContext = curSession?.MessageContext; if (messageContext == null) { _logger.UsingThreadContext(); messageContext = ServiceMessageContext.ThreadContext; } #pragma warning disable CA2000 // Dispose objects before losing scope var message = new OpcUaSubscriptionNotification(this, messageContext, notifications, _timeProvider, createdTimestamp: timestamp) { ApplicationUri = curSession?.Endpoint?.Server?.ApplicationUri ?? _client.ApplicationUri, EndpointUrl = curSession?.Endpoint?.EndpointUrl, EventTypeName = eventTypeName, SequenceNumber = Opc.Ua.SequenceNumber.Increment32(ref _sequenceNumber), MessageType = messageType }; #pragma warning restore CA2000 // Dispose objects before losing scope var count = message.GetDiagnosticCounters(out var modelChanges, out var heartbeats, out var overflows); if (messageType == MessageType.Event || messageType == MessageType.Condition) { if (!diagnosticsOnly) { callback.OnSubscriptionEventReceived(message); } if (count > 0) { callback.OnSubscriptionEventDiagnosticsChange(false, count, overflows, modelChanges == 0 ? 0 : 1); } } else { if (!diagnosticsOnly) { callback.OnSubscriptionDataChangeReceived(message); } if (count > 0) { callback.OnSubscriptionDataDiagnosticsChange(false, count, overflows, heartbeats); } } } /// /// Handle event notification. Depending on the sequential publishing setting /// this will be called in order and thread safe or from different threads. /// /// /// /// private void OnSubscriptionEventNotificationList(Subscription subscription, EventNotificationList notification, IList? stringTable) { Debug.Assert(ReferenceEquals(subscription, this)); ObjectDisposedException.ThrowIf(_disposed, this); if (notification?.Events == null) { _logger.EmptyEventNotification(this); return; } if (notification.Events.Count == 0) { _logger.NoEventsInNotification(this); return; } var session = Session; if (session is not IOpcUaSession sessionContext) { _logger.EventChangeWithoutSession(this, session?.ToString()); return; } ResetKeepAliveTimer(); var sw = Stopwatch.StartNew(); try { var sequenceNumber = notification.SequenceNumber; var publishTime = DateTime.SpecifyKind(notification.PublishTime, DateTimeKind.Utc); Debug.Assert(notification.Events != null); if (sequenceNumber == 1) { // Do not log when the sequence number is 1 after reconnect _previousSequenceNumber = 1; } else if (!Opc.Ua.SequenceNumber.Validate(sequenceNumber, ref _previousSequenceNumber, out var missingSequenceNumbers, out var dropped)) { _logger.UnexpectedEventSequenceNumber(this, sequenceNumber, Opc.Ua.SequenceNumber.ToString(missingSequenceNumbers), dropped ? "dropped" : "already received", publishTime); } var overflows = 0; var events = new List<(string?, OpcUaMonitoredItem.MonitoredItemNotifications)>(); foreach (var eventFieldList in notification.Events) { Debug.Assert(eventFieldList != null); if (TryGetMonitoredItemForNotification(eventFieldList.ClientHandle, out var monitoredItem)) { var collector = new OpcUaMonitoredItem.MonitoredItemNotifications(); if (!monitoredItem.TryGetMonitoredItemNotifications(publishTime, eventFieldList, collector)) { _logger.SkippingEventNotification(this); } events.Add((monitoredItem.EventTypeName, collector)); } } if (_sendFakeKeepAlives) { // Send fake keep alives to all the other subscribers SendFakeKeepAlives(session); } var total = events.Sum(e => e.Item2.Notifications.Count); #pragma warning disable CA2000 // Dispose objects before losing scope var advance = new Advance(this, sequenceNumber, total); #pragma warning restore CA2000 // Dispose objects before losing scope foreach (var (name, evt) in events) { foreach (var (callback, notifications) in evt.Notifications) { #pragma warning disable CA2000 // Dispose objects before losing scope var message = new OpcUaSubscriptionNotification(this, session.MessageContext, notifications, _timeProvider, advance, sequenceNumber) { ApplicationUri = session.Endpoint?.Server?.ApplicationUri ?? _client.ApplicationUri, EndpointUrl = session.Endpoint?.EndpointUrl, EventTypeName = name, SequenceNumber = Opc.Ua.SequenceNumber.Increment32(ref _sequenceNumber), MessageType = MessageType.Event, PublishTimestamp = publishTime }; #pragma warning restore CA2000 // Dispose objects before losing scope if (message.Notifications.Count > 0) { callback.OnSubscriptionEventReceived(message); overflows += message.Notifications.Sum(n => n.Overflow); callback.OnSubscriptionEventDiagnosticsChange(true, overflows, 1, 0); } else { _logger.NoNotificationsAdded(); } } } } catch (Exception e) { _logger.EventProcessingError(e); } finally { _logger.EventCallbackDuration(sw.Elapsed); if (sw.ElapsedMilliseconds > 1000) { _logger.SlowEventCallback(); } } } /// /// Handle keep alive messages /// /// /// /// private void OnSubscriptionKeepAliveNotification(Subscription subscription, NotificationData notification) { Debug.Assert(ReferenceEquals(subscription, this)); ObjectDisposedException.ThrowIf(_disposed, this); ResetKeepAliveTimer(); if (!PublishingEnabled) { _logger.KeepAliveWhileNotPublishing(); return; } var session = Session; if (session is not IOpcUaSession) { _logger.KeepAliveWithoutSession(this, session?.ToString()); return; } var sw = Stopwatch.StartNew(); try { var sequenceNumber = notification.SequenceNumber; var publishTime = DateTime.SpecifyKind(notification.PublishTime, DateTimeKind.Utc); // in case of a keepalive,the sequence number is not incremented by the servers _logger.KeepAliveReceived(this, sequenceNumber, publishTime); if (_sendFakeKeepAlives) { SendFakeKeepAlives(session); } else { #pragma warning disable CA2000 // Dispose objects before losing scope var message = new OpcUaSubscriptionNotification(this, session.MessageContext, Array.Empty(), _timeProvider) { ApplicationUri = session.Endpoint?.Server?.ApplicationUri ?? _client.ApplicationUri, EndpointUrl = session.Endpoint?.EndpointUrl, PublishTimestamp = publishTime, SequenceNumber = Opc.Ua.SequenceNumber.Increment32(ref _sequenceNumber), MessageType = MessageType.KeepAlive }; #pragma warning restore CA2000 // Dispose objects before losing scope foreach (var callback in CurrentlyMonitored .Select(c => c.Owner) .Distinct()) { callback.OnSubscriptionKeepAlive(message); } Debug.Assert(message.Notifications != null); } } catch (Exception e) { _logger.KeepAliveProcessingError(e); } finally { _logger.KeepAliveDuration(sw.Elapsed); if (sw.ElapsedMilliseconds > 1000) { _logger.SlowKeepAliveCallback(); } } } /// /// Handle cyclic read notifications created by the client /// /// /// /// /// public void OnSubscriptionCylicReadNotification(Subscription subscription, List values, uint sequenceNumber, DateTime publishTime) { Debug.Assert(ReferenceEquals(subscription, this)); ObjectDisposedException.ThrowIf(_disposed, this); var session = Session; if (session is not IOpcUaSession sessionContext) { _logger.DataChangeWithoutSession(this, session?.ToString()); return; } var sw = Stopwatch.StartNew(); try { var collector = new OpcUaMonitoredItem.MonitoredItemNotifications(); foreach (var cyclicDataChange in values.OrderBy(m => m.Value?.SourceTimestamp)) { if (TryGetMonitoredItemForNotification(cyclicDataChange.ClientHandle, out var monitoredItem) && !monitoredItem.TryGetMonitoredItemNotifications(publishTime, cyclicDataChange, collector)) { _logger.SkippingCyclicRead(this); } } foreach (var (callback, notifications) in collector.Notifications) { #pragma warning disable CA2000 // Dispose objects before losing scope var message = new OpcUaSubscriptionNotification(this, session.MessageContext, notifications, _timeProvider, null, sequenceNumber) { ApplicationUri = session.Endpoint?.Server?.ApplicationUri ?? _client.ApplicationUri, EndpointUrl = session.Endpoint?.EndpointUrl, PublishTimestamp = publishTime, SequenceNumber = Opc.Ua.SequenceNumber.Increment32(ref _sequenceNumber), MessageType = MessageType.DeltaFrame }; #pragma warning restore CA2000 // Dispose objects before losing scope callback.OnSubscriptionCyclicReadCompleted(message); Debug.Assert(message.Notifications != null); var count = message.GetDiagnosticCounters(out var _, out _, out var overflows); if (count > 0) { callback.OnSubscriptionCyclicReadDiagnosticsChange(count, overflows); } } } catch (Exception e) { _logger.CyclicReadProcessingError(e); } finally { _logger.CyclicReadDuration(sw.Elapsed); if (sw.ElapsedMilliseconds > 1000) { _logger.SlowCyclicReadCallback(); } } } /// /// Handle data change notification. Depending on the sequential publishing setting /// this will be called in order and thread safe or from different threads. /// /// /// /// private void OnSubscriptionDataChangeNotification(Subscription subscription, DataChangeNotification notification, IList? stringTable) { Debug.Assert(ReferenceEquals(subscription, this)); ObjectDisposedException.ThrowIf(_disposed, this); var session = Session; if (session is not IOpcUaSession sessionContext) { _logger.DataChangeWithoutSession(this, session.ToString()); return; } ResetKeepAliveTimer(); var firstDataChangeReceived = _firstDataChangeReceived; _firstDataChangeReceived = true; var sw = Stopwatch.StartNew(); try { var sequenceNumber = notification.SequenceNumber; var publishTime = DateTime.SpecifyKind(notification.PublishTime, DateTimeKind.Utc); // All notifications have the same message and thus sequence number if (sequenceNumber == 1) { // Do not log when the sequence number is 1 after reconnect _previousSequenceNumber = 1; } else if (!Opc.Ua.SequenceNumber.Validate(sequenceNumber, ref _previousSequenceNumber, out var missingSequenceNumbers, out var dropped)) { _logger.UnexpectedDataChangeSequenceNumber(this, sequenceNumber, Opc.Ua.SequenceNumber.ToString(missingSequenceNumbers), dropped ? "dropped" : "already received", publishTime); } // Collect notifications var collector = new OpcUaMonitoredItem.MonitoredItemNotifications(); foreach (var item in notification.MonitoredItems) { Debug.Assert(item != null); if (TryGetMonitoredItemForNotification(item.ClientHandle, out var monitoredItem) && !monitoredItem.TryGetMonitoredItemNotifications(publishTime, item, collector)) { _logger.SkippingDataChangeNotification(this); } } if (_sendFakeKeepAlives) { // Send fake keep alives to all the other subscribers SendFakeKeepAlives(session); } // Send to listeners #pragma warning disable CA2000 // Dispose objects before losing scope var advance = new Advance(this, sequenceNumber, collector.Notifications.Count); #pragma warning restore CA2000 // Dispose objects before losing scope foreach (var (callback, notifications) in collector.Notifications) { #pragma warning disable CA2000 // Dispose objects before losing scope var message = new OpcUaSubscriptionNotification(this, session.MessageContext, notifications, _timeProvider, advance, sequenceNumber) { ApplicationUri = session.Endpoint?.Server?.ApplicationUri ?? _client.ApplicationUri, EndpointUrl = session.Endpoint?.EndpointUrl, PublishTimestamp = publishTime, SequenceNumber = Opc.Ua.SequenceNumber.Increment32(ref _sequenceNumber), MessageType = firstDataChangeReceived ? MessageType.DeltaFrame : MessageType.KeyFrame }; #pragma warning restore CA2000 // Dispose objects before losing scope Debug.Assert(notification.MonitoredItems != null); callback.OnSubscriptionDataChangeReceived(message); Debug.Assert(message.Notifications != null); var count = message.GetDiagnosticCounters(out var _, out var heartbeats, out var overflows); if (count > 0) { callback.OnSubscriptionDataDiagnosticsChange(true, count, overflows, heartbeats); } } } catch (Exception e) { _logger.DataChangeNotificationError(e); } finally { _logger.DataChangeDuration(sw.Elapsed); if (sw.ElapsedMilliseconds > 1000) { _logger.SlowDataChangeCallback(); } } } /// /// Send fake keep alives to all subscribers /// /// private void SendFakeKeepAlives(ISession session) { // Send fake keep alives to all subscribers that need one var now = _timeProvider.GetUtcNow(); var keepAliveTimer = now - KeepAliveTimeout; foreach (var monitoredItems in CurrentlyMonitored.GroupBy(c => c.Owner)) { // Ka when the item never received a value or the last value is older than the keep alive timeout. if (monitoredItems.All(m => m.LastActivityTime < keepAliveTimer)) { foreach (var monitoredItem in monitoredItems) { monitoredItem.LastActivityTime = now; } monitoredItems.Key.OnSubscriptionKeepAlive(new OpcUaSubscriptionNotification(this, session.MessageContext, Array.Empty(), _timeProvider) { ApplicationUri = session.Endpoint?.Server?.ApplicationUri ?? _client.ApplicationUri, EndpointUrl = session.Endpoint?.EndpointUrl, PublishTimestamp = _timeProvider.GetUtcNow(), SequenceNumber = Opc.Ua.SequenceNumber.Increment32(ref _sequenceNumber), MessageType = MessageType.KeepAlive }); } } } /// /// Get monitored item using client handle /// /// /// /// private bool TryGetMonitoredItemForNotification(uint clientHandle, [NotNullWhen(true)] out OpcUaMonitoredItem? monitoredItem) { monitoredItem = FindItemByClientHandle(clientHandle) as OpcUaMonitoredItem; if (monitoredItem != null) { return true; } _unassignedNotifications++; _logger.MonitoredItemNotFound(clientHandle, this); return false; } /// /// Get notifications /// /// /// /// internal bool TryGetNotifications(ISubscriber owner, [NotNullWhen(true)] out IList? notifications) { try { if (IsClosed) { notifications = null; return false; } var collector = new OpcUaMonitoredItem.MonitoredItemNotifications(); // Ensure we order by client handle exactly like the meta data is ordered foreach (var item in CurrentlyMonitored .Where(m => m.Owner == owner).OrderBy(m => m.ClientHandle)) { item.TryGetLastMonitoredItemNotifications(collector); } if (!collector.Notifications.TryGetValue(owner, out var actualNotifications)) { notifications = null; return false; } notifications = actualNotifications; return true; } catch (Exception ex) { notifications = null; _logger.GetNotificationsFailed(ex, this); return false; } } /// /// Reset keep alive timer /// private void ResetKeepAliveTimer() { ObjectDisposedException.ThrowIf(_disposed, this); _continuouslyMissingKeepAlives = 0; if (!IsOnline) { _keepAliveWatcher.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); return; } try { var keepAliveTimeout = KeepAliveTimeout; _keepAliveWatcher.Change(keepAliveTimeout, keepAliveTimeout); } catch (ArgumentOutOfRangeException) { _keepAliveWatcher.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); } } /// /// Reset the monitored item watchdog /// /// private void ResetMonitoredItemWatchdogTimer(bool publishingEnabled) { var timeout = MonitoredItemWatchdogTimeout; if (timeout == TimeSpan.Zero) { if (_lastMonitoredItemCheck == null) { return; } publishingEnabled = false; } if (!publishingEnabled) { if (_lastMonitoredItemCheck != null) { _logger.StoppingWatchdog(this, timeout); } _lastMonitoredItemCheck = null; _monitoredItemWatcher.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); } else { if (_lastMonitoredItemCheck == null) { _logger.RestartingWatchdog(this, timeout); } _lastMonitoredItemCheck = _timeProvider.GetUtcNow(); Debug.Assert(timeout != TimeSpan.Zero); _monitoredItemWatcher.Change(timeout, timeout); } } /// /// Hand resynchronization /// /// private void OnResync(object? state) { lock (_timers) { if (_disposed || _resyncTimer == null) { Debug.Fail("Should not be called after dispose"); return; } if (IsRoot) { _client.TriggerSubscriptionSynchronization(this); } } } /// /// Checks status of monitored items /// /// private void OnMonitoredItemWatchdog(object? state) { var action = WatchdogBehavior ?? SubscriptionWatchdogBehavior.Diagnostic; lock (_timers) { if (_disposed || _monitoredItemWatcher == null) { Debug.Fail("Should not be called after dispose"); return; } var lastCheck = _lastMonitoredItemCheck; if (!IsOnline || lastCheck == null) { // Stop watchdog _monitoredItemWatcher.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); return; } if (MonitoredItemCount == 0) { _lastMonitoredItemCheck = _timeProvider.GetUtcNow(); return; } var lastCount = _lateMonitoredItems; var itemsChecked = 0; foreach (var item in CurrentlyMonitored) { itemsChecked++; if (item.WasLastValueReceivedBefore(lastCheck.Value)) { _logger.MonitoredItemLate(item, this); _lateMonitoredItems++; } } _lastMonitoredItemCheck = _timeProvider.GetUtcNow(); var missing = _lateMonitoredItems - lastCount; if (missing == 0) { _logger.AllItemsReporting(this); return; } if (action == SubscriptionWatchdogBehavior.Diagnostic) { return; } if (itemsChecked != missing) { if (WatchdogCondition == MonitoredItemWatchdogCondition.WhenAllAreLate) { _logger.SomeItemsLateDebug(missing, itemsChecked, this); return; } _logger.SomeItemsLate(this); } else { _logger.AllItemsLate(this); } _logger.LateItemsSummary(missing, itemsChecked, this, action); } var msg = $"Performed watchdog action {action} for subscription {this} " + $"because it has {_lateMonitoredItems} late monitored items."; RunWatchdogAction(action, msg); } /// /// Run watchdog action /// /// /// private void RunWatchdogAction(SubscriptionWatchdogBehavior action, string msg) { switch (action) { case SubscriptionWatchdogBehavior.Diagnostic: _logger.DiagnosticMessage(msg); break; case SubscriptionWatchdogBehavior.Reset: ResetMonitoredItemWatchdogTimer(false); _forceRecreate = true; _client.TriggerSubscriptionSynchronization(this); break; case SubscriptionWatchdogBehavior.FailFast: Publisher.Runtime.FailFast(msg, null); break; case SubscriptionWatchdogBehavior.ExitProcess: Console.WriteLine(msg); Publisher.Runtime.Exit(-10); break; } } /// /// Called when keep alive callback was missing /// /// private void OnKeepAliveMissing(object? state) { lock (_timers) { if (_disposed) { Debug.Fail("Should not be called after dispose"); return; } if (!IsOnline) { // Stop watchdog _keepAliveWatcher.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); return; } _missingKeepAlives++; _continuouslyMissingKeepAlives++; if (_continuouslyMissingKeepAlives == CurrentLifetimeCount + 1) { var action = WatchdogBehavior ?? SubscriptionWatchdogBehavior.Reset; _logger.KeepAliveExceeded( _continuouslyMissingKeepAlives, CurrentLifetimeCount, action, this); RunWatchdogAction(action, $"Subscription {this}: Keep alives exceeded " + $"({_continuouslyMissingKeepAlives}/{CurrentLifetimeCount})."); } else { _logger.MissingKeepAlive( _continuouslyMissingKeepAlives, CurrentLifetimeCount, this); } } } /// /// Publish status changed /// /// /// private void OnPublishStatusChange(Subscription subscription, PublishStateChangedEventArgs e) { if (_disposed) { return; } if (e.Status.HasFlag(PublishStateChangedMask.Stopped) && !_publishingStopped) { _logger.SubscriptionStopped(this); // ResetKeepAliveTimer(); // This will just prolong our suffering ResetMonitoredItemWatchdogTimer(false); _publishingStopped = true; } if (e.Status.HasFlag(PublishStateChangedMask.Recovered) && _publishingStopped) { _logger.SubscriptionRecovered(this); ResetKeepAliveTimer(); ResetMonitoredItemWatchdogTimer(true); _publishingStopped = false; } if (e.Status.HasFlag(PublishStateChangedMask.Transferred)) { _logger.SubscriptionTransferred(this); } if (e.Status.HasFlag(PublishStateChangedMask.Republish)) { _logger.SubscriptionRepublishing(this); } if (e.Status.HasFlag(PublishStateChangedMask.KeepAlive)) { _logger.SubscriptionKeepAlive(this); ResetKeepAliveTimer(); } if (e.Status.HasFlag(PublishStateChangedMask.Timeout)) { var action = WatchdogBehavior ?? SubscriptionWatchdogBehavior.Reset; _logger.SubscriptionTimeout(this, action.ToString()); // // Timed out on server - this means that the subscription is gone and // needs to be recreated. This is the default watchdog behavior. // RunWatchdogAction(action, $"Subscription {this} timed out!"); } } /// /// Subscription status changed /// /// /// private void OnStateChange(Subscription subscription, SubscriptionStateChangedEventArgs e) { if (e.Status.HasFlag(SubscriptionChangeMask.Created)) { _logger.SubscriptionCreated(this); _publishingStopped = false; } if (e.Status.HasFlag(SubscriptionChangeMask.Deleted)) { _logger.SubscriptionDeleted(this); } if (e.Status.HasFlag(SubscriptionChangeMask.Modified)) { _logger.SubscriptionModified2(this); } if (e.Status.HasFlag(SubscriptionChangeMask.ItemsAdded)) { _logger.SubscriptionItemsAdded(this); } if (e.Status.HasFlag(SubscriptionChangeMask.ItemsRemoved)) { _logger.SubscriptionItemsRemoved(this); } if (e.Status.HasFlag(SubscriptionChangeMask.ItemsCreated)) { _logger.SubscriptionItemsCreated(this); } if (e.Status.HasFlag(SubscriptionChangeMask.ItemsDeleted)) { _logger.SubscriptionItemsDeleted(this); } if (e.Status.HasFlag(SubscriptionChangeMask.ItemsModified)) { _logger.SubscriptionItemsModified(this); } if (e.Status.HasFlag(SubscriptionChangeMask.Transferred)) { _logger.SubscriptionTransferred(this); } } /// /// Helper to partition subscribers across subscriptions. Uses a bag packing /// algorithm. /// private sealed class Partition { /// /// Monitored items that should be in the subscription partition /// public List<(ISubscriber, BaseMonitoredItemModel)> Items { get; } = []; /// /// Create /// /// /// /// /// public static List Create(IEnumerable subscribers, uint maxMonitoredItemsInPartition, OpcUaSubscriptionOptions options) { var partitions = new List(); foreach (var subscriberItems in subscribers .Select(s => s.MonitoredItems .Select(m => (s, m.SetDefaults(options))) .ToList()) .OrderByDescending(tl => tl.Count)) { var placed = false; foreach (var partition in partitions) { if (partition.Items.Count + subscriberItems.Count <= maxMonitoredItemsInPartition) { partition.Items.AddRange(subscriberItems); placed = true; break; } } if (!placed) { // Break items into batches of max here and add partition each foreach (var batch in subscriberItems.Batch( (int)maxMonitoredItemsInPartition)) { var newPartition = new Partition(); newPartition.Items.AddRange(batch); partitions.Add(newPartition); } } } return partitions; } } /// /// Helper to advance the sequence number when all notifications are /// completed. /// private sealed class Advance : IDisposable { /// /// Create helper /// /// /// /// public Advance(OpcUaSubscription opcUaSubscription, uint sequenceNumber, int count) { _count = count; _opcUaSubscription = opcUaSubscription; _subscriptionId = opcUaSubscription.Id; _sequenceNumber = sequenceNumber; } /// public void Dispose() { var done = Interlocked.Decrement(ref _count); Debug.Assert(done >= 0); if (done == 0 && _opcUaSubscription.Id == _subscriptionId) { _opcUaSubscription._logger.AdvancingStream(_subscriptionId, _sequenceNumber); _opcUaSubscription._currentSequenceNumber = _sequenceNumber; } } private readonly OpcUaSubscription _opcUaSubscription; private readonly uint _subscriptionId; private readonly uint _sequenceNumber; private int _count; } private int HeartbeatsEnabled => MonitoredItems.Count(r => r is OpcUaMonitoredItem.Heartbeat h && h.TimerEnabled); private int ConditionsEnabled => MonitoredItems.Count(r => r is OpcUaMonitoredItem.Condition h && h.TimerEnabled); private IOpcUaClientDiagnostics State => (_client as IOpcUaClientDiagnostics) ?? OpcUaClient.Disconnected; /// /// Create observable metrics /// public void InitializeMetrics() { _meter.CreateObservableCounter("iiot_edge_publisher_missing_keep_alives", () => new Measurement(_missingKeepAlives, _metrics.TagList), description: "Number of missing keep alives in subscription."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_monitored_items", () => new Measurement(MonitoredItemCount, _metrics.TagList), description: "Total monitored item count."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_disabled_nodes", () => new Measurement(_disabledItems, _metrics.TagList), description: "Monitored items with monitoring mode disabled."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_nodes_monitoring_mode_inconsistent", () => new Measurement(_notAppliedItems, _metrics.TagList), description: "Monitored items with monitoring mode not applied."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_reporting_nodes", () => new Measurement(_reportingItems, _metrics.TagList), description: "Monitored items reporting."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_sampling_nodes", () => new Measurement(_samplingItems, _metrics.TagList), description: "Monitored items with sampling enabled."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_heartbeat_nodes", () => new Measurement(_heartbeatItems, _metrics.TagList), description: "Monitored items with heartbeats configured."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_heartbeat_enabled_nodes", () => new Measurement(HeartbeatsEnabled, _metrics.TagList), description: "Monitored items with heartbeats enabled."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_condition_nodes", () => new Measurement(_conditionItems, _metrics.TagList), description: "Monitored items with condition monitoring configured."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_condition_enabled_nodes", () => new Measurement(ConditionsEnabled, _metrics.TagList), description: "Monitored items with condition monitoring enabled."); _meter.CreateObservableCounter("iiot_edge_publisher_unassigned_notification_count", () => new Measurement(_unassignedNotifications, _metrics.TagList), description: "Number of notifications that could not be assigned."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_good_nodes", () => new Measurement(_goodMonitoredItems, _metrics.TagList), description: "Monitored items successfully created."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_bad_nodes", () => new Measurement(_badMonitoredItems, _metrics.TagList), description: "Monitored items that were not successfully created."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_late_nodes", () => new Measurement(_lateMonitoredItems, _metrics.TagList), description: "Monitored items that are late reporting."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_subscription_resync_count", () => new Measurement(_resyncCounter, _metrics.TagList), description: "How many times the subscriptions was resynced due to error."); _meter.CreateObservableCounter("iiot_edge_publisher_subscription_resync_total", () => new Measurement(_resyncTotal, _metrics.TagList), description: "Total number of resynchronization attempts on the subscription."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_subscription_stopped_count", () => new Measurement(_publishingStopped ? 1 : 0, _metrics.TagList), description: "Number of subscriptions that stopped publishing."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_deferred_acks_enabled_count", () => new Measurement(UseDeferredAcknoledgements ? 1 : 0, _metrics.TagList), description: "Number of subscriptions with deferred acknoledgements enabled."); _meter.CreateObservableCounter("iiot_edge_publisher_deferred_acks_last_sequencenumber", () => new Measurement(_sequenceNumber, _metrics.TagList), description: "Sequence number of the last notification received in subscription."); _meter.CreateObservableCounter("iiot_edge_publisher_deferred_acks_completed_sequencenumber", () => new Measurement(_currentSequenceNumber, _metrics.TagList), description: "Sequence number of the next notification to acknoledge in subscription."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_publish_requests_per_subscription", () => new Measurement(Ratio(State.OutstandingRequestCount, State.SubscriptionCount), _metrics.TagList), description: "Good publish requests per subsciption."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_good_publish_requests_per_subscription", () => new Measurement(Ratio(State.GoodPublishRequestCount, State.SubscriptionCount), _metrics.TagList), description: "Good publish requests per subsciption."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_bad_publish_requests_per_subscription", () => new Measurement(Ratio(State.BadPublishRequestCount, State.SubscriptionCount), _metrics.TagList), description: "Bad publish requests per subsciption."); _meter.CreateObservableUpDownCounter("iiot_edge_publisher_min_publish_requests_per_subscription", () => new Measurement(Ratio(State.MinPublishRequestCount, State.SubscriptionCount), _metrics.TagList), description: "Min publish requests queued per subsciption."); static double Ratio(int value, int count) => count == 0 ? 0.0 : (double)value / count; } private static readonly TimeSpan kMaxExponentialRetryDelayDefault = TimeSpan.FromSeconds(10); private const int kMaxMonitoredItemPerSubscriptionDefault = 64 * 1024; private uint _previousSequenceNumber; private uint _sequenceNumber; private uint _currentSequenceNumber; private bool _firstDataChangeReceived; private bool _forceRecreate; private uint? _childId; private readonly uint? _parentId; private readonly OpcUaClient _client; private readonly IOptions _options; private readonly ILoggerFactory _loggerFactory; private readonly ILogger _logger; private readonly IMetricsContext _metrics; private readonly ITimer _keepAliveWatcher; private readonly ITimer _monitoredItemWatcher; private readonly ITimer _resyncTimer; private readonly TimeProvider _timeProvider; private readonly Meter _meter = Diagnostics.NewMeter(); private static uint _lastIndex; private DateTimeOffset? _lastMonitoredItemCheck; private int _goodMonitoredItems; private int _reportingItems; private int _disabledItems; private int _samplingItems; private int _notAppliedItems; private int _heartbeatItems; private int _conditionItems; private int _lateMonitoredItems; private int _badMonitoredItems; private int _errorsDuringSync; private int _missingKeepAlives; private int _continuouslyMissingKeepAlives; private int _resyncCounter; private int _resyncTotal; private long _unassignedNotifications; private bool _publishingStopped; private bool _disposed; private bool _sendFakeKeepAlives; private readonly Lock _timers = new(); } /// /// Source-generated logging definitions for OpcUaSubscription /// internal static partial class OpcUaSubscriptionLogging { private const int EventClass = 1400; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Information, Message = "Disposed Subscription {Subscription} with {Count} items.")] public static partial void SubscriptionDisposedWithItems(this ILogger logger, OpcUaSubscription subscription, int count); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Information, Message = "Disposed Subscription {Subscription}.")] public static partial void SubscriptionDisposed(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Error, Message = "Disposing Subscription {Subscription} encountered error.")] public static partial void DisposalError(this ILogger logger, Exception ex, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Information, Message = "Closed Subscription {Subscription}.")] public static partial void SubscriptionClosed(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Error, Message = "Subscription {Subscription} closed!")] public static partial void SubscriptionClosedError(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Error, Message = "Failed to create keep alive for subscription {Subscription}.")] public static partial void KeepAliveCreateFailed(this ILogger logger, Exception ex, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Information, Message = "======== Closing subscription {Subscription} and re-creating =========")] public static partial void ClosingAndRecreatingSubscription(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 8, Level = LogLevel.Information, Message = "{State} Subscription {Subscription} in session {Session}.")] public static partial void StateSubscriptionSession(this ILogger logger, string state, OpcUaSubscription subscription, OpcUaSession session); [LoggerMessage(EventId = EventClass + 9, Level = LogLevel.Information, Message = "Creating new {State} subscription {Subscription} in session {Session}.")] public static partial void CreatingSubscription(this ILogger logger, string state, OpcUaSubscription subscription, OpcUaSession session); [LoggerMessage(EventId = EventClass + 10, Level = LogLevel.Information, Message = "Change KeepAliveCount to {New} in Subscription {Subscription}...")] public static partial void KeepAliveCountChanged(this ILogger logger, uint @new, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 11, Level = LogLevel.Information, Message = "Change publishing interval to {New} in Subscription {Subscription}...")] public static partial void PublishingIntervalChanged(this ILogger logger, TimeSpan @new, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 12, Level = LogLevel.Information, Message = "Change MaxNotificationsPerPublish to {New} in Subscription {Subscription}")] public static partial void MaxNotificationsPerPublishChanged(this ILogger logger, uint @new, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 13, Level = LogLevel.Information, Message = "Change LifetimeCount to {New} in Subscription {Subscription}...")] public static partial void LifetimeCountChanged(this ILogger logger, uint @new, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 14, Level = LogLevel.Information, Message = "Change Priority to {New} in Subscription {Subscription}...")] public static partial void PriorityChanged(this ILogger logger, byte @new, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 15, Level = LogLevel.Information, Message = "Subscription {Subscription} in session {Session} successfully modified.")] public static partial void SubscriptionModified(this ILogger logger, OpcUaSubscription subscription, OpcUaSession session); [LoggerMessage(EventId = EventClass + 16, Level = LogLevel.Information, Message = "Retrieved {Count} paths for items in subscription {Subscription}.")] public static partial void PathsRetrieved(this ILogger logger, int count, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 17, Level = LogLevel.Debug, Message = "Trying to update monitored item '{Item}' in {Subscription}...")] public static partial void UpdatingMonitoredItem(this ILogger logger, OpcUaMonitoredItem item, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 18, Level = LogLevel.Debug, Message = "Trying to remove monitored item '{Item}' from {Subscription}...")] public static partial void RemovingMonitoredItem(this ILogger logger, OpcUaMonitoredItem item, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 19, Level = LogLevel.Debug, Message = "Adding monitored item '{Item}' to {Subscription}...")] public static partial void AddingMonitoredItem(this ILogger logger, OpcUaMonitoredItem item, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 20, Level = LogLevel.Information, Message = "Disabled empty Subscription {Subscription} in session {Session}.")] public static partial void DisabledEmptySubscription(this ILogger logger, OpcUaSubscription subscription, OpcUaSession session); [LoggerMessage(EventId = EventClass + 21, Level = LogLevel.Debug, Message = "Completing {Count} same/added and {Removed} removed items in subscription {Subscription}...")] public static partial void CompletingItems(this ILogger logger, int count, int removed, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 22, Level = LogLevel.Debug, Message = "Completed {Count} valid and {Invalid} invalid items in subscription {Subscription}...")] public static partial void ItemCompletionStats(this ILogger logger, int count, int invalid, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 23, Level = LogLevel.Debug, Message = "Setting monitoring mode on {Count} items in subscription {Subscription}...")] public static partial void SettingMonitoringMode(this ILogger logger, int count, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 24, Level = LogLevel.Information, Message = "Set monitoring to {Value} for {Count} items in subscription {Subscription}.")] public static partial void MonitoringModeSet(this ILogger logger, Opc.Ua.MonitoringMode value, int count, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 25, Level = LogLevel.Information, Message = "Issuing ConditionRefresh on subscription {Subscription}")] public static partial void IssuingConditionRefresh(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 26, Level = LogLevel.Information, Message = "ConditionRefresh on subscription {Subscription} has completed.")] public static partial void ConditionRefreshCompleted(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 27, Level = LogLevel.Information, Message = "ConditionRefresh on subscription {Subscription} failed with an exception '{Message}'")] public static partial void ConditionRefreshFailed(this ILogger logger, OpcUaSubscription subscription, string message); [LoggerMessage(EventId = EventClass + 28, Level = LogLevel.Error, Message = "Child subscription {ChildId} not found in session {Session}.")] public static partial void ChildSubscriptionNotFound(this ILogger logger, uint? childId, OpcUaSession session); [LoggerMessage(EventId = EventClass + 29, Level = LogLevel.Debug, Message = "Closing subscription '{Subscription}'...")] public static partial void ClosingSubscription(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 30, Level = LogLevel.Debug, Message = "Deleted {Count} monitored items for '{Subscription}'.")] public static partial void DeletedMonitoredItems(this ILogger logger, int count, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 31, Level = LogLevel.Information, Message = "Subscription '{Subscription}' closed.")] public static partial void SubscriptionClosed2(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 32, Level = LogLevel.Error, Message = "Failed to close subscription {Subscription}")] public static partial void FailedToClose(this ILogger logger, Exception e, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 33, Level = LogLevel.Trace, Message = "Advancing stream #{SubscriptionId} to #{Position}")] public static partial void AdvancingStream(this ILogger logger, uint subscriptionId, uint position); [LoggerMessage(EventId = EventClass + 34, Level = LogLevel.Debug, Message = "A session was passed to send notification with but without message context. " + "Using thread context.")] public static partial void UsingThreadContext(this ILogger logger); [LoggerMessage(EventId = EventClass + 35, Level = LogLevel.Debug, Message = "Skipping the monitored item notification for Event received for subscription {Subscription}")] public static partial void SkippingEventNotification(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 36, Level = LogLevel.Debug, Message = "No notifications added to the message.")] public static partial void NoNotificationsAdded(this ILogger logger); [LoggerMessage(EventId = EventClass + 37, Level = LogLevel.Debug, Message = "Event callback took {Elapsed}")] public static partial void EventCallbackDuration(this ILogger logger, TimeSpan elapsed); [LoggerMessage(EventId = EventClass + 38, Level = LogLevel.Debug, Message = "Keep alive event received while publishing is not enabled - skip.")] public static partial void KeepAliveWhileNotPublishing(this ILogger logger); [LoggerMessage(EventId = EventClass + 39, Level = LogLevel.Debug, Message = "Keep alive for subscription {Subscription} with sequenceNumber {SequenceNumber}, " + "publishTime {PublishTime}.")] public static partial void KeepAliveReceived(this ILogger logger, OpcUaSubscription subscription, uint sequenceNumber, DateTime publishTime); [LoggerMessage(EventId = EventClass + 40, Level = LogLevel.Debug, Message = "Keep alive callback took {Elapsed}")] public static partial void KeepAliveDuration(this ILogger logger, TimeSpan elapsed); [LoggerMessage(EventId = EventClass + 41, Level = LogLevel.Debug, Message = "Skipping the cyclic read data change received for subscription {Subscription}")] public static partial void SkippingCyclicRead(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 42, Level = LogLevel.Debug, Message = "Cyclic read callback took {Elapsed}")] public static partial void CyclicReadDuration(this ILogger logger, TimeSpan elapsed); [LoggerMessage(EventId = EventClass + 43, Level = LogLevel.Debug, Message = "Skipping the monitored item notification for DataChange received for " + "subscription {Subscription}")] public static partial void SkippingDataChangeNotification(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 44, Level = LogLevel.Debug, Message = "Data change callback took {Elapsed}")] public static partial void DataChangeDuration(this ILogger logger, TimeSpan elapsed); [LoggerMessage(EventId = EventClass + 45, Level = LogLevel.Debug, Message = "Monitored item not found with client handle {ClientHandle} in subscription {Subscription}.")] public static partial void MonitoredItemNotFound(this ILogger logger, uint clientHandle, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 46, Level = LogLevel.Error, Message = "Failed to get a notifications from monitored items in subscription {Subscription}.")] public static partial void GetNotificationsFailed(this ILogger logger, Exception ex, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 47, Level = LogLevel.Information, Message = "{Subscription}: Stopping monitored item watchdog ({Timeout}).")] public static partial void StoppingWatchdog(this ILogger logger, OpcUaSubscription subscription, TimeSpan timeout); [LoggerMessage(EventId = EventClass + 48, Level = LogLevel.Information, Message = "{Subscription}: Restarting monitored item watchdog ({Timeout}).")] public static partial void RestartingWatchdog(this ILogger logger, OpcUaSubscription subscription, TimeSpan timeout); [LoggerMessage(EventId = EventClass + 49, Level = LogLevel.Debug, Message = "Monitored item {Item} in subscription {Subscription} is late.")] public static partial void MonitoredItemLate(this ILogger logger, OpcUaMonitoredItem item, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 50, Level = LogLevel.Debug, Message = "All monitored items in {Subscription} are reporting.")] public static partial void AllItemsReporting(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 51, Level = LogLevel.Debug, Message = "{Count} of the {Total} monitored items in {Subscription} are late " + "- no action.")] public static partial void SomeItemsLateDebug(this ILogger logger, int count, int total, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 52, Level = LogLevel.Information, Message = "{Count} of the {Total} monitored items in {Subscription} are now late " + "- running {Action} behavior action.")] public static partial void LateItemsSummary(this ILogger logger, int count, int total, OpcUaSubscription subscription, SubscriptionWatchdogBehavior action); [LoggerMessage(EventId = EventClass + 53, Level = LogLevel.Critical, Message = "{Message}")] public static partial void DiagnosticMessage(this ILogger logger, string message); [LoggerMessage(EventId = EventClass + 54, Level = LogLevel.Critical, Message = "#{Count}/{Lifetimecount}: Keep alive count exceeded. Perform {Action} for {Subscription}...")] public static partial void KeepAliveExceeded(this ILogger logger, int count, uint lifetimeCount, SubscriptionWatchdogBehavior action, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 55, Level = LogLevel.Information, Message = "#{Count}/{Lifetimecount}: Subscription {Subscription} is missing keep alive.")] public static partial void MissingKeepAlive(this ILogger logger, int count, uint lifetimeCount, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 56, Level = LogLevel.Information, Message = "Subscription {Subscription} STOPPED!")] public static partial void SubscriptionStopped(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 57, Level = LogLevel.Information, Message = "Subscription {Subscription} RECOVERED!")] public static partial void SubscriptionRecovered(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 58, Level = LogLevel.Information, Message = "Subscription {Subscription} transferred.")] public static partial void SubscriptionTransferred(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 59, Level = LogLevel.Information, Message = "Subscription {Subscription} republishing...")] public static partial void SubscriptionRepublishing(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 60, Level = LogLevel.Trace, Message = "Subscription {Subscription} keep alive.")] public static partial void SubscriptionKeepAlive(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 61, Level = LogLevel.Information, Message = "Subscription {Subscription} TIMEOUT! " + "---- Server closed subscription - performing recovery action {Action}...")] public static partial void SubscriptionTimeout(this ILogger logger, OpcUaSubscription subscription, string action); [LoggerMessage(EventId = EventClass + 62, Level = LogLevel.Debug, Message = "Subscription {Subscription} created.")] public static partial void SubscriptionCreated(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 63, Level = LogLevel.Debug, Message = "Subscription {Subscription} deleted.")] public static partial void SubscriptionDeleted(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 64, Level = LogLevel.Debug, Message = "Subscription {Subscription} modified")] public static partial void SubscriptionModified2(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 65, Level = LogLevel.Debug, Message = "Subscription {Subscription} items added.")] public static partial void SubscriptionItemsAdded(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 66, Level = LogLevel.Debug, Message = "Subscription {Subscription} items removed.")] public static partial void SubscriptionItemsRemoved(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 67, Level = LogLevel.Debug, Message = "Subscription {Subscription} items created.")] public static partial void SubscriptionItemsCreated(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 68, Level = LogLevel.Debug, Message = "Subscription {Subscription} items deleted.")] public static partial void SubscriptionItemsDeleted(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 69, Level = LogLevel.Debug, Message = "Subscription {Subscription} items modified.")] public static partial void SubscriptionItemsModified(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 70, Level = LogLevel.Information, Message = "{Subscription} - [{ResyncCount}/{ResyncTotal}] Removed {Removed} - now monitoring {Count} nodes:" + "\n# Good/Bad/Reporting: {Good}/{Bad}/{Reporting}")] public static partial void SubscriptionReportState(this ILogger logger, OpcUaSubscription subscription, int resyncCount, int resyncTotal, int removed, int count, int good, int bad, int reporting); [LoggerMessage(EventId = EventClass + 71, Level = LogLevel.Warning, Message = "{Subscription} - [{ResyncCount}/{ResyncTotal}] Removed {Removed} - now monitoring {Count} nodes:" + "\n# Good/Bad/Reporting: {Good}/{Bad}/{Reporting}" + "\n# Disabled/Errors: {Disabled}/{Errors}")] public static partial void SubscriptionReportStateWithErrors(this ILogger logger, OpcUaSubscription subscription, int resyncCount, int resyncTotal, int removed, int count, int good, int bad, int reporting, int disabled, int errors); [LoggerMessage(EventId = EventClass + 72, Level = LogLevel.Information, Message = "{Subscription} - [{ResyncCount}/{ResyncTotal}] Removed {Removed} - now monitoring {Count} nodes:" + "\n# Good/Bad/Reporting: {Good}/{Bad}/{Reporting}" + "\n# Disabled/Errors: {Disabled}/{Errors} (Not applied: {NotApplied})" + "\n# Sampling: {Sampling}" + "\n# Heartbeat/ing: {Heartbeat}/{EnabledHeartbeats}" + "\n# Condition/ing: {Conditions}/{EnabledConditions}")] public static partial void SubscriptionReportStateFull(this ILogger logger, OpcUaSubscription subscription, int resyncCount, int resyncTotal, int removed, int count, int good, int bad, int reporting, int disabled, int errors, int notApplied, int sampling, int heartbeat, int enabledHeartbeats, int conditions, int enabledConditions); [LoggerMessage(EventId = EventClass + 73, Level = LogLevel.Debug, Message = "{Subscription} - [{ResyncCount}/{ResyncTotal}] Applied changes to monitored items, but nothing changed.")] public static partial void SubscriptionNoMonitoredItemChange(this ILogger logger, OpcUaSubscription subscription, int resyncCount, int resyncTotal); [LoggerMessage(EventId = EventClass + 74, Level = LogLevel.Information, Message = "Successfully created subscription {Subscription}'.\nActual (revised) state/desired state:" + "\n# PublishingEnabled {CurrentPublishingEnabled}/{PublishingEnabled}" + "\n# PublishingInterval {CurrentPublishingInterval}/{PublishingInterval}" + "\n# KeepAliveCount {CurrentKeepAliveCount}/{KeepAliveCount}" + "\n# LifetimeCount {CurrentLifetimeCount}/{LifetimeCount}")] public static partial void RevisedValuesDuringCreate(this ILogger logger, OpcUaSubscription subscription, bool currentPublishingEnabled, bool publishingEnabled, int currentPublishingInterval, int publishingInterval, uint currentKeepAliveCount, uint keepAliveCount, uint currentLifetimeCount, uint lifetimeCount); [LoggerMessage(EventId = EventClass + 75, Level = LogLevel.Information, Message = "Successfully modified subscription {Subscription}'.\nActual (revised) state/desired state:" + "\n# PublishingEnabled {CurrentPublishingEnabled}/{PublishingEnabled}" + "\n# PublishingInterval {CurrentPublishingInterval}/{PublishingInterval}" + "\n# KeepAliveCount {CurrentKeepAliveCount}/{KeepAliveCount}" + "\n# LifetimeCount {CurrentLifetimeCount}/{LifetimeCount}")] public static partial void RevisedValuesDuringModify(this ILogger logger, OpcUaSubscription subscription, bool currentPublishingEnabled, bool publishingEnabled, int currentPublishingInterval, int publishingInterval, uint currentKeepAliveCount, uint keepAliveCount, uint currentLifetimeCount, uint lifetimeCount); [LoggerMessage(EventId = EventClass + 76, Level = LogLevel.Warning, Message = "Failed to resolve browse path in {Subscription} due to {ErrorInfo}...")] public static partial void BrowsePathResolveFailed(this ILogger logger, OpcUaSubscription subscription, ServiceResultModel errorInfo); [LoggerMessage(EventId = EventClass + 77, Level = LogLevel.Warning, Message = "Failed to resolve browse path for {NodeId} in {Subscription} due to '{ServiceResult}'")] public static partial void BrowsePathForNodeResolveFailed(this ILogger logger, string nodeId, OpcUaSubscription subscription, ServiceResultModel? serviceResult); [LoggerMessage(EventId = EventClass + 78, Level = LogLevel.Warning, Message = "Failed to get root path for {NodeId} in {Subscription} due to '{ServiceResult}'")] public static partial void RootPathResolveFailed(this ILogger logger, string nodeId, OpcUaSubscription subscription, ServiceResultModel? serviceResult); [LoggerMessage(EventId = EventClass + 79, Level = LogLevel.Warning, Message = "Failed to update monitored item '{Item}' in {Subscription}...")] public static partial void MonitoredItemUpdateFailed(this ILogger logger, Exception ex, OpcUaMonitoredItem item, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 80, Level = LogLevel.Warning, Message = "Failed to remove monitored item '{Item}' from {Subscription}...")] public static partial void MonitoredItemRemoveFailed(this ILogger logger, Exception ex, OpcUaMonitoredItem item, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 81, Level = LogLevel.Warning, Message = "Failed to add monitored item '{Item}' to {Subscription}...")] public static partial void MonitoredItemAddFailed(this ILogger logger, Exception ex, OpcUaMonitoredItem item, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 82, Level = LogLevel.Warning, Message = "Failed to resolve display name in {Subscription} due to {ErrorInfo}...")] public static partial void DisplayNameResolveFailed(this ILogger logger, OpcUaSubscription subscription, ServiceResultModel errorInfo); [LoggerMessage(EventId = EventClass + 83, Level = LogLevel.Warning, Message = "Failed to read display name for {NodeId} in {Subscription} due to '{ServiceResult}'")] public static partial void DisplayNameReadFailed(this ILogger logger, string nodeId, OpcUaSubscription subscription, ServiceResultModel? serviceResult); [LoggerMessage(EventId = EventClass + 84, Level = LogLevel.Warning, Message = "Failed to set monitoring for {Count} items in subscription {Subscription}.")] public static partial void MonitoringSetFailed(this ILogger logger, int count, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 85, Level = LogLevel.Warning, Message = "Set monitoring for item '{Item}' in subscription {Subscription} failed with '{Status}'.")] public static partial void MonitoringSetFailedForItem(this ILogger logger, NodeId item, OpcUaSubscription subscription, StatusCode status); [LoggerMessage(EventId = EventClass + 86, Level = LogLevel.Warning, Message = "EventChange for subscription {Subscription} has empty notification.")] public static partial void EmptyEventNotification(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 87, Level = LogLevel.Warning, Message = "EventChange for subscription {Subscription} has no events.")] public static partial void NoEventsInNotification(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 88, Level = LogLevel.Warning, Message = "EventChange for subscription {Subscription} received without a session {Session}.")] public static partial void EventChangeWithoutSession(this ILogger logger, OpcUaSubscription subscription, string? session); [LoggerMessage(EventId = EventClass + 89, Level = LogLevel.Warning, Message = "Event subscription notification for subscription {Subscription} has unexpected " + "sequenceNumber {SequenceNumber} missing {ExpectedSequenceNumber} which were {State}, publishTime {PublishTime}")] public static partial void UnexpectedEventSequenceNumber(this ILogger logger, OpcUaSubscription subscription, uint sequenceNumber, string expectedSequenceNumber, string state, DateTime publishTime); [LoggerMessage(EventId = EventClass + 90, Level = LogLevel.Warning, Message = "Exception processing subscription notification")] public static partial void EventProcessingError(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 91, Level = LogLevel.Warning, Message = "Spent more than 1 second in fast event callback.")] public static partial void SlowEventCallback(this ILogger logger); [LoggerMessage(EventId = EventClass + 92, Level = LogLevel.Warning, Message = "Keep alive event for subscription {Subscription} received without session {Session}.")] public static partial void KeepAliveWithoutSession(this ILogger logger, OpcUaSubscription subscription, string? session); [LoggerMessage(EventId = EventClass + 93, Level = LogLevel.Warning, Message = "Exception processing keep alive notification")] public static partial void KeepAliveProcessingError(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 94, Level = LogLevel.Warning, Message = "Spent more than 1 second in fast keep alive callback.")] public static partial void SlowKeepAliveCallback(this ILogger logger); [LoggerMessage(EventId = EventClass + 95, Level = LogLevel.Warning, Message = "DataChange for subscription {Subscription} received without session {Session}.")] public static partial void DataChangeWithoutSession(this ILogger logger, OpcUaSubscription subscription, string? session); [LoggerMessage(EventId = EventClass + 96, Level = LogLevel.Warning, Message = "Exception processing cyclic read notification")] public static partial void CyclicReadProcessingError(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 97, Level = LogLevel.Warning, Message = "Exception processing subscription notification")] public static partial void DataChangeNotificationError(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 98, Level = LogLevel.Warning, Message = "Spent more than 1 second in fast data change callback.")] public static partial void SlowDataChangeCallback(this ILogger logger); [LoggerMessage(EventId = EventClass + 99, Level = LogLevel.Warning, Message = "Spent more than 1 second in fast cyclic read callback.")] public static partial void SlowCyclicReadCallback(this ILogger logger); [LoggerMessage(EventId = EventClass + 100, Level = LogLevel.Warning, Message = "DataChange notification for subscription {Subscription} has unexpected sequenceNumber " + "{SequenceNumber} missing {ExpectedSequenceNumber} which were {Dropped}, publishTime {PublishTime}")] public static partial void UnexpectedDataChangeSequenceNumber(this ILogger logger, OpcUaSubscription subscription, uint sequenceNumber, string expectedSequenceNumber, string dropped, DateTime publishTime); [LoggerMessage(EventId = EventClass + 101, Level = LogLevel.Debug, Message = "Error {Error} occurred {Count} times for subscription {SubscriptionId}.")] public static partial void ErrorAddingMonitoredItems(this ILogger logger, string error, int count, uint subscriptionId); [LoggerMessage(EventId = EventClass + 102, Level = LogLevel.Error, Message = "Error {Error} occurred {Count} times for subscription {SubscriptionId}. NEW:\n {Items}.")] public static partial void ErrorAddingMonitoredItemsWithErrors(this ILogger logger, string error, int count, uint subscriptionId, string items); [LoggerMessage(EventId = EventClass + 103, Level = LogLevel.Information, Message = "All monitored items in {Subscription} are late.")] public static partial void AllItemsLate(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 104, Level = LogLevel.Information, Message = "Some monitored items in {Subscription} are late.")] public static partial void SomeItemsLate(this ILogger logger, OpcUaSubscription subscription); [LoggerMessage(EventId = EventClass + 105, Level = LogLevel.Information, Message = "Resync timer set to {RetryDelay} for {Subscription}.")] public static partial void ResyncTimerArmed(this ILogger logger, TimeSpan retryDelay, OpcUaSubscription subscription); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Services/OpcUaSubscriptionNotification.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Models { using Azure.IIoT.OpcUa.Publisher.Stack.Services; using Azure.IIoT.OpcUa.Encoders.PubSub; using Opc.Ua; using System; using System.Collections.Generic; using System.Diagnostics; /// /// Opc Ua subscription notification /// public sealed record class OpcUaSubscriptionNotification : IDisposable { /// public object? Context { get; set; } /// public uint SequenceNumber { get; internal set; } /// public MessageType MessageType { get; internal set; } /// public string? EventTypeName { get; internal set; } /// public string? EndpointUrl { get; internal set; } /// public string? ApplicationUri { get; internal set; } /// public DateTimeOffset? PublishTimestamp { get; internal set; } /// public uint? PublishSequenceNumber { get; private set; } /// public IServiceMessageContext ServiceMessageContext { get; private set; } /// public IList Notifications { get; private set; } /// public DateTimeOffset CreatedTimestamp { get; } /// /// Create acknoledgeable notification /// /// /// /// /// /// /// /// internal OpcUaSubscriptionNotification(OpcUaSubscription outer, IServiceMessageContext messageContext, IList notifications, TimeProvider timeProvider, IDisposable? advance = null, uint? sequenceNumber = null, DateTimeOffset? createdTimestamp = null) { _outer = outer; _advance = advance; PublishSequenceNumber = sequenceNumber; CreatedTimestamp = createdTimestamp ?? timeProvider.GetUtcNow(); ServiceMessageContext = messageContext; Notifications = notifications; } internal OpcUaSubscriptionNotification(DateTimeOffset createdTimestamp, ServiceMessageContext? serviceMessageContext = null, IList? notifications = null) { _outer = null; _advance = null; CreatedTimestamp = createdTimestamp; ServiceMessageContext = serviceMessageContext ?? new(); Notifications = notifications ?? Array.Empty(); } /// /// Create an empty notification /// /// /// internal OpcUaSubscriptionNotification(OpcUaSubscriptionNotification template, IList? notifications = null) { _outer = null; _advance = null; Notifications = notifications ?? Array.Empty(); CreatedTimestamp = template.CreatedTimestamp; Context = template.Context; ServiceMessageContext = template.ServiceMessageContext; ApplicationUri = template.ApplicationUri; EndpointUrl = template.EndpointUrl; EventTypeName = template.EventTypeName; PublishTimestamp = template.PublishTimestamp; PublishSequenceNumber = template.PublishSequenceNumber; MessageType = template.MessageType; SequenceNumber = template.SequenceNumber; } /// public bool TryUpgradeToKeyFrame(ISubscriber owner) { if (MessageType == MessageType.KeyFrame) { // Already a key frame return true; } if (_outer != null && _outer.TryGetNotifications(owner, out var allNotifications)) { MessageType = MessageType.KeyFrame; if (Notifications.IsReadOnly) { Notifications = [.. allNotifications]; } else { Notifications.Clear(); Notifications.AddRange(allNotifications); } return true; } return false; } /// public void Dispose() { _advance?.Dispose(); } #if DEBUG /// public void MarkProcessed() { _processed = true; } /// public void DebugAssertProcessed() { if (Context == null || _processed) { return; } Debug.Fail("Item not processed"); } private bool _processed; #endif /// /// Get diagnostics info from message /// /// /// /// /// internal int GetDiagnosticCounters(out int modelChanges, out int heartbeats, out int overflow) { modelChanges = 0; heartbeats = 0; overflow = 0; foreach (var n in Notifications) { if (n.Flags.HasFlag(MonitoredItemSourceFlags.ModelChanges)) { modelChanges++; } else if (n.Flags.HasFlag(MonitoredItemSourceFlags.Heartbeat)) { heartbeats++; } overflow += n.Overflow; } return Notifications.Count; } private readonly OpcUaSubscription? _outer; private readonly IDisposable? _advance; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/StackExtensions.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { using Opc.Ua; /// /// Samples message extension flags /// internal static class JsonDataSetMessageContentMaskEx { /// /// Extra fields included /// public const JsonDataSetMessageContentMask ExtensionFields = (JsonDataSetMessageContentMask)0x02000000; /// /// Node id included /// public const JsonDataSetMessageContentMask NodeId = (JsonDataSetMessageContentMask)0x10000000; /// /// Endpoint url included /// public const JsonDataSetMessageContentMask EndpointUrl = (JsonDataSetMessageContentMask)0x20000000; /// /// Application uri /// public const JsonDataSetMessageContentMask ApplicationUri = (JsonDataSetMessageContentMask)0x40000000; /// /// Display name included /// public const JsonDataSetMessageContentMask DisplayName = (JsonDataSetMessageContentMask)0x80000000; } /// /// Extensions for fields /// internal static class DataSetFieldContentMaskEx { /// /// Degrade a single data set field to just value instead of writing key value dictionary object /// public const DataSetFieldContentMask SingleFieldDegradeToValue = (DataSetFieldContentMask)64; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Transport/Extensions/EndPointEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace System.Net { using System.Net.Sockets; using System.Threading.Tasks; /// /// Endpoint extensions /// public static class EndPointEx { /// /// Get ip address from endpoint if the endpoint is an /// IPEndPoint. Otherwise return null. /// /// /// /// /// public static IPAddress GetIPAddress(this EndPoint endpoint, bool preferv4 = false) { if (endpoint is not IPEndPoint ipe) { throw new ArgumentException( "Failed to convert endpoint to ip endpoint."); } var address = ipe.Address; if (preferv4 && address.AddressFamily == AddressFamily.InterNetworkV6 && address.IsIPv4MappedToIPv6) { return address.MapToIPv4(); } return address; } /// /// Get port from endpoint if the endpoint is an /// IPEndPoint. Otherwise return -1. /// /// /// public static int GetPort(this EndPoint endpoint) { if (endpoint is IPEndPoint ipe) { return ipe.Port; } return -1; } /// /// Resolve endpoint to host:port or throw. /// /// /// public static string Resolve(this EndPoint endpoint) { var entry = endpoint.GetIPAddress().GetHostEntry(); return $"{entry.HostName}:{endpoint.GetPort()}"; } /// /// Resolve endpoint to host:port or throw. /// /// /// public static async Task ResolveAsync(this EndPoint endpoint) { var entry = await endpoint.GetIPAddress().GetHostEntryAsync().ConfigureAwait(false); return $"{entry.HostName}:{endpoint.GetPort()}"; } /// /// Resolve endpoint to host:port or return address:port as /// string if resolve fails /// /// /// public static string TryResolve(this EndPoint endpoint) { try { return endpoint.Resolve(); } catch { return $"{endpoint.GetIPAddress(true)}:{endpoint.GetPort()}"; } } /// /// Resolve endpoint to host:port or return address:port as /// string if resolve fails /// /// /// public static async Task TryResolveAsync(this EndPoint endpoint) { try { return await endpoint.ResolveAsync().ConfigureAwait(false); } catch { return $"{endpoint.GetIPAddress(true)}:{endpoint.GetPort()}"; } } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Transport/Extensions/IPAddressEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace System.Net { using System.Threading.Tasks; using Azure.IIoT.OpcUa.Publisher.Stack.Transport.Models; /// /// Ip address extensions /// public static class IPAddressEx { /// /// Clone address as v4 address /// /// /// public static IPv4Address AsV4(this IPAddress address) { return new IPv4Address(address.GetAddressBytes()); } /// /// Resolve address to host entry /// /// /// public static IPHostEntry GetHostEntry(this IPAddress address) { return Dns.GetHostEntry(address); } /// /// Resolve address to host /// /// /// public static Task GetHostEntryAsync(this IPAddress address) { return Dns.GetHostEntryAsync(address); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Transport/Extensions/NetworkInformationEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Transport { using Azure.IIoT.OpcUa.Publisher.Stack.Transport.Models; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; /// /// Network information extensions /// public static class NetworkInformationEx { /// /// Get all interface addresses /// /// /// public static IEnumerable GetAllNetInterfaces( NetworkClass netclass) { return NetworkInterface.GetAllNetworkInterfaces() .Where(n => n.NetworkInterfaceType.IsInClass(netclass) && n.OperationalStatus == OperationalStatus.Up && n.GetIPProperties()?.GatewayAddresses.Count > 0) .SelectMany(n => n.GetIPProperties().UnicastAddresses .Select(x => new NetInterface(n.Name, n.GetPhysicalAddress(), x.Address, x.IPv4Mask, n.GetIPProperties().GatewayAddresses .First(a => a != null).Address, n.GetIPProperties().DnsSuffix, n.GetIPProperties().DnsAddresses))) .Where(t => t.UnicastAddress.AddressFamily == AddressFamily.InterNetwork && !IPAddress.IsLoopback(t.UnicastAddress)) .Distinct(); } /// /// Check whether the interface type fits the class /// /// /// /// public static bool IsInClass(this NetworkInterfaceType type, NetworkClass netclass) { switch (type) { case NetworkInterfaceType.Ethernet: case NetworkInterfaceType.Ethernet3Megabit: case NetworkInterfaceType.GigabitEthernet: case NetworkInterfaceType.FastEthernetT: case NetworkInterfaceType.FastEthernetFx: case NetworkInterfaceType.Slip: case NetworkInterfaceType.IPOverAtm: return (netclass & NetworkClass.Wired) != 0; case NetworkInterfaceType.BasicIsdn: case NetworkInterfaceType.PrimaryIsdn: case NetworkInterfaceType.Isdn: case NetworkInterfaceType.GenericModem: case NetworkInterfaceType.AsymmetricDsl: case NetworkInterfaceType.SymmetricDsl: case NetworkInterfaceType.RateAdaptDsl: case NetworkInterfaceType.VeryHighSpeedDsl: case NetworkInterfaceType.MultiRateSymmetricDsl: case NetworkInterfaceType.Ppp: return (netclass & NetworkClass.Modem) != 0; case NetworkInterfaceType.Wireless80211: case NetworkInterfaceType.Wman: case NetworkInterfaceType.Wwanpp: case NetworkInterfaceType.Wwanpp2: return (netclass & NetworkClass.Wireless) != 0; case NetworkInterfaceType.Tunnel: return (netclass & NetworkClass.Tunnel) != 0; case NetworkInterfaceType.TokenRing: case NetworkInterfaceType.HighPerformanceSerialBus: case NetworkInterfaceType.Fddi: case NetworkInterfaceType.Atm: case NetworkInterfaceType.Loopback: return false; } return false; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Transport/Extensions/PhysicalAddressEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Transport { using System.Net.NetworkInformation; /// /// Physical address extensions /// public static class PhysicalAddressEx { /// /// Clone address /// /// /// public static PhysicalAddress Copy(this PhysicalAddress address) { return new PhysicalAddress(address.GetAddressBytes()); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Transport/IAsyncProbe.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Transport { using System; using System.Net.Sockets; /// /// Async port probe /// public interface IAsyncProbe : IDisposable { /// /// Complete probe using the passed in socket /// event arg. /// /// /// /// /// If the probe returns true, this value /// indicates whether the port is a valid port. /// /// Async timeout /// /// false if expected to be called again. /// true if probe is complete. /// bool OnComplete(int index, SocketAsyncEventArgs arg, out bool ok, out int timeout); /// /// Reset probe to beginning cancelling any /// outstanding socket operations. /// /// false if not cancelled bool Reset(); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Transport/IPortProbe.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Transport { /// /// Port probe factory /// public interface IPortProbe { /// /// Create async probe handler /// /// IAsyncProbe Create(); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Transport/IScanner.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Transport { using System; using System.Threading.Tasks; /// /// Scanner interface /// public interface IScanner : IDisposable { /// /// Number of currently active probes /// int ActiveProbes { get; } /// /// Items scanned so far /// int ScanCount { get; } /// /// Task that completes when scan is done. /// Task WaitToCompleteAsync(); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Transport/Models/AddressRange.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Transport.Models { using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Net; using System.Text; /// /// Represents a range of ipv4 addresses /// public sealed class AddressRange { /// /// Name of the Network interface. /// public string Nic { get; } /// /// Lowest address in range in host order /// public uint Low { get; } /// /// Highest address in range in host order /// public uint High { get; } /// /// Number of addresses in range /// public int Count => (int)(High - Low) + 1; /// /// Create address range /// /// /// /// public AddressRange(uint low, uint high, string? nic = null) { Nic = string.IsNullOrEmpty(nic) ? kNullNicName : nic; Low = _cur = low > high ? high : low; High = high < low ? low : high; } /// /// Create address range /// /// /// /// public AddressRange(IPAddress address, int suffix, string? nic = null) { ArgumentNullException.ThrowIfNull(address); if (suffix > 32) { throw new ArgumentException("Suffix too large", nameof(suffix)); } var curAddr = (uint)IPAddress.NetworkToHostOrder( (int)BitConverter.ToUInt32( address.GetAddressBytes(), 0)); var mask = 0xffffffff << (32 - suffix); High = curAddr | ~mask; Low = _cur = curAddr & mask; Nic = string.IsNullOrEmpty(nic) ? kNullNicName : nic; System.Diagnostics.Debug.Assert(Low <= High); System.Diagnostics.Debug.Assert(High != 0); } /// /// Create address range from unicast address uinfo /// /// /// /// public AddressRange(NetInterface itf, bool localOnly = false, int? suffix = null) { ArgumentNullException.ThrowIfNull(itf); var curAddr = (uint)new IPv4Address(itf.UnicastAddress); Nic = string.IsNullOrEmpty(itf.Name) ? kNullNicName : itf.Name; if (localOnly) { // Add local address only High = curAddr; Low = _cur = curAddr; } else { var mask = suffix == null ? (uint)new IPv4Address(itf.SubnetMask) : 0xffffffff << (32 - suffix.Value); High = curAddr | ~mask; Low = _cur = curAddr & mask; } System.Diagnostics.Debug.Assert(Low <= High); System.Diagnostics.Debug.Assert(High != 0); } /// /// Create address range from address and subnet mask /// /// /// /// /// public AddressRange(IPAddress address, IPAddress subnet, int? suffix = null, string? nic = null) { ArgumentNullException.ThrowIfNull(address); ArgumentNullException.ThrowIfNull(subnet); var mask = suffix == null ? (uint)new IPv4Address(subnet) : 0xffffffff << (32 - suffix.Value); var curAddr = new IPv4Address(address); Nic = string.IsNullOrEmpty(nic) ? kNullNicName : nic; High = curAddr | ~mask; Low = _cur = curAddr & mask; System.Diagnostics.Debug.Assert(Low <= High); System.Diagnostics.Debug.Assert(High != 0); } /// public override bool Equals(object? obj) { if (obj is not AddressRange range) { return false; } return Low == range.Low && High == range.High; } /// public static bool operator ==(AddressRange range1, AddressRange range2) => EqualityComparer.Default.Equals(range1, range2); /// public static bool operator !=(AddressRange range1, AddressRange range2) => !(range1 == range2); /// public override int GetHashCode() { return HashCode.Combine(Low, High); } /// public override string ToString() { var sb = new StringBuilder(); AppendTo(sb); return sb.ToString(); } /// /// Clone /// /// public AddressRange Copy() { return new AddressRange(Low, High, Nic); } /// /// Parses a series of address ranges /// /// /// /// public static bool TryParse(string value, [NotNullWhen(true)] out IEnumerable? ranges) { try { ranges = Parse(value); return true; } catch { ranges = null; return false; } } /// /// Format a series of address ranges /// /// /// public static string Format(IEnumerable ranges) { var sb = new StringBuilder(); var first = true; foreach (var range in Merge(ranges)) { if (!first) { sb.Append(';'); } first = false; range.AppendTo(sb); } return sb.ToString(); } /// /// Parse /// /// /// /// public static IEnumerable Parse(string value) { if (string.IsNullOrEmpty(value)) { throw new ArgumentNullException(nameof(value)); } var split = value.Split([';', ','], StringSplitOptions.RemoveEmptyEntries); var unmerged = split .SelectMany(s => { var nic = string.Empty; var x = s.Split('[', StringSplitOptions.RemoveEmptyEntries); if (x.Length > 1) { var postFix = x[1].Split(']'); if (postFix.Length > 1) { nic = postFix[0]; } s = x[0].Trim(); } x = s.Split('/', StringSplitOptions.RemoveEmptyEntries); if (x.Length != 2) { x = s.Split('-', StringSplitOptions.RemoveEmptyEntries); if (x.Length != 2) { throw new FormatException("Bad suffix format"); } // Combine into cidr ranges and parse so we get distinct ranges return Parse(new AddressRange( new IPv4Address(IPAddress.Parse(x[0])), new IPv4Address(IPAddress.Parse(x[1])), nic).ToString()); } var suffix = int.Parse(x[1], CultureInfo.InvariantCulture); if (suffix == 0 || suffix > 32) { throw new FormatException("Bad suffix value"); } if (x[0] == "*") { return NetworkInformationEx.GetAllNetInterfaces( NetworkClass.Wired) .Select(t => new AddressRange(t, false, suffix)); } return new AddressRange(IPAddress.Parse(x[0]), suffix, nic) .YieldReturn(); }) .Distinct() .ToList(); return Merge(unmerged); } /// /// Fills next batch of addresses /// /// /// public void FillNextBatch(IList batch, int count) { for (var i = 0; _cur <= High && i < count; i++) { batch.Add(_cur++); } } /// /// Reset range /// public void Reset() { _cur = Low; } /// /// Tests contains address /// /// /// public bool Contains(IPv4Address value) { return value >= Low && value <= High; } /// /// Whether it overlaps with another address range /// /// /// public bool Overlaps(AddressRange other) { return Contains(other.Low) || Contains(other.High) || other.Contains(Low) || other.Contains(High); } /// /// Merge overlapping ranges /// /// /// private static IEnumerable Merge(IEnumerable ranges) { var results = new Stack(); if (ranges != null) { foreach (var range in ranges.OrderBy(k => k.Low)) { if (results.Count == 0) { results.Push(range); } else { var top = results.Peek(); if (top.Overlaps(range)) { var nic = (top.Nic + range.Nic) .Replace("localhost", "", StringComparison.InvariantCulture) .Replace(kNullNicName, "", StringComparison.InvariantCulture); var union = new AddressRange( top.Low < range.Low ? top.Low : range.Low, top.High > range.High ? top.High : range.High, nic); results.Pop(); results.Push(union); } else { results.Push(range); } } } } return results.Reverse(); } /// /// Convert address range to cidr formatted ip strings /// /// /// private void AppendTo(StringBuilder sb) { long start = Low; long end = High; var first = true; while (end >= start) { byte subnetSize = 32; while (subnetSize > 0) { var mask = (1L << 32) - (1L << (32 - (subnetSize - 1))); if ((start & mask) != start) { break; } subnetSize--; } var x = Math.Floor(Math.Log(end - start + 1) / Math.Log(2)); var maxDiff = (byte)(32 - x); if (subnetSize < maxDiff) { subnetSize = maxDiff; } var ip = ((IPv4Address)start).ToString(); if (!first) { sb.Append(';'); } first = false; sb.Append(ip).Append('/').Append(subnetSize); if (Nic != kNullNicName) { sb.Append(" [").Append(Nic).Append(']'); } start += 1L << (32 - subnetSize); } } private const string kNullNicName = "custom"; private uint _cur; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Transport/Models/IPv4Address.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Transport.Models { using System; using System.Collections.Generic; using System.Net; /// /// IPV4 address /// public sealed class IPv4Address : IPAddress, IComparable, IComparable { /// /// Create address /// /// private IPv4Address(uint address) : base(address) { } /// /// Create address /// /// public IPv4Address(IPAddress address) : this(address.GetAddressBytes()) { } /// /// Create address /// /// public IPv4Address(byte[] address) : base(address) { if (address.Length != 4) { throw new ArgumentException(nameof(address.Length)); } } /// /// Convert to and from uint /// /// public static implicit operator uint(IPv4Address value) => (uint) NetworkToHostOrder((int)BitConverter.ToUInt32(value.GetAddressBytes(), 0)); /// /// Convert back to address from uint /// /// public static implicit operator IPv4Address(uint value) => new((uint)HostToNetworkOrder((int)value)); /// /// Convert from long /// /// public static explicit operator long(IPv4Address value) => NetworkToHostOrder((int)BitConverter.ToUInt32(value.GetAddressBytes(), 0)); /// /// Convert back to address from long /// /// public static explicit operator IPv4Address(long value) => new((uint)HostToNetworkOrder((int)value)); /// /// Add /// /// /// /// public static IPv4Address operator +(IPv4Address value, int x) => new((uint)((uint)value + x)); /// /// Subtract /// /// /// /// public static IPv4Address operator -(IPv4Address value, int x) => new((uint)((uint)value - x)); /// /// Increment by 1 /// /// /// public static IPv4Address operator ++(IPv4Address value) => value + 1; /// /// Decrement by 1 /// /// /// public static IPv4Address operator --(IPv4Address value) => value - 1; /// public static bool operator ==(IPv4Address left, IPv4Address right) => EqualityComparer.Default.Equals(left, right); /// public static bool operator !=(IPv4Address left, IPv4Address right) => !(left == right); /// public static bool operator <(IPv4Address left, IPAddress right) => left.CompareTo(right) < 0; /// public static bool operator <=(IPv4Address left, IPAddress right) => left.CompareTo(right) <= 0; /// public static bool operator >(IPv4Address left, IPAddress right) => left.CompareTo(right) > 0; /// public static bool operator >=(IPv4Address left, IPAddress right) => left.CompareTo(right) >= 0; /// public static bool operator <(IPv4Address left, IPv4Address right) => left.CompareTo(right) < 0; /// public static bool operator <=(IPv4Address left, IPv4Address right) => left.CompareTo(right) <= 0; /// public static bool operator >(IPv4Address left, IPv4Address right) => left.CompareTo(right) > 0; /// public static bool operator >=(IPv4Address left, IPv4Address right) => left.CompareTo(right) >= 0; /// public override int GetHashCode() { return base.GetHashCode(); } /// public override bool Equals(object? comparand) { return base.Equals(comparand); } /// public int CompareTo(IPv4Address? other) { if (other is null) { return int.MinValue; } return (int)(this - other); } /// public int CompareTo(IPAddress? other) { return CompareTo(other?.AsV4()); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Transport/Models/NetInterface.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Transport.Models { using System.Collections.Generic; using System.Net; using System.Net.NetworkInformation; /// /// Network interface model /// public sealed class NetInterface { /// /// Network interface name /// public string Name { get; } /// /// Address info /// public IPAddress UnicastAddress { get; } /// /// Subnet mask /// public IPAddress SubnetMask { get; } /// /// Mac address of interface /// public PhysicalAddress? MacAddress { get; } /// /// Gateway address /// public IPAddress? Gateway { get; } /// /// Domain name /// public string? DnsSuffix { get; } /// /// Name servers /// public IEnumerable DnsServers { get; } /// /// Create interface address /// /// /// /// public NetInterface(string name, IPAddress unicastAddress, IPAddress subnetMask) { Name = name; UnicastAddress = unicastAddress; SubnetMask = subnetMask; DnsServers = []; } /// /// Create context /// /// /// /// /// /// /// /// public NetInterface(string name, PhysicalAddress macAddress, IPAddress unicastAddress, IPAddress subnetMask, IPAddress gateway, string dnsSuffix, IEnumerable dnsServers) : this(name, unicastAddress, subnetMask) { Gateway = gateway; MacAddress = macAddress; DnsServers = dnsServers; DnsSuffix = dnsSuffix; } /// /// Equality /// /// /// public override bool Equals(object? obj) { return obj is NetInterface context && EqualityComparer.Default.Equals( MacAddress, context.MacAddress) && EqualityComparer.Default.Equals( UnicastAddress, context.UnicastAddress) && EqualityComparer.Default.Equals( SubnetMask, context.SubnetMask) && EqualityComparer.Default.Equals( Gateway, context.Gateway) && // EqualityComparer.Default.Equals( // DnsServers, context.DnsServers) && EqualityComparer.Default.Equals( DnsSuffix, context.DnsSuffix); } /// /// Get unique hash code /// /// public override int GetHashCode() { return System.HashCode.Combine(MacAddress, UnicastAddress, SubnetMask, Gateway, DnsSuffix); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Transport/Models/NetworkClass.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Transport.Models { using System; /// /// Network class flags for network selection /// [Flags] public enum NetworkClass { /// /// None class /// None = 0x0, /// /// Ethernet /// Wired = 0x1, /// /// Modem like, e.g. dsl, ppp /// Modem = 0x2, /// /// Mobile or 802.11 /// Wireless = 0x4, /// /// Tunnels /// Tunnel = 0x8, /// /// Any reasonable network /// All = Wired | Modem | Wireless | Tunnel } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Transport/Models/PortRange.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Transport.Models { using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; using System.Net; using System.Text; /// /// A port range /// public sealed class PortRange { /// /// Number of ports in range /// public int Count => _upper - _lower + 1; /// /// Create port range /// /// /// public PortRange(int lower, int upper) { _lower = Math.Max(IPEndPoint.MinPort, Math.Min(lower, upper)); _upper = Math.Min(IPEndPoint.MaxPort, Math.Max(lower, upper)); } /// /// Create port range /// /// public PortRange(int value) : this(value, value) { } /// /// Yield endpoints /// /// /// public IEnumerable GetEndpoints(IPAddress address) { for (var port = _lower; port <= _upper; port++) { yield return new IPEndPoint(address, port); } } /// public override bool Equals(object? obj) { if (obj is not PortRange range) { return false; } return _lower == range._lower && _upper == range._upper; } /// public static bool operator ==(PortRange range1, PortRange range2) => EqualityComparer.Default.Equals(range1, range2); /// public static bool operator !=(PortRange range1, PortRange range2) => !(range1 == range2); /// public override int GetHashCode() { return HashCode.Combine(_lower, _upper); } /// /// Tests contains value /// /// /// public bool Contains(int value) { return value >= _lower && value <= _upper; } /// /// Whether it overlaps with another port range /// /// /// public bool Overlaps(PortRange other) { return Contains(other._lower) || Contains(other._upper) || other.Contains(_lower) || other.Contains(_upper); } /// public override string ToString() { var sb = new StringBuilder(); AppendTo(sb); return sb.ToString(); } private readonly int _lower; private readonly int _upper; /// /// Parses a series of port ranges /// /// /// /// public static bool TryParse(string value, [NotNullWhen(true)] out IEnumerable? ranges) { try { ranges = Parse(value); return true; } catch { ranges = null; return false; } } /// /// Format a series of address ranges /// /// /// public static string Format(IEnumerable ranges) { var sb = new StringBuilder(); var first = true; foreach (var range in ranges) { if (!first) { sb.Append(';'); } first = false; range.AppendTo(sb); } return sb.ToString(); } /// /// Parse range /// /// /// public static IEnumerable Parse(string value) { var parsed = value.Split([';', ','], StringSplitOptions.RemoveEmptyEntries).Select(s => { var x = s.Split('-'); if (x.Length > 2) { throw new FormatException("Bad range format"); } var lows = x[0].Trim(); var highs = (x.Length == 2) ? x[1].Trim() : lows; var lowsInt = IPEndPoint.MinPort; var highsInt = IPEndPoint.MaxPort; if (lows != "*") { lowsInt = int.Parse(lows, CultureInfo.InvariantCulture); } if (highs != "*") { highsInt = int.Parse(highs, CultureInfo.InvariantCulture); } if (lowsInt < IPEndPoint.MinPort || highsInt > IPEndPoint.MaxPort || lowsInt > highsInt) { throw new ArgumentException("Port numbers are out of the range", nameof(value)); } return new PortRange(lowsInt, highsInt); }); return Merge(parsed); } /// /// Opc ua ports /// /// public static IEnumerable OpcUa { get { yield return new PortRange(4840, 4841); } } /// /// Well known opc ua ports /// /// public static IEnumerable WellKnown { get { yield return new PortRange(4840, 4841); yield return new PortRange(48000, 48100); yield return new PortRange(49320); yield return new PortRange(50000); yield return new PortRange(51200, 51300); yield return new PortRange(62222); // ... add more ports to well known range here } } /// /// All possible ports /// /// public static IEnumerable All { get { yield return new PortRange(IPEndPoint.MinPort, IPEndPoint.MaxPort); } } /// /// All IANA unassigned ports /// /// public static IEnumerable Unassigned { get { yield return new PortRange(4); yield return new PortRange(6); yield return new PortRange(8); yield return new PortRange(10); yield return new PortRange(12); yield return new PortRange(14); yield return new PortRange(15); yield return new PortRange(16); yield return new PortRange(26); yield return new PortRange(28); yield return new PortRange(30); yield return new PortRange(32); yield return new PortRange(34); yield return new PortRange(36); yield return new PortRange(40); yield return new PortRange(60); yield return new PortRange(81); yield return new PortRange(100); yield return new PortRange(114); yield return new PortRange(258); yield return new PortRange(272, 279); yield return new PortRange(285); yield return new PortRange(288, 307); yield return new PortRange(325, 332); yield return new PortRange(334, 343); yield return new PortRange(703); yield return new PortRange(708); yield return new PortRange(717, 728); yield return new PortRange(732, 740); yield return new PortRange(743); yield return new PortRange(745, 746); yield return new PortRange(755, 757); yield return new PortRange(766); yield return new PortRange(768); yield return new PortRange(778, 779); yield return new PortRange(781, 785); yield return new PortRange(786); yield return new PortRange(787); yield return new PortRange(788, 799); yield return new PortRange(803, 809); yield return new PortRange(811, 827); yield return new PortRange(834, 846); yield return new PortRange(849, 852); yield return new PortRange(855, 859); yield return new PortRange(863, 872); yield return new PortRange(874, 885); yield return new PortRange(889, 899); yield return new PortRange(904, 909); yield return new PortRange(914, 952); yield return new PortRange(954, 988); yield return new PortRange(1002, 1007); yield return new PortRange(1009); yield return new PortRange(1491); yield return new PortRange(1895); yield return new PortRange(1895); yield return new PortRange(2194, 2196); yield return new PortRange(2259); yield return new PortRange(2369); yield return new PortRange(2378); yield return new PortRange(2693); yield return new PortRange(2693); yield return new PortRange(2794); yield return new PortRange(2825); yield return new PortRange(2873); yield return new PortRange(2925); yield return new PortRange(2999); yield return new PortRange(2999); yield return new PortRange(3092); yield return new PortRange(3126); yield return new PortRange(3301); yield return new PortRange(3546); yield return new PortRange(3694); yield return new PortRange(3994); yield return new PortRange(4048); yield return new PortRange(4144); yield return new PortRange(4194, 4196); yield return new PortRange(4198); yield return new PortRange(4315); yield return new PortRange(4317, 4319); yield return new PortRange(4332); yield return new PortRange(4337, 4339); yield return new PortRange(4363, 4365); yield return new PortRange(4367); yield return new PortRange(4380, 4388); yield return new PortRange(4397, 4399); yield return new PortRange(4424); yield return new PortRange(4434, 4440); yield return new PortRange(4459, 4483); yield return new PortRange(4489, 4499); yield return new PortRange(4501); yield return new PortRange(4503, 4533); yield return new PortRange(4539, 4544); yield return new PortRange(4560, 4562); yield return new PortRange(4564, 4565); yield return new PortRange(4571, 4572); yield return new PortRange(4574, 4589); yield return new PortRange(4606, 4620); yield return new PortRange(4622, 4657); yield return new PortRange(4693, 4699); yield return new PortRange(4705, 4710); yield return new PortRange(4712, 4724); yield return new PortRange(4734, 4736); yield return new PortRange(4748, 4748); yield return new PortRange(4757, 4773); yield return new PortRange(4775, 4783); yield return new PortRange(4792, 4799); yield return new PortRange(4805, 4826); yield return new PortRange(4828, 4836); yield return new PortRange(4852, 4866); yield return new PortRange(4872, 4875); yield return new PortRange(4886, 4893); yield return new PortRange(4895, 4898); yield return new PortRange(4903, 4911); yield return new PortRange(4916, 4935); yield return new PortRange(4938, 4939); yield return new PortRange(4943, 4948); yield return new PortRange(4954, 4968); yield return new PortRange(4972, 4979); yield return new PortRange(4981, 4982); yield return new PortRange(4983); yield return new PortRange(4992, 4998); yield return new PortRange(5016, 5019); yield return new PortRange(5035, 5041); yield return new PortRange(5076, 5077); yield return new PortRange(5088, 5089); yield return new PortRange(5095, 5098); yield return new PortRange(5108, 5110); yield return new PortRange(5113); yield return new PortRange(5118, 5119); yield return new PortRange(5121, 5132); yield return new PortRange(5138, 5144); yield return new PortRange(5147, 5149); yield return new PortRange(5158, 5160); yield return new PortRange(5169, 5171); yield return new PortRange(5173, 5189); yield return new PortRange(5198, 5199); yield return new PortRange(5204, 5208); yield return new PortRange(5210, 5214); yield return new PortRange(5216, 5220); yield return new PortRange(5238, 5244); yield return new PortRange(5255, 5263); yield return new PortRange(5266, 5268); yield return new PortRange(5273, 5279); yield return new PortRange(5283, 5297); yield return new PortRange(5311); yield return new PortRange(5316); yield return new PortRange(5319); yield return new PortRange(5322, 5342); yield return new PortRange(5345, 5348); yield return new PortRange(5365, 5396); yield return new PortRange(5438, 5442); yield return new PortRange(5444); yield return new PortRange(5446, 5449); yield return new PortRange(5451, 5452); yield return new PortRange(5457, 5460); yield return new PortRange(5466, 5469); yield return new PortRange(5476, 5499); yield return new PortRange(5508, 5549); yield return new PortRange(5551, 5552); yield return new PortRange(5558, 5564); yield return new PortRange(5570, 5572); yield return new PortRange(5576, 5578); yield return new PortRange(5587, 5596); yield return new PortRange(5606, 5617); yield return new PortRange(5619, 5626); yield return new PortRange(5640, 5645); yield return new PortRange(5647, 5665); yield return new PortRange(5667, 5669); yield return new PortRange(5685, 5686); yield return new PortRange(5690, 5692); yield return new PortRange(5694, 5695); yield return new PortRange(5697, 5699); yield return new PortRange(5701, 5704); yield return new PortRange(5706, 5712); yield return new PortRange(5731, 5740); yield return new PortRange(5749); yield return new PortRange(5751, 5754); yield return new PortRange(5756); yield return new PortRange(5758, 5765); yield return new PortRange(5772, 5776); yield return new PortRange(5778, 5779); yield return new PortRange(5788, 5792); yield return new PortRange(5795, 5812); yield return new PortRange(5815, 5840); yield return new PortRange(5843, 5858); yield return new PortRange(5860, 5862); yield return new PortRange(5864, 5867); yield return new PortRange(5869, 5882); yield return new PortRange(5884, 5899); yield return new PortRange(5901, 5909); yield return new PortRange(5914, 5962); yield return new PortRange(5964, 5967); yield return new PortRange(5970, 5983); yield return new PortRange(5994, 5998); yield return new PortRange(6067); yield return new PortRange(6078, 6079); yield return new PortRange(6089, 6098); yield return new PortRange(6119, 6120); yield return new PortRange(6125, 6129); yield return new PortRange(6131, 6132); yield return new PortRange(6134, 6139); yield return new PortRange(6150, 6158); yield return new PortRange(6164, 6199); yield return new PortRange(6202, 6208); yield return new PortRange(6210, 6221); yield return new PortRange(6223, 6240); yield return new PortRange(6245, 6250); yield return new PortRange(6254, 6266); yield return new PortRange(6270, 6299); yield return new PortRange(6302, 6305); yield return new PortRange(6307, 6314); yield return new PortRange(6318, 6319); yield return new PortRange(6323); yield return new PortRange(6327, 6342); yield return new PortRange(6345, 6345); yield return new PortRange(6348, 6349); yield return new PortRange(6351, 6354); yield return new PortRange(6356, 6359); yield return new PortRange(6361, 6362); yield return new PortRange(6364, 6369); yield return new PortRange(6371, 6378); yield return new PortRange(6380, 6381); yield return new PortRange(6383, 6388); yield return new PortRange(6391, 6399); yield return new PortRange(6411, 6416); yield return new PortRange(6422, 6431); yield return new PortRange(6433, 6441); yield return new PortRange(6447, 6454); yield return new PortRange(6457, 6463); yield return new PortRange(6465, 6470); yield return new PortRange(6472, 6479); yield return new PortRange(6490, 6499); yield return new PortRange(6504); yield return new PortRange(6512, 6512); yield return new PortRange(6516, 6542); yield return new PortRange(6545, 6546); yield return new PortRange(6552, 6557); yield return new PortRange(6559, 6565); yield return new PortRange(6569, 6578); yield return new PortRange(6584, 6587); yield return new PortRange(6588); yield return new PortRange(6589, 6599); yield return new PortRange(6603, 6618); yield return new PortRange(6630); yield return new PortRange(6631); yield return new PortRange(6637, 6639); yield return new PortRange(6641, 6652); yield return new PortRange(6654); yield return new PortRange(6658, 6664); yield return new PortRange(6674, 6677); yield return new PortRange(6680, 6686); yield return new PortRange(6691, 6695); yield return new PortRange(6698, 6699); yield return new PortRange(6700); yield return new PortRange(6701); yield return new PortRange(6702); yield return new PortRange(6707, 6713); yield return new PortRange(6717, 6766); yield return new PortRange(6772, 6776); yield return new PortRange(6779, 6783); yield return new PortRange(6792, 6800); yield return new PortRange(6802, 6816); yield return new PortRange(6818, 6830); yield return new PortRange(6832, 6840); yield return new PortRange(6843, 6849); yield return new PortRange(6851, 6867); yield return new PortRange(6869, 6887); yield return new PortRange(6889); yield return new PortRange(6902, 6934); yield return new PortRange(6937, 6945); yield return new PortRange(6947, 6950); yield return new PortRange(6952, 6960); yield return new PortRange(6967, 6968); yield return new PortRange(6971, 6996); yield return new PortRange(7027, 7029); yield return new PortRange(7032, 7039); yield return new PortRange(7041, 7069); yield return new PortRange(7074, 7079); yield return new PortRange(7081, 7087); yield return new PortRange(7089, 7094); yield return new PortRange(7096, 7098); yield return new PortRange(7102, 7106); yield return new PortRange(7108, 7116); yield return new PortRange(7118, 7120); yield return new PortRange(7122, 7127); yield return new PortRange(7130, 7160); yield return new PortRange(7175, 7180); yield return new PortRange(7182, 7199); yield return new PortRange(7203, 7214); yield return new PortRange(7217, 7226); yield return new PortRange(7230, 7234); yield return new PortRange(7238, 7243); yield return new PortRange(7245, 7261); yield return new PortRange(7263, 7271); yield return new PortRange(7284, 7299); yield return new PortRange(7360, 7364); yield return new PortRange(7366, 7390); yield return new PortRange(7396); yield return new PortRange(7398, 7399); yield return new PortRange(7403, 7409); yield return new PortRange(7412, 7419); yield return new PortRange(7422, 7425); yield return new PortRange(7432, 7436); yield return new PortRange(7438, 7442); yield return new PortRange(7444, 7470); yield return new PortRange(7472); yield return new PortRange(7475, 7477); yield return new PortRange(7479, 7490); yield return new PortRange(7492, 7499); yield return new PortRange(7502, 7507); yield return new PortRange(7512, 7541); yield return new PortRange(7552, 7559); yield return new PortRange(7561, 7562); yield return new PortRange(7564, 7565); yield return new PortRange(7567, 7568); yield return new PortRange(7571, 7573); yield return new PortRange(7575, 7587); yield return new PortRange(7589, 7605); yield return new PortRange(7607, 7623); yield return new PortRange(7625); yield return new PortRange(7632); yield return new PortRange(7634, 7647); yield return new PortRange(7649, 7662); yield return new PortRange(7664, 7671); yield return new PortRange(7678, 7679); yield return new PortRange(7681, 7682); yield return new PortRange(7684, 7686); yield return new PortRange(7688); yield return new PortRange(7690, 7696); yield return new PortRange(7698, 7699); yield return new PortRange(7702, 7706); yield return new PortRange(7709, 7719); yield return new PortRange(7721, 7723); yield return new PortRange(7729, 7733); yield return new PortRange(7735, 7737); yield return new PortRange(7739, 7740); yield return new PortRange(7745, 7746); yield return new PortRange(7748, 7776); yield return new PortRange(7776); yield return new PortRange(7780); yield return new PortRange(7782, 7783); yield return new PortRange(7785); yield return new PortRange(7788); yield return new PortRange(7790, 7793); yield return new PortRange(7795, 7796); yield return new PortRange(7803, 7809); yield return new PortRange(7811, 7844); yield return new PortRange(7848, 7868); yield return new PortRange(7873, 7877); yield return new PortRange(7879); yield return new PortRange(7881, 7886); yield return new PortRange(7888, 7899); yield return new PortRange(7904, 7912); yield return new PortRange(7914, 7931); yield return new PortRange(7934, 7961); yield return new PortRange(7963, 7966); yield return new PortRange(7968, 7978); yield return new PortRange(7983, 7997); yield return new PortRange(8009, 8018); yield return new PortRange(8023, 8024); yield return new PortRange(8027, 8031); yield return new PortRange(8035, 8039); yield return new PortRange(8045, 8050); yield return new PortRange(8061, 8065); yield return new PortRange(8068, 8069); yield return new PortRange(8071, 8073); yield return new PortRange(8075, 8076); yield return new PortRange(8078, 8079); yield return new PortRange(8084, 8085); yield return new PortRange(8089); yield return new PortRange(8092, 8096); yield return new PortRange(8098, 8099); yield return new PortRange(8103, 8114); yield return new PortRange(8119, 8120); yield return new PortRange(8123, 8127); yield return new PortRange(8133, 8139); yield return new PortRange(8141, 8147); yield return new PortRange(8150, 8152); yield return new PortRange(8154, 8159); yield return new PortRange(8163, 8180); yield return new PortRange(8185, 8189); yield return new PortRange(8193); yield return new PortRange(8196, 8198); yield return new PortRange(8203, 8203); yield return new PortRange(8209, 8229); yield return new PortRange(8233, 8242); yield return new PortRange(8244, 8269); yield return new PortRange(8271, 8275); yield return new PortRange(8277, 8279); yield return new PortRange(8281); yield return new PortRange(8283, 8291); yield return new PortRange(8295, 8299); yield return new PortRange(8302, 8312); yield return new PortRange(8314, 8319); yield return new PortRange(8323, 8350); yield return new PortRange(8352, 8375); yield return new PortRange(8381, 8382); yield return new PortRange(8385, 8399); yield return new PortRange(8406, 8414); yield return new PortRange(8418, 8422); yield return new PortRange(8424, 8441); yield return new PortRange(8446, 8449); yield return new PortRange(8451, 8456); yield return new PortRange(8458, 8469); yield return new PortRange(8475, 8499); yield return new PortRange(8504, 8553); yield return new PortRange(8556, 8566); yield return new PortRange(8568, 8599); yield return new PortRange(8601, 8608); yield return new PortRange(8616, 8664); yield return new PortRange(8667, 8674); yield return new PortRange(8676, 8685); yield return new PortRange(8687); yield return new PortRange(8689, 8698); yield return new PortRange(8700, 8710); yield return new PortRange(8712, 8731); yield return new PortRange(8734, 8749); yield return new PortRange(8751, 8762); yield return new PortRange(8767, 8769); yield return new PortRange(8771, 8777); yield return new PortRange(8779, 8785); yield return new PortRange(8788, 8792); yield return new PortRange(8794, 8799); yield return new PortRange(8801, 8803); yield return new PortRange(8806, 8807); yield return new PortRange(8809, 8872); yield return new PortRange(8874, 8879); yield return new PortRange(8882); yield return new PortRange(8884, 8887); yield return new PortRange(8895, 8898); yield return new PortRange(8902, 8909); yield return new PortRange(8914, 8936); yield return new PortRange(8938, 8952); yield return new PortRange(8955, 8979); yield return new PortRange(8982, 8988); yield return new PortRange(8992, 8996); yield return new PortRange(9003, 9004); yield return new PortRange(9011, 9019); yield return new PortRange(9027, 9049); yield return new PortRange(9052, 9059); yield return new PortRange(9061, 9079); yield return new PortRange(9094, 9099); yield return new PortRange(9108, 9118); yield return new PortRange(9120, 9121); yield return new PortRange(9124, 9130); yield return new PortRange(9132, 9159); yield return new PortRange(9165, 9190); yield return new PortRange(9192, 9199); yield return new PortRange(9218, 9221); yield return new PortRange(9223, 9254); yield return new PortRange(9256, 9276); yield return new PortRange(9288, 9291); yield return new PortRange(9296, 9299); yield return new PortRange(9301, 9305); yield return new PortRange(9307, 9311); yield return new PortRange(9313, 9317); yield return new PortRange(9319, 9320); yield return new PortRange(9322, 9342); yield return new PortRange(9347, 9373); yield return new PortRange(9375, 9379); yield return new PortRange(9381, 9386); yield return new PortRange(9391, 9395); yield return new PortRange(9398, 9399); yield return new PortRange(9403, 9417); yield return new PortRange(9419, 9442); yield return new PortRange(9446, 9449); yield return new PortRange(9451, 9499); yield return new PortRange(9501, 9521); yield return new PortRange(9523, 9534); yield return new PortRange(9537, 9554); yield return new PortRange(9556, 9591); yield return new PortRange(9601, 9611); yield return new PortRange(9613); yield return new PortRange(9615); yield return new PortRange(9619, 9627); yield return new PortRange(9633, 9639); yield return new PortRange(9641, 9665); yield return new PortRange(9669, 9693); yield return new PortRange(9696, 9699); yield return new PortRange(9701, 9746); yield return new PortRange(9748, 9749); yield return new PortRange(9751, 9752); yield return new PortRange(9754, 9761); yield return new PortRange(9763, 9799); yield return new PortRange(9803, 9874); yield return new PortRange(9877); yield return new PortRange(9879, 9887); yield return new PortRange(9890, 9897); yield return new PortRange(9904, 9908); yield return new PortRange(9910); yield return new PortRange(9912, 9924); yield return new PortRange(9926, 9949); yield return new PortRange(9957, 9965); yield return new PortRange(9967, 9977); yield return new PortRange(9980); yield return new PortRange(9982, 9986); yield return new PortRange(9989, 9989); yield return new PortRange(10011, 10019); yield return new PortRange(10021, 10049); yield return new PortRange(10052, 10054); yield return new PortRange(10056, 10079); yield return new PortRange(10082, 10099); yield return new PortRange(10105, 10106); yield return new PortRange(10108, 10109); yield return new PortRange(10112); yield return new PortRange(10118, 10124); yield return new PortRange(10126, 10127); yield return new PortRange(10130, 10159); yield return new PortRange(10163, 10199); yield return new PortRange(10202, 10251); yield return new PortRange(10254, 10259); yield return new PortRange(10262, 10287); yield return new PortRange(10289, 10320); yield return new PortRange(10322, 10438); yield return new PortRange(10440, 10499); yield return new PortRange(10501, 10539); yield return new PortRange(10545, 10547); yield return new PortRange(10549, 10630); yield return new PortRange(10632, 10799); yield return new PortRange(10801, 10804); yield return new PortRange(10806, 10808); yield return new PortRange(10811, 10859); yield return new PortRange(10861, 10879); yield return new PortRange(10881, 10932); yield return new PortRange(10934, 10989); yield return new PortRange(10991, 10999); yield return new PortRange(11002, 11022); yield return new PortRange(11024, 11094); yield return new PortRange(11096, 11102); yield return new PortRange(11107); yield return new PortRange(11113, 11160); yield return new PortRange(11166, 11170); yield return new PortRange(11176, 11200); yield return new PortRange(11203, 11207); yield return new PortRange(11209, 11210); yield return new PortRange(11212, 11318); yield return new PortRange(11322, 11366); yield return new PortRange(11368, 11370); yield return new PortRange(11372, 11429); yield return new PortRange(11431, 11488); yield return new PortRange(11490, 11599); yield return new PortRange(11601, 11622); yield return new PortRange(11624, 11719); yield return new PortRange(11721, 11722); yield return new PortRange(11724, 11750); yield return new PortRange(11752, 11795); yield return new PortRange(11797, 11875); yield return new PortRange(11878, 11966); yield return new PortRange(11968, 11996); yield return new PortRange(12011); yield return new PortRange(12014, 12108); yield return new PortRange(12110, 12120); yield return new PortRange(12122, 12167); yield return new PortRange(12169, 12171); yield return new PortRange(12173, 12299); yield return new PortRange(12301); yield return new PortRange(12303, 12320); yield return new PortRange(12323, 12344); yield return new PortRange(12346, 12752); yield return new PortRange(12754, 12864); yield return new PortRange(12866, 13159); yield return new PortRange(13161, 13215); yield return new PortRange(13219, 13222); yield return new PortRange(13225, 13399); yield return new PortRange(13401, 13719); yield return new PortRange(13723); yield return new PortRange(13725, 13781); yield return new PortRange(13784); yield return new PortRange(13787, 13817); yield return new PortRange(13824, 13893); yield return new PortRange(13895, 13928); yield return new PortRange(13931, 13999); yield return new PortRange(14003, 14032); yield return new PortRange(14035, 14140); yield return new PortRange(14144); yield return new PortRange(14146, 14148); yield return new PortRange(14151, 14153); yield return new PortRange(14155, 14249); yield return new PortRange(14251, 14413); yield return new PortRange(14415, 14499); yield return new PortRange(14501, 14935); yield return new PortRange(14938, 14999); yield return new PortRange(15001); yield return new PortRange(15003, 15117); yield return new PortRange(15119, 15344); yield return new PortRange(15346, 15362); yield return new PortRange(15364, 15554); yield return new PortRange(15556, 15659); yield return new PortRange(15661, 15739); yield return new PortRange(15741, 15997); yield return new PortRange(16004, 16019); yield return new PortRange(16022, 16160); yield return new PortRange(16163, 16308); yield return new PortRange(16312, 16359); yield return new PortRange(16362, 16366); yield return new PortRange(16369, 16383); yield return new PortRange(16386, 16618); yield return new PortRange(16620, 16664); yield return new PortRange(16667, 16788); yield return new PortRange(16790, 16899); yield return new PortRange(16901, 16949); yield return new PortRange(16951, 16990); yield return new PortRange(16996, 17006); yield return new PortRange(17008, 17183); yield return new PortRange(17186, 17218); yield return new PortRange(17226, 17233); yield return new PortRange(17236, 17499); yield return new PortRange(17501, 17554); yield return new PortRange(17556, 17728); yield return new PortRange(17730, 17753); yield return new PortRange(17757, 17776); yield return new PortRange(17778, 17999); yield return new PortRange(18001, 18103); yield return new PortRange(18105, 18135); yield return new PortRange(18137, 18180); yield return new PortRange(18188, 18240); yield return new PortRange(18244, 18261); yield return new PortRange(18263, 18462); yield return new PortRange(18464, 18633); yield return new PortRange(18636, 18667); yield return new PortRange(18669, 18768); yield return new PortRange(18770, 18880); yield return new PortRange(18882, 18887); yield return new PortRange(18889, 18999); yield return new PortRange(19001, 19006); yield return new PortRange(19008, 19019); yield return new PortRange(19021, 19190); yield return new PortRange(19192, 19193); yield return new PortRange(19195, 19219); yield return new PortRange(19221, 19282); yield return new PortRange(19284, 19314); yield return new PortRange(19316, 19397); yield return new PortRange(19399, 19409); yield return new PortRange(19413, 19538); yield return new PortRange(19542, 19787); yield return new PortRange(19789, 19997); yield return new PortRange(20004); yield return new PortRange(20006, 20011); yield return new PortRange(20015, 20033); yield return new PortRange(20035, 20045); yield return new PortRange(20047, 20047); yield return new PortRange(20050, 20056); yield return new PortRange(20058, 20166); yield return new PortRange(20168, 20201); yield return new PortRange(20203, 20221); yield return new PortRange(20223, 20479); yield return new PortRange(20481, 20669); yield return new PortRange(20671, 20998); yield return new PortRange(21001, 21009); yield return new PortRange(21011, 21211); yield return new PortRange(21213, 21220); yield return new PortRange(21222, 21552); yield return new PortRange(21555, 21589); yield return new PortRange(21591, 21799); yield return new PortRange(21801, 21844); yield return new PortRange(21850, 21999); yield return new PortRange(22006, 22124); yield return new PortRange(22126, 22127); yield return new PortRange(22129, 22221); yield return new PortRange(22223, 22272); yield return new PortRange(22274, 22304); yield return new PortRange(22306, 22334); yield return new PortRange(22336, 22342); yield return new PortRange(22344, 22346); yield return new PortRange(22348, 22349); yield return new PortRange(22352, 22536); yield return new PortRange(22538, 22554); yield return new PortRange(22556, 22762); yield return new PortRange(22764, 22799); yield return new PortRange(22801, 22950); yield return new PortRange(22952, 22999); yield return new PortRange(23006, 23052); yield return new PortRange(23054, 23271); yield return new PortRange(23273, 23293); yield return new PortRange(23295, 23332); yield return new PortRange(23334, 23399); yield return new PortRange(23403, 23455); yield return new PortRange(23458, 23545); yield return new PortRange(23547, 23999); yield return new PortRange(24007, 24241); yield return new PortRange(24243, 24248); yield return new PortRange(24250, 24320); yield return new PortRange(24323, 24385); yield return new PortRange(24387, 24464); yield return new PortRange(24466, 24553); yield return new PortRange(24555, 24576); yield return new PortRange(24578, 24665); yield return new PortRange(24667, 24675); yield return new PortRange(24679); yield return new PortRange(24681, 24753); yield return new PortRange(24755, 24849); yield return new PortRange(24851, 24921); yield return new PortRange(24923, 24999); yield return new PortRange(25010, 25470); yield return new PortRange(25472, 25575); yield return new PortRange(25577, 25603); yield return new PortRange(25605, 25792); yield return new PortRange(25794, 25899); yield return new PortRange(25904, 25953); yield return new PortRange(25956, 25999); yield return new PortRange(26001, 26132); yield return new PortRange(26134, 26207); yield return new PortRange(26209, 26256); yield return new PortRange(26258, 26259); yield return new PortRange(26265, 26485); yield return new PortRange(26488); yield return new PortRange(26490, 26999); yield return new PortRange(27010, 27344); yield return new PortRange(27346, 27441); yield return new PortRange(27443, 27503); yield return new PortRange(27505, 27781); yield return new PortRange(27783, 27875); yield return new PortRange(27877, 27998); yield return new PortRange(28002, 28118); yield return new PortRange(28120, 28199); yield return new PortRange(28201, 28239); yield return new PortRange(28241, 28588); yield return new PortRange(28590, 29117); yield return new PortRange(29119, 29166); yield return new PortRange(29170, 29998); yield return new PortRange(30005, 30099); yield return new PortRange(30101, 30259); yield return new PortRange(30261, 30399); yield return new PortRange(30401, 30831); yield return new PortRange(30833, 30998); yield return new PortRange(31000, 31015); yield return new PortRange(31017, 31019); yield return new PortRange(31021, 31028); yield return new PortRange(31030, 31399); yield return new PortRange(31401, 31415); yield return new PortRange(31417, 31456); yield return new PortRange(31458, 31619); yield return new PortRange(31621, 31684); yield return new PortRange(31686, 31764); yield return new PortRange(31766, 31947); yield return new PortRange(31950, 32033); yield return new PortRange(32035, 32248); yield return new PortRange(32250, 32399); yield return new PortRange(32401, 32482); yield return new PortRange(32484, 32634); yield return new PortRange(32637, 32766); yield return new PortRange(32778, 32800); yield return new PortRange(32802, 32810); yield return new PortRange(32812, 32895); yield return new PortRange(32897, 33059); yield return new PortRange(33061, 33122); yield return new PortRange(33124, 33330); yield return new PortRange(33332); yield return new PortRange(33335, 33433); yield return new PortRange(33436, 33655); yield return new PortRange(33657, 34248); yield return new PortRange(34250, 34377); yield return new PortRange(34380, 34566); yield return new PortRange(34568, 34961); yield return new PortRange(34965, 34979); yield return new PortRange(34981, 34999); yield return new PortRange(35007, 35099); yield return new PortRange(35101, 35353); yield return new PortRange(35358, 36000); yield return new PortRange(36002, 36410); yield return new PortRange(36413, 36421); yield return new PortRange(36425, 36442); yield return new PortRange(36445, 36461); yield return new PortRange(36463, 36523); yield return new PortRange(36525, 36601); yield return new PortRange(36603, 36699); yield return new PortRange(36701, 36864); yield return new PortRange(36866, 37474); yield return new PortRange(37476, 37482); yield return new PortRange(37484, 37600); yield return new PortRange(37602, 37653); yield return new PortRange(37655, 37999); yield return new PortRange(38003, 38200); yield return new PortRange(38204, 38411); yield return new PortRange(38413, 38421); yield return new PortRange(38423, 38471); yield return new PortRange(38473, 38799); yield return new PortRange(38801, 38864); yield return new PortRange(38866, 39680); yield return new PortRange(39682, 39999); yield return new PortRange(40001, 40022); yield return new PortRange(40024, 40403); yield return new PortRange(40405, 40840); yield return new PortRange(40844, 40852); yield return new PortRange(40854, 41110); yield return new PortRange(41112, 41120); yield return new PortRange(41122, 41229); yield return new PortRange(41231, 41793); yield return new PortRange(41798, 42507); yield return new PortRange(42511, 42999); yield return new PortRange(43001, 43187); yield return new PortRange(43192, 43209); yield return new PortRange(43211, 43437); yield return new PortRange(43442, 44122); yield return new PortRange(43124, 44320); yield return new PortRange(44323); yield return new PortRange(44324, 44443); yield return new PortRange(44445, 44543); yield return new PortRange(44545, 44552); yield return new PortRange(44554, 44599); yield return new PortRange(44601, 44817); yield return new PortRange(44819, 44899); yield return new PortRange(44901, 44999); yield return new PortRange(45003, 45044); yield return new PortRange(45046, 45053); yield return new PortRange(45055, 45513); yield return new PortRange(45515, 45677); yield return new PortRange(45679, 45823); yield return new PortRange(45826, 45965); yield return new PortRange(45967, 46335); yield return new PortRange(46337, 46997); yield return new PortRange(47002, 47099); yield return new PortRange(47101, 47556); yield return new PortRange(47558, 47623); yield return new PortRange(47625, 47805); yield return new PortRange(47807); yield return new PortRange(47810, 47999); yield return new PortRange(48006, 48047); yield return new PortRange(48051, 48127); yield return new PortRange(48130, 48555); yield return new PortRange(48557, 48618); yield return new PortRange(48620, 48652); yield return new PortRange(48654, 48999); yield return new PortRange(49002, IPEndPoint.MaxPort); } } /// /// Append to builder /// /// private void AppendTo(StringBuilder sb) { if (IPEndPoint.MinPort == _lower) { if (_upper == IPEndPoint.MaxPort) { sb.Append('*'); return; } sb.Append('0'); } else { sb.Append(_lower); } if (_lower == _upper) { return; } sb.Append('-'); if (IPEndPoint.MaxPort == _upper) { sb.Append('*'); } else { sb.Append(_upper); } } /// /// Merge overlapping ranges /// /// /// private static IEnumerable Merge(IEnumerable ranges) { var results = new Stack(); if (ranges != null) { foreach (var range in ranges.OrderBy(k => k._lower)) { if (results.Count == 0) { results.Push(range); } else { var top = results.Peek(); if (top.Overlaps(range)) { var union = new PortRange( top._lower < range._lower ? top._lower : range._lower, top._upper > range._upper ? top._upper : range._upper); results.Pop(); results.Push(union); } else { results.Push(range); } } } } return results.Reverse(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Transport/Probe/ServerProbe.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Transport.Probe { using Azure.IIoT.OpcUa.Publisher.Stack.Transport; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Bindings; using System; using System.IO; using System.Net; using System.Net.Sockets; using System.Text; /// /// Opc ua secure channel probe factory /// internal sealed class ServerProbe : IPortProbe { /// /// Operation timeout /// public TimeSpan Timeout { get; set; } = TimeSpan.FromSeconds(5); /// /// Create server probe /// /// public ServerProbe(ILogger logger) { _logger = logger; } /// /// Create probe /// /// public IAsyncProbe Create() { return new ServerHelloAsyncProbe(_logger, (int)Timeout.TotalMilliseconds); } /// /// Async probe that sends a hello and validates the returned ack. /// private sealed class ServerHelloAsyncProbe : IAsyncProbe { /// /// Create opc ua server probe /// /// /// public ServerHelloAsyncProbe(ILogger logger, int timeout) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _timeout = timeout; _buffer = new byte[256]; } /// /// Reset probe /// public bool Reset() { var closed = false; if (_socket != null) { // If connected, close will cause a call to the completion port closed = _socket.Connected; _socket.SafeDispose(); _socket = null; } _state = State.BeginProbe; return closed; } /// /// Called whenever socket operation completes /// /// /// /// /// /// true if completed, false to be called again /// public bool OnComplete(int index, SocketAsyncEventArgs arg, out bool ok, out int timeout) { ok = false; timeout = _timeout; if (arg.SocketError != SocketError.Success) { _logger.ProbeNoOpcServer(index, _socket?.RemoteEndPoint?.ToString(), arg.SocketError); _state = State.BeginProbe; return true; } while (true) { switch (_state) { case State.BeginProbe: if (arg.ConnectSocket == null) { _logger.ProbeNoConnectedSocket(index); return true; } _socket = arg.ConnectSocket; var ep = _socket.RemoteEndPoint?.TryResolve(); using (var ostrm = new MemoryStream(_buffer, 0, _buffer.Length)) using (var encoder = new BinaryEncoder(ostrm, ServiceMessageContext.GlobalContext, true)) { encoder.WriteUInt32(null, TcpMessageType.Hello); encoder.WriteUInt32(null, 0); encoder.WriteUInt32(null, 0); // ProtocolVersion encoder.WriteUInt32(null, TcpMessageLimits.DefaultMaxMessageSize); encoder.WriteUInt32(null, TcpMessageLimits.DefaultMaxMessageSize); encoder.WriteUInt32(null, TcpMessageLimits.DefaultMaxMessageSize); encoder.WriteUInt32(null, TcpMessageLimits.DefaultMaxMessageSize); encoder.WriteByteString(null, Encoding.UTF8.GetBytes("opc.tcp://" + ep)); _size = encoder.Close(); } _buffer[4] = (byte)(_size & 0x000000FF); _buffer[5] = (byte)((_size & 0x0000FF00) >> 8); _buffer[6] = (byte)((_size & 0x00FF0000) >> 16); _buffer[7] = (byte)((_size & 0xFF000000) >> 24); arg.SetBuffer(_buffer, 0, _size); _len = 0; _logger.ProbeStart(index, "opc.tcp://" + ep, _socket.RemoteEndPoint?.ToString()); _state = State.SendHello; if (!_socket.SendAsync(arg)) { break; } return false; case State.SendHello: _len += arg.Count; System.Diagnostics.Debug.Assert(_socket != null); if (_len >= _size) { _len = 0; _size = TcpMessageLimits.MessageTypeAndSize; _state = State.ReceiveSize; arg.SetBuffer(0, _size); // Start read size if (!_socket.ReceiveAsync(arg)) { break; } return false; } // Continue to send reset arg.SetBuffer(_len, _size - _len); if (!_socket.SendAsync(arg)) { break; } return false; case State.ReceiveSize: _len += arg.Count; System.Diagnostics.Debug.Assert(_socket != null); if (_len >= _size) { var type = BitConverter.ToUInt32(_buffer, 0); if (type != TcpMessageType.Acknowledge) { if (TcpMessageType.IsValid(type)) { _logger.ProbeReturnedWrongType(index, _socket.RemoteEndPoint?.ToString(), type); } else { _logger.ProbeReturnedInvalidType(index, _socket.RemoteEndPoint?.ToString(), type); } _state = State.BeginProbe; return true; } _size = (int)BitConverter.ToUInt32(_buffer, 4); if (_size > _buffer.Length) { _logger.ProbeReturnedInvalidLength(index, _socket.RemoteEndPoint?.ToString(), _size); _state = State.BeginProbe; return true; } _len = 0; // Start receive message _state = State.ReceiveAck; } // Continue to read rest of type and size arg.SetBuffer(_len, _size - _len); if (!_socket.ReceiveAsync(arg)) { break; } return false; case State.ReceiveAck: _len += arg.Count; System.Diagnostics.Debug.Assert(_socket != null); if (_len >= _size) { _state = State.BeginProbe; // Validate message using (var istrm = new MemoryStream(_buffer, 0, _size)) using (var decoder = new BinaryDecoder(istrm, ServiceMessageContext.GlobalContext)) { var protocolVersion = decoder.ReadUInt32(null); var sendBufferSize = (int)decoder.ReadUInt32(null); var receiveBufferSize = (int)decoder.ReadUInt32(null); var maxMessageSize = (int)decoder.ReadUInt32(null); var maxChunkCount = (int)decoder.ReadUInt32(null); _logger.ProbeFoundOpcUaServer(index, _socket.RemoteEndPoint?.ToString(), protocolVersion); if (sendBufferSize < TcpMessageLimits.MinBufferSize || receiveBufferSize < TcpMessageLimits.MinBufferSize) { _logger.ProbeBadSizeValue(index, sendBufferSize, receiveBufferSize, _socket.RemoteEndPoint?.ToString()); } } ok = true; return true; } // Continue to read rest arg.SetBuffer(_len, _size - _len); if (!_socket.ReceiveAsync(arg)) { break; } return false; default: throw new InvalidProgramException("Bad state"); } } } /// /// Dispose handler /// public void Dispose() { Reset(); } private enum State { BeginProbe, SendHello, ReceiveSize, ReceiveAck } private State _state; private Socket? _socket; private int _len; private int _size; private readonly byte[] _buffer; private readonly ILogger _logger; private readonly int _timeout; } private readonly ILogger _logger; } /// /// Source-generated logging for ServerProbe /// internal static partial class ServerProbeLogging { private const int EventClass = 1600; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Debug, Message = "Probe {Index} : {RemoteEp} found no opc server. {Error}")] internal static partial void ProbeNoOpcServer(this ILogger logger, int index, string? remoteEp, SocketError error); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Error, Message = "Probe {Index} : Called without connected socket!")] internal static partial void ProbeNoConnectedSocket(this ILogger logger, int index); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Debug, Message = "Probe {Index} : {Endpoint} ({RemoteEp})...")] internal static partial void ProbeStart(this ILogger logger, int index, string endpoint, string? remoteEp); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Debug, Message = "Probe {Index} : {RemoteEp} returned message type {Type} != Ack.")] internal static partial void ProbeReturnedWrongType(this ILogger logger, int index, string? remoteEp, uint type); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Trace, Message = "Probe {Index} : {RemoteEp} returned invalid message type {Type}.")] internal static partial void ProbeReturnedInvalidType(this ILogger logger, int index, string? remoteEp, uint type); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Debug, Message = "Probe {Index} : {RemoteEp} returned invalid message length {Size}.")] internal static partial void ProbeReturnedInvalidLength(this ILogger logger, int index, string? remoteEp, int size); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Information, Message = "Probe {Index} : found OPC UA server at {RemoteEp} (protocol:{ProtocolVersion}) ...")] internal static partial void ProbeFoundOpcUaServer(this ILogger logger, int index, string? remoteEp, uint protocolVersion); [LoggerMessage(EventId = EventClass + 8, Level = LogLevel.Warning, Message = "Probe {Index} : Bad size value read {SendBufferSize} or {ReceiveBufferSize} from opc server at {RemoteEp}.")] internal static partial void ProbeBadSizeValue(this ILogger logger, int index, int sendBufferSize, int receiveBufferSize, string? remoteEp); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Transport/Scanner/BaseConnectProbe.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Transport.Scanner { using Microsoft.Extensions.Logging; using System; using System.Diagnostics.CodeAnalysis; using System.Net; using System.Net.Sockets; using System.Threading; /// /// A connect probe is a ip endpoint consumer that tries to connect /// to the consumed ip endpoint. if successful it uses the probe /// implementation to interrogate the server. /// /// internal abstract class BaseConnectProbe : IDisposable { /// /// Create connect probe /// /// /// /// /// protected BaseConnectProbe(int index, IAsyncProbe probe, ILogger logger, TimeProvider? timeProvider = null) { _probe = probe ?? throw new ArgumentNullException(nameof(probe)); _timeProvider = timeProvider ?? TimeProvider.System; _index = index; _logger = logger; _lock = new SemaphoreSlim(1, 1); _arg = new AsyncConnect(this); } /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Dispose probe /// /// protected virtual void Dispose(bool disposing) { if (!_disposedValue) { if (disposing) { _lock.Wait(); try { _cts.Cancel(); _probe?.Dispose(); DisposeArgsNoLock(); } finally { _cts.Dispose(); _lock.Release(); _lock.Dispose(); } } _disposedValue = true; } } /// /// Start probe /// public void Start() { OnBegin(); } /// /// Retrieve next endpoint /// /// /// /// protected abstract bool GetNext( [NotNullWhen(true)] out IPEndPoint? ep, out int timeout); /// /// Whether the probe should give up or retry after /// a failure. Default is false. /// /// protected virtual bool ShouldGiveUp() { return false; } /// /// Called on individual failure /// /// protected abstract void OnFail(IPEndPoint ep); /// /// Called on success /// /// protected abstract void OnSuccess(IPEndPoint ep); /// /// Called on timeout /// /// protected virtual void OnComplete(IPEndPoint ep) { } /// /// Called on exit /// protected virtual void OnExit() { } /// /// Begin connecting to next endpoint /// private void OnBegin() { var exit = false; _lock.Wait(); try { while (!_cts.IsCancellationRequested && !exit) { IPEndPoint? ep = null; var timeout = 3000; try { if (!GetNext(out ep, out timeout)) { exit = true; break; } } catch (OperationCanceledException) { exit = true; break; } catch (InvalidOperationException) { continue; } catch (Exception ex) { _logger.EndpointError(ex, _index); exit = true; break; } if (_arg?.IsRunning == true) { // Reset args since it is in running state and cannot be used... _logger.DisposingArgs(); DisposeArgsNoLock(); } while (!_cts.IsCancellationRequested) { _arg ??= new AsyncConnect(this); try { if (_arg.BeginConnect(ep, timeout)) { // Completed synchronously - go to next candidate break; } return; } catch (ObjectDisposedException) { // Try again } catch (InvalidOperationException) { // Operation in progress - try again } catch (SocketException sex) { if (sex.SocketErrorCode == SocketError.NoBufferSpaceAvailable || sex.SocketErrorCode == SocketError.TooManyOpenSockets) { if (ShouldGiveUp()) { // Exit only until we hit (approx.) min probe count. exit = true; break; } // Otherwise retry... } else { _logger.ConnectError(sex, sex.SocketErrorCode, _index); } } catch (Exception ex) { // Unexpected - shut probe down _logger.UnexpectedError(ex, _index); exit = true; break; } // Retry same endpoint address with new args DisposeArgsNoLock(); } if (exit) { // We failed, requeue the endpoint and kill this probe OnFail(ep); break; } } if (_cts.IsCancellationRequested) { return; } } finally { _lock.Release(); } if (exit) { // // We are here because we either... // // a) failed to dequeue // b) The producer has completed // c) Connect failed due to lack of ephimeral ports. // d) A non socket exception occurred. // // Notify of exit. // OnExit(); } } /// /// Dispose of args and resources /// private void DisposeArgsNoLock() { _arg?.Dispose(); _arg = null; } /// /// Internal arg state /// private enum State { Begin, Connect, Probe, Timeout, Error, Disposed } /// /// Wraps socket event arg and connection state /// private class AsyncConnect : IDisposable { /// /// Whether the connect is running /// internal bool IsRunning => _state != State.Begin; /// /// Create event arg wrapper /// /// public AsyncConnect(BaseConnectProbe outer) { _outer = outer; _timer = outer._timeProvider.CreateTimer(OnTimerTimeout, null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); _lock = new SemaphoreSlim(1, 1); _arg = new SocketAsyncEventArgs(); _arg.Completed += OnComplete; _arg.UserToken = this; } /// /// Dispose probe /// public void Dispose() { _lock.Wait(); try { if (_state != State.Disposed) { Socket.CancelConnectAsync(_arg); _arg.ConnectSocket?.Dispose(); _socket?.Dispose(); _arg.Dispose(); _timer.Dispose(); _state = State.Disposed; } } finally { _lock.Release(); _lock.Dispose(); } } /// /// Begins a connect and returns whether it completed /// synchronously so outer can loop. /// /// /// /// internal bool BeginConnect(IPEndPoint ep, int timeout) { _lock.Wait(); try { _arg.RemoteEndPoint = ep; // Reset arg, probe, and start connecting _outer._probe.Reset(); _arg.ConnectSocket.SafeDispose(); _state = State.Connect; // Open new socket _socket?.Dispose(); _socket = new Socket(SocketType.Stream, ProtocolType.IP); if (!_socket.ConnectAsync(_arg)) { // Complete inline and pull next... if (OnCompleteNoLock()) { // Go to next candidate return true; } } // Wait for completion or timeout after x seconds _timer.Change(TimeSpan.FromMilliseconds(timeout), Timeout.InfiniteTimeSpan); return false; } finally { _lock.Release(); } } /// /// Complete is called from completion queue on cancel or connect/error /// /// /// private void OnComplete(object? sender, SocketAsyncEventArgs arg) { _lock.Wait(); try { if (!OnCompleteNoLock()) { return; // assume next OnComplete will occur or timeout... } // Cancel timer and start next _timer.Change(Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); } catch (Exception ex) { _outer._logger.CompletionError(ex, _outer._index); } finally { _lock.Release(); } // We are now disposed, or at begin, go to next to cleanup or continue _outer.OnBegin(); } /// /// No lock complete /// /// private bool OnCompleteNoLock() { try { switch (_state) { case State.Connect: if (_arg.SocketError != SocketError.Success) { // Reset back to begin _state = State.Begin; return true; } // Start probe _state = State.Probe; return OnProbeNoLock(); case State.Probe: // Continue probing until completed return OnProbeNoLock(); case State.Timeout: // Timeout caused cancel already - stay in timeout condition. return true; case State.Error: case State.Disposed: // Stay in error state or disposed - this should not happen. return true; // Unexpected. // case State.Begin: default: throw new InvalidProgramException($"Unexpected state {_state}."); } } catch { // Go to error state _state = State.Error; return true; } finally { if (_state != State.Connect && _state != State.Probe) { // Terminal - complete address now if (_arg.RemoteEndPoint is IPEndPoint ep) { _outer.OnComplete(ep); } _arg.SocketError = SocketError.NotSocket; } } } /// /// Perform probe /// /// private bool OnProbeNoLock() { var completed = _outer._probe.OnComplete(_outer._index, _arg, out var ok, out var timeout); if (completed) { if (_arg.RemoteEndPoint is IPEndPoint ep) { if (ok) { _outer.OnSuccess(ep); } else { _outer.OnComplete(ep); } } _state = State.Begin; } else { // Wait for completion or timeout after x seconds _timer.Change(TimeSpan.FromMilliseconds(timeout), Timeout.InfiniteTimeSpan); } return completed; } /// /// Timeout current probe /// /// private void OnTimerTimeout(object? state) { if (!_lock.Wait(0)) { // lock is taken either by having completed or having re-begun. return; } try { switch (_state) { case State.Timeout: return; case State.Connect: // // Cancel current arg and mark as timedout which will // dispose the arg and open a new one. Should the arg // still complete later it will be in terminal state. // Socket.CancelConnectAsync(_arg); _state = State.Timeout; _arg.SocketError = SocketError.TimedOut; return; case State.Probe: _outer._logger.ProbeTimeout(_outer._index, _arg.RemoteEndPoint?.ToString()); _arg.SocketError = SocketError.TimedOut; _state = State.Timeout; if (_outer._probe.Reset()) { // We will get a disconnect complete callback now. return; } // // There was nothing to cancel so start from beginning. // Since connect socket is connected, go to begin state // This will close the socket and reconnect a new one. // _outer._logger.ProbeRestart(_outer._index); _state = State.Begin; _outer.OnBegin(); return; } } catch (Exception ex) { _outer._logger.TimeoutError(ex, _outer._index); } finally { _lock.Release(); } } private readonly ITimer _timer; private readonly SocketAsyncEventArgs _arg; private readonly SemaphoreSlim _lock; private readonly BaseConnectProbe _outer; private State _state; private Socket? _socket; } private readonly CancellationTokenSource _cts = new(); private readonly SemaphoreSlim _lock; private readonly int _index; private readonly IAsyncProbe _probe; private readonly ILogger _logger; private readonly TimeProvider _timeProvider; private AsyncConnect? _arg; private bool _disposedValue; } /// /// Source-generated logging definitions for BaseConnectProbe /// internal static partial class BaseConnectProbeLogging { private const int EventClass = 1630; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Error, Message = "Error getting endpoint for probe {Index}")] public static partial void EndpointError(this ILogger logger, Exception ex, int index); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Trace, Message = "Disposing args in running state.")] public static partial void DisposingArgs(this ILogger logger); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Error, Message = "{Code} in connect of probe {Index}...")] public static partial void ConnectError(this ILogger logger, Exception ex, SocketError code, int index); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Error, Message = "Probe {Index} has unexpected exception during connect.")] public static partial void UnexpectedError(this ILogger logger, Exception ex, int index); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Debug, Message = "Error during completion of probe {Index}")] public static partial void CompletionError(this ILogger logger, Exception ex, int index); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Debug, Message = "Probe {Index} {RemoteEp} timed out...")] public static partial void ProbeTimeout(this ILogger logger, int index, string? remoteEp); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Information, Message = "Probe {Index} not cancelled - try restart...")] public static partial void ProbeRestart(this ILogger logger, int index); [LoggerMessage(EventId = EventClass + 8, Level = LogLevel.Debug, Message = "Error during timeout of probe {Index}")] public static partial void TimeoutError(this ILogger logger, Exception ex, int index); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Transport/Scanner/NetworkScanner.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Transport.Scanner { using Azure.IIoT.OpcUa.Publisher.Stack.Transport.Models; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; using System.Net.NetworkInformation; using System.Threading; using System.Threading.Tasks; /// /// Scans network using icmp and finds all machines in it. /// public sealed class NetworkScanner : IScanner { /// /// Number of items scanned /// public int ScanCount => _scanCount; /// /// Number of active probes /// public int ActiveProbes => _pings.Count; /// /// Create scanner /// /// /// /// public NetworkScanner(ILogger logger, Action replies, CancellationToken ct) : this(logger, replies, false, null, NetworkClass.Wired, null, null, ct) { } /// /// Create scanner /// /// /// /// /// public NetworkScanner(ILogger logger, Action replies, NetworkClass netclass, CancellationToken ct) : this(logger, replies, false, null, netclass, null, null, ct) { } /// /// Create scanner /// /// /// /// /// /// /// /// /// public NetworkScanner(ILogger logger, Action replies, bool local, IEnumerable? addresses, NetworkClass netclass, int? maxProbeCount, TimeSpan? timeout, CancellationToken ct) { _logger = logger; _replies = replies; _ct = ct; _timeout = timeout ?? kDefaultProbeTimeout; _completion = new TaskCompletionSource( TaskCreationOptions.RunContinuationsAsynchronously); _candidates = []; if (addresses?.Any() != true) { _addresses = NetworkInformationEx.GetAllNetInterfaces(netclass) .Select(t => new AddressRange(t, local)).Distinct().ToList(); } else { _addresses = addresses.Select(a => a.Copy()).Distinct().ToList(); } _pings = CreatePings(local ? _addresses.Count + 1 : maxProbeCount ?? kDefaultMaxProbeCount); // Start initial pings _logger.StartScanning(_addresses.Select(a => a.ToString())); foreach (var ping in _pings.ToList()) { OnNextPing(ping); } } /// /// Scan completed /// public Task WaitToCompleteAsync() { return _completion.Task; } /// /// Dispose scanner /// public void Dispose() { lock (_candidates) { foreach (var ping in _pings) { ping.SendAsyncCancel(); ping.Dispose(); } _pings.Clear(); _completion.TrySetCanceled(); } } /// /// Schedule next /// /// private void OnNextPing(Ping ping) { lock (_candidates) { while (!_ct.IsCancellationRequested) { if (_candidates.Count > 0) { var address = (IPv4Address)_candidates[0]; _candidates.RemoveAt(0); ping.SendAsync(address, (int)_timeout.TotalMilliseconds, ping); return; } if (_addresses.Count == 0) { break; } _addresses[0].FillNextBatch(_candidates, kDefaultBatchSize); if (_candidates.Count == 0) { _addresses.RemoveAt(0); continue; } _candidates.Shuffle(); } if (_pings.Remove(ping)) { ping.Dispose(); if (_pings.Count == 0) { // All pings drained... _completion.TrySetResult(true); } } } } /// /// Helper to create ping /// /// /// private List CreatePings(int count) { var pings = new List(count); for (var i = 0; i < count; i++) { var ping = new Ping(); ping.PingCompleted += (sender, e) => { var reply = e.Reply; if (reply?.Status == IPStatus.Success) { _replies(this, reply); } // When completed, grab next Interlocked.Increment(ref _scanCount); OnNextPing((Ping)e.UserState!); }; pings.Add(ping); } return pings; } private const int kDefaultMaxProbeCount = 100; private const int kDefaultBatchSize = 1000; private static readonly TimeSpan kDefaultProbeTimeout = TimeSpan.FromSeconds(3); private readonly TimeSpan _timeout; private readonly List _candidates; private readonly List _addresses; private readonly ILogger _logger; private readonly List _pings; private readonly Action _replies; private readonly TaskCompletionSource _completion; private readonly CancellationToken _ct; private volatile int _scanCount; } /// /// Source-generated logging for NetworkScanner /// internal static partial class NetworkScannerLogging { private const int EventClass = 1660; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Information, Message = "Start scanning {Addresses}...")] internal static partial void StartScanning(this ILogger logger, IEnumerable addresses); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Stack/Transport/Scanner/PortScanner.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Transport.Scanner { using Microsoft.Extensions.Logging; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Net; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; /// /// Scans port ranges /// public sealed class PortScanner : IScanner { /// /// Number of items scanned /// public int ScanCount => _scanCount; /// /// Number of active probes /// public int ActiveProbes => _active; /// /// Create scanner with default port probe /// /// /// /// /// public PortScanner(ILogger logger, IEnumerable source, Action target, CancellationToken ct) : this(logger, source, target, null, ct) { } /// /// Create scanner /// /// /// /// /// /// public PortScanner(ILogger logger, IEnumerable source, Action target, IPortProbe? portProbe, CancellationToken ct) : this(logger, source, target, portProbe, null, null, null, ct) { } /// /// Create scanner /// /// /// /// /// /// /// /// /// public PortScanner(ILogger logger, IEnumerable source, Action target, IPortProbe? portProbe, int? maxProbeCount, int? minProbePercent, TimeSpan? timeout, CancellationToken ct) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _source = source?.GetEnumerator() ?? throw new ArgumentNullException(nameof(source)); _target = target ?? throw new ArgumentNullException(nameof(target)); _maxProbeCount = maxProbeCount ?? kDefaultMaxProbeCount; _minProbeCount = (int)(_maxProbeCount * ((minProbePercent ?? kDefaultMinProbePercent) / 100.0)); _timeout = timeout ?? kDefaultProbeTimeout; _portProbe = portProbe ?? new NullPortProbe(); _requeued = new ConcurrentQueue(); _probePool = Repeat(i => new ConnectProbe(this, i), _maxProbeCount) .ToList(); _cts = CancellationTokenSource.CreateLinkedTokenSource(ct); _completion = new TaskCompletionSource( TaskCreationOptions.RunContinuationsAsynchronously); _active = _maxProbeCount; foreach (var probe in _probePool) { probe.Start(); } static IEnumerable Repeat(Func factory, int count) { for (var i = 0; i < count; i++) { yield return factory(i); } } } /// /// Scan completed /// public Task WaitToCompleteAsync() { return _completion.Task; } /// /// Dispose scanner /// public void Dispose() { // Kill producer _cts.Cancel(); // Clean up all probes _active = 0; foreach (var probe in _probePool) { probe.Dispose(); } _probePool.Clear(); _completion.TrySetCanceled(); _cts.Dispose(); } /// /// Return next from source. /// /// private bool Next([NotNullWhen(true)] out IPEndPoint? ep) { if (_cts.IsCancellationRequested) { ep = null; return false; } lock (_source) { if (!_source.MoveNext()) { ep = null; return false; } ep = _source.Current; } return true; } /// /// Exit probe and if last propagate target complete /// private void OnProbeExit() { if (Interlocked.Decrement(ref _active) == 0) { // All probes drained - propagate target complete... if (_cts.IsCancellationRequested) { _completion.TrySetCanceled(); } else { _completion.TrySetResult(true); } } } /// /// Returns probe timeout in milliseconds but with entropy /// #pragma warning disable CA5394 // Do not use insecure randomness private int ProbeTimeoutInMilliseconds => Random.Shared.Next( (int)(_timeout.TotalMilliseconds * 0.7), (int)(_timeout.TotalMilliseconds * 1.5)); #pragma warning restore CA5394 // Do not use insecure randomness /// /// Port connect probe /// private sealed class ConnectProbe : BaseConnectProbe { /// /// Create probe /// /// /// public ConnectProbe(PortScanner scanner, int index) : base(index, scanner._portProbe.Create(), scanner._logger) { _scanner = scanner; } /// /// Get next endpoint /// /// /// /// protected override bool GetNext( [NotNullWhen(true)] out IPEndPoint? ep, out int timeout) { if (!_scanner.Next(out ep)) { timeout = 0; return false; } timeout = _scanner.ProbeTimeoutInMilliseconds; Interlocked.Increment(ref _scanner._scanCount); return true; } /// /// Called on error /// /// protected override bool ShouldGiveUp() { return _scanner._active > _scanner._minProbeCount; } /// /// Called when endpoint probe failed for some reason /// /// protected override void OnFail(IPEndPoint ep) { _scanner._requeued.Enqueue(ep); Interlocked.Decrement(ref _scanner._scanCount); } /// /// Called on success /// /// protected override void OnSuccess(IPEndPoint ep) { _scanner._target(_scanner, ep); } /// /// Called when probe terminates /// protected override void OnExit() { _scanner.OnProbeExit(); } private readonly PortScanner _scanner; } /// /// Null port probe /// private class NullPortProbe : IAsyncProbe, IPortProbe { /// public bool OnComplete(int index, SocketAsyncEventArgs arg, out bool ok, out int timeout) { ok = true; timeout = 0; return true; } /// public void Dispose() { } /// public bool Reset() { return false; } /// public IAsyncProbe Create() { return this; } } /// /// Max number of connect probes. On Windows, up to 5000 the performance /// improvement is linear, e.g. all ports on a Windows PC are scanned in /// around 16 seconds. /// private const int kDefaultMaxProbeCount = 1000; /// /// By default ensure at least 80% probes are going. /// private const int kDefaultMinProbePercent = 80; private static readonly TimeSpan kDefaultProbeTimeout = TimeSpan.FromSeconds(5); private readonly ConcurrentQueue _requeued; private readonly IEnumerator _source; private readonly TaskCompletionSource _completion; private readonly List _probePool; private readonly Action _target; private readonly int _maxProbeCount; private readonly int _minProbeCount; private readonly TimeSpan _timeout; private readonly CancellationTokenSource _cts; private readonly IPortProbe _portProbe; private readonly ILogger _logger; private int _active; #pragma warning disable IDE0032 // Use auto property private int _scanCount; #pragma warning restore IDE0032 // Use auto property } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Storage/PhysicalFileProviderFactory.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Storage { using Azure.IIoT.OpcUa.Publisher; using Furly.Extensions.Storage; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System; using System.Collections.Concurrent; using System.IO; using System.Linq; /// /// Physical file provider factory /// public sealed class PhysicalFileProviderFactory : IFileProviderFactory, IDisposable { /// public PhysicalFileProviderFactory(IOptions options, ILogger logger) { _options = options; _logger = logger; _providers = new ConcurrentDictionary(); } /// public IFileProvider Create(string root) { root = Path.GetFullPath(string.IsNullOrWhiteSpace(root) ? Environment.CurrentDirectory : root); return _providers.GetOrAdd(root, directory => { if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } var provider = new PhysicalFileProvider(directory); if (_options.Value.UseFileChangePolling == true) { provider.UseActivePolling = true; provider.UsePollingFileWatcher = true; } _logger.MappingDirectory(directory); return provider; }); } /// public void Dispose() { _providers.Values.ToList().ForEach(p => p.Dispose()); } private readonly IOptions _options; private readonly ILogger _logger; private readonly ConcurrentDictionary _providers; } /// /// Source-generated logging extensions for PhysicalFileProviderFactory /// internal static partial class PhysicalFileProviderFactoryLogging { private const int EventClass = 1700; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Information, Message = "Mapping directory {Directory} via physical file provider.")] public static partial void MappingDirectory(this ILogger logger, string directory); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Storage/PublishedNodesConverter.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Storage { using Azure.IIoT.OpcUa.Publisher; using Azure.IIoT.OpcUa.Publisher.Config.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Azure.IoT.Edge.Services; using Furly.Exceptions; using Furly.Extensions.Serializers; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Opc.Ua; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; /// /// Published nodes /// public sealed class PublishedNodesConverter { /// /// Create converter /// /// /// /// /// public PublishedNodesConverter(ILogger logger, IJsonSerializer serializer, IOptions options, IIoTEdgeWorkloadApi? cryptoProvider = null) { _serializer = serializer ?? throw new ArgumentNullException(nameof(serializer)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _cryptoProvider = cryptoProvider; _forceCredentialEncryption = options.Value.ForceCredentialEncryption ?? false; _scaleTestCount = Math.Max(1, options.Value.ScaleTestCount ?? 0); _maxNodesPerDataSet = options.Value.MaxNodesPerDataSet <= 0 ? int.MaxValue : options.Value.MaxNodesPerDataSet; _noPublishingIntervalGrouping = options.Value.IgnoreConfiguredPublishingIntervals ?? false; } /// /// Read monitored item job from reader /// /// /// /// public IEnumerable Read(string publishedNodesContent) { var sw = Stopwatch.StartNew(); _logger.ReadingPublishedNodesFile(); try { var items = _serializer.Deserialize>(publishedNodesContent) ?? throw new SerializerException("Published nodes files, malformed."); _logger.ReadPublishedNodesFile(items.Count, sw.Elapsed); return items; } finally { sw.Stop(); } } /// /// Convert from writer group job model to published nodes entries /// /// /// /// /// /// public IEnumerable ToPublishedNodes(uint version, DateTimeOffset lastChanged, IEnumerable items, bool preferTimeSpan = true) { if (items == null) { return []; } var sw = Stopwatch.StartNew(); try { var publishedNodesEntries = items .Where(group => group?.DataSetWriters?.Count > 0) .SelectMany(group => group.DataSetWriters! .Where(writer => writer.DataSet?.DataSetSource?.PublishedVariables?.PublishedData != null || writer.DataSet?.DataSetSource?.PublishedEvents?.PublishedData != null) .Select(writer => (WriterGroup: group, Writer: writer))) .Select(item => AddConnectionModel(item.Writer.DataSet?.DataSetSource?.Connection, new PublishedNodesEntryModel { NodeId = null, Version = version, LastChangeDateTime = lastChanged, DataSetClassId = item.Writer.DataSet?.DataSetMetaData?.DataSetClassId ?? Guid.Empty, DataSetDescription = item.Writer.DataSet?.DataSetMetaData?.Description, DataSetKeyFrameCount = item.Writer.KeyFrameCount, MessagingMode = item.WriterGroup.HeaderLayoutUri == null ? null : Enum.Parse(item.WriterGroup.HeaderLayoutUri), // TODO: Make safe MessageEncoding = item.WriterGroup.MessageType, WriterGroupTransport = item.WriterGroup.Transport, WriterGroupTransportConfiguration = item.WriterGroup.TransportConfiguration, WriterGroupQualityOfService = item.WriterGroup.Publishing?.RequestedDeliveryGuarantee, WriterGroupMessageTtlTimepan = item.WriterGroup.Publishing?.Ttl, WriterGroupMessageRetention = item.WriterGroup.Publishing?.Retain, WriterGroupPartitions = item.WriterGroup.PublishQueuePartitions, WriterGroupQueueName = item.WriterGroup.Publishing?.QueueName, SendKeepAliveDataSetMessages = item.Writer.DataSet?.SendKeepAlive, SendKeepAliveAsKeyFrameMessages = item.Writer.DataSet?.KeepAliveAsKeyFrame, DataSetExtensionFields = item.Writer.DataSet?.ExtensionFields?.ToDictionary( e => e.DataSetFieldName, e => e.Value), MetaDataUpdateTimeTimespan = item.Writer.MetaDataUpdateTime, QueueName = item.Writer.Publishing?.QueueName, QualityOfService = item.Writer.Publishing?.RequestedDeliveryGuarantee, MessageTtlTimespan = item.Writer.Publishing?.Ttl, MessageRetention = item.Writer.Publishing?.Retain, MetaDataQueueName = item.Writer.MetaData?.QueueName, MetaDataRetention = item.Writer.MetaData?.Retain, MetaDataTtlTimespan = item.Writer.MetaData?.Ttl, MetaDataUpdateTime = null, BatchTriggerIntervalTimespan = item.WriterGroup.PublishingInterval, BatchTriggerInterval = null, DataSetSamplingInterval = null, DataSetSamplingIntervalTimespan = item.Writer.DataSet?.DataSetSource?.SubscriptionSettings?.DefaultSamplingInterval, DefaultHeartbeatInterval = null, DefaultHeartbeatIntervalTimespan = item.Writer.DataSet?.DataSetSource?.SubscriptionSettings?.DefaultHeartbeatInterval, DefaultHeartbeatBehavior = item.Writer.DataSet?.DataSetSource?.SubscriptionSettings?.DefaultHeartbeatBehavior, Priority = item.Writer.DataSet?.DataSetSource?.SubscriptionSettings?.Priority, MaxKeepAliveCount = item.Writer.DataSet?.DataSetSource?.SubscriptionSettings?.MaxKeepAliveCount, DataSetFetchDisplayNames = item.Writer.DataSet?.DataSetSource?.SubscriptionSettings?.ResolveDisplayName, RepublishAfterTransfer = item.Writer.DataSet?.DataSetSource?.SubscriptionSettings?.RepublishAfterTransfer, OpcNodeWatchdogTimespan = item.Writer.DataSet?.DataSetSource?.SubscriptionSettings?.MonitoredItemWatchdogTimeout, OpcNodeWatchdogCondition = item.Writer.DataSet?.DataSetSource?.SubscriptionSettings?.MonitoredItemWatchdogCondition, DataSetWriterWatchdogBehavior = item.Writer.DataSet?.DataSetSource?.SubscriptionSettings?.WatchdogBehavior, BatchSize = item.WriterGroup.NotificationPublishThreshold, DataSetName = item.Writer.DataSet?.Name, DataSetType = item.Writer.DataSet?.Type, DataSetRootNodeId = item.Writer.DataSet?.RootNode, DataSetSourceUri = item.Writer.DataSet?.DataSetSource?.Uri, DataSetSubject = item.Writer.DataSet?.Subject, DataSetWriterGroup = item.WriterGroup.Name == Constants.DefaultWriterGroupName ? null : item.WriterGroup.Name, DataSetWriterId = item.Writer.DataSetWriterName, DataSetRouting = item.Writer.DataSet?.Routing, DataSetPublishingInterval = null, DataSetPublishingIntervalTimespan = null, WriterGroupRootNodeId = item.WriterGroup.RootNode, WriterGroupType = item.WriterGroup.Type, WriterGroupProperties = item.WriterGroup.Properties?.ToDictionary(), PublisherId = item.WriterGroup.PublisherId, OpcNodes = ToOpcNodes(item.Writer.DataSet?.DataSetSource?.SubscriptionSettings, item.Writer.DataSet?.DataSetSource?.PublishedVariables, item.Writer.DataSet?.DataSetSource?.PublishedEvents, item.Writer.DataSet?.DataSetSource?.PublishedMethods, preferTimeSpan, false)? .ToList() ?? [], // ... // Added by Add connection information OpcAuthenticationMode = OpcAuthenticationMode.Anonymous, OpcAuthenticationUsername = null, OpcAuthenticationPassword = null, EndpointUrl = string.Empty, UseSecurity = false, UseReverseConnect = null, DisableSubscriptionTransfer = null, DumpConnectionDiagnostics = null, EndpointSecurityPolicy = null, EndpointSecurityMode = null, EncryptedAuthPassword = null, EncryptedAuthUsername = null })); // Coalesce into unique nodes entry data set groups // TODO: We should start with the grouping earlier return publishedNodesEntries .GroupBy(item => item, new FuncCompare((x, y) => x!.HasSameDataSet(y!))) .Select(group => { group.Key.OpcNodes = group .Where(g => g.OpcNodes != null) .SelectMany(g => g.OpcNodes!) .ToList(); return group.Key; }); } catch (Exception ex) { _logger.FailedToConvertPublishedNodes(ex); return []; } finally { _logger.ConvertedPublishedNodes(sw.Elapsed); sw.Stop(); } static IEnumerable? ToOpcNodes(PublishedDataSetSettingsModel? subscriptionSettings, PublishedDataItemsModel? publishedVariables, PublishedEventItemsModel? publishedEvents, PublishedMethodItemsModel? publishedMethods, bool preferTimeSpan, bool skipTriggeringNodes) { if (publishedVariables == null && publishedEvents == null) { return null; } return (publishedVariables?.PublishedData ?? Enumerable.Empty()) .Select(variable => new OpcNodeModel { DeadbandType = variable.DeadbandType, DeadbandValue = variable.DeadbandValue, DataSetClassFieldId = variable.DataSetClassFieldId, Id = variable.PublishedVariableNodeId, DisplayName = variable.PublishedVariableDisplayName, DataSetFieldId = variable.Id, AttributeId = variable.Attribute, IndexRange = variable.IndexRange, RegisterNode = variable.RegisterNodeForSampling, FetchDisplayName = variable.ReadDisplayNameFromNode, BrowsePath = variable.BrowsePath, UseCyclicRead = variable.SamplingUsingCyclicRead, CyclicReadMaxAge = preferTimeSpan ? null : (int?)variable.CyclicReadMaxAge?.TotalMilliseconds, CyclicReadMaxAgeTimespan = !preferTimeSpan ? null : variable.CyclicReadMaxAge, DiscardNew = variable.DiscardNew, QueueSize = variable.ServerQueueSize, DataChangeTrigger = variable.DataChangeTrigger, HeartbeatBehavior = variable.HeartbeatBehavior, HeartbeatInterval = preferTimeSpan ? null : (int?)variable.HeartbeatInterval?.TotalSeconds, HeartbeatIntervalTimespan = !preferTimeSpan ? null : variable.HeartbeatInterval, OpcSamplingInterval = preferTimeSpan ? null : (int?)variable.SamplingIntervalHint?.TotalMilliseconds, OpcSamplingIntervalTimespan = !preferTimeSpan ? null : variable.SamplingIntervalHint, OpcPublishingInterval = preferTimeSpan ? null : (int?) subscriptionSettings?.PublishingInterval?.TotalMilliseconds, OpcPublishingIntervalTimespan = !preferTimeSpan ? null : subscriptionSettings?.PublishingInterval, SkipFirst = variable.SkipFirst, TypeDefinitionId = variable.TypeDefinitionId, TriggeredNodes = skipTriggeringNodes ? null : ToOpcNodes(subscriptionSettings, variable.Triggering?.PublishedVariables, variable.Triggering?.PublishedEvents, variable.Triggering?.PublishedMethods, preferTimeSpan, true)?.ToList(), Topic = variable.Publishing?.QueueName, QualityOfService = variable.Publishing?.RequestedDeliveryGuarantee, // MonitoringMode = variable.MonitoringMode, // ... ExpandedNodeId = null, ConditionHandling = null, ModelChangeHandling = null, EventFilter = null }) .Concat((publishedEvents?.PublishedData ?? Enumerable.Empty()) .Select(evt => new OpcNodeModel { Id = evt.EventNotifier, EventFilter = new EventFilterModel { TypeDefinitionId = evt.TypeDefinitionId, SelectClauses = evt.SelectedFields?.Select(s => s.Clone()).ToList(), WhereClause = evt.Filter.Clone() }, ConditionHandling = evt.ConditionHandling.Clone(), ModelChangeHandling = evt.ModelChangeHandling.Clone(), DataSetFieldId = evt.Id, DisplayName = evt.PublishedEventName, FetchDisplayName = evt.ReadEventNameFromNode, BrowsePath = evt.BrowsePath, DiscardNew = evt.DiscardNew, QueueSize = evt.QueueSize, TriggeredNodes = skipTriggeringNodes ? null : ToOpcNodes(subscriptionSettings, evt.Triggering?.PublishedVariables, evt.Triggering?.PublishedEvents, evt.Triggering?.PublishedMethods, preferTimeSpan, true)?.ToList(), Topic = evt.Publishing?.QueueName, QualityOfService = evt.Publishing?.RequestedDeliveryGuarantee, // MonitoringMode = evt.MonitoringMode, // ... DeadbandType = null, TypeDefinitionId = null, DataChangeTrigger = null, DataSetClassFieldId = Guid.Empty, DeadbandValue = null, ExpandedNodeId = null, HeartbeatInterval = null, HeartbeatBehavior = null, HeartbeatIntervalTimespan = null, OpcSamplingInterval = null, OpcSamplingIntervalTimespan = null, CyclicReadMaxAgeTimespan = null, CyclicReadMaxAge = null, AttributeId = null, RegisterNode = null, UseCyclicRead = null, IndexRange = null, OpcPublishingInterval = preferTimeSpan ? null : (int?) subscriptionSettings?.PublishingInterval?.TotalMilliseconds, OpcPublishingIntervalTimespan = !preferTimeSpan ? null : subscriptionSettings?.PublishingInterval, SkipFirst = null })).Concat((publishedMethods?.PublishedData ?? Enumerable.Empty()) .Select(method => new OpcNodeModel { Id = method.MethodId, MethodMetadata = method.Metadata, // TODO: Clone DataSetFieldId = method.Id, BrowsePath = method.BrowsePath, TriggeredNodes = skipTriggeringNodes ? null : ToOpcNodes(subscriptionSettings, method.Triggering?.PublishedVariables, method.Triggering?.PublishedEvents, method.Triggering?.PublishedMethods, preferTimeSpan, true)?.ToList(), Topic = method.Publishing?.QueueName, QualityOfService = method.Publishing?.RequestedDeliveryGuarantee, // MonitoringMode = method.MonitoringMode, // ... DeadbandType = null, TypeDefinitionId = null, DataChangeTrigger = null, DataSetClassFieldId = Guid.Empty, DeadbandValue = null, ExpandedNodeId = null, HeartbeatInterval = null, HeartbeatBehavior = null, HeartbeatIntervalTimespan = null, OpcSamplingInterval = null, OpcSamplingIntervalTimespan = null, CyclicReadMaxAgeTimespan = null, CyclicReadMaxAge = null, AttributeId = null, RegisterNode = null, UseCyclicRead = null, IndexRange = null, ConditionHandling = null, DiscardNew = null, QueueSize = null, ModelChangeHandling = null, FetchDisplayName = null, DisplayName = null, EventFilter = null, OpcPublishingInterval = preferTimeSpan ? null : (int?) subscriptionSettings?.PublishingInterval?.TotalMilliseconds, OpcPublishingIntervalTimespan = !preferTimeSpan ? null : subscriptionSettings?.PublishingInterval, SkipFirst = null })); } } /// /// Convert published nodes configuration to Writer group jobs /// /// /// public IEnumerable ToWriterGroups(IEnumerable entries) { if (entries == null) { return []; } var sw = Stopwatch.StartNew(); try { if (!_noPublishingIntervalGrouping) { // // Split all entries by the publishing interval in the nodes using the entry publishing // interval as default. To prevent entries with no nodes to be removed here a dummy // entry is added to the list of nodes and removed again from the group entries selected. // entries = entries .SelectMany(entry => GetNodeModels(entry, _scaleTestCount) .DefaultIfEmpty(kDummyEntry) .GroupBy(n => n.GetNormalizedPublishingInterval( entry.GetNormalizedDataSetPublishingInterval())) .Select(g => entry with { // Set the publishing interval for this entry at the top DataSetPublishingIntervalTimespan = g.Key, DataSetPublishingInterval = null, OpcNodes = g .Where(n => n != kDummyEntry) .Select(n => n with { // Unset all node specific settings. OpcPublishingIntervalTimespan = null, OpcPublishingInterval = null }) .ToList() })); } return entries // // Now we have entries with nodes that have no publishing interval, group all entries // by group identifier // .Select(entry => ( Entry: entry, UniqueGroupId: entry.GetUniqueWriterGroupId() )) .GroupBy(entry => entry.UniqueGroupId) .Select(g => (g.Key, Entries: g.ToList())) // // In each group select the writers using the unique data set writer id which uses the // publishing interval. // .Select(group => ( Id: group.Key, Header: group.Entries[0].Entry, Writers: group.Entries .Select(entry => ( entry.Entry, UniqueWriterId: entry.Entry.GetUniqueDataSetWriterId() )) .GroupBy(e => e.UniqueWriterId) .Select(w => (w.Key, Writers: w.Select(e => e.Entry).ToList())) .ToList() )) // Now bring it all together into a group with writers and settings .Select(group => new WriterGroupModel { Id = group.Id, MessageType = group.Header.MessageEncoding, Transport = group.Header.WriterGroupTransport, TransportConfiguration = group.Header.WriterGroupTransportConfiguration, Publishing = new PublishingQueueSettingsModel { RequestedDeliveryGuarantee = group.Header.WriterGroupQualityOfService, QueueName = group.Header.WriterGroupQueueName, Retain = group.Header.WriterGroupMessageRetention, Ttl = group.Header.WriterGroupMessageTtlTimepan }, HeaderLayoutUri = group.Header.MessagingMode?.ToString(), Name = group.Header.DataSetWriterGroup, Properties = group.Header.WriterGroupProperties, PublisherId = group.Header.PublisherId, Type = group.Header.WriterGroupType, RootNode = group.Header.WriterGroupRootNodeId, NotificationPublishThreshold = group.Header.BatchSize, PublishQueuePartitions = group.Header.WriterGroupPartitions, PublishingInterval = group.Header.GetNormalizedBatchTriggerInterval(), DataSetWriters = group.Writers .Select(w => ( WriterId: w.Key, Header: w.Writers[0], WriterBatches: w.Writers .SelectMany(w => w.OpcNodes!) .Distinct(OpcNodeModelEx.Comparer) .Batch(_maxNodesPerDataSet) // Future: batch in service so it is centralized )) .SelectMany(b => b.WriterBatches // Do we need to materialize here? .DefaultIfEmpty(kDummyEntry.YieldReturn()) .Select(n => n.ToList()) .Select((nodes, index) => new DataSetWriterModel { Id = b.WriterId + "_" + index, DataSetWriterName = b.Header.DataSetWriterId, MetaDataUpdateTime = b.Header.GetNormalizedMetaDataUpdateTime(), KeyFrameCount = b.Header.DataSetKeyFrameCount, Publishing = new PublishingQueueSettingsModel { QueueName = b.Header.QueueName, RequestedDeliveryGuarantee = b.Header.QualityOfService, Retain = b.Header.MessageRetention, Ttl = b.Header.MessageTtlTimespan }, MetaData = new PublishingQueueSettingsModel { QueueName = b.Header.MetaDataQueueName, RequestedDeliveryGuarantee = null, Retain = b.Header.MetaDataRetention, Ttl = b.Header.MetaDataTtlTimespan }, DataSet = new PublishedDataSetModel { Name = b.Header.DataSetName, Type = b.Header.DataSetType, Subject = b.Header.DataSetSubject, RootNode = b.Header.DataSetRootNodeId, DataSetMetaData = new DataSetMetaDataModel { DataSetClassId = b.Header.DataSetClassId, Description = b.Header.DataSetDescription, MajorVersion = null, Name = b.Header.DataSetName }, ExtensionFields = b.Header.DataSetExtensionFields? .Select(ef => new ExtensionFieldModel { DataSetFieldName = ef.Key, Value = ef.Value }) .ToList(), SendKeepAlive = b.Header.SendKeepAliveDataSetMessages, KeepAliveAsKeyFrame = b.Header.SendKeepAliveAsKeyFrameMessages, Routing = b.Header.DataSetRouting, DataSetSource = new PublishedDataSetSourceModel { Uri = b.Header.DataSetSourceUri, Connection = b.Header.ToConnectionModel(ToCredential), SubscriptionSettings = new PublishedDataSetSettingsModel { MaxKeepAliveCount = b.Header.MaxKeepAliveCount, RepublishAfterTransfer = b.Header.RepublishAfterTransfer, MonitoredItemWatchdogTimeout = b.Header.OpcNodeWatchdogTimespan, MonitoredItemWatchdogCondition = b.Header.OpcNodeWatchdogCondition, WatchdogBehavior = b.Header.DataSetWriterWatchdogBehavior, Priority = b.Header.Priority, ResolveDisplayName = b.Header.DataSetFetchDisplayNames, DefaultHeartbeatBehavior = b.Header.DefaultHeartbeatBehavior, DefaultHeartbeatInterval = b.Header.GetNormalizedDefaultHeartbeatInterval(), DefaultSamplingInterval = b.Header.GetNormalizedDataSetSamplingInterval(), PublishingInterval = b.Header.GetNormalizedDataSetPublishingInterval(), MaxNotificationsPerPublish = null, EnableImmediatePublishing = null, EnableSequentialPublishing = null, LifeTimeCount = null, UseDeferredAcknoledgements = null // ... }, PublishedVariables = ToPublishedDataItems(nodes.Where(n => n != kDummyEntry), false), PublishedEvents = ToPublishedEventItems(nodes.Where(n => n != kDummyEntry), false), PublishedMethods = ToPublishedMethodItems(nodes.Where(n => n != kDummyEntry), false) } }, MessageSettings = null, DataSetFieldContentMask = null })) .ToList(), KeepAliveTime = null, MaxNetworkMessageSize = null, MessageSettings = null, Priority = null, PublishQueueSize = null, SecurityGroupId = null, SecurityKeyServices = null, SecurityMode = null, LocaleIds = null }) .ToList(); // Convert here or else we dont print conversion correctly } catch (Exception ex) { _logger.FailedToConvertPublishedNodes(ex); return []; } finally { _logger.ConvertedPublishedNodes(sw.Elapsed); sw.Stop(); } IEnumerable GetNodeModels(PublishedNodesEntryModel item, int scaleTestCount) { if (item.OpcNodes != null) { foreach (var node in item.OpcNodes) { if (!node.TryGetId(out var id)) { _logger.MissingNodeId(); continue; } if (scaleTestCount <= 1) { yield return new OpcNodeModel { Id = id, DisplayName = node.DisplayName, DataSetClassFieldId = node.DataSetClassFieldId, DataSetFieldId = node.DataSetFieldId, ExpandedNodeId = node.ExpandedNodeId, // The publishing interval item wins over dataset over global default OpcPublishingIntervalTimespan = node.GetNormalizedPublishingInterval() ?? item.GetNormalizedDataSetPublishingInterval(), OpcSamplingIntervalTimespan = node.GetNormalizedSamplingInterval(), HeartbeatIntervalTimespan = node.GetNormalizedHeartbeatInterval(), QueueSize = node.QueueSize, DiscardNew = node.DiscardNew, BrowsePath = node.BrowsePath, AttributeId = node.AttributeId, FetchDisplayName = node.FetchDisplayName, IndexRange = node.IndexRange, RegisterNode = node.RegisterNode, UseCyclicRead = node.UseCyclicRead, TypeDefinitionId = node.TypeDefinitionId, CyclicReadMaxAgeTimespan = node.GetNormalizedCyclicReadMaxAge(), SkipFirst = node.SkipFirst, DataChangeTrigger = node.DataChangeTrigger, DeadbandType = node.DeadbandType, DeadbandValue = node.DeadbandValue, EventFilter = node.EventFilter, HeartbeatBehavior = node.HeartbeatBehavior, ConditionHandling = node.ConditionHandling, TriggeredNodes = node.TriggeredNodes, QualityOfService = node.QualityOfService, Topic = node.Topic, ModelChangeHandling = node.ModelChangeHandling }; } else { for (var i = 0; i < scaleTestCount; i++) { yield return new OpcNodeModel { Id = id, DisplayName = !string.IsNullOrEmpty(node.DisplayName) ? $"{node.DisplayName}_{i}" : null, DataSetFieldId = node.DataSetFieldId, DataSetClassFieldId = node.DataSetClassFieldId, ExpandedNodeId = node.ExpandedNodeId, HeartbeatIntervalTimespan = node.GetNormalizedHeartbeatInterval(), // The publishing interval item wins over dataset over global default OpcPublishingIntervalTimespan = node.GetNormalizedPublishingInterval() ?? item.GetNormalizedDataSetPublishingInterval(), OpcSamplingIntervalTimespan = node.GetNormalizedSamplingInterval(), QueueSize = node.QueueSize, SkipFirst = node.SkipFirst, DataChangeTrigger = node.DataChangeTrigger, BrowsePath = node.BrowsePath, AttributeId = node.AttributeId, FetchDisplayName = node.FetchDisplayName, IndexRange = node.IndexRange, RegisterNode = node.RegisterNode, UseCyclicRead = node.UseCyclicRead, TypeDefinitionId = node.TypeDefinitionId, CyclicReadMaxAgeTimespan = node.GetNormalizedCyclicReadMaxAge(), DeadbandType = node.DeadbandType, DeadbandValue = node.DeadbandValue, DiscardNew = node.DiscardNew, HeartbeatBehavior = node.HeartbeatBehavior, EventFilter = node.EventFilter, TriggeredNodes = null, ConditionHandling = node.ConditionHandling, QualityOfService = node.QualityOfService, Topic = node.Topic, ModelChangeHandling = node.ModelChangeHandling }; } } } } if (!string.IsNullOrWhiteSpace(item.NodeId?.Identifier)) { yield return new OpcNodeModel { Id = item.NodeId.Identifier, OpcPublishingIntervalTimespan = item.GetNormalizedDataSetPublishingInterval() }; } } static PublishedDataItemsModel ToPublishedDataItems(IEnumerable opcNodes, bool skipTriggering) { return new PublishedDataItemsModel { PublishedData = opcNodes .Where(node => node.MethodMetadata == null && node.EventFilter == null && node.ModelChangeHandling == null) .Select(node => new PublishedDataSetVariableModel { Id = node.DataSetFieldId, PublishedVariableNodeId = node.Id, DataSetClassFieldId = node.DataSetClassFieldId, // At this point in time the next values are ensured to be filled in with // the appropriate value: configured or default PublishedVariableDisplayName = node.DisplayName, SamplingIntervalHint = node.OpcSamplingIntervalTimespan, HeartbeatInterval = node.HeartbeatIntervalTimespan, HeartbeatBehavior = node.HeartbeatBehavior, ServerQueueSize = node.QueueSize, DiscardNew = node.DiscardNew, SamplingUsingCyclicRead = node.UseCyclicRead, CyclicReadMaxAge = node.CyclicReadMaxAgeTimespan, Attribute = node.AttributeId, IndexRange = node.IndexRange, RegisterNodeForSampling = node.RegisterNode, BrowsePath = node.BrowsePath, ReadDisplayNameFromNode = node.FetchDisplayName, MonitoringMode = null, SubstituteValue = null, SkipFirst = node.SkipFirst, DataChangeTrigger = node.DataChangeTrigger, TypeDefinitionId = node.TypeDefinitionId, DeadbandValue = node.DeadbandValue, DeadbandType = node.DeadbandType, Publishing = node.Topic == null && node.QualityOfService == null ? null : new PublishingQueueSettingsModel { QueueName = node.Topic, RequestedDeliveryGuarantee = node.QualityOfService, Retain = null, Ttl = null }, Triggering = skipTriggering || node.TriggeredNodes == null ? null : new PublishedDataSetTriggerModel { PublishedVariables = ToPublishedDataItems(node.TriggeredNodes, true), PublishedEvents = ToPublishedEventItems(node.TriggeredNodes, true), PublishedMethods = ToPublishedMethodItems(node.TriggeredNodes, true) } }) .ToList() }; } static PublishedEventItemsModel ToPublishedEventItems(IEnumerable opcNodes, bool skipTriggering) { return new PublishedEventItemsModel { PublishedData = opcNodes .Where(node => node.MethodMetadata == null && (node.EventFilter != null || node.ModelChangeHandling != null)) .Select(node => new PublishedDataSetEventModel { Id = node.DataSetFieldId, EventNotifier = node.Id, QueueSize = node.QueueSize, DiscardNew = node.DiscardNew, PublishedEventName = node.DisplayName, ReadEventNameFromNode = node.FetchDisplayName, BrowsePath = node.BrowsePath, MonitoringMode = null, TypeDefinitionId = node.EventFilter?.TypeDefinitionId, SelectedFields = node.EventFilter?.SelectClauses?.Select(s => s.Clone()).ToList(), Filter = node.EventFilter?.WhereClause.Clone(), ConditionHandling = node.ConditionHandling.Clone(), ModelChangeHandling = node.ModelChangeHandling.Clone(), Publishing = node.Topic == null && node.QualityOfService == null ? null : new PublishingQueueSettingsModel { QueueName = node.Topic, RequestedDeliveryGuarantee = node.QualityOfService, Retain = null, Ttl = null }, Triggering = skipTriggering || node.TriggeredNodes == null ? null : new PublishedDataSetTriggerModel { PublishedVariables = ToPublishedDataItems(node.TriggeredNodes, true), PublishedEvents = ToPublishedEventItems(node.TriggeredNodes, true), PublishedMethods = ToPublishedMethodItems(node.TriggeredNodes, true) } }).ToList() }; } static PublishedMethodItemsModel ToPublishedMethodItems(IEnumerable opcNodes, bool skipTriggering) { return new PublishedMethodItemsModel { PublishedData = opcNodes.Where(node => node.MethodMetadata != null) .Select(node => new PublishedDataSetMethodModel { Id = node.DataSetFieldId, MethodId = node.Id, Metadata = node.MethodMetadata, // TODO: .Clone() BrowsePath = node.BrowsePath, TypeDefinitionId = node.EventFilter?.TypeDefinitionId, Publishing = node.Topic == null && node.QualityOfService == null ? null : new PublishingQueueSettingsModel { QueueName = node.Topic, RequestedDeliveryGuarantee = node.QualityOfService, Retain = null, Ttl = null }, Triggering = skipTriggering || node.TriggeredNodes == null ? null : new PublishedDataSetTriggerModel { PublishedVariables = ToPublishedDataItems(node.TriggeredNodes, true), PublishedEvents = ToPublishedEventItems(node.TriggeredNodes, true), PublishedMethods = ToPublishedMethodItems(node.TriggeredNodes, true) } }).ToList() }; } } /// /// Adds the credentials from the connection to the published nodes model /// /// /// /// private PublishedNodesEntryModel AddConnectionModel(ConnectionModel? connection, PublishedNodesEntryModel publishedNodesEntryModel) { publishedNodesEntryModel.OpcAuthenticationPassword = null; publishedNodesEntryModel.OpcAuthenticationUsername = null; publishedNodesEntryModel.EncryptedAuthPassword = null; publishedNodesEntryModel.EncryptedAuthUsername = null; var credential = connection?.User; switch (credential?.Type ?? CredentialType.None) { case CredentialType.X509Certificate: case CredentialType.UserName: publishedNodesEntryModel.OpcAuthenticationMode = credential?.Type == CredentialType.X509Certificate ? OpcAuthenticationMode.Certificate : OpcAuthenticationMode.UsernamePassword; Debug.Assert(credential != null); var (user, pw, encrypted) = ToUserNamePasswordCredentialAsync(credential.Value).GetAwaiter().GetResult(); if (encrypted) { publishedNodesEntryModel.EncryptedAuthPassword = pw; publishedNodesEntryModel.EncryptedAuthUsername = user; } else { publishedNodesEntryModel.OpcAuthenticationPassword = pw; publishedNodesEntryModel.OpcAuthenticationUsername = user; } break; case CredentialType.None: publishedNodesEntryModel.OpcAuthenticationMode = OpcAuthenticationMode.Anonymous; break; default: throw new NotSupportedException( $"Credentials of type {credential?.Type} are not supported."); } if (connection != null) { if (connection.Endpoint != null) { publishedNodesEntryModel.EndpointUrl = connection.Endpoint.Url; publishedNodesEntryModel.EndpointSecurityPolicy = connection.Endpoint.SecurityPolicy; if (connection.Endpoint.SecurityMode == SecurityMode.None) { // Fall back to let UseSecurity decide on security (legacy) publishedNodesEntryModel.UseSecurity = false; publishedNodesEntryModel.EndpointSecurityMode = null; } else if (connection.Endpoint.SecurityMode == SecurityMode.NotNone) { // Fall back to let UseSecurity decide on security (legacy) publishedNodesEntryModel.UseSecurity = true; publishedNodesEntryModel.EndpointSecurityMode = null; } else { publishedNodesEntryModel.UseSecurity = null; publishedNodesEntryModel.EndpointSecurityMode = connection.Endpoint.SecurityMode; } } publishedNodesEntryModel.UseReverseConnect = connection.Options.HasFlag(ConnectionOptions.UseReverseConnect) ? true : null; publishedNodesEntryModel.DisableSubscriptionTransfer = connection.Options.HasFlag(ConnectionOptions.NoSubscriptionTransfer) ? true : null; publishedNodesEntryModel.DumpConnectionDiagnostics = connection.Options.HasFlag(ConnectionOptions.DumpDiagnostics) ? true : null; } return publishedNodesEntryModel; async Task<(string? user, string? password, bool encrypted)> ToUserNamePasswordCredentialAsync( UserIdentityModel? credential) { var userString = credential?.User ?? string.Empty; var passwordString = credential?.Password ?? string.Empty; if (_forceCredentialEncryption) { if (_cryptoProvider != null) { try { const string kInitializationVector = "alKGJdfsgidfasdO"; // See previous publisher var userBytes = await _cryptoProvider.EncryptAsync(kInitializationVector, Encoding.UTF8.GetBytes(userString)).ConfigureAwait(false); var passwordBytes = await _cryptoProvider.EncryptAsync(kInitializationVector, Encoding.UTF8.GetBytes(passwordString)).ConfigureAwait(false); return (Convert.ToBase64String(userBytes.Span), Convert.ToBase64String(passwordBytes.Span), true); } catch (Exception ex) { Runtime.FailFast("Attempting to store a credential. " + "Credential encryption is enforced but crypto provider failed to encrypt!", ex); } } Runtime.FailFast("Attempting to store a credential. " + "Credential encryption is enforced but no crypto provider present!", null); } return (userString, passwordString, false); } } /// /// Convert to credential model and take into account backwards compatibility /// by using the crypto provider to decrypt encrypted credentials. /// /// private CredentialModel ToCredential(PublishedNodesEntryModel entry) { switch (entry.OpcAuthenticationMode) { case OpcAuthenticationMode.UsernamePassword: case OpcAuthenticationMode.Certificate: var user = entry.OpcAuthenticationUsername ?? string.Empty; var password = entry.OpcAuthenticationPassword ?? string.Empty; try { const string kInitializationVector = "alKGJdfsgidfasdO"; // See previous publisher if (!string.IsNullOrEmpty(entry.EncryptedAuthUsername) && string.IsNullOrEmpty(user)) { if (_cryptoProvider != null) { var userBytes = _cryptoProvider.DecryptAsync(kInitializationVector, Convert.FromBase64String(entry.EncryptedAuthUsername)) .AsTask().GetAwaiter().GetResult(); user = Encoding.UTF8.GetString(userBytes.Span); } else { const string error = "No crypto provider to decrypt encrypted username in config."; if (_forceCredentialEncryption) { Runtime.FailFast("Credential encryption is enforced! " + error, null); } _logger.CredentialDecryptionError(error); break; } } if (!string.IsNullOrEmpty(entry.EncryptedAuthPassword) && string.IsNullOrEmpty(password)) { if (_cryptoProvider != null) { var passwordBytes = _cryptoProvider.DecryptAsync(kInitializationVector, Convert.FromBase64String(entry.EncryptedAuthPassword)) .AsTask().GetAwaiter().GetResult(); password = Encoding.UTF8.GetString(passwordBytes.Span); } else { const string error = "No crypto provider to decrypt encrypted password in config."; if (_forceCredentialEncryption) { Runtime.FailFast("Credential encryption is enforced! " + error, null); } _logger.CredentialDecryptionError(error); break; } } } catch (Exception ex) { const string error = "Failed to decrypt encrypted username and password in config."; if (_forceCredentialEncryption) { Runtime.FailFast("Credential encryption is enforced! " + error, ex); } // There is no reason we should use the encrypted credential here as plain // text so just use none and move on. _logger.CredentialDecryptionException(ex, error); break; } return new CredentialModel { Type = entry.OpcAuthenticationMode == OpcAuthenticationMode.Certificate ? CredentialType.X509Certificate : CredentialType.UserName, Value = new UserIdentityModel { User = user, Password = password } }; } return new CredentialModel { Type = CredentialType.None }; } private static readonly OpcNodeModel kDummyEntry = new(); private readonly bool _forceCredentialEncryption; private readonly int _scaleTestCount; private readonly int _maxNodesPerDataSet; private readonly bool _noPublishingIntervalGrouping; private readonly IIoTEdgeWorkloadApi? _cryptoProvider; private readonly IJsonSerializer _serializer; private readonly ILogger _logger; } /// /// Source-generated logging extensions for PublishedNodesConverter /// internal static partial class PublishedNodesConverterLogging { private const int EventClass = 1720; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Debug, Message = "Reading and validating published nodes file...")] internal static partial void ReadingPublishedNodesFile(this ILogger logger); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Information, Message = "Read {Count} entry models from published nodes file in {Elapsed}")] internal static partial void ReadPublishedNodesFile(this ILogger logger, int count, TimeSpan elapsed); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Error, Message = "failed to convert the published nodes.")] internal static partial void FailedToConvertPublishedNodes(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Information, Message = "Converted published nodes entry models to jobs in {Elapsed}")] internal static partial void ConvertedPublishedNodes(this ILogger logger, TimeSpan elapsed); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Error, Message = "No node id was configured in the opc node entry - skipping...")] internal static partial void MissingNodeId(this ILogger logger); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Error, Message = "{Error} - not using credential!")] internal static partial void CredentialDecryptionError(this ILogger logger, string error); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Error, Message = "{Error} - not using credential!")] internal static partial void CredentialDecryptionException(this ILogger logger, Exception ex, string error); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/src/Storage/PublishedNodesProvider.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Storage { using Azure.IIoT.OpcUa.Publisher; using Furly.Extensions.Storage; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.Extensions.Primitives; using System; using System.IO; using System.Text; using System.Threading; /// /// Provider for published nodes file. /// public sealed class PublishedNodesProvider : IStorageProvider, IDisposable { /// public event EventHandler? Changed; /// /// Provider of storage for published nodes file. /// /// File provider factory /// Publisher configuration with location /// of published nodes file. /// Logger public PublishedNodesProvider(IFileProviderFactory factory, IOptions options, ILogger logger) { // TODO: Use IFileProvider and IStorageProvider going forward _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _fileMode = options.Value.PublishedNodesFile == null || options.Value.CreatePublishFileIfNotExist == true ? FileMode.OpenOrCreate : FileMode.Open; _fileName = options.Value.PublishedNodesFile ?? PublisherConfig.PublishedNodesFileDefault; var root = Path.GetDirectoryName(_fileName); if (string.IsNullOrWhiteSpace(root)) { root = Environment.CurrentDirectory; } _root = root; _provider = factory.Create(_root); _watch = _provider.Watch(Path.GetFileName(_fileName)); _watch.RegisterChangeCallback(ChangeCallback, this); _lock = new SemaphoreSlim(1, 1); } /// public DateTime GetLastWriteTime() { _lock.Wait(); try { var fileName = Path.GetFileName(_fileName); return _provider.GetFileInfo(fileName).LastModified.UtcDateTime; } finally { _lock.Release(); } } /// public string ReadContent() { _lock.Wait(); try { if (!File.Exists(_fileName)) { return string.Empty; } // Create file only if it is the default file. using var fileStream = new FileStream(_fileName, _fileMode, FileAccess.Read, FileShare.Read); return fileStream.ReadAsString(Encoding.UTF8); } catch (Exception e) { _logger.ReadContentFailed(e, _fileName); throw; } finally { _lock.Release(); } } /// public void WriteContent(string content, bool disableRaisingEvents = false) { _lock.Wait(); try { if (disableRaisingEvents) { _disableRaisingEvents = true; } try { using var fileStream = new FileStream(_fileName, _fileMode, FileAccess.Write, // We will require that there is no other process using the file. FileShare.None); fileStream.SetLength(0); fileStream.Write(Encoding.UTF8.GetBytes(content)); } catch (IOException e) { _logger.UpdateFileRestrictedShare(_fileName); // We will fall back to writing with ReadWrite access. try { using var fileStream = new FileStream(_fileName, _fileMode, FileAccess.Write, // Relaxing requirements. FileShare.ReadWrite); fileStream.SetLength(0); fileStream.Write(Encoding.UTF8.GetBytes(content)); return; } catch (Exception) { _logger.UpdateFileFailed(e, _fileName); } throw; } } finally { // Retore state. if (disableRaisingEvents) { _disableRaisingEvents = false; } _lock.Release(); } } /// public void Dispose() { _lock.Dispose(); } /// /// Register callback /// /// private void ChangeCallback(object? obj) { var currentChangeToken = _watch; _watch = _provider.Watch(Path.GetFileName(_fileName)); _watch.RegisterChangeCallback(ChangeCallback, this); if (!currentChangeToken.HasChanged || _disableRaisingEvents) { _logger.NoRaisingEvent(currentChangeToken.HasChanged); return; } var exists = File.Exists(_fileName); Changed?.Invoke(this, new FileSystemEventArgs(exists ? WatcherChangeTypes.Changed : WatcherChangeTypes.Deleted, _root, Path.GetFileName(_fileName))); } private readonly string _root; private readonly ILogger _logger; private readonly FileMode _fileMode; private readonly string _fileName; private readonly SemaphoreSlim _lock; private readonly IFileProvider _provider; private bool _disableRaisingEvents; private IChangeToken _watch; } /// /// Source-generated logging extensions for PublishedNodesProvider /// internal static partial class PublishedNodesProviderLogging { private const int EventClass = 1740; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Debug, Message = "Failed to read content of published nodes file from \"{Path}\"")] public static partial void ReadContentFailed(this ILogger logger, Exception exception, string path); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Warning, Message = "Failed to update published nodes file at \"{Path}\" with restricted share policies. " + "Please close any other application that uses this file. Falling back to opening it with more relaxed share policies.")] public static partial void UpdateFileRestrictedShare(this ILogger logger, string path); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Error, Message = "Failed to update published nodes file at \"{Path}\"")] public static partial void UpdateFileFailed(this ILogger logger, Exception exception, string path); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Trace, Message = "No raising event while writing ({Changed}).")] public static partial void NoRaisingEvent(this ILogger logger, bool changed); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Azure.IIoT.OpcUa.Publisher.Tests.csproj ================================================  net9.0 aggressive all runtime; build; native; contentfiles; analyzers; buildtransitive all runtime; build; native; contentfiles; analyzers Always ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/GlobalSuppressions.cs ================================================ // This file is used by Code Analysis to maintain SuppressMessage // attributes that are applied to this project. // Project-level suppressions either have no target or are given // a specific target and scoped to a namespace, type, member, etc. using System.Diagnostics.CodeAnalysis; [assembly: SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "xunit")] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Logging.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests { using Microsoft.Extensions.Logging; using Neovolve.Logging.Xunit; internal static class Logging { /// /// Default level /// public static LogLevel Level => LogLevel.Warning; /// /// Configuration /// public static LoggingConfig Config => new() { LogLevel = Level }; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Model/MonitoredItemModelTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Stack.Models { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using System; using System.Collections.Generic; using Xunit; public class MonitoredItemModelTests { private readonly BaseMonitoredItemModel _dataModel = new DataMonitoredItemModel { StartNodeId = "DataStartNodeId", AggregateFilter = new AggregateFilterModel { AggregateConfiguration = new AggregateConfigurationModel { PercentDataBad = 10, PercentDataGood = 20, TreatUncertainAsBad = false, UseSlopedExtrapolation = false }, AggregateTypeId = "DataAggregateTypeId", ProcessingInterval = TimeSpan.FromMilliseconds(25), StartTime = DateTime.Now }, DataSetClassFieldId = Guid.NewGuid(), SamplingInterval = TimeSpan.FromMilliseconds(5000), QueueSize = 10, AttributeId = NodeAttribute.DataType, DataChangeFilter = new DataChangeFilterModel { DataChangeTrigger = DataChangeTriggerType.StatusValue, DeadbandType = DeadbandType.Absolute, DeadbandValue = 45 }, DiscardNew = true, SkipFirst = true, DataSetFieldName = "DataSetFieldName", HeartbeatInterval = TimeSpan.FromMilliseconds(30000), DataSetFieldId = "DataSetFieldId", IndexRange = "DataIndexRange", MonitoringMode = MonitoringMode.Sampling, RelativePath = new string[] { "DataRelativePath" } }; private readonly BaseMonitoredItemModel _eventModel = new EventMonitoredItemModel { StartNodeId = "EventStartNodeId", QueueSize = 10, AttributeId = NodeAttribute.DataType, DiscardNew = true, DataSetFieldName = "EventDataSetFieldName", DataSetFieldId = "DataSetFieldId", MonitoringMode = MonitoringMode.Sampling, RelativePath = new string[] { "EventRelativePath" }, EventFilter = new EventFilterModel { SelectClauses = new List { new() { AttributeId = NodeAttribute.DataType, BrowsePath = new string[] { "EventBrowsePath "}, IndexRange = "SelectClauseIndexRange", TypeDefinitionId = "SelectClauseTypeDefinitionId", DisplayName = "SelectClauseDisplayName", DataSetClassFieldId = Guid.NewGuid() } } } }; [Fact] public void CloneDataModelTest() { var clone = _dataModel with { }; // Should be equal Assert.IsType(clone); Assert.True(clone.Equals(_dataModel)); } [Fact] public void CompareDataModelTestShouldSucceed() { var clone = _dataModel with { }; // Should be equal Assert.IsType(clone); Assert.True(clone.Equals(_dataModel)); } [Fact] public void CompareDataModelTestShouldFail() { var clone = _dataModel with { QueueSize = 47000 }; // Should not be equal Assert.IsType(clone); Assert.False(clone.Equals(_dataModel)); } [Fact] public void CloneEventModelTest() { var clone = _eventModel with { }; // Should be equal Assert.IsType(clone); Assert.True(clone.Equals(_eventModel)); } [Fact] public void CompareEventModelTestShouldSucceed() { var clone = _eventModel with { }; // Should be equal Assert.IsType(clone); Assert.True(clone.Equals(_eventModel)); } [Fact] public void CompareEventModelTestShouldFail() { var clone = _eventModel with { StartNodeId = "SomethingElse" }; // Should not be equal Assert.IsType(clone); Assert.False(clone.Equals(_eventModel)); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Parser/ContentFilterParserTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ #nullable enable namespace Azure.IIoT.OpcUa.Publisher.Parser.Tests { using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Json; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class ContentFilterParserTests { private readonly IJsonSerializer _serializer = new DefaultJsonSerializer(); private readonly ITestOutputHelper _output; public ContentFilterParserTests(ITestOutputHelper output) { _output = output; } [Fact] public async Task AnnexBPart1Example1Async() { // (((AType.A = 5) or InList(BType.B, 3,5,7)) and BaseObjectType.displayName LIKE "Main%") const string query = @" select * from BaseObjectType, AType, BType where ((AType/A = 5) or BType/B in (3,5,7)) and BaseObjectType.displayName like 'Main%' "; var parser = new FilterQueryParser(_serializer); var context = new TestParserContext { new IdentifierMetaData("AType", new [] { "/A" }, "A"), new IdentifierMetaData("BType", new [] { "/B" }, "B") }; var filter = await parser.ParseEventFilterAsync(query, context, default); Assert.NotNull(filter); Assert.NotNull(filter.SelectClauses); Assert.NotEmpty(filter.SelectClauses); Assert.NotNull(filter.WhereClause); var expectedWhere = new ContentFilterModel { Elements = new[] { new ContentFilterElementModel { FilterOperator = FilterOperatorType.And, FilterOperands = new[] { new FilterOperandModel { Index = 1 }, new FilterOperandModel { Index = 2 } } }, new ContentFilterElementModel { FilterOperator = FilterOperatorType.Like, FilterOperands = new[] { new FilterOperandModel { NodeId = "i=58", BrowsePath = Array.Empty(), AttributeId = NodeAttribute.DisplayName }, new FilterOperandModel { Value = "Main%" } } }, new ContentFilterElementModel { FilterOperator = FilterOperatorType.Or, FilterOperands = new[] { new FilterOperandModel { Index = 3 }, new FilterOperandModel { Index = 4 } } }, new ContentFilterElementModel { FilterOperator = FilterOperatorType.InList, FilterOperands = new[] { new FilterOperandModel { NodeId = "BType", BrowsePath = new [] { "/B" }, AttributeId = NodeAttribute.Value }, new FilterOperandModel { Value = 3 }, new FilterOperandModel { Value = 5 }, new FilterOperandModel { Value = 7 } } }, new ContentFilterElementModel { FilterOperator = FilterOperatorType.Equals, FilterOperands = new[] { new FilterOperandModel { NodeId = "AType", BrowsePath = new [] { "/A" }, AttributeId = NodeAttribute.Value }, new FilterOperandModel { Value = 5 } } } } }; var evtFilter = _serializer.SerializeToString(filter.WhereClause); var expFilter = _serializer.SerializeToString(expectedWhere); Assert.Equal(expFilter, evtFilter); } [Fact] public async Task AnnexBPart1Example2Async() { const string query = @" select * from SystemEventType, Area1, Area2 where oftype SystemEventType and (inview Area1 or inview Area2) "; var parser = new FilterQueryParser(_serializer); var context = new TestParserContext { new IdentifierMetaData(Opc.Ua.ObjectTypeIds.SystemEventType.ToString(), new [] { "/A" }, "A"), new IdentifierMetaData(Opc.Ua.ObjectTypeIds.SystemEventType.ToString(), new [] { "/B" }, "B") }; var filter = await parser.ParseEventFilterAsync(query, context, default); Assert.NotNull(filter); Assert.NotNull(filter.SelectClauses); Assert.NotEmpty(filter.SelectClauses); Assert.NotNull(filter.WhereClause); var expectedWhere = new ContentFilterModel { Elements = new[] { new ContentFilterElementModel { FilterOperator = FilterOperatorType.And, FilterOperands = new[] { new FilterOperandModel { Index = 1 }, new FilterOperandModel { Index = 4 } } }, new ContentFilterElementModel { FilterOperator = FilterOperatorType.Or, FilterOperands = new[] { new FilterOperandModel { Index = 2 }, new FilterOperandModel { Index = 3 } } }, new ContentFilterElementModel { FilterOperator = FilterOperatorType.InView, FilterOperands = new[] { new FilterOperandModel { NodeId = "Area2", BrowsePath = Array.Empty(), AttributeId = NodeAttribute.NodeId } } }, new ContentFilterElementModel { FilterOperator = FilterOperatorType.InView, FilterOperands = new[] { new FilterOperandModel { NodeId = "Area1", BrowsePath = Array.Empty(), AttributeId = NodeAttribute.NodeId } } }, new ContentFilterElementModel { FilterOperator = FilterOperatorType.OfType, FilterOperands = new [] { new FilterOperandModel { // Literal Value = Opc.Ua.ObjectTypeIds.SystemEventType.ToString(), DataType = "NodeId" } } } } }; var evtFilter = _serializer.SerializeToString(filter.WhereClause); var expFilter = _serializer.SerializeToString(expectedWhere); Assert.Equal(expFilter, evtFilter); } [Fact] public async Task AnnexBPart2Example1Async() { const string query1 = @" select PersonType/LastName, AnimalType/Name, ScheduleType/Period from PersonType, AnimalType, ScheduleType, HasSchedule, HasPet where PersonType relatedTo ( AnimalType relatedTo (ScheduleType, HasSchedule, 1), HasPet, 1) "; var parser = new FilterQueryParser(_serializer); var context = new TestParserContext { new IdentifierMetaData("PersonType", new [] { "/LastName" }, "LastName"), new IdentifierMetaData("HasPet", Array.Empty(), "HasPet"), new IdentifierMetaData("AnimalType", new [] { "/Name" }, "Name"), new IdentifierMetaData("HasSchedule", Array.Empty(), "HasSchedule"), new IdentifierMetaData("ScheduleType", new [] { "/Period" }, "Period") }; var filter = await parser.ParseEventFilterAsync(query1, context, default); _output.WriteLine(_serializer.SerializeToString(filter, SerializeOption.Indented)); Assert.NotNull(filter); Assert.NotNull(filter.SelectClauses); Assert.NotEmpty(filter.SelectClauses); Assert.NotNull(filter.WhereClause); var expectedWhere = new ContentFilterModel { Elements = new[] { new ContentFilterElementModel { FilterOperator = FilterOperatorType.RelatedTo, FilterOperands = new[] { new FilterOperandModel { NodeId = "PersonType", BrowsePath = Array.Empty(), AttributeId = NodeAttribute.NodeId }, new FilterOperandModel { Index = 1 }, new FilterOperandModel { NodeId = "HasPet", BrowsePath = Array.Empty(), AttributeId = NodeAttribute.NodeId }, new FilterOperandModel { Value = 1 } } }, new ContentFilterElementModel { FilterOperator = FilterOperatorType.RelatedTo, FilterOperands = new[] { new FilterOperandModel { NodeId = "AnimalType", BrowsePath = Array.Empty(), AttributeId = NodeAttribute.NodeId }, new FilterOperandModel { NodeId = "ScheduleType", BrowsePath = Array.Empty(), AttributeId = NodeAttribute.NodeId }, new FilterOperandModel { NodeId = "HasSchedule", BrowsePath = Array.Empty(), AttributeId = NodeAttribute.NodeId }, new FilterOperandModel { Value = 1 } } } } }; var evtFilter = _serializer.SerializeToString(filter.WhereClause); var expFilter = _serializer.SerializeToString(expectedWhere); Assert.Equal(expFilter, evtFilter); const string query2 = @" select /LastName, /Name, /Period from PersonType, AnimalType, ScheduleType, HasSchedule, HasPet where PersonType relatedTo ( AnimalType relatedTo (ScheduleType, HasSchedule, 1), HasPet, 1) "; var filter2 = await parser.ParseEventFilterAsync(query2, context, default); var filterJson1 = _serializer.SerializeToString(filter); var filterJson2 = _serializer.SerializeToString(filter2); Assert.Equal(filterJson1, filterJson2); } [Fact] public async Task AnnexBPart2Example2Async() { const string query = @" select /LastName, AnimalType/Name from PersonType, HasChild, CatType AnimalType, HasSchedule, FeedingScheduleType where PersonType relatedTo (PersonType, HasChild, 1) or CatType relatedTo (FeedingScheduleType, HasSchedule, 1) "; var parser = new FilterQueryParser(_serializer); var context = new TestParserContext { new IdentifierMetaData("PersonType", new [] { "/LastName" }, "LastName"), new IdentifierMetaData("HasPet", Array.Empty(), "HasPet"), new IdentifierMetaData("AnimalType", new [] { "/Name" }, "Name"), new IdentifierMetaData("CatType", new [] { "/Name" }, "Name"), new IdentifierMetaData("HasSchedule", Array.Empty(), "HasSchedule"), new IdentifierMetaData("FeedingScheduleType",new [] { "/Period" }, "Period") }; var filter = await parser.ParseEventFilterAsync(query, context, default); _output.WriteLine(_serializer.SerializeToString(filter, SerializeOption.Indented)); Assert.NotNull(filter); Assert.NotNull(filter.SelectClauses); Assert.NotEmpty(filter.SelectClauses); Assert.NotNull(filter.WhereClause); var expectedWhere = new ContentFilterModel { Elements = new[] { new ContentFilterElementModel { FilterOperator = FilterOperatorType.Or, FilterOperands = new[] { new FilterOperandModel { Index = 1 }, new FilterOperandModel { Index = 2 } } }, new ContentFilterElementModel { FilterOperator = FilterOperatorType.RelatedTo, FilterOperands = new[] { new FilterOperandModel { NodeId = "CatType", BrowsePath = Array.Empty(), AttributeId = NodeAttribute.NodeId }, new FilterOperandModel { NodeId = "FeedingScheduleType", BrowsePath = Array.Empty(), AttributeId = NodeAttribute.NodeId }, new FilterOperandModel { NodeId = "HasSchedule", BrowsePath = Array.Empty(), AttributeId = NodeAttribute.NodeId }, new FilterOperandModel { Value = 1 } } }, new ContentFilterElementModel { FilterOperator = FilterOperatorType.RelatedTo, FilterOperands = new[] { new FilterOperandModel { NodeId = "PersonType", BrowsePath = Array.Empty(), AttributeId = NodeAttribute.NodeId }, new FilterOperandModel { NodeId = "PersonType", BrowsePath = Array.Empty(), AttributeId = NodeAttribute.NodeId }, new FilterOperandModel { NodeId = "HasChild", BrowsePath = Array.Empty(), AttributeId = NodeAttribute.NodeId }, new FilterOperandModel { Value = 1 } } } } }; var evtFilter = _serializer.SerializeToString(filter.WhereClause); var expFilter = _serializer.SerializeToString(expectedWhere); Assert.Equal(expFilter, evtFilter); } [Fact] public async Task AnnexBPart2Example3Async() { // Get PersonType.LastName, AnimalType.Name, ScheduleType.Period // where a person has a pet and the animal has a feeding schedule // and the person has a Zipcode = ‘02138’ // and (the Schedule.Period is Daily or Hourly) // and Amount to feed is > 10. const string query = @" select PersonType/LastName, AnimalType/Name, ScheduleType/Period from PersonType, AnimalType, ScheduleType, HasSchedule, HasPet, Int32 where PersonType relatedTo (AnimalType relatedTo (ScheduleType, HasSchedule, 1), HasPet, 1) and PersonType/Zipcode = '02138' and (PersonTypeAnimalTypeFeedingSchedule/Period = 'Daily' or PersonTypeAnimalTypeFeedingSchedule/Period = 'Hourly') and PersonTypeAnimalTypeFeedingSchedule/Amount > (10 cast(Int32)) "; var parser = new FilterQueryParser(_serializer); var context = new TestParserContext { new IdentifierMetaData("PersonType", new [] { "/LastName" }, "LastName"), new IdentifierMetaData("PersonType", new [] { "/Zipcode" }, "Zipcode"), new IdentifierMetaData("PersonType", new [] { "AnimalType", "FeedingSchedule", "/Period" }, "Period"), new IdentifierMetaData("PersonType", new [] { "AnimalType", "FeedingSchedule", "/Amount" }, "Amount"), new IdentifierMetaData("HasPet", Array.Empty(), "HasPet"), new IdentifierMetaData("AnimalType", new [] { "/Name" }, "Name"), new IdentifierMetaData("Int32", Array.Empty(), "Int32"), new IdentifierMetaData("HasSchedule", Array.Empty(), "HasSchedule"), new IdentifierMetaData("ScheduleType", new [] { "/Period" }, "Period") }; var filter = await parser.ParseEventFilterAsync(query, context, default); _output.WriteLine(_serializer.SerializeToString(filter, SerializeOption.Indented)); Assert.NotNull(filter); Assert.NotNull(filter.SelectClauses); Assert.NotEmpty(filter.SelectClauses); Assert.NotNull(filter.WhereClause); } [Fact] public async Task AnnexBPart2Example4Async() { // Get PersonType.LastName where a person has a child who has a pet. const string query = @" select PersonType/LastName from PersonType, AnimalType, HasPet, HasChild where PersonType relatedTo (PersonType relatedTo (AnimalType, HasPet, 1), HasChild, 1) "; var parser = new FilterQueryParser(_serializer); var context = new TestParserContext { new IdentifierMetaData("PersonType", new [] { "/LastName" }, "LastName"), new IdentifierMetaData("HasPet", Array.Empty(), "HasPet"), new IdentifierMetaData("AnimalType", new [] { "/Name" }, "Name"), new IdentifierMetaData("HasChild", Array.Empty(), "HasChild") }; var filter = await parser.ParseEventFilterAsync(query, context, default); _output.WriteLine(_serializer.SerializeToString(filter, SerializeOption.Indented)); Assert.NotNull(filter); Assert.NotNull(filter.SelectClauses); Assert.NotEmpty(filter.SelectClauses); Assert.NotNull(filter.WhereClause); var expectedWhere = new ContentFilterModel { Elements = new[] { new ContentFilterElementModel { FilterOperator = FilterOperatorType.RelatedTo, FilterOperands = new[] { new FilterOperandModel { NodeId = "PersonType", BrowsePath = Array.Empty(), AttributeId = NodeAttribute.NodeId }, new FilterOperandModel { Index = 1 }, new FilterOperandModel { NodeId = "HasChild", BrowsePath = Array.Empty(), AttributeId = NodeAttribute.NodeId }, new FilterOperandModel { Value = 1 } } }, new ContentFilterElementModel { FilterOperator = FilterOperatorType.RelatedTo, FilterOperands = new[] { new FilterOperandModel { NodeId = "PersonType", BrowsePath = Array.Empty(), AttributeId = NodeAttribute.NodeId }, new FilterOperandModel { NodeId = "AnimalType", BrowsePath = Array.Empty(), AttributeId = NodeAttribute.NodeId }, new FilterOperandModel { NodeId = "HasPet", BrowsePath = Array.Empty(), AttributeId = NodeAttribute.NodeId }, new FilterOperandModel { Value = 1 } } } } }; var evtFilter = _serializer.SerializeToString(filter.WhereClause); var expFilter = _serializer.SerializeToString(expectedWhere); Assert.Equal(expFilter, evtFilter); } [Fact] public async Task AnnexBPart2Example5Async() { // Get the last names of children that have the same first name as a parent of theirs const string query = @" select parent/LastName from PersonType parent, PersonType child, HasChild where parent relatedTo (child, HasChild, 1) and parent/FirstName = child/FirstName "; var parser = new FilterQueryParser(_serializer); var context = new TestParserContext { new IdentifierMetaData("PersonType", new [] { "/LastName" }, "LastName"), new IdentifierMetaData("PersonType", new [] { "/FirstName" }, "FirstName"), new IdentifierMetaData("HasChild", Array.Empty(), "HasChild") }; var filter = await parser.ParseEventFilterAsync(query, context, default); _output.WriteLine(_serializer.SerializeToString(filter, SerializeOption.Indented)); Assert.NotNull(filter); Assert.NotNull(filter.SelectClauses); Assert.NotEmpty(filter.SelectClauses); Assert.NotNull(filter.WhereClause); var expectedWhere = new ContentFilterModel { Elements = new[] { new ContentFilterElementModel { FilterOperator = FilterOperatorType.And, FilterOperands = new[] { new FilterOperandModel { Index = 1 }, new FilterOperandModel { Index = 2 } } }, new ContentFilterElementModel { FilterOperator = FilterOperatorType.Equals, FilterOperands = new[] { new FilterOperandModel { NodeId = "PersonType", BrowsePath = new [] { "/FirstName" }, AttributeId = NodeAttribute.Value, Alias = "parent" }, new FilterOperandModel { NodeId = "PersonType", BrowsePath = new [] { "/FirstName" }, AttributeId = NodeAttribute.Value, Alias = "child" } } }, new ContentFilterElementModel { FilterOperator = FilterOperatorType.RelatedTo, FilterOperands = new[] { new FilterOperandModel { NodeId = "PersonType", BrowsePath = Array.Empty(), AttributeId = NodeAttribute.NodeId, Alias = "parent" }, new FilterOperandModel { NodeId = "PersonType", BrowsePath = Array.Empty(), AttributeId = NodeAttribute.NodeId, Alias = "child" }, new FilterOperandModel { NodeId = "HasChild", BrowsePath = Array.Empty(), AttributeId = NodeAttribute.NodeId }, new FilterOperandModel { Value = 1 } } } } }; var evtFilter = _serializer.SerializeToString(filter.WhereClause); var expFilter = _serializer.SerializeToString(expectedWhere); Assert.Equal(expFilter, evtFilter); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Parser/EventFilterParserTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ #nullable enable namespace Azure.IIoT.OpcUa.Publisher.Parser.Tests { using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Json; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class EventFilterParserTests { private readonly IJsonSerializer _serializer = new DefaultJsonSerializer(); private readonly ITestOutputHelper _output; public EventFilterParserTests(ITestOutputHelper output) { _output = output; } [Theory] [InlineData("SELECT *")] [InlineData("SELECT * FROM BaseEventType")] [InlineData("SELECT * FROM ns0:BaseEventType")] public async Task SimpleStatementParsingNoPrefixNoWhereTestsAsync(string query) { var parser = new FilterQueryParser(_serializer); var context = new TestParserContext { new IdentifierMetaData(Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), new[] { "/Severity" }, "Severity"), new IdentifierMetaData(Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), new[] { "/SourceNode" }, "SourceNode"), new IdentifierMetaData(Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), new[] { "/SourceName" }, "SourceName"), new IdentifierMetaData(Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), new[] { "/LocalTime" }, "LocalTime") }; var eventFilter = await parser.ParseEventFilterAsync(query, context, default); Assert.NotNull(eventFilter); Assert.NotNull(eventFilter.SelectClauses); Assert.NotEmpty(eventFilter.SelectClauses); Assert.Null(eventFilter.WhereClause); _output.WriteLine(_serializer.SerializeToString(eventFilter, SerializeOption.Indented)); } [Theory] [InlineData("SELECT * FROM BaseEventType " + "WHERE /Severity > 5 AND /SourceName = 'SouthMotor'")] [InlineData("SELECT * " + "WHERE /Severity > 5 AND /SourceName = 'SouthMotor'")] [InlineData("SELECT /Severity, /SourceNode FROM BaseEventType " + "WHERE !(/Severity <= 5 OR /SourceName == 'SouthMotor')")] [InlineData("SELECT /LocalTime FROM BaseEventType " + "WHERE NOT ISNULL /LocalTime " + "AND (/Severity <> 5 OR /SourceName != 'SouthMotor')")] [InlineData("SELECT E/Severity, E/SourceNode FROM BaseEventType E " + "WHERE !(E/Severity <= 5 OR E/SourceName == 'SouthMotor')")] [InlineData("SELECT E/0:Severity, E/SourceNode FROM ns0:BaseEventType E " + "WHERE NOT (E/0:Severity <= 5 OR E/0:SourceName == 'SouthMotor')")] [InlineData("SELECT /0:LocalTime FROM ns0:BaseEventType " + "WHERE NOT ISNULL /0:LocalTime " + "AND (/0:Severity <> 5 OR /0:SourceName != 'SouthMotor')")] [InlineData("SELECT E/Severity, /SourceNode FROM BaseEventType E " + "WHERE !(E/Severity <= 5 OR E/SourceName == 'SouthMotor')")] [InlineData("SELECT E/0:Severity, /SourceNode FROM ns0:BaseEventType E " + "WHERE NOT (E/0:Severity <= 5 OR E/0:SourceName == 'SouthMotor')")] public async Task SimpleStatementParsingNoPrefixTestsAsync(string query) { var parser = new FilterQueryParser(_serializer); var context = new TestParserContext { new IdentifierMetaData(Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), new[] { "/Severity" }, "Severity"), new IdentifierMetaData(Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), new[] { "/SourceNode" }, "SourceNode"), new IdentifierMetaData(Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), new[] { "/SourceName" }, "SourceName"), new IdentifierMetaData(Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), new[] { "/LocalTime" }, "LocalTime") }; var eventFilter = await parser.ParseEventFilterAsync(query, context, default); Assert.NotNull(eventFilter); Assert.NotNull(eventFilter.SelectClauses); Assert.NotEmpty(eventFilter.SelectClauses); Assert.NotNull(eventFilter.WhereClause); var where = eventFilter.WhereClause!.Elements; Assert.NotNull(where); Assert.NotEmpty(where); _output.WriteLine(_serializer.SerializeToString(eventFilter, SerializeOption.Indented)); } [Theory] [InlineData("PREFIX ua SELECT * FROM ua:BaseEventType " + "WHERE /ua:Severity > 5 AND /ua:SourceName = 'SouthMotor'")] [InlineData("PREFIX ua " + "SELECT /ua:Severity, /ua:SourceNode FROM ua:BaseEventType " + "WHERE !(/ua:Severity <= 5 OR /ua:SourceName == 'SouthMotor')")] [InlineData("PREFIX ua PREFIX f " + "SELECT /f:LocalTime FROM ua:BaseEventType " + "WHERE NOT ISNULL /f:LocalTime " + "AND (/ua:Severity <> 5 OR /ua:SourceName != 'SouthMotor')")] [InlineData("PREFIX ua PREFIX f " + "SELECT E/ua:Severity, E/ua:SourceNode FROM ua:BaseEventType E " + "WHERE !(E/ua:Severity <= 5 OR E/ua:SourceName == 'SouthMotor')")] public async Task SimpleStatementParsingTestsAsync(string query) { var parser = new FilterQueryParser(_serializer); var context = new TestParserContext { new IdentifierMetaData("http://microsoft/ua#BaseEventType", new[] { "/[http://microsoft/ua#Severity]" }, "Severity"), new IdentifierMetaData("http://microsoft/ua#BaseEventType", new[] { "/[http://microsoft/ua#SourceNode]" }, "SourceNode"), new IdentifierMetaData("http://microsoft/ua#BaseEventType", new[] { "/[http://microsoft/ua#SourceName]" }, "SourceName"), new IdentifierMetaData("http://microsoft/ua#BaseEventType", new[] { "/[http://microsoft/f#LocalTime]" }, "LocalTime") }; var eventFilter = await parser.ParseEventFilterAsync(query, context, default); Assert.NotNull(eventFilter); Assert.NotNull(eventFilter.SelectClauses); Assert.NotEmpty(eventFilter.SelectClauses); Assert.NotNull(eventFilter.WhereClause); var where = eventFilter.WhereClause!.Elements; Assert.NotNull(where); Assert.NotEmpty(where); _output.WriteLine(_serializer.SerializeToString(eventFilter, SerializeOption.Indented)); } [Theory] [InlineData("SELECT * FROM ´http://microsoft/ua#BaseEventType´ " + "WHERE ´/[http://microsoft/ua#Severity]´ > 5 " + "AND ´/[http://microsoft/ua#SourceName]´ = 'SouthMotor'")] [InlineData("SELECT ´E/[http://microsoft/ua#Severity]´, ´E/[http://microsoft/ua#SourceNode]´ " + "FROM ´http://microsoft/ua#BaseEventType´ E " + "WHERE !(´E/[http://microsoft/ua#Severity]´ <= 5 " + " OR ´E/[http://microsoft/ua#SourceName]´ == 'SouthMotor')")] public async Task SimpleStatementParsingTestsInlineNamespacesAsync(string query) { var parser = new FilterQueryParser(_serializer); var context = new TestParserContext { new IdentifierMetaData("http://microsoft/ua#BaseEventType", new[] { "/[http://microsoft/ua#Severity]" }, "Severity"), new IdentifierMetaData("http://microsoft/ua#BaseEventType", new[] { "/[http://microsoft/ua#SourceNode]" }, "SourceNode"), new IdentifierMetaData("http://microsoft/ua#BaseEventType", new[] { "/[http://microsoft/ua#SourceName]" }, "SourceName"), new IdentifierMetaData("http://microsoft/ua#BaseEventType", new[] { "/[http://microsoft/f#LocalTime]" }, "LocalTime") }; var eventFilter = await parser.ParseEventFilterAsync(query, context, default); Assert.NotNull(eventFilter); Assert.NotNull(eventFilter.SelectClauses); Assert.NotEmpty(eventFilter.SelectClauses); Assert.NotNull(eventFilter.WhereClause); var where = eventFilter.WhereClause!.Elements; Assert.NotNull(where); Assert.NotEmpty(where); _output.WriteLine(_serializer.SerializeToString(eventFilter, SerializeOption.Indented)); } [Theory] [InlineData("SELECT")] [InlineData("SELECT " + "WHERE /Severity > 5 AND /SourceName = 'SouthMotor'")] [InlineData("FROM BaseEventType")] [InlineData("SELECT * FROM 0:BaseEventType")] [InlineData("SELECT * FROM BaseEventType " + "WHERE /ua:Severity > 5 AND /SourceName = 'SouthMotor'")] [InlineData("PREFIX ua f SELECT * FROM BaseEventType " + "WHERE /ua:Severity > 5 AND /ub:SourceName = 'SouthMotor'")] [InlineData("SELECT * " + "WHERE /Severity > 5 NAND /SourceName = 'SouthMotor'")] public async Task SimpleStatementParsingFailsTestsAsync(string query) { var parser = new FilterQueryParser(_serializer); var context = new TestParserContext { new IdentifierMetaData(Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), new[] { "/Severity" }, "Severity"), new IdentifierMetaData(Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), new[] { "/SourceNode" }, "SourceNode"), new IdentifierMetaData(Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), new[] { "/SourceName" }, "SourceName"), new IdentifierMetaData(Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), new[] { "/LocalTime" }, "LocalTime") }; await Assert.ThrowsAsync( () => parser.ParseEventFilterAsync(query, context, default)); } [Fact] public async Task SimpleStatementTest2Async() { const string query = "SELECT * FROM BaseEventType WHERE /Severity > 5 AND /SourceName = 'SouthMotor'"; var parser = new FilterQueryParser(_serializer); var context = new TestParserContext { new IdentifierMetaData(Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), new[] { "/Severity" }, "Severity"), new IdentifierMetaData(Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), new[] { "/SourceNode" }, "SourceNode"), new IdentifierMetaData(Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), new[] { "/SourceName" }, "SourceName"), new IdentifierMetaData(Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), new[] { "/LocalTime" }, "LocalTime") }; var eventFilter = await parser.ParseEventFilterAsync(query, context, default); Assert.NotNull(eventFilter); Assert.NotNull(eventFilter.SelectClauses); Assert.NotEmpty(eventFilter.SelectClauses); Assert.NotNull(eventFilter.WhereClause); var where = eventFilter.WhereClause!.Elements; Assert.NotNull(where); Assert.NotEmpty(where); _output.WriteLine(_serializer.SerializeToString(eventFilter, SerializeOption.Indented)); } [Fact] public async Task SimpleStatementTest3Async() { const string query = "SELECT * FROM BaseEventType WHERE /Severity > 5 AND /SourceName = 'SouthMotor'"; var parser = new FilterQueryParser(_serializer); var context = new TestParserContext { new IdentifierMetaData(Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), new[] { "/Severity" }, "Severity"), new IdentifierMetaData(Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), new[] { "/SourceNode" }, "SourceNode"), new IdentifierMetaData(Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), new[] { "/SourceName" }, "SourceName"), new IdentifierMetaData(Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), new[] { "/LocalTime" }, "LocalTime") }; var eventFilter = await parser.ParseEventFilterAsync(query, context, default); Assert.NotNull(eventFilter); Assert.NotNull(eventFilter.SelectClauses); Assert.NotEmpty(eventFilter.SelectClauses); Assert.NotNull(eventFilter.WhereClause); var where = eventFilter.WhereClause!.Elements; Assert.NotNull(where); Assert.NotEmpty(where); _output.WriteLine(_serializer.SerializeToString(eventFilter, SerializeOption.Indented)); } [Fact] public async Task SimpleStatementTest4Async() { const string query = @" PREFIX t http://test/# SELECT * FROM BaseEventType WHERE (/Severity > 5 AND /Severity < 10) OR /SourceNode IN('t:i=1544'^^NodeId, 't:i=1545'^^NodeId)"; var parser = new FilterQueryParser(_serializer); var context = new TestParserContext { new IdentifierMetaData(Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), new[] { "/Severity" }, "Severity"), new IdentifierMetaData(Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), new[] { "/SourceNode" }, "SourceNode"), new IdentifierMetaData(Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), new[] { "/SourceName" }, "SourceName"), new IdentifierMetaData(Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), new[] { "/LocalTime" }, "LocalTime") }; var eventFilter = await parser.ParseEventFilterAsync(query, context, default); Assert.NotNull(eventFilter); Assert.NotNull(eventFilter.SelectClauses); Assert.NotEmpty(eventFilter.SelectClauses); Assert.NotNull(eventFilter.WhereClause); var where = eventFilter.WhereClause!.Elements; Assert.NotNull(where); Assert.NotEmpty(where); _output.WriteLine(_serializer.SerializeToString(eventFilter, SerializeOption.Indented)); } [Fact] public async Task AlarmsTestFilterTestAsync() { var parser = new FilterQueryParser(_serializer); var context = new TestParserContext { new IdentifierMetaData("i=2041", new[] { "/Severity" }, "Severity"), new IdentifierMetaData("i=2041", new[] { "/SourceNode" }, "SourceNode"), new IdentifierMetaData("i=10751", new[] { "/Additional" }, "Additional") }; const string query1 = @" PREFIX ac SELECT * FROM i=10751, i=2041 WHERE OFTYPE i=10751 AND /SourceNode IN ('ac:s=1%3aMetals%2fSouthMotor'^^NodeId) "; var filter1 = await parser.ParseEventFilterAsync(query1, context, default); // Test with default aliasing const string query2 = @" PREFIX ac SELECT /Additional, /Severity, /SourceNode FROM TripAlarmType, BaseEventType WHERE OFTYPE TripAlarmType AND /SourceNode IN ('ac:s=1%3aMetals%2fSouthMotor'^^NodeId) "; var filter2 = await parser.ParseEventFilterAsync(query2, context, default); var whereExpected = new ContentFilterModel { Elements = new[] { new ContentFilterElementModel // Index 0 { FilterOperator = FilterOperatorType.And, FilterOperands = new [] { // Filter element indexes new FilterOperandModel { Index = 1 }, new FilterOperandModel { Index = 2 } } }, new ContentFilterElementModel // Index 1 { FilterOperator = FilterOperatorType.InList, FilterOperands = new [] { // Source node property of base event type should be ... new FilterOperandModel { // Simple attribute AttributeId = NodeAttribute.Value, // Note: Default namespace which we omit NodeId = Opc.Ua.ObjectTypeIds.BaseEventType.ToString(), BrowsePath = new[] { "/" + Opc.Ua.BrowseNames.SourceNode } }, // ...In the following list new FilterOperandModel { // Literal Value = "http://opcfoundation.org/AlarmCondition#s=1%3aMetals%2fSouthMotor", DataType = "NodeId" } } }, new ContentFilterElementModel // Index 2 { FilterOperator = FilterOperatorType.OfType, FilterOperands = new[] { new FilterOperandModel { // Literal Value = Opc.Ua.ObjectTypeIds.TripAlarmType.ToString(), DataType = "NodeId" } } } } }; Assert.NotNull(filter1); Assert.NotNull(filter1.SelectClauses); Assert.Equal(3, filter1.SelectClauses!.Count); Assert.NotNull(filter1.WhereClause); var f1 = _serializer.SerializeToString(filter1); var f2 = _serializer.SerializeToString(filter2); Assert.Equal(f1, f2); var evtFilter = _serializer.SerializeToString(filter1.WhereClause); var expFilter = _serializer.SerializeToString(whereExpected); Assert.Equal(expFilter, evtFilter); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Parser/TestParserContext.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ #nullable enable namespace Azure.IIoT.OpcUa.Publisher.Parser.Tests { using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; public sealed class TestParserContext : List, IFilterParserContext { public Task> GetIdentifiersAsync(string typeId, CancellationToken ct) { return Task.FromResult(this.Where(id => id.TypeDefinitionId == typeId)); } public bool TryGetNamespaceUri(uint index, out string? namespaceUri) { if (index == 0) { namespaceUri = string.Empty; return true; } namespaceUri = null; return false; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Properties/AssemblyInfo.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ #if !DEBUG using Xunit; [assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly, MaxParallelThreads = 4)] #endif ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Publisher/empty_pn.json ================================================ [] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Publisher/pn_2.5_legacy.json ================================================ [ { "EndpointUrl": "opc.tcp://opcplc:50000", "UseSecurity": false, "OpcAuthenticationMode": "UsernamePassword", "OpcAuthenticationUsername": "username", "OpcAuthenticationPassword": "password", "NodeId": { "Identifier": "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1" } } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Publisher/pn_2.5_legacy_error.json ================================================ [ { "EndpointUrl": "opc.tcp://opcplc:50000", "UseSecurity": false, "OpcAuthenticationMode": "UsernamePassword", "OpcAuthenticationUsername": "username", "OpcAuthenticationPassword": "password", "NodeId": { "Identifier": "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1" }, "OpcNodes": [ { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Publisher/pn_assets.json ================================================ [ { "DataSetWriterId": "Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234", "DataSetWriterGroup": "Leaf0", "DataSetPublishingInterval": 10000, "EndpointUrl": "opc.tcp://opcplc:50000", "UseSecurity": false, "OpcAuthenticationMode": "Anonymous", "OpcAuthenticationUsername": "", "OpcAuthenticationPassword": "", "OpcNodes": [ { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=StepUp", "DataSetFieldId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=StepUp" } ] }, { "DataSetWriterId": "Leaf1_10000_2e4fc28f-ffa2-4532-9f22-378d47bbee5d", "DataSetWriterGroup": "Leaf1", "DataSetPublishingInterval": 10000, "EndpointUrl": "opc.tcp://opcplc:50000", "UseSecurity": false, "OpcAuthenticationMode": "UsernamePassword", "OpcAuthenticationUsername": "usr", "OpcAuthenticationPassword": "pwd", "OpcNodes": [ { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1", "DataSetFieldId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Publisher/pn_assets_with_optional_fields.json ================================================ [ { "DataSetWriterId": "Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234", "DataSetName": "Tag_Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234", "DataSetWriterGroup": "Leaf0", "EndpointUrl": "opc.tcp://opcplc:50000", "UseSecurity": false, "OpcAuthenticationMode": "Anonymous", "OpcNodes": [ { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=StepUp", "DataSetFieldId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=StepUp", "OpcSamplingIntervalTimespan": "00:00:01.500", "OpcPublishingIntervalTimespan": "00:00:01.500", "HeartbeatIntervalTimespan": "00:00:01.500", "SkipFirst": true, "QueueSize": 10 } ] }, { "DataSetWriterId": "Leaf1_10000_2e4fc28f-ffa2-4532-9f22-378d47bbee5d", "DataSetName": "Tag_Leaf1_10000_2e4fc28f-ffa2-4532-9f22-378d47bbee5d", "DataSetWriterGroup": "Leaf1", "DataSetPublishingInterval": 10000, "EndpointUrl": "opc.tcp://opcplc:50000", "UseSecurity": false, "OpcAuthenticationMode": "UsernamePassword", "OpcAuthenticationUsername": "usr", "OpcAuthenticationPassword": "pwd", "OpcNodes": [ { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1", "DataSetFieldId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1", "OpcSamplingInterval": 2000, "OpcPublishingInterval": 2000, "HeartbeatInterval": 2, "SkipFirst": true, "QueueSize": 10 } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Publisher/pn_events.json ================================================ [ { "DataSetWriterId": "Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234", "DataSetName": "Tag_Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234", "DataSetWriterGroup": "Leaf0", "DataSetPublishingInterval": 10000, "EndpointUrl": "opc.tcp://opcplc:50000", "UseSecurity": false, "OpcNodes": [ { "Id": "i=2253", "DisplayName": "SimpleEvents", "QueueSize": 10, "EventFilter": { "SelectClauses": [ { "TypeDefinitionId": "i=2041", "BrowsePath": [ "EventId" ] }, { "TypeDefinitionId": "i=2041", "BrowsePath": [ "Message" ] }, { "TypeDefinitionId": "ns=16;i=235", "BrowsePath": [ "16:CycleId" ] }, { "TypeDefinitionId": "ns=16;i=235", "BrowsePath": [ "16:CurrentStep" ] } ], "WhereClause": { "Elements": [ { "FilterOperator": "OfType", "FilterOperands": [ { "Value": "ns=16;i=235" } ] } ] } } } ] }, { "DataSetWriterId": "Leaf1_1000_3085991c-b85c-4311-9bfb-a916da952234", "DataSetName": "Tag_Leaf1_1000_3085991c-b85c-4311-9bfb-a916da952234", "DataSetWriterGroup": "Leaf1", "DataSetPublishingInterval": 1000, "EndpointUrl": "opc.tcp://opcplc:50000", "UseSecurity": false, "OpcNodes": [ { "Id": "i=2255", "DisplayName": "Alarms", "QueueSize": 10, "EventFilter": { "SelectClauses": [ { "TypeDefinitionId": "i=2041", "BrowsePath": [ "EventId" ] }, { "TypeDefinitionId": "i=2041", "BrowsePath": [ "Message" ] } ], "WhereClause": { "Elements": [ { "FilterOperator": "OfType", "FilterOperands": [ { "Value": "ns=17;i=235" } ] } ] } } } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Publisher/pn_opc_nodes_empty.json ================================================ [ { "DataSetWriterId": "Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234", "DataSetName": "Tag_Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234", "DataSetWriterGroup": "Leaf0", "DataSetPublishingInterval": 10000, "EndpointUrl": "opc.tcp://opcplc:50000", "UseSecurity": false, "OpcAuthenticationMode": "Anonymous", "OpcAuthenticationUsername": "", "OpcAuthenticationPassword": "", "OpcNodes": [] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Publisher/pn_opc_nodes_empty_and_null.json ================================================ [ { "DataSetWriterId": "Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234", "DataSetName": "Tag_Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234", "DataSetWriterGroup": "Leaf0", "DataSetPublishingInterval": 10000, "EndpointUrl": "opc.tcp://opcplc:50000", "UseSecurity": false, "OpcAuthenticationMode": "Anonymous", "OpcAuthenticationUsername": "", "OpcAuthenticationPassword": "", "OpcNodes": [] }, { "DataSetWriterId": "Leaf1_10000_2e4fc28f-ffa2-4532-9f22-378d47bbee5d", "DataSetName": "Tag_Leaf1_10000_2e4fc28f-ffa2-4532-9f22-378d47bbee5d", "DataSetWriterGroup": "Leaf1", "DataSetPublishingInterval": 10000, "EndpointUrl": "opc.tcp://opcplc:50000", "UseSecurity": false, "OpcAuthenticationMode": "UsernamePassword", "OpcAuthenticationUsername": "usr", "OpcAuthenticationPassword": "pwd" } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Publisher/pn_opc_nodes_null.json ================================================ [ { "DataSetWriterId": "Leaf1_10000_2e4fc28f-ffa2-4532-9f22-378d47bbee5d", "DataSetName": "Tag_Leaf1_10000_2e4fc28f-ffa2-4532-9f22-378d47bbee5d", "DataSetWriterGroup": "Leaf1", "DataSetPublishingInterval": 10000, "EndpointUrl": "opc.tcp://opcplc:50000", "UseSecurity": false, "OpcAuthenticationMode": "UsernamePassword", "OpcAuthenticationUsername": "usr", "OpcAuthenticationPassword": "pwd" } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Publisher/pn_pending_alarms.json ================================================ [ { "DataSetWriterId": "Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234", "Tag": "Tag_Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234", "DataSetWriterGroup": "Leaf0", "DataSetPublishingInterval": 10000, "EndpointUrl": "opc.tcp://opcplc:50000", "UseSecurity": false, "OpcNodes": [ { "DisplayName": "PendingAlarms", "Id": "i=2253", "EventFilter": { "TypeDefinitionId": "i=2041" }, "ConditionHandling": { "UpdateInterval": 10, "SnapshotInterval": 20 } } ] }, { "DataSetWriterId": "Leaf1_1000_3085991c-b85c-4311-9bfb-a916da952234", "Tag": "Tag_Leaf1_1000_3085991c-b85c-4311-9bfb-a916da952234", "DataSetWriterGroup": "Leaf1", "DataSetPublishingInterval": 1000, "EndpointUrl": "opc.tcp://opcplc:50000", "UseSecurity": false, "OpcNodes": [ { "DisplayName": "OtherAlarms", "Id": "i=2255", "EventFilter": { "TypeDefinitionId": "i=2044" }, "ConditionHandling": { "UpdateInterval": 10, "SnapshotInterval": 20 } } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Publisher/publishednodes.json ================================================ [ { "EndpointUrl": "opc.tcp://server1:49580", "OpcNodes": [ { "Id": "ns=2;s=Node-Server1", "DisplayName": "Node-Server1" } ] }, { "EndpointUrl": "opc.tcp://server2:49580", "OpcNodes": [ { "Id": "ns=2;s=Node-Server2", "DisplayName": "Node-Server2" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Publisher/publishednodes_with_duplicates.json ================================================ [ { "EndpointUrl": "opc.tcp://10.0.0.1:59412", "UseSecurity": false, "OpcAuthenticationMode": "UsernamePassword", "OpcAuthenticationUsername": "user", "OpcAuthenticationPassword": "passwd", "OpcNodes": [ { "Id": "ns=2;s=Variable1.Line1.Power", "DisplayName": "Variable1_Power", "OpcSamplingInterval": 60000, "OpcPublishingInterval": 60000, "HeartbeatInterval": 3343, "SkipFirst": false }, { "Id": "ns=2;s=Variable1.Line1.Speed", "DisplayName": "Variable1_Line1_Speed", "OpcSamplingInterval": 900000, "OpcPublishingInterval": 900000, "HeartbeatInterval": 3465, "SkipFirst": false }, { "Id": "ns=2;s=Variable1.Line1.Power", "DisplayName": "Variable1_Line1_Power", "OpcSamplingInterval": 60000, "OpcPublishingInterval": 60000, "HeartbeatInterval": 3343, "SkipFirst": false } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Publisher/publishednodeswithoptionalfields.json ================================================ [ { "EndpointUrl": "opc.tcp://server1:49580", "UseSecurity": false, "OpcNodes": [ { "Id": "ns=2;s=Node-Server1", "DisplayName": "Node-Server1", "OpcSamplingInterval": 2000, "OpcPublishingInterval": 2000 } ] }, { "EndpointUrl": "opc.tcp://server2:49580", "UseSecurity": false, "OpcNodes": [ { "Id": "ns=2;s=Node-Server2", "DisplayName": "Node-Server2", "OpcSamplingInterval": 2000, "OpcPublishingInterval": 2000 } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Runtime/TopicBuilderTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Runtime { using FluentAssertions; using Microsoft.Extensions.Configuration; using System.Collections.Generic; using Xunit; public class TopicBuilderTests { [Fact] public void TestRootTopicBuilding() { var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.PublisherId = "MyPublisher"; new TopicBuilder(options.Value).RootTopic.Should().Be(options.Value.PublisherId); } [Fact] public void TestMethodTopicBuilding1() { var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.PublisherId = "MyPublisher"; new TopicBuilder(options.Value).MethodTopic.Should().Be($"{options.Value.PublisherId}/methods"); } [Fact] public void TestMethodTopicBuilding2() { var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.PublisherId = "MyPublisher"; options.Value.TopicTemplates.Method = null; new TopicBuilder(options.Value).MethodTopic.Should().BeEmpty(); } [Fact] public void TestMethodTopicBuilding3() { var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.PublisherId = "MyPublisher"; options.Value.TopicTemplates.Method = null; new TopicBuilder(options.Value, null, new TopicTemplatesOptions { Method = "{RootTopic}/methods" }).MethodTopic.Should().Be($"{options.Value.PublisherId}/methods"); } [Fact] public void TestEventsTopicBuilding1() { var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.PublisherId = "MyPublisher"; new TopicBuilder(options.Value).EventsTopic.Should().Be($"{options.Value.PublisherId}/EventSource/EventName"); } [Fact] public void TestTelemetryTopicBuildingWithDefault() { var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.PublisherId = "MyPublisher"; new TopicBuilder(options.Value, variables: new Dictionary { ["DataSetWriter"] = "Foo", ["WriterGroup"] = "Bar" }).TelemetryTopic.Should().Be($"{options.Value.PublisherId}/messages/Bar"); } [Fact] public void TestTelemetryTopicBuilding1() { var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.PublisherId = "MyPublisher"; options.Value.TopicTemplates.Telemetry = "{RootTopic}/{WriterGroup}/{DataSetWriter}"; new TopicBuilder(options.Value, variables: new Dictionary { ["DataSetWriter"] = "Foo", ["WriterGroup"] = "Bar" }).TelemetryTopic.Should().Be($"{options.Value.PublisherId}/Bar/Foo"); } [Fact] public void TestTelemetryTopicBuilding2() { var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.PublisherId = "MyPublisher"; options.Value.TopicTemplates.Telemetry = "{RootTopic}/{Unknown}/{DataSetWriter}"; new TopicBuilder(options.Value, variables: new Dictionary { ["DataSetWriter"] = "Foo", ["WriterGroup"] = "Bar" }).TelemetryTopic.Should().Be($"{options.Value.PublisherId}/Unknown/Foo"); } [Fact] public void TestTelemetryTopicBuilding3() { var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.PublisherId = "MyPublisher"; options.Value.TopicTemplates.Telemetry = "{RootTopic}/{TelemetryTopic}/{DataSetWriter}"; new TopicBuilder(options.Value, variables: new Dictionary { ["DataSetWriter"] = "Foo", ["WriterGroup"] = "Bar" }).TelemetryTopic.Should().Be($"{options.Value.PublisherId}/TelemetryTopic/Foo"); } [Fact] public void TestTelemetryTopicBuilding4() { var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.PublisherId = "MyPublisher"; options.Value.TopicTemplates.Root = "{PublisherId}"; options.Value.TopicTemplates.Telemetry = "{PublisherId}/{RootTopic}"; new TopicBuilder(options.Value).TelemetryTopic.Should().Be($"{options.Value.PublisherId}/PublisherId"); } [Fact] public void TestTelemetryTopicBuilding5() { var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.PublisherId = "MyPublisher"; options.Value.TopicTemplates.Root = "{TelemetryTopic}"; options.Value.TopicTemplates.Telemetry = "{RootTopic}"; new TopicBuilder(options.Value).TelemetryTopic.Should().Be("TelemetryTopic"); } [Fact] public void TestTelemetryTopicBuilding6() { var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.TopicTemplates.Telemetry = "{TelemetryTopic}"; new TopicBuilder(options.Value).TelemetryTopic.Should().Be("TelemetryTopic"); } [Fact] public void TestTelemetryTopicBuilding7() { var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.PublisherId = "MyPublisher"; options.Value.TopicTemplates.Telemetry = "{RootTopic}/writer/{DataSetWriter}/group/{WriterGroup}/messages"; new TopicBuilder(options.Value, variables: new Dictionary { ["DataSetWriter"] = "Foo", ["WriterGroup"] = "Bar" }).TelemetryTopic.Should().Be($"{options.Value.PublisherId}/writer/Foo/group/Bar/messages"); } [Fact] public void TestTelemetryTopicBuilding8() { var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.PublisherId = "MyPublisher"; new TopicBuilder(options.Value, null, new TopicTemplatesOptions { Telemetry = "{RootTopic}/writer/{DataSetWriter}/group/{WriterGroup}/messages" }, new Dictionary { ["DataSetWriter"] = "Foo", ["WriterGroup"] = "Bar" }).TelemetryTopic.Should().Be($"{options.Value.PublisherId}/writer/Foo/group/Bar/messages"); } [Fact] public void TestTelemetryTopicBuilding9() { var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.PublisherId = "MyPublisher"; #pragma warning disable CA1308 // Normalize strings to uppercase options.Value.TopicTemplates.Telemetry = "{RootTopic}/writer/{DataSetWriter}/group/{WriterGroup}/messages".ToLowerInvariant(); #pragma warning restore CA1308 // Normalize strings to uppercase new TopicBuilder(options.Value, variables: new Dictionary { ["DataSetWriter"] = "Foo", ["WriterGroup"] = "Bar" }).TelemetryTopic.Should().Be($"{options.Value.PublisherId}/writer/Foo/group/Bar/messages"); } [Fact] public void TestMetadataTopicBuildingWithDefaultIsNull() { var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.PublisherId = "MyPublisher"; new TopicBuilder(options.Value, variables: new Dictionary { ["DataSetWriter"] = "Foo", ["WriterGroup"] = "Bar" }).DataSetMetaDataTopic.Should().BeEmpty(); } [Fact] public void TestMetadataTopicBuilding1() { var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.PublisherId = "MyPublisher"; options.Value.TopicTemplates.DataSetMetaData = "{TelemetryTopic}/metadata"; new TopicBuilder(options.Value, variables: new Dictionary { ["DataSetWriter"] = "Foo", ["WriterGroup"] = "Bar" }).DataSetMetaDataTopic.Should().Be($"{options.Value.PublisherId}/messages/Bar/metadata"); } [Fact] public void TestMetadataTopicBuilding2() { var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.PublisherId = "MyPublisher"; options.Value.TopicTemplates.DataSetMetaData = "{TelemetryTopic}/$someothername"; new TopicBuilder(options.Value, null, new TopicTemplatesOptions { DataSetMetaData = "{TelemetryTopic}/metadata" }, new Dictionary { ["DataSetWriter"] = "Foo", ["WriterGroup"] = "Bar" }).DataSetMetaDataTopic.Should().Be($"{options.Value.PublisherId}/messages/Bar/metadata"); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/Alarms/NodeServicesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.Alarms { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class NodeServicesTests : IClassFixture { public NodeServicesTests(AlarmsServer server, ITestOutputHelper output) { _server = server; _output = output; } private AlarmServerTests GetTests() { return new AlarmServerTests( () => new NodeServices(_server.Client, _server.Parser, _output.BuildLoggerFor>(Logging.Level), new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions()), _server.GetConnection()); } private readonly ITestOutputHelper _output; private readonly AlarmsServer _server; [Fact] public Task BrowseAreaPathTestAsync() { return GetTests().BrowseAreaPathTestAsync(); } [Fact] public Task BrowseMetalsSouthMotorTestAsync() { return GetTests().BrowseMetalsSouthMotorTestAsync(); } [Fact] public Task BrowseColoursEastTankTestAsync() { return GetTests().BrowseColoursEastTankTestAsync(); } [Fact] public Task CompileAlarmQueryTest1Async() { return GetTests().CompileAlarmQueryTest1Async(); } [Fact] public Task CompileAlarmQueryTest2Async() { return GetTests().CompileAlarmQueryTest2Async(); } [Fact] public Task CompileSimpleBaseEventQueryTestAsync() { return GetTests().CompileSimpleBaseEventQueryTestAsync(); } [Fact] public Task CompileSimpleTripAlarmQueryTestAsync() { return GetTests().CompileSimpleTripAlarmQueryTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/Asset/ConfigurationTest1.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.Asset { using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection1.Name)] public class ConfigurationTest1 { public ConfigurationTest1(AssetServer server, ITestOutputHelper output) { _server = server; _output = output; } private AssetTests1 GetTests() { #pragma warning disable CA2000 // Dispose objects before losing scope return new AssetTests1(c => new ConfigurationServices(c, _server.Client, new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(), _output.BuildLoggerFor(Logging.Level)), _server.GetConnection()); #pragma warning restore CA2000 // Dispose objects before losing scope } private readonly AssetServer _server; private readonly ITestOutputHelper _output; [Fact] public Task ConfigureAndDeleteAssetsAsync() { return GetTests().ConfigureAndDeleteAssetsAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/Asset/ConfigurationTest2.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.Asset { using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection2.Name)] public class ConfigurationTest2 { public ConfigurationTest2(AssetServer server, ITestOutputHelper output) { _server = server; _output = output; } private AssetTests2 GetTests() { #pragma warning disable CA2000 // Dispose objects before losing scope return new AssetTests2(c => new ConfigurationServices(c, _server.Client, new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(), _output.BuildLoggerFor(Logging.Level)), _server.GetConnection()); #pragma warning restore CA2000 // Dispose objects before losing scope } private readonly AssetServer _server; private readonly ITestOutputHelper _output; [Fact] public Task ConfigureAsset1Async() { return GetTests().ConfigureAsset1Async(); } [Fact] public Task ConfigureAsset2Async() { return GetTests().ConfigureAsset2Async(); } [Fact] public Task ConfigureAsset3Async() { return GetTests().ConfigureAsset3Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/Asset/ConfigurationTest3.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.Asset { using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection3.Name)] public class ConfigurationTest3 { public ConfigurationTest3(AssetServer server, ITestOutputHelper output) { _server = server; _output = output; } private AssetTests3 GetTests() { #pragma warning disable CA2000 // Dispose objects before losing scope return new AssetTests3(c => new ConfigurationServices(c, _server.Client, new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(), _output.BuildLoggerFor(Logging.Level)), _server.GetConnection()); #pragma warning restore CA2000 // Dispose objects before losing scope } private readonly AssetServer _server; private readonly ITestOutputHelper _output; [Fact] public Task ConfigureAsset1Async() { return GetTests().ConfigureAsset1Async(); } [Fact] public Task ConfigureAsset2Async() { return GetTests().ConfigureAsset2Async(); } [Fact] public Task ConfigureAsset3Async() { return GetTests().ConfigureAsset3Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/Asset/ConfigurationTest4.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.Asset { using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection4.Name)] public class ConfigurationTest4 { public ConfigurationTest4(AssetServer server, ITestOutputHelper output) { _server = server; _output = output; } private AssetTests4 GetTests() { #pragma warning disable CA2000 // Dispose objects before losing scope return new AssetTests4(c => new ConfigurationServices(c, _server.Client, new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(), _output.BuildLoggerFor(Logging.Level)), _server.GetConnection()); #pragma warning restore CA2000 // Dispose objects before losing scope } private readonly AssetServer _server; private readonly ITestOutputHelper _output; [Fact] public Task ConfigureDuplicateAssetFailsAsync() { return GetTests().ConfigureDuplicateAssetFailsAsync(); } [Fact] public Task ConfigureAssetFails1Async() { return GetTests().ConfigureAssetFails1Async(); } [Fact] public Task ConfigureWithBadStreamFails1Async() { return GetTests().ConfigureWithBadStreamFails1Async(); } [Fact] public Task ConfigureWithBadStreamFails2Async() { return GetTests().ConfigureWithBadStreamFails2Async(); } [Fact] public Task ConfigureWithBadStreamFails3Async() { return GetTests().ConfigureWithBadStreamFails3Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/Asset/WriteCollection1.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.Asset { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public class WriteCollection1 : ICollectionFixture { public const string Name = "AssetWrite1"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/Asset/WriteCollection2.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.Asset { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public class WriteCollection2 : ICollectionFixture { public const string Name = "AssetWrite2"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/Asset/WriteCollection3.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.Asset { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public class WriteCollection3 : ICollectionFixture { public const string Name = "AssetWrite3"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/Asset/WriteCollection4.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.Asset { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public class WriteCollection4 : ICollectionFixture { public const string Name = "AssetWrite4"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/AssetDeviceIntegrationTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.Iot.Operations.Services.AssetAndDeviceRegistry.Models; using Furly.Azure.IoT.Operations.Services; using Furly.Extensions.Serializers; using AssetModel = Iot.Operations.Services.AssetAndDeviceRegistry.Models.Asset; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Moq; using System; using System.Buffers; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Xunit; using Azure.IIoT.OpcUa.Publisher.Stack; using Autofac.Util; public class AssetDeviceIntegrationTests { public AssetDeviceIntegrationTests() { // Initialize mocks _srMock.Setup(x => x.Register(It.IsAny())).Returns(new Disposable()); _optionsMock.SetupGet(o => o.Value).Returns(new PublisherOptions { PublisherId = "aio" }); } [Fact] public void ConstructorInitializesFields() { // Arrange/Act var sut = CreateSut(); // Assert Assert.NotNull(sut); } [Fact] public async Task DisposeAsyncCanBeCalledMultipleTimes() { // Arrange var sut = CreateSut(); // Act await sut.DisposeAsync(); // Should not throw await sut.DisposeAsync(); } [Fact] public void DisposeCallsDisposeAsyncMethod() { // Arrange var sut = CreateSut(); // Act/Assert sut.Dispose(); // Should not throw sut.Dispose(); } [Fact] public void OnDeviceCreatedAddsDeviceAndWritesToChangeFeed() { // Arrange var sut = CreateSut(); var device = new Device(); const string deviceName = "dev1"; const string endpointName = "ep1"; // Act sut.OnDeviceCreated(deviceName, endpointName, device); // Assert: device should be in the internal dictionary Assert.Single(sut.Devices, d => d.DeviceName == deviceName); } [Fact] public void OnDeviceCreatedThrowsIfChangeFeedWasCompleted() { // Arrange var sut = CreateSut(); var device = new Device(); const string deviceName = "dev1"; const string endpointName = "ep1"; TryCompleteChannel(sut); // Act / Assert Assert.Throws( () => sut.OnDeviceCreated(deviceName, endpointName, device)); } [Fact] public void OnDeviceUpdatedUpdatesDeviceAndWritesToChangeFeed() { // Arrange var sut = CreateSut(); var device = new Device(); const string deviceName = "dev1"; const string endpointName = "ep1"; // Act sut.OnDeviceUpdated(deviceName, endpointName, device); // Assert: device should be in the internal dictionary Assert.Single(sut.Devices, d => d.DeviceName == deviceName); } [Fact] public void OnDeviceUpdatedThrowsIfChangeFeedWasCompleted() { // Arrange var sut = CreateSut(); var device = new Device(); const string deviceName = "dev1"; const string endpointName = "ep1"; TryCompleteChannel(sut); // Act / Assert Assert.Throws( () => sut.OnDeviceUpdated(deviceName, endpointName, device)); } [Fact] public void OnDeviceDeletedRemovesDeviceAndWritesToChangeFeed() { // Arrange var sut = CreateSut(); var device = new Device(); const string deviceName = "dev1"; const string endpointName = "ep1"; // Add device first sut.OnDeviceCreated(deviceName, endpointName, device); // Act sut.OnDeviceDeleted(deviceName, endpointName); // Assert: device should be removed from the internal dictionary Assert.DoesNotContain(sut.Devices, d => d.DeviceName == deviceName); } [Fact] public void OnDeviceDeletedThrowsIfChangeFeedWasCompleted() { // Arrange var sut = CreateSut(); var device = new Device(); const string deviceName = "dev1"; const string endpointName = "ep1"; // Add device first sut.OnDeviceCreated(deviceName, endpointName, device); TryCompleteChannel(sut); // Act / Assert Assert.Throws( () => sut.OnDeviceDeleted(deviceName, endpointName)); } [Fact] public void OnAssetCreatedAddsAssetAndWritesToChangeFeed() { // Arrange var sut = CreateSut(); var asset = new AssetModel { DeviceRef = new AssetDeviceRef { DeviceName = "dev1", EndpointName = "ep1" } }; const string deviceName = "dev1"; const string endpointName = "ep1"; const string assetName = "asset1"; // Act sut.OnDeviceCreated(deviceName, endpointName, new Device()); sut.OnAssetCreated(deviceName, endpointName, assetName, asset); // Assert: asset should be in the internal dictionary Assert.Single(sut.Assets, a => a.AssetName == assetName); } [Fact] public void OnAssetCreatedThrowsIfChangeFeedWasCompleted() { // Arrange var sut = CreateSut(); var asset = new AssetModel { DeviceRef = new AssetDeviceRef { DeviceName = "dev1", EndpointName = "ep1" } }; const string deviceName = "dev1"; const string endpointName = "ep1"; const string assetName = "asset1"; TryCompleteChannel(sut); // Act / Assert Assert.Throws( () => sut.OnAssetCreated(deviceName, endpointName, assetName, asset)); } [Fact] public void OnAssetUpdatedUpdatesAssetAndWritesToChangeFeed() { // Arrange var sut = CreateSut(); var asset = new AssetModel { DeviceRef = new AssetDeviceRef { DeviceName = "dev1", EndpointName = "ep1" } }; const string deviceName = "dev1"; const string endpointName = "ep1"; const string assetName = "asset1"; // Act sut.OnAssetUpdated(deviceName, endpointName, assetName, asset); // Assert: asset should be in the internal dictionary Assert.Single(sut.Assets, a => a.AssetName == assetName); } [Fact] public void OnAssetUpdatedThrowsIfChangeFeedWasCompleted() { // Arrange var sut = CreateSut(); var asset = new AssetModel { DeviceRef = new AssetDeviceRef { DeviceName = "dev1", EndpointName = "ep1" } }; const string deviceName = "dev1"; const string endpointName = "ep1"; const string assetName = "asset1"; TryCompleteChannel(sut); // Act / Assert Assert.Throws( () => sut.OnAssetUpdated(deviceName, endpointName, assetName, asset)); } [Fact] public void OnAssetDeletedRemovesAssetAndWritesToChangeFeed() { // Arrange var sut = CreateSut(); var asset = new AssetModel { DeviceRef = new AssetDeviceRef { DeviceName = "dev1", EndpointName = "ep1" } }; const string deviceName = "dev1"; const string endpointName = "ep1"; const string assetName = "asset1"; // Add asset first sut.OnDeviceCreated(deviceName, endpointName, new Device()); sut.OnAssetCreated(deviceName, endpointName, assetName, asset); // Act sut.OnAssetDeleted(deviceName, endpointName, assetName); // Assert: asset should be removed from the internal dictionary Assert.DoesNotContain(sut.Assets, a => a.AssetName == assetName); } [Fact] public void OnAssetDeletedThrowsIfChangeFeedWasCompleted() { // Arrange var sut = CreateSut(); var asset = new AssetModel { DeviceRef = new AssetDeviceRef { DeviceName = "dev1", EndpointName = "ep1" } }; const string deviceName = "dev1"; const string endpointName = "ep1"; const string assetName = "asset1"; // Add asset first sut.OnDeviceCreated(deviceName, endpointName, new Device()); sut.OnAssetCreated(deviceName, endpointName, assetName, asset); TryCompleteChannel(sut); // Act / Assert Assert.Throws( () => sut.OnAssetDeleted(deviceName, endpointName, assetName)); } [Fact] public async Task RunAsyncProcessesChangeFeedWithoutException() { // Arrange var sut = CreateSut(); using var cts = new System.Threading.CancellationTokenSource(100); // Cancel after 100ms // Act/Assert await sut.RunAsync(cts.Token); // Should not throw } [Fact] public async Task RunDiscoveryUsingTypesAsyncReportsDiscoveredAssets() { // Arrange var sut = CreateSut(); var device = new Device { Endpoints = new DeviceEndpoints { Inbound = new Dictionary { { "ep1", new InboundEndpointSchemaMapValue { Address = "opc.tcp://localhost:4840" } } } } }; var resource = new AssetDeviceIntegration.DeviceEndpointResource( "dev1", device, "ep1"); var types = new List { "ns=2;s=Type1" }; var errors = new AssetDeviceIntegration.ValidationErrors(sut); var publishedNodesEntry = new PublishedNodesEntryModel { EndpointUrl = "opc.tcp://endpoint", DataSetWriterGroup = "AssetGroup", WriterGroupRootNodeId = "rootId", WriterGroupType = "typeRef", OpcNodes = new List { new OpcNodeModel { Id = "ns=2;s=Type1", DisplayName = "Node1" } } }; var serviceResponseMock = new ServiceResponse { ErrorInfo = null, Result = publishedNodesEntry }; _configurationServicesMock .Setup(s => s.ExpandAsync( It.IsAny(), It.IsAny(), default)) .Returns(AsyncEnumerable.Range(0, 1).Select(_ => serviceResponseMock)); #pragma warning disable CA2012 // Use ValueTasks correctly _clientMock.Setup(c => c.ReportDiscoveredAssetAsync( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), null, default)) .Returns(ValueTask.FromResult(null)) .Verifiable(); #pragma warning restore CA2012 // Use ValueTasks correctly // Act await sut.RunDiscoveryUsingTypesAsync(resource, new DeviceEndpointConfiguration { AssetTypes = types }, errors, default); // Assert _clientMock .Verify(c => c.ReportDiscoveredAssetAsync( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), null, default), Times.AtLeastOnce()); } [Fact] public async Task RunDiscoveryUsingTypesAsyncReportsNothingIfNothingIsFound() { // Arrange var sut = CreateSut(); var device = new Device { Endpoints = new DeviceEndpoints { Inbound = new Dictionary { { "ep1", new InboundEndpointSchemaMapValue { Address = "opc.tcp://localhost:4840" } } } } }; var resource = new AssetDeviceIntegration.DeviceEndpointResource( "dev1", device, "ep1"); var types = new List { "ns=2;s=Type1" }; var errors = new AssetDeviceIntegration.ValidationErrors(sut); var publishedNodesEntry = new PublishedNodesEntryModel { EndpointUrl = "opc.tcp://endpoint", DataSetWriterGroup = "AssetGroup", WriterGroupRootNodeId = "rootId", WriterGroupType = "typeRef", OpcNodes = new List() }; var serviceResponseMock = new ServiceResponse { ErrorInfo = null, Result = publishedNodesEntry }; _configurationServicesMock .Setup(s => s.ExpandAsync( It.IsAny(), It.IsAny(), default)) .Returns(AsyncEnumerable.Range(0, 1).Select(_ => serviceResponseMock)); #pragma warning disable CA2012 // Use ValueTasks correctly _clientMock.Setup(c => c.ReportDiscoveredAssetAsync( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), null, default)) .Returns(ValueTask.FromResult(null)) .Verifiable(); #pragma warning restore CA2012 // Use ValueTasks correctly // Act await sut.RunDiscoveryUsingTypesAsync(resource, new DeviceEndpointConfiguration { AssetTypes = types }, errors, default); // Assert _clientMock .Verify(c => c.ReportDiscoveredAssetAsync( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), null, default), Times.Never); } [Fact] public async Task RunDiscoveryUsingTypesAsyncEndpointNotFoundReportsError() { // Arrange var sut = CreateSut(); var device = new Device(); var resource = new AssetDeviceIntegration.DeviceEndpointResource("dev1", device, "ep1"); var types = new List { "ns=2;s=Type1" }; var errors = new AssetDeviceIntegration.ValidationErrors(sut); // Act await sut.RunDiscoveryUsingTypesAsync(resource, new DeviceEndpointConfiguration { AssetTypes = types }, errors, default); // Assert: error should be recorded (no exception thrown) } [Fact] public async Task ToPublishedNodesAsyncWithDatasetsAndEventsReturnsEntries() { // Arrange var sut = CreateSut(); var d = new Device { Endpoints = new DeviceEndpoints { Inbound = new Dictionary { { "ep1", new InboundEndpointSchemaMapValue { Address = "opc.tcp://localhost:4840" } } } } }; var device = new AssetDeviceIntegration.DeviceResource("dev1", d); sut.OnDeviceCreated("dev1", "ep1", d); var dataset = new AssetDataset { Name = "ds1", DataPoints = new List { new AssetDatasetDataPointSchemaElement { Name = "dp1", DataSource = "ns=2;s=dp1" } } }; var @event = new AssetEvent { Name = "ev1", DataSource = "ns=2;s=ev1" }; var eg = new AssetEventGroup { Name = "eg1", Events = new List { @event } }; var asset = new AssetDeviceIntegration.AssetResource("asset1", new AssetModel { DeviceRef = new AssetDeviceRef { DeviceName = "dev1", EndpointName = "ep1" }, Datasets = new List { dataset }, EventGroups = new List { eg } }); var errors = new AssetDeviceIntegration.ValidationErrors(sut); _serializerMock .Setup(s => s.Deserialize(It.IsAny>(), It.IsAny())) .Returns((object)null); // Act var result = await sut.ToPublishedNodesAsync( new[] { device }, new[] { asset }, errors, default); // Assert Assert.NotNull(result); } [Fact] public async Task ToPublishedNodesAsyncDeviceNotFoundReportsError() { // Arrange var sut = CreateSut(); var asset = new AssetDeviceIntegration.AssetResource("asset1", new AssetModel { DeviceRef = new AssetDeviceRef { DeviceName = "devX", EndpointName = "epX" } }); var errors = new AssetDeviceIntegration.ValidationErrors(sut); // Act var result = await sut.ToPublishedNodesAsync( Array.Empty(), new[] { asset }, errors, default); // Assert Assert.NotNull(result); } [Fact] public async Task ToPublishedNodesAsyncReturnsExpectedEntries() { // Arrange var sut = CreateSut(); var device = new AssetDeviceIntegration.DeviceResource("dev1", new Device { Endpoints = new DeviceEndpoints { Inbound = new Dictionary { { "ep1", new InboundEndpointSchemaMapValue { Address = "opc.tcp://localhost:4840" } } } } }); var asset = new AssetDeviceIntegration.AssetResource("asset1", new AssetModel { DeviceRef = new AssetDeviceRef { DeviceName = "dev1", EndpointName = "ep1" }, Datasets = null, EventGroups = null }); var errors = new AssetDeviceIntegration.ValidationErrors(sut); // Act var result = await sut.ToPublishedNodesAsync( new[] { device }, new[] { asset }, errors, default); // Assert Assert.NotNull(result); // Should be empty because no datasets/events, but no error thrown } [Fact] public void CollectAssetAndDevicePropertiesReturnsExpectedDictionary() { // Arrange var device = new AssetDeviceIntegration.DeviceResource("dev1", new Device { Model = "X", Manufacturer = "Y" }); var asset = new AssetDeviceIntegration.AssetResource("asset1", new AssetModel { DeviceRef = new AssetDeviceRef { DeviceName = "dev1", EndpointName = "ep1" }, Model = null, Manufacturer = "B" }); // Act var result = AssetDeviceIntegration.CollectAssetAndDeviceProperties( asset, device); // Assert Assert.NotNull(result); Assert.Equal("X", result[nameof(Device.Model)]); Assert.Equal("B", result[nameof(AssetModel.Manufacturer)]); } [Fact] public async Task ValidationErrorsReportAsyncReportsDeviceAndAssetStatus() { // Arrange var sut = CreateSut(); var errors = new AssetDeviceIntegration.ValidationErrors(sut); var device = new AssetDeviceIntegration.DeviceEndpointResource("dev1", new Device(), "ep1"); var asset = new AssetDeviceIntegration.AssetResource("asset1", new AssetModel { DeviceRef = new AssetDeviceRef { DeviceName = "dev1", EndpointName = "ep1" } }); errors.OnError(device, "code1", "error1"); errors.OnError(asset, "code2", "error2"); #pragma warning disable CA2012 // Use ValueTasks correctly _clientMock .Setup(c => c.UpdateDeviceStatusAsync( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns(ValueTask.FromResult(null)) .Verifiable(); #pragma warning restore CA2012 // Use ValueTasks correctly #pragma warning disable CA2012 // Use ValueTasks correctly _clientMock .Setup(c => c.UpdateAssetStatusAsync( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns(ValueTask.FromResult(null)) .Verifiable(); #pragma warning restore CA2012 // Use ValueTasks correctly // Act await errors.ReportAsync(default); // Assert _clientMock .Verify(c => c.UpdateDeviceStatusAsync( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.AtLeastOnce()); _clientMock .Verify(c => c.UpdateAssetStatusAsync( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.AtLeastOnce()); } [Fact] public void ValidationErrorsOnErrorAddsError() { // Arrange var sut = CreateSut(); var errors = new AssetDeviceIntegration.ValidationErrors(sut); var device = new AssetDeviceIntegration.DeviceEndpointResource("dev1", new Device(), "ep1"); // Act errors.OnError(device, "code1", "error1"); // No assert, just ensure no exception and internal state updated } private static void TryCompleteChannel(AssetDeviceIntegration sut) { // Simulate full channel by completing writer var field = typeof(AssetDeviceIntegration).GetField("_changeFeed", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); var channel = (System.Threading.Channels.Channel<(string, AssetDeviceIntegration.Resource)>) field.GetValue(sut); channel.Writer.TryComplete(); } private AssetDeviceIntegration CreateSut() { return new(_clientMock.Object, _srMock.Object, _publishedNodesMock.Object, _configurationServicesMock.Object, _connectionsMock.Object, _discoveryMock.Object, _serializerMock.Object, _optionsMock.Object, _loggerMock.Object); } private readonly Mock> _optionsMock = new(); private readonly Mock _discoveryMock = new(); private readonly Mock> _connectionsMock = new(); private readonly Mock _clientMock = new(); private readonly Mock _srMock = new(); private readonly Mock _publishedNodesMock = new(); private readonly Mock _serializerMock = new(); private readonly Mock _configurationServicesMock = new(); private readonly Mock> _loggerMock = new(); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/DeterministicAlarms/NodeServicesTests1.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.DeterministicAlarms { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class NodeServicesTests1 : IClassFixture { public NodeServicesTests1(DeterministicAlarmsServer1 server, ITestOutputHelper output) { _server = server; _output = output; } private DeterministicAlarmsTests1 GetTests() { return new DeterministicAlarmsTests1( () => new NodeServices(_server.Client, _server.Parser, _output.BuildLoggerFor>(Logging.Level), new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions()), _server.GetConnection()); } private readonly ITestOutputHelper _output; private readonly DeterministicAlarmsServer1 _server; [Fact] public Task BrowseAreaPathVendingMachine1TemperatureHighTestAsync() { return GetTests().BrowseAreaPathVendingMachine1TemperatureHighTestAsync(); } [Fact] public Task BrowseAreaPathVendingMachine2LightOffTestAsync() { return GetTests().BrowseAreaPathVendingMachine2LightOffTestAsync(); } [Fact] public Task BrowseAreaPathVendingMachine1DoorOpenTestAsync() { return GetTests().BrowseAreaPathVendingMachine1DoorOpenTestAsync(); } [Fact] public Task BrowseAreaPathVendingMachine2DoorOpenTestAsync() { return GetTests().BrowseAreaPathVendingMachine2DoorOpenTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/DeterministicAlarms/NodeServicesTests2.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.DeterministicAlarms { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class NodeServicesTests2 : IClassFixture { public NodeServicesTests2(DeterministicAlarmsServer2 server, ITestOutputHelper output) { _output = output; _server = server; } private DeterministicAlarmsTests2 GetTests() { return new DeterministicAlarmsTests2( () => new NodeServices(_server.Client, _server.Parser, _output.BuildLoggerFor>(Logging.Level), new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions()), _server.GetConnection()); } private readonly ITestOutputHelper _output; private readonly DeterministicAlarmsServer2 _server; [Fact] public Task BrowseAreaPathVendingMachine1DoorOpenTestAsync() { return GetTests().BrowseAreaPathVendingMachine1DoorOpenTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/Encoder/MonitoredItemMessageEncoderJsonGzipTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Moq; using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using Xunit; public class MonitoredItemMessageEncoderJsonGzipTests { /// /// Create compliant encoder /// /// private static NetworkMessageEncoder GetEncoder() { var loggerMock = new Mock>(); var metricsMock = new Mock(); metricsMock.SetupGet(m => m.TagList).Returns(new TagList()); var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); return new NetworkMessageEncoder(options, metricsMock.Object, loggerMock.Object); } [Theory] [InlineData(false)] [InlineData(true)] public void EmptyMessagesTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = new List(); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Empty(networkMessages); Assert.Equal(0, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(0, encoder.MessagesProcessedCount); } [Theory] [InlineData(false)] [InlineData(true)] public void EmptyDataSetMessageModelTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = new[] { new OpcUaSubscriptionNotification(DateTimeOffset.UtcNow) }; using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Empty(networkMessages); Assert.Equal(0, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(0, encoder.MessagesProcessedCount); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeTooBigMessageTest(bool encodeBatchFlag) { const int maxMessageSize = 100; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(3, false, encoding: MessageEncoding.JsonGzip, isSampleMode: true); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Empty(networkMessages); Assert.Equal(0, encoder.NotificationsProcessedCount); Assert.Equal(6, encoder.NotificationsDroppedCount); Assert.Equal(0, encoder.MessagesProcessedCount); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeDataTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(20, false, encoding: MessageEncoding.JsonGzip, isSampleMode: true); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); if (encodeBatchFlag) { Assert.Equal(1, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(20, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(1, encoder.MessagesProcessedCount); Assert.Equal(20, encoder.AvgNotificationsPerMessage); } else { Assert.Equal(210, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(20, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(210, encoder.MessagesProcessedCount); Assert.Equal(0.10, Math.Round(encoder.AvgNotificationsPerMessage, 2)); } } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeDataWithMultipleNotificationsTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(20, false, encoding: MessageEncoding.JsonGzip, isSampleMode: true); messages = [ new (messages[0], messages.SelectMany(n => n.Notifications).ToList()) ]; using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); if (encodeBatchFlag) { Assert.Equal(1, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(1, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(1, encoder.MessagesProcessedCount); Assert.Equal(1, encoder.AvgNotificationsPerMessage); } else { Assert.Equal(210, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(1, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(210, encoder.MessagesProcessedCount); Assert.Equal(0.005, Math.Round(encoder.AvgNotificationsPerMessage, 3)); } } [Theory] [InlineData(true)] [InlineData(false)] public void EncodeChunkTest(bool encodeBatchFlag) { const int maxMessageSize = 8 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(50, false, MessageEncoding.JsonGzip, isSampleMode: true); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); var count = networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count); Assert.All(networkMessages, m => Assert.All(((NetworkMessage)m.Event).Buffers, m => Assert.True(m.Length <= maxMessageSize, m.Length.ToString(CultureInfo.InvariantCulture)))); if (encodeBatchFlag) { Assert.InRange(count, 2, 3); Assert.Equal(50, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal((uint)count, encoder.MessagesProcessedCount); Assert.Equal(25, Math.Round(encoder.AvgNotificationsPerMessage)); } else { Assert.InRange(count, 1270, 1280); Assert.Equal(50, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal((uint)count, encoder.MessagesProcessedCount); Assert.Equal(0.04, Math.Round(encoder.AvgNotificationsPerMessage, 2)); } } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeEventTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(1, true, encoding: MessageEncoding.JsonGzip, isSampleMode: true); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Equal(1, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(1u, encoder.NotificationsProcessedCount); Assert.Equal(0u, encoder.NotificationsDroppedCount); Assert.Equal(1u, encoder.MessagesProcessedCount); Assert.Equal(1, encoder.AvgNotificationsPerMessage); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeEventsTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(20, true, encoding: MessageEncoding.JsonGzip, isSampleMode: true); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); if (encodeBatchFlag) { Assert.Equal(1, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(20, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(1, encoder.MessagesProcessedCount); Assert.Equal(20, encoder.AvgNotificationsPerMessage); } else { Assert.Equal(210, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(20, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(210, encoder.MessagesProcessedCount); Assert.Equal(0.10, Math.Round(encoder.AvgNotificationsPerMessage, 2)); } } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/Encoder/MonitoredItemMessageEncoderJsonTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Moq; using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using Xunit; public class MonitoredItemMessageEncoderJsonTests { /// /// Create compliant encoder /// /// private static NetworkMessageEncoder GetEncoder() { var loggerMock = new Mock>(); var metricsMock = new Mock(); metricsMock.SetupGet(m => m.TagList).Returns(new TagList()); var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); return new NetworkMessageEncoder(options, metricsMock.Object, loggerMock.Object); } [Theory] [InlineData(false)] [InlineData(true)] public void EmptyMessagesTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = new List(); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Empty(networkMessages); Assert.Equal(0, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(0, encoder.MessagesProcessedCount); } [Theory] [InlineData(false)] [InlineData(true)] public void EmptyDataSetMessageModelTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = new[] { new OpcUaSubscriptionNotification(DateTimeOffset.UtcNow) }; using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Empty(networkMessages); Assert.Equal(0, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(0, encoder.MessagesProcessedCount); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeTooBigMessageTest(bool encodeBatchFlag) { const int maxMessageSize = 100; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(3, false, isSampleMode: true); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Empty(networkMessages); Assert.Equal(0, encoder.NotificationsProcessedCount); Assert.Equal(6, encoder.NotificationsDroppedCount); Assert.Equal(0, encoder.MessagesProcessedCount); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeAsUadpNotSupportedTest(bool encodeBatchFlag) { const int maxMessageSize = 100; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(3, false, encoding: MessageEncoding.Uadp, isSampleMode: true); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Empty(networkMessages); Assert.Equal(0, encoder.NotificationsProcessedCount); Assert.Equal(6, encoder.NotificationsDroppedCount); Assert.Equal(0, encoder.MessagesProcessedCount); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeDataTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(20, false, isSampleMode: true); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); if (encodeBatchFlag) { Assert.Equal(1, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(20, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(1, encoder.MessagesProcessedCount); Assert.Equal(20, encoder.AvgNotificationsPerMessage); } else { Assert.Equal(210, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(20, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(210, encoder.MessagesProcessedCount); Assert.Equal(0.10, Math.Round(encoder.AvgNotificationsPerMessage, 2)); } } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeDataWithMultipleNotificationsTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(20, false, isSampleMode: true); messages = [ new (messages[0], messages.SelectMany(n => n.Notifications).ToList()) ]; using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); if (encodeBatchFlag) { Assert.Equal(1, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(1, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(1, encoder.MessagesProcessedCount); Assert.Equal(1, encoder.AvgNotificationsPerMessage); } else { Assert.Equal(210, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(1, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(210, encoder.MessagesProcessedCount); Assert.Equal(0.005, Math.Round(encoder.AvgNotificationsPerMessage, 3)); } } [Theory] [InlineData(true)] [InlineData(false)] public void EncodeChunkTest(bool encodeBatchFlag) { const int maxMessageSize = 8 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(50, false, isSampleMode: true); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); var count = networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count); Assert.All(networkMessages, m => Assert.All(((NetworkMessage)m.Event).Buffers, m => Assert.True(m.Length <= maxMessageSize, m.Length.ToString(CultureInfo.InvariantCulture)))); if (encodeBatchFlag) { Assert.InRange(count, 31, 33); Assert.Equal(50, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal((uint)count, encoder.MessagesProcessedCount); Assert.Equal(1.56, Math.Round(encoder.AvgNotificationsPerMessage, 2)); } else { Assert.InRange(count, 1270, 1280); Assert.Equal(50, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal((uint)count, encoder.MessagesProcessedCount); Assert.Equal(0.04, Math.Round(encoder.AvgNotificationsPerMessage, 2)); } } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeEventTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(1, true, isSampleMode: true); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Equal(1, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(1u, encoder.NotificationsProcessedCount); Assert.Equal(0u, encoder.NotificationsDroppedCount); Assert.Equal(1u, encoder.MessagesProcessedCount); Assert.Equal(1, encoder.AvgNotificationsPerMessage); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeEventsTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(20, true, isSampleMode: true); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); if (encodeBatchFlag) { Assert.Equal(1, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(20, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(1, encoder.MessagesProcessedCount); Assert.Equal(20, encoder.AvgNotificationsPerMessage); } else { Assert.Equal(210, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(20, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(210, encoder.MessagesProcessedCount); Assert.Equal(0.10, Math.Round(encoder.AvgNotificationsPerMessage, 2)); } } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/Encoder/NetworkMessage.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Azure.IIoT.OpcUa.Publisher.Stack.Services; using Furly.Extensions.Logging; using Furly.Extensions.Messaging; using Moq; using Opc.Ua; using System; using System.Buffers; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; public sealed class NetworkMessage : IEvent { public CloudEventHeader CloudEvent { get; private set; } public IEvent AsCloudEvent(CloudEventHeader header) { CloudEvent = header; return this; } public DateTimeOffset Timestamp { get; private set; } public IEvent SetTimestamp(DateTimeOffset value) { Timestamp = value; return this; } public QoS QoS { get; private set; } public IEvent SetQoS(QoS value) { QoS = value; return this; } public string ContentType { get; private set; } public IEvent SetContentType(string value) { ContentType = value; return this; } public string ContentEncoding { get; private set; } public IEvent SetContentEncoding(string value) { ContentEncoding = value; return this; } public string Topic { get; private set; } public IEvent SetTopic(string value) { Topic = value; return this; } public IEventSchema Schema { get; private set; } public IEvent SetSchema(IEventSchema schema) { Schema = schema; return this; } public bool Retain { get; private set; } public IEvent SetRetain(bool value) { Retain = value; return this; } public TimeSpan Ttl { get; private set; } public IEvent SetTtl(TimeSpan value) { Ttl = value; return this; } public IList> Buffers { get; } = []; public IEvent AddBuffers(IEnumerable> value) { Buffers.AddRange(value); return this; } public Dictionary Properties { get; } = []; public IEvent AddProperty(string name, string value) { Properties.AddOrUpdate(name, value); return this; } public static IEvent Create() { return new NetworkMessage(); } public static IList GenerateSampleSubscriptionNotifications( uint numOfMessages, bool eventList = false, MessageEncoding encoding = MessageEncoding.Json, NetworkMessageContentFlags extraNetworkMessageMask = 0, bool isSampleMode = false, bool randomTopic = false) { var messages = new List(); const string publisherId = "Publisher"; var writer = new DataSetWriterModel { Id = string.Empty, DataSet = new PublishedDataSetModel { DataSetSource = new PublishedDataSetSourceModel { PublishedVariables = new PublishedDataItemsModel { PublishedData = new List() } }, DataSetMetaData = new DataSetMetaDataModel { Name = "testdataset", DataSetClassId = Guid.NewGuid() } } }; var writerGroup = new WriterGroupModel { Id = string.Empty, MessageSettings = new WriterGroupMessageSettingsModel { NetworkMessageContentMask = NetworkMessageContentFlags.PublisherId | NetworkMessageContentFlags.WriterGroupId | NetworkMessageContentFlags.NetworkMessageNumber | NetworkMessageContentFlags.SequenceNumber | NetworkMessageContentFlags.PayloadHeader | NetworkMessageContentFlags.Timestamp | NetworkMessageContentFlags.DataSetClassId | (isSampleMode ? NetworkMessageContentFlags.MonitoredItemMessage : NetworkMessageContentFlags.NetworkMessageHeader) | NetworkMessageContentFlags.DataSetMessageHeader | extraNetworkMessageMask }, MessageType = encoding }; var seq = 1u; var subscriber = new Mock(); #pragma warning disable CA2000 // Dispose objects before losing scope var dataItem = new OpcUaMonitoredItem.DataChange(subscriber.Object, new DataMonitoredItemModel { StartNodeId = "i=2258" }, Log.Console(), TimeProvider.System); #pragma warning restore CA2000 // Dispose objects before losing scope #pragma warning disable CA2000 // Dispose objects before losing scope var eventItem = new OpcUaMonitoredItem.Event(subscriber.Object, new EventMonitoredItemModel { StartNodeId = "i=2258", EventFilter = new EventFilterModel() }, Log.Console(), TimeProvider.System); #pragma warning restore CA2000 // Dispose objects before losing scope eventItem.Fields.Add(("1", default)); eventItem.Fields.Add(("2", default)); eventItem.Fields.Add(("3", default)); eventItem.Fields.Add(("4", default)); eventItem.Fields.Add(("5", default)); eventItem.Fields.Add(("6", default)); for (uint i = 0; i < numOfMessages; i++) { var suffix = $"-{i}"; var notifications = new OpcUaMonitoredItem.MonitoredItemNotifications(); for (uint k = 0; k < i + 1; k++) { var notificationSuffix = suffix + $"-{k}"; var displayName = "DisplayName" + notificationSuffix; var nodeId = "NodeId" + notificationSuffix; if (eventList) { var eventFieldList = new EventFieldList { ClientHandle = k, EventFields = new Variant[] { 1, 2, 3, 4, 5, 6 }, Message = new NotificationMessage { SequenceNumber = seq++ } }; // Fake the item to be created as part of the subscription and grab the data eventItem.Template = eventItem.Template with { StartNodeId = nodeId, DataSetFieldId = nodeId, DataSetFieldName = displayName, }; eventItem.DisplayName = displayName; eventItem.StartNodeId = new NodeId(nodeId, 0); eventItem.Handle = eventItem; eventItem.Valid = true; eventItem.TryGetMonitoredItemNotifications(DateTimeOffset.UtcNow, eventFieldList, notifications); } else { var monitoredItemNotification = new MonitoredItemNotification { ClientHandle = k, Value = new DataValue(new Variant(k), new StatusCode(0), DateTime.UtcNow), Message = new NotificationMessage { SequenceNumber = seq++ } }; // Fake the item to be created as part of the subscription and grab the data dataItem.Template = dataItem.Template with { StartNodeId = nodeId, DataSetFieldId = nodeId, DataSetFieldName = displayName, }; dataItem.DisplayName = displayName; dataItem.StartNodeId = new NodeId(nodeId, 0); dataItem.Handle = dataItem; dataItem.Valid = true; dataItem.TryGetMonitoredItemNotifications(DateTimeOffset.UtcNow, monitoredItemNotification, notifications); } } #pragma warning disable CA5394 // Do not use insecure randomness var message = new OpcUaSubscriptionNotification(DateTimeOffset.UtcNow, notifications: notifications.Notifications[subscriber.Object]) { Context = new DataSetWriterContext { NextWriterSequenceNumber = () => i, DataSetWriterId = 1, Qos = null, Topic = randomTopic ? Guid.NewGuid().ToString() : string.Empty, Retain = false, Ttl = randomTopic ? TimeSpan.FromSeconds(Random.Shared.Next(60)) : null, PublisherId = publisherId, ExtensionFields = Array.Empty<(string, DataValue)>(), Schema = null, // TODO CloudEvent = null, // TODO Writer = writer, WriterName = writer.DataSetWriterName ?? Constants.DefaultDataSetWriterName, MetaData = null, WriterGroup = writerGroup }, PublishTimestamp = DateTimeOffset.UtcNow, MessageType = eventList ? Encoders.PubSub.MessageType.Event : Encoders.PubSub.MessageType.KeyFrame, EndpointUrl = "EndpointUrl" + suffix, ApplicationUri = "ApplicationUri" + suffix }; #pragma warning restore CA5394 // Do not use insecure randomness messages.Add(message); } return messages; } public void Dispose() { } public ValueTask SendAsync(CancellationToken ct = default) { return ValueTask.CompletedTask; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/Encoder/NetworkMessageEncoderJsonGzipTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Moq; using Opc.Ua; using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using Xunit; public class NetworkMessageEncoderJsonGzipTests { /// /// Create compliant encoder /// /// private static NetworkMessageEncoder GetEncoder() { var loggerMock = new Mock>(); var metricsMock = new Mock(); metricsMock.SetupGet(m => m.TagList).Returns(new TagList()); var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.UseStandardsCompliantEncoding = true; return new NetworkMessageEncoder(options, metricsMock.Object, loggerMock.Object); } [Theory] [InlineData(false)] [InlineData(true)] public void EmptyMessagesTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = new List(); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Empty(networkMessages); Assert.Equal(0, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(0, encoder.MessagesProcessedCount); } [Theory] [InlineData(false)] [InlineData(true)] public void EmptyDataSetMessageModelTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = new[] { new OpcUaSubscriptionNotification(DateTimeOffset.UtcNow) }; using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Empty(networkMessages); Assert.Equal(0, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(0, encoder.MessagesProcessedCount); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeTooBigJsonMessageTest(bool encodeBatchFlag) { const int maxMessageSize = 100; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(3, false, MessageEncoding.JsonGzip); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Empty(networkMessages); Assert.Equal(0, encoder.NotificationsProcessedCount); Assert.Equal(3, encoder.NotificationsDroppedCount); Assert.Equal(0, encoder.MessagesProcessedCount); } [Theory] [InlineData(true)] [InlineData(false)] public void EncodeJsonTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(20, false, MessageEncoding.JsonGzip); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); // Batch or no batch, the difference is that we cram all notifications // into a message or write all messages as array in batch mode. If // single message is desired, single message mode should be set (see next test). Assert.Equal(1, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(20, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(1, encoder.MessagesProcessedCount); Assert.Equal(20, encoder.AvgNotificationsPerMessage); } [Theory] [InlineData(true)] [InlineData(false)] public void EncodeChunkTest(bool encodeBatchFlag) { const int maxMessageSize = 8 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(500, false, MessageEncoding.JsonGzip); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); var count = networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count); Assert.All(networkMessages, m => Assert.All(((NetworkMessage)m.Event).Buffers, m => Assert.True(m.Length <= maxMessageSize, m.Length.ToString(CultureInfo.InvariantCulture)))); Assert.InRange(count, 150, 212); Assert.Equal(500, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal((uint)count, encoder.MessagesProcessedCount); Assert.InRange(Math.Round(encoder.AvgNotificationsPerMessage), 2, 3); } [Fact] public void EncodeJsonSingleMessageTest() { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(20, false, MessageEncoding.JsonGzip, NetworkMessageContentFlags.SingleDataSetMessage); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, false); Assert.Equal(20, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(20, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(20, encoder.MessagesProcessedCount); Assert.Equal(1, encoder.AvgNotificationsPerMessage); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeEventsJsonTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(20, true, MessageEncoding.JsonGzip); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Equal(1, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(20, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(1, encoder.MessagesProcessedCount); Assert.Equal(20, encoder.AvgNotificationsPerMessage); } [Fact] public void EncodeEventsSingleMessageJsonTest() { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(20, true, MessageEncoding.JsonGzip, NetworkMessageContentFlags.SingleDataSetMessage); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, false); // Single message, no array envelope due to batching resulting in 210 events from 20 notifications. Assert.Equal(210, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(20, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(210, encoder.MessagesProcessedCount); Assert.Equal(0.10, Math.Round(encoder.AvgNotificationsPerMessage, 2)); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeMetadataJsonTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(20, false, MessageEncoding.JsonGzip); messages[10] = messages[10] with { // Emit metadata MessageType = Encoders.PubSub.MessageType.Metadata, Context = ((DataSetWriterContext)messages[10].Context) with { MetaData = new PublishedDataSetMessageSchemaModel { Id = "dataset", DataSetFieldContentFlags = null, DataSetMessageContentFlags = null, MetaData = new PublishedDataSetMetaDataModel { DataSetMetaData = new DataSetMetaDataModel { Name = "test" }, Fields = new[] { new PublishedFieldMetaDataModel { Name = "test", BuiltInType = (byte)BuiltInType.UInt16 } } } } } }; using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Equal(3, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(19, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(3, encoder.MessagesProcessedCount); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeNothingTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(1, false, MessageEncoding.JsonGzip); messages[0].MessageType = Encoders.PubSub.MessageType.KeyFrame; messages[0].Notifications.Clear(); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Empty(networkMessages); Assert.Equal(0, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(0, encoder.MessagesProcessedCount); Assert.Equal(0, encoder.AvgNotificationsPerMessage); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeKeepAliveTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(1, false, MessageEncoding.JsonGzip); messages[0].MessageType = Encoders.PubSub.MessageType.KeepAlive; messages[0].Notifications.Clear(); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Single(networkMessages); Assert.Equal(1, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(1, encoder.MessagesProcessedCount); Assert.Equal(1, encoder.AvgNotificationsPerMessage); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/Encoder/NetworkMessageEncoderJsonTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Moq; using Opc.Ua; using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using Xunit; public class NetworkMessageEncoderJsonTests { /// /// Create compliant encoder /// /// private static NetworkMessageEncoder GetEncoder() { var loggerMock = new Mock>(); var metricsMock = new Mock(); metricsMock.SetupGet(m => m.TagList).Returns(new TagList()); var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.UseStandardsCompliantEncoding = true; return new NetworkMessageEncoder(options, metricsMock.Object, loggerMock.Object); } [Theory] [InlineData(false)] [InlineData(true)] public void EmptyMessagesTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = new List(); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Empty(networkMessages); Assert.Equal(0, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(0, encoder.MessagesProcessedCount); } [Theory] [InlineData(false)] [InlineData(true)] public void EmptyDataSetMessageModelTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = new[] { new OpcUaSubscriptionNotification(DateTimeOffset.UtcNow) }; using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Empty(networkMessages); Assert.Equal(0, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(0, encoder.MessagesProcessedCount); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeTooBigJsonMessageTest(bool encodeBatchFlag) { const int maxMessageSize = 100; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(3, false, MessageEncoding.Json); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Empty(networkMessages); Assert.Equal(0, encoder.NotificationsProcessedCount); Assert.Equal(3, encoder.NotificationsDroppedCount); Assert.Equal(0, encoder.MessagesProcessedCount); } [Theory] [InlineData(true)] [InlineData(false)] public void EncodeJsonTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(20, false, MessageEncoding.Json); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); // Batch or no batch, the difference is that we cram all notifications // into a message or write all messages as array in batch mode. If // single message is desired, single message mode should be set (see next test). Assert.Equal(1, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(20, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(1, encoder.MessagesProcessedCount); Assert.Equal(20, encoder.AvgNotificationsPerMessage); } [Theory] [InlineData(true)] [InlineData(false)] public void EncodeJsonWithRandomTopicTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(20, false, MessageEncoding.Json, randomTopic: true); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); // Batch or no batch, each notification has its own topic, so every single one generates a message Assert.Equal(20, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(20, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(20, encoder.MessagesProcessedCount); Assert.Equal(1, encoder.AvgNotificationsPerMessage); } [Theory] [InlineData(true)] [InlineData(false)] public void EncodeChunkTest(bool encodeBatchFlag) { const int maxMessageSize = 8 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(500, false, MessageEncoding.Json); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); var count = networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count(b => b.Length != 0)); Assert.All(networkMessages, m => Assert.All(((NetworkMessage)m.Event).Buffers, m => Assert.True(m.Length <= maxMessageSize, m.Length.ToString(CultureInfo.InvariantCulture)))); Assert.InRange(count, 65, 68); Assert.Equal(95, encoder.NotificationsProcessedCount); Assert.Equal((uint)500 - 95, encoder.NotificationsDroppedCount); Assert.Equal((uint)count, encoder.MessagesProcessedCount); Assert.Equal(1, Math.Round(encoder.AvgNotificationsPerMessage)); } [Theory] [InlineData(true)] [InlineData(false)] public void EncodeJsonSingleMessageTest(bool randomTopic) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(20, false, MessageEncoding.Json, NetworkMessageContentFlags.SingleDataSetMessage, randomTopic: randomTopic); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, false); Assert.Equal(20, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(20, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(20, encoder.MessagesProcessedCount); Assert.Equal(1, encoder.AvgNotificationsPerMessage); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeEventsJsonTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(20, true, MessageEncoding.Json); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Equal(1, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(20, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(1, encoder.MessagesProcessedCount); Assert.Equal(20, encoder.AvgNotificationsPerMessage); } [Fact] public void EncodeEventsSingleMessageJsonTest() { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(20, true, MessageEncoding.Json, NetworkMessageContentFlags.SingleDataSetMessage); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, false); // Single message, no array envelope due to batching resulting in 210 events from 20 notifications. Assert.Equal(210, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(20, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(210, encoder.MessagesProcessedCount); Assert.Equal(0.10, Math.Round(encoder.AvgNotificationsPerMessage, 2)); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeMetadataJsonTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(20, false, MessageEncoding.Json); messages[10] = messages[10] with { // Emit metadata MessageType = Encoders.PubSub.MessageType.Metadata, Context = ((DataSetWriterContext)messages[10].Context) with { MetaData = new PublishedDataSetMessageSchemaModel { Id = "dataset", DataSetFieldContentFlags = null, DataSetMessageContentFlags = null, MetaData = new PublishedDataSetMetaDataModel { DataSetMetaData = new DataSetMetaDataModel { Name = "test" }, Fields = new[] { new PublishedFieldMetaDataModel { Name = "test", BuiltInType = (byte)BuiltInType.UInt16 } } } } } }; using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Equal(3, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(19, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(3, encoder.MessagesProcessedCount); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeNothingTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(1, false, MessageEncoding.Json); messages[0].MessageType = Encoders.PubSub.MessageType.KeyFrame; messages[0].Notifications.Clear(); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Empty(networkMessages); Assert.Equal(0, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(0, encoder.MessagesProcessedCount); Assert.Equal(0, encoder.AvgNotificationsPerMessage); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeKeepAliveTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(1, false, MessageEncoding.Json); messages[0].MessageType = Encoders.PubSub.MessageType.KeepAlive; messages[0].Notifications.Clear(); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Single(networkMessages); Assert.Equal(1, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(1, encoder.MessagesProcessedCount); Assert.Equal(1, encoder.AvgNotificationsPerMessage); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/Encoder/NetworkMessageEncoderLegacyTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Moq; using Opc.Ua; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using Xunit; public class NetworkMessageEncoderLegacyTests { /// /// Create legacy encoder /// /// private static NetworkMessageEncoder GetEncoder() { var loggerMock = new Mock>(); var metricsMock = new Mock(); metricsMock.SetupGet(m => m.TagList).Returns(new TagList()); var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.UseStandardsCompliantEncoding = false; return new NetworkMessageEncoder(options, metricsMock.Object, loggerMock.Object); } [Theory] [InlineData(false)] [InlineData(true)] public void EmptyMessagesTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = new List(); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Empty(networkMessages); Assert.Equal(0, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(0, encoder.MessagesProcessedCount); } [Theory] [InlineData(false)] [InlineData(true)] public void EmptyDataSetMessageModelTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = new[] { new OpcUaSubscriptionNotification(DateTimeOffset.UtcNow) }; using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Empty(networkMessages); Assert.Equal(0, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(0, encoder.MessagesProcessedCount); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeTooBigJsonMessageTest(bool encodeBatchFlag) { const int maxMessageSize = 100; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(3, false, MessageEncoding.Json); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Empty(networkMessages); Assert.Equal(0, encoder.NotificationsProcessedCount); Assert.Equal(3, encoder.NotificationsDroppedCount); Assert.Equal(0, encoder.MessagesProcessedCount); } [Theory] [InlineData(true)] [InlineData(false)] public void EncodeJsonTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(20, false, MessageEncoding.Json); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); // Batch or no batch, the difference is that we cram all notifications // into a message or write all messages as array in batch mode. If // single message is desired, single message mode should be set (see next test). Assert.Equal(1, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(20, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(1, encoder.MessagesProcessedCount); Assert.Equal(20, encoder.AvgNotificationsPerMessage); } [Theory] [InlineData(true)] [InlineData(false)] public void EncodeChunkTest(bool encodeBatchFlag) { const int maxMessageSize = 8 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(500, false, MessageEncoding.Json); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); var count = networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count(b => b.Length != 0)); Assert.InRange(count, 66, 68); Assert.Equal(95, encoder.NotificationsProcessedCount); Assert.Equal((uint)500 - 95, encoder.NotificationsDroppedCount); Assert.Equal((uint)count, encoder.MessagesProcessedCount); Assert.Equal(1, Math.Round(encoder.AvgNotificationsPerMessage)); } [Fact] public void EncodeJsonSingleMessageTest() { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(20, false, MessageEncoding.Json, NetworkMessageContentFlags.SingleDataSetMessage); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, false); Assert.Equal(20, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(20, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(20, encoder.MessagesProcessedCount); Assert.Equal(1, encoder.AvgNotificationsPerMessage); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeEventsJsonTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(20, true, MessageEncoding.Json); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Equal(1, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(20, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(1, encoder.MessagesProcessedCount); Assert.Equal(20, encoder.AvgNotificationsPerMessage); } [Fact] public void EncodeEventsSingleMessageJsonTest() { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(20, true, MessageEncoding.Json, NetworkMessageContentFlags.SingleDataSetMessage); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, false); // Single message, no array envelope due to batching resulting in 210 events from 20 notifications. Assert.Equal(210, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(20, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(210, encoder.MessagesProcessedCount); Assert.Equal(0.10, Math.Round(encoder.AvgNotificationsPerMessage, 2)); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeMetadataJsonTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(20, false, MessageEncoding.Json); messages[10] = messages[10] with { // Emit metadata MessageType = Encoders.PubSub.MessageType.Metadata, Context = ((DataSetWriterContext)messages[10].Context) with { MetaData = new PublishedDataSetMessageSchemaModel { Id = "dataset", DataSetFieldContentFlags = null, DataSetMessageContentFlags = null, MetaData = new PublishedDataSetMetaDataModel { DataSetMetaData = new DataSetMetaDataModel { Name = "test" }, Fields = new[] { new PublishedFieldMetaDataModel { Name = "test", BuiltInType = (byte)BuiltInType.UInt16 } } } } } }; using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Equal(3, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(19, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(3, encoder.MessagesProcessedCount); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeNothingTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(1, false, MessageEncoding.Json); messages[0].MessageType = Encoders.PubSub.MessageType.KeyFrame; messages[0].Notifications.Clear(); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Empty(networkMessages); Assert.Equal(0, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(0, encoder.MessagesProcessedCount); Assert.Equal(0, encoder.AvgNotificationsPerMessage); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeKeepAliveTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(1, false, MessageEncoding.Json); messages[0].MessageType = Encoders.PubSub.MessageType.KeepAlive; messages[0].Notifications.Clear(); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Single(networkMessages); Assert.Equal(1, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(1, encoder.MessagesProcessedCount); Assert.Equal(1, encoder.AvgNotificationsPerMessage); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/Encoder/NetworkMessageEncoderUadpTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services { using Azure.IIoT.OpcUa.Publisher; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Moq; using Opc.Ua; using System; using System.Diagnostics; using System.Globalization; using System.Linq; using Xunit; public class NetworkMessageEncoderUadpTests { private static NetworkMessageEncoder GetEncoder() { var loggerMock = new Mock>(); var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); var metricsMock = new Mock(); metricsMock.SetupGet(m => m.TagList).Returns(new TagList()); return new NetworkMessageEncoder(options, metricsMock.Object, loggerMock.Object); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeChunkedUadpMessageTest1(bool encodeBatchFlag) { const int maxMessageSize = 100; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(10, false, MessageEncoding.Uadp); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Equal(33, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.All(networkMessages, m => Assert.All(((NetworkMessage)m.Event).Buffers, m => Assert.True(m.Length <= maxMessageSize, m.Length.ToString(CultureInfo.InvariantCulture)))); Assert.Equal(10, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(33, encoder.MessagesProcessedCount); Assert.Equal(0.30, Math.Round(encoder.AvgNotificationsPerMessage, 2)); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeChunkedUadpMessageTest2(bool encodeBatchFlag) { const int maxMessageSize = 100; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(100, false, MessageEncoding.Uadp); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Equal(2025, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.All(networkMessages, m => Assert.All(((NetworkMessage)m.Event).Buffers, m => Assert.True(m.Length <= maxMessageSize, m.Length.ToString(CultureInfo.InvariantCulture)))); Assert.Equal(100, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(2025, encoder.MessagesProcessedCount); Assert.Equal(0.05, Math.Round(encoder.AvgNotificationsPerMessage, 2)); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeUadpTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(20, false, MessageEncoding.Uadp); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Equal(1, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(20, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(1, encoder.MessagesProcessedCount); Assert.Equal(20, encoder.AvgNotificationsPerMessage); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeEventsUadpTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(20, true, MessageEncoding.Uadp); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Equal(1, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(20, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(1, encoder.MessagesProcessedCount); Assert.Equal(20, encoder.AvgNotificationsPerMessage); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeMetadataUadpTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(20, false, MessageEncoding.Uadp); messages[10] = messages[10] with { // Emit metadata MessageType = Encoders.PubSub.MessageType.Metadata, Context = ((DataSetWriterContext)messages[10].Context) with { MetaData = new PublishedDataSetMessageSchemaModel { Id = "dataset", DataSetFieldContentFlags = null, DataSetMessageContentFlags = null, MetaData = new PublishedDataSetMetaDataModel { DataSetMetaData = new DataSetMetaDataModel { Name = "test" }, Fields = new[] { new PublishedFieldMetaDataModel { Name = "test", BuiltInType = (byte)BuiltInType.UInt16 } } } } } }; using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Equal(3, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(19, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(3, encoder.MessagesProcessedCount); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeMetadataUadpChunkTest(bool encodeBatchFlag) { const int maxMessageSize = 100; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(1, false, MessageEncoding.Uadp); messages[0] = messages[0] with { // Emit metadata MessageType = Encoders.PubSub.MessageType.Metadata, Context = ((DataSetWriterContext)messages[0].Context) with { MetaData = new PublishedDataSetMessageSchemaModel { Id = "dataset", DataSetFieldContentFlags = null, DataSetMessageContentFlags = null, MetaData = new PublishedDataSetMetaDataModel { DataSetMetaData = new DataSetMetaDataModel { Name = "test" }, Fields = Enumerable.Range(0, 10000) .Select(r => new PublishedFieldMetaDataModel { Name = "testfield" + r, BuiltInType = (byte)BuiltInType.UInt16 }) .ToList() } } } }; using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Equal(8194, networkMessages.Sum(m => ((NetworkMessage)m.Event).Buffers.Count)); Assert.Equal(0, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(8194, encoder.MessagesProcessedCount); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeNothingTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(1, false, MessageEncoding.Uadp); messages[0].MessageType = Encoders.PubSub.MessageType.KeyFrame; messages[0].Notifications.Clear(); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Empty(networkMessages); Assert.Equal(0, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(0, encoder.MessagesProcessedCount); Assert.Equal(0, encoder.AvgNotificationsPerMessage); } [Theory] [InlineData(false)] [InlineData(true)] public void EncodeKeepAliveTest(bool encodeBatchFlag) { const int maxMessageSize = 256 * 1024; var messages = NetworkMessage.GenerateSampleSubscriptionNotifications(1, false, MessageEncoding.Uadp); messages[0].MessageType = Encoders.PubSub.MessageType.KeepAlive; messages[0].Notifications.Clear(); using var encoder = GetEncoder(); var networkMessages = encoder.Encode(NetworkMessage.Create, messages, maxMessageSize, encodeBatchFlag); Assert.Single(networkMessages); Assert.Equal(1, encoder.NotificationsProcessedCount); Assert.Equal(0, encoder.NotificationsDroppedCount); Assert.Equal(1, encoder.MessagesProcessedCount); Assert.Equal(1, encoder.AvgNotificationsPerMessage); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/FileSystem/BrowseTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.FileSystem { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; [Collection(FileCollection.Name)] public class BrowseTests { public BrowseTests(FileSystemServer server) { _server = server; } private BrowseTests GetTests() { return new BrowseTests( () => new FileSystemServices(_server.Client, new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions()), _server.GetConnection(), _server.TempPath); } private readonly FileSystemServer _server; [Fact] public Task GetFileSystemsTest1Async() { return GetTests().GetFileSystemsTest1Async(); } [Fact] public Task GetDirectoriesTest1Async() { return GetTests().GetDirectoriesTest1Async(); } [Fact] public Task GetDirectoriesTest2Async() { return GetTests().GetDirectoriesTest2Async(); } [Fact] public Task GetDirectoriesTest3Async() { return GetTests().GetDirectoriesTest3Async(); } [Fact] public Task GetDirectoriesTest4Async() { return GetTests().GetDirectoriesTest4Async(); } [Fact] public Task GetDirectoriesTest5Async() { return GetTests().GetDirectoriesTest5Async(); } [Fact] public Task GetDirectoriesTest6Async() { return GetTests().GetDirectoriesTest6Async(); } [Fact] public Task GetFilesTest1Async() { return GetTests().GetFilesTest1Async(); } [Fact] public Task GetFilesTest2Async() { return GetTests().GetFilesTest2Async(); } [Fact] public Task GetFilesTest3Async() { return GetTests().GetFilesTest3Async(); } [Fact] public Task GetFilesTest4Async() { return GetTests().GetFilesTest4Async(); } [Fact] public Task GetFilesTest5Async() { return GetTests().GetFilesTest5Async(); } [Fact] public Task GetFilesTest6Async() { return GetTests().GetFilesTest6Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/FileSystem/FileCollection.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.FileSystem { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public class FileCollection : ICollectionFixture { public const string Name = "FileSystem"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/FileSystem/OperationsTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.FileSystem { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; [Collection(FileCollection.Name)] public class OperationsTests { public OperationsTests(FileSystemServer server) { _server = server; } private OperationsTests GetTests() { return new OperationsTests( () => new FileSystemServices(_server.Client, new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions()), _server.GetConnection(), _server.TempPath); } private readonly FileSystemServer _server; [Fact] public Task CreateDirectoryTest1Async() { return GetTests().CreateDirectoryTest1Async(); } [Fact] public Task CreateDirectoryTest2Async() { return GetTests().CreateDirectoryTest2Async(); } [Fact] public Task CreateDirectoryTest3Async() { return GetTests().CreateDirectoryTest3Async(); } [Fact] public Task CreateDirectoryTest4Async() { return GetTests().CreateDirectoryTest4Async(); } [Fact] public Task DeleteDirectoryTest1Async() { return GetTests().DeleteDirectoryTest1Async(); } [Fact] public Task DeleteDirectoryTest2Async() { return GetTests().DeleteDirectoryTest2Async(); } [Fact] public Task DeleteDirectoryTest3Async() { return GetTests().DeleteDirectoryTest3Async(); } [Fact] public Task CreateFileTest1Async() { return GetTests().CreateFileTest1Async(); } [Fact] public Task CreateFileTest2Async() { return GetTests().CreateFileTest2Async(); } [Fact] public Task CreateFileTest3Async() { return GetTests().CreateFileTest3Async(); } [Fact] public Task CreateFileTest4Async() { return GetTests().CreateFileTest4Async(); } [Fact] public Task GetFileInfoTest1Async() { return GetTests().GetFileInfoTest1Async(); } [Fact] public Task GetFileInfoTest2Async() { return GetTests().GetFileInfoTest2Async(); } [Fact] public Task GetFileInfoTest3Async() { return GetTests().GetFileInfoTest3Async(); } [Fact] public Task DeleteFileTest1Async() { return GetTests().DeleteFileTest1Async(); } [Fact] public Task DeleteFileTest2Async() { return GetTests().DeleteFileTest2Async(); } [Fact] public Task DeleteFileTest3Async() { return GetTests().DeleteFileTest3Async(); } [Fact] public Task DeleteFileTest4Async() { return GetTests().DeleteFileTest4Async(); } [Fact] public Task DeleteFileTest5Async() { return GetTests().DeleteFileTest5Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/FileSystem/ReadTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.FileSystem { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; [Collection(FileCollection.Name)] public class ReadTests { public ReadTests(FileSystemServer server) { _server = server; } private ReadTests GetTests() { return new ReadTests( () => new FileSystemServices(_server.Client, new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions()), _server.GetConnection(), _server.TempPath); } private readonly FileSystemServer _server; [Fact] public Task ReadFileTest0Async() { return GetTests().ReadFileTest0Async(); } [Fact] public Task ReadFileTest1Async() { return GetTests().ReadFileTest1Async(); } [Fact] public Task ReadFileTest2Async() { return GetTests().ReadFileTest2Async(); } [Fact] public Task ReadFileTest3Async() { return GetTests().ReadFileTest3Async(); } [Fact] public Task ReadFileTest4Async() { return GetTests().ReadFileTest4Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/FileSystem/WriteTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.FileSystem { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; [Collection(FileCollection.Name)] public class WriteTests { public WriteTests(FileSystemServer server) { _server = server; } private WriteTests GetTests() { return new WriteTests( () => new FileSystemServices(_server.Client, new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions()), _server.GetConnection(), _server.TempPath); } private readonly FileSystemServer _server; [Fact] public Task WriteFileTest0Async() { return GetTests().WriteFileTest0Async(); } [Fact] public Task WriteFileTest1Async() { return GetTests().WriteFileTest1Async(); } [Fact] public Task WriteFileTest2Async() { return GetTests().WriteFileTest2Async(); } [Fact] public Task AppendFileTest0Async() { return GetTests().AppendFileTest0Async(); } [Fact] public Task AppendFileTest1Async() { return GetTests().AppendFileTest1Async(); } [Fact] public Task AppendFileTest2Async() { return GetTests().AppendFileTest2Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/HistoricalAccess/NodeServicesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.HistoricalAccess { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class NodeServicesTests { public NodeServicesTests(HistoricalAccessServer server, ITestOutputHelper output) { _server = server; _output = output; } private NodeHistoricalAccessTests GetTests() { return new NodeHistoricalAccessTests( () => new NodeServices(_server.Client, _server.Parser, _output.BuildLoggerFor>(Logging.Level), new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions()), _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly ITestOutputHelper _output; [Fact] public Task GetServerCapabilitiesTestAsync() { return GetTests().GetServerCapabilitiesTestAsync(); } [Fact] public Task HistoryGetServerCapabilitiesTestAsync() { return GetTests().HistoryGetServerCapabilitiesTestAsync(); } [Fact] public Task HistoryGetInt16NodeHistoryConfiguration() { return GetTests().HistoryGetInt16NodeHistoryConfigurationAsync(); } [Fact] public Task HistoryGetInt64NodeHistoryConfigurationAsync() { return GetTests().HistoryGetInt64NodeHistoryConfigurationAsync(); } [Fact] public Task HistoryGetNodeHistoryConfigurationFromBadNode() { return GetTests().HistoryGetNodeHistoryConfigurationFromBadNodeAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/HistoricalAccess/ReadAtTimesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.HistoricalAccess { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class ReadAtTimesTests { public ReadAtTimesTests(HistoricalAccessServer server, ITestOutputHelper output) { _server = server; _output = output; } private HistoryReadValuesAtTimesTests GetTests() { return new HistoryReadValuesAtTimesTests(_server, () => new HistoryServices( new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(), new NodeServices(_server.Client, _server.Parser, _output.BuildLoggerFor>(Logging.Level), new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions())), _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly ITestOutputHelper _output; [Fact] public Task HistoryReadInt32ValuesAtTimesTest1Async() { return GetTests().HistoryReadInt32ValuesAtTimesTest1Async(); } [Fact] public Task HistoryReadInt32ValuesAtTimesTest2Async() { return GetTests().HistoryReadInt32ValuesAtTimesTest2Async(); } [Fact] public Task HistoryReadInt32ValuesAtTimesTest3Async() { return GetTests().HistoryReadInt32ValuesAtTimesTest3Async(); } [Fact] public Task HistoryReadInt32ValuesAtTimesTest4Async() { return GetTests().HistoryReadInt32ValuesAtTimesTest4Async(); } [Fact] public Task HistoryStreamInt32ValuesAtTimesTest1Async() { return GetTests().HistoryStreamInt32ValuesAtTimesTest1Async(); } [Fact] public Task HistoryStreamInt32ValuesAtTimesTest2Async() { return GetTests().HistoryStreamInt32ValuesAtTimesTest2Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/HistoricalAccess/ReadCollection.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.HistoricalAccess { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public class ReadCollection : ICollectionFixture { public const string Name = "HistoricalAccessRead"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/HistoricalAccess/ReadModifiedTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.HistoricalAccess { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class ReadModifiedTests { public ReadModifiedTests(HistoricalAccessServer server, ITestOutputHelper output) { _server = server; _output = output; } private HistoryReadValuesModifiedTests GetTests() { return new HistoryReadValuesModifiedTests(_server, () => new HistoryServices( new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(), new NodeServices(_server.Client, _server.Parser, _output.BuildLoggerFor>(Logging.Level), new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions())), _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly ITestOutputHelper _output; [Fact] public Task HistoryReadInt16ValuesModifiedTestAsync() { return GetTests().HistoryReadInt16ValuesModifiedTestAsync(); } [Fact] public Task HistoryStreamInt16ValuesModifiedTestAsync() { return GetTests().HistoryStreamInt16ValuesModifiedTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/HistoricalAccess/ReadProcessedTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.HistoricalAccess { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class ReadProcessedTests { public ReadProcessedTests(HistoricalAccessServer server, ITestOutputHelper output) { _server = server; _output = output; } private HistoryReadValuesProcessedTests GetTests() { return new HistoryReadValuesProcessedTests(_server, () => new HistoryServices( new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(), new NodeServices(_server.Client, _server.Parser, _output.BuildLoggerFor>(Logging.Level), new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions())), _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly ITestOutputHelper _output; [Fact] public Task HistoryReadUInt64ProcessedValuesTest1Async() { return GetTests().HistoryReadUInt64ProcessedValuesTest1Async(); } [Fact] public Task HistoryReadUInt64ProcessedValuesTest2Async() { return GetTests().HistoryReadUInt64ProcessedValuesTest2Async(); } [Fact] public Task HistoryReadUInt64ProcessedValuesTest3Async() { return GetTests().HistoryReadUInt64ProcessedValuesTest3Async(); } [Fact] public Task HistoryStreamUInt64ProcessedValuesTest1Async() { return GetTests().HistoryStreamUInt64ProcessedValuesTest1Async(); } [Fact] public Task HistoryStreamUInt64ProcessedValuesTest2Async() { return GetTests().HistoryStreamUInt64ProcessedValuesTest2Async(); } [Fact] public Task HistoryStreamUInt64ProcessedValuesTest3Async() { return GetTests().HistoryStreamUInt64ProcessedValuesTest3Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/HistoricalAccess/ReadValuesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.HistoricalAccess { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class ReadValuesTests { public ReadValuesTests(HistoricalAccessServer server, ITestOutputHelper output) { _server = server; _output = output; } private HistoryReadValuesTests GetTests() { return new HistoryReadValuesTests(_server, () => new HistoryServices( new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(), new NodeServices(_server.Client, _server.Parser, _output.BuildLoggerFor>(Logging.Level), new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions())), _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly ITestOutputHelper _output; [Fact] public Task HistoryReadInt64ValuesTest1Async() { return GetTests().HistoryReadInt64ValuesTest1Async(); } [Fact] public Task HistoryReadInt64ValuesTest2Async() { return GetTests().HistoryReadInt64ValuesTest2Async(); } [Fact] public Task HistoryReadInt64ValuesTest3Async() { return GetTests().HistoryReadInt64ValuesTest3Async(); } [Fact] public Task HistoryReadInt64ValuesTest4Async() { return GetTests().HistoryReadInt64ValuesTest4Async(); } [Fact] public Task HistoryStreamInt64ValuesTest1Async() { return GetTests().HistoryStreamInt64ValuesTest1Async(); } [Fact] public Task HistoryStreamInt64ValuesTest2Async() { return GetTests().HistoryStreamInt64ValuesTest2Async(); } [Fact] public Task HistoryStreamInt64ValuesTest3Async() { return GetTests().HistoryStreamInt64ValuesTest3Async(); } [Fact] public Task HistoryStreamInt64ValuesTest4Async() { return GetTests().HistoryStreamInt64ValuesTest4Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/HistoricalAccess/UpdateValuesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.HistoricalAccess { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class UpdateValuesTests { public UpdateValuesTests(HistoricalAccessServer server, ITestOutputHelper output) { _server = server; _output = output; } private HistoryUpdateValuesTests GetTests() { return new HistoryUpdateValuesTests( () => new HistoryServices( new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(), new NodeServices(_server.Client, _server.Parser, _output.BuildLoggerFor>(Logging.Level), new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions())), _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly ITestOutputHelper _output; [Fact] public Task HistoryUpsertUInt32ValuesTest1Async() { return GetTests().HistoryUpsertUInt32ValuesTest1Async(); } [Fact] public Task HistoryUpsertUInt32ValuesTest2Async() { return GetTests().HistoryUpsertUInt32ValuesTest2Async(); } [Fact] public Task HistoryInsertUInt32ValuesTest1Async() { return GetTests().HistoryInsertUInt32ValuesTest1Async(); } [Fact] public Task HistoryInsertUInt32ValuesTest2Async() { return GetTests().HistoryInsertUInt32ValuesTest2Async(); } [Fact] public Task HistoryReplaceUInt32ValuesTest1Async() { return GetTests().HistoryReplaceUInt32ValuesTest1Async(); } [Fact] public Task HistoryReplaceUInt32ValuesTest2Async() { return GetTests().HistoryReplaceUInt32ValuesTest2Async(); } [Fact] public Task HistoryInsertDeleteUInt32ValuesTest1Async() { return GetTests().HistoryInsertDeleteUInt32ValuesTest1Async(); } [Fact] public Task HistoryInsertDeleteUInt32ValuesTest2Async() { return GetTests().HistoryInsertDeleteUInt32ValuesTest2Async(); } [Fact] public Task HistoryInsertDeleteUInt32ValuesTest3Async() { return GetTests().HistoryInsertDeleteUInt32ValuesTest3Async(); } [Fact] public Task HistoryInsertDeleteUInt32ValuesTest4Async() { return GetTests().HistoryInsertDeleteUInt32ValuesTest4Async(); } [Fact] public Task HistoryDeleteUInt32ValuesTest1Async() { return GetTests().HistoryDeleteUInt32ValuesTest1Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/HistoricalEvents/NodeServicesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.HistoricalEvents { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class NodeServicesTests { public NodeServicesTests(HistoricalEventsServer server, ITestOutputHelper output) { _server = server; _output = output; } private NodeHistoricalEventsTests GetTests() { return new NodeHistoricalEventsTests( () => new NodeServices(_server.Client, _server.Parser, _output.BuildLoggerFor>(Logging.Level), new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions()), _server.GetConnection()); } private readonly HistoricalEventsServer _server; private readonly ITestOutputHelper _output; [Fact] public Task GetServerCapabilitiesTestAsync() { return GetTests().GetServerCapabilitiesTestAsync(); } [Fact] public Task HistoryGetServerCapabilitiesTestAsync() { return GetTests().HistoryGetServerCapabilitiesTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/HistoricalEvents/ReadCollection.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.HistoricalEvents { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public class ReadCollection : ICollectionFixture { public const string Name = "HistoricalEventsRead"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/Plc/NodeServicesTests1.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.Plc { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class NodeServicesTests1 : IClassFixture { public NodeServicesTests1(PlcServer server, ITestOutputHelper output) { _output = output; _server = server; } private SimulatorNodesTests GetTests() { return new SimulatorNodesTests(_server, () => new NodeServices(_server.Client, _server.Parser, _output.BuildLoggerFor>(Logging.Level), new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions()), _server.GetConnection()); } private readonly ITestOutputHelper _output; private readonly PlcServer _server; [Fact] public Task AlternatingBooleanTelemetryChangesWithPeriodAsync() { return GetTests().AlternatingBooleanTelemetryChangesWithPeriodAsync(); } [Fact] public Task BadNodeHasAlternatingStatusCodeAsync() { return GetTests().BadNodeHasAlternatingStatusCodeAsync(); } [Fact] public Task FastLimitNumberOfUpdatesStopsUpdatingAfterLimitAsync() { return GetTests().FastLimitNumberOfUpdatesStopsUpdatingAfterLimitAsync(); } [Fact] public Task FastUIntScalar1TelemetryChangesWithPeriodAsync() { return GetTests().FastUIntScalar1TelemetryChangesWithPeriodAsync(); } [Fact] public Task NegativeTrendDataNodeHasValueWithTrendAsync() { return GetTests().NegativeTrendDataNodeHasValueWithTrendAsync(); } [Fact] public Task NegativeTrendDataTelemetryChangesWithPeriodAsync() { return GetTests().NegativeTrendDataTelemetryChangesWithPeriodAsync(); } [Fact] public Task PositiveTrendDataNodeHasValueWithTrendAsync() { return GetTests().PositiveTrendDataNodeHasValueWithTrendAsync(); } [Fact] public Task PositiveTrendDataTelemetryChangesWithPeriodAsync() { return GetTests().PositiveTrendDataTelemetryChangesWithPeriodAsync(); } [Fact] public Task RandomSignedInt32TelemetryChangesWithPeriodAsync() { return GetTests().RandomSignedInt32TelemetryChangesWithPeriodAsync(); } [Fact] public Task RandomUnsignedInt32TelemetryChangesWithPeriodAsync() { return GetTests().RandomUnsignedInt32TelemetryChangesWithPeriodAsync(); } [Fact] public Task SlowLimitNumberOfUpdatesStopsUpdatingAfterLimitAsync() { return GetTests().SlowLimitNumberOfUpdatesStopsUpdatingAfterLimitAsync(); } [Fact] public Task SlowUIntScalar1TelemetryChangesWithPeriodAsync() { return GetTests().SlowUIntScalar1TelemetryChangesWithPeriodAsync(); } [Fact] public Task TelemetryContainsOutlierInDipDataAsync() { return GetTests().TelemetryContainsOutlierInDipDataAsync(); } [Fact] public Task TelemetryContainsOutlierInSpikeDataAsync() { return GetTests().TelemetryContainsOutlierInSpikeDataAsync(); } [Fact] public Task TelemetryFastNodeTestAsync() { return GetTests().TelemetryFastNodeTestAsync(); } [Fact] public Task TelemetryStepUpTestAsync() { return GetTests().TelemetryStepUpTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/Plc/NodeServicesTests2.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.Plc { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class NodeServicesTests2 : IClassFixture { public NodeServicesTests2(PlcServer server, ITestOutputHelper output) { _output = output; _server = server; } private PlcModelComplexTypeTests GetTests() { return new PlcModelComplexTypeTests(_server, () => new NodeServices(_server.Client, _server.Parser, _output.BuildLoggerFor>(Logging.Level), new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions()), _server.GetConnection()); } private readonly ITestOutputHelper _output; private readonly PlcServer _server; [Fact] public Task PlcModelHeaterTestsAsync() { return GetTests().PlcModelHeaterTestsAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/PublishedNodesJsonServicesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services { using Azure.IIoT.OpcUa.Publisher.Tests.Utils; using Azure.IIoT.OpcUa.Publisher; using Azure.IIoT.OpcUa.Publisher.Config.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack.Runtime; using Azure.IIoT.OpcUa.Publisher.Storage; using FluentAssertions; using Furly.Exceptions; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Moq; using Neovolve.Logging.Xunit; using Publisher.Services; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; /// /// Tests the publisher configuration services /// public class PublishedNodesJsonServicesTests : TempFileProviderBase { /// /// Constructor that initializes common resources used by tests. /// /// public PublishedNodesJsonServicesTests(ITestOutputHelper output) { _newtonSoftJsonSerializer = new NewtonsoftJsonSerializer(); _loggerFactory = LogFactory.Create(output, Logging.Config); var clientConfigMock = new OpcUaClientConfig(new ConfigurationBuilder().Build()).ToOptions(); _options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); _options.Value.PublishedNodesFile = _tempFile; _options.Value.UseFileChangePolling = true; _options.Value.DefaultTransport = WriterGroupTransport.Mqtt; _options.Value.MessagingProfile = MessagingProfile.Get( MessagingMode.PubSub, MessageEncoding.Json); _publishedNodesJobConverter = new PublishedNodesConverter( _loggerFactory.CreateLogger(), _newtonSoftJsonSerializer, _options); // Note that each test is responsible for setting content of _tempFile; Utils.CopyContent("Publisher/empty_pn.json", _tempFile); using var factory = new PhysicalFileProviderFactory(_options, _loggerFactory.CreateLogger()); _publishedNodesProvider = new PublishedNodesProvider(factory, _options, _loggerFactory.CreateLogger()); _triggerMock = new Mock(); var factoryMock = new Mock(); var lifetime = new Mock(); lifetime.SetupGet(l => l.WriterGroup).Returns(_triggerMock.Object); factoryMock .Setup(factory => factory.Create(It.IsAny())) .Returns(lifetime.Object); _publisher = new PublisherService(factoryMock.Object, _options, _loggerFactory.CreateLogger()); } protected override void Dispose(bool disposing) { if (disposing) { _loggerFactory.Dispose(); _publishedNodesProvider.Dispose(); } base.Dispose(disposing); } /// /// This method should be called only after content of _tempFile is set. /// private PublishedNodesJsonServices InitPublisherConfigService() { var configService = new PublishedNodesJsonServices( _publishedNodesJobConverter, _publisher, _loggerFactory.CreateLogger(), _publishedNodesProvider, _newtonSoftJsonSerializer ); configService.GetAwaiter().GetResult(); return configService; } [Fact] public async Task TestCreateUpdateWithAmbigousNodesArgumentsAsync() { await using var configService = InitPublisherConfigService(); const int numberOfEndpoints = 3; var opcNodes = Enumerable.Range(0, numberOfEndpoints) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}", DataSetFieldId = "alwaysthesameid" }) .ToList(); var writer = GenerateEndpoint(0, opcNodes, false); writer.OpcNodes = opcNodes; // The call should throw an exception. await FluentActions .Invoking(async () => await configService.CreateOrUpdateDataSetWriterEntryAsync(writer)) .Should() .ThrowAsync() .WithMessage("Field ids must be present and unique."); } [Fact] public async Task TestCreateUpdateWithoutEndpointUrlThrowsAsync() { await using var configService = InitPublisherConfigService(); const int numberOfEndpoints = 3; var opcNodes = Enumerable.Range(0, numberOfEndpoints) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}" }) .ToList(); var writer = GenerateEndpoint(0, opcNodes, false); writer.OpcNodes = opcNodes; writer.EndpointUrl = null; // The call should throw an exception. await FluentActions .Invoking(async () => await configService.CreateOrUpdateDataSetWriterEntryAsync(writer)) .Should() .ThrowAsync() .WithMessage("Missing endpoint url in entry"); } [Fact] public async Task TestCreateUpdateWithoutNodeIdThrowsAsync() { await using var configService = InitPublisherConfigService(); const int numberOfEndpoints = 3; var opcNodes = Enumerable.Range(0, numberOfEndpoints) .Select(i => new OpcNodeModel { DataSetFieldId = $"{i}" }) .ToList(); var writer = GenerateEndpoint(0, opcNodes, false); writer.OpcNodes = opcNodes; // The call should throw an exception. await FluentActions .Invoking(async () => await configService.CreateOrUpdateDataSetWriterEntryAsync(writer)) .Should() .ThrowAsync() .WithMessage("Node must contain a node ID"); } [Fact] public async Task TestCreateUpdateWithWithNodeIdAsDataSetFieldAsync() { await using var configService = InitPublisherConfigService(); const int numberOfEndpoints = 3; var opcNodes = Enumerable.Range(0, numberOfEndpoints) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}" }) .ToList(); var writer = GenerateEndpoint(0, opcNodes, false); writer.OpcNodes = opcNodes; // The call should not throw an exception. await configService.CreateOrUpdateDataSetWriterEntryAsync(writer); } [Theory] [InlineData(true)] [InlineData(false)] public async Task TestCreateUpdateWithNodesWithPublishingIntervalSetArgumentsAsync(bool timespan) { await using var configService = InitPublisherConfigService(); const int numberOfEndpoints = 3; var opcNodes = Enumerable.Range(0, numberOfEndpoints) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}", DataSetFieldId = $"test{i}", OpcPublishingIntervalTimespan = timespan ? TimeSpan.FromSeconds(1) : null, OpcPublishingInterval = timespan ? null : 1 }) .ToList(); var writer = GenerateEndpoint(0, opcNodes, false); writer.OpcNodes = opcNodes; // The call should throw an exception. await FluentActions .Invoking(async () => await configService.CreateOrUpdateDataSetWriterEntryAsync(writer)) .Should() .ThrowAsync() .WithMessage("Publishing interval not allowed on node level. Must be set at writer level."); } [Theory] [InlineData(true)] [InlineData(false)] public async Task TestAddNodesWithPublishingIntervalSetArgumentsAsync(bool timespan) { await using var configService = InitPublisherConfigService(); const int numberOfEndpoints = 3; var opcNodes = Enumerable.Range(0, numberOfEndpoints) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}", DataSetFieldId = $"test{i}" }) .ToList(); var writer = GenerateEndpoint(0, opcNodes, false); await configService.CreateOrUpdateDataSetWriterEntryAsync(writer); if (timespan) { opcNodes.ForEach(n => n.OpcPublishingIntervalTimespan = TimeSpan.FromSeconds(1)); } else { opcNodes.ForEach(n => n.OpcPublishingInterval = 1); } // The call should throw an exception. await FluentActions .Invoking(async () => await configService.AddOrUpdateNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, opcNodes.Skip(1).ToList())) .Should() .ThrowAsync() .WithMessage("Publishing interval not allowed on node level. Must be set at writer level."); } [Fact] public async Task TestCreateUpdateRemoveWriterEntries1Async() { await using var configService = InitPublisherConfigService(); await FluentActions .Invoking(async () => await configService .GetDataSetWriterEntryAsync("test12", "test2")) .Should() .ThrowAsync() .WithMessage("Could not find entry with provided writer id and writer group."); const int numberOfNodes = 3; var opcNodes = Enumerable.Range(0, numberOfNodes) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}", DataSetFieldId = $"{i}" }) .ToList(); var writers = await configService.GetConfiguredEndpointsAsync(); writers.Should().BeEmpty(); var writer = GenerateEndpoint(0, opcNodes, false); // Create writer.OpcNodes = opcNodes; await configService.CreateOrUpdateDataSetWriterEntryAsync(writer); writers = await configService.GetConfiguredEndpointsAsync(); writers.Count.Should().Be(1); var writerResult = await configService.GetDataSetWriterEntryAsync( writer.DataSetWriterGroup!, writer.DataSetWriterId!); writerResult.DisableSubscriptionTransfer.Should().BeNull(); writerResult.OpcNodes.Should().BeNull(); // Update var updatedWriter = writer with { DisableSubscriptionTransfer = true }; await configService.CreateOrUpdateDataSetWriterEntryAsync(updatedWriter); writerResult = await configService.GetDataSetWriterEntryAsync( updatedWriter.DataSetWriterGroup!, updatedWriter.DataSetWriterId!); writerResult.DisableSubscriptionTransfer.Should().BeTrue(); writerResult.OpcNodes.Should().BeNull(); writers = await configService.GetConfiguredEndpointsAsync(); writers.Count.Should().Be(1); var nodes = await configService.GetNodesAsync(updatedWriter.DataSetWriterGroup!, updatedWriter.DataSetWriterId!); nodes.Count.Should().Be(numberOfNodes); // Add opcNodes.ForEach(o => o.OpcPublishingIntervalTimespan = null); // Reset in memory changes var writer2 = GenerateEndpoint(1, opcNodes, false); await configService.CreateOrUpdateDataSetWriterEntryAsync(writer2); writers = await configService.GetConfiguredEndpointsAsync(); writers.Count.Should().Be(2); // Create ambigous entry opcNodes.ForEach(o => o.OpcPublishingIntervalTimespan = null); // Reset in memory changes updatedWriter = writer2 with { DisableSubscriptionTransfer = true }; await configService.AddOrUpdateEndpointsAsync(updatedWriter.YieldReturn().ToList()); writers = await configService.GetConfiguredEndpointsAsync(); writers.Count.Should().Be(3); opcNodes.ForEach(o => o.OpcPublishingIntervalTimespan = null); // Reset in memory changes await FluentActions .Invoking(async () => await configService .CreateOrUpdateDataSetWriterEntryAsync(writer2)) .Should() .ThrowAsync() .WithMessage("Trying to find entry with provided writer id produced ambigious results."); await FluentActions .Invoking(async () => await configService .GetDataSetWriterEntryAsync(writer2.DataSetWriterGroup!, writer2.DataSetWriterId!)) .Should() .ThrowAsync() .WithMessage("Trying to find entry with provided writer id produced ambigious results."); // Remove await configService.RemoveDataSetWriterEntryAsync( writer.DataSetWriterGroup!, writer.DataSetWriterId!); writers = await configService.GetConfiguredEndpointsAsync(); writers.Count.Should().Be(2); await FluentActions .Invoking(async () => await configService .GetDataSetWriterEntryAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!)) .Should() .ThrowAsync() .WithMessage("Could not find entry with provided writer id and writer group."); // Remove force await configService.RemoveDataSetWriterEntryAsync(writer2.DataSetWriterGroup!, writer2.DataSetWriterId!, true); writers = await configService.GetConfiguredEndpointsAsync(); writers.Should().BeEmpty(); } [Fact] public async Task TestCreateUpdateRemoveWriterEntries2Async() { await using var configService = InitPublisherConfigService(); await FluentActions .Invoking(async () => await configService .GetDataSetWriterEntryAsync("test12", "test2")) .Should() .ThrowAsync() .WithMessage("Could not find entry with provided writer id and writer group."); const int numberOfNodes = 3; var opcNodes = Enumerable.Range(0, numberOfNodes) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}", DataSetFieldId = $"{i}" }) .ToList(); var writers = await configService.GetConfiguredEndpointsAsync(); writers.Should().BeEmpty(); var writer = GenerateEndpoint(0, opcNodes, false); writer.OpcNodes = null; await configService.CreateOrUpdateDataSetWriterEntryAsync(writer); writers = await configService.GetConfiguredEndpointsAsync(); writers.Count.Should().Be(1); var nodes = await configService.GetNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!); nodes.Should().BeEmpty(); var writerResult = await configService.GetDataSetWriterEntryAsync( writer.DataSetWriterGroup!, writer.DataSetWriterId!); writerResult.DisableSubscriptionTransfer.Should().BeNull(); writerResult.OpcNodes.Should().BeNull(); // Remove await configService.RemoveDataSetWriterEntryAsync( writer.DataSetWriterGroup!, writer.DataSetWriterId!); writers = await configService.GetConfiguredEndpointsAsync(); writers.Should().BeEmpty(); await FluentActions .Invoking(async () => await configService .GetDataSetWriterEntryAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!)) .Should() .ThrowAsync() .WithMessage("Could not find entry with provided writer id and writer group."); // No failure when forcing await configService.RemoveDataSetWriterEntryAsync( writer.DataSetWriterGroup!, writer.DataSetWriterId!, true); writers = await configService.GetConfiguredEndpointsAsync(); writers.Should().BeEmpty(); } [Fact] public async Task TestRemoveNodesWithEmptyIdsAsync() { await using var configService = InitPublisherConfigService(); await FluentActions .Invoking(async () => await configService .RemoveNodesAsync("test", "test", Array.Empty())) .Should() .ThrowAsync() .WithMessage("Field ids must be specified."); } [Theory] [InlineData(true)] [InlineData(false)] public async Task TestRemoveNodesFromEmptyWriterAsync(bool useNullAsEmpty) { await using var configService = InitPublisherConfigService(); const int numberOfNodes = 3; var opcNodes = Enumerable.Range(0, numberOfNodes) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}", DataSetFieldId = $"{i}" }) .ToList(); // Create writer var writer = GenerateEndpoint(0, opcNodes, false); writer.OpcNodes = useNullAsEmpty ? null : Array.Empty(); await configService.CreateOrUpdateDataSetWriterEntryAsync(writer); var writerResult = await configService.GetDataSetWriterEntryAsync( writer.DataSetWriterGroup!, writer.DataSetWriterId!); await FluentActions .Invoking(async () => await configService .RemoveNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, new[] { "1" })) .Should() .ThrowAsync() .WithMessage("No nodes in dataset."); } [Fact] public async Task TestGetNodesWithEmptyEntryAsync() { await using var configService = InitPublisherConfigService(); const int numberOfNodes = 3; var opcNodes = Enumerable.Range(0, numberOfNodes) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}", DataSetFieldId = $"{i}" }) .ToList(); // Create writer var writer = GenerateEndpoint(0, opcNodes, false); writer.OpcNodes = null; await configService.CreateOrUpdateDataSetWriterEntryAsync(writer); var writerResult = await configService.GetDataSetWriterEntryAsync( writer.DataSetWriterGroup!, writer.DataSetWriterId!); var nodes = await configService.GetNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!); nodes.Should().BeEmpty(); await FluentActions .Invoking(async () => await configService .GetNodeAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, "1")) .Should() .ThrowAsync() .WithMessage("Node with id 1 not found."); } [Fact] public async Task TestAddQueryAndRemoveNodesAsync() { await using var configService = InitPublisherConfigService(); const int numberOfNodes = 3; var opcNodes = Enumerable.Range(0, numberOfNodes) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}", DataSetFieldId = $"{i}" }) .ToList(); // Create writer var writer = GenerateEndpoint(0, opcNodes, false); await configService.CreateOrUpdateDataSetWriterEntryAsync(writer); var writerResult = await configService.GetDataSetWriterEntryAsync( writer.DataSetWriterGroup!, writer.DataSetWriterId!); var nodes = await configService.GetNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!); nodes.Count.Should().Be(1); // Add await configService.AddOrUpdateNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, opcNodes.Skip(1).ToList()); nodes = await configService.GetNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!); nodes.Count.Should().Be(numberOfNodes); // Update opcNodes.ForEach(node => node.OpcSamplingIntervalTimespan = TimeSpan.FromSeconds(3)); await configService.AddOrUpdateNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, opcNodes); nodes = await configService.GetNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!); nodes.Count.Should().Be(numberOfNodes); nodes.Should().AllSatisfy(nodes => nodes.OpcSamplingIntervalTimespan.Should().Be(TimeSpan.FromSeconds(3))); // Remove await configService.RemoveNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, "1".YieldReturn().ToList()); nodes = await configService.GetNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!); nodes.Count.Should().Be(numberOfNodes - 1); nodes.Should().NotContain(node => node.DataSetFieldId == "1"); // Add a lot of nodes opcNodes = Enumerable.Range(0, 10000) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}", DataSetFieldId = $"{i}" }) .ToList(); await configService.AddOrUpdateNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, opcNodes); nodes = await configService.GetNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!); nodes.Count.Should().Be(10000); // Query tests nodes = await configService.GetNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, "99", 100); nodes.Count.Should().Be(100); nodes[0].Should().NotBeNull().And.Match(node => node.DataSetFieldId == "100"); nodes = await configService.GetNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, nodes[^1].DataSetFieldId, 10000); nodes[0].Should().NotBeNull().And.Match(node => node.DataSetFieldId == "200"); nodes.Count.Should().Be(9800); nodes = await configService.GetNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, null, 5000); nodes.Count.Should().Be(5000); nodes[0].Should().NotBeNull().And.Match(node => node.DataSetFieldId == "0"); nodes = await configService.GetNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, nodes[^1].DataSetFieldId); nodes[0].Should().NotBeNull().And.Match(node => node.DataSetFieldId == "5000"); nodes.Count.Should().Be(5000); nodes = await configService.GetNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, nodes[^1].DataSetFieldId); nodes.Count.Should().Be(0); nodes = await configService.GetNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, "testtesttest"); nodes.Count.Should().Be(0); // Remove 200 items nodes = await configService.GetNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, "99", 200); await configService.RemoveNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, nodes.Select(node => node.DataSetFieldId).ToList()); nodes = await configService.GetNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, null, 20000); nodes.Count.Should().Be(9800); nodes = await configService.GetNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, "99", 100); nodes.Count.Should().Be(100); nodes[0].Should().NotBeNull().And.Match(node => node.DataSetFieldId == "300"); // Remove every other await configService.RemoveNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, Enumerable.Range(0, 10000).Where(i => i % 2 == 0).Select(i => $"{i}").ToList()); nodes = await configService.GetNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!); nodes.Count.Should().Be(4900); // Remove something not there await FluentActions .Invoking(async () => await configService.RemoveNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, Enumerable.Range(0, 10000).Where(i => i % 2 == 0).Select(i => $"{i}").ToList())) .Should() .ThrowAsync() .WithMessage("Specified nodes not found in dataset"); await FluentActions .Invoking(async () => await configService.RemoveNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, new[] { "0" })) .Should() .ThrowAsync() .WithMessage("Specified node not found in dataset"); // Remove partial await configService.RemoveNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, new[] { "0", "1" }); nodes = await configService.GetNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!); nodes.Count.Should().Be(4899); // Remove all but original await configService.CreateOrUpdateDataSetWriterEntryAsync(writer); nodes = await configService.GetNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!); nodes.Count.Should().Be(1); writerResult = await configService.GetDataSetWriterEntryAsync( writer.DataSetWriterGroup!, writer.DataSetWriterId!); writerResult.DisableSubscriptionTransfer.Should().BeNull(); writerResult.OpcNodes.Should().BeNull(); } [Fact] public async Task TestGetNodeAsync() { await using var configService = InitPublisherConfigService(); const int numberOfNodes = 3; var opcNodes = Enumerable.Range(0, numberOfNodes) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}", DataSetFieldId = $"{i}" }) .ToList(); // Create writer var writer = GenerateEndpoint(0, opcNodes, false); writer.OpcNodes = opcNodes; await configService.CreateOrUpdateDataSetWriterEntryAsync(writer); var writerResult = await configService.GetDataSetWriterEntryAsync( writer.DataSetWriterGroup!, writer.DataSetWriterId!); var node = await configService.GetNodeAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, "1"); node.Should().NotBeNull(); node.Id.Should().Be("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1"); await FluentActions .Invoking(async () => await configService .GetNodeAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, "4")) .Should() .ThrowAsync() .WithMessage("Node with id 4 not found."); await configService.RemoveNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, new[] { "1" }); await FluentActions .Invoking(async () => await configService .GetNodeAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, "1")) .Should() .ThrowAsync() .WithMessage("Node with id 1 not found."); node = await configService.GetNodeAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, "0"); node.Should().NotBeNull(); node.Id.Should().Be("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt0"); await configService.RemoveDataSetWriterEntryAsync( writer.DataSetWriterGroup!, writer.DataSetWriterId!); await FluentActions .Invoking(async () => await configService .GetNodeAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, "0")) .Should() .ThrowAsync() .WithMessage("Could not find entry with provided writer id and writer group."); } [Fact] public async Task TestInsertNodesAsync() { await using var configService = InitPublisherConfigService(); const int numberOfNodes = 3; var opcNodes = Enumerable.Range(0, numberOfNodes) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}", DataSetFieldId = $"{i}" }) .ToList(); // Create writer var writer = GenerateEndpoint(0, opcNodes, false); await configService.CreateOrUpdateDataSetWriterEntryAsync(writer); var writerResult = await configService.GetDataSetWriterEntryAsync( writer.DataSetWriterGroup!, writer.DataSetWriterId!); var nodes = await configService.GetNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!); nodes.Count.Should().Be(1); var i = 1; while (i < 1000) { #pragma warning disable CA5394 // Do not use insecure randomness var batchSize = (Random.Shared.Next() % 3) + 1; var offset = Random.Shared.Next() % i; #pragma warning restore CA5394 // Do not use insecure randomness opcNodes = Enumerable.Range(i, batchSize) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}", DataSetFieldId = $"{i}" }) .ToList(); i += batchSize; await configService.AddOrUpdateNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, opcNodes, $"{offset}"); } nodes = await configService.GetNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!); nodes.Count.Should().Be(i); await FluentActions .Invoking(async () => await configService .AddOrUpdateNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, opcNodes, $"{i + 1}")) .Should() .ThrowAsync() .WithMessage("Field to insert after not found."); } [Fact] public async Task AddWithoutDistinctIdsResultsInErrorAsync() { await using var configService = InitPublisherConfigService(); var opcNodes = Enumerable.Range(0, 10) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}", DataSetFieldId = "alwaysthesameid" }) .ToList(); // Create writer var writer = GenerateEndpoint(0, opcNodes, false); await configService.CreateOrUpdateDataSetWriterEntryAsync(writer); var writerResult = await configService.GetDataSetWriterEntryAsync( writer.DataSetWriterGroup!, writer.DataSetWriterId!); var nodes = await configService.GetNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!); nodes.Count.Should().Be(1); await FluentActions .Invoking(async () => await configService.AddOrUpdateNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, opcNodes.Skip(1).ToList())) .Should() .ThrowAsync() .WithMessage("Field ids must be present and unique."); } [Fact] public async Task AddWithoutNodeIdResultsInErrorAsync() { await using var configService = InitPublisherConfigService(); var opcNodes = Enumerable.Range(0, 10) .Select(i => new OpcNodeModel { Id = $"i={i}", DataSetFieldId = $"{i}" }) .ToList(); // Create writer var writer = GenerateEndpoint(0, opcNodes, false); await configService.CreateOrUpdateDataSetWriterEntryAsync(writer); var writerResult = await configService.GetDataSetWriterEntryAsync( writer.DataSetWriterGroup!, writer.DataSetWriterId!); var nodes = await configService.GetNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!); nodes.Count.Should().Be(1); opcNodes.ForEach(n => n.Id = null); await FluentActions .Invoking(async () => await configService.AddOrUpdateNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, opcNodes.Skip(1).ToList())) .Should() .ThrowAsync() .WithMessage("Node must contain a node ID"); } [Fact] public async Task AddWithDistinctNodeIdButNoDataSetFieldIdSucceedsAsync() { await using var configService = InitPublisherConfigService(); var opcNodes = Enumerable.Range(0, 10) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}" }) .ToList(); // Create writer var writer = GenerateEndpoint(0, opcNodes, false); await configService.CreateOrUpdateDataSetWriterEntryAsync(writer); var writerResult = await configService.GetDataSetWriterEntryAsync( writer.DataSetWriterGroup!, writer.DataSetWriterId!); var nodes = await configService.GetNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!); nodes.Count.Should().Be(1); await configService.AddOrUpdateNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, opcNodes.Skip(1).ToList()); } [Fact] public async Task RemoveWithoutDistinctIdsResultsInErrorAsync() { await using var configService = InitPublisherConfigService(); var opcNodes = Enumerable.Range(0, 10) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}", DataSetFieldId = "alwaysthesameid" }) .ToList(); // Create writer var writer = GenerateEndpoint(0, opcNodes, false); await configService.CreateOrUpdateDataSetWriterEntryAsync(writer); var writerResult = await configService.GetDataSetWriterEntryAsync( writer.DataSetWriterGroup!, writer.DataSetWriterId!); var nodes = await configService.GetNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!); nodes.Count.Should().Be(1); await FluentActions .Invoking(async () => await configService.RemoveNodesAsync(writer.DataSetWriterGroup!, writer.DataSetWriterId!, new[] { "1", "1", "2" })) .Should() .ThrowAsync() .WithMessage("Field ids must be unique."); } [Fact] public async Task StartStopTest1Async() { await using var configService = InitPublisherConfigService(); await configService.PublishStartAsync(new ConnectionModel { Endpoint = new EndpointModel { Url = "opc.tcp://testendpoint1" } }, new PublishStartRequestModel { Item = new PublishedItemModel { HeartbeatInterval = TimeSpan.FromMinutes(1), PublishingInterval = TimeSpan.FromSeconds(2), NodeId = "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt0", DisplayName = "test", SamplingInterval = TimeSpan.FromSeconds(3) } }); var entries = await configService.GetConfiguredEndpointsAsync(true); entries.Count.Should().Be(1); entries[0].EndpointUrl.Should().Be("opc.tcp://testendpoint1"); entries[0].UseSecurity.Should().BeFalse(); entries[0].OpcNodes.Count.Should().Be(1); entries[0].MessageEncoding.Should().Be(MessageEncoding.Json); entries[0].MessagingMode.Should().Be(MessagingMode.FullSamples); var node = entries[0].OpcNodes[0]; node.Id.Should().Be("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt0"); node.HeartbeatInterval.Should().BeNull(); node.OpcPublishingInterval.Should().BeNull(); node.OpcSamplingInterval.Should().BeNull(); node.HeartbeatIntervalTimespan.Should().Be(TimeSpan.FromMinutes(1)); node.OpcPublishingIntervalTimespan.Should().Be(TimeSpan.FromSeconds(2)); node.OpcSamplingIntervalTimespan.Should().Be(TimeSpan.FromSeconds(3)); var list = await configService.PublishListAsync(new ConnectionModel { Endpoint = new EndpointModel { Url = "opc.tcp://testendpoint1" } }, new PublishedItemListRequestModel()); list.Items.Count.Should().Be(1); list.Items[0].HeartbeatInterval.Should().Be(node.HeartbeatIntervalTimespan); list.Items[0].PublishingInterval.Should().Be(node.OpcPublishingIntervalTimespan); list.Items[0].SamplingInterval.Should().Be(node.OpcSamplingIntervalTimespan); await configService.PublishStopAsync(new ConnectionModel { Endpoint = new EndpointModel { Url = "opc.tcp://testendpoint1" } }, new PublishStopRequestModel { NodeId = "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt0" }); entries = await configService.GetConfiguredEndpointsAsync(true); entries.Count.Should().Be(1); entries[0].OpcNodes.Should().BeEmpty(); list = await configService.PublishListAsync(new ConnectionModel { Endpoint = new EndpointModel { Url = "opc.tcp://testendpoint1" } }, new PublishedItemListRequestModel()); list.Items.Should().BeEmpty(); } [Fact] public async Task StartStopTest2Async() { await using var configService = InitPublisherConfigService(); var opcNodes = Enumerable.Range(0, 101) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}", DataSetFieldId = "alwaysthesameid" }) .ToList(); var items = Enumerable.Range(1, 100).Select(i => GenerateEndpoint(i, opcNodes, true) with { DataSetWriterGroup = null, MessageEncoding = MessageEncoding.Json, MessagingMode = MessagingMode.FullSamples, DataSetWriterId = null, DataSetPublishingInterval = null }).ToList(); await configService.SetConfiguredEndpointsAsync(items); var results = await configService.GetConfiguredEndpointsAsync(false); results.Count.Should().Be(100); var list = await configService.PublishListAsync(new ConnectionModel { Endpoint = new EndpointModel { Url = results[0].EndpointUrl } }, new PublishedItemListRequestModel()); list.Items.Count.Should().Be(2); var updated = list.Items[0] with { HeartbeatInterval = TimeSpan.FromMinutes(1), }; // Update await configService.PublishStartAsync(new ConnectionModel { Endpoint = new EndpointModel { Url = results[0].EndpointUrl } }, new PublishStartRequestModel { Item = updated }); var entries = await configService.GetConfiguredEndpointsAsync(true); entries.Count.Should().Be(100); var entry = entries.Find(e => e.EndpointUrl == results[0].EndpointUrl); entry.Should().NotBeNull(); entry.MessageEncoding.Should().Be(MessageEncoding.Json); entry.MessagingMode.Should().Be(MessagingMode.FullSamples); entry.OpcNodes.Count.Should().Be(2); var node = entry.OpcNodes[0]; node.Id.Should().Be("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt0"); node.HeartbeatInterval.Should().BeNull(); node.HeartbeatIntervalTimespan.Should().Be(TimeSpan.FromMinutes(1)); await configService.PublishStopAsync(new ConnectionModel { Endpoint = new EndpointModel { Url = results[0].EndpointUrl } }, new PublishStopRequestModel { NodeId = updated.NodeId }); entries = await configService.GetConfiguredEndpointsAsync(true); entries.Count.Should().Be(100); entry = entries.Find(e => e.EndpointUrl == results[0].EndpointUrl); entry.MessageEncoding.Should().Be(MessageEncoding.Json); entry.MessagingMode.Should().Be(MessagingMode.FullSamples); entry.OpcNodes.Count.Should().Be(1); } [Fact] public async Task Legacy25PublishedNodesFileAsync() { Utils.CopyContent("Publisher/pn_2.5_legacy.json", _tempFile); await using (var configService = InitPublisherConfigService()) { var endpoints = await configService.GetConfiguredEndpointsAsync(); Assert.Single(endpoints); var endpoint = endpoints[0]; Assert.Equal("opc.tcp://opcplc:50000", endpoint.EndpointUrl); Assert.False(endpoint.UseSecurity); Assert.Equal(OpcAuthenticationMode.UsernamePassword, endpoint.OpcAuthenticationMode); Assert.Equal("username", endpoint.OpcAuthenticationUsername); Assert.Null(endpoint.OpcAuthenticationPassword); endpoint.OpcAuthenticationPassword = "password"; var nodes = await configService.GetConfiguredNodesOnEndpointAsync(endpoint); Assert.Single(nodes); Assert.Equal("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1", nodes[0].Id); endpoint.OpcNodes = [ new() { Id = "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt2" } ]; await configService.PublishNodesAsync(endpoint); endpoints = await configService.GetConfiguredEndpointsAsync(); Assert.Single(endpoints); endpoint.OpcNodes = null; nodes = await configService.GetConfiguredNodesOnEndpointAsync(endpoint); Assert.Equal(2, nodes.Count); Assert.Equal("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1", nodes[0].Id); Assert.Equal("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt2", nodes[1].Id); } // Simulate restart. await using (var configService = InitPublisherConfigService()) { // We should get the same endpoint and nodes after restart. var endpoints = await configService.GetConfiguredEndpointsAsync(); Assert.Single(endpoints); var endpoint = endpoints[0]; Assert.Equal("opc.tcp://opcplc:50000", endpoint.EndpointUrl); Assert.False(endpoint.UseSecurity); Assert.Equal(OpcAuthenticationMode.UsernamePassword, endpoint.OpcAuthenticationMode); Assert.Equal("username", endpoint.OpcAuthenticationUsername); Assert.Null(endpoint.OpcAuthenticationPassword); endpoint.OpcAuthenticationPassword = "password"; var nodes = await configService.GetConfiguredNodesOnEndpointAsync(endpoint); Assert.Equal(2, nodes.Count); Assert.Equal("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1", nodes[0].Id); Assert.Equal("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt2", nodes[1].Id); } } [Fact] public async Task UpdateConfiguredEndpointsAsync() { await using var configService = InitPublisherConfigService(); var opcNodes = Enumerable.Range(0, 101) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}", DataSetFieldId = "alwaysthesameid" }) .ToList(); var items = Enumerable.Range(1, 100).Select(i => GenerateEndpoint(i, opcNodes, false)).ToList(); await configService.SetConfiguredEndpointsAsync(items); var results = await configService.GetConfiguredEndpointsAsync(false); results.Count.Should().Be(100); await configService.UnpublishAllNodesAsync(results[50]); results = await configService.GetConfiguredEndpointsAsync(false); results.Count.Should().Be(99); // purge await configService.UnpublishAllNodesAsync(null); results = await configService.GetConfiguredEndpointsAsync(false); results.Should().BeEmpty(); } [Fact] public async Task UpdateConfiguredEndpointsWithBrowsePathsAsync() { await using var configService = InitPublisherConfigService(); var opcNodes = Enumerable.Range(0, 101) .Select(i => new OpcNodeModel { Id = null, BrowsePath = new[] { "Objects", "Telemetry", $"FastUInt{i}" }, DataSetFieldId = "alwaysthesameid" }) .ToList(); var items = Enumerable.Range(1, 100).Select(i => GenerateEndpoint(i, opcNodes, false)).ToList(); await configService.SetConfiguredEndpointsAsync(items); var results = await configService.GetConfiguredEndpointsAsync(false); results.Count.Should().Be(100); await configService.UnpublishAllNodesAsync(results[50]); results = await configService.GetConfiguredEndpointsAsync(false); results.Count.Should().Be(99); // purge await configService.UnpublishAllNodesAsync(new PublishedNodesEntryModel { EndpointUrl = null! }); results = await configService.GetConfiguredEndpointsAsync(false); results.Should().BeEmpty(); } [Fact] public async Task Legacy25PublishedNodesFileErrorAsync() { Utils.CopyContent("Publisher/pn_2.5_legacy_error.json", _tempFile); await using var configService = InitPublisherConfigService(); // Transformation of published nodes entries should throw a serialization error since // Engine/pn_2.5_legacy_error.json contains both NodeId and OpcNodes. // So as a result, we should end up with zero endpoints. var endpoints = await configService.GetConfiguredEndpointsAsync(); Assert.Empty(endpoints); } [Theory] [InlineData("Publisher/pn_assets.json")] [InlineData("Publisher/pn_assets_with_optional_fields.json")] public void TestPnJsonWithMultipleJobsExpectDifferentJobIds(string publishedNodesFile) { Utils.CopyContent(publishedNodesFile, _tempFile); using var configService = InitPublisherConfigService(); Assert.Equal(2, _publisher.WriterGroups.Count); } [Fact] public async Task TestSerializableExceptionResponseAsync() { await using var configService = InitPublisherConfigService(); const int numberOfEndpoints = 1; var opcNodes = Enumerable.Range(0, numberOfEndpoints) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}" }) .ToList(); var endpoints = Enumerable.Range(0, numberOfEndpoints) .Select(i => GenerateEndpoint(i, opcNodes, false)) .ToList(); await configService.PublishNodesAsync(endpoints[0]); const string details = "{\"DataSetWriterId\":\"DataSetWriterId0\",\"DataSetWriterGroup\":\"DataSetWriterGroup\",\"OpcNodes\":[{\"Id\":\"nsu=http://microsoft.com/Opc/OpcPlc/;s=SlowUInt0\",\"OpcPublishingIntervalTimespan\":\"00:00:01\"}],\"EndpointUrl\":\"opc.tcp://opcplc:50000\",\"UseSecurity\":null,\"OpcAuthenticationMode\":\"anonymous\"}"; const string exceptionResponse = "Nodes not found: \n" + details; var opcNodes1 = Enumerable.Range(0, numberOfEndpoints) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=SlowUInt{i}" }) .ToList(); var endpointsToDelete = Enumerable.Range(0, numberOfEndpoints) .Select(i => GenerateEndpoint(i, opcNodes1, false)) .ToList(); // try to unpublish a not published nodes. await FluentActions .Invoking(async () => await configService.UnpublishNodesAsync(endpointsToDelete[0])) .Should() .ThrowAsync() .WithMessage(exceptionResponse); } [Fact] public async Task TestPublishNodesEmptyAsync() { await using var configService = InitPublisherConfigService(); var request = new PublishedNodesEntryModel { EndpointUrl = "opc.tcp://opcplc:50000" }; // Check null OpcNodes in request. await FluentActions .Invoking(async () => await configService .PublishNodesAsync(request)) .Should() .ThrowAsync() .WithMessage("null or empty OpcNodes is provided in request"); request.OpcNodes = []; // Check empty OpcNodes in request. await FluentActions .Invoking(async () => await configService .PublishNodesAsync(request)) .Should() .ThrowAsync() .WithMessage("null or empty OpcNodes is provided in request"); } [Theory] [InlineData(false, false)] [InlineData(false, true)] [InlineData(true, false)] [InlineData(true, true)] public async Task TestUnpublishNodesEmptyOpcNodesAsync( bool useEmptyOpcNodes, bool customEndpoint) { await using var configService = InitPublisherConfigService(); const int numberOfEndpoints = 3; var opcNodes = Enumerable.Range(0, numberOfEndpoints) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}" }) .ToList(); var endpoints = Enumerable.Range(0, numberOfEndpoints) .Select(i => GenerateEndpoint(i, opcNodes, customEndpoint)) .ToList(); await configService.PublishNodesAsync(endpoints[0]); await configService.PublishNodesAsync(endpoints[1]); await configService.PublishNodesAsync(endpoints[2]); endpoints[1] = GenerateEndpoint(1, opcNodes, customEndpoint); endpoints[1].OpcNodes = useEmptyOpcNodes ? new List() : null; // Check null or empty OpcNodes in request. await FluentActions .Invoking(async () => await configService .UnpublishNodesAsync(endpoints[1])) .Should() .NotThrowAsync(); var configuredEndpoints = await configService .GetConfiguredEndpointsAsync(); Assert.Equal(2, configuredEndpoints.Count); Assert.True(endpoints[0].HasSameDataSet(configuredEndpoints[0])); Assert.True(endpoints[2].HasSameDataSet(configuredEndpoints[1])); } [Fact] public async Task TestAddOrUpdateEndpointsMultipleEndpointEntriesAsync() { await using var configService = InitPublisherConfigService(); const int numberOfEndpoints = 3; var opcNodes = Enumerable.Range(0, numberOfEndpoints) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}" }) .ToList(); var endpoints = Enumerable.Range(0, numberOfEndpoints) .Select(i => GenerateEndpoint(i, opcNodes, false)) .ToList(); // Make endpoint at index 0 and 2 the same. endpoints[2].DataSetWriterId = endpoints[0].DataSetWriterId; endpoints[2].DataSetWriterGroup = endpoints[0].DataSetWriterGroup; endpoints[2].DataSetPublishingInterval = endpoints[0].DataSetPublishingInterval; // The call should throw an exception. await FluentActions .Invoking(async () => await configService .AddOrUpdateEndpointsAsync(endpoints)) .Should() .ThrowAsync() .WithMessage("Request contains two entries for the same endpoint at index 0 and 2"); } [Fact] public async Task TestAddOrUpdateEndpointsWithNonDefaultWriterGroupTransportAndSecurityAsync() { await using var configService = InitPublisherConfigService(); const int numberOfEndpoints = 3; var opcNodes = Enumerable.Range(0, numberOfEndpoints) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}" }) .ToList(); var endpoints = Enumerable.Range(0, numberOfEndpoints) .Select(i => GenerateEndpoint(i, opcNodes, false)) .ToList(); endpoints.ForEach(ep => ep.WriterGroupTransport = WriterGroupTransport.FileSystem); endpoints.ForEach(ep => ep.EndpointSecurityMode = SecurityMode.Best); await configService.AddOrUpdateEndpointsAsync(endpoints); var configuredEndpoints = await configService.GetConfiguredEndpointsAsync(); Assert.All(configuredEndpoints, ep => { Assert.Equal(WriterGroupTransport.FileSystem, ep.WriterGroupTransport); Assert.Equal(SecurityMode.Best, ep.EndpointSecurityMode); }); } [Fact] public async Task TestAddOrUpdateEndpointsMultipleEndpointEntriesTimespanAsync() { await using var configService = InitPublisherConfigService(); const int numberOfEndpoints = 3; var opcNodes = Enumerable.Range(0, numberOfEndpoints) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}" }) .ToList(); var endpoints = Enumerable.Range(0, numberOfEndpoints) .Select(i => GenerateEndpoint(i, opcNodes, false)) .ToList(); endpoints.ForEach(e => e.DataSetPublishingIntervalTimespan = TimeSpan.FromMilliseconds(e.DataSetPublishingInterval ?? 1000)); // Make endpoint at index 0 and 2 the same. endpoints[2].DataSetWriterId = endpoints[0].DataSetWriterId; endpoints[2].DataSetWriterGroup = endpoints[0].DataSetWriterGroup; endpoints[2].DataSetPublishingIntervalTimespan = endpoints[0].DataSetPublishingIntervalTimespan; // The call should throw an exception. await FluentActions .Invoking(async () => await configService .AddOrUpdateEndpointsAsync(endpoints)) .Should() .ThrowAsync() .WithMessage("Request contains two entries for the same endpoint at index 0 and 2"); } [Theory] [InlineData(false)] [InlineData(true)] public async Task TestAddOrUpdateEndpointsAddEndpointsAsync( bool useDataSetSpecificEndpoints ) { _options.Value.MaxNodesPerDataSet = 2; await using var configService = InitPublisherConfigService(); Assert.Empty(_publisher.WriterGroups); const int numberOfEndpoints = 3; var opcNodes = Enumerable.Range(0, numberOfEndpoints) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}" }) .ToList(); var endpoints = Enumerable.Range(0, numberOfEndpoints) .Select(i => GenerateEndpoint(i, opcNodes, useDataSetSpecificEndpoints)) .ToList(); var tasks = new List(); for (var i = 0; i < numberOfEndpoints; i++) { tasks.Add(configService.AddOrUpdateEndpointsAsync( new List { endpoints[i] })); } await Task.WhenAll(tasks); for (var i = 0; i < numberOfEndpoints; i++) { var endpointNodes = await configService .GetConfiguredNodesOnEndpointAsync(endpoints[i]); AssertSameNodes(endpoints[i], endpointNodes); } Assert.Single(_publisher.WriterGroups); } [Theory] [InlineData("Publisher/pn_events.json")] [InlineData("Publisher/pn_pending_alarms.json")] [InlineData("Publisher/empty_pn.json")] [InlineData("Publisher/pn_assets.json")] [InlineData("Publisher/pn_assets_with_optional_fields.json")] [InlineData("Publisher/publishednodes.json")] [InlineData("Publisher/publishednodeswithoptionalfields.json")] [InlineData("Publisher/publishednodes_with_duplicates.json")] public async Task TestAddOrUpdateEndpointsRemoveEndpointsAsync(string publishedNodesFile) { Utils.CopyContent(publishedNodesFile, _tempFile); await using var configService = InitPublisherConfigService(); var payload = Utils.GetFileContent(publishedNodesFile); var payloadRequests = _newtonSoftJsonSerializer.Deserialize>(payload); var index = 0; foreach (var request in payloadRequests) { request.OpcNodes = index % 2 == 0 ? null : new List(); ++index; var shouldThrow = !_publishedNodesJobConverter.ToPublishedNodes(0, default, _publisher.WriterGroups) .Select(p => p.PropagatePublishingIntervalToNodes()) .Any(dataSet => dataSet.HasSameDataSet(request.PropagatePublishingIntervalToNodes())); if (shouldThrow) { await FluentActions .Invoking(async () => await configService .AddOrUpdateEndpointsAsync(new List { request })) .Should() .ThrowAsync() .WithMessage($"Endpoint not found: {request.EndpointUrl}"); } else { await FluentActions .Invoking(async () => await configService .AddOrUpdateEndpointsAsync(new List { request })) .Should() .NotThrowAsync(); } } var configuredEndpoints = await configService .GetConfiguredEndpointsAsync(); Assert.Empty(configuredEndpoints); } [Fact] public async Task TestAddOrUpdateEndpointsAddAndRemoveAsync() { _options.Value.MaxNodesPerDataSet = 2; await using var configService = InitPublisherConfigService(); Assert.Empty(_publisher.WriterGroups); var opcNodes = Enumerable.Range(0, 5) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}" }) .ToList(); var endpoints = Enumerable.Range(0, 5) .Select(i => GenerateEndpoint(i, opcNodes)) .ToList(); var tasks = new List(); for (var i = 0; i < 3; i++) { tasks.Add(configService.PublishNodesAsync(endpoints[i])); } await Task.WhenAll(tasks); for (var i = 0; i < 3; i++) { var endpointNodes = await configService .GetConfiguredNodesOnEndpointAsync(endpoints[i]); AssertSameNodes(endpoints[i], endpointNodes); } // Helper method. async Task AssertGetConfiguredNodesOnEndpointThrows( PublishedNodesJsonServices publisherConfigurationService, PublishedNodesEntryModel endpoint ) { await FluentActions .Invoking(async () => await publisherConfigurationService .GetConfiguredNodesOnEndpointAsync(endpoint)) .Should() .ThrowAsync() .WithMessage($"Endpoint not found: {endpoint.EndpointUrl}"); } // Those calls should throw. for (var i = 3; i < 5; i++) { await AssertGetConfiguredNodesOnEndpointThrows(configService, endpoints[i]); } var updateRequest = Enumerable.Range(0, 5) .Select(i => GenerateEndpoint(i, opcNodes)) .ToList(); updateRequest[0].OpcNodes = null; // Should result in endpoint deletion. updateRequest[1].OpcNodes = []; // Should result in endpoint deletion. updateRequest[2].OpcNodes = [.. opcNodes.GetRange(0, 4)]; updateRequest[3].OpcNodes = null; // Should throw as endpoint does not exist. // Should throw as updateRequest[3] endpoint is not present in current configuratoin. await FluentActions .Invoking(async () => await configService .AddOrUpdateEndpointsAsync(updateRequest)) .Should() .ThrowAsync() .WithMessage($"Endpoint not found: {updateRequest[3].EndpointUrl}"); updateRequest.RemoveAt(3); await configService.AddOrUpdateEndpointsAsync(updateRequest); // Check endpoint 0. await AssertGetConfiguredNodesOnEndpointThrows(configService, endpoints[0]); // Check endpoint 1. await AssertGetConfiguredNodesOnEndpointThrows(configService, endpoints[1]); // Check endpoint 2. var endpointNodes2 = await configService .GetConfiguredNodesOnEndpointAsync(endpoints[2]); AssertSameNodes(updateRequest[2], endpointNodes2); // Check endpoint 3. await AssertGetConfiguredNodesOnEndpointThrows(configService, endpoints[3]) ; // Check endpoint 4. var endpointNodes4 = await configService .GetConfiguredNodesOnEndpointAsync(endpoints[4]); AssertSameNodes(updateRequest[3], endpointNodes4); } [Theory] [InlineData("Publisher/pn_opc_nodes_empty.json")] [InlineData("Publisher/pn_opc_nodes_null.json")] public async Task TestInitStandaloneJobOrchestratorFromEmptyOpcNodes1Async(string publishedNodesFile) { Utils.CopyContent(publishedNodesFile, _tempFile); await using var configService = InitPublisherConfigService(); // Behavior change in 2.9.10 we now allow empty entries var configuredEndpoints = await configService.GetConfiguredEndpointsAsync(); Assert.Single(configuredEndpoints); // There should also not be any job entries. var group = Assert.Single(_publisher.WriterGroups); var writer = Assert.Single(group.DataSetWriters); Assert.Empty(writer.DataSet.DataSetSource.PublishedVariables.PublishedData); } [Fact] public async Task TestInitStandaloneJobOrchestratorFromEmptyOpcNodes2Async() { Utils.CopyContent("Publisher/pn_opc_nodes_empty_and_null.json", _tempFile); await using var configService = InitPublisherConfigService(); // Behavior change in 2.9.10 we now allow empty entries var configuredEndpoints = await configService.GetConfiguredEndpointsAsync(); Assert.Equal(2, configuredEndpoints.Count); // There should also not be any job entries. Assert.Equal(2, _publisher.WriterGroups.Count); Assert.All(_publisher.WriterGroups .Select(d => d.DataSetWriters), writers => { var writer = Assert.Single(writers); Assert.Empty(writer.DataSet.DataSetSource.PublishedVariables.PublishedData); }); } [Fact] public async Task OptionalFieldsPublishedNodesFileAsync() { Utils.CopyContent("Publisher/pn_assets_with_optional_fields.json", _tempFile); await using (var configService = InitPublisherConfigService()) { var endpoints = await configService.GetConfiguredEndpointsAsync(); Assert.Equal(2, endpoints.Count); Assert.Equal("Leaf0", endpoints[0].DataSetWriterGroup); Assert.Equal("opc.tcp://opcplc:50000", endpoints[0].EndpointUrl); Assert.False(endpoints[0].UseSecurity); Assert.Equal(OpcAuthenticationMode.Anonymous, endpoints[0].OpcAuthenticationMode); Assert.Equal("Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234", endpoints[0].DataSetWriterId); Assert.Equal("Tag_Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234", endpoints[0].DataSetName); Assert.Equal("Leaf1", endpoints[1].DataSetWriterGroup); Assert.Equal("opc.tcp://opcplc:50000", endpoints[1].EndpointUrl); Assert.False(endpoints[1].UseSecurity); Assert.Equal(OpcAuthenticationMode.UsernamePassword, endpoints[1].OpcAuthenticationMode); Assert.Equal("Leaf1_10000_2e4fc28f-ffa2-4532-9f22-378d47bbee5d", endpoints[1].DataSetWriterId); Assert.Equal("Tag_Leaf1_10000_2e4fc28f-ffa2-4532-9f22-378d47bbee5d", endpoints[1].DataSetName); endpoints[0].OpcNodes = null; var nodes = await configService.GetConfiguredNodesOnEndpointAsync(endpoints[0]); Assert.Single(nodes); Assert.Equal("nsu=http://microsoft.com/Opc/OpcPlc/;s=StepUp", nodes[0].Id); endpoints[0].OpcNodes = [ new() { Id = "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt2" } ]; await configService.PublishNodesAsync(endpoints[0]); endpoints = await configService.GetConfiguredEndpointsAsync(); Assert.Single(endpoints); endpoints[0].OpcNodes = null; nodes = await configService.GetConfiguredNodesOnEndpointAsync(endpoints[0]); Assert.Equal(2, nodes.Count); Assert.Equal("nsu=http://microsoft.com/Opc/OpcPlc/;s=StepUp", nodes[0].Id); Assert.Equal("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt2", nodes[1].Id); } // Simulate restart. await using (var configService = InitPublisherConfigService()) { // We should get the same endpoint and nodes after restart. var endpoints = await configService.GetConfiguredEndpointsAsync(); Assert.Single(endpoints); Assert.Equal("Leaf0", endpoints[0].DataSetWriterGroup); Assert.Equal("opc.tcp://opcplc:50000", endpoints[0].EndpointUrl); Assert.False(endpoints[0].UseSecurity); Assert.Equal(OpcAuthenticationMode.Anonymous, endpoints[0].OpcAuthenticationMode); Assert.Equal("Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234", endpoints[0].DataSetWriterId); Assert.Equal("Tag_Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234", endpoints[0].DataSetName); var nodes = await configService.GetConfiguredNodesOnEndpointAsync(endpoints[0]); Assert.Equal(2, nodes.Count); Assert.Equal("nsu=http://microsoft.com/Opc/OpcPlc/;s=StepUp", nodes[0].Id); Assert.Equal("nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt2", nodes[1].Id); } } [Theory] [InlineData("Publisher/publishednodes.json")] [InlineData("Publisher/publishednodeswithoptionalfields.json")] [InlineData("Publisher/pn_assets.json")] [InlineData("Publisher/pn_assets_with_optional_fields.json")] [InlineData("Publisher/pn_events.json")] [InlineData("Publisher/pn_pending_alarms.json")] public async Task PublishNodesOnEmptyConfigurationAsync(string publishedNodesFile) { Utils.CopyContent("Publisher/empty_pn.json", _tempFile); await using var configService = InitPublisherConfigService(); var payload = Utils.GetFileContent(publishedNodesFile); foreach (var request in _newtonSoftJsonSerializer.Deserialize>(payload)) { await FluentActions .Invoking(async () => await configService.PublishNodesAsync(request)) .Should() .NotThrowAsync(); } _publisher.WriterGroups.Count .Should() .Be(1); } [Theory] [InlineData("Publisher/publishednodes.json", "Publisher/publishednodeswithoptionalfields.json")] [InlineData("Publisher/publishednodeswithoptionalfields.json", "Publisher/publishednodes.json")] [InlineData("Publisher/pn_assets.json", "Publisher/pn_assets_with_optional_fields.json")] [InlineData("Publisher/pn_assets_with_optional_fields.json", "Publisher/pn_assets.json")] [InlineData("Publisher/pn_events.json", "Publisher/pn_pending_alarms.json")] public async Task PublishNodesOnExistingConfigurationAsync(string existingConfig, string newConfig) { Utils.CopyContent(existingConfig, _tempFile); await using var configService = InitPublisherConfigService(); var payload = Utils.GetFileContent(newConfig); foreach (var request in _newtonSoftJsonSerializer.Deserialize>(payload)) { await FluentActions .Invoking(async () => await configService.PublishNodesAsync(request)) .Should() .NotThrowAsync(); } _publisher.WriterGroups.Count .Should() .Be(1); } [Theory] [InlineData("Publisher/publishednodes.json", "Publisher/pn_assets.json")] [InlineData("Publisher/publishednodeswithoptionalfields.json", "Publisher/pn_assets_with_optional_fields.json")] [InlineData("Publisher/pn_assets.json", "Publisher/publishednodes.json")] [InlineData("Publisher/pn_assets_with_optional_fields.json", "Publisher/publishednodeswithoptionalfields.json")] public async Task PublishNodesOnNewConfigurationAsync(string existingConfig, string newConfig) { Utils.CopyContent(existingConfig, _tempFile); await using var configService = InitPublisherConfigService(); var payload = Utils.GetFileContent(newConfig); foreach (var request in _newtonSoftJsonSerializer.Deserialize>(payload)) { await FluentActions .Invoking(async () => await configService.PublishNodesAsync(request)) .Should() .NotThrowAsync(); } _publisher.WriterGroups.Count .Should() .Be(1); } [Theory] [InlineData("Publisher/publishednodes.json")] [InlineData("Publisher/publishednodeswithoptionalfields.json")] [InlineData("Publisher/pn_assets.json")] [InlineData("Publisher/pn_assets_with_optional_fields.json")] public async Task UnpublishNodesOnExistingConfigurationAsync(string publishedNodesFile) { Utils.CopyContent(publishedNodesFile, _tempFile); await using var configService = InitPublisherConfigService(); var payload = Utils.GetFileContent(publishedNodesFile); foreach (var request in _newtonSoftJsonSerializer.Deserialize>(payload)) { await FluentActions .Invoking(async () => await configService.UnpublishNodesAsync(request)) .Should() .NotThrowAsync(); } _publisher.WriterGroups.Count .Should() .Be(0); } [Theory] [InlineData("Publisher/publishednodes.json", "Publisher/pn_assets.json")] [InlineData("Publisher/publishednodeswithoptionalfields.json", "Publisher/pn_assets_with_optional_fields.json")] [InlineData("Publisher/pn_assets.json", "Publisher/publishednodes.json")] [InlineData("Publisher/pn_assets_with_optional_fields.json", "Publisher/publishednodeswithoptionalfields.json")] public async Task UnpublishNodesOnNonExistingConfigurationAsync(string existingConfig, string newConfig) { Utils.CopyContent(existingConfig, _tempFile); await using var configService = InitPublisherConfigService(); var payload = Utils.GetFileContent(newConfig); foreach (var request in _newtonSoftJsonSerializer.Deserialize>(payload)) { await FluentActions .Invoking(async () => await configService.UnpublishNodesAsync(request)) .Should() .ThrowAsync() .WithMessage($"Endpoint not found: {request.EndpointUrl}"); } _publisher.WriterGroups.Sum(writerGroup => writerGroup.DataSetWriters.Count) .Should() .Be(2); } [Theory] [InlineData(2, 10)] // [InlineData(100, 1000)] public async Task PublishNodesStressTestAsync(int numberOfEndpoints, int numberOfNodes) { await using (var fileStream = new FileStream(_tempFile, FileMode.Open, FileAccess.Write)) { fileStream.Write(Encoding.UTF8.GetBytes("[]")); } await using var configService = InitPublisherConfigService(); var payload = new List(); for (var endpointIndex = 0; endpointIndex < numberOfEndpoints; ++endpointIndex) { var model = new PublishedNodesEntryModel { EndpointUrl = $"opc.tcp://server{endpointIndex}:49580", OpcNodes = [] }; for (var nodeIndex = 0; nodeIndex < numberOfNodes; ++nodeIndex) { model.OpcNodes.Add(new OpcNodeModel { Id = $"ns=2;s=Node-Server-{nodeIndex}" }); } payload.Add(model); } // Publish all nodes. foreach (var request in payload) { await FluentActions .Invoking(async () => await configService.PublishNodesAsync(request)) .Should() .NotThrowAsync(); } void CheckEndpointsAndNodes( int expectedNumberOfEndpoints, int expectedNumberOfNodesPerEndpoint ) { var writerGroups = _publisher.WriterGroups; writerGroups .SelectMany(writerGroup => writerGroup.DataSetWriters) .Count(v => v.DataSet.DataSetSource.PublishedVariables.PublishedData.Count == expectedNumberOfNodesPerEndpoint) .Should() .Be(expectedNumberOfEndpoints); } // Check CheckEndpointsAndNodes(numberOfEndpoints, numberOfNodes); // Publish one more node for each endpoint. var payloadDiff = new List(); for (var endpointIndex = 0; endpointIndex < numberOfEndpoints; ++endpointIndex) { var model = new PublishedNodesEntryModel { EndpointUrl = $"opc.tcp://server{endpointIndex}:49580", OpcNodes = [ new() { Id = $"ns=2;s=Node-Server-{numberOfNodes}" } ] }; payloadDiff.Add(model); } foreach (var request in payloadDiff) { await FluentActions .Invoking(async () => await configService.PublishNodesAsync(request)) .Should() .NotThrowAsync(); } // Check CheckEndpointsAndNodes(numberOfEndpoints, numberOfNodes + 1); // Unpublish new nodes for each endpoint. foreach (var request in payloadDiff) { await FluentActions .Invoking(async () => await configService.UnpublishNodesAsync(request)) .Should() .NotThrowAsync(); } // Check CheckEndpointsAndNodes(numberOfEndpoints, numberOfNodes); } private static PublishedNodesEntryModel GenerateEndpoint( int dataSetIndex, List opcNodes, bool customEndpoint = false ) { return new PublishedNodesEntryModel { EndpointUrl = customEndpoint ? $"opc.tcp://opcplc:{50000 + dataSetIndex}" : "opc.tcp://opcplc:50000", DataSetWriterId = $"DataSetWriterId{dataSetIndex}", DataSetWriterGroup = "DataSetWriterGroup", DataSetPublishingInterval = (dataSetIndex + 1) * 1000, OpcNodes = [.. opcNodes.GetRange(0, dataSetIndex + 1)] }; } private static void AssertSameNodes(PublishedNodesEntryModel endpoint, List nodes) { endpoint.PropagatePublishingIntervalToNodes(); Assert.True(endpoint.OpcNodes.SetEqualsSafe(nodes, (a, b) => a.IsSame(b))); } private readonly NewtonsoftJsonSerializer _newtonSoftJsonSerializer; private readonly ILoggerFactory _loggerFactory; private readonly PublishedNodesConverter _publishedNodesJobConverter; private readonly IOptions _options; private readonly PublishedNodesProvider _publishedNodesProvider; private readonly Mock _triggerMock; private readonly PublisherService _publisher; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/RuntimeStateReporterTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services { using Azure.IIoT.OpcUa.Publisher.Services; using FluentAssertions; using Furly; using Furly.Extensions.Logging; using Furly.Extensions.Messaging; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Furly.Extensions.Storage.Services; using Microsoft.Extensions.Configuration; using Moq; using System; using System.Buffers; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Xunit; public class RuntimeStateReporterTests { [Fact] public async Task ReportingDisabledTestAsync() { var client = new Mock(); var collector = new Mock(); IJsonSerializer _serializer = new NewtonsoftJsonSerializer(); var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); // This will disable state reporting. options.Value.EnableRuntimeStateReporting = false; var _logger = Log.Console(); using var runtimeStateReporter = new RuntimeStateReporter( client.Object.YieldReturn(), _serializer, new MemoryKVStore().YieldReturn(), options, collector.Object, _logger); await FluentActions .Invoking(async () => await runtimeStateReporter.SendRestartAnnouncementAsync(default)) .Should() .NotThrowAsync() ; client.Verify(c => c.CreateEvent(), Times.Never()); } [Fact] public async Task ClientNotInitializedTestAsync() { var client = new Mock(); var collector = new Mock(); client.Setup(m => m.CreateEvent()).Throws(); IJsonSerializer _serializer = new NewtonsoftJsonSerializer(); var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.EnableRuntimeStateReporting = true; var _logger = Log.Console(); using var runtimeStateReporter = new RuntimeStateReporter( client.Object.YieldReturn(), _serializer, new MemoryKVStore().YieldReturn(), options, collector.Object, _logger); await FluentActions .Invoking(async () => await runtimeStateReporter.SendRestartAnnouncementAsync(default)) .Should() .NotThrowAsync() ; } [Fact] public async Task ReportingTestAsync() { var _client = new Mock(); var collector = new Mock(); var _message = new Mock() .SetupAllProperties(); _message .Setup(m => m.Dispose()); _client .Setup(c => c.CreateEvent()) .Returns(_message.Object); _message .Setup(c => c.SendAsync(It.IsAny())) .Returns(ValueTask.CompletedTask); var contentType = string.Empty; var contentEncoding = string.Empty; var routingInfo = string.Empty; List> buffers = null; _message.Setup(c => c.SetRetain(It.Is(v => v))) .Returns(_message.Object); _message.Setup(c => c.AddProperty(It.IsAny(), It.IsAny())) .Callback((k, v) => { if (k == OpcUa.Constants.MessagePropertyRoutingKey) { routingInfo = v; } }) .Returns(_message.Object); _message.Setup(c => c.SetContentType(It.IsAny())) .Callback(v => contentType = v) .Returns(_message.Object); _message.Setup(c => c.SetContentEncoding(It.IsAny())) .Callback(v => contentEncoding = v) .Returns(_message.Object); _message.Setup(c => c.AddBuffers(It.IsAny>>())) .Callback>>(v => buffers = v.ToList()) .Returns(_message.Object); _message.Setup(c => c.SetTopic(It.IsAny())) .Returns(_message.Object); IJsonSerializer _serializer = new NewtonsoftJsonSerializer(); var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.EnableRuntimeStateReporting = true; options.Value.RuntimeStateRoutingInfo = "runtimeinfo"; var _logger = Log.Console(); using var runtimeStateReporter = new RuntimeStateReporter( _client.Object.YieldReturn(), _serializer, new MemoryKVStore().YieldReturn(), options, collector.Object, _logger); await FluentActions .Invoking(async () => await runtimeStateReporter.SendRestartAnnouncementAsync(default)) .Should() .NotThrowAsync() ; _message.Verify(c => c.SendAsync(It.IsAny()), Times.Once()); _message.Verify(m => m.Dispose(), Times.Once()); Assert.Equal("runtimeinfo", routingInfo); Assert.Equal(ContentMimeType.Json, contentType); Assert.Equal(Encoding.UTF8.WebName, contentEncoding); Assert.Single(buffers); var body = Encoding.UTF8.GetString(buffers[0].FirstSpan); Assert.StartsWith("{\"MessageType\":\"RestartAnnouncement\",\"MessageVersion\":1,\"TimestampUtc\":", body, StringComparison.Ordinal); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/SimpleEvents/NodeServicesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.SimpleEvents { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class NodeServicesTests : IClassFixture { public NodeServicesTests(SimpleEventsServer server, ITestOutputHelper output) { _output = output; _server = server; } private SimpleEventsServerTests GetTests() { return new SimpleEventsServerTests( () => new NodeServices(_server.Client, _server.Parser, _output.BuildLoggerFor>(Logging.Level), new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions()), _server.GetConnection()); } private readonly ITestOutputHelper _output; private readonly SimpleEventsServer _server; [Fact] public Task CompileSimpleBaseEventQueryTestAsync() { return GetTests().CompileSimpleBaseEventQueryTestAsync(); } [Fact] public Task CompileSimpleEventsQueryTestAsync() { return GetTests().CompileSimpleEventsQueryTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/TestData/BrowsePathTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.TestData { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class BrowsePathTests { public BrowsePathTests(TestDataServer server, ITestOutputHelper output) { _server = server; _output = output; } private BrowsePathTests GetTests() { return new BrowsePathTests( () => new NodeServices(_server.Client, _server.Parser, _output.BuildLoggerFor>(Logging.Level), new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions()), _server.GetConnection()); } private readonly TestDataServer _server; private readonly ITestOutputHelper _output; [Fact] public Task NodeBrowsePathStaticScalarMethod3Test1Async() { return GetTests().NodeBrowsePathStaticScalarMethod3Test1Async(); } [Fact] public Task NodeBrowsePathStaticScalarMethod3Test2Async() { return GetTests().NodeBrowsePathStaticScalarMethod3Test2Async(); } [Fact] public Task NodeBrowsePathStaticScalarMethod3Test3Async() { return GetTests().NodeBrowsePathStaticScalarMethod3Test3Async(); } [Fact] public Task NodeBrowsePathStaticScalarMethodsTestAsync() { return GetTests().NodeBrowsePathStaticScalarMethodsTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/TestData/BrowseStreamTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.TestData { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class BrowseStreamTests { public BrowseStreamTests(TestDataServer server, ITestOutputHelper output) { _server = server; _output = output; } private BrowseStreamTests GetTests() { return new BrowseStreamTests( () => new NodeServices(_server.Client, _server.Parser, _output.BuildLoggerFor>(Logging.Level), new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions()), _server.GetConnection()); } private readonly TestDataServer _server; private readonly ITestOutputHelper _output; [Fact] public Task NodeBrowseInRootTest1Async() { return GetTests().NodeBrowseInRootTest1Async(); } [Fact] public Task NodeBrowseInRootTest2Async() { return GetTests().NodeBrowseInRootTest2Async(); } [Fact] public Task NodeBrowseBoilersObjectsTest1Async() { return GetTests().NodeBrowseBoilersObjectsTest1Async(); } [Fact] public Task NodeBrowseDataAccessObjectsTest1Async() { return GetTests().NodeBrowseDataAccessObjectsTest1Async(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestAsync() { return GetTests().NodeBrowseStaticScalarVariablesTestAsync(); } [Fact] public Task NodeBrowseStaticArrayVariablesTestAsync() { return GetTests().NodeBrowseStaticArrayVariablesTestAsync(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestWithFilter1Async() { return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter1Async(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestWithFilter2Async() { return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter2Async(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestWithFilter3Async() { return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter3Async(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestWithFilter4Async() { return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter4Async(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestWithFilter5Async() { return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter5Async(); } [Fact] public Task NodeBrowseDiagnosticsNoneTestAsync() { return GetTests().NodeBrowseDiagnosticsNoneTestAsync(); } [Fact] public Task NodeBrowseDiagnosticsStatusTestAsync() { return GetTests().NodeBrowseDiagnosticsStatusTestAsync(); } [Fact] public Task NodeBrowseDiagnosticsInfoTestAsync() { return GetTests().NodeBrowseDiagnosticsInfoTestAsync(); } [Fact] public Task NodeBrowseDiagnosticsVerboseTestAsync() { return GetTests().NodeBrowseDiagnosticsVerboseTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/TestData/BrowseTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.TestData { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class BrowseTests { public BrowseTests(TestDataServer server, ITestOutputHelper output) { _server = server; _output = output; } private BrowseServicesTests GetTests() { return new BrowseServicesTests( () => new NodeServices(_server.Client, _server.Parser, _output.BuildLoggerFor>(Logging.Level), new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions()), _server.GetConnection()); } private readonly TestDataServer _server; private readonly ITestOutputHelper _output; [Fact] public Task NodeBrowseInRootTest1Async() { return GetTests().NodeBrowseInRootTest1Async(); } [Fact] public Task NodeBrowseInRootTest2Async() { return GetTests().NodeBrowseInRootTest2Async(); } [Fact] public Task NodeBrowseFirstInRootTest1Async() { return GetTests().NodeBrowseFirstInRootTest1Async(); } [Fact] public Task NodeBrowseFirstInRootTest2Async() { return GetTests().NodeBrowseFirstInRootTest2Async(); } [Fact] public Task NodeBrowseBoilersObjectsTest1Async() { return GetTests().NodeBrowseBoilersObjectsTest1Async(); } [Fact] public Task NodeBrowseBoilersObjectsTest2Async() { return GetTests().NodeBrowseBoilersObjectsTest2Async(); } [Fact] public Task NodeBrowseDataAccessObjectsTest1Async() { return GetTests().NodeBrowseDataAccessObjectsTest1Async(); } [Fact] public Task NodeBrowseDataAccessObjectsTest2Async() { return GetTests().NodeBrowseDataAccessObjectsTest2Async(); } [Fact] public Task NodeBrowseDataAccessObjectsTest3Async() { return GetTests().NodeBrowseDataAccessObjectsTest3Async(); } [Fact] public Task NodeBrowseDataAccessObjectsTest4Async() { return GetTests().NodeBrowseDataAccessObjectsTest4Async(); } [Fact] public Task NodeBrowseDataAccessFC1001Test1Async() { return GetTests().NodeBrowseDataAccessFC1001Test1Async(); } [Fact] public Task NodeBrowseDataAccessFC1001Test2Async() { return GetTests().NodeBrowseDataAccessFC1001Test2Async(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestAsync() { return GetTests().NodeBrowseStaticScalarVariablesTestAsync(); } [Fact] public Task NodeBrowseStaticArrayVariablesTestAsync() { return GetTests().NodeBrowseStaticArrayVariablesTestAsync(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestWithFilter1Async() { return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter1Async(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestWithFilter2Async() { return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter2Async(); } [Fact] public Task NodeBrowseStaticArrayVariablesWithValuesTestAsync() { return GetTests().NodeBrowseStaticArrayVariablesWithValuesTestAsync(); } [Fact] public Task NodeBrowseStaticArrayVariablesRawModeTestAsync() { return GetTests().NodeBrowseStaticArrayVariablesRawModeTestAsync(); } [Fact] public Task NodeBrowseContinuationTest1Async() { return GetTests().NodeBrowseContinuationTest1Async(); } [Fact] public Task NodeBrowseContinuationTest2Async() { return GetTests().NodeBrowseContinuationTest2Async(); } [Fact] public Task NodeBrowseContinuationTest3Async() { return GetTests().NodeBrowseContinuationTest3Async(); } [Fact] public Task NodeBrowseContinuationTest4Async() { return GetTests().NodeBrowseContinuationTest4Async(); } [Fact] public Task NodeBrowseDiagnosticsNoneTestAsync() { return GetTests().NodeBrowseDiagnosticsNoneTestAsync(); } [Fact] public Task NodeBrowseDiagnosticsStatusTestAsync() { return GetTests().NodeBrowseDiagnosticsStatusTestAsync(); } [Fact] public Task NodeBrowseDiagnosticsInfoTestAsync() { return GetTests().NodeBrowseDiagnosticsInfoTestAsync(); } [Fact] public Task NodeBrowseDiagnosticsVerboseTestAsync() { return GetTests().NodeBrowseDiagnosticsVerboseTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/TestData/CallArrayTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.TestData { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection.Name)] public class CallArrayTests { public CallArrayTests(TestDataServer server, ITestOutputHelper output) { _server = server; _output = output; } private CallArrayMethodTests GetTests() { return new CallArrayMethodTests( () => new NodeServices(_server.Client, _server.Parser, _output.BuildLoggerFor>(Logging.Level), new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions()), _server.GetConnection()); } private readonly TestDataServer _server; private readonly ITestOutputHelper _output; [Fact] public Task NodeMethodMetadataStaticArrayMethod1TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod1TestAsync(); } [Fact] public Task NodeMethodMetadataStaticArrayMethod2TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod2TestAsync(); } [Fact] public Task NodeMethodMetadataStaticArrayMethod3TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod3TestAsync(); } [Fact] public Task NodeMethodCallStaticArrayMethod1Test1Async() { return GetTests().NodeMethodCallStaticArrayMethod1Test1Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod1Test2Async() { return GetTests().NodeMethodCallStaticArrayMethod1Test2Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod1Test3Async() { return GetTests().NodeMethodCallStaticArrayMethod1Test3Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod1Test4Async() { return GetTests().NodeMethodCallStaticArrayMethod1Test4Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod1Test5Async() { return GetTests().NodeMethodCallStaticArrayMethod1Test5Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod2Test1Async() { return GetTests().NodeMethodCallStaticArrayMethod2Test1Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod2Test2Async() { return GetTests().NodeMethodCallStaticArrayMethod2Test2Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod2Test3Async() { return GetTests().NodeMethodCallStaticArrayMethod2Test3Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod2Test4Async() { return GetTests().NodeMethodCallStaticArrayMethod2Test4Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod3Test1Async() { return GetTests().NodeMethodCallStaticArrayMethod3Test1Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod3Test2Async() { return GetTests().NodeMethodCallStaticArrayMethod3Test2Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod3Test3Async() { return GetTests().NodeMethodCallStaticArrayMethod3Test3Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/TestData/CallScalarTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.TestData { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection.Name)] public class CallScalarTests { public CallScalarTests(TestDataServer server, ITestOutputHelper output) { _server = server; _output = output; } private CallScalarMethodTests GetTests() { return new CallScalarMethodTests( () => new NodeServices(_server.Client, _server.Parser, _output.BuildLoggerFor>(Logging.Level), new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions()), _server.GetConnection()); } private readonly TestDataServer _server; private readonly ITestOutputHelper _output; [Fact] public Task NodeMethodMetadataStaticScalarMethod1TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod1TestAsync(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod2TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod2TestAsync(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod3TestAsync(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest1Async() { return GetTests().NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest1Async(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest2Async() { return GetTests().NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest2Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod1Test1Async() { return GetTests().NodeMethodCallStaticScalarMethod1Test1Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod1Test2Async() { return GetTests().NodeMethodCallStaticScalarMethod1Test2Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod1Test3Async() { return GetTests().NodeMethodCallStaticScalarMethod1Test3Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod1Test4Async() { return GetTests().NodeMethodCallStaticScalarMethod1Test4Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod1Test5Async() { return GetTests().NodeMethodCallStaticScalarMethod1Test5Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod2Test1Async() { return GetTests().NodeMethodCallStaticScalarMethod2Test1Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod2Test2Async() { return GetTests().NodeMethodCallStaticScalarMethod2Test2Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod3Test1Async() { return GetTests().NodeMethodCallStaticScalarMethod3Test1Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod3Test2Async() { return GetTests().NodeMethodCallStaticScalarMethod3Test2Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod3WithBrowsePathNoIdsTestAsync() { return GetTests().NodeMethodCallStaticScalarMethod3WithBrowsePathNoIdsTestAsync(); } [Fact] public Task NodeMethodCallStaticScalarMethod3WithObjectIdAndBrowsePathTestAsync() { return GetTests().NodeMethodCallStaticScalarMethod3WithObjectIdAndBrowsePathTestAsync(); } [Fact] public Task NodeMethodCallStaticScalarMethod3WithObjectIdAndMethodIdAndBrowsePathTestAsync() { return GetTests().NodeMethodCallStaticScalarMethod3WithObjectIdAndMethodIdAndBrowsePathTestAsync(); } [Fact] public Task NodeMethodCallStaticScalarMethod3WithObjectPathAndMethodIdAndBrowsePathTestAsync() { return GetTests().NodeMethodCallStaticScalarMethod3WithObjectPathAndMethodIdAndBrowsePathTestAsync(); } [Fact] public Task NodeMethodCallStaticScalarMethod3WithObjectIdAndPathAndMethodIdAndPathTestAsync() { return GetTests().NodeMethodCallStaticScalarMethod3WithObjectIdAndPathAndMethodIdAndPathTestAsync(); } [Fact] public Task NodeMethodCallBoiler2ResetTestAsync() { return GetTests().NodeMethodCallBoiler2ResetTestAsync(); } [Fact] public Task NodeMethodCallBoiler1ResetTestAsync() { return GetTests().NodeMethodCallBoiler1ResetTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/TestData/ExpandTests1.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.TestData { using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class ExpandTests1 { public ExpandTests1(TestDataServer server, ITestOutputHelper output) { _server = server; _output = output; } private ConfigurationTests1 GetTests() { #pragma warning disable CA2000 // Dispose objects before losing scope return new ConfigurationTests1(new ConfigurationServices(null!, _server.Client, new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(), _output.BuildLoggerFor(Logging.Level)), _server.GetConnection()); #pragma warning restore CA2000 // Dispose objects before losing scope } private readonly TestDataServer _server; private readonly ITestOutputHelper _output; [Fact] public Task ExpandObjectWithBrowsePathTest1Async() { return GetTests().ExpandObjectWithBrowsePathTest1Async(); } [Fact] public Task ExpandObjectWithBrowsePathTest2Async() { return GetTests().ExpandObjectWithBrowsePathTest2Async(); } [Fact] public Task ExpandObjectTest1Async() { return GetTests().ExpandObjectTest1Async(); } [Fact] public Task ExpandObjectTest2Async() { return GetTests().ExpandObjectTest2Async(); } [Fact] public Task ExpandServerObjectTest1Async() { return GetTests().ExpandServerObjectTest1Async(); } [Fact] public Task ExpandServerObjectTest2Async() { return GetTests().ExpandServerObjectTest2Async(); } [Fact] public Task ExpandServerObjectTest3Async() { return GetTests().ExpandServerObjectTest3Async(); } [Fact] public Task ExpandServerObjectTest4Async() { return GetTests().ExpandServerObjectTest4Async(); } [Fact] public Task ExpandServerObjectTest5Async() { return GetTests().ExpandServerObjectTest5Async(); } [Fact] public Task ExpandBaseObjectTypeTest1Async() { return GetTests().ExpandBaseObjectTypeTest1Async(); } [Fact] public Task ExpandBaseObjectTypeTest2Async() { return GetTests().ExpandBaseObjectTypeTest2Async(); } [Fact] public Task ExpandBaseObjectsAndObjectTypesTestAsync() { return GetTests().ExpandBaseObjectsAndObjectTypesTestAsync(); } [Fact] public Task ExpandBoilerTypeTestAsync() { return GetTests().ExpandBoilerTypeTestAsync(); } [Fact] public Task ExpandBoilerDrumTypeTestAsync() { return GetTests().ExpandBoilerDrumTypeTestAsync(); } [Fact] public Task ExpandBoilerDrumAndValveTypeTestAsync() { return GetTests().ExpandBoilerDrumAndValveTypeTestAsync(); } [Fact] public Task ExpandValveTypeTestAsync() { return GetTests().ExpandValveTypeTestAsync(); } [Fact] public Task ExpandTestDataObjectTypeTestAsync() { return GetTests().ExpandTestDataObjectTypeTestAsync(); } [Fact] public Task ExpandServerTypeTestAsync() { return GetTests().ExpandServerTypeTestAsync(); } [Fact] public Task ExpandServerTypeWithMethodsTestAsync() { return GetTests().ExpandServerTypeWithMethodsTestAsync(); } [Fact] public Task ExpandPublishSubscribeTestAsync() { return GetTests().ExpandPublishSubscribeTestAsync(); } [Fact] public Task ExpandVariablesTest1Async() { return GetTests().ExpandVariablesTest1Async(); } [Fact] public Task ExpandVariablesAndObjectsTest1Async() { return GetTests().ExpandVariablesAndObjectsTest1Async(); } [Fact] public Task ExpandVariableTypesTest1Async() { return GetTests().ExpandVariableTypesTest1Async(); } [Fact] public Task ExpandVariableTypesTest2Async() { return GetTests().ExpandVariableTypesTest2Async(); } [Fact] public Task ExpandVariableTypesTest3Async() { return GetTests().ExpandVariableTypesTest3Async(); } [Fact] public Task ExpandObjectWithNoObjectsTest1Async() { return GetTests().ExpandObjectWithNoObjectsTest1Async(); } [Fact] public Task ExpandObjectWithNoObjectsTest2Async() { return GetTests().ExpandObjectWithNoObjectsTest2Async(); } [Fact] public Task ExpandEmptyEntryTest1Async() { return GetTests().ExpandEmptyEntryTest1Async(); } [Fact] public Task ExpandEmptyEntryTest2Async() { return GetTests().ExpandEmptyEntryTest2Async(); } [Fact] public Task ExpandBadNodeIdTest1Async() { return GetTests().ExpandBadNodeIdTest1Async(); } [Fact] public Task ExpandBadNodeIdTest2Async() { return GetTests().ExpandBadNodeIdTest2Async(); } [Fact] public Task ExpandBadNodeIdTest3Async() { return GetTests().ExpandBadNodeIdTest3Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/TestData/ExpandTests2.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.TestData { using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class ExpandTests2 { public ExpandTests2(TestDataServer server, ITestOutputHelper output) { _server = server; _output = output; } private ConfigurationTests2 GetTests() { return new ConfigurationTests2(c => new ConfigurationServices(c, _server.Client, new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(), _output.BuildLoggerFor(Logging.Level)), _server.GetConnection()); } private readonly TestDataServer _server; private readonly ITestOutputHelper _output; [Fact] public Task ConfigureFromObjectErrorTest1Async() { return GetTests().ConfigureFromObjectErrorTest1Async(); } [Fact] public Task ConfigureFromObjectErrorTest2Async() { return GetTests().ConfigureFromObjectErrorTest2Async(); } [Fact] public Task ConfigureFromObjectErrorTest3Async() { return GetTests().ConfigureFromObjectErrorTest3Async(); } [Fact] public Task ConfigureFromObjectWithBrowsePathTest1Async() { return GetTests().ConfigureFromObjectWithBrowsePathTest1Async(); } [Fact] public Task ConfigureFromObjectWithBrowsePathTest2Async() { return GetTests().ConfigureFromObjectWithBrowsePathTest2Async(); } [Fact] public Task ConfigureFromObjectTest1Async() { return GetTests().ConfigureFromObjectTest1Async(); } [Fact] public Task ConfigureFromObjectTest2Async() { return GetTests().ConfigureFromObjectTest2Async(); } [Fact] public Task ConfigureFromServerObjectTest1Async() { return GetTests().ConfigureFromServerObjectTest1Async(); } [Fact] public Task ConfigureFromServerObjectTest2Async() { return GetTests().ConfigureFromServerObjectTest2Async(); } [Fact] public Task ConfigureFromServerObjectTest3Async() { return GetTests().ConfigureFromServerObjectTest3Async(); } [Fact] public Task ConfigureFromServerObjectTest4Async() { return GetTests().ConfigureFromServerObjectTest4Async(); } [Fact] public Task ConfigureFromServerObjectTest5Async() { return GetTests().ConfigureFromServerObjectTest5Async(); } [Fact] public Task ConfigureFromBaseObjectTypeTest1Async() { return GetTests().ConfigureFromBaseObjectTypeTest1Async(); } [Fact] public Task ConfigureFromBaseObjectTypeTest2Async() { return GetTests().ConfigureFromBaseObjectTypeTest2Async(); } [Fact] public Task ConfigureFromBaseObjectsAndObjectTypesTestAsync() { return GetTests().ConfigureFromBaseObjectsAndObjectTypesTestAsync(); } [Fact] public Task ConfigureFromVariablesTest1Async() { return GetTests().ConfigureFromVariablesTest1Async(); } [Fact] public Task ConfigureFromVariablesAndObjectsTest1Async() { return GetTests().ConfigureFromVariablesAndObjectsTest1Async(); } [Fact] public Task ConfigureFromVariableTypesTest1Async() { return GetTests().ConfigureFromVariableTypesTest1Async(); } [Fact] public Task ConfigureFromVariableTypesTest2Async() { return GetTests().ConfigureFromVariableTypesTest2Async(); } [Fact] public Task ConfigureFromVariableTypesTest3Async() { return GetTests().ConfigureFromVariableTypesTest3Async(); } [Fact] public Task ConfigureFromObjectWithNoObjectsTest1Async() { return GetTests().ConfigureFromObjectWithNoObjectsTest1Async(); } [Fact] public Task ConfigureFromObjectWithNoObjectsTest2Async() { return GetTests().ConfigureFromObjectWithNoObjectsTest2Async(); } [Fact] public Task ConfigureFromEmptyEntryTest1Async() { return GetTests().ConfigureFromEmptyEntryTest1Async(); } [Fact] public Task ConfigureFromEmptyEntryTest2Async() { return GetTests().ConfigureFromEmptyEntryTest2Async(); } [Fact] public Task ConfigureFromBadNodeIdTest1Async() { return GetTests().ConfigureFromBadNodeIdTest1Async(); } [Fact] public Task ConfigureFromBadNodeIdTest2Async() { return GetTests().ConfigureFromBadNodeIdTest2Async(); } [Fact] public Task ConfigureFromBadNodeIdTest3Async() { return GetTests().ConfigureFromBadNodeIdTest3Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/TestData/MetadataArrayTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.TestData { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection.Name)] public class MetadataArrayTests { public MetadataArrayTests(TestDataServer server, ITestOutputHelper output) { _server = server; _output = output; } private CallArrayMethodTests GetTests() { return new CallArrayMethodTests( () => new NodeServices(_server.Client, _server.Parser, _output.BuildLoggerFor>(Logging.Level), new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions()), _server.GetConnection(), newMetadata: true); } private readonly TestDataServer _server; private readonly ITestOutputHelper _output; [Fact] public Task NodeMethodMetadataStaticArrayMethod1TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod1TestAsync(); } [Fact] public Task NodeMethodMetadataStaticArrayMethod2TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod2TestAsync(); } [Fact] public Task NodeMethodMetadataStaticArrayMethod3TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod3TestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/TestData/MetadataScalarTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.TestData { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection.Name)] public class MetadataScalarTests { public MetadataScalarTests(TestDataServer server, ITestOutputHelper output) { _server = server; _output = output; } private CallScalarMethodTests GetTests() { return new CallScalarMethodTests( () => new NodeServices(_server.Client, _server.Parser, _output.BuildLoggerFor>(Logging.Level), new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions()), _server.GetConnection(), newMetadata: true); } private readonly TestDataServer _server; private readonly ITestOutputHelper _output; [Fact] public Task NodeMethodMetadataStaticScalarMethod1TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod1TestAsync(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod2TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod2TestAsync(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod3TestAsync(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest1Async() { return GetTests().NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest1Async(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest2Async() { return GetTests().NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest2Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/TestData/MetadataTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.TestData { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class MetadataTests { public MetadataTests(TestDataServer server, ITestOutputHelper output) { _server = server; _output = output; } private NodeMetadataTests GetTests() { return new NodeMetadataTests( () => new NodeServices(_server.Client, _server.Parser, _output.BuildLoggerFor>(Logging.Level), new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions()), _server.GetConnection()); } private readonly TestDataServer _server; private readonly ITestOutputHelper _output; [Fact] public Task GetServerCapabilitiesTestAsync() { return GetTests().GetServerCapabilitiesTestAsync(); } [Fact] public Task HistoryGetServerCapabilitiesTestAsync() { return GetTests().HistoryGetServerCapabilitiesTestAsync(); } [Fact] public Task NodeGetMetadataForFolderTypeTestAsync() { return GetTests().NodeGetMetadataForFolderTypeTestAsync(); } [Fact] public Task NodeGetMetadataForServerObjectTestAsync() { return GetTests().NodeGetMetadataForServerObjectTestAsync(); } [Fact] public Task NodeGetMetadataForConditionTypeTestAsync() { return GetTests().NodeGetMetadataForConditionTypeTestAsync(); } [Fact] public Task NodeGetMetadataTestForBaseEventTypeTestAsync() { return GetTests().NodeGetMetadataTestForBaseEventTypeTestAsync(); } [Fact] public Task NodeGetMetadataForBaseInterfaceTypeTestAsync() { return GetTests().NodeGetMetadataForBaseInterfaceTypeTestAsync(); } [Fact] public Task NodeGetMetadataForBaseDataVariableTypeTestAsync() { return GetTests().NodeGetMetadataForBaseDataVariableTypeTestAsync(); } [Fact] public Task NodeGetMetadataForPropertyTypeTestAsync() { return GetTests().NodeGetMetadataForPropertyTypeTestAsync(); } [Fact] public Task NodeGetMetadataForAudioVariableTypeTestAsync() { return GetTests().NodeGetMetadataForAudioVariableTypeTestAsync(); } [Fact] public Task NodeGetMetadataForServerStatusVariableTestAsync() { return GetTests().NodeGetMetadataForServerStatusVariableTestAsync(); } [Fact] public Task NodeGetMetadataForRedundancySupportPropertyTestAsync() { return GetTests().NodeGetMetadataForRedundancySupportPropertyTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/TestData/ReadArrayTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.TestData { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class ValueReadArrayTests { public ValueReadArrayTests(TestDataServer server, ITestOutputHelper output) { _server = server; _output = output; } private ReadArrayValueTests GetTests() { return new ReadArrayValueTests( () => new NodeServices(_server.Client, _server.Parser, _output.BuildLoggerFor>(Logging.Level), new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions()), _server.GetConnection(), (c, n, s) => _server.Client.ReadValueAsync(c, n, s)); } private readonly TestDataServer _server; private readonly ITestOutputHelper _output; [Fact] public Task NodeReadAllStaticArrayVariableNodeClassTest1Async() { return GetTests().NodeReadAllStaticArrayVariableNodeClassTest1Async(); } [Fact] public Task NodeReadAllStaticArrayVariableAccessLevelTest1Async() { return GetTests().NodeReadAllStaticArrayVariableAccessLevelTest1Async(); } [Fact] public Task NodeReadAllStaticArrayVariableWriteMaskTest1Async() { return GetTests().NodeReadAllStaticArrayVariableWriteMaskTest1Async(); } [Fact] public Task NodeReadAllStaticArrayVariableWriteMaskTest2Async() { return GetTests().NodeReadAllStaticArrayVariableWriteMaskTest2Async(); } [Fact] public Task NodeReadStaticArrayBooleanValueVariableTestAsync() { return GetTests().NodeReadStaticArrayBooleanValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArraySByteValueVariableTestAsync() { return GetTests().NodeReadStaticArraySByteValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayByteValueVariableTestAsync() { return GetTests().NodeReadStaticArrayByteValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayInt16ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayInt16ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayUInt16ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayUInt16ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayInt32ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayInt32ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayUInt32ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayUInt32ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayInt64ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayInt64ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayUInt64ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayUInt64ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayFloatValueVariableTestAsync() { return GetTests().NodeReadStaticArrayFloatValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayDoubleValueVariableTestAsync() { return GetTests().NodeReadStaticArrayDoubleValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayStringValueVariableTestAsync() { return GetTests().NodeReadStaticArrayStringValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayDateTimeValueVariableTestAsync() { return GetTests().NodeReadStaticArrayDateTimeValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayGuidValueVariableTestAsync() { return GetTests().NodeReadStaticArrayGuidValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayByteStringValueVariableTestAsync() { return GetTests().NodeReadStaticArrayByteStringValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayXmlElementValueVariableTestAsync() { return GetTests().NodeReadStaticArrayXmlElementValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayNodeIdValueVariableTestAsync() { return GetTests().NodeReadStaticArrayNodeIdValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayExpandedNodeIdValueVariableTestAsync() { return GetTests().NodeReadStaticArrayExpandedNodeIdValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayQualifiedNameValueVariableTestAsync() { return GetTests().NodeReadStaticArrayQualifiedNameValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayLocalizedTextValueVariableTestAsync() { return GetTests().NodeReadStaticArrayLocalizedTextValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayStatusCodeValueVariableTestAsync() { return GetTests().NodeReadStaticArrayStatusCodeValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayVariantValueVariableTestAsync() { return GetTests().NodeReadStaticArrayVariantValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayEnumerationValueVariableTestAsync() { return GetTests().NodeReadStaticArrayEnumerationValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayStructureValueVariableTestAsync() { return GetTests().NodeReadStaticArrayStructureValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayNumberValueVariableTestAsync() { return GetTests().NodeReadStaticArrayNumberValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayIntegerValueVariableTestAsync() { return GetTests().NodeReadStaticArrayIntegerValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayUIntegerValueVariableTestAsync() { return GetTests().NodeReadStaticArrayUIntegerValueVariableTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/TestData/ReadCollection.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.TestData { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public class ReadCollection : ICollectionFixture { public const string Name = "TestDataRead"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/TestData/ReadScalarTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.TestData { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class ValueReadScalarTests { public ValueReadScalarTests(TestDataServer server, ITestOutputHelper output) { _server = server; _output = output; } private ReadScalarValueTests GetTests() { return new ReadScalarValueTests( () => new NodeServices(_server.Client, _server.Parser, _output.BuildLoggerFor>(Logging.Level), new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions()), _server.GetConnection(), (ep, n, s) => _server.Client.ReadValueAsync(ep, n, s)); } private readonly TestDataServer _server; private readonly ITestOutputHelper _output; [Fact] public Task NodeReadAllStaticScalarVariableNodeClassTest1Async() { return GetTests().NodeReadAllStaticScalarVariableNodeClassTest1Async(); } [Fact] public Task NodeReadAllStaticScalarVariableAccessLevelTest1Async() { return GetTests().NodeReadAllStaticScalarVariableAccessLevelTest1Async(); } [Fact] public Task NodeReadAllStaticScalarVariableWriteMaskTest1Async() { return GetTests().NodeReadAllStaticScalarVariableWriteMaskTest1Async(); } [Fact] public Task NodeReadAllStaticScalarVariableWriteMaskTest2Async() { return GetTests().NodeReadAllStaticScalarVariableWriteMaskTest2Async(); } [Fact] public Task NodeReadStaticScalarBooleanValueVariableTestAsync() { return GetTests().NodeReadStaticScalarBooleanValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest1Async() { return GetTests().NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest1Async(); } [Fact] public Task NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest2Async() { return GetTests().NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest2Async(); } [Fact] public Task NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest3Async() { return GetTests().NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest3Async(); } [Fact] public Task NodeReadStaticScalarSByteValueVariableTestAsync() { return GetTests().NodeReadStaticScalarSByteValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarByteValueVariableTestAsync() { return GetTests().NodeReadStaticScalarByteValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarInt16ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarInt16ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarUInt16ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarUInt16ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarInt32ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarInt32ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarUInt32ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarUInt32ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarInt64ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarInt64ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarUInt64ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarUInt64ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarFloatValueVariableTestAsync() { return GetTests().NodeReadStaticScalarFloatValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarDoubleValueVariableTestAsync() { return GetTests().NodeReadStaticScalarDoubleValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarStringValueVariableTestAsync() { return GetTests().NodeReadStaticScalarStringValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarDateTimeValueVariableTestAsync() { return GetTests().NodeReadStaticScalarDateTimeValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarGuidValueVariableTestAsync() { return GetTests().NodeReadStaticScalarGuidValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarByteStringValueVariableTestAsync() { return GetTests().NodeReadStaticScalarByteStringValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarXmlElementValueVariableTestAsync() { return GetTests().NodeReadStaticScalarXmlElementValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarNodeIdValueVariableTestAsync() { return GetTests().NodeReadStaticScalarNodeIdValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarExpandedNodeIdValueVariableTestAsync() { return GetTests().NodeReadStaticScalarExpandedNodeIdValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarQualifiedNameValueVariableTestAsync() { return GetTests().NodeReadStaticScalarQualifiedNameValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarLocalizedTextValueVariableTestAsync() { return GetTests().NodeReadStaticScalarLocalizedTextValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarStatusCodeValueVariableTestAsync() { return GetTests().NodeReadStaticScalarStatusCodeValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarVariantValueVariableTestAsync() { return GetTests().NodeReadStaticScalarVariantValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarEnumerationValueVariableTestAsync() { return GetTests().NodeReadStaticScalarEnumerationValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarStructuredValueVariableTestAsync() { return GetTests().NodeReadStaticScalarStructuredValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarNumberValueVariableTestAsync() { return GetTests().NodeReadStaticScalarNumberValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarIntegerValueVariableTestAsync() { return GetTests().NodeReadStaticScalarIntegerValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarUIntegerValueVariableTestAsync() { return GetTests().NodeReadStaticScalarUIntegerValueVariableTestAsync(); } [Fact] public Task NodeReadDataAccessMeasurementFloatValueTestAsync() { return GetTests().NodeReadDataAccessMeasurementFloatValueTestAsync(); } [Fact] public Task NodeReadDiagnosticsNoneTestAsync() { return GetTests().NodeReadDiagnosticsNoneTestAsync(); } [Fact] public Task NodeReadDiagnosticsStatusTestAsync() { return GetTests().NodeReadDiagnosticsStatusTestAsync(); } [Fact] public Task NodeReadDiagnosticsDebugTestAsync() { return GetTests().NodeReadDiagnosticsDebugTestAsync(); } [Fact] public Task NodeReadDiagnosticsVerboseTestAsync() { return GetTests().NodeReadDiagnosticsVerboseTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/TestData/WriteArrayTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.TestData { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection.Name)] public class ValueWriteArrayTests { public ValueWriteArrayTests(TestDataServer server, ITestOutputHelper output) { _server = server; _output = output; } private WriteArrayValueTests GetTests() { return new WriteArrayValueTests( () => new NodeServices(_server.Client, _server.Parser, _output.BuildLoggerFor>(Logging.Level), new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions()), _server.GetConnection(), (c, n, s) => _server.Client.ReadValueAsync(c, n, s)); } private readonly TestDataServer _server; private readonly ITestOutputHelper _output; [Fact] public Task NodeWriteStaticArrayBooleanValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayBooleanValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArraySByteValueVariableTestAsync() { return GetTests().NodeWriteStaticArraySByteValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayByteValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayByteValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayInt16ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayInt16ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayUInt16ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayUInt16ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayInt32ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayInt32ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayUInt32ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayUInt32ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayInt64ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayInt64ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayUInt64ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayUInt64ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayFloatValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayFloatValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayDoubleValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayDoubleValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayStringValueVariableTest1Async() { return GetTests().NodeWriteStaticArrayStringValueVariableTest1Async(); } [Fact] public Task NodeWriteStaticArrayStringValueVariableTest2Async() { return GetTests().NodeWriteStaticArrayStringValueVariableTest2Async(); } [Fact] public Task NodeWriteStaticArrayDateTimeValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayDateTimeValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayGuidValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayGuidValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayByteStringValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayByteStringValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayXmlElementValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayXmlElementValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayNodeIdValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayNodeIdValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayExpandedNodeIdValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayExpandedNodeIdValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayQualifiedNameValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayQualifiedNameValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayLocalizedTextValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayLocalizedTextValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayStatusCodeValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayStatusCodeValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayVariantValueVariableTest1Async() { return GetTests().NodeWriteStaticArrayVariantValueVariableTest1Async(); } [Fact] public Task NodeWriteStaticArrayEnumerationValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayEnumerationValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayStructureValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayStructureValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayNumberValueVariableTest1Async() { return GetTests().NodeWriteStaticArrayNumberValueVariableTest1Async(); } [Fact] public Task NodeWriteStaticArrayNumberValueVariableTest2Async() { return GetTests().NodeWriteStaticArrayNumberValueVariableTest2Async(); } [Fact] public Task NodeWriteStaticArrayIntegerValueVariableTest1Async() { return GetTests().NodeWriteStaticArrayIntegerValueVariableTest1Async(); } [Fact] public Task NodeWriteStaticArrayIntegerValueVariableTest2Async() { return GetTests().NodeWriteStaticArrayIntegerValueVariableTest2Async(); } [Fact] public Task NodeWriteStaticArrayUIntegerValueVariableTest1Async() { return GetTests().NodeWriteStaticArrayUIntegerValueVariableTest1Async(); } [Fact] public Task NodeWriteStaticArrayUIntegerValueVariableTest2Async() { return GetTests().NodeWriteStaticArrayUIntegerValueVariableTest2Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/TestData/WriteCollection.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.TestData { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public class WriteCollection : ICollectionFixture { public const string Name = "TestDataWrite"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Services/TestData/WriteScalarTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Services.TestData { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Microsoft.Extensions.Configuration; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection.Name)] public class ValueWriteScalarTests { public ValueWriteScalarTests(TestDataServer server, ITestOutputHelper output) { _server = server; _output = output; } private WriteScalarValueTests GetTests() { return new WriteScalarValueTests( () => new NodeServices(_server.Client, _server.Parser, _output.BuildLoggerFor>(Logging.Level), new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions()), _server.GetConnection(), (c, n, s) => _server.Client.ReadValueAsync(c, n, s)); } private readonly TestDataServer _server; private readonly ITestOutputHelper _output; [Fact] public Task NodeWriteStaticScalarBooleanValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarBooleanValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest1Async() { return GetTests().NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest1Async(); } [Fact] public Task NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest2Async() { return GetTests().NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest2Async(); } [Fact] public Task NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest3Async() { return GetTests().NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest3Async(); } [Fact] public Task NodeWriteStaticScalarSByteValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarSByteValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarByteValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarByteValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarInt16ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarInt16ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarUInt16ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarUInt16ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarInt32ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarInt32ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarUInt32ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarUInt32ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarInt64ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarInt64ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarUInt64ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarUInt64ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarFloatValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarFloatValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarDoubleValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarDoubleValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarStringValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarStringValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarDateTimeValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarDateTimeValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarGuidValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarGuidValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarByteStringValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarByteStringValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarXmlElementValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarXmlElementValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarNodeIdValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarNodeIdValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarExpandedNodeIdValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarExpandedNodeIdValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarQualifiedNameValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarQualifiedNameValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarLocalizedTextValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarLocalizedTextValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarStatusCodeValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarStatusCodeValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarVariantValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarVariantValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarEnumerationValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarEnumerationValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarStructuredValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarStructuredValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarNumberValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarNumberValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarIntegerValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarIntegerValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarUIntegerValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarUIntegerValueVariableTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Stack/Extensions/RelativePathExTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Opc.Ua.Extensions { using Azure.IIoT.OpcUa.Publisher.Models; using Xunit; public class RelativePathExTests { [Fact] public void EncodeDecodePath1() { var path = new string[] { "Test", "Test", "<#HasChild>Test", "Test", "Test", "/foo", ".bar", "/!#flah", "!#flah", "xxxx" }; var context = new ServiceMessageContext(); var relative = path.ToRelativePath(context); var result = relative.AsString(context, NamespaceFormat.Uri); Assert.Equal(path, result); } [Fact] public void EncodeDecodePath2() { var path = new string[] { "Test", "<#http://opcfoundation.org/ua#i_33>Test", "<#!HasProperty>Test", "<#!http://contoso.com/ua#i_44>Test", "Test", "#foo", "!.bar", "!#/flah", "!/#flah", "!xxxx" }; var context = new ServiceMessageContext(); var relative = path.ToRelativePath(context); var expected = relative.AsString(context, NamespaceFormat.Uri); relative = expected.ToRelativePath(context); var result = relative.AsString(context, NamespaceFormat.Uri); Assert.Equal(expected, result); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Stack/Extensions/SequenceNumberTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Opc.Ua.Extensions { using System.Linq; using Xunit; public class SequenceNumberTests { [Fact] public void TestIncrementSequenceNumber0() { uint v = 3234232; var v2 = SequenceNumber.Increment32(ref v); Assert.Equal(v, v2); Assert.Equal(3234232u + 1u, v); } [Fact] public void TestIncrementSequenceNumber1() { var v = 0xffffffff; var v2 = SequenceNumber.Increment32(ref v); Assert.Equal(v, v2); Assert.Equal(1u, v); } [Fact] public void TestIncrementSequenceNumber2() { uint v = 0; var v2 = SequenceNumber.Increment32(ref v); Assert.Equal(v, v2); Assert.Equal(1u, v); } [Fact] public void TestIncrementSequenceNumber3() { var v = 0xfffffffe; var v2 = SequenceNumber.Increment32(ref v); Assert.Equal(v, v2); Assert.Equal(0xffffffff, v); } [Fact] public void TestGetMissingSequenceNumbers0() { var missing = SequenceNumber.Missing(4u, 4u, out var dropped).ToList(); Assert.Empty(missing); Assert.False(dropped); missing = [.. SequenceNumber.Missing(0u, 0u, out dropped)]; Assert.Empty(missing); Assert.False(dropped); missing = [.. SequenceNumber.Missing(0xffffffffu, 0xffffffffu, out dropped)]; Assert.Empty(missing); Assert.False(dropped); } [Fact] public void TestGetMissingSequenceNumbers1() { var missing = SequenceNumber.Missing(0xffffffffu, 1u, out var dropped).ToList(); Assert.Empty(missing); Assert.False(dropped); } [Fact] public void TestGetMissingSequenceNumbers2() { var missing = SequenceNumber.Missing(1u, 0xffffffffu, out var dropped).ToList(); Assert.Empty(missing); Assert.False(dropped); } [Fact] public void TestGetMissingSequenceNumbers3() { var missing = SequenceNumber.Missing(0xfffffffeu, 2u, out var dropped).ToList(); Assert.Equal(new uint[] { 0xffffffff, 1u }, missing); Assert.True(dropped); missing = [.. SequenceNumber.Missing(2u, 0xfffffffeu, out dropped)]; Assert.Equal(new uint[] { 0xffffffff, 1u }, missing); Assert.False(dropped); } [Fact] public void TestGetMissingSequenceNumbers4() { var missing = SequenceNumber.Missing(0xfffffffeu, 3u, out var dropped).ToList(); Assert.Equal(new uint[] { 0xffffffff, 1u, 2u }, missing); Assert.True(dropped); missing = [.. SequenceNumber.Missing(3u, 0xfffffffeu, out dropped)]; Assert.Equal(new uint[] { 0xffffffff, 1u, 2u }, missing); Assert.False(dropped); } [Fact] public void TestGetMissingSequenceNumbers5() { const uint maxInt = unchecked(int.MaxValue); const uint minInt = unchecked((uint)int.MinValue); var missing = SequenceNumber.Missing(maxInt - 1, minInt + 1, out var dropped).ToList(); Assert.Equal(new uint[] { maxInt, minInt }, missing); Assert.True(dropped); missing = [.. SequenceNumber.Missing(minInt + 1, maxInt - 1, out dropped)]; Assert.Equal(new uint[] { maxInt, minInt }, missing); Assert.False(dropped); missing = [.. SequenceNumber.Missing(minInt, maxInt, out dropped)]; Assert.Empty(missing); Assert.False(dropped); missing = [.. SequenceNumber.Missing(maxInt, minInt, out dropped)]; Assert.Empty(missing); Assert.False(dropped); missing = [.. SequenceNumber.Missing(maxInt, maxInt, out dropped)]; Assert.Empty(missing); Assert.False(dropped); missing = [.. SequenceNumber.Missing(minInt, minInt, out dropped)]; Assert.Empty(missing); Assert.False(dropped); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Stack/GetBrowsePathsFromRootTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Extensions { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Opc.Ua; using Opc.Ua.Extensions; using System.Linq; using System.Threading.Tasks; using Xunit; public sealed class GetBrowsePathsFromRootTests : IClassFixture { public GetBrowsePathsFromRootTests(PlcServer server) { _server = server; } private readonly PlcServer _server; [Fact] public async Task GetBrowsePathsFromRootTest1Async() { var nodes = new[] { Plc.Namespaces.PlcApplications + "#s=FastUIntScalar1" }; var results = await _server.Client.ExecuteAsync(_server.GetConnection(), async context => { var results = await context.Session.GetBrowsePathsFromRootAsync(new RequestHeader(), nodes.Select(n => n.ToNodeId(context.Session.MessageContext)).ToList(), context.Ct); return results.Select(r => r.Path.Elements .Select(e => e.TargetName.AsString(context.Session.MessageContext, NamespaceFormat.Index)) .ToList()); }); var result = Assert.Single(results); Assert.Equal("Objects/2:OpcPlc/2:Telemetry/2:Fast/2:FastUIntScalar1", result.Aggregate((a, b) => $"{a}/{b}")); } [Fact] public async Task GetBrowsePathsFromRootTest2Async() { var nodes = new[] { Plc.Namespaces.PlcApplications + "#s=FastUIntScalar10" }; var results = await _server.Client.ExecuteAsync(_server.GetConnection(), async context => { return await context.Session.GetBrowsePathsFromRootAsync(new RequestHeader(), nodes.Select(n => n.ToNodeId(context.Session.MessageContext)).ToList(), context.Ct); }); var result = Assert.Single(results); Assert.Empty(result.Path.Elements); Assert.NotNull(result.ErrorInfo); Assert.Equal(StatusCodes.BadNodeIdUnknown, result.ErrorInfo.StatusCode); } [Fact] public async Task GetBrowsePathsFromRootTest3Async() { var nodes = new[] { Plc.Namespaces.PlcApplications + "#s=FastUIntScalar1", Plc.Namespaces.PlcApplications + "#s=FastUIntScalar2", Plc.Namespaces.PlcApplications + "#s=FastUIntScalar3" }; var results = await _server.Client.ExecuteAsync(_server.GetConnection(), async context => { var results = await context.Session.GetBrowsePathsFromRootAsync(new RequestHeader(), nodes.Select(n => n.ToNodeId(context.Session.MessageContext)).ToList(), context.Ct); return results.Select(r => r.Path.Elements .Select(e => e.TargetName.AsString(context.Session.MessageContext, NamespaceFormat.Index)) .ToList()); }); Assert.Collection(results, result => Assert.Equal("Objects/2:OpcPlc/2:Telemetry/2:Fast/2:FastUIntScalar1", result.Aggregate((a, b) => $"{a}/{b}")), result => Assert.Equal("Objects/2:OpcPlc/2:Telemetry/2:Fast/2:FastUIntScalar2", result.Aggregate((a, b) => $"{a}/{b}")), result => Assert.Equal("Objects/2:OpcPlc/2:Telemetry/2:Fast/2:FastUIntScalar3", result.Aggregate((a, b) => $"{a}/{b}")) ); } [Fact] public async Task GetBrowsePathsFromRootTest4Async() { var nodes = new[] { Plc.Namespaces.PlcApplications + "#s=FastUIntScalar1", Plc.Namespaces.PlcApplications + "#s=FastUIntScalar10" }; var results = await _server.Client.ExecuteAsync(_server.GetConnection(), async context => { return await context.Session.GetBrowsePathsFromRootAsync(new RequestHeader(), nodes.Select(n => n.ToNodeId(context.Session.MessageContext)).ToList(), context.Ct); }); Assert.Collection(results, result => { Assert.NotEmpty(result.Path.Elements); Assert.Null(result.ErrorInfo); Assert.Equal(5, result.Path.Elements.Count); }, result => { Assert.Empty(result.Path.Elements); Assert.NotNull(result.ErrorInfo); Assert.Equal(StatusCodes.BadNodeIdUnknown, result.ErrorInfo.StatusCode); }); } [Theory] [InlineData(0)] [InlineData(146)] [InlineData(13523)] //[InlineData(50000)] public async Task GetBrowsePathsFromRootTest5Async(int count) { var nodes = Enumerable.Range(0, count).Select(n => Plc.Namespaces.PlcApplications + "#s=FastUIntScalar1").ToList(); var results = await _server.Client.ExecuteAsync(_server.GetConnection(), async context => { var results = await context.Session.GetBrowsePathsFromRootAsync(new RequestHeader(), nodes.ConvertAll(n => n.ToNodeId(context.Session.MessageContext)), context.Ct); return results.Select(r => r.Path.Elements .Select(e => e.TargetName.AsString(context.Session.MessageContext, NamespaceFormat.Index)) .ToList()); }); Assert.All(results, result => Assert.Equal( "Objects/2:OpcPlc/2:Telemetry/2:Fast/2:FastUIntScalar1", result.Aggregate((a, b) => $"{a}/{b}"))); } [Fact] public async Task GetBrowsePathsFromRootTest7Async() { var nodes = new[] { ObjectIds.ObjectsFolder, ObjectIds.TypesFolder, ObjectIds.EventTypesFolder, ObjectTypeIds.BaseConditionClassType, DataTypeIds.AliasNameDataType, DataTypeIds.XVType, VariableIds.AlarmConditionType_ActiveState, VariableIds.Server_ServerCapabilities_MaxSelectClauseParameters, VariableIds.Server_LocalTime, VariableIds.AcknowledgeableConditionType_AckedState, VariableIds.Server_ServerStatus_CurrentTime, ObjectIds.Server }; var results = await _server.Client.ExecuteAsync(_server.GetConnection(), async context => { var results = await context.Session.GetBrowsePathsFromRootAsync( new RequestHeader(), nodes, context.Ct); return results .Select(r => r.Path.Elements .Select(e => e.TargetName.AsString(context.Session.MessageContext, NamespaceFormat.Index)) .Aggregate((a, b) => $"{a}/{b}")) .ToList(); }); Assert.Collection(results, result => Assert.Equal("Objects", result), result => Assert.Equal("Types", result), result => Assert.Equal("Types/EventTypes", result), result => Assert.Equal("Types/ObjectTypes/BaseObjectType/BaseConditionClassType", result), result => Assert.Equal("Types/DataTypes/BaseDataType/Structure/AliasNameDataType", result), result => Assert.Equal("Types/DataTypes/BaseDataType/Structure/XVType", result), result => Assert.Equal("Types/EventTypes/BaseEventType/ConditionType/AcknowledgeableConditionType/AlarmConditionType/ActiveState", result), result => Assert.Equal("Objects/Server/ServerCapabilities/MaxSelectClauseParameters", result), result => Assert.Equal("Objects/Server/LocalTime", result), result => Assert.Equal("Types/EventTypes/BaseEventType/ConditionType/AcknowledgeableConditionType/AckedState", result), result => Assert.Equal("Objects/Server/ServerStatus/CurrentTime", result), result => Assert.Equal("Objects/Server", result) ); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Stack/GetSimpleEventFilterTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Stack { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Moq; using Opc.Ua; using Opc.Ua.Client; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Xunit; public class GetSimpleEventFilterTests : OpcUaMonitoredItemTestsBase { [Fact] public async Task SetupSimpleFilterForBaseEventTypeAsync() { // Arrange var template = new EventMonitoredItemModel { StartNodeId = "i=2258", EventFilter = new EventFilterModel { TypeDefinitionId = ObjectTypeIds.BaseEventType.ToString() } }; // Act var monitoredItem = await GetMonitoredItemAsync(template); // Assert Assert.NotNull(monitoredItem.Filter); Assert.IsType(monitoredItem.Filter); var eventFilter = (EventFilter)monitoredItem.Filter; Assert.NotNull(eventFilter.SelectClauses); Assert.Equal(2, eventFilter.SelectClauses.Count); Assert.Equal(ObjectTypeIds.BaseEventType, eventFilter.SelectClauses[0].TypeDefinitionId); Assert.Equal(BrowseNames.Message, eventFilter.SelectClauses[0].BrowsePath.ElementAtOrDefault(0)); Assert.Equal(ObjectTypeIds.BaseEventType, eventFilter.SelectClauses[1].TypeDefinitionId); Assert.Equal(BrowseNames.EventType, eventFilter.SelectClauses[1].BrowsePath.ElementAtOrDefault(0)); Assert.NotNull(eventFilter.WhereClause); Assert.NotNull(eventFilter.WhereClause.Elements); Assert.Single(eventFilter.WhereClause.Elements); Assert.Equal(FilterOperator.OfType, eventFilter.WhereClause.Elements[0].FilterOperator); Assert.NotNull(eventFilter.WhereClause.Elements[0].FilterOperands); Assert.Single(eventFilter.WhereClause.Elements[0].FilterOperands); Assert.IsType(eventFilter.WhereClause.Elements[0].FilterOperands[0].Body); var operand = (LiteralOperand)eventFilter.WhereClause.Elements[0].FilterOperands[0].Body; Assert.IsType(operand.Value.Value); var nodeId = (NodeId)operand.Value.Value; Assert.Equal(nodeId, ObjectTypeIds.BaseEventType); } [Fact] public async Task SetupSimpleFilterForConditionTypeAsync() { // Arrange var template = new EventMonitoredItemModel { StartNodeId = "i=2258", EventFilter = new EventFilterModel { TypeDefinitionId = ObjectTypeIds.ConditionType.ToString() } }; // Act var monitoredItem = await GetMonitoredItemAsync(template); // Assert Assert.NotNull(monitoredItem.Filter); Assert.IsType(monitoredItem.Filter); var eventFilter = (EventFilter)monitoredItem.Filter; Assert.NotNull(eventFilter.SelectClauses); Assert.Equal(7, eventFilter.SelectClauses.Count); Assert.Equal(Attributes.NodeId, eventFilter.SelectClauses[0].AttributeId); Assert.Equal(ObjectTypeIds.ConditionType, eventFilter.SelectClauses[0].TypeDefinitionId); Assert.Empty(eventFilter.SelectClauses[0].BrowsePath); Assert.Equal(ObjectTypeIds.BaseEventType, eventFilter.SelectClauses[1].TypeDefinitionId); Assert.Equal(BrowseNames.Comment, eventFilter.SelectClauses[1].BrowsePath.ElementAtOrDefault(0)); Assert.Equal(ObjectTypeIds.BaseEventType, eventFilter.SelectClauses[2].TypeDefinitionId); Assert.Equal(BrowseNames.ConditionName, eventFilter.SelectClauses[2].BrowsePath.ElementAtOrDefault(0)); Assert.Equal(ObjectTypeIds.BaseEventType, eventFilter.SelectClauses[3].TypeDefinitionId); Assert.Equal(BrowseNames.EnabledState, eventFilter.SelectClauses[3].BrowsePath.ElementAtOrDefault(0)); Assert.Equal(ObjectTypeIds.BaseEventType, eventFilter.SelectClauses[4].TypeDefinitionId); Assert.Equal(BrowseNames.EnabledState, eventFilter.SelectClauses[4].BrowsePath.ElementAtOrDefault(0)); Assert.Equal(BrowseNames.Id, eventFilter.SelectClauses[4].BrowsePath.ElementAtOrDefault(1)); Assert.Equal(ObjectTypeIds.BaseEventType, eventFilter.SelectClauses[5].TypeDefinitionId); Assert.Equal(BrowseNames.Message, eventFilter.SelectClauses[5].BrowsePath.ElementAtOrDefault(0)); Assert.Equal(ObjectTypeIds.BaseEventType, eventFilter.SelectClauses[6].TypeDefinitionId); Assert.Equal(BrowseNames.EventType, eventFilter.SelectClauses[6].BrowsePath.ElementAtOrDefault(0)); Assert.NotNull(eventFilter.WhereClause); Assert.NotNull(eventFilter.WhereClause.Elements); Assert.Single(eventFilter.WhereClause.Elements); Assert.Equal(FilterOperator.OfType, eventFilter.WhereClause.Elements[0].FilterOperator); Assert.NotNull(eventFilter.WhereClause.Elements[0].FilterOperands); Assert.Single(eventFilter.WhereClause.Elements[0].FilterOperands); Assert.IsType(eventFilter.WhereClause.Elements[0].FilterOperands[0].Body); var operand = (LiteralOperand)eventFilter.WhereClause.Elements[0].FilterOperands[0].Body; Assert.IsType(operand.Value.Value); var nodeId = (NodeId)operand.Value.Value; Assert.Equal(nodeId, ObjectTypeIds.ConditionType); } [Fact] public async Task SetupSimpleFilterForConditionTypeWithConditionHandlingEnabledAsync() { // Arrange var template = new EventMonitoredItemModel { StartNodeId = "i=2258", EventFilter = new EventFilterModel { TypeDefinitionId = ObjectTypeIds.ConditionType.ToString() }, ConditionHandling = new ConditionHandlingOptionsModel { SnapshotInterval = 10 } }; // Act var monitoredItem = await GetMonitoredItemAsync(template); // Assert Assert.NotNull(monitoredItem.Filter); Assert.IsType(monitoredItem.Filter); var eventFilter = (EventFilter)monitoredItem.Filter; Assert.NotNull(eventFilter.SelectClauses); Assert.Equal(8, eventFilter.SelectClauses.Count); Assert.Equal(Attributes.NodeId, eventFilter.SelectClauses[0].AttributeId); Assert.Equal(ObjectTypeIds.ConditionType, eventFilter.SelectClauses[0].TypeDefinitionId); Assert.Empty(eventFilter.SelectClauses[0].BrowsePath); Assert.Equal(ObjectTypeIds.BaseEventType, eventFilter.SelectClauses[1].TypeDefinitionId); Assert.Equal(BrowseNames.Comment, eventFilter.SelectClauses[1].BrowsePath.ElementAtOrDefault(0)); Assert.Equal(ObjectTypeIds.BaseEventType, eventFilter.SelectClauses[2].TypeDefinitionId); Assert.Equal(BrowseNames.ConditionName, eventFilter.SelectClauses[2].BrowsePath.ElementAtOrDefault(0)); Assert.Equal(ObjectTypeIds.BaseEventType, eventFilter.SelectClauses[3].TypeDefinitionId); Assert.Equal(BrowseNames.EnabledState, eventFilter.SelectClauses[3].BrowsePath.ElementAtOrDefault(0)); Assert.Equal(ObjectTypeIds.BaseEventType, eventFilter.SelectClauses[4].TypeDefinitionId); Assert.Equal(BrowseNames.EnabledState, eventFilter.SelectClauses[4].BrowsePath.ElementAtOrDefault(0)); Assert.Equal(BrowseNames.Id, eventFilter.SelectClauses[4].BrowsePath.ElementAtOrDefault(1)); Assert.Equal(ObjectTypeIds.BaseEventType, eventFilter.SelectClauses[5].TypeDefinitionId); Assert.Equal(BrowseNames.Message, eventFilter.SelectClauses[5].BrowsePath.ElementAtOrDefault(0)); Assert.Equal(ObjectTypeIds.BaseEventType, eventFilter.SelectClauses[6].TypeDefinitionId); Assert.Equal(BrowseNames.EventType, eventFilter.SelectClauses[6].BrowsePath.ElementAtOrDefault(0)); Assert.Equal(ObjectTypeIds.ConditionType, eventFilter.SelectClauses[7].TypeDefinitionId); Assert.Equal(BrowseNames.Retain, eventFilter.SelectClauses[7].BrowsePath.ElementAtOrDefault(0)); Assert.NotNull(eventFilter.WhereClause); Assert.NotNull(eventFilter.WhereClause.Elements); Assert.Single(eventFilter.WhereClause.Elements); Assert.Equal(FilterOperator.OfType, eventFilter.WhereClause.Elements[0].FilterOperator); Assert.NotNull(eventFilter.WhereClause.Elements[0].FilterOperands); Assert.Single(eventFilter.WhereClause.Elements[0].FilterOperands); Assert.IsType(eventFilter.WhereClause.Elements[0].FilterOperands[0].Body); var operand = (LiteralOperand)eventFilter.WhereClause.Elements[0].FilterOperands[0].Body; Assert.IsType(operand.Value.Value); var nodeId = (NodeId)operand.Value.Value; Assert.Equal(nodeId, ObjectTypeIds.ConditionType); } public GetSimpleEventFilterTests() { AddNode(_baseObjectTypeNode); AddNode(_baseEventTypeNode); AddNode(_messageNode); AddNode(_conditionTypeNode); AddNode(_conditionNameNode); AddNode(_commentNode); AddNode(_enabledStateNode); AddNode(_idNode); _baseObjectTypeNode.ReferenceTable.Add(ReferenceTypeIds.HasSubtype, false, ObjectTypeIds.BaseEventType); _baseEventTypeNode.ReferenceTable.Add(ReferenceTypeIds.HasSubtype, true, ObjectTypeIds.BaseObjectType); _baseEventTypeNode.ReferenceTable.Add(ReferenceTypeIds.HasProperty, false, _messageNode.NodeId); _messageNode.ReferenceTable.Add(ReferenceTypeIds.HasProperty, true, ObjectTypeIds.BaseEventType); _baseEventTypeNode.ReferenceTable.Add(ReferenceTypeIds.HasSubtype, false, ObjectTypeIds.ConditionType); _conditionTypeNode.ReferenceTable.Add(ReferenceTypeIds.HasSubtype, true, ObjectTypeIds.BaseEventType); _conditionTypeNode.ReferenceTable.Add(ReferenceTypeIds.HasProperty, false, _conditionNameNode.NodeId); _conditionTypeNode.ReferenceTable.Add(ReferenceTypeIds.HasProperty, false, _commentNode.NodeId); _conditionNameNode.ReferenceTable.Add(ReferenceTypeIds.HasProperty, true, ObjectTypeIds.ConditionType); _conditionTypeNode.ReferenceTable.Add(ReferenceTypeIds.HasComponent, false, _enabledStateNode.NodeId); _enabledStateNode.ReferenceTable.Add(ReferenceTypeIds.HasComponent, true, ObjectTypeIds.ConditionType); _enabledStateNode.ReferenceTable.Add(ReferenceTypeIds.HasProperty, false, _idNode.NodeId); _idNode.ReferenceTable.Add(ReferenceTypeIds.HasProperty, true, _enabledStateNode.NodeId); _commentNode.ReferenceTable.Add(ReferenceTypeIds.HasProperty, true, ObjectTypeIds.ConditionType); } protected override Node GetNode(uint id) { return _nodes.TryGetValue(id, out var node) ? node : base.GetNode(id); } private void AddNode(Node node) { _nodes[(uint)node.NodeId.Identifier] = node; } private readonly Node _baseObjectTypeNode = new() { AccessRestrictions = 0, Description = null, DisplayName = BrowseNames.BaseObjectType, Handle = null, NodeClass = Opc.Ua.NodeClass.ObjectType, NodeId = ObjectTypeIds.BaseObjectType }; private readonly Node _baseEventTypeNode = new() { AccessRestrictions = 0, Description = null, DisplayName = BrowseNames.BaseEventType, Handle = null, NodeClass = Opc.Ua.NodeClass.ObjectType, NodeId = ObjectTypeIds.BaseEventType }; private readonly Node _messageNode = new() { AccessRestrictions = 0, Description = null, DisplayName = BrowseNames.Message, BrowseName = BrowseNames.Message, Handle = null, NodeClass = Opc.Ua.NodeClass.Variable, NodeId = VariableIds.BaseEventType_Message }; private readonly Node _conditionTypeNode = new() { AccessRestrictions = 0, Description = null, DisplayName = BrowseNames.ConditionType, Handle = null, NodeClass = Opc.Ua.NodeClass.ObjectType, NodeId = ObjectTypeIds.ConditionType }; private readonly Node _conditionNameNode = new() { AccessRestrictions = 0, Description = null, DisplayName = BrowseNames.ConditionName, BrowseName = BrowseNames.ConditionName, Handle = null, NodeClass = Opc.Ua.NodeClass.Variable, NodeId = VariableIds.ConditionType_ConditionName }; private readonly Node _commentNode = new() { AccessRestrictions = 0, Description = null, DisplayName = BrowseNames.Comment, BrowseName = BrowseNames.Comment, Handle = null, NodeClass = Opc.Ua.NodeClass.Variable, NodeId = VariableIds.ConditionType_Comment }; private readonly Node _enabledStateNode = new() { AccessRestrictions = 0, Description = null, DisplayName = BrowseNames.EnabledState, BrowseName = BrowseNames.EnabledState, Handle = null, NodeClass = Opc.Ua.NodeClass.Variable, NodeId = VariableIds.ConditionType_EnabledState }; private readonly Node _idNode = new() { AccessRestrictions = 0, Description = null, DisplayName = BrowseNames.Id, BrowseName = BrowseNames.Id, Handle = null, NodeClass = Opc.Ua.NodeClass.Variable, NodeId = VariableIds.ConditionType_EnabledState_Id }; private readonly Dictionary _nodes = []; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Stack/OpcUaApplicationTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Stack { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Autofac; using Furly.Exceptions; using Opc.Ua; using System; using System.Linq; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Threading.Tasks; using Xunit; public class OpcUaApplicationTests { [Fact] public async Task GetApplicationCertificateTest1Async() { await using var bootstrap = Build(); var oldCerts = bootstrap.Resolve(); await CleanAsync(oldCerts, CertificateStoreName.Application); await using var container = Build(); var certs = container.Resolve(); var certificates = await certs.ListCertificatesAsync(CertificateStoreName.Application, true); Assert.Equal(3, certificates.Count); Assert.All(certificates, own => Assert.True(own.HasPrivateKey)); } [Fact] public async Task GetApplicationCertificateTest2Async() { await using var container = Build(); var certs = container.Resolve(); await CleanAsync(certs, CertificateStoreName.Application); var certificates = await certs.ListCertificatesAsync(CertificateStoreName.Application); Assert.Empty(certificates); using var newCert = CreateRSACertificate("test"); var p = Guid.NewGuid().ToString(); await certs.AddCertificateAsync(CertificateStoreName.Application, newCert.Export(X509ContentType.Pfx, p), p); certificates = await certs.ListCertificatesAsync(CertificateStoreName.Application, true); var own = Assert.Single(certificates); Assert.True(own.HasPrivateKey); } [Fact] public async Task GetTrustedCertificatesTest1Async() { await using var container = Build(); var certs = container.Resolve(); await CleanAsync(certs, CertificateStoreName.Trusted); var certificates = await certs.ListCertificatesAsync(CertificateStoreName.Trusted); Assert.Empty(certificates); using var newCert = CreateRSACertificate("test"); var p = Guid.NewGuid().ToString(); await certs.AddCertificateAsync(CertificateStoreName.Trusted, newCert.Export(X509ContentType.Pfx, p), p); certificates = await certs.ListCertificatesAsync(CertificateStoreName.Trusted); var cert = Assert.Single(certificates); Assert.Equal(cert.Thumbprint, newCert.Thumbprint); await certs.RemoveCertificateAsync(CertificateStoreName.Trusted, newCert.Thumbprint); certificates = await certs.ListCertificatesAsync(CertificateStoreName.Trusted); Assert.Empty(certificates); } [Fact] public async Task GetTrustedCertificatesTest2Async() { await using var container = Build(); var certs = container.Resolve(); await CleanAsync(certs, CertificateStoreName.Trusted); var certificates = await certs.ListCertificatesAsync(CertificateStoreName.Trusted); Assert.Empty(certificates); using var newCert = CreateRSACertificate("test"); var p = Guid.NewGuid().ToString(); var pfx = newCert.Export(X509ContentType.Pfx, p); await certs.AddCertificateAsync(CertificateStoreName.Trusted, pfx, p); await certs.AddCertificateAsync(CertificateStoreName.Trusted, pfx, p); await certs.AddCertificateAsync(CertificateStoreName.Trusted, pfx, p); certificates = await certs.ListCertificatesAsync(CertificateStoreName.Trusted); var cert = Assert.Single(certificates); await CleanAsync(certs, CertificateStoreName.Trusted); } [Fact] public async Task GetTrustedCertificatesTest3Async() { await using var container = Build(); var certs = container.Resolve(); await CleanAsync(certs, CertificateStoreName.Trusted); var certificates = await certs.ListCertificatesAsync(CertificateStoreName.Trusted); Assert.Empty(certificates); using var newCert1 = CreateRSACertificate("test1"); using var newCert2 = CreateRSACertificate("test2"); using var newCert3 = CreateRSACertificate("test3"); var p1 = Guid.NewGuid().ToString(); var p2 = Guid.NewGuid().ToString(); var p3 = Guid.NewGuid().ToString(); await certs.AddCertificateAsync(CertificateStoreName.Trusted, newCert1.Export(X509ContentType.Pfx, p1), p1); await certs.AddCertificateAsync(CertificateStoreName.Trusted, newCert2.Export(X509ContentType.Pfx, p2), p2); await certs.AddCertificateAsync(CertificateStoreName.Trusted, newCert3.Export(X509ContentType.Pfx, p3), p3); certificates = await certs.ListCertificatesAsync(CertificateStoreName.Trusted); Assert.Equal(3, certificates.Count); await CleanAsync(certs, CertificateStoreName.Trusted); } [Fact] public async Task GetTrustedCertificatesTest4Async() { await using var container = Build(); var certs = container.Resolve(); await CleanAsync(certs, CertificateStoreName.Trusted); await CleanAsync(certs, CertificateStoreName.Issuer); var certificates = await certs.ListCertificatesAsync(CertificateStoreName.Trusted); Assert.Empty(certificates); certificates = await certs.ListCertificatesAsync(CertificateStoreName.Issuer); Assert.Empty(certificates); using var newCert1 = CreateRSACertificate("test1"); using var newCert2 = CreateRSACertificate("test2"); using var newCert3 = CreateRSACertificate("test3"); var chain = newCert1.RawData.Concat(newCert2.RawData).Concat(newCert3.RawData).ToArray(); await certs.AddCertificateChainAsync(chain); certificates = await certs.ListCertificatesAsync(CertificateStoreName.Trusted); Assert.Single(certificates); certificates = await certs.ListCertificatesAsync(CertificateStoreName.Issuer); Assert.Equal(2, certificates.Count); await CleanAsync(certs, CertificateStoreName.Trusted); await CleanAsync(certs, CertificateStoreName.Issuer); } [Fact] public async Task GetTrustedHttpsCertificatesTestAsync() { await using var container = Build(); var certs = container.Resolve(); await CleanAsync(certs, CertificateStoreName.Https); await CleanAsync(certs, CertificateStoreName.HttpsIssuer); var certificates = await certs.ListCertificatesAsync(CertificateStoreName.Https); Assert.Empty(certificates); certificates = await certs.ListCertificatesAsync(CertificateStoreName.HttpsIssuer); Assert.Empty(certificates); using var newCert1 = CreateRSACertificate("test1"); using var newCert2 = CreateRSACertificate("test2"); using var newCert3 = CreateRSACertificate("test3"); var chain = newCert1.RawData.Concat(newCert2.RawData).Concat(newCert3.RawData).ToArray(); await certs.AddCertificateChainAsync(chain, true); certificates = await certs.ListCertificatesAsync(CertificateStoreName.Https); Assert.Single(certificates); certificates = await certs.ListCertificatesAsync(CertificateStoreName.HttpsIssuer); Assert.Equal(2, certificates.Count); await CleanAsync(certs, CertificateStoreName.Https); await CleanAsync(certs, CertificateStoreName.HttpsIssuer); } [Fact] public async Task ApproveRejectedCertificateTestAsync() { await using var container = Build(); var certs = container.Resolve(); await CleanAsync(certs, CertificateStoreName.Trusted); await CleanAsync(certs, CertificateStoreName.Rejected); var certificates = await certs.ListCertificatesAsync(CertificateStoreName.Trusted); Assert.Empty(certificates); using var rejectedCert = CreateRSACertificate("test1"); var p = Guid.NewGuid().ToString(); await certs.AddCertificateAsync(CertificateStoreName.Rejected, rejectedCert.Export(X509ContentType.Pfx, p), p); certificates = await certs.ListCertificatesAsync(CertificateStoreName.Rejected); Assert.Single(certificates); certificates = await certs.ListCertificatesAsync(CertificateStoreName.Trusted); Assert.Empty(certificates); await certs.ApproveRejectedCertificateAsync(rejectedCert.Thumbprint); certificates = await certs.ListCertificatesAsync(CertificateStoreName.Rejected); Assert.Empty(certificates); certificates = await certs.ListCertificatesAsync(CertificateStoreName.Trusted); var approved = Assert.Single(certificates); Assert.Equal(approved.Thumbprint, rejectedCert.Thumbprint); await CleanAsync(certs, CertificateStoreName.Rejected); await CleanAsync(certs, CertificateStoreName.Trusted); } [Fact] public async Task ApproveRejectedCertificateNotFoundTestAsync() { await using var container = Build(); var certs = container.Resolve(); using var rejectedCert = CreateRSACertificate("test1"); await Assert.ThrowsAsync( async () => await certs.ApproveRejectedCertificateAsync(rejectedCert.Thumbprint)); } [Fact] public async Task RemoveCertificateNotFoundTestAsync() { await using var container = Build(); var certs = container.Resolve(); using var rejectedCert = CreateRSACertificate("test1"); await Assert.ThrowsAsync( async () => await certs.RemoveCertificateAsync( CertificateStoreName.Trusted, rejectedCert.Thumbprint)); } [Fact] public async Task GetUserCertificateTest1Async() { await using var container = Build(); var certs = container.Resolve(); await CleanAsync(certs, CertificateStoreName.User); var certificates = await certs.ListCertificatesAsync(CertificateStoreName.User); Assert.Empty(certificates); using var newCert1 = CreateRSACertificate("user1"); using var newCert2 = CreateRSACertificate("user2"); using var newCert3 = CreateRSACertificate("user3"); var p1 = Guid.NewGuid().ToString(); var p2 = Guid.NewGuid().ToString(); var p3 = Guid.NewGuid().ToString(); await certs.AddCertificateAsync(CertificateStoreName.User, newCert1.Export(X509ContentType.Pfx, p1), p1); await certs.AddCertificateAsync(CertificateStoreName.User, newCert2.Export(X509ContentType.Pfx, p2), p2); await certs.AddCertificateAsync(CertificateStoreName.User, newCert3.Export(X509ContentType.Pfx, p3), p3); certificates = await certs.ListCertificatesAsync(CertificateStoreName.User, true); Assert.Equal(3, certificates.Count); Assert.All(certificates, c => Assert.False(c.HasPrivateKey)); var config = container.Resolve(); var credential = new CredentialModel { Type = CredentialType.X509Certificate, Value = new UserIdentityModel { User = "DC=user2", Password = p2 } }; var identity = await credential.ToUserIdentityAsync(config.Value); Assert.NotNull(identity); Assert.Equal(UserTokenType.Certificate, identity.TokenType); var x509Token = identity.GetIdentityToken() as X509IdentityToken; Assert.NotNull(x509Token); Assert.True(x509Token.Certificate.HasPrivateKey); Assert.Equal(newCert2.Thumbprint, x509Token.Certificate.Thumbprint); } [Fact] public async Task GetUserCertificateTest2Async() { await using var container = Build(); var certs = container.Resolve(); await CleanAsync(certs, CertificateStoreName.User); var certificates = await certs.ListCertificatesAsync(CertificateStoreName.User); Assert.Empty(certificates); using var newCert1 = CreateRSACertificate("user1"); using var newCert2 = CreateRSACertificate("user2"); using var newCert3 = CreateRSACertificate("user3"); var p1 = Guid.NewGuid().ToString(); var p2 = Guid.NewGuid().ToString(); var p3 = Guid.NewGuid().ToString(); await certs.AddCertificateAsync(CertificateStoreName.User, newCert1.Export(X509ContentType.Pfx, p1), p1); await certs.AddCertificateAsync(CertificateStoreName.User, newCert2.Export(X509ContentType.Pfx, p2), p2); await certs.AddCertificateAsync(CertificateStoreName.User, newCert3.Export(X509ContentType.Pfx, p3), p3); certificates = await certs.ListCertificatesAsync(CertificateStoreName.User, true); Assert.Equal(3, certificates.Count); Assert.All(certificates, c => Assert.False(c.HasPrivateKey)); var config = container.Resolve(); var credential = new CredentialModel { Type = CredentialType.X509Certificate, Value = new UserIdentityModel { Thumbprint = newCert3.Thumbprint, Password = p3 } }; var identity = await credential.ToUserIdentityAsync(config.Value); Assert.NotNull(identity); Assert.Equal(UserTokenType.Certificate, identity.TokenType); var x509Token = identity.GetIdentityToken() as X509IdentityToken; Assert.NotNull(x509Token); Assert.True(x509Token.Certificate.HasPrivateKey); Assert.Equal(newCert3.Thumbprint, x509Token.Certificate.Thumbprint); } [Fact] public async Task GetUserCertificateTest3Async() { await using var container = Build(); var certs = container.Resolve(); await CleanAsync(certs, CertificateStoreName.User); var certificates = await certs.ListCertificatesAsync(CertificateStoreName.User); Assert.Empty(certificates); using var newCert1 = CreateRSACertificate("user1"); using var newCert2 = CreateRSACertificate("user2"); using var newCert3 = CreateRSACertificate("user3"); var p1 = Guid.NewGuid().ToString(); var p2 = Guid.NewGuid().ToString(); var p3 = Guid.NewGuid().ToString(); await certs.AddCertificateAsync(CertificateStoreName.User, newCert1.Export(X509ContentType.Pfx, p1), p1); await certs.AddCertificateAsync(CertificateStoreName.User, newCert2.Export(X509ContentType.Pfx, p2), p2); await certs.AddCertificateAsync(CertificateStoreName.User, newCert3.Export(X509ContentType.Pfx, p3), p3); certificates = await certs.ListCertificatesAsync(CertificateStoreName.User, true); Assert.Equal(3, certificates.Count); Assert.All(certificates, c => Assert.False(c.HasPrivateKey)); var config = container.Resolve(); var credential = new CredentialModel { Type = CredentialType.X509Certificate, Value = new UserIdentityModel { Thumbprint = newCert3.Thumbprint, Password = p1 } }; var ex = await Assert.ThrowsAsync( async () => await credential.ToUserIdentityAsync(config.Value)); Assert.Equal(StatusCodes.BadCertificateInvalid, ex.StatusCode); config = container.Resolve(); credential = new CredentialModel { Type = CredentialType.X509Certificate, Value = new UserIdentityModel { Password = p3 } }; ex = await Assert.ThrowsAsync( async () => await credential.ToUserIdentityAsync(config.Value)); Assert.Equal(StatusCodes.BadNotSupported, ex.StatusCode); config = container.Resolve(); credential = new CredentialModel { Type = CredentialType.X509Certificate, Value = new UserIdentityModel { Thumbprint = newCert3.Thumbprint } }; ex = await Assert.ThrowsAsync( async () => await credential.ToUserIdentityAsync(config.Value)); Assert.Equal(StatusCodes.BadCertificateInvalid, ex.StatusCode); } private static async Task CleanAsync(IOpcUaCertificates certs, CertificateStoreName store) { var certificates = await certs.ListCertificatesAsync(store); foreach (var c in certificates) { await certs.RemoveCertificateAsync(store, c.Thumbprint); } } private static X509Certificate2 CreateRSACertificate(string name) { using var rsa = RSA.Create(); var req = new CertificateRequest("DC=" + name, rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pss); req.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.DigitalSignature, false)); return req.CreateSelfSigned(DateTimeOffset.Now, DateTimeOffset.Now.AddHours(5)); } private static IContainer Build() { var containerBuilder = new ContainerBuilder(); containerBuilder.AddLogging(); containerBuilder.AddOpcUaStack(); containerBuilder.AddNewtonsoftJsonSerializer(); return containerBuilder.Build(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Stack/OpcUaMonitoredItemTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Stack { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Azure.IIoT.OpcUa.Publisher.Stack.Services; using Opc.Ua; using DeadbandType = Publisher.Models.DeadbandType; using MonitoringMode = Publisher.Models.MonitoringMode; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Xunit; public class OpcUaMonitoredItemTests : OpcUaMonitoredItemTestsBase { [Fact] public async Task SetDefaultValuesWhenPropertiesAreNullInBaseTemplateAsync() { var template = new DataMonitoredItemModel { StartNodeId = "i=2258", DiscardNew = null }; var monitoredItem = await GetMonitoredItemAsync(template) as OpcUaMonitoredItem.DataChange; Assert.Equal(Attributes.Value, monitoredItem.AttributeId); Assert.Equal(Opc.Ua.MonitoringMode.Reporting, monitoredItem.MonitoringMode); Assert.Equal(1000, monitoredItem.SamplingInterval); Assert.True(monitoredItem.DiscardOldest); Assert.False(monitoredItem.SkipMonitoredItemNotification()); } [Fact] public async Task SetSkipFirstBeforeFirstNotificationProcessedSucceedsTestsAsync() { var template = new DataMonitoredItemModel { StartNodeId = "i=2258", SkipFirst = true }; var monitoredItem = await GetMonitoredItemAsync(template) as OpcUaMonitoredItem.DataChange; Assert.False(monitoredItem.TrySetSkipFirst(true)); Assert.True(monitoredItem.TrySetSkipFirst(false)); Assert.True(monitoredItem.TrySetSkipFirst(true)); Assert.True(monitoredItem.TrySetSkipFirst(false)); Assert.True(monitoredItem.TrySetSkipFirst(true)); Assert.True(monitoredItem.SkipMonitoredItemNotification()); // This is allowed since it does not matter Assert.True(monitoredItem.TrySetSkipFirst(false)); Assert.False(monitoredItem.TrySetSkipFirst(true)); Assert.False(monitoredItem.SkipMonitoredItemNotification()); } [Fact] public async Task SetSkipFirstAfterFirstNotificationProcessedFailsTestsAsync() { var template = new DataMonitoredItemModel { StartNodeId = "i=2258", SkipFirst = true }; var monitoredItem = await GetMonitoredItemAsync(template) as OpcUaMonitoredItem.DataChange; Assert.True(monitoredItem.SkipMonitoredItemNotification()); Assert.False(monitoredItem.TrySetSkipFirst(true)); // This is allowed since it does not matter Assert.True(monitoredItem.TrySetSkipFirst(false)); Assert.False(monitoredItem.TrySetSkipFirst(true)); // This is allowed since it does not matter Assert.True(monitoredItem.TrySetSkipFirst(false)); Assert.False(monitoredItem.SkipMonitoredItemNotification()); } [Fact] public async Task NotsetSkipFirstAfterFirstNotificationProcessedFailsSettingTestsAsync() { var template = new DataMonitoredItemModel { StartNodeId = "i=2258" }; var monitoredItem = await GetMonitoredItemAsync(template) as OpcUaMonitoredItem.DataChange; Assert.False(monitoredItem.SkipMonitoredItemNotification()); Assert.False(monitoredItem.TrySetSkipFirst(true)); Assert.False(monitoredItem.SkipMonitoredItemNotification()); } [Fact] public async Task SetBaseValuesWhenPropertiesAreSetInBaseTemplateAsync() { var template = new DataMonitoredItemModel { DataSetFieldId = "i=2258", DataSetFieldName = "DisplayName", AttributeId = (NodeAttribute)Attributes.Value, IndexRange = "5:20", RelativePath = new[] { "RelativePath1", "RelativePath2" }, MonitoringMode = MonitoringMode.Sampling, StartNodeId = "i=2258", DataSetClassFieldId = Guid.NewGuid(), QueueSize = 10, SkipFirst = true, SamplingInterval = TimeSpan.FromMilliseconds(10000), DiscardNew = true }; var monitoredItem = await GetMonitoredItemAsync(template) as OpcUaMonitoredItem.DataChange; Assert.Equal("DisplayName", monitoredItem.DisplayName); Assert.Equal((uint)NodeAttribute.Value, monitoredItem.AttributeId); Assert.Equal("5:20", monitoredItem.IndexRange); Assert.Equal(Opc.Ua.MonitoringMode.Sampling, monitoredItem.MonitoringMode); Assert.Equal("i=2258", monitoredItem.StartNodeId); Assert.Equal(10u, monitoredItem.QueueSize); Assert.Equal(10000, monitoredItem.SamplingInterval); Assert.False(monitoredItem.DiscardOldest); Assert.Null(monitoredItem.Handle); Assert.True(monitoredItem.SkipMonitoredItemNotification()); } [Fact] public async Task SetDataChangeFilterWhenBaseTemplateIsDataTemplateAsync() { var template = new DataMonitoredItemModel { StartNodeId = "i=2258", DataChangeFilter = new DataChangeFilterModel { DataChangeTrigger = DataChangeTriggerType.StatusValue, DeadbandType = DeadbandType.Percent, DeadbandValue = 10.0 } }; var monitoredItem = await GetMonitoredItemAsync(template); Assert.NotNull(monitoredItem.Filter); Assert.IsType(monitoredItem.Filter); var dataChangeFilter = (DataChangeFilter)monitoredItem.Filter; Assert.Equal(DataChangeTrigger.StatusValue, dataChangeFilter.Trigger); Assert.Equal((uint)Opc.Ua.DeadbandType.Percent, dataChangeFilter.DeadbandType); Assert.Equal(10.0, dataChangeFilter.DeadbandValue); } [Fact] public async Task SetEventFilterWhenBaseTemplateIsEventTemplateAsync() { var template = new EventMonitoredItemModel { StartNodeId = "i=2258", EventFilter = new EventFilterModel { SelectClauses = new List { new() { TypeDefinitionId = "i=2041", BrowsePath = new []{ "EventId" } } }, WhereClause = new ContentFilterModel { Elements = new List { new() { FilterOperator = FilterOperatorType.OfType, FilterOperands = new List { new() { Value = "ns=2;i=235" } } } } } } }; var monitoredItem = await GetMonitoredItemAsync(template); Assert.NotNull(monitoredItem.Filter); Assert.IsType(monitoredItem.Filter); var eventFilter = (EventFilter)monitoredItem.Filter; Assert.NotEmpty(eventFilter.SelectClauses); Assert.Equal(ObjectTypeIds.BaseEventType, eventFilter.SelectClauses[0].TypeDefinitionId); Assert.Equal("EventId", eventFilter.SelectClauses[0].BrowsePath.ElementAtOrDefault(0)); Assert.NotNull(eventFilter.WhereClause); Assert.Single(eventFilter.WhereClause.Elements); Assert.Equal(FilterOperator.OfType, eventFilter.WhereClause.Elements[0].FilterOperator); Assert.Single(eventFilter.WhereClause.Elements[0].FilterOperands); Assert.IsType(eventFilter.WhereClause.Elements[0].FilterOperands[0].Body); var literalOperand = (LiteralOperand)eventFilter.WhereClause.Elements[0].FilterOperands[0].Body; Assert.Equal(new NodeId("ns=2;i=235"), literalOperand.Value.Value); } [Fact] public async Task AddConditionTypeSelectClausesWhenPendingAlarmsIsSetInEventTemplateAsync() { var template = new EventMonitoredItemModel { StartNodeId = "i=2258", EventFilter = new EventFilterModel(), ConditionHandling = new ConditionHandlingOptionsModel { SnapshotInterval = 10, UpdateInterval = 20 } }; var monitoredItem = await GetMonitoredItemAsync(template); Assert.NotNull(monitoredItem.Filter); Assert.IsType(monitoredItem.Filter); var eventFilter = (EventFilter)monitoredItem.Filter; Assert.NotNull(eventFilter.SelectClauses); Assert.Equal(11, eventFilter.SelectClauses.Count); Assert.Equal(Attributes.NodeId, eventFilter.SelectClauses[9].AttributeId); Assert.Equal(ObjectTypeIds.ConditionType, eventFilter.SelectClauses[9].TypeDefinitionId); Assert.Empty(eventFilter.SelectClauses[9].BrowsePath); Assert.Equal(Attributes.Value, eventFilter.SelectClauses[10].AttributeId); Assert.Equal(ObjectTypeIds.ConditionType, eventFilter.SelectClauses[10].TypeDefinitionId); Assert.Equal("Retain", eventFilter.SelectClauses[10].BrowsePath.FirstOrDefault()); } [Fact] public async Task SetupFieldNameWithNamespaceNameWhenNamespaceIndexIsUsedAsync() { var template = new EventMonitoredItemModel { StartNodeId = "i=2258", EventFilter = new EventFilterModel { SelectClauses = new List { new() { TypeDefinitionId = "nsu=http://opcfoundation.org/Quickstarts/SimpleEvents;i=235", BrowsePath = new []{ "2:CycleId" } }, new() { TypeDefinitionId = "nsu=http://opcfoundation.org/Quickstarts/SimpleEvents;i=235", BrowsePath = new []{ "2:CurrentStep" } } }, WhereClause = new ContentFilterModel { Elements = new List { new() { FilterOperator = FilterOperatorType.OfType, FilterOperands = new List { new() { Value = "ns=2;i=235" } } } } } } }; var namespaceTable = new NamespaceTable(new[] { Namespaces.OpcUa, "http://opcfoundation.org/UA/Diagnostics", "http://opcfoundation.org/Quickstarts/SimpleEvents" }); var eventItem = await GetMonitoredItemAsync(template, namespaceTable) as OpcUaMonitoredItem.Event; Assert.Equal(((EventFilter)eventItem.Filter).SelectClauses.Count, eventItem.Fields.Count); Assert.Equal("http://opcfoundation.org/Quickstarts/SimpleEvents#CycleId", eventItem.Fields[0].Name); Assert.Equal("http://opcfoundation.org/Quickstarts/SimpleEvents#CurrentStep", eventItem.Fields[1].Name); } [Fact] public async Task UseDefaultFieldNameWhenNamespaceTableIsEmptyAsync() { var namespaceUris = new NamespaceTable(); namespaceUris.Append("http://test"); namespaceUris.Append("http://opcfoundation.org/Quickstarts/SimpleEvents"); var template = new EventMonitoredItemModel { StartNodeId = "i=2258", EventFilter = new EventFilterModel { SelectClauses = new List { new() { TypeDefinitionId = "nsu=http://opcfoundation.org/Quickstarts/SimpleEvents;i=235", BrowsePath = new []{ "2:CycleId" } }, new() { TypeDefinitionId = "nsu=http://opcfoundation.org/Quickstarts/SimpleEvents;i=235", BrowsePath = new []{ "2:CurrentStep" } } }, WhereClause = new ContentFilterModel { Elements = new List { new() { FilterOperator = FilterOperatorType.OfType, FilterOperands = new List { new() { Value = "ns=2;i=235" } } } } } } }; var eventItem = await GetMonitoredItemAsync(template, namespaceUris) as OpcUaMonitoredItem.Event; Assert.Equal(((EventFilter)eventItem.Filter).SelectClauses.Count, eventItem.Fields.Count); Assert.Equal("http://opcfoundation.org/Quickstarts/SimpleEvents#CycleId", eventItem.Fields[0].Name); Assert.Equal("http://opcfoundation.org/Quickstarts/SimpleEvents#CurrentStep", eventItem.Fields[1].Name); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Stack/OpcUaMonitoredItemTestsBase.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Stack { using Azure.IIoT.OpcUa.Encoders; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Stack.Extensions; using Azure.IIoT.OpcUa.Publisher.Stack.Models; using Azure.IIoT.OpcUa.Publisher.Stack.Services; using Furly.Extensions.Logging; using Furly.Extensions.Serializers.Newtonsoft; using Moq; using Opc.Ua; using Opc.Ua.Client; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; public abstract class OpcUaMonitoredItemTestsBase { protected virtual Mock SetupMockedSession(NamespaceTable namespaceTable = null) { using var mock = Autofac.Extras.Moq.AutoMock.GetLoose(); namespaceTable ??= new NamespaceTable(); var s = new Mock(); s.Setup(x => x.ReadNodeAsync(It.IsAny(), It.IsAny())) .Returns((NodeId x, CancellationToken _) => Task.FromResult(GetNode(x))); s.Setup(x => x.ReadNodesAsync(It.IsAny>(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns((IList nodeIds, NodeClass nodeClass, bool includeReferences, CancellationToken cancellationToken) => Task.FromResult(GetNodes(nodeIds, nodeClass, includeReferences))); s.Setup(x => x.FetchReferencesAsync(It.IsAny(), It.IsAny())) .Returns((NodeId x, CancellationToken _) => Task.FromResult(new ReferenceDescriptionCollection(GetReferences(x)))); var nodeCache = new LruNodeCache(s.Object); var session = mock.Mock(); var messageContext = new ServiceMessageContext { NamespaceUris = namespaceTable }; var codec = new JsonVariantEncoder(messageContext, new NewtonsoftJsonSerializer()); session.SetupGet(x => x.Codec).Returns(codec); session.SetupGet(x => x.LruNodeCache).Returns(nodeCache); session.SetupGet(x => x.MessageContext).Returns(messageContext); return session; } protected virtual IEnumerable GetReferences(NodeId x) { var node = GetNode(x); return node == null ? Array.Empty() : node.ReferenceTable.Select(r => new ReferenceDescription { ReferenceTypeId = new NodeId(r.ReferenceTypeId), IsForward = !r.IsInverse, NodeId = new ExpandedNodeId(r.TargetId) }); } protected virtual IEnumerable GetReferences(uint id) { return Array.Empty(); } protected virtual (IList, IList) GetNodes( IList nodeIds, NodeClass nodeClass, bool includeReferences) { var nodes = new List(); var results = new List(); foreach (var id in nodeIds) { var node = GetNode(id); if (node != null && (nodeClass == NodeClass.Unspecified || node.NodeClass == nodeClass)) { nodes.Add(node); results.Add(ServiceResult.Good); } else { results.Add(new ServiceResult(StatusCodes.BadNodeIdUnknown)); } } return (nodes, results); } protected virtual Node GetNode(NodeId x) { if (x.IdType == IdType.Numeric && x.Identifier is uint id) { return GetNode(id); } return null; } protected virtual Node GetNode(uint id) { return null; } internal async Task GetMonitoredItemAsync(BaseMonitoredItemModel template, NamespaceTable namespaceUris = null) { var session = SetupMockedSession(namespaceUris).Object; var subscriber = new Mock(); var monitoredItemWrapper = OpcUaMonitoredItem.Create(null!, (subscriber.Object, template).YieldReturn(), Log.ConsoleFactory(), TimeProvider.System).Single(); using var subscription = new SimpleSubscription(); monitoredItemWrapper.AddTo(subscription, session, out _); if (monitoredItemWrapper.FinalizeAddTo != null) { await monitoredItemWrapper.FinalizeAddTo(session, default); } return monitoredItemWrapper; } internal sealed class SimpleSubscription : Subscription { public SimpleSubscription() { } public SimpleSubscription(Subscription template, bool copyEventHandlers) : base(template, copyEventHandlers) { } public override Subscription CloneSubscription(bool copyEventHandlers) { throw new NotImplementedException(); } } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Stack/Transport/Extensions/NetworkInformationExTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Stack.Transport { using Azure.IIoT.OpcUa.Publisher.Stack.Transport; using System.Net.NetworkInformation; using Xunit; public class NetworkInformationExTests { [Fact] public void TestCopy() { var addr1 = new PhysicalAddress([0, 1, 2, 3, 4, 5, 6, 7]); var addr2 = new PhysicalAddress([0, 1, 2, 3, 4, 5, 6, 7]); var addr3 = addr1.Copy(); Assert.Equal(addr1, addr2); Assert.Equal(addr1, addr3); Assert.Equal(addr2, addr3); Assert.Equal(addr1.GetHashCode(), addr2.GetHashCode()); Assert.Equal(addr1.GetHashCode(), addr3.GetHashCode()); } [Fact] public void TestNotEqual() { var addr1 = new PhysicalAddress([0, 1, 2, 3, 4, 5, 6, 7]); var addr2 = new PhysicalAddress([1, 1, 2, 3, 4, 5, 6, 7]); var addr3 = new PhysicalAddress([1, 1, 2, 3, 4, 5, 6]); Assert.NotEqual(addr1, addr2); Assert.NotEqual(addr1, addr3); Assert.NotEqual(addr2, addr3); Assert.NotEqual(addr1.GetHashCode(), addr2.GetHashCode()); Assert.NotEqual(addr1.GetHashCode(), addr3.GetHashCode()); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Stack/Transport/Models/AddressRangeTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Stack.Transport.Models { using Azure.IIoT.OpcUa.Publisher.Stack.Transport; using Azure.IIoT.OpcUa.Publisher.Stack.Transport.Models; using System; using System.Collections.Generic; using System.Linq; using System.Net; using Xunit; public class AddressRangeTests { [Fact] public void TestSubnetRange1() { var range = new AddressRange( IPAddress.Parse("10.93.232.185"), 20); Assert.Equal(IPAddress.Parse("10.93.224.0"), (IPv4Address)range.Low); Assert.Equal(IPAddress.Parse("10.93.239.255"), (IPv4Address)range.High); Assert.Equal(4096, range.Count); } [Fact] public void TestSubnetRange2() { var range = new AddressRange( IPAddress.Parse("10.93.232.185"), IPAddress.Parse("255.255.240.0")); Assert.Equal(IPAddress.Parse("10.93.224.0"), (IPv4Address)range.Low); Assert.Equal(IPAddress.Parse("10.93.239.255"), (IPv4Address)range.High); Assert.Equal(4096, range.Count); } [Fact] public void TestSubnetNicLocal() { var nics = NetworkInformationEx.GetAllNetInterfaces(NetworkClass.Wired).ToList(); if (nics.Count == 0) { return; } var nic = nics[0]; var range = new AddressRange(nic, true); Assert.Equal(nic.UnicastAddress, (IPv4Address)range.Low); Assert.Equal(nic.UnicastAddress, (IPv4Address)range.High); Assert.Equal(1, range.Count); } [Fact] public void TestSubnetNic() { var nics = NetworkInformationEx.GetAllNetInterfaces(NetworkClass.Wired).ToList(); if (nics.Count == 0) { return; } var nic = nics[0]; var expected = new AddressRange(nic.UnicastAddress, nic.SubnetMask); var range = new AddressRange(nic); Assert.Equal((IPv4Address)expected.Low, (IPv4Address)range.Low); Assert.Equal((IPv4Address)expected.High, (IPv4Address)range.High); Assert.Equal(expected.Count, range.Count); } [Fact] public void TestSingleAddress() { var range = new AddressRange(IPAddress.Loopback, 32, "local"); var list = new List(); range.FillNextBatch(list, 1000); Assert.Single(list); Assert.Equal(IPAddress.Loopback, (IPv4Address)list.Single()); Assert.Equal(IPAddress.Loopback, (IPv4Address)range.High); Assert.Equal(IPAddress.Loopback, (IPv4Address)range.Low); } [Fact] public void TestSimpleRange() { var range = new AddressRange(0, 255); Assert.Equal(0u, range.Low); Assert.Equal(255u, range.High); Assert.Equal(256, range.Count); Assert.Equal(IPAddress.Any, (IPv4Address)range.Low); } [Fact] public void TestEquality1() { var range1 = new AddressRange(0, 255); var range2 = new AddressRange(0, 255); Assert.Equal(range1, range2); Assert.True(range1 == range2); Assert.False(range1 != range2); } [Fact] public void TestNoneEquality1() { var range1 = new AddressRange(0, 255); var range2 = new AddressRange(1, 255); Assert.NotEqual(range1, range2); Assert.True(range1 != range2); Assert.False(range1 == range2); } [Fact] public void TestEquality2() { var range1 = new AddressRange((IPv4Address)0u, 24); var range2 = new AddressRange(0, 255); Assert.Equal(range1, range2); Assert.True(range1 == range2); Assert.False(range1 != range2); } [Fact] public void TestParsing1() { var success = AddressRange.TryParse("0.0.0.0/24", out var range1); Assert.True(success); var range2 = new AddressRange(0, 255); Assert.Single(range1); Assert.Equal(range2, range1.Single()); Assert.Equal("custom", range1.First().Nic); Assert.Equal("0.0.0.0/24", range1.First().ToString()); } [Fact] public void TestParsing1WithRange() { var success = AddressRange.TryParse("0.0.0.0-0.0.0.255", out var range1); Assert.True(success); var range2 = new AddressRange(0, 255); Assert.Single(range1); Assert.Equal(range2, range1.Single()); Assert.Equal("custom", range1.First().Nic); Assert.Equal("0.0.0.0/24", range1.First().ToString()); } [Fact] public void TestParsing1WithNic() { var success = AddressRange.TryParse("0.0.0.0/24[abc]", out var range1); Assert.True(success); var range2 = new AddressRange(0, 255); Assert.Single(range1); Assert.Equal(range2, range1.Single()); Assert.Equal("abc", range1.First().Nic); Assert.Equal("0.0.0.0/24 [abc]", range1.First().ToString()); } [Fact] public void TestParsing2() { var success = AddressRange.TryParse("0.0.0.0/24,0.0.0.0/24", out var range1); Assert.True(success); var range2 = new AddressRange(0, 255); Assert.Single(range1); Assert.Equal(range2, range1.First()); Assert.Equal("custom", range1.First().Nic); Assert.Equal("0.0.0.0/24", range1.First().ToString()); } [Fact] public void TestParsing2WithNic() { var success = AddressRange.TryParse("0.0.0.0/24[xyz],0.0.0.0/24[abc def ]", out var range1); Assert.True(success); var range2 = new AddressRange(0, 255); Assert.Single(range1); Assert.Equal(range2, range1.First()); Assert.Equal("xyz", range1.First().Nic); } [Fact] public void TestParsing3() { var success = AddressRange.TryParse("0.0.0.0/24;0.0.0.0/24;;;", out var range1); Assert.True(success); var range2 = new AddressRange(0, 255); Assert.Single(range1); Assert.Equal(range2, range1.First()); Assert.Equal("custom", range1.First().Nic); } [Fact] public void TestParsing3b() { var success = AddressRange.TryParse("0.0.0.0/24;0.0.0.0-0.0.0.255;;;", out var range1); Assert.True(success); var range2 = new AddressRange(0, 255); Assert.Single(range1); Assert.Equal(range2, range1.First()); Assert.Equal("custom", range1.First().Nic); Assert.Equal("0.0.0.0/24", range1.First().ToString()); } [Fact] public void TestParsing4() { var success = AddressRange.TryParse("0.0.0.0/24[abc];0.0.0.0/24[abc];;;", out var range1); Assert.True(success); var range2 = new AddressRange(0, 255); Assert.Single(range1); Assert.Equal(range2, range1.First()); Assert.Equal("abc", range1.First().Nic); } [Fact] public void TestParsing5() { var success = AddressRange.TryParse("0.0.0.0/24 [abc];0.0.0.0-0.0.0.255[abc];;;", out var range1); Assert.True(success); var range2 = new AddressRange(0, 255); Assert.Single(range1); Assert.Equal(range2, range1.First()); Assert.Equal("abc", range1.First().Nic); } [Fact] public void TestParsing6() { const string str = "1.1.1.1/24[abc];2.2.2.2/24[cde];3.3.3.3/24 [efg]"; var success = AddressRange.TryParse(str, out var ranges); var range1 = new AddressRange(16843008, 16843263); var range2 = new AddressRange(33686016, 33686271); var range3 = new AddressRange(50529024, 50529279); Assert.Collection(ranges, a => { Assert.Equal(range1, a); Assert.Equal("abc", a.Nic); }, b => { Assert.Equal(range2, b); Assert.Equal("cde", b.Nic); }, c => { Assert.Equal(range3, c); Assert.Equal("efg", c.Nic); }); Assert.Equal("1.1.1.0/24 [abc];2.2.2.0/24 [cde];3.3.3.0/24 [efg]", AddressRange.Format(ranges)); } [Fact] public void TestParsing7() { const string str = "192.168.1.0-192.168.2.9[abc]"; var success = AddressRange.TryParse(str, out var ranges); Assert.True(success); var range1 = new AddressRange(3232235776, 3232236031); var range2 = new AddressRange(3232236032, 3232236039); var range3 = new AddressRange(3232236040, 3232236041); Assert.Collection(ranges, a => { Assert.Equal(range1, a); Assert.Equal("abc", a.Nic); }, b => { Assert.Equal(range2, b); Assert.Equal("abc", b.Nic); }, c => { Assert.Equal(range3, c); Assert.Equal("abc", c.Nic); }); Assert.Equal("192.168.1.0/24 [abc];192.168.2.0/29 [abc];192.168.2.8/31 [abc]", AddressRange.Format(ranges)); } [Fact] public void TestParseFormatExceptions() { Assert.Throws(() => AddressRange.Parse("0.0.0.0/24;x/2;;")); Assert.Throws(() => AddressRange.Parse("0.0.=0/24")); Assert.Throws(() => AddressRange.Parse("0.0.0.0-0..0")); Assert.Throws(() => AddressRange.Parse("0.0.0.0-0.0.")); Assert.Throws(() => AddressRange.Parse("0.0.0.0/16-0.0.0.0/22")); Assert.Throws(() => AddressRange.Parse("0.0.0.0-0.0.0.222/3")); Assert.Throws(() => AddressRange.Parse("0.0.0.0[]")); Assert.Throws(() => AddressRange.Parse("0.0.0.0")); Assert.Throws(() => AddressRange.Parse("0.0.0.0.0/2")); Assert.Throws(() => AddressRange.Parse("0.0.0.0/88")); Assert.Throws(() => AddressRange.Parse("0.0.0.0/88[333]")); Assert.Throws(() => AddressRange.Parse("0..0/88")); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Stack/Transport/Models/IPv4AddressTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Stack.Transport.Models { using Azure.IIoT.OpcUa.Publisher.Stack.Transport.Models; using System; using System.Net; using Xunit; public class IPv4AddressTests { [Fact] public void TestEmptyAddress() { var address = new IPv4Address([0, 0, 0, 0]); uint val = address; long val2 = address; Assert.Equal(0u, val); Assert.Equal(0L, val2); Assert.Equal(address, IPAddress.Any); } [Fact] public void TestIncrementAddress() { var address = new IPv4Address([255, 255, 255, 255]); var any = new IPv4Address([0, 0, 0, 0]); var incremented = address + 1; address++; Assert.Equal(0u, (uint)incremented); Assert.Equal(IPAddress.Any, incremented); Assert.Equal(any, incremented); Assert.Equal(0u, (uint)address); Assert.Equal(IPAddress.Any, address); Assert.Equal(any, address); } [Fact] public void TestDecrementAddress() { var address = new IPv4Address([0, 0, 0, 0]); var bcast = new IPv4Address([255, 255, 255, 255]); var decremented = address - 1; address--; Assert.Equal((uint)bcast, (uint)decremented); Assert.Equal(IPAddress.Broadcast, decremented); Assert.Equal(bcast, decremented); Assert.Equal(-1, (int)decremented); Assert.Equal((uint)bcast, (uint)address); Assert.Equal(bcast, address); Assert.Equal(IPAddress.Broadcast, address); Assert.Equal(-1, (int)address); } [Fact] public void TestSubtractAddress() { var bcast = new IPv4Address([255, 255, 255, 255]); var any = new IPv4Address([0, 0, 0, 0]); var subtracted = bcast - bcast; Assert.Equal(0u, subtracted); Assert.Equal(IPAddress.Any, (IPv4Address)subtracted); Assert.Equal(any, (IPv4Address)subtracted); } [Fact] public void ThrowForSize() { Assert.Throws(() => new IPv4Address([])); Assert.Throws(() => new IPv4Address([0])); Assert.Throws(() => new IPv4Address([0, 1, 1, 2, 1])); Assert.Throws(() => new IPv4Address([0, 2, 4])); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Stack/Transport/Models/PortRangeTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Stack.Transport.Models { using Azure.IIoT.OpcUa.Publisher.Stack.Transport.Models; using System; using System.Linq; using Xunit; public class PortRangeTests { [Fact] public void TestSimpleRange() { var range1 = new PortRange(0, 100); var range2 = new PortRange(100, 0); Assert.Equal(101, range1.Count); Assert.Equal(range1, range2); Assert.False(range1 != range2); Assert.True(range1 == range2); Assert.True(range1.Overlaps(range2)); Assert.True(range1.Contains(0)); Assert.True(range1.Contains(100)); Assert.True(range1.Contains(6)); } [Fact] public void TestNoneEquality1() { var range1 = new PortRange(0, 4); var range2 = new PortRange(1, 4); Assert.NotEqual(range1, range2); Assert.True(range1 != range2); Assert.False(range1 == range2); Assert.True(range1.Overlaps(range2)); } [Fact] public void TestNoneEquality2() { var range1 = new PortRange(0, 4); var range2 = new PortRange(7, 9); Assert.NotEqual(range1, range2); Assert.True(range1 != range2); Assert.False(range1 == range2); Assert.False(range1.Overlaps(range2)); } [Fact] public void TestParsing1() { var success = PortRange.TryParse("0-100", out var range1); var range2 = new PortRange(0, 100); Assert.True(success); Assert.Single(range1); Assert.Equal(range2, range1.Single()); Assert.Equal("0-100", PortRange.Format(range1)); } [Fact] public void TestParsing2() { var success = PortRange.TryParse("0-100;144", out var range1); var range2 = new PortRange(0, 100); var range3 = new PortRange(144); Assert.True(success); Assert.Equal(range2, range1.First()); Assert.Equal(range3, range1.Skip(1).First()); Assert.Equal(2, range1.Count()); Assert.Equal("0-100;144", PortRange.Format(range1)); } [Fact] public void TestParsing2b() { var success = PortRange.TryParse("0-100;44", out var range1); var range2 = new PortRange(0, 100); Assert.True(success); Assert.Equal(range2, range1.First()); Assert.Single(range1); Assert.Equal("0-100", PortRange.Format(range1)); } [Fact] public void TestParsing3() { var success = PortRange.TryParse("0,3,6,,,,", out var range1); Assert.True(success); Assert.Equal(new PortRange(0), range1.First()); Assert.Equal(new PortRange(3), range1.Skip(1).First()); Assert.Equal(new PortRange(6), range1.Skip(2).First()); Assert.Equal(3, range1.Count()); Assert.Equal("0;3;6", PortRange.Format(range1)); } [Fact] public void TestParsing3b() { var success = PortRange.TryParse("0-1,3-4,6-9,,,,", out var range1); Assert.True(success); Assert.Equal(new PortRange(0, 1), range1.First()); Assert.Equal(new PortRange(3, 4), range1.Skip(1).First()); Assert.Equal(new PortRange(6, 9), range1.Skip(2).First()); Assert.Equal(3, range1.Count()); Assert.Equal("0-1;3-4;6-9", PortRange.Format(range1)); } [Fact] public void TestParsing3c() { var success = PortRange.TryParse("0-1;3-4;6-*", out var range1); Assert.True(success); Assert.Equal(new PortRange(0, 1), range1.First()); Assert.Equal(new PortRange(3, 4), range1.Skip(1).First()); Assert.Equal(new PortRange(6, 65536), range1.Skip(2).First()); Assert.Equal(3, range1.Count()); Assert.Equal("0-1;3-4;6-*", PortRange.Format(range1)); } [Fact] public void TestParsing3d() { var success = PortRange.TryParse("0-1,1-2,2-3,,,,", out var range1); Assert.True(success); Assert.Single(range1); Assert.Equal(new PortRange(0, 3), range1.First()); Assert.Equal("0-3", PortRange.Format(range1)); } [Fact] public void TestParsing4() { var success = PortRange.TryParse(",,,,", out var range1); Assert.True(success); Assert.Empty(range1); } [Fact] public void TestParsing5() { var success = PortRange.TryParse("*", out var range1); Assert.True(success); Assert.Single(range1); Assert.Equal(new PortRange(0, 65536), range1.Single()); Assert.Equal("*", range1.Single().ToString()); } [Fact] public void TestParsing6() { var success = PortRange.TryParse("100-*", out var range1); Assert.True(success); Assert.Single(range1); Assert.Equal(new PortRange(100, 65536), range1.Single()); Assert.Equal("100-*", range1.Single().ToString()); } [Fact] public void TestParsing7() { var success = PortRange.TryParse("*-100", out var range1); Assert.True(success); Assert.Single(range1); Assert.Equal(new PortRange(0, 100), range1.Single()); Assert.Equal("0-100", range1.Single().ToString()); } [Fact] public void TestParseFormatExceptions() { Assert.Throws(() => PortRange.Parse("0.0.0.0/24;x/2;;")); Assert.Throws(() => PortRange.Parse("abf,d")); Assert.Throws(() => PortRange.Parse("0-1-2")); Assert.Throws(() => PortRange.Parse("0,1-2,f,")); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Storage/PublishedNodesJobConverterTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Storage { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Storage; using Furly.Azure.IoT.Edge.Services; using Furly.Extensions.Logging; using Furly.Extensions.Serializers.Newtonsoft; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Options; using Moq; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Xunit; /// /// The referenced schema file across these test is a linked asset in the /// project file set to copy to the output build directory so that it can /// be easily referenced here. /// public class PublishedNodesJobConverterTests { [Fact] public void PnPlcEmptyTest() { const string pn = @" [ ] "; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var writerGroups = converter.Read(pn); // No writerGroups Assert.Empty(writerGroups); } [Fact] public void PnPlcNullNodesTest() { const string pn = """ [ { "DataSetWriterId": "testid", "EndpointUrl": "opc.tcp://localhost:50000", "OpcAuthenticationMode": "usernamePassword", "OpcAuthenticationUsername": "OpcAuthenticationUsername", "OpcAuthenticationPassword": "OpcAuthenticationPassword" } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions(), null); var entries = converter.Read(pn); var entry = Assert.Single(entries); Assert.Equal("OpcAuthenticationPassword", entry.OpcAuthenticationPassword); Assert.Equal("OpcAuthenticationUsername", entry.OpcAuthenticationUsername); Assert.Null(entry.EncryptedAuthUsername); Assert.Null(entry.EncryptedAuthPassword); Assert.Equal(OpcAuthenticationMode.UsernamePassword, entry.OpcAuthenticationMode); Assert.Null(entry.OpcNodes); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); var group = Assert.Single(writerGroups); var writer = Assert.Single(group.DataSetWriters); Assert.NotNull(writer.DataSet?.DataSetSource); Assert.NotNull(writer.DataSet.DataSetSource.PublishedVariables?.PublishedData); Assert.Empty(writer.DataSet.DataSetSource.PublishedVariables.PublishedData); Assert.NotNull(writer.DataSet.DataSetSource.PublishedEvents?.PublishedData); Assert.Empty(writer.DataSet.DataSetSource.PublishedEvents.PublishedData); var credential = writer.DataSet.DataSetSource.Connection?.User; Assert.NotNull(credential); Assert.Equal(CredentialType.UserName, credential.Type); Assert.Equal("OpcAuthenticationPassword", credential.Value.Password); Assert.Equal("OpcAuthenticationUsername", credential.Value.User); entries = converter.ToPublishedNodes(3, DateTimeOffset.UtcNow, writerGroups); entry = Assert.Single(entries); Assert.Equal("OpcAuthenticationPassword", entry.OpcAuthenticationPassword); Assert.Equal("OpcAuthenticationUsername", entry.OpcAuthenticationUsername); Assert.Null(entry.EncryptedAuthUsername); Assert.Null(entry.EncryptedAuthPassword); Assert.Equal(OpcAuthenticationMode.UsernamePassword, entry.OpcAuthenticationMode); Assert.Empty(entry.OpcNodes); } [Fact] public void PnPlcNoNodesTest() { const string pn = """ [ { "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions(), null); var entries = converter.Read(pn); var entry = Assert.Single(entries); Assert.Empty(entry.OpcNodes); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); var group = Assert.Single(writerGroups); var writer = Assert.Single(group.DataSetWriters); Assert.NotNull(writer.DataSet?.DataSetSource); Assert.NotNull(writer.DataSet.DataSetSource.PublishedVariables?.PublishedData); Assert.Empty(writer.DataSet.DataSetSource.PublishedVariables.PublishedData); Assert.NotNull(writer.DataSet.DataSetSource.PublishedEvents?.PublishedData); Assert.Empty(writer.DataSet.DataSetSource.PublishedEvents.PublishedData); entries = converter.ToPublishedNodes(3, DateTimeOffset.UtcNow, writerGroups); entry = Assert.Single(entries); Assert.Empty(entry.OpcNodes); } [Theory] [InlineData(false, false)] [InlineData(true, false)] [InlineData(true, true)] public void PnPlcPlainTextUserNamePasswordTest(bool withCryptoProvider, bool providerThrows) { const string pn = """ [ { "DataSetWriterId": "testid", "EndpointUrl": "opc.tcp://localhost:50000", "OpcAuthenticationMode": "usernamePassword", "OpcAuthenticationUsername": "OpcAuthenticationUsername", "OpcAuthenticationPassword": "OpcAuthenticationPassword", "OpcNodes": [ { "Id": "i=2258", "HeartbeatInterval": 2 } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions(), cryptoProvider: withCryptoProvider ? providerThrows ? CreateThrowProvider() : CreateMockProvider() : null); var entries = converter.Read(pn); var entry = Assert.Single(entries); Assert.Equal("OpcAuthenticationPassword", entry.OpcAuthenticationPassword); Assert.Equal("OpcAuthenticationUsername", entry.OpcAuthenticationUsername); Assert.Null(entry.EncryptedAuthUsername); Assert.Null(entry.EncryptedAuthPassword); Assert.Equal(OpcAuthenticationMode.UsernamePassword, entry.OpcAuthenticationMode); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); var group = Assert.Single(writerGroups); var credential = Assert.Single(group.DataSetWriters).DataSet?.DataSetSource?.Connection?.User; Assert.NotNull(credential); Assert.Equal(CredentialType.UserName, credential.Type); Assert.Equal("OpcAuthenticationPassword", credential.Value.Password); Assert.Equal("OpcAuthenticationUsername", credential.Value.User); entries = converter.ToPublishedNodes(3, DateTimeOffset.UtcNow, writerGroups); entry = Assert.Single(entries); Assert.Equal("OpcAuthenticationPassword", entry.OpcAuthenticationPassword); Assert.Equal("OpcAuthenticationUsername", entry.OpcAuthenticationUsername); Assert.Null(entry.EncryptedAuthUsername); Assert.Null(entry.EncryptedAuthPassword); Assert.Equal(OpcAuthenticationMode.UsernamePassword, entry.OpcAuthenticationMode); } [Fact] public void PnPlcPlainTextUserNamePasswordWithCryptoProviderForceEncryptionTest() { const string pn = """ [ { "DataSetWriterId": "testid", "EndpointUrl": "opc.tcp://localhost:50000", "OpcAuthenticationMode": "usernamePassword", "OpcAuthenticationUsername": "DecryptedAuthUsername", "OpcAuthenticationPassword": "DecryptedAuthPassword", "OpcNodes": [ { "Id": "i=2258", "HeartbeatInterval": 2 } ] } ] """; var logger = Log.Console(); var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.ForceCredentialEncryption = true; var converter = new PublishedNodesConverter(logger, _serializer, options, CreateMockProvider()); var entries = converter.Read(pn); var entry = Assert.Single(entries); Assert.Equal("DecryptedAuthPassword", entry.OpcAuthenticationPassword); Assert.Equal("DecryptedAuthUsername", entry.OpcAuthenticationUsername); Assert.Null(entry.EncryptedAuthUsername); Assert.Null(entry.EncryptedAuthPassword); Assert.Equal(OpcAuthenticationMode.UsernamePassword, entry.OpcAuthenticationMode); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); var group = Assert.Single(writerGroups); var credential = Assert.Single(group.DataSetWriters).DataSet?.DataSetSource?.Connection?.User; Assert.NotNull(credential); Assert.Equal(CredentialType.UserName, credential.Type); Assert.Equal("DecryptedAuthPassword", credential.Value.Password); Assert.Equal("DecryptedAuthUsername", credential.Value.User); entries = converter.ToPublishedNodes(3, DateTimeOffset.UtcNow, writerGroups); entry = Assert.Single(entries); var encryptedAuthUsername = Convert.ToBase64String(Encoding.UTF8.GetBytes("EncryptedAuthUsername")); var encryptedAuthPassword = Convert.ToBase64String(Encoding.UTF8.GetBytes("EncryptedAuthPassword")); Assert.Equal(encryptedAuthPassword, entry.EncryptedAuthPassword); Assert.Equal(encryptedAuthUsername, entry.EncryptedAuthUsername); Assert.Null(entry.OpcAuthenticationUsername); Assert.Null(entry.OpcAuthenticationPassword); Assert.Equal(OpcAuthenticationMode.UsernamePassword, entry.OpcAuthenticationMode); } [Fact] public void PnPlcEncryptedUserNamePasswordWithoutCryptoProviderTest() { const string pn = """ [ { "DataSetWriterId": "testid", "EndpointUrl": "opc.tcp://localhost:50000", "OpcAuthenticationMode": "usernamePassword", "EncryptedAuthUsername": "EncryptedAuthUsername", "EncryptedAuthPassword": "EncryptedAuthPassword", "OpcNodes": [ { "Id": "i=2258", "HeartbeatInterval": 2 } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var entry = Assert.Single(entries); Assert.Null(entry.OpcAuthenticationPassword); Assert.Null(entry.OpcAuthenticationUsername); Assert.Equal("EncryptedAuthUsername", entry.EncryptedAuthUsername); Assert.Equal("EncryptedAuthPassword", entry.EncryptedAuthPassword); Assert.Equal(OpcAuthenticationMode.UsernamePassword, entry.OpcAuthenticationMode); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); var group = Assert.Single(writerGroups); var credential = Assert.Single(group.DataSetWriters).DataSet?.DataSetSource?.Connection?.User; Assert.NotNull(credential); Assert.Equal(CredentialType.None, credential.Type); Assert.Null(credential.Value); entries = converter.ToPublishedNodes(3, DateTimeOffset.UtcNow, writerGroups); entry = Assert.Single(entries); Assert.Null(entry.OpcAuthenticationPassword); Assert.Null(entry.OpcAuthenticationUsername); Assert.Null(entry.EncryptedAuthUsername); Assert.Null(entry.EncryptedAuthPassword); Assert.Equal(OpcAuthenticationMode.Anonymous, entry.OpcAuthenticationMode); } [Fact] public void PnPlcEncryptedUserNamePasswordWithThrowingCryptoProviderTest() { const string pn = """ [ { "DataSetWriterId": "testid", "EndpointUrl": "opc.tcp://localhost:50000", "OpcAuthenticationMode": "usernamePassword", "EncryptedAuthUsername": "EncryptedAuthUsername", "EncryptedAuthPassword": "EncryptedAuthPassword", "OpcNodes": [ { "Id": "i=2258", "HeartbeatInterval": 2 } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions(), cryptoProvider: CreateThrowProvider()); var entries = converter.Read(pn); var entry = Assert.Single(entries); Assert.Null(entry.OpcAuthenticationPassword); Assert.Null(entry.OpcAuthenticationUsername); Assert.Equal("EncryptedAuthUsername", entry.EncryptedAuthUsername); Assert.Equal("EncryptedAuthPassword", entry.EncryptedAuthPassword); Assert.Equal(OpcAuthenticationMode.UsernamePassword, entry.OpcAuthenticationMode); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); var group = Assert.Single(writerGroups); var credential = Assert.Single(group.DataSetWriters).DataSet?.DataSetSource?.Connection?.User; Assert.NotNull(credential); Assert.Equal(CredentialType.None, credential.Type); Assert.Null(credential.Value); entries = converter.ToPublishedNodes(3, DateTimeOffset.UtcNow, writerGroups); entry = Assert.Single(entries); Assert.Null(entry.OpcAuthenticationPassword); Assert.Null(entry.OpcAuthenticationUsername); Assert.Null(entry.EncryptedAuthUsername); Assert.Null(entry.EncryptedAuthPassword); Assert.Equal(OpcAuthenticationMode.Anonymous, entry.OpcAuthenticationMode); } [Fact] public void PnPlcEncryptedUserNamePasswordWithCryptoProviderTest() { var encryptedAuthUsername = Convert.ToBase64String(Encoding.UTF8.GetBytes("EncryptedAuthUsername")); var encryptedAuthPassword = Convert.ToBase64String(Encoding.UTF8.GetBytes("EncryptedAuthPassword")); var pn = $$""" [ { "DataSetWriterId": "testid", "EndpointUrl": "opc.tcp://localhost:50000", "OpcAuthenticationMode": "usernamePassword", "EncryptedAuthUsername": "{{encryptedAuthUsername}}", "EncryptedAuthPassword": "{{encryptedAuthPassword}}", "OpcNodes": [ { "Id": "i=2258", "HeartbeatInterval": 2 } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions(), cryptoProvider: CreateMockProvider()); var entries = converter.Read(pn); var entry = Assert.Single(entries); Assert.Null(entry.OpcAuthenticationPassword); Assert.Null(entry.OpcAuthenticationUsername); Assert.Equal(encryptedAuthUsername, encryptedAuthUsername); Assert.Equal(encryptedAuthPassword, entry.EncryptedAuthPassword); Assert.Equal(OpcAuthenticationMode.UsernamePassword, entry.OpcAuthenticationMode); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); var group = Assert.Single(writerGroups); var credential = Assert.Single(group.DataSetWriters).DataSet?.DataSetSource?.Connection?.User; Assert.NotNull(credential); Assert.Equal(CredentialType.UserName, credential.Type); Assert.Equal("DecryptedAuthPassword", credential.Value.Password); Assert.Equal("DecryptedAuthUsername", credential.Value.User); // Now we should have converted back to plain text entries = converter.ToPublishedNodes(3, DateTimeOffset.UtcNow, writerGroups); entry = Assert.Single(entries); Assert.Equal("DecryptedAuthPassword", entry.OpcAuthenticationPassword); Assert.Equal("DecryptedAuthUsername", entry.OpcAuthenticationUsername); Assert.Null(entry.EncryptedAuthUsername); Assert.Null(entry.EncryptedAuthPassword); Assert.Equal(OpcAuthenticationMode.UsernamePassword, entry.OpcAuthenticationMode); } [Fact] public void PnPlcEncryptedUserNamePasswordWithCryptoProviderAndForceEncryptionTest() { var encryptedAuthUsername = Convert.ToBase64String(Encoding.UTF8.GetBytes("EncryptedAuthUsername")); var encryptedAuthPassword = Convert.ToBase64String(Encoding.UTF8.GetBytes("EncryptedAuthPassword")); var pn = $$""" [ { "DataSetWriterId": "testid", "EndpointUrl": "opc.tcp://localhost:50000", "OpcAuthenticationMode": "usernamePassword", "EncryptedAuthUsername": "{{encryptedAuthUsername}}", "EncryptedAuthPassword": "{{encryptedAuthPassword}}", "OpcNodes": [ { "Id": "i=2258", "HeartbeatInterval": 2 } ] } ] """; var logger = Log.Console(); var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.ForceCredentialEncryption = true; var converter = new PublishedNodesConverter(logger, _serializer, options, CreateMockProvider()); var entries = converter.Read(pn); var entry = Assert.Single(entries); Assert.Null(entry.OpcAuthenticationPassword); Assert.Null(entry.OpcAuthenticationUsername); Assert.Equal(encryptedAuthUsername, encryptedAuthUsername); Assert.Equal(encryptedAuthPassword, entry.EncryptedAuthPassword); Assert.Equal(OpcAuthenticationMode.UsernamePassword, entry.OpcAuthenticationMode); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); var group = Assert.Single(writerGroups); var credential = Assert.Single(group.DataSetWriters).DataSet?.DataSetSource?.Connection?.User; Assert.NotNull(credential); Assert.Equal(CredentialType.UserName, credential.Type); Assert.Equal("DecryptedAuthPassword", credential.Value.Password); Assert.Equal("DecryptedAuthUsername", credential.Value.User); // Now we should have converted back to encrypted entries = converter.ToPublishedNodes(3, DateTimeOffset.UtcNow, writerGroups); entry = Assert.Single(entries); Assert.Null(entry.OpcAuthenticationPassword); Assert.Null(entry.OpcAuthenticationUsername); Assert.Equal(encryptedAuthUsername, entry.EncryptedAuthUsername); Assert.Equal(encryptedAuthPassword, entry.EncryptedAuthPassword); Assert.Equal(OpcAuthenticationMode.UsernamePassword, entry.OpcAuthenticationMode); } [Fact] public void PnPlcEncryptedUserNamePasswordWithoutCryptoProviderAndForceEncryptionTest() { var encryptedAuthUsername = Convert.ToBase64String(Encoding.UTF8.GetBytes("EncryptedAuthUsername")); var encryptedAuthPassword = Convert.ToBase64String(Encoding.UTF8.GetBytes("EncryptedAuthPassword")); var pn = $$""" [ { "DataSetWriterId": "testid", "EndpointUrl": "opc.tcp://localhost:50000", "OpcAuthenticationMode": "usernamePassword", "EncryptedAuthUsername": "{{encryptedAuthUsername}}", "EncryptedAuthPassword": "{{encryptedAuthPassword}}", "OpcNodes": [ { "Id": "i=2258", "HeartbeatInterval": 2 } ] } ] """; var failFastCalled = false; Publisher.Runtime.FailFast = (_, _) => failFastCalled = true; var logger = Log.Console(); var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.ForceCredentialEncryption = true; var converter = new PublishedNodesConverter(logger, _serializer, options); var entries = converter.Read(pn); var entry = Assert.Single(entries); Assert.Null(entry.OpcAuthenticationPassword); Assert.Null(entry.OpcAuthenticationUsername); Assert.Equal(encryptedAuthUsername, encryptedAuthUsername); Assert.Equal(encryptedAuthPassword, entry.EncryptedAuthPassword); Assert.Equal(OpcAuthenticationMode.UsernamePassword, entry.OpcAuthenticationMode); var writerGroups = converter.ToWriterGroups(entries).ToList(); Assert.True(failFastCalled); // Process exited failFastCalled = false; Assert.NotEmpty(writerGroups); var group = Assert.Single(writerGroups); var credential = Assert.Single(group.DataSetWriters).DataSet?.DataSetSource?.Connection?.User; Assert.NotNull(credential); Assert.Equal(CredentialType.None, credential.Type); Assert.Null(credential.Value); // Fake credential credential.Value = new UserIdentityModel { User = "user", Password = "password" }; credential.Type = CredentialType.UserName; entries = converter.ToPublishedNodes(3, DateTimeOffset.UtcNow, writerGroups).ToList(); Assert.True(failFastCalled); // Process exited entry = Assert.Single(entries); Assert.Equal("password", entry.OpcAuthenticationPassword); Assert.Equal("user", entry.OpcAuthenticationUsername); Assert.Null(entry.EncryptedAuthPassword); Assert.Null(entry.EncryptedAuthUsername); Assert.Equal(OpcAuthenticationMode.UsernamePassword, entry.OpcAuthenticationMode); } [Fact] public void PnPlcEncryptedUserNamePasswordWithoutThrowingCryptoProviderAndForceEncryptionTest() { var encryptedAuthUsername = Convert.ToBase64String(Encoding.UTF8.GetBytes("EncryptedAuthUsername")); var encryptedAuthPassword = Convert.ToBase64String(Encoding.UTF8.GetBytes("EncryptedAuthPassword")); var pn = $$""" [ { "DataSetWriterId": "testid", "EndpointUrl": "opc.tcp://localhost:50000", "OpcAuthenticationMode": "usernamePassword", "EncryptedAuthUsername": "{{encryptedAuthUsername}}", "EncryptedAuthPassword": "{{encryptedAuthPassword}}", "OpcNodes": [ { "Id": "i=2258", "HeartbeatInterval": 2 } ] } ] """; var failFastCalled = false; Publisher.Runtime.FailFast = (_, _) => failFastCalled = true; var logger = Log.Console(); var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.ForceCredentialEncryption = true; var converter = new PublishedNodesConverter(logger, _serializer, options, CreateThrowProvider()); var entries = converter.Read(pn); var entry = Assert.Single(entries); Assert.Null(entry.OpcAuthenticationPassword); Assert.Null(entry.OpcAuthenticationUsername); Assert.Equal(encryptedAuthUsername, encryptedAuthUsername); Assert.Equal(encryptedAuthPassword, entry.EncryptedAuthPassword); Assert.Equal(OpcAuthenticationMode.UsernamePassword, entry.OpcAuthenticationMode); var writerGroups = converter.ToWriterGroups(entries).ToList(); Assert.True(failFastCalled); // Process exited failFastCalled = false; Assert.NotEmpty(writerGroups); var group = Assert.Single(writerGroups); var credential = Assert.Single(group.DataSetWriters).DataSet?.DataSetSource?.Connection?.User; Assert.NotNull(credential); Assert.Equal(CredentialType.None, credential.Type); Assert.Null(credential.Value); // Now we should have converted back to encrypted // Fake credential credential.Value = new UserIdentityModel { User = "user", Password = "password" }; credential.Type = CredentialType.UserName; entries = converter.ToPublishedNodes(3, DateTimeOffset.UtcNow, writerGroups).ToList(); Assert.True(failFastCalled); // Process exited entry = Assert.Single(entries); Assert.Equal("password", entry.OpcAuthenticationPassword); Assert.Equal("user", entry.OpcAuthenticationUsername); Assert.Null(entry.EncryptedAuthPassword); Assert.Null(entry.EncryptedAuthUsername); Assert.Equal(OpcAuthenticationMode.UsernamePassword, entry.OpcAuthenticationMode); } [Fact] public void PnPlcPubSubDataSetWriterIdTest() { const string pn = """ [ { "DataSetWriterId": "testid", "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "HeartbeatInterval": 2 } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries).ToList(); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Equal("testid", writerGroups .Single().DataSetWriters .Single().DataSetWriterName); Assert.Equal("5256a3e80f028d78c673bac7866a09b3b3bb69fa_0", writerGroups .Single().DataSetWriters .Single().Id); } [Fact] public void PnPlcPubSubDataSetWriterIdIsNullTest() { const string pn = """ [ { "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "HeartbeatInterval": 2 } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries).ToList(); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Equal("39d40f4aae5f07696bc0737f6ba45a4d4bd63d79_0", writerGroups .Single().DataSetWriters .Single().Id); Assert.Null(writerGroups .Single().DataSetWriters .Single().DataSetWriterName); } [Fact] public void PnPlcPubSubDataSetWriterGroupTest() { const string pn = """ [ { "DataSetWriterGroup": "testgroup", "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "HeartbeatInterval": 2 } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries).ToList(); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Equal("testgroup", writerGroups .Single().Name); Assert.Equal("8b7a6decc0651d269ea794c7e699bfcf77a97c31", writerGroups .Single().Id); Assert.Null(writerGroups // Will be set later based on configuration. .Single().DataSetWriters .Single().DataSet.DataSetSource.Connection.Group); } [Fact] public void PnPlcPubSubDataSetFieldId1Test() { const string pn = """ [ { "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "DataSetFieldId": "testfieldid1" } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Equal("testfieldid1", writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.PublishedVariables.PublishedData.Single().Id); } [Fact] public void PnPlcPubSubDataSetFieldId2Test() { const string pn = """ [ { "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "DataSetFieldId": "testfieldid1" }, { "Id": "i=2259", "DataSetFieldId": "testfieldid2" } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries).ToList(); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Equal(2, writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.PublishedVariables.PublishedData.Count); Assert.Equal("testfieldid1", writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.PublishedVariables.PublishedData[0].Id); Assert.Equal("testfieldid2", writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.PublishedVariables.PublishedData[writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.PublishedVariables.PublishedData.Count - 1].Id); } [Fact] public void PnPlcPubSubDataSetFieldIdDuplicateTest() { const string pn = """ [ { "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "DataSetFieldId": "testfieldid" }, { "Id": "i=2259", "DataSetFieldId": "testfieldid" } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries).ToList(); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Equal(2, writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.PublishedVariables.PublishedData.Count); Assert.Equal("testfieldid", writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.PublishedVariables.PublishedData[0].Id); Assert.Equal("testfieldid", writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.PublishedVariables.PublishedData[writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.PublishedVariables.PublishedData.Count - 1].Id); } [Fact] public void PnPlcPubSubDisplayNameDuplicateTest() { const string pn = """ [ { "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "DisplayName": "testdisplayname" }, { "Id": "i=2259", "DisplayName": "testdisplayname" } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries).ToList(); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Equal(2, writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.PublishedVariables.PublishedData.Count); Assert.Equal("testdisplayname", writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.PublishedVariables.PublishedData[0].PublishedVariableDisplayName); Assert.Equal("testdisplayname", writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.PublishedVariables.PublishedData[writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.PublishedVariables.PublishedData.Count - 1].PublishedVariableDisplayName); } [Fact] public void PnPlcPubSubFullDuplicateTest() { const string pn = """ [ { "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "DisplayName": "testdisplayname", "DataSetFieldId": "testfieldid" }, { "Id": "i=2259", "DisplayName": "testdisplayname", "DataSetFieldId": "testfieldid" } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries).ToList(); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Equal(2, writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.PublishedVariables.PublishedData.Count); Assert.Equal("testfieldid", writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.PublishedVariables.PublishedData[0].Id); Assert.Equal("testfieldid", writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.PublishedVariables.PublishedData[writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.PublishedVariables.PublishedData.Count - 1].Id); } [Fact] public void PnPlcPubSubFullTest1() { const string pn = """ [ { "DataSetWriterGroup": "testgroup", "DataSetWriterId": "testwriterid", "DataSetPublishingInterval": 1000, "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "DataSetFieldId": "testfieldid1", "OpcPublishingInterval": 2000 } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries).ToList(); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Single(writerGroups .Single().DataSetWriters[0].DataSet.DataSetSource.PublishedVariables.PublishedData); Assert.Equal("testfieldid1", writerGroups .Single().DataSetWriters[0].DataSet.DataSetSource.PublishedVariables.PublishedData[0].Id); Assert.Equal("i=2258", writerGroups .Single().DataSetWriters[0].DataSet.DataSetSource.PublishedVariables.PublishedData[0].PublishedVariableNodeId); Assert.Equal("testgroup", writerGroups .Single().Name); Assert.Equal("8b7a6decc0651d269ea794c7e699bfcf77a97c31", writerGroups .Single().Id); Assert.Null(writerGroups // Will be set later based on configuration. .Single().DataSetWriters[0].DataSet.DataSetSource.Connection.Group); Assert.Equal("testwriterid", writerGroups .Single().DataSetWriters[0].DataSetWriterName); Assert.Equal(2000, writerGroups .Single().DataSetWriters[0].DataSet.DataSetSource.SubscriptionSettings.PublishingInterval.Value.TotalMilliseconds); } [Fact] public void PnPlcPubSubFullTest2() { const string pn = """ [ { "DataSetWriterGroup": "testgroup", "DataSetWriterId": "testwriterid", "DataSetPublishingInterval": 1000, "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "DataSetFieldId": "testfieldid1", "OpcPublishingInterval": 1000 }, { "Id": "i=2259", } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries).ToList(); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); // Single group, single writer, double published data Assert.Equal(2, writerGroups .Single().DataSetWriters[0].DataSet.DataSetSource.PublishedVariables.PublishedData.Count); Assert.Equal("testfieldid1", writerGroups .Single().DataSetWriters[0].DataSet.DataSetSource.PublishedVariables.PublishedData[0].Id); Assert.Equal("i=2258", writerGroups .Single().DataSetWriters[0].DataSet.DataSetSource.PublishedVariables.PublishedData[0].PublishedVariableNodeId); Assert.Null(writerGroups .Single().DataSetWriters[0].DataSet.DataSetSource.PublishedVariables.PublishedData[1].Id); Assert.Equal("i=2259", writerGroups .Single().DataSetWriters[0].DataSet.DataSetSource.PublishedVariables.PublishedData[1].PublishedVariableNodeId); Assert.Equal("testgroup", writerGroups .Single().Name); Assert.Equal("8b7a6decc0651d269ea794c7e699bfcf77a97c31", writerGroups .Single().Id); Assert.Null(writerGroups // Will be set later based on configuration. .Single().DataSetWriters[0].DataSet.DataSetSource.Connection.Group); Assert.Equal("testwriterid", writerGroups .Single().DataSetWriters[0].DataSetWriterName); Assert.Equal(1000, writerGroups .Single().DataSetWriters[0].DataSet.DataSetSource.SubscriptionSettings.PublishingInterval.Value.TotalMilliseconds); } [Fact] public void PnPlcPubSubFullTest3() { const string pn = """ [ { "DataSetWriterGroup": "testgroup", "DataSetWriterId": "testwriterid", "DataSetPublishingInterval": 1000, "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "DataSetFieldId": "testfieldid1", "OpcPublishingInterval": 2000 }, { "Id": "i=2259", } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries).ToList(); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); // Single group, double writer, single published data Assert.Single(writerGroups .Single().DataSetWriters[0].DataSet.DataSetSource.PublishedVariables.PublishedData); Assert.Equal("testfieldid1", writerGroups .Single().DataSetWriters[0].DataSet.DataSetSource.PublishedVariables.PublishedData[0].Id); Assert.Equal("i=2258", writerGroups .Single().DataSetWriters[0].DataSet.DataSetSource.PublishedVariables.PublishedData[0].PublishedVariableNodeId); Assert.Null(writerGroups .Single().DataSetWriters[writerGroups .Single().DataSetWriters.Count - 1].DataSet.DataSetSource.PublishedVariables.PublishedData[writerGroups .Single().DataSetWriters[writerGroups .Single().DataSetWriters.Count - 1].DataSet.DataSetSource.PublishedVariables.PublishedData.Count - 1].Id); Assert.Equal("i=2259", writerGroups .Single().DataSetWriters[writerGroups .Single().DataSetWriters.Count - 1].DataSet.DataSetSource.PublishedVariables.PublishedData[writerGroups .Single().DataSetWriters[writerGroups .Single().DataSetWriters.Count - 1].DataSet.DataSetSource.PublishedVariables.PublishedData.Count - 1].PublishedVariableNodeId); Assert.Equal("testgroup", writerGroups .Single().Name); Assert.Equal("8b7a6decc0651d269ea794c7e699bfcf77a97c31", writerGroups .Single().Id); Assert.Null(writerGroups // Will be set later based on configuration. .Single().DataSetWriters[0].DataSet.DataSetSource.Connection.Group); Assert.Equal("testwriterid", writerGroups .Single().DataSetWriters[0].DataSetWriterName); Assert.Equal(2000, writerGroups .Single().DataSetWriters[0].DataSet.DataSetSource.SubscriptionSettings.PublishingInterval.Value.TotalMilliseconds); Assert.Equal(1000, writerGroups .Single().DataSetWriters[writerGroups .Single().DataSetWriters.Count - 1].DataSet.DataSetSource.SubscriptionSettings.PublishingInterval.Value.TotalMilliseconds); } [Fact] public void PnPlcPubSubDataSetPublishingInterval1Test() { const string pn = """ [ { "DataSetPublishingInterval": 1000, "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Equal(1000, writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.SubscriptionSettings.PublishingInterval.Value.TotalMilliseconds); } [Fact] public void PnPlcPubSubDataSetPublishingInterval2Test() { const string pn = """ [ { "DataSetPublishingInterval": 1000, "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "OpcPublishingInterval": 2000 } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Equal(2000, writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.SubscriptionSettings.PublishingInterval.Value.TotalMilliseconds); } [Fact] public void PnPlcPubSubDataSetPublishingInterval3Test() { const string pn = """ [ { "DataSetPublishingInterval": 1000, "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258" }, { "Id": "i=2259" } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Equal(1000, writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.SubscriptionSettings.PublishingInterval.Value.TotalMilliseconds); } [Fact] public void PnPlcPubSubDataSetPublishingInterval4Test() { const string pn = """ [ { "DataSetPublishingInterval": 1000, "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "OpcPublishingInterval": 2000 }, { "Id": "i=2259" } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Equal(2000, writerGroups .First().DataSetWriters[0].DataSet.DataSetSource.SubscriptionSettings.PublishingInterval.Value.TotalMilliseconds); } [Fact] public void PnPlcPubSubDataSetPublishingIntervalTimespan1Test() { const string pn = """ [ { "DataSetPublishingIntervalTimespan": "00:00:01", "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Equal(1000, writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.SubscriptionSettings.PublishingInterval.Value.TotalMilliseconds); } [Fact] public void PnPlcPubSubDataSetPublishingIntervalTimespan2Test() { const string pn = """ [ { "DataSetPublishingIntervalTimespan": "00:00:01", "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "OpcPublishingIntervalTimespan": "00:00:02" } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Equal(2000, writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.SubscriptionSettings.PublishingInterval.Value.TotalMilliseconds); } [Fact] public void PnPlcPubSubDataSetPublishingIntervalTimespan3Test() { const string pn = """ [ { "DataSetPublishingIntervalTimespan": "00:00:01", "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258" }, { "Id": "i=2259" } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Equal(1000, writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.SubscriptionSettings.PublishingInterval.Value.TotalMilliseconds); } [Fact] public void PnPlcPubSubDataSetPublishingIntervalTimespan4Test() { const string pn = """ [ { "DataSetPublishingIntervalTimespan": "00:00:01", "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", }, { "Id": "i=2259", "OpcPublishingInterval": 3000 } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Equal(1000, writerGroups .Single().DataSetWriters[0].DataSet.DataSetSource.SubscriptionSettings.PublishingInterval.Value.TotalMilliseconds); } [Fact] public void PnPlcPubSubDisplayName1Test() { const string pn = """ [ { "DataSetPublishingInterval": 1000, "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "DisplayName": "testdisplayname1" }, ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Equal("testdisplayname1", writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.PublishedVariables.PublishedData.Single().PublishedVariableDisplayName); } [Fact] public void PnPlcPubSubDisplayName2Test() { const string pn = """ [ { "DataSetPublishingInterval": 1000, "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", }, ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Null(writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.PublishedVariables.PublishedData.Single().Id); } [Fact] public void PnPlcPubSubDisplayName3Test() { const string pn = """ [ { "DataSetPublishingInterval": 1000, "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "DisplayName": "testdisplayname1", "DataSetFieldId": "testdatasetfieldid1", }, ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Equal("testdatasetfieldid1", writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.PublishedVariables.PublishedData.Single().Id); } [Fact] public void PnPlcPubSubDisplayName4Test() { const string pn = """ [ { "DataSetPublishingInterval": 1000, "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "DataSetFieldId": "testdatasetfieldid1", }, ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Equal("testdatasetfieldid1", writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.PublishedVariables.PublishedData.Single().Id); } [Fact] public void PnPlcPubSubPublishedNodeDisplayName1Test() { const string pn = """ [ { "DataSetPublishingInterval": 1000, "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "DisplayName": "testdisplayname1" }, ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Equal("testdisplayname1", writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.PublishedVariables.PublishedData.Single().PublishedVariableDisplayName); } [Fact] public void PnPlcPubSubPublishedNodeDisplayName2Test() { const string pn = """ [ { "DataSetPublishingInterval": 1000, "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", }, ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Null(writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.PublishedVariables.PublishedData.Single().PublishedVariableDisplayName); } [Fact] public void PnPlcPubSubPublishedNodeDisplayName3Test() { const string pn = """ [ { "DataSetPublishingInterval": 1000, "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "DisplayName": "testdisplayname1", "DataSetFieldId": "testdatasetfieldid1", }, ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Equal("testdisplayname1", writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.PublishedVariables.PublishedData.Single().PublishedVariableDisplayName); } [Fact] public void PnPlcPubSubPublishedNodeDisplayName4Test() { const string pn = """ [ { "DataSetPublishingInterval": 1000, "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "DataSetFieldId": "testdatasetfieldid1", }, ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Null(writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.PublishedVariables.PublishedData.Single().PublishedVariableDisplayName); } [Fact] public void PnPlcHeartbeatInterval2Test() { const string pn = """ [ { "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "HeartbeatInterval": 2 } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries).ToList(); Assert.NotEmpty(writerGroups); var j = Assert.Single(writerGroups); Assert.Null(j.MessageSettings); Assert.Single(writerGroups .Single().DataSetWriters); Assert.Equal("opc.tcp://localhost:50000", writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.Connection.Endpoint.Url); Assert.Equal(2, j .DataSetWriters.Single() .DataSet.DataSetSource.PublishedVariables.PublishedData.Single() .HeartbeatInterval.Value.TotalSeconds); } [Fact] public void PnPlcHeartbeatIntervalTimespanTest() { const string pn = """ [ { "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "HeartbeatIntervalTimespan": "00:00:01.500" } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries).ToList(); Assert.NotEmpty(writerGroups); var j = Assert.Single(writerGroups); Assert.Null(j.MessageSettings); Assert.Single(writerGroups .Single().DataSetWriters); Assert.Equal("opc.tcp://localhost:50000", writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.Connection.Endpoint.Url); Assert.Equal(1500, j .DataSetWriters.Single() .DataSet.DataSetSource.PublishedVariables.PublishedData.Single() .HeartbeatInterval.Value.TotalMilliseconds); } [Fact] public void PnPlcHeartbeatSkipSingleTrueTest() { const string pn = """ [ { "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "SkipSingle": true } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries).ToList(); Assert.NotEmpty(writerGroups); var j = Assert.Single(writerGroups); Assert.Null(j.MessageSettings); Assert.Single(writerGroups .Single().DataSetWriters); Assert.Equal("opc.tcp://localhost:50000", writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.Connection.Endpoint.Url); } [Fact] public void PnPlcHeartbeatSkipSingleFalseTest() { const string pn = """ [ { "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "SkipSingle": false } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries).ToList(); Assert.NotEmpty(writerGroups); Assert.Single(writerGroups); Assert.Single(writerGroups .Single().DataSetWriters); Assert.Equal("opc.tcp://localhost:50000", writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.Connection.Endpoint.Url); } [Fact] public void PnPlcPublishingInterval2000Test() { const string pn = """ [ { "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "OpcPublishingInterval": 2000 } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); var j = Assert.Single(writerGroups); Assert.Single(j.DataSetWriters); Assert.Null(j.MessageSettings); Assert.Equal("opc.tcp://localhost:50000", writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.Connection.Endpoint.Url); Assert.Equal(2000, j.DataSetWriters.Single() .DataSet.DataSetSource.SubscriptionSettings.PublishingInterval.Value.TotalMilliseconds); } [Fact] public void PnPlcPublishingIntervalCliTest() { const string pn = """ [ { "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258" } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); var j = Assert.Single(writerGroups); Assert.Single(j.DataSetWriters); Assert.Null(j.MessageSettings); Assert.Equal("opc.tcp://localhost:50000", writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.Connection.Endpoint.Url); Assert.Null(j.DataSetWriters.Single() .DataSet.DataSetSource.SubscriptionSettings.PublishingInterval); } [Fact] public void PnPlcSamplingInterval2000Test() { const string pn = """ [ { "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "OpcSamplingInterval": 2000 } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); var j = Assert.Single(writerGroups); Assert.Single(j.DataSetWriters); Assert.Null(j.MessageSettings); Assert.Equal("opc.tcp://localhost:50000", writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.Connection.Endpoint.Url); Assert.Equal(2000, j .DataSetWriters.Single() .DataSet.DataSetSource.PublishedVariables.PublishedData.Single() .SamplingIntervalHint.Value.TotalMilliseconds); } [Fact] public void PnPlcExpandedNodeIdTest() { const string pn = """ [ { "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "ExpandedNodeId": "nsu=http://opcfoundation.org/UA/;i=2258" } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); var j = Assert.Single(writerGroups); Assert.Single(j.DataSetWriters); Assert.Null(j.MessageSettings); Assert.Equal("opc.tcp://localhost:50000", writerGroups .Single().DataSetWriters .Single().DataSet.DataSetSource.Connection.Endpoint.Url); } [Fact] public void PnPlcExpandedNodeId2Test() { const string pn = """ [ { "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "ExpandedNodeId": "nsu=http://opcfoundation.org/UA/;i=2258" } ] }, { "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2262" }, { "Id": "ns=2;s=AlternatingBoolean" }, { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=NegativeTrendData" } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); var j = Assert.Single(writerGroups); Assert.Null(j.MessageSettings); Assert.Single(j.DataSetWriters); Assert.Equal("opc.tcp://localhost:50000", j.DataSetWriters .Single().DataSet.DataSetSource.Connection.Endpoint.Url); } [Fact] public void PnPlcExpandedNodeId3Test() { const string pn = """ [ { "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258" }, { "Id": "ns=2;s=DipData" }, { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=NegativeTrendData" } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); var j = Assert.Single(writerGroups); Assert.Null(j.MessageSettings); Assert.Single(j.DataSetWriters); Assert.Equal("opc.tcp://localhost:50000", j.DataSetWriters .Single().DataSet.DataSetSource.Connection.Endpoint.Url); } [Fact] public void PnPlcExpandedNodeId4Test() { const string pn = """ [ { "EndpointUrl": "opc.tcp://localhost:50000", "NodeId": { "Identifier": "i=2258" } }, { "EndpointUrl": "opc.tcp://localhost:50000", "NodeId": { "Identifier": "ns=0;i=2261" } }, { "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "ExpandedNodeId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=AlternatingBoolean" } ] }, { "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2262" }, { "Id": "ns=2;s=DipData" }, { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=NegativeTrendData" } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); var j = Assert.Single(writerGroups); Assert.Null(j.MessageSettings); Assert.Single(j.DataSetWriters); Assert.Equal("opc.tcp://localhost:50000", j.DataSetWriters .Single().DataSet.DataSetSource.Connection.Endpoint.Url); } [Fact] public void PnPlcMultiJob1Test() { const string pn = """ [ { "EndpointUrl": "opc.tcp://localhost1:50000", "NodeId": { "Identifier": "i=2258" } }, { "EndpointUrl": "opc.tcp://localhost2:50000", "NodeId": { "Identifier": "ns=0;i=2261" } }, { "EndpointUrl": "opc.tcp://localhost3:50000", "OpcNodes": [ { "ExpandedNodeId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=AlternatingBoolean" } ] }, { "EndpointUrl": "opc.tcp://localhost4:50000", "OpcNodes": [ { "Id": "i=2262" }, { "Id": "ns=2;s=DipData" }, { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=NegativeTrendData" } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); var j = Assert.Single(writerGroups); Assert.Null(j.MessageSettings); Assert.Equal(4, j.DataSetWriters.Count); } [Fact] public void PnPlcMultiJob2Test() { const string pn = """ [ { "EndpointUrl": "opc.tcp://localhost:50001", "NodeId": { "Identifier": "i=2258", } }, { "EndpointUrl": "opc.tcp://localhost:50002", "NodeId": { "Identifier": "ns=0;i=2261" } }, { "EndpointUrl": "opc.tcp://localhost:50003", "OpcNodes": [ { "OpcPublishingInterval": 1000, "ExpandedNodeId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=AlternatingBoolean" } ] }, { "EndpointUrl": "opc.tcp://localhost:50004", "OpcNodes": [ { "OpcPublishingInterval": 1000, "Id": "i=2262" }, { "OpcPublishingInterval": 1000, "Id": "ns=2;s=DipData" }, { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=NegativeTrendData", "OpcPublishingInterval": 1000 } ] } ] """; var endpointUrls = new string[] { "opc.tcp://localhost:50001", "opc.tcp://localhost:50002", "opc.tcp://localhost:50003", "opc.tcp://localhost:50004" }; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); var j = Assert.Single(writerGroups); Assert.Null(j.MessageSettings); Assert.Equal(4, j.DataSetWriters.Count); Assert.True(endpointUrls.ToHashSet().SetEqualsSafe( j.DataSetWriters.Select(w => w.DataSet.DataSetSource.Connection.Endpoint.Url))); } [Fact] public void PnPlcMultiJob3Test() { const string pn = """ [ { "EndpointUrl": "opc.tcp://localhost:50000", "NodeId": { "Identifier": "i=2258", } }, { "EndpointUrl": "opc.tcp://localhost:50000", "NodeId": { "Identifier": "ns=0;i=2261" } }, { "EndpointUrl": "opc.tcp://localhost:50001", "OpcNodes": [ { "OpcPublishingInterval": 1000, "ExpandedNodeId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=AlternatingBoolean" } ] }, { "EndpointUrl": "opc.tcp://localhost:50001", "OpcNodes": [ { "OpcPublishingInterval": 1000, "Id": "i=2262" }, { "OpcPublishingInterval": 1000, "Id": "ns=2;s=DipData" }, { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=NegativeTrendData", "OpcPublishingInterval": 1000 } ] } ] """; var endpointUrls = new string[] { "opc.tcp://localhost:50000", "opc.tcp://localhost:50001" }; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); var j = Assert.Single(writerGroups); Assert.Null(j.MessageSettings); Assert.Equal(2, j.DataSetWriters.Count); Assert.True(endpointUrls.ToHashSet().SetEqualsSafe( j.DataSetWriters.Select(w => w.DataSet.DataSetSource.Connection.Endpoint.Url))); } [Fact] public void PnPlcMultiJob4Test() { const string pn = """ [ { "EndpointUrl": "opc.tcp://localhost:50000", "NodeId": { "Identifier": "i=2258", } }, { "EndpointUrl": "opc.tcp://localhost:50000", "NodeId": { "Identifier": "ns=0;i=2261" } }, { "EndpointUrl": "opc.tcp://localhost:50001", "OpcNodes": [ { "ExpandedNodeId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=AlternatingBoolean" } ] }, { "EndpointUrl": "opc.tcp://localhost:50001", "OpcNodes": [ { "OpcPublishingInterval": 2000, "Id": "i=2262" }, { "OpcPublishingInterval": 2000, "Id": "ns=2;s=DipData" }, { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=NegativeTrendData", } ] } ] """; var endpointUrls = new string[] { "opc.tcp://localhost:50000", "opc.tcp://localhost:50001" }; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries); Assert.NotEmpty(writerGroups); var j = Assert.Single(writerGroups); Assert.Null(j.MessageSettings); Assert.Equal(3, j.DataSetWriters.Count); Assert.True(endpointUrls.ToHashSet().SetEqualsSafe( j.DataSetWriters.Select(w => w.DataSet.DataSetSource.Connection.Endpoint.Url))); } [Theory] [InlineData("Publisher/publishednodes_with_duplicates.json")] public async Task PnWithDuplicatesTestAsync(string publishedNodesJsonFile) { var pn = await File.ReadAllTextAsync(publishedNodesJsonFile); var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries).ToList(); Assert.NotEmpty(writerGroups); var j = Assert.Single(writerGroups); Assert.Null(j.MessageSettings); Assert.Equal(2, j.DataSetWriters.Count); Assert.All(j.DataSetWriters, dataSetWriter => Assert.Equal("opc.tcp://10.0.0.1:59412", dataSetWriter.DataSet.DataSetSource.Connection.Endpoint.Url)); Assert.Single(j.DataSetWriters, dataSetWriter => TimeSpan.FromMinutes(15) == dataSetWriter.DataSet.DataSetSource.SubscriptionSettings.PublishingInterval); Assert.Single(j.DataSetWriters, dataSetWriter => TimeSpan.FromMinutes(1) == dataSetWriter.DataSet.DataSetSource.SubscriptionSettings.PublishingInterval); Assert.Single(j.DataSetWriters, dataSetWriter => dataSetWriter.DataSet.DataSetSource.PublishedVariables.PublishedData.Any( p => TimeSpan.FromMinutes(15) == p.SamplingIntervalHint)); Assert.Equal(3, j.DataSetWriters.Sum(dataSetWriter => dataSetWriter.DataSet.DataSetSource.PublishedVariables.PublishedData.Count)); } [Fact] public void PnPlcMultiJobBatching1Test() { var pn = new StringBuilder(""" [ { "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ """); for (var i = 1; i < 10000; i++) { pn .Append("{ \"Id\": \"i=") .Append(i) .Append("\" },"); } pn.Append(""" { "Id": "i=10000" } ] } ] """); var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn.ToString()); var writerGroups = converter.ToWriterGroups(entries).ToList(); // No writerGroups Assert.NotEmpty(writerGroups); var j = Assert.Single(writerGroups); Assert.Null(j.MessageSettings); Assert.Equal(10, j.DataSetWriters.Count); Assert.All(j.DataSetWriters, dataSetWriter => Assert.Equal("opc.tcp://localhost:50000", dataSetWriter.DataSet.DataSetSource.Connection.Endpoint.Url)); Assert.All(j.DataSetWriters, dataSetWriter => Assert.Null( dataSetWriter.DataSet.DataSetSource.SubscriptionSettings.PublishingInterval)); Assert.All(j.DataSetWriters, dataSetWriter => Assert.All( dataSetWriter.DataSet.DataSetSource.PublishedVariables.PublishedData, p => Assert.Null(p.SamplingIntervalHint))); Assert.All(j.DataSetWriters, dataSetWriter => Assert.Equal(1000, dataSetWriter.DataSet.DataSetSource.PublishedVariables.PublishedData.Count)); } [Fact] public void PnPlcMultiJobBatching2Test() { var pn = new StringBuilder(""" [ { "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ """); for (var i = 1; i < 10000; i++) { pn .Append("{ \"Id\": \"i=") .Append(i) .Append('\"') .Append(i % 2 == 1 ? ",\"OpcPublishingInterval\": 2000" : null) .Append("},"); } pn.Append(""" { "Id": "i=10000" } ] } ] """); var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn.ToString()); var writerGroups = converter.ToWriterGroups(entries).ToList(); // No writerGroups Assert.NotEmpty(writerGroups); var j = Assert.Single(writerGroups); Assert.Null(j.MessageSettings); Assert.Equal(10, j.DataSetWriters.Count); Assert.All(j.DataSetWriters, dataSetWriter => Assert.Equal("opc.tcp://localhost:50000", dataSetWriter.DataSet.DataSetSource.Connection.Endpoint.Url)); Assert.Equal( new TimeSpan?[] { TimeSpan.FromMilliseconds(2000), TimeSpan.FromMilliseconds(2000), TimeSpan.FromMilliseconds(2000), TimeSpan.FromMilliseconds(2000), TimeSpan.FromMilliseconds(2000), null, null, null, null, null }, j.DataSetWriters.Select(dataSetWriter => dataSetWriter.DataSet.DataSetSource.SubscriptionSettings?.PublishingInterval)); Assert.All(j.DataSetWriters, dataSetWriter => Assert.All( dataSetWriter.DataSet.DataSetSource.PublishedVariables.PublishedData, p => Assert.Null(p.SamplingIntervalHint))); Assert.All(j.DataSetWriters, dataSetWriter => Assert.Equal(1000, dataSetWriter.DataSet.DataSetSource.PublishedVariables.PublishedData.Count)); } [Fact] public void PnPlcJobWithAllEventPropertiesTest() { var pn = new StringBuilder(""" [ { "EndpointUrl": "opc.tcp://localhost:50000", "OpcNodes": [ { "Id": "i=2258", "DisplayName": "TestingDisplayName", "EventFilter": { "SelectClauses": [ { "TypeDefinitionId": "i=2041", "BrowsePath": [ "EventId" ], "AttributeId": "BrowseName", "IndexRange": "5:20" } ], "WhereClause": { "Elements": [ { "FilterOperator": "OfType", "FilterOperands": [ { "NodeId": "i=2041", "BrowsePath": [ "EventId" ], "AttributeId": "BrowseName", "Value": "ns=2;i=235", "IndexRange": "5:20", "Index": 10, "Alias": "Test", } ] } ] } } } ] } ] """); var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn.ToString()); var writerGroups = converter.ToWriterGroups(entries).ToList(); // Check writerGroups Assert.Single(writerGroups); Assert.Single(writerGroups[0].DataSetWriters); Assert.Single(writerGroups[0].DataSetWriters[0].DataSet.DataSetSource.PublishedEvents.PublishedData); Assert.NotNull(writerGroups[0].DataSetWriters[0].DataSet.DataSetSource.PublishedVariables); Assert.NotNull(writerGroups[0].DataSetWriters[0].DataSet.DataSetSource.PublishedEvents); Assert.Empty(writerGroups[0].DataSetWriters[0].DataSet.DataSetSource.PublishedVariables.PublishedData); Assert.Single(writerGroups[0].DataSetWriters[0].DataSet.DataSetSource.PublishedEvents.PublishedData); // Check model var model = writerGroups[0].DataSetWriters[0].DataSet.DataSetSource.PublishedEvents.PublishedData[0]; Assert.Equal("TestingDisplayName", model.PublishedEventName); Assert.Equal("i=2258", model.EventNotifier); // Check select clauses Assert.Single(model.SelectedFields); Assert.Equal("i=2041", model.SelectedFields[0].TypeDefinitionId); Assert.Single(model.SelectedFields[0].BrowsePath); Assert.Equal("EventId", model.SelectedFields[0].BrowsePath[0]); Assert.Equal(NodeAttribute.BrowseName, model.SelectedFields[0].AttributeId.Value); Assert.Equal("5:20", model.SelectedFields[0].IndexRange); Assert.NotNull(model.Filter); Assert.Single(model.Filter.Elements); Assert.Equal(FilterOperatorType.OfType, model.Filter.Elements[0].FilterOperator); Assert.Single(model.Filter.Elements[0].FilterOperands); Assert.Equal("i=2041", model.Filter.Elements[0].FilterOperands[0].NodeId); Assert.Equal("ns=2;i=235", model.Filter.Elements[0].FilterOperands[0].Value); // Check where clause Assert.Single(model.Filter.Elements[0].FilterOperands[0].BrowsePath); Assert.Equal("EventId", model.Filter.Elements[0].FilterOperands[0].BrowsePath[0]); Assert.Equal(NodeAttribute.BrowseName, model.Filter.Elements[0].FilterOperands[0].AttributeId.Value); Assert.Equal("5:20", model.Filter.Elements[0].FilterOperands[0].IndexRange); Assert.NotNull(model.Filter.Elements[0].FilterOperands[0].Index); Assert.Equal((uint)10, model.Filter.Elements[0].FilterOperands[0].Index.Value); Assert.Equal("Test", model.Filter.Elements[0].FilterOperands[0].Alias); } [Fact] public void PnPlcMultiJob1TestWithDataItemsAndEvents() { const string pn = """ [ { "EndpointUrl": "opc.tcp://localhost1:50000", "NodeId": { "Identifier": "i=2258" } }, { "EndpointUrl": "opc.tcp://localhost2:50000", "NodeId": { "Identifier": "ns=0;i=2261" } }, { "EndpointUrl": "opc.tcp://localhost3:50000", "OpcNodes": [ { "ExpandedNodeId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=AlternatingBoolean", "DisplayName": "AlternatingBoolean" }, { "Id": "i=2253", "OpcPublishingInterval": 5000, "EventFilter": { "SelectClauses": [ { "TypeDefinitionId": "i=2041", "BrowsePath": [ "EventId" ] } ], "WhereClause": { "Elements": [ { "FilterOperator": "OfType", "FilterOperands": [ { "Value": "ns=2;i=235" } ] } ] } } } ] }, { "EndpointUrl": "opc.tcp://localhost4:50000", "OpcNodes": [ { "Id": "i=2262" }, { "Id": "ns=2;s=DipData" }, { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=NegativeTrendData" } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries).ToList(); Assert.NotEmpty(writerGroups); var writers = Assert.Single(writerGroups).DataSetWriters; Assert.Equal(5, writers.Count); Assert.Single(writers[0].DataSet.DataSetSource.PublishedVariables.PublishedData); var dataItemModel = writers[0].DataSet.DataSetSource.PublishedVariables.PublishedData[0]; Assert.Equal("i=2258", dataItemModel.PublishedVariableNodeId); Assert.Empty(writers[0].DataSet.DataSetSource.PublishedEvents.PublishedData); Assert.Single(writers[1].DataSet.DataSetSource.PublishedVariables.PublishedData); Assert.Empty(writers[1].DataSet.DataSetSource.PublishedEvents.PublishedData); dataItemModel = writers[1].DataSet.DataSetSource.PublishedVariables.PublishedData[0]; Assert.Equal("ns=0;i=2261", dataItemModel.PublishedVariableNodeId); Assert.Single(writers[2].DataSet.DataSetSource.PublishedVariables.PublishedData); Assert.Empty(writers[2].DataSet.DataSetSource.PublishedEvents.PublishedData); dataItemModel = writers[2].DataSet.DataSetSource.PublishedVariables.PublishedData[0]; Assert.Equal("AlternatingBoolean", dataItemModel.PublishedVariableDisplayName); Assert.Equal("nsu=http://microsoft.com/Opc/OpcPlc/;s=AlternatingBoolean", dataItemModel.PublishedVariableNodeId); Assert.Empty(writers[3].DataSet.DataSetSource.PublishedVariables.PublishedData); Assert.NotEmpty(writers[3].DataSet.DataSetSource.PublishedEvents.PublishedData); var eventModel = writers[3].DataSet.DataSetSource.PublishedEvents.PublishedData[0]; Assert.Equal("i=2253", eventModel.EventNotifier); Assert.Single(eventModel.SelectedFields); Assert.Equal("i=2041", eventModel.SelectedFields[0].TypeDefinitionId); Assert.Single(eventModel.SelectedFields[0].BrowsePath); Assert.Equal("EventId", eventModel.SelectedFields[0].BrowsePath[0]); Assert.NotNull(eventModel.Filter); Assert.Single(eventModel.Filter.Elements); Assert.Equal(FilterOperatorType.OfType, eventModel.Filter.Elements[0].FilterOperator); Assert.Single(eventModel.Filter.Elements[0].FilterOperands); Assert.Equal("ns=2;i=235", eventModel.Filter.Elements[0].FilterOperands[0].Value); Assert.NotEmpty(writers[4].DataSet.DataSetSource.PublishedVariables.PublishedData); Assert.Empty(writers[4].DataSet.DataSetSource.PublishedEvents.PublishedData); dataItemModel = writers[4].DataSet.DataSetSource.PublishedVariables.PublishedData[0]; Assert.Equal("i=2262", dataItemModel.PublishedVariableNodeId); dataItemModel = writers[4].DataSet.DataSetSource.PublishedVariables.PublishedData[1]; Assert.Equal("ns=2;s=DipData", dataItemModel.PublishedVariableNodeId); dataItemModel = writers[4].DataSet.DataSetSource.PublishedVariables.PublishedData[2]; Assert.Equal("nsu=http://microsoft.com/Opc/OpcPlc/;s=NegativeTrendData", dataItemModel.PublishedVariableNodeId); } [Fact] public void PnPlcJobTestWithEvents() { const string pn = """ [ { "EndpointUrl": "opc.tcp://desktop-fhd2fr4:62563/Quickstarts/SimpleEventsServer", "UseSecurity": false, "OpcNodes": [ { "Id": "i=2253", "DisplayName": "DisplayName2253", "OpcPublishingInterval": 5000, "EventFilter": { "SelectClauses": [ { "TypeDefinitionId": "i=2041", "BrowsePath": [ "EventId" ] }, { "TypeDefinitionId": "i=2041", "BrowsePath": [ "EventType" ] }, { "TypeDefinitionId": "i=2041", "BrowsePath": [ "SourceNode" ] }, { "TypeDefinitionId": "i=2041", "BrowsePath": [ "SourceName" ] }, { "TypeDefinitionId": "i=2041", "BrowsePath": [ "Time" ] }, { "TypeDefinitionId": "i=2041", "BrowsePath": [ "ReceiveTime" ] }, { "TypeDefinitionId": "i=2041", "BrowsePath": [ "LocalTime" ] }, { "TypeDefinitionId": "i=2041", "BrowsePath": [ "Message" ] }, { "TypeDefinitionId": "i=2041", "BrowsePath": [ "Severity" ] }, { "TypeDefinitionId": "i=2041", "BrowsePath": [ "2:CycleId" ] }, { "TypeDefinitionId": "i=2041", "BrowsePath": [ "2:CurrentStep" ] } ], "WhereClause": { "Elements": [ { "FilterOperator": "OfType", "FilterOperands": [ { "Value": "ns=2;i=235" } ] } ] } } } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries).ToList(); Assert.NotEmpty(writerGroups); var j = Assert.Single(writerGroups); Assert.Single(writerGroups[0].DataSetWriters); Assert.Empty(writerGroups[0].DataSetWriters[0].DataSet.DataSetSource.PublishedVariables.PublishedData); Assert.Single(writerGroups[0].DataSetWriters[0].DataSet.DataSetSource.PublishedEvents.PublishedData); Assert.All(j.DataSetWriters, dataSetWriter => Assert.Single(dataSetWriter.DataSet.DataSetSource.PublishedEvents.PublishedData)); var eventModel = writerGroups[0].DataSetWriters[0].DataSet.DataSetSource.PublishedEvents.PublishedData[0]; Assert.Equal("DisplayName2253", eventModel.PublishedEventName); Assert.Equal("i=2253", eventModel.EventNotifier); Assert.Equal(11, eventModel.SelectedFields.Count); Assert.All(eventModel.SelectedFields, x => { Assert.Equal("i=2041", x.TypeDefinitionId); Assert.Single(x.BrowsePath); }); Assert.Equal(new[] { "EventId", "EventType", "SourceNode", "SourceName", "Time", "ReceiveTime", "LocalTime", "Message", "Severity", "2:CycleId", "2:CurrentStep" }, eventModel.SelectedFields.Select(x => x.BrowsePath[0])); } [Fact] public void PnPlcJobTestWithConditionHandling() { const string pn = """ [ { "EndpointUrl": "opc.tcp://desktop-fhd2fr4:62563/Quickstarts/SimpleEventsServer", "UseSecurity": false, "OpcNodes": [ { "Id": "i=2253", "OpcPublishingInterval": 5000, "EventFilter": { "TypeDefinitionId": "ns=2;i=235" }, "ConditionHandling": { "UpdateInterval": 10, "SnapshotInterval": 30 } } ] } ] """; var logger = Log.Console(); var converter = new PublishedNodesConverter(logger, _serializer, GetOptions()); var entries = converter.Read(pn); var writerGroups = converter.ToWriterGroups(entries).ToList(); Assert.NotEmpty(writerGroups); var j = Assert.Single(writerGroups); Assert.Single(writerGroups[0].DataSetWriters); Assert.Empty(writerGroups[0].DataSetWriters[0].DataSet.DataSetSource.PublishedVariables.PublishedData); Assert.Single(writerGroups[0].DataSetWriters[0].DataSet.DataSetSource.PublishedEvents.PublishedData); Assert.All(j.DataSetWriters, dataSetWriter => Assert.Single(dataSetWriter.DataSet.DataSetSource.PublishedEvents.PublishedData)); var eventModel = writerGroups[0].DataSetWriters[0].DataSet.DataSetSource.PublishedEvents.PublishedData[0]; Assert.Equal("i=2253", eventModel.EventNotifier); Assert.Equal("ns=2;i=235", eventModel.TypeDefinitionId); Assert.NotNull(eventModel.ConditionHandling); Assert.Equal(10, eventModel.ConditionHandling.UpdateInterval); Assert.Equal(30, eventModel.ConditionHandling.SnapshotInterval); } private static IIoTEdgeWorkloadApi CreateMockProvider() { var provider = new Mock(); provider.Setup(p => p.DecryptAsync(It.IsAny(), It.IsAny>(), It.IsAny())) .Returns((string _, ReadOnlyMemory cipher, CancellationToken _) => ValueTask.FromResult>( Encoding.UTF8.GetBytes(Encoding.UTF8.GetString(cipher.Span).Replace("Encrypted", "Decrypted", StringComparison.Ordinal)).AsMemory())); provider.Setup(p => p.EncryptAsync(It.IsAny(), It.IsAny>(), It.IsAny())) .Returns((string _, ReadOnlyMemory plaintext, CancellationToken _) => ValueTask.FromResult>( Encoding.UTF8.GetBytes(Encoding.UTF8.GetString(plaintext.Span).Replace("Decrypted", "Encrypted", StringComparison.Ordinal)).AsMemory())); return provider.Object; } private static IIoTEdgeWorkloadApi CreateThrowProvider() { var provider = new Mock(); #pragma warning disable CA2012 // Use ValueTasks correctly provider.Setup(p => p.DecryptAsync(It.IsAny(), It.IsAny>(), It.IsAny())) .Returns(ValueTask.FromException>(new FormatException("DecryptAsync"))); provider.Setup(p => p.EncryptAsync(It.IsAny(), It.IsAny>(), It.IsAny())) .Returns(ValueTask.FromException>(new FormatException("EncryptAsync"))); #pragma warning restore CA2012 // Use ValueTasks correctly return provider.Object; } private static IOptions GetOptions() { var options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); options.Value.MessagingProfile = MessagingProfile.Get(MessagingMode.Samples, MessageEncoding.Json); return options; } private readonly NewtonsoftJsonSerializer _serializer = new(); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Utils/TempFileProviderBase.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Utils { using System; using System.IO; /// /// Base class that provides a temporary file that will be cleaned up on disposal. /// public class TempFileProviderBase : IDisposable { protected readonly string _tempFile; public TempFileProviderBase() { _tempFile = Path.GetTempFileName(); } protected virtual void Dispose(bool disposing) { try { // Remove temporary published nodes file if one was created. if (File.Exists(_tempFile)) { File.Delete(_tempFile); } } catch { // Nothign to do. } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher/tests/Utils/Utils.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Utils { using System.IO; using System.Text; /// /// Utilities for tests. /// public static class Utils { /// /// Get content of a file as string. /// /// /// public static string GetFileContent(string path) { using var payloadReader = new StreamReader(path); return payloadReader.ReadToEnd(); } /// /// Copy content of source file to destination file. /// /// /// /// public static void CopyContent(string sourcePath, string destinationPath) { var content = GetFileContent(sourcePath); using var fileStream = new FileStream(destinationPath, FileMode.Open, FileAccess.Write, FileShare.ReadWrite); fileStream.Write(Encoding.UTF8.GetBytes(content)); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/AdditionalData.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Flags that are set by the historian when /// returning archived values. /// [Flags] [DataContract] public enum AdditionalData { /// /// No additional data /// [EnumMember(Value = "None")] None = 0x0, /// /// A data value which was calculated with an /// incomplete interval. /// [EnumMember(Value = "Partial")] Partial = 0x4, /// /// A raw data value that hides other data at /// the same timestamp. /// [EnumMember(Value = "ExtraData")] ExtraData = 0x8, /// /// Multiple values match the aggregate criteria /// (i.e. multiple minimum values at different /// timestamps within the same interval) /// [EnumMember(Value = "MultipleValues")] MultipleValues = 0x10 } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/AggregateConfigurationModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Aggregate configuration /// [DataContract] public sealed record class AggregateConfigurationModel { /// /// Whether to treat uncertain as bad /// [DataMember(Name = "treatUncertainAsBad", Order = 1, EmitDefaultValue = false)] public bool? TreatUncertainAsBad { get; set; } /// /// Percent of data that is bad /// [DataMember(Name = "percentDataBad", Order = 2, EmitDefaultValue = false)] public byte? PercentDataBad { get; set; } /// /// Percent of data that is good /// [DataMember(Name = "percentDataGood", Order = 3, EmitDefaultValue = false)] public byte? PercentDataGood { get; set; } /// /// Whether to use sloped extrapolation. /// [DataMember(Name = "useSlopedExtrapolation", Order = 4, EmitDefaultValue = false)] public bool? UseSlopedExtrapolation { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/AggregateFilterModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Aggregate Filter /// [DataContract] public sealed record class AggregateFilterModel { /// /// Start time /// [DataMember(Name = "startTime", Order = 0, EmitDefaultValue = false)] public DateTime? StartTime { get; set; } /// /// Aggregate type /// [DataMember(Name = "aggregateTypeId", Order = 1, EmitDefaultValue = false)] public string? AggregateTypeId { get; set; } /// /// Processing Interval /// [DataMember(Name = "processingInterval", Order = 2, EmitDefaultValue = false)] public TimeSpan? ProcessingInterval { get; set; } /// /// Aggregate Configuration - use an empty configuration /// to clear the configuration and use the server defaults. /// Returns null if the default configuration in the /// server is being used. /// [DataMember(Name = "aggregateConfiguration", Order = 3, EmitDefaultValue = false)] public AggregateConfigurationModel? AggregateConfiguration { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ApplicationInfoModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Collections.Generic; using System.Runtime.Serialization; /// /// Application info model /// [DataContract] public sealed record class ApplicationInfoModel { /// /// Unique application id /// [DataMember(Name = "applicationId", Order = 0)] public required string ApplicationId { get; set; } /// /// Type of application /// /// Server [DataMember(Name = "applicationType", Order = 1)] public ApplicationType ApplicationType { get; set; } /// /// Unique application uri /// [DataMember(Name = "applicationUri", Order = 2)] public required string ApplicationUri { get; set; } /// /// Product uri /// [DataMember(Name = "productUri", Order = 3, EmitDefaultValue = false)] public string? ProductUri { get; set; } /// /// Default name of application /// [DataMember(Name = "applicationName", Order = 4, EmitDefaultValue = false)] public string? ApplicationName { get; set; } /// /// Locale of default name - defaults to "en" /// [DataMember(Name = "locale", Order = 5, EmitDefaultValue = false)] public string? Locale { get; set; } /// /// Localized Names of application keyed on locale /// [DataMember(Name = "localizedNames", Order = 6, EmitDefaultValue = false)] public IReadOnlyDictionary? LocalizedNames { get; set; } /// /// The capabilities advertised by the server. /// /// LDS /// DA [DataMember(Name = "capabilities", Order = 7, EmitDefaultValue = false)] public IReadOnlySet? Capabilities { get; set; } /// /// Discovery urls of the server /// [DataMember(Name = "discoveryUrls", Order = 8, EmitDefaultValue = false)] public IReadOnlySet? DiscoveryUrls { get; set; } /// /// Discovery profile uri /// [DataMember(Name = "discoveryProfileUri", Order = 9, EmitDefaultValue = false)] public string? DiscoveryProfileUri { get; set; } /// /// Gateway server uri /// [DataMember(Name = "gatewayServerUri", Order = 10, EmitDefaultValue = false)] public string? GatewayServerUri { get; set; } /// /// Host addresses of server application or null /// [DataMember(Name = "hostAddresses", Order = 11, EmitDefaultValue = false)] public IReadOnlySet? HostAddresses { get; set; } /// /// Site of the application /// /// productionlineA /// cellB [DataMember(Name = "siteId", Order = 12, EmitDefaultValue = false)] public string? SiteId { get; set; } /// /// Discoverer that registered the application /// [DataMember(Name = "discovererId", Order = 13, EmitDefaultValue = false)] public string? DiscovererId { get; set; } /// /// Last time application was seen if not visible /// [DataMember(Name = "notSeenSince", Order = 14, EmitDefaultValue = false)] public DateTimeOffset? NotSeenSince { get; set; } /// /// Created /// [DataMember(Name = "created", Order = 15, EmitDefaultValue = false)] public OperationContextModel? Created { get; set; } /// /// Updated /// [DataMember(Name = "updated", Order = 16, EmitDefaultValue = false)] public OperationContextModel? Updated { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ApplicationRegistrationModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Application with optional list of endpoints /// [DataContract] public sealed record class ApplicationRegistrationModel { /// /// Application information /// [DataMember(Name = "application", Order = 0)] [Required] public required ApplicationInfoModel Application { get; set; } /// /// List of endpoints for it /// [DataMember(Name = "endpoints", Order = 1, EmitDefaultValue = false)] public IReadOnlyList? Endpoints { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ApplicationType.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Application type /// [DataContract] public enum ApplicationType { /// /// Application is server /// [EnumMember(Value = "Server")] Server, /// /// Application is client /// [EnumMember(Value = "Client")] Client, /// /// Application is client and server /// [EnumMember(Value = "ClientAndServer")] ClientAndServer, /// /// Application is discovery server /// [EnumMember(Value = "DiscoveryServer")] DiscoveryServer } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/AttributeReadRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Attribute to read /// [DataContract] public sealed record class AttributeReadRequestModel { /// /// Node to read from or write to (mandatory) /// [DataMember(Name = "nodeId", Order = 0)] [Required] public required string NodeId { get; set; } /// /// Attribute to read or write /// [DataMember(Name = "attribute", Order = 1)] [Required] public required NodeAttribute Attribute { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/AttributeReadResponseModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Furly.Extensions.Serializers; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Attribute value read /// [DataContract] public sealed record class AttributeReadResponseModel { /// /// Attribute value /// [DataMember(Name = "value", Order = 0)] [SkipValidation] public required VariantValue Value { get; set; } /// /// Service result in case of error /// [DataMember(Name = "errorInfo", Order = 1, EmitDefaultValue = false)] public ServiceResultModel? ErrorInfo { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/AttributeWriteRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Furly.Extensions.Serializers; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Attribute and value to write to it /// [DataContract] public sealed record class AttributeWriteRequestModel { /// /// Node to write to (mandatory) /// [DataMember(Name = "nodeId", Order = 0)] [Required] public required string NodeId { get; set; } /// /// Attribute to write (mandatory) /// [DataMember(Name = "attribute", Order = 1)] [Required] public required NodeAttribute Attribute { get; set; } /// /// Value to write (mandatory) /// [DataMember(Name = "value", Order = 2)] [SkipValidation] public required VariantValue Value { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/AttributeWriteResponseModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Attribute write result /// [DataContract] public sealed record class AttributeWriteResponseModel { /// /// Service result in case of error /// [DataMember(Name = "errorInfo", Order = 1, EmitDefaultValue = false)] public ServiceResultModel? ErrorInfo { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/AuthenticationMethodModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Furly.Extensions.Serializers; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Authentication Method model /// [DataContract] public sealed record class AuthenticationMethodModel { /// /// Method id /// [DataMember(Name = "id", Order = 0)] [Required] public required string Id { get; set; } /// /// Type of credential /// [DataMember(Name = "credentialType", Order = 1)] public CredentialType CredentialType { get; set; } /// /// Security policy to use when passing credential. /// [DataMember(Name = "securityPolicy", Order = 2, EmitDefaultValue = false)] public string? SecurityPolicy { get; set; } /// /// Method specific configuration /// [DataMember(Name = "configuration", Order = 3, EmitDefaultValue = false)] [SkipValidation] public VariantValue? Configuration { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/Azure.IIoT.OpcUa.Publisher.Models.csproj ================================================  net9.0 true true true Azure OPC Publisher Sdk shared models enable ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/BrowseDirection.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Direction to browse /// [DataContract] public enum BrowseDirection { /// /// Browse forward (default) /// [EnumMember(Value = "Forward")] Forward, /// /// Browse backward /// [EnumMember(Value = "Backward")] Backward, /// /// Browse both directions /// [EnumMember(Value = "Both")] Both } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/BrowseFirstRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Browse request model /// [DataContract] public sealed record class BrowseFirstRequestModel { /// /// Node to browse. /// (defaults to root folder). /// [DataMember(Name = "nodeId", Order = 0)] public string? NodeId { get; set; } /// /// Direction to browse in /// (default: forward) /// [DataMember(Name = "direction", Order = 1, EmitDefaultValue = false)] public BrowseDirection? Direction { get; set; } /// /// View to browse /// (default: null = new view = All nodes). /// [DataMember(Name = "view", Order = 2, EmitDefaultValue = false)] public BrowseViewModel? View { get; set; } /// /// Reference types to browse. /// (default: hierarchical). /// [DataMember(Name = "referenceTypeId", Order = 3, EmitDefaultValue = false)] public string? ReferenceTypeId { get; set; } /// /// Whether to include subtypes of the reference type. /// (default is false) /// [DataMember(Name = "noSubtypes", Order = 4, EmitDefaultValue = false)] public bool? NoSubtypes { get; set; } /// /// Max number of references to return. There might /// be less returned as this is up to the client /// restrictions. Set to 0 to return no references /// or target nodes. /// (default is decided by client e.g. 60) /// [DataMember(Name = "maxReferencesToReturn", Order = 5, EmitDefaultValue = false)] public uint? MaxReferencesToReturn { get; set; } /// /// Whether to collapse all references into a set of /// unique target nodes and not show reference /// information. /// (default is false) /// [DataMember(Name = "targetNodesOnly", Order = 6, EmitDefaultValue = false)] public bool? TargetNodesOnly { get; set; } /// /// Whether to read variable values on target nodes. /// (default is false) /// [DataMember(Name = "readVariableValues", Order = 7, EmitDefaultValue = false)] public bool? ReadVariableValues { get; set; } /// /// Filter returned target nodes by only returning /// nodes that have classes defined in this array. /// (default: null - all targets are returned) /// [DataMember(Name = "nodeClassFilter", Order = 8, EmitDefaultValue = false)] public IReadOnlyList? NodeClassFilter { get; set; } /// /// Optional request header /// [DataMember(Name = "header", Order = 9, EmitDefaultValue = false)] public RequestHeaderModel? Header { get; set; } /// /// Whether to only return the raw node id /// information and not read the target node. /// (default is false) /// [DataMember(Name = "nodeIdsOnly", Order = 10, EmitDefaultValue = false)] public bool? NodeIdsOnly { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/BrowseFirstResponseModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Browse response model /// [DataContract] public sealed record class BrowseFirstResponseModel { /// /// Node info for the currently browsed node /// [DataMember(Name = "node", Order = 0)] public required NodeModel Node { get; set; } /// /// References returned /// [DataMember(Name = "references", Order = 1)] public required IReadOnlyList References { get; set; } /// /// Continuation token if more results pending. /// [DataMember(Name = "continuationToken", Order = 2, EmitDefaultValue = false)] public string? ContinuationToken { get; set; } /// /// Service result in case of error /// [DataMember(Name = "errorInfo", Order = 3, EmitDefaultValue = false)] public ServiceResultModel? ErrorInfo { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/BrowseNextRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Request node browsing continuation /// [DataContract] public sealed record class BrowseNextRequestModel { /// /// Continuation token from previews browse request. /// (mandatory) /// [DataMember(Name = "continuationToken", Order = 0)] [Required] public required string ContinuationToken { get; set; } /// /// Whether to abort browse and release. /// (default: false) /// [DataMember(Name = "abort", Order = 1, EmitDefaultValue = false)] public bool? Abort { get; set; } /// /// Whether to collapse all references into a set of /// unique target nodes and not show reference /// information. /// (default is false) /// [DataMember(Name = "targetNodesOnly", Order = 2, EmitDefaultValue = false)] public bool? TargetNodesOnly { get; set; } /// /// Whether to read variable values on target nodes. /// (default is false) /// [DataMember(Name = "readVariableValues", Order = 3, EmitDefaultValue = false)] public bool? ReadVariableValues { get; set; } /// /// Optional request header /// [DataMember(Name = "header", Order = 4, EmitDefaultValue = false)] public RequestHeaderModel? Header { get; set; } /// /// Whether to only return the raw node id /// information and not read the target node. /// (default is false) /// [DataMember(Name = "nodeIdsOnly", Order = 5, EmitDefaultValue = false)] public bool? NodeIdsOnly { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/BrowseNextResponseModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Result of node browse continuation /// [DataContract] public sealed record class BrowseNextResponseModel { /// /// References returned /// [DataMember(Name = "references", Order = 0)] public required IReadOnlyList References { get; set; } /// /// Continuation token if more results pending. /// [DataMember(Name = "continuationToken", Order = 1, EmitDefaultValue = false)] public string? ContinuationToken { get; set; } /// /// Service result in case of error /// [DataMember(Name = "errorInfo", Order = 2, EmitDefaultValue = false)] public ServiceResultModel? ErrorInfo { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/BrowsePathRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Browse nodes by path /// [DataContract] public sealed record class BrowsePathRequestModel { /// /// Node to browse from (defaults to root folder). /// [DataMember(Name = "nodeId", Order = 0, EmitDefaultValue = false)] public string? NodeId { get; set; } /// /// The paths to browse from node. /// (mandatory) /// [DataMember(Name = "browsePaths", Order = 1)] [Required] public required IReadOnlyList> BrowsePaths { get; set; } /// /// Whether to read variable values on target nodes. /// (default is false) /// [DataMember(Name = "readVariableValues", Order = 2, EmitDefaultValue = false)] public bool? ReadVariableValues { get; set; } /// /// Optional request header /// [DataMember(Name = "header", Order = 3, EmitDefaultValue = false)] public RequestHeaderModel? Header { get; set; } /// /// Whether to only return the raw node id /// information and not read the target node. /// (default is false) /// [DataMember(Name = "nodeIdsOnly", Order = 4, EmitDefaultValue = false)] public bool? NodeIdsOnly { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/BrowsePathResponseModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Result of node browse continuation /// [DataContract] public sealed record class BrowsePathResponseModel { /// /// Targets /// [DataMember(Name = "targets", Order = 0, EmitDefaultValue = false)] public IReadOnlyList? Targets { get; set; } /// /// Service result in case of error /// [DataMember(Name = "errorInfo", Order = 1, EmitDefaultValue = false)] public ServiceResultModel? ErrorInfo { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/BrowseStreamChunkModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Browse stream chunk /// [DataContract] public sealed record class BrowseStreamChunkModel { /// /// Source node id /// [DataMember(Name = "sourceId", Order = 0)] public required string SourceId { get; init; } /// /// Source node attributes if this chunk contains /// the source node attributes that were read. /// This can be null, then reference is not /// null. /// [DataMember(Name = "attributes", Order = 1, EmitDefaultValue = false)] public NodeModel? Attributes { get; init; } /// /// References read from the source node to a target /// node. This can be null, then attributes is not /// null. /// [DataMember(Name = "reference", Order = 2, EmitDefaultValue = false)] public NodeReferenceModel? Reference { get; init; } /// /// Service result in case of error /// [DataMember(Name = "errorInfo", Order = 3, EmitDefaultValue = false)] public ServiceResultModel? ErrorInfo { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/BrowseStreamRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Browse stream request model /// [DataContract] public sealed record class BrowseStreamRequestModel { /// /// Optional request header /// [DataMember(Name = "header", Order = 0, EmitDefaultValue = false)] public RequestHeaderModel? Header { get; init; } /// /// Start nodes to browse. /// (defaults to root folder). /// [DataMember(Name = "nodeId", Order = 1)] public IReadOnlyList? NodeIds { get; init; } /// /// Direction to browse in /// (default: forward) /// [DataMember(Name = "direction", Order = 2, EmitDefaultValue = false)] public BrowseDirection? Direction { get; init; } /// /// View to browse /// (default: null = new view = All nodes). /// [DataMember(Name = "view", Order = 3, EmitDefaultValue = false)] public BrowseViewModel? View { get; init; } /// /// Reference types to browse. /// (default: hierarchical). /// [DataMember(Name = "referenceTypeId", Order = 4, EmitDefaultValue = false)] public string? ReferenceTypeId { get; init; } /// /// Whether to include subtypes of the reference type. /// (default is false) /// [DataMember(Name = "noSubtypes", Order = 5, EmitDefaultValue = false)] public bool? NoSubtypes { get; init; } /// /// Whether to read variable values on source nodes. /// (default is false) /// [DataMember(Name = "readVariableValues", Order = 6, EmitDefaultValue = false)] public bool? ReadVariableValues { get; init; } /// /// Whether to not browse recursively /// (default is false) /// [DataMember(Name = "noRecurse", Order = 7, EmitDefaultValue = false)] public bool? NoRecurse { get; init; } /// /// Filter returned target nodes by only returning /// nodes that have classes defined in this array. /// (default: null - all targets are returned) /// [DataMember(Name = "nodeClassFilter", Order = 8, EmitDefaultValue = false)] public IReadOnlyList? NodeClassFilter { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/BrowseViewModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// View to browse /// [DataContract] public sealed record class BrowseViewModel { /// /// Node of the view to browse /// [DataMember(Name = "viewId", Order = 0)] [Required] public required string ViewId { get; set; } /// /// Browses specific version of the view. /// [DataMember(Name = "version", Order = 1, EmitDefaultValue = false)] public uint? Version { get; set; } /// /// Browses at or before this timestamp. /// [DataMember(Name = "timestamp", Order = 2, EmitDefaultValue = false)] public DateTime? Timestamp { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/CertificateStoreName.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// The types of certificate stores /// [DataContract] public enum CertificateStoreName { /// /// Own store /// [EnumMember(Value = "Application")] Application, /// /// Rejected store /// [EnumMember(Value = "Rejected")] Rejected, /// /// Trusted store /// [EnumMember(Value = "Trusted")] Trusted, /// /// Https certificates /// [EnumMember(Value = "Https")] Https, /// /// User store /// [EnumMember(Value = "User")] User, /// /// Opc Ua certificate issuer store /// [EnumMember(Value = "Issuer")] Issuer, /// /// Https certificate issuer store /// [EnumMember(Value = "HttpsIssuer")] HttpsIssuer, /// /// User issuer store /// [EnumMember(Value = "UserIssuer")] UserIssuer, } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ChannelDiagnosticModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Channel diagnostics model /// [DataContract] public record class ChannelDiagnosticModel { /// /// Timestamp of the diagnostic information /// [DataMember(Name = "timeStamp", Order = 1)] public required DateTimeOffset TimeStamp { get; init; } /// /// The session id if connected. Empty if disconnected. /// [DataMember(Name = "sessionId", Order = 2, EmitDefaultValue = false)] public string? SessionId { get; init; } /// /// When the session was created. /// [DataMember(Name = "sessionCreated", Order = 3, EmitDefaultValue = false)] public DateTimeOffset? SessionCreated { get; init; } /// /// The connection information specified by user. /// [DataMember(Name = "connection", Order = 4)] public required ConnectionModel Connection { get; init; } /// /// Effective remote ip address used for the /// connection if connected. Empty if disconnected. /// [DataMember(Name = "remoteIpAddress", Order = 5, EmitDefaultValue = false)] public string? RemoteIpAddress { get; init; } /// /// The effective remote port used when connected, /// null if disconnected. /// [DataMember(Name = "remotePort", Order = 6, EmitDefaultValue = false)] public int? RemotePort { get; init; } /// /// Effective local ip address used for the connection /// if connected. Empty if disconnected. /// [DataMember(Name = "localIpAddress", Order = 7, EmitDefaultValue = false)] public string? LocalIpAddress { get; init; } /// /// The effective local port used when connected, /// null if disconnected. /// [DataMember(Name = "localPort", Order = 8, EmitDefaultValue = false)] public int? LocalPort { get; init; } /// /// The id assigned to the channel that the token /// belongs to. /// [DataMember(Name = "channelId", Order = 9, EmitDefaultValue = false)] public uint? ChannelId { get; init; } /// /// The id assigned to the token. /// [DataMember(Name = "tokenId", Order = 10, EmitDefaultValue = false)] public uint? TokenId { get; init; } /// /// When the token was created by the server /// (refers to the server's clock). /// [DataMember(Name = "createdAt", Order = 11, EmitDefaultValue = false)] public DateTime? CreatedAt { get; init; } /// /// The lifetime of the token /// [DataMember(Name = "lifetime", Order = 12, EmitDefaultValue = false)] public TimeSpan? Lifetime { get; init; } /// /// Client keys /// [DataMember(Name = "client", Order = 13, EmitDefaultValue = false)] public ChannelKeyModel? Client { get; init; } /// /// Server keys /// [DataMember(Name = "server", Order = 14, EmitDefaultValue = false)] public ChannelKeyModel? Server { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ChannelKeyModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Channel token key model. /// [DataContract] public record class ChannelKeyModel { /// /// Iv /// [DataMember(Name = "iv", Order = 0)] public required IReadOnlyList Iv { get; init; } /// /// Key /// [DataMember(Name = "key", Order = 1)] public required IReadOnlyList Key { get; init; } /// /// Signature length /// [DataMember(Name = "sigLen", Order = 2)] public required int SigLen { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ConditionHandlingOptionsModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Condition handling options model /// [DataContract] public sealed record class ConditionHandlingOptionsModel { /// /// Time interval for sending pending interval updates in seconds. /// [DataMember(Name = "updateInterval", Order = 1, EmitDefaultValue = false)] public int? UpdateInterval { get; set; } /// /// Time interval for sending pending interval snapshot in seconds. /// [DataMember(Name = "snapshotInterval", Order = 2, EmitDefaultValue = false)] public int? SnapshotInterval { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ConnectionDiagnosticsModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Connection diagnostics /// [DataContract] public record class ConnectionDiagnosticsModel { /// /// The connection information specified by user. /// [DataMember(Name = "connection", Order = 0)] public required ConnectionModel Connection { get; init; } /// /// The session and subscriptions diagnostics from /// the server. /// [DataMember(Name = "server", Order = 1, EmitDefaultValue = false)] public SessionDiagnosticsModel? Server { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ConnectionModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Connection model /// [DataContract] public sealed record class ConnectionModel { /// /// Endpoint information /// [DataMember(Name = "endpoint", Order = 0)] [Required] public required EndpointModel Endpoint { get; set; } /// /// User /// [DataMember(Name = "user", Order = 1, EmitDefaultValue = false)] public CredentialModel? User { get; set; } /// /// Diagnostics configuration /// [DataMember(Name = "diagnostics", Order = 2, EmitDefaultValue = false)] public DiagnosticsModel? Diagnostics { get; set; } /// /// Connection group allows splitting connections /// per purpose. /// [DataMember(Name = "group", Order = 3, EmitDefaultValue = false)] public string? Group { get; set; } /// /// Optional list of preferred locales in preference order. /// [DataMember(Name = "locales", Order = 4, EmitDefaultValue = false)] public IReadOnlyList? Locales { get; set; } /// /// Connection options to apply to the created /// connection. /// [DataMember(Name = "options", Order = 5, EmitDefaultValue = false)] public ConnectionOptions Options { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ConnectionOptions.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Options that can be applied to a connection /// [Flags] [DataContract] public enum ConnectionOptions { /// /// No options /// [EnumMember(Value = "None")] None = 0x0, /// /// Create a reverse connection /// [EnumMember(Value = "UseReverseConnect")] UseReverseConnect = 0x1, /// /// Do not load complex types /// [EnumMember(Value = "NoComplexTypeSystem")] NoComplexTypeSystem = 0x10, /// /// Do not transfer subscription on reconnect /// [EnumMember(Value = "NoSubscriptionTransfer")] NoSubscriptionTransfer = 0x20, /// /// Dump diagnostics on a timer /// [EnumMember(Value = "DumpDiagnostics")] DumpDiagnostics = 0x100 } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/Constants.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa { /// /// Common twin properties /// public static class Constants { /// /// Type property name constant /// public const string TwinPropertyTypeKey = "__type__"; /// /// Site id property name constant /// public const string TwinPropertySiteKey = "__siteid__"; /// /// Semver Version property name constant /// public const string TwinPropertyVersionKey = "__version__"; /// /// Full Version property name constant /// public const string TwinPropertyFullVersionKey = "__fullversion__"; /// /// Scheme property constant /// public const string TwinPropertySchemeKey = "__scheme__"; /// /// Hostname property constant /// public const string TwinPropertyHostnameKey = "__hostname__"; /// /// Adresseses property constant /// public const string TwinPropertyIpAddressesKey = "__ip__"; /// /// Port key constant /// public const string TwinPropertyPortKey = "__port__"; /// /// Spi key property name constant /// public const string TwinPropertyApiKeyKey = "__apikey__"; /// /// Certificate property name constant /// public const string TwinPropertyCertificateKey = "__certificate__"; /// /// Routing info message property /// public const string MessagePropertyRoutingKey = "$$RoutingInfo"; /// /// Routing info message property /// public const string MessagePropertySchemaKey = "$$MessageSchema"; /// /// Gateway identity /// public const string EntityTypeGateway = "iiotedge"; /// /// Publisher module identity /// public const string EntityTypePublisher = "OpcPublisher"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ContentFilterElementModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// An expression element in the filter ast /// [DataContract] public sealed record class ContentFilterElementModel { /// /// The operator to use on the operands /// [DataMember(Name = "filterOperator", Order = 0, EmitDefaultValue = false)] public FilterOperatorType FilterOperator { get; set; } /// /// The operands in the element for the operator /// [DataMember(Name = "filterOperands", Order = 1, EmitDefaultValue = false)] public IReadOnlyList? FilterOperands { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ContentFilterModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Content filter /// [DataContract] public sealed record class ContentFilterModel { /// /// The flat list of elements in the filter AST /// [DataMember(Name = "elements", Order = 0)] public IReadOnlyList? Elements { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/CredentialModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Credential model. For backwards compatibility /// the actual credentials to pass to the server is set /// through the value property. /// [DataContract] public sealed record class CredentialModel { /// /// Type of credential /// [DataMember(Name = "type", Order = 0, EmitDefaultValue = false)] public CredentialType? Type { get; set; } /// /// Credential to pass to server. Can be omitted in case of /// . /// [DataMember(Name = "value", Order = 1, EmitDefaultValue = false)] public UserIdentityModel? Value { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/CredentialType.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Type of credentials to use for authentication /// [DataContract] public enum CredentialType { /// /// No credentials for anonymous access /// [EnumMember(Value = "None")] None, /// /// User name and password as credential /// [EnumMember(Value = "UserName")] UserName, /// /// Credential is a x509 certificate /// [EnumMember(Value = "X509Certificate")] X509Certificate, /// /// Jwt token as credential /// [EnumMember(Value = "JwtToken")] JwtToken } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/DataChangeFilterModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Data change filter /// [DataContract] public sealed record class DataChangeFilterModel { /// /// Data change trigger type /// [DataMember(Name = "dataChangeTrigger", Order = 0, EmitDefaultValue = false)] public DataChangeTriggerType? DataChangeTrigger { get; set; } /// /// Dead band /// [DataMember(Name = "deadbandType", Order = 1, EmitDefaultValue = false)] public DeadbandType? DeadbandType { get; set; } /// /// Dead band value /// [DataMember(Name = "deadbandValue", Order = 2, EmitDefaultValue = false)] public double? DeadbandValue { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/DataChangeTriggerType.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Data change trigger /// [DataContract] public enum DataChangeTriggerType { /// /// Status /// [EnumMember(Value = "Status")] Status, /// /// Status value /// [EnumMember(Value = "StatusValue")] StatusValue, /// /// Status value and timestamp /// [EnumMember(Value = "StatusValueTimestamp")] StatusValueTimestamp } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/DataLocation.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Indicate the data location /// [DataContract] public enum DataLocation { /// /// A raw data value. /// [EnumMember(Value = "Raw")] Raw = 0, /// /// Calculated data /// [EnumMember(Value = "Calculated")] Calculated = 1, /// /// A data value which was interpolated. /// [EnumMember(Value = "Interpolated")] Interpolated = 2, } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/DataSetFieldContentFlags.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Content for dataset field /// [Flags] [DataContract] public enum DataSetFieldContentFlags { /// /// Status code /// [EnumMember(Value = "StatusCode")] StatusCode = 0x1, /// /// Source timestamp /// [EnumMember(Value = "SourceTimestamp")] SourceTimestamp = 0x2, /// /// Server timestamp /// [EnumMember(Value = "ServerTimestamp")] ServerTimestamp = 0x4, /// /// Source picoseconds /// [EnumMember(Value = "SourcePicoSeconds")] SourcePicoSeconds = 0x8, /// /// Server picoseconds /// [EnumMember(Value = "ServerPicoSeconds")] ServerPicoSeconds = 0x10, /// /// Raw value /// [EnumMember(Value = "RawData")] RawData = 0x20, /// /// Write data set with one entry as value /// [EnumMember(Value = "SingleFieldDegradeToValue")] SingleFieldDegradeToValue = 0x1000, /// /// Node id included /// [EnumMember(Value = "NodeId")] NodeId = 0x10000, /// /// Display name included /// [EnumMember(Value = "DisplayName")] DisplayName = 0x20000, /// /// Endpoint url included /// [EnumMember(Value = "EndpointUrl")] EndpointUrl = 0x40000, /// /// Application uri /// [EnumMember(Value = "ApplicationUri")] ApplicationUri = 0x80000, /// /// Subscription id included /// [EnumMember(Value = "SubscriptionId")] SubscriptionId = 0x100000, /// /// Extension fields included /// [EnumMember(Value = "ExtensionFields")] ExtensionFields = 0x200000 } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/DataSetMessageContentFlags.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Data set message content /// [DataContract] [Flags] public enum DataSetMessageContentFlags { /// /// Timestamp /// [EnumMember(Value = "Timestamp")] Timestamp = 0x1, /// /// Picoseconds (uadp) /// [EnumMember(Value = "PicoSeconds")] PicoSeconds = 0x2, /// /// Metadata version (json) /// [EnumMember(Value = "MetaDataVersion")] MetaDataVersion = 0x4, /// /// Status /// [EnumMember(Value = "Status")] Status = 0x8, /// /// Dataset writer id (json) /// [EnumMember(Value = "DataSetWriterId")] DataSetWriterId = 0x10, /// /// Major version (uadp) /// [EnumMember(Value = "MajorVersion")] MajorVersion = 0x20, /// /// Minor version (uadp) /// [EnumMember(Value = "MinorVersion")] MinorVersion = 0x40, /// /// Sequence number /// [EnumMember(Value = "SequenceNumber")] SequenceNumber = 0x80, /// /// Default Uadp /// [EnumMember(Value = "DefaultUadp")] DefaultUadp = SequenceNumber | DataSetWriterId | Timestamp | MajorVersion | MinorVersion | Status | PicoSeconds, /// /// Message type (json) /// [EnumMember(Value = "MessageType")] MessageType = 0x100, /// /// Dataset writer name (json) /// [EnumMember(Value = "DataSetWriterName")] DataSetWriterName = 0x200, /// /// Default non-reversible json /// [EnumMember(Value = "DefaultJson")] DefaultJson = MessageType | DataSetWriterName | SequenceNumber | DataSetWriterId | Timestamp | MetaDataVersion | Status, /// /// Reversible encoding (json) /// [EnumMember(Value = "ReversibleFieldEncoding")] ReversibleFieldEncoding = 0x400, } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/DataSetMetaDataModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Metadata for the published dataset /// [DataContract] public sealed record class DataSetMetaDataModel { /// /// Name of the dataset /// [DataMember(Name = "name", Order = 0, EmitDefaultValue = false)] public string? Name { get; set; } /// /// Dataset class id /// [DataMember(Name = "dataSetClassId", Order = 3, EmitDefaultValue = false)] public Guid DataSetClassId { get; set; } /// /// Description of the dataset /// [DataMember(Name = "description", Order = 4, EmitDefaultValue = false)] public string? Description { get; set; } /// /// Major version /// [DataMember(Name = "majorVersion", Order = 5, EmitDefaultValue = false)] public uint? MajorVersion { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/DataSetOrderingType.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Ordering model /// [DataContract] public enum DataSetOrderingType { /// /// None /// None = 0, /// /// Ascending writer id /// [EnumMember(Value = "AscendingWriterId")] AscendingWriterId = 1, /// /// Single /// [EnumMember(Value = "AscendingWriterIdSingle")] AscendingWriterIdSingle = 2, } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/DataSetRoutingMode.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Specifies how OPC UA node paths are mapped to message routing paths/topics. /// Controls automatic topic structure generation from OPC UA address space. /// Used to create a unified namespace when publishing to message brokers /// that support hierarchical routing like MQTT. /// [DataContract] public enum DataSetRoutingMode { /// /// Disable automatic topic path generation. /// Uses only explicitly configured topic templates and queue names. /// Provides maximum control over message routing. /// Best when custom routing patterns are required. /// [EnumMember(Value = "None")] None = 0, /// /// Automatically generate topic paths using OPC UA browse names. /// Creates hierarchical paths matching the OPC UA address space structure. /// Makes data organization intuitive and discoverable. /// Example: "Objects/Server/Data/Value1" /// Falls back to configured templates if specified. /// [EnumMember(Value = "UseBrowseNames")] UseBrowseNames = 1, /// /// Generate topic paths using browse names prefixed with namespace index. /// Ensures unique paths when nodes have same names in different namespaces. /// Preserves complete namespace context in the routing path. /// Example: "0:Objects/2:MyDevice/2:Sensors/2:Temperature" /// Falls back to configured templates if specified. /// [EnumMember(Value = "UseBrowseNamesWithNamespaceIndex")] UseBrowseNamesWithNamespaceIndex = 2, } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/DataSetWriterMessageSettingsModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Data set writer message model /// [DataContract] public sealed record class DataSetWriterMessageSettingsModel { /// /// Dataset message content /// [DataMember(Name = "dataSetMessageContentMask", Order = 0, EmitDefaultValue = false)] public DataSetMessageContentFlags? DataSetMessageContentMask { get; set; } /// /// Configured size of network message /// [DataMember(Name = "configuredSize", Order = 1, EmitDefaultValue = false)] public ushort? ConfiguredSize { get; set; } /// /// Uadp metwork message number /// [DataMember(Name = "networkMessageNumber", Order = 2, EmitDefaultValue = false)] public ushort? NetworkMessageNumber { get; set; } /// /// Uadp dataset offset /// [DataMember(Name = "dataSetOffset", Order = 3, EmitDefaultValue = false)] public ushort? DataSetOffset { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/DataSetWriterModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Data set writer description /// [DataContract] public sealed record class DataSetWriterModel { /// /// Dataset writer identifier. /// [DataMember(Name = "id", Order = 0)] public required string Id { get; set; } /// /// Published dataset inline definition /// [DataMember(Name = "dataSet", Order = 1, EmitDefaultValue = false)] public PublishedDataSetModel? DataSet { get; set; } /// /// Dataset field content mask /// [DataMember(Name = "dataSetFieldContentMask", Order = 2, EmitDefaultValue = false)] public DataSetFieldContentFlags? DataSetFieldContentMask { get; set; } /// /// Data set message settings /// [DataMember(Name = "messageSettings", Order = 3, EmitDefaultValue = false)] public DataSetWriterMessageSettingsModel? MessageSettings { get; set; } /// /// Keyframe count /// [DataMember(Name = "keyFrameCount", Order = 4, EmitDefaultValue = false)] public uint? KeyFrameCount { get; set; } /// /// Dataset writer name. /// [DataMember(Name = "dataSetWriterName", Order = 5)] public string? DataSetWriterName { get; set; } /// /// Metadata message sending interval /// [DataMember(Name = "metaDataUpdateTime", Order = 6, EmitDefaultValue = false)] public TimeSpan? MetaDataUpdateTime { get; set; } /// /// Metadata queue settings the writer should use to publish /// metadata messages to. /// [DataMember(Name = "metaData", Order = 7, EmitDefaultValue = false)] public PublishingQueueSettingsModel? MetaData { get; set; } /// /// Queue settings writer should use to publish messages /// to. Overrides the writer group queue settings. /// (Publisher extension) /// [DataMember(Name = "publishing", Order = 8, EmitDefaultValue = false)] public PublishingQueueSettingsModel? Publishing { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/DataTypeMetadataModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Data type metadata model /// [DataContract] public sealed record class DataTypeMetadataModel { /// /// The data type for the instance declaration. /// [DataMember(Name = "dataType", Order = 0, EmitDefaultValue = false)] public string? DataType { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/DeadbandType.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Deadband type /// [DataContract] public enum DeadbandType { /// /// Absolute /// [EnumMember(Value = "Absolute")] Absolute, /// /// Percentage /// [EnumMember(Value = "Percent")] Percent } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/DeleteEventsDetailsModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// The events to delete /// [DataContract] public sealed record class DeleteEventsDetailsModel { /// /// Events to delete /// [DataMember(Name = "eventIds", Order = 0)] [Required] public required IReadOnlyList EventIds { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/DeleteValuesAtTimesDetailsModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Deletes data at times /// [DataContract] public sealed record class DeleteValuesAtTimesDetailsModel { /// /// The timestamps to delete /// [DataMember(Name = "reqTimes", Order = 0)] [Required] public required IReadOnlyList ReqTimes { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/DeleteValuesDetailsModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Delete values /// [DataContract] public sealed record class DeleteValuesDetailsModel { /// /// Start time /// [DataMember(Name = "startTime", Order = 0, EmitDefaultValue = false)] public DateTime? StartTime { get; set; } /// /// End time to delete until /// [DataMember(Name = "endTime", Order = 1, EmitDefaultValue = false)] public DateTime? EndTime { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/DiagnosticsLevel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Level of diagnostics requested in responses /// [DataContract] public enum DiagnosticsLevel { /// /// Include no diagnostics in response /// [EnumMember(Value = "None")] None = 0, /// /// Include status and symbol text (default) /// [EnumMember(Value = "Status")] Status = 1, /// /// Include additional information /// [EnumMember(Value = "Information")] Information = 10, /// /// Include inner diagnostics for tracing /// [EnumMember(Value = "Debug")] Debug = 50, /// /// Include full diagnostics trace. /// [EnumMember(Value = "Verbose")] Verbose = 100 } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/DiagnosticsModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Diagnostics configuration /// [DataContract] public sealed record class DiagnosticsModel { /// /// Requested level of response diagnostics. /// (default: None) /// [DataMember(Name = "level", Order = 0, EmitDefaultValue = false)] public DiagnosticsLevel? Level { get; set; } /// /// Client audit log entry. /// (default: client generated) /// [DataMember(Name = "auditId", Order = 1, EmitDefaultValue = false)] public string? AuditId { get; set; } /// /// Timestamp of request. /// (default: client generated) /// [DataMember(Name = "timeStamp", Order = 2, EmitDefaultValue = false)] public DateTime? TimeStamp { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/DiscoveryCancelRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Discovery cancel request /// [DataContract] public sealed record class DiscoveryCancelRequestModel { /// /// Id of discovery request /// [DataMember(Name = "id", Order = 0, EmitDefaultValue = false)] public string? Id { get; set; } /// /// Operation audit context /// [DataMember(Name = "context", Order = 1, EmitDefaultValue = false)] public OperationContextModel? Context { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/DiscoveryConfigModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Collections.Generic; using System.Runtime.Serialization; /// /// Discovery configuration api model /// [DataContract] public sealed record class DiscoveryConfigModel { /// /// Address ranges to scan (null == all wired nics) /// [DataMember(Name = "addressRangesToScan", Order = 0, EmitDefaultValue = false)] public string? AddressRangesToScan { get; set; } /// /// Network probe timeout /// [DataMember(Name = "networkProbeTimeout", Order = 1, EmitDefaultValue = false)] public TimeSpan? NetworkProbeTimeout { get; set; } /// /// Max network probes that should ever run. /// [DataMember(Name = "maxNetworkProbes", Order = 2, EmitDefaultValue = false)] public int? MaxNetworkProbes { get; set; } /// /// Port ranges to scan (null == all unassigned) /// [DataMember(Name = "portRangesToScan", Order = 3, EmitDefaultValue = false)] public string? PortRangesToScan { get; set; } /// /// Port probe timeout /// [DataMember(Name = "portProbeTimeout", Order = 4, EmitDefaultValue = false)] public TimeSpan? PortProbeTimeout { get; set; } /// /// Max port probes that should ever run. /// [DataMember(Name = "maxPortProbes", Order = 5, EmitDefaultValue = false)] public int? MaxPortProbes { get; set; } /// /// Probes that must always be there as percent of max. /// [DataMember(Name = "minPortProbesPercent", Order = 6, EmitDefaultValue = false)] public int? MinPortProbesPercent { get; set; } /// /// Delay time between discovery sweeps /// [DataMember(Name = "idleTimeBetweenScans", Order = 7, EmitDefaultValue = false)] public TimeSpan? IdleTimeBetweenScans { get; set; } /// /// List of preset discovery urls to use /// [DataMember(Name = "discoveryUrls", Order = 8, EmitDefaultValue = false)] public IReadOnlyList? DiscoveryUrls { get; set; } /// /// List of locales to filter with during discovery /// [DataMember(Name = "locales", Order = 9, EmitDefaultValue = false)] public IReadOnlyList? Locales { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/DiscoveryEventModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; /// /// One of n events with the discovered application info /// public sealed record class DiscoveryEventModel { /// /// Timestamp of the discovery sweep. /// public DateTimeOffset TimeStamp { get; set; } /// /// Index in the batch with same timestamp. /// public int Index { get; set; } /// /// Discovered endpoint in form of endpoint registration /// public EndpointRegistrationModel? Registration { get; set; } /// /// Application to which this endpoint belongs /// public ApplicationInfoModel? Application { get; set; } /// /// Discovery result summary on last element /// public DiscoveryResultModel? Result { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/DiscoveryMode.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Discovery mode to use /// [DataContract] public enum DiscoveryMode { /// /// No discovery /// [EnumMember(Value = "Off")] Off, /// /// Find and use local discovery server on edge device /// [EnumMember(Value = "Local")] Local, /// /// Find and use all LDS in all connected networks /// [EnumMember(Value = "Network")] Network, /// /// Fast network scan of */24 and known list of ports /// [EnumMember(Value = "Fast")] Fast, /// /// Perform a deep scan of all networks. /// [EnumMember(Value = "Scan")] Scan } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/DiscoveryProgressModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Collections.Generic; using System.Runtime.Serialization; /// /// Discovery progress /// [DataContract] public sealed record class DiscoveryProgressModel { /// /// Id of discovery request /// [DataMember(Name = "requestId", Order = 0, EmitDefaultValue = false)] public string? RequestId { get; set; } /// /// Event type /// [DataMember(Name = "eventType", Order = 1)] public DiscoveryProgressType EventType { get; set; } /// /// Discoverer that registered the application /// [DataMember(Name = "discovererId", Order = 2, EmitDefaultValue = false)] public string? DiscovererId { get; set; } /// /// Additional request information as per event /// [DataMember(Name = "requestDetails", Order = 3, EmitDefaultValue = false)] public IReadOnlyDictionary? RequestDetails { get; set; } /// /// Timestamp of the message /// [DataMember(Name = "timeStamp", Order = 4)] public DateTimeOffset TimeStamp { get; set; } /// /// Number of workers running /// [DataMember(Name = "workers", Order = 5, EmitDefaultValue = false)] public int? Workers { get; set; } /// /// Progress /// [DataMember(Name = "progress", Order = 6, EmitDefaultValue = false)] public int? Progress { get; set; } /// /// Total /// [DataMember(Name = "total", Order = 7, EmitDefaultValue = false)] public int? Total { get; set; } /// /// Number of items discovered /// [DataMember(Name = "discovered", Order = 8, EmitDefaultValue = false)] public int? Discovered { get; set; } /// /// Discovery result /// [DataMember(Name = "result", Order = 9, EmitDefaultValue = false)] public string? Result { get; set; } /// /// Discovery result details /// [DataMember(Name = "resultDetails", Order = 10, EmitDefaultValue = false)] public IReadOnlyDictionary? ResultDetails { get; set; } /// /// Discovery request /// [DataMember(Name = "request", Order = 11, EmitDefaultValue = false)] public required DiscoveryRequestModel Request { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/DiscoveryProgressType.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Discovery progress event type /// [DataContract] public enum DiscoveryProgressType { /// /// Discovery run pending /// [EnumMember(Value = "Pending")] Pending, /// /// Discovery run started /// [EnumMember(Value = "Started")] Started, /// /// Discovery was cancelled /// [EnumMember(Value = "Cancelled")] Cancelled, /// /// Discovery resulted in error /// [EnumMember(Value = "Error")] Error, /// /// Discovery finished /// [EnumMember(Value = "Finished")] Finished, /// /// Network scanning started /// [EnumMember(Value = "NetworkScanStarted")] NetworkScanStarted, /// /// Network scanning result /// [EnumMember(Value = "NetworkScanResult")] NetworkScanResult, /// /// Network scan progress /// [EnumMember(Value = "NetworkScanProgress")] NetworkScanProgress, /// /// Network scan finished /// [EnumMember(Value = "NetworkScanFinished")] NetworkScanFinished, /// /// Port scan started /// [EnumMember(Value = "PortScanStarted")] PortScanStarted, /// /// Port scan result /// [EnumMember(Value = "PortScanResult")] PortScanResult, /// /// Port scan progress /// [EnumMember(Value = "PortScanProgress")] PortScanProgress, /// /// Port scan finished /// [EnumMember(Value = "PortScanFinished")] PortScanFinished, /// /// Server discovery started /// [EnumMember(Value = "ServerDiscoveryStarted")] ServerDiscoveryStarted, /// /// Endpoint discovery started /// [EnumMember(Value = "EndpointsDiscoveryStarted")] EndpointsDiscoveryStarted, /// /// Endpoint discovery finished /// [EnumMember(Value = "EndpointsDiscoveryFinished")] EndpointsDiscoveryFinished, /// /// Server discovery finished /// [EnumMember(Value = "ServerDiscoveryFinished")] ServerDiscoveryFinished, } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/DiscoveryRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Discovery request /// [DataContract] public sealed record class DiscoveryRequestModel { /// /// Id of discovery request /// [DataMember(Name = "id", Order = 0, EmitDefaultValue = false)] public string? Id { get; set; } /// /// Discovery mode to use /// [DataMember(Name = "discovery", Order = 1, EmitDefaultValue = false)] public DiscoveryMode? Discovery { get; set; } /// /// Scan configuration to use /// [DataMember(Name = "configuration", Order = 2, EmitDefaultValue = false)] public DiscoveryConfigModel? Configuration { get; set; } /// /// Operation audit context /// [DataMember(Name = "context", Order = 3, EmitDefaultValue = false)] public OperationContextModel? Context { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/DiscoveryResultModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Furly.Extensions.Serializers; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Result of a discovery run - part of last event element /// in batch /// [DataContract] public sealed record class DiscoveryResultModel { /// /// Id of discovery request /// [DataMember(Name = "id", Order = 0, EmitDefaultValue = false)] public string? Id { get; set; } /// /// Configuration used during discovery /// [DataMember(Name = "discoveryConfig", Order = 1, EmitDefaultValue = false)] public DiscoveryConfigModel? DiscoveryConfig { get; set; } /// /// If true, only register, do not unregister based /// on these events. /// [DataMember(Name = "registerOnly", Order = 2, EmitDefaultValue = false)] public bool? RegisterOnly { get; set; } /// /// If discovery failed, result information /// [DataMember(Name = "diagnostics", Order = 3, EmitDefaultValue = false)] [SkipValidation] public VariantValue? Diagnostics { get; set; } /// /// Operation audit context /// [DataMember(Name = "context", Order = 4, EmitDefaultValue = false)] public OperationContextModel? Context { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/EndpointConnectivityState.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// State of the endpoint after activation /// [DataContract] public enum EndpointConnectivityState { /// /// Client connecting to endpoint /// [EnumMember(Value = "Connecting")] Connecting, /// /// Server not reachable /// [EnumMember(Value = "NotReachable")] NotReachable, /// /// Server busy - try later /// [EnumMember(Value = "Busy")] Busy, /// /// Client is not trusted - update client cert /// [EnumMember(Value = "NoTrust")] NoTrust, /// /// Server certificate is invalid - update server certificate /// [EnumMember(Value = "CertificateInvalid")] CertificateInvalid, /// /// Connected and ready /// [EnumMember(Value = "Ready")] Ready, /// /// Any other connection error /// [EnumMember(Value = "Error")] Error, /// /// Client disconnected /// [EnumMember(Value = "Disconnected")] Disconnected, /// /// User is not authorized to connect. /// [EnumMember(Value = "Unauthorized")] Unauthorized } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/EndpointEventModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Endpoint Event model /// [DataContract] public sealed record class EndpointEventModel { /// /// Type of event /// [DataMember(Name = "eventType", Order = 0)] public EndpointEventType EventType { get; set; } /// /// Endpoint id /// [DataMember(Name = "id", Order = 1, EmitDefaultValue = false)] public string? Id { get; set; } /// /// Endpoint info /// [DataMember(Name = "endpoint", Order = 2)] public required EndpointInfoModel Endpoint { get; set; } /// /// Context /// [DataMember(Name = "context", Order = 3, EmitDefaultValue = false)] public OperationContextModel? Context { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/EndpointEventType.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Activation state of the endpoint twin /// [DataContract] public enum EndpointEventType { /// /// New /// [EnumMember(Value = "New")] New, /// /// Enabled /// [EnumMember(Value = "Enabled")] Enabled, /// /// Disabled /// [EnumMember(Value = "Disabled")] Disabled, /// /// Deleted /// [EnumMember(Value = "Deleted")] Deleted, } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/EndpointInfoModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Endpoint info /// [DataContract] public sealed record class EndpointInfoModel { /// /// Endpoint registration /// [DataMember(Name = "registration", Order = 0)] [Required] public required EndpointRegistrationModel Registration { get; set; } /// /// Application id endpoint is registered under. /// [DataMember(Name = "applicationId", Order = 1)] [Required] public required string ApplicationId { get; set; } /// /// Last state of the endpoint /// [DataMember(Name = "endpointState", Order = 3, EmitDefaultValue = false)] public EndpointConnectivityState? EndpointState { get; set; } /// /// Last time endpoint was seen /// [DataMember(Name = "notSeenSince", Order = 5, EmitDefaultValue = false)] public DateTimeOffset? NotSeenSince { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/EndpointModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Endpoint model /// [DataContract] public sealed record class EndpointModel { /// /// Endpoint url to use to connect with /// [DataMember(Name = "url", Order = 0)] [Required] public required string Url { get; set; } /// /// Alternative endpoint urls that can be used for /// accessing and validating the server /// [DataMember(Name = "alternativeUrls", Order = 1, EmitDefaultValue = false)] public IReadOnlySet? AlternativeUrls { get; set; } /// /// Security Mode to use for communication. /// default to best. /// [DataMember(Name = "securityMode", Order = 2, EmitDefaultValue = false)] public SecurityMode? SecurityMode { get; set; } /// /// Security policy uri to use for communication. /// default to best. /// [DataMember(Name = "securityPolicy", Order = 3, EmitDefaultValue = false)] public string? SecurityPolicy { get; set; } /// /// Endpoint certificate thumbprint /// [DataMember(Name = "certificate", Order = 4, EmitDefaultValue = false)] public string? Certificate { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/EndpointRegistrationModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Endpoint registration /// [DataContract] public sealed record class EndpointRegistrationModel { /// /// Endpoint identifier which is hashed from /// the supervisor, site and url. /// [DataMember(Name = "id", Order = 0)] [Required] public required string Id { get; set; } /// /// Original endpoint url of the endpoint /// [DataMember(Name = "endpointUrl", Order = 1, EmitDefaultValue = false)] public string? EndpointUrl { get; set; } /// /// Registered site of the endpoint /// [DataMember(Name = "siteId", Order = 2, EmitDefaultValue = false)] public string? SiteId { get; set; } /// /// Entity that registered and can access the endpoint /// [DataMember(Name = "discovererId", Order = 4, EmitDefaultValue = false)] public string? DiscovererId { get; set; } /// /// Endpoint information of the registration /// [DataMember(Name = "endpoint", Order = 5)] public EndpointModel? Endpoint { get; set; } /// /// Security level of the endpoint /// [DataMember(Name = "securityLevel", Order = 6, EmitDefaultValue = false)] public int? SecurityLevel { get; set; } /// /// Supported authentication methods that can be selected to /// obtain a credential and used to interact with the endpoint. /// [DataMember(Name = "authenticationMethods", Order = 7, EmitDefaultValue = false)] public IReadOnlyList? AuthenticationMethods { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/EnumDescriptionModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Enum type schema /// [DataContract] public record class EnumDescriptionModel { /// /// Data type identifier /// [DataMember(Name = "dataTypeId", Order = 1)] public required string DataTypeId { get; set; } /// /// Name of the type /// [DataMember(Name = "name", Order = 2)] public required string Name { get; set; } /// /// Fields of the enum /// [DataMember(Name = "fields", Order = 3)] public required IReadOnlyList Fields { get; set; } /// /// Underlying built in type of the enum. /// Default is integer. /// [DataMember(Name = "builtInType", Order = 4, EmitDefaultValue = false)] public byte? BuiltInType { get; set; } /// /// This is an option set and represents bit flags. /// [DataMember(Name = "isOptionSet", Order = 5, EmitDefaultValue = false)] public bool IsOptionSet { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/EnumFieldDescriptionModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Enum description field /// [DataContract] public record class EnumFieldDescriptionModel { /// /// Name of the type /// [DataMember(Name = "name", Order = 1)] public required string Name { get; set; } /// /// Value of the field in the enum /// [DataMember(Name = "value", Order = 2)] public long Value { get; set; } /// /// Name to display to user /// [DataMember(Name = "displayName", Order = 3, EmitDefaultValue = false)] public string? DisplayName { get; set; } /// /// Description /// [DataMember(Name = "description", Order = 4, EmitDefaultValue = false)] public string? Description { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/EventFilterModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Event filter /// [DataContract] public sealed record class EventFilterModel { /// /// Select clauses /// [DataMember(Name = "selectClauses", Order = 0, EmitDefaultValue = false)] public IReadOnlyList? SelectClauses { get; set; } /// /// Where clause /// [DataMember(Name = "whereClause", Order = 1, EmitDefaultValue = false)] public ContentFilterModel? WhereClause { get; set; } /// /// Simple event Type definition node id /// [DataMember(Name = "typeDefinitionId", Order = 3, EmitDefaultValue = false)] public string? TypeDefinitionId { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ExceptionDeviationType.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Exception deviation type /// [DataContract] public enum ExceptionDeviationType { /// /// Absolute value /// [EnumMember(Value = "AbsoluteValue")] AbsoluteValue, /// /// Percent of value /// [EnumMember(Value = "PercentOfValue")] PercentOfValue, /// /// Percent of a range /// [EnumMember(Value = "PercentOfRange")] PercentOfRange, /// /// Percent of range /// [EnumMember(Value = "PercentOfEURange")] PercentOfEURange } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ExtensionFieldModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Furly.Extensions.Serializers; using System; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Extension fields /// [DataContract] public record ExtensionFieldModel { /// /// Field name or display name of the published variable /// [DataMember(Name = "dataSetFieldName", Order = 1, EmitDefaultValue = false)] public required string DataSetFieldName { get; init; } /// /// Name of the published dataset /// [DataMember(Name = "value", Order = 2, EmitDefaultValue = false)] [SkipValidation] public required VariantValue Value { get; init; } /// /// Identifier of field in the dataset class. /// [DataMember(Name = "dataSetClassFieldId", Order = 3, EmitDefaultValue = false)] public Guid DataSetClassFieldId { get; init; } /// /// Description for the field as it should show up in /// the data set meta data. /// [DataMember(Name = "dataSetFieldDescription", Order = 4, EmitDefaultValue = false)] public string? DataSetFieldDescription { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/FileInfoModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// File info /// [DataContract] public record FileInfoModel { /// /// The size of the file in Bytes. When a file is /// currently opened for write, the size might not be /// accurate or available. /// [DataMember(Name = "size", Order = 0, EmitDefaultValue = false)] public long? Size { get; init; } /// /// Whether the file is writable. /// [DataMember(Name = "writable", Order = 1, EmitDefaultValue = false)] public bool Writable { get; init; } /// /// The number of currently valid file handles on /// the file. /// [DataMember(Name = "openCount", Order = 2, EmitDefaultValue = false)] public ushort OpenCount { get; init; } /// /// The media type of the file based on RFC 2046. /// [DataMember(Name = "mimeType", Order = 3, EmitDefaultValue = false)] public string? MimeType { get; init; } /// /// The maximum number of bytes of /// the read and write buffers. /// [DataMember(Name = "maxBufferSize", Order = 4, EmitDefaultValue = false)] public uint? MaxBufferSize { get; init; } /// /// The time the file was last modified. /// [DataMember(Name = "lastModified", Order = 5, EmitDefaultValue = false)] public DateTime? LastModified { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/FileOpenWriteOptionsModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// File open for write options /// [DataContract] public record FileOpenWriteOptionsModel { /// /// The write mode to use when writing to the file. /// The default mode is "Create", erasing the file /// if it exists and writing a new one. /// [DataMember(Name = "mode", Order = 1, EmitDefaultValue = false)] public FileWriteMode Mode { get; init; } /// /// Optional method to call to close and commit the /// file after writing is done. Many file types require /// to call a special method when closing to make the /// content persist, e.g., during device or software /// update or when uploding configuration. The method /// id is specific to the file type opened. /// [DataMember(Name = "closeMethodId", Order = 2, EmitDefaultValue = false)] public string? CloseAndCommitMethodId { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/FileSystemObjectModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// File system object model /// [DataContract] public record FileSystemObjectModel { /// /// The node id of the filesystem object /// [DataMember(Name = "nodeId", Order = 0, EmitDefaultValue = false)] public string? NodeId { get; init; } /// /// The browse path to the filesystem object /// [DataMember(Name = "browsePath", Order = 1, EmitDefaultValue = false)] public IReadOnlyList? BrowsePath { get; init; } /// /// The name of the filesystem object /// [DataMember(Name = "name", Order = 2, EmitDefaultValue = false)] public string? Name { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/FileWriteMode.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// File write mode /// [DataContract] public enum FileWriteMode { /// /// The existing content of the file is erased. /// [EnumMember(Value = "Create")] Create, /// /// The file is opened for writing. /// [EnumMember(Value = "Write")] Write, /// /// The file is opened and positioned /// at end of the file /// [EnumMember(Value = "Append")] Append } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/FilterOperandModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Furly.Extensions.Serializers; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Filter operand /// [DataContract] public sealed record class FilterOperandModel { /// /// Element reference in the outer list if /// operand is an element operand /// [DataMember(Name = "index", Order = 0, EmitDefaultValue = false)] public uint? Index { get; set; } /// /// Variant value if operand is a literal /// [DataMember(Name = "value", Order = 1, EmitDefaultValue = false)] [SkipValidation] public VariantValue? Value { get; set; } /// /// Type definition node id if operand is /// simple or full attribute operand. /// [DataMember(Name = "nodeId", Order = 2, EmitDefaultValue = false)] public string? NodeId { get; set; } /// /// Browse path of attribute operand /// [DataMember(Name = "browsePath", Order = 3, EmitDefaultValue = false)] public IReadOnlyList? BrowsePath { get; set; } /// /// Attribute id /// [DataMember(Name = "attributeId", Order = 4, EmitDefaultValue = false)] public NodeAttribute? AttributeId { get; set; } /// /// Index range of attribute operand /// [DataMember(Name = "indexRange", Order = 5, EmitDefaultValue = false)] public string? IndexRange { get; set; } /// /// Optional alias to refer to it makeing it a /// full blown attribute operand /// [DataMember(Name = "alias", Order = 6, EmitDefaultValue = false)] public string? Alias { get; set; } /// /// Data type if operand is a literal /// [DataMember(Name = "dataType", Order = 7, EmitDefaultValue = false)] public string? DataType { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/FilterOperatorType.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Filter operator type /// [DataContract] public enum FilterOperatorType { /// /// Equals /// [EnumMember(Value = "Equals")] Equals, /// /// Element == null /// [EnumMember(Value = "IsNull")] IsNull, /// /// Greater than /// [EnumMember(Value = "GreaterThan")] GreaterThan, /// /// Less than /// [EnumMember(Value = "LessThan")] LessThan, /// /// Greater than or equal /// [EnumMember(Value = "GreaterThanOrEqual")] GreaterThanOrEqual, /// /// Less than or equal /// [EnumMember(Value = "LessThanOrEqual")] LessThanOrEqual, /// /// String match /// [EnumMember(Value = "Like")] Like, /// /// Logical not /// [EnumMember(Value = "Not")] Not, /// /// Between /// [EnumMember(Value = "Between")] Between, /// /// In list /// [EnumMember(Value = "InList")] InList, /// /// Logical And /// [EnumMember(Value = "And")] And, /// /// Logical Or /// [EnumMember(Value = "Or")] Or, /// /// Cast /// [EnumMember(Value = "Cast")] Cast, /// /// View scope /// [EnumMember(Value = "InView")] InView, /// /// Type test /// [EnumMember(Value = "OfType")] OfType, /// /// Relationship /// [EnumMember(Value = "RelatedTo")] RelatedTo, /// /// Bitwise and /// [EnumMember(Value = "BitwiseAnd")] BitwiseAnd, /// /// Bitwise or /// [EnumMember(Value = "BitwiseOr")] BitwiseOr } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/GetConfiguredEndpointsRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Get configured endpoints request call /// [DataContract] public sealed record class GetConfiguredEndpointsRequestModel { /// /// Include nodes that make up the configuration /// [DataMember(Name = "includeNodes", Order = 0, EmitDefaultValue = false)] public bool? IncludeNodes { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/GetConfiguredEndpointsResponseModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Result of GetConfiguredEndpoints method call /// [DataContract] public sealed record class GetConfiguredEndpointsResponseModel { /// /// Collection of Endpoints in the configuration /// [DataMember(Name = "endpoints", Order = 0, EmitDefaultValue = false)] public IReadOnlyList? Endpoints { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/GetConfiguredNodesOnEndpointResponseModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Result of GetConfiguredNodesOnEndpoint method call /// [DataContract] public sealed record class GetConfiguredNodesOnEndpointResponseModel { /// /// Collection of Nodes configured for a particular endpoint /// [DataMember(Name = "opcNodes", Order = 0, EmitDefaultValue = false)] public IReadOnlyList? OpcNodes { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/HeartbeatBehavior.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Controls how heartbeat messages are handled for monitored items. /// Heartbeats help maintain awareness of node state and connection health /// even when values don't change. Can be configured globally via the /// --hbb command line option. Works with heartbeat interval settings. /// [DataContract] [Flags] public enum HeartbeatBehavior { /// /// Default behavior that sends last known value when heartbeat triggers. /// Reports exact state regardless of value quality or status. /// Most straightforward option for basic monitoring. /// Value may be bad or uncertain quality. /// [EnumMember(Value = "WatchdogLKV")] WatchdogLKV = 0x0, /// /// Sends only good quality values when heartbeat triggers. /// Ensures reported values meet quality requirements. /// May not reflect actual current state if last good value is old. /// Use when data quality is more important than immediacy. /// [EnumMember(Value = "WatchdogLKG")] WatchdogLKG = 0x1, /// /// Periodically publishes last known value at heartbeat interval. /// Provides regular state updates regardless of value changes. /// Useful for monitoring systems that expect periodic updates. /// Higher bandwidth usage due to regular messages. /// [EnumMember(Value = "PeriodicLKV")] PeriodicLKV = 0x2, /// /// Periodically publishes last good quality value at heartbeat interval. /// Combines periodic updates with quality filtering. /// Ensures regular, quality-checked status updates. /// Best choice for reliable system state monitoring. /// [EnumMember(Value = "PeriodicLKG")] PeriodicLKG = WatchdogLKG | PeriodicLKV, /// /// Like WatchdogLKV but updates timestamps on each heartbeat. /// Helps distinguish between multiple heartbeat messages. /// Useful when downstream systems track value freshness. /// Can be combined with other behaviors using flags. /// [EnumMember(Value = "WatchdogLKVWithUpdatedTimestamps")] WatchdogLKVWithUpdatedTimestamps = 0x4, // Others can be combining Cont, LKG with 0x4 /// /// Records heartbeat events in diagnostics without sending messages. /// Allows monitoring heartbeat behavior without generating traffic. /// Useful for testing and troubleshooting configurations. /// Can be combined with other behaviors using flags. /// [EnumMember(Value = "WatchdogLKVDiagnosticsOnly")] WatchdogLKVDiagnosticsOnly = 0x8, // Others can be combining Cont, LKG with 0x8 /// /// Reserved, do not use /// #pragma warning disable CA1700 // Do not name enum values 'Reserved' Reserved = 0x10, #pragma warning restore CA1700 // Do not name enum values 'Reserved' /// /// Only sends periodic heartbeat messages with last known value. /// Filters out regular value change notifications. /// Reduces message volume in fast-changing nodes. /// Use when only periodic snapshots are needed. /// [EnumMember(Value = "PeriodicLKVDropValue")] PeriodicLKVDropValue = PeriodicLKV | Reserved, /// /// Only sends periodic heartbeat messages with last good value. /// Combines periodic-only updates with quality filtering. /// Most restrictive option for message generation. /// Best for reducing traffic while ensuring quality. /// [EnumMember(Value = "PeriodicLKGDropValue")] PeriodicLKGDropValue = PeriodicLKG | Reserved, } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/HistoricEventModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Furly.Extensions.Serializers; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Historic event /// [DataContract] public sealed record class HistoricEventModel { /// /// The selected fields of the event /// [DataMember(Name = "eventFields", Order = 0)] [SkipValidation] public required IReadOnlyList EventFields { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/HistoricValueModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Furly.Extensions.Serializers; using System; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Historic data /// [DataContract] public sealed record class HistoricValueModel { /// /// The value of data value. /// [DataMember(Name = "value", Order = 0)] [SkipValidation] public VariantValue? Value { get; set; } /// /// Built in data type of the updated values /// [DataMember(Name = "dataType", Order = 1, EmitDefaultValue = false)] public string? DataType { get; set; } /// /// The status code associated with the value. /// [DataMember(Name = "status", Order = 2, EmitDefaultValue = false)] public ServiceResultModel? Status { get; set; } /// /// The source timestamp associated with the value. /// [DataMember(Name = "sourceTimestamp", Order = 3, EmitDefaultValue = false)] public DateTime? SourceTimestamp { get; set; } /// /// Additional resolution for the source timestamp. /// [DataMember(Name = "sourcePicoseconds", Order = 4, EmitDefaultValue = false)] public ushort? SourcePicoseconds { get; set; } /// /// The server timestamp associated with the value. /// [DataMember(Name = "serverTimestamp", Order = 5, EmitDefaultValue = false)] public DateTime? ServerTimestamp { get; set; } /// /// Additional resolution for the server timestamp. /// [DataMember(Name = "serverPicoseconds", Order = 6, EmitDefaultValue = false)] public ushort? ServerPicoseconds { get; set; } /// /// Indicates the location of the data. (Default: raw) /// [DataMember(Name = "dataLocation", Order = 7, EmitDefaultValue = false)] public DataLocation? DataLocation { get; set; } /// /// modification information when reading modifications. /// [DataMember(Name = "modificationInfo", Order = 8, EmitDefaultValue = false)] public ModificationInfoModel? ModificationInfo { get; set; } /// /// History information if any (default: none) /// [DataMember(Name = "additionalData", Order = 9, EmitDefaultValue = false)] public AdditionalData? AdditionalData { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/HistoryConfigurationModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Collections.Generic; using System.Runtime.Serialization; /// /// History configuration /// [DataContract] public sealed record class HistoryConfigurationModel { /// /// specifies whether the historical data was /// collected in such a manner that it should /// be displayed as SlopedInterpolation (sloped /// line between points) or as SteppedInterpolation /// (vertically-connected horizontal lines /// between points) when raw data is examined. /// This Property also effects how some /// Aggregates are calculated /// [DataMember(Name = "stepped", Order = 0, EmitDefaultValue = false)] public bool? Stepped { get; set; } /// /// Human readable string that specifies how /// the value of this HistoricalDataNode is /// calculated /// [DataMember(Name = "definition", Order = 1, EmitDefaultValue = false)] public string? Definition { get; set; } /// /// Specifies the maximum interval between data /// points in the history repository /// regardless of their value change /// [DataMember(Name = "maxTimeInterval", Order = 2, EmitDefaultValue = false)] public TimeSpan? MaxTimeInterval { get; set; } /// /// Specifies the minimum interval between /// data points in the history repository /// regardless of their value change /// [DataMember(Name = "minTimeInterval", Order = 3, EmitDefaultValue = false)] public TimeSpan? MinTimeInterval { get; set; } /// /// Minimum amount that the data for the /// Node shall change in order for the change /// to be reported to the history database /// [DataMember(Name = "exceptionDeviation", Order = 4, EmitDefaultValue = false)] public double? ExceptionDeviation { get; set; } /// /// Specifies how the ExceptionDeviation is /// determined /// [DataMember(Name = "exceptionDeviationType", Order = 5, EmitDefaultValue = false)] public ExceptionDeviationType? ExceptionDeviationType { get; set; } /// /// The date before which there is no data in the /// archive either online or offline /// [DataMember(Name = "startOfArchive", Order = 6, EmitDefaultValue = false)] public DateTime? StartOfArchive { get; set; } /// /// The last date of the archive /// [DataMember(Name = "endOfArchive", Order = 7, EmitDefaultValue = false)] public DateTime? EndOfArchive { get; set; } /// /// Date of the earliest data in the online archive /// [DataMember(Name = "startOfOnlineArchive", Order = 8, EmitDefaultValue = false)] public DateTime? StartOfOnlineArchive { get; set; } /// /// Server supports ServerTimestamps in addition /// to SourceTimestamp /// [DataMember(Name = "serverTimestampSupported", Order = 9, EmitDefaultValue = false)] public bool? ServerTimestampSupported { get; set; } /// /// Aggregate configuration /// [DataMember(Name = "aggregateConfiguration", Order = 10, EmitDefaultValue = false)] public AggregateConfigurationModel? AggregateConfiguration { get; set; } /// /// Allowed aggregate functions /// [DataMember(Name = "aggregateFunctions", Order = 11, EmitDefaultValue = false)] public IReadOnlyDictionary? AggregateFunctions { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/HistoryConfigurationRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Request history configuration /// [DataContract] public sealed record class HistoryConfigurationRequestModel { /// /// Optional request header /// [DataMember(Name = "header", Order = 0, EmitDefaultValue = false)] public RequestHeaderModel? Header { get; set; } /// /// Continuation token to continue reading more /// results. /// [DataMember(Name = "nodeId", Order = 1)] [Required] public required string NodeId { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/HistoryConfigurationResponseModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Response with history configuration /// [DataContract] public sealed record class HistoryConfigurationResponseModel { /// /// History Configuration /// results. /// [DataMember(Name = "configuration", Order = 0)] public HistoryConfigurationModel? Configuration { get; set; } /// /// Service result in case of error /// [DataMember(Name = "errorInfo", Order = 1, EmitDefaultValue = false)] public ServiceResultModel? ErrorInfo { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/HistoryReadNextRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Request node history read continuation /// [DataContract] public sealed record class HistoryReadNextRequestModel { /// /// Continuation token to continue reading more /// results. /// [DataMember(Name = "continuationToken", Order = 0)] [Required] public required string ContinuationToken { get; set; } /// /// Abort reading after this read /// [DataMember(Name = "abort", Order = 1, EmitDefaultValue = false)] public bool? Abort { get; set; } /// /// Optional request header /// [DataMember(Name = "header", Order = 2, EmitDefaultValue = false)] public RequestHeaderModel? Header { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/HistoryReadNextResponseModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// History read continuation result /// /// [DataContract] public sealed record class HistoryReadNextResponseModel where T : class { /// /// History as json encoded extension object /// [DataMember(Name = "history", Order = 0)] public required T? History { get; set; } /// /// Continuation token if more results pending. /// [DataMember(Name = "continuationToken", Order = 1, EmitDefaultValue = false)] public string? ContinuationToken { get; set; } /// /// Service result in case of error /// [DataMember(Name = "errorInfo", Order = 2, EmitDefaultValue = false)] public ServiceResultModel? ErrorInfo { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/HistoryReadRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Request node history read /// /// [DataContract] public sealed record class HistoryReadRequestModel where T : class { /// /// Node to read from (mandatory without browse path) /// [DataMember(Name = "nodeId", Order = 0, EmitDefaultValue = false)] public string? NodeId { get; set; } /// /// An optional path from NodeId instance to /// the actual node. /// [DataMember(Name = "browsePath", Order = 1, EmitDefaultValue = false)] public IReadOnlyList? BrowsePath { get; set; } /// /// The HistoryReadDetailsType extension object /// encoded in json and containing the tunneled /// Historian reader request. /// [DataMember(Name = "details", Order = 2)] [Required] public required T Details { get; set; } /// /// Index range to read, e.g. 1:2,0:1 for 2 slices /// out of a matrix or 0:1 for the first item in /// an array, string or bytestring. /// See 7.22 of part 4: NumericRange. /// [DataMember(Name = "indexRange", Order = 3, EmitDefaultValue = false)] public string? IndexRange { get; set; } /// /// Optional request header /// [DataMember(Name = "header", Order = 4, EmitDefaultValue = false)] public RequestHeaderModel? Header { get; set; } /// /// Decide what timestamps to return. /// [DataMember(Name = "timestampsToReturn", Order = 5, EmitDefaultValue = false)] public TimestampsToReturn? TimestampsToReturn { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/HistoryReadResponseModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// History read results /// /// [DataContract] public sealed record class HistoryReadResponseModel where T : class { /// /// History as json encoded extension object /// [DataMember(Name = "history", Order = 0)] public required T? History { get; set; } /// /// Continuation token if more results pending. /// [DataMember(Name = "continuationToken", Order = 1, EmitDefaultValue = false)] public string? ContinuationToken { get; set; } /// /// Service result in case of error /// [DataMember(Name = "errorInfo", Order = 2, EmitDefaultValue = false)] public ServiceResultModel? ErrorInfo { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/HistoryServerCapabilitiesModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// History Server capabilities /// [DataContract] public sealed record class HistoryServerCapabilitiesModel { /// /// Server supports historic data access /// [DataMember(Name = "supportsHistoricData", Order = 0, EmitDefaultValue = false)] public bool AccessHistoryDataCapability { get; set; } /// /// Server supports historic event access /// [DataMember(Name = "supportsHistoricEvents", Order = 1, EmitDefaultValue = false)] public bool AccessHistoryEventsCapability { get; set; } /// /// Maximum number of historic data values that will /// be returned in a single read. /// [DataMember(Name = "maxReturnDataValues", Order = 2, EmitDefaultValue = false)] public uint? MaxReturnDataValues { get; set; } /// /// Maximum number of events that will be returned /// in a single read. /// [DataMember(Name = "maxReturnEventValues", Order = 3, EmitDefaultValue = false)] public uint? MaxReturnEventValues { get; set; } /// /// Server supports inserting data /// [DataMember(Name = "insertDataCapability", Order = 4, EmitDefaultValue = false)] public bool? InsertDataCapability { get; set; } /// /// Server supports replacing historic data /// [DataMember(Name = "replaceDataCapability", Order = 5, EmitDefaultValue = false)] public bool? ReplaceDataCapability { get; set; } /// /// Server supports updating historic data /// [DataMember(Name = "updateDataCapability", Order = 6, EmitDefaultValue = false)] public bool? UpdateDataCapability { get; set; } /// /// Server supports deleting raw data /// [DataMember(Name = "deleteRawCapability", Order = 7, EmitDefaultValue = false)] public bool? DeleteRawCapability { get; set; } /// /// Server support deleting data at times /// [DataMember(Name = "deleteAtTimeCapability", Order = 8, EmitDefaultValue = false)] public bool? DeleteAtTimeCapability { get; set; } /// /// Server supports inserting events /// [DataMember(Name = "insertEventCapability", Order = 9, EmitDefaultValue = false)] public bool? InsertEventCapability { get; set; } /// /// Server supports replacing events /// [DataMember(Name = "replaceEventCapability", Order = 10, EmitDefaultValue = false)] public bool? ReplaceEventCapability { get; set; } /// /// Server supports updating events /// [DataMember(Name = "updateEventCapability", Order = 11, EmitDefaultValue = false)] public bool? UpdateEventCapability { get; set; } /// /// Server supports deleting events /// [DataMember(Name = "deleteEventCapability", Order = 12, EmitDefaultValue = false)] public bool? DeleteEventCapability { get; set; } /// /// Allows inserting annotations /// [DataMember(Name = "insertAnnotationCapability", Order = 13, EmitDefaultValue = false)] public bool? InsertAnnotationCapability { get; set; } /// /// Server supports ServerTimestamps in addition /// to SourceTimestamp /// [DataMember(Name = "serverTimestampSupported", Order = 14, EmitDefaultValue = false)] public bool? ServerTimestampSupported { get; set; } /// /// Supported aggregate functions /// [DataMember(Name = "aggregateFunctions", Order = 15, EmitDefaultValue = false)] public IReadOnlyDictionary? AggregateFunctions { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/HistoryUpdateOperation.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// History update type /// [DataContract] public enum HistoryUpdateOperation { /// /// Insert /// [EnumMember(Value = "Insert")] Insert = 1, /// /// Replace /// [EnumMember(Value = "Replace")] Replace, /// /// Update /// [EnumMember(Value = "Update")] Update, /// /// Delete /// [EnumMember(Value = "Delete")] Delete, } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/HistoryUpdateRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Request node history update /// /// [DataContract] public sealed record class HistoryUpdateRequestModel where T : class { /// /// Node to update (mandatory without browse path) /// [DataMember(Name = "nodeId", Order = 0, EmitDefaultValue = false)] public string? NodeId { get; set; } /// /// An optional path from NodeId instance to /// the actual node. /// [DataMember(Name = "browsePath", Order = 1, EmitDefaultValue = false)] public IReadOnlyList? BrowsePath { get; set; } /// /// The HistoryUpdateDetailsType extension object /// encoded as json Variant and containing the tunneled /// update request for the Historian server. The value /// is updated at edge using above node address. /// [DataMember(Name = "details", Order = 2)] [Required] public required T Details { get; set; } /// /// Optional request header /// [DataMember(Name = "header", Order = 3, EmitDefaultValue = false)] public RequestHeaderModel? Header { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/HistoryUpdateResponseModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// History update results /// [DataContract] public sealed record class HistoryUpdateResponseModel { /// /// List of results from the update operation /// [DataMember(Name = "results", Order = 0, EmitDefaultValue = false)] public IReadOnlyList? Results { get; set; } /// /// Service result in case of service call error /// [DataMember(Name = "errorInfo", Order = 1, EmitDefaultValue = false)] public ServiceResultModel? ErrorInfo { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/InstanceDeclarationModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Instance declaration meta data /// [DataContract] public sealed record class InstanceDeclarationModel { /// /// The type that the declaration belongs to. /// [DataMember(Name = "rootTypeId", Order = 0)] public string? RootTypeId { get; set; } /// /// The browse path /// [DataMember(Name = "browsePath", Order = 1)] public IReadOnlyList? BrowsePath { get; set; } /// /// A localized path to the instance declaration. /// [DataMember(Name = "displayPath", Order = 2)] public string? DisplayPath { get; set; } /// /// The modelling rule for the instance /// declaration (i.e. Mandatory or Optional). /// [DataMember(Name = "modellingRule", Order = 3, EmitDefaultValue = false)] public string? ModellingRule { get; set; } /// /// The node id for the instance. /// [DataMember(Name = "nodeId", Order = 4, EmitDefaultValue = false)] public string? NodeId { get; set; } /// /// The node class of the instance declaration. /// [DataMember(Name = "nodeClass", Order = 5)] public NodeClass NodeClass { get; set; } /// /// The browse name for the instance declaration. /// [DataMember(Name = "browseName", Order = 6, EmitDefaultValue = false)] public string? BrowseName { get; set; } /// /// The display name for the instance declaration. /// [DataMember(Name = "displayName", Order = 7, EmitDefaultValue = false)] public string? DisplayName { get; set; } /// /// The description for the instance declaration. /// [DataMember(Name = "description", Order = 8, EmitDefaultValue = false)] public string? Description { get; set; } /// /// Variable meta data /// [DataMember(Name = "variable", Order = 9, EmitDefaultValue = false)] public VariableMetadataModel? VariableMetadata { get; set; } /// /// Method meta data /// [DataMember(Name = "method", Order = 10, EmitDefaultValue = false)] public MethodMetadataModel? MethodMetadata { get; set; } /// /// An instance declaration that has been overridden /// by the current instance. /// [DataMember(Name = "overriddenDeclaration", Order = 11, EmitDefaultValue = false)] public InstanceDeclarationModel? OverriddenDeclaration { get; set; } /// /// The modelling rule node id. /// [DataMember(Name = "modellingRuleId", Order = 12, EmitDefaultValue = false)] public string? ModellingRuleId { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/LocalizedTextModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Localized text. /// [DataContract] public sealed record class LocalizedTextModel { /// /// Text /// [DataMember(Name = "text", Order = 0)] public required string Text { get; set; } /// /// Locale or null for default locale /// [DataMember(Name = "locale", Order = 1, EmitDefaultValue = false)] public string? Locale { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/MessageEncoding.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Specifies the encoding format for OPC UA Publisher messages. /// Can be combined with compression and reversibility flags to control /// message format characteristics. /// [DataContract] [Flags] public enum MessageEncoding { /// /// OPC UA binary encoding format (UADP). /// Most efficient format with smallest message size. /// Best choice when receivers can handle binary OPC UA encoding. /// [EnumMember(Value = "Uadp")] Uadp = 0x1, /// /// Standard JSON encoding format. /// Human-readable format suitable for most messaging systems. /// Default encoding when not specified otherwise. /// May lose some OPC UA type information. /// [EnumMember(Value = "Json")] Json = 0x2, /// /// XML encoding format. /// Most verbose but highly compatible format. /// Provides good interoperability with legacy systems. /// [EnumMember(Value = "Xml")] Xml = 0x4, /// /// Apache Avro binary encoding format. /// Schema-based encoding that supports evolution. /// Provides good balance between size and compatibility. /// [EnumMember(Value = "Avro")] Avro = 0x8, /// /// Flag indicating that messages preserve all OPC UA type information /// and can be decoded back to the original data structure. /// Use with Json or other encodings to ensure lossless transmission. /// [EnumMember(Value = "IsReversible")] IsReversible = 0x40, /// /// JSON encoding that preserves all OPC UA type information. /// Combination of Json and IsReversible flags. /// Allows exact reconstruction of original OPC UA data types. /// Larger message size than standard JSON encoding. /// [EnumMember(Value = "JsonReversible")] JsonReversible = Json | IsReversible, /// /// Flag indicating that messages should be compressed using GZIP. /// Reduces bandwidth usage at the cost of additional processing. /// Most effective with text-based encodings like JSON and XML. /// IsGzipCompressed = 0x80, /// /// GZIP compressed JSON encoding. /// Combination of Json and IsGzipCompressed flags. /// Provides good compromise between size and readability. /// Recommended for bandwidth-constrained scenarios. /// [EnumMember(Value = "JsonGzip")] JsonGzip = Json | IsGzipCompressed, /// /// GZIP compressed Avro encoding. /// Combination of Avro and IsGzipCompressed flags. /// Maximum compression for binary format. /// Best choice for minimal bandwidth usage. /// [EnumMember(Value = "AvroGzip")] AvroGzip = IsGzipCompressed | Avro, /// /// GZIP compressed JSON encoding with full type preservation. /// Combines Json, IsReversible and IsGzipCompressed flags. /// Ensures lossless data transmission with minimal bandwidth. /// Recommended for reliable systems integration. /// [EnumMember(Value = "JsonReversibleGzip")] JsonReversibleGzip = JsonGzip | IsReversible, } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/MessageTimestamp.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Message timestamp configuration option /// [DataContract] public enum MessageTimestamp { /// /// The time (utc) the message was created either because /// it was received from the server or as heartbeat, using /// the publisher module clock. /// [EnumMember(Value = "CurrentTimeUtc")] CurrentTimeUtc, /// /// The publish time of the subscription notification /// which is using the server clock. None if not provided /// or available. /// [EnumMember(Value = "PublishTime")] PublishTime, /// /// The time (utc) the message was encoded and subsequently /// put on the wire, using the publisher module clock. /// [EnumMember(Value = "EncodingTimeUtc")] EncodingTimeUtc, } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/MessagingMode.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Defines how OPC UA Publisher formats and structures messages for transport. /// Each mode provides different trade-offs between message completeness, /// bandwidth efficiency, and compatibility with different message consumers. /// [DataContract] public enum MessagingMode { /// /// OPC UA PubSub standard format as specified in Part 14 of the OPC UA spec. /// Includes complete message metadata and supports all PubSub features. /// Default mode that provides best compatibility and completeness. /// Recommended for standards-compliant message processing. /// [EnumMember(Value = "PubSub")] PubSub, /// /// Simple JSON telemetry format compatible with Azure Time Series Insights. /// Each message contains basic node information and value changes. /// More compact than PubSub mode but with limited metadata. /// Suitable for simple monitoring scenarios. /// [EnumMember(Value = "Samples")] Samples, /// /// Complete OPC UA network message format including all headers and metadata. /// Provides maximum information about the message context and data. /// Largest message size but enables full featured message processing. /// Use when complete message context is required. /// [EnumMember(Value = "FullNetworkMessages")] FullNetworkMessages, /// /// Enhanced samples format with complete metadata and timestamps. /// Similar to Samples mode but includes additional context information. /// Provides good balance between completeness and message size. /// Suitable for advanced monitoring with historical context. /// [EnumMember(Value = "FullSamples")] FullSamples, /// /// Dataset messages without network message wrapper. /// Includes dataset metadata but omits network-level headers. /// Reduced message size while maintaining dataset context. /// Good choice when network-level information is not needed. /// [EnumMember(Value = "DataSetMessages")] DataSetMessages, /// /// Individual dataset message without network message wrapper. /// Similar to DataSetMessages but optimized for single dataset scenarios. /// More efficient than batched messages when publishing single datasets. /// Best for simple publisher configurations with one dataset. /// [EnumMember(Value = "SingleDataSetMessage")] SingleDataSetMessage, /// /// Pure key-value pairs representing datasets without any headers. /// Maximum efficiency with minimal overhead. /// Requires consumers to understand data context from configuration. /// Use when minimal message size is critical and context is known. /// [EnumMember(Value = "DataSets")] DataSets, /// /// Single dataset as key-value pairs without headers. /// Most efficient format for single dataset scenarios. /// Like DataSets mode but optimized for single dataset publishing. /// Best for minimal overhead in simple configurations. /// [EnumMember(Value = "SingleDataSet")] SingleDataSet, /// /// Datasets containing only raw values without type information. /// Most compact representation of data values. /// May lose OPC UA type information in transmission. /// Use only when data types are known by consumers. /// [EnumMember(Value = "RawDataSets")] RawDataSets, /// /// Single dataset with raw values only. /// Most compact format possible for single dataset. /// Combines benefits of SingleDataSet and RawDataSets modes. /// Best choice when absolute minimum message size is required. /// [EnumMember(Value = "SingleRawDataSet")] SingleRawDataSet } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/MethodCallArgumentModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Furly.Extensions.Serializers; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Method argument model /// [DataContract] public sealed record class MethodCallArgumentModel { /// /// Initial value or value to use /// [DataMember(Name = "value", Order = 0)] [SkipValidation] public VariantValue? Value { get; set; } /// /// Data type Id of the value (from meta data) /// [DataMember(Name = "dataType", Order = 1)] public string? DataType { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/MethodCallRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Call request model /// /// /// A method call request can specify the targets in several ways: ///
    ///
  • Specify methodId and objectId node ids and leave the browse /// paths null.
  • ///
  • Specify an objectBrowsePath to a real object node from /// the node specified with objectId. If objectId == null, the /// root node (i=84) is used.
  • ///
  • Specify a methodBrowsePath from the above object node /// to the actual method node to call on the object. methodId /// remains null.
  • ///
  • Like previously, but specify methodId and method browse /// path from it to a real method node.
  • ///
///
[DataContract] public sealed record class MethodCallRequestModel { /// /// Method id of method to call. /// [DataMember(Name = "methodId", Order = 0, EmitDefaultValue = false)] public string? MethodId { get; set; } /// /// Context of the method, i.e. an object or object type /// node. If null then the method is called in the context /// of the inverse HasComponent reference of the MethodId /// if it exists. /// [DataMember(Name = "objectId", Order = 1, EmitDefaultValue = false)] public string? ObjectId { get; set; } /// /// Arguments for the method - null means no args /// [DataMember(Name = "arguments", Order = 2, EmitDefaultValue = false)] public IReadOnlyList? Arguments { get; set; } /// /// An optional component path from the node identified by /// MethodId or from a resolved objectId to the actual /// method node. /// [DataMember(Name = "methodBrowsePath", Order = 3, EmitDefaultValue = false)] public IReadOnlyList? MethodBrowsePath { get; set; } /// /// An optional component path from the node identified by /// ObjectId to the actual object or objectType node. /// If ObjectId is null, the root node (i=84) is used /// [DataMember(Name = "objectBrowsePath", Order = 4, EmitDefaultValue = false)] public IReadOnlyList? ObjectBrowsePath { get; set; } /// /// Optional request header /// [DataMember(Name = "header", Order = 5, EmitDefaultValue = false)] public RequestHeaderModel? Header { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/MethodCallResponseModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Method call response model /// [DataContract] public sealed record class MethodCallResponseModel { /// /// Resulting output values of method call /// [DataMember(Name = "results", Order = 0)] public required IReadOnlyList Results { get; set; } /// /// Service result in case of error /// [DataMember(Name = "errorInfo", Order = 1, EmitDefaultValue = false)] public ServiceResultModel? ErrorInfo { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/MethodMetadataArgumentModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Furly.Extensions.Serializers; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Method argument metadata model /// [DataContract] public sealed record class MethodMetadataArgumentModel { /// /// Name of the argument /// [DataMember(Name = "name", Order = 0)] public required string Name { get; set; } /// /// Optional description of argument /// [DataMember(Name = "description", Order = 1, EmitDefaultValue = false)] public string? Description { get; set; } /// /// Data type node of the argument /// [DataMember(Name = "type", Order = 2)] public required NodeModel Type { get; set; } /// /// Default value for the argument /// [DataMember(Name = "defaultValue", Order = 3, EmitDefaultValue = false)] [SkipValidation] public VariantValue? DefaultValue { get; set; } /// /// Optional, scalar if not set /// [DataMember(Name = "valueRank", Order = 4, EmitDefaultValue = false)] public NodeValueRank? ValueRank { get; set; } /// /// Optional Array dimension of argument /// [DataMember(Name = "arrayDimensions", Order = 5, EmitDefaultValue = false)] public IReadOnlyList? ArrayDimensions { get; set; } /// /// Service result in case of error /// [DataMember(Name = "errorInfo", Order = 6, EmitDefaultValue = false)] public ServiceResultModel? ErrorInfo { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/MethodMetadataModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Method metadata model /// [DataContract] public record class MethodMetadataModel { /// /// Id of object that the method is a component of /// [DataMember(Name = "objectId", Order = 0, EmitDefaultValue = false)] public string? ObjectId { get; set; } /// /// Input argument meta data /// [DataMember(Name = "inputArguments", Order = 1, EmitDefaultValue = false)] public IReadOnlyList? InputArguments { get; set; } /// /// output argument meta data /// [DataMember(Name = "outputArguments", Order = 2, EmitDefaultValue = false)] public IReadOnlyList? OutputArguments { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/MethodMetadataRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Method metadata request model /// [DataContract] public sealed record class MethodMetadataRequestModel { /// /// Method id of method to call. /// (Required) /// [DataMember(Name = "methodId", Order = 0)] public string? MethodId { get; set; } /// /// An optional component path from the node identified by /// MethodId to the actual method node. /// [DataMember(Name = "methodBrowsePath", Order = 1, EmitDefaultValue = false)] public IReadOnlyList? MethodBrowsePath { get; set; } /// /// Optional request header /// [DataMember(Name = "header", Order = 2, EmitDefaultValue = false)] public RequestHeaderModel? Header { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/MethodMetadataResponseModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Result of method metadata query /// [DataContract] public sealed record class MethodMetadataResponseModel : MethodMetadataModel { /// /// Service result in case of error /// [DataMember(Name = "errorInfo", Order = 3, EmitDefaultValue = false)] public ServiceResultModel? ErrorInfo { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ModelChangeHandlingOptionsModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Describes how model changes are published /// [DataContract] public sealed record class ModelChangeHandlingOptionsModel { /// /// Rebrowse period /// [DataMember(Name = "rebrowseIntervalTimespan", Order = 1, EmitDefaultValue = false)] public TimeSpan? RebrowseIntervalTimespan { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ModificationInfoModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Modification information /// [DataContract] public sealed record class ModificationInfoModel { /// /// Modification time /// [DataMember(Name = "modificationTime", Order = 0, EmitDefaultValue = false)] public DateTime? ModificationTime { get; set; } /// /// Operation /// [DataMember(Name = "updateType", Order = 1, EmitDefaultValue = false)] public HistoryUpdateOperation? UpdateType { get; set; } /// /// User who made the change /// [DataMember(Name = "userName", Order = 2, EmitDefaultValue = false)] public string? UserName { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/MonitoredItemWatchdogCondition.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Defines the conditions that trigger the subscription watchdog behavior. /// Works in conjunction with OpcNodeWatchdogTimespan to determine when nodes /// are considered "late" and DataSetWriterWatchdogBehavior to define the response. /// Can be configured globally via the --mwc command line option. /// [DataContract] [Flags] public enum MonitoredItemWatchdogCondition { /// /// Triggers watchdog behavior only when all monitored items exceed their timeout. /// Most lenient condition that waits for complete communication loss. /// Reduces false positives when some nodes update less frequently. /// Suitable when all nodes must be non-responsive to indicate an issue. /// [EnumMember(Value = "WhenAllAreLate")] WhenAllAreLate, /// /// Triggers watchdog behavior when any monitored item exceeds its timeout. /// Default behavior that provides quickest response to communication issues. /// May trigger more frequently in systems with variable update rates. /// Best for critical monitoring where any delay requires attention. /// [EnumMember(Value = "WhenAnyIsLate")] WhenAnyIsLate } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/MonitoringItemMode.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Monitoring modes /// [DataContract] public enum MonitoringMode { /// /// Disabled /// [EnumMember(Value = "Disabled")] Disabled, /// /// Sampling /// [EnumMember(Value = "Sampling")] Sampling, /// /// Reporting /// [EnumMember(Value = "Reporting")] Reporting } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/NamespaceFormat.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Namespace serialization format for node ids /// and qualified names. /// [DataContract] public enum NamespaceFormat { /// /// The legacy uri format /// [EnumMember(Value = "Uri")] Uri, /// /// With ns= namespace index except for index 0 /// [EnumMember(Value = "Index")] Index, /// /// With nsu= namespace except for namespace 0 /// [EnumMember(Value = "Expanded")] Expanded, /// /// With nsu= namespace even for namespace 0 /// [EnumMember(Value = "ExpandedWithNamespace0")] ExpandedWithNamespace0, } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/NetworkMessageContentFlags.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Network message content /// [DataContract] [Flags] public enum NetworkMessageContentFlags { /// /// Publisher id /// [EnumMember(Value = "PublisherId")] PublisherId = 0x1, /// /// Group header /// [EnumMember(Value = "GroupHeader")] GroupHeader = 0x2, /// /// Writer group id /// [EnumMember(Value = "WriterGroupId")] WriterGroupId = 0x4, /// /// Group version /// [EnumMember(Value = "GroupVersion")] GroupVersion = 0x8, /// /// Network message number /// [EnumMember(Value = "NetworkMessageNumber")] NetworkMessageNumber = 0x10, /// /// Sequence number /// [EnumMember(Value = "SequenceNumber")] SequenceNumber = 0x20, /// /// Payload header /// [EnumMember(Value = "PayloadHeader")] PayloadHeader = 0x40, /// /// Timestamp /// [EnumMember(Value = "Timestamp")] Timestamp = 0x80, /// /// Picoseconds /// [EnumMember(Value = "Picoseconds")] Picoseconds = 0x100, /// /// Dataset class id /// [EnumMember(Value = "DataSetClassId")] DataSetClassId = 0x200, /// /// Promoted fields /// [EnumMember(Value = "PromotedFields")] PromotedFields = 0x400, /// /// Network message header /// [EnumMember(Value = "NetworkMessageHeader")] NetworkMessageHeader = 0x800, /// /// Dataset message header /// [EnumMember(Value = "DataSetMessageHeader")] DataSetMessageHeader = 0x1000, /// /// Single dataset messages /// [EnumMember(Value = "SingleDataSetMessage")] SingleDataSetMessage = 0x2000, /// /// Reply to /// [EnumMember(Value = "ReplyTo")] ReplyTo = 0x4000, /// /// Wrap messages in array (publisher extension) /// [EnumMember(Value = "UseArrayEnvelope")] UseArrayEnvelope = 0x1000000, /// /// Use compatibility mode with 2.8 (publisher extension) /// [EnumMember(Value = "UseCompatibilityMode")] UseCompatibilityMode = 0x2000000, /// /// Monitored item message (publisher extension) /// [EnumMember(Value = "MonitoredItemMessage")] MonitoredItemMessage = 0x8000000, } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/NodeAccessLevel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Flags that can be set for the AccessLevel attribute. /// [Flags] [DataContract] public enum NodeAccessLevel { /// /// No access /// [EnumMember(Value = "None")] None = 0x0, /// /// The current value of the Variable may be read. /// [EnumMember(Value = "CurrentRead")] CurrentRead = 0x1, /// /// The current value of the Variable may be written. /// [EnumMember(Value = "CurrentWrite")] CurrentWrite = 0x2, /// /// The history for the Variable may be read. /// [EnumMember(Value = "HistoryRead")] HistoryRead = 0x4, /// /// The history for the Variable may be updated. /// [EnumMember(Value = "HistoryWrite")] HistoryWrite = 0x8, /// /// Indicates if the Variable generates /// SemanticChangeEvents when its value changes. /// [EnumMember(Value = "SemanticChange")] SemanticChange = 0x10, /// /// Indicates if the current StatusCode of the /// value is writable. /// [EnumMember(Value = "StatusWrite")] StatusWrite = 0x20, /// /// Indicates if the current SourceTimestamp is /// writable. /// [EnumMember(Value = "TimestampWrite")] TimestampWrite = 0x40, /// /// Reads are not atomic. /// [EnumMember(Value = "NonatomicRead")] NonatomicRead = 0x100, /// /// Writes are not atomic /// [EnumMember(Value = "NonatomicWrite")] NonatomicWrite = 0x200, /// /// Writes cannot be performed with IndexRange. /// [EnumMember(Value = "WriteFullArrayOnly")] WriteFullArrayOnly = 0x400, } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/NodeAccessRestrictions.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Flags that can be read or written in the /// AccessRestrictions attribute. /// [Flags] [DataContract] public enum NodeAccessRestrictions { /// /// No restrictions /// [EnumMember(Value = "None")] None = 0x0, /// /// The Client can only access the Node when using a /// SecureChannel which digitally signs all messages. /// [EnumMember(Value = "SigningRequired")] SigningRequired = 0x1, /// /// The Client can only access the Node when using a /// SecureChannel which encrypts all messages. /// [EnumMember(Value = "EncryptionRequired")] EncryptionRequired = 0x2, /// /// The Client cannot access the Node when using /// SessionlessInvoke Service invocation. /// [EnumMember(Value = "SessionRequired")] SessionRequired = 0x4 } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/NodeAttribute.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Node attribute identifiers /// [DataContract] public enum NodeAttribute { /// /// Node identifier /// [EnumMember(Value = "NodeId")] NodeId = 1, /// /// Node class /// [EnumMember(Value = "NodeClass")] NodeClass, /// /// Browse name /// [EnumMember(Value = "BrowseName")] BrowseName, /// /// Display name /// [EnumMember(Value = "DisplayName")] DisplayName, /// /// Description /// [EnumMember(Value = "Description")] Description, /// /// Node write mask /// [EnumMember(Value = "WriteMask")] WriteMask, /// /// User write mask /// [EnumMember(Value = "UserWriteMask")] UserWriteMask, /// /// Is abstract /// [EnumMember(Value = "IsAbstract")] IsAbstract, /// /// Symmetric /// [EnumMember(Value = "Symmetric")] Symmetric, /// /// Inverse name /// [EnumMember(Value = "InverseName")] InverseName, /// /// Contains no loop /// [EnumMember(Value = "ContainsNoLoops")] ContainsNoLoops, /// /// Event notifier /// [EnumMember(Value = "EventNotifier")] EventNotifier, /// /// Value for variable /// [EnumMember(Value = "Value")] Value, /// /// Datatype /// [EnumMember(Value = "DataType")] DataType, /// /// Value rank /// [EnumMember(Value = "ValueRank")] ValueRank, /// /// Array dimension /// [EnumMember(Value = "ArrayDimensions")] ArrayDimensions, /// /// Accesslevel /// [EnumMember(Value = "AccessLevel")] AccessLevel, /// /// User access level /// [EnumMember(Value = "UserAccessLevel")] UserAccessLevel, /// /// Minimum sampling interval /// [EnumMember(Value = "MinimumSamplingInterval")] MinimumSamplingInterval, /// /// Whether node is historizing /// [EnumMember(Value = "Historizing")] Historizing, /// /// Method can be called /// [EnumMember(Value = "Executable")] Executable, /// /// User can call method /// [EnumMember(Value = "UserExecutable")] UserExecutable, /// /// Data type definition /// [EnumMember(Value = "DataTypeDefinition")] DataTypeDefinition, /// /// Role permissions /// [EnumMember(Value = "RolePermissions")] RolePermissions, /// /// User role permissions /// [EnumMember(Value = "UserRolePermissions")] UserRolePermissions, /// /// Access restrictions on node /// [EnumMember(Value = "AccessRestrictions")] AccessRestrictions } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/NodeClass.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Node class /// [DataContract] public enum NodeClass { /// /// Object class /// [EnumMember(Value = "Object")] #pragma warning disable CA1720 // Identifier contains type name Object, #pragma warning restore CA1720 // Identifier contains type name /// /// Variable /// [EnumMember(Value = "Variable")] Variable, /// /// Method class /// [EnumMember(Value = "Method")] Method, /// /// Object type /// [EnumMember(Value = "ObjectType")] ObjectType, /// /// Variable type /// [EnumMember(Value = "VariableType")] VariableType, /// /// Reference type /// [EnumMember(Value = "ReferenceType")] ReferenceType, /// /// Data type /// [EnumMember(Value = "DataType")] DataType, /// /// View class /// [EnumMember(Value = "View")] View } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/NodeEventNotifier.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Flags that can be set for the EventNotifier attribute. /// [Flags] [DataContract] public enum NodeEventNotifier { /// /// The Object or View produces event /// notifications. /// [EnumMember(Value = "SubscribeToEvents")] SubscribeToEvents = 0x1, /// /// The Object has an event history which may /// be read. /// [EnumMember(Value = "HistoryRead")] HistoryRead = 0x4, /// /// The Object has an event history which may /// be updated. /// [EnumMember(Value = "HistoryWrite")] HistoryWrite = 0x8, } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/NodeIdModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Represents an OPC UA Node identifier in string format. /// Used to identify nodes in the OPC UA address space for monitoring. /// Supports standard OPC UA node ID formats including: /// - Namespace index and identifier (ns=0;i=85) /// - String identifiers (ns=2;s=MyNode) /// - GUID identifiers (ns=3;g=8599E6C4-6667-4FB7-9EA9-C6896B31DB02) /// - Opaque/binary identifiers (ns=4;b=FA34E...) /// [DataContract] public sealed record class NodeIdModel { /// /// The node identifier string in standard OPC UA notation. /// Format: ns={namespace};{type}={value} /// Examples: /// - ns=0;i=85 (numeric identifier) /// - ns=2;s=MyNode (string identifier) /// - ns=3;g=8599E6C4-6667-4FB7-9EA9-C6896B31DB02 (GUID) /// - ns=4;b=FA34E... (binary/opaque) /// If namespace index is omitted, ns=0 is assumed. /// [DataMember(Name = "Identifier", Order = 0, EmitDefaultValue = false)] public string? Identifier { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/NodeMetadataRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Node metadata request model /// [DataContract] public sealed record class NodeMetadataRequestModel { /// /// Optional request header /// [DataMember(Name = "header", Order = 0, EmitDefaultValue = false)] public RequestHeaderModel? Header { get; set; } /// /// Node id of the type. /// (Required) /// [DataMember(Name = "nodeId", Order = 1)] public string? NodeId { get; set; } /// /// An optional component path from the node identified by /// NodeId to the actual node. /// [DataMember(Name = "browsePath", Order = 2, EmitDefaultValue = false)] public IReadOnlyList? BrowsePath { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/NodeMetadataResponseModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Node metadata model /// [DataContract] public sealed record class NodeMetadataResponseModel { /// /// The node id of the node /// [DataMember(Name = "nodeId", Order = 0)] public string? NodeId { get; set; } /// /// The class of the node /// [DataMember(Name = "nodeClass", Order = 1)] public NodeClass NodeClass { get; set; } /// /// The display name of the node. /// [DataMember(Name = "displayName", Order = 2, EmitDefaultValue = false)] public string? DisplayName { get; set; } /// /// The description for the node. /// [DataMember(Name = "description", Order = 3, EmitDefaultValue = false)] public string? Description { get; set; } /// /// Variable meta data if the node is of class /// or /// otherwise /// null. /// [DataMember(Name = "variableMetadata", Order = 4, EmitDefaultValue = false)] public VariableMetadataModel? VariableMetadata { get; set; } /// /// Data type meta data if the node is of class /// otherwise /// null. /// [DataMember(Name = "dataTypeMetadata", Order = 5, EmitDefaultValue = false)] public DataTypeMetadataModel? DataTypeMetadata { get; set; } /// /// Method meta data if the node is of class /// otherwise /// null. /// [DataMember(Name = "nethodMetadata", Order = 6, EmitDefaultValue = false)] public MethodMetadataModel? MethodMetadata { get; set; } /// /// The returned type definition if the node is /// of class or /// /// referenced a type definition node or if the node /// is a , /// , /// or , /// [DataMember(Name = "typeDefinition", Order = 7, EmitDefaultValue = false)] public TypeDefinitionModel? TypeDefinition { get; set; } /// /// Service result in case of error /// [DataMember(Name = "errorInfo", Order = 8, EmitDefaultValue = false)] public ServiceResultModel? ErrorInfo { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/NodeModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Furly.Extensions.Serializers; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Node model /// [DataContract] public sealed record class NodeModel { /// /// Type of node /// [DataMember(Name = "nodeClass", Order = 0, EmitDefaultValue = false)] public NodeClass? NodeClass { get; set; } /// /// Display name /// [DataMember(Name = "displayName", Order = 1, EmitDefaultValue = false)] public string? DisplayName { get; set; } /// /// Id of node. /// (Mandatory). /// [DataMember(Name = "nodeId", Order = 2)] [Required] public required string NodeId { get; set; } /// /// Description if any /// [DataMember(Name = "description", Order = 3, EmitDefaultValue = false)] public string? Description { get; set; } /// /// Browse name /// [DataMember(Name = "browseName", Order = 4, EmitDefaultValue = false)] public string? BrowseName { get; set; } /// /// Value of variable or default value of the /// subtyped variable in case node is a variable /// type, otherwise null. /// [DataMember(Name = "value", Order = 5, EmitDefaultValue = false)] [SkipValidation] public VariantValue? Value { get; set; } /// /// Pico seconds part of when value was read at source. /// [DataMember(Name = "sourcePicoseconds", Order = 6, EmitDefaultValue = false)] public ushort? SourcePicoseconds { get; set; } /// /// Timestamp of when value was read at source. /// [DataMember(Name = "sourceTimestamp", Order = 7, EmitDefaultValue = false)] public DateTime? SourceTimestamp { get; set; } /// /// Pico seconds part of when value was read at server. /// [DataMember(Name = "serverPicoseconds", Order = 8, EmitDefaultValue = false)] public ushort? ServerPicoseconds { get; set; } /// /// Timestamp of when value was read at server. /// [DataMember(Name = "serverTimestamp", Order = 9, EmitDefaultValue = false)] public DateTime? ServerTimestamp { get; set; } /// /// Service result in case of error reading the value /// [DataMember(Name = "errorInfo", Order = 10, EmitDefaultValue = false)] public ServiceResultModel? ErrorInfo { get; set; } /// /// Node access restrictions if any. /// (default: none) /// [DataMember(Name = "accessRestrictions", Order = 11, EmitDefaultValue = false)] public NodeAccessRestrictions? AccessRestrictions { get; set; } /// /// Default write mask for the node /// (default: 0) /// [DataMember(Name = "writeMask", Order = 12, EmitDefaultValue = false)] public uint? WriteMask { get; set; } /// /// User write mask for the node /// (default: 0) /// [DataMember(Name = "userWriteMask", Order = 13, EmitDefaultValue = false)] public uint? UserWriteMask { get; set; } /// /// Whether type is abstract, if type can /// be abstract. Null if not type node. /// (default: false) /// [DataMember(Name = "isAbstract", Order = 14, EmitDefaultValue = false)] public bool? IsAbstract { get; set; } /// /// Whether a view contains loops. Null if /// not a view. /// [DataMember(Name = "containsNoLoops", Order = 15, EmitDefaultValue = false)] public bool? ContainsNoLoops { get; set; } /// /// If object or view and eventing, event notifier /// to subscribe to. /// (default: no events supported) /// [DataMember(Name = "eventNotifier", Order = 16, EmitDefaultValue = false)] public NodeEventNotifier? EventNotifier { get; set; } /// /// If method node class, whether method can /// be called. /// [DataMember(Name = "executable", Order = 17, EmitDefaultValue = false)] public bool? Executable { get; set; } /// /// If method node class, whether method can /// be called by current user. /// (default: false if not executable) /// [DataMember(Name = "userExecutable", Order = 18, EmitDefaultValue = false)] public bool? UserExecutable { get; set; } /// /// Data type definition in case node is a /// data type node and definition is available, /// otherwise null. /// [DataMember(Name = "dataTypeDefinition", Order = 19, EmitDefaultValue = false)] [SkipValidation] public VariantValue? DataTypeDefinition { get; set; } /// /// Default access level for value in variable /// node or null if not a variable. /// (default: No access) /// [DataMember(Name = "accessLevel", Order = 20, EmitDefaultValue = false)] public NodeAccessLevel? AccessLevel { get; set; } /// /// User access level for value in variable node /// or null. /// (default: No access) /// [DataMember(Name = "userAccessLevel", Order = 21, EmitDefaultValue = false)] public NodeAccessLevel? UserAccessLevel { get; set; } /// /// If variable the datatype of the variable. /// (default: null) /// [DataMember(Name = "dataType", Order = 22, EmitDefaultValue = false)] public string? DataType { get; set; } /// /// Value rank of the variable data of a variable /// or variable type, otherwise null. /// (default: scalar = -1) /// [DataMember(Name = "valueRank", Order = 23, EmitDefaultValue = false)] public NodeValueRank? ValueRank { get; set; } /// /// Array dimensions of variable or variable type. /// (default: empty array) /// [DataMember(Name = "arrayDimensions", Order = 24, EmitDefaultValue = false)] public IReadOnlyList? ArrayDimensions { get; set; } /// /// Whether the value of a variable is historizing. /// (default: false) /// [DataMember(Name = "historizing", Order = 25, EmitDefaultValue = false)] public bool? Historizing { get; set; } /// /// Minimum sampling interval for the variable /// value, otherwise null if not a variable node. /// (default: null) /// [DataMember(Name = "minimumSamplingInterval", Order = 26, EmitDefaultValue = false)] public double? MinimumSamplingInterval { get; set; } /// /// Inverse name of the reference if the node is /// a reference type, otherwise null. /// [DataMember(Name = "inverseName", Order = 27, EmitDefaultValue = false)] public string? InverseName { get; set; } /// /// Whether the reference is symmetric in case /// the node is a reference type, otherwise /// null. /// [DataMember(Name = "symmetric", Order = 28, EmitDefaultValue = false)] public bool? Symmetric { get; set; } /// /// Role permissions /// [DataMember(Name = "rolePermissions", Order = 29, EmitDefaultValue = false)] public IReadOnlyList? RolePermissions { get; set; } /// /// User Role permissions /// [DataMember(Name = "userRolePermissions", Order = 30, EmitDefaultValue = false)] public IReadOnlyList? UserRolePermissions { get; set; } /// /// Optional type definition of the node /// [DataMember(Name = "typeDefinitionId", Order = 31, EmitDefaultValue = false)] public string? TypeDefinitionId { get; set; } /// /// Whether node has children which are defined as /// any forward hierarchical references. /// (default: unknown) /// [DataMember(Name = "children", Order = 32, EmitDefaultValue = false)] public bool? Children { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/NodePathTargetModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Node path target /// [DataContract] public sealed record class NodePathTargetModel { /// /// The target browse path /// [DataMember(Name = "browsePath", Order = 0)] public required IReadOnlyList BrowsePath { get; set; } /// /// Target node /// [DataMember(Name = "target", Order = 1)] public required NodeModel Target { get; set; } /// /// Remaining index in path /// [DataMember(Name = "remainingPathIndex", Order = 2, EmitDefaultValue = false)] public int? RemainingPathIndex { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/NodeReferenceModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Reference model /// [DataContract] public sealed record class NodeReferenceModel { /// /// Reference Type id /// [DataMember(Name = "referenceTypeId", Order = 0, EmitDefaultValue = false)] public string? ReferenceTypeId { get; set; } /// /// Browse direction of reference /// [DataMember(Name = "direction", Order = 1, EmitDefaultValue = false)] public BrowseDirection? Direction { get; set; } /// /// Target node /// [DataMember(Name = "target", Order = 2)] [Required] public required NodeModel Target { get; set; } /// /// Service result in case of error /// [DataMember(Name = "errorInfo", Order = 3, EmitDefaultValue = false)] public ServiceResultModel? ErrorInfo { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/NodeType.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// The node type /// [DataContract] public enum NodeType { /// /// Unknown /// [EnumMember(Value = "Unknown")] Unknown, /// /// Variable /// [EnumMember(Value = "Variable")] Variable, /// /// Data variable /// [EnumMember(Value = "DataVariable")] DataVariable, /// /// Variable /// [EnumMember(Value = "Property")] Property, /// /// Data type /// [EnumMember(Value = "DataType")] DataType, /// /// View class /// [EnumMember(Value = "View")] View, /// /// Regular object type /// [EnumMember(Value = "Object")] #pragma warning disable CA1720 // Identifier contains type name Object, #pragma warning restore CA1720 // Identifier contains type name /// /// Type is event type /// [EnumMember(Value = "Event")] Event, /// /// Interface type /// [EnumMember(Value = "Interface")] Interface } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/NodeValueRank.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Constants defined for the ValueRank attribute. /// [Flags] [DataContract] #pragma warning disable CA2217 // Do not mark enums with FlagsAttribute public enum NodeValueRank #pragma warning restore CA2217 // Do not mark enums with FlagsAttribute { /// /// The variable may be a scalar or a one /// dimensional array. /// [EnumMember(Value = "ScalarOrOneDimension")] ScalarOrOneDimension = -3, /// /// The variable may be a scalar or an array of /// any dimension. /// [EnumMember(Value = "Any")] Any = -2, /// /// The variable is always a scalar. /// [EnumMember(Value = "Scalar")] Scalar = Any | OneDimension, /// /// The variable is always an array with one or /// more dimensions. /// [EnumMember(Value = "OneOrMoreDimensions")] OneOrMoreDimensions = 0, /// /// The variable is always one dimensional array. /// [EnumMember(Value = "OneDimension")] OneDimension = 1, /// /// The variable is always an array with two or /// more dimensions. /// [EnumMember(Value = "TwoDimensions")] TwoDimensions = 2 } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/OpcAuthenticationMode.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Specifies the authentication method used to connect to OPC UA servers. /// The chosen mode determines how the Publisher authenticates itself to servers. /// When using credentials or certificates, encrypted communication should be enabled /// via UseSecurity or EndpointSecurityMode to protect authentication secrets. /// [DataContract] public enum OpcAuthenticationMode { /// /// No authentication credentials provided (default). /// Server must allow anonymous access for connections to succeed. /// Least secure option - use only when no security requirements exist /// or in secure, isolated networks. /// [EnumMember(Value = "Anonymous")] Anonymous, /// /// Authenticate using username and password credentials. /// Requires OpcAuthenticationUsername and OpcAuthenticationPassword. /// WARNING: Always use with encrypted communication (SignAndEncrypt) /// to prevent credential exposure. Credentials can be stored encrypted /// at rest using the --fce command line option. /// [EnumMember(Value = "UsernamePassword")] UsernamePassword, /// /// Authenticate using X.509 certificates. /// Uses certificate from User certificate store in PKI configuration. /// OpcAuthenticationUsername specifies the certificate subject name. /// OpcAuthenticationPassword provides the private key password if needed. /// Most secure option when properly managed. /// [EnumMember(Value = "Certificate")] Certificate } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/OpcNodeModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Furly.Extensions.Messaging; using System; using System.Collections.Generic; using System.Runtime.Serialization; /// /// Defines configuration for monitoring an OPC UA node. /// Contains settings for sampling, filtering, publishing /// behavior, and message routing. This model allows /// fine-grained control over how each node's data is collected /// and transmitted. Part of a PublishedNodesEntryModel's /// OpcNodes collection. /// [DataContract] public record class OpcNodeModel { /// /// The OPC UA node identifier string in standard notation. /// Format: ns={namespace};{type}={value} Required field that /// uniquely identifies the node to monitor. Examples: /// "ns=2;s=MyTag", "ns=0;i=2258" See OPC UA Part 3 for node /// ID format specifications. /// [DataMember(Name = "Id", Order = 0, EmitDefaultValue = false)] public string? Id { get; set; } /// /// Server-side sampling rate in milliseconds. Determines how /// often the server checks for value changes. Default from /// DataSetSamplingInterval if not specified. Should be less /// than or equal to OpcPublishingInterval for effective /// sampling. Ignored when OpcSamplingIntervalTimespan is /// defined. /// [DataMember(Name = "OpcSamplingInterval", Order = 1, EmitDefaultValue = false)] public int? OpcSamplingInterval { get; set; } /// /// Server-side sampling rate as a TimeSpan. Takes precedence /// over OpcSamplingInterval if both are defined. Provides /// more precise control over timing than milliseconds. /// Example: "00:00:00.100" for 100ms sampling. Should be /// less than or equal to OpcPublishingIntervalTimespan for /// effective sampling. /// [DataMember(Name = "OpcSamplingIntervalTimespan", Order = 2, EmitDefaultValue = false)] public TimeSpan? OpcSamplingIntervalTimespan { get; set; } /// /// Custom identifier for this node in dataset messages. Used /// as field name in message payloads if specified. Falls back /// to DisplayName if not provided. Helps correlate data with /// specific measurements or tags. Must be unique within a /// dataset writer. /// [DataMember(Name = "DataSetFieldId", Order = 3, EmitDefaultValue = false)] public string? DataSetFieldId { get; set; } /// /// Unique identifier for correlating fields with dataset /// class metadata. Links monitored item data with dataset /// class field definitions. Used to provide context and type /// information for the field. Must match corresponding field /// ID in dataset class metadata. Important for proper message /// decoding by subscribers. /// [DataMember(Name = "DataSetClassFieldId", Order = 4, EmitDefaultValue = false)] public Guid DataSetClassFieldId { get; set; } /// /// Human-readable name for the monitored item. Used as field /// identifier if DataSetFieldId not specified. Can be /// overridden by actual node DisplayName if /// FetchDisplayName=true. Helps identify data sources in /// messages and logs. Should be unique within a dataset for /// clear identification. /// [DataMember(Name = "DisplayName", Order = 5, EmitDefaultValue = false)] public string? DisplayName { get; set; } /// /// Size of the server-side queue for this monitored item. /// Controls how many values can be buffered during slow /// connections. Values are discarded according to DiscardNew /// when queue is full. Default is 1 unless otherwise /// configured. Larger queues help prevent data loss but use /// more server memory. /// [DataMember(Name = "QueueSize", Order = 6, EmitDefaultValue = false)] public uint? QueueSize { get; set; } /// /// Controls queue overflow behavior for monitored items. /// True: Discard newest values when queue is full (LIFO). /// False: Discard oldest values when queue is full (FIFO, /// default). Use True to preserve historical data during /// connection issues. Use False to maintain current value /// accuracy. /// [DataMember(Name = "DiscardNew", Order = 7, EmitDefaultValue = false)] public bool? DiscardNew { get; set; } /// /// Specifies what triggers value change notifications. Only /// applies to DataItems (not Events or Alarms). Options: /// - Status: Changes in status or quality /// - StatusValue: Changes in value or status (default) /// - StatusValueTimestamp: Any change including timestamp /// Controls sensitivity of change detection. /// [DataMember(Name = "DataChangeTrigger", Order = 8, EmitDefaultValue = false)] public DataChangeTriggerType? DataChangeTrigger { get; set; } /// /// Deadband type of the data change filter to apply. Does not /// apply to events. /// [DataMember(Name = "DeadbandType", Order = 9, EmitDefaultValue = false)] public DeadbandType? DeadbandType { get; set; } /// /// Deadband value of the data change filter to apply. Does /// not apply to events /// [DataMember(Name = "DeadbandValue", Order = 10, EmitDefaultValue = false)] public double? DeadbandValue { get; set; } /// /// Event Filter to apply. When specified the node is assmed /// to be an event notifier node to subscribe to. /// [DataMember(Name = "EventFilter", Order = 11, EmitDefaultValue = false)] public EventFilterModel? EventFilter { get; set; } /// /// Settings for pending condition handling /// [DataMember(Name = "ConditionHandling", Order = 12, EmitDefaultValue = false)] public ConditionHandlingOptionsModel? ConditionHandling { get; set; } /// /// Relative path through the address space to reach target /// node. Sequence of browse names from starting node to /// target. Example: ["Objects", "Server", "Data", /// "Dynamic", "Scalar"]. Allows referencing nodes through /// hierarchical structure. Alternative to direct node ID /// addressing. /// [DataMember(Name = "BrowsePath", Order = 14, EmitDefaultValue = false)] public IReadOnlyList? BrowsePath { get; set; } /// /// The OPC UA attribute to monitor on the node. Default is /// Value (13) for variables. Common alternatives: /// - DisplayName (4): Human-readable name /// - Description (5): Detailed information /// - BrowseName (3): Browse name. /// See OPC UA Part 6 for complete attribute list. /// [DataMember(Name = "AttributeId", Order = 15, EmitDefaultValue = false)] public NodeAttribute? AttributeId { get; set; } /// /// Range specification for array or string values. Format: /// "start:end" or "index". Examples: "0:3" (first 4 /// elements), "7" (8th element) Allows monitoring specific /// array elements. Default: null (entire value monitored) /// [DataMember(Name = "IndexRange", Order = 16, EmitDefaultValue = false)] public string? IndexRange { get; set; } /// /// Custom routing topic/queue for this node's messages. /// Overrides writer and writer group queue settings. Enables /// node-specific message routing patterns. Messages are split /// into separate network messages when nodes have different /// topics. Format depends on transport (e.g., MQTT topic /// syntax). /// [DataMember(Name = "Topic", Order = 17, EmitDefaultValue = false)] public string? Topic { get; set; } /// /// Quality of service to use for the node. Overrides the /// writer and Writer group quality of service and together /// with queue name causes network messages to be split. /// [DataMember(Name = "QualityOfService", Order = 18, EmitDefaultValue = false)] public QoS? QualityOfService { get; set; } /// /// Controls heartbeat message generation for this node. /// Overrides DefaultHeartbeatBehavior from parent /// configuration. See HeartbeatBehavior enum for available /// options. Node-specific heartbeat settings allow /// fine-grained control over connection monitoring and state /// maintenance. /// [DataMember(Name = "HeartbeatBehavior", Order = 19, EmitDefaultValue = false)] public HeartbeatBehavior? HeartbeatBehavior { get; set; } /// /// Node-specific heartbeat interval in milliseconds. /// Overrides DefaultHeartbeatInterval from parent /// configuration. Controls how often heartbeat messages are /// generated. Set to 0 to disable heartbeats for this node. /// Ignored when HeartbeatIntervalTimespan is defined. /// [DataMember(Name = "HeartbeatInterval", Order = 20, EmitDefaultValue = false)] public int? HeartbeatInterval { get; set; } /// /// Node-specific heartbeat interval as TimeSpan. Takes /// precedence over HeartbeatInterval if both defined. /// Overrides DefaultHeartbeatIntervalTimespan setting. /// Provides more precise control over timing. Example: /// "00:00:10" for 10-second interval. /// [DataMember(Name = "HeartbeatIntervalTimespan", Order = 21, EmitDefaultValue = false)] public TimeSpan? HeartbeatIntervalTimespan { get; set; } /// /// Controls handling of initial value notification. True: /// Suppress first value from monitored item. False: Publish /// initial value (default). Useful when only changes are /// relevant. Server always sends initial value on creation. /// [DataMember(Name = "SkipFirst", Order = 22, EmitDefaultValue = false)] public bool? SkipFirst { get; set; } /// /// Client-side publishing rate in milliseconds. Controls how /// often the server sends notifications. Must be >= /// OpcSamplingInterval for proper operation. Overrides /// DataSetPublishingInterval when specified. Ignored if /// OpcPublishingIntervalTimespan is defined. /// [DataMember(Name = "OpcPublishingInterval", Order = 23, EmitDefaultValue = false)] public int? OpcPublishingInterval { get; set; } /// /// OpcPublishingInterval as TimeSpan. /// [DataMember(Name = "OpcPublishingIntervalTimespan", Order = 24, EmitDefaultValue = false)] public TimeSpan? OpcPublishingIntervalTimespan { get; set; } /// /// Use periodic reads instead of monitored items. True: Sample /// using CyclicRead service calls False: Use standard /// subscription monitoring (default) Useful for nodes that /// don't support monitoring or when consistent sampling /// timing is required. Consider CyclicReadMaxAge when /// enabled. /// [DataMember(Name = "UseCyclicRead", Order = 25, EmitDefaultValue = false)] public bool? UseCyclicRead { get; set; } /// /// Optimize node access using RegisterNodes service. True: /// Register node for faster subsequent reads False: Use /// direct node access (default) Can improve performance for /// frequently accessed nodes. Server must support /// RegisterNodes service. /// [DataMember(Name = "RegisterNode", Order = 26, EmitDefaultValue = false)] public bool? RegisterNode { get; set; } /// /// Retrieve node's DisplayName attribute on startup. True: /// Query and use actual display name False: Use configured /// DisplayName (default) Overrides DataSetFetchDisplayNames /// setting. Used for human-readable field identification. /// [DataMember(Name = "FetchDisplayName", Order = 27, EmitDefaultValue = false)] public bool? FetchDisplayName { get; set; } /// /// Configuration for model change tracking nodes /// [DataMember(Name = "ModelChangeHandling", Order = 28, EmitDefaultValue = false)] public ModelChangeHandlingOptionsModel? ModelChangeHandling { get; set; } /// /// Collection of dependent nodes triggered by this node. Read /// atomically when parent node changes. Limited to one level /// of triggering (no cascading). Useful for maintaining data /// consistency between related measurements. Changes to /// triggered nodes must be made through parent node's API /// calls. /// [DataMember(Name = "TriggeredNodes", Order = 29, EmitDefaultValue = false)] public IReadOnlyList? TriggeredNodes { get; set; } /// /// Maximum age for cached values in cyclic reads. Specified in /// milliseconds. Default: 0 (no caching) Only applies when /// UseCyclicRead is true. Server may return cached value if /// within max age. Helps reduce server load in high-frequency /// reads. Ignored when CyclicReadMaxAgeTimespan is defined. /// [DataMember(Name = "CyclicReadMaxAge", Order = 31, EmitDefaultValue = false)] public int? CyclicReadMaxAge { get; set; } /// /// Maximum age for cached values in cyclic reads as TimeSpan. /// Takes precedence over CyclicReadMaxAge if both defined. /// Only applies when UseCyclicRead is true. Default: /// "00:00:00" (no caching) Example: "00:00:00.500" for 500ms /// max cache age. Helps optimize read performance vs data /// freshness. /// [DataMember(Name = "CyclicReadMaxAgeTimespan", Order = 32, EmitDefaultValue = false)] public TimeSpan? CyclicReadMaxAgeTimespan { get; set; } /// /// A type definition id that references a well known opc ua /// type definition node for the variable represented by this /// node entry. /// [DataMember(Name = "TypeDefinitionId", Order = 33, EmitDefaultValue = false)] public string? TypeDefinitionId { get; set; } /// /// If the node is a method this is the method metadata that /// represents the input and output arguments of the method. /// [DataMember(Name = "MethodMetadata", Order = 34, EmitDefaultValue = false)] public MethodMetadataModel? MethodMetadata { get; set; } /// /// Alternative node identifier with full namespace URI. Same /// as Id but uses complete namespace URI instead of index. /// Format: "nsu={uri};{type}={value}" Example: /// "nsu=http://opcfoundation.org/UA/;i=2258" Provides more /// portable node identification across servers. /// [DataMember(Name = "ExpandedNodeId", Order = 40, EmitDefaultValue = false)] public string? ExpandedNodeId { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/OperationContextModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Operation log model /// [DataContract] public sealed record class OperationContextModel { /// /// User /// [DataMember(Name = "AuthorityId", Order = 0, EmitDefaultValue = false)] public string? AuthorityId { get; set; } /// /// Operation time /// [DataMember(Name = "Time", Order = 1, EmitDefaultValue = false)] public DateTimeOffset Time { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/OperationLimitsModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Server limits /// [DataContract] public sealed record class OperationLimitsModel { /// /// Min supported sampling rate /// [DataMember(Name = "minSupportedSampleRate", Order = 0, EmitDefaultValue = false)] public double? MinSupportedSampleRate { get; set; } /// /// Max browse continuation points /// [DataMember(Name = "maxBrowseContinuationPoints", Order = 1, EmitDefaultValue = false)] public ushort? MaxBrowseContinuationPoints { get; set; } /// /// Max query continuation points /// [DataMember(Name = "maxQueryContinuationPoints", Order = 2, EmitDefaultValue = false)] public ushort? MaxQueryContinuationPoints { get; set; } /// /// Max history continuation points /// [DataMember(Name = "maxHistoryContinuationPoints", Order = 3, EmitDefaultValue = false)] public ushort? MaxHistoryContinuationPoints { get; set; } /// /// Max array length supported /// [DataMember(Name = "maxArrayLength", Order = 4, EmitDefaultValue = false)] public uint? MaxArrayLength { get; set; } /// /// Max string length supported /// [DataMember(Name = "maxStringLength", Order = 5, EmitDefaultValue = false)] public uint? MaxStringLength { get; set; } /// /// Max byte buffer length supported /// [DataMember(Name = "maxByteStringLength", Order = 6, EmitDefaultValue = false)] public uint? MaxByteStringLength { get; set; } /// /// Max nodes that can be part of a single browse call. /// [DataMember(Name = "maxNodesPerBrowse", Order = 7, EmitDefaultValue = false)] public uint? MaxNodesPerBrowse { get; set; } /// /// Max nodes that can be read in single read call /// [DataMember(Name = "maxNodesPerRead", Order = 8, EmitDefaultValue = false)] public uint? MaxNodesPerRead { get; set; } /// /// Max nodes that can be read in single write call /// [DataMember(Name = "maxNodesPerWrite", Order = 9, EmitDefaultValue = false)] public uint? MaxNodesPerWrite { get; set; } /// /// Max nodes that can be read in single method call /// [DataMember(Name = "maxNodesPerMethodCall", Order = 10, EmitDefaultValue = false)] public uint? MaxNodesPerMethodCall { get; set; } /// /// Number of nodes that can be in a History Read value call /// [DataMember(Name = "maxNodesPerHistoryReadData", Order = 11, EmitDefaultValue = false)] public uint? MaxNodesPerHistoryReadData { get; set; } /// /// Number of nodes that can be in a History Read events call /// [DataMember(Name = "maxNodesPerHistoryReadEvents", Order = 12, EmitDefaultValue = false)] public uint? MaxNodesPerHistoryReadEvents { get; set; } /// /// Number of nodes that can be in a History Update call /// [DataMember(Name = "maxNodesPerHistoryUpdateData", Order = 13, EmitDefaultValue = false)] public uint? MaxNodesPerHistoryUpdateData { get; set; } /// /// Number of nodes that can be in a History events update call /// [DataMember(Name = "maxNodesPerHistoryUpdateEvents", Order = 14, EmitDefaultValue = false)] public uint? MaxNodesPerHistoryUpdateEvents { get; set; } /// /// Max nodes that can be registered at once /// [DataMember(Name = "maxNodesPerRegisterNodes", Order = 15, EmitDefaultValue = false)] public uint? MaxNodesPerRegisterNodes { get; set; } /// /// Max nodes that can be part of a browse path /// [DataMember(Name = "maxNodesPerTranslatePathsToNodeIds", Order = 16, EmitDefaultValue = false)] public uint? MaxNodesPerTranslatePathsToNodeIds { get; set; } /// /// Max nodes that can be added or removed in a single call. /// [DataMember(Name = "maxNodesPerNodeManagement", Order = 17, EmitDefaultValue = false)] public uint? MaxNodesPerNodeManagement { get; set; } /// /// Max monitored items that can be updated at once. /// [DataMember(Name = "maxMonitoredItemsPerCall", Order = 18, EmitDefaultValue = false)] public uint? MaxMonitoredItemsPerCall { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/Properties/AssemblyInfo.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Azure.IIoT.OpcUa.Publisher.Models.Tests")] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishBulkRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Publish in bulk request /// [DataContract] public sealed record class PublishBulkRequestModel { /// /// Node to add /// [DataMember(Name = "nodesToAdd", Order = 0, EmitDefaultValue = false)] public IReadOnlyList? NodesToAdd { get; set; } /// /// Node to remove /// [DataMember(Name = "nodesToRemove", Order = 1, EmitDefaultValue = false)] public IReadOnlyList? NodesToRemove { get; set; } /// /// Optional request header /// [DataMember(Name = "header", Order = 2, EmitDefaultValue = false)] public RequestHeaderModel? Header { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishBulkResponseModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Result of bulk request /// [DataContract] public sealed record class PublishBulkResponseModel { /// /// Node to add /// [DataMember(Name = "nodesToAdd", Order = 0, EmitDefaultValue = false)] public IReadOnlyList? NodesToAdd { get; set; } /// /// Node to remove /// [DataMember(Name = "nodesToRemove", Order = 1, EmitDefaultValue = false)] public IReadOnlyList? NodesToRemove { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishDiagnosticInfoModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Collections.Generic; using System.Runtime.Serialization; /// /// Model for a diagnostic info. /// [DataContract] public sealed record class PublishDiagnosticInfoModel { /// /// Endpoints covered by the diagnostics model. /// The endpoints are all part of the same writer /// group. Specify /// [DataMember(Name = "endpoints", Order = 0, EmitDefaultValue = true)] public IReadOnlyList? Endpoints { get; set; } /// /// SentMessagesPerSec /// [DataMember(Name = "sentMessagesPerSec", Order = 1, EmitDefaultValue = true)] public double SentMessagesPerSec { get; set; } /// /// IngestionDuration /// [DataMember(Name = "ingestionDuration", Order = 2, EmitDefaultValue = true)] public TimeSpan IngestionDuration { get; set; } /// /// IngressDataChanges /// [DataMember(Name = "ingressDataChanges", Order = 3, EmitDefaultValue = true)] public long IngressDataChanges { get; set; } /// /// IngressValueChanges /// [DataMember(Name = "ingressValueChanges", Order = 4, EmitDefaultValue = true)] public long IngressValueChanges { get; set; } /// /// IngressBatchBlockBufferSize /// [DataMember(Name = "ingressBatchBlockBufferSize", Order = 5, EmitDefaultValue = true)] public long IngressBatchBlockBufferSize { get; set; } /// /// EncodingBlockInputSize /// [DataMember(Name = "encodingBlockInputSize", Order = 6, EmitDefaultValue = true)] public long EncodingBlockInputSize { get; set; } /// /// EncodingBlockOutputSize /// [DataMember(Name = "encodingBlockOutputSize", Order = 7, EmitDefaultValue = true)] public long EncodingBlockOutputSize { get; set; } /// /// EncoderNotificationsProcessed /// [DataMember(Name = "encoderNotificationsProcessed", Order = 8, EmitDefaultValue = true)] public long EncoderNotificationsProcessed { get; set; } /// /// EncoderNotificationsDropped /// [DataMember(Name = "encoderNotificationsDropped", Order = 9, EmitDefaultValue = true)] public long EncoderNotificationsDropped { get; set; } /// /// EncoderIoTMessagesProcessed /// [DataMember(Name = "encoderIoTMessagesProcessed", Order = 10, EmitDefaultValue = true)] public long EncoderIoTMessagesProcessed { get; set; } /// /// EncoderAvgNotificationsMessage /// [DataMember(Name = "encoderAvgNotificationsMessage", Order = 11, EmitDefaultValue = true)] public double EncoderAvgNotificationsMessage { get; set; } /// /// EncoderAvgIoTMessageBodySize /// [DataMember(Name = "encoderAvgIoTMessageBodySize", Order = 12, EmitDefaultValue = true)] public double EncoderAvgIoTMessageBodySize { get; set; } /// /// EncoderAvgIoTChunkUsage /// [DataMember(Name = "encoderAvgIoTChunkUsage", Order = 13, EmitDefaultValue = true)] public double EncoderAvgIoTChunkUsage { get; set; } /// /// EstimatedIoTChunksPerDay /// [DataMember(Name = "estimatedIoTChunksPerDay", Order = 14, EmitDefaultValue = true)] public double EstimatedIoTChunksPerDay { get; set; } /// /// OutgressInputBufferCount /// [DataMember(Name = "outgressInputBufferCount", Order = 16, EmitDefaultValue = true)] public long OutgressInputBufferCount { get; set; } /// /// OutgressInputBufferDropped /// [DataMember(Name = "outgressInputBufferDropped", Order = 17, EmitDefaultValue = true)] public long OutgressInputBufferDropped { get; set; } /// /// OutgressIoTMessageCount /// [DataMember(Name = "outgressIoTMessageCount", Order = 18, EmitDefaultValue = true)] public long OutgressIoTMessageCount { get; set; } /// /// ConnectionRetries /// [DataMember(Name = "connectionRetries", Order = 19, EmitDefaultValue = true)] public long ConnectionRetries { get; set; } /// /// OpcEndpointConnected /// [DataMember(Name = "opcEndpointConnected", Order = 20, EmitDefaultValue = true)] public bool OpcEndpointConnected { get; set; } /// /// MonitoredOpcNodesSucceededCount /// [DataMember(Name = "monitoredOpcNodesSucceededCount", Order = 21, EmitDefaultValue = true)] public long MonitoredOpcNodesSucceededCount { get; set; } /// /// MonitoredOpcNodesFailedCount /// [DataMember(Name = "monitoredOpcNodesFailedCount", Order = 22, EmitDefaultValue = true)] public long MonitoredOpcNodesFailedCount { get; set; } /// /// Number of incoming event notifications /// [DataMember(Name = "ingressEventNotifications", Order = 23, EmitDefaultValue = true)] public long IngressEventNotifications { get; set; } /// /// Total incoming events so far. /// [DataMember(Name = "ingressEvents", Order = 24, EmitDefaultValue = true)] public long IngressEvents { get; set; } /// /// Encoder max message split ratio /// [DataMember(Name = "encoderMaxMessageSplitRatio", Order = 25, EmitDefaultValue = true)] public double EncoderMaxMessageSplitRatio { get; set; } /// /// Data changes received in the last minute /// [DataMember(Name = "ingressDataChangesInLastMinute", Order = 26, EmitDefaultValue = true)] public long IngressDataChangesInLastMinute { get; set; } /// /// Value changes received in the last minute /// [DataMember(Name = "ingressValueChangesInLastMinute", Order = 27, EmitDefaultValue = true)] public long IngressValueChangesInLastMinute { get; set; } /// /// Number of heartbeats of the total value changes /// [DataMember(Name = "ingressHeartbeats", Order = 28, EmitDefaultValue = true)] public long IngressHeartbeats { get; set; } /// /// Number of cyclic reads of the total value changes /// [DataMember(Name = "ingressCyclicReads", Order = 29, EmitDefaultValue = true)] public long IngressCyclicReads { get; set; } /// /// Legacy Endpoint Information /// public PublishedNodesEntryModel? Endpoint { get => Endpoints?.Count != 1 ? null : Endpoints[0]; set => Endpoints = value == null ? null : new List { value }; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishStartRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Publish request /// [DataContract] public sealed record class PublishStartRequestModel { /// /// Node to publish /// [DataMember(Name = "item", Order = 0)] [Required] public required PublishedItemModel Item { get; set; } /// /// Optional request header /// [DataMember(Name = "header", Order = 1, EmitDefaultValue = false)] public RequestHeaderModel? Header { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishStartResponseModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Result of publish request /// [DataContract] public sealed record class PublishStartResponseModel { /// /// Service result in case of error /// [DataMember(Name = "errorInfo", Order = 0, EmitDefaultValue = false)] public ServiceResultModel? ErrorInfo { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishStopRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Unpublish request /// [DataContract] public sealed record class PublishStopRequestModel { /// /// Node of published item to unpublish /// [DataMember(Name = "nodeId", Order = 0)] [Required] public required string NodeId { get; set; } /// /// Optional request header /// [DataMember(Name = "header", Order = 1, EmitDefaultValue = false)] public RequestHeaderModel? Header { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishStopResponseModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Result of publish stop request /// [DataContract] public sealed record class PublishStopResponseModel { /// /// Service result in case of error /// [DataMember(Name = "errorInfo", Order = 0, EmitDefaultValue = false)] public ServiceResultModel? ErrorInfo { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishedDataItemsModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Published items /// [DataContract] public sealed record class PublishedDataItemsModel { /// /// Published data variables /// [DataMember(Name = "publishedData", Order = 0)] public IReadOnlyList? PublishedData { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishedDataSetEventModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Describes event fields to be published /// [DataContract] public sealed record class PublishedDataSetEventModel { /// /// Identifier of event in the dataset. /// [DataMember(Name = "id", Order = 0, EmitDefaultValue = false)] public string? Id { get; set; } /// /// Event notifier to subscribe to (or start node) /// [DataMember(Name = "eventNotifier", Order = 1)] public string? EventNotifier { get; set; } /// /// Browse path to event notifier node (Publisher extension) /// [DataMember(Name = "browsePath", Order = 2, EmitDefaultValue = false)] public IReadOnlyList? BrowsePath { get; set; } /// /// Event fields to select /// [DataMember(Name = "selectedFields", Order = 3)] public IReadOnlyList? SelectedFields { get; set; } /// /// Filter to use to select event fields /// [DataMember(Name = "filter", Order = 4)] public ContentFilterModel? Filter { get; set; } /// /// Queue size (Publisher extension) /// [DataMember(Name = "queueSize", Order = 5, EmitDefaultValue = false)] public uint? QueueSize { get; set; } /// /// Discard new values if queue is full (Publisher extension) /// [DataMember(Name = "discardNew", Order = 6, EmitDefaultValue = false)] public bool? DiscardNew { get; set; } /// /// Monitoring mode (Publisher extension) /// [DataMember(Name = "monitoringMode", Order = 7, EmitDefaultValue = false)] public MonitoringMode? MonitoringMode { get; set; } /// /// Condition handling settings /// [DataMember(Name = "conditionHandling", Order = 9)] public ConditionHandlingOptionsModel? ConditionHandling { get; set; } /// /// Simple event Type definition id /// [DataMember(Name = "typeDefinitionId", Order = 10)] public string? TypeDefinitionId { get; set; } /// /// Event name /// [DataMember(Name = "publishedEventName", Order = 11, EmitDefaultValue = false)] public string? PublishedEventName { get; set; } /// /// Read event name from node. /// (Publisher extension) /// [DataMember(Name = "readEventNameFromNode", Order = 12, EmitDefaultValue = false)] public bool? ReadEventNameFromNode { get; set; } /// /// Model change event publishing configuration. /// (Publisher extension) /// [DataMember(Name = "modelChangeHandling", Order = 13, EmitDefaultValue = false)] public ModelChangeHandlingOptionsModel? ModelChangeHandling { get; set; } /// /// Triggering configuration. /// (Publisher extension) /// [DataMember(Name = "triggering", Order = 14, EmitDefaultValue = false)] public PublishedDataSetTriggerModel? Triggering { get; set; } /// /// Queue settings writer should use to publish messages /// to. Overrides the writer and writer group queue settings. /// (Publisher extension) /// [DataMember(Name = "publishing", Order = 15, EmitDefaultValue = false)] public PublishingQueueSettingsModel? Publishing { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishedDataSetMessageSchemaModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Used to generate various message schemas for a data set message /// [DataContract] public sealed record class PublishedDataSetMessageSchemaModel { /// /// The identifier of the schema /// [DataMember(Name = "id", Order = 1, EmitDefaultValue = false)] public required string Id { get; init; } /// /// Metadata describing the data set message content /// [DataMember(Name = "metaData", Order = 2, EmitDefaultValue = false)] public required PublishedDataSetMetaDataModel MetaData { get; init; } /// /// Dataset content encoding flags /// [DataMember(Name = "dataSetMessageContentFlags", Order = 3, EmitDefaultValue = false)] public required DataSetMessageContentFlags? DataSetMessageContentFlags { get; init; } /// /// Dataset field encoding flags /// [DataMember(Name = "dataSetFieldContentFlags", Order = 4, EmitDefaultValue = false)] public required DataSetFieldContentFlags? DataSetFieldContentFlags { get; init; } /// /// Optional type name for the message type /// [DataMember(Name = "typeName", Order = 5, EmitDefaultValue = false)] public string? TypeName { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishedDataSetMetaDataModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Published metadata /// [DataContract] public sealed record class PublishedDataSetMetaDataModel { /// /// Minor version /// [DataMember(Name = "minorVersion", Order = 0, EmitDefaultValue = false)] public uint MinorVersion { get; init; } /// /// Provides context of the dataset meta data that is to /// be emitted. If set to null no dataset metadata is emitted. /// [DataMember(Name = "dataSetMetaData", Order = 1, EmitDefaultValue = false)] public required DataSetMetaDataModel DataSetMetaData { get; init; } /// /// Field metadata /// [DataMember(Name = "fields", Order = 2, EmitDefaultValue = false)] public required IReadOnlyList Fields { get; init; } /// /// Structure schema definitions /// [DataMember(Name = "StructureDataTypes", Order = 3, EmitDefaultValue = false)] public IReadOnlyList? StructureDataTypes { get; set; } /// /// Enum schema definitions /// [DataMember(Name = "enumDataTypes", Order = 4, EmitDefaultValue = false)] public IReadOnlyList? EnumDataTypes { get; set; } /// /// Simple type schema definitions /// [DataMember(Name = "simpleDataTypes", Order = 5, EmitDefaultValue = false)] public IReadOnlyList? SimpleDataTypes { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishedDataSetMethodModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Describes methods that can be called and results published /// [DataContract] public sealed record class PublishedDataSetMethodModel { /// /// Identifier of method in the dataset. /// [DataMember(Name = "id", Order = 0, EmitDefaultValue = false)] public string? Id { get; set; } /// /// Node id of the method or starting point of browse path /// [DataMember(Name = "methodId", Order = 1, EmitDefaultValue = false)] public string? MethodId { get; set; } /// /// Browse path to event notifier node (Publisher extension) /// [DataMember(Name = "browsePath", Order = 2, EmitDefaultValue = false)] public IReadOnlyList? BrowsePath { get; set; } /// /// Method metadata /// [DataMember(Name = "metadata", Order = 3)] public MethodMetadataModel? Metadata { get; set; } /// /// Simple event Type definition id /// [DataMember(Name = "typeDefinitionId", Order = 4)] public string? TypeDefinitionId { get; set; } /// /// Triggering configuration. /// [DataMember(Name = "triggering", Order = 5, EmitDefaultValue = false)] public PublishedDataSetTriggerModel? Triggering { get; set; } /// /// Queue settings writer should use to publish messages /// to. Overrides the writer and writer group queue settings. /// [DataMember(Name = "publishing", Order = 6, EmitDefaultValue = false)] public PublishingQueueSettingsModel? Publishing { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishedDataSetModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Published data set describing metadata and dataset source /// [DataContract] public sealed record class PublishedDataSetModel { /// /// Name of the published dataset /// [DataMember(Name = "name", Order = 0, EmitDefaultValue = false)] public string? Name { get; set; } /// /// Data set source /// [DataMember(Name = "dataSetSource", Order = 1)] public PublishedDataSetSourceModel? DataSetSource { get; set; } /// /// Provides context of the dataset meta data that is to /// be emitted. If set to null no dataset metadata is emitted. /// [DataMember(Name = "dataSetMetaData", Order = 2, EmitDefaultValue = false)] public DataSetMetaDataModel? DataSetMetaData { get; set; } /// /// Extension fields /// [DataMember(Name = "extensionFields", Order = 3, EmitDefaultValue = false)] public IReadOnlyList? ExtensionFields { get; set; } /// /// Send keep alive messages for the data set /// [DataMember(Name = "sendKeepAlive", Order = 4, EmitDefaultValue = false)] public bool? SendKeepAlive { get; set; } /// /// Whenever sending a keep alive message send a keyframe /// message instead. /// [DataMember(Name = "keepAliveAsKeyFrame", Order = 5, EmitDefaultValue = false)] public bool? KeepAliveAsKeyFrame { get; set; } /// /// The data set routing option /// [DataMember(Name = "routing", Order = 6, EmitDefaultValue = false)] public DataSetRoutingMode? Routing { get; set; } /// /// Root node of the dataset /// (Publisher extension) /// [DataMember(Name = "rootNode", Order = 7, EmitDefaultValue = false)] public string? RootNode { get; set; } /// /// Type of the dataset /// (Publisher extension) /// [DataMember(Name = "type", Order = 8, EmitDefaultValue = false)] public string? Type { get; set; } /// /// Subject of the dataset /// (Publisher extension) /// [DataMember(Name = "subject", Order = 9, EmitDefaultValue = false)] public string? Subject { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishedDataSetSettingsModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Published dataset settings - corresponds to SubscriptionModel /// [DataContract] public sealed record class PublishedDataSetSettingsModel { /// /// Publishing interval /// [DataMember(Name = "publishingInterval", Order = 0, EmitDefaultValue = false)] public TimeSpan? PublishingInterval { get; set; } /// /// Life time /// [DataMember(Name = "lifeTimeCount", Order = 1, EmitDefaultValue = false)] public uint? LifeTimeCount { get; set; } /// /// Max keep alive count /// [DataMember(Name = "maxKeepAliveCount", Order = 2, EmitDefaultValue = false)] public uint? MaxKeepAliveCount { get; set; } /// /// Max notifications per publish /// [DataMember(Name = "maxNotificationsPerPublish", Order = 3, EmitDefaultValue = false)] public uint? MaxNotificationsPerPublish { get; set; } /// /// Priority /// [DataMember(Name = "priority", Order = 4, EmitDefaultValue = false)] public byte? Priority { get; set; } /// /// Triggers automatic monitored items display name discovery /// [DataMember(Name = "resolveDisplayName", Order = 5, EmitDefaultValue = false)] public bool? ResolveDisplayName { get; set; } /// /// Use deferred acknoledgements /// [DataMember(Name = "useDeferredAcknoledgements", Order = 6, EmitDefaultValue = false)] public bool? UseDeferredAcknoledgements { get; set; } /// /// Will set the subscription to have publishing /// enabled and every monitored item created to be /// in desired monitoring mode. /// [DataMember(Name = "enableImmediatePublishing", Order = 8, EmitDefaultValue = false)] public bool? EnableImmediatePublishing { get; set; } /// /// Enable sequential publishing feature in the stack. /// [DataMember(Name = "enableSequentialPublishing", Order = 9, EmitDefaultValue = false)] public bool? EnableSequentialPublishing { get; set; } /// /// Republish after transferring the subscription during /// reconnect handling. /// [DataMember(Name = "republishAfterTransfer", Order = 10, EmitDefaultValue = false)] public bool? RepublishAfterTransfer { get; set; } /// /// Subscription watchdog behavior /// [DataMember(Name = "watchdogBehavior", Order = 11, EmitDefaultValue = false)] public SubscriptionWatchdogBehavior? WatchdogBehavior { get; set; } /// /// Monitored item watchdog timeout /// [DataMember(Name = "monitoredItemWatchdogTimeout", Order = 13, EmitDefaultValue = false)] public TimeSpan? MonitoredItemWatchdogTimeout { get; set; } /// /// Monitored item watchdog timeout /// [DataMember(Name = "monitoredItemWatchdogCondition", Order = 14, EmitDefaultValue = false)] public MonitoredItemWatchdogCondition? MonitoredItemWatchdogCondition { get; set; } /// /// Default sampling interval /// [DataMember(Name = "defaultSamplingInterval", Order = 15, EmitDefaultValue = false)] public TimeSpan? DefaultSamplingInterval { get; set; } /// /// Default heartbeat interval /// [DataMember(Name = "DefaultHeartbeatInterval", Order = 16, EmitDefaultValue = false)] public TimeSpan? DefaultHeartbeatInterval { get; set; } /// /// The default behavior of heartbeat /// [DataMember(Name = "DefaultHeartbeatBehavior", Order = 17, EmitDefaultValue = false)] public HeartbeatBehavior? DefaultHeartbeatBehavior { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishedDataSetSourceModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Data set source akin to a monitored item subscription. /// [DataContract] public sealed record class PublishedDataSetSourceModel { /// /// Either published data variables /// [DataMember(Name = "publishedVariables", Order = 0, EmitDefaultValue = false)] public PublishedDataItemsModel? PublishedVariables { get; set; } /// /// Or published events data /// [DataMember(Name = "publishedEvents", Order = 1, EmitDefaultValue = false)] public PublishedEventItemsModel? PublishedEvents { get; set; } /// /// Or published method calls /// [DataMember(Name = "publishedMethods", Order = 2, EmitDefaultValue = false)] public PublishedMethodItemsModel? PublishedMethods { get; set; } /// /// Connection information (publisher extension) /// [DataMember(Name = "connection", Order = 3)] public ConnectionModel? Connection { get; set; } /// /// Subscription settings (publisher extension) /// [DataMember(Name = "subscriptionSettings", Order = 4, EmitDefaultValue = false)] public PublishedDataSetSettingsModel? SubscriptionSettings { get; set; } /// /// Identifies the source of the dataset to subscribers. /// (publisher extension) /// [DataMember(Name = "uri", Order = 5, EmitDefaultValue = false)] public string? Uri { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishedDataSetTriggerModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Triggered items. /// [DataContract] public sealed record class PublishedDataSetTriggerModel { /// /// Either published data variables /// [DataMember(Name = "publishedVariables", Order = 0, EmitDefaultValue = false)] public PublishedDataItemsModel? PublishedVariables { get; set; } /// /// Or published events triggering /// [DataMember(Name = "publishedEvents", Order = 1, EmitDefaultValue = false)] public PublishedEventItemsModel? PublishedEvents { get; set; } /// /// Or published calls /// [DataMember(Name = "publishedMethods", Order = 2, EmitDefaultValue = false)] public PublishedMethodItemsModel? PublishedMethods { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishedDataSetVariableModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Furly.Extensions.Serializers; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// A published variable /// [DataContract] public sealed record class PublishedDataSetVariableModel { /// /// Field index of this variable in the dataset. /// [DataMember(Name = "fieldIndex", Order = 0, EmitDefaultValue = false)] public int FieldIndex { get; set; } /// /// Node id of the variable /// [DataMember(Name = "publishedVariableNodeId", Order = 1, EmitDefaultValue = false)] public string? PublishedVariableNodeId { get; set; } /// /// Display name of the published variable /// [DataMember(Name = "publishedVariableDisplayName", Order = 2, EmitDefaultValue = false)] public string? PublishedVariableDisplayName { get; set; } /// /// An optional component path from the node identified by /// PublishedVariableNodeId to the actual node to publish /// (Publisher extension). /// [DataMember(Name = "browsePath", Order = 3, EmitDefaultValue = false)] public IReadOnlyList? BrowsePath { get; set; } /// /// Default is . /// [DataMember(Name = "attribute", Order = 4, EmitDefaultValue = false)] public NodeAttribute? Attribute { get; set; } /// /// Index range /// [DataMember(Name = "indexRange", Order = 5, EmitDefaultValue = false)] public string? IndexRange { get; set; } /// /// Sampling Interval hint - default is best effort /// [DataMember(Name = "samplingIntervalHint", Order = 6, EmitDefaultValue = false)] public TimeSpan? SamplingIntervalHint { get; set; } /// /// Data change trigger /// [DataMember(Name = "dataChangeTrigger", Order = 7, EmitDefaultValue = false)] public DataChangeTriggerType? DataChangeTrigger { get; set; } /// /// Deadband type /// [DataMember(Name = "deadbandType", Order = 8, EmitDefaultValue = false)] public DeadbandType? DeadbandType { get; set; } /// /// Deadband value /// [DataMember(Name = "deadbandValue", Order = 9, EmitDefaultValue = false)] public double? DeadbandValue { get; set; } /// /// Substitution value for bad / empty results (not supported yet) /// [DataMember(Name = "substituteValue", Order = 10, EmitDefaultValue = false)] [SkipValidation] public VariantValue? SubstituteValue { get; set; } /// /// Monitoring mode (Publisher extension) /// [DataMember(Name = "monitoringMode", Order = 12, EmitDefaultValue = false)] public MonitoringMode? MonitoringMode { get; set; } /// /// Queue size (Publisher extension) /// [DataMember(Name = "serverQueueSize", Order = 13, EmitDefaultValue = false)] public uint? ServerQueueSize { get; set; } /// /// Discard new values if queue is full (Publisher extension) /// [DataMember(Name = "discardNew", Order = 14, EmitDefaultValue = false)] public bool? DiscardNew { get; set; } /// /// Behavior of the heartbeatfeature (Publisher extension) /// [DataMember(Name = "heartbeatBehavior", Order = 15, EmitDefaultValue = false)] public HeartbeatBehavior? HeartbeatBehavior { get; set; } /// /// Hidden trigger that triggers reporting this variable on /// at a minimum interval. Mutually exclusive with TriggerId. /// (Publisher extension) /// [DataMember(Name = "heartbeatInterval", Order = 16, EmitDefaultValue = false)] public TimeSpan? HeartbeatInterval { get; set; } /// /// Instruct the monitored item to skip the first /// received value (Publisher extension) /// [DataMember(Name = "skipFirst", Order = 17, EmitDefaultValue = false)] public bool? SkipFirst { get; set; } /// /// Identifier of field in the dataset class. /// [DataMember(Name = "dataSetClassFieldId", Order = 18, EmitDefaultValue = false)] public Guid DataSetClassFieldId { get; set; } /// /// Try and perform a cyclic read using the client /// (Publisher extension) /// [DataMember(Name = "samplingUsingCyclicRead", Order = 19, EmitDefaultValue = false)] public bool? SamplingUsingCyclicRead { get; set; } /// /// Try and register the node before sampling /// (Publisher extension) /// [DataMember(Name = "registerNodeForSampling", Order = 20, EmitDefaultValue = false)] public bool? RegisterNodeForSampling { get; set; } /// /// Read the display name from the node /// (Publisher extension) /// [DataMember(Name = "readDisplayNameFromNode", Order = 21, EmitDefaultValue = false)] public bool? ReadDisplayNameFromNode { get; set; } /// /// Triggering configuration /// (Publisher extension) /// [DataMember(Name = "triggering", Order = 22, EmitDefaultValue = false)] public PublishedDataSetTriggerModel? Triggering { get; set; } /// /// Queue settings writer should use to publish messages /// to. Overrides the writer and writer group queue settings. /// (Publisher extension) /// [DataMember(Name = "publishing", Order = 23, EmitDefaultValue = false)] public PublishingQueueSettingsModel? Publishing { get; set; } /// /// The max cache age to use for cyclic reads. /// Default is 0 (uncached reads). /// [DataMember(Name = "cyclicReadMaxAge", Order = 24, EmitDefaultValue = false)] public TimeSpan? CyclicReadMaxAge { get; set; } /// /// Type definition id /// [DataMember(Name = "typeDefinitionId", Order = 25, EmitDefaultValue = false)] public string? TypeDefinitionId { get; set; } /// /// Unique Identifier of variable in the dataset. /// [DataMember(Name = "id", Order = 30, EmitDefaultValue = false)] public string? Id { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishedEventItemsModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Published items /// [DataContract] public sealed record class PublishedEventItemsModel { /// /// Published data variables /// [DataMember(Name = "publishedData", Order = 0)] public IReadOnlyList? PublishedData { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishedFieldMetaDataModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Collections.Generic; using System.Runtime.Serialization; /// /// Metadata containing the field schema definitions for /// items produced by the dataset writer /// [DataContract] public record class PublishedFieldMetaDataModel { /// /// Name of the field /// [DataMember(Name = "name", Order = 0, EmitDefaultValue = false)] public required string Name { get; init; } /// /// Field id /// [DataMember(Name = "id", Order = 1, EmitDefaultValue = false)] public Guid Id { get; init; } /// /// Description /// [DataMember(Name = "description", Order = 2, EmitDefaultValue = false)] public string? Description { get; init; } /// /// Flags /// [DataMember(Name = "flags", Order = 3, EmitDefaultValue = false)] public ushort Flags { get; init; } /// /// Underlying built in type of the type /// [DataMember(Name = "builtInType", Order = 4, EmitDefaultValue = false)] public byte BuiltInType { get; init; } /// /// Data type /// [DataMember(Name = "dataType", Order = 5, EmitDefaultValue = false)] public string? DataType { get; init; } /// /// Value rank of the type /// [DataMember(Name = "valueRank", Order = 6, EmitDefaultValue = false)] public int ValueRank { get; init; } /// /// Array dimensions if non scalar /// [DataMember(Name = "arrayDimensions", Order = 7, EmitDefaultValue = false)] public IReadOnlyList? ArrayDimensions { get; init; } /// /// Max string length /// [DataMember(Name = "maxStringLength", Order = 8, EmitDefaultValue = false)] public uint MaxStringLength { get; init; } /// /// Properties of the field /// [DataMember(Name = "properties", Order = 10, EmitDefaultValue = false)] public IReadOnlyList? Properties { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishedItemListRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Request list of published items /// [DataContract] public sealed record class PublishedItemListRequestModel { /// /// Continuation token or null to start /// [DataMember(Name = "continuationToken", Order = 0, EmitDefaultValue = false)] public string? ContinuationToken { get; set; } /// /// Optional request header /// [DataMember(Name = "header", Order = 2, EmitDefaultValue = false)] public RequestHeaderModel? Header { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishedItemListResponseModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// List of published nodes /// [DataContract] public sealed record class PublishedItemListResponseModel { /// /// Monitored items /// [DataMember(Name = "items", Order = 0)] public IReadOnlyList? Items { get; set; } /// /// Continuation or null if final /// [DataMember(Name = "continuationToken", Order = 1, EmitDefaultValue = false)] public string? ContinuationToken { get; set; } } /// /// List of published nodes /// [DataContract] public sealed record class SetEndpointConfigurationRequestModel { /// /// Monitored items /// [DataMember(Name = "items", Order = 0)] public IReadOnlyList? Items { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishedItemModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// A monitored and published item /// [DataContract] public sealed record class PublishedItemModel { /// /// Variable node monitored /// [DataMember(Name = "nodeId", Order = 0)] [Required] public required string NodeId { get; set; } /// /// Display name of the variable node monitored /// [DataMember(Name = "displayName", Order = 1, EmitDefaultValue = false)] public string? DisplayName { get; set; } /// /// Publishing interval to use /// [DataMember(Name = "publishingInterval", Order = 2, EmitDefaultValue = false)] public TimeSpan? PublishingInterval { get; set; } /// /// Sampling interval to use /// [DataMember(Name = "samplingInterval", Order = 3, EmitDefaultValue = false)] public TimeSpan? SamplingInterval { get; set; } /// /// Heartbeat interval to use /// [DataMember(Name = "heartbeatInterval", Order = 4, EmitDefaultValue = false)] public TimeSpan? HeartbeatInterval { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishedMethodItemsModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Published items /// [DataContract] public sealed record class PublishedMethodItemsModel { /// /// Published data variables /// [DataMember(Name = "publishedData", Order = 0)] public IReadOnlyList? PublishedData { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishedNetworkMessageSchemaModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Used to generate various message schemas for a network message /// public sealed record class PublishedNetworkMessageSchemaModel { /// /// The identifier of the schema to generate /// [DataMember(Name = "id", Order = 1, EmitDefaultValue = false)] public required string Id { get; init; } /// /// The version of the schema /// [DataMember(Name = "version", Order = 2, EmitDefaultValue = false)] public required ulong Version { get; init; } /// /// Data set messages in the network message /// [DataMember(Name = "dataSetMessages", Order = 3, EmitDefaultValue = false)] public required IReadOnlyList DataSetMessages { get; init; } /// /// Dataset content encoding flags /// [DataMember(Name = "networkMessageContentFlags", Order = 4, EmitDefaultValue = false)] public required NetworkMessageContentFlags? NetworkMessageContentFlags { get; init; } /// /// Optional type name for the message type /// [DataMember(Name = "typeName", Order = 5, EmitDefaultValue = false)] public string? TypeName { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishedNodeCreateAssetRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Request to create an asset in the configuration api /// /// Type of the configuration [DataContract] public sealed record class PublishedNodeCreateAssetRequestModel { /// /// Optional request header to use for all operations /// against the server. /// [DataMember(Name = "header", Order = 1, EmitDefaultValue = false)] public RequestHeaderModel? Header { get; init; } /// /// The asset entry in the configuration that is to be /// created or updated. It must contain the writer group /// id as well as the data set name which is the name of /// asset. /// [DataMember(Name = "entry", Order = 2)] [Required] public required PublishedNodesEntryModel Entry { get; init; } /// /// The asset configuration to use when creating the asset. /// [DataMember(Name = "configuration", Order = 3)] [Required] public required T Configuration { get; init; } /// /// Time to wait after the configuration is applied to perform /// the configuration of the asset in the configuration api. /// This is to let the server settle. /// [DataMember(Name = "waitTime", Order = 4, EmitDefaultValue = false)] public TimeSpan? WaitTime { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishedNodeDeleteAssetRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Contains entry in the published nodes configuration representing /// the asset as well as an optional request header. /// [DataContract] public sealed record class PublishedNodeDeleteAssetRequestModel { /// /// Optional request header to use for all operations /// against the server. /// [DataMember(Name = "header", Order = 1, EmitDefaultValue = false)] public RequestHeaderModel? Header { get; init; } /// /// The asset entry in the configuration that is either /// to be deleted. It must contain the as well as the writer /// id which represents the asset id. /// [DataMember(Name = "entry", Order = 2)] [Required] public required PublishedNodesEntryModel Entry { get; init; } /// /// The asset on the server is deleted no matter whether /// the removal in the publisher configuration was successful /// or not. /// [DataMember(Name = "force", Order = 3, EmitDefaultValue = false)] public bool Force { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishedNodeExpansionModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// /// Node expansion configuration. Configures how an entry should /// be expanded into configuration. If a node is an object it is /// expanded to all contained variables. /// /// /// If a node is an object type, all objects of that type are /// searched from the object root node. These found objects are /// then expanded into their variables. /// /// /// If the node is a variable, the variable is expanded to include /// all contained variables or properties. All entries will have /// the data set field id configured as data set class id. /// /// /// If a node is a variable type, then all variables of this type /// are found and added to a single writer entry. Note: That by /// themselves these variables are no further expanded. /// /// [DataContract] public sealed record class PublishedNodeExpansionModel { /// /// Optional request header to use for all operations /// against the server. /// [DataMember(Name = "header", Order = 1, EmitDefaultValue = false)] public RequestHeaderModel? Header { get; init; } /// /// By default the api will create a new distinct /// writer per expanded object. Objects that cannot /// be expanded are part of the originally provided /// writer. The writer id is then post fixed with /// the data set field id of the object node field. /// If true, all variables of all expanded nodes are /// added to the originally provided entry. /// [DataMember(Name = "createSingleWriter", Order = 2, EmitDefaultValue = false)] public bool CreateSingleWriter { get; init; } /// /// Max number of levels to expand an instance node /// such as an object or variable into resulting /// variables. /// If the node is a variable instance to start with /// but the /// property is set to excluded it, then setting this /// value to 0 is equivalent to a value of 1 to get /// the first level of variables contained in the /// variable, but not the variable itself. Otherwise /// only the variable itelf is returned. If the node /// is an object instance, 0 is equivalent to /// infinite and all levels are expanded. /// [DataMember(Name = "maxLevelsToExpand", Order = 3, EmitDefaultValue = false)] public uint MaxLevelsToExpand { get; init; } /// /// Do not consider subtypes of an object type when /// searching for instances of the type. /// [DataMember(Name = "noSubTypesOfTypeNodes", Order = 4, EmitDefaultValue = false)] public bool NoSubTypesOfTypeNodes { get; init; } /// /// If the node is an object or variable instance do /// not include it but only the instances underneath /// them. /// [DataMember(Name = "excludeRootIfInstanceNode", Order = 5, EmitDefaultValue = false)] public bool ExcludeRootIfInstanceNode { get; init; } /// /// Max browse depth for object search operation or /// when searching for an instance of a type. /// To only expand an object to its variables set /// this value to 0. The depth of expansion of a /// variable itself can be controlled via the /// " property. /// If the root object is excluded a value of 0 is /// equivalent to a value of 1 to get the first level /// of objects contained in the object but not the /// object itself, e.g. a folder object. /// [DataMember(Name = "maxDepth", Order = 6, EmitDefaultValue = false)] public uint? MaxDepth { get; init; } /// /// If false, treats instance nodes found just like /// objects that need to be expanded. In case of a /// companion spec object type this could be set to /// true, flattening the structure into a single /// writer that represents the object in its entirety. /// However, when using generic interfaces that can /// be implemented across objects in the address /// space and only its variables are important, it /// might be useful to set this to false. /// [DataMember(Name = "flattenTypeInstance", Order = 7, EmitDefaultValue = false)] public bool FlattenTypeInstance { get; init; } /// /// Include not just variables and events but also /// methods when expanding an object. /// [DataMember(Name = "includeMethods", Order = 8, EmitDefaultValue = false)] public bool IncludeMethods { get; init; } /// /// Errors are silently discarded and only /// successfully expanded nodes are returned. /// [DataMember(Name = "discardErrors", Order = 9, EmitDefaultValue = false)] public bool DiscardErrors { get; init; } /// /// Use the browse name as display name for nodes. The /// display name is rooted in the parent node from /// which browsing occurs, or just the browse name if /// the browse root is not a parent. /// [DataMember(Name = "useBrowseNameAsDisplayName", Order = 10, EmitDefaultValue = false)] public bool UseBrowseNameAsDisplayName { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishedNodesEntryModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Furly.Extensions.Messaging; using Furly.Extensions.Serializers; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// /// Configuration model for OPC UA Publisher that defines how /// OPC UA nodes are published to messaging systems. Used to /// configure connections to OPC UA servers, setup node /// monitoring, and control message publishing. /// /// /// Key features: /// - Endpoint configuration and security settings /// - Writer group and dataset organization /// - Publishing intervals and sampling controls /// - Message batching and triggering /// - Subscription and monitoring options /// - Heartbeat and watchdog behaviors /// - Security modes and authentication /// /// /// For detailed configuration options, see individual /// properties. /// /// [DataContract] public record class PublishedNodesEntryModel { /// /// A monotonically increasing number identifying the change /// version. At this point the version number is informational /// only, but should be provided in API requests if available. /// Not used inside file based configuration. /// [DataMember(Name = "Version", Order = 0, EmitDefaultValue = false)] public uint? Version { get; set; } /// /// The time the Publisher configuration was last updated. /// Read only and informational only. /// [DataMember(Name = "LastChangeDateTime", Order = 1, EmitDefaultValue = false)] public DateTimeOffset? LastChangeDateTime { get; set; } /// /// The unique identifier for a data set writer used to collect /// OPC UA nodes to be semantically grouped and published with /// the same publishing interval. When not specified, uses a /// string representing the common publishing interval of the /// nodes in the data set collection. This attribute uniquely /// identifies a data set within a DataSetWriterGroup. The /// uniqueness is determined using the provided DataSetWriterId /// and the publishing interval of the grouped OpcNodes. /// [DataMember(Name = "DataSetWriterId", Order = 2, EmitDefaultValue = false)] public string? DataSetWriterId { get; set; } /// /// The data set writer group collecting datasets defined for a /// certain endpoint. This attribute is used to identify the /// session opened into the server. The default value consists /// of the EndpointUrl string, followed by a deterministic hash /// composed of the EndpointUrl, UseSecurity, /// OpcAuthenticationMode, UserName and Password attributes. /// [DataMember(Name = "DataSetWriterGroup", Order = 3, EmitDefaultValue = false)] public string? DataSetWriterGroup { get; set; } /// /// The DataSet collection grouping the nodes to be published /// for the specific DataSetWriter. Each node can specify /// monitoring parameters including sampling intervals, deadband /// settings, and event filtering options. Contains variable /// nodes or event notifiers to monitor. /// [DataMember(Name = "OpcNodes", Order = 4, EmitDefaultValue = false)] public IList? OpcNodes { get; set; } /// /// The optional dataset class id as it shall appear in dataset /// messages and dataset metadata. Used to uniquely identify the /// type of dataset being published. Default: Guid.Empty /// [DataMember(Name = "DataSetClassId", Order = 5, EmitDefaultValue = false)] public Guid DataSetClassId { get; set; } /// /// The optional name of the dataset as it will appear in the /// dataset metadata. Used for identification and organization /// of datasets. /// [DataMember(Name = "DataSetName", Order = 6, EmitDefaultValue = false)] public string? DataSetName { get; set; } /// /// The publishing interval used for a grouped set of nodes /// under a certain DataSetWriter, expressed in milliseconds. /// When a specific node underneath DataSetWriter defines /// OpcPublishingInterval (or Timespan), its value will /// overwrite this interval and potentially split the data set /// writer into more than one subscription. Ignored when /// DataSetPublishingIntervalTimespan is present. /// [DataMember(Name = "DataSetPublishingInterval", Order = 7, EmitDefaultValue = false)] public int? DataSetPublishingInterval { get; set; } /// /// The publishing interval for a dataset writer, expressed as a /// TimeSpan value. Takes precedence over /// DataSetPublishingInterval if defined. Provides more precise /// control over timing than milliseconds. When overridden by /// node-specific intervals, the writer may split into multiple /// subscriptions. /// [DataMember(Name = "DataSetPublishingIntervalTimespan", Order = 8, EmitDefaultValue = false)] public TimeSpan? DataSetPublishingIntervalTimespan { get; set; } /// /// Controls key frame insertion frequency in the message /// stream. A key frame contains all current values, while /// delta frames only contain changes. Setting this ensures /// periodic complete state updates, useful for late-joining /// consumers or state synchronization. Key frames can also /// include configured DataSetExtensionFields for additional /// context. Default: 0 (key frames disabled) /// [DataMember(Name = "DataSetKeyFrameCount", Order = 9, EmitDefaultValue = false)] public uint? DataSetKeyFrameCount { get; set; } /// /// The interval in milliseconds at which metadata messages are /// sent, even when the metadata has not changed. Only applies /// when metadata messaging is supported or explicitly enabled. /// Ignored when MetaDataUpdateTimeTimespan is defined. /// [DataMember(Name = "MetaDataUpdateTime", Order = 10, EmitDefaultValue = false)] public int? MetaDataUpdateTime { get; set; } /// /// The interval as TimeSpan at which metadata messages are /// sent, even when metadata has not changed. Takes precedence /// over MetaDataUpdateTime if both are defined. Only applies /// when metadata messaging is supported or explicitly enabled. /// [DataMember(Name = "MetaDataUpdateTimeTimespan", Order = 11, EmitDefaultValue = false)] public TimeSpan? MetaDataUpdateTimeTimespan { get; set; } /// /// Controls whether to send keep alive messages for this /// dataset when a subscription keep alive notification is /// received. Keep alive messages help maintain connection /// status awareness. Only valid if the messaging mode supports /// keep alive messages. Default: false /// [DataMember(Name = "SendKeepAliveDataSetMessages", Order = 12, EmitDefaultValue = false)] public bool? SendKeepAliveDataSetMessages { get; set; } /// /// The required OPC UA server endpoint URL to connect to. This /// is the only required field in the configuration. Format: /// "opc.tcp://host:port/path" /// [DataMember(Name = "EndpointUrl", Order = 13)] [Required] public required string EndpointUrl { get; set; } /// /// Defines how many publishing timer expirations to wait /// before sending a keep-alive message when no notifications /// are pending. Works with SendKeepAliveDataSetMessages to /// maintain connection awareness. Keep-alive messages help /// detect connection issues even when no data changes are /// occurring. /// [DataMember(Name = "MaxKeepAliveCount", Order = 14, EmitDefaultValue = false)] public uint? MaxKeepAliveCount { get; set; } /// /// The optional description of the dataset. /// [DataMember(Name = "DataSetDescription", Order = 15, EmitDefaultValue = false)] public string? DataSetDescription { get; set; } /// /// Priority of the writer subscription. /// [DataMember(Name = "Priority", Order = 16, EmitDefaultValue = false)] public byte? Priority { get; set; } /// /// Optional key-value pairs inserted into key frame and /// metadata messages in the same data set. Values are /// formatted using OPC UA Variant JSON encoding. Used to add /// contextual information to datasets. /// [DataMember(Name = "DataSetExtensionFields", Order = 17, EmitDefaultValue = false)] [SkipValidation] public IDictionary? DataSetExtensionFields { get; set; } /// /// The specific security mode to use for the specified /// endpoint. Overrides setting. If /// the security mode is not available with any configured /// security policy connectivity will fail. Default: /// if /// is true, otherwise /// [DataMember(Name = "EndpointSecurityMode", Order = 18, EmitDefaultValue = false)] public SecurityMode? EndpointSecurityMode { get; set; } /// /// The security policy URI to use for the endpoint connection. /// Overrides UseSecurity setting and refines /// EndpointSecurityMode choice. Examples include /// "http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256". /// If the specified policy is not available with the chosen /// security mode, connectivity will fail. This allows enforcing /// specific security requirements. /// [DataMember(Name = "EndpointSecurityPolicy", Order = 19, EmitDefaultValue = false)] public string? EndpointSecurityPolicy { get; set; } /// /// The messaging mode to use when publishing the data sets in /// the writer group. Supported modes include: /// - PubSub: OPC UA PubSub standard format /// - Samples: Simple JSON telemetry format (default) /// - FullNetworkMessages: Complete network message format /// - DataSetMessages: Dataset-only message format /// - RawDataSets: Minimal dataset format /// See messageformats.md documentation for details on each /// format. /// [DataMember(Name = "MessagingMode", Order = 20, EmitDefaultValue = false)] public MessagingMode? MessagingMode { get; set; } /// /// The encoding format to use for messages in the writer /// group. Options include: /// - Json: Standard JSON encoding /// - JsonReversible: Lossless JSON encoding /// - JsonGzip: Compressed JSON /// - JsonReversibleGzip: Compressed lossless JSON /// - Uadp: Binary OPC UA encoding (most efficient) /// Choose based on bandwidth requirements and receiver /// capabilities. /// [DataMember(Name = "MessageEncoding", Order = 21, EmitDefaultValue = false)] public MessageEncoding? MessageEncoding { get; set; } /// /// The number of notifications that are queued before a /// network message is generated. Controls message batching for /// optimizing network traffic vs latency. For historic reasons /// the default value is 50 unless otherwise configured via the /// --bs command line option. /// [DataMember(Name = "BatchSize", Order = 22, EmitDefaultValue = false)] public uint? BatchSize { get; set; } /// /// The interval at which batched network messages are /// published, in milliseconds. Messages are published when /// this interval elapses or when BatchSize is reached. For /// historic reasons the default is 10 seconds unless /// configured via --bi. Ignored when /// BatchTriggerIntervalTimespan is specified. Used with /// BatchSize to optimize network traffic vs latency. /// [DataMember(Name = "BatchTriggerInterval", Order = 23, EmitDefaultValue = false)] public int? BatchTriggerInterval { get; set; } /// /// The interval at which batched network messages are /// published, as a TimeSpan. Takes precedence over /// BatchTriggerInterval if both are defined. Messages are /// published when this interval elapses or when BatchSize is /// reached. Provides more precise control over publishing /// timing than millisecond interval. Used with BatchSize to /// optimize network traffic vs latency. /// [DataMember(Name = "BatchTriggerIntervalTimespan", Order = 24, EmitDefaultValue = false)] public TimeSpan? BatchTriggerIntervalTimespan { get; set; } /// /// Use reverse connect to connect ot the endpoint /// [DataMember(Name = "UseReverseConnect", Order = 25, EmitDefaultValue = false)] public bool? UseReverseConnect { get; set; } /// /// Configure the dataset routing behavior for the contained /// nodes. /// [DataMember(Name = "DataSetRouting", Order = 26, EmitDefaultValue = false)] public DataSetRoutingMode? DataSetRouting { get; set; } /// /// Overrides the default writer group topic template for /// message routing. Used to customize where messages from this /// writer group are published. Particularly useful when /// publishing to MQTT topics or message queues where specific /// routing patterns are needed. /// [DataMember(Name = "WriterGroupQueueName", Order = 27, EmitDefaultValue = false)] public string? WriterGroupQueueName { get; set; } /// /// The quality of service level for message delivery. Options: /// - AtMostOnce: Fire and forget delivery /// - AtLeastOnce: Guaranteed delivery, possible duplicates /// (default) /// - ExactlyOnce: Guaranteed single delivery /// QoS is only applied if supported by the chosen transport. /// [DataMember(Name = "WriterGroupQualityOfService", Order = 28, EmitDefaultValue = false)] public QoS? WriterGroupQualityOfService { get; set; } /// /// Specifies the transport technology to use for publishing /// messages. Controls how messages are delivered to the /// messaging system. Available transports can be found in /// transports.md documentation. Common options include Azure /// IoT Hub (default), MQTT, and MQTT v5. /// [DataMember(Name = "WriterGroupTransport", Order = 29, EmitDefaultValue = false)] public WriterGroupTransport? WriterGroupTransport { get; set; } /// /// Controls whether to use a secure OPC UA transport mode to /// establish a session. When true, defaults to /// SecurityMode.NotNone which requires signed or encrypted /// communication. When false, uses SecurityMode.None with no /// security. Can be overridden by EndpointSecurityMode and /// EndpointSecurityPolicy settings. Use encrypted /// communication whenever possible to protect credentials and /// data. /// [DataMember(Name = "UseSecurity", Order = 30)] public bool? UseSecurity { get; set; } /// /// Specifies the authentication mode for connecting to the OPC /// UA server. Supported modes: /// - Anonymous: No authentication (default) /// - UsernamePassword: Username and password authentication /// - Certificate: Certificate-based authentication using X.509 /// certificates /// When using credentials or certificates, encrypted /// communication should be enabled via UseSecurity or /// EndpointSecurityMode to protect secrets. For certificate /// auth, the certificate must be in the User certificate /// store. /// [DataMember(Name = "OpcAuthenticationMode", Order = 31)] public OpcAuthenticationMode OpcAuthenticationMode { get; set; } /// /// The encrypted username for authentication when /// OpcAuthenticationMode is UsernamePassword. Encrypted /// credentials at rest can be enforced using the --fce command /// line option. Version 2.6+ stores credentials in plain text /// by default, while 2.5 and below always encrypted them. /// [DataMember(Name = "EncryptedAuthUsername", Order = 32, EmitDefaultValue = false)] public string? EncryptedAuthUsername { get; set; } /// /// The encrypted password for authentication when /// OpcAuthenticationMode is UsernamePassword. For certificate /// authentication, contains the password to access the private /// key. Encrypted credentials at rest can be enforced using /// the --fce command line option. Version 2.6+ stores /// credentials in plain text by default, while 2.5 and below /// always encrypted them. /// [DataMember(Name = "EncryptedAuthPassword", Order = 33, EmitDefaultValue = false)] public string? EncryptedAuthPassword { get; set; } /// /// The plaintext username for UsernamePassword authentication, /// or the subject name of the certificate for Certificate /// authentication. When using Certificate mode, this refers to /// a certificate in the User certificate store of the PKI /// configuration. /// [DataMember(Name = "OpcAuthenticationUsername", Order = 34, EmitDefaultValue = false)] public string? OpcAuthenticationUsername { get; set; } /// /// The plaintext password for UsernamePassword authentication, /// or the password protecting the private key for Certificate /// authentication. For Certificate mode, this must match the /// password used when adding the certificate to the PKI store. /// [DataMember(Name = "OpcAuthenticationPassword", Order = 35, EmitDefaultValue = false)] public string? OpcAuthenticationPassword { get; set; } /// /// Overrides the writer group queue name at the individual /// writer level. When specified, causes network messages to be /// split across different queues. The split also takes QoS /// settings into account, allowing fine-grained control over /// message routing and delivery guarantees. /// [DataMember(Name = "QueueName", Order = 36, EmitDefaultValue = false)] public string? QueueName { get; set; } /// /// The queue name to use for metadata messages from this /// writer. Overrides the default metadata topic template. /// Allows routing metadata to specific destinations separate /// from data messages. /// [DataMember(Name = "MetaDataQueueName", Order = 37, EmitDefaultValue = false)] public string? MetaDataQueueName { get; set; } /// /// The QoS level for this writer's messages. Overrides the /// writer group QoS setting. When specified with a custom /// queue name, causes network messages to be split with /// different delivery guarantees. /// [DataMember(Name = "QualityOfService", Order = 38, EmitDefaultValue = false)] public QoS? QualityOfService { get; set; } /// /// Specifies how many partitions to split the writer group /// into when publishing to target topics. Used to distribute /// message load and enable parallel processing by consumers. /// Default is 1 partition. Particularly useful for /// high-throughput scenarios or when using partitioned /// queues/topics in the messaging system. /// [DataMember(Name = "WriterGroupPartitions", Order = 39, EmitDefaultValue = false)] public int? WriterGroupPartitions { get; set; } /// /// Controls whether subscription transfer is disabled during /// reconnect. When false (default), attempts to transfer /// subscriptions on reconnect to maintain data continuity. Set /// to true to fix interoperability issues with servers that /// don't support subscription transfer. Can be configured /// globally via command line options. /// [DataMember(Name = "DisableSubscriptionTransfer", Order = 40, EmitDefaultValue = false)] public bool? DisableSubscriptionTransfer { get; set; } /// /// Controls whether to republish missed values after a /// subscription is transferred during reconnect handling. Only /// applies when DisableSubscriptionTransfer is false. Helps /// ensure no data is lost during connection interruptions. /// Default: true /// [DataMember(Name = "RepublishAfterTransfer", Order = 41, EmitDefaultValue = false)] public bool? RepublishAfterTransfer { get; set; } /// /// The timeout duration used to monitor whether monitored /// items in the subscription are continuously reporting fresh /// data. This watchdog mechanism helps detect stale data or /// connectivity issues. When this timeout expires, the /// configured DataSetWriterWatchdogBehavior is triggered based /// on OpcNodeWatchdogCondition. Expressed as a TimeSpan value. /// [DataMember(Name = "OpcNodeWatchdogTimespan", Order = 42, EmitDefaultValue = false)] public TimeSpan? OpcNodeWatchdogTimespan { get; set; } /// /// Defines what action to take when the watchdog timer /// triggers. Available behaviors: /// - Diagnostic: Log the event only /// - Reset: Reset the subscription /// - FailFast: Terminate the connection /// - ExitProcess: Shut down the publisher /// The behavior is executed when watchdog conditions are met /// according to OpcNodeWatchdogCondition. Can be configured /// via --dwb command line option. /// [DataMember(Name = "DataSetWriterWatchdogBehavior", Order = 43, EmitDefaultValue = false)] public SubscriptionWatchdogBehavior? DataSetWriterWatchdogBehavior { get; set; } /// /// Specifies the condition that triggers the watchdog /// behavior. Options: /// - WhenAnyAreLate: Execute when any monitored item is late /// (default) /// - WhenAllAreLate: Execute only when all items are late /// Can be configured via --mwc command line option. Used in /// conjunction with OpcNodeWatchdogTimespan and /// DataSetWriterWatchdogBehavior to implement monitoring and /// recovery strategies. /// [DataMember(Name = "OpcNodeWatchdogCondition", Order = 44, EmitDefaultValue = false)] public MonitoredItemWatchdogCondition? OpcNodeWatchdogCondition { get; set; } /// /// Default sampling interval in milliseconds for all monitored /// items in the dataset. Used if individual nodes don't /// specify their own sampling interval. Follows OPC UA /// specification for sampling behavior. Ignored when /// DataSetSamplingIntervalTimespan is present. Defaults to /// value configured via --oi command line option. /// [DataMember(Name = "DataSetSamplingInterval", Order = 45, EmitDefaultValue = false)] public int? DataSetSamplingInterval { get; set; } /// /// Default sampling interval as TimeSpan for all monitored /// items in the dataset. Takes precedence over /// DataSetSamplingInterval if both are defined. Used if /// individual nodes don't specify their own sampling interval. /// Provides more precise control over sampling timing. Follows /// OPC UA specification for sampling behavior. /// [DataMember(Name = "DataSetSamplingIntervalTimespan", Order = 46, EmitDefaultValue = false)] public TimeSpan? DataSetSamplingIntervalTimespan { get; set; } /// /// Controls whether to fetch display names of monitored /// variable nodes and use those inside messages as field /// names. When true, fetches display names for all nodes. If /// false, uses DisplayName value if provided; if not provided, /// uses the node id. Can be configured via --fd command line /// option. /// [DataMember(Name = "DataSetFetchDisplayNames", Order = 47, EmitDefaultValue = false)] public bool? DataSetFetchDisplayNames { get; set; } /// /// Time-to-live duration for messages sent through the writer /// group. Only applied if the transport technology supports /// message TTL. After this duration expires, messages may be /// discarded by the messaging system. Used to prevent stale /// data from being processed by consumers. /// [DataMember(Name = "WriterGroupMessageTtlTimepan", Order = 49, EmitDefaultValue = false)] public TimeSpan? WriterGroupMessageTtlTimepan { get; set; } /// /// Controls whether messages should be retained by the /// messaging system. Only applied if the transport technology /// supports message retention. When true, messages are kept by /// the broker even after delivery. Useful for late-joining /// subscribers to receive the last known values. /// [DataMember(Name = "WriterGroupMessageRetention", Order = 50, EmitDefaultValue = false)] public bool? WriterGroupMessageRetention { get; set; } /// /// Time-to-live duration for messages sent by this specific /// writer. Overrides WriterGroupMessageTtlTimespan at the /// individual writer level. Only applied if the transport /// technology supports message TTL. Allows different TTL /// settings for different types of data. /// [DataMember(Name = "MessageTtlTimespan", Order = 52, EmitDefaultValue = false)] public TimeSpan? MessageTtlTimespan { get; set; } /// /// Controls message retention for this specific writer. /// Overrides WriterGroupMessageRetention at the individual /// writer level. Only applied if the transport technology /// supports retention. Together with QueueName, allows /// splitting messages across different queues with different /// retention policies. /// [DataMember(Name = "MessageRetention", Order = 53, EmitDefaultValue = false)] public bool? MessageRetention { get; set; } /// /// The interval in milliseconds at which to publish heartbeat /// messages. Heartbeat acts like a watchdog that fires after /// this interval has passed and no new value has been /// received. A value of 0 disables heartbeat. Ignored when /// DefaultHeartbeatIntervalTimespan is defined. See /// heartbeat.md for detailed behavior documentation. /// [DataMember(Name = "DefaultHeartbeatInterval", Order = 54, EmitDefaultValue = false)] public int? DefaultHeartbeatInterval { get; set; } /// /// The heartbeat interval as TimeSpan for all nodes in this /// dataset. Takes precedence over DefaultHeartbeatInterval if /// defined. Controls how often heartbeat messages are /// published when no value changes occur. /// [DataMember(Name = "DefaultHeartbeatIntervalTimespan", Order = 55, EmitDefaultValue = false)] public TimeSpan? DefaultHeartbeatIntervalTimespan { get; set; } /// /// Configures how heartbeat messages are handled for all /// nodes. Supported behaviors: /// - WatchdogLKV: Last Known Value semantics (default) /// - WatchdogLKG: Last Known Good value semantics /// - PeriodicLKV: Continuous periodic sending of last known /// value /// - PeriodicLKG: Continuous periodic sending of last good /// value /// - PeriodicLKVDropValue: Periodic reporting only, drop /// out-of-period values /// - PeriodicLKGDropValue: Periodic reporting only, drop /// out-of-period values /// Can be configured via --hbb command line option. /// [DataMember(Name = "DefaultHeartbeatBehavior", Order = 56, EmitDefaultValue = false)] public HeartbeatBehavior? DefaultHeartbeatBehavior { get; set; } /// /// Contains an uri identifier that allows correlation of the writer /// data set source into other systems. Will be used as part of /// cloud events header if enabled. /// [DataMember(Name = "DataSetSourceUri", Order = 57, EmitDefaultValue = false)] public string? DataSetSourceUri { get; set; } /// /// Contains an identifier that allows correlation of the writer /// group into other systems in the context of the source. Will be /// used as part of cloud events header if enabled. /// [DataMember(Name = "DataSetSubject", Order = 58, EmitDefaultValue = false)] public string? DataSetSubject { get; set; } /// /// Additional properties of the writer group that should be retained /// with the configuration. /// [DataMember(Name = "WriterGroupProperties", Order = 59, EmitDefaultValue = false)] [SkipValidation] public Dictionary? WriterGroupProperties { get; set; } /// /// A type definition id that references a well known opc ua type /// definition node for the dataset represented by this entry. /// If set it is used in context of cloud events to specify a concrete /// type of dataset message in the cloud events type header. /// [DataMember(Name = "DataSetType", Order = 60, EmitDefaultValue = false)] public string? DataSetType { get; set; } /// /// A root node that all nodes that use a non rooted browse paths in the /// dataset should start from. /// [DataMember(Name = "DataSetRootNodeId", Order = 61, EmitDefaultValue = false)] public string? DataSetRootNodeId { get; set; } /// /// A node that represents the writer group in the server address space. /// This is the instance id of the root node from which all datasets /// originate. It is informational only and would not need to be /// configured /// [DataMember(Name = "WriterGroupRootNodeId", Order = 62, EmitDefaultValue = false)] public string? WriterGroupRootNodeId { get; set; } /// /// A type that is attached to the writer group and explains the shape /// of the writer group. It is the type definition id of the writer /// group root node id. It is informational only and would not need /// to be configured /// [DataMember(Name = "WriterGroupType", Order = 63, EmitDefaultValue = false)] public string? WriterGroupType { get; set; } /// /// Metadata retention setting for the dataset writer. /// [DataMember(Name = "MetaDataRetention", Order = 65, EmitDefaultValue = false)] public bool? MetaDataRetention { get; set; } /// /// Metadata time-to-live duration for the dataset writer. /// [DataMember(Name = "MetaDataTtlTimespan", Order = 66, EmitDefaultValue = false)] public TimeSpan? MetaDataTtlTimespan { get; set; } /// /// When sending of keep alive messages is enabled, this /// flag controls whether the keep alive messages are sent /// as key frames. Key frames contain all current values. /// [DataMember(Name = "SendKeepAliveAsKeyFrameMessages", Order = 67, EmitDefaultValue = false)] public bool? SendKeepAliveAsKeyFrameMessages { get; set; } /// /// Set a publisher id to use that is different form the /// global publisher identity. /// [DataMember(Name = "PublisherId", Order = 68, EmitDefaultValue = false)] public string? PublisherId { get; set; } /// /// Pass connection string for the transport layer. This works /// for transports that support connection strings such as /// IoT Hub or Event Hubs. It enables overriding the default /// connection string configured for the publisher. The transport /// must be configured using the command line options first, and /// can be overriden here. If it is not configured on the command /// line first, the setting here is ignored. /// [DataMember(Name = "WriterGroupTransportConfiguration", Order = 69, EmitDefaultValue = false)] public string? WriterGroupTransportConfiguration { get; set; } /// /// Enables detailed server diagnostics logging for the /// connection. When enabled, provides additional diagnostic /// information useful for troubleshooting connectivity, /// authentication, and subscription issues. The diagnostics /// data is included in the publisher's logs. Default: false /// [DataMember(Name = "DumpConnectionDiagnostics", Order = 98, EmitDefaultValue = false)] public bool? DumpConnectionDiagnostics { get; set; } /// /// Specifies a single node to monitor using namespace index /// syntax ("ns="). Alternative to using OpcNodes list for /// simple monitoring scenarios. /// [DataMember(Name = "NodeId", Order = 99, EmitDefaultValue = false)] public NodeIdModel? NodeId { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishedNodesEntryRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Wraps a request and a published nodes entry to bind to a /// body more easily for api that requires an entry and additional /// configuration /// /// [DataContract] public sealed record class PublishedNodesEntryRequestModel { /// /// Published nodes entry /// [DataMember(Name = "entry", Order = 0)] [Required] public required PublishedNodesEntryModel Entry { get; init; } /// /// Request /// [DataMember(Name = "request", Order = 1)] public T? Request { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishedNodesResponseModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { /// /// PublishNodes direct method response /// public sealed record class PublishedNodesResponseModel { } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublisherDiagnosticTargetType.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Target to sent publisher diagnostics to /// [DataContract] public enum PublisherDiagnosticTargetType { /// /// Diagnostics are emitted to logger /// [EnumMember(Value = "Logger")] Logger, /// /// Diagnostics are sent as events /// [EnumMember(Value = "Events")] Events } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/PublishingQueueSettingsModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Furly.Extensions.Messaging; using System; using System.Runtime.Serialization; /// /// Publishing Queue settings /// [DataContract] public sealed record class PublishingQueueSettingsModel { /// /// Queue name writer should use to publish messages to. /// [DataMember(Name = "queueName", Order = 1, EmitDefaultValue = false)] public string? QueueName { get; set; } /// /// Desired Quality of service to use in case of broker /// transport that supports configuring delivery guarantees. /// [DataMember(Name = "requestedDeliveryGuarantee", Order = 2, EmitDefaultValue = false)] public QoS? RequestedDeliveryGuarantee { get; set; } /// /// Desired Time to live to use in case of using a broker /// transport that supports ttl. /// [DataMember(Name = "ttl", Order = 3, EmitDefaultValue = false)] public TimeSpan? Ttl { get; set; } /// /// If the broker transport supports message retention this /// setting determines if the messages should be retained /// in the queue. /// [DataMember(Name = "retain", Order = 4, EmitDefaultValue = false)] public bool? Retain { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/QueryCompilationRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Query compiler request model /// [DataContract] public record class QueryCompilationRequestModel { /// /// Optional request header /// [DataMember(Name = "header", Order = 0, EmitDefaultValue = false)] public RequestHeaderModel? Header { get; init; } /// /// The query to compile. /// [DataMember(Name = "query", Order = 1)] [Required] public required string Query { get; init; } /// /// Query type /// [DataMember(Name = "queryType", Order = 2)] public QueryType QueryType { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/QueryCompilationResponseModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Query compiler response model /// [DataContract] public record class QueryCompilationResponseModel { /// /// Service result returned by server in case of /// error during parsing or compilation. /// [DataMember(Name = "errorInfo", Order = 0, EmitDefaultValue = false)] public ServiceResultModel? ErrorInfo { get; init; } /// /// Event filter result if request was to create /// an event filter. /// [DataMember(Name = "eventFilter", Order = 1, EmitDefaultValue = false)] public EventFilterModel? EventFilter { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/QueryType.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Query type /// [DataContract] public enum QueryType { /// /// Query is an event filter /// [EnumMember(Value = "Event")] Event, /// /// Query is a query description /// [EnumMember(Value = "Query")] Query } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ReadEventsDetailsModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Read event data /// [DataContract] public sealed record class ReadEventsDetailsModel { /// /// Start time to read from /// [DataMember(Name = "startTime", Order = 0, EmitDefaultValue = false)] public DateTime? StartTime { get; set; } /// /// End time to read to /// [DataMember(Name = "endTime", Order = 1, EmitDefaultValue = false)] public DateTime? EndTime { get; set; } /// /// Number of events to read /// [DataMember(Name = "numEvents", Order = 2, EmitDefaultValue = false)] public uint? NumEvents { get; set; } /// /// The filter to use to select the event fields /// [DataMember(Name = "filter", Order = 3, EmitDefaultValue = false)] public EventFilterModel? Filter { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ReadModifiedValuesDetailsModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Read modified data /// [DataContract] public sealed record class ReadModifiedValuesDetailsModel { /// /// The start time to read from /// [DataMember(Name = "startTime", Order = 0, EmitDefaultValue = false)] public DateTime? StartTime { get; set; } /// /// The end time to read to /// [DataMember(Name = "endTime", Order = 1, EmitDefaultValue = false)] public DateTime? EndTime { get; set; } /// /// The number of values to read /// [DataMember(Name = "numValues", Order = 2, EmitDefaultValue = false)] public uint? NumValues { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ReadProcessedValuesDetailsModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Read processed historic data /// [DataContract] public sealed record class ReadProcessedValuesDetailsModel { /// /// Start time to read from. /// [DataMember(Name = "startTime", Order = 0, EmitDefaultValue = false)] public DateTime? StartTime { get; set; } /// /// End time to read until /// [DataMember(Name = "endTime", Order = 1, EmitDefaultValue = false)] public DateTime? EndTime { get; set; } /// /// Interval to process /// [DataMember(Name = "processingInterval", Order = 2, EmitDefaultValue = false)] public TimeSpan? ProcessingInterval { get; set; } /// /// The aggregate type to apply. Can be the name of /// the aggregate if available in the history server /// capabilities, or otherwise will be used as a node /// id referring to the aggregate. /// [DataMember(Name = "aggregateType", Order = 3, EmitDefaultValue = false)] public string? AggregateType { get; set; } /// /// Aggregate Configuration - use null or empty configuration /// to use the server defaults. /// [DataMember(Name = "aggregateConfiguration", Order = 4, EmitDefaultValue = false)] public AggregateConfigurationModel? AggregateConfiguration { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ReadRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Request node attribute read /// [DataContract] public sealed record class ReadRequestModel { /// /// Attributes to read /// [DataMember(Name = "attributes", Order = 0)] [Required] public required IReadOnlyList Attributes { get; set; } /// /// Optional request header /// [DataMember(Name = "header", Order = 1, EmitDefaultValue = false)] public RequestHeaderModel? Header { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ReadResponseModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Result of attribute reads /// [DataContract] public sealed record class ReadResponseModel { /// /// All results of attribute reads /// [DataMember(Name = "results", Order = 0)] public required IReadOnlyList Results { get; set; } /// /// Service result in case of error /// [DataMember(Name = "errorInfo", Order = 1, EmitDefaultValue = false)] public ServiceResultModel? ErrorInfo { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ReadValuesAtTimesDetailsModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Read data at specified times /// [DataContract] public sealed record class ReadValuesAtTimesDetailsModel { /// /// Requested datums /// [DataMember(Name = "reqTimes", Order = 0)] [Required] public required IReadOnlyList ReqTimes { get; set; } /// /// Whether to use simple bounds /// [DataMember(Name = "useSimpleBounds", Order = 1, EmitDefaultValue = false)] public bool? UseSimpleBounds { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ReadValuesDetailsModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Read historic values /// [DataContract] public sealed record class ReadValuesDetailsModel { /// /// Beginning of period to read. Set to null /// if no specific start time is specified. /// [DataMember(Name = "startTime", Order = 0, EmitDefaultValue = false)] public DateTime? StartTime { get; set; } /// /// End of period to read. Set to null if no /// specific end time is specified. /// [DataMember(Name = "endTime", Order = 1, EmitDefaultValue = false)] public DateTime? EndTime { get; set; } /// /// The maximum number of values returned for any Node /// over the time range. If only one time is specified, /// the time range shall extend to return this number /// of values. 0 or null indicates that there is no /// maximum. /// [DataMember(Name = "numValues", Order = 2, EmitDefaultValue = false)] public uint? NumValues { get; set; } /// /// Whether to return the bounding values or not. /// [DataMember(Name = "returnBounds", Order = 3, EmitDefaultValue = false)] public bool? ReturnBounds { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/RelativePathElementModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// An element of a relative path /// [DataContract] public record class RelativePathElementModel { /// /// Target browse name with namespace /// [DataMember(Name = "TargetName", Order = 0)] public required string TargetName { get; init; } /// /// Reference type identifier. /// (default is hierarchical reference) /// [DataMember(Name = "ReferenceTypeId", Order = 1)] public required string ReferenceTypeId { get; init; } /// /// Whether the reference is inverse /// (default is false) /// [DataMember(Name = "IsInverse", Order = 2, EmitDefaultValue = false)] public bool? IsInverse { get; init; } /// /// Whether reference subtypes should be excluded /// (default is false) /// [DataMember(Name = "noSubtypes", Order = 3, EmitDefaultValue = false)] public bool? NoSubtypes { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/RequestEnvelope.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Wraps a request and a connection to bind to a /// body more easily for api that requires a /// connection endpoint /// /// [DataContract] public record class RequestEnvelope { /// /// Connection the request is targeting /// [DataMember(Name = "connection", Order = 0)] [Required] public required ConnectionModel Connection { get; set; } /// /// Request /// [DataMember(Name = "request", Order = 1)] public T? Request { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/RequestHeaderModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Request header model /// [DataContract] public sealed record class RequestHeaderModel { /// /// Optional User Elevation. We suggest to use the /// connection object to elevate the user instead of /// using the request elevation. /// [DataMember(Name = "elevation", Order = 0, EmitDefaultValue = false)] public CredentialModel? Elevation { get; set; } /// /// Optional list of preferred locales in preference /// order to be used during connecting the session. /// We suggest to use the connection object to set /// the locales /// [DataMember(Name = "locales", Order = 1, EmitDefaultValue = false)] public IReadOnlyList? Locales { get; set; } /// /// Optional diagnostics configuration for the /// service call. This configures the returned /// diagnostic information in the result. /// [DataMember(Name = "diagnostics", Order = 2, EmitDefaultValue = false)] public DiagnosticsModel? Diagnostics { get; set; } /// /// Optional namespace format to use when serializing /// nodes and qualified names in responses. /// [DataMember(Name = "namespaceFormat", Order = 3, EmitDefaultValue = false)] public NamespaceFormat? NamespaceFormat { get; set; } /// /// Operation timeout in ms. This applies to every /// operation that is invoked, not to the entire /// transaction and overrides the configured operation /// timeout. /// [DataMember(Name = "operationTimeout", Order = 4, EmitDefaultValue = false)] public int? OperationTimeout { get; set; } /// /// Service call timeout in ms. As opposed to the /// operation timeout this terminates the entire /// transaction if it takes longer than the timeout to /// complete. Note that a connect and reconnect during /// the service call is gated by the connect timeout /// setting. If a connect timeout is not specified /// this timeout is used also for connect timeout. /// [DataMember(Name = "serviceCallTimeout", Order = 5, EmitDefaultValue = false)] public int? ServiceCallTimeout { get; set; } /// /// Connect timeout in ms. As opposed to the service call /// timeout this terminates the entire transaction if /// it takes longer than the timeout to connect a session /// A connect and reconnect during the service call /// resets the timeout therefore the overall time for /// the call to complete can be longer than specified. /// [DataMember(Name = "connectTimeout", Order = 6, EmitDefaultValue = false)] public int? ConnectTimeout { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/RolePermissionModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Role permission model /// [DataContract] public sealed record class RolePermissionModel { /// /// Identifier of the role object. /// [DataMember(Name = "roleId", Order = 0)] [Required] public required string RoleId { get; set; } /// /// Permissions assigned for the role. /// [DataMember(Name = "permissions", Order = 1, EmitDefaultValue = false)] public RolePermissions? Permissions { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/RolePermissions.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Individual permissions assigned to a role /// [Flags] [DataContract] public enum RolePermissions { /// /// No permissions /// [EnumMember(Value = "None")] None = 0x0, /// /// Gives role the Browse permissions. /// [EnumMember(Value = "Browse")] Browse = 0x1, /// /// Gives role the ReadRolePermissions permissions. /// [EnumMember(Value = "ReadRolePermissions")] ReadRolePermissions = 0x2, /// /// Gives role the WriteAttribute permissions. /// [EnumMember(Value = "WriteAttribute")] WriteAttribute = 0x4, /// /// Gives role the WriteRolePermissions permissions. /// [EnumMember(Value = "WriteRolePermissions")] WriteRolePermissions = 0x8, /// /// Gives role the WriteHistorizing permissions. /// [EnumMember(Value = "WriteHistorizing")] WriteHistorizing = 0x10, /// /// Gives role the Read permissions. /// [EnumMember(Value = "Read")] Read = 0x20, /// /// Gives role the Write value permissions. /// [EnumMember(Value = "Write")] Write = 0x40, /// /// Gives role the ReadHistory permissions. /// [EnumMember(Value = "ReadHistory")] ReadHistory = 0x80, /// /// Gives role the InsertHistory permissions. /// [EnumMember(Value = "InsertHistory")] InsertHistory = 0x100, /// /// Gives role the ModifyHistory permissions. /// [EnumMember(Value = "ModifyHistory")] ModifyHistory = 0x200, /// /// Gives role the DeleteHistory permissions. /// [EnumMember(Value = "DeleteHistory")] DeleteHistory = 0x400, /// /// Gives role the ReceiveEvents permissions. /// [EnumMember(Value = "ReceiveEvents")] ReceiveEvents = 0x800, /// /// Gives role the Call permissions. /// [EnumMember(Value = "Call")] Call = 0x1000, /// /// Gives role the AddReference permissions. /// [EnumMember(Value = "AddReference")] AddReference = 0x2000, /// /// Gives role the RemoveReference permissions. /// [EnumMember(Value = "RemoveReference")] RemoveReference = 0x4000, /// /// Gives role the DeleteNode permissions. /// [EnumMember(Value = "DeleteNode")] DeleteNode = 0x8000, /// /// Gives role the AddNode permissions. /// [EnumMember(Value = "AddNode")] AddNode = 0x10000, } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/RuntimeStateEventModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Model for reporting runtime state. /// [DataContract] public class RuntimeStateEventModel { /// /// Defines the message type that is sent. /// [DataMember(Name = "MessageType", Order = 0, EmitDefaultValue = true)] public RuntimeStateEventType MessageType { get; set; } /// /// Defines the message version. /// [DataMember(Name = "MessageVersion", Order = 1, EmitDefaultValue = true)] public int MessageVersion { get; set; } /// /// The utc timestamp of the runtime state event /// [DataMember(Name = "TimestampUtc", Order = 2, EmitDefaultValue = true)] public DateTimeOffset TimestampUtc { get; set; } /// /// The Publisher version /// [DataMember(Name = "Version", Order = 3, EmitDefaultValue = true)] public string? Version { get; set; } /// /// The Publisher Id if available /// [DataMember(Name = "PublisherId", Order = 4, EmitDefaultValue = true)] public string? PublisherId { get; set; } /// /// The Site if available /// [DataMember(Name = "Site", Order = 5, EmitDefaultValue = true)] public string? Site { get; set; } /// /// The Device Id if available /// [DataMember(Name = "DeviceId", Order = 6, EmitDefaultValue = true)] public string? DeviceId { get; set; } /// /// The Module Id if available /// [DataMember(Name = "ModuleId", Order = 7, EmitDefaultValue = true)] public string? ModuleId { get; set; } /// /// The Publisher semantic version string /// [DataMember(Name = "SemVer", Order = 8, EmitDefaultValue = true)] public string? SemVer { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/RuntimeStateEventType.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Enum of valid values for MessageType. /// [DataContract] public enum RuntimeStateEventType { /// /// Restart announcement. /// [EnumMember(Value = "RestartAnnouncement")] RestartAnnouncement, /// /// Runtime state is running /// [EnumMember(Value = "Running")] Running, /// /// Shutdown announcement. /// [EnumMember(Value = "ShutdownAnnouncement")] ShutdownAnnouncement, /// /// Runtime state is stopped /// [EnumMember(Value = "Stopped")] Stopped, } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/SecurityMode.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Specifies the security mode for OPC UA endpoint connections. /// Determines how messages are protected during transmission between /// the Publisher and OPC UA servers. Proper security mode selection /// is crucial for protecting sensitive data and credentials. /// [DataContract] [Flags] public enum SecurityMode { /// /// Selects the highest security level available from the server. /// WARNING: May select None if no secure endpoints are available. /// Not recommended for production - use explicit security modes /// to enforce security requirements. /// [EnumMember(Value = "Best")] Best, /// /// Messages are signed but not encrypted. /// Ensures message integrity and authenticity. /// Protects against tampering but not eavesdropping. /// Use when data confidentiality is not required. /// [EnumMember(Value = "Sign")] Sign, /// /// Messages are both signed and encrypted. /// Provides maximum security with full message protection. /// Ensures confidentiality, integrity, and authenticity. /// Recommended when transmitting sensitive data or credentials. /// [EnumMember(Value = "SignAndEncrypt")] SignAndEncrypt, /// /// No message security applied. /// WARNING: Transmits all data in clear text. /// Should only be used in secure networks or for testing. /// Not recommended for production environments. /// [EnumMember(Value = "None")] None, /// /// Requires either Sign or SignAndEncrypt mode. /// Ensures some level of message protection. /// Default when UseSecurity is true. /// Recommended minimum security for production use. /// [EnumMember(Value = "NotNone")] NotNone, } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ServerCapabilitiesModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Server capabilities /// [DataContract] public sealed record class ServerCapabilitiesModel { /// /// Operation limits /// [DataMember(Name = "operationLimits", Order = 0)] public required OperationLimitsModel OperationLimits { get; set; } /// /// Supported locales /// [DataMember(Name = "supportedLocales", Order = 1)] public IReadOnlyList? SupportedLocales { get; set; } /// /// Server profiles /// [DataMember(Name = "serverProfileArray", Order = 2)] public IReadOnlyList? ServerProfiles { get; set; } /// /// Supported modelling rules /// [DataMember(Name = "modellingRules", Order = 3, EmitDefaultValue = false)] public IReadOnlyDictionary? ModellingRules { get; set; } /// /// Supported aggregate functions /// [DataMember(Name = "aggregateFunctions", Order = 4, EmitDefaultValue = false)] public IReadOnlyDictionary? AggregateFunctions { get; set; } /// /// Supported aggregate functions /// [DataMember(Name = "MaxSessions", Order = 5, EmitDefaultValue = false)] public uint? MaxSessions { get; set; } /// /// Supported aggregate functions /// [DataMember(Name = "MaxSubscriptions", Order = 6, EmitDefaultValue = false)] public uint? MaxSubscriptions { get; set; } /// /// Supported aggregate functions /// [DataMember(Name = "MaxMonitoredItems", Order = 7, EmitDefaultValue = false)] public uint? MaxMonitoredItems { get; set; } /// /// Supported aggregate functions /// [DataMember(Name = "MaxSubscriptionsPerSession", Order = 8, EmitDefaultValue = false)] public uint? MaxSubscriptionsPerSession { get; set; } /// /// Supported aggregate functions /// [DataMember(Name = "MaxMonitoredItemsPerSubscription", Order = 9, EmitDefaultValue = false)] public uint? MaxMonitoredItemsPerSubscription { get; set; } /// /// Supported aggregate functions /// [DataMember(Name = "MaxSelectClauseParameters", Order = 10, EmitDefaultValue = false)] public uint? MaxSelectClauseParameters { get; set; } /// /// Supported aggregate functions /// [DataMember(Name = "MaxWhereClauseParameters", Order = 11, EmitDefaultValue = false)] public uint? MaxWhereClauseParameters { get; set; } /// /// Supported aggregate functions /// [DataMember(Name = "MaxMonitoredItemsQueueSize", Order = 12, EmitDefaultValue = false)] public uint? MaxMonitoredItemsQueueSize { get; set; } /// /// Supported aggregate functions /// [DataMember(Name = "conformanceUnits", Order = 13, EmitDefaultValue = false)] public IReadOnlyList? ConformanceUnits { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ServerEndpointQueryModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Endpoint model /// [DataContract] public sealed record class ServerEndpointQueryModel { /// /// Discovery url to use to query /// [DataMember(Name = "discoveryUrl", Order = 0)] public string? DiscoveryUrl { get; set; } /// /// Endpoint url that should match the found endpoint /// [DataMember(Name = "url", Order = 1)] public string? Url { get; set; } /// /// Endpoint must support this Security Mode. /// [DataMember(Name = "securityMode", Order = 2, EmitDefaultValue = false)] public SecurityMode? SecurityMode { get; set; } /// /// Endpoint must support this Security policy. /// [DataMember(Name = "securityPolicy", Order = 3, EmitDefaultValue = false)] public string? SecurityPolicy { get; set; } /// /// Endpoint must match with this certificate thumbprint /// [DataMember(Name = "certificate", Order = 4, EmitDefaultValue = false)] public string? Certificate { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ServerRegistrationRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Server registration request /// [DataContract] public sealed record class ServerRegistrationRequestModel { /// /// Discovery url to use for registration /// [DataMember(Name = "discoveryUrl", Order = 0)] [Required] public required string DiscoveryUrl { get; set; } /// /// User defined request id /// [DataMember(Name = "id", Order = 1, EmitDefaultValue = false)] public string? Id { get; set; } /// /// Operation audit context /// [DataMember(Name = "context", Order = 3, EmitDefaultValue = false)] public OperationContextModel? Context { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ServiceCounterModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Service counters /// [DataContract] public record class ServiceCounterModel { /// /// Total count /// [DataMember(Name = "totalCount", Order = 1, EmitDefaultValue = false)] public uint TotalCount { get; init; } /// /// Error count /// [DataMember(Name = "errorCount", Order = 2, EmitDefaultValue = false)] public uint ErrorCount { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ServiceResponse.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Response envelope /// /// [DataContract] public sealed record class ServiceResponse where T : class { /// /// Result /// [DataMember(Name = "result", Order = 0, EmitDefaultValue = false)] public T? Result { get; init; } /// /// Service result in case of error /// [DataMember(Name = "errorInfo", Order = 1, EmitDefaultValue = false)] public ServiceResultModel? ErrorInfo { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ServiceResultModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Service result /// [DataContract] public sealed record class ServiceResultModel { /// /// Error code - if null operation succeeded. /// [DataMember(Name = "statusCode", Order = 0, EmitDefaultValue = false)] public uint StatusCode { get; set; } /// /// Error message in case of error or null. /// [DataMember(Name = "errorMessage", Order = 1, EmitDefaultValue = false)] public string? ErrorMessage { get; set; } /// /// Symbolic identifier /// [DataMember(Name = "symbolicId", Order = 2)] public string? SymbolicId { get; set; } /// /// Locale of the error message /// [DataMember(Name = "locale", Order = 3, EmitDefaultValue = false)] public string? Locale { get; set; } /// /// Additional information if available /// [DataMember(Name = "additionalInfo", Order = 4, EmitDefaultValue = false)] public string? AdditionalInfo { get; set; } /// /// Namespace uri /// [DataMember(Name = "namespaceUri", Order = 5, EmitDefaultValue = false)] public string? NamespaceUri { get; set; } /// /// Inner result if any /// [DataMember(Name = "inner", Order = 6, EmitDefaultValue = false)] public ServiceResultModel? Inner { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/SessionDiagnosticsModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Collections.Generic; using System.Runtime.Serialization; /// /// Session diagnostics /// [DataContract] public record class SessionDiagnosticsModel { /// /// Session id /// [DataMember(Name = "sessionId", Order = 0, EmitDefaultValue = false)] public string? SessionId { get; init; } /// /// Session name /// [DataMember(Name = "sessionName", Order = 1, EmitDefaultValue = false)] public string? SessionName { get; init; } /// /// Server uri /// [DataMember(Name = "serverUri", Order = 2, EmitDefaultValue = false)] public string? ServerUri { get; init; } /// /// Actual session timeout /// [DataMember(Name = "actualSessionTimeout", Order = 3, EmitDefaultValue = false)] public double ActualSessionTimeout { get; init; } /// /// Max response message size /// [DataMember(Name = "maxResponseMessageSize", Order = 8, EmitDefaultValue = false)] public uint MaxResponseMessageSize { get; init; } /// /// Connection established /// [DataMember(Name = "connectTime", Order = 9, EmitDefaultValue = false)] public DateTime ConnectTime { get; init; } /// /// Last contact /// [DataMember(Name = "lastContactTime", Order = 10, EmitDefaultValue = false)] public DateTime LastContactTime { get; init; } /// /// Current subscriptions count /// [DataMember(Name = "currentSubscriptionsCount", Order = 11, EmitDefaultValue = false)] public uint CurrentSubscriptionsCount { get; init; } /// /// Current monitored items count /// [DataMember(Name = "currentMonitoredItemsCount", Order = 12, EmitDefaultValue = false)] public uint CurrentMonitoredItemsCount { get; init; } /// /// Current publish requests in queue /// [DataMember(Name = "currentPublishRequestsInQueue", Order = 13, EmitDefaultValue = false)] public uint CurrentPublishRequestsInQueue { get; init; } /// /// Total request count /// [DataMember(Name = "totalRequestCount", Order = 14, EmitDefaultValue = false)] public ServiceCounterModel? TotalRequestCount { get; init; } /// /// Unauthorized request count /// [DataMember(Name = "unauthorizedRequestCount", Order = 15, EmitDefaultValue = false)] public uint UnauthorizedRequestCount { get; init; } /// /// Read count /// [DataMember(Name = "readCount", Order = 16, EmitDefaultValue = false)] public ServiceCounterModel? ReadCount { get; init; } /// /// History read counts /// [DataMember(Name = "historyReadCount", Order = 17, EmitDefaultValue = false)] public ServiceCounterModel? HistoryReadCount { get; init; } /// /// Write counts /// [DataMember(Name = "writeCount", Order = 18, EmitDefaultValue = false)] public ServiceCounterModel? WriteCount { get; init; } /// /// History update count /// [DataMember(Name = "historyUpdateCount", Order = 19, EmitDefaultValue = false)] public ServiceCounterModel? HistoryUpdateCount { get; init; } /// /// Call count /// [DataMember(Name = "callCount", Order = 20, EmitDefaultValue = false)] public ServiceCounterModel? CallCount { get; init; } /// /// Create monitored item count /// [DataMember(Name = "createMonitoredItemsCount", Order = 21, EmitDefaultValue = false)] public ServiceCounterModel? CreateMonitoredItemsCount { get; init; } /// /// Modify monitored item counts /// [DataMember(Name = "modifyMonitoredItemsCount", Order = 22, EmitDefaultValue = false)] public ServiceCounterModel? ModifyMonitoredItemsCount { get; init; } /// /// Set monitoring mode counts /// [DataMember(Name = "setMonitoringModeCount", Order = 23, EmitDefaultValue = false)] public ServiceCounterModel? SetMonitoringModeCount { get; init; } /// /// Set triggering counts /// [DataMember(Name = "setTriggeringCount", Order = 24, EmitDefaultValue = false)] public ServiceCounterModel? SetTriggeringCount { get; init; } /// /// Delete monitored items counts /// [DataMember(Name = "deleteMonitoredItemsCount", Order = 25, EmitDefaultValue = false)] public ServiceCounterModel? DeleteMonitoredItemsCount { get; init; } /// /// Create Subscription count /// [DataMember(Name = "createSubscriptionCount", Order = 26, EmitDefaultValue = false)] public ServiceCounterModel? CreateSubscriptionCount { get; init; } /// /// Modify subscription count /// [DataMember(Name = "modifySubscriptionCount", Order = 27, EmitDefaultValue = false)] public ServiceCounterModel? ModifySubscriptionCount { get; init; } /// /// Set publishing mode count /// [DataMember(Name = "setPublishingModeCount", Order = 28, EmitDefaultValue = false)] public ServiceCounterModel? SetPublishingModeCount { get; init; } /// /// Publish counts /// [DataMember(Name = "publishCount", Order = 29, EmitDefaultValue = false)] public ServiceCounterModel? PublishCount { get; init; } /// /// Republish count /// [DataMember(Name = "republishCount", Order = 30, EmitDefaultValue = false)] public ServiceCounterModel? RepublishCount { get; init; } /// /// Transfer subscriptions count /// [DataMember(Name = "transferSubscriptionsCount", Order = 31, EmitDefaultValue = false)] public ServiceCounterModel? TransferSubscriptionsCount { get; init; } /// /// Delete subscriptions count /// [DataMember(Name = "deleteSubscriptionsCount", Order = 32, EmitDefaultValue = false)] public ServiceCounterModel? DeleteSubscriptionsCount { get; init; } /// /// Add nodes count /// [DataMember(Name = "addNodesCount", Order = 33, EmitDefaultValue = false)] public ServiceCounterModel? AddNodesCount { get; init; } /// /// Add References count /// [DataMember(Name = "addReferencesCount", Order = 34, EmitDefaultValue = false)] public ServiceCounterModel? AddReferencesCount { get; init; } /// /// Delete nodes count /// [DataMember(Name = "deleteNodesCount", Order = 35, EmitDefaultValue = false)] public ServiceCounterModel? DeleteNodesCount { get; init; } /// /// Delete References count /// [DataMember(Name = "deleteReferencesCount", Order = 36, EmitDefaultValue = false)] public ServiceCounterModel? DeleteReferencesCount { get; init; } /// /// Browse count /// [DataMember(Name = "browseCount", Order = 37, EmitDefaultValue = false)] public ServiceCounterModel? BrowseCount { get; init; } /// /// Browse next count /// [DataMember(Name = "browseNextCount", Order = 38, EmitDefaultValue = false)] public ServiceCounterModel? BrowseNextCount { get; init; } /// /// Translate browse paths to node ids count /// [DataMember(Name = "translateBrowsePathsToNodeIdsCount", Order = 39, EmitDefaultValue = false)] public ServiceCounterModel? TranslateBrowsePathsToNodeIdsCount { get; init; } /// /// Query first count /// [DataMember(Name = "queryFirstCount", Order = 40, EmitDefaultValue = false)] public ServiceCounterModel? QueryFirstCount { get; init; } /// /// Query next count /// [DataMember(Name = "queryNextCount", Order = 41, EmitDefaultValue = false)] public ServiceCounterModel? QueryNextCount { get; init; } /// /// Register nodes count /// [DataMember(Name = "registerNodesCount", Order = 42, EmitDefaultValue = false)] public ServiceCounterModel? RegisterNodesCount { get; init; } /// /// Unregister nodes count /// [DataMember(Name = "unregisterNodesCount", Order = 43, EmitDefaultValue = false)] public ServiceCounterModel? UnregisterNodesCount { get; init; } /// /// Subscription diagnostics /// [DataMember(Name = "subscriptions", Order = 44, EmitDefaultValue = false)] public IReadOnlyList? Subscriptions { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/SetConfiguredEndpointsRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Set configured endpoints request call /// [DataContract] public sealed record class SetConfiguredEndpointsRequestModel { /// /// Endpoints and nodes that make up the configuration /// [DataMember(Name = "endpoints", Order = 0, EmitDefaultValue = false)] public IEnumerable? Endpoints { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/SimpleAttributeOperandModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Collections.Generic; using System.Runtime.Serialization; /// /// Simple attribute operand model /// [DataContract] public record class SimpleAttributeOperandModel { /// /// Type definition node id if operand is /// simple or full attribute operand. /// [DataMember(Name = "typeDefinitionId", Order = 0)] public string? TypeDefinitionId { get; set; } /// /// Browse path of attribute operand /// [DataMember(Name = "browsePath", Order = 1, EmitDefaultValue = false)] public IReadOnlyList? BrowsePath { get; set; } /// /// Attribute id /// [DataMember(Name = "attributeId", Order = 2, EmitDefaultValue = false)] public NodeAttribute? AttributeId { get; set; } /// /// Index range of attribute operand /// [DataMember(Name = "indexRange", Order = 3, EmitDefaultValue = false)] public string? IndexRange { get; set; } /// /// Optional display name /// [DataMember(Name = "displayName", Order = 4, EmitDefaultValue = false)] public string? DisplayName { get; set; } /// /// Optional data set class field id (Publisher extension) /// [DataMember(Name = "dataSetClassFieldId", Order = 5, EmitDefaultValue = false)] public Guid DataSetClassFieldId { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/SimpleTypeDescriptionModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Simple type schema /// [DataContract] public record class SimpleTypeDescriptionModel { /// /// Data type identifier /// [DataMember(Name = "dataTypeId", Order = 1)] public required string DataTypeId { get; set; } /// /// Name of the type /// [DataMember(Name = "name", Order = 2)] public required string Name { get; set; } /// /// Base data type /// [DataMember(Name = "baseDataType", Order = 3, EmitDefaultValue = false)] public string? BaseDataType { get; set; } /// /// Underlying built in type of the enum. /// Default is integer. /// [DataMember(Name = "builtInType", Order = 4, EmitDefaultValue = false)] public byte? BuiltInType { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/SkipValidationAttribute.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace System.ComponentModel.DataAnnotations { /// /// Always validates true /// [AttributeUsage(AttributeTargets.All, AllowMultiple = false)] public class SkipValidationAttribute : ValidationAttribute { /// public override bool IsValid(object? value) { return true; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/StructureDescriptionModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Structure type schema /// public record class StructureDescriptionModel { /// /// Data type identifier /// [DataMember(Name = "dataTypeId", Order = 1)] public required string DataTypeId { get; set; } /// /// Name of the type /// [DataMember(Name = "name", Order = 2)] public required string Name { get; set; } /// /// Type of the structure. Default is structure. /// [DataMember(Name = "structureType", Order = 3, EmitDefaultValue = false)] public StructureType? StructureType { get; set; } /// /// Fields of the structure /// [DataMember(Name = "Fields", Order = 4)] public required IReadOnlyList Fields { get; set; } /// /// Base data type /// [DataMember(Name = "baseDataType", Order = 5, EmitDefaultValue = false)] public string? BaseDataType { get; set; } /// /// Default encoding /// [DataMember(Name = "defaultEncodingId", Order = 6, EmitDefaultValue = false)] public string? DefaultEncodingId { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/StructureFieldDescriptionModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Structure field description /// [DataContract] public record class StructureFieldDescriptionModel { /// /// Name of the field /// [DataMember(Name = "name", Order = 1)] public required string Name { get; set; } /// /// Data type schema /// [DataMember(Name = "dataType", Order = 2)] public required string DataType { get; set; } /// /// Description of the field /// [DataMember(Name = "description", Order = 3, EmitDefaultValue = false)] public string? Description { get; set; } /// /// Optionality of the field /// [DataMember(Name = "isOptional", Order = 4, EmitDefaultValue = false)] public bool IsOptional { get; set; } /// /// Value rank of the type /// [DataMember(Name = "valueRank", Order = 6, EmitDefaultValue = false)] public int ValueRank { get; set; } /// /// Array dimensions if non scalar /// [DataMember(Name = "arrayDimensions", Order = 7, EmitDefaultValue = false)] public IReadOnlyList? ArrayDimensions { get; set; } /// /// Max string length /// [DataMember(Name = "maxStringLength", Order = 8, EmitDefaultValue = false)] public uint MaxStringLength { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/StructureType.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Type of structure /// [DataContract] public enum StructureType { /// /// Default /// [EnumMember(Value = "Structure")] Structure = 0, /// /// With optional fields /// [EnumMember(Value = "StructureWithOptionalFields")] StructureWithOptionalFields = 1, /// /// Union /// [EnumMember(Value = "Union")] Union = 2, /// /// With subtyped values /// [EnumMember(Value = "StructureWithSubtypedValues")] StructureWithSubtypedValues = 3, /// /// Union but with subtyped values /// [EnumMember(Value = "UnionWithSubtypedValues")] UnionWithSubtypedValues = 4, } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/SubscriptionDiagnosticsModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Subscription diagnostics /// [DataContract] public record class SubscriptionDiagnosticsModel { /// /// Subscription id /// [DataMember(Name = "subscriptionId", Order = 0, EmitDefaultValue = false)] public uint SubscriptionId { get; init; } /// /// Subscription priority /// [DataMember(Name = "priority", Order = 1, EmitDefaultValue = false)] public byte Priority { get; init; } /// /// Publishing interval /// [DataMember(Name = "publishingInterval", Order = 2, EmitDefaultValue = false)] public double PublishingInterval { get; init; } /// /// Max keep alive count /// [DataMember(Name = "maxKeepAliveCount", Order = 3, EmitDefaultValue = false)] public uint MaxKeepAliveCount { get; init; } /// /// Max lifetime count /// [DataMember(Name = "maxLifetimeCount", Order = 4, EmitDefaultValue = false)] public uint MaxLifetimeCount { get; init; } /// /// Current keep alive count /// [DataMember(Name = "currentKeepAliveCount", Order = 5, EmitDefaultValue = false)] public uint CurrentKeepAliveCount { get; init; } /// /// Current lifetime count /// [DataMember(Name = "currentLifetimeCount", Order = 6, EmitDefaultValue = false)] public uint CurrentLifetimeCount { get; init; } /// /// Max notifications per publish /// [DataMember(Name = "maxNotificationsPerPublish", Order = 7, EmitDefaultValue = false)] public uint MaxNotificationsPerPublish { get; init; } /// /// Publishing enabled /// [DataMember(Name = "publishingEnabled", Order = 8, EmitDefaultValue = false)] public bool PublishingEnabled { get; init; } /// /// Modify count /// [DataMember(Name = "modifyCount", Order = 9, EmitDefaultValue = false)] public uint ModifyCount { get; init; } /// /// Subscription enable count /// [DataMember(Name = "enableCount", Order = 10, EmitDefaultValue = false)] public uint EnableCount { get; init; } /// /// Disable count /// [DataMember(Name = "disableCount", Order = 11, EmitDefaultValue = false)] public uint DisableCount { get; init; } /// /// Monitored item count /// [DataMember(Name = "monitoredItemCount", Order = 12, EmitDefaultValue = false)] public uint MonitoredItemCount { get; init; } /// /// Disabled monitored item count /// [DataMember(Name = "disabledMonitoredItemCount", Order = 13, EmitDefaultValue = false)] public uint DisabledMonitoredItemCount { get; init; } /// /// Publish request count /// [DataMember(Name = "publishRequestCount", Order = 14, EmitDefaultValue = false)] public uint PublishRequestCount { get; init; } /// /// Late publish request count /// [DataMember(Name = "latePublishRequestCount", Order = 15, EmitDefaultValue = false)] public uint LatePublishRequestCount { get; init; } /// /// Data change notifications count /// [DataMember(Name = "dataChangeNotificationsCount", Order = 16, EmitDefaultValue = false)] public uint DataChangeNotificationsCount { get; init; } /// /// Event notifications count /// [DataMember(Name = "eventNotificationsCount", Order = 17, EmitDefaultValue = false)] public uint EventNotificationsCount { get; init; } /// /// Total Notifications count /// [DataMember(Name = "notificationsCount", Order = 18, EmitDefaultValue = false)] public uint NotificationsCount { get; init; } /// /// Unacknowledged message count /// [DataMember(Name = "unacknowledgedMessageCount", Order = 19, EmitDefaultValue = false)] public uint UnacknowledgedMessageCount { get; init; } /// /// Discarded message count /// [DataMember(Name = "discardedMessageCount", Order = 20, EmitDefaultValue = false)] public uint DiscardedMessageCount { get; init; } /// /// Next sequence number /// [DataMember(Name = "nextSequenceNumber", Order = 21, EmitDefaultValue = false)] public uint NextSequenceNumber { get; init; } /// /// Monitoring queue overflow count /// [DataMember(Name = "monitoringQueueOverflowCount", Order = 22, EmitDefaultValue = false)] public uint MonitoringQueueOverflowCount { get; init; } /// /// Event queue overflow count /// [DataMember(Name = "eventQueueOverFlowCount", Order = 23, EmitDefaultValue = false)] public uint EventQueueOverFlowCount { get; init; } /// /// Transfer request count /// [DataMember(Name = "transferRequestCount", Order = 24, EmitDefaultValue = false)] public uint TransferRequestCount { get; init; } /// /// Transferred to alt client count /// [DataMember(Name = "transferredToAltClientCount", Order = 25, EmitDefaultValue = false)] public uint TransferredToAltClientCount { get; init; } /// /// Transferred to same client count /// [DataMember(Name = "transferredToSameClientCount", Order = 26, EmitDefaultValue = false)] public uint TransferredToSameClientCount { get; init; } /// /// Publish request count /// [DataMember(Name = "republishRequestCount", Order = 27, EmitDefaultValue = false)] public uint RepublishRequestCount { get; init; } /// /// Republish message request count /// [DataMember(Name = "republishMessageRequestCount", Order = 28, EmitDefaultValue = false)] public uint RepublishMessageRequestCount { get; init; } /// /// Republish message count /// [DataMember(Name = "republishMessageCount", Order = 29, EmitDefaultValue = false)] public uint RepublishMessageCount { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/SubscriptionWatchdogBehavior.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Defines how the publisher responds when monitored items stop reporting data. /// The watchdog triggers when items are late according to OpcNodeWatchdogTimespan /// and OpcNodeWatchdogCondition settings. Can be configured globally via the /// --dwb command line option. /// [DataContract] [Flags] public enum SubscriptionWatchdogBehavior { /// /// Log watchdog events to diagnostics output only. /// Least intrusive behavior that maintains normal operation. /// Useful for monitoring and troubleshooting connection issues. /// Recommended for non-critical monitoring scenarios. /// [EnumMember(Value = "Diagnostic")] Diagnostic, /// /// Attempts to reestablish the subscription when watchdog triggers. /// Automatically recovers from temporary connection issues. /// May cause brief interruption during reset operation. /// Good balance between reliability and availability. /// [EnumMember(Value = "Reset")] Reset, /// /// Immediately terminates the publisher application when triggered. /// Most aggressive recovery option that forces complete restart. /// Useful when clean restart is required for recovery. /// WARNING: Will disrupt all active subscriptions. /// [EnumMember(Value = "FailFast")] FailFast, /// /// Gracefully exits the process with exit code -10 when triggered. /// Allows container orchestrators or service managers to handle restart. /// Provides clean shutdown with specific error indication. /// Suitable for managed deployment environments. /// [EnumMember(Value = "ExitProcess")] ExitProcess } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/TestConnectionRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Test connection request /// [DataContract] public sealed record class TestConnectionRequestModel { /// /// Optional request header /// [DataMember(Name = "header", Order = 0, EmitDefaultValue = false)] public RequestHeaderModel? Header { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/TestConnectionResponseModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Test connection response /// [DataContract] public sealed record class TestConnectionResponseModel { /// /// Service result in case of error /// [DataMember(Name = "errorInfo", Order = 0, EmitDefaultValue = false)] public ServiceResultModel? ErrorInfo { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/TimestampsToReturn.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Timestamps /// [DataContract] public enum TimestampsToReturn { /// /// Both time stamps /// [EnumMember(Value = "Both")] Both, /// /// Source time /// [EnumMember(Value = "Source")] Source, /// /// Server time /// [EnumMember(Value = "Server")] Server, /// /// No timestamp /// [EnumMember(Value = "None")] None } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/TypeDefinitionModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Type definition /// [DataContract] public sealed record class TypeDefinitionModel { /// /// The node id of the type of the node /// [DataMember(Name = "typeDefinitionId", Order = 0)] [Required] public required string TypeDefinitionId { get; set; } /// /// The type of the node /// [DataMember(Name = "nodeType", Order = 1)] public NodeType NodeType { get; set; } /// /// Display name /// [DataMember(Name = "displayName", Order = 2, EmitDefaultValue = false)] public string? DisplayName { get; set; } /// /// Browse name /// [DataMember(Name = "browseName", Order = 3, EmitDefaultValue = false)] public string? BrowseName { get; set; } /// /// Description if any /// [DataMember(Name = "description", Order = 4, EmitDefaultValue = false)] public string? Description { get; set; } /// /// Super types hierarchy starting from base type /// up to which is /// not included. /// [DataMember(Name = "typeHierarchy", Order = 5, EmitDefaultValue = false)] public IReadOnlyList? TypeHierarchy { get; set; } /// /// Fully inherited instance declarations of the type /// of the node. /// [DataMember(Name = "typeMembers", Order = 6, EmitDefaultValue = false)] public IReadOnlyList? Declarations { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/UpdateEventsDetailsModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Insert, upsert or replace historic events /// [DataContract] public sealed record class UpdateEventsDetailsModel { /// /// The filter to use to select the events /// [DataMember(Name = "filter", Order = 0, EmitDefaultValue = false)] public EventFilterModel? Filter { get; set; } /// /// The new events to insert /// [DataMember(Name = "events", Order = 1)] [Required] public required IReadOnlyList Events { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/UpdateValuesDetailsModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Insert, upsert, or update historic values /// [DataContract] public sealed record class UpdateValuesDetailsModel { /// /// Values to insert /// [DataMember(Name = "values", Order = 0)] [Required] public required IReadOnlyList Values { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/UserIdentityModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// User identity model /// [DataContract] public sealed record class UserIdentityModel { /// /// /// For authentication /// this is the name of the user. /// /// /// For authentication /// this is the subject name of the certificate that has been /// configured. /// Either or must be /// used to select the certificate in the user certificate store. /// /// /// Not used for the other authentication types. /// /// [DataMember(Name = "user", Order = 1, EmitDefaultValue = false)] public string? User { get; set; } /// /// /// For authentication /// this is the password of the user. /// /// /// For authentication /// this is the passcode to export the configured certificate's /// private key. /// /// /// Not used for the other authentication types. /// /// [DataMember(Name = "password", Order = 2, EmitDefaultValue = false)] public string? Password { get; set; } /// /// /// For authentication /// this is the thumbprint of the configured certificate to use. /// Either or must be /// used to select the certificate in the user certificate store. /// /// /// Not used for the other authentication types. /// /// [DataMember(Name = "thumbprint", Order = 3, EmitDefaultValue = false)] public string? Thumbprint { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ValueReadRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Collections.Generic; using System.Runtime.Serialization; /// /// Request node value read /// [DataContract] public sealed record class ValueReadRequestModel { /// /// Node to read from (mandatory) /// [DataMember(Name = "nodeId", Order = 0, EmitDefaultValue = false)] public string? NodeId { get; set; } /// /// An optional path from NodeId instance to /// an actual node. /// [DataMember(Name = "browsePath", Order = 1, EmitDefaultValue = false)] public IReadOnlyList? BrowsePath { get; set; } /// /// Index range to read, e.g. 1:2,0:1 for 2 slices /// out of a matrix or 0:1 for the first item in /// an array, string or bytestring. /// See 7.22 of part 4: NumericRange. /// [DataMember(Name = "indexRange", Order = 2, EmitDefaultValue = false)] public string? IndexRange { get; set; } /// /// Optional request header /// [DataMember(Name = "header", Order = 3, EmitDefaultValue = false)] public RequestHeaderModel? Header { get; set; } /// /// Maximum age of the value to be read in milliseconds. /// The age of the value is based on the difference /// between the ServerTimestamp and the time when /// the Server starts processing the request. /// If not supplied, the Server shall attempt to read /// a new value from the data source. /// [DataMember(Name = "maxAge", Order = 4, EmitDefaultValue = false)] public TimeSpan? MaxAge { get; set; } /// /// Decide what timestamps to return. /// [DataMember(Name = "timestampsToReturn", Order = 5, EmitDefaultValue = false)] public TimestampsToReturn? TimestampsToReturn { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ValueReadResponseModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Furly.Extensions.Serializers; using System; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Value read response model /// [DataContract] public sealed record class ValueReadResponseModel { /// /// Value read /// [DataMember(Name = "value", Order = 0, EmitDefaultValue = false)] [SkipValidation] public VariantValue? Value { get; set; } /// /// Built in data type of the value read. /// [DataMember(Name = "dataType", Order = 1, EmitDefaultValue = false)] public string? DataType { get; set; } /// /// Pico seconds part of when value was read at source. /// [DataMember(Name = "sourcePicoseconds", Order = 2, EmitDefaultValue = false)] public ushort? SourcePicoseconds { get; set; } /// /// Timestamp of when value was read at source. /// [DataMember(Name = "sourceTimestamp", Order = 3, EmitDefaultValue = false)] public DateTime? SourceTimestamp { get; set; } /// /// Pico seconds part of when value was read at server. /// [DataMember(Name = "serverPicoseconds", Order = 4, EmitDefaultValue = false)] public ushort? ServerPicoseconds { get; set; } /// /// Timestamp of when value was read at server. /// [DataMember(Name = "serverTimestamp", Order = 5, EmitDefaultValue = false)] public DateTime? ServerTimestamp { get; set; } /// /// Service result in case of error /// [DataMember(Name = "errorInfo", Order = 6, EmitDefaultValue = false)] public ServiceResultModel? ErrorInfo { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ValueWriteRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Furly.Extensions.Serializers; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Value write request model /// [DataContract] public sealed record class ValueWriteRequestModel { /// /// Node id to write value to. /// [DataMember(Name = "nodeId", Order = 0, EmitDefaultValue = false)] public string? NodeId { get; set; } /// /// An optional path from NodeId instance to /// the actual node. /// [DataMember(Name = "browsePath", Order = 1, EmitDefaultValue = false)] public IReadOnlyList? BrowsePath { get; set; } /// /// Value to write. The system tries to convert /// the value according to the data type value, /// e.g. convert comma seperated value strings /// into arrays. (Mandatory) /// [DataMember(Name = "value", Order = 2)] [SkipValidation] public required VariantValue Value { get; set; } /// /// A built in datatype for the value. This can /// be a data type from browse, or a built in /// type. /// (default: best effort) /// [DataMember(Name = "dataType", Order = 3, EmitDefaultValue = false)] public string? DataType { get; set; } /// /// Index range to write /// [DataMember(Name = "indexRange", Order = 4, EmitDefaultValue = false)] public string? IndexRange { get; set; } /// /// Optional request header /// [DataMember(Name = "header", Order = 5, EmitDefaultValue = false)] public RequestHeaderModel? Header { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/ValueWriteResponseModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Value write response model /// [DataContract] public sealed record class ValueWriteResponseModel { /// /// Service result in case of error /// [DataMember(Name = "errorInfo", Order = 0, EmitDefaultValue = false)] public ServiceResultModel? ErrorInfo { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/VariableMetadataModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Variable metadata model /// [DataContract] public sealed record class VariableMetadataModel { /// /// The data type for the variable. /// [DataMember(Name = "dataType", Order = 0, EmitDefaultValue = false)] public DataTypeMetadataModel? DataType { get; set; } /// /// The value rank of the variable. /// [DataMember(Name = "valueRank", Order = 1, EmitDefaultValue = false)] public NodeValueRank? ValueRank { get; set; } /// /// Array dimensions of the variable. /// [DataMember(Name = "arrayDimensions", Order = 2, EmitDefaultValue = false)] public IReadOnlyList? ArrayDimensions { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/WriteRequestModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Request node attribute write /// [DataContract] public sealed record class WriteRequestModel { /// /// Attributes to update /// [DataMember(Name = "attributes", Order = 0)] [Required] public required IReadOnlyList Attributes { get; set; } /// /// Optional request header /// [DataMember(Name = "header", Order = 1, EmitDefaultValue = false)] public RequestHeaderModel? Header { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/WriteResponseModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Result of attribute write /// [DataContract] public sealed record class WriteResponseModel { /// /// All results of attribute writes /// [DataMember(Name = "results", Order = 0)] public required IReadOnlyList Results { get; set; } /// /// Service result in case of error /// [DataMember(Name = "errorInfo", Order = 1, EmitDefaultValue = false)] public ServiceResultModel? ErrorInfo { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/WriterGroupDiagnosticModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Model for a diagnostic info. /// [DataContract] public record class WriterGroupDiagnosticModel { /// /// Publisher version string /// [DataMember(Name = "PublisherVersion", Order = 99, EmitDefaultValue = true)] public string? PublisherVersion { get; set; } /// /// Writer group name /// [DataMember(Name = "WriterGroupName", Order = 98, EmitDefaultValue = true)] public string? WriterGroupName { get; set; } /// /// Timestamp for this diagnostics information /// [DataMember(Name = "Timestamp", Order = 0, EmitDefaultValue = true)] public DateTimeOffset Timestamp { get; set; } /// /// Ingestion start /// [DataMember(Name = "IngestionStart", Order = 1, EmitDefaultValue = true)] public DateTimeOffset IngestionStart { get; set; } /// /// Ingestion duration /// [DataMember(Name = "IngestionDuration", Order = 2, EmitDefaultValue = true)] public TimeSpan IngestionDuration { get; set; } /// /// SentMessagesPerSec /// [DataMember(Name = "SentMessagesPerSec", Order = 3, EmitDefaultValue = true)] public double SentMessagesPerSec { get; set; } /// /// IngressDataChanges /// [DataMember(Name = "IngressDataChanges", Order = 4, EmitDefaultValue = true)] public long IngressDataChanges { get; set; } /// /// IngressValueChanges /// [DataMember(Name = "IngressValueChanges", Order = 5, EmitDefaultValue = true)] public long IngressValueChanges { get; set; } /// /// Number of heartbeats of the total values /// [DataMember(Name = "IngressHeartbeats", Order = 6, EmitDefaultValue = true)] public long IngressHeartbeats { get; set; } /// /// Number of cyclic reads of all sampled values /// [DataMember(Name = "IngressCyclicReads", Order = 7, EmitDefaultValue = true)] public long IngressCyclicReads { get; set; } /// /// Data changes received in the last minute /// [DataMember(Name = "IngressDataChangesInLastMinute", Order = 8, EmitDefaultValue = true)] public long IngressDataChangesInLastMinute { get; set; } /// /// Value changes received in the last minute /// [DataMember(Name = "IngressValueChangesInLastMinute", Order = 9, EmitDefaultValue = true)] public long IngressValueChangesInLastMinute { get; set; } /// /// IngressBatchBlockBufferSize /// [DataMember(Name = "IngressBatchBlockBufferSize", Order = 10, EmitDefaultValue = true)] public long IngressBatchBlockBufferSize { get; set; } /// /// EncodingBlockInputSize /// [DataMember(Name = "EncodingBlockInputSize", Order = 11, EmitDefaultValue = true)] public long EncodingBlockInputSize { get; set; } /// /// EncodingBlockOutputSize /// [DataMember(Name = "EncodingBlockOutputSize", Order = 12, EmitDefaultValue = true)] public long EncodingBlockOutputSize { get; set; } /// /// EncoderNotificationsProcessed /// [DataMember(Name = "EncoderNotificationsProcessed", Order = 13, EmitDefaultValue = true)] public long EncoderNotificationsProcessed { get; set; } /// /// EncoderNotificationsDropped /// [DataMember(Name = "EncoderNotificationsDropped", Order = 14, EmitDefaultValue = true)] public long EncoderNotificationsDropped { get; set; } /// /// EncoderIoTMessagesProcessed /// [DataMember(Name = "EncoderIoTMessagesProcessed", Order = 15, EmitDefaultValue = true)] public long EncoderIoTMessagesProcessed { get; set; } /// /// EncoderAvgNotificationsMessage /// [DataMember(Name = "EncoderAvgNotificationsMessage", Order = 16, EmitDefaultValue = true)] public double EncoderAvgNotificationsMessage { get; set; } /// /// EncoderAvgIoTMessageBodySize /// [DataMember(Name = "EncoderAvgIoTMessageBodySize", Order = 17, EmitDefaultValue = true)] public double EncoderAvgIoTMessageBodySize { get; set; } /// /// EncoderAvgIoTChunkUsage /// [DataMember(Name = "EncoderAvgIoTChunkUsage", Order = 18, EmitDefaultValue = true)] public double EncoderAvgIoTChunkUsage { get; set; } /// /// EstimatedIoTChunksPerDay /// [DataMember(Name = "EstimatedIoTChunksPerDay", Order = 19, EmitDefaultValue = true)] public double EstimatedIoTChunksPerDay { get; set; } /// /// OutgressInputBufferCount /// [DataMember(Name = "OutgressInputBufferCount", Order = 20, EmitDefaultValue = true)] public long OutgressInputBufferCount { get; set; } /// /// OutgressInputBufferDropped /// [DataMember(Name = "OutgressInputBufferDropped", Order = 21, EmitDefaultValue = true)] public long OutgressInputBufferDropped { get; set; } /// /// OutgressIoTMessageCount /// [DataMember(Name = "OutgressIoTMessageCount", Order = 22, EmitDefaultValue = true)] public long OutgressIoTMessageCount { get; set; } /// /// Connection Retries /// [DataMember(Name = "ConnectionRetries", Order = 23, EmitDefaultValue = true)] public long ConnectionRetries { get; set; } /// /// OpcEndpointConnected /// [DataMember(Name = "OpcEndpointConnected", Order = 24, EmitDefaultValue = true)] public bool OpcEndpointConnected { get; set; } /// /// MonitoredOpcNodesSucceededCount /// [DataMember(Name = "MonitoredOpcNodesSucceededCount", Order = 25, EmitDefaultValue = true)] public long MonitoredOpcNodesSucceededCount { get; set; } /// /// MonitoredOpcNodesFailedCount /// [DataMember(Name = "MonitoredOpcNodesFailedCount", Order = 26, EmitDefaultValue = true)] public long MonitoredOpcNodesFailedCount { get; set; } /// /// Number of incoming event notifications /// [DataMember(Name = "IngressEventNotifications", Order = 27, EmitDefaultValue = true)] public long IngressEventNotifications { get; set; } /// /// Total incoming events so far. /// [DataMember(Name = "IngressEvents", Order = 28, EmitDefaultValue = true)] public long IngressEvents { get; set; } /// /// Encoder max message split ratio /// [DataMember(Name = "EncoderMaxMessageSplitRatio", Order = 29, EmitDefaultValue = true)] public double EncoderMaxMessageSplitRatio { get; set; } /// /// Number of incoming keep alive notifications /// [DataMember(Name = "IngressKeepAliveNotifications", Order = 30, EmitDefaultValue = true)] public long IngressKeepAliveNotifications { get; set; } /// /// Number of endpoints connected /// [DataMember(Name = "NumberOfConnectedEndpoints", Order = 36, EmitDefaultValue = true)] public int NumberOfConnectedEndpoints { get; set; } /// /// Number of endpoints disconnected /// [DataMember(Name = "NumberOfDisconnectedEndpoints", Order = 37, EmitDefaultValue = true)] public int NumberOfDisconnectedEndpoints { get; set; } /// /// Number of model changes generated /// [DataMember(Name = "IngressModelChanges", Order = 39, EmitDefaultValue = true)] public long IngressModelChanges { get; set; } /// /// Events in the last minute /// [DataMember(Name = "IngressEventsInLastMinute", Order = 40, EmitDefaultValue = true)] public long IngressEventsInLastMinute { get; set; } /// /// Heartbeats in the last minute /// [DataMember(Name = "IngressHeartbeatsInLastMinute", Order = 41, EmitDefaultValue = true)] public long IngressHeartbeatsInLastMinute { get; set; } /// /// Cyclic reads last minute /// [DataMember(Name = "IngressCyclicReadsInLastMinute", Order = 42, EmitDefaultValue = true)] public long IngressCyclicReadsInLastMinute { get; set; } /// /// Number of model changes generated /// [DataMember(Name = "IngressModelChangesInLastMinute", Order = 43, EmitDefaultValue = true)] public long IngressModelChangesInLastMinute { get; set; } /// /// Event list notifications in the last minute /// [DataMember(Name = "IngressEventNotificationsInLastMinute", Order = 44, EmitDefaultValue = true)] public long IngressEventNotificationsInLastMinute { get; set; } /// /// Messages failed sending /// [DataMember(Name = "OutgressIoTMessageFailedCount", Order = 45, EmitDefaultValue = true)] public long OutgressIoTMessageFailedCount { get; set; } /// /// Total server queue overflows /// [DataMember(Name = "ServerQueueOverflows", Order = 46, EmitDefaultValue = true)] public long ServerQueueOverflows { get; set; } /// /// Queue server queue overflows in the last minute /// [DataMember(Name = "ServerQueueOverflowsInLastMinute", Order = 47, EmitDefaultValue = true)] public long ServerQueueOverflowsInLastMinute { get; set; } /// /// Sampled values in the completed cyclic reads /// [DataMember(Name = "IngressSampledValues", Order = 48, EmitDefaultValue = true)] public long IngressSampledValues { get; set; } /// /// Sampled values in the last minute /// [DataMember(Name = "IngressSampledValuesInLastMinute", Order = 49, EmitDefaultValue = true)] public long IngressSampledValuesInLastMinute { get; set; } /// /// Notifications dropped before pushing to publish queue /// [DataMember(Name = "IngressNotificationsDropped", Order = 50, EmitDefaultValue = true)] public long IngressNotificationsDropped { get; set; } /// /// Total partitions /// [DataMember(Name = "TotalPublishQueuePartitions", Order = 51, EmitDefaultValue = true)] public int TotalPublishQueuePartitions { get; set; } /// /// Active partitions /// [DataMember(Name = "ActivePublishQueuePartitions", Order = 52, EmitDefaultValue = true)] public int ActivePublishQueuePartitions { get; set; } /// /// Gets the CPU utilization percentage. /// [DataMember(Name = "CpuUsedPercentage", Order = 60, EmitDefaultValue = true)] public double CpuUsedPercentage { get; set; } /// /// Gets the CPU units available in the system. /// [DataMember(Name = "GuaranteedCpuUnits", Order = 61, EmitDefaultValue = true)] public double GuaranteedCpuUnits { get; set; } /// /// Gets the maximum CPU units available in the system. /// [DataMember(Name = "MaximumCpuUnits", Order = 62, EmitDefaultValue = true)] public double MaximumCpuUnits { get; set; } /// /// Gets the memory utilization percentage. /// [DataMember(Name = "MemoryUsedPercentage", Order = 63, EmitDefaultValue = true)] public double MemoryUsedPercentage { get; set; } /// /// Gets the memory used in bytes. /// [DataMember(Name = "MemoryUsedInBytes", Order = 64, EmitDefaultValue = true)] public ulong MemoryUsedInBytes { get; set; } /// /// Gets the memory allocated to the system in bytes. /// [DataMember(Name = "GuaranteedMemoryInBytes", Order = 65, EmitDefaultValue = true)] public ulong GuaranteedMemoryInBytes { get; set; } /// /// Gets the Request Memory Limit or the Maximum allocated for the VM. /// [DataMember(Name = "MaximumMemoryInBytes", Order = 66, EmitDefaultValue = true)] public ulong MaximumMemoryInBytes { get; set; } /// /// Nodes that are late reporting if watchdog is enabled /// [DataMember(Name = "MonitoredOpcNodesLateCount", Order = 67, EmitDefaultValue = true)] public long MonitoredOpcNodesLateCount { get; set; } /// /// Nodes with active heartbeat timer /// [DataMember(Name = "ActiveHeartbeatCount", Order = 68, EmitDefaultValue = true)] public long ActiveHeartbeatCount { get; set; } /// /// Nodes with active condition snapshot timer /// [DataMember(Name = "ActiveConditionCount", Order = 69, EmitDefaultValue = true)] public long ActiveConditionCount { get; set; } /// /// ConnectionCount /// [DataMember(Name = "ConnectionCount", Order = 70, EmitDefaultValue = true)] public long ConnectionCount { get; set; } /// /// Number of writers in the writer group /// [DataMember(Name = "NumberOfWriters", Order = 71, EmitDefaultValue = true)] public int NumberOfWriters { get; set; } /// /// Total Publish requests of all clients assigned to /// the group. /// [DataMember(Name = "TotalPublishRequests", Order = 72, EmitDefaultValue = true)] public int TotalPublishRequests { get; set; } /// /// Total Good publish requests of all clients assigned to /// the group. They might not apply to the subscriptions /// assigned to the group. /// [DataMember(Name = "TotalGoodPublishRequests", Order = 73, EmitDefaultValue = true)] public int TotalGoodPublishRequests { get; set; } /// /// Total bad publish requests of all clients assigned to /// the group. They might not apply to the subscriptions /// assigned to the group. /// [DataMember(Name = "TotalBadPublishRequests", Order = 74, EmitDefaultValue = true)] public int TotalBadPublishRequests { get; set; } /// /// Total min publish requests of all clients assigned to /// the group. /// [DataMember(Name = "TotalMinPublishRequests", Order = 75, EmitDefaultValue = true)] public int TotalMinPublishRequests { get; set; } /// /// Total number of monitored nodes in the writer group. /// [DataMember(Name = "MonitoredOpcNodesCount", Order = 76, EmitDefaultValue = true)] public int MonitoredOpcNodesCount { get; set; } /// /// Container Cpu limit utilization /// [DataMember(Name = "CpuLimitUtilization", Order = 77, EmitDefaultValue = true)] public double CpuLimitUtilization { get; set; } /// /// Container Cpu request utilization /// [DataMember(Name = "CpuRequestUtilization", Order = 78, EmitDefaultValue = true)] public double CpuRequestUtilization { get; set; } /// /// Container memory limit utilization /// [DataMember(Name = "MemoryLimitUtilization", Order = 79, EmitDefaultValue = true)] public double MemoryLimitUtilization { get; set; } /// /// Connections currently reconnecting /// [DataMember(Name = "ConnectionsReconnecting", Order = 80, EmitDefaultValue = true)] public int ConnectionsReconnecting { get; set; } /// /// Successful connection keep alives since last reconnect /// [DataMember(Name = "ConnectionKeepAlives", Order = 81, EmitDefaultValue = true)] public long ConnectionKeepAlives { get; set; } /// /// Total keep alives over all connections /// [DataMember(Name = "ConnectionKeepAlivesTotal", Order = 82, EmitDefaultValue = true)] public long ConnectionKeepAlivesTotal { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/WriterGroupMessageSettingsModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Writer group message configuration /// [DataContract] public sealed record class WriterGroupMessageSettingsModel { /// /// Network message content /// [DataMember(Name = "networkMessageContentMask", Order = 0, EmitDefaultValue = false)] public NetworkMessageContentFlags? NetworkMessageContentMask { get; set; } /// /// Group version /// [DataMember(Name = "groupVersion", Order = 1, EmitDefaultValue = false)] public uint? GroupVersion { get; set; } /// /// Uadp dataset ordering /// [DataMember(Name = "dataSetOrdering", Order = 2, EmitDefaultValue = false)] public DataSetOrderingType? DataSetOrdering { get; set; } /// /// Uadp Sampling offset /// [DataMember(Name = "samplingOffset", Order = 3, EmitDefaultValue = false)] public double? SamplingOffset { get; set; } /// /// Publishing offset for uadp messages /// [DataMember(Name = "publishingOffset", Order = 4, EmitDefaultValue = false)] public IReadOnlyList? PublishingOffset { get; set; } /// /// Max messages per publish /// [DataMember(Name = "maxDataSetMessagesPerPublish", Order = 5, EmitDefaultValue = false)] public uint? MaxDataSetMessagesPerPublish { get; set; } /// /// Optional namespace format to use when serializing /// nodes and qualified names in responses. /// [DataMember(Name = "namespaceFormat", Order = 6, EmitDefaultValue = false)] public NamespaceFormat? NamespaceFormat { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/WriterGroupModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using Furly.Extensions.Serializers; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; /// /// Network message writer group model /// [DataContract] public sealed record class WriterGroupModel { /// /// Writer group identifier /// [DataMember(Name = "id", Order = 0)] [Required] public required string Id { get; set; } /// /// Network message types to generate /// (publisher extension) /// [DataMember(Name = "messageType", Order = 1, EmitDefaultValue = false)] public MessageEncoding? MessageType { get; set; } /// /// The data set writers generating /// dataset messages in the group /// [DataMember(Name = "dataSetWriters", Order = 2, EmitDefaultValue = false)] public IReadOnlyList? DataSetWriters { get; set; } /// /// Network message configuration /// [DataMember(Name = "messageSettings", Order = 3, EmitDefaultValue = false)] public WriterGroupMessageSettingsModel? MessageSettings { get; set; } /// /// Priority of the writer group /// [DataMember(Name = "priority", Order = 4, EmitDefaultValue = false)] public byte? Priority { get; set; } /// /// Name of the writer group /// [DataMember(Name = "name", Order = 5, EmitDefaultValue = false)] public string? Name { get; set; } /// /// Locales to use /// [DataMember(Name = "localeIds", Order = 6, EmitDefaultValue = false)] public IReadOnlyList? LocaleIds { get; set; } /// /// Header layout uri /// [DataMember(Name = "headerLayoutUri", Order = 7, EmitDefaultValue = false)] public string? HeaderLayoutUri { get; set; } /// /// Security mode /// [DataMember(Name = "securityMode", Order = 8, EmitDefaultValue = false)] public SecurityMode? SecurityMode { get; set; } /// /// Security group to use /// [DataMember(Name = "securityGroupId", Order = 9, EmitDefaultValue = false)] public string? SecurityGroupId { get; set; } /// /// Security key services to use /// [DataMember(Name = "securityKeyServices", Order = 10, EmitDefaultValue = false)] public IReadOnlyList? SecurityKeyServices { get; set; } /// /// Max network message size. The max size is limited /// by the capabilities of the underlying event client /// transport, e.g., 256k in the case of IoT Hub. /// [DataMember(Name = "maxNetworkMessageSize", Order = 11, EmitDefaultValue = false)] public uint? MaxNetworkMessageSize { get; set; } /// /// Publishing interval is the time to wait before /// generating a network message from the queue of /// collected notifications. The default is set to /// the value of the BatchTriggerInterval option. /// [DataMember(Name = "publishingInterval", Order = 12, EmitDefaultValue = false)] public TimeSpan? PublishingInterval { get; set; } /// /// Keep alive time /// [DataMember(Name = "keepAliveTime", Order = 13, EmitDefaultValue = false)] public TimeSpan? KeepAliveTime { get; set; } /// /// Number of notifications to queue before sending a batch /// (Publisher extension). /// The default is set to the value of the BatchSize option. /// [DataMember(Name = "notificationPublishThreshold", Order = 14, EmitDefaultValue = false)] public uint? NotificationPublishThreshold { get; set; } /// /// Max publish queue size. /// [DataMember(Name = "publishQueueSize", Order = 15, EmitDefaultValue = false)] public uint? PublishQueueSize { get; set; } /// /// Desired Transport to use. If transport is not registered /// the default (first) registered transport is used. /// (Publisher extension) /// [DataMember(Name = "transport", Order = 16, EmitDefaultValue = false)] public WriterGroupTransport? Transport { get; set; } /// /// Queue settings to use for messages in the writer group. /// (Publisher extension) /// [DataMember(Name = "publishing", Order = 17, EmitDefaultValue = false)] public PublishingQueueSettingsModel? Publishing { get; set; } /// /// Number of partitions to create of the publish queue. /// (Publisher extension) /// [DataMember(Name = "publishQueuePartitions", Order = 18, EmitDefaultValue = false)] public int? PublishQueuePartitions { get; set; } /// /// Root node of the writer group /// [DataMember(Name = "rootNode", Order = 19, EmitDefaultValue = false)] public string? RootNode { get; set; } /// /// Type of the writer group /// [DataMember(Name = "type", Order = 20, EmitDefaultValue = false)] public string? Type { get; set; } /// /// Writer group properties and attributes /// (Publisher extension) /// [DataMember(Name = "properties", Order = 21, EmitDefaultValue = false)] [SkipValidation] public Dictionary? Properties { get; set; } /// /// Publisher identifier if different from the global one /// (Publisher extension) /// [DataMember(Name = "publisherId", Order = 22, EmitDefaultValue = false)] public string? PublisherId { get; set; } /// /// Writer group transport configuration (optional) /// [DataMember(Name = "transportConfiguration", Order = 23, EmitDefaultValue = false)] public string? TransportConfiguration { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/WriterGroupTransport.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Runtime.Serialization; /// /// Specifies the transport technology used to publish messages from OPC Publisher. /// Each transport offers different capabilities for message delivery, routing, /// and quality of service. The transport choice affects how messages are delivered /// and what features are available. /// [DataContract] public enum WriterGroupTransport { /// /// Default transport using Azure IoT Hub or IoT Edge. /// Provides secure, reliable message delivery to Azure cloud. /// Supports message batching, compression, and QoS. /// Message size limited to 256KB by IoT Hub. /// [EnumMember(Value = "IoTHub")] IoTHub, /// /// Publish to any MQTT broker using MQTT v3.1.1 protocol. /// Supports configurable topics and QoS levels. /// Compatible with most MQTT brokers (Mosquitto, HiveMQ, etc.). /// Good choice for local network publishing. /// [EnumMember(Value = "Mqtt")] Mqtt, /// /// Direct publishing to Azure Event Hubs. /// Designed for high-throughput data ingestion. /// Supports partitioning for parallel processing. /// Suitable for big data and analytics scenarios. /// [EnumMember(Value = "EventHub")] EventHub, /// /// Publishing through Dapr pub/sub building block. /// Provides transport abstraction and flexibility. /// Supports multiple message brokers through components. /// Ideal for cloud-native and microservices architectures. /// [EnumMember(Value = "Dapr")] Dapr, /// /// Publish messages to HTTP endpoints (webhooks). /// Supports configurable endpoints and authentication. /// Messages sent as HTTP POST requests. /// Useful for integration with web services and APIs. /// [EnumMember(Value = "Http")] Http, /// /// Write messages to local or network file system. /// Supports various file formats and patterns. /// Useful for logging, debugging, or offline scenarios. /// Can integrate with file-based processing systems. /// [EnumMember(Value = "FileSystem")] FileSystem, /// /// Publish to Aio MQTT broker using MQTT v5 protocol. /// [EnumMember(Value = "AioMqtt")] AioMqtt, /// /// Publish to Aio Distributed State store. /// [EnumMember(Value = "AioDss")] AioDss, /// /// Messages are discarded without being published. /// Used for testing or when only monitoring is needed. /// No external dependencies or configuration required. /// Minimal resource usage as messages are dropped. /// [EnumMember(Value = "Null")] Null } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/X509CertificateChainModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Certificate chain /// [DataContract] public sealed record class X509CertificateChainModel { /// /// Chain /// [DataMember(Name = "chain", Order = 0, EmitDefaultValue = false)] public IReadOnlyList? Chain { get; set; } /// /// Chain validation status if validated /// [DataMember(Name = "status", Order = 1, EmitDefaultValue = false)] public IReadOnlyList? Status { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/X509CertificateModel.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Collections.Generic; using System.Runtime.Serialization; /// /// Certificate model /// [DataContract] public sealed record class X509CertificateModel { /// /// Subject /// [DataMember(Name = "subject", Order = 0, EmitDefaultValue = false)] public string? Subject { get; set; } /// /// Thumbprint /// [DataMember(Name = "thumbprint", Order = 1, EmitDefaultValue = false)] public string? Thumbprint { get; set; } /// /// Serial number /// [DataMember(Name = "serialNumber", Order = 2, EmitDefaultValue = false)] public string? SerialNumber { get; set; } /// /// Not before validity /// [DataMember(Name = "notBeforeUtc", Order = 3, EmitDefaultValue = false)] public DateTime? NotBeforeUtc { get; set; } /// /// Not after validity /// [DataMember(Name = "notAfterUtc", Order = 4, EmitDefaultValue = false)] public DateTime? NotAfterUtc { get; set; } /// /// Self signed certificate /// [DataMember(Name = "selfSigned", Order = 5, EmitDefaultValue = false)] public bool? SelfSigned { get; set; } /// /// Certificate as Pkcs12 /// [DataMember(Name = "pfx", Order = 6)] public IReadOnlyCollection? Pfx { get; set; } /// /// Contains private key /// [DataMember(Name = "hasPrivateKey", Order = 7, EmitDefaultValue = false)] public bool? HasPrivateKey { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/src/X509ChainStatus.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models { using System; using System.Runtime.Serialization; /// /// Status of x509 chain /// [Flags] [DataContract] public enum X509ChainStatus { /// /// Specifies that the X509 chain is not valid due to an invalid /// time value, such as a value that indicates an expired certificate. /// [EnumMember(Value = "NotTimeValid")] NotTimeValid = 0x1, /// /// Specifies that the X509 chain is invalid due to a revoked certificate. /// [EnumMember(Value = "Revoked")] Revoked = 0x4, /// /// Specifies that the X509 chain is invalid due to an invalid /// certificate signature. /// [EnumMember(Value = "NotSignatureValid")] NotSignatureValid = 0x8, /// /// Specifies that the key usage is not valid. /// [EnumMember(Value = "NotValidForUsage")] NotValidForUsage = 0x10, /// /// Specifies that the X509 chain is invalid due to an untrusted /// root certificate. /// [EnumMember(Value = "UntrustedRoot")] UntrustedRoot = 0x20, /// /// Specifies that it is not possible to determine whether the /// certificate has been revoked. This can be due to the certificate /// revocation list (CRL) being offline or unavailable. /// [EnumMember(Value = "RevocationStatusUnknown")] RevocationStatusUnknown = 0x40, /// /// Specifies that the X509 chain could not be built. /// [EnumMember(Value = "Cyclic")] Cyclic = 0x80, /// /// Specifies that the X509 chain is invalid due to an invalid /// extension. /// [EnumMember(Value = "InvalidExtension")] InvalidExtension = 0x100, /// /// Specifies that the X509 chain is invalid due to invalid /// policy constraints. /// [EnumMember(Value = "InvalidPolicyConstraints")] InvalidPolicyConstraints = 0x200, /// /// Specifies that the X509 chain is invalid due to invalid /// basic constraints. /// [EnumMember(Value = "InvalidBasicConstraints")] InvalidBasicConstraints = 0x400, /// /// Specifies that the X509 chain is invalid due to invalid /// name constraints. /// [EnumMember(Value = "InvalidNameConstraints")] InvalidNameConstraints = 0x800, /// /// Specifies that the certificate does not have a supported /// name constraint or has a name constraint that is unsupported. /// [EnumMember(Value = "HasNotSupportedNameConstraint")] HasNotSupportedNameConstraint = 0x1000, /// /// Specifies that the certificate has an undefined name constraint. /// [EnumMember(Value = "HasNotDefinedNameConstraint")] HasNotDefinedNameConstraint = 0x2000, /// /// Specifies that the certificate has an impermissible name /// constraint. /// [EnumMember(Value = "HasNotPermittedNameConstraint")] HasNotPermittedNameConstraint = 0x4000, /// /// Specifies that the X509 chain is invalid because a certificate /// has excluded a name constraint. /// [EnumMember(Value = "HasExcludedNameConstraint")] HasExcludedNameConstraint = 0x8000, /// /// Specifies that the X509 chain could not be built up to the /// root certificate. /// [EnumMember(Value = "PartialChain")] PartialChain = 0x10000, /// /// Specifies that the trust list is not valid because of an invalid /// time value, such as one that indicates that the CTL has expired. /// [EnumMember(Value = "CtlNotTimeValid")] CtlNotTimeValid = 0x20000, /// /// Specifies that the trust list contains an invalid signature. /// [EnumMember(Value = "CtlNotSignatureValid")] CtlNotSignatureValid = 0x40000, /// /// Specifies that the trust list is not valid for this use. /// [EnumMember(Value = "CtlNotValidForUsage")] CtlNotValidForUsage = 0x80000, /// /// Specifies that the certificate has not been strong signed. /// [EnumMember(Value = "HasWeakSignature")] HasWeakSignature = 0x100000, /// /// Specifies that the online certificate revocation list /// the X509 chain relies on is currently offline. /// [EnumMember(Value = "OfflineRevocation")] OfflineRevocation = 0x1000000, /// /// Specifies that there is no certificate policy extension in /// the certificate. /// [EnumMember(Value = "NoIssuanceChainPolicy")] NoIssuanceChainPolicy = 0x2000000, /// /// Specifies that the certificate is explicitly distrusted. /// [EnumMember(Value = "ExplicitDistrust")] ExplicitDistrust = 0x4000000, /// /// Specifies that the certificate does not support a critical /// extension. /// [EnumMember(Value = "HasNotSupportedCriticalExtension")] HasNotSupportedCriticalExtension = 0x8000000 } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/tests/Azure.IIoT.OpcUa.Publisher.Models.Tests.csproj ================================================  net9.0 aggressive all runtime; build; native; contentfiles; analyzers; buildtransitive all runtime; build; native; contentfiles; analyzers ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/tests/Fixtures/TypeFixture.cs ================================================ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models.Tests { using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Runtime.Serialization; /// /// Helper /// public static class TypeFixture { public static IEnumerable GetDataContractTypes() { return GetAllModelTypes() .Distinct() .Select(t => new object[] { t }); } public static IEnumerable GetAllModelTypes() { return typeof(T).Assembly.GetExportedTypes() .Where(t => t.GetCustomAttribute() != null && t.GetGenericArguments().Length == 0); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/tests/GlobalSuppressions.cs ================================================ // This file is used by Code Analysis to maintain SuppressMessage // attributes that are applied to this project. // Project-level suppressions either have no target or are given // a specific target and scoped to a namespace, type, member, etc. using System.Diagnostics.CodeAnalysis; [assembly: SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "xunit")] [assembly: SuppressMessage("Usage", "xUnit1042:The member referenced by the MemberData attribute returns untyped data rows", Justification = "xunit")] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/tests/JsonSerializerTests.cs ================================================ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models.Tests { using AutoFixture; using AutoFixture.Kernel; using FluentAssertions; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Json; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text.Json; using Xunit; public class JsonSerializerTests { [Theory] [MemberData(nameof(TypeFixture.GetDataContractTypes), MemberType = typeof(TypeFixture))] public void SerializerDeserializeScalarTypeToBuffer(Type type) { var instance = Activator.CreateInstance(type); var buffer = _serializer.SerializeObjectToMemory(instance, type); var result = _serializer.Deserialize(buffer.ToArray(), type); result.Should().BeEquivalentTo(instance); } [Theory] [MemberData(nameof(TypeFixture.GetDataContractTypes), MemberType = typeof(TypeFixture))] public void SerializerDeserializeScalarTypeToString(Type type) { var instance = Activator.CreateInstance(type); var str = _serializer.SerializeObjectToString(instance); var result = _serializer.Deserialize(str, type); result.Should().BeEquivalentTo(instance); var expectedString = JsonSerializer.Serialize(instance, _serializer.Settings); str.Should().Be(expectedString); } [Theory] [MemberData(nameof(TypeFixture.GetDataContractTypes), MemberType = typeof(TypeFixture))] public void SerializerDeserializeScalarTypeToBufferWithFixture(Type type) { var fixture = new Fixture(); fixture.Customizations.Add(new TypeRelay(typeof(IReadOnlySet<>), typeof(HashSet<>))); fixture.Customizations.Add(new TypeRelay(typeof(IReadOnlyList<>), typeof(List<>))); fixture.Customizations.Add(new TypeRelay(typeof(IReadOnlyDictionary<,>), typeof(Dictionary<,>))); fixture.Customizations.Add(new TypeRelay(typeof(IReadOnlyCollection<>), typeof(List<>))); fixture.Behaviors .OfType() .ToList() .ForEach(b => fixture.Behaviors.Remove(b)); fixture.Behaviors.Add(new OmitOnRecursionBehavior(recursionDepth: 2)); // Create some random variant value fixture.Register(() => _serializer.FromObject(Activator.CreateInstance(type))); // Ensure utc datetimes fixture.Register(() => DateTimeOffset.UtcNow); fixture.Register(() => DateTime.UtcNow); var instance = new SpecimenContext(fixture).Resolve(new SeededRequest(type, null)); var buffer = _serializer.SerializeObjectToMemory(instance, type); var result = _serializer.Deserialize(buffer.ToArray(), type); result.Should().BeEquivalentTo(instance, options => options.AllowingInfiniteRecursion()); } [Theory] [MemberData(nameof(TypeFixture.GetDataContractTypes), MemberType = typeof(TypeFixture))] public void SerializerDeserializeArrayTypeToBufferWithFixture(Type type) { var fixture = new Fixture { RepeatCount = 2 }; fixture.Customizations.Add(new TypeRelay(typeof(IReadOnlySet<>), typeof(HashSet<>))); fixture.Customizations.Add(new TypeRelay(typeof(IReadOnlyList<>), typeof(List<>))); fixture.Customizations.Add(new TypeRelay(typeof(IReadOnlyDictionary<,>), typeof(Dictionary<,>))); fixture.Customizations.Add(new TypeRelay(typeof(IReadOnlyCollection<>), typeof(List<>))); fixture.Behaviors .OfType() .ToList() .ForEach(b => fixture.Behaviors.Remove(b)); fixture.Behaviors.Add(new OmitOnRecursionBehavior(recursionDepth: 2)); // Create some random variant value fixture.Register(() => _serializer.FromObject(Activator.CreateInstance(type))); // Ensure utc datetimes fixture.Register(() => DateTimeOffset.UtcNow); fixture.Register(() => DateTime.UtcNow); var builder = new SpecimenContext(fixture); var instance = ((IEnumerable)builder.Resolve( new MultipleRequest(new SeededRequest(type, null)))).Cast().ToArray(); var buffer = _serializer.SerializeObjectToMemory(instance, instance.GetType()); var result = _serializer.Deserialize(buffer.ToArray(), type.MakeArrayType()); result.Should().BeEquivalentTo(instance, options => options.AllowingInfiniteRecursion()); } private readonly DefaultJsonSerializer _serializer = new(); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/tests/MsgPackSerializerTests.cs ================================================ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models.Tests { using AutoFixture; using AutoFixture.Kernel; using FluentAssertions; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.MessagePack; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Xunit; public class MsgPackSerializerTests { [Theory] [MemberData(nameof(TypeFixture.GetDataContractTypes), MemberType = typeof(TypeFixture))] public void SerializerDeserializeScalarTypeToBuffer(Type type) { var instance = Activator.CreateInstance(type); var buffer = _serializer.SerializeObjectToMemory(instance, type); var result = _serializer.Deserialize(buffer.ToArray(), type); result.Should().BeEquivalentTo(instance); } [Theory] [MemberData(nameof(TypeFixture.GetDataContractTypes), MemberType = typeof(TypeFixture))] public void SerializerDeserializeScalarTypeToBufferWithFixture(Type type) { var fixture = new Fixture(); fixture.Customizations.Add(new TypeRelay(typeof(IReadOnlySet<>), typeof(HashSet<>))); fixture.Customizations.Add(new TypeRelay(typeof(IReadOnlyList<>), typeof(List<>))); fixture.Customizations.Add(new TypeRelay(typeof(IReadOnlyDictionary<,>), typeof(Dictionary<,>))); fixture.Customizations.Add(new TypeRelay(typeof(IReadOnlyCollection<>), typeof(List<>))); fixture.Behaviors .OfType() .ToList() .ForEach(b => fixture.Behaviors.Remove(b)); fixture.Behaviors.Add(new OmitOnRecursionBehavior(recursionDepth: 2)); // Create some random variant value fixture.Register(() => _serializer.FromObject(Activator.CreateInstance(type))); // Ensure utc datetimes fixture.Register(() => DateTimeOffset.UtcNow); fixture.Register(() => DateTime.UtcNow); var instance = new SpecimenContext(fixture).Resolve(new SeededRequest(type, null)); var buffer = _serializer.SerializeObjectToMemory(instance, type); var result = _serializer.Deserialize(buffer.ToArray(), type); result.Should().BeEquivalentTo(instance, options => options.AllowingInfiniteRecursion()); } [Theory] [MemberData(nameof(TypeFixture.GetDataContractTypes), MemberType = typeof(TypeFixture))] public void SerializerDeserializeArrayTypeToBufferWithFixture(Type type) { var fixture = new Fixture(); fixture.Customizations.Add(new TypeRelay(typeof(IReadOnlySet<>), typeof(HashSet<>))); fixture.Customizations.Add(new TypeRelay(typeof(IReadOnlyList<>), typeof(List<>))); fixture.Customizations.Add(new TypeRelay(typeof(IReadOnlyDictionary<,>), typeof(Dictionary<,>))); fixture.Customizations.Add(new TypeRelay(typeof(IReadOnlyCollection<>), typeof(List<>))); fixture.Behaviors .OfType() .ToList() .ForEach(b => fixture.Behaviors.Remove(b)); fixture.Behaviors.Add(new OmitOnRecursionBehavior(recursionDepth: 2)); // Create some random variant value fixture.Register(() => _serializer.FromObject(Activator.CreateInstance(type))); // Ensure utc datetimes fixture.Register(() => DateTimeOffset.UtcNow); fixture.Register(() => DateTime.UtcNow); var builder = new SpecimenContext(fixture); var instance = ((IEnumerable)builder.Resolve( new MultipleRequest(new SeededRequest(type, null)))).Cast().ToArray(); var buffer = _serializer.SerializeObjectToMemory(instance, instance.GetType()); var result = _serializer.Deserialize(buffer.ToArray(), type.MakeArrayType()); result.Should().BeEquivalentTo(instance, options => options.AllowingInfiniteRecursion()); } private readonly MessagePackSerializer _serializer = new(); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/tests/NewtonsoftSerializerTests.cs ================================================ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models.Tests { using AutoFixture; using AutoFixture.Kernel; using FluentAssertions; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Newtonsoft.Json; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Xunit; public class NewtonsoftSerializerTests { [Theory] [MemberData(nameof(TypeFixture.GetDataContractTypes), MemberType = typeof(TypeFixture))] public void SerializerDeserializeScalarTypeToBuffer(Type type) { var instance = Activator.CreateInstance(type); var buffer = _serializer.SerializeObjectToMemory(instance, type); var result = _serializer.Deserialize(buffer.ToArray(), type); result.Should().BeEquivalentTo(instance); } [Theory] [MemberData(nameof(TypeFixture.GetDataContractTypes), MemberType = typeof(TypeFixture))] public void SerializerDeserializeScalarTypeToString(Type type) { var instance = Activator.CreateInstance(type); var str = _serializer.SerializeObjectToString(instance, type); var result = _serializer.Deserialize(str, type); result.Should().BeEquivalentTo(instance); var expectedString = JsonConvert.SerializeObject(instance, _serializer.Settings); str.Should().Be(expectedString); } [Theory] [MemberData(nameof(TypeFixture.GetDataContractTypes), MemberType = typeof(TypeFixture))] public void SerializerDeserializeScalarTypeToBufferWithFixture(Type type) { var fixture = new Fixture(); fixture.Customizations.Add(new TypeRelay(typeof(IReadOnlySet<>), typeof(HashSet<>))); fixture.Customizations.Add(new TypeRelay(typeof(IReadOnlyList<>), typeof(List<>))); fixture.Customizations.Add(new TypeRelay(typeof(IReadOnlyDictionary<,>), typeof(Dictionary<,>))); fixture.Customizations.Add(new TypeRelay(typeof(IReadOnlyCollection<>), typeof(List<>))); fixture.Behaviors .OfType() .ToList() .ForEach(b => fixture.Behaviors.Remove(b)); fixture.Behaviors.Add(new OmitOnRecursionBehavior(recursionDepth: 2)); // Create some random variant value fixture.Register(() => _serializer.FromObject(Activator.CreateInstance(type))); // Ensure utc datetimes fixture.Register(() => DateTimeOffset.UtcNow); fixture.Register(() => DateTime.UtcNow); var instance = new SpecimenContext(fixture).Resolve(new SeededRequest(type, null)); var buffer = _serializer.SerializeObjectToMemory(instance, type); var result = _serializer.Deserialize(buffer.ToArray(), type); result.Should().BeEquivalentTo(instance, options => options.AllowingInfiniteRecursion()); } [Theory] [MemberData(nameof(TypeFixture.GetDataContractTypes), MemberType = typeof(TypeFixture))] public void SerializerDeserializeArrayTypeToBufferWithFixture(Type type) { var fixture = new Fixture { RepeatCount = 2 }; fixture.Customizations.Add(new TypeRelay(typeof(IReadOnlySet<>), typeof(HashSet<>))); fixture.Customizations.Add(new TypeRelay(typeof(IReadOnlyList<>), typeof(List<>))); fixture.Customizations.Add(new TypeRelay(typeof(IReadOnlyDictionary<,>), typeof(Dictionary<,>))); fixture.Customizations.Add(new TypeRelay(typeof(IReadOnlyCollection<>), typeof(List<>))); fixture.Behaviors .OfType() .ToList() .ForEach(b => fixture.Behaviors.Remove(b)); fixture.Behaviors.Add(new OmitOnRecursionBehavior(recursionDepth: 2)); // Create some random variant value fixture.Register(() => _serializer.FromObject(Activator.CreateInstance(type))); // Ensure utc datetimes fixture.Register(() => DateTimeOffset.UtcNow); fixture.Register(() => DateTime.UtcNow); var builder = new SpecimenContext(fixture); var instance = ((IEnumerable)builder.Resolve( new MultipleRequest(new SeededRequest(type, null)))).Cast().ToArray(); var buffer = _serializer.SerializeObjectToMemory(instance, instance.GetType()); var result = _serializer.Deserialize(buffer.ToArray(), type.MakeArrayType()); result.Should().BeEquivalentTo(instance, options => options.AllowingInfiniteRecursion()); } private readonly NewtonsoftJsonSerializer _serializer = new(); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Models/tests/PublishNodesEndpointApiModelTests.cs ================================================ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Models.Tests { using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using System; using Xunit; public class PublishedNodesEntryModelTests { [Fact] public void UseSecurityDeserializationTest() { var newtonSoftJsonSerializer = new NewtonsoftJsonSerializer(); var modelJson = """ { "EndpointUrl": "opc.tcp://localhost:50002", "NodeId": { "Identifier": "ns=0;i=2261" } } """; var model = newtonSoftJsonSerializer.Deserialize(modelJson); Assert.Null(model.UseSecurity); modelJson = """ { "EndpointUrl": "opc.tcp://localhost:50002", "UseSecurity": false, "NodeId": { "Identifier": "ns=0;i=2261" } } """; model = newtonSoftJsonSerializer.Deserialize(modelJson); Assert.False(model.UseSecurity); modelJson = """ { "EndpointUrl": "opc.tcp://localhost:50002", "UseSecurity": true, "NodeId": { "Identifier": "ns=0;i=2261" } } """; model = newtonSoftJsonSerializer.Deserialize(modelJson); Assert.True(model.UseSecurity); } [Fact] public void UseSecuritySerializationTest() { var newtonSoftJsonSerializer = new NewtonsoftJsonSerializer(); var model = new PublishedNodesEntryModel { EndpointUrl = "opc.tcp://localhost:50000", OpcNodes = [ new() { Id = "i=2258" } ] }; var modeJson = newtonSoftJsonSerializer.SerializeToString(model); Assert.DoesNotContain("\"UseSecurity\":false", modeJson, StringComparison.Ordinal); model = new PublishedNodesEntryModel { EndpointUrl = "opc.tcp://localhost:50000", UseSecurity = false, OpcNodes = [ new() { Id = "i=2258" } ] }; modeJson = newtonSoftJsonSerializer.SerializeToString(model); Assert.Contains("\"UseSecurity\":false", modeJson, StringComparison.Ordinal); model = new PublishedNodesEntryModel { EndpointUrl = "opc.tcp://localhost:50000", UseSecurity = true, OpcNodes = [ new() { Id = "i=2258" } ] }; modeJson = newtonSoftJsonSerializer.SerializeToString(model); Assert.Contains("\"UseSecurity\":true", modeJson, StringComparison.Ordinal); } [Fact] public void OpcAuthenticationModeDeserializationTest() { var newtonSoftJsonSerializer = new NewtonsoftJsonSerializer(); var modelJson = """ { "EndpointUrl": "opc.tcp://localhost:50002", "OpcNodes": [ { "Identifier": "ns=0;i=2261" } ] } """; var model = newtonSoftJsonSerializer.Deserialize(modelJson); Assert.Equal(OpcAuthenticationMode.Anonymous, model.OpcAuthenticationMode); modelJson = """ { "EndpointUrl": "opc.tcp://localhost:50002", "OpcAuthenticationMode": "anonymous", "OpcNodes": [ { "Identifier": "ns=0;i=2261" } ] } """; model = newtonSoftJsonSerializer.Deserialize(modelJson); Assert.Equal(OpcAuthenticationMode.Anonymous, model.OpcAuthenticationMode); modelJson = """ { "EndpointUrl": "opc.tcp://localhost:50002", "OpcAuthenticationMode": "usernamePassword", "OpcNodes": [ { "Identifier": "ns=0;i=2261" } ] } """; model = newtonSoftJsonSerializer.Deserialize(modelJson); Assert.Equal(OpcAuthenticationMode.UsernamePassword, model.OpcAuthenticationMode); } [Fact] public void OpcAuthenticationModeSerializationTest() { var newtonSoftJsonSerializer = new NewtonsoftJsonSerializer(); var model = new PublishedNodesEntryModel { EndpointUrl = "opc.tcp://localhost:50000", OpcNodes = [ new() { Id = "i=2258" } ] }; var modeJson = newtonSoftJsonSerializer.SerializeToString(model); Assert.Contains("\"OpcAuthenticationMode\":\"Anonymous\"", modeJson, StringComparison.Ordinal); model = new PublishedNodesEntryModel { EndpointUrl = "opc.tcp://localhost:50000", OpcAuthenticationMode = OpcAuthenticationMode.Anonymous, OpcNodes = [ new() { Id = "i=2258" } ] }; modeJson = newtonSoftJsonSerializer.SerializeToString(model); Assert.Contains("\"OpcAuthenticationMode\":\"Anonymous\"", modeJson, StringComparison.Ordinal); model = new PublishedNodesEntryModel { EndpointUrl = "opc.tcp://localhost:50000", OpcAuthenticationMode = OpcAuthenticationMode.UsernamePassword, OpcNodes = [ new() { Id = "i=2258" } ] }; modeJson = newtonSoftJsonSerializer.SerializeToString(model); Assert.Contains("\"OpcAuthenticationMode\":\"UsernamePassword\"", modeJson, StringComparison.Ordinal); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Azure.IIoT.OpcUa.Publisher.Module.Cli.csproj ================================================  Exe net9.0 true enable true Always Always Always ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Initfiles/Kepserver.init ================================================ ### // @delay 5 // @retries 3 ExpandAndCreateOrUpdateDataSetWriterEntries_V2 { "entry": { "EndpointUrl": "opc.tcp://DESKTOP-BGFJS91:50001", "UseSecurity": false, "DataSetWriterGroup": "Simulation", "OpcNodes": [ { "Id": "ns=2;s=Sim.CH1" } ] }, "request": { "maxLevelsToExpand": 1, "createSingleWriter": true } } ### # @on-error Shutdown_V2 true ### ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Initfiles/MachineTools.init ================================================ ### // 3 retries in case of failure, with a delay of 5 seconds between // @delay 5 // @retries 3 // Creates writer entries for all objects that implement the // machine tool object type or one of its subtypes on the // umati reference server ExpandAndCreateOrUpdateDataSetWriterEntries_V2 { "entry": { "EndpointUrl": "opc.tcp://opcua.umati.app:4840", "UseSecurity": false, "DataSetWriterGroup": "MachineTools", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/MachineTool/;i=13" } ] }, "request": { "flattenTypeInstance": true } } ### // Shutdown the publisher in case the expansion failed // and let docker restart it. The Fail fast argument // provided as json payload. # @on-error Shutdown_V2 true ### ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Initfiles/Machinery.init ================================================ ### // @delay 5 ExpandAndCreateOrUpdateDataSetWriterEntries { "entry": { "EndpointUrl": "opc.tcp://opcua.umati.app:4840", "UseSecurity": false, "DataSetWriterGroup": "Machinery Objects", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Machinery/;i=1001" } ] }, "request": { "flattenTypeInstance": true } } // @retries 3 ### Shutdown // @on-error ### ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Initfiles/Objects.init ================================================ ### // @delay 5 // @retries 3 ExpandAndCreateOrUpdateDataSetWriterEntries_V2 { "entry": { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": false, "DataSetWriterGroup": "Objects", "OpcNodes": [ { "Id": "i=85" } ] } } ### # @on-error Shutdown_V2 true ### ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Initfiles/Variables.init ================================================ ### // @delay 5 // @retries 3 ExpandAndCreateOrUpdateDataSetWriterEntries_V2 { "entry": { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": false, "DataSetWriterGroup": "Variables", "OpcNodes": [ { "Id": "i=85" } ] }, "request": { "createSingleWriter": true, "maxDepth": 10, "discardErrors": true } } ### # @on-error Shutdown_V2 true ### ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/AllBad.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "MessagingMode": "PubSub", "DataSetPublishingInterval": 100, "OpcNodes": [ { "Id": "ns=0;s=unknown1", "OpcSamplingInterval": 100, "FetchDisplayName": true }, { "Id": "ns=0;s=unknown2", "OpcSamplingInterval": 100 }, { "Id": "ns=0;s=unknown3", "OpcSamplingInterval": 100 } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/BrowsePath.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "BrowsePath": [ "Objects", "Server", "ServerStatus", "CurrentTime" ], "DisplayName": "ServerTime" }, { "BrowsePath": [ "Objects", "Server", "ServerStatus", "State" ], "DisplayName": "ServerState" }, { "BrowsePath": [ "Objects", "17:OpcPlc", "17:Telemetry", "17:Fast", "17:FastUIntScalar1" ], "DisplayName": "FastUIntScalar1" }, { "BrowsePath": [ "Objects", "nsu=http://opcfoundation.org/UA/Plc/Applications;OpcPlc", "nsu=http://opcfoundation.org/UA/Plc/Applications;Telemetry", "nsu=http://opcfoundation.org/UA/Plc/Applications;Fast", "nsu=http://opcfoundation.org/UA/Plc/Applications;FastUIntScalar2" ], "DisplayName": "FastUIntScalar2" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/CyclicReads.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "i=2258", "UseCyclicRead": true }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=StepUp", "UseCyclicRead": true }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean", "UseCyclicRead": true }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32", "UseCyclicRead": true }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32", "UseCyclicRead": true }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData", "UseCyclicRead": true }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1", "UseCyclicRead": true }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2", "UseCyclicRead": true }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3", "UseCyclicRead": true }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1", "UseCyclicRead": true }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2", "UseCyclicRead": true }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3", "UseCyclicRead": true }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData", "UseCyclicRead": true }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData", "UseCyclicRead": true }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1", "UseCyclicRead": true }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2", "UseCyclicRead": true }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3", "UseCyclicRead": true }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1", "UseCyclicRead": true }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1", "UseCyclicRead": true }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2", "UseCyclicRead": true }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3", "UseCyclicRead": true }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1", "UseCyclicRead": true }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData", "UseCyclicRead": true }, { "Id": "ns=24;i=1259", "UseCyclicRead": true } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/DataItems.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "EndpointSecurityMode": "Sign", "OpcNodes": [ { "Id": "ns=24;i=1259", "OpcSamplingInterval": 2000, "OpcPublishingInterval": 2000, "DisplayName": "Output", "SkipFirst": true } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/DataSetTopics.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "MES", "QueueName": "{RootTopic}/{DataSetWriterName}/Status", "MessagingMode": "RawDataSets", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc;s=Plc" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "MES", "QueueName": "{RootTopic}/{DataSetWriterName}/Items/Produced", "MessagingMode": "RawDataSets", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=StepUp" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "MES", "QueueName": "{RootTopic}/{DataSetWriterName}/Items/Routing", "MessagingMode": "RawDataSets", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "MES", "QueueName": "{RootTopic}/{DataSetWriterName}/Random/SignedInt32", "MessagingMode": "RawDataSets", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "MES", "QueueName": "{RootTopic}/{DataSetWriterName}/Random/UnsignedInt32", "MessagingMode": "RawDataSets", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "MES", "QueueName": "{RootTopic}/{DataSetWriterName}/Health", "MessagingMode": "RawDataSets", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Test", "QueueName": "{RootTopic}/{DataSetWriterName}/Fast/UInt/Scalar1", "MessagingMode": "RawDataSets", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Test", "QueueName": "{RootTopic}/{DataSetWriterName}/Fast/UInt/Scalar2", "MessagingMode": "RawDataSets", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Test", "QueueName": "{RootTopic}/{DataSetWriterName}/Fast/UInt/Scalar3", "MessagingMode": "RawDataSets", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Test", "QueueName": "{RootTopic}/{DataSetWriterName}/Fast/Random/UInt/Scalar1", "MessagingMode": "RawDataSets", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Test", "QueueName": "{RootTopic}/{DataSetWriterName}/Fast/Random/UInt/Scalar2", "MessagingMode": "RawDataSets", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Test", "QueueName": "{RootTopic}/{DataSetWriterName}/Fast/Random/UInt/Scalar3", "MessagingMode": "RawDataSets", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Test", "QueueName": "{RootTopic}/{DataSetWriterName}/Trend", "MessagingMode": "RawDataSets", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Assembly", "QueueName": "{RootTopic}/{DataSetWriterName}/Trend", "MessagingMode": "RawDataSets", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Assembly", "QueueName": "{RootTopic}/{DataSetWriterName}/Slow/UInt/Scalar1", "MessagingMode": "RawDataSets", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Assembly", "QueueName": "{RootTopic}/{DataSetWriterName}/Slow/UInt/Scalar2", "MessagingMode": "RawDataSets", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Assembly", "QueueName": "{RootTopic}/{DataSetWriterName}/Slow/UInt/Scalar3", "MessagingMode": "RawDataSets", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Assembly", "QueueName": "{RootTopic}/{DataSetWriterName}/Slow/UInt/Scalar1/Bad", "MessagingMode": "RawDataSets", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Packaging", "QueueName": "{RootTopic}/{DataSetWriterName}/Slow/UInt/Scalar1/Random", "MessagingMode": "RawDataSets", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Packaging", "QueueName": "{RootTopic}/{DataSetWriterName}/Slow/UInt/Scalar2/Random", "MessagingMode": "RawDataSets", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Packaging", "QueueName": "{RootTopic}/{DataSetWriterName}/Slow/UInt/Scalar3/Random", "MessagingMode": "RawDataSets", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Packaging", "QueueName": "{RootTopic}/{DataSetWriterName}/Slow/UInt/Scalar1/Random/Bad", "MessagingMode": "RawDataSets", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Packaging", "QueueName": "{RootTopic}/{DataSetWriterName}/Health", "MessagingMode": "RawDataSets", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/Deadband.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "EndpointSecurityMode": "SignAndEncrypt", "OpcNodes": [ { "Id": "http://test.org/UA/Data/#i=11224", "OpcSamplingInterval": 1000, "OpcPublishingInterval": 1000, "QueueSize": 10, "DeadbandType": "Absolute", "DeadbandValue": 5.0, "DisplayName": "DoubleValues" }, { "Id": "http://test.org/UA/Data/#i=11206", "OpcSamplingInterval": 1000, "OpcPublishingInterval": 1000, "QueueSize": 10, "DeadbandType": "Percent", "DeadbandValue": 5.0, "DisplayName": "Int64Values" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/Empty.json ================================================ [ ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/Extremes.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=504fb315-75db-ef6e-2650-7c499743800a" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWX" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=LongString10kB" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=LongString50kB" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=LongString100kB" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=LongString200kB" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadFastUIntScalar1" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadFastRandomUIntScalar1" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=Special_\u0022!\u00A7$%\u0026/()=?\u0060\u00B4\\\u002B~*\u0027#_-:.;,\u003C\u003E|@^\u00B0\u20AC\u00B5{[]}" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/FastTime.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "DataSetPublishingInterval": 10, "UseSecurity": true, "OpcNodes": [ { "Id": "ns=24;i=1259", "OpcSamplingInterval": 10, "QueueSize": 10 }, { "Id": "i=2258", "OpcSamplingInterval": 10, "QueueSize": 10 } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/FixedAndData.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "i=2258" }, { "Id": "i=2271" }, { "Id": "i=2254" }, { "Id": "i=2255" }, { "Id": "i=11702" }, { "Id": "i=11703" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/Fixedvalue.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "i=2271" }, { "Id": "i=2254" }, { "Id": "i=2255" }, { "Id": "i=11702" }, { "Id": "i=11703" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/Heartbeat.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "OpcNodes": [ { "Id": "ns=24;i=1259", "OpcPublishingInterval": 20000, "HeartbeatInterval": 20, "DisplayName": "Output" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/Heartbeat2.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "OpcNodes": [ { "Id": "i=2258", "FetchDisplayName": true, "OpcPublishingInterval": 60000, "HeartbeatInterval": 60 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean", "FetchDisplayName": true, "OpcPublishingInterval": 60000, "HeartbeatInterval": 60 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32", "FetchDisplayName": true, "OpcPublishingInterval": 60000, "HeartbeatInterval": 60 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32", "FetchDisplayName": true, "OpcPublishingInterval": 60000, "HeartbeatInterval": 60 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData", "FetchDisplayName": true, "OpcPublishingInterval": 60000, "HeartbeatInterval": 60 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1", "FetchDisplayName": true, "OpcPublishingInterval": 60000, "HeartbeatInterval": 60 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2", "FetchDisplayName": true, "OpcPublishingInterval": 60000, "HeartbeatInterval": 60 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3", "FetchDisplayName": true, "OpcPublishingInterval": 60000, "HeartbeatInterval": 60 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1", "FetchDisplayName": true, "OpcPublishingInterval": 60000, "HeartbeatInterval": 60 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2", "FetchDisplayName": true, "OpcPublishingInterval": 60000, "HeartbeatInterval": 60 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3", "FetchDisplayName": true, "OpcPublishingInterval": 60000, "HeartbeatInterval": 60 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData", "FetchDisplayName": true, "OpcPublishingInterval": 60000, "HeartbeatInterval": 60 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData", "FetchDisplayName": true, "OpcPublishingInterval": 60000, "HeartbeatInterval": 60 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1", "FetchDisplayName": true, "OpcPublishingInterval": 60000, "HeartbeatInterval": 60 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2", "FetchDisplayName": true, "OpcPublishingInterval": 60000, "HeartbeatInterval": 60 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3", "FetchDisplayName": true, "OpcPublishingInterval": 60000, "HeartbeatInterval": 60 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1", "FetchDisplayName": true, "OpcPublishingInterval": 60000, "HeartbeatInterval": 60 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1", "FetchDisplayName": true, "OpcPublishingInterval": 60000, "HeartbeatInterval": 60 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2", "FetchDisplayName": true, "OpcPublishingInterval": 60000, "HeartbeatInterval": 60 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3", "FetchDisplayName": true, "OpcPublishingInterval": 60000, "HeartbeatInterval": 60 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1", "FetchDisplayName": true, "OpcPublishingInterval": 60000, "HeartbeatInterval": 60 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData", "FetchDisplayName": true, "OpcPublishingInterval": 60000, "HeartbeatInterval": 60 } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/Heartbeat3.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "DefaultHeartbeatInterval": 60000, "DataSetPublishingInterval": 1000, "DataSetSamplingInterval": 1000, "DataSetFetchDisplayNames": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/Isa95Jobs.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "i=2253", "DisplayName": "Isa95JobResponseData", "QueueSize": 10, "EventFilter": { "TypeDefinitionId": "nsu=http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/;i=1006" } } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/KeepAlive.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "SendKeepAliveDataSetMessages": true, "MessagingMode": "PubSub", "UseSecurity": true, "OpcNodes": [ { "Id": "i=2259", "FetchDisplayName": true } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/KeyFrames.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "MessagingMode": "PubSub", "DataSetExtensionFields": { "EngineeringUnits": "mm/sec", "AssetId": 5, "Important": false, "Variance": 12.3465 }, "DataSetKeyFrameCount": 10, "DataSetPublishingInterval": 100, "OpcNodes": [ { "Id": "i=2258", "OpcSamplingInterval": 100, "FetchDisplayName": true } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/ModelChanges.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "EndpointSecurityMode": "SignAndEncrypt", "OpcNodes": [ { "ModelChangeHandling": { "RebrowsePeriod": "00:00:10" } } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/MultiDataSetWriter.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "MES", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc;s=Plc" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "MES", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=StepUp" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "MES", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "MES", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "MES", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "MES", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "MES", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Test", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Test", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Test", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Test", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Test", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Assembly", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Assembly", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Assembly", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Assembly", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Assembly", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Assembly", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Packaging", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Packaging", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Packaging", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Packaging", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterId": "Packaging", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/MultiEndpoint.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc;s=Plc" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=StepUp" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/MultiWriterGroup.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "MES", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc;s=Plc" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "MES", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=StepUp" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "MES", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "MES", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "MES", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "MES", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "MES", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Test", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Test", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Test", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Test", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Test", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Assembly", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Assembly", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Assembly", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Assembly", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Assembly", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Assembly", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Packaging", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Packaging", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Packaging", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Packaging", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Packaging", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/MultiWriterGroupFs.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "MES", "WriterGroupTransport": "FileSystem", "WriterGroupTransportConfiguration": "MES", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc;s=Plc" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "MES", "WriterGroupTransport": "FileSystem", "WriterGroupTransportConfiguration": "MES", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=StepUp" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "MES", "WriterGroupTransport": "FileSystem", "WriterGroupTransportConfiguration": "MES", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "MES", "WriterGroupTransport": "FileSystem", "WriterGroupTransportConfiguration": "MES", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "MES", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "MES", "WriterGroupTransport": "FileSystem", "WriterGroupTransportConfiguration": "MES", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "MES", "WriterGroupTransport": "FileSystem", "WriterGroupTransportConfiguration": "MES", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Test", "WriterGroupTransport": "FileSystem", "WriterGroupTransportConfiguration": "Test", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Test", "WriterGroupTransport": "FileSystem", "WriterGroupTransportConfiguration": "Test", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Test", "WriterGroupTransport": "FileSystem", "WriterGroupTransportConfiguration": "Test", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Test", "WriterGroupTransport": "FileSystem", "WriterGroupTransportConfiguration": "Test", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Test", "WriterGroupTransport": "FileSystem", "WriterGroupTransportConfiguration": "Test", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Assembly", "WriterGroupTransport": "FileSystem", "WriterGroupTransportConfiguration": "Assembly1", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Assembly", "WriterGroupTransport": "FileSystem", "WriterGroupTransportConfiguration": "Assembly1", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData" } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Assembly", "WriterGroupTransport": "FileSystem", "WriterGroupTransportConfiguration": "Assembly2", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Assembly", "WriterGroupTransport": "FileSystem", "WriterGroupTransportConfiguration": "Assembly2", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Assembly", "WriterGroupTransport": "FileSystem", "WriterGroupTransportConfiguration": "Assembly2", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Assembly", "WriterGroupTransport": "FileSystem", "WriterGroupTransportConfiguration": "Assembly2", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Packaging", "WriterGroupTransport": "FileSystem", "WriterGroupTransportConfiguration": "Packaging1", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Packaging", "WriterGroupTransport": "FileSystem", "WriterGroupTransportConfiguration": "Packaging1", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Packaging", "WriterGroupTransport": "FileSystem", "WriterGroupTransportConfiguration": "Packaging1", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Packaging", "WriterGroupTransport": "FileSystem", "WriterGroupTransportConfiguration": "Packaging1", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1", "OpcPublishingInterval": 10000 } ] }, { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetWriterGroup": "Packaging", "WriterGroupTransport": "FileSystem", "WriterGroupTransportConfiguration": "Packaging2", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/NoNodes.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "EndpointSecurityMode": "Sign", "OpcNodes": [] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/PendingAlarms.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "DisplayName": "PendingAlarms", "Id": "i=2253", "EventFilter": { "TypeDefinitionId": "i=2041" }, "ConditionHandling": { "UpdateInterval": 10, "SnapshotInterval": 20 } } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/PlcSimulation.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc;s=Plc" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=StepUp" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1", "OpcPublishingInterval": 10000 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2", "OpcPublishingInterval": 10000 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3", "OpcPublishingInterval": 10000 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1", "OpcPublishingInterval": 10000 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1", "OpcPublishingInterval": 10000 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2", "OpcPublishingInterval": 10000 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3", "OpcPublishingInterval": 10000 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1", "OpcPublishingInterval": 10000 }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/RegisteredRead.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "ns=24;i=1259", "OpcSamplingInterval": 500, "FetchDisplayName": true, "RegisterNode": true, "UseCyclicRead": true } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/SimpleEvents.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "i=2253", "DisplayName": "SimpleEvents", "QueueSize": 10, "EventFilter": { "SelectClauses": [ { "TypeDefinitionId": "i=2041", "BrowsePath": [ "EventId" ] }, { "TypeDefinitionId": "i=2041", "BrowsePath": [ "Message" ] }, { "TypeDefinitionId": "ns=16;i=235", "BrowsePath": [ "16:CycleId" ] }, { "TypeDefinitionId": "ns=16;i=235", "BrowsePath": [ "16:CurrentStep" ] } ], "WhereClause": { "Elements": [ { "FilterOperator": "OfType", "FilterOperands": [ { "Value": "ns=16;i=235" } ] } ] } } } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/SlowSample.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "DataSetFetchDisplayNames": true, "DataSetSamplingInterval": 30000, "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/SomeBad.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "MessagingMode": "PubSub", "DataSetPublishingInterval": 100, "OpcNodes": [ { "Id": "ns=24;i=1259", "OpcSamplingInterval": 1000, "FetchDisplayName": true }, { "Id": "ns=0;s=unknown2", "OpcSamplingInterval": 100 }, { "Id": "ns=0;s=unknown3", "OpcSamplingInterval": 100 } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/SubscribeErrors.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "OpcNodes": [ { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=StepUp" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean" }, { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=RandomSignedInt32" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DoesNotExist" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/TopicPerNode.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "MessagingMode": "RawDataSets", "OpcNodes": [ { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=StepUp", "Topic": "{RootTopic}/StepUp" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean", "Topic": "{RootTopic}/AlternatingBoolean" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32", "Topic": "{RootTopic}/Random/Int/Scalar1" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32", "Topic": "{RootTopic}/Random/UInt/Scalar1" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData", "Topic": "{RootTopic}/DipData" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1", "Topic": "{RootTopic}/Fast/UInt/Scalar1" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2", "Topic": "{RootTopic}/Fast/UInt/Scalar2" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3", "Topic": "{RootTopic}/Fast/UInt/Scalar3" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1", "Topic": "{RootTopic}/Fast/UInt/Scalar1/Random" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2", "Topic": "{RootTopic}/Fast/UInt/Scalar2/Random" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3", "Topic": "{RootTopic}/Fast/UInt/Scalar3/Random" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData", "Topic": "{RootTopic}/TrendData/Negative" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData", "Topic": "{RootTopic}/TrendData/Positive" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1", "Topic": "{RootTopic}/Slow/UInt/Scalar1" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2", "Topic": "{RootTopic}/Slow/UInt/Scalar2" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3", "Topic": "{RootTopic}/Slow/UInt/Scalar3" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1", "Topic": "{RootTopic}/Slow/UInt/Scalar1/Bad" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1", "Topic": "{RootTopic}/Slow/UInt/Scalar1/Random" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2", "Topic": "{RootTopic}/Slow/UInt/Scalar2/Random" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3", "Topic": "{RootTopic}/Slow/UInt/Scalar3/Random" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1", "Topic": "{RootTopic}/Slow/UInt/Scalar1/Random/Bad" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData", "Topic": "{RootTopic}/SpikeData" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Profiles/UnifiedNamespace.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": true, "MessagingMode": "SingleRawDataSet", "DataSetRouting": "UseBrowseNames", "OpcNodes": [ { "ModelChangeHandling": { "RebrowsePeriod": "00:00:10" } }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=StepUp" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=AlternatingBoolean" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomUnsignedInt32" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=DipData" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar1" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar2" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastUIntScalar3" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar1" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar2" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=FastRandomUIntScalar3" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=NegativeTrendData" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=PositiveTrendData" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar1" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar2" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowUIntScalar3" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowUIntScalar1" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar1" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar2" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SlowRandomUIntScalar3" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=BadSlowRandomUIntScalar1" }, { "Id": "nsu=http://opcfoundation.org/UA/Plc/Applications;s=SpikeData" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Program.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Runtime { using Autofac; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Stack.Sample; using Azure.IIoT.OpcUa.Publisher.Stack.Services; using Furly.Azure; using Furly.Azure.IoT; using Furly.Azure.IoT.Models; using Furly.Exceptions; using Furly.Extensions.Logging; using Furly.Extensions.Serializers; using Microsoft.AspNetCore.Hosting.Server; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Nito.AsyncEx; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; /// /// Publisher module host process /// public static class Program { /// /// Entry point /// /// /// public static void Main(string[] args) { var checkTrust = false; var withServer = false; string? deviceId = null, moduleId = null; int? reverseConnectPort = null; var loggerFactory = Log.ConsoleFactory(); var logger = loggerFactory.CreateLogger(); logger.PublisherModuleInit(); var instances = 1; string? connectionString = null; string? publishProfile = null; string? publishInitProfile = null; string? publishInitFilePath = null; string? publishedNodesFilePath = null; var useNullTransport = false; string? dumpMessages = null; string? dumpMessagesOutput = null; var scaleunits = 0u; var errorResponseRate = 0; var unknownArgs = new List(); try { for (var i = 0; i < args.Length; i++) { switch (args[i]) { case "--error-rate": i++; if (i < args.Length && int.TryParse(args[i], out var rate)) { errorResponseRate = rate; break; } throw new ArgumentException("Missing argument for --error-rate"); case "--dump-profiles": Console.WriteLine(); Console.WriteLine(); Console.WriteLine("The following messaging profiles are supported (selected with --mm and --me):"); Console.WriteLine(); Console.Write(MessagingProfile.GetAllAsMarkdownTable()); return; case "-C": case "--connection-string": i++; if (i < args.Length) { connectionString = args[i]; break; } throw new ArgumentException( "Missing argument for --connection-string"); case "-?": case "-h": case "--help": throw new ArgumentException("Help"); case "-N": case "--instances": i++; if (i < args.Length && int.TryParse(args[i], out instances)) { break; } throw new ArgumentException("Missing argument for --instances"); case "-U": case "--scale": i++; if (i < args.Length && uint.TryParse(args[i], out scaleunits)) { withServer = true; break; } throw new ArgumentException("Missing argument for --scale"); case "--reverse-connect": reverseConnectPort = 4840; break; case "--port": i++; if (i < args.Length && int.TryParse(args[i], out var port)) { reverseConnectPort = port; break; } throw new ArgumentException("Missing argument for --port"); case "-T": case "--only-trusted": checkTrust = true; break; case "-X": case "--out-null": useNullTransport = true; break; case "-S": case "--with-server": withServer = true; break; case "-D": case "--dump-messages": i++; useNullTransport = true; if (i < args.Length) { dumpMessages = args[i]; break; } throw new ArgumentException("Missing argument for --dump-messages"); case "-O": case "--dump-output": i++; if (i < args.Length) { dumpMessagesOutput = args[i]; break; } throw new ArgumentException("Missing argument for --dump-output"); case "-P": case "--publish-profile": i++; if (i < args.Length) { publishProfile = args[i]; withServer = true; break; } throw new ArgumentException("Missing argument for --publish-profile"); case "-I": case "--init-profile": i++; if (i < args.Length) { publishInitProfile = args[i]; withServer = true; break; } throw new ArgumentException("Missing argument for --init-profile"); case "--pnjson": i++; if (i < args.Length) { publishedNodesFilePath = args[i]; break; } throw new ArgumentException("Missing argument for --pnjson"); case "--init": i++; if (i < args.Length) { publishInitFilePath = args[i]; break; } throw new ArgumentException("Missing argument for --init"); case "--": break; default: unknownArgs.Add(args[i]); break; } } if (string.IsNullOrEmpty(connectionString) && !useNullTransport) { try { var configuration = new ConfigurationBuilder() .AddFromDotEnvFile() .AddEnvironmentVariables() .Build(); connectionString = configuration.GetValue("PCS_IOTHUB_CONNSTRING", string.Empty); if (string.IsNullOrEmpty(connectionString)) { connectionString = configuration.GetValue("_HUB_CS", string.Empty); } if (!string.IsNullOrEmpty(connectionString) && !ConnectionString.TryParse(connectionString, out _)) { throw new ArgumentException("Bad connection string configured."); } } catch (Exception e) { logger.MissingConnectionString(e.Message); } } deviceId = Dns.GetHostName().ToUpperInvariant(); logger.UsingDeviceId(deviceId); moduleId = "publisher"; logger.UsingModuleId(moduleId); args = [.. unknownArgs]; } catch (Exception e) { Console.Error.WriteLine( $@"{e.Message} Usage: Azure.IIoT.OpcUa.Publisher.Module.Cli [options] Options: -C --connection-string IoT Hub owner connection string to use to connect to IoT hub for operations on the registry. If not provided, read from environment. --help -? -h Prints out this help. "); return; } AppDomain.CurrentDomain.UnhandledException += (s, e) => logger.UnhandledException(e.ExceptionObject as Exception); using var cts = new CancellationTokenSource(); Task hostingTask; try { if (dumpMessages != null) { hostingTask = DumpMessagesAsync(dumpMessages, publishProfile, publishInitProfile, loggerFactory, TimeSpan.FromMinutes(2), scaleunits, errorResponseRate, dumpMessagesOutput, args, cts.Token); } else if (!withServer) { if (publishInitFilePath != null && !File.Exists(publishInitFilePath)) { publishInitFilePath = $"./Initfiles/{publishInitFilePath}.init"; if (File.Exists(publishInitFilePath)) { const string copyTo = "profile.init"; File.Copy(publishInitFilePath, copyTo, true); File.SetLastWriteTimeUtc(copyTo, DateTime.UtcNow); publishInitFilePath = copyTo; } else { publishInitFilePath = null; } } hostingTask = HostAsync(connectionString, loggerFactory, deviceId, moduleId, args, reverseConnectPort, !checkTrust, publishInitFilePath, publishedNodesFilePath, cts.Token); } else { hostingTask = WithServerAsync(connectionString, loggerFactory, deviceId, moduleId, args, publishProfile, publishInitProfile, scaleunits, errorResponseRate, !checkTrust, reverseConnectPort, cts.Token); } while (!cts.Token.IsCancellationRequested) { var key = Console.ReadKey(); switch (key.KeyChar) { case 'X': case 'x': Console.WriteLine("Exiting..."); cts.Cancel(); break; case 'P': case 'p': Console.WriteLine("Restarting publisher..."); kRestartPublisher.Set(); break; case 'S': case 's': Console.WriteLine("Restarting server..."); kRestartServer.Set(); break; case 'C': Console.WriteLine("Closing sessions and subscriptions in server"); ServerControl?.CloseSessions(true); break; case 'c': Console.WriteLine("Closing sessions in server"); ServerControl?.CloseSessions(false); break; case 'D': case 'd': Console.WriteLine("Closing subscriptions in server"); ServerControl?.CloseSubscriptions(); break; case '!': var control = ServerControl; if (control != null) { Console.WriteLine("Chaos !!!!!!!!!!!!!..."); control.Chaos = !control.Chaos; } break; } } // Wait for hosting task to exit hostingTask.GetAwaiter().GetResult(); } catch (Exception e) { logger.UnhandledException(e); } } private static readonly AsyncAutoResetEvent kRestartServer = new(false); private static readonly AsyncAutoResetEvent kRestartPublisher = new(false); private static ITestServer? ServerControl { get; set; } /// /// Host the module with connection string loaded from iot hub /// /// /// /// /// /// /// /// /// /// /// private static async Task HostAsync(string? connectionString, ILoggerFactory loggerFactory, string deviceId, string moduleId, string[] args, int? reverseConnectPort, bool acceptAll, string? publishInitFile, string? publishedNodesFilePath = null, CancellationToken ct = default) { var logger = loggerFactory.CreateLogger(); logger.ConnectionStringStart(deviceId, moduleId); ConnectionString? cs = null; if (connectionString != null) { while (true) { try { cs = await AddOrGetAsync(connectionString, deviceId, moduleId, logger).ConfigureAwait(false); logger.ConnectionStringRetrieved(deviceId, moduleId); break; } catch (Exception ex) { logger.ConnectionStringFailed(ex, deviceId, moduleId); } } } while (!ct.IsCancellationRequested) { using var cts = CancellationTokenSource.CreateLinkedTokenSource(ct); var running = RunAsync(logger, deviceId, moduleId, args, acceptAll, cs, reverseConnectPort, publishedNodesFilePath, publishInitFile, cts.Token); Console.WriteLine("Publisher running (Press P to restart)..."); await kRestartPublisher.WaitAsync(ct).ConfigureAwait(false); try { await cts.CancelAsync().ConfigureAwait(false); await running.ConfigureAwait(false); } catch (OperationCanceledException) { } } static async Task RunAsync(ILogger logger, string deviceId, string moduleId, string[] args, bool acceptAll, ConnectionString? cs, int? reverseConnectPort, string? publishedNodesFilePath, string? publishInitFile, CancellationToken ct) { logger.PublisherModuleStarting(deviceId, moduleId); var arguments = args.ToList(); if (publishedNodesFilePath == null) { publishedNodesFilePath = "profile.json"; await CopyProfileToPnJsonAsync("Empty", publishedNodesFilePath, null, ct).ConfigureAwait(false); } arguments.Add($"--pf={publishedNodesFilePath}"); if (publishInitFile != null) { arguments.Add($"--pi={publishInitFile}"); } if (!args.Any(a => a.StartsWith("-t=", StringComparison.OrdinalIgnoreCase))) { if (cs != null) { arguments.Add($"--ec={cs}"); } else { arguments.Add("-t=Null"); } } arguments.Add("--cl=5"); // enable 5 second client linger if (acceptAll) { // Accept all certificates arguments.Add("--aa"); } if (reverseConnectPort != null) { // Since we started the server with reverse connect // default the profile to use reverse connect arguments.Add("--urc"); } await Publisher.Module.Program.RunAsync([.. arguments], ct).ConfigureAwait(false); logger.PublisherModuleExited(deviceId, moduleId); } } /// /// setup publishing from sample server /// /// /// /// /// /// /// /// /// /// /// /// /// private static async Task WithServerAsync(string? connectionString, ILoggerFactory loggerFactory, string deviceId, string moduleId, string[] args, string? publishProfile, string? publishInitProfile, uint scaleunits, int errorRate, bool acceptAll, int? reverseConnectPort, CancellationToken ct) { try { using var server = new ServerWrapper(scaleunits, errorRate, loggerFactory, reverseConnectPort); // Start test server var endpointUrl = $"opc.tcp://localhost:{server.Port}/UA/SampleServer"; var publishInitFile = await LoadInitFileAsync(publishInitProfile, endpointUrl, ct).ConfigureAwait(false); if (publishInitFile != null && publishProfile == null) { publishProfile = "Empty"; } var publishedNodesFilePath = await LoadPnJsonAsync(server, publishProfile, endpointUrl, ct).ConfigureAwait(false); // Start publisher module await HostAsync(connectionString, loggerFactory, deviceId, moduleId, args, reverseConnectPort, acceptAll, publishInitFile, publishedNodesFilePath, ct).ConfigureAwait(false); } catch (OperationCanceledException) { } } /// /// Dump messages /// /// /// /// /// /// /// /// /// /// /// /// private static async Task DumpMessagesAsync(string messageMode, string? publishProfile, string? publishInitProfile, ILoggerFactory loggerFactory, TimeSpan duration, uint scaleunits, int errorRate, string? dumpMessagesOutput, string[] args, CancellationToken ct) { try { // Dump one message encoding at a time var rootFolder = Path.Combine(dumpMessagesOutput ?? ".", "dump"); foreach (var messageProfile in MessagingProfile.Supported) { if (messageProfile.MessageEncoding.HasFlag(MessageEncoding.IsGzipCompressed)) { // No need to dump gzip continue; } if (messageMode != "all" && !messageProfile.MessagingMode.ToString().Equals( messageMode, StringComparison.OrdinalIgnoreCase) && !messageProfile.MessageEncoding.ToString().Equals( messageMode, StringComparison.OrdinalIgnoreCase)) { Console.WriteLine($"Skipping {messageProfile}..."); continue; } var outputFolder = Path.Combine(rootFolder, messageProfile.MessagingMode.ToString(), messageProfile.MessageEncoding.ToString()); if (Directory.Exists(outputFolder) && Directory.EnumerateFiles(outputFolder).Any()) { continue; } Directory.CreateDirectory(outputFolder); await DumpPublishingProfiles(outputFolder, messageProfile, publishProfile, publishInitProfile).ConfigureAwait(false); } } catch (OperationCanceledException) { } // Dump message profile for all publishing profiles async Task DumpPublishingProfiles(string rootFolder, MessagingProfile messageProfile, string? profile, string? publishInitProfile) { if (publishInitProfile != null) { var outputFolder = Path.Combine(rootFolder, publishInitProfile); await DumpMessagesForDuration(outputFolder, "Empty", messageProfile, publishInitProfile, args).ConfigureAwait(false); return; } foreach (var publishProfile in Directory.EnumerateFiles("./Profiles", "*.json")) { var publishProfileName = Path.GetFileNameWithoutExtension(publishProfile); if (profile == null && (publishProfileName.StartsWith("Unified", StringComparison.OrdinalIgnoreCase) || publishProfileName.StartsWith("Empty", StringComparison.OrdinalIgnoreCase) || publishProfileName.StartsWith("NoNodes", StringComparison.OrdinalIgnoreCase))) { continue; } if (profile != null && !publishProfileName.Equals(profile, StringComparison.OrdinalIgnoreCase)) { continue; } var logger = loggerFactory.CreateLogger(publishProfileName); var outputFolder = Path.Combine(rootFolder, publishProfileName); if (Directory.Exists(outputFolder) && Directory.EnumerateFiles(outputFolder).Any()) { continue; } Directory.CreateDirectory(outputFolder); await DumpMessagesForDuration(outputFolder, publishProfile, messageProfile, null, args).ConfigureAwait(false); } } async Task DumpMessagesForDuration(string outputFolder, string publishProfile, MessagingProfile messageProfile, string? publishInitProfile, string[] args) { using var runtime = new CancellationTokenSource(duration); try { using var linkedToken = CancellationTokenSource.CreateLinkedTokenSource( ct, runtime.Token); var name = Path.GetFileNameWithoutExtension(publishProfile); Console.Title = $"Dumping {messageProfile} for {name}..."; await RunAsync(loggerFactory, publishProfile, messageProfile, outputFolder, scaleunits, errorRate, args, publishInitProfile, linkedToken.Token).ConfigureAwait(false); } catch (OperationCanceledException) when (runtime.IsCancellationRequested) { } } static async Task RunAsync(ILoggerFactory loggerFactory, string publishProfile, MessagingProfile messageProfile, string outputFolder, uint scaleunits, int errorRate, string[] args, string? publishInitProfile, CancellationToken ct) { // Start test server using var server = new ServerWrapper(scaleunits, errorRate, loggerFactory, null); var name = Path.GetFileNameWithoutExtension(publishProfile); var endpointUrl = $"opc.tcp://localhost:{server.Port}/UA/SampleServer"; var publishedNodesFilePath = await LoadPnJsonAsync(server, name, endpointUrl, ct).ConfigureAwait(false); if (publishedNodesFilePath == null) { return; } var initProfile = Path.GetFileNameWithoutExtension(publishInitProfile); var publishInitFile = await LoadInitFileAsync(initProfile, endpointUrl, ct).ConfigureAwait(false); // // Check whether the profile overrides the messaging mode, then set it to the desired // one regardless of whether it will work or not // var check = await File.ReadAllTextAsync(publishedNodesFilePath, ct).ConfigureAwait(false); if (check.Contains("\"MessagingMode\":", StringComparison.InvariantCulture) && !check.Contains($"\"MessagingMode\": \"{messageProfile.MessagingMode}\"", StringComparison.InvariantCulture)) { check = ReplacePropertyValue(check, "MessagingMode", messageProfile.MessagingMode.ToString()); await File.WriteAllTextAsync(publishedNodesFilePath, check, ct).ConfigureAwait(false); } var arguments = new HashSet { "-c", "--ps", $"--pf={publishedNodesFilePath}", $"--me={messageProfile.MessageEncoding}", $"--mm={messageProfile.MessagingMode}", $"--ttt={name}/{{WriterGroup}}", $"--mdt={name}/{{WriterGroup}}", "-t=FileSystem", $"-o={outputFolder}", "--aa" }; if (publishInitFile != null) { arguments.Add($"--pi={publishInitFile}"); } args.ForEach(a => arguments.Add(a)); await Publisher.Module.Program.RunAsync([.. arguments], ct).ConfigureAwait(false); } } private static async Task LoadPnJsonAsync(ServerWrapper server, string? publishProfile, string? endpointUrl, CancellationToken ct) { const string publishedNodesFilePath = "profile.json"; if (!string.IsNullOrEmpty(publishProfile)) { await CopyProfileToPnJsonAsync(publishProfile, publishedNodesFilePath, endpointUrl, ct).ConfigureAwait(false); return publishedNodesFilePath; } var testServer = await server.Server.Task.ConfigureAwait(false); if (testServer?.PublishedNodesJson != null && endpointUrl != null) { var json = testServer.PublishedNodesJson.Replace("{{EndpointUrl}}", endpointUrl, StringComparison.Ordinal); // var entries = JsonSerializer.Deserialize(server.PublishedNodesJson); await File.WriteAllTextAsync(publishedNodesFilePath, json, ct).ConfigureAwait(false); return publishedNodesFilePath; } return null; } private static async Task CopyProfileToPnJsonAsync(string publishProfile, string publishedNodesFilePath, string? endpointUrl, CancellationToken ct) { var publishedNodesFile = $"./Profiles/{publishProfile}.json"; if (!File.Exists(publishedNodesFile)) { throw new ArgumentException($"Profile {publishProfile} does not exist"); } var text = await File.ReadAllTextAsync(publishedNodesFile, ct).ConfigureAwait(false); if (endpointUrl != null) { text = text.Replace("{{EndpointUrl}}", endpointUrl, StringComparison.Ordinal); } await File.WriteAllTextAsync(publishedNodesFilePath, text, ct).ConfigureAwait(false); } private static async Task LoadInitFileAsync(string? initProfile, string endpointUrl, CancellationToken ct) { const string initFile = "profile.init"; if (!string.IsNullOrEmpty(initProfile)) { var publishedNodesFile = $"./Initfiles/{initProfile}.init"; if (!File.Exists(publishedNodesFile)) { throw new ArgumentException($"Init profile {initProfile} does not exist"); } await File.WriteAllTextAsync(initFile, (await File.ReadAllTextAsync(publishedNodesFile, ct).ConfigureAwait(false)) .Replace("{{EndpointUrl}}", endpointUrl, StringComparison.Ordinal), ct).ConfigureAwait(false); return initFile; } return null; } /// /// Add or get module identity /// /// /// /// /// private static async Task AddOrGetAsync(string connectionString, string deviceId, string moduleId, ILogger logger) { var builder = new ContainerBuilder(); builder.AddIoTHubServiceClient(); builder.Configure( options => options.ConnectionString = connectionString); builder.AddDefaultJsonSerializer(); builder.AddLogging(); var container = builder.Build(); await using (container.ConfigureAwait(false)) { var registry = container.Resolve(); // Create iot edge gateway try { await registry.CreateOrUpdateAsync(new DeviceTwinModel { Id = deviceId, Tags = new Dictionary { [Constants.TwinPropertyTypeKey] = Constants.EntityTypeGateway }, IotEdge = true }, false).ConfigureAwait(false); } catch (ResourceConflictException) { logger.IotEdgeDeviceExists(deviceId); } // Create publisher module try { await registry.CreateOrUpdateAsync(new DeviceTwinModel { Id = deviceId, ModuleId = moduleId }, false, default).ConfigureAwait(false); } catch (ResourceConflictException) { logger.PublisherExists(moduleId); } var module = await registry.GetRegistrationAsync(deviceId, moduleId).ConfigureAwait(false); return ConnectionString.CreateModuleConnectionString(registry.HostName, deviceId, moduleId, module.PrimaryKey!); } } /// /// Wraps server and disposes after use /// private sealed class ServerWrapper : IDisposable { public int Port { get; } = 61457; public TaskCompletionSource Server { get; private set; } = new(); /// /// Create wrapper /// /// /// /// /// public ServerWrapper(uint scaleunits, int errorRate, ILoggerFactory logger, int? reverseConnectPort) { _cts = new CancellationTokenSource(); _server = RunSampleServerAsync(scaleunits, errorRate, logger, Port, reverseConnectPort, _cts.Token); } /// public void Dispose() { _cts.Cancel(); _server.Wait(); _cts.Dispose(); } /// /// Run server until cancelled /// /// /// /// /// /// /// private async Task RunSampleServerAsync(uint scaleunits, int errorRate, ILoggerFactory loggerFactory, int port, int? reverseConnectPort, CancellationToken ct) { var logger = loggerFactory.CreateLogger(); while (!ct.IsCancellationRequested) { try { using (var server = new ServerConsoleHost( new ServerFactory(loggerFactory.CreateLogger(), Directory.GetCurrentDirectory(), scaleunits) { LogStatus = false, EnableDiagnostics = true }, loggerFactory.CreateLogger()) { PkiRootPath = Path.Combine(Directory.GetCurrentDirectory(), "server"), AutoAccept = true }) { logger.ServerRestarting(); await server.StartAsync(new List { port }).ConfigureAwait(false); server.TestServer.InjectErrorResponseRate = errorRate; Server.SetResult(server.TestServer); ServerControl = server.TestServer; logger.ServerRestarted(); if (reverseConnectPort != null) { logger.ReverseConnectToClient(); await server.AddReverseConnectionAsync( new Uri($"opc.tcp://localhost:{reverseConnectPort}"), 1).ConfigureAwait(false); } await kRestartServer.WaitAsync(ct).ConfigureAwait(false); ServerControl = null; logger.StoppingServer(); Server = new TaskCompletionSource(); } logger.ServerStopped(); logger.WaitingToRestartServer(); await kRestartServer.WaitAsync(ct).ConfigureAwait(false); } catch (OperationCanceledException) { } catch (Exception ex) { logger.ServerException(ex); } } ServerControl = null; logger.ServerExited(); } private readonly CancellationTokenSource _cts; private readonly Task _server; } public static string ReplacePropertyValue(string json, string propertyName, string newValue) { var pattern = $"\"{propertyName}\"\\s*:\\s*\"[^\"]*\""; var replacement = $"\"{propertyName}\": \"{newValue}\""; return Regex.Replace(json, pattern, replacement); } } /// /// Source-generated logging definitions for Program /// internal static partial class ProgramLogging { private const int EventClass = 0; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Information, Message = "Publisher module command line interface.")] public static partial void PublisherModuleInit(this ILogger logger); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Information, Message = "Error {Error}: Missing connection string - continue...")] public static partial void MissingConnectionString(this ILogger logger, string error); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Information, Message = "Using '{DeviceId}'")] public static partial void UsingDeviceId(this ILogger logger, string deviceId); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Information, Message = "Using '{ModuleId}'")] public static partial void UsingModuleId(this ILogger logger, string moduleId); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Error, Message = "Exception")] public static partial void UnhandledException(this ILogger logger, Exception? exception); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Information, Message = "Create or retrieve connection string for {DeviceId} {ModuleId}...")] public static partial void ConnectionStringStart(this ILogger logger, string deviceId, string moduleId); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Information, Message = "Retrieved connection string for {DeviceId} {ModuleId}.")] public static partial void ConnectionStringRetrieved(this ILogger logger, string deviceId, string moduleId); [LoggerMessage(EventId = EventClass + 8, Level = LogLevel.Error, Message = "Failed to get connection string for {DeviceId} {ModuleId}...")] public static partial void ConnectionStringFailed(this ILogger logger, Exception exception, string deviceId, string moduleId); [LoggerMessage(EventId = EventClass + 9, Level = LogLevel.Information, Message = "Starting publisher module {DeviceId} {ModuleId}...")] public static partial void PublisherModuleStarting(this ILogger logger, string deviceId, string moduleId); [LoggerMessage(EventId = EventClass + 10, Level = LogLevel.Information, Message = "Publisher module {DeviceId} {ModuleId} exited.")] public static partial void PublisherModuleExited(this ILogger logger, string deviceId, string moduleId); [LoggerMessage(EventId = EventClass + 11, Level = LogLevel.Information, Message = "IoT Edge device {DeviceId} already exists.")] public static partial void IotEdgeDeviceExists(this ILogger logger, string deviceId); [LoggerMessage(EventId = EventClass + 12, Level = LogLevel.Information, Message = "Publisher {ModuleId} already exists...")] public static partial void PublisherExists(this ILogger logger, string moduleId); [LoggerMessage(EventId = EventClass + 13, Level = LogLevel.Information, Message = "(Re-)Starting server...")] public static partial void ServerRestarting(this ILogger logger); [LoggerMessage(EventId = EventClass + 14, Level = LogLevel.Information, Message = "Server (re-)started (Press S to kill).")] public static partial void ServerRestarted(this ILogger logger); [LoggerMessage(EventId = EventClass + 15, Level = LogLevel.Information, Message = "Reverse connect to client...")] public static partial void ReverseConnectToClient(this ILogger logger); [LoggerMessage(EventId = EventClass + 16, Level = LogLevel.Information, Message = "Stopping server...")] public static partial void StoppingServer(this ILogger logger); [LoggerMessage(EventId = EventClass + 17, Level = LogLevel.Information, Message = "Server stopped.")] public static partial void ServerStopped(this ILogger logger); [LoggerMessage(EventId = EventClass + 18, Level = LogLevel.Information, Message = "Waiting to restarting server (Press S to restart)...")] public static partial void WaitingToRestartServer(this ILogger logger); [LoggerMessage(EventId = EventClass + 19, Level = LogLevel.Error, Message = "Server ran into exception.")] public static partial void ServerException(this ILogger logger, Exception exception); [LoggerMessage(EventId = EventClass + 20, Level = LogLevel.Information, Message = "Server exited.")] public static partial void ServerExited(this ILogger logger); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/Properties/AssemblyInfo.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using System; [assembly: CLSCompliant(false)] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/cli/publishednodes.json ================================================ ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/src/Azure.IIoT.OpcUa.Publisher.Module.csproj ================================================  Exe net9.0 true true true enable true iotedge/opc-publisher mcr.microsoft.com/dotnet/aspnet:9.0-azurelinux3.0-distroless ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/src/Controllers/CertificatesController.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Controllers { using Azure.IIoT.OpcUa.Publisher.Module.Filters; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Asp.Versioning; using Furly; using Furly.Tunnel.Router; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Threading; using System.Threading.Tasks; /// /// /// This section lists the certificate APi provided by OPC Publisher providing /// all public and private key infrastructure (PKI) related API methods. /// /// /// The method name for all transports other than HTTP (which uses the shown /// HTTP methods and resource uris) is the name of the subsection header. /// To use the version specific method append "_V1" or "_V2" to the method /// name. /// /// [Version("_V1")] [Version("_V2")] [Version("")] [RouterExceptionFilter] [ControllerExceptionFilter] [ApiVersion("2")] [Route("v{version:apiVersion}/pki")] [ApiController] [Authorize] [Produces(ContentMimeType.Json, ContentMimeType.MsgPack)] [Consumes(ContentMimeType.Json, ContentMimeType.MsgPack)] public class CertificatesController : ControllerBase, IMethodController { /// /// Create controller with service /// /// public CertificatesController(IOpcUaCertificates certificates) { _certificates = certificates ?? throw new ArgumentNullException(nameof(certificates)); } /// /// ListCertificates /// /// /// Get the certificates in the specified certificate store /// /// The store to enumerate /// /// The list of certificates currently in the store. /// if store name is invalid. /// The operation was successful. /// The passed in information such as store name /// is invalid /// Nothing could be found. /// An internal error ocurred. [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpGet("{store}/certs")] public async Task> ListCertificatesAsync( string store, CancellationToken ct = default) { if (!Enum.TryParse(store, out var storeType)) { throw new ArgumentException("Invalid store name"); } return await _certificates.ListCertificatesAsync(storeType, false, ct).ConfigureAwait(false); } /// /// ListCertificateRevocationLists /// /// /// Get the certificates in the specified certificated store /// /// The store to enumerate /// /// The list of certificates revocation lists currently /// in the store. /// if store name is invalid. /// The operation was successful. /// The passed in information such as store name /// is invalid /// Nothing could be found. /// An internal error ocurred. [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpGet("{store}/crls")] public async Task> ListCertificateRevocationListsAsync( string store, CancellationToken ct = default) { if (!Enum.TryParse(store, out var storeType)) { throw new ArgumentException("Invalid store name"); } return await _certificates.ListCertificateRevocationListsAsync(storeType, ct).ConfigureAwait(false); } /// /// AddCertificate /// /// /// Add a certificate to the specified store. The certificate is provided /// as a pfx/pkcs12 optionally password protected blob. /// /// The store to add the certificate to /// The pfx encoded certificate. /// The optional password of the pfx /// /// /// is null. /// if store name is invalid. /// The operation was successful. /// The passed in information such as store name /// is invalid /// An internal error ocurred. [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPatch("{store}/certs")] public async Task AddCertificateAsync(string store, [FromBody][Required] byte[] pfxBlob, [FromQuery] string? password, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(pfxBlob); if (!Enum.TryParse(store, out var storeType)) { throw new ArgumentException("Invalid store name"); } await _certificates.AddCertificateAsync(storeType, pfxBlob, password, ct).ConfigureAwait(false); } /// /// AddCertificateRevocationList /// /// /// Add a certificate revocation list to the specified store. The certificate /// revocation list is provided as a der encoded blob. /// /// The store to add the certificate to /// The pfx encoded certificate. /// /// /// is null. /// if store name is invalid. /// The operation was successful. /// The passed in information is invalid /// An internal error ocurred. [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPatch("{store}/crls")] public async Task AddCertificateRevocationListAsync(string store, [FromBody][Required] byte[] crl, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(crl); if (!Enum.TryParse(store, out var storeType)) { throw new ArgumentException("Invalid store name"); } await _certificates.AddCertificateRevocationListAsync(storeType, crl, ct).ConfigureAwait(false); } /// /// AddCertificateChain /// /// /// Add a certificate chain to the specified store. The certificate is provided /// as a concatenated asn encoded set of certificates with the first the /// one to add, and the remainder the issuer chain. /// /// The certificate chain. /// /// /// is null. /// The operation was successful. /// The passed in information is invalid /// An internal error ocurred. [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("trusted/certs")] public async Task AddCertificateChainAsync([FromBody][Required] byte[] certificateChain, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(certificateChain); await _certificates.AddCertificateChainAsync(certificateChain, false, ct).ConfigureAwait(false); } /// /// ApproveRejectedCertificate /// /// /// Move a rejected certificate from the rejected folder to the trusted /// folder on the publisher. /// /// The thumbprint of the certificate to trust. /// /// The operation was successful. /// The passed in information is invalid /// An internal error ocurred. [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("rejected/certs/{thumbprint}/approve")] public async Task ApproveRejectedCertificateAsync(string thumbprint, CancellationToken ct = default) { await _certificates.ApproveRejectedCertificateAsync(thumbprint, ct).ConfigureAwait(false); } /// /// AddTrustedHttpsCertificateAsync /// /// /// Add a certificate chain to the trusted https store. The certificate is /// provided as a concatenated set of certificates with the first the /// one to add, and the remainder the issuer chain. /// /// The certificate chain. /// /// /// is null. /// The operation was successful. /// The passed in information is invalid /// An internal error ocurred. [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("https/certs")] public async Task AddTrustedHttpsCertificateAsync([FromBody][Required] byte[] certificateChain, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(certificateChain); await _certificates.AddCertificateChainAsync(certificateChain, true, ct).ConfigureAwait(false); } /// /// RemoveCertificate /// /// /// Remove a certificate with the provided thumbprint from the specified /// store. /// /// The store to add the certificate to /// The thumbprint of the certificate to delete. /// /// if store name is invalid. /// The operation was successful. /// The passed in information such store name is invalid /// Nothing could be found. /// An internal error ocurred. [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpDelete("{store}/certs/{thumbprint}")] public async Task RemoveCertificateAsync(string store, string thumbprint, CancellationToken ct = default) { if (!Enum.TryParse(store, out var storeType)) { throw new ArgumentException("Invalid store name"); } await _certificates.RemoveCertificateAsync(storeType, thumbprint, ct).ConfigureAwait(false); } /// /// RemoveCertificateRevocationList /// /// /// Remove a certificate revocation list from the specified store. /// /// The store to add the certificate to /// The crl to delete. /// /// if store name is invalid. /// The operation was successful. /// The passed in information such store name is invalid /// Nothing could be found. /// An internal error ocurred. [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpDelete("{store}/crls")] public async Task RemoveCertificateRevocationListAsync(string store, byte[] crl, CancellationToken ct = default) { if (!Enum.TryParse(store, out var storeType)) { throw new ArgumentException("Invalid store name"); } await _certificates.RemoveCertificateRevocationListAsync(storeType, crl, ct).ConfigureAwait(false); } /// /// RemoveAll /// /// /// Remove all certificates and revocation lists from the specified /// store. /// /// The store to add the certificate to /// /// if store name is invalid. /// The operation was successful. /// The passed in information such store name is invalid /// Nothing could be found. /// An internal error ocurred. [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpDelete("{store}")] public async Task RemoveAllAsync(string store, CancellationToken ct = default) { if (!Enum.TryParse(store, out var storeType)) { throw new ArgumentException("Invalid store name"); } await _certificates.CleanAsync(storeType, ct).ConfigureAwait(false); } private readonly IOpcUaCertificates _certificates; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/src/Controllers/ConfigurationController.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Controllers { using Azure.IIoT.OpcUa.Publisher.Module.Filters; using Azure.IIoT.OpcUa.Publisher.Models; using Asp.Versioning; using Furly; using Furly.Tunnel.Router; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Threading; using System.Threading.Tasks; /// /// /// This section contains the API to configure OPC Publisher. /// /// /// The method name for all transports other than HTTP (which uses the shown /// HTTP methods and resource uris) is the name of the subsection header. /// To use the version specific method append "_V1" or "_V2" to the method /// name. /// /// [Version("_V2")] [Version("_V1")] [Version("")] [RouterExceptionFilter] [ControllerExceptionFilter] [ApiVersion("2")] [Route("v{version:apiVersion}/configuration")] [ApiController] [Authorize] [Produces(ContentMimeType.Json, ContentMimeType.MsgPack)] [Consumes(ContentMimeType.Json, ContentMimeType.MsgPack)] public class ConfigurationController : ControllerBase, IMethodController { /// /// Create publisher methods controller /// /// public ConfigurationController(IPublishedNodesServices configServices) { _configServices = configServices; } /// /// PublishStart /// /// /// Start publishing values from a node on a server. The group field in the /// Connection Model can be used to specify a writer group identifier that will /// be used in the configuration entry that is created from it inside OPC Publisher. /// /// The server and node to publish. /// The results of the operation. /// /// is null. /// The operation was successful. /// The passed in information is invalid /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("start")] public async Task PublishStartAsync( [FromBody][Required] RequestEnvelope request) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _configServices.PublishStartAsync(request.Connection, request.Request).ConfigureAwait(false); } /// /// PublishStop /// /// /// Stop publishing values from a node on the specified server. The group field /// that was used in the Connection Model to start publishing must also be /// specified in this connection model. /// /// The node to stop publishing /// The result of the stop operation. /// /// is null. /// The operation was successful. /// The item could not be unpublished /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("stop")] public async Task PublishStopAsync( [FromBody][Required] RequestEnvelope request) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _configServices.PublishStopAsync(request.Connection, request.Request).ConfigureAwait(false); } /// /// PublishBulk /// /// /// Configure node values to publish and unpublish in bulk. The group field in /// the Connection Model can be used to specify a writer group identifier that /// will be used in the configuration entry that is created from it inside OPC /// Publisher. /// /// The nodes to publish or unpublish. /// The result for each operation. /// /// is null. /// The operation was successful. /// The item could not be unpublished /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("bulk")] public async Task PublishBulkAsync( [FromBody][Required] RequestEnvelope request) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _configServices.PublishBulkAsync(request.Connection, request.Request).ConfigureAwait(false); } /// /// PublishList /// /// /// Get all published nodes for a server endpoint. /// The group field that was used in the Connection Model to start /// publishing must also be specified in this connection model. /// /// /// The list of published nodes. /// /// is null. /// The items were found and returned. /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("list")] public async Task PublishListAsync( [FromBody][Required] RequestEnvelope request) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _configServices.PublishListAsync(request.Connection, request.Request).ConfigureAwait(false); } /// /// [PublishNodes](./directmethods.md#publishnodes_v1) /// /// /// PublishNodes enables a client to add a set of nodes to be published. /// Further information is provided in the OPC Publisher documentation. /// /// The request contains the nodes to publish. /// /// The result of the operation. /// /// is null. /// The operation was successful. /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("nodes")] public async Task PublishNodesAsync( [FromBody][Required] PublishedNodesEntryModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); await _configServices.PublishNodesAsync(request, ct).ConfigureAwait(false); return new PublishedNodesResponseModel(); } /// /// [UnpublishNodes](./directmethods.md#unpublishnodes_v1) /// /// /// UnpublishNodes method enables a client to remove nodes from a previously /// configured DataSetWriter. Further information is provided in the /// OPC Publisher documentation. /// /// The request payload specifying the nodes to /// unpublish. /// /// The result of the operation. /// /// is null. /// The operation was successful. /// The nodes could not be unpublished /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("nodes/unpublish")] public async Task UnpublishNodesAsync( [FromBody][Required] PublishedNodesEntryModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); await _configServices.UnpublishNodesAsync(request, ct).ConfigureAwait(false); return new PublishedNodesResponseModel(); } /// /// [UnpublishAllNodes](./directmethods.md#unpublishallnodes_v1) /// /// /// Unpublish all specified nodes or all nodes in the publisher /// configuration. Further information is provided in the /// OPC Publisher documentation. /// /// The request contains the parts of the /// configuration to remove. /// /// The result of the operation. /// The operation was successful. /// The nodes could not be unpublished /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("nodes/unpublish/all")] public async Task UnpublishAllNodesAsync( [FromBody] PublishedNodesEntryModel? request, CancellationToken ct = default) { await _configServices.UnpublishAllNodesAsync(request, ct).ConfigureAwait(false); return new PublishedNodesResponseModel(); } /// /// [AddOrUpdateEndpoints](./directmethods.md#addorupdateendpoints_v1) /// /// /// Add or update endpoint configuration and nodes on a server. /// Further information is provided in the OPC Publisher documentation. /// /// The parts of the configuration to add or /// update. /// /// The result of the operation. /// /// is null. /// The operation was successful. /// The endpoint was not found to add to /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPatch] public async Task AddOrUpdateEndpointsAsync( [FromBody][Required] IReadOnlyList request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); await _configServices.AddOrUpdateEndpointsAsync(request, ct).ConfigureAwait(false); return new PublishedNodesResponseModel(); } /// /// [GetConfiguredEndpoints](./directmethods.md#getconfiguredendpoints_v1) /// /// /// Get a list of nodes under a configured endpoint in the configuration. /// Further information is provided in the OPC Publisher documentation. /// configuration. /// /// Optional but can be spcified to include /// the nodes in the response. /// /// The result of the operation. /// The data was retrieved. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpGet] public async Task GetConfiguredEndpointsAsync( [FromQuery] GetConfiguredEndpointsRequestModel? request = null, CancellationToken ct = default) { var response = await _configServices.GetConfiguredEndpointsAsync( request?.IncludeNodes ?? false, ct).ConfigureAwait(false); return new GetConfiguredEndpointsResponseModel { Endpoints = response }; } /// /// [SetConfiguredEndpoints](./directmethods.md#setconfiguredendpoints_v1) /// /// /// Enables clients to update the entire published nodes configuration /// in one call. This includes clearing the existing configuration. /// Further information is provided in the OPC Publisher documentation. /// configuration. /// /// The new published nodes configuration /// /// The result of the operation. /// /// is null. /// The operation was successful. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPut] public async Task SetConfiguredEndpointsAsync( [FromBody][Required] SetConfiguredEndpointsRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); await _configServices.SetConfiguredEndpointsAsync(new List( request.Endpoints ?? []), ct).ConfigureAwait(false); } /// /// [GetConfiguredNodesOnEndpoint](./directmethods.md#getconfigurednodesonendpoint_v) /// /// /// Get the nodes of a published nodes entry object returned earlier from /// a call to GetConfiguredEndpoints. Further information is provided in /// the OPC Publisher documentation. /// /// The entry model from a call to GetConfiguredEndpoints /// for which to gather the nodes. /// /// The result of the operation. /// /// is null. /// The information was returned. /// The passed in information is invalid /// The entry was not found. /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("endpoints/list/nodes")] public async Task GetConfiguredNodesOnEndpointAsync( [FromBody][Required] PublishedNodesEntryModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); var response = await _configServices.GetConfiguredNodesOnEndpointAsync( request, ct).ConfigureAwait(false); return new GetConfiguredNodesOnEndpointResponseModel { OpcNodes = response }; } /// /// [GetDiagnosticInfo](./directmethods.md#getdiagnosticinfo_v1) /// /// /// Get the list of diagnostics info for all dataset writers in the OPC Publisher /// at the point the call is received. Further information is provided in the /// OPC Publisher documentation. /// /// /// The list of diagnostic infos for currently active writers. /// The operation was successful. /// Call not supported or functionality disabled. /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status405MethodNotAllowed)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("diagnostics")] public async Task> GetDiagnosticInfoAsync( CancellationToken ct = default) { return await _configServices.GetDiagnosticInfoAsync(ct).ConfigureAwait(false); } private readonly IPublishedNodesServices _configServices; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/src/Controllers/DiagnosticsController.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Controllers { using Azure.IIoT.OpcUa.Publisher.Module.Filters; using Azure.IIoT.OpcUa.Publisher.Models; using Asp.Versioning; using Furly; using Furly.Tunnel.Router; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; /// /// /// This section lists the diagnostics APi provided by OPC Publisher providing /// connection related diagnostics API methods. /// /// /// The method name for all transports other than HTTP (which uses the shown /// HTTP methods and resource uris) is the name of the subsection header. /// To use the version specific method append "_V1" or "_V2" to the method /// name. /// /// [Version("_V1")] [Version("_V2")] [Version("")] [RouterExceptionFilter] [ControllerExceptionFilter] [ApiVersion("2")] [Route("v{version:apiVersion}")] [ApiController] [Authorize] [Produces(ContentMimeType.Json, ContentMimeType.MsgPack)] [Consumes(ContentMimeType.Json, ContentMimeType.MsgPack)] public class DiagnosticsController : ControllerBase, IMethodController { /// /// Create controller with service /// /// public DiagnosticsController(IClientDiagnostics diagnostics) { _diagnostics = diagnostics ?? throw new ArgumentNullException(nameof(diagnostics)); } /// /// ResetAllConnections /// /// /// Can be used to reset all established connections causing a full /// reconnect and recreate of all subscriptions. /// /// /// The operation was successful. /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpGet("reset")] public async Task ResetAllConnectionsAsync(CancellationToken ct = default) { await _diagnostics.ResetAllConnectionsAsync(ct).ConfigureAwait(false); } /// /// GetActiveConnections /// /// /// Get all active connections the publisher is currently managing. /// /// /// The operation was successful. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpGet("connections")] public Task> GetActiveConnectionsAsync( CancellationToken ct = default) { ct.ThrowIfCancellationRequested(); return Task.FromResult(_diagnostics.ActiveConnections); } /// /// GetConnectionDiagnostics /// /// /// Get diagnostics for all active clients including server and /// client session diagnostics. /// /// /// The operation was successful. /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpGet("diagnostics/connections")] public IAsyncEnumerable GetConnectionDiagnosticsAsync( CancellationToken ct = default) { return _diagnostics.GetConnectionDiagnosticsAsync(ct); } /// /// GetChannelDiagnostics /// /// /// Get channel diagnostic information for all connections. /// /// /// The operation was successful. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpGet("diagnostics/channels")] public Task> GetChannelDiagnosticsAsync( CancellationToken ct = default) { ct.ThrowIfCancellationRequested(); return Task.FromResult(_diagnostics.ChannelDiagnostics); } /// /// WatchChannelDiagnostics /// /// /// Get channel diagnostic information for all connections. /// The first set of diagnostics are the diagnostics active for /// all connections, continue reading to get updates. /// /// /// The operation was successful. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpGet("diagnostics/channels/watch")] public IAsyncEnumerable WatchChannelDiagnosticsAsync( CancellationToken ct = default) { return _diagnostics.WatchChannelDiagnosticsAsync(ct); } private readonly IClientDiagnostics _diagnostics; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/src/Controllers/DiscoveryController.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Controllers { using Azure.IIoT.OpcUa.Publisher.Module.Filters; using Azure.IIoT.OpcUa.Publisher.Models; using Asp.Versioning; using Furly; using Furly.Tunnel.Router; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using System; using System.ComponentModel.DataAnnotations; using System.Threading; using System.Threading.Tasks; /// /// /// OPC UA and network discovery related API. /// /// /// The method name for all transports other than HTTP (which uses the shown /// HTTP methods and resource uris) is the name of the subsection header. /// To use the version specific method append "_V1" or "_V2" to the method /// /// [Version("_V1")] [Version("_V2")] [Version("")] [RouterExceptionFilter] [ControllerExceptionFilter] [ApiVersion("2")] [Route("v{version:apiVersion}/discovery")] [ApiController] [Authorize] [Produces(ContentMimeType.Json, ContentMimeType.MsgPack)] [Consumes(ContentMimeType.Json, ContentMimeType.MsgPack)] public class DiscoveryController : ControllerBase, IMethodController { /// /// Create controller with service /// /// /// public DiscoveryController(INetworkDiscovery discover, IServerDiscovery servers) { _discover = discover ?? throw new ArgumentNullException(nameof(discover)); _servers = servers ?? throw new ArgumentNullException(nameof(servers)); } /// /// FindServer /// /// /// Find servers matching the specified endpoint query spec. /// /// The endpoint query specifying the /// matching criteria for the discovered endpoints. /// /// The application information of a found server. /// Endpoints are only included in the response if they match /// the query specification. If no server is found the call /// returns 404 NotFound error. /// /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("findserver")] public async Task FindServerAsync( [FromBody][Required] ServerEndpointQueryModel endpoint, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(endpoint); return await _servers.FindServerAsync(endpoint, ct: ct).ConfigureAwait(false); } /// /// Register /// /// /// Start server registration. The results of the registration /// are published as events to the default event transport. /// /// Contains all information to perform /// the registration request including discovery url to use. /// /// Returns true if the registration request was /// processed. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("register")] public async Task RegisterAsync( [FromBody][Required] ServerRegistrationRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); await _discover.RegisterAsync(request, ct: ct).ConfigureAwait(false); return true; } /// /// Discover /// /// /// Start network discovery using the provided discovery request /// configuration. The discovery results are published to the /// configured default event transport. /// /// The discovery configuration to use /// during the discovery run. /// /// Returns true if the discovery operation started. /// /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost] public async Task DiscoverAsync( [FromBody][Required] DiscoveryRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); await _discover.DiscoverAsync(request, ct: ct).ConfigureAwait(false); return true; } /// /// Cancel /// /// /// Cancel a discovery run that is ongoing using the discovery /// request token specified in the discover operation. /// /// The information needed to cancel the /// discovery operation. /// /// Returns true if the cancellation request was processed. /// /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("cancel")] public async Task CancelAsync( [FromBody][Required] DiscoveryCancelRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); await _discover.CancelAsync(request, ct: ct).ConfigureAwait(false); return true; } private readonly INetworkDiscovery _discover; private readonly IServerDiscovery _servers; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/src/Controllers/FileSystemController.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Controllers { using Azure.IIoT.OpcUa.Publisher.Module.Filters; using Azure.IIoT.OpcUa.Publisher.Models; using Asp.Versioning; using Furly; using Furly.Extensions.Serializers; using Furly.Tunnel.Router; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Primitives; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Threading; using System.Threading.Tasks; /// /// /// This section lists the file transfer API provided by OPC Publisher providing /// access to file transfer services to move files in and out of a server /// using the File transfer specification. /// /// /// The method name for all transports other than HTTP (which uses the shown /// HTTP methods and resource uris) is the name of the subsection header. /// To use the version specific method append "_V1" or "_V2" to the method /// name. /// /// [Version("_V1")] [Version("_V2")] [Version("")] [RouterExceptionFilter] [ControllerExceptionFilter] [ApiVersion("2")] [Route("v{version:apiVersion}/filesystem")] [ApiController] [Authorize] [Produces(ContentMimeType.Json, ContentMimeType.MsgPack)] [Consumes(ContentMimeType.Json, ContentMimeType.MsgPack)] public class FileSystemController : ControllerBase, IMethodController { /// /// Create controller with service /// /// /// public FileSystemController(IFileSystemServices files, IJsonSerializer serializer) { _files = files ?? throw new ArgumentNullException(nameof(files)); _serializer = serializer ?? throw new ArgumentNullException(nameof(serializer)); } /// /// GetFileSystems /// /// /// Gets all file systems of the server. /// /// The connection information identifying the /// server to connect to perform the operation on. /// /// The directories. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("list")] public IAsyncEnumerable> GetFileSystemsAsync( [FromBody][Required] ConnectionModel connection, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(connection); return _files.GetFileSystemsAsync(connection, ct); } /// /// GetDirectories /// /// /// Gets all directories in a directory or file system /// /// The directory or filesystem object and connection /// information identifying the server to connect to perform the operation /// on. /// /// The directories. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("list/directories")] public async Task>> GetDirectoriesAsync( [FromBody][Required] RequestEnvelope request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _files.GetDirectoriesAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// GetFiles /// /// /// Get files in a directory or file system on a server. /// /// The directory or filesystem object and connection /// information identifying the server to connect to perform the operation /// on. /// /// The file information. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("list/files")] public async Task>> GetFilesAsync( [FromBody][Required] RequestEnvelope request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _files.GetFilesAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// GetParent /// /// /// Gets the parent directory or filesystem of a file or directory. /// /// The file or directory object and connection information /// identifying the server to connect to perform the operation on. /// /// The parent directory or filesystem. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("parent")] public async Task> GetParentAsync( [FromBody][Required] RequestEnvelope request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _files.GetParentAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// GetFileInfo /// /// /// Gets the file information for a file on the server. /// /// The file object and connection information /// identifying the server to connect to perform the operation on. /// /// The file information. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("info/file")] public async Task> GetFileInfoAsync( [FromBody][Required] RequestEnvelope request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _files.GetFileInfoAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// CreateFile /// /// /// Create a new file in a directory or file system on the server /// /// The file system or directory object to create the /// file in and the connection information identifying the server to /// connect to perform the operation on. /// The name of the file to create as child /// under the directory or filesystem provided /// /// The new directory. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("create/file/{name}")] public async Task> CreateFileAsync( [FromBody][Required] RequestEnvelope request, string name, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); ArgumentNullException.ThrowIfNullOrWhiteSpace(name); return await _files.CreateFileAsync(request.Connection, request.Request, name, ct).ConfigureAwait(false); } /// /// CreateDirectory /// /// /// Create a new directory in an existing file system or directory on the server. /// /// The file system or directory object to create the /// directory in and the connection information identifying the server to /// connect to perform the operation on. /// The name of the directory to create as child /// under the parent directory provided /// /// The new file. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("create/directory/{name}")] public async Task> CreateDirectoryAsync( [FromBody][Required] RequestEnvelope request, string name, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); ArgumentNullException.ThrowIfNullOrWhiteSpace(name); return await _files.CreateDirectoryAsync(request.Connection, request.Request, name, ct).ConfigureAwait(false); } /// /// DeleteFileSystemObject /// /// /// Delete a file or directory in an existing file system on the server. /// /// The file or directory object to delete and the /// connection information identifying the server to connect to perform /// the operation on. /// /// The new file. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("delete")] public async Task DeleteFileSystemObjectAsync( [FromBody][Required] RequestEnvelope request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _files.DeleteFileSystemObjectAsync(request.Connection, request.Request, ct: ct).ConfigureAwait(false); } /// /// DeleteFileOrDirectory /// /// /// Delete a file or directory in the specified directory or file system. /// /// The filesystem or directory object in which to /// delete the specified file or directory and the connection to use for /// the operation. /// The node id of the file or /// directory to delete /// /// The new file. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("delete/{fileOrDirectoryNodeId}")] public async Task DeleteFileOrDirectoryAsync( [FromBody][Required] RequestEnvelope request, string fileOrDirectoryNodeId, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); ArgumentNullException.ThrowIfNullOrWhiteSpace(fileOrDirectoryNodeId); return await _files.DeleteFileSystemObjectAsync(request.Connection, new FileSystemObjectModel { NodeId = fileOrDirectoryNodeId }, request.Request, ct).ConfigureAwait(false); } /// /// Download /// /// /// Download a file from the server /// /// The connection information identifying the server /// to connect to perform the operation on. This is passed as json serialized via /// the header "x-ms-connection" /// The file object to upload. This is passed as json /// serialized via the header "x-ms-target" /// /// /// /// is null. /// /// is null. /// The operation is not supported /// over the transport chosen /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpGet("download")] public async Task DownloadAsync( [FromHeader(Name = "x-ms-connection")][Required] string connectionJson, [FromHeader(Name = "x-ms-target")][Required] string fileObjectJson, CancellationToken ct = default) { ArgumentNullException.ThrowIfNullOrWhiteSpace(connectionJson); ArgumentNullException.ThrowIfNullOrWhiteSpace(fileObjectJson); var connection = _serializer.Deserialize(connectionJson); var fileObject = _serializer.Deserialize(fileObjectJson); ArgumentNullException.ThrowIfNull(connection); ArgumentNullException.ThrowIfNull(fileObject); if (HttpContext == null) { throw new NotSupportedException("Download not supported"); } var response = HttpContext.Response; await response.StartAsync(ct).ConfigureAwait(false); var result = await _files.CopyToAsync(connection, fileObject, response.Body, ct).ConfigureAwait(false); if (result?.StatusCode != 0) { HttpContext.Response.StatusCode = StatusCodes.Status500InternalServerError; HttpContext.Response.Headers.Append("errorInfo", new StringValues(_serializer.SerializeObjectToString(result))); } await response.CompleteAsync().ConfigureAwait(false); } /// /// Upload /// /// /// Upload a file to the server. /// /// The connection information identifying the server /// to connect to perform the operation on. This is passed as json serialized via /// the header "x-ms-connection" /// The file object to upload. This is passed as json /// serialized via the header "x-ms-target" /// The file write options to use passed as /// header "x-ms-mode" /// /// /// /// is null. /// /// is null. /// /// is null. /// The operation is not supported /// over the transport chosen /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("upload")] public async Task UploadAsync( [FromHeader(Name = "x-ms-connection")][Required] string connectionJson, [FromHeader(Name = "x-ms-target")][Required] string fileObjectJson, [FromHeader(Name = "x-ms-options")][Required] string writeOptionsJson, CancellationToken ct = default) { ArgumentNullException.ThrowIfNullOrWhiteSpace(connectionJson); ArgumentNullException.ThrowIfNullOrWhiteSpace(fileObjectJson); ArgumentNullException.ThrowIfNullOrWhiteSpace(writeOptionsJson); var connection = _serializer.Deserialize(connectionJson); var fileObject = _serializer.Deserialize(fileObjectJson); var options = _serializer.Deserialize(writeOptionsJson); ArgumentNullException.ThrowIfNull(connection); ArgumentNullException.ThrowIfNull(fileObject); if (HttpContext == null) { throw new NotSupportedException("Upload not supported"); } await using var _ = HttpContext.Request.Body.ConfigureAwait(false); var result = await _files.CopyFromAsync(connection, fileObject, HttpContext.Request.Body, options, ct).ConfigureAwait(false); if (result?.StatusCode != 0) { HttpContext.Response.StatusCode = StatusCodes.Status500InternalServerError; HttpContext.Response.Headers.Append("errorInfo", new StringValues(_serializer.SerializeObjectToString(result))); } } private readonly IFileSystemServices _files; private readonly IJsonSerializer _serializer; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/src/Controllers/GeneralController.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Controllers { using Azure.IIoT.OpcUa.Publisher.Module.Filters; using Azure.IIoT.OpcUa.Publisher.Models; using Asp.Versioning; using Furly; using Furly.Extensions.Serializers; using Furly.Tunnel.Router; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Threading; using System.Threading.Tasks; /// /// /// This section lists the general APi provided by OPC Publisher providing /// all connection, endpoint and address space related API methods. /// /// /// The method name for all transports other than HTTP (which uses the shown /// HTTP methods and resource uris) is the name of the subsection header. /// To use the version specific method append "_V1" or "_V2" to the method /// name. /// /// [Version("_V1")] [Version("_V2")] [Version("")] [RouterExceptionFilter] [ControllerExceptionFilter] [ApiVersion("2")] [Route("v{version:apiVersion}")] [ApiController] [Authorize] [Produces(ContentMimeType.Json, ContentMimeType.MsgPack)] [Consumes(ContentMimeType.Json, ContentMimeType.MsgPack)] public class GeneralController : ControllerBase, IMethodController { /// /// Create controller with service /// /// /// /// public GeneralController(IConnectionServices endpoints, ICertificateServices certificates, INodeServices nodes) { _certificates = certificates ?? throw new ArgumentNullException(nameof(certificates)); _nodes = nodes ?? throw new ArgumentNullException(nameof(nodes)); _endpoints = endpoints ?? throw new ArgumentNullException(nameof(endpoints)); } /// /// GetServerCapabilities /// /// /// Get the capabilities of the server. The server capabilities are exposed /// as a property of the server object and this method provides a convinient /// way to retrieve them. /// /// The request payload and connection information /// identifying the server to connect to perform the operation on. /// /// The server capabilities. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("capabilities")] public async Task GetServerCapabilitiesAsync( [FromBody][Required] RequestEnvelope request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); return await _nodes.GetServerCapabilitiesAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// Browse /// /// /// Browse a a node to discover its references. For more information consult /// /// the relevant section of the OPC UA reference specification. /// The operation might return a continuation token. The continuation token /// can be used in the BrowseNext method call to retrieve the remainder of /// references or additional continuation tokens. /// /// The request payload and connection information /// identifying the server to connect to perform the operation on. /// /// The references and optional continuation token /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("browse/first")] public async Task BrowseAsync( [FromBody][Required] RequestEnvelope request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _nodes.BrowseFirstAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// BrowseNext /// /// /// Browse next /// /// The request payload and connection information /// identifying the server to connect to perform the operation on. /// /// The references and optional continuation token /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("browse/next")] public async Task BrowseNextAsync( [FromBody][Required] RequestEnvelope request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _nodes.BrowseNextAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// BrowseStream (only HTTP transport) /// /// /// Recursively browse a node to discover its references and nodes. /// The results are returned as a stream of nodes and references. Consult /// /// the relevant section of the OPC UA reference specification for more /// information. /// /// The request payload and connection information /// identifying the server to connect to perform the operation on. /// /// The nodes and references as stream. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("browse")] public IAsyncEnumerable BrowseStreamAsync( [FromBody][Required] RequestEnvelope request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return _nodes.BrowseAsync(request.Connection, request.Request, ct); } /// /// BrowsePath /// /// /// Translate a start node and browse path into 0 or more target nodes. /// Allows programming aginst types in OPC UA. For more information consult /// /// the relevant section of the OPC UA reference specification. /// /// The request payload and connection information /// identifying the server to connect to perform the operation on. /// /// The target nodes found. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("browse/path")] public async Task BrowsePathAsync( [FromBody][Required] RequestEnvelope request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _nodes.BrowsePathAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// ValueRead /// /// /// Read the value of a variable node. This uses the service detailed in the /// /// relevant section of the OPC UA reference specification. /// /// The request payload and connection information /// identifying the server to connect to perform the operation on. /// /// The value read from the node variable or error information. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("read")] public async Task ValueReadAsync( [FromBody][Required] RequestEnvelope request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _nodes.ValueReadAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// ValueWrite /// /// /// Write the value of a variable node. This uses the service detailed in /// /// the relevant section of the OPC UA reference specification. /// /// The request payload and connection information /// identifying the server to connect to perform the operation on. /// /// The result of the write operation or error information. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("write")] public async Task ValueWriteAsync( [FromBody][Required] RequestEnvelope request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _nodes.ValueWriteAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// GetMetadata /// /// /// Get the type metadata for a any node. For data type nodes the /// response contains the data type metadata including fields. For /// method nodes the output and input arguments metadata is provided. /// For objects and object types the instance declaration is returned. /// /// The request payload and connection information /// identifying the server to connect to perform the operation on. /// /// The meta data of the node and optionally error information /// in case of failure. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("metadata")] public async Task GetMetadataAsync( [FromBody][Required] RequestEnvelope request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _nodes.GetMetadataAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// CompileQuery /// /// /// Compile a query string into a query spec that can be used when /// setting up event filters on monitored items that monitor events. /// /// The compilation request and connection /// information. /// /// The compilation response. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("query/compile")] public async Task CompileQueryAsync( [FromBody][Required] RequestEnvelope request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _nodes.CompileQueryAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// MethodMetadata /// /// /// Get the metadata for calling the method. This API is obsolete. /// Use the more powerful GetMetadata method instead. /// /// The request payload and connection information /// identifying the server to connect to perform the operation on. /// /// The method meta data and optionally error information /// in case of failure. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("call/$metadata")] public async Task MethodMetadataAsync( [FromBody][Required] RequestEnvelope request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _nodes.GetMethodMetadataAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// MethodCall /// /// /// Call a method on the OPC UA server endpoint with the specified input /// arguments and received the result in the form of the method output arguments. /// See /// the relevant section of the OPC UA reference specification for more /// information. /// /// The request payload and connection information /// identifying the server to connect to perform the operation on. /// /// The output argument values of the method call and optionally /// error information in case of failure. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("call")] public async Task MethodCallAsync( [FromBody][Required] RequestEnvelope request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _nodes.MethodCallAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// NodeRead /// /// /// Read any writeable attribute of a specified node on the server. See /// /// the relevant section of the OPC UA reference specification for more /// information. The attributes supported by the node are dependend /// on the node class of the node. /// /// The request payload and connection information /// identifying the server to connect to perform the operation on. /// /// The value of the attribute read and optionally /// error information in case of failure. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("read/attributes")] public async Task NodeReadAsync( [FromBody][Required] RequestEnvelope request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _nodes.ReadAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// NodeWrite /// /// /// Write any writeable attribute of a specified node on the server. See /// /// the relevant section of the OPC UA reference specification for more /// information. The attributes supported by the node are dependend /// on the node class of the node. /// /// The request payload and connection information /// identifying the server to connect to perform the operation on. /// /// The write operation result and optionally /// error information in case of failure. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("write/attributes")] public async Task NodeWriteAsync( [FromBody][Required] RequestEnvelope request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _nodes.WriteAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// HistoryRead /// /// /// Read the history using the respective OPC UA service call. See /// /// the relevant section of the OPC UA reference specification for more /// information. If continuation is returned the remaining results /// of the operation can be read using the HistoryReadNext method. /// /// The request payload and connection information /// identifying the server to connect to perform the operation on. /// /// /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("historyread/first")] public async Task> HistoryReadAsync( [FromBody][Required] RequestEnvelope> request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _nodes.HistoryReadAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// HistoryReadNext /// /// /// Read next history using the respective OPC UA service call. See /// /// the relevant section of the OPC UA reference specification for more /// information. /// /// The request payload and connection information /// identifying the server to connect to perform the operation on. /// /// The history read results. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("historyread/next")] public async Task> HistoryReadNextAsync( [FromBody][Required] RequestEnvelope request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _nodes.HistoryReadNextAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// HistoryUpdate /// /// /// Update history using the respective OPC UA service call. Consult the /// /// relevant section of the OPC UA reference specification for more /// information. /// /// The request payload and connection information /// identifying the server to connect to perform the operation on. /// /// The update result. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("historyupdate")] public async Task HistoryUpdateAsync( [FromBody][Required] RequestEnvelope> request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _nodes.HistoryUpdateAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// GetEndpointCertificate /// /// /// Get a server endpoint's certificate and certificate chain if /// available. /// /// The server endpoint to get the certificate /// for. /// /// The certificate of the server endpoint /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("certificate")] public async Task GetEndpointCertificateAsync( [FromBody][Required] EndpointModel endpoint, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(endpoint); return await _certificates.GetEndpointCertificateAsync(endpoint, ct).ConfigureAwait(false); } /// /// HistoryGetServerCapabilities /// /// /// Get the historian capabilities exposed as part of the OPC UA server /// server object. /// /// The request payload and connection information /// identifying the server to connect to perform the operation on. /// /// The historian capabilities of the server. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("history/capabilities")] public async Task HistoryGetServerCapabilitiesAsync( [FromBody][Required] RequestEnvelope request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); return await _nodes.HistoryGetServerCapabilitiesAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// HistoryGetConfiguration /// /// /// Get the historian configuration of a historizing node in the OPC UA server /// /// The request payload and connection information /// identifying the server to connect to perform the operation on. /// /// The node historian configuration. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("history/configuration")] public async Task HistoryGetConfigurationAsync( [FromBody][Required] RequestEnvelope request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _nodes.HistoryGetConfigurationAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// TestConnection /// /// /// Test connection to an opc ua server. The call will not establish /// any persistent connection but will just allow a client to test /// that the server is available. /// /// The request payload and connection information /// identifying the server to connect to perform the operation on. /// /// The test results. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("test")] public async Task TestConnectionAsync( [FromBody][Required] RequestEnvelope request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _endpoints.TestConnectionAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } private readonly ICertificateServices _certificates; private readonly IConnectionServices _endpoints; private readonly INodeServices _nodes; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/src/Controllers/HistoryController.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Controllers { using Azure.IIoT.OpcUa.Publisher.Module.Filters; using Azure.IIoT.OpcUa.Publisher.Models; using Asp.Versioning; using Furly; using Furly.Tunnel.Router; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Threading; using System.Threading.Tasks; /// /// /// This section lists all OPC UA HDA or Historian related API provided by /// OPC Publisher. /// /// /// The method name for all transports other than HTTP (which uses the shown /// HTTP methods and resource uris) is the name of the subsection header. /// To use the version specific method append "_V1" or "_V2" to the method /// name. /// /// [Version("_V1")] [Version("_V2")] [Version("")] [RouterExceptionFilter] [ControllerExceptionFilter] [ApiVersion("2")] [Route("v{version:apiVersion}/history")] [ApiController] [Authorize] [Produces(ContentMimeType.Json, ContentMimeType.MsgPack)] [Consumes(ContentMimeType.Json, ContentMimeType.MsgPack)] public class HistoryController : ControllerBase, IMethodController { /// /// Create controller with service /// /// public HistoryController(IHistoryServices historian) { _history = historian ?? throw new ArgumentNullException(nameof(historian)); } /// /// HistoryReplaceEvents /// /// /// Replace events in a timeseries in the historian of the OPC UA server. See /// /// the relevant section of the OPC UA reference specification and /// /// respective service documentation for more information. /// /// The events to replace with in the timeseries. /// /// The results of the operation. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("events/replace")] public async Task HistoryReplaceEventsAsync( [FromBody][Required] RequestEnvelope> request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _history.HistoryReplaceEventsAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// HistoryInsertEvents /// /// /// Insert event entries into a specified timeseries of the historian. See /// /// the relevant section of the OPC UA reference specification and /// /// respective service documentation for more information. /// /// The events to insert into the timeseries. /// /// The results of the operation. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("events/insert")] public async Task HistoryInsertEventsAsync( [FromBody][Required] RequestEnvelope> request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _history.HistoryInsertEventsAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// HistoryUpsertEvents /// /// /// Upsert events into a time series of the opc server historian. See /// /// the relevant section of the OPC UA reference specification and /// /// respective service documentation for more information. /// /// The events to upsert into the timeseries. /// /// The results of the operation. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("events/upsert")] public async Task HistoryUpsertEventsAsync( [FromBody][Required] RequestEnvelope> request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _history.HistoryUpsertEventsAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// HistoryDeleteEvents /// /// /// Delete event entries in a timeseries of the server historian. See /// /// the relevant section of the OPC UA reference specification and /// /// respective service documentation for more information. /// /// The events to delete in the timeseries. /// /// The results of the operation. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("events/delete")] public async Task HistoryDeleteEventsAsync( [FromBody][Required] RequestEnvelope> request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _history.HistoryDeleteEventsAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// HistoryDeleteValuesAtTimes /// /// /// Delete value change entries in a timeseries of the server historian. See /// /// the relevant section of the OPC UA reference specification and /// /// respective service documentation for more information. /// /// The values to delete in the timeseries. /// /// The results of the operation. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("values/delete/attimes")] public async Task HistoryDeleteValuesAtTimesAsync( [FromBody][Required] RequestEnvelope> request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _history.HistoryDeleteValuesAtTimesAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// HistoryDeleteModifiedValues /// /// /// Delete value change entries in a timeseries of the server historian. See /// /// the relevant section of the OPC UA reference specification and /// /// respective service documentation for more information. /// /// The values to delete in the timeseries. /// /// The results of the operation. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("values/delete/modified")] public async Task HistoryDeleteModifiedValuesAsync( [FromBody][Required] RequestEnvelope> request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _history.HistoryDeleteModifiedValuesAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// HistoryDeleteValues /// /// /// Delete value change entries in a timeseries of the server historian. See /// /// the relevant section of the OPC UA reference specification and /// /// respective service documentation for more information. /// /// The values to delete in the timeseries. /// /// The results of the operation. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("values/delete")] public async Task HistoryDeleteValuesAsync( [FromBody][Required] RequestEnvelope> request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _history.HistoryDeleteValuesAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// HistoryReplaceValues /// /// /// Replace value change entries in a timeseries of the server historian. See /// /// the relevant section of the OPC UA reference specification and /// /// respective service documentation for more information. /// /// The values to replace with in the timeseries. /// /// The results of the operation. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("values/replace")] public async Task HistoryReplaceValuesAsync( [FromBody][Required] RequestEnvelope> request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _history.HistoryReplaceValuesAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// HistoryInsertValues /// /// /// Insert value change entries in a timeseries of the server historian. See /// /// the relevant section of the OPC UA reference specification and /// /// respective service documentation for more information. /// /// The values to insert into the timeseries. /// /// The results of the operation. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("values/insert")] public async Task HistoryInsertValuesAsync( [FromBody][Required] RequestEnvelope> request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _history.HistoryInsertValuesAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// HistoryUpsertValues /// /// /// Upsert value change entries in a timeseries of the server historian. See /// /// the relevant section of the OPC UA reference specification and /// /// respective service documentation for more information. /// /// The values to upsert into the timeseries. /// /// The results of the operation. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("values/upsert")] public async Task HistoryUpsertValuesAsync( [FromBody][Required] RequestEnvelope> request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _history.HistoryUpsertValuesAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// HistoryReadEvents /// /// /// Read an event timeseries inside the OPC UA server historian. See /// /// the relevant section of the OPC UA reference specification and /// /// respective service documentation for more information. /// /// The events to read in the timeseries. /// /// The events read from the historian. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("events/read/first")] public async Task> HistoryReadEventsAsync( [FromBody][Required] RequestEnvelope> request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _history.HistoryReadEventsAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// HistoryReadEventsNext /// /// /// Continue reading an event timeseries inside the OPC UA server historian. /// See /// the relevant section of the OPC UA reference specification and /// /// respective service documentation for more information. /// /// The continuation from a previous read request. /// /// The events read from the historian. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("events/read/next")] public async Task> HistoryReadEventsNextAsync( [FromBody][Required] RequestEnvelope request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _history.HistoryReadEventsNextAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// HistoryReadValues /// /// /// Read a data change timeseries inside the OPC UA server historian. /// See /// the relevant section of the OPC UA reference specification and /// /// respective service documentation for more information. /// /// The values to read in the timeseries. /// /// The values read from the historian. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("values/read/first")] public async Task> HistoryReadValuesAsync( [FromBody][Required] RequestEnvelope> request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _history.HistoryReadValuesAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// HistoryReadValuesAtTimes /// /// /// Read parts of a timeseries inside the OPC UA server historian. /// See /// the relevant section of the OPC UA reference specification and /// /// respective service documentation for more information. /// /// The values to read in the timeseries. /// /// The values read from the historian. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("values/read/first/attimes")] public async Task> HistoryReadValuesAtTimesAsync( [FromBody][Required] RequestEnvelope> request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _history.HistoryReadValuesAtTimesAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// HistoryReadProcessedValues /// /// /// Read processed timeseries data inside the OPC UA server historian. /// See /// the relevant section of the OPC UA reference specification and /// /// respective service documentation for more information. /// /// The values to read in the timeseries. /// /// The processed values read from the historian. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("values/read/first/processed")] public async Task> HistoryReadProcessedValuesAsync( [FromBody][Required] RequestEnvelope> request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _history.HistoryReadProcessedValuesAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// HistoryReadModifiedValues /// /// /// Read modified changes in a timeseries inside the OPC UA server historian. /// See /// the relevant section of the OPC UA reference specification and /// /// respective service documentation for more information. /// /// The values to read in the timeseries. /// /// The modified values read from the historian. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("values/read/first/modified")] public async Task> HistoryReadModifiedValuesAsync( [FromBody][Required] RequestEnvelope> request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _history.HistoryReadModifiedValuesAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// HistoryReadValuesNext /// /// /// Continue reading a timeseries inside the OPC UA server historian. /// See /// the relevant section of the OPC UA reference specification and /// /// respective service documentation for more information. /// /// The continuation token from a previous read operation. /// /// The values read from the historian. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("values/read/next")] public async Task> HistoryReadValuesNextAsync( [FromBody][Required] RequestEnvelope request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return await _history.HistoryReadValuesNextAsync(request.Connection, request.Request, ct).ConfigureAwait(false); } /// /// HistoryStreamValues (only HTTP transport) /// /// /// Read an entire timeseries from an OPC UA server historian as stream. /// See /// the relevant section of the OPC UA reference specification and /// /// respective service documentation for more information. /// /// The values to read in the timeseries. /// /// The values read from the historian as stream. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("values/read")] public IAsyncEnumerable HistoryStreamValuesAsync( [FromBody][Required] RequestEnvelope> request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return _history.HistoryStreamValuesAsync(request.Connection, request.Request, ct); } /// /// HistoryStreamModifiedValues (only HTTP transport) /// /// /// Read an entire modified series from an OPC UA server historian as stream. /// See /// the relevant section of the OPC UA reference specification and /// /// respective service documentation for more information. /// /// The values to read in the timeseries. /// /// The modified values read from the historian as stream. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("values/read/modified")] public IAsyncEnumerable HistoryStreamModifiedValuesAsync( [FromBody][Required] RequestEnvelope> request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return _history.HistoryStreamModifiedValuesAsync(request.Connection, request.Request, ct); } /// /// HistoryStreamValuesAtTimes (only HTTP transport) /// /// /// Read specific timeseries data from an OPC UA server historian as stream. /// See /// the relevant section of the OPC UA reference specification and /// /// respective service documentation for more information. /// /// The values to read in the timeseries. /// /// The values read from the historian as stream. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("values/read/attimes")] public IAsyncEnumerable HistoryStreamValuesAtTimesAsync( [FromBody][Required] RequestEnvelope> request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return _history.HistoryStreamValuesAtTimesAsync(request.Connection, request.Request, ct); } /// /// HistoryStreamProcessedValues (only HTTP transport) /// /// /// Read processed timeseries data from an OPC UA server historian as stream. /// See /// the relevant section of the OPC UA reference specification and /// /// respective service documentation for more information. /// /// The values to read in the timeseries. /// /// The processed values read from the historian as stream. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("values/read/processed")] public IAsyncEnumerable HistoryStreamProcessedValuesAsync( [FromBody][Required] RequestEnvelope> request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return _history.HistoryStreamProcessedValuesAsync(request.Connection, request.Request, ct); } /// /// HistoryStreamEvents (only HTTP transport) /// /// /// Read an entire event timeseries from an OPC UA server historian as stream. /// See /// the relevant section of the OPC UA reference specification and /// /// respective service documentation for more information. /// /// The events to read in the timeseries. /// /// The events read from the historian as stream. /// /// is null. /// The operation was successful or the response payload /// contains relevant error information. /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("events/read")] public IAsyncEnumerable HistoryStreamEventsAsync( [FromBody][Required] RequestEnvelope> request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Connection); ArgumentNullException.ThrowIfNull(request.Request); return _history.HistoryStreamEventsAsync(request.Connection, request.Request, ct); } private readonly IHistoryServices _history; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/src/Controllers/LegacyController.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Controllers { using Azure.IIoT.OpcUa.Publisher.Module.Filters; using Furly.Tunnel.Router; using System; using System.Threading.Tasks; /// /// Legacy controller /// [Version("_V2")] [Version("_V1")] [Version("")] [ControllerExceptionFilter] public class LegacyController : IMethodController { /// /// Handler for GetInfo direct method /// /// #pragma warning disable CA1822 // Mark members as static public Task GetInfoAsync() #pragma warning restore CA1822 // Mark members as static { return Task.FromException(new NotSupportedException( "GetInfo not supported")); } /// /// Handler for GetDiagnosticLog direct method - not supported /// /// #pragma warning disable CA1822 // Mark members as static public Task GetDiagnosticLogAsync() #pragma warning restore CA1822 // Mark members as static { return Task.FromException(new NotSupportedException( "GetDiagnosticLog not supported")); } /// /// Handler for GetDiagnosticStartupLog direct method - not supported /// /// #pragma warning disable CA1822 // Mark members as static public Task GetDiagnosticStartupLogAsync() #pragma warning restore CA1822 // Mark members as static { return Task.FromException(new NotSupportedException( "GetDiagnosticStartupLog not supported")); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/src/Controllers/PublisherController.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Controllers { using Azure.IIoT.OpcUa.Publisher.Module.Filters; using Furly.Tunnel.Router; using System; using System.Threading.Tasks; /// /// Publisher controller /// [Version("_V2")] [Version("")] [RouterExceptionFilter] public class PublisherController : IMethodController { /// /// Support restarting the module /// /// /// /// public PublisherController(IProcessControl process, IApiKeyProvider apikey, ISslCertProvider certificate) { _apikey = apikey; _certificate = certificate; _process = process; } /// /// Get ApiKey to use when calling the HTTP API. /// /// public Task GetApiKeyAsync() { return Task.FromResult(_apikey.ApiKey); } /// /// Get server certificate as PEM. /// /// public Task GetServerCertificateAsync() { return Task.FromResult(_certificate.Certificate?.ExportCertificatePem()); } /// /// Shutdown /// /// /// /// public async Task ShutdownAsync(bool failFast = false) { if (!_process.Shutdown(failFast)) { // Should be gone now await Task.Delay(TimeSpan.FromSeconds(10)).ConfigureAwait(false); throw new NotSupportedException("Failed to invoke shutdown"); } } /// /// Legacy shutdown /// /// public Task ExitApplicationAsync() { return ShutdownAsync(); } private readonly IApiKeyProvider _apikey; private readonly ISslCertProvider _certificate; private readonly IProcessControl _process; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/src/Controllers/WriterController.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Controllers { using Azure.IIoT.OpcUa.Publisher.Module.Filters; using Azure.IIoT.OpcUa.Publisher.Models; using Asp.Versioning; using Furly; using Furly.Extensions.AspNetCore.OpenApi; using Furly.Extensions.Http; using Furly.Extensions.Serializers; using Furly.Tunnel.Router; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; /// /// /// This section contains the API to configure data set writers and writer /// groups inside OPC Publisher. It supersedes the configuration API. /// Applications should use one or the other, but not both at the same /// time. /// /// /// The method name for all transports other than HTTP (which uses the shown /// HTTP methods and resource uris) is the name of the subsection header. /// To use the version specific method append "_V1" or "_V2" to the method /// name. /// /// [Version("_V2")] [Version("_V1")] [Version("")] [RouterExceptionFilter] [ControllerExceptionFilter] [ApiVersion("2")] [Route("v{version:apiVersion}/writer")] [ApiController] [Authorize] [Produces(ContentMimeType.Json, ContentMimeType.MsgPack)] [Consumes(ContentMimeType.Json, ContentMimeType.MsgPack)] public class WriterController : ControllerBase, IMethodController { /// /// Create publisher methods controller /// /// /// /// /// public WriterController(IPublishedNodesServices publisher, IConfigurationServices configuration, IAssetConfiguration assets, IJsonSerializer serializer) { _publisher = publisher; _configuration = configuration; _assets = assets; _serializer = serializer; } /// /// CreateOrUpdateDataSetWriterEntry /// /// /// Create a published nodes entry for a specific writer group and dataset writer. /// The entry must specify a unique writer group and dataset writer id. A null value /// is treated as empty string. If the entry is found it is replaced, if it is not /// found, it is created. If more than one entry is found with the same writer group /// and writer id an error is returned. The writer entry provided must include at /// least one node which will be the initial set. All nodes must specify a unique /// dataSetFieldId. A null value is treated as empty string. Publishing intervals /// at node level are also not supported and generate an error. Publishing /// intervals must be configured at the data set writer level. /// /// The entry to create for the writer /// /// /// is null. /// The item was created /// The passed in information is invalid /// A unique item could not be found to update. [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status403Forbidden)] [HttpPut] public async Task CreateOrUpdateDataSetWriterEntryAsync( [FromBody][Required] PublishedNodesEntryModel dataSetWriterEntry, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(dataSetWriterEntry); await _publisher.CreateOrUpdateDataSetWriterEntryAsync( dataSetWriterEntry, ct).ConfigureAwait(false); } /// /// GetDataSetWriterEntry /// /// /// Get the published nodes entry for a specific writer group and dataset writer. /// Dedicated errors are returned if no, or no unique entry could be found. The /// entry does not contain the nodes. Nodes can be retrieved using the GetNodes /// API. /// /// The writer group name of the entry /// The data set writer identifer of the entry /// /// The entry selected without nodes /// /// is null. /// /// is null. /// The item was found /// The passed in information is invalid /// There is no unique item present. /// The item was not found [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status403Forbidden)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] [HttpGet("{dataSetWriterGroup}/{dataSetWriterId}")] public async Task GetDataSetWriterEntryAsync( string dataSetWriterGroup, string dataSetWriterId, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(dataSetWriterGroup); ArgumentNullException.ThrowIfNull(dataSetWriterId); return await _publisher.GetDataSetWriterEntryAsync( dataSetWriterGroup, dataSetWriterId, ct).ConfigureAwait(false); } /// /// AddOrUpdateNodes /// /// /// Add Nodes to a dedicated data set writer in a writer group. Each node must have /// a unique DataSetFieldId. If the field already exists, the node is updated. /// If a node does not have a dataset field id an error is returned. Publishing /// intervals at node level are also not supported and generate an error. Publishing /// intervals must be configured at the data set writer level. /// /// The writer group name of the entry /// The data set writer identifer of the entry /// Nodes to add or update /// Field after which to insert the nodes. If /// not specified, nodes are added at the end of the entry /// /// /// is null. /// /// is null. /// /// is null. /// The items were added /// The passed in information is invalid /// A unique entry could not be found to add to. /// The entry was not found [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status403Forbidden)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] [HttpPost("{dataSetWriterGroup}/{dataSetWriterId}/add")] public async Task AddOrUpdateNodesAsync(string dataSetWriterGroup, string dataSetWriterId, [FromBody][Required] IReadOnlyList opcNodes, [FromQuery] string? insertAfterFieldId = null, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(dataSetWriterGroup); ArgumentNullException.ThrowIfNull(dataSetWriterId); ArgumentNullException.ThrowIfNull(opcNodes); await _publisher.AddOrUpdateNodesAsync(dataSetWriterGroup, dataSetWriterId, opcNodes, insertAfterFieldId, ct).ConfigureAwait(false); } /// /// AddOrUpdateNode /// /// /// Add a node to a dedicated data set writer in a writer group. A node must have /// a unique DataSetFieldId. If the field already exists, the node is updated. /// If a node does not have a dataset field id an error is returned. Publishing /// intervals at node level are also not supported and generate an error. Publishing /// intervals must be configured at the data set writer level. /// /// The writer group name of the entry /// The data set writer identifer of the entry /// Node to add or update /// Field after which to insert the nodes. If /// not specified, nodes are added at the end of the entry /// /// /// is null. /// /// is null. /// /// is null. /// The item was added /// The passed in information is invalid /// A unique item could not be found to update. /// An entry was not found to add the node to [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status403Forbidden)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] [HttpPut("{dataSetWriterGroup}/{dataSetWriterId}")] public async Task AddOrUpdateNodeAsync(string dataSetWriterGroup, string dataSetWriterId, [FromBody][Required] OpcNodeModel opcNode, [FromQuery] string? insertAfterFieldId = null, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(dataSetWriterGroup); ArgumentNullException.ThrowIfNull(dataSetWriterId); ArgumentNullException.ThrowIfNull(opcNode); await _publisher.AddOrUpdateNodesAsync(dataSetWriterGroup, dataSetWriterId, new[] { opcNode }, insertAfterFieldId, ct).ConfigureAwait(false); } /// /// RemoveNodes /// /// /// Remove Nodes that match the provided data set field ids from a data set writer /// in a writer group. If one of the fields is not found, no error is returned, /// however, if all fields are not found an error is returned. /// /// The writer group name of the entry /// The data set writer identifer of the entry /// The identifiers of the fields to remove /// /// /// is null. /// /// is null. /// /// is null. /// Some or all items were removed /// The passed in information is invalid /// A unique item could not be found to remove from. /// The entry or all items to remove were not found [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status403Forbidden)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] [HttpPost("{dataSetWriterGroup}/{dataSetWriterId}/remove")] public async Task RemoveNodesAsync(string dataSetWriterGroup, string dataSetWriterId, [FromBody][Required] IReadOnlyList dataSetFieldIds, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(dataSetWriterGroup); ArgumentNullException.ThrowIfNull(dataSetWriterId); ArgumentNullException.ThrowIfNull(dataSetFieldIds); await _publisher.RemoveNodesAsync(dataSetWriterGroup, dataSetWriterId, dataSetFieldIds, ct).ConfigureAwait(false); } /// /// RemoveNode /// /// /// Remove a node with the specified data set field id from a data set writer /// in a writer group. If the field is not found, an error is returned. /// /// The writer group name of the entry /// The data set writer identifer of the entry /// Identifier of the field to remove /// /// /// is null. /// /// is null. /// /// is null. /// The item was removed /// The passed in information is invalid /// A unique item could not be found to remove from. /// The entry or item to remove was not found [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status403Forbidden)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] [HttpDelete("{dataSetWriterGroup}/{dataSetWriterId}/{dataSetFieldId}")] public async Task RemoveNodeAsync(string dataSetWriterGroup, string dataSetWriterId, string dataSetFieldId, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(dataSetWriterGroup); ArgumentNullException.ThrowIfNull(dataSetWriterId); ArgumentNullException.ThrowIfNull(dataSetFieldId); await _publisher.RemoveNodesAsync(dataSetWriterGroup, dataSetWriterId, new[] { dataSetFieldId }, ct).ConfigureAwait(false); } /// /// GetNode /// /// /// Get a node from a dataset in a writer group. /// Dedicated errors are returned if no, or no unique entry could be found, or /// the node does not exist. /// /// The writer group name of the entry /// The data set writer identifer of the entry /// The data set field id of the node to return /// /// The node inside the dataset /// /// is null. /// /// is null. /// /// is null. /// The item was retrieved /// The passed in information is invalid /// A unique item could not be found to get a node from. /// The entry or item was not found [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status403Forbidden)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] [HttpGet("{dataSetWriterGroup}/{dataSetWriterId}/{dataSetFieldId}")] public async Task GetNodeAsync( string dataSetWriterGroup, string dataSetWriterId, string dataSetFieldId, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(dataSetWriterGroup); ArgumentNullException.ThrowIfNull(dataSetWriterId); ArgumentNullException.ThrowIfNull(dataSetFieldId); return await _publisher.GetNodeAsync( dataSetWriterGroup, dataSetWriterId, dataSetFieldId, ct).ConfigureAwait(false); } /// /// GetNodes /// /// /// Get Nodes from a data set writer in a writer group. The nodes can optionally /// be offset from a previous last node identified by the dataSetFieldId and /// pageanated by the pageSize. If the dataSetFieldId is not found, an empty list /// is returned. If the dataSetFieldId is not specified, the first page is returned. /// /// The writer group name of the entry /// The data set writer identifer of the entry /// the field id after which to start the page. /// If not specified, nodes from the beginning are returned. /// Number of nodes to return /// /// List of nodes or none if none were found /// /// is null. /// /// is null. /// The items were found /// The passed in information is invalid /// A unique item could not be found to get nodes from. /// The entry was not found [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status403Forbidden)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] [HttpGet("{dataSetWriterGroup}/{dataSetWriterId}/nodes")] [AutoRestExtension(NextPageLinkName = "lastDataSetFieldId")] public async Task> GetNodesAsync( string dataSetWriterGroup, string dataSetWriterId, [FromQuery] string? lastDataSetFieldId = null, [FromQuery] int? pageSize = null, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(dataSetWriterGroup); ArgumentNullException.ThrowIfNull(dataSetWriterId); if (Request != null) { if (Request.Headers.TryGetValue(HttpHeader.ContinuationToken, out var value)) { lastDataSetFieldId = value.FirstOrDefault(); } if (Request.Headers.TryGetValue(HttpHeader.MaxItemCount, out value)) { pageSize = int.Parse(value.FirstOrDefault()!, CultureInfo.InvariantCulture); } } return await _publisher.GetNodesAsync(dataSetWriterGroup, dataSetWriterId, lastDataSetFieldId, pageSize, ct).ConfigureAwait(false); } /// /// RemoveDataSetWriterEntry /// /// /// Remove the published nodes entry for a specific data set writer in a writer /// group. Dedicated errors are returned if no, or no unique entry could be found. /// /// The writer group name of the entry /// The data set writer identifer of the entry /// Force delete all writers even if more than one were /// found. Does not error when none were found. /// /// /// is null. /// /// is null. /// The entry was removed /// The passed in information is invalid /// A unique item could not be found to remove. /// The entry to remove was not found [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status403Forbidden)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] [HttpDelete("{dataSetWriterGroup}/{dataSetWriterId}")] public async Task RemoveDataSetWriterEntryAsync(string dataSetWriterGroup, string dataSetWriterId, [FromQuery] bool force = false, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(dataSetWriterGroup); ArgumentNullException.ThrowIfNull(dataSetWriterId); await _publisher.RemoveDataSetWriterEntryAsync(dataSetWriterGroup, dataSetWriterId, force, ct).ConfigureAwait(false); } /// /// ExpandWriter /// /// /// Expands the provided nodes in the entry to a series of published node entries. /// The provided entry is used template. The entry is expanded using expansion /// configuration provided. Expanded entries are returned one by one with error /// information if any. The configuration is not updated but the resulting entries /// can be modified and later saved in the configuration using the configuration /// API. The server must be online and accessible /// for the expansion to work. /// /// The entry to expand and the node expansion configuration /// to use. If no configuration is provided a default configuration is used which /// and no error entries are returned. /// /// /// is null. /// The item was created /// The passed in information is invalid /// A unique item could not be found to update. /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status403Forbidden)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("expand")] public IAsyncEnumerable> ExpandWriterAsync( [FromBody][Required] PublishedNodesEntryRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Entry); var expansion = request.Request ?? new PublishedNodeExpansionModel { DiscardErrors = true }; return _configuration.ExpandAsync(request.Entry, expansion, ct); } /// /// ExpandAndCreateOrUpdateDataSetWriterEntries /// /// /// Create a series of published nodes entries using the provided entry as template. /// The entry is expanded using expansion configuration provided. Expanded entries /// are returned one by one with error information if any. The configuration is also /// saved in the local configuration store. The server must be online and accessible /// for the expansion to work. /// /// The entry to create for the writer and node expansion /// configuration to use /// /// /// is null. /// The item was created /// The passed in information is invalid /// A unique item could not be found to update. /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status403Forbidden)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost] public IAsyncEnumerable> ExpandAndCreateOrUpdateDataSetWriterEntriesAsync( [FromBody][Required] PublishedNodesEntryRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Entry); var expansion = request.Request ?? new PublishedNodeExpansionModel { DiscardErrors = false }; return _configuration.CreateOrUpdateAsync(request.Entry, expansion, ct); } /// /// CreateOrUpdateAsset (With binary configuration) /// /// /// Creates an asset from the entry in the request and the configuration provided /// in the Web of Things Asset configuration byte buffer. The entry must contain a /// data set name which will be used as the asset name. The writer can stay empty. /// It will be set to the asset id on successful return. The server must support the /// WoT profile per . /// The asset will be created and the configuration updated to reference it. A /// wait time can be provided as optional query parameter to wait until the server /// has settled after uploading the configuration. /// /// The contains the entry and WoT file to configure the /// server to expose the asset. /// /// /// is null. /// The asset was created /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status403Forbidden)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("assets/create")] [Ignore] public async Task> CreateOrUpdateAsset2Async( [FromBody][Required] PublishedNodeCreateAssetRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); return await _assets.CreateOrUpdateAssetAsync(request, ct).ConfigureAwait(false); } /// /// CreateOrUpdateAsset /// /// /// Creates an asset from the entry in the request and the configuration provided /// in the Web of Things Asset json configuration property. The entry must contain /// a data set name which will be used as the asset name. The writer can stay empty. /// It will be set to the asset id on successful return. The server must support the /// WoT profile per . /// The asset will be created and the configuration updated to reference it. A /// wait time can be provided as optional query parameter to wait until the server /// has settled after uploading the configuration. /// /// The contains the entry and WoT file to configure the /// server to expose the asset. /// /// /// is null. /// The asset was created /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status403Forbidden)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("assets")] public async Task> CreateOrUpdateAssetAsync( [FromBody][Required] PublishedNodeCreateAssetRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); return await _assets.CreateOrUpdateAssetAsync(new PublishedNodeCreateAssetRequestModel { Entry = request.Entry, WaitTime = request.WaitTime, Header = request.Header, Configuration = _serializer.SerializeObjectToMemory(request.Configuration).ToArray() }, ct).ConfigureAwait(false); } /// /// GetAllAssets /// /// /// Get a list of entries representing the assets in the server. This will not touch /// the configuration, it will obtain the list from the server. If the server does not /// support the /// result will be empty. /// /// The entry to use to list the assets with the optional /// header information used when invoking services on the server. /// /// /// is null. /// Successfully completed the listing /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status403Forbidden)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("assets/list")] public IAsyncEnumerable> GetAllAssetsAsync( [FromBody][Required] PublishedNodesEntryRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Entry); return _assets.GetAllAssetsAsync(request.Entry, request.Request, ct); } /// /// DeleteAsset /// /// /// Delete the asset referenced by the entry in the request. The entry must contain /// the asset id to delete. The asset id is the data set writer id. The entry must /// also contain the writer group id or deletion of the asset in the configuration /// will fail before the asset is deleted. The server must support WoT connectivity /// profile per . /// First the entry in the configuration will be deleted and then the asset on the /// server. If deletion of the asset in the configuration fails it will not be /// deleted in the server. An optional request option force can be used to force /// the deletion of the asset in the server regardless of the failure to delete the /// entry in the configuration. /// /// Request that contains the entry of the asset that /// should be deleted. /// /// /// is null. /// The asset was deleted successfully /// The passed in information is invalid /// The operation timed out. /// An unexpected error occurred [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status403Forbidden)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status408RequestTimeout)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] [HttpPost("assets/delete")] public async Task DeleteAssetAsync( [FromBody][Required] PublishedNodeDeleteAssetRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(request); return await _assets.DeleteAssetAsync(request, ct).ConfigureAwait(false); } private readonly IPublishedNodesServices _publisher; private readonly IConfigurationServices _configuration; private readonly IAssetConfiguration _assets; private readonly IJsonSerializer _serializer; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/src/Filters/ControllerExceptionFilterAttribute.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Filters { using Azure.IIoT.OpcUa.Exceptions; using Furly.Exceptions; using Furly.Tunnel.Exceptions; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Diagnostics.ExceptionSummarization; using System; using System.IO; using System.Net; using System.Net.Sockets; using System.Security; using System.Threading.Tasks; /// /// Detect all the unhandled exceptions returned by the API controllers /// and decorate the response accordingly, managing the HTTP status code /// and preparing a JSON response with useful error details. /// When including the stack trace, split the text in multiple lines /// for an easier parsing. /// @see https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters /// public sealed class ControllerExceptionFilterAttribute : ExceptionFilterAttribute { /// public override void OnException(ExceptionContext context) { ArgumentNullException.ThrowIfNull(context); if (context.Exception == null) { base.OnException(context); return; } if (context.Exception is AggregateException ae) { var root = ae.GetBaseException(); if (root is AggregateException && ae.InnerExceptions.Count > 0) { context.Exception = ae.InnerExceptions[0]; } else { context.Exception = root; } } var summarizer = context.HttpContext?.RequestServices? .GetService(); switch (context.Exception) { case ResourceNotFoundException: context.Result = GetResponse(HttpStatusCode.NotFound, context.Exception, summarizer); break; case ResourceInvalidStateException: context.Result = GetResponse(HttpStatusCode.Forbidden, context.Exception, summarizer); break; case ResourceConflictException: context.Result = GetResponse(HttpStatusCode.Conflict, context.Exception, summarizer); break; case UnauthorizedAccessException: case SecurityException: context.Result = GetResponse(HttpStatusCode.Unauthorized, context.Exception, summarizer); break; case MethodCallStatusException mcs: context.Result = new ObjectResult(mcs.Details.ToProblemDetails()); break; case SerializerException: case MethodCallException: case BadRequestException: case ArgumentException: context.Result = GetResponse(HttpStatusCode.BadRequest, context.Exception, summarizer); break; case NotSupportedException: context.Result = GetResponse(HttpStatusCode.MethodNotAllowed, context.Exception, summarizer); break; case NotImplementedException: context.Result = GetResponse(HttpStatusCode.NotImplemented, context.Exception, summarizer); break; case TimeoutException: context.Result = GetResponse(HttpStatusCode.RequestTimeout, context.Exception, summarizer); break; case SocketException: case IOException: context.Result = GetResponse(HttpStatusCode.BadGateway, context.Exception, summarizer); break; // // The following will most certainly be retried by our // service client implementations and thus dependent // services: // // InternalServerError // BadGateway // ServiceUnavailable // GatewayTimeout // PreconditionFailed // TemporaryRedirect // TooManyRequests // // As such, if you want to terminate make sure exception // is caught ahead of here and returns a status other than // one of the above. // case ServerBusyException: context.Result = GetResponse(HttpStatusCode.TooManyRequests, context.Exception, summarizer); break; case ResourceOutOfDateException: context.Result = GetResponse(HttpStatusCode.PreconditionFailed, context.Exception, summarizer); break; case ExternalDependencyException: context.Result = GetResponse(HttpStatusCode.ServiceUnavailable, context.Exception, summarizer); break; default: context.Result = GetResponse(HttpStatusCode.InternalServerError, context.Exception, summarizer); break; } } /// public override Task OnExceptionAsync(ExceptionContext context) { try { OnException(context); return Task.CompletedTask; } catch (Exception) { return base.OnExceptionAsync(context); } } /// /// Create result /// /// /// /// /// private static ObjectResult GetResponse(HttpStatusCode code, Exception exception, IExceptionSummarizer? summarizer) { if (summarizer != null) { var ex = exception.AsMethodCallStatusException((int)code, summarizer); return new ObjectResult(ex.Details.ToProblemDetails()) { StatusCode = (int)code }; } return new ObjectResult(exception.Message) { StatusCode = (int)code }; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/src/Filters/RouterExceptionFilterAttribute.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Filters { using Azure.IIoT.OpcUa.Exceptions; using Furly.Exceptions; using Furly.Tunnel.Router; using System; using System.IO; using System.Net; using System.Net.Sockets; using System.Security; using System.Threading.Tasks; /// /// Convert all the exceptions returned by the module controllers to a /// status code. /// public sealed class RouterExceptionFilterAttribute : ExceptionFilterAttribute { /// public override Exception Filter(Exception exception, out int status) { switch (exception) { case AggregateException ae: var root = ae.GetBaseException(); if (root is not AggregateException ae2) { return Filter(root, out status); } status = (int)HttpStatusCode.InternalServerError; Exception? result = null; foreach (var ex in ae2.InnerExceptions) { result = Filter(ex, out status); if (status != (int)HttpStatusCode.InternalServerError) { break; } } return result ?? new InvalidOperationException(); case ResourceNotFoundException: status = (int)HttpStatusCode.NotFound; break; case ResourceInvalidStateException: status = (int)HttpStatusCode.Forbidden; break; case ResourceConflictException: status = (int)HttpStatusCode.Conflict; break; case SecurityException: case UnauthorizedAccessException: status = (int)HttpStatusCode.Unauthorized; break; case MethodCallStatusException mcse: status = mcse.Details.Status ?? (int)HttpStatusCode.InternalServerError; break; case SerializerException: case MethodCallException: case BadRequestException: case ArgumentException: status = (int)HttpStatusCode.BadRequest; break; case NotImplementedException: status = (int)HttpStatusCode.NotImplemented; break; case NotSupportedException: status = (int)HttpStatusCode.MethodNotAllowed; break; case TimeoutException: status = (int)HttpStatusCode.RequestTimeout; break; case SocketException: case IOException: status = (int)HttpStatusCode.BadGateway; break; case MessageSizeLimitException: status = (int)HttpStatusCode.RequestEntityTooLarge; break; case TaskCanceledException: case OperationCanceledException: status = (int)HttpStatusCode.Gone; return new OperationCanceledException( "Request was canceled by the client or after timeout."); // // The following will most certainly be retried by our // service client implementations and thus dependent // services: // // InternalServerError // GatewayTimeout // PreconditionFailed // TemporaryRedirect // TooManyRequests // // As such, if you want to terminate make sure exception // is caught ahead of here and returns a status other than // one of the above. // case ServerBusyException: status = (int)HttpStatusCode.TooManyRequests; break; case ExternalDependencyException: status = (int)HttpStatusCode.ServiceUnavailable; break; case ResourceOutOfDateException: status = (int)HttpStatusCode.PreconditionFailed; break; default: status = (int)HttpStatusCode.InternalServerError; break; } return exception; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/src/Program.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module { using Autofac.Extensions.DependencyInjection; using Azure.IIoT.OpcUa.Publisher.Module.Runtime; using Furly.Extensions.Hosting; using k8s; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; using System; using System.Diagnostics; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; /// /// Module /// public static class Program { /// /// Log logo /// /// private static void LogLogo(string userString) { Console.WriteLine($@" ██████╗ ██████╗ ██████╗ ██████╗ ██╗ ██╗██████╗ ██╗ ██╗███████╗██╗ ██╗███████╗██████╗ ██╔═══██╗██╔══██╗██╔════╝ ██╔══██╗██║ ██║██╔══██╗██║ ██║██╔════╝██║ ██║██╔════╝██╔══██╗ ██║ ██║██████╔╝██║ ██████╔╝██║ ██║██████╔╝██║ ██║███████╗███████║█████╗ ██████╔╝ ██║ ██║██╔═══╝ ██║ ██╔═══╝ ██║ ██║██╔══██╗██║ ██║╚════██║██╔══██║██╔══╝ ██╔══██╗ ╚██████╔╝██║ ╚██████╗ ██║ ╚██████╔╝██████╔╝███████╗██║███████║██║ ██║███████╗██║ ██║ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝╚══════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ {PublisherConfig.Version,97} {userString,97} "); } /// /// Main entry point /// /// public static void Main(string[] args) { #if DEBUG if (args.Any(a => a.Contains("wfd", StringComparison.InvariantCultureIgnoreCase) || a.Contains("waitfordebugger", StringComparison.InvariantCultureIgnoreCase)) || KubernetesClientConfiguration.IsInCluster()) { Console.WriteLine("Waiting for debugger being attached..."); while (!Debugger.IsAttached) { Thread.Sleep(1000); } Console.WriteLine("Debugger attached."); Debugger.Break(); } #endif using var cts = new CancellationTokenSource(); RunAsync(args, cts.Token).GetAwaiter().GetResult(); } /// /// Async main entry point /// /// /// /// public static async Task RunAsync(string[] args, CancellationToken ct) { var userString = string.Empty; if (PublisherConfig.IsContainer) { var currentDir = Environment.CurrentDirectory; var currentUser = Environment.UserName; if (!IsWriteable(currentDir)) { currentDir = "/home" + (string.IsNullOrEmpty(currentUser) ? currentDir : $"/{currentUser}"); // Rootless containers have read-only filesystem except /home Environment.CurrentDirectory = currentDir; } userString = $"Running as [{currentUser}] in {currentDir}"; } LogLogo(userString); await CreateHostBuilder(args).RunAsync(ct).ConfigureAwait(false); } /// /// Create host builder /// /// /// public static IHostBuilder CreateHostBuilder(string[] args) { return Host.CreateDefaultBuilder() .UseServiceProviderFactory(new AutofacServiceProviderFactory()) .ConfigureHostConfiguration(builder => builder .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", true) .AddEnvironmentVariables() .AddFromDotEnvFile() .AddSecrets() .AddConnectorAdditionalConfiguration() .AddInMemoryCollection(new CommandLine(args))) .ConfigureWebHostDefaults(builder => builder //.UseUrls("http://*:9702", "https://*:9703") .UseStartup() .UseKestrel(o => o.AddServerHeader = false)) ; } /// /// Tests whether the path is writeable /// /// /// private static bool IsWriteable(string path) { try { string tempFilePath = Path.Combine(path, Path.GetRandomFileName()); using (FileStream fs = File.Create(tempFilePath)) { // File created successfully, directory is writable } // Delete the temporary file File.Delete(tempFilePath); return true; } catch { return false; } } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/src/Properties/AssemblyInfo.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Azure.IIoT.OpcUa.Publisher.Module.Tests")] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/src/Runtime/CommandLine.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Runtime { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Stack.Runtime; using Furly.Azure.IoT.Edge; using Furly.Extensions.Messaging; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Mono.Options; using Newtonsoft.Json; using Opc.Ua; using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; /// /// Class that represents a dictionary with all command line arguments from /// the current and legacy versions of the OPC Publisher. They are represented /// via configuration interfaces that is injected into the publisher container. /// public sealed class CommandLine : Dictionary { /// /// Creates a new instance of the cli options based on existing configuration values. /// public CommandLine() { _logger = new CommandLineLogger(); } internal enum HelpType { None, CommandLine, EnvVars, MessageProfiles } /// /// Parse arguments and set values in the environment the way the new configuration expects it. /// /// The specified command line arguments. /// public CommandLine(string[] args, CommandLineLogger? logger = null) { _logger = logger ?? new CommandLineLogger(); var help = HelpType.None; var unsupportedOptions = new List(); var legacyOptions = new List(); // Key for the Legacy (before 2.9) compatibility mode. Controlled the content type value const string LegacyCompatibility = "LegacyCompatibility"; // command line options var options = new Mono.Options.OptionSet { "", "General", "-------", "", // show help { "h|help", "Show help and exit.\n", _ => help = HelpType.CommandLine }, { "help-env", "Show environment variables and exit.\n", _ => help = HelpType.EnvVars}, { "help-mm", "Show message modes and exit.\n", _ => help = HelpType.MessageProfiles}, // Publisher configuration options { $"f|pf=|publishfile=|{PublisherConfig.PublishedNodesFileKey}=", "The name of the file containing the configuration of the nodes to be published as well as the information to connect to the OPC UA server sources.\nThis file is also used to persist changes made through the control plane, e.g., through IoT Hub device method calls.\nWhen no file is specified a default `publishednodes.json` file is created in the working directory.\nDefault: `publishednodes.json`\n", s => this[PublisherConfig.PublishedNodesFileKey] = s }, { $"cf|createifnotexist:|{PublisherConfig.CreatePublishFileIfNotExistKey}:", "Permit publisher to create the the specified publish file if it does not exist. The new file will be created under the access rights of the publisher module.\nThe default file 'publishednodes.json' is always created when no file name was provided on the command line and this option is ignored.\nIf a file was specified but does not exist and should not be created the module exits.\nDefault: `false`\n", (bool? b) => this[PublisherConfig.CreatePublishFileIfNotExistKey] = b?.ToString() ?? "True" }, { $"pol|usepolling:|{PublisherConfig.UseFileChangePollingKey}:", "Poll for file changes instead of using a file system watcher.\nUse this setting when the underlying file system does not support file system notifications such as in some docker container setups.\nDefault: `false`\n", (bool? b) => this[PublisherConfig.UseFileChangePollingKey] = b?.ToString() ?? "True" }, { $"fe|forceencryptedcredentials:|{PublisherConfig.ForceCredentialEncryptionKey}:", "If set to true the publisher will never write plain text credentials into the published nodes configuration file.\nIf a credential cannot be written to the file using the IoT Edge workload API crypto provider the publisher will exit with an error.\nDefault: `false` (write secrets as plain text into the configuration file which should be properly ACL'ed)\n", (bool? b) => this[PublisherConfig.ForceCredentialEncryptionKey] = b?.ToString() ?? "True" }, { $"id|publisherid=|{PublisherConfig.PublisherIdKey}=", "Sets the publisher id of the publisher.\nDefault: `not set` which results in the IoT edge identity being used \n", s => this[PublisherConfig.PublisherIdKey] = s}, { $"s|site=|{PublisherConfig.SiteIdKey}=", "Sets the site name of the publisher module.\nDefault: `not set` \n", s => this[PublisherConfig.SiteIdKey] = s}, { $"pi|initfile:|{Configuration.FileSystem.InitFilePathKey}:", $"A file from which to read initialization instructions.\nUse this option to have OPC Publisher run a set of method calls found in this file.\nThe file must be formatted using a subset of the .http/.rest file format without support for indentation, scripting or environment variables.\nDefault: `not set` (disabled). If only a file name is specified, it is loaded from the path of the file specifed using `-f` (`{PublisherConfig.PublishedNodesFileKey}`). If just the argument is provided without a value the default is `publishednodes.init`.\n", pi => this[Configuration.FileSystem.InitFilePathKey] = pi ?? " " }, { $"il|initlog=|{Configuration.FileSystem.InitLogFileKey}=", $"A file into which the results of the initialization instructions are written.\nOnly valid if `--pi` option (`{Configuration.FileSystem.InitFilePathKey}`) is specified.\nDefault: If a init file is set using `--pi` (`{Configuration.FileSystem.InitFilePathKey}`), it is appended with the `.log` extension. If just a file name is used, the file is created in the same folder as the init file configured using the `--pi` command line option (`{Configuration.FileSystem.InitFilePathKey}`).\n", il => this[Configuration.FileSystem.InitLogFileKey] = il }, { $"rs|runtimestatereporting:|{PublisherConfig.EnableRuntimeStateReportingKey}:", "Enable that when publisher starts or restarts it reports its runtime state using a restart message.\nDefault: `false` (disabled)\n", (bool? b) => this[PublisherConfig.EnableRuntimeStateReportingKey] = b?.ToString() ?? "True"}, { $"api-key=|{PublisherConfig.ApiKeyOverrideKey}=", "Sets the api key that must be used to authenticate calls on the publisher REST endpoint.\nDefault: `not set` (Key will be generated if not available) \n", s => this[PublisherConfig.ApiKeyOverrideKey] = s}, { $"doa|disableopenapi:|{PublisherConfig.DisableOpenApiEndpointKey}:", "Disable the OPC Publisher Open API endpoint exposed by the built-in HTTP server.\nDefault: `false` (enabled).\n", (bool? b) => this[PublisherConfig.DisableOpenApiEndpointKey] = b?.ToString() ?? "True" }, "", "Messaging configuration", "-----------------------", "", { $"c|strict:|{PublisherConfig.UseStandardsCompliantEncodingKey}:", "Use strict OPC UA standard compliance. It is recommended to run the publisher in compliant mode for best interoperability.\nBe aware that explicitly specifying other command line options can result in non-comnpliance despite this option being set.\nDefault: `false` for backwards compatibility (2.5.x - 2.8.x)\n", (bool? b) => this[PublisherConfig.UseStandardsCompliantEncodingKey] = b?.ToString() ?? "True" }, { $"nf|namespaceformat=|{PublisherConfig.DefaultNamespaceFormatKey}=", $"The format to use when serializing node ids and qualified names containing a namespace uri into a string.\nAllowed values:\n `{string.Join("`\n `", Enum.GetNames())}`\nDefault: `{nameof(NamespaceFormat.Expanded)}` if `-c` is specified, otherwise `{nameof(NamespaceFormat.Uri)}` for backwards compatibility.\n", (NamespaceFormat m) => this[PublisherConfig.DefaultNamespaceFormatKey] = m.ToString() }, { $"mm|messagingmode=|{PublisherConfig.MessagingModeKey}=", $"The messaging mode for messages\nAllowed values:\n `{string.Join("`\n `", Enum.GetNames())}`\nDefault: `{nameof(MessagingMode.PubSub)}` if `-c` is specified, otherwise `{nameof(MessagingMode.Samples)}` for backwards compatibility.\n", (MessagingMode m) => this[PublisherConfig.MessagingModeKey] = m.ToString() }, { $"ode|optimizeddatasetencoding:|{PublisherConfig.WriteValueWhenDataSetHasSingleEntryKey}:", "When a data set has a single entry the encoder will write only the value of a data set entry and omit the key.\nThis is not compliant with OPC UA Part 14.\nDefault: `false`.\n", (bool? b) => this[PublisherConfig.WriteValueWhenDataSetHasSingleEntryKey] = b?.ToString() ?? "True" }, // TODO: Add ability to specify networkmessage mask // TODO: Add ability to specify dataset message mask // TODO: Add ability to specify dataset field message mask // TODO: Allow override of content type // TODO: Allow overriding schema { $"me|messageencoding=|{PublisherConfig.MessageEncodingKey}=", $"The message encoding for messages\nAllowed values:\n `{string.Join("`\n `", Enum.GetNames())}`\nDefault: `{nameof(MessageEncoding.Json)}`.\n", (MessageEncoding m) => this[PublisherConfig.MessageEncodingKey] = m.ToString() }, { $"fm|fullfeaturedmessage=|{PublisherConfig.FullFeaturedMessageKey}=", "The full featured mode for messages (all fields filled in) for backwards compatibilty. \nDefault: `false` for legacy compatibility.\n", (string b) => this[PublisherConfig.FullFeaturedMessageKey] = b, /* hidden = */ true }, { $"bi|batchtriggerinterval=|{PublisherConfig.BatchTriggerIntervalKey}=", $"The network message publishing interval in milliseconds. Determines the publishing period at which point messages are emitted.\nWhen `--bs` (`{PublisherConfig.BatchSizeKey}`) is 1 and `--bi` is set to 0 batching is disabled.\nDefault: `10000` (10 seconds).\nAlso can be set using `BatchTriggerInterval` environment variable in the form of a duration string in the form `[d.]hh:mm:ss[.fffffff]`.\n", (uint k) => this[PublisherConfig.BatchTriggerIntervalKey] = TimeSpan.FromMilliseconds(k).ToString() }, { "si|iothubsendinterval=", "The network message publishing interval in seconds for backwards compatibilty. \nDefault: `10` seconds.\n", (string k) => this[PublisherConfig.BatchTriggerIntervalKey] = TimeSpan.FromSeconds(int.Parse(k, CultureInfo.CurrentCulture)).ToString(), /* hidden = */ true }, { $"bs|batchsize=|{PublisherConfig.BatchSizeKey}=", $"The number of incoming OPC UA subscription notifications to collect until sending a network messages. When `--bs` (`{PublisherConfig.BatchSizeKey}`) is set to 1 and `--bi` (`{PublisherConfig.BatchTriggerIntervalKey}`) is 0 batching is disabled and messages are sent as soon as notifications arrive.\nDefault: `50`.\n", (uint i) => this[PublisherConfig.BatchSizeKey] = i.ToString(CultureInfo.CurrentCulture) }, { $"rdb|removedupsinbatch:|{PublisherConfig.RemoveDuplicatesFromBatchKey}:", "Use this option to remove values with the same node id from batch messages in legacy `Samples` mode. Sends only the latest value as per the value's source timestamp.\nOnly applies to `Samples` mode, otherwise this setting is ignored.\nDefault: `false` (keep all duplicate values).\n", (bool? b) => this[PublisherConfig.RemoveDuplicatesFromBatchKey] = b?.ToString() ?? "True" }, { $"ms|maxmessagesize=|iothubmessagesize=|{PublisherConfig.IoTHubMaxMessageSizeKey}=", "The maximum size of the messages to emit. In case the encoder cannot encode a message because the size would be exceeded, the message is dropped. Otherwise the encoder will aim to chunk messages if possible. \nDefault: `256k` in case of IoT Hub messages, `0` otherwise.\n", (uint i) => this[PublisherConfig.IoTHubMaxMessageSizeKey] = i.ToString(CultureInfo.CurrentCulture) }, { $"qos|{PublisherConfig.DefaultQualityOfServiceKey}=", $"The default quality of service to use for data set messages.\nThis does not apply to metadata messages which are always sent with `AtLeastOnce` semantics.\nAllowed values:\n `{string.Join("`\n `", Enum.GetNames())}`\nDefault: `{nameof(QoS.AtLeastOnce)}`.\n", (QoS q) => this[PublisherConfig.DefaultQualityOfServiceKey] = q.ToString() }, { $"ttl|{PublisherConfig.DefaultMessageTimeToLiveKey}=", "The default time to live for all network message published in milliseconds if the transport supports it.\nThis does not apply to metadata messages which are always sent with a ttl of the metadata update interval or infinite ttl.\nDefault: `not set` (infinite).\n", (uint k) => this[PublisherConfig.DefaultMessageTimeToLiveKey] = TimeSpan.FromMilliseconds(k).ToString() }, { $"retain:|{PublisherConfig.DefaultMessageRetentionKey}:", "Whether by default to send messages with retain flag to a broker if the transport supports it.\nThis does not apply to metadata messages which are always sent as retained messages.\nDefault: `false'.\n", (bool? b) => this[PublisherConfig.DefaultMessageRetentionKey] = b?.ToString() ?? "True" }, // TODO: Add ConfiguredMessageSize { $"mts|messagetimestamp=|{PublisherConfig.MessageTimestampKey}=", $"The value to set as as the timestamp property of messages during encoding (if the encoding supports writing message timestamps).\nAllowed values:\n `{string.Join("`\n `", Enum.GetNames())}`\nDefault: `{nameof(MessageTimestamp.CurrentTimeUtc)}` to use the time when the message was created in OPC Publisher.\n", (MessageTimestamp m) => this[PublisherConfig.MessageTimestampKey] = m.ToString() }, { $"npd|maxnodesperdataset=|{PublisherConfig.MaxNodesPerDataSetKey}=", "Maximum number of nodes within a Subscription. When there are more nodes configured for a data set writer, they will be added to new subscriptions. This also affects metadata message size. \nDefault: `1000`.\n", (uint i) => this[PublisherConfig.MaxNodesPerDataSetKey] = i.ToString(CultureInfo.CurrentCulture) }, { $"kfc|keyframecount=|{PublisherConfig.DefaultKeyFrameCountKey}=", "The default number of delta messages to send until a key frame message is sent. If 0, no key frame messages are sent, if 1, every message will be a key frame. \nDefault: `0`.\n", (uint i) => this[PublisherConfig.DefaultKeyFrameCountKey] = i.ToString(CultureInfo.CurrentCulture) }, { $"ka|sendkeepalives:|{PublisherConfig.EnableDataSetKeepAlivesKey}:", "Enables sending keep alive messages triggered by writer subscription's keep alive notifications. This setting can be used to enable the messaging profile's support for keep alive messages.\nIf the chosen messaging profile does not support keep alive messages this setting is ignored.\nDefault: `false` (to save bandwidth).\n", (bool? b) => this[PublisherConfig.EnableDataSetKeepAlivesKey] = b?.ToString() ?? "True" }, { $"kaf|keepalivesaskeyframe:|{PublisherConfig.SendDataSetKeepAlivesAsKeyFrameKey}:", "When the sending of keep alive messages is enabled determines whether the empty keep alive message will be promoted to a key frame messages\nDefault: `false`.\n", (bool? b) => this[PublisherConfig.SendDataSetKeepAlivesAsKeyFrameKey] = b?.ToString() ?? "True" }, { $"msi|metadatasendinterval=|{PublisherConfig.DefaultMetaDataUpdateTimeKey}=", $"Default value in milliseconds for the metadata send interval which determines in which interval metadata is sent.\nEven when disabled, metadata is still sent when the metadata version changes unless `--mm=*Samples` (`{PublisherConfig.MessagingModeKey})=*Samples`) is set in which case this setting is ignored. Only valid for network message encodings. \nDefault: `0` which means periodic sending of metadata is disabled.\n", (uint i) => this[PublisherConfig.DefaultMetaDataUpdateTimeKey] = TimeSpan.FromMilliseconds(i).ToString() }, { $"dm|disablemetadata:|{PublisherConfig.DisableDataSetMetaDataKey}:", $"Disables sending any metadata when metadata version changes. This setting can be used to also override the messaging profile's default support for metadata sending.\nIt is recommended to disable sending metadata when too many nodes are part of a data set as this can slow down start up time.\nDefault: `False` if the messaging profile selected supports sending metadata and `--strict` (`{PublisherConfig.UseStandardsCompliantEncodingKey}`) is set but not '--dct' (`{PublisherConfig.DisableComplexTypeSystemKey}`), `True` otherwise.\n", (bool? b) => this[PublisherConfig.DisableDataSetMetaDataKey] = b?.ToString() ?? "True" }, { $"lc|legacycompatibility=|{LegacyCompatibility}=", "Run the publisher in legacy (2.5.x) compatibility mode.\nDefault: `false` (disabled).\n", b => this[LegacyCompatibility] = b, /* hidden = */ true }, { $"amt|asyncmetadataloadtimeout=|{PublisherConfig.AsyncMetaDataLoadTimeoutKey}=", $"The default duration in seconds a publish request should wait until the meta data is loaded.\nLoaded metadata guarantees a metadata message is sent before the first message is sent but loading of metadata takes time during subscription setup. Set to `0` to block until metadata is loaded.\nOnly used if meta data is supported and enabled.\nDefault: `{PublisherConfig.AsyncMetaDataLoadTimeoutDefaultMillis}` milliseconds.\n", (uint i) => this[PublisherConfig.AsyncMetaDataLoadTimeoutKey] = TimeSpan.FromMilliseconds(i).ToString() }, { $"ps|publishschemas:|{PublisherConfig.PublishMessageSchemaKey}:", "Publish the Avro or Json message schemas to schema registry or subtopics.\nAutomatically enables complex type system and metadata support.\nOnly has effect if the messaging profile supports publishing schemas.\nDefault: `True` if the message encoding requires schemas (for example Avro) otherwise `False`.\n", (bool? b) => this[PublisherConfig.PublishMessageSchemaKey] = b?.ToString() ?? "True" }, { $"asj|preferavro:|{PublisherConfig.PreferAvroOverJsonSchemaKey}:", "Publish Avro schema even for Json encoded messages. Automatically enables publishing schemas as if `--ps` was set.\nDefault: `false`.\n", (bool? b) => this[PublisherConfig.PreferAvroOverJsonSchemaKey] = b?.ToString() ?? "True" }, { $"daf|disableavrofiles:|{Configuration.AvroWriter.DisableKey}:", "Disable writing avro files and instead dump messages and schema as zip files using the filesystem transport.\nDefault: `false`.\n", (bool? b) => this[Configuration.AvroWriter.DisableKey] = b?.ToString() ?? "True" }, { $"om|maxsendqueuesize=|{PublisherConfig.MaxNetworkMessageSendQueueSizeKey}=", $"The maximum number of messages to buffer on the send path before messages are dropped.\nDefault: `{PublisherConfig.MaxNetworkMessageSendQueueSizeDefault}`\n", (uint i) => this[PublisherConfig.MaxNetworkMessageSendQueueSizeKey] = i.ToString(CultureInfo.InvariantCulture) }, { "maxoutgressmessages|MaxOutgressMessages=", "Deprecated - do not use", (string i) => this[PublisherConfig.MaxNetworkMessageSendQueueSizeKey] = i, /* hidden = */ true }, { $"wgp|writergrouppartitions=|{PublisherConfig.DefaultWriterGroupPartitionCountKey}=", "The number of partitions to split the writer group into. Each partition represents a data flow to the transport sink. The partition is selected by topic hash.\nDefault: `0` (partitioning is disabled)\n", (ushort i) => this[PublisherConfig.DefaultWriterGroupPartitionCountKey] = i.ToString(CultureInfo.InvariantCulture) }, { $"t|dmt=|defaultmessagetransport=|{PublisherConfig.DefaultTransportKey}=", $"The desired transport to use to publish network messages with.\nRequires the transport to be properly configured (see transport settings).\nAllowed values:\n `{string.Join("`\n `", Enum.GetNames())}`\nDefault: `{nameof(WriterGroupTransport.IoTHub)}` or the first configured transport of the allowed value list.\n", (WriterGroupTransport p) => this[PublisherConfig.DefaultTransportKey] = p.ToString() }, "", "Transport settings", "------------------", "", { $"b|mqc=|mqttclientconnectionstring=|{Configuration.MqttBroker.MqttClientConnectionStringKey}=", $"An mqtt connection string to use. Use this option to connect OPC Publisher to a MQTT Broker endpoint.\nTo connect to an MQTT broker use the format 'HostName=;Port=[;Username=;Password=;Protocol=<'v5'|'v311'>]'. To publish via MQTT by default specify `-t={nameof(WriterGroupTransport.Mqtt)}`.\nDefault: `not set`.\n", mqc => this[Configuration.MqttBroker.MqttClientConnectionStringKey] = mqc }, { $"e|ec=|edgehubconnectionstring=|dc=|deviceconnectionstring=|{Configuration.IoTEdge.EdgeHubConnectionString}=", $"A edge hub or iot hub connection string to use if you run OPC Publisher outside of IoT Edge. The connection string can be obtained from the IoT Hub portal. It is not required to use this option if running inside IoT Edge. To publish through IoT Edge by default specify `-t={nameof(WriterGroupTransport.IoTHub)}`.\nDefault: `not set`.\n", dc => this[Configuration.IoTEdge.EdgeHubConnectionString] = dc }, { $"ht|ih=|iothubprotocol=|{Configuration.IoTEdge.HubTransport}=", $"Protocol to use for communication with EdgeHub.\nAllowed values:\n `{string.Join("`\n `", Enum.GetNames())}`\nDefault: `{nameof(TransportOption.Mqtt)}` if device or edge hub connection string is provided, ignored otherwise.\n", (TransportOption p) => this[Configuration.IoTEdge.HubTransport] = p.ToString() }, { $"eh=|eventhubnamespaceconnectionstring=|{Configuration.EventHubs.EventHubNamespaceConnectionString}=", "The connection string of an existing event hub namespace to use for the Azure EventHub transport.\nDefault: `not set`.\n", eh => this[Configuration.EventHubs.EventHubNamespaceConnectionString] = eh }, { $"sg=|schemagroup=|{Configuration.EventHubs.SchemaGroupNameKey}=", "The schema group in an event hub namespace to publish message schemas to.\nDefault: `not set`.\n", sg => this[Configuration.EventHubs.SchemaGroupNameKey] = sg }, { $"d|dcs=|daprconnectionstring=|{Configuration.Dapr.DaprConnectionStringKey}=", $"Connect the OPC Publisher to a dapr pub sub component using a connection string.\nThe connection string specifies the PubSub component to use and allows you to configure the side car connection if needed.\nUse the format 'PubSubComponent=[;GrpcPort=;HttpPort=[;Scheme=<'https'|'http'>][;Host=]][;CheckSideCarHealth=<'true'|'false'>]'.\nTo publish through dapr by default specify `-t={nameof(WriterGroupTransport.Dapr)}`.\nDefault: `not set`.\n", dcs => this[Configuration.Dapr.DaprConnectionStringKey] = dcs }, { $"w|hcs=|httpconnectionstring=|{Configuration.Http.HttpConnectionStringKey}=", $"Allows OPC Publisher to publish multipart messages to a topic path using the http protocol (web hook). Specify the target host and configure the optional connection settings using a connection string of the format 'HostName=[;Port=][;Scheme=<'https'|'http'>][;Put=true][;ApiKey=]'. To publish via HTTP by default specify `-t={nameof(WriterGroupTransport.Http)}`.\nDefault: `not set`.\n", hcs => this[Configuration.Http.HttpConnectionStringKey] = hcs }, { $"o|outdir=|{Configuration.FileSystem.OutputRootKey}=", $"A folder to write messages into.\nUse this option to have OPC Publisher write messages to a folder structure under this folder. The structure reflects the topic tree. To publish into the file system folder by default specify `-t={nameof(WriterGroupTransport.FileSystem)}`.\nDefault: `not set`.\n", or => this[Configuration.FileSystem.OutputRootKey] = or }, { $"p|httpserverport=|{PublisherConfig.HttpServerPortKey}=", $"The port on which the http server of OPC Publisher is listening.\nDefault: `{PublisherConfig.HttpServerPortDefault}` if no value is provided.\n", p => this[PublisherConfig.HttpServerPortKey] = p }, { $"unsecurehttp:|{PublisherConfig.UnsecureHttpServerPortKey}:", $"Allow unsecure access to the REST api of OPC Publisher. A port can be specified if the default port {PublisherConfig.UnsecureHttpServerPortDefault} is not desired.\nDo not enable this in production as it exposes the Api Key on the network.\nDefault: `disabled`, if specified without a port `{PublisherConfig.UnsecureHttpServerPortDefault}` port is used.\n", (ushort? p) => this[PublisherConfig.UnsecureHttpServerPortKey] = p?.ToString(CultureInfo.CurrentCulture) ?? PublisherConfig.UnsecureHttpServerPortDefault.ToString(CultureInfo.CurrentCulture) }, { $"rtc|renewtlscert:|{PublisherConfig.RenewTlsCertificateOnStartupKey}:", "If set a new tls certificate is created during startup updating any previously created ones.\nDefault: `false`.\n", (bool? b) => this[PublisherConfig.RenewTlsCertificateOnStartupKey] = b?.ToString() ?? "True" }, { $"useopenapiv3:|{Configuration.OpenApi.UseOpenApiV3Key}:", "If enabled exposes the open api schema of OPC Publisher using v3 schema (yaml).\nOnly valid if Open API endpoint is not disabled.\nDefault: `v2` (json).\n", (bool? b) => this[Configuration.OpenApi.UseOpenApiV3Key] = b?.ToString() ?? "True" }, "", "Routing configuration", "---------------------", "", { $"rtt|roottopictemplate:|{PublisherConfig.RootTopicTemplateKey}:", "The default root topic of OPC Publisher.\nIf not specified, the `{{PublisherId}}` template is the root topic.\nCurrently only the template variables\n `{{SiteId}}` and\n `{{PublisherId}}`\ncan be used as dynamic substituations in the template. If the template variable does not exist it is replaced with the `$default` string.\nDefault: `{{PublisherId}}`.\n", t => this[PublisherConfig.RootTopicTemplateKey] = t }, { $"mtt|methodtopictemplate=|{PublisherConfig.MethodTopicTemplateKey}=", "The topic at which OPC Publisher's method handler is mounted.\nIf not specified, the `{{RootTopic}}/methods` template will be used as root topic with the method names as sub topic.\nOnly\n `{{RootTopic}}`\n `{{SiteId}}` and\n `{{PublisherId}}`\ncan currently be used as replacement variables in the template.\nDefault: `{{RootTopic}}/methods`.\n", t => this[PublisherConfig.MethodTopicTemplateKey] = t }, { $"ttt|telemetrytopictemplate:|{PublisherConfig.TelemetryTopicTemplateKey}:", "The default topic that all messages are sent to.\nIf not specified, the `{{RootTopic}}/messages/{{WriterGroup}}` template will be used as root topic for all events sent by OPC Publisher.\nThe template variables\n `{{RootTopic}}`\n `{{SiteId}}`\n `{{Encoding}}`\n `{{PublisherId}}`\n `{{DataSetClassId}}`\n `{{DataSetWriter}}` and\n `{{WriterGroup}}`\n can be used as dynamic parts in the template. If a template variable does not exist the name of the variable is emitted.\nDefault: `{{RootTopic}}/messages/{{WriterGroup}}`.\n", t => this[PublisherConfig.TelemetryTopicTemplateKey] = t }, { $"ett|eventstopictemplate=|{PublisherConfig.EventsTopicTemplateKey}=", "The topic into which OPC Publisher publishes any events that are not telemetry messages such as discovery or runtime events.\nIf not specified, the `{{RootTopic}}/events` template will be used.\nOnly\n `{{RootTopic}}`\n `{{SiteId}}`\n `{{Encoding}}` and\n `{{PublisherId}}`\ncan currently be used as replacement variables in the template.\nDefault: `{{RootTopic}}/events`.\n", t => this[PublisherConfig.EventsTopicTemplateKey] = t }, { $"dtt|diagnosticstopictemplate=|{PublisherConfig.DiagnosticsTopicTemplateKey}=", "The topic into which OPC Publisher publishes writer group diagnostics events.\nIf not specified, the `{{RootTopic}}/diagnostics/{{WriterGroup}}` template will be used.\nOnly\n `{{RootTopic}}`\n `{{SiteId}}`\n `{{Encoding}}`\n `{{PublisherId}}` and\n `{{WriterGroup}}`\ncan currently be used as replacement variables in the template.\nDefault: `{{RootTopic}}/diagnostics/{{WriterGroup}}`\n", t => this[PublisherConfig.DiagnosticsTopicTemplateKey] = t }, { $"mdt|metadatatopictemplate:|{PublisherConfig.DataSetMetaDataTopicTemplateKey}:", "The topic that metadata should be sent to.\nIn case of MQTT the message will by default be sent as RETAIN message with a TTL of either metadata send interval or infinite if metadata send interval is not configured.\nOnly valid if metadata is supported and/or explicitely enabled.\nThe template variables\n `{{RootTopic}}`\n `{{SiteId}}`\n `{{TelemetryTopic}}`\n `{{Encoding}}`\n `{{PublisherId}}`\n `{{DataSetClassId}}`\n `{{DataSetWriter}}` and\n `{{WriterGroup}}`\ncan be used as dynamic parts in the template. \nDefault: `{{TelemetryTopic}}` which means metadata is sent to the same output as regular messages. If specified without value, the default output is `{{TelemetryTopic}}/metadata`.\n", s => this[PublisherConfig.DataSetMetaDataTopicTemplateKey] = !string.IsNullOrEmpty(s) ? s : PublisherConfig.MetadataTopicTemplateDefault }, { $"stt|schematopictemplate:|{PublisherConfig.SchemaTopicTemplateKey}:", $"The topic that schemas should be sent to if schema publishing is configured.\nIn case of MQTT schemas will not be sent with .\nOnly valid if schema publishing is enabled using `--ps` (`{PublisherConfig.PublishMessageSchemaKey}`) command line option ().\n" + "The template variables\n `{{RootTopic}}`\n `{{SiteId}}`\n `{{PublisherId}}`\n `{{TelemetryTopic}}`\ncan be used as variables inside the template. \nDefault: `{{TelemetryTopic}}/schema` which means the schema is sent to a sub topic where the telemetry message is sent to.\n", s => this[PublisherConfig.SchemaTopicTemplateKey] = !string.IsNullOrEmpty(s) ? s : PublisherConfig.SchemaTopicTemplateDefault }, { $"uns|datasetrouting=|{PublisherConfig.DefaultDataSetRoutingKey}=", $"Configures whether messages should automatically be routed using the browse path of the monitored item inside the address space starting from the RootFolder.\nThe browse path is appended as topic structure to the telemetry topic root which can be configured using `--ttt` (`{PublisherConfig.TelemetryTopicTemplateKey}`). Reserved characters in browse names are escaped with their hex ASCII code.\nAllowed values:\n `{string.Join("`\n `", Enum.GetNames())}`\nDefault: `{nameof(DataSetRoutingMode.None)}` (Topics must be configured).\n", (DataSetRoutingMode m) => this[PublisherConfig.DefaultDataSetRoutingKey] = m.ToString() }, { $"ri|enableroutinginfo:|{PublisherConfig.EnableDataSetRoutingInfoKey}:", $"Add routing information to messages. The name of the property is `{Constants.MessagePropertyRoutingKey}` and the value is the `DataSetWriterGroup` from which the particular message is emitted. Disabled if `{PublisherConfig.EnableCloudEventsKey}` is enabled.\nDefault: `{PublisherConfig.EnableDataSetRoutingInfoDefault}`.\n", (bool? b) => this[PublisherConfig.EnableDataSetRoutingInfoKey] = b?.ToString() ?? "True" }, { $"ce|cloudevents:|{PublisherConfig.EnableCloudEventsKey}:", $"Add cloud event headers to messages. The cloud events comply to the opc ua cloud events extension.\nDefault: `{PublisherConfig.EnableCloudEventsDefault}`.\n", (bool? b) => this[PublisherConfig.EnableCloudEventsKey] = b?.ToString() ?? "True" }, "", "Subscription settings", "---------------------", "", { $"oi|opcsamplinginterval=|{OpcUaSubscriptionConfig.DefaultSamplingIntervalKey}=", "Default value in milliseconds to request the servers to sample values. This value is used if an explicit sampling interval for a node was not configured. \nDefault: `1000`.\nAlso can be set using `DefaultSamplingInterval` environment variable in the form of a duration string in the form `[d.]hh:mm:ss[.fffffff]`.\n", (uint i) => this[OpcUaSubscriptionConfig.DefaultSamplingIntervalKey] = TimeSpan.FromMilliseconds(i).ToString() }, { $"op|opcpublishinginterval=|{OpcUaSubscriptionConfig.DefaultPublishingIntervalKey}=", "Default value in milliseconds for the publishing interval setting of a subscription created with an OPC UA server. This value is used if an explicit publishing interval was not configured.\nWhen setting to `0` the server decides the lowest publishing interval it can support.\nDefault: `1000`.\nAlso can be set using `DefaultPublishingInterval` environment variable in the form of a duration string in the form `[d.]hh:mm:ss[.fffffff]`.\n", (uint i) => this[OpcUaSubscriptionConfig.DefaultPublishingIntervalKey] = TimeSpan.FromMilliseconds(i).ToString() }, { $"eip|immediatepublishing:|{OpcUaSubscriptionConfig.EnableImmediatePublishingKey}:", "By default OPC Publisher will create a subscription with publishing disabled and only enable it after it has filled it with all configured monitored items. Use this setting to create the subscription with publishing already enabled.\nDefault: `false`.\n", (bool? b) => this[OpcUaSubscriptionConfig.EnableImmediatePublishingKey] = b?.ToString() ?? "True" }, { $"ska|keepalivecount=|{OpcUaSubscriptionConfig.DefaultKeepAliveCountKey}=", "Specifies the default number of publishing intervals before a keep alive is returned with the next queued publishing response.\nDefault: `auto set based on publishing interval`.\n", (uint u) => this[OpcUaSubscriptionConfig.DefaultKeepAliveCountKey] = u.ToString(CultureInfo.CurrentCulture) }, { "kt|keepalivethreshold=|MaxKeepAliveCount=", "Legacy way of specifying the keep alive counter.\n", (string s) => this[OpcUaSubscriptionConfig.DefaultKeepAliveCountKey] = s, /* hidden = */ true }, { $"slt|lifetimecount=|{OpcUaSubscriptionConfig.DefaultLifetimeCountKey}=", "Default subscription lifetime count which is a multiple of the keep alive counter and when reached instructs the server to declare the subscription invalid.\nDefault: `auto set based on publishing interval`.\n", (uint i) => this[OpcUaSubscriptionConfig.DefaultLifetimeCountKey] = i.ToString(CultureInfo.CurrentCulture) }, { "MinSubscriptionLifetime=", "Legacy way of specifying the subscription lifetime.", (string s) => this[OpcUaSubscriptionConfig.DefaultLifetimeCountKey] = s, /* hidden = */ true }, { $"fd|fetchdisplayname:|{OpcUaSubscriptionConfig.FetchOpcNodeDisplayNameKey}:", "Fetches the displayname for the monitored items subscribed if a display name was not specified in the configuration.\nNote: This has high impact on OPC Publisher startup performance.\nDefault: `false` (disabled).\n", (bool? b) => this[OpcUaSubscriptionConfig.FetchOpcNodeDisplayNameKey] = b?.ToString() ?? "True" }, { $"fp|fetchpathfromroot:|{OpcUaSubscriptionConfig.FetchOpcBrowsePathFromRootKey}:", "(Experimental) Explicitly disable or enable retrieving relative paths from root for monitored items.\nDefault: `false` (disabled).\n", (bool? b) => this[OpcUaSubscriptionConfig.FetchOpcBrowsePathFromRootKey] = b?.ToString() ?? "True" }, { $"qs|queuesize=|{OpcUaSubscriptionConfig.DefaultQueueSizeKey}=", "Default queue size for all monitored items if queue size was not specified in the configuration.\nDefault: `1` (for backwards compatibility).\n", (uint u) => this[OpcUaSubscriptionConfig.DefaultQueueSizeKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"aq|autosetqueuesize:|{OpcUaSubscriptionConfig.AutoSetQueueSizesKey}:", "(Experimental) Automatically calculate queue sizes for monitored items using the subscription publishing interval and the item's sampling rate as max(configured queue size, roundup(publishinginterval / samplinginterval)).\nNote that the server might revise the queue size down if it cannot handle the calculated size.\nDefault: `false` (disabled).\n", (bool? b) => this[OpcUaSubscriptionConfig.AutoSetQueueSizesKey] = b?.ToString() ?? "True" }, { $"ndo|nodiscardold:|{OpcUaSubscriptionConfig.DefaultDiscardNewKey}:", "The publisher is using this as default value for the discard old setting of monitored item queue configuration. Setting to true will ensure that new values are dropped before older ones are drained. \nDefault: `false` (which is the OPC UA default).\n", (bool? b) => this[OpcUaSubscriptionConfig.DefaultDiscardNewKey] = b?.ToString() ?? "True" }, { $"mc|monitoreditemdatachangetrigger=|{OpcUaSubscriptionConfig.DefaultDataChangeTriggerKey}=", $"Default data change trigger for all monitored items configured in the published nodes configuration unless explicitly overridden.\nAllowed values:\n `{string.Join("`\n `", Enum.GetNames())}`\nDefault: `{nameof(DataChangeTriggerType.StatusValue)}` (which is the OPC UA default).\n", (DataChangeTriggerType t) => this[OpcUaSubscriptionConfig.DefaultDataChangeTriggerKey] = t.ToString() }, { $"mwt|monitoreditemwatchdog=|{OpcUaSubscriptionConfig.DefaultMonitoredItemWatchdogSecondsKey}=", "The subscription and monitored item watchdog timeout in seconds the subscription uses to check on late reporting monitored items unless overridden in the published nodes configuration explicitly.\nDefault: `not set` (watchdog disabled).\n", (uint u) => this[OpcUaSubscriptionConfig.DefaultMonitoredItemWatchdogSecondsKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"mwc|monitoreditemwatchdogcondition=|{OpcUaSubscriptionConfig.DefaultMonitoredItemWatchdogConditionKey}=", $"The default condition when to run the action configured as the watchdog behavior. The condition can be overridden in the published nodes configuration.\nAllowed values:\n `{string.Join("`\n `", Enum.GetNames())}`\nDefault: `{nameof(MonitoredItemWatchdogCondition.WhenAllAreLate)}` (if enabled).\n", (MonitoredItemWatchdogCondition b) => this[OpcUaSubscriptionConfig.DefaultMonitoredItemWatchdogConditionKey] = b.ToString() }, { $"dwb|watchdogbehavior=|{OpcUaSubscriptionConfig.DefaultWatchdogBehaviorKey}=", $"Default behavior of the subscription and monitored item watchdog mechanism unless overridden in the published nodes configuration explicitly.\nAllowed values:\n `{string.Join("`\n `", Enum.GetNames())}`\nDefault: `{nameof(SubscriptionWatchdogBehavior.Diagnostic)}` (if enabled).\n", (SubscriptionWatchdogBehavior b) => this[OpcUaSubscriptionConfig.DefaultWatchdogBehaviorKey] = b.ToString() }, { $"sf|skipfirst:|{OpcUaSubscriptionConfig.DefaultSkipFirstKey}:", $"The publisher is using this as default value for the skip first setting of nodes configured without a skip first setting. A value of True will skip sending the first notification received when the monitored item is added to the subscription.\nDefault: `{OpcUaSubscriptionConfig.DefaultSkipFirstDefault}` (disabled).\n", (bool? b) => this[OpcUaSubscriptionConfig.DefaultSkipFirstKey] = b?.ToString() ?? "True" }, { "skipfirstevent:", "Maintained for backwards compatibility, do not use.", (string b) => this[OpcUaSubscriptionConfig.DefaultSkipFirstKey] = b ?? "True", /* hidden = */ true }, { $"rat|republishaftertransfer:|{OpcUaSubscriptionConfig.DefaultRepublishAfterTransferKey}:", $"Configure whether publisher republishes missed subscription notifications still in the server queue after transferring a subscription during reconnect handling.\nThis can result in out of order notifications after a reconnect but minimizes data loss.\nDefault: `{OpcUaSubscriptionConfig.DefaultRepublishAfterTransferDefault}` (disabled).\n", (bool? b) => this[OpcUaSubscriptionConfig.DefaultRepublishAfterTransferKey] = b?.ToString() ?? "True" }, { $"hbb|heartbeatbehavior=|{OpcUaSubscriptionConfig.DefaultHeartbeatBehaviorKey}=", $"Default behavior of the heartbeat mechanism unless overridden in the published nodes configuration explicitly.\nAllowed values:\n `{string.Join("`\n `", Enum.GetNames().Where(n => !n.StartsWith(nameof(HeartbeatBehavior.Reserved), StringComparison.InvariantCulture)))}`\nDefault: `{nameof(HeartbeatBehavior.WatchdogLKV)}` (Sending LKV in a watchdog fashion).\n", (HeartbeatBehavior b) => this[OpcUaSubscriptionConfig.DefaultHeartbeatBehaviorKey] = b.ToString() }, { $"hb|heartbeatinterval=|{OpcUaSubscriptionConfig.DefaultHeartbeatIntervalKey}=", "The publisher is using this as default value in seconds for the heartbeat interval setting of nodes that were configured without a heartbeat interval setting. A heartbeat is sent at this interval if no value has been received.\nDefault: `0` (disabled)\nAlso can be set using `DefaultHeartbeatInterval` environment variable in the form of a duration string in the form `[d.]hh:mm:ss[.fffffff]`.\n", (uint i) => this[OpcUaSubscriptionConfig.DefaultHeartbeatIntervalKey] = TimeSpan.FromSeconds(i).ToString() }, { $"ucr|usecyclicreads:|{OpcUaSubscriptionConfig.DefaultSamplingUsingCyclicReadKey}:", "All nodes should be sampled using periodical client reads instead of subscriptions services, unless otherwise configured.\nDefault: `false`.\n", (bool? b) => this[OpcUaSubscriptionConfig.DefaultSamplingUsingCyclicReadKey] = b?.ToString() ?? "True" }, { $"xmi|maxmonitoreditems=|{OpcUaSubscriptionConfig.MaxMonitoredItemPerSubscriptionKey}=", "Max monitored items per subscription until the subscription is split.\nThis is used if the server does not provide limits in its server capabilities.\nDefault: `not set`.\n", (uint u) => this[OpcUaSubscriptionConfig.MaxMonitoredItemPerSubscriptionKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"da|deferredacks:|{OpcUaSubscriptionConfig.UseDeferredAcknoledgementsKey}:", "(Experimental) Acknoledge subscription notifications only when the data has been successfully published.\nDefault: `false`.\n", (bool? b) => this[OpcUaSubscriptionConfig.UseDeferredAcknoledgementsKey] = b?.ToString() ?? "True" }, { $"rbp|rebrowseperiod=|{OpcUaSubscriptionConfig.DefaultRebrowsePeriodKey}=", $"(Experimental) The default time to wait until the address space model is browsed again when generating model change notifications.\nDefault: `{OpcUaSubscriptionConfig.DefaultRebrowsePeriodDefault}`.\n", (TimeSpan t) => this[OpcUaSubscriptionConfig.DefaultRebrowsePeriodKey] = t.ToString() }, { $"sqp|sequentialpublishing:|{OpcUaSubscriptionConfig.EnableSequentialPublishingKey}:", $"Set to false to disable sequential publishing in the protocol stack.\nDefault: `{OpcUaSubscriptionConfig.EnableSequentialPublishingDefault}` (enabled).\n", (bool? b) => this[OpcUaSubscriptionConfig.EnableSequentialPublishingKey] = b?.ToString() ?? "True" }, { $"smi|subscriptionmanagementinterval=|{OpcUaSubscriptionConfig.SubscriptionManagementIntervalSecondsKey}=", "The interval in seconds after which the publisher re-applies the desired state of the subscription to a session.\nDefault: `0` (only on configuration change).\n", (uint u) => this[OpcUaSubscriptionConfig.SubscriptionManagementIntervalSecondsKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"bnr|badnoderetrydelay=|{OpcUaSubscriptionConfig.BadMonitoredItemRetryDelaySecondsKey}=", $"The delay in seconds after which nodes that were rejected by the server while added or updating a subscription or while publishing, are re-applied to a subscription.\nSet to 0 to disable retrying.\nDefault: `{OpcUaSubscriptionConfig.BadMonitoredItemRetryDelayDefaultSec}` seconds.\n", (uint u) => this[OpcUaSubscriptionConfig.BadMonitoredItemRetryDelaySecondsKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"inr|invalidnoderetrydelay=|{OpcUaSubscriptionConfig.InvalidMonitoredItemRetryDelaySecondsKey}=", $"The delay in seconds after which the publisher attempts to re-apply nodes that were incorrectly configured to a subscription.\nSet to 0 to disable retrying.\nDefault: `{OpcUaSubscriptionConfig.InvalidMonitoredItemRetryDelayDefaultSec}` seconds.\n", (uint u) => this[OpcUaSubscriptionConfig.InvalidMonitoredItemRetryDelaySecondsKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"bmd|badnoderetrymaxdelay=|{OpcUaSubscriptionConfig.BadMonitoredItemRetryDelayMaxSecondsKey}=", $"The max delay in seconds between retrying nodes that were rejected by the server while added or updating a subscription or while publishing.\nWhen set an exponential retry policy is used with the `--bmr` (`{OpcUaSubscriptionConfig.BadMonitoredItemRetryDelaySecondsKey}`) value as the starting delay.\nDefault: `not set`.\n", (uint u) => this[OpcUaSubscriptionConfig.BadMonitoredItemRetryDelayMaxSecondsKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"imd|invalidnoderetrymaxdelay=|{OpcUaSubscriptionConfig.InvalidMonitoredItemRetryDelayMaxSecondsKey}=", $"The max delay in seconds between retrying nodes that were incorrectly configured in the a subscription.\nWhen set an exponential retry policy is used with the `--inr` (`{OpcUaSubscriptionConfig.InvalidMonitoredItemRetryDelaySecondsKey}`) value as the starting delay.\nDefault: `not set`.\n", (uint u) => this[OpcUaSubscriptionConfig.InvalidMonitoredItemRetryDelayMaxSecondsKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"ser|subscriptionerrorretrydelay=|{OpcUaSubscriptionConfig.SubscriptionErrorRetryDelaySecondsKey}=", $"The delay in seconds between attempts to create a subscription in a session.\nSet to 0 to disable retrying.\nDefault: `{OpcUaSubscriptionConfig.SubscriptionErrorRetryDelayDefaultSec}` seconds.\n", (uint u) => this[OpcUaSubscriptionConfig.SubscriptionErrorRetryDelaySecondsKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"urc|usereverseconnect:|{PublisherConfig.DefaultUseReverseConnectKey}:", "(Experimental) Use reverse connect for all endpoints in the published nodes configuration unless otherwise configured.\nDefault: `false`.\n", (bool? b) => this[PublisherConfig.DefaultUseReverseConnectKey] = b?.ToString() ?? "True" }, { $"dtr|disabletransferonreconnect:|{PublisherConfig.DisableSubscriptionTransferKey}:", "Do not attempt to transfer subscriptions when reconnecting but re-establish the subscription.\nDefault: `false`.\n", (bool? b) => this[PublisherConfig.DisableSubscriptionTransferKey] = b?.ToString() ?? "True" }, { $"dct|disablecomplextypesystem:|{PublisherConfig.DisableComplexTypeSystemKey}:", "Never load the complex type system for any connections that are required for subscriptions.\nThis setting not just disables meta data messages but also prevents transcoding of unknown complex types in outgoing messages.\nDefault: `false`.\n", (bool? b) => this[PublisherConfig.DisableComplexTypeSystemKey] = b?.ToString() ?? "True" }, { $"dsg|disablesessionpergroup:|{PublisherConfig.DisableSessionPerWriterGroupKey}:", $"Disable creating a separate session per writer group. Instead sessions are re-used across writer groups.\nDefault: `{PublisherConfig.DisableSessionPerWriterGroupDefault}`.\n", (bool? b) => this[PublisherConfig.DisableSessionPerWriterGroupKey] = b?.ToString() ?? "True" }, { $"ipi|ignorepublishingintervals:|{PublisherConfig.IgnoreConfiguredPublishingIntervalsKey}:", $"Always use the publishing interval provided via `--op` ({OpcUaSubscriptionConfig.DefaultPublishingIntervalKey}) and ignore all publishing interval settings in the configuration.\nCombine with `--op=0` (({OpcUaSubscriptionConfig.DefaultPublishingIntervalKey})=0) to let the server use the lowest publishing interval it can support.\nDefault: `{PublisherConfig.IgnoreConfiguredPublishingIntervalsDefault}` (disabled).\n", (bool? b) => this[PublisherConfig.IgnoreConfiguredPublishingIntervalsKey] = b?.ToString() ?? "True" }, "", "OPC UA Client configuration", "---------------------------", "", { $"aa|acceptuntrusted:|{OpcUaClientConfig.AutoAcceptUntrustedCertificatesKey}:", "The publisher accepts untrusted certificates presented by a server it connects to.\nThis does not include servers presenting bad certificates or certificates that fail chain validation. These errors cannot be suppressed and connection will always be rejected.\nWARNING: This setting should never be used in production environments!\n", (bool? b) => this[OpcUaClientConfig.AutoAcceptUntrustedCertificatesKey] = b?.ToString() ?? "True" }, { "autoaccept:", "Maintained for backwards compatibility, do not use.", (string b) => this[OpcUaClientConfig.AutoAcceptUntrustedCertificatesKey] = b ?? "True", /* hidden = */ true }, { $"rur|rejectunknownrevocationstatus:|{OpcUaClientConfig.RejectUnknownRevocationStatusKey}:", $"Set this to `False` to accept certificates presented by a server that have an unknown revocation status.\nWARNING: This setting should never be used in production environments!\nDefault: `{OpcUaClientConfig.RejectUnknownRevocationStatusDefault}`.\n", (bool? b) => this[OpcUaClientConfig.RejectUnknownRevocationStatusKey] = b?.ToString() ?? "True" }, { $"ct|createsessiontimeout=|{OpcUaClientConfig.CreateSessionTimeoutKey}=", $"Amount of time in seconds to wait until a session is connected.\nDefault: `{OpcUaClientConfig.CreateSessionTimeoutDefaultSec}` seconds.\n", (uint u) => this[OpcUaClientConfig.CreateSessionTimeoutKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"mr|reconnectperiod=|{OpcUaClientConfig.MinReconnectDelayKey}=", $"The minimum amount of time in milliseconds to wait reconnection of session is attempted again.\nDefault: `{OpcUaClientConfig.MinReconnectDelayDefault}` milliseconds.\n", (uint i) => this[OpcUaClientConfig.MinReconnectDelayKey] = i.ToString(CultureInfo.CurrentCulture) }, { $"xr|maxreconnectperiod=|{OpcUaClientConfig.MaxReconnectDelayKey}=", $"The maximum amount of time in millseconds to wait between reconnection attempts of the session.\nDefault: `{OpcUaClientConfig.MaxReconnectDelayDefault}` milliseconds.\n", (uint i) => this[OpcUaClientConfig.MaxReconnectDelayKey] = i.ToString(CultureInfo.CurrentCulture) }, { $"sto|sessiontimeout=|{OpcUaClientConfig.DefaultSessionTimeoutKey}=", $"Maximum amount of time in seconds that a session should remain open by the OPC server without any activity (session timeout). Requested from the OPC server at session creation.\nDefault: `{OpcUaClientConfig.DefaultSessionTimeoutDefaultSec}` seconds.\n", (uint u) => this[OpcUaClientConfig.DefaultSessionTimeoutKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"ki|keepaliveinterval=|{OpcUaClientConfig.KeepAliveIntervalKey}=", $"The interval in seconds the publisher is sending keep alive messages to the OPC servers on the endpoints it is connected to.\nDefault: `{OpcUaClientConfig.KeepAliveIntervalDefaultSec}` seconds.\n", (uint i) => this[OpcUaClientConfig.KeepAliveIntervalKey] = i.ToString(CultureInfo.CurrentCulture) }, { $"sct|servicecalltimeout=|{OpcUaClientConfig.DefaultServiceCallTimeoutKey}=", $"Maximum amount of time in seconds that a service call should take before it is being cancelled.\nThis value can be overridden in the request header.\nDefault: `{OpcUaClientConfig.DefaultServiceCallTimeoutDefaultSec}` seconds.\n", (uint u) => this[OpcUaClientConfig.DefaultServiceCallTimeoutKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"cto|connecttimeout=|{OpcUaClientConfig.DefaultConnectTimeoutKey}=", "Maximum amount of time in seconds that a service call should wait for a connected session to be used.\nThis value can be overridden in the request header.\nDefault: `not set` (in this case the default service call timeout value is used).\n", (uint u) => this[OpcUaClientConfig.DefaultConnectTimeoutKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"ot|operationtimeout=|{OpcUaClientConfig.OperationTimeoutKey}=", $"The operation service call timeout of individual service requests to the server in milliseconds. As opposed to the `--sct` ({OpcUaClientConfig.DefaultServiceCallTimeoutKey}) timeout, this is the timeout hint provided to the server in every request.\nThis value can be overridden in the request header.\nDefault: `{OpcUaClientConfig.OperationTimeoutDefault}` milliseconds.\n", (uint u) => this[OpcUaClientConfig.OperationTimeoutKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"cl|clientlinger=|{OpcUaClientConfig.LingerTimeoutSecondsKey}=", "Amount of time in seconds to delay closing a client and underlying session after the a last service call.\nUse this setting to speed up multiple subsequent calls.\nDefault: `0` sec (no linger).\n", (uint u) => this[OpcUaClientConfig.LingerTimeoutSecondsKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"rcp|reverseconnectport=|{OpcUaClientConfig.ReverseConnectPortKey}=", $"The port to use when accepting inbound reverse connect requests from servers.\nDefault: `{OpcUaClientConfig.ReverseConnectPortDefault}`.\n", (ushort u) => this[OpcUaClientConfig.ReverseConnectPortKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"mnr|maxnodesperread=|{OpcUaClientConfig.MaxNodesPerReadOverrideKey}=", "Limit max number of nodes to read in a single read request when batching reads or the server limit if less.\nDefault: `0` (using server limit).\n", (uint u) => this[OpcUaClientConfig.MaxNodesPerReadOverrideKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"mnb|maxnodesperbrowse=|{OpcUaClientConfig.MaxNodesPerBrowseOverrideKey}=", "Limit max number of nodes per browse request when batching browse operations or the server limit if less.\nDefault: `0` (using server limit).\n", (uint u) => this[OpcUaClientConfig.MaxNodesPerBrowseOverrideKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"ncc|nodecachecapacity=|{OpcUaClientConfig.NodeCacheCapacityKey}=", "The max size of the node caches used in the complex type system.\nThere are caches (values, nodes, references).\nDefault: `4096`.\n", (uint u) => this[OpcUaClientConfig.NodeCacheCapacityKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"nct|nodecachetimeout=|{OpcUaClientConfig.NodeCacheTimeoutKey}=", "The timeout of a node cache entries if not used in milliseconds.\nDefault: `3600`.\n", (uint u) => this[OpcUaClientConfig.NodeCacheTimeoutKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"mpr|minpublishrequests=|{OpcUaClientConfig.MinPublishRequestsKey}=", $"Minimum number of publish requests to queue once subscriptions are created in the session.\nDefault: `{OpcUaClientConfig.MinPublishRequestsDefault}`.\n", (uint u) => this[OpcUaClientConfig.MinPublishRequestsKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"ppr|percentpublishrequests=|{OpcUaClientConfig.PublishRequestsPerSubscriptionPercentKey}=", $"Percentage ratio of publish requests per subscriptions in the session in percent up to the number configured using `--xpr` ({OpcUaClientConfig.MaxPublishRequestsKey}).\nDefault: `{OpcUaClientConfig.PublishRequestsPerSubscriptionPercentDefault}`% (1 request per subscription).\n", (ushort u) => this[OpcUaClientConfig.PublishRequestsPerSubscriptionPercentKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"xpr|maxpublishrequests=|{OpcUaClientConfig.MaxPublishRequestsKey}=", $"Maximum number of publish requests to every queue once subscriptions are created in the session.\nDefault: `{OpcUaClientConfig.MaxPublishRequestsDefault}`.\n", (uint u) => this[OpcUaClientConfig.MaxPublishRequestsKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"dcp|disablecomplextypepreloading:|{OpcUaClientConfig.DisableComplexTypePreloadingKey}:", "Complex types (structures, enumerations) a server exposes are preloaded from the server after the session is connected. In some cases this can cause problems either on the client or server itself. Use this setting to disable pre-loading support.\nNote that since the complex type system is used for meta data messages it will still be loaded at the time the subscription is created, therefore also disable meta data support if you want to ensure the complex types are never loaded for an endpoint.\nDefault: `false`.\n", (bool? b) => this[OpcUaClientConfig.DisableComplexTypePreloadingKey] = b?.ToString() ?? "True" }, { $"otl|opctokenlifetime=|{OpcUaClientConfig.SecurityTokenLifetimeKey}=", "OPC UA Stack Transport Secure Channel - Security token lifetime in milliseconds.\nDefault: `3600000` (1h).\n", (uint u) => this[OpcUaClientConfig.SecurityTokenLifetimeKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"ocl|opcchannellifetime=|{OpcUaClientConfig.ChannelLifetimeKey}=", "OPC UA Stack Transport Secure Channel - Channel lifetime in milliseconds.\nDefault: `300000` (5 min).\n", (uint u) => this[OpcUaClientConfig.ChannelLifetimeKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"omb|opcmaxbufferlen=|{OpcUaClientConfig.MaxBufferSizeKey}=", "OPC UA Stack Transport Secure Channel - Max buffer size.\nDefault: `65535` (64KB -1).\n", (uint u) => this[OpcUaClientConfig.MaxBufferSizeKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"oml|opcmaxmessagelen=|{OpcUaClientConfig.MaxMessageSizeKey}=", "OPC UA Stack Transport Secure Channel - Max message size.\nDefault: `4194304` (4 MB).\n", (uint u) => this[OpcUaClientConfig.MaxMessageSizeKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"oal|opcmaxarraylen=|{OpcUaClientConfig.MaxArrayLengthKey}=", "OPC UA Stack Transport Secure Channel - Max array length.\nDefault: `65535` (64KB - 1).\n", (uint u) => this[OpcUaClientConfig.MaxArrayLengthKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"ol|opcmaxstringlen=|{OpcUaClientConfig.MaxStringLengthKey}=", "The max length of a string opc can transmit/receive over the OPC UA secure channel.\nDefault: `130816` (128KB - 256).\n", (uint u) => this[OpcUaClientConfig.MaxStringLengthKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"obl|opcmaxbytestringlen=|{OpcUaClientConfig.MaxByteStringLengthKey}=", "OPC UA Stack Transport Secure Channel - Max byte string length.\nDefault: `1048576` (1MB).\n", (uint u) => this[OpcUaClientConfig.MaxByteStringLengthKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"au|appuri=|{OpcUaClientConfig.ApplicationUriKey}=", "Application URI as per OPC UA definition inside the OPC UA client application configuration presented to the server.\nDefault: `not set`.\n", s => this[OpcUaClientConfig.ApplicationUriKey] = s }, { $"pu|producturi=|{OpcUaClientConfig.ProductUriKey}=", "The Product URI as per OPC UA definition insde the OPC UA client application configuration presented to the server.\nDefault: `not set`.\n", s => this[OpcUaClientConfig.ProductUriKey] = s }, { $"rejectsha1=|{OpcUaClientConfig.RejectSha1SignedCertificatesKey}=", "If set to `False` OPC Publisher will accept SHA1 certificates which have been officially deprecated and are unsafe to use.\nNote: Set this to `False` to support older equipment that uses Sha1 signed certificates rather than using no security.\nDefault: `True`.\n", (bool b) => this[OpcUaClientConfig.RejectSha1SignedCertificatesKey] = b.ToString() }, { $"mks|minkeysize=|{OpcUaClientConfig.MinimumCertificateKeySizeKey}=", "Minimum accepted certificate size.\nNote: It is recommended to this value to the highest certificate key size possible based on the connected OPC UA servers.\nDefault: 1024.\n", s => this[OpcUaClientConfig.MinimumCertificateKeySizeKey] = s }, { $"tm|trustmyself=|{OpcUaClientConfig.AddAppCertToTrustedStoreKey}=", "Set to `False` to disable adding the publisher's own certificate to the trusted store automatically.\nDefault: `True`.\n", (bool b) => this[OpcUaClientConfig.AddAppCertToTrustedStoreKey] = b.ToString() }, { $"sn|appcertsubjectname=|{OpcUaClientConfig.ApplicationCertificateSubjectNameKey}=", $"The subject name for the app cert.\nDefault: `CN=, C=DE, S=Bav, O=Microsoft, DC=localhost`.\n", s => this[OpcUaClientConfig.ApplicationCertificateSubjectNameKey] = s }, { $"an|appname=|{OpcUaClientConfig.ApplicationNameKey}=", $"The name for the app (used during OPC UA authentication).\nDefault: `{OpcUaClientConfig.ApplicationNameDefault}`\n", s => this[OpcUaClientConfig.ApplicationNameKey] = s }, { $"pki|pkirootpath=|{OpcUaClientConfig.PkiRootPathKey}=", "PKI certificate store root path.\nDefault: `pki`.\n", s => this[OpcUaClientConfig.PkiRootPathKey] = s }, { $"ap|appcertstorepath=|{OpcUaClientConfig.ApplicationCertificateStorePathKey}=", "The path where the own application cert should be stored.\nDefault: $\"{{PkiRootPath}}/own\".\n", s => this[OpcUaClientConfig.ApplicationCertificateStorePathKey] = s }, { $"apt|at=|appcertstoretype=|{OpcUaClientConfig.ApplicationCertificateStoreTypeKey}=", $"The own application cert store type.\nAllowed values:\n `{CertificateStoreType.Directory}`\n `{CertificateStoreType.X509Store}`\n `{FlatCertificateStore.StoreTypeName}`\nDefault: `{CertificateStoreType.Directory}`.\n", s => SetStoreType(s, OpcUaClientConfig.ApplicationCertificateStoreTypeKey, "apt") }, { $"cfa|configurefromappcert:|{OpcUaClientConfig.TryConfigureFromExistingAppCertKey}:", "Automatically set the application subject name, host name and application uri from the first valid application certificate found in the application certificate store path.\nIf the chosen certificate is valid, it will be used, otherwise a new, self-signed certificate with the information will be created.\nDefault: `false`.\n", (bool? b) => this[OpcUaClientConfig.TryConfigureFromExistingAppCertKey] = b?.ToString() ?? "True" }, { $"apw|appcertstorepwd=|{OpcUaClientConfig.ApplicationCertificatePasswordKey}=", "Password to use when storing the application certificate in the store folder if the store is of type `Directory`.\nDefault: empty, which means application certificate is not protected by default.\n", s => this[OpcUaClientConfig.ApplicationCertificatePasswordKey] = s }, { $"tp|trustedcertstorepath=|{OpcUaClientConfig.TrustedPeerCertificatesPathKey}=", "The path of the trusted cert store.\nDefault: $\"{{PkiRootPath}}/trusted\".\n", s => this[OpcUaClientConfig.TrustedPeerCertificatesPathKey] = s }, { $"tpt|{OpcUaClientConfig.TrustedPeerCertificatesTypeKey}=", $"Trusted peer certificate store type.\nAllowed values:\n `{CertificateStoreType.Directory}`\n `{CertificateStoreType.X509Store}`\n `{FlatCertificateStore.StoreTypeName}`\nDefault: `{CertificateStoreType.Directory}`.\n", s => SetStoreType(s, OpcUaClientConfig.TrustedPeerCertificatesTypeKey, "tpt") }, { $"rp|rejectedcertstorepath=|{OpcUaClientConfig.RejectedCertificateStorePathKey}=", "The path of the rejected cert store.\nDefault: $\"{{PkiRootPath}}/rejected\".\n", s => this[OpcUaClientConfig.RejectedCertificateStorePathKey] = s }, { $"rpt|{OpcUaClientConfig.RejectedCertificateStoreTypeKey}=", $"Rejected certificate store type.\nAllowed values:\n `{CertificateStoreType.Directory}`\n `{CertificateStoreType.X509Store}`\n `{FlatCertificateStore.StoreTypeName}`\nDefault: `{CertificateStoreType.Directory}`.\n", s => SetStoreType(s, OpcUaClientConfig.RejectedCertificateStoreTypeKey, "rpt") }, { $"ip|issuercertstorepath=|{OpcUaClientConfig.TrustedIssuerCertificatesPathKey}=", "The path of the trusted issuer cert store.\nDefault: $\"{{PkiRootPath}}/issuer\".\n", s => this[OpcUaClientConfig.TrustedIssuerCertificatesPathKey] = s }, { $"ipt|{OpcUaClientConfig.TrustedIssuerCertificatesTypeKey}=", $"Trusted issuer certificate store type.\nAllowed values:\n `{CertificateStoreType.Directory}`\n `{CertificateStoreType.X509Store}`\n `{FlatCertificateStore.StoreTypeName}`\nDefault: `{CertificateStoreType.Directory}`.\n", s => SetStoreType(s, OpcUaClientConfig.TrustedIssuerCertificatesTypeKey, "ipt") }, { $"up|usercertstorepath=|{OpcUaClientConfig.TrustedUserCertificatesPathKey}=", "The path of the certificate store for user certificates.\nDefault: $\"{{PkiRootPath}}/users\".\n", s => this[OpcUaClientConfig.TrustedUserCertificatesPathKey] = s }, { $"upt|{OpcUaClientConfig.TrustedUserCertificatesTypeKey}=", $"Type of certificate store for all User certificates.\nAllowed values:\n `{CertificateStoreType.Directory}`\n `{CertificateStoreType.X509Store}`\n `{FlatCertificateStore.StoreTypeName}`\nDefault: `{CertificateStoreType.Directory}`.\n", s => SetStoreType(s, OpcUaClientConfig.TrustedUserCertificatesTypeKey, "upt") }, { $"uip|userissuercertstorepath=|{OpcUaClientConfig.UserIssuerCertificatesPathKey}=", "The path of the user issuer cert store.\nDefault: $\"{{PkiRootPath}}/users/issuer\".\n", s => this[OpcUaClientConfig.UserIssuerCertificatesPathKey] = s }, { $"uit|{OpcUaClientConfig.UserIssuerCertificatesTypeKey}=", $"Type of the issuer certificate store for User certificates.\nAllowed values:\n `{CertificateStoreType.Directory}`\n `{CertificateStoreType.X509Store}`\n `{FlatCertificateStore.StoreTypeName}`\nDefault: `{CertificateStoreType.Directory}`.\n", s => SetStoreType(s, OpcUaClientConfig.UserIssuerCertificatesTypeKey, "uip") }, "", "Diagnostic options", "------------------", "", { $"ll|loglevel=|{Configuration.LoggingLevel.LogLevelKey}=", $"The loglevel to use.\nAllowed values:\n `{string.Join("`\n `", Enum.GetNames())}`\nDefault: `{LogLevel.Information}`.\n", (LogLevel l) => this[Configuration.LoggingLevel.LogLevelKey] = l.ToString() }, { $"lfm|logformat=|{Configuration.LoggingFormat.LogFormatKey}=", $"The log format to use when writing to the console.\nAllowed values:\n `{string.Join("`\n `", Configuration.LoggingFormat.LogFormatsSupported)}`\nDefault: `{Configuration.LoggingFormat.LogFormatDefault}`.\n", (string s) => this[Configuration.LoggingFormat.LogFormatKey] = s }, { $"di|diagnosticsinterval=|{PublisherConfig.DiagnosticsIntervalKey}=", $"Produce publisher diagnostic information at this specified interval in seconds.\nBy default diagnostics are written to the OPC Publisher logger (which requires at least --loglevel or environment variable `{Configuration.LoggingLevel.LogLevelKey}` =`information`) unless configured differently using `--pd` ({PublisherConfig.DiagnosticsTargetKey}).\n`0` disables diagnostic output.\nDefault:60000 (60 seconds).\nAlso can be set using `DiagnosticsInterval` environment variable in the form of a duration string in the form `[d.]hh:mm:ss[.fffffff]`\".\n", (uint i) => this[PublisherConfig.DiagnosticsIntervalKey] = TimeSpan.FromSeconds(i).ToString() }, { $"pd|diagnosticstarget=|{PublisherConfig.DiagnosticsTargetKey}=", $"Configures how to emit diagnostics information at the `--di` ({PublisherConfig.DiagnosticsIntervalKey}) configured interval.\nUse this to for example emit diagnostics as events to the event topic template instead of the console.\nAllowed values:\n `{string.Join("`\n `", Enum.GetNames())}`\nDefault: `{PublisherDiagnosticTargetType.Logger}`.\n", (PublisherDiagnosticTargetType d) => this[PublisherConfig.DiagnosticsTargetKey] = d.ToString() }, { $"dr|disableresourcemonitoring:|{PublisherConfig.DisableResourceMonitoringKey}:", "Disable resource monitoring as part of the diagnostics output and metrics.\nDefault: `false` (enabled).\n", (bool? b) => this[PublisherConfig.DisableResourceMonitoringKey] = b?.ToString() ?? "True" }, { $"ln|lognotifications:|{PublisherConfig.DebugLogNotificationsKey}:", "Log ingress subscription notifications at Informational level to aid debugging.\nDefault: `disabled`.\n", (bool? b) => this[PublisherConfig.DebugLogNotificationsKey] = b?.ToString() ?? "True" }, { $"lnh|lognotificationsandheartbeats:|{PublisherConfig.DebugLogNotificationsWithHeartbeatKey}:", $"Include heartbeats in notifications log.\nIf set also implicitly enables debug logging via `--ln` ({PublisherConfig.DebugLogNotificationsKey}).\nDefault: `disabled`.\n", (bool? b) => this[PublisherConfig.DebugLogNotificationsWithHeartbeatKey] = b?.ToString() ?? "True" }, { $"lnf|lognotificationfilter=|{PublisherConfig.DebugLogNotificationsFilterKey}=", $"Only log notifications where the data set field name, subscription name, or data set name match the provided regular expression pattern.\nIf set implicitly enables debug logging via `--ln` ({PublisherConfig.DebugLogNotificationsKey}).\nDefault: `null` (matches all).\n", (string? r) => this[PublisherConfig.DebugLogNotificationsFilterKey] = r }, { $"len|logencodednotifications:|{PublisherConfig.DebugLogEncodedNotificationsKey}:", "Log encoded subscription and monitored item notifications at Informational level to aid debugging.\nDefault: `disabled`.\n", (bool? b) => this[PublisherConfig.DebugLogEncodedNotificationsKey] = b?.ToString() ?? "True" }, { $"sl|opcstacklogging:|{OpcUaClientConfig.EnableOpcUaStackLoggingKey}:", "Enable opc ua stack logging beyond logging at error level.\nDefault: `disabled`.\n", (bool? b) => this[OpcUaClientConfig.EnableOpcUaStackLoggingKey] = b?.ToString() ?? "True" }, { $"ksf|keysetlogfolder:|{OpcUaClientConfig.OpcUaKeySetLogFolderNameKey}:", "Writes negotiated symmetric keys for all running client connection to this file.\nThe file can be loaded by Wireshark 4.3 and used to decrypt encrypted channels when analyzing network traffic captures.\nNote that enabling this feature presents a security risk!\nDefault: `disabled`.\n", (string? f) => this[OpcUaClientConfig.OpcUaKeySetLogFolderNameKey] = f ?? Directory.GetCurrentDirectory() }, { $"ecw|enableconsolewriter:|{Configuration.ConsoleWriter.EnableKey}:", "Enable writing encoded messages to standard error log through the filesystem transport (must enable via `-t FileSystem` and `-o` must be set to either `stderr` or `stdout`).\nDefault: `false`.\n", (bool? b) => this[Configuration.ConsoleWriter.EnableKey] = b?.ToString() ?? "True" }, { $"oc|otlpcollector=|{Configuration.Otel.OtlpCollectorEndpointKey}=", "Specifiy the OpenTelemetry collector grpc endpoint url to export diagnostics to.\nDefault: `disabled`.\n", s => this[Configuration.Otel.OtlpCollectorEndpointKey] = s }, { $"eol|enableotellogging:|{Configuration.Otel.EnableOtelLoggingKey}:", "Enable logging over open telemetry endpoint.\nBy default only metrics are enabled.\nDefault: `disabled`.\n", (bool? b) => this[Configuration.Otel.EnableOtelLoggingKey] = b?.ToString() ?? "True" }, { $"eot|enableoteltraces:|{Configuration.Otel.EnableOtelTracesKey}:", "Enable traces over open telemetry endpoint.\nBy default only metrics are emitted.\nDefault: `disabled`.\n", (bool? b) => this[Configuration.Otel.EnableOtelTracesKey] = b?.ToString() ?? "True" }, { $"oxi|otlpexportinterval=|{Configuration.Otel.OtlpExportIntervalMillisecondsKey}=", $"The interval in milliseconds when OpenTelemetry is exported to the collector endpoint.\nDefault: `{Configuration.Otel.OtlpExportIntervalMillisecondsDefault}` ({Configuration.Otel.OtlpExportIntervalMillisecondsDefault / 1000} seconds).\n", (uint i) => this[Configuration.Otel.OtlpExportIntervalMillisecondsKey] = TimeSpan.FromMilliseconds(i).ToString() }, { $"mms|maxmetricstreams=|{Configuration.Otel.OtlpMaxMetricStreamsKey}=", $"Specifiy the max number of streams to collect in the default view.\nDefault: `{Configuration.Otel.OtlpMaxMetricDefault}`.\n", (uint u) => this[Configuration.Otel.OtlpMaxMetricStreamsKey] = u.ToString(CultureInfo.CurrentCulture) }, { $"em|enableprometheusendpoint:|{Configuration.Otel.EnableMetricsKey}:", "Explicitly enable or disable exporting prometheus metrics directly on the standard path.\nDefault: `disabled` if Otlp collector is configured, otherwise `enabled`.\n", (bool? b) => this[Configuration.Otel.EnableMetricsKey] = b?.ToString() ?? "True" }, { $"ari|addruntimeinstrumentation:|{Configuration.Otel.OtlpRuntimeInstrumentationKey}:", $"Include metrics captured for the underlying runtime and web server.\nDefault: `{Configuration.Otel.OtlpRuntimeInstrumentationDefault}`.\n", (bool? b) => this[Configuration.Otel.OtlpRuntimeInstrumentationKey] = b?.ToString() ?? "True" }, { $"ats|addtotalsuffix:|{Configuration.Otel.OtlpTotalNameSuffixForCountersKey}:", $"Add total suffix to all counter instrument names when exporting metrics via prometheus exporter.\nDefault: `{Configuration.Otel.OtlpTotalNameSuffixForCountersDefault}`.\n", (bool? b) => this[Configuration.Otel.OtlpTotalNameSuffixForCountersKey] = b?.ToString() ?? "True" }, // testing purposes { "sc|scaletestcount=", "The number of monitored item clones in scale tests.\n", (string i) => this[PublisherConfig.ScaleTestCountKey] = i, /* hidden = */ true }, // Legacy: unsupported and hidden { "mq|monitoreditemqueuecapacity=", "Legacy - do not use.", _ => legacyOptions.Add("mq|monitoreditemqueuecapacity"), /* hidden = */ true }, { "tc|telemetryconfigfile=", "Legacy - do not use.", _ => legacyOptions.Add("tc|telemetryconfigfile"), /* hidden = */ true }, { "ic|iotcentral=", "Legacy - do not use.", _ => legacyOptions.Add("ic|iotcentral"), /* hidden = */ true }, { "ns|noshutdown=", "Legacy - do not use.", _ => legacyOptions.Add("ns|noshutdown"), /* hidden = */ true }, { "rf|runforever", "Legacy - do not use.", _ => legacyOptions.Add("rf|runforever"), /* hidden = */ true }, { "pn|portnum=", "Legacy - do not use.", _ => legacyOptions.Add("pn|portnum"), /* hidden = */ true }, { "pa|path=", "Legacy - do not use.", _ => legacyOptions.Add("pa|path"), /* hidden = */ true }, { "lr|ldsreginterval=", "Legacy - do not use.", _ => legacyOptions.Add("lr|ldsreginterval"), /* hidden = */ true }, { "ss|suppressedopcstatuscodes=", "Legacy - do not use.", _ => legacyOptions.Add("ss|suppressedopcstatuscodes"), /* hidden = */ true }, { "csr", "Legacy - do not use.", _ => legacyOptions.Add("csr"), /* hidden = */ true }, { "ab|applicationcertbase64=", "Legacy - do not use.",_ => legacyOptions.Add("ab|applicationcertbase64"), /* hidden = */ true }, { "af|applicationcertfile=", "Legacy - do not use.", _ => legacyOptions.Add("af|applicationcertfile"), /* hidden = */ true }, { "pk|privatekeyfile=", "Legacy - do not use.", _ => legacyOptions.Add("pk|privatekeyfile"), /* hidden = */ true }, { "pb|privatekeybase64=", "Legacy - do not use.", _ => legacyOptions.Add("pb|privatekeybase64"), /* hidden = */ true }, { "cp|certpassword=", "Legacy - do not use.", _ => legacyOptions.Add("cp|certpassword"), /* hidden = */ true }, { "tb|addtrustedcertbase64=", "Legacy - do not use.", _ => legacyOptions.Add("tb|addtrustedcertbase64"), /* hidden = */ true }, { "tf|addtrustedcertfile=", "Legacy - do not use.", _ => legacyOptions.Add("tf|addtrustedcertfile"), /* hidden = */ true }, { "tt|trustedcertstoretype=", "Legacy - do not use.", _ => legacyOptions.Add("tt|trustedcertstoretype"), /* hidden = */ true }, { "rt|rejectedcertstoretype=", "Legacy - do not use.", _ => legacyOptions.Add("rt|rejectedcertstoretype"), /* hidden = */ true }, { "it|issuercertstoretype=", "Legacy - do not use.", _ => legacyOptions.Add("it|issuercertstoretype"), /* hidden = */ true }, { "ib|addissuercertbase64=", "Legacy - do not use.", _ => legacyOptions.Add("ib|addissuercertbase64"), /* hidden = */ true }, { "if|addissuercertfile=", "Legacy - do not use.", _ => legacyOptions.Add("if|addissuercertfile"), /* hidden = */ true }, { "rb|updatecrlbase64=", "Legacy - do not use.", _ => legacyOptions.Add("rb|updatecrlbase64"), /* hidden = */ true }, { "uc|updatecrlfile=", "Legacy - do not use.", _ => legacyOptions.Add("uc|updatecrlfile"), /* hidden = */ true }, { "rc|removecert=", "Legacy - do not use.", _ => legacyOptions.Add("rc|removecert"), /* hidden = */ true }, { "dt|devicecertstoretype=", "Legacy - do not use.", _ => legacyOptions.Add("dt|devicecertstoretype"), /* hidden = */ true }, { "dp|devicecertstorepath=", "Legacy - do not use.", _ => legacyOptions.Add("dp|devicecertstorepath"), /* hidden = */ true }, { "i|install", "Legacy - do not use.", _ => legacyOptions.Add("i|install"), /* hidden = */ true }, { "st|opcstacktracemask=", "Legacy - do not use.", _ => legacyOptions.Add("st|opcstacktracemask"), /* hidden = */ true }, { "sd|shopfloordomain=", "Legacy - do not use.", _ => legacyOptions.Add("sd|shopfloordomain"), /* hidden = */ true }, { "vc|verboseconsole=", "Legacy - do not use.", _ => legacyOptions.Add("vc|verboseconsole"), /* hidden = */ true }, { "as|autotrustservercerts=", "Legacy - do not use.", _ => legacyOptions.Add("as|autotrustservercerts"), /* hidden = */ true }, { "l|lf|logfile=", "Legacy - do not use.", _ => legacyOptions.Add("l|lf|logfile"), /* hidden = */ true }, { "lt|logflushtimespan=", "Legacy - do not use.", _ => legacyOptions.Add("lt|logflushtimespan"), /* hidden = */ true } }; try { unsupportedOptions = options.Parse(args); } catch (Exception e) { _logger.Warning("Parse args exception {0}.", e.Message); _logger.ExitProcess(160); return; } if (unsupportedOptions.Count > 0) { foreach (var option in unsupportedOptions) { _logger.Warning("Option {0} wrong or not supported, " + "please use -h option to get all the supported options.", option); } } if (legacyOptions.Count > 0) { foreach (var option in legacyOptions) { _logger.Warning("Legacy option {0} not supported, please use -h option to get all the supported options.", option); } } switch (help) { case HelpType.CommandLine: options.WriteOptionDescriptions(Console.Out); _logger.ExitProcess(0); return; case HelpType.EnvVars: var envVars = options .Where(o => !o.Hidden && o.OptionValueType != OptionValueType.None && !o.GetNames().Any(n => n.Contains("help", StringComparison.OrdinalIgnoreCase))) .Select(o => new { key = o.GetNames().Last(), description = o.Description }) .ToList(); Console.WriteLine(JsonConvert.SerializeObject(envVars, Formatting.Indented)); _logger.ExitProcess(0); return; case HelpType.MessageProfiles: Console.WriteLine(MessagingProfile.GetAllAsMarkdownTable()); return; } // Test the publisher configuration for having all necessary content var configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", true) .AddEnvironmentVariables() .AddFromDotEnvFile() .AddConnectorAdditionalConfiguration() .AddInMemoryCollection(this).Build(); try { // Throws if the messaging profile configuration is invalid _ = new PublisherConfig(configuration).ToOptions(); } catch (Exception ex) { _logger.Warning("{0}\nPlease use -h option to get all the supported options.", ex.Message); _logger.ExitProcess(170); return; } // Validate edge configuration var iotEdgeOptions = new IoTEdgeClientOptions(); new Configuration.IoTEdge(configuration).Configure(iotEdgeOptions); var publisherOptions = new PublisherOptions(); new Configuration.Aio(configuration).Configure(publisherOptions); // Check that the important values are provided if (iotEdgeOptions.EdgeHubConnectionString == null && publisherOptions.IsAzureIoTOperationsConnector == null) { _logger.Warning( "To connect to Azure IoT Hub you must run as module inside IoT Edge or " + "specify a device connection string using EdgeHubConnectionString " + "environment variable or command line."); } void SetStoreType(string s, string storeTypeKey, string optionName) { if (s.Equals(CertificateStoreType.X509Store, StringComparison.OrdinalIgnoreCase) || s.Equals(CertificateStoreType.Directory, StringComparison.OrdinalIgnoreCase) || s.Equals(FlatCertificateStore.StoreTypeName, StringComparison.OrdinalIgnoreCase)) { this[storeTypeKey] = s; return; } throw new OptionException("Bad store type", optionName); } } private readonly CommandLineLogger _logger; } /// /// Log command line errors /// public class CommandLineLogger { /// /// Call exit with exit code /// /// public virtual void ExitProcess(int exitCode) { Publisher.Runtime.Exit(exitCode); } /// /// Write a log event with the Warning level. /// /// Message template describing the event. public virtual void Warning(string messageTemplate) { Console.WriteLine(messageTemplate); } /// /// Write a log event with the Warning level. /// /// /// Message template describing the event. /// Object positionally formatted into the message template. public virtual void Warning(string messageTemplate, T0 propertyValue0) { Console.WriteLine(string.Format(CultureInfo.CurrentCulture, messageTemplate, propertyValue0)); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/src/Runtime/Configuration.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Runtime { using Autofac; using Azure.IIoT.OpcUa.Encoders; using Azure.IIoT.OpcUa.Encoders.Schemas; using Azure.IIoT.OpcUa.Publisher.Module.Controllers; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.Iot.Operations.Protocol; using Furly.Azure.EventHubs; using Furly.Azure.IoT.Edge; using Furly.Azure.IoT.Operations.Runtime; using Furly.Extensions.AspNetCore.OpenApi; using Furly.Extensions.Configuration; using Furly.Extensions.Dapr; using Furly.Extensions.Logging; using Furly.Extensions.Messaging.Runtime; using Furly.Extensions.Mqtt; using Furly.Extensions.Rpc.Runtime; using Furly.Tunnel.Router.Services; using k8s; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Console; using Microsoft.Extensions.Options; using Microsoft.OpenApi.Models; using OpenTelemetry; using OpenTelemetry.Exporter; using OpenTelemetry.Logs; using OpenTelemetry.Metrics; using OpenTelemetry.Trace; using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Text.RegularExpressions; /// /// Configuration extensions /// public static class Configuration { /// /// Add all publisher dependencies minus connectivity components. /// /// public static void AddPublisherServices(this ContainerBuilder builder) { builder.AddDefaultJsonSerializer(); builder.AddNewtonsoftJsonSerializer(); builder.AddMessagePackSerializer(); builder.AddPublisherCore(); builder.RegisterType() .AsImplementedInterfaces().SingleInstance(); builder.RegisterType() .AsImplementedInterfaces().AsSelf().SingleInstance(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType>() .AsImplementedInterfaces(); builder.RegisterType>() .AsImplementedInterfaces(); builder.RegisterType>() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces().AsSelf().SingleInstance(); builder.RegisterType() .AsImplementedInterfaces(); // Register and configure controllers builder.RegisterType() .AsImplementedInterfaces().SingleInstance() .PropertiesAutowired( PropertyWiringOptions.AllowCircularDependencies); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); } /// /// Add resource monitoring /// /// /// public static void AddResourceMonitoring(this IServiceCollection services, IConfiguration configuration) { var publisherOptions = new PublisherConfig(configuration).ToOptions(); if (publisherOptions.Value.DisableResourceMonitoring != true) { services.AddResourceMonitoring(); } } /// /// Add mqtt client /// /// /// public static void AddMqttClient(this ContainerBuilder builder, IConfiguration configuration) { var mqttOptions = new MqttOptions(); new MqttBroker(configuration).Configure(mqttOptions); if (mqttOptions.HostName != null) { builder.AddMqttClient(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); } } /// /// Add IoT edge services /// /// /// public static void AddIoTEdgeServices(this ContainerBuilder builder, IConfiguration configuration) { // Validate edge configuration var iotEdgeOptions = new IoTEdgeClientOptions(); new IoTEdge(configuration).Configure(iotEdgeOptions); if (iotEdgeOptions.EdgeHubConnectionString != null) { builder.AddIoTEdgeServices(); builder.RegisterType() .AsImplementedInterfaces(); } } /// /// Add IoT operations services /// /// /// public static void AddIoTOperationsServices(this ContainerBuilder builder, IConfiguration configuration) { var publisherOptions = new PublisherOptions(); new Aio(configuration).Configure(publisherOptions); if (publisherOptions.IsAzureIoTOperationsConnector.HasValue) { // builder.AddAzureIoTOperations(); builder.AddAzureIoTOperationsCore(); builder.AddAdrClient(); builder.AddTelemetryPublisher(); builder.AddSchemaRegistry(); // builder.AddLeaderElection(); // builder.AddStateStore(); if (publisherOptions.UseFileChangePolling == true) { builder.Configure(options => options.FileSystemPollingInterval = TimeSpan.FromSeconds(5)); } builder.RegisterType().AsImplementedInterfaces(); if (publisherOptions.IsAzureIoTOperationsConnector.Value) { builder.RegisterInstance(new HybridLogicalClock( DateTime.UtcNow, 0, publisherOptions.PublisherId)) .AsSelf().SingleInstance(); builder.RegisterType() .AsSelf().AsImplementedInterfaces().SingleInstance(); } } } /// /// Add Event Hubs client /// /// /// public static void AddEventHubsClient(this ContainerBuilder builder, IConfiguration configuration) { // Validate edge configuration var eventHubsOptions = new EventHubsClientOptions(); new EventHubs(configuration).Configure(eventHubsOptions); if (eventHubsOptions.ConnectionString != null) { builder.AddHubEventClient(); builder.RegisterType() .AsImplementedInterfaces(); } } /// /// Add file system client /// /// /// public static void AddFileSystemEventClient(this ContainerBuilder builder, IConfiguration configuration) { var fsOptions = new FileSystemEventClientOptions(); new FileSystem(configuration).Configure(fsOptions); if (fsOptions.OutputFolder != null) { builder.AddFileSystemEventClient(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); } } /// /// Add file system rpc server /// /// /// public static void AddFileSystemRpcServer(this ContainerBuilder builder, IConfiguration configuration) { var fsOptions = new FileSystemRpcServerOptions(); new FileSystem(configuration).Configure(fsOptions); if (fsOptions.RequestFilePath != null) { builder.AddFileSystemRpcServer(); builder.RegisterType() .AsImplementedInterfaces(); } } /// /// Add http event client /// /// /// public static void AddHttpEventClient(this ContainerBuilder builder, IConfiguration configuration) { var httpOptions = new HttpEventClientOptions(); new Http(configuration).Configure(httpOptions); if (httpOptions.HostName != null) { builder.AddHttpEventClient(); builder.RegisterType() .AsImplementedInterfaces(); } } /// /// Add dapr client /// /// /// public static void AddDaprPubSubClient(this ContainerBuilder builder, IConfiguration configuration) { var daprOptions = new DaprOptions(); new Dapr(configuration).Configure(daprOptions); if (!string.IsNullOrWhiteSpace(daprOptions.PubSubComponent)) { builder.AddDaprPubSubClient(); builder.RegisterType() .AsImplementedInterfaces(); } } /// /// Add dapr client /// /// /// public static void AddDaprStateStoreClient(this ContainerBuilder builder, IConfiguration configuration) { var daprOptions = new DaprOptions(); new Dapr(configuration).Configure(daprOptions); if (!string.IsNullOrWhiteSpace(daprOptions.StateStoreName)) { builder.AddDaprStateStoreClient(); builder.RegisterType() .AsImplementedInterfaces(); } } /// /// Use prometheus endpoint /// /// /// public static IApplicationBuilder UseOpenTelemetryPrometheusEndpoint(this IApplicationBuilder app) { if (app.ApplicationServices.GetService()?.AddPrometheusEndpoint == true) { app.UseOpenTelemetryPrometheusScrapingEndpoint(); } return app; } /// /// Add open api /// /// public static IServiceCollection AddOpenApi(this IServiceCollection services) { return services .AddSingleton, OpenApi>() .AddSingleton, OpenApi>() .AddSwagger(Constants.EntityTypePublisher, string.Empty); } /// /// Use open api /// /// public static IApplicationBuilder UseOpenApi(this IApplicationBuilder builder) { var options = builder.ApplicationServices.GetService>(); if (options?.Value.DisableOpenApiEndpoint != true) { return builder.UseSwagger(); } return builder; } /// /// Add open telemetry to the logging builder /// /// /// /// public static ILoggingBuilder AddOpenTelemetry(this ILoggingBuilder builder, IConfiguration configuration, Action configure) { var configurator = new Otel(configuration); if (configurator.EnableOtelLogging) { builder.Services.AddOtel(); builder.AddOpenTelemetry(options => { configure(options); options.AddOtlpExporter((o, _) => configurator.Configure("Logging", o)); }); } return builder; } /// /// Enable tracing if tracing enabled /// /// /// /// /// public static OpenTelemetryBuilder WithTracing(this OpenTelemetryBuilder builder, IConfiguration configuration, Action configure) { var configurator = new Otel(configuration); if (configurator.EnableOtelTraces) { return builder.WithTracing(options => { options.ConfigureServices(services => services.AddOtel()); options.AddOtlpExporter(o => configurator.Configure("Traces", o)); if (configurator.AddRuntimeInstrumentation) { options = options .AddHttpClientInstrumentation() .AddAspNetCoreInstrumentation(); } configure(options); }); } return builder; } /// /// Enable tracing if tracing enabled /// /// /// /// /// public static OpenTelemetryBuilder WithMetrics(this OpenTelemetryBuilder builder, IConfiguration configuration, Action configure) { var configurator = new Otel(configuration); if (configurator.AddPrometheusEndpoint || configurator.EnableOtelMetrics || configurator.AddRuntimeInstrumentation) // We use runtime instrumentation for diagnostics { return builder.WithMetrics(options => { options.ConfigureServices(services => services.AddOtel()); if (configurator.AddPrometheusEndpoint) { options.SetMaxMetricStreams(configurator.MaxMetricStreams); options.AddPrometheusExporter(o => { o.DisableTotalNameSuffixForCounters = !configurator.EnableTotalNameSuffixForCounters; // // Configures scrape endpoint response caching. Multiple scrape requests // within the cache duration time period will receive the same previously // generated response. Disable response caching. The default value is 300. // o.ScrapeResponseCacheDurationMilliseconds = 0; }); if (configurator.AddRuntimeInstrumentation) { options = options .AddHttpClientInstrumentation() .AddAspNetCoreInstrumentation(); } } if (configurator.EnableOtelMetrics) { options = options .SetMaxMetricStreams(configurator.MaxMetricStreams) .AddOtlpExporter(o => configurator.Configure("Metrics", o)); if (configurator.AddRuntimeInstrumentation) { options = options .AddHttpClientInstrumentation() .AddAspNetCoreInstrumentation(); } } if (configurator.AddRuntimeInstrumentation) { options = options.AddRuntimeInstrumentation(); } configure(options); }); } return builder; } /// /// Adds secrets from a env file that is located at $ADDITIONAL_CONFIGURATION /// Defaults to .env file in docker /run/secrets folder. /// /// public static IConfigurationBuilder AddSecrets(this IConfigurationBuilder builder) { try { return builder.Add(new DotEnvFileSource( Environment.GetEnvironmentVariable("ADDITIONAL_CONFIGURATION") ?? "/run/secrets/.env")); } catch (UnauthorizedAccessException) { return builder; } } /// /// Add connector configuration /// /// /// public static IConfigurationBuilder AddConnectorAdditionalConfiguration( this IConfigurationBuilder builder) { var connectorConfigMountPath = Environment.GetEnvironmentVariable( Azure.Iot.Operations.Connector.ConnectorConfigurations. ConnectorFileMountSettings.ConnectorConfigMountPathEnvVar); if (string.IsNullOrEmpty(connectorConfigMountPath)) { return builder; } var additionalConfiguration = Path.Combine(connectorConfigMountPath, "ADDITIONAL_CONNECTOR_CONFIGURATION"); var diagnostics = Path.Combine(connectorConfigMountPath, Azure.Iot.Operations.Connector.ConnectorConfigurations. ConnectorFileMountSettings.ConnectorDiagnosticsConfigFileName); return builder .AddJsonFile(diagnostics, optional: true, reloadOnChange: true) .AddJsonFile(additionalConfiguration, optional: true, reloadOnChange: true); } /// /// Add obs configuration /// /// /// private static IServiceCollection AddOtel(this IServiceCollection services) { return services .AddSingleton() .AddSingleton>( services => services.GetRequiredService()) .AddSingleton>( services => services.GetRequiredService()) ; } /// /// Otel configuration from environment /// internal sealed class Otel : ConfigureOptionBase { public const string EnableMetricsKey = "EnableMetrics"; public const string EnableOtelLoggingKey = "EnableOtelLogging"; public const string EnableOtelTracesKey = "EnableOtelTraces"; public const string OtlpCollectorEndpointKey = "OtlpCollectorEndpoint"; public const string OtlpMaxMetricStreamsKey = "OtlpMaxMetricStreams"; public const string OtlpExportIntervalMillisecondsKey = "OtlpExportIntervalMilliseconds"; public const string OtlpRuntimeInstrumentationKey = "OtlpRuntimeInstrumentation"; public const string OtlpTotalNameSuffixForCountersKey = "OtlpTotalNameSuffixForCounters"; public const int OtlpExportIntervalMillisecondsDefault = 15000; public const int OtlpMaxMetricDefault = 4000; public const bool OtlpRuntimeInstrumentationDefault = false; public const bool OtlpTotalNameSuffixForCountersDefault = false; /// /// Add runtime instrumentation /// public bool AddRuntimeInstrumentation => GetBoolOrDefault(OtlpRuntimeInstrumentationKey, OtlpRuntimeInstrumentationDefault); /// /// Otlp collector endpoint /// public string OTlpMetricsEndpoint => GetStringOrDefault(OtlpCollectorEndpointKey, GetStringOrDefault("OTLP_GRPC_METRIC_ENDPOINT", GetStringOrDefault("OTLP_HTTP_METRIC_ENDPOINT", string.Empty))); /// /// Otlp collector endpoint /// public string OTlpTracesEndpoint => GetStringOrDefault(OtlpCollectorEndpointKey, GetStringOrDefault("OTLP_GRPC_TRACE_ENDPOINT", GetStringOrDefault("OTLP_HTTP_TRACE_ENDPOINT", string.Empty))); /// /// Otlp collector endpoint /// public string OTlpLogEndpoint => GetStringOrDefault(OtlpCollectorEndpointKey, GetStringOrDefault("OTLP_GRPC_LOG_ENDPOINT", GetStringOrDefault("OTLP_HTTP_LOG_ENDPOINT", string.Empty))); /// /// Enable otel or prometheus metrics /// public bool EnableMetrics => GetBoolOrDefault(EnableMetricsKey); /// /// Use prometheus /// public bool AddPrometheusEndpoint => GetBoolOrDefault(EnableMetricsKey) && string.IsNullOrEmpty(OTlpMetricsEndpoint); /// /// Use otel metrics exporter /// public bool EnableOtelMetrics => GetBoolOrDefault(EnableMetricsKey) && !string.IsNullOrEmpty(OTlpMetricsEndpoint); /// /// Logging over otel enabled and endpoint configured /// public bool EnableOtelLogging => GetBoolOrDefault(EnableOtelLoggingKey) && !string.IsNullOrEmpty(OTlpLogEndpoint); /// /// Traces over otel /// public bool EnableOtelTraces => GetBoolOrDefault(EnableOtelTracesKey) && !string.IsNullOrEmpty(OTlpTracesEndpoint); /// /// Max metrics to collect, the default in otel is 1000 /// public int MaxMetricStreams => Math.Max(1, GetIntOrDefault(OtlpMaxMetricStreamsKey, OtlpMaxMetricDefault)); /// /// Enable total suffix /// public bool EnableTotalNameSuffixForCounters => GetBoolOrDefault(OtlpTotalNameSuffixForCountersKey, OtlpTotalNameSuffixForCountersDefault); /// public void Configure(string? name, OtlpExporterOptions options) { var endpoint = name switch { "Metrics" => OTlpMetricsEndpoint, "Traces" => OTlpTracesEndpoint, "Logging" => OTlpLogEndpoint, _ => null, }; if (!string.IsNullOrEmpty(endpoint) && Uri.TryCreate(endpoint, UriKind.RelativeOrAbsolute, out var uri)) { options.Endpoint = new UriBuilder(uri) { Scheme = Uri.UriSchemeHttp }.Uri; } } /// public override void Configure(string? name, MetricReaderOptions options) { options.PeriodicExportingMetricReaderOptions = new PeriodicExportingMetricReaderOptions { ExportIntervalMilliseconds = GetIntOrDefault( OtlpExportIntervalMillisecondsKey, GetIntOrDefault("OTLP_METRIC_EXPORT_INTERVAL_3P", OtlpExportIntervalMillisecondsDefault)) }; } /// /// Create otlp configuration /// /// public Otel(IConfiguration configuration) : base(configuration) { } } /// /// Configure kestrel setup /// internal sealed class Kestrel : ConfigureOptionBase { /// /// Create kestrel configuration /// /// /// /// public Kestrel(ISslCertProvider certificates, IOptions options, IConfiguration configuration) : base(configuration) { _certificates = certificates; _options = options; } /// public override void Configure(string? name, KestrelServerOptions options) { if (_options.Value.UnsecureHttpServerPort != null) { options.ListenAnyIP(_options.Value.UnsecureHttpServerPort.Value); } if (_options.Value.HttpServerPort != null) { options.Listen(IPAddress.Any, _options.Value.HttpServerPort.Value, listenOptions => listenOptions.UseHttps(httpsOptions => httpsOptions .ServerCertificateSelector = (_, _) => _certificates.Certificate)); } } private readonly IOptions _options; private readonly ISslCertProvider _certificates; } /// /// Configure logger filter /// internal sealed class LoggingLevel : ConfigureOptionBase { /// /// Configuration /// public const string LogLevelKey = "LogLevel"; /// public override void Configure(string? name, LoggerFilterOptions options) { var levelString = GetStringOrDefault(LogLevelKey); if (!string.IsNullOrEmpty(levelString)) { if (Enum.TryParse(levelString, true, out var ll)) { options.MinLevel = ll; } else { // Compatibilty with serilog switch (levelString) { case "Verbose": options.MinLevel = LogLevel.Trace; break; case "Fatal": options.MinLevel = LogLevel.Critical; break; } } // Use command line configuration only return; } // Get diagnostic config from { logs: { level: x } } levelString = GetStringOrDefault("logs:level"); if (string.IsNullOrEmpty(levelString)) { return; } switch (levelString.ToLowerInvariant()) { case "trace": options.MinLevel = LogLevel.Trace; return; case "debug": options.MinLevel = LogLevel.Debug; return; case "info": options.MinLevel = LogLevel.Information; return; case "warn": options.MinLevel = LogLevel.Warning; return; case "error": options.MinLevel = LogLevel.Error; return; case "none": options.MinLevel = LogLevel.None; return; } // Since it is free form, try to adapt to .net log level names if (Enum.TryParse(levelString, true, out var logLevel)) { options.MinLevel = logLevel; } } /// /// Create logging configurator /// /// public LoggingLevel(IConfiguration configuration) : base(configuration) { } } /// /// Logging format /// internal class LoggingFormat : PostConfigureOptionBase { /// /// Supported formats /// public static readonly string[] LogFormatsSupported = [ ConsoleFormatterNames.Simple, Syslog.FormatterName, ConsoleFormatterNames.Systemd ]; /// /// Configuration /// public const string LogFormatKey = "LogFormat"; /// /// Default format /// public const string LogFormatDefault = ConsoleFormatterNames.Simple; /// public override void PostConfigure(string? name, ConsoleLoggerOptions options) { switch (GetStringOrDefault(LogFormatKey)) { case Syslog.FormatterName: options.FormatterName = Syslog.FormatterName; break; case ConsoleFormatterNames.Systemd: options.FormatterName = ConsoleFormatterNames.Systemd; break; case ConsoleFormatterNames.Simple: options.FormatterName = ConsoleFormatterNames.Simple; break; default: options.FormatterName = LogFormatDefault; break; } } /// /// Create logging configurator /// /// public LoggingFormat(IConfiguration configuration) : base(configuration) { } } /// /// Logging format /// /// internal sealed class ConsoleLogging : LoggingFormat, IConfigureOptions, IConfigureNamedOptions where T : ConsoleFormatterOptions { /// public void Configure(string? name, T options) { options.TimestampFormat = "[yy-MM-dd HH:mm:ss.ffff] "; options.IncludeScopes = true; options.UseUtcTimestamp = true; } /// public void Configure(T options) { Configure(null, options); } /// /// Create logging configurator /// /// public ConsoleLogging(IConfiguration configuration) : base(configuration) { } } /// /// Configure the method router /// internal sealed class Router : PostConfigureOptionBase { /// /// Create configuration /// /// /// public Router(IConfiguration configuration, IOptions options) : base(configuration) { _options = options; } /// public override void PostConfigure(string? name, RouterOptions options) { options.MountPoint ??= new TopicBuilder(_options.Value).MethodTopic; } private readonly IOptions _options; } /// /// Configure the Dapr event client /// internal sealed class Dapr : ConfigureOptionBase { public const string PubSubComponentKey = "PubSubComponent"; public const string StateStoreKey = "StateStore"; public const string HttpPortKey = "HttpPort"; public const string GrpcPortKey = "GrpcPort"; public const string SchemeKey = "Scheme"; public const string HostKey = "Host"; public const string CheckSideCarHealthKey = "CheckSideCarHealth"; public const string DaprConnectionStringKey = "DaprConnectionString"; /// public override void Configure(string? name, DaprOptions options) { var daprConnectionString = GetStringOrDefault(DaprConnectionStringKey); if (daprConnectionString != null) { options.PubSubComponent = null; options.StateStoreName = null; var properties = ToDictionary(daprConnectionString); if (properties.TryGetValue(PubSubComponentKey, out var component)) { options.PubSubComponent = component; } if (properties.TryGetValue(StateStoreKey, out var stateStore)) { options.StateStoreName = stateStore; } // Select the scheme, default to http (side car) if (!properties.TryGetValue(SchemeKey, out var scheme)) { scheme = "http"; } // Select the host, default to localhost if (!properties.TryGetValue(HostKey, out var host)) { host = "localhost"; } // Check whether to check side car health if (properties.TryGetValue(CheckSideCarHealthKey, out var value) && bool.TryParse(value, out var check)) { options.CheckSideCarHealthBeforeAccess = check; } // Permit the port to be set if provided, otherwise use defaults. if (properties.TryGetValue(GrpcPortKey, out value) && int.TryParse(value, CultureInfo.InvariantCulture, out var port)) { options.GrpcEndpoint = scheme + "://" + host + ":" + port; } if (properties.TryGetValue(HttpPortKey, out value) && int.TryParse(value, CultureInfo.InvariantCulture, out port)) { options.HttpEndpoint = scheme + "://" + host + ":" + port; } } else { options.PubSubComponent ??= GetStringOrDefault(PubSubComponentKey); options.StateStoreName ??= GetStringOrDefault(StateStoreKey); } // The api token should be part of the environment if dapr is supported options.ApiToken ??= GetStringOrDefault(EnvironmentVariable.DAPRAPITOKEN); } /// /// Create configuration /// /// public Dapr(IConfiguration configuration) : base(configuration) { } } /// /// Configure the http event client /// internal sealed class Http : ConfigureOptionBase { public const string HttpConnectionStringKey = "HttpConnectionString"; public const string WebHookHostUrlKey = "WebHookHostUrl"; public const string HostNameKey = "HostName"; public const string PortKey = "Port"; public const string SchemeKey = "Scheme"; public const string PutKey = "Put"; /// public override void Configure(string? name, HttpEventClientOptions options) { var httpConnectionString = GetStringOrDefault(HttpConnectionStringKey); if (httpConnectionString != null) { var properties = ToDictionary(httpConnectionString); if (properties.TryGetValue(HostNameKey, out var value)) { options.HostName = value; } // Permit the port to be set if provided, otherwise use defaults. if (properties.TryGetValue(PortKey, out value) && int.TryParse(value, CultureInfo.InvariantCulture, out var port)) { options.Port = port; } if (properties.TryGetValue(SchemeKey, out value) && value.Equals("http", StringComparison.OrdinalIgnoreCase)) { options.UseHttpScheme = true; } if (properties.TryGetValue(PutKey, out _)) { options.UseHttpPutMethod = true; } } else { var url = GetStringOrDefault(WebHookHostUrlKey); if (!string.IsNullOrEmpty(url) && Uri.TryCreate(url, UriKind.Absolute, out var uri)) { options.HostName = uri.Host; options.Port = uri.Port; options.UseHttpScheme = uri.Scheme == Uri.UriSchemeHttp; } } } /// /// Create configuration /// /// public Http(IConfiguration configuration) : base(configuration) { } } /// /// Open api configuration /// internal sealed class OpenApi : ConfigureOptionBase { public const string UseOpenApiV3Key = "UseOpenApiV3"; /// public override void Configure(string? name, OpenApiOptions options) { options.SchemaVersion = GetBoolOrDefault(UseOpenApiV3Key) ? 3 : 2; options.ProjectUri = new Uri("https://www.github.com/Azure/Industrial-IoT"); options.License = new OpenApiLicense { Name = "MIT LICENSE", Url = new Uri("https://opensource.org/licenses/MIT") }; } /// /// Create configuration /// /// public OpenApi(IConfiguration configuration) : base(configuration) { } } /// /// Configure the file based event client /// internal sealed class FileSystem : ConfigureOptionBase, IConfigureOptions, IConfigureNamedOptions { public const string OutputRootKey = "OutputRoot"; public const string InitFilePathKey = "InitFilePath"; public const string InitLogFileKey = "InitLogFile"; /// public void Configure(FileSystemRpcServerOptions options) { Configure(null, options); } /// public void Configure(string? name, FileSystemRpcServerOptions options) { var publishedNodesFile = GetStringOrDefault( PublisherConfig.PublishedNodesFileKey); var rootFolder = Path.GetDirectoryName(publishedNodesFile) ?? Environment.CurrentDirectory; options.RequestFilePath ??= GetStringOrDefault(InitFilePathKey); if (options.RequestFilePath == null) { return; } if (options.RequestFilePath.Trim().Length == 0) { // We use pn.json file path and publishednodes.init file name options.RequestFilePath = Path.Combine(rootFolder, "publishednodes.init"); } // Just file? else if (string.IsNullOrEmpty( Path.GetDirectoryName(options.RequestFilePath))) { options.RequestFilePath = Path.Combine(rootFolder, options.RequestFilePath!); } options.ResponseFilePath ??= GetStringOrDefault(InitLogFileKey); if (options.ResponseFilePath == null && options.RequestFilePath != null) { options.ResponseFilePath = options.RequestFilePath + ".log"; } // Just file? else if (string.IsNullOrEmpty( Path.GetDirectoryName(options.ResponseFilePath))) { options.ResponseFilePath = Path.Combine(Path.GetDirectoryName( options.RequestFilePath) ?? Environment.CurrentDirectory, options.ResponseFilePath!); } } /// public override void Configure(string? name, FileSystemEventClientOptions options) { options.OutputFolder ??= GetStringOrDefault(OutputRootKey); } /// /// Create configuration /// /// public FileSystem(IConfiguration configuration) : base(configuration) { } } /// /// Configure mqtt broker /// internal sealed class MqttBroker : ConfigureOptionBase { /// /// Configuration /// public const string MqttClientConnectionStringKey = "MqttClientConnectionString"; public const string ClientPartitionsKey = "MqttClientPartitions"; public const string KeepAlivePeriodKey = "MqttBrokerKeepAlivePeriod"; public const string ClientIdKey = "MqttClientId"; public const string UserNameKey = "MqttBrokerUserName"; public const string PasswordKey = "MqttBrokerPasswordKey"; public const string HostNameKey = "MqttBrokerHostName"; public const string HostPortKey = "MqttBrokerPort"; public const string ProtocolKey = "MqttProtocolVersion"; public const string UseTlsKey = "MqttBrokerUsesTls"; /// public override void Configure(string? name, MqttOptions options) { var mqttClientConnectionString = GetStringOrDefault(MqttClientConnectionStringKey); if (mqttClientConnectionString != null) { var properties = ToDictionary(mqttClientConnectionString); if (properties.TryGetValue(nameof(options.HostName), out var value)) { options.HostName = value; } if (properties.TryGetValue(nameof(options.Port), out value) && int.TryParse(value, CultureInfo.InvariantCulture, out var port)) { options.Port = port; } if (properties.TryGetValue(nameof(options.UserName), out value)) { options.UserName = value; } if (properties.TryGetValue(nameof(options.Password), out value)) { options.Password = value; } if (properties.TryGetValue(nameof(options.Protocol), out value) && Enum.TryParse(value, true, out var version)) { options.Protocol = version; } if (properties.TryGetValue(nameof(options.UseTls), out value) && bool.TryParse(value, out var useTls)) { options.UseTls = useTls; } if (properties.TryGetValue(nameof(options.KeepAlivePeriod), out value) && TimeSpan.TryParse(value, out var keepAlive)) { options.KeepAlivePeriod = keepAlive; } if (properties.TryGetValue("Partitions", out value) && int.TryParse(value, out var partitions)) { options.NumberOfClientPartitions = partitions; } } else { if (string.IsNullOrEmpty(options.HostName)) { options.ClientId = GetStringOrDefault(HostNameKey); } if (string.IsNullOrEmpty(options.UserName)) { options.UserName = GetStringOrDefault(UserNameKey); } if (string.IsNullOrEmpty(options.Password)) { options.Password = GetStringOrDefault(PasswordKey); } options.Port ??= GetIntOrNull(HostPortKey); if (Enum.TryParse(GetStringOrDefault(ProtocolKey), true, out var version)) { options.Protocol = version; } options.UseTls ??= GetBoolOrNull(UseTlsKey); options.NumberOfClientPartitions ??= GetIntOrNull(ClientPartitionsKey); if (options.KeepAlivePeriod == null) { options.KeepAlivePeriod = GetDurationOrNull(KeepAlivePeriodKey); } } if (string.IsNullOrEmpty(options.ClientId)) { options.ClientId = GetStringOrDefault(ClientIdKey); } } /// /// Transport configuration /// /// public MqttBroker(IConfiguration configuration) : base(configuration) { } } /// /// Avro file writer configuration /// internal sealed class AvroWriter : ConfigureOptionBase { public const string DisableKey = "DisableAvroFileWriter"; public override void Configure(string? name, AvroFileWriterOptions options) { options.Disabled = GetBoolOrDefault(DisableKey); } /// /// Transport configuration /// /// public AvroWriter(IConfiguration configuration) : base(configuration) { } } /// /// Console file writer configuration /// internal sealed class ConsoleWriter : ConfigureOptionBase { public const string EnableKey = "EnableConsoleWriter"; public override void Configure(string? name, ConsoleWriterOptions options) { options.Enabled = GetBoolOrDefault(EnableKey); } /// /// Transport configuration /// /// public ConsoleWriter(IConfiguration configuration) : base(configuration) { } } /// /// Configure schema topic templates /// internal sealed class SchemaTopicBuilder : ConfigureOptionBase { /// public override void Configure(string? name, MqttOptions options) { if (_options.Value.SchemaOptions != null && _options.Value.TopicTemplates.Schema != null) { options.ConfigureSchemaMessage = message => { // // Set the telemetry topic template to the passed // in message topic // var templates = new TopicTemplatesOptions { Telemetry = message.Topic }; message.Topic = new TopicBuilder(_options.Value, templates: templates).SchemaTopic; }; } } /// public SchemaTopicBuilder(IConfiguration configuration, IOptions options) : base(configuration) { _options = options; } private readonly IOptions _options; } /// /// Configure edge client /// internal sealed class IoTEdge : ConfigureOptionBase { /// /// Configuration /// public const string HubTransport = "Transport"; public const string UpstreamProtocol = "UpstreamProtocol"; public const string EdgeHubConnectionString = "EdgeHubConnectionString"; /// public override void Configure(string? name, IoTEdgeClientOptions options) { if (string.IsNullOrEmpty(options.EdgeHubConnectionString)) { options.EdgeHubConnectionString = GetStringOrDefault(EdgeHubConnectionString); } if (options.EdgeHubConnectionString == null && Environment.GetEnvironmentVariable("IOTEDGE_DEVICEID") != null) { options.EdgeHubConnectionString = string.Empty; } if (options.Transport == TransportOption.None) { if (Enum.TryParse(GetStringOrDefault(HubTransport), out var transport) || Enum.TryParse(GetStringOrDefault(UpstreamProtocol), out transport)) { options.Transport = transport; } } options.Product = $"OpcPublisher_{GetType().Assembly.GetReleaseVersion()}"; } /// /// Transport configuration /// /// public IoTEdge(IConfiguration configuration) : base(configuration) { } } /// /// Configure Azure IoT Operations integration /// internal sealed class Aio : ConfigureOptionBase { /// /// Configuration /// public const string BrokerHostName = "AIO_BROKER_HOSTNAME"; public const string ConnectorId = "CONNECTOR_ID"; public const string DiscoveredDeviceEndpointTypeKey = "AioDiscoveredDeviceEndpointType"; public const string DiscoveredDeviceEndpointTypeVersionKey = "AioDiscoveredDeviceEndpointTypeVersion"; public const string NetworkDiscoveryModeKey = "AioNetworkDiscoveryMode"; public const string NetworkDiscoveryIntervalKey = "AioNetworkDiscoveryInterval"; public const string NetworkDiscoveryAddressRangesToScanKey = "AioNetworkDiscoveryAddressRangesToScan"; public const string NetworkDiscoveryNetworkProbeTimeoutKey = "AioNetworkDiscoveryNetworkProbeTimeout"; public const string NetworkDiscoveryMaxNetworkProbesKey = "AioNetworkDiscoveryMaxNetworkProbes"; public const string NetworkDiscoveryPortRangesToScanKey = "AioNetworkDiscoveryPortRangesToScan"; public const string NetworkDiscoveryPortProbeTimeoutKey = "AioNetworkDiscoveryPortProbeTimeout"; public const string NetworkDiscoveryMaxPortProbesKey = "AioNetworkDiscoveryMaxPortProbes"; /// public override void Configure(string? name, PublisherOptions options) { if (!KubernetesClientConfiguration.IsInCluster()) { return; } var connectorId = GetStringOrDefault(ConnectorId); if (string.IsNullOrEmpty(connectorId)) { return; } // Set default connector operations mode options.IsAzureIoTOperationsConnector = true; options.UseStandardsCompliantEncoding = true; options.EnableCloudEvents = true; options.DiagnosticsTarget = Models.PublisherDiagnosticTargetType.Events; options.EnableRuntimeStateReporting = true; options.AllowedEventAndDiagnosticsTransports.Add( Models.WriterGroupTransport.AioMqtt); options.SchemaOptions = new SchemaOptions(); options.RuntimeStateRoutingInfo = "status"; options.PublisherId = connectorId; options.AioDiscoveredDeviceEndpointType = GetStringOrDefault(DiscoveredDeviceEndpointTypeKey); options.AioDiscoveredDeviceEndpointTypeVersion = GetStringOrDefault(DiscoveredDeviceEndpointTypeVersionKey); var discoveryMode = GetStringOrDefault(NetworkDiscoveryModeKey); if (Enum.TryParse(discoveryMode, true, out var mode)) { options.AioNetworkDiscoveryMode = mode; } options.AioNetworkDiscoveryInterval = GetDurationOrNull(NetworkDiscoveryIntervalKey, TimeSpan.FromHours(12)); options.AioNetworkDiscovery.AddressRangesToScan = GetStringOrDefault(NetworkDiscoveryAddressRangesToScanKey); options.AioNetworkDiscovery.NetworkProbeTimeout = GetDurationOrNull(NetworkDiscoveryNetworkProbeTimeoutKey); options.AioNetworkDiscovery.MaxNetworkProbes = GetIntOrNull(NetworkDiscoveryMaxNetworkProbesKey); options.AioNetworkDiscovery.PortRangesToScan = GetStringOrDefault(NetworkDiscoveryPortRangesToScanKey); options.AioNetworkDiscovery.PortProbeTimeout = GetDurationOrNull(NetworkDiscoveryPortProbeTimeoutKey); options.AioNetworkDiscovery.MaxPortProbes = GetIntOrNull(NetworkDiscoveryMaxPortProbesKey); options.UseFileChangePolling = GetBoolOrNull(PublisherConfig.UseFileChangePollingKey); } /// /// Create configuration /// /// public Aio(IConfiguration configuration) : base(configuration) { } } /// /// Configure event hub client /// internal sealed class EventHubs : ConfigureOptionBase { /// /// Configuration /// public const string SchemaGroupNameKey = "SchemaGroupName"; public const string EventHubNamespaceConnectionString = "EventHubNamespaceConnectionString"; /// public override void Configure(string? name, EventHubsClientOptions options) { if (string.IsNullOrEmpty(options.ConnectionString)) { options.ConnectionString = GetStringOrDefault(EventHubNamespaceConnectionString); } var schemaGroupName = GetStringOrDefault(SchemaGroupNameKey); if (!string.IsNullOrEmpty(schemaGroupName)) { options.SchemaRegistry = new SchemaRegistryOptions { FullyQualifiedNamespace = string.Empty, // TODO: Remove SchemaGroupName = schemaGroupName }; } } /// /// Transport configuration /// /// public EventHubs(IConfiguration configuration) : base(configuration) { } } /// /// Parse connection string as dictionary /// /// /// /// /// /// /// private static Dictionary ToDictionary(string valuePairString, char kvpDelimiter = ';', char kvpSeparator = '=') { if (string.IsNullOrWhiteSpace(valuePairString)) { throw new ArgumentException("Malformed Token"); } valuePairString = valuePairString.Trim(';'); // This regex allows semi-colons to be part of the allowed characters // for device names. Although new devices are not // allowed to have semi-colons in the name, some legacy devices still // have them and so this name validation cannot be changed. var parts = new Regex($"(?:^|{kvpDelimiter})([^{kvpDelimiter}{kvpSeparator}]*){kvpSeparator}") .Matches(valuePairString) .Cast() .Select(m => new string[] { m.Result("$1"), valuePairString[ (m.Index + m.Value.Length)..(m.NextMatch().Success ? m.NextMatch().Index : valuePairString.Length)] }) .ToList(); if (parts.Count == 0 || parts.Any(p => p.Length != 2)) { throw new FormatException("Malformed Token"); } return parts.ToDictionary(kvp => kvp[0], (kvp) => kvp[1], StringComparer.OrdinalIgnoreCase); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/src/Runtime/Security.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Runtime { using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System; using System.Net.Http.Headers; using System.Security.Claims; using System.Text.Encodings.Web; using System.Threading.Tasks; /// /// Security configuration /// internal static class Security { /// /// Api key scheme /// public const string ApiKeyScheme = "ApiKey"; /// /// Use api key handler /// /// /// public static AuthenticationBuilder UsingConfiguredApiKey(this AuthenticationBuilder builder) { builder.Services.AddHttpContextAccessor(); builder.Services.AddAuthentication(ApiKeyScheme) .AddScheme(ApiKeyScheme, null); return builder; } /// /// Api key authentication handler /// internal sealed class ApiKeyHandler : AuthenticationHandler { /// /// Create authentication handler /// /// /// /// /// /// public ApiKeyHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, IHttpContextAccessor context, IApiKeyProvider apiKeyProvider) : base(options, logger, encoder) { _context = context; _apiKeyProvider = apiKeyProvider; } /// protected override Task HandleAuthenticateAsync() { var httpContext = _context.HttpContext; if (httpContext == null) { return Task.FromResult(AuthenticateResult.Fail( "No request.")); } var authorization = httpContext.Request.Headers.Authorization; if (authorization.Count == 0 || string.IsNullOrEmpty(authorization[0])) { return Task.FromResult(AuthenticateResult.Fail( "Missing Authorization header.")); } try { var header = AuthenticationHeaderValue.Parse(authorization[0]!); if (header.Scheme != ApiKeyScheme) { return Task.FromResult(AuthenticateResult.NoResult()); } if (_apiKeyProvider.ApiKey != header.Parameter?.Trim()) { throw new UnauthorizedAccessException(); } var claims = new[] { new Claim(ClaimTypes.NameIdentifier, ApiKeyScheme) }; var identity = new ClaimsIdentity(claims, Scheme.Name); var principal = new ClaimsPrincipal(identity); var ticket = new AuthenticationTicket(principal, Scheme.Name); return Task.FromResult(AuthenticateResult.Success(ticket)); } catch (Exception ex) { return Task.FromResult(AuthenticateResult.Fail(ex)); } } private readonly IHttpContextAccessor _context; private readonly IApiKeyProvider _apiKeyProvider; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/src/Runtime/Syslog.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Runtime { using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Console; using Microsoft.Extensions.Options; using System; using System.Globalization; using System.IO; using System.Text; /// /// Logging formatter compatible with syslogs format. /// public sealed class Syslog : ConsoleFormatter, IDisposable { /// /// The default timestamp format for all IoT compatible logging events.. /// public const string DefaultTimestampFormat = "yyyy-MM-ddTHH:mm:ss.fffZ "; /// /// Name of the formatter /// public const string FormatterName = "syslog"; /// /// Initializes a new instance of the class. /// /// public Syslog(IOptionsMonitor options) : base(FormatterName) { _optionsReloadToken = options.OnChange(opt => { _options = opt; _includeScopes = opt.IncludeScopes; }); _options = options.CurrentValue; _serviceId = "opcpublisher@311"; _timestampFormat = DefaultTimestampFormat; _includeScopes = _options.IncludeScopes; } /// public override void Write(in LogEntry logEntry, IExternalScopeProvider? scopeProvider, TextWriter textWriter) { var message = logEntry.Formatter?.Invoke(logEntry.State, logEntry.Exception); if (message is null) { return; } var messageBuilder = new StringBuilder(kInitialLength) .Append(kSyslogMap[(int)logEntry.LogLevel]) .Append(DateTimeOffset.UtcNow.ToString(_timestampFormat, CultureInfo.InvariantCulture)); if (_includeScopes && scopeProvider != null && !string.IsNullOrEmpty(_serviceId)) { messageBuilder.Append('[').Append(_serviceId); scopeProvider.ForEachScope((scope, state) => state.Append(' ').Append(scope), messageBuilder); messageBuilder.Append("] "); } messageBuilder.Append("- ").AppendLine(message); if (logEntry.Exception != null) { // TODO: syslog format does not support stack traces messageBuilder.AppendLine(logEntry.Exception.ToString()); } textWriter.Write(messageBuilder.ToString()); } /// public void Dispose() { _optionsReloadToken?.Dispose(); } private const int kInitialLength = 256; /// /// Map of to syslog severity. /// private static readonly string[] kSyslogMap = [ /* Trace */ "<7>", /* Debug */ "<7>", /* Info */ "<6>", /* Warn */ "<4>", /* Error */ "<3>", /* Crit */ "<3>" ]; private readonly IDisposable? _optionsReloadToken; private readonly string _timestampFormat; private readonly string _serviceId; private bool _includeScopes; private ConsoleFormatterOptions _options; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/src/Startup.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module { using Azure.IIoT.OpcUa.Publisher.Module.Runtime; using Autofac; using Autofac.Extensions.DependencyInjection; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Console; using OpenTelemetry.Logs; using OpenTelemetry.Metrics; using OpenTelemetry.Resources; using OpenTelemetry.Trace; using System; /// /// Webservice startup /// public class Startup { /// /// Configuration /// public IConfigurationRoot Configuration { get; } /// /// Create startup /// /// public Startup(IConfiguration configuration) { Configuration = new ConfigurationBuilder() .AddConfiguration(configuration) .AddFromDotEnvFile() .AddEnvironmentVariables() .Build(); // Set polling mode on file watcher if configured if (Configuration.GetValue(PublisherConfig.UseFileChangePollingKey)? .Equals("True", StringComparison.OrdinalIgnoreCase) ?? false) { Environment.SetEnvironmentVariable("DOTNET_USE_POLLING_FILE_WATCHER", "1"); } } /// /// Configure services /// /// /// public void ConfigureServices(IServiceCollection services) { services.AddLogging(options => options .AddDebug() .AddConsole() .AddConsoleFormatter() .AddOpenTelemetry(Configuration, options => { options.IncludeScopes = true; options.ParseStateValues = true; options.IncludeFormattedMessage = true; options.SetResourceBuilder(ResourceBuilder.CreateDefault() .AddTelemetrySdk() .AddService(Constants.EntityTypePublisher, default, GetType().Assembly.GetReleaseVersion().ToString())); })) ; services.AddHttpClient(); services.AddResourceMonitoring(Configuration); services.AddExceptionSummarizer(builder => { builder.AddDefaultProviders(); // TODO: Add opc ua exceptions }); services.AddRouting(); services.AddHealthChecks(); services.AddMemoryCache(); services.AddResponseCompression(options => options.EnableForHttps = true); services.AddAuthorization(); services.AddAuthentication() .UsingConfiguredApiKey() ; services.AddOpenTelemetry() .ConfigureResource(r => r .AddService(Constants.EntityTypePublisher, default, GetType().Assembly.GetReleaseVersion().ToString())) .WithTracing(Configuration, builder => builder .SetSampler(new AlwaysOnSampler()) .AddHttpClientInstrumentation() .AddAspNetCoreInstrumentation()) .WithMetrics(Configuration, builder => builder .AddMeter(Diagnostics.Meter.Name)) ; services.AddControllers() .AddJsonSerializer() .AddMessagePackSerializer() ; services.AddOpenApi(); } /// /// This method is called by the runtime, after the ConfigureServices /// method above and used to add middleware /// /// /// #pragma warning disable CA1822 // Mark members as static public void Configure(IApplicationBuilder app, IHostApplicationLifetime appLifetime) #pragma warning restore CA1822 // Mark members as static { app.UseRouting(); // app.UseHsts(); // app.UseHttpsRedirection(); app.UseResponseCompression(); app.UseAuthentication(); app.UseAuthorization(); app.UseOpenApi(); app.UseOpenTelemetryPrometheusEndpoint(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); endpoints.MapHealthChecks("/healthz"); }); var applicationContainer = app.ApplicationServices.GetAutofacRoot(); appLifetime.ApplicationStopped.Register(applicationContainer.Dispose); } /// /// Autofac configuration. /// /// public virtual void ConfigureContainer(ContainerBuilder builder) { // Register publisher services and transports builder.AddPublisherServices(); // // Order is important here because we want // to fall back in the reverse order for // sending operational and discovery events! // builder.AddMemoryKeyValueStore(); builder.AddDaprStateStoreClient(Configuration); builder.AddNullEventClient(); builder.AddFileSystemEventClient(Configuration); builder.AddFileSystemRpcServer(Configuration); builder.AddHttpEventClient(Configuration); builder.AddDaprPubSubClient(Configuration); builder.AddEventHubsClient(Configuration); builder.AddMqttClient(Configuration); builder.AddIoTEdgeServices(Configuration); builder.AddIoTOperationsServices(Configuration); // Register configuration interfaces builder.RegisterInstance(Configuration) .AsImplementedInterfaces(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Azure.IIoT.OpcUa.Publisher.Module.Tests.csproj ================================================  net9.0 aggressive all runtime; build; native; contentfiles; analyzers all runtime; build; native; contentfiles; analyzers; buildtransitive Always ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Clients/Adapters/DiscoveryApiAdapter.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ #nullable enable namespace Azure.IIoT.OpcUa.Publisher.Service.Clients.Adapters { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Sdk; using System; using System.Threading; using System.Threading.Tasks; /// /// Implements discovery services as adapter on top of discovery api. /// public sealed class DiscoveryApiAdapter : INetworkDiscovery, IServerDiscovery { /// /// Create adapter /// /// public DiscoveryApiAdapter(IDiscoveryApi client) { _client = client ?? throw new ArgumentNullException(nameof(client)); } /// public async Task RegisterAsync(ServerRegistrationRequestModel request, CancellationToken ct = default) { await _client.RegisterAsync(request, ct).ConfigureAwait(false); } /// public async Task DiscoverAsync(DiscoveryRequestModel request, CancellationToken ct = default) { await _client.DiscoverAsync(request, ct).ConfigureAwait(false); } /// public async Task CancelAsync(DiscoveryCancelRequestModel request, CancellationToken ct = default) { await _client.CancelAsync(request, ct).ConfigureAwait(false); } /// public async Task FindServerAsync( ServerEndpointQueryModel query, CancellationToken ct = default) { return await _client.FindServerAsync(query, ct).ConfigureAwait(false); } private readonly IDiscoveryApi _client; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Clients/Adapters/HistoryApiAdapter.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ #nullable enable namespace Azure.IIoT.OpcUa.Publisher.Service.Clients.Adapters { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Sdk; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; /// /// Adapts historian services to historic access services /// public sealed class HistoryApiAdapter : IHistoryServices { /// /// Create service /// /// public HistoryApiAdapter(IHistoryApi client) { _client = client ?? throw new ArgumentNullException(nameof(client)); } /// public Task HistoryDeleteEventsAsync(ConnectionModel endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { return _client.HistoryDeleteEventsAsync(endpoint, request, ct); } /// public Task HistoryDeleteValuesAtTimesAsync( ConnectionModel endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { return _client.HistoryDeleteValuesAtTimesAsync(endpoint, request, ct); } /// public Task HistoryDeleteModifiedValuesAsync( ConnectionModel endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { return _client.HistoryDeleteModifiedValuesAsync(endpoint, request, ct); } /// public Task HistoryDeleteValuesAsync( ConnectionModel endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { return _client.HistoryDeleteValuesAsync(endpoint, request, ct); } /// public Task HistoryReplaceEventsAsync( ConnectionModel endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { return _client.HistoryReplaceEventsAsync(endpoint, request, ct); } /// public Task HistoryReplaceValuesAsync( ConnectionModel endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { return _client.HistoryReplaceValuesAsync(endpoint, request, ct); } /// public Task HistoryInsertEventsAsync( ConnectionModel endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { return _client.HistoryInsertEventsAsync(endpoint, request, ct); } /// public Task HistoryInsertValuesAsync( ConnectionModel endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { return _client.HistoryInsertValuesAsync(endpoint, request, ct); } /// public Task HistoryUpsertEventsAsync( ConnectionModel endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { return _client.HistoryUpsertEventsAsync(endpoint, request, ct); } /// public Task HistoryUpsertValuesAsync( ConnectionModel endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { return _client.HistoryUpsertValuesAsync(endpoint, request, ct); } /// public async Task> HistoryReadEventsAsync( ConnectionModel endpoint, HistoryReadRequestModel request, CancellationToken ct) { return await _client.HistoryReadEventsAsync(endpoint, request, ct).ConfigureAwait(false); } /// public async Task> HistoryReadEventsNextAsync( ConnectionModel endpoint, HistoryReadNextRequestModel request, CancellationToken ct) { return await _client.HistoryReadEventsNextAsync(endpoint, request, ct).ConfigureAwait(false); } /// public async Task> HistoryReadValuesAsync( ConnectionModel endpoint, HistoryReadRequestModel request, CancellationToken ct) { return await _client.HistoryReadValuesAsync(endpoint, request, ct).ConfigureAwait(false); } /// public async Task> HistoryReadValuesAtTimesAsync( ConnectionModel endpoint, HistoryReadRequestModel request, CancellationToken ct) { return await _client.HistoryReadValuesAtTimesAsync(endpoint, request, ct).ConfigureAwait(false); } /// public async Task> HistoryReadProcessedValuesAsync( ConnectionModel endpoint, HistoryReadRequestModel request, CancellationToken ct) { return await _client.HistoryReadProcessedValuesAsync(endpoint, request, ct).ConfigureAwait(false); } /// public async Task> HistoryReadModifiedValuesAsync( ConnectionModel endpoint, HistoryReadRequestModel request, CancellationToken ct) { return await _client.HistoryReadModifiedValuesAsync(endpoint, request, ct).ConfigureAwait(false); } /// public async Task> HistoryReadValuesNextAsync( ConnectionModel endpoint, HistoryReadNextRequestModel request, CancellationToken ct) { return await _client.HistoryReadValuesNextAsync(endpoint, request, ct).ConfigureAwait(false); } /// public IAsyncEnumerable HistoryStreamValuesAsync(ConnectionModel endpoint, HistoryReadRequestModel request, CancellationToken ct) { // TODO: throw new NotImplementedException(); } /// public IAsyncEnumerable HistoryStreamModifiedValuesAsync(ConnectionModel endpoint, HistoryReadRequestModel request, CancellationToken ct) { // TODO: throw new NotImplementedException(); } /// public IAsyncEnumerable HistoryStreamValuesAtTimesAsync(ConnectionModel endpoint, HistoryReadRequestModel request, CancellationToken ct) { // TODO: throw new NotImplementedException(); } /// public IAsyncEnumerable HistoryStreamProcessedValuesAsync(ConnectionModel endpoint, HistoryReadRequestModel request, CancellationToken ct) { // TODO: throw new NotImplementedException(); } /// public IAsyncEnumerable HistoryStreamEventsAsync(ConnectionModel endpoint, HistoryReadRequestModel request, CancellationToken ct) { // TODO: throw new NotImplementedException(); } private readonly IHistoryApi _client; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Clients/Adapters/PublisherApiAdapter.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ #nullable enable namespace Azure.IIoT.OpcUa.Publisher.Service.Clients.Adapters { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Sdk; using System; using System.Threading; using System.Threading.Tasks; /// /// Implements node services as adapter on top of twin api. /// public sealed class PublisherApiAdapter : ICertificateServices { /// /// Create adapter /// /// public PublisherApiAdapter(IDiscoveryApi client) { _client = client ?? throw new ArgumentNullException(nameof(client)); } /// public async Task GetEndpointCertificateAsync( EndpointModel endpoint, CancellationToken ct) { return await _client.GetEndpointCertificateAsync(endpoint, ct).ConfigureAwait(false); } private readonly IDiscoveryApi _client; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Clients/Adapters/TwinApiAdapter.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ #nullable enable namespace Azure.IIoT.OpcUa.Publisher.Service.Clients.Adapters { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Sdk; using Furly.Extensions.Serializers; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; /// /// Implements node services as adapter on top of twin api. /// public sealed class TwinApiAdapter : INodeServices { /// /// Create adapter /// /// public TwinApiAdapter(ITwinApi client) { _client = client ?? throw new ArgumentNullException(nameof(client)); } /// public async Task BrowseFirstAsync(ConnectionModel endpoint, BrowseFirstRequestModel request, CancellationToken ct) { return await _client.NodeBrowseFirstAsync(endpoint, request, ct).ConfigureAwait(false); } /// public async Task BrowseNextAsync(ConnectionModel endpoint, BrowseNextRequestModel request, CancellationToken ct) { return await _client.NodeBrowseNextAsync(endpoint, request, ct).ConfigureAwait(false); } /// public IAsyncEnumerable BrowseAsync(ConnectionModel endpoint, BrowseStreamRequestModel request, CancellationToken ct = default) { // TODO throw new NotSupportedException("Browse stream is not supported"); } /// public async Task BrowsePathAsync(ConnectionModel endpoint, BrowsePathRequestModel request, CancellationToken ct) { return await _client.NodeBrowsePathAsync(endpoint, request, ct).ConfigureAwait(false); } /// public async Task ValueReadAsync(ConnectionModel endpoint, ValueReadRequestModel request, CancellationToken ct) { return await _client.NodeValueReadAsync(endpoint, request, ct).ConfigureAwait(false); } /// public async Task ValueWriteAsync(ConnectionModel endpoint, ValueWriteRequestModel request, CancellationToken ct) { return await _client.NodeValueWriteAsync(endpoint, request, ct).ConfigureAwait(false); } /// public async Task GetMethodMetadataAsync(ConnectionModel endpoint, MethodMetadataRequestModel request, CancellationToken ct) { return await _client.NodeMethodGetMetadataAsync(endpoint, request, ct).ConfigureAwait(false); } /// public async Task MethodCallAsync(ConnectionModel endpoint, MethodCallRequestModel request, CancellationToken ct) { return await _client.NodeMethodCallAsync(endpoint, request, ct).ConfigureAwait(false); } /// public async Task ReadAsync(ConnectionModel endpoint, ReadRequestModel request, CancellationToken ct) { return await _client.NodeReadAsync(endpoint, request, ct).ConfigureAwait(false); } /// public async Task WriteAsync(ConnectionModel endpoint, WriteRequestModel request, CancellationToken ct) { return await _client.NodeWriteAsync(endpoint, request, ct).ConfigureAwait(false); } /// public async Task GetServerCapabilitiesAsync(ConnectionModel endpoint, RequestHeaderModel? header, CancellationToken ct) { return await _client.GetServerCapabilitiesAsync(endpoint, header, ct).ConfigureAwait(false); } /// public async Task GetMetadataAsync(ConnectionModel endpoint, NodeMetadataRequestModel request, CancellationToken ct) { return await _client.GetMetadataAsync(endpoint, request, ct).ConfigureAwait(false); } /// public async Task CompileQueryAsync(ConnectionModel endpoint, QueryCompilationRequestModel request, CancellationToken ct) { return await _client.CompileQueryAsync(endpoint, request, ct).ConfigureAwait(false); } /// public async Task HistoryGetServerCapabilitiesAsync( ConnectionModel endpoint, RequestHeaderModel? header, CancellationToken ct) { return await _client.HistoryGetServerCapabilitiesAsync(endpoint, header, ct).ConfigureAwait(false); } /// public async Task HistoryGetConfigurationAsync( ConnectionModel endpoint, HistoryConfigurationRequestModel request, CancellationToken ct) { return await _client.HistoryGetConfigurationAsync(endpoint, request, ct).ConfigureAwait(false); } /// public async Task> HistoryReadAsync( ConnectionModel endpoint, HistoryReadRequestModel request, CancellationToken ct) { return await _client.HistoryReadAsync(endpoint, request, ct).ConfigureAwait(false); } /// public async Task> HistoryReadNextAsync( ConnectionModel endpoint, HistoryReadNextRequestModel request, CancellationToken ct) { return await _client.HistoryReadNextAsync(endpoint, request, ct).ConfigureAwait(false); } /// public async Task HistoryUpdateAsync( ConnectionModel endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { return await _client.HistoryUpdateAsync(endpoint, request, ct).ConfigureAwait(false); } private readonly ITwinApi _client; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Clients/ConfigurationServicesRestClient.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Clients { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Sdk; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.IO; using System.Net.Http; using System.Threading; using System.Threading.Tasks; /// /// Implementation of file system services over http /// public sealed class ConfigurationServicesRestClient : IConfigurationServices, IAssetConfiguration, IAssetConfiguration, IAssetConfiguration { /// /// Create service client /// /// /// /// public ConfigurationServicesRestClient(IHttpClientFactory httpClient, IOptions options, ISerializer serializer) : this(httpClient, options?.Value.Target, serializer) { } /// /// Create service client /// /// /// /// public ConfigurationServicesRestClient(IHttpClientFactory httpClient, string serviceUri, ISerializer serializer = null) { if (string.IsNullOrWhiteSpace(serviceUri)) { throw new ArgumentNullException(nameof(serviceUri), "Please configure the Url of the endpoint micro service."); } _serviceUri = serviceUri.TrimEnd('/'); _serializer = serializer ?? new NewtonsoftJsonSerializer(); _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient)); } /// public IAsyncEnumerable> ExpandAsync( PublishedNodesEntryModel entry, PublishedNodeExpansionModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(entry); var uri = new Uri($"{_serviceUri}/v2/writer/expand"); return _httpClient.PostStreamAsync>(uri, RequestBody(entry, request), _serializer, ct: ct); } /// public IAsyncEnumerable> CreateOrUpdateAsync( PublishedNodesEntryModel entry, PublishedNodeExpansionModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(entry); var uri = new Uri($"{_serviceUri}/v2/writer"); return _httpClient.PostStreamAsync>(uri, RequestBody(entry, request), _serializer, ct: ct); } /// public async Task> CreateOrUpdateAssetAsync( PublishedNodeCreateAssetRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Entry); ArgumentNullException.ThrowIfNull(request.Entry.DataSetWriterGroup); ArgumentNullException.ThrowIfNull(request.Entry.DataSetName); ArgumentNullException.ThrowIfNull(request.Configuration); var uri = new Uri($"{_serviceUri}/v2/writer/assets/create"); var buffer = request.Configuration.ReadAsBuffer(); var requestWithBuffer = new PublishedNodeCreateAssetRequestModel { Entry = request.Entry, Header = request.Header, WaitTime = request.WaitTime, Configuration = [.. buffer] }; return await _httpClient.PostAsync>(uri, requestWithBuffer, _serializer, ct: ct).ConfigureAwait(false); } public async Task> CreateOrUpdateAssetAsync( PublishedNodeCreateAssetRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Entry); ArgumentNullException.ThrowIfNull(request.Entry.DataSetWriterGroup); ArgumentNullException.ThrowIfNull(request.Entry.DataSetName); var uri = new Uri($"{_serviceUri}/v2/writer/assets"); return await _httpClient.PostAsync>(uri, request, _serializer, ct: ct).ConfigureAwait(false); } /// public async Task> CreateOrUpdateAssetAsync( PublishedNodeCreateAssetRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Entry); ArgumentNullException.ThrowIfNull(request.Entry.DataSetWriterGroup); ArgumentNullException.ThrowIfNull(request.Entry.DataSetName); ArgumentNullException.ThrowIfNull(request.Configuration); var uri = new Uri($"{_serviceUri}/v2/writer/assets/create"); return await _httpClient.PostAsync>(uri, request, _serializer, ct: ct).ConfigureAwait(false); } /// public IAsyncEnumerable> GetAllAssetsAsync( PublishedNodesEntryModel entry, RequestHeaderModel header, CancellationToken ct) { ArgumentNullException.ThrowIfNull(entry); var uri = new Uri($"{_serviceUri}/v2/writer/assets/list"); return _httpClient.PostStreamAsync>(uri, RequestBody(entry, header), _serializer, ct: ct); } /// public async Task DeleteAssetAsync( PublishedNodeDeleteAssetRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); ArgumentNullException.ThrowIfNull(request.Entry); ArgumentNullException.ThrowIfNull(request.Entry.DataSetWriterGroup); ArgumentNullException.ThrowIfNull(request.Entry.DataSetWriterId); var uri = new Uri($"{_serviceUri}/v2/writer/assets/delete"); return await _httpClient.PostAsync(uri, request, _serializer, ct: ct).ConfigureAwait(false); } /// /// Create envelope /// /// /// /// /// private static PublishedNodesEntryRequestModel RequestBody(PublishedNodesEntryModel entry, T request) { return new PublishedNodesEntryRequestModel { Entry = entry, Request = request }; } private readonly IHttpClientFactory _httpClient; private readonly ISerializer _serializer; private readonly string _serviceUri; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Clients/FileSystemServicesRestClient.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Clients { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Sdk; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Microsoft.Extensions.Options; using System; using System.Buffers; using System.Collections.Generic; using System.IO; using System.IO.Pipelines; using System.Linq; using System.Net.Http; using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; /// /// Implementation of file system services over http /// public sealed class FileSystemServicesRestClient : IFileSystemServices { /// /// Create service client /// /// /// /// public FileSystemServicesRestClient(IHttpClientFactory httpClient, IOptions options, ISerializer serializer) : this(httpClient, options?.Value.Target, serializer) { } /// /// Create service client /// /// /// /// public FileSystemServicesRestClient(IHttpClientFactory httpClient, string serviceUri, ISerializer serializer = null) { if (string.IsNullOrWhiteSpace(serviceUri)) { throw new ArgumentNullException(nameof(serviceUri), "Please configure the Url of the endpoint micro service."); } _serviceUri = serviceUri.TrimEnd('/'); _serializer = serializer ?? new NewtonsoftJsonSerializer(); _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient)); } /// public IAsyncEnumerable> GetFileSystemsAsync( ConnectionModel endpoint, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); var uri = new Uri($"{_serviceUri}/v2/filesystem/list"); return _httpClient.PostStreamAsync>(uri, endpoint, _serializer, ct: ct); } /// public async Task>> GetDirectoriesAsync( ConnectionModel endpoint, FileSystemObjectModel fileSystemOrDirectory, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(fileSystemOrDirectory); var uri = new Uri($"{_serviceUri}/v2/filesystem/list/directories"); return await _httpClient.PostAsync>>(uri, RequestBody(endpoint, fileSystemOrDirectory), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task>> GetFilesAsync( ConnectionModel endpoint, FileSystemObjectModel fileSystemOrDirectory, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(fileSystemOrDirectory); var uri = new Uri($"{_serviceUri}/v2/filesystem/list/files"); return await _httpClient.PostAsync>>(uri, RequestBody(endpoint, fileSystemOrDirectory), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task> GetParentAsync(ConnectionModel endpoint, FileSystemObjectModel fileOrDirectoryObject, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(fileOrDirectoryObject); var uri = new Uri($"{_serviceUri}/v2/filesystem/parent"); return await _httpClient.PostAsync>(uri, RequestBody(endpoint, fileOrDirectoryObject), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task> GetFileInfoAsync(ConnectionModel endpoint, FileSystemObjectModel file, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(file); var uri = new Uri($"{_serviceUri}/v2/filesystem/info/file"); return await _httpClient.PostAsync>(uri, RequestBody(endpoint, file), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task> OpenReadAsync(ConnectionModel endpoint, FileSystemObjectModel file, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(file); return await DownloadStream.CreateAsync(this, endpoint, file, ct).ConfigureAwait(false); } /// public Task> OpenWriteAsync(ConnectionModel endpoint, FileSystemObjectModel file, FileOpenWriteOptionsModel options, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(file); return Task.FromResult(UploadStream.Create(this, endpoint, file, options, ct)); } /// public async Task> CreateDirectoryAsync(ConnectionModel endpoint, FileSystemObjectModel fileSystemOrDirectory, string name, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(fileSystemOrDirectory); ArgumentNullException.ThrowIfNullOrWhiteSpace(name); var uri = new Uri($"{_serviceUri}/v2/filesystem/create/directory/{name.UrlEncode()}"); return await _httpClient.PostAsync>(uri, RequestBody(endpoint, fileSystemOrDirectory), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task> CreateFileAsync(ConnectionModel endpoint, FileSystemObjectModel fileSystemOrDirectory, string name, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(fileSystemOrDirectory); ArgumentNullException.ThrowIfNullOrWhiteSpace(name); var uri = new Uri($"{_serviceUri}/v2/filesystem/create/file/{name.UrlEncode()}"); return await _httpClient.PostAsync>(uri, RequestBody(endpoint, fileSystemOrDirectory), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task DeleteFileSystemObjectAsync(ConnectionModel endpoint, FileSystemObjectModel fileOrDirectoryObject, FileSystemObjectModel parentFileSystemOrDirectory, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(fileOrDirectoryObject); if (parentFileSystemOrDirectory == null) { var uri = new Uri($"{_serviceUri}/v2/filesystem/delete"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, fileOrDirectoryObject), _serializer, ct: ct).ConfigureAwait(false); } else { if (fileOrDirectoryObject.BrowsePath?.Count > 0) { throw new NotSupportedException("Not yet supported"); } var uri = new Uri($"{_serviceUri}/v2/filesystem/delete/{fileOrDirectoryObject.NodeId.UrlEncode()}"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, parentFileSystemOrDirectory), _serializer, ct: ct).ConfigureAwait(false); } } /// /// Create envelope /// /// /// /// /// private static RequestEnvelope RequestBody(ConnectionModel connection, T request) { return new RequestEnvelope { Connection = connection, Request = request }; } /// /// File stream wraps a body of a response /// internal sealed class DownloadStream : Stream { /// public override bool CanRead => _body.CanRead; /// public override bool CanSeek => _body.CanSeek; /// public override bool CanWrite => _body.CanWrite; /// public override long Length => _body.Length; /// public override long Position { get => _body.Position; set => _body.Position = value; } /// /// Create download stream /// /// /// /// private DownloadStream(HttpClient httpClient, HttpRequestMessage request, Stream body) { _httpClient = httpClient; _request = request; _body = body; } /// public static async Task> CreateAsync(FileSystemServicesRestClient outer, ConnectionModel endpoint, FileSystemObjectModel file, CancellationToken ct) { var uri = new Uri($"{outer._serviceUri}/v2/filesystem/download"); var httpClient = outer._httpClient.CreateClient(); httpClient.Timeout = TimeSpan.FromMinutes(2); var _serializer = new NewtonsoftJsonSerializer(); using var request = new HttpRequestMessage(HttpMethod.Get, uri); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/octet-stream")); request.Headers.Add("x-ms-target", _serializer.SerializeObjectToString(file)); request.Headers.Add("x-ms-connection", _serializer.SerializeObjectToString(endpoint)); try { var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, ct).ConfigureAwait(false); var stream = await response.Content.ReadAsStreamAsync(ct); if (!response.IsSuccessStatusCode) { string errorInfo = null; if (response.Headers.TryGetValues("errorInfo", out var header)) { errorInfo = header.FirstOrDefault(); } response.Dispose(); if (errorInfo != null) { // Error response return new ServiceResponse { ErrorInfo = _serializer.Deserialize(errorInfo) }; } throw new HttpRequestException($"Failed to download file: {response.StatusCode}"); } var client = httpClient; httpClient = null; return new ServiceResponse { Result = new DownloadStream(client, request, stream) }; } finally { httpClient?.Dispose(); } } /// protected override void Dispose(bool disposing) { if (disposing) { _body.Dispose(); _request.Dispose(); _httpClient.Dispose(); } base.Dispose(disposing); } /// public override void Flush() { _body.Flush(); } /// public override int Read(byte[] buffer, int offset, int count) { return _body.Read(buffer, offset, count); } /// public override long Seek(long offset, SeekOrigin origin) { return _body.Seek(offset, origin); } /// public override void SetLength(long value) { _body.SetLength(value); } /// public override void Write(byte[] buffer, int offset, int count) { _body.Write(buffer, offset, count); } private readonly HttpClient _httpClient; private readonly HttpRequestMessage _request; private readonly Stream _body; } /// /// Write stream wraps a request content body /// internal sealed class UploadStream : Stream { /// public override bool CanRead => false; /// public override bool CanSeek => false; /// public override bool CanWrite => true; /// public override long Length => _length; /// public override long Position { get; set; } /// /// Service response /// public ServiceResponse Result { get; private set; } /// /// Create upload stream /// /// /// /// /// public UploadStream(HttpClient httpClient, HttpRequestMessage request, IJsonSerializer serializer, CancellationToken ct) { _httpClient = httpClient; _request = request; _serializer = serializer; _request.Content = new StreamContent(_pipe.Reader.AsStream(false)); _streaming = StartAsync(ct); } /// public static ServiceResponse Create(FileSystemServicesRestClient outer, ConnectionModel endpoint, FileSystemObjectModel file, FileOpenWriteOptionsModel options, CancellationToken ct) { var uri = new Uri($"{outer._serviceUri}/v2/filesystem/upload"); var httpClient = outer._httpClient.CreateClient(); httpClient.Timeout = TimeSpan.FromMinutes(2); var request = new HttpRequestMessage(HttpMethod.Post, uri); var serializer = new NewtonsoftJsonSerializer(); request.Headers.Add("x-ms-target", serializer.SerializeObjectToString(file)); request.Headers.Add("x-ms-connection", serializer.SerializeObjectToString(endpoint)); request.Headers.Add("x-ms-options", serializer.SerializeObjectToString(options)); var stream = new UploadStream(httpClient, request, serializer, ct); return new ServiceResponse { Result = stream }; } /// public override void Flush() { } /// public override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); } /// public override void SetLength(long value) { throw new NotSupportedException(); } /// public override int Read(byte[] buffer, int offset, int count) { throw new NotSupportedException(); } /// public override void Write(byte[] buffer, int offset, int count) { _pipe.Writer.Write(buffer.AsSpan().Slice(offset, count)); _length += count; } /// public override async ValueTask DisposeAsync() { // Stream owner is done writing and disposes if (_streaming != null) { try { await _pipe.Writer.CompleteAsync().ConfigureAwait(false); // now wait until fully sent and result received await _streaming.ConfigureAwait(false); _streaming = null; } catch (OperationCanceledException) { } // Ct triggered finally { _request.Dispose(); _httpClient.Dispose(); } } await base.DisposeAsync(); } /// protected override void Dispose(bool disposing) { if (disposing && _streaming != null) { DisposeAsync().AsTask().GetAwaiter().GetResult(); } base.Dispose(disposing); } /// /// Start streaming /// /// /// /// private async Task StartAsync(CancellationToken ct) { var response = await _httpClient.SendAsync(_request, ct).ConfigureAwait(false); // Stream fully sent and response returned if (!response.IsSuccessStatusCode) { string errorInfo = null; if (response.Headers.TryGetValues("errorInfo", out var header)) { errorInfo = header.FirstOrDefault(); } response.Dispose(); if (errorInfo != null) { // Error response Result = new ServiceResponse { ErrorInfo = _serializer.Deserialize(errorInfo) }; } throw new HttpRequestException($"Failed to upload file: {response.StatusCode}"); } } private readonly HttpClient _httpClient; private readonly HttpRequestMessage _request; private readonly Pipe _pipe = new(); private readonly IJsonSerializer _serializer; private int _length; private Task _streaming; } private readonly IHttpClientFactory _httpClient; private readonly ISerializer _serializer; private readonly string _serviceUri; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Clients/HistoryServicesRestClient.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Clients { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Sdk; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.Net.Http; using System.Threading; using System.Threading.Tasks; /// /// Implementation of Historian services over http. /// public sealed class HistoryServicesRestClient : IHistoryServices { /// /// Create service client /// /// /// /// public HistoryServicesRestClient(IHttpClientFactory httpClient, IOptions options, ISerializer serializer) : this(httpClient, options?.Value.Target, serializer) { } /// /// Create service client /// /// /// /// public HistoryServicesRestClient(IHttpClientFactory httpClient, string serviceUri, ISerializer serializer = null) { if (string.IsNullOrWhiteSpace(serviceUri)) { throw new ArgumentNullException(nameof(serviceUri), "Please configure the Url of the endpoint micro service."); } _serializer = serializer ?? new NewtonsoftJsonSerializer(); _serviceUri = serviceUri.TrimEnd('/'); _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient)); } /// public async Task> HistoryReadValuesAsync( ConnectionModel endpoint, HistoryReadRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/history/values/read/first"); return await _httpClient.PostAsync>(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task> HistoryReadModifiedValuesAsync( ConnectionModel endpoint, HistoryReadRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/history/values/read/first/modified"); return await _httpClient.PostAsync>(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task> HistoryReadValuesAtTimesAsync( ConnectionModel endpoint, HistoryReadRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/history/values/read/first/attimes"); return await _httpClient.PostAsync>(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task> HistoryReadProcessedValuesAsync( ConnectionModel endpoint, HistoryReadRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/history/values/read/first/processed"); return await _httpClient.PostAsync>(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task> HistoryReadValuesNextAsync( ConnectionModel endpoint, HistoryReadNextRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); if (string.IsNullOrEmpty(request.ContinuationToken)) { throw new ArgumentException("Continuation missing.", nameof(request)); } var uri = new Uri($"{_serviceUri}/v2/history/values/read/next"); return await _httpClient.PostAsync>(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task> HistoryReadEventsAsync( ConnectionModel endpoint, HistoryReadRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/history/events/read/first"); return await _httpClient.PostAsync>(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task> HistoryReadEventsNextAsync( ConnectionModel endpoint, HistoryReadNextRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); if (string.IsNullOrEmpty(request.ContinuationToken)) { throw new ArgumentException("Continuation missing.", nameof(request)); } var uri = new Uri($"{_serviceUri}/v2/history/events/read/next"); return await _httpClient.PostAsync>(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task HistoryReplaceValuesAsync(ConnectionModel endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/history/values/replace"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task HistoryReplaceEventsAsync(ConnectionModel endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/history/events/replace"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task HistoryInsertValuesAsync(ConnectionModel endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/history/values/insert"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task HistoryUpsertValuesAsync(ConnectionModel endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/history/values/upsert"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task HistoryInsertEventsAsync(ConnectionModel endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/history/events/insert"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task HistoryUpsertEventsAsync(ConnectionModel endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/history/events/upsert"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task HistoryDeleteValuesAsync(ConnectionModel endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/history/values/delete"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task HistoryDeleteValuesAtTimesAsync(ConnectionModel endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/history/values/delete/attimes"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task HistoryDeleteModifiedValuesAsync(ConnectionModel endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/history/values/delete/modified"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task HistoryDeleteEventsAsync(ConnectionModel endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/history/events/delete"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } public IAsyncEnumerable HistoryStreamValuesAsync(ConnectionModel endpoint, HistoryReadRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/history/values/read"); return _httpClient.PostStreamAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct); } public IAsyncEnumerable HistoryStreamModifiedValuesAsync(ConnectionModel endpoint, HistoryReadRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/history/values/read/modified"); return _httpClient.PostStreamAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct); } public IAsyncEnumerable HistoryStreamValuesAtTimesAsync(ConnectionModel endpoint, HistoryReadRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/history/values/read/attimes"); return _httpClient.PostStreamAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct); } public IAsyncEnumerable HistoryStreamProcessedValuesAsync(ConnectionModel endpoint, HistoryReadRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/history/values/read/processed"); return _httpClient.PostStreamAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct); } public IAsyncEnumerable HistoryStreamEventsAsync(ConnectionModel endpoint, HistoryReadRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/history/events/read"); return _httpClient.PostStreamAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct); } /// /// Create envelope /// /// /// /// /// private static RequestEnvelope RequestBody(ConnectionModel connection, T request) { return new RequestEnvelope { Connection = connection, Request = request }; } private readonly IHttpClientFactory _httpClient; private readonly ISerializer _serializer; private readonly string _serviceUri; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Clients/NodeServicesRestClient.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Clients { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Sdk; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; /// /// Implementation of node services over http /// public sealed class NodeServicesRestClient : INodeServices { /// /// Create service client /// /// /// /// public NodeServicesRestClient(IHttpClientFactory httpClient, IOptions options, ISerializer serializer) : this(httpClient, options?.Value.Target, serializer) { } /// /// Create service client /// /// /// /// public NodeServicesRestClient(IHttpClientFactory httpClient, string serviceUri, ISerializer serializer = null) { if (string.IsNullOrWhiteSpace(serviceUri)) { throw new ArgumentNullException(nameof(serviceUri), "Please configure the Url of the endpoint micro service."); } _serviceUri = serviceUri.TrimEnd('/'); _serializer = serializer ?? new NewtonsoftJsonSerializer(); _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient)); } /// public IAsyncEnumerable BrowseAsync(ConnectionModel endpoint, BrowseStreamRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/browse"); return _httpClient.PostStreamAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct); } /// public async Task BrowseFirstAsync(ConnectionModel endpoint, BrowseFirstRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/browse/first"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task BrowseNextAsync(ConnectionModel endpoint, BrowseNextRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); if (request.ContinuationToken == null) { throw new ArgumentException("Continuation missing.", nameof(request)); } var uri = new Uri($"{_serviceUri}/v2/browse/next"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task BrowsePathAsync(ConnectionModel endpoint, BrowsePathRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); if (request.BrowsePaths == null || request.BrowsePaths.Count == 0 || request.BrowsePaths.Any(p => p == null || p.Count == 0)) { throw new ArgumentException("Browse paths missing.", nameof(request)); } var uri = new Uri($"{_serviceUri}/v2/browse/path"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task ReadAsync(ConnectionModel endpoint, ReadRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); if (request.Attributes == null || request.Attributes.Count == 0) { throw new ArgumentException(nameof(request.Attributes)); } var uri = new Uri($"{_serviceUri}/v2/read/attributes"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task WriteAsync(ConnectionModel endpoint, WriteRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); if (request.Attributes == null || request.Attributes.Count == 0) { throw new ArgumentException(nameof(request.Attributes)); } var uri = new Uri($"{_serviceUri}/v2/write/attributes"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task ValueReadAsync(ConnectionModel endpoint, ValueReadRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/read"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task ValueWriteAsync(ConnectionModel endpoint, ValueWriteRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); if (request.Value is null) { throw new ArgumentException("Value missing.", nameof(request)); } var uri = new Uri($"{_serviceUri}/v2/write"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task GetMethodMetadataAsync( ConnectionModel endpoint, MethodMetadataRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/call/$metadata"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task MethodCallAsync( ConnectionModel endpoint, MethodCallRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/call"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task GetMetadataAsync(ConnectionModel endpoint, NodeMetadataRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/metadata"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task CompileQueryAsync(ConnectionModel endpoint, QueryCompilationRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); var uri = new Uri($"{_serviceUri}/v2/query/compile"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task GetServerCapabilitiesAsync(ConnectionModel endpoint, RequestHeaderModel header, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); var uri = new Uri($"{_serviceUri}/v2/capabilities"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, header), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task HistoryGetServerCapabilitiesAsync( ConnectionModel endpoint, RequestHeaderModel header, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); var uri = new Uri($"{_serviceUri}/v2/history/capabilities"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, header), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task HistoryGetConfigurationAsync( ConnectionModel endpoint, HistoryConfigurationRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); if (request.NodeId == null) { throw new ArgumentException("NodeId missing.", nameof(request)); } var uri = new Uri($"{_serviceUri}/v2/history/configuration"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task> HistoryReadAsync( ConnectionModel endpoint, HistoryReadRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); if (request.Details == null) { throw new ArgumentException("Details missing.", nameof(request)); } var uri = new Uri($"{_serviceUri}/v2/historyread/first"); return await _httpClient.PostAsync>(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task> HistoryReadNextAsync( ConnectionModel endpoint, HistoryReadNextRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); if (string.IsNullOrEmpty(request.ContinuationToken)) { throw new ArgumentException("Continuation missing.", nameof(request)); } var uri = new Uri($"{_serviceUri}v2/historyread/next"); return await _httpClient.PostAsync>(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// public async Task HistoryUpdateAsync( ConnectionModel endpoint, HistoryUpdateRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); ArgumentNullException.ThrowIfNull(request); if (request.Details == null) { throw new ArgumentException("Details missing.", nameof(request)); } var uri = new Uri($"{_serviceUri}/v2/historyupdate"); return await _httpClient.PostAsync(uri, RequestBody(endpoint, request), _serializer, ct: ct).ConfigureAwait(false); } /// /// Create envelope /// /// /// /// /// private static RequestEnvelope RequestBody(ConnectionModel connection, T request) { return new RequestEnvelope { Connection = connection, Request = request }; } private readonly IHttpClientFactory _httpClient; private readonly ISerializer _serializer; private readonly string _serviceUri; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/Alarms/Json/NodeServicesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.Alarms.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class NodeServicesTests : IClassFixture, IClassFixture, IDisposable { public NodeServicesTests(AlarmsServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private AlarmServerTests GetTests() { return new AlarmServerTests( _client.Resolve>, _server.GetConnection()); } private readonly AlarmsServer _server; private readonly IContainer _client; [Fact] public Task BrowseAreaPathTestAsync() { return GetTests().BrowseAreaPathTestAsync(); } [Fact] public Task BrowseMetalsSouthMotorTestAsync() { return GetTests().BrowseMetalsSouthMotorTestAsync(); } [Fact] public Task BrowseColoursEastTankTestAsync() { return GetTests().BrowseColoursEastTankTestAsync(); } [Fact] public Task CompileAlarmQueryTest1Async() { return GetTests().CompileAlarmQueryTest1Async(); } [Fact] public Task CompileAlarmQueryTest2Async() { return GetTests().CompileAlarmQueryTest2Async(); } [Fact] public Task CompileSimpleBaseEventQueryTestAsync() { return GetTests().CompileSimpleBaseEventQueryTestAsync(); } [Fact] public Task CompileSimpleTripAlarmQueryTestAsync() { return GetTests().CompileSimpleTripAlarmQueryTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/Alarms/MsgPack/NodeServicesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.Alarms.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class NodeServicesTests : IClassFixture, IClassFixture, IDisposable { public NodeServicesTests(AlarmsServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private AlarmServerTests GetTests() { return new AlarmServerTests( _client.Resolve>, _server.GetConnection()); } private readonly AlarmsServer _server; private readonly IContainer _client; [Fact] public Task BrowseAreaPathTestAsync() { return GetTests().BrowseAreaPathTestAsync(); } [Fact] public Task BrowseMetalsSouthMotorTestAsync() { return GetTests().BrowseMetalsSouthMotorTestAsync(); } [Fact] public Task BrowseColoursEastTankTestAsync() { return GetTests().BrowseColoursEastTankTestAsync(); } [Fact] public Task CompileAlarmQueryTest1Async() { return GetTests().CompileAlarmQueryTest1Async(); } [Fact] public Task CompileAlarmQueryTest2Async() { return GetTests().CompileAlarmQueryTest2Async(); } [Fact] public Task CompileSimpleBaseEventQueryTestAsync() { return GetTests().CompileSimpleBaseEventQueryTestAsync(); } [Fact] public Task CompileSimpleTripAlarmQueryTestAsync() { return GetTests().CompileSimpleTripAlarmQueryTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/Asset/Json/ConfigurationTest1.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.Asset.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.IO; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection1.Name)] public sealed class ConfigurationTest1 : IClassFixture, IDisposable { public ConfigurationTest1(AssetServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private AssetTests1 GetTests() { #pragma warning disable CA2000 // Dispose objects before losing scope return new AssetTests1(_ => _client.Resolve>(), _server.GetConnection(), false); #pragma warning restore CA2000 // Dispose objects before losing scope } private readonly AssetServer _server; private readonly IContainer _client; [Fact] public Task ConfigureAndDeleteAssetsAsync() { return GetTests().ConfigureAndDeleteAssetsAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/Asset/Json/ConfigurationTest2.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.Asset.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.IO; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection2.Name)] public sealed class ConfigurationTest2 : IClassFixture, IDisposable { public ConfigurationTest2(AssetServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private AssetTests2 GetTests() { #pragma warning disable CA2000 // Dispose objects before losing scope return new AssetTests2(_ => _client.Resolve>(), _server.GetConnection(), false); #pragma warning restore CA2000 // Dispose objects before losing scope } private readonly AssetServer _server; private readonly IContainer _client; [Fact] public Task ConfigureAsset1Async() { return GetTests().ConfigureAsset1Async(); } [Fact] public Task ConfigureAsset2Async() { return GetTests().ConfigureAsset2Async(); } [Fact] public Task ConfigureAsset3Async() { return GetTests().ConfigureAsset3Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/Asset/Json/ConfigurationTest3.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.Asset.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection3.Name)] public sealed class ConfigurationTest3 : IClassFixture, IDisposable { public ConfigurationTest3(AssetServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private AssetTests3 GetTests() { #pragma warning disable CA2000 // Dispose objects before losing scope return new AssetTests3(_ => _client.Resolve>(), _server.GetConnection(), false); #pragma warning restore CA2000 // Dispose objects before losing scope } private readonly AssetServer _server; private readonly IContainer _client; [Fact] public Task ConfigureAsset1Async() { return GetTests().ConfigureAsset1Async(); } [Fact] public Task ConfigureAsset2Async() { return GetTests().ConfigureAsset2Async(); } [Fact] public Task ConfigureAsset3Async() { return GetTests().ConfigureAsset3Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/Asset/Json/ConfigurationTest4.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.Asset.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.IO; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection4.Name)] public sealed class ConfigurationTest4 : IClassFixture, IDisposable { public ConfigurationTest4(AssetServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private AssetTests4 GetTests() { #pragma warning disable CA2000 // Dispose objects before losing scope return new AssetTests4(_ => _client.Resolve>(), _server.GetConnection(), false); #pragma warning restore CA2000 // Dispose objects before losing scope } private readonly AssetServer _server; private readonly IContainer _client; [Fact] public Task ConfigureDuplicateAssetFailsAsync() { return GetTests().ConfigureDuplicateAssetFailsAsync(); } [SkippableFact] public Task ConfigureAssetFails1Async() { Skip.If(true, "Using bytes only"); return GetTests().ConfigureAssetFails1Async(); } [SkippableFact] public Task ConfigureWithBadStreamFails1Async() { Skip.If(true, "Using bytes only"); return GetTests().ConfigureWithBadStreamFails1Async(); } [SkippableFact] public Task ConfigureWithBadStreamFails2Async() { Skip.If(true, "Using bytes only"); return GetTests().ConfigureWithBadStreamFails2Async(); } [SkippableFact] public Task ConfigureWithBadStreamFails3Async() { Skip.If(true, "Using bytes only"); return GetTests().ConfigureWithBadStreamFails3Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/Asset/Json/WriteCollection1.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.Asset.Json { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public class WriteCollection1 : ICollectionFixture { public const string Name = "AssetWrite1RestJson"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/Asset/Json/WriteCollection2.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.Asset.Json { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public class WriteCollection2 : ICollectionFixture { public const string Name = "AssetWrite2RestJson"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/Asset/Json/WriteCollection3.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.Asset.Json { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public class WriteCollection3 : ICollectionFixture { public const string Name = "AssetWrite3RestJson"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/Asset/Json/WriteCollection4.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.Asset.Json { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public class WriteCollection4 : ICollectionFixture { public const string Name = "AssetWrite4RestJson"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/Asset/MsgPack/ConfigurationTest1.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.Asset.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.IO; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection1.Name)] public sealed class ConfigurationTest1 : IClassFixture, IDisposable { public ConfigurationTest1(AssetServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private AssetTests1 GetTests() { #pragma warning disable CA2000 // Dispose objects before losing scope return new AssetTests1(_ => _client.Resolve>(), _server.GetConnection(), false); #pragma warning restore CA2000 // Dispose objects before losing scope } private readonly AssetServer _server; private readonly IContainer _client; [Fact] public Task ConfigureAndDeleteAssetsAsync() { return GetTests().ConfigureAndDeleteAssetsAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/Asset/MsgPack/ConfigurationTest2.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.Asset.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.IO; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection2.Name)] public sealed class ConfigurationTest2 : IClassFixture, IDisposable { public ConfigurationTest2(AssetServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private AssetTests2 GetTests() { #pragma warning disable CA2000 // Dispose objects before losing scope return new AssetTests2(_ => _client.Resolve>(), _server.GetConnection(), false); #pragma warning restore CA2000 // Dispose objects before losing scope } private readonly AssetServer _server; private readonly IContainer _client; [Fact] public Task ConfigureAsset1Async() { return GetTests().ConfigureAsset1Async(); } [Fact] public Task ConfigureAsset2Async() { return GetTests().ConfigureAsset2Async(); } [Fact] public Task ConfigureAsset3Async() { return GetTests().ConfigureAsset3Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/Asset/MsgPack/ConfigurationTest3.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.Asset.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection3.Name)] public sealed class ConfigurationTest3 : IClassFixture, IDisposable { public ConfigurationTest3(AssetServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private AssetTests3 GetTests() { #pragma warning disable CA2000 // Dispose objects before losing scope return new AssetTests3(_ => _client.Resolve>(), _server.GetConnection(), false); #pragma warning restore CA2000 // Dispose objects before losing scope } private readonly AssetServer _server; private readonly IContainer _client; [Fact] public Task ConfigureAsset1Async() { return GetTests().ConfigureAsset1Async(); } [Fact] public Task ConfigureAsset2Async() { return GetTests().ConfigureAsset2Async(); } [Fact] public Task ConfigureAsset3Async() { return GetTests().ConfigureAsset3Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/Asset/MsgPack/ConfigurationTest4.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.Asset.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.IO; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection4.Name)] public sealed class ConfigurationTest4 : IClassFixture, IDisposable { public ConfigurationTest4(AssetServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private AssetTests4 GetTests() { #pragma warning disable CA2000 // Dispose objects before losing scope return new AssetTests4(_ => _client.Resolve>(), _server.GetConnection(), false); #pragma warning restore CA2000 // Dispose objects before losing scope } private readonly AssetServer _server; private readonly IContainer _client; [Fact] public Task ConfigureDuplicateAssetFailsAsync() { return GetTests().ConfigureDuplicateAssetFailsAsync(); } [SkippableFact] public Task ConfigureAssetFails1Async() { Skip.If(true, "Using bytes only"); return GetTests().ConfigureAssetFails1Async(); } [SkippableFact] public Task ConfigureWithBadStreamFails1Async() { Skip.If(true, "Using bytes only"); return GetTests().ConfigureWithBadStreamFails1Async(); } [SkippableFact] public Task ConfigureWithBadStreamFails2Async() { Skip.If(true, "Using bytes only"); return GetTests().ConfigureWithBadStreamFails2Async(); } [SkippableFact] public Task ConfigureWithBadStreamFails3Async() { Skip.If(true, "Using bytes only"); return GetTests().ConfigureWithBadStreamFails3Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/Asset/MsgPack/WriteCollection1.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.Asset.MsgPack { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public class WriteCollection1 : ICollectionFixture { public const string Name = "AssetWrite1RestMsgPack"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/Asset/MsgPack/WriteCollection2.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.Asset.MsgPack { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public class WriteCollection2 : ICollectionFixture { public const string Name = "AssetWrite2RestMsgPack"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/Asset/MsgPack/WriteCollection3.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.Asset.MsgPack { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public class WriteCollection3 : ICollectionFixture { public const string Name = "AssetWrite3RestMsgPack"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/Asset/MsgPack/WriteCollection4.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.Asset.MsgPack { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public class WriteCollection4 : ICollectionFixture { public const string Name = "AssetWrite4RestMsgPack"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/DeterministicAlarms/Json/NodeServicesTests1.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.DeterministicAlarms.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class NodeServicesTests1 : IClassFixture, IClassFixture, IDisposable { public NodeServicesTests1(DeterministicAlarmsServer1 server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private DeterministicAlarmsTests1 GetTests() { return new DeterministicAlarmsTests1( _client.Resolve>, _server.GetConnection()); } private readonly DeterministicAlarmsServer1 _server; private readonly IContainer _client; [Fact] public Task BrowseAreaPathVendingMachine1TemperatureHighTestAsync() { return GetTests().BrowseAreaPathVendingMachine1TemperatureHighTestAsync(); } [Fact] public Task BrowseAreaPathVendingMachine2LightOffTestAsync() { return GetTests().BrowseAreaPathVendingMachine2LightOffTestAsync(); } [Fact] public Task BrowseAreaPathVendingMachine1DoorOpenTestAsync() { return GetTests().BrowseAreaPathVendingMachine1DoorOpenTestAsync(); } [Fact] public Task BrowseAreaPathVendingMachine2DoorOpenTestAsync() { return GetTests().BrowseAreaPathVendingMachine2DoorOpenTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/DeterministicAlarms/Json/NodeServicesTests2.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.DeterministicAlarms.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class NodeServicesTests2 : IClassFixture, IClassFixture, IDisposable { public NodeServicesTests2(DeterministicAlarmsServer2 server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private DeterministicAlarmsTests2 GetTests() { return new DeterministicAlarmsTests2( _client.Resolve>, _server.GetConnection()); } private readonly DeterministicAlarmsServer2 _server; private readonly IContainer _client; [Fact] public Task BrowseAreaPathVendingMachine1DoorOpenTestAsync() { return GetTests().BrowseAreaPathVendingMachine1DoorOpenTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/DeterministicAlarms/MsgPack/NodeServicesTests1.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.DeterministicAlarms.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class NodeServicesTests1 : IClassFixture, IClassFixture, IDisposable { public NodeServicesTests1(DeterministicAlarmsServer1 server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private DeterministicAlarmsTests1 GetTests() { return new DeterministicAlarmsTests1( _client.Resolve>, _server.GetConnection()); } private readonly DeterministicAlarmsServer1 _server; private readonly IContainer _client; [Fact] public Task BrowseAreaPathVendingMachine1TemperatureHighTestAsync() { return GetTests().BrowseAreaPathVendingMachine1TemperatureHighTestAsync(); } [Fact] public Task BrowseAreaPathVendingMachine2LightOffTestAsync() { return GetTests().BrowseAreaPathVendingMachine2LightOffTestAsync(); } [Fact] public Task BrowseAreaPathVendingMachine1DoorOpenTestAsync() { return GetTests().BrowseAreaPathVendingMachine1DoorOpenTestAsync(); } [Fact] public Task BrowseAreaPathVendingMachine2DoorOpenTestAsync() { return GetTests().BrowseAreaPathVendingMachine2DoorOpenTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/DeterministicAlarms/MsgPack/NodeServicesTests2.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.DeterministicAlarms.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class NodeServicesTests2 : IClassFixture, IClassFixture, IDisposable { public NodeServicesTests2(DeterministicAlarmsServer2 server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private DeterministicAlarmsTests2 GetTests() { return new DeterministicAlarmsTests2( _client.Resolve>, _server.GetConnection()); } private readonly DeterministicAlarmsServer2 _server; private readonly IContainer _client; [Fact] public Task BrowseAreaPathVendingMachine1DoorOpenTestAsync() { return GetTests().BrowseAreaPathVendingMachine1DoorOpenTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/DmApiPublisherControllerTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller { using Azure.IIoT.OpcUa.Publisher.Module.Controllers; using Azure.IIoT.OpcUa.Publisher; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Services; using Azure.IIoT.OpcUa.Publisher.Storage; using Azure.IIoT.OpcUa.Publisher.Tests.Utils; using Autofac; using FluentAssertions; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Moq; using Neovolve.Logging.Xunit; using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; /// /// Tests the Direct Methods API for the pubisher /// public sealed class DmApiPublisherControllerTests : TempFileProviderBase { /// /// Constructor that initializes common resources used by tests. /// /// public DmApiPublisherControllerTests(ITestOutputHelper output) { _newtonSoftJsonSerializer = new NewtonsoftJsonSerializer(); _loggerFactory = LogFactory.Create(output, Logging.Config); _options = new PublisherConfig(new ConfigurationBuilder().Build()).ToOptions(); _options.Value.PublishedNodesFile = _tempFile; _options.Value.UseFileChangePolling = true; _options.Value.MessagingProfile = MessagingProfile.Get( MessagingMode.PubSub, MessageEncoding.Json); _publishedNodesJobConverter = new PublishedNodesConverter( _loggerFactory.CreateLogger(), _newtonSoftJsonSerializer, _options); // Note that each test is responsible for setting content of _tempFile; CopyContent("Resources/empty_pn.json", _tempFile); using var factory = new PhysicalFileProviderFactory(_options, _loggerFactory.CreateLogger()); _publishedNodesProvider = new PublishedNodesProvider(factory, _options, _loggerFactory.CreateLogger()); _triggerMock = new Mock(); var factoryMock = new Mock(); var lifetime = new Mock(); lifetime.SetupGet(l => l.WriterGroup).Returns(_triggerMock.Object); factoryMock .Setup(factory => factory.Create(It.IsAny())) .Returns(lifetime.Object); _publisher = new PublisherService(factoryMock.Object, _options, _loggerFactory.CreateLogger()); _diagnostic = new Mock(); var mockDiag = new WriterGroupDiagnosticModel(); _diagnostic.Setup(m => m.TryGetDiagnosticsForWriterGroup(It.IsAny(), out mockDiag)).Returns(true); } protected override void Dispose(bool disposing) { if (disposing) { _loggerFactory.Dispose(); _publishedNodesProvider.Dispose(); } base.Dispose(disposing); } /// /// This method should be called only after content of _tempFile is set. /// private PublishedNodesJsonServices InitPublisherConfigService() { var configService = new PublishedNodesJsonServices( _publishedNodesJobConverter, _publisher, _loggerFactory.CreateLogger(), _publishedNodesProvider, _newtonSoftJsonSerializer, _diagnostic.Object ); configService.GetAwaiter().GetResult(); return configService; } [Fact] public async Task DmApiPublishUnpublishNodesTestAsync() { CopyContent("Resources/empty_pn.json", _tempFile); await using var configService = InitPublisherConfigService(); var methodsController = new ConfigurationController(configService); using var publishPayloads = new StreamReader("Resources/DmApiPayloadCollection.json"); var publishNodesRequest = _newtonSoftJsonSerializer.Deserialize>( await publishPayloads.ReadToEndAsync()); foreach (var request in publishNodesRequest) { var initialNode = request.OpcNodes[0]; for (var i = 0; i < 10000; i++) { request.OpcNodes.Add(new OpcNodeModel { Id = initialNode.Id + i.ToString(CultureInfo.InvariantCulture), DataSetFieldId = initialNode.DataSetFieldId, DisplayName = initialNode.DisplayName, ExpandedNodeId = initialNode.ExpandedNodeId, HeartbeatIntervalTimespan = initialNode.HeartbeatIntervalTimespan, OpcPublishingInterval = initialNode.OpcPublishingInterval, OpcPublishingIntervalTimespan = initialNode.OpcPublishingIntervalTimespan, OpcSamplingInterval = initialNode.OpcSamplingInterval, QueueSize = initialNode.QueueSize, SkipFirst = initialNode.SkipFirst, DataChangeTrigger = initialNode.DataChangeTrigger, DeadbandType = initialNode.DeadbandType, DeadbandValue = initialNode.DeadbandValue }); } await FluentActions .Invoking(async () => await methodsController.PublishNodesAsync(request)) .Should() .NotThrowAsync() ; } var writerGroup = Assert.Single(_publisher.WriterGroups); Assert.Equal(8u, _publisher.Version); foreach (var request in publishNodesRequest) { await FluentActions .Invoking(async () => await methodsController .UnpublishNodesAsync(request)) .Should() .NotThrowAsync() ; } Assert.Empty(_publisher.WriterGroups); Assert.Equal(15u, _publisher.Version); } [Fact] public async Task DmApiPublishUnpublishAllNodesTestAsync() { CopyContent("Resources/empty_pn.json", _tempFile); await using var configService = InitPublisherConfigService(); var methodsController = new ConfigurationController(configService); using var publishPayloads = new StreamReader("Resources/DmApiPayloadCollection.json"); var publishNodesRequest = _newtonSoftJsonSerializer.Deserialize>( await publishPayloads.ReadToEndAsync()); foreach (var request in publishNodesRequest) { var initialNode = request.OpcNodes[0]; for (var i = 0; i < 10000; i++) { request.OpcNodes.Add(new OpcNodeModel { Id = initialNode.Id + i.ToString(CultureInfo.InvariantCulture), DataSetFieldId = initialNode.DataSetFieldId, DisplayName = initialNode.DisplayName, ExpandedNodeId = initialNode.ExpandedNodeId, HeartbeatIntervalTimespan = initialNode.HeartbeatIntervalTimespan, OpcPublishingInterval = initialNode.OpcPublishingInterval, OpcSamplingInterval = initialNode.OpcSamplingInterval, QueueSize = initialNode.QueueSize, SkipFirst = initialNode.SkipFirst, DataChangeTrigger = initialNode.DataChangeTrigger, DeadbandType = initialNode.DeadbandType, DeadbandValue = initialNode.DeadbandValue }); } await FluentActions .Invoking(async () => await methodsController.PublishNodesAsync(request)) .Should() .NotThrowAsync(); } var writerGroup = Assert.Single(_publisher.WriterGroups); var unpublishAllNodesRequest = publishNodesRequest.GroupBy(pn => string.Concat(pn.EndpointUrl, pn.DataSetWriterId, pn.DataSetPublishingInterval)) .Select(g => g.First()).ToList(); foreach (var request in unpublishAllNodesRequest) { request.OpcNodes?.Clear(); await FluentActions .Invoking(async () => await methodsController .UnpublishAllNodesAsync(request)) .Should() .NotThrowAsync(); } Assert.Empty(_publisher.WriterGroups); } [Fact] public async Task DmApiPublishNodesToJobTestAsync() { CopyContent("Resources/empty_pn.json", _tempFile); await using var configService = InitPublisherConfigService(); var methodsController = new ConfigurationController(configService); using var publishPayloads = new StreamReader("Resources/DmApiPayloadCollection.json"); var publishNodesRequests = _newtonSoftJsonSerializer.Deserialize> (await publishPayloads.ReadToEndAsync()); foreach (var request in publishNodesRequests) { await FluentActions .Invoking(async () => await methodsController .PublishNodesAsync(request)) .Should() .NotThrowAsync() ; } var writerGroup = Assert.Single(_publisher.WriterGroups); writerGroup.DataSetWriters.Count.Should().Be(6); Assert.All(writerGroup.DataSetWriters, writer => Assert.Equal(publishNodesRequests[0].EndpointUrl, writer.DataSet.DataSetSource.Connection.Endpoint.Url)); Assert.Equal(publishNodesRequests .Select(n => (n.UseSecurity ?? false) ? SecurityMode.SignAndEncrypt : SecurityMode.None) .ToHashSet(), writerGroup.DataSetWriters .Select(w => w.DataSet.DataSetSource.Connection.Endpoint.SecurityMode.Value) .ToHashSet()); Assert.Equal(9, writerGroup.DataSetWriters.Sum(w => w.DataSet.DataSetSource.PublishedVariables.PublishedData.Count)); } [Fact] public async Task DmApiGetConfiguredNodesOnEndpointAsyncTestAsync() { const string endpointUrl = "opc.tcp://opcplc:50010"; var endpointRequest = new PublishedNodesEntryModel { EndpointUrl = endpointUrl }; var (d, methodsController) = await PublishNodeAsync("Resources/DmApiPayloadTwoEndpoints.json"); var response = await FluentActions .Invoking(async () => await methodsController .GetConfiguredNodesOnEndpointAsync(endpointRequest)) .Should() .NotThrowAsync(); await d.DisposeAsync(); response.Subject.OpcNodes.Count .Should() .Be(2); response.Subject.OpcNodes[0].Id .Should() .Be("ns=2;s=FastUInt1"); response.Subject.OpcNodes[1].Id .Should() .Be("ns=2;s=FastUInt2"); } [Fact] public async Task DmApiGetConfiguredNodesOnEndpointAsyncDataSetWriterGroupTestAsync() { const string endpointUrl = "opc.tcp://opcplc:50000"; const string dataSetWriterGroup = "Leaf0"; const string dataSetWriterId = "Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234"; const string dataSetName = "Tag_Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234"; const OpcAuthenticationMode authenticationMode = OpcAuthenticationMode.UsernamePassword; const string username = "usr"; const string password = "pwd"; var endpointRequest = new PublishedNodesEntryModel { EndpointUrl = endpointUrl, DataSetWriterGroup = dataSetWriterGroup, DataSetWriterId = dataSetWriterId, DataSetName = dataSetName, OpcAuthenticationMode = authenticationMode, OpcAuthenticationUsername = username, OpcAuthenticationPassword = password }; var (d, methodsController) = await PublishNodeAsync("Resources/DmApiPayloadTwoEndpoints.json", a => a.DataSetWriterGroup == "Leaf0"); var response = await FluentActions .Invoking(async () => await methodsController .GetConfiguredNodesOnEndpointAsync(endpointRequest)) .Should() .NotThrowAsync(); await d.DisposeAsync(); response.Subject.OpcNodes.Count .Should() .Be(1); response.Subject.OpcNodes[0].Id .Should() .Be("ns=2;s=SlowUInt1"); } [Fact] public async Task DmApiGetConfiguredNodesOnEndpointAsyncDataSetWriterIdTestAsync() { // Testing that we can differentiate between endpoints // even if they only have different DataSetWriterIds. var opcNodes = Enumerable.Range(0, 5) .Select(i => new OpcNodeModel { Id = $"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}" }) .ToList(); var endpoints = Enumerable.Range(0, 5) .Select(i => new PublishedNodesEntryModel { EndpointUrl = "opc.tcp://opcplc:50000", DataSetWriterId = i != 0 ? $"DataSetWriterId{i}" : null, OpcNodes = [.. opcNodes.GetRange(0, i + 1)] }) .ToList(); var (d, methodsController) = await PublishNodeAsync("Resources/empty_pn.json"); for (var i = 0; i < 5; ++i) { await methodsController.PublishNodesAsync(endpoints[i]); } for (var i = 0; i < 5; ++i) { var response = await FluentActions .Invoking(async () => await methodsController .GetConfiguredNodesOnEndpointAsync(endpoints[i])) .Should() .NotThrowAsync(); response.Subject.OpcNodes.Count .Should() .Be(i + 1); response.Subject.OpcNodes[response.Subject.OpcNodes.Count - 1].Id .Should() .Be($"nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt{i}"); } await d.DisposeAsync(); } [Fact] public async Task DmApiGetConfiguredNodesOnEndpointAsyncUseSecurityTestAsync() { const string endpointUrl = "opc.tcp://opcplc:50000"; const bool useSecurity = false; var endpointRequest = new PublishedNodesEntryModel { EndpointUrl = endpointUrl, UseSecurity = useSecurity }; var (d, methodsController) = await PublishNodeAsync("Resources/DmApiPayloadTwoEndpoints.json"); var response = await FluentActions .Invoking(async () => await methodsController .GetConfiguredNodesOnEndpointAsync(endpointRequest)) .Should() .NotThrowAsync(); await d.DisposeAsync(); response.Subject.OpcNodes.Count .Should() .Be(1); response.Subject.OpcNodes[0].Id .Should() .Be("ns=2;s=SlowUInt3"); } [Fact] public async Task DmApiGetConfiguredNodesOnEndpointAsyncOpcAuthenticationModeTestAsync() { const string endpointUrl = "opc.tcp://opcplc:50000"; const string dataSetWriterGroup = "Leaf1"; const string dataSetWriterId = "Leaf1_10000_3085991c-b85c-4311-9bfb-a916da952235"; const string dataSetName = "Tag_Leaf1_10000_3085991c-b85c-4311-9bfb-a916da952235"; const int dataSetPublishingInterval = 3000; const OpcAuthenticationMode authenticationMode = OpcAuthenticationMode.Anonymous; var endpointRequest = new PublishedNodesEntryModel { EndpointUrl = endpointUrl, DataSetWriterGroup = dataSetWriterGroup, DataSetWriterId = dataSetWriterId, DataSetName = dataSetName, DataSetPublishingInterval = dataSetPublishingInterval, OpcAuthenticationMode = authenticationMode }; var (d, methodsController) = await PublishNodeAsync("Resources/DmApiPayloadTwoEndpoints.json", a => a.DataSetWriterGroup == "Leaf1"); var response = await FluentActions .Invoking(async () => await methodsController .GetConfiguredNodesOnEndpointAsync(endpointRequest)) .Should() .NotThrowAsync(); await d.DisposeAsync(); response.Subject.OpcNodes.Count .Should() .Be(1); response.Subject.OpcNodes[0].Id .Should() .Be("ns=2;s=SlowUInt2"); } [Fact] public async Task DmApiGetConfiguredNodesOnEndpointAsyncUsernamePasswordTestAsync() { const string endpointUrl = "opc.tcp://opcplc:50000"; const OpcAuthenticationMode authenticationMode = OpcAuthenticationMode.UsernamePassword; const string username = "usr"; const string password = "pwd"; var endpointRequest = new PublishedNodesEntryModel { EndpointUrl = endpointUrl, OpcAuthenticationMode = authenticationMode, OpcAuthenticationUsername = username, OpcAuthenticationPassword = password }; var (d, methodsController) = await PublishNodeAsync("Resources/DmApiPayloadTwoEndpoints.json"); var response = await FluentActions .Invoking(async () => await methodsController .GetConfiguredNodesOnEndpointAsync(endpointRequest)) .Should() .NotThrowAsync(); await d.DisposeAsync(); response.Subject.OpcNodes.Count .Should() .Be(2); response.Subject.OpcNodes[0].Id .Should() .Be("ns=2;s=FastUInt3"); response.Subject.OpcNodes[1].Id .Should() .Be("ns=2;s=FastUInt4"); } /// /// publish nodes from publishedNodesFile /// /// /// private async Task<(PublishedNodesJsonServices, ConfigurationController)> PublishNodeAsync(string publishedNodesFile, Func predicate = null) { CopyContent("Resources/empty_pn.json", _tempFile); var configService = InitPublisherConfigService(); var methodsController = new ConfigurationController(configService); using var publishPayloads = new StreamReader(publishedNodesFile); var publishNodesRequest = _newtonSoftJsonSerializer.Deserialize>( await publishPayloads.ReadToEndAsync().ConfigureAwait(false)); foreach (var request in publishNodesRequest.Where(predicate ?? (_ => true))) { await FluentActions .Invoking(async () => await methodsController.PublishNodesAsync(request).ConfigureAwait(false)) .Should() .NotThrowAsync() .ConfigureAwait(false); } return (configService, methodsController); } [Theory] [InlineData("Resources/DmApiPayloadCollection.json")] public async Task DmApiGetConfiguredEndpointsTestAsync(string publishedNodesFile) { CopyContent("Resources/empty_pn.json", _tempFile); await using var configService = InitPublisherConfigService(); var methodsController = new ConfigurationController(configService); using var publishPayloads = new StreamReader(publishedNodesFile); var publishNodesRequests = _newtonSoftJsonSerializer.Deserialize> (await publishPayloads.ReadToEndAsync()); // Check that GetConfiguredEndpointsAsync returns empty list var endpoints = await FluentActions .Invoking(async () => await methodsController .GetConfiguredEndpointsAsync()) .Should() .NotThrowAsync(); endpoints.Subject.Endpoints.Count.Should().Be(0); // Publish nodes foreach (var request in publishNodesRequests) { await FluentActions .Invoking(async () => await methodsController .PublishNodesAsync(request)) .Should() .NotThrowAsync(); } // Check configured endpoints count endpoints = await FluentActions .Invoking(async () => await methodsController .GetConfiguredEndpointsAsync()) .Should() .NotThrowAsync(); endpoints.Subject.Endpoints.Count.Should().Be(5); var tags = endpoints.Subject.Endpoints.Select(e => e.DataSetName).ToHashSet(); tags.Should().Contain("Tag_Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234"); tags.Should().Contain("Tag_Leaf1_10000_2e4fc28f-ffa2-4532-9f22-378d47bbee5d"); tags.Should().Contain("Tag_Leaf2_10000_3085991c-b85c-4311-9bfb-a916da952234"); tags.Should().Contain("Tag_Leaf3_10000_2e4fc28f-ffa2-4532-9f22-378d47bbee5d"); tags.Should().Contain((string)null); var endpointsHash = endpoints.Subject.Endpoints.Select(e => e.GetHashCode()).ToList(); Assert.Equal(endpointsHash.Distinct().Count(), endpointsHash.Count); } [Fact] public async Task DmApiGetDiagnosticInfoTestAsync() { CopyContent("Resources/empty_pn.json", _tempFile); await using var configService = InitPublisherConfigService(); var methodsController = new ConfigurationController(configService); var response = await FluentActions .Invoking(async () => await methodsController .GetDiagnosticInfoAsync()) .Should() .NotThrowAsync(); response.Subject .Should() .NotBeNull(); } /// /// Copy content of source file to destination file. /// /// /// /// private static void CopyContent(string sourcePath, string destinationPath) { var content = GetFileContent(sourcePath); using var fileStream = new FileStream(destinationPath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite); fileStream.Write(Encoding.UTF8.GetBytes(content)); static string GetFileContent(string path) { using var payloadReader = new StreamReader(path); return payloadReader.ReadToEnd(); } } private readonly NewtonsoftJsonSerializer _newtonSoftJsonSerializer; private readonly ILoggerFactory _loggerFactory; private readonly PublishedNodesConverter _publishedNodesJobConverter; private readonly IOptions _options; private readonly PublishedNodesProvider _publishedNodesProvider; private readonly Mock _triggerMock; private readonly PublisherService _publisher; private readonly Mock _diagnostic; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/FileSystem/Json/BrowseTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.FileSystem.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(FileCollection.Name)] public sealed class BrowseTests : IClassFixture, IDisposable { public BrowseTests(FileSystemServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private BrowseTests GetTests() { return new BrowseTests( _client.Resolve>, _server.GetConnection(), _server.TempPath); } private readonly FileSystemServer _server; private readonly IContainer _client; [Fact] public Task GetFileSystemsTest1Async() { return GetTests().GetFileSystemsTest1Async(); } [Fact] public Task GetDirectoriesTest1Async() { return GetTests().GetDirectoriesTest1Async(); } [Fact] public Task GetDirectoriesTest2Async() { return GetTests().GetDirectoriesTest2Async(); } [Fact] public Task GetDirectoriesTest3Async() { return GetTests().GetDirectoriesTest3Async(); } [Fact] public Task GetDirectoriesTest4Async() { return GetTests().GetDirectoriesTest4Async(); } [Fact] public Task GetDirectoriesTest5Async() { return GetTests().GetDirectoriesTest5Async(); } [Fact] public Task GetDirectoriesTest6Async() { return GetTests().GetDirectoriesTest6Async(); } [Fact] public Task GetFilesTest1Async() { return GetTests().GetFilesTest1Async(); } [Fact] public Task GetFilesTest2Async() { return GetTests().GetFilesTest2Async(); } [Fact] public Task GetFilesTest3Async() { return GetTests().GetFilesTest3Async(); } [Fact] public Task GetFilesTest4Async() { return GetTests().GetFilesTest4Async(); } [Fact] public Task GetFilesTest5Async() { return GetTests().GetFilesTest5Async(); } [Fact] public Task GetFilesTest6Async() { return GetTests().GetFilesTest6Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/FileSystem/Json/FileCollection.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.FileSystem.Json { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public class FileCollection : ICollectionFixture { public const string Name = "FileSystemRestJson"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/FileSystem/Json/OperationsTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.FileSystem.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(FileCollection.Name)] public sealed class OperationsTests : IClassFixture, IDisposable { public OperationsTests(FileSystemServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private OperationsTests GetTests() { return new OperationsTests( _client.Resolve>, _server.GetConnection(), _server.TempPath); } private readonly FileSystemServer _server; private readonly IContainer _client; [Fact] public Task CreateDirectoryTest1Async() { return GetTests().CreateDirectoryTest1Async(); } [Fact] public Task CreateDirectoryTest2Async() { return GetTests().CreateDirectoryTest2Async(); } [Fact] public Task CreateDirectoryTest3Async() { return GetTests().CreateDirectoryTest3Async(); } [Fact] public Task CreateDirectoryTest4Async() { return GetTests().CreateDirectoryTest4Async(); } [SkippableFact] public Task DeleteDirectoryTest1Async() { Skip.If(true, "TODO"); return GetTests().DeleteDirectoryTest1Async(); } [Fact] public Task DeleteDirectoryTest2Async() { return GetTests().DeleteDirectoryTest2Async(); } [Fact] public Task DeleteDirectoryTest3Async() { return GetTests().DeleteDirectoryTest3Async(); } [Fact] public Task CreateFileTest1Async() { return GetTests().CreateFileTest1Async(); } [Fact] public Task CreateFileTest2Async() { return GetTests().CreateFileTest2Async(); } [Fact] public Task CreateFileTest3Async() { return GetTests().CreateFileTest3Async(); } [Fact] public Task CreateFileTest4Async() { return GetTests().CreateFileTest4Async(); } [Fact] public Task GetFileInfoTest1Async() { return GetTests().GetFileInfoTest1Async(); } [Fact] public Task GetFileInfoTest2Async() { return GetTests().GetFileInfoTest2Async(); } [Fact] public Task GetFileInfoTest3Async() { return GetTests().GetFileInfoTest3Async(); } [Fact] public Task DeleteFileTest1Async() { return GetTests().DeleteFileTest1Async(); } [SkippableFact] public Task DeleteFileTest2Async() { Skip.If(true, "TODO"); return GetTests().DeleteFileTest2Async(); } [Fact] public Task DeleteFileTest3Async() { return GetTests().DeleteFileTest3Async(); } [Fact] public Task DeleteFileTest4Async() { return GetTests().DeleteFileTest4Async(); } [Fact] public Task DeleteFileTest5Async() { return GetTests().DeleteFileTest5Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/FileSystem/Json/ReadTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.FileSystem.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(FileCollection.Name)] public sealed class ReadTests : IClassFixture, IDisposable { public ReadTests(FileSystemServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private ReadTests GetTests() { return new ReadTests( _client.Resolve>, _server.GetConnection(), _server.TempPath); } private readonly FileSystemServer _server; private readonly IContainer _client; [Fact] public Task ReadFileTest0Async() { return GetTests().ReadFileTest0Async(); } [SkippableFact] public Task ReadFileTest1Async() { Skip.If(true); return GetTests().ReadFileTest1Async(); } [SkippableFact] public Task ReadFileTest2Async() { Skip.If(true); return GetTests().ReadFileTest2Async(); } [SkippableFact] public Task ReadFileTest3Async() { Skip.If(true); return GetTests().ReadFileTest3Async(); } [SkippableFact] public Task ReadFileTest4Async() { Skip.If(true); return GetTests().ReadFileTest4Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/FileSystem/Json/WriteTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.FileSystem.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(FileCollection.Name)] public sealed class WriteTests : IClassFixture, IDisposable { public WriteTests(FileSystemServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private WriteTests GetTests() { return new WriteTests( _client.Resolve>, _server.GetConnection(), _server.TempPath); } private readonly FileSystemServer _server; private readonly IContainer _client; [Fact] public Task WriteFileTest0Async() { return GetTests().WriteFileTest0Async(); } [SkippableFact] public Task WriteFileTest1Async() { Skip.If(true); return GetTests().WriteFileTest1Async(); } [SkippableFact] public Task WriteFileTest2Async() { Skip.If(true); return GetTests().WriteFileTest2Async(); } [Fact] public Task AppendFileTest0Async() { return GetTests().AppendFileTest0Async(); } [SkippableFact] public Task AppendFileTest1Async() { Skip.If(true); return GetTests().AppendFileTest1Async(); } [Fact] public Task AppendFileTest2Async() { return GetTests().AppendFileTest2Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/FileSystem/MsgPack/BrowseTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.FileSystem.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(FileCollection.Name)] public sealed class BrowseTests : IClassFixture, IDisposable { public BrowseTests(FileSystemServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private BrowseTests GetTests() { return new BrowseTests( _client.Resolve>, _server.GetConnection(), _server.TempPath); } private readonly FileSystemServer _server; private readonly IContainer _client; [Fact] public Task GetFileSystemsTest1Async() { return GetTests().GetFileSystemsTest1Async(); } [Fact] public Task GetDirectoriesTest1Async() { return GetTests().GetDirectoriesTest1Async(); } [Fact] public Task GetDirectoriesTest2Async() { return GetTests().GetDirectoriesTest2Async(); } [Fact] public Task GetDirectoriesTest3Async() { return GetTests().GetDirectoriesTest3Async(); } [Fact] public Task GetDirectoriesTest4Async() { return GetTests().GetDirectoriesTest4Async(); } [Fact] public Task GetDirectoriesTest5Async() { return GetTests().GetDirectoriesTest5Async(); } [Fact] public Task GetDirectoriesTest6Async() { return GetTests().GetDirectoriesTest6Async(); } [Fact] public Task GetFilesTest1Async() { return GetTests().GetFilesTest1Async(); } [Fact] public Task GetFilesTest2Async() { return GetTests().GetFilesTest2Async(); } [Fact] public Task GetFilesTest3Async() { return GetTests().GetFilesTest3Async(); } [Fact] public Task GetFilesTest4Async() { return GetTests().GetFilesTest4Async(); } [Fact] public Task GetFilesTest5Async() { return GetTests().GetFilesTest5Async(); } [Fact] public Task GetFilesTest6Async() { return GetTests().GetFilesTest6Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/FileSystem/MsgPack/FileCollection.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.FileSystem.MsgPack { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public class FileCollection : ICollectionFixture { public const string Name = "FileSystemRestMsgPack"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/FileSystem/MsgPack/OperationsTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.FileSystem.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(FileCollection.Name)] public sealed class OperationsTests : IClassFixture, IDisposable { public OperationsTests(FileSystemServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private OperationsTests GetTests() { return new OperationsTests( _client.Resolve>, _server.GetConnection(), _server.TempPath); } private readonly FileSystemServer _server; private readonly IContainer _client; [Fact] public Task CreateDirectoryTest1Async() { return GetTests().CreateDirectoryTest1Async(); } [Fact] public Task CreateDirectoryTest2Async() { return GetTests().CreateDirectoryTest2Async(); } [Fact] public Task CreateDirectoryTest3Async() { return GetTests().CreateDirectoryTest3Async(); } [Fact] public Task CreateDirectoryTest4Async() { return GetTests().CreateDirectoryTest4Async(); } [SkippableFact] public Task DeleteDirectoryTest1Async() { Skip.If(true, "TODO"); return GetTests().DeleteDirectoryTest1Async(); } [Fact] public Task DeleteDirectoryTest2Async() { return GetTests().DeleteDirectoryTest2Async(); } [Fact] public Task DeleteDirectoryTest3Async() { return GetTests().DeleteDirectoryTest3Async(); } [Fact] public Task CreateFileTest1Async() { return GetTests().CreateFileTest1Async(); } [Fact] public Task CreateFileTest2Async() { return GetTests().CreateFileTest2Async(); } [Fact] public Task CreateFileTest3Async() { return GetTests().CreateFileTest3Async(); } [Fact] public Task CreateFileTest4Async() { return GetTests().CreateFileTest4Async(); } [Fact] public Task GetFileInfoTest1Async() { return GetTests().GetFileInfoTest1Async(); } [Fact] public Task GetFileInfoTest2Async() { return GetTests().GetFileInfoTest2Async(); } [Fact] public Task GetFileInfoTest3Async() { return GetTests().GetFileInfoTest3Async(); } [Fact] public Task DeleteFileTest1Async() { return GetTests().DeleteFileTest1Async(); } [SkippableFact] public Task DeleteFileTest2Async() { Skip.If(true, "TODO"); return GetTests().DeleteFileTest2Async(); } [Fact] public Task DeleteFileTest3Async() { return GetTests().DeleteFileTest3Async(); } [Fact] public Task DeleteFileTest4Async() { return GetTests().DeleteFileTest4Async(); } [Fact] public Task DeleteFileTest5Async() { return GetTests().DeleteFileTest5Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/FileSystem/MsgPack/ReadTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.FileSystem.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(FileCollection.Name)] public sealed class ReadTests : IClassFixture, IDisposable { public ReadTests(FileSystemServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private ReadTests GetTests() { return new ReadTests( _client.Resolve>, _server.GetConnection(), _server.TempPath); } private readonly FileSystemServer _server; private readonly IContainer _client; [Fact] public Task ReadFileTest0Async() { return GetTests().ReadFileTest0Async(); } [SkippableFact] public Task ReadFileTest1Async() { Skip.If(true); return GetTests().ReadFileTest1Async(); } [SkippableFact] public Task ReadFileTest2Async() { Skip.If(true); return GetTests().ReadFileTest2Async(); } [SkippableFact] public Task ReadFileTest3Async() { Skip.If(true); return GetTests().ReadFileTest3Async(); } [SkippableFact] public Task ReadFileTest4Async() { Skip.If(true); return GetTests().ReadFileTest4Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/FileSystem/MsgPack/WriteTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.FileSystem.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(FileCollection.Name)] public sealed class WriteTests : IClassFixture, IDisposable { public WriteTests(FileSystemServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private WriteTests GetTests() { return new WriteTests( _client.Resolve>, _server.GetConnection(), _server.TempPath); } private readonly FileSystemServer _server; private readonly IContainer _client; [Fact] public Task WriteFileTest0Async() { return GetTests().WriteFileTest0Async(); } [SkippableFact] public Task WriteFileTest1Async() { Skip.If(true); return GetTests().WriteFileTest1Async(); } [SkippableFact] public Task WriteFileTest2Async() { Skip.If(true); return GetTests().WriteFileTest2Async(); } [Fact] public Task AppendFileTest0Async() { return GetTests().AppendFileTest0Async(); } [SkippableFact] public Task AppendFileTest1Async() { Skip.If(true); return GetTests().AppendFileTest1Async(); } [Fact] public Task AppendFileTest2Async() { return GetTests().AppendFileTest2Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/HistoricalAccess/Json/NodeServicesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.HistoricalAccess.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class NodeServicesTests : IClassFixture, IDisposable { public NodeServicesTests(HistoricalAccessServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private NodeHistoricalAccessTests GetTests() { return new NodeHistoricalAccessTests( _client.Resolve>, _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly IContainer _client; [Fact] public Task GetServerCapabilitiesTestAsync() { return GetTests().GetServerCapabilitiesTestAsync(); } [Fact] public Task HistoryGetServerCapabilitiesTestAsync() { return GetTests().HistoryGetServerCapabilitiesTestAsync(); } [Fact] public Task HistoryGetInt16NodeHistoryConfiguration() { return GetTests().HistoryGetInt16NodeHistoryConfigurationAsync(); } [Fact] public Task HistoryGetInt64NodeHistoryConfigurationAsync() { return GetTests().HistoryGetInt64NodeHistoryConfigurationAsync(); } [Fact] public Task HistoryGetNodeHistoryConfigurationFromBadNode() { return GetTests().HistoryGetNodeHistoryConfigurationFromBadNodeAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/HistoricalAccess/Json/ReadAtTimesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.HistoricalAccess.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class ReadAtTimesTests : IClassFixture, IDisposable { public ReadAtTimesTests(HistoricalAccessServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private HistoryReadValuesAtTimesTests GetTests() { return new HistoryReadValuesAtTimesTests(_server, _client.Resolve>, _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly IContainer _client; [Fact] public Task HistoryReadInt32ValuesAtTimesTest1Async() { return GetTests().HistoryReadInt32ValuesAtTimesTest1Async(); } [Fact] public Task HistoryReadInt32ValuesAtTimesTest2Async() { return GetTests().HistoryReadInt32ValuesAtTimesTest2Async(); } [Fact] public Task HistoryReadInt32ValuesAtTimesTest3Async() { return GetTests().HistoryReadInt32ValuesAtTimesTest3Async(); } [Fact] public Task HistoryReadInt32ValuesAtTimesTest4Async() { return GetTests().HistoryReadInt32ValuesAtTimesTest4Async(); } [Fact] public Task HistoryStreamInt32ValuesAtTimesTest1Async() { return GetTests().HistoryStreamInt32ValuesAtTimesTest1Async(); } [Fact] public Task HistoryStreamInt32ValuesAtTimesTest2Async() { return GetTests().HistoryStreamInt32ValuesAtTimesTest2Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/HistoricalAccess/Json/ReadCollection.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.HistoricalAccess.Json { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public sealed class ReadCollection : ICollectionFixture { public const string Name = "HistoricalAccessServerReadRestJson"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/HistoricalAccess/Json/ReadModifiedTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.HistoricalAccess.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class ReadModifiedTests : IClassFixture, IDisposable { public ReadModifiedTests(HistoricalAccessServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private HistoryReadValuesModifiedTests GetTests() { return new HistoryReadValuesModifiedTests(_server, _client.Resolve>, _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly IContainer _client; [Fact] public Task HistoryReadInt16ValuesModifiedTestAsync() { return GetTests().HistoryReadInt16ValuesModifiedTestAsync(); } [Fact] public Task HistoryStreamInt16ValuesModifiedTestAsync() { return GetTests().HistoryStreamInt16ValuesModifiedTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/HistoricalAccess/Json/ReadProcessedTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.HistoricalAccess.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class ReadProcessedTests : IClassFixture, IDisposable { public ReadProcessedTests(HistoricalAccessServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private HistoryReadValuesProcessedTests GetTests() { return new HistoryReadValuesProcessedTests(_server, _client.Resolve>, _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly IContainer _client; [Fact] public Task HistoryReadUInt64ProcessedValuesTest1Async() { return GetTests().HistoryReadUInt64ProcessedValuesTest1Async(); } [Fact] public Task HistoryReadUInt64ProcessedValuesTest2Async() { return GetTests().HistoryReadUInt64ProcessedValuesTest2Async(); } [Fact] public Task HistoryReadUInt64ProcessedValuesTest3Async() { return GetTests().HistoryReadUInt64ProcessedValuesTest3Async(); } [Fact] public Task HistoryStreamUInt64ProcessedValuesTest1Async() { return GetTests().HistoryStreamUInt64ProcessedValuesTest1Async(); } [Fact] public Task HistoryStreamUInt64ProcessedValuesTest2Async() { return GetTests().HistoryStreamUInt64ProcessedValuesTest2Async(); } [Fact] public Task HistoryStreamUInt64ProcessedValuesTest3Async() { return GetTests().HistoryStreamUInt64ProcessedValuesTest3Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/HistoricalAccess/Json/ReadValuesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.HistoricalAccess.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class ReadValuesTests : IClassFixture, IDisposable { public ReadValuesTests(HistoricalAccessServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private HistoryReadValuesTests GetTests() { return new HistoryReadValuesTests(_server, _client.Resolve>, _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly IContainer _client; [Fact] public Task HistoryReadInt64ValuesTest1Async() { return GetTests().HistoryReadInt64ValuesTest1Async(); } [Fact] public Task HistoryReadInt64ValuesTest2Async() { return GetTests().HistoryReadInt64ValuesTest2Async(); } [Fact] public Task HistoryReadInt64ValuesTest3Async() { return GetTests().HistoryReadInt64ValuesTest3Async(); } [Fact] public Task HistoryReadInt64ValuesTest4Async() { return GetTests().HistoryReadInt64ValuesTest4Async(); } [Fact] public Task HistoryStreamInt64ValuesTest1Async() { return GetTests().HistoryStreamInt64ValuesTest1Async(); } [Fact] public Task HistoryStreamInt64ValuesTest2Async() { return GetTests().HistoryStreamInt64ValuesTest2Async(); } [Fact] public Task HistoryStreamInt64ValuesTest3Async() { return GetTests().HistoryStreamInt64ValuesTest3Async(); } [Fact] public Task HistoryStreamInt64ValuesTest4Async() { return GetTests().HistoryStreamInt64ValuesTest4Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/HistoricalAccess/Json/UpdateValuesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.HistoricalAccess.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class UpdateValuesTests : IClassFixture, IDisposable { public UpdateValuesTests(HistoricalAccessServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private HistoryUpdateValuesTests GetTests() { return new HistoryUpdateValuesTests( _client.Resolve>, _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly IContainer _client; [Fact] public Task HistoryUpsertUInt32ValuesTest1Async() { return GetTests().HistoryUpsertUInt32ValuesTest1Async(); } [Fact] public Task HistoryUpsertUInt32ValuesTest2Async() { return GetTests().HistoryUpsertUInt32ValuesTest2Async(); } [Fact] public Task HistoryInsertUInt32ValuesTest1Async() { return GetTests().HistoryInsertUInt32ValuesTest1Async(); } [Fact] public Task HistoryInsertUInt32ValuesTest2Async() { return GetTests().HistoryInsertUInt32ValuesTest2Async(); } [Fact] public Task HistoryReplaceUInt32ValuesTest1Async() { return GetTests().HistoryReplaceUInt32ValuesTest1Async(); } [Fact] public Task HistoryReplaceUInt32ValuesTest2Async() { return GetTests().HistoryReplaceUInt32ValuesTest2Async(); } [Fact] public Task HistoryInsertDeleteUInt32ValuesTest1Async() { return GetTests().HistoryInsertDeleteUInt32ValuesTest1Async(); } [Fact] public Task HistoryInsertDeleteUInt32ValuesTest2Async() { return GetTests().HistoryInsertDeleteUInt32ValuesTest2Async(); } [Fact] public Task HistoryInsertDeleteUInt32ValuesTest3Async() { return GetTests().HistoryInsertDeleteUInt32ValuesTest3Async(); } [Fact] public Task HistoryInsertDeleteUInt32ValuesTest4Async() { return GetTests().HistoryInsertDeleteUInt32ValuesTest4Async(); } [Fact] public Task HistoryDeleteUInt32ValuesTest1Async() { return GetTests().HistoryDeleteUInt32ValuesTest1Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/HistoricalAccess/MsgPack/NodeServicesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.HistoricalAccess.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class NodeServicesTests : IClassFixture, IDisposable { public NodeServicesTests(HistoricalAccessServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private NodeHistoricalAccessTests GetTests() { return new NodeHistoricalAccessTests( _client.Resolve>, _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly IContainer _client; [Fact] public Task GetServerCapabilitiesTestAsync() { return GetTests().GetServerCapabilitiesTestAsync(); } [Fact] public Task HistoryGetServerCapabilitiesTestAsync() { return GetTests().HistoryGetServerCapabilitiesTestAsync(); } [Fact] public Task HistoryGetInt16NodeHistoryConfiguration() { return GetTests().HistoryGetInt16NodeHistoryConfigurationAsync(); } [Fact] public Task HistoryGetInt64NodeHistoryConfigurationAsync() { return GetTests().HistoryGetInt64NodeHistoryConfigurationAsync(); } [Fact] public Task HistoryGetNodeHistoryConfigurationFromBadNode() { return GetTests().HistoryGetNodeHistoryConfigurationFromBadNodeAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/HistoricalAccess/MsgPack/ReadAtTimesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.HistoricalAccess.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class ReadAtTimesTests : IClassFixture, IDisposable { public ReadAtTimesTests(HistoricalAccessServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private HistoryReadValuesAtTimesTests GetTests() { return new HistoryReadValuesAtTimesTests(_server, _client.Resolve>, _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly IContainer _client; [Fact] public Task HistoryReadInt32ValuesAtTimesTest1Async() { return GetTests().HistoryReadInt32ValuesAtTimesTest1Async(); } [Fact] public Task HistoryReadInt32ValuesAtTimesTest2Async() { return GetTests().HistoryReadInt32ValuesAtTimesTest2Async(); } [Fact] public Task HistoryReadInt32ValuesAtTimesTest3Async() { return GetTests().HistoryReadInt32ValuesAtTimesTest3Async(); } [Fact] public Task HistoryReadInt32ValuesAtTimesTest4Async() { return GetTests().HistoryReadInt32ValuesAtTimesTest4Async(); } [SkippableFact] public Task HistoryStreamInt32ValuesAtTimesTest1Async() { Skip.If(true, "Not yet supported"); return GetTests().HistoryStreamInt32ValuesAtTimesTest1Async(); } [SkippableFact] public Task HistoryStreamInt32ValuesAtTimesTest2Async() { return GetTests().HistoryStreamInt32ValuesAtTimesTest2Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/HistoricalAccess/MsgPack/ReadCollection.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.HistoricalAccess.MsgPack { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public sealed class ReadCollection : ICollectionFixture { public const string Name = "HistoricalAccessServerReadRestMsgPack"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/HistoricalAccess/MsgPack/ReadModifiedTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.HistoricalAccess.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class ReadModifiedTests : IClassFixture, IDisposable { public ReadModifiedTests(HistoricalAccessServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private HistoryReadValuesModifiedTests GetTests() { return new HistoryReadValuesModifiedTests(_server, _client.Resolve>, _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly IContainer _client; [Fact] public Task HistoryReadInt16ValuesModifiedTestAsync() { return GetTests().HistoryReadInt16ValuesModifiedTestAsync(); } [SkippableFact] public Task HistoryStreamInt16ValuesModifiedTestAsync() { return GetTests().HistoryStreamInt16ValuesModifiedTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/HistoricalAccess/MsgPack/ReadProcessedTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.HistoricalAccess.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class ReadProcessedTests : IClassFixture, IDisposable { public ReadProcessedTests(HistoricalAccessServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private HistoryReadValuesProcessedTests GetTests() { return new HistoryReadValuesProcessedTests(_server, _client.Resolve>, _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly IContainer _client; [Fact] public Task HistoryReadUInt64ProcessedValuesTest1Async() { return GetTests().HistoryReadUInt64ProcessedValuesTest1Async(); } [Fact] public Task HistoryReadUInt64ProcessedValuesTest2Async() { return GetTests().HistoryReadUInt64ProcessedValuesTest2Async(); } [SkippableFact] public Task HistoryReadUInt64ProcessedValuesTest3Async() { return GetTests().HistoryReadUInt64ProcessedValuesTest3Async(); } [SkippableFact] public Task HistoryStreamUInt64ProcessedValuesTest1Async() { return GetTests().HistoryStreamUInt64ProcessedValuesTest1Async(); } [SkippableFact] public Task HistoryStreamUInt64ProcessedValuesTest2Async() { return GetTests().HistoryStreamUInt64ProcessedValuesTest2Async(); } [SkippableFact] public Task HistoryStreamUInt64ProcessedValuesTest3Async() { return GetTests().HistoryStreamUInt64ProcessedValuesTest3Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/HistoricalAccess/MsgPack/ReadValuesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.HistoricalAccess.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class ReadValuesTests : IClassFixture, IDisposable { public ReadValuesTests(HistoricalAccessServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private HistoryReadValuesTests GetTests() { return new HistoryReadValuesTests(_server, _client.Resolve>, _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly IContainer _client; [Fact] public Task HistoryReadInt64ValuesTest1Async() { return GetTests().HistoryReadInt64ValuesTest1Async(); } [Fact] public Task HistoryReadInt64ValuesTest2Async() { return GetTests().HistoryReadInt64ValuesTest2Async(); } [Fact] public Task HistoryReadInt64ValuesTest3Async() { return GetTests().HistoryReadInt64ValuesTest3Async(); } [Fact] public Task HistoryReadInt64ValuesTest4Async() { return GetTests().HistoryReadInt64ValuesTest4Async(); } [SkippableFact] public Task HistoryStreamInt64ValuesTest1Async() { return GetTests().HistoryStreamInt64ValuesTest1Async(); } [SkippableFact] public Task HistoryStreamInt64ValuesTest2Async() { return GetTests().HistoryStreamInt64ValuesTest2Async(); } [SkippableFact] public Task HistoryStreamInt64ValuesTest3Async() { return GetTests().HistoryStreamInt64ValuesTest3Async(); } [SkippableFact] public Task HistoryStreamInt64ValuesTest4Async() { return GetTests().HistoryStreamInt64ValuesTest4Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/HistoricalAccess/MsgPack/UpdateValuesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.HistoricalAccess.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class UpdateValuesTests : IClassFixture, IDisposable { public UpdateValuesTests(HistoricalAccessServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private HistoryUpdateValuesTests GetTests() { return new HistoryUpdateValuesTests( _client.Resolve>, _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly IContainer _client; [Fact] public Task HistoryUpsertUInt32ValuesTest1Async() { return GetTests().HistoryUpsertUInt32ValuesTest1Async(); } [Fact] public Task HistoryUpsertUInt32ValuesTest2Async() { return GetTests().HistoryUpsertUInt32ValuesTest2Async(); } [Fact] public Task HistoryInsertUInt32ValuesTest1Async() { return GetTests().HistoryInsertUInt32ValuesTest1Async(); } [Fact] public Task HistoryInsertUInt32ValuesTest2Async() { return GetTests().HistoryInsertUInt32ValuesTest2Async(); } [Fact] public Task HistoryReplaceUInt32ValuesTest1Async() { return GetTests().HistoryReplaceUInt32ValuesTest1Async(); } [Fact] public Task HistoryReplaceUInt32ValuesTest2Async() { return GetTests().HistoryReplaceUInt32ValuesTest2Async(); } [Fact] public Task HistoryInsertDeleteUInt32ValuesTest1Async() { return GetTests().HistoryInsertDeleteUInt32ValuesTest1Async(); } [Fact] public Task HistoryInsertDeleteUInt32ValuesTest2Async() { return GetTests().HistoryInsertDeleteUInt32ValuesTest2Async(); } [Fact] public Task HistoryInsertDeleteUInt32ValuesTest3Async() { return GetTests().HistoryInsertDeleteUInt32ValuesTest3Async(); } [Fact] public Task HistoryInsertDeleteUInt32ValuesTest4Async() { return GetTests().HistoryInsertDeleteUInt32ValuesTest4Async(); } [Fact] public Task HistoryDeleteUInt32ValuesTest1Async() { return GetTests().HistoryDeleteUInt32ValuesTest1Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/HistoricalEvents/Json/NodeServicesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.HistoricalEvents.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class NodeServicesTests : IClassFixture, IDisposable { public NodeServicesTests(HistoricalEventsServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private NodeHistoricalEventsTests GetTests() { return new NodeHistoricalEventsTests( _client.Resolve>, _server.GetConnection()); } private readonly HistoricalEventsServer _server; private readonly IContainer _client; [Fact] public Task GetServerCapabilitiesTestAsync() { return GetTests().GetServerCapabilitiesTestAsync(); } [Fact] public Task HistoryGetServerCapabilitiesTestAsync() { return GetTests().HistoryGetServerCapabilitiesTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/HistoricalEvents/Json/ReadCollection.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.HistoricalEvents.Json { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public sealed class ReadCollection : ICollectionFixture { public const string Name = "HistoricalEventsServerReadRestJson"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/HistoricalEvents/MsgPack/NodeServicesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.HistoricalEvents.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class NodeServicesTests : IClassFixture, IDisposable { public NodeServicesTests(HistoricalEventsServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private NodeHistoricalEventsTests GetTests() { return new NodeHistoricalEventsTests( _client.Resolve>, _server.GetConnection()); } private readonly HistoricalEventsServer _server; private readonly IContainer _client; [Fact] public Task GetServerCapabilitiesTestAsync() { return GetTests().GetServerCapabilitiesTestAsync(); } [Fact] public Task HistoryGetServerCapabilitiesTestAsync() { return GetTests().HistoryGetServerCapabilitiesTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/HistoricalEvents/MsgPack/ReadCollection.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.HistoricalEvents.MsgPack { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public sealed class ReadCollection : ICollectionFixture { public const string Name = "HistoricalEventsServerReadRestMsgPack"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/Plc/Json/NodeServicesTests1.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.Plc.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class NodeServicesTests1 : IClassFixture, IClassFixture, IDisposable { public NodeServicesTests1(PlcServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private SimulatorNodesTests GetTests() { return new SimulatorNodesTests(_server, _client.Resolve>, _server.GetConnection()); } private readonly PlcServer _server; private readonly IContainer _client; [Fact] public Task AlternatingBooleanTelemetryChangesWithPeriodAsync() { return GetTests().AlternatingBooleanTelemetryChangesWithPeriodAsync(); } [Fact] public Task BadNodeHasAlternatingStatusCodeAsync() { return GetTests().BadNodeHasAlternatingStatusCodeAsync(); } [Fact] public Task FastLimitNumberOfUpdatesStopsUpdatingAfterLimitAsync() { return GetTests().FastLimitNumberOfUpdatesStopsUpdatingAfterLimitAsync(); } [Fact] public Task FastUIntScalar1TelemetryChangesWithPeriodAsync() { return GetTests().FastUIntScalar1TelemetryChangesWithPeriodAsync(); } [Fact] public Task NegativeTrendDataNodeHasValueWithTrendAsync() { return GetTests().NegativeTrendDataNodeHasValueWithTrendAsync(); } [Fact] public Task NegativeTrendDataTelemetryChangesWithPeriodAsync() { return GetTests().NegativeTrendDataTelemetryChangesWithPeriodAsync(); } [Fact] public Task PositiveTrendDataNodeHasValueWithTrendAsync() { return GetTests().PositiveTrendDataNodeHasValueWithTrendAsync(); } [Fact] public Task PositiveTrendDataTelemetryChangesWithPeriodAsync() { return GetTests().PositiveTrendDataTelemetryChangesWithPeriodAsync(); } [Fact] public Task RandomSignedInt32TelemetryChangesWithPeriodAsync() { return GetTests().RandomSignedInt32TelemetryChangesWithPeriodAsync(); } [Fact] public Task RandomUnsignedInt32TelemetryChangesWithPeriodAsync() { return GetTests().RandomUnsignedInt32TelemetryChangesWithPeriodAsync(); } [Fact] public Task SlowLimitNumberOfUpdatesStopsUpdatingAfterLimitAsync() { return GetTests().SlowLimitNumberOfUpdatesStopsUpdatingAfterLimitAsync(); } [Fact] public Task SlowUIntScalar1TelemetryChangesWithPeriodAsync() { return GetTests().SlowUIntScalar1TelemetryChangesWithPeriodAsync(); } [Fact] public Task TelemetryContainsOutlierInDipDataAsync() { return GetTests().TelemetryContainsOutlierInDipDataAsync(); } [Fact] public Task TelemetryContainsOutlierInSpikeDataAsync() { return GetTests().TelemetryContainsOutlierInSpikeDataAsync(); } [Fact] public Task TelemetryFastNodeTestAsync() { return GetTests().TelemetryFastNodeTestAsync(); } [Fact] public Task TelemetryStepUpTestAsync() { return GetTests().TelemetryStepUpTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/Plc/Json/NodeServicesTests2.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.Plc.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class NodeServicesTests2 : IClassFixture, IClassFixture, IDisposable { public NodeServicesTests2(PlcServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private PlcModelComplexTypeTests GetTests() { return new PlcModelComplexTypeTests(_server, _client.Resolve>, _server.GetConnection()); } private readonly PlcServer _server; private readonly IContainer _client; [Fact] public Task PlcModelHeaterTestsAsync() { return GetTests().PlcModelHeaterTestsAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/Plc/MsgPack/NodeServicesTests1.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.Plc.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class NodeServicesTests1 : IClassFixture, IClassFixture, IDisposable { public NodeServicesTests1(PlcServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private SimulatorNodesTests GetTests() { return new SimulatorNodesTests(_server, _client.Resolve>, _server.GetConnection()); } private readonly PlcServer _server; private readonly IContainer _client; [Fact] public Task AlternatingBooleanTelemetryChangesWithPeriodAsync() { return GetTests().AlternatingBooleanTelemetryChangesWithPeriodAsync(); } [Fact] public Task BadNodeHasAlternatingStatusCodeAsync() { return GetTests().BadNodeHasAlternatingStatusCodeAsync(); } [Fact] public Task FastLimitNumberOfUpdatesStopsUpdatingAfterLimitAsync() { return GetTests().FastLimitNumberOfUpdatesStopsUpdatingAfterLimitAsync(); } [Fact] public Task FastUIntScalar1TelemetryChangesWithPeriodAsync() { return GetTests().FastUIntScalar1TelemetryChangesWithPeriodAsync(); } [Fact] public Task NegativeTrendDataNodeHasValueWithTrendAsync() { return GetTests().NegativeTrendDataNodeHasValueWithTrendAsync(); } [Fact] public Task NegativeTrendDataTelemetryChangesWithPeriodAsync() { return GetTests().NegativeTrendDataTelemetryChangesWithPeriodAsync(); } [Fact] public Task PositiveTrendDataNodeHasValueWithTrendAsync() { return GetTests().PositiveTrendDataNodeHasValueWithTrendAsync(); } [Fact] public Task PositiveTrendDataTelemetryChangesWithPeriodAsync() { return GetTests().PositiveTrendDataTelemetryChangesWithPeriodAsync(); } [Fact] public Task RandomSignedInt32TelemetryChangesWithPeriodAsync() { return GetTests().RandomSignedInt32TelemetryChangesWithPeriodAsync(); } [Fact] public Task RandomUnsignedInt32TelemetryChangesWithPeriodAsync() { return GetTests().RandomUnsignedInt32TelemetryChangesWithPeriodAsync(); } [Fact] public Task SlowLimitNumberOfUpdatesStopsUpdatingAfterLimitAsync() { return GetTests().SlowLimitNumberOfUpdatesStopsUpdatingAfterLimitAsync(); } [Fact] public Task SlowUIntScalar1TelemetryChangesWithPeriodAsync() { return GetTests().SlowUIntScalar1TelemetryChangesWithPeriodAsync(); } [Fact] public Task TelemetryContainsOutlierInDipDataAsync() { return GetTests().TelemetryContainsOutlierInDipDataAsync(); } [Fact] public Task TelemetryContainsOutlierInSpikeDataAsync() { return GetTests().TelemetryContainsOutlierInSpikeDataAsync(); } [Fact] public Task TelemetryFastNodeTestAsync() { return GetTests().TelemetryFastNodeTestAsync(); } [Fact] public Task TelemetryStepUpTestAsync() { return GetTests().TelemetryStepUpTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/Plc/MsgPack/NodeServicesTests2.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.Plc.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class NodeServicesTests2 : IClassFixture, IClassFixture, IDisposable { public NodeServicesTests2(PlcServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private PlcModelComplexTypeTests GetTests() { return new PlcModelComplexTypeTests(_server, _client.Resolve>, _server.GetConnection()); } private readonly PlcServer _server; private readonly IContainer _client; [Fact] public Task PlcModelHeaterTestsAsync() { return GetTests().PlcModelHeaterTestsAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/SimpleEvents/Json/NodeServicesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.SimpleEvents.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class NodeServicesTests : IClassFixture, IClassFixture, IDisposable { public NodeServicesTests(SimpleEventsServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private SimpleEventsServerTests GetTests() { return new SimpleEventsServerTests( _client.Resolve>, _server.GetConnection()); } private readonly SimpleEventsServer _server; private readonly IContainer _client; [Fact] public Task CompileSimpleBaseEventQueryTestAsync() { return GetTests().CompileSimpleBaseEventQueryTestAsync(); } [Fact] public Task CompileSimpleEventsQueryTestAsync() { return GetTests().CompileSimpleEventsQueryTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/SimpleEvents/MsgPack/NodeServicesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.SimpleEvents.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class NodeServicesTests : IClassFixture, IClassFixture, IDisposable { public NodeServicesTests(SimpleEventsServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private SimpleEventsServerTests GetTests() { return new SimpleEventsServerTests( _client.Resolve>, _server.GetConnection()); } private readonly SimpleEventsServer _server; private readonly IContainer _client; [Fact] public Task CompileSimpleBaseEventQueryTestAsync() { return GetTests().CompileSimpleBaseEventQueryTestAsync(); } [Fact] public Task CompileSimpleEventsQueryTestAsync() { return GetTests().CompileSimpleEventsQueryTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/Json/BrowsePathTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class BrowsePathTests : IClassFixture, IDisposable { public BrowsePathTests(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private BrowsePathTests GetTests() { return new BrowsePathTests( _client.Resolve>, _server.GetConnection()); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task NodeBrowsePathStaticScalarMethod3Test1Async() { return GetTests().NodeBrowsePathStaticScalarMethod3Test1Async(); } [Fact] public Task NodeBrowsePathStaticScalarMethod3Test2Async() { return GetTests().NodeBrowsePathStaticScalarMethod3Test2Async(); } [Fact] public Task NodeBrowsePathStaticScalarMethod3Test3Async() { return GetTests().NodeBrowsePathStaticScalarMethod3Test3Async(); } [Fact] public Task NodeBrowsePathStaticScalarMethodsTestAsync() { return GetTests().NodeBrowsePathStaticScalarMethodsTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/Json/BrowseStreamTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class BrowseStreamTests : IClassFixture, IDisposable { public BrowseStreamTests(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private BrowseStreamTests GetTests() { return new BrowseStreamTests( _client.Resolve>, _server.GetConnection()); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task NodeBrowseInRootTest1Async() { return GetTests().NodeBrowseInRootTest1Async(); } [Fact] public Task NodeBrowseInRootTest2Async() { return GetTests().NodeBrowseInRootTest2Async(); } [Fact] public Task NodeBrowseBoilersObjectsTest1Async() { return GetTests().NodeBrowseBoilersObjectsTest1Async(); } [Fact] public Task NodeBrowseDataAccessObjectsTest1Async() { return GetTests().NodeBrowseDataAccessObjectsTest1Async(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestAsync() { return GetTests().NodeBrowseStaticScalarVariablesTestAsync(); } [Fact] public Task NodeBrowseStaticArrayVariablesTestAsync() { return GetTests().NodeBrowseStaticArrayVariablesTestAsync(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestWithFilter1Async() { return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter1Async(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestWithFilter2Async() { return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter2Async(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestWithFilter3Async() { return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter3Async(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestWithFilter4Async() { return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter4Async(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestWithFilter5Async() { return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter5Async(); } [Fact] public Task NodeBrowseDiagnosticsNoneTestAsync() { return GetTests().NodeBrowseDiagnosticsNoneTestAsync(); } [Fact] public Task NodeBrowseDiagnosticsStatusTestAsync() { return GetTests().NodeBrowseDiagnosticsStatusTestAsync(); } [Fact] public Task NodeBrowseDiagnosticsOperationsTestAsync() { return GetTests().NodeBrowseDiagnosticsInfoTestAsync(); } [Fact] public Task NodeBrowseDiagnosticsVerboseTestAsync() { return GetTests().NodeBrowseDiagnosticsVerboseTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/Json/BrowseTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class BrowseTests : IClassFixture, IDisposable { public BrowseTests(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private BrowseServicesTests GetTests() { return new BrowseServicesTests( _client.Resolve>, _server.GetConnection()); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task NodeBrowseInRootTest1Async() { return GetTests().NodeBrowseInRootTest1Async(); } [Fact] public Task NodeBrowseInRootTest2Async() { return GetTests().NodeBrowseInRootTest2Async(); } [Fact] public Task NodeBrowseFirstInRootTest1Async() { return GetTests().NodeBrowseFirstInRootTest1Async(); } [Fact] public Task NodeBrowseFirstInRootTest2Async() { return GetTests().NodeBrowseFirstInRootTest2Async(); } [Fact] public Task NodeBrowseBoilersObjectsTest1Async() { return GetTests().NodeBrowseBoilersObjectsTest1Async(); } [Fact] public Task NodeBrowseBoilersObjectsTest2Async() { return GetTests().NodeBrowseBoilersObjectsTest2Async(); } [Fact] public Task NodeBrowseDataAccessObjectsTest1Async() { return GetTests().NodeBrowseDataAccessObjectsTest1Async(); } [Fact] public Task NodeBrowseDataAccessObjectsTest2Async() { return GetTests().NodeBrowseDataAccessObjectsTest2Async(); } [Fact] public Task NodeBrowseDataAccessObjectsTest3Async() { return GetTests().NodeBrowseDataAccessObjectsTest3Async(); } [Fact] public Task NodeBrowseDataAccessObjectsTest4Async() { return GetTests().NodeBrowseDataAccessObjectsTest4Async(); } [Fact] public Task NodeBrowseDataAccessFC1001Test1Async() { return GetTests().NodeBrowseDataAccessFC1001Test1Async(); } [Fact] public Task NodeBrowseDataAccessFC1001Test2Async() { return GetTests().NodeBrowseDataAccessFC1001Test2Async(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestAsync() { return GetTests().NodeBrowseStaticScalarVariablesTestAsync(); } [Fact] public Task NodeBrowseStaticArrayVariablesTestAsync() { return GetTests().NodeBrowseStaticArrayVariablesTestAsync(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestWithFilter1Async() { return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter1Async(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestWithFilter2Async() { return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter2Async(); } [Fact] public Task NodeBrowseStaticArrayVariablesWithValuesTestAsync() { return GetTests().NodeBrowseStaticArrayVariablesWithValuesTestAsync(); } [Fact] public Task NodeBrowseStaticArrayVariablesRawModeTestAsync() { return GetTests().NodeBrowseStaticArrayVariablesRawModeTestAsync(); } [Fact] public Task NodeBrowseContinuationTest1Async() { return GetTests().NodeBrowseContinuationTest1Async(); } [Fact] public Task NodeBrowseContinuationTest2Async() { return GetTests().NodeBrowseContinuationTest2Async(); } [Fact] public Task NodeBrowseContinuationTest3Async() { return GetTests().NodeBrowseContinuationTest3Async(); } [Fact] public Task NodeBrowseContinuationTest4Async() { return GetTests().NodeBrowseContinuationTest4Async(); } [Fact] public Task NodeBrowseDiagnosticsNoneTestAsync() { return GetTests().NodeBrowseDiagnosticsNoneTestAsync(); } [Fact] public Task NodeBrowseDiagnosticsStatusTestAsync() { return GetTests().NodeBrowseDiagnosticsStatusTestAsync(); } [Fact] public Task NodeBrowseDiagnosticsInfoTestAsync() { return GetTests().NodeBrowseDiagnosticsInfoTestAsync(); } [Fact] public Task NodeBrowseDiagnosticsVerboseTestAsync() { return GetTests().NodeBrowseDiagnosticsVerboseTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/Json/CallArrayTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection.Name)] public sealed class CallArrayTests : IClassFixture, IDisposable { public CallArrayTests(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private CallArrayMethodTests GetTests() { return new CallArrayMethodTests( _client.Resolve>, _server.GetConnection()); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task NodeMethodMetadataStaticArrayMethod1TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod1TestAsync(); } [Fact] public Task NodeMethodMetadataStaticArrayMethod2TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod2TestAsync(); } [Fact] public Task NodeMethodMetadataStaticArrayMethod3TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod3TestAsync(); } [Fact] public Task NodeMethodCallStaticArrayMethod1Test1Async() { return GetTests().NodeMethodCallStaticArrayMethod1Test1Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod1Test2Async() { return GetTests().NodeMethodCallStaticArrayMethod1Test2Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod1Test3Async() { return GetTests().NodeMethodCallStaticArrayMethod1Test3Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod1Test4Async() { return GetTests().NodeMethodCallStaticArrayMethod1Test4Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod1Test5Async() { return GetTests().NodeMethodCallStaticArrayMethod1Test5Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod2Test1Async() { return GetTests().NodeMethodCallStaticArrayMethod2Test1Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod2Test2Async() { return GetTests().NodeMethodCallStaticArrayMethod2Test2Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod2Test3Async() { return GetTests().NodeMethodCallStaticArrayMethod2Test3Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod2Test4Async() { return GetTests().NodeMethodCallStaticArrayMethod2Test4Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod3Test1Async() { return GetTests().NodeMethodCallStaticArrayMethod3Test1Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod3Test2Async() { return GetTests().NodeMethodCallStaticArrayMethod3Test2Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod3Test3Async() { return GetTests().NodeMethodCallStaticArrayMethod3Test3Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/Json/CallScalarTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection.Name)] public sealed class CallScalarTests : IClassFixture, IDisposable { public CallScalarTests(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private CallScalarMethodTests GetTests() { return new CallScalarMethodTests( _client.Resolve>, _server.GetConnection()); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task NodeMethodMetadataStaticScalarMethod1TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod1TestAsync(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod2TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod2TestAsync(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod3TestAsync(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest1Async() { return GetTests().NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest1Async(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest2Async() { return GetTests().NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest2Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod1Test1Async() { return GetTests().NodeMethodCallStaticScalarMethod1Test1Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod1Test2Async() { return GetTests().NodeMethodCallStaticScalarMethod1Test2Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod1Test3Async() { return GetTests().NodeMethodCallStaticScalarMethod1Test3Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod1Test4Async() { return GetTests().NodeMethodCallStaticScalarMethod1Test4Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod1Test5Async() { return GetTests().NodeMethodCallStaticScalarMethod1Test5Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod2Test1Async() { return GetTests().NodeMethodCallStaticScalarMethod2Test1Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod2Test2Async() { return GetTests().NodeMethodCallStaticScalarMethod2Test2Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod3Test1Async() { return GetTests().NodeMethodCallStaticScalarMethod3Test1Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod3Test2Async() { return GetTests().NodeMethodCallStaticScalarMethod3Test2Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod3WithBrowsePathNoIdsTestAsync() { return GetTests().NodeMethodCallStaticScalarMethod3WithBrowsePathNoIdsTestAsync(); } [Fact] public Task NodeMethodCallStaticScalarMethod3WithObjectIdAndBrowsePathTestAsync() { return GetTests().NodeMethodCallStaticScalarMethod3WithObjectIdAndBrowsePathTestAsync(); } [Fact] public Task NodeMethodCallStaticScalarMethod3WithObjectIdAndMethodIdAndBrowsePathTestAsync() { return GetTests().NodeMethodCallStaticScalarMethod3WithObjectIdAndMethodIdAndBrowsePathTestAsync(); } [Fact] public Task NodeMethodCallStaticScalarMethod3WithObjectPathAndMethodIdAndBrowsePathTestAsync() { return GetTests().NodeMethodCallStaticScalarMethod3WithObjectPathAndMethodIdAndBrowsePathTestAsync(); } [Fact] public Task NodeMethodCallStaticScalarMethod3WithObjectIdAndPathAndMethodIdAndPathTestAsync() { return GetTests().NodeMethodCallStaticScalarMethod3WithObjectIdAndPathAndMethodIdAndPathTestAsync(); } [Fact] public Task NodeMethodCallBoiler2ResetTestAsync() { return GetTests().NodeMethodCallBoiler2ResetTestAsync(); } [Fact] public Task NodeMethodCallBoiler1ResetTestAsync() { return GetTests().NodeMethodCallBoiler1ResetTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/Json/ExpandTests1.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class ExpandTests1 : IClassFixture, IDisposable { public ExpandTests1(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private ConfigurationTests1 GetTests() { return new ConfigurationTests1(_client.Resolve(), _server.GetConnection()); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task ExpandObjectWithBrowsePathTest1Async() { return GetTests().ExpandObjectWithBrowsePathTest1Async(); } [Fact] public Task ExpandObjectWithBrowsePathTest2Async() { return GetTests().ExpandObjectWithBrowsePathTest2Async(); } [Fact] public Task ExpandObjectTest1Async() { return GetTests().ExpandObjectTest1Async(); } [Fact] public Task ExpandObjectTest2Async() { return GetTests().ExpandObjectTest2Async(); } [Fact] public Task ExpandServerObjectTest1Async() { return GetTests().ExpandServerObjectTest1Async(); } [Fact] public Task ExpandServerObjectTest2Async() { return GetTests().ExpandServerObjectTest2Async(); } [Fact] public Task ExpandServerObjectTest3Async() { return GetTests().ExpandServerObjectTest3Async(); } [Fact] public Task ExpandServerObjectTest4Async() { return GetTests().ExpandServerObjectTest4Async(); } [Fact] public Task ExpandServerObjectTest5Async() { return GetTests().ExpandServerObjectTest5Async(); } [Fact] public Task ExpandBaseObjectTypeTest1Async() { return GetTests().ExpandBaseObjectTypeTest1Async(); } [Fact] public Task ExpandBaseObjectTypeTest2Async() { return GetTests().ExpandBaseObjectTypeTest2Async(); } [Fact] public Task ExpandBaseObjectsAndObjectTypesTestAsync() { return GetTests().ExpandBaseObjectsAndObjectTypesTestAsync(); } [Fact] public Task ExpandBoilerTypeTestAsync() { return GetTests().ExpandBoilerTypeTestAsync(); } [Fact] public Task ExpandBoilerDrumTypeTestAsync() { return GetTests().ExpandBoilerDrumTypeTestAsync(); } [Fact] public Task ExpandBoilerDrumAndValveTypeTestAsync() { return GetTests().ExpandBoilerDrumAndValveTypeTestAsync(); } [Fact] public Task ExpandValveTypeTestAsync() { return GetTests().ExpandValveTypeTestAsync(); } [Fact] public Task ExpandTestDataObjectTypeTestAsync() { return GetTests().ExpandTestDataObjectTypeTestAsync(); } [Fact] public Task ExpandServerTypeTestAsync() { return GetTests().ExpandServerTypeTestAsync(); } [Fact] public Task ExpandServerTypeWithMethodsTestAsync() { return GetTests().ExpandServerTypeWithMethodsTestAsync(); } [Fact] public Task ExpandPublishSubscribeTestAsync() { return GetTests().ExpandPublishSubscribeTestAsync(); } [Fact] public Task ExpandVariablesTest1Async() { return GetTests().ExpandVariablesTest1Async(); } [Fact] public Task ExpandVariablesAndObjectsTest1Async() { return GetTests().ExpandVariablesAndObjectsTest1Async(); } [Fact] public Task ExpandVariableTypesTest1Async() { return GetTests().ExpandVariableTypesTest1Async(); } [Fact] public Task ExpandVariableTypesTest2Async() { return GetTests().ExpandVariableTypesTest2Async(); } [Fact] public Task ExpandVariableTypesTest3Async() { return GetTests().ExpandVariableTypesTest3Async(); } [Fact] public Task ExpandObjectWithNoObjectsTest1Async() { return GetTests().ExpandObjectWithNoObjectsTest1Async(); } [Fact] public Task ExpandObjectWithNoObjectsTest2Async() { return GetTests().ExpandObjectWithNoObjectsTest2Async(); } [Fact] public Task ExpandEmptyEntryTest1Async() { return GetTests().ExpandEmptyEntryTest1Async(); } [Fact] public Task ExpandEmptyEntryTest2Async() { return GetTests().ExpandEmptyEntryTest2Async(); } [Fact] public Task ExpandBadNodeIdTest1Async() { return GetTests().ExpandBadNodeIdTest1Async(); } [Fact] public Task ExpandBadNodeIdTest2Async() { return GetTests().ExpandBadNodeIdTest2Async(); } [Fact] public Task ExpandBadNodeIdTest3Async() { return GetTests().ExpandBadNodeIdTest3Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/Json/MetadataArrayTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class MetadataArrayTests : IClassFixture, IDisposable { public MetadataArrayTests(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private CallArrayMethodTests GetTests() { return new CallArrayMethodTests( _client.Resolve>, _server.GetConnection(), newMetadata: true); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task NodeMethodMetadataStaticArrayMethod1TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod1TestAsync(); } [Fact] public Task NodeMethodMetadataStaticArrayMethod2TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod2TestAsync(); } [Fact] public Task NodeMethodMetadataStaticArrayMethod3TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod3TestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/Json/MetadataScalarTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class MetadataScalarTests : IClassFixture, IDisposable { public MetadataScalarTests(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private CallScalarMethodTests GetTests() { return new CallScalarMethodTests( _client.Resolve>, _server.GetConnection(), newMetadata: true); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task NodeMethodMetadataStaticScalarMethod1TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod1TestAsync(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod2TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod2TestAsync(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod3TestAsync(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest1Async() { return GetTests().NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest1Async(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest2Async() { return GetTests().NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest2Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/Json/MetadataTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class MetadataTests : IClassFixture, IDisposable { public MetadataTests(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private NodeMetadataTests GetTests() { return new NodeMetadataTests( _client.Resolve>, _server.GetConnection()); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task GetServerCapabilitiesTestAsync() { return GetTests().GetServerCapabilitiesTestAsync(); } [Fact] public Task HistoryGetServerCapabilitiesTestAsync() { return GetTests().HistoryGetServerCapabilitiesTestAsync(); } [Fact] public Task NodeGetMetadataForFolderTypeTestAsync() { return GetTests().NodeGetMetadataForFolderTypeTestAsync(); } [Fact] public Task NodeGetMetadataForServerObjectTestAsync() { return GetTests().NodeGetMetadataForServerObjectTestAsync(); } [Fact] public Task NodeGetMetadataForConditionTypeTestAsync() { return GetTests().NodeGetMetadataForConditionTypeTestAsync(); } [Fact] public Task NodeGetMetadataTestForBaseEventTypeTestAsync() { return GetTests().NodeGetMetadataTestForBaseEventTypeTestAsync(); } [Fact] public Task NodeGetMetadataForBaseInterfaceTypeTestAsync() { return GetTests().NodeGetMetadataForBaseInterfaceTypeTestAsync(); } [Fact] public Task NodeGetMetadataForBaseDataVariableTypeTestAsync() { return GetTests().NodeGetMetadataForBaseDataVariableTypeTestAsync(); } [Fact] public Task NodeGetMetadataForPropertyTypeTestAsync() { return GetTests().NodeGetMetadataForPropertyTypeTestAsync(); } [Fact] public Task NodeGetMetadataForAudioVariableTypeTestAsync() { return GetTests().NodeGetMetadataForAudioVariableTypeTestAsync(); } [Fact] public Task NodeGetMetadataForServerStatusVariableTestAsync() { return GetTests().NodeGetMetadataForServerStatusVariableTestAsync(); } [Fact] public Task NodeGetMetadataForRedundancySupportPropertyTestAsync() { return GetTests().NodeGetMetadataForRedundancySupportPropertyTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/Json/ReadCollection.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.Json { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public sealed class ReadCollection : ICollectionFixture { public const string Name = "TestDataServerReadRestJson"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/Json/ValueReadArrayTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class ValueReadArrayTests : IClassFixture, IDisposable { public ValueReadArrayTests(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private ReadArrayValueTests GetTests() { return new ReadArrayValueTests( _client.Resolve>, _server.GetConnection(), (ep, n, s) => _server.Client.ReadValueAsync(new ConnectionModel { Endpoint = new EndpointModel { Url = ep.Endpoint.Url, Certificate = _server.Certificate?.RawData?.ToThumbprint() } }, n, s)); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task NodeReadAllStaticArrayVariableNodeClassTest1Async() { return GetTests().NodeReadAllStaticArrayVariableNodeClassTest1Async(); } [Fact] public Task NodeReadAllStaticArrayVariableAccessLevelTest1Async() { return GetTests().NodeReadAllStaticArrayVariableAccessLevelTest1Async(); } [Fact] public Task NodeReadAllStaticArrayVariableWriteMaskTest1Async() { return GetTests().NodeReadAllStaticArrayVariableWriteMaskTest1Async(); } [Fact] public Task NodeReadAllStaticArrayVariableWriteMaskTest2Async() { return GetTests().NodeReadAllStaticArrayVariableWriteMaskTest2Async(); } [Fact] public Task NodeReadStaticArrayBooleanValueVariableTestAsync() { return GetTests().NodeReadStaticArrayBooleanValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArraySByteValueVariableTestAsync() { return GetTests().NodeReadStaticArraySByteValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayByteValueVariableTestAsync() { return GetTests().NodeReadStaticArrayByteValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayInt16ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayInt16ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayUInt16ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayUInt16ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayInt32ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayInt32ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayUInt32ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayUInt32ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayInt64ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayInt64ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayUInt64ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayUInt64ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayFloatValueVariableTestAsync() { return GetTests().NodeReadStaticArrayFloatValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayDoubleValueVariableTestAsync() { return GetTests().NodeReadStaticArrayDoubleValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayStringValueVariableTestAsync() { return GetTests().NodeReadStaticArrayStringValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayDateTimeValueVariableTestAsync() { return GetTests().NodeReadStaticArrayDateTimeValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayGuidValueVariableTestAsync() { return GetTests().NodeReadStaticArrayGuidValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayByteStringValueVariableTestAsync() { return GetTests().NodeReadStaticArrayByteStringValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayXmlElementValueVariableTestAsync() { return GetTests().NodeReadStaticArrayXmlElementValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayNodeIdValueVariableTestAsync() { return GetTests().NodeReadStaticArrayNodeIdValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayExpandedNodeIdValueVariableTestAsync() { return GetTests().NodeReadStaticArrayExpandedNodeIdValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayQualifiedNameValueVariableTestAsync() { return GetTests().NodeReadStaticArrayQualifiedNameValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayLocalizedTextValueVariableTestAsync() { return GetTests().NodeReadStaticArrayLocalizedTextValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayStatusCodeValueVariableTestAsync() { return GetTests().NodeReadStaticArrayStatusCodeValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayVariantValueVariableTestAsync() { return GetTests().NodeReadStaticArrayVariantValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayEnumerationValueVariableTestAsync() { return GetTests().NodeReadStaticArrayEnumerationValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayStructureValueVariableTestAsync() { return GetTests().NodeReadStaticArrayStructureValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayNumberValueVariableTestAsync() { return GetTests().NodeReadStaticArrayNumberValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayIntegerValueVariableTestAsync() { return GetTests().NodeReadStaticArrayIntegerValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayUIntegerValueVariableTestAsync() { return GetTests().NodeReadStaticArrayUIntegerValueVariableTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/Json/ValueReadScalarTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class ValueReadScalarTests : IClassFixture, IDisposable { public ValueReadScalarTests(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private ReadScalarValueTests GetTests() { return new ReadScalarValueTests( _client.Resolve>, _server.GetConnection(), (ep, n, s) => _server.Client.ReadValueAsync(new ConnectionModel { Endpoint = new EndpointModel { Url = ep.Endpoint.Url, Certificate = _server.Certificate?.RawData?.ToThumbprint() } }, n, s)); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task NodeReadAllStaticScalarVariableNodeClassTest1Async() { return GetTests().NodeReadAllStaticScalarVariableNodeClassTest1Async(); } [Fact] public Task NodeReadAllStaticScalarVariableAccessLevelTest1Async() { return GetTests().NodeReadAllStaticScalarVariableAccessLevelTest1Async(); } [Fact] public Task NodeReadAllStaticScalarVariableWriteMaskTest1Async() { return GetTests().NodeReadAllStaticScalarVariableWriteMaskTest1Async(); } [Fact] public Task NodeReadAllStaticScalarVariableWriteMaskTest2Async() { return GetTests().NodeReadAllStaticScalarVariableWriteMaskTest2Async(); } [Fact] public Task NodeReadStaticScalarBooleanValueVariableTestAsync() { return GetTests().NodeReadStaticScalarBooleanValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest1Async() { return GetTests().NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest1Async(); } [Fact] public Task NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest2Async() { return GetTests().NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest2Async(); } [Fact] public Task NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest3Async() { return GetTests().NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest3Async(); } [Fact] public Task NodeReadStaticScalarSByteValueVariableTestAsync() { return GetTests().NodeReadStaticScalarSByteValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarByteValueVariableTestAsync() { return GetTests().NodeReadStaticScalarByteValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarInt16ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarInt16ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarUInt16ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarUInt16ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarInt32ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarInt32ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarUInt32ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarUInt32ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarInt64ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarInt64ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarUInt64ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarUInt64ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarFloatValueVariableTestAsync() { return GetTests().NodeReadStaticScalarFloatValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarDoubleValueVariableTestAsync() { return GetTests().NodeReadStaticScalarDoubleValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarStringValueVariableTestAsync() { return GetTests().NodeReadStaticScalarStringValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarDateTimeValueVariableTestAsync() { return GetTests().NodeReadStaticScalarDateTimeValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarGuidValueVariableTestAsync() { return GetTests().NodeReadStaticScalarGuidValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarByteStringValueVariableTestAsync() { return GetTests().NodeReadStaticScalarByteStringValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarXmlElementValueVariableTestAsync() { return GetTests().NodeReadStaticScalarXmlElementValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarNodeIdValueVariableTestAsync() { return GetTests().NodeReadStaticScalarNodeIdValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarExpandedNodeIdValueVariableTestAsync() { return GetTests().NodeReadStaticScalarExpandedNodeIdValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarQualifiedNameValueVariableTestAsync() { return GetTests().NodeReadStaticScalarQualifiedNameValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarLocalizedTextValueVariableTestAsync() { return GetTests().NodeReadStaticScalarLocalizedTextValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarStatusCodeValueVariableTestAsync() { return GetTests().NodeReadStaticScalarStatusCodeValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarVariantValueVariableTestAsync() { return GetTests().NodeReadStaticScalarVariantValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarEnumerationValueVariableTestAsync() { return GetTests().NodeReadStaticScalarEnumerationValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarStructuredValueVariableTestAsync() { return GetTests().NodeReadStaticScalarStructuredValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarNumberValueVariableTestAsync() { return GetTests().NodeReadStaticScalarNumberValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarIntegerValueVariableTestAsync() { return GetTests().NodeReadStaticScalarIntegerValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarUIntegerValueVariableTestAsync() { return GetTests().NodeReadStaticScalarUIntegerValueVariableTestAsync(); } [Fact] public Task NodeReadDataAccessMeasurementFloatValueTestAsync() { return GetTests().NodeReadDataAccessMeasurementFloatValueTestAsync(); } [Fact] public Task NodeReadDiagnosticsNoneTestAsync() { return GetTests().NodeReadDiagnosticsNoneTestAsync(); } [Fact] public Task NodeReadDiagnosticsStatusTestAsync() { return GetTests().NodeReadDiagnosticsStatusTestAsync(); } [Fact] public Task NodeReadDiagnosticsDebugTestAsync() { return GetTests().NodeReadDiagnosticsDebugTestAsync(); } [Fact] public Task NodeReadDiagnosticsVerboseTestAsync() { return GetTests().NodeReadDiagnosticsVerboseTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/Json/ValueWriteArrayTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection.Name)] public sealed class ValueWriteArrayTests : IClassFixture, IDisposable { public ValueWriteArrayTests(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private WriteArrayValueTests GetTests() { return new WriteArrayValueTests( _client.Resolve>, _server.GetConnection(), (ep, n, s) => _server.Client.ReadValueAsync(new ConnectionModel { Endpoint = new EndpointModel { Url = ep.Endpoint.Url, Certificate = _server.Certificate?.RawData?.ToThumbprint() } }, n, s)); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task NodeWriteStaticArrayBooleanValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayBooleanValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArraySByteValueVariableTestAsync() { return GetTests().NodeWriteStaticArraySByteValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayByteValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayByteValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayInt16ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayInt16ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayUInt16ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayUInt16ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayInt32ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayInt32ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayUInt32ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayUInt32ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayInt64ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayInt64ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayUInt64ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayUInt64ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayFloatValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayFloatValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayDoubleValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayDoubleValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayStringValueVariableTest1Async() { return GetTests().NodeWriteStaticArrayStringValueVariableTest1Async(); } [Fact] public Task NodeWriteStaticArrayStringValueVariableTest2Async() { return GetTests().NodeWriteStaticArrayStringValueVariableTest2Async(); } [Fact] public Task NodeWriteStaticArrayDateTimeValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayDateTimeValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayGuidValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayGuidValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayByteStringValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayByteStringValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayXmlElementValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayXmlElementValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayNodeIdValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayNodeIdValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayExpandedNodeIdValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayExpandedNodeIdValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayQualifiedNameValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayQualifiedNameValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayLocalizedTextValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayLocalizedTextValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayStatusCodeValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayStatusCodeValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayVariantValueVariableTest1Async() { return GetTests().NodeWriteStaticArrayVariantValueVariableTest1Async(); } [Fact] public Task NodeWriteStaticArrayEnumerationValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayEnumerationValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayStructureValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayStructureValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayNumberValueVariableTest1Async() { return GetTests().NodeWriteStaticArrayNumberValueVariableTest1Async(); } [Fact] public Task NodeWriteStaticArrayNumberValueVariableTest2Async() { return GetTests().NodeWriteStaticArrayNumberValueVariableTest2Async(); } [Fact] public Task NodeWriteStaticArrayIntegerValueVariableTest1Async() { return GetTests().NodeWriteStaticArrayIntegerValueVariableTest1Async(); } [Fact] public Task NodeWriteStaticArrayIntegerValueVariableTest2Async() { return GetTests().NodeWriteStaticArrayIntegerValueVariableTest2Async(); } [Fact] public Task NodeWriteStaticArrayUIntegerValueVariableTest1Async() { return GetTests().NodeWriteStaticArrayUIntegerValueVariableTest1Async(); } [Fact] public Task NodeWriteStaticArrayUIntegerValueVariableTest2Async() { return GetTests().NodeWriteStaticArrayUIntegerValueVariableTest2Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/Json/ValueWriteScalarTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.Json { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection.Name)] public sealed class ValueWriteScalarTests : IClassFixture, IDisposable { public ValueWriteScalarTests(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.Json); } public void Dispose() { _client.Dispose(); } private WriteScalarValueTests GetTests() { return new WriteScalarValueTests( _client.Resolve>, _server.GetConnection(), (ep, n, s) => _server.Client.ReadValueAsync(new ConnectionModel { Endpoint = new EndpointModel { Url = ep.Endpoint.Url, Certificate = _server.Certificate?.RawData?.ToThumbprint() } }, n, s)); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task NodeWriteStaticScalarBooleanValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarBooleanValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest1Async() { return GetTests().NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest1Async(); } [Fact] public Task NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest2Async() { return GetTests().NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest2Async(); } [Fact] public Task NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest3Async() { return GetTests().NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest3Async(); } [Fact] public Task NodeWriteStaticScalarSByteValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarSByteValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarByteValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarByteValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarInt16ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarInt16ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarUInt16ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarUInt16ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarInt32ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarInt32ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarUInt32ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarUInt32ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarInt64ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarInt64ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarUInt64ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarUInt64ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarFloatValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarFloatValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarDoubleValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarDoubleValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarStringValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarStringValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarDateTimeValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarDateTimeValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarGuidValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarGuidValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarByteStringValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarByteStringValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarXmlElementValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarXmlElementValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarNodeIdValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarNodeIdValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarExpandedNodeIdValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarExpandedNodeIdValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarQualifiedNameValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarQualifiedNameValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarLocalizedTextValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarLocalizedTextValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarStatusCodeValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarStatusCodeValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarVariantValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarVariantValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarEnumerationValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarEnumerationValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarStructuredValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarStructuredValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarNumberValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarNumberValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarIntegerValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarIntegerValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarUIntegerValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarUIntegerValueVariableTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/Json/WriteCollection.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.Json { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public sealed class WriteCollection : ICollectionFixture { public const string Name = "TestDataServerWriteRestJson"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/MsgPack/BrowsePathTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class BrowsePathTests : IClassFixture, IDisposable { public BrowsePathTests(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private BrowsePathTests GetTests() { return new BrowsePathTests( _client.Resolve>, _server.GetConnection()); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task NodeBrowsePathStaticScalarMethod3Test1Async() { return GetTests().NodeBrowsePathStaticScalarMethod3Test1Async(); } [Fact] public Task NodeBrowsePathStaticScalarMethod3Test2Async() { return GetTests().NodeBrowsePathStaticScalarMethod3Test2Async(); } [Fact] public Task NodeBrowsePathStaticScalarMethod3Test3Async() { return GetTests().NodeBrowsePathStaticScalarMethod3Test3Async(); } [Fact] public Task NodeBrowsePathStaticScalarMethodsTestAsync() { return GetTests().NodeBrowsePathStaticScalarMethodsTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/MsgPack/BrowseStreamTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class BrowseStreamTests : IClassFixture, IDisposable { public BrowseStreamTests(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private BrowseStreamTests GetTests() { return new BrowseStreamTests( _client.Resolve>, _server.GetConnection()); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task NodeBrowseInRootTest1Async() { return GetTests().NodeBrowseInRootTest1Async(); } [Fact] public Task NodeBrowseInRootTest2Async() { return GetTests().NodeBrowseInRootTest2Async(); } [Fact] public Task NodeBrowseBoilersObjectsTest1Async() { return GetTests().NodeBrowseBoilersObjectsTest1Async(); } [Fact] public Task NodeBrowseDataAccessObjectsTest1Async() { return GetTests().NodeBrowseDataAccessObjectsTest1Async(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestAsync() { return GetTests().NodeBrowseStaticScalarVariablesTestAsync(); } [Fact] public Task NodeBrowseStaticArrayVariablesTestAsync() { return GetTests().NodeBrowseStaticArrayVariablesTestAsync(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestWithFilter1Async() { return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter1Async(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestWithFilter2Async() { return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter2Async(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestWithFilter3Async() { return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter3Async(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestWithFilter4Async() { return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter4Async(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestWithFilter5Async() { return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter5Async(); } [Fact] public Task NodeBrowseDiagnosticsNoneTestAsync() { return GetTests().NodeBrowseDiagnosticsNoneTestAsync(); } [Fact] public Task NodeBrowseDiagnosticsStatusTestAsync() { return GetTests().NodeBrowseDiagnosticsStatusTestAsync(); } [Fact] public Task NodeBrowseDiagnosticsOperationsTestAsync() { return GetTests().NodeBrowseDiagnosticsInfoTestAsync(); } [Fact] public Task NodeBrowseDiagnosticsVerboseTestAsync() { return GetTests().NodeBrowseDiagnosticsVerboseTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/MsgPack/BrowseTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class BrowseTests : IClassFixture, IDisposable { public BrowseTests(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private BrowseServicesTests GetTests() { return new BrowseServicesTests( _client.Resolve>, _server.GetConnection()); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task NodeBrowseInRootTest1Async() { return GetTests().NodeBrowseInRootTest1Async(); } [Fact] public Task NodeBrowseInRootTest2Async() { return GetTests().NodeBrowseInRootTest2Async(); } [Fact] public Task NodeBrowseFirstInRootTest1Async() { return GetTests().NodeBrowseFirstInRootTest1Async(); } [Fact] public Task NodeBrowseFirstInRootTest2Async() { return GetTests().NodeBrowseFirstInRootTest2Async(); } [Fact] public Task NodeBrowseBoilersObjectsTest1Async() { return GetTests().NodeBrowseBoilersObjectsTest1Async(); } [Fact] public Task NodeBrowseBoilersObjectsTest2Async() { return GetTests().NodeBrowseBoilersObjectsTest2Async(); } [Fact] public Task NodeBrowseDataAccessObjectsTest1Async() { return GetTests().NodeBrowseDataAccessObjectsTest1Async(); } [Fact] public Task NodeBrowseDataAccessObjectsTest2Async() { return GetTests().NodeBrowseDataAccessObjectsTest2Async(); } [Fact] public Task NodeBrowseDataAccessObjectsTest3Async() { return GetTests().NodeBrowseDataAccessObjectsTest3Async(); } [Fact] public Task NodeBrowseDataAccessObjectsTest4Async() { return GetTests().NodeBrowseDataAccessObjectsTest4Async(); } [Fact] public Task NodeBrowseDataAccessFC1001Test1Async() { return GetTests().NodeBrowseDataAccessFC1001Test1Async(); } [Fact] public Task NodeBrowseDataAccessFC1001Test2Async() { return GetTests().NodeBrowseDataAccessFC1001Test2Async(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestAsync() { return GetTests().NodeBrowseStaticScalarVariablesTestAsync(); } [Fact] public Task NodeBrowseStaticArrayVariablesTestAsync() { return GetTests().NodeBrowseStaticArrayVariablesTestAsync(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestWithFilter1Async() { return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter1Async(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestWithFilter2Async() { return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter2Async(); } [Fact] public Task NodeBrowseStaticArrayVariablesWithValuesTestAsync() { return GetTests().NodeBrowseStaticArrayVariablesWithValuesTestAsync(); } [Fact] public Task NodeBrowseStaticArrayVariablesRawModeTestAsync() { return GetTests().NodeBrowseStaticArrayVariablesRawModeTestAsync(); } [Fact] public Task NodeBrowseContinuationTest1Async() { return GetTests().NodeBrowseContinuationTest1Async(); } [Fact] public Task NodeBrowseContinuationTest2Async() { return GetTests().NodeBrowseContinuationTest2Async(); } [Fact] public Task NodeBrowseContinuationTest3Async() { return GetTests().NodeBrowseContinuationTest3Async(); } [Fact] public Task NodeBrowseContinuationTest4Async() { return GetTests().NodeBrowseContinuationTest4Async(); } [Fact] public Task NodeBrowseDiagnosticsNoneTestAsync() { return GetTests().NodeBrowseDiagnosticsNoneTestAsync(); } [Fact] public Task NodeBrowseDiagnosticsStatusTestAsync() { return GetTests().NodeBrowseDiagnosticsStatusTestAsync(); } [Fact] public Task NodeBrowseDiagnosticsInfoTestAsync() { return GetTests().NodeBrowseDiagnosticsInfoTestAsync(); } [Fact] public Task NodeBrowseDiagnosticsVerboseTestAsync() { return GetTests().NodeBrowseDiagnosticsVerboseTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/MsgPack/CallArrayTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection.Name)] public sealed class CallArrayTests : IClassFixture, IDisposable { public CallArrayTests(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private CallArrayMethodTests GetTests() { return new CallArrayMethodTests( _client.Resolve>, _server.GetConnection()); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task NodeMethodMetadataStaticArrayMethod1TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod1TestAsync(); } [Fact] public Task NodeMethodMetadataStaticArrayMethod2TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod2TestAsync(); } [Fact] public Task NodeMethodMetadataStaticArrayMethod3TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod3TestAsync(); } [Fact] public Task NodeMethodCallStaticArrayMethod1Test1Async() { return GetTests().NodeMethodCallStaticArrayMethod1Test1Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod1Test2Async() { return GetTests().NodeMethodCallStaticArrayMethod1Test2Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod1Test3Async() { return GetTests().NodeMethodCallStaticArrayMethod1Test3Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod1Test4Async() { return GetTests().NodeMethodCallStaticArrayMethod1Test4Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod1Test5Async() { return GetTests().NodeMethodCallStaticArrayMethod1Test5Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod2Test1Async() { return GetTests().NodeMethodCallStaticArrayMethod2Test1Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod2Test2Async() { return GetTests().NodeMethodCallStaticArrayMethod2Test2Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod2Test3Async() { return GetTests().NodeMethodCallStaticArrayMethod2Test3Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod2Test4Async() { return GetTests().NodeMethodCallStaticArrayMethod2Test4Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod3Test1Async() { return GetTests().NodeMethodCallStaticArrayMethod3Test1Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod3Test2Async() { return GetTests().NodeMethodCallStaticArrayMethod3Test2Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod3Test3Async() { return GetTests().NodeMethodCallStaticArrayMethod3Test3Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/MsgPack/CallScalarTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection.Name)] public sealed class CallScalarTests : IClassFixture, IDisposable { public CallScalarTests(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private CallScalarMethodTests GetTests() { return new CallScalarMethodTests( _client.Resolve>, _server.GetConnection()); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task NodeMethodMetadataStaticScalarMethod1TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod1TestAsync(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod2TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod2TestAsync(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod3TestAsync(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest1Async() { return GetTests().NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest1Async(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest2Async() { return GetTests().NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest2Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod1Test1Async() { return GetTests().NodeMethodCallStaticScalarMethod1Test1Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod1Test2Async() { return GetTests().NodeMethodCallStaticScalarMethod1Test2Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod1Test3Async() { return GetTests().NodeMethodCallStaticScalarMethod1Test3Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod1Test4Async() { return GetTests().NodeMethodCallStaticScalarMethod1Test4Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod1Test5Async() { return GetTests().NodeMethodCallStaticScalarMethod1Test5Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod2Test1Async() { return GetTests().NodeMethodCallStaticScalarMethod2Test1Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod2Test2Async() { return GetTests().NodeMethodCallStaticScalarMethod2Test2Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod3Test1Async() { return GetTests().NodeMethodCallStaticScalarMethod3Test1Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod3Test2Async() { return GetTests().NodeMethodCallStaticScalarMethod3Test2Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod3WithBrowsePathNoIdsTestAsync() { return GetTests().NodeMethodCallStaticScalarMethod3WithBrowsePathNoIdsTestAsync(); } [Fact] public Task NodeMethodCallStaticScalarMethod3WithObjectIdAndBrowsePathTestAsync() { return GetTests().NodeMethodCallStaticScalarMethod3WithObjectIdAndBrowsePathTestAsync(); } [Fact] public Task NodeMethodCallStaticScalarMethod3WithObjectIdAndMethodIdAndBrowsePathTestAsync() { return GetTests().NodeMethodCallStaticScalarMethod3WithObjectIdAndMethodIdAndBrowsePathTestAsync(); } [Fact] public Task NodeMethodCallStaticScalarMethod3WithObjectPathAndMethodIdAndBrowsePathTestAsync() { return GetTests().NodeMethodCallStaticScalarMethod3WithObjectPathAndMethodIdAndBrowsePathTestAsync(); } [Fact] public Task NodeMethodCallStaticScalarMethod3WithObjectIdAndPathAndMethodIdAndPathTestAsync() { return GetTests().NodeMethodCallStaticScalarMethod3WithObjectIdAndPathAndMethodIdAndPathTestAsync(); } [Fact] public Task NodeMethodCallBoiler2ResetTestAsync() { return GetTests().NodeMethodCallBoiler2ResetTestAsync(); } [Fact] public Task NodeMethodCallBoiler1ResetTestAsync() { return GetTests().NodeMethodCallBoiler1ResetTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/MsgPack/ExpandTests1.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class ExpandTests1 : IClassFixture, IDisposable { public ExpandTests1(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private ConfigurationTests1 GetTests() { return new ConfigurationTests1(_client.Resolve(), _server.GetConnection()); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task ExpandObjectWithBrowsePathTest1Async() { return GetTests().ExpandObjectWithBrowsePathTest1Async(); } [Fact] public Task ExpandObjectWithBrowsePathTest2Async() { return GetTests().ExpandObjectWithBrowsePathTest2Async(); } [Fact] public Task ExpandObjectTest1Async() { return GetTests().ExpandObjectTest1Async(); } [Fact] public Task ExpandObjectTest2Async() { return GetTests().ExpandObjectTest2Async(); } [Fact] public Task ExpandServerObjectTest1Async() { return GetTests().ExpandServerObjectTest1Async(); } [Fact] public Task ExpandServerObjectTest2Async() { return GetTests().ExpandServerObjectTest2Async(); } [Fact] public Task ExpandServerObjectTest3Async() { return GetTests().ExpandServerObjectTest3Async(); } [Fact] public Task ExpandServerObjectTest4Async() { return GetTests().ExpandServerObjectTest4Async(); } [Fact] public Task ExpandServerObjectTest5Async() { return GetTests().ExpandServerObjectTest5Async(); } [Fact] public Task ExpandBaseObjectTypeTest1Async() { return GetTests().ExpandBaseObjectTypeTest1Async(); } [Fact] public Task ExpandBaseObjectTypeTest2Async() { return GetTests().ExpandBaseObjectTypeTest2Async(); } [Fact] public Task ExpandBaseObjectsAndObjectTypesTestAsync() { return GetTests().ExpandBaseObjectsAndObjectTypesTestAsync(); } [Fact] public Task ExpandBoilerTypeTestAsync() { return GetTests().ExpandBoilerTypeTestAsync(); } [Fact] public Task ExpandBoilerDrumTypeTestAsync() { return GetTests().ExpandBoilerDrumTypeTestAsync(); } [Fact] public Task ExpandBoilerDrumAndValveTypeTestAsync() { return GetTests().ExpandBoilerDrumAndValveTypeTestAsync(); } [Fact] public Task ExpandValveTypeTestAsync() { return GetTests().ExpandValveTypeTestAsync(); } [Fact] public Task ExpandTestDataObjectTypeTestAsync() { return GetTests().ExpandTestDataObjectTypeTestAsync(); } [Fact] public Task ExpandServerTypeTestAsync() { return GetTests().ExpandServerTypeTestAsync(); } [Fact] public Task ExpandServerTypeWithMethodsTestAsync() { return GetTests().ExpandServerTypeWithMethodsTestAsync(); } [Fact] public Task ExpandPublishSubscribeTestAsync() { return GetTests().ExpandPublishSubscribeTestAsync(); } [Fact] public Task ExpandVariablesTest1Async() { return GetTests().ExpandVariablesTest1Async(); } [Fact] public Task ExpandVariablesAndObjectsTest1Async() { return GetTests().ExpandVariablesAndObjectsTest1Async(); } [Fact] public Task ExpandVariableTypesTest1Async() { return GetTests().ExpandVariableTypesTest1Async(); } [Fact] public Task ExpandVariableTypesTest2Async() { return GetTests().ExpandVariableTypesTest2Async(); } [Fact] public Task ExpandVariableTypesTest3Async() { return GetTests().ExpandVariableTypesTest3Async(); } [Fact] public Task ExpandObjectWithNoObjectsTest1Async() { return GetTests().ExpandObjectWithNoObjectsTest1Async(); } [Fact] public Task ExpandObjectWithNoObjectsTest2Async() { return GetTests().ExpandObjectWithNoObjectsTest2Async(); } [Fact] public Task ExpandEmptyEntryTest1Async() { return GetTests().ExpandEmptyEntryTest1Async(); } [Fact] public Task ExpandEmptyEntryTest2Async() { return GetTests().ExpandEmptyEntryTest2Async(); } [Fact] public Task ExpandBadNodeIdTest1Async() { return GetTests().ExpandBadNodeIdTest1Async(); } [Fact] public Task ExpandBadNodeIdTest2Async() { return GetTests().ExpandBadNodeIdTest2Async(); } [Fact] public Task ExpandBadNodeIdTest3Async() { return GetTests().ExpandBadNodeIdTest3Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/MsgPack/MetadataArrayTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class MetadataArrayTests : IClassFixture, IDisposable { public MetadataArrayTests(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private CallArrayMethodTests GetTests() { return new CallArrayMethodTests( _client.Resolve>, _server.GetConnection(), newMetadata: true); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task NodeMethodMetadataStaticArrayMethod1TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod1TestAsync(); } [Fact] public Task NodeMethodMetadataStaticArrayMethod2TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod2TestAsync(); } [Fact] public Task NodeMethodMetadataStaticArrayMethod3TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod3TestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/MsgPack/MetadataScalarTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class MetadataScalarTests : IClassFixture, IDisposable { public MetadataScalarTests(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private CallScalarMethodTests GetTests() { return new CallScalarMethodTests( _client.Resolve>, _server.GetConnection(), newMetadata: true); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task NodeMethodMetadataStaticScalarMethod1TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod1TestAsync(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod2TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod2TestAsync(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod3TestAsync(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest1Async() { return GetTests().NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest1Async(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest2Async() { return GetTests().NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest2Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/MsgPack/MetadataTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class MetadataTests : IClassFixture, IDisposable { public MetadataTests(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private NodeMetadataTests GetTests() { return new NodeMetadataTests( _client.Resolve>, _server.GetConnection()); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task GetServerCapabilitiesTestAsync() { return GetTests().GetServerCapabilitiesTestAsync(); } [Fact] public Task HistoryGetServerCapabilitiesTestAsync() { return GetTests().HistoryGetServerCapabilitiesTestAsync(); } [Fact] public Task NodeGetMetadataForFolderTypeTestAsync() { return GetTests().NodeGetMetadataForFolderTypeTestAsync(); } [Fact] public Task NodeGetMetadataForServerObjectTestAsync() { return GetTests().NodeGetMetadataForServerObjectTestAsync(); } [Fact] public Task NodeGetMetadataForConditionTypeTestAsync() { return GetTests().NodeGetMetadataForConditionTypeTestAsync(); } [Fact] public Task NodeGetMetadataTestForBaseEventTypeTestAsync() { return GetTests().NodeGetMetadataTestForBaseEventTypeTestAsync(); } [Fact] public Task NodeGetMetadataForBaseInterfaceTypeTestAsync() { return GetTests().NodeGetMetadataForBaseInterfaceTypeTestAsync(); } [Fact] public Task NodeGetMetadataForBaseDataVariableTypeTestAsync() { return GetTests().NodeGetMetadataForBaseDataVariableTypeTestAsync(); } [Fact] public Task NodeGetMetadataForPropertyTypeTestAsync() { return GetTests().NodeGetMetadataForPropertyTypeTestAsync(); } [Fact] public Task NodeGetMetadataForAudioVariableTypeTestAsync() { return GetTests().NodeGetMetadataForAudioVariableTypeTestAsync(); } [Fact] public Task NodeGetMetadataForServerStatusVariableTestAsync() { return GetTests().NodeGetMetadataForServerStatusVariableTestAsync(); } [Fact] public Task NodeGetMetadataForRedundancySupportPropertyTestAsync() { return GetTests().NodeGetMetadataForRedundancySupportPropertyTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/MsgPack/ReadCollection.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.MsgPack { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public sealed class ReadCollection : ICollectionFixture { public const string Name = "TestDataServerReadRestMsgPack"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/MsgPack/ValueReadArrayTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class ValueReadArrayTests : IClassFixture, IDisposable { public ValueReadArrayTests(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private ReadArrayValueTests GetTests() { return new ReadArrayValueTests( _client.Resolve>, _server.GetConnection(), (ep, n, s) => _server.Client.ReadValueAsync(new ConnectionModel { Endpoint = new EndpointModel { Url = ep.Endpoint.Url, Certificate = _server.Certificate?.RawData?.ToThumbprint() } }, n, s)); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task NodeReadAllStaticArrayVariableNodeClassTest1Async() { return GetTests().NodeReadAllStaticArrayVariableNodeClassTest1Async(); } [Fact] public Task NodeReadAllStaticArrayVariableAccessLevelTest1Async() { return GetTests().NodeReadAllStaticArrayVariableAccessLevelTest1Async(); } [Fact] public Task NodeReadAllStaticArrayVariableWriteMaskTest1Async() { return GetTests().NodeReadAllStaticArrayVariableWriteMaskTest1Async(); } [Fact] public Task NodeReadAllStaticArrayVariableWriteMaskTest2Async() { return GetTests().NodeReadAllStaticArrayVariableWriteMaskTest2Async(); } [Fact] public Task NodeReadStaticArrayBooleanValueVariableTestAsync() { return GetTests().NodeReadStaticArrayBooleanValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArraySByteValueVariableTestAsync() { return GetTests().NodeReadStaticArraySByteValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayByteValueVariableTestAsync() { return GetTests().NodeReadStaticArrayByteValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayInt16ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayInt16ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayUInt16ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayUInt16ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayInt32ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayInt32ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayUInt32ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayUInt32ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayInt64ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayInt64ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayUInt64ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayUInt64ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayFloatValueVariableTestAsync() { return GetTests().NodeReadStaticArrayFloatValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayDoubleValueVariableTestAsync() { return GetTests().NodeReadStaticArrayDoubleValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayStringValueVariableTestAsync() { return GetTests().NodeReadStaticArrayStringValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayDateTimeValueVariableTestAsync() { return GetTests().NodeReadStaticArrayDateTimeValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayGuidValueVariableTestAsync() { return GetTests().NodeReadStaticArrayGuidValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayByteStringValueVariableTestAsync() { return GetTests().NodeReadStaticArrayByteStringValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayXmlElementValueVariableTestAsync() { return GetTests().NodeReadStaticArrayXmlElementValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayNodeIdValueVariableTestAsync() { return GetTests().NodeReadStaticArrayNodeIdValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayExpandedNodeIdValueVariableTestAsync() { return GetTests().NodeReadStaticArrayExpandedNodeIdValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayQualifiedNameValueVariableTestAsync() { return GetTests().NodeReadStaticArrayQualifiedNameValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayLocalizedTextValueVariableTestAsync() { return GetTests().NodeReadStaticArrayLocalizedTextValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayStatusCodeValueVariableTestAsync() { return GetTests().NodeReadStaticArrayStatusCodeValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayVariantValueVariableTestAsync() { return GetTests().NodeReadStaticArrayVariantValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayEnumerationValueVariableTestAsync() { return GetTests().NodeReadStaticArrayEnumerationValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayStructureValueVariableTestAsync() { return GetTests().NodeReadStaticArrayStructureValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayNumberValueVariableTestAsync() { return GetTests().NodeReadStaticArrayNumberValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayIntegerValueVariableTestAsync() { return GetTests().NodeReadStaticArrayIntegerValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayUIntegerValueVariableTestAsync() { return GetTests().NodeReadStaticArrayUIntegerValueVariableTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/MsgPack/ValueReadScalarTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class ValueReadScalarTests : IClassFixture, IDisposable { public ValueReadScalarTests(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private ReadScalarValueTests GetTests() { return new ReadScalarValueTests( _client.Resolve>, _server.GetConnection(), (ep, n, s) => _server.Client.ReadValueAsync(new ConnectionModel { Endpoint = new EndpointModel { Url = ep.Endpoint.Url, Certificate = _server.Certificate?.RawData?.ToThumbprint() } }, n, s)); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task NodeReadAllStaticScalarVariableNodeClassTest1Async() { return GetTests().NodeReadAllStaticScalarVariableNodeClassTest1Async(); } [Fact] public Task NodeReadAllStaticScalarVariableAccessLevelTest1Async() { return GetTests().NodeReadAllStaticScalarVariableAccessLevelTest1Async(); } [Fact] public Task NodeReadAllStaticScalarVariableWriteMaskTest1Async() { return GetTests().NodeReadAllStaticScalarVariableWriteMaskTest1Async(); } [Fact] public Task NodeReadAllStaticScalarVariableWriteMaskTest2Async() { return GetTests().NodeReadAllStaticScalarVariableWriteMaskTest2Async(); } [Fact] public Task NodeReadStaticScalarBooleanValueVariableTestAsync() { return GetTests().NodeReadStaticScalarBooleanValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest1Async() { return GetTests().NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest1Async(); } [Fact] public Task NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest2Async() { return GetTests().NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest2Async(); } [Fact] public Task NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest3Async() { return GetTests().NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest3Async(); } [Fact] public Task NodeReadStaticScalarSByteValueVariableTestAsync() { return GetTests().NodeReadStaticScalarSByteValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarByteValueVariableTestAsync() { return GetTests().NodeReadStaticScalarByteValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarInt16ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarInt16ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarUInt16ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarUInt16ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarInt32ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarInt32ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarUInt32ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarUInt32ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarInt64ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarInt64ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarUInt64ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarUInt64ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarFloatValueVariableTestAsync() { return GetTests().NodeReadStaticScalarFloatValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarDoubleValueVariableTestAsync() { return GetTests().NodeReadStaticScalarDoubleValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarStringValueVariableTestAsync() { return GetTests().NodeReadStaticScalarStringValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarDateTimeValueVariableTestAsync() { return GetTests().NodeReadStaticScalarDateTimeValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarGuidValueVariableTestAsync() { return GetTests().NodeReadStaticScalarGuidValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarByteStringValueVariableTestAsync() { return GetTests().NodeReadStaticScalarByteStringValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarXmlElementValueVariableTestAsync() { return GetTests().NodeReadStaticScalarXmlElementValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarNodeIdValueVariableTestAsync() { return GetTests().NodeReadStaticScalarNodeIdValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarExpandedNodeIdValueVariableTestAsync() { return GetTests().NodeReadStaticScalarExpandedNodeIdValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarQualifiedNameValueVariableTestAsync() { return GetTests().NodeReadStaticScalarQualifiedNameValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarLocalizedTextValueVariableTestAsync() { return GetTests().NodeReadStaticScalarLocalizedTextValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarStatusCodeValueVariableTestAsync() { return GetTests().NodeReadStaticScalarStatusCodeValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarVariantValueVariableTestAsync() { return GetTests().NodeReadStaticScalarVariantValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarEnumerationValueVariableTestAsync() { return GetTests().NodeReadStaticScalarEnumerationValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarStructuredValueVariableTestAsync() { return GetTests().NodeReadStaticScalarStructuredValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarNumberValueVariableTestAsync() { return GetTests().NodeReadStaticScalarNumberValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarIntegerValueVariableTestAsync() { return GetTests().NodeReadStaticScalarIntegerValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarUIntegerValueVariableTestAsync() { return GetTests().NodeReadStaticScalarUIntegerValueVariableTestAsync(); } [Fact] public Task NodeReadDataAccessMeasurementFloatValueTestAsync() { return GetTests().NodeReadDataAccessMeasurementFloatValueTestAsync(); } [Fact] public Task NodeReadDiagnosticsNoneTestAsync() { return GetTests().NodeReadDiagnosticsNoneTestAsync(); } [Fact] public Task NodeReadDiagnosticsStatusTestAsync() { return GetTests().NodeReadDiagnosticsStatusTestAsync(); } [Fact] public Task NodeReadDiagnosticsDebugTestAsync() { return GetTests().NodeReadDiagnosticsDebugTestAsync(); } [Fact] public Task NodeReadDiagnosticsVerboseTestAsync() { return GetTests().NodeReadDiagnosticsVerboseTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/MsgPack/ValueWriteArrayTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection.Name)] public sealed class ValueWriteArrayTests : IClassFixture, IDisposable { public ValueWriteArrayTests(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private WriteArrayValueTests GetTests() { return new WriteArrayValueTests( _client.Resolve>, _server.GetConnection(), (ep, n, s) => _server.Client.ReadValueAsync(new ConnectionModel { Endpoint = new EndpointModel { Url = ep.Endpoint.Url, Certificate = _server.Certificate?.RawData?.ToThumbprint() } }, n, s)); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task NodeWriteStaticArrayBooleanValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayBooleanValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArraySByteValueVariableTestAsync() { return GetTests().NodeWriteStaticArraySByteValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayByteValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayByteValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayInt16ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayInt16ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayUInt16ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayUInt16ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayInt32ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayInt32ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayUInt32ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayUInt32ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayInt64ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayInt64ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayUInt64ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayUInt64ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayFloatValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayFloatValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayDoubleValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayDoubleValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayStringValueVariableTest1Async() { return GetTests().NodeWriteStaticArrayStringValueVariableTest1Async(); } [Fact] public Task NodeWriteStaticArrayStringValueVariableTest2Async() { return GetTests().NodeWriteStaticArrayStringValueVariableTest2Async(); } [Fact] public Task NodeWriteStaticArrayDateTimeValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayDateTimeValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayGuidValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayGuidValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayByteStringValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayByteStringValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayXmlElementValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayXmlElementValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayNodeIdValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayNodeIdValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayExpandedNodeIdValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayExpandedNodeIdValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayQualifiedNameValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayQualifiedNameValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayLocalizedTextValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayLocalizedTextValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayStatusCodeValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayStatusCodeValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayVariantValueVariableTest1Async() { return GetTests().NodeWriteStaticArrayVariantValueVariableTest1Async(); } [Fact] public Task NodeWriteStaticArrayEnumerationValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayEnumerationValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayStructureValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayStructureValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayNumberValueVariableTest1Async() { return GetTests().NodeWriteStaticArrayNumberValueVariableTest1Async(); } [Fact] public Task NodeWriteStaticArrayNumberValueVariableTest2Async() { return GetTests().NodeWriteStaticArrayNumberValueVariableTest2Async(); } [Fact] public Task NodeWriteStaticArrayIntegerValueVariableTest1Async() { return GetTests().NodeWriteStaticArrayIntegerValueVariableTest1Async(); } [Fact] public Task NodeWriteStaticArrayIntegerValueVariableTest2Async() { return GetTests().NodeWriteStaticArrayIntegerValueVariableTest2Async(); } [Fact] public Task NodeWriteStaticArrayUIntegerValueVariableTest1Async() { return GetTests().NodeWriteStaticArrayUIntegerValueVariableTest1Async(); } [Fact] public Task NodeWriteStaticArrayUIntegerValueVariableTest2Async() { return GetTests().NodeWriteStaticArrayUIntegerValueVariableTest2Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/MsgPack/ValueWriteScalarTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.MsgPack { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection.Name)] public sealed class ValueWriteScalarTests : IClassFixture, IDisposable { public ValueWriteScalarTests(TestDataServer server, PublisherModuleFixture module, ITestOutputHelper output) { _server = server; _client = module.CreateRestClientContainer(output, TestSerializerType.MsgPack); } public void Dispose() { _client.Dispose(); } private WriteScalarValueTests GetTests() { return new WriteScalarValueTests( _client.Resolve>, _server.GetConnection(), (ep, n, s) => _server.Client.ReadValueAsync(new ConnectionModel { Endpoint = new EndpointModel { Url = ep.Endpoint.Url, Certificate = _server.Certificate?.RawData?.ToThumbprint() } }, n, s)); } private readonly TestDataServer _server; private readonly IContainer _client; [Fact] public Task NodeWriteStaticScalarBooleanValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarBooleanValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest1Async() { return GetTests().NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest1Async(); } [Fact] public Task NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest2Async() { return GetTests().NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest2Async(); } [Fact] public Task NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest3Async() { return GetTests().NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest3Async(); } [Fact] public Task NodeWriteStaticScalarSByteValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarSByteValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarByteValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarByteValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarInt16ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarInt16ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarUInt16ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarUInt16ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarInt32ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarInt32ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarUInt32ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarUInt32ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarInt64ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarInt64ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarUInt64ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarUInt64ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarFloatValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarFloatValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarDoubleValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarDoubleValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarStringValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarStringValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarDateTimeValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarDateTimeValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarGuidValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarGuidValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarByteStringValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarByteStringValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarXmlElementValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarXmlElementValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarNodeIdValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarNodeIdValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarExpandedNodeIdValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarExpandedNodeIdValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarQualifiedNameValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarQualifiedNameValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarLocalizedTextValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarLocalizedTextValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarStatusCodeValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarStatusCodeValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarVariantValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarVariantValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarEnumerationValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarEnumerationValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarStructuredValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarStructuredValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarNumberValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarNumberValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarIntegerValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarIntegerValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarUIntegerValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarUIntegerValueVariableTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Controller/TestData/MsgPack/WriteCollection.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Controller.TestData.MsgPack { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public sealed class WriteCollection : ICollectionFixture { public const string Name = "TestDataServerWriteRestMsgPack"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Fixtures/PublisherIntegrationTestBase.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Sdk; using Azure.IIoT.OpcUa.Encoders; using Autofac; using Furly.Extensions.Mqtt; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Microsoft.Extensions.Logging; using Neovolve.Logging.Xunit; using System; using System.Buffers; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; /// /// Json message /// /// /// /// public readonly record struct JsonMessage(string Topic, JsonElement Message, string ContentType); /// /// Base class for integration testing, it connects to the server, runs /// publisher and injects mocked IoTHub services. /// public class PublisherIntegrationTestBase : IDisposable { protected string EndpointUrl { get; set; } protected CancellationToken Ct => _cts.Token; /// /// Create fixture /// /// /// /// public PublisherIntegrationTestBase(ITestOutputHelper testOutputHelper, TimeSpan? timeout = null, string testName = null) { _cts = new CancellationTokenSource(timeout ?? kTotalTestTimeout); _testOutputHelper = testOutputHelper; _logFactory = LogFactory.Create(testOutputHelper, Logging.Config); _logger = _logFactory.CreateLogger(testName ?? "PublisherIntegrationTest"); } /// /// Dispose /// /// protected virtual void Dispose(bool disposing) { if (disposing && !_disposedValue) { _disposedValue = true; if (_cts.IsCancellationRequested) { _logger.TestTimeout(); } if (_publisher != null) { StopPublisherAsync().WaitAsync(TimeSpan.FromMinutes(1)).GetAwaiter().GetResult(); } _cts.Dispose(); _logFactory.Dispose(); } } /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Get one message from running publisher /// /// /// /// /// /// /// protected Task> ProcessMessagesAsync(string test, string publishedNodesFile, Func predicate = null, string messageType = null, string[] arguments = default) { // Collect messages from server with default settings return ProcessMessagesAsync(test, publishedNodesFile, kTelemetryTimeout, 1, predicate, messageType, arguments); } /// /// Get one message from a running publisher /// /// /// /// /// /// /// /// protected Task<(JsonMessage? Metadata, List Messages)> ProcessMessagesAndMetadataAsync( string test, string publishedNodesFile, Func predicate = null, string messageType = null, string[] arguments = default, MqttVersion? version = null) { // Collect messages from server with default settings return ProcessMessagesAndMetadataAsync(test, publishedNodesFile, kTelemetryTimeout, 1, predicate, messageType, arguments, version); } /// /// Process messages and return /// /// /// /// /// /// /// /// /// protected async Task> ProcessMessagesAsync(string test, string publishedNodesFile, TimeSpan messageCollectionTimeout, int messageCount, Func predicate = null, string messageType = null, string[] arguments = default) { var (_, messages) = await ProcessMessagesAndMetadataAsync(test, publishedNodesFile, messageCollectionTimeout, messageCount, predicate, messageType, arguments).ConfigureAwait(false); return messages; } /// /// Start publisher and wait for messages and return them /// /// /// /// /// /// /// /// /// /// protected async Task<(JsonMessage? Metadata, List Messages)> ProcessMessagesAndMetadataAsync( string test, string publishedNodesFile, TimeSpan messageCollectionTimeout, int messageCount, Func predicate = null, string messageType = null, string[] arguments = default, MqttVersion? version = null) { StartPublisher(test, publishedNodesFile, arguments, version); try { return await WaitForMessagesAndMetadataAsync(messageCollectionTimeout, messageCount, predicate, messageType).ConfigureAwait(false); } finally { await StopPublisherAsync(); } } /// /// Wait for one message /// /// /// protected Task> WaitForMessagesAsync( Func predicate = null, string messageType = null) { // Collect messages from server with default settings return WaitForMessagesAsync(kTelemetryTimeout, 1, predicate, messageType); } /// /// Wait for one message /// /// /// /// /// protected async Task> WaitForMessagesAsync(TimeSpan messageCollectionTimeout, int messageCount, Func predicate = null, string messageType = null) { // Collect messages from server with default settings var (_, messages) = await WaitForMessagesAndMetadataAsync(messageCollectionTimeout, messageCount, predicate, messageType).ConfigureAwait(false); return messages; } /// /// Wait for messages /// /// /// /// /// protected async Task<(JsonMessage? Metadata, List Messages)> WaitForMessagesAndMetadataAsync( TimeSpan messageCollectionTimeout, int messageCount, Func predicate = null, string messageType = null) { var stopWatch = new Stopwatch(); stopWatch.Start(); var messages = new List(); JsonMessage? metadata = null; using var cts = new CancellationTokenSource(messageCollectionTimeout); try { await foreach (var evt in _publisher.ReadTelemetryAsync(cts.Token)) { if (evt.Properties.TryGetValue(Constants.MessagePropertySchemaKey, out var schematype) && schematype != MessageSchemaTypes.NetworkMessageJson && schematype != MessageSchemaTypes.MonitoredItemMessageJson && schematype != MessageSchemaTypes.NetworkMessageUadp) { continue; } if (evt.Data.IsEmpty) { // Skip empty messages continue; } var json = Encoding.UTF8.GetString(evt.Data.ToArray()); var document = JsonDocument.Parse(json); json = JsonSerializer.Serialize(document, kIndented); var element = document.RootElement; if (element.ValueKind == JsonValueKind.Array) { foreach (var item in element.EnumerateArray()) { Add(messages, item, ref metadata, predicate, messageType, _messageIds, evt.Topic, evt.ContentType); } } else if (element.ValueKind == JsonValueKind.Object) { Add(messages, element, ref metadata, predicate, messageType, _messageIds, evt.Topic, evt.ContentType); } if (messages.Count >= messageCount) { break; } } } catch (OperationCanceledException) { } _logger.MessagesReceived(messages.Count, stopWatch.Elapsed); return (metadata, messages.Take(messageCount).ToList()); static void Add(List messages, JsonElement item, ref JsonMessage? metadata, Func predicate, string messageType, HashSet messageIds, string topic, string contentType) { if (messageType != null) { if (item.TryGetProperty("MessageType", out var v)) { var type = v.GetString(); if (type == "ua-metadata") { metadata = new JsonMessage(topic, item, contentType); } if (type != messageType) { return; } } if (item.TryGetProperty("MessageId", out var id)) { Assert.True(messageIds.Add(id.GetString())); } } var add = item; if (predicate != null) { add = predicate(item); } if (add.ValueKind == JsonValueKind.Object) { messages.Add(new JsonMessage(topic, add, contentType)); } } } private static readonly JsonSerializerOptions kIndented = new() { WriteIndented = true }; /// /// Start publisher /// /// /// /// /// /// /// /// protected void StartPublisher(string test, string publishedNodesFile = null, string[] arguments = default, MqttVersion? version = null, int? reverseConnectPort = null, int keepAliveInterval = 120, SecurityMode? securityMode = null) { var sw = Stopwatch.StartNew(); _logger = _logFactory.CreateLogger(test); arguments ??= []; _publishedNodesFilePath = Path.GetTempFileName(); WritePublishedNodes(test, publishedNodesFile, reverseConnectPort != null, securityMode); arguments = [ .. arguments, .. new[] { $"--pf={_publishedNodesFilePath}" }, ]; if (OperatingSystem.IsLinux()) { arguments = [.. arguments, "--pol"]; } if (reverseConnectPort != null) { arguments = [ .. arguments, .. new[] { $"--rcp={reverseConnectPort.Value}" }, ]; } _publisher = new PublisherModule(null, null, null, null, _testOutputHelper, arguments, version, keepAliveInterval); _logger.PublisherStarted(sw.Elapsed); } /// /// Update published nodes file /// /// /// /// /// protected void WritePublishedNodes(string test, string publishedNodesFile, bool useReverseConnect = false, SecurityMode? securityMode = null) { if (!string.IsNullOrEmpty(publishedNodesFile)) { var pnJson = File.ReadAllText(publishedNodesFile) .Replace("\"{{UseReverseConnect}}\"", useReverseConnect ? "true" : "false", StringComparison.Ordinal) .Replace("{{EndpointUrl}}", EndpointUrl, StringComparison.Ordinal) .Replace("{{SecurityMode}}", (securityMode ?? SecurityMode.None).ToString(), StringComparison.Ordinal) .Replace("{{DataSetWriterGroup}}", test, StringComparison.Ordinal); File.WriteAllText(_publishedNodesFilePath, pnJson); } } /// /// Get publisher api /// protected IPublisherApi PublisherApi => _publisher?.ClientContainer?.Resolve(); /// /// Stop publisher /// protected async Task StopPublisherAsync() { if (_publisher != null) { var sw = Stopwatch.StartNew(); await _publisher.DisposeAsync(); _publisher = null; if (File.Exists(_publishedNodesFilePath)) { File.Delete(_publishedNodesFilePath); } _logger.PublisherStopped(sw.Elapsed); } } /// /// Get endpoints from file /// /// /// /// /// /// protected PublishedNodesEntryModel[] GetEndpointsFromFile(string test, string publishedNodesFile, bool useReverseConnect = false, SecurityMode? securityMode = null) { IJsonSerializer serializer = new NewtonsoftJsonSerializer(); var fileContent = File.ReadAllText(publishedNodesFile) .Replace("\"{{UseReverseConnect}}\"", useReverseConnect ? "true" : "false", StringComparison.Ordinal) .Replace("{{EndpointUrl}}", EndpointUrl, StringComparison.Ordinal) .Replace("{{SecurityMode}}", (securityMode ?? SecurityMode.None).ToString(), StringComparison.Ordinal) .Replace("{{DataSetWriterGroup}}", test, StringComparison.Ordinal); return serializer.Deserialize(fileContent); } private static readonly TimeSpan kTelemetryTimeout = TimeSpan.FromMinutes(2); private static readonly TimeSpan kTotalTestTimeout = TimeSpan.FromMinutes(5); private readonly CancellationTokenSource _cts; private readonly ITestOutputHelper _testOutputHelper; private readonly HashSet _messageIds = []; private readonly ILoggerFactory _logFactory; private ILogger _logger; private PublisherModule _publisher; private string _publishedNodesFilePath; private bool _disposedValue; } /// /// Source-generated logging definitions for PublisherIntegrationTestBase /// internal static partial class PublisherIntegrationTestLogging { private const int EventClass = 0; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Error, Message = "OperationCanceledException thrown due to test time out.")] public static partial void TestTimeout(this ILogger logger); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Information, Message = "Received {MessageCount} messages in {Elapsed}.")] public static partial void MessagesReceived(this ILogger logger, int messageCount, TimeSpan elapsed); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Information, Message = "Publisher started in {Elapsed}.")] public static partial void PublisherStarted(this ILogger logger, TimeSpan elapsed); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Information, Message = "Publisher stopped in {Elapsed}.")] public static partial void PublisherStopped(this ILogger logger, TimeSpan elapsed); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Fixtures/PublisherModule.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Clients; using Azure.IIoT.OpcUa.Publisher.Module.Runtime; using Azure.IIoT.OpcUa.Publisher.Sdk; using Azure.IIoT.OpcUa.Publisher.Sdk.Clients; using Azure.IIoT.OpcUa.Publisher.Service.Clients.Adapters; using Azure.IIoT.OpcUa.Publisher.Testing.Runtime; using Autofac; using Autofac.Extensions.DependencyInjection; using Furly.Azure; using Furly.Azure.IoT; using Furly.Azure.IoT.Edge; using Furly.Azure.IoT.Mock; using Furly.Azure.IoT.Mock.Services; using Furly.Azure.IoT.Models; using Furly.Extensions.Hosting; using Furly.Extensions.Messaging; using Furly.Extensions.Mqtt; using Furly.Extensions.Mqtt.Clients; using Furly.Extensions.Serializers; using Furly.Extensions.Utils; using Furly.Tunnel.Protocol; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Neovolve.Logging.Xunit; using Opc.Ua; using System; using System.Buffers; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http; using System.Net.Http.Headers; using System.Text; using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; using Xunit.Abstractions; /// /// Publisher telemetry /// /// /// /// /// /// /// /// public sealed record class PublisherTelemetry(string DeviceId, string ModuleId, string Topic, ReadOnlySequence Data, string ContentType, string ContentEncoding, IReadOnlyDictionary Properties); /// /// Opc Publisher module fixture /// public sealed class PublisherModule : WebApplicationFactory, IHttpClientFactory { /// /// Sdk target /// public string Target { get; } /// /// Current directory /// public string CurrentDirectory { get; } /// /// ServerPkiRootPath /// public string ServerPkiRootPath { get; } /// /// ClientPkiRootPath /// public string ClientPkiRootPath { get; } /// /// Hub container /// public IContainer ClientContainer { get; } /// /// Create fixture /// /// /// /// /// /// /// /// /// public PublisherModule(IMessageSink messageSink, IEnumerable devices = null, string deviceId = null, string moduleId = null, ITestOutputHelper testOutputHelper = null, string[] arguments = default, MqttVersion? version = null, int keepAliveInterval = 120) { _logFactory = testOutputHelper != null ? LogFactory.Create(testOutputHelper, Logging.Config) : null; ClientContainer = CreateIoTHubSdkClientContainer(messageSink, testOutputHelper, devices, version); // Create module identitity deviceId ??= Utils.GetHostName(); moduleId ??= Guid.NewGuid().ToString(); arguments ??= []; var publisherModule = new DeviceTwinModel { Id = deviceId, ModuleId = moduleId }; var service = ClientContainer.Resolve(); var twin = service.CreateOrUpdateAsync(publisherModule).AsTask().GetAwaiter().GetResult(); var device = service.GetRegistrationAsync(twin.Id, twin.ModuleId).AsTask().GetAwaiter().GetResult(); _useMqtt = version != null; if (_useMqtt) { // Resolve the mqtt server to make sure it is running _ = ClientContainer.Resolve().GetAwaiter().GetResult(); } CurrentDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); if (!Directory.Exists(CurrentDirectory)) { Directory.CreateDirectory(CurrentDirectory); } ServerPkiRootPath = Path.Combine(CurrentDirectory, "pki", Guid.NewGuid().ToByteArray().ToBase16String()); ClientPkiRootPath = Path.Combine(CurrentDirectory, "pki", Guid.NewGuid().ToByteArray().ToBase16String()); // Create a virtual connection betwenn publisher module and hub var hub = ClientContainer.Resolve(); _connection = hub.Connect(device.Id, device.ModuleId); // Start module var edgeHubCs = ConnectionString.CreateModuleConnectionString( "test.test.org", device.Id, device.ModuleId, device.PrimaryKey); var mqttOptions = ClientContainer.Resolve>(); var mqttCs = $"HostName={mqttOptions.Value.HostName};Port={mqttOptions.Value.Port};" + $"UserName={mqttOptions.Value.UserName};Password={mqttOptions.Value.Password};" + $"UseTls={mqttOptions.Value.UseTls};Protocol={mqttOptions.Value.Protocol};" + $"Partitions={mqttOptions.Value.NumberOfClientPartitions};" + $"KeepAlivePeriod={mqttOptions.Value.KeepAlivePeriod}" ; var publisherId = Guid.NewGuid().ToString(); arguments = [ .. arguments, .. new[] { $"--id={publisherId}", $"--ec={edgeHubCs}", $"--mqc={mqttCs}", $"--ki={keepAliveInterval}", "--aa" }, ]; if (OperatingSystem.IsLinux()) { arguments = [.. arguments, "--pol"]; } if (_useMqtt) { arguments = [.. arguments, "-t=Mqtt"]; } if (!arguments.Any(a => a.StartsWith("-f=", StringComparison.Ordinal) || a.StartsWith("--pf=", StringComparison.Ordinal) || a.StartsWith("--publishfile=", StringComparison.Ordinal))) { arguments = [ .. arguments, "--cf", "--pf=" + Path.Combine(CurrentDirectory, "publishednodes.json"), ]; } var configBuilder = new ConfigurationBuilder() .AddInMemoryCollection(new Dictionary { { "PkiRootPath", ClientPkiRootPath } }) .AddInMemoryCollection(new CommandLine(arguments)) ; _config = configBuilder.Build(); _ = Server; // Ensure server is created // Register with the telemetry handler to receive telemetry events if (!_useMqtt) { var register = ClientContainer.Resolve>(); _telemetry = new IoTHubTelemetryHandler(); _handler1 = register.Register(_telemetry); Target = Furly.Azure.HubResource.Format(null, device.Id, device.ModuleId); } else { _consumer = new EventConsumer(); var register = ClientContainer.Resolve(); var options = Resolve>(); var topicBuilder = new TopicBuilder(options.Value); _handler2 = register.SubscribeAsync(topicBuilder.RootTopic + "/messages/#", _consumer) .AsTask().GetAwaiter().GetResult(); Target = topicBuilder.MethodTopic; } } /// protected override IHostBuilder CreateHostBuilder() { return Host.CreateDefaultBuilder(); } /// protected override void ConfigureWebHost(IWebHostBuilder builder) { builder .UseContentRoot(".") .UseStartup() .UseConfiguration(_config) .ConfigureServices(services => services .AddMvc() .AddApplicationPart(typeof(Startup).Assembly) .AddControllersAsServices()) ; base.ConfigureWebHost(builder); } /// protected override IHost CreateHost(IHostBuilder builder) { builder .UseServiceProviderFactory(new AutofacServiceProviderFactory()) .ConfigureContainer(ConfigureContainer) ; return base.CreateHost(builder); } /// public HttpClient CreateClient(string name) { return CreateClient(new WebApplicationFactoryClientOptions { AllowAutoRedirect = false }); } /// protected override void ConfigureClient(HttpClient client) { var apiKey = _connection.Twin.State[Constants.TwinPropertyApiKeyKey].ConvertTo(); base.ConfigureClient(client); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("ApiKey", apiKey); client.Timeout = TimeSpan.FromMinutes(30); } /// /// Resolve service from publisher module /// /// /// public T Resolve() { return (T)Server.Services.GetService(typeof(T)); } /// /// Read publisher telemetry /// /// /// /// public IAsyncEnumerable ReadTelemetryAsync(CancellationToken ct) { if (_telemetry != null) { return _telemetry.Reader.ReadAllAsync(ct); } else if (_consumer != null) { return _consumer.Reader.ReadAllAsync(ct); } else { throw new InvalidOperationException("No consumer configured."); } } /// public override async ValueTask DisposeAsync() { await base.DisposeAsync(); // Throw if we cannot dispose using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(5)); await InnerDisposeAsync().WaitAsync(cts.Token); _logFactory?.Dispose(); async Task InnerDisposeAsync() { _connection.Close(); _handler1?.Dispose(); if (_handler2 != null) { await _handler2.DisposeAsync(); } if (Directory.Exists(CurrentDirectory)) { Try.Op(() => Directory.Delete(CurrentDirectory, true)); } ClientContainer.Dispose(); } } internal sealed class IoTEdgeMockIdentity : IIoTEdgeDeviceIdentity { public string Hub { get; } = "Hub"; public string DeviceId { get; } = "DeviceId"; public string ModuleId { get; } = "ModuleId"; public string Gateway { get; } = "Gateway"; } /// public void ConfigureContainer(ContainerBuilder builder) { // Register publisher services builder.AddPublisherServices(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces().InstancePerLifetimeScope(); if (_connection.EventClient is IProcessIdentity identity) { builder.RegisterInstance(identity); } builder.RegisterInstance(_connection.EventClient); builder.RegisterInstance(_connection.RpcServer); builder.RegisterInstance(_connection.Twin); if (_logFactory != null) { builder.RegisterInstance(_logFactory); } // Register transport services if (_useMqtt) { // Dont just register if the broker is not running or // otherwise the connect hangs during startup. // TODO: Look into this. builder.AddMqttClient(_config); } // Override client config builder.RegisterInstance(_config).AsImplementedInterfaces(); // Override process control builder.RegisterType() .AsImplementedInterfaces().SingleInstance(); } /// /// Create client container /// /// /// /// public IContainer CreateClientScope(ITestOutputHelper output, TestSerializerType serializerType) { var builder = new ContainerBuilder(); builder.ConfigureServices(services => services.AddLogging()); builder.AddOptions(); #pragma warning disable CA2000 // Dispose objects before losing scope builder.RegisterInstance(LogFactory.Create(output, Logging.Config)) .AsImplementedInterfaces(); #pragma warning restore CA2000 // Dispose objects before losing scope // Add API builder.Configure(options => options.Target = Server.BaseAddress.ToString()); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); switch (serializerType) { case TestSerializerType.NewtonsoftJson: builder.AddNewtonsoftJsonSerializer(); break; case TestSerializerType.Json: builder.AddDefaultJsonSerializer(); break; case TestSerializerType.MsgPack: builder.AddMessagePackSerializer(); break; } // Register http client factory builder.RegisterInstance(this) .As().ExternallyOwned(); // Do not dispose return builder.Build(); } /// /// Create hub container /// /// /// /// /// /// private IContainer CreateIoTHubSdkClientContainer(IMessageSink messageSink = null, ITestOutputHelper testOutputHelper = null, IEnumerable devices = null, MqttVersion? mqttVersion = null) { var builder = new ContainerBuilder(); builder.AddNewtonsoftJsonSerializer(); builder.Configure(options => options.Target = Target); builder.ConfigureServices(services => { services.AddHttpClient(); services.AddLogging(logging => { if (messageSink != null) { // logging.AddXunit(messageSink); // TODO } if (testOutputHelper != null) { logging.AddXunit(testOutputHelper); } else { logging.AddConsole(); } }); }); builder.Configure(option => { option.ConnectionString = ConnectionString.CreateServiceConnectionString( "test.test.org", "iothubowner", Convert.ToBase64String( Encoding.UTF8.GetBytes(Guid.NewGuid().ToString()))).ToString(); }); // Configure mqtt builder.ConfigureMqtt(options => { options.AllowUntrustedCertificates = true; options.UseTls = false; options.Protocol = mqttVersion ?? MqttVersion.v5; options.KeepAlivePeriod = TimeSpan.Zero; options.NumberOfClientPartitions = 1; options.Port = Interlocked.Increment(ref _mqttPort); }); if (devices != null) { builder.Register(ctx => IoTHubMock.Create(devices, ctx.Resolve())) .AsImplementedInterfaces().SingleInstance(); } else { builder.RegisterType() .AsImplementedInterfaces().SingleInstance(); } if (mqttVersion != null) { // Override the iothub rpcclient with an mqtt server implementation builder.AddMqttServer(); } builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); builder.RegisterType() .AsImplementedInterfaces(); return builder.Build(); } /// /// Mock exiting /// internal sealed class ExitOverride : IProcessControl { public bool Shutdown(bool failFast) { return true; } } /// /// Adapter for telemetry handler /// internal sealed class IoTHubTelemetryHandler : IIoTHubTelemetryHandler { public ChannelReader Reader => _channel.Reader; internal IoTHubTelemetryHandler() { _channel = Channel.CreateUnbounded(); } public ValueTask HandleAsync(string deviceId, string moduleId, string topic, ReadOnlySequence data, string contentType, string contentEncoding, IReadOnlyDictionary properties, CancellationToken ct) { return _channel.Writer.WriteAsync(new PublisherTelemetry( deviceId, moduleId, topic, data, contentType, contentEncoding, properties), ct); } private readonly Channel _channel; } /// /// Adapter for event consumer /// internal sealed class EventConsumer : IEventConsumer { public ChannelReader Reader => _channel.Reader; internal EventConsumer() { _channel = Channel.CreateUnbounded(); } public async Task HandleAsync(string topic, ReadOnlySequence data, string contentType, IReadOnlyDictionary properties, IEventClient responder = null, CancellationToken ct = default) { properties.TryGetValue("ContentEncoding", out var contentEncoding); await _channel.Writer.WriteAsync(new PublisherTelemetry( null, null, topic, data, contentType, contentEncoding, properties), ct).ConfigureAwait(false); } private readonly Channel _channel; } private static int _mqttPort = 48882; private readonly IIoTHubConnection _connection; private readonly IConfiguration _config; private readonly bool _useMqtt; private readonly IoTHubTelemetryHandler _telemetry; private readonly IDisposable _handler1; private readonly IAsyncDisposable _handler2; private readonly EventConsumer _consumer; private readonly ILoggerFactory _logFactory; } public class ModuleStartup : Startup { public ModuleStartup(IConfiguration configuration) : base(configuration) { } public override void ConfigureContainer(ContainerBuilder builder) { } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Fixtures/PublisherModuleFixture.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures { using Autofac; using System; using Xunit.Abstractions; public sealed class PublisherModuleMqttv5Fixture : IDisposable { public IContainer SdkContainer => _publisher.ClientContainer; /// /// Create fixture /// /// public PublisherModuleMqttv5Fixture(IMessageSink messageSink) { _publisher = new PublisherModule(messageSink, version: Furly.Extensions.Mqtt.MqttVersion.v5); } /// public void Dispose() { _publisher.Dispose(); } private readonly PublisherModule _publisher; } public sealed class PublisherModuleMqttv311Fixture : IDisposable { public IContainer SdkContainer => _publisher.ClientContainer; /// /// Create fixture /// /// public PublisherModuleMqttv311Fixture(IMessageSink messageSink) { _publisher = new PublisherModule(messageSink, version: Furly.Extensions.Mqtt.MqttVersion.v311); } /// public void Dispose() { _publisher.Dispose(); } private readonly PublisherModule _publisher; } public sealed class PublisherModuleFixture : IDisposable { public IContainer SdkContainer => _publisher.ClientContainer; /// /// Create fixture /// /// public PublisherModuleFixture(IMessageSink messageSink) { _publisher = new PublisherModule(messageSink); } /// /// Create rest client scope /// /// /// /// public IContainer CreateRestClientContainer(ITestOutputHelper output, TestSerializerType serializerType) { return _publisher.CreateClientScope(output, serializerType); } /// public void Dispose() { _publisher.Dispose(); } private readonly PublisherModule _publisher; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Fixtures/ReferenceServerReadCollection.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public class ReferenceServerReadCollection : ICollectionFixture { public const string Name = "Read"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Fixtures/TempFileProviderBase.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Tests.Utils { using System; using System.IO; /// /// Base class that provides a temporary file that will be cleaned up on disposal. /// public class TempFileProviderBase : IDisposable { protected readonly string _tempFile; public TempFileProviderBase() { _tempFile = Path.GetTempFileName(); } protected virtual void Dispose(bool disposing) { try { // Remove temporary published nodes file if one was created. if (File.Exists(_tempFile)) { File.Delete(_tempFile); } } catch { // Nothign to do. } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Fixtures/TestSerializerType.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures { public enum TestSerializerType { Json, MsgPack, NewtonsoftJson, } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Fixtures/TwinIntegrationTestBase.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures { using System; using System.Threading; using Xunit.Abstractions; public abstract class TwinIntegrationTestBase : IDisposable { protected CancellationToken Ct => _cts.Token; protected TwinIntegrationTestBase(ITestOutputHelper testOutputHelper = null, TimeSpan? timeout = null) { _cts = new CancellationTokenSource(timeout ?? kTotalTestTimeout); _testOutputHelper = testOutputHelper; } protected virtual void Dispose(bool disposing) { if (!_disposedValue) { if (disposing) { if (_cts.IsCancellationRequested) { _testOutputHelper.WriteLine( "OperationCanceledException thrown due to test time out."); } _cts.Dispose(); } _disposedValue = true; } } public void Dispose() { // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method Dispose(disposing: true); GC.SuppressFinalize(this); } private static readonly TimeSpan kTotalTestTimeout = #if DEBUG TimeSpan.FromMinutes(60) #else TimeSpan.FromMinutes(2) #endif ; private readonly CancellationTokenSource _cts; private readonly ITestOutputHelper _testOutputHelper; private bool _disposedValue; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/GlobalSuppressions.cs ================================================ // This file is used by Code Analysis to maintain SuppressMessage // attributes that are applied to this project. // Project-level suppressions either have no target or are given // a specific target and scoped to a namespace, type, member, etc. using System.Diagnostics.CodeAnalysis; [assembly: SuppressMessage("Reliability", "CA2007:Consider calling ConfigureAwait on the awaited task", Justification = "xunit")] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Logging.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests { using Microsoft.Extensions.Logging; using Neovolve.Logging.Xunit; internal static class Logging { /// /// Default level /// public static LogLevel Level => LogLevel.Information; /// /// Configuration /// public static LoggingConfig Config => new() { LogLevel = Level }; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/Alarms/NodeServicesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.Alarms { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class NodeServicesTests : TwinIntegrationTestBase, IClassFixture, IClassFixture { public NodeServicesTests(AlarmsServer server, PublisherModuleMqttv5Fixture module, ITestOutputHelper output) : base(output) { _server = server; _module = module; } private AlarmServerTests GetTests() { return new AlarmServerTests( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly AlarmsServer _server; private readonly PublisherModuleMqttv5Fixture _module; [Fact] public Task BrowseAreaPathTestAsync() { return GetTests().BrowseAreaPathTestAsync(Ct); } [Fact] public Task BrowseMetalsSouthMotorTestAsync() { return GetTests().BrowseMetalsSouthMotorTestAsync(Ct); } [Fact] public Task BrowseColoursEastTankTestAsync() { return GetTests().BrowseColoursEastTankTestAsync(Ct); } [Fact] public Task CompileAlarmQueryTest1Async() { return GetTests().CompileAlarmQueryTest1Async(); } [Fact] public Task CompileAlarmQueryTest2Async() { return GetTests().CompileAlarmQueryTest2Async(); } [Fact] public Task CompileSimpleBaseEventQueryTestAsync() { return GetTests().CompileSimpleBaseEventQueryTestAsync(); } [Fact] public Task CompileSimpleTripAlarmQueryTestAsync() { return GetTests().CompileSimpleTripAlarmQueryTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/DeterministicAlarms/NodeServicesTests1.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.DeterministicAlarms { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class NodeServicesTests1 : TwinIntegrationTestBase, IClassFixture, IClassFixture { public NodeServicesTests1(DeterministicAlarmsServer1 server, PublisherModuleMqttv311Fixture module, ITestOutputHelper output) : base(output) { _server = server; _module = module; } private DeterministicAlarmsTests1 GetTests() { return new DeterministicAlarmsTests1( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly DeterministicAlarmsServer1 _server; private readonly PublisherModuleMqttv311Fixture _module; [Fact] public Task BrowseAreaPathVendingMachine1TemperatureHighTestAsync() { return GetTests().BrowseAreaPathVendingMachine1TemperatureHighTestAsync(Ct); } [Fact] public Task BrowseAreaPathVendingMachine2LightOffTestAsync() { return GetTests().BrowseAreaPathVendingMachine2LightOffTestAsync(Ct); } [Fact] public Task BrowseAreaPathVendingMachine1DoorOpenTestAsync() { return GetTests().BrowseAreaPathVendingMachine1DoorOpenTestAsync(Ct); } [Fact] public Task BrowseAreaPathVendingMachine2DoorOpenTestAsync() { return GetTests().BrowseAreaPathVendingMachine2DoorOpenTestAsync(Ct); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/DeterministicAlarms/NodeServicesTests2.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.DeterministicAlarms { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class NodeServicesTests2 : TwinIntegrationTestBase, IClassFixture, IClassFixture { public NodeServicesTests2(DeterministicAlarmsServer2 server, PublisherModuleMqttv5Fixture module, ITestOutputHelper output) : base(output) { _server = server; _module = module; } private DeterministicAlarmsTests2 GetTests() { return new DeterministicAlarmsTests2( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly DeterministicAlarmsServer2 _server; private readonly PublisherModuleMqttv5Fixture _module; [Fact] public Task BrowseAreaPathVendingMachine1DoorOpenTestAsync() { return GetTests().BrowseAreaPathVendingMachine1DoorOpenTestAsync(Ct); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/HistoricalAccess/NodeServicesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.HistoricalAccess { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class NodeServicesTests : TwinIntegrationTestBase, IClassFixture { public NodeServicesTests(HistoricalAccessServer server, PublisherModuleMqttv5Fixture module, ITestOutputHelper output) : base(output) { _server = server; _module = module; } private NodeHistoricalAccessTests GetTests() { return new NodeHistoricalAccessTests( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly PublisherModuleMqttv5Fixture _module; [Fact] public Task GetServerCapabilitiesTestAsync() { return GetTests().GetServerCapabilitiesTestAsync(Ct); } [Fact] public Task HistoryGetServerCapabilitiesTestAsync() { return GetTests().HistoryGetServerCapabilitiesTestAsync(Ct); } [Fact] public Task HistoryGetInt16NodeHistoryConfiguration() { return GetTests().HistoryGetInt16NodeHistoryConfigurationAsync(Ct); } [Fact] public Task HistoryGetInt64NodeHistoryConfigurationAsync() { return GetTests().HistoryGetInt64NodeHistoryConfigurationAsync(Ct); } [Fact] public Task HistoryGetNodeHistoryConfigurationFromBadNode() { return GetTests().HistoryGetNodeHistoryConfigurationFromBadNodeAsync(Ct); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/HistoricalAccess/ReadAtTimesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.HistoricalAccess { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class ReadAtTimesTests : TwinIntegrationTestBase, IClassFixture { public ReadAtTimesTests(HistoricalAccessServer server, PublisherModuleMqttv5Fixture module, ITestOutputHelper output) : base(output) { _server = server; _module = module; } private HistoryReadValuesAtTimesTests GetTests() { return new HistoryReadValuesAtTimesTests(_server, _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly PublisherModuleMqttv5Fixture _module; [Fact] public Task HistoryReadInt32ValuesAtTimesTest1Async() { return GetTests().HistoryReadInt32ValuesAtTimesTest1Async(Ct); } [Fact] public Task HistoryReadInt32ValuesAtTimesTest2Async() { return GetTests().HistoryReadInt32ValuesAtTimesTest2Async(Ct); } [Fact] public Task HistoryReadInt32ValuesAtTimesTest3Async() { return GetTests().HistoryReadInt32ValuesAtTimesTest3Async(Ct); } [Fact] public Task HistoryReadInt32ValuesAtTimesTest4Async() { return GetTests().HistoryReadInt32ValuesAtTimesTest4Async(Ct); } [SkippableFact] public Task HistoryStreamInt32ValuesAtTimesTest1Async() { Skip.If(true, "Not yet supported"); return GetTests().HistoryStreamInt32ValuesAtTimesTest1Async(Ct); } [SkippableFact] public Task HistoryStreamInt32ValuesAtTimesTest2Async() { Skip.If(true, "Not yet supported"); return GetTests().HistoryStreamInt32ValuesAtTimesTest2Async(Ct); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/HistoricalAccess/ReadCollection.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.HistoricalAccess { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name, DisableParallelization = true)] public class ReadCollection : ICollectionFixture { public const string Name = "HistoricalAccessServerReadModuleMqtt"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/HistoricalAccess/ReadModifiedTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.HistoricalAccess { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class ReadModifiedTests : TwinIntegrationTestBase, IClassFixture { public ReadModifiedTests(HistoricalAccessServer server, PublisherModuleMqttv311Fixture module, ITestOutputHelper output) : base(output) { _server = server; _module = module; } private HistoryReadValuesModifiedTests GetTests() { return new HistoryReadValuesModifiedTests(_server, _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly PublisherModuleMqttv311Fixture _module; [Fact] public Task HistoryReadInt16ValuesModifiedTestAsync() { return GetTests().HistoryReadInt16ValuesModifiedTestAsync(Ct); } [SkippableFact] public Task HistoryStreamInt16ValuesModifiedTestAsync() { Skip.If(true, "Not yet supported"); return GetTests().HistoryStreamInt16ValuesModifiedTestAsync(Ct); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/HistoricalAccess/ReadProcessedTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.HistoricalAccess { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class ReadProcessedTests : TwinIntegrationTestBase, IClassFixture { public ReadProcessedTests(HistoricalAccessServer server, PublisherModuleMqttv5Fixture module, ITestOutputHelper output) : base(output) { _server = server; _module = module; } private HistoryReadValuesProcessedTests GetTests() { return new HistoryReadValuesProcessedTests(_server, _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly PublisherModuleMqttv5Fixture _module; [Fact] public Task HistoryReadUInt64ProcessedValuesTest1Async() { return GetTests().HistoryReadUInt64ProcessedValuesTest1Async(Ct); } [Fact] public Task HistoryReadUInt64ProcessedValuesTest2Async() { return GetTests().HistoryReadUInt64ProcessedValuesTest2Async(Ct); } [SkippableFact] public Task HistoryReadUInt64ProcessedValuesTest3Async() { Skip.If(true, "Not yet supported"); return GetTests().HistoryReadUInt64ProcessedValuesTest3Async(Ct); } [SkippableFact] public Task HistoryStreamUInt64ProcessedValuesTest1Async() { Skip.If(true, "Not yet supported"); return GetTests().HistoryStreamUInt64ProcessedValuesTest1Async(Ct); } [SkippableFact] public Task HistoryStreamUInt64ProcessedValuesTest2Async() { Skip.If(true, "Not yet supported"); return GetTests().HistoryStreamUInt64ProcessedValuesTest2Async(Ct); } [SkippableFact] public Task HistoryStreamUInt64ProcessedValuesTest3Async() { Skip.If(true, "Not yet supported"); return GetTests().HistoryStreamUInt64ProcessedValuesTest3Async(Ct); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/HistoricalAccess/ReadValuesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.HistoricalAccess { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class ReadValuesTests : TwinIntegrationTestBase, IClassFixture { public ReadValuesTests(HistoricalAccessServer server, PublisherModuleMqttv5Fixture module, ITestOutputHelper output) : base(output) { _server = server; _module = module; } private HistoryReadValuesTests GetTests() { return new HistoryReadValuesTests(_server, _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly PublisherModuleMqttv5Fixture _module; [Fact] public Task HistoryReadInt64ValuesTest1Async() { return GetTests().HistoryReadInt64ValuesTest1Async(Ct); } [Fact] public Task HistoryReadInt64ValuesTest2Async() { return GetTests().HistoryReadInt64ValuesTest2Async(Ct); } [Fact] public Task HistoryReadInt64ValuesTest3Async() { return GetTests().HistoryReadInt64ValuesTest3Async(Ct); } [Fact] public Task HistoryReadInt64ValuesTest4Async() { return GetTests().HistoryReadInt64ValuesTest4Async(Ct); } [SkippableFact] public Task HistoryStreamInt64ValuesTest1Async() { Skip.If(true, "Not yet supported"); return GetTests().HistoryStreamInt64ValuesTest1Async(Ct); } [SkippableFact] public Task HistoryStreamInt64ValuesTest2Async() { Skip.If(true, "Not yet supported"); return GetTests().HistoryStreamInt64ValuesTest2Async(Ct); } [SkippableFact] public Task HistoryStreamInt64ValuesTest3Async() { Skip.If(true, "Not yet supported"); return GetTests().HistoryStreamInt64ValuesTest3Async(Ct); } [SkippableFact] public Task HistoryStreamInt64ValuesTest4Async() { Skip.If(true, "Not yet supported"); return GetTests().HistoryStreamInt64ValuesTest4Async(Ct); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/HistoricalAccess/UpdateValuesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.HistoricalAccess { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class UpdateValuesTests : TwinIntegrationTestBase, IClassFixture { public UpdateValuesTests(HistoricalAccessServer server, PublisherModuleMqttv5Fixture module, ITestOutputHelper output) : base(output) { _server = server; _module = module; } private HistoryUpdateValuesTests GetTests() { return new HistoryUpdateValuesTests( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly PublisherModuleMqttv5Fixture _module; [Fact] public Task HistoryUpsertUInt32ValuesTest1Async() { return GetTests().HistoryUpsertUInt32ValuesTest1Async(Ct); } [Fact] public Task HistoryUpsertUInt32ValuesTest2Async() { return GetTests().HistoryUpsertUInt32ValuesTest2Async(Ct); } [Fact] public Task HistoryInsertUInt32ValuesTest1Async() { return GetTests().HistoryInsertUInt32ValuesTest1Async(Ct); } [Fact] public Task HistoryInsertUInt32ValuesTest2Async() { return GetTests().HistoryInsertUInt32ValuesTest2Async(Ct); } [Fact] public Task HistoryReplaceUInt32ValuesTest1Async() { return GetTests().HistoryReplaceUInt32ValuesTest1Async(Ct); } [Fact] public Task HistoryReplaceUInt32ValuesTest2Async() { return GetTests().HistoryReplaceUInt32ValuesTest2Async(Ct); } [Fact] public Task HistoryInsertDeleteUInt32ValuesTest1Async() { return GetTests().HistoryInsertDeleteUInt32ValuesTest1Async(Ct); } [Fact] public Task HistoryInsertDeleteUInt32ValuesTest2Async() { return GetTests().HistoryInsertDeleteUInt32ValuesTest2Async(Ct); } [Fact] public Task HistoryInsertDeleteUInt32ValuesTest3Async() { return GetTests().HistoryInsertDeleteUInt32ValuesTest3Async(Ct); } [Fact] public Task HistoryInsertDeleteUInt32ValuesTest4Async() { return GetTests().HistoryInsertDeleteUInt32ValuesTest4Async(Ct); } [Fact] public Task HistoryDeleteUInt32ValuesTest1Async() { return GetTests().HistoryDeleteUInt32ValuesTest1Async(Ct); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/HistoricalEvents/NodeServicesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.HistoricalEvents { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class NodeServicesTests : TwinIntegrationTestBase, IClassFixture { public NodeServicesTests(HistoricalEventsServer server, PublisherModuleMqttv5Fixture module, ITestOutputHelper output) : base(output) { _server = server; _module = module; } private NodeHistoricalEventsTests GetTests() { return new NodeHistoricalEventsTests( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly HistoricalEventsServer _server; private readonly PublisherModuleMqttv5Fixture _module; [Fact] public Task GetServerCapabilitiesTestAsync() { return GetTests().GetServerCapabilitiesTestAsync(Ct); } [Fact] public Task HistoryGetServerCapabilitiesTestAsync() { return GetTests().HistoryGetServerCapabilitiesTestAsync(Ct); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/HistoricalEvents/ReadCollection.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.HistoricalEvents { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name, DisableParallelization = true)] public class ReadCollection : ICollectionFixture { public const string Name = "HistoricalEventsServerReadModuleMqtt"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/Plc/NodeServicesTests1.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.Plc { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class NodeServicesTests1 : TwinIntegrationTestBase, IClassFixture, IClassFixture { public NodeServicesTests1(PlcServer server, PublisherModuleMqttv5Fixture module, ITestOutputHelper output) : base(output) { _server = server; _module = module; } private SimulatorNodesTests GetTests() { return new SimulatorNodesTests(_server, _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly PlcServer _server; private readonly PublisherModuleMqttv5Fixture _module; [Fact] public Task AlternatingBooleanTelemetryChangesWithPeriodAsync() { return GetTests().AlternatingBooleanTelemetryChangesWithPeriodAsync(Ct); } [Fact] public Task BadNodeHasAlternatingStatusCodeAsync() { return GetTests().BadNodeHasAlternatingStatusCodeAsync(Ct); } [Fact] public Task FastLimitNumberOfUpdatesStopsUpdatingAfterLimitAsync() { return GetTests().FastLimitNumberOfUpdatesStopsUpdatingAfterLimitAsync(Ct); } [Fact] public Task FastUIntScalar1TelemetryChangesWithPeriodAsync() { return GetTests().FastUIntScalar1TelemetryChangesWithPeriodAsync(Ct); } [Fact] public Task NegativeTrendDataNodeHasValueWithTrendAsync() { return GetTests().NegativeTrendDataNodeHasValueWithTrendAsync(Ct); } [Fact] public Task NegativeTrendDataTelemetryChangesWithPeriodAsync() { return GetTests().NegativeTrendDataTelemetryChangesWithPeriodAsync(Ct); } [Fact] public Task PositiveTrendDataNodeHasValueWithTrendAsync() { return GetTests().PositiveTrendDataNodeHasValueWithTrendAsync(Ct); } [Fact] public Task PositiveTrendDataTelemetryChangesWithPeriodAsync() { return GetTests().PositiveTrendDataTelemetryChangesWithPeriodAsync(Ct); } [Fact] public Task RandomSignedInt32TelemetryChangesWithPeriodAsync() { return GetTests().RandomSignedInt32TelemetryChangesWithPeriodAsync(Ct); } [Fact] public Task RandomUnsignedInt32TelemetryChangesWithPeriodAsync() { return GetTests().RandomUnsignedInt32TelemetryChangesWithPeriodAsync(Ct); } [Fact] public Task SlowLimitNumberOfUpdatesStopsUpdatingAfterLimitAsync() { return GetTests().SlowLimitNumberOfUpdatesStopsUpdatingAfterLimitAsync(Ct); } [Fact] public Task SlowUIntScalar1TelemetryChangesWithPeriodAsync() { return GetTests().SlowUIntScalar1TelemetryChangesWithPeriodAsync(Ct); } [Fact] public Task TelemetryContainsOutlierInDipDataAsync() { return GetTests().TelemetryContainsOutlierInDipDataAsync(Ct); } [Fact] public Task TelemetryContainsOutlierInSpikeDataAsync() { return GetTests().TelemetryContainsOutlierInSpikeDataAsync(Ct); } [Fact] public Task TelemetryFastNodeTestAsync() { return GetTests().TelemetryFastNodeTestAsync(Ct); } [Fact] public Task TelemetryStepUpTestAsync() { return GetTests().TelemetryStepUpTestAsync(Ct); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/Plc/NodeServicesTests2.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.Plc { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class NodeServicesTests2 : TwinIntegrationTestBase, IClassFixture { public NodeServicesTests2(PlcServer server, ITestOutputHelper output) : base(output) { _server = server; _module = new PublisherModule(null, testOutputHelper: output, version: Furly.Extensions.Mqtt.MqttVersion.v5); } private PlcModelComplexTypeTests GetTests() { return new PlcModelComplexTypeTests(_server, _module.ClientContainer.Resolve>, _server.GetConnection()); } protected override void Dispose(bool disposing) { if (disposing) { _module.Dispose(); } base.Dispose(disposing); } private readonly PlcServer _server; private readonly PublisherModule _module; [Fact] public Task PlcModelHeaterTestsAsync() { return GetTests().PlcModelHeaterTestsAsync(Ct); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/ReferenceServer/MqttConfigurationIntegrationTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.ReferenceServer { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Furly.Extensions.Mqtt; using Json.More; using System; using System.Collections.Generic; using System.Text.Json; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public class MqttConfigurationIntegrationTests : PublisherIntegrationTestBase { private readonly ITestOutputHelper _output; private readonly ReferenceServer _fixture; public MqttConfigurationIntegrationTests(ITestOutputHelper output) : base(output) { _output = output; _fixture = new ReferenceServer(); EndpointUrl = _fixture.EndpointUrl; } protected override void Dispose(bool disposing) { base.Dispose(disposing); if (disposing) { _fixture.Dispose(); } } [Theory] [InlineData(true)] [InlineData(false)] public async Task CanSendDataItemToTopicConfiguredWithMethodAsync(bool useMqtt5) { var name = nameof(CanSendDataItemToTopicConfiguredWithMethodAsync) + (useMqtt5 ? "v5" : "v311"); var testInput = GetEndpointsFromFile(name, "./Resources/DataItems.json"); StartPublisher(name, arguments: ["--mm=FullSamples"], // Alternative to --fm=True version: useMqtt5 ? MqttVersion.v5 : MqttVersion.v311); try { var endpoints = await PublisherApi.GetConfiguredEndpointsAsync(ct: Ct); Assert.Empty(endpoints.Endpoints); var result = await PublisherApi.PublishNodesAsync(testInput[0], Ct); Assert.NotNull(result); var messages = await WaitForMessagesAsync(); var message = Assert.Single(messages); Assert.Equal("ns=23;i=1259", message.Message.GetProperty("NodeId").GetString()); Assert.InRange(message.Message.GetProperty("Value").GetProperty("Value").GetDouble(), double.MinValue, double.MaxValue); endpoints = await PublisherApi.GetConfiguredEndpointsAsync(ct: Ct); var e = Assert.Single(endpoints.Endpoints); var nodes = await PublisherApi.GetConfiguredNodesOnEndpointAsync(e, Ct); var n = Assert.Single(nodes.OpcNodes); Assert.Equal(testInput[0].OpcNodes[0].Id, n.Id); result = await PublisherApi.UnpublishNodesAsync(e, Ct); Assert.NotNull(result); endpoints = await PublisherApi.GetConfiguredEndpointsAsync(ct: Ct); Assert.Empty(endpoints.Endpoints); } finally { await StopPublisherAsync(); } } [Theory] [InlineData(true)] [InlineData(false)] public async Task CanSendEventToTopicConfiguredWithMethodAsync(bool useMqtt5) { var name = nameof(CanSendEventToTopicConfiguredWithMethodAsync) + (useMqtt5 ? "v5" : "v311"); var testInput = GetEndpointsFromFile(name, "./Resources/SimpleEvents.json"); StartPublisher(name, version: useMqtt5 ? MqttVersion.v5 : MqttVersion.v311); try { var endpoints = await PublisherApi.GetConfiguredEndpointsAsync(ct: Ct); Assert.Empty(endpoints.Endpoints); var result = await PublisherApi.PublishNodesAsync(testInput[0], Ct); Assert.NotNull(result); var messages = await WaitForMessagesAsync(); var message = Assert.Single(messages); Assert.Equal("i=2253", message.Message.GetProperty("NodeId").GetString()); Assert.NotEmpty(message.Message.GetProperty("Value").GetProperty("EventId").GetString()); endpoints = await PublisherApi.GetConfiguredEndpointsAsync(ct: Ct); var e = Assert.Single(endpoints.Endpoints); var nodes = await PublisherApi.GetConfiguredNodesOnEndpointAsync(e, Ct); var n = Assert.Single(nodes.OpcNodes); Assert.Equal(testInput[0].OpcNodes[0].Id, n.Id); _output.WriteLine("Unpublishing nodes..."); result = await PublisherApi.UnpublishAllNodesAsync(ct: Ct); Assert.NotNull(result); _output.WriteLine("Checking endpoints..."); endpoints = await PublisherApi.GetConfiguredEndpointsAsync(ct: Ct); Assert.Empty(endpoints.Endpoints); } finally { _output.WriteLine("Stopping publisher..."); await StopPublisherAsync(); } } [Theory] [InlineData(true)] [InlineData(false)] public async Task CanSendPendingConditionsToTopicConfiguredWithMethodAsync(bool useMqtt5) { var name = nameof(CanSendPendingConditionsToTopicConfiguredWithMethodAsync) + (useMqtt5 ? "v5" : "v311"); var testInput = GetEndpointsFromFile(name, "./Resources/PendingAlarms.json"); StartPublisher(name, version: useMqtt5 ? MqttVersion.v5 : MqttVersion.v311); try { var endpoints = await PublisherApi.GetConfiguredEndpointsAsync(ct: Ct); Assert.Empty(endpoints.Endpoints); var result = await PublisherApi.PublishNodesAsync(testInput[0], Ct); Assert.NotNull(result); var messages = await WaitForMessagesAsync(GetAlarmCondition); messages.ForEach(m => _output.WriteLine(m.Topic + m.Message.ToJsonString())); var evt = Assert.Single(messages).Message; Assert.Equal(JsonValueKind.Object, evt.ValueKind); Assert.Equal("i=2253", evt.GetProperty("NodeId").GetString()); Assert.Equal("PendingAlarms", evt.GetProperty("DisplayName").GetString()); Assert.True(evt.TryGetProperty("Value", out var sev)); Assert.True(sev.TryGetProperty("Severity", out sev)); Assert.True(sev.TryGetProperty("Value", out sev)); Assert.True(sev.GetInt32() >= 100); _output.WriteLine("GetConfigured 1"); endpoints = await PublisherApi.GetConfiguredEndpointsAsync(ct: Ct); var e = Assert.Single(endpoints.Endpoints); var nodes = await PublisherApi.GetConfiguredNodesOnEndpointAsync(e, Ct); var n = Assert.Single(nodes.OpcNodes); Assert.Equal(testInput[0].OpcNodes[0].Id, n.Id); _output.WriteLine("Unpublish"); result = await PublisherApi.UnpublishNodesAsync(testInput[0], Ct); Assert.NotNull(result); _output.WriteLine("GetConfigured 2"); endpoints = await PublisherApi.GetConfiguredEndpointsAsync(ct: Ct); Assert.Empty(endpoints.Endpoints); } finally { await StopPublisherAsync(); } } [Theory] [InlineData(true)] [InlineData(false)] public async Task CanSendDataItemToTopicConfiguredWithMethod2Async(bool useMqtt5) { var name = nameof(CanSendDataItemToTopicConfiguredWithMethod2Async) + (useMqtt5 ? "v5" : "v311"); var testInput1 = GetEndpointsFromFile(name, "./Resources/DataItems.json"); var testInput2 = GetEndpointsFromFile(name, "./Resources/SimpleEvents.json"); var testInput3 = GetEndpointsFromFile(name, "./Resources/PendingAlarms.json"); StartPublisher(name, version: useMqtt5 ? MqttVersion.v5 : MqttVersion.v311); try { var endpoints = await PublisherApi.GetConfiguredEndpointsAsync(ct: Ct); Assert.Empty(endpoints.Endpoints); _output.WriteLine("Publishing 1"); await PublisherApi.PublishNodesAsync(testInput1[0], Ct); _output.WriteLine("Publishing 2"); await PublisherApi.PublishNodesAsync(testInput2[0], Ct); _output.WriteLine("Publishing 3"); await PublisherApi.PublishNodesAsync(testInput3[0], Ct); _output.WriteLine("Checking endpoints..."); endpoints = await PublisherApi.GetConfiguredEndpointsAsync(ct: Ct); var e = Assert.Single(endpoints.Endpoints); var nodes = await PublisherApi.GetConfiguredNodesOnEndpointAsync(e, Ct); Assert.Equal(3, nodes.OpcNodes.Count); _output.WriteLine("Unpublishing all..."); await PublisherApi.UnpublishAllNodesAsync(ct: Ct); endpoints = await PublisherApi.GetConfiguredEndpointsAsync(); Assert.Empty(endpoints.Endpoints); _output.WriteLine("Re-adding with AddOrUpdate..."); await PublisherApi.AddOrUpdateEndpointsAsync(new List { new() { OpcNodes = [.. nodes.OpcNodes], EndpointUrl = e.EndpointUrl, UseSecurity = e.UseSecurity, DataSetWriterGroup = name } }, Ct); _output.WriteLine("Checking endpoints..."); endpoints = await PublisherApi.GetConfiguredEndpointsAsync(ct: Ct); e = Assert.Single(endpoints.Endpoints); nodes = await PublisherApi.GetConfiguredNodesOnEndpointAsync(e, Ct); Assert.Equal(3, nodes.OpcNodes.Count); _output.WriteLine("Removing items..."); await PublisherApi.UnpublishNodesAsync(testInput3[0], Ct); nodes = await PublisherApi.GetConfiguredNodesOnEndpointAsync(e, Ct); Assert.Equal(2, nodes.OpcNodes.Count); await PublisherApi.UnpublishNodesAsync(testInput2[0], Ct); nodes = await PublisherApi.GetConfiguredNodesOnEndpointAsync(e, Ct); Assert.Single(nodes.OpcNodes); _output.WriteLine("Waiting for remaining..."); var messages = await WaitForMessagesAsync(GetDataFrame); var message = Assert.Single(messages); Assert.Equal("ns=23;i=1259", message.Message.GetProperty("NodeId").GetString()); Assert.InRange(message.Message.GetProperty("Value").GetProperty("Value").GetDouble(), double.MinValue, double.MaxValue); var diagnostics = await PublisherApi.GetDiagnosticInfoAsync(Ct); var diag = Assert.Single(diagnostics); Assert.Equal(e.EndpointUrl, diag.Endpoint.EndpointUrl); } finally { await StopPublisherAsync(); } } [Theory] [InlineData(true)] [InlineData(false)] public async Task CanSendPendingConditionsToTopicConfiguredWithMethod2Async(bool useMqtt5) { var name = nameof(CanSendPendingConditionsToTopicConfiguredWithMethod2Async) + (useMqtt5 ? "v5" : "v311"); var testInput = GetEndpointsFromFile(name, "./Resources/PendingAlarms.json"); StartPublisher(name, version: useMqtt5 ? MqttVersion.v5 : MqttVersion.v311); try { var endpoints = await PublisherApi.GetConfiguredEndpointsAsync(ct: Ct); Assert.Empty(endpoints.Endpoints); var result = await PublisherApi.PublishNodesAsync(testInput[0], Ct); Assert.NotNull(result); var messages = await WaitForMessagesAsync(GetAlarmCondition); messages.ForEach(m => _output.WriteLine(m.Topic + m.Message.ToJsonString())); var evt = Assert.Single(messages).Message; Assert.Equal(JsonValueKind.Object, evt.ValueKind); Assert.Equal("i=2253", evt.GetProperty("NodeId").GetString()); Assert.Equal("PendingAlarms", evt.GetProperty("DisplayName").GetString()); Assert.True(evt.TryGetProperty("Value", out var sev)); Assert.True(sev.TryGetProperty("Severity", out sev)); Assert.True(sev.TryGetProperty("Value", out sev)); Assert.True(sev.GetInt32() >= 100); // Disable pending alarms testInput[0].OpcNodes[0].ConditionHandling = null; testInput[0].OpcNodes[0].DisplayName = "SimpleEvents"; result = await PublisherApi.AddOrUpdateEndpointsAsync( new List { testInput[0] }, Ct); Assert.NotNull(result); endpoints = await PublisherApi.GetConfiguredEndpointsAsync(ct: Ct); var e = Assert.Single(endpoints.Endpoints); var nodes = await PublisherApi.GetConfiguredNodesOnEndpointAsync(e, Ct); var n = Assert.Single(nodes.OpcNodes); // TODO: Fix if (n != null) return; // Wait until it was applied and we receive normal events again messages = await WaitForMessagesAsync( message => message.GetProperty("DisplayName").GetString() == "SimpleEvents" && message.GetProperty("Value").GetProperty("ReceiveTime").ValueKind == JsonValueKind.String ? message : default); messages.ForEach(m => _output.WriteLine(m.Topic + m.Message.ToJsonString())); var message = Assert.Single(messages); Assert.Equal("i=2253", message.Message.GetProperty("NodeId").GetString()); Assert.Equal("SimpleEvents", message.Message.GetProperty("DisplayName").GetString()); Assert.True(message.Message.TryGetProperty("Value", out sev)); Assert.True(sev.TryGetProperty("Severity", out sev)); Assert.True(sev.GetInt32() > 0, $"{message.Message.ToJsonString()}"); result = await PublisherApi.UnpublishNodesAsync(testInput[0], Ct); Assert.NotNull(result); endpoints = await PublisherApi.GetConfiguredEndpointsAsync(ct: Ct); Assert.Empty(endpoints.Endpoints); } finally { await StopPublisherAsync(); } } private JsonElement GetDataFrame(JsonElement jsonElement) { return jsonElement.GetProperty("NodeId").GetString() != "i=2253" ? jsonElement : default; } private static JsonElement GetAlarmCondition(JsonElement jsonElement) { return jsonElement .TryGetProperty("Value", out var node) && node .TryGetProperty("SourceNode", out node) && node .TryGetProperty("Value", out node) && node .GetString().StartsWith("http://opcfoundation.org/AlarmCondition#s=1%3a", StringComparison.InvariantCulture) ? jsonElement : default; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/ReferenceServer/MqttPubSubIntegrationTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.ReferenceServer { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.ReferenceServer; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Furly.Extensions.Mqtt; using Json.More; using System; using System.Linq; using System.Text.Json; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public class MqttPubSubIntegrationTests : PublisherIntegrationTestBase { private readonly ReferenceServer _fixture; private readonly ITestOutputHelper _output; public MqttPubSubIntegrationTests(ITestOutputHelper output) : base(output) { _output = output; _fixture = new ReferenceServer(); EndpointUrl = _fixture.EndpointUrl; } protected override void Dispose(bool disposing) { base.Dispose(disposing); if (disposing) { _fixture.Dispose(); } } [Fact] public async Task CanSendDataItemToMqttBrokerTestAsync() { // Arrange // Act var (metadata, messages) = await ProcessMessagesAndMetadataAsync( nameof(CanSendDataItemToMqttBrokerTestAsync), "./Resources/DataItems.json", messageType: "ua-data", arguments: ["--mm=PubSub", "--mdt={TelemetryTopic}/metadatamessage", "--dm=False"], version: MqttVersion.v311); // Assert var message = Assert.Single(messages); var output = message.Message.GetProperty("Messages")[0].GetProperty("Payload").GetProperty("Output"); Assert.NotEqual(JsonValueKind.Null, output.ValueKind); Assert.InRange(output.GetProperty("Value").GetDouble(), double.MinValue, double.MaxValue); Assert.NotNull(metadata); Assert.EndsWith("/metadatamessage", metadata.Value.Topic, StringComparison.Ordinal); } [Fact] public async Task CanSendDataItemButNotMetaDataWhenMetaDataIsDisabledTestAsync() { // Arrange // Act var (metadata, messages) = await ProcessMessagesAndMetadataAsync( nameof(CanSendDataItemButNotMetaDataWhenMetaDataIsDisabledTestAsync), "./Resources/DataItems.json", arguments: ["--dm", "--mm=DataSetMessages"], version: MqttVersion.v5); // Assert var message = Assert.Single(messages); var output = message.Message.GetProperty("Payload").GetProperty("Output"); Assert.NotEqual(JsonValueKind.Null, output.ValueKind); Assert.InRange(output.GetProperty("Value").GetDouble(), double.MinValue, double.MaxValue); Assert.Null(metadata); } [Fact] public async Task CanSendDataItemAsDataSetMessagesToMqttBrokerWithCompliantEncodingTestAsync() { // Arrange // Act var (metadata, messages) = await ProcessMessagesAndMetadataAsync( nameof(CanSendDataItemAsDataSetMessagesToMqttBrokerWithCompliantEncodingTestAsync), "./Resources/DataItems.json", messageType: "ua-deltaframe", arguments: ["-c", "--mm=DataSetMessages"], version: MqttVersion.v311); // Assert var message = Assert.Single(messages); var output = message.Message.GetProperty("Payload").GetProperty("Output"); Assert.NotEqual(JsonValueKind.Null, output.ValueKind); Assert.InRange(output.GetProperty("Value").GetDouble(), double.MinValue, double.MaxValue); Assert.NotNull(metadata); } [Fact] public async Task CanSendDataItemAsRawDataSetsToMqttBrokerWithCompliantEncodingTestAsync() { // Arrange // Act var (metadata, messages) = await ProcessMessagesAndMetadataAsync( nameof(CanSendDataItemAsRawDataSetsToMqttBrokerWithCompliantEncodingTestAsync), "./Resources/DataItems.json", messageType: "ua-deltaframe", arguments: ["-c", "--dm=False", "--mm=RawDataSets", "--mdt"], version: MqttVersion.v5); // Assert var output = Assert.Single(messages); Assert.NotEqual(JsonValueKind.Null, output.Message.ValueKind); Assert.InRange(output.Message.GetProperty("Output").GetDouble(), double.MinValue, double.MaxValue); // Explicitely enabled metadata despite messaging profile Assert.NotNull(metadata); Assert.EndsWith("/metadata", metadata.Value.Topic, StringComparison.Ordinal); } [Fact] public async Task CanEncodeWithoutReversibleEncodingTestAsync() { // Arrange // Act var (metadata, result) = await ProcessMessagesAndMetadataAsync(nameof(CanEncodeWithoutReversibleEncodingTestAsync), "./Resources/SimpleEvents.json", messageType: "ua-data", arguments: ["--mm=PubSub", "--me=Json", "--dm=false"], version: MqttVersion.v5); Assert.Single(result); var messages = result .SelectMany(x => x.Message.GetProperty("Messages").EnumerateArray()) .ToArray(); // Assert Assert.NotEmpty(messages); Assert.All(messages, m => { var value = m.GetProperty("Payload"); // Variant encoding is the default var eventId = value.GetProperty(BasicPubSubIntegrationTests.EventId).GetProperty("Value"); var message = value.GetProperty(BasicPubSubIntegrationTests.Message).GetProperty("Value"); var cycleId = value.GetProperty(BasicPubSubIntegrationTests.CycleIdUri).GetProperty("Value"); var currentStep = value.GetProperty(BasicPubSubIntegrationTests.CurrentStepUri).GetProperty("Value"); Assert.Equal(JsonValueKind.String, eventId.ValueKind); Assert.Equal(JsonValueKind.String, message.ValueKind); Assert.Equal(JsonValueKind.String, cycleId.ValueKind); Assert.Equal(JsonValueKind.String, currentStep.GetProperty("Name").ValueKind); Assert.Equal(JsonValueKind.Number, currentStep.GetProperty("Duration").ValueKind); }); Assert.NotNull(metadata); BasicPubSubIntegrationTests.AssertSimpleEventsMetadata(metadata.Value); } [Fact] public async Task CanEncodeWithReversibleEncodingTestAsync() { // Arrange // Act var (metadata, result) = await ProcessMessagesAndMetadataAsync(nameof(CanEncodeWithReversibleEncodingTestAsync), "./Resources/SimpleEvents.json", TimeSpan.FromMinutes(2), 4, messageType: "ua-data", arguments: ["--mm=PubSub", "--me=JsonReversible", "--dm=False"], version: MqttVersion.v311); var messages = result .SelectMany(x => x.Message.GetProperty("Messages").EnumerateArray()) .ToArray(); // Assert Assert.NotEmpty(messages); Assert.All(messages, m => { var body = m.GetProperty("Payload"); var eventId = body.GetProperty(BasicPubSubIntegrationTests.EventId).GetProperty("Value"); Assert.Equal("ByteString", eventId.GetProperty("Type").GetString()); Assert.Equal(JsonValueKind.String, eventId.GetProperty("Body").ValueKind); var message = body.GetProperty(BasicPubSubIntegrationTests.Message).GetProperty("Value"); Assert.Equal("LocalizedText", message.GetProperty("Type").GetString()); Assert.Equal(JsonValueKind.String, message.GetProperty("Body").GetProperty("Text").ValueKind); Assert.Equal("en-US", message.GetProperty("Body").GetProperty("Locale").GetString()); var cycleId = body.GetProperty(BasicPubSubIntegrationTests.CycleIdUri).GetProperty("Value"); Assert.Equal("String", cycleId.GetProperty("Type").GetString()); Assert.Equal(JsonValueKind.String, cycleId.GetProperty("Body").ValueKind); var currentStep = body.GetProperty(BasicPubSubIntegrationTests.CurrentStepUri).GetProperty("Value"); body = currentStep.GetProperty("Body"); Assert.Equal("ExtensionObject", currentStep.GetProperty("Type").GetString()); Assert.Equal("http://opcfoundation.org/SimpleEvents#i=183", body.GetProperty("TypeId").GetString()); Assert.Equal("Json", body.GetProperty("Encoding").GetString()); Assert.Equal(JsonValueKind.String, body.GetProperty("Body").GetProperty("Name").ValueKind); Assert.Equal(JsonValueKind.Number, body.GetProperty("Body").GetProperty("Duration").ValueKind); }); Assert.NotNull(metadata); BasicPubSubIntegrationTests.AssertSimpleEventsMetadata(metadata.Value); } [Fact] public async Task CanEncodeEventWithCompliantEncodingTestAsync() { // Arrange // Act var (metadata, result) = await ProcessMessagesAndMetadataAsync(nameof(CanEncodeEventWithCompliantEncodingTestAsync), "./Resources/SimpleEvents.json", messageType: "ua-data", arguments: ["-c", "--mm=PubSub", "--me=Json"], version: MqttVersion.v5); Assert.Single(result); var messages = result .SelectMany(x => x.Message.GetProperty("Messages").EnumerateArray()) .ToArray(); // Assert Assert.NotEmpty(messages); Assert.All(messages, m => { var value = m.GetProperty("Payload"); // Variant encoding is the default var eventId = value.GetProperty(BasicPubSubIntegrationTests.EventId).GetProperty("Value"); var message = value.GetProperty(BasicPubSubIntegrationTests.Message).GetProperty("Value"); var cycleId = value.GetProperty(BasicPubSubIntegrationTests.CycleIdExpanded).GetProperty("Value"); var currentStep = value.GetProperty(BasicPubSubIntegrationTests.CurrentStepExpanded).GetProperty("Value"); Assert.Equal(JsonValueKind.String, eventId.ValueKind); Assert.Equal(JsonValueKind.String, message.ValueKind); Assert.Equal(JsonValueKind.String, cycleId.ValueKind); Assert.Equal(JsonValueKind.String, currentStep.GetProperty("Name").ValueKind); Assert.Equal(JsonValueKind.Number, currentStep.GetProperty("Duration").ValueKind); }); Assert.NotNull(metadata); BasicPubSubIntegrationTests.AssertCompliantSimpleEventsMetadata(metadata.Value); } [Fact] public async Task CanEncodeWithReversibleEncodingAndWithCompliantEncodingTestAsync() { // Arrange // Act var (metadata, result) = await ProcessMessagesAndMetadataAsync(nameof(CanEncodeWithReversibleEncodingAndWithCompliantEncodingTestAsync), "./Resources/SimpleEvents.json", TimeSpan.FromMinutes(2), 4, messageType: "ua-data", arguments: ["-c", "--mm=PubSub", "--me=JsonReversible"], version: MqttVersion.v311); var messages = result .SelectMany(x => x.Message.GetProperty("Messages").EnumerateArray()) .ToArray(); // Assert Assert.NotEmpty(messages); Assert.All(messages, m => { var body = m.GetProperty("Payload"); var eventId = body.GetProperty(BasicPubSubIntegrationTests.EventId).GetProperty("Value"); Assert.Equal(15, eventId.GetProperty("Type").GetInt32()); Assert.Equal(JsonValueKind.String, eventId.GetProperty("Body").ValueKind); var message = body.GetProperty(BasicPubSubIntegrationTests.Message).GetProperty("Value"); Assert.Equal(21, message.GetProperty("Type").GetInt32()); Assert.Equal(JsonValueKind.String, message.GetProperty("Body").GetProperty("Text").ValueKind); Assert.Equal("en-US", message.GetProperty("Body").GetProperty("Locale").GetString()); var cycleId = body.GetProperty(BasicPubSubIntegrationTests.CycleIdExpanded).GetProperty("Value"); Assert.Equal(12, cycleId.GetProperty("Type").GetInt32()); Assert.Equal(JsonValueKind.String, cycleId.GetProperty("Body").ValueKind); var currentStep = body.GetProperty(BasicPubSubIntegrationTests.CurrentStepExpanded).GetProperty("Value"); body = currentStep.GetProperty("Body"); Assert.Equal(22, currentStep.GetProperty("Type").GetInt32()); Assert.Equal(183, body.GetProperty("TypeId").GetProperty("Id").GetInt32()); Assert.Equal(JsonValueKind.String, body.GetProperty("Body").GetProperty("Name").ValueKind); Assert.Equal(JsonValueKind.Number, body.GetProperty("Body").GetProperty("Duration").ValueKind); }); Assert.NotNull(metadata); BasicPubSubIntegrationTests.AssertCompliantSimpleEventsMetadata(metadata.Value); } [Fact] public async Task CanSendPendingConditionsToMqttBrokerTestAsync() { // Arrange // Act var (metadata, messages) = await ProcessMessagesAndMetadataAsync(nameof(CanSendPendingConditionsToMqttBrokerTestAsync), "./Resources/PendingAlarms.json", BasicPubSubIntegrationTests.GetAlarmCondition, messageType: "ua-data", arguments: ["--mm=PubSub", "--dm=False"], version: MqttVersion.v311); // Assert var message = Assert.Single(messages); _output.WriteLine(message.Topic + message.Message.ToJsonString()); Assert.Equal(JsonValueKind.Object, message.Message.ValueKind); Assert.True(message.Message.GetProperty("Payload").GetProperty("Severity").GetProperty("Value").GetInt32() >= 100); Assert.NotNull(metadata); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/ReferenceServer/MqttUnifiedNamespaceTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.ReferenceServer { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Furly.Extensions.Mqtt; using Json.More; using System; using System.Linq; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public class MqttUnifiedNamespaceTests : PublisherIntegrationTestBase { private readonly ReferenceServer _fixture; private readonly ITestOutputHelper _output; public MqttUnifiedNamespaceTests(ITestOutputHelper output) : base(output) { _output = output; _fixture = new ReferenceServer(); EndpointUrl = _fixture.EndpointUrl; } protected override void Dispose(bool disposing) { base.Dispose(disposing); if (disposing) { _fixture.Dispose(); } } [Fact] public async Task CanSendAddressSpaceDataToUnifiedNamespaceAsync() { // Arrange // Act var (metadata, messages) = await ProcessMessagesAndMetadataAsync( nameof(CanSendAddressSpaceDataToUnifiedNamespaceAsync), "./Resources/DataItems1.json", messageCollectionTimeout: TimeSpan.FromMinutes(1), messageCount: 10, arguments: ["--mm=SingleRawDataSet", "--uns=UseBrowseNamesWithNamespaceIndex"], version: MqttVersion.v5); // Assert Assert.NotEmpty(messages); var currentTimes = messages.Where(m => m.Topic .EndsWith(nameof(CanSendAddressSpaceDataToUnifiedNamespaceAsync) + "/Objects/Server/ServerStatus/CurrentTime", StringComparison.InvariantCulture)).ToList(); var outputs = messages.Where(m => m.Topic .EndsWith(nameof(CanSendAddressSpaceDataToUnifiedNamespaceAsync) + "/Objects/23:Boilers/23:Boiler \\x231/23:DrumX001/23:LIX001/23:Output", StringComparison.InvariantCulture)).ToList(); Assert.NotEmpty(currentTimes); Assert.NotEmpty(outputs); if (currentTimes.Count + outputs.Count != messages.Count) { messages.ForEach(m => _output.WriteLine(m.Topic + m.Message.ToJsonString())); } // TODO: Fix Assert.Equal(messages.Count, currentTimes.Count + outputs.Count); Assert.All(currentTimes, a => { Assert.True(a.Message.TryGetProperty("i=2258", out var dateTimeValue)); Assert.True(dateTimeValue.TryGetDateTime(out _)); }); Assert.All(outputs, a => { Assert.True(a.Message.TryGetProperty("ns=23;i=1259", out var doubleValue)); Assert.True(doubleValue.TryGetDouble(out _)); }); } [Fact] public async Task CanSendAddressSpaceDataToUnifiedNamespaceRawAsync() { // Arrange // Act var (metadata, messages) = await ProcessMessagesAndMetadataAsync( nameof(CanSendAddressSpaceDataToUnifiedNamespaceRawAsync), "./Resources/DataItems1.json", messageCollectionTimeout: TimeSpan.FromMinutes(1), messageCount: 10, arguments: ["--mm=SingleRawDataSet", "--uns=UseBrowseNames"], version: MqttVersion.v311); // Assert Assert.NotEmpty(messages); var currentTimes = messages.Where(m => m.Topic .EndsWith(nameof(CanSendAddressSpaceDataToUnifiedNamespaceRawAsync) + "/Objects/Server/ServerStatus/CurrentTime", StringComparison.InvariantCulture)).ToList(); var outputs = messages.Where(m => m.Topic .EndsWith(nameof(CanSendAddressSpaceDataToUnifiedNamespaceRawAsync) + "/Objects/Boilers/Boiler \\x231/DrumX001/LIX001/Output", StringComparison.InvariantCulture)).ToList(); Assert.NotEmpty(currentTimes); Assert.NotEmpty(outputs); if (currentTimes.Count + outputs.Count != messages.Count) { messages.ForEach(m => _output.WriteLine(m.Topic + m.Message.ToJsonString())); } // TODO: Fix Assert.Equal(messages.Count, currentTimes.Count + outputs.Count); Assert.All(currentTimes, a => { Assert.True(a.Message.TryGetProperty("i=2258", out var dateTimeValue)); Assert.True(dateTimeValue.TryGetDateTime(out _)); }); Assert.All(outputs, a => { Assert.True(a.Message.TryGetProperty("ns=23;i=1259", out var doubleValue)); Assert.True(doubleValue.TryGetDouble(out _)); }); } [Fact] public async Task CanSendAddressSpaceDataToUnifiedNamespacePerWriterWithRawDataSetsAsync() { // Arrange // Act var (metadata, messages) = await ProcessMessagesAndMetadataAsync( nameof(CanSendAddressSpaceDataToUnifiedNamespacePerWriterWithRawDataSetsAsync), "./Resources/UnifiedNamespace.json", messageCollectionTimeout: TimeSpan.FromMinutes(1), messageCount: 10, version: MqttVersion.v5); // Assert Assert.NotEmpty(messages); var currentTimes = messages.Where(m => m.Topic .EndsWith(nameof(CanSendAddressSpaceDataToUnifiedNamespacePerWriterWithRawDataSetsAsync) + "/Objects/Server/ServerStatus/CurrentTime", StringComparison.InvariantCulture)).ToList(); var outputs = messages.Where(m => m.Topic .EndsWith(nameof(CanSendAddressSpaceDataToUnifiedNamespacePerWriterWithRawDataSetsAsync) + "/Objects/Boilers/Boiler \\x231/DrumX001/LIX001/Output", StringComparison.InvariantCulture)).ToList(); Assert.NotEmpty(currentTimes); Assert.NotEmpty(outputs); if (currentTimes.Count + outputs.Count != messages.Count) { messages.ForEach(m => _output.WriteLine(m.Topic + m.Message.ToJsonString())); } // TODO: Fix Assert.Equal(messages.Count, currentTimes.Count + outputs.Count); Assert.All(currentTimes, a => { Assert.True(a.Message.TryGetProperty("i=2258", out var dateTimeValue)); Assert.True(dateTimeValue.TryGetDateTime(out _)); }); Assert.All(outputs, a => { Assert.True(a.Message.TryGetProperty("ns=23;i=1259", out var doubleValue)); Assert.True(doubleValue.TryGetDouble(out _)); }); } [Fact] public async Task CanSendModelChangeEventsToUnifiedNamespaceAsync() { // TODO: Fix await Task.Delay(1); return; // TODO FIX #if FALSE // Arrange // Act var (metadata, messages) = await ProcessMessagesAndMetadataAsync( nameof(CanSendModelChangeEventsToUnifiedNamespace), "./Resources/ModelChanges.json", messageCollectionTimeout: TimeSpan.FromMinutes(1), messageCount: 10, arguments: new[] { "--mm=SingleRawDataSet", "--uns=UseBrowseNamesWithNamespaceIndex" }, version: MqttVersion.v5); // Assert Assert.NotEmpty(messages); var payload1 = messages[0].Message; _output.WriteLine(payload1.ToJsonString()); Assert.NotEqual(JsonValueKind.Null, payload1.ValueKind); Assert.True(Guid.TryParse(payload1.GetProperty("EventId").GetString(), out _)); Assert.Equal("http://www.microsoft.com/opc-publisher#s=ReferenceChange", payload1.GetProperty("EventType").GetString()); Assert.Equal("i=84", payload1.GetProperty("SourceNode").GetString()); Assert.True(DateTime.TryParse(payload1.GetProperty("Time").GetString(), out _)); Assert.True(payload1.GetProperty("Change").GetProperty("IsForward").GetBoolean()); Assert.Equal("Objects", payload1.GetProperty("Change").GetProperty("DisplayName").GetString()); Assert.EndsWith("/messages/<>", messages[0].Topic, StringComparison.Ordinal); var payload2 = messages[1].Message; _output.WriteLine(payload2.ToJsonString()); Assert.NotEqual(JsonValueKind.Null, payload1.ValueKind); Assert.True(Guid.TryParse(payload2.GetProperty("EventId").GetString(), out _)); Assert.Equal("http://www.microsoft.com/opc-publisher#s=NodeChange", payload2.GetProperty("EventType").GetString()); Assert.Equal("i=85", payload2.GetProperty("SourceNode").GetString()); Assert.True(DateTime.TryParse(payload2.GetProperty("Time").GetString(), out _)); Assert.Equal("Objects", payload2.GetProperty("Change").GetProperty("DisplayName").GetString()); Assert.EndsWith("/messages/<>/Objects", messages[1].Topic, StringComparison.Ordinal); // TODO: currently metadata is sent later // Assert.NotNull(metadata); #endif } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/SimpleEvents/NodeServicesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.SimpleEvents { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public sealed class NodeServicesTests : TwinIntegrationTestBase, IClassFixture, IClassFixture { public NodeServicesTests(SimpleEventsServer server, PublisherModuleMqttv5Fixture module, ITestOutputHelper output) : base(output) { _server = server; _module = module; } private SimpleEventsServerTests GetTests() { return new SimpleEventsServerTests( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly SimpleEventsServer _server; private readonly PublisherModuleMqttv5Fixture _module; [Fact] public Task CompileSimpleBaseEventQueryTestAsync() { return GetTests().CompileSimpleBaseEventQueryTestAsync(); } [Fact] public Task CompileSimpleEventsQueryTestAsync() { return GetTests().CompileSimpleEventsQueryTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/TestData/BrowsePathTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.TestData { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class BrowsePathTests : TwinIntegrationTestBase, IClassFixture { public BrowsePathTests(TestDataServer server, PublisherModuleMqttv5Fixture module, ITestOutputHelper output) : base(output) { _server = server; _module = module; } private BrowsePathTests GetTests() { return new BrowsePathTests( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly TestDataServer _server; private readonly PublisherModuleMqttv5Fixture _module; [Fact] public Task NodeBrowsePathStaticScalarMethod3Test1Async() { return GetTests().NodeBrowsePathStaticScalarMethod3Test1Async(Ct); } [Fact] public Task NodeBrowsePathStaticScalarMethod3Test2Async() { return GetTests().NodeBrowsePathStaticScalarMethod3Test2Async(Ct); } [Fact] public Task NodeBrowsePathStaticScalarMethod3Test3Async() { return GetTests().NodeBrowsePathStaticScalarMethod3Test3Async(Ct); } [Fact] public Task NodeBrowsePathStaticScalarMethodsTestAsync() { return GetTests().NodeBrowsePathStaticScalarMethodsTestAsync(Ct); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/TestData/BrowseStreamTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.TestData { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public sealed class BrowseStreamTests : TwinIntegrationTestBase, IClassFixture { public BrowseStreamTests(TestDataServer server, PublisherModuleMqttv5Fixture module, ITestOutputHelper output) : base(output) { _server = server; _module = module; } private BrowseStreamTests GetTests() { return new BrowseStreamTests( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly TestDataServer _server; private readonly PublisherModuleMqttv5Fixture _module; [SkippableFact] public Task NodeBrowseInRootTest1Async() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseInRootTest1Async(Ct); } [SkippableFact] public Task NodeBrowseInRootTest2Async() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseInRootTest2Async(Ct); } [SkippableFact] public Task NodeBrowseBoilersObjectsTest1Async() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseBoilersObjectsTest1Async(Ct); } [SkippableFact] public Task NodeBrowseDataAccessObjectsTest1Async() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseDataAccessObjectsTest1Async(Ct); } [SkippableFact] public Task NodeBrowseStaticScalarVariablesTestAsync() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseStaticScalarVariablesTestAsync(Ct); } [SkippableFact] public Task NodeBrowseStaticArrayVariablesTestAsync() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseStaticArrayVariablesTestAsync(Ct); } [SkippableFact] public Task NodeBrowseStaticScalarVariablesTestWithFilter1Async() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter1Async(Ct); } [SkippableFact] public Task NodeBrowseStaticScalarVariablesTestWithFilter2Async() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter2Async(Ct); } [SkippableFact] public Task NodeBrowseStaticScalarVariablesTestWithFilter3Async() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter3Async(Ct); } [SkippableFact] public Task NodeBrowseStaticScalarVariablesTestWithFilter4Async() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter4Async(Ct); } [SkippableFact] public Task NodeBrowseStaticScalarVariablesTestWithFilter5Async() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter5Async(Ct); } [SkippableFact] public Task NodeBrowseDiagnosticsNoneTestAsync() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseDiagnosticsNoneTestAsync(Ct); } [SkippableFact] public Task NodeBrowseDiagnosticsStatusTestAsync() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseDiagnosticsStatusTestAsync(Ct); } [SkippableFact] public Task NodeBrowseDiagnosticsOperationsTestAsync() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseDiagnosticsInfoTestAsync(Ct); } [SkippableFact] public Task NodeBrowseDiagnosticsVerboseTestAsync() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseDiagnosticsVerboseTestAsync(Ct); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/TestData/BrowseTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.TestData { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class BrowseTests : TwinIntegrationTestBase, IClassFixture { public BrowseTests(TestDataServer server, PublisherModuleMqttv5Fixture module, ITestOutputHelper output) : base(output) { _server = server; _module = module; } private BrowseServicesTests GetTests() { return new BrowseServicesTests( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly TestDataServer _server; private readonly PublisherModuleMqttv5Fixture _module; [Fact] public Task NodeBrowseInRootTest1Async() { return GetTests().NodeBrowseInRootTest1Async(Ct); } [Fact] public Task NodeBrowseInRootTest2Async() { return GetTests().NodeBrowseInRootTest2Async(Ct); } [Fact] public Task NodeBrowseFirstInRootTest1Async() { return GetTests().NodeBrowseFirstInRootTest1Async(Ct); } [Fact] public Task NodeBrowseFirstInRootTest2Async() { return GetTests().NodeBrowseFirstInRootTest2Async(Ct); } [Fact] public Task NodeBrowseBoilersObjectsTest1Async() { return GetTests().NodeBrowseBoilersObjectsTest1Async(Ct); } [Fact] public Task NodeBrowseBoilersObjectsTest2Async() { return GetTests().NodeBrowseBoilersObjectsTest2Async(Ct); } [Fact] public Task NodeBrowseDataAccessObjectsTest1Async() { return GetTests().NodeBrowseDataAccessObjectsTest1Async(Ct); } [Fact] public Task NodeBrowseDataAccessObjectsTest2Async() { return GetTests().NodeBrowseDataAccessObjectsTest2Async(Ct); } [Fact] public Task NodeBrowseDataAccessObjectsTest3Async() { return GetTests().NodeBrowseDataAccessObjectsTest3Async(Ct); } [Fact] public Task NodeBrowseDataAccessObjectsTest4Async() { return GetTests().NodeBrowseDataAccessObjectsTest4Async(Ct); } [Fact] public Task NodeBrowseDataAccessFC1001Test1Async() { return GetTests().NodeBrowseDataAccessFC1001Test1Async(Ct); } [Fact] public Task NodeBrowseDataAccessFC1001Test2Async() { return GetTests().NodeBrowseDataAccessFC1001Test2Async(Ct); } [Fact] public Task NodeBrowseStaticScalarVariablesTestAsync() { return GetTests().NodeBrowseStaticScalarVariablesTestAsync(Ct); } [Fact] public Task NodeBrowseStaticArrayVariablesTestAsync() { return GetTests().NodeBrowseStaticArrayVariablesTestAsync(Ct); } [Fact] public Task NodeBrowseStaticScalarVariablesTestWithFilter1Async() { return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter1Async(Ct); } [Fact] public Task NodeBrowseStaticScalarVariablesTestWithFilter2Async() { return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter2Async(Ct); } [Fact] public Task NodeBrowseStaticArrayVariablesWithValuesTestAsync() { return GetTests().NodeBrowseStaticArrayVariablesWithValuesTestAsync(Ct); } [Fact] public Task NodeBrowseStaticArrayVariablesRawModeTestAsync() { return GetTests().NodeBrowseStaticArrayVariablesRawModeTestAsync(Ct); } [Fact] public Task NodeBrowseContinuationTest1Async() { return GetTests().NodeBrowseContinuationTest1Async(Ct); } [Fact] public Task NodeBrowseContinuationTest2Async() { return GetTests().NodeBrowseContinuationTest2Async(Ct); } [Fact] public Task NodeBrowseContinuationTest3Async() { return GetTests().NodeBrowseContinuationTest3Async(Ct); } [Fact] public Task NodeBrowseContinuationTest4Async() { return GetTests().NodeBrowseContinuationTest4Async(Ct); } [Fact] public Task NodeBrowseDiagnosticsNoneTestAsync() { return GetTests().NodeBrowseDiagnosticsNoneTestAsync(Ct); } [Fact] public Task NodeBrowseDiagnosticsStatusTestAsync() { return GetTests().NodeBrowseDiagnosticsStatusTestAsync(Ct); } [Fact] public Task NodeBrowseDiagnosticsInfoTestAsync() { return GetTests().NodeBrowseDiagnosticsInfoTestAsync(Ct); } [Fact] public Task NodeBrowseDiagnosticsVerboseTestAsync() { return GetTests().NodeBrowseDiagnosticsVerboseTestAsync(Ct); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/TestData/CallArrayTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.TestData { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection.Name)] public class CallArrayTests : TwinIntegrationTestBase, IClassFixture { public CallArrayTests(TestDataServer server, PublisherModuleMqttv5Fixture module, ITestOutputHelper output) : base(output) { _server = server; _module = module; } private CallArrayMethodTests GetTests() { return new CallArrayMethodTests( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly TestDataServer _server; private readonly PublisherModuleMqttv5Fixture _module; [Fact] public Task NodeMethodMetadataStaticArrayMethod1TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod1TestAsync(Ct); } [Fact] public Task NodeMethodMetadataStaticArrayMethod2TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod2TestAsync(Ct); } [Fact] public Task NodeMethodMetadataStaticArrayMethod3TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod3TestAsync(Ct); } [Fact] public Task NodeMethodCallStaticArrayMethod1Test1Async() { return GetTests().NodeMethodCallStaticArrayMethod1Test1Async(Ct); } [Fact] public Task NodeMethodCallStaticArrayMethod1Test2Async() { return GetTests().NodeMethodCallStaticArrayMethod1Test2Async(Ct); } [Fact] public Task NodeMethodCallStaticArrayMethod1Test3Async() { return GetTests().NodeMethodCallStaticArrayMethod1Test3Async(Ct); } [Fact] public Task NodeMethodCallStaticArrayMethod1Test4Async() { return GetTests().NodeMethodCallStaticArrayMethod1Test4Async(Ct); } [Fact] public Task NodeMethodCallStaticArrayMethod1Test5Async() { return GetTests().NodeMethodCallStaticArrayMethod1Test5Async(Ct); } [Fact] public Task NodeMethodCallStaticArrayMethod2Test1Async() { return GetTests().NodeMethodCallStaticArrayMethod2Test1Async(Ct); } [Fact] public Task NodeMethodCallStaticArrayMethod2Test2Async() { return GetTests().NodeMethodCallStaticArrayMethod2Test2Async(Ct); } [Fact] public Task NodeMethodCallStaticArrayMethod2Test3Async() { return GetTests().NodeMethodCallStaticArrayMethod2Test3Async(Ct); } [Fact] public Task NodeMethodCallStaticArrayMethod2Test4Async() { return GetTests().NodeMethodCallStaticArrayMethod2Test4Async(Ct); } [Fact] public Task NodeMethodCallStaticArrayMethod3Test1Async() { return GetTests().NodeMethodCallStaticArrayMethod3Test1Async(Ct); } [Fact] public Task NodeMethodCallStaticArrayMethod3Test2Async() { return GetTests().NodeMethodCallStaticArrayMethod3Test2Async(Ct); } [Fact] public Task NodeMethodCallStaticArrayMethod3Test3Async() { return GetTests().NodeMethodCallStaticArrayMethod3Test3Async(Ct); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/TestData/CallScalarTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.TestData { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection.Name)] public class CallScalarTests : TwinIntegrationTestBase, IClassFixture { public CallScalarTests(TestDataServer server, PublisherModuleMqttv311Fixture module, ITestOutputHelper output) : base(output) { _server = server; _module = module; } private CallScalarMethodTests GetTests() { return new CallScalarMethodTests( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly TestDataServer _server; private readonly PublisherModuleMqttv311Fixture _module; [Fact] public Task NodeMethodMetadataStaticScalarMethod1TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod1TestAsync(Ct); } [Fact] public Task NodeMethodMetadataStaticScalarMethod2TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod2TestAsync(Ct); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod3TestAsync(Ct); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest1Async() { return GetTests().NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest1Async(Ct); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest2Async() { return GetTests().NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest2Async(Ct); } [Fact] public Task NodeMethodCallStaticScalarMethod1Test1Async() { return GetTests().NodeMethodCallStaticScalarMethod1Test1Async(Ct); } [Fact] public Task NodeMethodCallStaticScalarMethod1Test2Async() { return GetTests().NodeMethodCallStaticScalarMethod1Test2Async(Ct); } [Fact] public Task NodeMethodCallStaticScalarMethod1Test3Async() { return GetTests().NodeMethodCallStaticScalarMethod1Test3Async(Ct); } [Fact] public Task NodeMethodCallStaticScalarMethod1Test4Async() { return GetTests().NodeMethodCallStaticScalarMethod1Test4Async(Ct); } [Fact] public Task NodeMethodCallStaticScalarMethod1Test5Async() { return GetTests().NodeMethodCallStaticScalarMethod1Test5Async(Ct); } [Fact] public Task NodeMethodCallStaticScalarMethod2Test1Async() { return GetTests().NodeMethodCallStaticScalarMethod2Test1Async(Ct); } [Fact] public Task NodeMethodCallStaticScalarMethod2Test2Async() { return GetTests().NodeMethodCallStaticScalarMethod2Test2Async(Ct); } [Fact] public Task NodeMethodCallStaticScalarMethod3Test1Async() { return GetTests().NodeMethodCallStaticScalarMethod3Test1Async(Ct); } [Fact] public Task NodeMethodCallStaticScalarMethod3Test2Async() { return GetTests().NodeMethodCallStaticScalarMethod3Test2Async(Ct); } [Fact] public Task NodeMethodCallStaticScalarMethod3WithBrowsePathNoIdsTestAsync() { return GetTests().NodeMethodCallStaticScalarMethod3WithBrowsePathNoIdsTestAsync(Ct); } [Fact] public Task NodeMethodCallStaticScalarMethod3WithObjectIdAndBrowsePathTestAsync() { return GetTests().NodeMethodCallStaticScalarMethod3WithObjectIdAndBrowsePathTestAsync(Ct); } [Fact] public Task NodeMethodCallStaticScalarMethod3WithObjectIdAndMethodIdAndBrowsePathTestAsync() { return GetTests().NodeMethodCallStaticScalarMethod3WithObjectIdAndMethodIdAndBrowsePathTestAsync(Ct); } [Fact] public Task NodeMethodCallStaticScalarMethod3WithObjectPathAndMethodIdAndBrowsePathTestAsync() { return GetTests().NodeMethodCallStaticScalarMethod3WithObjectPathAndMethodIdAndBrowsePathTestAsync(Ct); } [Fact] public Task NodeMethodCallStaticScalarMethod3WithObjectIdAndPathAndMethodIdAndPathTestAsync() { return GetTests().NodeMethodCallStaticScalarMethod3WithObjectIdAndPathAndMethodIdAndPathTestAsync(Ct); } [Fact] public Task NodeMethodCallBoiler2ResetTestAsync() { return GetTests().NodeMethodCallBoiler2ResetTestAsync(Ct); } [Fact] public Task NodeMethodCallBoiler1ResetTestAsync() { return GetTests().NodeMethodCallBoiler1ResetTestAsync(Ct); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/TestData/MetadataArrayTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.TestData { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class MetadataArrayTests : TwinIntegrationTestBase, IClassFixture { public MetadataArrayTests(TestDataServer server, PublisherModuleMqttv5Fixture module, ITestOutputHelper output) : base(output) { _server = server; _module = module; } private CallArrayMethodTests GetTests() { return new CallArrayMethodTests( _module.SdkContainer.Resolve>, _server.GetConnection(), newMetadata: true); } private readonly TestDataServer _server; private readonly PublisherModuleMqttv5Fixture _module; [Fact] public Task NodeMethodMetadataStaticArrayMethod1TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod1TestAsync(Ct); } [Fact] public Task NodeMethodMetadataStaticArrayMethod2TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod2TestAsync(Ct); } [Fact] public Task NodeMethodMetadataStaticArrayMethod3TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod3TestAsync(Ct); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/TestData/MetadataScalarTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.TestData { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class MetadataScalarTests : TwinIntegrationTestBase, IClassFixture { public MetadataScalarTests(TestDataServer server, PublisherModuleMqttv5Fixture module, ITestOutputHelper output) : base(output) { _server = server; _module = module; } private CallScalarMethodTests GetTests() { return new CallScalarMethodTests( _module.SdkContainer.Resolve>, _server.GetConnection(), newMetadata: true); } private readonly TestDataServer _server; private readonly PublisherModuleMqttv5Fixture _module; [Fact] public Task NodeMethodMetadataStaticScalarMethod1TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod1TestAsync(Ct); } [Fact] public Task NodeMethodMetadataStaticScalarMethod2TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod2TestAsync(Ct); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod3TestAsync(Ct); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest1Async() { return GetTests().NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest1Async(Ct); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest2Async() { return GetTests().NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest2Async(Ct); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/TestData/MetadataTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.TestData { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class MetadataTests : TwinIntegrationTestBase, IClassFixture { public MetadataTests(TestDataServer server, PublisherModuleMqttv5Fixture module, ITestOutputHelper output) : base(output) { _server = server; _module = module; } private NodeMetadataTests GetTests() { return new NodeMetadataTests( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly TestDataServer _server; private readonly PublisherModuleMqttv5Fixture _module; [Fact] public Task GetServerCapabilitiesTestAsync() { return GetTests().GetServerCapabilitiesTestAsync(Ct); } [Fact] public Task HistoryGetServerCapabilitiesTestAsync() { return GetTests().HistoryGetServerCapabilitiesTestAsync(Ct); } [Fact] public Task NodeGetMetadataForFolderTypeTestAsync() { return GetTests().NodeGetMetadataForFolderTypeTestAsync(Ct); } [Fact] public Task NodeGetMetadataForServerObjectTestAsync() { return GetTests().NodeGetMetadataForServerObjectTestAsync(Ct); } [Fact] public Task NodeGetMetadataForConditionTypeTestAsync() { return GetTests().NodeGetMetadataForConditionTypeTestAsync(Ct); } [Fact] public Task NodeGetMetadataTestForBaseEventTypeTestAsync() { return GetTests().NodeGetMetadataTestForBaseEventTypeTestAsync(Ct); } [Fact] public Task NodeGetMetadataForBaseInterfaceTypeTestAsync() { return GetTests().NodeGetMetadataForBaseInterfaceTypeTestAsync(Ct); } [Fact] public Task NodeGetMetadataForBaseDataVariableTypeTestAsync() { return GetTests().NodeGetMetadataForBaseDataVariableTypeTestAsync(Ct); } [Fact] public Task NodeGetMetadataForPropertyTypeTestAsync() { return GetTests().NodeGetMetadataForPropertyTypeTestAsync(Ct); } [Fact] public Task NodeGetMetadataForAudioVariableTypeTestAsync() { return GetTests().NodeGetMetadataForAudioVariableTypeTestAsync(Ct); } [Fact] public Task NodeGetMetadataForServerStatusVariableTestAsync() { return GetTests().NodeGetMetadataForServerStatusVariableTestAsync(Ct); } [Fact] public Task NodeGetMetadataForRedundancySupportPropertyTestAsync() { return GetTests().NodeGetMetadataForRedundancySupportPropertyTestAsync(Ct); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/TestData/ReadCollection.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.TestData { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name, DisableParallelization = true)] public class ReadCollection : ICollectionFixture { public const string Name = "TestDataServerReadModuleMqtt"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/TestData/ValueReadArrayTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.TestData { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class ValueReadArrayTests : TwinIntegrationTestBase, IClassFixture { public ValueReadArrayTests(TestDataServer server, PublisherModuleMqttv311Fixture module, ITestOutputHelper output) : base(output) { _server = server; _module = module; } private ReadArrayValueTests GetTests() { return new ReadArrayValueTests( _module.SdkContainer.Resolve>, _server.GetConnection(), (ep, n, s) => _server.Client.ReadValueAsync(new ConnectionModel { Endpoint = new EndpointModel { Url = ep.Endpoint.Url, Certificate = _server.Certificate?.RawData?.ToThumbprint() } }, n, s)); } private readonly TestDataServer _server; private readonly PublisherModuleMqttv311Fixture _module; [Fact] public Task NodeReadAllStaticArrayVariableNodeClassTest1Async() { return GetTests().NodeReadAllStaticArrayVariableNodeClassTest1Async(Ct); } [Fact] public Task NodeReadAllStaticArrayVariableAccessLevelTest1Async() { return GetTests().NodeReadAllStaticArrayVariableAccessLevelTest1Async(Ct); } [Fact] public Task NodeReadAllStaticArrayVariableWriteMaskTest1Async() { return GetTests().NodeReadAllStaticArrayVariableWriteMaskTest1Async(Ct); } [Fact] public Task NodeReadAllStaticArrayVariableWriteMaskTest2Async() { return GetTests().NodeReadAllStaticArrayVariableWriteMaskTest2Async(Ct); } [Fact] public Task NodeReadStaticArrayBooleanValueVariableTestAsync() { return GetTests().NodeReadStaticArrayBooleanValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArraySByteValueVariableTestAsync() { return GetTests().NodeReadStaticArraySByteValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArrayByteValueVariableTestAsync() { return GetTests().NodeReadStaticArrayByteValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArrayInt16ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayInt16ValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArrayUInt16ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayUInt16ValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArrayInt32ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayInt32ValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArrayUInt32ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayUInt32ValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArrayInt64ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayInt64ValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArrayUInt64ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayUInt64ValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArrayFloatValueVariableTestAsync() { return GetTests().NodeReadStaticArrayFloatValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArrayDoubleValueVariableTestAsync() { return GetTests().NodeReadStaticArrayDoubleValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArrayStringValueVariableTestAsync() { return GetTests().NodeReadStaticArrayStringValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArrayDateTimeValueVariableTestAsync() { return GetTests().NodeReadStaticArrayDateTimeValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArrayGuidValueVariableTestAsync() { return GetTests().NodeReadStaticArrayGuidValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArrayByteStringValueVariableTestAsync() { return GetTests().NodeReadStaticArrayByteStringValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArrayXmlElementValueVariableTestAsync() { return GetTests().NodeReadStaticArrayXmlElementValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArrayNodeIdValueVariableTestAsync() { return GetTests().NodeReadStaticArrayNodeIdValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArrayExpandedNodeIdValueVariableTestAsync() { return GetTests().NodeReadStaticArrayExpandedNodeIdValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArrayQualifiedNameValueVariableTestAsync() { return GetTests().NodeReadStaticArrayQualifiedNameValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArrayLocalizedTextValueVariableTestAsync() { return GetTests().NodeReadStaticArrayLocalizedTextValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArrayStatusCodeValueVariableTestAsync() { return GetTests().NodeReadStaticArrayStatusCodeValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArrayVariantValueVariableTestAsync() { return GetTests().NodeReadStaticArrayVariantValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArrayEnumerationValueVariableTestAsync() { return GetTests().NodeReadStaticArrayEnumerationValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArrayStructureValueVariableTestAsync() { return GetTests().NodeReadStaticArrayStructureValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArrayNumberValueVariableTestAsync() { return GetTests().NodeReadStaticArrayNumberValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArrayIntegerValueVariableTestAsync() { return GetTests().NodeReadStaticArrayIntegerValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticArrayUIntegerValueVariableTestAsync() { return GetTests().NodeReadStaticArrayUIntegerValueVariableTestAsync(Ct); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/TestData/ValueReadScalarTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.TestData { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(ReadCollection.Name)] public class ValueReadScalarTests : TwinIntegrationTestBase, IClassFixture { public ValueReadScalarTests(TestDataServer server, PublisherModuleMqttv5Fixture module, ITestOutputHelper output) : base(output) { _server = server; _module = module; } private ReadScalarValueTests GetTests() { return new ReadScalarValueTests( _module.SdkContainer.Resolve>, _server.GetConnection(), (ep, n, s) => _server.Client.ReadValueAsync(new ConnectionModel { Endpoint = new EndpointModel { Url = ep.Endpoint.Url, Certificate = _server.Certificate?.RawData?.ToThumbprint() } }, n, s)); } private readonly TestDataServer _server; private readonly PublisherModuleMqttv5Fixture _module; [Fact] public Task NodeReadAllStaticScalarVariableNodeClassTest1Async() { return GetTests().NodeReadAllStaticScalarVariableNodeClassTest1Async(Ct); } [Fact] public Task NodeReadAllStaticScalarVariableAccessLevelTest1Async() { return GetTests().NodeReadAllStaticScalarVariableAccessLevelTest1Async(Ct); } [Fact] public Task NodeReadAllStaticScalarVariableWriteMaskTest1Async() { return GetTests().NodeReadAllStaticScalarVariableWriteMaskTest1Async(Ct); } [Fact] public Task NodeReadAllStaticScalarVariableWriteMaskTest2Async() { return GetTests().NodeReadAllStaticScalarVariableWriteMaskTest2Async(Ct); } [Fact] public Task NodeReadStaticScalarBooleanValueVariableTestAsync() { return GetTests().NodeReadStaticScalarBooleanValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest1Async() { return GetTests().NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest1Async(Ct); } [Fact] public Task NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest2Async() { return GetTests().NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest2Async(Ct); } [Fact] public Task NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest3Async() { return GetTests().NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest3Async(Ct); } [Fact] public Task NodeReadStaticScalarSByteValueVariableTestAsync() { return GetTests().NodeReadStaticScalarSByteValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarByteValueVariableTestAsync() { return GetTests().NodeReadStaticScalarByteValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarInt16ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarInt16ValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarUInt16ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarUInt16ValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarInt32ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarInt32ValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarUInt32ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarUInt32ValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarInt64ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarInt64ValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarUInt64ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarUInt64ValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarFloatValueVariableTestAsync() { return GetTests().NodeReadStaticScalarFloatValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarDoubleValueVariableTestAsync() { return GetTests().NodeReadStaticScalarDoubleValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarStringValueVariableTestAsync() { return GetTests().NodeReadStaticScalarStringValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarDateTimeValueVariableTestAsync() { return GetTests().NodeReadStaticScalarDateTimeValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarGuidValueVariableTestAsync() { return GetTests().NodeReadStaticScalarGuidValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarByteStringValueVariableTestAsync() { return GetTests().NodeReadStaticScalarByteStringValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarXmlElementValueVariableTestAsync() { return GetTests().NodeReadStaticScalarXmlElementValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarNodeIdValueVariableTestAsync() { return GetTests().NodeReadStaticScalarNodeIdValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarExpandedNodeIdValueVariableTestAsync() { return GetTests().NodeReadStaticScalarExpandedNodeIdValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarQualifiedNameValueVariableTestAsync() { return GetTests().NodeReadStaticScalarQualifiedNameValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarLocalizedTextValueVariableTestAsync() { return GetTests().NodeReadStaticScalarLocalizedTextValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarStatusCodeValueVariableTestAsync() { return GetTests().NodeReadStaticScalarStatusCodeValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarVariantValueVariableTestAsync() { return GetTests().NodeReadStaticScalarVariantValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarEnumerationValueVariableTestAsync() { return GetTests().NodeReadStaticScalarEnumerationValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarStructuredValueVariableTestAsync() { return GetTests().NodeReadStaticScalarStructuredValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarNumberValueVariableTestAsync() { return GetTests().NodeReadStaticScalarNumberValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarIntegerValueVariableTestAsync() { return GetTests().NodeReadStaticScalarIntegerValueVariableTestAsync(Ct); } [Fact] public Task NodeReadStaticScalarUIntegerValueVariableTestAsync() { return GetTests().NodeReadStaticScalarUIntegerValueVariableTestAsync(Ct); } [Fact] public Task NodeReadDataAccessMeasurementFloatValueTestAsync() { return GetTests().NodeReadDataAccessMeasurementFloatValueTestAsync(Ct); } [Fact] public Task NodeReadDiagnosticsNoneTestAsync() { return GetTests().NodeReadDiagnosticsNoneTestAsync(Ct); } [Fact] public Task NodeReadDiagnosticsStatusTestAsync() { return GetTests().NodeReadDiagnosticsStatusTestAsync(Ct); } [Fact] public Task NodeReadDiagnosticsDebugTestAsync() { return GetTests().NodeReadDiagnosticsDebugTestAsync(Ct); } [Fact] public Task NodeReadDiagnosticsVerboseTestAsync() { return GetTests().NodeReadDiagnosticsVerboseTestAsync(Ct); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/TestData/ValueWriteArrayTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.TestData { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection.Name)] public class ValueWriteArrayTests : TwinIntegrationTestBase, IClassFixture { public ValueWriteArrayTests(TestDataServer server, PublisherModuleMqttv5Fixture module, ITestOutputHelper output) : base(output) { _server = server; _module = module; } private WriteArrayValueTests GetTests() { return new WriteArrayValueTests( _module.SdkContainer.Resolve>, _server.GetConnection(), (ep, n, s) => _server.Client.ReadValueAsync(new ConnectionModel { Endpoint = new EndpointModel { Url = ep.Endpoint.Url, Certificate = _server.Certificate?.RawData?.ToThumbprint() } }, n, s)); } private readonly TestDataServer _server; private readonly PublisherModuleMqttv5Fixture _module; [Fact] public Task NodeWriteStaticArrayBooleanValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayBooleanValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticArraySByteValueVariableTestAsync() { return GetTests().NodeWriteStaticArraySByteValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticArrayByteValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayByteValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticArrayInt16ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayInt16ValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticArrayUInt16ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayUInt16ValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticArrayInt32ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayInt32ValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticArrayUInt32ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayUInt32ValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticArrayInt64ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayInt64ValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticArrayUInt64ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayUInt64ValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticArrayFloatValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayFloatValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticArrayDoubleValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayDoubleValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticArrayStringValueVariableTest1Async() { return GetTests().NodeWriteStaticArrayStringValueVariableTest1Async(Ct); } [Fact] public Task NodeWriteStaticArrayStringValueVariableTest2Async() { return GetTests().NodeWriteStaticArrayStringValueVariableTest2Async(Ct); } [Fact] public Task NodeWriteStaticArrayDateTimeValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayDateTimeValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticArrayGuidValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayGuidValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticArrayByteStringValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayByteStringValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticArrayXmlElementValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayXmlElementValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticArrayNodeIdValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayNodeIdValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticArrayExpandedNodeIdValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayExpandedNodeIdValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticArrayQualifiedNameValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayQualifiedNameValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticArrayLocalizedTextValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayLocalizedTextValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticArrayStatusCodeValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayStatusCodeValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticArrayVariantValueVariableTest1Async() { return GetTests().NodeWriteStaticArrayVariantValueVariableTest1Async(Ct); } [Fact] public Task NodeWriteStaticArrayEnumerationValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayEnumerationValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticArrayStructureValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayStructureValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticArrayNumberValueVariableTest1Async() { return GetTests().NodeWriteStaticArrayNumberValueVariableTest1Async(Ct); } [Fact] public Task NodeWriteStaticArrayNumberValueVariableTest2Async() { return GetTests().NodeWriteStaticArrayNumberValueVariableTest2Async(Ct); } [Fact] public Task NodeWriteStaticArrayIntegerValueVariableTest1Async() { return GetTests().NodeWriteStaticArrayIntegerValueVariableTest1Async(Ct); } [Fact] public Task NodeWriteStaticArrayIntegerValueVariableTest2Async() { return GetTests().NodeWriteStaticArrayIntegerValueVariableTest2Async(Ct); } [Fact] public Task NodeWriteStaticArrayUIntegerValueVariableTest1Async() { return GetTests().NodeWriteStaticArrayUIntegerValueVariableTest1Async(Ct); } [Fact] public Task NodeWriteStaticArrayUIntegerValueVariableTest2Async() { return GetTests().NodeWriteStaticArrayUIntegerValueVariableTest2Async(Ct); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/TestData/ValueWriteScalarTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.TestData { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; [Collection(WriteCollection.Name)] public class ValueWriteScalarTests : TwinIntegrationTestBase, IClassFixture { public ValueWriteScalarTests(TestDataServer server, PublisherModuleMqttv311Fixture module, ITestOutputHelper output) : base(output) { _server = server; _module = module; } private WriteScalarValueTests GetTests() { return new WriteScalarValueTests( _module.SdkContainer.Resolve>, _server.GetConnection(), (ep, n, s) => _server.Client.ReadValueAsync(new ConnectionModel { Endpoint = new EndpointModel { Url = ep.Endpoint.Url, Certificate = _server.Certificate?.RawData?.ToThumbprint() } }, n, s)); } private readonly TestDataServer _server; private readonly PublisherModuleMqttv311Fixture _module; [Fact] public Task NodeWriteStaticScalarBooleanValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarBooleanValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest1Async() { return GetTests().NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest1Async(Ct); } [Fact] public Task NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest2Async() { return GetTests().NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest2Async(Ct); } [Fact] public Task NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest3Async() { return GetTests().NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest3Async(Ct); } [Fact] public Task NodeWriteStaticScalarSByteValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarSByteValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarByteValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarByteValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarInt16ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarInt16ValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarUInt16ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarUInt16ValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarInt32ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarInt32ValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarUInt32ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarUInt32ValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarInt64ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarInt64ValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarUInt64ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarUInt64ValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarFloatValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarFloatValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarDoubleValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarDoubleValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarStringValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarStringValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarDateTimeValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarDateTimeValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarGuidValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarGuidValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarByteStringValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarByteStringValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarXmlElementValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarXmlElementValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarNodeIdValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarNodeIdValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarExpandedNodeIdValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarExpandedNodeIdValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarQualifiedNameValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarQualifiedNameValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarLocalizedTextValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarLocalizedTextValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarStatusCodeValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarStatusCodeValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarVariantValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarVariantValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarEnumerationValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarEnumerationValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarStructuredValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarStructuredValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarNumberValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarNumberValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarIntegerValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarIntegerValueVariableTestAsync(Ct); } [Fact] public Task NodeWriteStaticScalarUIntegerValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarUIntegerValueVariableTestAsync(Ct); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Mqtt/TestData/WriteCollection.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Mqtt.TestData { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public class WriteCollection : ICollectionFixture { public const string Name = "TestDataServerWriteModuleMqtt"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Properties/AssemblyInfo.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ #if !DEBUG using Xunit; [assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly, MaxParallelThreads = 4)] #endif ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Resources/CyclicRead.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseReverseConnect": "{{UseReverseConnect}}", "UseSecurity": false, "DataSetWriterGroup": "{{DataSetWriterGroup}}", "OpcNodes": [ { "Id": "ns=23;i=1259", "OpcSamplingInterval": 500, "FetchDisplayName": true, "UseCyclicRead": true, "CyclicReadMaxAge": 500 } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Resources/DataItems.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": false, "DataSetWriterGroup": "{{DataSetWriterGroup}}", "OpcNodes": [ { "Id": "ns=23;i=1259", "OpcSamplingInterval": 200, "OpcPublishingInterval": 200, "DisplayName": "Output", "SkipFirst": true } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Resources/DataItems1.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": false, "DataSetWriterGroup": "{{DataSetWriterGroup}}", "OpcNodes": [ { "Id": "ns=23;i=1259" }, { "Id": "i=2258" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Resources/DataItems2.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseReverseConnect": "{{UseReverseConnect}}", "EndpointSecurityMode": "{{SecurityMode}}", "DataSetWriterGroup": "{{DataSetWriterGroup}}", "OpcNodes": [ { "Id": "http://test.org/UA/Data/#i=11224", "OpcSamplingInterval": 100, "OpcPublishingInterval": 100, "DisplayName": "Output2" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Resources/Deadband.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": false, "DataSetWriterGroup": "{{DataSetWriterGroup}}", "OpcNodes": [ { "Id": "http://test.org/UA/Data/#i=11224", "OpcSamplingInterval": 1000, "OpcPublishingInterval": 1000, "QueueSize": 10, "DeadbandType": "Absolute", "DeadbandValue": 5.0, "DisplayName": "DoubleValues" }, { "Id": "http://test.org/UA/Data/#i=11206", "OpcSamplingInterval": 1000, "OpcPublishingInterval": 1000, "QueueSize": 10, "DeadbandType": "Percent", "DeadbandValue": 5.0, "DisplayName": "Int64Values" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Resources/DmApiPayloadCollection.json ================================================ [ { "DataSetWriterGroup": "Leaf0", "DataSetWriterId": "Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234", "DataSetName": "Tag_Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234", "EndpointUrl": "opc.tcp://opcplc:50000", "UseSecurity": false, "OpcAuthenticationMode": "UsernamePassword", "OpcAuthenticationUsername": "usr", "OpcAuthenticationPassword": "pwd", "OpcNodes": [ { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=StepUp", "DataSetFieldId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=StepUp", "DisplayName": "StepUp", "OpcSamplingIntervalTimespan": "00:00:02", "OpcPublishingIntervalTimespan": "00:00:01.500", "HeartbeatIntervalTimespan": "00:00:01.500", "SkipFirst": true, "QueueSize": 10 }, { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=StepUp", "DataSetFieldId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=StepUp", "DisplayName": "StepUp", "OpcSamplingInterval": 2000, "OpcPublishingInterval": 1500, "HeartbeatInterval": 4, "SkipFirst": true, "QueueSize": 10 } ] }, { "DataSetWriterGroup": "Leaf0", "DataSetWriterId": "Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234", "DataSetName": "Tag_Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234", "EndpointUrl": "opc.tcp://opcplc:50000", "UseSecurity": false, "OpcAuthenticationMode": "UsernamePassword", "OpcAuthenticationUsername": "usr", "OpcAuthenticationPassword": "pwd", "OpcNodes": [ { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1", "DataSetFieldId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1", "DisplayName": "FastUInt1", "OpcSamplingIntervalTimespan": "00:00:02.000", "OpcPublishingIntervalTimespan": "00:00:01.500", "HeartbeatIntervalTimespan": "00:00:01.500", "SkipFirst": true, "QueueSize": 10 } ] }, { "DataSetWriterGroup": "Leaf0", "DataSetWriterId": "Leaf1_10000_2e4fc28f-ffa2-4532-9f22-378d47bbee5d", "DataSetName": "Tag_Leaf1_10000_2e4fc28f-ffa2-4532-9f22-378d47bbee5d", "EndpointUrl": "opc.tcp://opcplc:50000", "UseSecurity": false, "OpcAuthenticationMode": "UsernamePassword", "Username": "usr", "OpcAuthenticationPassword": "pwd", "OpcNodes": [ { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1", "DataSetFieldId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1", "OpcSamplingInterval": 2000, "OpcPublishingInterval": 2000, "HeartbeatInterval": 2, "SkipFirst": false, "QueueSize": 1 } ] }, { "DataSetWriterGroup": "Leaf0", "DataSetWriterId": "Leaf2_10000_3085991c-b85c-4311-9bfb-a916da952234", "DataSetName": "Tag_Leaf2_10000_3085991c-b85c-4311-9bfb-a916da952234", "DataSetPublishingIntervalTimespan": "00:00:02.500", "EndpointUrl": "opc.tcp://opcplc:50000", "UseSecurity": false, "OpcAuthenticationMode": "UsernamePassword", "OpcAuthenticationUsername": "usr", "OpcAuthenticationPassword": "pwd", "OpcNodes": [ { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=StepUp", "DataSetFieldId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=StepUp", "DisplayName": "StepUp", "OpcSamplingIntervalTimespan": "00:00:01.500", "OpcPublishingIntervalTimespan": "00:00:01.500", "HeartbeatIntervalTimespan": "00:00:01.500", "SkipFirst": true, "QueueSize": 10 } ] }, { "DataSetWriterGroup": "Leaf0", "DataSetWriterId": "Leaf3_10000_2e4fc28f-ffa2-4532-9f22-378d47bbee5d", "DataSetName": "Tag_Leaf3_10000_2e4fc28f-ffa2-4532-9f22-378d47bbee5d", "DataSetPublishingInterval": 10000, "EndpointUrl": "opc.tcp://opcplc:50000", "UseSecurity": false, "OpcAuthenticationMode": "UsernamePassword", "Username": "usr", "OpcAuthenticationPassword": "pwd", "OpcNodes": [ { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1", "DataSetFieldId": "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1", "OpcSamplingInterval": 2000, "OpcPublishingInterval": 2000, "HeartbeatInterval": 2, "SkipFirst": false, "QueueSize": 1 }, { "Id": "i=2253", "DisplayName": "SimpleEvents", "QueueSize": 10, "EventFilter": { "SelectClauses": [ { "TypeDefinitionId": "i=2041", "BrowsePath": [ "EventId" ] }, { "TypeDefinitionId": "i=2041", "BrowsePath": [ "Message" ] }, { "TypeDefinitionId": "ns=16;i=235", "BrowsePath": [ "16:CycleId" ] }, { "TypeDefinitionId": "ns=16;i=235", "BrowsePath": [ "16:CurrentStep" ] } ], "WhereClause": { "Elements": [ { "FilterOperator": "OfType", "FilterOperands": [ { "Value": "ns=16;i=235" } ] } ] } } } ] }, { "DataSetWriterGroup": "Leaf0", "EndpointUrl": "opc.tcp://opcplc:50000", "OpcNodes": [ { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=StepUp" }, { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt1" } ] }, { "DataSetWriterGroup": "Leaf0", "EndpointUrl": "opc.tcp://opcplc:50000", "OpcNodes": [ { "Id": "nsu=http://microsoft.com/Opc/OpcPlc/;s=FastUInt2" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Resources/DmApiPayloadTwoEndpoints.json ================================================ [ { "DataSetWriterGroup": "Leaf0", "DataSetWriterId": "Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234", "DataSetName": "Tag_Leaf0_10000_3085991c-b85c-4311-9bfb-a916da952234", "EndpointUrl": "opc.tcp://opcplc:50000", "UseSecurity": false, "OpcAuthenticationMode": "UsernamePassword", "OpcAuthenticationUsername": "usr", "OpcAuthenticationPassword": "pwd", "OpcNodes": [ { "Id": "ns=2;s=SlowUInt1", "DataSetFieldId": "ns=2;s=SlowUInt1", "DisplayName": "SlowUint1", "OpcSamplingInterval": 2000, "OpcPublishingInterval": 1500, "HeartbeatInterval": 4, "SkipFirst": true, "QueueSize": 10 } ] }, { "DataSetWriterGroup": "Leaf1", "DataSetWriterId": "Leaf1_10000_3085991c-b85c-4311-9bfb-a916da952235", "DataSetName": "Tag_Leaf1_10000_3085991c-b85c-4311-9bfb-a916da952235", "DataSetPublishingInterval": 3000, "EndpointUrl": "opc.tcp://opcplc:50000", "OpcAuthenticationMode": "Anonymous", "OpcNodes": [ { "Id": "ns=2;s=SlowUInt2", "DataSetFieldId": "ns=2;s=SlowUInt2", "DisplayName": "SlowUint", "OpcSamplingInterval": 2000, "HeartbeatInterval": 4, "SkipFirst": true, "QueueSize": 10 } ] }, { "DataSetWriterGroup": "Leaf2", "DataSetWriterId": "Leaf2_10000_3085991c-b85c-4311-9bfb-a916da952235", "DataSetName": "Tag_Leaf2_10000_3085991c-b85c-4311-9bfb-a916da952235", "DataSetPublishingInterval": 10000, "EndpointUrl": "opc.tcp://opcplc:50000", "UseSecurity": false, "OpcNodes": [ { "Id": "i=2253", "DisplayName": "SimpleEvents", "QueueSize": 10, "EventFilter": { "SelectClauses": [ { "TypeDefinitionId": "i=2041", "BrowsePath": [ "EventId" ] }, { "TypeDefinitionId": "i=2041", "BrowsePath": [ "Message" ] }, { "TypeDefinitionId": "ns=16;i=235", "BrowsePath": [ "16:CycleId" ] }, { "TypeDefinitionId": "ns=16;i=235", "BrowsePath": [ "16:CurrentStep" ] } ], "WhereClause": { "Elements": [ { "FilterOperator": "OfType", "FilterOperands": [ { "Value": "ns=16;i=235" } ] } ] } } } ] }, { "EndpointUrl": "opc.tcp://opcplc:50000", "UseSecurity": false, "DataSetPublishingIntervalTimespan": "00:00:02", "OpcNodes": [ { "Id": "ns=2;s=SlowUInt3", "DataSetFieldId": "ns=2;s=SlowUInt3", "DisplayName": "SlowUint", "OpcSamplingInterval": 2000, "HeartbeatInterval": 4, "SkipFirst": true, "QueueSize": 10 } ] }, { "EndpointUrl": "opc.tcp://opcplc:50000", "OpcAuthenticationMode": "UsernamePassword", "OpcAuthenticationUsername": "usr", "OpcAuthenticationPassword": "pwd", "OpcNodes": [ { "Id": "ns=2;s=FastUInt3", "OpcPublishingInterval": 1000 }, { "Id": "ns=2;s=FastUInt4", "OpcPublishingInterval": 2000 } ] }, { "EndpointUrl": "opc.tcp://opcplc:50010", "OpcAuthenticationMode": "Anonymous", "UseSecurity": false, "OpcNodes": [ { "Id": "ns=2;s=FastUInt1", "OpcPublishingInterval": 1000 }, { "Id": "ns=2;s=FastUInt2", "OpcPublishingInterval": 2000 } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Resources/ExtensionFields.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": false, "DataSetWriterGroup": "{{DataSetWriterGroup}}", "DataSetExtensionFields": { "EngineeringUnits": "mm/sec", "AssetId": 5, "Important": false, "Variance": 12.3465 }, "OpcNodes": [ { "Id": "ns=23;i=1259", "OpcSamplingInterval": 200, "OpcPublishingInterval": 200, "DisplayName": "Output", "SkipFirst": true } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Resources/Fixedvalue.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "EndpointSecurityMode": "{{SecurityMode}}", "DataSetFetchDisplayNames": true, "OpcNodes": [ { "Id": "i=2271" }, { "Id": "i=2254" }, { "Id": "i=2255" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Resources/Heartbeat.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": false, "DataSetWriterGroup": "{{DataSetWriterGroup}}", "OpcNodes": [ { "Id": "i=2271", "HeartbeatInterval": 1 } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Resources/Heartbeat2.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": false, "DataSetWriterGroup": "{{DataSetWriterGroup}}", "OpcNodes": [ { "Id": "ns=23;i=1259", "OpcSamplingInterval": 100, "FetchDisplayName": true, "OpcPublishingInterval": 100, "HeartbeatInterval": 1, "HeartbeatBehavior": "PeriodicLKVDropValue" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Resources/HeartbeatErrors.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": false, "DataSetWriterGroup": "{{DataSetWriterGroup}}", "OpcNodes": [ { "Id": "i=932534", "HeartbeatInterval": 1 } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Resources/Isa95Jobs.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": false, "DataSetWriterGroup": "{{DataSetWriterGroup}}", "OpcNodes": [ { "Id": "i=2253", "DisplayName": "Isa95JobResponseData", "QueueSize": 10, "EventFilter": { "TypeDefinitionId": "nsu=http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/;i=1006" } } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Resources/KeepAlive.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseReverseConnect": "{{UseReverseConnect}}", "SendKeepAliveDataSetMessages": true, "MaxKeepAliveCount": 2, "MessagingMode": "PubSub", "UseSecurity": false, "DataSetWriterGroup": "{{DataSetWriterGroup}}", "OpcNodes": [ { "Id": "i=2259", "FetchDisplayName": true } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Resources/KeyFrames.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "MessagingMode": "PubSub", "UseSecurity": false, "DataSetWriterGroup": "{{DataSetWriterGroup}}", "DataSetExtensionFields": { "EngineeringUnits": "mm/sec", "AssetId": 5, "Important": false, "Variance": 12.3465 }, "DataSetKeyFrameCount": 10, "DataSetPublishingInterval": 100, "OpcNodes": [ { "Id": "i=2258", "OpcSamplingInterval": 100, "FetchDisplayName": true } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Resources/ModelChanges.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": false, "OpcNodes": [ { "ModelChangeHandling": { "RebrowsePeriod": "00:00:10" } } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Resources/PendingAlarms.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": false, "DataSetWriterGroup": "{{DataSetWriterGroup}}", "OpcNodes": [ { "DisplayName": "PendingAlarms", "Id": "i=2253", "EventFilter": { "TypeDefinitionId": "i=2041" }, "ConditionHandling": { "UpdateInterval": 1, "SnapshotInterval": 2 } } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Resources/RegisteredRead.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseReverseConnect": "{{UseReverseConnect}}", "UseSecurity": false, "DataSetWriterGroup": "{{DataSetWriterGroup}}", "OpcNodes": [ { "Id": "ns=23;i=1259", "OpcSamplingInterval": 500, "FetchDisplayName": true, "RegisterNode": true, "UseCyclicRead": true } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Resources/SimpleEvents.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": false, "DataSetWriterGroup": "{{DataSetWriterGroup}}", "OpcNodes": [ { "Id": "i=2253", "DisplayName": "SimpleEvents", "QueueSize": 10, "EventFilter": { "SelectClauses": [ { "TypeDefinitionId": "i=2041", "BrowsePath": [ "EventId" ] }, { "TypeDefinitionId": "i=2041", "BrowsePath": [ "Message" ] }, { "TypeDefinitionId": "ns=16;i=235", "BrowsePath": [ "16:CycleId" ] }, { "TypeDefinitionId": "ns=16;i=235", "BrowsePath": [ "16:CurrentStep" ] } ], "WhereClause": { "Elements": [ { "FilterOperator": "OfType", "FilterOperands": [ { "Value": "ns=16;i=235" } ] } ] } } } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Resources/SimpleEvents2.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": false, "DataSetWriterGroup": "{{DataSetWriterGroup}}", "OpcNodes": [ { "Id": "i=2253", "DisplayName": "Alarm", "EventFilter": { "TypeDefinitionId": "i=10060" } }, { "Id": "i=2253", "DisplayName": "CycleStarted", "EventFilter": { "TypeDefinitionId": "ns=16;i=235" } } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Resources/UnifiedNamespace.json ================================================ [ { "EndpointUrl": "{{EndpointUrl}}", "UseSecurity": false, "DataSetWriterGroup": "{{DataSetWriterGroup}}", "MessagingMode": "RawDataSets", "DataSetRouting": "UseBrowseNames", "OpcNodes": [ { "Id": "ns=23;i=1259" }, { "Id": "i=2258" } ] } ] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Resources/empty_pn.json ================================================ [] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Runtime/CommandLineTest.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Runtime { using Azure.IIoT.OpcUa.Publisher.Module.Runtime; using System.Collections.Generic; /// /// Test class to override Exit method /// public class CommandLineTest : CommandLineLogger { /// /// Exit code /// public int ExitCode { get; set; } = -1; /// /// Warnings reported by StandaloneCliOptions. /// public IList Warnings { get; } = []; public CommandLine CommandLine { get; } public CommandLineTest(string[] args) { CommandLine = new CommandLine(args, this); } /// /// Set exit code /// /// public override void ExitProcess(int exitCode) { ExitCode = exitCode; } /// public override void Warning(string messageTemplate) { Warnings.Add(messageTemplate); } /// public override void Warning(string messageTemplate, T propertyValue0) { Warnings.Add(messageTemplate + "::" + propertyValue0); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Runtime/PublisherCliTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Runtime { using Azure.IIoT.OpcUa.Publisher.Module.Runtime; using FluentAssertions; using System; using Xunit; /// /// Class to test Cli options /// public class PublisherCliTests { public PublisherCliTests() { Environment.SetEnvironmentVariable("IOTEDGE_DEVICEID", "deviceId"); } /// /// ValidOptionTest /// /// /// [Theory] [InlineData("testValue", new string[] { "-dc", "testValue" })] [InlineData("testValue", new string[] { "--dc", "testValue" })] [InlineData("testValue", new string[] { "-ec", "testValue" })] [InlineData("testValue", new string[] { "--ec", "testValue" })] [InlineData("testValue", new string[] { "-deviceconnectionstring", "testValue" })] [InlineData("testValue", new string[] { "--deviceconnectionstring", "testValue" })] public void ValidOptionTest(string expected, string[] param) { var result = new CommandLine(param); result.Count .Should() .Be(1); result.Values.Should() .Equal(expected); } /// /// Valid boolean option test /// /// /// [Theory] [InlineData("True", new string[] { "-aa" })] [InlineData("True", new string[] { "--aa" })] [InlineData("True", new string[] { "-autoaccept" })] [InlineData("True", new string[] { "--autoaccept" })] [InlineData("True", new string[] { "--autoaccept=True" })] [InlineData("False", new string[] { "--autoaccept=False" })] [InlineData("False", new string[] { "-aa=false" })] [InlineData("True", new string[] { "-aa=true" })] [InlineData("True", new string[] { "-acceptuntrusted" })] [InlineData("True", new string[] { "--acceptuntrusted" })] [InlineData("True", new string[] { "--acceptuntrusted=True" })] [InlineData("False", new string[] { "--acceptuntrusted=False" })] [InlineData("True", new string[] { "--AutoAcceptUntrustedCertificates" })] [InlineData("True", new string[] { "--AutoAcceptUntrustedCertificates=True" })] public void ValidAutoAcceptUntrustedCertificatesOptionTest(string expected, string[] param) { var result = new CommandLine(param); result.Count .Should() .Be(1); result.Keys.Should() .Equal("AutoAcceptUntrustedCertificates"); result.Values.Should() .Equal(expected); } /// /// Valid boolean option test /// /// /// [Theory] [InlineData("True", new string[] { "-c" })] [InlineData("True", new string[] { "--c" })] [InlineData("True", new string[] { "-strict" })] [InlineData("True", new string[] { "--strict" })] [InlineData("True", new string[] { "--strict=True" })] [InlineData("False", new string[] { "--strict=False" })] [InlineData("True", new string[] { "--UseStandardsCompliantEncoding" })] [InlineData("True", new string[] { "--UseStandardsCompliantEncoding=True" })] public void ValidUseStandardsCompliantEncodingOptionTest(string expected, string[] param) { var result = new CommandLine(param); result.Count .Should() .Be(1); result.Keys.Should() .Equal(PublisherConfig.UseStandardsCompliantEncodingKey); result.Values.Should() .Equal(expected); } /// /// LegacyOptionTest /// /// /// [Theory] [InlineData("tc|telemetryconfigfile", new string[] { "-tc", "testValue" })] [InlineData("tc|telemetryconfigfile", new string[] { "--tc", "testValue" })] [InlineData("tc|telemetryconfigfile", new string[] { "-telemetryconfigfile", "testValue" })] [InlineData("tc|telemetryconfigfile", new string[] { "--telemetryconfigfile", "testValue" })] public void LegacyOptionTest(string cliOption, string[] param) { var result = new CommandLineTest(param); result.CommandLine.Count.Should().Be(0); result.Warnings.Count.Should().Be(1); result.Warnings[0].Should().Be( "Legacy option {0} not supported, please use -h option to get all the supported options." + "::" + cliOption ); } /// /// UnsupportedOptionTest /// /// [Theory] [InlineData("-xx")] [InlineData("--xx")] [InlineData("--unknown")] [InlineData("-unknown", "testValue")] [InlineData("unknown=testValue")] public void UnsupportedOptionTest(params string[] param) { var result = new CommandLineTest(param); result.CommandLine.Count.Should().Be(0); result.Warnings.Count.Should().Be(param.Length); for (var i = 0; i < result.Warnings.Count; ++i) { var warning = result.Warnings[i]; warning.Should().Be( "Option {0} wrong or not supported, please use -h option to get all the supported options." + "::" + param[i] ); } } /// /// MissingOptionParameterTest /// /// [Theory] [InlineData("-dc")] [InlineData("--dc")] [InlineData("-deviceconnectionstring")] [InlineData("--deviceconnectionstring")] public void MissingOptionParameterTest(params string[] param) { var result = new CommandLineTest(param); result.ExitCode.Should().Be(160); result.Warnings.Count.Should().Be(1); result.Warnings[0].Should().Be($"Parse args exception {{0}}.::Missing required value for option '{param[0]}'."); } /// /// HelpOptionParameterTest /// /// [Theory] [InlineData([new string[] { "-h" }])] [InlineData([new string[] { "--h" }])] [InlineData([new string[] { "-help" }])] [InlineData([new string[] { "--help" }])] public void HelpOptionParameterTest(string[] param) { var result = new CommandLineTest(param); result.ExitCode .Should() .Be(0); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Runtime/PublisherControllerTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Runtime { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using System; using System.Security.Cryptography.X509Certificates; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public class PublisherControllerTests : PublisherIntegrationTestBase { private readonly ITestOutputHelper _output; public PublisherControllerTests(ITestOutputHelper output) : base(output) { _output = output; } [Fact] public async Task GetApiKeyAndCertificateTestAsync() { const string name = nameof(GetApiKeyAndCertificateTestAsync); StartPublisher(name, "./Resources/empty_pn.json", arguments: ["--mm=PubSub"]); try { var apiKey = await PublisherApi.GetApiKeyAsync(); Assert.NotNull(apiKey); Assert.NotNull(Convert.FromBase64String(apiKey)); var certificate = await PublisherApi.GetServerCertificateAsync(); Assert.NotNull(certificate); using var x509 = X509Certificate2.CreateFromPem(certificate); Assert.StartsWith("DC=", x509.Subject, StringComparison.Ordinal); } finally { await StopPublisherAsync(); } } [Fact] public async Task ShutdownTestAsync() { const string name = nameof(ShutdownTestAsync); StartPublisher(name, "./Resources/empty_pn.json"); try { // We mocked this call await PublisherApi.ShutdownAsync(); await PublisherApi.ShutdownAsync(true); } finally { await StopPublisherAsync(); } } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/Alarms/NodeServicesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.Alarms { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; public sealed class NodeServicesTests : IClassFixture, IClassFixture { public NodeServicesTests(AlarmsServer server, PublisherModuleFixture module) { _server = server; _module = module; } private AlarmServerTests GetTests() { return new AlarmServerTests( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly AlarmsServer _server; private readonly PublisherModuleFixture _module; [Fact] public Task BrowseAreaPathTestAsync() { return GetTests().BrowseAreaPathTestAsync(); } [Fact] public Task BrowseMetalsSouthMotorTestAsync() { return GetTests().BrowseMetalsSouthMotorTestAsync(); } [Fact] public Task BrowseColoursEastTankTestAsync() { return GetTests().BrowseColoursEastTankTestAsync(); } [Fact] public Task CompileAlarmQueryTest1Async() { return GetTests().CompileAlarmQueryTest1Async(); } [Fact] public Task CompileAlarmQueryTest2Async() { return GetTests().CompileAlarmQueryTest2Async(); } [Fact] public Task CompileSimpleBaseEventQueryTestAsync() { return GetTests().CompileSimpleBaseEventQueryTestAsync(); } [Fact] public Task CompileSimpleTripAlarmQueryTestAsync() { return GetTests().CompileSimpleTripAlarmQueryTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/DeterministicAlarms/NodeServicesTests1.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.DeterministicAlarms { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; public sealed class NodeServicesTests1 : IClassFixture, IClassFixture { public NodeServicesTests1(DeterministicAlarmsServer1 server, PublisherModuleFixture module) { _server = server; _module = module; } private DeterministicAlarmsTests1 GetTests() { return new DeterministicAlarmsTests1( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly DeterministicAlarmsServer1 _server; private readonly PublisherModuleFixture _module; [Fact] public Task BrowseAreaPathVendingMachine1TemperatureHighTestAsync() { return GetTests().BrowseAreaPathVendingMachine1TemperatureHighTestAsync(); } [Fact] public Task BrowseAreaPathVendingMachine2LightOffTestAsync() { return GetTests().BrowseAreaPathVendingMachine2LightOffTestAsync(); } [Fact] public Task BrowseAreaPathVendingMachine1DoorOpenTestAsync() { return GetTests().BrowseAreaPathVendingMachine1DoorOpenTestAsync(); } [Fact] public Task BrowseAreaPathVendingMachine2DoorOpenTestAsync() { return GetTests().BrowseAreaPathVendingMachine2DoorOpenTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/DeterministicAlarms/NodeServicesTests2.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.DeterministicAlarms { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; public sealed class NodeServicesTests2 : IClassFixture, IClassFixture { public NodeServicesTests2(DeterministicAlarmsServer2 server, PublisherModuleFixture module) { _server = server; _module = module; } private DeterministicAlarmsTests2 GetTests() { return new DeterministicAlarmsTests2( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly DeterministicAlarmsServer2 _server; private readonly PublisherModuleFixture _module; [Fact] public Task BrowseAreaPathVendingMachine1DoorOpenTestAsync() { return GetTests().BrowseAreaPathVendingMachine1DoorOpenTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/HistoricalAccess/NodeServicesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.HistoricalAccess { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; [Collection(ReadCollection.Name)] public class NodeServicesTests : IClassFixture { public NodeServicesTests(HistoricalAccessServer server, PublisherModuleFixture module) { _server = server; _module = module; } private NodeHistoricalAccessTests GetTests() { return new NodeHistoricalAccessTests( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly PublisherModuleFixture _module; [Fact] public Task GetServerCapabilitiesTestAsync() { return GetTests().GetServerCapabilitiesTestAsync(); } [Fact] public Task HistoryGetServerCapabilitiesTestAsync() { return GetTests().HistoryGetServerCapabilitiesTestAsync(); } [Fact] public Task HistoryGetInt16NodeHistoryConfiguration() { return GetTests().HistoryGetInt16NodeHistoryConfigurationAsync(); } [Fact] public Task HistoryGetInt64NodeHistoryConfigurationAsync() { return GetTests().HistoryGetInt64NodeHistoryConfigurationAsync(); } [Fact] public Task HistoryGetNodeHistoryConfigurationFromBadNode() { return GetTests().HistoryGetNodeHistoryConfigurationFromBadNodeAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/HistoricalAccess/ReadAtTimesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.HistoricalAccess { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; [Collection(ReadCollection.Name)] public class ReadAtTimesTests : IClassFixture { public ReadAtTimesTests(HistoricalAccessServer server, PublisherModuleFixture module) { _server = server; _module = module; } private HistoryReadValuesAtTimesTests GetTests() { return new HistoryReadValuesAtTimesTests(_server, _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly PublisherModuleFixture _module; [Fact] public Task HistoryReadInt32ValuesAtTimesTest1Async() { return GetTests().HistoryReadInt32ValuesAtTimesTest1Async(); } [Fact] public Task HistoryReadInt32ValuesAtTimesTest2Async() { return GetTests().HistoryReadInt32ValuesAtTimesTest2Async(); } [Fact] public Task HistoryReadInt32ValuesAtTimesTest3Async() { return GetTests().HistoryReadInt32ValuesAtTimesTest3Async(); } [Fact] public Task HistoryReadInt32ValuesAtTimesTest4Async() { return GetTests().HistoryReadInt32ValuesAtTimesTest4Async(); } [SkippableFact] public Task HistoryStreamInt32ValuesAtTimesTest1Async() { Skip.If(true, "Not yet supported"); return GetTests().HistoryStreamInt32ValuesAtTimesTest1Async(); } [SkippableFact] public Task HistoryStreamInt32ValuesAtTimesTest2Async() { Skip.If(true, "Not yet supported"); return GetTests().HistoryStreamInt32ValuesAtTimesTest2Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/HistoricalAccess/ReadCollection.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.HistoricalAccess { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public class ReadCollection : ICollectionFixture { public const string Name = "HistoricalAccessServerReadModuleSdk"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/HistoricalAccess/ReadModifiedTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.HistoricalAccess { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; [Collection(ReadCollection.Name)] public class ReadModifiedTests : IClassFixture { public ReadModifiedTests(HistoricalAccessServer server, PublisherModuleFixture module) { _server = server; _module = module; } private HistoryReadValuesModifiedTests GetTests() { return new HistoryReadValuesModifiedTests(_server, _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly PublisherModuleFixture _module; [Fact] public Task HistoryReadInt16ValuesModifiedTestAsync() { return GetTests().HistoryReadInt16ValuesModifiedTestAsync(); } [SkippableFact] public Task HistoryStreamInt16ValuesModifiedTestAsync() { Skip.If(true, "Not yet supported"); return GetTests().HistoryStreamInt16ValuesModifiedTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/HistoricalAccess/ReadProcessedTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.HistoricalAccess { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; [Collection(ReadCollection.Name)] public class ReadProcessedTests : IClassFixture { public ReadProcessedTests(HistoricalAccessServer server, PublisherModuleFixture module) { _server = server; _module = module; } private HistoryReadValuesProcessedTests GetTests() { return new HistoryReadValuesProcessedTests(_server, _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly PublisherModuleFixture _module; [Fact] public Task HistoryReadUInt64ProcessedValuesTest1Async() { return GetTests().HistoryReadUInt64ProcessedValuesTest1Async(); } [Fact] public Task HistoryReadUInt64ProcessedValuesTest2Async() { return GetTests().HistoryReadUInt64ProcessedValuesTest2Async(); } [SkippableFact] public Task HistoryReadUInt64ProcessedValuesTest3Async() { Skip.If(true, "Not yet supported"); return GetTests().HistoryReadUInt64ProcessedValuesTest3Async(); } [SkippableFact] public Task HistoryStreamUInt64ProcessedValuesTest1Async() { Skip.If(true, "Not yet supported"); return GetTests().HistoryStreamUInt64ProcessedValuesTest1Async(); } [SkippableFact] public Task HistoryStreamUInt64ProcessedValuesTest2Async() { Skip.If(true, "Not yet supported"); return GetTests().HistoryStreamUInt64ProcessedValuesTest2Async(); } [SkippableFact] public Task HistoryStreamUInt64ProcessedValuesTest3Async() { Skip.If(true, "Not yet supported"); return GetTests().HistoryStreamUInt64ProcessedValuesTest3Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/HistoricalAccess/ReadValuesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.HistoricalAccess { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; [Collection(ReadCollection.Name)] public class ReadValuesTests : IClassFixture { public ReadValuesTests(HistoricalAccessServer server, PublisherModuleFixture module) { _server = server; _module = module; } private HistoryReadValuesTests GetTests() { return new HistoryReadValuesTests(_server, _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly PublisherModuleFixture _module; [Fact] public Task HistoryReadInt64ValuesTest1Async() { return GetTests().HistoryReadInt64ValuesTest1Async(); } [Fact] public Task HistoryReadInt64ValuesTest2Async() { return GetTests().HistoryReadInt64ValuesTest2Async(); } [Fact] public Task HistoryReadInt64ValuesTest3Async() { return GetTests().HistoryReadInt64ValuesTest3Async(); } [Fact] public Task HistoryReadInt64ValuesTest4Async() { return GetTests().HistoryReadInt64ValuesTest4Async(); } [SkippableFact] public Task HistoryStreamInt64ValuesTest1Async() { Skip.If(true, "Not yet supported"); return GetTests().HistoryStreamInt64ValuesTest1Async(); } [SkippableFact] public Task HistoryStreamInt64ValuesTest2Async() { Skip.If(true, "Not yet supported"); return GetTests().HistoryStreamInt64ValuesTest2Async(); } [SkippableFact] public Task HistoryStreamInt64ValuesTest3Async() { Skip.If(true, "Not yet supported"); return GetTests().HistoryStreamInt64ValuesTest3Async(); } [SkippableFact] public Task HistoryStreamInt64ValuesTest4Async() { Skip.If(true, "Not yet supported"); return GetTests().HistoryStreamInt64ValuesTest4Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/HistoricalAccess/UpdateValuesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.HistoricalAccess { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; [Collection(ReadCollection.Name)] public class UpdateValuesTests : IClassFixture { public UpdateValuesTests(HistoricalAccessServer server, PublisherModuleFixture module) { _server = server; _module = module; } private HistoryUpdateValuesTests GetTests() { return new HistoryUpdateValuesTests( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly HistoricalAccessServer _server; private readonly PublisherModuleFixture _module; [Fact] public Task HistoryUpsertUInt32ValuesTest1Async() { return GetTests().HistoryUpsertUInt32ValuesTest1Async(); } [Fact] public Task HistoryUpsertUInt32ValuesTest2Async() { return GetTests().HistoryUpsertUInt32ValuesTest2Async(); } [Fact] public Task HistoryInsertUInt32ValuesTest1Async() { return GetTests().HistoryInsertUInt32ValuesTest1Async(); } [Fact] public Task HistoryInsertUInt32ValuesTest2Async() { return GetTests().HistoryInsertUInt32ValuesTest2Async(); } [Fact] public Task HistoryReplaceUInt32ValuesTest1Async() { return GetTests().HistoryReplaceUInt32ValuesTest1Async(); } [Fact] public Task HistoryReplaceUInt32ValuesTest2Async() { return GetTests().HistoryReplaceUInt32ValuesTest2Async(); } [Fact] public Task HistoryInsertDeleteUInt32ValuesTest1Async() { return GetTests().HistoryInsertDeleteUInt32ValuesTest1Async(); } [Fact] public Task HistoryInsertDeleteUInt32ValuesTest2Async() { return GetTests().HistoryInsertDeleteUInt32ValuesTest2Async(); } [Fact] public Task HistoryInsertDeleteUInt32ValuesTest3Async() { return GetTests().HistoryInsertDeleteUInt32ValuesTest3Async(); } [Fact] public Task HistoryInsertDeleteUInt32ValuesTest4Async() { return GetTests().HistoryInsertDeleteUInt32ValuesTest4Async(); } [Fact] public Task HistoryDeleteUInt32ValuesTest1Async() { return GetTests().HistoryDeleteUInt32ValuesTest1Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/HistoricalEvents/NodeServicesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.HistoricalEvents { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; [Collection(ReadCollection.Name)] public class NodeServicesTests : IClassFixture { public NodeServicesTests(HistoricalEventsServer server, PublisherModuleFixture module) { _server = server; _module = module; } private NodeHistoricalEventsTests GetTests() { return new NodeHistoricalEventsTests( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly HistoricalEventsServer _server; private readonly PublisherModuleFixture _module; [Fact] public Task GetServerCapabilitiesTestAsync() { return GetTests().GetServerCapabilitiesTestAsync(); } [Fact] public Task HistoryGetServerCapabilitiesTestAsync() { return GetTests().HistoryGetServerCapabilitiesTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/HistoricalEvents/ReadCollection.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.HistoricalEvents { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public class ReadCollection : ICollectionFixture { public const string Name = "HistoricalEventsServerReadModuleSdk"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/Isa95Jobs/BasicPubSubIntegrationTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.Isa95Jobs { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using System; using System.Linq; using System.Text.Json; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public class BasicPubSubIntegrationTests : PublisherIntegrationTestBase { internal const string EventId = "EventId"; internal const string Message = "Message"; internal const string JobResponseExpanded = "nsu=http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/;JobResponse"; internal const string JobStateExpanded = "nsu=http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/;JobState"; internal const string JobResponseUri = "http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/#JobResponse"; internal const string JobStateUri = "http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/#JobState"; private readonly ITestOutputHelper _output; private readonly Isa95JobsServer _fixture; public BasicPubSubIntegrationTests(ITestOutputHelper output) : base(output) { _output = output; _fixture = new Isa95JobsServer(); EndpointUrl = _fixture.EndpointUrl; } protected override void Dispose(bool disposing) { base.Dispose(disposing); if (disposing) { _fixture.Dispose(); } } [Fact] public async Task CanEncodeWithReversibleEncodingTestAsync() { // Arrange // Act var (metadata, result) = await ProcessMessagesAndMetadataAsync( nameof(CanEncodeWithReversibleEncodingTestAsync), "./Resources/Isa95Jobs.json", TimeSpan.FromMinutes(2), 4, messageType: "ua-data", arguments: ["--mm=PubSub", "--me=JsonReversible", "--dm=false"] ); var messages = result .SelectMany(x => x.Message.GetProperty("Messages").EnumerateArray()) .ToArray(); // Assert Assert.NotEmpty(messages); Assert.All(messages, m => { var payload = m.GetProperty("Payload"); var eventId = payload.GetProperty(EventId).GetProperty("Value"); Assert.Equal("ByteString", eventId.GetProperty("Type").GetString()); Assert.Equal(JsonValueKind.String, eventId.GetProperty("Body").ValueKind); var message = payload.GetProperty(Message).GetProperty("Value"); Assert.Equal("LocalizedText", message.GetProperty("Type").GetString()); Assert.Equal(JsonValueKind.String, message.GetProperty("Body").GetProperty("Text").ValueKind); Assert.Equal("en-US", message.GetProperty("Body").GetProperty("Locale").GetString()); var jobState = payload.GetProperty(JobStateUri).GetProperty("Value"); Assert.Equal("ExtensionObject", jobState.GetProperty("Type").GetString()); var jobResponse = payload.GetProperty(JobResponseUri).GetProperty("Value"); Assert.Equal("ExtensionObject", jobResponse.GetProperty("Type").GetString()); var extensionObject = jobResponse.GetProperty("Body"); Assert.Equal("http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/#i=3013", extensionObject.GetProperty("TypeId").GetString()); Assert.Equal("Json", extensionObject.GetProperty("Encoding").GetString()); var body = extensionObject.GetProperty("Body"); var equipmentActuals = body.GetProperty("EquipmentActuals"); var materialActuals = body.GetProperty("MaterialActuals"); Assert.Equal(JsonValueKind.Array, equipmentActuals.ValueKind); Assert.Equal(JsonValueKind.Array, materialActuals.ValueKind); Assert.Equal(2, equipmentActuals.GetArrayLength()); Assert.Equal(2, materialActuals.GetArrayLength()); Assert.All(equipmentActuals.EnumerateArray(), e => { Assert.Equal(JsonValueKind.String, e.GetProperty("EquipmentUse").ValueKind); Assert.Equal("consumable", e.GetProperty("EquipmentUse").GetString()); Assert.Equal(JsonValueKind.String, e.GetProperty("Quantity").ValueKind); }); Assert.All(materialActuals.EnumerateArray(), e => { Assert.Equal(JsonValueKind.String, e.GetProperty("MaterialClassID").ValueKind); Assert.True(e.GetProperty("MaterialClassID").TryGetGuid(out _)); Assert.Equal(JsonValueKind.String, e.GetProperty("MaterialUse").ValueKind); Assert.Equal("consumable", e.GetProperty("MaterialUse").GetString()); Assert.Equal(JsonValueKind.String, e.GetProperty("Quantity").ValueKind); }); extensionObject = jobState.GetProperty("Body"); Assert.Equal("http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/#i=3015", extensionObject.GetProperty("TypeId").GetString()); Assert.Equal("Json", extensionObject.GetProperty("Encoding").GetString()); body = extensionObject.GetProperty("Body"); var state = body.GetProperty("State"); Assert.Equal(JsonValueKind.Array, state.ValueKind); Assert.Equal(3, state.GetArrayLength()); Assert.All(state.EnumerateArray(), e => { Assert.Equal(JsonValueKind.Array, e.GetProperty("BrowsePath").GetProperty("Elements").ValueKind); Assert.True(e.GetProperty("StateNumber").TryGetInt32(out _)); Assert.Equal(JsonValueKind.String, e.GetProperty("StateText").GetProperty("Text").ValueKind); Assert.Equal("en-US", e.GetProperty("StateText").GetProperty("Locale").GetString()); }); }); } [Fact] public async Task CanEncodeEventWithCompliantEncodingTestAsync() { // Arrange // Act var (metadata, result) = await ProcessMessagesAndMetadataAsync( nameof(CanEncodeEventWithCompliantEncodingTestAsync), "./Resources/Isa95Jobs.json", messageType: "ua-data", arguments: ["-c", "--mm=PubSub", "--me=Json"]); Assert.Single(result); var messages = result .SelectMany(x => x.Message.GetProperty("Messages").EnumerateArray()) .ToArray(); // Assert Assert.NotEmpty(messages); Assert.All(messages, m => { var value = m.GetProperty("Payload"); // Variant encoding is the default var eventId = value.GetProperty(EventId).GetProperty("Value"); var message = value.GetProperty(Message).GetProperty("Value"); var jobResponse = value.GetProperty(JobResponseExpanded).GetProperty("Value"); var equipmentActuals = jobResponse.GetProperty("EquipmentActuals"); var materialActuals = jobResponse.GetProperty("MaterialActuals"); Assert.Equal(JsonValueKind.String, eventId.ValueKind); Assert.Equal(JsonValueKind.String, message.ValueKind); Assert.Equal(JsonValueKind.Array, equipmentActuals.ValueKind); Assert.Equal(JsonValueKind.Array, materialActuals.ValueKind); Assert.Equal(2, equipmentActuals.GetArrayLength()); Assert.Equal(2, materialActuals.GetArrayLength()); Assert.All(equipmentActuals.EnumerateArray(), e => { Assert.Equal(JsonValueKind.String, e.GetProperty("EquipmentUse").ValueKind); Assert.Equal("consumable", e.GetProperty("EquipmentUse").GetString()); Assert.Equal(JsonValueKind.String, e.GetProperty("Quantity").ValueKind); }); Assert.All(materialActuals.EnumerateArray(), e => { Assert.Equal(JsonValueKind.String, e.GetProperty("MaterialClassID").ValueKind); Assert.True(e.GetProperty("MaterialClassID").TryGetGuid(out _)); Assert.Equal(JsonValueKind.String, e.GetProperty("MaterialUse").ValueKind); Assert.Equal("consumable", e.GetProperty("MaterialUse").GetString()); Assert.Equal(JsonValueKind.String, e.GetProperty("Quantity").ValueKind); }); var jobState = value.GetProperty(JobStateExpanded).GetProperty("Value"); var state = jobState.GetProperty("State"); Assert.Equal(JsonValueKind.Array, state.ValueKind); Assert.Equal(3, state.GetArrayLength()); Assert.All(state.EnumerateArray(), e => { Assert.Equal(JsonValueKind.Array, e.GetProperty("BrowsePath").GetProperty("Elements").ValueKind); Assert.True(e.GetProperty("StateNumber").TryGetInt32(out _)); Assert.Equal(JsonValueKind.String, e.GetProperty("StateText").ValueKind); }); }); } [Fact] public async Task CanEncodeWithReversibleEncodingAndWithCompliantEncodingTestAsync() { // Arrange // Act var (metadata, result) = await ProcessMessagesAndMetadataAsync( nameof(CanEncodeWithReversibleEncodingAndWithCompliantEncodingTestAsync), "./Resources/Isa95Jobs.json", TimeSpan.FromMinutes(2), 4, messageType: "ua-data", arguments: ["-c", "--mm=PubSub", "--me=JsonReversible"]); var messages = result .SelectMany(x => x.Message.GetProperty("Messages").EnumerateArray()) .ToArray(); // Assert Assert.NotEmpty(messages); Assert.All(messages, m => { var payload = m.GetProperty("Payload"); var eventId = payload.GetProperty(EventId).GetProperty("Value"); Assert.Equal(15, eventId.GetProperty("Type").GetInt32()); Assert.Equal(JsonValueKind.String, eventId.GetProperty("Body").ValueKind); var message = payload.GetProperty(Message).GetProperty("Value"); Assert.Equal(21, message.GetProperty("Type").GetInt32()); Assert.Equal(JsonValueKind.String, message.GetProperty("Body").GetProperty("Text").ValueKind); Assert.Equal("en-US", message.GetProperty("Body").GetProperty("Locale").GetString()); var jobResponse = payload.GetProperty(JobResponseExpanded).GetProperty("Value"); Assert.Equal(22, jobResponse.GetProperty("Type").GetInt32()); var jobState = payload.GetProperty(JobStateExpanded).GetProperty("Value"); Assert.Equal(22, jobState.GetProperty("Type").GetInt32()); var extensionObject = jobResponse.GetProperty("Body"); Assert.Equal(3013, extensionObject.GetProperty("TypeId").GetProperty("Id").GetInt32()); Assert.Equal(2, extensionObject.GetProperty("TypeId").GetProperty("Namespace").GetInt32()); var body = extensionObject.GetProperty("Body"); var equipmentActuals = body.GetProperty("EquipmentActuals"); var materialActuals = body.GetProperty("MaterialActuals"); Assert.Equal(JsonValueKind.Array, equipmentActuals.ValueKind); Assert.Equal(JsonValueKind.Array, materialActuals.ValueKind); Assert.Equal(2, equipmentActuals.GetArrayLength()); Assert.Equal(2, materialActuals.GetArrayLength()); Assert.All(equipmentActuals.EnumerateArray(), e => { Assert.Equal(JsonValueKind.String, e.GetProperty("EquipmentUse").ValueKind); Assert.Equal("consumable", e.GetProperty("EquipmentUse").GetString()); Assert.Equal(JsonValueKind.String, e.GetProperty("Quantity").ValueKind); }); Assert.All(materialActuals.EnumerateArray(), e => { Assert.Equal(JsonValueKind.String, e.GetProperty("MaterialClassID").ValueKind); Assert.True(e.GetProperty("MaterialClassID").TryGetGuid(out _)); Assert.Equal(JsonValueKind.String, e.GetProperty("MaterialUse").ValueKind); Assert.Equal("consumable", e.GetProperty("MaterialUse").GetString()); Assert.Equal(JsonValueKind.String, e.GetProperty("Quantity").ValueKind); }); extensionObject = jobState.GetProperty("Body"); Assert.Equal(3015, extensionObject.GetProperty("TypeId").GetProperty("Id").GetInt32()); Assert.Equal(2, extensionObject.GetProperty("TypeId").GetProperty("Namespace").GetInt32()); body = extensionObject.GetProperty("Body"); var state = body.GetProperty("State"); Assert.Equal(JsonValueKind.Array, state.ValueKind); Assert.Equal(3, state.GetArrayLength()); Assert.All(state.EnumerateArray(), e => { Assert.Equal(JsonValueKind.Array, e.GetProperty("BrowsePath").GetProperty("Elements").ValueKind); Assert.True(e.GetProperty("StateNumber").TryGetInt32(out _)); Assert.Equal(JsonValueKind.String, e.GetProperty("StateText").GetProperty("Text").ValueKind); Assert.Equal("en-US", e.GetProperty("StateText").GetProperty("Locale").GetString()); }); }); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/Plc/NodeServicesTests1.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.Plc { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; public sealed class NodeServicesTests1 : IClassFixture, IClassFixture { public NodeServicesTests1(PlcServer server, PublisherModuleFixture module) { _server = server; _module = module; } private SimulatorNodesTests GetTests() { return new SimulatorNodesTests(_server, _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly PlcServer _server; private readonly PublisherModuleFixture _module; [Fact] public Task AlternatingBooleanTelemetryChangesWithPeriodAsync() { return GetTests().AlternatingBooleanTelemetryChangesWithPeriodAsync(); } [Fact] public Task BadNodeHasAlternatingStatusCodeAsync() { return GetTests().BadNodeHasAlternatingStatusCodeAsync(); } [Fact] public Task FastLimitNumberOfUpdatesStopsUpdatingAfterLimitAsync() { return GetTests().FastLimitNumberOfUpdatesStopsUpdatingAfterLimitAsync(); } [Fact] public Task FastUIntScalar1TelemetryChangesWithPeriodAsync() { return GetTests().FastUIntScalar1TelemetryChangesWithPeriodAsync(); } [Fact] public Task NegativeTrendDataNodeHasValueWithTrendAsync() { return GetTests().NegativeTrendDataNodeHasValueWithTrendAsync(); } [Fact] public Task NegativeTrendDataTelemetryChangesWithPeriodAsync() { return GetTests().NegativeTrendDataTelemetryChangesWithPeriodAsync(); } [Fact] public Task PositiveTrendDataNodeHasValueWithTrendAsync() { return GetTests().PositiveTrendDataNodeHasValueWithTrendAsync(); } [Fact] public Task PositiveTrendDataTelemetryChangesWithPeriodAsync() { return GetTests().PositiveTrendDataTelemetryChangesWithPeriodAsync(); } [Fact] public Task RandomSignedInt32TelemetryChangesWithPeriodAsync() { return GetTests().RandomSignedInt32TelemetryChangesWithPeriodAsync(); } [Fact] public Task RandomUnsignedInt32TelemetryChangesWithPeriodAsync() { return GetTests().RandomUnsignedInt32TelemetryChangesWithPeriodAsync(); } [Fact] public Task SlowLimitNumberOfUpdatesStopsUpdatingAfterLimitAsync() { return GetTests().SlowLimitNumberOfUpdatesStopsUpdatingAfterLimitAsync(); } [Fact] public Task SlowUIntScalar1TelemetryChangesWithPeriodAsync() { return GetTests().SlowUIntScalar1TelemetryChangesWithPeriodAsync(); } [Fact] public Task TelemetryContainsOutlierInDipDataAsync() { return GetTests().TelemetryContainsOutlierInDipDataAsync(); } [Fact] public Task TelemetryContainsOutlierInSpikeDataAsync() { return GetTests().TelemetryContainsOutlierInSpikeDataAsync(); } [Fact] public Task TelemetryFastNodeTestAsync() { return GetTests().TelemetryFastNodeTestAsync(); } [Fact] public Task TelemetryStepUpTestAsync() { return GetTests().TelemetryStepUpTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/Plc/NodeServicesTests2.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.Plc { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; public sealed class NodeServicesTests2 : IClassFixture, IClassFixture { public NodeServicesTests2(PlcServer server, PublisherModuleFixture module) { _server = server; _module = module; } private PlcModelComplexTypeTests GetTests() { return new PlcModelComplexTypeTests(_server, _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly PlcServer _server; private readonly PublisherModuleFixture _module; [Fact] public Task PlcModelHeaterTestsAsync() { return GetTests().PlcModelHeaterTestsAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/ReferenceServer/AdvancedPubSubIntegrationTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.ReferenceServer { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Json.More; using System; using System.Linq; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public class AdvancedPubSubIntegrationTests : PublisherIntegrationTestBase { private readonly ITestOutputHelper _output; public AdvancedPubSubIntegrationTests(ITestOutputHelper output) : base(output) { _output = output; } [Fact] public async Task RestartServerTestAsync() { var server = new ReferenceServer(); EndpointUrl = server.EndpointUrl; const string name = nameof(RestartServerTestAsync); StartPublisher(name, "./Resources/Fixedvalue.json", arguments: ["--mm=PubSub", "--dm=false"], keepAliveInterval: 1); try { // Arrange // Act var (metadata, messages) = await WaitForMessagesAndMetadataAsync(TimeSpan.FromMinutes(2), 1, messageType: "ua-data"); // Assert var message = Assert.Single(messages).Message; AssertFixedValueMessage(message); Assert.NotNull(metadata); await server.RestartAsync(WaitUntilDisconnectedAsync); _output.WriteLine("Restarted server"); (metadata, messages) = await WaitForMessagesAndMetadataAsync(TimeSpan.FromMinutes(2), 1, messageType: "ua-data"); message = Assert.Single(messages).Message; AssertFixedValueMessage(message); // When we recreated the session we did not handle new metadata but now that we create we do. // Assert.Null(metadata); Assert.NotNull(metadata); } finally { server.Dispose(); await StopPublisherAsync(); } } [Fact] public async Task RestartServerWithHeartbeatTestAsync() { var server = new ReferenceServer(); EndpointUrl = server.EndpointUrl; const string name = nameof(RestartServerWithHeartbeatTestAsync); StartPublisher(name, "./Resources/Heartbeat2.json", arguments: ["--mm=PubSub", "--dm=false", "--bs=1"], keepAliveInterval: 1); try { // Arrange // Act var (metadata, messages) = await WaitForMessagesAndMetadataAsync(TimeSpan.FromMinutes(2), 1, messageType: "ua-data"); // Assert var message = Assert.Single(messages).Message; Assert.NotNull(metadata); await server.RestartAsync(WaitUntilDisconnectedAsync); _output.WriteLine("Restarted server"); (metadata, messages) = await WaitForMessagesAndMetadataAsync(TimeSpan.FromSeconds(10), 1000, messageType: "ua-data"); (metadata, messages) = await WaitForMessagesAndMetadataAsync(TimeSpan.FromSeconds(10), 1, messageType: "ua-data"); message = Assert.Single(messages).Message; _output.WriteLine(message.ToJsonString()); var output = message.GetProperty("Messages")[0].GetProperty("Payload").GetProperty("Output"); Assert.NotEqual(JsonValueKind.Null, output.ValueKind); Assert.InRange(output.GetProperty("Value").GetDouble(), double.MinValue, double.MaxValue); } finally { server.Dispose(); await StopPublisherAsync(); } } [Fact] public async Task RestartServerWithCyclicReadTestAsync() { var server = new ReferenceServer(); EndpointUrl = server.EndpointUrl; const string name = nameof(RestartServerWithCyclicReadTestAsync); StartPublisher(name, "./Resources/CyclicRead.json", arguments: ["--mm=PubSub", "--dm=false"], keepAliveInterval: 1); try { // Arrange // Act var (metadata, messages) = await WaitForMessagesAndMetadataAsync(TimeSpan.FromMinutes(2), 1, messageType: "ua-data"); // Assert var message = Assert.Single(messages).Message; Assert.NotNull(metadata); await server.RestartAsync(WaitUntilDisconnectedAsync); _output.WriteLine("Restarted server"); (metadata, messages) = await WaitForMessagesAndMetadataAsync(TimeSpan.FromSeconds(10), 1000, messageType: "ua-data"); (metadata, messages) = await WaitForMessagesAndMetadataAsync(TimeSpan.FromMinutes(2), 1, messageType: "ua-data"); message = Assert.Single(messages).Message; } finally { server.Dispose(); await StopPublisherAsync(); } } [Fact] public async Task SwitchServerWithSameWriterGroupTestAsync() { var server = new ReferenceServer(); EndpointUrl = server.EndpointUrl; const string name = nameof(SwitchServerWithSameWriterGroupTestAsync); StartPublisher(name, "./Resources/DataItems.json", arguments: ["--mm=PubSub", "--dm=false"]); try { // Arrange // Act var (metadata, messages) = await WaitForMessagesAndMetadataAsync(TimeSpan.FromMinutes(2), 1, messageType: "ua-data"); // Assert var message = Assert.Single(messages).Message; var output = message.GetProperty("Messages")[0].GetProperty("Payload").GetProperty("Output"); Assert.NotEqual(JsonValueKind.Null, output.ValueKind); Assert.InRange(output.GetProperty("Value").GetDouble(), double.MinValue, double.MaxValue); Assert.NotNull(metadata); var diagnostics = await PublisherApi.GetDiagnosticInfoAsync(); var diag = Assert.Single(diagnostics); Assert.Equal(name, diag.Endpoint.DataSetWriterGroup); // Switch to new server var old = server; server = new ReferenceServer(); EndpointUrl = server.EndpointUrl; old.Dispose(); // Point to new server WritePublishedNodes(name, "./Resources/DataItems.json"); // Now we should have torn down the other subscription (metadata, messages) = await WaitForMessagesAndMetadataAsync(TimeSpan.FromMinutes(2), 1, messageType: "ua-data"); message = Assert.Single(messages).Message; _output.WriteLine(message.ToJsonString()); output = message.GetProperty("Messages")[0].GetProperty("Payload").GetProperty("Output"); Assert.NotEqual(JsonValueKind.Null, output.ValueKind); Assert.InRange(output.GetProperty("Value").GetDouble(), double.MinValue, double.MaxValue); diagnostics = await PublisherApi.GetDiagnosticInfoAsync(); for (var i = 0; i < 10 && diagnostics.Count == 0; i++) { _output.WriteLine($"######### {i}: Failed to get diagnosticsinfo."); await Task.Delay(1000); diagnostics = await PublisherApi.GetDiagnosticInfoAsync(); } diag = Assert.Single(diagnostics); Assert.Equal(name, diag.Endpoint.DataSetWriterGroup); } finally { server.Dispose(); await StopPublisherAsync(); } } [Fact] public async Task SwitchServerWithDifferentWriterGroupTestAsync() { var server = new ReferenceServer(); EndpointUrl = server.EndpointUrl; const string name = nameof(SwitchServerWithDifferentWriterGroupTestAsync); StartPublisher(name, "./Resources/DataItems2.json", arguments: ["--mm=PubSub", "--dm=false"]); try { // Arrange // Act var (metadata, messages) = await WaitForMessagesAndMetadataAsync(TimeSpan.FromMinutes(2), 1, messageType: "ua-data"); // Assert var message = Assert.Single(messages).Message; var output = message.GetProperty("Messages")[0].GetProperty("Payload").GetProperty("Output2"); Assert.NotEqual(JsonValueKind.Null, output.ValueKind); Assert.InRange(output.GetProperty("Value").GetDouble(), double.MinValue, double.MaxValue); Assert.NotNull(metadata); var diagnostics = await PublisherApi.GetDiagnosticInfoAsync(); var diag = Assert.Single(diagnostics); Assert.Equal(name, diag.Endpoint.DataSetWriterGroup); // Switch to new server var old = server; server = new ReferenceServer(); EndpointUrl = server.EndpointUrl; old.Dispose(); // Point to new server const string name2 = nameof(SwitchServerWithDifferentWriterGroupTestAsync) + "new"; WritePublishedNodes(name2, "./Resources/DataItems2.json"); // Now we should have torn down the other subscription (metadata, messages) = await WaitForMessagesAndMetadataAsync(TimeSpan.FromMinutes(2), 1, predicate: WaitUntilOutput2, messageType: "ua-data"); message = Assert.Single(messages).Message; _output.WriteLine(message.ToJsonString()); output = message.GetProperty("Messages")[0].GetProperty("Payload").GetProperty("Output2"); Assert.NotEqual(JsonValueKind.Null, output.ValueKind); Assert.InRange(output.GetProperty("Value").GetDouble(), double.MinValue, double.MaxValue); diagnostics = await PublisherApi.GetDiagnosticInfoAsync(); for (var i = 0; i < 10 && (diagnostics.Count != 1 || diagnostics[0].Endpoint.DataSetWriterGroup != name2); i++) { _output.WriteLine($"######### {i}: Failed to get diagnosticsinfo."); await Task.Delay(1000); diagnostics = await PublisherApi.GetDiagnosticInfoAsync(); } diag = Assert.Single(diagnostics); Assert.Equal(name2, diag.Endpoint.DataSetWriterGroup); } finally { await StopPublisherAsync(); server.Dispose(); } } [Theory] [InlineData(false, 100)] [InlineData(true, 100)] [InlineData(false, 1)] [InlineData(true, 1)] public async Task AddNodeToDataSetWriterGroupWithNodeUsingDeviceMethodAsync(bool differentPublishingInterval, int maxMonitoredItems) { var server = new ReferenceServer(); EndpointUrl = server.EndpointUrl; const string name = nameof(AddNodeToDataSetWriterGroupWithNodeUsingDeviceMethodAsync); var testInput1 = GetEndpointsFromFile(name, "./Resources/DataItems.json"); var testInput2 = GetEndpointsFromFile(name, "./Resources/DataItems2.json"); if (!differentPublishingInterval) { // Set both to the same so that there is a single writer instead of 2 testInput2[0].OpcNodes[0].OpcPublishingInterval = testInput1[0].OpcNodes[0].OpcPublishingInterval; } StartPublisher(name, arguments: ["--mm=PubSub", "--dm=false", "--xmi=" + maxMonitoredItems]); try { var endpoints = await PublisherApi.GetConfiguredEndpointsAsync(); Assert.Empty(endpoints.Endpoints); var result = await PublisherApi.PublishNodesAsync(testInput1[0]); Assert.NotNull(result); var (metadata, messages) = await WaitForMessagesAndMetadataAsync(TimeSpan.FromMinutes(2), 1, messageType: "ua-data"); var message = Assert.Single(messages).Message; var output = message.GetProperty("Messages")[0].GetProperty("Payload").GetProperty("Output"); Assert.NotEqual(JsonValueKind.Null, output.ValueKind); Assert.InRange(output.GetProperty("Value").GetDouble(), double.MinValue, double.MaxValue); Assert.NotNull(metadata); endpoints = await PublisherApi.GetConfiguredEndpointsAsync(); var e = Assert.Single(endpoints.Endpoints); var nodes = await PublisherApi.GetConfiguredNodesOnEndpointAsync(e); var n = Assert.Single(nodes.OpcNodes); Assert.Equal(testInput1[0].OpcNodes[0].Id, n.Id); // Add another node result = await PublisherApi.PublishNodesAsync(testInput2[0]); Assert.NotNull(result); endpoints = await PublisherApi.GetConfiguredEndpointsAsync(); e = Assert.Single(endpoints.Endpoints); nodes = await PublisherApi.GetConfiguredNodesOnEndpointAsync(e); Assert.Equal(2, nodes.OpcNodes.Count); Assert.Contains(testInput1[0].OpcNodes[0].Id, nodes.OpcNodes.Select(e => e.Id)); Assert.Contains(testInput2[0].OpcNodes[0].Id, nodes.OpcNodes.Select(e => e.Id)); (metadata, messages) = await WaitForMessagesAndMetadataAsync(TimeSpan.FromMinutes(2), 1, predicate: WaitUntilOutput2, messageType: "ua-data"); var diagnostics = await PublisherApi.GetDiagnosticInfoAsync(); var diag = Assert.Single(diagnostics); Assert.Equal(0, diag.MonitoredOpcNodesFailedCount); Assert.Equal(2, diag.MonitoredOpcNodesSucceededCount); // Remove endpoint result = await PublisherApi.UnpublishNodesAsync(e); Assert.NotNull(result); endpoints = await PublisherApi.GetConfiguredEndpointsAsync(); Assert.Empty(endpoints.Endpoints); } finally { await StopPublisherAsync(); server.Dispose(); } } [Fact] public async Task SwitchServerWithDifferentDataTestAsync() { var server = new ReferenceServer(); EndpointUrl = server.EndpointUrl; const string name = nameof(SwitchServerWithDifferentDataTestAsync); StartPublisher(name, "./Resources/DataItems.json", arguments: ["--mm=PubSub", "--dm=false"]); try { // Arrange // Act var (metadata, messages) = await WaitForMessagesAndMetadataAsync(TimeSpan.FromMinutes(2), 1, messageType: "ua-data"); // Assert var message = Assert.Single(messages).Message; var output = message.GetProperty("Messages")[0].GetProperty("Payload").GetProperty("Output"); Assert.NotEqual(JsonValueKind.Null, output.ValueKind); Assert.InRange(output.GetProperty("Value").GetDouble(), double.MinValue, double.MaxValue); Assert.NotNull(metadata); var diagnostics = await PublisherApi.GetDiagnosticInfoAsync(); var diag = Assert.Single(diagnostics); Assert.Equal(name, diag.Endpoint.DataSetWriterGroup); WritePublishedNodes(name, "./Resources/empty_pn.json"); for (var i = 0; i < 10 && diagnostics.Count != 0; i++) { diagnostics = await PublisherApi.GetDiagnosticInfoAsync(); await Task.Delay(1000); } Assert.Empty(diagnostics); // Switch to different server var old = server; server = new ReferenceServer(); EndpointUrl = server.EndpointUrl; old.Dispose(); // Point to new server WritePublishedNodes(name, "./Resources/DataItems2.json"); // Now we should have torn down the other subscription (metadata, messages) = await WaitForMessagesAndMetadataAsync(TimeSpan.FromMinutes(2), 1, predicate: WaitUntilOutput2, messageType: "ua-data"); message = Assert.Single(messages).Message; _output.WriteLine(message.ToJsonString()); output = message.GetProperty("Messages")[0].GetProperty("Payload").GetProperty("Output2"); Assert.NotEqual(JsonValueKind.Null, output.ValueKind); Assert.InRange(output.GetProperty("Value").GetDouble(), double.MinValue, double.MaxValue); Assert.NotNull(metadata); diagnostics = await PublisherApi.GetDiagnosticInfoAsync(); diag = Assert.Single(diagnostics); Assert.Equal(name, diag.Endpoint.DataSetWriterGroup); } finally { server.Dispose(); await StopPublisherAsync(); } } [Fact] public async Task SwitchSecuritySettingsTestAsync() { var server = new ReferenceServer(); EndpointUrl = server.EndpointUrl; const string name = nameof(SwitchSecuritySettingsTestAsync); StartPublisher(name, "./Resources/Fixedvalue.json", arguments: ["--mm=PubSub", "--dm=false", "--aa"], securityMode: Models.SecurityMode.SignAndEncrypt); try { // Arrange // Act var (metadata, messages) = await WaitForMessagesAndMetadataAsync(TimeSpan.FromMinutes(2), 1, messageType: "ua-data"); // Assert var message = Assert.Single(messages).Message; AssertFixedValueMessage(message); Assert.NotNull(metadata); var diagnostics = await PublisherApi.GetDiagnosticInfoAsync(); var diag = Assert.Single(diagnostics); Assert.Equal(Models.SecurityMode.SignAndEncrypt, diag.Endpoint.EndpointSecurityMode); WritePublishedNodes(name, "./Resources/Fixedvalue.json", securityMode: Models.SecurityMode.None); (metadata, messages) = await WaitForMessagesAndMetadataAsync(TimeSpan.FromMinutes(2), 1, messageType: "ua-data"); // Assert message = Assert.Single(messages).Message; AssertFixedValueMessage(message); Assert.NotNull(metadata); diagnostics = await PublisherApi.GetDiagnosticInfoAsync(); diag = Assert.Single(diagnostics); Assert.Null(diag.Endpoint.EndpointSecurityMode); WritePublishedNodes(name, "./Resources/Fixedvalue.json", securityMode: Models.SecurityMode.Sign); (metadata, messages) = await WaitForMessagesAndMetadataAsync(TimeSpan.FromMinutes(2), 1, messageType: "ua-data"); // Assert message = Assert.Single(messages).Message; AssertFixedValueMessage(message); Assert.NotNull(metadata); diagnostics = await PublisherApi.GetDiagnosticInfoAsync(); diag = Assert.Single(diagnostics); Assert.Equal(Models.SecurityMode.Sign, diag.Endpoint.EndpointSecurityMode); } finally { server.Dispose(); await StopPublisherAsync(); } } [Fact] public async Task RestartConfigurationTestAsync() { using var server = new ReferenceServer(); EndpointUrl = server.EndpointUrl; for (var cycles = 0; cycles < 3; cycles++) { const string name = nameof(RestartConfigurationTestAsync); StartPublisher(name, "./Resources/DataItems.json", arguments: ["--mm=PubSub", "--dm=false"]); try { // Arrange // Act await WaitForMessagesAndMetadataAsync(TimeSpan.FromSeconds(5), 1, messageType: "ua-data"); const string name2 = nameof(RestartConfigurationTestAsync) + "new"; WritePublishedNodes(name2, "./Resources/DataItems2.json"); var diagnostics = await PublisherApi.GetDiagnosticInfoAsync(); for (var i = 0; i < 60 && (diagnostics.Count != 1 || diagnostics[0].Endpoint.DataSetWriterGroup != name2); i++) { _output.WriteLine($"######### {i}: Failed to get diagnosticsinfo."); await Task.Delay(500); diagnostics = await PublisherApi.GetDiagnosticInfoAsync(); } var diag = Assert.Single(diagnostics); Assert.Equal(name2, diag.Endpoint.DataSetWriterGroup); } finally { await StopPublisherAsync(); } } } internal static JsonElement WaitUntilOutput2(JsonElement jsonElement) { var messages = jsonElement.GetProperty("Messages"); if (messages.ValueKind == JsonValueKind.Array) { var element = messages.EnumerateArray().FirstOrDefault(); if (element.GetProperty("Payload").TryGetProperty("Output2", out _)) { return jsonElement; } } return default; } private async Task WaitUntilDisconnectedAsync() { using var cts = new CancellationTokenSource(60000); while (true) { cts.Token.ThrowIfCancellationRequested(); var diagnostics = await PublisherApi.GetDiagnosticInfoAsync(cts.Token); var diag = Assert.Single(diagnostics); if (!diag.OpcEndpointConnected) { _output.WriteLine("Disconnected!"); break; } await Task.Delay(1000, cts.Token); } } internal static void AssertFixedValueMessage(JsonElement message) { var m = message.GetProperty("Messages")[0]; var type = m.GetProperty("MessageType").GetString(); // TODO Assert.Equal("ua-keyframe", type); var payload1 = m.GetProperty("Payload"); var items1 = new[] { payload1.GetProperty("LocaleIdArray"), payload1.GetProperty("ServerArray"), payload1.GetProperty("NamespaceArray") }; Assert.All(items1, item => Assert.Equal(JsonValueKind.Array, item.GetProperty("Value").ValueKind)); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/ReferenceServer/BasicPubSubIntegrationTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.ReferenceServer { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using FluentAssertions; using Json.More; using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text.Json; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public class BasicPubSubIntegrationTests : PublisherIntegrationTestBase { internal const string EventId = "EventId"; internal const string Message = "Message"; internal const string CycleIdExpanded = "nsu=http://opcfoundation.org/SimpleEvents;CycleId"; internal const string CurrentStepExpanded = "nsu=http://opcfoundation.org/SimpleEvents;CurrentStep"; internal const string CycleIdUri = "http://opcfoundation.org/SimpleEvents#CycleId"; internal const string CurrentStepUri = "http://opcfoundation.org/SimpleEvents#CurrentStep"; private readonly ITestOutputHelper _output; private readonly ReferenceServer _fixture; public BasicPubSubIntegrationTests(ITestOutputHelper output) : base(output) { _output = output; _fixture = new ReferenceServer(); EndpointUrl = _fixture.EndpointUrl; } protected override void Dispose(bool disposing) { base.Dispose(disposing); if (disposing) { _fixture.Dispose(); } } [Fact] public async Task CanSendDataItemToIoTHubTestAsync() { // Arrange // Act var (metadata, messages) = await ProcessMessagesAndMetadataAsync( nameof(CanSendDataItemToIoTHubTestAsync), "./Resources/DataItems.json", messageType: "ua-data", arguments: ["--mm=PubSub", "--dm=false"]); // Assert var message = Assert.Single(messages).Message; var output = message.GetProperty("Messages")[0].GetProperty("Payload").GetProperty("Output"); Assert.NotEqual(JsonValueKind.Null, output.ValueKind); Assert.InRange(output.GetProperty("Value").GetDouble(), double.MinValue, double.MaxValue); Assert.NotNull(metadata); } [Fact] public async Task CanSendModelChangeEventsToIoTHubTestAsync() { // Arrange // Act var messages = await ProcessMessagesAsync(nameof(CanSendModelChangeEventsToIoTHubTestAsync), "./Resources/ModelChanges.json", TimeSpan.FromMinutes(2), 5, messageType: "ua-data", arguments: ["--mm=PubSub", "--dm=false"]); // Assert Assert.NotEmpty(messages); var payload1 = messages[0].Message.GetProperty("Messages")[0].GetProperty("Payload"); _output.WriteLine(payload1.ToJsonString()); Assert.NotEqual(JsonValueKind.Null, payload1.ValueKind); Assert.True(Guid.TryParse(payload1.GetProperty("EventId").GetProperty("Value").GetString(), out _)); Assert.Equal("http://www.microsoft.com/opc-publisher#s=ReferenceChange", payload1.GetProperty("EventType").GetProperty("Value").GetString()); Assert.True(DateTime.TryParse(payload1.GetProperty("Time").GetProperty("Value").GetString(), out _)); Assert.True(payload1.GetProperty("Change").GetProperty("Value").GetProperty("IsForward").GetBoolean()); // NO order anymore: // Assert.Equal("i=84", payload1.GetProperty("SourceNode").GetProperty("Value").GetString()); // Assert.Equal("Objects", payload1.GetProperty("Change").GetProperty("Value").GetProperty("DisplayName").GetString()); var payload2 = messages[1].Message.GetProperty("Messages")[0].GetProperty("Payload"); _output.WriteLine(payload2.ToJsonString()); Assert.NotEqual(JsonValueKind.Null, payload1.ValueKind); Assert.True(Guid.TryParse(payload2.GetProperty("EventId").GetProperty("Value").GetString(), out _)); Assert.Equal("http://www.microsoft.com/opc-publisher#s=NodeChange", payload2.GetProperty("EventType").GetProperty("Value").GetString()); Assert.True(DateTime.TryParse(payload2.GetProperty("Time").GetProperty("Value").GetString(), out _)); // NO order anymore: // Assert.Equal("i=85", payload2.GetProperty("SourceNode").GetProperty("Value").GetString()); // Assert.Equal("Objects", payload2.GetProperty("Change").GetProperty("Value").GetProperty("DisplayName").GetString()); // TODO: currently metadata is sent later // Assert.NotNull(metadata); } [Fact] public async Task CanSendDataItemButNotMetaDataWhenMetaDataIsDisabledTestAsync() { // Arrange // Act var (metadata, messages) = await ProcessMessagesAndMetadataAsync( nameof(CanSendDataItemButNotMetaDataWhenMetaDataIsDisabledTestAsync), "./Resources/DataItems.json", arguments: ["-c", "--dm", "--mm=DataSetMessages"]); // Assert var message = Assert.Single(messages).Message; var output = message.GetProperty("Payload").GetProperty("Output"); Assert.NotEqual(JsonValueKind.Null, output.ValueKind); Assert.InRange(output.GetProperty("Value").GetDouble(), double.MinValue, double.MaxValue); Assert.Null(metadata); } [Fact] public async Task CanSendDataItemButNotMetaDataWhenComplexTypeSystemIsDisabledTestAsync() { // Arrange // Act var (metadata, messages) = await ProcessMessagesAndMetadataAsync( nameof(CanSendDataItemButNotMetaDataWhenComplexTypeSystemIsDisabledTestAsync), "./Resources/DataItems.json", arguments: ["-c", "--dct", "--mm=DataSetMessages"]); // Assert var message = Assert.Single(messages).Message; var output = message.GetProperty("Payload").GetProperty("Output"); Assert.NotEqual(JsonValueKind.Null, output.ValueKind); Assert.InRange(output.GetProperty("Value").GetDouble(), double.MinValue, double.MaxValue); Assert.Null(metadata); } [Fact] public async Task CanSendDataItemAsDataSetMessagesToIoTHubWithCompliantEncodingTestAsync() { // Arrange // Act var (metadata, messages) = await ProcessMessagesAndMetadataAsync( nameof(CanSendDataItemAsDataSetMessagesToIoTHubWithCompliantEncodingTestAsync), "./Resources/DataItems.json", messageType: "ua-deltaframe", arguments: ["-c", "--mm=DataSetMessages"]); // Assert var message = Assert.Single(messages).Message; var output = message.GetProperty("Payload").GetProperty("Output"); Assert.NotEqual(JsonValueKind.Null, output.ValueKind); Assert.InRange(output.GetProperty("Value").GetDouble(), double.MinValue, double.MaxValue); Assert.NotNull(metadata); } [Fact] public async Task CanSendDataItemAsRawDataSetsToIoTHubWithCompliantEncodingTestAsync() { // Arrange // Act var (metadata, messages) = await ProcessMessagesAndMetadataAsync( nameof(CanSendDataItemAsRawDataSetsToIoTHubWithCompliantEncodingTestAsync), "./Resources/DataItems.json", messageType: "ua-deltaframe", arguments: ["-c", "--dm=False", "--mm=RawDataSets"]); // Assert var output = Assert.Single(messages).Message; Assert.NotEqual(JsonValueKind.Null, output.ValueKind); Assert.InRange(output.GetProperty("Output").GetDouble(), double.MinValue, double.MaxValue); // Explicitely enabled metadata despite messaging profile Assert.NotNull(metadata); } [Fact] public async Task CanEncodeWithoutReversibleEncodingTestAsync() { // Arrange // Act var (metadata, result) = await ProcessMessagesAndMetadataAsync( nameof(CanEncodeWithoutReversibleEncodingTestAsync), "./Resources/SimpleEvents.json", messageType: "ua-data", arguments: ["--mm=PubSub", "--me=Json", "--dm=false"] ); Assert.Single(result); var messages = result .SelectMany(x => x.Message.GetProperty("Messages").EnumerateArray()) .ToArray(); // Assert Assert.NotEmpty(messages); Assert.All(messages, m => { var value = m.GetProperty("Payload"); // Variant encoding is the default var eventId = value.GetProperty(EventId).GetProperty("Value"); var message = value.GetProperty(Message).GetProperty("Value"); var cycleId = value.GetProperty(CycleIdUri).GetProperty("Value"); var currentStep = value.GetProperty(CurrentStepUri).GetProperty("Value"); Assert.Equal(JsonValueKind.String, eventId.ValueKind); Assert.Equal(JsonValueKind.String, message.ValueKind); Assert.Equal(JsonValueKind.String, cycleId.ValueKind); Assert.Equal(JsonValueKind.String, currentStep.GetProperty("Name").ValueKind); Assert.Equal(JsonValueKind.Number, currentStep.GetProperty("Duration").ValueKind); }); AssertSimpleEventsMetadata(metadata); } [Fact] public async Task CanEncodeWithReversibleEncodingTestAsync() { // Arrange // Act var (metadata, result) = await ProcessMessagesAndMetadataAsync( nameof(CanEncodeWithReversibleEncodingTestAsync), "./Resources/SimpleEvents.json", TimeSpan.FromMinutes(2), 4, messageType: "ua-data", arguments: ["--mm=PubSub", "--me=JsonReversible", "--dm=false"] ); var messages = result .SelectMany(x => x.Message.GetProperty("Messages").EnumerateArray()) .ToArray(); // Assert Assert.NotEmpty(messages); Assert.All(messages, m => { var body = m.GetProperty("Payload"); var eventId = body.GetProperty(EventId).GetProperty("Value"); Assert.Equal("ByteString", eventId.GetProperty("Type").GetString()); Assert.Equal(JsonValueKind.String, eventId.GetProperty("Body").ValueKind); var message = body.GetProperty(Message).GetProperty("Value"); Assert.Equal("LocalizedText", message.GetProperty("Type").GetString()); Assert.Equal(JsonValueKind.String, message.GetProperty("Body").GetProperty("Text").ValueKind); Assert.Equal("en-US", message.GetProperty("Body").GetProperty("Locale").GetString()); var cycleId = body.GetProperty(CycleIdUri).GetProperty("Value"); Assert.Equal("String", cycleId.GetProperty("Type").GetString()); Assert.Equal(JsonValueKind.String, cycleId.GetProperty("Body").ValueKind); var currentStep = body.GetProperty(CurrentStepUri).GetProperty("Value"); body = currentStep.GetProperty("Body"); Assert.Equal("ExtensionObject", currentStep.GetProperty("Type").GetString()); Assert.Equal("http://opcfoundation.org/SimpleEvents#i=183", body.GetProperty("TypeId").GetString()); Assert.Equal("Json", body.GetProperty("Encoding").GetString()); Assert.Equal(JsonValueKind.String, body.GetProperty("Body").GetProperty("Name").ValueKind); Assert.Equal(JsonValueKind.Number, body.GetProperty("Body").GetProperty("Duration").ValueKind); }); AssertSimpleEventsMetadata(metadata); } [Fact] public async Task CanEncodeEventWithCompliantEncodingTestAsync() { // Arrange // Act var (metadata, result) = await ProcessMessagesAndMetadataAsync( nameof(CanEncodeEventWithCompliantEncodingTestAsync), "./Resources/SimpleEvents.json", messageType: "ua-data", arguments: ["-c", "--mm=PubSub", "--me=Json"]); Assert.Single(result); var messages = result .SelectMany(x => x.Message.GetProperty("Messages").EnumerateArray()) .ToArray(); // Assert Assert.NotEmpty(messages); Assert.All(messages, m => { var value = m.GetProperty("Payload"); // Variant encoding is the default var eventId = value.GetProperty(EventId).GetProperty("Value"); var message = value.GetProperty(Message).GetProperty("Value"); var cycleId = value.GetProperty(CycleIdExpanded).GetProperty("Value"); var currentStep = value.GetProperty(CurrentStepExpanded).GetProperty("Value"); Assert.Equal(JsonValueKind.String, eventId.ValueKind); Assert.Equal(JsonValueKind.String, message.ValueKind); Assert.Equal(JsonValueKind.String, cycleId.ValueKind); Assert.Equal(JsonValueKind.String, currentStep.GetProperty("Name").ValueKind); Assert.Equal(JsonValueKind.Number, currentStep.GetProperty("Duration").ValueKind); }); AssertCompliantSimpleEventsMetadata(metadata); } [Fact] public async Task CanEncodeWithReversibleEncodingAndWithCompliantEncodingTestAsync() { // Arrange // Act var (metadata, result) = await ProcessMessagesAndMetadataAsync( nameof(CanEncodeWithReversibleEncodingAndWithCompliantEncodingTestAsync), "./Resources/SimpleEvents.json", TimeSpan.FromMinutes(2), 4, messageType: "ua-data", arguments: ["-c", "--mm=PubSub", "--me=JsonReversible"]); var messages = result .SelectMany(x => x.Message.GetProperty("Messages").EnumerateArray()) .ToArray(); // Assert Assert.NotEmpty(messages); Assert.All(messages, m => { var body = m.GetProperty("Payload"); var eventId = body.GetProperty(EventId).GetProperty("Value"); Assert.Equal(15, eventId.GetProperty("Type").GetInt32()); Assert.Equal(JsonValueKind.String, eventId.GetProperty("Body").ValueKind); var message = body.GetProperty(Message).GetProperty("Value"); Assert.Equal(21, message.GetProperty("Type").GetInt32()); Assert.Equal(JsonValueKind.String, message.GetProperty("Body").GetProperty("Text").ValueKind); Assert.Equal("en-US", message.GetProperty("Body").GetProperty("Locale").GetString()); var cycleId = body.GetProperty(CycleIdExpanded).GetProperty("Value"); Assert.Equal(12, cycleId.GetProperty("Type").GetInt32()); Assert.Equal(JsonValueKind.String, cycleId.GetProperty("Body").ValueKind); var currentStep = body.GetProperty(CurrentStepExpanded).GetProperty("Value"); body = currentStep.GetProperty("Body"); Assert.Equal(22, currentStep.GetProperty("Type").GetInt32()); Assert.Equal(183, body.GetProperty("TypeId").GetProperty("Id").GetInt32()); Assert.Equal(JsonValueKind.String, body.GetProperty("Body").GetProperty("Name").ValueKind); Assert.Equal(JsonValueKind.Number, body.GetProperty("Body").GetProperty("Duration").ValueKind); }); AssertCompliantSimpleEventsMetadata(metadata); } [Fact] public async Task CanEncode2EventsWithCompliantEncodingTestAsync() { var dataSetWriterNames = new HashSet(); // Arrange // Act var (metadata, result) = await ProcessMessagesAndMetadataAsync( nameof(CanEncode2EventsWithCompliantEncodingTestAsync), "./Resources/SimpleEvents2.json", GetBothEvents, messageType: "ua-data", arguments: ["-c", "--mm=PubSub", "--me=Json"]); Assert.Single(result); var messages = result .SelectMany(x => x.Message.GetProperty("Messages").EnumerateArray()) .ToArray(); dataSetWriterNames.Select(d => d.Split('|')[1]) .Should().Contain(new[] { "CycleStarted", "Alarm" }); // Assert Assert.NotEmpty(messages); Assert.All(messages, m => { var value = m.GetProperty("Payload"); // Variant encoding is the default var eventId = value.GetProperty(EventId).GetProperty("Value"); var message = value.GetProperty(Message).GetProperty("Value"); var cycleId = value.GetProperty(CycleIdExpanded).GetProperty("Value"); var currentStep = value.GetProperty(CurrentStepExpanded).GetProperty("Value"); Assert.Equal(JsonValueKind.String, eventId.ValueKind); Assert.Equal(JsonValueKind.String, message.ValueKind); Assert.Equal(JsonValueKind.String, cycleId.ValueKind); Assert.Equal(JsonValueKind.String, currentStep.GetProperty("Name").ValueKind); Assert.Equal(JsonValueKind.Number, currentStep.GetProperty("Duration").ValueKind); }); JsonElement GetBothEvents(JsonElement jsonElement) { var messages = jsonElement.GetProperty("Messages"); if (messages.ValueKind != JsonValueKind.Array) { return default; } var isAllCycleStarted = true; foreach (var element in messages.EnumerateArray()) { var dataSetWriterName = element.GetProperty("DataSetWriterName").GetString(); if (dataSetWriterName != null) { dataSetWriterNames.Add(dataSetWriterName); } if (!dataSetWriterName.EndsWith("|CycleStarted", StringComparison.Ordinal)) { isAllCycleStarted = false; } } return dataSetWriterNames.Count == 2 && isAllCycleStarted ? jsonElement : default; } } [Fact] public async Task CanSendPendingConditionsToIoTHubTestAsync() { // Arrange // Act var (metadata, messages) = await ProcessMessagesAndMetadataAsync( nameof(CanSendPendingConditionsToIoTHubTestAsync), "./Resources/PendingAlarms.json", GetAlarmCondition, messageType: "ua-data", arguments: ["--mm=PubSub", "--dm=False"]); // Assert Assert.NotEmpty(messages); var message = Assert.Single(messages).Message; _output.WriteLine(message.ToJsonString()); Assert.Equal(JsonValueKind.Object, message.ValueKind); Assert.True(message.GetProperty("Payload").GetProperty("Severity").GetProperty("Value").GetInt32() >= 100); Assert.NotNull(metadata); } [Fact] public async Task CanSendExtensionFieldsToIoTHubTestAsync() { // Arrange // Act var (metadata, result) = await ProcessMessagesAndMetadataAsync( nameof(CanSendExtensionFieldsToIoTHubTestAsync), "./Resources/ExtensionFields.json", messageType: "ua-data", arguments: ["--mm=FullNetworkMessages", "--dm=false"]); Assert.Single(result); var messages = result .SelectMany(x => x.Message.GetProperty("Messages").EnumerateArray()) .ToArray(); // Assert Assert.NotEmpty(messages); Assert.All(messages, m => { var payload = m.GetProperty("Payload"); Assert.False(payload.GetProperty("Important").GetProperty("Value").GetBoolean()); Assert.Equal(5, payload.GetProperty("AssetId").GetProperty("Value").GetInt16()); Assert.Equal("mm/sec", payload.GetProperty("EngineeringUnits").GetProperty("Value").GetString()); Assert.Equal(12.3465, payload.GetProperty("Variance").GetProperty("Value").GetDouble(), 6); Assert.NotEmpty(payload.GetProperty("EndpointUrl").GetProperty("Value").GetString()); Assert.NotEmpty(payload.GetProperty("ApplicationUri").GetProperty("Value").GetString()); }); Assert.NotNull(metadata); var metadataFields = metadata.Value.Message.GetProperty("MetaData").GetProperty("Fields"); Assert.Equal(JsonValueKind.Array, metadataFields.ValueKind); var fieldNames = metadataFields.EnumerateArray().Select(v => v.GetProperty("Name").GetString()).ToHashSet(); var expectedNames = new[] { "Output", "EndpointUrl", "ApplicationUri", "EngineeringUnits", "AssetId", "Important", "Variance" }; Assert.Equal(expectedNames.Length, fieldNames.Count); Assert.All(expectedNames, n => fieldNames.Contains(n)); } [Fact] public async Task CanSendKeyFramesWithExtensionFieldsToIoTHubTestAsync() { // Arrange // Act var (metadata, messages) = await ProcessMessagesAndMetadataAsync( nameof(CanSendDataItemToIoTHubTestAsync), "./Resources/KeyFrames.json", messageType: "ua-data", arguments: ["--mm=FullNetworkMessages", "--dm=false"]); // Assert var message = Assert.Single(messages).Message; var firstDataSet = message.GetProperty("Messages")[0]; Assert.Equal("ua-keyframe", firstDataSet.GetProperty("MessageType").GetString()); var payload = firstDataSet.GetProperty("Payload"); Assert.NotEqual(JsonValueKind.Null, payload.ValueKind); var time = payload.GetProperty("CurrentTime"); Assert.NotEqual(JsonValueKind.Null, time.ValueKind); Assert.True(time.GetProperty("Value").GetDateTime() < DateTime.UtcNow); Assert.False(payload.GetProperty("Important").GetProperty("Value").GetBoolean()); Assert.Equal(5, payload.GetProperty("AssetId").GetProperty("Value").GetInt16()); Assert.Equal("mm/sec", payload.GetProperty("EngineeringUnits").GetProperty("Value").GetString()); Assert.Equal(12.3465, payload.GetProperty("Variance").GetProperty("Value").GetDouble(), 6); Assert.NotNull(metadata); var metadataFields = metadata.Value.Message.GetProperty("MetaData").GetProperty("Fields"); Assert.Equal(JsonValueKind.Array, metadataFields.ValueKind); var fieldNames = metadataFields.EnumerateArray().Select(v => v.GetProperty("Name").GetString()).ToHashSet(); var expectedNames = new[] { "AssetId", "CurrentTime", "EngineeringUnits", "Important", "Variance" }; Assert.Equal(expectedNames.Length, fieldNames.Count); Assert.All(expectedNames, n => fieldNames.Contains(n)); } [Fact] public async Task CanSendFullAndCompliantNetworkMessageWithEndpointUrlAndApplicationUriToIoTHubTestAsync() { // Arrange // Act var (metadata, messages) = await ProcessMessagesAndMetadataAsync( nameof(CanSendDataItemToIoTHubTestAsync), "./Resources/DataItems.json", messageType: "ua-data", arguments: ["--mm=PubSub", "--fm=true", "--strict"]); // Assert var message = Assert.Single(messages).Message; var firstDataSet = message.GetProperty("Messages")[0]; var payload = firstDataSet.GetProperty("Payload"); Assert.NotEqual(JsonValueKind.Null, payload.ValueKind); var output = payload.GetProperty("Output"); Assert.NotEqual(JsonValueKind.Null, output.ValueKind); Assert.InRange(output.GetProperty("Value").GetDouble(), double.MinValue, double.MaxValue); var ep = payload.GetProperty("EndpointUrl").GetProperty("Value").GetString(); Assert.False(string.IsNullOrEmpty(ep)); var appuri = payload.GetProperty("ApplicationUri").GetProperty("Value").GetString(); Assert.False(string.IsNullOrEmpty(appuri)); Assert.NotNull(metadata); var fields = metadata.Value.Message.GetProperty("MetaData").GetProperty("Fields"); Assert.Equal(JsonValueKind.Array, fields.ValueKind); var fieldNames = fields.EnumerateArray().Select(v => v.GetProperty("Name").GetString()).ToList(); Assert.Equal(3, fieldNames.Count); Assert.Equal("Output", fieldNames[0]); Assert.Equal("EndpointUrl", fieldNames[1]); Assert.Equal("ApplicationUri", fieldNames[2]); } [Fact] public async Task CanSendKeyFramesWithExtensionFieldsToIoTHubTestJsonReversibleAsync() { // Arrange // Act var (metadata, messages) = await ProcessMessagesAndMetadataAsync( nameof(CanSendKeyFramesWithExtensionFieldsToIoTHubTestJsonReversibleAsync), "./Resources/KeyFrames.json", messageType: "ua-data", // NOTE: while we --fm and fullnetworkmessage, the keyframes.json overrides this back to PubSub arguments: ["--mm=FullNetworkMessages", "--me=JsonReversible", "--fm=true", "--strict"]); // Assert var message = Assert.Single(messages).Message; var firstDataSet = message.GetProperty("Messages")[0]; Assert.Equal("ua-keyframe", firstDataSet.GetProperty("MessageType").GetString()); var payload = firstDataSet.GetProperty("Payload"); Assert.NotEqual(JsonValueKind.Null, payload.ValueKind); var time = payload.GetProperty("CurrentTime").GetProperty("Value"); Assert.NotEqual(JsonValueKind.Null, time.ValueKind); Assert.True(time.GetProperty("Body").GetDateTime() < DateTime.UtcNow); var ep = payload.TryGetProperty("EndpointUrl", out _); Assert.False(ep); var appuri = payload.TryGetProperty("ApplicationUri", out _); Assert.False(appuri); Assert.False(payload.GetProperty("Important").GetProperty("Value").GetProperty("Body").GetBoolean()); Assert.Equal("5", payload.GetProperty("AssetId").GetProperty("Value").GetProperty("Body").GetString()); Assert.Equal("mm/sec", payload.GetProperty("EngineeringUnits").GetProperty("Value").GetProperty("Body").GetString()); Assert.Equal(12.3465f, payload.GetProperty("Variance").GetProperty("Value").GetProperty("Body").GetSingle()); Assert.NotNull(metadata); var metadataFields = metadata.Value.Message.GetProperty("MetaData").GetProperty("Fields"); Assert.Equal(JsonValueKind.Array, metadataFields.ValueKind); var fieldNames = metadataFields.EnumerateArray().Select(v => v.GetProperty("Name").GetString()).ToHashSet(); var expectedNames = new[] { "AssetId", "CurrentTime", "EngineeringUnits", "Important", "Variance" }; Assert.Equal(expectedNames.Length, fieldNames.Count); Assert.All(expectedNames, n => fieldNames.Contains(n)); // TODO: Need to have order in fields! Assert.Equal(metadataFields.EnumerateArray().Select(v => v.GetProperty("Name").GetString()), // TODO: Need to have order in fields! payload.EnumerateObject().Select(p => p.Name)); } [Fact] public async Task CyclicReadWithAgeTestAsync() { var (metadata, messages) = await ProcessMessagesAndMetadataAsync( nameof(CyclicReadWithAgeTestAsync), "./Resources/CyclicRead.json", TimeSpan.FromMinutes(1), 10, messageType: "ua-data", arguments: ["--mm=PubSub", "--dm=false"]); // Assert Assert.Equal(10, messages.Count); var message = messages[0].Message; var output = message.GetProperty("Messages")[0].GetProperty("Payload").GetProperty("Output"); Assert.NotEqual(JsonValueKind.Null, output.ValueKind); Assert.InRange(output.GetProperty("Value").GetDouble(), double.MinValue, double.MaxValue); Assert.NotNull(metadata); } [Fact] public async Task PeriodicHeartbeatTestAsync() { // Arrange // Act var (metadata, messages) = await ProcessMessagesAndMetadataAsync( nameof(PeriodicHeartbeatTestAsync), "./Resources/Heartbeat2.json", TimeSpan.FromMinutes(1), 10, messageType: "ua-data", arguments: ["--mm=PubSub", "-c"]); // Assert Assert.NotNull(metadata); Assert.Equal(10, messages.Count); // Assert that all messages are 1 second apart var timestamps = messages.ConvertAll(m => m.Message.GetProperty("Messages")[0] .GetProperty("Timestamp").GetDateTimeOffset()); _output.WriteLine(string.Join('\n', timestamps .Select(t => t.ToString("o", CultureInfo.InvariantCulture)) .ToArray())); var diffs = new List(); for (var index = 0; index < timestamps.Count - 1; index++) { var diff = timestamps[index + 1] - timestamps[index]; diffs.Add(diff); } _output.WriteLine(string.Join('\n', diffs .Select(t => t.ToString()) .ToArray())); #if FIX // Not stable enough when run with all tests together // TODO: Need a better and more reliable timer mechanism. var allowedVariance = TimeSpan.FromMilliseconds(10); Assert.All(diffs, diff => Assert.True( diff - TimeSpan.FromSeconds(1)< allowedVariance && diff - TimeSpan.FromSeconds(1) > -allowedVariance, $"{diff} > {allowedVariance}")); #endif } [Theory] [InlineData(100)] [InlineData(1)] public async Task CanSendKeyFramesToIoTHubTestAsync(int maxMonitoredItems) { // Arrange // Act var (metadata, messages) = await ProcessMessagesAndMetadataAsync( nameof(CanSendKeyFramesToIoTHubTestAsync), "./Resources/KeyFrames.json", TimeSpan.FromMinutes(2), 11, messageType: "ua-data", arguments: ["--dm=false", "--xmi=" + maxMonitoredItems]); // Assert var allDataSetMessages = messages.Select(m => m.Message.GetProperty("Messages")).SelectMany(m => m.EnumerateArray()).ToList(); Assert.True(allDataSetMessages.Count >= 11); var dataSetMessages = allDataSetMessages.Take(11).ToArray(); Assert.Equal("ua-keyframe", dataSetMessages[0].GetProperty("MessageType").GetString()); Assert.All(dataSetMessages.AsSpan(1, 9).ToArray(), m => Assert.Equal("ua-deltaframe", m.GetProperty("MessageType").GetString())); Assert.Equal("ua-keyframe", dataSetMessages[10].GetProperty("MessageType").GetString()); Assert.NotNull(metadata); } internal static JsonElement GetAlarmCondition(JsonElement jsonElement) { var messages = jsonElement.GetProperty("Messages"); return messages.ValueKind != JsonValueKind.Array ? default : messages.EnumerateArray().FirstOrDefault(element => { return element.GetProperty("MessageType").GetString() == "ua-condition" && element.GetProperty("Payload").TryGetProperty("SourceNode", out var node) && node.TryGetProperty("Value", out node) && node.ValueKind != JsonValueKind.Null && node.GetString().StartsWith("http://opcfoundation.org/AlarmCondition#s=1%3a", StringComparison.InvariantCulture); }); } internal static void AssertCompliantSimpleEventsMetadata(JsonMessage? metadata) { Assert.NotNull(metadata); var eventFields = metadata.Value.Message.GetProperty("MetaData").GetProperty("Fields"); Assert.Equal(JsonValueKind.Array, eventFields.ValueKind); Assert.Collection(eventFields.EnumerateArray(), v => { Assert.Equal("EventId", v.GetProperty("Name").GetString()); Assert.Equal(15, v.GetProperty("DataType").GetProperty("Id").GetInt32()); }, v => { Assert.Equal("Message", v.GetProperty("Name").GetString()); Assert.Equal(21, v.GetProperty("DataType").GetProperty("Id").GetInt32()); }, v => { Assert.Equal(CycleIdExpanded, v.GetProperty("Name").GetString()); Assert.Equal(12, v.GetProperty("DataType").GetProperty("Id").GetInt32()); }, v => { Assert.Equal(CurrentStepExpanded, v.GetProperty("Name").GetString()); Assert.Equal(183, v.GetProperty("DataType").GetProperty("Id").GetInt32()); Assert.Equal("http://opcfoundation.org/SimpleEvents", v.GetProperty("DataType").GetProperty("Namespace").GetString()); }); var namespaces = metadata.Value.Message.GetProperty("MetaData").GetProperty("Namespaces"); Assert.Equal(JsonValueKind.Array, namespaces.ValueKind); Assert.Equal(24, namespaces.GetArrayLength()); var structureDataTypes = metadata.Value.Message.GetProperty("MetaData").GetProperty("StructureDataTypes"); Assert.Equal(JsonValueKind.Array, structureDataTypes.ValueKind); var s = structureDataTypes.EnumerateArray().First().GetProperty("StructureDefinition"); Assert.Equal("Structure_0", s.GetProperty("StructureType").GetString()); var structureFields = s.GetProperty("Fields"); Assert.Equal(JsonValueKind.Array, structureFields.ValueKind); Assert.Collection(structureFields.EnumerateArray(), v => { Assert.Equal("Name", v.GetProperty("Name").GetString()); Assert.Equal(12, v.GetProperty("DataType").GetProperty("Id").GetInt32()); }, v => { Assert.Equal("Duration", v.GetProperty("Name").GetString()); Assert.Equal(11, v.GetProperty("DataType").GetProperty("Id").GetInt32()); }); } internal static void AssertSimpleEventsMetadata(JsonMessage? metadata) { Assert.NotNull(metadata); var eventFields = metadata.Value.Message.GetProperty("MetaData").GetProperty("Fields"); Assert.Equal(JsonValueKind.Array, eventFields.ValueKind); Assert.Collection(eventFields.EnumerateArray(), v => { Assert.Equal("EventId", v.GetProperty("Name").GetString()); Assert.Equal("ByteString", v.GetProperty("DataType").GetString()); }, v => { Assert.Equal("Message", v.GetProperty("Name").GetString()); Assert.Equal("LocalizedText", v.GetProperty("DataType").GetString()); }, v => { Assert.Equal("http://opcfoundation.org/SimpleEvents#CycleId", v.GetProperty("Name").GetString()); Assert.Equal("String", v.GetProperty("DataType").GetString()); }, v => { Assert.Equal("http://opcfoundation.org/SimpleEvents#CurrentStep", v.GetProperty("Name").GetString()); Assert.Equal("http://opcfoundation.org/SimpleEvents#i=183", v.GetProperty("DataType").GetString()); }); var namespaces = metadata.Value.Message.GetProperty("MetaData").GetProperty("Namespaces"); Assert.Equal(JsonValueKind.Array, namespaces.ValueKind); Assert.Equal(24, namespaces.GetArrayLength()); var structureDataTypes = metadata.Value.Message.GetProperty("MetaData").GetProperty("StructureDataTypes"); Assert.Equal(JsonValueKind.Array, structureDataTypes.ValueKind); var s = structureDataTypes.EnumerateArray().First().GetProperty("StructureDefinition"); Assert.Equal("Structure_0", s.GetProperty("StructureType").GetString()); var structureFields = s.GetProperty("Fields"); Assert.Equal(JsonValueKind.Array, structureFields.ValueKind); Assert.Collection(structureFields.EnumerateArray(), v => { Assert.Equal("Name", v.GetProperty("Name").GetString()); Assert.Equal("String", v.GetProperty("DataType").GetString()); }, v => { Assert.Equal("Duration", v.GetProperty("Name").GetString()); Assert.Equal("Double", v.GetProperty("DataType").GetString()); }); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/ReferenceServer/BasicSamplesIntegrationTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.ReferenceServer { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Encoders; using Azure.IIoT.OpcUa.Encoders.Models; using FluentAssertions; using Json.More; using Opc.Ua; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Text.Json; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public class BasicSamplesIntegrationTests : PublisherIntegrationTestBase { private const string kEventId = "EventId"; private const string kMessage = "Message"; private const string kCycleId = "http://opcfoundation.org/SimpleEvents#CycleId"; private const string kCurrentStep = "http://opcfoundation.org/SimpleEvents#CurrentStep"; private readonly ITestOutputHelper _output; private readonly ReferenceServer _fixture; public BasicSamplesIntegrationTests(ITestOutputHelper output) : base(output) { _output = output; _fixture = new ReferenceServer(); EndpointUrl = _fixture.EndpointUrl; } protected override void Dispose(bool disposing) { base.Dispose(disposing); if (disposing) { _fixture.Dispose(); } } [Fact] public async Task CanSendDataItemToIoTHubTestAsync() { // Arrange // Act var messages = await ProcessMessagesAsync(nameof(CanSendDataItemToIoTHubTestAsync), "./Resources/DataItems.json"); // Assert var message = Assert.Single(messages); Assert.Equal("ns=23;i=1259", message.Message.GetProperty("NodeId").GetString()); Assert.InRange(message.Message.GetProperty("Value").GetProperty("Value").GetDouble(), double.MinValue, double.MaxValue); } [Theory] [InlineData(MessageTimestamp.EncodingTimeUtc, HeartbeatBehavior.WatchdogLKV)] [InlineData(MessageTimestamp.EncodingTimeUtc, HeartbeatBehavior.WatchdogLKG)] [InlineData(MessageTimestamp.CurrentTimeUtc, HeartbeatBehavior.WatchdogLKVWithUpdatedTimestamps)] [InlineData(MessageTimestamp.PublishTime, HeartbeatBehavior.PeriodicLKV)] public async Task CanSendHeartbeatToIoTHubTestAsync(MessageTimestamp timestamp, HeartbeatBehavior behavior) { // Arrange // Act var messages = await ProcessMessagesAsync(nameof(CanSendHeartbeatToIoTHubTestAsync) + timestamp, "./Resources/Heartbeat.json", TimeSpan.FromMinutes(2), 5, arguments: ["--fm=True", $"--mts={timestamp}", $"--hbb={behavior}"]); // Assert Assert.True(messages.Count > 1); var timestamps = new HashSet(); for (var i = 0; i < messages.Count; i++) { var message = messages[i].Message; _output.WriteLine(message.ToJsonString()); if (!message.GetProperty("Value").TryGetProperty("StatusCode", out _)) { Assert.Equal("i=2271", message.GetProperty("NodeId").GetString()); Assert.NotEmpty(message.GetProperty("ApplicationUri").GetString()); Assert.True(message.GetProperty("SequenceNumber").GetUInt32() > 0); Assert.Equal("en-US", message.GetProperty("Value").GetProperty("Value").EnumerateArray().First().GetString()); } if (message.TryGetProperty("Timestamp", out _)) { Assert.NotEmpty(message.GetProperty("Timestamp").GetString()); timestamps.Add(message.GetProperty("Timestamp").GetDateTime()); } } if (timestamp == MessageTimestamp.PublishTime) { Assert.NotEmpty(timestamps); } else { Assert.Equal(messages.Count, timestamps.Count); } } [Theory] [InlineData(HeartbeatBehavior.WatchdogLKV)] [InlineData(HeartbeatBehavior.WatchdogLKVWithUpdatedTimestamps)] [InlineData(HeartbeatBehavior.PeriodicLKV)] public async Task CanSendHeartbeatWithMIErrorToIoTHubTestAsync(HeartbeatBehavior behavior) { // Arrange // Act var messages = await ProcessMessagesAsync(nameof(CanSendHeartbeatWithMIErrorToIoTHubTestAsync), "./Resources/HeartbeatErrors.json", TimeSpan.FromMinutes(2), 5, arguments: ["--fm=True", $"--hbb={behavior}"]); // Assert Assert.True(messages.Count > 1); var message = messages[0].Message; _output.WriteLine(message.ToJsonString()); Assert.Equal("i=932534", message.GetProperty("NodeId").GetString()); Assert.NotEmpty(message.GetProperty("ApplicationUri").GetString()); Assert.True(message.GetProperty("SequenceNumber").GetUInt32() > 0); Assert.Equal("BadNodeIdUnknown", message.GetProperty("Value") .GetProperty("StatusCode").GetProperty("Symbol").GetString()); } [Fact] public async Task CanSendDeadbandItemsToIoTHubTestAsync() { // Arrange // Act var messages = await ProcessMessagesAsync(nameof(CanSendDeadbandItemsToIoTHubTestAsync), "./Resources/Deadband.json", TimeSpan.FromMinutes(2), 20, arguments: ["--fm=True"]); // Assert messages.ForEach(m => _output.WriteLine(m.Topic + m.Message.ToJsonString())); var doubleValues = messages .Where(message => message.Message.GetProperty("DisplayName").GetString() == "DoubleValues" && message.Message.GetProperty("Value").TryGetProperty("Value", out _)); double? dvalue = null; foreach (var message in doubleValues) { Assert.Equal("http://test.org/UA/Data/#i=11224", message.Message.GetProperty("NodeId").GetString()); var value1 = message.Message.GetProperty("Value").GetProperty("Value").GetDouble(); _output.WriteLine(JsonSerializer.Serialize(message)); if (dvalue != null) { var abs = Math.Abs(dvalue.Value - value1); Assert.True(abs >= 5.0, $"Value within absolute deadband limit {abs} < 5 ({dvalue.Value}/{value1})"); } dvalue = value1; } var int64Values = messages .Where(message => message.Message.GetProperty("DisplayName").GetString() == "Int64Values" && message.Message.GetProperty("Value").TryGetProperty("Value", out _)); long? lvalue = null; foreach (var message in int64Values) { Assert.Equal("http://test.org/UA/Data/#i=11206", message.Message.GetProperty("NodeId").GetString()); var value1 = message.Message.GetProperty("Value").GetProperty("Value").GetInt64(); _output.WriteLine(JsonSerializer.Serialize(message)); if (lvalue != null) { var abs = Math.Abs(lvalue.Value - value1); // TODO: Investigate this, it should be 10% Assert.True(abs >= 3, $"Value within percent deadband limit {abs} < 3% ({lvalue.Value}/{value1})"); } lvalue = value1; } } [Fact] public async Task CanSendEventToIoTHubTestAsync() { // Arrange // Act var messages = await ProcessMessagesAsync(nameof(CanSendEventToIoTHubTestAsync), "./Resources/SimpleEvents.json"); // Assert var message = Assert.Single(messages).Message; Assert.Equal("i=2253", message.GetProperty("NodeId").GetString()); Assert.False(message.TryGetProperty("ApplicationUri", out _)); Assert.False(message.TryGetProperty("Timestamp", out _)); Assert.False(message.TryGetProperty("SequenceNumber", out _)); Assert.NotEmpty(message.GetProperty("Value").GetProperty("EventId").GetString()); } [Theory] [InlineData(true)] [InlineData(false)] public async Task CanSendEventToIoTHubTestFullFeaturedMessageAsync(bool useCurrentTime) { // Arrange // Act var messages = await ProcessMessagesAsync( nameof(CanSendEventToIoTHubTestFullFeaturedMessageAsync), "./Resources/SimpleEvents.json", arguments: ["--fm=true", useCurrentTime ? "--mts=CurrentTimeUtc" : "--mts=PublishTime"]); // Assert var message = Assert.Single(messages).Message; Assert.Equal("i=2253", message.GetProperty("NodeId").GetString()); Assert.NotEmpty(message.GetProperty("ApplicationUri").GetString()); Assert.NotEmpty(message.GetProperty("Timestamp").GetString()); Assert.True(message.GetProperty("SequenceNumber").GetUInt32() > 0); Assert.NotEmpty(message.GetProperty("Value").GetProperty("EventId").GetString()); } [Fact] public async Task CanEncodeWithReversibleEncodingSamplesTestAsync() { // Arrange // Act var result = await ProcessMessagesAsync( nameof(CanEncodeWithReversibleEncodingSamplesTestAsync), "./Resources/SimpleEvents.json", arguments: ["--mm=Samples", "--me=JsonReversible"] ); var m = Assert.Single(result).Message; var value = m.GetProperty("Value"); var type = value.GetProperty("Type").GetString(); var body = value.GetProperty("Body"); Assert.Equal("ExtensionObject", type); var encoding = body.GetProperty("Encoding").GetString(); body = body.GetProperty("Body"); Assert.Equal("Json", encoding); var eventId = body.GetProperty(kEventId); Assert.Equal("ByteString", eventId.GetProperty("Type").GetString()); Assert.Equal(JsonValueKind.String, eventId.GetProperty("Body").ValueKind); var message = body.GetProperty(kMessage); Assert.Equal("LocalizedText", message.GetProperty("Type").GetString()); Assert.Equal(JsonValueKind.String, message.GetProperty("Body").GetProperty("Text").ValueKind); Assert.Equal("en-US", message.GetProperty("Body").GetProperty("Locale").GetString()); var cycleId = body.GetProperty(kCycleId); Assert.Equal("String", cycleId.GetProperty("Type").GetString()); Assert.Equal(JsonValueKind.String, cycleId.GetProperty("Body").ValueKind); var currentStep = body.GetProperty(kCurrentStep); body = currentStep.GetProperty("Body"); Assert.Equal("ExtensionObject", currentStep.GetProperty("Type").GetString()); Assert.Equal("http://opcfoundation.org/SimpleEvents#i=183", body.GetProperty("TypeId").GetString()); Assert.Equal("Json", body.GetProperty("Encoding").GetString()); Assert.Equal(JsonValueKind.String, body.GetProperty("Body").GetProperty("Name").ValueKind); Assert.Equal(JsonValueKind.Number, body.GetProperty("Body").GetProperty("Duration").ValueKind); var json = value .GetProperty("Body") .GetProperty("Body") .GetRawText(); var buffer = Encoding.UTF8.GetBytes(json); var serviceMessageContext = new ServiceMessageContext(); serviceMessageContext.Factory.AddEncodeableType(typeof(EncodeableDictionary)); await using var stream = new MemoryStream(buffer); using var decoder = new JsonDecoderEx(stream, serviceMessageContext); var actual = new EncodeableDictionary(); actual.Decode(decoder); Assert.Equal(4, actual.Count); Assert.Equal(new[] { kEventId, kMessage, kCycleId, kCurrentStep }, actual.Select(x => x.Key)); Assert.All(actual.Select(x => x.Value?.Value), Assert.NotNull); var eof = decoder.ReadDataValue(null); Assert.Null(eof); } [Fact] public async Task CanSendPendingConditionsToIoTHubTestAsync() { // Arrange // Act var messages = await ProcessMessagesAsync(nameof(CanSendPendingConditionsToIoTHubTestAsync), "./Resources/PendingAlarms.json", GetAlarmCondition); // Assert messages.ForEach(m => _output.WriteLine(m.Topic + m.Message.ToJsonString())); var evt = Assert.Single(messages).Message; Assert.Equal(JsonValueKind.Object, evt.ValueKind); Assert.Equal("i=2253", evt.GetProperty("NodeId").GetString()); Assert.Equal("PendingAlarms", evt.GetProperty("DisplayName").GetString()); Assert.True(evt.TryGetProperty("Value", out var sev)); Assert.True(sev.TryGetProperty("Severity", out sev)); Assert.True(sev.TryGetProperty("Value", out sev)); Assert.True(sev.GetInt32() >= 100); } [Fact] public async Task CanSendDataItemToIoTHubTestWithDeviceMethodAsync() { const string name = nameof(CanSendDataItemToIoTHubTestWithDeviceMethodAsync); var testInput = GetEndpointsFromFile(name, "./Resources/DataItems.json"); StartPublisher(name, arguments: ["--mm=FullSamples"]); // Alternative to --fm=True try { var endpoints = await PublisherApi.GetConfiguredEndpointsAsync(); Assert.Empty(endpoints.Endpoints); var result = await PublisherApi.PublishNodesAsync(testInput[0]); Assert.NotNull(result); var messages = await WaitForMessagesAsync(); var message = Assert.Single(messages).Message; Assert.Equal("ns=23;i=1259", message.GetProperty("NodeId").GetString()); Assert.InRange(message.GetProperty("Value").GetProperty("Value").GetDouble(), double.MinValue, double.MaxValue); endpoints = await PublisherApi.GetConfiguredEndpointsAsync(); var e = Assert.Single(endpoints.Endpoints); var nodes = await PublisherApi.GetConfiguredNodesOnEndpointAsync(e); var n = Assert.Single(nodes.OpcNodes); Assert.Equal(testInput[0].OpcNodes[0].Id, n.Id); result = await PublisherApi.UnpublishNodesAsync(e); Assert.NotNull(result); endpoints = await PublisherApi.GetConfiguredEndpointsAsync(); Assert.Empty(endpoints.Endpoints); } finally { await StopPublisherAsync(); } } [Fact] public async Task CanSendEventToIoTHubTestWithDeviceMethodAsync() { const string name = nameof(CanSendEventToIoTHubTestWithDeviceMethodAsync); var testInput = GetEndpointsFromFile(name, "./Resources/SimpleEvents.json"); StartPublisher(name); try { var endpoints = await PublisherApi.GetConfiguredEndpointsAsync(); Assert.Empty(endpoints.Endpoints); var result = await PublisherApi.PublishNodesAsync(testInput[0]); Assert.NotNull(result); var messages = await WaitForMessagesAsync(); var message = Assert.Single(messages).Message; Assert.Equal("i=2253", message.GetProperty("NodeId").GetString()); Assert.NotEmpty(message.GetProperty("Value").GetProperty("EventId").GetString()); endpoints = await PublisherApi.GetConfiguredEndpointsAsync(); var e = Assert.Single(endpoints.Endpoints); var nodes = await PublisherApi.GetConfiguredNodesOnEndpointAsync(e); var n = Assert.Single(nodes.OpcNodes); Assert.Equal(testInput[0].OpcNodes[0].Id, n.Id); result = await PublisherApi.UnpublishAllNodesAsync(); Assert.NotNull(result); endpoints = await PublisherApi.GetConfiguredEndpointsAsync(); Assert.Empty(endpoints.Endpoints); } finally { await StopPublisherAsync(); } } [Fact] public async Task CanSendPendingConditionsToIoTHubTestWithDeviceMethodAsync() { const string name = nameof(CanSendPendingConditionsToIoTHubTestWithDeviceMethodAsync); var testInput = GetEndpointsFromFile(name, "./Resources/PendingAlarms.json"); StartPublisher(name); try { var endpoints = await PublisherApi.GetConfiguredEndpointsAsync(); Assert.Empty(endpoints.Endpoints); var result = await PublisherApi.PublishNodesAsync(testInput[0]); Assert.NotNull(result); var messages = await WaitForMessagesAsync(GetAlarmCondition); messages.ForEach(m => _output.WriteLine(m.Topic + m.Message.ToJsonString())); var evt = Assert.Single(messages).Message; Assert.Equal(JsonValueKind.Object, evt.ValueKind); Assert.Equal("i=2253", evt.GetProperty("NodeId").GetString()); Assert.Equal("PendingAlarms", evt.GetProperty("DisplayName").GetString()); Assert.True(evt.TryGetProperty("Value", out var sev)); Assert.True(sev.TryGetProperty("Severity", out sev)); Assert.True(sev.TryGetProperty("Value", out sev)); Assert.True(sev.GetInt32() >= 100); endpoints = await PublisherApi.GetConfiguredEndpointsAsync(); var e = Assert.Single(endpoints.Endpoints); var nodes = await PublisherApi.GetConfiguredNodesOnEndpointAsync(e); var n = Assert.Single(nodes.OpcNodes); Assert.Equal(testInput[0].OpcNodes[0].Id, n.Id); result = await PublisherApi.UnpublishNodesAsync(testInput[0]); Assert.NotNull(result); endpoints = await PublisherApi.GetConfiguredEndpointsAsync(); Assert.Empty(endpoints.Endpoints); } finally { await StopPublisherAsync(); } } [Theory] [InlineData(100)] [InlineData(1)] public async Task CanSendDataItemToIoTHubTestWithDeviceMethod2Async(int maxMonitoredItems) { const string name = nameof(CanSendDataItemToIoTHubTestWithDeviceMethod2Async); var testInput1 = GetEndpointsFromFile(name, "./Resources/DataItems.json"); var testInput2 = GetEndpointsFromFile(name, "./Resources/SimpleEvents.json"); var testInput3 = GetEndpointsFromFile(name, "./Resources/PendingAlarms.json"); StartPublisher(name, arguments: ["--xmi=" + maxMonitoredItems]); try { var endpoints = await PublisherApi.GetConfiguredEndpointsAsync(); Assert.Empty(endpoints.Endpoints); await PublisherApi.PublishNodesAsync(testInput1[0]); await PublisherApi.PublishNodesAsync(testInput2[0]); await PublisherApi.PublishNodesAsync(testInput3[0]); endpoints = await PublisherApi.GetConfiguredEndpointsAsync(); var e = Assert.Single(endpoints.Endpoints); var nodes = await PublisherApi.GetConfiguredNodesOnEndpointAsync(e); Assert.Equal(3, nodes.OpcNodes.Count); await PublisherApi.UnpublishAllNodesAsync(); endpoints = await PublisherApi.GetConfiguredEndpointsAsync(); Assert.Empty(endpoints.Endpoints); await PublisherApi.AddOrUpdateEndpointsAsync(new List { new () { OpcNodes = [.. nodes.OpcNodes], EndpointUrl = e.EndpointUrl, UseSecurity = e.UseSecurity, DataSetWriterGroup = name } }); endpoints = await PublisherApi.GetConfiguredEndpointsAsync(); e = Assert.Single(endpoints.Endpoints); nodes = await PublisherApi.GetConfiguredNodesOnEndpointAsync(e); Assert.Equal(3, nodes.OpcNodes.Count); var messages1 = await WaitForMessagesAsync(GetDataFrame); var message1 = Assert.Single(messages1).Message; Assert.Equal("ns=23;i=1259", message1.GetProperty("NodeId").GetString()); Assert.InRange(message1.GetProperty("Value").GetProperty("Value").GetDouble(), double.MinValue, double.MaxValue); _output.WriteLine("Removing items..."); await PublisherApi.UnpublishNodesAsync(testInput3[0]); nodes = await PublisherApi.GetConfiguredNodesOnEndpointAsync(e); Assert.Equal(2, nodes.OpcNodes.Count); await PublisherApi.UnpublishNodesAsync(testInput2[0]); nodes = await PublisherApi.GetConfiguredNodesOnEndpointAsync(e); Assert.Single(nodes.OpcNodes); _output.WriteLine("Waiting for remaining..."); var messages = await WaitForMessagesAsync(GetDataFrame); var message = Assert.Single(messages).Message; Assert.Equal("ns=23;i=1259", message.GetProperty("NodeId").GetString()); Assert.InRange(message.GetProperty("Value").GetProperty("Value").GetDouble(), double.MinValue, double.MaxValue); var diagnostics = await PublisherApi.GetDiagnosticInfoAsync(); var diag = Assert.Single(diagnostics); Assert.Equal(e.EndpointUrl, diag.Endpoint.EndpointUrl); } finally { await StopPublisherAsync(); } } [Fact] public async Task CanSendPendingConditionsToIoTHubTestWithDeviceMethod2Async() { const string name = nameof(CanSendPendingConditionsToIoTHubTestWithDeviceMethod2Async); var testInput = GetEndpointsFromFile(name, "./Resources/PendingAlarms.json"); StartPublisher(name); try { var endpoints = await PublisherApi.GetConfiguredEndpointsAsync(); Assert.Empty(endpoints.Endpoints); var result = await PublisherApi.PublishNodesAsync(testInput[0]); Assert.NotNull(result); var messages = await WaitForMessagesAsync(GetAlarmCondition); messages.ForEach(m => _output.WriteLine(m.Topic + m.Message.ToJsonString())); var evt = Assert.Single(messages).Message; Assert.Equal(JsonValueKind.Object, evt.ValueKind); Assert.Equal("i=2253", evt.GetProperty("NodeId").GetString()); Assert.Equal("PendingAlarms", evt.GetProperty("DisplayName").GetString()); Assert.True(evt.TryGetProperty("Value", out var sev)); Assert.True(sev.TryGetProperty("Severity", out sev)); Assert.True(sev.TryGetProperty("Value", out sev)); Assert.True(sev.GetInt32() >= 100); // Disable pending alarms testInput[0].OpcNodes[0].ConditionHandling = null; testInput[0].OpcNodes[0].DisplayName = "SimpleEvents"; result = await PublisherApi.AddOrUpdateEndpointsAsync(new List { testInput[0] }); Assert.NotNull(result); endpoints = await PublisherApi.GetConfiguredEndpointsAsync(); var e = Assert.Single(endpoints.Endpoints); var nodes = await PublisherApi.GetConfiguredNodesOnEndpointAsync(e); var n = Assert.Single(nodes.OpcNodes); // Wait until it was applied and we receive normal events again messages = await WaitForMessagesAsync( message => message.GetProperty("DisplayName").GetString() == "SimpleEvents" && message.GetProperty("Value").GetProperty("ReceiveTime").ValueKind == JsonValueKind.String ? message : default); messages.ForEach(m => _output.WriteLine(m.Topic + m.Message.ToJsonString())); var message = Assert.Single(messages).Message; Assert.Equal("i=2253", message.GetProperty("NodeId").GetString()); Assert.Equal("SimpleEvents", message.GetProperty("DisplayName").GetString()); Assert.True(message.TryGetProperty("Value", out sev)); Assert.True(sev.TryGetProperty("Severity", out sev)); Assert.True(sev.GetInt32() != 0, $"{message.ToJsonString()}"); result = await PublisherApi.UnpublishNodesAsync(testInput[0]); Assert.NotNull(result); endpoints = await PublisherApi.GetConfiguredEndpointsAsync(); Assert.Empty(endpoints.Endpoints); } finally { await StopPublisherAsync(); } } private JsonElement GetDataFrame(JsonElement jsonElement) { return jsonElement.GetProperty("NodeId").GetString() != "i=2253" ? jsonElement : default; } private static JsonElement GetAlarmCondition(JsonElement jsonElement) { return jsonElement .TryGetProperty("Value", out var node) && node .TryGetProperty("SourceNode", out node) && node .TryGetProperty("Value", out node) && node .GetString().StartsWith("http://opcfoundation.org/AlarmCondition#s=1%3a", StringComparison.InvariantCulture) ? jsonElement : default; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/ReferenceServer/ReverseConnectIntegrationTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.ReferenceServer { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Neovolve.Logging.Xunit; using System; using System.Linq; using System.Text.Json; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; public class ReverseConnectIntegrationTests : PublisherIntegrationTestBase { private readonly ITestOutputHelper _output; public ReverseConnectIntegrationTests(ITestOutputHelper output) : base(output) { _output = output; } [Theory] [InlineData(true)] [InlineData(false)] public async Task RegisteredReadTestAsync(bool useReverseConnect) { #pragma warning disable CA2000 // Dispose objects before losing scope var server = ReferenceServer.Create(LogFactory.Create(_output, Logging.Config), useReverseConnect); #pragma warning restore CA2000 // Dispose objects before losing scope EndpointUrl = server.EndpointUrl; var name = nameof(RegisteredReadTestAsync) + (useReverseConnect ? "WithReverseConnect" : "NoReverseConnect"); StartPublisher(name, "./Resources/RegisteredRead.json", arguments: ["--mm=PubSub", "--dm=false"], reverseConnectPort: useReverseConnect ? server.ReverseConnectPort : null); try { // Arrange // Act var (metadata, messages) = await WaitForMessagesAndMetadataAsync(TimeSpan.FromMinutes(2), 1, messageType: "ua-data"); // Assert var message = Assert.Single(messages).Message; var output = message.GetProperty("Messages")[0].GetProperty("Payload").GetProperty("Output"); Assert.NotEqual(JsonValueKind.Null, output.ValueKind); Assert.InRange(output.GetProperty("Value").GetDouble(), double.MinValue, double.MaxValue); var diagnostics = await PublisherApi.GetDiagnosticInfoAsync(); var diag = Assert.Single(diagnostics); Assert.Equal(name, diag.Endpoint.DataSetWriterGroup); Assert.NotNull(metadata); } finally { server.Dispose(); await StopPublisherAsync(); } } [Theory] [InlineData(true)] [InlineData(false)] public async Task KeepAliveTestAsync(bool useReverseConnect) { #pragma warning disable CA2000 // Dispose objects before losing scope using var server = ReferenceServer.Create(LogFactory.Create(_output, Logging.Config), useReverseConnect); #pragma warning restore CA2000 // Dispose objects before losing scope EndpointUrl = server.EndpointUrl; var name = nameof(KeepAliveTestAsync) + (useReverseConnect ? "WithReverseConnect" : "NoReverseConnect"); StartPublisher(name, "./Resources/KeepAlive.json", reverseConnectPort: useReverseConnect ? server.ReverseConnectPort : null); try { // Arrange // Act var (metadata, messages) = await WaitForMessagesAndMetadataAsync(TimeSpan.FromMinutes(2), 1, predicate: WaitUntilKeepAlive, messageType: "ua-data"); // Assert var message = Assert.Single(messages).Message; Assert.True(message.GetProperty("Messages")[0].TryGetProperty("Payload", out var payload)); Assert.Empty(payload.EnumerateObject()); var diagnostics = await PublisherApi.GetDiagnosticInfoAsync(); var diag = Assert.Single(diagnostics); Assert.Equal(name, diag.Endpoint.DataSetWriterGroup); } finally { await StopPublisherAsync(); } static JsonElement WaitUntilKeepAlive(JsonElement jsonElement) { var messages = jsonElement.GetProperty("Messages"); if (messages.ValueKind == JsonValueKind.Array) { var element = messages.EnumerateArray().FirstOrDefault(); if (element.GetProperty("MessageType").GetString() == "ua-keepalive") { return jsonElement; } } return default; } } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/SimpleEvents/NodeServicesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.SimpleEvents { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; public sealed class NodeServicesTests : IClassFixture, IClassFixture { public NodeServicesTests(SimpleEventsServer server, PublisherModuleFixture module) { _server = server; _module = module; } private SimpleEventsServerTests GetTests() { return new SimpleEventsServerTests( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly SimpleEventsServer _server; private readonly PublisherModuleFixture _module; [Fact] public Task CompileSimpleBaseEventQueryTestAsync() { return GetTests().CompileSimpleBaseEventQueryTestAsync(); } [Fact] public Task CompileSimpleEventsQueryTestAsync() { return GetTests().CompileSimpleEventsQueryTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/TestData/BrowsePathTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.TestData { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; [Collection(ReadCollection.Name)] public class BrowsePathTests : IClassFixture { public BrowsePathTests(TestDataServer server, PublisherModuleFixture module) { _server = server; _module = module; } private BrowsePathTests GetTests() { return new BrowsePathTests( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly TestDataServer _server; private readonly PublisherModuleFixture _module; [Fact] public Task NodeBrowsePathStaticScalarMethod3Test1Async() { return GetTests().NodeBrowsePathStaticScalarMethod3Test1Async(); } [Fact] public Task NodeBrowsePathStaticScalarMethod3Test2Async() { return GetTests().NodeBrowsePathStaticScalarMethod3Test2Async(); } [Fact] public Task NodeBrowsePathStaticScalarMethod3Test3Async() { return GetTests().NodeBrowsePathStaticScalarMethod3Test3Async(); } [Fact] public Task NodeBrowsePathStaticScalarMethodsTestAsync() { return GetTests().NodeBrowsePathStaticScalarMethodsTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/TestData/BrowseStreamTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.TestData { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; [Collection(ReadCollection.Name)] public sealed class BrowseStreamTests : IClassFixture { public BrowseStreamTests(TestDataServer server, PublisherModuleFixture module) { _server = server; _module = module; } private BrowseStreamTests GetTests() { return new BrowseStreamTests( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly TestDataServer _server; private readonly PublisherModuleFixture _module; [SkippableFact] public Task NodeBrowseInRootTest1Async() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseInRootTest1Async(); } [SkippableFact] public Task NodeBrowseInRootTest2Async() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseInRootTest2Async(); } [SkippableFact] public Task NodeBrowseBoilersObjectsTest1Async() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseBoilersObjectsTest1Async(); } [SkippableFact] public Task NodeBrowseDataAccessObjectsTest1Async() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseDataAccessObjectsTest1Async(); } [SkippableFact] public Task NodeBrowseStaticScalarVariablesTestAsync() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseStaticScalarVariablesTestAsync(); } [SkippableFact] public Task NodeBrowseStaticArrayVariablesTestAsync() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseStaticArrayVariablesTestAsync(); } [SkippableFact] public Task NodeBrowseStaticScalarVariablesTestWithFilter1Async() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter1Async(); } [SkippableFact] public Task NodeBrowseStaticScalarVariablesTestWithFilter2Async() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter2Async(); } [SkippableFact] public Task NodeBrowseStaticScalarVariablesTestWithFilter3Async() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter3Async(); } [SkippableFact] public Task NodeBrowseStaticScalarVariablesTestWithFilter4Async() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter4Async(); } [SkippableFact] public Task NodeBrowseStaticScalarVariablesTestWithFilter5Async() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter5Async(); } [SkippableFact] public Task NodeBrowseDiagnosticsNoneTestAsync() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseDiagnosticsNoneTestAsync(); } [SkippableFact] public Task NodeBrowseDiagnosticsStatusTestAsync() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseDiagnosticsStatusTestAsync(); } [SkippableFact] public Task NodeBrowseDiagnosticsOperationsTestAsync() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseDiagnosticsInfoTestAsync(); } [SkippableFact] public Task NodeBrowseDiagnosticsVerboseTestAsync() { Skip.If(true, "Not yet supported"); return GetTests().NodeBrowseDiagnosticsVerboseTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/TestData/BrowseTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.TestData { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; [Collection(ReadCollection.Name)] public class BrowseTests : IClassFixture { public BrowseTests(TestDataServer server, PublisherModuleFixture module) { _server = server; _module = module; } private BrowseServicesTests GetTests() { return new BrowseServicesTests( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly TestDataServer _server; private readonly PublisherModuleFixture _module; [Fact] public Task NodeBrowseInRootTest1Async() { return GetTests().NodeBrowseInRootTest1Async(); } [Fact] public Task NodeBrowseInRootTest2Async() { return GetTests().NodeBrowseInRootTest2Async(); } [Fact] public Task NodeBrowseFirstInRootTest1Async() { return GetTests().NodeBrowseFirstInRootTest1Async(); } [Fact] public Task NodeBrowseFirstInRootTest2Async() { return GetTests().NodeBrowseFirstInRootTest2Async(); } [Fact] public Task NodeBrowseBoilersObjectsTest1Async() { return GetTests().NodeBrowseBoilersObjectsTest1Async(); } [Fact] public Task NodeBrowseBoilersObjectsTest2Async() { return GetTests().NodeBrowseBoilersObjectsTest2Async(); } [Fact] public Task NodeBrowseDataAccessObjectsTest1Async() { return GetTests().NodeBrowseDataAccessObjectsTest1Async(); } [Fact] public Task NodeBrowseDataAccessObjectsTest2Async() { return GetTests().NodeBrowseDataAccessObjectsTest2Async(); } [Fact] public Task NodeBrowseDataAccessObjectsTest3Async() { return GetTests().NodeBrowseDataAccessObjectsTest3Async(); } [Fact] public Task NodeBrowseDataAccessObjectsTest4Async() { return GetTests().NodeBrowseDataAccessObjectsTest4Async(); } [Fact] public Task NodeBrowseDataAccessFC1001Test1Async() { return GetTests().NodeBrowseDataAccessFC1001Test1Async(); } [Fact] public Task NodeBrowseDataAccessFC1001Test2Async() { return GetTests().NodeBrowseDataAccessFC1001Test2Async(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestAsync() { return GetTests().NodeBrowseStaticScalarVariablesTestAsync(); } [Fact] public Task NodeBrowseStaticArrayVariablesTestAsync() { return GetTests().NodeBrowseStaticArrayVariablesTestAsync(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestWithFilter1Async() { return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter1Async(); } [Fact] public Task NodeBrowseStaticScalarVariablesTestWithFilter2Async() { return GetTests().NodeBrowseStaticScalarVariablesTestWithFilter2Async(); } [Fact] public Task NodeBrowseStaticArrayVariablesWithValuesTestAsync() { return GetTests().NodeBrowseStaticArrayVariablesWithValuesTestAsync(); } [Fact] public Task NodeBrowseStaticArrayVariablesRawModeTestAsync() { return GetTests().NodeBrowseStaticArrayVariablesRawModeTestAsync(); } [Fact] public Task NodeBrowseContinuationTest1Async() { return GetTests().NodeBrowseContinuationTest1Async(); } [Fact] public Task NodeBrowseContinuationTest2Async() { return GetTests().NodeBrowseContinuationTest2Async(); } [Fact] public Task NodeBrowseContinuationTest3Async() { return GetTests().NodeBrowseContinuationTest3Async(); } [Fact] public Task NodeBrowseContinuationTest4Async() { return GetTests().NodeBrowseContinuationTest4Async(); } [Fact] public Task NodeBrowseDiagnosticsNoneTestAsync() { return GetTests().NodeBrowseDiagnosticsNoneTestAsync(); } [Fact] public Task NodeBrowseDiagnosticsStatusTestAsync() { return GetTests().NodeBrowseDiagnosticsStatusTestAsync(); } [Fact] public Task NodeBrowseDiagnosticsInfoTestAsync() { return GetTests().NodeBrowseDiagnosticsInfoTestAsync(); } [Fact] public Task NodeBrowseDiagnosticsVerboseTestAsync() { return GetTests().NodeBrowseDiagnosticsVerboseTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/TestData/CallArrayTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.TestData { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; [Collection(WriteCollection.Name)] public class CallArrayTests : IClassFixture { public CallArrayTests(TestDataServer server, PublisherModuleFixture module) { _server = server; _module = module; } private CallArrayMethodTests GetTests() { return new CallArrayMethodTests( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly TestDataServer _server; private readonly PublisherModuleFixture _module; [Fact] public Task NodeMethodMetadataStaticArrayMethod1TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod1TestAsync(); } [Fact] public Task NodeMethodMetadataStaticArrayMethod2TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod2TestAsync(); } [Fact] public Task NodeMethodMetadataStaticArrayMethod3TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod3TestAsync(); } [Fact] public Task NodeMethodCallStaticArrayMethod1Test1Async() { return GetTests().NodeMethodCallStaticArrayMethod1Test1Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod1Test2Async() { return GetTests().NodeMethodCallStaticArrayMethod1Test2Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod1Test3Async() { return GetTests().NodeMethodCallStaticArrayMethod1Test3Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod1Test4Async() { return GetTests().NodeMethodCallStaticArrayMethod1Test4Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod1Test5Async() { return GetTests().NodeMethodCallStaticArrayMethod1Test5Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod2Test1Async() { return GetTests().NodeMethodCallStaticArrayMethod2Test1Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod2Test2Async() { return GetTests().NodeMethodCallStaticArrayMethod2Test2Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod2Test3Async() { return GetTests().NodeMethodCallStaticArrayMethod2Test3Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod2Test4Async() { return GetTests().NodeMethodCallStaticArrayMethod2Test4Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod3Test1Async() { return GetTests().NodeMethodCallStaticArrayMethod3Test1Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod3Test2Async() { return GetTests().NodeMethodCallStaticArrayMethod3Test2Async(); } [Fact] public Task NodeMethodCallStaticArrayMethod3Test3Async() { return GetTests().NodeMethodCallStaticArrayMethod3Test3Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/TestData/CallScalarTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.TestData { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; [Collection(WriteCollection.Name)] public class CallScalarTests : IClassFixture { public CallScalarTests(TestDataServer server, PublisherModuleFixture module) { _server = server; _module = module; } private CallScalarMethodTests GetTests() { return new CallScalarMethodTests( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly TestDataServer _server; private readonly PublisherModuleFixture _module; [Fact] public Task NodeMethodMetadataStaticScalarMethod1TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod1TestAsync(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod2TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod2TestAsync(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod3TestAsync(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest1Async() { return GetTests().NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest1Async(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest2Async() { return GetTests().NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest2Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod1Test1Async() { return GetTests().NodeMethodCallStaticScalarMethod1Test1Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod1Test2Async() { return GetTests().NodeMethodCallStaticScalarMethod1Test2Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod1Test3Async() { return GetTests().NodeMethodCallStaticScalarMethod1Test3Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod1Test4Async() { return GetTests().NodeMethodCallStaticScalarMethod1Test4Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod1Test5Async() { return GetTests().NodeMethodCallStaticScalarMethod1Test5Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod2Test1Async() { return GetTests().NodeMethodCallStaticScalarMethod2Test1Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod2Test2Async() { return GetTests().NodeMethodCallStaticScalarMethod2Test2Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod3Test1Async() { return GetTests().NodeMethodCallStaticScalarMethod3Test1Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod3Test2Async() { return GetTests().NodeMethodCallStaticScalarMethod3Test2Async(); } [Fact] public Task NodeMethodCallStaticScalarMethod3WithBrowsePathNoIdsTestAsync() { return GetTests().NodeMethodCallStaticScalarMethod3WithBrowsePathNoIdsTestAsync(); } [Fact] public Task NodeMethodCallStaticScalarMethod3WithObjectIdAndBrowsePathTestAsync() { return GetTests().NodeMethodCallStaticScalarMethod3WithObjectIdAndBrowsePathTestAsync(); } [Fact] public Task NodeMethodCallStaticScalarMethod3WithObjectIdAndMethodIdAndBrowsePathTestAsync() { return GetTests().NodeMethodCallStaticScalarMethod3WithObjectIdAndMethodIdAndBrowsePathTestAsync(); } [Fact] public Task NodeMethodCallStaticScalarMethod3WithObjectPathAndMethodIdAndBrowsePathTestAsync() { return GetTests().NodeMethodCallStaticScalarMethod3WithObjectPathAndMethodIdAndBrowsePathTestAsync(); } [Fact] public Task NodeMethodCallStaticScalarMethod3WithObjectIdAndPathAndMethodIdAndPathTestAsync() { return GetTests().NodeMethodCallStaticScalarMethod3WithObjectIdAndPathAndMethodIdAndPathTestAsync(); } [Fact] public Task NodeMethodCallBoiler2ResetTestAsync() { return GetTests().NodeMethodCallBoiler2ResetTestAsync(); } [Fact] public Task NodeMethodCallBoiler1ResetTestAsync() { return GetTests().NodeMethodCallBoiler1ResetTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/TestData/MetadataArrayTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.TestData { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; [Collection(ReadCollection.Name)] public class MetadataArrayTests : IClassFixture { public MetadataArrayTests(TestDataServer server, PublisherModuleFixture module) { _server = server; _module = module; } private CallArrayMethodTests GetTests() { return new CallArrayMethodTests( _module.SdkContainer.Resolve>, _server.GetConnection(), newMetadata: true); } private readonly TestDataServer _server; private readonly PublisherModuleFixture _module; [Fact] public Task NodeMethodMetadataStaticArrayMethod1TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod1TestAsync(); } [Fact] public Task NodeMethodMetadataStaticArrayMethod2TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod2TestAsync(); } [Fact] public Task NodeMethodMetadataStaticArrayMethod3TestAsync() { return GetTests().NodeMethodMetadataStaticArrayMethod3TestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/TestData/MetadataScalarTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.TestData { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; [Collection(ReadCollection.Name)] public class MetadataScalarTests : IClassFixture { public MetadataScalarTests(TestDataServer server, PublisherModuleFixture module) { _server = server; _module = module; } private CallScalarMethodTests GetTests() { return new CallScalarMethodTests( _module.SdkContainer.Resolve>, _server.GetConnection(), newMetadata: true); } private readonly TestDataServer _server; private readonly PublisherModuleFixture _module; [Fact] public Task NodeMethodMetadataStaticScalarMethod1TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod1TestAsync(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod2TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod2TestAsync(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3TestAsync() { return GetTests().NodeMethodMetadataStaticScalarMethod3TestAsync(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest1Async() { return GetTests().NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest1Async(); } [Fact] public Task NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest2Async() { return GetTests().NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest2Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/TestData/MetadataTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.TestData { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; [Collection(ReadCollection.Name)] public class MetadataTests : IClassFixture { public MetadataTests(TestDataServer server, PublisherModuleFixture module) { _server = server; _module = module; } private NodeMetadataTests GetTests() { return new NodeMetadataTests( _module.SdkContainer.Resolve>, _server.GetConnection()); } private readonly TestDataServer _server; private readonly PublisherModuleFixture _module; [Fact] public Task GetServerCapabilitiesTestAsync() { return GetTests().GetServerCapabilitiesTestAsync(); } [Fact] public Task HistoryGetServerCapabilitiesTestAsync() { return GetTests().HistoryGetServerCapabilitiesTestAsync(); } [Fact] public Task NodeGetMetadataForFolderTypeTestAsync() { return GetTests().NodeGetMetadataForFolderTypeTestAsync(); } [Fact] public Task NodeGetMetadataForServerObjectTestAsync() { return GetTests().NodeGetMetadataForServerObjectTestAsync(); } [Fact] public Task NodeGetMetadataForConditionTypeTestAsync() { return GetTests().NodeGetMetadataForConditionTypeTestAsync(); } [Fact] public Task NodeGetMetadataTestForBaseEventTypeTestAsync() { return GetTests().NodeGetMetadataTestForBaseEventTypeTestAsync(); } [Fact] public Task NodeGetMetadataForBaseInterfaceTypeTestAsync() { return GetTests().NodeGetMetadataForBaseInterfaceTypeTestAsync(); } [Fact] public Task NodeGetMetadataForBaseDataVariableTypeTestAsync() { return GetTests().NodeGetMetadataForBaseDataVariableTypeTestAsync(); } [Fact] public Task NodeGetMetadataForPropertyTypeTestAsync() { return GetTests().NodeGetMetadataForPropertyTypeTestAsync(); } [Fact] public Task NodeGetMetadataForAudioVariableTypeTestAsync() { return GetTests().NodeGetMetadataForAudioVariableTypeTestAsync(); } [Fact] public Task NodeGetMetadataForServerStatusVariableTestAsync() { return GetTests().NodeGetMetadataForServerStatusVariableTestAsync(); } [Fact] public Task NodeGetMetadataForRedundancySupportPropertyTestAsync() { return GetTests().NodeGetMetadataForRedundancySupportPropertyTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/TestData/ReadCollection.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.TestData { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public class ReadCollection : ICollectionFixture { public const string Name = "TestDataServerReadModuleSdk"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/TestData/ValueReadArrayTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.TestData { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; [Collection(ReadCollection.Name)] public class ValueReadArrayTests : IClassFixture { public ValueReadArrayTests(TestDataServer server, PublisherModuleFixture module) { _server = server; _module = module; } private ReadArrayValueTests GetTests() { return new ReadArrayValueTests( _module.SdkContainer.Resolve>, _server.GetConnection(), (ep, n, s) => _server.Client.ReadValueAsync(new ConnectionModel { Endpoint = new EndpointModel { Url = ep.Endpoint.Url, Certificate = _server.Certificate?.RawData?.ToThumbprint() } }, n, s)); } private readonly TestDataServer _server; private readonly PublisherModuleFixture _module; [Fact] public Task NodeReadAllStaticArrayVariableNodeClassTest1Async() { return GetTests().NodeReadAllStaticArrayVariableNodeClassTest1Async(); } [Fact] public Task NodeReadAllStaticArrayVariableAccessLevelTest1Async() { return GetTests().NodeReadAllStaticArrayVariableAccessLevelTest1Async(); } [Fact] public Task NodeReadAllStaticArrayVariableWriteMaskTest1Async() { return GetTests().NodeReadAllStaticArrayVariableWriteMaskTest1Async(); } [Fact] public Task NodeReadAllStaticArrayVariableWriteMaskTest2Async() { return GetTests().NodeReadAllStaticArrayVariableWriteMaskTest2Async(); } [Fact] public Task NodeReadStaticArrayBooleanValueVariableTestAsync() { return GetTests().NodeReadStaticArrayBooleanValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArraySByteValueVariableTestAsync() { return GetTests().NodeReadStaticArraySByteValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayByteValueVariableTestAsync() { return GetTests().NodeReadStaticArrayByteValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayInt16ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayInt16ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayUInt16ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayUInt16ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayInt32ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayInt32ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayUInt32ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayUInt32ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayInt64ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayInt64ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayUInt64ValueVariableTestAsync() { return GetTests().NodeReadStaticArrayUInt64ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayFloatValueVariableTestAsync() { return GetTests().NodeReadStaticArrayFloatValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayDoubleValueVariableTestAsync() { return GetTests().NodeReadStaticArrayDoubleValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayStringValueVariableTestAsync() { return GetTests().NodeReadStaticArrayStringValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayDateTimeValueVariableTestAsync() { return GetTests().NodeReadStaticArrayDateTimeValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayGuidValueVariableTestAsync() { return GetTests().NodeReadStaticArrayGuidValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayByteStringValueVariableTestAsync() { return GetTests().NodeReadStaticArrayByteStringValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayXmlElementValueVariableTestAsync() { return GetTests().NodeReadStaticArrayXmlElementValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayNodeIdValueVariableTestAsync() { return GetTests().NodeReadStaticArrayNodeIdValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayExpandedNodeIdValueVariableTestAsync() { return GetTests().NodeReadStaticArrayExpandedNodeIdValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayQualifiedNameValueVariableTestAsync() { return GetTests().NodeReadStaticArrayQualifiedNameValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayLocalizedTextValueVariableTestAsync() { return GetTests().NodeReadStaticArrayLocalizedTextValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayStatusCodeValueVariableTestAsync() { return GetTests().NodeReadStaticArrayStatusCodeValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayVariantValueVariableTestAsync() { return GetTests().NodeReadStaticArrayVariantValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayEnumerationValueVariableTestAsync() { return GetTests().NodeReadStaticArrayEnumerationValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayStructureValueVariableTestAsync() { return GetTests().NodeReadStaticArrayStructureValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayNumberValueVariableTestAsync() { return GetTests().NodeReadStaticArrayNumberValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayIntegerValueVariableTestAsync() { return GetTests().NodeReadStaticArrayIntegerValueVariableTestAsync(); } [Fact] public Task NodeReadStaticArrayUIntegerValueVariableTestAsync() { return GetTests().NodeReadStaticArrayUIntegerValueVariableTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/TestData/ValueReadScalarTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.TestData { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; [Collection(ReadCollection.Name)] public class ValueReadScalarTests : IClassFixture { public ValueReadScalarTests(TestDataServer server, PublisherModuleFixture module) { _server = server; _module = module; } private ReadScalarValueTests GetTests() { return new ReadScalarValueTests( _module.SdkContainer.Resolve>, _server.GetConnection(), (ep, n, s) => _server.Client.ReadValueAsync(new ConnectionModel { Endpoint = new EndpointModel { Url = ep.Endpoint.Url, Certificate = _server.Certificate?.RawData?.ToThumbprint() } }, n, s)); } private readonly TestDataServer _server; private readonly PublisherModuleFixture _module; [Fact] public Task NodeReadAllStaticScalarVariableNodeClassTest1Async() { return GetTests().NodeReadAllStaticScalarVariableNodeClassTest1Async(); } [Fact] public Task NodeReadAllStaticScalarVariableAccessLevelTest1Async() { return GetTests().NodeReadAllStaticScalarVariableAccessLevelTest1Async(); } [Fact] public Task NodeReadAllStaticScalarVariableWriteMaskTest1Async() { return GetTests().NodeReadAllStaticScalarVariableWriteMaskTest1Async(); } [Fact] public Task NodeReadAllStaticScalarVariableWriteMaskTest2Async() { return GetTests().NodeReadAllStaticScalarVariableWriteMaskTest2Async(); } [Fact] public Task NodeReadStaticScalarBooleanValueVariableTestAsync() { return GetTests().NodeReadStaticScalarBooleanValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest1Async() { return GetTests().NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest1Async(); } [Fact] public Task NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest2Async() { return GetTests().NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest2Async(); } [Fact] public Task NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest3Async() { return GetTests().NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest3Async(); } [Fact] public Task NodeReadStaticScalarSByteValueVariableTestAsync() { return GetTests().NodeReadStaticScalarSByteValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarByteValueVariableTestAsync() { return GetTests().NodeReadStaticScalarByteValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarInt16ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarInt16ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarUInt16ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarUInt16ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarInt32ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarInt32ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarUInt32ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarUInt32ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarInt64ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarInt64ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarUInt64ValueVariableTestAsync() { return GetTests().NodeReadStaticScalarUInt64ValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarFloatValueVariableTestAsync() { return GetTests().NodeReadStaticScalarFloatValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarDoubleValueVariableTestAsync() { return GetTests().NodeReadStaticScalarDoubleValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarStringValueVariableTestAsync() { return GetTests().NodeReadStaticScalarStringValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarDateTimeValueVariableTestAsync() { return GetTests().NodeReadStaticScalarDateTimeValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarGuidValueVariableTestAsync() { return GetTests().NodeReadStaticScalarGuidValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarByteStringValueVariableTestAsync() { return GetTests().NodeReadStaticScalarByteStringValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarXmlElementValueVariableTestAsync() { return GetTests().NodeReadStaticScalarXmlElementValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarNodeIdValueVariableTestAsync() { return GetTests().NodeReadStaticScalarNodeIdValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarExpandedNodeIdValueVariableTestAsync() { return GetTests().NodeReadStaticScalarExpandedNodeIdValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarQualifiedNameValueVariableTestAsync() { return GetTests().NodeReadStaticScalarQualifiedNameValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarLocalizedTextValueVariableTestAsync() { return GetTests().NodeReadStaticScalarLocalizedTextValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarStatusCodeValueVariableTestAsync() { return GetTests().NodeReadStaticScalarStatusCodeValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarVariantValueVariableTestAsync() { return GetTests().NodeReadStaticScalarVariantValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarEnumerationValueVariableTestAsync() { return GetTests().NodeReadStaticScalarEnumerationValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarStructuredValueVariableTestAsync() { return GetTests().NodeReadStaticScalarStructuredValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarNumberValueVariableTestAsync() { return GetTests().NodeReadStaticScalarNumberValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarIntegerValueVariableTestAsync() { return GetTests().NodeReadStaticScalarIntegerValueVariableTestAsync(); } [Fact] public Task NodeReadStaticScalarUIntegerValueVariableTestAsync() { return GetTests().NodeReadStaticScalarUIntegerValueVariableTestAsync(); } [Fact] public Task NodeReadDataAccessMeasurementFloatValueTestAsync() { return GetTests().NodeReadDataAccessMeasurementFloatValueTestAsync(); } [Fact] public Task NodeReadDiagnosticsNoneTestAsync() { return GetTests().NodeReadDiagnosticsNoneTestAsync(); } [Fact] public Task NodeReadDiagnosticsStatusTestAsync() { return GetTests().NodeReadDiagnosticsStatusTestAsync(); } [Fact] public Task NodeReadDiagnosticsDebugTestAsync() { return GetTests().NodeReadDiagnosticsDebugTestAsync(); } [Fact] public Task NodeReadDiagnosticsVerboseTestAsync() { return GetTests().NodeReadDiagnosticsVerboseTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/TestData/ValueWriteArrayTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.TestData { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; [Collection(WriteCollection.Name)] public class ValueWriteArrayTests : IClassFixture { public ValueWriteArrayTests(TestDataServer server, PublisherModuleFixture module) { _server = server; _module = module; } private WriteArrayValueTests GetTests() { return new WriteArrayValueTests( _module.SdkContainer.Resolve>, _server.GetConnection(), (ep, n, s) => _server.Client.ReadValueAsync(new ConnectionModel { Endpoint = new EndpointModel { Url = ep.Endpoint.Url, Certificate = _server.Certificate?.RawData?.ToThumbprint() } }, n, s)); } private readonly TestDataServer _server; private readonly PublisherModuleFixture _module; [Fact] public Task NodeWriteStaticArrayBooleanValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayBooleanValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArraySByteValueVariableTestAsync() { return GetTests().NodeWriteStaticArraySByteValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayByteValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayByteValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayInt16ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayInt16ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayUInt16ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayUInt16ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayInt32ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayInt32ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayUInt32ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayUInt32ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayInt64ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayInt64ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayUInt64ValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayUInt64ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayFloatValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayFloatValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayDoubleValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayDoubleValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayStringValueVariableTest1Async() { return GetTests().NodeWriteStaticArrayStringValueVariableTest1Async(); } [Fact] public Task NodeWriteStaticArrayStringValueVariableTest2Async() { return GetTests().NodeWriteStaticArrayStringValueVariableTest2Async(); } [Fact] public Task NodeWriteStaticArrayDateTimeValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayDateTimeValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayGuidValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayGuidValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayByteStringValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayByteStringValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayXmlElementValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayXmlElementValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayNodeIdValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayNodeIdValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayExpandedNodeIdValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayExpandedNodeIdValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayQualifiedNameValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayQualifiedNameValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayLocalizedTextValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayLocalizedTextValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayStatusCodeValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayStatusCodeValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayVariantValueVariableTest1Async() { return GetTests().NodeWriteStaticArrayVariantValueVariableTest1Async(); } [Fact] public Task NodeWriteStaticArrayEnumerationValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayEnumerationValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayStructureValueVariableTestAsync() { return GetTests().NodeWriteStaticArrayStructureValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticArrayNumberValueVariableTest1Async() { return GetTests().NodeWriteStaticArrayNumberValueVariableTest1Async(); } [Fact] public Task NodeWriteStaticArrayNumberValueVariableTest2Async() { return GetTests().NodeWriteStaticArrayNumberValueVariableTest2Async(); } [Fact] public Task NodeWriteStaticArrayIntegerValueVariableTest1Async() { return GetTests().NodeWriteStaticArrayIntegerValueVariableTest1Async(); } [Fact] public Task NodeWriteStaticArrayIntegerValueVariableTest2Async() { return GetTests().NodeWriteStaticArrayIntegerValueVariableTest2Async(); } [Fact] public Task NodeWriteStaticArrayUIntegerValueVariableTest1Async() { return GetTests().NodeWriteStaticArrayUIntegerValueVariableTest1Async(); } [Fact] public Task NodeWriteStaticArrayUIntegerValueVariableTest2Async() { return GetTests().NodeWriteStaticArrayUIntegerValueVariableTest2Async(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/TestData/ValueWriteScalarTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.TestData { using Azure.IIoT.OpcUa.Publisher.Module.Tests.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Testing.Tests; using Autofac; using System.Threading.Tasks; using Xunit; [Collection(WriteCollection.Name)] public class ValueWriteScalarTests : IClassFixture { public ValueWriteScalarTests(TestDataServer server, PublisherModuleFixture module) { _server = server; _module = module; } private WriteScalarValueTests GetTests() { return new WriteScalarValueTests( _module.SdkContainer.Resolve>, _server.GetConnection(), (ep, n, s) => _server.Client.ReadValueAsync(new ConnectionModel { Endpoint = new EndpointModel { Url = ep.Endpoint.Url, Certificate = _server.Certificate?.RawData?.ToThumbprint() } }, n, s)); } private readonly TestDataServer _server; private readonly PublisherModuleFixture _module; [Fact] public Task NodeWriteStaticScalarBooleanValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarBooleanValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest1Async() { return GetTests().NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest1Async(); } [Fact] public Task NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest2Async() { return GetTests().NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest2Async(); } [Fact] public Task NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest3Async() { return GetTests().NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest3Async(); } [Fact] public Task NodeWriteStaticScalarSByteValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarSByteValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarByteValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarByteValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarInt16ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarInt16ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarUInt16ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarUInt16ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarInt32ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarInt32ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarUInt32ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarUInt32ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarInt64ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarInt64ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarUInt64ValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarUInt64ValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarFloatValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarFloatValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarDoubleValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarDoubleValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarStringValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarStringValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarDateTimeValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarDateTimeValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarGuidValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarGuidValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarByteStringValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarByteStringValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarXmlElementValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarXmlElementValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarNodeIdValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarNodeIdValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarExpandedNodeIdValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarExpandedNodeIdValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarQualifiedNameValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarQualifiedNameValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarLocalizedTextValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarLocalizedTextValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarStatusCodeValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarStatusCodeValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarVariantValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarVariantValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarEnumerationValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarEnumerationValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarStructuredValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarStructuredValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarNumberValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarNumberValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarIntegerValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarIntegerValueVariableTestAsync(); } [Fact] public Task NodeWriteStaticScalarUIntegerValueVariableTestAsync() { return GetTests().NodeWriteStaticScalarUIntegerValueVariableTestAsync(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/Sdk/TestData/WriteCollection.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Module.Tests.Sdk.TestData { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Xunit; [CollectionDefinition(Name)] public class WriteCollection : ICollectionFixture { public const string Name = "TestDataServerWriteModuleSdk"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Module/tests/_dummy_.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.14.36414.22 MinimumVisualStudioVersion = 10.0.40219.1 Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {9B79D755-DAB7-4AC6-8EC0-CB877B3DDA53} EndGlobalSection EndGlobal ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Sdk/src/Azure.IIoT.OpcUa.Publisher.Sdk.csproj ================================================  net9.0 true true true Azure OPC Publisher Module Sdk enable ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Sdk/src/Clients/DiscoveryApiClient.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Sdk.Clients { using Azure.IIoT.OpcUa.Publisher.Sdk; using Azure.IIoT.OpcUa.Publisher.Models; using Furly; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Furly.Tunnel; using Microsoft.Extensions.Options; using System; using System.Threading; using System.Threading.Tasks; /// /// Implements node and publish services through command control against /// the OPC Publihser module receiving service requests via device method calls. /// public sealed class DiscoveryApiClient : IDiscoveryApi { /// /// Create module client /// /// /// /// /// public DiscoveryApiClient(IMethodClient methodClient, string target, TimeSpan? timeout = null, IJsonSerializer? serializer = null) { _serializer = serializer ?? new NewtonsoftJsonSerializer(); _methodClient = methodClient ?? throw new ArgumentNullException(nameof(methodClient)); if (string.IsNullOrEmpty(target)) { throw new ArgumentNullException(nameof(target)); } _target = target; _timeout = timeout ?? TimeSpan.FromMinutes(1); } /// /// Create module client /// /// /// /// public DiscoveryApiClient(IMethodClient methodClient, IOptions options, IJsonSerializer? serializer = null) : this(methodClient, options.Value.Target!, options.Value.Timeout, serializer) { } /// public async Task GetEndpointCertificateAsync( EndpointModel endpoint, CancellationToken ct) { ArgumentNullException.ThrowIfNull(endpoint); var response = await _methodClient.CallMethodAsync(_target, "GetEndpointCertificate_V2", _serializer.SerializeToMemory(endpoint), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task CancelAsync(DiscoveryCancelRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); await _methodClient.CallMethodAsync(_target, "Cancel_V2", _serializer.SerializeToMemory(request), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); } /// public async Task DiscoverAsync(DiscoveryRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); await _methodClient.CallMethodAsync(_target, "Discover_V2", _serializer.SerializeToMemory(request), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); } /// public async Task RegisterAsync(ServerRegistrationRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); await _methodClient.CallMethodAsync(_target, "Register_V2", _serializer.SerializeToMemory(request), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); } /// public async Task FindServerAsync( ServerEndpointQueryModel query, CancellationToken ct) { ArgumentNullException.ThrowIfNull(query); var response = await _methodClient.CallMethodAsync(_target, "FindServer_V2", _serializer.SerializeToMemory(query), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } private readonly IJsonSerializer _serializer; private readonly IMethodClient _methodClient; private readonly string _target; private readonly TimeSpan _timeout; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Sdk/src/Clients/Extensions.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Sdk.Clients { using Furly.Exceptions; using Furly.Extensions.Serializers; using System; /// /// Helper extensions shared by clients /// internal static class Extensions { /// /// Deserialize the response or throw if failed. /// /// /// Register serializers. /// Options with serializer configuration. /// /// public static T DeserializeResponse(this ISerializer serializer, ReadOnlyMemory buffer) { return serializer.Deserialize(buffer) ?? throw new MethodCallException("Bad response"); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Sdk/src/Clients/HistoryApiClient.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Sdk.Clients { using Azure.IIoT.OpcUa.Publisher.Models; using Furly; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Furly.Tunnel; using Microsoft.Extensions.Options; using System; using System.Threading; using System.Threading.Tasks; /// /// Implementation of history api. /// public sealed class HistoryApiClient : IHistoryApi { /// /// Create module client /// /// /// /// /// public HistoryApiClient(IMethodClient methodClient, string target, TimeSpan? timeout = null, IJsonSerializer? serializer = null) { _serializer = serializer ?? new NewtonsoftJsonSerializer(); _methodClient = methodClient ?? throw new ArgumentNullException(nameof(methodClient)); if (string.IsNullOrEmpty(target)) { throw new ArgumentNullException(nameof(target)); } _target = target; _timeout = timeout ?? TimeSpan.FromMinutes(1); } /// /// Create module client /// /// /// /// public HistoryApiClient(IMethodClient methodClient, IOptions options, IJsonSerializer? serializer = null) : this(methodClient, options.Value.Target!, options.Value.Timeout, serializer) { } /// public async Task> HistoryReadValuesAsync( ConnectionModel connection, HistoryReadRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); if (request.Details == null) { throw new ArgumentException("Details missing.", nameof(request)); } var response = await _methodClient.CallMethodAsync(_target, "HistoryReadValues_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse>(response); } /// public async Task> HistoryReadModifiedValuesAsync( ConnectionModel connection, HistoryReadRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); if (request.Details == null) { throw new ArgumentException("Details missing.", nameof(request)); } var response = await _methodClient.CallMethodAsync(_target, "HistoryReadModifiedValues_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse>(response); } /// public async Task> HistoryReadValuesAtTimesAsync( ConnectionModel connection, HistoryReadRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); if (request.Details == null) { throw new ArgumentException("Details missing.", nameof(request)); } var response = await _methodClient.CallMethodAsync(_target, "HistoryReadValuesAtTimes_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse>(response); } /// public async Task> HistoryReadProcessedValuesAsync( ConnectionModel connection, HistoryReadRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); if (request.Details == null) { throw new ArgumentException("Details missing.", nameof(request)); } var response = await _methodClient.CallMethodAsync(_target, "HistoryReadProcessedValues_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse>(response); } /// public async Task> HistoryReadValuesNextAsync( ConnectionModel connection, HistoryReadNextRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); if (request.ContinuationToken == null) { throw new ArgumentException("Continuation missing.", nameof(request)); } var response = await _methodClient.CallMethodAsync(_target, "HistoryReadValuesNext_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse>(response); } /// public async Task HistoryReplaceValuesAsync(ConnectionModel connection, HistoryUpdateRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); if (request.Details == null) { throw new ArgumentException("Details missing.", nameof(request)); } var response = await _methodClient.CallMethodAsync(_target, "HistoryReplaceValues_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task HistoryInsertValuesAsync(ConnectionModel connection, HistoryUpdateRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); if (request.Details == null) { throw new ArgumentException("Details missing.", nameof(request)); } var response = await _methodClient.CallMethodAsync(_target, "HistoryInsertValues_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task HistoryUpsertValuesAsync(ConnectionModel connection, HistoryUpdateRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); if (request.Details == null) { throw new ArgumentException("Details missing.", nameof(request)); } var response = await _methodClient.CallMethodAsync(_target, "HistoryUpsertValues_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task HistoryDeleteValuesAsync(ConnectionModel connection, HistoryUpdateRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); if (request.Details == null) { throw new ArgumentException("Details missing.", nameof(request)); } var response = await _methodClient.CallMethodAsync(_target, "HistoryDeleteValues_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task HistoryDeleteModifiedValuesAsync( ConnectionModel connection, HistoryUpdateRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); if (request.Details == null) { throw new ArgumentException("Details missing.", nameof(request)); } var response = await _methodClient.CallMethodAsync(_target, "HistoryDeleteModifiedValues_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task HistoryDeleteValuesAtTimesAsync( ConnectionModel connection, HistoryUpdateRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); if (request.Details == null) { throw new ArgumentException("Details missing.", nameof(request)); } var response = await _methodClient.CallMethodAsync(_target, "HistoryDeleteValuesAtTimes_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task> HistoryReadEventsAsync( ConnectionModel connection, HistoryReadRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); if (request.Details == null) { throw new ArgumentException("Details missing.", nameof(request)); } var response = await _methodClient.CallMethodAsync(_target, "HistoryReadEvents_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse>(response); } /// public async Task> HistoryReadEventsNextAsync( ConnectionModel connection, HistoryReadNextRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); if (request.ContinuationToken == null) { throw new ArgumentException("Continuation missing.", nameof(request)); } var response = await _methodClient.CallMethodAsync(_target, "HistoryReadEventsNext_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse>(response); } /// public async Task HistoryReplaceEventsAsync(ConnectionModel connection, HistoryUpdateRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); if (request.Details == null) { throw new ArgumentException("Details missing.", nameof(request)); } var response = await _methodClient.CallMethodAsync(_target, "HistoryReplaceEvents_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task HistoryInsertEventsAsync(ConnectionModel connection, HistoryUpdateRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); if (request.Details == null) { throw new ArgumentException("Details missing.", nameof(request)); } var response = await _methodClient.CallMethodAsync(_target, "HistoryInsertEvents_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task HistoryUpsertEventsAsync(ConnectionModel connection, HistoryUpdateRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); if (request.Details == null) { throw new ArgumentException("Details missing.", nameof(request)); } var response = await _methodClient.CallMethodAsync(_target, "HistoryUpsertEvents_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task HistoryDeleteEventsAsync(ConnectionModel connection, HistoryUpdateRequestModel request, CancellationToken ct = default) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); if (request.Details == null) { throw new ArgumentException("Details missing.", nameof(request)); } var response = await _methodClient.CallMethodAsync(_target, "HistoryDeleteEvents_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } private readonly ISerializer _serializer; private readonly IMethodClient _methodClient; private readonly string _target; private readonly TimeSpan _timeout; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Sdk/src/Clients/PublisherApiClient.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Sdk.Clients { using Azure.IIoT.OpcUa.Publisher.Sdk; using Azure.IIoT.OpcUa.Publisher.Models; using Furly; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Furly.Tunnel; using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; /// /// Implements node and publish services through command control against /// the OPC Publihser module. /// public sealed class PublisherApiClient : IPublisherApi { /// /// Create module client /// /// /// /// /// public PublisherApiClient(IMethodClient methodClient, string target, TimeSpan? timeout = null, IJsonSerializer? serializer = null) { _serializer = serializer ?? new NewtonsoftJsonSerializer(); _methodClient = methodClient ?? throw new ArgumentNullException(nameof(methodClient)); if (string.IsNullOrEmpty(target)) { throw new ArgumentNullException(nameof(target)); } _target = target; _timeout = timeout ?? TimeSpan.FromMinutes(1); } /// /// Create module client /// /// /// /// public PublisherApiClient(IMethodClient methodClient, IOptions options, IJsonSerializer? serializer = null) : this(methodClient, options.Value.Target!, options.Value.Timeout, serializer) { } /// public async Task CreateOrUpdateDataSetWriterEntryAsync(PublishedNodesEntryModel entry, CancellationToken ct) { ArgumentNullException.ThrowIfNull(entry); await _methodClient.CallMethodAsync(_target, "CreateOrUpdateDataSetWriterEntry", _serializer.SerializeToMemory(entry), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); } /// public async Task GetDataSetWriterEntryAsync(string dataSetWriterGroup, string dataSetWriterId, CancellationToken ct) { ArgumentException.ThrowIfNullOrEmpty(dataSetWriterGroup); ArgumentException.ThrowIfNullOrEmpty(dataSetWriterId); var response = await _methodClient.CallMethodAsync(_target, "GetDataSetWriterEntry", _serializer.SerializeToMemory(new { dataSetWriterGroup, dataSetWriterId }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task AddOrUpdateNodesAsync(string dataSetWriterGroup, string dataSetWriterId, IReadOnlyList opcNodes, string? insertAfterFieldId, CancellationToken ct) { ArgumentNullException.ThrowIfNull(dataSetWriterGroup); ArgumentNullException.ThrowIfNull(dataSetWriterId); await _methodClient.CallMethodAsync(_target, "AddOrUpdateNodes", _serializer.SerializeToMemory(new { dataSetWriterGroup, dataSetWriterId, opcNodes, insertAfterFieldId }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); } /// public async Task RemoveNodesAsync(string dataSetWriterGroup, string dataSetWriterId, IReadOnlyList dataSetFieldIds, CancellationToken ct) { ArgumentException.ThrowIfNullOrEmpty(dataSetWriterGroup); ArgumentException.ThrowIfNullOrEmpty(dataSetWriterId); ArgumentNullException.ThrowIfNull(dataSetFieldIds); if (dataSetFieldIds.Count == 0) { throw new ArgumentException("No fields to remove.", nameof(dataSetFieldIds)); } await _methodClient.CallMethodAsync(_target, "RemoveNodes", _serializer.SerializeToMemory(new { dataSetWriterGroup, dataSetWriterId, dataSetFieldIds }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); } /// public async Task> GetNodesAsync(string dataSetWriterGroup, string dataSetWriterId, string? lastDataSetFieldId, int? pageSize, CancellationToken ct) { ArgumentException.ThrowIfNullOrEmpty(dataSetWriterGroup); ArgumentException.ThrowIfNullOrEmpty(dataSetWriterId); var response = await _methodClient.CallMethodAsync(_target, "GetNodes", _serializer.SerializeToMemory(new { dataSetWriterGroup, dataSetWriterId, lastDataSetFieldId, pageSize }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse>(response); } /// public async Task RemoveDataSetWriterEntryAsync(string dataSetWriterGroup, string dataSetWriterId, CancellationToken ct) { ArgumentException.ThrowIfNullOrEmpty(dataSetWriterGroup); ArgumentException.ThrowIfNullOrEmpty(dataSetWriterId); await _methodClient.CallMethodAsync(_target, "RemoveDataSetWriterEntry", _serializer.SerializeToMemory(new { dataSetWriterGroup, dataSetWriterId }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); } /// public async Task PublishStartAsync(ConnectionModel connection, PublishStartRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); var response = await _methodClient.CallMethodAsync(_target, "PublishStart", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task PublishStopAsync(ConnectionModel connection, PublishStopRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); var response = await _methodClient.CallMethodAsync(_target, "PublishStop", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task PublishBulkAsync(ConnectionModel connection, PublishBulkRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); var response = await _methodClient.CallMethodAsync(_target, "PublishBulk", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task PublishListAsync(ConnectionModel connection, PublishedItemListRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); var response = await _methodClient.CallMethodAsync(_target, "PublishList", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task PublishNodesAsync( PublishedNodesEntryModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); var response = await _methodClient.CallMethodAsync(_target, "PublishNodes", _serializer.SerializeToMemory(request), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task UnpublishNodesAsync( PublishedNodesEntryModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); var response = await _methodClient.CallMethodAsync(_target, "UnpublishNodes", _serializer.SerializeToMemory(request), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task UnpublishAllNodesAsync( PublishedNodesEntryModel? request, CancellationToken ct) { var response = await _methodClient.CallMethodAsync(_target, "UnpublishAllNodes", _serializer.SerializeToMemory(request), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task AddOrUpdateEndpointsAsync( IReadOnlyList request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); var response = await _methodClient.CallMethodAsync(_target, "AddOrUpdateEndpoints", _serializer.SerializeToMemory(request), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task GetConfiguredEndpointsAsync( GetConfiguredEndpointsRequestModel? request, CancellationToken ct) { var response = await _methodClient.CallMethodAsync(_target, "GetConfiguredEndpoints", request == null ? null : _serializer.SerializeToMemory(request), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task SetConfiguredEndpointsAsync( SetConfiguredEndpointsRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); await _methodClient.CallMethodAsync(_target, "SetConfiguredEndpoints", _serializer.SerializeToMemory(request), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); } /// public async Task GetConfiguredNodesOnEndpointAsync( PublishedNodesEntryModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(request); var response = await _methodClient.CallMethodAsync(_target, "GetConfiguredNodesOnEndpoint", _serializer.SerializeToMemory(request), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task> GetDiagnosticInfoAsync(CancellationToken ct) { var response = await _methodClient.CallMethodAsync(_target, "GetDiagnosticInfo", null, ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse>(response); } /// public async Task ShutdownAsync(bool failFast, CancellationToken ct) { await _methodClient.CallMethodAsync(_target, "Shutdown", _serializer.SerializeToMemory(failFast), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); } /// public async Task GetServerCertificateAsync(CancellationToken ct) { var response = await _methodClient.CallMethodAsync(_target, "GetServerCertificate", null, ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task GetApiKeyAsync(CancellationToken ct) { var response = await _methodClient.CallMethodAsync(_target, "GetApiKey", null, ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } private readonly IJsonSerializer _serializer; private readonly IMethodClient _methodClient; private readonly string _target; private readonly TimeSpan _timeout; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Sdk/src/Clients/TwinApiClient.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Sdk.Clients { using Azure.IIoT.OpcUa.Publisher.Models; using Furly; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Newtonsoft; using Furly.Tunnel; using Microsoft.Extensions.Options; using System; using System.Linq; using System.Threading; using System.Threading.Tasks; /// /// Implementation of twin api. /// public sealed class TwinApiClient : ITwinApi { /// /// Create module client /// /// /// /// /// public TwinApiClient(IMethodClient methodClient, string target, TimeSpan? timeout = null, IJsonSerializer? serializer = null) { _serializer = serializer ?? new NewtonsoftJsonSerializer(); _methodClient = methodClient ?? throw new ArgumentNullException(nameof(methodClient)); if (string.IsNullOrEmpty(target)) { throw new ArgumentNullException(nameof(target)); } _target = target; _timeout = timeout ?? TimeSpan.FromMinutes(1); } /// /// Create module client /// /// /// /// public TwinApiClient(IMethodClient methodClient, IOptions options, IJsonSerializer? serializer = null) : this(methodClient, options.Value.Target!, options.Value.Timeout, serializer) { } /// public async Task TestConnectionAsync( ConnectionModel connection, TestConnectionRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); var response = await _methodClient.CallMethodAsync(_target, "TestConnection_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task NodeBrowseFirstAsync(ConnectionModel connection, BrowseFirstRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); var response = await _methodClient.CallMethodAsync(_target, "Browse_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task NodeBrowseNextAsync(ConnectionModel connection, BrowseNextRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); if (request.ContinuationToken == null) { throw new ArgumentException("Continuation missing.", nameof(request)); } var response = await _methodClient.CallMethodAsync(_target, "BrowseNext_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task NodeBrowsePathAsync(ConnectionModel connection, BrowsePathRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); if (request.BrowsePaths == null || request.BrowsePaths.Count == 0 || request.BrowsePaths.Any(p => p == null || p.Count == 0)) { throw new ArgumentException("Browse paths missing.", nameof(request)); } var response = await _methodClient.CallMethodAsync(_target, "BrowsePath_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task NodeReadAsync(ConnectionModel connection, ReadRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); if (request.Attributes == null || request.Attributes.Count == 0) { throw new ArgumentException(nameof(request.Attributes)); } var response = await _methodClient.CallMethodAsync(_target, "NodeRead_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task NodeWriteAsync(ConnectionModel connection, WriteRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); if (request.Attributes == null || request.Attributes.Count == 0) { throw new ArgumentException(nameof(request.Attributes)); } var response = await _methodClient.CallMethodAsync(_target, "NodeWrite_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task NodeValueReadAsync(ConnectionModel connection, ValueReadRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); var response = await _methodClient.CallMethodAsync(_target, "ValueRead_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task NodeValueWriteAsync(ConnectionModel connection, ValueWriteRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); if (request.Value is null) { throw new ArgumentException("Value missing.", nameof(request)); } var response = await _methodClient.CallMethodAsync(_target, "ValueWrite_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task NodeMethodGetMetadataAsync( ConnectionModel connection, MethodMetadataRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); var response = await _methodClient.CallMethodAsync(_target, "MethodMetadata_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task NodeMethodCallAsync( ConnectionModel connection, MethodCallRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); var response = await _methodClient.CallMethodAsync(_target, "MethodCall_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task GetServerCapabilitiesAsync( ConnectionModel connection, RequestHeaderModel? header, CancellationToken ct) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } var response = await _methodClient.CallMethodAsync(_target, "GetServerCapabilities_V2", _serializer.SerializeToMemory(new { connection, header }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task GetMetadataAsync(ConnectionModel connection, NodeMetadataRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); var response = await _methodClient.CallMethodAsync(_target, "GetMetadata_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task CompileQueryAsync(ConnectionModel connection, QueryCompilationRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); var response = await _methodClient.CallMethodAsync(_target, "CompileQuery_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task HistoryGetServerCapabilitiesAsync( ConnectionModel connection, RequestHeaderModel? header, CancellationToken ct) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } var response = await _methodClient.CallMethodAsync(_target, "HistoryGetServerCapabilities_V2", _serializer.SerializeToMemory(new { connection, header }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task HistoryGetConfigurationAsync( ConnectionModel connection, HistoryConfigurationRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); var response = await _methodClient.CallMethodAsync(_target, "HistoryGetConfiguration_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } /// public async Task> HistoryReadAsync( ConnectionModel connection, HistoryReadRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); if (request.Details == null) { throw new ArgumentException("Details missing.", nameof(request)); } var response = await _methodClient.CallMethodAsync(_target, "HistoryRead_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse>(response); } /// public async Task> HistoryReadNextAsync( ConnectionModel connection, HistoryReadNextRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); if (string.IsNullOrEmpty(request.ContinuationToken)) { throw new ArgumentException("Continuation missing.", nameof(request)); } var response = await _methodClient.CallMethodAsync(_target, "HistoryReadNext_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse>(response); } /// public async Task HistoryUpdateAsync( ConnectionModel connection, HistoryUpdateRequestModel request, CancellationToken ct) { ArgumentNullException.ThrowIfNull(connection); if (string.IsNullOrEmpty(connection.Endpoint?.Url)) { throw new ArgumentException("Endpoint Url missing.", nameof(connection)); } ArgumentNullException.ThrowIfNull(request); if (request.Details == null) { throw new ArgumentException("Details missing.", nameof(request)); } var response = await _methodClient.CallMethodAsync(_target, "HistoryUpdate_V2", _serializer.SerializeToMemory(new { connection, request }), ContentMimeType.Json, _timeout, ct).ConfigureAwait(false); return _serializer.DeserializeResponse(response); } private readonly IJsonSerializer _serializer; private readonly IMethodClient _methodClient; private readonly string _target; private readonly TimeSpan _timeout; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Sdk/src/IDiscoveryApi.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Sdk { using Azure.IIoT.OpcUa.Publisher.Models; using System.Threading; using System.Threading.Tasks; /// /// Discovery api /// public interface IDiscoveryApi { /// /// Kick off onboarding of new server /// /// /// /// Task RegisterAsync(ServerRegistrationRequestModel request, CancellationToken ct = default); /// /// Kick off a one time discovery on all supervisors /// /// /// /// Task DiscoverAsync(DiscoveryRequestModel request, CancellationToken ct = default); /// /// Cancel a discovery request with a particular id /// /// /// /// Task CancelAsync(DiscoveryCancelRequestModel request, CancellationToken ct = default); /// /// Find a server using the endpoint url in the query /// object. Returns a application registration object only /// if the endpoint is part of the application's endpoint /// list. /// /// /// /// Task FindServerAsync( ServerEndpointQueryModel query, CancellationToken ct = default); /// /// Get the certificate of an endpoint /// /// /// /// Task GetEndpointCertificateAsync( EndpointModel endpoint, CancellationToken ct = default); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Sdk/src/IHistoryApi.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Sdk { using Azure.IIoT.OpcUa.Publisher.Models; using System.Threading; using System.Threading.Tasks; /// /// Represents OPC Historic Access api /// public interface IHistoryApi { /// /// Read raw historic values /// /// /// /// /// Task> HistoryReadValuesAsync( ConnectionModel connection, HistoryReadRequestModel request, CancellationToken ct = default); /// /// Read modified historic values /// /// /// /// /// Task> HistoryReadModifiedValuesAsync( ConnectionModel connection, HistoryReadRequestModel request, CancellationToken ct = default); /// /// Read historic values at specific datum /// /// /// /// /// Task> HistoryReadValuesAtTimesAsync( ConnectionModel connection, HistoryReadRequestModel request, CancellationToken ct = default); /// /// Read processed historic values /// /// /// /// /// Task> HistoryReadProcessedValuesAsync( ConnectionModel connection, HistoryReadRequestModel request, CancellationToken ct = default); /// /// Read next set of historic values /// /// /// /// /// Task> HistoryReadValuesNextAsync( ConnectionModel connection, HistoryReadNextRequestModel request, CancellationToken ct = default); /// /// Replace historic values /// /// /// /// /// Task HistoryReplaceValuesAsync(ConnectionModel connection, HistoryUpdateRequestModel request, CancellationToken ct = default); /// /// Insert historic values /// /// /// /// /// Task HistoryInsertValuesAsync(ConnectionModel connection, HistoryUpdateRequestModel request, CancellationToken ct = default); /// /// Upsert historic values /// /// /// /// /// Task HistoryUpsertValuesAsync(ConnectionModel connection, HistoryUpdateRequestModel request, CancellationToken ct = default); /// /// Delete historic values /// /// /// /// /// Task HistoryDeleteValuesAsync(ConnectionModel connection, HistoryUpdateRequestModel request, CancellationToken ct = default); /// /// Delete historic values /// /// /// /// /// Task HistoryDeleteModifiedValuesAsync(ConnectionModel connection, HistoryUpdateRequestModel request, CancellationToken ct = default); /// /// Delete historic values at specified datum /// /// /// /// /// Task HistoryDeleteValuesAtTimesAsync(ConnectionModel connection, HistoryUpdateRequestModel request, CancellationToken ct = default); /// /// Read event history /// /// /// /// /// Task> HistoryReadEventsAsync( ConnectionModel connection, HistoryReadRequestModel request, CancellationToken ct = default); /// /// Read next set of historic events /// /// /// /// /// Task> HistoryReadEventsNextAsync( ConnectionModel connection, HistoryReadNextRequestModel request, CancellationToken ct = default); /// /// Replace historic events /// /// /// /// /// Task HistoryReplaceEventsAsync(ConnectionModel connection, HistoryUpdateRequestModel request, CancellationToken ct = default); /// /// Insert historic events /// /// /// /// /// Task HistoryInsertEventsAsync(ConnectionModel connection, HistoryUpdateRequestModel request, CancellationToken ct = default); /// /// Upsert historic events /// /// /// /// /// Task HistoryUpsertEventsAsync(ConnectionModel connection, HistoryUpdateRequestModel request, CancellationToken ct = default); /// /// Delete event history /// /// /// /// /// Task HistoryDeleteEventsAsync(ConnectionModel connection, HistoryUpdateRequestModel request, CancellationToken ct = default); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Sdk/src/IPublisherApi.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Sdk { using Azure.IIoT.OpcUa.Publisher.Models; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; /// /// Publisher module api /// public interface IPublisherApi { /// /// Create a published nodes entry for a specific writer group and /// dataset writer. /// /// /// /// Task CreateOrUpdateDataSetWriterEntryAsync( PublishedNodesEntryModel entry, CancellationToken ct = default); /// /// Get the published nodes entry for a specific writer group and dataset /// writer. /// /// /// /// /// Task GetDataSetWriterEntryAsync( string dataSetWriterGroup, string dataSetWriterId, CancellationToken ct = default); /// /// Add Nodes to a dedicated data set writer in a writer group. /// /// /// /// /// /// /// Task AddOrUpdateNodesAsync(string dataSetWriterGroup, string dataSetWriterId, IReadOnlyList opcNodes, string? insertAfterFieldId = null, CancellationToken ct = default); /// /// Remove Nodes with the data set field ids from a data set writer in /// a writer group. /// /// /// /// /// /// Task RemoveNodesAsync(string dataSetWriterGroup, string dataSetWriterId, IReadOnlyList dataSetFieldIds, CancellationToken ct = default); /// /// Get Nodes from a data set writer in a writer group. /// /// /// /// /// /// /// Task> GetNodesAsync(string dataSetWriterGroup, string dataSetWriterId, string? lastDataSetFieldId = null, int? pageSize = null, CancellationToken ct = default); /// /// Remove the published nodes entry for a specific data set /// writer in a writer group. /// /// /// /// /// Task RemoveDataSetWriterEntryAsync(string dataSetWriterGroup, string dataSetWriterId, CancellationToken ct = default); /// /// Get configured endpoints /// /// /// /// Task GetConfiguredEndpointsAsync( GetConfiguredEndpointsRequestModel? request = null, CancellationToken ct = default); /// /// Get nodes of an endpoint /// /// /// /// Task GetConfiguredNodesOnEndpointAsync( PublishedNodesEntryModel request, CancellationToken ct = default); /// /// Set configured endpoints /// /// /// /// Task SetConfiguredEndpointsAsync(SetConfiguredEndpointsRequestModel request, CancellationToken ct = default); /// /// Add or update publishing endpoints /// /// /// /// Task AddOrUpdateEndpointsAsync( IReadOnlyList request, CancellationToken ct = default); /// /// Publish nodes /// /// /// /// Task PublishNodesAsync( PublishedNodesEntryModel request, CancellationToken ct = default); /// /// Remove all nodes on endpoint /// /// /// /// Task UnpublishAllNodesAsync( PublishedNodesEntryModel? request = null, CancellationToken ct = default); /// /// Stop publishing specified nodes on endpoint /// /// /// /// Task UnpublishNodesAsync( PublishedNodesEntryModel request, CancellationToken ct = default); /// /// Start publishing node values /// /// /// /// /// Task PublishStartAsync(ConnectionModel connection, PublishStartRequestModel request, CancellationToken ct = default); /// /// Start publishing node values /// /// /// /// /// Task PublishStopAsync(ConnectionModel connection, PublishStopRequestModel request, CancellationToken ct = default); /// /// Configure nodes to publish and unpublish in bulk /// /// /// /// /// Task PublishBulkAsync(ConnectionModel connection, PublishBulkRequestModel request, CancellationToken ct = default); /// /// Get all published nodes for connection. /// /// /// /// /// Task PublishListAsync(ConnectionModel connection, PublishedItemListRequestModel request, CancellationToken ct = default); /// /// Get diagnostic info /// /// /// Task> GetDiagnosticInfoAsync( CancellationToken ct = default); /// /// Shutdown publisher /// /// /// /// Task ShutdownAsync(bool failFast = false, CancellationToken ct = default); /// /// Get server certificate as PEM string /// /// /// Task GetServerCertificateAsync(CancellationToken ct = default); /// /// Get api key as string /// /// /// Task GetApiKeyAsync(CancellationToken ct = default); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Sdk/src/ITwinApi.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Sdk { using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Extensions.Serializers; using System.Threading; using System.Threading.Tasks; /// /// Represents Twin api /// public interface ITwinApi { /// /// This call is used to test a connection by opening a session /// to the server identified by the connection object. /// /// /// /// /// Task TestConnectionAsync( ConnectionModel connection, TestConnectionRequestModel request, CancellationToken ct = default); /// /// Get the capabilities of the server /// /// /// /// /// Task GetServerCapabilitiesAsync( ConnectionModel connection, RequestHeaderModel? header = null, CancellationToken ct = default); /// /// Browse node on a server /// /// /// /// /// Task NodeBrowseFirstAsync(ConnectionModel connection, BrowseFirstRequestModel request, CancellationToken ct = default); /// /// Browse next references on a server /// /// /// /// /// Task NodeBrowseNextAsync(ConnectionModel connection, BrowseNextRequestModel request, CancellationToken ct = default); /// /// Browse by path on a server /// /// /// /// /// Task NodeBrowsePathAsync(ConnectionModel connection, BrowsePathRequestModel request, CancellationToken ct = default); /// /// Get the node metadata which includes the fields /// and meta data of the type and can be used when constructing /// event filters or calling methods to pass the correct arguments. /// /// /// /// /// Task GetMetadataAsync(ConnectionModel connection, NodeMetadataRequestModel request, CancellationToken ct = default); /// /// Compile the query string into a filter query syntax /// structure that can be used in other calls. /// /// /// /// /// Task CompileQueryAsync(ConnectionModel connection, QueryCompilationRequestModel request, CancellationToken ct = default); /// /// Call method on a server /// /// /// /// /// Task NodeMethodCallAsync(ConnectionModel connection, MethodCallRequestModel request, CancellationToken ct = default); /// /// Get meta data for method call on a server /// /// /// /// /// Task NodeMethodGetMetadataAsync(ConnectionModel connection, MethodMetadataRequestModel request, CancellationToken ct = default); /// /// Read node value on a server /// /// /// /// /// Task NodeValueReadAsync(ConnectionModel connection, ValueReadRequestModel request, CancellationToken ct = default); /// /// Write node value on a server /// /// /// /// /// Task NodeValueWriteAsync(ConnectionModel connection, ValueWriteRequestModel request, CancellationToken ct = default); /// /// Read node attributes on a server /// /// /// /// /// Task NodeReadAsync(ConnectionModel connection, ReadRequestModel request, CancellationToken ct = default); /// /// Write node attributes on a server /// /// /// /// /// Task NodeWriteAsync(ConnectionModel connection, WriteRequestModel request, CancellationToken ct = default); /// /// Get history server capabilities /// /// /// /// /// Task HistoryGetServerCapabilitiesAsync( ConnectionModel connection, RequestHeaderModel? header = null, CancellationToken ct = default); /// /// Get a node's history configuration /// /// /// /// /// Task HistoryGetConfigurationAsync( ConnectionModel connection, HistoryConfigurationRequestModel request, CancellationToken ct = default); /// /// Read node history with custom encoded extension object details /// /// /// /// /// Task> HistoryReadAsync( ConnectionModel connection, HistoryReadRequestModel request, CancellationToken ct = default); /// /// Read history call with custom encoded extension object details /// /// /// /// /// Task> HistoryReadNextAsync( ConnectionModel connection, HistoryReadNextRequestModel request, CancellationToken ct = default); /// /// Update using extension object details /// /// /// /// /// Task HistoryUpdateAsync( ConnectionModel connection, HistoryUpdateRequestModel request, CancellationToken ct = default); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Sdk/src/Properties/AssemblyInfo.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Azure.IIoT.OpcUa.Publisher.Sdk.Tests")] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Sdk/src/SdkOptions.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Sdk { using System; /// /// Configuration for IoT Edge Opc Publisher sdk /// public sealed class SdkOptions { /// /// Edge target path. This is the mount path of the /// publisher'smethod router which using the publisher /// module's command line arguments and is defaulting to /// /// {PublisherId}/methods /// /// or the device and module identifier in the form of /// /// {deviceId}_module_{moduleId} /// . /// public string? Target { get; set; } /// /// Call timeout /// public TimeSpan? Timeout { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/cli/Azure.IIoT.OpcUa.Publisher.Testing.Cli.csproj ================================================  Exe net9.0 true disable true false iot/opc-ua-test-server linux-x64 mcr.microsoft.com/dotnet/runtime:9.0-azurelinux3.0-distroless-extra ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/cli/FlatCertificateStore.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Cli { using Opc.Ua; using Opc.Ua.Security.Certificates; using System; using System.IO; using System.Linq; using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; /// /// A flat certificate store option to use with a secret/volume mount /// public sealed class FlatCertificateStore : ICertificateStoreType { /// /// Identifier for flat directory certificate store. /// public const string StoreTypeName = "FlatDirectory"; /// /// Prefix for flat directory certificate store. /// public const string StoreTypePrefix = $"{StoreTypeName}:"; /// public ICertificateStore CreateStore() => new FlatDirectoryCertificateStore(); /// public bool SupportsStorePath(string storePath) => !string.IsNullOrEmpty(storePath) && storePath.StartsWith(StoreTypePrefix, StringComparison.InvariantCultureIgnoreCase); internal sealed class FlatDirectoryCertificateStore : ICertificateStore { private const string CrtExtension = ".crt"; private const string KeyExtension = ".key"; private readonly DirectoryCertificateStore _innerStore; /// /// Create certificate store /// public FlatDirectoryCertificateStore() { _innerStore = new DirectoryCertificateStore(noSubDirs: true); } /// public string StoreType => StoreTypeName; /// public string StorePath => _innerStore.StorePath; /// public bool SupportsLoadPrivateKey => _innerStore.SupportsLoadPrivateKey; /// public bool SupportsCRLs => _innerStore.SupportsCRLs; public bool NoPrivateKeys => _innerStore.NoPrivateKeys; /// public void Dispose() => _innerStore.Dispose(); /// public void Open(string location, bool noPrivateKeys = true) { ArgumentNullException.ThrowIfNullOrEmpty(location); if (!location.StartsWith(StoreTypePrefix, StringComparison.Ordinal)) { throw new ArgumentException( $"Expected argument {nameof(location)} starting with {StoreTypePrefix}", nameof(location)); } _innerStore.Open(location.Substring(StoreTypePrefix.Length), noPrivateKeys); } /// public void Close() => _innerStore.Close(); /// public Task AddAsync(X509Certificate2 certificate, string password = null, CancellationToken ct = default) => _innerStore.AddAsync(certificate, password, ct); /// public Task AddRejectedAsync(X509Certificate2Collection certificates, int maxCertificates, CancellationToken ct = default) => _innerStore.AddRejectedAsync(certificates, maxCertificates, ct); /// public Task DeleteAsync(string thumbprint, CancellationToken ct = default) => _innerStore.DeleteAsync(thumbprint, ct); /// public async Task EnumerateAsync(CancellationToken ct = default) { var certificatesCollection = await _innerStore.EnumerateAsync(ct).ConfigureAwait(false); if (!_innerStore.Directory.Exists) { return certificatesCollection; } foreach (var file in _innerStore.Directory.GetFiles('*' + CrtExtension)) { try { var certificates = new X509Certificate2Collection(); certificates.ImportFromPemFile(file.FullName); certificatesCollection.AddRange(certificates); foreach (var certificate in certificates) { Utils.LogInfo("Enumerate certificates - certificate added {thumbprint}", certificate.Thumbprint); } } catch (Exception e) { Utils.LogError(e, "Could not load certificate from file: {fileName}", file.FullName); } } return certificatesCollection; } /// public Task AddCRLAsync(X509CRL crl, CancellationToken ct = default) => _innerStore.AddCRLAsync(crl, ct); /// public Task DeleteCRLAsync(X509CRL crl, CancellationToken ct = default) => _innerStore.DeleteCRLAsync(crl, ct); /// public Task EnumerateCRLsAsync(CancellationToken ct = default) => _innerStore.EnumerateCRLsAsync(ct); /// public Task EnumerateCRLsAsync(X509Certificate2 issuer, bool validateUpdateTime = true, CancellationToken ct = default) => _innerStore.EnumerateCRLsAsync(issuer, validateUpdateTime, ct); /// public async Task FindByThumbprintAsync( string thumbprint, CancellationToken ct = default) { var certificatesCollection = await _innerStore.FindByThumbprintAsync(thumbprint, ct).ConfigureAwait(false); if (!_innerStore.Directory.Exists) { return certificatesCollection; } foreach (var file in _innerStore.Directory.GetFiles('*' + CrtExtension)) { try { var certificates = new X509Certificate2Collection(); certificates.ImportFromPemFile(file.FullName); foreach (var certificate in certificates) { if (string.Equals(certificate.Thumbprint, thumbprint, StringComparison.OrdinalIgnoreCase)) { Utils.LogInfo("Find by thumbprint: {thumbprint} - found", thumbprint); certificatesCollection.Add(certificate); } } } catch (Exception e) { Utils.LogError(e, "Could not load certificate from file: {fileName}", file.FullName); } } return certificatesCollection; } /// public Task IsRevokedAsync(X509Certificate2 issuer, X509Certificate2 certificate, CancellationToken ct = default) => _innerStore.IsRevokedAsync(issuer, certificate, ct); /// public Task LoadPrivateKeyAsync(string thumbprint, string subjectName, string password, CancellationToken ct = default) => LoadPrivateKeyAsync(thumbprint, subjectName, applicationUri: null, certificateType: null, password, ct); /// public async Task LoadPrivateKeyAsync(string thumbprint, string subjectName, string applicationUri, NodeId certificateType, string password, CancellationToken ct = default) { if (!_innerStore.Directory.Exists) { return await _innerStore.LoadPrivateKeyAsync(thumbprint, subjectName, applicationUri, certificateType, password, ct).ConfigureAwait(false); } foreach (var file in _innerStore.Directory.GetFiles('*' + CrtExtension)) { try { var keyFile = new FileInfo(file.FullName.Replace(CrtExtension, KeyExtension, StringComparison.OrdinalIgnoreCase)); if (keyFile.Exists) { using var certificate = X509CertificateLoader.LoadCertificateFromFile( file.FullName); if (!MatchCertificate(certificate, thumbprint, subjectName, applicationUri, certificateType)) { continue; } var privateKeyCertificate = X509Certificate2.CreateFromPemFile( file.FullName, keyFile.FullName); Utils.LogInfo("Loading private key succeeded for {thumbprint} - {subjectName}", thumbprint, subjectName); return privateKeyCertificate; } } catch (Exception e) { Utils.LogError(e, "Could not load private key for certificate file: {fileName}", file.FullName); } } return await _innerStore.LoadPrivateKeyAsync(thumbprint, subjectName, applicationUri, certificateType, password, ct).ConfigureAwait(false); } private static bool MatchCertificate(X509Certificate2 certificate, string thumbprint, string subjectName, string applicationUri, NodeId certificateType) { if (certificateType == null || certificateType == ObjectTypeIds.RsaSha256ApplicationCertificateType || certificateType == ObjectTypeIds.RsaMinApplicationCertificateType || certificateType == ObjectTypeIds.ApplicationCertificateType) { if (!string.IsNullOrEmpty(thumbprint) && !string.Equals(certificate.Thumbprint, thumbprint, StringComparison.OrdinalIgnoreCase)) { return false; } if (!string.IsNullOrEmpty(subjectName) && !X509Utils.CompareDistinguishedName(subjectName, certificate.Subject) && ( subjectName.Contains('=', StringComparison.OrdinalIgnoreCase) || !X509Utils.ParseDistinguishedName(certificate.Subject) .Any(s => s.Equals("CN=" + subjectName, StringComparison.Ordinal)))) { return false; } // skip if not RSA certificate return X509Utils.GetRSAPublicKeySize(certificate) >= 0; } return false; } } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/cli/Program.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Cli { using Azure.IIoT.OpcUa.Publisher.Stack.Services; using Furly.Extensions.Logging; using k8s; using Microsoft.Extensions.Logging; using Opc.Ua; using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Runtime.Loader; using System.Threading; using System.Threading.Tasks; /// /// Test client for opc ua services /// public static class Program { /// /// Test client entry point /// /// /// public static void Main(string[] args) { #if DEBUG if (args.Any(a => a.Contains("wfd", StringComparison.InvariantCultureIgnoreCase) || a.Contains("waitfordebugger", StringComparison.InvariantCultureIgnoreCase)) || KubernetesClientConfiguration.IsInCluster()) { Console.WriteLine("Waiting for debugger being attached..."); while (!Debugger.IsAttached) { Thread.Sleep(1000); } Console.WriteLine("Debugger attached."); Debugger.Break(); } #endif AppDomain.CurrentDomain.UnhandledException += (s, e) => Console.WriteLine("unhandled: " + e.ExceptionObject); var host = Utils.GetHostName(); var runsInKubenetes = KubernetesClientConfiguration.IsInCluster(); var ports = new List(); var server = "sample"; try { for (var i = 0; i < args.Length; i++) { switch (args[i]) { case "--server": case "-s": i++; if (i < args.Length) { server = args[i]; break; } throw new ArgumentException( "Missing arguments for server option"); case "--hosts": case "-H": i++; if (i < args.Length) { host = args[i]; break; } throw new ArgumentException( "Missing arguments for hosts option"); case "-p": case "--port": i++; if (i < args.Length) { ports.Add(ushort.Parse(args[i], CultureInfo.InvariantCulture)); break; } throw new ArgumentException( "Missing arguments for port option"); case "-?": case "-h": case "--help": throw new ArgumentException("Help"); default: throw new ArgumentException($"Unsupported option '{args[i]}'"); } } if (ports.Count == 0) { var envPort = Environment.GetEnvironmentVariable("SERVER_PORT"); if (!string.IsNullOrEmpty(envPort) && int.TryParse(envPort, out var port)) { ports.Add(port); } else { throw new ArgumentException("Missing port to run sample server."); } } } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine( @" Test server host usage: [options] operation [args] Options: --hosts / -H Full host name to use with comma seperated alternative hosts. --port / -p Port to listen on. --help / -? / -h Prints out this help. Operations (Mutually exclusive): --server / -s Run server with the given name (e.g. sample, testdata, etc.) " ); return; } if (ports.Count == 0) { ports.Add(runsInKubenetes ? 50000 : 51210); } try { var hosts = host.Split(',', StringSplitOptions.TrimEntries); var alternativeHosts = new List(); if (hosts.Length > 1) { alternativeHosts.AddRange(hosts[1..]); } Debug.Assert(hosts.Length > 0); Console.WriteLine("Running ..."); RunServerAsync(server, hosts[0], ports, alternativeHosts, runsInKubenetes).Wait(); } catch (Exception e) { Console.WriteLine(e); return; } if (!runsInKubenetes) { Console.WriteLine("Press key to exit..."); Console.ReadKey(); } } /// /// Run server until exit /// /// /// /// /// /// private static async Task RunServerAsync(string serverType, string host, IEnumerable ports, List alternativeHosts, bool runsInKubernetes) { var logger = Log.Console(); var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); AssemblyLoadContext.Default.Unloading += _ => tcs.TrySetResult(true); if (runsInKubernetes) { // Register FlatDirectoryCertificateStoreType as known certificate store type. var certStoreTypeName = CertificateStoreType.GetCertificateStoreTypeByName( FlatCertificateStore.StoreTypeName); if (certStoreTypeName is null) { CertificateStoreType.RegisterCertificateStoreType( FlatCertificateStore.StoreTypeName, new FlatCertificateStore()); } Console.WriteLine("Running in Kubernetes, using flat certificate store."); } using var server = new ServerConsoleHost( TestServerFactory.Create(serverType, Log.Console()), logger) { HostName = host, AlternativeHosts = alternativeHosts, UriPath = runsInKubernetes ? string.Empty : null, CertStoreType = runsInKubernetes ? FlatCertificateStore.StoreTypeName : null, PkiRootPath = runsInKubernetes ? FlatCertificateStore.StoreTypePrefix + "pki" : null, AutoAccept = true }; await server.StartAsync(ports).ConfigureAwait(false); #if DEBUG if (!Console.IsInputRedirected && !runsInKubernetes) { Console.WriteLine("Press any key to exit..."); Console.TreatControlCAsInput = true; await Task.WhenAny(tcs.Task, Task.Run(Console.ReadKey)).ConfigureAwait(false); return; } #endif await tcs.Task.ConfigureAwait(false); logger.LogInformation("Exiting."); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/cli/Properties/AssemblyInfo.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using System; [assembly: CLSCompliant(false)] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/cli/TestServerFactory.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Cli { using Azure.IIoT.OpcUa.Publisher.Stack; using Furly.Extensions.Utils; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Server; using Opc.Ua.Test; using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; using System.Xml; /// /// Reference server factory /// public class TestServerFactory : IServerFactory { /// /// Whether to log status /// public bool LogStatus { get; set; } /// /// Server factory /// /// /// public TestServerFactory(ILogger logger, IEnumerable nodes) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _nodes = nodes ?? throw new ArgumentNullException(nameof(nodes)); } /// /// Full set of servers /// /// public TestServerFactory(ILogger logger) : this(logger, new List { new TestData.TestDataServer(), new MemoryBuffer.MemoryBufferServer(), new Boiler.BoilerServer(), new Vehicles.VehiclesServer(), new Reference.ReferenceServer(), new HistoricalEvents.HistoricalEventsServer(new TimeService()), new HistoricalAccess.HistoricalAccessServer(new TimeService()), new Views.ViewsServer(), new DataAccess.DataAccessServer(), new Alarms.AlarmConditionServer(new TimeService()), new PerfTest.PerfTestServer(), new SimpleEvents.SimpleEventsServer(), new Plc.PlcServer(new TimeService(), logger, 1), new FileSystem.FileSystemServer(), new Asset.AssetServer(logger), new Isa95Jobs.Isa95JobControlServer() }) { } internal static IServerFactory Create(string serverType, ILogger logger) { switch (serverType.ToLowerInvariant()) { case "reference": return new TestServerFactory(logger, [ new Reference.ReferenceServer(), ]); case "plc": return new TestServerFactory(logger, [ new Plc.PlcServer(new TimeService(), logger, 1), ]); case "asset": return new TestServerFactory(logger, [ new Asset.AssetServer(logger), ]); case "testdata": return new TestServerFactory(logger, [ new TestData.TestDataServer(), new MemoryBuffer.MemoryBufferServer(), new Boiler.BoilerServer(), new Vehicles.VehiclesServer(), new DataAccess.DataAccessServer(), ]); default: return new TestServerFactory(logger, [ new TestData.TestDataServer(), new MemoryBuffer.MemoryBufferServer(), new Boiler.BoilerServer(), new Vehicles.VehiclesServer(), new Reference.ReferenceServer(), new HistoricalEvents.HistoricalEventsServer(new TimeService()), new HistoricalAccess.HistoricalAccessServer(new TimeService()), new Views.ViewsServer(), new DataAccess.DataAccessServer(), new Alarms.AlarmConditionServer(new TimeService()), new PerfTest.PerfTestServer(), new SimpleEvents.SimpleEventsServer(), new Plc.PlcServer(new TimeService(), logger, 1), new FileSystem.FileSystemServer(), new Asset.AssetServer(logger), new Isa95Jobs.Isa95JobControlServer() ]); } } /// public ApplicationConfiguration CreateServer(IEnumerable ports, string pkiRootPath, out ServerBase server, string listenHostName, IEnumerable alternativeAddresses, string path, string certStoreType, Action configure) { server = new Server(LogStatus, _nodes, _logger); return Server.CreateServerConfiguration( ports, listenHostName, alternativeAddresses, path, pkiRootPath, certStoreType, configure: configure); } /// private sealed class Server : ReverseConnectServer { /// /// Create server /// /// /// /// internal Server(bool logStatus, IEnumerable nodes, ILogger logger) { _logger = logger; _logStatus = logStatus; _nodes = nodes; } /// /// Create configuration /// /// /// /// /// /// /// /// /// /// public static ApplicationConfiguration CreateServerConfiguration( IEnumerable ports, string hostName, IEnumerable alternativeAddresses, string path, string pkiRootPath, string certStoreType, bool enableDiagnostics = false, Action configure = null) { var extensions = new List { new MemoryBuffer.MemoryBufferConfiguration { Buffers = [ new MemoryBuffer.MemoryBufferInstance { Name = "UInt32", TagCount = 10000, DataType = "UInt32" }, new MemoryBuffer.MemoryBufferInstance { Name = "Double", TagCount = 100, DataType = "Double" } ] } /// ... }; certStoreType ??= CertificateStoreType.Directory; if (string.IsNullOrEmpty(pkiRootPath)) { pkiRootPath = "pki"; } path ??= "/UA/SampleServer"; if (path.Length > 0 && !path.StartsWith('/')) { path = "/" + path; } var configuration = new ApplicationConfiguration { ApplicationName = "UA Core Sample Server", ApplicationType = ApplicationType.Server, ApplicationUri = $"urn:{hostName ?? Utils.GetHostName()}:OPCFoundation:CoreSampleServer", Extensions = new XmlElementCollection( extensions.Select(XmlElementEx.SerializeObject)), ProductUri = "http://opcfoundation.org/UA/SampleServer", SecurityConfiguration = new SecurityConfiguration { ApplicationCertificate = new CertificateIdentifier { StoreType = certStoreType, StorePath = $"{pkiRootPath}/own", SubjectName = "UA Core Sample Server" }, TrustedPeerCertificates = new CertificateTrustList { StoreType = certStoreType, StorePath = $"{pkiRootPath}/trusted" }, TrustedIssuerCertificates = new CertificateTrustList { StoreType = certStoreType, StorePath = $"{pkiRootPath}/issuer" }, RejectedCertificateStore = new CertificateTrustList { StoreType = certStoreType, StorePath = $"{pkiRootPath}/rejected" }, MinimumCertificateKeySize = 1024, RejectSHA1SignedCertificates = false, AutoAcceptUntrustedCertificates = true, AddAppCertToTrustedStore = true, RejectUnknownRevocationStatus = true }, TransportConfigurations = [], TransportQuotas = new TransportQuotas(), ServerConfiguration = new ServerConfiguration { // Sample server specific ServerProfileArray = [ "Standard UA Server Profile", "Data Access Server Facet", "Method Server Facet" ], ServerCapabilities = [ "DA" ], SupportedPrivateKeyFormats = [ "PFX", "PEM" ], NodeManagerSaveFile = "nodes.xml", DiagnosticsEnabled = enableDiagnostics, ShutdownDelay = 0, // Runtime configuration BaseAddresses = [.. ports .Distinct() .Select(p => $"opc.tcp://{hostName ?? "localhost"}:{p}{path}")], AlternateBaseAddresses = alternativeAddresses == null ? null : [.. alternativeAddresses.Distinct().SelectMany(e => ports .Distinct() .Select(p => $"opc.tcp://{e}:{p}{path}"))], SecurityPolicies = [ new ServerSecurityPolicy { SecurityMode = MessageSecurityMode.Sign, SecurityPolicyUri = SecurityPolicies.Basic256Sha256 }, new ServerSecurityPolicy { SecurityMode = MessageSecurityMode.SignAndEncrypt, SecurityPolicyUri =SecurityPolicies.Basic256Sha256 }, new ServerSecurityPolicy { SecurityMode = MessageSecurityMode.None, SecurityPolicyUri = SecurityPolicies.None } ], UserTokenPolicies = [ new UserTokenPolicy { TokenType = UserTokenType.Anonymous, SecurityPolicyUri = SecurityPolicies.None }, new UserTokenPolicy { TokenType = UserTokenType.UserName }, new UserTokenPolicy { TokenType = UserTokenType.Certificate } ], MinRequestThreadCount = 200, MaxRequestThreadCount = 2000, MaxQueuedRequestCount = 2000000, MaxSessionCount = 10000, MinSessionTimeout = 10000, MaxSessionTimeout = 3600000, MaxBrowseContinuationPoints = 1000, MaxQueryContinuationPoints = 1000, MaxHistoryContinuationPoints = 1000, MaxRequestAge = 600000, MinPublishingInterval = 100, MaxPublishingInterval = 3600000, PublishingResolution = 50, MaxSubscriptionLifetime = 3600000, MaxMessageQueueSize = 100, MaxNotificationQueueSize = 100, MaxNotificationsPerPublish = 1000, MinMetadataSamplingInterval = 1000, MaxPublishRequestCount = 20, MaxSubscriptionCount = 100, MaxEventQueueSize = 10000, MinSubscriptionLifetime = 10000, // Do not register with LDS MaxRegistrationInterval = 0, // TODO RegistrationEndpoint = null }, TraceConfiguration = new TraceConfiguration { TraceMasks = 1 } }; configure?.Invoke(configuration.ServerConfiguration); return configuration; } /// protected override ServerProperties LoadServerProperties() { return new ServerProperties { ManufacturerName = "OPC Foundation", ProductName = "OPC UA Sample Servers", ProductUri = "http://opcfoundation.org/UA/Samples/v1.0", SoftwareVersion = Utils.GetAssemblySoftwareVersion(), BuildNumber = Utils.GetAssemblyBuildNumber(), BuildDate = Utils.GetAssemblyTimestamp() }; } /// protected override MasterNodeManager CreateMasterNodeManager( IServerInternal server, ApplicationConfiguration configuration) { _logger.CreatingNodeManagers(); var nodeManagers = _nodes .Select(n => n.Create(server, configuration)); return new MasterNodeManager(server, configuration, null, nodeManagers.ToArray()); } /// protected override void OnServerStopping() { _logger.ServerStopping(); base.OnServerStopping(); _cts.Cancel(); _statusLogger?.Wait(); } /// protected override void OnServerStarted(IServerInternal server) { // start the status thread _cts = new CancellationTokenSource(); if (_logStatus) { _statusLogger = Task.Run(() => LogStatusAsync(_cts.Token)); // print notification on session events CurrentInstance.SessionManager.SessionActivated += OnEvent; CurrentInstance.SessionManager.SessionClosing += OnEvent; CurrentInstance.SessionManager.SessionCreated += OnEvent; } base.OnServerStarted(server); // request notifications when the user identity is changed. all valid users are accepted by default. server.SessionManager.ImpersonateUser += SessionManager_ImpersonateUser; } /// protected override void OnServerStarting(ApplicationConfiguration configuration) { _logger.ServerStarting(); CreateUserIdentityValidators(configuration); base.OnServerStarting(configuration); } /// protected override void OnNodeManagerStarted(IServerInternal server) { _logger.NodeManagersStarted(); base.OnNodeManagerStarted(server); } /// protected override void Dispose(bool disposing) { base.Dispose(disposing); _cts?.Dispose(); } /// /// Handle session event by logging status /// /// /// private void OnEvent(ISession session, SessionEventReason reason) { _lastEventTime = DateTimeOffset.UtcNow; LogSessionStatus(session, reason.ToString()); } /// /// Continously log session status if not logged during events /// /// /// private async Task LogStatusAsync(CancellationToken ct) { while (!ct.IsCancellationRequested) { if (DateTimeOffset.UtcNow - _lastEventTime > TimeSpan.FromMilliseconds(6000)) { foreach (var session in CurrentInstance.SessionManager.GetSessions()) { LogSessionStatus(session, "-Status-", true); } _lastEventTime = DateTimeOffset.UtcNow; } await Try.Async(() => Task.Delay(1000, ct)).ConfigureAwait(false); } } /// /// Helper to log session status /// /// /// /// private void LogSessionStatus(ISession session, string reason, bool lastContact = false) { lock (session.DiagnosticsLock) { var item = $"{reason,9}:{session.SessionDiagnostics.SessionName,20}:"; if (lastContact) { item += $"Last Event:{session.SessionDiagnostics.ClientLastContactTime.ToLocalTime():HH:mm:ss}"; } else { if (session.Identity != null) { item += $":{session.Identity.DisplayName,20}"; } item += $":{session.Id}"; } _logger.ItemStatus(item); } } /// /// Creates the objects used to validate the user identity tokens supported by the server. /// /// private void CreateUserIdentityValidators(ApplicationConfiguration configuration) { for (var i = 0; i < configuration.ServerConfiguration.UserTokenPolicies.Count; i++) { var policy = configuration.ServerConfiguration.UserTokenPolicies[i]; // ignore policies without an explicit id. if (string.IsNullOrEmpty(policy.PolicyId)) { continue; } // create a validator for an issued token policy. if (policy.TokenType == UserTokenType.IssuedToken) { // the name of the element in the configuration file. var qname = new XmlQualifiedName(policy.PolicyId, Namespaces.OpcUa); // find the id for the issuer certificate. var id = configuration.ParseExtension(qname); if (id == null) { Utils.Trace( Utils.TraceMasks.Error, "Could not load CertificateIdentifier for UserTokenPolicy {0}", policy.PolicyId); continue; } } // create a validator for a certificate token policy. if (policy.TokenType == UserTokenType.Certificate) { // the name of the element in the configuration file. var qname = new XmlQualifiedName(policy.PolicyId, Namespaces.OpcUa); // find the location of the trusted issuers. var trustedIssuers = configuration.ParseExtension(qname); if (trustedIssuers == null) { Utils.Trace( Utils.TraceMasks.Error, "Could not load CertificateTrustList for UserTokenPolicy {0}", policy.PolicyId); continue; } // trusts any certificate in the trusted people store. _certificateValidator = CertificateValidator.GetChannelValidator(); } } } /// /// Called when a client tries to change its user identity. /// /// /// /// is null. /// private void SessionManager_ImpersonateUser(ISession session, ImpersonateEventArgs args) { ArgumentNullException.ThrowIfNull(session); if (args.NewIdentity is AnonymousIdentityToken guest) { args.Identity = new UserIdentity(guest); Utils.Trace("Guest access accepted: {0}", args.Identity.DisplayName); return; } // check for a user name token. if (args.NewIdentity is UserNameIdentityToken userNameToken) { var admin = VerifyPassword(userNameToken.UserName, userNameToken.DecryptedPassword); args.Identity = new UserIdentity(userNameToken); if (admin) { args.Identity = new SystemConfigurationIdentity(args.Identity); } Utils.Trace("UserName Token accepted: {0}", args.Identity.DisplayName); return; } // check for x509 user token. if (args.NewIdentity is X509IdentityToken x509Token) { var admin = VerifyCertificate(x509Token.Certificate); args.Identity = new UserIdentity(x509Token); if (admin) { args.Identity = new SystemConfigurationIdentity(args.Identity); } Utils.Trace("X509 Token accepted: {0}", args.Identity.DisplayName); return; } // check for x509 user token. if (args.NewIdentity is IssuedIdentityToken wssToken) { var admin = VerifyToken(wssToken); args.Identity = new UserIdentity(wssToken); if (admin) { args.Identity = new SystemConfigurationIdentity(args.Identity); } Utils.Trace("Issued Token accepted: {0}", args.Identity.DisplayName); return; } // construct translation object with default text. var info = new TranslationInfo("InvalidToken", "en-US", "Specified token is not valid."); // create an exception with a vendor defined sub-code. throw new ServiceResultException(new ServiceResult( StatusCodes.BadIdentityTokenRejected, "Bad token", kServerNamespaceUri, new LocalizedText(info))); } /// /// Validates the token /// /// /// private static bool VerifyToken(IssuedIdentityToken wssToken) { if ((wssToken.TokenData?.Length ?? 0) == 0) { var info = new TranslationInfo("InvalidToken", "en-US", "Specified token is empty."); // create an exception with a vendor defined sub-code. throw new ServiceResultException(new ServiceResult( StatusCodes.BadIdentityTokenRejected, "Bad token", kServerNamespaceUri, new LocalizedText(info))); } return false; } /// /// Validates the password for a username token. /// /// /// /// private static bool VerifyPassword(string userName, string password) { if (string.IsNullOrEmpty(password)) { // construct translation object with default text. var info = new TranslationInfo( "InvalidPassword", "en-US", "Specified password is not valid for user '{0}'.", userName); // create an exception with a vendor defined sub-code. throw new ServiceResultException(new ServiceResult( StatusCodes.BadIdentityTokenRejected, "InvalidPassword", kServerNamespaceUri, new LocalizedText(info))); } if (userName.Equals("test", StringComparison.OrdinalIgnoreCase) && password == "test") { // Testing purposes only return true; } return false; } /// /// Verifies that a certificate user token is trusted. /// /// /// private bool VerifyCertificate(X509Certificate2 certificate) { try { if (_certificateValidator != null) { _certificateValidator.Validate(certificate); } else { CertificateValidator.Validate(certificate); } // determine if self-signed. var isSelfSigned = X509Utils.CompareDistinguishedName( certificate.Subject, certificate.Issuer); // do not allow self signed application certs as user token if (isSelfSigned && X509Utils.HasApplicationURN(certificate)) { throw new ServiceResultException(StatusCodes.BadCertificateUseNotAllowed); } return false; } catch (Exception e) { TranslationInfo info; StatusCode result = StatusCodes.BadIdentityTokenRejected; if (e is ServiceResultException se && se.StatusCode == StatusCodes.BadCertificateUseNotAllowed) { info = new TranslationInfo( "InvalidCertificate", "en-US", "'{0}' is an invalid user certificate.", certificate.Subject); result = StatusCodes.BadIdentityTokenInvalid; } else { // construct translation object with default text. info = new TranslationInfo( "UntrustedCertificate", "en-US", "'{0}' is not a trusted user certificate.", certificate.Subject); } // create an exception with a vendor defined sub-code. throw new ServiceResultException(new ServiceResult( result, info.Key, kServerNamespaceUri, new LocalizedText(info))); } } private readonly ILogger _logger; private readonly bool _logStatus; private readonly IEnumerable _nodes; private Task _statusLogger; private DateTimeOffset _lastEventTime; private CancellationTokenSource _cts; private ICertificateValidator _certificateValidator; private const string kServerNamespaceUri = "http://opcfoundation.org/UA/Sample/"; } private readonly ILogger _logger; private readonly IEnumerable _nodes; } /// /// Source-generated logging definitions for TestServer /// internal static partial class TestServerLogging { private const int EventClass = 0; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Information, Message = "Creating the Node Managers.")] public static partial void CreatingNodeManagers(this ILogger logger); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Debug, Message = "The server is stopping.")] public static partial void ServerStopping(this ILogger logger); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Debug, Message = "The server is starting.")] public static partial void ServerStarting(this ILogger logger); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Information, Message = "The NodeManagers have started.")] public static partial void NodeManagersStarted(this ILogger logger); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Information, Message = "{Log}")] public static partial void ItemStatus(this ILogger logger, string log); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Alarms/AlarmConditionNodeManager.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Alarms { using Opc.Ua; using Opc.Ua.Server; using Opc.Ua.Test; using System; using System.Collections.Generic; using System.Threading; /// /// A node manager for a simple server that exposes several Areas, Sources and Conditions. /// /// /// This node manager presumes that the information model consists of a hierachy of predefined /// Areas with a number of Sources contained within them. Each individual Source is /// identified by a fully qualified path. The underlying system knows how to access the source /// configuration when it is provided the fully qualified path. /// public class AlarmConditionServerNodeManager : CustomNodeManager2 { /// /// Initializes the node manager. /// /// /// /// public AlarmConditionServerNodeManager(IServerInternal server, ApplicationConfiguration configuration, TimeService timeservice) : base(server, configuration, Namespaces.AlarmCondition) { SystemContext.SystemHandle = _system = new UnderlyingSystem(timeservice); SystemContext.NodeIdFactory = this; // get the configuration for the node manager. _configuration = configuration.ParseExtension(); // use suitable defaults if no configuration exists. _configuration ??= new AlarmConditionServerConfiguration { Areas = [ new AreaConfiguration { Name = "Green", SubAreas = [ new AreaConfiguration { Name = "East", SubAreas = [ new AreaConfiguration { Name = "Red", SourcePaths = [ "Colours/EastTank", "Colours/NorthMotor" ] }, new AreaConfiguration { Name = "Blue", SourcePaths = [ "Metals/WestTank", "Metals/SouthMotor" ] } ] } ] }, new AreaConfiguration { Name = "Yellow", SubAreas = [ new AreaConfiguration { Name = "West", SubAreas = [ new AreaConfiguration { Name = "Red", SourcePaths = [ "Metals/SouthMotor", "Colours/NorthMotor" ] }, new AreaConfiguration { Name = "Blue", SourcePaths = [ "Colours/EastTank", "Metals/WestTank" ] } ] } ] } ] }; // create the table to store the available areas. _areas = []; // create the table to store the available sources. _sources = []; _timeservice = timeservice; } /// /// An overrideable version of the Dispose. /// /// protected override void Dispose(bool disposing) { if (disposing) { if (_system != null) { _system.Dispose(); _system = null; } if (_simulationTimer != null) { _simulationTimer.Dispose(); _simulationTimer = null; } } base.Dispose(disposing); } /// /// Creates the NodeId for the specified node. /// /// The context. /// The node. /// The new NodeId. /// /// This method is called by the NodeState.Create() method which initializes a Node from /// the type model. During initialization a number of child nodes are created and need to /// have NodeIds assigned to them. This implementation constructs NodeIds by constructing /// strings. Other implementations could assign unique integers or Guids and save the new /// Node in a dictionary for later lookup. /// public override NodeId New(ISystemContext context, NodeState node) { return ModelUtils.ConstructIdForComponent(node, NamespaceIndex); } /// /// Does any initialization required before the address space can be used. /// /// /// /// The externalReferences is an out parameter that allows the node manager to link to nodes /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and /// should have a reference to the root folder node(s) exposed by this node manager. /// public override void CreateAddressSpace(IDictionary> externalReferences) { lock (Lock) { if (_configuration.Areas != null) { // Top level areas need a reference from the Server object. // These references are added to a list that is returned to the caller. // The caller will update the Objects folder node. if (!externalReferences.TryGetValue(ObjectIds.Server, out var references)) { externalReferences[ObjectIds.Server] = references = []; } for (var ii = 0; ii < _configuration.Areas.Count; ii++) { // recursively process each area. var area = CreateAndIndexAreas(null, _configuration.Areas[ii]); AddRootNotifier(area); // add an organizes reference from the ObjectsFolder to the area. references.Add(new NodeStateReference(ReferenceTypeIds.HasNotifier, false, area.NodeId)); } } // start the simulation. _system.StartSimulation(); _simulationTimer = new Timer(OnRaiseSystemEvents, null, 1000, 1000); } } private void OnRaiseSystemEvents(object state) { try { var e = new SystemEventState(null); e.Initialize( SystemContext, null, EventSeverity.Medium, new LocalizedText("Raising Events")); e.SetChildValue(SystemContext, BrowseNames.SourceNode, ObjectIds.Server, false); e.SetChildValue(SystemContext, BrowseNames.SourceName, "Internal", false); Server.ReportEvent(e); var ae = new AuditEventState(null); ae.Initialize( SystemContext, null, EventSeverity.Medium, new LocalizedText("Events Raised"), true, _timeservice.UtcNow); ae.SetChildValue(SystemContext, BrowseNames.SourceNode, ObjectIds.Server, false); ae.SetChildValue(SystemContext, BrowseNames.SourceName, "Internal", false); Server.ReportEvent(ae); } catch (Exception e) { Utils.Trace(e, "Unexpected error in OnRaiseSystemEvents"); } } /// /// Creates and indexes an area defined for the server. /// /// /// private AreaState CreateAndIndexAreas(AreaState parent, AreaConfiguration configuration) { // create a unique path to the area. var areaPath = Utils.Format("{0}/{1}", (parent != null) ? parent.SymbolicName : string.Empty, configuration.Name); var areaId = ModelUtils.ConstructIdForArea(areaPath, NamespaceIndex); // create the object that will be used to access the area and any variables contained within it. var area = new AreaState(SystemContext, parent, areaId, configuration); _areas[areaPath] = area; parent?.AddChild(area); // create an index any sub-areas defined for the area. if (configuration.SubAreas != null) { for (var ii = 0; ii < configuration.SubAreas.Count; ii++) { CreateAndIndexAreas(area, configuration.SubAreas[ii]); } } // add references to sources. if (configuration.SourcePaths != null) { for (var ii = 0; ii < configuration.SourcePaths.Count; ii++) { var sourcePath = configuration.SourcePaths[ii]; // check if the source already exists because it is referenced by another area. if (!_sources.TryGetValue(sourcePath, out var source)) { var sourceId = ModelUtils.ConstructIdForSource(sourcePath, NamespaceIndex); _sources[sourcePath] = source = new SourceState(this, sourceId, sourcePath, _timeservice); } // HasEventSource and HasNotifier control the propagation of event notifications so // they are not like other references. These calls set up a link between the source // and area that will cause events produced by the source to be automatically // propagated to the area. source.AddNotifier(SystemContext, ReferenceTypeIds.HasEventSource, true, area); area.AddNotifier(SystemContext, ReferenceTypeIds.HasEventSource, false, source); } } return area; } /// /// Frees any resources allocated for the address space. /// public override void DeleteAddressSpace() { lock (Lock) { _system.StopSimulation(); _areas.Clear(); _sources.Clear(); } } /// /// Returns a unique handle for the node. /// /// /// /// protected override NodeHandle GetManagerHandle(ServerSystemContext context, NodeId nodeId, IDictionary cache) { lock (Lock) { // quickly exclude nodes that are not in the namespace. if (!IsNodeIdInNamespace(nodeId)) { return null; } // check for check for nodes that are being currently monitored. if (MonitoredNodes.TryGetValue(nodeId, out var monitoredNode)) { return new NodeHandle { NodeId = nodeId, Validated = true, Node = monitoredNode.Node }; } // parse the identifier. var parsedNodeId = ParsedNodeId.Parse(nodeId); if (parsedNodeId != null) { return new NodeHandle { NodeId = nodeId, Validated = false, Node = null, ParsedNodeId = parsedNodeId }; } return null; } } /// /// Verifies that the specified node exists. /// /// /// /// protected override NodeState ValidateNode( ServerSystemContext context, NodeHandle handle, IDictionary cache) { // not valid if no root. if (handle == null) { return null; } // check if previously validated. if (handle.Validated) { return handle.Node; } NodeState target = null; // check if already in the cache. if (cache != null) { if (cache.TryGetValue(handle.NodeId, out target)) { // nulls mean a NodeId which was previously found to be invalid has been referenced again. if (target == null) { return null; } handle.Node = target; handle.Validated = true; return handle.Node; } target = null; } try { // check if the node id has been parsed. if (handle.ParsedNodeId is not ParsedNodeId parsedNodeId) { return null; } NodeState root = null; // validate area. if (parsedNodeId.RootType == ModelUtils.Area) { if (!_areas.TryGetValue(parsedNodeId.RootId, out var area)) { return null; } root = area; } // validate soucre. else if (parsedNodeId.RootType == ModelUtils.Source) { if (!_sources.TryGetValue(parsedNodeId.RootId, out var source)) { return null; } root = source; } // unknown root type. else { return null; } // all done if no components to validate. if (string.IsNullOrEmpty(parsedNodeId.ComponentPath)) { handle.Validated = true; handle.Node = target = root; return handle.Node; } // validate component. NodeState component = root.FindChildBySymbolicName(context, parsedNodeId.ComponentPath); // component does not exist. if (component == null) { return null; } // found a valid component. handle.Validated = true; handle.Node = target = component; return handle.Node; } finally { // store the node in the cache to optimize subsequent lookups. cache?.Add(handle.NodeId, target); } } private UnderlyingSystem _system; private readonly AlarmConditionServerConfiguration _configuration; private readonly Dictionary _areas; private readonly Dictionary _sources; private readonly TimeService _timeservice; private Timer _simulationTimer; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Alarms/AlarmConditionServer.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Alarms { using Opc.Ua; using Opc.Ua.Server; using Opc.Ua.Test; /// public class AlarmConditionServer : INodeManagerFactory { /// public StringCollection NamespacesUris { get { return [ Namespaces.AlarmCondition ]; } } /// public AlarmConditionServer(TimeService timeservice) { _timeservice = timeservice; } /// public INodeManager Create(IServerInternal server, ApplicationConfiguration configuration) { return new AlarmConditionServerNodeManager(server, configuration, _timeservice); } private readonly TimeService _timeservice; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Alarms/AlarmConditionServerConfiguration.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Alarms { using Opc.Ua; using System.Collections.Generic; using System.Runtime.Serialization; /// /// Stores the configuration the Alarm Condition server. /// [DataContract(Namespace = Namespaces.AlarmCondition)] public class AlarmConditionServerConfiguration { /// /// The default constructor. /// public AlarmConditionServerConfiguration() { Initialize(); } /// /// Initializes the object during deserialization. /// /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { Areas = []; } /// /// Gets or sets the list of top level Areas exposed by the server. /// [DataMember(Order = 1)] public AreaConfigurationCollection Areas { get; set; } } /// /// Stores the configuration for a Area within the Alarm Condition server. /// [DataContract(Namespace = Namespaces.AlarmCondition)] public class AreaConfiguration { /// /// The default constructor. /// public AreaConfiguration() { Initialize(); } /// /// Initializes the object during deserialization. /// /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { Name = null; SubAreas = null; SourcePaths = null; } /// /// The browse name for the instance. /// [DataMember(Order = 1)] public string Name { get; set; } /// /// Gets or set the list of sub-areas. /// [DataMember(Order = 2)] public AreaConfigurationCollection SubAreas { get; set; } /// /// Gets or set the list of sources. /// [DataMember(Order = 3)] public StringCollection SourcePaths { get; set; } } /// /// A collection of AreaConfiguration objects. /// [CollectionDataContract(Name = "ListOfAreaConfiguration", Namespace = Namespaces.AlarmCondition, ItemName = "AreaConfiguration")] public class AreaConfigurationCollection : List; } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Alarms/AreaState.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Alarms { using Opc.Ua; /// /// Maps an alarm area to a UA object node. /// public class AreaState : FolderState { /// /// Initializes the area. /// /// /// /// /// public AreaState( ISystemContext context, AreaState parent, NodeId nodeId, AreaConfiguration configuration) : base(parent) { Initialize(context); // initialize the area with the fixed metadata. SymbolicName = configuration.Name; NodeId = nodeId; BrowseName = new QualifiedName(Utils.Format("{0}", configuration.Name), nodeId.NamespaceIndex); DisplayName = BrowseName.Name; Description = null; ReferenceTypeId = ReferenceTypeIds.HasNotifier; TypeDefinitionId = ObjectTypeIds.FolderType; EventNotifier = EventNotifiers.SubscribeToEvents; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Alarms/ModelUtils.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Alarms { using Opc.Ua; using Opc.Ua.Server; using System.Text; /// /// Defines constants and methods used by all classes in the information model. /// public static class ModelUtils { /// /// The RootType for a Area node identfier. /// public const int Area = 0; /// /// The RootType for a Source node identfier. /// public const int Source = 1; /// /// Constructs a node identifier for a area. /// /// The area path. /// Index of the namespace that qualifies the identifier. /// The new node identifier. public static NodeId ConstructIdForArea(string areaPath, ushort namespaceIndex) { var parsedNodeId = new ParsedNodeId { RootId = areaPath, NamespaceIndex = namespaceIndex, RootType = 0 }; return parsedNodeId.Construct(); } /// /// Constructs a NodeId for a source. /// /// The source id. /// Index of the namespace. /// The new NodeId. public static NodeId ConstructIdForSource(string sourceId, ushort namespaceIndex) { var parsedNodeId = new ParsedNodeId { RootId = sourceId, NamespaceIndex = namespaceIndex, RootType = 1 }; return parsedNodeId.Construct(); } /// /// Constructs the node identifier for a component. /// /// The component. /// Index of the namespace. /// The node identifier for a component. public static NodeId ConstructIdForComponent(NodeState component, ushort namespaceIndex) { if (component == null) { return null; } // components must be instances with a parent. if (component is not BaseInstanceState instance || instance.Parent == null) { return component.NodeId; } // parent must have a string identifier. if (instance.Parent.NodeId.Identifier is not string parentId) { return null; } var buffer = new StringBuilder(); buffer.Append(parentId); // check if the parent is another component. var index = parentId.IndexOf('?'); if (index < 0) { buffer.Append('?'); } else { buffer.Append('/'); } buffer.Append(component.SymbolicName); // return the node identifier. return new NodeId(buffer.ToString(), namespaceIndex); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Alarms/Namespaces.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Alarms { /// /// Defines constants for namespaces used by the application. /// public static class Namespaces { /// /// The namespace for the nodes provided by the server. /// public const string AlarmCondition = "http://opcfoundation.org/AlarmCondition"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Alarms/SourceState.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Alarms { using Opc.Ua; using Opc.Ua.Server; using Opc.Ua.Test; using System; using System.Collections.Generic; /// /// Maps an alarm source to a UA object node. /// public class SourceState : BaseObjectState { /// /// Initializes the area. /// /// /// /// /// public SourceState( CustomNodeManager2 nodeManager, NodeId nodeId, string sourcePath, TimeService timeService) : base(null) { Initialize(nodeManager.SystemContext); // save the node manager that owns the source. _nodeManager = nodeManager; _timeService = timeService; // create the source with the underlying system. _source = ((UnderlyingSystem)nodeManager.SystemContext.SystemHandle).CreateSource(sourcePath, OnAlarmChanged); // initialize the area with the fixed metadata. SymbolicName = _source.Name; NodeId = nodeId; BrowseName = new QualifiedName(Utils.Format("{0}", _source.Name), nodeId.NamespaceIndex); DisplayName = BrowseName.Name; Description = null; ReferenceTypeId = null; TypeDefinitionId = ObjectTypeIds.BaseObjectType; EventNotifier = EventNotifiers.None; // create a dialog. _dialog = CreateDialog("OnlineState"); // create the table of conditions. _alarms = []; _events = []; _branches = []; // request an updated for all alarms. _source.Refresh(); } /// /// Returns the last event produced for any conditions belonging to the node or its chilren. /// /// The system context. /// The list of condition events to return. /// Whether to recursively report events for the children. public override void ConditionRefresh(ISystemContext context, List events, bool includeChildren) { // need to check if this source has already been processed during this refresh operation. for (var ii = 0; ii < events.Count; ii++) { if (events[ii] is InstanceStateSnapshot e && ReferenceEquals(e.Handle, this)) { return; } } // report the dialog. if (_dialog != null) { // do not refresh dialogs that are not active. if (_dialog.Retain.Value) { // create a snapshot. var e = new InstanceStateSnapshot(); e.Initialize(context, _dialog); // set the handle of the snapshot to check for duplicates. e.Handle = this; events.Add(e); } } // the alarm objects act as a cache for the last known state and are used to generate refresh events. foreach (var alarm in _alarms.Values) { // do not refresh alarms that are not in an interesting state. if (!alarm.Retain.Value) { continue; } // create a snapshot. var e = new InstanceStateSnapshot(); e.Initialize(context, alarm); // set the handle of the snapshot to check for duplicates. e.Handle = this; events.Add(e); } // report any active branches. foreach (var alarm in _branches.Values) { // create a snapshot. var e = new InstanceStateSnapshot(); e.Initialize(context, alarm); // set the handle of the snapshot to check for duplicates. e.Handle = this; events.Add(e); } } protected override void Dispose(bool disposing) { base.Dispose(disposing); _dialog?.Dispose(); } /// /// Called when the state of an alarm for the source has changed. /// /// private void OnAlarmChanged(UnderlyingSystemAlarm alarm) { lock (_nodeManager.Lock) { // ignore archived alarms for now. if (alarm.RecordNumber != 0) { var branchId = new NodeId(alarm.RecordNumber, NodeId.NamespaceIndex); // find the alarm branch. if (!_branches.TryGetValue(branchId, out var branch)) { _branches[branchId] = branch = CreateAlarm(alarm, branchId); } // map the system information to the UA defined alarm. UpdateAlarm(branch, alarm); ReportChanges(branch); // delete the branch. if ((alarm.State & UnderlyingSystemAlarmStates.Deleted) != 0) { _branches.Remove(branchId); } return; } // find the alarm node. if (!_alarms.TryGetValue(alarm.Name, out var node)) { _alarms[alarm.Name] = node = CreateAlarm(alarm, null); } // map the system information to the UA defined alarm. UpdateAlarm(node, alarm); ReportChanges(node); } } /// /// Creates a new dialog condition /// /// private DialogConditionState CreateDialog(string dialogName) { ISystemContext context = _nodeManager.SystemContext; var node = new DialogConditionState(this) { SymbolicName = dialogName }; // specify optional fields. node.EnabledState = new TwoStateVariableState(node); node.EnabledState.TransitionTime = new PropertyState(node.EnabledState); node.EnabledState.EffectiveDisplayName = new PropertyState(node.EnabledState); node.EnabledState.Create(context, null, BrowseNames.EnabledState, null, false); // specify reference type between the source and the alarm. node.ReferenceTypeId = ReferenceTypeIds.HasComponent; // This call initializes the condition from the type model (i.e. creates all of the objects // and variables requried to store its state). The information about the type model was // incorporated into the class when the class was created. node.Create( context, null, new QualifiedName(dialogName, BrowseName.NamespaceIndex), null, true); AddChild(node); // initialize event information. node.EventId.Value = Guid.NewGuid().ToByteArray(); node.EventType.Value = node.TypeDefinitionId; node.SourceNode.Value = NodeId; node.SourceName.Value = SymbolicName; node.ConditionName.Value = node.SymbolicName; node.Time.Value = _timeService.UtcNow; node.ReceiveTime.Value = node.Time.Value; if (node.LocalTime != null) { node.LocalTime.Value = Utils.GetTimeZoneInfo(); } node.Message.Value = "The dialog was activated"; node.Retain.Value = true; node.SetEnableState(context, true); node.SetSeverity(context, EventSeverity.Low); // initialize the dialog information. node.Prompt.Value = "Please specify a new state for the source."; node.ResponseOptionSet.Value = _responseOptions; node.DefaultResponse.Value = 2; node.CancelResponse.Value = 2; node.OkResponse.Value = 0; // set up method handlers. node.OnRespond = OnRespond; // this flag needs to be set because the underlying system does not produce these events. node.AutoReportStateChanges = true; // activate the dialog. node.Activate(context); // return the new node. return node; } /// /// The responses used with the dialog condition. /// private readonly LocalizedText[] _responseOptions = [ "Online", "Offline", "No Change" ]; /// /// Creates a new alarm for the source. /// /// The alarm. /// The branch id. /// The new alarm. private AlarmConditionState CreateAlarm(UnderlyingSystemAlarm alarm, NodeId branchId) { ISystemContext context = _nodeManager.SystemContext; AlarmConditionState node = null; // need to map the alarm type to a UA defined alarm type. switch (alarm.AlarmType) { case "HighAlarm": { var node2 = new ExclusiveDeviationAlarmState(this); node = node2; node2.HighLimit = new PropertyState(node2); break; } case "HighLowAlarm": { var node2 = new NonExclusiveLevelAlarmState(this); node = node2; node2.HighHighLimit = new PropertyState(node2); node2.HighLimit = new PropertyState(node2); node2.LowLimit = new PropertyState(node2); node2.LowLowLimit = new PropertyState(node2); node2.HighHighState = new TwoStateVariableState(node2); node2.HighState = new TwoStateVariableState(node2); node2.LowState = new TwoStateVariableState(node2); node2.LowLowState = new TwoStateVariableState(node2); break; } case "TripAlarm": { node = new TripAlarmState(this); break; } default: { node = new AlarmConditionState(this); break; } } node.SymbolicName = alarm.Name; // add optional components. node.Comment = new ConditionVariableState(node); node.ClientUserId = new PropertyState(node); node.AddComment = new AddCommentMethodState(node); node.ConfirmedState = new TwoStateVariableState(node); node.Confirm = new AddCommentMethodState(node); if (NodeId.IsNull(branchId)) { node.SuppressedState = new TwoStateVariableState(node); node.ShelvingState = new ShelvedStateMachineState(node); } // adding optional components to children is a little more complicated since the // necessary initilization strings defined by the class that represents the child. // in this case we pre-create the child, add the optional components // and call create without assigning NodeIds. The NodeIds will be assigned when the // parent object is created. node.EnabledState = new TwoStateVariableState(node); node.EnabledState.TransitionTime = new PropertyState(node.EnabledState); node.EnabledState.EffectiveDisplayName = new PropertyState(node.EnabledState); node.EnabledState.Create(context, null, BrowseNames.EnabledState, null, false); // same procedure add optional components to the ActiveState component. node.ActiveState = new TwoStateVariableState(node); node.ActiveState.TransitionTime = new PropertyState(node.ActiveState); node.ActiveState.EffectiveDisplayName = new PropertyState(node.ActiveState); node.ActiveState.Create(context, null, BrowseNames.ActiveState, null, false); // specify reference type between the source and the alarm. node.ReferenceTypeId = ReferenceTypeIds.HasComponent; // This call initializes the condition from the type model (i.e. creates all of the objects // and variables requried to store its state). The information about the type model was // incorporated into the class when the class was created. // // This method also assigns new NodeIds to all of the components by calling the INodeIdFactory.New // method on the INodeIdFactory object which is part of the system context. The NodeManager provides // the INodeIdFactory implementation used here. node.Create( context, null, new QualifiedName(alarm.Name, BrowseName.NamespaceIndex), null, true); // don't add branches to the address space. if (NodeId.IsNull(branchId)) { AddChild(node); } // initialize event information.node node.EventType.Value = node.TypeDefinitionId; node.SourceNode.Value = NodeId; node.SourceName.Value = SymbolicName; node.ConditionName.Value = node.SymbolicName; node.Time.Value = _timeService.UtcNow; node.ReceiveTime.Value = node.Time.Value; if (node.LocalTime != null) { node.LocalTime.Value = Utils.GetTimeZoneInfo(); } node.BranchId.Value = branchId; // set up method handlers. node.OnEnableDisable = OnEnableDisableAlarm; node.OnAcknowledge = OnAcknowledge; node.OnAddComment = OnAddComment; node.OnConfirm = OnConfirm; node.OnShelve = OnShelve; node.OnTimedUnshelve = OnTimedUnshelve; // return the new node. return node; } /// /// Updates the alarm with a new state. /// /// The node. /// The alarm. private void UpdateAlarm(AlarmConditionState node, UnderlyingSystemAlarm alarm) { ISystemContext context = _nodeManager.SystemContext; // remove old event. if (node.EventId.Value != null) { _events.Remove(Utils.ToHexString(node.EventId.Value)); } // update the basic event information (include generating a unique id for the event). node.EventId.Value = Guid.NewGuid().ToByteArray(); node.Time.Value = _timeService.UtcNow; node.ReceiveTime.Value = node.Time.Value; // save the event for later lookup. _events[Utils.ToHexString(node.EventId.Value)] = node; // determine the retain state. node.Retain.Value = true; if (alarm != null) { node.Time.Value = alarm.Time; node.Message.Value = new LocalizedText(alarm.Reason); // update the states. node.SetEnableState(context, (alarm.State & UnderlyingSystemAlarmStates.Enabled) != 0); node.SetAcknowledgedState(context, (alarm.State & UnderlyingSystemAlarmStates.Acknowledged) != 0); node.SetConfirmedState(context, (alarm.State & UnderlyingSystemAlarmStates.Confirmed) != 0); node.SetActiveState(context, (alarm.State & UnderlyingSystemAlarmStates.Active) != 0); node.SetSuppressedState(context, (alarm.State & UnderlyingSystemAlarmStates.Suppressed) != 0); // update other information. node.SetComment(context, alarm.Comment, alarm.UserName); node.SetSeverity(context, alarm.Severity); node.EnabledState.TransitionTime.Value = alarm.EnableTime; node.ActiveState.TransitionTime.Value = alarm.ActiveTime; // check for deleted items. if ((alarm.State & UnderlyingSystemAlarmStates.Deleted) != 0) { node.Retain.Value = false; } // handle high alarms. if (node is ExclusiveLimitAlarmState highAlarm) { highAlarm.HighLimit.Value = alarm.Limits[0]; if ((alarm.State & UnderlyingSystemAlarmStates.High) != 0) { highAlarm.SetLimitState(context, LimitAlarmStates.High); } } // handle high-low alarms. if (node is NonExclusiveLimitAlarmState highLowAlarm) { highLowAlarm.HighHighLimit.Value = alarm.Limits[0]; highLowAlarm.HighLimit.Value = alarm.Limits[1]; highLowAlarm.LowLimit.Value = alarm.Limits[2]; highLowAlarm.LowLowLimit.Value = alarm.Limits[3]; var limit = LimitAlarmStates.Inactive; if ((alarm.State & UnderlyingSystemAlarmStates.HighHigh) != 0) { limit |= LimitAlarmStates.HighHigh; } if ((alarm.State & UnderlyingSystemAlarmStates.High) != 0) { limit |= LimitAlarmStates.High; } if ((alarm.State & UnderlyingSystemAlarmStates.Low) != 0) { limit |= LimitAlarmStates.Low; } if ((alarm.State & UnderlyingSystemAlarmStates.LowLow) != 0) { limit |= LimitAlarmStates.LowLow; } highLowAlarm.SetLimitState(context, limit); } } // not interested in disabled or inactive alarms. if (!node.EnabledState.Id.Value || !node.ActiveState.Id.Value) { node.Retain.Value = false; } } /// /// Called when the alarm is enabled or disabled. /// /// /// /// private ServiceResult OnEnableDisableAlarm( ISystemContext context, ConditionState condition, bool enabling) { _source.EnableAlarm(condition.SymbolicName, enabling); return ServiceResult.Good; } /// /// Called when the alarm has a comment added. /// /// /// /// /// private ServiceResult OnAddComment( ISystemContext context, ConditionState condition, byte[] eventId, LocalizedText comment) { var alarm = FindAlarmByEventId(eventId); if (alarm == null) { return StatusCodes.BadEventIdUnknown; } _source.CommentAlarm(alarm.SymbolicName, GetRecordNumber(alarm), comment, GetUserName(context)); return ServiceResult.Good; } /// /// Called when the alarm is acknowledged. /// /// /// /// /// private ServiceResult OnAcknowledge( ISystemContext context, ConditionState condition, byte[] eventId, LocalizedText comment) { var alarm = FindAlarmByEventId(eventId); if (alarm == null) { return StatusCodes.BadEventIdUnknown; } _source.AcknowledgeAlarm(alarm.SymbolicName, GetRecordNumber(alarm), comment, GetUserName(context)); return ServiceResult.Good; } /// /// Called when the alarm is confirmed. /// /// /// /// /// private ServiceResult OnConfirm( ISystemContext context, ConditionState condition, byte[] eventId, LocalizedText comment) { var alarm = FindAlarmByEventId(eventId); if (alarm == null) { return StatusCodes.BadEventIdUnknown; } _source.ConfirmAlarm(alarm.SymbolicName, GetRecordNumber(alarm), comment, GetUserName(context)); return ServiceResult.Good; } /// /// Called when the alarm is shelved. /// /// /// /// /// /// private ServiceResult OnShelve( ISystemContext context, AlarmConditionState alarm, bool shelving, bool oneShot, double shelvingTime) { alarm.SetShelvingState(context, shelving, oneShot, shelvingTime); alarm.Message.Value = "The alarm shelved."; UpdateAlarm(alarm, null); ReportChanges(alarm); return ServiceResult.Good; } /// /// Called when the alarm is shelved. /// /// /// private ServiceResult OnTimedUnshelve( ISystemContext context, AlarmConditionState alarm) { // update the alarm state and produce and event. alarm.SetShelvingState(context, false, false, 0); alarm.Message.Value = "The timed shelving period expired."; UpdateAlarm(alarm, null); ReportChanges(alarm); return ServiceResult.Good; } /// /// Called when the dialog receives a response. /// /// /// /// private ServiceResult OnRespond( ISystemContext context, DialogConditionState dialog, int selectedResponse) { // response 0 means set the source online. if (selectedResponse == 0) { _source.SetOfflineState(false); } // response 1 means set the source offine. if (selectedResponse == 1) { _source.SetOfflineState(true); } // other responses mean do nothing. dialog.SetResponse(context, selectedResponse); // dialog no longer interesting once it is deactivated. dialog.Message.Value = "The dialog was deactivated"; dialog.Retain.Value = false; return ServiceResult.Good; } /// /// Reports the changes to the alarm. /// /// private void ReportChanges(AlarmConditionState alarm) { // report changes to node attributes. alarm.ClearChangeMasks(_nodeManager.SystemContext, true); // check if events are being monitored for the source. if (AreEventsMonitored) { // create a snapshot. var e = new InstanceStateSnapshot(); e.Initialize(_nodeManager.SystemContext, alarm); // report the event. alarm.ReportEvent(_nodeManager.SystemContext, e); } } /// /// Finds the alarm by event id. /// /// The event id. /// The alarm. Null if not found. private AlarmConditionState FindAlarmByEventId(byte[] eventId) { if (eventId == null) { return null; } if (!_events.TryGetValue(Utils.ToHexString(eventId), out var alarm)) { return null; } return alarm; } /// /// Gets the record number associated with tge alarm. /// /// The alarm. /// The record number; 0 if the alarm is not an archived alarm. private uint GetRecordNumber(AlarmConditionState alarm) { if (alarm == null) { return 0; } if (alarm.BranchId == null || alarm.BranchId.Value == null) { return 0; } var recordNumber = alarm.BranchId.Value.Identifier as uint?; return recordNumber ?? 0; } /// /// Gets the user name associated with the context. /// /// private string GetUserName(ISystemContext context) { if (context.UserIdentity != null) { return context.UserIdentity.DisplayName; } return null; } private readonly CustomNodeManager2 _nodeManager; private readonly TimeService _timeService; private readonly UnderlyingSystemSource _source; private readonly Dictionary _alarms; private readonly Dictionary _events; private readonly Dictionary _branches; private readonly DialogConditionState _dialog; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Alarms/UnderlyingSystem.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Alarms { using Opc.Ua; using Opc.Ua.Test; using System; using System.Collections.Generic; using System.Threading; /// /// An object that provides access to the underlying system. /// public class UnderlyingSystem : IDisposable { /// /// Initializes a new instance of the class. /// /// public UnderlyingSystem(TimeService timeService) { _sources = []; _timeService = timeService; } /// /// The finializer implementation. /// ~UnderlyingSystem() { Dispose(false); } /// /// Frees any unmanaged resources. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// An overrideable version of the Dispose. /// /// protected virtual void Dispose(bool disposing) { if (disposing && _simulationTimer != null) { _simulationTimer.Dispose(); _simulationTimer = null; } } /// /// Creates a source. /// /// The source path. /// The callback invoked when an alarm changes. /// The source. public UnderlyingSystemSource CreateSource(string sourcePath, AlarmChangedEventHandler alarmChangeCallback) { UnderlyingSystemSource source = null; lock (_lock) { // create a new source. source = new UnderlyingSystemSource(_timeService); // extract the name from the path. var name = sourcePath; var index = name.LastIndexOf('/'); if (index != -1) { name = name[(index + 1)..]; } // extract the type from the path. var type = sourcePath; index = type.IndexOf('/'); if (index != -1) { type = type[..index]; } // create the source. source.SourcePath = sourcePath; source.Name = name; source.SourceType = type; source.OnAlarmChanged = alarmChangeCallback; _sources.Add(sourcePath, source); } // add the alarms based on the source type. // note that the source and alarm types used here are types defined by the underlying system. // the node manager will need to map these types to UA defined types. switch (source.SourceType) { case "Colours": { source.CreateAlarm("Red", "HighAlarm"); source.CreateAlarm("Yellow", "HighLowAlarm"); source.CreateAlarm("Green", "TripAlarm"); break; } case "Metals": { source.CreateAlarm("Gold", "HighAlarm"); source.CreateAlarm("Silver", "HighLowAlarm"); source.CreateAlarm("Bronze", "TripAlarm"); break; } } // return the new source. return source; } /// /// Starts a simulation which causes the alarm states to change. /// /// /// This simulation randomly activates the alarms that belong to the sources. /// Once an alarm is active it has to be acknowledged and confirmed. /// Once an alarm is confirmed it go to the inactive state. /// If the alarm stays active the severity will be gradually increased. /// public void StartSimulation() { lock (_lock) { if (_simulationTimer != null) { _simulationTimer.Dispose(); _simulationTimer = null; } _simulationTimer = new Timer(DoSimulation, null, 1000, 1000); } } /// /// Stops the simulation. /// public void StopSimulation() { lock (_lock) { if (_simulationTimer != null) { _simulationTimer.Dispose(); _simulationTimer = null; } } } /// /// Simulates a source by updating the state of the alarms belonging to the condition. /// /// private void DoSimulation(object state) { try { // get the list of sources. List sources = null; lock (_lock) { _simulationCounter++; sources = [.. _sources.Values]; } // run simulation for each source. for (var ii = 0; ii < sources.Count; ii++) { sources[ii].DoSimulation(_simulationCounter, ii); } } catch (Exception e) { Utils.Trace(e, "Unexpected error running simulation for system"); } } private readonly Lock _lock = new(); private readonly Dictionary _sources; private readonly TimeService _timeService; private Timer _simulationTimer; private long _simulationCounter; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Alarms/UnderlyingSystemAlarm.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Alarms { using Opc.Ua; using System; /// /// This class stores the state of a alarm known to the system. /// /// /// This class only stores the information about an alarm that a system has. The /// system has no concept of the UA information model and the NodeManager must /// convert the information stored in this class into the UA equivalent. /// public class UnderlyingSystemAlarm { /// /// The source that the alarm belongs to /// /// The source. public UnderlyingSystemSource Source { get; set; } /// /// Gets or sets the name of the alarm. /// /// The name of the alarm. public string Name { get; set; } /// /// Gets or sets the type of the alarm. /// /// The type of the alarm. public string AlarmType { get; set; } /// /// Gets or sets a unique record number assigned to an archived snapshot of the alarm. /// /// The record number assigned to an archived snapshot of the alarm. /// /// Past state transitions are assigned a record number when they are archived. This /// Record number allows the system to updated archived record. This number is 0 if /// the state transition has not been archived. /// public uint RecordNumber { get; set; } /// /// Gets or sets the time when the alarm last changed state. /// /// The last state change time. public DateTime Time { get; set; } /// /// Gets or sets the reason for the last state change. /// /// The reason for the last state change. public string Reason { get; set; } /// /// Gets or sets the severity of the alarm. /// /// The alarm severity. public EventSeverity Severity { get; set; } /// /// Gets or sets the comment associated with the alarm. /// /// The comment. public string Comment { get; set; } /// /// Gets or sets the name of the user that provided the comment. /// /// The name of the user that provided the comment. public string UserName { get; set; } /// /// Gets or sets the current alarm state. /// /// The current alarm state. public UnderlyingSystemAlarmStates State { get; set; } /// /// Gets or sets the time when the alarm went into the enabled state. /// /// When the alarm went into the enabled state. public DateTime EnableTime { get; set; } /// /// Gets or sets the time when the alarm went into the active state. /// /// When the alarm went into the active state. public DateTime ActiveTime { get; set; } /// /// Gets or sets the limits that apply to the alarm. /// /// The limits that apply to the alarm. /// /// 1 limit = High /// 2 limits = High, Low /// 4 limits = HighHigh, High, Low, LowLow /// public double[] Limits { get; set; } /// /// Creates a snapshort of the alarm. /// /// The snapshot, public UnderlyingSystemAlarm CreateSnapshot() { return (UnderlyingSystemAlarm)MemberwiseClone(); } /// /// Sets or clears the bits in the alarm state mask. /// /// The bits. /// if set to true the bits are set; otherwise they are cleared. /// True if the state changed as a result of setting the bits. public bool SetStateBits(UnderlyingSystemAlarmStates bits, bool isSet) { if (isSet) { var currentlySet = (State & bits) == bits; State |= bits; return !currentlySet; } var currentlyCleared = (State & ~bits) == State; State &= ~bits; return !currentlyCleared; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Alarms/UnderlyingSystemAlarmStates.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Alarms { using System; /// /// Defines the possible states for the condition. /// [Flags] public enum UnderlyingSystemAlarmStates { /// /// The condition state is unknown. /// None = 0x0, /// /// The condition is enabled and will produce events. /// Enabled = 0x1, /// /// The condition requires acknowledgement by the user. /// Acknowledged = 0x2, /// /// The condition requires that the used confirm that action was taken. /// Confirmed = 0x4, /// /// The condition is active. /// Active = 0x8, /// /// The condition has been suppressed by the system. /// Suppressed = 0x10, /// /// The condition has been shelved by the user. /// Shelved = 0x20, /// /// The condition has exceeed the high-high limit. /// HighHigh = 0x40, /// /// The condition has exceeed the high limit. /// High = 0x80, /// /// The condition has exceeed the low limit. /// Low = 0x100, /// /// The condition has exceeed the low-low limit. /// LowLow = 0x200, /// /// A mask used to clear all limit bits. /// Limits = HighHigh | High | Low | LowLow, /// /// The condition has deleted. /// Deleted = 0x400 } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Alarms/UnderlyingSystemSource.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Alarms { using Opc.Ua; using Opc.Ua.Test; using System; using System.Collections.Generic; /// /// This class simulates a source in the system. /// public class UnderlyingSystemSource { /// /// Initializes a new instance of the class. /// /// public UnderlyingSystemSource(TimeService timeService) { _alarms = []; _archive = []; _timeService = timeService; } /// /// Used to receive events when the state of an alarm changed. /// public AlarmChangedEventHandler OnAlarmChanged { get; set; } /// /// Gets or sets the name of the source. /// /// The name. public string Name { get; set; } /// /// Gets or sets the fully qualified name for the source. /// /// The fully qualified name for a source. public string SourcePath { get; set; } /// /// Gets or sets the type of the source. /// /// The type of the source. public string SourceType { get; set; } /// /// Creates a new active alarm for the source. /// /// Name of the alarm. /// Type of the alarm. public void CreateAlarm(string alarmName, string alarmType) { var alarm = new UnderlyingSystemAlarm { Source = this, Name = alarmName, AlarmType = alarmType, RecordNumber = 0, Reason = "Alarm created.", Time = _timeService.UtcNow, Severity = EventSeverity.Low, Comment = null, UserName = null, State = UnderlyingSystemAlarmStates.Active | UnderlyingSystemAlarmStates.Enabled, EnableTime = _timeService.UtcNow, ActiveTime = _timeService.UtcNow }; switch (alarmType) { case "HighAlarm": { alarm.Limits = [80]; alarm.State |= UnderlyingSystemAlarmStates.High; break; } case "HighLowAlarm": { alarm.Limits = [90, 70, 30, 10]; alarm.State |= UnderlyingSystemAlarmStates.High; break; } } lock (_alarms) { _alarms.Add(alarm); } } /// /// Enables or disables the alarm. /// /// Name of the alarm. /// if set to true the alarm is enabled. public void EnableAlarm(string alarmName, bool enabling) { var snapshots = new List(); lock (_alarms) { var alarm = FindAlarm(alarmName, 0); if (alarm != null) { // enable/disable the alarm. if (alarm.SetStateBits(UnderlyingSystemAlarmStates.Enabled, enabling)) { alarm.Time = alarm.EnableTime = _timeService.UtcNow; alarm.Reason = "The alarm was " + (enabling ? "enabled." : "disabled."); snapshots.Add(alarm.CreateSnapshot()); } // enable/disable any archived records for the alarm. foreach (var record in _archive.Values) { if (record.Name != alarmName) { continue; } if (record.SetStateBits(UnderlyingSystemAlarmStates.Enabled, enabling)) { record.Time = alarm.EnableTime = _timeService.UtcNow; record.Reason = "The alarm was " + (enabling ? "enabled." : "disabled."); snapshots.Add(alarm.CreateSnapshot()); } } } } // report any alarm changes after releasing the lock. for (var ii = 0; ii < snapshots.Count; ii++) { ReportAlarmChange(snapshots[ii]); } } /// /// Adds a comment to an alarm. /// /// Name of the alarm. /// The record number. /// The comment. /// Name of the user. public void CommentAlarm(string alarmName, uint recordNumber, LocalizedText comment, string userName) { UnderlyingSystemAlarm snapshot = null; lock (_alarms) { var alarm = FindAlarm(alarmName, recordNumber); if (alarm != null) { alarm.Time = _timeService.UtcNow; alarm.Reason = "A comment was added."; alarm.UserName = userName; // only change the comment if a non-null comment was provided. if (comment != null && (!string.IsNullOrEmpty(comment.Text) || !string.IsNullOrEmpty(comment.Locale))) { alarm.Comment = Utils.Format("{0}", comment); } snapshot = alarm.CreateSnapshot(); } } if (snapshot != null) { ReportAlarmChange(snapshot); } } /// /// Acknowledges an alarm. /// /// Name of the alarm. /// The record number. /// The comment. /// Name of the user. public void AcknowledgeAlarm(string alarmName, uint recordNumber, LocalizedText comment, string userName) { UnderlyingSystemAlarm snapshot = null; lock (_alarms) { var alarm = FindAlarm(alarmName, recordNumber); if (alarm != null) { if (alarm.SetStateBits(UnderlyingSystemAlarmStates.Acknowledged, true)) { alarm.Time = _timeService.UtcNow; alarm.Reason = "The alarm was acknoweledged."; alarm.Comment = Utils.Format("{0}", comment); alarm.UserName = userName; alarm.SetStateBits(UnderlyingSystemAlarmStates.Confirmed, false); } snapshot = alarm.CreateSnapshot(); } } if (snapshot != null) { ReportAlarmChange(snapshot); } } /// /// Confirms an alarm. /// /// Name of the alarm. /// The record number. /// The comment. /// Name of the user. public void ConfirmAlarm(string alarmName, uint recordNumber, LocalizedText comment, string userName) { UnderlyingSystemAlarm snapshot = null; lock (_alarms) { var alarm = FindAlarm(alarmName, recordNumber); if (alarm != null) { if (alarm.SetStateBits(UnderlyingSystemAlarmStates.Confirmed, true)) { alarm.Time = _timeService.UtcNow; alarm.Reason = "The alarm was confirmed."; alarm.Comment = Utils.Format("{0}", comment); alarm.UserName = userName; // remove branch. if (recordNumber != 0) { _archive.Remove(recordNumber); alarm.SetStateBits(UnderlyingSystemAlarmStates.Deleted, true); } // de-activate alarm. else { alarm.SetStateBits(UnderlyingSystemAlarmStates.Active, false); } } snapshot = alarm.CreateSnapshot(); } } if (snapshot != null) { ReportAlarmChange(snapshot); } } /// /// Reports the current state of all conditions. /// public void Refresh() { var snapshots = new List(); lock (_alarms) { for (var ii = 0; ii < _alarms.Count; ii++) { var alarm = _alarms[ii]; snapshots.Add(alarm.CreateSnapshot()); } } // report any alarm changes after releasing the lock. for (var ii = 0; ii < snapshots.Count; ii++) { ReportAlarmChange(snapshots[ii]); } } /// /// Sets the state of the source (surpresses any active alarms). /// /// if set to true the source is offline. public void SetOfflineState(bool offline) { IsOffline = offline; var snapshots = new List(); lock (_alarms) { for (var ii = 0; ii < _alarms.Count; ii++) { var alarm = _alarms[ii]; if (alarm.SetStateBits(UnderlyingSystemAlarmStates.Suppressed, offline)) { alarm.Time = alarm.EnableTime = _timeService.UtcNow; alarm.Reason = "The alarm was " + (offline ? "suppressed." : "unsuppressed."); // check if the alarm change should be reported. if ((alarm.State & UnderlyingSystemAlarmStates.Enabled) != 0) { snapshots.Add(alarm.CreateSnapshot()); } } } } // report any alarm changes after releasing the lock. for (var ii = 0; ii < snapshots.Count; ii++) { ReportAlarmChange(snapshots[ii]); } } /// /// Gets a value indicating whether the source is offline. /// /// /// true if this instance is offline; otherwise, false. /// /// /// All alarms for offline sources are suppressed. /// public bool IsOffline { get; private set; } /// /// Simulates a source by updating the state of the alarms belonging to the condition. /// /// The number of simulation cycles that have elapsed. /// The index of the source within the system. public void DoSimulation(long counter, int index) { try { var snapshots = new List(); // update the alarms. lock (_alarms) { for (var ii = 0; ii < _alarms.Count; ii++) { UpdateAlarm(_alarms[ii], counter, ii + index, snapshots); } } // report any alarm changes after releasing the lock. for (var ii = 0; ii < snapshots.Count; ii++) { ReportAlarmChange(snapshots[ii]); } } catch (Exception e) { Utils.Trace(e, "Unexpected error running simulation for source {0}", SourcePath); } } /// /// Finds the alarm identified by the name. /// /// Name of the alarm. /// The record number associated with the alarm. /// The alarm if null; otherwise null. private UnderlyingSystemAlarm FindAlarm(string alarmName, uint recordNumber) { lock (_alarms) { // look up archived alarm. if (recordNumber != 0) { if (!_archive.TryGetValue(recordNumber, out var alarm)) { return null; } return alarm; } // look up alarm. for (var ii = 0; ii < _alarms.Count; ii++) { var alarm = _alarms[ii]; if (alarm.Name == alarmName) { return alarm; } } return null; } } /// /// Reports a change to an alarm record. /// /// The alarm. private void ReportAlarmChange(UnderlyingSystemAlarm alarm) { if (OnAlarmChanged != null) { try { OnAlarmChanged(alarm); } catch (Exception e) { Utils.Trace(e, "Unexpected error reporting change to an Alarm for Source {0}.", SourcePath); } } } /// /// Updates the state of an alarm. /// /// /// /// /// private void UpdateAlarm(UnderlyingSystemAlarm alarm, long counter, int index, List snapshots) { string reason = null; // ignore disabled alarms. if ((alarm.State & UnderlyingSystemAlarmStates.Enabled) == 0) { return; } // check if the alarm needs to be updated this cycle. if (counter % (8 + (index % 4)) == 0) { // check if it is time to activate. if ((alarm.State & UnderlyingSystemAlarmStates.Active) == 0) { reason = "The alarm is active."; alarm.SetStateBits(UnderlyingSystemAlarmStates.Active, true); alarm.SetStateBits(UnderlyingSystemAlarmStates.Acknowledged | UnderlyingSystemAlarmStates.Confirmed, false); alarm.Severity = EventSeverity.Low; alarm.ActiveTime = _timeService.UtcNow; switch (alarm.AlarmType) { case "HighAlarm": { alarm.SetStateBits(UnderlyingSystemAlarmStates.Limits, false); alarm.SetStateBits(UnderlyingSystemAlarmStates.High, true); break; } case "HighLowAlarm": { alarm.SetStateBits(UnderlyingSystemAlarmStates.Limits, false); alarm.SetStateBits(UnderlyingSystemAlarmStates.Low, true); break; } } } // bump the severity. else if ((alarm.State & UnderlyingSystemAlarmStates.Acknowledged) == 0) { if (alarm.Severity < EventSeverity.High) { reason = "The alarm severity has increased."; var values = Enum.GetValues(); for (var ii = 0; ii < values.Length; ii++) { var severity = (EventSeverity)values.GetValue(ii); if (severity > alarm.Severity) { alarm.Severity = severity; break; } } if (alarm.Severity > EventSeverity.Medium) { switch (alarm.AlarmType) { case "HighLowAlarm": { alarm.SetStateBits(UnderlyingSystemAlarmStates.Limits, false); alarm.SetStateBits(UnderlyingSystemAlarmStates.LowLow, true); break; } } } } // give up on the alarm. else { // create an archived state that needs to be acknowledged. if (alarm.AlarmType == "TripAlarm") { // check the number of archived states. var count = 0; foreach (var record in _archive.Values) { if (record.Name == alarm.Name) { count++; } } // limit the number of archived states to avoid filling up the display. if (count < 2) { // archive the current state. var snapshot = alarm.CreateSnapshot(); snapshot.RecordNumber = ++_nextRecordNumber; snapshot.Severity = EventSeverity.Low; _archive.Add(snapshot.RecordNumber, snapshot); snapshots.Add(snapshot); } } reason = "The alarm was deactivated by the system."; alarm.SetStateBits(UnderlyingSystemAlarmStates.Active, false); //alarm.SetStateBits(UnderlyingSystemAlarmStates.Acknowledged | UnderlyingSystemAlarmStates.Confirmed, true); alarm.Severity = EventSeverity.Low; } } } // update the reason. if (reason != null) { alarm.Time = _timeService.UtcNow; alarm.Reason = reason; // return a snapshot used to report the state change. snapshots.Add(alarm.CreateSnapshot()); } // no change so nothing to report. } private readonly List _alarms; private readonly Dictionary _archive; private readonly TimeService _timeService; private uint _nextRecordNumber; } /// /// Used to receive events when the state of an alarm changes. /// /// public delegate void AlarmChangedEventHandler(UnderlyingSystemAlarm alarm); } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Asset/AssetNodeManager.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ #nullable enable namespace Asset { using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Opc.Ua; using Opc.Ua.Server; using System; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Reflection; public class AssetNodeManager : CustomNodeManager2 { /// /// Create node manager /// /// /// /// public AssetNodeManager(IServerInternal server, ApplicationConfiguration configuration, ILogger logger) : base(server, configuration) { SystemContext.NodeIdFactory = this; _logger = logger; var extension = configuration.ParseExtension(); _folder = Path.Combine(extension?.CurrentDirectory ?? Directory.GetCurrentDirectory(), "settings"); // create our settings folder, if required if (!Directory.Exists(_folder)) { Directory.CreateDirectory(_folder); } // in the node manager constructor, we add all namespaces var namespaceUris = new List { Namespaces.AssetServer }; LoadNamespaceUrisFromEmbeddedNodesetXml(namespaceUris); // add a seperate namespace for each asset from the WoT TD files foreach (var file in Directory.EnumerateFiles(_folder, "*.jsonld")) { try { var contents = File.ReadAllText(file); // parse WoT TD file contents var td = JsonConvert.DeserializeObject(contents) ?? throw ServiceResultException.Create( StatusCodes.BadConfigurationError, "Bad description"); namespaceUris.Add("http://opcfoundation.org/UA/" + td.Name + "/"); AddNamespacesFromCompanionSpecs(namespaceUris, td); } catch (Exception ex) { // skip this file, but log an error _logger.AssetNodeManagerError(ex); } } NamespaceUris = namespaceUris; } protected override void Dispose(bool disposing) { if (disposing) { lock (Lock) { foreach (var manager in _fileManagers.Values) { manager.Dispose(); } foreach (var asset in _assets.Values) { asset.Dispose(); } _fileManagers.Clear(); _assetManagement.Dispose(); } } base.Dispose(disposing); } public override NodeId New(ISystemContext context, NodeState node) { // for new nodes we create, pick our default namespace return new NodeId(Utils.IncrementIdentifier(ref _lastUsedId), (ushort)Server.NamespaceUris.GetIndex(Namespaces.AssetServer)); } public override void CreateAddressSpace(IDictionary> externalReferences) { lock (Lock) { // in the create address space call, we add all our nodes if (!externalReferences.TryGetValue(Opc.Ua.ObjectIds.ObjectsFolder, out var objectsFolderReferences)) { externalReferences[Opc.Ua.ObjectIds.ObjectsFolder] = objectsFolderReferences = []; } AddNodesFromEmbeddedNodesetXml(); AddNodesForAssetManagement(objectsFolderReferences); foreach (var file in Directory.EnumerateFiles(_folder, "*.jsonld")) { try { var contents = File.ReadAllText(file); // parse WoT TD file contents var td = JsonConvert.DeserializeObject(contents); if (td?.Context == null || td.Name == null) { continue; } #pragma warning disable CA2000 // Dispose objects before losing scope if (CreateAssetNode(td.Name, out var assetNode)) { AddNodesForThingDescription(assetNode, td); } #pragma warning restore CA2000 // Dispose objects before losing scope } catch (Exception ex) { // skip this file, but log an error _logger.AssetConfigError(ex); } } AddReverseReferences(externalReferences); base.CreateAddressSpace(externalReferences); } } public override void DeleteAddressSpace() { lock (Lock) { base.DeleteAddressSpace(); } } internal ServiceResult OnCreateAsset(ISystemContext _context, MethodState _method, NodeId _objectId, string assetName, ref NodeId assetId) { lock (Lock) { if (string.IsNullOrEmpty(assetName)) { return ServiceResult.Create(StatusCodes.BadInvalidArgument, "Argument invalid"); } #pragma warning disable CA2000 // Dispose objects before losing scope var success = CreateAssetNode(assetName, out var assetNode); #pragma warning restore CA2000 // Dispose objects before losing scope if (!success) { return new ServiceResult(StatusCodes.BadBrowseNameDuplicated, new LocalizedText(assetNode.NodeId.ToString())); } assetId = assetNode.NodeId; return ServiceResult.Good; } } internal ServiceResult OnDeleteAsset(ISystemContext _context, MethodState _method, NodeId _objectId, NodeId assetId) { lock (Lock) { var asset = FindPredefinedNode(assetId, typeof(IWoTAssetTypeState)); if (asset == null) { return ServiceResult.Create(StatusCodes.BadNodeIdUnknown, "Not found"); } var assetName = asset.DisplayName.Text; if (_fileManagers.TryGetValue(assetId, out var filemanager)) { filemanager.Delete(); // Delete the file filemanager.Dispose(); _fileManagers.Remove(assetId); } DeleteNode(SystemContext, assetId); _tags.Remove(assetName); _assets.Remove(assetName); foreach (var key in _uaVariables.Keys.Where(n => n.StartsWith( assetName + ":", StringComparison.InvariantCulture)).ToList()) { _uaVariables.Remove(key); } return ServiceResult.Good; } } internal ServiceResult OnSimpleReadValue(ISystemContext context, NodeState node, ref object? value) { if (!TryGetBinding(node, out var assetInterface, out var assetTag)) { return ServiceResult.Create(StatusCodes.BadInvalidState, "Asset not found"); } return assetInterface.Read(assetTag, ref value); } internal ServiceResult OnSimpleWriteValue(ISystemContext context, NodeState node, ref object value) { if (!TryGetBinding(node, out var assetInterface, out var assetTag)) { return ServiceResult.Create(StatusCodes.BadInvalidState, "Asset not found"); } return assetInterface.Write(assetTag, ref value); } internal void OnDataChange(BaseVariableState variable, AssetTag assetTag, object? value, StatusCode statusCode, DateTime timestamp) { lock (Lock) { _logger.DataChange(assetTag); variable.Value = value; variable.StatusCode = statusCode; variable.Timestamp = timestamp; // notifies any monitored items that the value has changed. variable.ClearChangeMasks(SystemContext, false); } } /// /// Called after creating a MonitoredItem2. /// /// The context. /// The handle for the node. /// The monitored item. protected override void OnMonitoredItemCreated(ServerSystemContext context, NodeHandle handle, ISampledDataChangeMonitoredItem monitoredItem) { if (TryGetBinding(handle.Node, out var assetInterface, out var assetTag) && monitoredItem.MonitoringMode != MonitoringMode.Disabled && handle.Node is BaseVariableState source) { assetInterface.Observe(assetTag, monitoredItem.Id, (tag, value, status, timestamp) => OnDataChange(source, tag, value, status, timestamp)); } } /// /// Called after modifying a MonitoredItem2. /// /// The context. /// The handle for the node. /// The monitored item. protected override void OnMonitoredItemModified(ServerSystemContext context, NodeHandle handle, ISampledDataChangeMonitoredItem monitoredItem) { if (TryGetBinding(handle.Node, out var assetInterface, out var assetTag) && monitoredItem.MonitoringMode != MonitoringMode.Disabled && handle.Node is BaseVariableState source) { assetInterface.Unobserve(assetTag, monitoredItem.Id); assetInterface.Observe(assetTag, monitoredItem.Id, (tag, value, status, timestamp) => OnDataChange(source, tag, value, status, timestamp)); } } /// /// Called after deleting a MonitoredItem2. /// /// The context. /// The handle for the node. /// The monitored item. protected override void OnMonitoredItemDeleted(ServerSystemContext context, NodeHandle handle, ISampledDataChangeMonitoredItem monitoredItem) { if (TryGetBinding(handle.Node, out var assetInterface, out var assetTag) && handle.Node is BaseVariableState) { assetInterface.Unobserve(assetTag, monitoredItem.Id); } } /// /// Called after changing the MonitoringMode for a MonitoredItem2. /// /// The context. /// The handle for the node. /// The monitored item. /// The previous monitoring mode. /// The current monitoring mode. protected override void OnMonitoringModeChanged(ServerSystemContext context, NodeHandle handle, ISampledDataChangeMonitoredItem monitoredItem, MonitoringMode previousMode, MonitoringMode monitoringMode) { if (TryGetBinding(handle.Node, out var assetInterface, out var assetTag) && handle.Node is BaseVariableState source) { if (previousMode != MonitoringMode.Disabled && monitoredItem.MonitoringMode == MonitoringMode.Disabled) { assetInterface.Unobserve(assetTag, monitoredItem.Id); } if (previousMode == MonitoringMode.Disabled && monitoredItem.MonitoringMode != MonitoringMode.Disabled) { assetInterface.Observe(assetTag, monitoredItem.Id, (tag, value, status, timestamp) => OnDataChange(source, tag, value, status, timestamp)); } } } public void AddNodesForThingDescription(NodeState parent, ThingDescription td) { lock (Lock) { AddNodesForThingDescriptionInternal(parent, td); } } private void AddNodesForThingDescriptionInternal(NodeState parent, ThingDescription td) { ArgumentNullException.ThrowIfNull(td.Context); // Limitation, the asset name must be the name we are using as thing name td.Name = parent.BrowseName.Name; var newNamespace = "http://opcfoundation.org/UA/" + td.Name + "/"; List namespaceUris = [.. NamespaceUris]; if (!namespaceUris.Contains(newNamespace)) { namespaceUris.Add(newNamespace); } foreach (var ns in td.Context) { var nsUri = ns.ToString() ?? string.Empty; if (!nsUri.Contains("https://www.w3.org/", StringComparison.InvariantCulture) && nsUri.Contains("opcua", StringComparison.InvariantCulture)) { var namespaces = JsonConvert.DeserializeObject(nsUri); if (namespaces?.Namespaces == null) { continue; } foreach (var opcuaCompanionSpecUrl in namespaces.Namespaces) { namespaceUris.Add(opcuaCompanionSpecUrl.ToString()); } } } AddNamespacesFromCompanionSpecs(namespaceUris, td); NamespaceUris = namespaceUris; AddNodesFromCompanionSpecs(td); var assetId = GetOrAddAssetForThing(td); // create nodes for each TD property if (td.Properties != null) { foreach (var property in td.Properties) { if (property.Value.Forms != null) { foreach (var form in property.Value.Forms) { var formString = form?.ToString(); if (formString != null) { AddNodeAndAssetTagForWotProperty(parent, td, property.Key, property.Value, formString, assetId); } } } } } _logger.WoTParsed(assetId); } private bool CreateAssetNode(string assetName, out NodeState assetNode) { // check if the asset node already exists var browser = _assetManagement.CreateBrowser(SystemContext, null, null, false, BrowseDirection.Forward, null, null, true); var reference = browser.Next(); while ((reference != null) && (reference is NodeStateReference)) { var node = reference as NodeStateReference; if ((node?.Target != null) && (node.Target.DisplayName.Text == assetName)) { assetNode = node.Target; return false; } reference = browser.Next(); } var asset = new IWoTAssetTypeState(_assetManagement); asset.Create(SystemContext, NodeId.Null, new QualifiedName(assetName), null, true); _assetManagement.AddChild(asset); _fileManagers.Add(asset.NodeId, new FileManager(this, asset.WoTFile, _folder, _logger)); AddPredefinedNode(SystemContext, asset); assetNode = asset; return true; } private void AddNodesForAssetManagement(IList objectsFolderReferences) { var WoTConNamespaceIndex = (ushort)Server.NamespaceUris.GetIndex(Namespaces.WoT_Con); var assetManagementPassiveNode = (BaseObjectState)FindPredefinedNode( new NodeId(Objects.WoTAssetConnectionManagement, WoTConNamespaceIndex), typeof(BaseObjectState)); _assetManagement.Create(SystemContext, assetManagementPassiveNode); var createAssetPassiveNode = (MethodState)FindPredefinedNode( new NodeId(Methods.WoTAssetConnectionManagement_CreateAsset, WoTConNamespaceIndex), typeof(MethodState)); _assetManagement.CreateAsset = new(null); _assetManagement.CreateAsset.Create(SystemContext, createAssetPassiveNode); _assetManagement.CreateAsset.OnCall = new CreateAssetMethodStateMethodCallHandler(OnCreateAsset); var createAssetInputArgumentsPassiveNode = (BaseVariableState)FindPredefinedNode( new NodeId(Variables.WoTAssetConnectionManagementType_CreateAsset_InputArguments, WoTConNamespaceIndex), typeof(BaseVariableState)); _assetManagement.CreateAsset.InputArguments = new(null); _assetManagement.CreateAsset.InputArguments.Create(SystemContext, createAssetInputArgumentsPassiveNode); var createAssetOutputArgumentsPassiveNode = (BaseVariableState)FindPredefinedNode( new NodeId(Variables.WoTAssetConnectionManagementType_CreateAsset_OutputArguments, WoTConNamespaceIndex), typeof(BaseVariableState)); _assetManagement.CreateAsset.OutputArguments = new(null); _assetManagement.CreateAsset.OutputArguments.Create(SystemContext, createAssetOutputArgumentsPassiveNode); var deleteAssetPassiveNode = (MethodState)FindPredefinedNode( new NodeId(Methods.WoTAssetConnectionManagement_DeleteAsset, WoTConNamespaceIndex), typeof(MethodState)); _assetManagement.DeleteAsset = new(null); _assetManagement.DeleteAsset.Create(SystemContext, deleteAssetPassiveNode); _assetManagement.DeleteAsset.OnCall = new DeleteAssetMethodStateMethodCallHandler(OnDeleteAsset); var deleteAssetInputArgumentsPassiveNode = (BaseVariableState)FindPredefinedNode( new NodeId(Variables.WoTAssetConnectionManagementType_DeleteAsset_InputArguments, WoTConNamespaceIndex), typeof(BaseVariableState)); _assetManagement.DeleteAsset.InputArguments = new(null); _assetManagement.DeleteAsset.InputArguments.Create(SystemContext, deleteAssetInputArgumentsPassiveNode); // create a variable listing our supported WoT protocol bindings #pragma warning disable CA2000 // Dispose objects before losing scope CreateVariable(_assetManagement, "SupportedWoTBindings", new ExpandedNodeId(DataTypes.UriString), WoTConNamespaceIndex, new[] { "https://www.w3.org/2019/wot/modbus", "https://www.github.com/Azure/Industrial-IoT/sim" }); #pragma warning restore CA2000 // Dispose objects before losing scope // add everything to our server namespace objectsFolderReferences.Add(new NodeStateReference(Opc.Ua.ReferenceTypes.Organizes, false, _assetManagement.NodeId)); AddPredefinedNode(SystemContext, _assetManagement); } private void AddNamespacesFromCompanionSpecs(List namespaceUris, ThingDescription td) { ArgumentNullException.ThrowIfNull(td.Context); // check if an OPC UA companion spec is mentioned in the WoT TD file foreach (var ns in td.Context) { var nsUri = ns.ToString() ?? string.Empty; if (nsUri.Contains("https://www.w3.org/", StringComparison.InvariantCulture) && !nsUri.Contains("opcua", StringComparison.InvariantCulture)) { continue; } var namespaces = JsonConvert.DeserializeObject(nsUri); if (namespaces?.Namespaces == null) { continue; } foreach (var opcuaCompanionSpecUrl in namespaces.Namespaces) { // support local Nodesets if (!opcuaCompanionSpecUrl.IsAbsoluteUri || (!opcuaCompanionSpecUrl.AbsoluteUri.Contains("http://", StringComparison.InvariantCulture) && !opcuaCompanionSpecUrl.AbsoluteUri.Contains("https://", StringComparison.InvariantCulture))) { string? nodesetFile; if (Path.IsPathFullyQualified(opcuaCompanionSpecUrl.OriginalString)) { // absolute file path nodesetFile = opcuaCompanionSpecUrl.OriginalString; } else { // relative file path nodesetFile = Path.Combine(Directory.GetCurrentDirectory(), opcuaCompanionSpecUrl.OriginalString); } _logger.LoadingNodeset(nodesetFile); LoadNamespaceUrisFromNodesetXml(namespaceUris, nodesetFile); } } } } private void AddNodesFromCompanionSpecs(ThingDescription td) { ArgumentNullException.ThrowIfNull(td.Context); foreach (var ns in td.Context) { var nsUri = ns.ToString() ?? string.Empty; if (nsUri.Contains("https://www.w3.org/", StringComparison.InvariantCulture) && !nsUri.Contains("opcua", StringComparison.InvariantCulture)) { continue; } var namespaces = JsonConvert.DeserializeObject(nsUri); if (namespaces?.Namespaces == null) { continue; } foreach (var opcuaCompanionSpecUrl in namespaces.Namespaces) { // support local Nodesets if (!opcuaCompanionSpecUrl.IsAbsoluteUri || (!opcuaCompanionSpecUrl.AbsoluteUri.Contains("http://", StringComparison.InvariantCulture) && !opcuaCompanionSpecUrl.AbsoluteUri.Contains("https://", StringComparison.InvariantCulture))) { string? nodesetFile; if (Path.IsPathFullyQualified(opcuaCompanionSpecUrl.OriginalString)) { // absolute file path nodesetFile = opcuaCompanionSpecUrl.OriginalString; } else { // relative file path nodesetFile = Path.Combine(Directory.GetCurrentDirectory(), opcuaCompanionSpecUrl.OriginalString); } _logger.AddingNodeset(); AddNodesFromNodesetXml(nodesetFile); } } } } private static void LoadNamespaceUrisFromNodesetXml(List namespaceUris, string nodesetFile) { using var stream = new FileStream(nodesetFile, FileMode.Open, FileAccess.Read); var nodeSet = Opc.Ua.Export.UANodeSet.Read(stream); if (nodeSet.NamespaceUris?.Length > 0) { foreach (var ns in nodeSet.NamespaceUris) { if (!namespaceUris.Contains(ns)) { namespaceUris.Add(ns); } } } } private void LoadNamespaceUrisFromEmbeddedNodesetXml(List namespaceUris) { var type = GetType().GetTypeInfo(); var resourcePath = $"{type.Assembly.GetName().Name}.Generated.{type.Namespace}.Design.{type.Namespace}.NodeSet2.xml"; var stream = type.Assembly.GetManifestResourceStream(resourcePath); if (stream == null) { throw new ServiceResultException("Failed to load nodeset xml from embedded resource"); } try { var nodeSet = Opc.Ua.Export.UANodeSet.Read(stream); if (nodeSet.NamespaceUris?.Length > 0) { foreach (var ns in nodeSet.NamespaceUris) { if (!namespaceUris.Contains(ns)) { namespaceUris.Add(ns); } } } } finally { stream.Dispose(); } } private void AddNodesFromNodesetXml(string nodesetFile) { using var stream = new FileStream(nodesetFile, FileMode.Open); var nodeSet = Opc.Ua.Export.UANodeSet.Read(stream); var predefinedNodes = new NodeStateCollection(); nodeSet.Import(SystemContext, predefinedNodes); for (var i = 0; i < predefinedNodes.Count; i++) { try { AddPredefinedNode(SystemContext, predefinedNodes[i]); } catch (Exception ex) { _logger.AssetNodeManagerError(ex); } } } private void AddNodesFromEmbeddedNodesetXml() { var type = GetType().GetTypeInfo(); var resourcePath = $"{type.Assembly.GetName().Name}.Generated.{type.Namespace}.Design.{type.Namespace}.NodeSet2.xml"; var stream = type.Assembly.GetManifestResourceStream(resourcePath); if (stream == null) { throw new ServiceResultException("Failed to load nodeset xml from embedded resource"); } try { var nodeSet = Opc.Ua.Export.UANodeSet.Read(stream); var predefinedNodes = new NodeStateCollection(); nodeSet.Import(SystemContext, predefinedNodes); for (var i = 0; i < predefinedNodes.Count; i++) { try { AddPredefinedNode(SystemContext, predefinedNodes[i]); } catch (Exception ex) { _logger.AssetNodeManagerError(ex); } } } finally { stream.Dispose(); } } private void AddNodeAndAssetTagForWotProperty(NodeState assetFolder, ThingDescription td, string propertyName, Property property, string form, string assetId) { var assetTag = AddAssetTagForTdProperty(td, propertyName, property, form, assetId); // create an OPC UA variable optionally with a specified type. var variable = CreateAssetTagVariable(assetFolder, assetTag.Name, new ExpandedNodeId(DataTypes.Float), assetFolder.NodeId.NamespaceIndex, assetId, !property.ReadOnly); _uaVariables.Add($"{assetId}:{propertyName}", variable); } private AssetTag AddAssetTagForTdProperty(ThingDescription td, string propertyName, Property property, string form, string assetId) { _logger.AddAssetForProperty(property); // check if we need to create a new asset first if (!_tags.TryGetValue(assetId, out var tagList)) { tagList = []; _tags.Add(assetId, tagList); } if (!Uri.TryCreate(td.Base, UriKind.Absolute, out var baseUri)) { throw new FormatException("Missing uri information in thing description."); } else if (baseUri.Scheme == "modbus+tcp") { // create an asset tag and add to our list var modbusForm = JsonConvert.DeserializeObject(form); if (modbusForm?.Href != null && Uri.TryCreate(modbusForm.Href, UriKind.Relative, out var address)) { var tag = new AssetTag() { Form = modbusForm, Name = propertyName, Address = address }; tagList.AddOrUpdate(propertyName, tag); return tag; } } // else if ... add other protocols here else { // create an asset tag and add to our list var genform = JsonConvert.DeserializeObject(form); if (genform?.Href != null && Uri.TryCreate(genform.Href, UriKind.Relative, out var address)) { var tag = new AssetTag() { Form = genform, Name = propertyName, Address = address }; tagList.AddOrUpdate(propertyName, tag); return tag; } } throw new FormatException("TD Format wrong or unsupported."); } private string GetOrAddAssetForThing(ThingDescription td) { ArgumentNullException.ThrowIfNull(td); ArgumentNullException.ThrowIfNull(td.Base); ArgumentNullException.ThrowIfNull(td.Name); if (!_assets.TryGetValue(td.Name, out var assetInterface)) { var parsedUri = new Uri(td.Base); // Try Create modbus asset if (ModbusTcpAsset.TryConnect(parsedUri, _logger, out assetInterface)) { _logger.CreatedModbusAsset(td.Name); } // else ... // default assetInterface ??= new SimulatedAsset(); _assets.Add(td.Name, assetInterface); } Debug.Assert(assetInterface != null); return td.Name; } private BaseDataVariableState CreateVariable(NodeState parent, string name, ExpandedNodeId type, ushort namespaceIndex, object? value) { var referenceType = ExpandedNodeId.ToNodeId(ReferenceTypeIds.HasWoTComponent, Server.NamespaceUris); var variable = new BaseDataVariableState(parent) { SymbolicName = name, ReferenceTypeId = referenceType, NodeId = new NodeId(name, namespaceIndex), BrowseName = new QualifiedName(name, namespaceIndex), DisplayName = new LocalizedText("en", name), WriteMask = AttributeWriteMask.None, UserWriteMask = AttributeWriteMask.None, AccessLevel = AccessLevels.CurrentRead, DataType = ExpandedNodeId.ToNodeId(type, Server.NamespaceUris), Value = value }; parent.AddReference(referenceType, false, variable.NodeId); variable.AddReference(referenceType, true, parent.NodeId); AddPredefinedNode(SystemContext, variable); return variable; } private BaseDataVariableState CreateAssetTagVariable(NodeState parent, string name, ExpandedNodeId type, ushort namespaceIndex, string assetId, bool writeable = false) { var referenceType = ExpandedNodeId.ToNodeId(ReferenceTypeIds.HasWoTComponent, Server.NamespaceUris); var variable = new BaseDataVariableState(parent) { SymbolicName = name, Handle = assetId, ReferenceTypeId = referenceType, NodeId = new NodeId(name, namespaceIndex), BrowseName = new QualifiedName(name, namespaceIndex), DisplayName = new LocalizedText("en", name), WriteMask = AttributeWriteMask.None, UserWriteMask = AttributeWriteMask.None, AccessLevel = AccessLevels.CurrentRead, DataType = ExpandedNodeId.ToNodeId(type, Server.NamespaceUris), OnSimpleReadValue = new NodeValueSimpleEventHandler(OnSimpleReadValue) }; if (writeable) { variable.AccessLevel = AccessLevels.CurrentReadOrWrite; variable.UserAccessLevel = AccessLevels.CurrentReadOrWrite; variable.UserWriteMask = AttributeWriteMask.ValueForVariableType; variable.WriteMask = AttributeWriteMask.ValueForVariableType; variable.OnSimpleWriteValue = new NodeValueSimpleEventHandler(OnSimpleWriteValue); } parent.AddReference(referenceType, false, variable.NodeId); variable.AddReference(referenceType, true, parent.NodeId); AddPredefinedNode(SystemContext, variable); return variable; } private bool TryGetBinding(NodeState node, [NotNullWhen(true)] out IAsset? assetInterface, [NotNullWhen(true)] out AssetTag? assetTag) { if (node.Handle is not string assetId || !_assets.TryGetValue(assetId, out assetInterface) || !_tags.TryGetValue(assetId, out var tag) || !tag.TryGetValue(node.SymbolicName, out assetTag)) { assetInterface = null; assetTag = null; return false; } return true; } private readonly WoTAssetConnectionManagementTypeState _assetManagement = new(null); private readonly Dictionary _uaVariables = []; private readonly Dictionary _assets = []; private readonly Dictionary> _tags = []; private readonly Dictionary _fileManagers = []; private readonly ILogger _logger; private readonly string _folder; private long _lastUsedId; } /// /// Source-generated logging definitions for AssetNodeManager /// internal static partial class AssetNodeManagerLogging { private const int EventClass = 0; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Error, Message = "Error")] public static partial void AssetNodeManagerError(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Error, Message = "Error parsing asset configuration file.")] public static partial void AssetConfigError(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Debug, Message = "Data change for {AssetTag}")] public static partial void DataChange(this ILogger logger, AssetTag assetTag); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Information, Message = "Successfully parsed WoT file for asset: {AssetId}")] public static partial void WoTParsed(this ILogger logger, string assetId); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Information, Message = "Loading nodeset from local file {File}")] public static partial void LoadingNodeset(this ILogger logger, string file); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Information, Message = "Adding node set from local nodeset file")] public static partial void AddingNodeset(this ILogger logger); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Information, Message = "Created modbus asset {AssetId}")] public static partial void CreatedModbusAsset(this ILogger logger, string assetId); [LoggerMessage(EventId = EventClass + 8, Level = LogLevel.Debug, Message = "Add asset for Property {Property}")] public static partial void AddAssetForProperty(this ILogger logger, Property property); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Asset/AssetServer.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Asset { using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Server; /// public class AssetServer : INodeManagerFactory { /// public StringCollection NamespacesUris { get { return [ Namespaces.AssetServer, Namespaces.WoT_Con ]; } } public AssetServer(ILogger logger) { _logger = logger; } /// public INodeManager Create(IServerInternal server, ApplicationConfiguration configuration) { return new AssetNodeManager(server, configuration, _logger); } private readonly ILogger _logger; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Asset/AssetTag.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ #nullable enable namespace Asset { using System; public abstract class AssetTag { /// /// Tag name /// public required string Name { get; init; } /// /// Tag address /// public required Uri Address { get; init; } } public class AssetTag : AssetTag { public required T Form { get; init; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Asset/FileManager.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ #nullable enable namespace Asset { using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Opc.Ua; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; public sealed class FileManager : IDisposable { public FileManager(AssetNodeManager nodeManager, WoTAssetFileTypeState file, string folder, ILogger logger) { _nodeManager = nodeManager; _folder = folder; _file = file; _logger = logger; _file.Size.Value = 0; if (_file.MaxByteStringLength != null) { _file.LastModifiedTime.Value = DateTime.MinValue; } _file.Writable.Value = false; _file.UserWritable.Value = false; _file.OpenCount.Value = 0; if (_file.MaxByteStringLength != null) { _file.MaxByteStringLength.Value = ushort.MaxValue; } _file.Open.OnCall = new OpenMethodStateMethodCallHandler(OnOpen); _file.Close.OnCall = new CloseMethodStateMethodCallHandler(OnClose); _file.Read.OnCall = new ReadMethodStateMethodCallHandler(OnRead); _file.Write.OnCall = new WriteMethodStateMethodCallHandler(OnWrite); _file.GetPosition.OnCall = new GetPositionMethodStateMethodCallHandler(OnGetPosition); _file.SetPosition.OnCall = new SetPositionMethodStateMethodCallHandler(OnSetPosition); _file.CloseAndUpdate.OnCall = new CloseAndUpdateMethodStateMethodCallHandler(OnCloseAndUpdate); } public void Dispose() { lock (_handles) { foreach (var handle in _handles.Values) { handle.Dispose(); } _handles.Clear(); } } private Handle Find(ISystemContext _context, uint fileHandle) { lock (_handles) { if (!_handles.TryGetValue(fileHandle, out var handle)) { throw new ServiceResultException( StatusCodes.BadInvalidArgument); } if (handle.SessionId != _context.SessionId) { throw new ServiceResultException( StatusCodes.BadUserAccessDenied); } return handle; } } private ServiceResult OnOpen(ISystemContext _context, MethodState _method, NodeId _objectId, byte mode, ref uint fileHandle) { if (mode != 1 && mode != 6) { return StatusCodes.BadNotSupported; } lock (_handles) { try { if (_handles.Count >= 10) { return StatusCodes.BadTooManyOperations; } if (_writing && mode != 1) { return ServiceResult.Create(StatusCodes.BadInvalidState, "Writing already"); } Handle handle; if (mode == 6) { // Writing handle = new Handle(_context.SessionId); _writing = true; } else if (mode == 1) { // Reading var path = Path.Combine(_folder, _file.Parent.DisplayName.Text + ".jsonld"); handle = new Handle(_context.SessionId, File.Open(path, FileMode.Open)); } else { return ServiceResult.Create(StatusCodes.BadNotSupported, "Unsupported mode"); } fileHandle = ++_nextHandle; _handles.Add(fileHandle, handle); _file.OpenCount.Value = (ushort)_handles.Count; } catch (Exception ex) { return ServiceResult.Create(ex, StatusCodes.BadUserAccessDenied, ex.Message); } } return ServiceResult.Good; } private ServiceResult OnGetPosition(ISystemContext _context, MethodState _method, NodeId _objectId, uint fileHandle, ref ulong position) { var handle = Find(_context, fileHandle); position = (ulong)handle.Stream.Position; return ServiceResult.Good; } private ServiceResult OnSetPosition(ISystemContext _context, MethodState _method, NodeId _objectId, uint fileHandle, ulong position) { var handle = Find(_context, fileHandle); handle.Stream.Seek((long)position, SeekOrigin.Begin); return ServiceResult.Good; } private ServiceResult OnRead(ISystemContext _context, MethodState _method, NodeId _objectId, uint fileHandle, int length, ref byte[] data) { lock (_handles) { var handle = Find(_context, fileHandle); if (handle.Writing) { return StatusCodes.BadInvalidState; } if (data?.Length > 0) { var buffer = new byte[data.Length]; handle.Stream.ReadExactly(data); data = buffer; } else { data = []; } } return ServiceResult.Good; } private ServiceResult OnWrite(ISystemContext _context, MethodState _method, NodeId _objectId, uint fileHandle, byte[] data) { lock (_handles) { var handle = Find(_context, fileHandle); if (!handle.Writing) { return ServiceResult.Create(StatusCodes.BadInvalidState, "Not writable"); } if (data?.Length > 0) { handle.Stream.Write(data, 0, data.Length); } } return ServiceResult.Good; } private ServiceResult OnClose(ISystemContext _context, MethodState _method, NodeId _objectId, uint fileHandle) { lock (_handles) { if (!_handles.TryGetValue(fileHandle, out var handle)) { return ServiceResult.Create(StatusCodes.BadInvalidArgument, "Bad file handle"); } if (handle.SessionId != _context.SessionId) { return ServiceResult.Create(StatusCodes.BadUserAccessDenied, "Bad sessionid"); } _writing = false; _handles.Remove(fileHandle); handle.Dispose(); _file.OpenCount.Value = (ushort)_handles.Count; return ServiceResult.Good; } } private ServiceResult OnCloseAndUpdate(ISystemContext _context, MethodState _method, NodeId _objectId, uint fileHandle) { if (!TryGetHandle(_context, fileHandle, out var handle, out var sr)) { return sr; } try { // Reset handle.Stream.Position = 0; var jsonSerializer = JsonSerializer.CreateDefault(); using var text = new StreamReader(handle.Stream); using var reader = new JsonTextReader(text); var td = jsonSerializer.Deserialize(reader); if (td?.Context == null) { throw new FormatException("Missing context"); } _nodeManager.AddNodesForThingDescription(_file.Parent, td); File.WriteAllText(Path.Combine(_folder, _file.Parent.DisplayName.Text + ".jsonld"), JsonConvert.SerializeObject(td)); return ServiceResult.Good; } catch (Exception ex) { return new ServiceResult(StatusCodes.BadDecodingError, ex); } finally { handle.Dispose(); } bool TryGetHandle(ISystemContext _context, uint fileHandle, [NotNullWhen(true)] out Handle? handle, [NotNullWhen(false)] out ServiceResult? sr) { lock (_handles) { if (!_handles.TryGetValue(fileHandle, out handle)) { sr = StatusCodes.BadInvalidArgument; return false; } if (handle.SessionId != _context.SessionId) { sr = StatusCodes.BadUserAccessDenied; return false; } _writing = false; _handles.Remove(fileHandle); _file.OpenCount.Value = (ushort)_handles.Count; sr = null; return true; } } } public void Delete() { try { File.Delete(Path.Combine(_folder, _file.Parent.DisplayName.Text + ".jsonld")); } catch (Exception ex) { _logger.FileManagerError(ex); } } private sealed record class Handle : IDisposable { public NodeId SessionId { get; } public Stream Stream { get; } public bool Writing { get; } public Handle(NodeId sessionId) { SessionId = sessionId; Writing = true; Stream = new MemoryStream(); } public Handle(NodeId sessionId, Stream stream) { SessionId = sessionId; Stream = stream; } public void Dispose() { Stream.Dispose(); } } private readonly AssetNodeManager _nodeManager; private readonly WoTAssetFileTypeState _file; private readonly ILogger _logger; private readonly string _folder; private readonly Dictionary _handles = []; private bool _writing; private uint _nextHandle = 1u; } /// /// Source-generated logging definitions for FileManager /// internal static partial class FileManagerLogging { private const int EventClass = 10; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Error, Message = "Error")] public static partial void FileManagerError(this ILogger logger, Exception ex); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Asset/IAsset.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ #nullable enable namespace Asset { using Microsoft.Extensions.Logging; using Opc.Ua; using System; using System.Diagnostics.CodeAnalysis; public delegate void OnAssetTagChange(AssetTag tag, object? value, StatusCode statusCode, DateTime timestamp); /// /// Asset interface /// public interface IAsset : IDisposable { /// /// Read from the asset tag /// /// /// /// ServiceResult Read(AssetTag tag, ref object? value); /// /// Write to the asset tag /// /// /// /// ServiceResult Write(AssetTag tag, ref object value); /// /// Observe /// /// /// /// /// /// void Observe(AssetTag tag, uint id, OnAssetTagChange callback); /// /// Unobserve /// /// /// /// /// void Unobserve(AssetTag tag, uint id); } /// /// Creates assets /// public interface IAssetFactory { /// /// Try connect /// /// /// /// /// public static abstract bool TryConnect(Uri tdBase, ILogger logger, [NotNullWhen(true)] out IAsset? asset); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Asset/ModbusBinding.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ #nullable enable namespace Asset { using Newtonsoft.Json; using System.Runtime.Serialization; public sealed class ModbusForm : Form { [JsonProperty("modv:type")] public ModbusType PayloadType { get; set; } [JsonProperty("modv:entity")] public ModbusEntity? Entity { get; set; } [JsonProperty("modv:function")] public ModbusFunction? Function { get; set; } [JsonProperty("modv:timeout")] public int? Timeout { get; set; } [JsonProperty("modv:mostSignificantByte")] public bool? MostSignificantByte { get; set; } [JsonProperty("modv:mostSignificantWord")] public bool? MostSignificantWord { get; set; } [JsonProperty("modv:zeroBasedAddressing")] public bool? ZeroBasedAddressing { get; set; } [JsonProperty("modv:pollingTime")] public long ModbusPollingTime { get; set; } } [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public enum ModbusEntity { [EnumMember(Value = "Coil")] Coil, [EnumMember(Value = "DiscreteInput")] DiscreteInput, [EnumMember(Value = "HoldingRegister")] HoldingRegister, [EnumMember(Value = "InputRegister")] InputRegister, } [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public enum ModbusFunction { [EnumMember(Value = "readCoil")] ReadCoil = 1, [EnumMember(Value = "readDiscreteInput")] ReadDiscreteInput = 2, [EnumMember(Value = "readHoldingRegisters")] ReadHoldingRegisters = 3, [EnumMember(Value = "readInputRegisters")] ReadInputRegisters = 4, [EnumMember(Value = "writeSingleCoil")] WriteSingleCoil = 5, [EnumMember(Value = "writeSingleHoldingRegister")] WriteSingleHoldingRegister = 6, [EnumMember(Value = "writeMultipleCoils")] WriteMultipleCoils = 15, [EnumMember(Value = "writeMultipleHoldingRegisters")] WriteMultipleHoldingRegisters = 16, // Not needed // [EnumMember(Value = "readWriteMultipleRegisters")] // ReadWriteMultipleRegisters = 23, // [EnumMember(Value = "readFifoQueue")] // ReadFifoQueue = 24, // [EnumMember(Value = "readDeviceIdentification")] // ReadDeviceIdentification = 43 } [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public enum ModbusType { [EnumMember(Value = "xsd:integer")] Xsdinteger, [EnumMember(Value = "xsd:boolean")] Xsdboolean, [EnumMember(Value = "xsd:string")] Xsdstring, [EnumMember(Value = "xsd:float")] Xsdfloat, [EnumMember(Value = "xsd:decimal")] Xsddecimal, [EnumMember(Value = "xsd:byte")] Xsdbyte, [EnumMember(Value = "xsd:short")] Xsdshort, [EnumMember(Value = "xsd:int")] Xsdint, [EnumMember(Value = "xsd:long")] Xsdlong, [EnumMember(Value = "xsd:unsignedByte")] XsdunsignedByte, [EnumMember(Value = "xsd:unsignedShort")] XsdunsignedShort, [EnumMember(Value = "xsd:unsignedInt")] XsdunsignedInt, [EnumMember(Value = "xsd:unsignedLong")] XsdunsignedLong, [EnumMember(Value = "xsd:double")] Xsddouble, [EnumMember(Value = "xsd:hexBinary")] XsdhexBinary, } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Asset/ModbusFormExtension.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ #nullable enable namespace Asset { using Opc.Ua; using System; using System.Text; public static class ModbusFormExtension { /// /// Get datatype id /// /// /// /// public static NodeId GetDataTypeId(this ModbusForm form) { switch (form.PayloadType) { case ModbusType.Xsdfloat: return DataTypeIds.Float; case ModbusType.Xsdinteger: return DataTypeIds.Integer; case ModbusType.Xsdboolean: return DataTypeIds.Boolean; case ModbusType.Xsdstring: return DataTypeIds.String; case ModbusType.Xsddecimal: return DataTypeIds.Decimal; case ModbusType.Xsdbyte: return DataTypeIds.SByte; case ModbusType.Xsdshort: return DataTypeIds.Int16; case ModbusType.Xsdint: return DataTypeIds.Int32; case ModbusType.Xsdlong: return DataTypeIds.Int64; case ModbusType.XsdunsignedByte: return DataTypeIds.Byte; case ModbusType.XsdunsignedShort: return DataTypeIds.UInt16; case ModbusType.XsdunsignedInt: return DataTypeIds.UInt32; case ModbusType.XsdunsignedLong: return DataTypeIds.UInt64; case ModbusType.Xsddouble: return DataTypeIds.Double; case ModbusType.XsdhexBinary: return DataTypeIds.ByteString; default: throw ServiceResultException.Create(StatusCodes.BadNotReadable, "Invalid data type"); } } /// /// Convert value to buffer (little endian) to write /// /// /// /// /// public static ReadOnlyMemory ToBuffer(this ModbusForm form, object value) { switch (form.PayloadType) { case ModbusType.Xsdfloat: return BitConverter.GetBytes((float)value); case ModbusType.Xsdinteger: return BitConverter.GetBytes((int)value); case ModbusType.Xsdboolean: return BitConverter.GetBytes((bool)value); case ModbusType.Xsdstring: return Encoding.UTF8.GetBytes((string)value); case ModbusType.Xsddecimal: return GetBytes((decimal)value); case ModbusType.Xsdbyte: return new[] { (byte)(sbyte)value }; case ModbusType.Xsdshort: return BitConverter.GetBytes((short)value); case ModbusType.Xsdint: return BitConverter.GetBytes((int)value); case ModbusType.Xsdlong: return BitConverter.GetBytes((long)value); case ModbusType.XsdunsignedByte: return new[] { (byte)value }; case ModbusType.XsdunsignedShort: return BitConverter.GetBytes((ushort)value); case ModbusType.XsdunsignedInt: return BitConverter.GetBytes((uint)value); case ModbusType.XsdunsignedLong: return BitConverter.GetBytes((ulong)value); case ModbusType.Xsddouble: return BitConverter.GetBytes((double)value); case ModbusType.XsdhexBinary: return (byte[])value; default: throw ServiceResultException.Create(StatusCodes.BadNotReadable, "Invalid data type"); } } /// /// Convert (little endian) value to object based on modbus type /// /// /// /// /// public static ServiceResult ToObject(this ModbusForm form, ReadOnlyMemory buffer, ref object? value) { switch (form.PayloadType) { case ModbusType.Xsdfloat: value = BitConverter.ToSingle(buffer.Span); break; case ModbusType.Xsdinteger: value = BitConverter.ToInt32(buffer.Span); break; case ModbusType.Xsdboolean: value = BitConverter.ToBoolean(buffer.Span); break; case ModbusType.Xsdstring: value = Encoding.UTF8.GetString(buffer.Span); break; case ModbusType.Xsddecimal: value = ToDecimal(buffer.Span); break; case ModbusType.Xsdbyte: value = (sbyte)buffer.Span[0]; break; case ModbusType.Xsdshort: value = BitConverter.ToInt16(buffer.Span); break; case ModbusType.Xsdint: value = BitConverter.ToInt32(buffer.Span); break; case ModbusType.Xsdlong: value = BitConverter.ToInt64(buffer.Span); break; case ModbusType.XsdunsignedByte: value = buffer.Span[0]; break; case ModbusType.XsdunsignedShort: value = BitConverter.ToUInt16(buffer.Span); break; case ModbusType.XsdunsignedInt: value = BitConverter.ToUInt32(buffer.Span); break; case ModbusType.XsdunsignedLong: value = BitConverter.ToUInt64(buffer.Span); break; case ModbusType.Xsddouble: value = BitConverter.ToDouble(buffer.Span); break; case ModbusType.XsdhexBinary: value = buffer.ToArray(); break; default: return ServiceResult.Create(StatusCodes.BadNotReadable, "Invalid data type"); } return ServiceResult.Good; } private static decimal ToDecimal(ReadOnlySpan bytes) { var bits = new int[4]; bits[0] = bytes[0] | (bytes[1] << 8) | (bytes[2] << 0x10) | (bytes[3] << 0x18); //lo bits[1] = bytes[4] | (bytes[5] << 8) | (bytes[6] << 0x10) | (bytes[7] << 0x18); //mid bits[2] = bytes[8] | (bytes[9] << 8) | (bytes[10] << 0x10) | (bytes[11] << 0x18); //hi bits[3] = bytes[12] | (bytes[13] << 8) | (bytes[14] << 0x10) | (bytes[15] << 0x18); //flags return new decimal(bits); } private static byte[] GetBytes(decimal d) { var bytes = new byte[16]; var bits = decimal.GetBits(d); var lo = bits[0]; var mid = bits[1]; var hi = bits[2]; var flags = bits[3]; bytes[0] = (byte)lo; bytes[1] = (byte)(lo >> 8); bytes[2] = (byte)(lo >> 0x10); bytes[3] = (byte)(lo >> 0x18); bytes[4] = (byte)mid; bytes[5] = (byte)(mid >> 8); bytes[6] = (byte)(mid >> 0x10); bytes[7] = (byte)(mid >> 0x18); bytes[8] = (byte)hi; bytes[9] = (byte)(hi >> 8); bytes[10] = (byte)(hi >> 0x10); bytes[11] = (byte)(hi >> 0x18); bytes[12] = (byte)flags; bytes[13] = (byte)(flags >> 8); bytes[14] = (byte)(flags >> 0x10); bytes[15] = (byte)(flags >> 0x18); return bytes; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Asset/ModbusProtocol.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ #nullable enable namespace Asset { using Opc.Ua; using System; using System.Buffers; using System.Buffers.Binary; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; internal static class ModbusProtocol { /// /// Encapsulate MODBUS Application Protocol header /// /// /// /// internal record struct Mbap(ushort TransactionId, byte UnitId, ushort ProtocolId = 0) { public const int Length = 7; } /// /// Write a request to read modbus data /// /// /// /// /// /// /// public static void EncodeReadRequest(this IBufferWriter writer, ModbusFunction function, Mbap mbap, ushort startingAddress, ushort quantity) { switch (function) { case ModbusFunction.ReadCoil: writer.EncodeReadCoilsRequest(mbap, startingAddress, quantity); break; case ModbusFunction.ReadDiscreteInput: writer.EncodeReadDiscreteInputRequest(mbap, startingAddress, quantity); break; case ModbusFunction.ReadHoldingRegisters: writer.EncodeReadHoldingRegistersRequest(mbap, startingAddress, quantity); break; case ModbusFunction.ReadInputRegisters: writer.EncodeReadInputRegistersRequest(mbap, startingAddress, quantity); break; default: throw new NotSupportedException("Not a read request"); } } /// /// Write a request to write modbus data /// /// /// /// /// /// /// /// public static void WriteWriteRequest(this IBufferWriter writer, ModbusFunction function, Mbap mbap, ushort startingAddress, ushort quantity, ReadOnlySpan registersOrCoils) { switch (function) { case ModbusFunction.WriteSingleCoil: writer.EncodeWriteSingleCoilRequest(mbap, startingAddress, registersOrCoils); break; case ModbusFunction.WriteMultipleCoils: writer.EncodeWriteMultipleCoilsRequest(mbap, startingAddress, quantity, registersOrCoils); break; case ModbusFunction.WriteSingleHoldingRegister: writer.EncodeWriteSingleRegisterRequest(mbap, startingAddress, registersOrCoils); break; case ModbusFunction.WriteMultipleHoldingRegisters: writer.EncodeWriteMultipleRegistersRequest(mbap, startingAddress, quantity, registersOrCoils); break; default: throw new NotSupportedException("Not a write request"); } } /// /// Try to read the read response /// /// /// /// /// /// /// public static bool TryReadReadResponse(this IBufferWriter writer, ModbusFunction function, ref ReadOnlySequence response, ref ServiceResult error) { switch (function) { case ModbusFunction.ReadCoil: return writer.TryReadReadCoilsResponse(ref response, ref error); case ModbusFunction.ReadDiscreteInput: return writer.TryReadReadDiscreteInputResponse(ref response, ref error); case ModbusFunction.ReadHoldingRegisters: return writer.TryReadReadReadHoldingRegistersResponse(ref response, ref error); case ModbusFunction.ReadInputRegisters: return writer.TryReadReadInputRegistersResponse(ref response, ref error); default: throw new NotSupportedException("Not a read request"); } } /// /// Try to read the write response /// /// /// /// /// /// /// /// /// /// public static bool TryReadWriteResponse(this IBufferWriter writer, ModbusFunction function, ref ReadOnlySequence response, ushort outputAddress, ushort quantity, ReadOnlySpan registersOrCoils, ref ServiceResult error) { switch (function) { case ModbusFunction.WriteSingleCoil: return writer.TryReadWriteSingleCoilResponse(ref response, outputAddress, registersOrCoils, ref error); case ModbusFunction.WriteMultipleCoils: return writer.TryReadWriteMultipleCoilsResponse(ref response, outputAddress, quantity, ref error); case ModbusFunction.WriteSingleHoldingRegister: return writer.TryReadWriteSingleRegisterResponse(ref response, outputAddress, registersOrCoils, ref error); case ModbusFunction.WriteMultipleHoldingRegisters: return writer.TryReadWriteMultipleRegistersResponse(ref response, outputAddress, quantity, ref error); default: throw new NotSupportedException("Not a read request"); } } /// /// Encode read coils request /// /// /// /// /// public static void EncodeReadCoilsRequest(this IBufferWriter writer, Mbap mbap, ushort startingAddress, ushort quantityOfCoils) { ArgumentOutOfRangeException.ThrowIfZero(quantityOfCoils); ArgumentOutOfRangeException.ThrowIfGreaterThan(quantityOfCoils, 2000); EncodeSimpleRequest(ModbusFunction.ReadCoil, mbap, startingAddress, quantityOfCoils, writer); } /// /// Try read coils response /// /// /// /// /// public static bool TryReadReadCoilsResponse(this IBufferWriter output, ref ReadOnlySequence response, ref ServiceResult error) { return TryReadBitResponse(ModbusFunction.ReadCoil, ref response, output, ref error); } /// /// Encode writing a single coil request /// /// /// /// /// public static void EncodeWriteSingleCoilRequest(this IBufferWriter writer, Mbap mbap, ushort outputAddress, ReadOnlySpan outputValue) { ArgumentOutOfRangeException.ThrowIfLessThan(outputValue.Length, 1); var onOff = outputValue[0] != 0 ? (ushort)0xFF00 : (ushort)0x0; EncodeSimpleRequest(ModbusFunction.WriteSingleCoil, mbap, outputAddress, onOff, writer); } public static bool TryReadWriteSingleCoilResponse(this IBufferWriter writer, ref ReadOnlySequence reader, ushort outputAddress, ReadOnlySpan outputValue, ref ServiceResult error) { Debug.Assert(writer != null); ArgumentOutOfRangeException.ThrowIfLessThan(outputValue.Length, 1); var onOff = outputValue[0] != 0 ? (ushort)0xFF00 : (ushort)0x0; return TryReadEchoResponse(ModbusFunction.WriteSingleCoil, ref reader, outputAddress, onOff, ref error); } public static void EncodeWriteMultipleCoilsRequest(this IBufferWriter writer, Mbap mbap, ushort outputAddress, ushort quantityOfOutputs, ReadOnlySpan coilStates) { ArgumentOutOfRangeException.ThrowIfZero(quantityOfOutputs); ArgumentOutOfRangeException.ThrowIfGreaterThan(quantityOfOutputs, 0x7b0); ArgumentOutOfRangeException.ThrowIfGreaterThan(coilStates.Length, byte.MaxValue); ArgumentOutOfRangeException.ThrowIfGreaterThan(quantityOfOutputs, coilStates.Length * 8); EncodeWriteBitRequest(ModbusFunction.WriteMultipleCoils, mbap, outputAddress, quantityOfOutputs, coilStates, writer); } public static bool TryReadWriteMultipleCoilsResponse(this IBufferWriter writer, ref ReadOnlySequence response, ushort outputAddress, ushort quantityOfOutputs, ref ServiceResult error) { Debug.Assert(writer != null); return TryReadEchoResponse(ModbusFunction.WriteMultipleCoils, ref response, outputAddress, quantityOfOutputs, ref error); } /// /// Encode write single register request /// /// /// /// /// public static void EncodeWriteSingleRegisterRequest(this IBufferWriter writer, Mbap mbap, ushort outputAddress, ReadOnlySpan outputValue) { ArgumentOutOfRangeException.ThrowIfLessThan(outputValue.Length, 2); var value = BitConverter.ToUInt16(outputValue); EncodeSimpleRequest(ModbusFunction.WriteSingleHoldingRegister, mbap, outputAddress, value, writer); } /// /// Try read write single register response /// /// /// /// /// /// /// public static bool TryReadWriteSingleRegisterResponse(this IBufferWriter writer, ref ReadOnlySequence response, ushort outputAddress, ReadOnlySpan outputValue, ref ServiceResult error) { Debug.Assert(writer != null); var value = BitConverter.ToUInt16(outputValue); return TryReadEchoResponse(ModbusFunction.WriteSingleHoldingRegister, ref response, outputAddress, value, ref error); } /// /// Encode write multi register request /// /// /// /// /// /// public static void EncodeWriteMultipleRegistersRequest(this IBufferWriter writer, Mbap mbap, ushort outputAddress, ushort quantityOfRegisters, ReadOnlySpan registers) { ArgumentOutOfRangeException.ThrowIfZero(quantityOfRegisters); ArgumentOutOfRangeException.ThrowIfGreaterThan(quantityOfRegisters, 123); ArgumentOutOfRangeException.ThrowIfGreaterThan(quantityOfRegisters, registers.Length / 2); EncodeWriteWordRequest(ModbusFunction.WriteMultipleHoldingRegisters, mbap, outputAddress, quantityOfRegisters, registers, writer); } /// /// Try read multi register response /// /// /// /// /// /// /// public static bool TryReadWriteMultipleRegistersResponse(this IBufferWriter writer, ref ReadOnlySequence response, ushort outputAddress, ushort quantityOfRegisters, ref ServiceResult error) { Debug.Assert(writer != null); return TryReadEchoResponse(ModbusFunction.WriteMultipleHoldingRegisters, ref response, outputAddress, quantityOfRegisters, ref error); } /// /// Encode read discrete input request /// /// /// /// /// public static void EncodeReadDiscreteInputRequest(this IBufferWriter writer, Mbap mbap, ushort startingAddress, ushort quantityOfInputs) { ArgumentOutOfRangeException.ThrowIfZero(quantityOfInputs); ArgumentOutOfRangeException.ThrowIfGreaterThan(quantityOfInputs, 2000); EncodeSimpleRequest(ModbusFunction.ReadDiscreteInput, mbap, startingAddress, quantityOfInputs, writer); } /// /// Try read response from discrete input /// /// /// /// /// public static bool TryReadReadDiscreteInputResponse(this IBufferWriter inputStatus, ref ReadOnlySequence response, ref ServiceResult error) { return TryReadBitResponse(ModbusFunction.ReadDiscreteInput, ref response, inputStatus, ref error); } /// /// Encode read holding registers request /// /// /// /// /// public static void EncodeReadHoldingRegistersRequest(this IBufferWriter writer, Mbap mbap, ushort startingAddress, ushort quantityOfRegisters) { ArgumentOutOfRangeException.ThrowIfZero(quantityOfRegisters); ArgumentOutOfRangeException.ThrowIfGreaterThan(quantityOfRegisters, 125); EncodeSimpleRequest(ModbusFunction.ReadHoldingRegisters, mbap, startingAddress, quantityOfRegisters, writer); } /// /// Try read holding registers response /// /// /// /// /// public static bool TryReadReadReadHoldingRegistersResponse(this IBufferWriter registerValues, ref ReadOnlySequence response, ref ServiceResult error) { return TryReadRegisterResponse(ModbusFunction.ReadHoldingRegisters, ref response, registerValues, ref error); } /// /// Encode read input registers request /// /// /// /// /// public static void EncodeReadInputRegistersRequest(this IBufferWriter writer, Mbap mbap, ushort startingAddress, ushort quantityOfInputRegisters) { ArgumentOutOfRangeException.ThrowIfZero(quantityOfInputRegisters); ArgumentOutOfRangeException.ThrowIfGreaterThan(quantityOfInputRegisters, 0x7D); EncodeSimpleRequest(ModbusFunction.ReadInputRegisters, mbap, startingAddress, quantityOfInputRegisters, writer); } /// /// Try read input registers response /// /// /// /// /// public static bool TryReadReadInputRegistersResponse(this IBufferWriter registerValues, ref ReadOnlySequence response, ref ServiceResult error) { return TryReadRegisterResponse(ModbusFunction.ReadInputRegisters, ref response, registerValues, ref error); } /// /// Write a modbus request to read a quantity of coils or registers /// /// /// /// /// /// private static void EncodeSimpleRequest(ModbusFunction function, Mbap mbap, ushort startingAddress, ushort quantityOrOutputValue, IBufferWriter writer) { const int length = Mbap.Length + 5; var adu = writer.GetSpan(length); var request = adu.Slice(Mbap.Length, 5); WriteMbap(mbap, request.Length, adu); WriteRequestHeader(function, startingAddress, quantityOrOutputValue, request); writer.Advance(length); } /// /// Write a modbus request with a buffer and buffer count /// /// /// /// /// /// /// private static void EncodeWriteBitRequest(ModbusFunction function, Mbap mbap, ushort startingAddress, ushort quantity, ReadOnlySpan bitBuffer, IBufferWriter writer) { var length = Mbap.Length + 6 + bitBuffer.Length; var adu = writer.GetSpan(length); var request = adu[Mbap.Length..length]; WriteRequestHeader(function, startingAddress, quantity, request); request[5] = (byte)bitBuffer.Length; bitBuffer.CopyTo(request[6..]); WriteMbap(mbap, request.Length, adu); writer.Advance(length); } /// /// Write a modbus request with a buffer and buffer count /// /// /// /// /// /// /// private static void EncodeWriteWordRequest(ModbusFunction function, Mbap mbap, ushort startingAddress, ushort quantity, ReadOnlySpan words, IBufferWriter writer) { var length = Mbap.Length + 6 + words.Length; var adu = writer.GetSpan(length); var request = adu[Mbap.Length..length]; WriteRequestHeader(function, startingAddress, quantity, request); request[5] = (byte)words.Length; CopyWords(words, request[6..]); WriteMbap(mbap, request.Length, adu); writer.Advance(length); } /// /// Read and validate echo response /// /// /// /// /// /// /// private static bool TryReadEchoResponse(ModbusFunction function, ref ReadOnlySequence response, ushort outputAddress, ushort outputValue, ref ServiceResult error) { var reader = new SequenceReader(response); if (!TryReadFunctionOrError(ref reader, function, ref error) || !reader.TryReadBigEndian(out short address) || !reader.TryReadBigEndian(out short value)) { return false; } if (outputAddress != address || value != outputValue) { // Should not happen - reconnect throw new ServiceResultException( "Unexpected address or value returned in echo response"); } return true; } /// /// Read coils or input states from response /// /// /// /// /// /// private static bool TryReadBitResponse(ModbusFunction function, ref ReadOnlySequence response, IBufferWriter inputStatus, ref ServiceResult error) { var reader = new SequenceReader(response); if (!TryReadFunctionOrError(ref reader, function, ref error) || !reader.TryReadBigEndian(out short byteCount)) { return false; } if (reader.UnreadSpan.Length < byteCount) { return false; } inputStatus.Write(reader.UnreadSpan[byteCount..]); reader.Advance(byteCount); return true; } /// /// Read register values from response /// /// /// /// /// /// private static bool TryReadRegisterResponse(ModbusFunction function, ref ReadOnlySequence response, IBufferWriter registerValues, ref ServiceResult error) { var reader = new SequenceReader(response); return TryReadFunctionOrError(ref reader, function, ref error) && reader.TryReadBigEndian(out short byteCount) && TryCopyWords(ref reader, registerValues, byteCount); } /// /// Copy from reader to span /// /// /// /// /// private static bool TryCopyWords(ref SequenceReader reader, IBufferWriter registerValues, short byteCount) { var span = registerValues.GetSpan(byteCount); Span tmp = stackalloc byte[2]; for (var i = 0; i < byteCount; i += 2) { if (!reader.TryRead(out tmp[0]) || !reader.TryRead(out tmp[1])) { return false; } if (BitConverter.IsLittleEndian) { // Convert from big endian by swapping span[i + 1] = tmp[0]; span[i] = tmp[1]; } else { span[i] = tmp[0]; span[1 + 1] = tmp[1]; } } registerValues.Advance(byteCount); return true; } /// /// Copy words from span to span /// /// /// private static void CopyWords(ReadOnlySpan reader, Span span) { Debug.Assert(span.Length == reader.Length); if (BitConverter.IsLittleEndian) { // Convert from big endian by swapping for (var i = 0; i < reader.Length; i += 2) { span[i + 1] = reader[i]; span[i] = reader[i + 1]; } } else { reader.CopyTo(span); } } private static void WriteRequestHeader(ModbusFunction function, ushort startingAddress, ushort quantity, Span buffer) { buffer[0] = (byte)function; BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(1, 2), startingAddress); BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(3, 2), quantity); } private static void WriteMbap(Mbap mbap, int length, Span buffer) { Debug.Assert(buffer.Length >= Mbap.Length); BinaryPrimitives.WriteUInt16BigEndian(buffer[..2], mbap.TransactionId); BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(2, 2), mbap.ProtocolId); // length is the number of bytes following this field which includes unitid BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(4, 2), (ushort)(length + 1)); buffer[6] = mbap.UnitId; } private static bool TryReadFunctionOrError(ref SequenceReader reader, ModbusFunction function, ref ServiceResult error) { if (reader.TryRead(out var functionCode)) { if (functionCode == (byte)function) { return true; } else if ((functionCode & ~0x80) == (byte)function) { if (reader.TryRead(out var errorCode)) { error = ToServiceResult(errorCode); return true; } } else { ThrowBadResponse(); } } return false; [DoesNotReturn] static void ThrowBadResponse() => throw new ServiceResultException("Bad response"); static ServiceResult ToServiceResult(byte errorCode) { switch (errorCode) { case 1: return new ServiceResult(StatusCodes.Bad, "Illegal function"); case 2: return new ServiceResult(StatusCodes.Bad, "Illegal data address"); case 3: return new ServiceResult(StatusCodes.Bad, "Illegal data value"); case 4: return new ServiceResult(StatusCodes.Bad, "Server failure"); case 5: return new ServiceResult(StatusCodes.Bad, "Acknowledge"); case 6: return new ServiceResult(StatusCodes.Bad, "Server busy"); case 7: return new ServiceResult(StatusCodes.Bad, "Negative acknowledge"); case 8: return new ServiceResult(StatusCodes.Bad, "Memory parity error"); case 10: return new ServiceResult(StatusCodes.Bad, "Gateway path unavailable"); case 11: return new ServiceResult(StatusCodes.Bad, "Target unit failed to respond"); default: return new ServiceResult(StatusCodes.Bad, "Unknown error"); } } } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Asset/ModbusTcpAsset.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ #nullable enable namespace Asset { using Microsoft.Extensions.Logging; using Opc.Ua; using System; using System.Buffers; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO.Pipelines; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; /// /// See https://w3c.github.io/wot-binding-templates/bindings/protocols/modbus/ /// internal sealed class ModbusTcpAsset : IAsset, IAssetFactory { private ModbusTcpAsset(Uri address, ILogger logger) { _logger = logger; // check if we can reach the Modbus asset _unitId = byte.Parse(address.PathAndQuery, CultureInfo.InvariantCulture); _address = address; Reconnect(); } public static bool TryConnect(Uri tdBase, ILogger logger, [NotNullWhen(true)] out IAsset? asset) { // Create modbus asset if (tdBase.Scheme != "modbus+tcp") { asset = default; return false; } asset = new ModbusTcpAsset(tdBase, logger); return true; } public void Dispose() { try { _tcpClient?.Dispose(); _tcpClient = null; } finally { _lock.Dispose(); } } public ServiceResult Read(AssetTag tag, ref object? value) { if (tag is not AssetTag modbusTag) { return ServiceResult.Create(StatusCodes.BadInvalidArgument, "Not a modbus tag"); } // {address}?quantity={?quantity} if (!ushort.TryParse(modbusTag.Address.LocalPath, CultureInfo.InvariantCulture, out var registerAddress)) { return ServiceResult.Create(StatusCodes.BadInvalidArgument, "Not a register address"); } var form = modbusTag.Form; var function = form.Entity switch { ModbusEntity.Coil => ModbusFunction.ReadCoil, ModbusEntity.DiscreteInput => ModbusFunction.ReadDiscreteInput, ModbusEntity.HoldingRegister => ModbusFunction.ReadHoldingRegisters, ModbusEntity.InputRegister => ModbusFunction.ReadInputRegisters, _ => form.Function ?? ModbusFunction.ReadHoldingRegisters }; // Read the amount of registers/coils referenced in this URL var queryParts = modbusTag.Address.Query.Split(['?', '&', '='], StringSplitOptions.RemoveEmptyEntries); ushort quantity = kDefaultQuantity; if (queryParts.Length > 0) { if (queryParts.Length != 2 || queryParts[0] != "quantity" || !ushort.TryParse(queryParts[1], CultureInfo.InvariantCulture, out quantity)) { return ServiceResult.Create(StatusCodes.BadInvalidArgument, "Invalid quantity in query."); } } var timeout = form.Timeout ?? kDefaultTimeout; try { var tagBytes = ReadAsync(function, registerAddress, quantity, timeout) .GetAwaiter().GetResult(); return form.ToObject(tagBytes, ref value); } catch (ServiceResultException sre) { return sre.Result; } } public ServiceResult Write(AssetTag tag, ref object value) { if (tag is not AssetTag modbusTag) { return ServiceResult.Create(StatusCodes.BadInvalidArgument, "Not a modbus tag"); } // {address}?quantity={?quantity} if (!ushort.TryParse(modbusTag.Address.LocalPath, CultureInfo.InvariantCulture, out var registerAddress)) { return ServiceResult.Create(StatusCodes.BadInvalidArgument, "Not a register address"); } var form = modbusTag.Form; // Read the amount of registers/coils referenced in this URL var queryParts = modbusTag.Address.Query.Split(['?', '&', '='], StringSplitOptions.RemoveEmptyEntries); ushort quantity = kDefaultQuantity; if (queryParts.Length > 0) { if (queryParts.Length != 2 || queryParts[0] != "quantity" || !ushort.TryParse(queryParts[1], CultureInfo.InvariantCulture, out quantity)) { return ServiceResult.Create(StatusCodes.BadInvalidArgument, "Invalid quantity in query."); } } var function = form.Entity switch { ModbusEntity.DiscreteInput or ModbusEntity.InputRegister => (ModbusFunction?)null, // Invalid ModbusEntity.Coil when quantity == 1 => ModbusFunction.WriteSingleCoil, ModbusEntity.Coil => ModbusFunction.WriteMultipleCoils, ModbusEntity.HoldingRegister when quantity == 1 => ModbusFunction.WriteSingleHoldingRegister, ModbusEntity.HoldingRegister => ModbusFunction.WriteMultipleHoldingRegisters, _ => form.Function ?? ModbusFunction.WriteSingleCoil }; if (!function.HasValue) { return ServiceResult.Create(StatusCodes.BadInvalidArgument, "Function or entity not supported"); } var timeout = form.Timeout ?? kDefaultTimeout; try { WriteAsync(function.Value, registerAddress, quantity, timeout, form.ToBuffer(value)).GetAwaiter().GetResult(); return ServiceResult.Good; } catch (ServiceResultException sre) { return sre.Result; } } public void Observe(AssetTag tag, uint id, OnAssetTagChange callback) { if (tag is not AssetTag) { throw ServiceResultException.Create(StatusCodes.BadInvalidArgument, "Not a modbus tag"); } // TODO: Implement polling } public void Unobserve(AssetTag tag, uint id) { if (tag is not AssetTag) { throw ServiceResultException.Create(StatusCodes.BadInvalidArgument, "Not a modbus tag"); } // TODO: Implement polling } private async Task WriteAsync(ModbusFunction function, ushort address, ushort quantity, int timeout, ReadOnlyMemory values, CancellationToken ct = default) { await _lock.WaitAsync(ct).ConfigureAwait(false); try { ObjectDisposedException.ThrowIf(_tcpClient == null, this); _tcpClient.SendTimeout = timeout; _tcpClient.ReceiveTimeout = timeout; Debug.Assert(_writer != null); Debug.Assert(_reader != null); var mbap = new ModbusProtocol.Mbap(_transactionID++, _unitId); _writer.WriteWriteRequest(function, mbap, address, quantity, values.Span); // send request to Modbus server await _writer.FlushAsync(ct).ConfigureAwait(false); // TODO: go full duplex using transaction id var error = ServiceResult.Good; while (true) { var result = await _reader.ReadAsync(ct).ConfigureAwait(false); if (result.IsCanceled) { throw new TimeoutException(); } var buffer = result.Buffer; var responseBuffer = new ArrayBufferWriter(); if (!responseBuffer.TryReadWriteResponse(function, ref buffer, address, quantity, values.Span, ref error)) { // More must be read to completely parse the response continue; } // // All has been read that is to be read or we would have // thrown here, advance to the end so that next read can // start // _reader.AdvanceTo(buffer.End); // Check error received and throw if not good if (error != ServiceResult.Good) { throw new ServiceResultException(error); } return; // Done } } catch (Exception ex) { _logger.ModbusTcpAssetError(ex); Reconnect(); throw; } finally { _lock.Release(); } } private async Task> ReadAsync(ModbusFunction function, ushort address, ushort quantity, int timeout, CancellationToken ct = default) { await _lock.WaitAsync(ct).ConfigureAwait(false); try { ObjectDisposedException.ThrowIf(_tcpClient == null, this); _tcpClient.SendTimeout = timeout; _tcpClient.ReceiveTimeout = timeout; Debug.Assert(_writer != null); Debug.Assert(_reader != null); var mbap = new ModbusProtocol.Mbap(_transactionID++, _unitId); _writer.EncodeReadRequest(function, mbap, address, quantity); // send request to Modbus server await _writer.FlushAsync(ct).ConfigureAwait(false); // TODO: go full duplex using transaction id var error = ServiceResult.Good; while (true) { var result = await _reader.ReadAsync(ct).ConfigureAwait(false); if (result.IsCanceled) { throw new TimeoutException(); } var buffer = result.Buffer; var responseBuffer = new ArrayBufferWriter(); if (!responseBuffer.TryReadReadResponse(function, ref buffer, ref error)) { // More must be read to completely parse the response continue; } // // All has been read that is to be read or we would have // thrown here, advance to the end so that next read can // start // _reader.AdvanceTo(buffer.End); // Check error received and throw if not good if (error != ServiceResult.Good) { throw new ServiceResultException(error); } return responseBuffer.WrittenMemory; } } catch (Exception ex) { _logger.ModbusTcpAssetError(ex); Reconnect(); throw; } finally { _lock.Release(); } } private void Reconnect() { Debug.Assert(_lock.CurrentCount == 0, "Reconnect should not be called concurrently"); _tcpClient?.Dispose(); var port = _address.Port == 0 ? kIanaPort : _address.Port; _tcpClient = new TcpClient(_address.IdnHost, port); var stream = _tcpClient.GetStream(); _writer = PipeWriter.Create(stream); _reader = PipeReader.Create(stream); } private const int kDefaultQuantity = 1; private const int kIanaPort = 502; /// /// private const bool kDefaultZeroBaseAddressing = false; /// private const bool kDefaultMostSignificantByte = true; /// private const bool kDefaultMostSignificantWord = true; /// private const int kDefaultTimeout = Timeout.Infinite; private ushort _transactionID; private readonly byte _unitId; private readonly ILogger _logger; private readonly Uri _address; private readonly SemaphoreSlim _lock = new(1, 1); private TcpClient? _tcpClient; private PipeReader? _reader; private PipeWriter? _writer; } /// /// Source-generated logging definitions for ModbusTcpAsset /// internal static partial class ModbusTcpAssetLogging { private const int EventClass = 20; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Error, Message = "Error")] public static partial void ModbusTcpAssetError(this ILogger logger, Exception ex); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Asset/Namespaces.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ #nullable enable namespace Asset { /// /// Defines constants for namespaces used by the application. /// public static partial class Namespaces { /// /// The namespace for the nodes provided by the server. /// public const string AssetServer = "http://opcfoundation.org/AssetServer"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Asset/Samples/SimulatedAsset.td.jsonld ================================================ { "@context": [ "https://www.w3.org/2022/wot/td/v1.1" ], "id": "urn:sim3264", "securityDefinitions": { "nosec_sc": { "scheme": "nosec" } }, "security": [ "nosec_sc" ], "@type": [ "Thing" ], "name": "sim-3264", "base": "sim://simserver1:443", "title": "Simulated Asset", "properties": { "VoltageL1-N": { "type": "number", "opcua:nodeId": "s=VoltageL-N", "readOnly": true, "observable": true, "forms": [ { "href": "1", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL2-N": { "type": "number", "opcua:nodeId": "s=VoltageL-N", "readOnly": true, "observable": true, "forms": [ { "href": "3", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL3-N": { "type": "number", "opcua:nodeId": "s=VoltageL-N", "readOnly": true, "observable": true, "forms": [ { "href": "5", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL1-L2": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "7", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL2-L3": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "9", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL3-L1": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "11", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "CurrentL1": { "type": "number", "opcua:nodeId": "s=Current", "readOnly": true, "observable": true, "forms": [ { "href": "13", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "CurrentL2": { "type": "number", "opcua:nodeId": "s=Current", "readOnly": true, "observable": true, "forms": [ { "href": "15", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "CurrentL3": { "type": "number", "opcua:nodeId": "s=Current", "readOnly": true, "observable": true, "forms": [ { "href": "17", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "PowerFactorL1": { "type": "number", "opcua:nodeId": "s=PowerFactor", "readOnly": true, "observable": true, "forms": [ { "href": "19", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "PowerFactorL2": { "type": "number", "opcua:nodeId": "s=PowerFactor", "readOnly": true, "observable": true, "forms": [ { "href": "139", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "PowerFactorL3": { "type": "number", "opcua:nodeId": "s=PowerFactor", "readOnly": true, "observable": true, "forms": [ { "href": "141", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalApparentPower": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "63", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalActivePower": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "65", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalReactivePower": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "67", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalPowerFactor": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "69", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Asset/SimulatedAsset.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ #nullable enable namespace Asset { using Opc.Ua; using System; using System.Collections.Concurrent; using System.Threading; using System.Xml; using TestData; public sealed class SimulatedAsset : IAsset { public ServiceResult Read(AssetTag tag, ref object? value) { return GetTag(tag).Read(ref value); } public ServiceResult Write(AssetTag tag, ref object value) { return GetTag(tag).Write(value); } public void Observe(AssetTag tag, uint id, OnAssetTagChange callback) { GetTag(tag).Observe(id, callback); } public void Unobserve(AssetTag tag, uint id) { ArgumentNullException.ThrowIfNull(tag.Address); if (_tags.TryGetValue(tag.Address, out var assetTag)) { assetTag.Unobserve(id); } } public void Dispose() { foreach (var tag in _tags.Values) { tag.Dispose(); } _tags.Clear(); } private SimulatedTag GetTag(AssetTag tag) { if (tag is not AssetTag simTag) { throw ServiceResultException.Create(StatusCodes.BadInvalidArgument, "Not a simulated tag"); } ArgumentNullException.ThrowIfNull(tag.Address); return _tags.GetOrAdd(tag.Address, _ => new SimulatedTag(this, simTag)); } /// /// Simulated tag /// internal sealed record class SimulatedTag : IDisposable { public SimulatedAsset Asset { get; } public AssetTag Tag { get; } /// /// Create tag /// /// /// public SimulatedTag(SimulatedAsset asset, AssetTag tag) { Asset = asset; Tag = tag; _timer = new Timer(PollValue); } public void Dispose() { _timer.Dispose(); } #pragma warning disable IDE0060 // Remove unused parameter public void Observe(uint id, OnAssetTagChange callback) #pragma warning restore IDE0060 // Remove unused parameter { if (Interlocked.Increment(ref _monitoringCount) == 1) { _callback = callback; _timer.Change(Tag.Form.PollingTime, Tag.Form.PollingTime); } } #pragma warning disable IDE0060 // Remove unused parameter public void Unobserve(uint id) #pragma warning restore IDE0060 // Remove unused parameter { if (Interlocked.Decrement(ref _monitoringCount) == 0) { _timer.Change(Timeout.Infinite, Timeout.Infinite); } } public ServiceResult Write(object value) { throw new NotImplementedException(); } public ServiceResult Read(ref object? value) { var dataType = Tag.Form.GetDataTypeId(); if (NodeId.IsNull(dataType)) { return ServiceResult.Create(StatusCodes.BadDataTypeIdUnknown, "Bad payload"); } if (Tag.Form.IsArray) { value = dataType.Identifier switch { Opc.Ua.DataTypes.Boolean => _generator.GetRandomArray(), Opc.Ua.DataTypes.SByte => _generator.GetRandomArray(), Opc.Ua.DataTypes.Byte => _generator.GetRandomArray(), Opc.Ua.DataTypes.Int16 => _generator.GetRandomArray(), Opc.Ua.DataTypes.UInt16 => _generator.GetRandomArray(), Opc.Ua.DataTypes.Int32 => _generator.GetRandomArray(), Opc.Ua.DataTypes.UInt32 => _generator.GetRandomArray(), Opc.Ua.DataTypes.Int64 => _generator.GetRandomArray(), Opc.Ua.DataTypes.UInt64 => _generator.GetRandomArray(), Opc.Ua.DataTypes.Float => _generator.GetRandomArray(), Opc.Ua.DataTypes.Double => _generator.GetRandomArray(), Opc.Ua.DataTypes.String => _generator.GetRandomArray(), Opc.Ua.DataTypes.DateTime => _generator.GetRandomArray(), Opc.Ua.DataTypes.Guid => _generator.GetRandomArray(), Opc.Ua.DataTypes.ByteString => _generator.GetRandomArray(), Opc.Ua.DataTypes.XmlElement => _generator.GetRandomArray(), Opc.Ua.DataTypes.NodeId => _generator.GetRandomArray(), Opc.Ua.DataTypes.ExpandedNodeId => _generator.GetRandomArray(), Opc.Ua.DataTypes.QualifiedName => _generator.GetRandomArray(), Opc.Ua.DataTypes.LocalizedText => _generator.GetRandomArray(), Opc.Ua.DataTypes.StatusCode => _generator.GetRandomArray(), Opc.Ua.DataTypes.BaseDataType => _generator.GetRandomArray(), Opc.Ua.DataTypes.Enumeration => _generator.GetRandomArray(), Opc.Ua.DataTypes.Number => _generator.GetRandomArray(BuiltInType.Number, 100, false), Opc.Ua.DataTypes.Integer => _generator.GetRandomArray(BuiltInType.Integer, 100, false), Opc.Ua.DataTypes.UInteger => _generator.GetRandomArray(BuiltInType.UInteger, 100, false), Opc.Ua.DataTypes.Structure => GetRandomArray(), _ => null }; return ServiceResult.Good; } value = dataType.Identifier switch { Opc.Ua.DataTypes.Boolean => _generator.GetRandom(), Opc.Ua.DataTypes.SByte => _generator.GetRandom(), Opc.Ua.DataTypes.Byte => _generator.GetRandom(), Opc.Ua.DataTypes.Int16 => _generator.GetRandom(), Opc.Ua.DataTypes.UInt16 => _generator.GetRandom(), Opc.Ua.DataTypes.Int32 => _generator.GetRandom(), Opc.Ua.DataTypes.UInt32 => _generator.GetRandom(), Opc.Ua.DataTypes.Int64 => _generator.GetRandom(), Opc.Ua.DataTypes.UInt64 => _generator.GetRandom(), Opc.Ua.DataTypes.Float => _generator.GetRandom(), Opc.Ua.DataTypes.Double => _generator.GetRandom(), Opc.Ua.DataTypes.String => _generator.GetRandom(), Opc.Ua.DataTypes.DateTime => _generator.GetRandom(), Opc.Ua.DataTypes.Guid => _generator.GetRandom(), Opc.Ua.DataTypes.ByteString => _generator.GetRandom(), Opc.Ua.DataTypes.XmlElement => _generator.GetRandom(), Opc.Ua.DataTypes.NodeId => _generator.GetRandom(), Opc.Ua.DataTypes.ExpandedNodeId => _generator.GetRandom(), Opc.Ua.DataTypes.QualifiedName => _generator.GetRandom(), Opc.Ua.DataTypes.LocalizedText => _generator.GetRandom(), Opc.Ua.DataTypes.StatusCode => _generator.GetRandom(), Opc.Ua.DataTypes.BaseDataType => _generator.GetRandomVariant().Value, Opc.Ua.DataTypes.Structure => GetRandomStructure(), Opc.Ua.DataTypes.Enumeration => _generator.GetRandom(), Opc.Ua.DataTypes.Number => _generator.GetRandom(BuiltInType.Number), Opc.Ua.DataTypes.Integer => _generator.GetRandom(BuiltInType.Integer), Opc.Ua.DataTypes.UInteger => _generator.GetRandom(BuiltInType.UInteger), _ => null }; return ServiceResult.Good; ExtensionObject[]? GetRandomArray() { var values = _generator.GetRandomArray(10); for (var i = 0; values != null && i < values.Length; i++) { values[i] = GetRandomStructure(); } return values; } ExtensionObject GetRandomStructure() { if (_generator.GetRandomBoolean()) { var scalar = new ScalarValueDataType { BooleanValue = _generator.GetRandom(), SByteValue = _generator.GetRandom(), ByteValue = _generator.GetRandom(), Int16Value = _generator.GetRandom(), UInt16Value = _generator.GetRandom(), Int32Value = _generator.GetRandom(), UInt32Value = _generator.GetRandom(), Int64Value = _generator.GetRandom(), UInt64Value = _generator.GetRandom(), FloatValue = _generator.GetRandom(), DoubleValue = _generator.GetRandom(), StringValue = _generator.GetRandom(), DateTimeValue = _generator.GetRandom(), GuidValue = _generator.GetRandom(), ByteStringValue = _generator.GetRandom(), XmlElementValue = _generator.GetRandom(), NodeIdValue = _generator.GetRandom(), ExpandedNodeIdValue = _generator.GetRandom(), QualifiedNameValue = _generator.GetRandom(), LocalizedTextValue = _generator.GetRandom(), StatusCodeValue = _generator.GetRandom(), VariantValue = _generator.GetRandomVariant() }; return new ExtensionObject(scalar); } var array = new ArrayValueDataType { BooleanValue = _generator.GetRandomArray(10), SByteValue = _generator.GetRandomArray(10), ByteValue = _generator.GetRandomArray(10), Int16Value = _generator.GetRandomArray(10), UInt16Value = _generator.GetRandomArray(10), Int32Value = _generator.GetRandomArray(10), UInt32Value = _generator.GetRandomArray(10), Int64Value = _generator.GetRandomArray(10), UInt64Value = _generator.GetRandomArray(10), FloatValue = _generator.GetRandomArray(10), DoubleValue = _generator.GetRandomArray(10), StringValue = _generator.GetRandomArray(10), DateTimeValue = _generator.GetRandomArray(10), GuidValue = _generator.GetRandomArray(10), ByteStringValue = _generator.GetRandomArray(10), XmlElementValue = _generator.GetRandomArray(10), NodeIdValue = _generator.GetRandomArray(10), ExpandedNodeIdValue = _generator.GetRandomArray(10), QualifiedNameValue = _generator.GetRandomArray(10), LocalizedTextValue = _generator.GetRandomArray(10), StatusCodeValue = _generator.GetRandomArray(10) }; var values = _generator.GetRandomArray(10); for (var i = 0; values != null && i < values.Length; i++) { array.VariantValue.Add(new Variant(values[i])); } return new ExtensionObject(array.TypeId, array); } } private void PollValue(object? state) { object? value = null; var result = Read(ref value); _callback?.Invoke(Tag, value, result.StatusCode, DateTime.UtcNow); } private readonly Opc.Ua.Test.TestDataGenerator _generator = new(); private readonly Timer _timer; private int _monitoringCount; private OnAssetTagChange? _callback; } private readonly ConcurrentDictionary _tags = new(); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Asset/SimulatedBinding.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ #nullable enable namespace Asset { using Newtonsoft.Json; public sealed class SimulatedForm : Form { [JsonProperty("sim:type")] public string? PayloadType { get; set; } [JsonProperty("sim:array")] public bool IsArray { get; set; } [JsonProperty("sim:pollingTime")] public long PollingTime { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Asset/SimulatedFormExtension.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ #nullable enable namespace Asset { using Opc.Ua; using System.Reflection; public static class SimulatedFormExtension { /// /// Get datatype id /// /// /// public static NodeId GetDataTypeId(this SimulatedForm form) { var fields = typeof(DataTypeIds).GetFields( BindingFlags.Public | BindingFlags.Static); foreach (var field in fields) { try { var value = field.GetValue(typeof(DataTypeIds)) as NodeId; if (value != null && field.Name == form.PayloadType) { return value; } } catch { continue; } } return NodeId.Null; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Asset/ThingDescription.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ #nullable enable namespace Asset { using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Runtime.Serialization; public sealed class ThingDescription { [JsonProperty("@context")] #pragma warning disable CA1819 // Properties should not return arrays public object[]? Context { get; set; } #pragma warning restore CA1819 // Properties should not return arrays [JsonProperty("id")] public string? Id { get; set; } [JsonProperty("securityDefinitions")] public SecurityDefinitions? SecurityDefinitions { get; set; } [JsonProperty("security")] #pragma warning disable CA1819 // Properties should not return arrays public string[]? Security { get; set; } #pragma warning restore CA1819 // Properties should not return arrays [JsonProperty("@type")] #pragma warning disable CA1819 // Properties should not return arrays public string[]? Type { get; set; } #pragma warning restore CA1819 // Properties should not return arrays [JsonProperty("name")] public string? Name { get; set; } [JsonProperty("base")] public string? Base { get; set; } [JsonProperty("title")] public string? Title { get; set; } [JsonProperty("properties")] #pragma warning disable CA2227 // Collection properties should be read only public Dictionary? Properties { get; set; } #pragma warning restore CA2227 // Collection properties should be read only // Actions // Events // Forms } public sealed class OpcUaNamespaces { [JsonProperty("opcua")] #pragma warning disable CA1819 // Properties should not return arrays public Uri[]? Namespaces { get; set; } #pragma warning restore CA1819 // Properties should not return arrays } public sealed class Property { [JsonProperty("type")] public TypeEnum Type { get; set; } [JsonProperty("opcua:nodeId")] public string? OpcUaNodeId { get; set; } [JsonProperty("readOnly")] public bool ReadOnly { get; set; } [JsonProperty("observable")] public bool Observable { get; set; } [JsonProperty("forms")] #pragma warning disable CA1819 // Properties should not return arrays public object[]? Forms { get; set; } #pragma warning restore CA1819 // Properties should not return arrays } [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public enum Op { [EnumMember(Value = "readproperty")] ReadProperty, [EnumMember(Value = "writeproperty")] WriteProperty, [EnumMember(Value = "observeproperty")] ObserveProperty, [EnumMember(Value = "unobserveproperty")] UnobserveProperty, } [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public enum TypeEnum { [EnumMember(Value = "number")] Number } public abstract class Form { [JsonProperty("href")] public string? Href { get; set; } [JsonProperty("op")] #pragma warning disable CA1819 // Properties should not return arrays public Op[]? Op { get; set; } #pragma warning restore CA1819 // Properties should not return arrays } public sealed class SecurityDefinitions { [JsonProperty("nosec_sc")] public NosecSc? NosecSc { get; set; } } public sealed class NosecSc { [JsonProperty("scheme")] public string? Scheme { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Azure.IIoT.OpcUa.Publisher.Testing.Servers.csproj ================================================  net9.0 Contains several test servers to run tests against true true false false disable ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Boiler/BoilerNodeManager.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Boiler { using Opc.Ua; using Opc.Ua.Sample; using System.Collections.Generic; using System.Reflection; /// /// A node manager the diagnostic information exposed by the server. /// public class BoilerNodeManager : SampleNodeManager { /// /// Initializes the node manager. /// /// /// public BoilerNodeManager( Opc.Ua.Server.IServerInternal server, ApplicationConfiguration configuration) : base(server) { System.Diagnostics.Contracts.Contract.Assume(configuration != null); var namespaceUris = new List { Namespaces.Boiler, Namespaces.Boiler + "/Instance" }; NamespaceUris = namespaceUris; _namespaceIndex = Server.NamespaceUris.GetIndexOrAppend(namespaceUris[1]); // AddEncodeableNodeManagerTypes(typeof(BoilerNodeManager).Assembly, typeof(BoilerNodeManager).Namespace); _lastUsedId = 0; _boilers = []; } protected override void Dispose(bool disposing) { if (disposing && _boilers != null) { foreach (var boiler in _boilers) { boiler.Dispose(); } _boilers = null; } base.Dispose(disposing); } /// /// Creates the NodeId for the specified node. /// /// The context. /// The node. /// The new NodeId. public override NodeId New(ISystemContext context, NodeState node) { var id = Utils.IncrementIdentifier(ref _lastUsedId); return new NodeId(id, _namespaceIndex); } /// /// Does any initialization required before the address space can be used. /// /// /// /// The externalReferences is an out parameter that allows the node manager to link to nodes /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and /// should have a reference to the root folder node(s) exposed by this node manager. /// public override void CreateAddressSpace(IDictionary> externalReferences) { lock (Lock) { base.CreateAddressSpace(externalReferences); CreateBoiler(SystemContext, 2); } } /// /// Creates a boiler and adds it to the address space. /// /// The context to use. /// The unit number for the boiler. private void CreateBoiler(SystemContext context, int unitNumber) { var boiler = new BoilerState(null); var name = Utils.Format("Boiler #{0}", unitNumber); boiler.Create( context, null, new QualifiedName(name, _namespaceIndex), null, true); var folder = FindPredefinedNode( ExpandedNodeId.ToNodeId(ObjectIds.Boilers, Server.NamespaceUris), typeof(NodeState)); folder.AddReference(Opc.Ua.ReferenceTypeIds.Organizes, false, boiler.NodeId); boiler.AddReference(Opc.Ua.ReferenceTypeIds.Organizes, true, folder.NodeId); var unitLabel = Utils.Format("{0}0", unitNumber); UpdateDisplayName(boiler.InputPipe, unitLabel); UpdateDisplayName(boiler.Drum, unitLabel); UpdateDisplayName(boiler.OutputPipe, unitLabel); UpdateDisplayName(boiler.LevelController, unitLabel); UpdateDisplayName(boiler.FlowController, unitLabel); UpdateDisplayName(boiler.CustomController, unitLabel); _boilers.Add(boiler); AddPredefinedNode(context, boiler); // Autostart boiler simulation state machine var start = boiler.Simulation.Start; IList inputArguments = []; IList outputArguments = []; var errors = new List(); start.Call(context, boiler.NodeId, inputArguments, errors, outputArguments); } /// /// Updates the display name for an instance with the unit label name. /// /// The instance to update. /// The label to apply. /// This method assumes the DisplayName has the form NameX001 where X0 is the unit label placeholder. private void UpdateDisplayName(BaseInstanceState instance, string unitLabel) { var displayName = instance.DisplayName; if (displayName != null) { var text = displayName.Text; if (text != null) { text = text.Replace("X0", unitLabel); } displayName = new LocalizedText(displayName.Locale, text); } instance.DisplayName = displayName; } /// /// Loads a node set from a file or resource and addes them to the set of predefined nodes. /// /// protected override NodeStateCollection LoadPredefinedNodes(ISystemContext context) { var type = GetType().GetTypeInfo(); var predefinedNodes = new NodeStateCollection(); predefinedNodes.LoadFromBinaryResource(context, $"{type.Assembly.GetName().Name}.Generated.{type.Namespace}.Design.{type.Namespace}.PredefinedNodes.uanodes", type.Assembly, true); return predefinedNodes; } /// /// Replaces the generic node with a node specific to the model. /// /// /// protected override NodeState AddBehaviourToPredefinedNode(ISystemContext context, NodeState predefinedNode) { if (predefinedNode is not BaseObjectState passiveNode) { return predefinedNode; } var typeId = passiveNode.TypeDefinitionId; if (!IsNodeIdInNamespace(typeId) || typeId.IdType != IdType.Numeric) { return predefinedNode; } switch ((uint)typeId.Identifier) { case ObjectTypes.BoilerType: { if (passiveNode is BoilerState) { break; } var activeNode = new BoilerState(passiveNode.Parent); activeNode.Create(context, passiveNode); // replace the node in the parent. passiveNode.Parent?.ReplaceChild(context, activeNode); // Autostart boiler simulation state machine var start = activeNode.Simulation.Start; IList inputArguments = []; IList outputArguments = []; var errors = new List(); start.Call(context, activeNode.NodeId, inputArguments, errors, outputArguments); _boilers.Add(activeNode); return activeNode; } } return predefinedNode; } /// /// Does any processing after a monitored item is created. /// /// /// /// /// protected override void OnCreateMonitoredItem( ISystemContext systemContext, MonitoredItemCreateRequest itemToCreate, MonitoredNode monitoredNode, DataChangeMonitoredItem monitoredItem) { // TBD } /// /// Does any processing after a monitored item is created. /// /// /// /// /// /// protected override void OnModifyMonitoredItem( ISystemContext systemContext, MonitoredItemModifyRequest itemToModify, MonitoredNode monitoredNode, DataChangeMonitoredItem monitoredItem, double previousSamplingInterval) { // TBD } /// /// Does any processing after a monitored item is deleted. /// /// /// /// protected override void OnDeleteMonitoredItem( ISystemContext systemContext, MonitoredNode monitoredNode, DataChangeMonitoredItem monitoredItem) { // TBD } /// /// Does any processing after a monitored item is created. /// /// /// /// /// /// protected override void OnSetMonitoringMode( ISystemContext systemContext, MonitoredNode monitoredNode, DataChangeMonitoredItem monitoredItem, MonitoringMode previousMode, MonitoringMode currentMode) { // TBD } private readonly ushort _namespaceIndex; private long _lastUsedId; private List _boilers; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Boiler/BoilerServer.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Boiler { using Opc.Ua; using Opc.Ua.Server; /// public class BoilerServer : INodeManagerFactory { /// public StringCollection NamespacesUris { get { return [ Namespaces.Boiler, Namespaces.Boiler + "Instance" ]; } } /// public INodeManager Create(IServerInternal server, ApplicationConfiguration configuration) { return new BoilerNodeManager(server, configuration); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Boiler/BoilerState.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Boiler { using Opc.Ua; using System; using System.Collections.Generic; using System.Threading; public partial class BoilerState { /// /// Initializes the object as a collection of counters which change value on read. /// /// /// protected override void OnAfterCreate(ISystemContext context, NodeState node) { base.OnAfterCreate(context, node); Simulation.OnAfterTransition = OnControlSimulation; _random = new Random(); } /// /// Cleans up when the object is disposed. /// /// protected override void Dispose(bool disposing) { if (disposing && _simulationTimer != null) { _simulationTimer.Dispose(); _simulationTimer = null; } base.Dispose(disposing); } /// /// Changes the state of the simulation. /// /// /// /// /// /// /// private ServiceResult OnControlSimulation( ISystemContext context, StateMachineState machine, uint transitionId, uint causeId, IList inputArguments, IList outputArguments) { switch (causeId) { case Opc.Ua.Methods.ProgramStateMachineType_Start: { if (_simulationTimer != null) { _simulationTimer.Dispose(); _simulationTimer = null; } var updateRate = Simulation.UpdateRate.Value; if (updateRate < 100) { updateRate = 100; Simulation.UpdateRate.Value = updateRate; } _simulationContext = context; _simulationTimer = new Timer(DoSimulation, null, (int)updateRate, (int)updateRate); break; } case Opc.Ua.Methods.ProgramStateMachineType_Halt: case Opc.Ua.Methods.ProgramStateMachineType_Suspend: { if (_simulationTimer != null) { _simulationTimer.Dispose(); _simulationTimer = null; } _simulationContext = context; break; } case Opc.Ua.Methods.ProgramStateMachineType_Reset: { if (_simulationTimer != null) { _simulationTimer.Dispose(); _simulationTimer = null; } _simulationContext = context; break; } } return ServiceResult.Good; } /// /// Rounds a value to the significate digits specified and adds a random perturbation. /// /// /// private double RoundAndPerturb(double value, byte significantDigits) { double offsetToApply = 0; if (!value.Equals(0.0)) { // need to move all significate digits above the decimal point. var offset = significantDigits - Math.Log10(Math.Abs(value)); offsetToApply = Math.Floor(offset); if (offsetToApply.Equals(offset)) { offsetToApply--; } } // round value to significant digits. var perturbedValue = Math.Round(value * Math.Pow(10.0, offsetToApply)); // apply the perturbation. perturbedValue += (_random.NextDouble() - 0.5) * 5; // restore original exponent. return Math.Round(perturbedValue) * Math.Pow(10.0, -offsetToApply); } /// /// Moves the value towards the target. /// /// /// /// /// private double Adjust(double value, double target, double step, Opc.Ua.Range range) { // convert percentage step to an absolute step if range is specified. if (range != null) { step *= range.Magnitude; } var difference = target - value; if (difference < 0) { value -= step; if (value < target) { return target; } } else { value += step; if (value > target) { return target; } } return value; } /// /// Returns the value as a percentage of the range. /// /// private double GetPercentage(AnalogItemState value) { var percentage = value.Value; var range = value.EURange.Value; if (range != null) { percentage /= Math.Abs(range.High - range.Low); if (Math.Abs(percentage) > 1.0) { percentage = 1.0; } } return percentage; } /// /// Returns the value as a percentage of the range. /// /// /// private double GetValue(double value, Opc.Ua.Range range) { if (range != null) { return value * range.Magnitude; } return value; } /// /// Updates the values for the simulation. /// /// private void DoSimulation(object state) { try { _simulationCounter++; // adjust level. m_drum.LevelIndicator.Output.Value = Adjust( m_drum.LevelIndicator.Output.Value, m_levelController.SetPoint.Value, 0.1, m_drum.LevelIndicator.Output.EURange.Value); // calculate inputs for custom controller. m_customController.Input1.Value = m_levelController.UpdateMeasurement(m_drum.LevelIndicator.Output); m_customController.Input2.Value = GetPercentage(m_inputPipe.FlowTransmitter1.Output); m_customController.Input3.Value = GetPercentage(m_outputPipe.FlowTransmitter2.Output); // calculate output for custom controller. m_customController.ControlOut.Value = (m_customController.Input1.Value + m_customController.Input3.Value - m_customController.Input2.Value) / 2; // update flow controller set point. m_flowController.SetPoint.Value = GetValue((m_customController.ControlOut.Value + 1) / 2, m_inputPipe.FlowTransmitter1.Output.EURange.Value); var error = m_flowController.UpdateMeasurement(m_inputPipe.FlowTransmitter1.Output); // adjust the input valve. m_inputPipe.Valve.Input.Value = Adjust(m_inputPipe.Valve.Input.Value, (error > 0) ? 100 : 0, 10, null); // adjust the input flow. m_inputPipe.FlowTransmitter1.Output.Value = Adjust( m_inputPipe.FlowTransmitter1.Output.Value, m_flowController.SetPoint.Value, 0.6, m_inputPipe.FlowTransmitter1.Output.EURange.Value); // add pertubations. m_drum.LevelIndicator.Output.Value = RoundAndPerturb(m_drum.LevelIndicator.Output.Value, 3); m_inputPipe.FlowTransmitter1.Output.Value = RoundAndPerturb(m_inputPipe.FlowTransmitter1.Output.Value, 3); m_outputPipe.FlowTransmitter2.Output.Value = RoundAndPerturb(m_outputPipe.FlowTransmitter2.Output.Value, 3); ClearChangeMasks(_simulationContext, true); } catch (Exception e) { Utils.Trace(e, "Unexpected error during boiler simulation."); } } private ISystemContext _simulationContext; private Timer _simulationTimer; private Random _random; #pragma warning disable IDE0052 // Remove unread private members private long _simulationCounter; #pragma warning restore IDE0052 // Remove unread private members } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Boiler/BoilerStateMachineState.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Boiler { using Opc.Ua; using System.Collections.Generic; public partial class BoilerStateMachineState { /// /// Initializes the object as a collection of counters which change value on read. /// /// /// protected override void OnAfterCreate(ISystemContext context, NodeState node) { base.OnAfterCreate(context, node); Start.OnCallMethod = OnStart; Start.OnReadExecutable = IsStartExecutable; Start.OnReadUserExecutable = IsStartUserExecutable; Suspend.OnCallMethod = OnSuspend; Suspend.OnReadExecutable = IsSuspendExecutable; Suspend.OnReadUserExecutable = IsSuspendUserExecutable; Resume.OnCallMethod = OnResume; Resume.OnReadExecutable = IsResumeExecutable; Resume.OnReadUserExecutable = IsResumeUserExecutable; Halt.OnCallMethod = OnHalt; Halt.OnReadExecutable = IsHaltExecutable; Halt.OnReadUserExecutable = IsHaltUserExecutable; Reset.OnCallMethod = OnResetOverride; Reset.OnReadExecutable = IsResetExecutableOverride; Reset.OnReadUserExecutable = IsResetExecutableOverride; } // The following were added to make the existing integration tests pass private ServiceResult OnResetOverride(ISystemContext context, MethodState method, IList inputArguments, IList outputArguments) { return ServiceResult.Good; } private ServiceResult IsResetExecutableOverride(ISystemContext context, NodeState node, ref bool value) { value = true; return ServiceResult.Good; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Boiler/GenericController.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Boiler { using Opc.Ua; using System; /// /// A object representing a generic controller. /// public partial class GenericControllerState { /// /// Updates the measurement and calculates the new control output. /// /// public double UpdateMeasurement(AnalogItemState source) { var range = source.EURange.Value; m_measurement.Value = source.Value; // clamp the setpoint. if (range != null) { if (m_setPoint.Value > range.High) { m_setPoint.Value = range.High; } if (m_setPoint.Value < range.Low) { m_setPoint.Value = range.Low; } } // calculate error. m_controlOut.Value = m_setPoint.Value - m_measurement.Value; if (range != null) { m_controlOut.Value /= range.Magnitude; if (Math.Abs(m_controlOut.Value) > 1.0) { m_controlOut.Value = (m_controlOut.Value < 0) ? -1.0 : +1.0; } } // return the new output. return m_controlOut.Value; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Common/DataChangeMonitoredItem.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using System; using System.Collections.Generic; using System.Threading; using Opc.Ua.Server; namespace Opc.Ua.Sample { /// /// Provides a basic monitored item implementation which does not support queuing. /// public class DataChangeMonitoredItem : IDataChangeMonitoredItem2 { /// /// Constructs a new instance. /// /// /// /// /// /// /// /// /// /// /// /// public DataChangeMonitoredItem( MonitoredNode source, uint id, uint attributeId, NumericRange indexRange, QualifiedName dataEncoding, DiagnosticsMasks diagnosticsMasks, TimestampsToReturn timestampsToReturn, MonitoringMode monitoringMode, uint clientHandle, double samplingInterval, bool alwaysReportUpdates) { _source = source; Id = id; AttributeId = attributeId; _indexRange = indexRange; DataEncoding = dataEncoding; _timestampsToReturn = timestampsToReturn; _diagnosticsMasks = diagnosticsMasks; MonitoringMode = monitoringMode; ClientHandle = clientHandle; _samplingInterval = samplingInterval; _nextSampleTime = DateTime.UtcNow.Ticks; _readyToPublish = false; _readyToTrigger = false; _resendData = false; AlwaysReportUpdates = alwaysReportUpdates; NodeId = source.Node.NodeId; } /// /// Constructs a new instance. /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// public DataChangeMonitoredItem( IMonitoredItemQueueFactory monitoredItemQueueFactory, MonitoredNode source, uint id, uint attributeId, NumericRange indexRange, QualifiedName dataEncoding, DiagnosticsMasks diagnosticsMasks, TimestampsToReturn timestampsToReturn, MonitoringMode monitoringMode, uint clientHandle, double samplingInterval, uint queueSize, bool discardOldest, DataChangeFilter filter, Range range, bool alwaysReportUpdates) { _source = source; _monitoredItemQueueFactory = monitoredItemQueueFactory; Id = id; AttributeId = attributeId; _indexRange = indexRange; DataEncoding = dataEncoding; _timestampsToReturn = timestampsToReturn; _diagnosticsMasks = diagnosticsMasks; MonitoringMode = monitoringMode; ClientHandle = clientHandle; _samplingInterval = samplingInterval; _nextSampleTime = DateTime.UtcNow.Ticks; _readyToPublish = false; _readyToTrigger = false; _resendData = false; _queue = null; _queueSize = queueSize; DataChangeFilter = filter; _range = 0; AlwaysReportUpdates = alwaysReportUpdates; NodeId = source.Node.NodeId; if (range != null) { _range = range.High - range.Low; } if (queueSize > 1) { _queue = new DataChangeQueueHandler(id, false, _monitoredItemQueueFactory); _queue.SetQueueSize(queueSize, discardOldest, diagnosticsMasks); _queue.SetSamplingInterval(samplingInterval); } } /// /// Constructs a new instance from a template. /// /// /// /// /// public DataChangeMonitoredItem( ISubscriptionStore subscriptionStore, IMonitoredItemQueueFactory monitoredItemQueueFactory, MonitoredNode source, IStoredMonitoredItem storedMonitoredItem) { _source = source; _monitoredItemQueueFactory = monitoredItemQueueFactory; Id = storedMonitoredItem.Id; AttributeId = storedMonitoredItem.AttributeId; _indexRange = storedMonitoredItem.ParsedIndexRange; DataEncoding = storedMonitoredItem.Encoding; _timestampsToReturn = storedMonitoredItem.TimestampsToReturn; _diagnosticsMasks = storedMonitoredItem.DiagnosticsMasks; MonitoringMode = storedMonitoredItem.MonitoringMode; ClientHandle = storedMonitoredItem.ClientHandle; _samplingInterval = storedMonitoredItem.SamplingInterval; _nextSampleTime = DateTime.UtcNow.Ticks; _readyToPublish = false; _readyToTrigger = false; _resendData = false; _queue = null; _queueSize = storedMonitoredItem.QueueSize; DataChangeFilter = storedMonitoredItem.FilterToUse as DataChangeFilter; _range = storedMonitoredItem.Range; AlwaysReportUpdates = storedMonitoredItem.AlwaysReportUpdates; _lastValue = storedMonitoredItem.LastValue; _lastError = storedMonitoredItem.LastError; NodeId = storedMonitoredItem.NodeId; if (storedMonitoredItem.QueueSize > 1) { IDataChangeMonitoredItemQueue queue = subscriptionStore .RestoreDataChangeMonitoredItemQueue( storedMonitoredItem.Id); if (queue != null) { _queue = new DataChangeQueueHandler( queue, storedMonitoredItem.DiscardOldest, storedMonitoredItem.SamplingInterval); } else { _queue = new DataChangeQueueHandler( storedMonitoredItem.Id, false, _monitoredItemQueueFactory); _queue.SetQueueSize( storedMonitoredItem.QueueSize, storedMonitoredItem.DiscardOldest, storedMonitoredItem.DiagnosticsMasks); _queue.SetSamplingInterval(storedMonitoredItem.SamplingInterval); } } } /// /// Gets the id for the attribute being monitored. /// public uint AttributeId { get; } /// /// Gets the index range used to selected a subset of the value. /// public NumericRange IndexRange => _indexRange; /// /// Gets the data encoding to use when returning the value. /// public QualifiedName DataEncoding { get; } /// /// Whether the monitored item should report a value without checking if it was changed. /// public bool AlwaysReportUpdates { get; set; } /// /// The number of milliseconds until the next sample. /// public int TimeToNextSample { get { lock (_lock) { if (MonitoringMode == MonitoringMode.Disabled) { return int.MaxValue; } DateTime now = DateTime.UtcNow; if (_nextSampleTime <= now.Ticks) { return 0; } return (int)((_nextSampleTime - now.Ticks) / TimeSpan.TicksPerMillisecond); } } } /// /// The monitoring mode. /// public MonitoringMode MonitoringMode { get; private set; } /// /// The sampling interval. /// public double SamplingInterval { get { lock (_lock) { return _samplingInterval; } } } /// /// Modifies the monitored item parameters, /// /// /// /// /// public ServiceResult Modify( DiagnosticsMasks diagnosticsMasks, TimestampsToReturn timestampsToReturn, uint clientHandle, double samplingInterval) { return Modify( diagnosticsMasks, timestampsToReturn, clientHandle, samplingInterval, 0, false, null, null); } /// /// Modifies the monitored item parameters, /// /// /// /// /// /// /// /// /// public ServiceResult Modify( DiagnosticsMasks diagnosticsMasks, TimestampsToReturn timestampsToReturn, uint clientHandle, double samplingInterval, uint queueSize, bool discardOldest, DataChangeFilter filter, Range range) { lock (_lock) { _diagnosticsMasks = diagnosticsMasks; _timestampsToReturn = timestampsToReturn; ClientHandle = clientHandle; _queueSize = queueSize; // subtract the previous sampling interval. long oldSamplingInterval = (long)(_samplingInterval * TimeSpan.TicksPerMillisecond); if (oldSamplingInterval < _nextSampleTime) { _nextSampleTime -= oldSamplingInterval; } _samplingInterval = samplingInterval; // calculate the next sampling interval. long newSamplingInterval = (long)(_samplingInterval * TimeSpan.TicksPerMillisecond); if (_samplingInterval > 0) { _nextSampleTime += newSamplingInterval; } else { _nextSampleTime = 0; } // update the filter and the range. DataChangeFilter = filter; _range = 0; if (range != null) { _range = range.High - range.Low; } // update the queue size. if (queueSize > 1) { (_queue ??= new DataChangeQueueHandler(Id, false, _monitoredItemQueueFactory)) .SetQueueSize( queueSize, discardOldest, diagnosticsMasks); _queue.SetSamplingInterval(samplingInterval); } else { _queue = null; } return ServiceResult.Good; } } /// /// Called when the attribute being monitored changed. Reads and queues the value. /// /// public void ValueChanged(ISystemContext context) { var value = new DataValue(); ServiceResult error = _source.Node .ReadAttribute(context, AttributeId, NumericRange.Empty, null, value); if (ServiceResult.IsBad(error)) { value = new DataValue(error.StatusCode); } value.ServerTimestamp = DateTime.UtcNow; QueueValue(value, error, false); } /// /// The node manager for the monitored item. /// public INodeManager NodeManager => _source.NodeManager; /// /// The session for the monitored item. /// public ISession Session { get { ISubscription subscription = SubscriptionCallback; if (subscription != null) { return subscription.Session; } return null; } } /// /// The monitored items owner identity. /// public IUserIdentity EffectiveIdentity { get { ISubscription subscription = SubscriptionCallback; return subscription?.EffectiveIdentity; } } /// /// The identifier for the subscription that the monitored item belongs to. /// public uint SubscriptionId { get { ISubscription subscription = SubscriptionCallback; if (subscription != null) { return subscription.Id; } return 0; } } /// /// The unique identifier for the monitored item. /// public uint Id { get; } /// /// The client handle. /// public uint ClientHandle { get; private set; } /// /// The callback to use to notify the subscription when values are ready to publish. /// public ISubscription SubscriptionCallback { get; set; } /// /// The handle assigned to the monitored item by the node manager. /// public object ManagerHandle => _source; /// /// The type of monitor item. /// public int MonitoredItemType => MonitoredItemTypeMask.DataChange; /// /// Returns true if the item is ready to publish. /// public bool IsReadyToPublish { get { lock (_lock) { // check if not ready to publish. if (!_readyToPublish) { return false; } // check if monitoring was turned off. if (MonitoringMode != MonitoringMode.Reporting) { return false; } // re-queue if too little time has passed since the last publish. long now = DateTime.UtcNow.Ticks; return _nextSampleTime <= now; } } } /// /// Gets or Sets a value indicating whether the item is ready to trigger in case it has some linked items. /// public bool IsReadyToTrigger { get { lock (_lock) { // only allow to trigger if sampling or reporting. if (MonitoringMode == MonitoringMode.Disabled) { return false; } return _readyToTrigger; } } set { lock (_lock) { _readyToTrigger = value; } } } /// public bool IsResendData { get { lock (_lock) { return _resendData; } } } /// /// Returns the results for the create request. /// /// public ServiceResult GetCreateResult(out MonitoredItemCreateResult result) { lock (_lock) { result = new MonitoredItemCreateResult { MonitoredItemId = Id, StatusCode = StatusCodes.Good, RevisedSamplingInterval = _samplingInterval, RevisedQueueSize = 0, FilterResult = null }; if (_queue != null) { result.RevisedQueueSize = _queueSize; } return ServiceResult.Good; } } /// /// Returns the results for the modify request. /// /// public ServiceResult GetModifyResult(out MonitoredItemModifyResult result) { lock (_lock) { result = new MonitoredItemModifyResult { StatusCode = StatusCodes.Good, RevisedSamplingInterval = _samplingInterval, RevisedQueueSize = 0, FilterResult = null }; if (_queue != null) { result.RevisedQueueSize = _queueSize; } return ServiceResult.Good; } } /// public void SetupResendDataTrigger() { lock (_lock) { if (MonitoringMode == MonitoringMode.Reporting) { _resendData = true; } } } /// public IStoredMonitoredItem ToStorableMonitoredItem() { return new StoredMonitoredItem { SamplingInterval = _samplingInterval, SubscriptionId = SubscriptionCallback.Id, QueueSize = _queueSize, AlwaysReportUpdates = AlwaysReportUpdates, AttributeId = AttributeId, ClientHandle = ClientHandle, DiagnosticsMasks = _diagnosticsMasks, IsDurable = false, Encoding = DataEncoding, FilterToUse = DataChangeFilter, Id = Id, LastError = _lastError, LastValue = _lastValue, MonitoringMode = MonitoringMode, NodeId = _source.Node.NodeId, OriginalFilter = DataChangeFilter, Range = _range, TimestampsToReturn = _timestampsToReturn, ParsedIndexRange = _indexRange }; } /// public void QueueValue(DataValue value, ServiceResult error) { QueueValue(value, error, false); } /// public void QueueValue(DataValue value, ServiceResult error, bool ignoreFilters) { lock (_lock) { // check if value has changed. if (!AlwaysReportUpdates && !ignoreFilters && !MonitoredItem.ValueChanged( value, error, _lastValue, _lastError, DataChangeFilter, _range)) { return; } // make a shallow copy of the value. if (value != null) { value = new DataValue { WrappedValue = value.WrappedValue, StatusCode = value.StatusCode, SourceTimestamp = value.SourceTimestamp, SourcePicoseconds = value.SourcePicoseconds, ServerTimestamp = value.ServerTimestamp, ServerPicoseconds = value.ServerPicoseconds }; // ensure the data value matches the error status code. if (error != null && error.StatusCode.Code != 0) { value.StatusCode = error.StatusCode; } } _lastValue = value; _lastError = error; // queue value. _queue?.QueueValue(value, error); // flag the item as ready to publish. _readyToPublish = true; _readyToTrigger = true; } } /// /// Sets a flag indicating that the semantics for the monitored node have changed. /// /// /// The StatusCode for next value reported by the monitored item will have the SemanticsChanged bit set. /// public void SetSemanticsChanged() { lock (_lock) { _semanticsChanged = true; } } /// /// Sets a flag indicating that the structure of the monitored node has changed. /// /// /// The StatusCode for next value reported by the monitored item will have the StructureChanged bit set. /// public void SetStructureChanged() { lock (_lock) { _structureChanged = true; } } /// /// Changes the monitoring mode. /// /// public MonitoringMode SetMonitoringMode(MonitoringMode monitoringMode) { lock (_lock) { MonitoringMode previousMode = MonitoringMode; if (previousMode == monitoringMode) { return previousMode; } if (previousMode == MonitoringMode.Disabled) { _nextSampleTime = DateTime.UtcNow.Ticks; _lastError = null; _lastValue = null; } MonitoringMode = monitoringMode; if (monitoringMode == MonitoringMode.Disabled) { _readyToPublish = false; _readyToTrigger = false; } return previousMode; } } /// /// No filters supported. /// public DataChangeFilter DataChangeFilter { get; private set; } public bool IsDurable => false; public NodeId NodeId { get; } /// /// Increments the sample time to the next interval. /// private void IncrementSampleTime() { // update next sample time. long now = DateTime.UtcNow.Ticks; long samplingInterval = (long)(_samplingInterval * TimeSpan.TicksPerMillisecond); if (_nextSampleTime > 0) { long delta = now - _nextSampleTime; if (samplingInterval > 0 && delta >= 0) { _nextSampleTime += ((delta / samplingInterval) + 1) * samplingInterval; } } // set sampling time based on current time. else { _nextSampleTime = now + samplingInterval; } } /// /// Called by the subscription to publish any notification. /// /// /// /// /// public bool Publish( OperationContext context, Queue notifications, Queue diagnostics, uint maxNotificationsPerPublish) { lock (_lock) { // check if not ready to publish. if (!IsReadyToPublish) { if (!_resendData) { return false; } } else { // update sample time. IncrementSampleTime(); } // check if queuing is enabled. if (_queue != null && (!_resendData || _queue.ItemsInQueue != 0)) { uint notificationCount = 0; while ( notificationCount < maxNotificationsPerPublish && _queue.PublishSingleValue(out DataValue value, out ServiceResult error)) { Publish(context, value, error, notifications, diagnostics); notificationCount++; if (_resendData) { break; } } } else { Publish(context, _lastValue, _lastError, notifications, diagnostics); } bool moreValuesToPublish = _queue?.ItemsInQueue > 0; // update flags _readyToPublish = moreValuesToPublish; _readyToTrigger = moreValuesToPublish; _resendData = false; return moreValuesToPublish; } } /// /// Publishes a value. /// /// /// /// /// /// private void Publish( OperationContext context, DataValue value, ServiceResult error, Queue notifications, Queue diagnostics) { // set semantics changed bit. if (_semanticsChanged) { if (value != null) { value.StatusCode = value.StatusCode.SetSemanticsChanged(true); } if (error != null) { error = new ServiceResult( error.StatusCode.SetSemanticsChanged(true), error.SymbolicId, error.NamespaceUri, error.LocalizedText, error.AdditionalInfo, error.InnerResult); } _semanticsChanged = false; } // set structure changed bit. if (_structureChanged) { if (value != null) { value.StatusCode = value.StatusCode.SetStructureChanged(true); } if (error != null) { _ = new ServiceResult( error.StatusCode.SetStructureChanged(true), error.SymbolicId, error.NamespaceUri, error.LocalizedText, error.AdditionalInfo, error.InnerResult); } _structureChanged = false; } // copy data value. var item = new MonitoredItemNotification { ClientHandle = ClientHandle, Value = value }; // apply timestamp filter. if (_timestampsToReturn is not TimestampsToReturn.Server and not TimestampsToReturn.Both) { item.Value.ServerTimestamp = DateTime.MinValue; } if (_timestampsToReturn is not TimestampsToReturn.Source and not TimestampsToReturn.Both) { item.Value.SourceTimestamp = DateTime.MinValue; } notifications.Enqueue(item); // update diagnostic info. DiagnosticInfo diagnosticInfo = null; if (_lastError != null && (_diagnosticsMasks & DiagnosticsMasks.OperationAll) != 0) { diagnosticInfo = ServerUtils.CreateDiagnosticInfo( _source.Server, context, _lastError); } diagnostics.Enqueue(diagnosticInfo); } /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// An overrideable version of the Dispose. /// /// protected virtual void Dispose(bool disposing) { //only durable queues need to be disposed } private readonly Lock _lock = new(); private readonly IMonitoredItemQueueFactory _monitoredItemQueueFactory; private readonly MonitoredNode _source; private DataValue _lastValue; private ServiceResult _lastError; private NumericRange _indexRange; private TimestampsToReturn _timestampsToReturn; private DiagnosticsMasks _diagnosticsMasks; private double _samplingInterval; private DataChangeQueueHandler _queue; private uint _queueSize; private double _range; private long _nextSampleTime; private bool _readyToPublish; private bool _readyToTrigger; private bool _semanticsChanged; private bool _structureChanged; private bool _resendData; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Common/FolderConfiguration.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ #nullable enable namespace Opc.Ua { using System.IO; using System.Runtime.Serialization; /// /// Access to a folder to use for the instance of the server. /// [DataContract(Namespace = Namespaces.OpcUa)] public class FolderConfiguration { /// /// The default constructor. /// public FolderConfiguration() { Initialize(); } /// /// Initializes the object during deserialization. /// /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { CurrentDirectory = Directory.GetCurrentDirectory(); } /// /// Which folder is the current directory /// [DataMember(Order = 1)] public string? CurrentDirectory { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Common/MonitoredNode.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using System.Collections.Generic; using Opc.Ua.Server; namespace Opc.Ua.Sample { /// /// Keeps track of the monitored items for a single node. /// public class MonitoredNode { /// /// Initializes the instance with the context for the node being monitored. /// /// /// /// public MonitoredNode(IServerInternal server, INodeManager nodeManager, NodeState node) { Server = server; NodeManager = nodeManager; Node = node; } /// /// The server that the node belongs to. /// public IServerInternal Server { get; } /// /// The node manager that the node belongs to. /// public INodeManager NodeManager { get; } /// /// The node being monitored. /// public NodeState Node { get; } /// /// Whether the node has any active monitored items for the specified attribute. /// /// public bool IsMonitoringRequired(uint attributeId) { if (m_monitoredItems != null) { for (int ii = 0; ii < m_monitoredItems.Count; ii++) { DataChangeMonitoredItem monitoredItem = m_monitoredItems[ii]; if (monitoredItem.AttributeId == attributeId && monitoredItem.MonitoringMode != MonitoringMode.Disabled) { return true; } } } return false; } /// /// Creates a new data change monitored item. /// /// The system context. /// The unique identifier for the monitiored item. /// The attribute to monitor. /// The index range to use for array values. /// The data encoding to return for structured values. /// The diagnostics masks to use. /// The timestamps to return. /// The initial monitoring mode. /// The handle assigned by the client. /// The sampling interval. /// The queue size. /// Whether to discard the oldest values when the queue overflows. /// The data change filter to use. /// The range to use when evaluating a percentage deadband filter. /// Whether the monitored item should skip the check for a change in value. /// The new monitored item. public DataChangeMonitoredItem CreateDataChangeItem( ISystemContext context, uint monitoredItemId, uint attributeId, NumericRange indexRange, QualifiedName dataEncoding, DiagnosticsMasks diagnosticsMasks, TimestampsToReturn timestampsToReturn, MonitoringMode monitoringMode, uint clientHandle, double samplingInterval, uint queueSize, bool discardOldest, DataChangeFilter filter, Range range, bool alwaysReportUpdates) { var monitoredItem = new DataChangeMonitoredItem( Server.MonitoredItemQueueFactory, this, monitoredItemId, attributeId, indexRange, dataEncoding, diagnosticsMasks, timestampsToReturn, monitoringMode, clientHandle, samplingInterval, queueSize, discardOldest, filter, range, alwaysReportUpdates); if (m_monitoredItems == null) { m_monitoredItems = []; Node.OnStateChanged = OnNodeChange; } m_monitoredItems.Add(monitoredItem); return monitoredItem; } /// /// Creates a new data change monitored item. /// /// The system context. /// The unique identifier for the monitiored item. /// The attribute to monitor. /// The index range to use for array values. /// The data encoding to return for structured values. /// The diagnostics masks to use. /// The timestamps to return. /// The initial monitoring mode. /// The handle assigned by the client. /// The sampling interval. /// Whether the monitored item should skip the check for a change in value. /// The new monitored item. public DataChangeMonitoredItem CreateDataChangeItem( ISystemContext context, uint monitoredItemId, uint attributeId, NumericRange indexRange, QualifiedName dataEncoding, DiagnosticsMasks diagnosticsMasks, TimestampsToReturn timestampsToReturn, MonitoringMode monitoringMode, uint clientHandle, double samplingInterval, bool alwaysReportUpdates) { return CreateDataChangeItem( context, monitoredItemId, attributeId, indexRange, dataEncoding, diagnosticsMasks, timestampsToReturn, monitoringMode, clientHandle, samplingInterval, 0, false, null, null, alwaysReportUpdates); } /// /// Restore a data change item after a server restart /// /// /// The new monitored item. public DataChangeMonitoredItem RestoreDataChangeItem( IStoredMonitoredItem storedMonitoredItem) { var monitoredItem = new DataChangeMonitoredItem( Server.SubscriptionStore, Server.MonitoredItemQueueFactory, this, storedMonitoredItem); if (m_monitoredItems == null) { m_monitoredItems = []; Node.OnStateChanged = OnNodeChange; } m_monitoredItems.Add(monitoredItem); return monitoredItem; } /// /// Deletes the monitored item. /// /// public void DeleteItem(IMonitoredItem monitoredItem) { if (m_monitoredItems != null) { for (int ii = 0; ii < m_monitoredItems.Count; ii++) { if (ReferenceEquals(monitoredItem, m_monitoredItems[ii])) { m_monitoredItems.RemoveAt(ii); break; } } } } /// /// Handles change events raised by the node. /// /// The system context. /// The node that raised the event. /// What caused the event to be raised public void OnNodeChange( ISystemContext context, NodeState state, NodeStateChangeMasks masks) { if (m_monitoredItems != null) { for (int ii = 0; ii < m_monitoredItems.Count; ii++) { DataChangeMonitoredItem monitoredItem = m_monitoredItems[ii]; // check if the node has been deleted. if ((masks & NodeStateChangeMasks.Deleted) != 0) { monitoredItem.QueueValue(null, StatusCodes.BadNodeIdUnknown, false); continue; } if (monitoredItem.AttributeId == Attributes.Value) { if ((masks & NodeStateChangeMasks.Value) != 0) { monitoredItem.ValueChanged(context); } } else if ((masks & NodeStateChangeMasks.NonValue) != 0) { monitoredItem.ValueChanged(context); } } } } /// /// Subscribes to events produced by the node. /// /// /// public void SubscribeToEvents(ISystemContext context, IEventMonitoredItem eventSubscription) { m_eventSubscriptions ??= []; if (m_eventSubscriptions.Count == 0) { Node.OnReportEvent = OnReportEvent; Node.SetAreEventsMonitored(context, true, true); } for (int ii = 0; ii < m_eventSubscriptions.Count; ii++) { if (ReferenceEquals(eventSubscription, m_eventSubscriptions[ii])) { return; } } m_eventSubscriptions.Add(eventSubscription); } /// /// Unsubscribes to events produced by the node. /// /// /// public void UnsubscribeToEvents( ISystemContext context, IEventMonitoredItem eventSubscription) { if (m_eventSubscriptions != null) { for (int ii = 0; ii < m_eventSubscriptions.Count; ii++) { if (ReferenceEquals(eventSubscription, m_eventSubscriptions[ii])) { m_eventSubscriptions.RemoveAt(ii); if (m_eventSubscriptions.Count == 0) { Node.SetAreEventsMonitored(context, false, true); Node.OnReportEvent = null; } break; } } } } /// /// Handles events reported by the node. /// /// The system context. /// The node that raised the event. /// The event to report. public void OnReportEvent(ISystemContext context, NodeState state, IFilterTarget e) { if (m_eventSubscriptions != null) { for (int ii = 0; ii < m_eventSubscriptions.Count; ii++) { m_eventSubscriptions[ii].QueueEvent(e); } } } /// /// Resends the events for any conditions belonging to the node or its children. /// /// The system context. /// The item to refresh. public void ConditionRefresh(ISystemContext context, IEventMonitoredItem monitoredItem) { if (m_eventSubscriptions != null) { for (int ii = 0; ii < m_eventSubscriptions.Count; ii++) { // only process items monitoring this node. if (!ReferenceEquals(monitoredItem, m_eventSubscriptions[ii])) { continue; } // get the set of condition events for the node and its children. var events = new List(); Node.ConditionRefresh(context, events, true); // report the events to the monitored item. for (int jj = 0; jj < events.Count; jj++) { monitoredItem.QueueEvent(events[jj]); } } } } private List m_eventSubscriptions; private List m_monitoredItems; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Common/SampleNodeManager.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2022 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Reflection; using System.Threading; using Opc.Ua.Server; namespace Opc.Ua.Sample { /// /// A node manager for a variety of test data. /// public class SampleNodeManager : INodeManager, INodeIdFactory, IDisposable { /// /// Initializes the node manager. /// /// public SampleNodeManager(IServerInternal server) { // save a reference to the server that owns the node manager. Server = server; // create the default context. SystemContext = Server.DefaultSystemContext.Copy(); SystemContext.SystemHandle = null; SystemContext.NodeIdFactory = this; // create the table of nodes. PredefinedNodes = []; RootNotifiers = []; _sampledItems = []; _minimumSamplingInterval = 100; } /// /// Frees any unmanaged resources. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// An overrideable version of the Dispose. /// /// protected virtual void Dispose(bool disposing) { if (disposing) { lock (Lock) { Utils.SilentDispose(_samplingTimer); _samplingTimer = null; foreach (NodeState node in PredefinedNodes.Values) { Utils.SilentDispose(node); } } } } /// /// Creates the NodeId for the specified node. /// /// The context. /// The node. /// The new NodeId. public virtual NodeId New(ISystemContext context, NodeState node) { return node.NodeId; } /// /// Acquires the lock on the node manager. /// public object Lock { get; } = new object(); /// /// The server that the node manager belongs to. /// protected IServerInternal Server { get; } /// /// The default context to use. /// protected ServerSystemContext SystemContext { get; } /// /// The predefined nodes managed by the node manager. /// protected NodeIdDictionary PredefinedNodes { get; } /// /// The root notifiers for the node manager. /// protected List RootNotifiers { get; } /// /// Returns true if the namespace for the node id is one of the namespaces managed by the node manager. /// /// The node id to check. /// True if the namespace is one of the nodes. protected virtual bool IsNodeIdInNamespace(NodeId nodeId) { if (NodeId.IsNull(nodeId)) { return false; } // quickly exclude nodes that not in the namespace. for (int ii = 0; ii < _namespaceIndexes.Length; ii++) { if (nodeId.NamespaceIndex == _namespaceIndexes[ii]) { return true; } } return false; } /// /// Returns the node if the handle refers to a node managed by this manager. /// /// The handle to check. /// Non-null if the handle belongs to the node manager. protected virtual NodeState IsHandleInNamespace(object managerHandle) { if (managerHandle is not NodeState source) { return null; } if (!IsNodeIdInNamespace(source.NodeId)) { return null; } return source; } /// /// Returns the state object for the specified node if it exists. /// /// public NodeState Find(NodeId nodeId) { lock (Lock) { if (!PredefinedNodes.TryGetValue(nodeId, out NodeState node)) { return null; } return node; } } /// /// Creates a new instance and assigns unique identifiers to all children. /// /// The operation context. /// An optional parent identifier. /// The reference type from the parent. /// The browse name. /// The instance to create. /// The new node id. /// public NodeId CreateNode( ServerSystemContext context, NodeId parentId, NodeId referenceTypeId, QualifiedName browseName, BaseInstanceState instance) { ServerSystemContext contextToUse = SystemContext.Copy(context); lock (Lock) { instance.ReferenceTypeId = referenceTypeId; NodeState parent = null; if (parentId != null) { if (!PredefinedNodes.TryGetValue(parentId, out parent)) { throw ServiceResultException.Create( StatusCodes.BadNodeIdUnknown, "Cannot find parent with id: {0}", parentId); } parent.AddChild(instance); } instance.Create(contextToUse, null, browseName, null, true); AddPredefinedNode(contextToUse, instance); return instance.NodeId; } } /// /// Deletes a node and all of its children. /// /// /// public bool DeleteNode(ServerSystemContext context, NodeId nodeId) { ServerSystemContext contextToUse = SystemContext.Copy(context); bool found = false; var referencesToRemove = new List(); lock (Lock) { if (PredefinedNodes.TryGetValue(nodeId, out NodeState node)) { RemovePredefinedNode(contextToUse, node, referencesToRemove); found = true; } RemoveRootNotifier(node); } // must release the lock before removing cross references to other node managers. if (referencesToRemove.Count > 0) { Server.NodeManager.RemoveReferences(referencesToRemove); } return found; } /// /// Adds all encodeable types defined in a node manager to the server factory. /// /// The assembly which contains the encodeable types. /// A filter with which the FullName of the type must start. protected void AddEncodeableNodeManagerTypes(Assembly assembly, string filter) { Server.Factory.AddEncodeableTypes( assembly.GetExportedTypes().Where(t => t.FullName.StartsWith(filter, StringComparison.Ordinal))); } /// /// Returns the namespaces used by the node manager. /// /// /// All NodeIds exposed by the node manager must be qualified by a namespace URI. This property /// returns the URIs used by the node manager. In this example all NodeIds use a single URI. /// public virtual IEnumerable NamespaceUris { get => _namespaceUris; protected set { if (value != null) { _namespaceUris = [.. value]; } else { _namespaceUris = []; } _namespaceIndexes = new ushort[_namespaceUris.Count]; } } /// /// Does any initialization required before the address space can be used. /// /// /// /// The externalReferences is an out parameter that allows the node manager to link to nodes /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and /// should have a reference to the root folder node(s) exposed by this node manager. /// public virtual void CreateAddressSpace( IDictionary> externalReferences) { lock (Lock) { // add the uris to the server's namespace table and cache the indexes. for (int ii = 0; ii < _namespaceUris.Count; ii++) { _namespaceIndexes[ii] = Server.NamespaceUris .GetIndexOrAppend(_namespaceUris[ii]); } LoadPredefinedNodes(SystemContext, externalReferences); } } /// /// Loads a node set from a file or resource and adds them to the set of predefined nodes. /// /// /// /// /// public virtual void LoadPredefinedNodes( ISystemContext context, Assembly assembly, string resourcePath, IDictionary> externalReferences) { // load the predefined nodes from an XML document. var predefinedNodes = new NodeStateCollection(); predefinedNodes.LoadFromResource(context, resourcePath, assembly, true); // add the predefined nodes to the node manager. for (int ii = 0; ii < predefinedNodes.Count; ii++) { AddPredefinedNode(context, predefinedNodes[ii]); } // ensure the reverse references exist. AddReverseReferences(externalReferences); } /// /// Loads a node set from a file or resource and adds them to the set of predefined nodes. /// /// protected virtual NodeStateCollection LoadPredefinedNodes(ISystemContext context) { return []; } /// /// Loads a node set from a file or resource and adds them to the set of predefined nodes. /// /// /// protected virtual void LoadPredefinedNodes( ISystemContext context, IDictionary> externalReferences) { // load the predefined nodes from an XML document. NodeStateCollection predefinedNodes = LoadPredefinedNodes(context); // add the predefined nodes to the node manager. for (int ii = 0; ii < predefinedNodes.Count; ii++) { AddPredefinedNode(context, predefinedNodes[ii]); } // ensure the reverse references exist. AddReverseReferences(externalReferences); } /// /// Replaces the generic node with a node specific to the model. /// /// /// protected virtual NodeState AddBehaviourToPredefinedNode( ISystemContext context, NodeState predefinedNode) { if (predefinedNode is not BaseObjectState) { return predefinedNode; } return predefinedNode; } /// /// Recursively indexes the node and its children. /// /// /// protected virtual void AddPredefinedNode(ISystemContext context, NodeState node) { NodeState activeNode = AddBehaviourToPredefinedNode(context, node); PredefinedNodes[activeNode.NodeId] = activeNode; if (activeNode is BaseTypeState type) { AddTypesToTypeTree(type); } var children = new List(); activeNode.GetChildren(context, children); for (int ii = 0; ii < children.Count; ii++) { AddPredefinedNode(context, children[ii]); } } /// /// Recursively indexes the node and its children. /// /// /// /// protected virtual void RemovePredefinedNode( ISystemContext context, NodeState node, List referencesToRemove) { PredefinedNodes.Remove(node.NodeId); node.UpdateChangeMasks(NodeStateChangeMasks.Deleted); node.ClearChangeMasks(context, false); OnNodeRemoved(node); // remove from the parent. if (node is BaseInstanceState instance && instance.Parent != null) { instance.Parent.RemoveChild(instance); } // remove children. var children = new List(); node.GetChildren(context, children); for (int ii = 0; ii < children.Count; ii++) { node.RemoveChild(children[ii]); } for (int ii = 0; ii < children.Count; ii++) { RemovePredefinedNode(context, children[ii], referencesToRemove); } // remove from type table. if (node is BaseTypeState type) { Server.TypeTree.Remove(type.NodeId); } // remove inverse references. var references = new List(); node.GetReferences(context, references); for (int ii = 0; ii < references.Count; ii++) { IReference reference = references[ii]; if (reference.TargetId.IsAbsolute) { continue; } var referenceToRemove = new LocalReference( (NodeId)reference.TargetId, reference.ReferenceTypeId, !reference.IsInverse, node.NodeId); referencesToRemove.Add(referenceToRemove); } } /// /// Called after a node has been deleted. /// /// protected virtual void OnNodeRemoved(NodeState node) { // overridden by the sub-class. } /// /// Add the node to the set of root notifiers. /// /// protected virtual void AddRootNotifier(NodeState notifier) { for (int ii = 0; ii < RootNotifiers.Count; ii++) { if (ReferenceEquals(notifier, RootNotifiers[ii])) { return; } } RootNotifiers.Add(notifier); // subscribe to existing events. if (Server.EventManager != null) { IList monitoredItems = Server.EventManager.GetMonitoredItems(); for (int ii = 0; ii < monitoredItems.Count; ii++) { if (monitoredItems[ii].MonitoringAllEvents) { SubscribeToAllEvents(SystemContext, monitoredItems[ii], true, notifier); } } } } /// /// Remove the node from the set of root notifiers. /// /// protected virtual void RemoveRootNotifier(NodeState notifier) { for (int ii = 0; ii < RootNotifiers.Count; ii++) { if (ReferenceEquals(notifier, RootNotifiers[ii])) { RootNotifiers.RemoveAt(ii); break; } } } /// /// Ensures that all reverse references exist. /// /// A list of references to add to external targets. protected virtual void AddReverseReferences( IDictionary> externalReferences) { foreach (NodeState source in PredefinedNodes.Values) { // assign a default value to any variable value. if (source is BaseVariableState variable && variable.Value == null) { variable.Value = TypeInfo.GetDefaultValue( variable.DataType, variable.ValueRank, Server.TypeTree); } // add reference from supertype for type nodes. /* BaseTypeState type = source as BaseTypeState; if (type != null && !NodeId.IsNull(type.SuperTypeId)) { if (!IsNodeIdInNamespace(type.SuperTypeId)) { AddExternalReference( type.SuperTypeId, ReferenceTypeIds.HasSubtype, false, type.NodeId, externalReferences); } } */ IList references = []; source.GetReferences(SystemContext, references); for (int ii = 0; ii < references.Count; ii++) { IReference reference = references[ii]; // nothing to do with external nodes. if (reference.TargetId?.IsAbsolute != false) { continue; } var targetId = (NodeId)reference.TargetId; // add inverse reference to internal targets. if (PredefinedNodes.TryGetValue(targetId, out NodeState target)) { if (!target.ReferenceExists( reference.ReferenceTypeId, !reference.IsInverse, source.NodeId)) { target.AddReference( reference.ReferenceTypeId, !reference.IsInverse, source.NodeId); } continue; } // check for inverse references to external notifiers. if (reference.IsInverse && reference.ReferenceTypeId == ReferenceTypeIds.HasNotifier) { AddRootNotifier(source); } // nothing more to do for references to nodes managed by this manager. if (IsNodeIdInNamespace(targetId)) { continue; } // add external reference. AddExternalReference( targetId, reference.ReferenceTypeId, !reference.IsInverse, source.NodeId, externalReferences); } } } /// /// Adds an external reference to the dictionary. /// /// /// /// /// /// protected void AddExternalReference( NodeId sourceId, NodeId referenceTypeId, bool isInverse, NodeId targetId, IDictionary> externalReferences) { // get list of references to external nodes. if (!externalReferences.TryGetValue(sourceId, out IList referencesToAdd)) { externalReferences[sourceId] = referencesToAdd = []; } // add reserve reference from external node. var referenceToAdd = new ReferenceNode { ReferenceTypeId = referenceTypeId, IsInverse = isInverse, TargetId = targetId }; referencesToAdd.Add(referenceToAdd); } /// /// Recursively adds the types to the type tree. /// /// protected void AddTypesToTypeTree(BaseTypeState type) { if (!NodeId.IsNull(type.SuperTypeId) && !Server.TypeTree.IsKnown(type.SuperTypeId)) { AddTypesToTypeTree(type.SuperTypeId); } if (type.NodeClass != NodeClass.ReferenceType) { Server.TypeTree.AddSubtype(type.NodeId, type.SuperTypeId); } else { Server.TypeTree.AddReferenceSubtype(type.NodeId, type.SuperTypeId, type.BrowseName); } } /// /// Recursively adds the types to the type tree. /// /// protected void AddTypesToTypeTree(NodeId typeId) { if (Find(typeId) is not BaseTypeState type) { return; } AddTypesToTypeTree(type); } /// /// Finds the specified node and checks if it is of the expected type. /// /// /// /// Returns null if not found or not of the correct type. public NodeState FindPredefinedNode(NodeId nodeId, Type expectedType) { if (nodeId == null) { return null; } if (!PredefinedNodes.TryGetValue(nodeId, out NodeState node)) { return null; } if (expectedType?.IsInstanceOfType(node) == false) { return null; } return node; } /// /// Frees any resources allocated for the address space. /// public virtual void DeleteAddressSpace() { lock (Lock) { PredefinedNodes.Clear(); } } /// /// Returns a unique handle for the node. /// /// /// /// This must efficiently determine whether the node belongs to the node manager. If it does belong to /// NodeManager it should return a handle that does not require the NodeId to be validated again when /// the handle is passed into other methods such as 'Read' or 'Write'. /// public virtual object GetManagerHandle(NodeId nodeId) { lock (Lock) { return GetManagerHandle(SystemContext, nodeId, null); } } /// /// Returns a unique handle for the node. /// /// /// /// /// /// This must efficiently determine whether the node belongs to the node manager. If it does belong to /// NodeManager it should return a handle that does not require the NodeId to be validated again when /// the handle is passed into other methods such as 'Read' or 'Write'. /// protected virtual object GetManagerHandle( ISystemContext context, NodeId nodeId, IDictionary cache) { lock (Lock) { // quickly exclude nodes that not in the namespace. if (!IsNodeIdInNamespace(nodeId)) { return null; } // lookup the node. if (!PredefinedNodes.TryGetValue(nodeId, out NodeState node)) { return null; } return node; } } /// /// This method is used to add bi-directional references to nodes from other node managers. /// /// /// /// The additional references are optional, however, the NodeManager should support them. /// public virtual void AddReferences(IDictionary> references) { lock (Lock) { foreach (KeyValuePair> current in references) { // check for valid handle. if (GetManagerHandle(SystemContext, current.Key, null) is not NodeState source) { continue; } // add reference to external target. foreach (IReference reference in current.Value) { source.AddReference( reference.ReferenceTypeId, reference.IsInverse, reference.TargetId); } } } } /// /// This method is used to delete bi-directional references to nodes from other node managers. /// /// /// /// /// /// public virtual ServiceResult DeleteReference( object sourceHandle, NodeId referenceTypeId, bool isInverse, ExpandedNodeId targetId, bool deleteBidirectional) { lock (Lock) { // check for valid handle. NodeState source = IsHandleInNamespace(sourceHandle); if (source == null) { return StatusCodes.BadNodeIdUnknown; } source.RemoveReference(referenceTypeId, isInverse, targetId); if (deleteBidirectional) { // check if the target is also managed by the node manager. if (!targetId.IsAbsolute) { var target = GetManagerHandle( SystemContext, (NodeId)targetId, null) as NodeState; target?.RemoveReference(referenceTypeId, !isInverse, source.NodeId); } } return ServiceResult.Good; } } /// /// Returns the basic metadata for the node. Returns null if the node does not exist. /// /// /// /// /// /// This method validates any placeholder handle. /// public virtual NodeMetadata GetNodeMetadata( OperationContext context, object targetHandle, BrowseResultMask resultMask) { ServerSystemContext systemContext = SystemContext.Copy(context); lock (Lock) { // check for valid handle. NodeState target = IsHandleInNamespace(targetHandle); if (target == null) { return null; } // validate node. if (!ValidateNode(systemContext, target)) { return null; } // read the attributes. List values = target.ReadAttributes( systemContext, Attributes.WriteMask, Attributes.UserWriteMask, Attributes.DataType, Attributes.ValueRank, Attributes.ArrayDimensions, Attributes.AccessLevel, Attributes.UserAccessLevel, Attributes.EventNotifier, Attributes.Executable, Attributes.UserExecutable); // construct the metadata object. var metadata = new NodeMetadata(target, target.NodeId) { NodeClass = target.NodeClass, BrowseName = target.BrowseName, DisplayName = target.DisplayName }; if (values[0] != null && values[1] != null) { metadata.WriteMask = (AttributeWriteMask)(((uint)values[0]) & ((uint)values[1])); } metadata.DataType = (NodeId)values[2]; if (values[3] != null) { metadata.ValueRank = (int)values[3]; } metadata.ArrayDimensions = (IList)values[4]; if (values[5] != null && values[6] != null) { metadata.AccessLevel = (byte)(((byte)values[5]) & ((byte)values[6])); } if (values[7] != null) { metadata.EventNotifier = (byte)values[7]; } if (values[8] != null && values[9] != null) { metadata.Executable = ((bool)values[8]) && ((bool)values[9]); } // get instance references. if (target is BaseInstanceState instance) { metadata.TypeDefinition = instance.TypeDefinitionId; metadata.ModellingRule = instance.ModellingRuleId; } // fill in the common attributes. return metadata; } } /// /// Browses the references from a node managed by the node manager. /// /// /// /// /// /// The continuation point is created for every browse operation and contains the browse parameters. /// The node manager can store its state information in the Data and Index properties. /// /// is null. /// public virtual void Browse( OperationContext context, ref ContinuationPoint continuationPoint, IList references) { ArgumentNullException.ThrowIfNull(continuationPoint); ArgumentNullException.ThrowIfNull(references); // check for view. if (!ViewDescription.IsDefault(continuationPoint.View)) { throw new ServiceResultException(StatusCodes.BadViewIdUnknown); } ServerSystemContext systemContext = SystemContext.Copy(context); lock (Lock) { // verify that the node exists. NodeState source = IsHandleInNamespace(continuationPoint.NodeToBrowse) ?? throw new ServiceResultException(StatusCodes.BadNodeIdUnknown); // validate node. if (!ValidateNode(systemContext, source)) { throw new ServiceResultException(StatusCodes.BadNodeIdUnknown); } // check for previous continuation point. INodeBrowser browser = continuationPoint.Data as INodeBrowser ?? source.CreateBrowser( systemContext, continuationPoint.View, continuationPoint.ReferenceTypeId, continuationPoint.IncludeSubtypes, continuationPoint.BrowseDirection, null, null, false); // apply filters to references. for (IReference reference = browser.Next(); reference != null; reference = browser.Next()) { // create the type definition reference. ReferenceDescription description = GetReferenceDescription( context, reference, continuationPoint); if (description == null) { continue; } // check if limit reached. if (continuationPoint.MaxResultsToReturn != 0 && references.Count >= continuationPoint.MaxResultsToReturn) { browser.Push(reference); continuationPoint.Data = browser; return; } references.Add(description); } // release the continuation point if all done. continuationPoint.Dispose(); continuationPoint = null; } } /// /// Returns the references for the node that meets the criteria specified. /// /// /// /// private ReferenceDescription GetReferenceDescription( OperationContext context, IReference reference, ContinuationPoint continuationPoint) { // create the type definition reference. var description = new ReferenceDescription { NodeId = reference.TargetId }; description.SetReferenceType( continuationPoint.ResultMask, reference.ReferenceTypeId, !reference.IsInverse); // do not cache target parameters for remote nodes. if (reference.TargetId.IsAbsolute) { // only return remote references if no node class filter is specified. if (continuationPoint.NodeClassMask != 0) { return null; } return description; } NodeState target = null; // check for local reference. if (reference is NodeStateReference referenceInfo) { target = referenceInfo.Target; } // check for internal reference. if (target == null) { var targetId = (NodeId)reference.TargetId; if (IsNodeIdInNamespace(targetId) && !PredefinedNodes.TryGetValue(targetId, out target)) { target = null; } } // the target may be a reference to a node in another node manager. In these cases // the target attributes must be fetched by the caller. The Unfiltered flag tells the // caller to do that. if (target == null) { description.Unfiltered = true; return description; } // apply node class filter. if (continuationPoint.NodeClassMask != 0 && ((continuationPoint.NodeClassMask & (uint)target.NodeClass) == 0)) { return null; } NodeId typeDefinition = null; if (target is BaseInstanceState instance) { typeDefinition = instance.TypeDefinitionId; } // set target attributes. description.SetTargetAttributes( continuationPoint.ResultMask, target.NodeClass, target.BrowseName, target.DisplayName, typeDefinition); return description; } /// /// Returns the target of the specified browse path fragment(s). /// /// /// /// /// /// /// /// If reference exists but the node manager does not know the browse name it must /// return the NodeId as an unresolvedTargetIds. The caller will try to check the /// browse name. /// public virtual void TranslateBrowsePath( OperationContext context, object sourceHandle, RelativePathElement relativePath, IList targetIds, IList unresolvedTargetIds) { ServerSystemContext systemContext = SystemContext.Copy(context); IDictionary operationCache = new NodeIdDictionary(); lock (Lock) { // verify that the node exists. NodeState source = IsHandleInNamespace(sourceHandle); if (source == null) { return; } // validate node. if (!ValidateNode(systemContext, source)) { return; } // get list of references that relative path. INodeBrowser browser = source.CreateBrowser( systemContext, null, relativePath.ReferenceTypeId, relativePath.IncludeSubtypes, relativePath.IsInverse ? BrowseDirection.Inverse : BrowseDirection.Forward, relativePath.TargetName, null, false); // check the browse names. try { for (IReference reference = browser.Next(); reference != null; reference = browser.Next()) { // ignore unknown external references. if (reference.TargetId.IsAbsolute) { continue; } NodeState target = null; // check for local reference. if (reference is NodeStateReference referenceInfo) { target = referenceInfo.Target; } if (target == null) { var targetId = (NodeId)reference.TargetId; // the target may be a reference to a node in another node manager. if (!IsNodeIdInNamespace(targetId)) { unresolvedTargetIds.Add((NodeId)reference.TargetId); continue; } // look up the target manually. target = GetManagerHandle( systemContext, targetId, operationCache) as NodeState; if (target == null) { continue; } } // check browse name. if (target.BrowseName == relativePath.TargetName) { // ensure duplicate node ids are not added. if (!targetIds.Contains(reference.TargetId)) { targetIds.Add(reference.TargetId); } } } } finally { browser.Dispose(); } } } /// /// Reads the value for the specified attribute. /// /// /// /// /// /// public virtual void Read( OperationContext context, double maxAge, IList nodesToRead, IList values, IList errors) { ServerSystemContext systemContext = SystemContext.Copy(context); IDictionary operationCache = new NodeIdDictionary(); var nodesToValidate = new List(); lock (Lock) { for (int ii = 0; ii < nodesToRead.Count; ii++) { ReadValueId nodeToRead = nodesToRead[ii]; // skip items that have already been processed. if (nodeToRead.Processed) { continue; } // check for valid handle. if (GetManagerHandle( systemContext, nodeToRead.NodeId, operationCache) is not NodeState source) { continue; } // owned by this node manager. nodeToRead.Processed = true; // create an initial value. DataValue value = values[ii] = new DataValue(); value.Value = null; value.ServerTimestamp = DateTime.UtcNow; value.SourceTimestamp = DateTime.MinValue; value.StatusCode = StatusCodes.Good; // check if the node is ready for reading. if (source.ValidationRequired) { errors[ii] = StatusCodes.BadNodeIdUnknown; // must validate node in a separate operation. var operation = new ReadWriteOperationState { Source = source, Index = ii }; nodesToValidate.Add(operation); continue; } // read the attribute value. errors[ii] = source.ReadAttribute( systemContext, nodeToRead.AttributeId, nodeToRead.ParsedIndexRange, nodeToRead.DataEncoding, value); } // check for nothing to do. if (nodesToValidate.Count == 0) { return; } // validates the nodes (reads values from the underlying data source if required). for (int ii = 0; ii < nodesToValidate.Count; ii++) { ReadWriteOperationState operation = nodesToValidate[ii]; if (!ValidateNode(systemContext, operation.Source)) { continue; } ReadValueId nodeToRead = nodesToRead[operation.Index]; DataValue value = values[operation.Index]; // update the attribute value. errors[operation.Index] = operation.Source.ReadAttribute( systemContext, nodeToRead.AttributeId, nodeToRead.ParsedIndexRange, nodeToRead.DataEncoding, value); } } } /// /// Stores the state of a call method operation. /// private struct ReadWriteOperationState { public NodeState Source; public int Index; } /// /// Verifies that the specified node exists. /// /// /// protected virtual bool ValidateNode(ServerSystemContext context, NodeState node) { // validate node only if required. if (node.ValidationRequired) { return node.Validate(context); } return true; } /// /// Reads the history for the specified nodes. /// /// /// /// /// /// /// /// public virtual void HistoryRead( OperationContext context, HistoryReadDetails details, TimestampsToReturn timestampsToReturn, bool releaseContinuationPoints, IList nodesToRead, IList results, IList errors) { ServerSystemContext systemContext = SystemContext.Copy(context); IDictionary operationCache = new NodeIdDictionary(); var nodesToValidate = new List(); var readsToComplete = new List(); lock (Lock) { for (int ii = 0; ii < nodesToRead.Count; ii++) { HistoryReadValueId nodeToRead = nodesToRead[ii]; // skip items that have already been processed. if (nodeToRead.Processed) { continue; } // check for valid handle. if (GetManagerHandle( systemContext, nodeToRead.NodeId, operationCache) is not NodeState source) { continue; } // owned by this node manager. nodeToRead.Processed = true; // only variables supported. if (source is not BaseVariableState variable) { errors[ii] = StatusCodes.BadHistoryOperationUnsupported; continue; } results[ii] = new HistoryReadResult(); var operation = new ReadWriteOperationState { Source = source, Index = ii }; // check if the node is ready for reading. if (source.ValidationRequired) { // must validate node in a separate operation. errors[ii] = StatusCodes.BadNodeIdUnknown; nodesToValidate.Add(operation); continue; } // read the data. readsToComplete.Add(operation); } // validates the nodes (reads values from the underlying data source if required). for (int ii = 0; ii < nodesToValidate.Count; ii++) { ReadWriteOperationState operation = nodesToValidate[ii]; if (!ValidateNode(systemContext, operation.Source)) { continue; } readsToComplete.Add(operation); } } // reads the data without holding onto the lock. for (int ii = 0; ii < readsToComplete.Count; ii++) { ReadWriteOperationState operation = readsToComplete[ii]; errors[operation.Index] = HistoryRead( systemContext, operation.Source, details, timestampsToReturn, releaseContinuationPoints, nodesToRead[operation.Index], results[operation.Index]); } } /// /// Reads the history for a single node which has already been validated. /// /// /// /// /// /// /// /// protected virtual ServiceResult HistoryRead( ISystemContext context, NodeState source, HistoryReadDetails details, TimestampsToReturn timestampsToReturn, bool releaseContinuationPoints, HistoryReadValueId nodesToRead, HistoryReadResult result) { // check for variable. if (source is not BaseVariableState variable) { return StatusCodes.BadHistoryOperationUnsupported; } // check for access. lock (Lock) { if ((variable.AccessLevel & AccessLevels.HistoryRead) == 0) { return StatusCodes.BadNotReadable; } } // handle read raw. if (details is ReadRawModifiedDetails readRawDetails) { return HistoryReadRaw( context, variable, readRawDetails, timestampsToReturn, releaseContinuationPoints, nodesToRead, result); } // handle read processed. if (details is ReadProcessedDetails readProcessedDetails) { return HistoryReadProcessed( context, variable, readProcessedDetails, timestampsToReturn, releaseContinuationPoints, nodesToRead, result); } // handle read processed. if (details is ReadAtTimeDetails readAtTimeDetails) { return HistoryReadAtTime( context, variable, readAtTimeDetails, timestampsToReturn, releaseContinuationPoints, nodesToRead, result); } return StatusCodes.BadHistoryOperationUnsupported; } /// /// Reads the raw history for the variable value. /// /// /// /// /// /// /// /// protected virtual ServiceResult HistoryReadRaw( ISystemContext context, BaseVariableState source, ReadRawModifiedDetails details, TimestampsToReturn timestampsToReturn, bool releaseContinuationPoints, HistoryReadValueId nodeToRead, HistoryReadResult result) { return StatusCodes.BadHistoryOperationUnsupported; } /// /// Reads the processed history for the variable value. /// /// /// /// /// /// /// /// protected virtual ServiceResult HistoryReadProcessed( ISystemContext context, BaseVariableState source, ReadProcessedDetails details, TimestampsToReturn timestampsToReturn, bool releaseContinuationPoints, HistoryReadValueId nodeToRead, HistoryReadResult result) { return StatusCodes.BadHistoryOperationUnsupported; } /// /// Reads the history for the variable value. /// /// /// /// /// /// /// /// protected virtual ServiceResult HistoryReadAtTime( ISystemContext context, BaseVariableState source, ReadAtTimeDetails details, TimestampsToReturn timestampsToReturn, bool releaseContinuationPoints, HistoryReadValueId nodeToRead, HistoryReadResult result) { return StatusCodes.BadHistoryOperationUnsupported; } /// /// Writes the value for the specified attributes. /// /// /// /// public virtual void Write( OperationContext context, IList nodesToWrite, IList errors) { ServerSystemContext systemContext = SystemContext.Copy(context); IDictionary operationCache = new NodeIdDictionary(); var nodesToValidate = new List(); lock (Lock) { for (int ii = 0; ii < nodesToWrite.Count; ii++) { WriteValue nodeToWrite = nodesToWrite[ii]; // skip items that have already been processed. if (nodeToWrite.Processed) { continue; } // check for valid handle. if (GetManagerHandle( systemContext, nodeToWrite.NodeId, operationCache) is not NodeState source) { continue; } // owned by this node manager. nodeToWrite.Processed = true; // index range is not supported. if (!string.IsNullOrEmpty(nodeToWrite.IndexRange)) { errors[ii] = StatusCodes.BadWriteNotSupported; continue; } // check if the node is ready for reading. if (source.ValidationRequired) { errors[ii] = StatusCodes.BadNodeIdUnknown; // must validate node in a separate operation. var operation = new ReadWriteOperationState { Source = source, Index = ii }; nodesToValidate.Add(operation); continue; } // write the attribute value. errors[ii] = source.WriteAttribute( systemContext, nodeToWrite.AttributeId, nodeToWrite.ParsedIndexRange, nodeToWrite.Value); // updates to source finished - report changes to monitored items. source.ClearChangeMasks(systemContext, false); } // check for nothing to do. if (nodesToValidate.Count == 0) { return; } // validates the nodes (reads values from the underlying data source if required). for (int ii = 0; ii < nodesToValidate.Count; ii++) { ReadWriteOperationState operation = nodesToValidate[ii]; if (!ValidateNode(systemContext, operation.Source)) { continue; } WriteValue nodeToWrite = nodesToWrite[operation.Index]; // write the attribute value. errors[operation.Index] = operation.Source.WriteAttribute( systemContext, nodeToWrite.AttributeId, nodeToWrite.ParsedIndexRange, nodeToWrite.Value); // updates to source finished - report changes to monitored items. operation.Source.ClearChangeMasks(systemContext, false); } } } /// /// Updates the history for the specified nodes. /// /// /// /// /// /// public virtual void HistoryUpdate( OperationContext context, Type detailsType, IList nodesToUpdate, IList results, IList errors) { ServerSystemContext systemContext = SystemContext.Copy(context); IDictionary operationCache = new NodeIdDictionary(); var nodesToValidate = new List(); lock (Lock) { for (int ii = 0; ii < nodesToUpdate.Count; ii++) { HistoryUpdateDetails nodeToUpdate = nodesToUpdate[ii]; // skip items that have already been processed. if (nodeToUpdate.Processed) { continue; } // check for valid handle. if (GetManagerHandle( systemContext, nodeToUpdate.NodeId, operationCache) is not NodeState source) { continue; } // owned by this node manager. nodeToUpdate.Processed = true; // check if the node is ready for reading. if (source.ValidationRequired) { errors[ii] = StatusCodes.BadNodeIdUnknown; // must validate node in a separate operation. var operation = new ReadWriteOperationState { Source = source, Index = ii }; nodesToValidate.Add(operation); continue; } // historical data not available. errors[ii] = StatusCodes.BadHistoryOperationUnsupported; } // check for nothing to do. if (nodesToValidate.Count == 0) { return; } // validates the nodes (reads values from the underlying data source if required). for (int ii = 0; ii < nodesToValidate.Count; ii++) { ReadWriteOperationState operation = nodesToValidate[ii]; if (!ValidateNode(systemContext, operation.Source)) { continue; } // historical data not available. errors[ii] = StatusCodes.BadHistoryOperationUnsupported; } } } /// /// Calls a method on the specified nodes. /// /// /// /// /// public virtual void Call( OperationContext context, IList methodsToCall, IList results, IList errors) { ServerSystemContext systemContext = SystemContext.Copy(context); IDictionary operationCache = new NodeIdDictionary(); var nodesToValidate = new List(); lock (Lock) { for (int ii = 0; ii < methodsToCall.Count; ii++) { CallMethodRequest methodToCall = methodsToCall[ii]; // skip items that have already been processed. if (methodToCall.Processed) { continue; } // check for valid handle. if (GetManagerHandle( systemContext, methodToCall.ObjectId, operationCache) is not NodeState source) { continue; } // owned by this node manager. methodToCall.Processed = true; // find the method. MethodState method = source.FindMethod(systemContext, methodToCall.MethodId); if (method == null) { // check for loose coupling. if (source.ReferenceExists( ReferenceTypeIds.HasComponent, false, methodToCall.MethodId)) { method = (MethodState)FindPredefinedNode( methodToCall.MethodId, typeof(MethodState)); } if (method == null) { errors[ii] = StatusCodes.BadMethodInvalid; continue; } } CallMethodResult result = results[ii] = new CallMethodResult(); // check if the node is ready for reading. if (source.ValidationRequired) { errors[ii] = StatusCodes.BadNodeIdUnknown; // must validate node in a separate operation. var operation = new CallOperationState { Source = source, Method = method, Index = ii }; nodesToValidate.Add(operation); continue; } // call the method. errors[ii] = Call(systemContext, methodToCall, source, method, result); } // check for nothing to do. if (nodesToValidate.Count == 0) { return; } // validates the nodes (reads values from the underlying data source if required). for (int ii = 0; ii < nodesToValidate.Count; ii++) { CallOperationState operation = nodesToValidate[ii]; // validate the object. if (!ValidateNode(systemContext, operation.Source)) { continue; } // call the method. CallMethodResult result = results[operation.Index]; errors[operation.Index] = Call( systemContext, methodsToCall[operation.Index], operation.Source, operation.Method, result); } } } /// /// Stores the state of a call method operation. /// private struct CallOperationState { public NodeState Source; public MethodState Method; public int Index; } /// /// Calls a method on an object. /// /// /// /// /// /// protected virtual ServiceResult Call( ISystemContext context, CallMethodRequest methodToCall, NodeState source, MethodState method, CallMethodResult result) { var systemContext = context as ServerSystemContext; var argumentErrors = new List(); var outputArguments = new VariantCollection(); ServiceResult error = method.Call( context, methodToCall.ObjectId, methodToCall.InputArguments, argumentErrors, outputArguments); if (ServiceResult.IsBad(error)) { return error; } // check for argument errors. bool argumentsValid = true; for (int jj = 0; jj < argumentErrors.Count; jj++) { ServiceResult argumentError = argumentErrors[jj]; if (argumentError != null) { result.InputArgumentResults.Add(argumentError.StatusCode); if (ServiceResult.IsBad(argumentError)) { argumentsValid = false; } } else { result.InputArgumentResults.Add(StatusCodes.Good); } // only fill in diagnostic info if it is requested. if ((systemContext.OperationContext.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0) { if (ServiceResult.IsBad(argumentError)) { argumentsValid = false; result.InputArgumentDiagnosticInfos.Add( new DiagnosticInfo( argumentError, systemContext.OperationContext.DiagnosticsMask, false, systemContext.OperationContext.StringTable)); } else { result.InputArgumentDiagnosticInfos.Add(null); } } } // check for validation errors. if (!argumentsValid) { result.StatusCode = StatusCodes.BadInvalidArgument; return result.StatusCode; } // do not return diagnostics if there are no errors. result.InputArgumentDiagnosticInfos.Clear(); // return output arguments. result.OutputArguments = outputArguments; return ServiceResult.Good; } /// /// Subscribes or unsubscribes to events produced by the specified source. /// /// /// /// /// /// /// /// This method is called when a event subscription is created or deletes. The node manager /// must start/stop reporting events for the specified object and all objects below it in /// the notifier hierarchy. /// public virtual ServiceResult SubscribeToEvents( OperationContext context, object sourceId, uint subscriptionId, IEventMonitoredItem monitoredItem, bool unsubscribe) { ServerSystemContext systemContext = SystemContext.Copy(context); lock (Lock) { // check for valid handle. NodeState source = IsHandleInNamespace(sourceId); if (source == null) { return StatusCodes.BadNodeIdInvalid; } // check if the object supports subscritions. if (sourceId is not BaseObjectState instance || instance.EventNotifier != EventNotifiers.SubscribeToEvents) { return StatusCodes.BadNotSupported; } var monitoredNode = instance.Handle as MonitoredNode; // handle unsubscribe. if (unsubscribe) { if (monitoredNode != null) { monitoredNode.UnsubscribeToEvents(systemContext, monitoredItem); // do any post processing. OnUnsubscribeToEvents(systemContext, monitoredNode, monitoredItem); } return ServiceResult.Good; } // subscribe to events. if (monitoredNode == null) { instance.Handle = monitoredNode = new MonitoredNode(Server, this, source); } monitoredNode.SubscribeToEvents(systemContext, monitoredItem); // do any post processing. OnSubscribeToEvents(systemContext, monitoredNode, monitoredItem); return ServiceResult.Good; } } /// /// Subscribes or unsubscribes to events produced by all event sources. /// /// /// /// /// /// /// This method is called when a event subscription is created or deleted. The node /// manager must start/stop reporting events for all objects that it manages. /// public virtual ServiceResult SubscribeToAllEvents( OperationContext context, uint subscriptionId, IEventMonitoredItem monitoredItem, bool unsubscribe) { ServerSystemContext systemContext = SystemContext.Copy(context); lock (Lock) { // update root notifiers. for (int ii = 0; ii < RootNotifiers.Count; ii++) { SubscribeToAllEvents( systemContext, monitoredItem, unsubscribe, RootNotifiers[ii]); } return ServiceResult.Good; } } /// /// Subscribes/unsubscribes to all events produced by the specified node. /// /// /// /// /// protected void SubscribeToAllEvents( ISystemContext systemContext, IEventMonitoredItem monitoredItem, bool unsubscribe, NodeState source) { var monitoredNode = source.Handle as MonitoredNode; // handle unsubscribe. if (unsubscribe) { if (monitoredNode != null) { monitoredNode.UnsubscribeToEvents(systemContext, monitoredItem); // do any post processing. OnUnsubscribeToEvents(systemContext, monitoredNode, monitoredItem); } return; } // subscribe to events. if (monitoredNode == null) { source.Handle = monitoredNode = new MonitoredNode(Server, this, source); } monitoredNode.SubscribeToEvents(systemContext, monitoredItem); // do any post processing. OnSubscribeToEvents(systemContext, monitoredNode, monitoredItem); } /// /// Does any processing after a monitored item is subscribed to. /// /// /// /// protected virtual void OnSubscribeToEvents( ISystemContext systemContext, MonitoredNode monitoredNode, IEventMonitoredItem monitoredItem) { // does nothing. } /// /// Does any processing after a monitored item is subscribed to. /// /// /// /// protected virtual void OnUnsubscribeToEvents( ISystemContext systemContext, MonitoredNode monitoredNode, IEventMonitoredItem monitoredItem) { // does nothing. } /// /// Tells the node manager to refresh any conditions associated with the specified monitored items. /// /// /// /// /// This method is called when the condition refresh method is called for a subscription. /// The node manager must create a refresh event for each condition monitored by the subscription. /// public virtual ServiceResult ConditionRefresh( OperationContext context, IList monitoredItems) { ServerSystemContext systemContext = SystemContext.Copy(context); lock (Lock) { for (int ii = 0; ii < monitoredItems.Count; ii++) { IEventMonitoredItem monitoredItem = monitoredItems[ii]; if (monitoredItem == null) { continue; } // check for global subscription. if (monitoredItem.MonitoringAllEvents) { for (int jj = 0; jj < RootNotifiers.Count; jj++) { if (RootNotifiers[jj].Handle is not MonitoredNode monitoredNode) { continue; } monitoredNode.ConditionRefresh(systemContext, monitoredItem); } } // check for subscription to local node. else { NodeState source = IsHandleInNamespace(monitoredItem.ManagerHandle); if (source == null) { continue; } if (source.Handle is not MonitoredNode monitoredNode) { continue; } monitoredNode.ConditionRefresh(systemContext, monitoredItem); } } } return ServiceResult.Good; } /// /// Creates a new set of monitored items for a set of variables. /// /// /// /// /// /// /// /// /// /// /// /// /// This method only handles data change subscriptions. Event subscriptions are created by the SDK. /// public virtual void CreateMonitoredItems( OperationContext context, uint subscriptionId, double publishingInterval, TimestampsToReturn timestampsToReturn, IList itemsToCreate, IList errors, IList filterErrors, IList monitoredItems, bool createDurable, ref long globalIdCounter) { ServerSystemContext systemContext = SystemContext.Copy(context); IDictionary operationCache = new NodeIdDictionary(); var nodesToValidate = new List(); lock (Lock) { for (int ii = 0; ii < itemsToCreate.Count; ii++) { MonitoredItemCreateRequest itemToCreate = itemsToCreate[ii]; // skip items that have already been processed. if (itemToCreate.Processed) { continue; } ReadValueId itemToMonitor = itemToCreate.ItemToMonitor; // check for valid handle. if (GetManagerHandle( systemContext, itemToMonitor.NodeId, operationCache) is not NodeState source) { continue; } // owned by this node manager. itemToCreate.Processed = true; // check if the node is ready for reading. if (source.ValidationRequired) { errors[ii] = StatusCodes.BadNodeIdUnknown; // must validate node in a separate operation. var operation = new ReadWriteOperationState { Source = source, Index = ii }; nodesToValidate.Add(operation); continue; } errors[ii] = CreateMonitoredItem( systemContext, source, subscriptionId, publishingInterval, context.DiagnosticsMask, timestampsToReturn, itemToCreate, createDurable, ref globalIdCounter, out MonitoringFilterResult filterError, out IMonitoredItem monitoredItem); // save any filter error details. filterErrors[ii] = filterError; if (ServiceResult.IsBad(errors[ii])) { continue; } // save the monitored item. monitoredItems[ii] = monitoredItem; } // check for nothing to do. if (nodesToValidate.Count == 0) { return; } // validates the nodes (reads values from the underlying data source if required). for (int ii = 0; ii < nodesToValidate.Count; ii++) { ReadWriteOperationState operation = nodesToValidate[ii]; // validate the object. if (!ValidateNode(systemContext, operation.Source)) { continue; } MonitoredItemCreateRequest itemToCreate = itemsToCreate[operation.Index]; errors[operation.Index] = CreateMonitoredItem( systemContext, operation.Source, subscriptionId, publishingInterval, context.DiagnosticsMask, timestampsToReturn, itemToCreate, createDurable, ref globalIdCounter, out MonitoringFilterResult filterError, out IMonitoredItem monitoredItem); // save any filter error details. filterErrors[operation.Index] = filterError; if (ServiceResult.IsBad(errors[operation.Index])) { continue; } // save the monitored item. monitoredItems[operation.Index] = monitoredItem; } } } /// /// Restore a set of monitored items after a restart. /// /// /// /// /// is null. /// public virtual void RestoreMonitoredItems( IList itemsToRestore, IList monitoredItems, IUserIdentity savedOwnerIdentity) { ArgumentNullException.ThrowIfNull(itemsToRestore); ArgumentNullException.ThrowIfNull(monitoredItems); if (Server.IsRunning) { throw new InvalidOperationException( "Subscription restore can only occur on startup"); } ServerSystemContext systemContext = SystemContext.Copy(); IDictionary operationCache = new NodeIdDictionary(); var nodesToValidate = new List(); lock (Lock) { for (int ii = 0; ii < itemsToRestore.Count; ii++) { IStoredMonitoredItem itemToCreate = itemsToRestore[ii]; // skip items that have already been processed. if (itemToCreate.IsRestored) { continue; } // check for valid handle. if (GetManagerHandle( systemContext, itemToCreate.NodeId, operationCache) is not NodeState source) { continue; } // owned by this node manager. itemToCreate.IsRestored = true; // check if the node is ready for reading. if (source.ValidationRequired) { // must validate node in a separate operation. var operation = new ReadWriteOperationState { Source = source, Index = ii }; nodesToValidate.Add(operation); continue; } bool success = RestoreMonitoredItem( systemContext, source, itemToCreate, out IMonitoredItem monitoredItem); if (!success) { continue; } // save the monitored item. monitoredItems[ii] = monitoredItem; } // check for nothing to do. if (nodesToValidate.Count == 0) { return; } // validates the nodes (reads values from the underlying data source if required). for (int ii = 0; ii < nodesToValidate.Count; ii++) { ReadWriteOperationState operation = nodesToValidate[ii]; // validate the object. if (!ValidateNode(systemContext, operation.Source)) { continue; } IStoredMonitoredItem itemToCreate = itemsToRestore[operation.Index]; bool success = RestoreMonitoredItem( systemContext, operation.Source, itemToCreate, out IMonitoredItem monitoredItem); if (!success) { continue; } // save the monitored item. monitoredItems[operation.Index] = monitoredItem; } } } /// /// Reads the initial value for a monitored item. /// /// The context. /// The monitored node. /// The monitored item. /// If the filters should be ignored. protected virtual ServiceResult ReadInitialValue( ISystemContext context, MonitoredNode node, IDataChangeMonitoredItem2 monitoredItem, bool ignoreFilters) { var initialValue = new DataValue { Value = null, ServerTimestamp = DateTime.UtcNow, SourceTimestamp = DateTime.MinValue, StatusCode = StatusCodes.BadWaitingForInitialData }; ServiceResult error = node.Node.ReadAttribute( context, monitoredItem.AttributeId, monitoredItem.IndexRange, monitoredItem.DataEncoding, initialValue); monitoredItem.QueueValue(initialValue, error, ignoreFilters); return error; } /// /// Validates a data change filter provided by the client. /// /// The system context. /// The node being monitored. /// The attribute being monitored. /// The requested monitoring filter. /// The validated data change filter. /// The EU range associated with the value if required by the filter. /// Any error condition. Good if no errors occurred. protected ServiceResult ValidateDataChangeFilter( ISystemContext context, NodeState source, uint attributeId, ExtensionObject requestedFilter, out DataChangeFilter filter, out Range range) { range = null; // check for valid filter type. filter = requestedFilter.Body as DataChangeFilter; if (filter == null) { return StatusCodes.BadMonitoredItemFilterUnsupported; } // only supported for value attributes. if (attributeId != Attributes.Value) { return StatusCodes.BadMonitoredItemFilterUnsupported; } // only supported for variables. if (source is not BaseVariableState variable) { return StatusCodes.BadMonitoredItemFilterUnsupported; } // check the datatype. if (filter.DeadbandType != (uint)DeadbandType.None) { BuiltInType builtInType = TypeInfo.GetBuiltInType( variable.DataType, Server.TypeTree); if (!TypeInfo.IsNumericType(builtInType)) { return StatusCodes.BadMonitoredItemFilterUnsupported; } } // validate filter. ServiceResult error = filter.Validate(); if (ServiceResult.IsBad(error)) { return error; } if (filter.DeadbandType == (uint)DeadbandType.Percent) { if (variable.FindChild( context, BrowseNames.EURange) is not BaseVariableState euRange) { return StatusCodes.BadMonitoredItemFilterUnsupported; } range = euRange.Value as Range; if (range == null) { return StatusCodes.BadMonitoredItemFilterUnsupported; } } // all good. return ServiceResult.Good; } /// /// Restore a single monitored Item after a restart /// /// /// /// /// /// true if sucesfully restored protected virtual bool RestoreMonitoredItem( ServerSystemContext context, NodeState source, IStoredMonitoredItem storedMonitoredItem, out IMonitoredItem monitoredItem) { // create monitored node. if (source.Handle is not MonitoredNode monitoredNode) { source.Handle = monitoredNode = new MonitoredNode(Server, this, source); } // check if the variable needs to be sampled. bool samplingRequired = false; if (storedMonitoredItem.AttributeId == Attributes.Value) { var variable = source as BaseVariableState; if (variable.MinimumSamplingInterval > 0) { storedMonitoredItem.SamplingInterval = CalculateSamplingInterval( variable, storedMonitoredItem.SamplingInterval); samplingRequired = true; } } // create the item. DataChangeMonitoredItem datachangeItem = monitoredNode.RestoreDataChangeItem( storedMonitoredItem); if (samplingRequired) { CreateSampledItem(storedMonitoredItem.SamplingInterval, datachangeItem); } // update monitored item list. monitoredItem = datachangeItem; return true; } /// /// Creates a new set of monitored items for a set of variables. /// /// /// /// /// /// /// /// /// /// /// /// /// /// This method only handles data change subscriptions. Event subscriptions are created by the SDK. /// protected virtual ServiceResult CreateMonitoredItem( ISystemContext context, NodeState source, uint subscriptionId, double publishingInterval, DiagnosticsMasks diagnosticsMasks, TimestampsToReturn timestampsToReturn, MonitoredItemCreateRequest itemToCreate, bool createDurable, ref long globalIdCounter, out MonitoringFilterResult filterError, out IMonitoredItem monitoredItem) { filterError = null; monitoredItem = null; // read initial value. var initialValue = new DataValue { Value = null, ServerTimestamp = DateTime.UtcNow, SourceTimestamp = DateTime.MinValue, StatusCode = StatusCodes.BadWaitingForInitialData }; ServiceResult error = source.ReadAttribute( context, itemToCreate.ItemToMonitor.AttributeId, itemToCreate.ItemToMonitor.ParsedIndexRange, itemToCreate.ItemToMonitor.DataEncoding, initialValue); if (ServiceResult.IsBad(error)) { if (error.StatusCode.Code is StatusCodes.BadAttributeIdInvalid or StatusCodes.BadDataEncodingInvalid or StatusCodes.BadDataEncodingUnsupported) { return error; } initialValue.StatusCode = error.StatusCode; _ = ServiceResult.Good; } // validate parameters. MonitoringParameters parameters = itemToCreate.RequestedParameters; // validate the data change filter. DataChangeFilter filter = null; Range range = null; if (!ExtensionObject.IsNull(parameters.Filter)) { error = ValidateDataChangeFilter( context, source, itemToCreate.ItemToMonitor.AttributeId, parameters.Filter, out filter, out range); if (ServiceResult.IsBad(error)) { return error; } } // create monitored node. if (source.Handle is not MonitoredNode monitoredNode) { source.Handle = monitoredNode = new MonitoredNode(Server, this, source); } // create a globally unique identifier. uint monitoredItemId = Utils.IncrementIdentifier(ref globalIdCounter); // determine the sampling interval. double samplingInterval = itemToCreate.RequestedParameters.SamplingInterval; if (samplingInterval < 0) { samplingInterval = publishingInterval; } // check if the variable needs to be sampled. bool samplingRequired = false; if (itemToCreate.ItemToMonitor.AttributeId == Attributes.Value) { var variable = source as BaseVariableState; if (variable.MinimumSamplingInterval > 0) { samplingInterval = CalculateSamplingInterval(variable, samplingInterval); samplingRequired = true; } } // create the item. DataChangeMonitoredItem datachangeItem = monitoredNode.CreateDataChangeItem( context, monitoredItemId, itemToCreate.ItemToMonitor.AttributeId, itemToCreate.ItemToMonitor.ParsedIndexRange, itemToCreate.ItemToMonitor.DataEncoding, diagnosticsMasks, timestampsToReturn, itemToCreate.MonitoringMode, itemToCreate.RequestedParameters.ClientHandle, samplingInterval, itemToCreate.RequestedParameters.QueueSize, itemToCreate.RequestedParameters.DiscardOldest, filter, range, false); if (samplingRequired) { CreateSampledItem(samplingInterval, datachangeItem); } // report the initial value. datachangeItem.QueueValue(initialValue, null, true); // do any post processing. OnCreateMonitoredItem(context, itemToCreate, monitoredNode, datachangeItem); // update monitored item list. monitoredItem = datachangeItem; return ServiceResult.Good; } /// /// Calculates the sampling interval. /// /// /// private double CalculateSamplingInterval( BaseVariableState variable, double samplingInterval) { if (samplingInterval < variable.MinimumSamplingInterval) { samplingInterval = variable.MinimumSamplingInterval; } if ((samplingInterval % _minimumSamplingInterval) != 0) { samplingInterval = Math.Truncate(samplingInterval / _minimumSamplingInterval); samplingInterval++; samplingInterval *= _minimumSamplingInterval; } return samplingInterval; } /// /// Creates a new sampled item. /// /// /// private void CreateSampledItem( double samplingInterval, DataChangeMonitoredItem monitoredItem) { _sampledItems.Add(monitoredItem); _samplingTimer ??= new Timer( DoSample, null, (int)_minimumSamplingInterval, (int)_minimumSamplingInterval); } /// /// Deletes a sampled item. /// /// private void DeleteSampledItem(DataChangeMonitoredItem monitoredItem) { for (int ii = 0; ii < _sampledItems.Count; ii++) { if (ReferenceEquals(monitoredItem, _sampledItems[ii])) { _sampledItems.RemoveAt(ii); break; } } if (_sampledItems.Count == 0 && _samplingTimer != null) { _samplingTimer.Dispose(); _samplingTimer = null; } } /// /// Polls each monitored item which requires sample. /// /// private void DoSample(object state) { try { lock (Lock) { for (int ii = 0; ii < _sampledItems.Count; ii++) { DataChangeMonitoredItem monitoredItem = _sampledItems[ii]; if (monitoredItem.TimeToNextSample < _minimumSamplingInterval) { monitoredItem.ValueChanged(SystemContext); } } } } catch (Exception e) { Utils.LogError(e, "Unexpected error during diagnostics scan."); } } /// /// Does any processing after a monitored item is created. /// /// /// /// /// protected virtual void OnCreateMonitoredItem( ISystemContext systemContext, MonitoredItemCreateRequest itemToCreate, MonitoredNode monitoredNode, DataChangeMonitoredItem monitoredItem) { // does nothing. } /// /// Modifies the parameters for a set of monitored items. /// /// /// /// /// /// /// public virtual void ModifyMonitoredItems( OperationContext context, TimestampsToReturn timestampsToReturn, IList monitoredItems, IList itemsToModify, IList errors, IList filterErrors) { ServerSystemContext systemContext = SystemContext.Copy(context); lock (Lock) { for (int ii = 0; ii < monitoredItems.Count; ii++) { MonitoredItemModifyRequest itemToModify = itemsToModify[ii]; // skip items that have already been processed. if (itemToModify.Processed) { continue; } // modify the monitored item. errors[ii] = ModifyMonitoredItem( systemContext, context.DiagnosticsMask, timestampsToReturn, monitoredItems[ii], itemToModify, out MonitoringFilterResult filterError); // save any filter error details. filterErrors[ii] = filterError; } } } /// /// Modifies the parameters for a monitored item. /// /// /// /// /// /// /// protected virtual ServiceResult ModifyMonitoredItem( ISystemContext context, DiagnosticsMasks diagnosticsMasks, TimestampsToReturn timestampsToReturn, IMonitoredItem monitoredItem, MonitoredItemModifyRequest itemToModify, out MonitoringFilterResult filterError) { filterError = null; // check for valid handle. if (monitoredItem.ManagerHandle is not MonitoredNode monitoredNode) { return ServiceResult.Good; } if (IsHandleInNamespace(monitoredNode.Node) == null) { return ServiceResult.Good; } // owned by this node manager. itemToModify.Processed = true; // check for valid monitored item. var datachangeItem = monitoredItem as DataChangeMonitoredItem; // validate parameters. MonitoringParameters parameters = itemToModify.RequestedParameters; // validate the data change filter. DataChangeFilter filter = null; Range range = null; ServiceResult error; if (!ExtensionObject.IsNull(parameters.Filter)) { error = ValidateDataChangeFilter( context, monitoredNode.Node, datachangeItem.AttributeId, parameters.Filter, out filter, out range); if (ServiceResult.IsBad(error)) { return error; } } double previousSamplingInterval = datachangeItem.SamplingInterval; // check if the variable needs to be sampled. double samplingInterval = itemToModify.RequestedParameters.SamplingInterval; if (datachangeItem.AttributeId == Attributes.Value) { var variable = monitoredNode.Node as BaseVariableState; if (variable.MinimumSamplingInterval > 0) { samplingInterval = CalculateSamplingInterval(variable, samplingInterval); } } // modify the monitored item parameters. _ = datachangeItem.Modify( diagnosticsMasks, timestampsToReturn, itemToModify.RequestedParameters.ClientHandle, samplingInterval, itemToModify.RequestedParameters.QueueSize, itemToModify.RequestedParameters.DiscardOldest, filter, range); // do any post processing. OnModifyMonitoredItem( context, itemToModify, monitoredNode, datachangeItem, previousSamplingInterval); return ServiceResult.Good; } /// /// Does any processing after a monitored item is created. /// /// /// /// /// /// protected virtual void OnModifyMonitoredItem( ISystemContext systemContext, MonitoredItemModifyRequest itemToModify, MonitoredNode monitoredNode, DataChangeMonitoredItem monitoredItem, double previousSamplingInterval) { // does nothing. } /// /// Deletes a set of monitored items. /// /// /// /// /// public virtual void DeleteMonitoredItems( OperationContext context, IList monitoredItems, IList processedItems, IList errors) { ServerSystemContext systemContext = SystemContext.Copy(context); lock (Lock) { for (int ii = 0; ii < monitoredItems.Count; ii++) { // skip items that have already been processed. if (processedItems[ii]) { continue; } // delete the monitored item. errors[ii] = DeleteMonitoredItem( systemContext, monitoredItems[ii], out bool processed); // indicate whether it was processed or not. processedItems[ii] = processed; } } } /// /// Deletes a monitored item. /// /// /// /// protected virtual ServiceResult DeleteMonitoredItem( ISystemContext context, IMonitoredItem monitoredItem, out bool processed) { processed = false; // check for valid handle. if (monitoredItem.ManagerHandle is not MonitoredNode monitoredNode) { return ServiceResult.Good; } if (IsHandleInNamespace(monitoredNode.Node) == null) { return ServiceResult.Good; } // owned by this node manager. processed = true; // check for valid monitored item. var datachangeItem = monitoredItem as DataChangeMonitoredItem; // check if the variable needs to be sampled. if (datachangeItem.AttributeId == Attributes.Value) { var variable = monitoredNode.Node as BaseVariableState; if (variable.MinimumSamplingInterval > 0) { DeleteSampledItem(datachangeItem); } } // remove item. monitoredNode.DeleteItem(datachangeItem); // do any post processing. OnDeleteMonitoredItem(context, monitoredNode, datachangeItem); return ServiceResult.Good; } /// /// Does any processing after a monitored item is deleted. /// /// /// /// protected virtual void OnDeleteMonitoredItem( ISystemContext systemContext, MonitoredNode monitoredNode, DataChangeMonitoredItem monitoredItem) { // does nothing. } /// /// Transfers a set of monitored items. /// /// The context. /// Whether the subscription should send initial values after transfer. /// The set of monitoring items to update. /// The list of bool with items that were already processed. /// Any errors. public virtual void TransferMonitoredItems( OperationContext context, bool sendInitialValues, IList monitoredItems, IList processedItems, IList errors) { ServerSystemContext systemContext = SystemContext.Copy(context); IList transferredItems = []; lock (Lock) { for (int ii = 0; ii < monitoredItems.Count; ii++) { // skip items that have already been processed. if (processedItems[ii] || monitoredItems[ii] == null) { continue; } // check handle. // check for valid handle. if (monitoredItems[ii].ManagerHandle is not MonitoredNode monitoredNode) { continue; } // owned by this node manager. processedItems[ii] = true; transferredItems.Add(monitoredItems[ii]); if (sendInitialValues) { monitoredItems[ii].SetupResendDataTrigger(); } errors[ii] = StatusCodes.Good; } } // do any post processing. OnMonitoredItemsTransferred(systemContext, transferredItems); } /// /// Called after transfer of MonitoredItems. /// /// The context. /// The transferred monitored items. protected virtual void OnMonitoredItemsTransferred( ServerSystemContext context, IList monitoredItems) { // overridden by the sub-class. } /// /// Changes the monitoring mode for a set of monitored items. /// /// /// /// /// /// public virtual void SetMonitoringMode( OperationContext context, MonitoringMode monitoringMode, IList monitoredItems, IList processedItems, IList errors) { ServerSystemContext systemContext = SystemContext.Copy(context); lock (Lock) { for (int ii = 0; ii < monitoredItems.Count; ii++) { // skip items that have already been processed. if (processedItems[ii]) { continue; } // update monitoring mode. errors[ii] = SetMonitoringMode( systemContext, monitoredItems[ii], monitoringMode, out bool processed); // indicate whether it was processed or not. processedItems[ii] = processed; } } } /// /// Changes the monitoring mode for an item. /// /// /// /// /// protected virtual ServiceResult SetMonitoringMode( ISystemContext context, IMonitoredItem monitoredItem, MonitoringMode monitoringMode, out bool processed) { processed = false; // check for valid handle. if (monitoredItem.ManagerHandle is not MonitoredNode monitoredNode) { return ServiceResult.Good; } if (IsHandleInNamespace(monitoredNode.Node) == null) { return ServiceResult.Good; } // owned by this node manager. processed = true; // check for valid monitored item. var datachangeItem = monitoredItem as DataChangeMonitoredItem; // update monitoring mode. MonitoringMode previousMode = datachangeItem.SetMonitoringMode(monitoringMode); // need to provide an immediate update after enabling. if (previousMode == MonitoringMode.Disabled && monitoringMode != MonitoringMode.Disabled) { ReadInitialValue(context, monitoredNode, datachangeItem, false); } // do any post processing. OnSetMonitoringMode( context, monitoredNode, datachangeItem, previousMode, monitoringMode); return ServiceResult.Good; } /// /// Does any processing after a monitored item is created. /// /// /// /// /// /// protected virtual void OnSetMonitoringMode( ISystemContext systemContext, MonitoredNode monitoredNode, DataChangeMonitoredItem monitoredItem, MonitoringMode previousMode, MonitoringMode currentMode) { // does nothing. } private IList _namespaceUris; private ushort[] _namespaceIndexes; private Timer _samplingTimer; private readonly List _sampledItems; private readonly double _minimumSamplingInterval; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DataAccess/BlockState.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DataAccess { using Opc.Ua; using Opc.Ua.Server; using System.Collections.Generic; /// /// A object which maps a block to a UA object. /// public class BlockState : BaseObjectState { /// /// Initializes a new instance of the class. /// /// The context. /// The node id. /// The block. public BlockState( DataAccessNodeManager nodeManager, NodeId nodeId, UnderlyingSystemBlock block) : base(null) { _blockId = block.Id; _nodeManager = nodeManager; SymbolicName = block.Name; NodeId = nodeId; BrowseName = new QualifiedName(block.Name, nodeId.NamespaceIndex); DisplayName = new LocalizedText(block.Name); Description = null; WriteMask = 0; UserWriteMask = 0; EventNotifier = EventNotifiers.None; if (nodeManager.SystemContext.SystemHandle is UnderlyingSystem system) { var tags = block.GetTags(); for (var ii = 0; ii < tags.Count; ii++) { var variable = CreateVariable(nodeManager.SystemContext, tags[ii]); AddChild(variable); variable.OnSimpleWriteValue = OnWriteTagValue; } } } /// /// Starts the monitoring the block. /// /// The context. public void StartMonitoring(ServerSystemContext context) { if (_monitoringCount == 0 && context.SystemHandle is UnderlyingSystem system) { var block = system.FindBlock(_blockId); block?.StartMonitoring(OnTagsChanged); } _monitoringCount++; } /// /// Stop the monitoring the block. /// /// The context. public bool StopMonitoring(ServerSystemContext context) { _monitoringCount--; if (_monitoringCount == 0 && context.SystemHandle is UnderlyingSystem system) { var block = system.FindBlock(_blockId); block?.StopMonitoring(); } return _monitoringCount != 0; } /// /// Used to receive notifications when the value attribute is read or written. /// /// /// /// public ServiceResult OnWriteTagValue( ISystemContext context, NodeState node, ref object value) { if (context.SystemHandle is not UnderlyingSystem system) { return StatusCodes.BadCommunicationError; } var block = system.FindBlock(_blockId); if (block == null) { return StatusCodes.BadNodeIdUnknown; } var error = block.WriteTagValue(node.SymbolicName, value); if (error != 0) { // the simulator uses UA status codes so there is no need for a mapping table. return error; } return ServiceResult.Good; } /// /// Called when one or more tags changes. /// /// The tags. private void OnTagsChanged(IList tags) { lock (_nodeManager.Lock) { for (var ii = 0; ii < tags.Count; ii++) { if (FindChildBySymbolicName(_nodeManager.SystemContext, tags[ii].Name) is BaseVariableState variable) { UpdateVariable(_nodeManager.SystemContext, tags[ii], variable); } } ClearChangeMasks(_nodeManager.SystemContext, true); } } /// /// Populates the browser with references that meet the criteria. /// /// The context for the system being accessed. /// The browser to populate. protected override void PopulateBrowser(ISystemContext context, NodeBrowser browser) { base.PopulateBrowser(context, browser); // check if the parent segments need to be returned. if (browser.IsRequired(ReferenceTypeIds.Organizes, true)) { if (context.SystemHandle is not UnderlyingSystem system) { return; } // add reference for each segment. var segments = system.FindSegmentsForBlock(_blockId); for (var ii = 0; ii < segments.Count; ii++) { browser.Add(ReferenceTypeIds.Organizes, true, ModelUtils.ConstructIdForSegment(segments[ii].Id, NodeId.NamespaceIndex)); } } } /// /// Creates a variable from a tag. /// /// The context. /// The tag. /// The variable that represents the tag. private BaseDataVariableState CreateVariable(ISystemContext context, UnderlyingSystemTag tag) { // create the variable type based on the tag type. BaseDataVariableState variable; switch (tag.TagType) { case UnderlyingSystemTagType.Analog: { var node = new AnalogItemState(this); if (tag.EngineeringUnits != null) { node.EngineeringUnits = new PropertyState(node); } if (tag.EuRange.Length >= 4) { node.InstrumentRange = new PropertyState(node); } variable = node; break; } case UnderlyingSystemTagType.Digital: { variable = new TwoStateDiscreteState(this); break; } case UnderlyingSystemTagType.Enumerated: { var node = new MultiStateDiscreteState(this); if (tag.Labels != null) { node.EnumStrings = new PropertyState(node); } variable = node; break; } default: { variable = new DataItemState(this); break; } } // set the symbolic name and reference types. variable.SymbolicName = tag.Name; variable.ReferenceTypeId = ReferenceTypeIds.HasComponent; // initialize the variable from the type model. variable.Create( context, null, new QualifiedName(tag.Name, BrowseName.NamespaceIndex), null, true); // update the variable values. UpdateVariable(context, tag, variable); return variable; } /// /// Updates a variable from a tag. /// /// The context. /// The tag. /// The variable to update. private void UpdateVariable(ISystemContext context, UnderlyingSystemTag tag, BaseVariableState variable) { System.Diagnostics.Contracts.Contract.Assume(context != null); variable.Description = tag.Description; variable.Value = tag.Value; variable.Timestamp = tag.Timestamp; switch (tag.DataType) { case UnderlyingSystemDataType.Integer1: { variable.DataType = DataTypes.SByte; break; } case UnderlyingSystemDataType.Integer2: { variable.DataType = DataTypes.Int16; break; } case UnderlyingSystemDataType.Integer4: { variable.DataType = DataTypes.Int32; break; } case UnderlyingSystemDataType.Real4: { variable.DataType = DataTypes.Float; break; } case UnderlyingSystemDataType.String: { variable.DataType = DataTypes.String; break; } } variable.ValueRank = ValueRanks.Scalar; variable.ArrayDimensions = null; if (tag.IsWriteable) { variable.AccessLevel = AccessLevels.CurrentReadOrWrite; variable.UserAccessLevel = AccessLevels.CurrentReadOrWrite; } else { variable.AccessLevel = AccessLevels.CurrentRead; variable.UserAccessLevel = AccessLevels.CurrentRead; } variable.MinimumSamplingInterval = MinimumSamplingIntervals.Continuous; variable.Historizing = false; switch (tag.TagType) { case UnderlyingSystemTagType.Analog: { var node = variable as AnalogItemState; if (tag.EuRange != null) { if (tag.EuRange.Length >= 2 && node.EURange != null) { node.EURange.Value = new Range(tag.EuRange[0], tag.EuRange[1]); node.EURange.Timestamp = tag.Block.Timestamp; } if (tag.EuRange.Length >= 4 && node.InstrumentRange != null) { node.InstrumentRange.Value = new Range(tag.EuRange[2], tag.EuRange[3]); node.InstrumentRange.Timestamp = tag.Block.Timestamp; } } if (!string.IsNullOrEmpty(tag.EngineeringUnits) && node.EngineeringUnits != null) { node.EngineeringUnits.Value = new EUInformation { DisplayName = tag.EngineeringUnits, NamespaceUri = Namespaces.DataAccess }; node.EngineeringUnits.Timestamp = tag.Block.Timestamp; } break; } case UnderlyingSystemTagType.Digital: { var node = variable as TwoStateDiscreteState; if (tag.Labels != null && node.TrueState != null && node.FalseState != null && tag.Labels.Length >= 2) { node.TrueState.Value = new LocalizedText(tag.Labels[0]); node.TrueState.Timestamp = tag.Block.Timestamp; node.FalseState.Value = new LocalizedText(tag.Labels[1]); node.FalseState.Timestamp = tag.Block.Timestamp; } break; } case UnderlyingSystemTagType.Enumerated: { var node = variable as MultiStateDiscreteState; if (tag.Labels != null) { var strings = new LocalizedText[tag.Labels.Length]; for (var ii = 0; ii < tag.Labels.Length; ii++) { strings[ii] = new LocalizedText(tag.Labels[ii]); } node.EnumStrings.Value = strings; node.EnumStrings.Timestamp = tag.Block.Timestamp; } break; } } } private readonly string _blockId; private readonly CustomNodeManager2 _nodeManager; private int _monitoringCount; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DataAccess/DataAccessNodeManager.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DataAccess { using Opc.Ua; using Opc.Ua.Server; using System.Collections.Generic; /// /// A node manager for a server that exposes several variables. /// public class DataAccessNodeManager : CustomNodeManager2 { /// /// Initializes the node manager. /// /// /// public DataAccessNodeManager(IServerInternal server, ApplicationConfiguration configuration) : base(server, configuration, Namespaces.DataAccess) { AliasRoot = "DA"; SystemContext.SystemHandle = _system = new UnderlyingSystem(); SystemContext.NodeIdFactory = this; // get the configuration for the node manager. // use suitable defaults if no configuration exists. _configuration = configuration.ParseExtension() ?? new DataAccessServerConfiguration(); // create the table to store the cached blocks. _blocks = []; } /// /// An overrideable version of the Dispose. /// /// protected override void Dispose(bool disposing) { if (disposing) { _system.Dispose(); } base.Dispose(disposing); } /// /// Creates the NodeId for the specified node. /// /// The context. /// The node. /// The new NodeId. /// /// This method is called by the NodeState.Create() method which initializes a Node from /// the type model. During initialization a number of child nodes are created and need to /// have NodeIds assigned to them. This implementation constructs NodeIds by constructing /// strings. Other implementations could assign unique integers or Guids and save the new /// Node in a dictionary for later lookup. /// public override NodeId New(ISystemContext context, NodeState node) { return ModelUtils.ConstructIdForComponent(node, NamespaceIndex); } /// /// Does any initialization required before the address space can be used. /// /// /// /// The externalReferences is an out parameter that allows the node manager to link to nodes /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and /// should have a reference to the root folder node(s) exposed by this node manager. /// public override void CreateAddressSpace(IDictionary> externalReferences) { lock (Lock) { // find the top level segments and link them to the ObjectsFolder. var segments = _system.FindSegments(null); for (var ii = 0; ii < segments.Count; ii++) { // Top level areas need a reference from the Server object. // These references are added to a list that is returned to the caller. // The caller will update the Objects folder node. if (!externalReferences.TryGetValue(ObjectIds.ObjectsFolder, out var references)) { externalReferences[ObjectIds.ObjectsFolder] = references = []; } // construct the NodeId of a segment. var segmentId = ModelUtils.ConstructIdForSegment(segments[ii].Id, NamespaceIndex); // add an organizes reference from the ObjectsFolder to the area. references.Add(new NodeStateReference(ReferenceTypeIds.Organizes, false, segmentId)); } // start the simulation. _system.StartSimulation(); } } /// /// Frees any resources allocated for the address space. /// public override void DeleteAddressSpace() { lock (Lock) { _system.StopSimulation(); _blocks.Clear(); } } /// /// Returns a unique handle for the node. /// /// /// /// protected override NodeHandle GetManagerHandle(ServerSystemContext context, NodeId nodeId, IDictionary cache) { lock (Lock) { // quickly exclude nodes that are not in the namespace. if (!IsNodeIdInNamespace(nodeId)) { return null; } // check for check for nodes that are being currently monitored. if (MonitoredNodes.TryGetValue(nodeId, out var monitoredNode)) { return new NodeHandle { NodeId = nodeId, Validated = true, Node = monitoredNode.Node }; } if (nodeId.IdType != IdType.String && PredefinedNodes.TryGetValue(nodeId, out var node)) { return new NodeHandle { NodeId = nodeId, Node = node, Validated = true }; } // parse the identifier. var parsedNodeId = ParsedNodeId.Parse(nodeId); if (parsedNodeId != null) { return new NodeHandle { NodeId = nodeId, Validated = false, Node = null, ParsedNodeId = parsedNodeId }; } return null; } } /// /// Verifies that the specified node exists. /// /// /// /// protected override NodeState ValidateNode( ServerSystemContext context, NodeHandle handle, IDictionary cache) { // not valid if no root. if (handle == null) { return null; } // check if previously validated. if (handle.Validated) { return handle.Node; } NodeState target = null; // check if already in the cache. if (cache != null) { if (cache.TryGetValue(handle.NodeId, out target)) { // nulls mean a NodeId which was previously found to be invalid has been referenced again. if (target == null) { return null; } handle.Node = target; handle.Validated = true; return handle.Node; } target = null; } try { // check if the node id has been parsed. if (handle.ParsedNodeId is not ParsedNodeId parsedNodeId) { return null; } NodeState root = null; // validate a segment. if (parsedNodeId.RootType == ModelUtils.Segment) { var segment = _system.FindSegment(parsedNodeId.RootId); // segment does not exist. if (segment == null) { return null; } var rootId = ModelUtils.ConstructIdForSegment(segment.Id, NamespaceIndex); // create a temporary object to use for the operation. root = new SegmentState(context, rootId, segment); } // validate segment. else if (parsedNodeId.RootType == ModelUtils.Block) { // validate the block. var block = _system.FindBlock(parsedNodeId.RootId); // block does not exist. if (block == null) { return null; } var rootId = ModelUtils.ConstructIdForBlock(block.Id, NamespaceIndex); // check for check for blocks that are being currently monitored. if (_blocks.TryGetValue(rootId, out var node)) { root = node; } // create a temporary object to use for the operation. else { root = new BlockState(this, rootId, block); } } // unknown root type. else { return null; } // all done if no components to validate. if (string.IsNullOrEmpty(parsedNodeId.ComponentPath)) { handle.Validated = true; handle.Node = target = root; return handle.Node; } // validate component. NodeState component = root.FindChildBySymbolicName(context, parsedNodeId.ComponentPath); // component does not exist. if (component == null) { return null; } // found a valid component. handle.Validated = true; handle.Node = target = component; return handle.Node; } finally { // store the node in the cache to optimize subsequent lookups. cache?.Add(handle.NodeId, target); } } /// /// Called after creating a MonitoredItem. /// /// The context. /// The handle for the node. /// The monitored item. protected override void OnMonitoredItemCreated(ServerSystemContext context, NodeHandle handle, ISampledDataChangeMonitoredItem monitoredItem) { if (handle.Node.GetHierarchyRoot() is BlockState block) { block.StartMonitoring(context); // need to save the block to ensure that multiple monitored items use the same instance. _blocks[block.NodeId] = block; } } /// /// Called after deleting a MonitoredItem. /// /// The context. /// The handle for the node. /// The monitored item. protected override void OnMonitoredItemDeleted(ServerSystemContext context, NodeHandle handle, ISampledDataChangeMonitoredItem monitoredItem) { if (handle.Node.GetHierarchyRoot() is BlockState block && !block.StopMonitoring(context)) { // can remove the block since all monitored items for the block are gone. _blocks.Remove(block.NodeId); } } private readonly UnderlyingSystem _system; #pragma warning disable IDE0052 // Remove unread private members private readonly DataAccessServerConfiguration _configuration; #pragma warning restore IDE0052 // Remove unread private members private readonly Dictionary _blocks; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DataAccess/DataAccessServer.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DataAccess { using Opc.Ua; using Opc.Ua.Server; /// public class DataAccessServer : INodeManagerFactory { /// public StringCollection NamespacesUris { get { return [ Namespaces.DataAccess ]; } } /// public INodeManager Create(IServerInternal server, ApplicationConfiguration configuration) { return new DataAccessNodeManager(server, configuration); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DataAccess/DataAccessServerConfiguration.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DataAccess { using System.Runtime.Serialization; /// /// Stores the configuration the data access node manager. /// [DataContract(Namespace = Namespaces.DataAccess)] public class DataAccessServerConfiguration { /// /// The default constructor. /// public DataAccessServerConfiguration() { Initialize(); } /// /// Initializes the object during deserialization. /// /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DataAccess/ModelUtils.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DataAccess { using Opc.Ua; using Opc.Ua.Server; using System.Text; /// /// A class that builds NodeIds used by the DataAccess NodeManager /// public static class ModelUtils { /// /// The RootType for a Segment node identfier. /// public const int Segment = 0; /// /// The RootType for a Block node identfier. /// public const int Block = 1; /// /// Constructs a node identifier for a segment. /// /// The segment path. /// Index of the namespace that qualifies the identifier. /// The new node identifier. public static NodeId ConstructIdForSegment(string segmentPath, ushort namespaceIndex) { var parsedNodeId = new ParsedNodeId { RootId = segmentPath, NamespaceIndex = namespaceIndex, RootType = 0 }; return parsedNodeId.Construct(); } /// /// Constructs a NodeId for a block. /// /// The block id. /// Index of the namespace. /// The new NodeId. public static NodeId ConstructIdForBlock(string blockId, ushort namespaceIndex) { var parsedNodeId = new ParsedNodeId { RootId = blockId, NamespaceIndex = namespaceIndex, RootType = 1 }; return parsedNodeId.Construct(); } /// /// Constructs the node identifier for a component. /// /// The component. /// Index of the namespace. /// The node identifier for a component. public static NodeId ConstructIdForComponent(NodeState component, ushort namespaceIndex) { if (component == null) { return null; } // components must be instances with a parent. if (component is not BaseInstanceState instance || instance.Parent == null) { return component.NodeId; } // parent must have a string identifier. if (instance.Parent.NodeId.Identifier is not string parentId) { return null; } var buffer = new StringBuilder(); buffer.Append(parentId); // check if the parent is another component. var index = parentId.IndexOf('?'); if (index < 0) { buffer.Append('?'); } else { buffer.Append('/'); } buffer.Append(component.SymbolicName); // return the node identifier. return new NodeId(buffer.ToString(), namespaceIndex); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DataAccess/Namespaces.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DataAccess { /// /// Defines constants for namespaces used by the application. /// public static class Namespaces { /// /// The namespace for the nodes provided by the server. /// public const string DataAccess = "DataAccess"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DataAccess/SegmentBrowser.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DataAccess { using Opc.Ua; using System.Collections.Generic; /// /// Browses the children of a segment. /// public class SegmentBrowser : NodeBrowser { /// /// Creates a new browser object with a set of filters. /// /// The system context to use. /// The view which may restrict the set of references/nodes found. /// The type of references being followed. /// Whether subtypes of the reference type are followed. /// Which way the references are being followed. /// The browse name of a specific target (used when translating browse paths). /// Any additional references that should be included. /// If true the browser should not making blocking calls to external systems. /// The segment being accessed. public SegmentBrowser( ISystemContext context, ViewDescription view, NodeId referenceType, bool includeSubtypes, BrowseDirection browseDirection, QualifiedName browseName, IEnumerable additionalReferences, bool internalOnly, SegmentState source) : base( context, view, referenceType, includeSubtypes, browseDirection, browseName, additionalReferences, internalOnly) { _source = source; _stage = Stage.Begin; } /// /// Returns the next reference. /// /// The next reference that meets the browse criteria. public override IReference Next() { var system = (UnderlyingSystem)SystemContext.SystemHandle; lock (DataLock) { // enumerate pre-defined references. // always call first to ensure any pushed-back references are returned first. var reference = base.Next(); if (reference != null) { return reference; } if (_stage == Stage.Begin) { _segments = system.FindSegments(_source.SegmentPath); _stage = Stage.Segments; _position = 0; } // don't start browsing huge number of references when only internal references are requested. if (InternalOnly) { return null; } // enumerate segments. if (_stage == Stage.Segments) { if (IsRequired(ReferenceTypeIds.Organizes, false)) { reference = NextChild(); if (reference != null) { return reference; } } _blocks = system.FindBlocks(_source.SegmentPath); _stage = Stage.Blocks; _position = 0; } // enumerate blocks. if (_stage == Stage.Blocks && IsRequired(ReferenceTypeIds.Organizes, false)) { reference = NextChild(); if (reference != null) { return reference; } _stage = Stage.Done; _position = 0; } // all done. return null; } } /// /// Returns the next child. /// private NodeStateReference NextChild() { var system = (UnderlyingSystem)SystemContext.SystemHandle; NodeId targetId = null; // check if a specific browse name is requested. if (!QualifiedName.IsNull(BrowseName)) { // check if match found previously. if (_position == int.MaxValue) { return null; } // browse name must be qualified by the correct namespace. if (_source.BrowseName.NamespaceIndex != BrowseName.NamespaceIndex) { return null; } // look for matching segment. if (_stage == Stage.Segments && _segments != null) { for (var ii = 0; ii < _segments.Count; ii++) { if (BrowseName.Name == _segments[ii].Name) { targetId = ModelUtils.ConstructIdForSegment(_segments[ii].Id, _source.NodeId.NamespaceIndex); break; } } } // look for matching block. if (_stage == Stage.Blocks && _blocks != null) { for (var ii = 0; ii < _blocks.Count; ii++) { var block = system.FindBlock(_blocks[ii]); if (block != null && BrowseName.Name == block.Name) { targetId = ModelUtils.ConstructIdForBlock(_blocks[ii], _source.NodeId.NamespaceIndex); break; } } } _position = int.MaxValue; } // return the child at the next position. else { // look for next segment. if (_stage == Stage.Segments && _segments != null) { if (_position >= _segments.Count) { return null; } targetId = ModelUtils.ConstructIdForSegment(_segments[_position++].Id, _source.NodeId.NamespaceIndex); } // look for next block. else if (_stage == Stage.Blocks && _blocks != null) { if (_position >= _blocks.Count) { return null; } targetId = ModelUtils.ConstructIdForBlock(_blocks[_position++], _source.NodeId.NamespaceIndex); } } // create reference. if (targetId != null) { return new NodeStateReference(ReferenceTypeIds.Organizes, false, targetId); } return null; } /// /// The stages available in a browse operation. /// private enum Stage { Begin, Segments, Blocks, Done } private Stage _stage; private int _position; private readonly SegmentState _source; private IList _segments; private IList _blocks; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DataAccess/SegmentState.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DataAccess { using Opc.Ua; using System.Collections.Generic; /// /// A object which maps a segment to a UA object. /// public class SegmentState : FolderState { /// /// Initializes a new instance of the class. /// /// The context. /// The node id. /// The segment. public SegmentState(ISystemContext context, NodeId nodeId, UnderlyingSystemSegment segment) : base(null) { System.Diagnostics.Contracts.Contract.Assume(context != null); SegmentPath = segment.Id; TypeDefinitionId = ObjectTypeIds.FolderType; SymbolicName = segment.Name; NodeId = nodeId; BrowseName = new QualifiedName(segment.Name, nodeId.NamespaceIndex); DisplayName = new LocalizedText(segment.Name); Description = null; WriteMask = 0; UserWriteMask = 0; EventNotifier = EventNotifiers.None; } /// /// Gets the segment path. /// /// The segment path. public string SegmentPath { get; } /// /// Creates a browser that explores the structure of the block. /// /// The system context to use. /// The view which may restrict the set of references/nodes found. /// The type of references being followed. /// Whether subtypes of the reference type are followed. /// Which way the references are being followed. /// The browse name of a specific target (used when translating browse paths). /// Any additional references that should be included. /// If true the browser should not making blocking calls to external systems. /// The browse object (must be disposed). public override INodeBrowser CreateBrowser( ISystemContext context, ViewDescription view, NodeId referenceType, bool includeSubtypes, BrowseDirection browseDirection, QualifiedName browseName, IEnumerable additionalReferences, bool internalOnly) { NodeBrowser browser = new SegmentBrowser( context, view, referenceType, includeSubtypes, browseDirection, browseName, additionalReferences, internalOnly, this); PopulateBrowser(context, browser); return browser; } /// /// Populates the browser with references that meet the criteria. /// /// The context for the system being accessed. /// The browser to populate. protected override void PopulateBrowser(ISystemContext context, NodeBrowser browser) { base.PopulateBrowser(context, browser); // check if the parent segments need to be returned. if (browser.IsRequired(ReferenceTypeIds.Organizes, true)) { if (context.SystemHandle is not UnderlyingSystem system) { return; } // add reference for parent segment. var segment = system.FindParentForSegment(SegmentPath); if (segment != null) { browser.Add(ReferenceTypeIds.Organizes, true, ModelUtils.ConstructIdForSegment(segment.Id, NodeId.NamespaceIndex)); } } } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DataAccess/UnderlyingSystem.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DataAccess { using Opc.Ua; using System; using System.Collections.Generic; using System.Threading; /// /// An object that provides access to the underlying system. /// public class UnderlyingSystem : IDisposable { /// /// Initializes a new instance of the class. /// public UnderlyingSystem() { _blocks = []; } /// /// The finializer implementation. /// ~UnderlyingSystem() { Dispose(false); } /// /// Frees any unmanaged reblocks. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// An overrideable version of the Dispose. /// /// protected virtual void Dispose(bool disposing) { if (disposing && _simulationTimer != null) { _simulationTimer.Dispose(); _simulationTimer = null; } } /// /// A database which stores all known block paths. /// /// /// These are hardcoded for an example but the real data could come from a DB, /// a file or any other system accessed with a non-UA API. /// The name of the block is the final path element. /// The same block can have many paths. /// Each preceding element is a segment. /// private readonly string[] s_BlockPathDatabase = [ "Factory/East/Boiler1/Pipe1001", "Factory/East/Boiler1/Drum1002", "Factory/East/Boiler1/Pipe1002", "Factory/East/Boiler1/FC1001", "Factory/East/Boiler1/LC1001", "Factory/East/Boiler1/CC1001", "Factory/West/Boiler2/Pipe2001", "Factory/West/Boiler2/Drum2002", "Factory/West/Boiler2/Pipe2002", "Factory/West/Boiler2/FC2001", "Factory/West/Boiler2/LC2001", "Factory/West/Boiler2/CC2001", "Assets/Sensors/Flow/Pipe1001", "Assets/Sensors/Level/Drum1002", "Assets/Sensors/Flow/Pipe1002", "Assets/Controllers/Flow/FC1001", "Assets/Controllers/Level/LC1001", "Assets/Controllers/Custom/CC1001", "Assets/Sensors/Flow/Pipe2001", "Assets/Sensors/Level/Drum2002", "Assets/Sensors/Flow/Pipe2002", "Assets/Controllers/Flow/FC2001", "Assets/Controllers/Level/LC2001", "Assets/Controllers/Custom/CC2001", "TestData/Static/FC1001", "TestData/Static/LC1001", "TestData/Static/CC1001", "TestData/Static/FC2001", "TestData/Static/LC2001", "TestData/Static/CC2001" ]; /// /// A database which stores all known blocks. /// /// /// /// These are hardcoded for an example but the real data could come from a DB, /// a file or any other system accessed with a non-UA API. /// /// /// The name of the block is the first element. /// The type of block is the second element. /// /// private readonly string[] s_BlockDatabase = [ "Pipe1001/FlowSensor", "Drum1002/LevelSensor", "Pipe1002/FlowSensor", "Pipe2001/FlowSensor", "Drum2002/LevelSensor", "Pipe2002/FlowSensor", "FC1001/Controller", "LC1001/Controller", "CC1001/CustomController", "FC2001/Controller", "LC2001/Controller", "CC2001/CustomController" ]; /// /// Returns the segment /// /// The path to the segment. /// The segment. Null if the segment path does not exist. public UnderlyingSystemSegment FindSegment(string segmentPath) { lock (_lock) { // check for invalid path. if (string.IsNullOrEmpty(segmentPath)) { return null; } // extract the seqment name from the path. var segmentName = segmentPath; var index = segmentPath.LastIndexOf('/'); if (index != -1) { segmentName = segmentName[(index + 1)..]; } if (string.IsNullOrEmpty(segmentName)) { return null; } // see if there is a block path that includes the segment. index = segmentPath.Length; for (var ii = 0; ii < s_BlockPathDatabase.Length; ii++) { var blockPath = s_BlockPathDatabase[ii]; if (index >= blockPath.Length || blockPath[index] != '/') { continue; } // segment found - return the info. if (blockPath.StartsWith(segmentPath, StringComparison.Ordinal)) { return new UnderlyingSystemSegment { Id = segmentPath, Name = segmentName, SegmentType = null }; } } return null; } } /// /// Finds the segments belonging to the specified segment. /// /// The path to the segment to search. /// The list of segments found. Null if the segment path does not exist. public IList FindSegments(string segmentPath) { lock (_lock) { // check for invalid path. if (string.IsNullOrEmpty(segmentPath)) { segmentPath = string.Empty; } var segments = new Dictionary(); // find all block paths that start with the specified segment. var length = segmentPath.Length; for (var ii = 0; ii < s_BlockPathDatabase.Length; ii++) { var blockPath = s_BlockPathDatabase[ii]; // check for segment path prefix in block path. if (length > 0) { if (length >= blockPath.Length || blockPath[length] != '/') { continue; } if (!blockPath.StartsWith(segmentPath, StringComparison.Ordinal)) { continue; } blockPath = blockPath[(length + 1)..]; } // extract segment name. var index = blockPath.IndexOf('/'); if (index != -1) { var segmentName = blockPath[..index]; if (!segments.ContainsKey(segmentName)) { var segmentId = segmentName; if (!string.IsNullOrEmpty(segmentPath)) { segmentId = segmentPath; segmentId += "/"; segmentId += segmentName; } var segment = new UnderlyingSystemSegment { Id = segmentId, Name = segmentName, SegmentType = null }; segments.Add(segmentName, segment); } } } // return list. return [.. segments.Values]; } } /// /// Finds the blocks belonging to the specified segment. /// /// The path to the segment to search. /// The list of blocks found. Null if the segment path does not exist. public IList FindBlocks(string segmentPath) { lock (_lock) { // check for invalid path. if (string.IsNullOrEmpty(segmentPath)) { segmentPath = string.Empty; } var blocks = new List(); // look up the segment in the "DB". var length = segmentPath.Length; for (var ii = 0; ii < s_BlockPathDatabase.Length; ii++) { var blockPath = s_BlockPathDatabase[ii]; // check for segment path prefix in block path. if (length > 0) { if (length >= blockPath.Length || blockPath[length] != '/') { continue; } if (!blockPath.StartsWith(segmentPath, StringComparison.Ordinal)) { continue; } blockPath = blockPath[(length + 1)..]; } // check if there are no more segments in the path. var index = blockPath.IndexOf('/'); if (index == -1) { blockPath = blockPath[(index + 1)..]; if (!blocks.Contains(blockPath)) { blocks.Add(blockPath); } } } return blocks; } } /// /// Finds the parent segment for the specified segment. /// /// The segment path. /// The segment path for the parent. public UnderlyingSystemSegment FindParentForSegment(string segmentPath) { lock (_lock) { // check for invalid segment. var segment = FindSegment(segmentPath); if (segment == null) { return null; } // check for root segment. var index = segmentPath.LastIndexOf('/'); if (index == -1) { return null; } // construct the parent. var parent = new UnderlyingSystemSegment { Id = segmentPath[..index], SegmentType = null }; index = parent.Id.LastIndexOf('/'); if (index == -1) { parent.Name = parent.Id; } else { parent.Name = parent.Id[..index]; } return parent; } } /// /// Finds a block. /// /// The block identifier. /// The block. public UnderlyingSystemBlock FindBlock(string blockId) { UnderlyingSystemBlock block = null; lock (_lock) { // check for invalid name. if (string.IsNullOrEmpty(blockId)) { return null; } // look for cached block. if (_blocks.TryGetValue(blockId, out block)) { return block; } // lookup block in database. string blockType = null; var length = blockId.Length; for (var ii = 0; ii < s_BlockDatabase.Length; ii++) { blockType = s_BlockDatabase[ii]; if (length >= blockType.Length || blockType[length] != '/') { continue; } if (blockType.StartsWith(blockId, StringComparison.Ordinal)) { blockType = blockType[(length + 1)..]; break; } blockType = null; } // block not found. if (blockType == null) { return null; } // create a new block. block = new UnderlyingSystemBlock { // create the block. Id = blockId, Name = blockId, BlockType = blockType }; _blocks.Add(blockId, block); // add the tags based on the block type. // note that the block and tag types used here are types defined by the underlying system. // the node manager will need to map these types to UA defined types. switch (block.BlockType) { case "FlowSensor": { block.CreateTag("Measurement", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Analog, "liters/sec", false); block.CreateTag("Online", UnderlyingSystemDataType.Integer1, UnderlyingSystemTagType.Digital, null, false); break; } case "LevelSensor": { block.CreateTag("Measurement", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Analog, "liters", false); block.CreateTag("Online", UnderlyingSystemDataType.Integer1, UnderlyingSystemTagType.Digital, null, false); break; } case "Controller": { block.CreateTag("SetPoint", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Normal, null, true); block.CreateTag("Measurement", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Normal, null, false); block.CreateTag("Output", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Normal, null, false); block.CreateTag("Status", UnderlyingSystemDataType.Integer4, UnderlyingSystemTagType.Enumerated, null, false); break; } case "CustomController": { block.CreateTag("Input1", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Normal, null, true); block.CreateTag("Input2", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Normal, null, true); block.CreateTag("Input3", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Normal, null, true); block.CreateTag("Output", UnderlyingSystemDataType.Real4, UnderlyingSystemTagType.Normal, null, false); break; } } } // return the new block. return block; } /// /// Finds the segments for block. /// /// The block id. /// The list of segments. public IList FindSegmentsForBlock(string blockId) { lock (_lock) { // check for invalid path. if (string.IsNullOrEmpty(blockId)) { return null; } var segments = new List(); // look up the segment in the block path database. var length = blockId.Length; for (var ii = 0; ii < s_BlockPathDatabase.Length; ii++) { var blockPath = s_BlockPathDatabase[ii]; if (length >= blockPath.Length || blockPath[^length] != '/') { continue; } if (!blockPath.EndsWith(blockId, StringComparison.Ordinal)) { continue; } var segmentPath = blockPath[..(blockPath.Length - length - 1)]; // construct segment. var segment = new UnderlyingSystemSegment { Id = segmentPath, SegmentType = null }; var index = segmentPath.LastIndexOf('/'); if (index == -1) { segment.Name = segmentPath; } else { segment.Name = segmentPath[..index]; } segments.Add(segment); } return segments; } } /// /// Starts a simulation which causes the tag states to change. /// /// /// This simulation randomly activates the tags that belong to the blocks. /// Once an tag is active it has to be acknowledged and confirmed. /// Once an tag is confirmed it go to the inactive state. /// If the tag stays active the severity will be gradually increased. /// public void StartSimulation() { lock (_lock) { if (_simulationTimer != null) { _simulationTimer.Dispose(); _simulationTimer = null; } _generator = new Opc.Ua.Test.TestDataGenerator(); _simulationTimer = new Timer(DoSimulation, null, 1000, 1000); } } /// /// Stops the simulation. /// public void StopSimulation() { lock (_lock) { if (_simulationTimer != null) { _simulationTimer.Dispose(); _simulationTimer = null; } } } /// /// Simulates a block by updating the state of the tags belonging to the condition. /// /// private void DoSimulation(object state) { try { // get the list of blocks. List blocks = null; lock (_lock) { _simulationCounter++; blocks = [.. _blocks.Values]; } // run simulation for each block. for (var ii = 0; ii < blocks.Count; ii++) { blocks[ii].DoSimulation(_simulationCounter, ii, _generator); } } catch (Exception e) { Utils.Trace(e, "Unexpected error running simulation for system"); } } private readonly Lock _lock = new(); private readonly Dictionary _blocks; private Timer _simulationTimer; private long _simulationCounter; private Opc.Ua.Test.TestDataGenerator _generator; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DataAccess/UnderlyingSystemBlock.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DataAccess { using Opc.Ua; using System; using System.Collections.Generic; /// /// This class simulates a block in the system. /// public class UnderlyingSystemBlock { /// /// Initializes a new instance of the class. /// public UnderlyingSystemBlock() { _tags = []; } /// /// Gets or sets the unique identifier for the block. /// /// The unique identifier for the block. public string Id { get; set; } /// /// Gets or sets the name of the block. /// /// The name. public string Name { get; set; } /// /// Gets or sets the type of the block. /// /// The type of the block. public string BlockType { get; set; } /// /// Gets or sets the time when the block structure last changed. /// /// When the block structure last changed. public DateTime Timestamp { get; set; } /// /// Creates the tag. /// /// Name of the tag. /// Type of the data. /// Type of the tag. /// The engineering units. /// if set to true the tag is writeable. public void CreateTag( string tagName, UnderlyingSystemDataType dataType, UnderlyingSystemTagType tagType, string engineeringUnits, bool writeable) { // create tag. var tag = new UnderlyingSystemTag { Block = this, Name = tagName, Description = null, EngineeringUnits = engineeringUnits, DataType = dataType, TagType = tagType, IsWriteable = writeable, Labels = null, EuRange = null }; switch (tagType) { case UnderlyingSystemTagType.Analog: { tag.Description = "An analog value."; tag.TagType = UnderlyingSystemTagType.Analog; tag.EuRange = [100, 0]; break; } case UnderlyingSystemTagType.Digital: { tag.Description = "A digital value."; tag.TagType = UnderlyingSystemTagType.Digital; tag.Labels = ["Online", "Offline"]; break; } case UnderlyingSystemTagType.Enumerated: { tag.Description = "An enumerated value."; tag.TagType = UnderlyingSystemTagType.Enumerated; tag.Labels = ["Red", "Yellow", "Green"]; break; } default: { tag.Description = "A generic value."; break; } } // set an initial value. switch (tag.DataType) { case UnderlyingSystemDataType.Integer1: { tag.Value = (sbyte)0; break; } case UnderlyingSystemDataType.Integer2: { tag.Value = (short)0; break; } case UnderlyingSystemDataType.Integer4: { tag.Value = 0; break; } case UnderlyingSystemDataType.Real4: { tag.Value = (float)0; break; } case UnderlyingSystemDataType.String: { tag.Value = string.Empty; break; } } lock (_tags) { _tags.Add(tag); Timestamp = DateTime.UtcNow; } } /// /// Returns a snapshot of the tags belonging to the block. /// /// The list of tags. Null if the block does not exist. public IList GetTags() { lock (_tags) { // create snapshots of the tags. var tags = new UnderlyingSystemTag[_tags.Count]; for (var ii = 0; ii < _tags.Count; ii++) { tags[ii] = _tags[ii].CreateSnapshot(); } return tags; } } /// /// Starts the monitoring. /// /// The callback to use when reporting changes. public void StartMonitoring(TagsChangedEventHandler callback) { lock (_tags) { _onTagsChanged = callback; } } /// /// Writes the tag value. /// /// Name of the tag. /// The value. /// The status code for the operation. public uint WriteTagValue(string tagName, object value) { UnderlyingSystemTag tag = null; TagsChangedEventHandler onTagsChanged = null; lock (_tags) { onTagsChanged = _onTagsChanged; // find the tag. tag = FindTag(tagName); if (tag == null) { return StatusCodes.BadNodeIdUnknown; } // cast value to correct type. try { switch (tag.DataType) { case UnderlyingSystemDataType.Integer1: { tag.Value = (sbyte)value; break; } case UnderlyingSystemDataType.Integer2: { tag.Value = (short)value; break; } case UnderlyingSystemDataType.Integer4: { tag.Value = (int)value; break; } case UnderlyingSystemDataType.Real4: { tag.Value = (float)value; break; } case UnderlyingSystemDataType.String: { tag.Value = (string)value; break; } } } catch { return StatusCodes.BadTypeMismatch; } // updated the timestamp. tag.Timestamp = DateTime.UtcNow; } // raise notification. if (tag != null && onTagsChanged != null) { onTagsChanged(new UnderlyingSystemTag[] { tag }); } return StatusCodes.Good; } /// /// Stops monitoring. /// public void StopMonitoring() { lock (_tags) { _onTagsChanged = null; } } /// /// Simulates a block by updating the state of the tags belonging to the condition. /// /// The number of simulation cycles that have elapsed. /// The index of the block within the system. /// An object which generates random data. public void DoSimulation(long counter, int index, Opc.Ua.Test.TestDataGenerator generator) { try { TagsChangedEventHandler onTagsChanged = null; var snapshots = new List(); // update the tags. lock (_tags) { onTagsChanged = _onTagsChanged; // do nothing if not monitored. if (onTagsChanged == null) { return; } for (var ii = 0; ii < _tags.Count; ii++) { var tag = _tags[ii]; UpdateTagValue(tag, generator); var value = new DataValue { Value = tag.Value, StatusCode = StatusCodes.Good, SourceTimestamp = tag.Timestamp }; if (counter % (8 + (index % 4)) == 0) { UpdateTagMetadata(tag, generator); } snapshots.Add(tag.CreateSnapshot()); } } // report any tag changes after releasing the lock. onTagsChanged?.Invoke(snapshots); } catch (Exception e) { Utils.Trace(e, "Unexpected error running simulation for block {0}", Name); } } /// /// Finds the tag identified by the name. /// /// Name of the tag. /// The tag if null; otherwise null. private UnderlyingSystemTag FindTag(string tagName) { lock (_tags) { // look up tag. for (var ii = 0; ii < _tags.Count; ii++) { var tag = _tags[ii]; if (tag.Name == tagName) { return tag; } } return null; } } /// /// Updates the value of an tag. /// /// /// private bool UpdateTagValue( UnderlyingSystemTag tag, Opc.Ua.Test.TestDataGenerator generator) { // don't update writeable tags. if (tag.IsWriteable) { return false; } // check if a range applies to the value. var high = 0; var low = 0; switch (tag.TagType) { case UnderlyingSystemTagType.Analog: { if (tag.EuRange?.Length >= 2) { high = (int)tag.EuRange[0]; low = (int)tag.EuRange[1]; } break; } case UnderlyingSystemTagType.Digital: { high = 1; low = 0; break; } case UnderlyingSystemTagType.Enumerated: { if (tag.Labels?.Length > 0) { high = tag.Labels.Length - 1; low = 0; } break; } } // select a value in the range. var value = -1; if (high > low) { value = (generator.GetRandomUInt16() % (high - low + 1)) + low; } // cast value to correct type or generate a random value. switch (tag.DataType) { case UnderlyingSystemDataType.Integer1: { if (value == -1) { tag.Value = generator.GetRandomSByte(); } else { tag.Value = (sbyte)value; } break; } case UnderlyingSystemDataType.Integer2: { if (value == -1) { tag.Value = generator.GetRandomInt16(); } else { tag.Value = (short)value; } break; } case UnderlyingSystemDataType.Integer4: { if (value == -1) { tag.Value = generator.GetRandomInt32(); } else { tag.Value = value; } break; } case UnderlyingSystemDataType.Real4: { if (value == -1) { tag.Value = generator.GetRandomFloat(); } else { tag.Value = (float)value; } break; } case UnderlyingSystemDataType.String: { tag.Value = generator.GetRandomString(); break; } } tag.Timestamp = DateTime.UtcNow; return true; } /// /// Updates the metadata for a tag. /// /// /// private bool UpdateTagMetadata( UnderlyingSystemTag tag, Opc.Ua.Test.TestDataGenerator generator) { switch (tag.TagType) { case UnderlyingSystemTagType.Analog: { if (tag.EuRange != null) { var range = new double[tag.EuRange.Length]; for (var ii = 0; ii < tag.EuRange.Length; ii++) { range[ii] = tag.EuRange[ii] + 1; } tag.EuRange = range; } break; } case UnderlyingSystemTagType.Digital: case UnderlyingSystemTagType.Enumerated: { if (tag.Labels != null) { var labels = new string[tag.Labels.Length]; for (var ii = 0; ii < tag.Labels.Length; ii++) { labels[ii] = generator.GetRandomString(); } tag.Labels = labels; } break; } default: { return false; } } return true; } private readonly List _tags; private TagsChangedEventHandler _onTagsChanged; } /// /// Used to receive events when the state of an tag changes. /// /// public delegate void TagsChangedEventHandler(IList tags); } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DataAccess/UnderlyingSystemDataType.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DataAccess { /// /// Defines the possible tag data types /// public enum UnderlyingSystemDataType { /// /// A 1-byte integer value. /// Integer1 = 0, /// /// A 2-byte integer value. /// Integer2 = 1, /// /// A 4-byte integer value. /// Integer4 = 2, /// /// A 4-byte floating point value. /// Real4 = 3, /// /// A string value. /// String = 4 } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DataAccess/UnderlyingSystemSegment.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DataAccess { /// /// Stores information about a segment in the system. /// public class UnderlyingSystemSegment { /// /// Gets or sets the unique id for the segment. /// /// The unique id for the segment public string Id { get; set; } /// /// Gets or sets the name of the segment. /// /// The name of the segment. public string Name { get; set; } /// /// Gets or sets the type of the segment. /// /// The type of the segment. public string SegmentType { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DataAccess/UnderlyingSystemTag.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DataAccess { using System; /// /// This class stores the state of a tag known to the system. /// /// /// This class only stores the information about an tag that a system has. The /// system has no concept of the UA information model and the NodeManager must /// convert the information stored in this class into the UA equivalent. /// public class UnderlyingSystemTag { /// /// The block that the tag belongs to /// /// The block. public UnderlyingSystemBlock Block { get; set; } /// /// Gets or sets the name of the tag. /// /// The name of the tag. public string Name { get; set; } /// /// Gets or sets the description of the tag. /// /// The description of the tag. public string Description { get; set; } /// /// Gets or sets the engineering units for the tag. /// /// The engineering units for the tag. public string EngineeringUnits { get; set; } /// /// Gets or sets the data type for the tag. /// /// The data type for the tag. public UnderlyingSystemDataType DataType { get; set; } /// /// Gets or sets the type of the tag. /// /// The type of the tag. public UnderlyingSystemTagType TagType { get; set; } /// /// Gets or sets the value of the tag. /// /// The tag value. public object Value { get; set; } /// /// Gets or sets the timestamp for the value. /// /// The timestamp for the value. public DateTime Timestamp { get; set; } /// /// Gets or sets a value indicating whether the value is writeable. /// /// /// true if the vaklue is writeable; otherwise, false. /// public bool IsWriteable { get; set; } /// /// Gets or sets the EU ranges for the tag. /// /// The EU ranges for the tag. /// /// 2 values: HighEU, LowEU /// 4 values: HighEU, LowEU, HighIR, LowIR /// public double[] EuRange { get; set; } /// /// Gets or sets the labels for the tag values. /// /// The labels for the tag values. /// /// Digital Tags: TrueState, FalseState /// Enumerated Tags: Lookup table for Value. /// public string[] Labels { get; set; } /// /// Creates a snapshot of the tag. /// /// The snapshot. public UnderlyingSystemTag CreateSnapshot() { return (UnderlyingSystemTag)MemberwiseClone(); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DataAccess/UnderlyingSystemTagType.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DataAccess { /// /// Defines the possible tag types /// public enum UnderlyingSystemTagType { /// /// The tag has no special characteristics. /// Normal = 0, /// /// The tag is an analog value with a high and low range. /// Analog = 1, /// /// The tag is a digital value with a true and false state. /// Digital = 2, /// /// The tag is a enumerated value with set of names states. /// Enumerated = 3 } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DeterministicAlarms/Configuration/Alarm.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DeterministicAlarms.Configuration { public class Alarm { public AlarmObjectStates ObjectType { get; set; } public string Name { get; set; } public string Id { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DeterministicAlarms/Configuration/AlarmObjectStates.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DeterministicAlarms.Configuration { public enum AlarmObjectStates { TripAlarmType, OffNormalAlarmType, AlarmConditionType, LimitAlarmType, ConditionType } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DeterministicAlarms/Configuration/AlarmsConfiguration.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DeterministicAlarms.Configuration { using System.Text.Json; using System.Text.Json.Serialization; public class AlarmsConfiguration { public Folder[] Folders { get; set; } public Script Script { get; set; } public static AlarmsConfiguration FromJson(string json) { return JsonSerializer.Deserialize( json, kSerializerOptions); } private static readonly JsonSerializerOptions kSerializerOptions = new() { ReadCommentHandling = JsonCommentHandling.Skip, PropertyNamingPolicy = JsonNamingPolicy.CamelCase, PropertyNameCaseInsensitive = true, Converters = { new JsonStringEnumConverter() } }; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DeterministicAlarms/Configuration/ConditionStates.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DeterministicAlarms.Configuration { public enum ConditionStates { Enabled, Activated } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DeterministicAlarms/Configuration/Event.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DeterministicAlarms.Configuration { using Opc.Ua; public class Event { public string AlarmId { get; set; } public string Reason { get; set; } public EventSeverity Severity { get; set; } public string EventId { get; set; } public StateChange[] StateChanges { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DeterministicAlarms/Configuration/Folder.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DeterministicAlarms.Configuration { public class Folder { public string Name { get; set; } public Source[] Sources { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DeterministicAlarms/Configuration/Script.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DeterministicAlarms.Configuration { public class Script { public int WaitUntilStartInSeconds { get; set; } public bool IsScriptInRepeatingLoop { get; set; } public int RunningForSeconds { get; set; } public Step[] Steps { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DeterministicAlarms/Configuration/ScriptException.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DeterministicAlarms.Configuration { using System; public class ScriptException : Exception { public ScriptException(string message) : base(message) { } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DeterministicAlarms/Configuration/Source.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DeterministicAlarms.Configuration { public class Source { public string Name { get; set; } public Alarm[] Alarms { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DeterministicAlarms/Configuration/StateChange.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DeterministicAlarms.Configuration { public class StateChange { public ConditionStates StateType { get; set; } public bool State { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DeterministicAlarms/Configuration/Step.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DeterministicAlarms.Configuration { public class Step { public @Event Event { get; set; } public int SleepInSeconds { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DeterministicAlarms/DeterministicAlarmsNodeManager.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DeterministicAlarms { using DeterministicAlarms.Configuration; using DeterministicAlarms.Model; using DeterministicAlarms.SimBackend; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Server; using Opc.Ua.Test; using System; using System.Collections.Generic; using System.Linq; public class DeterministicAlarmsNodeManager : CustomNodeManager2 { private readonly SimBackendService _system; private readonly List _folders = []; private uint _nodeIdCounter; private List _rootNotifiers; private readonly IServerInternal _server; private readonly ServerSystemContext _defaultSystemContext; private readonly Dictionary _sourceNodes = []; private readonly AlarmsConfiguration _scriptconfiguration; private readonly TimeService _timeService; private Dictionary _scriptAlarmToSources; private readonly string _configurationJson; private readonly ILogger _logger; /// /// Initializes the node manager. /// /// /// /// /// /// public DeterministicAlarmsNodeManager(IServerInternal server, ApplicationConfiguration configuration, TimeService timeService, string configurationJson, ILogger logger) : base(server, configuration) { _server = server; _defaultSystemContext = _server.DefaultSystemContext.Copy(); SystemContext.NodeIdFactory = this; SystemContext.SystemHandle = _system = new SimBackendService(); _configurationJson = configurationJson; _logger = logger; _timeService = timeService; // set one namespace for the type model and one names for dynamically created nodes. var namespaceUrls = new string[1]; namespaceUrls[0] = Namespaces.DeterministicAlarmsInstance; SetNamespaces(namespaceUrls); // read script configuration file try { _scriptconfiguration = AlarmsConfiguration.FromJson(_configurationJson); } catch (Exception ex) { _logger.ConfigurationError(ex); _logger.PrintConfiguration(_configurationJson); } } /// /// Verifies the script configuration file /// /// /// private void VerifyScriptConfiguration(AlarmsConfiguration scriptConfiguration) { _scriptAlarmToSources = []; foreach (var folder in scriptConfiguration.Folders) { foreach (var source in folder.Sources) { if (!_sourceNodes.ContainsKey(source.Name)) { throw new ScriptException($"Source Name: {source.Name} doesn't exist"); } foreach (var alarm in source.Alarms) { if (_scriptAlarmToSources.ContainsKey(alarm.Id)) { throw new ScriptException($"AlarmId: {alarm.Id} already exist"); } _scriptAlarmToSources[alarm.Id] = source.Name; } } } var uniqueEventIds = new HashSet(); foreach (var step in scriptConfiguration.Script.Steps) { if (step.Event != null) { if (!uniqueEventIds.Add(step.Event.EventId)) { throw new ScriptException($"EventId: {step.Event.EventId} already exist"); } if (!_scriptAlarmToSources.ContainsKey(step.Event.AlarmId)) { throw new ScriptException($"AlarmId: {step.Event.AlarmId} is not defined"); } if (step.Event.StateChanges == null || step.Event.StateChanges.Length == 0) { throw new ScriptException($"{step.Event.EventId} doesn't have any StateChanges"); } } } } /// /// Starts the script replay /// /// private void ReplayScriptStart(AlarmsConfiguration scriptConfiguration) { try { VerifyScriptConfiguration(scriptConfiguration); _logger.ScriptStarting(); var scriptEngine = new ScriptEngine(scriptConfiguration.Script, OnScriptStepAvailable, _timeService); } catch (ScriptException ex) { _logger.ScriptEngineError(ex); throw; } } /// /// Called when a new script step are available /// /// /// private void OnScriptStepAvailable(Step step, long loopNumber) { if (step == null) { _logger.ScriptEnded(); } else { if (step.Event != null) { var alarm = GetAlarm(step); UpdateAlarm(alarm, step.Event); var sourceNodeId = _scriptAlarmToSources[step.Event.AlarmId]; _sourceNodes[sourceNodeId].UpdateAlarmInSource(alarm, $"{step.Event.EventId} ({loopNumber})"); } PrintScriptStep(step, loopNumber); } } /// /// Update Alarm information /// /// /// private static void UpdateAlarm(SimAlarmStateBackend alarm, Event scriptEvent) { alarm.Reason = scriptEvent.Reason; alarm.Severity = scriptEvent.Severity; alarm.Time = DateTime.UtcNow; foreach (var stateChange in scriptEvent.StateChanges) { switch (stateChange.StateType) { case ConditionStates.Enabled: alarm.SetStateBits(SimConditionStatesEnum.Enabled, stateChange.State); alarm.EnableTime = DateTime.UtcNow; break; case ConditionStates.Activated: alarm.SetStateBits(SimConditionStatesEnum.Active, stateChange.State); alarm.ActiveTime = DateTime.UtcNow; break; default: break; } } } /// /// Get Alarm information /// /// /// private SimAlarmStateBackend GetAlarm(Step step) { var sourceNodeId = _scriptAlarmToSources[step.Event.AlarmId]; return _system.SourceNodes[sourceNodeId].Alarms[step.Event.AlarmId]; } /// /// Print script current step /// /// /// private void PrintScriptStep(Step step, long loopNumber) { if (step.Event != null) { _logger.AlarmEvent(loopNumber, step.Event.AlarmId, step.Event.Reason); foreach (var sc in step.Event.StateChanges) { _logger.StateChange(sc.StateType, sc.State); } } if (step.SleepInSeconds > 0) { _logger.SleepEvent(loopNumber, step.SleepInSeconds); } } // CustomNodeManager2 overrides /// /// Creates a new set of monitored items for a set of variables. /// /// /// /// /// /// /// /// /// /// /// /// /// This method only handles data change subscriptions. Event subscriptions are created by the SDK. /// public override void CreateMonitoredItems( OperationContext context, uint subscriptionId, double publishingInterval, TimestampsToReturn timestampsToReturn, IList itemsToCreate, IList errors, IList filterErrors, IList monitoredItems, bool createDurable, ref long globalIdCounter) { var systemContext = _defaultSystemContext.Copy(context); IDictionary operationCache = new NodeIdDictionary(); var nodesToValidate = new List(); var createdItems = new List(); lock (Lock) { for (var ii = 0; ii < itemsToCreate.Count; ii++) { var monitoredItemCreateRequest = itemsToCreate[ii]; // skip items that have already been processed. if (monitoredItemCreateRequest.Processed) { continue; } var itemToMonitor = monitoredItemCreateRequest.ItemToMonitor; // check for valid handle. var handle = GetManagerHandle(systemContext, itemToMonitor.NodeId, operationCache); if (handle == null) { continue; } // owned by this node manager. monitoredItemCreateRequest.Processed = true; // must validate node in a seperate operation. errors[ii] = StatusCodes.BadNodeIdUnknown; handle.Index = ii; nodesToValidate.Add(handle); } // check for nothing to do. if (nodesToValidate.Count == 0) { return; } } // validates the nodes (reads values from the underlying data source if required). for (var ii = 0; ii < nodesToValidate.Count; ii++) { var handle = nodesToValidate[ii]; MonitoringFilterResult filterResult = null; IMonitoredItem monitoredItem = null; lock (Lock) { // validate node. var source = ValidateNode(systemContext, handle, operationCache); if (source == null) { continue; } var itemToCreate = itemsToCreate[handle.Index]; // create monitored item. errors[handle.Index] = CreateMonitoredItem( systemContext, handle, subscriptionId, publishingInterval, context.DiagnosticsMask, timestampsToReturn, itemToCreate, createDurable, ref globalIdCounter, out filterResult, out monitoredItem); } // save any filter error details. filterErrors[handle.Index] = filterResult; if (ServiceResult.IsBad(errors[handle.Index])) { continue; } // save the monitored item. monitoredItems[handle.Index] = monitoredItem; createdItems.Add(monitoredItem); } // do any post processing. OnCreateMonitoredItemsComplete(systemContext, createdItems); } /// /// Verifies that the specified node exists. /// /// /// /// protected override NodeState ValidateNode( ServerSystemContext context, NodeHandle handle, IDictionary cache) { // lookup in cache. var target = FindNodeInCache(context, handle, cache); if (target != null) { handle.Node = target; handle.Validated = true; return handle.Node; } // return default. return handle.Node; } /// /// Subscribes or unsubscribes to events produced by all event sources. /// /// /// /// /// /// /// This method is called when a event subscription is created or deleted. The node /// manager must start/stop reporting events for all objects that it manages. /// public override ServiceResult SubscribeToAllEvents( OperationContext context, uint subscriptionId, IEventMonitoredItem monitoredItem, bool unsubscribe) { var serverSystemContext = SystemContext.Copy(context); lock (Lock) { // A client has subscribed to the Server object which means all events produced // by this manager must be reported. This is done by incrementing the monitoring // reference count for all root notifiers. if (_rootNotifiers != null) { for (var ii = 0; ii < _rootNotifiers.Count; ii++) { SubscribeToEvents(serverSystemContext, _rootNotifiers[ii], monitoredItem, unsubscribe); } } return ServiceResult.Good; } } /// /// Subscribes to events. /// /// The context. /// The source. /// The monitored item. /// if set to true [unsubscribe]. /// Any error code. protected override ServiceResult SubscribeToEvents( ServerSystemContext context, NodeState source, IEventMonitoredItem monitoredItem, bool unsubscribe) { // handle unsubscribe. if (unsubscribe) { // check for existing monitored node. if (!MonitoredNodes.TryGetValue(source.NodeId, out var monitoredNode2)) { return StatusCodes.BadNodeIdUnknown; } monitoredNode2.Remove(monitoredItem); // check if node is no longer being monitored. if (!monitoredNode2.HasMonitoredItems) { MonitoredNodes.Remove(source.NodeId); } // update flag. source.SetAreEventsMonitored(context, !unsubscribe, true); // call subclass. OnSubscribeToEvents(context, monitoredNode2, unsubscribe); // all done. return ServiceResult.Good; } // only objects or views can be subscribed to. if (source is not BaseObjectState instance || (instance.EventNotifier & EventNotifiers.SubscribeToEvents) == 0) { if (source is not ViewState view || (view.EventNotifier & EventNotifiers.SubscribeToEvents) == 0) { return StatusCodes.BadNotSupported; } } // check for existing monitored node. if (!MonitoredNodes.TryGetValue(source.NodeId, out var monitoredNode)) { MonitoredNodes[source.NodeId] = monitoredNode = new MonitoredNode2(this, source); } // this links the node to specified monitored item and ensures all events // reported by the node are added to the monitored item's queue. monitoredNode.Add(monitoredItem); // This call recursively updates a reference count all nodes in the notifier // hierarchy below the area. Sources with a reference count of 0 do not have // any active subscriptions so they do not need to report events. source.SetAreEventsMonitored(context, !unsubscribe, true); // signal update. OnSubscribeToEvents(context, monitoredNode, unsubscribe); // all done. return ServiceResult.Good; } /// /// Does any initialization required before the address space can be used. /// /// /// /// The externalReferences is an out parameter that allows the node manager to link to nodes /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and /// should have a reference to the root folder node(s) exposed by this node manager. /// public override void CreateAddressSpace(IDictionary> externalReferences) { lock (Lock) { if (!externalReferences.TryGetValue(ObjectIds.Server, out var references)) { externalReferences[ObjectIds.Server] = references = []; } // Folders Nodes foreach (var folder in _scriptconfiguration.Folders) { var simFolderState = new SimFolderState(SystemContext, null, new NodeId(folder.Name, NamespaceIndex), folder.Name); simFolderState.AddReference(ReferenceTypeIds.HasNotifier, true, ObjectIds.Server); AddRootNotifier(simFolderState); _folders.Add(simFolderState); // Source Nodes foreach (var source in folder.Sources) { SimSourceNodeState simSourceNodeState; _sourceNodes[source.Name] = simSourceNodeState = new SimSourceNodeState(this, new NodeId(source.Name, NamespaceIndex), source.Name, source.Alarms); simFolderState.AddChild(simSourceNodeState); simSourceNodeState.AddNotifier(SystemContext, ReferenceTypeIds.HasEventSource, true, simFolderState); simFolderState.AddNotifier(SystemContext, ReferenceTypeIds.HasEventSource, false, simSourceNodeState); } references.Add(new NodeStateReference(ReferenceTypeIds.HasNotifier, false, simFolderState.NodeId)); AddPredefinedNode(SystemContext, simFolderState); } } ReplayScriptStart(_scriptconfiguration); } /// /// Tells the node manager to refresh any conditions associated with the specified monitored items. /// /// /// /// /// This method is called when the condition refresh method is called for a subscription. /// The node manager must create a refresh event for each condition monitored by the subscription. /// public override ServiceResult ConditionRefresh( OperationContext context, IList monitoredItems) { foreach (var monitoredItem in monitoredItems.Cast()) { if (monitoredItem == null) { continue; } var events = new List(); var nodesToRefresh = new List(); lock (Lock) { // check for server subscription. if (monitoredItem.NodeId == ObjectIds.Server) { if (_rootNotifiers != null) { nodesToRefresh.AddRange(_rootNotifiers); } } else { if (!MonitoredNodes.TryGetValue(monitoredItem.NodeId, out var monitoredNode)) { continue; } // get the refresh events. nodesToRefresh.Add(monitoredNode.Node); } } foreach (var node in nodesToRefresh) { node.ConditionRefresh(SystemContext, events, true); } foreach (var @event in events) { monitoredItem.QueueEvent(@event); } } return ServiceResult.Good; } /// /// Adds a root notifier. /// /// The notifier. /// /// A root notifier is a notifier owned by the NodeManager that is not the target of a /// HasNotifier reference. These nodes need to be linked directly to the Server object. /// protected override void AddRootNotifier(NodeState notifier) { _rootNotifiers ??= []; for (var ii = 0; ii < _rootNotifiers.Count; ii++) { if (ReferenceEquals(notifier, _rootNotifiers[ii])) { return; } } _rootNotifiers.Add(notifier); // need to prevent recursion with the server object. if (notifier.NodeId != ObjectIds.Server) { notifier.OnReportEvent = OnReportEvent; if (!notifier.ReferenceExists(ReferenceTypeIds.HasNotifier, true, ObjectIds.Server)) { notifier.AddReference(ReferenceTypeIds.HasNotifier, true, ObjectIds.Server); } } // subscribe to existing events. if (_server.EventManager != null) { var monitoredItems = _server.EventManager.GetMonitoredItems(); for (var ii = 0; ii < monitoredItems.Count; ii++) { if (monitoredItems[ii].MonitoringAllEvents) { SubscribeToEvents( SystemContext, notifier, monitoredItems[ii], true); } } } } /// /// Creates the NodeId for the specified node. /// /// The context. /// The node. /// The new NodeId. /// /// This method is called by the NodeState.Create() method which initializes a Node from /// the type model. During initialization a number of child nodes are created and need to /// have NodeIds assigned to them. This implementation constructs NodeIds by constructing /// strings. Other implementations could assign unique integers or Guids and save the new /// Node in a dictionary for later lookup. /// public override NodeId New(ISystemContext context, NodeState node) { return new NodeId(++_nodeIdCounter, NamespaceIndex); } /// /// Loads a node set from a file or resource and addes them to the set of predefined nodes. /// /// protected override NodeStateCollection LoadPredefinedNodes(ISystemContext context) { return []; } } /// /// Source-generated logging definitions for DeterministicAlarmsNodeManager /// internal static partial class DeterministicAlarmsNodeManagerLogging { private const int EventClass = 30; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Error, Message = "Can't read or decode configuration.")] public static partial void ConfigurationError(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Error, Message = "{Configuration}")] public static partial void PrintConfiguration(this ILogger logger, string configuration); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Information, Message = "Script starts executing")] public static partial void ScriptStarting(this ILogger logger); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Error, Message = "Script Engine Exception\nSCRIPT WILL NOT START")] public static partial void ScriptEngineError(this ILogger logger, Exception ex); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Information, Message = "SCRIPT ENDED")] public static partial void ScriptEnded(this ILogger logger); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Information, Message = "({LoopNumber}) -\t{AlarmId}\t{Reason}")] public static partial void AlarmEvent(this ILogger logger, long loopNumber, string alarmId, string reason); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Information, Message = "\t\t{StateType} - {State}")] public static partial void StateChange(this ILogger logger, ConditionStates stateType, bool state); [LoggerMessage(EventId = EventClass + 8, Level = LogLevel.Information, Message = "({LoopNumber}) -\tSleep: {SleepInSeconds}")] public static partial void SleepEvent(this ILogger logger, long loopNumber, double sleepInSeconds); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DeterministicAlarms/DeterministicAlarmsServer.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DeterministicAlarms { using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Server; using Opc.Ua.Test; /// public class DeterministicAlarmsServer : INodeManagerFactory { /// public StringCollection NamespacesUris { get { return [ Namespaces.DeterministicAlarmsInstance ]; } } public DeterministicAlarmsServer(TimeService timeservice, string configurationJson, ILogger logger) { _timeservice = timeservice; _configurationJson = configurationJson; _logger = logger; } /// public INodeManager Create(IServerInternal server, ApplicationConfiguration configuration) { return new DeterministicAlarmsNodeManager(server, configuration, _timeservice, _configurationJson, _logger); } private readonly TimeService _timeservice; private readonly string _configurationJson; private readonly ILogger _logger; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DeterministicAlarms/Model/SimConditionStatesEnum.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DeterministicAlarms.Model { using System; [Flags] public enum SimConditionStatesEnum { /// /// The condition state is unknown. /// None = 0x0, /// /// The condition is enabled and will produce events. /// Enabled = 0x1, /// /// The condition requires acknowledgement by the user. /// Acknowledged = 0x2, /// /// The condition requires that the used confirm that action was taken. /// Confirmed = 0x4, /// /// The condition is active. /// Active = 0x8, /// /// The condition has been suppressed by the system. /// Suppressed = 0x10, /// /// The condition has been shelved by the user. /// Shelved = 0x20, ///// ///// The condition has exceeed the high-high limit. ///// //HighHigh = 0x40, ///// ///// The condition has exceeed the high limit. ///// //High = 0x80, ///// ///// The condition has exceeed the low limit. ///// //Low = 0x100, ///// ///// The condition has exceeed the low-low limit. ///// //LowLow = 0x200, ///// ///// A mask used to clear all limit bits. ///// //Limits = 0x3C0, /// /// The condition has deleted. /// Deleted = 0x400 } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DeterministicAlarms/Model/SimFolderState.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DeterministicAlarms.Model { using Opc.Ua; public class SimFolderState : FolderState { public SimFolderState(ISystemContext context, NodeState parent, NodeId nodeId, string name) : base(parent) { Initialize(context); // initialize the area with the fixed metadata. SymbolicName = name; NodeId = nodeId; BrowseName = new QualifiedName(name, nodeId.NamespaceIndex); DisplayName = BrowseName.Name; Description = null; ReferenceTypeId = ReferenceTypeIds.HasNotifier; TypeDefinitionId = ObjectTypeIds.FolderType; EventNotifier = EventNotifiers.SubscribeToEvents; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DeterministicAlarms/Model/SimSourceNodeState.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DeterministicAlarms.Model { using DeterministicAlarms.Configuration; using DeterministicAlarms.SimBackend; using Opc.Ua; using System; using System.Collections.Generic; using System.Text; public class SimSourceNodeState : BaseObjectState { private readonly DeterministicAlarmsNodeManager _nodeManager; private readonly SimSourceNodeBackend _simSourceNodeBackend; private readonly Dictionary _alarmNodes = []; private readonly Dictionary _events = []; public SimSourceNodeState(DeterministicAlarmsNodeManager nodeManager, NodeId nodeId, string name, IList alarms) : base(null) { _nodeManager = nodeManager; Initialize(_nodeManager.SystemContext); // Creates the whole backend object model for one source _simSourceNodeBackend = ((SimBackendService)_nodeManager.SystemContext.SystemHandle) .CreateSourceNodeBackend(name, alarms, OnAlarmChanged); // initialize the area with the fixed metadata. SymbolicName = name; NodeId = nodeId; BrowseName = new QualifiedName(name, nodeId.NamespaceIndex); DisplayName = BrowseName.Name; Description = null; ReferenceTypeId = null; TypeDefinitionId = ObjectTypeIds.BaseObjectType; EventNotifier = EventNotifiers.None; // This is to create all alarms _simSourceNodeBackend.Refresh(); } public override void ConditionRefresh(ISystemContext context, List events, bool includeChildren) { foreach (var @event in events) { if (@event is InstanceStateSnapshot instanceSnapShotForExistingEvent && ReferenceEquals(instanceSnapShotForExistingEvent.Handle, this)) { return; } } foreach (var alarm in _alarmNodes.Values) { if (!alarm.Retain.Value) { continue; } var instanceStateSnapshotNewAlarm = new InstanceStateSnapshot(); instanceStateSnapshotNewAlarm.Initialize(context, alarm); instanceStateSnapshotNewAlarm.Handle = this; events.Add(instanceStateSnapshotNewAlarm); } } private void OnAlarmChanged(object sender, SimAlarmStateBackendEventArgs alarm) { UpdateAlarmInSource(alarm.SnapshotAlarm); } public void UpdateAlarmInSource(SimAlarmStateBackend alarm, string eventId = null) { lock (_nodeManager.Lock) { if (!_alarmNodes.TryGetValue(alarm.Name, out var node)) { _alarmNodes[alarm.Name] = node = CreateAlarmOrCondition(alarm, null); } UpdateAlarm(node, alarm, eventId); ReportChanges(node); } } private ConditionState CreateAlarmOrCondition(SimAlarmStateBackend alarm, NodeId branchId) { ISystemContext context = _nodeManager.SystemContext; ConditionState node; // Condition if (alarm.AlarmType == AlarmObjectStates.ConditionType) { node = new ConditionState(this); } // All alarms inherent from AlarmConditionState else { switch (alarm.AlarmType) { case AlarmObjectStates.TripAlarmType: node = new TripAlarmState(this); break; case AlarmObjectStates.LimitAlarmType: node = new LimitAlarmState(this); break; case AlarmObjectStates.OffNormalAlarmType: node = new OffNormalAlarmState(this); break; default: node = new AlarmConditionState(this); break; } // create elements that conditiontype doesn't have CreateAlarmSpecificElements(context, (AlarmConditionState)node, branchId); } CreateCommonFieldsForAlarmAndCondition(context, node, alarm); // This call initializes the condition from the type model (i.e. creates all of the objects // and variables requried to store its state). The information about the type model was // incorporated into the class when the class was created. // // This method also assigns new NodeIds to all of the components by calling the INodeIdFactory.New // method on the INodeIdFactory object which is part of the system context. The NodeManager provides // the INodeIdFactory implementation used here. node.Create( context, null, new QualifiedName(alarm.Name, BrowseName.NamespaceIndex), null, true); // initialize event information.node node.EventType.Value = node.TypeDefinitionId; node.SourceNode.Value = NodeId; node.SourceName.Value = SymbolicName; node.ConditionName.Value = node.SymbolicName; node.Time.Value = DateTime.UtcNow; node.ReceiveTime.Value = node.Time.Value; node.BranchId.Value = branchId; // don't add branches to the address space. if (NodeId.IsNull(branchId)) { AddChild(node); } return node; } private static void CreateAlarmSpecificElements(ISystemContext context, AlarmConditionState node, NodeId branchId) { node.ConfirmedState = new TwoStateVariableState(node); node.Confirm = new AddCommentMethodState(node); if (NodeId.IsNull(branchId)) { node.SuppressedState = new TwoStateVariableState(node); node.ShelvingState = new ShelvedStateMachineState(node); } node.ActiveState = new TwoStateVariableState(node); node.ActiveState.TransitionTime = new PropertyState(node.ActiveState); node.ActiveState.EffectiveDisplayName = new PropertyState(node.ActiveState); node.ActiveState.Create(context, null, BrowseNames.ActiveState, null, false); } private static void CreateCommonFieldsForAlarmAndCondition(ISystemContext context, ConditionState node, SimAlarmStateBackend alarm) { node.SymbolicName = alarm.Name; // add optional components. node.Comment = new ConditionVariableState(node); node.ClientUserId = new PropertyState(node); node.AddComment = new AddCommentMethodState(node); // adding optional components to children is a little more complicated since the // necessary initilization strings defined by the class that represents the child. // in this case we pre-create the child, add the optional components // and call create without assigning NodeIds. The NodeIds will be assigned when the // parent object is created. node.EnabledState = new TwoStateVariableState(node); node.EnabledState.TransitionTime = new PropertyState(node.EnabledState); node.EnabledState.EffectiveDisplayName = new PropertyState(node.EnabledState); node.EnabledState.Create(context, null, BrowseNames.EnabledState, null, false); // specify reference type between the source and the alarm. node.ReferenceTypeId = ReferenceTypeIds.HasComponent; } private void UpdateAlarm(ConditionState node, SimAlarmStateBackend alarm, string eventId = null) { ISystemContext context = _nodeManager.SystemContext; // remove old event. if (node.EventId.Value != null) { _events.Remove(Utils.ToHexString(node.EventId.Value)); } node.EventId.Value = eventId != null ? Encoding.UTF8.GetBytes(eventId) : Guid.NewGuid().ToByteArray(); node.Time.Value = DateTime.UtcNow; node.ReceiveTime.Value = node.Time.Value; // save the event for later lookup. _events[Utils.ToHexString(node.EventId.Value)] = node; // determine the retain state. node.Retain.Value = true; if (alarm != null) { node.Time.Value = alarm.Time; node.Message.Value = new LocalizedText(alarm.Reason); node.SetComment(context, alarm.Comment, alarm.UserName); node.SetSeverity(context, alarm.Severity); node.EnabledState.TransitionTime.Value = alarm.EnableTime; node.SetEnableState(context, (alarm.State & SimConditionStatesEnum.Enabled) != 0); if (node is AlarmConditionState nodeAlarm) { nodeAlarm.SetAcknowledgedState(context, (alarm.State & SimConditionStatesEnum.Acknowledged) != 0); nodeAlarm.SetConfirmedState(context, (alarm.State & SimConditionStatesEnum.Confirmed) != 0); nodeAlarm.SetActiveState(context, (alarm.State & SimConditionStatesEnum.Active) != 0); nodeAlarm.SetSuppressedState(context, (alarm.State & SimConditionStatesEnum.Suppressed) != 0); nodeAlarm.ActiveState.TransitionTime.Value = alarm.ActiveTime; // not interested in inactive alarms if (!nodeAlarm.ActiveState.Id.Value) { nodeAlarm.Retain.Value = false; } } } // check for deleted items. if ((alarm.State & SimConditionStatesEnum.Deleted) != 0) { node.Retain.Value = false; } // not interested in disabled alarms. if (!node.EnabledState.Id.Value) { node.Retain.Value = false; } } private void ReportChanges(ConditionState alarm) { // report changes to node attributes. alarm.ClearChangeMasks(_nodeManager.SystemContext, true); // check if events are being monitored for the source. if (AreEventsMonitored) { // create a snapshot. var e = new InstanceStateSnapshot(); e.Initialize(_nodeManager.SystemContext, alarm); // report the event. alarm.ReportEvent(_nodeManager.SystemContext, e); } } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DeterministicAlarms/Namespaces.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DeterministicAlarms { /// /// Defines constants for namespaces used by the application. /// public static class Namespaces { /// /// The namespace for the nodes provided by the plc server for alarm instance. /// public const string DeterministicAlarmsInstance = "http://opcfoundation.org/UA/DetermAlarmsInstance"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DeterministicAlarms/ScriptEngine.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DeterministicAlarms { using DeterministicAlarms.Configuration; using Opc.Ua.Test; using System; using System.Collections.Generic; using System.Timers; public class ScriptEngine { public delegate void NextScriptStepAvailable(Step step, long numberOfLoops); private LinkedList _steps; private LinkedListNode _currentStep; private ITimer _stepsTimer; private readonly Script _script; private long _numberOfLoops = 1; private DateTime _scriptStopTime; private readonly TimeService _timeService; public NextScriptStepAvailable OnNextScriptStepAvailable { get; set; } /// /// Initialize ScriptEngine /// /// /// /// public ScriptEngine(Script script, NextScriptStepAvailable scriptCallback, TimeService timeService) { OnNextScriptStepAvailable += scriptCallback ?? throw new ScriptException("Script Callback is not defined"); _script = script; _timeService = timeService; CreateLinkedList(script.Steps); StartScript(); } private void StartScript() { _stepsTimer = _timeService.NewTimer(OnStepTimedEvent, Convert.ToUInt32(_script.WaitUntilStartInSeconds * 1000)); _scriptStopTime = _timeService.Now.AddSeconds(_script.RunningForSeconds + _script.WaitUntilStartInSeconds); } private void StopScript() { _stepsTimer.Close(); _stepsTimer = null; } /// /// Create the Linked List that will be used internally to go through the steps /// /// private void CreateLinkedList(IList steps) { _steps = new LinkedList(); foreach (var step in steps) { _steps.AddLast(step); } } /// /// Active a new step /// /// private void ActivateCurrentStep(LinkedListNode step) { _currentStep = step; OnNextScriptStepAvailable?.Invoke(step?.Value, _numberOfLoops); if (_stepsTimer != null) { _stepsTimer.Interval = Math.Max(1, step.Value.SleepInSeconds * 1000); } } /// /// Get the next step /// /// /// private LinkedListNode GetNextValue(LinkedListNode step) { // Script should end because it has been executed as long as expected in the parameter // RunningForSeconds if (_scriptStopTime < _timeService.Now) { StopScript(); return null; } // Is it the first step? if (step == null) { return _steps.First; } // Do we have a next step? if (step.Next != null) { return step.Next; } // We don't have a next step, now we should see if we should repeat // and start on first step again or terminate. if (_script.IsScriptInRepeatingLoop) { _numberOfLoops++; return _steps.First; } StopScript(); return null; } /// /// Trigger when next step should be executed /// /// /// private void OnStepTimedEvent(object source, ElapsedEventArgs e) { ActivateCurrentStep(GetNextValue(_currentStep)); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DeterministicAlarms/SimBackend/SimAlarmStateBackend.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DeterministicAlarms.SimBackend { using DeterministicAlarms.Configuration; using DeterministicAlarms.Model; using Opc.Ua; using System; public class SimAlarmStateBackend { public string Name { get; internal set; } public AlarmObjectStates AlarmType { get; set; } public DateTime Time { get; internal set; } public string Reason { get; internal set; } public SimConditionStatesEnum State { get; internal set; } public LocalizedText Comment { get; internal set; } public string UserName { get; internal set; } public EventSeverity Severity { get; internal set; } public DateTime EnableTime { get; internal set; } public DateTime ActiveTime { get; internal set; } public SimSourceNodeBackend Source { get; internal set; } public string Id { get; internal set; } internal SimAlarmStateBackend CreateSnapshot() { return (SimAlarmStateBackend)MemberwiseClone(); } internal bool SetStateBits(SimConditionStatesEnum bits, bool isSet) { if (isSet) { var currentlySet = (State & bits) == bits; State |= bits; return !currentlySet; } var currentlyCleared = (State & ~bits) == State; State &= ~bits; return !currentlyCleared; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DeterministicAlarms/SimBackend/SimBackendService.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DeterministicAlarms.SimBackend { using DeterministicAlarms.Configuration; using System; using System.Collections.Generic; using System.Threading; public class SimBackendService { private readonly Lock _lock = new(); public Dictionary SourceNodes { get; } = []; public SimSourceNodeBackend CreateSourceNodeBackend(string name, IList alarms, EventHandler alarmChangeCallback) { SimSourceNodeBackend simSourceNodeBackend; lock (_lock) { simSourceNodeBackend = new SimSourceNodeBackend { Name = name }; simSourceNodeBackend.OnAlarmChanged += alarmChangeCallback; simSourceNodeBackend.CreateAlarms(alarms); SourceNodes[name] = simSourceNodeBackend; } return simSourceNodeBackend; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DeterministicAlarms/SimBackend/SimSourceNodeBackend.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace DeterministicAlarms.SimBackend { using DeterministicAlarms.Configuration; using System; using System.Collections.Generic; public class SimAlarmStateBackendEventArgs : EventArgs { public SimAlarmStateBackend SnapshotAlarm { get; set; } } public class SimSourceNodeBackend { public Dictionary Alarms { get; } = []; public string Name { get; internal set; } public event EventHandler OnAlarmChanged; public void CreateAlarms(IList alarmsFromConfiguration) { foreach (var alarmConfiguration in alarmsFromConfiguration) { var alarmStateBackend = new SimAlarmStateBackend { Source = this, Id = alarmConfiguration.Id, Name = alarmConfiguration.Name, Time = DateTime.UtcNow, AlarmType = alarmConfiguration.ObjectType }; lock (Alarms) { Alarms.Add(alarmConfiguration.Id, alarmStateBackend); } } } internal void Refresh() { var snapshots = new List(); lock (Alarms) { foreach (var alarm in Alarms.Values) { snapshots.Add(alarm.CreateSnapshot()); } } foreach (var snapshotAlarm in snapshots) { OnAlarmChanged!.Invoke(this, new SimAlarmStateBackendEventArgs { SnapshotAlarm = snapshotAlarm }); } } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/DeterministicAlarms/readme.md ================================================ # OPC UA Deterministic Alarm Replayer ## Introduction This makes it possible to create more deterministic tests of Alarms. This is done by using a script that defines Alarms and execute them. ## Script The script has two sections. * Definition of the Folders, Sources of alarms, and the Alarms themselves. * The replay steps ``` { // These folders will be children to the Server Object "folders": [ { "name": "VendingMachines", "sources": [ { // We only support BaseObjectState "objectType": "BaseObjectState", // The name needs to be unique "name": "VendingMachine1", "alarms": [ { // We support a subset of current AlarmTypes "objectType": "TripAlarmType", // This is the name of the Alarm and will be visible in the Address Space "name": "VendingMachine1_DoorOpen", // This is the Id that will be used later in the script to identify the Alarm // This needs to be unique "id": "V1_DoorOpen" }, { "objectType": "LimitAlarmType", "name": "VendingMachine1_TemperatureHigh", "id": "V1_TemperatureHigh" } ] }, { "objectType": "BaseObjectState", "name": "VendingMachine2", "alarms": [ { "objectType": "TripAlarmType", "name": "VendingMachine2_DoorOpen", "id": "V2_DoorOpen" }, { "objectType": "OffNormalAlarmType", "name": "VendingMachine2_LightOff", "id": "V2_LightOff" } ] } ] } ], // This is the start of the replay part "script": { // This enable to have a waiting period before the replay starts "waitUntilStartInSeconds": 10, // Enable if the script should be executed in a loop "isScriptInRepeatingLoop": true, // How long the test should execute "runningForSeconds": 6000, // The steps // Two types of steps exist: // 1) Event - where a state is changed for an Alarm // 2) Sleep - insert a waiting time // For each step both of these values above can be set, but the recommendation are // to only set one of these in each step "steps": [ { "event": { // The Alarm id that was defined above "alarmId": "V1_DoorOpen", // This is a message that will be shown "reason": "Door Open", // Severity. Can be one of following values: Min, Low, MediumLow, Medium, MediumHigh, // High, Max (From Opc.Ua EventSeverity enum) "severity": "High", // This is the eventId. This needs to be unique // This is, when executed, combined with the number of the current loop // Example: "V1_DoorOpen-1 (1)" is the complete EventId for the first loop "eventId": "V1_DoorOpen-1", // This is a list of State changes that should be triggered in the event "stateChanges": [ { // Type of State Change // Currently only Enabled and Activated is supported "stateType": "Enabled", // True or False "state": true }, { "stateType": "Activated", "state": true } ] } }, { "sleepInSeconds": 5 }, { "event": { "alarmId": "V2_LightOff", "reason": "Light Off in machine", "severity": "Medium", "eventId": "V2_LightOff-1", "stateChanges": [ { "stateType": "Enabled", "state": true }, { "stateType": "Activated", "state": true } ] } }, { "sleepInSeconds": 7 }, { "event": { "alarmId": "V1_DoorOpen", "reason": "Door Closed", "severity": "Medium", "eventId": "V1_DoorOpen-2", "stateChanges": [ { "stateType": "Activated", "state": false } ] } }, { "sleepInSeconds": 4 }, { "event": { "alarmId": "V1_TemperatureHigh", "reason": "Temperature is HIGH", "severity": "High", "eventId": "V1_TemperatureHigh-1", "stateChanges": [ { "stateType": "Activated", "state": true }, { "stateType": "Enabled", "state": true } ] } } ] } } ``` ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/FileSystem/DirectoryBrowser.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace FileSystem { using Opc.Ua; using System.Collections.Generic; using System.IO; /// /// Browses the file system folder and files /// public class DirectoryBrowser : NodeBrowser { /// /// Create browser /// /// /// /// /// /// /// /// /// /// public DirectoryBrowser(ISystemContext context, ViewDescription view, NodeId referenceType, bool includeSubtypes, BrowseDirection browseDirection, QualifiedName browseName, IEnumerable additionalReferences, bool internalOnly, DirectoryObjectState source) : base(context, view, referenceType, includeSubtypes, browseDirection, browseName, additionalReferences, internalOnly) { _source = source; _stage = Stage.Begin; } /// /// Returns the next reference. /// /// The next reference that meets the browse criteria. public override IReference Next() { lock (DataLock) { // enumerate pre-defined references. // always call first to ensure any pushed-back references are returned first. var reference = base.Next(); if (reference != null) { return reference; } // don't start browsing huge number of references when only internal references are requested. if (InternalOnly) { return null; } if (!IsRequired(ReferenceTypeIds.HasComponent, false)) { return null; } if (_stage == Stage.Begin) { _directories = [.. Directory.GetDirectories(_source.FullPath)]; _stage = Stage.Directories; } // enumerate segments. if (_stage == Stage.Directories) { reference = NextChild(); if (reference != null) { return reference; } _files = [.. Directory.GetFiles(_source.FullPath)]; _stage = Stage.Files; } // enumerate files. if (_stage == Stage.Files) { reference = NextChild(); if (reference != null) { return reference; } _stage = Stage.Done; } // all done. return null; } } /// /// Returns the next child. /// private NodeStateReference NextChild() { NodeId targetId = null; // check if a specific browse name is requested. if (!QualifiedName.IsNull(BrowseName)) { // browse name must be qualified by the correct namespace. if (_source.BrowseName.NamespaceIndex != BrowseName.NamespaceIndex) { return null; } // look for matching directory. if (_stage == Stage.Directories && _directories != null) { foreach (var name in _directories) { if (BrowseName.Name == Path.GetFileName(name)) { targetId = ModelUtils.ConstructIdForDirectory(name, _source.NodeId.NamespaceIndex); _directories = null; break; } } _directories = null; } // look for matching file. if (_stage == Stage.Files && _files != null) { foreach (var name in _files) { if (BrowseName.Name == Path.GetFileName(name)) { targetId = ModelUtils.ConstructIdForFile(name, _source.NodeId.NamespaceIndex); _files = null; break; } } _files = null; } } // return the child at the next position. else { // look for next directory. if (_stage == Stage.Directories && _directories?.Count > 0) { var name = _directories[0]; _directories = _directories[1..]; targetId = ModelUtils.ConstructIdForDirectory(name, _source.NodeId.NamespaceIndex); } // look for next file. else if (_stage == Stage.Files && _files?.Count > 0) { var name = _files[0]; _files = _files[1..]; targetId = ModelUtils.ConstructIdForFile(name, _source.NodeId.NamespaceIndex); } } // create reference. if (targetId != null) { return new NodeStateReference(ReferenceTypeIds.HasComponent, false, targetId); } return null; } /// /// The stages available in a browse operation. /// private enum Stage { Begin, Directories, Files, Done } private Stage _stage; private readonly DirectoryObjectState _source; private List _files; private List _directories; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/FileSystem/DirectoryObjectState.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace FileSystem { using Opc.Ua; using Opc.Ua.Server; using System; using System.Collections.Generic; using System.IO; /// /// A object which maps a segment to directory /// public class DirectoryObjectState : FileDirectoryState { /// /// Gets the full path /// /// The segment path. public string FullPath { get; } /// /// Is volume /// public bool IsVolume { get; } /// /// Create directory object /// /// /// /// /// public DirectoryObjectState(ISystemContext context, NodeId nodeId, string path, bool isVolume) : base(null) { System.Diagnostics.Contracts.Contract.Assume(context != null); FullPath = path; IsVolume = isVolume; TypeDefinitionId = ObjectTypeIds.FileDirectoryType; SymbolicName = path; NodeId = nodeId; BrowseName = new QualifiedName(isVolume ? path : ModelUtils.GetName(path), nodeId.NamespaceIndex); DisplayName = new LocalizedText(isVolume ? path : ModelUtils.GetName(path)); Description = null; WriteMask = 0; UserWriteMask = 0; EventNotifier = EventNotifiers.None; DeleteFileSystemObject = new DeleteFileMethodState(this) { OnCall = new DeleteFileMethodStateMethodCallHandler(OnDeleteFileSystemObject), Executable = true, UserExecutable = true }; DeleteFileSystemObject.Create(context, MethodIds.FileDirectoryType_DeleteFileSystemObject, BrowseNames.DeleteFileSystemObject, BrowseNames.DeleteFileSystemObject, false); CreateFile = new CreateFileMethodState(this) { OnCall = new CreateFileMethodStateMethodCallHandler(OnCreateFile), Executable = true, UserExecutable = true }; CreateFile.Create(context, MethodIds.FileDirectoryType_CreateFile, BrowseNames.CreateFile, BrowseNames.CreateFile, false); CreateDirectory = new CreateDirectoryMethodState(this) { OnCall = new CreateDirectoryMethodStateMethodCallHandler(OnCreateDirectory), Executable = true, UserExecutable = true }; CreateDirectory.Create(context, MethodIds.FileDirectoryType_CreateDirectory, BrowseNames.CreateDirectory, BrowseNames.CreateDirectory, false); MoveOrCopy = new MoveOrCopyMethodState(this) { OnCall = new MoveOrCopyMethodStateMethodCallHandler(OnMoveOrCopy), Executable = true, UserExecutable = true }; MoveOrCopy.Create(context, MethodIds.FileDirectoryType_MoveOrCopy, BrowseNames.MoveOrCopy, BrowseNames.MoveOrCopy, false); } private ServiceResult OnMoveOrCopy(ISystemContext _context, MethodState _method, NodeId _objectId, NodeId objectToMoveOrCopy, NodeId targetDirectory, bool createCopy, string newName, ref NodeId newNodeId) { var objectToMoveOrCopy2 = ParsedNodeId.Parse(objectToMoveOrCopy); if (objectToMoveOrCopy2.RootType == ModelUtils.Volume) { return ServiceResult.Create(StatusCodes.BadInvalidArgument, "Source is not a directory or file"); } var targetDirectory2 = ParsedNodeId.Parse(targetDirectory); if (targetDirectory2.RootType != ModelUtils.Directory) { return ServiceResult.Create(StatusCodes.BadInvalidArgument, "Target is not a directory"); } var path = objectToMoveOrCopy2.RootId; var dst = Path.Combine(targetDirectory2.RootId, newName ?? Path.GetFileName(path)); try { if (File.Exists(path)) { if (createCopy) { File.Copy(path, dst); } else { File.Move(path, dst); } newNodeId = ModelUtils.ConstructIdForFile(dst, NodeId.NamespaceIndex); } else if (Directory.Exists(path)) { if (createCopy) { CopyDirectory(path, dst); } else { Directory.Move(path, dst); } newNodeId = ModelUtils.ConstructIdForDirectory(dst, NodeId.NamespaceIndex); } else { return ServiceResult.Create(StatusCodes.BadNotFound, $"File sytem object {path} not found"); } return ServiceResult.Good; } catch (Exception ex) { return ServiceResult.Create(ex, StatusCodes.BadUserAccessDenied, "Failed to move or copy"); } } private ServiceResult OnCreateDirectory(ISystemContext _context, MethodState _method, NodeId _objectId, string directoryName, ref NodeId directoryNodeId) { var name = Path.Combine(FullPath, directoryName); if (Path.Exists(name)) { return ServiceResult.Create(StatusCodes.BadBrowseNameDuplicated, "Directory or file with same name exists"); } Directory.CreateDirectory(name); directoryNodeId = ModelUtils.ConstructIdForDirectory(name, NodeId.NamespaceIndex); return ServiceResult.Good; } private ServiceResult OnCreateFile(ISystemContext _context, MethodState _method, NodeId _objectId, string fileName, bool requestFileOpen, ref NodeId fileNodeId, ref uint fileHandle) { var name = Path.Combine(FullPath, fileName); if (Path.Exists(name)) { return ServiceResult.Create(StatusCodes.BadBrowseNameDuplicated, "Directory or file with same name exists"); } fileNodeId = ModelUtils.ConstructIdForFile(name, NodeId.NamespaceIndex); if (requestFileOpen) { if (_context.SystemHandle is not FileSystem system || system.GetHandle(fileNodeId) is not FileHandle handle) { return ServiceResult.Create(StatusCodes.BadInvalidState, "Failed to get handle"); } return handle.Open(0x2, out fileHandle); // open for writing } try { using var f = File.Create(name); } catch (Exception ex) { return ServiceResult.Create(ex, null, StatusCodes.BadUserAccessDenied); } fileHandle = 0; return StatusCodes.Good; } private ServiceResult OnDeleteFileSystemObject(ISystemContext _context, MethodState _method, NodeId _objectId, NodeId objectToDelete) { var objectToDelete2 = ParsedNodeId.Parse(objectToDelete); var path = objectToDelete2.RootId; try { switch (objectToDelete2.RootType) { case ModelUtils.File: if (File.Exists(path)) { File.Delete(path); break; } return ServiceResult.Create(StatusCodes.BadNotFound, $"File sytem object {path} not found"); case ModelUtils.Directory: if (Directory.Exists(path)) { Directory.Delete(path, true); break; } return ServiceResult.Create(StatusCodes.BadNotFound, $"File sytem object {path} not found"); case ModelUtils.Volume: return ServiceResult.Create(StatusCodes.BadUserAccessDenied, "Cannot delete root of filesystem"); default: return ServiceResult.Create(StatusCodes.BadInvalidState, "Not a fileSystem object."); } } catch (Exception ex) { return ServiceResult.Create(ex, StatusCodes.BadUserAccessDenied, "Failed to delete file system object."); } return ServiceResult.Good; } /// /// Create browser on directory /// /// /// /// /// /// /// /// /// /// public override INodeBrowser CreateBrowser( ISystemContext context, ViewDescription view, NodeId referenceType, bool includeSubtypes, BrowseDirection browseDirection, QualifiedName browseName, IEnumerable additionalReferences, bool internalOnly) { NodeBrowser browser = new DirectoryBrowser( context, view, referenceType, includeSubtypes, browseDirection, browseName, additionalReferences, internalOnly, this); PopulateBrowser(context, browser); return browser; } /// /// Populates the browser with references that meet the criteria. /// /// The context for the system being accessed. /// The browser to populate. protected override void PopulateBrowser(ISystemContext context, NodeBrowser browser) { base.PopulateBrowser(context, browser); // check if the parent segments need to be returned. if (browser.IsRequired(ReferenceTypeIds.Organizes, true) && IsVolume) { // add reference to server browser.Add(ReferenceTypeIds.Organizes, true, ObjectIds.Server); } else if (browser.IsRequired(ReferenceTypeIds.HasComponent, true) && !IsVolume) { var parent = Path.GetDirectoryName(FullPath); if (Path.GetPathRoot(FullPath) == parent) { // add reference for parent volume. browser.Add(ReferenceTypeIds.HasComponent, true, ModelUtils.ConstructIdForVolume(parent, NodeId.NamespaceIndex)); } else { // add reference to parent directory browser.Add(ReferenceTypeIds.HasComponent, true, ModelUtils.ConstructIdForDirectory(parent, NodeId.NamespaceIndex)); } } } private static void CopyDirectory(string sourcePath, string targetPath) { foreach (var dirPath in Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories)) { Directory.CreateDirectory(dirPath.Replace(sourcePath, targetPath, StringComparison.InvariantCulture)); } foreach (var newPath in Directory.GetFiles(sourcePath, "*", SearchOption.AllDirectories)) { File.Copy(newPath, newPath.Replace(sourcePath, targetPath, StringComparison.InvariantCulture), true); } } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/FileSystem/FileHandle.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace FileSystem { using Opc.Ua; using Opc.Ua.Server; using System; using System.Collections.Generic; using System.IO; using System.Threading; /// /// File handle /// /// public sealed record FileHandle(ParsedNodeId NodeId) : IDisposable { private bool IsOpenForWrite => _write != null; private bool IsOpenForRead => _reads.Count > 0; /// /// Length /// public long Length => new FileInfo(NodeId.RootId).Length; /// /// Can be written to /// public bool IsWriteable => !IsOpenForRead && !IsOpenForWrite && !new FileInfo(NodeId.RootId).IsReadOnly; /// /// Last modification /// public DateTime LastModifiedTime => File.GetLastWriteTimeUtc(NodeId.RootId); /// /// How many file handles are open /// public ushort OpenCount => (ushort)(_reads.Count + (IsOpenForWrite ? 1 : 0)); /// /// Mime type /// public string MimeType { get; } = "text/plain"; // TODO /// /// Max byte string length /// public uint MaxByteStringLength { get; } = 4 * 1024; // TODO /// /// Get stream /// /// /// public Stream GetStream(uint fileHandle) { lock (_lock) { if (_write != null && fileHandle == 1) { return _write; } else if (_reads.TryGetValue(fileHandle, out var stream)) { return stream; } return null; } } /// /// Open /// /// /// /// public ServiceResult Open(byte mode, out uint fileHandle) { lock (_lock) { fileHandle = 0u; try { if (mode == 0x1) { if (_write != null) { return ServiceResult.Create(StatusCodes.BadInvalidState, "File already open for write"); } // read var stream = new FileStream(NodeId.RootId, FileMode.Open, FileAccess.Read); fileHandle = ++_handles; _reads.Add(fileHandle, stream); } else if ((mode & 0x2) != 0) { if (_reads.Count != 0 || _write != null) { return ServiceResult.Create(StatusCodes.BadInvalidState, "File already open for read or write"); } if ((mode & 0x4) != 0) { // Erase = OpenOrCreate + Truncate _write = new FileStream(NodeId.RootId, FileMode.Create, FileAccess.Write); } else if ((mode & 0x8) != 0) { // Append _write = new FileStream(NodeId.RootId, FileMode.Append, FileAccess.Write); } else { // Open or create _write = new FileStream(NodeId.RootId, FileMode.OpenOrCreate, FileAccess.Write); } fileHandle = 1u; } else { return ServiceResult.Create(StatusCodes.BadInvalidArgument, "Unknown mode value."); } } catch (Exception ex) { return ServiceResult.Create(ex, StatusCodes.BadUserAccessDenied, "Failed to open file"); } } return ServiceResult.Good; } public bool Close(uint fileHandle) { lock (_lock) { if (_write != null && fileHandle == 1) { _write.Dispose(); _write = null; return true; } if (_reads.TryGetValue(fileHandle, out var stream)) { stream.Dispose(); _reads.Remove(fileHandle); return true; } } return false; } public void Dispose() { _write?.Dispose(); foreach (var stream in _reads.Values) { stream.Dispose(); } _reads.Clear(); } private uint _handles = 1; private readonly Dictionary _reads = []; private readonly Lock _lock = new(); private Stream _write; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/FileSystem/FileObjectState.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace FileSystem { using Opc.Ua; using System; using System.IO; /// /// A object which maps a segment to a UA object. /// public class FileObjectState : FileState { /// /// Gets the path to the file /// /// The segment path. public string FullPath { get; } /// /// Initializes a new instance of the class. /// /// The context. /// The node id. /// The segment. public FileObjectState(ISystemContext context, NodeId nodeId, string path) : base(null) { System.Diagnostics.Contracts.Contract.Assume(context != null); FullPath = path; TypeDefinitionId = ObjectTypeIds.FileType; SymbolicName = path; NodeId = nodeId; BrowseName = new QualifiedName(Path.GetFileName(path), nodeId.NamespaceIndex); DisplayName = new LocalizedText(Path.GetFileName(path)); Description = null; WriteMask = 0; UserWriteMask = 0; EventNotifier = EventNotifiers.None; OpenCount = new PropertyState(this); OpenCount.OnReadValue += OnOpenCount; OpenCount.AccessLevel = AccessLevels.CurrentRead; OpenCount.UserAccessLevel = AccessLevels.CurrentRead; OpenCount.Create(context, VariableIds.FileType_OpenCount, BrowseNames.OpenCount, BrowseNames.OpenCount, true); Writable = new PropertyState(this); Writable.OnReadValue += OnWritable; Writable.AccessLevel = AccessLevels.CurrentRead; Writable.UserAccessLevel = AccessLevels.CurrentRead; Writable.Create(context, VariableIds.FileType_Writable, BrowseNames.Writable, BrowseNames.Writable, true); UserWritable = new PropertyState(this); UserWritable.OnReadValue += OnWritable; UserWritable.AccessLevel = AccessLevels.CurrentRead; UserWritable.UserAccessLevel = AccessLevels.CurrentRead; UserWritable.Create(context, VariableIds.FileType_UserWritable, BrowseNames.UserWritable, BrowseNames.UserWritable, true); Size = new PropertyState(this); Size.OnReadValue += OnSize; Size.AccessLevel = AccessLevels.CurrentRead; Size.UserAccessLevel = AccessLevels.CurrentRead; Size.Create(context, VariableIds.FileType_Size, BrowseNames.Size, BrowseNames.Size, true); MimeType = new PropertyState(this); MimeType.OnReadValue += OnMimeType; MimeType.AccessLevel = AccessLevels.CurrentRead; MimeType.UserAccessLevel = AccessLevels.CurrentRead; MimeType.Create(context, VariableIds.FileType_MimeType, BrowseNames.MimeType, BrowseNames.MimeType, true); #if OPTIONAL_MAX_BYTE_STRING MaxByteStringLength = new PropertyState(this); MaxByteStringLength.OnReadValue += OnMaxByteStringLength; MaxByteStringLength.AccessLevel = AccessLevels.CurrentRead; MaxByteStringLength.UserAccessLevel = AccessLevels.CurrentRead; MaxByteStringLength.Create(context, VariableIds.FileType_MaxByteStringLength, BrowseNames.MaxByteStringLength, BrowseNames.MaxByteStringLength, true); #endif LastModifiedTime = new PropertyState(this); LastModifiedTime.OnReadValue += OnLastModifiedTime; LastModifiedTime.AccessLevel = AccessLevels.CurrentRead; LastModifiedTime.UserAccessLevel = AccessLevels.CurrentRead; LastModifiedTime.Create(context, VariableIds.FileType_LastModifiedTime, BrowseNames.LastModifiedTime, BrowseNames.LastModifiedTime, true); Open = new OpenMethodState(this) { OnCall = new OpenMethodStateMethodCallHandler(OnOpen), Executable = true, UserExecutable = true }; Open.Create(context, MethodIds.FileType_Open, BrowseNames.Open, BrowseNames.Open, false); Write = new WriteMethodState(this) { OnCall = new WriteMethodStateMethodCallHandler(OnWrite), Executable = true, UserExecutable = true }; Write.Create(context, MethodIds.FileType_Write, BrowseNames.Write, BrowseNames.Write, false); Read = new ReadMethodState(this) { OnCall = new ReadMethodStateMethodCallHandler(OnRead), Executable = true, UserExecutable = true }; Read.Create(context, MethodIds.FileType_Read, BrowseNames.Read, BrowseNames.Read, false); Close = new CloseMethodState(this) { OnCall = new CloseMethodStateMethodCallHandler(OnClose), Executable = true, UserExecutable = true }; Close.Create(context, MethodIds.FileType_Close, BrowseNames.Close, BrowseNames.Close, false); GetPosition = new GetPositionMethodState(this) { OnCall = new GetPositionMethodStateMethodCallHandler(OnGetPosition), Executable = true, UserExecutable = true }; GetPosition.Create(context, MethodIds.FileType_GetPosition, BrowseNames.GetPosition, BrowseNames.GetPosition, false); SetPosition = new SetPositionMethodState(this) { OnCall = new SetPositionMethodStateMethodCallHandler(OnSetPosition), Executable = true, UserExecutable = true }; SetPosition.Create(context, MethodIds.FileType_SetPosition, BrowseNames.SetPosition, BrowseNames.SetPosition, false); } #if OPTIONAL_MAX_BYTE_STRING private ServiceResult OnMaxByteStringLength(ISystemContext context, NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp) { if (GetFileHandle(context, NodeId, out var handle, out var result)) { value = handle.MaxByteStringLength; timestamp = DateTime.UtcNow; statusCode = StatusCodes.Good; } return result; } #endif private ServiceResult OnMimeType(ISystemContext context, NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp) { if (GetFileHandle(context, NodeId, out var handle, out var result)) { value = handle.MimeType; timestamp = DateTime.UtcNow; statusCode = StatusCodes.Uncertain; } return result; } private ServiceResult OnLastModifiedTime(ISystemContext context, NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp) { if (GetFileHandle(context, NodeId, out var handle, out var result)) { value = handle.LastModifiedTime; timestamp = DateTime.UtcNow; statusCode = StatusCodes.Good; } return result; } private ServiceResult OnWritable(ISystemContext context, NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp) { if (GetFileHandle(context, NodeId, out var handle, out var result)) { value = handle.IsWriteable; timestamp = DateTime.UtcNow; statusCode = StatusCodes.Good; } return result; } private ServiceResult OnSize(ISystemContext context, NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp) { if (GetFileHandle(context, NodeId, out var handle, out var result)) { value = handle.Length; timestamp = DateTime.UtcNow; statusCode = StatusCodes.Good; } return result; } private ServiceResult OnOpenCount(ISystemContext context, NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp) { if (GetFileHandle(context, NodeId, out var handle, out var result)) { value = handle.OpenCount; timestamp = DateTime.UtcNow; statusCode = StatusCodes.Good; } return result; } private ServiceResult OnOpen(ISystemContext _context, MethodState _method, NodeId _objectId, byte mode, ref uint fileHandle) { if (GetFileHandle(_context, _objectId, out var handle, out var result)) { result = handle.Open(mode, out fileHandle); } return result; } private ServiceResult OnClose(ISystemContext _context, MethodState _method, NodeId _objectId, uint fileHandle) { if (GetFileHandle(_context, _objectId, out var handle, out var result) && !handle.Close(fileHandle)) { return ServiceResult.Create(StatusCodes.BadInvalidState, "File handle could not be closed."); } return result; } private ServiceResult OnSetPosition(ISystemContext _context, MethodState _method, NodeId _objectId, uint fileHandle, ulong position) { if (GetFileHandle(_context, _objectId, out var handle, out var result)) { var stream = handle.GetStream(fileHandle); if (stream == null) { return ServiceResult.Create(StatusCodes.BadInvalidState, "File handle not open."); } stream.Position = (long)position; } return result; } private ServiceResult OnGetPosition(ISystemContext _context, MethodState _method, NodeId _objectId, uint fileHandle, ref ulong position) { if (GetFileHandle(_context, _objectId, out var handle, out var result)) { var stream = handle.GetStream(fileHandle); if (stream == null) { return ServiceResult.Create(StatusCodes.BadInvalidState, "File handle not open."); } position = (ulong)stream.Position; } return result; } private ServiceResult OnRead(ISystemContext _context, MethodState _method, NodeId _objectId, uint fileHandle, int length, ref byte[] data) { if (GetFileHandle(_context, _objectId, out var handle, out var result)) { var stream = handle.GetStream(fileHandle); if (stream == null) { return ServiceResult.Create(StatusCodes.BadInvalidState, "File handle not open."); } var buffer = new Span(new byte[length]); var read = stream.Read(buffer); data = buffer[..read].ToArray(); } return result; } private ServiceResult OnWrite(ISystemContext _context, MethodState _method, NodeId _objectId, uint fileHandle, byte[] data) { if (GetFileHandle(_context, _objectId, out var handle, out var result)) { var stream = handle.GetStream(fileHandle); if (stream == null) { return StatusCodes.BadInvalidState; } stream.Write(data.AsSpan()); } return result; } /// /// Populates the browser with references that meet the criteria. /// /// The context for the system being accessed. /// The browser to populate. protected override void PopulateBrowser(ISystemContext context, NodeBrowser browser) { base.PopulateBrowser(context, browser); // check if the parent segments need to be returned. if (browser.IsRequired(ReferenceTypeIds.HasComponent, true)) { var directory = Path.GetDirectoryName(FullPath); if (Path.GetPathRoot(FullPath) == directory) { browser.Add(ReferenceTypeIds.HasComponent, true, ModelUtils.ConstructIdForVolume(directory, NodeId.NamespaceIndex)); } else { browser.Add(ReferenceTypeIds.HasComponent, true, ModelUtils.ConstructIdForDirectory(directory, NodeId.NamespaceIndex)); } } } private static bool GetFileHandle(ISystemContext context, NodeId nodeId, out FileHandle handle, out ServiceResult result) { if (context.SystemHandle is not FileSystem system || system.GetHandle(nodeId) is not FileHandle h) { result = ServiceResult.Create(StatusCodes.BadInvalidState, "Object is not a file."); handle = default; return false; } handle = h; result = ServiceResult.Good; return true; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/FileSystem/FileSystem.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace FileSystem { using Opc.Ua; using Opc.Ua.Server; using System; using System.Collections.Generic; using System.Threading; /// /// File system and handle management /// public sealed class FileSystem : IDisposable { public void Dispose() { lock (_syncRoot) { foreach (var handle in _handles.Values) { handle.Dispose(); } _handles.Clear(); } } public FileHandle GetHandle(NodeId nodeId) { lock (_syncRoot) { if (_handles.TryGetValue(nodeId, out var handle)) { return handle; } var parsed = ParsedNodeId.Parse(nodeId); if (parsed == null || parsed.RootType != ModelUtils.File) { return null; } handle = new FileHandle(parsed); _handles.Add(nodeId, handle); return handle; } } private readonly Lock _syncRoot = new(); private readonly Dictionary _handles = []; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/FileSystem/FileSystemNodeManager.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace FileSystem { using Opc.Ua; using Opc.Ua.Server; using System.Collections.Generic; using System.IO; using System.Linq; /// /// A node manager for a server that exposes several variables. /// public class FileSystemNodeManager : CustomNodeManager2 { /// /// Initializes the node manager. /// /// /// public FileSystemNodeManager(IServerInternal server, ApplicationConfiguration configuration) : base(server, configuration, Namespaces.FileSystem) { SystemContext.SystemHandle = _system = new FileSystem(); SystemContext.NodeIdFactory = this; var namespaceUris = new List { Namespaces.FileSystem }; NamespaceUris = namespaceUris; _namespaceIndex = Server.NamespaceUris.GetIndexOrAppend(namespaceUris[0]); // get the configuration for the node manager. // use suitable defaults if no configuration exists. _configuration = configuration.ParseExtension() ?? new FileSystemServerConfiguration(); } /// /// An overrideable version of the Dispose. /// /// protected override void Dispose(bool disposing) { if (disposing) { _system.Dispose(); } base.Dispose(disposing); } /// /// Creates the NodeId for the specified node. /// /// The context. /// The node. /// The new NodeId. /// /// This method is called by the NodeState.Create() method which initializes a Node from /// the type model. During initialization a number of child nodes are created and need to /// have NodeIds assigned to them. This implementation constructs NodeIds by constructing /// strings. Other implementations could assign unique integers or Guids and save the new /// Node in a dictionary for later lookup. /// public override NodeId New(ISystemContext context, NodeState node) { return ModelUtils.ConstructIdForComponent(node, NamespaceIndex); } /// /// Does any initialization required before the address space can be used. /// /// /// /// The externalReferences is an out parameter that allows the node manager to link to nodes /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and /// should have a reference to the root folder node(s) exposed by this node manager. /// public override void CreateAddressSpace(IDictionary> externalReferences) { lock (Lock) { // find the top level segments and link them to the Server folder. foreach (var fs in DriveInfo.GetDrives()) { if (!externalReferences.TryGetValue(ObjectIds.Server, out var references)) { externalReferences[ObjectIds.Server] = references = []; } // construct the NodeId of a segment. var fsId = ModelUtils.ConstructIdForVolume(fs.Name, _namespaceIndex); // add an organizes reference from the server to the volume. references.Add(new NodeStateReference(ReferenceTypeIds.Organizes, false, fsId)); } } } /// /// Frees any resources allocated for the address space. /// public override void DeleteAddressSpace() { lock (Lock) { } } /// /// Returns a unique handle for the node. /// /// /// /// protected override NodeHandle GetManagerHandle(ServerSystemContext context, NodeId nodeId, IDictionary cache) { lock (Lock) { // quickly exclude nodes that are not in the namespace. if (!IsNodeIdInNamespace(nodeId)) { return null; } if (nodeId.IdType != IdType.String && PredefinedNodes.TryGetValue(nodeId, out var node)) { return new NodeHandle { NodeId = nodeId, Node = node, Validated = true }; } // parse the identifier. var parsedNodeId = ParsedNodeId.Parse(nodeId); if (parsedNodeId != null) { return new NodeHandle { NodeId = nodeId, Validated = false, Node = null, ParsedNodeId = parsedNodeId }; } return null; } } /// /// Verifies that the specified node exists. /// /// /// /// protected override NodeState ValidateNode(ServerSystemContext context, NodeHandle handle, IDictionary cache) { // not valid if no root. if (handle == null) { return null; } // check if previously validated. if (handle.Validated) { return handle.Node; } NodeState target = null; // check if already in the cache. if (cache != null) { if (cache.TryGetValue(handle.NodeId, out target)) { // nulls mean a NodeId which was previously found to be invalid has been referenced again. if (target == null) { return null; } handle.Node = target; handle.Validated = true; return handle.Node; } target = null; } try { // check if the node id has been parsed. if (handle.ParsedNodeId is not ParsedNodeId parsedNodeId) { return null; } NodeState root = null; // Validate drive if (parsedNodeId.RootType == ModelUtils.Volume) { var volume = DriveInfo.GetDrives().FirstOrDefault(d => d.Name == parsedNodeId.RootId); // volume does not exist. if (volume == null) { return null; } var rootId = ModelUtils.ConstructIdForVolume(volume.Name, _namespaceIndex); // create a temporary object to use for the operation. #pragma warning disable CA2000 // Dispose objects before losing scope root = new DirectoryObjectState(context, rootId, volume.Name, true); #pragma warning restore CA2000 // Dispose objects before losing scope } // Validate directory else if (parsedNodeId.RootType == ModelUtils.Directory) { // block does not exist. if (!Path.Exists(parsedNodeId.RootId)) { return null; } var rootId = ModelUtils.ConstructIdForDirectory(parsedNodeId.RootId, _namespaceIndex); #pragma warning disable CA2000 // Dispose objects before losing scope root = new DirectoryObjectState(context, rootId, parsedNodeId.RootId, false); #pragma warning restore CA2000 // Dispose objects before losing scope } // Validate file else if (parsedNodeId.RootType == ModelUtils.File) { // block does not exist. if (!Path.Exists(parsedNodeId.RootId)) { return null; } var rootId = ModelUtils.ConstructIdForFile(parsedNodeId.RootId, _namespaceIndex); #pragma warning disable CA2000 // Dispose objects before losing scope root = new FileObjectState(context, rootId, parsedNodeId.RootId); #pragma warning restore CA2000 // Dispose objects before losing scope } // unknown root type. else { return null; } // all done if no components to validate. if (string.IsNullOrEmpty(parsedNodeId.ComponentPath)) { handle.Validated = true; handle.Node = target = root; return handle.Node; } // validate component. NodeState component = root.FindChildBySymbolicName(context, parsedNodeId.ComponentPath); // component does not exist. if (component == null) { return null; } // found a valid component. handle.Validated = true; handle.Node = target = component; return handle.Node; } finally { // store the node in the cache to optimize subsequent lookups. cache?.Add(handle.NodeId, target); } } private readonly ushort _namespaceIndex; #pragma warning disable IDE0052 // Remove unread private members private readonly FileSystemServerConfiguration _configuration; private readonly FileSystem _system; #pragma warning restore IDE0052 // Remove unread private members } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/FileSystem/FileSystemServer.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace FileSystem { using Opc.Ua; using Opc.Ua.Server; /// public class FileSystemServer : INodeManagerFactory { /// public StringCollection NamespacesUris { get { return [ Namespaces.FileSystem ]; } } /// public INodeManager Create(IServerInternal server, ApplicationConfiguration configuration) { return new FileSystemNodeManager(server, configuration); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/FileSystem/FileSystemServerConfiguration.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace FileSystem { using System.Runtime.Serialization; /// /// Stores the configuration the file system node manager. /// [DataContract(Namespace = Namespaces.FileSystem)] public class FileSystemServerConfiguration { /// /// The default constructor. /// public FileSystemServerConfiguration() { } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/FileSystem/ModelUtils.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace FileSystem { using Opc.Ua; using Opc.Ua.Server; using System.IO; using System.Text; /// /// A class that builds NodeIds used by the FileSystem NodeManager /// public static class ModelUtils { /// /// The RootType for a Volume node identfier. /// public const int Volume = 0; /// /// The RootType for a Directory node identfier. /// public const int Directory = 1; /// /// The RootType for a File node identfier. /// public const int File = 2; /// /// Create id for drive /// /// /// /// public static NodeId ConstructIdForVolume(string path, ushort namespaceIndex) { var parsedNodeId = new ParsedNodeId { RootId = path, NamespaceIndex = namespaceIndex, RootType = 0 }; return parsedNodeId.Construct(); } /// /// Constructs a NodeId a file or directory. /// /// The directory. /// Index of the namespace. /// The new NodeId. public static NodeId ConstructIdForDirectory(string path, ushort namespaceIndex) { var parsedNodeId = new ParsedNodeId { RootId = path, NamespaceIndex = namespaceIndex, RootType = 1 }; return parsedNodeId.Construct(); } /// /// Constructs a NodeId a file or directory. /// /// The file. /// Index of the namespace. /// The new NodeId. public static NodeId ConstructIdForFile(string path, ushort namespaceIndex) { var parsedNodeId = new ParsedNodeId { RootId = path, NamespaceIndex = namespaceIndex, RootType = 2 }; return parsedNodeId.Construct(); } public static string GetName(string path) { var name = Path.GetFileName(path); if (string.IsNullOrEmpty(name)) { return path; } return name; } /// /// Constructs the node identifier for a component. /// /// The component. /// Index of the namespace. /// The node identifier for a component. public static NodeId ConstructIdForComponent(NodeState component, ushort namespaceIndex) { if (component == null) { return null; } // components must be instances with a parent. if (component is not BaseInstanceState instance || instance.Parent == null) { return component.NodeId; } // parent must have a string identifier. if (instance.Parent.NodeId.Identifier is not string parentId) { return null; } var buffer = new StringBuilder(); buffer.Append(parentId); // check if the parent is another component. var index = parentId.IndexOf('?', System.StringComparison.InvariantCulture); if (index < 0) { buffer.Append('?'); } else { buffer.Append('/'); } buffer.Append(component.SymbolicName); // return the node identifier. return new NodeId(buffer.ToString(), namespaceIndex); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/FileSystem/Namespaces.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace FileSystem { /// /// Defines constants for namespaces used by the application. /// public static class Namespaces { /// /// The namespace for the nodes provided by the server. /// public const string FileSystem = "FileSystem"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Asset/Design/Asset.Classes.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2024 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; using System; using System.Collections.Generic; namespace Asset { #region WoTAssetConnectionManagementTypeState Class #if (!OPCUA_EXCLUDE_WoTAssetConnectionManagementTypeState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class WoTAssetConnectionManagementTypeState : BaseObjectState { #region Constructors /// public WoTAssetConnectionManagementTypeState(NodeState parent) : base(parent) { } /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(Asset.ObjectTypes.WoTAssetConnectionManagementType, Asset.Namespaces.WoT_Con, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACQAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvV29ULUNvbi//////BGCAAgEAAAABACgA" + "AABXb1RBc3NldENvbm5lY3Rpb25NYW5hZ2VtZW50VHlwZUluc3RhbmNlAQEBAAEBAQABAAAA/////wIA" + "AAAEYYIKBAAAAAEACwAAAENyZWF0ZUFzc2V0AQEaAAAvAQEaABoAAAABAf////8CAAAAF2CpCgIAAAAA" + "AA4AAABJbnB1dEFyZ3VtZW50cwEBGwAALgBEGwAAAJYBAAAAAQAqAQEYAAAACQAAAEFzc2V0TmFtZQAM" + "/////wAAAAAAAQAoAQEAAAABAAAAAQAAAAEB/////wAAAAAXYKkKAgAAAAAADwAAAE91dHB1dEFyZ3Vt" + "ZW50cwEBHAAALgBEHAAAAJYBAAAAAQAqAQEWAAAABwAAAEFzc2V0SWQAEf////8AAAAAAAEAKAEBAAAA" + "AQAAAAEAAAABAf////8AAAAABGGCCgQAAAABAAsAAABEZWxldGVBc3NldAEBHQAALwEBHQAdAAAAAQH/" + "////AQAAABdgqQoCAAAAAAAOAAAASW5wdXRBcmd1bWVudHMBAR4AAC4ARB4AAACWAQAAAAEAKgEBFgAA" + "AAcAAABBc3NldElkABH/////AAAAAAABACgBAQAAAAEAAAABAAAAAQH/////AAAAAA=="; #endregion #endif #endregion #region Public Properties /// public CreateAssetMethodState CreateAsset { get { return m_createAssetMethod; } set { if (!Object.ReferenceEquals(m_createAssetMethod, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_createAssetMethod = value; } } /// public DeleteAssetMethodState DeleteAsset { get { return m_deleteAssetMethod; } set { if (!Object.ReferenceEquals(m_deleteAssetMethod, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_deleteAssetMethod = value; } } #endregion #region Overridden Methods /// public override void GetChildren( ISystemContext context, IList children) { if (m_createAssetMethod != null) { children.Add(m_createAssetMethod); } if (m_deleteAssetMethod != null) { children.Add(m_deleteAssetMethod); } base.GetChildren(context, children); } /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case Asset.BrowseNames.CreateAsset: { if (createOrReplace) { if (CreateAsset == null) { if (replacement == null) { CreateAsset = new CreateAssetMethodState(this); } else { CreateAsset = (CreateAssetMethodState)replacement; } } } instance = CreateAsset; break; } case Asset.BrowseNames.DeleteAsset: { if (createOrReplace) { if (DeleteAsset == null) { if (replacement == null) { DeleteAsset = new DeleteAssetMethodState(this); } else { DeleteAsset = (DeleteAssetMethodState)replacement; } } } instance = DeleteAsset; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private CreateAssetMethodState m_createAssetMethod; private DeleteAssetMethodState m_deleteAssetMethod; #endregion } #endif #endregion #region IWoTAssetTypeState Class #if (!OPCUA_EXCLUDE_IWoTAssetTypeState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class IWoTAssetTypeState : BaseInterfaceState { #region Constructors /// public IWoTAssetTypeState(NodeState parent) : base(parent) { } /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(Asset.ObjectTypes.IWoTAssetType, Asset.Namespaces.WoT_Con, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACQAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvV29ULUNvbi//////BGCAAgEAAAABABUA" + "AABJV29UQXNzZXRUeXBlSW5zdGFuY2UBASoAAQEqACoAAAD/////AQAAAARggAoBAAAAAQAHAAAAV29U" + "RmlsZQEBKwAALwEBbgArAAAA/////wsAAAAVYIkKAgAAAAAABAAAAFNpemUBASwAAC4ARCwAAAAACf//" + "//8BAf////8AAAAAFWCJCgIAAAAAAAgAAABXcml0YWJsZQEBLQAALgBELQAAAAAB/////wEB/////wAA" + "AAAVYIkKAgAAAAAADAAAAFVzZXJXcml0YWJsZQEBLgAALgBELgAAAAAB/////wEB/////wAAAAAVYIkK" + "AgAAAAAACQAAAE9wZW5Db3VudAEBLwAALgBELwAAAAAF/////wEB/////wAAAAAEYYIKBAAAAAAABAAA" + "AE9wZW4BATMAAC8BADwtMwAAAAEB/////wIAAAAXYKkKAgAAAAAADgAAAElucHV0QXJndW1lbnRzAQE0" + "AAAuAEQ0AAAAlgEAAAABACoBARMAAAAEAAAATW9kZQAD/////wAAAAAAAQAoAQEAAAABAAAAAQAAAAEB" + "/////wAAAAAXYKkKAgAAAAAADwAAAE91dHB1dEFyZ3VtZW50cwEBNQAALgBENQAAAJYBAAAAAQAqAQEZ" + "AAAACgAAAEZpbGVIYW5kbGUAB/////8AAAAAAAEAKAEBAAAAAQAAAAEAAAABAf////8AAAAABGGCCgQA" + "AAAAAAUAAABDbG9zZQEBNgAALwEAPy02AAAAAQH/////AQAAABdgqQoCAAAAAAAOAAAASW5wdXRBcmd1" + "bWVudHMBATcAAC4ARDcAAACWAQAAAAEAKgEBGQAAAAoAAABGaWxlSGFuZGxlAAf/////AAAAAAABACgB" + "AQAAAAEAAAABAAAAAQH/////AAAAAARhggoEAAAAAAAEAAAAUmVhZAEBOAAALwEAQS04AAAAAQH/////" + "AgAAABdgqQoCAAAAAAAOAAAASW5wdXRBcmd1bWVudHMBATkAAC4ARDkAAACWAgAAAAEAKgEBGQAAAAoA" + "AABGaWxlSGFuZGxlAAf/////AAAAAAABACoBARUAAAAGAAAATGVuZ3RoAAb/////AAAAAAABACgBAQAA" + "AAEAAAACAAAAAQH/////AAAAABdgqQoCAAAAAAAPAAAAT3V0cHV0QXJndW1lbnRzAQE6AAAuAEQ6AAAA" + "lgEAAAABACoBARMAAAAEAAAARGF0YQAP/////wAAAAAAAQAoAQEAAAABAAAAAQAAAAEB/////wAAAAAE" + "YYIKBAAAAAAABQAAAFdyaXRlAQE7AAAvAQBELTsAAAABAf////8BAAAAF2CpCgIAAAAAAA4AAABJbnB1" + "dEFyZ3VtZW50cwEBPAAALgBEPAAAAJYCAAAAAQAqAQEZAAAACgAAAEZpbGVIYW5kbGUAB/////8AAAAA" + "AAEAKgEBEwAAAAQAAABEYXRhAA//////AAAAAAABACgBAQAAAAEAAAACAAAAAQH/////AAAAAARhggoE" + "AAAAAAALAAAAR2V0UG9zaXRpb24BAT0AAC8BAEYtPQAAAAEB/////wIAAAAXYKkKAgAAAAAADgAAAElu" + "cHV0QXJndW1lbnRzAQE+AAAuAEQ+AAAAlgEAAAABACoBARkAAAAKAAAARmlsZUhhbmRsZQAH/////wAA" + "AAAAAQAoAQEAAAABAAAAAQAAAAEB/////wAAAAAXYKkKAgAAAAAADwAAAE91dHB1dEFyZ3VtZW50cwEB" + "PwAALgBEPwAAAJYBAAAAAQAqAQEXAAAACAAAAFBvc2l0aW9uAAn/////AAAAAAABACgBAQAAAAEAAAAB" + "AAAAAQH/////AAAAAARhggoEAAAAAAALAAAAU2V0UG9zaXRpb24BAUAAAC8BAEktQAAAAAEB/////wEA" + "AAAXYKkKAgAAAAAADgAAAElucHV0QXJndW1lbnRzAQFBAAAuAERBAAAAlgIAAAABACoBARkAAAAKAAAA" + "RmlsZUhhbmRsZQAH/////wAAAAAAAQAqAQEXAAAACAAAAFBvc2l0aW9uAAn/////AAAAAAABACgBAQAA" + "AAEAAAACAAAAAQH/////AAAAAARhggoEAAAAAQAOAAAAQ2xvc2VBbmRVcGRhdGUBAWoAAC8BAW8AagAA" + "AAEB/////wEAAAAXYKkKAgAAAAAADgAAAElucHV0QXJndW1lbnRzAQFrAAAuAERrAAAAlgEAAAABACoB" + "ARkAAAAKAAAARmlsZUhhbmRsZQAH/////wAAAAAAAQAoAQEAAAABAAAAAQAAAAEB/////wAAAAA="; #endregion #endif #endregion #region Public Properties /// public WoTAssetFileTypeState WoTFile { get { return m_woTFile; } set { if (!Object.ReferenceEquals(m_woTFile, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_woTFile = value; } } #endregion #region Overridden Methods /// public override void GetChildren( ISystemContext context, IList children) { if (m_woTFile != null) { children.Add(m_woTFile); } base.GetChildren(context, children); } /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case Asset.BrowseNames.WoTFile: { if (createOrReplace) { if (WoTFile == null) { if (replacement == null) { WoTFile = new WoTAssetFileTypeState(this); } else { WoTFile = (WoTAssetFileTypeState)replacement; } } } instance = WoTFile; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private WoTAssetFileTypeState m_woTFile; #endregion } #endif #endregion #region WoTAssetTypeState Class #if (!OPCUA_EXCLUDE_WoTAssetTypeState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class WoTAssetTypeState : BaseObjectState { #region Constructors /// public WoTAssetTypeState(NodeState parent) : base(parent) { } /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(Asset.ObjectTypes.WoTAssetType, Asset.Namespaces.WoT_Con, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACQAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvV29ULUNvbi//////BGCAAgEAAAABABQA" + "AABXb1RBc3NldFR5cGVJbnN0YW5jZQEBcwABAXMAcwAAAAEAAAABAMNEAAEBKgABAAAABGCACgEAAAAB" + "AAcAAABXb1RGaWxlAQF0AAAvAQFuAHQAAAD/////CwAAABVgiQoCAAAAAAAEAAAAU2l6ZQEBdQAALgBE" + "dQAAAAAJ/////wEB/////wAAAAAVYIkKAgAAAAAACAAAAFdyaXRhYmxlAQF2AAAuAER2AAAAAAH/////" + "AQH/////AAAAABVgiQoCAAAAAAAMAAAAVXNlcldyaXRhYmxlAQF3AAAuAER3AAAAAAH/////AQH/////" + "AAAAABVgiQoCAAAAAAAJAAAAT3BlbkNvdW50AQF4AAAuAER4AAAAAAX/////AQH/////AAAAAARhggoE" + "AAAAAAAEAAAAT3BlbgEBfAAALwEAPC18AAAAAQH/////AgAAABdgqQoCAAAAAAAOAAAASW5wdXRBcmd1" + "bWVudHMBAX0AAC4ARH0AAACWAQAAAAEAKgEBEwAAAAQAAABNb2RlAAP/////AAAAAAABACgBAQAAAAEA" + "AAABAAAAAQH/////AAAAABdgqQoCAAAAAAAPAAAAT3V0cHV0QXJndW1lbnRzAQF+AAAuAER+AAAAlgEA" + "AAABACoBARkAAAAKAAAARmlsZUhhbmRsZQAH/////wAAAAAAAQAoAQEAAAABAAAAAQAAAAEB/////wAA" + "AAAEYYIKBAAAAAAABQAAAENsb3NlAQF/AAAvAQA/LX8AAAABAf////8BAAAAF2CpCgIAAAAAAA4AAABJ" + "bnB1dEFyZ3VtZW50cwEBgAAALgBEgAAAAJYBAAAAAQAqAQEZAAAACgAAAEZpbGVIYW5kbGUAB/////8A" + "AAAAAAEAKAEBAAAAAQAAAAEAAAABAf////8AAAAABGGCCgQAAAAAAAQAAABSZWFkAQGBAAAvAQBBLYEA" + "AAABAf////8CAAAAF2CpCgIAAAAAAA4AAABJbnB1dEFyZ3VtZW50cwEBggAALgBEggAAAJYCAAAAAQAq" + "AQEZAAAACgAAAEZpbGVIYW5kbGUAB/////8AAAAAAAEAKgEBFQAAAAYAAABMZW5ndGgABv////8AAAAA" + "AAEAKAEBAAAAAQAAAAIAAAABAf////8AAAAAF2CpCgIAAAAAAA8AAABPdXRwdXRBcmd1bWVudHMBAYMA" + "AC4ARIMAAACWAQAAAAEAKgEBEwAAAAQAAABEYXRhAA//////AAAAAAABACgBAQAAAAEAAAABAAAAAQH/" + "////AAAAAARhggoEAAAAAAAFAAAAV3JpdGUBAYQAAC8BAEQthAAAAAEB/////wEAAAAXYKkKAgAAAAAA" + "DgAAAElucHV0QXJndW1lbnRzAQGFAAAuAESFAAAAlgIAAAABACoBARkAAAAKAAAARmlsZUhhbmRsZQAH" + "/////wAAAAAAAQAqAQETAAAABAAAAERhdGEAD/////8AAAAAAAEAKAEBAAAAAQAAAAIAAAABAf////8A" + "AAAABGGCCgQAAAAAAAsAAABHZXRQb3NpdGlvbgEBhgAALwEARi2GAAAAAQH/////AgAAABdgqQoCAAAA" + "AAAOAAAASW5wdXRBcmd1bWVudHMBAYcAAC4ARIcAAACWAQAAAAEAKgEBGQAAAAoAAABGaWxlSGFuZGxl" + "AAf/////AAAAAAABACgBAQAAAAEAAAABAAAAAQH/////AAAAABdgqQoCAAAAAAAPAAAAT3V0cHV0QXJn" + "dW1lbnRzAQGIAAAuAESIAAAAlgEAAAABACoBARcAAAAIAAAAUG9zaXRpb24ACf////8AAAAAAAEAKAEB" + "AAAAAQAAAAEAAAABAf////8AAAAABGGCCgQAAAAAAAsAAABTZXRQb3NpdGlvbgEBiQAALwEASS2JAAAA" + "AQH/////AQAAABdgqQoCAAAAAAAOAAAASW5wdXRBcmd1bWVudHMBAYoAAC4ARIoAAACWAgAAAAEAKgEB" + "GQAAAAoAAABGaWxlSGFuZGxlAAf/////AAAAAAABACoBARcAAAAIAAAAUG9zaXRpb24ACf////8AAAAA" + "AAEAKAEBAAAAAQAAAAIAAAABAf////8AAAAABGGCCgQAAAABAA4AAABDbG9zZUFuZFVwZGF0ZQEBiwAA" + "LwEBbwCLAAAAAQH/////AQAAABdgqQoCAAAAAAAOAAAASW5wdXRBcmd1bWVudHMBAYwAAC4ARIwAAACW" + "AQAAAAEAKgEBGQAAAAoAAABGaWxlSGFuZGxlAAf/////AAAAAAABACgBAQAAAAEAAAABAAAAAQH/////" + "AAAAAA=="; #endregion #endif #endregion #region Public Properties /// public WoTAssetFileTypeState WoTFile { get { return m_woTFile; } set { if (!Object.ReferenceEquals(m_woTFile, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_woTFile = value; } } #endregion #region Overridden Methods /// public override void GetChildren( ISystemContext context, IList children) { if (m_woTFile != null) { children.Add(m_woTFile); } base.GetChildren(context, children); } /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case Asset.BrowseNames.WoTFile: { if (createOrReplace) { if (WoTFile == null) { if (replacement == null) { WoTFile = new WoTAssetFileTypeState(this); } else { WoTFile = (WoTAssetFileTypeState)replacement; } } } instance = WoTFile; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private WoTAssetFileTypeState m_woTFile; #endregion } #endif #endregion #region WoTAssetFileTypeState Class #if (!OPCUA_EXCLUDE_WoTAssetFileTypeState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class WoTAssetFileTypeState : FileState { #region Constructors /// public WoTAssetFileTypeState(NodeState parent) : base(parent) { } /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(Asset.ObjectTypes.WoTAssetFileType, Asset.Namespaces.WoT_Con, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACQAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvV29ULUNvbi//////BGCAAgEAAAABABgA" + "AABXb1RBc3NldEZpbGVUeXBlSW5zdGFuY2UBAW4AAQFuAG4AAAD/////CwAAABVgiQgCAAAAAAAEAAAA" + "U2l6ZQEBAAAALgBEAAn/////AQH/////AAAAABVgiQgCAAAAAAAIAAAAV3JpdGFibGUBAQAAAC4ARAAB" + "/////wEB/////wAAAAAVYIkIAgAAAAAADAAAAFVzZXJXcml0YWJsZQEBAAAALgBEAAH/////AQH/////" + "AAAAABVgiQgCAAAAAAAJAAAAT3BlbkNvdW50AQEAAAAuAEQABf////8BAf////8AAAAABGGCCAQAAAAA" + "AAQAAABPcGVuAQEAAAAvAQA8LQEB/////wIAAAAXYKkIAgAAAAAADgAAAElucHV0QXJndW1lbnRzAQEA" + "AAAuAESWAQAAAAEAKgEBEwAAAAQAAABNb2RlAAP/////AAAAAAABACgBAQAAAAEAAAABAAAAAQH/////" + "AAAAABdgqQgCAAAAAAAPAAAAT3V0cHV0QXJndW1lbnRzAQEAAAAuAESWAQAAAAEAKgEBGQAAAAoAAABG" + "aWxlSGFuZGxlAAf/////AAAAAAABACgBAQAAAAEAAAABAAAAAQH/////AAAAAARhgggEAAAAAAAFAAAA" + "Q2xvc2UBAQAAAC8BAD8tAQH/////AQAAABdgqQgCAAAAAAAOAAAASW5wdXRBcmd1bWVudHMBAQAAAC4A" + "RJYBAAAAAQAqAQEZAAAACgAAAEZpbGVIYW5kbGUAB/////8AAAAAAAEAKAEBAAAAAQAAAAEAAAABAf//" + "//8AAAAABGGCCAQAAAAAAAQAAABSZWFkAQEAAAAvAQBBLQEB/////wIAAAAXYKkIAgAAAAAADgAAAElu" + "cHV0QXJndW1lbnRzAQEAAAAuAESWAgAAAAEAKgEBGQAAAAoAAABGaWxlSGFuZGxlAAf/////AAAAAAAB" + "ACoBARUAAAAGAAAATGVuZ3RoAAb/////AAAAAAABACgBAQAAAAEAAAACAAAAAQH/////AAAAABdgqQgC" + "AAAAAAAPAAAAT3V0cHV0QXJndW1lbnRzAQEAAAAuAESWAQAAAAEAKgEBEwAAAAQAAABEYXRhAA//////" + "AAAAAAABACgBAQAAAAEAAAABAAAAAQH/////AAAAAARhgggEAAAAAAAFAAAAV3JpdGUBAQAAAC8BAEQt" + "AQH/////AQAAABdgqQgCAAAAAAAOAAAASW5wdXRBcmd1bWVudHMBAQAAAC4ARJYCAAAAAQAqAQEZAAAA" + "CgAAAEZpbGVIYW5kbGUAB/////8AAAAAAAEAKgEBEwAAAAQAAABEYXRhAA//////AAAAAAABACgBAQAA" + "AAEAAAACAAAAAQH/////AAAAAARhgggEAAAAAAALAAAAR2V0UG9zaXRpb24BAQAAAC8BAEYtAQH/////" + "AgAAABdgqQgCAAAAAAAOAAAASW5wdXRBcmd1bWVudHMBAQAAAC4ARJYBAAAAAQAqAQEZAAAACgAAAEZp" + "bGVIYW5kbGUAB/////8AAAAAAAEAKAEBAAAAAQAAAAEAAAABAf////8AAAAAF2CpCAIAAAAAAA8AAABP" + "dXRwdXRBcmd1bWVudHMBAQAAAC4ARJYBAAAAAQAqAQEXAAAACAAAAFBvc2l0aW9uAAn/////AAAAAAAB" + "ACgBAQAAAAEAAAABAAAAAQH/////AAAAAARhgggEAAAAAAALAAAAU2V0UG9zaXRpb24BAQAAAC8BAEkt" + "AQH/////AQAAABdgqQgCAAAAAAAOAAAASW5wdXRBcmd1bWVudHMBAQAAAC4ARJYCAAAAAQAqAQEZAAAA" + "CgAAAEZpbGVIYW5kbGUAB/////8AAAAAAAEAKgEBFwAAAAgAAABQb3NpdGlvbgAJ/////wAAAAAAAQAo" + "AQEAAAABAAAAAgAAAAEB/////wAAAAAEYYIKBAAAAAEADgAAAENsb3NlQW5kVXBkYXRlAQFvAAAvAQFv" + "AG8AAAABAf////8BAAAAF2CpCgIAAAAAAA4AAABJbnB1dEFyZ3VtZW50cwEBcAAALgBEcAAAAJYBAAAA" + "AQAqAQEZAAAACgAAAEZpbGVIYW5kbGUAB/////8AAAAAAAEAKAEBAAAAAQAAAAEAAAABAf////8AAAAA"; #endregion #endif #endregion #region Public Properties /// public CloseAndUpdateMethodState CloseAndUpdate { get { return m_closeAndUpdateMethod; } set { if (!Object.ReferenceEquals(m_closeAndUpdateMethod, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_closeAndUpdateMethod = value; } } #endregion #region Overridden Methods /// public override void GetChildren( ISystemContext context, IList children) { if (m_closeAndUpdateMethod != null) { children.Add(m_closeAndUpdateMethod); } base.GetChildren(context, children); } /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case Asset.BrowseNames.CloseAndUpdate: { if (createOrReplace) { if (CloseAndUpdate == null) { if (replacement == null) { CloseAndUpdate = new CloseAndUpdateMethodState(this); } else { CloseAndUpdate = (CloseAndUpdateMethodState)replacement; } } } instance = CloseAndUpdate; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private CloseAndUpdateMethodState m_closeAndUpdateMethod; #endregion } #endif #endregion #region CreateAssetMethodState Class #if (!OPCUA_EXCLUDE_CreateAssetMethodState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class CreateAssetMethodState : MethodState { #region Constructors /// public CreateAssetMethodState(NodeState parent) : base(parent) { } /// public new static NodeState Construct(NodeState parent) { return new CreateAssetMethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACQAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvV29ULUNvbi//////BGGCAAQAAAABABUA" + "AABDcmVhdGVBc3NldE1ldGhvZFR5cGUBAQAAAQEAAAEB/////wAAAAA="; #endregion #endif #endregion #region Event Callbacks /// public CreateAssetMethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult _result = null; string assetName = (string)_inputArguments[0]; NodeId assetId = (NodeId)_outputArguments[0]; if (OnCall != null) { _result = OnCall( _context, this, _objectId, assetName, ref assetId); } _outputArguments[0] = assetId; return _result; } #endregion #region Private Fields #endregion } /// public delegate ServiceResult CreateAssetMethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, string assetName, ref NodeId assetId); #endif #endregion #region DeleteAssetMethodState Class #if (!OPCUA_EXCLUDE_DeleteAssetMethodState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class DeleteAssetMethodState : MethodState { #region Constructors /// public DeleteAssetMethodState(NodeState parent) : base(parent) { } /// public new static NodeState Construct(NodeState parent) { return new DeleteAssetMethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACQAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvV29ULUNvbi//////BGGCAAQAAAABABUA" + "AABEZWxldGVBc3NldE1ldGhvZFR5cGUBAQAAAQEAAAEB/////wAAAAA="; #endregion #endif #endregion #region Event Callbacks /// public DeleteAssetMethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult _result = null; NodeId assetId = (NodeId)_inputArguments[0]; if (OnCall != null) { _result = OnCall( _context, this, _objectId, assetId); } return _result; } #endregion #region Private Fields #endregion } /// public delegate ServiceResult DeleteAssetMethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, NodeId assetId); #endif #endregion #region CloseAndUpdateMethodState Class #if (!OPCUA_EXCLUDE_CloseAndUpdateMethodState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class CloseAndUpdateMethodState : MethodState { #region Constructors /// public CloseAndUpdateMethodState(NodeState parent) : base(parent) { } /// public new static NodeState Construct(NodeState parent) { return new CloseAndUpdateMethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACQAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvV29ULUNvbi//////BGGCAAQAAAABABgA" + "AABDbG9zZUFuZFVwZGF0ZU1ldGhvZFR5cGUBAQAAAQEAAAEB/////wAAAAA="; #endregion #endif #endregion #region Event Callbacks /// public CloseAndUpdateMethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult _result = null; uint fileHandle = (uint)_inputArguments[0]; if (OnCall != null) { _result = OnCall( _context, this, _objectId, fileHandle); } return _result; } #endregion #region Private Fields #endregion } /// public delegate ServiceResult CloseAndUpdateMethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, uint fileHandle); #endif #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Asset/Design/Asset.Constants.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2024 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; namespace Asset { #region Method Identifiers /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Methods { /// public const uint WoTAssetConnectionManagementType_CreateAsset = 26; /// public const uint WoTAssetConnectionManagementType_DeleteAsset = 29; /// public const uint WoTAssetConnectionManagement_CreateAsset = 32; /// public const uint WoTAssetConnectionManagement_DeleteAsset = 35; /// public const uint IWoTAssetType_WoTFile_Open = 51; /// public const uint IWoTAssetType_WoTFile_Close = 54; /// public const uint IWoTAssetType_WoTFile_Read = 56; /// public const uint IWoTAssetType_WoTFile_Write = 59; /// public const uint IWoTAssetType_WoTFile_GetPosition = 61; /// public const uint IWoTAssetType_WoTFile_SetPosition = 64; /// public const uint IWoTAssetType_WoTFile_CloseAndUpdate = 106; /// public const uint WoTAssetType_WoTFile_Open = 124; /// public const uint WoTAssetType_WoTFile_Close = 127; /// public const uint WoTAssetType_WoTFile_Read = 129; /// public const uint WoTAssetType_WoTFile_Write = 132; /// public const uint WoTAssetType_WoTFile_GetPosition = 134; /// public const uint WoTAssetType_WoTFile_SetPosition = 137; /// public const uint WoTAssetType_WoTFile_CloseAndUpdate = 139; /// public const uint WoTAssetFileType_CloseAndUpdate = 111; /// public const string WoTAssetConnectionManagementType_CreateAssetMethodType = ""; /// public const string WoTAssetConnectionManagementType_DeleteAssetMethodType = ""; /// public const string WoTAssetFileType_CloseAndUpdateMethodType = ""; } #endregion #region Object Identifiers /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Objects { /// public const uint WoTAssetConnectionManagementType_WoTAssetName_Placeholder = 2; /// public const uint WoTAssetConnectionManagement = 31; /// public const uint IWoTAssetType_WoTFile = 43; /// public const uint WoTAssetType_WoTFile = 116; } #endregion #region ObjectType Identifiers /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectTypes { /// public const uint WoTAssetConnectionManagementType = 1; /// public const uint IWoTAssetType = 42; /// public const uint WoTAssetType = 115; /// public const uint WoTAssetFileType = 110; } #endregion #region ReferenceType Identifiers /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ReferenceTypes { /// public const uint HasWoTComponent = 142; } #endregion #region Variable Identifiers /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Variables { /// public const uint WoTAssetConnectionManagementType_CreateAsset_InputArguments = 27; /// public const uint WoTAssetConnectionManagementType_CreateAsset_OutputArguments = 28; /// public const uint WoTAssetConnectionManagementType_DeleteAsset_InputArguments = 30; /// public const uint WoTAssetConnectionManagement_CreateAsset_InputArguments = 33; /// public const uint WoTAssetConnectionManagement_CreateAsset_OutputArguments = 34; /// public const uint WoTAssetConnectionManagement_DeleteAsset_InputArguments = 36; /// public const uint IWoTAssetType_WoTFile_Size = 44; /// public const uint IWoTAssetType_WoTFile_Writable = 45; /// public const uint IWoTAssetType_WoTFile_UserWritable = 46; /// public const uint IWoTAssetType_WoTFile_OpenCount = 47; /// public const uint IWoTAssetType_WoTFile_Open_InputArguments = 52; /// public const uint IWoTAssetType_WoTFile_Open_OutputArguments = 53; /// public const uint IWoTAssetType_WoTFile_Close_InputArguments = 55; /// public const uint IWoTAssetType_WoTFile_Read_InputArguments = 57; /// public const uint IWoTAssetType_WoTFile_Read_OutputArguments = 58; /// public const uint IWoTAssetType_WoTFile_Write_InputArguments = 60; /// public const uint IWoTAssetType_WoTFile_GetPosition_InputArguments = 62; /// public const uint IWoTAssetType_WoTFile_GetPosition_OutputArguments = 63; /// public const uint IWoTAssetType_WoTFile_SetPosition_InputArguments = 65; /// public const uint IWoTAssetType_WoTFile_CloseAndUpdate_InputArguments = 107; /// public const uint IWoTAssetType_WoTPropertyName_Placeholder = 66; /// public const uint WoTAssetType_WoTFile_Size = 117; /// public const uint WoTAssetType_WoTFile_Writable = 118; /// public const uint WoTAssetType_WoTFile_UserWritable = 119; /// public const uint WoTAssetType_WoTFile_OpenCount = 120; /// public const uint WoTAssetType_WoTFile_Open_InputArguments = 125; /// public const uint WoTAssetType_WoTFile_Open_OutputArguments = 126; /// public const uint WoTAssetType_WoTFile_Close_InputArguments = 128; /// public const uint WoTAssetType_WoTFile_Read_InputArguments = 130; /// public const uint WoTAssetType_WoTFile_Read_OutputArguments = 131; /// public const uint WoTAssetType_WoTFile_Write_InputArguments = 133; /// public const uint WoTAssetType_WoTFile_GetPosition_InputArguments = 135; /// public const uint WoTAssetType_WoTFile_GetPosition_OutputArguments = 136; /// public const uint WoTAssetType_WoTFile_SetPosition_InputArguments = 138; /// public const uint WoTAssetType_WoTFile_CloseAndUpdate_InputArguments = 140; /// public const uint WoTAssetType_WoTPropertyName_Placeholder = 141; /// public const uint WoTAssetFileType_CloseAndUpdate_InputArguments = 112; } #endregion #region Method Node Identifiers /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class MethodIds { /// public static readonly ExpandedNodeId WoTAssetConnectionManagementType_CreateAsset = new ExpandedNodeId(Asset.Methods.WoTAssetConnectionManagementType_CreateAsset, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetConnectionManagementType_DeleteAsset = new ExpandedNodeId(Asset.Methods.WoTAssetConnectionManagementType_DeleteAsset, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetConnectionManagement_CreateAsset = new ExpandedNodeId(Asset.Methods.WoTAssetConnectionManagement_CreateAsset, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetConnectionManagement_DeleteAsset = new ExpandedNodeId(Asset.Methods.WoTAssetConnectionManagement_DeleteAsset, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId IWoTAssetType_WoTFile_Open = new ExpandedNodeId(Asset.Methods.IWoTAssetType_WoTFile_Open, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId IWoTAssetType_WoTFile_Close = new ExpandedNodeId(Asset.Methods.IWoTAssetType_WoTFile_Close, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId IWoTAssetType_WoTFile_Read = new ExpandedNodeId(Asset.Methods.IWoTAssetType_WoTFile_Read, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId IWoTAssetType_WoTFile_Write = new ExpandedNodeId(Asset.Methods.IWoTAssetType_WoTFile_Write, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId IWoTAssetType_WoTFile_GetPosition = new ExpandedNodeId(Asset.Methods.IWoTAssetType_WoTFile_GetPosition, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId IWoTAssetType_WoTFile_SetPosition = new ExpandedNodeId(Asset.Methods.IWoTAssetType_WoTFile_SetPosition, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId IWoTAssetType_WoTFile_CloseAndUpdate = new ExpandedNodeId(Asset.Methods.IWoTAssetType_WoTFile_CloseAndUpdate, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetType_WoTFile_Open = new ExpandedNodeId(Asset.Methods.WoTAssetType_WoTFile_Open, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetType_WoTFile_Close = new ExpandedNodeId(Asset.Methods.WoTAssetType_WoTFile_Close, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetType_WoTFile_Read = new ExpandedNodeId(Asset.Methods.WoTAssetType_WoTFile_Read, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetType_WoTFile_Write = new ExpandedNodeId(Asset.Methods.WoTAssetType_WoTFile_Write, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetType_WoTFile_GetPosition = new ExpandedNodeId(Asset.Methods.WoTAssetType_WoTFile_GetPosition, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetType_WoTFile_SetPosition = new ExpandedNodeId(Asset.Methods.WoTAssetType_WoTFile_SetPosition, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetType_WoTFile_CloseAndUpdate = new ExpandedNodeId(Asset.Methods.WoTAssetType_WoTFile_CloseAndUpdate, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetFileType_CloseAndUpdate = new ExpandedNodeId(Asset.Methods.WoTAssetFileType_CloseAndUpdate, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetConnectionManagementType_CreateAssetMethodType = new ExpandedNodeId(Asset.Methods.WoTAssetConnectionManagementType_CreateAssetMethodType, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetConnectionManagementType_DeleteAssetMethodType = new ExpandedNodeId(Asset.Methods.WoTAssetConnectionManagementType_DeleteAssetMethodType, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetFileType_CloseAndUpdateMethodType = new ExpandedNodeId(Asset.Methods.WoTAssetFileType_CloseAndUpdateMethodType, Asset.Namespaces.WoT_Con); } #endregion #region Object Node Identifiers /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectIds { /// public static readonly ExpandedNodeId WoTAssetConnectionManagementType_WoTAssetName_Placeholder = new ExpandedNodeId(Asset.Objects.WoTAssetConnectionManagementType_WoTAssetName_Placeholder, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetConnectionManagement = new ExpandedNodeId(Asset.Objects.WoTAssetConnectionManagement, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId IWoTAssetType_WoTFile = new ExpandedNodeId(Asset.Objects.IWoTAssetType_WoTFile, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetType_WoTFile = new ExpandedNodeId(Asset.Objects.WoTAssetType_WoTFile, Asset.Namespaces.WoT_Con); } #endregion #region ObjectType Node Identifiers /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectTypeIds { /// public static readonly ExpandedNodeId WoTAssetConnectionManagementType = new ExpandedNodeId(Asset.ObjectTypes.WoTAssetConnectionManagementType, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId IWoTAssetType = new ExpandedNodeId(Asset.ObjectTypes.IWoTAssetType, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetType = new ExpandedNodeId(Asset.ObjectTypes.WoTAssetType, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetFileType = new ExpandedNodeId(Asset.ObjectTypes.WoTAssetFileType, Asset.Namespaces.WoT_Con); } #endregion #region ReferenceType Node Identifiers /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ReferenceTypeIds { /// public static readonly ExpandedNodeId HasWoTComponent = new ExpandedNodeId(Asset.ReferenceTypes.HasWoTComponent, Asset.Namespaces.WoT_Con); } #endregion #region Variable Node Identifiers /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class VariableIds { /// public static readonly ExpandedNodeId WoTAssetConnectionManagementType_CreateAsset_InputArguments = new ExpandedNodeId(Asset.Variables.WoTAssetConnectionManagementType_CreateAsset_InputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetConnectionManagementType_CreateAsset_OutputArguments = new ExpandedNodeId(Asset.Variables.WoTAssetConnectionManagementType_CreateAsset_OutputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetConnectionManagementType_DeleteAsset_InputArguments = new ExpandedNodeId(Asset.Variables.WoTAssetConnectionManagementType_DeleteAsset_InputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetConnectionManagement_CreateAsset_InputArguments = new ExpandedNodeId(Asset.Variables.WoTAssetConnectionManagement_CreateAsset_InputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetConnectionManagement_CreateAsset_OutputArguments = new ExpandedNodeId(Asset.Variables.WoTAssetConnectionManagement_CreateAsset_OutputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetConnectionManagement_DeleteAsset_InputArguments = new ExpandedNodeId(Asset.Variables.WoTAssetConnectionManagement_DeleteAsset_InputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId IWoTAssetType_WoTFile_Size = new ExpandedNodeId(Asset.Variables.IWoTAssetType_WoTFile_Size, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId IWoTAssetType_WoTFile_Writable = new ExpandedNodeId(Asset.Variables.IWoTAssetType_WoTFile_Writable, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId IWoTAssetType_WoTFile_UserWritable = new ExpandedNodeId(Asset.Variables.IWoTAssetType_WoTFile_UserWritable, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId IWoTAssetType_WoTFile_OpenCount = new ExpandedNodeId(Asset.Variables.IWoTAssetType_WoTFile_OpenCount, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId IWoTAssetType_WoTFile_Open_InputArguments = new ExpandedNodeId(Asset.Variables.IWoTAssetType_WoTFile_Open_InputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId IWoTAssetType_WoTFile_Open_OutputArguments = new ExpandedNodeId(Asset.Variables.IWoTAssetType_WoTFile_Open_OutputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId IWoTAssetType_WoTFile_Close_InputArguments = new ExpandedNodeId(Asset.Variables.IWoTAssetType_WoTFile_Close_InputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId IWoTAssetType_WoTFile_Read_InputArguments = new ExpandedNodeId(Asset.Variables.IWoTAssetType_WoTFile_Read_InputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId IWoTAssetType_WoTFile_Read_OutputArguments = new ExpandedNodeId(Asset.Variables.IWoTAssetType_WoTFile_Read_OutputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId IWoTAssetType_WoTFile_Write_InputArguments = new ExpandedNodeId(Asset.Variables.IWoTAssetType_WoTFile_Write_InputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId IWoTAssetType_WoTFile_GetPosition_InputArguments = new ExpandedNodeId(Asset.Variables.IWoTAssetType_WoTFile_GetPosition_InputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId IWoTAssetType_WoTFile_GetPosition_OutputArguments = new ExpandedNodeId(Asset.Variables.IWoTAssetType_WoTFile_GetPosition_OutputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId IWoTAssetType_WoTFile_SetPosition_InputArguments = new ExpandedNodeId(Asset.Variables.IWoTAssetType_WoTFile_SetPosition_InputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId IWoTAssetType_WoTFile_CloseAndUpdate_InputArguments = new ExpandedNodeId(Asset.Variables.IWoTAssetType_WoTFile_CloseAndUpdate_InputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId IWoTAssetType_WoTPropertyName_Placeholder = new ExpandedNodeId(Asset.Variables.IWoTAssetType_WoTPropertyName_Placeholder, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetType_WoTFile_Size = new ExpandedNodeId(Asset.Variables.WoTAssetType_WoTFile_Size, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetType_WoTFile_Writable = new ExpandedNodeId(Asset.Variables.WoTAssetType_WoTFile_Writable, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetType_WoTFile_UserWritable = new ExpandedNodeId(Asset.Variables.WoTAssetType_WoTFile_UserWritable, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetType_WoTFile_OpenCount = new ExpandedNodeId(Asset.Variables.WoTAssetType_WoTFile_OpenCount, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetType_WoTFile_Open_InputArguments = new ExpandedNodeId(Asset.Variables.WoTAssetType_WoTFile_Open_InputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetType_WoTFile_Open_OutputArguments = new ExpandedNodeId(Asset.Variables.WoTAssetType_WoTFile_Open_OutputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetType_WoTFile_Close_InputArguments = new ExpandedNodeId(Asset.Variables.WoTAssetType_WoTFile_Close_InputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetType_WoTFile_Read_InputArguments = new ExpandedNodeId(Asset.Variables.WoTAssetType_WoTFile_Read_InputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetType_WoTFile_Read_OutputArguments = new ExpandedNodeId(Asset.Variables.WoTAssetType_WoTFile_Read_OutputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetType_WoTFile_Write_InputArguments = new ExpandedNodeId(Asset.Variables.WoTAssetType_WoTFile_Write_InputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetType_WoTFile_GetPosition_InputArguments = new ExpandedNodeId(Asset.Variables.WoTAssetType_WoTFile_GetPosition_InputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetType_WoTFile_GetPosition_OutputArguments = new ExpandedNodeId(Asset.Variables.WoTAssetType_WoTFile_GetPosition_OutputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetType_WoTFile_SetPosition_InputArguments = new ExpandedNodeId(Asset.Variables.WoTAssetType_WoTFile_SetPosition_InputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetType_WoTFile_CloseAndUpdate_InputArguments = new ExpandedNodeId(Asset.Variables.WoTAssetType_WoTFile_CloseAndUpdate_InputArguments, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetType_WoTPropertyName_Placeholder = new ExpandedNodeId(Asset.Variables.WoTAssetType_WoTPropertyName_Placeholder, Asset.Namespaces.WoT_Con); /// public static readonly ExpandedNodeId WoTAssetFileType_CloseAndUpdate_InputArguments = new ExpandedNodeId(Asset.Variables.WoTAssetFileType_CloseAndUpdate_InputArguments, Asset.Namespaces.WoT_Con); } #endregion #region BrowseName Declarations /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class BrowseNames { /// public const string CloseAndUpdate = "CloseAndUpdate"; /// public const string CloseAndUpdateMethodType = "CloseAndUpdateMethodType"; /// public const string CreateAsset = "CreateAsset"; /// public const string CreateAssetMethodType = "CreateAssetMethodType"; /// public const string DeleteAsset = "DeleteAsset"; /// public const string DeleteAssetMethodType = "DeleteAssetMethodType"; /// public const string HasWoTComponent = "HasWoTComponent"; /// public const string IWoTAssetType = "IWoTAssetType"; /// public const string WoTAssetConnectionManagement = "WoTAssetConnectionManagement"; /// public const string WoTAssetConnectionManagementType = "WoTAssetConnectionManagementType"; /// public const string WoTAssetFileType = "WoTAssetFileType"; /// public const string WoTAssetName_Placeholder = ""; /// public const string WoTAssetType = "WoTAssetType"; /// public const string WoTFile = "WoTFile"; /// public const string WoTPropertyName_Placeholder = ""; } #endregion #region Namespace Declarations /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Namespaces { /// /// The URI for the WoT_Con namespace (.NET code namespace is 'UAModel.WoT_Con'). /// public const string WoT_Con = "http://opcfoundation.org/UA/WoT-Con/"; /// /// The URI for the OpcUa namespace (.NET code namespace is 'Opc.Ua'). /// public const string OpcUa = "http://opcfoundation.org/UA/"; /// /// The URI for the OpcUaXsd namespace (.NET code namespace is 'Opc.Ua'). /// public const string OpcUaXsd = "http://opcfoundation.org/UA/2008/02/Types.xsd"; } #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Asset/Design/Asset.NodeSet2.xml ================================================  http://opcfoundation.org/UA/WoT-Con/ i=1 i=2 i=3 i=4 i=5 i=6 i=7 i=8 i=9 i=10 i=11 i=13 i=12 i=15 i=14 i=16 i=17 i=18 i=20 i=21 i=19 i=22 i=26 i=27 i=28 i=47 i=46 i=35 i=36 i=48 i=45 i=40 i=37 i=38 i=39 i=53 i=52 i=51 i=54 i=9004 i=9005 i=17597 i=9006 i=15112 i=17604 i=17603 http://opcfoundation.org/UA/WoT-Con/ https://reference.opcfoundation.org/WoT/v100/docs/8.1 ns=1;i=68 ns=1;i=69 ns=1;i=70 ns=1;i=71 ns=1;i=72 ns=1;i=73 ns=1;i=74 ns=1;i=99 ns=1;i=100 ns=1;i=101 i=11715 i=11616 NamespaceUri i=68 ns=1;i=67 http://opcfoundation.org/UA/WoT-Con/ NamespaceVersion i=68 ns=1;i=67 1.00.0 NamespacePublicationDate i=68 ns=1;i=67 2024-04-20T00:00:00Z IsNamespaceSubset i=68 ns=1;i=67 false StaticNodeIdTypes i=68 ns=1;i=67 0 StaticNumericNodeIdRange i=68 ns=1;i=67 1:2147483647 StaticStringNodeIdPattern i=68 ns=1;i=67 DefaultRolePermissions i=68 ns=1;i=67 DefaultUserRolePermissions i=68 ns=1;i=67 DefaultAccessRestrictions i=68 ns=1;i=67 WoTAssetConnectionManagementType WoT Connectivity Base Functionality https://reference.opcfoundation.org/WoT/v100/docs/6.3.1/#6.3.1.1 ns=1;i=2 ns=1;i=26 ns=1;i=29 i=58 <WoTAssetName> ns=1;i=42 i=58 i=11508 ns=1;i=1 CreateAsset https://reference.opcfoundation.org/WoT/v100/docs/6.3.1/#6.3.1.2 ns=1;i=27 ns=1;i=28 i=78 ns=1;i=1 InputArguments i=68 i=78 ns=1;i=26 i=297 AssetName i=12 -1 OutputArguments i=68 i=78 ns=1;i=26 i=297 AssetId i=17 -1 DeleteAsset https://reference.opcfoundation.org/WoT/v100/docs/6.3.1/#6.3.1.3 ns=1;i=30 i=78 ns=1;i=1 InputArguments i=68 i=78 ns=1;i=29 i=297 AssetId i=17 -1 WoTAssetConnectionManagement WoT Connectivity Base Functionality https://reference.opcfoundation.org/WoT/v100/docs/6.2 ns=1;i=32 ns=1;i=35 i=2253 ns=1;i=1 CreateAsset ns=1;i=33 ns=1;i=34 ns=1;i=31 InputArguments i=68 ns=1;i=32 i=297 AssetName i=12 -1 OutputArguments i=68 ns=1;i=32 i=297 AssetId i=17 -1 DeleteAsset ns=1;i=36 ns=1;i=31 InputArguments i=68 ns=1;i=35 i=297 AssetId i=17 -1 IWoTAssetType WoT Connectivity Base Functionality https://reference.opcfoundation.org/WoT/v100/docs/6.3.2 ns=1;i=43 ns=1;i=66 i=17602 WoTFile ns=1;i=44 ns=1;i=45 ns=1;i=46 ns=1;i=47 ns=1;i=51 ns=1;i=54 ns=1;i=56 ns=1;i=59 ns=1;i=61 ns=1;i=64 ns=1;i=106 ns=1;i=110 i=78 ns=1;i=42 Size i=68 i=78 ns=1;i=43 Writable i=68 i=78 ns=1;i=43 UserWritable i=68 i=78 ns=1;i=43 OpenCount i=68 i=78 ns=1;i=43 Open ns=1;i=52 ns=1;i=53 i=78 ns=1;i=43 InputArguments i=68 i=78 ns=1;i=51 i=297 Mode i=3 -1 OutputArguments i=68 i=78 ns=1;i=51 i=297 FileHandle i=7 -1 Close ns=1;i=55 i=78 ns=1;i=43 InputArguments i=68 i=78 ns=1;i=54 i=297 FileHandle i=7 -1 Read ns=1;i=57 ns=1;i=58 i=78 ns=1;i=43 InputArguments i=68 i=78 ns=1;i=56 i=297 FileHandle i=7 -1 i=297 Length i=6 -1 OutputArguments i=68 i=78 ns=1;i=56 i=297 Data i=15 -1 Write ns=1;i=60 i=78 ns=1;i=43 InputArguments i=68 i=78 ns=1;i=59 i=297 FileHandle i=7 -1 i=297 Data i=15 -1 GetPosition ns=1;i=62 ns=1;i=63 i=78 ns=1;i=43 InputArguments i=68 i=78 ns=1;i=61 i=297 FileHandle i=7 -1 OutputArguments i=68 i=78 ns=1;i=61 i=297 Position i=9 -1 SetPosition ns=1;i=65 i=78 ns=1;i=43 InputArguments i=68 i=78 ns=1;i=64 i=297 FileHandle i=7 -1 i=297 Position i=9 -1 CloseAndUpdate ns=1;i=107 i=78 ns=1;i=43 InputArguments i=68 i=78 ns=1;i=106 i=297 FileHandle i=7 -1 <WoTPropertyName> i=63 i=11508 ns=1;i=42 WoTAssetType WoT Connectivity Base Functionality https://reference.opcfoundation.org/WoT/v100/docs/6.3.2 ns=1;i=116 ns=1;i=141 ns=1;i=42 i=58 WoTFile ns=1;i=117 ns=1;i=118 ns=1;i=119 ns=1;i=120 ns=1;i=124 ns=1;i=127 ns=1;i=129 ns=1;i=132 ns=1;i=134 ns=1;i=137 ns=1;i=139 ns=1;i=110 i=78 ns=1;i=115 Size i=68 i=78 ns=1;i=116 Writable i=68 i=78 ns=1;i=116 UserWritable i=68 i=78 ns=1;i=116 OpenCount i=68 i=78 ns=1;i=116 Open ns=1;i=125 ns=1;i=126 i=78 ns=1;i=116 InputArguments i=68 i=78 ns=1;i=124 i=297 Mode i=3 -1 OutputArguments i=68 i=78 ns=1;i=124 i=297 FileHandle i=7 -1 Close ns=1;i=128 i=78 ns=1;i=116 InputArguments i=68 i=78 ns=1;i=127 i=297 FileHandle i=7 -1 Read ns=1;i=130 ns=1;i=131 i=78 ns=1;i=116 InputArguments i=68 i=78 ns=1;i=129 i=297 FileHandle i=7 -1 i=297 Length i=6 -1 OutputArguments i=68 i=78 ns=1;i=129 i=297 Data i=15 -1 Write ns=1;i=133 i=78 ns=1;i=116 InputArguments i=68 i=78 ns=1;i=132 i=297 FileHandle i=7 -1 i=297 Data i=15 -1 GetPosition ns=1;i=135 ns=1;i=136 i=78 ns=1;i=116 InputArguments i=68 i=78 ns=1;i=134 i=297 FileHandle i=7 -1 OutputArguments i=68 i=78 ns=1;i=134 i=297 Position i=9 -1 SetPosition ns=1;i=138 i=78 ns=1;i=116 InputArguments i=68 i=78 ns=1;i=137 i=297 FileHandle i=7 -1 i=297 Position i=9 -1 CloseAndUpdate ns=1;i=140 i=78 ns=1;i=116 InputArguments i=68 i=78 ns=1;i=139 i=297 FileHandle i=7 -1 <WoTPropertyName> i=63 i=11508 ns=1;i=115 HasWoTComponent WoT Connectivity Base Functionality https://reference.opcfoundation.org/WoT/v100/docs/6.3.4 i=47 WoTComponentOf WoTAssetFileType WoT Connectivity Base Functionality https://reference.opcfoundation.org/WoT/v100/docs/6.3.3/#6.3.3.1 ns=1;i=111 i=11575 CloseAndUpdate https://reference.opcfoundation.org/WoT/v100/docs/6.3.3/#6.3.3.2 ns=1;i=112 i=78 ns=1;i=110 InputArguments i=68 i=78 ns=1;i=111 i=297 FileHandle i=7 -1 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Boiler/Design/Boiler.Classes.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; using System; using System.Collections.Generic; namespace Boiler { #region GenericControllerState Class #if !OPCUA_EXCLUDE_GenericControllerState /// /// Stores an instance of the GenericControllerType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCode("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class GenericControllerState : BaseObjectState { #region Constructors /// /// Initializes the type with its default attribute values. /// /// public GenericControllerState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return NodeId.Create(ObjectTypes.GenericControllerType, Namespaces.Boiler, namespaceUris); } #if !OPCUA_EXCLUDE_InitializationStrings /// /// Initializes the instance. /// /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// /// /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACMAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvQm9pbGVyL/////8EYIACAQAAAAEAHQAA" + "AEdlbmVyaWNDb250cm9sbGVyVHlwZUluc3RhbmNlAQHSAAEB0gDSAAAA/////wMAAAAVYIkKAgAAAAEA" + "CwAAAE1lYXN1cmVtZW50AQHcAwAuAETcAwAAAAv/////AQH/////AAAAABVgiQoCAAAAAQAIAAAAU2V0" + "UG9pbnQBAd0DAC4ARN0DAAAAC/////8DA/////8AAAAAFWCJCgIAAAABAAoAAABDb250cm9sT3V0AQHe" + "AwAuAETeAwAAAAv/////AQH/////AAAAAA=="; #endregion #endif #endregion #region Public Properties /// public PropertyState Measurement { get { return m_measurement; } set { if (!ReferenceEquals(m_measurement, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_measurement = value; } } /// public PropertyState SetPoint { get { return m_setPoint; } set { if (!ReferenceEquals(m_setPoint, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_setPoint = value; } } /// public PropertyState ControlOut { get { return m_controlOut; } set { if (!ReferenceEquals(m_controlOut, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_controlOut = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_measurement != null) { children.Add(m_measurement); } if (m_setPoint != null) { children.Add(m_setPoint); } if (m_controlOut != null) { children.Add(m_controlOut); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// /// /// /// /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case BrowseNames.Measurement: { if (createOrReplace && Measurement == null) { if (replacement == null) { Measurement = new PropertyState(this); } else { Measurement = (PropertyState)replacement; } } instance = Measurement; break; } case BrowseNames.SetPoint: { if (createOrReplace && SetPoint == null) { if (replacement == null) { SetPoint = new PropertyState(this); } else { SetPoint = (PropertyState)replacement; } } instance = SetPoint; break; } case BrowseNames.ControlOut: { if (createOrReplace && ControlOut == null) { if (replacement == null) { ControlOut = new PropertyState(this); } else { ControlOut = (PropertyState)replacement; } } instance = ControlOut; break; } } return instance ?? base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private PropertyState m_measurement; private PropertyState m_setPoint; private PropertyState m_controlOut; #endregion } #endif #endregion #region GenericSensorState Class #if (!OPCUA_EXCLUDE_GenericSensorState) /// /// Stores an instance of the GenericSensorType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class GenericSensorState : BaseObjectState { #region Constructors /// /// Initializes the type with its default attribute values. /// public GenericSensorState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(Boiler.ObjectTypes.GenericSensorType, Boiler.Namespaces.Boiler, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACMAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvQm9pbGVyL/////8EYIACAQAAAAEAGQAA" + "AEdlbmVyaWNTZW5zb3JUeXBlSW5zdGFuY2UBAd8DAQHfA98DAAD/////AQAAABVgiQoCAAAAAQAGAAAA" + "T3V0cHV0AQHgAwAvAQBACeADAAAAC/////8BAf////8BAAAAFWCJCgIAAAAAAAcAAABFVVJhbmdlAQHj" + "AwAuAETjAwAAAQB0A/////8BAf////8AAAAA"; #endregion #endif #endregion #region Public Properties /// public AnalogItemState Output { get { return m_output; } set { if (!Object.ReferenceEquals(m_output, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_output = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_output != null) { children.Add(m_output); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case Boiler.BrowseNames.Output: { if (createOrReplace) { if (Output == null) { if (replacement == null) { Output = new AnalogItemState(this); } else { Output = (AnalogItemState)replacement; } } } instance = Output; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private AnalogItemState m_output; #endregion } #endif #endregion #region GenericActuatorState Class #if (!OPCUA_EXCLUDE_GenericActuatorState) /// /// Stores an instance of the GenericActuatorType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class GenericActuatorState : BaseObjectState { #region Constructors /// /// Initializes the type with its default attribute values. /// public GenericActuatorState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(Boiler.ObjectTypes.GenericActuatorType, Boiler.Namespaces.Boiler, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACMAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvQm9pbGVyL/////8EYIACAQAAAAEAGwAA" + "AEdlbmVyaWNBY3R1YXRvclR5cGVJbnN0YW5jZQEB5gMBAeYD5gMAAP////8BAAAAFWCJCgIAAAABAAUA" + "AABJbnB1dAEB5wMALwEAQAnnAwAAAAv/////AgL/////AQAAABVgiQoCAAAAAAAHAAAARVVSYW5nZQEB" + "6gMALgBE6gMAAAEAdAP/////AQH/////AAAAAA=="; #endregion #endif #endregion #region Public Properties /// public AnalogItemState Input { get { return m_input; } set { if (!Object.ReferenceEquals(m_input, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_input = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_input != null) { children.Add(m_input); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case Boiler.BrowseNames.Input: { if (createOrReplace) { if (Input == null) { if (replacement == null) { Input = new AnalogItemState(this); } else { Input = (AnalogItemState)replacement; } } } instance = Input; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private AnalogItemState m_input; #endregion } #endif #endregion #region CustomControllerState Class #if (!OPCUA_EXCLUDE_CustomControllerState) /// /// Stores an instance of the CustomControllerType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class CustomControllerState : BaseObjectState { #region Constructors /// /// Initializes the type with its default attribute values. /// public CustomControllerState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(Boiler.ObjectTypes.CustomControllerType, Boiler.Namespaces.Boiler, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACMAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvQm9pbGVyL/////8EYIACAQAAAAEAHAAA" + "AEN1c3RvbUNvbnRyb2xsZXJUeXBlSW5zdGFuY2UBAQECAQEBAgECAAD/////BQAAABVgiQoCAAAAAQAG" + "AAAASW5wdXQxAQHtAwAuAETtAwAAAAv/////AgL/////AAAAABVgiQoCAAAAAQAGAAAASW5wdXQyAQHu" + "AwAuAETuAwAAAAv/////AgL/////AAAAABVgiQoCAAAAAQAGAAAASW5wdXQzAQHvAwAuAETvAwAAAAv/" + "////AgL/////AAAAABVgiQoCAAAAAQAKAAAAQ29udHJvbE91dAEB8AMALgBE8AMAAAAL/////wEB////" + "/wAAAAAVYMkKAgAAAAwAAABEZXNjcmlwdGlvblgBAAsAAABEZXNjcmlwdGlvbgEB8QMALgBE8QMAAAAV" + "/////wEB/////wAAAAA="; #endregion #endif #endregion #region Public Properties /// public PropertyState Input1 { get { return m_input1; } set { if (!Object.ReferenceEquals(m_input1, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_input1 = value; } } /// public PropertyState Input2 { get { return m_input2; } set { if (!Object.ReferenceEquals(m_input2, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_input2 = value; } } /// public PropertyState Input3 { get { return m_input3; } set { if (!Object.ReferenceEquals(m_input3, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_input3 = value; } } /// public PropertyState ControlOut { get { return m_controlOut; } set { if (!Object.ReferenceEquals(m_controlOut, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_controlOut = value; } } /// public PropertyState DescriptionX { get { return m_descriptionX; } set { if (!Object.ReferenceEquals(m_descriptionX, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_descriptionX = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_input1 != null) { children.Add(m_input1); } if (m_input2 != null) { children.Add(m_input2); } if (m_input3 != null) { children.Add(m_input3); } if (m_controlOut != null) { children.Add(m_controlOut); } if (m_descriptionX != null) { children.Add(m_descriptionX); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case Boiler.BrowseNames.Input1: { if (createOrReplace) { if (Input1 == null) { if (replacement == null) { Input1 = new PropertyState(this); } else { Input1 = (PropertyState)replacement; } } } instance = Input1; break; } case Boiler.BrowseNames.Input2: { if (createOrReplace) { if (Input2 == null) { if (replacement == null) { Input2 = new PropertyState(this); } else { Input2 = (PropertyState)replacement; } } } instance = Input2; break; } case Boiler.BrowseNames.Input3: { if (createOrReplace) { if (Input3 == null) { if (replacement == null) { Input3 = new PropertyState(this); } else { Input3 = (PropertyState)replacement; } } } instance = Input3; break; } case Boiler.BrowseNames.ControlOut: { if (createOrReplace) { if (ControlOut == null) { if (replacement == null) { ControlOut = new PropertyState(this); } else { ControlOut = (PropertyState)replacement; } } } instance = ControlOut; break; } case Boiler.BrowseNames.DescriptionX: { if (createOrReplace) { if (DescriptionX == null) { if (replacement == null) { DescriptionX = new PropertyState(this); } else { DescriptionX = (PropertyState)replacement; } } } instance = DescriptionX; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private PropertyState m_input1; private PropertyState m_input2; private PropertyState m_input3; private PropertyState m_controlOut; private PropertyState m_descriptionX; #endregion } #endif #endregion #region ValveState Class #if (!OPCUA_EXCLUDE_ValveState) /// /// Stores an instance of the ValveType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class ValveState : GenericActuatorState { #region Constructors /// /// Initializes the type with its default attribute values. /// public ValveState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(Boiler.ObjectTypes.ValveType, Boiler.Namespaces.Boiler, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACMAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvQm9pbGVyL/////8EYIACAQAAAAEAEQAA" + "AFZhbHZlVHlwZUluc3RhbmNlAQHyAwEB8gPyAwAA/////wEAAAAVYIkKAgAAAAEABQAAAElucHV0AQHz" + "AwAvAQBACfMDAAAAC/////8CAv////8BAAAAFWCJCgIAAAAAAAcAAABFVVJhbmdlAQH2AwAuAET2AwAA" + "AQB0A/////8BAf////8AAAAA"; #endregion #endif #endregion #region Public Properties #endregion #region Overridden Methods #endregion #region Private Fields #endregion } #endif #endregion #region LevelControllerState Class #if (!OPCUA_EXCLUDE_LevelControllerState) /// /// Stores an instance of the LevelControllerType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class LevelControllerState : GenericControllerState { #region Constructors /// /// Initializes the type with its default attribute values. /// public LevelControllerState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(Boiler.ObjectTypes.LevelControllerType, Boiler.Namespaces.Boiler, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACMAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvQm9pbGVyL/////8EYIACAQAAAAEAGwAA" + "AExldmVsQ29udHJvbGxlclR5cGVJbnN0YW5jZQEB+QMBAfkD+QMAAP////8DAAAAFWCJCgIAAAABAAsA" + "AABNZWFzdXJlbWVudAEB+gMALgBE+gMAAAAL/////wEB/////wAAAAAVYIkKAgAAAAEACAAAAFNldFBv" + "aW50AQH7AwAuAET7AwAAAAv/////AwP/////AAAAABVgiQoCAAAAAQAKAAAAQ29udHJvbE91dAEB/AMA" + "LgBE/AMAAAAL/////wEB/////wAAAAA="; #endregion #endif #endregion #region Public Properties #endregion #region Overridden Methods #endregion #region Private Fields #endregion } #endif #endregion #region FlowControllerState Class #if (!OPCUA_EXCLUDE_FlowControllerState) /// /// Stores an instance of the FlowControllerType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class FlowControllerState : GenericControllerState { #region Constructors /// /// Initializes the type with its default attribute values. /// public FlowControllerState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(Boiler.ObjectTypes.FlowControllerType, Boiler.Namespaces.Boiler, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACMAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvQm9pbGVyL/////8EYIACAQAAAAEAGgAA" + "AEZsb3dDb250cm9sbGVyVHlwZUluc3RhbmNlAQH9AwEB/QP9AwAA/////wMAAAAVYIkKAgAAAAEACwAA" + "AE1lYXN1cmVtZW50AQH+AwAuAET+AwAAAAv/////AQH/////AAAAABVgiQoCAAAAAQAIAAAAU2V0UG9p" + "bnQBAf8DAC4ARP8DAAAAC/////8DA/////8AAAAAFWCJCgIAAAABAAoAAABDb250cm9sT3V0AQEABAAu" + "AEQABAAAAAv/////AQH/////AAAAAA=="; #endregion #endif #endregion #region Public Properties #endregion #region Overridden Methods #endregion #region Private Fields #endregion } #endif #endregion #region LevelIndicatorState Class #if (!OPCUA_EXCLUDE_LevelIndicatorState) /// /// Stores an instance of the LevelIndicatorType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class LevelIndicatorState : GenericSensorState { #region Constructors /// /// Initializes the type with its default attribute values. /// public LevelIndicatorState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(Boiler.ObjectTypes.LevelIndicatorType, Boiler.Namespaces.Boiler, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACMAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvQm9pbGVyL/////8EYIACAQAAAAEAGgAA" + "AExldmVsSW5kaWNhdG9yVHlwZUluc3RhbmNlAQEBBAEBAQQBBAAA/////wEAAAAVYIkKAgAAAAEABgAA" + "AE91dHB1dAEBAgQALwEAQAkCBAAAAAv/////AQH/////AQAAABVgiQoCAAAAAAAHAAAARVVSYW5nZQEB" + "BQQALgBEBQQAAAEAdAP/////AQH/////AAAAAA=="; #endregion #endif #endregion #region Public Properties #endregion #region Overridden Methods #endregion #region Private Fields #endregion } #endif #endregion #region FlowTransmitterState Class #if (!OPCUA_EXCLUDE_FlowTransmitterState) /// /// Stores an instance of the FlowTransmitterType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class FlowTransmitterState : GenericSensorState { #region Constructors /// /// Initializes the type with its default attribute values. /// public FlowTransmitterState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(Boiler.ObjectTypes.FlowTransmitterType, Boiler.Namespaces.Boiler, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACMAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvQm9pbGVyL/////8EYIACAQAAAAEAGwAA" + "AEZsb3dUcmFuc21pdHRlclR5cGVJbnN0YW5jZQEBCAQBAQgECAQAAP////8BAAAAFWCJCgIAAAABAAYA" + "AABPdXRwdXQBAQkEAC8BAEAJCQQAAAAL/////wEB/////wEAAAAVYIkKAgAAAAAABwAAAEVVUmFuZ2UB" + "AQwEAC4ARAwEAAABAHQD/////wEB/////wAAAAA="; #endregion #endif #endregion #region Public Properties #endregion #region Overridden Methods #endregion #region Private Fields #endregion } #endif #endregion #region BoilerStateMachineState Class #if !OPCUA_EXCLUDE_BoilerStateMachineState /// /// Stores an instance of the BoilerStateMachineType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCode("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class BoilerStateMachineState : ProgramStateMachineState { #region Constructors /// /// Initializes the type with its default attribute values. /// /// public BoilerStateMachineState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return NodeId.Create(ObjectTypes.BoilerStateMachineType, Namespaces.Boiler, namespaceUris); } #if !OPCUA_EXCLUDE_InitializationStrings /// /// Initializes the instance. /// /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// /// /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACMAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvQm9pbGVyL/////8EYIACAQAAAAEAHgAA" + "AEJvaWxlclN0YXRlTWFjaGluZVR5cGVJbnN0YW5jZQEBDwQBAQ8EDwQAAP////8LAAAAFWCJCgIAAAAA" + "AAwAAABDdXJyZW50U3RhdGUBARAEAC8BAMgKEAQAAAAV/////wEB/////wIAAAAVYIkKAgAAAAAAAgAA" + "AElkAQERBAAuAEQRBAAAABH/////AQH/////AAAAABVgiQoCAAAAAAAGAAAATnVtYmVyAQETBAAuAEQT" + "BAAAAAf/////AQH/////AAAAABVgiQoCAAAAAAAOAAAATGFzdFRyYW5zaXRpb24BARUEAC8BAM8KFQQA" + "AAAV/////wEB/////wMAAAAVYIkKAgAAAAAAAgAAAElkAQEWBAAuAEQWBAAAABH/////AQH/////AAAA" + "ABVgiQoCAAAAAAAGAAAATnVtYmVyAQEYBAAuAEQYBAAAAAf/////AQH/////AAAAABVgiQoCAAAAAAAO" + "AAAAVHJhbnNpdGlvblRpbWUBARkEAC4ARBkEAAABACYB/////wEB/////wAAAAAVYIkKAgAAAAAACQAA" + "AERlbGV0YWJsZQEBGwQALgBEGwQAAAAB/////wEB/////wAAAAAVYIkKAgAAAAAACgAAAEF1dG9EZWxl" + "dGUBARwEAC4ARBwEAAAAAf////8BAf////8AAAAAFWCJCgIAAAAAAAwAAABSZWN5Y2xlQ291bnQBAR0E" + "AC4ARB0EAAAABv////8BAf////8AAAAAJGGCCgQAAAABAAUAAABTdGFydAEBRwQDAAAAAEsAAABDYXVz" + "ZXMgdGhlIFByb2dyYW0gdG8gdHJhbnNpdGlvbiBmcm9tIHRoZSBSZWFkeSBzdGF0ZSB0byB0aGUgUnVu" + "bmluZyBzdGF0ZS4ALwEAeglHBAAAAQEBAAAAADUBAQE3BAAAAAAkYYIKBAAAAAEABwAAAFN1c3BlbmQB" + "AUgEAwAAAABPAAAAQ2F1c2VzIHRoZSBQcm9ncmFtIHRvIHRyYW5zaXRpb24gZnJvbSB0aGUgUnVubmlu" + "ZyBzdGF0ZSB0byB0aGUgU3VzcGVuZGVkIHN0YXRlLgAvAQB7CUgEAAABAQEAAAAANQEBAT0EAAAAACRh" + "ggoEAAAAAQAGAAAAUmVzdW1lAQFJBAMAAAAATwAAAENhdXNlcyB0aGUgUHJvZ3JhbSB0byB0cmFuc2l0" + "aW9uIGZyb20gdGhlIFN1c3BlbmRlZCBzdGF0ZSB0byB0aGUgUnVubmluZyBzdGF0ZS4ALwEAfAlJBAAA" + "AQEBAAAAADUBAQE/BAAAAAAkYYIKBAAAAAEABAAAAEhhbHQBAUoEAwAAAABgAAAAQ2F1c2VzIHRoZSBQ" + "cm9ncmFtIHRvIHRyYW5zaXRpb24gZnJvbSB0aGUgUmVhZHksIFJ1bm5pbmcgb3IgU3VzcGVuZGVkIHN0" + "YXRlIHRvIHRoZSBIYWx0ZWQgc3RhdGUuAC8BAH0JSgQAAAEBAwAAAAA1AQEBOQQANQEBAUEEADUBAQFF" + "BAAAAAAkYYIKBAAAAAEABQAAAFJlc2V0AQFLBAMAAAAASgAAAENhdXNlcyB0aGUgUHJvZ3JhbSB0byB0" + "cmFuc2l0aW9uIGZyb20gdGhlIEhhbHRlZCBzdGF0ZSB0byB0aGUgUmVhZHkgc3RhdGUuAC8BAH4JSwQA" + "AAEBAQAAAAA1AQEBNQQAAAAANWCJCgIAAAABAAoAAABVcGRhdGVSYXRlAQFMBAMAAAAAJgAAAFRoZSBy" + "YXRlIGF0IHdoaWNoIHRoZSBzaW11bGF0aW9uIHJ1bnMuAC4AREwEAAAAB/////8DA/////8AAAAA"; #endregion #endif #endregion #region Public Properties /// public PropertyState UpdateRate { get { return m_updateRate; } set { if (!ReferenceEquals(m_updateRate, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_updateRate = value; } } /// public MethodState Start { get { return m_startMethod; } set { if (!ReferenceEquals(m_startMethod, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_startMethod = value; } } /// public MethodState Suspend { get { return m_suspendMethod; } set { if (!ReferenceEquals(m_suspendMethod, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_suspendMethod = value; } } /// public MethodState Resume { get { return m_resumeMethod; } set { if (!ReferenceEquals(m_resumeMethod, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_resumeMethod = value; } } /// public MethodState Halt { get { return m_haltMethod; } set { if (!ReferenceEquals(m_haltMethod, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_haltMethod = value; } } /// public MethodState Reset { get { return m_resetMethod; } set { if (!ReferenceEquals(m_resetMethod, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_resetMethod = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_updateRate != null) { children.Add(m_updateRate); } if (m_startMethod != null) { children.Add(m_startMethod); } if (m_suspendMethod != null) { children.Add(m_suspendMethod); } if (m_resumeMethod != null) { children.Add(m_resumeMethod); } if (m_haltMethod != null) { children.Add(m_haltMethod); } if (m_resetMethod != null) { children.Add(m_resetMethod); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// /// /// /// /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case BrowseNames.UpdateRate: { if (createOrReplace && UpdateRate == null) { if (replacement == null) { UpdateRate = new PropertyState(this); } else { UpdateRate = (PropertyState)replacement; } } instance = UpdateRate; break; } case BrowseNames.Start: { if (createOrReplace && Start == null) { if (replacement == null) { Start = new MethodState(this); } else { Start = (MethodState)replacement; } } instance = Start; break; } case BrowseNames.Suspend: { if (createOrReplace && Suspend == null) { if (replacement == null) { Suspend = new MethodState(this); } else { Suspend = (MethodState)replacement; } } instance = Suspend; break; } case BrowseNames.Resume: { if (createOrReplace && Resume == null) { if (replacement == null) { Resume = new MethodState(this); } else { Resume = (MethodState)replacement; } } instance = Resume; break; } case BrowseNames.Halt: { if (createOrReplace && Halt == null) { if (replacement == null) { Halt = new MethodState(this); } else { Halt = (MethodState)replacement; } } instance = Halt; break; } case BrowseNames.Reset: { if (createOrReplace && Reset == null) { if (replacement == null) { Reset = new MethodState(this); } else { Reset = (MethodState)replacement; } } instance = Reset; break; } } return instance ?? base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private PropertyState m_updateRate; private MethodState m_startMethod; private MethodState m_suspendMethod; private MethodState m_resumeMethod; private MethodState m_haltMethod; private MethodState m_resetMethod; #endregion } #endif #endregion #region BoilerInputPipeState Class #if (!OPCUA_EXCLUDE_BoilerInputPipeState) /// /// Stores an instance of the BoilerInputPipeType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class BoilerInputPipeState : FolderState { #region Constructors /// /// Initializes the type with its default attribute values. /// public BoilerInputPipeState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(Boiler.ObjectTypes.BoilerInputPipeType, Boiler.Namespaces.Boiler, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACMAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvQm9pbGVyL/////8EYIACAQAAAAEAGwAA" + "AEJvaWxlcklucHV0UGlwZVR5cGVJbnN0YW5jZQEBTQQBAU0ETQQAAAEAAAAAMAABAU4EAgAAAIRgwAoB" + "AAAAEAAAAEZsb3dUcmFuc21pdHRlcjEBAAYAAABGVFgwMDEBAU4EAC8BAQgETgQAAAEBAAAAADABAQFN" + "BAEAAAAVYIkKAgAAAAEABgAAAE91dHB1dAEBTwQALwEAQAlPBAAAAAv/////AQH/////AQAAABVgiQoC" + "AAAAAAAHAAAARVVSYW5nZQEBUgQALgBEUgQAAAEAdAP/////AQH/////AAAAAIRgwAoBAAAABQAAAFZh" + "bHZlAQAJAAAAVmFsdmVYMDAxAQFVBAAvAQHyA1UEAAAB/////wEAAAAVYIkKAgAAAAEABQAAAElucHV0" + "AQFWBAAvAQBACVYEAAAAC/////8CAv////8BAAAAFWCJCgIAAAAAAAcAAABFVVJhbmdlAQFZBAAuAERZ" + "BAAAAQB0A/////8BAf////8AAAAA"; #endregion #endif #endregion #region Public Properties /// public FlowTransmitterState FlowTransmitter1 { get { return m_flowTransmitter1; } set { if (!Object.ReferenceEquals(m_flowTransmitter1, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_flowTransmitter1 = value; } } /// public ValveState Valve { get { return m_valve; } set { if (!Object.ReferenceEquals(m_valve, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_valve = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_flowTransmitter1 != null) { children.Add(m_flowTransmitter1); } if (m_valve != null) { children.Add(m_valve); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case Boiler.BrowseNames.FlowTransmitter1: { if (createOrReplace) { if (FlowTransmitter1 == null) { if (replacement == null) { FlowTransmitter1 = new FlowTransmitterState(this); } else { FlowTransmitter1 = (FlowTransmitterState)replacement; } } } instance = FlowTransmitter1; break; } case Boiler.BrowseNames.Valve: { if (createOrReplace) { if (Valve == null) { if (replacement == null) { Valve = new ValveState(this); } else { Valve = (ValveState)replacement; } } } instance = Valve; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private FlowTransmitterState m_flowTransmitter1; private ValveState m_valve; #endregion } #endif #endregion #region BoilerDrumState Class #if (!OPCUA_EXCLUDE_BoilerDrumState) /// /// Stores an instance of the BoilerDrumType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class BoilerDrumState : FolderState { #region Constructors /// /// Initializes the type with its default attribute values. /// public BoilerDrumState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(Boiler.ObjectTypes.BoilerDrumType, Boiler.Namespaces.Boiler, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACMAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvQm9pbGVyL/////8EYIACAQAAAAEAFgAA" + "AEJvaWxlckRydW1UeXBlSW5zdGFuY2UBAVwEAQFcBFwEAAABAAAAADAAAQFdBAEAAACEYMAKAQAAAA4A" + "AABMZXZlbEluZGljYXRvcgEABgAAAExJWDAwMQEBXQQALwEBAQRdBAAAAQEAAAAAMAEBAVwEAQAAABVg" + "iQoCAAAAAQAGAAAAT3V0cHV0AQFeBAAvAQBACV4EAAAAC/////8BAf////8BAAAAFWCJCgIAAAAAAAcA" + "AABFVVJhbmdlAQFhBAAuAERhBAAAAQB0A/////8BAf////8AAAAA"; #endregion #endif #endregion #region Public Properties /// public LevelIndicatorState LevelIndicator { get { return m_levelIndicator; } set { if (!Object.ReferenceEquals(m_levelIndicator, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_levelIndicator = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_levelIndicator != null) { children.Add(m_levelIndicator); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case Boiler.BrowseNames.LevelIndicator: { if (createOrReplace) { if (LevelIndicator == null) { if (replacement == null) { LevelIndicator = new LevelIndicatorState(this); } else { LevelIndicator = (LevelIndicatorState)replacement; } } } instance = LevelIndicator; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private LevelIndicatorState m_levelIndicator; #endregion } #endif #endregion #region BoilerOutputPipeState Class #if (!OPCUA_EXCLUDE_BoilerOutputPipeState) /// /// Stores an instance of the BoilerOutputPipeType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class BoilerOutputPipeState : FolderState { #region Constructors /// /// Initializes the type with its default attribute values. /// public BoilerOutputPipeState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(Boiler.ObjectTypes.BoilerOutputPipeType, Boiler.Namespaces.Boiler, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACMAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvQm9pbGVyL/////8EYIACAQAAAAEAHAAA" + "AEJvaWxlck91dHB1dFBpcGVUeXBlSW5zdGFuY2UBAWQEAQFkBGQEAAABAAAAADAAAQFlBAEAAACEYMAK" + "AQAAABAAAABGbG93VHJhbnNtaXR0ZXIyAQAGAAAARlRYMDAyAQFlBAAvAQEIBGUEAAABAQAAAAAwAQEB" + "ZAQBAAAAFWCJCgIAAAABAAYAAABPdXRwdXQBAWYEAC8BAEAJZgQAAAAL/////wEB/////wEAAAAVYIkK" + "AgAAAAAABwAAAEVVUmFuZ2UBAWkEAC4ARGkEAAABAHQD/////wEB/////wAAAAA="; #endregion #endif #endregion #region Public Properties /// public FlowTransmitterState FlowTransmitter2 { get { return m_flowTransmitter2; } set { if (!Object.ReferenceEquals(m_flowTransmitter2, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_flowTransmitter2 = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_flowTransmitter2 != null) { children.Add(m_flowTransmitter2); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case Boiler.BrowseNames.FlowTransmitter2: { if (createOrReplace) { if (FlowTransmitter2 == null) { if (replacement == null) { FlowTransmitter2 = new FlowTransmitterState(this); } else { FlowTransmitter2 = (FlowTransmitterState)replacement; } } } instance = FlowTransmitter2; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private FlowTransmitterState m_flowTransmitter2; #endregion } #endif #endregion #region BoilerState Class #if !OPCUA_EXCLUDE_BoilerState /// /// Stores an instance of the BoilerType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCode("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class BoilerState : BaseObjectState { #region Constructors /// /// Initializes the type with its default attribute values. /// /// public BoilerState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return NodeId.Create(ObjectTypes.BoilerType, Namespaces.Boiler, namespaceUris); } #if !OPCUA_EXCLUDE_InitializationStrings /// /// Initializes the instance. /// /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// /// /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACMAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvQm9pbGVyL/////+EYIACAQAAAAEAEgAA" + "AEJvaWxlclR5cGVJbnN0YW5jZQEBbAQBAWwEbAQAAAEEAAAAADAAAQFtBAAwAAEBfAQAMAABAYQEACQA" + "AQGaBAcAAACEYMAKAQAAAAkAAABJbnB1dFBpcGUBAAgAAABQaXBlWDAwMQEBbQQALwEBTQRtBAAAAQMA" + "AAAAMAEBAWwEADAAAQFuBAEB2QMAAQF8BAIAAACEYMAKAQAAABAAAABGbG93VHJhbnNtaXR0ZXIxAQAG" + "AAAARlRYMDAxAQFuBAAvAQEIBG4EAAABAQAAAAAwAQEBbQQBAAAAFWCJCgIAAAABAAYAAABPdXRwdXQB" + "AW8EAC8BAEAJbwQAAAAL/////wEBAgAAAAEB2wMAAQGNBAEB2wMAAQGWBAEAAAAVYIkKAgAAAAAABwAA" + "AEVVUmFuZ2UBAXIEAC4ARHIEAAABAHQD/////wEB/////wAAAACEYMAKAQAAAAUAAABWYWx2ZQEACQAA" + "AFZhbHZlWDAwMQEBdQQALwEB8gN1BAAAAf////8BAAAAFWCJCgIAAAABAAUAAABJbnB1dAEBdgQALwEA" + "QAl2BAAAAAv/////AgIBAAAAAQHbAwEBAY8EAQAAABVgiQoCAAAAAAAHAAAARVVSYW5nZQEBeQQALgBE" + "eQQAAAEAdAP/////AQH/////AAAAAIRgwAoBAAAABAAAAERydW0BAAgAAABEcnVtWDAwMQEBfAQALwEB" + "XAR8BAAAAQQAAAAAMAEBAWwEAQHZAwEBAW0EADAAAQF9BAEB2gMAAQGEBAEAAACEYMAKAQAAAA4AAABM" + "ZXZlbEluZGljYXRvcgEABgAAAExJWDAwMQEBfQQALwEBAQR9BAAAAQEAAAAAMAEBAXwEAQAAABVgiQoC" + "AAAAAQAGAAAAT3V0cHV0AQF+BAAvAQBACX4EAAAAGv////8BAQEAAAABAdsDAAEBkQQBAAAAFWCJCgIA" + "AAAAAAcAAABFVVJhbmdlAQGBBAAuAESBBAAAAQB0A/////8BAf////8AAAAAhGDACgEAAAAKAAAAT3V0" + "cHV0UGlwZQEACAAAAFBpcGVYMDAyAQGEBAAvAQFkBIQEAAABAwAAAAAwAQEBbAQBAdoDAQEBfAQAMAAB" + "AYUEAQAAAIRgwAoBAAAAEAAAAEZsb3dUcmFuc21pdHRlcjIBAAYAAABGVFgwMDIBAYUEAC8BAQgEhQQA" + "AAEBAAAAADABAQGEBAEAAAAVYIkKAgAAAAEABgAAAE91dHB1dAEBhgQALwEAQAmGBAAAAAv/////AQEB" + "AAAAAQHbAwABAZcEAQAAABVgiQoCAAAAAAAHAAAARVVSYW5nZQEBiQQALgBEiQQAAAEAdAP/////AQH/" + "////AAAAAARgwAoBAAAADgAAAEZsb3dDb250cm9sbGVyAQAGAAAARkNYMDAxAQGMBAAvAQH9A4wEAAD/" + "////AwAAABVgiQoCAAAAAQALAAAATWVhc3VyZW1lbnQBAY0EAC4ARI0EAAAAC/////8BAQEAAAABAdsD" + "AQEBbwQAAAAAFWCJCgIAAAABAAgAAABTZXRQb2ludAEBjgQALgBEjgQAAAAL/////wMDAQAAAAEB2wMB" + "AQGYBAAAAAAVYIkKAgAAAAEACgAAAENvbnRyb2xPdXQBAY8EAC4ARI8EAAAAC/////8BAQEAAAABAdsD" + "AAEBdgQAAAAABGDACgEAAAAPAAAATGV2ZWxDb250cm9sbGVyAQAGAAAATENYMDAxAQGQBAAvAQH5A5AE" + "AAD/////AwAAABVgiQoCAAAAAQALAAAATWVhc3VyZW1lbnQBAZEEAC4ARJEEAAAAC/////8BAQEAAAAB" + "AdsDAQEBfgQAAAAAFWCJCgIAAAABAAgAAABTZXRQb2ludAEBkgQALgBEkgQAAAAL/////wMD/////wAA" + "AAAVYIkKAgAAAAEACgAAAENvbnRyb2xPdXQBAZMEAC4ARJMEAAAAC/////8BAQEAAAABAdsDAAEBlQQA" + "AAAABGDACgEAAAAQAAAAQ3VzdG9tQ29udHJvbGxlcgEABgAAAENDWDAwMQEBlAQALwEBAQKUBAAA////" + "/wUAAAAVYIkKAgAAAAEABgAAAElucHV0MQEBlQQALgBElQQAAAAL/////wICAQAAAAEB2wMBAQGTBAAA" + "AAAVYIkKAgAAAAEABgAAAElucHV0MgEBlgQALgBElgQAAAAL/////wICAQAAAAEB2wMBAQFvBAAAAAAV" + "YIkKAgAAAAEABgAAAElucHV0MwEBlwQALgBElwQAAAAL/////wICAQAAAAEB2wMBAQGGBAAAAAAVYIkK" + "AgAAAAEACgAAAENvbnRyb2xPdXQBAZgEAC4ARJgEAAAAC/////8BAQEAAAABAdsDAAEBjgQAAAAAFWDJ" + "CgIAAAAMAAAARGVzY3JpcHRpb25YAQALAAAARGVzY3JpcHRpb24BAZkEAC4ARJkEAAAAFf////8BAf//" + "//8AAAAAhGCACgEAAAABAAoAAABTaW11bGF0aW9uAQGaBAAvAQEPBJoEAAABAQAAAAAkAQEBbAQLAAAA" + "FWCJCgIAAAAAAAwAAABDdXJyZW50U3RhdGUBAZsEAC8BAMgKmwQAAAAV/////wEB/////wIAAAAVYIkK" + "AgAAAAAAAgAAAElkAQGcBAAuAEScBAAAABH/////AQH/////AAAAABVgiQoCAAAAAAAGAAAATnVtYmVy" + "AQGeBAAuAESeBAAAAAf/////AQH/////AAAAABVgiQoCAAAAAAAOAAAATGFzdFRyYW5zaXRpb24BAaAE" + "AC8BAM8KoAQAAAAV/////wEB/////wMAAAAVYIkKAgAAAAAAAgAAAElkAQGhBAAuAEShBAAAABH/////" + "AQH/////AAAAABVgiQoCAAAAAAAGAAAATnVtYmVyAQGjBAAuAESjBAAAAAf/////AQH/////AAAAABVg" + "iQoCAAAAAAAOAAAAVHJhbnNpdGlvblRpbWUBAaQEAC4ARKQEAAABACYB/////wEB/////wAAAAAVYIkK" + "AgAAAAAACQAAAERlbGV0YWJsZQEBpgQALgBEpgQAAAAB/////wEB/////wAAAAAVYIkKAgAAAAAACgAA" + "AEF1dG9EZWxldGUBAacEAC4ARKcEAAAAAf////8BAf////8AAAAAFWCJCgIAAAAAAAwAAABSZWN5Y2xl" + "Q291bnQBAagEAC4ARKgEAAAABv////8BAf////8AAAAANWCJCgIAAAABAAoAAABVcGRhdGVSYXRlAQHX" + "BAMAAAAAJgAAAFRoZSByYXRlIGF0IHdoaWNoIHRoZSBzaW11bGF0aW9uIHJ1bnMuAC4ARNcEAAAAB///" + "//8DA/////8AAAAAJGGCCgQAAAABAAUAAABTdGFydAEBpToDAAAAAEsAAABDYXVzZXMgdGhlIFByb2dy" + "YW0gdG8gdHJhbnNpdGlvbiBmcm9tIHRoZSBSZWFkeSBzdGF0ZSB0byB0aGUgUnVubmluZyBzdGF0ZS4A" + "LwEBRwSlOgAAAQH/////AAAAACRhggoEAAAAAQAHAAAAU3VzcGVuZAEBpjoDAAAAAE8AAABDYXVzZXMg" + "dGhlIFByb2dyYW0gdG8gdHJhbnNpdGlvbiBmcm9tIHRoZSBSdW5uaW5nIHN0YXRlIHRvIHRoZSBTdXNw" + "ZW5kZWQgc3RhdGUuAC8BAUgEpjoAAAEB/////wAAAAAkYYIKBAAAAAEABgAAAFJlc3VtZQEBpzoDAAAA" + "AE8AAABDYXVzZXMgdGhlIFByb2dyYW0gdG8gdHJhbnNpdGlvbiBmcm9tIHRoZSBTdXNwZW5kZWQgc3Rh" + "dGUgdG8gdGhlIFJ1bm5pbmcgc3RhdGUuAC8BAUkEpzoAAAEB/////wAAAAAkYYIKBAAAAAEABAAAAEhh" + "bHQBAag6AwAAAABgAAAAQ2F1c2VzIHRoZSBQcm9ncmFtIHRvIHRyYW5zaXRpb24gZnJvbSB0aGUgUmVh" + "ZHksIFJ1bm5pbmcgb3IgU3VzcGVuZGVkIHN0YXRlIHRvIHRoZSBIYWx0ZWQgc3RhdGUuAC8BAUoEqDoA" + "AAEB/////wAAAAAkYYIKBAAAAAEABQAAAFJlc2V0AQGpOgMAAAAASgAAAENhdXNlcyB0aGUgUHJvZ3Jh" + "bSB0byB0cmFuc2l0aW9uIGZyb20gdGhlIEhhbHRlZCBzdGF0ZSB0byB0aGUgUmVhZHkgc3RhdGUuAC8B" + "AUsEqToAAAEB/////wAAAAA="; #endregion #endif #endregion #region Public Properties /// public BoilerInputPipeState InputPipe { get { return m_inputPipe; } set { if (!ReferenceEquals(m_inputPipe, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_inputPipe = value; } } /// public BoilerDrumState Drum { get { return m_drum; } set { if (!ReferenceEquals(m_drum, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_drum = value; } } /// public BoilerOutputPipeState OutputPipe { get { return m_outputPipe; } set { if (!ReferenceEquals(m_outputPipe, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_outputPipe = value; } } /// public FlowControllerState FlowController { get { return m_flowController; } set { if (!ReferenceEquals(m_flowController, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_flowController = value; } } /// public LevelControllerState LevelController { get { return m_levelController; } set { if (!ReferenceEquals(m_levelController, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_levelController = value; } } /// public CustomControllerState CustomController { get { return m_customController; } set { if (!ReferenceEquals(m_customController, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_customController = value; } } /// public BoilerStateMachineState Simulation { get { return m_simulation; } set { if (!ReferenceEquals(m_simulation, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_simulation = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_inputPipe != null) { children.Add(m_inputPipe); } if (m_drum != null) { children.Add(m_drum); } if (m_outputPipe != null) { children.Add(m_outputPipe); } if (m_flowController != null) { children.Add(m_flowController); } if (m_levelController != null) { children.Add(m_levelController); } if (m_customController != null) { children.Add(m_customController); } if (m_simulation != null) { children.Add(m_simulation); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// /// /// /// /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case BrowseNames.InputPipe: { if (createOrReplace && InputPipe == null) { if (replacement == null) { InputPipe = new BoilerInputPipeState(this); } else { InputPipe = (BoilerInputPipeState)replacement; } } instance = InputPipe; break; } case BrowseNames.Drum: { if (createOrReplace && Drum == null) { if (replacement == null) { Drum = new BoilerDrumState(this); } else { Drum = (BoilerDrumState)replacement; } } instance = Drum; break; } case BrowseNames.OutputPipe: { if (createOrReplace && OutputPipe == null) { if (replacement == null) { OutputPipe = new BoilerOutputPipeState(this); } else { OutputPipe = (BoilerOutputPipeState)replacement; } } instance = OutputPipe; break; } case BrowseNames.FlowController: { if (createOrReplace && FlowController == null) { if (replacement == null) { FlowController = new FlowControllerState(this); } else { FlowController = (FlowControllerState)replacement; } } instance = FlowController; break; } case BrowseNames.LevelController: { if (createOrReplace && LevelController == null) { if (replacement == null) { LevelController = new LevelControllerState(this); } else { LevelController = (LevelControllerState)replacement; } } instance = LevelController; break; } case BrowseNames.CustomController: { if (createOrReplace && CustomController == null) { if (replacement == null) { CustomController = new CustomControllerState(this); } else { CustomController = (CustomControllerState)replacement; } } instance = CustomController; break; } case BrowseNames.Simulation: { if (createOrReplace && Simulation == null) { if (replacement == null) { Simulation = new BoilerStateMachineState(this); } else { Simulation = (BoilerStateMachineState)replacement; } } instance = Simulation; break; } } return instance ?? base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private BoilerInputPipeState m_inputPipe; private BoilerDrumState m_drum; private BoilerOutputPipeState m_outputPipe; private FlowControllerState m_flowController; private LevelControllerState m_levelController; private CustomControllerState m_customController; private BoilerStateMachineState m_simulation; #endregion } #endif #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Boiler/Design/Boiler.Constants.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; namespace Boiler { #region Method Identifiers /// /// A class that declares constants for all Methods in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Methods { /// /// The identifier for the BoilerStateMachineType_Start Method. /// public const uint BoilerStateMachineType_Start = 1095; /// /// The identifier for the BoilerStateMachineType_Suspend Method. /// public const uint BoilerStateMachineType_Suspend = 1096; /// /// The identifier for the BoilerStateMachineType_Resume Method. /// public const uint BoilerStateMachineType_Resume = 1097; /// /// The identifier for the BoilerStateMachineType_Halt Method. /// public const uint BoilerStateMachineType_Halt = 1098; /// /// The identifier for the BoilerStateMachineType_Reset Method. /// public const uint BoilerStateMachineType_Reset = 1099; /// /// The identifier for the BoilerType_Simulation_Start Method. /// public const uint BoilerType_Simulation_Start = 15013; /// /// The identifier for the BoilerType_Simulation_Suspend Method. /// public const uint BoilerType_Simulation_Suspend = 15014; /// /// The identifier for the BoilerType_Simulation_Resume Method. /// public const uint BoilerType_Simulation_Resume = 15015; /// /// The identifier for the BoilerType_Simulation_Halt Method. /// public const uint BoilerType_Simulation_Halt = 15016; /// /// The identifier for the BoilerType_Simulation_Reset Method. /// public const uint BoilerType_Simulation_Reset = 15017; /// /// The identifier for the Boilers_Boiler1_Simulation_Start Method. /// public const uint Boilers_Boiler1_Simulation_Start = 15018; /// /// The identifier for the Boilers_Boiler1_Simulation_Suspend Method. /// public const uint Boilers_Boiler1_Simulation_Suspend = 15019; /// /// The identifier for the Boilers_Boiler1_Simulation_Resume Method. /// public const uint Boilers_Boiler1_Simulation_Resume = 15020; /// /// The identifier for the Boilers_Boiler1_Simulation_Halt Method. /// public const uint Boilers_Boiler1_Simulation_Halt = 15021; /// /// The identifier for the Boilers_Boiler1_Simulation_Reset Method. /// public const uint Boilers_Boiler1_Simulation_Reset = 15022; } #endregion #region Object Identifiers /// /// A class that declares constants for all Objects in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Objects { /// /// The identifier for the BoilerInputPipeType_FlowTransmitter1 Object. /// public const uint BoilerInputPipeType_FlowTransmitter1 = 1102; /// /// The identifier for the BoilerInputPipeType_Valve Object. /// public const uint BoilerInputPipeType_Valve = 1109; /// /// The identifier for the BoilerDrumType_LevelIndicator Object. /// public const uint BoilerDrumType_LevelIndicator = 1117; /// /// The identifier for the BoilerOutputPipeType_FlowTransmitter2 Object. /// public const uint BoilerOutputPipeType_FlowTransmitter2 = 1125; /// /// The identifier for the BoilerType_InputPipe Object. /// public const uint BoilerType_InputPipe = 1133; /// /// The identifier for the BoilerType_InputPipe_FlowTransmitter1 Object. /// public const uint BoilerType_InputPipe_FlowTransmitter1 = 1134; /// /// The identifier for the BoilerType_InputPipe_Valve Object. /// public const uint BoilerType_InputPipe_Valve = 1141; /// /// The identifier for the BoilerType_Drum Object. /// public const uint BoilerType_Drum = 1148; /// /// The identifier for the BoilerType_Drum_LevelIndicator Object. /// public const uint BoilerType_Drum_LevelIndicator = 1149; /// /// The identifier for the BoilerType_OutputPipe Object. /// public const uint BoilerType_OutputPipe = 1156; /// /// The identifier for the BoilerType_OutputPipe_FlowTransmitter2 Object. /// public const uint BoilerType_OutputPipe_FlowTransmitter2 = 1157; /// /// The identifier for the BoilerType_FlowController Object. /// public const uint BoilerType_FlowController = 1164; /// /// The identifier for the BoilerType_LevelController Object. /// public const uint BoilerType_LevelController = 1168; /// /// The identifier for the BoilerType_CustomController Object. /// public const uint BoilerType_CustomController = 1172; /// /// The identifier for the BoilerType_Simulation Object. /// public const uint BoilerType_Simulation = 1178; /// /// The identifier for the Boilers Object. /// public const uint Boilers = 1240; /// /// The identifier for the Boilers_Boiler1 Object. /// public const uint Boilers_Boiler1 = 1241; /// /// The identifier for the Boilers_Boiler1_InputPipe Object. /// public const uint Boilers_Boiler1_InputPipe = 1242; /// /// The identifier for the Boilers_Boiler1_InputPipe_FlowTransmitter1 Object. /// public const uint Boilers_Boiler1_InputPipe_FlowTransmitter1 = 1243; /// /// The identifier for the Boilers_Boiler1_InputPipe_Valve Object. /// public const uint Boilers_Boiler1_InputPipe_Valve = 1250; /// /// The identifier for the Boilers_Boiler1_Drum Object. /// public const uint Boilers_Boiler1_Drum = 1257; /// /// The identifier for the Boilers_Boiler1_Drum_LevelIndicator Object. /// public const uint Boilers_Boiler1_Drum_LevelIndicator = 1258; /// /// The identifier for the Boilers_Boiler1_OutputPipe Object. /// public const uint Boilers_Boiler1_OutputPipe = 1265; /// /// The identifier for the Boilers_Boiler1_OutputPipe_FlowTransmitter2 Object. /// public const uint Boilers_Boiler1_OutputPipe_FlowTransmitter2 = 1266; /// /// The identifier for the Boilers_Boiler1_FlowController Object. /// public const uint Boilers_Boiler1_FlowController = 1273; /// /// The identifier for the Boilers_Boiler1_LevelController Object. /// public const uint Boilers_Boiler1_LevelController = 1277; /// /// The identifier for the Boilers_Boiler1_CustomController Object. /// public const uint Boilers_Boiler1_CustomController = 1281; /// /// The identifier for the Boilers_Boiler1_Simulation Object. /// public const uint Boilers_Boiler1_Simulation = 1287; } #endregion #region ObjectType Identifiers /// /// A class that declares constants for all ObjectTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectTypes { /// /// The identifier for the GenericControllerType ObjectType. /// public const uint GenericControllerType = 210; /// /// The identifier for the GenericSensorType ObjectType. /// public const uint GenericSensorType = 991; /// /// The identifier for the GenericActuatorType ObjectType. /// public const uint GenericActuatorType = 998; /// /// The identifier for the CustomControllerType ObjectType. /// public const uint CustomControllerType = 513; /// /// The identifier for the ValveType ObjectType. /// public const uint ValveType = 1010; /// /// The identifier for the LevelControllerType ObjectType. /// public const uint LevelControllerType = 1017; /// /// The identifier for the FlowControllerType ObjectType. /// public const uint FlowControllerType = 1021; /// /// The identifier for the LevelIndicatorType ObjectType. /// public const uint LevelIndicatorType = 1025; /// /// The identifier for the FlowTransmitterType ObjectType. /// public const uint FlowTransmitterType = 1032; /// /// The identifier for the BoilerStateMachineType ObjectType. /// public const uint BoilerStateMachineType = 1039; /// /// The identifier for the BoilerInputPipeType ObjectType. /// public const uint BoilerInputPipeType = 1101; /// /// The identifier for the BoilerDrumType ObjectType. /// public const uint BoilerDrumType = 1116; /// /// The identifier for the BoilerOutputPipeType ObjectType. /// public const uint BoilerOutputPipeType = 1124; /// /// The identifier for the BoilerType ObjectType. /// public const uint BoilerType = 1132; } #endregion #region ReferenceType Identifiers /// /// A class that declares constants for all ReferenceTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ReferenceTypes { /// /// The identifier for the FlowTo ReferenceType. /// public const uint FlowTo = 985; /// /// The identifier for the HotFlowTo ReferenceType. /// public const uint HotFlowTo = 986; /// /// The identifier for the SignalTo ReferenceType. /// public const uint SignalTo = 987; } #endregion #region Variable Identifiers /// /// A class that declares constants for all Variables in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Variables { /// /// The identifier for the GenericControllerType_Measurement Variable. /// public const uint GenericControllerType_Measurement = 988; /// /// The identifier for the GenericControllerType_SetPoint Variable. /// public const uint GenericControllerType_SetPoint = 989; /// /// The identifier for the GenericControllerType_ControlOut Variable. /// public const uint GenericControllerType_ControlOut = 990; /// /// The identifier for the GenericSensorType_Output Variable. /// public const uint GenericSensorType_Output = 992; /// /// The identifier for the GenericSensorType_Output_EURange Variable. /// public const uint GenericSensorType_Output_EURange = 995; /// /// The identifier for the GenericActuatorType_Input Variable. /// public const uint GenericActuatorType_Input = 999; /// /// The identifier for the GenericActuatorType_Input_EURange Variable. /// public const uint GenericActuatorType_Input_EURange = 1002; /// /// The identifier for the CustomControllerType_Input1 Variable. /// public const uint CustomControllerType_Input1 = 1005; /// /// The identifier for the CustomControllerType_Input2 Variable. /// public const uint CustomControllerType_Input2 = 1006; /// /// The identifier for the CustomControllerType_Input3 Variable. /// public const uint CustomControllerType_Input3 = 1007; /// /// The identifier for the CustomControllerType_ControlOut Variable. /// public const uint CustomControllerType_ControlOut = 1008; /// /// The identifier for the CustomControllerType_DescriptionX Variable. /// public const uint CustomControllerType_DescriptionX = 1009; /// /// The identifier for the ValveType_Input_EURange Variable. /// public const uint ValveType_Input_EURange = 1014; /// /// The identifier for the LevelIndicatorType_Output_EURange Variable. /// public const uint LevelIndicatorType_Output_EURange = 1029; /// /// The identifier for the FlowTransmitterType_Output_EURange Variable. /// public const uint FlowTransmitterType_Output_EURange = 1036; /// /// The identifier for the BoilerStateMachineType_CurrentState_Id Variable. /// public const uint BoilerStateMachineType_CurrentState_Id = 1041; /// /// The identifier for the BoilerStateMachineType_CurrentState_Number Variable. /// public const uint BoilerStateMachineType_CurrentState_Number = 1043; /// /// The identifier for the BoilerStateMachineType_LastTransition_Id Variable. /// public const uint BoilerStateMachineType_LastTransition_Id = 1046; /// /// The identifier for the BoilerStateMachineType_LastTransition_Number Variable. /// public const uint BoilerStateMachineType_LastTransition_Number = 1048; /// /// The identifier for the BoilerStateMachineType_LastTransition_TransitionTime Variable. /// public const uint BoilerStateMachineType_LastTransition_TransitionTime = 1049; /// /// The identifier for the BoilerStateMachineType_ProgramDiagnostic_CreateSessionId Variable. /// public const uint BoilerStateMachineType_ProgramDiagnostic_CreateSessionId = 15024; /// /// The identifier for the BoilerStateMachineType_ProgramDiagnostic_CreateClientName Variable. /// public const uint BoilerStateMachineType_ProgramDiagnostic_CreateClientName = 15025; /// /// The identifier for the BoilerStateMachineType_ProgramDiagnostic_InvocationCreationTime Variable. /// public const uint BoilerStateMachineType_ProgramDiagnostic_InvocationCreationTime = 15026; /// /// The identifier for the BoilerStateMachineType_ProgramDiagnostic_LastTransitionTime Variable. /// public const uint BoilerStateMachineType_ProgramDiagnostic_LastTransitionTime = 15027; /// /// The identifier for the BoilerStateMachineType_ProgramDiagnostic_LastMethodCall Variable. /// public const uint BoilerStateMachineType_ProgramDiagnostic_LastMethodCall = 15028; /// /// The identifier for the BoilerStateMachineType_ProgramDiagnostic_LastMethodSessionId Variable. /// public const uint BoilerStateMachineType_ProgramDiagnostic_LastMethodSessionId = 15029; /// /// The identifier for the BoilerStateMachineType_ProgramDiagnostic_LastMethodInputArguments Variable. /// public const uint BoilerStateMachineType_ProgramDiagnostic_LastMethodInputArguments = 15030; /// /// The identifier for the BoilerStateMachineType_ProgramDiagnostic_LastMethodOutputArguments Variable. /// public const uint BoilerStateMachineType_ProgramDiagnostic_LastMethodOutputArguments = 15031; /// /// The identifier for the BoilerStateMachineType_ProgramDiagnostic_LastMethodInputValues Variable. /// public const uint BoilerStateMachineType_ProgramDiagnostic_LastMethodInputValues = 15032; /// /// The identifier for the BoilerStateMachineType_ProgramDiagnostic_LastMethodOutputValues Variable. /// public const uint BoilerStateMachineType_ProgramDiagnostic_LastMethodOutputValues = 15033; /// /// The identifier for the BoilerStateMachineType_ProgramDiagnostic_LastMethodCallTime Variable. /// public const uint BoilerStateMachineType_ProgramDiagnostic_LastMethodCallTime = 15034; /// /// The identifier for the BoilerStateMachineType_ProgramDiagnostic_LastMethodReturnStatus Variable. /// public const uint BoilerStateMachineType_ProgramDiagnostic_LastMethodReturnStatus = 15035; /// /// The identifier for the BoilerStateMachineType_Halted_StateNumber Variable. /// public const uint BoilerStateMachineType_Halted_StateNumber = 1076; /// /// The identifier for the BoilerStateMachineType_Ready_StateNumber Variable. /// public const uint BoilerStateMachineType_Ready_StateNumber = 1070; /// /// The identifier for the BoilerStateMachineType_Running_StateNumber Variable. /// public const uint BoilerStateMachineType_Running_StateNumber = 1072; /// /// The identifier for the BoilerStateMachineType_Suspended_StateNumber Variable. /// public const uint BoilerStateMachineType_Suspended_StateNumber = 1074; /// /// The identifier for the BoilerStateMachineType_HaltedToReady_TransitionNumber Variable. /// public const uint BoilerStateMachineType_HaltedToReady_TransitionNumber = 1078; /// /// The identifier for the BoilerStateMachineType_ReadyToRunning_TransitionNumber Variable. /// public const uint BoilerStateMachineType_ReadyToRunning_TransitionNumber = 1080; /// /// The identifier for the BoilerStateMachineType_RunningToHalted_TransitionNumber Variable. /// public const uint BoilerStateMachineType_RunningToHalted_TransitionNumber = 1082; /// /// The identifier for the BoilerStateMachineType_RunningToReady_TransitionNumber Variable. /// public const uint BoilerStateMachineType_RunningToReady_TransitionNumber = 1084; /// /// The identifier for the BoilerStateMachineType_RunningToSuspended_TransitionNumber Variable. /// public const uint BoilerStateMachineType_RunningToSuspended_TransitionNumber = 1086; /// /// The identifier for the BoilerStateMachineType_SuspendedToRunning_TransitionNumber Variable. /// public const uint BoilerStateMachineType_SuspendedToRunning_TransitionNumber = 1088; /// /// The identifier for the BoilerStateMachineType_SuspendedToHalted_TransitionNumber Variable. /// public const uint BoilerStateMachineType_SuspendedToHalted_TransitionNumber = 1090; /// /// The identifier for the BoilerStateMachineType_SuspendedToReady_TransitionNumber Variable. /// public const uint BoilerStateMachineType_SuspendedToReady_TransitionNumber = 1092; /// /// The identifier for the BoilerStateMachineType_ReadyToHalted_TransitionNumber Variable. /// public const uint BoilerStateMachineType_ReadyToHalted_TransitionNumber = 1094; /// /// The identifier for the BoilerStateMachineType_UpdateRate Variable. /// public const uint BoilerStateMachineType_UpdateRate = 1100; /// /// The identifier for the BoilerInputPipeType_FlowTransmitter1_Output Variable. /// public const uint BoilerInputPipeType_FlowTransmitter1_Output = 1103; /// /// The identifier for the BoilerInputPipeType_FlowTransmitter1_Output_EURange Variable. /// public const uint BoilerInputPipeType_FlowTransmitter1_Output_EURange = 1106; /// /// The identifier for the BoilerInputPipeType_Valve_Input Variable. /// public const uint BoilerInputPipeType_Valve_Input = 1110; /// /// The identifier for the BoilerInputPipeType_Valve_Input_EURange Variable. /// public const uint BoilerInputPipeType_Valve_Input_EURange = 1113; /// /// The identifier for the BoilerDrumType_LevelIndicator_Output Variable. /// public const uint BoilerDrumType_LevelIndicator_Output = 1118; /// /// The identifier for the BoilerDrumType_LevelIndicator_Output_EURange Variable. /// public const uint BoilerDrumType_LevelIndicator_Output_EURange = 1121; /// /// The identifier for the BoilerOutputPipeType_FlowTransmitter2_Output Variable. /// public const uint BoilerOutputPipeType_FlowTransmitter2_Output = 1126; /// /// The identifier for the BoilerOutputPipeType_FlowTransmitter2_Output_EURange Variable. /// public const uint BoilerOutputPipeType_FlowTransmitter2_Output_EURange = 1129; /// /// The identifier for the BoilerType_InputPipe_FlowTransmitter1_Output Variable. /// public const uint BoilerType_InputPipe_FlowTransmitter1_Output = 1135; /// /// The identifier for the BoilerType_InputPipe_FlowTransmitter1_Output_EURange Variable. /// public const uint BoilerType_InputPipe_FlowTransmitter1_Output_EURange = 1138; /// /// The identifier for the BoilerType_InputPipe_Valve_Input Variable. /// public const uint BoilerType_InputPipe_Valve_Input = 1142; /// /// The identifier for the BoilerType_InputPipe_Valve_Input_EURange Variable. /// public const uint BoilerType_InputPipe_Valve_Input_EURange = 1145; /// /// The identifier for the BoilerType_Drum_LevelIndicator_Output Variable. /// public const uint BoilerType_Drum_LevelIndicator_Output = 1150; /// /// The identifier for the BoilerType_Drum_LevelIndicator_Output_EURange Variable. /// public const uint BoilerType_Drum_LevelIndicator_Output_EURange = 1153; /// /// The identifier for the BoilerType_OutputPipe_FlowTransmitter2_Output Variable. /// public const uint BoilerType_OutputPipe_FlowTransmitter2_Output = 1158; /// /// The identifier for the BoilerType_OutputPipe_FlowTransmitter2_Output_EURange Variable. /// public const uint BoilerType_OutputPipe_FlowTransmitter2_Output_EURange = 1161; /// /// The identifier for the BoilerType_FlowController_Measurement Variable. /// public const uint BoilerType_FlowController_Measurement = 1165; /// /// The identifier for the BoilerType_FlowController_SetPoint Variable. /// public const uint BoilerType_FlowController_SetPoint = 1166; /// /// The identifier for the BoilerType_FlowController_ControlOut Variable. /// public const uint BoilerType_FlowController_ControlOut = 1167; /// /// The identifier for the BoilerType_LevelController_Measurement Variable. /// public const uint BoilerType_LevelController_Measurement = 1169; /// /// The identifier for the BoilerType_LevelController_SetPoint Variable. /// public const uint BoilerType_LevelController_SetPoint = 1170; /// /// The identifier for the BoilerType_LevelController_ControlOut Variable. /// public const uint BoilerType_LevelController_ControlOut = 1171; /// /// The identifier for the BoilerType_CustomController_Input1 Variable. /// public const uint BoilerType_CustomController_Input1 = 1173; /// /// The identifier for the BoilerType_CustomController_Input2 Variable. /// public const uint BoilerType_CustomController_Input2 = 1174; /// /// The identifier for the BoilerType_CustomController_Input3 Variable. /// public const uint BoilerType_CustomController_Input3 = 1175; /// /// The identifier for the BoilerType_CustomController_ControlOut Variable. /// public const uint BoilerType_CustomController_ControlOut = 1176; /// /// The identifier for the BoilerType_CustomController_DescriptionX Variable. /// public const uint BoilerType_CustomController_DescriptionX = 1177; /// /// The identifier for the BoilerType_Simulation_CurrentState Variable. /// public const uint BoilerType_Simulation_CurrentState = 1179; /// /// The identifier for the BoilerType_Simulation_CurrentState_Id Variable. /// public const uint BoilerType_Simulation_CurrentState_Id = 1180; /// /// The identifier for the BoilerType_Simulation_CurrentState_Number Variable. /// public const uint BoilerType_Simulation_CurrentState_Number = 1182; /// /// The identifier for the BoilerType_Simulation_LastTransition Variable. /// public const uint BoilerType_Simulation_LastTransition = 1184; /// /// The identifier for the BoilerType_Simulation_LastTransition_Id Variable. /// public const uint BoilerType_Simulation_LastTransition_Id = 1185; /// /// The identifier for the BoilerType_Simulation_LastTransition_Number Variable. /// public const uint BoilerType_Simulation_LastTransition_Number = 1187; /// /// The identifier for the BoilerType_Simulation_LastTransition_TransitionTime Variable. /// public const uint BoilerType_Simulation_LastTransition_TransitionTime = 1188; /// /// The identifier for the BoilerType_Simulation_Deletable Variable. /// public const uint BoilerType_Simulation_Deletable = 1190; /// /// The identifier for the BoilerType_Simulation_AutoDelete Variable. /// public const uint BoilerType_Simulation_AutoDelete = 1191; /// /// The identifier for the BoilerType_Simulation_RecycleCount Variable. /// public const uint BoilerType_Simulation_RecycleCount = 1192; /// /// The identifier for the BoilerType_Simulation_ProgramDiagnostic_CreateSessionId Variable. /// public const uint BoilerType_Simulation_ProgramDiagnostic_CreateSessionId = 15037; /// /// The identifier for the BoilerType_Simulation_ProgramDiagnostic_CreateClientName Variable. /// public const uint BoilerType_Simulation_ProgramDiagnostic_CreateClientName = 15038; /// /// The identifier for the BoilerType_Simulation_ProgramDiagnostic_InvocationCreationTime Variable. /// public const uint BoilerType_Simulation_ProgramDiagnostic_InvocationCreationTime = 15039; /// /// The identifier for the BoilerType_Simulation_ProgramDiagnostic_LastTransitionTime Variable. /// public const uint BoilerType_Simulation_ProgramDiagnostic_LastTransitionTime = 15040; /// /// The identifier for the BoilerType_Simulation_ProgramDiagnostic_LastMethodCall Variable. /// public const uint BoilerType_Simulation_ProgramDiagnostic_LastMethodCall = 15041; /// /// The identifier for the BoilerType_Simulation_ProgramDiagnostic_LastMethodSessionId Variable. /// public const uint BoilerType_Simulation_ProgramDiagnostic_LastMethodSessionId = 15042; /// /// The identifier for the BoilerType_Simulation_ProgramDiagnostic_LastMethodInputArguments Variable. /// public const uint BoilerType_Simulation_ProgramDiagnostic_LastMethodInputArguments = 15043; /// /// The identifier for the BoilerType_Simulation_ProgramDiagnostic_LastMethodOutputArguments Variable. /// public const uint BoilerType_Simulation_ProgramDiagnostic_LastMethodOutputArguments = 15044; /// /// The identifier for the BoilerType_Simulation_ProgramDiagnostic_LastMethodInputValues Variable. /// public const uint BoilerType_Simulation_ProgramDiagnostic_LastMethodInputValues = 15045; /// /// The identifier for the BoilerType_Simulation_ProgramDiagnostic_LastMethodOutputValues Variable. /// public const uint BoilerType_Simulation_ProgramDiagnostic_LastMethodOutputValues = 15046; /// /// The identifier for the BoilerType_Simulation_ProgramDiagnostic_LastMethodCallTime Variable. /// public const uint BoilerType_Simulation_ProgramDiagnostic_LastMethodCallTime = 15047; /// /// The identifier for the BoilerType_Simulation_ProgramDiagnostic_LastMethodReturnStatus Variable. /// public const uint BoilerType_Simulation_ProgramDiagnostic_LastMethodReturnStatus = 15048; /// /// The identifier for the BoilerType_Simulation_UpdateRate Variable. /// public const uint BoilerType_Simulation_UpdateRate = 1239; /// /// The identifier for the Boilers_Boiler1_InputPipe_FlowTransmitter1_Output Variable. /// public const uint Boilers_Boiler1_InputPipe_FlowTransmitter1_Output = 1244; /// /// The identifier for the Boilers_Boiler1_InputPipe_FlowTransmitter1_Output_EURange Variable. /// public const uint Boilers_Boiler1_InputPipe_FlowTransmitter1_Output_EURange = 1247; /// /// The identifier for the Boilers_Boiler1_InputPipe_Valve_Input Variable. /// public const uint Boilers_Boiler1_InputPipe_Valve_Input = 1251; /// /// The identifier for the Boilers_Boiler1_InputPipe_Valve_Input_EURange Variable. /// public const uint Boilers_Boiler1_InputPipe_Valve_Input_EURange = 1254; /// /// The identifier for the Boilers_Boiler1_Drum_LevelIndicator_Output Variable. /// public const uint Boilers_Boiler1_Drum_LevelIndicator_Output = 1259; /// /// The identifier for the Boilers_Boiler1_Drum_LevelIndicator_Output_EURange Variable. /// public const uint Boilers_Boiler1_Drum_LevelIndicator_Output_EURange = 1262; /// /// The identifier for the Boilers_Boiler1_OutputPipe_FlowTransmitter2_Output Variable. /// public const uint Boilers_Boiler1_OutputPipe_FlowTransmitter2_Output = 1267; /// /// The identifier for the Boilers_Boiler1_OutputPipe_FlowTransmitter2_Output_EURange Variable. /// public const uint Boilers_Boiler1_OutputPipe_FlowTransmitter2_Output_EURange = 1270; /// /// The identifier for the Boilers_Boiler1_FlowController_Measurement Variable. /// public const uint Boilers_Boiler1_FlowController_Measurement = 1274; /// /// The identifier for the Boilers_Boiler1_FlowController_SetPoint Variable. /// public const uint Boilers_Boiler1_FlowController_SetPoint = 1275; /// /// The identifier for the Boilers_Boiler1_FlowController_ControlOut Variable. /// public const uint Boilers_Boiler1_FlowController_ControlOut = 1276; /// /// The identifier for the Boilers_Boiler1_LevelController_Measurement Variable. /// public const uint Boilers_Boiler1_LevelController_Measurement = 1278; /// /// The identifier for the Boilers_Boiler1_LevelController_SetPoint Variable. /// public const uint Boilers_Boiler1_LevelController_SetPoint = 1279; /// /// The identifier for the Boilers_Boiler1_LevelController_ControlOut Variable. /// public const uint Boilers_Boiler1_LevelController_ControlOut = 1280; /// /// The identifier for the Boilers_Boiler1_CustomController_Input1 Variable. /// public const uint Boilers_Boiler1_CustomController_Input1 = 1282; /// /// The identifier for the Boilers_Boiler1_CustomController_Input2 Variable. /// public const uint Boilers_Boiler1_CustomController_Input2 = 1283; /// /// The identifier for the Boilers_Boiler1_CustomController_Input3 Variable. /// public const uint Boilers_Boiler1_CustomController_Input3 = 1284; /// /// The identifier for the Boilers_Boiler1_CustomController_ControlOut Variable. /// public const uint Boilers_Boiler1_CustomController_ControlOut = 1285; /// /// The identifier for the Boilers_Boiler1_CustomController_DescriptionX Variable. /// public const uint Boilers_Boiler1_CustomController_DescriptionX = 1286; /// /// The identifier for the Boilers_Boiler1_Simulation_CurrentState Variable. /// public const uint Boilers_Boiler1_Simulation_CurrentState = 1288; /// /// The identifier for the Boilers_Boiler1_Simulation_CurrentState_Id Variable. /// public const uint Boilers_Boiler1_Simulation_CurrentState_Id = 1289; /// /// The identifier for the Boilers_Boiler1_Simulation_CurrentState_Number Variable. /// public const uint Boilers_Boiler1_Simulation_CurrentState_Number = 1291; /// /// The identifier for the Boilers_Boiler1_Simulation_LastTransition Variable. /// public const uint Boilers_Boiler1_Simulation_LastTransition = 1293; /// /// The identifier for the Boilers_Boiler1_Simulation_LastTransition_Id Variable. /// public const uint Boilers_Boiler1_Simulation_LastTransition_Id = 1294; /// /// The identifier for the Boilers_Boiler1_Simulation_LastTransition_Number Variable. /// public const uint Boilers_Boiler1_Simulation_LastTransition_Number = 1296; /// /// The identifier for the Boilers_Boiler1_Simulation_LastTransition_TransitionTime Variable. /// public const uint Boilers_Boiler1_Simulation_LastTransition_TransitionTime = 1297; /// /// The identifier for the Boilers_Boiler1_Simulation_Deletable Variable. /// public const uint Boilers_Boiler1_Simulation_Deletable = 1299; /// /// The identifier for the Boilers_Boiler1_Simulation_AutoDelete Variable. /// public const uint Boilers_Boiler1_Simulation_AutoDelete = 1300; /// /// The identifier for the Boilers_Boiler1_Simulation_RecycleCount Variable. /// public const uint Boilers_Boiler1_Simulation_RecycleCount = 1301; /// /// The identifier for the Boilers_Boiler1_Simulation_ProgramDiagnostic_CreateSessionId Variable. /// public const uint Boilers_Boiler1_Simulation_ProgramDiagnostic_CreateSessionId = 15050; /// /// The identifier for the Boilers_Boiler1_Simulation_ProgramDiagnostic_CreateClientName Variable. /// public const uint Boilers_Boiler1_Simulation_ProgramDiagnostic_CreateClientName = 15051; /// /// The identifier for the Boilers_Boiler1_Simulation_ProgramDiagnostic_InvocationCreationTime Variable. /// public const uint Boilers_Boiler1_Simulation_ProgramDiagnostic_InvocationCreationTime = 15052; /// /// The identifier for the Boilers_Boiler1_Simulation_ProgramDiagnostic_LastTransitionTime Variable. /// public const uint Boilers_Boiler1_Simulation_ProgramDiagnostic_LastTransitionTime = 15053; /// /// The identifier for the Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodCall Variable. /// public const uint Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodCall = 15054; /// /// The identifier for the Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodSessionId Variable. /// public const uint Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodSessionId = 15055; /// /// The identifier for the Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodInputArguments Variable. /// public const uint Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodInputArguments = 15056; /// /// The identifier for the Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodOutputArguments Variable. /// public const uint Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodOutputArguments = 15057; /// /// The identifier for the Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodInputValues Variable. /// public const uint Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodInputValues = 15058; /// /// The identifier for the Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodOutputValues Variable. /// public const uint Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodOutputValues = 15059; /// /// The identifier for the Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodCallTime Variable. /// public const uint Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodCallTime = 15060; /// /// The identifier for the Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodReturnStatus Variable. /// public const uint Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodReturnStatus = 15061; /// /// The identifier for the Boilers_Boiler1_Simulation_UpdateRate Variable. /// public const uint Boilers_Boiler1_Simulation_UpdateRate = 1348; } #endregion #region Method Node Identifiers /// /// A class that declares constants for all Methods in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class MethodIds { /// /// The identifier for the BoilerStateMachineType_Start Method. /// public static readonly ExpandedNodeId BoilerStateMachineType_Start = new ExpandedNodeId(Boiler.Methods.BoilerStateMachineType_Start, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_Suspend Method. /// public static readonly ExpandedNodeId BoilerStateMachineType_Suspend = new ExpandedNodeId(Boiler.Methods.BoilerStateMachineType_Suspend, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_Resume Method. /// public static readonly ExpandedNodeId BoilerStateMachineType_Resume = new ExpandedNodeId(Boiler.Methods.BoilerStateMachineType_Resume, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_Halt Method. /// public static readonly ExpandedNodeId BoilerStateMachineType_Halt = new ExpandedNodeId(Boiler.Methods.BoilerStateMachineType_Halt, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_Reset Method. /// public static readonly ExpandedNodeId BoilerStateMachineType_Reset = new ExpandedNodeId(Boiler.Methods.BoilerStateMachineType_Reset, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_Start Method. /// public static readonly ExpandedNodeId BoilerType_Simulation_Start = new ExpandedNodeId(Boiler.Methods.BoilerType_Simulation_Start, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_Suspend Method. /// public static readonly ExpandedNodeId BoilerType_Simulation_Suspend = new ExpandedNodeId(Boiler.Methods.BoilerType_Simulation_Suspend, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_Resume Method. /// public static readonly ExpandedNodeId BoilerType_Simulation_Resume = new ExpandedNodeId(Boiler.Methods.BoilerType_Simulation_Resume, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_Halt Method. /// public static readonly ExpandedNodeId BoilerType_Simulation_Halt = new ExpandedNodeId(Boiler.Methods.BoilerType_Simulation_Halt, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_Reset Method. /// public static readonly ExpandedNodeId BoilerType_Simulation_Reset = new ExpandedNodeId(Boiler.Methods.BoilerType_Simulation_Reset, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_Start Method. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_Start = new ExpandedNodeId(Boiler.Methods.Boilers_Boiler1_Simulation_Start, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_Suspend Method. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_Suspend = new ExpandedNodeId(Boiler.Methods.Boilers_Boiler1_Simulation_Suspend, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_Resume Method. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_Resume = new ExpandedNodeId(Boiler.Methods.Boilers_Boiler1_Simulation_Resume, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_Halt Method. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_Halt = new ExpandedNodeId(Boiler.Methods.Boilers_Boiler1_Simulation_Halt, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_Reset Method. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_Reset = new ExpandedNodeId(Boiler.Methods.Boilers_Boiler1_Simulation_Reset, Boiler.Namespaces.Boiler); } #endregion #region Object Node Identifiers /// /// A class that declares constants for all Objects in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectIds { /// /// The identifier for the BoilerInputPipeType_FlowTransmitter1 Object. /// public static readonly ExpandedNodeId BoilerInputPipeType_FlowTransmitter1 = new ExpandedNodeId(Boiler.Objects.BoilerInputPipeType_FlowTransmitter1, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerInputPipeType_Valve Object. /// public static readonly ExpandedNodeId BoilerInputPipeType_Valve = new ExpandedNodeId(Boiler.Objects.BoilerInputPipeType_Valve, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerDrumType_LevelIndicator Object. /// public static readonly ExpandedNodeId BoilerDrumType_LevelIndicator = new ExpandedNodeId(Boiler.Objects.BoilerDrumType_LevelIndicator, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerOutputPipeType_FlowTransmitter2 Object. /// public static readonly ExpandedNodeId BoilerOutputPipeType_FlowTransmitter2 = new ExpandedNodeId(Boiler.Objects.BoilerOutputPipeType_FlowTransmitter2, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_InputPipe Object. /// public static readonly ExpandedNodeId BoilerType_InputPipe = new ExpandedNodeId(Boiler.Objects.BoilerType_InputPipe, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_InputPipe_FlowTransmitter1 Object. /// public static readonly ExpandedNodeId BoilerType_InputPipe_FlowTransmitter1 = new ExpandedNodeId(Boiler.Objects.BoilerType_InputPipe_FlowTransmitter1, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_InputPipe_Valve Object. /// public static readonly ExpandedNodeId BoilerType_InputPipe_Valve = new ExpandedNodeId(Boiler.Objects.BoilerType_InputPipe_Valve, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Drum Object. /// public static readonly ExpandedNodeId BoilerType_Drum = new ExpandedNodeId(Boiler.Objects.BoilerType_Drum, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Drum_LevelIndicator Object. /// public static readonly ExpandedNodeId BoilerType_Drum_LevelIndicator = new ExpandedNodeId(Boiler.Objects.BoilerType_Drum_LevelIndicator, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_OutputPipe Object. /// public static readonly ExpandedNodeId BoilerType_OutputPipe = new ExpandedNodeId(Boiler.Objects.BoilerType_OutputPipe, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_OutputPipe_FlowTransmitter2 Object. /// public static readonly ExpandedNodeId BoilerType_OutputPipe_FlowTransmitter2 = new ExpandedNodeId(Boiler.Objects.BoilerType_OutputPipe_FlowTransmitter2, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_FlowController Object. /// public static readonly ExpandedNodeId BoilerType_FlowController = new ExpandedNodeId(Boiler.Objects.BoilerType_FlowController, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_LevelController Object. /// public static readonly ExpandedNodeId BoilerType_LevelController = new ExpandedNodeId(Boiler.Objects.BoilerType_LevelController, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_CustomController Object. /// public static readonly ExpandedNodeId BoilerType_CustomController = new ExpandedNodeId(Boiler.Objects.BoilerType_CustomController, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation Object. /// public static readonly ExpandedNodeId BoilerType_Simulation = new ExpandedNodeId(Boiler.Objects.BoilerType_Simulation, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers Object. /// public static readonly ExpandedNodeId Boilers = new ExpandedNodeId(Boiler.Objects.Boilers, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1 Object. /// public static readonly ExpandedNodeId Boilers_Boiler1 = new ExpandedNodeId(Boiler.Objects.Boilers_Boiler1, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_InputPipe Object. /// public static readonly ExpandedNodeId Boilers_Boiler1_InputPipe = new ExpandedNodeId(Boiler.Objects.Boilers_Boiler1_InputPipe, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_InputPipe_FlowTransmitter1 Object. /// public static readonly ExpandedNodeId Boilers_Boiler1_InputPipe_FlowTransmitter1 = new ExpandedNodeId(Boiler.Objects.Boilers_Boiler1_InputPipe_FlowTransmitter1, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_InputPipe_Valve Object. /// public static readonly ExpandedNodeId Boilers_Boiler1_InputPipe_Valve = new ExpandedNodeId(Boiler.Objects.Boilers_Boiler1_InputPipe_Valve, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Drum Object. /// public static readonly ExpandedNodeId Boilers_Boiler1_Drum = new ExpandedNodeId(Boiler.Objects.Boilers_Boiler1_Drum, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Drum_LevelIndicator Object. /// public static readonly ExpandedNodeId Boilers_Boiler1_Drum_LevelIndicator = new ExpandedNodeId(Boiler.Objects.Boilers_Boiler1_Drum_LevelIndicator, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_OutputPipe Object. /// public static readonly ExpandedNodeId Boilers_Boiler1_OutputPipe = new ExpandedNodeId(Boiler.Objects.Boilers_Boiler1_OutputPipe, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_OutputPipe_FlowTransmitter2 Object. /// public static readonly ExpandedNodeId Boilers_Boiler1_OutputPipe_FlowTransmitter2 = new ExpandedNodeId(Boiler.Objects.Boilers_Boiler1_OutputPipe_FlowTransmitter2, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_FlowController Object. /// public static readonly ExpandedNodeId Boilers_Boiler1_FlowController = new ExpandedNodeId(Boiler.Objects.Boilers_Boiler1_FlowController, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_LevelController Object. /// public static readonly ExpandedNodeId Boilers_Boiler1_LevelController = new ExpandedNodeId(Boiler.Objects.Boilers_Boiler1_LevelController, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_CustomController Object. /// public static readonly ExpandedNodeId Boilers_Boiler1_CustomController = new ExpandedNodeId(Boiler.Objects.Boilers_Boiler1_CustomController, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation Object. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation = new ExpandedNodeId(Boiler.Objects.Boilers_Boiler1_Simulation, Boiler.Namespaces.Boiler); } #endregion #region ObjectType Node Identifiers /// /// A class that declares constants for all ObjectTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectTypeIds { /// /// The identifier for the GenericControllerType ObjectType. /// public static readonly ExpandedNodeId GenericControllerType = new ExpandedNodeId(Boiler.ObjectTypes.GenericControllerType, Boiler.Namespaces.Boiler); /// /// The identifier for the GenericSensorType ObjectType. /// public static readonly ExpandedNodeId GenericSensorType = new ExpandedNodeId(Boiler.ObjectTypes.GenericSensorType, Boiler.Namespaces.Boiler); /// /// The identifier for the GenericActuatorType ObjectType. /// public static readonly ExpandedNodeId GenericActuatorType = new ExpandedNodeId(Boiler.ObjectTypes.GenericActuatorType, Boiler.Namespaces.Boiler); /// /// The identifier for the CustomControllerType ObjectType. /// public static readonly ExpandedNodeId CustomControllerType = new ExpandedNodeId(Boiler.ObjectTypes.CustomControllerType, Boiler.Namespaces.Boiler); /// /// The identifier for the ValveType ObjectType. /// public static readonly ExpandedNodeId ValveType = new ExpandedNodeId(Boiler.ObjectTypes.ValveType, Boiler.Namespaces.Boiler); /// /// The identifier for the LevelControllerType ObjectType. /// public static readonly ExpandedNodeId LevelControllerType = new ExpandedNodeId(Boiler.ObjectTypes.LevelControllerType, Boiler.Namespaces.Boiler); /// /// The identifier for the FlowControllerType ObjectType. /// public static readonly ExpandedNodeId FlowControllerType = new ExpandedNodeId(Boiler.ObjectTypes.FlowControllerType, Boiler.Namespaces.Boiler); /// /// The identifier for the LevelIndicatorType ObjectType. /// public static readonly ExpandedNodeId LevelIndicatorType = new ExpandedNodeId(Boiler.ObjectTypes.LevelIndicatorType, Boiler.Namespaces.Boiler); /// /// The identifier for the FlowTransmitterType ObjectType. /// public static readonly ExpandedNodeId FlowTransmitterType = new ExpandedNodeId(Boiler.ObjectTypes.FlowTransmitterType, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType ObjectType. /// public static readonly ExpandedNodeId BoilerStateMachineType = new ExpandedNodeId(Boiler.ObjectTypes.BoilerStateMachineType, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerInputPipeType ObjectType. /// public static readonly ExpandedNodeId BoilerInputPipeType = new ExpandedNodeId(Boiler.ObjectTypes.BoilerInputPipeType, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerDrumType ObjectType. /// public static readonly ExpandedNodeId BoilerDrumType = new ExpandedNodeId(Boiler.ObjectTypes.BoilerDrumType, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerOutputPipeType ObjectType. /// public static readonly ExpandedNodeId BoilerOutputPipeType = new ExpandedNodeId(Boiler.ObjectTypes.BoilerOutputPipeType, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType ObjectType. /// public static readonly ExpandedNodeId BoilerType = new ExpandedNodeId(Boiler.ObjectTypes.BoilerType, Boiler.Namespaces.Boiler); } #endregion #region ReferenceType Node Identifiers /// /// A class that declares constants for all ReferenceTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ReferenceTypeIds { /// /// The identifier for the FlowTo ReferenceType. /// public static readonly ExpandedNodeId FlowTo = new ExpandedNodeId(Boiler.ReferenceTypes.FlowTo, Boiler.Namespaces.Boiler); /// /// The identifier for the HotFlowTo ReferenceType. /// public static readonly ExpandedNodeId HotFlowTo = new ExpandedNodeId(Boiler.ReferenceTypes.HotFlowTo, Boiler.Namespaces.Boiler); /// /// The identifier for the SignalTo ReferenceType. /// public static readonly ExpandedNodeId SignalTo = new ExpandedNodeId(Boiler.ReferenceTypes.SignalTo, Boiler.Namespaces.Boiler); } #endregion #region Variable Node Identifiers /// /// A class that declares constants for all Variables in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class VariableIds { /// /// The identifier for the GenericControllerType_Measurement Variable. /// public static readonly ExpandedNodeId GenericControllerType_Measurement = new ExpandedNodeId(Boiler.Variables.GenericControllerType_Measurement, Boiler.Namespaces.Boiler); /// /// The identifier for the GenericControllerType_SetPoint Variable. /// public static readonly ExpandedNodeId GenericControllerType_SetPoint = new ExpandedNodeId(Boiler.Variables.GenericControllerType_SetPoint, Boiler.Namespaces.Boiler); /// /// The identifier for the GenericControllerType_ControlOut Variable. /// public static readonly ExpandedNodeId GenericControllerType_ControlOut = new ExpandedNodeId(Boiler.Variables.GenericControllerType_ControlOut, Boiler.Namespaces.Boiler); /// /// The identifier for the GenericSensorType_Output Variable. /// public static readonly ExpandedNodeId GenericSensorType_Output = new ExpandedNodeId(Boiler.Variables.GenericSensorType_Output, Boiler.Namespaces.Boiler); /// /// The identifier for the GenericSensorType_Output_EURange Variable. /// public static readonly ExpandedNodeId GenericSensorType_Output_EURange = new ExpandedNodeId(Boiler.Variables.GenericSensorType_Output_EURange, Boiler.Namespaces.Boiler); /// /// The identifier for the GenericActuatorType_Input Variable. /// public static readonly ExpandedNodeId GenericActuatorType_Input = new ExpandedNodeId(Boiler.Variables.GenericActuatorType_Input, Boiler.Namespaces.Boiler); /// /// The identifier for the GenericActuatorType_Input_EURange Variable. /// public static readonly ExpandedNodeId GenericActuatorType_Input_EURange = new ExpandedNodeId(Boiler.Variables.GenericActuatorType_Input_EURange, Boiler.Namespaces.Boiler); /// /// The identifier for the CustomControllerType_Input1 Variable. /// public static readonly ExpandedNodeId CustomControllerType_Input1 = new ExpandedNodeId(Boiler.Variables.CustomControllerType_Input1, Boiler.Namespaces.Boiler); /// /// The identifier for the CustomControllerType_Input2 Variable. /// public static readonly ExpandedNodeId CustomControllerType_Input2 = new ExpandedNodeId(Boiler.Variables.CustomControllerType_Input2, Boiler.Namespaces.Boiler); /// /// The identifier for the CustomControllerType_Input3 Variable. /// public static readonly ExpandedNodeId CustomControllerType_Input3 = new ExpandedNodeId(Boiler.Variables.CustomControllerType_Input3, Boiler.Namespaces.Boiler); /// /// The identifier for the CustomControllerType_ControlOut Variable. /// public static readonly ExpandedNodeId CustomControllerType_ControlOut = new ExpandedNodeId(Boiler.Variables.CustomControllerType_ControlOut, Boiler.Namespaces.Boiler); /// /// The identifier for the CustomControllerType_DescriptionX Variable. /// public static readonly ExpandedNodeId CustomControllerType_DescriptionX = new ExpandedNodeId(Boiler.Variables.CustomControllerType_DescriptionX, Boiler.Namespaces.Boiler); /// /// The identifier for the ValveType_Input_EURange Variable. /// public static readonly ExpandedNodeId ValveType_Input_EURange = new ExpandedNodeId(Boiler.Variables.ValveType_Input_EURange, Boiler.Namespaces.Boiler); /// /// The identifier for the LevelIndicatorType_Output_EURange Variable. /// public static readonly ExpandedNodeId LevelIndicatorType_Output_EURange = new ExpandedNodeId(Boiler.Variables.LevelIndicatorType_Output_EURange, Boiler.Namespaces.Boiler); /// /// The identifier for the FlowTransmitterType_Output_EURange Variable. /// public static readonly ExpandedNodeId FlowTransmitterType_Output_EURange = new ExpandedNodeId(Boiler.Variables.FlowTransmitterType_Output_EURange, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_CurrentState_Id Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_CurrentState_Id = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_CurrentState_Id, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_CurrentState_Number Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_CurrentState_Number = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_CurrentState_Number, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_LastTransition_Id Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_LastTransition_Id = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_LastTransition_Id, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_LastTransition_Number Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_LastTransition_Number = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_LastTransition_Number, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_LastTransition_TransitionTime Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_LastTransition_TransitionTime = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_LastTransition_TransitionTime, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_ProgramDiagnostic_CreateSessionId Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_ProgramDiagnostic_CreateSessionId = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_ProgramDiagnostic_CreateSessionId, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_ProgramDiagnostic_CreateClientName Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_ProgramDiagnostic_CreateClientName = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_ProgramDiagnostic_CreateClientName, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_ProgramDiagnostic_InvocationCreationTime Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_ProgramDiagnostic_InvocationCreationTime = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_ProgramDiagnostic_InvocationCreationTime, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_ProgramDiagnostic_LastTransitionTime Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_ProgramDiagnostic_LastTransitionTime = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_ProgramDiagnostic_LastTransitionTime, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_ProgramDiagnostic_LastMethodCall Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_ProgramDiagnostic_LastMethodCall = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_ProgramDiagnostic_LastMethodCall, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_ProgramDiagnostic_LastMethodSessionId Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_ProgramDiagnostic_LastMethodSessionId = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_ProgramDiagnostic_LastMethodSessionId, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_ProgramDiagnostic_LastMethodInputArguments Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_ProgramDiagnostic_LastMethodInputArguments = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_ProgramDiagnostic_LastMethodInputArguments, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_ProgramDiagnostic_LastMethodOutputArguments Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_ProgramDiagnostic_LastMethodOutputArguments = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_ProgramDiagnostic_LastMethodOutputArguments, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_ProgramDiagnostic_LastMethodInputValues Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_ProgramDiagnostic_LastMethodInputValues = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_ProgramDiagnostic_LastMethodInputValues, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_ProgramDiagnostic_LastMethodOutputValues Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_ProgramDiagnostic_LastMethodOutputValues = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_ProgramDiagnostic_LastMethodOutputValues, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_ProgramDiagnostic_LastMethodCallTime Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_ProgramDiagnostic_LastMethodCallTime = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_ProgramDiagnostic_LastMethodCallTime, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_ProgramDiagnostic_LastMethodReturnStatus Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_ProgramDiagnostic_LastMethodReturnStatus = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_ProgramDiagnostic_LastMethodReturnStatus, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_Halted_StateNumber Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_Halted_StateNumber = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_Halted_StateNumber, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_Ready_StateNumber Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_Ready_StateNumber = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_Ready_StateNumber, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_Running_StateNumber Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_Running_StateNumber = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_Running_StateNumber, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_Suspended_StateNumber Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_Suspended_StateNumber = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_Suspended_StateNumber, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_HaltedToReady_TransitionNumber Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_HaltedToReady_TransitionNumber = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_HaltedToReady_TransitionNumber, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_ReadyToRunning_TransitionNumber Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_ReadyToRunning_TransitionNumber = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_ReadyToRunning_TransitionNumber, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_RunningToHalted_TransitionNumber Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_RunningToHalted_TransitionNumber = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_RunningToHalted_TransitionNumber, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_RunningToReady_TransitionNumber Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_RunningToReady_TransitionNumber = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_RunningToReady_TransitionNumber, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_RunningToSuspended_TransitionNumber Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_RunningToSuspended_TransitionNumber = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_RunningToSuspended_TransitionNumber, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_SuspendedToRunning_TransitionNumber Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_SuspendedToRunning_TransitionNumber = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_SuspendedToRunning_TransitionNumber, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_SuspendedToHalted_TransitionNumber Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_SuspendedToHalted_TransitionNumber = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_SuspendedToHalted_TransitionNumber, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_SuspendedToReady_TransitionNumber Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_SuspendedToReady_TransitionNumber = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_SuspendedToReady_TransitionNumber, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_ReadyToHalted_TransitionNumber Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_ReadyToHalted_TransitionNumber = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_ReadyToHalted_TransitionNumber, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerStateMachineType_UpdateRate Variable. /// public static readonly ExpandedNodeId BoilerStateMachineType_UpdateRate = new ExpandedNodeId(Boiler.Variables.BoilerStateMachineType_UpdateRate, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerInputPipeType_FlowTransmitter1_Output Variable. /// public static readonly ExpandedNodeId BoilerInputPipeType_FlowTransmitter1_Output = new ExpandedNodeId(Boiler.Variables.BoilerInputPipeType_FlowTransmitter1_Output, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerInputPipeType_FlowTransmitter1_Output_EURange Variable. /// public static readonly ExpandedNodeId BoilerInputPipeType_FlowTransmitter1_Output_EURange = new ExpandedNodeId(Boiler.Variables.BoilerInputPipeType_FlowTransmitter1_Output_EURange, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerInputPipeType_Valve_Input Variable. /// public static readonly ExpandedNodeId BoilerInputPipeType_Valve_Input = new ExpandedNodeId(Boiler.Variables.BoilerInputPipeType_Valve_Input, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerInputPipeType_Valve_Input_EURange Variable. /// public static readonly ExpandedNodeId BoilerInputPipeType_Valve_Input_EURange = new ExpandedNodeId(Boiler.Variables.BoilerInputPipeType_Valve_Input_EURange, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerDrumType_LevelIndicator_Output Variable. /// public static readonly ExpandedNodeId BoilerDrumType_LevelIndicator_Output = new ExpandedNodeId(Boiler.Variables.BoilerDrumType_LevelIndicator_Output, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerDrumType_LevelIndicator_Output_EURange Variable. /// public static readonly ExpandedNodeId BoilerDrumType_LevelIndicator_Output_EURange = new ExpandedNodeId(Boiler.Variables.BoilerDrumType_LevelIndicator_Output_EURange, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerOutputPipeType_FlowTransmitter2_Output Variable. /// public static readonly ExpandedNodeId BoilerOutputPipeType_FlowTransmitter2_Output = new ExpandedNodeId(Boiler.Variables.BoilerOutputPipeType_FlowTransmitter2_Output, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerOutputPipeType_FlowTransmitter2_Output_EURange Variable. /// public static readonly ExpandedNodeId BoilerOutputPipeType_FlowTransmitter2_Output_EURange = new ExpandedNodeId(Boiler.Variables.BoilerOutputPipeType_FlowTransmitter2_Output_EURange, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_InputPipe_FlowTransmitter1_Output Variable. /// public static readonly ExpandedNodeId BoilerType_InputPipe_FlowTransmitter1_Output = new ExpandedNodeId(Boiler.Variables.BoilerType_InputPipe_FlowTransmitter1_Output, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_InputPipe_FlowTransmitter1_Output_EURange Variable. /// public static readonly ExpandedNodeId BoilerType_InputPipe_FlowTransmitter1_Output_EURange = new ExpandedNodeId(Boiler.Variables.BoilerType_InputPipe_FlowTransmitter1_Output_EURange, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_InputPipe_Valve_Input Variable. /// public static readonly ExpandedNodeId BoilerType_InputPipe_Valve_Input = new ExpandedNodeId(Boiler.Variables.BoilerType_InputPipe_Valve_Input, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_InputPipe_Valve_Input_EURange Variable. /// public static readonly ExpandedNodeId BoilerType_InputPipe_Valve_Input_EURange = new ExpandedNodeId(Boiler.Variables.BoilerType_InputPipe_Valve_Input_EURange, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Drum_LevelIndicator_Output Variable. /// public static readonly ExpandedNodeId BoilerType_Drum_LevelIndicator_Output = new ExpandedNodeId(Boiler.Variables.BoilerType_Drum_LevelIndicator_Output, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Drum_LevelIndicator_Output_EURange Variable. /// public static readonly ExpandedNodeId BoilerType_Drum_LevelIndicator_Output_EURange = new ExpandedNodeId(Boiler.Variables.BoilerType_Drum_LevelIndicator_Output_EURange, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_OutputPipe_FlowTransmitter2_Output Variable. /// public static readonly ExpandedNodeId BoilerType_OutputPipe_FlowTransmitter2_Output = new ExpandedNodeId(Boiler.Variables.BoilerType_OutputPipe_FlowTransmitter2_Output, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_OutputPipe_FlowTransmitter2_Output_EURange Variable. /// public static readonly ExpandedNodeId BoilerType_OutputPipe_FlowTransmitter2_Output_EURange = new ExpandedNodeId(Boiler.Variables.BoilerType_OutputPipe_FlowTransmitter2_Output_EURange, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_FlowController_Measurement Variable. /// public static readonly ExpandedNodeId BoilerType_FlowController_Measurement = new ExpandedNodeId(Boiler.Variables.BoilerType_FlowController_Measurement, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_FlowController_SetPoint Variable. /// public static readonly ExpandedNodeId BoilerType_FlowController_SetPoint = new ExpandedNodeId(Boiler.Variables.BoilerType_FlowController_SetPoint, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_FlowController_ControlOut Variable. /// public static readonly ExpandedNodeId BoilerType_FlowController_ControlOut = new ExpandedNodeId(Boiler.Variables.BoilerType_FlowController_ControlOut, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_LevelController_Measurement Variable. /// public static readonly ExpandedNodeId BoilerType_LevelController_Measurement = new ExpandedNodeId(Boiler.Variables.BoilerType_LevelController_Measurement, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_LevelController_SetPoint Variable. /// public static readonly ExpandedNodeId BoilerType_LevelController_SetPoint = new ExpandedNodeId(Boiler.Variables.BoilerType_LevelController_SetPoint, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_LevelController_ControlOut Variable. /// public static readonly ExpandedNodeId BoilerType_LevelController_ControlOut = new ExpandedNodeId(Boiler.Variables.BoilerType_LevelController_ControlOut, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_CustomController_Input1 Variable. /// public static readonly ExpandedNodeId BoilerType_CustomController_Input1 = new ExpandedNodeId(Boiler.Variables.BoilerType_CustomController_Input1, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_CustomController_Input2 Variable. /// public static readonly ExpandedNodeId BoilerType_CustomController_Input2 = new ExpandedNodeId(Boiler.Variables.BoilerType_CustomController_Input2, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_CustomController_Input3 Variable. /// public static readonly ExpandedNodeId BoilerType_CustomController_Input3 = new ExpandedNodeId(Boiler.Variables.BoilerType_CustomController_Input3, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_CustomController_ControlOut Variable. /// public static readonly ExpandedNodeId BoilerType_CustomController_ControlOut = new ExpandedNodeId(Boiler.Variables.BoilerType_CustomController_ControlOut, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_CustomController_DescriptionX Variable. /// public static readonly ExpandedNodeId BoilerType_CustomController_DescriptionX = new ExpandedNodeId(Boiler.Variables.BoilerType_CustomController_DescriptionX, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_CurrentState Variable. /// public static readonly ExpandedNodeId BoilerType_Simulation_CurrentState = new ExpandedNodeId(Boiler.Variables.BoilerType_Simulation_CurrentState, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_CurrentState_Id Variable. /// public static readonly ExpandedNodeId BoilerType_Simulation_CurrentState_Id = new ExpandedNodeId(Boiler.Variables.BoilerType_Simulation_CurrentState_Id, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_CurrentState_Number Variable. /// public static readonly ExpandedNodeId BoilerType_Simulation_CurrentState_Number = new ExpandedNodeId(Boiler.Variables.BoilerType_Simulation_CurrentState_Number, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_LastTransition Variable. /// public static readonly ExpandedNodeId BoilerType_Simulation_LastTransition = new ExpandedNodeId(Boiler.Variables.BoilerType_Simulation_LastTransition, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_LastTransition_Id Variable. /// public static readonly ExpandedNodeId BoilerType_Simulation_LastTransition_Id = new ExpandedNodeId(Boiler.Variables.BoilerType_Simulation_LastTransition_Id, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_LastTransition_Number Variable. /// public static readonly ExpandedNodeId BoilerType_Simulation_LastTransition_Number = new ExpandedNodeId(Boiler.Variables.BoilerType_Simulation_LastTransition_Number, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_LastTransition_TransitionTime Variable. /// public static readonly ExpandedNodeId BoilerType_Simulation_LastTransition_TransitionTime = new ExpandedNodeId(Boiler.Variables.BoilerType_Simulation_LastTransition_TransitionTime, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_Deletable Variable. /// public static readonly ExpandedNodeId BoilerType_Simulation_Deletable = new ExpandedNodeId(Boiler.Variables.BoilerType_Simulation_Deletable, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_AutoDelete Variable. /// public static readonly ExpandedNodeId BoilerType_Simulation_AutoDelete = new ExpandedNodeId(Boiler.Variables.BoilerType_Simulation_AutoDelete, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_RecycleCount Variable. /// public static readonly ExpandedNodeId BoilerType_Simulation_RecycleCount = new ExpandedNodeId(Boiler.Variables.BoilerType_Simulation_RecycleCount, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_ProgramDiagnostic_CreateSessionId Variable. /// public static readonly ExpandedNodeId BoilerType_Simulation_ProgramDiagnostic_CreateSessionId = new ExpandedNodeId(Boiler.Variables.BoilerType_Simulation_ProgramDiagnostic_CreateSessionId, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_ProgramDiagnostic_CreateClientName Variable. /// public static readonly ExpandedNodeId BoilerType_Simulation_ProgramDiagnostic_CreateClientName = new ExpandedNodeId(Boiler.Variables.BoilerType_Simulation_ProgramDiagnostic_CreateClientName, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_ProgramDiagnostic_InvocationCreationTime Variable. /// public static readonly ExpandedNodeId BoilerType_Simulation_ProgramDiagnostic_InvocationCreationTime = new ExpandedNodeId(Boiler.Variables.BoilerType_Simulation_ProgramDiagnostic_InvocationCreationTime, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_ProgramDiagnostic_LastTransitionTime Variable. /// public static readonly ExpandedNodeId BoilerType_Simulation_ProgramDiagnostic_LastTransitionTime = new ExpandedNodeId(Boiler.Variables.BoilerType_Simulation_ProgramDiagnostic_LastTransitionTime, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_ProgramDiagnostic_LastMethodCall Variable. /// public static readonly ExpandedNodeId BoilerType_Simulation_ProgramDiagnostic_LastMethodCall = new ExpandedNodeId(Boiler.Variables.BoilerType_Simulation_ProgramDiagnostic_LastMethodCall, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_ProgramDiagnostic_LastMethodSessionId Variable. /// public static readonly ExpandedNodeId BoilerType_Simulation_ProgramDiagnostic_LastMethodSessionId = new ExpandedNodeId(Boiler.Variables.BoilerType_Simulation_ProgramDiagnostic_LastMethodSessionId, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_ProgramDiagnostic_LastMethodInputArguments Variable. /// public static readonly ExpandedNodeId BoilerType_Simulation_ProgramDiagnostic_LastMethodInputArguments = new ExpandedNodeId(Boiler.Variables.BoilerType_Simulation_ProgramDiagnostic_LastMethodInputArguments, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_ProgramDiagnostic_LastMethodOutputArguments Variable. /// public static readonly ExpandedNodeId BoilerType_Simulation_ProgramDiagnostic_LastMethodOutputArguments = new ExpandedNodeId(Boiler.Variables.BoilerType_Simulation_ProgramDiagnostic_LastMethodOutputArguments, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_ProgramDiagnostic_LastMethodInputValues Variable. /// public static readonly ExpandedNodeId BoilerType_Simulation_ProgramDiagnostic_LastMethodInputValues = new ExpandedNodeId(Boiler.Variables.BoilerType_Simulation_ProgramDiagnostic_LastMethodInputValues, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_ProgramDiagnostic_LastMethodOutputValues Variable. /// public static readonly ExpandedNodeId BoilerType_Simulation_ProgramDiagnostic_LastMethodOutputValues = new ExpandedNodeId(Boiler.Variables.BoilerType_Simulation_ProgramDiagnostic_LastMethodOutputValues, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_ProgramDiagnostic_LastMethodCallTime Variable. /// public static readonly ExpandedNodeId BoilerType_Simulation_ProgramDiagnostic_LastMethodCallTime = new ExpandedNodeId(Boiler.Variables.BoilerType_Simulation_ProgramDiagnostic_LastMethodCallTime, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_ProgramDiagnostic_LastMethodReturnStatus Variable. /// public static readonly ExpandedNodeId BoilerType_Simulation_ProgramDiagnostic_LastMethodReturnStatus = new ExpandedNodeId(Boiler.Variables.BoilerType_Simulation_ProgramDiagnostic_LastMethodReturnStatus, Boiler.Namespaces.Boiler); /// /// The identifier for the BoilerType_Simulation_UpdateRate Variable. /// public static readonly ExpandedNodeId BoilerType_Simulation_UpdateRate = new ExpandedNodeId(Boiler.Variables.BoilerType_Simulation_UpdateRate, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_InputPipe_FlowTransmitter1_Output Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_InputPipe_FlowTransmitter1_Output = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_InputPipe_FlowTransmitter1_Output, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_InputPipe_FlowTransmitter1_Output_EURange Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_InputPipe_FlowTransmitter1_Output_EURange = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_InputPipe_FlowTransmitter1_Output_EURange, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_InputPipe_Valve_Input Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_InputPipe_Valve_Input = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_InputPipe_Valve_Input, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_InputPipe_Valve_Input_EURange Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_InputPipe_Valve_Input_EURange = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_InputPipe_Valve_Input_EURange, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Drum_LevelIndicator_Output Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_Drum_LevelIndicator_Output = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_Drum_LevelIndicator_Output, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Drum_LevelIndicator_Output_EURange Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_Drum_LevelIndicator_Output_EURange = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_Drum_LevelIndicator_Output_EURange, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_OutputPipe_FlowTransmitter2_Output Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_OutputPipe_FlowTransmitter2_Output = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_OutputPipe_FlowTransmitter2_Output, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_OutputPipe_FlowTransmitter2_Output_EURange Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_OutputPipe_FlowTransmitter2_Output_EURange = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_OutputPipe_FlowTransmitter2_Output_EURange, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_FlowController_Measurement Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_FlowController_Measurement = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_FlowController_Measurement, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_FlowController_SetPoint Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_FlowController_SetPoint = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_FlowController_SetPoint, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_FlowController_ControlOut Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_FlowController_ControlOut = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_FlowController_ControlOut, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_LevelController_Measurement Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_LevelController_Measurement = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_LevelController_Measurement, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_LevelController_SetPoint Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_LevelController_SetPoint = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_LevelController_SetPoint, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_LevelController_ControlOut Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_LevelController_ControlOut = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_LevelController_ControlOut, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_CustomController_Input1 Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_CustomController_Input1 = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_CustomController_Input1, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_CustomController_Input2 Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_CustomController_Input2 = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_CustomController_Input2, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_CustomController_Input3 Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_CustomController_Input3 = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_CustomController_Input3, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_CustomController_ControlOut Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_CustomController_ControlOut = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_CustomController_ControlOut, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_CustomController_DescriptionX Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_CustomController_DescriptionX = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_CustomController_DescriptionX, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_CurrentState Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_CurrentState = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_Simulation_CurrentState, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_CurrentState_Id Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_CurrentState_Id = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_Simulation_CurrentState_Id, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_CurrentState_Number Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_CurrentState_Number = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_Simulation_CurrentState_Number, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_LastTransition Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_LastTransition = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_Simulation_LastTransition, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_LastTransition_Id Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_LastTransition_Id = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_Simulation_LastTransition_Id, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_LastTransition_Number Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_LastTransition_Number = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_Simulation_LastTransition_Number, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_LastTransition_TransitionTime Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_LastTransition_TransitionTime = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_Simulation_LastTransition_TransitionTime, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_Deletable Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_Deletable = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_Simulation_Deletable, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_AutoDelete Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_AutoDelete = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_Simulation_AutoDelete, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_RecycleCount Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_RecycleCount = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_Simulation_RecycleCount, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_ProgramDiagnostic_CreateSessionId Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_ProgramDiagnostic_CreateSessionId = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_Simulation_ProgramDiagnostic_CreateSessionId, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_ProgramDiagnostic_CreateClientName Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_ProgramDiagnostic_CreateClientName = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_Simulation_ProgramDiagnostic_CreateClientName, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_ProgramDiagnostic_InvocationCreationTime Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_ProgramDiagnostic_InvocationCreationTime = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_Simulation_ProgramDiagnostic_InvocationCreationTime, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_ProgramDiagnostic_LastTransitionTime Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_ProgramDiagnostic_LastTransitionTime = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_Simulation_ProgramDiagnostic_LastTransitionTime, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodCall Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodCall = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodCall, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodSessionId Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodSessionId = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodSessionId, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodInputArguments Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodInputArguments = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodInputArguments, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodOutputArguments Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodOutputArguments = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodOutputArguments, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodInputValues Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodInputValues = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodInputValues, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodOutputValues Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodOutputValues = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodOutputValues, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodCallTime Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodCallTime = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodCallTime, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodReturnStatus Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodReturnStatus = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodReturnStatus, Boiler.Namespaces.Boiler); /// /// The identifier for the Boilers_Boiler1_Simulation_UpdateRate Variable. /// public static readonly ExpandedNodeId Boilers_Boiler1_Simulation_UpdateRate = new ExpandedNodeId(Boiler.Variables.Boilers_Boiler1_Simulation_UpdateRate, Boiler.Namespaces.Boiler); } #endregion #region BrowseName Declarations /// /// Declares all of the BrowseNames used in the Model Design. /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class BrowseNames { /// /// The BrowseName for the Boiler1 component. /// public const string Boiler1 = "Boiler #1"; /// /// The BrowseName for the BoilerDrumType component. /// public const string BoilerDrumType = "BoilerDrumType"; /// /// The BrowseName for the BoilerInputPipeType component. /// public const string BoilerInputPipeType = "BoilerInputPipeType"; /// /// The BrowseName for the BoilerOutputPipeType component. /// public const string BoilerOutputPipeType = "BoilerOutputPipeType"; /// /// The BrowseName for the Boilers component. /// public const string Boilers = "Boilers"; /// /// The BrowseName for the BoilerStateMachineType component. /// public const string BoilerStateMachineType = "BoilerStateMachineType"; /// /// The BrowseName for the BoilerType component. /// public const string BoilerType = "BoilerType"; /// /// The BrowseName for the ControlOut component. /// public const string ControlOut = "ControlOut"; /// /// The BrowseName for the CustomController component. /// public const string CustomController = "CCX001"; /// /// The BrowseName for the CustomControllerType component. /// public const string CustomControllerType = "CustomControllerType"; /// /// The BrowseName for the DescriptionX component. /// public const string DescriptionX = "Description"; /// /// The BrowseName for the Drum component. /// public const string Drum = "DrumX001"; /// /// The BrowseName for the FlowController component. /// public const string FlowController = "FCX001"; /// /// The BrowseName for the FlowControllerType component. /// public const string FlowControllerType = "FlowControllerType"; /// /// The BrowseName for the FlowTo component. /// public const string FlowTo = "FlowTo"; /// /// The BrowseName for the FlowTransmitter1 component. /// public const string FlowTransmitter1 = "FTX001"; /// /// The BrowseName for the FlowTransmitter2 component. /// public const string FlowTransmitter2 = "FTX002"; /// /// The BrowseName for the FlowTransmitterType component. /// public const string FlowTransmitterType = "FlowTransmitterType"; /// /// The BrowseName for the GenericActuatorType component. /// public const string GenericActuatorType = "GenericActuatorType"; /// /// The BrowseName for the GenericControllerType component. /// public const string GenericControllerType = "GenericControllerType"; /// /// The BrowseName for the GenericSensorType component. /// public const string GenericSensorType = "GenericSensorType"; /// /// The BrowseName for the Halt component. /// public const string Halt = "Halt"; /// /// The BrowseName for the HotFlowTo component. /// public const string HotFlowTo = "HotFlowTo"; /// /// The BrowseName for the Input component. /// public const string Input = "Input"; /// /// The BrowseName for the Input1 component. /// public const string Input1 = "Input1"; /// /// The BrowseName for the Input2 component. /// public const string Input2 = "Input2"; /// /// The BrowseName for the Input3 component. /// public const string Input3 = "Input3"; /// /// The BrowseName for the InputPipe component. /// public const string InputPipe = "PipeX001"; /// /// The BrowseName for the LevelController component. /// public const string LevelController = "LCX001"; /// /// The BrowseName for the LevelControllerType component. /// public const string LevelControllerType = "LevelControllerType"; /// /// The BrowseName for the LevelIndicator component. /// public const string LevelIndicator = "LIX001"; /// /// The BrowseName for the LevelIndicatorType component. /// public const string LevelIndicatorType = "LevelIndicatorType"; /// /// The BrowseName for the Measurement component. /// public const string Measurement = "Measurement"; /// /// The BrowseName for the Output component. /// public const string Output = "Output"; /// /// The BrowseName for the OutputPipe component. /// public const string OutputPipe = "PipeX002"; /// /// The BrowseName for the Reset component. /// public const string Reset = "Reset"; /// /// The BrowseName for the Resume component. /// public const string Resume = "Resume"; /// /// The BrowseName for the SetPoint component. /// public const string SetPoint = "SetPoint"; /// /// The BrowseName for the SignalTo component. /// public const string SignalTo = "SignalTo"; /// /// The BrowseName for the Simulation component. /// public const string Simulation = "Simulation"; /// /// The BrowseName for the Start component. /// public const string Start = "Start"; /// /// The BrowseName for the Suspend component. /// public const string Suspend = "Suspend"; /// /// The BrowseName for the UpdateRate component. /// public const string UpdateRate = "UpdateRate"; /// /// The BrowseName for the Valve component. /// public const string Valve = "ValveX001"; /// /// The BrowseName for the ValveType component. /// public const string ValveType = "ValveType"; } #endregion #region Namespace Declarations /// /// Defines constants for all namespaces referenced by the model design. /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Namespaces { /// /// The URI for the OpcUa namespace (.NET code namespace is 'Opc.Ua'). /// public const string OpcUa = "http://opcfoundation.org/UA/"; /// /// The URI for the OpcUaXsd namespace (.NET code namespace is 'Opc.Ua'). /// public const string OpcUaXsd = "http://opcfoundation.org/UA/2008/02/Types.xsd"; /// /// The URI for the Boiler namespace (.NET code namespace is 'Boiler'). /// public const string Boiler = "http://opcfoundation.org/UA/Boiler/"; } #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Boiler/Design/Boiler.NodeIds.csv ================================================ BoilerDrumType,1116,ObjectType BoilerInputPipeType,1101,ObjectType BoilerOutputPipeType,1124,ObjectType Boilers,1240,Object BoilerStateMachineType,1039,ObjectType BoilerType,1132,ObjectType CustomControllerType,513,ObjectType FlowControllerType,1021,ObjectType FlowTo,985,ReferenceType FlowTransmitterType,1032,ObjectType GenericActuatorType,998,ObjectType GenericControllerType,210,ObjectType GenericSensorType,991,ObjectType HotFlowTo,986,ReferenceType LevelControllerType,1017,ObjectType LevelIndicatorType,1025,ObjectType SignalTo,987,ReferenceType ValveType,1010,ObjectType ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Boiler/Design/Boiler.NodeSet.xml ================================================  http://opcfoundation.org/UA/ http://opcfoundation.org/UA/Boiler/ ns=1;i=210 ObjectType_8 1 GenericControllerType GenericControllerType A generic PID controller 0 0 0 i=45 true i=58 i=46 false ns=1;i=988 i=46 false ns=1;i=989 i=46 false ns=1;i=990 i=45 false ns=1;i=1017 i=45 false ns=1;i=1021 false ns=1;i=513 ObjectType_8 1 CustomControllerType CustomControllerType A custom PID controller with 3 inputs 0 0 0 i=45 true i=58 i=46 false ns=1;i=1005 i=46 false ns=1;i=1006 i=46 false ns=1;i=1007 i=46 false ns=1;i=1008 i=46 false ns=1;i=1009 false ns=1;i=985 ReferenceType_32 1 FlowTo FlowTo A reference that indicates a flow between two objects. 0 0 0 i=45 true i=32 i=45 false ns=1;i=986 false false FlowFrom ns=1;i=986 ReferenceType_32 1 HotFlowTo HotFlowTo A reference that indicates a high temperature flow between two objects. 0 0 0 i=45 true ns=1;i=985 false false HotFlowFrom ns=1;i=987 ReferenceType_32 1 SignalTo SignalTo A reference that indicates an electrical signal between two variables. 0 0 0 i=45 true i=32 false false SignalFrom ns=1;i=988 Variable_2 1 Measurement Measurement 0 0 0 i=46 true ns=1;i=210 i=40 false i=68 i=37 false i=78 0 i=11 -1 1 1 0 false 0 ns=1;i=989 Variable_2 1 SetPoint SetPoint 0 0 0 i=46 true ns=1;i=210 i=40 false i=68 i=37 false i=78 0 i=11 -1 3 3 0 false 0 ns=1;i=990 Variable_2 1 ControlOut ControlOut 0 0 0 i=46 true ns=1;i=210 i=40 false i=68 i=37 false i=78 0 i=11 -1 1 1 0 false 0 ns=1;i=991 ObjectType_8 1 GenericSensorType GenericSensorType A generic sensor that read a process value. 0 0 0 i=45 true i=58 i=47 false ns=1;i=992 i=45 false ns=1;i=1025 i=45 false ns=1;i=1032 false ns=1;i=992 Variable_2 1 Output Output 0 0 0 i=47 true ns=1;i=991 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=995 0 i=11 -1 1 1 0 false 0 ns=1;i=995 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=992 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=998 ObjectType_8 1 GenericActuatorType GenericActuatorType Represents a piece of equipment that causes some action to occur. 0 0 0 i=45 true i=58 i=47 false ns=1;i=999 i=45 false ns=1;i=1010 false ns=1;i=999 Variable_2 1 Input Input 0 0 0 i=47 true ns=1;i=998 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=1002 0 i=11 -1 2 2 0 false 0 ns=1;i=1002 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=999 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=1005 Variable_2 1 Input1 Input1 0 0 0 i=46 true ns=1;i=513 i=40 false i=68 i=37 false i=78 0 i=11 -1 2 2 0 false 0 ns=1;i=1006 Variable_2 1 Input2 Input2 0 0 0 i=46 true ns=1;i=513 i=40 false i=68 i=37 false i=78 0 i=11 -1 2 2 0 false 0 ns=1;i=1007 Variable_2 1 Input3 Input3 0 0 0 i=46 true ns=1;i=513 i=40 false i=68 i=37 false i=78 0 i=11 -1 2 2 0 false 0 ns=1;i=1008 Variable_2 1 ControlOut ControlOut 0 0 0 i=46 true ns=1;i=513 i=40 false i=68 i=37 false i=78 0 i=11 -1 1 1 0 false 0 ns=1;i=1009 Variable_2 1 Description Description 0 0 0 i=46 true ns=1;i=513 i=40 false i=68 i=37 false i=78 i=21 -1 1 1 0 false 0 ns=1;i=1010 ObjectType_8 1 ValveType ValveType An actuator that controls the flow through a pipe. 0 0 0 i=45 true ns=1;i=998 false ns=1;i=1017 ObjectType_8 1 LevelControllerType LevelControllerType A controller for the level of a fluid in a drum. 0 0 0 i=45 true ns=1;i=210 false ns=1;i=1021 ObjectType_8 1 FlowControllerType FlowControllerType A controller for the flow of a fluid through a pipe. 0 0 0 i=45 true ns=1;i=210 false ns=1;i=1025 ObjectType_8 1 LevelIndicatorType LevelIndicatorType A sensor that reports the level of a liquid in a tank. 0 0 0 i=45 true ns=1;i=991 false ns=1;i=1032 ObjectType_8 1 FlowTransmitterType FlowTransmitterType A sensor that reports the flow of a liquid through a pipe. 0 0 0 i=45 true ns=1;i=991 false ns=1;i=1039 ObjectType_8 1 BoilerStateMachineType BoilerStateMachineType A program that produces simulated values for a running boiler. 0 0 0 i=45 true i=2391 i=47 false ns=1;i=1095 i=47 false ns=1;i=1096 i=47 false ns=1;i=1097 i=47 false ns=1;i=1098 i=47 false ns=1;i=1099 i=46 false ns=1;i=1100 false ns=1;i=1095 Method_4 1 Start Start Causes the Program to transition from the Ready state to the Running state. 0 0 0 i=47 true ns=1;i=1039 i=40 false i=2426 i=37 false i=78 true true ns=1;i=1096 Method_4 1 Suspend Suspend Causes the Program to transition from the Running state to the Suspended state. 0 0 0 i=47 true ns=1;i=1039 i=40 false i=2427 i=37 false i=78 true true ns=1;i=1097 Method_4 1 Resume Resume Causes the Program to transition from the Suspended state to the Running state. 0 0 0 i=47 true ns=1;i=1039 i=40 false i=2428 i=37 false i=78 true true ns=1;i=1098 Method_4 1 Halt Halt Causes the Program to transition from the Ready, Running or Suspended state to the Halted state. 0 0 0 i=47 true ns=1;i=1039 i=40 false i=2429 i=37 false i=78 true true ns=1;i=1099 Method_4 1 Reset Reset Causes the Program to transition from the Halted state to the Ready state. 0 0 0 i=47 true ns=1;i=1039 i=40 false i=2430 i=37 false i=78 true true ns=1;i=1100 Variable_2 1 UpdateRate UpdateRate The rate at which the simulation runs. 0 0 0 i=46 true ns=1;i=1039 i=40 false i=68 i=37 false i=78 0 i=7 -1 3 3 0 false 0 ns=1;i=1101 ObjectType_8 1 BoilerInputPipeType BoilerInputPipeType 0 0 0 i=45 true i=61 i=48 false ns=1;i=1102 i=47 false ns=1;i=1102 i=47 false ns=1;i=1109 false ns=1;i=1102 Object_1 1 FTX001 FTX001 0 0 0 i=47 true ns=1;i=1101 i=40 false ns=1;i=1032 i=37 false i=78 i=47 false ns=1;i=1103 1 ns=1;i=1103 Variable_2 1 Output Output 0 0 0 i=47 true ns=1;i=1102 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=1106 0 i=11 -1 1 1 0 false 0 ns=1;i=1106 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=1103 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=1109 Object_1 1 ValveX001 ValveX001 0 0 0 i=47 true ns=1;i=1101 i=40 false ns=1;i=1010 i=37 false i=78 i=47 false ns=1;i=1110 1 ns=1;i=1110 Variable_2 1 Input Input 0 0 0 i=47 true ns=1;i=1109 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=1113 0 i=11 -1 2 2 0 false 0 ns=1;i=1113 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=1110 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=1116 ObjectType_8 1 BoilerDrumType BoilerDrumType 0 0 0 i=45 true i=61 i=48 false ns=1;i=1117 i=47 false ns=1;i=1117 false ns=1;i=1117 Object_1 1 LIX001 LIX001 0 0 0 i=47 true ns=1;i=1116 i=40 false ns=1;i=1025 i=37 false i=78 i=47 false ns=1;i=1118 1 ns=1;i=1118 Variable_2 1 Output Output 0 0 0 i=47 true ns=1;i=1117 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=1121 0 i=11 -1 1 1 0 false 0 ns=1;i=1121 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=1118 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=1124 ObjectType_8 1 BoilerOutputPipeType BoilerOutputPipeType 0 0 0 i=45 true i=61 i=48 false ns=1;i=1125 i=47 false ns=1;i=1125 false ns=1;i=1125 Object_1 1 FTX002 FTX002 0 0 0 i=47 true ns=1;i=1124 i=40 false ns=1;i=1032 i=37 false i=78 i=47 false ns=1;i=1126 1 ns=1;i=1126 Variable_2 1 Output Output 0 0 0 i=47 true ns=1;i=1125 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=1129 0 i=11 -1 1 1 0 false 0 ns=1;i=1129 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=1126 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=1132 ObjectType_8 1 BoilerType BoilerType A boiler used to produce steam for a turbine. 0 0 0 i=45 true i=58 i=48 false ns=1;i=1133 i=48 false ns=1;i=1148 i=48 false ns=1;i=1156 i=36 false ns=1;i=1178 i=47 false ns=1;i=1133 i=47 false ns=1;i=1148 i=47 false ns=1;i=1156 i=47 false ns=1;i=1164 i=47 false ns=1;i=1168 i=47 false ns=1;i=1172 i=47 false ns=1;i=1178 false ns=1;i=1133 Object_1 1 PipeX001 PipeX001 0 0 0 i=47 true ns=1;i=1132 i=40 false ns=1;i=1101 i=37 false i=78 i=48 false ns=1;i=1134 ns=1;i=985 false ns=1;i=1148 i=47 false ns=1;i=1134 i=47 false ns=1;i=1141 1 ns=1;i=1134 Object_1 1 FTX001 FTX001 0 0 0 i=47 true ns=1;i=1133 i=40 false ns=1;i=1032 i=37 false i=78 i=48 true ns=1;i=1133 i=47 false ns=1;i=1135 1 ns=1;i=1135 Variable_2 1 Output Output 0 0 0 i=47 true ns=1;i=1134 i=40 false i=2368 i=37 false i=78 ns=1;i=987 false ns=1;i=1165 ns=1;i=987 false ns=1;i=1174 i=46 false ns=1;i=1138 0 i=11 -1 1 1 0 false 0 ns=1;i=1138 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=1135 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=1141 Object_1 1 ValveX001 ValveX001 0 0 0 i=47 true ns=1;i=1133 i=40 false ns=1;i=1010 i=37 false i=78 i=47 false ns=1;i=1142 1 ns=1;i=1142 Variable_2 1 Input Input 0 0 0 i=47 true ns=1;i=1141 i=40 false i=2368 i=37 false i=78 ns=1;i=987 true ns=1;i=1167 i=46 false ns=1;i=1145 0 i=11 -1 2 2 0 false 0 ns=1;i=1145 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=1142 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=1148 Object_1 1 DrumX001 DrumX001 0 0 0 i=47 true ns=1;i=1132 i=40 false ns=1;i=1116 i=37 false i=78 ns=1;i=985 true ns=1;i=1133 i=48 false ns=1;i=1149 ns=1;i=986 false ns=1;i=1156 i=47 false ns=1;i=1149 1 ns=1;i=1149 Object_1 1 LIX001 LIX001 0 0 0 i=47 true ns=1;i=1148 i=40 false ns=1;i=1025 i=37 false i=78 i=48 true ns=1;i=1148 i=47 false ns=1;i=1150 1 ns=1;i=1150 Variable_2 1 Output Output 0 0 0 i=47 true ns=1;i=1149 i=40 false i=2368 i=37 false i=78 ns=1;i=987 false ns=1;i=1169 i=46 false ns=1;i=1153 0 i=26 -1 1 1 0 false 0 ns=1;i=1153 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=1150 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=1156 Object_1 1 PipeX002 PipeX002 0 0 0 i=47 true ns=1;i=1132 i=40 false ns=1;i=1124 i=37 false i=78 ns=1;i=986 true ns=1;i=1148 i=48 false ns=1;i=1157 i=47 false ns=1;i=1157 1 ns=1;i=1157 Object_1 1 FTX002 FTX002 0 0 0 i=47 true ns=1;i=1156 i=40 false ns=1;i=1032 i=37 false i=78 i=48 true ns=1;i=1156 i=47 false ns=1;i=1158 1 ns=1;i=1158 Variable_2 1 Output Output 0 0 0 i=47 true ns=1;i=1157 i=40 false i=2368 i=37 false i=78 ns=1;i=987 false ns=1;i=1175 i=46 false ns=1;i=1161 0 i=11 -1 1 1 0 false 0 ns=1;i=1161 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=1158 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=1164 Object_1 1 FCX001 FCX001 0 0 0 i=47 true ns=1;i=1132 i=40 false ns=1;i=1021 i=37 false i=78 i=46 false ns=1;i=1165 i=46 false ns=1;i=1166 i=46 false ns=1;i=1167 0 ns=1;i=1165 Variable_2 1 Measurement Measurement 0 0 0 i=46 true ns=1;i=1164 i=40 false i=68 i=37 false i=78 ns=1;i=987 true ns=1;i=1135 0 i=11 -1 1 1 0 false 0 ns=1;i=1166 Variable_2 1 SetPoint SetPoint 0 0 0 i=46 true ns=1;i=1164 i=40 false i=68 i=37 false i=78 ns=1;i=987 true ns=1;i=1176 0 i=11 -1 3 3 0 false 0 ns=1;i=1167 Variable_2 1 ControlOut ControlOut 0 0 0 i=46 true ns=1;i=1164 i=40 false i=68 i=37 false i=78 ns=1;i=987 false ns=1;i=1142 0 i=11 -1 1 1 0 false 0 ns=1;i=1168 Object_1 1 LCX001 LCX001 0 0 0 i=47 true ns=1;i=1132 i=40 false ns=1;i=1017 i=37 false i=78 i=46 false ns=1;i=1169 i=46 false ns=1;i=1170 i=46 false ns=1;i=1171 0 ns=1;i=1169 Variable_2 1 Measurement Measurement 0 0 0 i=46 true ns=1;i=1168 i=40 false i=68 i=37 false i=78 ns=1;i=987 true ns=1;i=1150 0 i=11 -1 1 1 0 false 0 ns=1;i=1170 Variable_2 1 SetPoint SetPoint 0 0 0 i=46 true ns=1;i=1168 i=40 false i=68 i=37 false i=78 0 i=11 -1 3 3 0 false 0 ns=1;i=1171 Variable_2 1 ControlOut ControlOut 0 0 0 i=46 true ns=1;i=1168 i=40 false i=68 i=37 false i=78 ns=1;i=987 false ns=1;i=1173 0 i=11 -1 1 1 0 false 0 ns=1;i=1172 Object_1 1 CCX001 CCX001 0 0 0 i=47 true ns=1;i=1132 i=40 false ns=1;i=513 i=37 false i=78 i=46 false ns=1;i=1173 i=46 false ns=1;i=1174 i=46 false ns=1;i=1175 i=46 false ns=1;i=1176 i=46 false ns=1;i=1177 0 ns=1;i=1173 Variable_2 1 Input1 Input1 0 0 0 i=46 true ns=1;i=1172 i=40 false i=68 i=37 false i=78 ns=1;i=987 true ns=1;i=1171 0 i=11 -1 2 2 0 false 0 ns=1;i=1174 Variable_2 1 Input2 Input2 0 0 0 i=46 true ns=1;i=1172 i=40 false i=68 i=37 false i=78 ns=1;i=987 true ns=1;i=1135 0 i=11 -1 2 2 0 false 0 ns=1;i=1175 Variable_2 1 Input3 Input3 0 0 0 i=46 true ns=1;i=1172 i=40 false i=68 i=37 false i=78 ns=1;i=987 true ns=1;i=1158 0 i=11 -1 2 2 0 false 0 ns=1;i=1176 Variable_2 1 ControlOut ControlOut 0 0 0 i=46 true ns=1;i=1172 i=40 false i=68 i=37 false i=78 ns=1;i=987 false ns=1;i=1166 0 i=11 -1 1 1 0 false 0 ns=1;i=1177 Variable_2 1 Description Description 0 0 0 i=46 true ns=1;i=1172 i=40 false i=68 i=37 false i=78 i=21 -1 1 1 0 false 0 ns=1;i=1178 Object_1 1 Simulation Simulation 0 0 0 i=47 true ns=1;i=1132 i=40 false ns=1;i=1039 i=37 false i=78 i=47 false ns=1;i=1179 i=47 false ns=1;i=1184 i=46 false ns=1;i=1190 i=46 false ns=1;i=1191 i=46 false ns=1;i=1192 i=46 false ns=1;i=1239 i=47 false ns=1;i=15013 i=47 false ns=1;i=15014 i=47 false ns=1;i=15015 i=47 false ns=1;i=15016 i=47 false ns=1;i=15017 1 ns=1;i=1179 Variable_2 0 CurrentState CurrentState 0 0 0 i=47 true ns=1;i=1178 i=40 false i=2760 i=37 false i=78 i=46 false ns=1;i=1180 i=46 false ns=1;i=1182 i=21 -1 1 1 0 false 0 ns=1;i=1180 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=1179 i=40 false i=68 i=37 false i=78 i=0 i=17 -1 1 1 0 false 0 ns=1;i=1182 Variable_2 0 Number Number 0 0 0 i=46 true ns=1;i=1179 i=40 false i=68 i=37 false i=78 0 i=7 -1 1 1 0 false 0 ns=1;i=1184 Variable_2 0 LastTransition LastTransition 0 0 0 i=47 true ns=1;i=1178 i=40 false i=2767 i=37 false i=78 i=46 false ns=1;i=1185 i=46 false ns=1;i=1187 i=46 false ns=1;i=1188 i=21 -1 1 1 0 false 0 ns=1;i=1185 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=1184 i=40 false i=68 i=37 false i=78 i=0 i=17 -1 1 1 0 false 0 ns=1;i=1187 Variable_2 0 Number Number 0 0 0 i=46 true ns=1;i=1184 i=40 false i=68 i=37 false i=78 0 i=7 -1 1 1 0 false 0 ns=1;i=1188 Variable_2 0 TransitionTime TransitionTime 0 0 0 i=46 true ns=1;i=1184 i=40 false i=68 i=37 false i=78 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=1190 Variable_2 0 Deletable Deletable 0 0 0 i=46 true ns=1;i=1178 i=40 false i=68 i=37 false i=78 false i=1 -1 1 1 0 false 0 ns=1;i=1191 Variable_2 0 AutoDelete AutoDelete 0 0 0 i=46 true ns=1;i=1178 i=40 false i=68 i=37 false i=78 false i=1 -1 1 1 0 false 0 ns=1;i=1192 Variable_2 0 RecycleCount RecycleCount 0 0 0 i=46 true ns=1;i=1178 i=40 false i=68 i=37 false i=78 0 i=6 -1 1 1 0 false 0 ns=1;i=1239 Variable_2 1 UpdateRate UpdateRate The rate at which the simulation runs. 0 0 0 i=46 true ns=1;i=1178 i=40 false i=68 i=37 false i=78 0 i=7 -1 3 3 0 false 0 ns=1;i=1240 Object_1 1 Boilers Boilers 0 0 0 i=40 false i=61 i=48 false ns=1;i=1241 i=35 true i=85 i=48 true i=2253 i=47 false ns=1;i=1241 1 ns=1;i=1241 Object_1 1 Boiler #1 Boiler #1 0 0 0 i=47 true ns=1;i=1240 i=40 false ns=1;i=1132 i=48 true ns=1;i=1240 i=48 false ns=1;i=1242 i=48 false ns=1;i=1257 i=48 false ns=1;i=1265 i=36 false ns=1;i=1287 i=47 false ns=1;i=1242 i=47 false ns=1;i=1257 i=47 false ns=1;i=1265 i=47 false ns=1;i=1273 i=47 false ns=1;i=1277 i=47 false ns=1;i=1281 i=47 false ns=1;i=1287 0 ns=1;i=1242 Object_1 1 PipeX001 Pipe1001 0 0 0 i=47 true ns=1;i=1241 i=40 false ns=1;i=1101 i=48 true ns=1;i=1241 i=48 false ns=1;i=1243 ns=1;i=985 false ns=1;i=1257 i=47 false ns=1;i=1243 i=47 false ns=1;i=1250 1 ns=1;i=1243 Object_1 1 FTX001 FTX001 0 0 0 i=47 true ns=1;i=1242 i=40 false ns=1;i=1032 i=48 true ns=1;i=1242 i=47 false ns=1;i=1244 1 ns=1;i=1244 Variable_2 1 Output Output 0 0 0 i=47 true ns=1;i=1243 i=40 false i=2368 ns=1;i=987 false ns=1;i=1274 ns=1;i=987 false ns=1;i=1283 i=46 false ns=1;i=1247 0 i=11 -1 1 1 0 false 0 ns=1;i=1247 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=1244 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=1250 Object_1 1 ValveX001 ValveX001 0 0 0 i=47 true ns=1;i=1242 i=40 false ns=1;i=1010 i=47 false ns=1;i=1251 1 ns=1;i=1251 Variable_2 1 Input Input 0 0 0 i=47 true ns=1;i=1250 i=40 false i=2368 ns=1;i=987 true ns=1;i=1276 i=46 false ns=1;i=1254 0 i=11 -1 2 2 0 false 0 ns=1;i=1254 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=1251 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=1257 Object_1 1 DrumX001 Drum1001 0 0 0 i=47 true ns=1;i=1241 i=40 false ns=1;i=1116 i=48 true ns=1;i=1241 ns=1;i=985 true ns=1;i=1242 i=48 false ns=1;i=1258 ns=1;i=986 false ns=1;i=1265 i=47 false ns=1;i=1258 1 ns=1;i=1258 Object_1 1 LIX001 LIX001 0 0 0 i=47 true ns=1;i=1257 i=40 false ns=1;i=1025 i=48 true ns=1;i=1257 i=47 false ns=1;i=1259 1 ns=1;i=1259 Variable_2 1 Output Output 0 0 0 i=47 true ns=1;i=1258 i=40 false i=2368 ns=1;i=987 false ns=1;i=1278 i=46 false ns=1;i=1262 0 i=26 -1 1 1 0 false 0 ns=1;i=1262 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=1259 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=1265 Object_1 1 PipeX002 Pipe1002 0 0 0 i=47 true ns=1;i=1241 i=40 false ns=1;i=1124 i=48 true ns=1;i=1241 ns=1;i=986 true ns=1;i=1257 i=48 false ns=1;i=1266 i=47 false ns=1;i=1266 1 ns=1;i=1266 Object_1 1 FTX002 FTX002 0 0 0 i=47 true ns=1;i=1265 i=40 false ns=1;i=1032 i=48 true ns=1;i=1265 i=47 false ns=1;i=1267 1 ns=1;i=1267 Variable_2 1 Output Output 0 0 0 i=47 true ns=1;i=1266 i=40 false i=2368 ns=1;i=987 false ns=1;i=1284 i=46 false ns=1;i=1270 0 i=11 -1 1 1 0 false 0 ns=1;i=1270 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=1267 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=1273 Object_1 1 FCX001 FC1001 0 0 0 i=47 true ns=1;i=1241 i=40 false ns=1;i=1021 i=46 false ns=1;i=1274 i=46 false ns=1;i=1275 i=46 false ns=1;i=1276 0 ns=1;i=1274 Variable_2 1 Measurement Measurement 0 0 0 i=46 true ns=1;i=1273 i=40 false i=68 ns=1;i=987 true ns=1;i=1244 0 i=11 -1 1 1 0 false 0 ns=1;i=1275 Variable_2 1 SetPoint SetPoint 0 0 0 i=46 true ns=1;i=1273 i=40 false i=68 ns=1;i=987 true ns=1;i=1285 0 i=11 -1 3 3 0 false 0 ns=1;i=1276 Variable_2 1 ControlOut ControlOut 0 0 0 i=46 true ns=1;i=1273 i=40 false i=68 ns=1;i=987 false ns=1;i=1251 0 i=11 -1 1 1 0 false 0 ns=1;i=1277 Object_1 1 LCX001 LC1001 0 0 0 i=47 true ns=1;i=1241 i=40 false ns=1;i=1017 i=46 false ns=1;i=1278 i=46 false ns=1;i=1279 i=46 false ns=1;i=1280 0 ns=1;i=1278 Variable_2 1 Measurement Measurement 0 0 0 i=46 true ns=1;i=1277 i=40 false i=68 ns=1;i=987 true ns=1;i=1259 0 i=11 -1 1 1 0 false 0 ns=1;i=1279 Variable_2 1 SetPoint SetPoint 0 0 0 i=46 true ns=1;i=1277 i=40 false i=68 0 i=11 -1 3 3 0 false 0 ns=1;i=1280 Variable_2 1 ControlOut ControlOut 0 0 0 i=46 true ns=1;i=1277 i=40 false i=68 ns=1;i=987 false ns=1;i=1282 0 i=11 -1 1 1 0 false 0 ns=1;i=1281 Object_1 1 CCX001 CC1001 0 0 0 i=47 true ns=1;i=1241 i=40 false ns=1;i=513 i=46 false ns=1;i=1282 i=46 false ns=1;i=1283 i=46 false ns=1;i=1284 i=46 false ns=1;i=1285 i=46 false ns=1;i=1286 0 ns=1;i=1282 Variable_2 1 Input1 Input1 0 0 0 i=46 true ns=1;i=1281 i=40 false i=68 ns=1;i=987 true ns=1;i=1280 0 i=11 -1 2 2 0 false 0 ns=1;i=1283 Variable_2 1 Input2 Input2 0 0 0 i=46 true ns=1;i=1281 i=40 false i=68 ns=1;i=987 true ns=1;i=1244 0 i=11 -1 2 2 0 false 0 ns=1;i=1284 Variable_2 1 Input3 Input3 0 0 0 i=46 true ns=1;i=1281 i=40 false i=68 ns=1;i=987 true ns=1;i=1267 0 i=11 -1 2 2 0 false 0 ns=1;i=1285 Variable_2 1 ControlOut ControlOut 0 0 0 i=46 true ns=1;i=1281 i=40 false i=68 ns=1;i=987 false ns=1;i=1275 0 i=11 -1 1 1 0 false 0 ns=1;i=1286 Variable_2 1 Description Description 0 0 0 i=46 true ns=1;i=1281 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=1287 Object_1 1 Simulation Simulation 0 0 0 i=47 true ns=1;i=1241 i=40 false ns=1;i=1039 i=36 true ns=1;i=1241 i=47 false ns=1;i=1288 i=47 false ns=1;i=1293 i=46 false ns=1;i=1299 i=46 false ns=1;i=1300 i=46 false ns=1;i=1301 i=46 false ns=1;i=1348 i=47 false ns=1;i=15018 i=47 false ns=1;i=15019 i=47 false ns=1;i=15020 i=47 false ns=1;i=15021 i=47 false ns=1;i=15022 1 ns=1;i=1288 Variable_2 0 CurrentState CurrentState 0 0 0 i=47 true ns=1;i=1287 i=40 false i=2760 i=46 false ns=1;i=1289 i=46 false ns=1;i=1291 i=21 -1 1 1 0 false 0 ns=1;i=1289 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=1288 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=1291 Variable_2 0 Number Number 0 0 0 i=46 true ns=1;i=1288 i=40 false i=68 0 i=7 -1 1 1 0 false 0 ns=1;i=1293 Variable_2 0 LastTransition LastTransition 0 0 0 i=47 true ns=1;i=1287 i=40 false i=2767 i=46 false ns=1;i=1294 i=46 false ns=1;i=1296 i=46 false ns=1;i=1297 i=21 -1 1 1 0 false 0 ns=1;i=1294 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=1293 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=1296 Variable_2 0 Number Number 0 0 0 i=46 true ns=1;i=1293 i=40 false i=68 0 i=7 -1 1 1 0 false 0 ns=1;i=1297 Variable_2 0 TransitionTime TransitionTime 0 0 0 i=46 true ns=1;i=1293 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=1299 Variable_2 0 Deletable Deletable 0 0 0 i=46 true ns=1;i=1287 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=1300 Variable_2 0 AutoDelete AutoDelete 0 0 0 i=46 true ns=1;i=1287 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=1301 Variable_2 0 RecycleCount RecycleCount 0 0 0 i=46 true ns=1;i=1287 i=40 false i=68 0 i=6 -1 1 1 0 false 0 ns=1;i=1348 Variable_2 1 UpdateRate UpdateRate The rate at which the simulation runs. 0 0 0 i=46 true ns=1;i=1287 i=40 false i=68 0 i=7 -1 3 3 0 false 0 ns=1;i=15013 Method_4 1 Start Start Causes the Program to transition from the Ready state to the Running state. 0 0 0 i=47 true ns=1;i=1178 i=40 false ns=1;i=1095 i=37 false i=78 true true ns=1;i=15014 Method_4 1 Suspend Suspend Causes the Program to transition from the Running state to the Suspended state. 0 0 0 i=47 true ns=1;i=1178 i=40 false ns=1;i=1096 i=37 false i=78 true true ns=1;i=15015 Method_4 1 Resume Resume Causes the Program to transition from the Suspended state to the Running state. 0 0 0 i=47 true ns=1;i=1178 i=40 false ns=1;i=1097 i=37 false i=78 true true ns=1;i=15016 Method_4 1 Halt Halt Causes the Program to transition from the Ready, Running or Suspended state to the Halted state. 0 0 0 i=47 true ns=1;i=1178 i=40 false ns=1;i=1098 i=37 false i=78 true true ns=1;i=15017 Method_4 1 Reset Reset Causes the Program to transition from the Halted state to the Ready state. 0 0 0 i=47 true ns=1;i=1178 i=40 false ns=1;i=1099 i=37 false i=78 true true ns=1;i=15018 Method_4 1 Start Start Causes the Program to transition from the Ready state to the Running state. 0 0 0 i=47 true ns=1;i=1287 i=40 false ns=1;i=1095 true true ns=1;i=15019 Method_4 1 Suspend Suspend Causes the Program to transition from the Running state to the Suspended state. 0 0 0 i=47 true ns=1;i=1287 i=40 false ns=1;i=1096 true true ns=1;i=15020 Method_4 1 Resume Resume Causes the Program to transition from the Suspended state to the Running state. 0 0 0 i=47 true ns=1;i=1287 i=40 false ns=1;i=1097 true true ns=1;i=15021 Method_4 1 Halt Halt Causes the Program to transition from the Ready, Running or Suspended state to the Halted state. 0 0 0 i=47 true ns=1;i=1287 i=40 false ns=1;i=1098 true true ns=1;i=15022 Method_4 1 Reset Reset Causes the Program to transition from the Halted state to the Ready state. 0 0 0 i=47 true ns=1;i=1287 i=40 false ns=1;i=1099 true true ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Boiler/Design/Boiler.NodeSet2.xml ================================================  http://opcfoundation.org/UA/Boiler/ i=1 i=2 i=3 i=4 i=5 i=6 i=7 i=8 i=9 i=10 i=11 i=13 i=12 i=15 i=14 i=16 i=17 i=18 i=20 i=21 i=19 i=22 i=26 i=27 i=28 i=47 i=46 i=35 i=36 i=48 i=45 i=40 i=37 i=38 i=39 FlowTo A reference that indicates a flow between two objects. i=32 FlowFrom HotFlowTo A reference that indicates a high temperature flow between two objects. ns=1;i=985 HotFlowFrom SignalTo A reference that indicates an electrical signal between two variables. i=32 SignalFrom GenericControllerType A generic PID controller ns=1;i=988 ns=1;i=989 ns=1;i=990 i=58 Measurement i=68 i=78 ns=1;i=210 SetPoint i=68 i=78 ns=1;i=210 ControlOut i=68 i=78 ns=1;i=210 GenericSensorType A generic sensor that read a process value. ns=1;i=992 i=58 Output ns=1;i=995 i=2368 i=78 ns=1;i=991 EURange i=68 i=78 ns=1;i=992 GenericActuatorType Represents a piece of equipment that causes some action to occur. ns=1;i=999 i=58 Input ns=1;i=1002 i=2368 i=78 ns=1;i=998 EURange i=68 i=78 ns=1;i=999 CustomControllerType A custom PID controller with 3 inputs ns=1;i=1005 ns=1;i=1006 ns=1;i=1007 ns=1;i=1008 ns=1;i=1009 i=58 Input1 i=68 i=78 ns=1;i=513 Input2 i=68 i=78 ns=1;i=513 Input3 i=68 i=78 ns=1;i=513 ControlOut i=68 i=78 ns=1;i=513 Description i=68 i=78 ns=1;i=513 ValveType An actuator that controls the flow through a pipe. ns=1;i=998 LevelControllerType A controller for the level of a fluid in a drum. ns=1;i=210 FlowControllerType A controller for the flow of a fluid through a pipe. ns=1;i=210 LevelIndicatorType A sensor that reports the level of a liquid in a tank. ns=1;i=991 FlowTransmitterType A sensor that reports the flow of a liquid through a pipe. ns=1;i=991 BoilerStateMachineType A program that produces simulated values for a running boiler. ns=1;i=1095 ns=1;i=1096 ns=1;i=1097 ns=1;i=1098 ns=1;i=1099 ns=1;i=1100 i=2391 Start Causes the Program to transition from the Ready state to the Running state. i=78 ns=1;i=1039 Suspend Causes the Program to transition from the Running state to the Suspended state. i=78 ns=1;i=1039 Resume Causes the Program to transition from the Suspended state to the Running state. i=78 ns=1;i=1039 Halt Causes the Program to transition from the Ready, Running or Suspended state to the Halted state. i=78 ns=1;i=1039 Reset Causes the Program to transition from the Halted state to the Ready state. i=78 ns=1;i=1039 UpdateRate The rate at which the simulation runs. i=68 i=78 ns=1;i=1039 BoilerInputPipeType ns=1;i=1102 ns=1;i=1109 ns=1;i=1102 i=61 FTX001 ns=1;i=1103 ns=1;i=1032 i=78 ns=1;i=1101 Output ns=1;i=1106 i=2368 i=78 ns=1;i=1102 EURange i=68 i=78 ns=1;i=1103 ValveX001 ns=1;i=1110 ns=1;i=1010 i=78 ns=1;i=1101 Input ns=1;i=1113 i=2368 i=78 ns=1;i=1109 EURange i=68 i=78 ns=1;i=1110 BoilerDrumType ns=1;i=1117 ns=1;i=1117 i=61 LIX001 ns=1;i=1118 ns=1;i=1025 i=78 ns=1;i=1116 Output ns=1;i=1121 i=2368 i=78 ns=1;i=1117 EURange i=68 i=78 ns=1;i=1118 BoilerOutputPipeType ns=1;i=1125 ns=1;i=1125 i=61 FTX002 ns=1;i=1126 ns=1;i=1032 i=78 ns=1;i=1124 Output ns=1;i=1129 i=2368 i=78 ns=1;i=1125 EURange i=68 i=78 ns=1;i=1126 BoilerType A boiler used to produce steam for a turbine. ns=1;i=1133 ns=1;i=1148 ns=1;i=1156 ns=1;i=1164 ns=1;i=1168 ns=1;i=1172 ns=1;i=1178 ns=1;i=1133 ns=1;i=1148 ns=1;i=1156 ns=1;i=1178 i=58 PipeX001 ns=1;i=1134 ns=1;i=1141 ns=1;i=1134 ns=1;i=1148 ns=1;i=1101 i=78 ns=1;i=1132 FTX001 ns=1;i=1135 ns=1;i=1133 ns=1;i=1032 i=78 ns=1;i=1133 Output ns=1;i=1138 ns=1;i=1165 ns=1;i=1174 i=2368 i=78 ns=1;i=1134 EURange i=68 i=78 ns=1;i=1135 ValveX001 ns=1;i=1142 ns=1;i=1010 i=78 ns=1;i=1133 Input ns=1;i=1145 ns=1;i=1167 i=2368 i=78 ns=1;i=1141 EURange i=68 i=78 ns=1;i=1142 DrumX001 ns=1;i=1149 ns=1;i=1133 ns=1;i=1149 ns=1;i=1156 ns=1;i=1116 i=78 ns=1;i=1132 LIX001 ns=1;i=1150 ns=1;i=1148 ns=1;i=1025 i=78 ns=1;i=1148 Output ns=1;i=1153 ns=1;i=1169 i=2368 i=78 ns=1;i=1149 EURange i=68 i=78 ns=1;i=1150 PipeX002 ns=1;i=1157 ns=1;i=1148 ns=1;i=1157 ns=1;i=1124 i=78 ns=1;i=1132 FTX002 ns=1;i=1158 ns=1;i=1156 ns=1;i=1032 i=78 ns=1;i=1156 Output ns=1;i=1161 ns=1;i=1175 i=2368 i=78 ns=1;i=1157 EURange i=68 i=78 ns=1;i=1158 FCX001 ns=1;i=1165 ns=1;i=1166 ns=1;i=1167 ns=1;i=1021 i=78 ns=1;i=1132 Measurement ns=1;i=1135 i=68 i=78 ns=1;i=1164 SetPoint ns=1;i=1176 i=68 i=78 ns=1;i=1164 ControlOut ns=1;i=1142 i=68 i=78 ns=1;i=1164 LCX001 ns=1;i=1169 ns=1;i=1170 ns=1;i=1171 ns=1;i=1017 i=78 ns=1;i=1132 Measurement ns=1;i=1150 i=68 i=78 ns=1;i=1168 SetPoint i=68 i=78 ns=1;i=1168 ControlOut ns=1;i=1173 i=68 i=78 ns=1;i=1168 CCX001 ns=1;i=1173 ns=1;i=1174 ns=1;i=1175 ns=1;i=1176 ns=1;i=1177 ns=1;i=513 i=78 ns=1;i=1132 Input1 ns=1;i=1171 i=68 i=78 ns=1;i=1172 Input2 ns=1;i=1135 i=68 i=78 ns=1;i=1172 Input3 ns=1;i=1158 i=68 i=78 ns=1;i=1172 ControlOut ns=1;i=1166 i=68 i=78 ns=1;i=1172 Description i=68 i=78 ns=1;i=1172 Simulation ns=1;i=1179 ns=1;i=1184 ns=1;i=1190 ns=1;i=1191 ns=1;i=1192 ns=1;i=1239 ns=1;i=15013 ns=1;i=15014 ns=1;i=15015 ns=1;i=15016 ns=1;i=15017 ns=1;i=1039 i=78 ns=1;i=1132 CurrentState ns=1;i=1180 ns=1;i=1182 i=2760 i=78 ns=1;i=1178 Id i=68 i=78 ns=1;i=1179 Number i=68 i=78 ns=1;i=1179 LastTransition ns=1;i=1185 ns=1;i=1187 ns=1;i=1188 i=2767 i=78 ns=1;i=1178 Id i=68 i=78 ns=1;i=1184 Number i=68 i=78 ns=1;i=1184 TransitionTime i=68 i=78 ns=1;i=1184 Deletable i=68 i=78 ns=1;i=1178 AutoDelete i=68 i=78 ns=1;i=1178 RecycleCount i=68 i=78 ns=1;i=1178 UpdateRate The rate at which the simulation runs. i=68 i=78 ns=1;i=1178 Start Causes the Program to transition from the Ready state to the Running state. i=78 ns=1;i=1178 Suspend Causes the Program to transition from the Running state to the Suspended state. i=78 ns=1;i=1178 Resume Causes the Program to transition from the Suspended state to the Running state. i=78 ns=1;i=1178 Halt Causes the Program to transition from the Ready, Running or Suspended state to the Halted state. i=78 ns=1;i=1178 Reset Causes the Program to transition from the Halted state to the Ready state. i=78 ns=1;i=1178 Boilers ns=1;i=1241 ns=1;i=1241 i=85 i=2253 i=61 Boiler #1 ns=1;i=1242 ns=1;i=1257 ns=1;i=1265 ns=1;i=1273 ns=1;i=1277 ns=1;i=1281 ns=1;i=1287 ns=1;i=1240 ns=1;i=1242 ns=1;i=1257 ns=1;i=1265 ns=1;i=1287 ns=1;i=1132 ns=1;i=1240 Pipe1001 ns=1;i=1243 ns=1;i=1250 ns=1;i=1241 ns=1;i=1243 ns=1;i=1257 ns=1;i=1101 ns=1;i=1241 FTX001 ns=1;i=1244 ns=1;i=1242 ns=1;i=1032 ns=1;i=1242 Output ns=1;i=1247 ns=1;i=1274 ns=1;i=1283 i=2368 ns=1;i=1243 EURange i=68 ns=1;i=1244 ValveX001 ns=1;i=1251 ns=1;i=1010 ns=1;i=1242 Input ns=1;i=1254 ns=1;i=1276 i=2368 ns=1;i=1250 EURange i=68 ns=1;i=1251 Drum1001 ns=1;i=1258 ns=1;i=1241 ns=1;i=1242 ns=1;i=1258 ns=1;i=1265 ns=1;i=1116 ns=1;i=1241 LIX001 ns=1;i=1259 ns=1;i=1257 ns=1;i=1025 ns=1;i=1257 Output ns=1;i=1262 ns=1;i=1278 i=2368 ns=1;i=1258 EURange i=68 ns=1;i=1259 Pipe1002 ns=1;i=1266 ns=1;i=1241 ns=1;i=1257 ns=1;i=1266 ns=1;i=1124 ns=1;i=1241 FTX002 ns=1;i=1267 ns=1;i=1265 ns=1;i=1032 ns=1;i=1265 Output ns=1;i=1270 ns=1;i=1284 i=2368 ns=1;i=1266 EURange i=68 ns=1;i=1267 FC1001 ns=1;i=1274 ns=1;i=1275 ns=1;i=1276 ns=1;i=1021 ns=1;i=1241 Measurement ns=1;i=1244 i=68 ns=1;i=1273 SetPoint ns=1;i=1285 i=68 ns=1;i=1273 ControlOut ns=1;i=1251 i=68 ns=1;i=1273 LC1001 ns=1;i=1278 ns=1;i=1279 ns=1;i=1280 ns=1;i=1017 ns=1;i=1241 Measurement ns=1;i=1259 i=68 ns=1;i=1277 SetPoint i=68 ns=1;i=1277 ControlOut ns=1;i=1282 i=68 ns=1;i=1277 CC1001 ns=1;i=1282 ns=1;i=1283 ns=1;i=1284 ns=1;i=1285 ns=1;i=1286 ns=1;i=513 ns=1;i=1241 Input1 ns=1;i=1280 i=68 ns=1;i=1281 Input2 ns=1;i=1244 i=68 ns=1;i=1281 Input3 ns=1;i=1267 i=68 ns=1;i=1281 ControlOut ns=1;i=1275 i=68 ns=1;i=1281 Description i=68 ns=1;i=1281 Simulation ns=1;i=1288 ns=1;i=1293 ns=1;i=1299 ns=1;i=1300 ns=1;i=1301 ns=1;i=1348 ns=1;i=15018 ns=1;i=15019 ns=1;i=15020 ns=1;i=15021 ns=1;i=15022 ns=1;i=1241 ns=1;i=1039 ns=1;i=1241 CurrentState ns=1;i=1289 ns=1;i=1291 i=2760 ns=1;i=1287 Id i=68 ns=1;i=1288 Number i=68 ns=1;i=1288 LastTransition ns=1;i=1294 ns=1;i=1296 ns=1;i=1297 i=2767 ns=1;i=1287 Id i=68 ns=1;i=1293 Number i=68 ns=1;i=1293 TransitionTime i=68 ns=1;i=1293 Deletable i=68 ns=1;i=1287 AutoDelete i=68 ns=1;i=1287 RecycleCount i=68 ns=1;i=1287 UpdateRate The rate at which the simulation runs. i=68 ns=1;i=1287 Start Causes the Program to transition from the Ready state to the Running state. ns=1;i=1287 Suspend Causes the Program to transition from the Running state to the Suspended state. ns=1;i=1287 Resume Causes the Program to transition from the Suspended state to the Running state. ns=1;i=1287 Halt Causes the Program to transition from the Ready, Running or Suspended state to the Halted state. ns=1;i=1287 Reset Causes the Program to transition from the Halted state to the Ready state. ns=1;i=1287 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Boiler/Design/Boiler.PredefinedNodes.xml ================================================  http://opcfoundation.org/UA/Boiler/ ReferenceType_32 ns=1;i=985 1 FlowTo A reference that indicates a flow between two objects. i=32 FlowFrom ReferenceType_32 ns=1;i=986 1 HotFlowTo A reference that indicates a high temperature flow between two objects. ns=1;i=985 HotFlowFrom ReferenceType_32 ns=1;i=987 1 SignalTo A reference that indicates an electrical signal between two variables. i=32 SignalFrom ObjectType_8 ns=1;i=210 1 GenericControllerType A generic PID controller i=58 Variable_2 ns=1;i=988 1 Measurement i=46 i=68 i=78 988 i=11 -1 1 1 Variable_2 ns=1;i=989 1 SetPoint i=46 i=68 i=78 989 i=11 -1 3 3 Variable_2 ns=1;i=990 1 ControlOut i=46 i=68 i=78 990 i=11 -1 1 1 ObjectType_8 ns=1;i=991 1 GenericSensorType A generic sensor that read a process value. i=58 Variable_2 ns=1;i=992 1 Output i=47 i=2368 i=78 992 i=11 -1 1 1 Variable_2 ns=1;i=995 0 EURange i=46 i=68 i=78 995 i=884 -1 1 1 ObjectType_8 ns=1;i=998 1 GenericActuatorType Represents a piece of equipment that causes some action to occur. i=58 Variable_2 ns=1;i=999 1 Input i=47 i=2368 i=78 999 i=11 -1 2 2 Variable_2 ns=1;i=1002 0 EURange i=46 i=68 i=78 1002 i=884 -1 1 1 ObjectType_8 ns=1;i=513 1 CustomControllerType A custom PID controller with 3 inputs i=58 Variable_2 ns=1;i=1005 1 Input1 i=46 i=68 i=78 1005 i=11 -1 2 2 Variable_2 ns=1;i=1006 1 Input2 i=46 i=68 i=78 1006 i=11 -1 2 2 Variable_2 ns=1;i=1007 1 Input3 i=46 i=68 i=78 1007 i=11 -1 2 2 Variable_2 ns=1;i=1008 1 ControlOut i=46 i=68 i=78 1008 i=11 -1 1 1 Variable_2 ns=1;i=1009 1 Description i=46 i=68 i=78 1009 i=21 -1 1 1 ObjectType_8 ns=1;i=1010 1 ValveType An actuator that controls the flow through a pipe. ns=1;i=998 ObjectType_8 ns=1;i=1017 1 LevelControllerType A controller for the level of a fluid in a drum. ns=1;i=210 ObjectType_8 ns=1;i=1021 1 FlowControllerType A controller for the flow of a fluid through a pipe. ns=1;i=210 ObjectType_8 ns=1;i=1025 1 LevelIndicatorType A sensor that reports the level of a liquid in a tank. ns=1;i=991 ObjectType_8 ns=1;i=1032 1 FlowTransmitterType A sensor that reports the flow of a liquid through a pipe. ns=1;i=991 ObjectType_8 ns=1;i=1039 1 BoilerStateMachineType A program that produces simulated values for a running boiler. i=2391 Method_4 ns=1;i=1095 1 Start Causes the Program to transition from the Ready state to the Running state. i=47 i=2426 i=78 1095 true true Method_4 ns=1;i=1096 1 Suspend Causes the Program to transition from the Running state to the Suspended state. i=47 i=2427 i=78 1096 true true Method_4 ns=1;i=1097 1 Resume Causes the Program to transition from the Suspended state to the Running state. i=47 i=2428 i=78 1097 true true Method_4 ns=1;i=1098 1 Halt Causes the Program to transition from the Ready, Running or Suspended state to the Halted state. i=47 i=2429 i=78 1098 true true Method_4 ns=1;i=1099 1 Reset Causes the Program to transition from the Halted state to the Ready state. i=47 i=2430 i=78 1099 true true Variable_2 ns=1;i=1100 1 UpdateRate The rate at which the simulation runs. i=46 i=68 i=78 1100 i=7 -1 3 3 ObjectType_8 ns=1;i=1101 1 BoilerInputPipeType i=61 i=48 ns=1;i=1102 Object_1 ns=1;i=1102 1 FTX001 i=47 ns=1;i=1032 i=78 1102 1 Variable_2 ns=1;i=1103 1 Output i=47 i=2368 i=78 1103 i=11 -1 1 1 Variable_2 ns=1;i=1106 0 EURange i=46 i=68 i=78 1106 i=884 -1 1 1 Object_1 ns=1;i=1109 1 ValveX001 i=47 ns=1;i=1010 i=78 1109 1 Variable_2 ns=1;i=1110 1 Input i=47 i=2368 i=78 1110 i=11 -1 2 2 Variable_2 ns=1;i=1113 0 EURange i=46 i=68 i=78 1113 i=884 -1 1 1 ObjectType_8 ns=1;i=1116 1 BoilerDrumType i=61 i=48 ns=1;i=1117 Object_1 ns=1;i=1117 1 LIX001 i=47 ns=1;i=1025 i=78 1117 1 Variable_2 ns=1;i=1118 1 Output i=47 i=2368 i=78 1118 i=11 -1 1 1 Variable_2 ns=1;i=1121 0 EURange i=46 i=68 i=78 1121 i=884 -1 1 1 ObjectType_8 ns=1;i=1124 1 BoilerOutputPipeType i=61 i=48 ns=1;i=1125 Object_1 ns=1;i=1125 1 FTX002 i=47 ns=1;i=1032 i=78 1125 1 Variable_2 ns=1;i=1126 1 Output i=47 i=2368 i=78 1126 i=11 -1 1 1 Variable_2 ns=1;i=1129 0 EURange i=46 i=68 i=78 1129 i=884 -1 1 1 ObjectType_8 ns=1;i=1132 1 BoilerType A boiler used to produce steam for a turbine. i=58 i=48 ns=1;i=1133 i=48 ns=1;i=1148 i=48 ns=1;i=1156 i=36 ns=1;i=1178 Object_1 ns=1;i=1133 1 PipeX001 i=47 ns=1;i=1101 i=78 1133 1 i=48 ns=1;i=1134 ns=1;i=985 ns=1;i=1148 Object_1 ns=1;i=1134 1 FTX001 i=47 ns=1;i=1032 i=78 1134 1 i=48 true ns=1;i=1133 Variable_2 ns=1;i=1135 1 Output i=47 i=2368 i=78 1135 i=11 -1 1 1 ns=1;i=987 ns=1;i=1165 ns=1;i=987 ns=1;i=1174 Variable_2 ns=1;i=1138 0 EURange i=46 i=68 i=78 1138 i=884 -1 1 1 Object_1 ns=1;i=1141 1 ValveX001 i=47 ns=1;i=1010 i=78 1141 1 Variable_2 ns=1;i=1142 1 Input i=47 i=2368 i=78 1142 i=11 -1 2 2 ns=1;i=987 true ns=1;i=1167 Variable_2 ns=1;i=1145 0 EURange i=46 i=68 i=78 1145 i=884 -1 1 1 Object_1 ns=1;i=1148 1 DrumX001 i=47 ns=1;i=1116 i=78 1148 1 ns=1;i=985 true ns=1;i=1133 i=48 ns=1;i=1149 ns=1;i=986 ns=1;i=1156 Object_1 ns=1;i=1149 1 LIX001 i=47 ns=1;i=1025 i=78 1149 1 i=48 true ns=1;i=1148 Variable_2 ns=1;i=1150 1 Output i=47 i=2368 i=78 1150 i=26 -1 1 1 ns=1;i=987 ns=1;i=1169 Variable_2 ns=1;i=1153 0 EURange i=46 i=68 i=78 1153 i=884 -1 1 1 Object_1 ns=1;i=1156 1 PipeX002 i=47 ns=1;i=1124 i=78 1156 1 ns=1;i=986 true ns=1;i=1148 i=48 ns=1;i=1157 Object_1 ns=1;i=1157 1 FTX002 i=47 ns=1;i=1032 i=78 1157 1 i=48 true ns=1;i=1156 Variable_2 ns=1;i=1158 1 Output i=47 i=2368 i=78 1158 i=11 -1 1 1 ns=1;i=987 ns=1;i=1175 Variable_2 ns=1;i=1161 0 EURange i=46 i=68 i=78 1161 i=884 -1 1 1 Object_1 ns=1;i=1164 1 FCX001 i=47 ns=1;i=1021 i=78 1164 Variable_2 ns=1;i=1165 1 Measurement i=46 i=68 i=78 1165 i=11 -1 1 1 ns=1;i=987 true ns=1;i=1135 Variable_2 ns=1;i=1166 1 SetPoint i=46 i=68 i=78 1166 i=11 -1 3 3 ns=1;i=987 true ns=1;i=1176 Variable_2 ns=1;i=1167 1 ControlOut i=46 i=68 i=78 1167 i=11 -1 1 1 ns=1;i=987 ns=1;i=1142 Object_1 ns=1;i=1168 1 LCX001 i=47 ns=1;i=1017 i=78 1168 Variable_2 ns=1;i=1169 1 Measurement i=46 i=68 i=78 1169 i=11 -1 1 1 ns=1;i=987 true ns=1;i=1150 Variable_2 ns=1;i=1170 1 SetPoint i=46 i=68 i=78 1170 i=11 -1 3 3 Variable_2 ns=1;i=1171 1 ControlOut i=46 i=68 i=78 1171 i=11 -1 1 1 ns=1;i=987 ns=1;i=1173 Object_1 ns=1;i=1172 1 CCX001 i=47 ns=1;i=513 i=78 1172 Variable_2 ns=1;i=1173 1 Input1 i=46 i=68 i=78 1173 i=11 -1 2 2 ns=1;i=987 true ns=1;i=1171 Variable_2 ns=1;i=1174 1 Input2 i=46 i=68 i=78 1174 i=11 -1 2 2 ns=1;i=987 true ns=1;i=1135 Variable_2 ns=1;i=1175 1 Input3 i=46 i=68 i=78 1175 i=11 -1 2 2 ns=1;i=987 true ns=1;i=1158 Variable_2 ns=1;i=1176 1 ControlOut i=46 i=68 i=78 1176 i=11 -1 1 1 ns=1;i=987 ns=1;i=1166 Variable_2 ns=1;i=1177 1 Description i=46 i=68 i=78 1177 i=21 -1 1 1 Object_1 ns=1;i=1178 1 Simulation i=47 ns=1;i=1039 i=78 1178 1 Variable_2 ns=1;i=1179 0 CurrentState i=47 i=2760 i=78 1179 i=21 -1 1 1 Variable_2 ns=1;i=1180 0 Id i=46 i=68 i=78 1180 i=17 -1 1 1 Variable_2 ns=1;i=1182 0 Number i=46 i=68 i=78 1182 i=7 -1 1 1 Variable_2 ns=1;i=1184 0 LastTransition i=47 i=2767 i=78 1184 i=21 -1 1 1 Variable_2 ns=1;i=1185 0 Id i=46 i=68 i=78 1185 i=17 -1 1 1 Variable_2 ns=1;i=1187 0 Number i=46 i=68 i=78 1187 i=7 -1 1 1 Variable_2 ns=1;i=1188 0 TransitionTime i=46 i=68 i=78 1188 i=294 -1 1 1 Variable_2 ns=1;i=1190 0 Deletable i=46 i=68 i=78 1190 i=1 -1 1 1 Variable_2 ns=1;i=1191 0 AutoDelete i=46 i=68 i=78 1191 i=1 -1 1 1 Variable_2 ns=1;i=1192 0 RecycleCount i=46 i=68 i=78 1192 i=6 -1 1 1 Variable_2 ns=1;i=1239 1 UpdateRate The rate at which the simulation runs. i=46 i=68 i=78 1239 i=7 -1 3 3 Method_4 ns=1;i=15013 1 Start Causes the Program to transition from the Ready state to the Running state. i=47 ns=1;i=1095 i=78 15013 true true Method_4 ns=1;i=15014 1 Suspend Causes the Program to transition from the Running state to the Suspended state. i=47 ns=1;i=1096 i=78 15014 true true Method_4 ns=1;i=15015 1 Resume Causes the Program to transition from the Suspended state to the Running state. i=47 ns=1;i=1097 i=78 15015 true true Method_4 ns=1;i=15016 1 Halt Causes the Program to transition from the Ready, Running or Suspended state to the Halted state. i=47 ns=1;i=1098 i=78 15016 true true Method_4 ns=1;i=15017 1 Reset Causes the Program to transition from the Halted state to the Ready state. i=47 ns=1;i=1099 i=78 15017 true true Object_1 ns=1;i=1240 1 Boilers i=47 i=61 1240 1 i=48 ns=1;i=1241 i=35 true i=85 i=48 true i=2253 Object_1 ns=1;i=1241 1 Boiler #1 i=47 ns=1;i=1132 1241 i=48 true ns=1;i=1240 i=48 ns=1;i=1242 i=48 ns=1;i=1257 i=48 ns=1;i=1265 i=36 ns=1;i=1287 Object_1 ns=1;i=1242 1 PipeX001 Pipe1001 i=47 ns=1;i=1101 1242 1 i=48 true ns=1;i=1241 i=48 ns=1;i=1243 ns=1;i=985 ns=1;i=1257 Object_1 ns=1;i=1243 1 FTX001 i=47 ns=1;i=1032 1243 1 i=48 true ns=1;i=1242 Variable_2 ns=1;i=1244 1 Output i=47 i=2368 1244 i=11 -1 1 1 ns=1;i=987 ns=1;i=1274 ns=1;i=987 ns=1;i=1283 Variable_2 ns=1;i=1247 0 EURange i=46 i=68 1247 i=884 -1 1 1 Object_1 ns=1;i=1250 1 ValveX001 i=47 ns=1;i=1010 1250 1 Variable_2 ns=1;i=1251 1 Input i=47 i=2368 1251 i=11 -1 2 2 ns=1;i=987 true ns=1;i=1276 Variable_2 ns=1;i=1254 0 EURange i=46 i=68 1254 i=884 -1 1 1 Object_1 ns=1;i=1257 1 DrumX001 Drum1001 i=47 ns=1;i=1116 1257 1 i=48 true ns=1;i=1241 ns=1;i=985 true ns=1;i=1242 i=48 ns=1;i=1258 ns=1;i=986 ns=1;i=1265 Object_1 ns=1;i=1258 1 LIX001 i=47 ns=1;i=1025 1258 1 i=48 true ns=1;i=1257 Variable_2 ns=1;i=1259 1 Output i=47 i=2368 1259 i=26 -1 1 1 ns=1;i=987 ns=1;i=1278 Variable_2 ns=1;i=1262 0 EURange i=46 i=68 1262 i=884 -1 1 1 Object_1 ns=1;i=1265 1 PipeX002 Pipe1002 i=47 ns=1;i=1124 1265 1 i=48 true ns=1;i=1241 ns=1;i=986 true ns=1;i=1257 i=48 ns=1;i=1266 Object_1 ns=1;i=1266 1 FTX002 i=47 ns=1;i=1032 1266 1 i=48 true ns=1;i=1265 Variable_2 ns=1;i=1267 1 Output i=47 i=2368 1267 i=11 -1 1 1 ns=1;i=987 ns=1;i=1284 Variable_2 ns=1;i=1270 0 EURange i=46 i=68 1270 i=884 -1 1 1 Object_1 ns=1;i=1273 1 FCX001 FC1001 i=47 ns=1;i=1021 1273 Variable_2 ns=1;i=1274 1 Measurement i=46 i=68 1274 i=11 -1 1 1 ns=1;i=987 true ns=1;i=1244 Variable_2 ns=1;i=1275 1 SetPoint i=46 i=68 1275 i=11 -1 3 3 ns=1;i=987 true ns=1;i=1285 Variable_2 ns=1;i=1276 1 ControlOut i=46 i=68 1276 i=11 -1 1 1 ns=1;i=987 ns=1;i=1251 Object_1 ns=1;i=1277 1 LCX001 LC1001 i=47 ns=1;i=1017 1277 Variable_2 ns=1;i=1278 1 Measurement i=46 i=68 1278 i=11 -1 1 1 ns=1;i=987 true ns=1;i=1259 Variable_2 ns=1;i=1279 1 SetPoint i=46 i=68 1279 i=11 -1 3 3 Variable_2 ns=1;i=1280 1 ControlOut i=46 i=68 1280 i=11 -1 1 1 ns=1;i=987 ns=1;i=1282 Object_1 ns=1;i=1281 1 CCX001 CC1001 i=47 ns=1;i=513 1281 Variable_2 ns=1;i=1282 1 Input1 i=46 i=68 1282 i=11 -1 2 2 ns=1;i=987 true ns=1;i=1280 Variable_2 ns=1;i=1283 1 Input2 i=46 i=68 1283 i=11 -1 2 2 ns=1;i=987 true ns=1;i=1244 Variable_2 ns=1;i=1284 1 Input3 i=46 i=68 1284 i=11 -1 2 2 ns=1;i=987 true ns=1;i=1267 Variable_2 ns=1;i=1285 1 ControlOut i=46 i=68 1285 i=11 -1 1 1 ns=1;i=987 ns=1;i=1275 Variable_2 ns=1;i=1286 1 Description i=46 i=68 1286 i=21 -1 1 1 Object_1 ns=1;i=1287 1 Simulation i=47 ns=1;i=1039 1287 1 i=36 true ns=1;i=1241 Variable_2 ns=1;i=1288 0 CurrentState i=47 i=2760 1288 i=21 -1 1 1 Variable_2 ns=1;i=1289 0 Id i=46 i=68 1289 i=17 -1 1 1 Variable_2 ns=1;i=1291 0 Number i=46 i=68 1291 i=7 -1 1 1 Variable_2 ns=1;i=1293 0 LastTransition i=47 i=2767 1293 i=21 -1 1 1 Variable_2 ns=1;i=1294 0 Id i=46 i=68 1294 i=17 -1 1 1 Variable_2 ns=1;i=1296 0 Number i=46 i=68 1296 i=7 -1 1 1 Variable_2 ns=1;i=1297 0 TransitionTime i=46 i=68 1297 i=294 -1 1 1 Variable_2 ns=1;i=1299 0 Deletable i=46 i=68 1299 i=1 -1 1 1 Variable_2 ns=1;i=1300 0 AutoDelete i=46 i=68 1300 i=1 -1 1 1 Variable_2 ns=1;i=1301 0 RecycleCount i=46 i=68 1301 i=6 -1 1 1 Variable_2 ns=1;i=1348 1 UpdateRate The rate at which the simulation runs. i=46 i=68 1348 i=7 -1 3 3 Method_4 ns=1;i=15018 1 Start Causes the Program to transition from the Ready state to the Running state. i=47 ns=1;i=1095 15018 true true Method_4 ns=1;i=15019 1 Suspend Causes the Program to transition from the Running state to the Suspended state. i=47 ns=1;i=1096 15019 true true Method_4 ns=1;i=15020 1 Resume Causes the Program to transition from the Suspended state to the Running state. i=47 ns=1;i=1097 15020 true true Method_4 ns=1;i=15021 1 Halt Causes the Program to transition from the Ready, Running or Suspended state to the Halted state. i=47 ns=1;i=1098 15021 true true Method_4 ns=1;i=15022 1 Reset Causes the Program to transition from the Halted state to the Ready state. i=47 ns=1;i=1099 15022 true true ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Boiler/Design/Boiler.Types.bsd ================================================ ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Boiler/Design/Boiler.Types.xsd ================================================ ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Boiler/Design/BoilerDesign.csv ================================================ GenericControllerType,210,ObjectType CustomControllerType,513,ObjectType FlowTo,985,ReferenceType HotFlowTo,986,ReferenceType SignalTo,987,ReferenceType GenericControllerType_Measurement,988,Variable GenericControllerType_SetPoint,989,Variable GenericControllerType_ControlOut,990,Variable GenericSensorType,991,ObjectType GenericSensorType_Output,992,Variable GenericSensorType_Output_Definition,993,Variable GenericSensorType_Output_ValuePrecision,994,Variable GenericSensorType_Output_EURange,995,Variable GenericSensorType_Output_InstrumentRange,996,Variable GenericSensorType_Output_EngineeringUnits,997,Variable GenericActuatorType,998,ObjectType GenericActuatorType_Input,999,Variable GenericActuatorType_Input_Definition,1000,Variable GenericActuatorType_Input_ValuePrecision,1001,Variable GenericActuatorType_Input_EURange,1002,Variable GenericActuatorType_Input_InstrumentRange,1003,Variable GenericActuatorType_Input_EngineeringUnits,1004,Variable CustomControllerType_Input1,1005,Variable CustomControllerType_Input2,1006,Variable CustomControllerType_Input3,1007,Variable CustomControllerType_ControlOut,1008,Variable CustomControllerType_DescriptionX,1009,Variable ValveType,1010,ObjectType ValveType_Input,1011,Variable ValveType_Input_Definition,1012,Variable ValveType_Input_ValuePrecision,1013,Variable ValveType_Input_EURange,1014,Variable ValveType_Input_InstrumentRange,1015,Variable ValveType_Input_EngineeringUnits,1016,Variable LevelControllerType,1017,ObjectType LevelControllerType_Measurement,1018,Variable LevelControllerType_SetPoint,1019,Variable LevelControllerType_ControlOut,1020,Variable FlowControllerType,1021,ObjectType FlowControllerType_Measurement,1022,Variable FlowControllerType_SetPoint,1023,Variable FlowControllerType_ControlOut,1024,Variable LevelIndicatorType,1025,ObjectType LevelIndicatorType_Output,1026,Variable LevelIndicatorType_Output_Definition,1027,Variable LevelIndicatorType_Output_ValuePrecision,1028,Variable LevelIndicatorType_Output_EURange,1029,Variable LevelIndicatorType_Output_InstrumentRange,1030,Variable LevelIndicatorType_Output_EngineeringUnits,1031,Variable FlowTransmitterType,1032,ObjectType FlowTransmitterType_Output,1033,Variable FlowTransmitterType_Output_Definition,1034,Variable FlowTransmitterType_Output_ValuePrecision,1035,Variable FlowTransmitterType_Output_EURange,1036,Variable FlowTransmitterType_Output_InstrumentRange,1037,Variable FlowTransmitterType_Output_EngineeringUnits,1038,Variable BoilerStateMachineType,1039,ObjectType BoilerStateMachineType_CurrentState,1040,Variable BoilerStateMachineType_CurrentState_Id,1041,Variable BoilerStateMachineType_CurrentState_Name,1042,Variable BoilerStateMachineType_CurrentState_Number,1043,Variable BoilerStateMachineType_CurrentState_EffectiveDisplayName,1044,Variable BoilerStateMachineType_LastTransition,1045,Variable BoilerStateMachineType_LastTransition_Id,1046,Variable BoilerStateMachineType_LastTransition_Name,1047,Variable BoilerStateMachineType_LastTransition_Number,1048,Variable BoilerStateMachineType_LastTransition_TransitionTime,1049,Variable BoilerStateMachineType_Creatable,1050,Variable BoilerStateMachineType_Deletable,1051,Variable BoilerStateMachineType_AutoDelete,1052,Variable BoilerStateMachineType_RecycleCount,1053,Variable BoilerStateMachineType_InstanceCount,1054,Variable BoilerStateMachineType_MaxInstanceCount,1055,Variable BoilerStateMachineType_MaxRecycleCount,1056,Variable BoilerStateMachineType_FinalResultData,1068,Object BoilerStateMachineType_Ready,1069,Object BoilerStateMachineType_Ready_StateNumber,1070,Variable BoilerStateMachineType_Running,1071,Object BoilerStateMachineType_Running_StateNumber,1072,Variable BoilerStateMachineType_Suspended,1073,Object BoilerStateMachineType_Suspended_StateNumber,1074,Variable BoilerStateMachineType_Halted,1075,Object BoilerStateMachineType_Halted_StateNumber,1076,Variable BoilerStateMachineType_HaltedToReady,1077,Object BoilerStateMachineType_HaltedToReady_TransitionNumber,1078,Variable BoilerStateMachineType_ReadyToRunning,1079,Object BoilerStateMachineType_ReadyToRunning_TransitionNumber,1080,Variable BoilerStateMachineType_RunningToHalted,1081,Object BoilerStateMachineType_RunningToHalted_TransitionNumber,1082,Variable BoilerStateMachineType_RunningToReady,1083,Object BoilerStateMachineType_RunningToReady_TransitionNumber,1084,Variable BoilerStateMachineType_RunningToSuspended,1085,Object BoilerStateMachineType_RunningToSuspended_TransitionNumber,1086,Variable BoilerStateMachineType_SuspendedToRunning,1087,Object BoilerStateMachineType_SuspendedToRunning_TransitionNumber,1088,Variable BoilerStateMachineType_SuspendedToHalted,1089,Object BoilerStateMachineType_SuspendedToHalted_TransitionNumber,1090,Variable BoilerStateMachineType_SuspendedToReady,1091,Object BoilerStateMachineType_SuspendedToReady_TransitionNumber,1092,Variable BoilerStateMachineType_ReadyToHalted,1093,Object BoilerStateMachineType_ReadyToHalted_TransitionNumber,1094,Variable BoilerStateMachineType_Start,1095,Method BoilerStateMachineType_Suspend,1096,Method BoilerStateMachineType_Resume,1097,Method BoilerStateMachineType_Halt,1098,Method BoilerStateMachineType_Reset,1099,Method BoilerStateMachineType_UpdateRate,1100,Variable BoilerInputPipeType,1101,ObjectType BoilerInputPipeType_FlowTransmitter1,1102,Object BoilerInputPipeType_FlowTransmitter1_Output,1103,Variable BoilerInputPipeType_FlowTransmitter1_Output_Definition,1104,Variable BoilerInputPipeType_FlowTransmitter1_Output_ValuePrecision,1105,Variable BoilerInputPipeType_FlowTransmitter1_Output_EURange,1106,Variable BoilerInputPipeType_FlowTransmitter1_Output_InstrumentRange,1107,Variable BoilerInputPipeType_FlowTransmitter1_Output_EngineeringUnits,1108,Variable BoilerInputPipeType_Valve,1109,Object BoilerInputPipeType_Valve_Input,1110,Variable BoilerInputPipeType_Valve_Input_Definition,1111,Variable BoilerInputPipeType_Valve_Input_ValuePrecision,1112,Variable BoilerInputPipeType_Valve_Input_EURange,1113,Variable BoilerInputPipeType_Valve_Input_InstrumentRange,1114,Variable BoilerInputPipeType_Valve_Input_EngineeringUnits,1115,Variable BoilerDrumType,1116,ObjectType BoilerDrumType_LevelIndicator,1117,Object BoilerDrumType_LevelIndicator_Output,1118,Variable BoilerDrumType_LevelIndicator_Output_Definition,1119,Variable BoilerDrumType_LevelIndicator_Output_ValuePrecision,1120,Variable BoilerDrumType_LevelIndicator_Output_EURange,1121,Variable BoilerDrumType_LevelIndicator_Output_InstrumentRange,1122,Variable BoilerDrumType_LevelIndicator_Output_EngineeringUnits,1123,Variable BoilerOutputPipeType,1124,ObjectType BoilerOutputPipeType_FlowTransmitter2,1125,Object BoilerOutputPipeType_FlowTransmitter2_Output,1126,Variable BoilerOutputPipeType_FlowTransmitter2_Output_Definition,1127,Variable BoilerOutputPipeType_FlowTransmitter2_Output_ValuePrecision,1128,Variable BoilerOutputPipeType_FlowTransmitter2_Output_EURange,1129,Variable BoilerOutputPipeType_FlowTransmitter2_Output_InstrumentRange,1130,Variable BoilerOutputPipeType_FlowTransmitter2_Output_EngineeringUnits,1131,Variable BoilerType,1132,ObjectType BoilerType_InputPipe,1133,Object BoilerType_InputPipe_FlowTransmitter1,1134,Object BoilerType_InputPipe_FlowTransmitter1_Output,1135,Variable BoilerType_InputPipe_FlowTransmitter1_Output_Definition,1136,Variable BoilerType_InputPipe_FlowTransmitter1_Output_ValuePrecision,1137,Variable BoilerType_InputPipe_FlowTransmitter1_Output_EURange,1138,Variable BoilerType_InputPipe_FlowTransmitter1_Output_InstrumentRange,1139,Variable BoilerType_InputPipe_FlowTransmitter1_Output_EngineeringUnits,1140,Variable BoilerType_InputPipe_Valve,1141,Object BoilerType_InputPipe_Valve_Input,1142,Variable BoilerType_InputPipe_Valve_Input_Definition,1143,Variable BoilerType_InputPipe_Valve_Input_ValuePrecision,1144,Variable BoilerType_InputPipe_Valve_Input_EURange,1145,Variable BoilerType_InputPipe_Valve_Input_InstrumentRange,1146,Variable BoilerType_InputPipe_Valve_Input_EngineeringUnits,1147,Variable BoilerType_Drum,1148,Object BoilerType_Drum_LevelIndicator,1149,Object BoilerType_Drum_LevelIndicator_Output,1150,Variable BoilerType_Drum_LevelIndicator_Output_Definition,1151,Variable BoilerType_Drum_LevelIndicator_Output_ValuePrecision,1152,Variable BoilerType_Drum_LevelIndicator_Output_EURange,1153,Variable BoilerType_Drum_LevelIndicator_Output_InstrumentRange,1154,Variable BoilerType_Drum_LevelIndicator_Output_EngineeringUnits,1155,Variable BoilerType_OutputPipe,1156,Object BoilerType_OutputPipe_FlowTransmitter2,1157,Object BoilerType_OutputPipe_FlowTransmitter2_Output,1158,Variable BoilerType_OutputPipe_FlowTransmitter2_Output_Definition,1159,Variable BoilerType_OutputPipe_FlowTransmitter2_Output_ValuePrecision,1160,Variable BoilerType_OutputPipe_FlowTransmitter2_Output_EURange,1161,Variable BoilerType_OutputPipe_FlowTransmitter2_Output_InstrumentRange,1162,Variable BoilerType_OutputPipe_FlowTransmitter2_Output_EngineeringUnits,1163,Variable BoilerType_FlowController,1164,Object BoilerType_FlowController_Measurement,1165,Variable BoilerType_FlowController_SetPoint,1166,Variable BoilerType_FlowController_ControlOut,1167,Variable BoilerType_LevelController,1168,Object BoilerType_LevelController_Measurement,1169,Variable BoilerType_LevelController_SetPoint,1170,Variable BoilerType_LevelController_ControlOut,1171,Variable BoilerType_CustomController,1172,Object BoilerType_CustomController_Input1,1173,Variable BoilerType_CustomController_Input2,1174,Variable BoilerType_CustomController_Input3,1175,Variable BoilerType_CustomController_ControlOut,1176,Variable BoilerType_CustomController_DescriptionX,1177,Variable BoilerType_Simulation,1178,Object BoilerType_Simulation_CurrentState,1179,Variable BoilerType_Simulation_CurrentState_Id,1180,Variable BoilerType_Simulation_CurrentState_Name,1181,Variable BoilerType_Simulation_CurrentState_Number,1182,Variable BoilerType_Simulation_CurrentState_EffectiveDisplayName,1183,Variable BoilerType_Simulation_LastTransition,1184,Variable BoilerType_Simulation_LastTransition_Id,1185,Variable BoilerType_Simulation_LastTransition_Name,1186,Variable BoilerType_Simulation_LastTransition_Number,1187,Variable BoilerType_Simulation_LastTransition_TransitionTime,1188,Variable BoilerType_Simulation_Deletable,1190,Variable BoilerType_Simulation_AutoDelete,1191,Variable BoilerType_Simulation_RecycleCount,1192,Variable BoilerType_Simulation_FinalResultData,1207,Object BoilerType_Simulation_UpdateRate,1239,Variable Boilers,1240,Object Boilers_Boiler1,1241,Object Boilers_Boiler1_InputPipe,1242,Object Boilers_Boiler1_InputPipe_FlowTransmitter1,1243,Object Boilers_Boiler1_InputPipe_FlowTransmitter1_Output,1244,Variable Boilers_Boiler1_InputPipe_FlowTransmitter1_Output_Definition,1245,Variable Boilers_Boiler1_InputPipe_FlowTransmitter1_Output_ValuePrecision,1246,Variable Boilers_Boiler1_InputPipe_FlowTransmitter1_Output_EURange,1247,Variable Boilers_Boiler1_InputPipe_FlowTransmitter1_Output_InstrumentRange,1248,Variable Boilers_Boiler1_InputPipe_FlowTransmitter1_Output_EngineeringUnits,1249,Variable Boilers_Boiler1_InputPipe_Valve,1250,Object Boilers_Boiler1_InputPipe_Valve_Input,1251,Variable Boilers_Boiler1_InputPipe_Valve_Input_Definition,1252,Variable Boilers_Boiler1_InputPipe_Valve_Input_ValuePrecision,1253,Variable Boilers_Boiler1_InputPipe_Valve_Input_EURange,1254,Variable Boilers_Boiler1_InputPipe_Valve_Input_InstrumentRange,1255,Variable Boilers_Boiler1_InputPipe_Valve_Input_EngineeringUnits,1256,Variable Boilers_Boiler1_Drum,1257,Object Boilers_Boiler1_Drum_LevelIndicator,1258,Object Boilers_Boiler1_Drum_LevelIndicator_Output,1259,Variable Boilers_Boiler1_Drum_LevelIndicator_Output_Definition,1260,Variable Boilers_Boiler1_Drum_LevelIndicator_Output_ValuePrecision,1261,Variable Boilers_Boiler1_Drum_LevelIndicator_Output_EURange,1262,Variable Boilers_Boiler1_Drum_LevelIndicator_Output_InstrumentRange,1263,Variable Boilers_Boiler1_Drum_LevelIndicator_Output_EngineeringUnits,1264,Variable Boilers_Boiler1_OutputPipe,1265,Object Boilers_Boiler1_OutputPipe_FlowTransmitter2,1266,Object Boilers_Boiler1_OutputPipe_FlowTransmitter2_Output,1267,Variable Boilers_Boiler1_OutputPipe_FlowTransmitter2_Output_Definition,1268,Variable Boilers_Boiler1_OutputPipe_FlowTransmitter2_Output_ValuePrecision,1269,Variable Boilers_Boiler1_OutputPipe_FlowTransmitter2_Output_EURange,1270,Variable Boilers_Boiler1_OutputPipe_FlowTransmitter2_Output_InstrumentRange,1271,Variable Boilers_Boiler1_OutputPipe_FlowTransmitter2_Output_EngineeringUnits,1272,Variable Boilers_Boiler1_FlowController,1273,Object Boilers_Boiler1_FlowController_Measurement,1274,Variable Boilers_Boiler1_FlowController_SetPoint,1275,Variable Boilers_Boiler1_FlowController_ControlOut,1276,Variable Boilers_Boiler1_LevelController,1277,Object Boilers_Boiler1_LevelController_Measurement,1278,Variable Boilers_Boiler1_LevelController_SetPoint,1279,Variable Boilers_Boiler1_LevelController_ControlOut,1280,Variable Boilers_Boiler1_CustomController,1281,Object Boilers_Boiler1_CustomController_Input1,1282,Variable Boilers_Boiler1_CustomController_Input2,1283,Variable Boilers_Boiler1_CustomController_Input3,1284,Variable Boilers_Boiler1_CustomController_ControlOut,1285,Variable Boilers_Boiler1_CustomController_DescriptionX,1286,Variable Boilers_Boiler1_Simulation,1287,Object Boilers_Boiler1_Simulation_CurrentState,1288,Variable Boilers_Boiler1_Simulation_CurrentState_Id,1289,Variable Boilers_Boiler1_Simulation_CurrentState_Name,1290,Variable Boilers_Boiler1_Simulation_CurrentState_Number,1291,Variable Boilers_Boiler1_Simulation_CurrentState_EffectiveDisplayName,1292,Variable Boilers_Boiler1_Simulation_LastTransition,1293,Variable Boilers_Boiler1_Simulation_LastTransition_Id,1294,Variable Boilers_Boiler1_Simulation_LastTransition_Name,1295,Variable Boilers_Boiler1_Simulation_LastTransition_Number,1296,Variable Boilers_Boiler1_Simulation_LastTransition_TransitionTime,1297,Variable Boilers_Boiler1_Simulation_Deletable,1299,Variable Boilers_Boiler1_Simulation_AutoDelete,1300,Variable Boilers_Boiler1_Simulation_RecycleCount,1301,Variable Boilers_Boiler1_Simulation_FinalResultData,1316,Object Boilers_Boiler1_Simulation_UpdateRate,1348,Variable BoilerStateMachineType_LastTransition_EffectiveTransitionTime,1349,Variable BoilerType_Simulation_LastTransition_EffectiveTransitionTime,1350,Variable Boilers_Boiler1_Simulation_LastTransition_EffectiveTransitionTime,1351,Variable BoilerStateMachineType_AvailableStates,15001,Variable BoilerStateMachineType_AvailableTransitions,15002,Variable BoilerType_Simulation_AvailableStates,15005,Variable BoilerType_Simulation_AvailableTransitions,15006,Variable Boilers_Boiler1_Simulation_AvailableStates,15009,Variable Boilers_Boiler1_Simulation_AvailableTransitions,15010,Variable BoilerType_Simulation_Start,15013,Method BoilerType_Simulation_Suspend,15014,Method BoilerType_Simulation_Resume,15015,Method BoilerType_Simulation_Halt,15016,Method BoilerType_Simulation_Reset,15017,Method Boilers_Boiler1_Simulation_Start,15018,Method Boilers_Boiler1_Simulation_Suspend,15019,Method Boilers_Boiler1_Simulation_Resume,15020,Method Boilers_Boiler1_Simulation_Halt,15021,Method Boilers_Boiler1_Simulation_Reset,15022,Method BoilerStateMachineType_ProgramDiagnostic,15023,Variable BoilerStateMachineType_ProgramDiagnostic_CreateSessionId,15024,Variable BoilerStateMachineType_ProgramDiagnostic_CreateClientName,15025,Variable BoilerStateMachineType_ProgramDiagnostic_InvocationCreationTime,15026,Variable BoilerStateMachineType_ProgramDiagnostic_LastTransitionTime,15027,Variable BoilerStateMachineType_ProgramDiagnostic_LastMethodCall,15028,Variable BoilerStateMachineType_ProgramDiagnostic_LastMethodSessionId,15029,Variable BoilerStateMachineType_ProgramDiagnostic_LastMethodInputArguments,15030,Variable BoilerStateMachineType_ProgramDiagnostic_LastMethodOutputArguments,15031,Variable BoilerStateMachineType_ProgramDiagnostic_LastMethodInputValues,15032,Variable BoilerStateMachineType_ProgramDiagnostic_LastMethodOutputValues,15033,Variable BoilerStateMachineType_ProgramDiagnostic_LastMethodCallTime,15034,Variable BoilerStateMachineType_ProgramDiagnostic_LastMethodReturnStatus,15035,Variable BoilerType_Simulation_ProgramDiagnostic,15036,Variable BoilerType_Simulation_ProgramDiagnostic_CreateSessionId,15037,Variable BoilerType_Simulation_ProgramDiagnostic_CreateClientName,15038,Variable BoilerType_Simulation_ProgramDiagnostic_InvocationCreationTime,15039,Variable BoilerType_Simulation_ProgramDiagnostic_LastTransitionTime,15040,Variable BoilerType_Simulation_ProgramDiagnostic_LastMethodCall,15041,Variable BoilerType_Simulation_ProgramDiagnostic_LastMethodSessionId,15042,Variable BoilerType_Simulation_ProgramDiagnostic_LastMethodInputArguments,15043,Variable BoilerType_Simulation_ProgramDiagnostic_LastMethodOutputArguments,15044,Variable BoilerType_Simulation_ProgramDiagnostic_LastMethodInputValues,15045,Variable BoilerType_Simulation_ProgramDiagnostic_LastMethodOutputValues,15046,Variable BoilerType_Simulation_ProgramDiagnostic_LastMethodCallTime,15047,Variable BoilerType_Simulation_ProgramDiagnostic_LastMethodReturnStatus,15048,Variable Boilers_Boiler1_Simulation_ProgramDiagnostic,15049,Variable Boilers_Boiler1_Simulation_ProgramDiagnostic_CreateSessionId,15050,Variable Boilers_Boiler1_Simulation_ProgramDiagnostic_CreateClientName,15051,Variable Boilers_Boiler1_Simulation_ProgramDiagnostic_InvocationCreationTime,15052,Variable Boilers_Boiler1_Simulation_ProgramDiagnostic_LastTransitionTime,15053,Variable Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodCall,15054,Variable Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodSessionId,15055,Variable Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodInputArguments,15056,Variable Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodOutputArguments,15057,Variable Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodInputValues,15058,Variable Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodOutputValues,15059,Variable Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodCallTime,15060,Variable Boilers_Boiler1_Simulation_ProgramDiagnostic_LastMethodReturnStatus,15061,Variable ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Boiler/Design/BoilerDesign.xml ================================================  http://opcfoundation.org/UA/ http://opcfoundation.org/UA/Boiler/ A reference that indicates a flow between two objects. FlowFrom A reference that indicates a high temperature flow between two objects. HotFlowFrom A reference that indicates an electrical signal between two variables. SignalFrom A generic PID controller A generic sensor that read a process value. Represents a piece of equipment that causes some action to occur. A custom PID controller with 3 inputs Description An actuator that controls the flow through a pipe. A controller for the level of a fluid in a drum. A controller for the flow of a fluid through a pipe. A sensor that reports the level of a liquid in a tank. A sensor that reports the flow of a liquid through a pipe. A program that produces simulated values for a running boiler. The rate at which the simulation runs. Causes the Program to transition from the Ready state to the Running state. Causes the Program to transition from the Running state to the Suspended state. Causes the Program to transition from the Suspended state to the Running state. Causes the Program to transition from the Ready, Running or Suspended state to the Halted state. Causes the Program to transition from the Halted state to the Ready state. FTX001 ValveX001 ua:HasNotifier BoilerInputPipeType_FlowTransmitter1 LIX001 ua:HasNotifier BoilerDrumType_LevelIndicator FTX002 ua:HasNotifier BoilerOutputPipeType_FlowTransmitter2 A boiler used to produce steam for a turbine. PipeX001 FTX001 ValveX001 FlowTo BoilerType_Drum DrumX001 LIX001 HotFlowTo BoilerType_OutputPipe PipeX002 FTX002 FCX001 SignalTo BoilerType_InputPipe_FlowTransmitter1_Output SignalTo BoilerType_InputPipe_Valve_Input LCX001 SignalTo BoilerType_Drum_LevelIndicator_Output SignalTo BoilerType_CustomController_Input1 CCX001 SignalTo BoilerType_InputPipe_FlowTransmitter1_Output SignalTo BoilerType_OutputPipe_FlowTransmitter2_Output SignalTo BoilerType_FlowController_SetPoint ua:HasNotifier BoilerType_InputPipe ua:HasNotifier BoilerType_Drum ua:HasNotifier BoilerType_OutputPipe ua:HasEventSource BoilerType_Simulation Boiler #1 Pipe1001 Drum1001 Pipe1002 FC1001 LC1001 CC1001 ua:HasNotifier Boilers_Boiler1 ua:Organizes ua:ObjectsFolder ua:HasNotifier ua:Server ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/BuildDesigns.bat ================================================ @echo off setlocal pushd Boiler\Design set design=BoilerDesign echo Building %design% Opc.Ua.ModelCompiler.exe compile -version v104 -d2 "%design%.xml" -cg "%design%.csv" -o2 "." popd pushd HistoricalEvents\Design set design=ModelDesign echo Building %design% Opc.Ua.ModelCompiler.exe compile -version v104 -d2 "%design%.xml" -cg "%design%.csv" -o2 "." popd pushd MemoryBuffer\Design set design=MemoryBufferDesign echo Building %design% Opc.Ua.ModelCompiler.exe compile -version v104 -d2 "%design%.xml" -cg "%design%.csv" -o2 "." popd pushd SimpleEvents\Design set design=ModelDesign echo Building %design% Opc.Ua.ModelCompiler.exe compile -version v104 -d2 "%design%.xml" -cg "%design%.csv" -o2 "." popd pushd TestData\Design set design=TestDataDesign echo Building %design% Opc.Ua.ModelCompiler.exe compile -version v104 -d2 "%design%.xml" -cg "%design%.csv" -o2 "." popd pushd Views\Design set design=ModelDesign echo Building %design% Opc.Ua.ModelCompiler.exe compile -version v104 -d2 "%design%.xml" -cg "%design%.csv" -o2 "." popd pushd Views\Design set design=OperationsDesign echo Building %design% Opc.Ua.ModelCompiler.exe compile -version v104 -d2 "%design%.xml" -cg "%design%.csv" -o2 "." popd pushd Views\Design set design=EngineeringDesign echo Building %design% Opc.Ua.ModelCompiler.exe compile -version v104 -d2 "%design%.xml" -cg "%design%.csv" -o2 "." popd pushd Vehicles\Design set design=ModelDesign1 echo Building %design% Opc.Ua.ModelCompiler.exe compile -version v104 -d2 "%design%.xml" -cg "%design%.csv" -o2 "." popd pushd Vehicles\Design set design=ModelDesign2 echo Building %design% Opc.Ua.ModelCompiler.exe compile -version v104 -d2 "%design%.xml" -cg "%design%.csv" -o2 "." popd pushd Plc\Design set design=ModelDesign echo Building %design% Opc.Ua.ModelCompiler.exe compile -version v104 -d2 "%design%.xml" -cg "%design%.csv" -o2 "." popd ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/BuildNodesets.bat ================================================ @echo off setlocal pushd Isa95Jobs echo Building %design% Opc.Ua.ModelCompiler.exe compile-nodesets -input "Nodesets" -o2 "Design" -uri http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/ popd ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/HistoricalEvents/Design/HistoricalEvents.Classes.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; using System; using System.Collections.Generic; namespace HistoricalEvents { #region WellTestReportState Class #if (!OPCUA_EXCLUDE_WellTestReportState) /// /// Stores an instance of the WellTestReportType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class WellTestReportState : BaseEventState { #region Constructors /// /// Initializes the type with its default attribute values. /// public WellTestReportState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(HistoricalEvents.ObjectTypes.WellTestReportType, HistoricalEvents.Namespaces.HistoricalEvents, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACkAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvSGlzdG9yaWNhbEV2ZW50c/////8EYIACAQAA" + "AAEAGgAAAFdlbGxUZXN0UmVwb3J0VHlwZUluc3RhbmNlAQH7AAEB+wD7AAAA/////wwAAAAVYIkKAgAA" + "AAAABwAAAEV2ZW50SWQBAfwAAC4ARPwAAAAAD/////8BAf////8AAAAAFWCJCgIAAAAAAAkAAABFdmVu" + "dFR5cGUBAf0AAC4ARP0AAAAAEf////8BAf////8AAAAAFWCJCgIAAAAAAAoAAABTb3VyY2VOb2RlAQH+" + "AAAuAET+AAAAABH/////AQH/////AAAAABVgiQoCAAAAAAAKAAAAU291cmNlTmFtZQEB/wAALgBE/wAA" + "AAAM/////wEB/////wAAAAAVYIkKAgAAAAAABAAAAFRpbWUBAQABAC4ARAABAAABACYB/////wEB////" + "/wAAAAAVYIkKAgAAAAAACwAAAFJlY2VpdmVUaW1lAQEBAQAuAEQBAQAAAQAmAf////8BAf////8AAAAA" + "FWCJCgIAAAAAAAcAAABNZXNzYWdlAQEDAQAuAEQDAQAAABX/////AQH/////AAAAABVgiQoCAAAAAAAI" + "AAAAU2V2ZXJpdHkBAQQBAC4ARAQBAAAABf////8BAf////8AAAAANWCJCgIAAAABAAgAAABOYW1lV2Vs" + "bAEBBQEDAAAAAEQAAABIdW1hbiByZWNvZ25pemFibGUgY29udGV4dCBmb3IgdGhlIHdlbGwgdGhhdCBj" + "b250YWlucyB0aGUgd2VsbCB0ZXN0LgAuAEQFAQAAAAz/////AQH/////AAAAADVgiQoCAAAAAQAHAAAA" + "VWlkV2VsbAEBBgEDAAAAAHMAAABVbmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIHdlbGwuIFRoaXMgdW5p" + "cXVlbHkgcmVwcmVzZW50cyB0aGUgd2VsbCByZWZlcmVuY2VkIGJ5IHRoZSAocG9zc2libHkgbm9uLXVu" + "aXF1ZSkgTmFtZVdlbGwuAC4ARAYBAAAADP////8BAf////8AAAAANWCJCgIAAAABAAgAAABUZXN0RGF0" + "ZQEBBwEDAAAAABsAAABUaGUgZGF0ZS10aW1lIG9mIHdlbGwgdGVzdC4ALgBEBwEAAAAN/////wEB////" + "/wAAAAA1YIkKAgAAAAEACgAAAFRlc3RSZWFzb24BAQgBAwAAAAA6AAAAVGhlIHJlYXNvbiBmb3IgdGhl" + "IHdlbGwgdGVzdDogaW5pdGlhbCwgcGVyaW9kaWMsIHJldmlzaW9uLgAuAEQIAQAAAAz/////AQH/////" + "AAAAAA=="; #endregion #endif #endregion #region Public Properties /// public PropertyState NameWell { get { return m_nameWell; } set { if (!Object.ReferenceEquals(m_nameWell, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_nameWell = value; } } /// public PropertyState UidWell { get { return m_uidWell; } set { if (!Object.ReferenceEquals(m_uidWell, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_uidWell = value; } } /// public PropertyState TestDate { get { return m_testDate; } set { if (!Object.ReferenceEquals(m_testDate, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_testDate = value; } } /// public PropertyState TestReason { get { return m_testReason; } set { if (!Object.ReferenceEquals(m_testReason, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_testReason = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_nameWell != null) { children.Add(m_nameWell); } if (m_uidWell != null) { children.Add(m_uidWell); } if (m_testDate != null) { children.Add(m_testDate); } if (m_testReason != null) { children.Add(m_testReason); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case HistoricalEvents.BrowseNames.NameWell: { if (createOrReplace) { if (NameWell == null) { if (replacement == null) { NameWell = new PropertyState(this); } else { NameWell = (PropertyState)replacement; } } } instance = NameWell; break; } case HistoricalEvents.BrowseNames.UidWell: { if (createOrReplace) { if (UidWell == null) { if (replacement == null) { UidWell = new PropertyState(this); } else { UidWell = (PropertyState)replacement; } } } instance = UidWell; break; } case HistoricalEvents.BrowseNames.TestDate: { if (createOrReplace) { if (TestDate == null) { if (replacement == null) { TestDate = new PropertyState(this); } else { TestDate = (PropertyState)replacement; } } } instance = TestDate; break; } case HistoricalEvents.BrowseNames.TestReason: { if (createOrReplace) { if (TestReason == null) { if (replacement == null) { TestReason = new PropertyState(this); } else { TestReason = (PropertyState)replacement; } } } instance = TestReason; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private PropertyState m_nameWell; private PropertyState m_uidWell; private PropertyState m_testDate; private PropertyState m_testReason; #endregion } #endif #endregion #region FluidLevelTestReportState Class #if (!OPCUA_EXCLUDE_FluidLevelTestReportState) /// /// Stores an instance of the FluidLevelTestReportType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class FluidLevelTestReportState : WellTestReportState { #region Constructors /// /// Initializes the type with its default attribute values. /// public FluidLevelTestReportState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(HistoricalEvents.ObjectTypes.FluidLevelTestReportType, HistoricalEvents.Namespaces.HistoricalEvents, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACkAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvSGlzdG9yaWNhbEV2ZW50c/////8EYIACAQAA" + "AAEAIAAAAEZsdWlkTGV2ZWxUZXN0UmVwb3J0VHlwZUluc3RhbmNlAQEJAQEBCQEJAQAA/////w4AAAAV" + "YIkKAgAAAAAABwAAAEV2ZW50SWQBAQoBAC4ARAoBAAAAD/////8BAf////8AAAAAFWCJCgIAAAAAAAkA" + "AABFdmVudFR5cGUBAQsBAC4ARAsBAAAAEf////8BAf////8AAAAAFWCJCgIAAAAAAAoAAABTb3VyY2VO" + "b2RlAQEMAQAuAEQMAQAAABH/////AQH/////AAAAABVgiQoCAAAAAAAKAAAAU291cmNlTmFtZQEBDQEA" + "LgBEDQEAAAAM/////wEB/////wAAAAAVYIkKAgAAAAAABAAAAFRpbWUBAQ4BAC4ARA4BAAABACYB////" + "/wEB/////wAAAAAVYIkKAgAAAAAACwAAAFJlY2VpdmVUaW1lAQEPAQAuAEQPAQAAAQAmAf////8BAf//" + "//8AAAAAFWCJCgIAAAAAAAcAAABNZXNzYWdlAQERAQAuAEQRAQAAABX/////AQH/////AAAAABVgiQoC" + "AAAAAAAIAAAAU2V2ZXJpdHkBARIBAC4ARBIBAAAABf////8BAf////8AAAAANWCJCgIAAAABAAgAAABO" + "YW1lV2VsbAEBEwEDAAAAAEQAAABIdW1hbiByZWNvZ25pemFibGUgY29udGV4dCBmb3IgdGhlIHdlbGwg" + "dGhhdCBjb250YWlucyB0aGUgd2VsbCB0ZXN0LgAuAEQTAQAAAAz/////AQH/////AAAAADVgiQoCAAAA" + "AQAHAAAAVWlkV2VsbAEBFAEDAAAAAHMAAABVbmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIHdlbGwuIFRo" + "aXMgdW5pcXVlbHkgcmVwcmVzZW50cyB0aGUgd2VsbCByZWZlcmVuY2VkIGJ5IHRoZSAocG9zc2libHkg" + "bm9uLXVuaXF1ZSkgTmFtZVdlbGwuAC4ARBQBAAAADP////8BAf////8AAAAANWCJCgIAAAABAAgAAABU" + "ZXN0RGF0ZQEBFQEDAAAAABsAAABUaGUgZGF0ZS10aW1lIG9mIHdlbGwgdGVzdC4ALgBEFQEAAAAN////" + "/wEB/////wAAAAA1YIkKAgAAAAEACgAAAFRlc3RSZWFzb24BARYBAwAAAAA6AAAAVGhlIHJlYXNvbiBm" + "b3IgdGhlIHdlbGwgdGVzdDogaW5pdGlhbCwgcGVyaW9kaWMsIHJldmlzaW9uLgAuAEQWAQAAAAz/////" + "AQH/////AAAAADVgiQoCAAAAAQAKAAAARmx1aWRMZXZlbAEBFwEDAAAAAGIAAABUaGUgZmx1aWQgbGV2" + "ZWwgYWNoaWV2ZWQgaW4gdGhlIHdlbGwuIFRoZSB2YWx1ZSBpcyBnaXZlbiBhcyBsZW5ndGggdW5pdHMg" + "ZnJvbSB0aGUgdG9wIG9mIHRoZSB3ZWxsLgAvAQBACRcBAAAAC/////8BAf////8CAAAAFWCJCgIAAAAA" + "AAcAAABFVVJhbmdlAQEwAQAuAEQwAQAAAQB0A/////8BAf////8AAAAAFWCJCgIAAAAAABAAAABFbmdp" + "bmVlcmluZ1VuaXRzAQEaAQAuAEQaAQAAAQB3A/////8BAf////8AAAAANWCJCgIAAAABAAgAAABUZXN0" + "ZWRCeQEBGwEDAAAAAEsAAABUaGUgYnVzaW5lc3MgYXNzb2NpYXRlIHRoYXQgY29uZHVjdGVkIHRoZSB0" + "ZXN0LiBUaGlzIGlzIGdlbmVyYWxseSBhIHBlcnNvbi4ALgBEGwEAAAAM/////wEB/////wAAAAA="; #endregion #endif #endregion #region Public Properties /// public AnalogItemState FluidLevel { get { return m_fluidLevel; } set { if (!Object.ReferenceEquals(m_fluidLevel, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_fluidLevel = value; } } /// public PropertyState TestedBy { get { return m_testedBy; } set { if (!Object.ReferenceEquals(m_testedBy, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_testedBy = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_fluidLevel != null) { children.Add(m_fluidLevel); } if (m_testedBy != null) { children.Add(m_testedBy); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case HistoricalEvents.BrowseNames.FluidLevel: { if (createOrReplace) { if (FluidLevel == null) { if (replacement == null) { FluidLevel = new AnalogItemState(this); } else { FluidLevel = (AnalogItemState)replacement; } } } instance = FluidLevel; break; } case HistoricalEvents.BrowseNames.TestedBy: { if (createOrReplace) { if (TestedBy == null) { if (replacement == null) { TestedBy = new PropertyState(this); } else { TestedBy = (PropertyState)replacement; } } } instance = TestedBy; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private AnalogItemState m_fluidLevel; private PropertyState m_testedBy; #endregion } #endif #endregion #region InjectionTestReportState Class #if (!OPCUA_EXCLUDE_InjectionTestReportState) /// /// Stores an instance of the InjectionTestReportType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class InjectionTestReportState : WellTestReportState { #region Constructors /// /// Initializes the type with its default attribute values. /// public InjectionTestReportState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(HistoricalEvents.ObjectTypes.InjectionTestReportType, HistoricalEvents.Namespaces.HistoricalEvents, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACkAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvSGlzdG9yaWNhbEV2ZW50c/////8EYIACAQAA" + "AAEAHwAAAEluamVjdGlvblRlc3RSZXBvcnRUeXBlSW5zdGFuY2UBARwBAQEcARwBAAD/////DgAAABVg" + "iQoCAAAAAAAHAAAARXZlbnRJZAEBHQEALgBEHQEAAAAP/////wEB/////wAAAAAVYIkKAgAAAAAACQAA" + "AEV2ZW50VHlwZQEBHgEALgBEHgEAAAAR/////wEB/////wAAAAAVYIkKAgAAAAAACgAAAFNvdXJjZU5v" + "ZGUBAR8BAC4ARB8BAAAAEf////8BAf////8AAAAAFWCJCgIAAAAAAAoAAABTb3VyY2VOYW1lAQEgAQAu" + "AEQgAQAAAAz/////AQH/////AAAAABVgiQoCAAAAAAAEAAAAVGltZQEBIQEALgBEIQEAAAEAJgH/////" + "AQH/////AAAAABVgiQoCAAAAAAALAAAAUmVjZWl2ZVRpbWUBASIBAC4ARCIBAAABACYB/////wEB////" + "/wAAAAAVYIkKAgAAAAAABwAAAE1lc3NhZ2UBASQBAC4ARCQBAAAAFf////8BAf////8AAAAAFWCJCgIA" + "AAAAAAgAAABTZXZlcml0eQEBJQEALgBEJQEAAAAF/////wEB/////wAAAAA1YIkKAgAAAAEACAAAAE5h" + "bWVXZWxsAQEmAQMAAAAARAAAAEh1bWFuIHJlY29nbml6YWJsZSBjb250ZXh0IGZvciB0aGUgd2VsbCB0" + "aGF0IGNvbnRhaW5zIHRoZSB3ZWxsIHRlc3QuAC4ARCYBAAAADP////8BAf////8AAAAANWCJCgIAAAAB" + "AAcAAABVaWRXZWxsAQEnAQMAAAAAcwAAAFVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgd2VsbC4gVGhp" + "cyB1bmlxdWVseSByZXByZXNlbnRzIHRoZSB3ZWxsIHJlZmVyZW5jZWQgYnkgdGhlIChwb3NzaWJseSBu" + "b24tdW5pcXVlKSBOYW1lV2VsbC4ALgBEJwEAAAAM/////wEB/////wAAAAA1YIkKAgAAAAEACAAAAFRl" + "c3REYXRlAQEoAQMAAAAAGwAAAFRoZSBkYXRlLXRpbWUgb2Ygd2VsbCB0ZXN0LgAuAEQoAQAAAA3/////" + "AQH/////AAAAADVgiQoCAAAAAQAKAAAAVGVzdFJlYXNvbgEBKQEDAAAAADoAAABUaGUgcmVhc29uIGZv" + "ciB0aGUgd2VsbCB0ZXN0OiBpbml0aWFsLCBwZXJpb2RpYywgcmV2aXNpb24uAC4ARCkBAAAADP////8B" + "Af////8AAAAANWCJCgIAAAABAAwAAABUZXN0RHVyYXRpb24BASoBAwAAAAAsAAAAVGhlIHRpbWUgbGVu" + "Z3RoICh3aXRoIHVvbSkgb2YgdGhlIHdlbGwgdGVzdC4ALwEAQAkqAQAAAAv/////AQH/////AgAAABVg" + "iQoCAAAAAAAHAAAARVVSYW5nZQEBMgEALgBEMgEAAAEAdAP/////AQH/////AAAAABVgiQoCAAAAAAAQ" + "AAAARW5naW5lZXJpbmdVbml0cwEBLQEALgBELQEAAAEAdwP/////AQH/////AAAAADVgiQoCAAAAAQAN" + "AAAASW5qZWN0ZWRGbHVpZAEBLgEDAAAAACMAAABUaGUgZmx1aWQgdGhhdCBpcyBiZWluZyBpbmplY3Rl" + "ZC4gLgAuAEQuAQAAAAz/////AQH/////AAAAAA=="; #endregion #endif #endregion #region Public Properties /// public AnalogItemState TestDuration { get { return m_testDuration; } set { if (!Object.ReferenceEquals(m_testDuration, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_testDuration = value; } } /// public PropertyState InjectedFluid { get { return m_injectedFluid; } set { if (!Object.ReferenceEquals(m_injectedFluid, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_injectedFluid = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_testDuration != null) { children.Add(m_testDuration); } if (m_injectedFluid != null) { children.Add(m_injectedFluid); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case HistoricalEvents.BrowseNames.TestDuration: { if (createOrReplace) { if (TestDuration == null) { if (replacement == null) { TestDuration = new AnalogItemState(this); } else { TestDuration = (AnalogItemState)replacement; } } } instance = TestDuration; break; } case HistoricalEvents.BrowseNames.InjectedFluid: { if (createOrReplace) { if (InjectedFluid == null) { if (replacement == null) { InjectedFluid = new PropertyState(this); } else { InjectedFluid = (PropertyState)replacement; } } } instance = InjectedFluid; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private AnalogItemState m_testDuration; private PropertyState m_injectedFluid; #endregion } #endif #endregion #region WellState Class #if (!OPCUA_EXCLUDE_WellState) /// /// Stores an instance of the WellType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class WellState : BaseObjectState { #region Constructors /// /// Initializes the type with its default attribute values. /// public WellState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(HistoricalEvents.ObjectTypes.WellType, HistoricalEvents.Namespaces.HistoricalEvents, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACkAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvSGlzdG9yaWNhbEV2ZW50c/////8EYIACAQAA" + "AAEAEAAAAFdlbGxUeXBlSW5zdGFuY2UBATQBAQE0ATQBAAD/////AAAAAA=="; #endregion #endif #endregion #region Public Properties #endregion #region Overridden Methods #endregion #region Private Fields #endregion } #endif #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/HistoricalEvents/Design/HistoricalEvents.Constants.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; namespace HistoricalEvents { #region Object Identifiers /// /// A class that declares constants for all Objects in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Objects { /// /// The identifier for the Plaforms Object. /// public const uint Plaforms = 303; } #endregion #region ObjectType Identifiers /// /// A class that declares constants for all ObjectTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectTypes { /// /// The identifier for the WellTestReportType ObjectType. /// public const uint WellTestReportType = 251; /// /// The identifier for the FluidLevelTestReportType ObjectType. /// public const uint FluidLevelTestReportType = 265; /// /// The identifier for the InjectionTestReportType ObjectType. /// public const uint InjectionTestReportType = 284; /// /// The identifier for the WellType ObjectType. /// public const uint WellType = 308; } #endregion #region Variable Identifiers /// /// A class that declares constants for all Variables in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Variables { /// /// The identifier for the WellTestReportType_NameWell Variable. /// public const uint WellTestReportType_NameWell = 261; /// /// The identifier for the WellTestReportType_UidWell Variable. /// public const uint WellTestReportType_UidWell = 262; /// /// The identifier for the WellTestReportType_TestDate Variable. /// public const uint WellTestReportType_TestDate = 263; /// /// The identifier for the WellTestReportType_TestReason Variable. /// public const uint WellTestReportType_TestReason = 264; /// /// The identifier for the FluidLevelTestReportType_FluidLevel Variable. /// public const uint FluidLevelTestReportType_FluidLevel = 279; /// /// The identifier for the FluidLevelTestReportType_FluidLevel_EURange Variable. /// public const uint FluidLevelTestReportType_FluidLevel_EURange = 304; /// /// The identifier for the FluidLevelTestReportType_FluidLevel_EngineeringUnits Variable. /// public const uint FluidLevelTestReportType_FluidLevel_EngineeringUnits = 282; /// /// The identifier for the FluidLevelTestReportType_TestedBy Variable. /// public const uint FluidLevelTestReportType_TestedBy = 283; /// /// The identifier for the InjectionTestReportType_TestDuration Variable. /// public const uint InjectionTestReportType_TestDuration = 298; /// /// The identifier for the InjectionTestReportType_TestDuration_EURange Variable. /// public const uint InjectionTestReportType_TestDuration_EURange = 306; /// /// The identifier for the InjectionTestReportType_TestDuration_EngineeringUnits Variable. /// public const uint InjectionTestReportType_TestDuration_EngineeringUnits = 301; /// /// The identifier for the InjectionTestReportType_InjectedFluid Variable. /// public const uint InjectionTestReportType_InjectedFluid = 302; } #endregion #region Object Node Identifiers /// /// A class that declares constants for all Objects in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectIds { /// /// The identifier for the Plaforms Object. /// public static readonly ExpandedNodeId Plaforms = new ExpandedNodeId(HistoricalEvents.Objects.Plaforms, HistoricalEvents.Namespaces.HistoricalEvents); } #endregion #region ObjectType Node Identifiers /// /// A class that declares constants for all ObjectTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectTypeIds { /// /// The identifier for the WellTestReportType ObjectType. /// public static readonly ExpandedNodeId WellTestReportType = new ExpandedNodeId(HistoricalEvents.ObjectTypes.WellTestReportType, HistoricalEvents.Namespaces.HistoricalEvents); /// /// The identifier for the FluidLevelTestReportType ObjectType. /// public static readonly ExpandedNodeId FluidLevelTestReportType = new ExpandedNodeId(HistoricalEvents.ObjectTypes.FluidLevelTestReportType, HistoricalEvents.Namespaces.HistoricalEvents); /// /// The identifier for the InjectionTestReportType ObjectType. /// public static readonly ExpandedNodeId InjectionTestReportType = new ExpandedNodeId(HistoricalEvents.ObjectTypes.InjectionTestReportType, HistoricalEvents.Namespaces.HistoricalEvents); /// /// The identifier for the WellType ObjectType. /// public static readonly ExpandedNodeId WellType = new ExpandedNodeId(HistoricalEvents.ObjectTypes.WellType, HistoricalEvents.Namespaces.HistoricalEvents); } #endregion #region Variable Node Identifiers /// /// A class that declares constants for all Variables in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class VariableIds { /// /// The identifier for the WellTestReportType_NameWell Variable. /// public static readonly ExpandedNodeId WellTestReportType_NameWell = new ExpandedNodeId(HistoricalEvents.Variables.WellTestReportType_NameWell, HistoricalEvents.Namespaces.HistoricalEvents); /// /// The identifier for the WellTestReportType_UidWell Variable. /// public static readonly ExpandedNodeId WellTestReportType_UidWell = new ExpandedNodeId(HistoricalEvents.Variables.WellTestReportType_UidWell, HistoricalEvents.Namespaces.HistoricalEvents); /// /// The identifier for the WellTestReportType_TestDate Variable. /// public static readonly ExpandedNodeId WellTestReportType_TestDate = new ExpandedNodeId(HistoricalEvents.Variables.WellTestReportType_TestDate, HistoricalEvents.Namespaces.HistoricalEvents); /// /// The identifier for the WellTestReportType_TestReason Variable. /// public static readonly ExpandedNodeId WellTestReportType_TestReason = new ExpandedNodeId(HistoricalEvents.Variables.WellTestReportType_TestReason, HistoricalEvents.Namespaces.HistoricalEvents); /// /// The identifier for the FluidLevelTestReportType_FluidLevel Variable. /// public static readonly ExpandedNodeId FluidLevelTestReportType_FluidLevel = new ExpandedNodeId(HistoricalEvents.Variables.FluidLevelTestReportType_FluidLevel, HistoricalEvents.Namespaces.HistoricalEvents); /// /// The identifier for the FluidLevelTestReportType_FluidLevel_EURange Variable. /// public static readonly ExpandedNodeId FluidLevelTestReportType_FluidLevel_EURange = new ExpandedNodeId(HistoricalEvents.Variables.FluidLevelTestReportType_FluidLevel_EURange, HistoricalEvents.Namespaces.HistoricalEvents); /// /// The identifier for the FluidLevelTestReportType_FluidLevel_EngineeringUnits Variable. /// public static readonly ExpandedNodeId FluidLevelTestReportType_FluidLevel_EngineeringUnits = new ExpandedNodeId(HistoricalEvents.Variables.FluidLevelTestReportType_FluidLevel_EngineeringUnits, HistoricalEvents.Namespaces.HistoricalEvents); /// /// The identifier for the FluidLevelTestReportType_TestedBy Variable. /// public static readonly ExpandedNodeId FluidLevelTestReportType_TestedBy = new ExpandedNodeId(HistoricalEvents.Variables.FluidLevelTestReportType_TestedBy, HistoricalEvents.Namespaces.HistoricalEvents); /// /// The identifier for the InjectionTestReportType_TestDuration Variable. /// public static readonly ExpandedNodeId InjectionTestReportType_TestDuration = new ExpandedNodeId(HistoricalEvents.Variables.InjectionTestReportType_TestDuration, HistoricalEvents.Namespaces.HistoricalEvents); /// /// The identifier for the InjectionTestReportType_TestDuration_EURange Variable. /// public static readonly ExpandedNodeId InjectionTestReportType_TestDuration_EURange = new ExpandedNodeId(HistoricalEvents.Variables.InjectionTestReportType_TestDuration_EURange, HistoricalEvents.Namespaces.HistoricalEvents); /// /// The identifier for the InjectionTestReportType_TestDuration_EngineeringUnits Variable. /// public static readonly ExpandedNodeId InjectionTestReportType_TestDuration_EngineeringUnits = new ExpandedNodeId(HistoricalEvents.Variables.InjectionTestReportType_TestDuration_EngineeringUnits, HistoricalEvents.Namespaces.HistoricalEvents); /// /// The identifier for the InjectionTestReportType_InjectedFluid Variable. /// public static readonly ExpandedNodeId InjectionTestReportType_InjectedFluid = new ExpandedNodeId(HistoricalEvents.Variables.InjectionTestReportType_InjectedFluid, HistoricalEvents.Namespaces.HistoricalEvents); } #endregion #region BrowseName Declarations /// /// Declares all of the BrowseNames used in the Model Design. /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class BrowseNames { /// /// The BrowseName for the FluidLevel component. /// public const string FluidLevel = "FluidLevel"; /// /// The BrowseName for the FluidLevelTestReportType component. /// public const string FluidLevelTestReportType = "FluidLevelTestReportType"; /// /// The BrowseName for the InjectedFluid component. /// public const string InjectedFluid = "InjectedFluid"; /// /// The BrowseName for the InjectionTestReportType component. /// public const string InjectionTestReportType = "InjectionTestReportType"; /// /// The BrowseName for the NameWell component. /// public const string NameWell = "NameWell"; /// /// The BrowseName for the Plaforms component. /// public const string Plaforms = "Plaforms"; /// /// The BrowseName for the TestDate component. /// public const string TestDate = "TestDate"; /// /// The BrowseName for the TestDuration component. /// public const string TestDuration = "TestDuration"; /// /// The BrowseName for the TestedBy component. /// public const string TestedBy = "TestedBy"; /// /// The BrowseName for the TestReason component. /// public const string TestReason = "TestReason"; /// /// The BrowseName for the UidWell component. /// public const string UidWell = "UidWell"; /// /// The BrowseName for the WellTestReportType component. /// public const string WellTestReportType = "WellTestReportType"; /// /// The BrowseName for the WellType component. /// public const string WellType = "WellType"; } #endregion #region Namespace Declarations /// /// Defines constants for all namespaces referenced by the model design. /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Namespaces { /// /// The URI for the OpcUa namespace (.NET code namespace is 'Opc.Ua'). /// public const string OpcUa = "http://opcfoundation.org/UA/"; /// /// The URI for the OpcUaXsd namespace (.NET code namespace is 'Opc.Ua'). /// public const string OpcUaXsd = "http://opcfoundation.org/UA/2008/02/Types.xsd"; /// /// The URI for the HistoricalEvents namespace (.NET code namespace is 'HistoricalEvents'). /// public const string HistoricalEvents = "http://opcfoundation.org/HistoricalEvents"; } #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/HistoricalEvents/Design/HistoricalEvents.NodeIds.csv ================================================ FluidLevelTestReportType,265,ObjectType InjectionTestReportType,284,ObjectType Plaforms,303,Object WellTestReportType,251,ObjectType WellType,308,ObjectType ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/HistoricalEvents/Design/HistoricalEvents.NodeSet.xml ================================================  http://opcfoundation.org/UA/ http://opcfoundation.org/HistoricalEvents ns=1;i=251 ObjectType_8 1 WellTestReportType WellTestReportType A report containing the results of a well test. 0 0 0 i=45 true i=2041 i=46 false ns=1;i=261 i=46 false ns=1;i=262 i=46 false ns=1;i=263 i=46 false ns=1;i=264 i=45 false ns=1;i=265 i=45 false ns=1;i=284 false ns=1;i=261 Variable_2 1 NameWell NameWell Human recognizable context for the well that contains the well test. 0 0 0 i=46 true ns=1;i=251 i=40 false i=68 i=37 false i=78 i=12 -1 1 1 0 false 0 ns=1;i=262 Variable_2 1 UidWell UidWell Unique identifier for the well. This uniquely represents the well referenced by the (possibly non-unique) NameWell. 0 0 0 i=46 true ns=1;i=251 i=40 false i=68 i=37 false i=78 i=12 -1 1 1 0 false 0 ns=1;i=263 Variable_2 1 TestDate TestDate The date-time of well test. 0 0 0 i=46 true ns=1;i=251 i=40 false i=68 i=37 false i=78 0001-01-01T00:00:00 i=13 -1 1 1 0 false 0 ns=1;i=264 Variable_2 1 TestReason TestReason The reason for the well test: initial, periodic, revision. 0 0 0 i=46 true ns=1;i=251 i=40 false i=68 i=37 false i=78 i=12 -1 1 1 0 false 0 ns=1;i=265 ObjectType_8 1 FluidLevelTestReportType FluidLevelTestReportType A report for a fluid level test. 0 0 0 i=45 true ns=1;i=251 i=47 false ns=1;i=279 i=46 false ns=1;i=283 false ns=1;i=279 Variable_2 1 FluidLevel FluidLevel The fluid level achieved in the well. The value is given as length units from the top of the well. 0 0 0 i=47 true ns=1;i=265 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=304 i=46 false ns=1;i=282 0 i=11 -1 1 1 0 false 0 ns=1;i=282 Variable_2 0 EngineeringUnits EngineeringUnits 0 0 0 i=46 true ns=1;i=279 i=40 false i=68 i=37 false i=80 i=887 -1 1 1 0 false 0 ns=1;i=283 Variable_2 1 TestedBy TestedBy The business associate that conducted the test. This is generally a person. 0 0 0 i=46 true ns=1;i=265 i=40 false i=68 i=37 false i=78 i=12 -1 1 1 0 false 0 ns=1;i=284 ObjectType_8 1 InjectionTestReportType InjectionTestReportType A report for a fluid level test. 0 0 0 i=45 true ns=1;i=251 i=47 false ns=1;i=298 i=46 false ns=1;i=302 false ns=1;i=298 Variable_2 1 TestDuration TestDuration The time length (with uom) of the well test. 0 0 0 i=47 true ns=1;i=284 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=306 i=46 false ns=1;i=301 0 i=11 -1 1 1 0 false 0 ns=1;i=301 Variable_2 0 EngineeringUnits EngineeringUnits 0 0 0 i=46 true ns=1;i=298 i=40 false i=68 i=37 false i=80 i=887 -1 1 1 0 false 0 ns=1;i=302 Variable_2 1 InjectedFluid InjectedFluid The fluid that is being injected. . 0 0 0 i=46 true ns=1;i=284 i=40 false i=68 i=37 false i=78 i=12 -1 1 1 0 false 0 ns=1;i=303 Object_1 1 Plaforms Plaforms 0 0 0 i=40 false i=61 i=35 true i=85 i=48 true i=2253 1 ns=1;i=304 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=279 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=306 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=298 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=308 ObjectType_8 1 WellType WellType A physical well. 0 0 0 i=45 true i=58 false ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/HistoricalEvents/Design/HistoricalEvents.NodeSet2.xml ================================================  http://opcfoundation.org/HistoricalEvents i=1 i=2 i=3 i=4 i=5 i=6 i=7 i=8 i=9 i=10 i=11 i=13 i=12 i=15 i=14 i=16 i=17 i=18 i=20 i=21 i=19 i=22 i=26 i=27 i=28 i=47 i=46 i=35 i=36 i=48 i=45 i=40 i=37 i=38 i=39 WellTestReportType A report containing the results of a well test. ns=1;i=261 ns=1;i=262 ns=1;i=263 ns=1;i=264 i=2041 NameWell Human recognizable context for the well that contains the well test. i=68 i=78 ns=1;i=251 UidWell Unique identifier for the well. This uniquely represents the well referenced by the (possibly non-unique) NameWell. i=68 i=78 ns=1;i=251 TestDate The date-time of well test. i=68 i=78 ns=1;i=251 TestReason The reason for the well test: initial, periodic, revision. i=68 i=78 ns=1;i=251 FluidLevelTestReportType A report for a fluid level test. ns=1;i=279 ns=1;i=283 ns=1;i=251 FluidLevel The fluid level achieved in the well. The value is given as length units from the top of the well. ns=1;i=304 ns=1;i=282 i=2368 i=78 ns=1;i=265 EURange i=68 i=78 ns=1;i=279 EngineeringUnits i=68 i=80 ns=1;i=279 TestedBy The business associate that conducted the test. This is generally a person. i=68 i=78 ns=1;i=265 InjectionTestReportType A report for a fluid level test. ns=1;i=298 ns=1;i=302 ns=1;i=251 TestDuration The time length (with uom) of the well test. ns=1;i=306 ns=1;i=301 i=2368 i=78 ns=1;i=284 EURange i=68 i=78 ns=1;i=298 EngineeringUnits i=68 i=80 ns=1;i=298 InjectedFluid The fluid that is being injected. . i=68 i=78 ns=1;i=284 WellType A physical well. i=58 Plaforms i=85 i=2253 i=61 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/HistoricalEvents/Design/HistoricalEvents.PredefinedNodes.xml ================================================  http://opcfoundation.org/HistoricalEvents ObjectType_8 ns=1;i=251 1 WellTestReportType A report containing the results of a well test. i=2041 Variable_2 ns=1;i=261 1 NameWell Human recognizable context for the well that contains the well test. i=46 i=68 i=78 261 i=12 -1 1 1 Variable_2 ns=1;i=262 1 UidWell Unique identifier for the well. This uniquely represents the well referenced by the (possibly non-unique) NameWell. i=46 i=68 i=78 262 i=12 -1 1 1 Variable_2 ns=1;i=263 1 TestDate The date-time of well test. i=46 i=68 i=78 263 i=13 -1 1 1 Variable_2 ns=1;i=264 1 TestReason The reason for the well test: initial, periodic, revision. i=46 i=68 i=78 264 i=12 -1 1 1 ObjectType_8 ns=1;i=265 1 FluidLevelTestReportType A report for a fluid level test. ns=1;i=251 Variable_2 ns=1;i=279 1 FluidLevel The fluid level achieved in the well. The value is given as length units from the top of the well. i=47 i=2368 i=78 279 i=11 -1 1 1 Variable_2 ns=1;i=304 0 EURange i=46 i=68 i=78 304 i=884 -1 1 1 Variable_2 ns=1;i=282 0 EngineeringUnits i=46 i=68 i=80 282 i=887 -1 1 1 Variable_2 ns=1;i=283 1 TestedBy The business associate that conducted the test. This is generally a person. i=46 i=68 i=78 283 i=12 -1 1 1 ObjectType_8 ns=1;i=284 1 InjectionTestReportType A report for a fluid level test. ns=1;i=251 Variable_2 ns=1;i=298 1 TestDuration The time length (with uom) of the well test. i=47 i=2368 i=78 298 i=11 -1 1 1 Variable_2 ns=1;i=306 0 EURange i=46 i=68 i=78 306 i=884 -1 1 1 Variable_2 ns=1;i=301 0 EngineeringUnits i=46 i=68 i=80 301 i=887 -1 1 1 Variable_2 ns=1;i=302 1 InjectedFluid The fluid that is being injected. . i=46 i=68 i=78 302 i=12 -1 1 1 ObjectType_8 ns=1;i=308 1 WellType A physical well. i=58 Object_1 ns=1;i=303 1 Plaforms i=47 i=61 303 1 i=35 true i=85 i=48 true i=2253 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/HistoricalEvents/Design/HistoricalEvents.Types.bsd ================================================ ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/HistoricalEvents/Design/HistoricalEvents.Types.xsd ================================================ ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/HistoricalEvents/Design/ModelDesign.csv ================================================ WellTestReportType,251,ObjectType WellTestReportType_EventId,252,Variable WellTestReportType_EventType,253,Variable WellTestReportType_SourceNode,254,Variable WellTestReportType_SourceName,255,Variable WellTestReportType_Time,256,Variable WellTestReportType_ReceiveTime,257,Variable WellTestReportType_LocalTime,258,Variable WellTestReportType_Message,259,Variable WellTestReportType_Severity,260,Variable WellTestReportType_NameWell,261,Variable WellTestReportType_UidWell,262,Variable WellTestReportType_TestDate,263,Variable WellTestReportType_TestReason,264,Variable FluidLevelTestReportType,265,ObjectType FluidLevelTestReportType_EventId,266,Variable FluidLevelTestReportType_EventType,267,Variable FluidLevelTestReportType_SourceNode,268,Variable FluidLevelTestReportType_SourceName,269,Variable FluidLevelTestReportType_Time,270,Variable FluidLevelTestReportType_ReceiveTime,271,Variable FluidLevelTestReportType_LocalTime,272,Variable FluidLevelTestReportType_Message,273,Variable FluidLevelTestReportType_Severity,274,Variable FluidLevelTestReportType_NameWell,275,Variable FluidLevelTestReportType_UidWell,276,Variable FluidLevelTestReportType_TestDate,277,Variable FluidLevelTestReportType_TestReason,278,Variable FluidLevelTestReportType_FluidLevel,279,Variable FluidLevelTestReportType_FluidLevel_Definition,280,Variable FluidLevelTestReportType_FluidLevel_ValuePrecision,281,Variable FluidLevelTestReportType_FluidLevel_EngineeringUnits,282,Variable FluidLevelTestReportType_TestedBy,283,Variable InjectionTestReportType,284,ObjectType InjectionTestReportType_EventId,285,Variable InjectionTestReportType_EventType,286,Variable InjectionTestReportType_SourceNode,287,Variable InjectionTestReportType_SourceName,288,Variable InjectionTestReportType_Time,289,Variable InjectionTestReportType_ReceiveTime,290,Variable InjectionTestReportType_LocalTime,291,Variable InjectionTestReportType_Message,292,Variable InjectionTestReportType_Severity,293,Variable InjectionTestReportType_NameWell,294,Variable InjectionTestReportType_UidWell,295,Variable InjectionTestReportType_TestDate,296,Variable InjectionTestReportType_TestReason,297,Variable InjectionTestReportType_TestDuration,298,Variable InjectionTestReportType_TestDuration_Definition,299,Variable InjectionTestReportType_TestDuration_ValuePrecision,300,Variable InjectionTestReportType_TestDuration_EngineeringUnits,301,Variable InjectionTestReportType_InjectedFluid,302,Variable Plaforms,303,Object FluidLevelTestReportType_FluidLevel_EURange,304,Variable FluidLevelTestReportType_FluidLevel_InstrumentRange,305,Variable InjectionTestReportType_TestDuration_EURange,306,Variable InjectionTestReportType_TestDuration_InstrumentRange,307,Variable WellType,308,ObjectType ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/HistoricalEvents/Design/ModelDesign.xml ================================================  http://opcfoundation.org/UA/ http://opcfoundation.org/HistoricalEvents A report containing the results of a well test. Human recognizable context for the well that contains the well test. Unique identifier for the well. This uniquely represents the well referenced by the (possibly non-unique) NameWell. The date-time of well test. The reason for the well test: initial, periodic, revision. A report for a fluid level test. The fluid level achieved in the well. The value is given as length units from the top of the well. The unit of measure for length. The business associate that conducted the test. This is generally a person. A report for a fluid level test. The time length (with uom) of the well test. The unit of measure for time. The fluid that is being injected. . A physical well. ua:Organizes ua:ObjectsFolder ua:HasNotifier ua:Server ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Isa95Jobs/Design/UAModel.ISA95_JOBCONTROL_V2.Classes.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2024 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; using System; using System.Collections.Generic; namespace UAModel.ISA95_JOBCONTROL_V2 { #region ISA95JobOrderStatusEventTypeState Class #if (!OPCUA_EXCLUDE_ISA95JobOrderStatusEventTypeState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class ISA95JobOrderStatusEventTypeState : BaseEventState { #region Constructors /// public ISA95JobOrderStatusEventTypeState(NodeState parent) : base(parent) { } /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(UAModel.ISA95_JOBCONTROL_V2.ObjectTypes.ISA95JobOrderStatusEventType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGCAAgEAAAABACQAAABJU0E5NUpvYk9yZGVyU3RhdHVzRXZlbnRUeXBlSW5zdGFuY2UBAe4DAQHuA+4D" + "AAAbAAAAACkBAQHrAwA2AQEBsRMANgEBAbITADYBAQGzEwA2AQEBtBMANgEBAbUTADYBAQG2EwA2AQEB" + "txMANgEBAbgTADYBAQG5EwA2AQEBuhMANgEBAbsTADYBAQHNEwA2AQEBzhMANgEBAc8TADYBAQHQEwA2" + "AQEB0RMANgEBAdITADYBAQHTEwA2AQEB1BMANgEBAdUTADYBAQHWEwA2AQEB1xMANgEBAdwTADYBAQHd" + "EwA2AQEB3hMANgEBAd8TCwAAABVgiQgCAAAAAAAHAAAARXZlbnRJZAEBAAAALgBEAA//////AQH/////" + "AAAAABVgiQgCAAAAAAAJAAAARXZlbnRUeXBlAQEAAAAuAEQAEf////8BAf////8AAAAAFWCJCAIAAAAA" + "AAoAAABTb3VyY2VOb2RlAQEAAAAuAEQAEf////8BAf////8AAAAAFWCJCAIAAAAAAAoAAABTb3VyY2VO" + "YW1lAQEAAAAuAEQADP////8BAf////8AAAAAFWCJCAIAAAAAAAQAAABUaW1lAQEAAAAuAEQBACYB////" + "/wEB/////wAAAAAVYIkIAgAAAAAACwAAAFJlY2VpdmVUaW1lAQEAAAAuAEQBACYB/////wEB/////wAA" + "AAAVYIkIAgAAAAAABwAAAE1lc3NhZ2UBAQAAAC4ARAAV/////wEB/////wAAAAAVYIkIAgAAAAAACAAA" + "AFNldmVyaXR5AQEAAAAuAEQABf////8BAf////8AAAAAFWCJCgIAAAABAAgAAABKb2JPcmRlcgEBnxcA" + "LgBEnxcAAAEBwAv/////AwP/////AAAAABVgiQoCAAAAAQALAAAASm9iUmVzcG9uc2UBAaEXAC4ARKEX" + "AAABAcUL/////wMD/////wAAAAAXYIkKAgAAAAEACAAAAEpvYlN0YXRlAQGgFwAuAESgFwAAAQG+CwEA" + "AAABAAAAAAAAAAMD/////wAAAAA="; #endregion #endif #endregion #region Public Properties /// public PropertyState JobOrder { get { return m_jobOrder; } set { if (!Object.ReferenceEquals(m_jobOrder, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_jobOrder = value; } } /// public PropertyState JobResponse { get { return m_jobResponse; } set { if (!Object.ReferenceEquals(m_jobResponse, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_jobResponse = value; } } /// public PropertyState JobState { get { return m_jobState; } set { if (!Object.ReferenceEquals(m_jobState, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_jobState = value; } } #endregion #region Overridden Methods /// public override void GetChildren( ISystemContext context, IList children) { if (m_jobOrder != null) { children.Add(m_jobOrder); } if (m_jobResponse != null) { children.Add(m_jobResponse); } if (m_jobState != null) { children.Add(m_jobState); } base.GetChildren(context, children); } /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.JobOrder: { if (createOrReplace) { if (JobOrder == null) { if (replacement == null) { JobOrder = new PropertyState(this); } else { JobOrder = (PropertyState)replacement; } } } instance = JobOrder; break; } case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.JobResponse: { if (createOrReplace) { if (JobResponse == null) { if (replacement == null) { JobResponse = new PropertyState(this); } else { JobResponse = (PropertyState)replacement; } } } instance = JobResponse; break; } case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.JobState: { if (createOrReplace) { if (JobState == null) { if (replacement == null) { JobState = new PropertyState(this); } else { JobState = (PropertyState)replacement; } } } instance = JobState; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private PropertyState m_jobOrder; private PropertyState m_jobResponse; private PropertyState m_jobState; #endregion } #endif #endregion #region ISA95JobResponseProviderObjectTypeState Class #if (!OPCUA_EXCLUDE_ISA95JobResponseProviderObjectTypeState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class ISA95JobResponseProviderObjectTypeState : BaseObjectState { #region Constructors /// public ISA95JobResponseProviderObjectTypeState(NodeState parent) : base(parent) { } /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(UAModel.ISA95_JOBCONTROL_V2.ObjectTypes.ISA95JobResponseProviderObjectType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); if (JobOrderResponseList != null) { JobOrderResponseList.Initialize(context, JobOrderResponseList_InitializationString); } } #region Initialization String private const string JobOrderResponseList_InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "F2CJCgIAAAABABQAAABKb2JPcmRlclJlc3BvbnNlTGlzdAEBohcALwA/ohcAAAEBxQsBAAAAAQAAAAAA" + "AAADA/////8AAAAA"; private const string InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGCAAgEAAAABACoAAABJU0E5NUpvYlJlc3BvbnNlUHJvdmlkZXJPYmplY3RUeXBlSW5zdGFuY2UBAesD" + "AQHrA+sDAAABAAAAACkAAQHuAwMAAAAXYIkKAgAAAAEAFAAAAEpvYk9yZGVyUmVzcG9uc2VMaXN0AQGi" + "FwAvAD+iFwAAAQHFCwEAAAABAAAAAAAAAAMD/////wAAAAAEYYIKBAAAAAEAHgAAAFJlcXVlc3RKb2JS" + "ZXNwb25zZUJ5Sm9iT3JkZXJJRAEBWhsALwEBWhtaGwAAAQH/////AgAAABdgqQoCAAAAAAAOAAAASW5w" + "dXRBcmd1bWVudHMBAZoXAC4ARJoXAACWAQAAAAEAKgEBYAAAAAoAAABKb2JPcmRlcklEAAz/////AAAA" + "AAJDAAAAQ29udGFpbnMgYW4gSUQgb2YgdGhlIGpvYiBvcmRlciwgYXMgc3BlY2lmaWVkIGJ5IHRoZSBt" + "ZXRob2QgY2FsbGVyLgEAKAEBAAAAAQAAAAEAAAABAf////8AAAAAF2CpCgIAAAAAAA8AAABPdXRwdXRB" + "cmd1bWVudHMBAZsXAC4ARJsXAACWAgAAAAEAKgEB4QAAAAsAAABKb2JSZXNwb25zZQEBxQv/////AAAA" + "AALBAAAAQ29udGFpbnMgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGV4ZWN1dGlvbiBvZiBhIGpvYiBvcmRl" + "ciwgc3VjaCBhcyB0aGUgY3VycmVudCBzdGF0dXMgb2YgdGhlIGpvYiwgYWN0dWFsIG1hdGVyaWFsIGNv" + "bnN1bWVkLCBhY3R1YWwgbWF0ZXJpYWwgcHJvZHVjZWQsIGFjdHVhbCBlcXVpcG1lbnQgdXNlZCwgYW5k" + "IGpvYiBzcGVjaWZpYyBkYXRhLgEAKgEBSgAAAAwAAABSZXR1cm5TdGF0dXMACf////8AAAAAAisAAABS" + "ZXR1cm5zIHRoZSBzdGF0dXMgb2YgdGhlIG1ldGhvZCBleGVjdXRpb24uAQAoAQEAAAABAAAAAgAAAAEB" + "/////wAAAAAEYYIKBAAAAAEAIQAAAFJlcXVlc3RKb2JSZXNwb25zZUJ5Sm9iT3JkZXJTdGF0ZQEBZhsA" + "LwEBZhtmGwAAAQH/////AgAAABdgqQoCAAAAAAAOAAAASW5wdXRBcmd1bWVudHMBAYAXAC4ARIAXAACW" + "AQAAAAEAKgEBYQEAAA0AAABKb2JPcmRlclN0YXRlAQG+CwEAAAABAAAAAAAAAAI7AQAAQ29udGFpbnMg" + "YSBqb2Igc3RhdHVzIG9mIHRoZSBKb2JSZXNwb25zZSB0byBiZSByZXR1cm5lZC4gVGhlIGFycmF5IHNo" + "YWxsIHByb3ZpZGUgYXQgbGVhc3Qgb25lIGVudHJ5IHJlcHJlc2VudGluZyB0aGUgdG9wIGxldmVsIHN0" + "YXRlIGFuZCBwb3RlbnRpYWxseSBhZGRpdGlvbmFsIGVudHJpZXMgcmVwcmVzZW50aW5nIHN1YnN0YXRl" + "cy4gVGhlIGZpcnN0IGVudHJ5IHNoYWxsIGJlIHRoZSB0b3AgbGV2ZWwgZW50cnksIGhhdmluZyB0aGUg" + "QnJvd3NlUGF0aCBzZXQgdG8gbnVsbC4gVGhlIG9yZGVyIG9mIHRoZSBzdWJzdGF0ZXMgaXMgbm90IGRl" + "ZmluZWQuAQAoAQEAAAABAAAAAQAAAAEB/////wAAAAAXYKkKAgAAAAAADwAAAE91dHB1dEFyZ3VtZW50" + "cwEBgRcALgBEgRcAAJYCAAAAAQAqAQHwAAAADAAAAEpvYlJlc3BvbnNlcwEBxQsBAAAAAQAAAAAAAAAC" + "ywAAAENvbnRhaW5zIGEgbGlzdCBvZiBpbmZvcm1hdGlvbiBhYm91dCB0aGUgZXhlY3V0aW9uIG9mIGEg" + "am9iIG9yZGVyLCBzdWNoIGFzIHRoZSBjdXJyZW50IHN0YXR1cyBvZiB0aGUgam9iLCBhY3R1YWwgbWF0" + "ZXJpYWwgY29uc3VtZWQsIGFjdHVhbCBtYXRlcmlhbCBwcm9kdWNlZCwgYWN0dWFsIGVxdWlwbWVudCB1" + "c2VkLCBhbmQgam9iIHNwZWNpZmljIGRhdGEuAQAqAQFKAAAADAAAAFJldHVyblN0YXR1cwAJ/////wAA" + "AAACKwAAAFJldHVybnMgdGhlIHN0YXR1cyBvZiB0aGUgbWV0aG9kIGV4ZWN1dGlvbi4BACgBAQAAAAEA" + "AAACAAAAAQH/////AAAAAA=="; #endregion #endif #endregion #region Public Properties /// public BaseDataVariableState JobOrderResponseList { get { return m_jobOrderResponseList; } set { if (!Object.ReferenceEquals(m_jobOrderResponseList, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_jobOrderResponseList = value; } } /// public RequestJobResponseByJobOrderIDMethodState RequestJobResponseByJobOrderID { get { return m_requestJobResponseByJobOrderIDMethod; } set { if (!Object.ReferenceEquals(m_requestJobResponseByJobOrderIDMethod, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_requestJobResponseByJobOrderIDMethod = value; } } /// public RequestJobResponseByJobOrderStateMethodState RequestJobResponseByJobOrderState { get { return m_requestJobResponseByJobOrderStateMethod; } set { if (!Object.ReferenceEquals(m_requestJobResponseByJobOrderStateMethod, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_requestJobResponseByJobOrderStateMethod = value; } } #endregion #region Overridden Methods /// public override void GetChildren( ISystemContext context, IList children) { if (m_jobOrderResponseList != null) { children.Add(m_jobOrderResponseList); } if (m_requestJobResponseByJobOrderIDMethod != null) { children.Add(m_requestJobResponseByJobOrderIDMethod); } if (m_requestJobResponseByJobOrderStateMethod != null) { children.Add(m_requestJobResponseByJobOrderStateMethod); } base.GetChildren(context, children); } /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.JobOrderResponseList: { if (createOrReplace) { if (JobOrderResponseList == null) { if (replacement == null) { JobOrderResponseList = new BaseDataVariableState(this); } else { JobOrderResponseList = (BaseDataVariableState)replacement; } } } instance = JobOrderResponseList; break; } case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.RequestJobResponseByJobOrderID: { if (createOrReplace) { if (RequestJobResponseByJobOrderID == null) { if (replacement == null) { RequestJobResponseByJobOrderID = new RequestJobResponseByJobOrderIDMethodState(this); } else { RequestJobResponseByJobOrderID = (RequestJobResponseByJobOrderIDMethodState)replacement; } } } instance = RequestJobResponseByJobOrderID; break; } case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.RequestJobResponseByJobOrderState: { if (createOrReplace) { if (RequestJobResponseByJobOrderState == null) { if (replacement == null) { RequestJobResponseByJobOrderState = new RequestJobResponseByJobOrderStateMethodState(this); } else { RequestJobResponseByJobOrderState = (RequestJobResponseByJobOrderStateMethodState)replacement; } } } instance = RequestJobResponseByJobOrderState; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private BaseDataVariableState m_jobOrderResponseList; private RequestJobResponseByJobOrderIDMethodState m_requestJobResponseByJobOrderIDMethod; private RequestJobResponseByJobOrderStateMethodState m_requestJobResponseByJobOrderStateMethod; #endregion } #endif #endregion #region ISA95JobResponseReceiverObjectTypeState Class #if (!OPCUA_EXCLUDE_ISA95JobResponseReceiverObjectTypeState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class ISA95JobResponseReceiverObjectTypeState : BaseObjectState { #region Constructors /// public ISA95JobResponseReceiverObjectTypeState(NodeState parent) : base(parent) { } /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(UAModel.ISA95_JOBCONTROL_V2.ObjectTypes.ISA95JobResponseReceiverObjectType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGCAAgEAAAABACoAAABJU0E5NUpvYlJlc3BvbnNlUmVjZWl2ZXJPYmplY3RUeXBlSW5zdGFuY2UBAewD" + "AQHsA+wDAAD/////AQAAAARhggoEAAAAAQASAAAAUmVjZWl2ZUpvYlJlc3BvbnNlAQFbGwAvAQFbG1sb" + "AAABAf////8CAAAAF2CpCgIAAAAAAA4AAABJbnB1dEFyZ3VtZW50cwEBnBcALgBEnBcAAJYBAAAAAQAq" + "AQHCAAAACwAAAEpvYlJlc3BvbnNlAQHFC/////8AAAAAAqIAAABDb250YWlucyBpbmZvcm1hdGlvbiBh" + "Ym91dCB0aGUgZXhlY3V0aW9uIG9mIGEgam9iIG9yZGVyLCBzdWNoIGFzIGFjdHVhbCBtYXRlcmlhbCBj" + "b25zdW1lZCwgYWN0dWFsIG1hdGVyaWFsIHByb2R1Y2VkLCBhY3R1YWwgZXF1aXBtZW50IHVzZWQsIGFu" + "ZCBqb2Igc3BlY2lmaWMgZGF0YS4BACgBAQAAAAEAAAABAAAAAQH/////AAAAABdgqQoCAAAAAAAPAAAA" + "T3V0cHV0QXJndW1lbnRzAQGdFwAuAESdFwAAlgEAAAABACoBAUoAAAAMAAAAUmV0dXJuU3RhdHVzAAn/" + "////AAAAAAIrAAAAUmV0dXJucyB0aGUgc3RhdHVzIG9mIHRoZSBtZXRob2QgZXhlY3V0aW9uLgEAKAEB" + "AAAAAQAAAAEAAAABAf////8AAAAA"; #endregion #endif #endregion #region Public Properties /// public ReceiveJobResponseMethodState ReceiveJobResponse { get { return m_receiveJobResponseMethod; } set { if (!Object.ReferenceEquals(m_receiveJobResponseMethod, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_receiveJobResponseMethod = value; } } #endregion #region Overridden Methods /// public override void GetChildren( ISystemContext context, IList children) { if (m_receiveJobResponseMethod != null) { children.Add(m_receiveJobResponseMethod); } base.GetChildren(context, children); } /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.ReceiveJobResponse: { if (createOrReplace) { if (ReceiveJobResponse == null) { if (replacement == null) { ReceiveJobResponse = new ReceiveJobResponseMethodState(this); } else { ReceiveJobResponse = (ReceiveJobResponseMethodState)replacement; } } } instance = ReceiveJobResponse; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private ReceiveJobResponseMethodState m_receiveJobResponseMethod; #endregion } #endif #endregion #region ISA95EndedStateMachineTypeState Class #if (!OPCUA_EXCLUDE_ISA95EndedStateMachineTypeState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class ISA95EndedStateMachineTypeState : FiniteStateMachineState { #region Constructors /// public ISA95EndedStateMachineTypeState(NodeState parent) : base(parent) { } /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(UAModel.ISA95_JOBCONTROL_V2.ObjectTypes.ISA95EndedStateMachineType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGCAAgEAAAABACIAAABJU0E5NUVuZGVkU3RhdGVNYWNoaW5lVHlwZUluc3RhbmNlAQHtAwEB7QPtAwAA" + "/////wEAAAAVYIkIAgAAAAAADAAAAEN1cnJlbnRTdGF0ZQEBAAAALwEAyAoAFf////8BAf////8BAAAA" + "FWCJCAIAAAAAAAIAAABJZAEBAAAALgBEABH/////AQH/////AAAAAA=="; #endregion #endif #endregion #region Public Properties #endregion #region Overridden Methods #endregion #region Private Fields #endregion } #endif #endregion #region ISA95InterruptedStateMachineTypeState Class #if (!OPCUA_EXCLUDE_ISA95InterruptedStateMachineTypeState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class ISA95InterruptedStateMachineTypeState : FiniteStateMachineState { #region Constructors /// public ISA95InterruptedStateMachineTypeState(NodeState parent) : base(parent) { } /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(UAModel.ISA95_JOBCONTROL_V2.ObjectTypes.ISA95InterruptedStateMachineType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGCAAgEAAAABACgAAABJU0E5NUludGVycnVwdGVkU3RhdGVNYWNoaW5lVHlwZUluc3RhbmNlAQHvAwEB" + "7wPvAwAA/////wEAAAAVYIkIAgAAAAAADAAAAEN1cnJlbnRTdGF0ZQEBAAAALwEAyAoAFf////8BAf//" + "//8BAAAAFWCJCAIAAAAAAAIAAABJZAEBAAAALgBEABH/////AQH/////AAAAAA=="; #endregion #endif #endregion #region Public Properties #endregion #region Overridden Methods #endregion #region Private Fields #endregion } #endif #endregion #region ISA95JobOrderReceiverObjectTypeState Class #if (!OPCUA_EXCLUDE_ISA95JobOrderReceiverObjectTypeState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class ISA95JobOrderReceiverObjectTypeState : FiniteStateMachineState { #region Constructors /// public ISA95JobOrderReceiverObjectTypeState(NodeState parent) : base(parent) { } /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(UAModel.ISA95_JOBCONTROL_V2.ObjectTypes.ISA95JobOrderReceiverObjectType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); if (Abort != null) { Abort.Initialize(context, Abort_InitializationString); } if (Cancel != null) { Cancel.Initialize(context, Cancel_InitializationString); } if (Clear != null) { Clear.Initialize(context, Clear_InitializationString); } if (Pause != null) { Pause.Initialize(context, Pause_InitializationString); } if (Resume != null) { Resume.Initialize(context, Resume_InitializationString); } if (RevokeStart != null) { RevokeStart.Initialize(context, RevokeStart_InitializationString); } if (Start != null) { Start.Initialize(context, Start_InitializationString); } if (Stop != null) { Stop.Initialize(context, Stop_InitializationString); } if (Store != null) { Store.Initialize(context, Store_InitializationString); } if (StoreAndStart != null) { StoreAndStart.Initialize(context, StoreAndStart_InitializationString); } if (Update != null) { Update.Initialize(context, Update_InitializationString); } } #region Initialization String private const string Abort_InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGGCCgQAAAABAAUAAABBYm9ydAEBYhsALwEBYhtiGwAAAQEIAAAAADUBAQG4EwA1AQEBuRMANQEBAdQT" + "ADUBAQHVEwA1AQEB3BMANQEBAd0TADUBAQHeEwA1AQEB3xMCAAAAF2CpCgIAAAAAAA4AAABJbnB1dEFy" + "Z3VtZW50cwEBrxcALgBErxcAAJYCAAAAAQAqAQGzAAAACgAAAEpvYk9yZGVySUQADP////8AAAAAApYA" + "AABDb250YWlucyBpbmZvcm1hdGlvbiBkZWZpbmluZyB0aGUgam9iIG9yZGVyIHdpdGggYWxsIHBhcmFt" + "ZXRlcnMgYW5kIGFueSBtYXRlcmlhbCwgZXF1aXBtZW50LCBvciBwaHlzaWNhbCBhc3NldCByZXF1aXJl" + "bWVudHMgYXNzb2NpYXRlZCB3aXRoIHRoZSBvcmRlci4BACoBAeoAAAAHAAAAQ29tbWVudAAVAQAAAAEA" + "AAAAAAAAAswAAABUaGUgY29tbWVudCBwcm92aWRlcyBhIGRlc2NyaXB0aW9uIG9mIHdoeSB0aGUgbWV0" + "aG9kIHdhcyBjYWxsZWQuIEluIG9yZGVyIHRvIHByb3ZpZGUgdGhlIGNvbW1lbnQgaW4gc2V2ZXJhbCBs" + "YW5ndWFnZXMsIGl0IGlzIGFuIGFycmF5IG9mIExvY2FsaXplZFRleHQuIFRoZSBhcnJheSBtYXkgYmUg" + "ZW1wdHksIHdoZW4gbm8gY29tbWVudCBpcyBwcm92aWRlZC4BACgBAQAAAAEAAAACAAAAAQH/////AAAA" + "ABdgqQoCAAAAAAAPAAAAT3V0cHV0QXJndW1lbnRzAQGwFwAuAESwFwAAlgEAAAABACoBAUoAAAAMAAAA" + "UmV0dXJuU3RhdHVzAAn/////AAAAAAIrAAAAUmV0dXJucyB0aGUgc3RhdHVzIG9mIHRoZSBtZXRob2Qg" + "ZXhlY3V0aW9uLgEAKAEBAAAAAQAAAAEAAAABAf////8AAAAA"; private const string Cancel_InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGGCCgQAAAABAAYAAABDYW5jZWwBAWMbAC8BAWMbYxsAAAEB/////wIAAAAXYKkKAgAAAAAADgAAAElu" + "cHV0QXJndW1lbnRzAQGxFwAuAESxFwAAlgIAAAABACoBAbMAAAAKAAAASm9iT3JkZXJJRAAM/////wAA" + "AAAClgAAAENvbnRhaW5zIGluZm9ybWF0aW9uIGRlZmluaW5nIHRoZSBqb2Igb3JkZXIgd2l0aCBhbGwg" + "cGFyYW1ldGVycyBhbmQgYW55IG1hdGVyaWFsLCBlcXVpcG1lbnQsIG9yIHBoeXNpY2FsIGFzc2V0IHJl" + "cXVpcmVtZW50cyBhc3NvY2lhdGVkIHdpdGggdGhlIG9yZGVyLgEAKgEB6gAAAAcAAABDb21tZW50ABUB" + "AAAAAQAAAAAAAAACzAAAAFRoZSBjb21tZW50IHByb3ZpZGVzIGEgZGVzY3JpcHRpb24gb2Ygd2h5IHRo" + "ZSBtZXRob2Qgd2FzIGNhbGxlZC4gSW4gb3JkZXIgdG8gcHJvdmlkZSB0aGUgY29tbWVudCBpbiBzZXZl" + "cmFsIGxhbmd1YWdlcywgaXQgaXMgYW4gYXJyYXkgb2YgTG9jYWxpemVkVGV4dC4gVGhlIGFycmF5IG1h" + "eSBiZSBlbXB0eSwgd2hlbiBubyBjb21tZW50IGlzIHByb3ZpZGVkLgEAKAEBAAAAAQAAAAIAAAABAf//" + "//8AAAAAF2CpCgIAAAAAAA8AAABPdXRwdXRBcmd1bWVudHMBAbIXAC4ARLIXAACWAQAAAAEAKgEBSgAA" + "AAwAAABSZXR1cm5TdGF0dXMACf////8AAAAAAisAAABSZXR1cm5zIHRoZSBzdGF0dXMgb2YgdGhlIG1l" + "dGhvZCBleGVjdXRpb24uAQAoAQEAAAABAAAAAQAAAAEB/////wAAAAA="; private const string Clear_InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGGCCgQAAAABAAUAAABDbGVhcgEBZBsALwEBZBtkGwAAAQH/////AgAAABdgqQoCAAAAAAAOAAAASW5w" + "dXRBcmd1bWVudHMBAbMXAC4ARLMXAACWAgAAAAEAKgEBswAAAAoAAABKb2JPcmRlcklEAAz/////AAAA" + "AAKWAAAAQ29udGFpbnMgaW5mb3JtYXRpb24gZGVmaW5pbmcgdGhlIGpvYiBvcmRlciB3aXRoIGFsbCBw" + "YXJhbWV0ZXJzIGFuZCBhbnkgbWF0ZXJpYWwsIGVxdWlwbWVudCwgb3IgcGh5c2ljYWwgYXNzZXQgcmVx" + "dWlyZW1lbnRzIGFzc29jaWF0ZWQgd2l0aCB0aGUgb3JkZXIuAQAqAQHqAAAABwAAAENvbW1lbnQAFQEA" + "AAABAAAAAAAAAALMAAAAVGhlIGNvbW1lbnQgcHJvdmlkZXMgYSBkZXNjcmlwdGlvbiBvZiB3aHkgdGhl" + "IG1ldGhvZCB3YXMgY2FsbGVkLiBJbiBvcmRlciB0byBwcm92aWRlIHRoZSBjb21tZW50IGluIHNldmVy" + "YWwgbGFuZ3VhZ2VzLCBpdCBpcyBhbiBhcnJheSBvZiBMb2NhbGl6ZWRUZXh0LiBUaGUgYXJyYXkgbWF5" + "IGJlIGVtcHR5LCB3aGVuIG5vIGNvbW1lbnQgaXMgcHJvdmlkZWQuAQAoAQEAAAABAAAAAgAAAAEB////" + "/wAAAAAXYKkKAgAAAAAADwAAAE91dHB1dEFyZ3VtZW50cwEBtBcALgBEtBcAAJYBAAAAAQAqAQFKAAAA" + "DAAAAFJldHVyblN0YXR1cwAJ/////wAAAAACKwAAAFJldHVybnMgdGhlIHN0YXR1cyBvZiB0aGUgbWV0" + "aG9kIGV4ZWN1dGlvbi4BACgBAQAAAAEAAAABAAAAAQH/////AAAAAA=="; private const string Pause_InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGGCCgQAAAABAAUAAABQYXVzZQEBXxsALwEBXxtfGwAAAQECAAAAADUBAQG2EwA1AQEB0hMCAAAAF2Cp" + "CgIAAAAAAA4AAABJbnB1dEFyZ3VtZW50cwEBqRcALgBEqRcAAJYCAAAAAQAqAQGzAAAACgAAAEpvYk9y" + "ZGVySUQADP////8AAAAAApYAAABDb250YWlucyBpbmZvcm1hdGlvbiBkZWZpbmluZyB0aGUgam9iIG9y" + "ZGVyIHdpdGggYWxsIHBhcmFtZXRlcnMgYW5kIGFueSBtYXRlcmlhbCwgZXF1aXBtZW50LCBvciBwaHlz" + "aWNhbCBhc3NldCByZXF1aXJlbWVudHMgYXNzb2NpYXRlZCB3aXRoIHRoZSBvcmRlci4BACoBAeoAAAAH" + "AAAAQ29tbWVudAAVAQAAAAEAAAAAAAAAAswAAABUaGUgY29tbWVudCBwcm92aWRlcyBhIGRlc2NyaXB0" + "aW9uIG9mIHdoeSB0aGUgbWV0aG9kIHdhcyBjYWxsZWQuIEluIG9yZGVyIHRvIHByb3ZpZGUgdGhlIGNv" + "bW1lbnQgaW4gc2V2ZXJhbCBsYW5ndWFnZXMsIGl0IGlzIGFuIGFycmF5IG9mIExvY2FsaXplZFRleHQu" + "IFRoZSBhcnJheSBtYXkgYmUgZW1wdHksIHdoZW4gbm8gY29tbWVudCBpcyBwcm92aWRlZC4BACgBAQAA" + "AAEAAAACAAAAAQH/////AAAAABdgqQoCAAAAAAAPAAAAT3V0cHV0QXJndW1lbnRzAQGqFwAuAESqFwAA" + "lgEAAAABACoBAUoAAAAMAAAAUmV0dXJuU3RhdHVzAAn/////AAAAAAIrAAAAUmV0dXJucyB0aGUgc3Rh" + "dHVzIG9mIHRoZSBtZXRob2QgZXhlY3V0aW9uLgEAKAEBAAAAAQAAAAEAAAABAf////8AAAAA"; private const string Resume_InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGGCCgQAAAABAAYAAABSZXN1bWUBAWAbAC8BAWAbYBsAAAEBAgAAAAA1AQEBuhMANQEBAdYTAgAAABdg" + "qQoCAAAAAAAOAAAASW5wdXRBcmd1bWVudHMBAasXAC4ARKsXAACWAgAAAAEAKgEBswAAAAoAAABKb2JP" + "cmRlcklEAAz/////AAAAAAKWAAAAQ29udGFpbnMgaW5mb3JtYXRpb24gZGVmaW5pbmcgdGhlIGpvYiBv" + "cmRlciB3aXRoIGFsbCBwYXJhbWV0ZXJzIGFuZCBhbnkgbWF0ZXJpYWwsIGVxdWlwbWVudCwgb3IgcGh5" + "c2ljYWwgYXNzZXQgcmVxdWlyZW1lbnRzIGFzc29jaWF0ZWQgd2l0aCB0aGUgb3JkZXIuAQAqAQHqAAAA" + "BwAAAENvbW1lbnQAFQEAAAABAAAAAAAAAALMAAAAVGhlIGNvbW1lbnQgcHJvdmlkZXMgYSBkZXNjcmlw" + "dGlvbiBvZiB3aHkgdGhlIG1ldGhvZCB3YXMgY2FsbGVkLiBJbiBvcmRlciB0byBwcm92aWRlIHRoZSBj" + "b21tZW50IGluIHNldmVyYWwgbGFuZ3VhZ2VzLCBpdCBpcyBhbiBhcnJheSBvZiBMb2NhbGl6ZWRUZXh0" + "LiBUaGUgYXJyYXkgbWF5IGJlIGVtcHR5LCB3aGVuIG5vIGNvbW1lbnQgaXMgcHJvdmlkZWQuAQAoAQEA" + "AAABAAAAAgAAAAEB/////wAAAAAXYKkKAgAAAAAADwAAAE91dHB1dEFyZ3VtZW50cwEBrBcALgBErBcA" + "AJYBAAAAAQAqAQFKAAAADAAAAFJldHVyblN0YXR1cwAJ/////wAAAAACKwAAAFJldHVybnMgdGhlIHN0" + "YXR1cyBvZiB0aGUgbWV0aG9kIGV4ZWN1dGlvbi4BACgBAQAAAAEAAAABAAAAAQH/////AAAAAA=="; private const string RevokeStart_InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGGCCgQAAAABAAsAAABSZXZva2VTdGFydAEBZRsALwEBZRtlGwAAAQECAAAAADUBAQGzEwA1AQEBzxMC" + "AAAAF2CpCgIAAAAAAA4AAABJbnB1dEFyZ3VtZW50cwEBtRcALgBEtRcAAJYCAAAAAQAqAQGzAAAACgAA" + "AEpvYk9yZGVySUQADP////8AAAAAApYAAABDb250YWlucyBpbmZvcm1hdGlvbiBkZWZpbmluZyB0aGUg" + "am9iIG9yZGVyIHdpdGggYWxsIHBhcmFtZXRlcnMgYW5kIGFueSBtYXRlcmlhbCwgZXF1aXBtZW50LCBv" + "ciBwaHlzaWNhbCBhc3NldCByZXF1aXJlbWVudHMgYXNzb2NpYXRlZCB3aXRoIHRoZSBvcmRlci4BACoB" + "AeoAAAAHAAAAQ29tbWVudAAVAQAAAAEAAAAAAAAAAswAAABUaGUgY29tbWVudCBwcm92aWRlcyBhIGRl" + "c2NyaXB0aW9uIG9mIHdoeSB0aGUgbWV0aG9kIHdhcyBjYWxsZWQuIEluIG9yZGVyIHRvIHByb3ZpZGUg" + "dGhlIGNvbW1lbnQgaW4gc2V2ZXJhbCBsYW5ndWFnZXMsIGl0IGlzIGFuIGFycmF5IG9mIExvY2FsaXpl" + "ZFRleHQuIFRoZSBhcnJheSBtYXkgYmUgZW1wdHksIHdoZW4gbm8gY29tbWVudCBpcyBwcm92aWRlZC4B" + "ACgBAQAAAAEAAAACAAAAAQH/////AAAAABdgqQoCAAAAAAAPAAAAT3V0cHV0QXJndW1lbnRzAQG2FwAu" + "AES2FwAAlgEAAAABACoBAUoAAAAMAAAAUmV0dXJuU3RhdHVzAAn/////AAAAAAIrAAAAUmV0dXJucyB0" + "aGUgc3RhdHVzIG9mIHRoZSBtZXRob2QgZXhlY3V0aW9uLgEAKAEBAAAAAQAAAAEAAAABAf////8AAAAA"; private const string Start_InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGGCCgQAAAABAAUAAABTdGFydAEBXRsALwEBXRtdGwAAAQECAAAAADUBAQGyEwA1AQEBzhMCAAAAF2Cp" + "CgIAAAAAAA4AAABJbnB1dEFyZ3VtZW50cwEBpRcALgBEpRcAAJYCAAAAAQAqAQGzAAAACgAAAEpvYk9y" + "ZGVySUQADP////8AAAAAApYAAABDb250YWlucyBpbmZvcm1hdGlvbiBkZWZpbmluZyB0aGUgam9iIG9y" + "ZGVyIHdpdGggYWxsIHBhcmFtZXRlcnMgYW5kIGFueSBtYXRlcmlhbCwgZXF1aXBtZW50LCBvciBwaHlz" + "aWNhbCBhc3NldCByZXF1aXJlbWVudHMgYXNzb2NpYXRlZCB3aXRoIHRoZSBvcmRlci4BACoBAeoAAAAH" + "AAAAQ29tbWVudAAVAQAAAAEAAAAAAAAAAswAAABUaGUgY29tbWVudCBwcm92aWRlcyBhIGRlc2NyaXB0" + "aW9uIG9mIHdoeSB0aGUgbWV0aG9kIHdhcyBjYWxsZWQuIEluIG9yZGVyIHRvIHByb3ZpZGUgdGhlIGNv" + "bW1lbnQgaW4gc2V2ZXJhbCBsYW5ndWFnZXMsIGl0IGlzIGFuIGFycmF5IG9mIExvY2FsaXplZFRleHQu" + "IFRoZSBhcnJheSBtYXkgYmUgZW1wdHksIHdoZW4gbm8gY29tbWVudCBpcyBwcm92aWRlZC4BACgBAQAA" + "AAEAAAACAAAAAQH/////AAAAABdgqQoCAAAAAAAPAAAAT3V0cHV0QXJndW1lbnRzAQGmFwAuAESmFwAA" + "lgEAAAABACoBAUoAAAAMAAAAUmV0dXJuU3RhdHVzAAn/////AAAAAAIrAAAAUmV0dXJucyB0aGUgc3Rh" + "dHVzIG9mIHRoZSBtZXRob2QgZXhlY3V0aW9uLgEAKAEBAAAAAQAAAAEAAAABAf////8AAAAA"; private const string Stop_InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGGCCgQAAAABAAQAAABTdG9wAQFeGwAvAQFeG14bAAABAQQAAAAANQEBAbsTADUBAQG3EwA1AQEB0xMA" + "NQEBAdcTAgAAABdgqQoCAAAAAAAOAAAASW5wdXRBcmd1bWVudHMBAacXAC4ARKcXAACWAgAAAAEAKgEB" + "swAAAAoAAABKb2JPcmRlcklEAAz/////AAAAAAKWAAAAQ29udGFpbnMgaW5mb3JtYXRpb24gZGVmaW5p" + "bmcgdGhlIGpvYiBvcmRlciB3aXRoIGFsbCBwYXJhbWV0ZXJzIGFuZCBhbnkgbWF0ZXJpYWwsIGVxdWlw" + "bWVudCwgb3IgcGh5c2ljYWwgYXNzZXQgcmVxdWlyZW1lbnRzIGFzc29jaWF0ZWQgd2l0aCB0aGUgb3Jk" + "ZXIuAQAqAQHqAAAABwAAAENvbW1lbnQAFQEAAAABAAAAAAAAAALMAAAAVGhlIGNvbW1lbnQgcHJvdmlk" + "ZXMgYSBkZXNjcmlwdGlvbiBvZiB3aHkgdGhlIG1ldGhvZCB3YXMgY2FsbGVkLiBJbiBvcmRlciB0byBw" + "cm92aWRlIHRoZSBjb21tZW50IGluIHNldmVyYWwgbGFuZ3VhZ2VzLCBpdCBpcyBhbiBhcnJheSBvZiBM" + "b2NhbGl6ZWRUZXh0LiBUaGUgYXJyYXkgbWF5IGJlIGVtcHR5LCB3aGVuIG5vIGNvbW1lbnQgaXMgcHJv" + "dmlkZWQuAQAoAQEAAAABAAAAAgAAAAEB/////wAAAAAXYKkKAgAAAAAADwAAAE91dHB1dEFyZ3VtZW50" + "cwEBqBcALgBEqBcAAJYBAAAAAQAqAQFKAAAADAAAAFJldHVyblN0YXR1cwAJ/////wAAAAACKwAAAFJl" + "dHVybnMgdGhlIHN0YXR1cyBvZiB0aGUgbWV0aG9kIGV4ZWN1dGlvbi4BACgBAQAAAAEAAAABAAAAAQH/" + "////AAAAAA=="; private const string Store_InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGGCCgQAAAABAAUAAABTdG9yZQEBWRsALwEBWRtZGwAAAQH/////AgAAABdgqQoCAAAAAAAOAAAASW5w" + "dXRBcmd1bWVudHMBAZgXAC4ARJgXAACWAgAAAAEAKgEBswAAAAgAAABKb2JPcmRlcgEBwAv/////AAAA" + "AAKWAAAAQ29udGFpbnMgaW5mb3JtYXRpb24gZGVmaW5pbmcgdGhlIGpvYiBvcmRlciB3aXRoIGFsbCBw" + "YXJhbWV0ZXJzIGFuZCBhbnkgbWF0ZXJpYWwsIGVxdWlwbWVudCwgb3IgcGh5c2ljYWwgYXNzZXQgcmVx" + "dWlyZW1lbnRzIGFzc29jaWF0ZWQgd2l0aCB0aGUgb3JkZXIuAQAqAQHqAAAABwAAAENvbW1lbnQAFQEA" + "AAABAAAAAAAAAALMAAAAVGhlIGNvbW1lbnQgcHJvdmlkZXMgYSBkZXNjcmlwdGlvbiBvZiB3aHkgdGhl" + "IG1ldGhvZCB3YXMgY2FsbGVkLiBJbiBvcmRlciB0byBwcm92aWRlIHRoZSBjb21tZW50IGluIHNldmVy" + "YWwgbGFuZ3VhZ2VzLCBpdCBpcyBhbiBhcnJheSBvZiBMb2NhbGl6ZWRUZXh0LiBUaGUgYXJyYXkgbWF5" + "IGJlIGVtcHR5LCB3aGVuIG5vIGNvbW1lbnQgaXMgcHJvdmlkZWQuAQAoAQEAAAABAAAAAgAAAAEB////" + "/wAAAAAXYKkKAgAAAAAADwAAAE91dHB1dEFyZ3VtZW50cwEBmRcALgBEmRcAAJYBAAAAAQAqAQFKAAAA" + "DAAAAFJldHVyblN0YXR1cwAJ/////wAAAAACKwAAAFJldHVybnMgdGhlIHN0YXR1cyBvZiB0aGUgbWV0" + "aG9kIGV4ZWN1dGlvbi4BACgBAQAAAAEAAAABAAAAAQH/////AAAAAA=="; private const string StoreAndStart_InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGGCCgQAAAABAA0AAABTdG9yZUFuZFN0YXJ0AQFcGwAvAQFcG1wbAAABAf////8CAAAAF2CpCgIAAAAA" + "AA4AAABJbnB1dEFyZ3VtZW50cwEBoxcALgBEoxcAAJYCAAAAAQAqAQGzAAAACAAAAEpvYk9yZGVyAQHA" + "C/////8AAAAAApYAAABDb250YWlucyBpbmZvcm1hdGlvbiBkZWZpbmluZyB0aGUgam9iIG9yZGVyIHdp" + "dGggYWxsIHBhcmFtZXRlcnMgYW5kIGFueSBtYXRlcmlhbCwgZXF1aXBtZW50LCBvciBwaHlzaWNhbCBh" + "c3NldCByZXF1aXJlbWVudHMgYXNzb2NpYXRlZCB3aXRoIHRoZSBvcmRlci4BACoBAeoAAAAHAAAAQ29t" + "bWVudAAVAQAAAAEAAAAAAAAAAswAAABUaGUgY29tbWVudCBwcm92aWRlcyBhIGRlc2NyaXB0aW9uIG9m" + "IHdoeSB0aGUgbWV0aG9kIHdhcyBjYWxsZWQuIEluIG9yZGVyIHRvIHByb3ZpZGUgdGhlIGNvbW1lbnQg" + "aW4gc2V2ZXJhbCBsYW5ndWFnZXMsIGl0IGlzIGFuIGFycmF5IG9mIExvY2FsaXplZFRleHQuIFRoZSBh" + "cnJheSBtYXkgYmUgZW1wdHksIHdoZW4gbm8gY29tbWVudCBpcyBwcm92aWRlZC4BACgBAQAAAAEAAAAC" + "AAAAAQH/////AAAAABdgqQoCAAAAAAAPAAAAT3V0cHV0QXJndW1lbnRzAQGkFwAuAESkFwAAlgEAAAAB" + "ACoBAUoAAAAMAAAAUmV0dXJuU3RhdHVzAAn/////AAAAAAIrAAAAUmV0dXJucyB0aGUgc3RhdHVzIG9m" + "IHRoZSBtZXRob2QgZXhlY3V0aW9uLgEAKAEBAAAAAQAAAAEAAAABAf////8AAAAA"; private const string Update_InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGGCCgQAAAABAAYAAABVcGRhdGUBAWEbAC8BAWEbYRsAAAEBBAAAAAA1AQEBtBMANQEBAbETADUBAQHN" + "EwA1AQEB0BMCAAAAF2CpCgIAAAAAAA4AAABJbnB1dEFyZ3VtZW50cwEBrRcALgBErRcAAJYCAAAAAQAq" + "AQGzAAAACAAAAEpvYk9yZGVyAQHAC/////8AAAAAApYAAABDb250YWlucyBpbmZvcm1hdGlvbiBkZWZp" + "bmluZyB0aGUgam9iIG9yZGVyIHdpdGggYWxsIHBhcmFtZXRlcnMgYW5kIGFueSBtYXRlcmlhbCwgZXF1" + "aXBtZW50LCBvciBwaHlzaWNhbCBhc3NldCByZXF1aXJlbWVudHMgYXNzb2NpYXRlZCB3aXRoIHRoZSBv" + "cmRlci4BACoBAeoAAAAHAAAAQ29tbWVudAAVAQAAAAEAAAAAAAAAAswAAABUaGUgY29tbWVudCBwcm92" + "aWRlcyBhIGRlc2NyaXB0aW9uIG9mIHdoeSB0aGUgbWV0aG9kIHdhcyBjYWxsZWQuIEluIG9yZGVyIHRv" + "IHByb3ZpZGUgdGhlIGNvbW1lbnQgaW4gc2V2ZXJhbCBsYW5ndWFnZXMsIGl0IGlzIGFuIGFycmF5IG9m" + "IExvY2FsaXplZFRleHQuIFRoZSBhcnJheSBtYXkgYmUgZW1wdHksIHdoZW4gbm8gY29tbWVudCBpcyBw" + "cm92aWRlZC4BACgBAQAAAAEAAAACAAAAAQH/////AAAAABdgqQoCAAAAAAAPAAAAT3V0cHV0QXJndW1l" + "bnRzAQGuFwAuAESuFwAAlgEAAAABACoBAUoAAAAMAAAAUmV0dXJuU3RhdHVzAAn/////AAAAAAIrAAAA" + "UmV0dXJucyB0aGUgc3RhdHVzIG9mIHRoZSBtZXRob2QgZXhlY3V0aW9uLgEAKAEBAAAAAQAAAAEAAAAB" + "Af////8AAAAA"; private const string InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGCAAgEAAAABACcAAABJU0E5NUpvYk9yZGVyUmVjZWl2ZXJPYmplY3RUeXBlSW5zdGFuY2UBAeoDAQHq" + "A+oDAAD/////FAAAABVgiQgCAAAAAAAMAAAAQ3VycmVudFN0YXRlAQEAAAAvAQDICgAV/////wEB////" + "/wEAAAAVYIkIAgAAAAAAAgAAAElkAQEAAAAuAEQAEf////8BAf////8AAAAABGGCCgQAAAABAAUAAABB" + "Ym9ydAEBYhsALwEBYhtiGwAAAQEIAAAAADUBAQG4EwA1AQEBuRMANQEBAdQTADUBAQHVEwA1AQEB3BMA" + "NQEBAd0TADUBAQHeEwA1AQEB3xMCAAAAF2CpCgIAAAAAAA4AAABJbnB1dEFyZ3VtZW50cwEBrxcALgBE" + "rxcAAJYCAAAAAQAqAQGzAAAACgAAAEpvYk9yZGVySUQADP////8AAAAAApYAAABDb250YWlucyBpbmZv" + "cm1hdGlvbiBkZWZpbmluZyB0aGUgam9iIG9yZGVyIHdpdGggYWxsIHBhcmFtZXRlcnMgYW5kIGFueSBt" + "YXRlcmlhbCwgZXF1aXBtZW50LCBvciBwaHlzaWNhbCBhc3NldCByZXF1aXJlbWVudHMgYXNzb2NpYXRl" + "ZCB3aXRoIHRoZSBvcmRlci4BACoBAeoAAAAHAAAAQ29tbWVudAAVAQAAAAEAAAAAAAAAAswAAABUaGUg" + "Y29tbWVudCBwcm92aWRlcyBhIGRlc2NyaXB0aW9uIG9mIHdoeSB0aGUgbWV0aG9kIHdhcyBjYWxsZWQu" + "IEluIG9yZGVyIHRvIHByb3ZpZGUgdGhlIGNvbW1lbnQgaW4gc2V2ZXJhbCBsYW5ndWFnZXMsIGl0IGlz" + "IGFuIGFycmF5IG9mIExvY2FsaXplZFRleHQuIFRoZSBhcnJheSBtYXkgYmUgZW1wdHksIHdoZW4gbm8g" + "Y29tbWVudCBpcyBwcm92aWRlZC4BACgBAQAAAAEAAAACAAAAAQH/////AAAAABdgqQoCAAAAAAAPAAAA" + "T3V0cHV0QXJndW1lbnRzAQGwFwAuAESwFwAAlgEAAAABACoBAUoAAAAMAAAAUmV0dXJuU3RhdHVzAAn/" + "////AAAAAAIrAAAAUmV0dXJucyB0aGUgc3RhdHVzIG9mIHRoZSBtZXRob2QgZXhlY3V0aW9uLgEAKAEB" + "AAAAAQAAAAEAAAABAf////8AAAAABGGCCgQAAAABAAYAAABDYW5jZWwBAWMbAC8BAWMbYxsAAAEB////" + "/wIAAAAXYKkKAgAAAAAADgAAAElucHV0QXJndW1lbnRzAQGxFwAuAESxFwAAlgIAAAABACoBAbMAAAAK" + "AAAASm9iT3JkZXJJRAAM/////wAAAAAClgAAAENvbnRhaW5zIGluZm9ybWF0aW9uIGRlZmluaW5nIHRo" + "ZSBqb2Igb3JkZXIgd2l0aCBhbGwgcGFyYW1ldGVycyBhbmQgYW55IG1hdGVyaWFsLCBlcXVpcG1lbnQs" + "IG9yIHBoeXNpY2FsIGFzc2V0IHJlcXVpcmVtZW50cyBhc3NvY2lhdGVkIHdpdGggdGhlIG9yZGVyLgEA" + "KgEB6gAAAAcAAABDb21tZW50ABUBAAAAAQAAAAAAAAACzAAAAFRoZSBjb21tZW50IHByb3ZpZGVzIGEg" + "ZGVzY3JpcHRpb24gb2Ygd2h5IHRoZSBtZXRob2Qgd2FzIGNhbGxlZC4gSW4gb3JkZXIgdG8gcHJvdmlk" + "ZSB0aGUgY29tbWVudCBpbiBzZXZlcmFsIGxhbmd1YWdlcywgaXQgaXMgYW4gYXJyYXkgb2YgTG9jYWxp" + "emVkVGV4dC4gVGhlIGFycmF5IG1heSBiZSBlbXB0eSwgd2hlbiBubyBjb21tZW50IGlzIHByb3ZpZGVk" + "LgEAKAEBAAAAAQAAAAIAAAABAf////8AAAAAF2CpCgIAAAAAAA8AAABPdXRwdXRBcmd1bWVudHMBAbIX" + "AC4ARLIXAACWAQAAAAEAKgEBSgAAAAwAAABSZXR1cm5TdGF0dXMACf////8AAAAAAisAAABSZXR1cm5z" + "IHRoZSBzdGF0dXMgb2YgdGhlIG1ldGhvZCBleGVjdXRpb24uAQAoAQEAAAABAAAAAQAAAAEB/////wAA" + "AAAEYYIKBAAAAAEABQAAAENsZWFyAQFkGwAvAQFkG2QbAAABAf////8CAAAAF2CpCgIAAAAAAA4AAABJ" + "bnB1dEFyZ3VtZW50cwEBsxcALgBEsxcAAJYCAAAAAQAqAQGzAAAACgAAAEpvYk9yZGVySUQADP////8A" + "AAAAApYAAABDb250YWlucyBpbmZvcm1hdGlvbiBkZWZpbmluZyB0aGUgam9iIG9yZGVyIHdpdGggYWxs" + "IHBhcmFtZXRlcnMgYW5kIGFueSBtYXRlcmlhbCwgZXF1aXBtZW50LCBvciBwaHlzaWNhbCBhc3NldCBy" + "ZXF1aXJlbWVudHMgYXNzb2NpYXRlZCB3aXRoIHRoZSBvcmRlci4BACoBAeoAAAAHAAAAQ29tbWVudAAV" + "AQAAAAEAAAAAAAAAAswAAABUaGUgY29tbWVudCBwcm92aWRlcyBhIGRlc2NyaXB0aW9uIG9mIHdoeSB0" + "aGUgbWV0aG9kIHdhcyBjYWxsZWQuIEluIG9yZGVyIHRvIHByb3ZpZGUgdGhlIGNvbW1lbnQgaW4gc2V2" + "ZXJhbCBsYW5ndWFnZXMsIGl0IGlzIGFuIGFycmF5IG9mIExvY2FsaXplZFRleHQuIFRoZSBhcnJheSBt" + "YXkgYmUgZW1wdHksIHdoZW4gbm8gY29tbWVudCBpcyBwcm92aWRlZC4BACgBAQAAAAEAAAACAAAAAQH/" + "////AAAAABdgqQoCAAAAAAAPAAAAT3V0cHV0QXJndW1lbnRzAQG0FwAuAES0FwAAlgEAAAABACoBAUoA" + "AAAMAAAAUmV0dXJuU3RhdHVzAAn/////AAAAAAIrAAAAUmV0dXJucyB0aGUgc3RhdHVzIG9mIHRoZSBt" + "ZXRob2QgZXhlY3V0aW9uLgEAKAEBAAAAAQAAAAEAAAABAf////8AAAAAN2CJCgIAAAABAAsAAABFcXVp" + "cG1lbnRJRAEBlRcDAAAAAGYAAABEZWZpbmVzIGEgcmVhZC1vbmx5IHNldCBvZiBFcXVpcG1lbnQgQ2xh" + "c3MgSURzIGFuZCBFcXVpcG1lbnQgSURzIHRoYXQgbWF5IGJlIHNwZWNpZmllZCBpbiBhIGpvYiBvcmRl" + "ci4ALwA/lRcAAAAMAQAAAAEAAAAAAAAAAQH/////AAAAADdgiQoCAAAAAQAMAAAASm9iT3JkZXJMaXN0" + "AQGRFwMAAAAATAAAAERlZmluZXMgYSByZWFkLW9ubHkgbGlzdCBvZiBqb2Igb3JkZXIgaW5mb3JtYXRp" + "b24gYXZhaWxhYmxlIGZyb20gdGhlIHNlcnZlci4ALwA/kRcAAAEBxwsBAAAAAQAAAAAAAAABAf////8A" + "AAAAN2CJCgIAAAABAA8AAABNYXRlcmlhbENsYXNzSUQBAZMXAwAAAABVAAAARGVmaW5lcyBhIHJlYWQt" + "b25seSBzZXQgb2YgTWF0ZXJpYWwgQ2xhc3NlcyBJRHMgdGhhdCBtYXkgYmUgc3BlY2lmaWVkIGluIGEg" + "am9iIG9yZGVyLgAvAD+TFwAAAAwBAAAAAQAAAAAAAAABAf////8AAAAAN2CJCgIAAAABABQAAABNYXRl" + "cmlhbERlZmluaXRpb25JRAEBlBcDAAAAAFUAAABEZWZpbmVzIGEgcmVhZC1vbmx5IHNldCBvZiBNYXRl" + "cmlhbCBDbGFzc2VzIElEcyB0aGF0IG1heSBiZSBzcGVjaWZpZWQgaW4gYSBqb2Igb3JkZXIuAC8AP5QX" + "AAAADAEAAAABAAAAAAAAAAEB/////wAAAAAVYIkKAgAAAAEAGAAAAE1heERvd25sb2FkYWJsZUpvYk9y" + "ZGVycwEByBcALgBEyBcAAAAF/////wEB/////wAAAAAEYYIKBAAAAAEABQAAAFBhdXNlAQFfGwAvAQFf" + "G18bAAABAQIAAAAANQEBAbYTADUBAQHSEwIAAAAXYKkKAgAAAAAADgAAAElucHV0QXJndW1lbnRzAQGp" + "FwAuAESpFwAAlgIAAAABACoBAbMAAAAKAAAASm9iT3JkZXJJRAAM/////wAAAAAClgAAAENvbnRhaW5z" + "IGluZm9ybWF0aW9uIGRlZmluaW5nIHRoZSBqb2Igb3JkZXIgd2l0aCBhbGwgcGFyYW1ldGVycyBhbmQg" + "YW55IG1hdGVyaWFsLCBlcXVpcG1lbnQsIG9yIHBoeXNpY2FsIGFzc2V0IHJlcXVpcmVtZW50cyBhc3Nv" + "Y2lhdGVkIHdpdGggdGhlIG9yZGVyLgEAKgEB6gAAAAcAAABDb21tZW50ABUBAAAAAQAAAAAAAAACzAAA" + "AFRoZSBjb21tZW50IHByb3ZpZGVzIGEgZGVzY3JpcHRpb24gb2Ygd2h5IHRoZSBtZXRob2Qgd2FzIGNh" + "bGxlZC4gSW4gb3JkZXIgdG8gcHJvdmlkZSB0aGUgY29tbWVudCBpbiBzZXZlcmFsIGxhbmd1YWdlcywg" + "aXQgaXMgYW4gYXJyYXkgb2YgTG9jYWxpemVkVGV4dC4gVGhlIGFycmF5IG1heSBiZSBlbXB0eSwgd2hl" + "biBubyBjb21tZW50IGlzIHByb3ZpZGVkLgEAKAEBAAAAAQAAAAIAAAABAf////8AAAAAF2CpCgIAAAAA" + "AA8AAABPdXRwdXRBcmd1bWVudHMBAaoXAC4ARKoXAACWAQAAAAEAKgEBSgAAAAwAAABSZXR1cm5TdGF0" + "dXMACf////8AAAAAAisAAABSZXR1cm5zIHRoZSBzdGF0dXMgb2YgdGhlIG1ldGhvZCBleGVjdXRpb24u" + "AQAoAQEAAAABAAAAAQAAAAEB/////wAAAAA3YIkKAgAAAAEACwAAAFBlcnNvbm5lbElEAQGXFwMAAAAA" + "XQAAAERlZmluZXMgYSByZWFkLW9ubHkgc2V0IG9mIFBlcnNvbm5lbCBJRHMgYW5kIFBlcnNvbiBJRHMg" + "dGhhdCBtYXkgYmUgc3BlY2lmaWVkIGluIGEgam9iIG9yZGVyLgAvAD+XFwAAAAwBAAAAAQAAAAAAAAAB" + "Af////8AAAAAN2CJCgIAAAABAA8AAABQaHlzaWNhbEFzc2V0SUQBAZYXAwAAAABwAAAARGVmaW5lcyBh" + "IHJlYWQtb25seSBzZXQgb2YgUGh5c2ljYWwgQXNzZXQgQ2xhc3MgSURzIGFuZCBQaHlzaWNhbCBBc3Nl" + "dCBJRHMgdGhhdCBtYXkgYmUgc3BlY2lmaWVkIGluIGEgam9iIG9yZGVyLgAvAD+WFwAAAAwBAAAAAQAA" + "AAAAAAABAf////8AAAAABGGCCgQAAAABAAYAAABSZXN1bWUBAWAbAC8BAWAbYBsAAAEBAgAAAAA1AQEB" + "uhMANQEBAdYTAgAAABdgqQoCAAAAAAAOAAAASW5wdXRBcmd1bWVudHMBAasXAC4ARKsXAACWAgAAAAEA" + "KgEBswAAAAoAAABKb2JPcmRlcklEAAz/////AAAAAAKWAAAAQ29udGFpbnMgaW5mb3JtYXRpb24gZGVm" + "aW5pbmcgdGhlIGpvYiBvcmRlciB3aXRoIGFsbCBwYXJhbWV0ZXJzIGFuZCBhbnkgbWF0ZXJpYWwsIGVx" + "dWlwbWVudCwgb3IgcGh5c2ljYWwgYXNzZXQgcmVxdWlyZW1lbnRzIGFzc29jaWF0ZWQgd2l0aCB0aGUg" + "b3JkZXIuAQAqAQHqAAAABwAAAENvbW1lbnQAFQEAAAABAAAAAAAAAALMAAAAVGhlIGNvbW1lbnQgcHJv" + "dmlkZXMgYSBkZXNjcmlwdGlvbiBvZiB3aHkgdGhlIG1ldGhvZCB3YXMgY2FsbGVkLiBJbiBvcmRlciB0" + "byBwcm92aWRlIHRoZSBjb21tZW50IGluIHNldmVyYWwgbGFuZ3VhZ2VzLCBpdCBpcyBhbiBhcnJheSBv" + "ZiBMb2NhbGl6ZWRUZXh0LiBUaGUgYXJyYXkgbWF5IGJlIGVtcHR5LCB3aGVuIG5vIGNvbW1lbnQgaXMg" + "cHJvdmlkZWQuAQAoAQEAAAABAAAAAgAAAAEB/////wAAAAAXYKkKAgAAAAAADwAAAE91dHB1dEFyZ3Vt" + "ZW50cwEBrBcALgBErBcAAJYBAAAAAQAqAQFKAAAADAAAAFJldHVyblN0YXR1cwAJ/////wAAAAACKwAA" + "AFJldHVybnMgdGhlIHN0YXR1cyBvZiB0aGUgbWV0aG9kIGV4ZWN1dGlvbi4BACgBAQAAAAEAAAABAAAA" + "AQH/////AAAAAARhggoEAAAAAQALAAAAUmV2b2tlU3RhcnQBAWUbAC8BAWUbZRsAAAEBAgAAAAA1AQEB" + "sxMANQEBAc8TAgAAABdgqQoCAAAAAAAOAAAASW5wdXRBcmd1bWVudHMBAbUXAC4ARLUXAACWAgAAAAEA" + "KgEBswAAAAoAAABKb2JPcmRlcklEAAz/////AAAAAAKWAAAAQ29udGFpbnMgaW5mb3JtYXRpb24gZGVm" + "aW5pbmcgdGhlIGpvYiBvcmRlciB3aXRoIGFsbCBwYXJhbWV0ZXJzIGFuZCBhbnkgbWF0ZXJpYWwsIGVx" + "dWlwbWVudCwgb3IgcGh5c2ljYWwgYXNzZXQgcmVxdWlyZW1lbnRzIGFzc29jaWF0ZWQgd2l0aCB0aGUg" + "b3JkZXIuAQAqAQHqAAAABwAAAENvbW1lbnQAFQEAAAABAAAAAAAAAALMAAAAVGhlIGNvbW1lbnQgcHJv" + "dmlkZXMgYSBkZXNjcmlwdGlvbiBvZiB3aHkgdGhlIG1ldGhvZCB3YXMgY2FsbGVkLiBJbiBvcmRlciB0" + "byBwcm92aWRlIHRoZSBjb21tZW50IGluIHNldmVyYWwgbGFuZ3VhZ2VzLCBpdCBpcyBhbiBhcnJheSBv" + "ZiBMb2NhbGl6ZWRUZXh0LiBUaGUgYXJyYXkgbWF5IGJlIGVtcHR5LCB3aGVuIG5vIGNvbW1lbnQgaXMg" + "cHJvdmlkZWQuAQAoAQEAAAABAAAAAgAAAAEB/////wAAAAAXYKkKAgAAAAAADwAAAE91dHB1dEFyZ3Vt" + "ZW50cwEBthcALgBEthcAAJYBAAAAAQAqAQFKAAAADAAAAFJldHVyblN0YXR1cwAJ/////wAAAAACKwAA" + "AFJldHVybnMgdGhlIHN0YXR1cyBvZiB0aGUgbWV0aG9kIGV4ZWN1dGlvbi4BACgBAQAAAAEAAAABAAAA" + "AQH/////AAAAAARhggoEAAAAAQAFAAAAU3RhcnQBAV0bAC8BAV0bXRsAAAEBAgAAAAA1AQEBshMANQEB" + "Ac4TAgAAABdgqQoCAAAAAAAOAAAASW5wdXRBcmd1bWVudHMBAaUXAC4ARKUXAACWAgAAAAEAKgEBswAA" + "AAoAAABKb2JPcmRlcklEAAz/////AAAAAAKWAAAAQ29udGFpbnMgaW5mb3JtYXRpb24gZGVmaW5pbmcg" + "dGhlIGpvYiBvcmRlciB3aXRoIGFsbCBwYXJhbWV0ZXJzIGFuZCBhbnkgbWF0ZXJpYWwsIGVxdWlwbWVu" + "dCwgb3IgcGh5c2ljYWwgYXNzZXQgcmVxdWlyZW1lbnRzIGFzc29jaWF0ZWQgd2l0aCB0aGUgb3JkZXIu" + "AQAqAQHqAAAABwAAAENvbW1lbnQAFQEAAAABAAAAAAAAAALMAAAAVGhlIGNvbW1lbnQgcHJvdmlkZXMg" + "YSBkZXNjcmlwdGlvbiBvZiB3aHkgdGhlIG1ldGhvZCB3YXMgY2FsbGVkLiBJbiBvcmRlciB0byBwcm92" + "aWRlIHRoZSBjb21tZW50IGluIHNldmVyYWwgbGFuZ3VhZ2VzLCBpdCBpcyBhbiBhcnJheSBvZiBMb2Nh" + "bGl6ZWRUZXh0LiBUaGUgYXJyYXkgbWF5IGJlIGVtcHR5LCB3aGVuIG5vIGNvbW1lbnQgaXMgcHJvdmlk" + "ZWQuAQAoAQEAAAABAAAAAgAAAAEB/////wAAAAAXYKkKAgAAAAAADwAAAE91dHB1dEFyZ3VtZW50cwEB" + "phcALgBEphcAAJYBAAAAAQAqAQFKAAAADAAAAFJldHVyblN0YXR1cwAJ/////wAAAAACKwAAAFJldHVy" + "bnMgdGhlIHN0YXR1cyBvZiB0aGUgbWV0aG9kIGV4ZWN1dGlvbi4BACgBAQAAAAEAAAABAAAAAQH/////" + "AAAAAARhggoEAAAAAQAEAAAAU3RvcAEBXhsALwEBXhteGwAAAQEEAAAAADUBAQG7EwA1AQEBtxMANQEB" + "AdMTADUBAQHXEwIAAAAXYKkKAgAAAAAADgAAAElucHV0QXJndW1lbnRzAQGnFwAuAESnFwAAlgIAAAAB" + "ACoBAbMAAAAKAAAASm9iT3JkZXJJRAAM/////wAAAAAClgAAAENvbnRhaW5zIGluZm9ybWF0aW9uIGRl" + "ZmluaW5nIHRoZSBqb2Igb3JkZXIgd2l0aCBhbGwgcGFyYW1ldGVycyBhbmQgYW55IG1hdGVyaWFsLCBl" + "cXVpcG1lbnQsIG9yIHBoeXNpY2FsIGFzc2V0IHJlcXVpcmVtZW50cyBhc3NvY2lhdGVkIHdpdGggdGhl" + "IG9yZGVyLgEAKgEB6gAAAAcAAABDb21tZW50ABUBAAAAAQAAAAAAAAACzAAAAFRoZSBjb21tZW50IHBy" + "b3ZpZGVzIGEgZGVzY3JpcHRpb24gb2Ygd2h5IHRoZSBtZXRob2Qgd2FzIGNhbGxlZC4gSW4gb3JkZXIg" + "dG8gcHJvdmlkZSB0aGUgY29tbWVudCBpbiBzZXZlcmFsIGxhbmd1YWdlcywgaXQgaXMgYW4gYXJyYXkg" + "b2YgTG9jYWxpemVkVGV4dC4gVGhlIGFycmF5IG1heSBiZSBlbXB0eSwgd2hlbiBubyBjb21tZW50IGlz" + "IHByb3ZpZGVkLgEAKAEBAAAAAQAAAAIAAAABAf////8AAAAAF2CpCgIAAAAAAA8AAABPdXRwdXRBcmd1" + "bWVudHMBAagXAC4ARKgXAACWAQAAAAEAKgEBSgAAAAwAAABSZXR1cm5TdGF0dXMACf////8AAAAAAisA" + "AABSZXR1cm5zIHRoZSBzdGF0dXMgb2YgdGhlIG1ldGhvZCBleGVjdXRpb24uAQAoAQEAAAABAAAAAQAA" + "AAEB/////wAAAAAEYYIKBAAAAAEABQAAAFN0b3JlAQFZGwAvAQFZG1kbAAABAf////8CAAAAF2CpCgIA" + "AAAAAA4AAABJbnB1dEFyZ3VtZW50cwEBmBcALgBEmBcAAJYCAAAAAQAqAQGzAAAACAAAAEpvYk9yZGVy" + "AQHAC/////8AAAAAApYAAABDb250YWlucyBpbmZvcm1hdGlvbiBkZWZpbmluZyB0aGUgam9iIG9yZGVy" + "IHdpdGggYWxsIHBhcmFtZXRlcnMgYW5kIGFueSBtYXRlcmlhbCwgZXF1aXBtZW50LCBvciBwaHlzaWNh" + "bCBhc3NldCByZXF1aXJlbWVudHMgYXNzb2NpYXRlZCB3aXRoIHRoZSBvcmRlci4BACoBAeoAAAAHAAAA" + "Q29tbWVudAAVAQAAAAEAAAAAAAAAAswAAABUaGUgY29tbWVudCBwcm92aWRlcyBhIGRlc2NyaXB0aW9u" + "IG9mIHdoeSB0aGUgbWV0aG9kIHdhcyBjYWxsZWQuIEluIG9yZGVyIHRvIHByb3ZpZGUgdGhlIGNvbW1l" + "bnQgaW4gc2V2ZXJhbCBsYW5ndWFnZXMsIGl0IGlzIGFuIGFycmF5IG9mIExvY2FsaXplZFRleHQuIFRo" + "ZSBhcnJheSBtYXkgYmUgZW1wdHksIHdoZW4gbm8gY29tbWVudCBpcyBwcm92aWRlZC4BACgBAQAAAAEA" + "AAACAAAAAQH/////AAAAABdgqQoCAAAAAAAPAAAAT3V0cHV0QXJndW1lbnRzAQGZFwAuAESZFwAAlgEA" + "AAABACoBAUoAAAAMAAAAUmV0dXJuU3RhdHVzAAn/////AAAAAAIrAAAAUmV0dXJucyB0aGUgc3RhdHVz" + "IG9mIHRoZSBtZXRob2QgZXhlY3V0aW9uLgEAKAEBAAAAAQAAAAEAAAABAf////8AAAAABGGCCgQAAAAB" + "AA0AAABTdG9yZUFuZFN0YXJ0AQFcGwAvAQFcG1wbAAABAf////8CAAAAF2CpCgIAAAAAAA4AAABJbnB1" + "dEFyZ3VtZW50cwEBoxcALgBEoxcAAJYCAAAAAQAqAQGzAAAACAAAAEpvYk9yZGVyAQHAC/////8AAAAA" + "ApYAAABDb250YWlucyBpbmZvcm1hdGlvbiBkZWZpbmluZyB0aGUgam9iIG9yZGVyIHdpdGggYWxsIHBh" + "cmFtZXRlcnMgYW5kIGFueSBtYXRlcmlhbCwgZXF1aXBtZW50LCBvciBwaHlzaWNhbCBhc3NldCByZXF1" + "aXJlbWVudHMgYXNzb2NpYXRlZCB3aXRoIHRoZSBvcmRlci4BACoBAeoAAAAHAAAAQ29tbWVudAAVAQAA" + "AAEAAAAAAAAAAswAAABUaGUgY29tbWVudCBwcm92aWRlcyBhIGRlc2NyaXB0aW9uIG9mIHdoeSB0aGUg" + "bWV0aG9kIHdhcyBjYWxsZWQuIEluIG9yZGVyIHRvIHByb3ZpZGUgdGhlIGNvbW1lbnQgaW4gc2V2ZXJh" + "bCBsYW5ndWFnZXMsIGl0IGlzIGFuIGFycmF5IG9mIExvY2FsaXplZFRleHQuIFRoZSBhcnJheSBtYXkg" + "YmUgZW1wdHksIHdoZW4gbm8gY29tbWVudCBpcyBwcm92aWRlZC4BACgBAQAAAAEAAAACAAAAAQH/////" + "AAAAABdgqQoCAAAAAAAPAAAAT3V0cHV0QXJndW1lbnRzAQGkFwAuAESkFwAAlgEAAAABACoBAUoAAAAM" + "AAAAUmV0dXJuU3RhdHVzAAn/////AAAAAAIrAAAAUmV0dXJucyB0aGUgc3RhdHVzIG9mIHRoZSBtZXRo" + "b2QgZXhlY3V0aW9uLgEAKAEBAAAAAQAAAAEAAAABAf////8AAAAABGGCCgQAAAABAAYAAABVcGRhdGUB" + "AWEbAC8BAWEbYRsAAAEBBAAAAAA1AQEBtBMANQEBAbETADUBAQHNEwA1AQEB0BMCAAAAF2CpCgIAAAAA" + "AA4AAABJbnB1dEFyZ3VtZW50cwEBrRcALgBErRcAAJYCAAAAAQAqAQGzAAAACAAAAEpvYk9yZGVyAQHA" + "C/////8AAAAAApYAAABDb250YWlucyBpbmZvcm1hdGlvbiBkZWZpbmluZyB0aGUgam9iIG9yZGVyIHdp" + "dGggYWxsIHBhcmFtZXRlcnMgYW5kIGFueSBtYXRlcmlhbCwgZXF1aXBtZW50LCBvciBwaHlzaWNhbCBh" + "c3NldCByZXF1aXJlbWVudHMgYXNzb2NpYXRlZCB3aXRoIHRoZSBvcmRlci4BACoBAeoAAAAHAAAAQ29t" + "bWVudAAVAQAAAAEAAAAAAAAAAswAAABUaGUgY29tbWVudCBwcm92aWRlcyBhIGRlc2NyaXB0aW9uIG9m" + "IHdoeSB0aGUgbWV0aG9kIHdhcyBjYWxsZWQuIEluIG9yZGVyIHRvIHByb3ZpZGUgdGhlIGNvbW1lbnQg" + "aW4gc2V2ZXJhbCBsYW5ndWFnZXMsIGl0IGlzIGFuIGFycmF5IG9mIExvY2FsaXplZFRleHQuIFRoZSBh" + "cnJheSBtYXkgYmUgZW1wdHksIHdoZW4gbm8gY29tbWVudCBpcyBwcm92aWRlZC4BACgBAQAAAAEAAAAC" + "AAAAAQH/////AAAAABdgqQoCAAAAAAAPAAAAT3V0cHV0QXJndW1lbnRzAQGuFwAuAESuFwAAlgEAAAAB" + "ACoBAUoAAAAMAAAAUmV0dXJuU3RhdHVzAAn/////AAAAAAIrAAAAUmV0dXJucyB0aGUgc3RhdHVzIG9m" + "IHRoZSBtZXRob2QgZXhlY3V0aW9uLgEAKAEBAAAAAQAAAAEAAAABAf////8AAAAAN2CJCgIAAAABAAoA" + "AABXb3JrTWFzdGVyAQGSFwMAAAAApgAAAERlZmluZXMgYSByZWFkLW9ubHkgc2V0IG9mIHdvcmsgbWFz" + "dGVyIElEcyB0aGF0IG1heSBiZSBzcGVjaWZpZWQgaW4gYSBqb2Igb3JkZXIsIGFuZCB0aGUgcmVhZC1v" + "bmx5IHNldCBvZiBwYXJhbWV0ZXJzIHRoYXQgbWF5IGJlIHNwZWNpZmllZCBmb3IgYSBzcGVjaWZpYyB3" + "b3JrIG1hc3Rlci4ALwA/khcAAAEBvwsBAAAAAQAAAAAAAAABAf////8AAAAA"; #endregion #endif #endregion #region Public Properties /// public AbortMethodState Abort { get { return m_abortMethod; } set { if (!Object.ReferenceEquals(m_abortMethod, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_abortMethod = value; } } /// public CancelMethodState Cancel { get { return m_cancelMethod; } set { if (!Object.ReferenceEquals(m_cancelMethod, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_cancelMethod = value; } } /// public ClearMethodState Clear { get { return m_clearMethod; } set { if (!Object.ReferenceEquals(m_clearMethod, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_clearMethod = value; } } /// public BaseDataVariableState EquipmentID { get { return m_equipmentID; } set { if (!Object.ReferenceEquals(m_equipmentID, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_equipmentID = value; } } /// public BaseDataVariableState JobOrderList { get { return m_jobOrderList; } set { if (!Object.ReferenceEquals(m_jobOrderList, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_jobOrderList = value; } } /// public BaseDataVariableState MaterialClassID { get { return m_materialClassID; } set { if (!Object.ReferenceEquals(m_materialClassID, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_materialClassID = value; } } /// public BaseDataVariableState MaterialDefinitionID { get { return m_materialDefinitionID; } set { if (!Object.ReferenceEquals(m_materialDefinitionID, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_materialDefinitionID = value; } } /// public PropertyState MaxDownloadableJobOrders { get { return m_maxDownloadableJobOrders; } set { if (!Object.ReferenceEquals(m_maxDownloadableJobOrders, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_maxDownloadableJobOrders = value; } } /// public PauseMethodState Pause { get { return m_pauseMethod; } set { if (!Object.ReferenceEquals(m_pauseMethod, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_pauseMethod = value; } } /// public BaseDataVariableState PersonnelID { get { return m_personnelID; } set { if (!Object.ReferenceEquals(m_personnelID, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_personnelID = value; } } /// public BaseDataVariableState PhysicalAssetID { get { return m_physicalAssetID; } set { if (!Object.ReferenceEquals(m_physicalAssetID, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_physicalAssetID = value; } } /// public ResumeMethodState Resume { get { return m_resumeMethod; } set { if (!Object.ReferenceEquals(m_resumeMethod, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_resumeMethod = value; } } /// public RevokeStartMethodState RevokeStart { get { return m_revokeStartMethod; } set { if (!Object.ReferenceEquals(m_revokeStartMethod, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_revokeStartMethod = value; } } /// public StartMethodState Start { get { return m_startMethod; } set { if (!Object.ReferenceEquals(m_startMethod, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_startMethod = value; } } /// public StopMethodState Stop { get { return m_stopMethod; } set { if (!Object.ReferenceEquals(m_stopMethod, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_stopMethod = value; } } /// public StoreMethodState Store { get { return m_storeMethod; } set { if (!Object.ReferenceEquals(m_storeMethod, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_storeMethod = value; } } /// public StoreAndStartMethodState StoreAndStart { get { return m_storeAndStartMethod; } set { if (!Object.ReferenceEquals(m_storeAndStartMethod, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_storeAndStartMethod = value; } } /// public new UpdateMethodState Update { get { return m_updateMethod; } set { if (!Object.ReferenceEquals(m_updateMethod, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_updateMethod = value; } } /// public BaseDataVariableState WorkMaster { get { return m_workMaster; } set { if (!Object.ReferenceEquals(m_workMaster, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_workMaster = value; } } #endregion #region Overridden Methods /// public override void GetChildren( ISystemContext context, IList children) { if (m_abortMethod != null) { children.Add(m_abortMethod); } if (m_cancelMethod != null) { children.Add(m_cancelMethod); } if (m_clearMethod != null) { children.Add(m_clearMethod); } if (m_equipmentID != null) { children.Add(m_equipmentID); } if (m_jobOrderList != null) { children.Add(m_jobOrderList); } if (m_materialClassID != null) { children.Add(m_materialClassID); } if (m_materialDefinitionID != null) { children.Add(m_materialDefinitionID); } if (m_maxDownloadableJobOrders != null) { children.Add(m_maxDownloadableJobOrders); } if (m_pauseMethod != null) { children.Add(m_pauseMethod); } if (m_personnelID != null) { children.Add(m_personnelID); } if (m_physicalAssetID != null) { children.Add(m_physicalAssetID); } if (m_resumeMethod != null) { children.Add(m_resumeMethod); } if (m_revokeStartMethod != null) { children.Add(m_revokeStartMethod); } if (m_startMethod != null) { children.Add(m_startMethod); } if (m_stopMethod != null) { children.Add(m_stopMethod); } if (m_storeMethod != null) { children.Add(m_storeMethod); } if (m_storeAndStartMethod != null) { children.Add(m_storeAndStartMethod); } if (m_updateMethod != null) { children.Add(m_updateMethod); } if (m_workMaster != null) { children.Add(m_workMaster); } base.GetChildren(context, children); } /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.Abort: { if (createOrReplace) { if (Abort == null) { if (replacement == null) { Abort = new AbortMethodState(this); } else { Abort = (AbortMethodState)replacement; } } } instance = Abort; break; } case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.Cancel: { if (createOrReplace) { if (Cancel == null) { if (replacement == null) { Cancel = new CancelMethodState(this); } else { Cancel = (CancelMethodState)replacement; } } } instance = Cancel; break; } case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.Clear: { if (createOrReplace) { if (Clear == null) { if (replacement == null) { Clear = new ClearMethodState(this); } else { Clear = (ClearMethodState)replacement; } } } instance = Clear; break; } case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.EquipmentID: { if (createOrReplace) { if (EquipmentID == null) { if (replacement == null) { EquipmentID = new BaseDataVariableState(this); } else { EquipmentID = (BaseDataVariableState)replacement; } } } instance = EquipmentID; break; } case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.JobOrderList: { if (createOrReplace) { if (JobOrderList == null) { if (replacement == null) { JobOrderList = new BaseDataVariableState(this); } else { JobOrderList = (BaseDataVariableState)replacement; } } } instance = JobOrderList; break; } case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.MaterialClassID: { if (createOrReplace) { if (MaterialClassID == null) { if (replacement == null) { MaterialClassID = new BaseDataVariableState(this); } else { MaterialClassID = (BaseDataVariableState)replacement; } } } instance = MaterialClassID; break; } case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.MaterialDefinitionID: { if (createOrReplace) { if (MaterialDefinitionID == null) { if (replacement == null) { MaterialDefinitionID = new BaseDataVariableState(this); } else { MaterialDefinitionID = (BaseDataVariableState)replacement; } } } instance = MaterialDefinitionID; break; } case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.MaxDownloadableJobOrders: { if (createOrReplace) { if (MaxDownloadableJobOrders == null) { if (replacement == null) { MaxDownloadableJobOrders = new PropertyState(this); } else { MaxDownloadableJobOrders = (PropertyState)replacement; } } } instance = MaxDownloadableJobOrders; break; } case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.Pause: { if (createOrReplace) { if (Pause == null) { if (replacement == null) { Pause = new PauseMethodState(this); } else { Pause = (PauseMethodState)replacement; } } } instance = Pause; break; } case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.PersonnelID: { if (createOrReplace) { if (PersonnelID == null) { if (replacement == null) { PersonnelID = new BaseDataVariableState(this); } else { PersonnelID = (BaseDataVariableState)replacement; } } } instance = PersonnelID; break; } case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.PhysicalAssetID: { if (createOrReplace) { if (PhysicalAssetID == null) { if (replacement == null) { PhysicalAssetID = new BaseDataVariableState(this); } else { PhysicalAssetID = (BaseDataVariableState)replacement; } } } instance = PhysicalAssetID; break; } case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.Resume: { if (createOrReplace) { if (Resume == null) { if (replacement == null) { Resume = new ResumeMethodState(this); } else { Resume = (ResumeMethodState)replacement; } } } instance = Resume; break; } case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.RevokeStart: { if (createOrReplace) { if (RevokeStart == null) { if (replacement == null) { RevokeStart = new RevokeStartMethodState(this); } else { RevokeStart = (RevokeStartMethodState)replacement; } } } instance = RevokeStart; break; } case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.Start: { if (createOrReplace) { if (Start == null) { if (replacement == null) { Start = new StartMethodState(this); } else { Start = (StartMethodState)replacement; } } } instance = Start; break; } case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.Stop: { if (createOrReplace) { if (Stop == null) { if (replacement == null) { Stop = new StopMethodState(this); } else { Stop = (StopMethodState)replacement; } } } instance = Stop; break; } case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.Store: { if (createOrReplace) { if (Store == null) { if (replacement == null) { Store = new StoreMethodState(this); } else { Store = (StoreMethodState)replacement; } } } instance = Store; break; } case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.StoreAndStart: { if (createOrReplace) { if (StoreAndStart == null) { if (replacement == null) { StoreAndStart = new StoreAndStartMethodState(this); } else { StoreAndStart = (StoreAndStartMethodState)replacement; } } } instance = StoreAndStart; break; } case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.Update: { if (createOrReplace) { if (Update == null) { if (replacement == null) { Update = new UpdateMethodState(this); } else { Update = (UpdateMethodState)replacement; } } } instance = Update; break; } case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.WorkMaster: { if (createOrReplace) { if (WorkMaster == null) { if (replacement == null) { WorkMaster = new BaseDataVariableState(this); } else { WorkMaster = (BaseDataVariableState)replacement; } } } instance = WorkMaster; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private AbortMethodState m_abortMethod; private CancelMethodState m_cancelMethod; private ClearMethodState m_clearMethod; private BaseDataVariableState m_equipmentID; private BaseDataVariableState m_jobOrderList; private BaseDataVariableState m_materialClassID; private BaseDataVariableState m_materialDefinitionID; private PropertyState m_maxDownloadableJobOrders; private PauseMethodState m_pauseMethod; private BaseDataVariableState m_personnelID; private BaseDataVariableState m_physicalAssetID; private ResumeMethodState m_resumeMethod; private RevokeStartMethodState m_revokeStartMethod; private StartMethodState m_startMethod; private StopMethodState m_stopMethod; private StoreMethodState m_storeMethod; private StoreAndStartMethodState m_storeAndStartMethod; private UpdateMethodState m_updateMethod; private BaseDataVariableState m_workMaster; #endregion } #endif #endregion #region ISA95JobOrderReceiverSubStatesTypeState Class #if (!OPCUA_EXCLUDE_ISA95JobOrderReceiverSubStatesTypeState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class ISA95JobOrderReceiverSubStatesTypeState : ISA95JobOrderReceiverObjectTypeState { #region Constructors /// public ISA95JobOrderReceiverSubStatesTypeState(NodeState parent) : base(parent) { } /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(UAModel.ISA95_JOBCONTROL_V2.ObjectTypes.ISA95JobOrderReceiverSubStatesType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); if (AllowedToStartSubstates != null) { AllowedToStartSubstates.Initialize(context, AllowedToStartSubstates_InitializationString); } if (EndedSubstates != null) { EndedSubstates.Initialize(context, EndedSubstates_InitializationString); } if (InterruptedSubstates != null) { InterruptedSubstates.Initialize(context, InterruptedSubstates_InitializationString); } if (NotAllowedToStartSubstates != null) { NotAllowedToStartSubstates.Initialize(context, NotAllowedToStartSubstates_InitializationString); } } #region Initialization String private const string AllowedToStartSubstates_InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "JGCACgEAAAABABcAAABBbGxvd2VkVG9TdGFydFN1YnN0YXRlcwEB2RMDAAAAABsAAABTdWJzdGF0ZXMg" + "b2YgQWxsb3dlZFRvU3RhcnQALwEB6QPZEwAAAQAAAAB1AQEByBMBAAAAFWCJCgIAAAAAAAwAAABDdXJy" + "ZW50U3RhdGUBAXMXAC8BAMgKcxcAAAAV/////wEB/////wEAAAAVYIkKAgAAAAAAAgAAAElkAQF0FwAu" + "AER0FwAAABH/////AQH/////AAAAAA=="; private const string EndedSubstates_InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "JGCACgEAAAABAA4AAABFbmRlZFN1YnN0YXRlcwEB2hMDAAAAABIAAABTdWJzdGF0ZXMgb2YgRW5kZWQA" + "LwEB7QPaEwAAAQAAAAB1AQEByxMBAAAAFWCJCgIAAAAAAAwAAABDdXJyZW50U3RhdGUBAXUXAC8BAMgK" + "dRcAAAAV/////wEB/////wEAAAAVYIkKAgAAAAAAAgAAAElkAQF2FwAuAER2FwAAABH/////AQH/////" + "AAAAAA=="; private const string InterruptedSubstates_InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "JGCACgEAAAABABQAAABJbnRlcnJ1cHRlZFN1YnN0YXRlcwEB2xMDAAAAABgAAABTdWJzdGF0ZXMgb2Yg" + "SW50ZXJydXB0ZWQALwEB7wPbEwAAAQAAAAB1AQEByhMBAAAAFWCJCgIAAAAAAAwAAABDdXJyZW50U3Rh" + "dGUBAXcXAC8BAMgKdxcAAAAV/////wEB/////wEAAAAVYIkKAgAAAAAAAgAAAElkAQF4FwAuAER4FwAA" + "ABH/////AQH/////AAAAAA=="; private const string NotAllowedToStartSubstates_InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "JGCACgEAAAABABoAAABOb3RBbGxvd2VkVG9TdGFydFN1YnN0YXRlcwEB2BMDAAAAAB4AAABTdWJzdGF0" + "ZXMgb2YgTm90QWxsb3dlZFRvU3RhcnQALwEB6QPYEwAAAQAAAAB1AQEBxxMBAAAAFWCJCgIAAAAAAAwA" + "AABDdXJyZW50U3RhdGUBAXEXAC8BAMgKcRcAAAAV/////wEB/////wEAAAAVYIkKAgAAAAAAAgAAAElk" + "AQFyFwAuAERyFwAAABH/////AQH/////AAAAAA=="; private const string InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGCAAgEAAAABACoAAABJU0E5NUpvYk9yZGVyUmVjZWl2ZXJTdWJTdGF0ZXNUeXBlSW5zdGFuY2UBAfAD" + "AQHwA/ADAAD/////DQAAABVgiQgCAAAAAAAMAAAAQ3VycmVudFN0YXRlAQEAAAAvAQDICgAV/////wEB" + "/////wEAAAAVYIkIAgAAAAAAAgAAAElkAQEAAAAuAEQAEf////8BAf////8AAAAAN2CJCgIAAAABAAsA" + "AABFcXVpcG1lbnRJRAEBlRcDAAAAAGYAAABEZWZpbmVzIGEgcmVhZC1vbmx5IHNldCBvZiBFcXVpcG1l" + "bnQgQ2xhc3MgSURzIGFuZCBFcXVpcG1lbnQgSURzIHRoYXQgbWF5IGJlIHNwZWNpZmllZCBpbiBhIGpv" + "YiBvcmRlci4ALwA/lRcAAAAMAQAAAAEAAAAAAAAAAQH/////AAAAADdgiQoCAAAAAQAMAAAASm9iT3Jk" + "ZXJMaXN0AQGRFwMAAAAATAAAAERlZmluZXMgYSByZWFkLW9ubHkgbGlzdCBvZiBqb2Igb3JkZXIgaW5m" + "b3JtYXRpb24gYXZhaWxhYmxlIGZyb20gdGhlIHNlcnZlci4ALwA/kRcAAAEBxwsBAAAAAQAAAAAAAAAB" + "Af////8AAAAAN2CJCgIAAAABAA8AAABNYXRlcmlhbENsYXNzSUQBAZMXAwAAAABVAAAARGVmaW5lcyBh" + "IHJlYWQtb25seSBzZXQgb2YgTWF0ZXJpYWwgQ2xhc3NlcyBJRHMgdGhhdCBtYXkgYmUgc3BlY2lmaWVk" + "IGluIGEgam9iIG9yZGVyLgAvAD+TFwAAAAwBAAAAAQAAAAAAAAABAf////8AAAAAN2CJCgIAAAABABQA" + "AABNYXRlcmlhbERlZmluaXRpb25JRAEBlBcDAAAAAFUAAABEZWZpbmVzIGEgcmVhZC1vbmx5IHNldCBv" + "ZiBNYXRlcmlhbCBDbGFzc2VzIElEcyB0aGF0IG1heSBiZSBzcGVjaWZpZWQgaW4gYSBqb2Igb3JkZXIu" + "AC8AP5QXAAAADAEAAAABAAAAAAAAAAEB/////wAAAAAVYIkKAgAAAAEAGAAAAE1heERvd25sb2FkYWJs" + "ZUpvYk9yZGVycwEByBcALgBEyBcAAAAF/////wEB/////wAAAAA3YIkKAgAAAAEACwAAAFBlcnNvbm5l" + "bElEAQGXFwMAAAAAXQAAAERlZmluZXMgYSByZWFkLW9ubHkgc2V0IG9mIFBlcnNvbm5lbCBJRHMgYW5k" + "IFBlcnNvbiBJRHMgdGhhdCBtYXkgYmUgc3BlY2lmaWVkIGluIGEgam9iIG9yZGVyLgAvAD+XFwAAAAwB" + "AAAAAQAAAAAAAAABAf////8AAAAAN2CJCgIAAAABAA8AAABQaHlzaWNhbEFzc2V0SUQBAZYXAwAAAABw" + "AAAARGVmaW5lcyBhIHJlYWQtb25seSBzZXQgb2YgUGh5c2ljYWwgQXNzZXQgQ2xhc3MgSURzIGFuZCBQ" + "aHlzaWNhbCBBc3NldCBJRHMgdGhhdCBtYXkgYmUgc3BlY2lmaWVkIGluIGEgam9iIG9yZGVyLgAvAD+W" + "FwAAAAwBAAAAAQAAAAAAAAABAf////8AAAAAN2CJCgIAAAABAAoAAABXb3JrTWFzdGVyAQGSFwMAAAAA" + "pgAAAERlZmluZXMgYSByZWFkLW9ubHkgc2V0IG9mIHdvcmsgbWFzdGVyIElEcyB0aGF0IG1heSBiZSBz" + "cGVjaWZpZWQgaW4gYSBqb2Igb3JkZXIsIGFuZCB0aGUgcmVhZC1vbmx5IHNldCBvZiBwYXJhbWV0ZXJz" + "IHRoYXQgbWF5IGJlIHNwZWNpZmllZCBmb3IgYSBzcGVjaWZpYyB3b3JrIG1hc3Rlci4ALwA/khcAAAEB" + "vwsBAAAAAQAAAAAAAAABAf////8AAAAAJGCACgEAAAABABcAAABBbGxvd2VkVG9TdGFydFN1YnN0YXRl" + "cwEB2RMDAAAAABsAAABTdWJzdGF0ZXMgb2YgQWxsb3dlZFRvU3RhcnQALwEB6QPZEwAAAQAAAAB1AQEB" + "yBMBAAAAFWCJCgIAAAAAAAwAAABDdXJyZW50U3RhdGUBAXMXAC8BAMgKcxcAAAAV/////wEB/////wEA" + "AAAVYIkKAgAAAAAAAgAAAElkAQF0FwAuAER0FwAAABH/////AQH/////AAAAACRggAoBAAAAAQAOAAAA" + "RW5kZWRTdWJzdGF0ZXMBAdoTAwAAAAASAAAAU3Vic3RhdGVzIG9mIEVuZGVkAC8BAe0D2hMAAAEAAAAA" + "dQEBAcsTAQAAABVgiQoCAAAAAAAMAAAAQ3VycmVudFN0YXRlAQF1FwAvAQDICnUXAAAAFf////8BAf//" + "//8BAAAAFWCJCgIAAAAAAAIAAABJZAEBdhcALgBEdhcAAAAR/////wEB/////wAAAAAkYIAKAQAAAAEA" + "FAAAAEludGVycnVwdGVkU3Vic3RhdGVzAQHbEwMAAAAAGAAAAFN1YnN0YXRlcyBvZiBJbnRlcnJ1cHRl" + "ZAAvAQHvA9sTAAABAAAAAHUBAQHKEwEAAAAVYIkKAgAAAAAADAAAAEN1cnJlbnRTdGF0ZQEBdxcALwEA" + "yAp3FwAAABX/////AQH/////AQAAABVgiQoCAAAAAAACAAAASWQBAXgXAC4ARHgXAAAAEf////8BAf//" + "//8AAAAAJGCACgEAAAABABoAAABOb3RBbGxvd2VkVG9TdGFydFN1YnN0YXRlcwEB2BMDAAAAAB4AAABT" + "dWJzdGF0ZXMgb2YgTm90QWxsb3dlZFRvU3RhcnQALwEB6QPYEwAAAQAAAAB1AQEBxxMBAAAAFWCJCgIA" + "AAAAAAwAAABDdXJyZW50U3RhdGUBAXEXAC8BAMgKcRcAAAAV/////wEB/////wEAAAAVYIkKAgAAAAAA" + "AgAAAElkAQFyFwAuAERyFwAAABH/////AQH/////AAAAAA=="; #endregion #endif #endregion #region Public Properties /// public ISA95PrepareStateMachineTypeState AllowedToStartSubstates { get { return m_allowedToStartSubstates; } set { if (!Object.ReferenceEquals(m_allowedToStartSubstates, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_allowedToStartSubstates = value; } } /// public ISA95EndedStateMachineTypeState EndedSubstates { get { return m_endedSubstates; } set { if (!Object.ReferenceEquals(m_endedSubstates, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_endedSubstates = value; } } /// public ISA95InterruptedStateMachineTypeState InterruptedSubstates { get { return m_interruptedSubstates; } set { if (!Object.ReferenceEquals(m_interruptedSubstates, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_interruptedSubstates = value; } } /// public ISA95PrepareStateMachineTypeState NotAllowedToStartSubstates { get { return m_notAllowedToStartSubstates; } set { if (!Object.ReferenceEquals(m_notAllowedToStartSubstates, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_notAllowedToStartSubstates = value; } } #endregion #region Overridden Methods /// public override void GetChildren( ISystemContext context, IList children) { if (m_allowedToStartSubstates != null) { children.Add(m_allowedToStartSubstates); } if (m_endedSubstates != null) { children.Add(m_endedSubstates); } if (m_interruptedSubstates != null) { children.Add(m_interruptedSubstates); } if (m_notAllowedToStartSubstates != null) { children.Add(m_notAllowedToStartSubstates); } base.GetChildren(context, children); } /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.AllowedToStartSubstates: { if (createOrReplace) { if (AllowedToStartSubstates == null) { if (replacement == null) { AllowedToStartSubstates = new ISA95PrepareStateMachineTypeState(this); } else { AllowedToStartSubstates = (ISA95PrepareStateMachineTypeState)replacement; } } } instance = AllowedToStartSubstates; break; } case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.EndedSubstates: { if (createOrReplace) { if (EndedSubstates == null) { if (replacement == null) { EndedSubstates = new ISA95EndedStateMachineTypeState(this); } else { EndedSubstates = (ISA95EndedStateMachineTypeState)replacement; } } } instance = EndedSubstates; break; } case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.InterruptedSubstates: { if (createOrReplace) { if (InterruptedSubstates == null) { if (replacement == null) { InterruptedSubstates = new ISA95InterruptedStateMachineTypeState(this); } else { InterruptedSubstates = (ISA95InterruptedStateMachineTypeState)replacement; } } } instance = InterruptedSubstates; break; } case UAModel.ISA95_JOBCONTROL_V2.BrowseNames.NotAllowedToStartSubstates: { if (createOrReplace) { if (NotAllowedToStartSubstates == null) { if (replacement == null) { NotAllowedToStartSubstates = new ISA95PrepareStateMachineTypeState(this); } else { NotAllowedToStartSubstates = (ISA95PrepareStateMachineTypeState)replacement; } } } instance = NotAllowedToStartSubstates; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private ISA95PrepareStateMachineTypeState m_allowedToStartSubstates; private ISA95EndedStateMachineTypeState m_endedSubstates; private ISA95InterruptedStateMachineTypeState m_interruptedSubstates; private ISA95PrepareStateMachineTypeState m_notAllowedToStartSubstates; #endregion } #endif #endregion #region ISA95PrepareStateMachineTypeState Class #if (!OPCUA_EXCLUDE_ISA95PrepareStateMachineTypeState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class ISA95PrepareStateMachineTypeState : FiniteStateMachineState { #region Constructors /// public ISA95PrepareStateMachineTypeState(NodeState parent) : base(parent) { } /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(UAModel.ISA95_JOBCONTROL_V2.ObjectTypes.ISA95PrepareStateMachineType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGCAAgEAAAABACQAAABJU0E5NVByZXBhcmVTdGF0ZU1hY2hpbmVUeXBlSW5zdGFuY2UBAekDAQHpA+kD" + "AAD/////AQAAABVgiQgCAAAAAAAMAAAAQ3VycmVudFN0YXRlAQEAAAAvAQDICgAV/////wEB/////wEA" + "AAAVYIkIAgAAAAAAAgAAAElkAQEAAAAuAEQAEf////8BAf////8AAAAA"; #endregion #endif #endregion #region Public Properties #endregion #region Overridden Methods #endregion #region Private Fields #endregion } #endif #endregion #region RequestJobResponseByJobOrderIDMethodState Class #if (!OPCUA_EXCLUDE_RequestJobResponseByJobOrderIDMethodState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class RequestJobResponseByJobOrderIDMethodState : MethodState { #region Constructors /// public RequestJobResponseByJobOrderIDMethodState(NodeState parent) : base(parent) { } /// public new static NodeState Construct(NodeState parent) { return new RequestJobResponseByJobOrderIDMethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGGCAAQAAAABACgAAABSZXF1ZXN0Sm9iUmVzcG9uc2VCeUpvYk9yZGVySURNZXRob2RUeXBlAQEAAAEB" + "AAABAf////8AAAAA"; #endregion #endif #endregion #region Event Callbacks /// public RequestJobResponseByJobOrderIDMethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult _result = null; string jobOrderID = (string)_inputArguments[0]; ISA95JobResponseDataType jobResponse = (ISA95JobResponseDataType)_outputArguments[0]; ulong returnStatus = (ulong)_outputArguments[1]; if (OnCall != null) { _result = OnCall( _context, this, _objectId, jobOrderID, ref jobResponse, ref returnStatus); } _outputArguments[0] = jobResponse; _outputArguments[1] = returnStatus; return _result; } #endregion #region Private Fields #endregion } /// /// public delegate ServiceResult RequestJobResponseByJobOrderIDMethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, string jobOrderID, ref ISA95JobResponseDataType jobResponse, ref ulong returnStatus); #endif #endregion #region RequestJobResponseByJobOrderStateMethodState Class #if (!OPCUA_EXCLUDE_RequestJobResponseByJobOrderStateMethodState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class RequestJobResponseByJobOrderStateMethodState : MethodState { #region Constructors /// public RequestJobResponseByJobOrderStateMethodState(NodeState parent) : base(parent) { } /// public new static NodeState Construct(NodeState parent) { return new RequestJobResponseByJobOrderStateMethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGGCAAQAAAABACsAAABSZXF1ZXN0Sm9iUmVzcG9uc2VCeUpvYk9yZGVyU3RhdGVNZXRob2RUeXBlAQEA" + "AAEBAAABAf////8AAAAA"; #endregion #endif #endregion #region Event Callbacks /// public RequestJobResponseByJobOrderStateMethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult _result = null; ISA95StateDataType[] jobOrderState = (ISA95StateDataType[])ExtensionObject.ToArray(_inputArguments[0], typeof(ISA95StateDataType)); ISA95JobResponseDataType[] jobResponses = (ISA95JobResponseDataType[])_outputArguments[0]; ulong returnStatus = (ulong)_outputArguments[1]; if (OnCall != null) { _result = OnCall( _context, this, _objectId, jobOrderState, ref jobResponses, ref returnStatus); } _outputArguments[0] = jobResponses; _outputArguments[1] = returnStatus; return _result; } #endregion #region Private Fields #endregion } /// /// public delegate ServiceResult RequestJobResponseByJobOrderStateMethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, ISA95StateDataType[] jobOrderState, ref ISA95JobResponseDataType[] jobResponses, ref ulong returnStatus); #endif #endregion #region ReceiveJobResponseMethodState Class #if (!OPCUA_EXCLUDE_ReceiveJobResponseMethodState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class ReceiveJobResponseMethodState : MethodState { #region Constructors /// public ReceiveJobResponseMethodState(NodeState parent) : base(parent) { } /// public new static NodeState Construct(NodeState parent) { return new ReceiveJobResponseMethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGGCAAQAAAABABwAAABSZWNlaXZlSm9iUmVzcG9uc2VNZXRob2RUeXBlAQEAAAEBAAABAf////8AAAAA"; #endregion #endif #endregion #region Event Callbacks /// public ReceiveJobResponseMethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult _result = null; ISA95JobResponseDataType jobResponse = (ISA95JobResponseDataType)ExtensionObject.ToEncodeable((ExtensionObject)_inputArguments[0]); ulong returnStatus = (ulong)_outputArguments[0]; if (OnCall != null) { _result = OnCall( _context, this, _objectId, jobResponse, ref returnStatus); } _outputArguments[0] = returnStatus; return _result; } #endregion #region Private Fields #endregion } /// /// public delegate ServiceResult ReceiveJobResponseMethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, ISA95JobResponseDataType jobResponse, ref ulong returnStatus); #endif #endregion #region AbortMethodState Class #if (!OPCUA_EXCLUDE_AbortMethodState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class AbortMethodState : MethodState { #region Constructors /// public AbortMethodState(NodeState parent) : base(parent) { } /// public new static NodeState Construct(NodeState parent) { return new AbortMethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGGCAAQAAAABAA8AAABBYm9ydE1ldGhvZFR5cGUBAQAAAQEAAAEB/////wAAAAA="; #endregion #endif #endregion #region Event Callbacks /// public AbortMethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult _result = null; string jobOrderID = (string)_inputArguments[0]; LocalizedText[] comment = (LocalizedText[])_inputArguments[1]; ulong returnStatus = (ulong)_outputArguments[0]; if (OnCall != null) { _result = OnCall( _context, this, _objectId, jobOrderID, comment, ref returnStatus); } _outputArguments[0] = returnStatus; return _result; } #endregion #region Private Fields #endregion } /// /// public delegate ServiceResult AbortMethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, string jobOrderID, LocalizedText[] comment, ref ulong returnStatus); #endif #endregion #region CancelMethodState Class #if (!OPCUA_EXCLUDE_CancelMethodState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class CancelMethodState : MethodState { #region Constructors /// public CancelMethodState(NodeState parent) : base(parent) { } /// public new static NodeState Construct(NodeState parent) { return new CancelMethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGGCAAQAAAABABAAAABDYW5jZWxNZXRob2RUeXBlAQEAAAEBAAABAf////8AAAAA"; #endregion #endif #endregion #region Event Callbacks /// public CancelMethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult _result = null; string jobOrderID = (string)_inputArguments[0]; LocalizedText[] comment = (LocalizedText[])_inputArguments[1]; ulong returnStatus = (ulong)_outputArguments[0]; if (OnCall != null) { _result = OnCall( _context, this, _objectId, jobOrderID, comment, ref returnStatus); } _outputArguments[0] = returnStatus; return _result; } #endregion #region Private Fields #endregion } /// /// public delegate ServiceResult CancelMethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, string jobOrderID, LocalizedText[] comment, ref ulong returnStatus); #endif #endregion #region ClearMethodState Class #if (!OPCUA_EXCLUDE_ClearMethodState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class ClearMethodState : MethodState { #region Constructors /// public ClearMethodState(NodeState parent) : base(parent) { } /// public new static NodeState Construct(NodeState parent) { return new ClearMethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGGCAAQAAAABAA8AAABDbGVhck1ldGhvZFR5cGUBAQAAAQEAAAEB/////wAAAAA="; #endregion #endif #endregion #region Event Callbacks /// public ClearMethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult _result = null; string jobOrderID = (string)_inputArguments[0]; LocalizedText[] comment = (LocalizedText[])_inputArguments[1]; ulong returnStatus = (ulong)_outputArguments[0]; if (OnCall != null) { _result = OnCall( _context, this, _objectId, jobOrderID, comment, ref returnStatus); } _outputArguments[0] = returnStatus; return _result; } #endregion #region Private Fields #endregion } /// /// public delegate ServiceResult ClearMethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, string jobOrderID, LocalizedText[] comment, ref ulong returnStatus); #endif #endregion #region PauseMethodState Class #if (!OPCUA_EXCLUDE_PauseMethodState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class PauseMethodState : MethodState { #region Constructors /// public PauseMethodState(NodeState parent) : base(parent) { } /// public new static NodeState Construct(NodeState parent) { return new PauseMethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGGCAAQAAAABAA8AAABQYXVzZU1ldGhvZFR5cGUBAQAAAQEAAAEB/////wAAAAA="; #endregion #endif #endregion #region Event Callbacks /// public PauseMethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult _result = null; string jobOrderID = (string)_inputArguments[0]; LocalizedText[] comment = (LocalizedText[])_inputArguments[1]; ulong returnStatus = (ulong)_outputArguments[0]; if (OnCall != null) { _result = OnCall( _context, this, _objectId, jobOrderID, comment, ref returnStatus); } _outputArguments[0] = returnStatus; return _result; } #endregion #region Private Fields #endregion } /// /// public delegate ServiceResult PauseMethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, string jobOrderID, LocalizedText[] comment, ref ulong returnStatus); #endif #endregion #region ResumeMethodState Class #if (!OPCUA_EXCLUDE_ResumeMethodState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class ResumeMethodState : MethodState { #region Constructors /// public ResumeMethodState(NodeState parent) : base(parent) { } /// public new static NodeState Construct(NodeState parent) { return new ResumeMethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGGCAAQAAAABABAAAABSZXN1bWVNZXRob2RUeXBlAQEAAAEBAAABAf////8AAAAA"; #endregion #endif #endregion #region Event Callbacks /// public ResumeMethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult _result = null; string jobOrderID = (string)_inputArguments[0]; LocalizedText[] comment = (LocalizedText[])_inputArguments[1]; ulong returnStatus = (ulong)_outputArguments[0]; if (OnCall != null) { _result = OnCall( _context, this, _objectId, jobOrderID, comment, ref returnStatus); } _outputArguments[0] = returnStatus; return _result; } #endregion #region Private Fields #endregion } /// /// public delegate ServiceResult ResumeMethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, string jobOrderID, LocalizedText[] comment, ref ulong returnStatus); #endif #endregion #region RevokeStartMethodState Class #if (!OPCUA_EXCLUDE_RevokeStartMethodState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class RevokeStartMethodState : MethodState { #region Constructors /// public RevokeStartMethodState(NodeState parent) : base(parent) { } /// public new static NodeState Construct(NodeState parent) { return new RevokeStartMethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGGCAAQAAAABABUAAABSZXZva2VTdGFydE1ldGhvZFR5cGUBAQAAAQEAAAEB/////wAAAAA="; #endregion #endif #endregion #region Event Callbacks /// public RevokeStartMethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult _result = null; string jobOrderID = (string)_inputArguments[0]; LocalizedText[] comment = (LocalizedText[])_inputArguments[1]; ulong returnStatus = (ulong)_outputArguments[0]; if (OnCall != null) { _result = OnCall( _context, this, _objectId, jobOrderID, comment, ref returnStatus); } _outputArguments[0] = returnStatus; return _result; } #endregion #region Private Fields #endregion } /// /// public delegate ServiceResult RevokeStartMethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, string jobOrderID, LocalizedText[] comment, ref ulong returnStatus); #endif #endregion #region StartMethodState Class #if (!OPCUA_EXCLUDE_StartMethodState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class StartMethodState : MethodState { #region Constructors /// public StartMethodState(NodeState parent) : base(parent) { } /// public new static NodeState Construct(NodeState parent) { return new StartMethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGGCAAQAAAABAA8AAABTdGFydE1ldGhvZFR5cGUBAQAAAQEAAAEB/////wAAAAA="; #endregion #endif #endregion #region Event Callbacks /// public StartMethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult _result = null; string jobOrderID = (string)_inputArguments[0]; LocalizedText[] comment = (LocalizedText[])_inputArguments[1]; ulong returnStatus = (ulong)_outputArguments[0]; if (OnCall != null) { _result = OnCall( _context, this, _objectId, jobOrderID, comment, ref returnStatus); } _outputArguments[0] = returnStatus; return _result; } #endregion #region Private Fields #endregion } /// /// public delegate ServiceResult StartMethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, string jobOrderID, LocalizedText[] comment, ref ulong returnStatus); #endif #endregion #region StopMethodState Class #if (!OPCUA_EXCLUDE_StopMethodState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class StopMethodState : MethodState { #region Constructors /// public StopMethodState(NodeState parent) : base(parent) { } /// public new static NodeState Construct(NodeState parent) { return new StopMethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGGCAAQAAAABAA4AAABTdG9wTWV0aG9kVHlwZQEBAAABAQAAAQH/////AAAAAA=="; #endregion #endif #endregion #region Event Callbacks /// public StopMethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult _result = null; string jobOrderID = (string)_inputArguments[0]; LocalizedText[] comment = (LocalizedText[])_inputArguments[1]; ulong returnStatus = (ulong)_outputArguments[0]; if (OnCall != null) { _result = OnCall( _context, this, _objectId, jobOrderID, comment, ref returnStatus); } _outputArguments[0] = returnStatus; return _result; } #endregion #region Private Fields #endregion } /// /// public delegate ServiceResult StopMethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, string jobOrderID, LocalizedText[] comment, ref ulong returnStatus); #endif #endregion #region StoreMethodState Class #if (!OPCUA_EXCLUDE_StoreMethodState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class StoreMethodState : MethodState { #region Constructors /// public StoreMethodState(NodeState parent) : base(parent) { } /// public new static NodeState Construct(NodeState parent) { return new StoreMethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGGCAAQAAAABAA8AAABTdG9yZU1ldGhvZFR5cGUBAQAAAQEAAAEB/////wAAAAA="; #endregion #endif #endregion #region Event Callbacks /// public StoreMethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult _result = null; ISA95JobOrderDataType jobOrder = (ISA95JobOrderDataType)ExtensionObject.ToEncodeable((ExtensionObject)_inputArguments[0]); LocalizedText[] comment = (LocalizedText[])_inputArguments[1]; ulong returnStatus = (ulong)_outputArguments[0]; if (OnCall != null) { _result = OnCall( _context, this, _objectId, jobOrder, comment, ref returnStatus); } _outputArguments[0] = returnStatus; return _result; } #endregion #region Private Fields #endregion } /// /// public delegate ServiceResult StoreMethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, ISA95JobOrderDataType jobOrder, LocalizedText[] comment, ref ulong returnStatus); #endif #endregion #region StoreAndStartMethodState Class #if (!OPCUA_EXCLUDE_StoreAndStartMethodState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class StoreAndStartMethodState : MethodState { #region Constructors /// public StoreAndStartMethodState(NodeState parent) : base(parent) { } /// public new static NodeState Construct(NodeState parent) { return new StoreAndStartMethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGGCAAQAAAABABcAAABTdG9yZUFuZFN0YXJ0TWV0aG9kVHlwZQEBAAABAQAAAQH/////AAAAAA=="; #endregion #endif #endregion #region Event Callbacks /// public StoreAndStartMethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult _result = null; ISA95JobOrderDataType jobOrder = (ISA95JobOrderDataType)ExtensionObject.ToEncodeable((ExtensionObject)_inputArguments[0]); LocalizedText[] comment = (LocalizedText[])_inputArguments[1]; ulong returnStatus = (ulong)_outputArguments[0]; if (OnCall != null) { _result = OnCall( _context, this, _objectId, jobOrder, comment, ref returnStatus); } _outputArguments[0] = returnStatus; return _result; } #endregion #region Private Fields #endregion } /// /// public delegate ServiceResult StoreAndStartMethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, ISA95JobOrderDataType jobOrder, LocalizedText[] comment, ref ulong returnStatus); #endif #endregion #region UpdateMethodState Class #if (!OPCUA_EXCLUDE_UpdateMethodState) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class UpdateMethodState : MethodState { #region Constructors /// public UpdateMethodState(NodeState parent) : base(parent) { } /// public new static NodeState Construct(NodeState parent) { return new UpdateMethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAADAAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi//////" + "BGGCAAQAAAABABAAAABVcGRhdGVNZXRob2RUeXBlAQEAAAEBAAABAf////8AAAAA"; #endregion #endif #endregion #region Event Callbacks /// public UpdateMethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult _result = null; ISA95JobOrderDataType jobOrder = (ISA95JobOrderDataType)ExtensionObject.ToEncodeable((ExtensionObject)_inputArguments[0]); LocalizedText[] comment = (LocalizedText[])_inputArguments[1]; ulong returnStatus = (ulong)_outputArguments[0]; if (OnCall != null) { _result = OnCall( _context, this, _objectId, jobOrder, comment, ref returnStatus); } _outputArguments[0] = returnStatus; return _result; } #endregion #region Private Fields #endregion } /// /// public delegate ServiceResult UpdateMethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, ISA95JobOrderDataType jobOrder, LocalizedText[] comment, ref ulong returnStatus); #endif #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Isa95Jobs/Design/UAModel.ISA95_JOBCONTROL_V2.Constants.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2024 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; namespace UAModel.ISA95_JOBCONTROL_V2 { #region DataType Identifiers /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class DataTypes { /// public const uint ISA95EquipmentDataType = 3005; /// public const uint ISA95JobOrderAndStateDataType = 3015; /// public const uint ISA95JobOrderDataType = 3008; /// public const uint ISA95JobResponseDataType = 3013; /// public const uint ISA95MaterialDataType = 3010; /// public const uint ISA95ParameterDataType = 3003; /// public const uint ISA95PersonnelDataType = 3011; /// public const uint ISA95PhysicalAssetDataType = 3012; /// public const uint ISA95PropertyDataType = 3002; /// public const uint ISA95StateDataType = 3006; /// public const uint ISA95WorkMasterDataType = 3007; } #endregion #region Method Identifiers /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Methods { /// public const uint ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderID = 7002; /// public const uint ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderState = 7014; /// public const uint ISA95JobResponseReceiverObjectType_ReceiveJobResponse = 7003; /// public const uint ISA95JobOrderReceiverObjectType_Abort = 7010; /// public const uint ISA95JobOrderReceiverObjectType_Cancel = 7011; /// public const uint ISA95JobOrderReceiverObjectType_Clear = 7012; /// public const uint ISA95JobOrderReceiverObjectType_Pause = 7007; /// public const uint ISA95JobOrderReceiverObjectType_Resume = 7008; /// public const uint ISA95JobOrderReceiverObjectType_RevokeStart = 7013; /// public const uint ISA95JobOrderReceiverObjectType_Start = 7005; /// public const uint ISA95JobOrderReceiverObjectType_Stop = 7006; /// public const uint ISA95JobOrderReceiverObjectType_Store = 7001; /// public const uint ISA95JobOrderReceiverObjectType_StoreAndStart = 7004; /// public const uint ISA95JobOrderReceiverObjectType_Update = 7009; /// public const string ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderIDMethodType = ""; /// public const string ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderStateMethodType = ""; /// public const string ISA95JobResponseReceiverObjectType_ReceiveJobResponseMethodType = ""; /// public const string ISA95JobOrderReceiverObjectType_AbortMethodType = ""; /// public const string ISA95JobOrderReceiverObjectType_CancelMethodType = ""; /// public const string ISA95JobOrderReceiverObjectType_ClearMethodType = ""; /// public const string ISA95JobOrderReceiverObjectType_PauseMethodType = ""; /// public const string ISA95JobOrderReceiverObjectType_ResumeMethodType = ""; /// public const string ISA95JobOrderReceiverObjectType_RevokeStartMethodType = ""; /// public const string ISA95JobOrderReceiverObjectType_StartMethodType = ""; /// public const string ISA95JobOrderReceiverObjectType_StopMethodType = ""; /// public const string ISA95JobOrderReceiverObjectType_StoreMethodType = ""; /// public const string ISA95JobOrderReceiverObjectType_StoreAndStartMethodType = ""; /// public const string ISA95JobOrderReceiverObjectType_UpdateMethodType = ""; } #endregion #region Object Identifiers /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Objects { /// public const uint ISA95EndedStateMachineType_Closed = 5057; /// public const uint ISA95EndedStateMachineType_Completed = 5056; /// public const uint ISA95EndedStateMachineType_FromCompletedToClosed = 5058; /// public const uint ISA95InterruptedStateMachineType_FromHeldToSuspended = 5061; /// public const uint ISA95InterruptedStateMachineType_FromSuspendedToHeld = 5062; /// public const uint ISA95InterruptedStateMachineType_Held = 5059; /// public const uint ISA95InterruptedStateMachineType_Suspended = 5060; /// public const uint ISA95JobOrderReceiverObjectType_Aborted = 5040; /// public const uint ISA95JobOrderReceiverObjectType_AllowedToStart = 5036; /// public const uint ISA95JobOrderReceiverObjectType_Ended = 5039; /// public const uint ISA95JobOrderReceiverObjectType_FromAllowedToStartToAborted = 5085; /// public const uint ISA95JobOrderReceiverObjectType_FromAllowedToStartToAllowedToStart = 5044; /// public const uint ISA95JobOrderReceiverObjectType_FromAllowedToStartToNotAllowedToStart = 5043; /// public const uint ISA95JobOrderReceiverObjectType_FromAllowedToStartToRunning = 5045; /// public const uint ISA95JobOrderReceiverObjectType_FromInterruptedToAborted = 5049; /// public const uint ISA95JobOrderReceiverObjectType_FromInterruptedToEnded = 5051; /// public const uint ISA95JobOrderReceiverObjectType_FromInterruptedToRunning = 5050; /// public const uint ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToAborted = 5084; /// public const uint ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToAllowedToStart = 5042; /// public const uint ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToNotAllowedToStart = 5041; /// public const uint ISA95JobOrderReceiverObjectType_FromRunningToAborted = 5048; /// public const uint ISA95JobOrderReceiverObjectType_FromRunningToEnded = 5047; /// public const uint ISA95JobOrderReceiverObjectType_FromRunningToInterrupted = 5046; /// public const uint ISA95JobOrderReceiverObjectType_Interrupted = 5038; /// public const uint ISA95JobOrderReceiverObjectType_NotAllowedToStart = 5035; /// public const uint ISA95JobOrderReceiverObjectType_Running = 5037; /// public const uint ISA95JobOrderReceiverSubStatesType_Aborted = 5068; /// public const uint ISA95JobOrderReceiverSubStatesType_AllowedToStart = 5064; /// public const uint ISA95JobOrderReceiverSubStatesType_Ended = 5067; /// public const uint ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToAborted = 5086; /// public const uint ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToAllowedToStart = 5072; /// public const uint ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToNotAllowedToStart = 5071; /// public const uint ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToRunning = 5073; /// public const uint ISA95JobOrderReceiverSubStatesType_FromInterruptedToAborted = 5077; /// public const uint ISA95JobOrderReceiverSubStatesType_FromInterruptedToEnded = 5079; /// public const uint ISA95JobOrderReceiverSubStatesType_FromInterruptedToRunning = 5078; /// public const uint ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToAborted = 5087; /// public const uint ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToAllowedToStart = 5070; /// public const uint ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToNotAllowedToStart = 5069; /// public const uint ISA95JobOrderReceiverSubStatesType_FromRunningToAborted = 5076; /// public const uint ISA95JobOrderReceiverSubStatesType_FromRunningToEnded = 5075; /// public const uint ISA95JobOrderReceiverSubStatesType_FromRunningToInterrupted = 5074; /// public const uint ISA95JobOrderReceiverSubStatesType_Interrupted = 5066; /// public const uint ISA95JobOrderReceiverSubStatesType_NotAllowedToStart = 5063; /// public const uint ISA95JobOrderReceiverSubStatesType_Running = 5065; /// public const uint ISA95JobOrderReceiverSubStatesType_AllowedToStartSubstates = 5081; /// public const uint ISA95JobOrderReceiverSubStatesType_EndedSubstates = 5082; /// public const uint ISA95JobOrderReceiverSubStatesType_InterruptedSubstates = 5083; /// public const uint ISA95JobOrderReceiverSubStatesType_NotAllowedToStartSubstates = 5080; /// public const uint ISA95PrepareStateMachineType_FromLoadedToReady = 5089; /// public const uint ISA95PrepareStateMachineType_FromLoadedToWaiting = 5090; /// public const uint ISA95PrepareStateMachineType_FromReadyToLoaded = 5055; /// public const uint ISA95PrepareStateMachineType_FromReadyToWaiting = 5088; /// public const uint ISA95PrepareStateMachineType_FromWaitingToReady = 5054; /// public const uint ISA95PrepareStateMachineType_Loaded = 5053; /// public const uint ISA95PrepareStateMachineType_Ready = 5052; /// public const uint ISA95PrepareStateMachineType_Waiting = 5000; /// public const uint http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2_ = 5001; /// public const uint ISA95PropertyDataType_Encoding_DefaultBinary = 5002; /// public const uint ISA95PropertyDataType_Encoding_DefaultXml = 5003; /// public const uint ISA95PropertyDataType_Encoding_DefaultJson = 5004; /// public const uint ISA95ParameterDataType_Encoding_DefaultBinary = 5005; /// public const uint ISA95ParameterDataType_Encoding_DefaultXml = 5006; /// public const uint ISA95ParameterDataType_Encoding_DefaultJson = 5007; /// public const uint ISA95EquipmentDataType_Encoding_DefaultBinary = 5008; /// public const uint ISA95EquipmentDataType_Encoding_DefaultXml = 5009; /// public const uint ISA95EquipmentDataType_Encoding_DefaultJson = 5010; /// public const uint ISA95WorkMasterDataType_Encoding_DefaultBinary = 5011; /// public const uint ISA95WorkMasterDataType_Encoding_DefaultXml = 5012; /// public const uint ISA95WorkMasterDataType_Encoding_DefaultJson = 5013; /// public const uint ISA95JobOrderDataType_Encoding_DefaultBinary = 5014; /// public const uint ISA95JobOrderDataType_Encoding_DefaultXml = 5015; /// public const uint ISA95JobOrderDataType_Encoding_DefaultJson = 5016; /// public const uint ISA95MaterialDataType_Encoding_DefaultBinary = 5017; /// public const uint ISA95MaterialDataType_Encoding_DefaultXml = 5018; /// public const uint ISA95MaterialDataType_Encoding_DefaultJson = 5019; /// public const uint ISA95PersonnelDataType_Encoding_DefaultBinary = 5020; /// public const uint ISA95PersonnelDataType_Encoding_DefaultXml = 5021; /// public const uint ISA95PersonnelDataType_Encoding_DefaultJson = 5022; /// public const uint ISA95PhysicalAssetDataType_Encoding_DefaultBinary = 5023; /// public const uint ISA95PhysicalAssetDataType_Encoding_DefaultXml = 5024; /// public const uint ISA95PhysicalAssetDataType_Encoding_DefaultJson = 5025; /// public const uint ISA95JobResponseDataType_Encoding_DefaultBinary = 5026; /// public const uint ISA95JobResponseDataType_Encoding_DefaultXml = 5027; /// public const uint ISA95JobResponseDataType_Encoding_DefaultJson = 5028; /// public const uint ISA95StateDataType_Encoding_DefaultBinary = 5029; /// public const uint ISA95StateDataType_Encoding_DefaultXml = 5030; /// public const uint ISA95StateDataType_Encoding_DefaultJson = 5031; /// public const uint ISA95JobOrderAndStateDataType_Encoding_DefaultBinary = 5032; /// public const uint ISA95JobOrderAndStateDataType_Encoding_DefaultXml = 5033; /// public const uint ISA95JobOrderAndStateDataType_Encoding_DefaultJson = 5034; } #endregion #region ObjectType Identifiers /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectTypes { /// public const uint ISA95JobOrderStatusEventType = 1006; /// public const uint ISA95JobResponseProviderObjectType = 1003; /// public const uint ISA95JobResponseReceiverObjectType = 1004; /// public const uint ISA95EndedStateMachineType = 1005; /// public const uint ISA95InterruptedStateMachineType = 1007; /// public const uint ISA95JobOrderReceiverObjectType = 1002; /// public const uint ISA95JobOrderReceiverSubStatesType = 1008; /// public const uint ISA95PrepareStateMachineType = 1001; } #endregion #region Variable Identifiers /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Variables { /// public const uint ISA95JobOrderStatusEventType_JobOrder = 6047; /// public const uint ISA95JobOrderStatusEventType_JobResponse = 6049; /// public const uint ISA95JobOrderStatusEventType_JobState = 6048; /// public const uint ISA95JobResponseProviderObjectType_JobOrderResponseList = 6050; /// public const uint ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderID_InputArguments = 6042; /// public const uint ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderID_OutputArguments = 6043; /// public const uint ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderState_InputArguments = 6016; /// public const uint ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderState_OutputArguments = 6017; /// public const uint ISA95JobResponseReceiverObjectType_ReceiveJobResponse_InputArguments = 6044; /// public const uint ISA95JobResponseReceiverObjectType_ReceiveJobResponse_OutputArguments = 6045; /// public const uint ISA95EndedStateMachineType_Closed_StateNumber = 6094; /// public const uint ISA95EndedStateMachineType_Completed_StateNumber = 6093; /// public const uint ISA95EndedStateMachineType_FromCompletedToClosed_TransitionNumber = 6095; /// public const uint ISA95InterruptedStateMachineType_FromHeldToSuspended_TransitionNumber = 6098; /// public const uint ISA95InterruptedStateMachineType_FromSuspendedToHeld_TransitionNumber = 6099; /// public const uint ISA95InterruptedStateMachineType_Held_StateNumber = 6096; /// public const uint ISA95InterruptedStateMachineType_Suspended_StateNumber = 6097; /// public const uint ISA95JobOrderReceiverObjectType_Abort_InputArguments = 6063; /// public const uint ISA95JobOrderReceiverObjectType_Abort_OutputArguments = 6064; /// public const uint ISA95JobOrderReceiverObjectType_Aborted_StateNumber = 6076; /// public const uint ISA95JobOrderReceiverObjectType_AllowedToStart_StateNumber = 6072; /// public const uint ISA95JobOrderReceiverObjectType_Cancel_InputArguments = 6065; /// public const uint ISA95JobOrderReceiverObjectType_Cancel_OutputArguments = 6066; /// public const uint ISA95JobOrderReceiverObjectType_Clear_InputArguments = 6067; /// public const uint ISA95JobOrderReceiverObjectType_Clear_OutputArguments = 6068; /// public const uint ISA95JobOrderReceiverObjectType_Ended_StateNumber = 6075; /// public const uint ISA95JobOrderReceiverObjectType_EquipmentID = 6037; /// public const uint ISA95JobOrderReceiverObjectType_FromAllowedToStartToAborted_TransitionNumber = 6010; /// public const uint ISA95JobOrderReceiverObjectType_FromAllowedToStartToAllowedToStart_TransitionNumber = 6080; /// public const uint ISA95JobOrderReceiverObjectType_FromAllowedToStartToNotAllowedToStart_TransitionNumber = 6079; /// public const uint ISA95JobOrderReceiverObjectType_FromAllowedToStartToRunning_TransitionNumber = 6081; /// public const uint ISA95JobOrderReceiverObjectType_FromInterruptedToAborted_TransitionNumber = 6085; /// public const uint ISA95JobOrderReceiverObjectType_FromInterruptedToEnded_TransitionNumber = 6087; /// public const uint ISA95JobOrderReceiverObjectType_FromInterruptedToRunning_TransitionNumber = 6086; /// public const uint ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToAborted_TransitionNumber = 6009; /// public const uint ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToAllowedToStart_TransitionNumber = 6078; /// public const uint ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToNotAllowedToStart_TransitionNumber = 6077; /// public const uint ISA95JobOrderReceiverObjectType_FromRunningToAborted_TransitionNumber = 6084; /// public const uint ISA95JobOrderReceiverObjectType_FromRunningToEnded_TransitionNumber = 6083; /// public const uint ISA95JobOrderReceiverObjectType_FromRunningToInterrupted_TransitionNumber = 6082; /// public const uint ISA95JobOrderReceiverObjectType_Interrupted_StateNumber = 6074; /// public const uint ISA95JobOrderReceiverObjectType_JobOrderList = 6033; /// public const uint ISA95JobOrderReceiverObjectType_MaterialClassID = 6035; /// public const uint ISA95JobOrderReceiverObjectType_MaterialDefinitionID = 6036; /// public const uint ISA95JobOrderReceiverObjectType_MaxDownloadableJobOrders = 6088; /// public const uint ISA95JobOrderReceiverObjectType_NotAllowedToStart_StateNumber = 6071; /// public const uint ISA95JobOrderReceiverObjectType_Pause_InputArguments = 6057; /// public const uint ISA95JobOrderReceiverObjectType_Pause_OutputArguments = 6058; /// public const uint ISA95JobOrderReceiverObjectType_PersonnelID = 6039; /// public const uint ISA95JobOrderReceiverObjectType_PhysicalAssetID = 6038; /// public const uint ISA95JobOrderReceiverObjectType_Resume_InputArguments = 6059; /// public const uint ISA95JobOrderReceiverObjectType_Resume_OutputArguments = 6060; /// public const uint ISA95JobOrderReceiverObjectType_RevokeStart_InputArguments = 6069; /// public const uint ISA95JobOrderReceiverObjectType_RevokeStart_OutputArguments = 6070; /// public const uint ISA95JobOrderReceiverObjectType_Running_StateNumber = 6073; /// public const uint ISA95JobOrderReceiverObjectType_Start_InputArguments = 6053; /// public const uint ISA95JobOrderReceiverObjectType_Start_OutputArguments = 6054; /// public const uint ISA95JobOrderReceiverObjectType_Stop_InputArguments = 6055; /// public const uint ISA95JobOrderReceiverObjectType_Stop_OutputArguments = 6056; /// public const uint ISA95JobOrderReceiverObjectType_Store_InputArguments = 6040; /// public const uint ISA95JobOrderReceiverObjectType_Store_OutputArguments = 6041; /// public const uint ISA95JobOrderReceiverObjectType_StoreAndStart_InputArguments = 6051; /// public const uint ISA95JobOrderReceiverObjectType_StoreAndStart_OutputArguments = 6052; /// public const uint ISA95JobOrderReceiverObjectType_Update_InputArguments = 6061; /// public const uint ISA95JobOrderReceiverObjectType_Update_OutputArguments = 6062; /// public const uint ISA95JobOrderReceiverObjectType_WorkMaster = 6034; /// public const uint ISA95JobOrderReceiverSubStatesType_Abort_InputArguments = 6063; /// public const uint ISA95JobOrderReceiverSubStatesType_Abort_OutputArguments = 6064; /// public const uint ISA95JobOrderReceiverSubStatesType_Aborted_StateNumber = 6105; /// public const uint ISA95JobOrderReceiverSubStatesType_AllowedToStart_StateNumber = 6101; /// public const uint ISA95JobOrderReceiverSubStatesType_Cancel_InputArguments = 6065; /// public const uint ISA95JobOrderReceiverSubStatesType_Cancel_OutputArguments = 6066; /// public const uint ISA95JobOrderReceiverSubStatesType_Clear_InputArguments = 6067; /// public const uint ISA95JobOrderReceiverSubStatesType_Clear_OutputArguments = 6068; /// public const uint ISA95JobOrderReceiverSubStatesType_Ended_StateNumber = 6104; /// public const uint ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToAborted_TransitionNumber = 6011; /// public const uint ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToAllowedToStart_TransitionNumber = 6109; /// public const uint ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToNotAllowedToStart_TransitionNumber = 6108; /// public const uint ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToRunning_TransitionNumber = 6110; /// public const uint ISA95JobOrderReceiverSubStatesType_FromInterruptedToAborted_TransitionNumber = 6114; /// public const uint ISA95JobOrderReceiverSubStatesType_FromInterruptedToEnded_TransitionNumber = 6116; /// public const uint ISA95JobOrderReceiverSubStatesType_FromInterruptedToRunning_TransitionNumber = 6115; /// public const uint ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToAborted_TransitionNumber = 6012; /// public const uint ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToAllowedToStart_TransitionNumber = 6107; /// public const uint ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToNotAllowedToStart_TransitionNumber = 6106; /// public const uint ISA95JobOrderReceiverSubStatesType_FromRunningToAborted_TransitionNumber = 6113; /// public const uint ISA95JobOrderReceiverSubStatesType_FromRunningToEnded_TransitionNumber = 6112; /// public const uint ISA95JobOrderReceiverSubStatesType_FromRunningToInterrupted_TransitionNumber = 6111; /// public const uint ISA95JobOrderReceiverSubStatesType_Interrupted_StateNumber = 6103; /// public const uint ISA95JobOrderReceiverSubStatesType_NotAllowedToStart_StateNumber = 6100; /// public const uint ISA95JobOrderReceiverSubStatesType_Pause_InputArguments = 6057; /// public const uint ISA95JobOrderReceiverSubStatesType_Pause_OutputArguments = 6058; /// public const uint ISA95JobOrderReceiverSubStatesType_Resume_InputArguments = 6059; /// public const uint ISA95JobOrderReceiverSubStatesType_Resume_OutputArguments = 6060; /// public const uint ISA95JobOrderReceiverSubStatesType_RevokeStart_InputArguments = 6069; /// public const uint ISA95JobOrderReceiverSubStatesType_RevokeStart_OutputArguments = 6070; /// public const uint ISA95JobOrderReceiverSubStatesType_Running_StateNumber = 6102; /// public const uint ISA95JobOrderReceiverSubStatesType_Start_InputArguments = 6053; /// public const uint ISA95JobOrderReceiverSubStatesType_Start_OutputArguments = 6054; /// public const uint ISA95JobOrderReceiverSubStatesType_Stop_InputArguments = 6055; /// public const uint ISA95JobOrderReceiverSubStatesType_Stop_OutputArguments = 6056; /// public const uint ISA95JobOrderReceiverSubStatesType_Store_InputArguments = 6040; /// public const uint ISA95JobOrderReceiverSubStatesType_Store_OutputArguments = 6041; /// public const uint ISA95JobOrderReceiverSubStatesType_StoreAndStart_InputArguments = 6051; /// public const uint ISA95JobOrderReceiverSubStatesType_StoreAndStart_OutputArguments = 6052; /// public const uint ISA95JobOrderReceiverSubStatesType_Update_InputArguments = 6061; /// public const uint ISA95JobOrderReceiverSubStatesType_Update_OutputArguments = 6062; /// public const uint ISA95JobOrderReceiverSubStatesType_AllowedToStartSubstates_CurrentState = 6003; /// public const uint ISA95JobOrderReceiverSubStatesType_AllowedToStartSubstates_CurrentState_Id = 6004; /// public const uint ISA95JobOrderReceiverSubStatesType_EndedSubstates_CurrentState = 6005; /// public const uint ISA95JobOrderReceiverSubStatesType_EndedSubstates_CurrentState_Id = 6006; /// public const uint ISA95JobOrderReceiverSubStatesType_InterruptedSubstates_CurrentState = 6007; /// public const uint ISA95JobOrderReceiverSubStatesType_InterruptedSubstates_CurrentState_Id = 6008; /// public const uint ISA95JobOrderReceiverSubStatesType_NotAllowedToStartSubstates_CurrentState = 6001; /// public const uint ISA95JobOrderReceiverSubStatesType_NotAllowedToStartSubstates_CurrentState_Id = 6002; /// public const uint ISA95PrepareStateMachineType_FromLoadedToReady_TransitionNumber = 6014; /// public const uint ISA95PrepareStateMachineType_FromLoadedToWaiting_TransitionNumber = 6015; /// public const uint ISA95PrepareStateMachineType_FromReadyToLoaded_TransitionNumber = 6092; /// public const uint ISA95PrepareStateMachineType_FromReadyToWaiting_TransitionNumber = 6013; /// public const uint ISA95PrepareStateMachineType_FromWaitingToReady_TransitionNumber = 6091; /// public const uint ISA95PrepareStateMachineType_Loaded_StateNumber = 6090; /// public const uint ISA95PrepareStateMachineType_Ready_StateNumber = 6089; /// public const uint ISA95PrepareStateMachineType_Waiting_StateNumber = 6000; /// public const uint http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__NamespaceUri = 6025; /// public const uint http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__NamespaceVersion = 6026; /// public const uint http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__NamespacePublicationDate = 6024; /// public const uint http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__IsNamespaceSubset = 6023; /// public const uint http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__StaticNodeIdTypes = 6027; /// public const uint http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__StaticNumericNodeIdRange = 6028; /// public const uint http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__StaticStringNodeIdPattern = 6029; } #endregion #region DataType Node Identifiers /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class DataTypeIds { /// public static readonly ExpandedNodeId ISA95EquipmentDataType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.DataTypes.ISA95EquipmentDataType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderAndStateDataType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.DataTypes.ISA95JobOrderAndStateDataType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderDataType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.DataTypes.ISA95JobOrderDataType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobResponseDataType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.DataTypes.ISA95JobResponseDataType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95MaterialDataType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.DataTypes.ISA95MaterialDataType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95ParameterDataType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.DataTypes.ISA95ParameterDataType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PersonnelDataType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.DataTypes.ISA95PersonnelDataType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PhysicalAssetDataType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.DataTypes.ISA95PhysicalAssetDataType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PropertyDataType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.DataTypes.ISA95PropertyDataType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95StateDataType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.DataTypes.ISA95StateDataType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95WorkMasterDataType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.DataTypes.ISA95WorkMasterDataType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); } #endregion #region Method Node Identifiers /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class MethodIds { /// public static readonly ExpandedNodeId ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderID = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderID, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderState = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderState, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobResponseReceiverObjectType_ReceiveJobResponse = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobResponseReceiverObjectType_ReceiveJobResponse, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Abort = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobOrderReceiverObjectType_Abort, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Cancel = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobOrderReceiverObjectType_Cancel, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Clear = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobOrderReceiverObjectType_Clear, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Pause = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobOrderReceiverObjectType_Pause, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Resume = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobOrderReceiverObjectType_Resume, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_RevokeStart = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobOrderReceiverObjectType_RevokeStart, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Start = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobOrderReceiverObjectType_Start, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Stop = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobOrderReceiverObjectType_Stop, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Store = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobOrderReceiverObjectType_Store, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_StoreAndStart = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobOrderReceiverObjectType_StoreAndStart, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Update = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobOrderReceiverObjectType_Update, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderIDMethodType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderIDMethodType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderStateMethodType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderStateMethodType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobResponseReceiverObjectType_ReceiveJobResponseMethodType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobResponseReceiverObjectType_ReceiveJobResponseMethodType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_AbortMethodType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobOrderReceiverObjectType_AbortMethodType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_CancelMethodType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobOrderReceiverObjectType_CancelMethodType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_ClearMethodType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobOrderReceiverObjectType_ClearMethodType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_PauseMethodType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobOrderReceiverObjectType_PauseMethodType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_ResumeMethodType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobOrderReceiverObjectType_ResumeMethodType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_RevokeStartMethodType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobOrderReceiverObjectType_RevokeStartMethodType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_StartMethodType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobOrderReceiverObjectType_StartMethodType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_StopMethodType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobOrderReceiverObjectType_StopMethodType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_StoreMethodType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobOrderReceiverObjectType_StoreMethodType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_StoreAndStartMethodType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobOrderReceiverObjectType_StoreAndStartMethodType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_UpdateMethodType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Methods.ISA95JobOrderReceiverObjectType_UpdateMethodType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); } #endregion #region Object Node Identifiers /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectIds { /// public static readonly ExpandedNodeId ISA95EndedStateMachineType_Closed = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95EndedStateMachineType_Closed, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95EndedStateMachineType_Completed = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95EndedStateMachineType_Completed, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95EndedStateMachineType_FromCompletedToClosed = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95EndedStateMachineType_FromCompletedToClosed, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95InterruptedStateMachineType_FromHeldToSuspended = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95InterruptedStateMachineType_FromHeldToSuspended, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95InterruptedStateMachineType_FromSuspendedToHeld = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95InterruptedStateMachineType_FromSuspendedToHeld, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95InterruptedStateMachineType_Held = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95InterruptedStateMachineType_Held, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95InterruptedStateMachineType_Suspended = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95InterruptedStateMachineType_Suspended, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Aborted = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverObjectType_Aborted, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_AllowedToStart = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverObjectType_AllowedToStart, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Ended = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverObjectType_Ended, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromAllowedToStartToAborted = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverObjectType_FromAllowedToStartToAborted, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromAllowedToStartToAllowedToStart = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverObjectType_FromAllowedToStartToAllowedToStart, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromAllowedToStartToNotAllowedToStart = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverObjectType_FromAllowedToStartToNotAllowedToStart, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromAllowedToStartToRunning = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverObjectType_FromAllowedToStartToRunning, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromInterruptedToAborted = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverObjectType_FromInterruptedToAborted, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromInterruptedToEnded = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverObjectType_FromInterruptedToEnded, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromInterruptedToRunning = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverObjectType_FromInterruptedToRunning, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToAborted = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToAborted, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToAllowedToStart = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToAllowedToStart, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToNotAllowedToStart = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToNotAllowedToStart, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromRunningToAborted = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverObjectType_FromRunningToAborted, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromRunningToEnded = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverObjectType_FromRunningToEnded, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromRunningToInterrupted = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverObjectType_FromRunningToInterrupted, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Interrupted = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverObjectType_Interrupted, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_NotAllowedToStart = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverObjectType_NotAllowedToStart, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Running = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverObjectType_Running, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Aborted = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverSubStatesType_Aborted, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_AllowedToStart = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverSubStatesType_AllowedToStart, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Ended = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverSubStatesType_Ended, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToAborted = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToAborted, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToAllowedToStart = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToAllowedToStart, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToNotAllowedToStart = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToNotAllowedToStart, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToRunning = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToRunning, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromInterruptedToAborted = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverSubStatesType_FromInterruptedToAborted, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromInterruptedToEnded = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverSubStatesType_FromInterruptedToEnded, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromInterruptedToRunning = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverSubStatesType_FromInterruptedToRunning, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToAborted = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToAborted, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToAllowedToStart = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToAllowedToStart, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToNotAllowedToStart = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToNotAllowedToStart, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromRunningToAborted = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverSubStatesType_FromRunningToAborted, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromRunningToEnded = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverSubStatesType_FromRunningToEnded, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromRunningToInterrupted = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverSubStatesType_FromRunningToInterrupted, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Interrupted = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverSubStatesType_Interrupted, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_NotAllowedToStart = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverSubStatesType_NotAllowedToStart, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Running = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverSubStatesType_Running, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_AllowedToStartSubstates = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverSubStatesType_AllowedToStartSubstates, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_EndedSubstates = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverSubStatesType_EndedSubstates, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_InterruptedSubstates = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverSubStatesType_InterruptedSubstates, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_NotAllowedToStartSubstates = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderReceiverSubStatesType_NotAllowedToStartSubstates, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PrepareStateMachineType_FromLoadedToReady = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95PrepareStateMachineType_FromLoadedToReady, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PrepareStateMachineType_FromLoadedToWaiting = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95PrepareStateMachineType_FromLoadedToWaiting, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PrepareStateMachineType_FromReadyToLoaded = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95PrepareStateMachineType_FromReadyToLoaded, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PrepareStateMachineType_FromReadyToWaiting = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95PrepareStateMachineType_FromReadyToWaiting, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PrepareStateMachineType_FromWaitingToReady = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95PrepareStateMachineType_FromWaitingToReady, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PrepareStateMachineType_Loaded = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95PrepareStateMachineType_Loaded, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PrepareStateMachineType_Ready = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95PrepareStateMachineType_Ready, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PrepareStateMachineType_Waiting = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95PrepareStateMachineType_Waiting, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2_ = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2_, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PropertyDataType_Encoding_DefaultBinary = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95PropertyDataType_Encoding_DefaultBinary, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PropertyDataType_Encoding_DefaultXml = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95PropertyDataType_Encoding_DefaultXml, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PropertyDataType_Encoding_DefaultJson = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95PropertyDataType_Encoding_DefaultJson, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95ParameterDataType_Encoding_DefaultBinary = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95ParameterDataType_Encoding_DefaultBinary, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95ParameterDataType_Encoding_DefaultXml = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95ParameterDataType_Encoding_DefaultXml, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95ParameterDataType_Encoding_DefaultJson = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95ParameterDataType_Encoding_DefaultJson, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95EquipmentDataType_Encoding_DefaultBinary = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95EquipmentDataType_Encoding_DefaultBinary, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95EquipmentDataType_Encoding_DefaultXml = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95EquipmentDataType_Encoding_DefaultXml, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95EquipmentDataType_Encoding_DefaultJson = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95EquipmentDataType_Encoding_DefaultJson, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95WorkMasterDataType_Encoding_DefaultBinary = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95WorkMasterDataType_Encoding_DefaultBinary, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95WorkMasterDataType_Encoding_DefaultXml = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95WorkMasterDataType_Encoding_DefaultXml, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95WorkMasterDataType_Encoding_DefaultJson = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95WorkMasterDataType_Encoding_DefaultJson, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderDataType_Encoding_DefaultBinary = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderDataType_Encoding_DefaultBinary, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderDataType_Encoding_DefaultXml = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderDataType_Encoding_DefaultXml, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderDataType_Encoding_DefaultJson = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderDataType_Encoding_DefaultJson, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95MaterialDataType_Encoding_DefaultBinary = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95MaterialDataType_Encoding_DefaultBinary, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95MaterialDataType_Encoding_DefaultXml = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95MaterialDataType_Encoding_DefaultXml, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95MaterialDataType_Encoding_DefaultJson = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95MaterialDataType_Encoding_DefaultJson, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PersonnelDataType_Encoding_DefaultBinary = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95PersonnelDataType_Encoding_DefaultBinary, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PersonnelDataType_Encoding_DefaultXml = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95PersonnelDataType_Encoding_DefaultXml, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PersonnelDataType_Encoding_DefaultJson = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95PersonnelDataType_Encoding_DefaultJson, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PhysicalAssetDataType_Encoding_DefaultBinary = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95PhysicalAssetDataType_Encoding_DefaultBinary, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PhysicalAssetDataType_Encoding_DefaultXml = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95PhysicalAssetDataType_Encoding_DefaultXml, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PhysicalAssetDataType_Encoding_DefaultJson = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95PhysicalAssetDataType_Encoding_DefaultJson, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobResponseDataType_Encoding_DefaultBinary = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobResponseDataType_Encoding_DefaultBinary, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobResponseDataType_Encoding_DefaultXml = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobResponseDataType_Encoding_DefaultXml, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobResponseDataType_Encoding_DefaultJson = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobResponseDataType_Encoding_DefaultJson, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95StateDataType_Encoding_DefaultBinary = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95StateDataType_Encoding_DefaultBinary, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95StateDataType_Encoding_DefaultXml = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95StateDataType_Encoding_DefaultXml, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95StateDataType_Encoding_DefaultJson = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95StateDataType_Encoding_DefaultJson, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderAndStateDataType_Encoding_DefaultBinary = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderAndStateDataType_Encoding_DefaultBinary, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderAndStateDataType_Encoding_DefaultXml = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderAndStateDataType_Encoding_DefaultXml, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderAndStateDataType_Encoding_DefaultJson = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Objects.ISA95JobOrderAndStateDataType_Encoding_DefaultJson, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); } #endregion #region ObjectType Node Identifiers /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectTypeIds { /// public static readonly ExpandedNodeId ISA95JobOrderStatusEventType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.ObjectTypes.ISA95JobOrderStatusEventType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobResponseProviderObjectType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.ObjectTypes.ISA95JobResponseProviderObjectType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobResponseReceiverObjectType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.ObjectTypes.ISA95JobResponseReceiverObjectType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95EndedStateMachineType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.ObjectTypes.ISA95EndedStateMachineType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95InterruptedStateMachineType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.ObjectTypes.ISA95InterruptedStateMachineType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.ObjectTypes.ISA95JobOrderReceiverObjectType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.ObjectTypes.ISA95JobOrderReceiverSubStatesType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PrepareStateMachineType = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.ObjectTypes.ISA95PrepareStateMachineType, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); } #endregion #region Variable Node Identifiers /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class VariableIds { /// public static readonly ExpandedNodeId ISA95JobOrderStatusEventType_JobOrder = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderStatusEventType_JobOrder, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderStatusEventType_JobResponse = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderStatusEventType_JobResponse, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderStatusEventType_JobState = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderStatusEventType_JobState, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobResponseProviderObjectType_JobOrderResponseList = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobResponseProviderObjectType_JobOrderResponseList, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderID_InputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderID_InputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderID_OutputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderID_OutputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderState_InputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderState_InputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderState_OutputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderState_OutputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobResponseReceiverObjectType_ReceiveJobResponse_InputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobResponseReceiverObjectType_ReceiveJobResponse_InputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobResponseReceiverObjectType_ReceiveJobResponse_OutputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobResponseReceiverObjectType_ReceiveJobResponse_OutputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95EndedStateMachineType_Closed_StateNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95EndedStateMachineType_Closed_StateNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95EndedStateMachineType_Completed_StateNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95EndedStateMachineType_Completed_StateNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95EndedStateMachineType_FromCompletedToClosed_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95EndedStateMachineType_FromCompletedToClosed_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95InterruptedStateMachineType_FromHeldToSuspended_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95InterruptedStateMachineType_FromHeldToSuspended_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95InterruptedStateMachineType_FromSuspendedToHeld_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95InterruptedStateMachineType_FromSuspendedToHeld_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95InterruptedStateMachineType_Held_StateNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95InterruptedStateMachineType_Held_StateNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95InterruptedStateMachineType_Suspended_StateNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95InterruptedStateMachineType_Suspended_StateNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Abort_InputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_Abort_InputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Abort_OutputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_Abort_OutputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Aborted_StateNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_Aborted_StateNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_AllowedToStart_StateNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_AllowedToStart_StateNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Cancel_InputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_Cancel_InputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Cancel_OutputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_Cancel_OutputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Clear_InputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_Clear_InputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Clear_OutputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_Clear_OutputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Ended_StateNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_Ended_StateNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_EquipmentID = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_EquipmentID, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromAllowedToStartToAborted_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_FromAllowedToStartToAborted_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromAllowedToStartToAllowedToStart_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_FromAllowedToStartToAllowedToStart_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromAllowedToStartToNotAllowedToStart_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_FromAllowedToStartToNotAllowedToStart_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromAllowedToStartToRunning_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_FromAllowedToStartToRunning_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromInterruptedToAborted_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_FromInterruptedToAborted_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromInterruptedToEnded_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_FromInterruptedToEnded_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromInterruptedToRunning_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_FromInterruptedToRunning_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToAborted_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToAborted_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToAllowedToStart_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToAllowedToStart_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToNotAllowedToStart_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToNotAllowedToStart_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromRunningToAborted_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_FromRunningToAborted_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromRunningToEnded_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_FromRunningToEnded_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_FromRunningToInterrupted_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_FromRunningToInterrupted_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Interrupted_StateNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_Interrupted_StateNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_JobOrderList = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_JobOrderList, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_MaterialClassID = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_MaterialClassID, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_MaterialDefinitionID = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_MaterialDefinitionID, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_MaxDownloadableJobOrders = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_MaxDownloadableJobOrders, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_NotAllowedToStart_StateNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_NotAllowedToStart_StateNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Pause_InputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_Pause_InputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Pause_OutputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_Pause_OutputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_PersonnelID = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_PersonnelID, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_PhysicalAssetID = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_PhysicalAssetID, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Resume_InputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_Resume_InputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Resume_OutputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_Resume_OutputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_RevokeStart_InputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_RevokeStart_InputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_RevokeStart_OutputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_RevokeStart_OutputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Running_StateNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_Running_StateNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Start_InputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_Start_InputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Start_OutputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_Start_OutputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Stop_InputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_Stop_InputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Stop_OutputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_Stop_OutputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Store_InputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_Store_InputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Store_OutputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_Store_OutputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_StoreAndStart_InputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_StoreAndStart_InputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_StoreAndStart_OutputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_StoreAndStart_OutputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Update_InputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_Update_InputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_Update_OutputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_Update_OutputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverObjectType_WorkMaster = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverObjectType_WorkMaster, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Abort_InputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_Abort_InputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Abort_OutputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_Abort_OutputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Aborted_StateNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_Aborted_StateNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_AllowedToStart_StateNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_AllowedToStart_StateNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Cancel_InputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_Cancel_InputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Cancel_OutputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_Cancel_OutputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Clear_InputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_Clear_InputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Clear_OutputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_Clear_OutputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Ended_StateNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_Ended_StateNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToAborted_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToAborted_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToAllowedToStart_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToAllowedToStart_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToNotAllowedToStart_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToNotAllowedToStart_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToRunning_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToRunning_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromInterruptedToAborted_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_FromInterruptedToAborted_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromInterruptedToEnded_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_FromInterruptedToEnded_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromInterruptedToRunning_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_FromInterruptedToRunning_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToAborted_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToAborted_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToAllowedToStart_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToAllowedToStart_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToNotAllowedToStart_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToNotAllowedToStart_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromRunningToAborted_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_FromRunningToAborted_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromRunningToEnded_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_FromRunningToEnded_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_FromRunningToInterrupted_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_FromRunningToInterrupted_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Interrupted_StateNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_Interrupted_StateNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_NotAllowedToStart_StateNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_NotAllowedToStart_StateNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Pause_InputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_Pause_InputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Pause_OutputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_Pause_OutputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Resume_InputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_Resume_InputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Resume_OutputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_Resume_OutputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_RevokeStart_InputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_RevokeStart_InputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_RevokeStart_OutputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_RevokeStart_OutputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Running_StateNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_Running_StateNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Start_InputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_Start_InputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Start_OutputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_Start_OutputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Stop_InputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_Stop_InputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Stop_OutputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_Stop_OutputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Store_InputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_Store_InputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Store_OutputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_Store_OutputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_StoreAndStart_InputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_StoreAndStart_InputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_StoreAndStart_OutputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_StoreAndStart_OutputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Update_InputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_Update_InputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_Update_OutputArguments = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_Update_OutputArguments, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_AllowedToStartSubstates_CurrentState = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_AllowedToStartSubstates_CurrentState, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_AllowedToStartSubstates_CurrentState_Id = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_AllowedToStartSubstates_CurrentState_Id, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_EndedSubstates_CurrentState = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_EndedSubstates_CurrentState, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_EndedSubstates_CurrentState_Id = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_EndedSubstates_CurrentState_Id, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_InterruptedSubstates_CurrentState = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_InterruptedSubstates_CurrentState, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_InterruptedSubstates_CurrentState_Id = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_InterruptedSubstates_CurrentState_Id, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_NotAllowedToStartSubstates_CurrentState = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_NotAllowedToStartSubstates_CurrentState, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95JobOrderReceiverSubStatesType_NotAllowedToStartSubstates_CurrentState_Id = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95JobOrderReceiverSubStatesType_NotAllowedToStartSubstates_CurrentState_Id, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PrepareStateMachineType_FromLoadedToReady_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95PrepareStateMachineType_FromLoadedToReady_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PrepareStateMachineType_FromLoadedToWaiting_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95PrepareStateMachineType_FromLoadedToWaiting_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PrepareStateMachineType_FromReadyToLoaded_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95PrepareStateMachineType_FromReadyToLoaded_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PrepareStateMachineType_FromReadyToWaiting_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95PrepareStateMachineType_FromReadyToWaiting_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PrepareStateMachineType_FromWaitingToReady_TransitionNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95PrepareStateMachineType_FromWaitingToReady_TransitionNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PrepareStateMachineType_Loaded_StateNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95PrepareStateMachineType_Loaded_StateNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PrepareStateMachineType_Ready_StateNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95PrepareStateMachineType_Ready_StateNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId ISA95PrepareStateMachineType_Waiting_StateNumber = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.ISA95PrepareStateMachineType_Waiting_StateNumber, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__NamespaceUri = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__NamespaceUri, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__NamespaceVersion = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__NamespaceVersion, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__NamespacePublicationDate = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__NamespacePublicationDate, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__IsNamespaceSubset = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__IsNamespaceSubset, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__StaticNodeIdTypes = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__StaticNodeIdTypes, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__StaticNumericNodeIdRange = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__StaticNumericNodeIdRange, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); /// public static readonly ExpandedNodeId http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__StaticStringNodeIdPattern = new ExpandedNodeId(UAModel.ISA95_JOBCONTROL_V2.Variables.http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__StaticStringNodeIdPattern, UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); } #endregion #region BrowseName Declarations /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class BrowseNames { /// public const string Abort = "Abort"; /// public const string Aborted = "Aborted"; /// public const string AbortMethodType = "AbortMethodType"; /// public const string AllowedToStart = "AllowedToStart"; /// public const string AllowedToStartSubstates = "AllowedToStartSubstates"; /// public const string Cancel = "Cancel"; /// public const string CancelMethodType = "CancelMethodType"; /// public const string Clear = "Clear"; /// public const string ClearMethodType = "ClearMethodType"; /// public const string Closed = "Closed"; /// public const string Completed = "Completed"; /// public const string Ended = "Ended"; /// public const string EndedSubstates = "EndedSubstates"; /// public const string EquipmentID = "EquipmentID"; /// public const string FromAllowedToStartToAborted = "FromAllowedToStartToAborted"; /// public const string FromAllowedToStartToAllowedToStart = "FromAllowedToStartToAllowedToStart"; /// public const string FromAllowedToStartToNotAllowedToStart = "FromAllowedToStartToNotAllowedToStart"; /// public const string FromAllowedToStartToRunning = "FromAllowedToStartToRunning"; /// public const string FromCompletedToClosed = "FromCompletedToClosed"; /// public const string FromHeldToSuspended = "FromHeldToSuspended"; /// public const string FromInterruptedToAborted = "FromInterruptedToAborted"; /// public const string FromInterruptedToEnded = "FromInterruptedToEnded"; /// public const string FromInterruptedToRunning = "FromInterruptedToRunning"; /// public const string FromLoadedToReady = "FromLoadedToReady"; /// public const string FromLoadedToWaiting = "FromLoadedToWaiting"; /// public const string FromNotAllowedToStartToAborted = "FromNotAllowedToStartToAborted"; /// public const string FromNotAllowedToStartToAllowedToStart = "FromNotAllowedToStartToAllowedToStart"; /// public const string FromNotAllowedToStartToNotAllowedToStart = "FromNotAllowedToStartToNotAllowedToStart"; /// public const string FromReadyToLoaded = "FromReadyToLoaded"; /// public const string FromReadyToWaiting = "FromReadyToWaiting"; /// public const string FromRunningToAborted = "FromRunningToAborted"; /// public const string FromRunningToEnded = "FromRunningToEnded"; /// public const string FromRunningToInterrupted = "FromRunningToInterrupted"; /// public const string FromSuspendedToHeld = "FromSuspendedToHeld"; /// public const string FromWaitingToReady = "FromWaitingToReady"; /// public const string Held = "Held"; /// public const string http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2_ = "http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/"; /// public const string Interrupted = "Interrupted"; /// public const string InterruptedSubstates = "InterruptedSubstates"; /// public const string ISA95EndedStateMachineType = "ISA95EndedStateMachineType"; /// public const string ISA95EquipmentDataType = "ISA95EquipmentDataType"; /// public const string ISA95InterruptedStateMachineType = "ISA95InterruptedStateMachineType"; /// public const string ISA95JobOrderAndStateDataType = "ISA95JobOrderAndStateDataType"; /// public const string ISA95JobOrderDataType = "ISA95JobOrderDataType"; /// public const string ISA95JobOrderReceiverObjectType = "ISA95JobOrderReceiverObjectType"; /// public const string ISA95JobOrderReceiverSubStatesType = "ISA95JobOrderReceiverSubStatesType"; /// public const string ISA95JobOrderStatusEventType = "ISA95JobOrderStatusEventType"; /// public const string ISA95JobResponseDataType = "ISA95JobResponseDataType"; /// public const string ISA95JobResponseProviderObjectType = "ISA95JobResponseProviderObjectType"; /// public const string ISA95JobResponseReceiverObjectType = "ISA95JobResponseReceiverObjectType"; /// public const string ISA95MaterialDataType = "ISA95MaterialDataType"; /// public const string ISA95ParameterDataType = "ISA95ParameterDataType"; /// public const string ISA95PersonnelDataType = "ISA95PersonnelDataType"; /// public const string ISA95PhysicalAssetDataType = "ISA95PhysicalAssetDataType"; /// public const string ISA95PrepareStateMachineType = "ISA95PrepareStateMachineType"; /// public const string ISA95PropertyDataType = "ISA95PropertyDataType"; /// public const string ISA95StateDataType = "ISA95StateDataType"; /// public const string ISA95WorkMasterDataType = "ISA95WorkMasterDataType"; /// public const string JobOrder = "JobOrder"; /// public const string JobOrderList = "JobOrderList"; /// public const string JobOrderResponseList = "JobOrderResponseList"; /// public const string JobResponse = "JobResponse"; /// public const string JobState = "JobState"; /// public const string Loaded = "Loaded"; /// public const string MaterialClassID = "MaterialClassID"; /// public const string MaterialDefinitionID = "MaterialDefinitionID"; /// public const string MaxDownloadableJobOrders = "MaxDownloadableJobOrders"; /// public const string NotAllowedToStart = "NotAllowedToStart"; /// public const string NotAllowedToStartSubstates = "NotAllowedToStartSubstates"; /// public const string Pause = "Pause"; /// public const string PauseMethodType = "PauseMethodType"; /// public const string PersonnelID = "PersonnelID"; /// public const string PhysicalAssetID = "PhysicalAssetID"; /// public const string Ready = "Ready"; /// public const string ReceiveJobResponse = "ReceiveJobResponse"; /// public const string ReceiveJobResponseMethodType = "ReceiveJobResponseMethodType"; /// public const string RequestJobResponseByJobOrderID = "RequestJobResponseByJobOrderID"; /// public const string RequestJobResponseByJobOrderIDMethodType = "RequestJobResponseByJobOrderIDMethodType"; /// public const string RequestJobResponseByJobOrderState = "RequestJobResponseByJobOrderState"; /// public const string RequestJobResponseByJobOrderStateMethodType = "RequestJobResponseByJobOrderStateMethodType"; /// public const string Resume = "Resume"; /// public const string ResumeMethodType = "ResumeMethodType"; /// public const string RevokeStart = "RevokeStart"; /// public const string RevokeStartMethodType = "RevokeStartMethodType"; /// public const string Running = "Running"; /// public const string Start = "Start"; /// public const string StartMethodType = "StartMethodType"; /// public const string Stop = "Stop"; /// public const string StopMethodType = "StopMethodType"; /// public const string Store = "Store"; /// public const string StoreAndStart = "StoreAndStart"; /// public const string StoreAndStartMethodType = "StoreAndStartMethodType"; /// public const string StoreMethodType = "StoreMethodType"; /// public const string Suspended = "Suspended"; /// public const string Update = "Update"; /// public const string UpdateMethodType = "UpdateMethodType"; /// public const string Waiting = "Waiting"; /// public const string WorkMaster = "WorkMaster"; } #endregion #region Namespace Declarations /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Namespaces { /// /// The URI for the ISA95_JOBCONTROL_V2 namespace (.NET code namespace is 'UAModel.ISA95_JOBCONTROL_V2'). /// public const string ISA95_JOBCONTROL_V2 = "http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/"; /// /// The URI for the OpcUa namespace (.NET code namespace is 'Opc.Ua'). /// public const string OpcUa = "http://opcfoundation.org/UA/"; } #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Isa95Jobs/Design/UAModel.ISA95_JOBCONTROL_V2.DataTypes.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2024 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; using System; using System.Collections.Generic; using System.Runtime.Serialization; namespace UAModel.ISA95_JOBCONTROL_V2 { #region ISA95EquipmentDataType Class #if (!OPCUA_EXCLUDE_ISA95EquipmentDataType) /// /// public enum ISA95EquipmentDataTypeFields : uint { None = 0, /// Description = 0x1, /// EquipmentUse = 0x2, /// Quantity = 0x4, /// EngineeringUnits = 0x8, /// Properties = 0x10 } /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2)] public partial class ISA95EquipmentDataType : IEncodeable, IJsonEncodeable { #region Constructors /// public ISA95EquipmentDataType() { Initialize(); } [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } private void Initialize() { EncodingMask = ISA95EquipmentDataTypeFields.None; m_iD = null; m_description = new LocalizedTextCollection(); m_equipmentUse = null; m_quantity = null; m_engineeringUnits = new Opc.Ua.EUInformation(); m_properties = new ISA95PropertyDataTypeCollection(); } #endregion #region Public Properties // [DataMember(Name = "EncodingMask", IsRequired = true, Order = 0)] public ISA95EquipmentDataTypeFields EncodingMask { get; set; } /// [DataMember(Name = "ID", IsRequired = false, Order = 1)] public string ID { get { return m_iD; } set { m_iD = value; } } /// [DataMember(Name = "Description", IsRequired = false, Order = 2)] public LocalizedTextCollection Description { get { return m_description; } set { m_description = value; if (value == null) { m_description = new LocalizedTextCollection(); } } } /// [DataMember(Name = "EquipmentUse", IsRequired = false, Order = 3)] public string EquipmentUse { get { return m_equipmentUse; } set { m_equipmentUse = value; } } /// [DataMember(Name = "Quantity", IsRequired = false, Order = 4)] public string Quantity { get { return m_quantity; } set { m_quantity = value; } } /// [DataMember(Name = "EngineeringUnits", IsRequired = false, Order = 5)] public Opc.Ua.EUInformation EngineeringUnits { get { return m_engineeringUnits; } set { m_engineeringUnits = value; if (value == null) { m_engineeringUnits = new Opc.Ua.EUInformation(); } } } /// [DataMember(Name = "Properties", IsRequired = false, Order = 6)] public ISA95PropertyDataTypeCollection Properties { get { return m_properties; } set { m_properties = value; if (value == null) { m_properties = new ISA95PropertyDataTypeCollection(); } } } #endregion #region IEncodeable Members /// public virtual ExpandedNodeId TypeId => DataTypeIds.ISA95EquipmentDataType; /// public virtual ExpandedNodeId BinaryEncodingId => ObjectIds.ISA95EquipmentDataType_Encoding_DefaultBinary; /// public virtual ExpandedNodeId XmlEncodingId => ObjectIds.ISA95EquipmentDataType_Encoding_DefaultXml; /// public virtual ExpandedNodeId JsonEncodingId => ObjectIds.ISA95EquipmentDataType_Encoding_DefaultJson; /// public virtual void Encode(IEncoder encoder) { encoder.PushNamespace(UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); encoder.WriteUInt32(nameof(EncodingMask), (uint)EncodingMask); encoder.WriteString("ID", ID); if ((EncodingMask & ISA95EquipmentDataTypeFields.Description) != 0) encoder.WriteLocalizedTextArray("Description", Description); if ((EncodingMask & ISA95EquipmentDataTypeFields.EquipmentUse) != 0) encoder.WriteString("EquipmentUse", EquipmentUse); if ((EncodingMask & ISA95EquipmentDataTypeFields.Quantity) != 0) encoder.WriteString("Quantity", Quantity); if ((EncodingMask & ISA95EquipmentDataTypeFields.EngineeringUnits) != 0) encoder.WriteEncodeable("EngineeringUnits", EngineeringUnits, typeof(Opc.Ua.EUInformation)); if ((EncodingMask & ISA95EquipmentDataTypeFields.Properties) != 0) encoder.WriteEncodeableArray("Properties", Properties.ToArray(), typeof(ISA95PropertyDataType)); encoder.PopNamespace(); } /// public virtual void Decode(IDecoder decoder) { decoder.PushNamespace(UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); EncodingMask = (ISA95EquipmentDataTypeFields)decoder.ReadUInt32(nameof(EncodingMask)); ID = decoder.ReadString("ID"); if ((EncodingMask & ISA95EquipmentDataTypeFields.Description) != 0) Description = decoder.ReadLocalizedTextArray("Description"); if ((EncodingMask & ISA95EquipmentDataTypeFields.EquipmentUse) != 0) EquipmentUse = decoder.ReadString("EquipmentUse"); if ((EncodingMask & ISA95EquipmentDataTypeFields.Quantity) != 0) Quantity = decoder.ReadString("Quantity"); if ((EncodingMask & ISA95EquipmentDataTypeFields.EngineeringUnits) != 0) EngineeringUnits = (Opc.Ua.EUInformation)decoder.ReadEncodeable("EngineeringUnits", typeof(Opc.Ua.EUInformation)); if ((EncodingMask & ISA95EquipmentDataTypeFields.Properties) != 0) Properties = (ISA95PropertyDataTypeCollection)decoder.ReadEncodeableArray("Properties", typeof(ISA95PropertyDataType)); decoder.PopNamespace(); } /// public virtual bool IsEqual(IEncodeable encodeable) { if (Object.ReferenceEquals(this, encodeable)) { return true; } ISA95EquipmentDataType value = encodeable as ISA95EquipmentDataType; if (value == null) { return false; } if (value.EncodingMask != this.EncodingMask) return false; if (!Utils.IsEqual(m_iD, value.m_iD)) return false; if ((EncodingMask & ISA95EquipmentDataTypeFields.Description) != 0) if (!Utils.IsEqual(m_description, value.m_description)) return false; if ((EncodingMask & ISA95EquipmentDataTypeFields.EquipmentUse) != 0) if (!Utils.IsEqual(m_equipmentUse, value.m_equipmentUse)) return false; if ((EncodingMask & ISA95EquipmentDataTypeFields.Quantity) != 0) if (!Utils.IsEqual(m_quantity, value.m_quantity)) return false; if ((EncodingMask & ISA95EquipmentDataTypeFields.EngineeringUnits) != 0) if (!Utils.IsEqual(m_engineeringUnits, value.m_engineeringUnits)) return false; if ((EncodingMask & ISA95EquipmentDataTypeFields.Properties) != 0) if (!Utils.IsEqual(m_properties, value.m_properties)) return false; return true; } /// public virtual object Clone() { return (ISA95EquipmentDataType)this.MemberwiseClone(); } /// public new object MemberwiseClone() { ISA95EquipmentDataType clone = (ISA95EquipmentDataType)base.MemberwiseClone(); clone.EncodingMask = this.EncodingMask; clone.m_iD = (string)Utils.Clone(this.m_iD); if ((EncodingMask & ISA95EquipmentDataTypeFields.Description) != 0) clone.m_description = (LocalizedTextCollection)Utils.Clone(this.m_description); if ((EncodingMask & ISA95EquipmentDataTypeFields.EquipmentUse) != 0) clone.m_equipmentUse = (string)Utils.Clone(this.m_equipmentUse); if ((EncodingMask & ISA95EquipmentDataTypeFields.Quantity) != 0) clone.m_quantity = (string)Utils.Clone(this.m_quantity); if ((EncodingMask & ISA95EquipmentDataTypeFields.EngineeringUnits) != 0) clone.m_engineeringUnits = (Opc.Ua.EUInformation)Utils.Clone(this.m_engineeringUnits); if ((EncodingMask & ISA95EquipmentDataTypeFields.Properties) != 0) clone.m_properties = (ISA95PropertyDataTypeCollection)Utils.Clone(this.m_properties); return clone; } #endregion #region Private Fields private string m_iD; private LocalizedTextCollection m_description; private string m_equipmentUse; private string m_quantity; private Opc.Ua.EUInformation m_engineeringUnits; private ISA95PropertyDataTypeCollection m_properties; #endregion } #region ISA95EquipmentDataTypeCollection Class /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfISA95EquipmentDataType", Namespace = UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2, ItemName = "ISA95EquipmentDataType")] public partial class ISA95EquipmentDataTypeCollection : List, ICloneable { #region Constructors /// public ISA95EquipmentDataTypeCollection() { } /// public ISA95EquipmentDataTypeCollection(int capacity) : base(capacity) { } /// public ISA95EquipmentDataTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// public static implicit operator ISA95EquipmentDataTypeCollection(ISA95EquipmentDataType[] values) { if (values != null) { return new ISA95EquipmentDataTypeCollection(values); } return new ISA95EquipmentDataTypeCollection(); } /// public static explicit operator ISA95EquipmentDataType[](ISA95EquipmentDataTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #region ICloneable Methods /// public object Clone() { return (ISA95EquipmentDataTypeCollection)this.MemberwiseClone(); } #endregion /// public new object MemberwiseClone() { ISA95EquipmentDataTypeCollection clone = new ISA95EquipmentDataTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((ISA95EquipmentDataType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion #region ISA95JobOrderAndStateDataType Class #if (!OPCUA_EXCLUDE_ISA95JobOrderAndStateDataType) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2)] public partial class ISA95JobOrderAndStateDataType : IEncodeable, IJsonEncodeable { #region Constructors /// public ISA95JobOrderAndStateDataType() { Initialize(); } [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } private void Initialize() { m_jobOrder = new ISA95JobOrderDataType(); m_state = new ISA95StateDataTypeCollection(); } #endregion #region Public Properties /// [DataMember(Name = "JobOrder", IsRequired = false, Order = 1)] public ISA95JobOrderDataType JobOrder { get { return m_jobOrder; } set { m_jobOrder = value; if (value == null) { m_jobOrder = new ISA95JobOrderDataType(); } } } /// [DataMember(Name = "State", IsRequired = false, Order = 2)] public ISA95StateDataTypeCollection State { get { return m_state; } set { m_state = value; if (value == null) { m_state = new ISA95StateDataTypeCollection(); } } } #endregion #region IEncodeable Members /// public virtual ExpandedNodeId TypeId => DataTypeIds.ISA95JobOrderAndStateDataType; /// public virtual ExpandedNodeId BinaryEncodingId => ObjectIds.ISA95JobOrderAndStateDataType_Encoding_DefaultBinary; /// public virtual ExpandedNodeId XmlEncodingId => ObjectIds.ISA95JobOrderAndStateDataType_Encoding_DefaultXml; /// public virtual ExpandedNodeId JsonEncodingId => ObjectIds.ISA95JobOrderAndStateDataType_Encoding_DefaultJson; /// public virtual void Encode(IEncoder encoder) { encoder.PushNamespace(UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); encoder.WriteEncodeable("JobOrder", JobOrder, typeof(ISA95JobOrderDataType)); encoder.WriteEncodeableArray("State", State.ToArray(), typeof(ISA95StateDataType)); encoder.PopNamespace(); } /// public virtual void Decode(IDecoder decoder) { decoder.PushNamespace(UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); JobOrder = (ISA95JobOrderDataType)decoder.ReadEncodeable("JobOrder", typeof(ISA95JobOrderDataType)); State = (ISA95StateDataTypeCollection)decoder.ReadEncodeableArray("State", typeof(ISA95StateDataType)); decoder.PopNamespace(); } /// public virtual bool IsEqual(IEncodeable encodeable) { if (Object.ReferenceEquals(this, encodeable)) { return true; } ISA95JobOrderAndStateDataType value = encodeable as ISA95JobOrderAndStateDataType; if (value == null) { return false; } if (!Utils.IsEqual(m_jobOrder, value.m_jobOrder)) return false; if (!Utils.IsEqual(m_state, value.m_state)) return false; return true; } /// public virtual object Clone() { return (ISA95JobOrderAndStateDataType)this.MemberwiseClone(); } /// public new object MemberwiseClone() { ISA95JobOrderAndStateDataType clone = (ISA95JobOrderAndStateDataType)base.MemberwiseClone(); clone.m_jobOrder = (ISA95JobOrderDataType)Utils.Clone(this.m_jobOrder); clone.m_state = (ISA95StateDataTypeCollection)Utils.Clone(this.m_state); return clone; } #endregion #region Private Fields private ISA95JobOrderDataType m_jobOrder; private ISA95StateDataTypeCollection m_state; #endregion } #region ISA95JobOrderAndStateDataTypeCollection Class /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfISA95JobOrderAndStateDataType", Namespace = UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2, ItemName = "ISA95JobOrderAndStateDataType")] public partial class ISA95JobOrderAndStateDataTypeCollection : List, ICloneable { #region Constructors /// public ISA95JobOrderAndStateDataTypeCollection() { } /// public ISA95JobOrderAndStateDataTypeCollection(int capacity) : base(capacity) { } /// public ISA95JobOrderAndStateDataTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// public static implicit operator ISA95JobOrderAndStateDataTypeCollection(ISA95JobOrderAndStateDataType[] values) { if (values != null) { return new ISA95JobOrderAndStateDataTypeCollection(values); } return new ISA95JobOrderAndStateDataTypeCollection(); } /// public static explicit operator ISA95JobOrderAndStateDataType[](ISA95JobOrderAndStateDataTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #region ICloneable Methods /// public object Clone() { return (ISA95JobOrderAndStateDataTypeCollection)this.MemberwiseClone(); } #endregion /// public new object MemberwiseClone() { ISA95JobOrderAndStateDataTypeCollection clone = new ISA95JobOrderAndStateDataTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((ISA95JobOrderAndStateDataType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion #region ISA95JobOrderDataType Class #if (!OPCUA_EXCLUDE_ISA95JobOrderDataType) /// /// public enum ISA95JobOrderDataTypeFields : uint { None = 0, /// Description = 0x1, /// WorkMasterID = 0x2, /// StartTime = 0x4, /// EndTime = 0x8, /// Priority = 0x10, /// JobOrderParameters = 0x20, /// PersonnelRequirements = 0x40, /// EquipmentRequirements = 0x80, /// PhysicalAssetRequirements = 0x100, /// MaterialRequirements = 0x200 } /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2)] public partial class ISA95JobOrderDataType : IEncodeable, IJsonEncodeable { #region Constructors /// public ISA95JobOrderDataType() { Initialize(); } [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } private void Initialize() { EncodingMask = ISA95JobOrderDataTypeFields.None; m_jobOrderID = null; m_description = new LocalizedTextCollection(); m_workMasterID = new ISA95WorkMasterDataTypeCollection(); m_startTime = DateTime.MinValue; m_endTime = DateTime.MinValue; m_priority = (short)0; m_jobOrderParameters = new ISA95ParameterDataTypeCollection(); m_personnelRequirements = new ISA95PersonnelDataTypeCollection(); m_equipmentRequirements = new ISA95EquipmentDataTypeCollection(); m_physicalAssetRequirements = new ISA95PhysicalAssetDataTypeCollection(); m_materialRequirements = new ISA95MaterialDataTypeCollection(); } #endregion #region Public Properties // [DataMember(Name = "EncodingMask", IsRequired = true, Order = 0)] public ISA95JobOrderDataTypeFields EncodingMask { get; set; } /// [DataMember(Name = "JobOrderID", IsRequired = false, Order = 1)] public string JobOrderID { get { return m_jobOrderID; } set { m_jobOrderID = value; } } /// [DataMember(Name = "Description", IsRequired = false, Order = 2)] public LocalizedTextCollection Description { get { return m_description; } set { m_description = value; if (value == null) { m_description = new LocalizedTextCollection(); } } } /// [DataMember(Name = "WorkMasterID", IsRequired = false, Order = 3)] public ISA95WorkMasterDataTypeCollection WorkMasterID { get { return m_workMasterID; } set { m_workMasterID = value; if (value == null) { m_workMasterID = new ISA95WorkMasterDataTypeCollection(); } } } /// [DataMember(Name = "StartTime", IsRequired = false, Order = 4)] public DateTime StartTime { get { return m_startTime; } set { m_startTime = value; } } /// [DataMember(Name = "EndTime", IsRequired = false, Order = 5)] public DateTime EndTime { get { return m_endTime; } set { m_endTime = value; } } /// [DataMember(Name = "Priority", IsRequired = false, Order = 6)] public short Priority { get { return m_priority; } set { m_priority = value; } } /// [DataMember(Name = "JobOrderParameters", IsRequired = false, Order = 7)] public ISA95ParameterDataTypeCollection JobOrderParameters { get { return m_jobOrderParameters; } set { m_jobOrderParameters = value; if (value == null) { m_jobOrderParameters = new ISA95ParameterDataTypeCollection(); } } } /// [DataMember(Name = "PersonnelRequirements", IsRequired = false, Order = 8)] public ISA95PersonnelDataTypeCollection PersonnelRequirements { get { return m_personnelRequirements; } set { m_personnelRequirements = value; if (value == null) { m_personnelRequirements = new ISA95PersonnelDataTypeCollection(); } } } /// [DataMember(Name = "EquipmentRequirements", IsRequired = false, Order = 9)] public ISA95EquipmentDataTypeCollection EquipmentRequirements { get { return m_equipmentRequirements; } set { m_equipmentRequirements = value; if (value == null) { m_equipmentRequirements = new ISA95EquipmentDataTypeCollection(); } } } /// [DataMember(Name = "PhysicalAssetRequirements", IsRequired = false, Order = 10)] public ISA95PhysicalAssetDataTypeCollection PhysicalAssetRequirements { get { return m_physicalAssetRequirements; } set { m_physicalAssetRequirements = value; if (value == null) { m_physicalAssetRequirements = new ISA95PhysicalAssetDataTypeCollection(); } } } /// [DataMember(Name = "MaterialRequirements", IsRequired = false, Order = 11)] public ISA95MaterialDataTypeCollection MaterialRequirements { get { return m_materialRequirements; } set { m_materialRequirements = value; if (value == null) { m_materialRequirements = new ISA95MaterialDataTypeCollection(); } } } #endregion #region IEncodeable Members /// public virtual ExpandedNodeId TypeId => DataTypeIds.ISA95JobOrderDataType; /// public virtual ExpandedNodeId BinaryEncodingId => ObjectIds.ISA95JobOrderDataType_Encoding_DefaultBinary; /// public virtual ExpandedNodeId XmlEncodingId => ObjectIds.ISA95JobOrderDataType_Encoding_DefaultXml; /// public virtual ExpandedNodeId JsonEncodingId => ObjectIds.ISA95JobOrderDataType_Encoding_DefaultJson; /// public virtual void Encode(IEncoder encoder) { encoder.PushNamespace(UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); encoder.WriteUInt32(nameof(EncodingMask), (uint)EncodingMask); encoder.WriteString("JobOrderID", JobOrderID); if ((EncodingMask & ISA95JobOrderDataTypeFields.Description) != 0) encoder.WriteLocalizedTextArray("Description", Description); if ((EncodingMask & ISA95JobOrderDataTypeFields.WorkMasterID) != 0) encoder.WriteEncodeableArray("WorkMasterID", WorkMasterID.ToArray(), typeof(ISA95WorkMasterDataType)); if ((EncodingMask & ISA95JobOrderDataTypeFields.StartTime) != 0) encoder.WriteDateTime("StartTime", StartTime); if ((EncodingMask & ISA95JobOrderDataTypeFields.EndTime) != 0) encoder.WriteDateTime("EndTime", EndTime); if ((EncodingMask & ISA95JobOrderDataTypeFields.Priority) != 0) encoder.WriteInt16("Priority", Priority); if ((EncodingMask & ISA95JobOrderDataTypeFields.JobOrderParameters) != 0) encoder.WriteEncodeableArray("JobOrderParameters", JobOrderParameters.ToArray(), typeof(ISA95ParameterDataType)); if ((EncodingMask & ISA95JobOrderDataTypeFields.PersonnelRequirements) != 0) encoder.WriteEncodeableArray("PersonnelRequirements", PersonnelRequirements.ToArray(), typeof(ISA95PersonnelDataType)); if ((EncodingMask & ISA95JobOrderDataTypeFields.EquipmentRequirements) != 0) encoder.WriteEncodeableArray("EquipmentRequirements", EquipmentRequirements.ToArray(), typeof(ISA95EquipmentDataType)); if ((EncodingMask & ISA95JobOrderDataTypeFields.PhysicalAssetRequirements) != 0) encoder.WriteEncodeableArray("PhysicalAssetRequirements", PhysicalAssetRequirements.ToArray(), typeof(ISA95PhysicalAssetDataType)); if ((EncodingMask & ISA95JobOrderDataTypeFields.MaterialRequirements) != 0) encoder.WriteEncodeableArray("MaterialRequirements", MaterialRequirements.ToArray(), typeof(ISA95MaterialDataType)); encoder.PopNamespace(); } /// public virtual void Decode(IDecoder decoder) { decoder.PushNamespace(UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); EncodingMask = (ISA95JobOrderDataTypeFields)decoder.ReadUInt32(nameof(EncodingMask)); JobOrderID = decoder.ReadString("JobOrderID"); if ((EncodingMask & ISA95JobOrderDataTypeFields.Description) != 0) Description = decoder.ReadLocalizedTextArray("Description"); if ((EncodingMask & ISA95JobOrderDataTypeFields.WorkMasterID) != 0) WorkMasterID = (ISA95WorkMasterDataTypeCollection)decoder.ReadEncodeableArray("WorkMasterID", typeof(ISA95WorkMasterDataType)); if ((EncodingMask & ISA95JobOrderDataTypeFields.StartTime) != 0) StartTime = decoder.ReadDateTime("StartTime"); if ((EncodingMask & ISA95JobOrderDataTypeFields.EndTime) != 0) EndTime = decoder.ReadDateTime("EndTime"); if ((EncodingMask & ISA95JobOrderDataTypeFields.Priority) != 0) Priority = decoder.ReadInt16("Priority"); if ((EncodingMask & ISA95JobOrderDataTypeFields.JobOrderParameters) != 0) JobOrderParameters = (ISA95ParameterDataTypeCollection)decoder.ReadEncodeableArray("JobOrderParameters", typeof(ISA95ParameterDataType)); if ((EncodingMask & ISA95JobOrderDataTypeFields.PersonnelRequirements) != 0) PersonnelRequirements = (ISA95PersonnelDataTypeCollection)decoder.ReadEncodeableArray("PersonnelRequirements", typeof(ISA95PersonnelDataType)); if ((EncodingMask & ISA95JobOrderDataTypeFields.EquipmentRequirements) != 0) EquipmentRequirements = (ISA95EquipmentDataTypeCollection)decoder.ReadEncodeableArray("EquipmentRequirements", typeof(ISA95EquipmentDataType)); if ((EncodingMask & ISA95JobOrderDataTypeFields.PhysicalAssetRequirements) != 0) PhysicalAssetRequirements = (ISA95PhysicalAssetDataTypeCollection)decoder.ReadEncodeableArray("PhysicalAssetRequirements", typeof(ISA95PhysicalAssetDataType)); if ((EncodingMask & ISA95JobOrderDataTypeFields.MaterialRequirements) != 0) MaterialRequirements = (ISA95MaterialDataTypeCollection)decoder.ReadEncodeableArray("MaterialRequirements", typeof(ISA95MaterialDataType)); decoder.PopNamespace(); } /// public virtual bool IsEqual(IEncodeable encodeable) { if (Object.ReferenceEquals(this, encodeable)) { return true; } ISA95JobOrderDataType value = encodeable as ISA95JobOrderDataType; if (value == null) { return false; } if (value.EncodingMask != this.EncodingMask) return false; if (!Utils.IsEqual(m_jobOrderID, value.m_jobOrderID)) return false; if ((EncodingMask & ISA95JobOrderDataTypeFields.Description) != 0) if (!Utils.IsEqual(m_description, value.m_description)) return false; if ((EncodingMask & ISA95JobOrderDataTypeFields.WorkMasterID) != 0) if (!Utils.IsEqual(m_workMasterID, value.m_workMasterID)) return false; if ((EncodingMask & ISA95JobOrderDataTypeFields.StartTime) != 0) if (!Utils.IsEqual(m_startTime, value.m_startTime)) return false; if ((EncodingMask & ISA95JobOrderDataTypeFields.EndTime) != 0) if (!Utils.IsEqual(m_endTime, value.m_endTime)) return false; if ((EncodingMask & ISA95JobOrderDataTypeFields.Priority) != 0) if (!Utils.IsEqual(m_priority, value.m_priority)) return false; if ((EncodingMask & ISA95JobOrderDataTypeFields.JobOrderParameters) != 0) if (!Utils.IsEqual(m_jobOrderParameters, value.m_jobOrderParameters)) return false; if ((EncodingMask & ISA95JobOrderDataTypeFields.PersonnelRequirements) != 0) if (!Utils.IsEqual(m_personnelRequirements, value.m_personnelRequirements)) return false; if ((EncodingMask & ISA95JobOrderDataTypeFields.EquipmentRequirements) != 0) if (!Utils.IsEqual(m_equipmentRequirements, value.m_equipmentRequirements)) return false; if ((EncodingMask & ISA95JobOrderDataTypeFields.PhysicalAssetRequirements) != 0) if (!Utils.IsEqual(m_physicalAssetRequirements, value.m_physicalAssetRequirements)) return false; if ((EncodingMask & ISA95JobOrderDataTypeFields.MaterialRequirements) != 0) if (!Utils.IsEqual(m_materialRequirements, value.m_materialRequirements)) return false; return true; } /// public virtual object Clone() { return (ISA95JobOrderDataType)this.MemberwiseClone(); } /// public new object MemberwiseClone() { ISA95JobOrderDataType clone = (ISA95JobOrderDataType)base.MemberwiseClone(); clone.EncodingMask = this.EncodingMask; clone.m_jobOrderID = (string)Utils.Clone(this.m_jobOrderID); if ((EncodingMask & ISA95JobOrderDataTypeFields.Description) != 0) clone.m_description = (LocalizedTextCollection)Utils.Clone(this.m_description); if ((EncodingMask & ISA95JobOrderDataTypeFields.WorkMasterID) != 0) clone.m_workMasterID = (ISA95WorkMasterDataTypeCollection)Utils.Clone(this.m_workMasterID); if ((EncodingMask & ISA95JobOrderDataTypeFields.StartTime) != 0) clone.m_startTime = (DateTime)Utils.Clone(this.m_startTime); if ((EncodingMask & ISA95JobOrderDataTypeFields.EndTime) != 0) clone.m_endTime = (DateTime)Utils.Clone(this.m_endTime); if ((EncodingMask & ISA95JobOrderDataTypeFields.Priority) != 0) clone.m_priority = (short)Utils.Clone(this.m_priority); if ((EncodingMask & ISA95JobOrderDataTypeFields.JobOrderParameters) != 0) clone.m_jobOrderParameters = (ISA95ParameterDataTypeCollection)Utils.Clone(this.m_jobOrderParameters); if ((EncodingMask & ISA95JobOrderDataTypeFields.PersonnelRequirements) != 0) clone.m_personnelRequirements = (ISA95PersonnelDataTypeCollection)Utils.Clone(this.m_personnelRequirements); if ((EncodingMask & ISA95JobOrderDataTypeFields.EquipmentRequirements) != 0) clone.m_equipmentRequirements = (ISA95EquipmentDataTypeCollection)Utils.Clone(this.m_equipmentRequirements); if ((EncodingMask & ISA95JobOrderDataTypeFields.PhysicalAssetRequirements) != 0) clone.m_physicalAssetRequirements = (ISA95PhysicalAssetDataTypeCollection)Utils.Clone(this.m_physicalAssetRequirements); if ((EncodingMask & ISA95JobOrderDataTypeFields.MaterialRequirements) != 0) clone.m_materialRequirements = (ISA95MaterialDataTypeCollection)Utils.Clone(this.m_materialRequirements); return clone; } #endregion #region Private Fields private string m_jobOrderID; private LocalizedTextCollection m_description; private ISA95WorkMasterDataTypeCollection m_workMasterID; private DateTime m_startTime; private DateTime m_endTime; private short m_priority; private ISA95ParameterDataTypeCollection m_jobOrderParameters; private ISA95PersonnelDataTypeCollection m_personnelRequirements; private ISA95EquipmentDataTypeCollection m_equipmentRequirements; private ISA95PhysicalAssetDataTypeCollection m_physicalAssetRequirements; private ISA95MaterialDataTypeCollection m_materialRequirements; #endregion } #region ISA95JobOrderDataTypeCollection Class /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfISA95JobOrderDataType", Namespace = UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2, ItemName = "ISA95JobOrderDataType")] public partial class ISA95JobOrderDataTypeCollection : List, ICloneable { #region Constructors /// public ISA95JobOrderDataTypeCollection() { } /// public ISA95JobOrderDataTypeCollection(int capacity) : base(capacity) { } /// public ISA95JobOrderDataTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// public static implicit operator ISA95JobOrderDataTypeCollection(ISA95JobOrderDataType[] values) { if (values != null) { return new ISA95JobOrderDataTypeCollection(values); } return new ISA95JobOrderDataTypeCollection(); } /// public static explicit operator ISA95JobOrderDataType[](ISA95JobOrderDataTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #region ICloneable Methods /// public object Clone() { return (ISA95JobOrderDataTypeCollection)this.MemberwiseClone(); } #endregion /// public new object MemberwiseClone() { ISA95JobOrderDataTypeCollection clone = new ISA95JobOrderDataTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((ISA95JobOrderDataType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion #region ISA95JobResponseDataType Class #if (!OPCUA_EXCLUDE_ISA95JobResponseDataType) /// /// public enum ISA95JobResponseDataTypeFields : uint { None = 0, /// Description = 0x1, /// StartTime = 0x2, /// EndTime = 0x4, /// JobResponseData = 0x8, /// PersonnelActuals = 0x10, /// EquipmentActuals = 0x20, /// PhysicalAssetActuals = 0x40, /// MaterialActuals = 0x80 } /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2)] public partial class ISA95JobResponseDataType : IEncodeable, IJsonEncodeable { #region Constructors /// public ISA95JobResponseDataType() { Initialize(); } [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } private void Initialize() { EncodingMask = ISA95JobResponseDataTypeFields.None; m_jobResponseID = null; m_description = null; m_jobOrderID = null; m_startTime = DateTime.MinValue; m_endTime = DateTime.MinValue; m_jobState = new ISA95StateDataTypeCollection(); m_jobResponseData = new ISA95ParameterDataTypeCollection(); m_personnelActuals = new ISA95PersonnelDataTypeCollection(); m_equipmentActuals = new ISA95EquipmentDataTypeCollection(); m_physicalAssetActuals = new ISA95PhysicalAssetDataTypeCollection(); m_materialActuals = new ISA95MaterialDataTypeCollection(); } #endregion #region Public Properties // [DataMember(Name = "EncodingMask", IsRequired = true, Order = 0)] public ISA95JobResponseDataTypeFields EncodingMask { get; set; } /// [DataMember(Name = "JobResponseID", IsRequired = false, Order = 1)] public string JobResponseID { get { return m_jobResponseID; } set { m_jobResponseID = value; } } /// [DataMember(Name = "Description", IsRequired = false, Order = 2)] public LocalizedText Description { get { return m_description; } set { m_description = value; } } /// [DataMember(Name = "JobOrderID", IsRequired = false, Order = 3)] public string JobOrderID { get { return m_jobOrderID; } set { m_jobOrderID = value; } } /// [DataMember(Name = "StartTime", IsRequired = false, Order = 4)] public DateTime StartTime { get { return m_startTime; } set { m_startTime = value; } } /// [DataMember(Name = "EndTime", IsRequired = false, Order = 5)] public DateTime EndTime { get { return m_endTime; } set { m_endTime = value; } } /// [DataMember(Name = "JobState", IsRequired = false, Order = 6)] public ISA95StateDataTypeCollection JobState { get { return m_jobState; } set { m_jobState = value; if (value == null) { m_jobState = new ISA95StateDataTypeCollection(); } } } /// [DataMember(Name = "JobResponseData", IsRequired = false, Order = 7)] public ISA95ParameterDataTypeCollection JobResponseData { get { return m_jobResponseData; } set { m_jobResponseData = value; if (value == null) { m_jobResponseData = new ISA95ParameterDataTypeCollection(); } } } /// [DataMember(Name = "PersonnelActuals", IsRequired = false, Order = 8)] public ISA95PersonnelDataTypeCollection PersonnelActuals { get { return m_personnelActuals; } set { m_personnelActuals = value; if (value == null) { m_personnelActuals = new ISA95PersonnelDataTypeCollection(); } } } /// [DataMember(Name = "EquipmentActuals", IsRequired = false, Order = 9)] public ISA95EquipmentDataTypeCollection EquipmentActuals { get { return m_equipmentActuals; } set { m_equipmentActuals = value; if (value == null) { m_equipmentActuals = new ISA95EquipmentDataTypeCollection(); } } } /// [DataMember(Name = "PhysicalAssetActuals", IsRequired = false, Order = 10)] public ISA95PhysicalAssetDataTypeCollection PhysicalAssetActuals { get { return m_physicalAssetActuals; } set { m_physicalAssetActuals = value; if (value == null) { m_physicalAssetActuals = new ISA95PhysicalAssetDataTypeCollection(); } } } /// [DataMember(Name = "MaterialActuals", IsRequired = false, Order = 11)] public ISA95MaterialDataTypeCollection MaterialActuals { get { return m_materialActuals; } set { m_materialActuals = value; if (value == null) { m_materialActuals = new ISA95MaterialDataTypeCollection(); } } } #endregion #region IEncodeable Members /// public virtual ExpandedNodeId TypeId => DataTypeIds.ISA95JobResponseDataType; /// public virtual ExpandedNodeId BinaryEncodingId => ObjectIds.ISA95JobResponseDataType_Encoding_DefaultBinary; /// public virtual ExpandedNodeId XmlEncodingId => ObjectIds.ISA95JobResponseDataType_Encoding_DefaultXml; /// public virtual ExpandedNodeId JsonEncodingId => ObjectIds.ISA95JobResponseDataType_Encoding_DefaultJson; /// public virtual void Encode(IEncoder encoder) { encoder.PushNamespace(UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); encoder.WriteUInt32(nameof(EncodingMask), (uint)EncodingMask); encoder.WriteString("JobResponseID", JobResponseID); if ((EncodingMask & ISA95JobResponseDataTypeFields.Description) != 0) encoder.WriteLocalizedText("Description", Description); encoder.WriteString("JobOrderID", JobOrderID); if ((EncodingMask & ISA95JobResponseDataTypeFields.StartTime) != 0) encoder.WriteDateTime("StartTime", StartTime); if ((EncodingMask & ISA95JobResponseDataTypeFields.EndTime) != 0) encoder.WriteDateTime("EndTime", EndTime); encoder.WriteEncodeableArray("JobState", JobState.ToArray(), typeof(ISA95StateDataType)); if ((EncodingMask & ISA95JobResponseDataTypeFields.JobResponseData) != 0) encoder.WriteEncodeableArray("JobResponseData", JobResponseData.ToArray(), typeof(ISA95ParameterDataType)); if ((EncodingMask & ISA95JobResponseDataTypeFields.PersonnelActuals) != 0) encoder.WriteEncodeableArray("PersonnelActuals", PersonnelActuals.ToArray(), typeof(ISA95PersonnelDataType)); if ((EncodingMask & ISA95JobResponseDataTypeFields.EquipmentActuals) != 0) encoder.WriteEncodeableArray("EquipmentActuals", EquipmentActuals.ToArray(), typeof(ISA95EquipmentDataType)); if ((EncodingMask & ISA95JobResponseDataTypeFields.PhysicalAssetActuals) != 0) encoder.WriteEncodeableArray("PhysicalAssetActuals", PhysicalAssetActuals.ToArray(), typeof(ISA95PhysicalAssetDataType)); if ((EncodingMask & ISA95JobResponseDataTypeFields.MaterialActuals) != 0) encoder.WriteEncodeableArray("MaterialActuals", MaterialActuals.ToArray(), typeof(ISA95MaterialDataType)); encoder.PopNamespace(); } /// public virtual void Decode(IDecoder decoder) { decoder.PushNamespace(UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); EncodingMask = (ISA95JobResponseDataTypeFields)decoder.ReadUInt32(nameof(EncodingMask)); JobResponseID = decoder.ReadString("JobResponseID"); if ((EncodingMask & ISA95JobResponseDataTypeFields.Description) != 0) Description = decoder.ReadLocalizedText("Description"); JobOrderID = decoder.ReadString("JobOrderID"); if ((EncodingMask & ISA95JobResponseDataTypeFields.StartTime) != 0) StartTime = decoder.ReadDateTime("StartTime"); if ((EncodingMask & ISA95JobResponseDataTypeFields.EndTime) != 0) EndTime = decoder.ReadDateTime("EndTime"); JobState = (ISA95StateDataTypeCollection)decoder.ReadEncodeableArray("JobState", typeof(ISA95StateDataType)); if ((EncodingMask & ISA95JobResponseDataTypeFields.JobResponseData) != 0) JobResponseData = (ISA95ParameterDataTypeCollection)decoder.ReadEncodeableArray("JobResponseData", typeof(ISA95ParameterDataType)); if ((EncodingMask & ISA95JobResponseDataTypeFields.PersonnelActuals) != 0) PersonnelActuals = (ISA95PersonnelDataTypeCollection)decoder.ReadEncodeableArray("PersonnelActuals", typeof(ISA95PersonnelDataType)); if ((EncodingMask & ISA95JobResponseDataTypeFields.EquipmentActuals) != 0) EquipmentActuals = (ISA95EquipmentDataTypeCollection)decoder.ReadEncodeableArray("EquipmentActuals", typeof(ISA95EquipmentDataType)); if ((EncodingMask & ISA95JobResponseDataTypeFields.PhysicalAssetActuals) != 0) PhysicalAssetActuals = (ISA95PhysicalAssetDataTypeCollection)decoder.ReadEncodeableArray("PhysicalAssetActuals", typeof(ISA95PhysicalAssetDataType)); if ((EncodingMask & ISA95JobResponseDataTypeFields.MaterialActuals) != 0) MaterialActuals = (ISA95MaterialDataTypeCollection)decoder.ReadEncodeableArray("MaterialActuals", typeof(ISA95MaterialDataType)); decoder.PopNamespace(); } /// public virtual bool IsEqual(IEncodeable encodeable) { if (Object.ReferenceEquals(this, encodeable)) { return true; } ISA95JobResponseDataType value = encodeable as ISA95JobResponseDataType; if (value == null) { return false; } if (value.EncodingMask != this.EncodingMask) return false; if (!Utils.IsEqual(m_jobResponseID, value.m_jobResponseID)) return false; if ((EncodingMask & ISA95JobResponseDataTypeFields.Description) != 0) if (!Utils.IsEqual(m_description, value.m_description)) return false; if (!Utils.IsEqual(m_jobOrderID, value.m_jobOrderID)) return false; if ((EncodingMask & ISA95JobResponseDataTypeFields.StartTime) != 0) if (!Utils.IsEqual(m_startTime, value.m_startTime)) return false; if ((EncodingMask & ISA95JobResponseDataTypeFields.EndTime) != 0) if (!Utils.IsEqual(m_endTime, value.m_endTime)) return false; if (!Utils.IsEqual(m_jobState, value.m_jobState)) return false; if ((EncodingMask & ISA95JobResponseDataTypeFields.JobResponseData) != 0) if (!Utils.IsEqual(m_jobResponseData, value.m_jobResponseData)) return false; if ((EncodingMask & ISA95JobResponseDataTypeFields.PersonnelActuals) != 0) if (!Utils.IsEqual(m_personnelActuals, value.m_personnelActuals)) return false; if ((EncodingMask & ISA95JobResponseDataTypeFields.EquipmentActuals) != 0) if (!Utils.IsEqual(m_equipmentActuals, value.m_equipmentActuals)) return false; if ((EncodingMask & ISA95JobResponseDataTypeFields.PhysicalAssetActuals) != 0) if (!Utils.IsEqual(m_physicalAssetActuals, value.m_physicalAssetActuals)) return false; if ((EncodingMask & ISA95JobResponseDataTypeFields.MaterialActuals) != 0) if (!Utils.IsEqual(m_materialActuals, value.m_materialActuals)) return false; return true; } /// public virtual object Clone() { return (ISA95JobResponseDataType)this.MemberwiseClone(); } /// public new object MemberwiseClone() { ISA95JobResponseDataType clone = (ISA95JobResponseDataType)base.MemberwiseClone(); clone.EncodingMask = this.EncodingMask; clone.m_jobResponseID = (string)Utils.Clone(this.m_jobResponseID); if ((EncodingMask & ISA95JobResponseDataTypeFields.Description) != 0) clone.m_description = (LocalizedText)Utils.Clone(this.m_description); clone.m_jobOrderID = (string)Utils.Clone(this.m_jobOrderID); if ((EncodingMask & ISA95JobResponseDataTypeFields.StartTime) != 0) clone.m_startTime = (DateTime)Utils.Clone(this.m_startTime); if ((EncodingMask & ISA95JobResponseDataTypeFields.EndTime) != 0) clone.m_endTime = (DateTime)Utils.Clone(this.m_endTime); clone.m_jobState = (ISA95StateDataTypeCollection)Utils.Clone(this.m_jobState); if ((EncodingMask & ISA95JobResponseDataTypeFields.JobResponseData) != 0) clone.m_jobResponseData = (ISA95ParameterDataTypeCollection)Utils.Clone(this.m_jobResponseData); if ((EncodingMask & ISA95JobResponseDataTypeFields.PersonnelActuals) != 0) clone.m_personnelActuals = (ISA95PersonnelDataTypeCollection)Utils.Clone(this.m_personnelActuals); if ((EncodingMask & ISA95JobResponseDataTypeFields.EquipmentActuals) != 0) clone.m_equipmentActuals = (ISA95EquipmentDataTypeCollection)Utils.Clone(this.m_equipmentActuals); if ((EncodingMask & ISA95JobResponseDataTypeFields.PhysicalAssetActuals) != 0) clone.m_physicalAssetActuals = (ISA95PhysicalAssetDataTypeCollection)Utils.Clone(this.m_physicalAssetActuals); if ((EncodingMask & ISA95JobResponseDataTypeFields.MaterialActuals) != 0) clone.m_materialActuals = (ISA95MaterialDataTypeCollection)Utils.Clone(this.m_materialActuals); return clone; } #endregion #region Private Fields private string m_jobResponseID; private LocalizedText m_description; private string m_jobOrderID; private DateTime m_startTime; private DateTime m_endTime; private ISA95StateDataTypeCollection m_jobState; private ISA95ParameterDataTypeCollection m_jobResponseData; private ISA95PersonnelDataTypeCollection m_personnelActuals; private ISA95EquipmentDataTypeCollection m_equipmentActuals; private ISA95PhysicalAssetDataTypeCollection m_physicalAssetActuals; private ISA95MaterialDataTypeCollection m_materialActuals; #endregion } #region ISA95JobResponseDataTypeCollection Class /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfISA95JobResponseDataType", Namespace = UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2, ItemName = "ISA95JobResponseDataType")] public partial class ISA95JobResponseDataTypeCollection : List, ICloneable { #region Constructors /// public ISA95JobResponseDataTypeCollection() { } /// public ISA95JobResponseDataTypeCollection(int capacity) : base(capacity) { } /// public ISA95JobResponseDataTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// public static implicit operator ISA95JobResponseDataTypeCollection(ISA95JobResponseDataType[] values) { if (values != null) { return new ISA95JobResponseDataTypeCollection(values); } return new ISA95JobResponseDataTypeCollection(); } /// public static explicit operator ISA95JobResponseDataType[](ISA95JobResponseDataTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #region ICloneable Methods /// public object Clone() { return (ISA95JobResponseDataTypeCollection)this.MemberwiseClone(); } #endregion /// public new object MemberwiseClone() { ISA95JobResponseDataTypeCollection clone = new ISA95JobResponseDataTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((ISA95JobResponseDataType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion #region ISA95MaterialDataType Class #if (!OPCUA_EXCLUDE_ISA95MaterialDataType) /// /// public enum ISA95MaterialDataTypeFields : uint { None = 0, /// MaterialClassID = 0x1, /// MaterialDefinitionID = 0x2, /// MaterialLotID = 0x4, /// MaterialSublotID = 0x8, /// Description = 0x10, /// MaterialUse = 0x20, /// Quantity = 0x40, /// EngineeringUnits = 0x80, /// Properties = 0x100 } /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2)] public partial class ISA95MaterialDataType : IEncodeable, IJsonEncodeable { #region Constructors /// public ISA95MaterialDataType() { Initialize(); } [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } private void Initialize() { EncodingMask = ISA95MaterialDataTypeFields.None; m_materialClassID = null; m_materialDefinitionID = null; m_materialLotID = null; m_materialSublotID = null; m_description = new LocalizedTextCollection(); m_materialUse = null; m_quantity = null; m_engineeringUnits = new Opc.Ua.EUInformation(); m_properties = new ISA95PropertyDataTypeCollection(); } #endregion #region Public Properties // [DataMember(Name = "EncodingMask", IsRequired = true, Order = 0)] public ISA95MaterialDataTypeFields EncodingMask { get; set; } /// [DataMember(Name = "MaterialClassID", IsRequired = false, Order = 1)] public string MaterialClassID { get { return m_materialClassID; } set { m_materialClassID = value; } } /// [DataMember(Name = "MaterialDefinitionID", IsRequired = false, Order = 2)] public string MaterialDefinitionID { get { return m_materialDefinitionID; } set { m_materialDefinitionID = value; } } /// [DataMember(Name = "MaterialLotID", IsRequired = false, Order = 3)] public string MaterialLotID { get { return m_materialLotID; } set { m_materialLotID = value; } } /// [DataMember(Name = "MaterialSublotID", IsRequired = false, Order = 4)] public string MaterialSublotID { get { return m_materialSublotID; } set { m_materialSublotID = value; } } /// [DataMember(Name = "Description", IsRequired = false, Order = 5)] public LocalizedTextCollection Description { get { return m_description; } set { m_description = value; if (value == null) { m_description = new LocalizedTextCollection(); } } } /// [DataMember(Name = "MaterialUse", IsRequired = false, Order = 6)] public string MaterialUse { get { return m_materialUse; } set { m_materialUse = value; } } /// [DataMember(Name = "Quantity", IsRequired = false, Order = 7)] public string Quantity { get { return m_quantity; } set { m_quantity = value; } } /// [DataMember(Name = "EngineeringUnits", IsRequired = false, Order = 8)] public Opc.Ua.EUInformation EngineeringUnits { get { return m_engineeringUnits; } set { m_engineeringUnits = value; if (value == null) { m_engineeringUnits = new Opc.Ua.EUInformation(); } } } /// [DataMember(Name = "Properties", IsRequired = false, Order = 9)] public ISA95PropertyDataTypeCollection Properties { get { return m_properties; } set { m_properties = value; if (value == null) { m_properties = new ISA95PropertyDataTypeCollection(); } } } #endregion #region IEncodeable Members /// public virtual ExpandedNodeId TypeId => DataTypeIds.ISA95MaterialDataType; /// public virtual ExpandedNodeId BinaryEncodingId => ObjectIds.ISA95MaterialDataType_Encoding_DefaultBinary; /// public virtual ExpandedNodeId XmlEncodingId => ObjectIds.ISA95MaterialDataType_Encoding_DefaultXml; /// public virtual ExpandedNodeId JsonEncodingId => ObjectIds.ISA95MaterialDataType_Encoding_DefaultJson; /// public virtual void Encode(IEncoder encoder) { encoder.PushNamespace(UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); encoder.WriteUInt32(nameof(EncodingMask), (uint)EncodingMask); if ((EncodingMask & ISA95MaterialDataTypeFields.MaterialClassID) != 0) encoder.WriteString("MaterialClassID", MaterialClassID); if ((EncodingMask & ISA95MaterialDataTypeFields.MaterialDefinitionID) != 0) encoder.WriteString("MaterialDefinitionID", MaterialDefinitionID); if ((EncodingMask & ISA95MaterialDataTypeFields.MaterialLotID) != 0) encoder.WriteString("MaterialLotID", MaterialLotID); if ((EncodingMask & ISA95MaterialDataTypeFields.MaterialSublotID) != 0) encoder.WriteString("MaterialSublotID", MaterialSublotID); if ((EncodingMask & ISA95MaterialDataTypeFields.Description) != 0) encoder.WriteLocalizedTextArray("Description", Description); if ((EncodingMask & ISA95MaterialDataTypeFields.MaterialUse) != 0) encoder.WriteString("MaterialUse", MaterialUse); if ((EncodingMask & ISA95MaterialDataTypeFields.Quantity) != 0) encoder.WriteString("Quantity", Quantity); if ((EncodingMask & ISA95MaterialDataTypeFields.EngineeringUnits) != 0) encoder.WriteEncodeable("EngineeringUnits", EngineeringUnits, typeof(Opc.Ua.EUInformation)); if ((EncodingMask & ISA95MaterialDataTypeFields.Properties) != 0) encoder.WriteEncodeableArray("Properties", Properties.ToArray(), typeof(ISA95PropertyDataType)); encoder.PopNamespace(); } /// public virtual void Decode(IDecoder decoder) { decoder.PushNamespace(UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); EncodingMask = (ISA95MaterialDataTypeFields)decoder.ReadUInt32(nameof(EncodingMask)); if ((EncodingMask & ISA95MaterialDataTypeFields.MaterialClassID) != 0) MaterialClassID = decoder.ReadString("MaterialClassID"); if ((EncodingMask & ISA95MaterialDataTypeFields.MaterialDefinitionID) != 0) MaterialDefinitionID = decoder.ReadString("MaterialDefinitionID"); if ((EncodingMask & ISA95MaterialDataTypeFields.MaterialLotID) != 0) MaterialLotID = decoder.ReadString("MaterialLotID"); if ((EncodingMask & ISA95MaterialDataTypeFields.MaterialSublotID) != 0) MaterialSublotID = decoder.ReadString("MaterialSublotID"); if ((EncodingMask & ISA95MaterialDataTypeFields.Description) != 0) Description = decoder.ReadLocalizedTextArray("Description"); if ((EncodingMask & ISA95MaterialDataTypeFields.MaterialUse) != 0) MaterialUse = decoder.ReadString("MaterialUse"); if ((EncodingMask & ISA95MaterialDataTypeFields.Quantity) != 0) Quantity = decoder.ReadString("Quantity"); if ((EncodingMask & ISA95MaterialDataTypeFields.EngineeringUnits) != 0) EngineeringUnits = (Opc.Ua.EUInformation)decoder.ReadEncodeable("EngineeringUnits", typeof(Opc.Ua.EUInformation)); if ((EncodingMask & ISA95MaterialDataTypeFields.Properties) != 0) Properties = (ISA95PropertyDataTypeCollection)decoder.ReadEncodeableArray("Properties", typeof(ISA95PropertyDataType)); decoder.PopNamespace(); } /// public virtual bool IsEqual(IEncodeable encodeable) { if (Object.ReferenceEquals(this, encodeable)) { return true; } ISA95MaterialDataType value = encodeable as ISA95MaterialDataType; if (value == null) { return false; } if (value.EncodingMask != this.EncodingMask) return false; if ((EncodingMask & ISA95MaterialDataTypeFields.MaterialClassID) != 0) if (!Utils.IsEqual(m_materialClassID, value.m_materialClassID)) return false; if ((EncodingMask & ISA95MaterialDataTypeFields.MaterialDefinitionID) != 0) if (!Utils.IsEqual(m_materialDefinitionID, value.m_materialDefinitionID)) return false; if ((EncodingMask & ISA95MaterialDataTypeFields.MaterialLotID) != 0) if (!Utils.IsEqual(m_materialLotID, value.m_materialLotID)) return false; if ((EncodingMask & ISA95MaterialDataTypeFields.MaterialSublotID) != 0) if (!Utils.IsEqual(m_materialSublotID, value.m_materialSublotID)) return false; if ((EncodingMask & ISA95MaterialDataTypeFields.Description) != 0) if (!Utils.IsEqual(m_description, value.m_description)) return false; if ((EncodingMask & ISA95MaterialDataTypeFields.MaterialUse) != 0) if (!Utils.IsEqual(m_materialUse, value.m_materialUse)) return false; if ((EncodingMask & ISA95MaterialDataTypeFields.Quantity) != 0) if (!Utils.IsEqual(m_quantity, value.m_quantity)) return false; if ((EncodingMask & ISA95MaterialDataTypeFields.EngineeringUnits) != 0) if (!Utils.IsEqual(m_engineeringUnits, value.m_engineeringUnits)) return false; if ((EncodingMask & ISA95MaterialDataTypeFields.Properties) != 0) if (!Utils.IsEqual(m_properties, value.m_properties)) return false; return true; } /// public virtual object Clone() { return (ISA95MaterialDataType)this.MemberwiseClone(); } /// public new object MemberwiseClone() { ISA95MaterialDataType clone = (ISA95MaterialDataType)base.MemberwiseClone(); clone.EncodingMask = this.EncodingMask; if ((EncodingMask & ISA95MaterialDataTypeFields.MaterialClassID) != 0) clone.m_materialClassID = (string)Utils.Clone(this.m_materialClassID); if ((EncodingMask & ISA95MaterialDataTypeFields.MaterialDefinitionID) != 0) clone.m_materialDefinitionID = (string)Utils.Clone(this.m_materialDefinitionID); if ((EncodingMask & ISA95MaterialDataTypeFields.MaterialLotID) != 0) clone.m_materialLotID = (string)Utils.Clone(this.m_materialLotID); if ((EncodingMask & ISA95MaterialDataTypeFields.MaterialSublotID) != 0) clone.m_materialSublotID = (string)Utils.Clone(this.m_materialSublotID); if ((EncodingMask & ISA95MaterialDataTypeFields.Description) != 0) clone.m_description = (LocalizedTextCollection)Utils.Clone(this.m_description); if ((EncodingMask & ISA95MaterialDataTypeFields.MaterialUse) != 0) clone.m_materialUse = (string)Utils.Clone(this.m_materialUse); if ((EncodingMask & ISA95MaterialDataTypeFields.Quantity) != 0) clone.m_quantity = (string)Utils.Clone(this.m_quantity); if ((EncodingMask & ISA95MaterialDataTypeFields.EngineeringUnits) != 0) clone.m_engineeringUnits = (Opc.Ua.EUInformation)Utils.Clone(this.m_engineeringUnits); if ((EncodingMask & ISA95MaterialDataTypeFields.Properties) != 0) clone.m_properties = (ISA95PropertyDataTypeCollection)Utils.Clone(this.m_properties); return clone; } #endregion #region Private Fields private string m_materialClassID; private string m_materialDefinitionID; private string m_materialLotID; private string m_materialSublotID; private LocalizedTextCollection m_description; private string m_materialUse; private string m_quantity; private Opc.Ua.EUInformation m_engineeringUnits; private ISA95PropertyDataTypeCollection m_properties; #endregion } #region ISA95MaterialDataTypeCollection Class /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfISA95MaterialDataType", Namespace = UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2, ItemName = "ISA95MaterialDataType")] public partial class ISA95MaterialDataTypeCollection : List, ICloneable { #region Constructors /// public ISA95MaterialDataTypeCollection() { } /// public ISA95MaterialDataTypeCollection(int capacity) : base(capacity) { } /// public ISA95MaterialDataTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// public static implicit operator ISA95MaterialDataTypeCollection(ISA95MaterialDataType[] values) { if (values != null) { return new ISA95MaterialDataTypeCollection(values); } return new ISA95MaterialDataTypeCollection(); } /// public static explicit operator ISA95MaterialDataType[](ISA95MaterialDataTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #region ICloneable Methods /// public object Clone() { return (ISA95MaterialDataTypeCollection)this.MemberwiseClone(); } #endregion /// public new object MemberwiseClone() { ISA95MaterialDataTypeCollection clone = new ISA95MaterialDataTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((ISA95MaterialDataType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion #region ISA95ParameterDataType Class #if (!OPCUA_EXCLUDE_ISA95ParameterDataType) /// /// public enum ISA95ParameterDataTypeFields : uint { None = 0, /// Description = 0x1, /// EngineeringUnits = 0x2, /// Subparameters = 0x4 } /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2)] public partial class ISA95ParameterDataType : IEncodeable, IJsonEncodeable { #region Constructors /// public ISA95ParameterDataType() { Initialize(); } [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } private void Initialize() { EncodingMask = ISA95ParameterDataTypeFields.None; m_iD = null; m_value = Variant.Null; m_description = new LocalizedTextCollection(); m_engineeringUnits = new Opc.Ua.EUInformation(); m_subparameters = new ISA95ParameterDataTypeCollection(); } #endregion #region Public Properties // [DataMember(Name = "EncodingMask", IsRequired = true, Order = 0)] public ISA95ParameterDataTypeFields EncodingMask { get; set; } /// [DataMember(Name = "ID", IsRequired = false, Order = 1)] public string ID { get { return m_iD; } set { m_iD = value; } } /// [DataMember(Name = "Value", IsRequired = false, Order = 2)] public Variant Value { get { return m_value; } set { m_value = value; } } /// [DataMember(Name = "Description", IsRequired = false, Order = 3)] public LocalizedTextCollection Description { get { return m_description; } set { m_description = value; if (value == null) { m_description = new LocalizedTextCollection(); } } } /// [DataMember(Name = "EngineeringUnits", IsRequired = false, Order = 4)] public Opc.Ua.EUInformation EngineeringUnits { get { return m_engineeringUnits; } set { m_engineeringUnits = value; if (value == null) { m_engineeringUnits = new Opc.Ua.EUInformation(); } } } /// [DataMember(Name = "Subparameters", IsRequired = false, Order = 5)] public ISA95ParameterDataTypeCollection Subparameters { get { return m_subparameters; } set { m_subparameters = value; if (value == null) { m_subparameters = new ISA95ParameterDataTypeCollection(); } } } #endregion #region IEncodeable Members /// public virtual ExpandedNodeId TypeId => DataTypeIds.ISA95ParameterDataType; /// public virtual ExpandedNodeId BinaryEncodingId => ObjectIds.ISA95ParameterDataType_Encoding_DefaultBinary; /// public virtual ExpandedNodeId XmlEncodingId => ObjectIds.ISA95ParameterDataType_Encoding_DefaultXml; /// public virtual ExpandedNodeId JsonEncodingId => ObjectIds.ISA95ParameterDataType_Encoding_DefaultJson; /// public virtual void Encode(IEncoder encoder) { encoder.PushNamespace(UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); encoder.WriteUInt32(nameof(EncodingMask), (uint)EncodingMask); encoder.WriteString("ID", ID); encoder.WriteVariant("Value", Value); if ((EncodingMask & ISA95ParameterDataTypeFields.Description) != 0) encoder.WriteLocalizedTextArray("Description", Description); if ((EncodingMask & ISA95ParameterDataTypeFields.EngineeringUnits) != 0) encoder.WriteEncodeable("EngineeringUnits", EngineeringUnits, typeof(Opc.Ua.EUInformation)); if ((EncodingMask & ISA95ParameterDataTypeFields.Subparameters) != 0) encoder.WriteEncodeableArray("Subparameters", Subparameters.ToArray(), typeof(ISA95ParameterDataType)); encoder.PopNamespace(); } /// public virtual void Decode(IDecoder decoder) { decoder.PushNamespace(UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); EncodingMask = (ISA95ParameterDataTypeFields)decoder.ReadUInt32(nameof(EncodingMask)); ID = decoder.ReadString("ID"); Value = decoder.ReadVariant("Value"); if ((EncodingMask & ISA95ParameterDataTypeFields.Description) != 0) Description = decoder.ReadLocalizedTextArray("Description"); if ((EncodingMask & ISA95ParameterDataTypeFields.EngineeringUnits) != 0) EngineeringUnits = (Opc.Ua.EUInformation)decoder.ReadEncodeable("EngineeringUnits", typeof(Opc.Ua.EUInformation)); if ((EncodingMask & ISA95ParameterDataTypeFields.Subparameters) != 0) Subparameters = (ISA95ParameterDataTypeCollection)decoder.ReadEncodeableArray("Subparameters", typeof(ISA95ParameterDataType)); decoder.PopNamespace(); } /// public virtual bool IsEqual(IEncodeable encodeable) { if (Object.ReferenceEquals(this, encodeable)) { return true; } ISA95ParameterDataType value = encodeable as ISA95ParameterDataType; if (value == null) { return false; } if (value.EncodingMask != this.EncodingMask) return false; if (!Utils.IsEqual(m_iD, value.m_iD)) return false; if (!Utils.IsEqual(m_value, value.m_value)) return false; if ((EncodingMask & ISA95ParameterDataTypeFields.Description) != 0) if (!Utils.IsEqual(m_description, value.m_description)) return false; if ((EncodingMask & ISA95ParameterDataTypeFields.EngineeringUnits) != 0) if (!Utils.IsEqual(m_engineeringUnits, value.m_engineeringUnits)) return false; if ((EncodingMask & ISA95ParameterDataTypeFields.Subparameters) != 0) if (!Utils.IsEqual(m_subparameters, value.m_subparameters)) return false; return true; } /// public virtual object Clone() { return (ISA95ParameterDataType)this.MemberwiseClone(); } /// public new object MemberwiseClone() { ISA95ParameterDataType clone = (ISA95ParameterDataType)base.MemberwiseClone(); clone.EncodingMask = this.EncodingMask; clone.m_iD = (string)Utils.Clone(this.m_iD); clone.m_value = (Variant)Utils.Clone(this.m_value); if ((EncodingMask & ISA95ParameterDataTypeFields.Description) != 0) clone.m_description = (LocalizedTextCollection)Utils.Clone(this.m_description); if ((EncodingMask & ISA95ParameterDataTypeFields.EngineeringUnits) != 0) clone.m_engineeringUnits = (Opc.Ua.EUInformation)Utils.Clone(this.m_engineeringUnits); if ((EncodingMask & ISA95ParameterDataTypeFields.Subparameters) != 0) clone.m_subparameters = (ISA95ParameterDataTypeCollection)Utils.Clone(this.m_subparameters); return clone; } #endregion #region Private Fields private string m_iD; private Variant m_value; private LocalizedTextCollection m_description; private Opc.Ua.EUInformation m_engineeringUnits; private ISA95ParameterDataTypeCollection m_subparameters; #endregion } #region ISA95ParameterDataTypeCollection Class /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfISA95ParameterDataType", Namespace = UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2, ItemName = "ISA95ParameterDataType")] public partial class ISA95ParameterDataTypeCollection : List, ICloneable { #region Constructors /// public ISA95ParameterDataTypeCollection() { } /// public ISA95ParameterDataTypeCollection(int capacity) : base(capacity) { } /// public ISA95ParameterDataTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// public static implicit operator ISA95ParameterDataTypeCollection(ISA95ParameterDataType[] values) { if (values != null) { return new ISA95ParameterDataTypeCollection(values); } return new ISA95ParameterDataTypeCollection(); } /// public static explicit operator ISA95ParameterDataType[](ISA95ParameterDataTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #region ICloneable Methods /// public object Clone() { return (ISA95ParameterDataTypeCollection)this.MemberwiseClone(); } #endregion /// public new object MemberwiseClone() { ISA95ParameterDataTypeCollection clone = new ISA95ParameterDataTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((ISA95ParameterDataType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion #region ISA95PersonnelDataType Class #if (!OPCUA_EXCLUDE_ISA95PersonnelDataType) /// /// public enum ISA95PersonnelDataTypeFields : uint { None = 0, /// Description = 0x1, /// PersonnelUse = 0x2, /// Quantity = 0x4, /// EngineeringUnits = 0x8, /// Properties = 0x10 } /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2)] public partial class ISA95PersonnelDataType : IEncodeable, IJsonEncodeable { #region Constructors /// public ISA95PersonnelDataType() { Initialize(); } [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } private void Initialize() { EncodingMask = ISA95PersonnelDataTypeFields.None; m_iD = null; m_description = new LocalizedTextCollection(); m_personnelUse = null; m_quantity = null; m_engineeringUnits = new Opc.Ua.EUInformation(); m_properties = new ISA95PropertyDataTypeCollection(); } #endregion #region Public Properties // [DataMember(Name = "EncodingMask", IsRequired = true, Order = 0)] public ISA95PersonnelDataTypeFields EncodingMask { get; set; } /// [DataMember(Name = "ID", IsRequired = false, Order = 1)] public string ID { get { return m_iD; } set { m_iD = value; } } /// [DataMember(Name = "Description", IsRequired = false, Order = 2)] public LocalizedTextCollection Description { get { return m_description; } set { m_description = value; if (value == null) { m_description = new LocalizedTextCollection(); } } } /// [DataMember(Name = "PersonnelUse", IsRequired = false, Order = 3)] public string PersonnelUse { get { return m_personnelUse; } set { m_personnelUse = value; } } /// [DataMember(Name = "Quantity", IsRequired = false, Order = 4)] public string Quantity { get { return m_quantity; } set { m_quantity = value; } } /// [DataMember(Name = "EngineeringUnits", IsRequired = false, Order = 5)] public Opc.Ua.EUInformation EngineeringUnits { get { return m_engineeringUnits; } set { m_engineeringUnits = value; if (value == null) { m_engineeringUnits = new Opc.Ua.EUInformation(); } } } /// [DataMember(Name = "Properties", IsRequired = false, Order = 6)] public ISA95PropertyDataTypeCollection Properties { get { return m_properties; } set { m_properties = value; if (value == null) { m_properties = new ISA95PropertyDataTypeCollection(); } } } #endregion #region IEncodeable Members /// public virtual ExpandedNodeId TypeId => DataTypeIds.ISA95PersonnelDataType; /// public virtual ExpandedNodeId BinaryEncodingId => ObjectIds.ISA95PersonnelDataType_Encoding_DefaultBinary; /// public virtual ExpandedNodeId XmlEncodingId => ObjectIds.ISA95PersonnelDataType_Encoding_DefaultXml; /// public virtual ExpandedNodeId JsonEncodingId => ObjectIds.ISA95PersonnelDataType_Encoding_DefaultJson; /// public virtual void Encode(IEncoder encoder) { encoder.PushNamespace(UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); encoder.WriteUInt32(nameof(EncodingMask), (uint)EncodingMask); encoder.WriteString("ID", ID); if ((EncodingMask & ISA95PersonnelDataTypeFields.Description) != 0) encoder.WriteLocalizedTextArray("Description", Description); if ((EncodingMask & ISA95PersonnelDataTypeFields.PersonnelUse) != 0) encoder.WriteString("PersonnelUse", PersonnelUse); if ((EncodingMask & ISA95PersonnelDataTypeFields.Quantity) != 0) encoder.WriteString("Quantity", Quantity); if ((EncodingMask & ISA95PersonnelDataTypeFields.EngineeringUnits) != 0) encoder.WriteEncodeable("EngineeringUnits", EngineeringUnits, typeof(Opc.Ua.EUInformation)); if ((EncodingMask & ISA95PersonnelDataTypeFields.Properties) != 0) encoder.WriteEncodeableArray("Properties", Properties.ToArray(), typeof(ISA95PropertyDataType)); encoder.PopNamespace(); } /// public virtual void Decode(IDecoder decoder) { decoder.PushNamespace(UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); EncodingMask = (ISA95PersonnelDataTypeFields)decoder.ReadUInt32(nameof(EncodingMask)); ID = decoder.ReadString("ID"); if ((EncodingMask & ISA95PersonnelDataTypeFields.Description) != 0) Description = decoder.ReadLocalizedTextArray("Description"); if ((EncodingMask & ISA95PersonnelDataTypeFields.PersonnelUse) != 0) PersonnelUse = decoder.ReadString("PersonnelUse"); if ((EncodingMask & ISA95PersonnelDataTypeFields.Quantity) != 0) Quantity = decoder.ReadString("Quantity"); if ((EncodingMask & ISA95PersonnelDataTypeFields.EngineeringUnits) != 0) EngineeringUnits = (Opc.Ua.EUInformation)decoder.ReadEncodeable("EngineeringUnits", typeof(Opc.Ua.EUInformation)); if ((EncodingMask & ISA95PersonnelDataTypeFields.Properties) != 0) Properties = (ISA95PropertyDataTypeCollection)decoder.ReadEncodeableArray("Properties", typeof(ISA95PropertyDataType)); decoder.PopNamespace(); } /// public virtual bool IsEqual(IEncodeable encodeable) { if (Object.ReferenceEquals(this, encodeable)) { return true; } ISA95PersonnelDataType value = encodeable as ISA95PersonnelDataType; if (value == null) { return false; } if (value.EncodingMask != this.EncodingMask) return false; if (!Utils.IsEqual(m_iD, value.m_iD)) return false; if ((EncodingMask & ISA95PersonnelDataTypeFields.Description) != 0) if (!Utils.IsEqual(m_description, value.m_description)) return false; if ((EncodingMask & ISA95PersonnelDataTypeFields.PersonnelUse) != 0) if (!Utils.IsEqual(m_personnelUse, value.m_personnelUse)) return false; if ((EncodingMask & ISA95PersonnelDataTypeFields.Quantity) != 0) if (!Utils.IsEqual(m_quantity, value.m_quantity)) return false; if ((EncodingMask & ISA95PersonnelDataTypeFields.EngineeringUnits) != 0) if (!Utils.IsEqual(m_engineeringUnits, value.m_engineeringUnits)) return false; if ((EncodingMask & ISA95PersonnelDataTypeFields.Properties) != 0) if (!Utils.IsEqual(m_properties, value.m_properties)) return false; return true; } /// public virtual object Clone() { return (ISA95PersonnelDataType)this.MemberwiseClone(); } /// public new object MemberwiseClone() { ISA95PersonnelDataType clone = (ISA95PersonnelDataType)base.MemberwiseClone(); clone.EncodingMask = this.EncodingMask; clone.m_iD = (string)Utils.Clone(this.m_iD); if ((EncodingMask & ISA95PersonnelDataTypeFields.Description) != 0) clone.m_description = (LocalizedTextCollection)Utils.Clone(this.m_description); if ((EncodingMask & ISA95PersonnelDataTypeFields.PersonnelUse) != 0) clone.m_personnelUse = (string)Utils.Clone(this.m_personnelUse); if ((EncodingMask & ISA95PersonnelDataTypeFields.Quantity) != 0) clone.m_quantity = (string)Utils.Clone(this.m_quantity); if ((EncodingMask & ISA95PersonnelDataTypeFields.EngineeringUnits) != 0) clone.m_engineeringUnits = (Opc.Ua.EUInformation)Utils.Clone(this.m_engineeringUnits); if ((EncodingMask & ISA95PersonnelDataTypeFields.Properties) != 0) clone.m_properties = (ISA95PropertyDataTypeCollection)Utils.Clone(this.m_properties); return clone; } #endregion #region Private Fields private string m_iD; private LocalizedTextCollection m_description; private string m_personnelUse; private string m_quantity; private Opc.Ua.EUInformation m_engineeringUnits; private ISA95PropertyDataTypeCollection m_properties; #endregion } #region ISA95PersonnelDataTypeCollection Class /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfISA95PersonnelDataType", Namespace = UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2, ItemName = "ISA95PersonnelDataType")] public partial class ISA95PersonnelDataTypeCollection : List, ICloneable { #region Constructors /// public ISA95PersonnelDataTypeCollection() { } /// public ISA95PersonnelDataTypeCollection(int capacity) : base(capacity) { } /// public ISA95PersonnelDataTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// public static implicit operator ISA95PersonnelDataTypeCollection(ISA95PersonnelDataType[] values) { if (values != null) { return new ISA95PersonnelDataTypeCollection(values); } return new ISA95PersonnelDataTypeCollection(); } /// public static explicit operator ISA95PersonnelDataType[](ISA95PersonnelDataTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #region ICloneable Methods /// public object Clone() { return (ISA95PersonnelDataTypeCollection)this.MemberwiseClone(); } #endregion /// public new object MemberwiseClone() { ISA95PersonnelDataTypeCollection clone = new ISA95PersonnelDataTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((ISA95PersonnelDataType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion #region ISA95PhysicalAssetDataType Class #if (!OPCUA_EXCLUDE_ISA95PhysicalAssetDataType) /// /// public enum ISA95PhysicalAssetDataTypeFields : uint { None = 0, /// Description = 0x1, /// PhysicalAssetUse = 0x2, /// Quantity = 0x4, /// EngineeringUnits = 0x8, /// Properties = 0x10 } /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2)] public partial class ISA95PhysicalAssetDataType : IEncodeable, IJsonEncodeable { #region Constructors /// public ISA95PhysicalAssetDataType() { Initialize(); } [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } private void Initialize() { EncodingMask = ISA95PhysicalAssetDataTypeFields.None; m_iD = null; m_description = new LocalizedTextCollection(); m_physicalAssetUse = null; m_quantity = null; m_engineeringUnits = new Opc.Ua.EUInformation(); m_properties = new ISA95PropertyDataTypeCollection(); } #endregion #region Public Properties // [DataMember(Name = "EncodingMask", IsRequired = true, Order = 0)] public ISA95PhysicalAssetDataTypeFields EncodingMask { get; set; } /// [DataMember(Name = "ID", IsRequired = false, Order = 1)] public string ID { get { return m_iD; } set { m_iD = value; } } /// [DataMember(Name = "Description", IsRequired = false, Order = 2)] public LocalizedTextCollection Description { get { return m_description; } set { m_description = value; if (value == null) { m_description = new LocalizedTextCollection(); } } } /// [DataMember(Name = "PhysicalAssetUse", IsRequired = false, Order = 3)] public string PhysicalAssetUse { get { return m_physicalAssetUse; } set { m_physicalAssetUse = value; } } /// [DataMember(Name = "Quantity", IsRequired = false, Order = 4)] public string Quantity { get { return m_quantity; } set { m_quantity = value; } } /// [DataMember(Name = "EngineeringUnits", IsRequired = false, Order = 5)] public Opc.Ua.EUInformation EngineeringUnits { get { return m_engineeringUnits; } set { m_engineeringUnits = value; if (value == null) { m_engineeringUnits = new Opc.Ua.EUInformation(); } } } /// [DataMember(Name = "Properties", IsRequired = false, Order = 6)] public ISA95PropertyDataTypeCollection Properties { get { return m_properties; } set { m_properties = value; if (value == null) { m_properties = new ISA95PropertyDataTypeCollection(); } } } #endregion #region IEncodeable Members /// public virtual ExpandedNodeId TypeId => DataTypeIds.ISA95PhysicalAssetDataType; /// public virtual ExpandedNodeId BinaryEncodingId => ObjectIds.ISA95PhysicalAssetDataType_Encoding_DefaultBinary; /// public virtual ExpandedNodeId XmlEncodingId => ObjectIds.ISA95PhysicalAssetDataType_Encoding_DefaultXml; /// public virtual ExpandedNodeId JsonEncodingId => ObjectIds.ISA95PhysicalAssetDataType_Encoding_DefaultJson; /// public virtual void Encode(IEncoder encoder) { encoder.PushNamespace(UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); encoder.WriteUInt32(nameof(EncodingMask), (uint)EncodingMask); encoder.WriteString("ID", ID); if ((EncodingMask & ISA95PhysicalAssetDataTypeFields.Description) != 0) encoder.WriteLocalizedTextArray("Description", Description); if ((EncodingMask & ISA95PhysicalAssetDataTypeFields.PhysicalAssetUse) != 0) encoder.WriteString("PhysicalAssetUse", PhysicalAssetUse); if ((EncodingMask & ISA95PhysicalAssetDataTypeFields.Quantity) != 0) encoder.WriteString("Quantity", Quantity); if ((EncodingMask & ISA95PhysicalAssetDataTypeFields.EngineeringUnits) != 0) encoder.WriteEncodeable("EngineeringUnits", EngineeringUnits, typeof(Opc.Ua.EUInformation)); if ((EncodingMask & ISA95PhysicalAssetDataTypeFields.Properties) != 0) encoder.WriteEncodeableArray("Properties", Properties.ToArray(), typeof(ISA95PropertyDataType)); encoder.PopNamespace(); } /// public virtual void Decode(IDecoder decoder) { decoder.PushNamespace(UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); EncodingMask = (ISA95PhysicalAssetDataTypeFields)decoder.ReadUInt32(nameof(EncodingMask)); ID = decoder.ReadString("ID"); if ((EncodingMask & ISA95PhysicalAssetDataTypeFields.Description) != 0) Description = decoder.ReadLocalizedTextArray("Description"); if ((EncodingMask & ISA95PhysicalAssetDataTypeFields.PhysicalAssetUse) != 0) PhysicalAssetUse = decoder.ReadString("PhysicalAssetUse"); if ((EncodingMask & ISA95PhysicalAssetDataTypeFields.Quantity) != 0) Quantity = decoder.ReadString("Quantity"); if ((EncodingMask & ISA95PhysicalAssetDataTypeFields.EngineeringUnits) != 0) EngineeringUnits = (Opc.Ua.EUInformation)decoder.ReadEncodeable("EngineeringUnits", typeof(Opc.Ua.EUInformation)); if ((EncodingMask & ISA95PhysicalAssetDataTypeFields.Properties) != 0) Properties = (ISA95PropertyDataTypeCollection)decoder.ReadEncodeableArray("Properties", typeof(ISA95PropertyDataType)); decoder.PopNamespace(); } /// public virtual bool IsEqual(IEncodeable encodeable) { if (Object.ReferenceEquals(this, encodeable)) { return true; } ISA95PhysicalAssetDataType value = encodeable as ISA95PhysicalAssetDataType; if (value == null) { return false; } if (value.EncodingMask != this.EncodingMask) return false; if (!Utils.IsEqual(m_iD, value.m_iD)) return false; if ((EncodingMask & ISA95PhysicalAssetDataTypeFields.Description) != 0) if (!Utils.IsEqual(m_description, value.m_description)) return false; if ((EncodingMask & ISA95PhysicalAssetDataTypeFields.PhysicalAssetUse) != 0) if (!Utils.IsEqual(m_physicalAssetUse, value.m_physicalAssetUse)) return false; if ((EncodingMask & ISA95PhysicalAssetDataTypeFields.Quantity) != 0) if (!Utils.IsEqual(m_quantity, value.m_quantity)) return false; if ((EncodingMask & ISA95PhysicalAssetDataTypeFields.EngineeringUnits) != 0) if (!Utils.IsEqual(m_engineeringUnits, value.m_engineeringUnits)) return false; if ((EncodingMask & ISA95PhysicalAssetDataTypeFields.Properties) != 0) if (!Utils.IsEqual(m_properties, value.m_properties)) return false; return true; } /// public virtual object Clone() { return (ISA95PhysicalAssetDataType)this.MemberwiseClone(); } /// public new object MemberwiseClone() { ISA95PhysicalAssetDataType clone = (ISA95PhysicalAssetDataType)base.MemberwiseClone(); clone.EncodingMask = this.EncodingMask; clone.m_iD = (string)Utils.Clone(this.m_iD); if ((EncodingMask & ISA95PhysicalAssetDataTypeFields.Description) != 0) clone.m_description = (LocalizedTextCollection)Utils.Clone(this.m_description); if ((EncodingMask & ISA95PhysicalAssetDataTypeFields.PhysicalAssetUse) != 0) clone.m_physicalAssetUse = (string)Utils.Clone(this.m_physicalAssetUse); if ((EncodingMask & ISA95PhysicalAssetDataTypeFields.Quantity) != 0) clone.m_quantity = (string)Utils.Clone(this.m_quantity); if ((EncodingMask & ISA95PhysicalAssetDataTypeFields.EngineeringUnits) != 0) clone.m_engineeringUnits = (Opc.Ua.EUInformation)Utils.Clone(this.m_engineeringUnits); if ((EncodingMask & ISA95PhysicalAssetDataTypeFields.Properties) != 0) clone.m_properties = (ISA95PropertyDataTypeCollection)Utils.Clone(this.m_properties); return clone; } #endregion #region Private Fields private string m_iD; private LocalizedTextCollection m_description; private string m_physicalAssetUse; private string m_quantity; private Opc.Ua.EUInformation m_engineeringUnits; private ISA95PropertyDataTypeCollection m_properties; #endregion } #region ISA95PhysicalAssetDataTypeCollection Class /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfISA95PhysicalAssetDataType", Namespace = UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2, ItemName = "ISA95PhysicalAssetDataType")] public partial class ISA95PhysicalAssetDataTypeCollection : List, ICloneable { #region Constructors /// public ISA95PhysicalAssetDataTypeCollection() { } /// public ISA95PhysicalAssetDataTypeCollection(int capacity) : base(capacity) { } /// public ISA95PhysicalAssetDataTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// public static implicit operator ISA95PhysicalAssetDataTypeCollection(ISA95PhysicalAssetDataType[] values) { if (values != null) { return new ISA95PhysicalAssetDataTypeCollection(values); } return new ISA95PhysicalAssetDataTypeCollection(); } /// public static explicit operator ISA95PhysicalAssetDataType[](ISA95PhysicalAssetDataTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #region ICloneable Methods /// public object Clone() { return (ISA95PhysicalAssetDataTypeCollection)this.MemberwiseClone(); } #endregion /// public new object MemberwiseClone() { ISA95PhysicalAssetDataTypeCollection clone = new ISA95PhysicalAssetDataTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((ISA95PhysicalAssetDataType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion #region ISA95PropertyDataType Class #if (!OPCUA_EXCLUDE_ISA95PropertyDataType) /// /// public enum ISA95PropertyDataTypeFields : uint { None = 0, /// Description = 0x1, /// EngineeringUnits = 0x2, /// Subproperties = 0x4 } /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2)] public partial class ISA95PropertyDataType : IEncodeable, IJsonEncodeable { #region Constructors /// public ISA95PropertyDataType() { Initialize(); } [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } private void Initialize() { EncodingMask = ISA95PropertyDataTypeFields.None; m_iD = null; m_value = Variant.Null; m_description = new LocalizedTextCollection(); m_engineeringUnits = new Opc.Ua.EUInformation(); m_subproperties = new ISA95PropertyDataTypeCollection(); } #endregion #region Public Properties // [DataMember(Name = "EncodingMask", IsRequired = true, Order = 0)] public ISA95PropertyDataTypeFields EncodingMask { get; set; } /// [DataMember(Name = "ID", IsRequired = false, Order = 1)] public string ID { get { return m_iD; } set { m_iD = value; } } /// [DataMember(Name = "Value", IsRequired = false, Order = 2)] public Variant Value { get { return m_value; } set { m_value = value; } } /// [DataMember(Name = "Description", IsRequired = false, Order = 3)] public LocalizedTextCollection Description { get { return m_description; } set { m_description = value; if (value == null) { m_description = new LocalizedTextCollection(); } } } /// [DataMember(Name = "EngineeringUnits", IsRequired = false, Order = 4)] public Opc.Ua.EUInformation EngineeringUnits { get { return m_engineeringUnits; } set { m_engineeringUnits = value; if (value == null) { m_engineeringUnits = new Opc.Ua.EUInformation(); } } } /// [DataMember(Name = "Subproperties", IsRequired = false, Order = 5)] public ISA95PropertyDataTypeCollection Subproperties { get { return m_subproperties; } set { m_subproperties = value; if (value == null) { m_subproperties = new ISA95PropertyDataTypeCollection(); } } } #endregion #region IEncodeable Members /// public virtual ExpandedNodeId TypeId => DataTypeIds.ISA95PropertyDataType; /// public virtual ExpandedNodeId BinaryEncodingId => ObjectIds.ISA95PropertyDataType_Encoding_DefaultBinary; /// public virtual ExpandedNodeId XmlEncodingId => ObjectIds.ISA95PropertyDataType_Encoding_DefaultXml; /// public virtual ExpandedNodeId JsonEncodingId => ObjectIds.ISA95PropertyDataType_Encoding_DefaultJson; /// public virtual void Encode(IEncoder encoder) { encoder.PushNamespace(UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); encoder.WriteUInt32(nameof(EncodingMask), (uint)EncodingMask); encoder.WriteString("ID", ID); encoder.WriteVariant("Value", Value); if ((EncodingMask & ISA95PropertyDataTypeFields.Description) != 0) encoder.WriteLocalizedTextArray("Description", Description); if ((EncodingMask & ISA95PropertyDataTypeFields.EngineeringUnits) != 0) encoder.WriteEncodeable("EngineeringUnits", EngineeringUnits, typeof(Opc.Ua.EUInformation)); if ((EncodingMask & ISA95PropertyDataTypeFields.Subproperties) != 0) encoder.WriteEncodeableArray("Subproperties", Subproperties.ToArray(), typeof(ISA95PropertyDataType)); encoder.PopNamespace(); } /// public virtual void Decode(IDecoder decoder) { decoder.PushNamespace(UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); EncodingMask = (ISA95PropertyDataTypeFields)decoder.ReadUInt32(nameof(EncodingMask)); ID = decoder.ReadString("ID"); Value = decoder.ReadVariant("Value"); if ((EncodingMask & ISA95PropertyDataTypeFields.Description) != 0) Description = decoder.ReadLocalizedTextArray("Description"); if ((EncodingMask & ISA95PropertyDataTypeFields.EngineeringUnits) != 0) EngineeringUnits = (Opc.Ua.EUInformation)decoder.ReadEncodeable("EngineeringUnits", typeof(Opc.Ua.EUInformation)); if ((EncodingMask & ISA95PropertyDataTypeFields.Subproperties) != 0) Subproperties = (ISA95PropertyDataTypeCollection)decoder.ReadEncodeableArray("Subproperties", typeof(ISA95PropertyDataType)); decoder.PopNamespace(); } /// public virtual bool IsEqual(IEncodeable encodeable) { if (Object.ReferenceEquals(this, encodeable)) { return true; } ISA95PropertyDataType value = encodeable as ISA95PropertyDataType; if (value == null) { return false; } if (value.EncodingMask != this.EncodingMask) return false; if (!Utils.IsEqual(m_iD, value.m_iD)) return false; if (!Utils.IsEqual(m_value, value.m_value)) return false; if ((EncodingMask & ISA95PropertyDataTypeFields.Description) != 0) if (!Utils.IsEqual(m_description, value.m_description)) return false; if ((EncodingMask & ISA95PropertyDataTypeFields.EngineeringUnits) != 0) if (!Utils.IsEqual(m_engineeringUnits, value.m_engineeringUnits)) return false; if ((EncodingMask & ISA95PropertyDataTypeFields.Subproperties) != 0) if (!Utils.IsEqual(m_subproperties, value.m_subproperties)) return false; return true; } /// public virtual object Clone() { return (ISA95PropertyDataType)this.MemberwiseClone(); } /// public new object MemberwiseClone() { ISA95PropertyDataType clone = (ISA95PropertyDataType)base.MemberwiseClone(); clone.EncodingMask = this.EncodingMask; clone.m_iD = (string)Utils.Clone(this.m_iD); clone.m_value = (Variant)Utils.Clone(this.m_value); if ((EncodingMask & ISA95PropertyDataTypeFields.Description) != 0) clone.m_description = (LocalizedTextCollection)Utils.Clone(this.m_description); if ((EncodingMask & ISA95PropertyDataTypeFields.EngineeringUnits) != 0) clone.m_engineeringUnits = (Opc.Ua.EUInformation)Utils.Clone(this.m_engineeringUnits); if ((EncodingMask & ISA95PropertyDataTypeFields.Subproperties) != 0) clone.m_subproperties = (ISA95PropertyDataTypeCollection)Utils.Clone(this.m_subproperties); return clone; } #endregion #region Private Fields private string m_iD; private Variant m_value; private LocalizedTextCollection m_description; private Opc.Ua.EUInformation m_engineeringUnits; private ISA95PropertyDataTypeCollection m_subproperties; #endregion } #region ISA95PropertyDataTypeCollection Class /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfISA95PropertyDataType", Namespace = UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2, ItemName = "ISA95PropertyDataType")] public partial class ISA95PropertyDataTypeCollection : List, ICloneable { #region Constructors /// public ISA95PropertyDataTypeCollection() { } /// public ISA95PropertyDataTypeCollection(int capacity) : base(capacity) { } /// public ISA95PropertyDataTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// public static implicit operator ISA95PropertyDataTypeCollection(ISA95PropertyDataType[] values) { if (values != null) { return new ISA95PropertyDataTypeCollection(values); } return new ISA95PropertyDataTypeCollection(); } /// public static explicit operator ISA95PropertyDataType[](ISA95PropertyDataTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #region ICloneable Methods /// public object Clone() { return (ISA95PropertyDataTypeCollection)this.MemberwiseClone(); } #endregion /// public new object MemberwiseClone() { ISA95PropertyDataTypeCollection clone = new ISA95PropertyDataTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((ISA95PropertyDataType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion #region ISA95StateDataType Class #if (!OPCUA_EXCLUDE_ISA95StateDataType) /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2)] public partial class ISA95StateDataType : IEncodeable, IJsonEncodeable { #region Constructors /// public ISA95StateDataType() { Initialize(); } [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } private void Initialize() { m_browsePath = new Opc.Ua.RelativePath(); m_stateText = null; m_stateNumber = (uint)0; } #endregion #region Public Properties /// [DataMember(Name = "BrowsePath", IsRequired = false, Order = 1)] public Opc.Ua.RelativePath BrowsePath { get { return m_browsePath; } set { m_browsePath = value; if (value == null) { m_browsePath = new Opc.Ua.RelativePath(); } } } /// [DataMember(Name = "StateText", IsRequired = false, Order = 2)] public LocalizedText StateText { get { return m_stateText; } set { m_stateText = value; } } /// [DataMember(Name = "StateNumber", IsRequired = false, Order = 3)] public uint StateNumber { get { return m_stateNumber; } set { m_stateNumber = value; } } #endregion #region IEncodeable Members /// public virtual ExpandedNodeId TypeId => DataTypeIds.ISA95StateDataType; /// public virtual ExpandedNodeId BinaryEncodingId => ObjectIds.ISA95StateDataType_Encoding_DefaultBinary; /// public virtual ExpandedNodeId XmlEncodingId => ObjectIds.ISA95StateDataType_Encoding_DefaultXml; /// public virtual ExpandedNodeId JsonEncodingId => ObjectIds.ISA95StateDataType_Encoding_DefaultJson; /// public virtual void Encode(IEncoder encoder) { encoder.PushNamespace(UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); encoder.WriteEncodeable("BrowsePath", BrowsePath, typeof(Opc.Ua.RelativePath)); encoder.WriteLocalizedText("StateText", StateText); encoder.WriteUInt32("StateNumber", StateNumber); encoder.PopNamespace(); } /// public virtual void Decode(IDecoder decoder) { decoder.PushNamespace(UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); BrowsePath = (Opc.Ua.RelativePath)decoder.ReadEncodeable("BrowsePath", typeof(Opc.Ua.RelativePath)); StateText = decoder.ReadLocalizedText("StateText"); StateNumber = decoder.ReadUInt32("StateNumber"); decoder.PopNamespace(); } /// public virtual bool IsEqual(IEncodeable encodeable) { if (Object.ReferenceEquals(this, encodeable)) { return true; } ISA95StateDataType value = encodeable as ISA95StateDataType; if (value == null) { return false; } if (!Utils.IsEqual(m_browsePath, value.m_browsePath)) return false; if (!Utils.IsEqual(m_stateText, value.m_stateText)) return false; if (!Utils.IsEqual(m_stateNumber, value.m_stateNumber)) return false; return true; } /// public virtual object Clone() { return (ISA95StateDataType)this.MemberwiseClone(); } /// public new object MemberwiseClone() { ISA95StateDataType clone = (ISA95StateDataType)base.MemberwiseClone(); clone.m_browsePath = (Opc.Ua.RelativePath)Utils.Clone(this.m_browsePath); clone.m_stateText = (LocalizedText)Utils.Clone(this.m_stateText); clone.m_stateNumber = (uint)Utils.Clone(this.m_stateNumber); return clone; } #endregion #region Private Fields private Opc.Ua.RelativePath m_browsePath; private LocalizedText m_stateText; private uint m_stateNumber; #endregion } #region ISA95StateDataTypeCollection Class /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfISA95StateDataType", Namespace = UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2, ItemName = "ISA95StateDataType")] public partial class ISA95StateDataTypeCollection : List, ICloneable { #region Constructors /// public ISA95StateDataTypeCollection() { } /// public ISA95StateDataTypeCollection(int capacity) : base(capacity) { } /// public ISA95StateDataTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// public static implicit operator ISA95StateDataTypeCollection(ISA95StateDataType[] values) { if (values != null) { return new ISA95StateDataTypeCollection(values); } return new ISA95StateDataTypeCollection(); } /// public static explicit operator ISA95StateDataType[](ISA95StateDataTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #region ICloneable Methods /// public object Clone() { return (ISA95StateDataTypeCollection)this.MemberwiseClone(); } #endregion /// public new object MemberwiseClone() { ISA95StateDataTypeCollection clone = new ISA95StateDataTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((ISA95StateDataType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion #region ISA95WorkMasterDataType Class #if (!OPCUA_EXCLUDE_ISA95WorkMasterDataType) /// /// public enum ISA95WorkMasterDataTypeFields : uint { None = 0, /// Description = 0x1, /// Parameters = 0x2 } /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2)] public partial class ISA95WorkMasterDataType : IEncodeable, IJsonEncodeable { #region Constructors /// public ISA95WorkMasterDataType() { Initialize(); } [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } private void Initialize() { EncodingMask = ISA95WorkMasterDataTypeFields.None; m_iD = null; m_description = null; m_parameters = new ISA95ParameterDataTypeCollection(); } #endregion #region Public Properties // [DataMember(Name = "EncodingMask", IsRequired = true, Order = 0)] public ISA95WorkMasterDataTypeFields EncodingMask { get; set; } /// [DataMember(Name = "ID", IsRequired = false, Order = 1)] public string ID { get { return m_iD; } set { m_iD = value; } } /// [DataMember(Name = "Description", IsRequired = false, Order = 2)] public LocalizedText Description { get { return m_description; } set { m_description = value; } } /// [DataMember(Name = "Parameters", IsRequired = false, Order = 3)] public ISA95ParameterDataTypeCollection Parameters { get { return m_parameters; } set { m_parameters = value; if (value == null) { m_parameters = new ISA95ParameterDataTypeCollection(); } } } #endregion #region IEncodeable Members /// public virtual ExpandedNodeId TypeId => DataTypeIds.ISA95WorkMasterDataType; /// public virtual ExpandedNodeId BinaryEncodingId => ObjectIds.ISA95WorkMasterDataType_Encoding_DefaultBinary; /// public virtual ExpandedNodeId XmlEncodingId => ObjectIds.ISA95WorkMasterDataType_Encoding_DefaultXml; /// public virtual ExpandedNodeId JsonEncodingId => ObjectIds.ISA95WorkMasterDataType_Encoding_DefaultJson; /// public virtual void Encode(IEncoder encoder) { encoder.PushNamespace(UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); encoder.WriteUInt32(nameof(EncodingMask), (uint)EncodingMask); encoder.WriteString("ID", ID); if ((EncodingMask & ISA95WorkMasterDataTypeFields.Description) != 0) encoder.WriteLocalizedText("Description", Description); if ((EncodingMask & ISA95WorkMasterDataTypeFields.Parameters) != 0) encoder.WriteEncodeableArray("Parameters", Parameters.ToArray(), typeof(ISA95ParameterDataType)); encoder.PopNamespace(); } /// public virtual void Decode(IDecoder decoder) { decoder.PushNamespace(UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2); EncodingMask = (ISA95WorkMasterDataTypeFields)decoder.ReadUInt32(nameof(EncodingMask)); ID = decoder.ReadString("ID"); if ((EncodingMask & ISA95WorkMasterDataTypeFields.Description) != 0) Description = decoder.ReadLocalizedText("Description"); if ((EncodingMask & ISA95WorkMasterDataTypeFields.Parameters) != 0) Parameters = (ISA95ParameterDataTypeCollection)decoder.ReadEncodeableArray("Parameters", typeof(ISA95ParameterDataType)); decoder.PopNamespace(); } /// public virtual bool IsEqual(IEncodeable encodeable) { if (Object.ReferenceEquals(this, encodeable)) { return true; } ISA95WorkMasterDataType value = encodeable as ISA95WorkMasterDataType; if (value == null) { return false; } if (value.EncodingMask != this.EncodingMask) return false; if (!Utils.IsEqual(m_iD, value.m_iD)) return false; if ((EncodingMask & ISA95WorkMasterDataTypeFields.Description) != 0) if (!Utils.IsEqual(m_description, value.m_description)) return false; if ((EncodingMask & ISA95WorkMasterDataTypeFields.Parameters) != 0) if (!Utils.IsEqual(m_parameters, value.m_parameters)) return false; return true; } /// public virtual object Clone() { return (ISA95WorkMasterDataType)this.MemberwiseClone(); } /// public new object MemberwiseClone() { ISA95WorkMasterDataType clone = (ISA95WorkMasterDataType)base.MemberwiseClone(); clone.EncodingMask = this.EncodingMask; clone.m_iD = (string)Utils.Clone(this.m_iD); if ((EncodingMask & ISA95WorkMasterDataTypeFields.Description) != 0) clone.m_description = (LocalizedText)Utils.Clone(this.m_description); if ((EncodingMask & ISA95WorkMasterDataTypeFields.Parameters) != 0) clone.m_parameters = (ISA95ParameterDataTypeCollection)Utils.Clone(this.m_parameters); return clone; } #endregion #region Private Fields private string m_iD; private LocalizedText m_description; private ISA95ParameterDataTypeCollection m_parameters; #endregion } #region ISA95WorkMasterDataTypeCollection Class /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfISA95WorkMasterDataType", Namespace = UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2, ItemName = "ISA95WorkMasterDataType")] public partial class ISA95WorkMasterDataTypeCollection : List, ICloneable { #region Constructors /// public ISA95WorkMasterDataTypeCollection() { } /// public ISA95WorkMasterDataTypeCollection(int capacity) : base(capacity) { } /// public ISA95WorkMasterDataTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// public static implicit operator ISA95WorkMasterDataTypeCollection(ISA95WorkMasterDataType[] values) { if (values != null) { return new ISA95WorkMasterDataTypeCollection(values); } return new ISA95WorkMasterDataTypeCollection(); } /// public static explicit operator ISA95WorkMasterDataType[](ISA95WorkMasterDataTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #region ICloneable Methods /// public object Clone() { return (ISA95WorkMasterDataTypeCollection)this.MemberwiseClone(); } #endregion /// public new object MemberwiseClone() { ISA95WorkMasterDataTypeCollection clone = new ISA95WorkMasterDataTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((ISA95WorkMasterDataType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Isa95Jobs/Design/UAModel.ISA95_JOBCONTROL_V2.NodeIds.csv ================================================ ISA95PrepareStateMachineType,1001,ObjectType ISA95JobOrderReceiverObjectType,1002,ObjectType ISA95JobResponseProviderObjectType,1003,ObjectType ISA95JobResponseReceiverObjectType,1004,ObjectType ISA95EndedStateMachineType,1005,ObjectType ISA95JobOrderStatusEventType,1006,ObjectType ISA95InterruptedStateMachineType,1007,ObjectType ISA95JobOrderReceiverSubStatesType,1008,ObjectType ISA95PropertyDataType,3002,DataType ISA95ParameterDataType,3003,DataType ISA95EquipmentDataType,3005,DataType ISA95StateDataType,3006,DataType ISA95WorkMasterDataType,3007,DataType ISA95JobOrderDataType,3008,DataType ISA95MaterialDataType,3010,DataType ISA95PersonnelDataType,3011,DataType ISA95PhysicalAssetDataType,3012,DataType ISA95JobResponseDataType,3013,DataType ISA95JobOrderAndStateDataType,3015,DataType ISA95PrepareStateMachineType_Waiting,5000,Object http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2_,5001,Object ISA95PropertyDataType_Encoding_DefaultBinary,5002,Object ISA95PropertyDataType_Encoding_DefaultXml,5003,Object ISA95PropertyDataType_Encoding_DefaultJson,5004,Object ISA95ParameterDataType_Encoding_DefaultBinary,5005,Object ISA95ParameterDataType_Encoding_DefaultXml,5006,Object ISA95ParameterDataType_Encoding_DefaultJson,5007,Object ISA95EquipmentDataType_Encoding_DefaultBinary,5008,Object ISA95EquipmentDataType_Encoding_DefaultXml,5009,Object ISA95EquipmentDataType_Encoding_DefaultJson,5010,Object ISA95WorkMasterDataType_Encoding_DefaultBinary,5011,Object ISA95WorkMasterDataType_Encoding_DefaultXml,5012,Object ISA95WorkMasterDataType_Encoding_DefaultJson,5013,Object ISA95JobOrderDataType_Encoding_DefaultBinary,5014,Object ISA95JobOrderDataType_Encoding_DefaultXml,5015,Object ISA95JobOrderDataType_Encoding_DefaultJson,5016,Object ISA95MaterialDataType_Encoding_DefaultBinary,5017,Object ISA95MaterialDataType_Encoding_DefaultXml,5018,Object ISA95MaterialDataType_Encoding_DefaultJson,5019,Object ISA95PersonnelDataType_Encoding_DefaultBinary,5020,Object ISA95PersonnelDataType_Encoding_DefaultXml,5021,Object ISA95PersonnelDataType_Encoding_DefaultJson,5022,Object ISA95PhysicalAssetDataType_Encoding_DefaultBinary,5023,Object ISA95PhysicalAssetDataType_Encoding_DefaultXml,5024,Object ISA95PhysicalAssetDataType_Encoding_DefaultJson,5025,Object ISA95JobResponseDataType_Encoding_DefaultBinary,5026,Object ISA95JobResponseDataType_Encoding_DefaultXml,5027,Object ISA95JobResponseDataType_Encoding_DefaultJson,5028,Object ISA95StateDataType_Encoding_DefaultBinary,5029,Object ISA95StateDataType_Encoding_DefaultXml,5030,Object ISA95StateDataType_Encoding_DefaultJson,5031,Object ISA95JobOrderAndStateDataType_Encoding_DefaultBinary,5032,Object ISA95JobOrderAndStateDataType_Encoding_DefaultXml,5033,Object ISA95JobOrderAndStateDataType_Encoding_DefaultJson,5034,Object ISA95JobOrderReceiverObjectType_NotAllowedToStart,5035,Object ISA95JobOrderReceiverObjectType_AllowedToStart,5036,Object ISA95JobOrderReceiverObjectType_Running,5037,Object ISA95JobOrderReceiverObjectType_Interrupted,5038,Object ISA95JobOrderReceiverObjectType_Ended,5039,Object ISA95JobOrderReceiverObjectType_Aborted,5040,Object ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToNotAllowedToStart,5041,Object ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToAllowedToStart,5042,Object ISA95JobOrderReceiverObjectType_FromAllowedToStartToNotAllowedToStart,5043,Object ISA95JobOrderReceiverObjectType_FromAllowedToStartToAllowedToStart,5044,Object ISA95JobOrderReceiverObjectType_FromAllowedToStartToRunning,5045,Object ISA95JobOrderReceiverObjectType_FromRunningToInterrupted,5046,Object ISA95JobOrderReceiverObjectType_FromRunningToEnded,5047,Object ISA95JobOrderReceiverObjectType_FromRunningToAborted,5048,Object ISA95JobOrderReceiverObjectType_FromInterruptedToAborted,5049,Object ISA95JobOrderReceiverObjectType_FromInterruptedToRunning,5050,Object ISA95JobOrderReceiverObjectType_FromInterruptedToEnded,5051,Object ISA95PrepareStateMachineType_Ready,5052,Object ISA95PrepareStateMachineType_Loaded,5053,Object ISA95PrepareStateMachineType_FromWaitingToReady,5054,Object ISA95PrepareStateMachineType_FromReadyToLoaded,5055,Object ISA95EndedStateMachineType_Completed,5056,Object ISA95EndedStateMachineType_Closed,5057,Object ISA95EndedStateMachineType_FromCompletedToClosed,5058,Object ISA95InterruptedStateMachineType_Held,5059,Object ISA95InterruptedStateMachineType_Suspended,5060,Object ISA95InterruptedStateMachineType_FromHeldToSuspended,5061,Object ISA95InterruptedStateMachineType_FromSuspendedToHeld,5062,Object ISA95JobOrderReceiverSubStatesType_NotAllowedToStart,5063,Object ISA95JobOrderReceiverSubStatesType_AllowedToStart,5064,Object ISA95JobOrderReceiverSubStatesType_Running,5065,Object ISA95JobOrderReceiverSubStatesType_Interrupted,5066,Object ISA95JobOrderReceiverSubStatesType_Ended,5067,Object ISA95JobOrderReceiverSubStatesType_Aborted,5068,Object ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToNotAllowedToStart,5069,Object ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToAllowedToStart,5070,Object ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToNotAllowedToStart,5071,Object ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToAllowedToStart,5072,Object ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToRunning,5073,Object ISA95JobOrderReceiverSubStatesType_FromRunningToInterrupted,5074,Object ISA95JobOrderReceiverSubStatesType_FromRunningToEnded,5075,Object ISA95JobOrderReceiverSubStatesType_FromRunningToAborted,5076,Object ISA95JobOrderReceiverSubStatesType_FromInterruptedToAborted,5077,Object ISA95JobOrderReceiverSubStatesType_FromInterruptedToRunning,5078,Object ISA95JobOrderReceiverSubStatesType_FromInterruptedToEnded,5079,Object ISA95JobOrderReceiverSubStatesType_NotAllowedToStartSubstates,5080,Object ISA95JobOrderReceiverSubStatesType_AllowedToStartSubstates,5081,Object ISA95JobOrderReceiverSubStatesType_EndedSubstates,5082,Object ISA95JobOrderReceiverSubStatesType_InterruptedSubstates,5083,Object ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToAborted,5084,Object ISA95JobOrderReceiverObjectType_FromAllowedToStartToAborted,5085,Object ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToAborted,5086,Object ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToAborted,5087,Object ISA95PrepareStateMachineType_FromReadyToWaiting,5088,Object ISA95PrepareStateMachineType_FromLoadedToReady,5089,Object ISA95PrepareStateMachineType_FromLoadedToWaiting,5090,Object ISA95PrepareStateMachineType_Waiting_StateNumber,6000,Variable ISA95JobOrderReceiverSubStatesType_NotAllowedToStartSubstates_CurrentState,6001,Variable ISA95JobOrderReceiverSubStatesType_NotAllowedToStartSubstates_CurrentState_Id,6002,Variable ISA95JobOrderReceiverSubStatesType_AllowedToStartSubstates_CurrentState,6003,Variable ISA95JobOrderReceiverSubStatesType_AllowedToStartSubstates_CurrentState_Id,6004,Variable ISA95JobOrderReceiverSubStatesType_EndedSubstates_CurrentState,6005,Variable ISA95JobOrderReceiverSubStatesType_EndedSubstates_CurrentState_Id,6006,Variable ISA95JobOrderReceiverSubStatesType_InterruptedSubstates_CurrentState,6007,Variable ISA95JobOrderReceiverSubStatesType_InterruptedSubstates_CurrentState_Id,6008,Variable ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToAborted_TransitionNumber,6009,Variable ISA95JobOrderReceiverObjectType_FromAllowedToStartToAborted_TransitionNumber,6010,Variable ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToAborted_TransitionNumber,6011,Variable ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToAborted_TransitionNumber,6012,Variable ISA95PrepareStateMachineType_FromReadyToWaiting_TransitionNumber,6013,Variable ISA95PrepareStateMachineType_FromLoadedToReady_TransitionNumber,6014,Variable ISA95PrepareStateMachineType_FromLoadedToWaiting_TransitionNumber,6015,Variable ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderState_InputArguments,6016,Variable ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderState_OutputArguments,6017,Variable http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__IsNamespaceSubset,6023,Variable http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__NamespacePublicationDate,6024,Variable http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__NamespaceUri,6025,Variable http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__NamespaceVersion,6026,Variable http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__StaticNodeIdTypes,6027,Variable http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__StaticNumericNodeIdRange,6028,Variable http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__StaticStringNodeIdPattern,6029,Variable ISA95JobOrderReceiverObjectType_JobOrderList,6033,Variable ISA95JobOrderReceiverObjectType_WorkMaster,6034,Variable ISA95JobOrderReceiverObjectType_MaterialClassID,6035,Variable ISA95JobOrderReceiverObjectType_MaterialDefinitionID,6036,Variable ISA95JobOrderReceiverObjectType_EquipmentID,6037,Variable ISA95JobOrderReceiverObjectType_PhysicalAssetID,6038,Variable ISA95JobOrderReceiverObjectType_PersonnelID,6039,Variable ISA95JobOrderReceiverObjectType_Store_InputArguments,6040,Variable ISA95JobOrderReceiverObjectType_Store_OutputArguments,6041,Variable ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderID_InputArguments,6042,Variable ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderID_OutputArguments,6043,Variable ISA95JobResponseReceiverObjectType_ReceiveJobResponse_InputArguments,6044,Variable ISA95JobResponseReceiverObjectType_ReceiveJobResponse_OutputArguments,6045,Variable ISA95JobOrderStatusEventType_JobOrder,6047,Variable ISA95JobOrderStatusEventType_JobState,6048,Variable ISA95JobOrderStatusEventType_JobResponse,6049,Variable ISA95JobResponseProviderObjectType_JobOrderResponseList,6050,Variable ISA95JobOrderReceiverObjectType_StoreAndStart_InputArguments,6051,Variable ISA95JobOrderReceiverObjectType_StoreAndStart_OutputArguments,6052,Variable ISA95JobOrderReceiverObjectType_Start_InputArguments,6053,Variable ISA95JobOrderReceiverObjectType_Start_OutputArguments,6054,Variable ISA95JobOrderReceiverObjectType_Stop_InputArguments,6055,Variable ISA95JobOrderReceiverObjectType_Stop_OutputArguments,6056,Variable ISA95JobOrderReceiverObjectType_Pause_InputArguments,6057,Variable ISA95JobOrderReceiverObjectType_Pause_OutputArguments,6058,Variable ISA95JobOrderReceiverObjectType_Resume_InputArguments,6059,Variable ISA95JobOrderReceiverObjectType_Resume_OutputArguments,6060,Variable ISA95JobOrderReceiverObjectType_Update_InputArguments,6061,Variable ISA95JobOrderReceiverObjectType_Update_OutputArguments,6062,Variable ISA95JobOrderReceiverObjectType_Abort_InputArguments,6063,Variable ISA95JobOrderReceiverObjectType_Abort_OutputArguments,6064,Variable ISA95JobOrderReceiverObjectType_Cancel_InputArguments,6065,Variable ISA95JobOrderReceiverObjectType_Cancel_OutputArguments,6066,Variable ISA95JobOrderReceiverObjectType_Clear_InputArguments,6067,Variable ISA95JobOrderReceiverObjectType_Clear_OutputArguments,6068,Variable ISA95JobOrderReceiverObjectType_RevokeStart_InputArguments,6069,Variable ISA95JobOrderReceiverObjectType_RevokeStart_OutputArguments,6070,Variable ISA95JobOrderReceiverObjectType_NotAllowedToStart_StateNumber,6071,Variable ISA95JobOrderReceiverObjectType_AllowedToStart_StateNumber,6072,Variable ISA95JobOrderReceiverObjectType_Running_StateNumber,6073,Variable ISA95JobOrderReceiverObjectType_Interrupted_StateNumber,6074,Variable ISA95JobOrderReceiverObjectType_Ended_StateNumber,6075,Variable ISA95JobOrderReceiverObjectType_Aborted_StateNumber,6076,Variable ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToNotAllowedToStart_TransitionNumber,6077,Variable ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToAllowedToStart_TransitionNumber,6078,Variable ISA95JobOrderReceiverObjectType_FromAllowedToStartToNotAllowedToStart_TransitionNumber,6079,Variable ISA95JobOrderReceiverObjectType_FromAllowedToStartToAllowedToStart_TransitionNumber,6080,Variable ISA95JobOrderReceiverObjectType_FromAllowedToStartToRunning_TransitionNumber,6081,Variable ISA95JobOrderReceiverObjectType_FromRunningToInterrupted_TransitionNumber,6082,Variable ISA95JobOrderReceiverObjectType_FromRunningToEnded_TransitionNumber,6083,Variable ISA95JobOrderReceiverObjectType_FromRunningToAborted_TransitionNumber,6084,Variable ISA95JobOrderReceiverObjectType_FromInterruptedToAborted_TransitionNumber,6085,Variable ISA95JobOrderReceiverObjectType_FromInterruptedToRunning_TransitionNumber,6086,Variable ISA95JobOrderReceiverObjectType_FromInterruptedToEnded_TransitionNumber,6087,Variable ISA95JobOrderReceiverObjectType_MaxDownloadableJobOrders,6088,Variable ISA95PrepareStateMachineType_Ready_StateNumber,6089,Variable ISA95PrepareStateMachineType_Loaded_StateNumber,6090,Variable ISA95PrepareStateMachineType_FromWaitingToReady_TransitionNumber,6091,Variable ISA95PrepareStateMachineType_FromReadyToLoaded_TransitionNumber,6092,Variable ISA95EndedStateMachineType_Completed_StateNumber,6093,Variable ISA95EndedStateMachineType_Closed_StateNumber,6094,Variable ISA95EndedStateMachineType_FromCompletedToClosed_TransitionNumber,6095,Variable ISA95InterruptedStateMachineType_Held_StateNumber,6096,Variable ISA95InterruptedStateMachineType_Suspended_StateNumber,6097,Variable ISA95InterruptedStateMachineType_FromHeldToSuspended_TransitionNumber,6098,Variable ISA95InterruptedStateMachineType_FromSuspendedToHeld_TransitionNumber,6099,Variable ISA95JobOrderReceiverSubStatesType_NotAllowedToStart_StateNumber,6100,Variable ISA95JobOrderReceiverSubStatesType_AllowedToStart_StateNumber,6101,Variable ISA95JobOrderReceiverSubStatesType_Running_StateNumber,6102,Variable ISA95JobOrderReceiverSubStatesType_Interrupted_StateNumber,6103,Variable ISA95JobOrderReceiverSubStatesType_Ended_StateNumber,6104,Variable ISA95JobOrderReceiverSubStatesType_Aborted_StateNumber,6105,Variable ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToNotAllowedToStart_TransitionNumber,6106,Variable ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToAllowedToStart_TransitionNumber,6107,Variable ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToNotAllowedToStart_TransitionNumber,6108,Variable ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToAllowedToStart_TransitionNumber,6109,Variable ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToRunning_TransitionNumber,6110,Variable ISA95JobOrderReceiverSubStatesType_FromRunningToInterrupted_TransitionNumber,6111,Variable ISA95JobOrderReceiverSubStatesType_FromRunningToEnded_TransitionNumber,6112,Variable ISA95JobOrderReceiverSubStatesType_FromRunningToAborted_TransitionNumber,6113,Variable ISA95JobOrderReceiverSubStatesType_FromInterruptedToAborted_TransitionNumber,6114,Variable ISA95JobOrderReceiverSubStatesType_FromInterruptedToRunning_TransitionNumber,6115,Variable ISA95JobOrderReceiverSubStatesType_FromInterruptedToEnded_TransitionNumber,6116,Variable ISA95JobOrderReceiverObjectType_Store,7001,Method ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderID,7002,Method ISA95JobResponseReceiverObjectType_ReceiveJobResponse,7003,Method ISA95JobOrderReceiverObjectType_StoreAndStart,7004,Method ISA95JobOrderReceiverObjectType_Start,7005,Method ISA95JobOrderReceiverObjectType_Stop,7006,Method ISA95JobOrderReceiverObjectType_Pause,7007,Method ISA95JobOrderReceiverObjectType_Resume,7008,Method ISA95JobOrderReceiverObjectType_Update,7009,Method ISA95JobOrderReceiverObjectType_Abort,7010,Method ISA95JobOrderReceiverObjectType_Cancel,7011,Method ISA95JobOrderReceiverObjectType_Clear,7012,Method ISA95JobOrderReceiverObjectType_RevokeStart,7013,Method ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderState,7014,Method ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Isa95Jobs/Design/UAModel.ISA95_JOBCONTROL_V2.NodeIds.permissions.csv ================================================ ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Isa95Jobs/Design/UAModel.ISA95_JOBCONTROL_V2.NodeSet.xml ================================================  http://opcfoundation.org/UA/ http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/ ns=1;i=1001 ObjectType_8 1 ISA95PrepareStateMachineType ISA95PrepareStateMachineType 0 0 0 i=45 true i=2771 i=47 false ns=1;i=5089 i=47 false ns=1;i=5090 i=47 false ns=1;i=5055 i=47 false ns=1;i=5088 i=47 false ns=1;i=5054 i=47 false ns=1;i=5053 i=47 false ns=1;i=5052 i=47 false ns=1;i=5000 false ns=1;i=1002 ObjectType_8 1 ISA95JobOrderReceiverObjectType ISA95JobOrderReceiverObjectType The OPENSCSJobOrderReciverObjectType contains a method to receive job order commands and optional definitions of allowable job order information 0 0 0 i=45 true i=2771 i=47 false ns=1;i=7010 i=47 false ns=1;i=5040 i=47 false ns=1;i=5036 i=47 false ns=1;i=7011 i=47 false ns=1;i=7012 i=47 false ns=1;i=5039 i=47 false ns=1;i=6037 i=47 false ns=1;i=5085 i=47 false ns=1;i=5044 i=47 false ns=1;i=5043 i=47 false ns=1;i=5045 i=47 false ns=1;i=5049 i=47 false ns=1;i=5051 i=47 false ns=1;i=5050 i=47 false ns=1;i=5084 i=47 false ns=1;i=5042 i=47 false ns=1;i=5041 i=47 false ns=1;i=5048 i=47 false ns=1;i=5047 i=47 false ns=1;i=5046 i=47 false ns=1;i=5038 i=47 false ns=1;i=6033 i=47 false ns=1;i=6035 i=47 false ns=1;i=6036 i=46 false ns=1;i=6088 i=47 false ns=1;i=5035 i=47 false ns=1;i=7007 i=47 false ns=1;i=6039 i=47 false ns=1;i=6038 i=47 false ns=1;i=7008 i=47 false ns=1;i=7013 i=47 false ns=1;i=5037 i=47 false ns=1;i=7005 i=47 false ns=1;i=7006 i=47 false ns=1;i=7001 i=47 false ns=1;i=7004 i=47 false ns=1;i=7009 i=47 false ns=1;i=6034 i=45 false ns=1;i=1008 false ns=1;i=1003 ObjectType_8 1 ISA95JobResponseProviderObjectType ISA95JobResponseProviderObjectType The OPENSCSJobResponseProviderObjectType contains a method to receive unsolicited job response requests. 0 0 0 i=45 true i=58 i=41 false ns=1;i=1006 i=47 false ns=1;i=6050 i=47 false ns=1;i=7002 i=47 false ns=1;i=7014 false ns=1;i=1004 ObjectType_8 1 ISA95JobResponseReceiverObjectType ISA95JobResponseReceiverObjectType A Job Response Receiver receives unsolicited Job Responses, usually as the result of completion of a job, or at intermediate points within the job. 0 0 0 i=45 true i=58 i=47 false ns=1;i=7003 false ns=1;i=1005 ObjectType_8 1 ISA95EndedStateMachineType ISA95EndedStateMachineType 0 0 0 i=45 true i=2771 i=47 false ns=1;i=5057 i=47 false ns=1;i=5056 i=47 false ns=1;i=5058 false ns=1;i=1006 ObjectType_8 1 ISA95JobOrderStatusEventType ISA95JobOrderStatusEventType 0 0 0 i=45 true i=2041 i=41 true ns=1;i=1003 i=54 true ns=1;i=5041 i=54 true ns=1;i=5042 i=54 true ns=1;i=5043 i=54 true ns=1;i=5044 i=54 true ns=1;i=5045 i=54 true ns=1;i=5046 i=54 true ns=1;i=5047 i=54 true ns=1;i=5048 i=54 true ns=1;i=5049 i=54 true ns=1;i=5050 i=54 true ns=1;i=5051 i=54 true ns=1;i=5069 i=54 true ns=1;i=5070 i=54 true ns=1;i=5071 i=54 true ns=1;i=5072 i=54 true ns=1;i=5073 i=54 true ns=1;i=5074 i=54 true ns=1;i=5075 i=54 true ns=1;i=5076 i=54 true ns=1;i=5077 i=54 true ns=1;i=5078 i=54 true ns=1;i=5079 i=54 true ns=1;i=5084 i=54 true ns=1;i=5085 i=54 true ns=1;i=5086 i=54 true ns=1;i=5087 i=46 false ns=1;i=6047 i=46 false ns=1;i=6049 i=46 false ns=1;i=6048 true ns=1;i=1007 ObjectType_8 1 ISA95InterruptedStateMachineType ISA95InterruptedStateMachineType 0 0 0 i=45 true i=2771 i=47 false ns=1;i=5061 i=47 false ns=1;i=5062 i=47 false ns=1;i=5059 i=47 false ns=1;i=5060 false ns=1;i=1008 ObjectType_8 1 ISA95JobOrderReceiverSubStatesType ISA95JobOrderReceiverSubStatesType 0 0 0 i=45 true ns=1;i=1002 i=47 false ns=1;i=5068 i=47 false ns=1;i=5064 i=47 false ns=1;i=5067 i=47 false ns=1;i=5086 i=47 false ns=1;i=5072 i=47 false ns=1;i=5071 i=47 false ns=1;i=5073 i=47 false ns=1;i=5077 i=47 false ns=1;i=5079 i=47 false ns=1;i=5078 i=47 false ns=1;i=5087 i=47 false ns=1;i=5070 i=47 false ns=1;i=5069 i=47 false ns=1;i=5076 i=47 false ns=1;i=5075 i=47 false ns=1;i=5074 i=47 false ns=1;i=5066 i=47 false ns=1;i=5063 i=47 false ns=1;i=5065 i=47 false ns=1;i=5081 i=47 false ns=1;i=5082 i=47 false ns=1;i=5083 i=47 false ns=1;i=5080 false ns=1;i=3002 DataType_64 1 ISA95PropertyDataType ISA95PropertyDataType A subtype of OPC UA Structure that defines two linked data items: an ID, which is a unique identifier for a property within the scope of the associated resource, and the value, which is the data for the property. 0 0 0 i=45 true i=22 i=38 false ns=1;i=5002 i=38 false ns=1;i=5004 i=38 false ns=1;i=5003 false ns=1;i=3003 DataType_64 1 ISA95ParameterDataType ISA95ParameterDataType A subtype of OPC UA Structure that defines three linked data items: the ID, which is a unique identifier for a property, the value, which is the data that is identified, and an optional description of the parameter. 0 0 0 i=45 true i=22 i=38 false ns=1;i=5005 i=38 false ns=1;i=5007 i=38 false ns=1;i=5006 false ns=1;i=3005 DataType_64 1 ISA95EquipmentDataType ISA95EquipmentDataType Defines an equipment resource or a piece of equipment, a quantity, an optional description, and an optional collection of properties. 0 0 0 i=45 true i=22 i=38 false ns=1;i=5008 i=38 false ns=1;i=5010 i=38 false ns=1;i=5009 false ns=1;i=3006 DataType_64 1 ISA95StateDataType ISA95StateDataType Defines the information needed to schedule and execute a job. 0 0 0 i=45 true i=22 i=38 false ns=1;i=5029 i=38 false ns=1;i=5031 i=38 false ns=1;i=5030 false ns=1;i=3007 DataType_64 1 ISA95WorkMasterDataType ISA95WorkMasterDataType Defines a Work Master ID and the defined parameters for the Work Master. 0 0 0 i=45 true i=22 i=38 false ns=1;i=5011 i=38 false ns=1;i=5013 i=38 false ns=1;i=5012 false ns=1;i=3008 DataType_64 1 ISA95JobOrderDataType ISA95JobOrderDataType Defines the information needed to schedule and execute a job. 0 0 0 i=45 true i=22 i=38 false ns=1;i=5014 i=38 false ns=1;i=5016 i=38 false ns=1;i=5015 false ns=1;i=3010 DataType_64 1 ISA95MaterialDataType ISA95MaterialDataType Defines a material resource, a quantity, an optional description, and an optional collection of properties. 0 0 0 i=45 true i=22 i=38 false ns=1;i=5017 i=38 false ns=1;i=5019 i=38 false ns=1;i=5018 false ns=1;i=3011 DataType_64 1 ISA95PersonnelDataType ISA95PersonnelDataType Defines a personnel resource or a person, a quantity, an optional description, and an optional collection of properties. 0 0 0 i=45 true i=22 i=38 false ns=1;i=5020 i=38 false ns=1;i=5022 i=38 false ns=1;i=5021 false ns=1;i=3012 DataType_64 1 ISA95PhysicalAssetDataType ISA95PhysicalAssetDataType Defines a physical asset, a quantity, an optional description, and an optional collection of properties. 0 0 0 i=45 true i=22 i=38 false ns=1;i=5023 i=38 false ns=1;i=5025 i=38 false ns=1;i=5024 false ns=1;i=3013 DataType_64 1 ISA95JobResponseDataType ISA95JobResponseDataType Defines the information needed to schedule and execute a job. 0 0 0 i=45 true i=22 i=38 false ns=1;i=5026 i=38 false ns=1;i=5028 i=38 false ns=1;i=5027 false ns=1;i=3015 DataType_64 1 ISA95JobOrderAndStateDataType ISA95JobOrderAndStateDataType Defines the information needed to schedule and execute a job. 0 0 0 i=45 true i=22 i=38 false ns=1;i=5032 i=38 false ns=1;i=5034 i=38 false ns=1;i=5033 false ns=1;i=5000 Object_1 1 Waiting Waiting The necessary pre-conditions have not been met and the job order is not ready to run. 0 0 0 i=47 true ns=1;i=1001 i=40 false i=2307 i=52 true ns=1;i=5090 i=52 true ns=1;i=5088 i=51 true ns=1;i=5054 i=46 false ns=1;i=6000 0 ns=1;i=5001 Object_1 1 http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/ http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/ 0 0 0 i=40 false i=11616 i=47 true i=11715 i=46 false ns=1;i=6025 i=46 false ns=1;i=6026 i=46 false ns=1;i=6024 i=46 false ns=1;i=6023 i=46 false ns=1;i=6027 i=46 false ns=1;i=6028 i=46 false ns=1;i=6029 0 ns=1;i=5002 Object_1 0 Default Binary Default Binary 0 0 0 i=40 false i=76 i=38 true ns=1;i=3002 i=39 false ns=1;i=6128 0 ns=1;i=5003 Object_1 0 Default XML Default XML 0 0 0 i=40 false i=76 i=38 true ns=1;i=3002 i=39 false ns=1;i=6129 0 ns=1;i=5004 Object_1 0 Default JSON Default JSON 0 0 0 i=40 false i=76 i=38 true ns=1;i=3002 0 ns=1;i=5005 Object_1 0 Default Binary Default Binary 0 0 0 i=40 false i=76 i=38 true ns=1;i=3003 i=39 false ns=1;i=6122 0 ns=1;i=5006 Object_1 0 Default XML Default XML 0 0 0 i=40 false i=76 i=38 true ns=1;i=3003 i=39 false ns=1;i=6123 0 ns=1;i=5007 Object_1 0 Default JSON Default JSON 0 0 0 i=40 false i=76 i=38 true ns=1;i=3003 0 ns=1;i=5008 Object_1 0 Default Binary Default Binary 0 0 0 i=40 false i=76 i=38 true ns=1;i=3005 i=39 false ns=1;i=6022 0 ns=1;i=5009 Object_1 0 Default XML Default XML 0 0 0 i=40 false i=76 i=38 true ns=1;i=3005 i=39 false ns=1;i=6030 0 ns=1;i=5010 Object_1 0 Default JSON Default JSON 0 0 0 i=40 false i=76 i=38 true ns=1;i=3005 0 ns=1;i=5011 Object_1 0 Default Binary Default Binary 0 0 0 i=40 false i=76 i=38 true ns=1;i=3007 i=39 false ns=1;i=6132 0 ns=1;i=5012 Object_1 0 Default XML Default XML 0 0 0 i=40 false i=76 i=38 true ns=1;i=3007 i=39 false ns=1;i=6133 0 ns=1;i=5013 Object_1 0 Default JSON Default JSON 0 0 0 i=40 false i=76 i=38 true ns=1;i=3007 0 ns=1;i=5014 Object_1 0 Default Binary Default Binary 0 0 0 i=40 false i=76 i=38 true ns=1;i=3008 i=39 false ns=1;i=6046 0 ns=1;i=5015 Object_1 0 Default XML Default XML 0 0 0 i=40 false i=76 i=38 true ns=1;i=3008 i=39 false ns=1;i=6117 0 ns=1;i=5016 Object_1 0 Default JSON Default JSON 0 0 0 i=40 false i=76 i=38 true ns=1;i=3008 0 ns=1;i=5017 Object_1 0 Default Binary Default Binary 0 0 0 i=40 false i=76 i=38 true ns=1;i=3010 i=39 false ns=1;i=6120 0 ns=1;i=5018 Object_1 0 Default XML Default XML 0 0 0 i=40 false i=76 i=38 true ns=1;i=3010 i=39 false ns=1;i=6121 0 ns=1;i=5019 Object_1 0 Default JSON Default JSON 0 0 0 i=40 false i=76 i=38 true ns=1;i=3010 0 ns=1;i=5020 Object_1 0 Default Binary Default Binary 0 0 0 i=40 false i=76 i=38 true ns=1;i=3011 i=39 false ns=1;i=6124 0 ns=1;i=5021 Object_1 0 Default XML Default XML 0 0 0 i=40 false i=76 i=38 true ns=1;i=3011 i=39 false ns=1;i=6125 0 ns=1;i=5022 Object_1 0 Default JSON Default JSON 0 0 0 i=40 false i=76 i=38 true ns=1;i=3011 0 ns=1;i=5023 Object_1 0 Default Binary Default Binary 0 0 0 i=40 false i=76 i=38 true ns=1;i=3012 i=39 false ns=1;i=6126 0 ns=1;i=5024 Object_1 0 Default XML Default XML 0 0 0 i=40 false i=76 i=38 true ns=1;i=3012 i=39 false ns=1;i=6127 0 ns=1;i=5025 Object_1 0 Default JSON Default JSON 0 0 0 i=40 false i=76 i=38 true ns=1;i=3012 0 ns=1;i=5026 Object_1 0 Default Binary Default Binary 0 0 0 i=40 false i=76 i=38 true ns=1;i=3013 i=39 false ns=1;i=6118 0 ns=1;i=5027 Object_1 0 Default XML Default XML 0 0 0 i=40 false i=76 i=38 true ns=1;i=3013 i=39 false ns=1;i=6119 0 ns=1;i=5028 Object_1 0 Default JSON Default JSON 0 0 0 i=40 false i=76 i=38 true ns=1;i=3013 0 ns=1;i=5029 Object_1 0 Default Binary Default Binary 0 0 0 i=40 false i=76 i=38 true ns=1;i=3006 i=39 false ns=1;i=6130 0 ns=1;i=5030 Object_1 0 Default XML Default XML 0 0 0 i=40 false i=76 i=38 true ns=1;i=3006 i=39 false ns=1;i=6131 0 ns=1;i=5031 Object_1 0 Default JSON Default JSON 0 0 0 i=40 false i=76 i=38 true ns=1;i=3006 0 ns=1;i=5032 Object_1 0 Default Binary Default Binary 0 0 0 i=40 false i=76 i=38 true ns=1;i=3015 i=39 false ns=1;i=6031 0 ns=1;i=5033 Object_1 0 Default XML Default XML 0 0 0 i=40 false i=76 i=38 true ns=1;i=3015 i=39 false ns=1;i=6032 0 ns=1;i=5034 Object_1 0 Default JSON Default JSON 0 0 0 i=40 false i=76 i=38 true ns=1;i=3015 0 ns=1;i=5035 Object_1 1 NotAllowedToStart NotAllowedToStart The job order is stored but may not be executed. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=2307 i=52 true ns=1;i=5043 i=51 true ns=1;i=5084 i=51 true ns=1;i=5042 i=52 true ns=1;i=5041 i=51 true ns=1;i=5041 i=46 false ns=1;i=6071 0 ns=1;i=5036 Object_1 1 AllowedToStart AllowedToStart The job order is stored and may be executed. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=2307 i=52 true ns=1;i=5042 i=51 true ns=1;i=5043 i=52 true ns=1;i=5044 i=51 true ns=1;i=5044 i=51 true ns=1;i=5045 i=51 true ns=1;i=5085 i=46 false ns=1;i=6072 0 ns=1;i=5037 Object_1 1 Running Running The job order is executing. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=2307 i=52 true ns=1;i=5045 i=52 true ns=1;i=5050 i=51 true ns=1;i=5048 i=51 true ns=1;i=5047 i=51 true ns=1;i=5046 i=46 false ns=1;i=6073 0 ns=1;i=5038 Object_1 1 Interrupted Interrupted The job order has been temporarily stopped. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=2307 i=51 true ns=1;i=5049 i=51 true ns=1;i=5051 i=51 true ns=1;i=5050 i=52 true ns=1;i=5046 i=46 false ns=1;i=6074 0 ns=1;i=5039 Object_1 1 Ended Ended The job order has been completed and is no longer in execution. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=2307 i=52 true ns=1;i=5047 i=52 true ns=1;i=5051 i=46 false ns=1;i=6075 0 ns=1;i=5040 Object_1 1 Aborted Aborted The job order is aborted. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=2307 i=52 true ns=1;i=5048 i=52 true ns=1;i=5049 i=52 true ns=1;i=5084 i=52 true ns=1;i=5085 i=46 false ns=1;i=6076 0 ns=1;i=5041 Object_1 1 FromNotAllowedToStartToNotAllowedToStart FromNotAllowedToStartToNotAllowedToStart This transition is triggered when the Update Method is called and the job order is modified. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=2310 i=54 false ns=1;i=1006 i=52 false ns=1;i=5035 i=51 false ns=1;i=5035 i=53 false ns=1;i=7009 i=46 false ns=1;i=6077 0 ns=1;i=5042 Object_1 1 FromNotAllowedToStartToAllowedToStart FromNotAllowedToStartToAllowedToStart This transition is triggered when the Start Method is called. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=2310 i=52 false ns=1;i=5036 i=54 false ns=1;i=1006 i=51 false ns=1;i=5035 i=53 false ns=1;i=7005 i=46 false ns=1;i=6078 0 ns=1;i=5043 Object_1 1 FromAllowedToStartToNotAllowedToStart FromAllowedToStartToNotAllowedToStart This transition is triggered when the RevokeStart Method is called. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=2310 i=51 false ns=1;i=5036 i=54 false ns=1;i=1006 i=52 false ns=1;i=5035 i=53 false ns=1;i=7013 i=46 false ns=1;i=6079 0 ns=1;i=5044 Object_1 1 FromAllowedToStartToAllowedToStart FromAllowedToStartToAllowedToStart This transition is triggered when the Update Method is called and the job order is modified. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=2310 i=52 false ns=1;i=5036 i=51 false ns=1;i=5036 i=54 false ns=1;i=1006 i=53 false ns=1;i=7009 i=46 false ns=1;i=6080 0 ns=1;i=5045 Object_1 1 FromAllowedToStartToRunning FromAllowedToStartToRunning This transition is triggered when a job order is started to be executed. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=2310 i=51 false ns=1;i=5036 i=54 false ns=1;i=1006 i=52 false ns=1;i=5037 i=46 false ns=1;i=6081 0 ns=1;i=5046 Object_1 1 FromRunningToInterrupted FromRunningToInterrupted This transition is triggered when an executing job order gets interrupted, either internally or by the Pause Method. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=2310 i=52 false ns=1;i=5038 i=54 false ns=1;i=1006 i=53 false ns=1;i=7007 i=51 false ns=1;i=5037 i=46 false ns=1;i=6082 0 ns=1;i=5047 Object_1 1 FromRunningToEnded FromRunningToEnded This transition is triggered when the execution of a job order has finished, either internally or by the Stop Method. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=2310 i=52 false ns=1;i=5039 i=54 false ns=1;i=1006 i=51 false ns=1;i=5037 i=53 false ns=1;i=7006 i=46 false ns=1;i=6083 0 ns=1;i=5048 Object_1 1 FromRunningToAborted FromRunningToAborted This transition is triggered when Abort Method is called. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=2310 i=53 false ns=1;i=7010 i=52 false ns=1;i=5040 i=54 false ns=1;i=1006 i=51 false ns=1;i=5037 i=46 false ns=1;i=6084 0 ns=1;i=5049 Object_1 1 FromInterruptedToAborted FromInterruptedToAborted This transition is triggered when Abort Method is called. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=2310 i=53 false ns=1;i=7010 i=52 false ns=1;i=5040 i=51 false ns=1;i=5038 i=54 false ns=1;i=1006 i=46 false ns=1;i=6085 0 ns=1;i=5050 Object_1 1 FromInterruptedToRunning FromInterruptedToRunning This transition is triggered when Resume Method is called. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=2310 i=51 false ns=1;i=5038 i=54 false ns=1;i=1006 i=53 false ns=1;i=7008 i=52 false ns=1;i=5037 i=46 false ns=1;i=6086 0 ns=1;i=5051 Object_1 1 FromInterruptedToEnded FromInterruptedToEnded This transition is triggered when Stop Method is called. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=2310 i=52 false ns=1;i=5039 i=51 false ns=1;i=5038 i=54 false ns=1;i=1006 i=53 false ns=1;i=7006 i=46 false ns=1;i=6087 0 ns=1;i=5052 Object_1 1 Ready Ready The necessary pre-conditions have been met and the job order is ready to run, awaiting a Start command. 0 0 0 i=47 true ns=1;i=1001 i=40 false i=2307 i=52 true ns=1;i=5089 i=51 true ns=1;i=5055 i=51 true ns=1;i=5088 i=52 true ns=1;i=5054 i=46 false ns=1;i=6089 0 ns=1;i=5053 Object_1 1 Loaded Loaded In situations where only one job may be in active memory and is able to be run, then the job is loaded in active memory, the necessary pre-conditions have been met, and the job order is ready to run, awaiting a Start command. 0 0 0 i=47 true ns=1;i=1001 i=40 false i=2307 i=51 true ns=1;i=5089 i=51 true ns=1;i=5090 i=52 true ns=1;i=5055 i=46 false ns=1;i=6090 0 ns=1;i=5054 Object_1 1 FromWaitingToReady FromWaitingToReady This transition is triggered when the system is ready to start the execution of the job order. 0 0 0 i=47 true ns=1;i=1001 i=40 false i=2310 i=52 false ns=1;i=5052 i=51 false ns=1;i=5000 i=46 false ns=1;i=6091 0 ns=1;i=5055 Object_1 1 FromReadyToLoaded FromReadyToLoaded This transition is triggered when the program or configuration to execute the job order is loaded. 0 0 0 i=47 true ns=1;i=1001 i=40 false i=2310 i=52 false ns=1;i=5053 i=51 false ns=1;i=5052 i=46 false ns=1;i=6092 0 ns=1;i=5056 Object_1 1 Completed Completed The job order has been completed and is no longer in execution. 0 0 0 i=47 true ns=1;i=1005 i=40 false i=2307 i=51 true ns=1;i=5058 i=46 false ns=1;i=6093 0 ns=1;i=5057 Object_1 1 Closed Closed The job order has been completed and no further post processing is performed. 0 0 0 i=47 true ns=1;i=1005 i=40 false i=2307 i=52 true ns=1;i=5058 i=46 false ns=1;i=6094 0 ns=1;i=5058 Object_1 1 FromCompletedToClosed FromCompletedToClosed This transition is triggered when the system has finalized post processing of a ended job order. 0 0 0 i=47 true ns=1;i=1005 i=40 false i=2310 i=52 false ns=1;i=5057 i=51 false ns=1;i=5056 i=46 false ns=1;i=6095 0 ns=1;i=5059 Object_1 1 Held Held The job order has been temporarily stopped due to a constraint of some form. 0 0 0 i=47 true ns=1;i=1007 i=40 false i=2307 i=51 true ns=1;i=5061 i=52 true ns=1;i=5062 i=46 false ns=1;i=6096 0 ns=1;i=5060 Object_1 1 Suspended Suspended The job order has been temporarily stopped due to a deliberate decision within the execution system. 0 0 0 i=47 true ns=1;i=1007 i=40 false i=2307 i=52 true ns=1;i=5061 i=51 true ns=1;i=5062 i=46 false ns=1;i=6097 0 ns=1;i=5061 Object_1 1 FromHeldToSuspended FromHeldToSuspended This transition is triggered when the system has switched the job order from internally held to externally suspended, for example by a call of the Pause Method. 0 0 0 i=47 true ns=1;i=1007 i=40 false i=2310 i=51 false ns=1;i=5059 i=52 false ns=1;i=5060 i=46 false ns=1;i=6098 0 ns=1;i=5062 Object_1 1 FromSuspendedToHeld FromSuspendedToHeld This transition is triggered when the system has switched the job order from externally suspended to an internal held, for example by a call of the Resume Method. 0 0 0 i=47 true ns=1;i=1007 i=40 false i=2310 i=52 false ns=1;i=5059 i=51 false ns=1;i=5060 i=46 false ns=1;i=6099 0 ns=1;i=5063 Object_1 1 NotAllowedToStart NotAllowedToStart The job order is stored but may not be executed. 0 0 0 i=47 true ns=1;i=1008 i=40 false i=2307 i=52 true ns=1;i=5071 i=51 true ns=1;i=5087 i=51 true ns=1;i=5070 i=52 true ns=1;i=5069 i=51 true ns=1;i=5069 i=117 false ns=1;i=5080 i=46 false ns=1;i=6100 0 ns=1;i=5064 Object_1 1 AllowedToStart AllowedToStart The job order is stored and may be executed. 0 0 0 i=47 true ns=1;i=1008 i=40 false i=2307 i=52 true ns=1;i=5070 i=51 true ns=1;i=5071 i=52 true ns=1;i=5072 i=51 true ns=1;i=5072 i=51 true ns=1;i=5073 i=51 true ns=1;i=5086 i=117 false ns=1;i=5081 i=46 false ns=1;i=6101 0 ns=1;i=5065 Object_1 1 Running Running The job order is executing. 0 0 0 i=47 true ns=1;i=1008 i=40 false i=2307 i=52 true ns=1;i=5073 i=52 true ns=1;i=5078 i=51 true ns=1;i=5076 i=51 true ns=1;i=5075 i=51 true ns=1;i=5074 i=46 false ns=1;i=6102 0 ns=1;i=5066 Object_1 1 Interrupted Interrupted The job order has been temporarily stopped. 0 0 0 i=47 true ns=1;i=1008 i=40 false i=2307 i=51 true ns=1;i=5077 i=51 true ns=1;i=5079 i=51 true ns=1;i=5078 i=52 true ns=1;i=5074 i=117 false ns=1;i=5083 i=46 false ns=1;i=6103 0 ns=1;i=5067 Object_1 1 Ended Ended The job order has been completed and is no longer in execution. 0 0 0 i=47 true ns=1;i=1008 i=40 false i=2307 i=52 true ns=1;i=5075 i=52 true ns=1;i=5079 i=117 false ns=1;i=5082 i=46 false ns=1;i=6104 0 ns=1;i=5068 Object_1 1 Aborted Aborted The job order is aborted. 0 0 0 i=47 true ns=1;i=1008 i=40 false i=2307 i=52 true ns=1;i=5076 i=52 true ns=1;i=5077 i=52 true ns=1;i=5087 i=52 true ns=1;i=5086 i=46 false ns=1;i=6105 0 ns=1;i=5069 Object_1 1 FromNotAllowedToStartToNotAllowedToStart FromNotAllowedToStartToNotAllowedToStart This transition is triggered when the Update Method is called and the job order is modified. 0 0 0 i=47 true ns=1;i=1008 i=40 false i=2310 i=54 false ns=1;i=1006 i=52 false ns=1;i=5063 i=51 false ns=1;i=5063 i=53 false ns=1;i=7009 i=46 false ns=1;i=6106 0 ns=1;i=5070 Object_1 1 FromNotAllowedToStartToAllowedToStart FromNotAllowedToStartToAllowedToStart This transition is triggered when the Start Method is called. 0 0 0 i=47 true ns=1;i=1008 i=40 false i=2310 i=52 false ns=1;i=5064 i=54 false ns=1;i=1006 i=51 false ns=1;i=5063 i=53 false ns=1;i=7005 i=46 false ns=1;i=6107 0 ns=1;i=5071 Object_1 1 FromAllowedToStartToNotAllowedToStart FromAllowedToStartToNotAllowedToStart This transition is triggered when the RevokeStart Method is called. 0 0 0 i=47 true ns=1;i=1008 i=40 false i=2310 i=51 false ns=1;i=5064 i=54 false ns=1;i=1006 i=52 false ns=1;i=5063 i=53 false ns=1;i=7013 i=46 false ns=1;i=6108 0 ns=1;i=5072 Object_1 1 FromAllowedToStartToAllowedToStart FromAllowedToStartToAllowedToStart This transition is triggered when the Update Method is called and the job order is modified. 0 0 0 i=47 true ns=1;i=1008 i=40 false i=2310 i=52 false ns=1;i=5064 i=51 false ns=1;i=5064 i=54 false ns=1;i=1006 i=53 false ns=1;i=7009 i=46 false ns=1;i=6109 0 ns=1;i=5073 Object_1 1 FromAllowedToStartToRunning FromAllowedToStartToRunning This transition is triggered when a job order is started to be executed. 0 0 0 i=47 true ns=1;i=1008 i=40 false i=2310 i=51 false ns=1;i=5064 i=54 false ns=1;i=1006 i=52 false ns=1;i=5065 i=46 false ns=1;i=6110 0 ns=1;i=5074 Object_1 1 FromRunningToInterrupted FromRunningToInterrupted This transition is triggered when an executing job order gets interrupted, either internally or by the Pause Method. 0 0 0 i=47 true ns=1;i=1008 i=40 false i=2310 i=52 false ns=1;i=5066 i=54 false ns=1;i=1006 i=51 false ns=1;i=5065 i=53 false ns=1;i=7007 i=46 false ns=1;i=6111 0 ns=1;i=5075 Object_1 1 FromRunningToEnded FromRunningToEnded This transition is triggered when the execution of a job order has finished, either internally or by the Stop Method. 0 0 0 i=47 true ns=1;i=1008 i=40 false i=2310 i=52 false ns=1;i=5067 i=54 false ns=1;i=1006 i=51 false ns=1;i=5065 i=53 false ns=1;i=7006 i=46 false ns=1;i=6112 0 ns=1;i=5076 Object_1 1 FromRunningToAborted FromRunningToAborted This transition is triggered when Abort Method is called. 0 0 0 i=47 true ns=1;i=1008 i=40 false i=2310 i=52 false ns=1;i=5068 i=54 false ns=1;i=1006 i=51 false ns=1;i=5065 i=53 false ns=1;i=7010 i=46 false ns=1;i=6113 0 ns=1;i=5077 Object_1 1 FromInterruptedToAborted FromInterruptedToAborted This transition is triggered when Abort Method is called. 0 0 0 i=47 true ns=1;i=1008 i=40 false i=2310 i=52 false ns=1;i=5068 i=51 false ns=1;i=5066 i=54 false ns=1;i=1006 i=53 false ns=1;i=7010 i=46 false ns=1;i=6114 0 ns=1;i=5078 Object_1 1 FromInterruptedToRunning FromInterruptedToRunning This transition is triggered when Resume Method is called. 0 0 0 i=47 true ns=1;i=1008 i=40 false i=2310 i=51 false ns=1;i=5066 i=54 false ns=1;i=1006 i=52 false ns=1;i=5065 i=53 false ns=1;i=7008 i=46 false ns=1;i=6115 0 ns=1;i=5079 Object_1 1 FromInterruptedToEnded FromInterruptedToEnded This transition is triggered when Stop Method is called. 0 0 0 i=47 true ns=1;i=1008 i=40 false i=2310 i=52 false ns=1;i=5067 i=51 false ns=1;i=5066 i=54 false ns=1;i=1006 i=53 false ns=1;i=7006 i=46 false ns=1;i=6116 0 ns=1;i=5080 Object_1 1 NotAllowedToStartSubstates NotAllowedToStartSubstates Substates of NotAllowedToStart 0 0 0 i=47 true ns=1;i=1008 i=40 false ns=1;i=1001 i=37 false i=80 i=117 true ns=1;i=5063 i=47 false ns=1;i=6001 0 ns=1;i=5081 Object_1 1 AllowedToStartSubstates AllowedToStartSubstates Substates of AllowedToStart 0 0 0 i=47 true ns=1;i=1008 i=40 false ns=1;i=1001 i=37 false i=80 i=117 true ns=1;i=5064 i=47 false ns=1;i=6003 0 ns=1;i=5082 Object_1 1 EndedSubstates EndedSubstates Substates of Ended 0 0 0 i=47 true ns=1;i=1008 i=40 false ns=1;i=1005 i=37 false i=80 i=117 true ns=1;i=5067 i=47 false ns=1;i=6005 0 ns=1;i=5083 Object_1 1 InterruptedSubstates InterruptedSubstates Substates of Interrupted 0 0 0 i=47 true ns=1;i=1008 i=40 false ns=1;i=1007 i=37 false i=80 i=117 true ns=1;i=5066 i=47 false ns=1;i=6007 0 ns=1;i=5084 Object_1 1 FromNotAllowedToStartToAborted FromNotAllowedToStartToAborted This transition is triggered when Abort Method is called. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=2310 i=53 false ns=1;i=7010 i=52 false ns=1;i=5040 i=54 false ns=1;i=1006 i=51 false ns=1;i=5035 i=46 false ns=1;i=6009 0 ns=1;i=5085 Object_1 1 FromAllowedToStartToAborted FromAllowedToStartToAborted This transition is triggered when Abort Method is called. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=2310 i=53 false ns=1;i=7010 i=52 false ns=1;i=5040 i=51 false ns=1;i=5036 i=54 false ns=1;i=1006 i=46 false ns=1;i=6010 0 ns=1;i=5086 Object_1 1 FromAllowedToStartToAborted FromAllowedToStartToAborted This transition is triggered when Abort Method is called. 0 0 0 i=47 true ns=1;i=1008 i=40 false i=2310 i=52 false ns=1;i=5068 i=51 false ns=1;i=5064 i=54 false ns=1;i=1006 i=53 false ns=1;i=7010 i=46 false ns=1;i=6011 0 ns=1;i=5087 Object_1 1 FromNotAllowedToStartToAborted FromNotAllowedToStartToAborted This transition is triggered when Abort Method is called. 0 0 0 i=47 true ns=1;i=1008 i=40 false i=2310 i=52 false ns=1;i=5068 i=54 false ns=1;i=1006 i=51 false ns=1;i=5063 i=53 false ns=1;i=7010 i=46 false ns=1;i=6012 0 ns=1;i=5088 Object_1 1 FromReadyToWaiting FromReadyToWaiting This transition is triggered when the system is not ready to start the execution of the job order anymore. 0 0 0 i=47 true ns=1;i=1001 i=40 false i=2310 i=51 false ns=1;i=5052 i=52 false ns=1;i=5000 i=46 false ns=1;i=6013 0 ns=1;i=5089 Object_1 1 FromLoadedToReady FromLoadedToReady This transition is triggered when the program or configuration to execute the job order is unloaded. 0 0 0 i=47 true ns=1;i=1001 i=40 false i=2310 i=51 false ns=1;i=5053 i=52 false ns=1;i=5052 i=46 false ns=1;i=6014 0 ns=1;i=5090 Object_1 1 FromLoadedToWaiting FromLoadedToWaiting This transition is triggered when the system is not ready to start the execution of the job order anymore. 0 0 0 i=47 true ns=1;i=1001 i=40 false i=2310 i=51 false ns=1;i=5053 i=52 false ns=1;i=5000 i=46 false ns=1;i=6015 0 ns=1;i=6000 Variable_2 0 StateNumber StateNumber 0 0 0 i=46 true ns=1;i=5000 i=40 false i=68 i=37 false i=78 1 i=7 -1 1 1 0 false 0 ns=1;i=6001 Variable_2 0 CurrentState CurrentState 0 0 0 i=47 true ns=1;i=5080 i=40 false i=2760 i=37 false i=78 i=46 false ns=1;i=6002 i=21 -1 1 1 0 false 0 ns=1;i=6002 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=6001 i=40 false i=68 i=37 false i=78 i=0 i=17 -1 1 1 0 false 0 ns=1;i=6003 Variable_2 0 CurrentState CurrentState 0 0 0 i=47 true ns=1;i=5081 i=40 false i=2760 i=37 false i=78 i=46 false ns=1;i=6004 i=21 -1 1 1 0 false 0 ns=1;i=6004 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=6003 i=40 false i=68 i=37 false i=78 i=0 i=17 -1 1 1 0 false 0 ns=1;i=6005 Variable_2 0 CurrentState CurrentState 0 0 0 i=47 true ns=1;i=5082 i=40 false i=2760 i=37 false i=78 i=46 false ns=1;i=6006 i=21 -1 1 1 0 false 0 ns=1;i=6006 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=6005 i=40 false i=68 i=37 false i=78 i=0 i=17 -1 1 1 0 false 0 ns=1;i=6007 Variable_2 0 CurrentState CurrentState 0 0 0 i=47 true ns=1;i=5083 i=40 false i=2760 i=37 false i=78 i=46 false ns=1;i=6008 i=21 -1 1 1 0 false 0 ns=1;i=6008 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=6007 i=40 false i=68 i=37 false i=78 i=0 i=17 -1 1 1 0 false 0 ns=1;i=6009 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5084 i=40 false i=68 i=37 false i=78 12 i=7 -1 1 1 0 false 0 ns=1;i=6010 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5085 i=40 false i=68 i=37 false i=78 13 i=7 -1 1 1 0 false 0 ns=1;i=6011 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5086 i=40 false i=68 i=37 false i=78 13 i=7 -1 1 1 0 false 0 ns=1;i=6012 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5087 i=40 false i=68 i=37 false i=78 12 i=7 -1 1 1 0 false 0 ns=1;i=6013 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5088 i=40 false i=68 i=37 false i=78 3 i=7 -1 1 1 0 false 0 ns=1;i=6014 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5089 i=40 false i=68 i=37 false i=78 4 i=7 -1 1 1 0 false 0 ns=1;i=6015 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5090 i=40 false i=68 i=37 false i=78 5 i=7 -1 1 1 0 false 0 ns=1;i=6016 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=7014 i=40 false i=68 i=37 false i=78 i=297 JobOrderState ns=1;i=3006 1 0 Contains a job status of the JobResponse to be returned. The array shall provide at least one entry representing the top level state and potentially additional entries representing substates. The first entry shall be the top level entry, having the BrowsePath set to null. The order of the substates is not defined. i=296 1 1 1 1 0 false 0 ns=1;i=6017 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=7014 i=40 false i=68 i=37 false i=78 i=297 JobResponses ns=1;i=3013 1 0 Contains a list of information about the execution of a job order, such as the current status of the job, actual material consumed, actual material produced, actual equipment used, and job specific data. i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 2 1 1 0 false 0 ns=1;i=6023 Variable_2 0 IsNamespaceSubset IsNamespaceSubset 0 0 0 i=46 true ns=1;i=5001 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=6024 Variable_2 0 NamespacePublicationDate NamespacePublicationDate 0 0 0 i=46 true ns=1;i=5001 i=40 false i=68 2024-01-31T00:00:00Z i=13 -1 1 1 0 false 0 ns=1;i=6025 Variable_2 0 NamespaceUri NamespaceUri 0 0 0 i=46 true ns=1;i=5001 i=40 false i=68 http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/ i=12 -1 1 1 0 false 0 ns=1;i=6026 Variable_2 0 NamespaceVersion NamespaceVersion 0 0 0 i=46 true ns=1;i=5001 i=40 false i=68 2.0.0 i=12 -1 1 1 0 false 0 ns=1;i=6027 Variable_2 0 StaticNodeIdTypes StaticNodeIdTypes 0 0 0 i=46 true ns=1;i=5001 i=40 false i=68 0 i=256 1 0 1 1 0 false 0 ns=1;i=6028 Variable_2 0 StaticNumericNodeIdRange StaticNumericNodeIdRange 0 0 0 i=46 true ns=1;i=5001 i=40 false i=68 1:2147483647 i=291 1 0 1 1 0 false 0 ns=1;i=6029 Variable_2 0 StaticStringNodeIdPattern StaticStringNodeIdPattern 0 0 0 i=46 true ns=1;i=5001 i=40 false i=68 0 i=12 -1 1 1 0 false 0 ns=1;i=6033 Variable_2 1 JobOrderList JobOrderList Defines a read-only list of job order information available from the server. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=63 i=37 false i=78 ns=1;i=3015 1 0 1 1 0 false 0 ns=1;i=6034 Variable_2 1 WorkMaster WorkMaster Defines a read-only set of work master IDs that may be specified in a job order, and the read-only set of parameters that may be specified for a specific work master. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=63 i=37 false i=78 ns=1;i=3007 1 0 1 1 0 false 0 ns=1;i=6035 Variable_2 1 MaterialClassID MaterialClassID Defines a read-only set of Material Classes IDs that may be specified in a job order. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=63 i=37 false i=78 i=12 1 0 1 1 0 false 0 ns=1;i=6036 Variable_2 1 MaterialDefinitionID MaterialDefinitionID Defines a read-only set of Material Classes IDs that may be specified in a job order. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=63 i=37 false i=78 i=12 1 0 1 1 0 false 0 ns=1;i=6037 Variable_2 1 EquipmentID EquipmentID Defines a read-only set of Equipment Class IDs and Equipment IDs that may be specified in a job order. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=63 i=37 false i=78 i=12 1 0 1 1 0 false 0 ns=1;i=6038 Variable_2 1 PhysicalAssetID PhysicalAssetID Defines a read-only set of Physical Asset Class IDs and Physical Asset IDs that may be specified in a job order. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=63 i=37 false i=78 i=12 1 0 1 1 0 false 0 ns=1;i=6039 Variable_2 1 PersonnelID PersonnelID Defines a read-only set of Personnel IDs and Person IDs that may be specified in a job order. 0 0 0 i=47 true ns=1;i=1002 i=40 false i=63 i=37 false i=78 i=12 1 0 1 1 0 false 0 ns=1;i=6040 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=7001 i=40 false i=68 i=37 false i=78 i=297 JobOrder ns=1;i=3008 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. i=296 1 2 1 1 0 false 0 ns=1;i=6041 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=7001 i=40 false i=68 i=37 false i=78 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 1 1 1 0 false 0 ns=1;i=6042 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=7002 i=40 false i=68 i=37 false i=78 i=297 JobOrderID i=12 -1 Contains an ID of the job order, as specified by the method caller. i=296 1 1 1 1 0 false 0 ns=1;i=6043 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=7002 i=40 false i=68 i=37 false i=78 i=297 JobResponse ns=1;i=3013 -1 Contains information about the execution of a job order, such as the current status of the job, actual material consumed, actual material produced, actual equipment used, and job specific data. i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 2 1 1 0 false 0 ns=1;i=6044 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=7003 i=40 false i=68 i=37 false i=78 i=297 JobResponse ns=1;i=3013 -1 Contains information about the execution of a job order, such as actual material consumed, actual material produced, actual equipment used, and job specific data. i=296 1 1 1 1 0 false 0 ns=1;i=6045 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=7003 i=40 false i=68 i=37 false i=78 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 1 1 1 0 false 0 ns=1;i=6047 Variable_2 1 JobOrder JobOrder 0 0 0 i=46 true ns=1;i=1006 i=40 false i=68 i=37 false i=78 ns=1;i=3008 -1 3 3 0 false 0 ns=1;i=6048 Variable_2 1 JobState JobState 0 0 0 i=46 true ns=1;i=1006 i=40 false i=68 i=37 false i=78 ns=1;i=3006 1 0 3 3 0 false 0 ns=1;i=6049 Variable_2 1 JobResponse JobResponse 0 0 0 i=46 true ns=1;i=1006 i=40 false i=68 i=37 false i=78 ns=1;i=3013 -1 3 3 0 false 0 ns=1;i=6050 Variable_2 1 JobOrderResponseList JobOrderResponseList 0 0 0 i=47 true ns=1;i=1003 i=40 false i=63 i=37 false i=80 ns=1;i=3013 1 0 3 3 0 false 0 ns=1;i=6051 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=7004 i=40 false i=68 i=37 false i=78 i=297 JobOrder ns=1;i=3008 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. i=296 1 2 1 1 0 false 0 ns=1;i=6052 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=7004 i=40 false i=68 i=37 false i=78 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 1 1 1 0 false 0 ns=1;i=6053 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=7005 i=40 false i=68 i=37 false i=78 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. i=296 1 2 1 1 0 false 0 ns=1;i=6054 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=7005 i=40 false i=68 i=37 false i=78 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 1 1 1 0 false 0 ns=1;i=6055 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=7006 i=40 false i=68 i=37 false i=78 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. i=296 1 2 1 1 0 false 0 ns=1;i=6056 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=7006 i=40 false i=68 i=37 false i=78 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 1 1 1 0 false 0 ns=1;i=6057 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=7007 i=40 false i=68 i=37 false i=78 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. i=296 1 2 1 1 0 false 0 ns=1;i=6058 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=7007 i=40 false i=68 i=37 false i=78 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 1 1 1 0 false 0 ns=1;i=6059 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=7008 i=40 false i=68 i=37 false i=78 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. i=296 1 2 1 1 0 false 0 ns=1;i=6060 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=7008 i=40 false i=68 i=37 false i=78 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 1 1 1 0 false 0 ns=1;i=6061 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=7009 i=40 false i=68 i=37 false i=78 i=297 JobOrder ns=1;i=3008 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. i=296 1 2 1 1 0 false 0 ns=1;i=6062 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=7009 i=40 false i=68 i=37 false i=78 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 1 1 1 0 false 0 ns=1;i=6063 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=7010 i=40 false i=68 i=37 false i=78 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. i=296 1 2 1 1 0 false 0 ns=1;i=6064 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=7010 i=40 false i=68 i=37 false i=78 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 1 1 1 0 false 0 ns=1;i=6065 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=7011 i=40 false i=68 i=37 false i=78 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. i=296 1 2 1 1 0 false 0 ns=1;i=6066 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=7011 i=40 false i=68 i=37 false i=78 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 1 1 1 0 false 0 ns=1;i=6067 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=7012 i=40 false i=68 i=37 false i=78 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. i=296 1 2 1 1 0 false 0 ns=1;i=6068 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=7012 i=40 false i=68 i=37 false i=78 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 1 1 1 0 false 0 ns=1;i=6069 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=7013 i=40 false i=68 i=37 false i=78 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. i=296 1 2 1 1 0 false 0 ns=1;i=6070 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=7013 i=40 false i=68 i=37 false i=78 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 1 1 1 0 false 0 ns=1;i=6071 Variable_2 0 StateNumber StateNumber 0 0 0 i=46 true ns=1;i=5035 i=40 false i=68 i=37 false i=78 1 i=7 -1 1 1 0 false 0 ns=1;i=6072 Variable_2 0 StateNumber StateNumber 0 0 0 i=46 true ns=1;i=5036 i=40 false i=68 i=37 false i=78 2 i=7 -1 1 1 0 false 0 ns=1;i=6073 Variable_2 0 StateNumber StateNumber 0 0 0 i=46 true ns=1;i=5037 i=40 false i=68 i=37 false i=78 3 i=7 -1 1 1 0 false 0 ns=1;i=6074 Variable_2 0 StateNumber StateNumber 0 0 0 i=46 true ns=1;i=5038 i=40 false i=68 i=37 false i=78 4 i=7 -1 1 1 0 false 0 ns=1;i=6075 Variable_2 0 StateNumber StateNumber 0 0 0 i=46 true ns=1;i=5039 i=40 false i=68 i=37 false i=78 5 i=7 -1 1 1 0 false 0 ns=1;i=6076 Variable_2 0 StateNumber StateNumber 0 0 0 i=46 true ns=1;i=5040 i=40 false i=68 i=37 false i=78 6 i=7 -1 1 1 0 false 0 ns=1;i=6077 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5041 i=40 false i=68 i=37 false i=78 1 i=7 -1 1 1 0 false 0 ns=1;i=6078 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5042 i=40 false i=68 i=37 false i=78 2 i=7 -1 1 1 0 false 0 ns=1;i=6079 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5043 i=40 false i=68 i=37 false i=78 3 i=7 -1 1 1 0 false 0 ns=1;i=6080 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5044 i=40 false i=68 i=37 false i=78 4 i=7 -1 1 1 0 false 0 ns=1;i=6081 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5045 i=40 false i=68 i=37 false i=78 5 i=7 -1 1 1 0 false 0 ns=1;i=6082 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5046 i=40 false i=68 i=37 false i=78 6 i=7 -1 1 1 0 false 0 ns=1;i=6083 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5047 i=40 false i=68 i=37 false i=78 7 i=7 -1 1 1 0 false 0 ns=1;i=6084 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5048 i=40 false i=68 i=37 false i=78 8 i=7 -1 1 1 0 false 0 ns=1;i=6085 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5049 i=40 false i=68 i=37 false i=78 9 i=7 -1 1 1 0 false 0 ns=1;i=6086 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5050 i=40 false i=68 i=37 false i=78 10 i=7 -1 1 1 0 false 0 ns=1;i=6087 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5051 i=40 false i=68 i=37 false i=78 11 i=7 -1 1 1 0 false 0 ns=1;i=6088 Variable_2 1 MaxDownloadableJobOrders MaxDownloadableJobOrders 0 0 0 i=46 true ns=1;i=1002 i=40 false i=68 i=37 false i=78 0 i=5 -1 1 1 0 false 0 ns=1;i=6089 Variable_2 0 StateNumber StateNumber 0 0 0 i=46 true ns=1;i=5052 i=40 false i=68 i=37 false i=78 2 i=7 -1 1 1 0 false 0 ns=1;i=6090 Variable_2 0 StateNumber StateNumber 0 0 0 i=46 true ns=1;i=5053 i=40 false i=68 i=37 false i=78 3 i=7 -1 1 1 0 false 0 ns=1;i=6091 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5054 i=40 false i=68 i=37 false i=78 1 i=7 -1 1 1 0 false 0 ns=1;i=6092 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5055 i=40 false i=68 i=37 false i=78 2 i=7 -1 1 1 0 false 0 ns=1;i=6093 Variable_2 0 StateNumber StateNumber 0 0 0 i=46 true ns=1;i=5056 i=40 false i=68 i=37 false i=78 1 i=7 -1 1 1 0 false 0 ns=1;i=6094 Variable_2 0 StateNumber StateNumber 0 0 0 i=46 true ns=1;i=5057 i=40 false i=68 i=37 false i=78 2 i=7 -1 1 1 0 false 0 ns=1;i=6095 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5058 i=40 false i=68 i=37 false i=78 1 i=7 -1 1 1 0 false 0 ns=1;i=6096 Variable_2 0 StateNumber StateNumber 0 0 0 i=46 true ns=1;i=5059 i=40 false i=68 i=37 false i=78 1 i=7 -1 1 1 0 false 0 ns=1;i=6097 Variable_2 0 StateNumber StateNumber 0 0 0 i=46 true ns=1;i=5060 i=40 false i=68 i=37 false i=78 2 i=7 -1 1 1 0 false 0 ns=1;i=6098 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5061 i=40 false i=68 i=37 false i=78 1 i=7 -1 1 1 0 false 0 ns=1;i=6099 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5062 i=40 false i=68 i=37 false i=78 2 i=7 -1 1 1 0 false 0 ns=1;i=6100 Variable_2 0 StateNumber StateNumber 0 0 0 i=46 true ns=1;i=5063 i=40 false i=68 i=37 false i=78 1 i=7 -1 1 1 0 false 0 ns=1;i=6101 Variable_2 0 StateNumber StateNumber 0 0 0 i=46 true ns=1;i=5064 i=40 false i=68 i=37 false i=78 2 i=7 -1 1 1 0 false 0 ns=1;i=6102 Variable_2 0 StateNumber StateNumber 0 0 0 i=46 true ns=1;i=5065 i=40 false i=68 i=37 false i=78 3 i=7 -1 1 1 0 false 0 ns=1;i=6103 Variable_2 0 StateNumber StateNumber 0 0 0 i=46 true ns=1;i=5066 i=40 false i=68 i=37 false i=78 4 i=7 -1 1 1 0 false 0 ns=1;i=6104 Variable_2 0 StateNumber StateNumber 0 0 0 i=46 true ns=1;i=5067 i=40 false i=68 i=37 false i=78 5 i=7 -1 1 1 0 false 0 ns=1;i=6105 Variable_2 0 StateNumber StateNumber 0 0 0 i=46 true ns=1;i=5068 i=40 false i=68 i=37 false i=78 6 i=7 -1 1 1 0 false 0 ns=1;i=6106 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5069 i=40 false i=68 i=37 false i=78 1 i=7 -1 1 1 0 false 0 ns=1;i=6107 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5070 i=40 false i=68 i=37 false i=78 2 i=7 -1 1 1 0 false 0 ns=1;i=6108 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5071 i=40 false i=68 i=37 false i=78 3 i=7 -1 1 1 0 false 0 ns=1;i=6109 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5072 i=40 false i=68 i=37 false i=78 4 i=7 -1 1 1 0 false 0 ns=1;i=6110 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5073 i=40 false i=68 i=37 false i=78 5 i=7 -1 1 1 0 false 0 ns=1;i=6111 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5074 i=40 false i=68 i=37 false i=78 6 i=7 -1 1 1 0 false 0 ns=1;i=6112 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5075 i=40 false i=68 i=37 false i=78 7 i=7 -1 1 1 0 false 0 ns=1;i=6113 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5076 i=40 false i=68 i=37 false i=78 8 i=7 -1 1 1 0 false 0 ns=1;i=6114 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5077 i=40 false i=68 i=37 false i=78 9 i=7 -1 1 1 0 false 0 ns=1;i=6115 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5078 i=40 false i=68 i=37 false i=78 10 i=7 -1 1 1 0 false 0 ns=1;i=6116 Variable_2 0 TransitionNumber TransitionNumber 0 0 0 i=46 true ns=1;i=5079 i=40 false i=68 i=37 false i=78 11 i=7 -1 1 1 0 false 0 ns=1;i=7001 Method_4 1 Store Store 0 0 0 i=47 true ns=1;i=1002 i=37 false i=80 i=46 false ns=1;i=6040 i=46 false ns=1;i=6041 true true ns=1;i=7002 Method_4 1 RequestJobResponseByJobOrderID RequestJobResponseByJobOrderID 0 0 0 i=47 true ns=1;i=1003 i=37 false i=78 i=46 false ns=1;i=6042 i=46 false ns=1;i=6043 true true ns=1;i=7003 Method_4 1 ReceiveJobResponse ReceiveJobResponse 0 0 0 i=47 true ns=1;i=1004 i=37 false i=78 i=46 false ns=1;i=6044 i=46 false ns=1;i=6045 true true ns=1;i=7004 Method_4 1 StoreAndStart StoreAndStart 0 0 0 i=47 true ns=1;i=1002 i=37 false i=80 i=46 false ns=1;i=6051 i=46 false ns=1;i=6052 true true ns=1;i=7005 Method_4 1 Start Start 0 0 0 i=47 true ns=1;i=1002 i=37 false i=80 i=53 true ns=1;i=5042 i=53 true ns=1;i=5070 i=46 false ns=1;i=6053 i=46 false ns=1;i=6054 true true ns=1;i=7006 Method_4 1 Stop Stop 0 0 0 i=47 true ns=1;i=1002 i=37 false i=80 i=53 true ns=1;i=5051 i=53 true ns=1;i=5047 i=53 true ns=1;i=5075 i=53 true ns=1;i=5079 i=46 false ns=1;i=6055 i=46 false ns=1;i=6056 true true ns=1;i=7007 Method_4 1 Pause Pause 0 0 0 i=47 true ns=1;i=1002 i=37 false i=80 i=53 true ns=1;i=5046 i=53 true ns=1;i=5074 i=46 false ns=1;i=6057 i=46 false ns=1;i=6058 true true ns=1;i=7008 Method_4 1 Resume Resume 0 0 0 i=47 true ns=1;i=1002 i=37 false i=80 i=53 true ns=1;i=5050 i=53 true ns=1;i=5078 i=46 false ns=1;i=6059 i=46 false ns=1;i=6060 true true ns=1;i=7009 Method_4 1 Update Update 0 0 0 i=47 true ns=1;i=1002 i=37 false i=80 i=53 true ns=1;i=5044 i=53 true ns=1;i=5041 i=53 true ns=1;i=5069 i=53 true ns=1;i=5072 i=46 false ns=1;i=6061 i=46 false ns=1;i=6062 true true ns=1;i=7010 Method_4 1 Abort Abort 0 0 0 i=47 true ns=1;i=1002 i=37 false i=80 i=53 true ns=1;i=5048 i=53 true ns=1;i=5049 i=53 true ns=1;i=5076 i=53 true ns=1;i=5077 i=53 true ns=1;i=5084 i=53 true ns=1;i=5085 i=53 true ns=1;i=5086 i=53 true ns=1;i=5087 i=46 false ns=1;i=6063 i=46 false ns=1;i=6064 true true ns=1;i=7011 Method_4 1 Cancel Cancel 0 0 0 i=47 true ns=1;i=1002 i=37 false i=80 i=46 false ns=1;i=6065 i=46 false ns=1;i=6066 true true ns=1;i=7012 Method_4 1 Clear Clear 0 0 0 i=47 true ns=1;i=1002 i=37 false i=80 i=46 false ns=1;i=6067 i=46 false ns=1;i=6068 true true ns=1;i=7013 Method_4 1 RevokeStart RevokeStart 0 0 0 i=47 true ns=1;i=1002 i=37 false i=80 i=53 true ns=1;i=5043 i=53 true ns=1;i=5071 i=46 false ns=1;i=6069 i=46 false ns=1;i=6070 true true ns=1;i=7014 Method_4 1 RequestJobResponseByJobOrderState RequestJobResponseByJobOrderState 0 0 0 i=47 true ns=1;i=1003 i=37 false i=78 i=46 false ns=1;i=6016 i=46 false ns=1;i=6017 true true ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Isa95Jobs/Design/UAModel.ISA95_JOBCONTROL_V2.NodeSet2.documentation.csv ================================================ Id,Name,Link,ConformanceUnits 1001,ISA95PrepareStateMachineType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.3","ISA-95 Job Control Job Order Receiver SubStates;" 1002,ISA95JobOrderReceiverObjectType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.2","ISA-95 Job Order Receiver V2;" 1003,ISA95JobResponseProviderObjectType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.7/#7.2.7.1","ISA-95 Job Response Provider V2;" 1004,ISA95JobResponseReceiverObjectType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.8/#7.2.8.1","ISA-95 Job Response Receiver V2;" 1005,ISA95EndedStateMachineType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.4","ISA-95 Job Control Job Order Receiver SubStates;" 1006,ISA95JobOrderStatusEventType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.6","ISA-95 Job Control Job Response Provider Job Order Status Events;" 1007,ISA95InterruptedStateMachineType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.5","ISA-95 Job Control Job Order Receiver SubStates;" 1008,ISA95JobOrderReceiverSubStatesType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.2/#7.2.2.2","ISA-95 Job Control Job Order Receiver SubStates;" 3002,ISA95PropertyDataType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.9","ISA-95 Job Order Receiver V2;ISA-95 Job Response Provider V2;ISA-95 Job Response Receiver V2;" 3003,ISA95ParameterDataType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.10","ISA-95 Job Order Receiver V2;ISA-95 Job Response Provider V2;ISA-95 Job Response Receiver V2;" 3005,ISA95EquipmentDataType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.1","ISA-95 Job Order Receiver V2;ISA-95 Job Response Provider V2;ISA-95 Job Response Receiver V2;" 3006,ISA95StateDataType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.2","ISA-95 Job Order Receiver V2;ISA-95 Job Response Provider V2;ISA-95 Job Response Receiver V2;" 3007,ISA95WorkMasterDataType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.11","ISA-95 Job Order Receiver V2;" 3008,ISA95JobOrderDataType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.4","ISA-95 Job Order Receiver V2;" 3010,ISA95MaterialDataType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.6","ISA-95 Job Order Receiver V2;ISA-95 Job Response Provider V2;ISA-95 Job Response Receiver V2;" 3011,ISA95PersonnelDataType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.7","ISA-95 Job Order Receiver V2;ISA-95 Job Response Provider V2;ISA-95 Job Response Receiver V2;" 3012,ISA95PhysicalAssetDataType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.8","ISA-95 Job Order Receiver V2;ISA-95 Job Response Provider V2;ISA-95 Job Response Receiver V2;" 3013,ISA95JobResponseDataType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.5","ISA-95 Job Response Provider V2;ISA-95 Job Response Receiver V2;" 3015,ISA95JobOrderAndStateDataType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.3","ISA-95 Job Order Receiver V2;" 5001,http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/9.1","" 7001,Store,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.3","" 7002,RequestJobResponseByJobOrderID,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.7/#7.2.7.2","" 7003,ReceiveJobResponse,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.8/#7.2.8.2","" 7004,StoreAndStart,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.4","" 7005,Start,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.5","" 7006,Stop,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.11","" 7007,Pause,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.7","" 7008,Resume,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.8","" 7009,Update,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.9","" 7010,Abort,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.10","" 7011,Cancel,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.12","" 7012,Clear,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.13","" 7013,RevokeStart,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.6","" 7014,RequestJobResponseByJobOrderState,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.7/#7.2.7.3","" ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Isa95Jobs/Design/UAModel.ISA95_JOBCONTROL_V2.NodeSet2.xml ================================================  http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/ i=1 i=2 i=3 i=4 i=5 i=6 i=7 i=8 i=9 i=10 i=11 i=13 i=12 i=15 i=14 i=16 i=17 i=18 i=20 i=21 i=19 i=22 i=26 i=27 i=28 i=47 i=46 i=35 i=36 i=48 i=45 i=40 i=37 i=38 i=39 i=53 i=52 i=51 i=54 i=9004 i=9005 i=17597 i=9006 i=15112 i=17604 i=17603 ISA95EquipmentDataType Defines an equipment resource or a piece of equipment, a quantity, an optional description, and an optional collection of properties. ISA-95 Job Order Receiver V2 ISA-95 Job Response Provider V2 ISA-95 Job Response Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.1 ns=1;i=5008 ns=1;i=5010 ns=1;i=5009 i=22 An identification of an EquipmentClass or Equipment. Additional information and description about the resource. Information about the expected use of the equipment, see the ISA 95 Part 2 standard for defined values. The quantity of the resource The Unit Of Measure of the quantity Any associated properties, or empty if there are no properties defined. ISA95JobOrderAndStateDataType Defines the information needed to schedule and execute a job. ISA-95 Job Order Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.3 ns=1;i=5032 ns=1;i=5034 ns=1;i=5033 i=22 The job order The State of the job order. The array shall provide at least one entry representing the top level state and potentially additional entries representing substates. The first entry shall be the top level entry, having the BrowsePath set to Null. The order of the subtstates is not defined. ISA95JobOrderDataType Defines the information needed to schedule and execute a job. ISA-95 Job Order Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.4 ns=1;i=5014 ns=1;i=5016 ns=1;i=5015 i=22 An identification of the Job Order. Addition information about the Job Order The array allows to provide descriptions in different languages. Work Master associated with the job order. If multiple work masters are defined, then the execution system can select the work master based on the availability of resources. The proposed start time for the order, may be empty if not specified The proposed end time for the order, may be empty if not specified The priority of the job order, may be empty of not specified. Higher numbers have higher priority. This type allows the Job Order clients to pick their own ranges, and the Job Order server only has to pick the highest number. Key value pair with values, not associated with a resource that is provided as part of the job order, may be empty if not specified. A specification of any personnel requirements associated with the job order, may be empty if not specified A specification of any equipment requirements associated with the job order, may be empty if not specified. A specification of any physical asset requirements associated with the job order, may be empty if not specified. A specification of any material requirements associated with the job order, may be empty if not specified. ISA95JobResponseDataType Defines the information needed to schedule and execute a job. ISA-95 Job Response Provider V2 ISA-95 Job Response Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.5 ns=1;i=5026 ns=1;i=5028 ns=1;i=5027 i=22 An identification of the Job Response Additional information about the Job Response An identification of the job order associated with the job response. The actual start time for the order. The actual end time for the order. The current state of the job. The array shall provide at least one entry representing the top level state and potentially additional entries representing substates. The first entry shall be the top level entry, having the BrowsePath set to Null. The order of the subtstates is not defined. Key value pair with values, not associated with a resource that is provided as part of the job response, may be empty if not specified. A specification of any personnel requirements associated with the job response, may be empty if not specified. A specification of any equipment requirements associated with the job response, may be empty if not specified. A specification of any physical asset requirements associated with the job response, may be empty if not specified. A specification of any material requirements associated with the job response, may be empty if not specified. ISA95MaterialDataType Defines a material resource, a quantity, an optional description, and an optional collection of properties. ISA-95 Job Order Receiver V2 ISA-95 Job Response Provider V2 ISA-95 Job Response Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.6 ns=1;i=5017 ns=1;i=5019 ns=1;i=5018 i=22 An identification of the resource, or null if the Material Class is not used to identify the material. An identification of the resource, or null if the Material Definition is not used to identify the material. An identification of the resource, or null if the Material Lot is not used to identify the material. An identification of the resource, or null if the Material Sublot is not used to identify the material. Additional information and description about the resource. Information about the expected use of the material, see the ISA 95 Part 2 standard for defined values. The quantity of the resource The Unit Of Measure of the quantity Any associated properties, or empty if there are no properties defined. ISA95ParameterDataType A subtype of OPC UA Structure that defines three linked data items: the ID, which is a unique identifier for a property, the value, which is the data that is identified, and an optional description of the parameter. ISA-95 Job Order Receiver V2 ISA-95 Job Response Provider V2 ISA-95 Job Response Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.10 ns=1;i=5005 ns=1;i=5007 ns=1;i=5006 i=22 A unique identifier for a parameter Value of the parameter. An optional description of the parameter. The array allows to provide descriptions in different languages when writing. When accessing, the server shall only provide one entry in the array. The Unit Of Measure of the value ISA95PersonnelDataType Defines a personnel resource or a person, a quantity, an optional description, and an optional collection of properties. ISA-95 Job Order Receiver V2 ISA-95 Job Response Provider V2 ISA-95 Job Response Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.7 ns=1;i=5020 ns=1;i=5022 ns=1;i=5021 i=22 An identification of a Personnel Class or Person. Additional information and description about the resource. Information about the expected use of the personnel, see the ISA 95 Part 2 standard for defined values. The quantity of the resource The Unit Of Measure of the quantity Any associated properties, or empty if there are no properties defined. ISA95PhysicalAssetDataType Defines a physical asset, a quantity, an optional description, and an optional collection of properties. ISA-95 Job Order Receiver V2 ISA-95 Job Response Provider V2 ISA-95 Job Response Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.8 ns=1;i=5023 ns=1;i=5025 ns=1;i=5024 i=22 An identification of a Physical Asset Class or Physical Asset. Additional information and description about the resource. Information about the expected use of the physical asset, see the ISA 95 Part 2 standard for defined values. The quantity of the resource The Unit Of Measure of the quantity Any associated properties, or empty if there are no properties defined. ISA95PropertyDataType A subtype of OPC UA Structure that defines two linked data items: an ID, which is a unique identifier for a property within the scope of the associated resource, and the value, which is the data for the property. ISA-95 Job Order Receiver V2 ISA-95 Job Response Provider V2 ISA-95 Job Response Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.9 ns=1;i=5002 ns=1;i=5004 ns=1;i=5003 i=22 Unique identifier for a property within the scope of the associated resource Value for the property An optional description of the parameter. The Unit Of Measure of the value ISA95StateDataType Defines the information needed to schedule and execute a job. ISA-95 Job Order Receiver V2 ISA-95 Job Response Provider V2 ISA-95 Job Response Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.2 ns=1;i=5029 ns=1;i=5031 ns=1;i=5030 i=22 The browse path of substates. Shall be null when the top-level state is represented. The state represented as human readable text. Shall represent the same text as the CurrentState Variable of a StateMachine would. The state represented as number. Shall represent the same number as the Number subvariable of the CurrentState Variable of a StateMachine would. ISA95WorkMasterDataType Defines a Work Master ID and the defined parameters for the Work Master. ISA-95 Job Order Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.11 ns=1;i=5011 ns=1;i=5013 ns=1;i=5012 i=22 An identification of the Work Master. Additional information and description about the Work Master. Defined parameters for the Work Master. ISA95JobOrderStatusEventType ISA-95 Job Control Job Response Provider Job Order Status Events https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.6 ns=1;i=6047 ns=1;i=6049 ns=1;i=6048 ns=1;i=1003 ns=1;i=5041 ns=1;i=5042 ns=1;i=5043 ns=1;i=5044 ns=1;i=5045 ns=1;i=5046 ns=1;i=5047 ns=1;i=5048 ns=1;i=5049 ns=1;i=5050 ns=1;i=5051 ns=1;i=5069 ns=1;i=5070 ns=1;i=5071 ns=1;i=5072 ns=1;i=5073 ns=1;i=5074 ns=1;i=5075 ns=1;i=5076 ns=1;i=5077 ns=1;i=5078 ns=1;i=5079 ns=1;i=5084 ns=1;i=5085 ns=1;i=5086 ns=1;i=5087 i=2041 JobOrder i=68 i=78 ns=1;i=1006 JobResponse i=68 i=78 ns=1;i=1006 JobState i=68 i=78 ns=1;i=1006 ISA95JobResponseProviderObjectType The OPENSCSJobResponseProviderObjectType contains a method to receive unsolicited job response requests. ISA-95 Job Response Provider V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.7/#7.2.7.1 ns=1;i=6050 ns=1;i=7002 ns=1;i=7014 ns=1;i=1006 i=58 JobOrderResponseList i=63 i=80 ns=1;i=1003 RequestJobResponseByJobOrderID https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.7/#7.2.7.2 ns=1;i=6042 ns=1;i=6043 i=78 ns=1;i=1003 InputArguments i=68 i=78 ns=1;i=7002 i=297 JobOrderID i=12 -1 Contains an ID of the job order, as specified by the method caller. OutputArguments i=68 i=78 ns=1;i=7002 i=297 JobResponse ns=1;i=3013 -1 Contains information about the execution of a job order, such as the current status of the job, actual material consumed, actual material produced, actual equipment used, and job specific data. i=297 ReturnStatus i=9 -1 Returns the status of the method execution. RequestJobResponseByJobOrderState https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.7/#7.2.7.3 ns=1;i=6016 ns=1;i=6017 i=78 ns=1;i=1003 InputArguments i=68 i=78 ns=1;i=7014 i=297 JobOrderState ns=1;i=3006 1 0 Contains a job status of the JobResponse to be returned. The array shall provide at least one entry representing the top level state and potentially additional entries representing substates. The first entry shall be the top level entry, having the BrowsePath set to null. The order of the substates is not defined. OutputArguments i=68 i=78 ns=1;i=7014 i=297 JobResponses ns=1;i=3013 1 0 Contains a list of information about the execution of a job order, such as the current status of the job, actual material consumed, actual material produced, actual equipment used, and job specific data. i=297 ReturnStatus i=9 -1 Returns the status of the method execution. ISA95JobResponseReceiverObjectType A Job Response Receiver receives unsolicited Job Responses, usually as the result of completion of a job, or at intermediate points within the job. ISA-95 Job Response Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.8/#7.2.8.1 ns=1;i=7003 i=58 ReceiveJobResponse https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.8/#7.2.8.2 ns=1;i=6044 ns=1;i=6045 i=78 ns=1;i=1004 InputArguments i=68 i=78 ns=1;i=7003 i=297 JobResponse ns=1;i=3013 -1 Contains information about the execution of a job order, such as actual material consumed, actual material produced, actual equipment used, and job specific data. OutputArguments i=68 i=78 ns=1;i=7003 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. ISA95EndedStateMachineType ISA-95 Job Control Job Order Receiver SubStates https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.4 ns=1;i=5057 ns=1;i=5056 ns=1;i=5058 i=2771 Closed The job order has been completed and no further post processing is performed. ns=1;i=6094 ns=1;i=5058 i=2307 ns=1;i=1005 StateNumber i=68 i=78 ns=1;i=5057 2 Completed The job order has been completed and is no longer in execution. ns=1;i=6093 ns=1;i=5058 i=2307 ns=1;i=1005 StateNumber i=68 i=78 ns=1;i=5056 1 FromCompletedToClosed This transition is triggered when the system has finalized post processing of a ended job order. ns=1;i=6095 ns=1;i=5057 ns=1;i=5056 i=2310 ns=1;i=1005 TransitionNumber i=68 i=78 ns=1;i=5058 1 ISA95InterruptedStateMachineType ISA-95 Job Control Job Order Receiver SubStates https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.5 ns=1;i=5061 ns=1;i=5062 ns=1;i=5059 ns=1;i=5060 i=2771 FromHeldToSuspended This transition is triggered when the system has switched the job order from internally held to externally suspended, for example by a call of the Pause Method. ns=1;i=6098 ns=1;i=5059 ns=1;i=5060 i=2310 ns=1;i=1007 TransitionNumber i=68 i=78 ns=1;i=5061 1 FromSuspendedToHeld This transition is triggered when the system has switched the job order from externally suspended to an internal held, for example by a call of the Resume Method. ns=1;i=6099 ns=1;i=5059 ns=1;i=5060 i=2310 ns=1;i=1007 TransitionNumber i=68 i=78 ns=1;i=5062 2 Held The job order has been temporarily stopped due to a constraint of some form. ns=1;i=6096 ns=1;i=5061 ns=1;i=5062 i=2307 ns=1;i=1007 StateNumber i=68 i=78 ns=1;i=5059 1 Suspended The job order has been temporarily stopped due to a deliberate decision within the execution system. ns=1;i=6097 ns=1;i=5061 ns=1;i=5062 i=2307 ns=1;i=1007 StateNumber i=68 i=78 ns=1;i=5060 2 ISA95JobOrderReceiverObjectType The OPENSCSJobOrderReciverObjectType contains a method to receive job order commands and optional definitions of allowable job order information ISA-95 Job Order Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.2 ns=1;i=7010 ns=1;i=5040 ns=1;i=5036 ns=1;i=7011 ns=1;i=7012 ns=1;i=5039 ns=1;i=6037 ns=1;i=5085 ns=1;i=5044 ns=1;i=5043 ns=1;i=5045 ns=1;i=5049 ns=1;i=5051 ns=1;i=5050 ns=1;i=5084 ns=1;i=5042 ns=1;i=5041 ns=1;i=5048 ns=1;i=5047 ns=1;i=5046 ns=1;i=5038 ns=1;i=6033 ns=1;i=6035 ns=1;i=6036 ns=1;i=6088 ns=1;i=5035 ns=1;i=7007 ns=1;i=6039 ns=1;i=6038 ns=1;i=7008 ns=1;i=7013 ns=1;i=5037 ns=1;i=7005 ns=1;i=7006 ns=1;i=7001 ns=1;i=7004 ns=1;i=7009 ns=1;i=6034 i=2771 Abort https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.10 ns=1;i=6063 ns=1;i=6064 ns=1;i=5048 ns=1;i=5049 ns=1;i=5076 ns=1;i=5077 ns=1;i=5084 ns=1;i=5085 ns=1;i=5086 ns=1;i=5087 i=80 ns=1;i=1002 InputArguments i=68 i=78 ns=1;i=7010 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. OutputArguments i=68 i=78 ns=1;i=7010 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. Aborted The job order is aborted. ns=1;i=6076 ns=1;i=5048 ns=1;i=5049 ns=1;i=5084 ns=1;i=5085 i=2307 ns=1;i=1002 StateNumber i=68 i=78 ns=1;i=5040 6 AllowedToStart The job order is stored and may be executed. ns=1;i=6072 ns=1;i=5042 ns=1;i=5043 ns=1;i=5044 ns=1;i=5044 ns=1;i=5045 ns=1;i=5085 i=2307 ns=1;i=1002 StateNumber i=68 i=78 ns=1;i=5036 2 Cancel https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.12 ns=1;i=6065 ns=1;i=6066 i=80 ns=1;i=1002 InputArguments i=68 i=78 ns=1;i=7011 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. OutputArguments i=68 i=78 ns=1;i=7011 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. Clear https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.13 ns=1;i=6067 ns=1;i=6068 i=80 ns=1;i=1002 InputArguments i=68 i=78 ns=1;i=7012 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. OutputArguments i=68 i=78 ns=1;i=7012 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. Ended The job order has been completed and is no longer in execution. ns=1;i=6075 ns=1;i=5047 ns=1;i=5051 i=2307 ns=1;i=1002 StateNumber i=68 i=78 ns=1;i=5039 5 EquipmentID Defines a read-only set of Equipment Class IDs and Equipment IDs that may be specified in a job order. i=63 i=78 ns=1;i=1002 FromAllowedToStartToAborted This transition is triggered when Abort Method is called. ns=1;i=6010 ns=1;i=7010 ns=1;i=5040 ns=1;i=5036 ns=1;i=1006 i=2310 ns=1;i=1002 TransitionNumber i=68 i=78 ns=1;i=5085 13 FromAllowedToStartToAllowedToStart This transition is triggered when the Update Method is called and the job order is modified. ns=1;i=6080 ns=1;i=5036 ns=1;i=5036 ns=1;i=1006 ns=1;i=7009 i=2310 ns=1;i=1002 TransitionNumber i=68 i=78 ns=1;i=5044 4 FromAllowedToStartToNotAllowedToStart This transition is triggered when the RevokeStart Method is called. ns=1;i=6079 ns=1;i=5036 ns=1;i=1006 ns=1;i=5035 ns=1;i=7013 i=2310 ns=1;i=1002 TransitionNumber i=68 i=78 ns=1;i=5043 3 FromAllowedToStartToRunning This transition is triggered when a job order is started to be executed. ns=1;i=6081 ns=1;i=5036 ns=1;i=1006 ns=1;i=5037 i=2310 ns=1;i=1002 TransitionNumber i=68 i=78 ns=1;i=5045 5 FromInterruptedToAborted This transition is triggered when Abort Method is called. ns=1;i=6085 ns=1;i=7010 ns=1;i=5040 ns=1;i=5038 ns=1;i=1006 i=2310 ns=1;i=1002 TransitionNumber i=68 i=78 ns=1;i=5049 9 FromInterruptedToEnded This transition is triggered when Stop Method is called. ns=1;i=6087 ns=1;i=5039 ns=1;i=5038 ns=1;i=1006 ns=1;i=7006 i=2310 ns=1;i=1002 TransitionNumber i=68 i=78 ns=1;i=5051 11 FromInterruptedToRunning This transition is triggered when Resume Method is called. ns=1;i=6086 ns=1;i=5038 ns=1;i=1006 ns=1;i=7008 ns=1;i=5037 i=2310 ns=1;i=1002 TransitionNumber i=68 i=78 ns=1;i=5050 10 FromNotAllowedToStartToAborted This transition is triggered when Abort Method is called. ns=1;i=6009 ns=1;i=7010 ns=1;i=5040 ns=1;i=1006 ns=1;i=5035 i=2310 ns=1;i=1002 TransitionNumber i=68 i=78 ns=1;i=5084 12 FromNotAllowedToStartToAllowedToStart This transition is triggered when the Start Method is called. ns=1;i=6078 ns=1;i=5036 ns=1;i=1006 ns=1;i=5035 ns=1;i=7005 i=2310 ns=1;i=1002 TransitionNumber i=68 i=78 ns=1;i=5042 2 FromNotAllowedToStartToNotAllowedToStart This transition is triggered when the Update Method is called and the job order is modified. ns=1;i=6077 ns=1;i=1006 ns=1;i=5035 ns=1;i=5035 ns=1;i=7009 i=2310 ns=1;i=1002 TransitionNumber i=68 i=78 ns=1;i=5041 1 FromRunningToAborted This transition is triggered when Abort Method is called. ns=1;i=6084 ns=1;i=7010 ns=1;i=5040 ns=1;i=1006 ns=1;i=5037 i=2310 ns=1;i=1002 TransitionNumber i=68 i=78 ns=1;i=5048 8 FromRunningToEnded This transition is triggered when the execution of a job order has finished, either internally or by the Stop Method. ns=1;i=6083 ns=1;i=5039 ns=1;i=1006 ns=1;i=5037 ns=1;i=7006 i=2310 ns=1;i=1002 TransitionNumber i=68 i=78 ns=1;i=5047 7 FromRunningToInterrupted This transition is triggered when an executing job order gets interrupted, either internally or by the Pause Method. ns=1;i=6082 ns=1;i=5038 ns=1;i=1006 ns=1;i=7007 ns=1;i=5037 i=2310 ns=1;i=1002 TransitionNumber i=68 i=78 ns=1;i=5046 6 Interrupted The job order has been temporarily stopped. ns=1;i=6074 ns=1;i=5049 ns=1;i=5051 ns=1;i=5050 ns=1;i=5046 i=2307 ns=1;i=1002 StateNumber i=68 i=78 ns=1;i=5038 4 JobOrderList Defines a read-only list of job order information available from the server. i=63 i=78 ns=1;i=1002 MaterialClassID Defines a read-only set of Material Classes IDs that may be specified in a job order. i=63 i=78 ns=1;i=1002 MaterialDefinitionID Defines a read-only set of Material Classes IDs that may be specified in a job order. i=63 i=78 ns=1;i=1002 MaxDownloadableJobOrders i=68 i=78 ns=1;i=1002 NotAllowedToStart The job order is stored but may not be executed. ns=1;i=6071 ns=1;i=5043 ns=1;i=5084 ns=1;i=5042 ns=1;i=5041 ns=1;i=5041 i=2307 ns=1;i=1002 StateNumber i=68 i=78 ns=1;i=5035 1 Pause https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.7 ns=1;i=6057 ns=1;i=6058 ns=1;i=5046 ns=1;i=5074 i=80 ns=1;i=1002 InputArguments i=68 i=78 ns=1;i=7007 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. OutputArguments i=68 i=78 ns=1;i=7007 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. PersonnelID Defines a read-only set of Personnel IDs and Person IDs that may be specified in a job order. i=63 i=78 ns=1;i=1002 PhysicalAssetID Defines a read-only set of Physical Asset Class IDs and Physical Asset IDs that may be specified in a job order. i=63 i=78 ns=1;i=1002 Resume https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.8 ns=1;i=6059 ns=1;i=6060 ns=1;i=5050 ns=1;i=5078 i=80 ns=1;i=1002 InputArguments i=68 i=78 ns=1;i=7008 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. OutputArguments i=68 i=78 ns=1;i=7008 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. RevokeStart https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.6 ns=1;i=6069 ns=1;i=6070 ns=1;i=5043 ns=1;i=5071 i=80 ns=1;i=1002 InputArguments i=68 i=78 ns=1;i=7013 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. OutputArguments i=68 i=78 ns=1;i=7013 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. Running The job order is executing. ns=1;i=6073 ns=1;i=5045 ns=1;i=5050 ns=1;i=5048 ns=1;i=5047 ns=1;i=5046 i=2307 ns=1;i=1002 StateNumber i=68 i=78 ns=1;i=5037 3 Start https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.5 ns=1;i=6053 ns=1;i=6054 ns=1;i=5042 ns=1;i=5070 i=80 ns=1;i=1002 InputArguments i=68 i=78 ns=1;i=7005 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. OutputArguments i=68 i=78 ns=1;i=7005 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. Stop https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.11 ns=1;i=6055 ns=1;i=6056 ns=1;i=5051 ns=1;i=5047 ns=1;i=5075 ns=1;i=5079 i=80 ns=1;i=1002 InputArguments i=68 i=78 ns=1;i=7006 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. OutputArguments i=68 i=78 ns=1;i=7006 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. Store https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.3 ns=1;i=6040 ns=1;i=6041 i=80 ns=1;i=1002 InputArguments i=68 i=78 ns=1;i=7001 i=297 JobOrder ns=1;i=3008 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. OutputArguments i=68 i=78 ns=1;i=7001 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. StoreAndStart https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.4 ns=1;i=6051 ns=1;i=6052 i=80 ns=1;i=1002 InputArguments i=68 i=78 ns=1;i=7004 i=297 JobOrder ns=1;i=3008 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. OutputArguments i=68 i=78 ns=1;i=7004 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. Update https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.9 ns=1;i=6061 ns=1;i=6062 ns=1;i=5044 ns=1;i=5041 ns=1;i=5069 ns=1;i=5072 i=80 ns=1;i=1002 InputArguments i=68 i=78 ns=1;i=7009 i=297 JobOrder ns=1;i=3008 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. OutputArguments i=68 i=78 ns=1;i=7009 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. WorkMaster Defines a read-only set of work master IDs that may be specified in a job order, and the read-only set of parameters that may be specified for a specific work master. i=63 i=78 ns=1;i=1002 ISA95JobOrderReceiverSubStatesType ISA-95 Job Control Job Order Receiver SubStates https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.2/#7.2.2.2 ns=1;i=5068 ns=1;i=5064 ns=1;i=5067 ns=1;i=5086 ns=1;i=5072 ns=1;i=5071 ns=1;i=5073 ns=1;i=5077 ns=1;i=5079 ns=1;i=5078 ns=1;i=5087 ns=1;i=5070 ns=1;i=5069 ns=1;i=5076 ns=1;i=5075 ns=1;i=5074 ns=1;i=5066 ns=1;i=5063 ns=1;i=5065 ns=1;i=5081 ns=1;i=5082 ns=1;i=5083 ns=1;i=5080 ns=1;i=1002 Aborted The job order is aborted. ns=1;i=6105 ns=1;i=5076 ns=1;i=5077 ns=1;i=5087 ns=1;i=5086 i=2307 ns=1;i=1008 StateNumber i=68 i=78 ns=1;i=5068 6 AllowedToStart The job order is stored and may be executed. ns=1;i=6101 ns=1;i=5070 ns=1;i=5071 ns=1;i=5072 ns=1;i=5072 ns=1;i=5073 ns=1;i=5086 ns=1;i=5081 i=2307 ns=1;i=1008 StateNumber i=68 i=78 ns=1;i=5064 2 Ended The job order has been completed and is no longer in execution. ns=1;i=6104 ns=1;i=5075 ns=1;i=5079 ns=1;i=5082 i=2307 ns=1;i=1008 StateNumber i=68 i=78 ns=1;i=5067 5 FromAllowedToStartToAborted This transition is triggered when Abort Method is called. ns=1;i=6011 ns=1;i=5068 ns=1;i=5064 ns=1;i=1006 ns=1;i=7010 i=2310 ns=1;i=1008 TransitionNumber i=68 i=78 ns=1;i=5086 13 FromAllowedToStartToAllowedToStart This transition is triggered when the Update Method is called and the job order is modified. ns=1;i=6109 ns=1;i=5064 ns=1;i=5064 ns=1;i=1006 ns=1;i=7009 i=2310 ns=1;i=1008 TransitionNumber i=68 i=78 ns=1;i=5072 4 FromAllowedToStartToNotAllowedToStart This transition is triggered when the RevokeStart Method is called. ns=1;i=6108 ns=1;i=5064 ns=1;i=1006 ns=1;i=5063 ns=1;i=7013 i=2310 ns=1;i=1008 TransitionNumber i=68 i=78 ns=1;i=5071 3 FromAllowedToStartToRunning This transition is triggered when a job order is started to be executed. ns=1;i=6110 ns=1;i=5064 ns=1;i=1006 ns=1;i=5065 i=2310 ns=1;i=1008 TransitionNumber i=68 i=78 ns=1;i=5073 5 FromInterruptedToAborted This transition is triggered when Abort Method is called. ns=1;i=6114 ns=1;i=5068 ns=1;i=5066 ns=1;i=1006 ns=1;i=7010 i=2310 ns=1;i=1008 TransitionNumber i=68 i=78 ns=1;i=5077 9 FromInterruptedToEnded This transition is triggered when Stop Method is called. ns=1;i=6116 ns=1;i=5067 ns=1;i=5066 ns=1;i=1006 ns=1;i=7006 i=2310 ns=1;i=1008 TransitionNumber i=68 i=78 ns=1;i=5079 11 FromInterruptedToRunning This transition is triggered when Resume Method is called. ns=1;i=6115 ns=1;i=5066 ns=1;i=1006 ns=1;i=5065 ns=1;i=7008 i=2310 ns=1;i=1008 TransitionNumber i=68 i=78 ns=1;i=5078 10 FromNotAllowedToStartToAborted This transition is triggered when Abort Method is called. ns=1;i=6012 ns=1;i=5068 ns=1;i=1006 ns=1;i=5063 ns=1;i=7010 i=2310 ns=1;i=1008 TransitionNumber i=68 i=78 ns=1;i=5087 12 FromNotAllowedToStartToAllowedToStart This transition is triggered when the Start Method is called. ns=1;i=6107 ns=1;i=5064 ns=1;i=1006 ns=1;i=5063 ns=1;i=7005 i=2310 ns=1;i=1008 TransitionNumber i=68 i=78 ns=1;i=5070 2 FromNotAllowedToStartToNotAllowedToStart This transition is triggered when the Update Method is called and the job order is modified. ns=1;i=6106 ns=1;i=1006 ns=1;i=5063 ns=1;i=5063 ns=1;i=7009 i=2310 ns=1;i=1008 TransitionNumber i=68 i=78 ns=1;i=5069 1 FromRunningToAborted This transition is triggered when Abort Method is called. ns=1;i=6113 ns=1;i=5068 ns=1;i=1006 ns=1;i=5065 ns=1;i=7010 i=2310 ns=1;i=1008 TransitionNumber i=68 i=78 ns=1;i=5076 8 FromRunningToEnded This transition is triggered when the execution of a job order has finished, either internally or by the Stop Method. ns=1;i=6112 ns=1;i=5067 ns=1;i=1006 ns=1;i=5065 ns=1;i=7006 i=2310 ns=1;i=1008 TransitionNumber i=68 i=78 ns=1;i=5075 7 FromRunningToInterrupted This transition is triggered when an executing job order gets interrupted, either internally or by the Pause Method. ns=1;i=6111 ns=1;i=5066 ns=1;i=1006 ns=1;i=5065 ns=1;i=7007 i=2310 ns=1;i=1008 TransitionNumber i=68 i=78 ns=1;i=5074 6 Interrupted The job order has been temporarily stopped. ns=1;i=6103 ns=1;i=5077 ns=1;i=5079 ns=1;i=5078 ns=1;i=5074 ns=1;i=5083 i=2307 ns=1;i=1008 StateNumber i=68 i=78 ns=1;i=5066 4 NotAllowedToStart The job order is stored but may not be executed. ns=1;i=6100 ns=1;i=5071 ns=1;i=5087 ns=1;i=5070 ns=1;i=5069 ns=1;i=5069 ns=1;i=5080 i=2307 ns=1;i=1008 StateNumber i=68 i=78 ns=1;i=5063 1 Running The job order is executing. ns=1;i=6102 ns=1;i=5073 ns=1;i=5078 ns=1;i=5076 ns=1;i=5075 ns=1;i=5074 i=2307 ns=1;i=1008 StateNumber i=68 i=78 ns=1;i=5065 3 AllowedToStartSubstates Substates of AllowedToStart ns=1;i=6003 ns=1;i=5064 ns=1;i=1001 i=80 ns=1;i=1008 CurrentState ns=1;i=6004 i=2760 i=78 ns=1;i=5081 Id i=68 i=78 ns=1;i=6003 EndedSubstates Substates of Ended ns=1;i=6005 ns=1;i=5067 ns=1;i=1005 i=80 ns=1;i=1008 CurrentState ns=1;i=6006 i=2760 i=78 ns=1;i=5082 Id i=68 i=78 ns=1;i=6005 InterruptedSubstates Substates of Interrupted ns=1;i=6007 ns=1;i=5066 ns=1;i=1007 i=80 ns=1;i=1008 CurrentState ns=1;i=6008 i=2760 i=78 ns=1;i=5083 Id i=68 i=78 ns=1;i=6007 NotAllowedToStartSubstates Substates of NotAllowedToStart ns=1;i=6001 ns=1;i=5063 ns=1;i=1001 i=80 ns=1;i=1008 CurrentState ns=1;i=6002 i=2760 i=78 ns=1;i=5080 Id i=68 i=78 ns=1;i=6001 ISA95PrepareStateMachineType ISA-95 Job Control Job Order Receiver SubStates https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.3 ns=1;i=5089 ns=1;i=5090 ns=1;i=5055 ns=1;i=5088 ns=1;i=5054 ns=1;i=5053 ns=1;i=5052 ns=1;i=5000 i=2771 FromLoadedToReady This transition is triggered when the program or configuration to execute the job order is unloaded. ns=1;i=6014 ns=1;i=5053 ns=1;i=5052 i=2310 ns=1;i=1001 TransitionNumber i=68 i=78 ns=1;i=5089 4 FromLoadedToWaiting This transition is triggered when the system is not ready to start the execution of the job order anymore. ns=1;i=6015 ns=1;i=5053 ns=1;i=5000 i=2310 ns=1;i=1001 TransitionNumber i=68 i=78 ns=1;i=5090 5 FromReadyToLoaded This transition is triggered when the program or configuration to execute the job order is loaded. ns=1;i=6092 ns=1;i=5053 ns=1;i=5052 i=2310 ns=1;i=1001 TransitionNumber i=68 i=78 ns=1;i=5055 2 FromReadyToWaiting This transition is triggered when the system is not ready to start the execution of the job order anymore. ns=1;i=6013 ns=1;i=5052 ns=1;i=5000 i=2310 ns=1;i=1001 TransitionNumber i=68 i=78 ns=1;i=5088 3 FromWaitingToReady This transition is triggered when the system is ready to start the execution of the job order. ns=1;i=6091 ns=1;i=5052 ns=1;i=5000 i=2310 ns=1;i=1001 TransitionNumber i=68 i=78 ns=1;i=5054 1 Loaded In situations where only one job may be in active memory and is able to be run, then the job is loaded in active memory, the necessary pre-conditions have been met, and the job order is ready to run, awaiting a Start command. ns=1;i=6090 ns=1;i=5089 ns=1;i=5090 ns=1;i=5055 i=2307 ns=1;i=1001 StateNumber i=68 i=78 ns=1;i=5053 3 Ready The necessary pre-conditions have been met and the job order is ready to run, awaiting a Start command. ns=1;i=6089 ns=1;i=5089 ns=1;i=5055 ns=1;i=5088 ns=1;i=5054 i=2307 ns=1;i=1001 StateNumber i=68 i=78 ns=1;i=5052 2 Waiting The necessary pre-conditions have not been met and the job order is not ready to run. ns=1;i=6000 ns=1;i=5090 ns=1;i=5088 ns=1;i=5054 i=2307 ns=1;i=1001 StateNumber i=68 i=78 ns=1;i=5000 1 http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/ https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/9.1 ns=1;i=6025 ns=1;i=6026 ns=1;i=6024 ns=1;i=6023 ns=1;i=6027 ns=1;i=6028 ns=1;i=6029 i=11715 i=11616 NamespaceUri i=68 ns=1;i=5001 http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/ NamespaceVersion i=68 ns=1;i=5001 2.0.0 NamespacePublicationDate i=68 ns=1;i=5001 2024-01-31T00:00:00Z IsNamespaceSubset i=68 ns=1;i=5001 false StaticNodeIdTypes i=68 ns=1;i=5001 0 StaticNumericNodeIdRange i=68 ns=1;i=5001 1:2147483647 StaticStringNodeIdPattern i=68 ns=1;i=5001 0 Default Binary ns=1;i=3002 ns=1;i=6128 i=76 Default XML ns=1;i=3002 ns=1;i=6129 i=76 Default JSON ns=1;i=3002 i=76 Default Binary ns=1;i=3003 ns=1;i=6122 i=76 Default XML ns=1;i=3003 ns=1;i=6123 i=76 Default JSON ns=1;i=3003 i=76 Default Binary ns=1;i=3005 ns=1;i=6022 i=76 Default XML ns=1;i=3005 ns=1;i=6030 i=76 Default JSON ns=1;i=3005 i=76 Default Binary ns=1;i=3007 ns=1;i=6132 i=76 Default XML ns=1;i=3007 ns=1;i=6133 i=76 Default JSON ns=1;i=3007 i=76 Default Binary ns=1;i=3008 ns=1;i=6046 i=76 Default XML ns=1;i=3008 ns=1;i=6117 i=76 Default JSON ns=1;i=3008 i=76 Default Binary ns=1;i=3010 ns=1;i=6120 i=76 Default XML ns=1;i=3010 ns=1;i=6121 i=76 Default JSON ns=1;i=3010 i=76 Default Binary ns=1;i=3011 ns=1;i=6124 i=76 Default XML ns=1;i=3011 ns=1;i=6125 i=76 Default JSON ns=1;i=3011 i=76 Default Binary ns=1;i=3012 ns=1;i=6126 i=76 Default XML ns=1;i=3012 ns=1;i=6127 i=76 Default JSON ns=1;i=3012 i=76 Default Binary ns=1;i=3013 ns=1;i=6118 i=76 Default XML ns=1;i=3013 ns=1;i=6119 i=76 Default JSON ns=1;i=3013 i=76 Default Binary ns=1;i=3006 ns=1;i=6130 i=76 Default XML ns=1;i=3006 ns=1;i=6131 i=76 Default JSON ns=1;i=3006 i=76 Default Binary ns=1;i=3015 ns=1;i=6031 i=76 Default XML ns=1;i=3015 ns=1;i=6032 i=76 Default JSON ns=1;i=3015 i=76 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Isa95Jobs/Design/UAModel.ISA95_JOBCONTROL_V2.PredefinedNodes.xml ================================================  http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/ DataType_64 ns=1;i=3005 1 ISA95EquipmentDataType Defines an equipment resource or a piece of equipment, a quantity, an optional description, and an optional collection of properties. i=22 i=14798 i=22 StructureWithOptionalFields_1 ID An identification of an EquipmentClass or Equipment. i=12 -1 0 false Description Additional information and description about the resource. i=21 1 0 0 true EquipmentUse Information about the expected use of the equipment, see the ISA 95 Part 2 standard for defined values. i=12 -1 0 true Quantity The quantity of the resource i=12878 -1 0 true EngineeringUnits The Unit Of Measure of the quantity i=887 -1 0 true Properties Any associated properties, or empty if there are no properties defined. ns=1;i=3002 1 0 0 true i=38 ns=1;i=5008 i=38 ns=1;i=5010 i=38 ns=1;i=5009 DataType_64 ns=1;i=3015 1 ISA95JobOrderAndStateDataType Defines the information needed to schedule and execute a job. i=22 i=14798 i=22 Structure_0 JobOrder The job order ns=1;i=3008 -1 0 false State The State of the job order. The array shall provide at least one entry representing the top level state and potentially additional entries representing substates. The first entry shall be the top level entry, having the BrowsePath set to Null. The order of the subtstates is not defined. ns=1;i=3006 1 0 0 false i=38 ns=1;i=5032 i=38 ns=1;i=5034 i=38 ns=1;i=5033 DataType_64 ns=1;i=3008 1 ISA95JobOrderDataType Defines the information needed to schedule and execute a job. i=22 i=14798 i=22 StructureWithOptionalFields_1 JobOrderID An identification of the Job Order. i=12 -1 0 false Description Addition information about the Job Order The array allows to provide descriptions in different languages. i=21 1 0 0 true WorkMasterID Work Master associated with the job order. If multiple work masters are defined, then the execution system can select the work master based on the availability of resources. ns=1;i=3007 1 0 0 true StartTime The proposed start time for the order, may be empty if not specified i=13 -1 0 true EndTime The proposed end time for the order, may be empty if not specified i=13 -1 0 true Priority The priority of the job order, may be empty of not specified. Higher numbers have higher priority. This type allows the Job Order clients to pick their own ranges, and the Job Order server only has to pick the highest number. i=4 -1 0 true JobOrderParameters Key value pair with values, not associated with a resource that is provided as part of the job order, may be empty if not specified. ns=1;i=3003 1 0 0 true PersonnelRequirements A specification of any personnel requirements associated with the job order, may be empty if not specified ns=1;i=3011 1 0 0 true EquipmentRequirements A specification of any equipment requirements associated with the job order, may be empty if not specified. ns=1;i=3005 1 0 0 true PhysicalAssetRequirements A specification of any physical asset requirements associated with the job order, may be empty if not specified. ns=1;i=3012 1 0 0 true MaterialRequirements A specification of any material requirements associated with the job order, may be empty if not specified. ns=1;i=3010 1 0 0 true i=38 ns=1;i=5014 i=38 ns=1;i=5016 i=38 ns=1;i=5015 DataType_64 ns=1;i=3013 1 ISA95JobResponseDataType Defines the information needed to schedule and execute a job. i=22 i=14798 i=22 StructureWithOptionalFields_1 JobResponseID An identification of the Job Response i=12 -1 0 false Description Additional information about the Job Response i=21 -1 0 true JobOrderID An identification of the job order associated with the job response. i=12 -1 0 false StartTime The actual start time for the order. i=13 -1 0 true EndTime The actual end time for the order. i=13 -1 0 true JobState The current state of the job. The array shall provide at least one entry representing the top level state and potentially additional entries representing substates. The first entry shall be the top level entry, having the BrowsePath set to Null. The order of the subtstates is not defined. ns=1;i=3006 1 0 0 false JobResponseData Key value pair with values, not associated with a resource that is provided as part of the job response, may be empty if not specified. ns=1;i=3003 1 0 0 true PersonnelActuals A specification of any personnel requirements associated with the job response, may be empty if not specified. ns=1;i=3011 1 0 0 true EquipmentActuals A specification of any equipment requirements associated with the job response, may be empty if not specified. ns=1;i=3005 1 0 0 true PhysicalAssetActuals A specification of any physical asset requirements associated with the job response, may be empty if not specified. ns=1;i=3012 1 0 0 true MaterialActuals A specification of any material requirements associated with the job response, may be empty if not specified. ns=1;i=3010 1 0 0 true i=38 ns=1;i=5026 i=38 ns=1;i=5028 i=38 ns=1;i=5027 DataType_64 ns=1;i=3010 1 ISA95MaterialDataType Defines a material resource, a quantity, an optional description, and an optional collection of properties. i=22 i=14798 i=22 StructureWithOptionalFields_1 MaterialClassID An identification of the resource, or null if the Material Class is not used to identify the material. i=12 -1 0 true MaterialDefinitionID An identification of the resource, or null if the Material Definition is not used to identify the material. i=12 -1 0 true MaterialLotID An identification of the resource, or null if the Material Lot is not used to identify the material. i=12 -1 0 true MaterialSublotID An identification of the resource, or null if the Material Sublot is not used to identify the material. i=12 -1 0 true Description Additional information and description about the resource. i=21 1 0 0 true MaterialUse Information about the expected use of the material, see the ISA 95 Part 2 standard for defined values. i=12 -1 0 true Quantity The quantity of the resource i=12878 -1 0 true EngineeringUnits The Unit Of Measure of the quantity i=887 -1 0 true Properties Any associated properties, or empty if there are no properties defined. ns=1;i=3002 1 0 0 true i=38 ns=1;i=5017 i=38 ns=1;i=5019 i=38 ns=1;i=5018 DataType_64 ns=1;i=3003 1 ISA95ParameterDataType A subtype of OPC UA Structure that defines three linked data items: the ID, which is a unique identifier for a property, the value, which is the data that is identified, and an optional description of the parameter. i=22 i=14798 i=22 StructureWithOptionalFields_1 ID A unique identifier for a parameter i=12 -1 0 false Value Value of the parameter. i=24 -1 0 false Description An optional description of the parameter. The array allows to provide descriptions in different languages when writing. When accessing, the server shall only provide one entry in the array. i=21 1 0 0 true EngineeringUnits The Unit Of Measure of the value i=887 -1 0 true Subparameters ns=1;i=3003 1 0 0 true i=38 ns=1;i=5005 i=38 ns=1;i=5007 i=38 ns=1;i=5006 DataType_64 ns=1;i=3011 1 ISA95PersonnelDataType Defines a personnel resource or a person, a quantity, an optional description, and an optional collection of properties. i=22 i=14798 i=22 StructureWithOptionalFields_1 ID An identification of a Personnel Class or Person. i=12 -1 0 false Description Additional information and description about the resource. i=21 1 0 0 true PersonnelUse Information about the expected use of the personnel, see the ISA 95 Part 2 standard for defined values. i=12 -1 0 true Quantity The quantity of the resource i=12878 -1 0 true EngineeringUnits The Unit Of Measure of the quantity i=887 -1 0 true Properties Any associated properties, or empty if there are no properties defined. ns=1;i=3002 1 0 0 true i=38 ns=1;i=5020 i=38 ns=1;i=5022 i=38 ns=1;i=5021 DataType_64 ns=1;i=3012 1 ISA95PhysicalAssetDataType Defines a physical asset, a quantity, an optional description, and an optional collection of properties. i=22 i=14798 i=22 StructureWithOptionalFields_1 ID An identification of a Physical Asset Class or Physical Asset. i=12 -1 0 false Description Additional information and description about the resource. i=21 1 0 0 true PhysicalAssetUse Information about the expected use of the physical asset, see the ISA 95 Part 2 standard for defined values. i=12 -1 0 true Quantity The quantity of the resource i=12878 -1 0 true EngineeringUnits The Unit Of Measure of the quantity i=887 -1 0 true Properties Any associated properties, or empty if there are no properties defined. ns=1;i=3002 1 0 0 true i=38 ns=1;i=5023 i=38 ns=1;i=5025 i=38 ns=1;i=5024 DataType_64 ns=1;i=3002 1 ISA95PropertyDataType A subtype of OPC UA Structure that defines two linked data items: an ID, which is a unique identifier for a property within the scope of the associated resource, and the value, which is the data for the property. i=22 i=14798 i=22 StructureWithOptionalFields_1 ID Unique identifier for a property within the scope of the associated resource i=12 -1 0 false Value Value for the property i=24 -1 0 false Description An optional description of the parameter. i=21 1 0 0 true EngineeringUnits The Unit Of Measure of the value i=887 -1 0 true Subproperties ns=1;i=3002 1 0 0 true i=38 ns=1;i=5002 i=38 ns=1;i=5004 i=38 ns=1;i=5003 DataType_64 ns=1;i=3006 1 ISA95StateDataType Defines the information needed to schedule and execute a job. i=22 i=14798 i=22 Structure_0 BrowsePath The browse path of substates. Shall be null when the top-level state is represented. i=540 -1 0 false StateText The state represented as human readable text. Shall represent the same text as the CurrentState Variable of a StateMachine would. i=21 -1 0 false StateNumber The state represented as number. Shall represent the same number as the Number subvariable of the CurrentState Variable of a StateMachine would. i=7 -1 0 false i=38 ns=1;i=5029 i=38 ns=1;i=5031 i=38 ns=1;i=5030 DataType_64 ns=1;i=3007 1 ISA95WorkMasterDataType Defines a Work Master ID and the defined parameters for the Work Master. i=22 i=14798 i=22 StructureWithOptionalFields_1 ID An identification of the Work Master. i=12 -1 0 false Description Additional information and description about the Work Master. i=21 -1 0 true Parameters Defined parameters for the Work Master. ns=1;i=3003 1 0 0 true i=38 ns=1;i=5011 i=38 ns=1;i=5013 i=38 ns=1;i=5012 ObjectType_8 ns=1;i=1006 1 ISA95JobOrderStatusEventType i=2041 true i=41 true ns=1;i=1003 i=54 true ns=1;i=5041 i=54 true ns=1;i=5042 i=54 true ns=1;i=5043 i=54 true ns=1;i=5044 i=54 true ns=1;i=5045 i=54 true ns=1;i=5046 i=54 true ns=1;i=5047 i=54 true ns=1;i=5048 i=54 true ns=1;i=5049 i=54 true ns=1;i=5050 i=54 true ns=1;i=5051 i=54 true ns=1;i=5069 i=54 true ns=1;i=5070 i=54 true ns=1;i=5071 i=54 true ns=1;i=5072 i=54 true ns=1;i=5073 i=54 true ns=1;i=5074 i=54 true ns=1;i=5075 i=54 true ns=1;i=5076 i=54 true ns=1;i=5077 i=54 true ns=1;i=5078 i=54 true ns=1;i=5079 i=54 true ns=1;i=5084 i=54 true ns=1;i=5085 i=54 true ns=1;i=5086 i=54 true ns=1;i=5087 Variable_2 ns=1;i=6047 1 JobOrder i=46 i=68 i=78 6047 ns=1;i=3008 -1 3 3 Variable_2 ns=1;i=6049 1 JobResponse i=46 i=68 i=78 6049 ns=1;i=3013 -1 3 3 Variable_2 ns=1;i=6048 1 JobState i=46 i=68 i=78 6048 ns=1;i=3006 1 0 3 3 ObjectType_8 ns=1;i=1003 1 ISA95JobResponseProviderObjectType The OPENSCSJobResponseProviderObjectType contains a method to receive unsolicited job response requests. i=58 i=41 ns=1;i=1006 Variable_2 ns=1;i=6050 1 JobOrderResponseList i=47 i=63 i=80 6050 ns=1;i=3013 1 0 3 3 Method_4 ns=1;i=7002 1 RequestJobResponseByJobOrderID i=47 ns=1;i=7002 i=78 7002 true true Variable_2 ns=1;i=6042 0 InputArguments i=46 i=68 i=78 6042 i=297 JobOrderID i=12 -1 Contains an ID of the job order, as specified by the method caller. i=296 1 1 1 1 Variable_2 ns=1;i=6043 0 OutputArguments i=46 i=68 i=78 6043 i=297 JobResponse ns=1;i=3013 -1 Contains information about the execution of a job order, such as the current status of the job, actual material consumed, actual material produced, actual equipment used, and job specific data. i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 2 1 1 Method_4 ns=1;i=7014 1 RequestJobResponseByJobOrderState i=47 ns=1;i=7014 i=78 7014 true true Variable_2 ns=1;i=6016 0 InputArguments i=46 i=68 i=78 6016 i=297 JobOrderState ns=1;i=3006 1 0 Contains a job status of the JobResponse to be returned. The array shall provide at least one entry representing the top level state and potentially additional entries representing substates. The first entry shall be the top level entry, having the BrowsePath set to null. The order of the substates is not defined. i=296 1 1 1 1 Variable_2 ns=1;i=6017 0 OutputArguments i=46 i=68 i=78 6017 i=297 JobResponses ns=1;i=3013 1 0 Contains a list of information about the execution of a job order, such as the current status of the job, actual material consumed, actual material produced, actual equipment used, and job specific data. i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 2 1 1 ObjectType_8 ns=1;i=1004 1 ISA95JobResponseReceiverObjectType A Job Response Receiver receives unsolicited Job Responses, usually as the result of completion of a job, or at intermediate points within the job. i=58 Method_4 ns=1;i=7003 1 ReceiveJobResponse i=47 ns=1;i=7003 i=78 7003 true true Variable_2 ns=1;i=6044 0 InputArguments i=46 i=68 i=78 6044 i=297 JobResponse ns=1;i=3013 -1 Contains information about the execution of a job order, such as actual material consumed, actual material produced, actual equipment used, and job specific data. i=296 1 1 1 1 Variable_2 ns=1;i=6045 0 OutputArguments i=46 i=68 i=78 6045 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 1 1 1 ObjectType_8 ns=1;i=1005 1 ISA95EndedStateMachineType i=2771 Object_1 ns=1;i=5057 1 Closed The job order has been completed and no further post processing is performed. i=47 i=2307 5057 i=52 true ns=1;i=5058 Variable_2 ns=1;i=6094 0 StateNumber i=46 i=68 i=78 6094 2 i=7 -1 1 1 Object_1 ns=1;i=5056 1 Completed The job order has been completed and is no longer in execution. i=47 i=2307 5056 i=51 true ns=1;i=5058 Variable_2 ns=1;i=6093 0 StateNumber i=46 i=68 i=78 6093 1 i=7 -1 1 1 Object_1 ns=1;i=5058 1 FromCompletedToClosed This transition is triggered when the system has finalized post processing of a ended job order. i=47 i=2310 5058 i=52 ns=1;i=5057 i=51 ns=1;i=5056 Variable_2 ns=1;i=6095 0 TransitionNumber i=46 i=68 i=78 6095 1 i=7 -1 1 1 ObjectType_8 ns=1;i=1007 1 ISA95InterruptedStateMachineType i=2771 Object_1 ns=1;i=5061 1 FromHeldToSuspended This transition is triggered when the system has switched the job order from internally held to externally suspended, for example by a call of the Pause Method. i=47 i=2310 5061 i=51 ns=1;i=5059 i=52 ns=1;i=5060 Variable_2 ns=1;i=6098 0 TransitionNumber i=46 i=68 i=78 6098 1 i=7 -1 1 1 Object_1 ns=1;i=5062 1 FromSuspendedToHeld This transition is triggered when the system has switched the job order from externally suspended to an internal held, for example by a call of the Resume Method. i=47 i=2310 5062 i=52 ns=1;i=5059 i=51 ns=1;i=5060 Variable_2 ns=1;i=6099 0 TransitionNumber i=46 i=68 i=78 6099 2 i=7 -1 1 1 Object_1 ns=1;i=5059 1 Held The job order has been temporarily stopped due to a constraint of some form. i=47 i=2307 5059 i=51 true ns=1;i=5061 i=52 true ns=1;i=5062 Variable_2 ns=1;i=6096 0 StateNumber i=46 i=68 i=78 6096 1 i=7 -1 1 1 Object_1 ns=1;i=5060 1 Suspended The job order has been temporarily stopped due to a deliberate decision within the execution system. i=47 i=2307 5060 i=52 true ns=1;i=5061 i=51 true ns=1;i=5062 Variable_2 ns=1;i=6097 0 StateNumber i=46 i=68 i=78 6097 2 i=7 -1 1 1 ObjectType_8 ns=1;i=1002 1 ISA95JobOrderReceiverObjectType The OPENSCSJobOrderReciverObjectType contains a method to receive job order commands and optional definitions of allowable job order information i=2771 Method_4 ns=1;i=7010 1 Abort i=47 ns=1;i=7010 i=80 7010 true true i=53 true ns=1;i=5048 i=53 true ns=1;i=5049 i=53 true ns=1;i=5076 i=53 true ns=1;i=5077 i=53 true ns=1;i=5084 i=53 true ns=1;i=5085 i=53 true ns=1;i=5086 i=53 true ns=1;i=5087 Variable_2 ns=1;i=6063 0 InputArguments i=46 i=68 i=78 6063 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. i=296 1 2 1 1 Variable_2 ns=1;i=6064 0 OutputArguments i=46 i=68 i=78 6064 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 1 1 1 Object_1 ns=1;i=5040 1 Aborted The job order is aborted. i=47 i=2307 5040 i=52 true ns=1;i=5048 i=52 true ns=1;i=5049 i=52 true ns=1;i=5084 i=52 true ns=1;i=5085 Variable_2 ns=1;i=6076 0 StateNumber i=46 i=68 i=78 6076 6 i=7 -1 1 1 Object_1 ns=1;i=5036 1 AllowedToStart The job order is stored and may be executed. i=47 i=2307 5036 i=52 true ns=1;i=5042 i=51 true ns=1;i=5043 i=52 true ns=1;i=5044 i=51 true ns=1;i=5044 i=51 true ns=1;i=5045 i=51 true ns=1;i=5085 Variable_2 ns=1;i=6072 0 StateNumber i=46 i=68 i=78 6072 2 i=7 -1 1 1 Method_4 ns=1;i=7011 1 Cancel i=47 ns=1;i=7011 i=80 7011 true true Variable_2 ns=1;i=6065 0 InputArguments i=46 i=68 i=78 6065 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. i=296 1 2 1 1 Variable_2 ns=1;i=6066 0 OutputArguments i=46 i=68 i=78 6066 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 1 1 1 Method_4 ns=1;i=7012 1 Clear i=47 ns=1;i=7012 i=80 7012 true true Variable_2 ns=1;i=6067 0 InputArguments i=46 i=68 i=78 6067 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. i=296 1 2 1 1 Variable_2 ns=1;i=6068 0 OutputArguments i=46 i=68 i=78 6068 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 1 1 1 Object_1 ns=1;i=5039 1 Ended The job order has been completed and is no longer in execution. i=47 i=2307 5039 i=52 true ns=1;i=5047 i=52 true ns=1;i=5051 Variable_2 ns=1;i=6075 0 StateNumber i=46 i=68 i=78 6075 5 i=7 -1 1 1 Variable_2 ns=1;i=6037 1 EquipmentID Defines a read-only set of Equipment Class IDs and Equipment IDs that may be specified in a job order. i=47 i=63 i=78 6037 i=12 1 0 1 1 Object_1 ns=1;i=5085 1 FromAllowedToStartToAborted This transition is triggered when Abort Method is called. i=47 i=2310 5085 i=53 ns=1;i=7010 i=52 ns=1;i=5040 i=51 ns=1;i=5036 i=54 ns=1;i=1006 Variable_2 ns=1;i=6010 0 TransitionNumber i=46 i=68 i=78 6010 13 i=7 -1 1 1 Object_1 ns=1;i=5044 1 FromAllowedToStartToAllowedToStart This transition is triggered when the Update Method is called and the job order is modified. i=47 i=2310 5044 i=52 ns=1;i=5036 i=51 ns=1;i=5036 i=54 ns=1;i=1006 i=53 ns=1;i=7009 Variable_2 ns=1;i=6080 0 TransitionNumber i=46 i=68 i=78 6080 4 i=7 -1 1 1 Object_1 ns=1;i=5043 1 FromAllowedToStartToNotAllowedToStart This transition is triggered when the RevokeStart Method is called. i=47 i=2310 5043 i=51 ns=1;i=5036 i=54 ns=1;i=1006 i=52 ns=1;i=5035 i=53 ns=1;i=7013 Variable_2 ns=1;i=6079 0 TransitionNumber i=46 i=68 i=78 6079 3 i=7 -1 1 1 Object_1 ns=1;i=5045 1 FromAllowedToStartToRunning This transition is triggered when a job order is started to be executed. i=47 i=2310 5045 i=51 ns=1;i=5036 i=54 ns=1;i=1006 i=52 ns=1;i=5037 Variable_2 ns=1;i=6081 0 TransitionNumber i=46 i=68 i=78 6081 5 i=7 -1 1 1 Object_1 ns=1;i=5049 1 FromInterruptedToAborted This transition is triggered when Abort Method is called. i=47 i=2310 5049 i=53 ns=1;i=7010 i=52 ns=1;i=5040 i=51 ns=1;i=5038 i=54 ns=1;i=1006 Variable_2 ns=1;i=6085 0 TransitionNumber i=46 i=68 i=78 6085 9 i=7 -1 1 1 Object_1 ns=1;i=5051 1 FromInterruptedToEnded This transition is triggered when Stop Method is called. i=47 i=2310 5051 i=52 ns=1;i=5039 i=51 ns=1;i=5038 i=54 ns=1;i=1006 i=53 ns=1;i=7006 Variable_2 ns=1;i=6087 0 TransitionNumber i=46 i=68 i=78 6087 11 i=7 -1 1 1 Object_1 ns=1;i=5050 1 FromInterruptedToRunning This transition is triggered when Resume Method is called. i=47 i=2310 5050 i=51 ns=1;i=5038 i=54 ns=1;i=1006 i=53 ns=1;i=7008 i=52 ns=1;i=5037 Variable_2 ns=1;i=6086 0 TransitionNumber i=46 i=68 i=78 6086 10 i=7 -1 1 1 Object_1 ns=1;i=5084 1 FromNotAllowedToStartToAborted This transition is triggered when Abort Method is called. i=47 i=2310 5084 i=53 ns=1;i=7010 i=52 ns=1;i=5040 i=54 ns=1;i=1006 i=51 ns=1;i=5035 Variable_2 ns=1;i=6009 0 TransitionNumber i=46 i=68 i=78 6009 12 i=7 -1 1 1 Object_1 ns=1;i=5042 1 FromNotAllowedToStartToAllowedToStart This transition is triggered when the Start Method is called. i=47 i=2310 5042 i=52 ns=1;i=5036 i=54 ns=1;i=1006 i=51 ns=1;i=5035 i=53 ns=1;i=7005 Variable_2 ns=1;i=6078 0 TransitionNumber i=46 i=68 i=78 6078 2 i=7 -1 1 1 Object_1 ns=1;i=5041 1 FromNotAllowedToStartToNotAllowedToStart This transition is triggered when the Update Method is called and the job order is modified. i=47 i=2310 5041 i=54 ns=1;i=1006 i=52 ns=1;i=5035 i=51 ns=1;i=5035 i=53 ns=1;i=7009 Variable_2 ns=1;i=6077 0 TransitionNumber i=46 i=68 i=78 6077 1 i=7 -1 1 1 Object_1 ns=1;i=5048 1 FromRunningToAborted This transition is triggered when Abort Method is called. i=47 i=2310 5048 i=53 ns=1;i=7010 i=52 ns=1;i=5040 i=54 ns=1;i=1006 i=51 ns=1;i=5037 Variable_2 ns=1;i=6084 0 TransitionNumber i=46 i=68 i=78 6084 8 i=7 -1 1 1 Object_1 ns=1;i=5047 1 FromRunningToEnded This transition is triggered when the execution of a job order has finished, either internally or by the Stop Method. i=47 i=2310 5047 i=52 ns=1;i=5039 i=54 ns=1;i=1006 i=51 ns=1;i=5037 i=53 ns=1;i=7006 Variable_2 ns=1;i=6083 0 TransitionNumber i=46 i=68 i=78 6083 7 i=7 -1 1 1 Object_1 ns=1;i=5046 1 FromRunningToInterrupted This transition is triggered when an executing job order gets interrupted, either internally or by the Pause Method. i=47 i=2310 5046 i=52 ns=1;i=5038 i=54 ns=1;i=1006 i=53 ns=1;i=7007 i=51 ns=1;i=5037 Variable_2 ns=1;i=6082 0 TransitionNumber i=46 i=68 i=78 6082 6 i=7 -1 1 1 Object_1 ns=1;i=5038 1 Interrupted The job order has been temporarily stopped. i=47 i=2307 5038 i=51 true ns=1;i=5049 i=51 true ns=1;i=5051 i=51 true ns=1;i=5050 i=52 true ns=1;i=5046 Variable_2 ns=1;i=6074 0 StateNumber i=46 i=68 i=78 6074 4 i=7 -1 1 1 Variable_2 ns=1;i=6033 1 JobOrderList Defines a read-only list of job order information available from the server. i=47 i=63 i=78 6033 ns=1;i=3015 1 0 1 1 Variable_2 ns=1;i=6035 1 MaterialClassID Defines a read-only set of Material Classes IDs that may be specified in a job order. i=47 i=63 i=78 6035 i=12 1 0 1 1 Variable_2 ns=1;i=6036 1 MaterialDefinitionID Defines a read-only set of Material Classes IDs that may be specified in a job order. i=47 i=63 i=78 6036 i=12 1 0 1 1 Variable_2 ns=1;i=6088 1 MaxDownloadableJobOrders i=46 i=68 i=78 6088 i=5 -1 1 1 Object_1 ns=1;i=5035 1 NotAllowedToStart The job order is stored but may not be executed. i=47 i=2307 5035 i=52 true ns=1;i=5043 i=51 true ns=1;i=5084 i=51 true ns=1;i=5042 i=52 true ns=1;i=5041 i=51 true ns=1;i=5041 Variable_2 ns=1;i=6071 0 StateNumber i=46 i=68 i=78 6071 1 i=7 -1 1 1 Method_4 ns=1;i=7007 1 Pause i=47 ns=1;i=7007 i=80 7007 true true i=53 true ns=1;i=5046 i=53 true ns=1;i=5074 Variable_2 ns=1;i=6057 0 InputArguments i=46 i=68 i=78 6057 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. i=296 1 2 1 1 Variable_2 ns=1;i=6058 0 OutputArguments i=46 i=68 i=78 6058 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 1 1 1 Variable_2 ns=1;i=6039 1 PersonnelID Defines a read-only set of Personnel IDs and Person IDs that may be specified in a job order. i=47 i=63 i=78 6039 i=12 1 0 1 1 Variable_2 ns=1;i=6038 1 PhysicalAssetID Defines a read-only set of Physical Asset Class IDs and Physical Asset IDs that may be specified in a job order. i=47 i=63 i=78 6038 i=12 1 0 1 1 Method_4 ns=1;i=7008 1 Resume i=47 ns=1;i=7008 i=80 7008 true true i=53 true ns=1;i=5050 i=53 true ns=1;i=5078 Variable_2 ns=1;i=6059 0 InputArguments i=46 i=68 i=78 6059 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. i=296 1 2 1 1 Variable_2 ns=1;i=6060 0 OutputArguments i=46 i=68 i=78 6060 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 1 1 1 Method_4 ns=1;i=7013 1 RevokeStart i=47 ns=1;i=7013 i=80 7013 true true i=53 true ns=1;i=5043 i=53 true ns=1;i=5071 Variable_2 ns=1;i=6069 0 InputArguments i=46 i=68 i=78 6069 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. i=296 1 2 1 1 Variable_2 ns=1;i=6070 0 OutputArguments i=46 i=68 i=78 6070 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 1 1 1 Object_1 ns=1;i=5037 1 Running The job order is executing. i=47 i=2307 5037 i=52 true ns=1;i=5045 i=52 true ns=1;i=5050 i=51 true ns=1;i=5048 i=51 true ns=1;i=5047 i=51 true ns=1;i=5046 Variable_2 ns=1;i=6073 0 StateNumber i=46 i=68 i=78 6073 3 i=7 -1 1 1 Method_4 ns=1;i=7005 1 Start i=47 ns=1;i=7005 i=80 7005 true true i=53 true ns=1;i=5042 i=53 true ns=1;i=5070 Variable_2 ns=1;i=6053 0 InputArguments i=46 i=68 i=78 6053 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. i=296 1 2 1 1 Variable_2 ns=1;i=6054 0 OutputArguments i=46 i=68 i=78 6054 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 1 1 1 Method_4 ns=1;i=7006 1 Stop i=47 ns=1;i=7006 i=80 7006 true true i=53 true ns=1;i=5051 i=53 true ns=1;i=5047 i=53 true ns=1;i=5075 i=53 true ns=1;i=5079 Variable_2 ns=1;i=6055 0 InputArguments i=46 i=68 i=78 6055 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. i=296 1 2 1 1 Variable_2 ns=1;i=6056 0 OutputArguments i=46 i=68 i=78 6056 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 1 1 1 Method_4 ns=1;i=7001 1 Store i=47 ns=1;i=7001 i=80 7001 true true Variable_2 ns=1;i=6040 0 InputArguments i=46 i=68 i=78 6040 i=297 JobOrder ns=1;i=3008 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. i=296 1 2 1 1 Variable_2 ns=1;i=6041 0 OutputArguments i=46 i=68 i=78 6041 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 1 1 1 Method_4 ns=1;i=7004 1 StoreAndStart i=47 ns=1;i=7004 i=80 7004 true true Variable_2 ns=1;i=6051 0 InputArguments i=46 i=68 i=78 6051 i=297 JobOrder ns=1;i=3008 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. i=296 1 2 1 1 Variable_2 ns=1;i=6052 0 OutputArguments i=46 i=68 i=78 6052 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 1 1 1 Method_4 ns=1;i=7009 1 Update i=47 ns=1;i=7009 i=80 7009 true true i=53 true ns=1;i=5044 i=53 true ns=1;i=5041 i=53 true ns=1;i=5069 i=53 true ns=1;i=5072 Variable_2 ns=1;i=6061 0 InputArguments i=46 i=68 i=78 6061 i=297 JobOrder ns=1;i=3008 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. i=296 1 2 1 1 Variable_2 ns=1;i=6062 0 OutputArguments i=46 i=68 i=78 6062 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. i=296 1 1 1 1 Variable_2 ns=1;i=6034 1 WorkMaster Defines a read-only set of work master IDs that may be specified in a job order, and the read-only set of parameters that may be specified for a specific work master. i=47 i=63 i=78 6034 ns=1;i=3007 1 0 1 1 ObjectType_8 ns=1;i=1008 1 ISA95JobOrderReceiverSubStatesType ns=1;i=1002 Object_1 ns=1;i=5068 1 Aborted The job order is aborted. i=47 i=2307 5068 i=52 true ns=1;i=5076 i=52 true ns=1;i=5077 i=52 true ns=1;i=5087 i=52 true ns=1;i=5086 Variable_2 ns=1;i=6105 0 StateNumber i=46 i=68 i=78 6105 6 i=7 -1 1 1 Object_1 ns=1;i=5064 1 AllowedToStart The job order is stored and may be executed. i=47 i=2307 5064 i=52 true ns=1;i=5070 i=51 true ns=1;i=5071 i=52 true ns=1;i=5072 i=51 true ns=1;i=5072 i=51 true ns=1;i=5073 i=51 true ns=1;i=5086 i=117 ns=1;i=5081 Variable_2 ns=1;i=6101 0 StateNumber i=46 i=68 i=78 6101 2 i=7 -1 1 1 Object_1 ns=1;i=5067 1 Ended The job order has been completed and is no longer in execution. i=47 i=2307 5067 i=52 true ns=1;i=5075 i=52 true ns=1;i=5079 i=117 ns=1;i=5082 Variable_2 ns=1;i=6104 0 StateNumber i=46 i=68 i=78 6104 5 i=7 -1 1 1 Object_1 ns=1;i=5086 1 FromAllowedToStartToAborted This transition is triggered when Abort Method is called. i=47 i=2310 5086 i=52 ns=1;i=5068 i=51 ns=1;i=5064 i=54 ns=1;i=1006 i=53 ns=1;i=7010 Variable_2 ns=1;i=6011 0 TransitionNumber i=46 i=68 i=78 6011 13 i=7 -1 1 1 Object_1 ns=1;i=5072 1 FromAllowedToStartToAllowedToStart This transition is triggered when the Update Method is called and the job order is modified. i=47 i=2310 5072 i=52 ns=1;i=5064 i=51 ns=1;i=5064 i=54 ns=1;i=1006 i=53 ns=1;i=7009 Variable_2 ns=1;i=6109 0 TransitionNumber i=46 i=68 i=78 6109 4 i=7 -1 1 1 Object_1 ns=1;i=5071 1 FromAllowedToStartToNotAllowedToStart This transition is triggered when the RevokeStart Method is called. i=47 i=2310 5071 i=51 ns=1;i=5064 i=54 ns=1;i=1006 i=52 ns=1;i=5063 i=53 ns=1;i=7013 Variable_2 ns=1;i=6108 0 TransitionNumber i=46 i=68 i=78 6108 3 i=7 -1 1 1 Object_1 ns=1;i=5073 1 FromAllowedToStartToRunning This transition is triggered when a job order is started to be executed. i=47 i=2310 5073 i=51 ns=1;i=5064 i=54 ns=1;i=1006 i=52 ns=1;i=5065 Variable_2 ns=1;i=6110 0 TransitionNumber i=46 i=68 i=78 6110 5 i=7 -1 1 1 Object_1 ns=1;i=5077 1 FromInterruptedToAborted This transition is triggered when Abort Method is called. i=47 i=2310 5077 i=52 ns=1;i=5068 i=51 ns=1;i=5066 i=54 ns=1;i=1006 i=53 ns=1;i=7010 Variable_2 ns=1;i=6114 0 TransitionNumber i=46 i=68 i=78 6114 9 i=7 -1 1 1 Object_1 ns=1;i=5079 1 FromInterruptedToEnded This transition is triggered when Stop Method is called. i=47 i=2310 5079 i=52 ns=1;i=5067 i=51 ns=1;i=5066 i=54 ns=1;i=1006 i=53 ns=1;i=7006 Variable_2 ns=1;i=6116 0 TransitionNumber i=46 i=68 i=78 6116 11 i=7 -1 1 1 Object_1 ns=1;i=5078 1 FromInterruptedToRunning This transition is triggered when Resume Method is called. i=47 i=2310 5078 i=51 ns=1;i=5066 i=54 ns=1;i=1006 i=52 ns=1;i=5065 i=53 ns=1;i=7008 Variable_2 ns=1;i=6115 0 TransitionNumber i=46 i=68 i=78 6115 10 i=7 -1 1 1 Object_1 ns=1;i=5087 1 FromNotAllowedToStartToAborted This transition is triggered when Abort Method is called. i=47 i=2310 5087 i=52 ns=1;i=5068 i=54 ns=1;i=1006 i=51 ns=1;i=5063 i=53 ns=1;i=7010 Variable_2 ns=1;i=6012 0 TransitionNumber i=46 i=68 i=78 6012 12 i=7 -1 1 1 Object_1 ns=1;i=5070 1 FromNotAllowedToStartToAllowedToStart This transition is triggered when the Start Method is called. i=47 i=2310 5070 i=52 ns=1;i=5064 i=54 ns=1;i=1006 i=51 ns=1;i=5063 i=53 ns=1;i=7005 Variable_2 ns=1;i=6107 0 TransitionNumber i=46 i=68 i=78 6107 2 i=7 -1 1 1 Object_1 ns=1;i=5069 1 FromNotAllowedToStartToNotAllowedToStart This transition is triggered when the Update Method is called and the job order is modified. i=47 i=2310 5069 i=54 ns=1;i=1006 i=52 ns=1;i=5063 i=51 ns=1;i=5063 i=53 ns=1;i=7009 Variable_2 ns=1;i=6106 0 TransitionNumber i=46 i=68 i=78 6106 1 i=7 -1 1 1 Object_1 ns=1;i=5076 1 FromRunningToAborted This transition is triggered when Abort Method is called. i=47 i=2310 5076 i=52 ns=1;i=5068 i=54 ns=1;i=1006 i=51 ns=1;i=5065 i=53 ns=1;i=7010 Variable_2 ns=1;i=6113 0 TransitionNumber i=46 i=68 i=78 6113 8 i=7 -1 1 1 Object_1 ns=1;i=5075 1 FromRunningToEnded This transition is triggered when the execution of a job order has finished, either internally or by the Stop Method. i=47 i=2310 5075 i=52 ns=1;i=5067 i=54 ns=1;i=1006 i=51 ns=1;i=5065 i=53 ns=1;i=7006 Variable_2 ns=1;i=6112 0 TransitionNumber i=46 i=68 i=78 6112 7 i=7 -1 1 1 Object_1 ns=1;i=5074 1 FromRunningToInterrupted This transition is triggered when an executing job order gets interrupted, either internally or by the Pause Method. i=47 i=2310 5074 i=52 ns=1;i=5066 i=54 ns=1;i=1006 i=51 ns=1;i=5065 i=53 ns=1;i=7007 Variable_2 ns=1;i=6111 0 TransitionNumber i=46 i=68 i=78 6111 6 i=7 -1 1 1 Object_1 ns=1;i=5066 1 Interrupted The job order has been temporarily stopped. i=47 i=2307 5066 i=51 true ns=1;i=5077 i=51 true ns=1;i=5079 i=51 true ns=1;i=5078 i=52 true ns=1;i=5074 i=117 ns=1;i=5083 Variable_2 ns=1;i=6103 0 StateNumber i=46 i=68 i=78 6103 4 i=7 -1 1 1 Object_1 ns=1;i=5063 1 NotAllowedToStart The job order is stored but may not be executed. i=47 i=2307 5063 i=52 true ns=1;i=5071 i=51 true ns=1;i=5087 i=51 true ns=1;i=5070 i=52 true ns=1;i=5069 i=51 true ns=1;i=5069 i=117 ns=1;i=5080 Variable_2 ns=1;i=6100 0 StateNumber i=46 i=68 i=78 6100 1 i=7 -1 1 1 Object_1 ns=1;i=5065 1 Running The job order is executing. i=47 i=2307 5065 i=52 true ns=1;i=5073 i=52 true ns=1;i=5078 i=51 true ns=1;i=5076 i=51 true ns=1;i=5075 i=51 true ns=1;i=5074 Variable_2 ns=1;i=6102 0 StateNumber i=46 i=68 i=78 6102 3 i=7 -1 1 1 Object_1 ns=1;i=5081 1 AllowedToStartSubstates Substates of AllowedToStart i=47 ns=1;i=1001 i=80 5081 i=117 true ns=1;i=5064 Variable_2 ns=1;i=6003 0 CurrentState i=47 i=2760 i=78 6003 i=21 -1 1 1 Variable_2 ns=1;i=6004 0 Id i=46 i=68 i=78 6004 i=17 -1 1 1 Object_1 ns=1;i=5082 1 EndedSubstates Substates of Ended i=47 ns=1;i=1005 i=80 5082 i=117 true ns=1;i=5067 Variable_2 ns=1;i=6005 0 CurrentState i=47 i=2760 i=78 6005 i=21 -1 1 1 Variable_2 ns=1;i=6006 0 Id i=46 i=68 i=78 6006 i=17 -1 1 1 Object_1 ns=1;i=5083 1 InterruptedSubstates Substates of Interrupted i=47 ns=1;i=1007 i=80 5083 i=117 true ns=1;i=5066 Variable_2 ns=1;i=6007 0 CurrentState i=47 i=2760 i=78 6007 i=21 -1 1 1 Variable_2 ns=1;i=6008 0 Id i=46 i=68 i=78 6008 i=17 -1 1 1 Object_1 ns=1;i=5080 1 NotAllowedToStartSubstates Substates of NotAllowedToStart i=47 ns=1;i=1001 i=80 5080 i=117 true ns=1;i=5063 Variable_2 ns=1;i=6001 0 CurrentState i=47 i=2760 i=78 6001 i=21 -1 1 1 Variable_2 ns=1;i=6002 0 Id i=46 i=68 i=78 6002 i=17 -1 1 1 ObjectType_8 ns=1;i=1001 1 ISA95PrepareStateMachineType i=2771 Object_1 ns=1;i=5089 1 FromLoadedToReady This transition is triggered when the program or configuration to execute the job order is unloaded. i=47 i=2310 5089 i=51 ns=1;i=5053 i=52 ns=1;i=5052 Variable_2 ns=1;i=6014 0 TransitionNumber i=46 i=68 i=78 6014 4 i=7 -1 1 1 Object_1 ns=1;i=5090 1 FromLoadedToWaiting This transition is triggered when the system is not ready to start the execution of the job order anymore. i=47 i=2310 5090 i=51 ns=1;i=5053 i=52 ns=1;i=5000 Variable_2 ns=1;i=6015 0 TransitionNumber i=46 i=68 i=78 6015 5 i=7 -1 1 1 Object_1 ns=1;i=5055 1 FromReadyToLoaded This transition is triggered when the program or configuration to execute the job order is loaded. i=47 i=2310 5055 i=52 ns=1;i=5053 i=51 ns=1;i=5052 Variable_2 ns=1;i=6092 0 TransitionNumber i=46 i=68 i=78 6092 2 i=7 -1 1 1 Object_1 ns=1;i=5088 1 FromReadyToWaiting This transition is triggered when the system is not ready to start the execution of the job order anymore. i=47 i=2310 5088 i=51 ns=1;i=5052 i=52 ns=1;i=5000 Variable_2 ns=1;i=6013 0 TransitionNumber i=46 i=68 i=78 6013 3 i=7 -1 1 1 Object_1 ns=1;i=5054 1 FromWaitingToReady This transition is triggered when the system is ready to start the execution of the job order. i=47 i=2310 5054 i=52 ns=1;i=5052 i=51 ns=1;i=5000 Variable_2 ns=1;i=6091 0 TransitionNumber i=46 i=68 i=78 6091 1 i=7 -1 1 1 Object_1 ns=1;i=5053 1 Loaded In situations where only one job may be in active memory and is able to be run, then the job is loaded in active memory, the necessary pre-conditions have been met, and the job order is ready to run, awaiting a Start command. i=47 i=2307 5053 i=51 true ns=1;i=5089 i=51 true ns=1;i=5090 i=52 true ns=1;i=5055 Variable_2 ns=1;i=6090 0 StateNumber i=46 i=68 i=78 6090 3 i=7 -1 1 1 Object_1 ns=1;i=5052 1 Ready The necessary pre-conditions have been met and the job order is ready to run, awaiting a Start command. i=47 i=2307 5052 i=52 true ns=1;i=5089 i=51 true ns=1;i=5055 i=51 true ns=1;i=5088 i=52 true ns=1;i=5054 Variable_2 ns=1;i=6089 0 StateNumber i=46 i=68 i=78 6089 2 i=7 -1 1 1 Object_1 ns=1;i=5000 1 Waiting The necessary pre-conditions have not been met and the job order is not ready to run. i=47 i=2307 5000 i=52 true ns=1;i=5090 i=52 true ns=1;i=5088 i=51 true ns=1;i=5054 Variable_2 ns=1;i=6000 0 StateNumber i=46 i=68 i=78 6000 1 i=7 -1 1 1 Object_1 ns=1;i=5001 1 http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/ i=11616 5001 i=47 true i=11715 Variable_2 ns=1;i=6025 0 NamespaceUri i=46 i=68 6025 http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/ i=12 -1 1 1 Variable_2 ns=1;i=6026 0 NamespaceVersion i=46 i=68 6026 2.0.0 i=12 -1 1 1 Variable_2 ns=1;i=6024 0 NamespacePublicationDate i=46 i=68 6024 2024-01-31T00:00:00Z i=13 -1 1 1 Variable_2 ns=1;i=6023 0 IsNamespaceSubset i=46 i=68 6023 false i=1 -1 1 1 Variable_2 ns=1;i=6027 0 StaticNodeIdTypes i=46 i=68 6027 0 i=256 1 0 1 1 Variable_2 ns=1;i=6028 0 StaticNumericNodeIdRange i=46 i=68 6028 1:2147483647 i=291 1 0 1 1 Variable_2 ns=1;i=6029 0 StaticStringNodeIdPattern i=46 i=68 6029 0 i=12 -1 1 1 Object_1 ns=1;i=5002 0 Default Binary i=76 5002 i=38 true ns=1;i=3002 i=39 ns=1;i=6128 Object_1 ns=1;i=5003 0 Default XML i=76 5003 i=38 true ns=1;i=3002 i=39 ns=1;i=6129 Object_1 ns=1;i=5004 0 Default JSON i=76 5004 i=38 true ns=1;i=3002 Object_1 ns=1;i=5005 0 Default Binary i=76 5005 i=38 true ns=1;i=3003 i=39 ns=1;i=6122 Object_1 ns=1;i=5006 0 Default XML i=76 5006 i=38 true ns=1;i=3003 i=39 ns=1;i=6123 Object_1 ns=1;i=5007 0 Default JSON i=76 5007 i=38 true ns=1;i=3003 Object_1 ns=1;i=5008 0 Default Binary i=76 5008 i=38 true ns=1;i=3005 i=39 ns=1;i=6022 Object_1 ns=1;i=5009 0 Default XML i=76 5009 i=38 true ns=1;i=3005 i=39 ns=1;i=6030 Object_1 ns=1;i=5010 0 Default JSON i=76 5010 i=38 true ns=1;i=3005 Object_1 ns=1;i=5011 0 Default Binary i=76 5011 i=38 true ns=1;i=3007 i=39 ns=1;i=6132 Object_1 ns=1;i=5012 0 Default XML i=76 5012 i=38 true ns=1;i=3007 i=39 ns=1;i=6133 Object_1 ns=1;i=5013 0 Default JSON i=76 5013 i=38 true ns=1;i=3007 Object_1 ns=1;i=5014 0 Default Binary i=76 5014 i=38 true ns=1;i=3008 i=39 ns=1;i=6046 Object_1 ns=1;i=5015 0 Default XML i=76 5015 i=38 true ns=1;i=3008 i=39 ns=1;i=6117 Object_1 ns=1;i=5016 0 Default JSON i=76 5016 i=38 true ns=1;i=3008 Object_1 ns=1;i=5017 0 Default Binary i=76 5017 i=38 true ns=1;i=3010 i=39 ns=1;i=6120 Object_1 ns=1;i=5018 0 Default XML i=76 5018 i=38 true ns=1;i=3010 i=39 ns=1;i=6121 Object_1 ns=1;i=5019 0 Default JSON i=76 5019 i=38 true ns=1;i=3010 Object_1 ns=1;i=5020 0 Default Binary i=76 5020 i=38 true ns=1;i=3011 i=39 ns=1;i=6124 Object_1 ns=1;i=5021 0 Default XML i=76 5021 i=38 true ns=1;i=3011 i=39 ns=1;i=6125 Object_1 ns=1;i=5022 0 Default JSON i=76 5022 i=38 true ns=1;i=3011 Object_1 ns=1;i=5023 0 Default Binary i=76 5023 i=38 true ns=1;i=3012 i=39 ns=1;i=6126 Object_1 ns=1;i=5024 0 Default XML i=76 5024 i=38 true ns=1;i=3012 i=39 ns=1;i=6127 Object_1 ns=1;i=5025 0 Default JSON i=76 5025 i=38 true ns=1;i=3012 Object_1 ns=1;i=5026 0 Default Binary i=76 5026 i=38 true ns=1;i=3013 i=39 ns=1;i=6118 Object_1 ns=1;i=5027 0 Default XML i=76 5027 i=38 true ns=1;i=3013 i=39 ns=1;i=6119 Object_1 ns=1;i=5028 0 Default JSON i=76 5028 i=38 true ns=1;i=3013 Object_1 ns=1;i=5029 0 Default Binary i=76 5029 i=38 true ns=1;i=3006 i=39 ns=1;i=6130 Object_1 ns=1;i=5030 0 Default XML i=76 5030 i=38 true ns=1;i=3006 i=39 ns=1;i=6131 Object_1 ns=1;i=5031 0 Default JSON i=76 5031 i=38 true ns=1;i=3006 Object_1 ns=1;i=5032 0 Default Binary i=76 5032 i=38 true ns=1;i=3015 i=39 ns=1;i=6031 Object_1 ns=1;i=5033 0 Default XML i=76 5033 i=38 true ns=1;i=3015 i=39 ns=1;i=6032 Object_1 ns=1;i=5034 0 Default JSON i=76 5034 i=38 true ns=1;i=3015 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Isa95Jobs/Design/UAModel.ISA95_JOBCONTROL_V2.Types.bsd ================================================ Defines an equipment resource or a piece of equipment, a quantity, an optional description, and an optional collection of properties. Defines the information needed to schedule and execute a job. Defines the information needed to schedule and execute a job. Defines the information needed to schedule and execute a job. Defines a material resource, a quantity, an optional description, and an optional collection of properties. A subtype of OPC UA Structure that defines three linked data items: the ID, which is a unique identifier for a property, the value, which is the data that is identified, and an optional description of the parameter. Defines a personnel resource or a person, a quantity, an optional description, and an optional collection of properties. Defines a physical asset, a quantity, an optional description, and an optional collection of properties. A subtype of OPC UA Structure that defines two linked data items: an ID, which is a unique identifier for a property within the scope of the associated resource, and the value, which is the data for the property. Defines the information needed to schedule and execute a job. Defines a Work Master ID and the defined parameters for the Work Master. ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Isa95Jobs/Design/UAModel.ISA95_JOBCONTROL_V2.Types.xsd ================================================ Defines an equipment resource or a piece of equipment, a quantity, an optional description, and an optional collection of properties. Defines the information needed to schedule and execute a job. Defines the information needed to schedule and execute a job. Defines the information needed to schedule and execute a job. Defines a material resource, a quantity, an optional description, and an optional collection of properties. A subtype of OPC UA Structure that defines three linked data items: the ID, which is a unique identifier for a property, the value, which is the data that is identified, and an optional description of the parameter. Defines a personnel resource or a person, a quantity, an optional description, and an optional collection of properties. Defines a physical asset, a quantity, an optional description, and an optional collection of properties. A subtype of OPC UA Structure that defines two linked data items: an ID, which is a unique identifier for a property within the scope of the associated resource, and the value, which is the data for the property. Defines the information needed to schedule and execute a job. Defines a Work Master ID and the defined parameters for the Work Master. ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Isa95Jobs/Nodesets/opc.ua.isa95-jobcontrol.nodeids.csv ================================================ ISA95PrepareStateMachineType,1001,ObjectType ISA95JobOrderReceiverObjectType,1002,ObjectType ISA95JobResponseProviderObjectType,1003,ObjectType ISA95JobResponseReceiverObjectType,1004,ObjectType ISA95EndedStateMachineType,1005,ObjectType ISA95JobOrderStatusEventType,1006,ObjectType ISA95InterruptedStateMachineType,1007,ObjectType ISA95JobOrderReceiverSubStatesType,1008,ObjectType ISA95PropertyDataType,3002,DataType ISA95ParameterDataType,3003,DataType ISA95EquipmentDataType,3005,DataType ISA95StateDataType,3006,DataType ISA95WorkMasterDataType,3007,DataType ISA95JobOrderDataType,3008,DataType ISA95MaterialDataType,3010,DataType ISA95PersonnelDataType,3011,DataType ISA95PhysicalAssetDataType,3012,DataType ISA95JobResponseDataType,3013,DataType ISA95JobOrderAndStateDataType,3015,DataType ISA95PrepareStateMachineType_Waiting,5000,Object Server_Namespaces_http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2_,5001,Object ISA95PropertyDataType_Encoding_DefaultBinary,5002,Object ISA95PropertyDataType_Encoding_DefaultXml,5003,Object ISA95PropertyDataType_Encoding_DefaultJson,5004,Object ISA95ParameterDataType_Encoding_DefaultBinary,5005,Object ISA95ParameterDataType_Encoding_DefaultXml,5006,Object ISA95ParameterDataType_Encoding_DefaultJson,5007,Object ISA95EquipmentDataType_Encoding_DefaultBinary,5008,Object ISA95EquipmentDataType_Encoding_DefaultXml,5009,Object ISA95EquipmentDataType_Encoding_DefaultJson,5010,Object ISA95WorkMasterDataType_Encoding_DefaultBinary,5011,Object ISA95WorkMasterDataType_Encoding_DefaultXml,5012,Object ISA95WorkMasterDataType_Encoding_DefaultJson,5013,Object ISA95JobOrderDataType_Encoding_DefaultBinary,5014,Object ISA95JobOrderDataType_Encoding_DefaultXml,5015,Object ISA95JobOrderDataType_Encoding_DefaultJson,5016,Object ISA95MaterialDataType_Encoding_DefaultBinary,5017,Object ISA95MaterialDataType_Encoding_DefaultXml,5018,Object ISA95MaterialDataType_Encoding_DefaultJson,5019,Object ISA95PersonnelDataType_Encoding_DefaultBinary,5020,Object ISA95PersonnelDataType_Encoding_DefaultXml,5021,Object ISA95PersonnelDataType_Encoding_DefaultJson,5022,Object ISA95PhysicalAssetDataType_Encoding_DefaultBinary,5023,Object ISA95PhysicalAssetDataType_Encoding_DefaultXml,5024,Object ISA95PhysicalAssetDataType_Encoding_DefaultJson,5025,Object ISA95JobResponseDataType_Encoding_DefaultBinary,5026,Object ISA95JobResponseDataType_Encoding_DefaultXml,5027,Object ISA95JobResponseDataType_Encoding_DefaultJson,5028,Object ISA95StateDataType_Encoding_DefaultBinary,5029,Object ISA95StateDataType_Encoding_DefaultXml,5030,Object ISA95StateDataType_Encoding_DefaultJson,5031,Object ISA95JobOrderAndStateDataType_Encoding_DefaultBinary,5032,Object ISA95JobOrderAndStateDataType_Encoding_DefaultXml,5033,Object ISA95JobOrderAndStateDataType_Encoding_DefaultJson,5034,Object ISA95JobOrderReceiverObjectType_NotAllowedToStart,5035,Object ISA95JobOrderReceiverObjectType_AllowedToStart,5036,Object ISA95JobOrderReceiverObjectType_Running,5037,Object ISA95JobOrderReceiverObjectType_Interrupted,5038,Object ISA95JobOrderReceiverObjectType_Ended,5039,Object ISA95JobOrderReceiverObjectType_Aborted,5040,Object ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToNotAllowedToStart,5041,Object ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToAllowedToStart,5042,Object ISA95JobOrderReceiverObjectType_FromAllowedToStartToNotAllowedToStart,5043,Object ISA95JobOrderReceiverObjectType_FromAllowedToStartToAllowedToStart,5044,Object ISA95JobOrderReceiverObjectType_FromAllowedToStartToRunning,5045,Object ISA95JobOrderReceiverObjectType_FromRunningToInterrupted,5046,Object ISA95JobOrderReceiverObjectType_FromRunningToEnded,5047,Object ISA95JobOrderReceiverObjectType_FromRunningToAborted,5048,Object ISA95JobOrderReceiverObjectType_FromInterruptedToAborted,5049,Object ISA95JobOrderReceiverObjectType_FromInterruptedToRunning,5050,Object ISA95JobOrderReceiverObjectType_FromInterruptedToEnded,5051,Object ISA95PrepareStateMachineType_Ready,5052,Object ISA95PrepareStateMachineType_Loaded,5053,Object ISA95PrepareStateMachineType_FromWaitingToReady,5054,Object ISA95PrepareStateMachineType_FromReadyToLoaded,5055,Object ISA95EndedStateMachineType_Completed,5056,Object ISA95EndedStateMachineType_Closed,5057,Object ISA95EndedStateMachineType_FromCompletedToClosed,5058,Object ISA95InterruptedStateMachineType_Held,5059,Object ISA95InterruptedStateMachineType_Suspended,5060,Object ISA95InterruptedStateMachineType_FromHeldToSuspended,5061,Object ISA95InterruptedStateMachineType_FromSuspendedToHeld,5062,Object ISA95JobOrderReceiverSubStatesType_NotAllowedToStart,5063,Object ISA95JobOrderReceiverSubStatesType_AllowedToStart,5064,Object ISA95JobOrderReceiverSubStatesType_Running,5065,Object ISA95JobOrderReceiverSubStatesType_Interrupted,5066,Object ISA95JobOrderReceiverSubStatesType_Ended,5067,Object ISA95JobOrderReceiverSubStatesType_Aborted,5068,Object ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToNotAllowedToStart,5069,Object ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToAllowedToStart,5070,Object ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToNotAllowedToStart,5071,Object ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToAllowedToStart,5072,Object ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToRunning,5073,Object ISA95JobOrderReceiverSubStatesType_FromRunningToInterrupted,5074,Object ISA95JobOrderReceiverSubStatesType_FromRunningToEnded,5075,Object ISA95JobOrderReceiverSubStatesType_FromRunningToAborted,5076,Object ISA95JobOrderReceiverSubStatesType_FromInterruptedToAborted,5077,Object ISA95JobOrderReceiverSubStatesType_FromInterruptedToRunning,5078,Object ISA95JobOrderReceiverSubStatesType_FromInterruptedToEnded,5079,Object ISA95JobOrderReceiverSubStatesType_NotAllowedToStartSubstates,5080,Object ISA95JobOrderReceiverSubStatesType_AllowedToStartSubstates,5081,Object ISA95JobOrderReceiverSubStatesType_EndedSubstates,5082,Object ISA95JobOrderReceiverSubStatesType_InterruptedSubstates,5083,Object ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToAborted,5084,Object ISA95JobOrderReceiverObjectType_FromAllowedToStartToAborted,5085,Object ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToAborted,5086,Object ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToAborted,5087,Object ISA95PrepareStateMachineType_FromReadyToWaiting,5088,Object ISA95PrepareStateMachineType_FromLoadedToReady,5089,Object ISA95PrepareStateMachineType_FromLoadedToWaiting,5090,Object ISA95PrepareStateMachineType_Waiting_StateNumber,6000,Variable ISA95JobOrderReceiverSubStatesType_NotAllowedToStartSubstates_CurrentState,6001,Variable ISA95JobOrderReceiverSubStatesType_NotAllowedToStartSubstates_CurrentState_Id,6002,Variable ISA95JobOrderReceiverSubStatesType_AllowedToStartSubstates_CurrentState,6003,Variable ISA95JobOrderReceiverSubStatesType_AllowedToStartSubstates_CurrentState_Id,6004,Variable ISA95JobOrderReceiverSubStatesType_EndedSubstates_CurrentState,6005,Variable ISA95JobOrderReceiverSubStatesType_EndedSubstates_CurrentState_Id,6006,Variable ISA95JobOrderReceiverSubStatesType_InterruptedSubstates_CurrentState,6007,Variable ISA95JobOrderReceiverSubStatesType_InterruptedSubstates_CurrentState_Id,6008,Variable ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToAborted_TransitionNumber,6009,Variable ISA95JobOrderReceiverObjectType_FromAllowedToStartToAborted_TransitionNumber,6010,Variable ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToAborted_TransitionNumber,6011,Variable ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToAborted_TransitionNumber,6012,Variable ISA95PrepareStateMachineType_FromReadyToWaiting_TransitionNumber,6013,Variable ISA95PrepareStateMachineType_FromLoadedToReady_TransitionNumber,6014,Variable ISA95PrepareStateMachineType_FromLoadedToWaiting_TransitionNumber,6015,Variable ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderState_InputArguments,6016,Variable ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderState_OutputArguments,6017,Variable TypeDictionary_BinarySchema,6018,Variable TypeDictionary_BinarySchema_NamespaceUri,6019,Variable TypeDictionary_XmlSchema,6020,Variable TypeDictionary_XmlSchema_NamespaceUri,6021,Variable TypeDictionary_BinarySchema_ISA95EquipmentDataType,6022,Variable Server_Namespaces_http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__IsNamespaceSubset,6023,Variable Server_Namespaces_http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__NamespacePublicationDate,6024,Variable Server_Namespaces_http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__NamespaceUri,6025,Variable Server_Namespaces_http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__NamespaceVersion,6026,Variable Server_Namespaces_http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__StaticNodeIdTypes,6027,Variable Server_Namespaces_http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__StaticNumericNodeIdRange,6028,Variable Server_Namespaces_http___opcfoundation_org_UA_ISA95_JOBCONTROL_V2__StaticStringNodeIdPattern,6029,Variable TypeDictionary_XmlSchema_ISA95EquipmentDataType,6030,Variable TypeDictionary_BinarySchema_ISA95JobOrderAndStateDataType,6031,Variable TypeDictionary_XmlSchema_ISA95JobOrderAndStateDataType,6032,Variable ISA95JobOrderReceiverObjectType_JobOrderList,6033,Variable ISA95JobOrderReceiverObjectType_WorkMaster,6034,Variable ISA95JobOrderReceiverObjectType_MaterialClassID,6035,Variable ISA95JobOrderReceiverObjectType_MaterialDefinitionID,6036,Variable ISA95JobOrderReceiverObjectType_EquipmentID,6037,Variable ISA95JobOrderReceiverObjectType_PhysicalAssetID,6038,Variable ISA95JobOrderReceiverObjectType_PersonnelID,6039,Variable ISA95JobOrderReceiverObjectType_Store_InputArguments,6040,Variable ISA95JobOrderReceiverObjectType_Store_OutputArguments,6041,Variable ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderID_InputArguments,6042,Variable ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderID_OutputArguments,6043,Variable ISA95JobResponseReceiverObjectType_ReceiveJobResponse_InputArguments,6044,Variable ISA95JobResponseReceiverObjectType_ReceiveJobResponse_OutputArguments,6045,Variable TypeDictionary_BinarySchema_ISA95JobOrderDataType,6046,Variable ISA95JobOrderStatusEventType_JobOrder,6047,Variable ISA95JobOrderStatusEventType_JobState,6048,Variable ISA95JobOrderStatusEventType_JobResponse,6049,Variable ISA95JobResponseProviderObjectType_JobOrderResponseList,6050,Variable ISA95JobOrderReceiverObjectType_StoreAndStart_InputArguments,6051,Variable ISA95JobOrderReceiverObjectType_StoreAndStart_OutputArguments,6052,Variable ISA95JobOrderReceiverObjectType_Start_InputArguments,6053,Variable ISA95JobOrderReceiverObjectType_Start_OutputArguments,6054,Variable ISA95JobOrderReceiverObjectType_Stop_InputArguments,6055,Variable ISA95JobOrderReceiverObjectType_Stop_OutputArguments,6056,Variable ISA95JobOrderReceiverObjectType_Pause_InputArguments,6057,Variable ISA95JobOrderReceiverObjectType_Pause_OutputArguments,6058,Variable ISA95JobOrderReceiverObjectType_Resume_InputArguments,6059,Variable ISA95JobOrderReceiverObjectType_Resume_OutputArguments,6060,Variable ISA95JobOrderReceiverObjectType_Update_InputArguments,6061,Variable ISA95JobOrderReceiverObjectType_Update_OutputArguments,6062,Variable ISA95JobOrderReceiverObjectType_Abort_InputArguments,6063,Variable ISA95JobOrderReceiverObjectType_Abort_OutputArguments,6064,Variable ISA95JobOrderReceiverObjectType_Cancel_InputArguments,6065,Variable ISA95JobOrderReceiverObjectType_Cancel_OutputArguments,6066,Variable ISA95JobOrderReceiverObjectType_Clear_InputArguments,6067,Variable ISA95JobOrderReceiverObjectType_Clear_OutputArguments,6068,Variable ISA95JobOrderReceiverObjectType_RevokeStart_InputArguments,6069,Variable ISA95JobOrderReceiverObjectType_RevokeStart_OutputArguments,6070,Variable ISA95JobOrderReceiverObjectType_NotAllowedToStart_StateNumber,6071,Variable ISA95JobOrderReceiverObjectType_AllowedToStart_StateNumber,6072,Variable ISA95JobOrderReceiverObjectType_Running_StateNumber,6073,Variable ISA95JobOrderReceiverObjectType_Interrupted_StateNumber,6074,Variable ISA95JobOrderReceiverObjectType_Ended_StateNumber,6075,Variable ISA95JobOrderReceiverObjectType_Aborted_StateNumber,6076,Variable ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToNotAllowedToStart_TransitionNumber,6077,Variable ISA95JobOrderReceiverObjectType_FromNotAllowedToStartToAllowedToStart_TransitionNumber,6078,Variable ISA95JobOrderReceiverObjectType_FromAllowedToStartToNotAllowedToStart_TransitionNumber,6079,Variable ISA95JobOrderReceiverObjectType_FromAllowedToStartToAllowedToStart_TransitionNumber,6080,Variable ISA95JobOrderReceiverObjectType_FromAllowedToStartToRunning_TransitionNumber,6081,Variable ISA95JobOrderReceiverObjectType_FromRunningToInterrupted_TransitionNumber,6082,Variable ISA95JobOrderReceiverObjectType_FromRunningToEnded_TransitionNumber,6083,Variable ISA95JobOrderReceiverObjectType_FromRunningToAborted_TransitionNumber,6084,Variable ISA95JobOrderReceiverObjectType_FromInterruptedToAborted_TransitionNumber,6085,Variable ISA95JobOrderReceiverObjectType_FromInterruptedToRunning_TransitionNumber,6086,Variable ISA95JobOrderReceiverObjectType_FromInterruptedToEnded_TransitionNumber,6087,Variable ISA95JobOrderReceiverObjectType_MaxDownloadableJobOrders,6088,Variable ISA95PrepareStateMachineType_Ready_StateNumber,6089,Variable ISA95PrepareStateMachineType_Loaded_StateNumber,6090,Variable ISA95PrepareStateMachineType_FromWaitingToReady_TransitionNumber,6091,Variable ISA95PrepareStateMachineType_FromReadyToLoaded_TransitionNumber,6092,Variable ISA95EndedStateMachineType_Completed_StateNumber,6093,Variable ISA95EndedStateMachineType_Closed_StateNumber,6094,Variable ISA95EndedStateMachineType_FromCompletedToClosed_TransitionNumber,6095,Variable ISA95InterruptedStateMachineType_Held_StateNumber,6096,Variable ISA95InterruptedStateMachineType_Suspended_StateNumber,6097,Variable ISA95InterruptedStateMachineType_FromHeldToSuspended_TransitionNumber,6098,Variable ISA95InterruptedStateMachineType_FromSuspendedToHeld_TransitionNumber,6099,Variable ISA95JobOrderReceiverSubStatesType_NotAllowedToStart_StateNumber,6100,Variable ISA95JobOrderReceiverSubStatesType_AllowedToStart_StateNumber,6101,Variable ISA95JobOrderReceiverSubStatesType_Running_StateNumber,6102,Variable ISA95JobOrderReceiverSubStatesType_Interrupted_StateNumber,6103,Variable ISA95JobOrderReceiverSubStatesType_Ended_StateNumber,6104,Variable ISA95JobOrderReceiverSubStatesType_Aborted_StateNumber,6105,Variable ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToNotAllowedToStart_TransitionNumber,6106,Variable ISA95JobOrderReceiverSubStatesType_FromNotAllowedToStartToAllowedToStart_TransitionNumber,6107,Variable ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToNotAllowedToStart_TransitionNumber,6108,Variable ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToAllowedToStart_TransitionNumber,6109,Variable ISA95JobOrderReceiverSubStatesType_FromAllowedToStartToRunning_TransitionNumber,6110,Variable ISA95JobOrderReceiverSubStatesType_FromRunningToInterrupted_TransitionNumber,6111,Variable ISA95JobOrderReceiverSubStatesType_FromRunningToEnded_TransitionNumber,6112,Variable ISA95JobOrderReceiverSubStatesType_FromRunningToAborted_TransitionNumber,6113,Variable ISA95JobOrderReceiverSubStatesType_FromInterruptedToAborted_TransitionNumber,6114,Variable ISA95JobOrderReceiverSubStatesType_FromInterruptedToRunning_TransitionNumber,6115,Variable ISA95JobOrderReceiverSubStatesType_FromInterruptedToEnded_TransitionNumber,6116,Variable TypeDictionary_XmlSchema_ISA95JobOrderDataType,6117,Variable TypeDictionary_BinarySchema_ISA95JobResponseDataType,6118,Variable TypeDictionary_XmlSchema_ISA95JobResponseDataType,6119,Variable TypeDictionary_BinarySchema_ISA95MaterialDataType,6120,Variable TypeDictionary_XmlSchema_ISA95MaterialDataType,6121,Variable TypeDictionary_BinarySchema_ISA95ParameterDataType,6122,Variable TypeDictionary_XmlSchema_ISA95ParameterDataType,6123,Variable TypeDictionary_BinarySchema_ISA95PersonnelDataType,6124,Variable TypeDictionary_XmlSchema_ISA95PersonnelDataType,6125,Variable TypeDictionary_BinarySchema_ISA95PhysicalAssetDataType,6126,Variable TypeDictionary_XmlSchema_ISA95PhysicalAssetDataType,6127,Variable TypeDictionary_BinarySchema_ISA95PropertyDataType,6128,Variable TypeDictionary_XmlSchema_ISA95PropertyDataType,6129,Variable TypeDictionary_BinarySchema_ISA95StateDataType,6130,Variable TypeDictionary_XmlSchema_ISA95StateDataType,6131,Variable TypeDictionary_BinarySchema_ISA95WorkMasterDataType,6132,Variable TypeDictionary_XmlSchema_ISA95WorkMasterDataType,6133,Variable ISA95JobOrderReceiverObjectType_Store,7001,Method ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderID,7002,Method ISA95JobResponseReceiverObjectType_ReceiveJobResponse,7003,Method ISA95JobOrderReceiverObjectType_StoreAndStart,7004,Method ISA95JobOrderReceiverObjectType_Start,7005,Method ISA95JobOrderReceiverObjectType_Stop,7006,Method ISA95JobOrderReceiverObjectType_Pause,7007,Method ISA95JobOrderReceiverObjectType_Resume,7008,Method ISA95JobOrderReceiverObjectType_Update,7009,Method ISA95JobOrderReceiverObjectType_Abort,7010,Method ISA95JobOrderReceiverObjectType_Cancel,7011,Method ISA95JobOrderReceiverObjectType_Clear,7012,Method ISA95JobOrderReceiverObjectType_RevokeStart,7013,Method ISA95JobResponseProviderObjectType_RequestJobResponseByJobOrderState,7014,Method ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Isa95Jobs/Nodesets/opc.ua.isa95-jobcontrol.nodeset2.documentation.csv ================================================ Id,Name,Link,ConformanceUnits 1001,ISA95PrepareStateMachineType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.3","ISA-95 Job Control Job Order Receiver SubStates;" 1002,ISA95JobOrderReceiverObjectType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.2","ISA-95 Job Order Receiver V2;" 1003,ISA95JobResponseProviderObjectType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.7/#7.2.7.1","ISA-95 Job Response Provider V2;" 1004,ISA95JobResponseReceiverObjectType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.8/#7.2.8.1","ISA-95 Job Response Receiver V2;" 1005,ISA95EndedStateMachineType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.4","ISA-95 Job Control Job Order Receiver SubStates;" 1006,ISA95JobOrderStatusEventType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.6","ISA-95 Job Control Job Response Provider Job Order Status Events;" 1007,ISA95InterruptedStateMachineType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.5","ISA-95 Job Control Job Order Receiver SubStates;" 1008,ISA95JobOrderReceiverSubStatesType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.2/#7.2.2.2","ISA-95 Job Control Job Order Receiver SubStates;" 3002,ISA95PropertyDataType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.9","ISA-95 Job Order Receiver V2;ISA-95 Job Response Provider V2;ISA-95 Job Response Receiver V2;" 3003,ISA95ParameterDataType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.10","ISA-95 Job Order Receiver V2;ISA-95 Job Response Provider V2;ISA-95 Job Response Receiver V2;" 3005,ISA95EquipmentDataType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.1","ISA-95 Job Order Receiver V2;ISA-95 Job Response Provider V2;ISA-95 Job Response Receiver V2;" 3006,ISA95StateDataType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.2","ISA-95 Job Order Receiver V2;ISA-95 Job Response Provider V2;ISA-95 Job Response Receiver V2;" 3007,ISA95WorkMasterDataType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.11","ISA-95 Job Order Receiver V2;" 3008,ISA95JobOrderDataType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.4","ISA-95 Job Order Receiver V2;" 3010,ISA95MaterialDataType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.6","ISA-95 Job Order Receiver V2;ISA-95 Job Response Provider V2;ISA-95 Job Response Receiver V2;" 3011,ISA95PersonnelDataType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.7","ISA-95 Job Order Receiver V2;ISA-95 Job Response Provider V2;ISA-95 Job Response Receiver V2;" 3012,ISA95PhysicalAssetDataType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.8","ISA-95 Job Order Receiver V2;ISA-95 Job Response Provider V2;ISA-95 Job Response Receiver V2;" 3013,ISA95JobResponseDataType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.5","ISA-95 Job Response Provider V2;ISA-95 Job Response Receiver V2;" 3015,ISA95JobOrderAndStateDataType,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.3","ISA-95 Job Order Receiver V2;" 5001,http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/9.1","" 7001,Store,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.3","" 7002,RequestJobResponseByJobOrderID,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.7/#7.2.7.2","" 7003,ReceiveJobResponse,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.8/#7.2.8.2","" 7004,StoreAndStart,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.4","" 7005,Start,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.5","" 7006,Stop,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.11","" 7007,Pause,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.7","" 7008,Resume,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.8","" 7009,Update,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.9","" 7010,Abort,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.10","" 7011,Cancel,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.12","" 7012,Clear,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.13","" 7013,RevokeStart,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.6","" 7014,RequestJobResponseByJobOrderState,"https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.7/#7.2.7.3","" ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Isa95Jobs/Nodesets/opc.ua.isa95-jobcontrol.nodeset2.xml ================================================ http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/ i=1 i=4 i=5 i=7 i=12 i=13 i=15 i=17 i=21 i=37 i=38 i=39 i=40 i=41 i=45 i=46 i=47 i=51 i=52 i=53 i=54 i=117 i=256 i=291 i=296 i=540 i=887 i=12878 ns=1;i=3002 ns=1;i=3003 ns=1;i=3005 ns=1;i=3006 ns=1;i=3007 ns=1;i=3008 ns=1;i=3010 ns=1;i=3011 ns=1;i=3012 ns=1;i=3013 ns=1;i=3015 ISA95EquipmentDataType Defines an equipment resource or a piece of equipment, a quantity, an optional description, and an optional collection of properties. ISA-95 Job Order Receiver V2 ISA-95 Job Response Provider V2 ISA-95 Job Response Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.1 ns=1;i=5008 ns=1;i=5010 ns=1;i=5009 i=22 An identification of an EquipmentClass or Equipment. Additional information and description about the resource. Information about the expected use of the equipment, see the ISA 95 Part 2 standard for defined values. The quantity of the resource The Unit Of Measure of the quantity Any associated properties, or empty if there are no properties defined. ISA95EquipmentDataType i=69 ns=1;i=5008 ns=1;i=6018 ISA95EquipmentDataType ISA95EquipmentDataType i=69 ns=1;i=5009 ns=1;i=6020 //xs:element[@name='ISA95EquipmentDataType'] ISA95JobOrderAndStateDataType Defines the information needed to schedule and execute a job. ISA-95 Job Order Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.3 ns=1;i=5032 ns=1;i=5034 ns=1;i=5033 i=22 The job order The State of the job order. The array shall provide at least one entry representing the top level state and potentially additional entries representing substates. The first entry shall be the top level entry, having the BrowsePath set to Null. The order of the subtstates is not defined. ISA95JobOrderAndStateDataType i=69 ns=1;i=5032 ns=1;i=6018 ISA95JobOrderAndStateDataType ISA95JobOrderAndStateDataType i=69 ns=1;i=5033 ns=1;i=6020 //xs:element[@name='ISA95JobOrderAndStateDataType'] ISA95JobOrderDataType Defines the information needed to schedule and execute a job. ISA-95 Job Order Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.4 ns=1;i=5014 ns=1;i=5016 ns=1;i=5015 i=22 An identification of the Job Order. Addition information about the Job Order The array allows to provide descriptions in different languages. Work Master associated with the job order. If multiple work masters are defined, then the execution system can select the work master based on the availability of resources. The proposed start time for the order, may be empty if not specified The proposed end time for the order, may be empty if not specified The priority of the job order, may be empty of not specified. Higher numbers have higher priority. This type allows the Job Order clients to pick their own ranges, and the Job Order server only has to pick the highest number. Key value pair with values, not associated with a resource that is provided as part of the job order, may be empty if not specified. A specification of any personnel requirements associated with the job order, may be empty if not specified A specification of any equipment requirements associated with the job order, may be empty if not specified. A specification of any physical asset requirements associated with the job order, may be empty if not specified. A specification of any material requirements associated with the job order, may be empty if not specified. ISA95JobOrderDataType i=69 ns=1;i=5014 ns=1;i=6018 ISA95JobOrderDataType ISA95JobOrderDataType i=69 ns=1;i=5015 ns=1;i=6020 //xs:element[@name='ISA95JobOrderDataType'] ISA95JobResponseDataType Defines the information needed to schedule and execute a job. ISA-95 Job Response Provider V2 ISA-95 Job Response Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.5 ns=1;i=5026 ns=1;i=5028 ns=1;i=5027 i=22 An identification of the Job Response Additional information about the Job Response An identification of the job order associated with the job response. The actual start time for the order. The actual end time for the order. The current state of the job. The array shall provide at least one entry representing the top level state and potentially additional entries representing substates. The first entry shall be the top level entry, having the BrowsePath set to Null. The order of the subtstates is not defined. Key value pair with values, not associated with a resource that is provided as part of the job response, may be empty if not specified. A specification of any personnel requirements associated with the job response, may be empty if not specified. A specification of any equipment requirements associated with the job response, may be empty if not specified. A specification of any physical asset requirements associated with the job response, may be empty if not specified. A specification of any material requirements associated with the job response, may be empty if not specified. ISA95JobResponseDataType i=69 ns=1;i=5026 ns=1;i=6018 ISA95JobResponseDataType ISA95JobResponseDataType i=69 ns=1;i=5027 ns=1;i=6020 //xs:element[@name='ISA95JobResponseDataType'] ISA95MaterialDataType Defines a material resource, a quantity, an optional description, and an optional collection of properties. ISA-95 Job Order Receiver V2 ISA-95 Job Response Provider V2 ISA-95 Job Response Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.6 ns=1;i=5017 ns=1;i=5019 ns=1;i=5018 i=22 An identification of the resource, or null if the Material Class is not used to identify the material. An identification of the resource, or null if the Material Definition is not used to identify the material. An identification of the resource, or null if the Material Lot is not used to identify the material. An identification of the resource, or null if the Material Sublot is not used to identify the material. Additional information and description about the resource. Information about the expected use of the material, see the ISA 95 Part 2 standard for defined values. The quantity of the resource The Unit Of Measure of the quantity Any associated properties, or empty if there are no properties defined. ISA95MaterialDataType i=69 ns=1;i=5017 ns=1;i=6018 ISA95MaterialDataType ISA95MaterialDataType i=69 ns=1;i=5018 ns=1;i=6020 //xs:element[@name='ISA95MaterialDataType'] ISA95ParameterDataType A subtype of OPC UA Structure that defines three linked data items: the ID, which is a unique identifier for a property, the value, which is the data that is identified, and an optional description of the parameter. ISA-95 Job Order Receiver V2 ISA-95 Job Response Provider V2 ISA-95 Job Response Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.10 ns=1;i=5005 ns=1;i=5007 ns=1;i=5006 i=22 A unique identifier for a parameter Value of the parameter. An optional description of the parameter. The array allows to provide descriptions in different languages when writing. When accessing, the server shall only provide one entry in the array. The Unit Of Measure of the value ISA95ParameterDataType i=69 ns=1;i=5005 ns=1;i=6018 ISA95ParameterDataType ISA95ParameterDataType i=69 ns=1;i=5006 ns=1;i=6020 //xs:element[@name='ISA95ParameterDataType'] ISA95PersonnelDataType Defines a personnel resource or a person, a quantity, an optional description, and an optional collection of properties. ISA-95 Job Order Receiver V2 ISA-95 Job Response Provider V2 ISA-95 Job Response Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.7 ns=1;i=5020 ns=1;i=5022 ns=1;i=5021 i=22 An identification of a Personnel Class or Person. Additional information and description about the resource. Information about the expected use of the personnel, see the ISA 95 Part 2 standard for defined values. The quantity of the resource The Unit Of Measure of the quantity Any associated properties, or empty if there are no properties defined. ISA95PersonnelDataType i=69 ns=1;i=5020 ns=1;i=6018 ISA95PersonnelDataType ISA95PersonnelDataType i=69 ns=1;i=5021 ns=1;i=6020 //xs:element[@name='ISA95PersonnelDataType'] ISA95PhysicalAssetDataType Defines a physical asset, a quantity, an optional description, and an optional collection of properties. ISA-95 Job Order Receiver V2 ISA-95 Job Response Provider V2 ISA-95 Job Response Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.8 ns=1;i=5023 ns=1;i=5025 ns=1;i=5024 i=22 An identification of a Physical Asset Class or Physical Asset. Additional information and description about the resource. Information about the expected use of the physical asset, see the ISA 95 Part 2 standard for defined values. The quantity of the resource The Unit Of Measure of the quantity Any associated properties, or empty if there are no properties defined. ISA95PhysicalAssetDataType i=69 ns=1;i=5023 ns=1;i=6018 ISA95PhysicalAssetDataType ISA95PhysicalAssetDataType i=69 ns=1;i=5024 ns=1;i=6020 //xs:element[@name='ISA95PhysicalAssetDataType'] ISA95PropertyDataType A subtype of OPC UA Structure that defines two linked data items: an ID, which is a unique identifier for a property within the scope of the associated resource, and the value, which is the data for the property. ISA-95 Job Order Receiver V2 ISA-95 Job Response Provider V2 ISA-95 Job Response Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.9 ns=1;i=5002 ns=1;i=5004 ns=1;i=5003 i=22 Unique identifier for a property within the scope of the associated resource Value for the property An optional description of the parameter. The Unit Of Measure of the value ISA95PropertyDataType i=69 ns=1;i=5002 ns=1;i=6018 ISA95PropertyDataType ISA95PropertyDataType i=69 ns=1;i=5003 ns=1;i=6020 //xs:element[@name='ISA95PropertyDataType'] ISA95StateDataType Defines the information needed to schedule and execute a job. ISA-95 Job Order Receiver V2 ISA-95 Job Response Provider V2 ISA-95 Job Response Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.2 ns=1;i=5029 ns=1;i=5031 ns=1;i=5030 i=22 The browse path of substates. Shall be null when the top-level state is represented. The state represented as human readable text. Shall represent the same text as the CurrentState Variable of a StateMachine would. The state represented as number. Shall represent the same number as the Number subvariable of the CurrentState Variable of a StateMachine would. ISA95StateDataType i=69 ns=1;i=5029 ns=1;i=6018 ISA95StateDataType ISA95StateDataType i=69 ns=1;i=5030 ns=1;i=6020 //xs:element[@name='ISA95StateDataType'] ISA95WorkMasterDataType Defines a Work Master ID and the defined parameters for the Work Master. ISA-95 Job Order Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.3.11 ns=1;i=5011 ns=1;i=5013 ns=1;i=5012 i=22 An identification of the Work Master. Additional information and description about the Work Master. Defined parameters for the Work Master. ISA95WorkMasterDataType i=69 ns=1;i=5011 ns=1;i=6018 ISA95WorkMasterDataType ISA95WorkMasterDataType i=69 ns=1;i=5012 ns=1;i=6020 //xs:element[@name='ISA95WorkMasterDataType'] TypeDictionary Collects the data type descriptions of http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/ i=72 ns=1;i=6022 ns=1;i=6031 ns=1;i=6046 ns=1;i=6118 ns=1;i=6120 ns=1;i=6122 ns=1;i=6124 ns=1;i=6126 ns=1;i=6128 ns=1;i=6130 ns=1;i=6132 ns=1;i=6019 i=93 PG9wYzpUeXBlRGljdGlvbmFyeSB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZ W1hLWluc3RhbmNlIiB4bWxuczp0bnM9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9yZy9VQS9JU 0E5NS1KT0JDT05UUk9MX1YyLyIgRGVmYXVsdEJ5dGVPcmRlcj0iTGl0dGxlRW5kaWFuIiB4b WxuczpvcGM9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9yZy9CaW5hcnlTY2hlbWEvIiB4bWxuc zp1YT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VBLyIgVGFyZ2V0TmFtZXNwYWNlPSJod HRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi8iPgogPG9wY zpJbXBvcnQgTmFtZXNwYWNlPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvIi8+CiA8b 3BjOlN0cnVjdHVyZWRUeXBlIEJhc2VUeXBlPSJ1YTpFeHRlbnNpb25PYmplY3QiIE5hbWU9I klTQTk1RXF1aXBtZW50RGF0YVR5cGUiPgogIDxvcGM6RG9jdW1lbnRhdGlvbj5EZWZpbmVzI GFuIGVxdWlwbWVudCByZXNvdXJjZSBvciBhIHBpZWNlIG9mIGVxdWlwbWVudCwgYSBxdWFud Gl0eSwgYW4gb3B0aW9uYWwgZGVzY3JpcHRpb24sIGFuZCBhbiBvcHRpb25hbCBjb2xsZWN0a W9uIG9mIHByb3BlcnRpZXMuPC9vcGM6RG9jdW1lbnRhdGlvbj4KICA8b3BjOkZpZWxkIFR5c GVOYW1lPSJvcGM6Qml0IiBOYW1lPSJEZXNjcmlwdGlvblNwZWNpZmllZCIvPgogIDxvcGM6R mllbGQgVHlwZU5hbWU9Im9wYzpCaXQiIE5hbWU9IkVxdWlwbWVudFVzZVNwZWNpZmllZCIvP gogIDxvcGM6RmllbGQgVHlwZU5hbWU9Im9wYzpCaXQiIE5hbWU9IlF1YW50aXR5U3BlY2lma WVkIi8+CiAgPG9wYzpGaWVsZCBUeXBlTmFtZT0ib3BjOkJpdCIgTmFtZT0iRW5naW5lZXJpb mdVbml0c1NwZWNpZmllZCIvPgogIDxvcGM6RmllbGQgVHlwZU5hbWU9Im9wYzpCaXQiIE5hb WU9IlByb3BlcnRpZXNTcGVjaWZpZWQiLz4KICA8b3BjOkZpZWxkIExlbmd0aD0iMjciIFR5c GVOYW1lPSJvcGM6Qml0IiBOYW1lPSJSZXNlcnZlZDEiLz4KICA8b3BjOkZpZWxkIFR5cGVOY W1lPSJvcGM6Q2hhckFycmF5IiBOYW1lPSJJRCIvPgogIDxvcGM6RmllbGQgU3dpdGNoRmllb GQ9IkRlc2NyaXB0aW9uU3BlY2lmaWVkIiBUeXBlTmFtZT0ib3BjOkludDMyIiBOYW1lPSJOb 09mRGVzY3JpcHRpb24iLz4KICA8b3BjOkZpZWxkIExlbmd0aEZpZWxkPSJOb09mRGVzY3Jpc HRpb24iIFN3aXRjaEZpZWxkPSJEZXNjcmlwdGlvblNwZWNpZmllZCIgVHlwZU5hbWU9InVhO kxvY2FsaXplZFRleHQiIE5hbWU9IkRlc2NyaXB0aW9uIi8+CiAgPG9wYzpGaWVsZCBTd2l0Y 2hGaWVsZD0iRXF1aXBtZW50VXNlU3BlY2lmaWVkIiBUeXBlTmFtZT0ib3BjOkNoYXJBcnJhe SIgTmFtZT0iRXF1aXBtZW50VXNlIi8+CiAgPG9wYzpGaWVsZCBTd2l0Y2hGaWVsZD0iUXVhb nRpdHlTcGVjaWZpZWQiIFR5cGVOYW1lPSJvcGM6Q2hhckFycmF5IiBOYW1lPSJRdWFudGl0e SIvPgogIDxvcGM6RmllbGQgU3dpdGNoRmllbGQ9IkVuZ2luZWVyaW5nVW5pdHNTcGVjaWZpZ WQiIFR5cGVOYW1lPSJ1YTpFVUluZm9ybWF0aW9uIiBOYW1lPSJFbmdpbmVlcmluZ1VuaXRzI i8+CiAgPG9wYzpGaWVsZCBTd2l0Y2hGaWVsZD0iUHJvcGVydGllc1NwZWNpZmllZCIgVHlwZ U5hbWU9Im9wYzpJbnQzMiIgTmFtZT0iTm9PZlByb3BlcnRpZXMiLz4KICA8b3BjOkZpZWxkI Exlbmd0aEZpZWxkPSJOb09mUHJvcGVydGllcyIgU3dpdGNoRmllbGQ9IlByb3BlcnRpZXNTc GVjaWZpZWQiIFR5cGVOYW1lPSJ0bnM6SVNBOTVQcm9wZXJ0eURhdGFUeXBlIiBOYW1lPSJQc m9wZXJ0aWVzIi8+CiA8L29wYzpTdHJ1Y3R1cmVkVHlwZT4KIDxvcGM6U3RydWN0dXJlZFR5c GUgQmFzZVR5cGU9InVhOkV4dGVuc2lvbk9iamVjdCIgTmFtZT0iSVNBOTVKb2JPcmRlckFuZ FN0YXRlRGF0YVR5cGUiPgogIDxvcGM6RG9jdW1lbnRhdGlvbj5EZWZpbmVzIHRoZSBpbmZvc m1hdGlvbiBuZWVkZWQgdG8gc2NoZWR1bGUgYW5kIGV4ZWN1dGUgYSBqb2IuPC9vcGM6RG9jd W1lbnRhdGlvbj4KICA8b3BjOkZpZWxkIFR5cGVOYW1lPSJ0bnM6SVNBOTVKb2JPcmRlckRhd GFUeXBlIiBOYW1lPSJKb2JPcmRlciIvPgogIDxvcGM6RmllbGQgVHlwZU5hbWU9Im9wYzpJb nQzMiIgTmFtZT0iTm9PZlN0YXRlIi8+CiAgPG9wYzpGaWVsZCBMZW5ndGhGaWVsZD0iTm9PZ lN0YXRlIiBUeXBlTmFtZT0idG5zOklTQTk1U3RhdGVEYXRhVHlwZSIgTmFtZT0iU3RhdGUiL z4KIDwvb3BjOlN0cnVjdHVyZWRUeXBlPgogPG9wYzpTdHJ1Y3R1cmVkVHlwZSBCYXNlVHlwZ T0idWE6RXh0ZW5zaW9uT2JqZWN0IiBOYW1lPSJJU0E5NUpvYk9yZGVyRGF0YVR5cGUiPgogI DxvcGM6RG9jdW1lbnRhdGlvbj5EZWZpbmVzIHRoZSBpbmZvcm1hdGlvbiBuZWVkZWQgdG8gc 2NoZWR1bGUgYW5kIGV4ZWN1dGUgYSBqb2IuPC9vcGM6RG9jdW1lbnRhdGlvbj4KICA8b3BjO kZpZWxkIFR5cGVOYW1lPSJvcGM6Qml0IiBOYW1lPSJEZXNjcmlwdGlvblNwZWNpZmllZCIvP gogIDxvcGM6RmllbGQgVHlwZU5hbWU9Im9wYzpCaXQiIE5hbWU9IldvcmtNYXN0ZXJJRFNwZ WNpZmllZCIvPgogIDxvcGM6RmllbGQgVHlwZU5hbWU9Im9wYzpCaXQiIE5hbWU9IlN0YXJ0V GltZVNwZWNpZmllZCIvPgogIDxvcGM6RmllbGQgVHlwZU5hbWU9Im9wYzpCaXQiIE5hbWU9I kVuZFRpbWVTcGVjaWZpZWQiLz4KICA8b3BjOkZpZWxkIFR5cGVOYW1lPSJvcGM6Qml0IiBOY W1lPSJQcmlvcml0eVNwZWNpZmllZCIvPgogIDxvcGM6RmllbGQgVHlwZU5hbWU9Im9wYzpCa XQiIE5hbWU9IkpvYk9yZGVyUGFyYW1ldGVyc1NwZWNpZmllZCIvPgogIDxvcGM6RmllbGQgV HlwZU5hbWU9Im9wYzpCaXQiIE5hbWU9IlBlcnNvbm5lbFJlcXVpcmVtZW50c1NwZWNpZmllZ CIvPgogIDxvcGM6RmllbGQgVHlwZU5hbWU9Im9wYzpCaXQiIE5hbWU9IkVxdWlwbWVudFJlc XVpcmVtZW50c1NwZWNpZmllZCIvPgogIDxvcGM6RmllbGQgVHlwZU5hbWU9Im9wYzpCaXQiI E5hbWU9IlBoeXNpY2FsQXNzZXRSZXF1aXJlbWVudHNTcGVjaWZpZWQiLz4KICA8b3BjOkZpZ WxkIFR5cGVOYW1lPSJvcGM6Qml0IiBOYW1lPSJNYXRlcmlhbFJlcXVpcmVtZW50c1NwZWNpZ mllZCIvPgogIDxvcGM6RmllbGQgTGVuZ3RoPSIyMiIgVHlwZU5hbWU9Im9wYzpCaXQiIE5hb WU9IlJlc2VydmVkMSIvPgogIDxvcGM6RmllbGQgVHlwZU5hbWU9Im9wYzpDaGFyQXJyYXkiI E5hbWU9IkpvYk9yZGVySUQiLz4KICA8b3BjOkZpZWxkIFN3aXRjaEZpZWxkPSJEZXNjcmlwd GlvblNwZWNpZmllZCIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgTmFtZT0iTm9PZkRlc2NyaXB0a W9uIi8+CiAgPG9wYzpGaWVsZCBMZW5ndGhGaWVsZD0iTm9PZkRlc2NyaXB0aW9uIiBTd2l0Y 2hGaWVsZD0iRGVzY3JpcHRpb25TcGVjaWZpZWQiIFR5cGVOYW1lPSJ1YTpMb2NhbGl6ZWRUZ Xh0IiBOYW1lPSJEZXNjcmlwdGlvbiIvPgogIDxvcGM6RmllbGQgU3dpdGNoRmllbGQ9Ildvc mtNYXN0ZXJJRFNwZWNpZmllZCIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgTmFtZT0iTm9PZldvc mtNYXN0ZXJJRCIvPgogIDxvcGM6RmllbGQgTGVuZ3RoRmllbGQ9Ik5vT2ZXb3JrTWFzdGVyS UQiIFN3aXRjaEZpZWxkPSJXb3JrTWFzdGVySURTcGVjaWZpZWQiIFR5cGVOYW1lPSJ0bnM6S VNBOTVXb3JrTWFzdGVyRGF0YVR5cGUiIE5hbWU9IldvcmtNYXN0ZXJJRCIvPgogIDxvcGM6R mllbGQgU3dpdGNoRmllbGQ9IlN0YXJ0VGltZVNwZWNpZmllZCIgVHlwZU5hbWU9Im9wYzpEY XRlVGltZSIgTmFtZT0iU3RhcnRUaW1lIi8+CiAgPG9wYzpGaWVsZCBTd2l0Y2hGaWVsZD0iR W5kVGltZVNwZWNpZmllZCIgVHlwZU5hbWU9Im9wYzpEYXRlVGltZSIgTmFtZT0iRW5kVGltZ SIvPgogIDxvcGM6RmllbGQgU3dpdGNoRmllbGQ9IlByaW9yaXR5U3BlY2lmaWVkIiBUeXBlT mFtZT0ib3BjOkludDE2IiBOYW1lPSJQcmlvcml0eSIvPgogIDxvcGM6RmllbGQgU3dpdGNoR mllbGQ9IkpvYk9yZGVyUGFyYW1ldGVyc1NwZWNpZmllZCIgVHlwZU5hbWU9Im9wYzpJbnQzM iIgTmFtZT0iTm9PZkpvYk9yZGVyUGFyYW1ldGVycyIvPgogIDxvcGM6RmllbGQgTGVuZ3RoR mllbGQ9Ik5vT2ZKb2JPcmRlclBhcmFtZXRlcnMiIFN3aXRjaEZpZWxkPSJKb2JPcmRlclBhc mFtZXRlcnNTcGVjaWZpZWQiIFR5cGVOYW1lPSJ0bnM6SVNBOTVQYXJhbWV0ZXJEYXRhVHlwZ SIgTmFtZT0iSm9iT3JkZXJQYXJhbWV0ZXJzIi8+CiAgPG9wYzpGaWVsZCBTd2l0Y2hGaWVsZ D0iUGVyc29ubmVsUmVxdWlyZW1lbnRzU3BlY2lmaWVkIiBUeXBlTmFtZT0ib3BjOkludDMyI iBOYW1lPSJOb09mUGVyc29ubmVsUmVxdWlyZW1lbnRzIi8+CiAgPG9wYzpGaWVsZCBMZW5nd GhGaWVsZD0iTm9PZlBlcnNvbm5lbFJlcXVpcmVtZW50cyIgU3dpdGNoRmllbGQ9IlBlcnNvb m5lbFJlcXVpcmVtZW50c1NwZWNpZmllZCIgVHlwZU5hbWU9InRuczpJU0E5NVBlcnNvbm5lb ERhdGFUeXBlIiBOYW1lPSJQZXJzb25uZWxSZXF1aXJlbWVudHMiLz4KICA8b3BjOkZpZWxkI FN3aXRjaEZpZWxkPSJFcXVpcG1lbnRSZXF1aXJlbWVudHNTcGVjaWZpZWQiIFR5cGVOYW1lP SJvcGM6SW50MzIiIE5hbWU9Ik5vT2ZFcXVpcG1lbnRSZXF1aXJlbWVudHMiLz4KICA8b3BjO kZpZWxkIExlbmd0aEZpZWxkPSJOb09mRXF1aXBtZW50UmVxdWlyZW1lbnRzIiBTd2l0Y2hGa WVsZD0iRXF1aXBtZW50UmVxdWlyZW1lbnRzU3BlY2lmaWVkIiBUeXBlTmFtZT0idG5zOklTQ Tk1RXF1aXBtZW50RGF0YVR5cGUiIE5hbWU9IkVxdWlwbWVudFJlcXVpcmVtZW50cyIvPgogI DxvcGM6RmllbGQgU3dpdGNoRmllbGQ9IlBoeXNpY2FsQXNzZXRSZXF1aXJlbWVudHNTcGVja WZpZWQiIFR5cGVOYW1lPSJvcGM6SW50MzIiIE5hbWU9Ik5vT2ZQaHlzaWNhbEFzc2V0UmVxd WlyZW1lbnRzIi8+CiAgPG9wYzpGaWVsZCBMZW5ndGhGaWVsZD0iTm9PZlBoeXNpY2FsQXNzZ XRSZXF1aXJlbWVudHMiIFN3aXRjaEZpZWxkPSJQaHlzaWNhbEFzc2V0UmVxdWlyZW1lbnRzU 3BlY2lmaWVkIiBUeXBlTmFtZT0idG5zOklTQTk1UGh5c2ljYWxBc3NldERhdGFUeXBlIiBOY W1lPSJQaHlzaWNhbEFzc2V0UmVxdWlyZW1lbnRzIi8+CiAgPG9wYzpGaWVsZCBTd2l0Y2hGa WVsZD0iTWF0ZXJpYWxSZXF1aXJlbWVudHNTcGVjaWZpZWQiIFR5cGVOYW1lPSJvcGM6SW50M zIiIE5hbWU9Ik5vT2ZNYXRlcmlhbFJlcXVpcmVtZW50cyIvPgogIDxvcGM6RmllbGQgTGVuZ 3RoRmllbGQ9Ik5vT2ZNYXRlcmlhbFJlcXVpcmVtZW50cyIgU3dpdGNoRmllbGQ9Ik1hdGVya WFsUmVxdWlyZW1lbnRzU3BlY2lmaWVkIiBUeXBlTmFtZT0idG5zOklTQTk1TWF0ZXJpYWxEY XRhVHlwZSIgTmFtZT0iTWF0ZXJpYWxSZXF1aXJlbWVudHMiLz4KIDwvb3BjOlN0cnVjdHVyZ WRUeXBlPgogPG9wYzpTdHJ1Y3R1cmVkVHlwZSBCYXNlVHlwZT0idWE6RXh0ZW5zaW9uT2JqZ WN0IiBOYW1lPSJJU0E5NUpvYlJlc3BvbnNlRGF0YVR5cGUiPgogIDxvcGM6RG9jdW1lbnRhd Glvbj5EZWZpbmVzIHRoZSBpbmZvcm1hdGlvbiBuZWVkZWQgdG8gc2NoZWR1bGUgYW5kIGV4Z WN1dGUgYSBqb2IuPC9vcGM6RG9jdW1lbnRhdGlvbj4KICA8b3BjOkZpZWxkIFR5cGVOYW1lP SJvcGM6Qml0IiBOYW1lPSJEZXNjcmlwdGlvblNwZWNpZmllZCIvPgogIDxvcGM6RmllbGQgV HlwZU5hbWU9Im9wYzpCaXQiIE5hbWU9IlN0YXJ0VGltZVNwZWNpZmllZCIvPgogIDxvcGM6R mllbGQgVHlwZU5hbWU9Im9wYzpCaXQiIE5hbWU9IkVuZFRpbWVTcGVjaWZpZWQiLz4KICA8b 3BjOkZpZWxkIFR5cGVOYW1lPSJvcGM6Qml0IiBOYW1lPSJKb2JSZXNwb25zZURhdGFTcGVja WZpZWQiLz4KICA8b3BjOkZpZWxkIFR5cGVOYW1lPSJvcGM6Qml0IiBOYW1lPSJQZXJzb25uZ WxBY3R1YWxzU3BlY2lmaWVkIi8+CiAgPG9wYzpGaWVsZCBUeXBlTmFtZT0ib3BjOkJpdCIgT mFtZT0iRXF1aXBtZW50QWN0dWFsc1NwZWNpZmllZCIvPgogIDxvcGM6RmllbGQgVHlwZU5hb WU9Im9wYzpCaXQiIE5hbWU9IlBoeXNpY2FsQXNzZXRBY3R1YWxzU3BlY2lmaWVkIi8+CiAgP G9wYzpGaWVsZCBUeXBlTmFtZT0ib3BjOkJpdCIgTmFtZT0iTWF0ZXJpYWxBY3R1YWxzU3BlY 2lmaWVkIi8+CiAgPG9wYzpGaWVsZCBMZW5ndGg9IjI0IiBUeXBlTmFtZT0ib3BjOkJpdCIgT mFtZT0iUmVzZXJ2ZWQxIi8+CiAgPG9wYzpGaWVsZCBUeXBlTmFtZT0ib3BjOkNoYXJBcnJhe SIgTmFtZT0iSm9iUmVzcG9uc2VJRCIvPgogIDxvcGM6RmllbGQgU3dpdGNoRmllbGQ9IkRlc 2NyaXB0aW9uU3BlY2lmaWVkIiBUeXBlTmFtZT0idWE6TG9jYWxpemVkVGV4dCIgTmFtZT0iR GVzY3JpcHRpb24iLz4KICA8b3BjOkZpZWxkIFR5cGVOYW1lPSJvcGM6Q2hhckFycmF5IiBOY W1lPSJKb2JPcmRlcklEIi8+CiAgPG9wYzpGaWVsZCBTd2l0Y2hGaWVsZD0iU3RhcnRUaW1lU 3BlY2lmaWVkIiBUeXBlTmFtZT0ib3BjOkRhdGVUaW1lIiBOYW1lPSJTdGFydFRpbWUiLz4KI CA8b3BjOkZpZWxkIFN3aXRjaEZpZWxkPSJFbmRUaW1lU3BlY2lmaWVkIiBUeXBlTmFtZT0ib 3BjOkRhdGVUaW1lIiBOYW1lPSJFbmRUaW1lIi8+CiAgPG9wYzpGaWVsZCBUeXBlTmFtZT0ib 3BjOkludDMyIiBOYW1lPSJOb09mSm9iU3RhdGUiLz4KICA8b3BjOkZpZWxkIExlbmd0aEZpZ WxkPSJOb09mSm9iU3RhdGUiIFR5cGVOYW1lPSJ0bnM6SVNBOTVTdGF0ZURhdGFUeXBlIiBOY W1lPSJKb2JTdGF0ZSIvPgogIDxvcGM6RmllbGQgU3dpdGNoRmllbGQ9IkpvYlJlc3BvbnNlR GF0YVNwZWNpZmllZCIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgTmFtZT0iTm9PZkpvYlJlc3Bvb nNlRGF0YSIvPgogIDxvcGM6RmllbGQgTGVuZ3RoRmllbGQ9Ik5vT2ZKb2JSZXNwb25zZURhd GEiIFN3aXRjaEZpZWxkPSJKb2JSZXNwb25zZURhdGFTcGVjaWZpZWQiIFR5cGVOYW1lPSJ0b nM6SVNBOTVQYXJhbWV0ZXJEYXRhVHlwZSIgTmFtZT0iSm9iUmVzcG9uc2VEYXRhIi8+CiAgP G9wYzpGaWVsZCBTd2l0Y2hGaWVsZD0iUGVyc29ubmVsQWN0dWFsc1NwZWNpZmllZCIgVHlwZ U5hbWU9Im9wYzpJbnQzMiIgTmFtZT0iTm9PZlBlcnNvbm5lbEFjdHVhbHMiLz4KICA8b3BjO kZpZWxkIExlbmd0aEZpZWxkPSJOb09mUGVyc29ubmVsQWN0dWFscyIgU3dpdGNoRmllbGQ9I lBlcnNvbm5lbEFjdHVhbHNTcGVjaWZpZWQiIFR5cGVOYW1lPSJ0bnM6SVNBOTVQZXJzb25uZ WxEYXRhVHlwZSIgTmFtZT0iUGVyc29ubmVsQWN0dWFscyIvPgogIDxvcGM6RmllbGQgU3dpd GNoRmllbGQ9IkVxdWlwbWVudEFjdHVhbHNTcGVjaWZpZWQiIFR5cGVOYW1lPSJvcGM6SW50M zIiIE5hbWU9Ik5vT2ZFcXVpcG1lbnRBY3R1YWxzIi8+CiAgPG9wYzpGaWVsZCBMZW5ndGhGa WVsZD0iTm9PZkVxdWlwbWVudEFjdHVhbHMiIFN3aXRjaEZpZWxkPSJFcXVpcG1lbnRBY3R1Y WxzU3BlY2lmaWVkIiBUeXBlTmFtZT0idG5zOklTQTk1RXF1aXBtZW50RGF0YVR5cGUiIE5hb WU9IkVxdWlwbWVudEFjdHVhbHMiLz4KICA8b3BjOkZpZWxkIFN3aXRjaEZpZWxkPSJQaHlza WNhbEFzc2V0QWN0dWFsc1NwZWNpZmllZCIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgTmFtZT0iT m9PZlBoeXNpY2FsQXNzZXRBY3R1YWxzIi8+CiAgPG9wYzpGaWVsZCBMZW5ndGhGaWVsZD0iT m9PZlBoeXNpY2FsQXNzZXRBY3R1YWxzIiBTd2l0Y2hGaWVsZD0iUGh5c2ljYWxBc3NldEFjd HVhbHNTcGVjaWZpZWQiIFR5cGVOYW1lPSJ0bnM6SVNBOTVQaHlzaWNhbEFzc2V0RGF0YVR5c GUiIE5hbWU9IlBoeXNpY2FsQXNzZXRBY3R1YWxzIi8+CiAgPG9wYzpGaWVsZCBTd2l0Y2hGa WVsZD0iTWF0ZXJpYWxBY3R1YWxzU3BlY2lmaWVkIiBUeXBlTmFtZT0ib3BjOkludDMyIiBOY W1lPSJOb09mTWF0ZXJpYWxBY3R1YWxzIi8+CiAgPG9wYzpGaWVsZCBMZW5ndGhGaWVsZD0iT m9PZk1hdGVyaWFsQWN0dWFscyIgU3dpdGNoRmllbGQ9Ik1hdGVyaWFsQWN0dWFsc1NwZWNpZ mllZCIgVHlwZU5hbWU9InRuczpJU0E5NU1hdGVyaWFsRGF0YVR5cGUiIE5hbWU9Ik1hdGVya WFsQWN0dWFscyIvPgogPC9vcGM6U3RydWN0dXJlZFR5cGU+CiA8b3BjOlN0cnVjdHVyZWRUe XBlIEJhc2VUeXBlPSJ1YTpFeHRlbnNpb25PYmplY3QiIE5hbWU9IklTQTk1TWF0ZXJpYWxEY XRhVHlwZSI+CiAgPG9wYzpEb2N1bWVudGF0aW9uPkRlZmluZXMgYSBtYXRlcmlhbCByZXNvd XJjZSwgYSBxdWFudGl0eSwgYW4gb3B0aW9uYWwgZGVzY3JpcHRpb24sIGFuZCBhbiBvcHRpb 25hbCBjb2xsZWN0aW9uIG9mIHByb3BlcnRpZXMuPC9vcGM6RG9jdW1lbnRhdGlvbj4KICA8b 3BjOkZpZWxkIFR5cGVOYW1lPSJvcGM6Qml0IiBOYW1lPSJNYXRlcmlhbENsYXNzSURTcGVja WZpZWQiLz4KICA8b3BjOkZpZWxkIFR5cGVOYW1lPSJvcGM6Qml0IiBOYW1lPSJNYXRlcmlhb ERlZmluaXRpb25JRFNwZWNpZmllZCIvPgogIDxvcGM6RmllbGQgVHlwZU5hbWU9Im9wYzpCa XQiIE5hbWU9Ik1hdGVyaWFsTG90SURTcGVjaWZpZWQiLz4KICA8b3BjOkZpZWxkIFR5cGVOY W1lPSJvcGM6Qml0IiBOYW1lPSJNYXRlcmlhbFN1YmxvdElEU3BlY2lmaWVkIi8+CiAgPG9wY zpGaWVsZCBUeXBlTmFtZT0ib3BjOkJpdCIgTmFtZT0iRGVzY3JpcHRpb25TcGVjaWZpZWQiL z4KICA8b3BjOkZpZWxkIFR5cGVOYW1lPSJvcGM6Qml0IiBOYW1lPSJNYXRlcmlhbFVzZVNwZ WNpZmllZCIvPgogIDxvcGM6RmllbGQgVHlwZU5hbWU9Im9wYzpCaXQiIE5hbWU9IlF1YW50a XR5U3BlY2lmaWVkIi8+CiAgPG9wYzpGaWVsZCBUeXBlTmFtZT0ib3BjOkJpdCIgTmFtZT0iR W5naW5lZXJpbmdVbml0c1NwZWNpZmllZCIvPgogIDxvcGM6RmllbGQgVHlwZU5hbWU9Im9wY zpCaXQiIE5hbWU9IlByb3BlcnRpZXNTcGVjaWZpZWQiLz4KICA8b3BjOkZpZWxkIExlbmd0a D0iMjMiIFR5cGVOYW1lPSJvcGM6Qml0IiBOYW1lPSJSZXNlcnZlZDEiLz4KICA8b3BjOkZpZ WxkIFN3aXRjaEZpZWxkPSJNYXRlcmlhbENsYXNzSURTcGVjaWZpZWQiIFR5cGVOYW1lPSJvc GM6Q2hhckFycmF5IiBOYW1lPSJNYXRlcmlhbENsYXNzSUQiLz4KICA8b3BjOkZpZWxkIFN3a XRjaEZpZWxkPSJNYXRlcmlhbERlZmluaXRpb25JRFNwZWNpZmllZCIgVHlwZU5hbWU9Im9wY zpDaGFyQXJyYXkiIE5hbWU9Ik1hdGVyaWFsRGVmaW5pdGlvbklEIi8+CiAgPG9wYzpGaWVsZ CBTd2l0Y2hGaWVsZD0iTWF0ZXJpYWxMb3RJRFNwZWNpZmllZCIgVHlwZU5hbWU9Im9wYzpDa GFyQXJyYXkiIE5hbWU9Ik1hdGVyaWFsTG90SUQiLz4KICA8b3BjOkZpZWxkIFN3aXRjaEZpZ WxkPSJNYXRlcmlhbFN1YmxvdElEU3BlY2lmaWVkIiBUeXBlTmFtZT0ib3BjOkNoYXJBcnJhe SIgTmFtZT0iTWF0ZXJpYWxTdWJsb3RJRCIvPgogIDxvcGM6RmllbGQgU3dpdGNoRmllbGQ9I kRlc2NyaXB0aW9uU3BlY2lmaWVkIiBUeXBlTmFtZT0ib3BjOkludDMyIiBOYW1lPSJOb09mR GVzY3JpcHRpb24iLz4KICA8b3BjOkZpZWxkIExlbmd0aEZpZWxkPSJOb09mRGVzY3JpcHRpb 24iIFN3aXRjaEZpZWxkPSJEZXNjcmlwdGlvblNwZWNpZmllZCIgVHlwZU5hbWU9InVhOkxvY 2FsaXplZFRleHQiIE5hbWU9IkRlc2NyaXB0aW9uIi8+CiAgPG9wYzpGaWVsZCBTd2l0Y2hGa WVsZD0iTWF0ZXJpYWxVc2VTcGVjaWZpZWQiIFR5cGVOYW1lPSJvcGM6Q2hhckFycmF5IiBOY W1lPSJNYXRlcmlhbFVzZSIvPgogIDxvcGM6RmllbGQgU3dpdGNoRmllbGQ9IlF1YW50aXR5U 3BlY2lmaWVkIiBUeXBlTmFtZT0ib3BjOkNoYXJBcnJheSIgTmFtZT0iUXVhbnRpdHkiLz4KI CA8b3BjOkZpZWxkIFN3aXRjaEZpZWxkPSJFbmdpbmVlcmluZ1VuaXRzU3BlY2lmaWVkIiBUe XBlTmFtZT0idWE6RVVJbmZvcm1hdGlvbiIgTmFtZT0iRW5naW5lZXJpbmdVbml0cyIvPgogI DxvcGM6RmllbGQgU3dpdGNoRmllbGQ9IlByb3BlcnRpZXNTcGVjaWZpZWQiIFR5cGVOYW1lP SJvcGM6SW50MzIiIE5hbWU9Ik5vT2ZQcm9wZXJ0aWVzIi8+CiAgPG9wYzpGaWVsZCBMZW5nd GhGaWVsZD0iTm9PZlByb3BlcnRpZXMiIFN3aXRjaEZpZWxkPSJQcm9wZXJ0aWVzU3BlY2lma WVkIiBUeXBlTmFtZT0idG5zOklTQTk1UHJvcGVydHlEYXRhVHlwZSIgTmFtZT0iUHJvcGVyd GllcyIvPgogPC9vcGM6U3RydWN0dXJlZFR5cGU+CiA8b3BjOlN0cnVjdHVyZWRUeXBlIEJhc 2VUeXBlPSJ1YTpFeHRlbnNpb25PYmplY3QiIE5hbWU9IklTQTk1UGFyYW1ldGVyRGF0YVR5c GUiPgogIDxvcGM6RG9jdW1lbnRhdGlvbj5BIHN1YnR5cGUgb2YgT1BDIFVBIFN0cnVjdHVyZ SB0aGF0IGRlZmluZXMgdGhyZWUgbGlua2VkIGRhdGEgaXRlbXM6IHRoZSBJRCwgd2hpY2gga XMgYSB1bmlxdWUgaWRlbnRpZmllciBmb3IgYSBwcm9wZXJ0eSwgdGhlIHZhbHVlLCB3aGlja CBpcyB0aGUgZGF0YSB0aGF0IGlzIGlkZW50aWZpZWQsIGFuZCBhbiBvcHRpb25hbCBkZXNjc mlwdGlvbiBvZiB0aGUgcGFyYW1ldGVyLjwvb3BjOkRvY3VtZW50YXRpb24+CiAgPG9wYzpGa WVsZCBUeXBlTmFtZT0ib3BjOkJpdCIgTmFtZT0iRGVzY3JpcHRpb25TcGVjaWZpZWQiLz4KI CA8b3BjOkZpZWxkIFR5cGVOYW1lPSJvcGM6Qml0IiBOYW1lPSJFbmdpbmVlcmluZ1VuaXRzU 3BlY2lmaWVkIi8+CiAgPG9wYzpGaWVsZCBUeXBlTmFtZT0ib3BjOkJpdCIgTmFtZT0iU3Vic GFyYW1ldGVyc1NwZWNpZmllZCIvPgogIDxvcGM6RmllbGQgTGVuZ3RoPSIyOSIgVHlwZU5hb WU9Im9wYzpCaXQiIE5hbWU9IlJlc2VydmVkMSIvPgogIDxvcGM6RmllbGQgVHlwZU5hbWU9I m9wYzpDaGFyQXJyYXkiIE5hbWU9IklEIi8+CiAgPG9wYzpGaWVsZCBUeXBlTmFtZT0idWE6V mFyaWFudCIgTmFtZT0iVmFsdWUiLz4KICA8b3BjOkZpZWxkIFN3aXRjaEZpZWxkPSJEZXNjc mlwdGlvblNwZWNpZmllZCIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgTmFtZT0iTm9PZkRlc2Nya XB0aW9uIi8+CiAgPG9wYzpGaWVsZCBMZW5ndGhGaWVsZD0iTm9PZkRlc2NyaXB0aW9uIiBTd 2l0Y2hGaWVsZD0iRGVzY3JpcHRpb25TcGVjaWZpZWQiIFR5cGVOYW1lPSJ1YTpMb2NhbGl6Z WRUZXh0IiBOYW1lPSJEZXNjcmlwdGlvbiIvPgogIDxvcGM6RmllbGQgU3dpdGNoRmllbGQ9I kVuZ2luZWVyaW5nVW5pdHNTcGVjaWZpZWQiIFR5cGVOYW1lPSJ1YTpFVUluZm9ybWF0aW9uI iBOYW1lPSJFbmdpbmVlcmluZ1VuaXRzIi8+CiAgPG9wYzpGaWVsZCBTd2l0Y2hGaWVsZD0iU 3VicGFyYW1ldGVyc1NwZWNpZmllZCIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgTmFtZT0iTm9PZ lN1YnBhcmFtZXRlcnMiLz4KICA8b3BjOkZpZWxkIExlbmd0aEZpZWxkPSJOb09mU3VicGFyY W1ldGVycyIgU3dpdGNoRmllbGQ9IlN1YnBhcmFtZXRlcnNTcGVjaWZpZWQiIFR5cGVOYW1lP SJ0bnM6SVNBOTVQYXJhbWV0ZXJEYXRhVHlwZSIgTmFtZT0iU3VicGFyYW1ldGVycyIvPgogP C9vcGM6U3RydWN0dXJlZFR5cGU+CiA8b3BjOlN0cnVjdHVyZWRUeXBlIEJhc2VUeXBlPSJ1Y TpFeHRlbnNpb25PYmplY3QiIE5hbWU9IklTQTk1UGVyc29ubmVsRGF0YVR5cGUiPgogIDxvc GM6RG9jdW1lbnRhdGlvbj5EZWZpbmVzIGEgcGVyc29ubmVsIHJlc291cmNlIG9yIGEgcGVyc 29uLCBhIHF1YW50aXR5LCBhbiBvcHRpb25hbCBkZXNjcmlwdGlvbiwgYW5kIGFuIG9wdGlvb mFsIGNvbGxlY3Rpb24gb2YgcHJvcGVydGllcy48L29wYzpEb2N1bWVudGF0aW9uPgogIDxvc GM6RmllbGQgVHlwZU5hbWU9Im9wYzpCaXQiIE5hbWU9IkRlc2NyaXB0aW9uU3BlY2lmaWVkI i8+CiAgPG9wYzpGaWVsZCBUeXBlTmFtZT0ib3BjOkJpdCIgTmFtZT0iUGVyc29ubmVsVXNlU 3BlY2lmaWVkIi8+CiAgPG9wYzpGaWVsZCBUeXBlTmFtZT0ib3BjOkJpdCIgTmFtZT0iUXVhb nRpdHlTcGVjaWZpZWQiLz4KICA8b3BjOkZpZWxkIFR5cGVOYW1lPSJvcGM6Qml0IiBOYW1lP SJFbmdpbmVlcmluZ1VuaXRzU3BlY2lmaWVkIi8+CiAgPG9wYzpGaWVsZCBUeXBlTmFtZT0ib 3BjOkJpdCIgTmFtZT0iUHJvcGVydGllc1NwZWNpZmllZCIvPgogIDxvcGM6RmllbGQgTGVuZ 3RoPSIyNyIgVHlwZU5hbWU9Im9wYzpCaXQiIE5hbWU9IlJlc2VydmVkMSIvPgogIDxvcGM6R mllbGQgVHlwZU5hbWU9Im9wYzpDaGFyQXJyYXkiIE5hbWU9IklEIi8+CiAgPG9wYzpGaWVsZ CBTd2l0Y2hGaWVsZD0iRGVzY3JpcHRpb25TcGVjaWZpZWQiIFR5cGVOYW1lPSJvcGM6SW50M zIiIE5hbWU9Ik5vT2ZEZXNjcmlwdGlvbiIvPgogIDxvcGM6RmllbGQgTGVuZ3RoRmllbGQ9I k5vT2ZEZXNjcmlwdGlvbiIgU3dpdGNoRmllbGQ9IkRlc2NyaXB0aW9uU3BlY2lmaWVkIiBUe XBlTmFtZT0idWE6TG9jYWxpemVkVGV4dCIgTmFtZT0iRGVzY3JpcHRpb24iLz4KICA8b3BjO kZpZWxkIFN3aXRjaEZpZWxkPSJQZXJzb25uZWxVc2VTcGVjaWZpZWQiIFR5cGVOYW1lPSJvc GM6Q2hhckFycmF5IiBOYW1lPSJQZXJzb25uZWxVc2UiLz4KICA8b3BjOkZpZWxkIFN3aXRja EZpZWxkPSJRdWFudGl0eVNwZWNpZmllZCIgVHlwZU5hbWU9Im9wYzpDaGFyQXJyYXkiIE5hb WU9IlF1YW50aXR5Ii8+CiAgPG9wYzpGaWVsZCBTd2l0Y2hGaWVsZD0iRW5naW5lZXJpbmdVb ml0c1NwZWNpZmllZCIgVHlwZU5hbWU9InVhOkVVSW5mb3JtYXRpb24iIE5hbWU9IkVuZ2luZ WVyaW5nVW5pdHMiLz4KICA8b3BjOkZpZWxkIFN3aXRjaEZpZWxkPSJQcm9wZXJ0aWVzU3BlY 2lmaWVkIiBUeXBlTmFtZT0ib3BjOkludDMyIiBOYW1lPSJOb09mUHJvcGVydGllcyIvPgogI DxvcGM6RmllbGQgTGVuZ3RoRmllbGQ9Ik5vT2ZQcm9wZXJ0aWVzIiBTd2l0Y2hGaWVsZD0iU HJvcGVydGllc1NwZWNpZmllZCIgVHlwZU5hbWU9InRuczpJU0E5NVByb3BlcnR5RGF0YVR5c GUiIE5hbWU9IlByb3BlcnRpZXMiLz4KIDwvb3BjOlN0cnVjdHVyZWRUeXBlPgogPG9wYzpTd HJ1Y3R1cmVkVHlwZSBCYXNlVHlwZT0idWE6RXh0ZW5zaW9uT2JqZWN0IiBOYW1lPSJJU0E5N VBoeXNpY2FsQXNzZXREYXRhVHlwZSI+CiAgPG9wYzpEb2N1bWVudGF0aW9uPkRlZmluZXMgY SBwaHlzaWNhbCBhc3NldCwgYSBxdWFudGl0eSwgYW4gb3B0aW9uYWwgZGVzY3JpcHRpb24sI GFuZCBhbiBvcHRpb25hbCBjb2xsZWN0aW9uIG9mIHByb3BlcnRpZXMuPC9vcGM6RG9jdW1lb nRhdGlvbj4KICA8b3BjOkZpZWxkIFR5cGVOYW1lPSJvcGM6Qml0IiBOYW1lPSJEZXNjcmlwd GlvblNwZWNpZmllZCIvPgogIDxvcGM6RmllbGQgVHlwZU5hbWU9Im9wYzpCaXQiIE5hbWU9I lBoeXNpY2FsQXNzZXRVc2VTcGVjaWZpZWQiLz4KICA8b3BjOkZpZWxkIFR5cGVOYW1lPSJvc GM6Qml0IiBOYW1lPSJRdWFudGl0eVNwZWNpZmllZCIvPgogIDxvcGM6RmllbGQgVHlwZU5hb WU9Im9wYzpCaXQiIE5hbWU9IkVuZ2luZWVyaW5nVW5pdHNTcGVjaWZpZWQiLz4KICA8b3BjO kZpZWxkIFR5cGVOYW1lPSJvcGM6Qml0IiBOYW1lPSJQcm9wZXJ0aWVzU3BlY2lmaWVkIi8+C iAgPG9wYzpGaWVsZCBMZW5ndGg9IjI3IiBUeXBlTmFtZT0ib3BjOkJpdCIgTmFtZT0iUmVzZ XJ2ZWQxIi8+CiAgPG9wYzpGaWVsZCBUeXBlTmFtZT0ib3BjOkNoYXJBcnJheSIgTmFtZT0iS UQiLz4KICA8b3BjOkZpZWxkIFN3aXRjaEZpZWxkPSJEZXNjcmlwdGlvblNwZWNpZmllZCIgV HlwZU5hbWU9Im9wYzpJbnQzMiIgTmFtZT0iTm9PZkRlc2NyaXB0aW9uIi8+CiAgPG9wYzpGa WVsZCBMZW5ndGhGaWVsZD0iTm9PZkRlc2NyaXB0aW9uIiBTd2l0Y2hGaWVsZD0iRGVzY3Jpc HRpb25TcGVjaWZpZWQiIFR5cGVOYW1lPSJ1YTpMb2NhbGl6ZWRUZXh0IiBOYW1lPSJEZXNjc mlwdGlvbiIvPgogIDxvcGM6RmllbGQgU3dpdGNoRmllbGQ9IlBoeXNpY2FsQXNzZXRVc2VTc GVjaWZpZWQiIFR5cGVOYW1lPSJvcGM6Q2hhckFycmF5IiBOYW1lPSJQaHlzaWNhbEFzc2V0V XNlIi8+CiAgPG9wYzpGaWVsZCBTd2l0Y2hGaWVsZD0iUXVhbnRpdHlTcGVjaWZpZWQiIFR5c GVOYW1lPSJvcGM6Q2hhckFycmF5IiBOYW1lPSJRdWFudGl0eSIvPgogIDxvcGM6RmllbGQgU 3dpdGNoRmllbGQ9IkVuZ2luZWVyaW5nVW5pdHNTcGVjaWZpZWQiIFR5cGVOYW1lPSJ1YTpFV UluZm9ybWF0aW9uIiBOYW1lPSJFbmdpbmVlcmluZ1VuaXRzIi8+CiAgPG9wYzpGaWVsZCBTd 2l0Y2hGaWVsZD0iUHJvcGVydGllc1NwZWNpZmllZCIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgT mFtZT0iTm9PZlByb3BlcnRpZXMiLz4KICA8b3BjOkZpZWxkIExlbmd0aEZpZWxkPSJOb09mU HJvcGVydGllcyIgU3dpdGNoRmllbGQ9IlByb3BlcnRpZXNTcGVjaWZpZWQiIFR5cGVOYW1lP SJ0bnM6SVNBOTVQcm9wZXJ0eURhdGFUeXBlIiBOYW1lPSJQcm9wZXJ0aWVzIi8+CiA8L29wY zpTdHJ1Y3R1cmVkVHlwZT4KIDxvcGM6U3RydWN0dXJlZFR5cGUgQmFzZVR5cGU9InVhOkV4d GVuc2lvbk9iamVjdCIgTmFtZT0iSVNBOTVQcm9wZXJ0eURhdGFUeXBlIj4KICA8b3BjOkRvY 3VtZW50YXRpb24+QSBzdWJ0eXBlIG9mIE9QQyBVQSBTdHJ1Y3R1cmUgdGhhdCBkZWZpbmVzI HR3byBsaW5rZWQgZGF0YSBpdGVtczogYW4gSUQsIHdoaWNoIGlzIGEgdW5pcXVlIGlkZW50a WZpZXIgZm9yIGEgcHJvcGVydHkgd2l0aGluIHRoZSBzY29wZSBvZiB0aGUgYXNzb2NpYXRlZ CByZXNvdXJjZSwgYW5kIHRoZSB2YWx1ZSwgd2hpY2ggaXMgdGhlIGRhdGEgZm9yIHRoZSBwc m9wZXJ0eS48L29wYzpEb2N1bWVudGF0aW9uPgogIDxvcGM6RmllbGQgVHlwZU5hbWU9Im9wY zpCaXQiIE5hbWU9IkRlc2NyaXB0aW9uU3BlY2lmaWVkIi8+CiAgPG9wYzpGaWVsZCBUeXBlT mFtZT0ib3BjOkJpdCIgTmFtZT0iRW5naW5lZXJpbmdVbml0c1NwZWNpZmllZCIvPgogIDxvc GM6RmllbGQgVHlwZU5hbWU9Im9wYzpCaXQiIE5hbWU9IlN1YnByb3BlcnRpZXNTcGVjaWZpZ WQiLz4KICA8b3BjOkZpZWxkIExlbmd0aD0iMjkiIFR5cGVOYW1lPSJvcGM6Qml0IiBOYW1lP SJSZXNlcnZlZDEiLz4KICA8b3BjOkZpZWxkIFR5cGVOYW1lPSJvcGM6Q2hhckFycmF5IiBOY W1lPSJJRCIvPgogIDxvcGM6RmllbGQgVHlwZU5hbWU9InVhOlZhcmlhbnQiIE5hbWU9IlZhb HVlIi8+CiAgPG9wYzpGaWVsZCBTd2l0Y2hGaWVsZD0iRGVzY3JpcHRpb25TcGVjaWZpZWQiI FR5cGVOYW1lPSJvcGM6SW50MzIiIE5hbWU9Ik5vT2ZEZXNjcmlwdGlvbiIvPgogIDxvcGM6R mllbGQgTGVuZ3RoRmllbGQ9Ik5vT2ZEZXNjcmlwdGlvbiIgU3dpdGNoRmllbGQ9IkRlc2Nya XB0aW9uU3BlY2lmaWVkIiBUeXBlTmFtZT0idWE6TG9jYWxpemVkVGV4dCIgTmFtZT0iRGVzY 3JpcHRpb24iLz4KICA8b3BjOkZpZWxkIFN3aXRjaEZpZWxkPSJFbmdpbmVlcmluZ1VuaXRzU 3BlY2lmaWVkIiBUeXBlTmFtZT0idWE6RVVJbmZvcm1hdGlvbiIgTmFtZT0iRW5naW5lZXJpb mdVbml0cyIvPgogIDxvcGM6RmllbGQgU3dpdGNoRmllbGQ9IlN1YnByb3BlcnRpZXNTcGVja WZpZWQiIFR5cGVOYW1lPSJvcGM6SW50MzIiIE5hbWU9Ik5vT2ZTdWJwcm9wZXJ0aWVzIi8+C iAgPG9wYzpGaWVsZCBMZW5ndGhGaWVsZD0iTm9PZlN1YnByb3BlcnRpZXMiIFN3aXRjaEZpZ WxkPSJTdWJwcm9wZXJ0aWVzU3BlY2lmaWVkIiBUeXBlTmFtZT0idG5zOklTQTk1UHJvcGVyd HlEYXRhVHlwZSIgTmFtZT0iU3VicHJvcGVydGllcyIvPgogPC9vcGM6U3RydWN0dXJlZFR5c GU+CiA8b3BjOlN0cnVjdHVyZWRUeXBlIEJhc2VUeXBlPSJ1YTpFeHRlbnNpb25PYmplY3QiI E5hbWU9IklTQTk1U3RhdGVEYXRhVHlwZSI+CiAgPG9wYzpEb2N1bWVudGF0aW9uPkRlZmluZ XMgdGhlIGluZm9ybWF0aW9uIG5lZWRlZCB0byBzY2hlZHVsZSBhbmQgZXhlY3V0ZSBhIGpvY i48L29wYzpEb2N1bWVudGF0aW9uPgogIDxvcGM6RmllbGQgVHlwZU5hbWU9InVhOlJlbGF0a XZlUGF0aCIgTmFtZT0iQnJvd3NlUGF0aCIvPgogIDxvcGM6RmllbGQgVHlwZU5hbWU9InVhO kxvY2FsaXplZFRleHQiIE5hbWU9IlN0YXRlVGV4dCIvPgogIDxvcGM6RmllbGQgVHlwZU5hb WU9Im9wYzpVSW50MzIiIE5hbWU9IlN0YXRlTnVtYmVyIi8+CiA8L29wYzpTdHJ1Y3R1cmVkV HlwZT4KIDxvcGM6U3RydWN0dXJlZFR5cGUgQmFzZVR5cGU9InVhOkV4dGVuc2lvbk9iamVjd CIgTmFtZT0iSVNBOTVXb3JrTWFzdGVyRGF0YVR5cGUiPgogIDxvcGM6RG9jdW1lbnRhdGlvb j5EZWZpbmVzIGEgV29yayBNYXN0ZXIgSUQgYW5kIHRoZSBkZWZpbmVkIHBhcmFtZXRlcnMgZ m9yIHRoZSBXb3JrIE1hc3Rlci48L29wYzpEb2N1bWVudGF0aW9uPgogIDxvcGM6RmllbGQgV HlwZU5hbWU9Im9wYzpCaXQiIE5hbWU9IkRlc2NyaXB0aW9uU3BlY2lmaWVkIi8+CiAgPG9wY zpGaWVsZCBUeXBlTmFtZT0ib3BjOkJpdCIgTmFtZT0iUGFyYW1ldGVyc1NwZWNpZmllZCIvP gogIDxvcGM6RmllbGQgTGVuZ3RoPSIzMCIgVHlwZU5hbWU9Im9wYzpCaXQiIE5hbWU9IlJlc 2VydmVkMSIvPgogIDxvcGM6RmllbGQgVHlwZU5hbWU9Im9wYzpDaGFyQXJyYXkiIE5hbWU9I klEIi8+CiAgPG9wYzpGaWVsZCBTd2l0Y2hGaWVsZD0iRGVzY3JpcHRpb25TcGVjaWZpZWQiI FR5cGVOYW1lPSJ1YTpMb2NhbGl6ZWRUZXh0IiBOYW1lPSJEZXNjcmlwdGlvbiIvPgogIDxvc GM6RmllbGQgU3dpdGNoRmllbGQ9IlBhcmFtZXRlcnNTcGVjaWZpZWQiIFR5cGVOYW1lPSJvc GM6SW50MzIiIE5hbWU9Ik5vT2ZQYXJhbWV0ZXJzIi8+CiAgPG9wYzpGaWVsZCBMZW5ndGhGa WVsZD0iTm9PZlBhcmFtZXRlcnMiIFN3aXRjaEZpZWxkPSJQYXJhbWV0ZXJzU3BlY2lmaWVkI iBUeXBlTmFtZT0idG5zOklTQTk1UGFyYW1ldGVyRGF0YVR5cGUiIE5hbWU9IlBhcmFtZXRlc nMiLz4KIDwvb3BjOlN0cnVjdHVyZWRUeXBlPgo8L29wYzpUeXBlRGljdGlvbmFyeT4K NamespaceUri i=68 ns=1;i=6018 http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/ TypeDictionary Collects the data type descriptions of http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/ i=72 ns=1;i=6030 ns=1;i=6032 ns=1;i=6117 ns=1;i=6119 ns=1;i=6121 ns=1;i=6123 ns=1;i=6125 ns=1;i=6127 ns=1;i=6129 ns=1;i=6131 ns=1;i=6133 ns=1;i=6021 i=92 PHhzOnNjaGVtYSBlbGVtZW50Rm9ybURlZmF1bHQ9InF1YWxpZmllZCIgdGFyZ2V0TmFtZXNwYWNlPSJod HRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvSVNBOTUtSk9CQ09OVFJPTF9WMi9UeXBlcy54c 2QiIHhtbG5zOnRucz0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VBL0lTQTk1LUpPQkNPT lRST0xfVjIvVHlwZXMueHNkIiB4bWxuczp1YT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL 1VBLzIwMDgvMDIvVHlwZXMueHNkIiB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwM S9YTUxTY2hlbWEiPgogPHhzOmltcG9ydCBuYW1lc3BhY2U9Imh0dHA6Ly9vcGNmb3VuZGF0a W9uLm9yZy9VQS8yMDA4LzAyL1R5cGVzLnhzZCIvPgogPHhzOmNvbXBsZXhUeXBlIG5hbWU9I klTQTk1RXF1aXBtZW50RGF0YVR5cGUiPgogIDx4czphbm5vdGF0aW9uPgogICA8eHM6ZG9jd W1lbnRhdGlvbj5EZWZpbmVzIGFuIGVxdWlwbWVudCByZXNvdXJjZSBvciBhIHBpZWNlIG9mI GVxdWlwbWVudCwgYSBxdWFudGl0eSwgYW4gb3B0aW9uYWwgZGVzY3JpcHRpb24sIGFuZCBhb iBvcHRpb25hbCBjb2xsZWN0aW9uIG9mIHByb3BlcnRpZXMuPC94czpkb2N1bWVudGF0aW9uP gogIDwveHM6YW5ub3RhdGlvbj4KICA8eHM6c2VxdWVuY2U+CiAgIDx4czplbGVtZW50IG1pb k9jY3Vycz0iMCIgdHlwZT0ieHM6dW5zaWduZWRJbnQiIG5hbWU9IkVuY29kaW5nTWFzayIvP gogICA8eHM6ZWxlbWVudCBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0iMSIgdHlwZT0ieHM6c 3RyaW5nIiBuYW1lPSJJRCIvPgogICA8eHM6ZWxlbWVudCBtaW5PY2N1cnM9IjAiIG1heE9jY 3Vycz0iMSIgdHlwZT0idWE6TGlzdE9mTG9jYWxpemVkVGV4dCIgbmFtZT0iRGVzY3JpcHRpb 24iLz4KICAgPHhzOmVsZW1lbnQgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9IjEiIHR5cGU9I nhzOnN0cmluZyIgbmFtZT0iRXF1aXBtZW50VXNlIi8+CiAgIDx4czplbGVtZW50IG1pbk9jY 3Vycz0iMCIgbWF4T2NjdXJzPSIxIiB0eXBlPSJ4czpzdHJpbmciIG5hbWU9IlF1YW50aXR5I i8+CiAgIDx4czplbGVtZW50IG1pbk9jY3Vycz0iMCIgbWF4T2NjdXJzPSIxIiB0eXBlPSJ1Y TpFVUluZm9ybWF0aW9uIiBuYW1lPSJFbmdpbmVlcmluZ1VuaXRzIi8+CiAgIDx4czplbGVtZ W50IG1pbk9jY3Vycz0iMCIgbWF4T2NjdXJzPSIxIiB0eXBlPSJ0bnM6TGlzdE9mSVNBOTVQc m9wZXJ0eURhdGFUeXBlIiBuYW1lPSJQcm9wZXJ0aWVzIi8+CiAgPC94czpzZXF1ZW5jZT4KI DwveHM6Y29tcGxleFR5cGU+CiA8eHM6ZWxlbWVudCB0eXBlPSJ0bnM6SVNBOTVFcXVpcG1lb nREYXRhVHlwZSIgbmFtZT0iSVNBOTVFcXVpcG1lbnREYXRhVHlwZSIvPgogPHhzOmNvbXBsZ XhUeXBlIG5hbWU9Ikxpc3RPZklTQTk1RXF1aXBtZW50RGF0YVR5cGUiPgogIDx4czpzZXF1Z W5jZT4KICAgPHhzOmVsZW1lbnQgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9InVuYm91bmRlZ CIgdHlwZT0idG5zOklTQTk1RXF1aXBtZW50RGF0YVR5cGUiIG5hbWU9IklTQTk1RXF1aXBtZ W50RGF0YVR5cGUiIG5pbGxhYmxlPSJ0cnVlIi8+CiAgPC94czpzZXF1ZW5jZT4KIDwveHM6Y 29tcGxleFR5cGU+CiA8eHM6ZWxlbWVudCB0eXBlPSJ0bnM6TGlzdE9mSVNBOTVFcXVpcG1lb nREYXRhVHlwZSIgbmFtZT0iTGlzdE9mSVNBOTVFcXVpcG1lbnREYXRhVHlwZSIgbmlsbGFib GU9InRydWUiLz4KIDx4czpjb21wbGV4VHlwZSBuYW1lPSJJU0E5NUpvYk9yZGVyQW5kU3Rhd GVEYXRhVHlwZSI+CiAgPHhzOmFubm90YXRpb24+CiAgIDx4czpkb2N1bWVudGF0aW9uPkRlZ mluZXMgdGhlIGluZm9ybWF0aW9uIG5lZWRlZCB0byBzY2hlZHVsZSBhbmQgZXhlY3V0ZSBhI GpvYi48L3hzOmRvY3VtZW50YXRpb24+CiAgPC94czphbm5vdGF0aW9uPgogIDx4czpzZXF1Z W5jZT4KICAgPHhzOmVsZW1lbnQgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9IjEiIHR5cGU9I nRuczpJU0E5NUpvYk9yZGVyRGF0YVR5cGUiIG5hbWU9IkpvYk9yZGVyIi8+CiAgIDx4czplb GVtZW50IG1pbk9jY3Vycz0iMCIgbWF4T2NjdXJzPSIxIiB0eXBlPSJ0bnM6TGlzdE9mSVNBO TVTdGF0ZURhdGFUeXBlIiBuYW1lPSJTdGF0ZSIvPgogIDwveHM6c2VxdWVuY2U+CiA8L3hzO mNvbXBsZXhUeXBlPgogPHhzOmVsZW1lbnQgdHlwZT0idG5zOklTQTk1Sm9iT3JkZXJBbmRTd GF0ZURhdGFUeXBlIiBuYW1lPSJJU0E5NUpvYk9yZGVyQW5kU3RhdGVEYXRhVHlwZSIvPgogP HhzOmNvbXBsZXhUeXBlIG5hbWU9Ikxpc3RPZklTQTk1Sm9iT3JkZXJBbmRTdGF0ZURhdGFUe XBlIj4KICA8eHM6c2VxdWVuY2U+CiAgIDx4czplbGVtZW50IG1pbk9jY3Vycz0iMCIgbWF4T 2NjdXJzPSJ1bmJvdW5kZWQiIHR5cGU9InRuczpJU0E5NUpvYk9yZGVyQW5kU3RhdGVEYXRhV HlwZSIgbmFtZT0iSVNBOTVKb2JPcmRlckFuZFN0YXRlRGF0YVR5cGUiIG5pbGxhYmxlPSJ0c nVlIi8+CiAgPC94czpzZXF1ZW5jZT4KIDwveHM6Y29tcGxleFR5cGU+CiA8eHM6ZWxlbWVud CB0eXBlPSJ0bnM6TGlzdE9mSVNBOTVKb2JPcmRlckFuZFN0YXRlRGF0YVR5cGUiIG5hbWU9I kxpc3RPZklTQTk1Sm9iT3JkZXJBbmRTdGF0ZURhdGFUeXBlIiBuaWxsYWJsZT0idHJ1ZSIvP gogPHhzOmNvbXBsZXhUeXBlIG5hbWU9IklTQTk1Sm9iT3JkZXJEYXRhVHlwZSI+CiAgPHhzO mFubm90YXRpb24+CiAgIDx4czpkb2N1bWVudGF0aW9uPkRlZmluZXMgdGhlIGluZm9ybWF0a W9uIG5lZWRlZCB0byBzY2hlZHVsZSBhbmQgZXhlY3V0ZSBhIGpvYi48L3hzOmRvY3VtZW50Y XRpb24+CiAgPC94czphbm5vdGF0aW9uPgogIDx4czpzZXF1ZW5jZT4KICAgPHhzOmVsZW1lb nQgbWluT2NjdXJzPSIwIiB0eXBlPSJ4czp1bnNpZ25lZEludCIgbmFtZT0iRW5jb2RpbmdNY XNrIi8+CiAgIDx4czplbGVtZW50IG1pbk9jY3Vycz0iMCIgbWF4T2NjdXJzPSIxIiB0eXBlP SJ4czpzdHJpbmciIG5hbWU9IkpvYk9yZGVySUQiLz4KICAgPHhzOmVsZW1lbnQgbWluT2Njd XJzPSIwIiBtYXhPY2N1cnM9IjEiIHR5cGU9InVhOkxpc3RPZkxvY2FsaXplZFRleHQiIG5hb WU9IkRlc2NyaXB0aW9uIi8+CiAgIDx4czplbGVtZW50IG1pbk9jY3Vycz0iMCIgbWF4T2Njd XJzPSIxIiB0eXBlPSJ0bnM6TGlzdE9mSVNBOTVXb3JrTWFzdGVyRGF0YVR5cGUiIG5hbWU9I ldvcmtNYXN0ZXJJRCIvPgogICA8eHM6ZWxlbWVudCBtaW5PY2N1cnM9IjAiIG1heE9jY3Vyc z0iMSIgdHlwZT0ieHM6ZGF0ZVRpbWUiIG5hbWU9IlN0YXJ0VGltZSIvPgogICA8eHM6ZWxlb WVudCBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0iMSIgdHlwZT0ieHM6ZGF0ZVRpbWUiIG5hb WU9IkVuZFRpbWUiLz4KICAgPHhzOmVsZW1lbnQgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9I jEiIHR5cGU9InhzOnNob3J0IiBuYW1lPSJQcmlvcml0eSIvPgogICA8eHM6ZWxlbWVudCBta W5PY2N1cnM9IjAiIG1heE9jY3Vycz0iMSIgdHlwZT0idG5zOkxpc3RPZklTQTk1UGFyYW1ld GVyRGF0YVR5cGUiIG5hbWU9IkpvYk9yZGVyUGFyYW1ldGVycyIvPgogICA8eHM6ZWxlbWVud CBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0iMSIgdHlwZT0idG5zOkxpc3RPZklTQTk1UGVyc 29ubmVsRGF0YVR5cGUiIG5hbWU9IlBlcnNvbm5lbFJlcXVpcmVtZW50cyIvPgogICA8eHM6Z WxlbWVudCBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0iMSIgdHlwZT0idG5zOkxpc3RPZklTQ Tk1RXF1aXBtZW50RGF0YVR5cGUiIG5hbWU9IkVxdWlwbWVudFJlcXVpcmVtZW50cyIvPgogI CA8eHM6ZWxlbWVudCBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0iMSIgdHlwZT0idG5zOkxpc 3RPZklTQTk1UGh5c2ljYWxBc3NldERhdGFUeXBlIiBuYW1lPSJQaHlzaWNhbEFzc2V0UmVxd WlyZW1lbnRzIi8+CiAgIDx4czplbGVtZW50IG1pbk9jY3Vycz0iMCIgbWF4T2NjdXJzPSIxI iB0eXBlPSJ0bnM6TGlzdE9mSVNBOTVNYXRlcmlhbERhdGFUeXBlIiBuYW1lPSJNYXRlcmlhb FJlcXVpcmVtZW50cyIvPgogIDwveHM6c2VxdWVuY2U+CiA8L3hzOmNvbXBsZXhUeXBlPgogP HhzOmVsZW1lbnQgdHlwZT0idG5zOklTQTk1Sm9iT3JkZXJEYXRhVHlwZSIgbmFtZT0iSVNBO TVKb2JPcmRlckRhdGFUeXBlIi8+CiA8eHM6Y29tcGxleFR5cGUgbmFtZT0iTGlzdE9mSVNBO TVKb2JPcmRlckRhdGFUeXBlIj4KICA8eHM6c2VxdWVuY2U+CiAgIDx4czplbGVtZW50IG1pb k9jY3Vycz0iMCIgbWF4T2NjdXJzPSJ1bmJvdW5kZWQiIHR5cGU9InRuczpJU0E5NUpvYk9yZ GVyRGF0YVR5cGUiIG5hbWU9IklTQTk1Sm9iT3JkZXJEYXRhVHlwZSIgbmlsbGFibGU9InRyd WUiLz4KICA8L3hzOnNlcXVlbmNlPgogPC94czpjb21wbGV4VHlwZT4KIDx4czplbGVtZW50I HR5cGU9InRuczpMaXN0T2ZJU0E5NUpvYk9yZGVyRGF0YVR5cGUiIG5hbWU9Ikxpc3RPZklTQ Tk1Sm9iT3JkZXJEYXRhVHlwZSIgbmlsbGFibGU9InRydWUiLz4KIDx4czpjb21wbGV4VHlwZ SBuYW1lPSJJU0E5NUpvYlJlc3BvbnNlRGF0YVR5cGUiPgogIDx4czphbm5vdGF0aW9uPgogI CA8eHM6ZG9jdW1lbnRhdGlvbj5EZWZpbmVzIHRoZSBpbmZvcm1hdGlvbiBuZWVkZWQgdG8gc 2NoZWR1bGUgYW5kIGV4ZWN1dGUgYSBqb2IuPC94czpkb2N1bWVudGF0aW9uPgogIDwveHM6Y W5ub3RhdGlvbj4KICA8eHM6c2VxdWVuY2U+CiAgIDx4czplbGVtZW50IG1pbk9jY3Vycz0iM CIgdHlwZT0ieHM6dW5zaWduZWRJbnQiIG5hbWU9IkVuY29kaW5nTWFzayIvPgogICA8eHM6Z WxlbWVudCBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0iMSIgdHlwZT0ieHM6c3RyaW5nIiBuY W1lPSJKb2JSZXNwb25zZUlEIi8+CiAgIDx4czplbGVtZW50IG1pbk9jY3Vycz0iMCIgbWF4T 2NjdXJzPSIxIiB0eXBlPSJ1YTpMb2NhbGl6ZWRUZXh0IiBuYW1lPSJEZXNjcmlwdGlvbiIvP gogICA8eHM6ZWxlbWVudCBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0iMSIgdHlwZT0ieHM6c 3RyaW5nIiBuYW1lPSJKb2JPcmRlcklEIi8+CiAgIDx4czplbGVtZW50IG1pbk9jY3Vycz0iM CIgbWF4T2NjdXJzPSIxIiB0eXBlPSJ4czpkYXRlVGltZSIgbmFtZT0iU3RhcnRUaW1lIi8+C iAgIDx4czplbGVtZW50IG1pbk9jY3Vycz0iMCIgbWF4T2NjdXJzPSIxIiB0eXBlPSJ4czpkY XRlVGltZSIgbmFtZT0iRW5kVGltZSIvPgogICA8eHM6ZWxlbWVudCBtaW5PY2N1cnM9IjAiI G1heE9jY3Vycz0iMSIgdHlwZT0idG5zOkxpc3RPZklTQTk1U3RhdGVEYXRhVHlwZSIgbmFtZ T0iSm9iU3RhdGUiLz4KICAgPHhzOmVsZW1lbnQgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9I jEiIHR5cGU9InRuczpMaXN0T2ZJU0E5NVBhcmFtZXRlckRhdGFUeXBlIiBuYW1lPSJKb2JSZ XNwb25zZURhdGEiLz4KICAgPHhzOmVsZW1lbnQgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9I jEiIHR5cGU9InRuczpMaXN0T2ZJU0E5NVBlcnNvbm5lbERhdGFUeXBlIiBuYW1lPSJQZXJzb 25uZWxBY3R1YWxzIi8+CiAgIDx4czplbGVtZW50IG1pbk9jY3Vycz0iMCIgbWF4T2NjdXJzP SIxIiB0eXBlPSJ0bnM6TGlzdE9mSVNBOTVFcXVpcG1lbnREYXRhVHlwZSIgbmFtZT0iRXF1a XBtZW50QWN0dWFscyIvPgogICA8eHM6ZWxlbWVudCBtaW5PY2N1cnM9IjAiIG1heE9jY3Vyc z0iMSIgdHlwZT0idG5zOkxpc3RPZklTQTk1UGh5c2ljYWxBc3NldERhdGFUeXBlIiBuYW1lP SJQaHlzaWNhbEFzc2V0QWN0dWFscyIvPgogICA8eHM6ZWxlbWVudCBtaW5PY2N1cnM9IjAiI G1heE9jY3Vycz0iMSIgdHlwZT0idG5zOkxpc3RPZklTQTk1TWF0ZXJpYWxEYXRhVHlwZSIgb mFtZT0iTWF0ZXJpYWxBY3R1YWxzIi8+CiAgPC94czpzZXF1ZW5jZT4KIDwveHM6Y29tcGxle FR5cGU+CiA8eHM6ZWxlbWVudCB0eXBlPSJ0bnM6SVNBOTVKb2JSZXNwb25zZURhdGFUeXBlI iBuYW1lPSJJU0E5NUpvYlJlc3BvbnNlRGF0YVR5cGUiLz4KIDx4czpjb21wbGV4VHlwZSBuY W1lPSJMaXN0T2ZJU0E5NUpvYlJlc3BvbnNlRGF0YVR5cGUiPgogIDx4czpzZXF1ZW5jZT4KI CAgPHhzOmVsZW1lbnQgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9InVuYm91bmRlZCIgdHlwZ T0idG5zOklTQTk1Sm9iUmVzcG9uc2VEYXRhVHlwZSIgbmFtZT0iSVNBOTVKb2JSZXNwb25zZ URhdGFUeXBlIiBuaWxsYWJsZT0idHJ1ZSIvPgogIDwveHM6c2VxdWVuY2U+CiA8L3hzOmNvb XBsZXhUeXBlPgogPHhzOmVsZW1lbnQgdHlwZT0idG5zOkxpc3RPZklTQTk1Sm9iUmVzcG9uc 2VEYXRhVHlwZSIgbmFtZT0iTGlzdE9mSVNBOTVKb2JSZXNwb25zZURhdGFUeXBlIiBuaWxsY WJsZT0idHJ1ZSIvPgogPHhzOmNvbXBsZXhUeXBlIG5hbWU9IklTQTk1TWF0ZXJpYWxEYXRhV HlwZSI+CiAgPHhzOmFubm90YXRpb24+CiAgIDx4czpkb2N1bWVudGF0aW9uPkRlZmluZXMgY SBtYXRlcmlhbCByZXNvdXJjZSwgYSBxdWFudGl0eSwgYW4gb3B0aW9uYWwgZGVzY3JpcHRpb 24sIGFuZCBhbiBvcHRpb25hbCBjb2xsZWN0aW9uIG9mIHByb3BlcnRpZXMuPC94czpkb2N1b WVudGF0aW9uPgogIDwveHM6YW5ub3RhdGlvbj4KICA8eHM6c2VxdWVuY2U+CiAgIDx4czplb GVtZW50IG1pbk9jY3Vycz0iMCIgdHlwZT0ieHM6dW5zaWduZWRJbnQiIG5hbWU9IkVuY29ka W5nTWFzayIvPgogICA8eHM6ZWxlbWVudCBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0iMSIgd HlwZT0ieHM6c3RyaW5nIiBuYW1lPSJNYXRlcmlhbENsYXNzSUQiLz4KICAgPHhzOmVsZW1lb nQgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9IjEiIHR5cGU9InhzOnN0cmluZyIgbmFtZT0iT WF0ZXJpYWxEZWZpbml0aW9uSUQiLz4KICAgPHhzOmVsZW1lbnQgbWluT2NjdXJzPSIwIiBtY XhPY2N1cnM9IjEiIHR5cGU9InhzOnN0cmluZyIgbmFtZT0iTWF0ZXJpYWxMb3RJRCIvPgogI CA8eHM6ZWxlbWVudCBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0iMSIgdHlwZT0ieHM6c3Rya W5nIiBuYW1lPSJNYXRlcmlhbFN1YmxvdElEIi8+CiAgIDx4czplbGVtZW50IG1pbk9jY3Vyc z0iMCIgbWF4T2NjdXJzPSIxIiB0eXBlPSJ1YTpMaXN0T2ZMb2NhbGl6ZWRUZXh0IiBuYW1lP SJEZXNjcmlwdGlvbiIvPgogICA8eHM6ZWxlbWVudCBtaW5PY2N1cnM9IjAiIG1heE9jY3Vyc z0iMSIgdHlwZT0ieHM6c3RyaW5nIiBuYW1lPSJNYXRlcmlhbFVzZSIvPgogICA8eHM6ZWxlb WVudCBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0iMSIgdHlwZT0ieHM6c3RyaW5nIiBuYW1lP SJRdWFudGl0eSIvPgogICA8eHM6ZWxlbWVudCBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0iM SIgdHlwZT0idWE6RVVJbmZvcm1hdGlvbiIgbmFtZT0iRW5naW5lZXJpbmdVbml0cyIvPgogI CA8eHM6ZWxlbWVudCBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0iMSIgdHlwZT0idG5zOkxpc 3RPZklTQTk1UHJvcGVydHlEYXRhVHlwZSIgbmFtZT0iUHJvcGVydGllcyIvPgogIDwveHM6c 2VxdWVuY2U+CiA8L3hzOmNvbXBsZXhUeXBlPgogPHhzOmVsZW1lbnQgdHlwZT0idG5zOklTQ Tk1TWF0ZXJpYWxEYXRhVHlwZSIgbmFtZT0iSVNBOTVNYXRlcmlhbERhdGFUeXBlIi8+CiA8e HM6Y29tcGxleFR5cGUgbmFtZT0iTGlzdE9mSVNBOTVNYXRlcmlhbERhdGFUeXBlIj4KICA8e HM6c2VxdWVuY2U+CiAgIDx4czplbGVtZW50IG1pbk9jY3Vycz0iMCIgbWF4T2NjdXJzPSJ1b mJvdW5kZWQiIHR5cGU9InRuczpJU0E5NU1hdGVyaWFsRGF0YVR5cGUiIG5hbWU9IklTQTk1T WF0ZXJpYWxEYXRhVHlwZSIgbmlsbGFibGU9InRydWUiLz4KICA8L3hzOnNlcXVlbmNlPgogP C94czpjb21wbGV4VHlwZT4KIDx4czplbGVtZW50IHR5cGU9InRuczpMaXN0T2ZJU0E5NU1hd GVyaWFsRGF0YVR5cGUiIG5hbWU9Ikxpc3RPZklTQTk1TWF0ZXJpYWxEYXRhVHlwZSIgbmlsb GFibGU9InRydWUiLz4KIDx4czpjb21wbGV4VHlwZSBuYW1lPSJJU0E5NVBhcmFtZXRlckRhd GFUeXBlIj4KICA8eHM6YW5ub3RhdGlvbj4KICAgPHhzOmRvY3VtZW50YXRpb24+QSBzdWJ0e XBlIG9mIE9QQyBVQSBTdHJ1Y3R1cmUgdGhhdCBkZWZpbmVzIHRocmVlIGxpbmtlZCBkYXRhI Gl0ZW1zOiB0aGUgSUQsIHdoaWNoIGlzIGEgdW5pcXVlIGlkZW50aWZpZXIgZm9yIGEgcHJvc GVydHksIHRoZSB2YWx1ZSwgd2hpY2ggaXMgdGhlIGRhdGEgdGhhdCBpcyBpZGVudGlmaWVkL CBhbmQgYW4gb3B0aW9uYWwgZGVzY3JpcHRpb24gb2YgdGhlIHBhcmFtZXRlci48L3hzOmRvY 3VtZW50YXRpb24+CiAgPC94czphbm5vdGF0aW9uPgogIDx4czpzZXF1ZW5jZT4KICAgPHhzO mVsZW1lbnQgbWluT2NjdXJzPSIwIiB0eXBlPSJ4czp1bnNpZ25lZEludCIgbmFtZT0iRW5jb 2RpbmdNYXNrIi8+CiAgIDx4czplbGVtZW50IG1pbk9jY3Vycz0iMCIgbWF4T2NjdXJzPSIxI iB0eXBlPSJ4czpzdHJpbmciIG5hbWU9IklEIi8+CiAgIDx4czplbGVtZW50IG1pbk9jY3Vyc z0iMCIgbWF4T2NjdXJzPSIxIiB0eXBlPSJ1YTpWYXJpYW50IiBuYW1lPSJWYWx1ZSIvPgogI CA8eHM6ZWxlbWVudCBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0iMSIgdHlwZT0idWE6TGlzd E9mTG9jYWxpemVkVGV4dCIgbmFtZT0iRGVzY3JpcHRpb24iLz4KICAgPHhzOmVsZW1lbnQgb WluT2NjdXJzPSIwIiBtYXhPY2N1cnM9IjEiIHR5cGU9InVhOkVVSW5mb3JtYXRpb24iIG5hb WU9IkVuZ2luZWVyaW5nVW5pdHMiLz4KICAgPHhzOmVsZW1lbnQgbWluT2NjdXJzPSIwIiBtY XhPY2N1cnM9IjEiIHR5cGU9InRuczpMaXN0T2ZJU0E5NVBhcmFtZXRlckRhdGFUeXBlIiBuY W1lPSJTdWJwYXJhbWV0ZXJzIi8+CiAgPC94czpzZXF1ZW5jZT4KIDwveHM6Y29tcGxleFR5c GU+CiA8eHM6ZWxlbWVudCB0eXBlPSJ0bnM6SVNBOTVQYXJhbWV0ZXJEYXRhVHlwZSIgbmFtZ T0iSVNBOTVQYXJhbWV0ZXJEYXRhVHlwZSIvPgogPHhzOmNvbXBsZXhUeXBlIG5hbWU9Ikxpc 3RPZklTQTk1UGFyYW1ldGVyRGF0YVR5cGUiPgogIDx4czpzZXF1ZW5jZT4KICAgPHhzOmVsZ W1lbnQgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9InVuYm91bmRlZCIgdHlwZT0idG5zOklTQ Tk1UGFyYW1ldGVyRGF0YVR5cGUiIG5hbWU9IklTQTk1UGFyYW1ldGVyRGF0YVR5cGUiIG5pb GxhYmxlPSJ0cnVlIi8+CiAgPC94czpzZXF1ZW5jZT4KIDwveHM6Y29tcGxleFR5cGU+CiA8e HM6ZWxlbWVudCB0eXBlPSJ0bnM6TGlzdE9mSVNBOTVQYXJhbWV0ZXJEYXRhVHlwZSIgbmFtZ T0iTGlzdE9mSVNBOTVQYXJhbWV0ZXJEYXRhVHlwZSIgbmlsbGFibGU9InRydWUiLz4KIDx4c zpjb21wbGV4VHlwZSBuYW1lPSJJU0E5NVBlcnNvbm5lbERhdGFUeXBlIj4KICA8eHM6YW5ub 3RhdGlvbj4KICAgPHhzOmRvY3VtZW50YXRpb24+RGVmaW5lcyBhIHBlcnNvbm5lbCByZXNvd XJjZSBvciBhIHBlcnNvbiwgYSBxdWFudGl0eSwgYW4gb3B0aW9uYWwgZGVzY3JpcHRpb24sI GFuZCBhbiBvcHRpb25hbCBjb2xsZWN0aW9uIG9mIHByb3BlcnRpZXMuPC94czpkb2N1bWVud GF0aW9uPgogIDwveHM6YW5ub3RhdGlvbj4KICA8eHM6c2VxdWVuY2U+CiAgIDx4czplbGVtZ W50IG1pbk9jY3Vycz0iMCIgdHlwZT0ieHM6dW5zaWduZWRJbnQiIG5hbWU9IkVuY29kaW5nT WFzayIvPgogICA8eHM6ZWxlbWVudCBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0iMSIgdHlwZ T0ieHM6c3RyaW5nIiBuYW1lPSJJRCIvPgogICA8eHM6ZWxlbWVudCBtaW5PY2N1cnM9IjAiI G1heE9jY3Vycz0iMSIgdHlwZT0idWE6TGlzdE9mTG9jYWxpemVkVGV4dCIgbmFtZT0iRGVzY 3JpcHRpb24iLz4KICAgPHhzOmVsZW1lbnQgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9IjEiI HR5cGU9InhzOnN0cmluZyIgbmFtZT0iUGVyc29ubmVsVXNlIi8+CiAgIDx4czplbGVtZW50I G1pbk9jY3Vycz0iMCIgbWF4T2NjdXJzPSIxIiB0eXBlPSJ4czpzdHJpbmciIG5hbWU9IlF1Y W50aXR5Ii8+CiAgIDx4czplbGVtZW50IG1pbk9jY3Vycz0iMCIgbWF4T2NjdXJzPSIxIiB0e XBlPSJ1YTpFVUluZm9ybWF0aW9uIiBuYW1lPSJFbmdpbmVlcmluZ1VuaXRzIi8+CiAgIDx4c zplbGVtZW50IG1pbk9jY3Vycz0iMCIgbWF4T2NjdXJzPSIxIiB0eXBlPSJ0bnM6TGlzdE9mS VNBOTVQcm9wZXJ0eURhdGFUeXBlIiBuYW1lPSJQcm9wZXJ0aWVzIi8+CiAgPC94czpzZXF1Z W5jZT4KIDwveHM6Y29tcGxleFR5cGU+CiA8eHM6ZWxlbWVudCB0eXBlPSJ0bnM6SVNBOTVQZ XJzb25uZWxEYXRhVHlwZSIgbmFtZT0iSVNBOTVQZXJzb25uZWxEYXRhVHlwZSIvPgogPHhzO mNvbXBsZXhUeXBlIG5hbWU9Ikxpc3RPZklTQTk1UGVyc29ubmVsRGF0YVR5cGUiPgogIDx4c zpzZXF1ZW5jZT4KICAgPHhzOmVsZW1lbnQgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9InVuY m91bmRlZCIgdHlwZT0idG5zOklTQTk1UGVyc29ubmVsRGF0YVR5cGUiIG5hbWU9IklTQTk1U GVyc29ubmVsRGF0YVR5cGUiIG5pbGxhYmxlPSJ0cnVlIi8+CiAgPC94czpzZXF1ZW5jZT4KI DwveHM6Y29tcGxleFR5cGU+CiA8eHM6ZWxlbWVudCB0eXBlPSJ0bnM6TGlzdE9mSVNBOTVQZ XJzb25uZWxEYXRhVHlwZSIgbmFtZT0iTGlzdE9mSVNBOTVQZXJzb25uZWxEYXRhVHlwZSIgb mlsbGFibGU9InRydWUiLz4KIDx4czpjb21wbGV4VHlwZSBuYW1lPSJJU0E5NVBoeXNpY2FsQ XNzZXREYXRhVHlwZSI+CiAgPHhzOmFubm90YXRpb24+CiAgIDx4czpkb2N1bWVudGF0aW9uP kRlZmluZXMgYSBwaHlzaWNhbCBhc3NldCwgYSBxdWFudGl0eSwgYW4gb3B0aW9uYWwgZGVzY 3JpcHRpb24sIGFuZCBhbiBvcHRpb25hbCBjb2xsZWN0aW9uIG9mIHByb3BlcnRpZXMuPC94c zpkb2N1bWVudGF0aW9uPgogIDwveHM6YW5ub3RhdGlvbj4KICA8eHM6c2VxdWVuY2U+CiAgI Dx4czplbGVtZW50IG1pbk9jY3Vycz0iMCIgdHlwZT0ieHM6dW5zaWduZWRJbnQiIG5hbWU9I kVuY29kaW5nTWFzayIvPgogICA8eHM6ZWxlbWVudCBtaW5PY2N1cnM9IjAiIG1heE9jY3Vyc z0iMSIgdHlwZT0ieHM6c3RyaW5nIiBuYW1lPSJJRCIvPgogICA8eHM6ZWxlbWVudCBtaW5PY 2N1cnM9IjAiIG1heE9jY3Vycz0iMSIgdHlwZT0idWE6TGlzdE9mTG9jYWxpemVkVGV4dCIgb mFtZT0iRGVzY3JpcHRpb24iLz4KICAgPHhzOmVsZW1lbnQgbWluT2NjdXJzPSIwIiBtYXhPY 2N1cnM9IjEiIHR5cGU9InhzOnN0cmluZyIgbmFtZT0iUGh5c2ljYWxBc3NldFVzZSIvPgogI CA8eHM6ZWxlbWVudCBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0iMSIgdHlwZT0ieHM6c3Rya W5nIiBuYW1lPSJRdWFudGl0eSIvPgogICA8eHM6ZWxlbWVudCBtaW5PY2N1cnM9IjAiIG1he E9jY3Vycz0iMSIgdHlwZT0idWE6RVVJbmZvcm1hdGlvbiIgbmFtZT0iRW5naW5lZXJpbmdVb ml0cyIvPgogICA8eHM6ZWxlbWVudCBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0iMSIgdHlwZ T0idG5zOkxpc3RPZklTQTk1UHJvcGVydHlEYXRhVHlwZSIgbmFtZT0iUHJvcGVydGllcyIvP gogIDwveHM6c2VxdWVuY2U+CiA8L3hzOmNvbXBsZXhUeXBlPgogPHhzOmVsZW1lbnQgdHlwZ T0idG5zOklTQTk1UGh5c2ljYWxBc3NldERhdGFUeXBlIiBuYW1lPSJJU0E5NVBoeXNpY2FsQ XNzZXREYXRhVHlwZSIvPgogPHhzOmNvbXBsZXhUeXBlIG5hbWU9Ikxpc3RPZklTQTk1UGh5c 2ljYWxBc3NldERhdGFUeXBlIj4KICA8eHM6c2VxdWVuY2U+CiAgIDx4czplbGVtZW50IG1pb k9jY3Vycz0iMCIgbWF4T2NjdXJzPSJ1bmJvdW5kZWQiIHR5cGU9InRuczpJU0E5NVBoeXNpY 2FsQXNzZXREYXRhVHlwZSIgbmFtZT0iSVNBOTVQaHlzaWNhbEFzc2V0RGF0YVR5cGUiIG5pb GxhYmxlPSJ0cnVlIi8+CiAgPC94czpzZXF1ZW5jZT4KIDwveHM6Y29tcGxleFR5cGU+CiA8e HM6ZWxlbWVudCB0eXBlPSJ0bnM6TGlzdE9mSVNBOTVQaHlzaWNhbEFzc2V0RGF0YVR5cGUiI G5hbWU9Ikxpc3RPZklTQTk1UGh5c2ljYWxBc3NldERhdGFUeXBlIiBuaWxsYWJsZT0idHJ1Z SIvPgogPHhzOmNvbXBsZXhUeXBlIG5hbWU9IklTQTk1UHJvcGVydHlEYXRhVHlwZSI+CiAgP HhzOmFubm90YXRpb24+CiAgIDx4czpkb2N1bWVudGF0aW9uPkEgc3VidHlwZSBvZiBPUEMgV UEgU3RydWN0dXJlIHRoYXQgZGVmaW5lcyB0d28gbGlua2VkIGRhdGEgaXRlbXM6IGFuIElEL CB3aGljaCBpcyBhIHVuaXF1ZSBpZGVudGlmaWVyIGZvciBhIHByb3BlcnR5IHdpdGhpbiB0a GUgc2NvcGUgb2YgdGhlIGFzc29jaWF0ZWQgcmVzb3VyY2UsIGFuZCB0aGUgdmFsdWUsIHdoa WNoIGlzIHRoZSBkYXRhIGZvciB0aGUgcHJvcGVydHkuPC94czpkb2N1bWVudGF0aW9uPgogI DwveHM6YW5ub3RhdGlvbj4KICA8eHM6c2VxdWVuY2U+CiAgIDx4czplbGVtZW50IG1pbk9jY 3Vycz0iMCIgdHlwZT0ieHM6dW5zaWduZWRJbnQiIG5hbWU9IkVuY29kaW5nTWFzayIvPgogI CA8eHM6ZWxlbWVudCBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0iMSIgdHlwZT0ieHM6c3Rya W5nIiBuYW1lPSJJRCIvPgogICA8eHM6ZWxlbWVudCBtaW5PY2N1cnM9IjAiIG1heE9jY3Vyc z0iMSIgdHlwZT0idWE6VmFyaWFudCIgbmFtZT0iVmFsdWUiLz4KICAgPHhzOmVsZW1lbnQgb WluT2NjdXJzPSIwIiBtYXhPY2N1cnM9IjEiIHR5cGU9InVhOkxpc3RPZkxvY2FsaXplZFRle HQiIG5hbWU9IkRlc2NyaXB0aW9uIi8+CiAgIDx4czplbGVtZW50IG1pbk9jY3Vycz0iMCIgb WF4T2NjdXJzPSIxIiB0eXBlPSJ1YTpFVUluZm9ybWF0aW9uIiBuYW1lPSJFbmdpbmVlcmluZ 1VuaXRzIi8+CiAgIDx4czplbGVtZW50IG1pbk9jY3Vycz0iMCIgbWF4T2NjdXJzPSIxIiB0e XBlPSJ0bnM6TGlzdE9mSVNBOTVQcm9wZXJ0eURhdGFUeXBlIiBuYW1lPSJTdWJwcm9wZXJ0a WVzIi8+CiAgPC94czpzZXF1ZW5jZT4KIDwveHM6Y29tcGxleFR5cGU+CiA8eHM6ZWxlbWVud CB0eXBlPSJ0bnM6SVNBOTVQcm9wZXJ0eURhdGFUeXBlIiBuYW1lPSJJU0E5NVByb3BlcnR5R GF0YVR5cGUiLz4KIDx4czpjb21wbGV4VHlwZSBuYW1lPSJMaXN0T2ZJU0E5NVByb3BlcnR5R GF0YVR5cGUiPgogIDx4czpzZXF1ZW5jZT4KICAgPHhzOmVsZW1lbnQgbWluT2NjdXJzPSIwI iBtYXhPY2N1cnM9InVuYm91bmRlZCIgdHlwZT0idG5zOklTQTk1UHJvcGVydHlEYXRhVHlwZ SIgbmFtZT0iSVNBOTVQcm9wZXJ0eURhdGFUeXBlIiBuaWxsYWJsZT0idHJ1ZSIvPgogIDwve HM6c2VxdWVuY2U+CiA8L3hzOmNvbXBsZXhUeXBlPgogPHhzOmVsZW1lbnQgdHlwZT0idG5zO kxpc3RPZklTQTk1UHJvcGVydHlEYXRhVHlwZSIgbmFtZT0iTGlzdE9mSVNBOTVQcm9wZXJ0e URhdGFUeXBlIiBuaWxsYWJsZT0idHJ1ZSIvPgogPHhzOmNvbXBsZXhUeXBlIG5hbWU9IklTQ Tk1U3RhdGVEYXRhVHlwZSI+CiAgPHhzOmFubm90YXRpb24+CiAgIDx4czpkb2N1bWVudGF0a W9uPkRlZmluZXMgdGhlIGluZm9ybWF0aW9uIG5lZWRlZCB0byBzY2hlZHVsZSBhbmQgZXhlY 3V0ZSBhIGpvYi48L3hzOmRvY3VtZW50YXRpb24+CiAgPC94czphbm5vdGF0aW9uPgogIDx4c zpzZXF1ZW5jZT4KICAgPHhzOmVsZW1lbnQgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9IjEiI HR5cGU9InVhOlJlbGF0aXZlUGF0aCIgbmFtZT0iQnJvd3NlUGF0aCIvPgogICA8eHM6ZWxlb WVudCBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0iMSIgdHlwZT0idWE6TG9jYWxpemVkVGV4d CIgbmFtZT0iU3RhdGVUZXh0Ii8+CiAgIDx4czplbGVtZW50IG1pbk9jY3Vycz0iMCIgbWF4T 2NjdXJzPSIxIiB0eXBlPSJ4czp1bnNpZ25lZEludCIgbmFtZT0iU3RhdGVOdW1iZXIiLz4KI CA8L3hzOnNlcXVlbmNlPgogPC94czpjb21wbGV4VHlwZT4KIDx4czplbGVtZW50IHR5cGU9I nRuczpJU0E5NVN0YXRlRGF0YVR5cGUiIG5hbWU9IklTQTk1U3RhdGVEYXRhVHlwZSIvPgogP HhzOmNvbXBsZXhUeXBlIG5hbWU9Ikxpc3RPZklTQTk1U3RhdGVEYXRhVHlwZSI+CiAgPHhzO nNlcXVlbmNlPgogICA8eHM6ZWxlbWVudCBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0idW5ib 3VuZGVkIiB0eXBlPSJ0bnM6SVNBOTVTdGF0ZURhdGFUeXBlIiBuYW1lPSJJU0E5NVN0YXRlR GF0YVR5cGUiIG5pbGxhYmxlPSJ0cnVlIi8+CiAgPC94czpzZXF1ZW5jZT4KIDwveHM6Y29tc GxleFR5cGU+CiA8eHM6ZWxlbWVudCB0eXBlPSJ0bnM6TGlzdE9mSVNBOTVTdGF0ZURhdGFUe XBlIiBuYW1lPSJMaXN0T2ZJU0E5NVN0YXRlRGF0YVR5cGUiIG5pbGxhYmxlPSJ0cnVlIi8+C iA8eHM6Y29tcGxleFR5cGUgbmFtZT0iSVNBOTVXb3JrTWFzdGVyRGF0YVR5cGUiPgogIDx4c zphbm5vdGF0aW9uPgogICA8eHM6ZG9jdW1lbnRhdGlvbj5EZWZpbmVzIGEgV29yayBNYXN0Z XIgSUQgYW5kIHRoZSBkZWZpbmVkIHBhcmFtZXRlcnMgZm9yIHRoZSBXb3JrIE1hc3Rlci48L 3hzOmRvY3VtZW50YXRpb24+CiAgPC94czphbm5vdGF0aW9uPgogIDx4czpzZXF1ZW5jZT4KI CAgPHhzOmVsZW1lbnQgbWluT2NjdXJzPSIwIiB0eXBlPSJ4czp1bnNpZ25lZEludCIgbmFtZ T0iRW5jb2RpbmdNYXNrIi8+CiAgIDx4czplbGVtZW50IG1pbk9jY3Vycz0iMCIgbWF4T2Njd XJzPSIxIiB0eXBlPSJ4czpzdHJpbmciIG5hbWU9IklEIi8+CiAgIDx4czplbGVtZW50IG1pb k9jY3Vycz0iMCIgbWF4T2NjdXJzPSIxIiB0eXBlPSJ1YTpMb2NhbGl6ZWRUZXh0IiBuYW1lP SJEZXNjcmlwdGlvbiIvPgogICA8eHM6ZWxlbWVudCBtaW5PY2N1cnM9IjAiIG1heE9jY3Vyc z0iMSIgdHlwZT0idG5zOkxpc3RPZklTQTk1UGFyYW1ldGVyRGF0YVR5cGUiIG5hbWU9IlBhc mFtZXRlcnMiLz4KICA8L3hzOnNlcXVlbmNlPgogPC94czpjb21wbGV4VHlwZT4KIDx4czplb GVtZW50IHR5cGU9InRuczpJU0E5NVdvcmtNYXN0ZXJEYXRhVHlwZSIgbmFtZT0iSVNBOTVXb 3JrTWFzdGVyRGF0YVR5cGUiLz4KIDx4czpjb21wbGV4VHlwZSBuYW1lPSJMaXN0T2ZJU0E5N VdvcmtNYXN0ZXJEYXRhVHlwZSI+CiAgPHhzOnNlcXVlbmNlPgogICA8eHM6ZWxlbWVudCBta W5PY2N1cnM9IjAiIG1heE9jY3Vycz0idW5ib3VuZGVkIiB0eXBlPSJ0bnM6SVNBOTVXb3JrT WFzdGVyRGF0YVR5cGUiIG5hbWU9IklTQTk1V29ya01hc3RlckRhdGFUeXBlIiBuaWxsYWJsZ T0idHJ1ZSIvPgogIDwveHM6c2VxdWVuY2U+CiA8L3hzOmNvbXBsZXhUeXBlPgogPHhzOmVsZ W1lbnQgdHlwZT0idG5zOkxpc3RPZklTQTk1V29ya01hc3RlckRhdGFUeXBlIiBuYW1lPSJMa XN0T2ZJU0E5NVdvcmtNYXN0ZXJEYXRhVHlwZSIgbmlsbGFibGU9InRydWUiLz4KPC94czpzY 2hlbWE+Cg== NamespaceUri i=68 ns=1;i=6020 http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/Types.xsd ISA95JobOrderStatusEventType ISA-95 Job Control Job Response Provider Job Order Status Events https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.6 ns=1;i=1003 ns=1;i=6047 ns=1;i=6049 ns=1;i=6048 i=2041 ns=1;i=5041 ns=1;i=5042 ns=1;i=5043 ns=1;i=5044 ns=1;i=5045 ns=1;i=5046 ns=1;i=5047 ns=1;i=5048 ns=1;i=5049 ns=1;i=5050 ns=1;i=5051 ns=1;i=5069 ns=1;i=5070 ns=1;i=5071 ns=1;i=5072 ns=1;i=5073 ns=1;i=5074 ns=1;i=5075 ns=1;i=5076 ns=1;i=5077 ns=1;i=5078 ns=1;i=5079 ns=1;i=5084 ns=1;i=5085 ns=1;i=5086 ns=1;i=5087 JobOrder i=68 i=78 ns=1;i=1006 JobResponse i=68 i=78 ns=1;i=1006 JobState i=68 i=78 ns=1;i=1006 ISA95JobResponseProviderObjectType The OPENSCSJobResponseProviderObjectType contains a method to receive unsolicited job response requests. ISA-95 Job Response Provider V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.7/#7.2.7.1 ns=1;i=1006 ns=1;i=6050 ns=1;i=7002 i=58 ns=1;i=7014 JobOrderResponseList i=63 i=80 ns=1;i=1003 RequestJobResponseByJobOrderID https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.7/#7.2.7.2 i=78 ns=1;i=6042 ns=1;i=6043 ns=1;i=1003 InputArguments i=68 i=78 ns=1;i=7002 i=297 JobOrderID i=12 -1 Contains an ID of the job order, as specified by the method caller. OutputArguments i=68 i=78 ns=1;i=7002 i=297 JobResponse ns=1;i=3013 -1 Contains information about the execution of a job order, such as the current status of the job, actual material consumed, actual material produced, actual equipment used, and job specific data. i=297 ReturnStatus i=9 -1 Returns the status of the method execution. RequestJobResponseByJobOrderState https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.7/#7.2.7.3 i=78 ns=1;i=6016 ns=1;i=6017 ns=1;i=1003 InputArguments i=78 i=68 ns=1;i=7014 i=297 JobOrderState ns=1;i=3006 1 0 Contains a job status of the JobResponse to be returned. The array shall provide at least one entry representing the top level state and potentially additional entries representing substates. The first entry shall be the top level entry, having the BrowsePath set to null. The order of the substates is not defined. OutputArguments i=78 i=68 ns=1;i=7014 i=297 JobResponses ns=1;i=3013 1 0 Contains a list of information about the execution of a job order, such as the current status of the job, actual material consumed, actual material produced, actual equipment used, and job specific data. i=297 ReturnStatus i=9 -1 Returns the status of the method execution. ISA95JobResponseReceiverObjectType A Job Response Receiver receives unsolicited Job Responses, usually as the result of completion of a job, or at intermediate points within the job. ISA-95 Job Response Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.8/#7.2.8.1 ns=1;i=7003 i=58 ReceiveJobResponse https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.8/#7.2.8.2 i=78 ns=1;i=6044 ns=1;i=6045 ns=1;i=1004 InputArguments i=68 i=78 ns=1;i=7003 i=297 JobResponse ns=1;i=3013 -1 Contains information about the execution of a job order, such as actual material consumed, actual material produced, actual equipment used, and job specific data. OutputArguments i=68 i=78 ns=1;i=7003 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. ISA95EndedStateMachineType ISA-95 Job Control Job Order Receiver SubStates https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.4 ns=1;i=5057 ns=1;i=5056 ns=1;i=5058 i=2771 Closed The job order has been completed and no further post processing is performed. i=2307 ns=1;i=1005 ns=1;i=6094 ns=1;i=5058 StateNumber i=68 i=78 ns=1;i=5057 2 Completed The job order has been completed and is no longer in execution. i=2307 ns=1;i=1005 ns=1;i=6093 ns=1;i=5058 StateNumber i=68 i=78 ns=1;i=5056 1 FromCompletedToClosed This transition is triggered when the system has finalized post processing of a ended job order. i=2310 ns=1;i=5057 ns=1;i=5056 ns=1;i=1005 ns=1;i=6095 TransitionNumber i=68 i=78 ns=1;i=5058 1 ISA95InterruptedStateMachineType ISA-95 Job Control Job Order Receiver SubStates https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.5 ns=1;i=5061 ns=1;i=5062 ns=1;i=5059 ns=1;i=5060 i=2771 FromHeldToSuspended This transition is triggered when the system has switched the job order from internally held to externally suspended, for example by a call of the Pause Method. i=2310 ns=1;i=1007 ns=1;i=5059 ns=1;i=5060 ns=1;i=6098 TransitionNumber i=68 i=78 ns=1;i=5061 1 FromSuspendedToHeld This transition is triggered when the system has switched the job order from externally suspended to an internal held, for example by a call of the Resume Method. i=2310 ns=1;i=1007 ns=1;i=5059 ns=1;i=5060 ns=1;i=6099 TransitionNumber i=68 i=78 ns=1;i=5062 2 Held The job order has been temporarily stopped due to a constraint of some form. i=2307 ns=1;i=1007 ns=1;i=6096 ns=1;i=5061 ns=1;i=5062 StateNumber i=68 i=78 ns=1;i=5059 1 Suspended The job order has been temporarily stopped due to a deliberate decision within the execution system. i=2307 ns=1;i=6097 ns=1;i=1007 ns=1;i=5061 ns=1;i=5062 StateNumber i=68 i=78 ns=1;i=5060 2 ISA95JobOrderReceiverObjectType The OPENSCSJobOrderReciverObjectType contains a method to receive job order commands and optional definitions of allowable job order information ISA-95 Job Order Receiver V2 https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.2 ns=1;i=7010 ns=1;i=5040 ns=1;i=5036 ns=1;i=7011 ns=1;i=7012 ns=1;i=5039 ns=1;i=6037 ns=1;i=5085 ns=1;i=5044 ns=1;i=5043 ns=1;i=5045 ns=1;i=5049 ns=1;i=5051 ns=1;i=5050 ns=1;i=5084 ns=1;i=5042 ns=1;i=5041 ns=1;i=5048 ns=1;i=5047 ns=1;i=5046 ns=1;i=5038 ns=1;i=6033 ns=1;i=6035 ns=1;i=6036 ns=1;i=6088 ns=1;i=5035 ns=1;i=7007 ns=1;i=6039 ns=1;i=6038 ns=1;i=7008 ns=1;i=7013 ns=1;i=5037 ns=1;i=7005 ns=1;i=7006 ns=1;i=7001 ns=1;i=7004 ns=1;i=7009 ns=1;i=6034 i=2771 Abort https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.10 i=80 ns=1;i=1002 ns=1;i=5048 ns=1;i=5049 ns=1;i=5076 ns=1;i=5077 ns=1;i=5084 ns=1;i=5085 ns=1;i=5086 ns=1;i=5087 ns=1;i=6063 ns=1;i=6064 InputArguments i=68 i=78 ns=1;i=7010 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. OutputArguments i=68 i=78 ns=1;i=7010 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. Aborted The job order is aborted. i=2307 ns=1;i=1002 ns=1;i=6076 ns=1;i=5048 ns=1;i=5049 ns=1;i=5084 ns=1;i=5085 StateNumber i=68 i=78 ns=1;i=5040 6 AllowedToStart The job order is stored and may be executed. i=2307 ns=1;i=1002 ns=1;i=6072 ns=1;i=5042 ns=1;i=5043 ns=1;i=5044 ns=1;i=5044 ns=1;i=5045 ns=1;i=5085 StateNumber i=68 i=78 ns=1;i=5036 2 Cancel https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.12 i=80 ns=1;i=1002 ns=1;i=6065 ns=1;i=6066 InputArguments i=68 i=78 ns=1;i=7011 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. OutputArguments i=68 i=78 ns=1;i=7011 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. Clear https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.13 i=80 ns=1;i=1002 ns=1;i=6067 ns=1;i=6068 InputArguments i=68 i=78 ns=1;i=7012 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. OutputArguments i=68 i=78 ns=1;i=7012 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. Ended The job order has been completed and is no longer in execution. i=2307 ns=1;i=1002 ns=1;i=6075 ns=1;i=5047 ns=1;i=5051 StateNumber i=68 i=78 ns=1;i=5039 5 EquipmentID Defines a read-only set of Equipment Class IDs and Equipment IDs that may be specified in a job order. i=78 i=63 ns=1;i=1002 FromAllowedToStartToAborted This transition is triggered when Abort Method is called. i=2310 ns=1;i=7010 ns=1;i=5040 ns=1;i=5036 ns=1;i=1002 ns=1;i=1006 ns=1;i=6010 TransitionNumber i=78 i=68 ns=1;i=5085 13 FromAllowedToStartToAllowedToStart This transition is triggered when the Update Method is called and the job order is modified. i=2310 ns=1;i=5036 ns=1;i=5036 ns=1;i=1002 ns=1;i=1006 ns=1;i=6080 ns=1;i=7009 TransitionNumber i=68 i=78 ns=1;i=5044 4 FromAllowedToStartToNotAllowedToStart This transition is triggered when the RevokeStart Method is called. i=2310 ns=1;i=5036 ns=1;i=1002 ns=1;i=1006 ns=1;i=5035 ns=1;i=7013 ns=1;i=6079 TransitionNumber i=68 i=78 ns=1;i=5043 3 FromAllowedToStartToRunning This transition is triggered when a job order is started to be executed. i=2310 ns=1;i=5036 ns=1;i=1002 ns=1;i=1006 ns=1;i=5037 ns=1;i=6081 TransitionNumber i=68 i=78 ns=1;i=5045 5 FromInterruptedToAborted This transition is triggered when Abort Method is called. i=2310 ns=1;i=7010 ns=1;i=5040 ns=1;i=1002 ns=1;i=5038 ns=1;i=1006 ns=1;i=6085 TransitionNumber i=68 i=78 ns=1;i=5049 9 FromInterruptedToEnded This transition is triggered when Stop Method is called. i=2310 ns=1;i=5039 ns=1;i=1002 ns=1;i=5038 ns=1;i=1006 ns=1;i=7006 ns=1;i=6087 TransitionNumber i=68 i=78 ns=1;i=5051 11 FromInterruptedToRunning This transition is triggered when Resume Method is called. i=2310 ns=1;i=1002 ns=1;i=5038 ns=1;i=1006 ns=1;i=7008 ns=1;i=5037 ns=1;i=6086 TransitionNumber i=68 i=78 ns=1;i=5050 10 FromNotAllowedToStartToAborted This transition is triggered when Abort Method is called. i=2310 ns=1;i=7010 ns=1;i=5040 ns=1;i=1002 ns=1;i=1006 ns=1;i=5035 ns=1;i=6009 TransitionNumber i=78 i=68 ns=1;i=5084 12 FromNotAllowedToStartToAllowedToStart This transition is triggered when the Start Method is called. i=2310 ns=1;i=5036 ns=1;i=1002 ns=1;i=1006 ns=1;i=5035 ns=1;i=7005 ns=1;i=6078 TransitionNumber i=68 i=78 ns=1;i=5042 2 FromNotAllowedToStartToNotAllowedToStart This transition is triggered when the Update Method is called and the job order is modified. i=2310 ns=1;i=1002 ns=1;i=1006 ns=1;i=5035 ns=1;i=5035 ns=1;i=6077 ns=1;i=7009 TransitionNumber i=68 i=78 ns=1;i=5041 1 FromRunningToAborted This transition is triggered when Abort Method is called. i=2310 ns=1;i=7010 ns=1;i=5040 ns=1;i=1002 ns=1;i=1006 ns=1;i=5037 ns=1;i=6084 TransitionNumber i=68 i=78 ns=1;i=5048 8 FromRunningToEnded This transition is triggered when the execution of a job order has finished, either internally or by the Stop Method. i=2310 ns=1;i=5039 ns=1;i=1002 ns=1;i=1006 ns=1;i=5037 ns=1;i=7006 ns=1;i=6083 TransitionNumber i=68 i=78 ns=1;i=5047 7 FromRunningToInterrupted This transition is triggered when an executing job order gets interrupted, either internally or by the Pause Method. i=2310 ns=1;i=1002 ns=1;i=5038 ns=1;i=1006 ns=1;i=7007 ns=1;i=5037 ns=1;i=6082 TransitionNumber i=68 i=78 ns=1;i=5046 6 Interrupted The job order has been temporarily stopped. i=2307 ns=1;i=1002 ns=1;i=6074 ns=1;i=5046 ns=1;i=5049 ns=1;i=5050 ns=1;i=5051 StateNumber i=68 i=78 ns=1;i=5038 4 JobOrderList Defines a read-only list of job order information available from the server. i=78 i=63 ns=1;i=1002 MaterialClassID Defines a read-only set of Material Classes IDs that may be specified in a job order. i=78 i=63 ns=1;i=1002 MaterialDefinitionID Defines a read-only set of Material Classes IDs that may be specified in a job order. i=78 i=63 ns=1;i=1002 MaxDownloadableJobOrders i=68 i=78 ns=1;i=1002 NotAllowedToStart The job order is stored but may not be executed. i=2307 ns=1;i=1002 ns=1;i=6071 ns=1;i=5041 ns=1;i=5041 ns=1;i=5042 ns=1;i=5043 ns=1;i=5084 StateNumber i=68 i=78 ns=1;i=5035 1 Pause https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.7 i=80 ns=1;i=6057 ns=1;i=6058 ns=1;i=1002 ns=1;i=5046 ns=1;i=5074 InputArguments i=68 i=78 ns=1;i=7007 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. OutputArguments i=68 i=78 ns=1;i=7007 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. PersonnelID Defines a read-only set of Personnel IDs and Person IDs that may be specified in a job order. i=78 i=63 ns=1;i=1002 PhysicalAssetID Defines a read-only set of Physical Asset Class IDs and Physical Asset IDs that may be specified in a job order. i=78 i=63 ns=1;i=1002 Resume https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.8 i=80 ns=1;i=6059 ns=1;i=6060 ns=1;i=1002 ns=1;i=5050 ns=1;i=5078 InputArguments i=68 i=78 ns=1;i=7008 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. OutputArguments i=68 i=78 ns=1;i=7008 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. RevokeStart https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.6 i=80 ns=1;i=6069 ns=1;i=6070 ns=1;i=1002 ns=1;i=5043 ns=1;i=5071 InputArguments i=68 i=78 ns=1;i=7013 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. OutputArguments i=68 i=78 ns=1;i=7013 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. Running The job order is executing. i=2307 ns=1;i=1002 ns=1;i=6073 ns=1;i=5045 ns=1;i=5046 ns=1;i=5047 ns=1;i=5048 ns=1;i=5050 StateNumber i=68 i=78 ns=1;i=5037 3 Start https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.5 i=80 ns=1;i=6053 ns=1;i=6054 ns=1;i=1002 ns=1;i=5042 ns=1;i=5070 InputArguments i=68 i=78 ns=1;i=7005 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. OutputArguments i=68 i=78 ns=1;i=7005 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. Stop https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.11 i=80 ns=1;i=6055 ns=1;i=6056 ns=1;i=1002 ns=1;i=5047 ns=1;i=5051 ns=1;i=5075 ns=1;i=5079 InputArguments i=68 i=78 ns=1;i=7006 i=297 JobOrderID i=12 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. OutputArguments i=68 i=78 ns=1;i=7006 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. Store https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.3 i=80 ns=1;i=6040 ns=1;i=6041 ns=1;i=1002 InputArguments i=68 i=78 ns=1;i=7001 i=297 JobOrder ns=1;i=3008 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. OutputArguments i=68 i=78 ns=1;i=7001 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. StoreAndStart https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.4 i=80 ns=1;i=6051 ns=1;i=6052 ns=1;i=1002 InputArguments i=68 i=78 ns=1;i=7004 i=297 JobOrder ns=1;i=3008 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. OutputArguments i=68 i=78 ns=1;i=7004 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. Update https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.1/#7.2.1.9 i=80 ns=1;i=6061 ns=1;i=6062 ns=1;i=1002 ns=1;i=5041 ns=1;i=5044 ns=1;i=5069 ns=1;i=5072 InputArguments i=68 i=78 ns=1;i=7009 i=297 JobOrder ns=1;i=3008 -1 Contains information defining the job order with all parameters and any material, equipment, or physical asset requirements associated with the order. i=297 Comment i=21 1 0 The comment provides a description of why the method was called. In order to provide the comment in several languages, it is an array of LocalizedText. The array may be empty, when no comment is provided. OutputArguments i=68 i=78 ns=1;i=7009 i=297 ReturnStatus i=9 -1 Returns the status of the method execution. WorkMaster Defines a read-only set of work master IDs that may be specified in a job order, and the read-only set of parameters that may be specified for a specific work master. i=78 i=63 ns=1;i=1002 ISA95JobOrderReceiverSubStatesType ISA-95 Job Control Job Order Receiver SubStates https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.2/#7.2.2.2 ns=1;i=5068 ns=1;i=5064 ns=1;i=5081 ns=1;i=5067 ns=1;i=5082 ns=1;i=5086 ns=1;i=5072 ns=1;i=5071 ns=1;i=5073 ns=1;i=5077 ns=1;i=5079 ns=1;i=5078 ns=1;i=5087 ns=1;i=5070 ns=1;i=5069 ns=1;i=5076 ns=1;i=5075 ns=1;i=5074 ns=1;i=5066 ns=1;i=5083 ns=1;i=1002 ns=1;i=5063 ns=1;i=5080 ns=1;i=5065 Aborted The job order is aborted. i=2307 ns=1;i=1008 ns=1;i=6105 ns=1;i=5076 ns=1;i=5077 ns=1;i=5086 ns=1;i=5087 StateNumber i=68 i=78 ns=1;i=5068 6 AllowedToStart The job order is stored and may be executed. i=2307 ns=1;i=1008 ns=1;i=5081 ns=1;i=6101 ns=1;i=5070 ns=1;i=5071 ns=1;i=5072 ns=1;i=5072 ns=1;i=5073 ns=1;i=5086 StateNumber i=68 i=78 ns=1;i=5064 2 AllowedToStartSubstates Substates of AllowedToStart i=80 ns=1;i=1001 ns=1;i=1008 ns=1;i=5064 ns=1;i=6003 CurrentState i=78 i=2760 ns=1;i=5081 ns=1;i=6004 Id i=78 i=68 ns=1;i=6003 Ended The job order has been completed and is no longer in execution. i=2307 ns=1;i=1008 ns=1;i=5082 ns=1;i=6104 ns=1;i=5075 ns=1;i=5079 StateNumber i=68 i=78 ns=1;i=5067 5 EndedSubstates Substates of Ended i=80 ns=1;i=1005 ns=1;i=6005 ns=1;i=1008 ns=1;i=5067 CurrentState i=78 i=2760 ns=1;i=5082 ns=1;i=6006 Id i=78 i=68 ns=1;i=6005 FromAllowedToStartToAborted This transition is triggered when Abort Method is called. i=2310 ns=1;i=7010 ns=1;i=5068 ns=1;i=5064 ns=1;i=1008 ns=1;i=1006 ns=1;i=6011 TransitionNumber i=78 i=68 ns=1;i=5086 13 FromAllowedToStartToAllowedToStart This transition is triggered when the Update Method is called and the job order is modified. i=2310 ns=1;i=5064 ns=1;i=5064 ns=1;i=1008 ns=1;i=1006 ns=1;i=6109 ns=1;i=7009 TransitionNumber i=68 i=78 ns=1;i=5072 4 FromAllowedToStartToNotAllowedToStart This transition is triggered when the RevokeStart Method is called. i=2310 ns=1;i=5064 ns=1;i=1008 ns=1;i=1006 ns=1;i=5063 ns=1;i=7013 ns=1;i=6108 TransitionNumber i=68 i=78 ns=1;i=5071 3 FromAllowedToStartToRunning This transition is triggered when a job order is started to be executed. i=2310 ns=1;i=5064 ns=1;i=1008 ns=1;i=1006 ns=1;i=5065 ns=1;i=6110 TransitionNumber i=68 i=78 ns=1;i=5073 5 FromInterruptedToAborted This transition is triggered when Abort Method is called. i=2310 ns=1;i=7010 ns=1;i=5068 ns=1;i=1008 ns=1;i=5066 ns=1;i=1006 ns=1;i=6114 TransitionNumber i=68 i=78 ns=1;i=5077 9 FromInterruptedToEnded This transition is triggered when Stop Method is called. i=2310 ns=1;i=5067 ns=1;i=1008 ns=1;i=5066 ns=1;i=1006 ns=1;i=7006 ns=1;i=6116 TransitionNumber i=68 i=78 ns=1;i=5079 11 FromInterruptedToRunning This transition is triggered when Resume Method is called. i=2310 ns=1;i=1008 ns=1;i=5066 ns=1;i=1006 ns=1;i=7008 ns=1;i=5065 ns=1;i=6115 TransitionNumber i=68 i=78 ns=1;i=5078 10 FromNotAllowedToStartToAborted This transition is triggered when Abort Method is called. i=2310 ns=1;i=7010 ns=1;i=5068 ns=1;i=1008 ns=1;i=1006 ns=1;i=5063 ns=1;i=6012 TransitionNumber i=78 i=68 ns=1;i=5087 12 FromNotAllowedToStartToAllowedToStart This transition is triggered when the Start Method is called. i=2310 ns=1;i=5064 ns=1;i=1008 ns=1;i=1006 ns=1;i=5063 ns=1;i=7005 ns=1;i=6107 TransitionNumber i=68 i=78 ns=1;i=5070 2 FromNotAllowedToStartToNotAllowedToStart This transition is triggered when the Update Method is called and the job order is modified. i=2310 ns=1;i=1008 ns=1;i=1006 ns=1;i=5063 ns=1;i=5063 ns=1;i=6106 ns=1;i=7009 TransitionNumber i=68 i=78 ns=1;i=5069 1 FromRunningToAborted This transition is triggered when Abort Method is called. i=2310 ns=1;i=7010 ns=1;i=5068 ns=1;i=1008 ns=1;i=1006 ns=1;i=5065 ns=1;i=6113 TransitionNumber i=68 i=78 ns=1;i=5076 8 FromRunningToEnded This transition is triggered when the execution of a job order has finished, either internally or by the Stop Method. i=2310 ns=1;i=5067 ns=1;i=1008 ns=1;i=1006 ns=1;i=5065 ns=1;i=7006 ns=1;i=6112 TransitionNumber i=68 i=78 ns=1;i=5075 7 FromRunningToInterrupted This transition is triggered when an executing job order gets interrupted, either internally or by the Pause Method. i=2310 ns=1;i=1008 ns=1;i=5066 ns=1;i=1006 ns=1;i=7007 ns=1;i=5065 ns=1;i=6111 TransitionNumber i=68 i=78 ns=1;i=5074 6 Interrupted The job order has been temporarily stopped. i=2307 ns=1;i=1008 ns=1;i=5083 ns=1;i=6103 ns=1;i=5074 ns=1;i=5077 ns=1;i=5078 ns=1;i=5079 StateNumber i=68 i=78 ns=1;i=5066 4 InterruptedSubstates Substates of Interrupted i=80 ns=1;i=1007 ns=1;i=6007 ns=1;i=1008 ns=1;i=5066 CurrentState i=78 i=2760 ns=1;i=5083 ns=1;i=6008 Id i=78 i=68 ns=1;i=6007 NotAllowedToStart The job order is stored but may not be executed. i=2307 ns=1;i=1008 ns=1;i=5080 ns=1;i=6100 ns=1;i=5069 ns=1;i=5069 ns=1;i=5070 ns=1;i=5071 ns=1;i=5087 StateNumber i=68 i=78 ns=1;i=5063 1 NotAllowedToStartSubstates Substates of NotAllowedToStart i=80 ns=1;i=1001 ns=1;i=6001 ns=1;i=1008 ns=1;i=5063 CurrentState i=78 i=2760 ns=1;i=5080 ns=1;i=6002 Id i=78 i=68 ns=1;i=6001 Running The job order is executing. i=2307 ns=1;i=1008 ns=1;i=6102 ns=1;i=5073 ns=1;i=5074 ns=1;i=5075 ns=1;i=5076 ns=1;i=5078 StateNumber i=68 i=78 ns=1;i=5065 3 ISA95PrepareStateMachineType ISA-95 Job Control Job Order Receiver SubStates https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/7.2.3 ns=1;i=5089 ns=1;i=5090 ns=1;i=5055 ns=1;i=5088 ns=1;i=5054 ns=1;i=5053 ns=1;i=5052 ns=1;i=5000 i=2771 FromLoadedToReady This transition is triggered when the program or configuration to execute the job order is unloaded. i=2310 ns=1;i=1001 ns=1;i=5053 ns=1;i=5052 ns=1;i=6014 TransitionNumber i=78 i=68 ns=1;i=5089 4 FromLoadedToWaiting This transition is triggered when the system is not ready to start the execution of the job order anymore. i=2310 ns=1;i=1001 ns=1;i=5053 ns=1;i=6015 ns=1;i=5000 TransitionNumber i=78 i=68 ns=1;i=5090 5 FromReadyToLoaded This transition is triggered when the program or configuration to execute the job order is loaded. i=2310 ns=1;i=1001 ns=1;i=5053 ns=1;i=5052 ns=1;i=6092 TransitionNumber i=68 i=78 ns=1;i=5055 2 FromReadyToWaiting This transition is triggered when the system is not ready to start the execution of the job order anymore. i=2310 ns=1;i=1001 ns=1;i=5052 ns=1;i=6013 ns=1;i=5000 TransitionNumber i=78 i=68 ns=1;i=5088 3 FromWaitingToReady This transition is triggered when the system is ready to start the execution of the job order. i=2310 ns=1;i=1001 ns=1;i=5052 ns=1;i=6091 ns=1;i=5000 TransitionNumber i=68 i=78 ns=1;i=5054 1 Loaded In situations where only one job may be in active memory and is able to be run, then the job is loaded in active memory, the necessary pre-conditions have been met, and the job order is ready to run, awaiting a Start command. i=2307 ns=1;i=1001 ns=1;i=6090 ns=1;i=5055 ns=1;i=5089 ns=1;i=5090 StateNumber i=68 i=78 ns=1;i=5053 3 Ready The necessary pre-conditions have been met and the job order is ready to run, awaiting a Start command. i=2307 ns=1;i=1001 ns=1;i=6089 ns=1;i=5054 ns=1;i=5055 ns=1;i=5088 ns=1;i=5089 StateNumber i=68 i=78 ns=1;i=5052 2 Waiting The necessary pre-conditions have not been met and the job order is not ready to run. i=2307 ns=1;i=6000 ns=1;i=1001 ns=1;i=5054 ns=1;i=5088 ns=1;i=5090 StateNumber i=68 i=78 ns=1;i=5000 1 http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/ https://reference.opcfoundation.org/ISA95JOBCONTROL/v200/docs/9.1 i=11616 ns=1;i=6023 ns=1;i=6024 ns=1;i=6025 ns=1;i=6026 ns=1;i=6027 ns=1;i=6028 ns=1;i=6029 i=11715 IsNamespaceSubset i=68 ns=1;i=5001 false NamespacePublicationDate i=68 ns=1;i=5001 2024-01-31T00:00:00Z NamespaceUri i=68 ns=1;i=5001 http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/ NamespaceVersion i=68 ns=1;i=5001 2.0.0 StaticNodeIdTypes i=68 ns=1;i=5001 0 StaticNumericNodeIdRange i=68 ns=1;i=5001 1:2147483647 StaticStringNodeIdPattern i=68 ns=1;i=5001 0 Default Binary i=76 ns=1;i=3002 ns=1;i=6128 Default XML i=76 ns=1;i=3002 ns=1;i=6129 Default JSON i=76 ns=1;i=3002 Default Binary i=76 ns=1;i=3003 ns=1;i=6122 Default XML i=76 ns=1;i=3003 ns=1;i=6123 Default JSON i=76 ns=1;i=3003 Default Binary i=76 ns=1;i=3005 ns=1;i=6022 Default XML i=76 ns=1;i=3005 ns=1;i=6030 Default JSON i=76 ns=1;i=3005 Default Binary i=76 ns=1;i=3007 ns=1;i=6132 Default XML i=76 ns=1;i=3007 ns=1;i=6133 Default JSON i=76 ns=1;i=3007 Default Binary i=76 ns=1;i=3008 ns=1;i=6046 Default XML i=76 ns=1;i=3008 ns=1;i=6117 Default JSON i=76 ns=1;i=3008 Default Binary i=76 ns=1;i=3010 ns=1;i=6120 Default XML i=76 ns=1;i=3010 ns=1;i=6121 Default JSON i=76 ns=1;i=3010 Default Binary i=76 ns=1;i=3011 ns=1;i=6124 Default XML i=76 ns=1;i=3011 ns=1;i=6125 Default JSON i=76 ns=1;i=3011 Default Binary i=76 ns=1;i=3012 ns=1;i=6126 Default XML i=76 ns=1;i=3012 ns=1;i=6127 Default JSON i=76 ns=1;i=3012 Default Binary i=76 ns=1;i=3013 ns=1;i=6118 Default XML i=76 ns=1;i=3013 ns=1;i=6119 Default JSON i=76 ns=1;i=3013 Default Binary i=76 ns=1;i=3006 ns=1;i=6130 Default XML i=76 ns=1;i=3006 ns=1;i=6131 Default JSON i=76 ns=1;i=3006 Default Binary i=76 ns=1;i=3015 ns=1;i=6031 Default XML i=76 ns=1;i=3015 ns=1;i=6032 Default JSON i=76 ns=1;i=3015 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Isa95Jobs/Nodesets/opc.ua.isa95-jobcontrol.types.bsd ================================================ Defines an equipment resource or a piece of equipment, a quantity, an optional description, and an optional collection of properties. Defines the information needed to schedule and execute a job. Defines the information needed to schedule and execute a job. Defines the information needed to schedule and execute a job. Defines a material resource, a quantity, an optional description, and an optional collection of properties. A subtype of OPC UA Structure that defines three linked data items: the ID, which is a unique identifier for a property, the value, which is the data that is identified, and an optional description of the parameter. Defines a personnel resource or a person, a quantity, an optional description, and an optional collection of properties. Defines a physical asset, a quantity, an optional description, and an optional collection of properties. A subtype of OPC UA Structure that defines two linked data items: an ID, which is a unique identifier for a property within the scope of the associated resource, and the value, which is the data for the property. Defines the information needed to schedule and execute a job. Defines a Work Master ID and the defined parameters for the Work Master. ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Isa95Jobs/Nodesets/opc.ua.isa95-jobcontrol.types.xsd ================================================ Defines an equipment resource or a piece of equipment, a quantity, an optional description, and an optional collection of properties. Defines the information needed to schedule and execute a job. Defines the information needed to schedule and execute a job. Defines the information needed to schedule and execute a job. Defines a material resource, a quantity, an optional description, and an optional collection of properties. A subtype of OPC UA Structure that defines three linked data items: the ID, which is a unique identifier for a property, the value, which is the data that is identified, and an optional description of the parameter. Defines a personnel resource or a person, a quantity, an optional description, and an optional collection of properties. Defines a physical asset, a quantity, an optional description, and an optional collection of properties. A subtype of OPC UA Structure that defines two linked data items: an ID, which is a unique identifier for a property within the scope of the associated resource, and the value, which is the data for the property. Defines the information needed to schedule and execute a job. Defines a Work Master ID and the defined parameters for the Work Master. ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/MemoryBuffer/Design/MemoryBuffer.Classes.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; using System.Collections.Generic; namespace MemoryBuffer { #region MemoryTagState Class #if !OPCUA_EXCLUDE_MemoryTagState /// /// Stores an instance of the MemoryTagType VariableType. /// /// [System.CodeDom.Compiler.GeneratedCode("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class MemoryTagState : BaseDataVariableState { #region Constructors /// /// Initializes the type with its default attribute values. /// /// public MemoryTagState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return NodeId.Create(VariableTypes.MemoryTagType, Namespaces.MemoryBuffer, namespaceUris); } /// /// Returns the id of the default data type node for the instance. /// /// protected override NodeId GetDefaultDataTypeId(NamespaceTable namespaceUris) { return NodeId.Create(DataTypes.BaseDataType, Opc.Ua.Namespaces.OpcUa, namespaceUris); } /// /// Returns the id of the default value rank for the instance. /// protected override int GetDefaultValueRank() { return ValueRanks.Scalar; } #if !OPCUA_EXCLUDE_InitializationStrings /// /// Initializes the instance. /// /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// /// /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACIAAABodHRwOi8vc2FtcGxlcy5vcmcvVUEvbWVtb3J5YnVmZmVy/////xVgiQICAAAAAQAVAAAA" + "TWVtb3J5VGFnVHlwZUluc3RhbmNlAQH6AwEB+gP6AwAAABj+////AQH/////AAAAAA=="; #endregion #endif #endregion } #region MemoryTagState Class /// /// A typed version of the MemoryTagType variable. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public class MemoryTagState : MemoryTagState { #region Constructors /// /// Initializes the instance with its defalt attribute values. /// public MemoryTagState(NodeState parent) : base(parent) { Value = default(T); } /// /// Initializes the instance with the default values. /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Value = default(T); DataType = TypeInfo.GetDataTypeId(typeof(T)); ValueRank = TypeInfo.GetValueRank(typeof(T)); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } #endregion #region Public Members /// /// The value of the variable. /// public new T Value { get { return CheckTypeBeforeCast(base.Value, true); } set { base.Value = value; } } #endregion } #endregion #endif #endregion #region MemoryBufferState Class #if !OPCUA_EXCLUDE_MemoryBufferState /// /// Stores an instance of the MemoryBufferType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCode("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class MemoryBufferState : BaseObjectState { #region Constructors /// /// Initializes the type with its default attribute values. /// /// public MemoryBufferState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return NodeId.Create(ObjectTypes.MemoryBufferType, Namespaces.MemoryBuffer, namespaceUris); } #if !OPCUA_EXCLUDE_InitializationStrings /// /// Initializes the instance. /// /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// /// /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACIAAABodHRwOi8vc2FtcGxlcy5vcmcvVUEvbWVtb3J5YnVmZmVy/////wRggAIBAAAAAQAYAAAA" + "TWVtb3J5QnVmZmVyVHlwZUluc3RhbmNlAQHoAwEB6APoAwAA/////wIAAAAVYKkKAgAAAAEADAAAAFN0" + "YXJ0QWRkcmVzcwEB6wMALgBE6wMAAAcAAAAAAAf/////AQH/////AAAAABVgqQoCAAAAAQALAAAAU2l6" + "ZUluQnl0ZXMBAewDAC4AROwDAAAHABAAAAAH/////wEB/////wAAAAA="; #endregion #endif #endregion #region Public Properties /// public PropertyState StartAddress { get => m_startAddress; set { if (!ReferenceEquals(m_startAddress, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_startAddress = value; } } /// public PropertyState SizeInBytes { get => m_sizeInBytes; set { if (!ReferenceEquals(m_sizeInBytes, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_sizeInBytes = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_startAddress != null) { children.Add(m_startAddress); } if (m_sizeInBytes != null) { children.Add(m_sizeInBytes); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// /// /// /// /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case BrowseNames.StartAddress: { if (createOrReplace && StartAddress == null) { if (replacement == null) { StartAddress = new PropertyState(this); } else { StartAddress = (PropertyState)replacement; } } instance = StartAddress; break; } case BrowseNames.SizeInBytes: { if (createOrReplace && SizeInBytes == null) { if (replacement == null) { SizeInBytes = new PropertyState(this); } else { SizeInBytes = (PropertyState)replacement; } } instance = SizeInBytes; break; } } return instance ?? base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private PropertyState m_startAddress; private PropertyState m_sizeInBytes; #endregion } #endif #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/MemoryBuffer/Design/MemoryBuffer.Constants.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; namespace MemoryBuffer { #region Object Identifiers /// /// A class that declares constants for all Objects in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Objects { /// /// The identifier for the MemoryBuffers Object. /// public const uint MemoryBuffers = 1025; } #endregion #region ObjectType Identifiers /// /// A class that declares constants for all ObjectTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectTypes { /// /// The identifier for the MemoryBufferType ObjectType. /// public const uint MemoryBufferType = 1000; } #endregion #region Variable Identifiers /// /// A class that declares constants for all Variables in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Variables { /// /// The identifier for the MemoryBufferType_StartAddress Variable. /// public const uint MemoryBufferType_StartAddress = 1003; /// /// The identifier for the MemoryBufferType_SizeInBytes Variable. /// public const uint MemoryBufferType_SizeInBytes = 1004; } #endregion #region VariableType Identifiers /// /// A class that declares constants for all VariableTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class VariableTypes { /// /// The identifier for the MemoryTagType VariableType. /// public const uint MemoryTagType = 1018; } #endregion #region Object Node Identifiers /// /// A class that declares constants for all Objects in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectIds { /// /// The identifier for the MemoryBuffers Object. /// public static readonly ExpandedNodeId MemoryBuffers = new ExpandedNodeId(MemoryBuffer.Objects.MemoryBuffers, MemoryBuffer.Namespaces.MemoryBuffer); } #endregion #region ObjectType Node Identifiers /// /// A class that declares constants for all ObjectTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectTypeIds { /// /// The identifier for the MemoryBufferType ObjectType. /// public static readonly ExpandedNodeId MemoryBufferType = new ExpandedNodeId(MemoryBuffer.ObjectTypes.MemoryBufferType, MemoryBuffer.Namespaces.MemoryBuffer); } #endregion #region Variable Node Identifiers /// /// A class that declares constants for all Variables in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class VariableIds { /// /// The identifier for the MemoryBufferType_StartAddress Variable. /// public static readonly ExpandedNodeId MemoryBufferType_StartAddress = new ExpandedNodeId(MemoryBuffer.Variables.MemoryBufferType_StartAddress, MemoryBuffer.Namespaces.MemoryBuffer); /// /// The identifier for the MemoryBufferType_SizeInBytes Variable. /// public static readonly ExpandedNodeId MemoryBufferType_SizeInBytes = new ExpandedNodeId(MemoryBuffer.Variables.MemoryBufferType_SizeInBytes, MemoryBuffer.Namespaces.MemoryBuffer); } #endregion #region VariableType Node Identifiers /// /// A class that declares constants for all VariableTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class VariableTypeIds { /// /// The identifier for the MemoryTagType VariableType. /// public static readonly ExpandedNodeId MemoryTagType = new ExpandedNodeId(MemoryBuffer.VariableTypes.MemoryTagType, MemoryBuffer.Namespaces.MemoryBuffer); } #endregion #region BrowseName Declarations /// /// Declares all of the BrowseNames used in the Model Design. /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class BrowseNames { /// /// The BrowseName for the MemoryBuffers component. /// public const string MemoryBuffers = "MemoryBuffers"; /// /// The BrowseName for the MemoryBufferType component. /// public const string MemoryBufferType = "MemoryBufferType"; /// /// The BrowseName for the MemoryTagType component. /// public const string MemoryTagType = "MemoryTagType"; /// /// The BrowseName for the SizeInBytes component. /// public const string SizeInBytes = "SizeInBytes"; /// /// The BrowseName for the StartAddress component. /// public const string StartAddress = "StartAddress"; } #endregion #region Namespace Declarations /// /// Defines constants for all namespaces referenced by the model design. /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Namespaces { /// /// The URI for the OpcUa namespace (.NET code namespace is 'Opc.Ua'). /// public const string OpcUa = "http://opcfoundation.org/UA/"; /// /// The URI for the OpcUaXsd namespace (.NET code namespace is 'Opc.Ua'). /// public const string OpcUaXsd = "http://opcfoundation.org/UA/2008/02/Types.xsd"; /// /// The URI for the MemoryBuffer namespace (.NET code namespace is 'MemoryBuffer'). /// public const string MemoryBuffer = "http://samples.org/UA/memorybuffer"; } #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/MemoryBuffer/Design/MemoryBuffer.NodeIds.csv ================================================ MemoryBuffers,1025,Object MemoryBufferType,1000,ObjectType MemoryTagType,1018,VariableType ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/MemoryBuffer/Design/MemoryBuffer.NodeSet.xml ================================================  http://opcfoundation.org/UA/ http://samples.org/UA/memorybuffer ns=1;i=1000 ObjectType_8 1 MemoryBufferType MemoryBufferType 0 0 0 i=45 true i=58 i=46 false ns=1;i=1003 i=46 false ns=1;i=1004 false ns=1;i=1003 Variable_2 1 StartAddress StartAddress 0 0 0 i=46 true ns=1;i=1000 i=40 false i=68 i=37 false i=78 0 i=7 -1 1 1 0 false 0 ns=1;i=1004 Variable_2 1 SizeInBytes SizeInBytes 0 0 0 i=46 true ns=1;i=1000 i=40 false i=68 i=37 false i=78 4096 i=7 -1 1 1 0 false 0 ns=1;i=1018 VariableType_16 1 MemoryTagType MemoryTagType 0 0 0 i=45 true i=63 i=24 -2 false ns=1;i=1025 Object_1 1 MemoryBuffers MemoryBuffers 0 0 0 i=40 false i=61 i=35 true i=85 0 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/MemoryBuffer/Design/MemoryBuffer.NodeSet2.xml ================================================  http://samples.org/UA/memorybuffer i=1 i=2 i=3 i=4 i=5 i=6 i=7 i=8 i=9 i=10 i=11 i=13 i=12 i=15 i=14 i=16 i=17 i=18 i=20 i=21 i=19 i=22 i=26 i=27 i=28 i=47 i=46 i=35 i=36 i=48 i=45 i=40 i=37 i=38 i=39 MemoryTagType i=63 MemoryBufferType ns=1;i=1003 ns=1;i=1004 i=58 StartAddress i=68 i=78 ns=1;i=1000 0 SizeInBytes i=68 i=78 ns=1;i=1000 4096 MemoryBuffers i=85 i=61 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/MemoryBuffer/Design/MemoryBuffer.PredefinedNodes.xml ================================================  http://samples.org/UA/memorybuffer VariableType_16 ns=1;i=1018 1 MemoryTagType i=63 i=24 ObjectType_8 ns=1;i=1000 1 MemoryBufferType i=58 Variable_2 ns=1;i=1003 1 StartAddress i=46 i=68 i=78 1003 0 i=7 -1 1 1 Variable_2 ns=1;i=1004 1 SizeInBytes i=46 i=68 i=78 1004 4096 i=7 -1 1 1 Object_1 ns=1;i=1025 1 MemoryBuffers i=47 i=61 1025 i=35 true i=85 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/MemoryBuffer/Design/MemoryBuffer.Types.bsd ================================================ ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/MemoryBuffer/Design/MemoryBuffer.Types.xsd ================================================ ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/MemoryBuffer/Design/MemoryBufferDesign.csv ================================================ MemoryBufferType,1000,ObjectType MemoryBufferType_StartAddress,1003,Variable MemoryBufferType_SizeInBytes,1004,Variable MemoryTagType,1018,VariableType MemoryBuffers,1025,Object ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/MemoryBuffer/Design/MemoryBufferDesign.xml ================================================  http://opcfoundation.org/UA/ http://samples.org/UA/memorybuffer 0 4096 ua:Organizes ua:ObjectsFolder ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Plc/Design/ModelDesign.csv ================================================ PlcTemperatureType,15001,DataType PlcType_PlcStatus,15003,Variable PlcTemperatureType_Encoding_DefaultBinary,15004,Object Plc_BinarySchema_PlcTemperatureType,15005,Variable Plc_BinarySchema_PlcTemperatureType_DataTypeVersion,15006,Variable Plc_BinarySchema_PlcTemperatureType_DictionaryFragment,15007,Variable PlcTemperatureType_Encoding_DefaultXml,15008,Object Plc_XmlSchema_PlcTemperatureType,15009,Variable Plc_XmlSchema_PlcTemperatureType_DataTypeVersion,15010,Variable Plc_XmlSchema_PlcTemperatureType_DictionaryFragment,15011,Variable PlcTemperatureType_Encoding_DefaultJson,15012,Object Plc1_PlcStatus,15013,Variable PlcHeaterStateType,15014,DataType PlcHeaterStateType_EnumStrings,15015,Variable PlcDataType,15032,DataType PlcType,15068,ObjectType Plc1,15070,Object PlcDataType_Encoding_DefaultBinary,15072,Object Plc_BinarySchema,15074,Variable Plc_BinarySchema_DataTypeVersion,15075,Variable Plc_BinarySchema_NamespaceUri,15076,Variable Plc_BinarySchema_Deprecated,15077,Variable Plc_BinarySchema_PlcDataType,15078,Variable Plc_BinarySchema_PlcDataType_DataTypeVersion,15079,Variable Plc_BinarySchema_PlcDataType_DictionaryFragment,15080,Variable PlcDataType_Encoding_DefaultXml,15084,Object Plc_XmlSchema,15086,Variable Plc_XmlSchema_DataTypeVersion,15087,Variable Plc_XmlSchema_NamespaceUri,15088,Variable Plc_XmlSchema_Deprecated,15089,Variable Plc_XmlSchema_PlcDataType,15090,Variable Plc_XmlSchema_PlcDataType_DataTypeVersion,15091,Variable Plc_XmlSchema_PlcDataType_DictionaryFragment,15092,Variable PlcDataType_Encoding_DefaultJson,15096,Object ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Plc/Design/ModelDesign.xml ================================================  http://opcfoundation.org/UA/ http://opcfoundation.org/UA/Plc Temperature in °C, pressure in Pa and heater state. Temperature in °C next to the heater at the bottom, and away from the heater at the top. Heater working state. 20 20 100020 On Plc #1 A simple plc. ua:Organizes ua:ObjectsFolder ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Plc/Design/PlcModel.Classes.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2021 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; using System; using System.Collections.Generic; namespace PlcModel { #region PlcState Class #if (!OPCUA_EXCLUDE_PlcState) /// /// Stores an instance of the PlcType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class PlcState : BaseObjectState { #region Constructors /// /// Initializes the type with its default attribute values. /// public PlcState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(PlcModel.ObjectTypes.PlcType, PlcModel.Namespaces.Plc, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAAB8AAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvUGxj/////4RggAIBAAAAAQAPAAAAUGxj" + "VHlwZUluc3RhbmNlAQHcOgEB3DrcOgAAAf////8BAAAAFWCpCgIAAAABAAkAAABQbGNTdGF0dXMBAZs6" + "AC8AP5s6AAAWAQHsOgK2AAAAPFBsY0RhdGFUeXBlIHhtbG5zPSJodHRwOi8vb3BjZm91bmRhdGlvbi5v" + "cmcvVUEvUGxjIj48VGVtcGVyYXR1cmU+PFRvcD4yMDwvVG9wPjxCb3R0b20+MjA8L0JvdHRvbT48L1Rl" + "bXBlcmF0dXJlPjxQcmVzc3VyZT4xMDAwMjA8L1ByZXNzdXJlPjxIZWF0ZXJTdGF0ZT5PbjwvSGVhdGVy" + "U3RhdGU+PC9QbGNEYXRhVHlwZT4BAbg6/////wEB/////wAAAAA="; #endregion #endif #endregion #region Public Properties /// public BaseDataVariableState PlcStatus { get { return m_plcStatus; } set { if (!Object.ReferenceEquals(m_plcStatus, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_plcStatus = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_plcStatus != null) { children.Add(m_plcStatus); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case PlcModel.BrowseNames.PlcStatus: { if (createOrReplace) { if (PlcStatus == null) { if (replacement == null) { PlcStatus = new BaseDataVariableState(this); } else { PlcStatus = (BaseDataVariableState)replacement; } } } instance = PlcStatus; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private BaseDataVariableState m_plcStatus; #endregion } #endif #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Plc/Design/PlcModel.Constants.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2021 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; namespace PlcModel { #region DataType Identifiers /// /// A class that declares constants for all DataTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class DataTypes { /// /// The identifier for the PlcDataType DataType. /// public const uint PlcDataType = 15032; /// /// The identifier for the PlcTemperatureType DataType. /// public const uint PlcTemperatureType = 15001; /// /// The identifier for the PlcHeaterStateType DataType. /// public const uint PlcHeaterStateType = 15014; } #endregion #region Object Identifiers /// /// A class that declares constants for all Objects in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Objects { /// /// The identifier for the Plc1 Object. /// public const uint Plc1 = 15070; /// /// The identifier for the PlcDataType_Encoding_DefaultBinary Object. /// public const uint PlcDataType_Encoding_DefaultBinary = 15072; /// /// The identifier for the PlcTemperatureType_Encoding_DefaultBinary Object. /// public const uint PlcTemperatureType_Encoding_DefaultBinary = 15004; /// /// The identifier for the PlcDataType_Encoding_DefaultXml Object. /// public const uint PlcDataType_Encoding_DefaultXml = 15084; /// /// The identifier for the PlcTemperatureType_Encoding_DefaultXml Object. /// public const uint PlcTemperatureType_Encoding_DefaultXml = 15008; /// /// The identifier for the PlcDataType_Encoding_DefaultJson Object. /// public const uint PlcDataType_Encoding_DefaultJson = 15096; /// /// The identifier for the PlcTemperatureType_Encoding_DefaultJson Object. /// public const uint PlcTemperatureType_Encoding_DefaultJson = 15012; } #endregion #region ObjectType Identifiers /// /// A class that declares constants for all ObjectTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectTypes { /// /// The identifier for the PlcType ObjectType. /// public const uint PlcType = 15068; } #endregion #region Variable Identifiers /// /// A class that declares constants for all Variables in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Variables { /// /// The identifier for the PlcHeaterStateType_EnumStrings Variable. /// public const uint PlcHeaterStateType_EnumStrings = 15015; /// /// The identifier for the PlcType_PlcStatus Variable. /// public const uint PlcType_PlcStatus = 15003; /// /// The identifier for the Plc1_PlcStatus Variable. /// public const uint Plc1_PlcStatus = 15013; /// /// The identifier for the Plc_BinarySchema Variable. /// public const uint Plc_BinarySchema = 15074; /// /// The identifier for the Plc_BinarySchema_NamespaceUri Variable. /// public const uint Plc_BinarySchema_NamespaceUri = 15076; /// /// The identifier for the Plc_BinarySchema_Deprecated Variable. /// public const uint Plc_BinarySchema_Deprecated = 15077; /// /// The identifier for the Plc_BinarySchema_PlcDataType Variable. /// public const uint Plc_BinarySchema_PlcDataType = 15078; /// /// The identifier for the Plc_BinarySchema_PlcTemperatureType Variable. /// public const uint Plc_BinarySchema_PlcTemperatureType = 15005; /// /// The identifier for the Plc_XmlSchema Variable. /// public const uint Plc_XmlSchema = 15086; /// /// The identifier for the Plc_XmlSchema_NamespaceUri Variable. /// public const uint Plc_XmlSchema_NamespaceUri = 15088; /// /// The identifier for the Plc_XmlSchema_Deprecated Variable. /// public const uint Plc_XmlSchema_Deprecated = 15089; /// /// The identifier for the Plc_XmlSchema_PlcDataType Variable. /// public const uint Plc_XmlSchema_PlcDataType = 15090; /// /// The identifier for the Plc_XmlSchema_PlcTemperatureType Variable. /// public const uint Plc_XmlSchema_PlcTemperatureType = 15009; } #endregion #region DataType Node Identifiers /// /// A class that declares constants for all DataTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class DataTypeIds { /// /// The identifier for the PlcDataType DataType. /// public static readonly ExpandedNodeId PlcDataType = new ExpandedNodeId(PlcModel.DataTypes.PlcDataType, PlcModel.Namespaces.Plc); /// /// The identifier for the PlcTemperatureType DataType. /// public static readonly ExpandedNodeId PlcTemperatureType = new ExpandedNodeId(PlcModel.DataTypes.PlcTemperatureType, PlcModel.Namespaces.Plc); /// /// The identifier for the PlcHeaterStateType DataType. /// public static readonly ExpandedNodeId PlcHeaterStateType = new ExpandedNodeId(PlcModel.DataTypes.PlcHeaterStateType, PlcModel.Namespaces.Plc); } #endregion #region Object Node Identifiers /// /// A class that declares constants for all Objects in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectIds { /// /// The identifier for the Plc1 Object. /// public static readonly ExpandedNodeId Plc1 = new ExpandedNodeId(PlcModel.Objects.Plc1, PlcModel.Namespaces.Plc); /// /// The identifier for the PlcDataType_Encoding_DefaultBinary Object. /// public static readonly ExpandedNodeId PlcDataType_Encoding_DefaultBinary = new ExpandedNodeId(PlcModel.Objects.PlcDataType_Encoding_DefaultBinary, PlcModel.Namespaces.Plc); /// /// The identifier for the PlcTemperatureType_Encoding_DefaultBinary Object. /// public static readonly ExpandedNodeId PlcTemperatureType_Encoding_DefaultBinary = new ExpandedNodeId(PlcModel.Objects.PlcTemperatureType_Encoding_DefaultBinary, PlcModel.Namespaces.Plc); /// /// The identifier for the PlcDataType_Encoding_DefaultXml Object. /// public static readonly ExpandedNodeId PlcDataType_Encoding_DefaultXml = new ExpandedNodeId(PlcModel.Objects.PlcDataType_Encoding_DefaultXml, PlcModel.Namespaces.Plc); /// /// The identifier for the PlcTemperatureType_Encoding_DefaultXml Object. /// public static readonly ExpandedNodeId PlcTemperatureType_Encoding_DefaultXml = new ExpandedNodeId(PlcModel.Objects.PlcTemperatureType_Encoding_DefaultXml, PlcModel.Namespaces.Plc); /// /// The identifier for the PlcDataType_Encoding_DefaultJson Object. /// public static readonly ExpandedNodeId PlcDataType_Encoding_DefaultJson = new ExpandedNodeId(PlcModel.Objects.PlcDataType_Encoding_DefaultJson, PlcModel.Namespaces.Plc); /// /// The identifier for the PlcTemperatureType_Encoding_DefaultJson Object. /// public static readonly ExpandedNodeId PlcTemperatureType_Encoding_DefaultJson = new ExpandedNodeId(PlcModel.Objects.PlcTemperatureType_Encoding_DefaultJson, PlcModel.Namespaces.Plc); } #endregion #region ObjectType Node Identifiers /// /// A class that declares constants for all ObjectTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectTypeIds { /// /// The identifier for the PlcType ObjectType. /// public static readonly ExpandedNodeId PlcType = new ExpandedNodeId(PlcModel.ObjectTypes.PlcType, PlcModel.Namespaces.Plc); } #endregion #region Variable Node Identifiers /// /// A class that declares constants for all Variables in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class VariableIds { /// /// The identifier for the PlcHeaterStateType_EnumStrings Variable. /// public static readonly ExpandedNodeId PlcHeaterStateType_EnumStrings = new ExpandedNodeId(PlcModel.Variables.PlcHeaterStateType_EnumStrings, PlcModel.Namespaces.Plc); /// /// The identifier for the PlcType_PlcStatus Variable. /// public static readonly ExpandedNodeId PlcType_PlcStatus = new ExpandedNodeId(PlcModel.Variables.PlcType_PlcStatus, PlcModel.Namespaces.Plc); /// /// The identifier for the Plc1_PlcStatus Variable. /// public static readonly ExpandedNodeId Plc1_PlcStatus = new ExpandedNodeId(PlcModel.Variables.Plc1_PlcStatus, PlcModel.Namespaces.Plc); /// /// The identifier for the Plc_BinarySchema Variable. /// public static readonly ExpandedNodeId Plc_BinarySchema = new ExpandedNodeId(PlcModel.Variables.Plc_BinarySchema, PlcModel.Namespaces.Plc); /// /// The identifier for the Plc_BinarySchema_NamespaceUri Variable. /// public static readonly ExpandedNodeId Plc_BinarySchema_NamespaceUri = new ExpandedNodeId(PlcModel.Variables.Plc_BinarySchema_NamespaceUri, PlcModel.Namespaces.Plc); /// /// The identifier for the Plc_BinarySchema_Deprecated Variable. /// public static readonly ExpandedNodeId Plc_BinarySchema_Deprecated = new ExpandedNodeId(PlcModel.Variables.Plc_BinarySchema_Deprecated, PlcModel.Namespaces.Plc); /// /// The identifier for the Plc_BinarySchema_PlcDataType Variable. /// public static readonly ExpandedNodeId Plc_BinarySchema_PlcDataType = new ExpandedNodeId(PlcModel.Variables.Plc_BinarySchema_PlcDataType, PlcModel.Namespaces.Plc); /// /// The identifier for the Plc_BinarySchema_PlcTemperatureType Variable. /// public static readonly ExpandedNodeId Plc_BinarySchema_PlcTemperatureType = new ExpandedNodeId(PlcModel.Variables.Plc_BinarySchema_PlcTemperatureType, PlcModel.Namespaces.Plc); /// /// The identifier for the Plc_XmlSchema Variable. /// public static readonly ExpandedNodeId Plc_XmlSchema = new ExpandedNodeId(PlcModel.Variables.Plc_XmlSchema, PlcModel.Namespaces.Plc); /// /// The identifier for the Plc_XmlSchema_NamespaceUri Variable. /// public static readonly ExpandedNodeId Plc_XmlSchema_NamespaceUri = new ExpandedNodeId(PlcModel.Variables.Plc_XmlSchema_NamespaceUri, PlcModel.Namespaces.Plc); /// /// The identifier for the Plc_XmlSchema_Deprecated Variable. /// public static readonly ExpandedNodeId Plc_XmlSchema_Deprecated = new ExpandedNodeId(PlcModel.Variables.Plc_XmlSchema_Deprecated, PlcModel.Namespaces.Plc); /// /// The identifier for the Plc_XmlSchema_PlcDataType Variable. /// public static readonly ExpandedNodeId Plc_XmlSchema_PlcDataType = new ExpandedNodeId(PlcModel.Variables.Plc_XmlSchema_PlcDataType, PlcModel.Namespaces.Plc); /// /// The identifier for the Plc_XmlSchema_PlcTemperatureType Variable. /// public static readonly ExpandedNodeId Plc_XmlSchema_PlcTemperatureType = new ExpandedNodeId(PlcModel.Variables.Plc_XmlSchema_PlcTemperatureType, PlcModel.Namespaces.Plc); } #endregion #region BrowseName Declarations /// /// Declares all of the BrowseNames used in the Model Design. /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class BrowseNames { /// /// The BrowseName for the Plc_BinarySchema component. /// public const string Plc_BinarySchema = "PlcModel"; /// /// The BrowseName for the Plc_XmlSchema component. /// public const string Plc_XmlSchema = "PlcModel"; /// /// The BrowseName for the Plc1 component. /// public const string Plc1 = "Plc #1"; /// /// The BrowseName for the PlcDataType component. /// public const string PlcDataType = "PlcDataType"; /// /// The BrowseName for the PlcHeaterStateType component. /// public const string PlcHeaterStateType = "PlcHeaterStateType"; /// /// The BrowseName for the PlcStatus component. /// public const string PlcStatus = "PlcStatus"; /// /// The BrowseName for the PlcTemperatureType component. /// public const string PlcTemperatureType = "PlcTemperatureType"; /// /// The BrowseName for the PlcType component. /// public const string PlcType = "PlcType"; } #endregion #region Namespace Declarations /// /// Defines constants for all namespaces referenced by the model design. /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Namespaces { /// /// The URI for the OpcUa namespace (.NET code namespace is 'Opc.Ua'). /// public const string OpcUa = "http://opcfoundation.org/UA/"; /// /// The URI for the OpcUaXsd namespace (.NET code namespace is 'Opc.Ua'). /// public const string OpcUaXsd = "http://opcfoundation.org/UA/2008/02/Types.xsd"; /// /// The URI for the Plc namespace (.NET code namespace is 'PlcModel'). /// public const string Plc = "http://opcfoundation.org/UA/Plc"; } #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Plc/Design/PlcModel.DataTypes.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2021 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; using System; using System.Collections.Generic; using System.Runtime.Serialization; namespace PlcModel { #region PlcDataType Class #if (!OPCUA_EXCLUDE_PlcDataType) /// /// Temperature in °C, pressure in Pa and heater state. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = PlcModel.Namespaces.Plc)] public partial class PlcDataType : IEncodeable { #region Constructors /// /// The default constructor. /// public PlcDataType() { Initialize(); } /// /// Called by the .NET framework during deserialization. /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { m_temperature = new PlcTemperatureType(); m_pressure = (int)0; m_heaterState = PlcHeaterStateType.Off; } #endregion #region Public Properties /// /// /// [DataMember(Name = "Temperature", IsRequired = false, Order = 1)] public PlcTemperatureType Temperature { get { return m_temperature; } set { m_temperature = value; if (value == null) { m_temperature = new PlcTemperatureType(); } } } /// [DataMember(Name = "Pressure", IsRequired = false, Order = 2)] public int Pressure { get { return m_pressure; } set { m_pressure = value; } } /// [DataMember(Name = "HeaterState", IsRequired = false, Order = 3)] public PlcHeaterStateType HeaterState { get { return m_heaterState; } set { m_heaterState = value; } } #endregion #region IEncodeable Members /// public virtual ExpandedNodeId TypeId { get { return DataTypeIds.PlcDataType; } } /// public virtual ExpandedNodeId BinaryEncodingId { get { return ObjectIds.PlcDataType_Encoding_DefaultBinary; } } /// public virtual ExpandedNodeId XmlEncodingId { get { return ObjectIds.PlcDataType_Encoding_DefaultXml; } } /// public virtual void Encode(IEncoder encoder) { encoder.PushNamespace(PlcModel.Namespaces.Plc); encoder.WriteEncodeable("Temperature", Temperature, typeof(PlcTemperatureType)); encoder.WriteInt32("Pressure", Pressure); encoder.WriteEnumerated("HeaterState", HeaterState); encoder.PopNamespace(); } /// public virtual void Decode(IDecoder decoder) { decoder.PushNamespace(PlcModel.Namespaces.Plc); Temperature = (PlcTemperatureType)decoder.ReadEncodeable("Temperature", typeof(PlcTemperatureType)); Pressure = decoder.ReadInt32("Pressure"); HeaterState = (PlcHeaterStateType)decoder.ReadEnumerated("HeaterState", typeof(PlcHeaterStateType)); decoder.PopNamespace(); } /// public virtual bool IsEqual(IEncodeable encodeable) { if (Object.ReferenceEquals(this, encodeable)) { return true; } PlcDataType value = encodeable as PlcDataType; if (value == null) { return false; } if (!Utils.IsEqual(m_temperature, value.m_temperature)) return false; if (!Utils.IsEqual(m_pressure, value.m_pressure)) return false; if (!Utils.IsEqual(m_heaterState, value.m_heaterState)) return false; return true; } #if !NET_STANDARD /// public virtual object Clone() { return (PlcDataType)this.MemberwiseClone(); } #endif /// public new object MemberwiseClone() { PlcDataType clone = (PlcDataType)base.MemberwiseClone(); clone.m_temperature = (PlcTemperatureType)Utils.Clone(this.m_temperature); clone.m_pressure = (int)Utils.Clone(this.m_pressure); clone.m_heaterState = (PlcHeaterStateType)Utils.Clone(this.m_heaterState); return clone; } #endregion #region Private Fields private PlcTemperatureType m_temperature; private int m_pressure; private PlcHeaterStateType m_heaterState; #endregion } #region PlcDataTypeCollection Class /// /// A collection of PlcDataType objects. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfPlcDataType", Namespace = PlcModel.Namespaces.Plc, ItemName = "PlcDataType")] #if !NET_STANDARD public partial class PlcDataTypeCollection : List, ICloneable #else public partial class PlcDataTypeCollection : List #endif { #region Constructors /// /// Initializes the collection with default values. /// public PlcDataTypeCollection() { } /// /// Initializes the collection with an initial capacity. /// public PlcDataTypeCollection(int capacity) : base(capacity) { } /// /// Initializes the collection with another collection. /// public PlcDataTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// /// Converts an array to a collection. /// public static implicit operator PlcDataTypeCollection(PlcDataType[] values) { if (values != null) { return new PlcDataTypeCollection(values); } return new PlcDataTypeCollection(); } /// /// Converts a collection to an array. /// public static explicit operator PlcDataType[](PlcDataTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #if !NET_STANDARD #region ICloneable Methods /// /// Creates a deep copy of the collection. /// public object Clone() { return (PlcDataTypeCollection)this.MemberwiseClone(); } #endregion #endif /// public new object MemberwiseClone() { PlcDataTypeCollection clone = new PlcDataTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((PlcDataType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion #region PlcTemperatureType Class #if (!OPCUA_EXCLUDE_PlcTemperatureType) /// /// Temperature in °C next to the heater at the bottom, and away from the heater at the top. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = PlcModel.Namespaces.Plc)] public partial class PlcTemperatureType : IEncodeable { #region Constructors /// /// The default constructor. /// public PlcTemperatureType() { Initialize(); } /// /// Called by the .NET framework during deserialization. /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { m_top = (int)0; m_bottom = (int)0; } #endregion #region Public Properties /// [DataMember(Name = "Top", IsRequired = false, Order = 1)] public int Top { get { return m_top; } set { m_top = value; } } /// [DataMember(Name = "Bottom", IsRequired = false, Order = 2)] public int Bottom { get { return m_bottom; } set { m_bottom = value; } } #endregion #region IEncodeable Members /// public virtual ExpandedNodeId TypeId { get { return DataTypeIds.PlcTemperatureType; } } /// public virtual ExpandedNodeId BinaryEncodingId { get { return ObjectIds.PlcTemperatureType_Encoding_DefaultBinary; } } /// public virtual ExpandedNodeId XmlEncodingId { get { return ObjectIds.PlcTemperatureType_Encoding_DefaultXml; } } /// public virtual void Encode(IEncoder encoder) { encoder.PushNamespace(PlcModel.Namespaces.Plc); encoder.WriteInt32("Top", Top); encoder.WriteInt32("Bottom", Bottom); encoder.PopNamespace(); } /// public virtual void Decode(IDecoder decoder) { decoder.PushNamespace(PlcModel.Namespaces.Plc); Top = decoder.ReadInt32("Top"); Bottom = decoder.ReadInt32("Bottom"); decoder.PopNamespace(); } /// public virtual bool IsEqual(IEncodeable encodeable) { if (Object.ReferenceEquals(this, encodeable)) { return true; } PlcTemperatureType value = encodeable as PlcTemperatureType; if (value == null) { return false; } if (!Utils.IsEqual(m_top, value.m_top)) return false; if (!Utils.IsEqual(m_bottom, value.m_bottom)) return false; return true; } #if !NET_STANDARD /// public virtual object Clone() { return (PlcTemperatureType)this.MemberwiseClone(); } #endif /// public new object MemberwiseClone() { PlcTemperatureType clone = (PlcTemperatureType)base.MemberwiseClone(); clone.m_top = (int)Utils.Clone(this.m_top); clone.m_bottom = (int)Utils.Clone(this.m_bottom); return clone; } #endregion #region Private Fields private int m_top; private int m_bottom; #endregion } #region PlcTemperatureTypeCollection Class /// /// A collection of PlcTemperatureType objects. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfPlcTemperatureType", Namespace = PlcModel.Namespaces.Plc, ItemName = "PlcTemperatureType")] #if !NET_STANDARD public partial class PlcTemperatureTypeCollection : List, ICloneable #else public partial class PlcTemperatureTypeCollection : List #endif { #region Constructors /// /// Initializes the collection with default values. /// public PlcTemperatureTypeCollection() { } /// /// Initializes the collection with an initial capacity. /// public PlcTemperatureTypeCollection(int capacity) : base(capacity) { } /// /// Initializes the collection with another collection. /// public PlcTemperatureTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// /// Converts an array to a collection. /// public static implicit operator PlcTemperatureTypeCollection(PlcTemperatureType[] values) { if (values != null) { return new PlcTemperatureTypeCollection(values); } return new PlcTemperatureTypeCollection(); } /// /// Converts a collection to an array. /// public static explicit operator PlcTemperatureType[](PlcTemperatureTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #if !NET_STANDARD #region ICloneable Methods /// /// Creates a deep copy of the collection. /// public object Clone() { return (PlcTemperatureTypeCollection)this.MemberwiseClone(); } #endregion #endif /// public new object MemberwiseClone() { PlcTemperatureTypeCollection clone = new PlcTemperatureTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((PlcTemperatureType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion #region PlcHeaterStateType Enumeration #if (!OPCUA_EXCLUDE_PlcHeaterStateType) /// /// Heater working state. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = PlcModel.Namespaces.Plc)] public enum PlcHeaterStateType { /// [EnumMember(Value = "Off_0")] Off = 0, /// [EnumMember(Value = "On_1")] On = 1, } #region PlcHeaterStateTypeCollection Class /// /// A collection of PlcHeaterStateType objects. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfPlcHeaterStateType", Namespace = PlcModel.Namespaces.Plc, ItemName = "PlcHeaterStateType")] #if !NET_STANDARD public partial class PlcHeaterStateTypeCollection : List, ICloneable #else public partial class PlcHeaterStateTypeCollection : List #endif { #region Constructors /// /// Initializes the collection with default values. /// public PlcHeaterStateTypeCollection() { } /// /// Initializes the collection with an initial capacity. /// public PlcHeaterStateTypeCollection(int capacity) : base(capacity) { } /// /// Initializes the collection with another collection. /// public PlcHeaterStateTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// /// Converts an array to a collection. /// public static implicit operator PlcHeaterStateTypeCollection(PlcHeaterStateType[] values) { if (values != null) { return new PlcHeaterStateTypeCollection(values); } return new PlcHeaterStateTypeCollection(); } /// /// Converts a collection to an array. /// public static explicit operator PlcHeaterStateType[](PlcHeaterStateTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #if !NET_STANDARD #region ICloneable Methods /// /// Creates a deep copy of the collection. /// public object Clone() { return (PlcHeaterStateTypeCollection)this.MemberwiseClone(); } #endregion #endif /// public new object MemberwiseClone() { PlcHeaterStateTypeCollection clone = new PlcHeaterStateTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((PlcHeaterStateType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Plc/Design/PlcModel.NodeIds.csv ================================================ Plc_BinarySchema,15074,Variable Plc_XmlSchema,15086,Variable Plc1,15070,Object PlcDataType,15032,DataType PlcDataType_Encoding_DefaultBinary,15072,Object PlcDataType_Encoding_DefaultJson,15096,Object PlcDataType_Encoding_DefaultXml,15084,Object PlcHeaterStateType,15014,DataType PlcTemperatureType,15001,DataType PlcTemperatureType_Encoding_DefaultBinary,15004,Object PlcTemperatureType_Encoding_DefaultJson,15012,Object PlcTemperatureType_Encoding_DefaultXml,15008,Object PlcType,15068,ObjectType ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Plc/Design/PlcModel.NodeSet.xml ================================================  http://opcfoundation.org/UA/ http://opcfoundation.org/UA/Plc ns=1;i=15001 DataType_64 1 PlcTemperatureType PlcTemperatureType Temperature in °C next to the heater at the bottom, and away from the heater at the top. 0 0 0 i=45 true i=22 i=38 false ns=1;i=15004 i=38 false ns=1;i=15008 i=38 false ns=1;i=15012 false ns=1;i=15003 Variable_2 1 PlcStatus PlcStatus 0 0 0 i=47 true ns=1;i=15068 i=40 false i=63 i=37 false i=78 ns=1;i=15084 20 20 100020 On ns=1;i=15032 -1 1 1 0 false 0 ns=1;i=15004 Object_1 0 Default Binary Default Binary 0 0 0 i=40 false i=76 i=38 true ns=1;i=15001 i=39 false ns=1;i=15005 0 ns=1;i=15005 Variable_2 1 PlcTemperatureType PlcTemperatureType 0 0 0 i=47 true ns=1;i=15074 i=40 false i=69 PlcTemperatureType i=12 -1 1 1 0 false 0 ns=1;i=15008 Object_1 0 Default XML Default XML 0 0 0 i=40 false i=76 i=38 true ns=1;i=15001 i=39 false ns=1;i=15009 0 ns=1;i=15009 Variable_2 1 PlcTemperatureType PlcTemperatureType 0 0 0 i=47 true ns=1;i=15086 i=40 false i=69 //xs:element[@name='PlcTemperatureType'] i=12 -1 1 1 0 false 0 ns=1;i=15012 Object_1 0 Default JSON Default JSON 0 0 0 i=40 false i=76 i=38 true ns=1;i=15001 0 ns=1;i=15013 Variable_2 1 PlcStatus PlcStatus 0 0 0 i=47 true ns=1;i=15070 i=40 false i=63 ns=1;i=15084 20 20 100020 On ns=1;i=15032 -1 1 1 0 false 0 ns=1;i=15014 DataType_64 1 PlcHeaterStateType PlcHeaterStateType Heater working state. 0 0 0 i=45 true i=29 i=46 false ns=1;i=15015 false ns=1;i=15015 Variable_2 0 EnumStrings EnumStrings 0 0 0 i=46 true ns=1;i=15014 i=40 false i=68 Off On i=21 1 0 1 1 0 false 0 ns=1;i=15032 DataType_64 1 PlcDataType PlcDataType Temperature in °C, pressure in Pa and heater state. 0 0 0 i=45 true i=22 i=38 false ns=1;i=15072 i=38 false ns=1;i=15084 i=38 false ns=1;i=15096 false ns=1;i=15068 ObjectType_8 1 PlcType PlcType 0 0 0 i=45 true i=58 i=47 false ns=1;i=15003 false ns=1;i=15070 Object_1 1 Plc #1 Plc #1 A simple plc. 0 0 0 i=40 false ns=1;i=15068 i=35 true i=85 i=47 false ns=1;i=15013 1 ns=1;i=15072 Object_1 0 Default Binary Default Binary 0 0 0 i=40 false i=76 i=38 true ns=1;i=15032 i=39 false ns=1;i=15078 0 ns=1;i=15074 Variable_2 1 PlcModel PlcModel 0 0 0 i=40 false i=72 i=47 true i=93 i=46 false ns=1;i=15076 i=46 false ns=1;i=15077 i=47 false ns=1;i=15078 i=47 false ns=1;i=15005 PG9wYzpUeXBlRGljdGlvbmFyeQ0KICB4bWxuczpvcGM9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9y Zy9CaW5hcnlTY2hlbWEvIg0KICB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1M U2NoZW1hLWluc3RhbmNlIg0KICB4bWxuczp1YT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VB LyINCiAgeG1sbnM6dG5zPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvUGxjIg0KICBEZWZh dWx0Qnl0ZU9yZGVyPSJMaXR0bGVFbmRpYW4iDQogIFRhcmdldE5hbWVzcGFjZT0iaHR0cDovL29w Y2ZvdW5kYXRpb24ub3JnL1VBL1BsYyINCj4NCiAgPG9wYzpJbXBvcnQgTmFtZXNwYWNlPSJodHRw Oi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvIiBMb2NhdGlvbj0iT3BjLlVhLkJpbmFyeVNjaGVtYS5i c2QiLz4NCg0KICA8b3BjOlN0cnVjdHVyZWRUeXBlIE5hbWU9IlBsY0RhdGFUeXBlIiBCYXNlVHlw ZT0idWE6RXh0ZW5zaW9uT2JqZWN0Ij4NCiAgICA8b3BjOkRvY3VtZW50YXRpb24+VGVtcGVyYXR1 cmUgaW4gwrBDLCBwcmVzc3VyZSBpbiBQYSBhbmQgaGVhdGVyIHN0YXRlLjwvb3BjOkRvY3VtZW50 YXRpb24+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJUZW1wZXJhdHVyZSIgVHlwZU5hbWU9InRuczpQ bGNUZW1wZXJhdHVyZVR5cGUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJQcmVzc3VyZSIgVHlw ZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkhlYXRlclN0YXRlIiBU eXBlTmFtZT0idG5zOlBsY0hlYXRlclN0YXRlVHlwZSIgLz4NCiAgPC9vcGM6U3RydWN0dXJlZFR5 cGU+DQoNCiAgPG9wYzpTdHJ1Y3R1cmVkVHlwZSBOYW1lPSJQbGNUZW1wZXJhdHVyZVR5cGUiIEJh c2VUeXBlPSJ1YTpFeHRlbnNpb25PYmplY3QiPg0KICAgIDxvcGM6RG9jdW1lbnRhdGlvbj5UZW1w ZXJhdHVyZSBpbiDCsEMgbmV4dCB0byB0aGUgaGVhdGVyIGF0IHRoZSBib3R0b20sIGFuZCBhd2F5 IGZyb20gdGhlIGhlYXRlciBhdCB0aGUgdG9wLjwvb3BjOkRvY3VtZW50YXRpb24+DQogICAgPG9w YzpGaWVsZCBOYW1lPSJUb3AiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVs ZCBOYW1lPSJCb3R0b20iIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogIDwvb3BjOlN0cnVjdHVy ZWRUeXBlPg0KDQogIDxvcGM6RW51bWVyYXRlZFR5cGUgTmFtZT0iUGxjSGVhdGVyU3RhdGVUeXBl IiBMZW5ndGhJbkJpdHM9IjMyIj4NCiAgICA8b3BjOkRvY3VtZW50YXRpb24+SGVhdGVyIHdvcmtp bmcgc3RhdGUuPC9vcGM6RG9jdW1lbnRhdGlvbj4NCiAgICA8b3BjOkVudW1lcmF0ZWRWYWx1ZSBO YW1lPSJPZmYiIFZhbHVlPSIwIiAvPg0KICAgIDxvcGM6RW51bWVyYXRlZFZhbHVlIE5hbWU9Ik9u IiBWYWx1ZT0iMSIgLz4NCiAgPC9vcGM6RW51bWVyYXRlZFR5cGU+DQoNCjwvb3BjOlR5cGVEaWN0 aW9uYXJ5Pg== i=15 -1 1 1 0 false 0 ns=1;i=15076 Variable_2 0 NamespaceUri NamespaceUri 0 0 0 i=46 true ns=1;i=15074 i=40 false i=68 http://opcfoundation.org/UA/Plc i=12 -1 1 1 0 false 0 ns=1;i=15077 Variable_2 0 Deprecated Deprecated 0 0 0 i=46 true ns=1;i=15074 i=40 false i=68 true i=1 -1 1 1 0 false 0 ns=1;i=15078 Variable_2 1 PlcDataType PlcDataType 0 0 0 i=47 true ns=1;i=15074 i=40 false i=69 PlcDataType i=12 -1 1 1 0 false 0 ns=1;i=15084 Object_1 0 Default XML Default XML 0 0 0 i=40 false i=76 i=38 true ns=1;i=15032 i=39 false ns=1;i=15090 0 ns=1;i=15086 Variable_2 1 PlcModel PlcModel 0 0 0 i=40 false i=72 i=47 true i=92 i=46 false ns=1;i=15088 i=46 false ns=1;i=15089 i=47 false ns=1;i=15090 i=47 false ns=1;i=15009 PHhzOnNjaGVtYQ0KICB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEi DQogIHhtbG5zOnVhPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvMjAwOC8wMi9UeXBlcy54 c2QiDQogIHhtbG5zOnRucz0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VBL1BsYyINCiAgdGFy Z2V0TmFtZXNwYWNlPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvUGxjIg0KICBlbGVtZW50 Rm9ybURlZmF1bHQ9InF1YWxpZmllZCINCj4NCiAgPHhzOmltcG9ydCBuYW1lc3BhY2U9Imh0dHA6 Ly9vcGNmb3VuZGF0aW9uLm9yZy9VQS8yMDA4LzAyL1R5cGVzLnhzZCIgLz4NCg0KICA8eHM6Y29t cGxleFR5cGUgbmFtZT0iUGxjRGF0YVR5cGUiPg0KICAgIDx4czphbm5vdGF0aW9uPg0KICAgICAg PHhzOmRvY3VtZW50YXRpb24+VGVtcGVyYXR1cmUgaW4gwrBDLCBwcmVzc3VyZSBpbiBQYSBhbmQg aGVhdGVyIHN0YXRlLjwveHM6ZG9jdW1lbnRhdGlvbj4NCiAgICA8L3hzOmFubm90YXRpb24+DQog ICAgPHhzOnNlcXVlbmNlPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iVGVtcGVyYXR1cmUiIHR5 cGU9InRuczpQbGNUZW1wZXJhdHVyZVR5cGUiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUi IC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJQcmVzc3VyZSIgdHlwZT0ieHM6aW50IiBtaW5P Y2N1cnM9IjAiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJIZWF0ZXJTdGF0ZSIgdHlwZT0i dG5zOlBsY0hlYXRlclN0YXRlVHlwZSIgbWluT2NjdXJzPSIwIiAvPg0KICAgIDwveHM6c2VxdWVu Y2U+DQogIDwveHM6Y29tcGxleFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9IlBsY0RhdGFUeXBl IiB0eXBlPSJ0bnM6UGxjRGF0YVR5cGUiIC8+DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9Ikxp c3RPZlBsY0RhdGFUeXBlIj4NCiAgICA8eHM6c2VxdWVuY2U+DQogICAgICA8eHM6ZWxlbWVudCBu YW1lPSJQbGNEYXRhVHlwZSIgdHlwZT0idG5zOlBsY0RhdGFUeXBlIiBtaW5PY2N1cnM9IjAiIG1h eE9jY3Vycz0idW5ib3VuZGVkIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICA8L3hzOnNlcXVlbmNl Pg0KICA8L3hzOmNvbXBsZXhUeXBlPg0KICA8eHM6ZWxlbWVudCBuYW1lPSJMaXN0T2ZQbGNEYXRh VHlwZSIgdHlwZT0idG5zOkxpc3RPZlBsY0RhdGFUeXBlIiBuaWxsYWJsZT0idHJ1ZSI+PC94czpl bGVtZW50Pg0KDQogIDx4czpjb21wbGV4VHlwZSBuYW1lPSJQbGNUZW1wZXJhdHVyZVR5cGUiPg0K ICAgIDx4czphbm5vdGF0aW9uPg0KICAgICAgPHhzOmRvY3VtZW50YXRpb24+VGVtcGVyYXR1cmUg aW4gwrBDIG5leHQgdG8gdGhlIGhlYXRlciBhdCB0aGUgYm90dG9tLCBhbmQgYXdheSBmcm9tIHRo ZSBoZWF0ZXIgYXQgdGhlIHRvcC48L3hzOmRvY3VtZW50YXRpb24+DQogICAgPC94czphbm5vdGF0 aW9uPg0KICAgIDx4czpzZXF1ZW5jZT4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlRvcCIgdHlw ZT0ieHM6aW50IiBtaW5PY2N1cnM9IjAiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJCb3R0 b20iIHR5cGU9InhzOmludCIgbWluT2NjdXJzPSIwIiAvPg0KICAgIDwveHM6c2VxdWVuY2U+DQog IDwveHM6Y29tcGxleFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9IlBsY1RlbXBlcmF0dXJlVHlw ZSIgdHlwZT0idG5zOlBsY1RlbXBlcmF0dXJlVHlwZSIgLz4NCg0KICA8eHM6Y29tcGxleFR5cGUg bmFtZT0iTGlzdE9mUGxjVGVtcGVyYXR1cmVUeXBlIj4NCiAgICA8eHM6c2VxdWVuY2U+DQogICAg ICA8eHM6ZWxlbWVudCBuYW1lPSJQbGNUZW1wZXJhdHVyZVR5cGUiIHR5cGU9InRuczpQbGNUZW1w ZXJhdHVyZVR5cGUiIG1pbk9jY3Vycz0iMCIgbWF4T2NjdXJzPSJ1bmJvdW5kZWQiIG5pbGxhYmxl PSJ0cnVlIiAvPg0KICAgIDwveHM6c2VxdWVuY2U+DQogIDwveHM6Y29tcGxleFR5cGU+DQogIDx4 czplbGVtZW50IG5hbWU9Ikxpc3RPZlBsY1RlbXBlcmF0dXJlVHlwZSIgdHlwZT0idG5zOkxpc3RP ZlBsY1RlbXBlcmF0dXJlVHlwZSIgbmlsbGFibGU9InRydWUiPjwveHM6ZWxlbWVudD4NCg0KICA8 eHM6c2ltcGxlVHlwZSAgbmFtZT0iUGxjSGVhdGVyU3RhdGVUeXBlIj4NCiAgICA8eHM6YW5ub3Rh dGlvbj4NCiAgICAgIDx4czpkb2N1bWVudGF0aW9uPkhlYXRlciB3b3JraW5nIHN0YXRlLjwveHM6 ZG9jdW1lbnRhdGlvbj4NCiAgICA8L3hzOmFubm90YXRpb24+DQogICAgPHhzOnJlc3RyaWN0aW9u IGJhc2U9InhzOnN0cmluZyI+DQogICAgICA8eHM6ZW51bWVyYXRpb24gdmFsdWU9Ik9mZl8wIiAv Pg0KICAgICAgPHhzOmVudW1lcmF0aW9uIHZhbHVlPSJPbl8xIiAvPg0KICAgIDwveHM6cmVzdHJp Y3Rpb24+DQogIDwveHM6c2ltcGxlVHlwZT4NCiAgPHhzOmVsZW1lbnQgbmFtZT0iUGxjSGVhdGVy U3RhdGVUeXBlIiB0eXBlPSJ0bnM6UGxjSGVhdGVyU3RhdGVUeXBlIiAvPg0KDQogIDx4czpjb21w bGV4VHlwZSBuYW1lPSJMaXN0T2ZQbGNIZWF0ZXJTdGF0ZVR5cGUiPg0KICAgIDx4czpzZXF1ZW5j ZT4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlBsY0hlYXRlclN0YXRlVHlwZSIgdHlwZT0idG5z OlBsY0hlYXRlclN0YXRlVHlwZSIgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9InVuYm91bmRlZCIg Lz4NCiAgICA8L3hzOnNlcXVlbmNlPg0KICA8L3hzOmNvbXBsZXhUeXBlPg0KICA8eHM6ZWxlbWVu dCBuYW1lPSJMaXN0T2ZQbGNIZWF0ZXJTdGF0ZVR5cGUiIHR5cGU9InRuczpMaXN0T2ZQbGNIZWF0 ZXJTdGF0ZVR5cGUiIG5pbGxhYmxlPSJ0cnVlIj48L3hzOmVsZW1lbnQ+DQoNCjwveHM6c2NoZW1h Pg== i=15 -1 1 1 0 false 0 ns=1;i=15088 Variable_2 0 NamespaceUri NamespaceUri 0 0 0 i=46 true ns=1;i=15086 i=40 false i=68 http://opcfoundation.org/UA/Plc i=12 -1 1 1 0 false 0 ns=1;i=15089 Variable_2 0 Deprecated Deprecated 0 0 0 i=46 true ns=1;i=15086 i=40 false i=68 true i=1 -1 1 1 0 false 0 ns=1;i=15090 Variable_2 1 PlcDataType PlcDataType 0 0 0 i=47 true ns=1;i=15086 i=40 false i=69 //xs:element[@name='PlcDataType'] i=12 -1 1 1 0 false 0 ns=1;i=15096 Object_1 0 Default JSON Default JSON 0 0 0 i=40 false i=76 i=38 true ns=1;i=15032 0 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Plc/Design/PlcModel.NodeSet2.xml ================================================  http://opcfoundation.org/UA/Plc i=1 i=2 i=3 i=4 i=5 i=6 i=7 i=8 i=9 i=10 i=11 i=13 i=12 i=15 i=14 i=16 i=17 i=18 i=20 i=21 i=19 i=22 i=26 i=27 i=28 i=47 i=46 i=35 i=36 i=48 i=45 i=40 i=37 i=38 i=39 i=53 i=52 i=51 i=54 i=9004 i=9005 i=17597 i=9006 i=15112 i=17604 i=17603 PlcDataType Temperature in °C, pressure in Pa and heater state. i=22 PlcTemperatureType Temperature in °C next to the heater at the bottom, and away from the heater at the top. i=22 PlcHeaterStateType Heater working state. ns=1;i=15015 i=29 EnumStrings i=68 ns=1;i=15014 Off On PlcType ns=1;i=15003 i=58 PlcStatus i=63 i=78 ns=1;i=15068 ns=1;i=15084 20 20 100020 On Plc #1 A simple plc. ns=1;i=15013 i=85 ns=1;i=15068 PlcStatus i=63 ns=1;i=15070 ns=1;i=15084 20 20 100020 On Default Binary ns=1;i=15032 ns=1;i=15078 i=76 Default Binary ns=1;i=15001 ns=1;i=15005 i=76 PlcModel ns=1;i=15076 ns=1;i=15077 ns=1;i=15078 ns=1;i=15005 i=93 i=72 PG9wYzpUeXBlRGljdGlvbmFyeQ0KICB4bWxuczpvcGM9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9y Zy9CaW5hcnlTY2hlbWEvIg0KICB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1M U2NoZW1hLWluc3RhbmNlIg0KICB4bWxuczp1YT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VB LyINCiAgeG1sbnM6dG5zPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvUGxjIg0KICBEZWZh dWx0Qnl0ZU9yZGVyPSJMaXR0bGVFbmRpYW4iDQogIFRhcmdldE5hbWVzcGFjZT0iaHR0cDovL29w Y2ZvdW5kYXRpb24ub3JnL1VBL1BsYyINCj4NCiAgPG9wYzpJbXBvcnQgTmFtZXNwYWNlPSJodHRw Oi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvIiBMb2NhdGlvbj0iT3BjLlVhLkJpbmFyeVNjaGVtYS5i c2QiLz4NCg0KICA8b3BjOlN0cnVjdHVyZWRUeXBlIE5hbWU9IlBsY0RhdGFUeXBlIiBCYXNlVHlw ZT0idWE6RXh0ZW5zaW9uT2JqZWN0Ij4NCiAgICA8b3BjOkRvY3VtZW50YXRpb24+VGVtcGVyYXR1 cmUgaW4gwrBDLCBwcmVzc3VyZSBpbiBQYSBhbmQgaGVhdGVyIHN0YXRlLjwvb3BjOkRvY3VtZW50 YXRpb24+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJUZW1wZXJhdHVyZSIgVHlwZU5hbWU9InRuczpQ bGNUZW1wZXJhdHVyZVR5cGUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJQcmVzc3VyZSIgVHlw ZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkhlYXRlclN0YXRlIiBU eXBlTmFtZT0idG5zOlBsY0hlYXRlclN0YXRlVHlwZSIgLz4NCiAgPC9vcGM6U3RydWN0dXJlZFR5 cGU+DQoNCiAgPG9wYzpTdHJ1Y3R1cmVkVHlwZSBOYW1lPSJQbGNUZW1wZXJhdHVyZVR5cGUiIEJh c2VUeXBlPSJ1YTpFeHRlbnNpb25PYmplY3QiPg0KICAgIDxvcGM6RG9jdW1lbnRhdGlvbj5UZW1w ZXJhdHVyZSBpbiDCsEMgbmV4dCB0byB0aGUgaGVhdGVyIGF0IHRoZSBib3R0b20sIGFuZCBhd2F5 IGZyb20gdGhlIGhlYXRlciBhdCB0aGUgdG9wLjwvb3BjOkRvY3VtZW50YXRpb24+DQogICAgPG9w YzpGaWVsZCBOYW1lPSJUb3AiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVs ZCBOYW1lPSJCb3R0b20iIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogIDwvb3BjOlN0cnVjdHVy ZWRUeXBlPg0KDQogIDxvcGM6RW51bWVyYXRlZFR5cGUgTmFtZT0iUGxjSGVhdGVyU3RhdGVUeXBl IiBMZW5ndGhJbkJpdHM9IjMyIj4NCiAgICA8b3BjOkRvY3VtZW50YXRpb24+SGVhdGVyIHdvcmtp bmcgc3RhdGUuPC9vcGM6RG9jdW1lbnRhdGlvbj4NCiAgICA8b3BjOkVudW1lcmF0ZWRWYWx1ZSBO YW1lPSJPZmYiIFZhbHVlPSIwIiAvPg0KICAgIDxvcGM6RW51bWVyYXRlZFZhbHVlIE5hbWU9Ik9u IiBWYWx1ZT0iMSIgLz4NCiAgPC9vcGM6RW51bWVyYXRlZFR5cGU+DQoNCjwvb3BjOlR5cGVEaWN0 aW9uYXJ5Pg== NamespaceUri i=68 ns=1;i=15074 http://opcfoundation.org/UA/Plc Deprecated i=68 ns=1;i=15074 true PlcDataType i=69 ns=1;i=15074 PlcDataType PlcTemperatureType i=69 ns=1;i=15074 PlcTemperatureType Default XML ns=1;i=15032 ns=1;i=15090 i=76 Default XML ns=1;i=15001 ns=1;i=15009 i=76 PlcModel ns=1;i=15088 ns=1;i=15089 ns=1;i=15090 ns=1;i=15009 i=92 i=72 PHhzOnNjaGVtYQ0KICB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEi DQogIHhtbG5zOnVhPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvMjAwOC8wMi9UeXBlcy54 c2QiDQogIHhtbG5zOnRucz0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VBL1BsYyINCiAgdGFy Z2V0TmFtZXNwYWNlPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvUGxjIg0KICBlbGVtZW50 Rm9ybURlZmF1bHQ9InF1YWxpZmllZCINCj4NCiAgPHhzOmltcG9ydCBuYW1lc3BhY2U9Imh0dHA6 Ly9vcGNmb3VuZGF0aW9uLm9yZy9VQS8yMDA4LzAyL1R5cGVzLnhzZCIgLz4NCg0KICA8eHM6Y29t cGxleFR5cGUgbmFtZT0iUGxjRGF0YVR5cGUiPg0KICAgIDx4czphbm5vdGF0aW9uPg0KICAgICAg PHhzOmRvY3VtZW50YXRpb24+VGVtcGVyYXR1cmUgaW4gwrBDLCBwcmVzc3VyZSBpbiBQYSBhbmQg aGVhdGVyIHN0YXRlLjwveHM6ZG9jdW1lbnRhdGlvbj4NCiAgICA8L3hzOmFubm90YXRpb24+DQog ICAgPHhzOnNlcXVlbmNlPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iVGVtcGVyYXR1cmUiIHR5 cGU9InRuczpQbGNUZW1wZXJhdHVyZVR5cGUiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUi IC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJQcmVzc3VyZSIgdHlwZT0ieHM6aW50IiBtaW5P Y2N1cnM9IjAiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJIZWF0ZXJTdGF0ZSIgdHlwZT0i dG5zOlBsY0hlYXRlclN0YXRlVHlwZSIgbWluT2NjdXJzPSIwIiAvPg0KICAgIDwveHM6c2VxdWVu Y2U+DQogIDwveHM6Y29tcGxleFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9IlBsY0RhdGFUeXBl IiB0eXBlPSJ0bnM6UGxjRGF0YVR5cGUiIC8+DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9Ikxp c3RPZlBsY0RhdGFUeXBlIj4NCiAgICA8eHM6c2VxdWVuY2U+DQogICAgICA8eHM6ZWxlbWVudCBu YW1lPSJQbGNEYXRhVHlwZSIgdHlwZT0idG5zOlBsY0RhdGFUeXBlIiBtaW5PY2N1cnM9IjAiIG1h eE9jY3Vycz0idW5ib3VuZGVkIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICA8L3hzOnNlcXVlbmNl Pg0KICA8L3hzOmNvbXBsZXhUeXBlPg0KICA8eHM6ZWxlbWVudCBuYW1lPSJMaXN0T2ZQbGNEYXRh VHlwZSIgdHlwZT0idG5zOkxpc3RPZlBsY0RhdGFUeXBlIiBuaWxsYWJsZT0idHJ1ZSI+PC94czpl bGVtZW50Pg0KDQogIDx4czpjb21wbGV4VHlwZSBuYW1lPSJQbGNUZW1wZXJhdHVyZVR5cGUiPg0K ICAgIDx4czphbm5vdGF0aW9uPg0KICAgICAgPHhzOmRvY3VtZW50YXRpb24+VGVtcGVyYXR1cmUg aW4gwrBDIG5leHQgdG8gdGhlIGhlYXRlciBhdCB0aGUgYm90dG9tLCBhbmQgYXdheSBmcm9tIHRo ZSBoZWF0ZXIgYXQgdGhlIHRvcC48L3hzOmRvY3VtZW50YXRpb24+DQogICAgPC94czphbm5vdGF0 aW9uPg0KICAgIDx4czpzZXF1ZW5jZT4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlRvcCIgdHlw ZT0ieHM6aW50IiBtaW5PY2N1cnM9IjAiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJCb3R0 b20iIHR5cGU9InhzOmludCIgbWluT2NjdXJzPSIwIiAvPg0KICAgIDwveHM6c2VxdWVuY2U+DQog IDwveHM6Y29tcGxleFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9IlBsY1RlbXBlcmF0dXJlVHlw ZSIgdHlwZT0idG5zOlBsY1RlbXBlcmF0dXJlVHlwZSIgLz4NCg0KICA8eHM6Y29tcGxleFR5cGUg bmFtZT0iTGlzdE9mUGxjVGVtcGVyYXR1cmVUeXBlIj4NCiAgICA8eHM6c2VxdWVuY2U+DQogICAg ICA8eHM6ZWxlbWVudCBuYW1lPSJQbGNUZW1wZXJhdHVyZVR5cGUiIHR5cGU9InRuczpQbGNUZW1w ZXJhdHVyZVR5cGUiIG1pbk9jY3Vycz0iMCIgbWF4T2NjdXJzPSJ1bmJvdW5kZWQiIG5pbGxhYmxl PSJ0cnVlIiAvPg0KICAgIDwveHM6c2VxdWVuY2U+DQogIDwveHM6Y29tcGxleFR5cGU+DQogIDx4 czplbGVtZW50IG5hbWU9Ikxpc3RPZlBsY1RlbXBlcmF0dXJlVHlwZSIgdHlwZT0idG5zOkxpc3RP ZlBsY1RlbXBlcmF0dXJlVHlwZSIgbmlsbGFibGU9InRydWUiPjwveHM6ZWxlbWVudD4NCg0KICA8 eHM6c2ltcGxlVHlwZSAgbmFtZT0iUGxjSGVhdGVyU3RhdGVUeXBlIj4NCiAgICA8eHM6YW5ub3Rh dGlvbj4NCiAgICAgIDx4czpkb2N1bWVudGF0aW9uPkhlYXRlciB3b3JraW5nIHN0YXRlLjwveHM6 ZG9jdW1lbnRhdGlvbj4NCiAgICA8L3hzOmFubm90YXRpb24+DQogICAgPHhzOnJlc3RyaWN0aW9u IGJhc2U9InhzOnN0cmluZyI+DQogICAgICA8eHM6ZW51bWVyYXRpb24gdmFsdWU9Ik9mZl8wIiAv Pg0KICAgICAgPHhzOmVudW1lcmF0aW9uIHZhbHVlPSJPbl8xIiAvPg0KICAgIDwveHM6cmVzdHJp Y3Rpb24+DQogIDwveHM6c2ltcGxlVHlwZT4NCiAgPHhzOmVsZW1lbnQgbmFtZT0iUGxjSGVhdGVy U3RhdGVUeXBlIiB0eXBlPSJ0bnM6UGxjSGVhdGVyU3RhdGVUeXBlIiAvPg0KDQogIDx4czpjb21w bGV4VHlwZSBuYW1lPSJMaXN0T2ZQbGNIZWF0ZXJTdGF0ZVR5cGUiPg0KICAgIDx4czpzZXF1ZW5j ZT4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlBsY0hlYXRlclN0YXRlVHlwZSIgdHlwZT0idG5z OlBsY0hlYXRlclN0YXRlVHlwZSIgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9InVuYm91bmRlZCIg Lz4NCiAgICA8L3hzOnNlcXVlbmNlPg0KICA8L3hzOmNvbXBsZXhUeXBlPg0KICA8eHM6ZWxlbWVu dCBuYW1lPSJMaXN0T2ZQbGNIZWF0ZXJTdGF0ZVR5cGUiIHR5cGU9InRuczpMaXN0T2ZQbGNIZWF0 ZXJTdGF0ZVR5cGUiIG5pbGxhYmxlPSJ0cnVlIj48L3hzOmVsZW1lbnQ+DQoNCjwveHM6c2NoZW1h Pg== NamespaceUri i=68 ns=1;i=15086 http://opcfoundation.org/UA/Plc Deprecated i=68 ns=1;i=15086 true PlcDataType i=69 ns=1;i=15086 //xs:element[@name='PlcDataType'] PlcTemperatureType i=69 ns=1;i=15086 //xs:element[@name='PlcTemperatureType'] Default JSON ns=1;i=15032 i=76 Default JSON ns=1;i=15001 i=76 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Plc/Design/PlcModel.PredefinedNodes.xml ================================================  http://opcfoundation.org/UA/Plc DataType_64 ns=1;i=15032 1 PlcDataType Temperature in °C, pressure in Pa and heater state. i=22 i=14798 i=22 Structure_0 Temperature ns=1;i=15001 -1 0 false Pressure i=6 -1 0 false HeaterState ns=1;i=15014 -1 0 false DataType_64 ns=1;i=15001 1 PlcTemperatureType Temperature in °C next to the heater at the bottom, and away from the heater at the top. i=22 i=14798 i=22 Structure_0 Top i=6 -1 0 false Bottom i=6 -1 0 false DataType_64 ns=1;i=15014 1 PlcHeaterStateType Heater working state. i=29 i=14799 0 Off Off 1 On On Variable_2 ns=1;i=15015 0 EnumStrings i=46 i=68 15015 Off On i=21 1 0 1 1 ObjectType_8 ns=1;i=15068 1 PlcType i=58 Variable_2 ns=1;i=15003 1 PlcStatus i=47 i=63 i=78 15003 ns=1;i=15084 20 20 100020 On ns=1;i=15032 -1 1 1 Object_1 ns=1;i=15070 1 Plc #1 A simple plc. i=47 ns=1;i=15068 15070 1 i=35 true i=85 Variable_2 ns=1;i=15013 1 PlcStatus i=47 i=63 15013 ns=1;i=15084 20 20 100020 On ns=1;i=15032 -1 1 1 Object_1 ns=1;i=15072 0 Default Binary i=76 15072 i=38 true ns=1;i=15032 i=39 ns=1;i=15078 Object_1 ns=1;i=15004 0 Default Binary i=76 15004 i=38 true ns=1;i=15001 i=39 ns=1;i=15005 Variable_2 ns=1;i=15074 1 PlcModel i=72 15074 PG9wYzpUeXBlRGljdGlvbmFyeQ0KICB4bWxuczpvcGM9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9y Zy9CaW5hcnlTY2hlbWEvIg0KICB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1M U2NoZW1hLWluc3RhbmNlIg0KICB4bWxuczp1YT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VB LyINCiAgeG1sbnM6dG5zPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvUGxjIg0KICBEZWZh dWx0Qnl0ZU9yZGVyPSJMaXR0bGVFbmRpYW4iDQogIFRhcmdldE5hbWVzcGFjZT0iaHR0cDovL29w Y2ZvdW5kYXRpb24ub3JnL1VBL1BsYyINCj4NCiAgPG9wYzpJbXBvcnQgTmFtZXNwYWNlPSJodHRw Oi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvIiBMb2NhdGlvbj0iT3BjLlVhLkJpbmFyeVNjaGVtYS5i c2QiLz4NCg0KICA8b3BjOlN0cnVjdHVyZWRUeXBlIE5hbWU9IlBsY0RhdGFUeXBlIiBCYXNlVHlw ZT0idWE6RXh0ZW5zaW9uT2JqZWN0Ij4NCiAgICA8b3BjOkRvY3VtZW50YXRpb24+VGVtcGVyYXR1 cmUgaW4gwrBDLCBwcmVzc3VyZSBpbiBQYSBhbmQgaGVhdGVyIHN0YXRlLjwvb3BjOkRvY3VtZW50 YXRpb24+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJUZW1wZXJhdHVyZSIgVHlwZU5hbWU9InRuczpQ bGNUZW1wZXJhdHVyZVR5cGUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJQcmVzc3VyZSIgVHlw ZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkhlYXRlclN0YXRlIiBU eXBlTmFtZT0idG5zOlBsY0hlYXRlclN0YXRlVHlwZSIgLz4NCiAgPC9vcGM6U3RydWN0dXJlZFR5 cGU+DQoNCiAgPG9wYzpTdHJ1Y3R1cmVkVHlwZSBOYW1lPSJQbGNUZW1wZXJhdHVyZVR5cGUiIEJh c2VUeXBlPSJ1YTpFeHRlbnNpb25PYmplY3QiPg0KICAgIDxvcGM6RG9jdW1lbnRhdGlvbj5UZW1w ZXJhdHVyZSBpbiDCsEMgbmV4dCB0byB0aGUgaGVhdGVyIGF0IHRoZSBib3R0b20sIGFuZCBhd2F5 IGZyb20gdGhlIGhlYXRlciBhdCB0aGUgdG9wLjwvb3BjOkRvY3VtZW50YXRpb24+DQogICAgPG9w YzpGaWVsZCBOYW1lPSJUb3AiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVs ZCBOYW1lPSJCb3R0b20iIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogIDwvb3BjOlN0cnVjdHVy ZWRUeXBlPg0KDQogIDxvcGM6RW51bWVyYXRlZFR5cGUgTmFtZT0iUGxjSGVhdGVyU3RhdGVUeXBl IiBMZW5ndGhJbkJpdHM9IjMyIj4NCiAgICA8b3BjOkRvY3VtZW50YXRpb24+SGVhdGVyIHdvcmtp bmcgc3RhdGUuPC9vcGM6RG9jdW1lbnRhdGlvbj4NCiAgICA8b3BjOkVudW1lcmF0ZWRWYWx1ZSBO YW1lPSJPZmYiIFZhbHVlPSIwIiAvPg0KICAgIDxvcGM6RW51bWVyYXRlZFZhbHVlIE5hbWU9Ik9u IiBWYWx1ZT0iMSIgLz4NCiAgPC9vcGM6RW51bWVyYXRlZFR5cGU+DQoNCjwvb3BjOlR5cGVEaWN0 aW9uYXJ5Pg== i=15 -1 1 1 i=47 true i=93 Variable_2 ns=1;i=15076 0 NamespaceUri i=46 i=68 15076 http://opcfoundation.org/UA/Plc i=12 -1 1 1 Variable_2 ns=1;i=15077 0 Deprecated i=46 i=68 15077 true i=1 -1 1 1 Variable_2 ns=1;i=15078 1 PlcDataType i=47 i=69 15078 PlcDataType i=12 -1 1 1 Variable_2 ns=1;i=15005 1 PlcTemperatureType i=47 i=69 15005 PlcTemperatureType i=12 -1 1 1 Object_1 ns=1;i=15084 0 Default XML i=76 15084 i=38 true ns=1;i=15032 i=39 ns=1;i=15090 Object_1 ns=1;i=15008 0 Default XML i=76 15008 i=38 true ns=1;i=15001 i=39 ns=1;i=15009 Variable_2 ns=1;i=15086 1 PlcModel i=72 15086 PHhzOnNjaGVtYQ0KICB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEi DQogIHhtbG5zOnVhPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvMjAwOC8wMi9UeXBlcy54 c2QiDQogIHhtbG5zOnRucz0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VBL1BsYyINCiAgdGFy Z2V0TmFtZXNwYWNlPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvUGxjIg0KICBlbGVtZW50 Rm9ybURlZmF1bHQ9InF1YWxpZmllZCINCj4NCiAgPHhzOmltcG9ydCBuYW1lc3BhY2U9Imh0dHA6 Ly9vcGNmb3VuZGF0aW9uLm9yZy9VQS8yMDA4LzAyL1R5cGVzLnhzZCIgLz4NCg0KICA8eHM6Y29t cGxleFR5cGUgbmFtZT0iUGxjRGF0YVR5cGUiPg0KICAgIDx4czphbm5vdGF0aW9uPg0KICAgICAg PHhzOmRvY3VtZW50YXRpb24+VGVtcGVyYXR1cmUgaW4gwrBDLCBwcmVzc3VyZSBpbiBQYSBhbmQg aGVhdGVyIHN0YXRlLjwveHM6ZG9jdW1lbnRhdGlvbj4NCiAgICA8L3hzOmFubm90YXRpb24+DQog ICAgPHhzOnNlcXVlbmNlPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iVGVtcGVyYXR1cmUiIHR5 cGU9InRuczpQbGNUZW1wZXJhdHVyZVR5cGUiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUi IC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJQcmVzc3VyZSIgdHlwZT0ieHM6aW50IiBtaW5P Y2N1cnM9IjAiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJIZWF0ZXJTdGF0ZSIgdHlwZT0i dG5zOlBsY0hlYXRlclN0YXRlVHlwZSIgbWluT2NjdXJzPSIwIiAvPg0KICAgIDwveHM6c2VxdWVu Y2U+DQogIDwveHM6Y29tcGxleFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9IlBsY0RhdGFUeXBl IiB0eXBlPSJ0bnM6UGxjRGF0YVR5cGUiIC8+DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9Ikxp c3RPZlBsY0RhdGFUeXBlIj4NCiAgICA8eHM6c2VxdWVuY2U+DQogICAgICA8eHM6ZWxlbWVudCBu YW1lPSJQbGNEYXRhVHlwZSIgdHlwZT0idG5zOlBsY0RhdGFUeXBlIiBtaW5PY2N1cnM9IjAiIG1h eE9jY3Vycz0idW5ib3VuZGVkIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICA8L3hzOnNlcXVlbmNl Pg0KICA8L3hzOmNvbXBsZXhUeXBlPg0KICA8eHM6ZWxlbWVudCBuYW1lPSJMaXN0T2ZQbGNEYXRh VHlwZSIgdHlwZT0idG5zOkxpc3RPZlBsY0RhdGFUeXBlIiBuaWxsYWJsZT0idHJ1ZSI+PC94czpl bGVtZW50Pg0KDQogIDx4czpjb21wbGV4VHlwZSBuYW1lPSJQbGNUZW1wZXJhdHVyZVR5cGUiPg0K ICAgIDx4czphbm5vdGF0aW9uPg0KICAgICAgPHhzOmRvY3VtZW50YXRpb24+VGVtcGVyYXR1cmUg aW4gwrBDIG5leHQgdG8gdGhlIGhlYXRlciBhdCB0aGUgYm90dG9tLCBhbmQgYXdheSBmcm9tIHRo ZSBoZWF0ZXIgYXQgdGhlIHRvcC48L3hzOmRvY3VtZW50YXRpb24+DQogICAgPC94czphbm5vdGF0 aW9uPg0KICAgIDx4czpzZXF1ZW5jZT4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlRvcCIgdHlw ZT0ieHM6aW50IiBtaW5PY2N1cnM9IjAiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJCb3R0 b20iIHR5cGU9InhzOmludCIgbWluT2NjdXJzPSIwIiAvPg0KICAgIDwveHM6c2VxdWVuY2U+DQog IDwveHM6Y29tcGxleFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9IlBsY1RlbXBlcmF0dXJlVHlw ZSIgdHlwZT0idG5zOlBsY1RlbXBlcmF0dXJlVHlwZSIgLz4NCg0KICA8eHM6Y29tcGxleFR5cGUg bmFtZT0iTGlzdE9mUGxjVGVtcGVyYXR1cmVUeXBlIj4NCiAgICA8eHM6c2VxdWVuY2U+DQogICAg ICA8eHM6ZWxlbWVudCBuYW1lPSJQbGNUZW1wZXJhdHVyZVR5cGUiIHR5cGU9InRuczpQbGNUZW1w ZXJhdHVyZVR5cGUiIG1pbk9jY3Vycz0iMCIgbWF4T2NjdXJzPSJ1bmJvdW5kZWQiIG5pbGxhYmxl PSJ0cnVlIiAvPg0KICAgIDwveHM6c2VxdWVuY2U+DQogIDwveHM6Y29tcGxleFR5cGU+DQogIDx4 czplbGVtZW50IG5hbWU9Ikxpc3RPZlBsY1RlbXBlcmF0dXJlVHlwZSIgdHlwZT0idG5zOkxpc3RP ZlBsY1RlbXBlcmF0dXJlVHlwZSIgbmlsbGFibGU9InRydWUiPjwveHM6ZWxlbWVudD4NCg0KICA8 eHM6c2ltcGxlVHlwZSAgbmFtZT0iUGxjSGVhdGVyU3RhdGVUeXBlIj4NCiAgICA8eHM6YW5ub3Rh dGlvbj4NCiAgICAgIDx4czpkb2N1bWVudGF0aW9uPkhlYXRlciB3b3JraW5nIHN0YXRlLjwveHM6 ZG9jdW1lbnRhdGlvbj4NCiAgICA8L3hzOmFubm90YXRpb24+DQogICAgPHhzOnJlc3RyaWN0aW9u IGJhc2U9InhzOnN0cmluZyI+DQogICAgICA8eHM6ZW51bWVyYXRpb24gdmFsdWU9Ik9mZl8wIiAv Pg0KICAgICAgPHhzOmVudW1lcmF0aW9uIHZhbHVlPSJPbl8xIiAvPg0KICAgIDwveHM6cmVzdHJp Y3Rpb24+DQogIDwveHM6c2ltcGxlVHlwZT4NCiAgPHhzOmVsZW1lbnQgbmFtZT0iUGxjSGVhdGVy U3RhdGVUeXBlIiB0eXBlPSJ0bnM6UGxjSGVhdGVyU3RhdGVUeXBlIiAvPg0KDQogIDx4czpjb21w bGV4VHlwZSBuYW1lPSJMaXN0T2ZQbGNIZWF0ZXJTdGF0ZVR5cGUiPg0KICAgIDx4czpzZXF1ZW5j ZT4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlBsY0hlYXRlclN0YXRlVHlwZSIgdHlwZT0idG5z OlBsY0hlYXRlclN0YXRlVHlwZSIgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9InVuYm91bmRlZCIg Lz4NCiAgICA8L3hzOnNlcXVlbmNlPg0KICA8L3hzOmNvbXBsZXhUeXBlPg0KICA8eHM6ZWxlbWVu dCBuYW1lPSJMaXN0T2ZQbGNIZWF0ZXJTdGF0ZVR5cGUiIHR5cGU9InRuczpMaXN0T2ZQbGNIZWF0 ZXJTdGF0ZVR5cGUiIG5pbGxhYmxlPSJ0cnVlIj48L3hzOmVsZW1lbnQ+DQoNCjwveHM6c2NoZW1h Pg== i=15 -1 1 1 i=47 true i=92 Variable_2 ns=1;i=15088 0 NamespaceUri i=46 i=68 15088 http://opcfoundation.org/UA/Plc i=12 -1 1 1 Variable_2 ns=1;i=15089 0 Deprecated i=46 i=68 15089 true i=1 -1 1 1 Variable_2 ns=1;i=15090 1 PlcDataType i=47 i=69 15090 //xs:element[@name='PlcDataType'] i=12 -1 1 1 Variable_2 ns=1;i=15009 1 PlcTemperatureType i=47 i=69 15009 //xs:element[@name='PlcTemperatureType'] i=12 -1 1 1 Object_1 ns=1;i=15096 0 Default JSON i=76 15096 i=38 true ns=1;i=15032 Object_1 ns=1;i=15012 0 Default JSON i=76 15012 i=38 true ns=1;i=15001 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Plc/Design/PlcModel.Types.bsd ================================================ Temperature in °C, pressure in Pa and heater state. Temperature in °C next to the heater at the bottom, and away from the heater at the top. Heater working state. ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Plc/Design/PlcModel.Types.xsd ================================================ Temperature in °C, pressure in Pa and heater state. Temperature in °C next to the heater at the bottom, and away from the heater at the top. Heater working state. ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/SimpleEvents/Design/ModelDesign.csv ================================================ CycleStepDataType,183,DataType SystemCycleStartedEventType,184,ObjectType SystemCycleStartedEventType_EventId,185,Variable SystemCycleStartedEventType_EventType,186,Variable SystemCycleStartedEventType_SourceNode,187,Variable SystemCycleStartedEventType_SourceName,188,Variable SystemCycleStartedEventType_Time,189,Variable SystemCycleStartedEventType_ReceiveTime,190,Variable SystemCycleStartedEventType_LocalTime,191,Variable SystemCycleStartedEventType_Message,192,Variable SystemCycleStartedEventType_Severity,193,Variable SystemCycleStartedEventType_CycleId,194,Variable SystemCycleStartedEventType_Steps,196,Variable SystemCycleAbortedEventType,197,ObjectType SystemCycleAbortedEventType_EventId,198,Variable SystemCycleAbortedEventType_EventType,199,Variable SystemCycleAbortedEventType_SourceNode,200,Variable SystemCycleAbortedEventType_SourceName,201,Variable SystemCycleAbortedEventType_Time,202,Variable SystemCycleAbortedEventType_ReceiveTime,203,Variable SystemCycleAbortedEventType_LocalTime,204,Variable SystemCycleAbortedEventType_Message,205,Variable SystemCycleAbortedEventType_Severity,206,Variable SystemCycleAbortedEventType_CycleId,207,Variable SystemCycleFinishedEventType,210,ObjectType SystemCycleFinishedEventType_EventId,211,Variable SystemCycleFinishedEventType_EventType,212,Variable SystemCycleFinishedEventType_SourceNode,213,Variable SystemCycleFinishedEventType_SourceName,214,Variable SystemCycleFinishedEventType_Time,215,Variable SystemCycleFinishedEventType_ReceiveTime,216,Variable SystemCycleFinishedEventType_LocalTime,217,Variable SystemCycleFinishedEventType_Message,218,Variable SystemCycleFinishedEventType_Severity,219,Variable SystemCycleFinishedEventType_CycleId,220,Variable CycleStepDataType_Encoding_DefaultXml,221,Object SimpleEvents_BinarySchema,222,Variable SimpleEvents_BinarySchema_DataTypeVersion,223,Variable SimpleEvents_BinarySchema_NamespaceUri,224,Variable SimpleEvents_BinarySchema_CycleStepDataType,225,Variable SimpleEvents_BinarySchema_CycleStepDataType_DataTypeVersion,226,Variable SimpleEvents_BinarySchema_CycleStepDataType_DictionaryFragment,227,Variable CycleStepDataType_Encoding_DefaultBinary,228,Object SimpleEvents_XmlSchema,229,Variable SimpleEvents_XmlSchema_DataTypeVersion,230,Variable SimpleEvents_XmlSchema_NamespaceUri,231,Variable SimpleEvents_XmlSchema_CycleStepDataType,232,Variable SimpleEvents_XmlSchema_CycleStepDataType_DataTypeVersion,233,Variable SimpleEvents_XmlSchema_CycleStepDataType_DictionaryFragment,234,Variable SystemCycleStatusEventType,235,ObjectType SystemCycleStatusEventType_EventId,236,Variable SystemCycleStatusEventType_EventType,237,Variable SystemCycleStatusEventType_SourceNode,238,Variable SystemCycleStatusEventType_SourceName,239,Variable SystemCycleStatusEventType_Time,240,Variable SystemCycleStatusEventType_ReceiveTime,241,Variable SystemCycleStatusEventType_LocalTime,242,Variable SystemCycleStatusEventType_Message,243,Variable SystemCycleStatusEventType_Severity,244,Variable SystemCycleStatusEventType_CycleId,245,Variable SystemCycleStatusEventType_CurrentStep,246,Variable SystemCycleStartedEventType_CurrentStep,247,Variable SystemCycleAbortedEventType_CurrentStep,248,Variable SystemCycleAbortedEventType_Error,249,Variable SystemCycleFinishedEventType_CurrentStep,250,Variable SimpleEvents_BinarySchema_Deprecated,15001,Variable SimpleEvents_XmlSchema_Deprecated,15002,Variable CycleStepDataType_Encoding_DefaultJson,15003,Object ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/SimpleEvents/Design/ModelDesign.xml ================================================  http://opcfoundation.org/UA/ http://opcfoundation.org/SimpleEvents An event raised when a system cycle starts. An event raised when a system cycle starts. An event raised when a system cycle is aborted. An event raised when a system cycle completes. ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/SimpleEvents/Design/SimpleEvents.Classes.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; using System; using System.Collections.Generic; namespace SimpleEvents { #region SystemCycleStatusEventState Class #if (!OPCUA_EXCLUDE_SystemCycleStatusEventState) /// /// Stores an instance of the SystemCycleStatusEventType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class SystemCycleStatusEventState : SystemEventState { #region Constructors /// /// Initializes the type with its default attribute values. /// public SystemCycleStatusEventState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(SimpleEvents.ObjectTypes.SystemCycleStatusEventType, SimpleEvents.Namespaces.SimpleEvents, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACUAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvU2ltcGxlRXZlbnRz/////wRggAIBAAAAAQAi" + "AAAAU3lzdGVtQ3ljbGVTdGF0dXNFdmVudFR5cGVJbnN0YW5jZQEB6wABAesA6wAAAP////8KAAAAFWCJ" + "CgIAAAAAAAcAAABFdmVudElkAQHsAAAuAETsAAAAAA//////AQH/////AAAAABVgiQoCAAAAAAAJAAAA" + "RXZlbnRUeXBlAQHtAAAuAETtAAAAABH/////AQH/////AAAAABVgiQoCAAAAAAAKAAAAU291cmNlTm9k" + "ZQEB7gAALgBE7gAAAAAR/////wEB/////wAAAAAVYIkKAgAAAAAACgAAAFNvdXJjZU5hbWUBAe8AAC4A" + "RO8AAAAADP////8BAf////8AAAAAFWCJCgIAAAAAAAQAAABUaW1lAQHwAAAuAETwAAAAAQAmAf////8B" + "Af////8AAAAAFWCJCgIAAAAAAAsAAABSZWNlaXZlVGltZQEB8QAALgBE8QAAAAEAJgH/////AQH/////" + "AAAAABVgiQoCAAAAAAAHAAAATWVzc2FnZQEB8wAALgBE8wAAAAAV/////wEB/////wAAAAAVYIkKAgAA" + "AAAACAAAAFNldmVyaXR5AQH0AAAuAET0AAAAAAX/////AQH/////AAAAABVgiQoCAAAAAQAHAAAAQ3lj" + "bGVJZAEB9QAALgBE9QAAAAAM/////wEB/////wAAAAAVYIkKAgAAAAEACwAAAEN1cnJlbnRTdGVwAQH2" + "AAAuAET2AAAAAQG3AP////8BAf////8AAAAA"; #endregion #endif #endregion #region Public Properties /// public PropertyState CycleId { get { return m_cycleId; } set { if (!Object.ReferenceEquals(m_cycleId, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_cycleId = value; } } /// public PropertyState CurrentStep { get { return m_currentStep; } set { if (!Object.ReferenceEquals(m_currentStep, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_currentStep = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_cycleId != null) { children.Add(m_cycleId); } if (m_currentStep != null) { children.Add(m_currentStep); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case SimpleEvents.BrowseNames.CycleId: { if (createOrReplace) { if (CycleId == null) { if (replacement == null) { CycleId = new PropertyState(this); } else { CycleId = (PropertyState)replacement; } } } instance = CycleId; break; } case SimpleEvents.BrowseNames.CurrentStep: { if (createOrReplace) { if (CurrentStep == null) { if (replacement == null) { CurrentStep = new PropertyState(this); } else { CurrentStep = (PropertyState)replacement; } } } instance = CurrentStep; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private PropertyState m_cycleId; private PropertyState m_currentStep; #endregion } #endif #endregion #region SystemCycleStartedEventState Class #if (!OPCUA_EXCLUDE_SystemCycleStartedEventState) /// /// Stores an instance of the SystemCycleStartedEventType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class SystemCycleStartedEventState : SystemCycleStatusEventState { #region Constructors /// /// Initializes the type with its default attribute values. /// public SystemCycleStartedEventState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(SimpleEvents.ObjectTypes.SystemCycleStartedEventType, SimpleEvents.Namespaces.SimpleEvents, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACUAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvU2ltcGxlRXZlbnRz/////wRggAIBAAAAAQAj" + "AAAAU3lzdGVtQ3ljbGVTdGFydGVkRXZlbnRUeXBlSW5zdGFuY2UBAbgAAQG4ALgAAAD/////CwAAABVg" + "iQoCAAAAAAAHAAAARXZlbnRJZAEBuQAALgBEuQAAAAAP/////wEB/////wAAAAAVYIkKAgAAAAAACQAA" + "AEV2ZW50VHlwZQEBugAALgBEugAAAAAR/////wEB/////wAAAAAVYIkKAgAAAAAACgAAAFNvdXJjZU5v" + "ZGUBAbsAAC4ARLsAAAAAEf////8BAf////8AAAAAFWCJCgIAAAAAAAoAAABTb3VyY2VOYW1lAQG8AAAu" + "AES8AAAAAAz/////AQH/////AAAAABVgiQoCAAAAAAAEAAAAVGltZQEBvQAALgBEvQAAAAEAJgH/////" + "AQH/////AAAAABVgiQoCAAAAAAALAAAAUmVjZWl2ZVRpbWUBAb4AAC4ARL4AAAABACYB/////wEB////" + "/wAAAAAVYIkKAgAAAAAABwAAAE1lc3NhZ2UBAcAAAC4ARMAAAAAAFf////8BAf////8AAAAAFWCJCgIA" + "AAAAAAgAAABTZXZlcml0eQEBwQAALgBEwQAAAAAF/////wEB/////wAAAAAVYIkKAgAAAAEABwAAAEN5" + "Y2xlSWQBAcIAAC4ARMIAAAAADP////8BAf////8AAAAAFWCJCgIAAAABAAsAAABDdXJyZW50U3RlcAEB" + "9wAALgBE9wAAAAEBtwD/////AQH/////AAAAABdgiQoCAAAAAQAFAAAAU3RlcHMBAcQAAC4ARMQAAAAB" + "AbcAAQAAAAEAAAAAAAAAAQH/////AAAAAA=="; #endregion #endif #endregion #region Public Properties /// public PropertyState Steps { get { return m_steps; } set { if (!Object.ReferenceEquals(m_steps, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_steps = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_steps != null) { children.Add(m_steps); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case SimpleEvents.BrowseNames.Steps: { if (createOrReplace) { if (Steps == null) { if (replacement == null) { Steps = new PropertyState(this); } else { Steps = (PropertyState)replacement; } } } instance = Steps; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private PropertyState m_steps; #endregion } #endif #endregion #region SystemCycleAbortedEventState Class #if (!OPCUA_EXCLUDE_SystemCycleAbortedEventState) /// /// Stores an instance of the SystemCycleAbortedEventType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class SystemCycleAbortedEventState : SystemCycleStatusEventState { #region Constructors /// /// Initializes the type with its default attribute values. /// public SystemCycleAbortedEventState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(SimpleEvents.ObjectTypes.SystemCycleAbortedEventType, SimpleEvents.Namespaces.SimpleEvents, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACUAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvU2ltcGxlRXZlbnRz/////wRggAIBAAAAAQAj" + "AAAAU3lzdGVtQ3ljbGVBYm9ydGVkRXZlbnRUeXBlSW5zdGFuY2UBAcUAAQHFAMUAAAD/////CwAAABVg" + "iQoCAAAAAAAHAAAARXZlbnRJZAEBxgAALgBExgAAAAAP/////wEB/////wAAAAAVYIkKAgAAAAAACQAA" + "AEV2ZW50VHlwZQEBxwAALgBExwAAAAAR/////wEB/////wAAAAAVYIkKAgAAAAAACgAAAFNvdXJjZU5v" + "ZGUBAcgAAC4ARMgAAAAAEf////8BAf////8AAAAAFWCJCgIAAAAAAAoAAABTb3VyY2VOYW1lAQHJAAAu" + "AETJAAAAAAz/////AQH/////AAAAABVgiQoCAAAAAAAEAAAAVGltZQEBygAALgBEygAAAAEAJgH/////" + "AQH/////AAAAABVgiQoCAAAAAAALAAAAUmVjZWl2ZVRpbWUBAcsAAC4ARMsAAAABACYB/////wEB////" + "/wAAAAAVYIkKAgAAAAAABwAAAE1lc3NhZ2UBAc0AAC4ARM0AAAAAFf////8BAf////8AAAAAFWCJCgIA" + "AAAAAAgAAABTZXZlcml0eQEBzgAALgBEzgAAAAAF/////wEB/////wAAAAAVYIkKAgAAAAEABwAAAEN5" + "Y2xlSWQBAc8AAC4ARM8AAAAADP////8BAf////8AAAAAFWCJCgIAAAABAAsAAABDdXJyZW50U3RlcAEB" + "+AAALgBE+AAAAAEBtwD/////AQH/////AAAAABVgiQoCAAAAAQAFAAAARXJyb3IBAfkAAC4ARPkAAAAA" + "E/////8BAf////8AAAAA"; #endregion #endif #endregion #region Public Properties /// public PropertyState Error { get { return m_error; } set { if (!Object.ReferenceEquals(m_error, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_error = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_error != null) { children.Add(m_error); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case SimpleEvents.BrowseNames.Error: { if (createOrReplace) { if (Error == null) { if (replacement == null) { Error = new PropertyState(this); } else { Error = (PropertyState)replacement; } } } instance = Error; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private PropertyState m_error; #endregion } #endif #endregion #region SystemCycleFinishedEventState Class #if (!OPCUA_EXCLUDE_SystemCycleFinishedEventState) /// /// Stores an instance of the SystemCycleFinishedEventType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class SystemCycleFinishedEventState : SystemCycleStatusEventState { #region Constructors /// /// Initializes the type with its default attribute values. /// public SystemCycleFinishedEventState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(SimpleEvents.ObjectTypes.SystemCycleFinishedEventType, SimpleEvents.Namespaces.SimpleEvents, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACUAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvU2ltcGxlRXZlbnRz/////wRggAIBAAAAAQAk" + "AAAAU3lzdGVtQ3ljbGVGaW5pc2hlZEV2ZW50VHlwZUluc3RhbmNlAQHSAAEB0gDSAAAA/////woAAAAV" + "YIkKAgAAAAAABwAAAEV2ZW50SWQBAdMAAC4ARNMAAAAAD/////8BAf////8AAAAAFWCJCgIAAAAAAAkA" + "AABFdmVudFR5cGUBAdQAAC4ARNQAAAAAEf////8BAf////8AAAAAFWCJCgIAAAAAAAoAAABTb3VyY2VO" + "b2RlAQHVAAAuAETVAAAAABH/////AQH/////AAAAABVgiQoCAAAAAAAKAAAAU291cmNlTmFtZQEB1gAA" + "LgBE1gAAAAAM/////wEB/////wAAAAAVYIkKAgAAAAAABAAAAFRpbWUBAdcAAC4ARNcAAAABACYB////" + "/wEB/////wAAAAAVYIkKAgAAAAAACwAAAFJlY2VpdmVUaW1lAQHYAAAuAETYAAAAAQAmAf////8BAf//" + "//8AAAAAFWCJCgIAAAAAAAcAAABNZXNzYWdlAQHaAAAuAETaAAAAABX/////AQH/////AAAAABVgiQoC" + "AAAAAAAIAAAAU2V2ZXJpdHkBAdsAAC4ARNsAAAAABf////8BAf////8AAAAAFWCJCgIAAAABAAcAAABD" + "eWNsZUlkAQHcAAAuAETcAAAAAAz/////AQH/////AAAAABVgiQoCAAAAAQALAAAAQ3VycmVudFN0ZXAB" + "AfoAAC4ARPoAAAABAbcA/////wEB/////wAAAAA="; #endregion #endif #endregion #region Public Properties #endregion #region Overridden Methods #endregion #region Private Fields #endregion } #endif #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/SimpleEvents/Design/SimpleEvents.Constants.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; namespace SimpleEvents { #region DataType Identifiers /// /// A class that declares constants for all DataTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class DataTypes { /// /// The identifier for the CycleStepDataType DataType. /// public const uint CycleStepDataType = 183; } #endregion #region Object Identifiers /// /// A class that declares constants for all Objects in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Objects { /// /// The identifier for the CycleStepDataType_Encoding_DefaultBinary Object. /// public const uint CycleStepDataType_Encoding_DefaultBinary = 228; /// /// The identifier for the CycleStepDataType_Encoding_DefaultXml Object. /// public const uint CycleStepDataType_Encoding_DefaultXml = 221; /// /// The identifier for the CycleStepDataType_Encoding_DefaultJson Object. /// public const uint CycleStepDataType_Encoding_DefaultJson = 15003; } #endregion #region ObjectType Identifiers /// /// A class that declares constants for all ObjectTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectTypes { /// /// The identifier for the SystemCycleStatusEventType ObjectType. /// public const uint SystemCycleStatusEventType = 235; /// /// The identifier for the SystemCycleStartedEventType ObjectType. /// public const uint SystemCycleStartedEventType = 184; /// /// The identifier for the SystemCycleAbortedEventType ObjectType. /// public const uint SystemCycleAbortedEventType = 197; /// /// The identifier for the SystemCycleFinishedEventType ObjectType. /// public const uint SystemCycleFinishedEventType = 210; } #endregion #region Variable Identifiers /// /// A class that declares constants for all Variables in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Variables { /// /// The identifier for the SystemCycleStatusEventType_CycleId Variable. /// public const uint SystemCycleStatusEventType_CycleId = 245; /// /// The identifier for the SystemCycleStatusEventType_CurrentStep Variable. /// public const uint SystemCycleStatusEventType_CurrentStep = 246; /// /// The identifier for the SystemCycleStartedEventType_Steps Variable. /// public const uint SystemCycleStartedEventType_Steps = 196; /// /// The identifier for the SystemCycleAbortedEventType_Error Variable. /// public const uint SystemCycleAbortedEventType_Error = 249; /// /// The identifier for the SimpleEvents_BinarySchema Variable. /// public const uint SimpleEvents_BinarySchema = 222; /// /// The identifier for the SimpleEvents_BinarySchema_NamespaceUri Variable. /// public const uint SimpleEvents_BinarySchema_NamespaceUri = 224; /// /// The identifier for the SimpleEvents_BinarySchema_Deprecated Variable. /// public const uint SimpleEvents_BinarySchema_Deprecated = 15001; /// /// The identifier for the SimpleEvents_BinarySchema_CycleStepDataType Variable. /// public const uint SimpleEvents_BinarySchema_CycleStepDataType = 225; /// /// The identifier for the SimpleEvents_XmlSchema Variable. /// public const uint SimpleEvents_XmlSchema = 229; /// /// The identifier for the SimpleEvents_XmlSchema_NamespaceUri Variable. /// public const uint SimpleEvents_XmlSchema_NamespaceUri = 231; /// /// The identifier for the SimpleEvents_XmlSchema_Deprecated Variable. /// public const uint SimpleEvents_XmlSchema_Deprecated = 15002; /// /// The identifier for the SimpleEvents_XmlSchema_CycleStepDataType Variable. /// public const uint SimpleEvents_XmlSchema_CycleStepDataType = 232; } #endregion #region DataType Node Identifiers /// /// A class that declares constants for all DataTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class DataTypeIds { /// /// The identifier for the CycleStepDataType DataType. /// public static readonly ExpandedNodeId CycleStepDataType = new ExpandedNodeId(SimpleEvents.DataTypes.CycleStepDataType, SimpleEvents.Namespaces.SimpleEvents); } #endregion #region Object Node Identifiers /// /// A class that declares constants for all Objects in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectIds { /// /// The identifier for the CycleStepDataType_Encoding_DefaultBinary Object. /// public static readonly ExpandedNodeId CycleStepDataType_Encoding_DefaultBinary = new ExpandedNodeId(SimpleEvents.Objects.CycleStepDataType_Encoding_DefaultBinary, SimpleEvents.Namespaces.SimpleEvents); /// /// The identifier for the CycleStepDataType_Encoding_DefaultXml Object. /// public static readonly ExpandedNodeId CycleStepDataType_Encoding_DefaultXml = new ExpandedNodeId(SimpleEvents.Objects.CycleStepDataType_Encoding_DefaultXml, SimpleEvents.Namespaces.SimpleEvents); /// /// The identifier for the CycleStepDataType_Encoding_DefaultJson Object. /// public static readonly ExpandedNodeId CycleStepDataType_Encoding_DefaultJson = new ExpandedNodeId(SimpleEvents.Objects.CycleStepDataType_Encoding_DefaultJson, SimpleEvents.Namespaces.SimpleEvents); } #endregion #region ObjectType Node Identifiers /// /// A class that declares constants for all ObjectTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectTypeIds { /// /// The identifier for the SystemCycleStatusEventType ObjectType. /// public static readonly ExpandedNodeId SystemCycleStatusEventType = new ExpandedNodeId(SimpleEvents.ObjectTypes.SystemCycleStatusEventType, SimpleEvents.Namespaces.SimpleEvents); /// /// The identifier for the SystemCycleStartedEventType ObjectType. /// public static readonly ExpandedNodeId SystemCycleStartedEventType = new ExpandedNodeId(SimpleEvents.ObjectTypes.SystemCycleStartedEventType, SimpleEvents.Namespaces.SimpleEvents); /// /// The identifier for the SystemCycleAbortedEventType ObjectType. /// public static readonly ExpandedNodeId SystemCycleAbortedEventType = new ExpandedNodeId(SimpleEvents.ObjectTypes.SystemCycleAbortedEventType, SimpleEvents.Namespaces.SimpleEvents); /// /// The identifier for the SystemCycleFinishedEventType ObjectType. /// public static readonly ExpandedNodeId SystemCycleFinishedEventType = new ExpandedNodeId(SimpleEvents.ObjectTypes.SystemCycleFinishedEventType, SimpleEvents.Namespaces.SimpleEvents); } #endregion #region Variable Node Identifiers /// /// A class that declares constants for all Variables in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class VariableIds { /// /// The identifier for the SystemCycleStatusEventType_CycleId Variable. /// public static readonly ExpandedNodeId SystemCycleStatusEventType_CycleId = new ExpandedNodeId(SimpleEvents.Variables.SystemCycleStatusEventType_CycleId, SimpleEvents.Namespaces.SimpleEvents); /// /// The identifier for the SystemCycleStatusEventType_CurrentStep Variable. /// public static readonly ExpandedNodeId SystemCycleStatusEventType_CurrentStep = new ExpandedNodeId(SimpleEvents.Variables.SystemCycleStatusEventType_CurrentStep, SimpleEvents.Namespaces.SimpleEvents); /// /// The identifier for the SystemCycleStartedEventType_Steps Variable. /// public static readonly ExpandedNodeId SystemCycleStartedEventType_Steps = new ExpandedNodeId(SimpleEvents.Variables.SystemCycleStartedEventType_Steps, SimpleEvents.Namespaces.SimpleEvents); /// /// The identifier for the SystemCycleAbortedEventType_Error Variable. /// public static readonly ExpandedNodeId SystemCycleAbortedEventType_Error = new ExpandedNodeId(SimpleEvents.Variables.SystemCycleAbortedEventType_Error, SimpleEvents.Namespaces.SimpleEvents); /// /// The identifier for the SimpleEvents_BinarySchema Variable. /// public static readonly ExpandedNodeId SimpleEvents_BinarySchema = new ExpandedNodeId(SimpleEvents.Variables.SimpleEvents_BinarySchema, SimpleEvents.Namespaces.SimpleEvents); /// /// The identifier for the SimpleEvents_BinarySchema_NamespaceUri Variable. /// public static readonly ExpandedNodeId SimpleEvents_BinarySchema_NamespaceUri = new ExpandedNodeId(SimpleEvents.Variables.SimpleEvents_BinarySchema_NamespaceUri, SimpleEvents.Namespaces.SimpleEvents); /// /// The identifier for the SimpleEvents_BinarySchema_Deprecated Variable. /// public static readonly ExpandedNodeId SimpleEvents_BinarySchema_Deprecated = new ExpandedNodeId(SimpleEvents.Variables.SimpleEvents_BinarySchema_Deprecated, SimpleEvents.Namespaces.SimpleEvents); /// /// The identifier for the SimpleEvents_BinarySchema_CycleStepDataType Variable. /// public static readonly ExpandedNodeId SimpleEvents_BinarySchema_CycleStepDataType = new ExpandedNodeId(SimpleEvents.Variables.SimpleEvents_BinarySchema_CycleStepDataType, SimpleEvents.Namespaces.SimpleEvents); /// /// The identifier for the SimpleEvents_XmlSchema Variable. /// public static readonly ExpandedNodeId SimpleEvents_XmlSchema = new ExpandedNodeId(SimpleEvents.Variables.SimpleEvents_XmlSchema, SimpleEvents.Namespaces.SimpleEvents); /// /// The identifier for the SimpleEvents_XmlSchema_NamespaceUri Variable. /// public static readonly ExpandedNodeId SimpleEvents_XmlSchema_NamespaceUri = new ExpandedNodeId(SimpleEvents.Variables.SimpleEvents_XmlSchema_NamespaceUri, SimpleEvents.Namespaces.SimpleEvents); /// /// The identifier for the SimpleEvents_XmlSchema_Deprecated Variable. /// public static readonly ExpandedNodeId SimpleEvents_XmlSchema_Deprecated = new ExpandedNodeId(SimpleEvents.Variables.SimpleEvents_XmlSchema_Deprecated, SimpleEvents.Namespaces.SimpleEvents); /// /// The identifier for the SimpleEvents_XmlSchema_CycleStepDataType Variable. /// public static readonly ExpandedNodeId SimpleEvents_XmlSchema_CycleStepDataType = new ExpandedNodeId(SimpleEvents.Variables.SimpleEvents_XmlSchema_CycleStepDataType, SimpleEvents.Namespaces.SimpleEvents); } #endregion #region BrowseName Declarations /// /// Declares all of the BrowseNames used in the Model Design. /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class BrowseNames { /// /// The BrowseName for the CurrentStep component. /// public const string CurrentStep = "CurrentStep"; /// /// The BrowseName for the CycleId component. /// public const string CycleId = "CycleId"; /// /// The BrowseName for the CycleStepDataType component. /// public const string CycleStepDataType = "CycleStepDataType"; /// /// The BrowseName for the Error component. /// public const string Error = "Error"; /// /// The BrowseName for the SimpleEvents_BinarySchema component. /// public const string SimpleEvents_BinarySchema = "SimpleEvents"; /// /// The BrowseName for the SimpleEvents_XmlSchema component. /// public const string SimpleEvents_XmlSchema = "SimpleEvents"; /// /// The BrowseName for the Steps component. /// public const string Steps = "Steps"; /// /// The BrowseName for the SystemCycleAbortedEventType component. /// public const string SystemCycleAbortedEventType = "SystemCycleAbortedEventType"; /// /// The BrowseName for the SystemCycleFinishedEventType component. /// public const string SystemCycleFinishedEventType = "SystemCycleFinishedEventType"; /// /// The BrowseName for the SystemCycleStartedEventType component. /// public const string SystemCycleStartedEventType = "SystemCycleStartedEventType"; /// /// The BrowseName for the SystemCycleStatusEventType component. /// public const string SystemCycleStatusEventType = "SystemCycleStatusEventType"; } #endregion #region Namespace Declarations /// /// Defines constants for all namespaces referenced by the model design. /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Namespaces { /// /// The URI for the OpcUa namespace (.NET code namespace is 'Opc.Ua'). /// public const string OpcUa = "http://opcfoundation.org/UA/"; /// /// The URI for the OpcUaXsd namespace (.NET code namespace is 'Opc.Ua'). /// public const string OpcUaXsd = "http://opcfoundation.org/UA/2008/02/Types.xsd"; /// /// The URI for the SimpleEvents namespace (.NET code namespace is 'SimpleEvents'). /// public const string SimpleEvents = "http://opcfoundation.org/SimpleEvents"; } #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/SimpleEvents/Design/SimpleEvents.DataTypes.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; using System; using System.Collections.Generic; using System.Runtime.Serialization; namespace SimpleEvents { #region CycleStepDataType Class #if (!OPCUA_EXCLUDE_CycleStepDataType) /// /// /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = SimpleEvents.Namespaces.SimpleEvents)] public partial class CycleStepDataType : IEncodeable { #region Constructors /// /// The default constructor. /// public CycleStepDataType() { Initialize(); } /// /// Called by the .NET framework during deserialization. /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { m_name = null; m_duration = (double)0; } #endregion #region Public Properties /// [DataMember(Name = "Name", IsRequired = false, Order = 1)] public string Name { get { return m_name; } set { m_name = value; } } /// [DataMember(Name = "Duration", IsRequired = false, Order = 2)] public double Duration { get { return m_duration; } set { m_duration = value; } } #endregion #region IEncodeable Members /// public virtual ExpandedNodeId TypeId { get { return DataTypeIds.CycleStepDataType; } } /// public virtual ExpandedNodeId BinaryEncodingId { get { return ObjectIds.CycleStepDataType_Encoding_DefaultBinary; } } /// public virtual ExpandedNodeId XmlEncodingId { get { return ObjectIds.CycleStepDataType_Encoding_DefaultXml; } } /// public virtual void Encode(IEncoder encoder) { encoder.PushNamespace(SimpleEvents.Namespaces.SimpleEvents); encoder.WriteString("Name", Name); encoder.WriteDouble("Duration", Duration); encoder.PopNamespace(); } /// public virtual void Decode(IDecoder decoder) { decoder.PushNamespace(SimpleEvents.Namespaces.SimpleEvents); Name = decoder.ReadString("Name"); Duration = decoder.ReadDouble("Duration"); decoder.PopNamespace(); } /// public virtual bool IsEqual(IEncodeable encodeable) { if (Object.ReferenceEquals(this, encodeable)) { return true; } CycleStepDataType value = encodeable as CycleStepDataType; if (value == null) { return false; } if (!Utils.IsEqual(m_name, value.m_name)) return false; if (!Utils.IsEqual(m_duration, value.m_duration)) return false; return true; } #if !NET_STANDARD /// public virtual object Clone() { return (CycleStepDataType)this.MemberwiseClone(); } #endif /// public new object MemberwiseClone() { CycleStepDataType clone = (CycleStepDataType)base.MemberwiseClone(); clone.m_name = (string)Utils.Clone(this.m_name); clone.m_duration = (double)Utils.Clone(this.m_duration); return clone; } #endregion #region Private Fields private string m_name; private double m_duration; #endregion } #region CycleStepDataTypeCollection Class /// /// A collection of CycleStepDataType objects. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfCycleStepDataType", Namespace = SimpleEvents.Namespaces.SimpleEvents, ItemName = "CycleStepDataType")] #if !NET_STANDARD public partial class CycleStepDataTypeCollection : List, ICloneable #else public partial class CycleStepDataTypeCollection : List #endif { #region Constructors /// /// Initializes the collection with default values. /// public CycleStepDataTypeCollection() { } /// /// Initializes the collection with an initial capacity. /// public CycleStepDataTypeCollection(int capacity) : base(capacity) { } /// /// Initializes the collection with another collection. /// public CycleStepDataTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// /// Converts an array to a collection. /// public static implicit operator CycleStepDataTypeCollection(CycleStepDataType[] values) { if (values != null) { return new CycleStepDataTypeCollection(values); } return new CycleStepDataTypeCollection(); } /// /// Converts a collection to an array. /// public static explicit operator CycleStepDataType[](CycleStepDataTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #if !NET_STANDARD #region ICloneable Methods /// /// Creates a deep copy of the collection. /// public object Clone() { return (CycleStepDataTypeCollection)this.MemberwiseClone(); } #endregion #endif /// public new object MemberwiseClone() { CycleStepDataTypeCollection clone = new CycleStepDataTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((CycleStepDataType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/SimpleEvents/Design/SimpleEvents.NodeIds.csv ================================================ CycleStepDataType,183,DataType CycleStepDataType_Encoding_DefaultBinary,228,Object CycleStepDataType_Encoding_DefaultJson,15003,Object CycleStepDataType_Encoding_DefaultXml,221,Object SimpleEvents_BinarySchema,222,Variable SimpleEvents_XmlSchema,229,Variable SystemCycleAbortedEventType,197,ObjectType SystemCycleFinishedEventType,210,ObjectType SystemCycleStartedEventType,184,ObjectType SystemCycleStatusEventType,235,ObjectType ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/SimpleEvents/Design/SimpleEvents.NodeSet.xml ================================================  http://opcfoundation.org/UA/ http://opcfoundation.org/SimpleEvents ns=1;i=183 DataType_64 1 CycleStepDataType CycleStepDataType 0 0 0 i=45 true i=22 i=38 false ns=1;i=228 i=38 false ns=1;i=221 i=38 false ns=1;i=15003 false ns=1;i=184 ObjectType_8 1 SystemCycleStartedEventType SystemCycleStartedEventType An event raised when a system cycle starts. 0 0 0 i=45 true ns=1;i=235 i=46 false ns=1;i=196 false ns=1;i=196 Variable_2 1 Steps Steps 0 0 0 i=46 true ns=1;i=184 i=40 false i=68 i=37 false i=78 ns=1;i=183 1 0 1 1 0 false 0 ns=1;i=197 ObjectType_8 1 SystemCycleAbortedEventType SystemCycleAbortedEventType An event raised when a system cycle is aborted. 0 0 0 i=45 true ns=1;i=235 i=46 false ns=1;i=249 false ns=1;i=210 ObjectType_8 1 SystemCycleFinishedEventType SystemCycleFinishedEventType An event raised when a system cycle completes. 0 0 0 i=45 true ns=1;i=235 false ns=1;i=221 Object_1 0 Default XML Default XML 0 0 0 i=40 false i=76 i=38 true ns=1;i=183 i=39 false ns=1;i=232 0 ns=1;i=222 Variable_2 1 SimpleEvents SimpleEvents 0 0 0 i=40 false i=72 i=47 true i=93 i=46 false ns=1;i=224 i=46 false ns=1;i=15001 i=47 false ns=1;i=225 PG9wYzpUeXBlRGljdGlvbmFyeQ0KICB4bWxuczpvcGM9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9y Zy9CaW5hcnlTY2hlbWEvIg0KICB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1M U2NoZW1hLWluc3RhbmNlIg0KICB4bWxuczp1YT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VB LyINCiAgeG1sbnM6dG5zPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvU2ltcGxlRXZlbnRzIg0K ICBEZWZhdWx0Qnl0ZU9yZGVyPSJMaXR0bGVFbmRpYW4iDQogIFRhcmdldE5hbWVzcGFjZT0iaHR0 cDovL29wY2ZvdW5kYXRpb24ub3JnL1NpbXBsZUV2ZW50cyINCj4NCiAgPG9wYzpJbXBvcnQgTmFt ZXNwYWNlPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvIiBMb2NhdGlvbj0iT3BjLlVhLkJp bmFyeVNjaGVtYS5ic2QiLz4NCg0KICA8b3BjOlN0cnVjdHVyZWRUeXBlIE5hbWU9IkN5Y2xlU3Rl cERhdGFUeXBlIiBCYXNlVHlwZT0idWE6RXh0ZW5zaW9uT2JqZWN0Ij4NCiAgICA8b3BjOkZpZWxk IE5hbWU9Ik5hbWUiIFR5cGVOYW1lPSJvcGM6U3RyaW5nIiAvPg0KICAgIDxvcGM6RmllbGQgTmFt ZT0iRHVyYXRpb24iIFR5cGVOYW1lPSJvcGM6RG91YmxlIiAvPg0KICA8L29wYzpTdHJ1Y3R1cmVk VHlwZT4NCg0KPC9vcGM6VHlwZURpY3Rpb25hcnk+ i=15 -1 1 1 0 false 0 ns=1;i=224 Variable_2 0 NamespaceUri NamespaceUri 0 0 0 i=46 true ns=1;i=222 i=40 false i=68 http://opcfoundation.org/SimpleEvents i=12 -1 1 1 0 false 0 ns=1;i=225 Variable_2 1 CycleStepDataType CycleStepDataType 0 0 0 i=47 true ns=1;i=222 i=40 false i=69 CycleStepDataType i=12 -1 1 1 0 false 0 ns=1;i=228 Object_1 0 Default Binary Default Binary 0 0 0 i=40 false i=76 i=38 true ns=1;i=183 i=39 false ns=1;i=225 0 ns=1;i=229 Variable_2 1 SimpleEvents SimpleEvents 0 0 0 i=40 false i=72 i=47 true i=92 i=46 false ns=1;i=231 i=46 false ns=1;i=15002 i=47 false ns=1;i=232 PHhzOnNjaGVtYQ0KICB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEi DQogIHhtbG5zOnVhPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvMjAwOC8wMi9UeXBlcy54 c2QiDQogIHhtbG5zOnRucz0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1NpbXBsZUV2ZW50cyIN CiAgdGFyZ2V0TmFtZXNwYWNlPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvU2ltcGxlRXZlbnRz Ig0KICBlbGVtZW50Rm9ybURlZmF1bHQ9InF1YWxpZmllZCINCj4NCiAgPHhzOmltcG9ydCBuYW1l c3BhY2U9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9yZy9VQS8yMDA4LzAyL1R5cGVzLnhzZCIgLz4N Cg0KICA8eHM6Y29tcGxleFR5cGUgbmFtZT0iQ3ljbGVTdGVwRGF0YVR5cGUiPg0KICAgIDx4czpz ZXF1ZW5jZT4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9Ik5hbWUiIHR5cGU9InhzOnN0cmluZyIg bWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9 IkR1cmF0aW9uIiB0eXBlPSJ4czpkb3VibGUiIG1pbk9jY3Vycz0iMCIgLz4NCiAgICA8L3hzOnNl cXVlbmNlPg0KICA8L3hzOmNvbXBsZXhUeXBlPg0KICA8eHM6ZWxlbWVudCBuYW1lPSJDeWNsZVN0 ZXBEYXRhVHlwZSIgdHlwZT0idG5zOkN5Y2xlU3RlcERhdGFUeXBlIiAvPg0KDQogIDx4czpjb21w bGV4VHlwZSBuYW1lPSJMaXN0T2ZDeWNsZVN0ZXBEYXRhVHlwZSI+DQogICAgPHhzOnNlcXVlbmNl Pg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iQ3ljbGVTdGVwRGF0YVR5cGUiIHR5cGU9InRuczpD eWNsZVN0ZXBEYXRhVHlwZSIgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9InVuYm91bmRlZCIgbmls bGFibGU9InRydWUiIC8+DQogICAgPC94czpzZXF1ZW5jZT4NCiAgPC94czpjb21wbGV4VHlwZT4N CiAgPHhzOmVsZW1lbnQgbmFtZT0iTGlzdE9mQ3ljbGVTdGVwRGF0YVR5cGUiIHR5cGU9InRuczpM aXN0T2ZDeWNsZVN0ZXBEYXRhVHlwZSIgbmlsbGFibGU9InRydWUiPjwveHM6ZWxlbWVudD4NCg0K PC94czpzY2hlbWE+ i=15 -1 1 1 0 false 0 ns=1;i=231 Variable_2 0 NamespaceUri NamespaceUri 0 0 0 i=46 true ns=1;i=229 i=40 false i=68 http://opcfoundation.org/SimpleEvents i=12 -1 1 1 0 false 0 ns=1;i=232 Variable_2 1 CycleStepDataType CycleStepDataType 0 0 0 i=47 true ns=1;i=229 i=40 false i=69 //xs:element[@name='CycleStepDataType'] i=12 -1 1 1 0 false 0 ns=1;i=235 ObjectType_8 1 SystemCycleStatusEventType SystemCycleStatusEventType An event raised when a system cycle starts. 0 0 0 i=45 true i=2130 i=46 false ns=1;i=245 i=46 false ns=1;i=246 i=45 false ns=1;i=184 i=45 false ns=1;i=197 i=45 false ns=1;i=210 false ns=1;i=245 Variable_2 1 CycleId CycleId 0 0 0 i=46 true ns=1;i=235 i=40 false i=68 i=37 false i=78 i=12 -1 1 1 0 false 0 ns=1;i=246 Variable_2 1 CurrentStep CurrentStep 0 0 0 i=46 true ns=1;i=235 i=40 false i=68 i=37 false i=78 ns=1;i=183 -1 1 1 0 false 0 ns=1;i=249 Variable_2 1 Error Error 0 0 0 i=46 true ns=1;i=197 i=40 false i=68 i=37 false i=78 0 i=19 -1 1 1 0 false 0 ns=1;i=15001 Variable_2 0 Deprecated Deprecated 0 0 0 i=46 true ns=1;i=222 i=40 false i=68 true i=1 -1 1 1 0 false 0 ns=1;i=15002 Variable_2 0 Deprecated Deprecated 0 0 0 i=46 true ns=1;i=229 i=40 false i=68 true i=1 -1 1 1 0 false 0 ns=1;i=15003 Object_1 0 Default JSON Default JSON 0 0 0 i=40 false i=76 i=38 true ns=1;i=183 0 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/SimpleEvents/Design/SimpleEvents.NodeSet2.xml ================================================  http://opcfoundation.org/SimpleEvents i=1 i=2 i=3 i=4 i=5 i=6 i=7 i=8 i=9 i=10 i=11 i=13 i=12 i=15 i=14 i=16 i=17 i=18 i=20 i=21 i=19 i=22 i=26 i=27 i=28 i=47 i=46 i=35 i=36 i=48 i=45 i=40 i=37 i=38 i=39 CycleStepDataType i=22 SystemCycleStatusEventType An event raised when a system cycle starts. ns=1;i=245 ns=1;i=246 i=2130 CycleId i=68 i=78 ns=1;i=235 CurrentStep i=68 i=78 ns=1;i=235 SystemCycleStartedEventType An event raised when a system cycle starts. ns=1;i=196 ns=1;i=235 Steps i=68 i=78 ns=1;i=184 SystemCycleAbortedEventType An event raised when a system cycle is aborted. ns=1;i=249 ns=1;i=235 Error i=68 i=78 ns=1;i=197 SystemCycleFinishedEventType An event raised when a system cycle completes. ns=1;i=235 Default Binary ns=1;i=183 ns=1;i=225 i=76 SimpleEvents ns=1;i=224 ns=1;i=15001 ns=1;i=225 i=93 i=72 PG9wYzpUeXBlRGljdGlvbmFyeQ0KICB4bWxuczpvcGM9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9y Zy9CaW5hcnlTY2hlbWEvIg0KICB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1M U2NoZW1hLWluc3RhbmNlIg0KICB4bWxuczp1YT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VB LyINCiAgeG1sbnM6dG5zPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvU2ltcGxlRXZlbnRzIg0K ICBEZWZhdWx0Qnl0ZU9yZGVyPSJMaXR0bGVFbmRpYW4iDQogIFRhcmdldE5hbWVzcGFjZT0iaHR0 cDovL29wY2ZvdW5kYXRpb24ub3JnL1NpbXBsZUV2ZW50cyINCj4NCiAgPG9wYzpJbXBvcnQgTmFt ZXNwYWNlPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvIiBMb2NhdGlvbj0iT3BjLlVhLkJp bmFyeVNjaGVtYS5ic2QiLz4NCg0KICA8b3BjOlN0cnVjdHVyZWRUeXBlIE5hbWU9IkN5Y2xlU3Rl cERhdGFUeXBlIiBCYXNlVHlwZT0idWE6RXh0ZW5zaW9uT2JqZWN0Ij4NCiAgICA8b3BjOkZpZWxk IE5hbWU9Ik5hbWUiIFR5cGVOYW1lPSJvcGM6U3RyaW5nIiAvPg0KICAgIDxvcGM6RmllbGQgTmFt ZT0iRHVyYXRpb24iIFR5cGVOYW1lPSJvcGM6RG91YmxlIiAvPg0KICA8L29wYzpTdHJ1Y3R1cmVk VHlwZT4NCg0KPC9vcGM6VHlwZURpY3Rpb25hcnk+ NamespaceUri i=68 ns=1;i=222 http://opcfoundation.org/SimpleEvents Deprecated i=68 ns=1;i=222 true CycleStepDataType i=69 ns=1;i=222 CycleStepDataType Default XML ns=1;i=183 ns=1;i=232 i=76 SimpleEvents ns=1;i=231 ns=1;i=15002 ns=1;i=232 i=92 i=72 PHhzOnNjaGVtYQ0KICB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEi DQogIHhtbG5zOnVhPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvMjAwOC8wMi9UeXBlcy54 c2QiDQogIHhtbG5zOnRucz0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1NpbXBsZUV2ZW50cyIN CiAgdGFyZ2V0TmFtZXNwYWNlPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvU2ltcGxlRXZlbnRz Ig0KICBlbGVtZW50Rm9ybURlZmF1bHQ9InF1YWxpZmllZCINCj4NCiAgPHhzOmltcG9ydCBuYW1l c3BhY2U9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9yZy9VQS8yMDA4LzAyL1R5cGVzLnhzZCIgLz4N Cg0KICA8eHM6Y29tcGxleFR5cGUgbmFtZT0iQ3ljbGVTdGVwRGF0YVR5cGUiPg0KICAgIDx4czpz ZXF1ZW5jZT4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9Ik5hbWUiIHR5cGU9InhzOnN0cmluZyIg bWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9 IkR1cmF0aW9uIiB0eXBlPSJ4czpkb3VibGUiIG1pbk9jY3Vycz0iMCIgLz4NCiAgICA8L3hzOnNl cXVlbmNlPg0KICA8L3hzOmNvbXBsZXhUeXBlPg0KICA8eHM6ZWxlbWVudCBuYW1lPSJDeWNsZVN0 ZXBEYXRhVHlwZSIgdHlwZT0idG5zOkN5Y2xlU3RlcERhdGFUeXBlIiAvPg0KDQogIDx4czpjb21w bGV4VHlwZSBuYW1lPSJMaXN0T2ZDeWNsZVN0ZXBEYXRhVHlwZSI+DQogICAgPHhzOnNlcXVlbmNl Pg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iQ3ljbGVTdGVwRGF0YVR5cGUiIHR5cGU9InRuczpD eWNsZVN0ZXBEYXRhVHlwZSIgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9InVuYm91bmRlZCIgbmls bGFibGU9InRydWUiIC8+DQogICAgPC94czpzZXF1ZW5jZT4NCiAgPC94czpjb21wbGV4VHlwZT4N CiAgPHhzOmVsZW1lbnQgbmFtZT0iTGlzdE9mQ3ljbGVTdGVwRGF0YVR5cGUiIHR5cGU9InRuczpM aXN0T2ZDeWNsZVN0ZXBEYXRhVHlwZSIgbmlsbGFibGU9InRydWUiPjwveHM6ZWxlbWVudD4NCg0K PC94czpzY2hlbWE+ NamespaceUri i=68 ns=1;i=229 http://opcfoundation.org/SimpleEvents Deprecated i=68 ns=1;i=229 true CycleStepDataType i=69 ns=1;i=229 //xs:element[@name='CycleStepDataType'] Default JSON ns=1;i=183 i=76 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/SimpleEvents/Design/SimpleEvents.PredefinedNodes.xml ================================================  http://opcfoundation.org/SimpleEvents DataType_64 ns=1;i=183 1 CycleStepDataType i=22 i=14798 i=22 Structure_0 Name i=12 -1 0 false Duration i=11 -1 0 false ObjectType_8 ns=1;i=235 1 SystemCycleStatusEventType An event raised when a system cycle starts. i=2130 Variable_2 ns=1;i=245 1 CycleId i=46 i=68 i=78 245 i=12 -1 1 1 Variable_2 ns=1;i=246 1 CurrentStep i=46 i=68 i=78 246 ns=1;i=183 -1 1 1 ObjectType_8 ns=1;i=184 1 SystemCycleStartedEventType An event raised when a system cycle starts. ns=1;i=235 Variable_2 ns=1;i=196 1 Steps i=46 i=68 i=78 196 ns=1;i=183 1 0 1 1 ObjectType_8 ns=1;i=197 1 SystemCycleAbortedEventType An event raised when a system cycle is aborted. ns=1;i=235 Variable_2 ns=1;i=249 1 Error i=46 i=68 i=78 249 i=19 -1 1 1 ObjectType_8 ns=1;i=210 1 SystemCycleFinishedEventType An event raised when a system cycle completes. ns=1;i=235 Object_1 ns=1;i=228 0 Default Binary i=76 228 i=38 true ns=1;i=183 i=39 ns=1;i=225 Variable_2 ns=1;i=222 1 SimpleEvents i=72 222 PG9wYzpUeXBlRGljdGlvbmFyeQ0KICB4bWxuczpvcGM9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9y Zy9CaW5hcnlTY2hlbWEvIg0KICB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1M U2NoZW1hLWluc3RhbmNlIg0KICB4bWxuczp1YT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VB LyINCiAgeG1sbnM6dG5zPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvU2ltcGxlRXZlbnRzIg0K ICBEZWZhdWx0Qnl0ZU9yZGVyPSJMaXR0bGVFbmRpYW4iDQogIFRhcmdldE5hbWVzcGFjZT0iaHR0 cDovL29wY2ZvdW5kYXRpb24ub3JnL1NpbXBsZUV2ZW50cyINCj4NCiAgPG9wYzpJbXBvcnQgTmFt ZXNwYWNlPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvIiBMb2NhdGlvbj0iT3BjLlVhLkJp bmFyeVNjaGVtYS5ic2QiLz4NCg0KICA8b3BjOlN0cnVjdHVyZWRUeXBlIE5hbWU9IkN5Y2xlU3Rl cERhdGFUeXBlIiBCYXNlVHlwZT0idWE6RXh0ZW5zaW9uT2JqZWN0Ij4NCiAgICA8b3BjOkZpZWxk IE5hbWU9Ik5hbWUiIFR5cGVOYW1lPSJvcGM6U3RyaW5nIiAvPg0KICAgIDxvcGM6RmllbGQgTmFt ZT0iRHVyYXRpb24iIFR5cGVOYW1lPSJvcGM6RG91YmxlIiAvPg0KICA8L29wYzpTdHJ1Y3R1cmVk VHlwZT4NCg0KPC9vcGM6VHlwZURpY3Rpb25hcnk+ i=15 -1 1 1 i=47 true i=93 Variable_2 ns=1;i=224 0 NamespaceUri i=46 i=68 224 http://opcfoundation.org/SimpleEvents i=12 -1 1 1 Variable_2 ns=1;i=15001 0 Deprecated i=46 i=68 15001 true i=1 -1 1 1 Variable_2 ns=1;i=225 1 CycleStepDataType i=47 i=69 225 CycleStepDataType i=12 -1 1 1 Object_1 ns=1;i=221 0 Default XML i=76 221 i=38 true ns=1;i=183 i=39 ns=1;i=232 Variable_2 ns=1;i=229 1 SimpleEvents i=72 229 PHhzOnNjaGVtYQ0KICB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEi DQogIHhtbG5zOnVhPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvMjAwOC8wMi9UeXBlcy54 c2QiDQogIHhtbG5zOnRucz0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1NpbXBsZUV2ZW50cyIN CiAgdGFyZ2V0TmFtZXNwYWNlPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvU2ltcGxlRXZlbnRz Ig0KICBlbGVtZW50Rm9ybURlZmF1bHQ9InF1YWxpZmllZCINCj4NCiAgPHhzOmltcG9ydCBuYW1l c3BhY2U9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9yZy9VQS8yMDA4LzAyL1R5cGVzLnhzZCIgLz4N Cg0KICA8eHM6Y29tcGxleFR5cGUgbmFtZT0iQ3ljbGVTdGVwRGF0YVR5cGUiPg0KICAgIDx4czpz ZXF1ZW5jZT4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9Ik5hbWUiIHR5cGU9InhzOnN0cmluZyIg bWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9 IkR1cmF0aW9uIiB0eXBlPSJ4czpkb3VibGUiIG1pbk9jY3Vycz0iMCIgLz4NCiAgICA8L3hzOnNl cXVlbmNlPg0KICA8L3hzOmNvbXBsZXhUeXBlPg0KICA8eHM6ZWxlbWVudCBuYW1lPSJDeWNsZVN0 ZXBEYXRhVHlwZSIgdHlwZT0idG5zOkN5Y2xlU3RlcERhdGFUeXBlIiAvPg0KDQogIDx4czpjb21w bGV4VHlwZSBuYW1lPSJMaXN0T2ZDeWNsZVN0ZXBEYXRhVHlwZSI+DQogICAgPHhzOnNlcXVlbmNl Pg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iQ3ljbGVTdGVwRGF0YVR5cGUiIHR5cGU9InRuczpD eWNsZVN0ZXBEYXRhVHlwZSIgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9InVuYm91bmRlZCIgbmls bGFibGU9InRydWUiIC8+DQogICAgPC94czpzZXF1ZW5jZT4NCiAgPC94czpjb21wbGV4VHlwZT4N CiAgPHhzOmVsZW1lbnQgbmFtZT0iTGlzdE9mQ3ljbGVTdGVwRGF0YVR5cGUiIHR5cGU9InRuczpM aXN0T2ZDeWNsZVN0ZXBEYXRhVHlwZSIgbmlsbGFibGU9InRydWUiPjwveHM6ZWxlbWVudD4NCg0K PC94czpzY2hlbWE+ i=15 -1 1 1 i=47 true i=92 Variable_2 ns=1;i=231 0 NamespaceUri i=46 i=68 231 http://opcfoundation.org/SimpleEvents i=12 -1 1 1 Variable_2 ns=1;i=15002 0 Deprecated i=46 i=68 15002 true i=1 -1 1 1 Variable_2 ns=1;i=232 1 CycleStepDataType i=47 i=69 232 //xs:element[@name='CycleStepDataType'] i=12 -1 1 1 Object_1 ns=1;i=15003 0 Default JSON i=76 15003 i=38 true ns=1;i=183 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/SimpleEvents/Design/SimpleEvents.Types.bsd ================================================ ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/SimpleEvents/Design/SimpleEvents.Types.xsd ================================================ ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/TestData/Design/TestData.Classes.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2021 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; using System; using System.Collections.Generic; using System.Xml; namespace TestData { #region GenerateValuesMethodState Class #if (!OPCUA_EXCLUDE_GenerateValuesMethodState) /// /// Stores an instance of the GenerateValuesMethodType Method. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class GenerateValuesMethodState : MethodState { #region Constructors /// /// Initializes the type with its default attribute values. /// public GenerateValuesMethodState(NodeState parent) : base(parent) { } /// /// Constructs an instance of a node. /// /// The parent. /// The new node. public new static NodeState Construct(NodeState parent) { return new GenerateValuesMethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAABgAAABodHRwOi8vdGVzdC5vcmcvVUEvRGF0YS//////BGGCCgQAAAABABgAAABHZW5lcmF0ZVZh" + "bHVlc01ldGhvZFR5cGUBAZkkAC8BAZkkmSQAAAEB/////wEAAAAXYKkKAgAAAAAADgAAAElucHV0QXJn" + "dW1lbnRzAQGaJAAuAESaJAAAlgEAAAABACoBAUYAAAAKAAAASXRlcmF0aW9ucwAH/////wAAAAADAAAA" + "ACUAAABUaGUgbnVtYmVyIG9mIG5ldyB2YWx1ZXMgdG8gZ2VuZXJhdGUuAQAoAQEAAAABAAAAAAAAAAEB" + "/////wAAAAA="; #endregion #endif #endregion #region Event Callbacks /// /// Raised when the the method is called. /// public GenerateValuesMethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// /// Invokes the method, returns the result and output argument. /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult result = null; uint iterations = (uint)_inputArguments[0]; if (OnCall != null) { result = OnCall( _context, this, _objectId, iterations); } return result; } #endregion #region Private Fields #endregion } /// /// Used to receive notifications when the method is called. /// /// /// /// /// /// public delegate ServiceResult GenerateValuesMethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, uint iterations); #endif #endregion #region GenerateValuesEventState Class #if (!OPCUA_EXCLUDE_GenerateValuesEventState) /// /// Stores an instance of the GenerateValuesEventType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class GenerateValuesEventState : BaseEventState { #region Constructors /// /// Initializes the type with its default attribute values. /// public GenerateValuesEventState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(TestData.ObjectTypes.GenerateValuesEventType, TestData.Namespaces.TestData, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAABgAAABodHRwOi8vdGVzdC5vcmcvVUEvRGF0YS//////BGCAAgEAAAABAB8AAABHZW5lcmF0ZVZh" + "bHVlc0V2ZW50VHlwZUluc3RhbmNlAQGbJAEBmySbJAAA/////woAAAAVYIkKAgAAAAAABwAAAEV2ZW50" + "SWQBAZwkAC4ARJwkAAAAD/////8BAf////8AAAAAFWCJCgIAAAAAAAkAAABFdmVudFR5cGUBAZ0kAC4A" + "RJ0kAAAAEf////8BAf////8AAAAAFWCJCgIAAAAAAAoAAABTb3VyY2VOb2RlAQGeJAAuAESeJAAAABH/" + "////AQH/////AAAAABVgiQoCAAAAAAAKAAAAU291cmNlTmFtZQEBnyQALgBEnyQAAAAM/////wEB////" + "/wAAAAAVYIkKAgAAAAAABAAAAFRpbWUBAaAkAC4ARKAkAAABACYB/////wEB/////wAAAAAVYIkKAgAA" + "AAAACwAAAFJlY2VpdmVUaW1lAQGhJAAuAEShJAAAAQAmAf////8BAf////8AAAAAFWCJCgIAAAAAAAcA" + "AABNZXNzYWdlAQGjJAAuAESjJAAAABX/////AQH/////AAAAABVgiQoCAAAAAAAIAAAAU2V2ZXJpdHkB" + "AaQkAC4ARKQkAAAABf////8BAf////8AAAAAFWCJCgIAAAABAAoAAABJdGVyYXRpb25zAQGlJAAuAESl" + "JAAAAAf/////AQH/////AAAAABVgiQoCAAAAAQANAAAATmV3VmFsdWVDb3VudAEBpiQALgBEpiQAAAAH" + "/////wEB/////wAAAAA="; #endregion #endif #endregion #region Public Properties /// public PropertyState Iterations { get { return m_iterations; } set { if (!Object.ReferenceEquals(m_iterations, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_iterations = value; } } /// public PropertyState NewValueCount { get { return m_newValueCount; } set { if (!Object.ReferenceEquals(m_newValueCount, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_newValueCount = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_iterations != null) { children.Add(m_iterations); } if (m_newValueCount != null) { children.Add(m_newValueCount); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case TestData.BrowseNames.Iterations: { if (createOrReplace) { if (Iterations == null) { if (replacement == null) { Iterations = new PropertyState(this); } else { Iterations = (PropertyState)replacement; } } } instance = Iterations; break; } case TestData.BrowseNames.NewValueCount: { if (createOrReplace) { if (NewValueCount == null) { if (replacement == null) { NewValueCount = new PropertyState(this); } else { NewValueCount = (PropertyState)replacement; } } } instance = NewValueCount; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private PropertyState m_iterations; private PropertyState m_newValueCount; #endregion } #endif #endregion #region TestDataObjectState Class #if (!OPCUA_EXCLUDE_TestDataObjectState) /// /// Stores an instance of the TestDataObjectType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCode("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class TestDataObjectState : BaseObjectState { #region Constructors /// /// Initializes the type with its default attribute values. /// /// public TestDataObjectState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return NodeId.Create(ObjectTypes.TestDataObjectType, Namespaces.TestData, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// /// /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAABgAAABodHRwOi8vdGVzdC5vcmcvVUEvRGF0YS//////BGCAAgEAAAABABoAAABUZXN0RGF0YU9i" + "amVjdFR5cGVJbnN0YW5jZQEBpyQBAackpyQAAAEAAAAAJAABAaskAwAAADVgiQoCAAAAAQAQAAAAU2lt" + "dWxhdGlvbkFjdGl2ZQEBqCQDAAAAAEcAAABJZiB0cnVlIHRoZSBzZXJ2ZXIgd2lsbCBwcm9kdWNlIG5l" + "dyB2YWx1ZXMgZm9yIGVhY2ggbW9uaXRvcmVkIHZhcmlhYmxlLgAuAESoJAAAAAH/////AQH/////AAAA" + "AARhggoEAAAAAQAOAAAAR2VuZXJhdGVWYWx1ZXMBAakkAC8BAakkqSQAAAEB/////wEAAAAXYKkKAgAA" + "AAAADgAAAElucHV0QXJndW1lbnRzAQGqJAAuAESqJAAAlgEAAAABACoBAUYAAAAKAAAASXRlcmF0aW9u" + "cwAH/////wAAAAADAAAAACUAAABUaGUgbnVtYmVyIG9mIG5ldyB2YWx1ZXMgdG8gZ2VuZXJhdGUuAQAo" + "AQEAAAABAAAAAAAAAAEB/////wAAAAAEYIAKAQAAAAEADQAAAEN5Y2xlQ29tcGxldGUBAaskAC8BAEEL" + "qyQAAAEAAAAAJAEBAackFwAAABVgiQoCAAAAAAAHAAAARXZlbnRJZAEBrCQALgBErCQAAAAP/////wEB" + "/////wAAAAAVYIkKAgAAAAAACQAAAEV2ZW50VHlwZQEBrSQALgBErSQAAAAR/////wEB/////wAAAAAV" + "YIkKAgAAAAAACgAAAFNvdXJjZU5vZGUBAa4kAC4ARK4kAAAAEf////8BAf////8AAAAAFWCJCgIAAAAA" + "AAoAAABTb3VyY2VOYW1lAQGvJAAuAESvJAAAAAz/////AQH/////AAAAABVgiQoCAAAAAAAEAAAAVGlt" + "ZQEBsCQALgBEsCQAAAEAJgH/////AQH/////AAAAABVgiQoCAAAAAAALAAAAUmVjZWl2ZVRpbWUBAbEk" + "AC4ARLEkAAABACYB/////wEB/////wAAAAAVYIkKAgAAAAAABwAAAE1lc3NhZ2UBAbMkAC4ARLMkAAAA" + "Ff////8BAf////8AAAAAFWCJCgIAAAAAAAgAAABTZXZlcml0eQEBtCQALgBEtCQAAAAF/////wEB////" + "/wAAAAAVYIkKAgAAAAAAEAAAAENvbmRpdGlvbkNsYXNzSWQBATotAC4ARDotAAAAEf////8BAf////8A" + "AAAAFWCJCgIAAAAAABIAAABDb25kaXRpb25DbGFzc05hbWUBATstAC4ARDstAAAAFf////8BAf////8A" + "AAAAFWCJCgIAAAAAAA0AAABDb25kaXRpb25OYW1lAQElLQAuAEQlLQAAAAz/////AQH/////AAAAABVg" + "iQoCAAAAAAAIAAAAQnJhbmNoSWQBAbUkAC4ARLUkAAAAEf////8BAf////8AAAAAFWCJCgIAAAAAAAYA" + "AABSZXRhaW4BAbYkAC4ARLYkAAAAAf////8BAf////8AAAAAFWCJCgIAAAAAAAwAAABFbmFibGVkU3Rh" + "dGUBAbckAC8BACMjtyQAAAAV/////wEBAgAAAAEALCMAAQHMJAEALCMAAQHUJAEAAAAVYIkKAgAAAAAA" + "AgAAAElkAQG4JAAuAES4JAAAAAH/////AQH/////AAAAABVgiQoCAAAAAAAHAAAAUXVhbGl0eQEBvSQA" + "LwEAKiO9JAAAABP/////AQH/////AQAAABVgiQoCAAAAAAAPAAAAU291cmNlVGltZXN0YW1wAQG+JAAu" + "AES+JAAAAQAmAf////8BAf////8AAAAAFWCJCgIAAAAAAAwAAABMYXN0U2V2ZXJpdHkBAcEkAC8BACoj" + "wSQAAAAF/////wEB/////wEAAAAVYIkKAgAAAAAADwAAAFNvdXJjZVRpbWVzdGFtcAEBwiQALgBEwiQA" + "AAEAJgH/////AQH/////AAAAABVgiQoCAAAAAAAHAAAAQ29tbWVudAEBwyQALwEAKiPDJAAAABX/////" + "AQH/////AQAAABVgiQoCAAAAAAAPAAAAU291cmNlVGltZXN0YW1wAQHEJAAuAETEJAAAAQAmAf////8B" + "Af////8AAAAAFWCJCgIAAAAAAAwAAABDbGllbnRVc2VySWQBAcUkAC4ARMUkAAAADP////8BAf////8A" + "AAAABGGCCgQAAAAAAAcAAABEaXNhYmxlAQHHJAAvAQBEI8ckAAABAQEAAAABAPkLAAEA8woAAAAABGGC" + "CgQAAAAAAAYAAABFbmFibGUBAcYkAC8BAEMjxiQAAAEBAQAAAAEA+QsAAQDzCgAAAAAEYYIKBAAAAAAA" + "CgAAAEFkZENvbW1lbnQBAcgkAC8BAEUjyCQAAAEBAQAAAAEA+QsAAQANCwEAAAAXYKkKAgAAAAAADgAA" + "AElucHV0QXJndW1lbnRzAQHJJAAuAETJJAAAlgIAAAABACoBAUYAAAAHAAAARXZlbnRJZAAP/////wAA" + "AAADAAAAACgAAABUaGUgaWRlbnRpZmllciBmb3IgdGhlIGV2ZW50IHRvIGNvbW1lbnQuAQAqAQFCAAAA" + "BwAAAENvbW1lbnQAFf////8AAAAAAwAAAAAkAAAAVGhlIGNvbW1lbnQgdG8gYWRkIHRvIHRoZSBjb25k" + "aXRpb24uAQAoAQEAAAABAAAAAAAAAAEB/////wAAAAAVYIkKAgAAAAAACgAAAEFja2VkU3RhdGUBAcwk" + "AC8BACMjzCQAAAAV/////wEBAQAAAAEALCMBAQG3JAEAAAAVYIkKAgAAAAAAAgAAAElkAQHNJAAuAETN" + "JAAAAAH/////AQH/////AAAAAARhggoEAAAAAAALAAAAQWNrbm93bGVkZ2UBAdwkAC8BAJcj3CQAAAEB" + "AQAAAAEA+QsAAQDwIgEAAAAXYKkKAgAAAAAADgAAAElucHV0QXJndW1lbnRzAQHdJAAuAETdJAAAlgIA" + "AAABACoBAUYAAAAHAAAARXZlbnRJZAAP/////wAAAAADAAAAACgAAABUaGUgaWRlbnRpZmllciBmb3Ig" + "dGhlIGV2ZW50IHRvIGNvbW1lbnQuAQAqAQFCAAAABwAAAENvbW1lbnQAFf////8AAAAAAwAAAAAkAAAA" + "VGhlIGNvbW1lbnQgdG8gYWRkIHRvIHRoZSBjb25kaXRpb24uAQAoAQEAAAABAAAAAAAAAAEB/////wAA" + "AAA="; #endregion #endif #endregion #region Public Properties /// public PropertyState SimulationActive { get => m_simulationActive; set { if (!ReferenceEquals(m_simulationActive, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_simulationActive = value; } } /// public GenerateValuesMethodState GenerateValues { get => m_generateValuesMethod; set { if (!ReferenceEquals(m_generateValuesMethod, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_generateValuesMethod = value; } } /// public AcknowledgeableConditionState CycleComplete { get => m_cycleComplete; set { if (!ReferenceEquals(m_cycleComplete, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_cycleComplete = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_simulationActive != null) { children.Add(m_simulationActive); } if (m_generateValuesMethod != null) { children.Add(m_generateValuesMethod); } if (m_cycleComplete != null) { children.Add(m_cycleComplete); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// /// /// /// /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case BrowseNames.SimulationActive: { if (createOrReplace && SimulationActive == null) { if (replacement == null) { SimulationActive = new PropertyState(this); } else { SimulationActive = (PropertyState)replacement; } } instance = SimulationActive; break; } case BrowseNames.GenerateValues: { if (createOrReplace && GenerateValues == null) { if (replacement == null) { GenerateValues = new GenerateValuesMethodState(this); } else { GenerateValues = (GenerateValuesMethodState)replacement; } } instance = GenerateValues; break; } case BrowseNames.CycleComplete: { if (createOrReplace && CycleComplete == null) { if (replacement == null) { CycleComplete = new AcknowledgeableConditionState(this); } else { CycleComplete = (AcknowledgeableConditionState)replacement; } } instance = CycleComplete; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private PropertyState m_simulationActive; private GenerateValuesMethodState m_generateValuesMethod; private AcknowledgeableConditionState m_cycleComplete; #endregion } #endif #endregion #region ScalarValue1MethodState Class #if (!OPCUA_EXCLUDE_ScalarValue1MethodState) /// /// Stores an instance of the ScalarValue1MethodType Method. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class ScalarValue1MethodState : MethodState { #region Constructors /// /// Initializes the type with its default attribute values. /// public ScalarValue1MethodState(NodeState parent) : base(parent) { } /// /// Constructs an instance of a node. /// /// The parent. /// The new node. public new static NodeState Construct(NodeState parent) { return new ScalarValue1MethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAABgAAABodHRwOi8vdGVzdC5vcmcvVUEvRGF0YS//////BGGCCgQAAAABABYAAABTY2FsYXJWYWx1" + "ZTFNZXRob2RUeXBlAQHhJAAvAQHhJOEkAAABAf////8CAAAAF2CpCgIAAAAAAA4AAABJbnB1dEFyZ3Vt" + "ZW50cwEB4iQALgBE4iQAAJYLAAAAAQAqAQEYAAAACQAAAEJvb2xlYW5JbgAB/////wAAAAAAAQAqAQEW" + "AAAABwAAAFNCeXRlSW4AAv////8AAAAAAAEAKgEBFQAAAAYAAABCeXRlSW4AA/////8AAAAAAAEAKgEB" + "FgAAAAcAAABJbnQxNkluAAT/////AAAAAAABACoBARcAAAAIAAAAVUludDE2SW4ABf////8AAAAAAAEA" + "KgEBFgAAAAcAAABJbnQzMkluAAb/////AAAAAAABACoBARcAAAAIAAAAVUludDMySW4AB/////8AAAAA" + "AAEAKgEBFgAAAAcAAABJbnQ2NEluAAj/////AAAAAAABACoBARcAAAAIAAAAVUludDY0SW4ACf////8A" + "AAAAAAEAKgEBFgAAAAcAAABGbG9hdEluAAr/////AAAAAAABACoBARcAAAAIAAAARG91YmxlSW4AC///" + "//8AAAAAAAEAKAEBAAAAAQAAAAAAAAABAf////8AAAAAF2CpCgIAAAAAAA8AAABPdXRwdXRBcmd1bWVu" + "dHMBAeMkAC4AROMkAACWCwAAAAEAKgEBGQAAAAoAAABCb29sZWFuT3V0AAH/////AAAAAAABACoBARcA" + "AAAIAAAAU0J5dGVPdXQAAv////8AAAAAAAEAKgEBFgAAAAcAAABCeXRlT3V0AAP/////AAAAAAABACoB" + "ARcAAAAIAAAASW50MTZPdXQABP////8AAAAAAAEAKgEBGAAAAAkAAABVSW50MTZPdXQABf////8AAAAA" + "AAEAKgEBFwAAAAgAAABJbnQzMk91dAAG/////wAAAAAAAQAqAQEYAAAACQAAAFVJbnQzMk91dAAH////" + "/wAAAAAAAQAqAQEXAAAACAAAAEludDY0T3V0AAj/////AAAAAAABACoBARgAAAAJAAAAVUludDY0T3V0" + "AAn/////AAAAAAABACoBARcAAAAIAAAARmxvYXRPdXQACv////8AAAAAAAEAKgEBGAAAAAkAAABEb3Vi" + "bGVPdXQAC/////8AAAAAAAEAKAEBAAAAAQAAAAAAAAABAf////8AAAAA"; #endregion #endif #endregion #region Event Callbacks /// /// Raised when the the method is called. /// public ScalarValue1MethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// /// Invokes the method, returns the result and output argument. /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult result = null; bool booleanIn = (bool)_inputArguments[0]; sbyte sByteIn = (sbyte)_inputArguments[1]; byte byteIn = (byte)_inputArguments[2]; short int16In = (short)_inputArguments[3]; ushort uInt16In = (ushort)_inputArguments[4]; int int32In = (int)_inputArguments[5]; uint uInt32In = (uint)_inputArguments[6]; long int64In = (long)_inputArguments[7]; ulong uInt64In = (ulong)_inputArguments[8]; float floatIn = (float)_inputArguments[9]; double doubleIn = (double)_inputArguments[10]; bool booleanOut = (bool)_outputArguments[0]; sbyte sByteOut = (sbyte)_outputArguments[1]; byte byteOut = (byte)_outputArguments[2]; short int16Out = (short)_outputArguments[3]; ushort uInt16Out = (ushort)_outputArguments[4]; int int32Out = (int)_outputArguments[5]; uint uInt32Out = (uint)_outputArguments[6]; long int64Out = (long)_outputArguments[7]; ulong uInt64Out = (ulong)_outputArguments[8]; float floatOut = (float)_outputArguments[9]; double doubleOut = (double)_outputArguments[10]; if (OnCall != null) { result = OnCall( _context, this, _objectId, booleanIn, sByteIn, byteIn, int16In, uInt16In, int32In, uInt32In, int64In, uInt64In, floatIn, doubleIn, ref booleanOut, ref sByteOut, ref byteOut, ref int16Out, ref uInt16Out, ref int32Out, ref uInt32Out, ref int64Out, ref uInt64Out, ref floatOut, ref doubleOut); } _outputArguments[0] = booleanOut; _outputArguments[1] = sByteOut; _outputArguments[2] = byteOut; _outputArguments[3] = int16Out; _outputArguments[4] = uInt16Out; _outputArguments[5] = int32Out; _outputArguments[6] = uInt32Out; _outputArguments[7] = int64Out; _outputArguments[8] = uInt64Out; _outputArguments[9] = floatOut; _outputArguments[10] = doubleOut; return result; } #endregion #region Private Fields #endregion } /// /// Used to receive notifications when the method is called. /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// public delegate ServiceResult ScalarValue1MethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, bool booleanIn, sbyte sByteIn, byte byteIn, short int16In, ushort uInt16In, int int32In, uint uInt32In, long int64In, ulong uInt64In, float floatIn, double doubleIn, ref bool booleanOut, ref sbyte sByteOut, ref byte byteOut, ref short int16Out, ref ushort uInt16Out, ref int int32Out, ref uint uInt32Out, ref long int64Out, ref ulong uInt64Out, ref float floatOut, ref double doubleOut); #endif #endregion #region ScalarValue2MethodState Class #if (!OPCUA_EXCLUDE_ScalarValue2MethodState) /// /// Stores an instance of the ScalarValue2MethodType Method. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class ScalarValue2MethodState : MethodState { #region Constructors /// /// Initializes the type with its default attribute values. /// public ScalarValue2MethodState(NodeState parent) : base(parent) { } /// /// Constructs an instance of a node. /// /// The parent. /// The new node. public new static NodeState Construct(NodeState parent) { return new ScalarValue2MethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAABgAAABodHRwOi8vdGVzdC5vcmcvVUEvRGF0YS//////BGGCCgQAAAABABYAAABTY2FsYXJWYWx1" + "ZTJNZXRob2RUeXBlAQHkJAAvAQHkJOQkAAABAf////8CAAAAF2CpCgIAAAAAAA4AAABJbnB1dEFyZ3Vt" + "ZW50cwEB5SQALgBE5SQAAJYKAAAAAQAqAQEXAAAACAAAAFN0cmluZ0luAAz/////AAAAAAABACoBARkA" + "AAAKAAAARGF0ZVRpbWVJbgAN/////wAAAAAAAQAqAQEVAAAABgAAAEd1aWRJbgAO/////wAAAAAAAQAq" + "AQEbAAAADAAAAEJ5dGVTdHJpbmdJbgAP/////wAAAAAAAQAqAQEbAAAADAAAAFhtbEVsZW1lbnRJbgAQ" + "/////wAAAAAAAQAqAQEXAAAACAAAAE5vZGVJZEluABH/////AAAAAAABACoBAR8AAAAQAAAARXhwYW5k" + "ZWROb2RlSWRJbgAS/////wAAAAAAAQAqAQEeAAAADwAAAFF1YWxpZmllZE5hbWVJbgAU/////wAAAAAA" + "AQAqAQEeAAAADwAAAExvY2FsaXplZFRleHRJbgAV/////wAAAAAAAQAqAQEbAAAADAAAAFN0YXR1c0Nv" + "ZGVJbgAT/////wAAAAAAAQAoAQEAAAABAAAAAAAAAAEB/////wAAAAAXYKkKAgAAAAAADwAAAE91dHB1" + "dEFyZ3VtZW50cwEB5iQALgBE5iQAAJYKAAAAAQAqAQEYAAAACQAAAFN0cmluZ091dAAM/////wAAAAAA" + "AQAqAQEaAAAACwAAAERhdGVUaW1lT3V0AA3/////AAAAAAABACoBARYAAAAHAAAAR3VpZE91dAAO////" + "/wAAAAAAAQAqAQEcAAAADQAAAEJ5dGVTdHJpbmdPdXQAD/////8AAAAAAAEAKgEBHAAAAA0AAABYbWxF" + "bGVtZW50T3V0ABD/////AAAAAAABACoBARgAAAAJAAAATm9kZUlkT3V0ABH/////AAAAAAABACoBASAA" + "AAARAAAARXhwYW5kZWROb2RlSWRPdXQAEv////8AAAAAAAEAKgEBHwAAABAAAABRdWFsaWZpZWROYW1l" + "T3V0ABT/////AAAAAAABACoBAR8AAAAQAAAATG9jYWxpemVkVGV4dE91dAAV/////wAAAAAAAQAqAQEc" + "AAAADQAAAFN0YXR1c0NvZGVPdXQAE/////8AAAAAAAEAKAEBAAAAAQAAAAAAAAABAf////8AAAAA"; #endregion #endif #endregion #region Event Callbacks /// /// Raised when the the method is called. /// public ScalarValue2MethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// /// Invokes the method, returns the result and output argument. /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult result = null; string stringIn = (string)_inputArguments[0]; DateTime dateTimeIn = (DateTime)_inputArguments[1]; Uuid guidIn = (Uuid)_inputArguments[2]; byte[] byteStringIn = (byte[])_inputArguments[3]; XmlElement xmlElementIn = (XmlElement)_inputArguments[4]; NodeId nodeIdIn = (NodeId)_inputArguments[5]; ExpandedNodeId expandedNodeIdIn = (ExpandedNodeId)_inputArguments[6]; QualifiedName qualifiedNameIn = (QualifiedName)_inputArguments[7]; LocalizedText localizedTextIn = (LocalizedText)_inputArguments[8]; StatusCode statusCodeIn = (StatusCode)_inputArguments[9]; string stringOut = (string)_outputArguments[0]; DateTime dateTimeOut = (DateTime)_outputArguments[1]; Uuid guidOut = (Uuid)_outputArguments[2]; byte[] byteStringOut = (byte[])_outputArguments[3]; XmlElement xmlElementOut = (XmlElement)_outputArguments[4]; NodeId nodeIdOut = (NodeId)_outputArguments[5]; ExpandedNodeId expandedNodeIdOut = (ExpandedNodeId)_outputArguments[6]; QualifiedName qualifiedNameOut = (QualifiedName)_outputArguments[7]; LocalizedText localizedTextOut = (LocalizedText)_outputArguments[8]; StatusCode statusCodeOut = (StatusCode)_outputArguments[9]; if (OnCall != null) { result = OnCall( _context, this, _objectId, stringIn, dateTimeIn, guidIn, byteStringIn, xmlElementIn, nodeIdIn, expandedNodeIdIn, qualifiedNameIn, localizedTextIn, statusCodeIn, ref stringOut, ref dateTimeOut, ref guidOut, ref byteStringOut, ref xmlElementOut, ref nodeIdOut, ref expandedNodeIdOut, ref qualifiedNameOut, ref localizedTextOut, ref statusCodeOut); } _outputArguments[0] = stringOut; _outputArguments[1] = dateTimeOut; _outputArguments[2] = guidOut; _outputArguments[3] = byteStringOut; _outputArguments[4] = xmlElementOut; _outputArguments[5] = nodeIdOut; _outputArguments[6] = expandedNodeIdOut; _outputArguments[7] = qualifiedNameOut; _outputArguments[8] = localizedTextOut; _outputArguments[9] = statusCodeOut; return result; } #endregion #region Private Fields #endregion } /// /// Used to receive notifications when the method is called. /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// public delegate ServiceResult ScalarValue2MethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, string stringIn, DateTime dateTimeIn, Uuid guidIn, byte[] byteStringIn, XmlElement xmlElementIn, NodeId nodeIdIn, ExpandedNodeId expandedNodeIdIn, QualifiedName qualifiedNameIn, LocalizedText localizedTextIn, StatusCode statusCodeIn, ref string stringOut, ref DateTime dateTimeOut, ref Uuid guidOut, ref byte[] byteStringOut, ref XmlElement xmlElementOut, ref NodeId nodeIdOut, ref ExpandedNodeId expandedNodeIdOut, ref QualifiedName qualifiedNameOut, ref LocalizedText localizedTextOut, ref StatusCode statusCodeOut); #endif #endregion #region ScalarValue3MethodState Class #if (!OPCUA_EXCLUDE_ScalarValue3MethodState) /// /// Stores an instance of the ScalarValue3MethodType Method. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class ScalarValue3MethodState : MethodState { #region Constructors /// /// Initializes the type with its default attribute values. /// public ScalarValue3MethodState(NodeState parent) : base(parent) { } /// /// Constructs an instance of a node. /// /// The parent. /// The new node. public new static NodeState Construct(NodeState parent) { return new ScalarValue3MethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAABgAAABodHRwOi8vdGVzdC5vcmcvVUEvRGF0YS//////BGGCCgQAAAABABYAAABTY2FsYXJWYWx1" + "ZTNNZXRob2RUeXBlAQHnJAAvAQHnJOckAAABAf////8CAAAAF2CpCgIAAAAAAA4AAABJbnB1dEFyZ3Vt" + "ZW50cwEB6CQALgBE6CQAAJYDAAAAAQAqAQEYAAAACQAAAFZhcmlhbnRJbgAY/////wAAAAAAAQAqAQEc" + "AAAADQAAAEVudW1lcmF0aW9uSW4AHf////8AAAAAAAEAKgEBGgAAAAsAAABTdHJ1Y3R1cmVJbgAW////" + "/wAAAAAAAQAoAQEAAAABAAAAAAAAAAEB/////wAAAAAXYKkKAgAAAAAADwAAAE91dHB1dEFyZ3VtZW50" + "cwEB6SQALgBE6SQAAJYDAAAAAQAqAQEZAAAACgAAAFZhcmlhbnRPdXQAGP////8AAAAAAAEAKgEBHQAA" + "AA4AAABFbnVtZXJhdGlvbk91dAAd/////wAAAAAAAQAqAQEbAAAADAAAAFN0cnVjdHVyZU91dAAW////" + "/wAAAAAAAQAoAQEAAAABAAAAAAAAAAEB/////wAAAAA="; #endregion #endif #endregion #region Event Callbacks /// /// Raised when the the method is called. /// public ScalarValue3MethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// /// Invokes the method, returns the result and output argument. /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult result = null; object variantIn = (object)_inputArguments[0]; int enumerationIn = (int)_inputArguments[1]; ExtensionObject structureIn = (ExtensionObject)_inputArguments[2]; object variantOut = (object)_outputArguments[0]; int enumerationOut = (int)_outputArguments[1]; ExtensionObject structureOut = (ExtensionObject)_outputArguments[2]; if (OnCall != null) { result = OnCall( _context, this, _objectId, variantIn, enumerationIn, structureIn, ref variantOut, ref enumerationOut, ref structureOut); } _outputArguments[0] = variantOut; _outputArguments[1] = enumerationOut; _outputArguments[2] = structureOut; return result; } #endregion #region Private Fields #endregion } /// /// Used to receive notifications when the method is called. /// /// /// /// /// /// /// /// /// /// /// public delegate ServiceResult ScalarValue3MethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, object variantIn, int enumerationIn, ExtensionObject structureIn, ref object variantOut, ref int enumerationOut, ref ExtensionObject structureOut); #endif #endregion #region ScalarValueObjectState Class #if (!OPCUA_EXCLUDE_ScalarValueObjectState) /// /// Stores an instance of the ScalarValueObjectType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCode("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class ScalarValueObjectState : TestDataObjectState { #region Constructors /// /// Initializes the type with its default attribute values. /// /// public ScalarValueObjectState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return NodeId.Create(ObjectTypes.ScalarValueObjectType, Namespaces.TestData, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// /// /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAABgAAABodHRwOi8vdGVzdC5vcmcvVUEvRGF0YS//////BGCAAgEAAAABAB0AAABTY2FsYXJWYWx1" + "ZU9iamVjdFR5cGVJbnN0YW5jZQEB6iQBAeok6iQAAAEAAAAAJAABAe4kHgAAADVgiQoCAAAAAQAQAAAA" + "U2ltdWxhdGlvbkFjdGl2ZQEB6yQDAAAAAEcAAABJZiB0cnVlIHRoZSBzZXJ2ZXIgd2lsbCBwcm9kdWNl" + "IG5ldyB2YWx1ZXMgZm9yIGVhY2ggbW9uaXRvcmVkIHZhcmlhYmxlLgAuAETrJAAAAAH/////AQH/////" + "AAAAAARhggoEAAAAAQAOAAAAR2VuZXJhdGVWYWx1ZXMBAewkAC8BAakk7CQAAAEB/////wEAAAAXYKkK" + "AgAAAAAADgAAAElucHV0QXJndW1lbnRzAQHtJAAuAETtJAAAlgEAAAABACoBAUYAAAAKAAAASXRlcmF0" + "aW9ucwAH/////wAAAAADAAAAACUAAABUaGUgbnVtYmVyIG9mIG5ldyB2YWx1ZXMgdG8gZ2VuZXJhdGUu" + "AQAoAQEAAAABAAAAAAAAAAEB/////wAAAAAEYIAKAQAAAAEADQAAAEN5Y2xlQ29tcGxldGUBAe4kAC8B" + "AEEL7iQAAAEAAAAAJAEBAeokFwAAABVgiQoCAAAAAAAHAAAARXZlbnRJZAEB7yQALgBE7yQAAAAP////" + "/wEB/////wAAAAAVYIkKAgAAAAAACQAAAEV2ZW50VHlwZQEB8CQALgBE8CQAAAAR/////wEB/////wAA" + "AAAVYIkKAgAAAAAACgAAAFNvdXJjZU5vZGUBAfEkAC4ARPEkAAAAEf////8BAf////8AAAAAFWCJCgIA" + "AAAAAAoAAABTb3VyY2VOYW1lAQHyJAAuAETyJAAAAAz/////AQH/////AAAAABVgiQoCAAAAAAAEAAAA" + "VGltZQEB8yQALgBE8yQAAAEAJgH/////AQH/////AAAAABVgiQoCAAAAAAALAAAAUmVjZWl2ZVRpbWUB" + "AfQkAC4ARPQkAAABACYB/////wEB/////wAAAAAVYIkKAgAAAAAABwAAAE1lc3NhZ2UBAfYkAC4ARPYk" + "AAAAFf////8BAf////8AAAAAFWCJCgIAAAAAAAgAAABTZXZlcml0eQEB9yQALgBE9yQAAAAF/////wEB" + "/////wAAAAAVYIkKAgAAAAAAEAAAAENvbmRpdGlvbkNsYXNzSWQBATwtAC4ARDwtAAAAEf////8BAf//" + "//8AAAAAFWCJCgIAAAAAABIAAABDb25kaXRpb25DbGFzc05hbWUBAT0tAC4ARD0tAAAAFf////8BAf//" + "//8AAAAAFWCJCgIAAAAAAA0AAABDb25kaXRpb25OYW1lAQEmLQAuAEQmLQAAAAz/////AQH/////AAAA" + "ABVgiQoCAAAAAAAIAAAAQnJhbmNoSWQBAfgkAC4ARPgkAAAAEf////8BAf////8AAAAAFWCJCgIAAAAA" + "AAYAAABSZXRhaW4BAfkkAC4ARPkkAAAAAf////8BAf////8AAAAAFWCJCgIAAAAAAAwAAABFbmFibGVk" + "U3RhdGUBAfokAC8BACMj+iQAAAAV/////wEBAgAAAAEALCMAAQEPJQEALCMAAQEXJQEAAAAVYIkKAgAA" + "AAAAAgAAAElkAQH7JAAuAET7JAAAAAH/////AQH/////AAAAABVgiQoCAAAAAAAHAAAAUXVhbGl0eQEB" + "ACUALwEAKiMAJQAAABP/////AQH/////AQAAABVgiQoCAAAAAAAPAAAAU291cmNlVGltZXN0YW1wAQEB" + "JQAuAEQBJQAAAQAmAf////8BAf////8AAAAAFWCJCgIAAAAAAAwAAABMYXN0U2V2ZXJpdHkBAQQlAC8B" + "ACojBCUAAAAF/////wEB/////wEAAAAVYIkKAgAAAAAADwAAAFNvdXJjZVRpbWVzdGFtcAEBBSUALgBE" + "BSUAAAEAJgH/////AQH/////AAAAABVgiQoCAAAAAAAHAAAAQ29tbWVudAEBBiUALwEAKiMGJQAAABX/" + "////AQH/////AQAAABVgiQoCAAAAAAAPAAAAU291cmNlVGltZXN0YW1wAQEHJQAuAEQHJQAAAQAmAf//" + "//8BAf////8AAAAAFWCJCgIAAAAAAAwAAABDbGllbnRVc2VySWQBAQglAC4ARAglAAAADP////8BAf//" + "//8AAAAABGGCCgQAAAAAAAcAAABEaXNhYmxlAQEKJQAvAQBEIwolAAABAQEAAAABAPkLAAEA8woAAAAA" + "BGGCCgQAAAAAAAYAAABFbmFibGUBAQklAC8BAEMjCSUAAAEBAQAAAAEA+QsAAQDzCgAAAAAEYYIKBAAA" + "AAAACgAAAEFkZENvbW1lbnQBAQslAC8BAEUjCyUAAAEBAQAAAAEA+QsAAQANCwEAAAAXYKkKAgAAAAAA" + "DgAAAElucHV0QXJndW1lbnRzAQEMJQAuAEQMJQAAlgIAAAABACoBAUYAAAAHAAAARXZlbnRJZAAP////" + "/wAAAAADAAAAACgAAABUaGUgaWRlbnRpZmllciBmb3IgdGhlIGV2ZW50IHRvIGNvbW1lbnQuAQAqAQFC" + "AAAABwAAAENvbW1lbnQAFf////8AAAAAAwAAAAAkAAAAVGhlIGNvbW1lbnQgdG8gYWRkIHRvIHRoZSBj" + "b25kaXRpb24uAQAoAQEAAAABAAAAAAAAAAEB/////wAAAAAVYIkKAgAAAAAACgAAAEFja2VkU3RhdGUB" + "AQ8lAC8BACMjDyUAAAAV/////wEBAQAAAAEALCMBAQH6JAEAAAAVYIkKAgAAAAAAAgAAAElkAQEQJQAu" + "AEQQJQAAAAH/////AQH/////AAAAAARhggoEAAAAAAALAAAAQWNrbm93bGVkZ2UBAR8lAC8BAJcjHyUA" + "AAEBAQAAAAEA+QsAAQDwIgEAAAAXYKkKAgAAAAAADgAAAElucHV0QXJndW1lbnRzAQEgJQAuAEQgJQAA" + "lgIAAAABACoBAUYAAAAHAAAARXZlbnRJZAAP/////wAAAAADAAAAACgAAABUaGUgaWRlbnRpZmllciBm" + "b3IgdGhlIGV2ZW50IHRvIGNvbW1lbnQuAQAqAQFCAAAABwAAAENvbW1lbnQAFf////8AAAAAAwAAAAAk" + "AAAAVGhlIGNvbW1lbnQgdG8gYWRkIHRvIHRoZSBjb25kaXRpb24uAQAoAQEAAAABAAAAAAAAAAEB////" + "/wAAAAAVYIkKAgAAAAEADAAAAEJvb2xlYW5WYWx1ZQEBIyUALwA/IyUAAAAB/////wEB/////wAAAAAV" + "YIkKAgAAAAEACgAAAFNCeXRlVmFsdWUBASQlAC8APyQlAAAAAv////8BAf////8AAAAAFWCJCgIAAAAB" + "AAkAAABCeXRlVmFsdWUBASUlAC8APyUlAAAAA/////8BAf////8AAAAAFWCJCgIAAAABAAoAAABJbnQx" + "NlZhbHVlAQEmJQAvAD8mJQAAAAT/////AQH/////AAAAABVgiQoCAAAAAQALAAAAVUludDE2VmFsdWUB" + "ASclAC8APyclAAAABf////8BAf////8AAAAAFWCJCgIAAAABAAoAAABJbnQzMlZhbHVlAQEoJQAvAD8o" + "JQAAAAb/////AQH/////AAAAABVgiQoCAAAAAQALAAAAVUludDMyVmFsdWUBASklAC8APyklAAAAB///" + "//8BAf////8AAAAAFWCJCgIAAAABAAoAAABJbnQ2NFZhbHVlAQEqJQAvAD8qJQAAAAj/////AQH/////" + "AAAAABVgiQoCAAAAAQALAAAAVUludDY0VmFsdWUBASslAC8APyslAAAACf////8BAf////8AAAAAFWCJ" + "CgIAAAABAAoAAABGbG9hdFZhbHVlAQEsJQAvAD8sJQAAAAr/////AQH/////AAAAABVgiQoCAAAAAQAL" + "AAAARG91YmxlVmFsdWUBAS0lAC8APy0lAAAAC/////8BAf////8AAAAAFWCJCgIAAAABAAsAAABTdHJp" + "bmdWYWx1ZQEBLiUALwA/LiUAAAAM/////wEB/////wAAAAAVYIkKAgAAAAEADQAAAERhdGVUaW1lVmFs" + "dWUBAS8lAC8APy8lAAAADf////8BAf////8AAAAAFWCJCgIAAAABAAkAAABHdWlkVmFsdWUBATAlAC8A" + "PzAlAAAADv////8BAf////8AAAAAFWCJCgIAAAABAA8AAABCeXRlU3RyaW5nVmFsdWUBATElAC8APzEl" + "AAAAD/////8BAf////8AAAAAFWCJCgIAAAABAA8AAABYbWxFbGVtZW50VmFsdWUBATIlAC8APzIlAAAA" + "EP////8BAf////8AAAAAFWCJCgIAAAABAAsAAABOb2RlSWRWYWx1ZQEBMyUALwA/MyUAAAAR/////wEB" + "/////wAAAAAVYIkKAgAAAAEAEwAAAEV4cGFuZGVkTm9kZUlkVmFsdWUBATQlAC8APzQlAAAAEv////8B" + "Af////8AAAAAFWCJCgIAAAABABIAAABRdWFsaWZpZWROYW1lVmFsdWUBATUlAC8APzUlAAAAFP////8B" + "Af////8AAAAAFWCJCgIAAAABABIAAABMb2NhbGl6ZWRUZXh0VmFsdWUBATYlAC8APzYlAAAAFf////8B" + "Af////8AAAAAFWCJCgIAAAABAA8AAABTdGF0dXNDb2RlVmFsdWUBATclAC8APzclAAAAE/////8BAf//" + "//8AAAAAFWCJCgIAAAABAAwAAABWYXJpYW50VmFsdWUBATglAC8APzglAAAAGP////8BAf////8AAAAA" + "FWCJCgIAAAABABAAAABFbnVtZXJhdGlvblZhbHVlAQE5JQAvAD85JQAAAB3/////AQH/////AAAAABVg" + "iQoCAAAAAQAOAAAAU3RydWN0dXJlVmFsdWUBATolAC8APzolAAAAFv////8BAf////8AAAAAFWCJCgIA" + "AAABAAsAAABOdW1iZXJWYWx1ZQEBOyUALwA/OyUAAAAa/////wEB/////wAAAAAVYIkKAgAAAAEADAAA" + "AEludGVnZXJWYWx1ZQEBPCUALwA/PCUAAAAb/////wEB/////wAAAAAVYIkKAgAAAAEADQAAAFVJbnRl" + "Z2VyVmFsdWUBAT0lAC8APz0lAAAAHP////8BAf////8AAAAA"; #endregion #endif #endregion #region Public Properties /// public BaseDataVariableState BooleanValue { get => m_booleanValue; set { if (!ReferenceEquals(m_booleanValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_booleanValue = value; } } /// public BaseDataVariableState SByteValue { get => m_sByteValue; set { if (!ReferenceEquals(m_sByteValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_sByteValue = value; } } /// public BaseDataVariableState ByteValue { get => m_byteValue; set { if (!ReferenceEquals(m_byteValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_byteValue = value; } } /// public BaseDataVariableState Int16Value { get => m_int16Value; set { if (!ReferenceEquals(m_int16Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_int16Value = value; } } /// public BaseDataVariableState UInt16Value { get => m_uInt16Value; set { if (!ReferenceEquals(m_uInt16Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_uInt16Value = value; } } /// public BaseDataVariableState Int32Value { get => m_int32Value; set { if (!ReferenceEquals(m_int32Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_int32Value = value; } } /// public BaseDataVariableState UInt32Value { get => m_uInt32Value; set { if (!ReferenceEquals(m_uInt32Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_uInt32Value = value; } } /// public BaseDataVariableState Int64Value { get => m_int64Value; set { if (!ReferenceEquals(m_int64Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_int64Value = value; } } /// public BaseDataVariableState UInt64Value { get => m_uInt64Value; set { if (!ReferenceEquals(m_uInt64Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_uInt64Value = value; } } /// public BaseDataVariableState FloatValue { get => m_floatValue; set { if (!ReferenceEquals(m_floatValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_floatValue = value; } } /// public BaseDataVariableState DoubleValue { get => m_doubleValue; set { if (!ReferenceEquals(m_doubleValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_doubleValue = value; } } /// public BaseDataVariableState StringValue { get => m_stringValue; set { if (!ReferenceEquals(m_stringValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_stringValue = value; } } /// public BaseDataVariableState DateTimeValue { get => m_dateTimeValue; set { if (!ReferenceEquals(m_dateTimeValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_dateTimeValue = value; } } /// public BaseDataVariableState GuidValue { get => m_guidValue; set { if (!ReferenceEquals(m_guidValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_guidValue = value; } } /// public BaseDataVariableState ByteStringValue { get => m_byteStringValue; set { if (!ReferenceEquals(m_byteStringValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_byteStringValue = value; } } /// public BaseDataVariableState XmlElementValue { get => m_xmlElementValue; set { if (!ReferenceEquals(m_xmlElementValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_xmlElementValue = value; } } /// public BaseDataVariableState NodeIdValue { get => m_nodeIdValue; set { if (!ReferenceEquals(m_nodeIdValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_nodeIdValue = value; } } /// public BaseDataVariableState ExpandedNodeIdValue { get => m_expandedNodeIdValue; set { if (!ReferenceEquals(m_expandedNodeIdValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_expandedNodeIdValue = value; } } /// public BaseDataVariableState QualifiedNameValue { get => m_qualifiedNameValue; set { if (!ReferenceEquals(m_qualifiedNameValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_qualifiedNameValue = value; } } /// public BaseDataVariableState LocalizedTextValue { get => m_localizedTextValue; set { if (!ReferenceEquals(m_localizedTextValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_localizedTextValue = value; } } /// public BaseDataVariableState StatusCodeValue { get => m_statusCodeValue; set { if (!ReferenceEquals(m_statusCodeValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_statusCodeValue = value; } } /// public BaseDataVariableState VariantValue { get => m_variantValue; set { if (!ReferenceEquals(m_variantValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_variantValue = value; } } /// public BaseDataVariableState EnumerationValue { get => m_enumerationValue; set { if (!ReferenceEquals(m_enumerationValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_enumerationValue = value; } } /// public BaseDataVariableState StructureValue { get => m_structureValue; set { if (!ReferenceEquals(m_structureValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_structureValue = value; } } /// public BaseDataVariableState NumberValue { get => m_numberValue; set { if (!ReferenceEquals(m_numberValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_numberValue = value; } } /// public BaseDataVariableState IntegerValue { get => m_integerValue; set { if (!ReferenceEquals(m_integerValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_integerValue = value; } } /// public BaseDataVariableState UIntegerValue { get => m_uIntegerValue; set { if (!ReferenceEquals(m_uIntegerValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_uIntegerValue = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_booleanValue != null) { children.Add(m_booleanValue); } if (m_sByteValue != null) { children.Add(m_sByteValue); } if (m_byteValue != null) { children.Add(m_byteValue); } if (m_int16Value != null) { children.Add(m_int16Value); } if (m_uInt16Value != null) { children.Add(m_uInt16Value); } if (m_int32Value != null) { children.Add(m_int32Value); } if (m_uInt32Value != null) { children.Add(m_uInt32Value); } if (m_int64Value != null) { children.Add(m_int64Value); } if (m_uInt64Value != null) { children.Add(m_uInt64Value); } if (m_floatValue != null) { children.Add(m_floatValue); } if (m_doubleValue != null) { children.Add(m_doubleValue); } if (m_stringValue != null) { children.Add(m_stringValue); } if (m_dateTimeValue != null) { children.Add(m_dateTimeValue); } if (m_guidValue != null) { children.Add(m_guidValue); } if (m_byteStringValue != null) { children.Add(m_byteStringValue); } if (m_xmlElementValue != null) { children.Add(m_xmlElementValue); } if (m_nodeIdValue != null) { children.Add(m_nodeIdValue); } if (m_expandedNodeIdValue != null) { children.Add(m_expandedNodeIdValue); } if (m_qualifiedNameValue != null) { children.Add(m_qualifiedNameValue); } if (m_localizedTextValue != null) { children.Add(m_localizedTextValue); } if (m_statusCodeValue != null) { children.Add(m_statusCodeValue); } if (m_variantValue != null) { children.Add(m_variantValue); } if (m_enumerationValue != null) { children.Add(m_enumerationValue); } if (m_structureValue != null) { children.Add(m_structureValue); } if (m_numberValue != null) { children.Add(m_numberValue); } if (m_integerValue != null) { children.Add(m_integerValue); } if (m_uIntegerValue != null) { children.Add(m_uIntegerValue); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// /// /// /// /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case BrowseNames.BooleanValue: { if (createOrReplace && BooleanValue == null) { if (replacement == null) { BooleanValue = new BaseDataVariableState(this); } else { BooleanValue = (BaseDataVariableState)replacement; } } instance = BooleanValue; break; } case BrowseNames.SByteValue: { if (createOrReplace && SByteValue == null) { if (replacement == null) { SByteValue = new BaseDataVariableState(this); } else { SByteValue = (BaseDataVariableState)replacement; } } instance = SByteValue; break; } case BrowseNames.ByteValue: { if (createOrReplace && ByteValue == null) { if (replacement == null) { ByteValue = new BaseDataVariableState(this); } else { ByteValue = (BaseDataVariableState)replacement; } } instance = ByteValue; break; } case BrowseNames.Int16Value: { if (createOrReplace && Int16Value == null) { if (replacement == null) { Int16Value = new BaseDataVariableState(this); } else { Int16Value = (BaseDataVariableState)replacement; } } instance = Int16Value; break; } case BrowseNames.UInt16Value: { if (createOrReplace && UInt16Value == null) { if (replacement == null) { UInt16Value = new BaseDataVariableState(this); } else { UInt16Value = (BaseDataVariableState)replacement; } } instance = UInt16Value; break; } case BrowseNames.Int32Value: { if (createOrReplace && Int32Value == null) { if (replacement == null) { Int32Value = new BaseDataVariableState(this); } else { Int32Value = (BaseDataVariableState)replacement; } } instance = Int32Value; break; } case BrowseNames.UInt32Value: { if (createOrReplace && UInt32Value == null) { if (replacement == null) { UInt32Value = new BaseDataVariableState(this); } else { UInt32Value = (BaseDataVariableState)replacement; } } instance = UInt32Value; break; } case BrowseNames.Int64Value: { if (createOrReplace && Int64Value == null) { if (replacement == null) { Int64Value = new BaseDataVariableState(this); } else { Int64Value = (BaseDataVariableState)replacement; } } instance = Int64Value; break; } case BrowseNames.UInt64Value: { if (createOrReplace && UInt64Value == null) { if (replacement == null) { UInt64Value = new BaseDataVariableState(this); } else { UInt64Value = (BaseDataVariableState)replacement; } } instance = UInt64Value; break; } case BrowseNames.FloatValue: { if (createOrReplace && FloatValue == null) { if (replacement == null) { FloatValue = new BaseDataVariableState(this); } else { FloatValue = (BaseDataVariableState)replacement; } } instance = FloatValue; break; } case BrowseNames.DoubleValue: { if (createOrReplace && DoubleValue == null) { if (replacement == null) { DoubleValue = new BaseDataVariableState(this); } else { DoubleValue = (BaseDataVariableState)replacement; } } instance = DoubleValue; break; } case BrowseNames.StringValue: { if (createOrReplace && StringValue == null) { if (replacement == null) { StringValue = new BaseDataVariableState(this); } else { StringValue = (BaseDataVariableState)replacement; } } instance = StringValue; break; } case BrowseNames.DateTimeValue: { if (createOrReplace && DateTimeValue == null) { if (replacement == null) { DateTimeValue = new BaseDataVariableState(this); } else { DateTimeValue = (BaseDataVariableState)replacement; } } instance = DateTimeValue; break; } case BrowseNames.GuidValue: { if (createOrReplace && GuidValue == null) { if (replacement == null) { GuidValue = new BaseDataVariableState(this); } else { GuidValue = (BaseDataVariableState)replacement; } } instance = GuidValue; break; } case BrowseNames.ByteStringValue: { if (createOrReplace && ByteStringValue == null) { if (replacement == null) { ByteStringValue = new BaseDataVariableState(this); } else { ByteStringValue = (BaseDataVariableState)replacement; } } instance = ByteStringValue; break; } case BrowseNames.XmlElementValue: { if (createOrReplace && XmlElementValue == null) { if (replacement == null) { XmlElementValue = new BaseDataVariableState(this); } else { XmlElementValue = (BaseDataVariableState)replacement; } } instance = XmlElementValue; break; } case BrowseNames.NodeIdValue: { if (createOrReplace && NodeIdValue == null) { if (replacement == null) { NodeIdValue = new BaseDataVariableState(this); } else { NodeIdValue = (BaseDataVariableState)replacement; } } instance = NodeIdValue; break; } case BrowseNames.ExpandedNodeIdValue: { if (createOrReplace && ExpandedNodeIdValue == null) { if (replacement == null) { ExpandedNodeIdValue = new BaseDataVariableState(this); } else { ExpandedNodeIdValue = (BaseDataVariableState)replacement; } } instance = ExpandedNodeIdValue; break; } case BrowseNames.QualifiedNameValue: { if (createOrReplace && QualifiedNameValue == null) { if (replacement == null) { QualifiedNameValue = new BaseDataVariableState(this); } else { QualifiedNameValue = (BaseDataVariableState)replacement; } } instance = QualifiedNameValue; break; } case BrowseNames.LocalizedTextValue: { if (createOrReplace && LocalizedTextValue == null) { if (replacement == null) { LocalizedTextValue = new BaseDataVariableState(this); } else { LocalizedTextValue = (BaseDataVariableState)replacement; } } instance = LocalizedTextValue; break; } case BrowseNames.StatusCodeValue: { if (createOrReplace && StatusCodeValue == null) { if (replacement == null) { StatusCodeValue = new BaseDataVariableState(this); } else { StatusCodeValue = (BaseDataVariableState)replacement; } } instance = StatusCodeValue; break; } case BrowseNames.VariantValue: { if (createOrReplace && VariantValue == null) { if (replacement == null) { VariantValue = new BaseDataVariableState(this); } else { VariantValue = (BaseDataVariableState)replacement; } } instance = VariantValue; break; } case BrowseNames.EnumerationValue: { if (createOrReplace && EnumerationValue == null) { if (replacement == null) { EnumerationValue = new BaseDataVariableState(this); } else { EnumerationValue = (BaseDataVariableState)replacement; } } instance = EnumerationValue; break; } case BrowseNames.StructureValue: { if (createOrReplace && StructureValue == null) { if (replacement == null) { StructureValue = new BaseDataVariableState(this); } else { StructureValue = (BaseDataVariableState)replacement; } } instance = StructureValue; break; } case BrowseNames.NumberValue: { if (createOrReplace && NumberValue == null) { if (replacement == null) { NumberValue = new BaseDataVariableState(this); } else { NumberValue = (BaseDataVariableState)replacement; } } instance = NumberValue; break; } case BrowseNames.IntegerValue: { if (createOrReplace && IntegerValue == null) { if (replacement == null) { IntegerValue = new BaseDataVariableState(this); } else { IntegerValue = (BaseDataVariableState)replacement; } } instance = IntegerValue; break; } case BrowseNames.UIntegerValue: { if (createOrReplace && UIntegerValue == null) { if (replacement == null) { UIntegerValue = new BaseDataVariableState(this); } else { UIntegerValue = (BaseDataVariableState)replacement; } } instance = UIntegerValue; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private BaseDataVariableState m_booleanValue; private BaseDataVariableState m_sByteValue; private BaseDataVariableState m_byteValue; private BaseDataVariableState m_int16Value; private BaseDataVariableState m_uInt16Value; private BaseDataVariableState m_int32Value; private BaseDataVariableState m_uInt32Value; private BaseDataVariableState m_int64Value; private BaseDataVariableState m_uInt64Value; private BaseDataVariableState m_floatValue; private BaseDataVariableState m_doubleValue; private BaseDataVariableState m_stringValue; private BaseDataVariableState m_dateTimeValue; private BaseDataVariableState m_guidValue; private BaseDataVariableState m_byteStringValue; private BaseDataVariableState m_xmlElementValue; private BaseDataVariableState m_nodeIdValue; private BaseDataVariableState m_expandedNodeIdValue; private BaseDataVariableState m_qualifiedNameValue; private BaseDataVariableState m_localizedTextValue; private BaseDataVariableState m_statusCodeValue; private BaseDataVariableState m_variantValue; private BaseDataVariableState m_enumerationValue; private BaseDataVariableState m_structureValue; private BaseDataVariableState m_numberValue; private BaseDataVariableState m_integerValue; private BaseDataVariableState m_uIntegerValue; #endregion } #endif #endregion #region AnalogScalarValueObjectState Class #if (!OPCUA_EXCLUDE_AnalogScalarValueObjectState) /// /// Stores an instance of the AnalogScalarValueObjectType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCode("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class AnalogScalarValueObjectState : TestDataObjectState { #region Constructors /// /// Initializes the type with its default attribute values. /// /// public AnalogScalarValueObjectState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return NodeId.Create(ObjectTypes.AnalogScalarValueObjectType, Namespaces.TestData, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// /// /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAABgAAABodHRwOi8vdGVzdC5vcmcvVUEvRGF0YS//////BGCAAgEAAAABACMAAABBbmFsb2dTY2Fs" + "YXJWYWx1ZU9iamVjdFR5cGVJbnN0YW5jZQEBPiUBAT4lPiUAAAEAAAAAJAABAUIlEAAAADVgiQoCAAAA" + "AQAQAAAAU2ltdWxhdGlvbkFjdGl2ZQEBPyUDAAAAAEcAAABJZiB0cnVlIHRoZSBzZXJ2ZXIgd2lsbCBw" + "cm9kdWNlIG5ldyB2YWx1ZXMgZm9yIGVhY2ggbW9uaXRvcmVkIHZhcmlhYmxlLgAuAEQ/JQAAAAH/////" + "AQH/////AAAAAARhggoEAAAAAQAOAAAAR2VuZXJhdGVWYWx1ZXMBAUAlAC8BAakkQCUAAAEB/////wEA" + "AAAXYKkKAgAAAAAADgAAAElucHV0QXJndW1lbnRzAQFBJQAuAERBJQAAlgEAAAABACoBAUYAAAAKAAAA" + "SXRlcmF0aW9ucwAH/////wAAAAADAAAAACUAAABUaGUgbnVtYmVyIG9mIG5ldyB2YWx1ZXMgdG8gZ2Vu" + "ZXJhdGUuAQAoAQEAAAABAAAAAAAAAAEB/////wAAAAAEYIAKAQAAAAEADQAAAEN5Y2xlQ29tcGxldGUB" + "AUIlAC8BAEELQiUAAAEAAAAAJAEBAT4lFwAAABVgiQoCAAAAAAAHAAAARXZlbnRJZAEBQyUALgBEQyUA" + "AAAP/////wEB/////wAAAAAVYIkKAgAAAAAACQAAAEV2ZW50VHlwZQEBRCUALgBERCUAAAAR/////wEB" + "/////wAAAAAVYIkKAgAAAAAACgAAAFNvdXJjZU5vZGUBAUUlAC4AREUlAAAAEf////8BAf////8AAAAA" + "FWCJCgIAAAAAAAoAAABTb3VyY2VOYW1lAQFGJQAuAERGJQAAAAz/////AQH/////AAAAABVgiQoCAAAA" + "AAAEAAAAVGltZQEBRyUALgBERyUAAAEAJgH/////AQH/////AAAAABVgiQoCAAAAAAALAAAAUmVjZWl2" + "ZVRpbWUBAUglAC4AREglAAABACYB/////wEB/////wAAAAAVYIkKAgAAAAAABwAAAE1lc3NhZ2UBAUol" + "AC4AREolAAAAFf////8BAf////8AAAAAFWCJCgIAAAAAAAgAAABTZXZlcml0eQEBSyUALgBESyUAAAAF" + "/////wEB/////wAAAAAVYIkKAgAAAAAAEAAAAENvbmRpdGlvbkNsYXNzSWQBAT4tAC4ARD4tAAAAEf//" + "//8BAf////8AAAAAFWCJCgIAAAAAABIAAABDb25kaXRpb25DbGFzc05hbWUBAT8tAC4ARD8tAAAAFf//" + "//8BAf////8AAAAAFWCJCgIAAAAAAA0AAABDb25kaXRpb25OYW1lAQEnLQAuAEQnLQAAAAz/////AQH/" + "////AAAAABVgiQoCAAAAAAAIAAAAQnJhbmNoSWQBAUwlAC4AREwlAAAAEf////8BAf////8AAAAAFWCJ" + "CgIAAAAAAAYAAABSZXRhaW4BAU0lAC4ARE0lAAAAAf////8BAf////8AAAAAFWCJCgIAAAAAAAwAAABF" + "bmFibGVkU3RhdGUBAU4lAC8BACMjTiUAAAAV/////wEBAgAAAAEALCMAAQFjJQEALCMAAQFrJQEAAAAV" + "YIkKAgAAAAAAAgAAAElkAQFPJQAuAERPJQAAAAH/////AQH/////AAAAABVgiQoCAAAAAAAHAAAAUXVh" + "bGl0eQEBVCUALwEAKiNUJQAAABP/////AQH/////AQAAABVgiQoCAAAAAAAPAAAAU291cmNlVGltZXN0" + "YW1wAQFVJQAuAERVJQAAAQAmAf////8BAf////8AAAAAFWCJCgIAAAAAAAwAAABMYXN0U2V2ZXJpdHkB" + "AVglAC8BACojWCUAAAAF/////wEB/////wEAAAAVYIkKAgAAAAAADwAAAFNvdXJjZVRpbWVzdGFtcAEB" + "WSUALgBEWSUAAAEAJgH/////AQH/////AAAAABVgiQoCAAAAAAAHAAAAQ29tbWVudAEBWiUALwEAKiNa" + "JQAAABX/////AQH/////AQAAABVgiQoCAAAAAAAPAAAAU291cmNlVGltZXN0YW1wAQFbJQAuAERbJQAA" + "AQAmAf////8BAf////8AAAAAFWCJCgIAAAAAAAwAAABDbGllbnRVc2VySWQBAVwlAC4ARFwlAAAADP//" + "//8BAf////8AAAAABGGCCgQAAAAAAAcAAABEaXNhYmxlAQFeJQAvAQBEI14lAAABAQEAAAABAPkLAAEA" + "8woAAAAABGGCCgQAAAAAAAYAAABFbmFibGUBAV0lAC8BAEMjXSUAAAEBAQAAAAEA+QsAAQDzCgAAAAAE" + "YYIKBAAAAAAACgAAAEFkZENvbW1lbnQBAV8lAC8BAEUjXyUAAAEBAQAAAAEA+QsAAQANCwEAAAAXYKkK" + "AgAAAAAADgAAAElucHV0QXJndW1lbnRzAQFgJQAuAERgJQAAlgIAAAABACoBAUYAAAAHAAAARXZlbnRJ" + "ZAAP/////wAAAAADAAAAACgAAABUaGUgaWRlbnRpZmllciBmb3IgdGhlIGV2ZW50IHRvIGNvbW1lbnQu" + "AQAqAQFCAAAABwAAAENvbW1lbnQAFf////8AAAAAAwAAAAAkAAAAVGhlIGNvbW1lbnQgdG8gYWRkIHRv" + "IHRoZSBjb25kaXRpb24uAQAoAQEAAAABAAAAAAAAAAEB/////wAAAAAVYIkKAgAAAAAACgAAAEFja2Vk" + "U3RhdGUBAWMlAC8BACMjYyUAAAAV/////wEBAQAAAAEALCMBAQFOJQEAAAAVYIkKAgAAAAAAAgAAAElk" + "AQFkJQAuAERkJQAAAAH/////AQH/////AAAAAARhggoEAAAAAAALAAAAQWNrbm93bGVkZ2UBAXMlAC8B" + "AJcjcyUAAAEBAQAAAAEA+QsAAQDwIgEAAAAXYKkKAgAAAAAADgAAAElucHV0QXJndW1lbnRzAQF0JQAu" + "AER0JQAAlgIAAAABACoBAUYAAAAHAAAARXZlbnRJZAAP/////wAAAAADAAAAACgAAABUaGUgaWRlbnRp" + "ZmllciBmb3IgdGhlIGV2ZW50IHRvIGNvbW1lbnQuAQAqAQFCAAAABwAAAENvbW1lbnQAFf////8AAAAA" + "AwAAAAAkAAAAVGhlIGNvbW1lbnQgdG8gYWRkIHRvIHRoZSBjb25kaXRpb24uAQAoAQEAAAABAAAAAAAA" + "AAEB/////wAAAAAVYIkKAgAAAAEACgAAAFNCeXRlVmFsdWUBAXclAC8BAEAJdyUAAAAC/////wEB////" + "/wEAAAAVYIkKAgAAAAAABwAAAEVVUmFuZ2UBAXolAC4ARHolAAABAHQD/////wEB/////wAAAAAVYIkK" + "AgAAAAEACQAAAEJ5dGVWYWx1ZQEBfSUALwEAQAl9JQAAAAP/////AQH/////AQAAABVgiQoCAAAAAAAH" + "AAAARVVSYW5nZQEBgCUALgBEgCUAAAEAdAP/////AQH/////AAAAABVgiQoCAAAAAQAKAAAASW50MTZW" + "YWx1ZQEBgyUALwEAQAmDJQAAAAT/////AQH/////AQAAABVgiQoCAAAAAAAHAAAARVVSYW5nZQEBhiUA" + "LgBEhiUAAAEAdAP/////AQH/////AAAAABVgiQoCAAAAAQALAAAAVUludDE2VmFsdWUBAYklAC8BAEAJ" + "iSUAAAAF/////wEB/////wEAAAAVYIkKAgAAAAAABwAAAEVVUmFuZ2UBAYwlAC4ARIwlAAABAHQD////" + "/wEB/////wAAAAAVYIkKAgAAAAEACgAAAEludDMyVmFsdWUBAY8lAC8BAEAJjyUAAAAG/////wEB////" + "/wEAAAAVYIkKAgAAAAAABwAAAEVVUmFuZ2UBAZIlAC4ARJIlAAABAHQD/////wEB/////wAAAAAVYIkK" + "AgAAAAEACwAAAFVJbnQzMlZhbHVlAQGVJQAvAQBACZUlAAAAB/////8BAf////8BAAAAFWCJCgIAAAAA" + "AAcAAABFVVJhbmdlAQGYJQAuAESYJQAAAQB0A/////8BAf////8AAAAAFWCJCgIAAAABAAoAAABJbnQ2" + "NFZhbHVlAQGbJQAvAQBACZslAAAACP////8BAf////8BAAAAFWCJCgIAAAAAAAcAAABFVVJhbmdlAQGe" + "JQAuAESeJQAAAQB0A/////8BAf////8AAAAAFWCJCgIAAAABAAsAAABVSW50NjRWYWx1ZQEBoSUALwEA" + "QAmhJQAAAAn/////AQH/////AQAAABVgiQoCAAAAAAAHAAAARVVSYW5nZQEBpCUALgBEpCUAAAEAdAP/" + "////AQH/////AAAAABVgiQoCAAAAAQAKAAAARmxvYXRWYWx1ZQEBpyUALwEAQAmnJQAAAAr/////AQH/" + "////AQAAABVgiQoCAAAAAAAHAAAARVVSYW5nZQEBqiUALgBEqiUAAAEAdAP/////AQH/////AAAAABVg" + "iQoCAAAAAQALAAAARG91YmxlVmFsdWUBAa0lAC8BAEAJrSUAAAAL/////wEB/////wEAAAAVYIkKAgAA" + "AAAABwAAAEVVUmFuZ2UBAbAlAC4ARLAlAAABAHQD/////wEB/////wAAAAAVYIkKAgAAAAEACwAAAE51" + "bWJlclZhbHVlAQGzJQAvAQBACbMlAAAAGv////8BAf////8BAAAAFWCJCgIAAAAAAAcAAABFVVJhbmdl" + "AQG2JQAuAES2JQAAAQB0A/////8BAf////8AAAAAFWCJCgIAAAABAAwAAABJbnRlZ2VyVmFsdWUBAbkl" + "AC8BAEAJuSUAAAAb/////wEB/////wEAAAAVYIkKAgAAAAAABwAAAEVVUmFuZ2UBAbwlAC4ARLwlAAAB" + "AHQD/////wEB/////wAAAAAVYIkKAgAAAAEADQAAAFVJbnRlZ2VyVmFsdWUBAb8lAC8BAEAJvyUAAAAc" + "/////wEB/////wEAAAAVYIkKAgAAAAAABwAAAEVVUmFuZ2UBAcIlAC4ARMIlAAABAHQD/////wEB////" + "/wAAAAA="; #endregion #endif #endregion #region Public Properties /// public AnalogItemState SByteValue { get => m_sByteValue; set { if (!ReferenceEquals(m_sByteValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_sByteValue = value; } } /// public AnalogItemState ByteValue { get => m_byteValue; set { if (!ReferenceEquals(m_byteValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_byteValue = value; } } /// public AnalogItemState Int16Value { get => m_int16Value; set { if (!ReferenceEquals(m_int16Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_int16Value = value; } } /// public AnalogItemState UInt16Value { get => m_uInt16Value; set { if (!ReferenceEquals(m_uInt16Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_uInt16Value = value; } } /// public AnalogItemState Int32Value { get => m_int32Value; set { if (!ReferenceEquals(m_int32Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_int32Value = value; } } /// public AnalogItemState UInt32Value { get => m_uInt32Value; set { if (!ReferenceEquals(m_uInt32Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_uInt32Value = value; } } /// public AnalogItemState Int64Value { get => m_int64Value; set { if (!ReferenceEquals(m_int64Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_int64Value = value; } } /// public AnalogItemState UInt64Value { get => m_uInt64Value; set { if (!ReferenceEquals(m_uInt64Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_uInt64Value = value; } } /// public AnalogItemState FloatValue { get => m_floatValue; set { if (!ReferenceEquals(m_floatValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_floatValue = value; } } /// public AnalogItemState DoubleValue { get => m_doubleValue; set { if (!ReferenceEquals(m_doubleValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_doubleValue = value; } } /// public AnalogItemState NumberValue { get => m_numberValue; set { if (!ReferenceEquals(m_numberValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_numberValue = value; } } /// public AnalogItemState IntegerValue { get => m_integerValue; set { if (!ReferenceEquals(m_integerValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_integerValue = value; } } /// public AnalogItemState UIntegerValue { get => m_uIntegerValue; set { if (!ReferenceEquals(m_uIntegerValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_uIntegerValue = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_sByteValue != null) { children.Add(m_sByteValue); } if (m_byteValue != null) { children.Add(m_byteValue); } if (m_int16Value != null) { children.Add(m_int16Value); } if (m_uInt16Value != null) { children.Add(m_uInt16Value); } if (m_int32Value != null) { children.Add(m_int32Value); } if (m_uInt32Value != null) { children.Add(m_uInt32Value); } if (m_int64Value != null) { children.Add(m_int64Value); } if (m_uInt64Value != null) { children.Add(m_uInt64Value); } if (m_floatValue != null) { children.Add(m_floatValue); } if (m_doubleValue != null) { children.Add(m_doubleValue); } if (m_numberValue != null) { children.Add(m_numberValue); } if (m_integerValue != null) { children.Add(m_integerValue); } if (m_uIntegerValue != null) { children.Add(m_uIntegerValue); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// /// /// /// /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case BrowseNames.SByteValue: { if (createOrReplace && SByteValue == null) { if (replacement == null) { SByteValue = new AnalogItemState(this); } else { SByteValue = (AnalogItemState)replacement; } } instance = SByteValue; break; } case BrowseNames.ByteValue: { if (createOrReplace && ByteValue == null) { if (replacement == null) { ByteValue = new AnalogItemState(this); } else { ByteValue = (AnalogItemState)replacement; } } instance = ByteValue; break; } case BrowseNames.Int16Value: { if (createOrReplace && Int16Value == null) { if (replacement == null) { Int16Value = new AnalogItemState(this); } else { Int16Value = (AnalogItemState)replacement; } } instance = Int16Value; break; } case BrowseNames.UInt16Value: { if (createOrReplace && UInt16Value == null) { if (replacement == null) { UInt16Value = new AnalogItemState(this); } else { UInt16Value = (AnalogItemState)replacement; } } instance = UInt16Value; break; } case BrowseNames.Int32Value: { if (createOrReplace && Int32Value == null) { if (replacement == null) { Int32Value = new AnalogItemState(this); } else { Int32Value = (AnalogItemState)replacement; } } instance = Int32Value; break; } case BrowseNames.UInt32Value: { if (createOrReplace && UInt32Value == null) { if (replacement == null) { UInt32Value = new AnalogItemState(this); } else { UInt32Value = (AnalogItemState)replacement; } } instance = UInt32Value; break; } case BrowseNames.Int64Value: { if (createOrReplace && Int64Value == null) { if (replacement == null) { Int64Value = new AnalogItemState(this); } else { Int64Value = (AnalogItemState)replacement; } } instance = Int64Value; break; } case BrowseNames.UInt64Value: { if (createOrReplace && UInt64Value == null) { if (replacement == null) { UInt64Value = new AnalogItemState(this); } else { UInt64Value = (AnalogItemState)replacement; } } instance = UInt64Value; break; } case BrowseNames.FloatValue: { if (createOrReplace && FloatValue == null) { if (replacement == null) { FloatValue = new AnalogItemState(this); } else { FloatValue = (AnalogItemState)replacement; } } instance = FloatValue; break; } case BrowseNames.DoubleValue: { if (createOrReplace && DoubleValue == null) { if (replacement == null) { DoubleValue = new AnalogItemState(this); } else { DoubleValue = (AnalogItemState)replacement; } } instance = DoubleValue; break; } case BrowseNames.NumberValue: { if (createOrReplace && NumberValue == null) { if (replacement == null) { NumberValue = new AnalogItemState(this); } else { NumberValue = (AnalogItemState)replacement; } } instance = NumberValue; break; } case BrowseNames.IntegerValue: { if (createOrReplace && IntegerValue == null) { if (replacement == null) { IntegerValue = new AnalogItemState(this); } else { IntegerValue = (AnalogItemState)replacement; } } instance = IntegerValue; break; } case BrowseNames.UIntegerValue: { if (createOrReplace && UIntegerValue == null) { if (replacement == null) { UIntegerValue = new AnalogItemState(this); } else { UIntegerValue = (AnalogItemState)replacement; } } instance = UIntegerValue; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private AnalogItemState m_sByteValue; private AnalogItemState m_byteValue; private AnalogItemState m_int16Value; private AnalogItemState m_uInt16Value; private AnalogItemState m_int32Value; private AnalogItemState m_uInt32Value; private AnalogItemState m_int64Value; private AnalogItemState m_uInt64Value; private AnalogItemState m_floatValue; private AnalogItemState m_doubleValue; private AnalogItemState m_numberValue; private AnalogItemState m_integerValue; private AnalogItemState m_uIntegerValue; #endregion } #endif #endregion #region ArrayValue1MethodState Class #if (!OPCUA_EXCLUDE_ArrayValue1MethodState) /// /// Stores an instance of the ArrayValue1MethodType Method. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class ArrayValue1MethodState : MethodState { #region Constructors /// /// Initializes the type with its default attribute values. /// public ArrayValue1MethodState(NodeState parent) : base(parent) { } /// /// Constructs an instance of a node. /// /// The parent. /// The new node. public new static NodeState Construct(NodeState parent) { return new ArrayValue1MethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAABgAAABodHRwOi8vdGVzdC5vcmcvVUEvRGF0YS//////BGGCCgQAAAABABUAAABBcnJheVZhbHVl" + "MU1ldGhvZFR5cGUBAcYlAC8BAcYlxiUAAAEB/////wIAAAAXYKkKAgAAAAAADgAAAElucHV0QXJndW1l" + "bnRzAQHHJQAuAETHJQAAlgsAAAABACoBARwAAAAJAAAAQm9vbGVhbkluAAEBAAAAAQAAAAAAAAAAAQAq" + "AQEaAAAABwAAAFNCeXRlSW4AAgEAAAABAAAAAAAAAAABACoBARkAAAAGAAAAQnl0ZUluAAMBAAAAAQAA" + "AAAAAAAAAQAqAQEaAAAABwAAAEludDE2SW4ABAEAAAABAAAAAAAAAAABACoBARsAAAAIAAAAVUludDE2" + "SW4ABQEAAAABAAAAAAAAAAABACoBARoAAAAHAAAASW50MzJJbgAGAQAAAAEAAAAAAAAAAAEAKgEBGwAA" + "AAgAAABVSW50MzJJbgAHAQAAAAEAAAAAAAAAAAEAKgEBGgAAAAcAAABJbnQ2NEluAAgBAAAAAQAAAAAA" + "AAAAAQAqAQEbAAAACAAAAFVJbnQ2NEluAAkBAAAAAQAAAAAAAAAAAQAqAQEaAAAABwAAAEZsb2F0SW4A" + "CgEAAAABAAAAAAAAAAABACoBARsAAAAIAAAARG91YmxlSW4ACwEAAAABAAAAAAAAAAABACgBAQAAAAEA" + "AAAAAAAAAQH/////AAAAABdgqQoCAAAAAAAPAAAAT3V0cHV0QXJndW1lbnRzAQHIJQAuAETIJQAAlgsA" + "AAABACoBAR0AAAAKAAAAQm9vbGVhbk91dAABAQAAAAEAAAAAAAAAAAEAKgEBGwAAAAgAAABTQnl0ZU91" + "dAACAQAAAAEAAAAAAAAAAAEAKgEBGgAAAAcAAABCeXRlT3V0AAMBAAAAAQAAAAAAAAAAAQAqAQEbAAAA" + "CAAAAEludDE2T3V0AAQBAAAAAQAAAAAAAAAAAQAqAQEcAAAACQAAAFVJbnQxNk91dAAFAQAAAAEAAAAA" + "AAAAAAEAKgEBGwAAAAgAAABJbnQzMk91dAAGAQAAAAEAAAAAAAAAAAEAKgEBHAAAAAkAAABVSW50MzJP" + "dXQABwEAAAABAAAAAAAAAAABACoBARsAAAAIAAAASW50NjRPdXQACAEAAAABAAAAAAAAAAABACoBARwA" + "AAAJAAAAVUludDY0T3V0AAkBAAAAAQAAAAAAAAAAAQAqAQEbAAAACAAAAEZsb2F0T3V0AAoBAAAAAQAA" + "AAAAAAAAAQAqAQEcAAAACQAAAERvdWJsZU91dAALAQAAAAEAAAAAAAAAAAEAKAEBAAAAAQAAAAAAAAAB" + "Af////8AAAAA"; #endregion #endif #endregion #region Event Callbacks /// /// Raised when the the method is called. /// public ArrayValue1MethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// /// Invokes the method, returns the result and output argument. /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult result = null; bool[] booleanIn = (bool[])_inputArguments[0]; sbyte[] sByteIn = (sbyte[])_inputArguments[1]; byte[] byteIn = (byte[])_inputArguments[2]; short[] int16In = (short[])_inputArguments[3]; ushort[] uInt16In = (ushort[])_inputArguments[4]; int[] int32In = (int[])_inputArguments[5]; uint[] uInt32In = (uint[])_inputArguments[6]; long[] int64In = (long[])_inputArguments[7]; ulong[] uInt64In = (ulong[])_inputArguments[8]; float[] floatIn = (float[])_inputArguments[9]; double[] doubleIn = (double[])_inputArguments[10]; bool[] booleanOut = (bool[])_outputArguments[0]; sbyte[] sByteOut = (sbyte[])_outputArguments[1]; byte[] byteOut = (byte[])_outputArguments[2]; short[] int16Out = (short[])_outputArguments[3]; ushort[] uInt16Out = (ushort[])_outputArguments[4]; int[] int32Out = (int[])_outputArguments[5]; uint[] uInt32Out = (uint[])_outputArguments[6]; long[] int64Out = (long[])_outputArguments[7]; ulong[] uInt64Out = (ulong[])_outputArguments[8]; float[] floatOut = (float[])_outputArguments[9]; double[] doubleOut = (double[])_outputArguments[10]; if (OnCall != null) { result = OnCall( _context, this, _objectId, booleanIn, sByteIn, byteIn, int16In, uInt16In, int32In, uInt32In, int64In, uInt64In, floatIn, doubleIn, ref booleanOut, ref sByteOut, ref byteOut, ref int16Out, ref uInt16Out, ref int32Out, ref uInt32Out, ref int64Out, ref uInt64Out, ref floatOut, ref doubleOut); } _outputArguments[0] = booleanOut; _outputArguments[1] = sByteOut; _outputArguments[2] = byteOut; _outputArguments[3] = int16Out; _outputArguments[4] = uInt16Out; _outputArguments[5] = int32Out; _outputArguments[6] = uInt32Out; _outputArguments[7] = int64Out; _outputArguments[8] = uInt64Out; _outputArguments[9] = floatOut; _outputArguments[10] = doubleOut; return result; } #endregion #region Private Fields #endregion } /// /// Used to receive notifications when the method is called. /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// public delegate ServiceResult ArrayValue1MethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, bool[] booleanIn, sbyte[] sByteIn, byte[] byteIn, short[] int16In, ushort[] uInt16In, int[] int32In, uint[] uInt32In, long[] int64In, ulong[] uInt64In, float[] floatIn, double[] doubleIn, ref bool[] booleanOut, ref sbyte[] sByteOut, ref byte[] byteOut, ref short[] int16Out, ref ushort[] uInt16Out, ref int[] int32Out, ref uint[] uInt32Out, ref long[] int64Out, ref ulong[] uInt64Out, ref float[] floatOut, ref double[] doubleOut); #endif #endregion #region ArrayValue2MethodState Class #if (!OPCUA_EXCLUDE_ArrayValue2MethodState) /// /// Stores an instance of the ArrayValue2MethodType Method. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class ArrayValue2MethodState : MethodState { #region Constructors /// /// Initializes the type with its default attribute values. /// public ArrayValue2MethodState(NodeState parent) : base(parent) { } /// /// Constructs an instance of a node. /// /// The parent. /// The new node. public new static NodeState Construct(NodeState parent) { return new ArrayValue2MethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAABgAAABodHRwOi8vdGVzdC5vcmcvVUEvRGF0YS//////BGGCCgQAAAABABUAAABBcnJheVZhbHVl" + "Mk1ldGhvZFR5cGUBAcklAC8BAcklySUAAAEB/////wIAAAAXYKkKAgAAAAAADgAAAElucHV0QXJndW1l" + "bnRzAQHKJQAuAETKJQAAlgoAAAABACoBARsAAAAIAAAAU3RyaW5nSW4ADAEAAAABAAAAAAAAAAABACoB" + "AR0AAAAKAAAARGF0ZVRpbWVJbgANAQAAAAEAAAAAAAAAAAEAKgEBGQAAAAYAAABHdWlkSW4ADgEAAAAB" + "AAAAAAAAAAABACoBAR8AAAAMAAAAQnl0ZVN0cmluZ0luAA8BAAAAAQAAAAAAAAAAAQAqAQEfAAAADAAA" + "AFhtbEVsZW1lbnRJbgAQAQAAAAEAAAAAAAAAAAEAKgEBGwAAAAgAAABOb2RlSWRJbgARAQAAAAEAAAAA" + "AAAAAAEAKgEBIwAAABAAAABFeHBhbmRlZE5vZGVJZEluABIBAAAAAQAAAAAAAAAAAQAqAQEiAAAADwAA" + "AFF1YWxpZmllZE5hbWVJbgAUAQAAAAEAAAAAAAAAAAEAKgEBIgAAAA8AAABMb2NhbGl6ZWRUZXh0SW4A" + "FQEAAAABAAAAAAAAAAABACoBAR8AAAAMAAAAU3RhdHVzQ29kZUluABMBAAAAAQAAAAAAAAAAAQAoAQEA" + "AAABAAAAAAAAAAEB/////wAAAAAXYKkKAgAAAAAADwAAAE91dHB1dEFyZ3VtZW50cwEByyUALgBEyyUA" + "AJYKAAAAAQAqAQEcAAAACQAAAFN0cmluZ091dAAMAQAAAAEAAAAAAAAAAAEAKgEBHgAAAAsAAABEYXRl" + "VGltZU91dAANAQAAAAEAAAAAAAAAAAEAKgEBGgAAAAcAAABHdWlkT3V0AA4BAAAAAQAAAAAAAAAAAQAq" + "AQEgAAAADQAAAEJ5dGVTdHJpbmdPdXQADwEAAAABAAAAAAAAAAABACoBASAAAAANAAAAWG1sRWxlbWVu" + "dE91dAAQAQAAAAEAAAAAAAAAAAEAKgEBHAAAAAkAAABOb2RlSWRPdXQAEQEAAAABAAAAAAAAAAABACoB" + "ASQAAAARAAAARXhwYW5kZWROb2RlSWRPdXQAEgEAAAABAAAAAAAAAAABACoBASMAAAAQAAAAUXVhbGlm" + "aWVkTmFtZU91dAAUAQAAAAEAAAAAAAAAAAEAKgEBIwAAABAAAABMb2NhbGl6ZWRUZXh0T3V0ABUBAAAA" + "AQAAAAAAAAAAAQAqAQEgAAAADQAAAFN0YXR1c0NvZGVPdXQAEwEAAAABAAAAAAAAAAABACgBAQAAAAEA" + "AAAAAAAAAQH/////AAAAAA=="; #endregion #endif #endregion #region Event Callbacks /// /// Raised when the the method is called. /// public ArrayValue2MethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// /// Invokes the method, returns the result and output argument. /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult result = null; string[] stringIn = (string[])_inputArguments[0]; DateTime[] dateTimeIn = (DateTime[])_inputArguments[1]; Uuid[] guidIn = (Uuid[])_inputArguments[2]; byte[][] byteStringIn = (byte[][])_inputArguments[3]; XmlElement[] xmlElementIn = (XmlElement[])_inputArguments[4]; NodeId[] nodeIdIn = (NodeId[])_inputArguments[5]; ExpandedNodeId[] expandedNodeIdIn = (ExpandedNodeId[])_inputArguments[6]; QualifiedName[] qualifiedNameIn = (QualifiedName[])_inputArguments[7]; LocalizedText[] localizedTextIn = (LocalizedText[])_inputArguments[8]; StatusCode[] statusCodeIn = (StatusCode[])_inputArguments[9]; string[] stringOut = (string[])_outputArguments[0]; DateTime[] dateTimeOut = (DateTime[])_outputArguments[1]; Uuid[] guidOut = (Uuid[])_outputArguments[2]; byte[][] byteStringOut = (byte[][])_outputArguments[3]; XmlElement[] xmlElementOut = (XmlElement[])_outputArguments[4]; NodeId[] nodeIdOut = (NodeId[])_outputArguments[5]; ExpandedNodeId[] expandedNodeIdOut = (ExpandedNodeId[])_outputArguments[6]; QualifiedName[] qualifiedNameOut = (QualifiedName[])_outputArguments[7]; LocalizedText[] localizedTextOut = (LocalizedText[])_outputArguments[8]; StatusCode[] statusCodeOut = (StatusCode[])_outputArguments[9]; if (OnCall != null) { result = OnCall( _context, this, _objectId, stringIn, dateTimeIn, guidIn, byteStringIn, xmlElementIn, nodeIdIn, expandedNodeIdIn, qualifiedNameIn, localizedTextIn, statusCodeIn, ref stringOut, ref dateTimeOut, ref guidOut, ref byteStringOut, ref xmlElementOut, ref nodeIdOut, ref expandedNodeIdOut, ref qualifiedNameOut, ref localizedTextOut, ref statusCodeOut); } _outputArguments[0] = stringOut; _outputArguments[1] = dateTimeOut; _outputArguments[2] = guidOut; _outputArguments[3] = byteStringOut; _outputArguments[4] = xmlElementOut; _outputArguments[5] = nodeIdOut; _outputArguments[6] = expandedNodeIdOut; _outputArguments[7] = qualifiedNameOut; _outputArguments[8] = localizedTextOut; _outputArguments[9] = statusCodeOut; return result; } #endregion #region Private Fields #endregion } /// /// Used to receive notifications when the method is called. /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// public delegate ServiceResult ArrayValue2MethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, string[] stringIn, DateTime[] dateTimeIn, Uuid[] guidIn, byte[][] byteStringIn, XmlElement[] xmlElementIn, NodeId[] nodeIdIn, ExpandedNodeId[] expandedNodeIdIn, QualifiedName[] qualifiedNameIn, LocalizedText[] localizedTextIn, StatusCode[] statusCodeIn, ref string[] stringOut, ref DateTime[] dateTimeOut, ref Uuid[] guidOut, ref byte[][] byteStringOut, ref XmlElement[] xmlElementOut, ref NodeId[] nodeIdOut, ref ExpandedNodeId[] expandedNodeIdOut, ref QualifiedName[] qualifiedNameOut, ref LocalizedText[] localizedTextOut, ref StatusCode[] statusCodeOut); #endif #endregion #region ArrayValue3MethodState Class #if (!OPCUA_EXCLUDE_ArrayValue3MethodState) /// /// Stores an instance of the ArrayValue3MethodType Method. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class ArrayValue3MethodState : MethodState { #region Constructors /// /// Initializes the type with its default attribute values. /// public ArrayValue3MethodState(NodeState parent) : base(parent) { } /// /// Constructs an instance of a node. /// /// The parent. /// The new node. public new static NodeState Construct(NodeState parent) { return new ArrayValue3MethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAABgAAABodHRwOi8vdGVzdC5vcmcvVUEvRGF0YS//////BGGCCgQAAAABABUAAABBcnJheVZhbHVl" + "M01ldGhvZFR5cGUBAcwlAC8BAcwlzCUAAAEB/////wIAAAAXYKkKAgAAAAAADgAAAElucHV0QXJndW1l" + "bnRzAQHNJQAuAETNJQAAlgMAAAABACoBARwAAAAJAAAAVmFyaWFudEluABgBAAAAAQAAAAAAAAAAAQAq" + "AQEgAAAADQAAAEVudW1lcmF0aW9uSW4AHQEAAAABAAAAAAAAAAABACoBAR4AAAALAAAAU3RydWN0dXJl" + "SW4AFgEAAAABAAAAAAAAAAABACgBAQAAAAEAAAAAAAAAAQH/////AAAAABdgqQoCAAAAAAAPAAAAT3V0" + "cHV0QXJndW1lbnRzAQHOJQAuAETOJQAAlgMAAAABACoBAR0AAAAKAAAAVmFyaWFudE91dAAYAQAAAAEA" + "AAAAAAAAAAEAKgEBIQAAAA4AAABFbnVtZXJhdGlvbk91dAAdAQAAAAEAAAAAAAAAAAEAKgEBHwAAAAwA" + "AABTdHJ1Y3R1cmVPdXQAFgEAAAABAAAAAAAAAAABACgBAQAAAAEAAAAAAAAAAQH/////AAAAAA=="; #endregion #endif #endregion #region Event Callbacks /// /// Raised when the the method is called. /// public ArrayValue3MethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// /// Invokes the method, returns the result and output argument. /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult result = null; Variant[] variantIn = (Variant[])_inputArguments[0]; int[] enumerationIn = (int[])_inputArguments[1]; ExtensionObject[] structureIn = (ExtensionObject[])_inputArguments[2]; Variant[] variantOut = (Variant[])_outputArguments[0]; int[] enumerationOut = (int[])_outputArguments[1]; ExtensionObject[] structureOut = (ExtensionObject[])_outputArguments[2]; if (OnCall != null) { result = OnCall( _context, this, _objectId, variantIn, enumerationIn, structureIn, ref variantOut, ref enumerationOut, ref structureOut); } _outputArguments[0] = variantOut; _outputArguments[1] = enumerationOut; _outputArguments[2] = structureOut; return result; } #endregion #region Private Fields #endregion } /// /// Used to receive notifications when the method is called. /// /// /// /// /// /// /// /// /// /// /// public delegate ServiceResult ArrayValue3MethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, Variant[] variantIn, int[] enumerationIn, ExtensionObject[] structureIn, ref Variant[] variantOut, ref int[] enumerationOut, ref ExtensionObject[] structureOut); #endif #endregion #region ArrayValueObjectState Class #if (!OPCUA_EXCLUDE_ArrayValueObjectState) /// /// Stores an instance of the ArrayValueObjectType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCode("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class ArrayValueObjectState : TestDataObjectState { #region Constructors /// /// Initializes the type with its default attribute values. /// /// public ArrayValueObjectState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return NodeId.Create(ObjectTypes.ArrayValueObjectType, Namespaces.TestData, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// /// /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAABgAAABodHRwOi8vdGVzdC5vcmcvVUEvRGF0YS//////BGCAAgEAAAABABwAAABBcnJheVZhbHVl" + "T2JqZWN0VHlwZUluc3RhbmNlAQHPJQEBzyXPJQAAAQAAAAAkAAEB0yUeAAAANWCJCgIAAAABABAAAABT" + "aW11bGF0aW9uQWN0aXZlAQHQJQMAAAAARwAAAElmIHRydWUgdGhlIHNlcnZlciB3aWxsIHByb2R1Y2Ug" + "bmV3IHZhbHVlcyBmb3IgZWFjaCBtb25pdG9yZWQgdmFyaWFibGUuAC4ARNAlAAAAAf////8BAf////8A" + "AAAABGGCCgQAAAABAA4AAABHZW5lcmF0ZVZhbHVlcwEB0SUALwEBqSTRJQAAAQH/////AQAAABdgqQoC" + "AAAAAAAOAAAASW5wdXRBcmd1bWVudHMBAdIlAC4ARNIlAACWAQAAAAEAKgEBRgAAAAoAAABJdGVyYXRp" + "b25zAAf/////AAAAAAMAAAAAJQAAAFRoZSBudW1iZXIgb2YgbmV3IHZhbHVlcyB0byBnZW5lcmF0ZS4B" + "ACgBAQAAAAEAAAAAAAAAAQH/////AAAAAARggAoBAAAAAQANAAAAQ3ljbGVDb21wbGV0ZQEB0yUALwEA" + "QQvTJQAAAQAAAAAkAQEBzyUXAAAAFWCJCgIAAAAAAAcAAABFdmVudElkAQHUJQAuAETUJQAAAA//////" + "AQH/////AAAAABVgiQoCAAAAAAAJAAAARXZlbnRUeXBlAQHVJQAuAETVJQAAABH/////AQH/////AAAA" + "ABVgiQoCAAAAAAAKAAAAU291cmNlTm9kZQEB1iUALgBE1iUAAAAR/////wEB/////wAAAAAVYIkKAgAA" + "AAAACgAAAFNvdXJjZU5hbWUBAdclAC4ARNclAAAADP////8BAf////8AAAAAFWCJCgIAAAAAAAQAAABU" + "aW1lAQHYJQAuAETYJQAAAQAmAf////8BAf////8AAAAAFWCJCgIAAAAAAAsAAABSZWNlaXZlVGltZQEB" + "2SUALgBE2SUAAAEAJgH/////AQH/////AAAAABVgiQoCAAAAAAAHAAAATWVzc2FnZQEB2yUALgBE2yUA" + "AAAV/////wEB/////wAAAAAVYIkKAgAAAAAACAAAAFNldmVyaXR5AQHcJQAuAETcJQAAAAX/////AQH/" + "////AAAAABVgiQoCAAAAAAAQAAAAQ29uZGl0aW9uQ2xhc3NJZAEBQC0ALgBEQC0AAAAR/////wEB////" + "/wAAAAAVYIkKAgAAAAAAEgAAAENvbmRpdGlvbkNsYXNzTmFtZQEBQS0ALgBEQS0AAAAV/////wEB////" + "/wAAAAAVYIkKAgAAAAAADQAAAENvbmRpdGlvbk5hbWUBASgtAC4ARCgtAAAADP////8BAf////8AAAAA" + "FWCJCgIAAAAAAAgAAABCcmFuY2hJZAEB3SUALgBE3SUAAAAR/////wEB/////wAAAAAVYIkKAgAAAAAA" + "BgAAAFJldGFpbgEB3iUALgBE3iUAAAAB/////wEB/////wAAAAAVYIkKAgAAAAAADAAAAEVuYWJsZWRT" + "dGF0ZQEB3yUALwEAIyPfJQAAABX/////AQECAAAAAQAsIwABAfQlAQAsIwABAfwlAQAAABVgiQoCAAAA" + "AAACAAAASWQBAeAlAC4AROAlAAAAAf////8BAf////8AAAAAFWCJCgIAAAAAAAcAAABRdWFsaXR5AQHl" + "JQAvAQAqI+UlAAAAE/////8BAf////8BAAAAFWCJCgIAAAAAAA8AAABTb3VyY2VUaW1lc3RhbXABAeYl" + "AC4AROYlAAABACYB/////wEB/////wAAAAAVYIkKAgAAAAAADAAAAExhc3RTZXZlcml0eQEB6SUALwEA" + "KiPpJQAAAAX/////AQH/////AQAAABVgiQoCAAAAAAAPAAAAU291cmNlVGltZXN0YW1wAQHqJQAuAETq" + "JQAAAQAmAf////8BAf////8AAAAAFWCJCgIAAAAAAAcAAABDb21tZW50AQHrJQAvAQAqI+slAAAAFf//" + "//8BAf////8BAAAAFWCJCgIAAAAAAA8AAABTb3VyY2VUaW1lc3RhbXABAewlAC4AROwlAAABACYB////" + "/wEB/////wAAAAAVYIkKAgAAAAAADAAAAENsaWVudFVzZXJJZAEB7SUALgBE7SUAAAAM/////wEB////" + "/wAAAAAEYYIKBAAAAAAABwAAAERpc2FibGUBAe8lAC8BAEQj7yUAAAEBAQAAAAEA+QsAAQDzCgAAAAAE" + "YYIKBAAAAAAABgAAAEVuYWJsZQEB7iUALwEAQyPuJQAAAQEBAAAAAQD5CwABAPMKAAAAAARhggoEAAAA" + "AAAKAAAAQWRkQ29tbWVudAEB8CUALwEARSPwJQAAAQEBAAAAAQD5CwABAA0LAQAAABdgqQoCAAAAAAAO" + "AAAASW5wdXRBcmd1bWVudHMBAfElAC4ARPElAACWAgAAAAEAKgEBRgAAAAcAAABFdmVudElkAA//////" + "AAAAAAMAAAAAKAAAAFRoZSBpZGVudGlmaWVyIGZvciB0aGUgZXZlbnQgdG8gY29tbWVudC4BACoBAUIA" + "AAAHAAAAQ29tbWVudAAV/////wAAAAADAAAAACQAAABUaGUgY29tbWVudCB0byBhZGQgdG8gdGhlIGNv" + "bmRpdGlvbi4BACgBAQAAAAEAAAAAAAAAAQH/////AAAAABVgiQoCAAAAAAAKAAAAQWNrZWRTdGF0ZQEB" + "9CUALwEAIyP0JQAAABX/////AQEBAAAAAQAsIwEBAd8lAQAAABVgiQoCAAAAAAACAAAASWQBAfUlAC4A" + "RPUlAAAAAf////8BAf////8AAAAABGGCCgQAAAAAAAsAAABBY2tub3dsZWRnZQEBBCYALwEAlyMEJgAA" + "AQEBAAAAAQD5CwABAPAiAQAAABdgqQoCAAAAAAAOAAAASW5wdXRBcmd1bWVudHMBAQUmAC4ARAUmAACW" + "AgAAAAEAKgEBRgAAAAcAAABFdmVudElkAA//////AAAAAAMAAAAAKAAAAFRoZSBpZGVudGlmaWVyIGZv" + "ciB0aGUgZXZlbnQgdG8gY29tbWVudC4BACoBAUIAAAAHAAAAQ29tbWVudAAV/////wAAAAADAAAAACQA" + "AABUaGUgY29tbWVudCB0byBhZGQgdG8gdGhlIGNvbmRpdGlvbi4BACgBAQAAAAEAAAAAAAAAAQH/////" + "AAAAABdgiQoCAAAAAQAMAAAAQm9vbGVhblZhbHVlAQEIJgAvAD8IJgAAAAEBAAAAAQAAAAAAAAABAf//" + "//8AAAAAF2CJCgIAAAABAAoAAABTQnl0ZVZhbHVlAQEJJgAvAD8JJgAAAAIBAAAAAQAAAAAAAAABAf//" + "//8AAAAAF2CJCgIAAAABAAkAAABCeXRlVmFsdWUBAQomAC8APwomAAAAAwEAAAABAAAAAAAAAAEB////" + "/wAAAAAXYIkKAgAAAAEACgAAAEludDE2VmFsdWUBAQsmAC8APwsmAAAABAEAAAABAAAAAAAAAAEB////" + "/wAAAAAXYIkKAgAAAAEACwAAAFVJbnQxNlZhbHVlAQEMJgAvAD8MJgAAAAUBAAAAAQAAAAAAAAABAf//" + "//8AAAAAF2CJCgIAAAABAAoAAABJbnQzMlZhbHVlAQENJgAvAD8NJgAAAAYBAAAAAQAAAAAAAAABAf//" + "//8AAAAAF2CJCgIAAAABAAsAAABVSW50MzJWYWx1ZQEBDiYALwA/DiYAAAAHAQAAAAEAAAAAAAAAAQH/" + "////AAAAABdgiQoCAAAAAQAKAAAASW50NjRWYWx1ZQEBDyYALwA/DyYAAAAIAQAAAAEAAAAAAAAAAQH/" + "////AAAAABdgiQoCAAAAAQALAAAAVUludDY0VmFsdWUBARAmAC8APxAmAAAACQEAAAABAAAAAAAAAAEB" + "/////wAAAAAXYIkKAgAAAAEACgAAAEZsb2F0VmFsdWUBAREmAC8APxEmAAAACgEAAAABAAAAAAAAAAEB" + "/////wAAAAAXYIkKAgAAAAEACwAAAERvdWJsZVZhbHVlAQESJgAvAD8SJgAAAAsBAAAAAQAAAAAAAAAB" + "Af////8AAAAAF2CJCgIAAAABAAsAAABTdHJpbmdWYWx1ZQEBEyYALwA/EyYAAAAMAQAAAAEAAAAAAAAA" + "AQH/////AAAAABdgiQoCAAAAAQANAAAARGF0ZVRpbWVWYWx1ZQEBFCYALwA/FCYAAAANAQAAAAEAAAAA" + "AAAAAQH/////AAAAABdgiQoCAAAAAQAJAAAAR3VpZFZhbHVlAQEVJgAvAD8VJgAAAA4BAAAAAQAAAAAA" + "AAABAf////8AAAAAF2CJCgIAAAABAA8AAABCeXRlU3RyaW5nVmFsdWUBARYmAC8APxYmAAAADwEAAAAB" + "AAAAAAAAAAEB/////wAAAAAXYIkKAgAAAAEADwAAAFhtbEVsZW1lbnRWYWx1ZQEBFyYALwA/FyYAAAAQ" + "AQAAAAEAAAAAAAAAAQH/////AAAAABdgiQoCAAAAAQALAAAATm9kZUlkVmFsdWUBARgmAC8APxgmAAAA" + "EQEAAAABAAAAAAAAAAEB/////wAAAAAXYIkKAgAAAAEAEwAAAEV4cGFuZGVkTm9kZUlkVmFsdWUBARkm" + "AC8APxkmAAAAEgEAAAABAAAAAAAAAAEB/////wAAAAAXYIkKAgAAAAEAEgAAAFF1YWxpZmllZE5hbWVW" + "YWx1ZQEBGiYALwA/GiYAAAAUAQAAAAEAAAAAAAAAAQH/////AAAAABdgiQoCAAAAAQASAAAATG9jYWxp" + "emVkVGV4dFZhbHVlAQEbJgAvAD8bJgAAABUBAAAAAQAAAAAAAAABAf////8AAAAAF2CJCgIAAAABAA8A" + "AABTdGF0dXNDb2RlVmFsdWUBARwmAC8APxwmAAAAEwEAAAABAAAAAAAAAAEB/////wAAAAAXYIkKAgAA" + "AAEADAAAAFZhcmlhbnRWYWx1ZQEBHSYALwA/HSYAAAAYAQAAAAEAAAAAAAAAAQH/////AAAAABdgiQoC" + "AAAAAQAQAAAARW51bWVyYXRpb25WYWx1ZQEBHiYALwA/HiYAAAAdAQAAAAEAAAAAAAAAAQH/////AAAA" + "ABdgiQoCAAAAAQAOAAAAU3RydWN0dXJlVmFsdWUBAR8mAC8APx8mAAAAFgEAAAABAAAAAAAAAAEB////" + "/wAAAAAXYIkKAgAAAAEACwAAAE51bWJlclZhbHVlAQEgJgAvAD8gJgAAABoBAAAAAQAAAAAAAAABAf//" + "//8AAAAAF2CJCgIAAAABAAwAAABJbnRlZ2VyVmFsdWUBASEmAC8APyEmAAAAGwEAAAABAAAAAAAAAAEB" + "/////wAAAAAXYIkKAgAAAAEADQAAAFVJbnRlZ2VyVmFsdWUBASImAC8APyImAAAAHAEAAAABAAAAAAAA" + "AAEB/////wAAAAA="; #endregion #endif #endregion #region Public Properties /// public BaseDataVariableState BooleanValue { get => m_booleanValue; set { if (!ReferenceEquals(m_booleanValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_booleanValue = value; } } /// public BaseDataVariableState SByteValue { get => m_sByteValue; set { if (!ReferenceEquals(m_sByteValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_sByteValue = value; } } /// public BaseDataVariableState ByteValue { get => m_byteValue; set { if (!ReferenceEquals(m_byteValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_byteValue = value; } } /// public BaseDataVariableState Int16Value { get => m_int16Value; set { if (!ReferenceEquals(m_int16Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_int16Value = value; } } /// public BaseDataVariableState UInt16Value { get => m_uInt16Value; set { if (!ReferenceEquals(m_uInt16Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_uInt16Value = value; } } /// public BaseDataVariableState Int32Value { get => m_int32Value; set { if (!ReferenceEquals(m_int32Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_int32Value = value; } } /// public BaseDataVariableState UInt32Value { get => m_uInt32Value; set { if (!ReferenceEquals(m_uInt32Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_uInt32Value = value; } } /// public BaseDataVariableState Int64Value { get => m_int64Value; set { if (!ReferenceEquals(m_int64Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_int64Value = value; } } /// public BaseDataVariableState UInt64Value { get => m_uInt64Value; set { if (!ReferenceEquals(m_uInt64Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_uInt64Value = value; } } /// public BaseDataVariableState FloatValue { get => m_floatValue; set { if (!ReferenceEquals(m_floatValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_floatValue = value; } } /// public BaseDataVariableState DoubleValue { get => m_doubleValue; set { if (!ReferenceEquals(m_doubleValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_doubleValue = value; } } /// public BaseDataVariableState StringValue { get => m_stringValue; set { if (!ReferenceEquals(m_stringValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_stringValue = value; } } /// public BaseDataVariableState DateTimeValue { get => m_dateTimeValue; set { if (!ReferenceEquals(m_dateTimeValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_dateTimeValue = value; } } /// public BaseDataVariableState GuidValue { get => m_guidValue; set { if (!ReferenceEquals(m_guidValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_guidValue = value; } } /// public BaseDataVariableState ByteStringValue { get => m_byteStringValue; set { if (!ReferenceEquals(m_byteStringValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_byteStringValue = value; } } /// public BaseDataVariableState XmlElementValue { get => m_xmlElementValue; set { if (!ReferenceEquals(m_xmlElementValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_xmlElementValue = value; } } /// public BaseDataVariableState NodeIdValue { get => m_nodeIdValue; set { if (!ReferenceEquals(m_nodeIdValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_nodeIdValue = value; } } /// public BaseDataVariableState ExpandedNodeIdValue { get => m_expandedNodeIdValue; set { if (!ReferenceEquals(m_expandedNodeIdValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_expandedNodeIdValue = value; } } /// public BaseDataVariableState QualifiedNameValue { get => m_qualifiedNameValue; set { if (!ReferenceEquals(m_qualifiedNameValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_qualifiedNameValue = value; } } /// public BaseDataVariableState LocalizedTextValue { get => m_localizedTextValue; set { if (!ReferenceEquals(m_localizedTextValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_localizedTextValue = value; } } /// public BaseDataVariableState StatusCodeValue { get => m_statusCodeValue; set { if (!ReferenceEquals(m_statusCodeValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_statusCodeValue = value; } } /// public BaseDataVariableState VariantValue { get => m_variantValue; set { if (!ReferenceEquals(m_variantValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_variantValue = value; } } /// public BaseDataVariableState EnumerationValue { get => m_enumerationValue; set { if (!ReferenceEquals(m_enumerationValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_enumerationValue = value; } } /// public BaseDataVariableState StructureValue { get => m_structureValue; set { if (!ReferenceEquals(m_structureValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_structureValue = value; } } /// public BaseDataVariableState NumberValue { get => m_numberValue; set { if (!ReferenceEquals(m_numberValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_numberValue = value; } } /// public BaseDataVariableState IntegerValue { get => m_integerValue; set { if (!ReferenceEquals(m_integerValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_integerValue = value; } } /// public BaseDataVariableState UIntegerValue { get => m_uIntegerValue; set { if (!ReferenceEquals(m_uIntegerValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_uIntegerValue = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_booleanValue != null) { children.Add(m_booleanValue); } if (m_sByteValue != null) { children.Add(m_sByteValue); } if (m_byteValue != null) { children.Add(m_byteValue); } if (m_int16Value != null) { children.Add(m_int16Value); } if (m_uInt16Value != null) { children.Add(m_uInt16Value); } if (m_int32Value != null) { children.Add(m_int32Value); } if (m_uInt32Value != null) { children.Add(m_uInt32Value); } if (m_int64Value != null) { children.Add(m_int64Value); } if (m_uInt64Value != null) { children.Add(m_uInt64Value); } if (m_floatValue != null) { children.Add(m_floatValue); } if (m_doubleValue != null) { children.Add(m_doubleValue); } if (m_stringValue != null) { children.Add(m_stringValue); } if (m_dateTimeValue != null) { children.Add(m_dateTimeValue); } if (m_guidValue != null) { children.Add(m_guidValue); } if (m_byteStringValue != null) { children.Add(m_byteStringValue); } if (m_xmlElementValue != null) { children.Add(m_xmlElementValue); } if (m_nodeIdValue != null) { children.Add(m_nodeIdValue); } if (m_expandedNodeIdValue != null) { children.Add(m_expandedNodeIdValue); } if (m_qualifiedNameValue != null) { children.Add(m_qualifiedNameValue); } if (m_localizedTextValue != null) { children.Add(m_localizedTextValue); } if (m_statusCodeValue != null) { children.Add(m_statusCodeValue); } if (m_variantValue != null) { children.Add(m_variantValue); } if (m_enumerationValue != null) { children.Add(m_enumerationValue); } if (m_structureValue != null) { children.Add(m_structureValue); } if (m_numberValue != null) { children.Add(m_numberValue); } if (m_integerValue != null) { children.Add(m_integerValue); } if (m_uIntegerValue != null) { children.Add(m_uIntegerValue); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// /// /// /// /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case BrowseNames.BooleanValue: { if (createOrReplace && BooleanValue == null) { if (replacement == null) { BooleanValue = new BaseDataVariableState(this); } else { BooleanValue = (BaseDataVariableState)replacement; } } instance = BooleanValue; break; } case BrowseNames.SByteValue: { if (createOrReplace && SByteValue == null) { if (replacement == null) { SByteValue = new BaseDataVariableState(this); } else { SByteValue = (BaseDataVariableState)replacement; } } instance = SByteValue; break; } case BrowseNames.ByteValue: { if (createOrReplace && ByteValue == null) { if (replacement == null) { ByteValue = new BaseDataVariableState(this); } else { ByteValue = (BaseDataVariableState)replacement; } } instance = ByteValue; break; } case BrowseNames.Int16Value: { if (createOrReplace && Int16Value == null) { if (replacement == null) { Int16Value = new BaseDataVariableState(this); } else { Int16Value = (BaseDataVariableState)replacement; } } instance = Int16Value; break; } case BrowseNames.UInt16Value: { if (createOrReplace && UInt16Value == null) { if (replacement == null) { UInt16Value = new BaseDataVariableState(this); } else { UInt16Value = (BaseDataVariableState)replacement; } } instance = UInt16Value; break; } case BrowseNames.Int32Value: { if (createOrReplace && Int32Value == null) { if (replacement == null) { Int32Value = new BaseDataVariableState(this); } else { Int32Value = (BaseDataVariableState)replacement; } } instance = Int32Value; break; } case BrowseNames.UInt32Value: { if (createOrReplace && UInt32Value == null) { if (replacement == null) { UInt32Value = new BaseDataVariableState(this); } else { UInt32Value = (BaseDataVariableState)replacement; } } instance = UInt32Value; break; } case BrowseNames.Int64Value: { if (createOrReplace && Int64Value == null) { if (replacement == null) { Int64Value = new BaseDataVariableState(this); } else { Int64Value = (BaseDataVariableState)replacement; } } instance = Int64Value; break; } case BrowseNames.UInt64Value: { if (createOrReplace && UInt64Value == null) { if (replacement == null) { UInt64Value = new BaseDataVariableState(this); } else { UInt64Value = (BaseDataVariableState)replacement; } } instance = UInt64Value; break; } case BrowseNames.FloatValue: { if (createOrReplace && FloatValue == null) { if (replacement == null) { FloatValue = new BaseDataVariableState(this); } else { FloatValue = (BaseDataVariableState)replacement; } } instance = FloatValue; break; } case BrowseNames.DoubleValue: { if (createOrReplace && DoubleValue == null) { if (replacement == null) { DoubleValue = new BaseDataVariableState(this); } else { DoubleValue = (BaseDataVariableState)replacement; } } instance = DoubleValue; break; } case BrowseNames.StringValue: { if (createOrReplace && StringValue == null) { if (replacement == null) { StringValue = new BaseDataVariableState(this); } else { StringValue = (BaseDataVariableState)replacement; } } instance = StringValue; break; } case BrowseNames.DateTimeValue: { if (createOrReplace && DateTimeValue == null) { if (replacement == null) { DateTimeValue = new BaseDataVariableState(this); } else { DateTimeValue = (BaseDataVariableState)replacement; } } instance = DateTimeValue; break; } case BrowseNames.GuidValue: { if (createOrReplace && GuidValue == null) { if (replacement == null) { GuidValue = new BaseDataVariableState(this); } else { GuidValue = (BaseDataVariableState)replacement; } } instance = GuidValue; break; } case BrowseNames.ByteStringValue: { if (createOrReplace && ByteStringValue == null) { if (replacement == null) { ByteStringValue = new BaseDataVariableState(this); } else { ByteStringValue = (BaseDataVariableState)replacement; } } instance = ByteStringValue; break; } case BrowseNames.XmlElementValue: { if (createOrReplace && XmlElementValue == null) { if (replacement == null) { XmlElementValue = new BaseDataVariableState(this); } else { XmlElementValue = (BaseDataVariableState)replacement; } } instance = XmlElementValue; break; } case BrowseNames.NodeIdValue: { if (createOrReplace && NodeIdValue == null) { if (replacement == null) { NodeIdValue = new BaseDataVariableState(this); } else { NodeIdValue = (BaseDataVariableState)replacement; } } instance = NodeIdValue; break; } case BrowseNames.ExpandedNodeIdValue: { if (createOrReplace && ExpandedNodeIdValue == null) { if (replacement == null) { ExpandedNodeIdValue = new BaseDataVariableState(this); } else { ExpandedNodeIdValue = (BaseDataVariableState)replacement; } } instance = ExpandedNodeIdValue; break; } case BrowseNames.QualifiedNameValue: { if (createOrReplace && QualifiedNameValue == null) { if (replacement == null) { QualifiedNameValue = new BaseDataVariableState(this); } else { QualifiedNameValue = (BaseDataVariableState)replacement; } } instance = QualifiedNameValue; break; } case BrowseNames.LocalizedTextValue: { if (createOrReplace && LocalizedTextValue == null) { if (replacement == null) { LocalizedTextValue = new BaseDataVariableState(this); } else { LocalizedTextValue = (BaseDataVariableState)replacement; } } instance = LocalizedTextValue; break; } case BrowseNames.StatusCodeValue: { if (createOrReplace && StatusCodeValue == null) { if (replacement == null) { StatusCodeValue = new BaseDataVariableState(this); } else { StatusCodeValue = (BaseDataVariableState)replacement; } } instance = StatusCodeValue; break; } case BrowseNames.VariantValue: { if (createOrReplace && VariantValue == null) { if (replacement == null) { VariantValue = new BaseDataVariableState(this); } else { VariantValue = (BaseDataVariableState)replacement; } } instance = VariantValue; break; } case BrowseNames.EnumerationValue: { if (createOrReplace && EnumerationValue == null) { if (replacement == null) { EnumerationValue = new BaseDataVariableState(this); } else { EnumerationValue = (BaseDataVariableState)replacement; } } instance = EnumerationValue; break; } case BrowseNames.StructureValue: { if (createOrReplace && StructureValue == null) { if (replacement == null) { StructureValue = new BaseDataVariableState(this); } else { StructureValue = (BaseDataVariableState)replacement; } } instance = StructureValue; break; } case BrowseNames.NumberValue: { if (createOrReplace && NumberValue == null) { if (replacement == null) { NumberValue = new BaseDataVariableState(this); } else { NumberValue = (BaseDataVariableState)replacement; } } instance = NumberValue; break; } case BrowseNames.IntegerValue: { if (createOrReplace && IntegerValue == null) { if (replacement == null) { IntegerValue = new BaseDataVariableState(this); } else { IntegerValue = (BaseDataVariableState)replacement; } } instance = IntegerValue; break; } case BrowseNames.UIntegerValue: { if (createOrReplace && UIntegerValue == null) { if (replacement == null) { UIntegerValue = new BaseDataVariableState(this); } else { UIntegerValue = (BaseDataVariableState)replacement; } } instance = UIntegerValue; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private BaseDataVariableState m_booleanValue; private BaseDataVariableState m_sByteValue; private BaseDataVariableState m_byteValue; private BaseDataVariableState m_int16Value; private BaseDataVariableState m_uInt16Value; private BaseDataVariableState m_int32Value; private BaseDataVariableState m_uInt32Value; private BaseDataVariableState m_int64Value; private BaseDataVariableState m_uInt64Value; private BaseDataVariableState m_floatValue; private BaseDataVariableState m_doubleValue; private BaseDataVariableState m_stringValue; private BaseDataVariableState m_dateTimeValue; private BaseDataVariableState m_guidValue; private BaseDataVariableState m_byteStringValue; private BaseDataVariableState m_xmlElementValue; private BaseDataVariableState m_nodeIdValue; private BaseDataVariableState m_expandedNodeIdValue; private BaseDataVariableState m_qualifiedNameValue; private BaseDataVariableState m_localizedTextValue; private BaseDataVariableState m_statusCodeValue; private BaseDataVariableState m_variantValue; private BaseDataVariableState m_enumerationValue; private BaseDataVariableState m_structureValue; private BaseDataVariableState m_numberValue; private BaseDataVariableState m_integerValue; private BaseDataVariableState m_uIntegerValue; #endregion } #endif #endregion #region AnalogArrayValueObjectState Class #if (!OPCUA_EXCLUDE_AnalogArrayValueObjectState) /// /// Stores an instance of the AnalogArrayValueObjectType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCode("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class AnalogArrayValueObjectState : TestDataObjectState { #region Constructors /// /// Initializes the type with its default attribute values. /// /// public AnalogArrayValueObjectState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return NodeId.Create(ObjectTypes.AnalogArrayValueObjectType, Namespaces.TestData, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// /// /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAABgAAABodHRwOi8vdGVzdC5vcmcvVUEvRGF0YS//////BGCAAgEAAAABACIAAABBbmFsb2dBcnJh" + "eVZhbHVlT2JqZWN0VHlwZUluc3RhbmNlAQEjJgEBIyYjJgAAAQAAAAAkAAEBJyYQAAAANWCJCgIAAAAB" + "ABAAAABTaW11bGF0aW9uQWN0aXZlAQEkJgMAAAAARwAAAElmIHRydWUgdGhlIHNlcnZlciB3aWxsIHBy" + "b2R1Y2UgbmV3IHZhbHVlcyBmb3IgZWFjaCBtb25pdG9yZWQgdmFyaWFibGUuAC4ARCQmAAAAAf////8B" + "Af////8AAAAABGGCCgQAAAABAA4AAABHZW5lcmF0ZVZhbHVlcwEBJSYALwEBqSQlJgAAAQH/////AQAA" + "ABdgqQoCAAAAAAAOAAAASW5wdXRBcmd1bWVudHMBASYmAC4ARCYmAACWAQAAAAEAKgEBRgAAAAoAAABJ" + "dGVyYXRpb25zAAf/////AAAAAAMAAAAAJQAAAFRoZSBudW1iZXIgb2YgbmV3IHZhbHVlcyB0byBnZW5l" + "cmF0ZS4BACgBAQAAAAEAAAAAAAAAAQH/////AAAAAARggAoBAAAAAQANAAAAQ3ljbGVDb21wbGV0ZQEB" + "JyYALwEAQQsnJgAAAQAAAAAkAQEBIyYXAAAAFWCJCgIAAAAAAAcAAABFdmVudElkAQEoJgAuAEQoJgAA" + "AA//////AQH/////AAAAABVgiQoCAAAAAAAJAAAARXZlbnRUeXBlAQEpJgAuAEQpJgAAABH/////AQH/" + "////AAAAABVgiQoCAAAAAAAKAAAAU291cmNlTm9kZQEBKiYALgBEKiYAAAAR/////wEB/////wAAAAAV" + "YIkKAgAAAAAACgAAAFNvdXJjZU5hbWUBASsmAC4ARCsmAAAADP////8BAf////8AAAAAFWCJCgIAAAAA" + "AAQAAABUaW1lAQEsJgAuAEQsJgAAAQAmAf////8BAf////8AAAAAFWCJCgIAAAAAAAsAAABSZWNlaXZl" + "VGltZQEBLSYALgBELSYAAAEAJgH/////AQH/////AAAAABVgiQoCAAAAAAAHAAAATWVzc2FnZQEBLyYA" + "LgBELyYAAAAV/////wEB/////wAAAAAVYIkKAgAAAAAACAAAAFNldmVyaXR5AQEwJgAuAEQwJgAAAAX/" + "////AQH/////AAAAABVgiQoCAAAAAAAQAAAAQ29uZGl0aW9uQ2xhc3NJZAEBQi0ALgBEQi0AAAAR////" + "/wEB/////wAAAAAVYIkKAgAAAAAAEgAAAENvbmRpdGlvbkNsYXNzTmFtZQEBQy0ALgBEQy0AAAAV////" + "/wEB/////wAAAAAVYIkKAgAAAAAADQAAAENvbmRpdGlvbk5hbWUBASktAC4ARCktAAAADP////8BAf//" + "//8AAAAAFWCJCgIAAAAAAAgAAABCcmFuY2hJZAEBMSYALgBEMSYAAAAR/////wEB/////wAAAAAVYIkK" + "AgAAAAAABgAAAFJldGFpbgEBMiYALgBEMiYAAAAB/////wEB/////wAAAAAVYIkKAgAAAAAADAAAAEVu" + "YWJsZWRTdGF0ZQEBMyYALwEAIyMzJgAAABX/////AQECAAAAAQAsIwABAUgmAQAsIwABAVAmAQAAABVg" + "iQoCAAAAAAACAAAASWQBATQmAC4ARDQmAAAAAf////8BAf////8AAAAAFWCJCgIAAAAAAAcAAABRdWFs" + "aXR5AQE5JgAvAQAqIzkmAAAAE/////8BAf////8BAAAAFWCJCgIAAAAAAA8AAABTb3VyY2VUaW1lc3Rh" + "bXABATomAC4ARDomAAABACYB/////wEB/////wAAAAAVYIkKAgAAAAAADAAAAExhc3RTZXZlcml0eQEB" + "PSYALwEAKiM9JgAAAAX/////AQH/////AQAAABVgiQoCAAAAAAAPAAAAU291cmNlVGltZXN0YW1wAQE+" + "JgAuAEQ+JgAAAQAmAf////8BAf////8AAAAAFWCJCgIAAAAAAAcAAABDb21tZW50AQE/JgAvAQAqIz8m" + "AAAAFf////8BAf////8BAAAAFWCJCgIAAAAAAA8AAABTb3VyY2VUaW1lc3RhbXABAUAmAC4AREAmAAAB" + "ACYB/////wEB/////wAAAAAVYIkKAgAAAAAADAAAAENsaWVudFVzZXJJZAEBQSYALgBEQSYAAAAM////" + "/wEB/////wAAAAAEYYIKBAAAAAAABwAAAERpc2FibGUBAUMmAC8BAEQjQyYAAAEBAQAAAAEA+QsAAQDz" + "CgAAAAAEYYIKBAAAAAAABgAAAEVuYWJsZQEBQiYALwEAQyNCJgAAAQEBAAAAAQD5CwABAPMKAAAAAARh" + "ggoEAAAAAAAKAAAAQWRkQ29tbWVudAEBRCYALwEARSNEJgAAAQEBAAAAAQD5CwABAA0LAQAAABdgqQoC" + "AAAAAAAOAAAASW5wdXRBcmd1bWVudHMBAUUmAC4AREUmAACWAgAAAAEAKgEBRgAAAAcAAABFdmVudElk" + "AA//////AAAAAAMAAAAAKAAAAFRoZSBpZGVudGlmaWVyIGZvciB0aGUgZXZlbnQgdG8gY29tbWVudC4B" + "ACoBAUIAAAAHAAAAQ29tbWVudAAV/////wAAAAADAAAAACQAAABUaGUgY29tbWVudCB0byBhZGQgdG8g" + "dGhlIGNvbmRpdGlvbi4BACgBAQAAAAEAAAAAAAAAAQH/////AAAAABVgiQoCAAAAAAAKAAAAQWNrZWRT" + "dGF0ZQEBSCYALwEAIyNIJgAAABX/////AQEBAAAAAQAsIwEBATMmAQAAABVgiQoCAAAAAAACAAAASWQB" + "AUkmAC4AREkmAAAAAf////8BAf////8AAAAABGGCCgQAAAAAAAsAAABBY2tub3dsZWRnZQEBWCYALwEA" + "lyNYJgAAAQEBAAAAAQD5CwABAPAiAQAAABdgqQoCAAAAAAAOAAAASW5wdXRBcmd1bWVudHMBAVkmAC4A" + "RFkmAACWAgAAAAEAKgEBRgAAAAcAAABFdmVudElkAA//////AAAAAAMAAAAAKAAAAFRoZSBpZGVudGlm" + "aWVyIGZvciB0aGUgZXZlbnQgdG8gY29tbWVudC4BACoBAUIAAAAHAAAAQ29tbWVudAAV/////wAAAAAD" + "AAAAACQAAABUaGUgY29tbWVudCB0byBhZGQgdG8gdGhlIGNvbmRpdGlvbi4BACgBAQAAAAEAAAAAAAAA" + "AQH/////AAAAABdgiQoCAAAAAQAKAAAAU0J5dGVWYWx1ZQEBXCYALwEAQAlcJgAAAAIBAAAAAQAAAAAA" + "AAABAf////8BAAAAFWCJCgIAAAAAAAcAAABFVVJhbmdlAQFfJgAuAERfJgAAAQB0A/////8BAf////8A" + "AAAAF2CJCgIAAAABAAkAAABCeXRlVmFsdWUBAWImAC8BAEAJYiYAAAADAQAAAAEAAAAAAAAAAQH/////" + "AQAAABVgiQoCAAAAAAAHAAAARVVSYW5nZQEBZSYALgBEZSYAAAEAdAP/////AQH/////AAAAABdgiQoC" + "AAAAAQAKAAAASW50MTZWYWx1ZQEBaCYALwEAQAloJgAAAAQBAAAAAQAAAAAAAAABAf////8BAAAAFWCJ" + "CgIAAAAAAAcAAABFVVJhbmdlAQFrJgAuAERrJgAAAQB0A/////8BAf////8AAAAAF2CJCgIAAAABAAsA" + "AABVSW50MTZWYWx1ZQEBbiYALwEAQAluJgAAAAUBAAAAAQAAAAAAAAABAf////8BAAAAFWCJCgIAAAAA" + "AAcAAABFVVJhbmdlAQFxJgAuAERxJgAAAQB0A/////8BAf////8AAAAAF2CJCgIAAAABAAoAAABJbnQz" + "MlZhbHVlAQF0JgAvAQBACXQmAAAABgEAAAABAAAAAAAAAAEB/////wEAAAAVYIkKAgAAAAAABwAAAEVV" + "UmFuZ2UBAXcmAC4ARHcmAAABAHQD/////wEB/////wAAAAAXYIkKAgAAAAEACwAAAFVJbnQzMlZhbHVl" + "AQF6JgAvAQBACXomAAAABwEAAAABAAAAAAAAAAEB/////wEAAAAVYIkKAgAAAAAABwAAAEVVUmFuZ2UB" + "AX0mAC4ARH0mAAABAHQD/////wEB/////wAAAAAXYIkKAgAAAAEACgAAAEludDY0VmFsdWUBAYAmAC8B" + "AEAJgCYAAAAIAQAAAAEAAAAAAAAAAQH/////AQAAABVgiQoCAAAAAAAHAAAARVVSYW5nZQEBgyYALgBE" + "gyYAAAEAdAP/////AQH/////AAAAABdgiQoCAAAAAQALAAAAVUludDY0VmFsdWUBAYYmAC8BAEAJhiYA" + "AAAJAQAAAAEAAAAAAAAAAQH/////AQAAABVgiQoCAAAAAAAHAAAARVVSYW5nZQEBiSYALgBEiSYAAAEA" + "dAP/////AQH/////AAAAABdgiQoCAAAAAQAKAAAARmxvYXRWYWx1ZQEBjCYALwEAQAmMJgAAAAoBAAAA" + "AQAAAAAAAAABAf////8BAAAAFWCJCgIAAAAAAAcAAABFVVJhbmdlAQGPJgAuAESPJgAAAQB0A/////8B" + "Af////8AAAAAF2CJCgIAAAABAAsAAABEb3VibGVWYWx1ZQEBkiYALwEAQAmSJgAAAAsBAAAAAQAAAAAA" + "AAABAf////8BAAAAFWCJCgIAAAAAAAcAAABFVVJhbmdlAQGVJgAuAESVJgAAAQB0A/////8BAf////8A" + "AAAAF2CJCgIAAAABAAsAAABOdW1iZXJWYWx1ZQEBmCYALwEAQAmYJgAAABoBAAAAAQAAAAAAAAABAf//" + "//8BAAAAFWCJCgIAAAAAAAcAAABFVVJhbmdlAQGbJgAuAESbJgAAAQB0A/////8BAf////8AAAAAF2CJ" + "CgIAAAABAAwAAABJbnRlZ2VyVmFsdWUBAZ4mAC8BAEAJniYAAAAbAQAAAAEAAAAAAAAAAQH/////AQAA" + "ABVgiQoCAAAAAAAHAAAARVVSYW5nZQEBoSYALgBEoSYAAAEAdAP/////AQH/////AAAAABdgiQoCAAAA" + "AQANAAAAVUludGVnZXJWYWx1ZQEBpCYALwEAQAmkJgAAABwBAAAAAQAAAAAAAAABAf////8BAAAAFWCJ" + "CgIAAAAAAAcAAABFVVJhbmdlAQGnJgAuAESnJgAAAQB0A/////8BAf////8AAAAA"; #endregion #endif #endregion #region Public Properties /// public AnalogItemState SByteValue { get => m_sByteValue; set { if (!ReferenceEquals(m_sByteValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_sByteValue = value; } } /// public AnalogItemState ByteValue { get => m_byteValue; set { if (!ReferenceEquals(m_byteValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_byteValue = value; } } /// public AnalogItemState Int16Value { get => m_int16Value; set { if (!ReferenceEquals(m_int16Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_int16Value = value; } } /// public AnalogItemState UInt16Value { get => m_uInt16Value; set { if (!ReferenceEquals(m_uInt16Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_uInt16Value = value; } } /// public AnalogItemState Int32Value { get => m_int32Value; set { if (!ReferenceEquals(m_int32Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_int32Value = value; } } /// public AnalogItemState UInt32Value { get => m_uInt32Value; set { if (!ReferenceEquals(m_uInt32Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_uInt32Value = value; } } /// public AnalogItemState Int64Value { get => m_int64Value; set { if (!ReferenceEquals(m_int64Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_int64Value = value; } } /// public AnalogItemState UInt64Value { get => m_uInt64Value; set { if (!ReferenceEquals(m_uInt64Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_uInt64Value = value; } } /// public AnalogItemState FloatValue { get => m_floatValue; set { if (!ReferenceEquals(m_floatValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_floatValue = value; } } /// public AnalogItemState DoubleValue { get => m_doubleValue; set { if (!ReferenceEquals(m_doubleValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_doubleValue = value; } } /// public AnalogItemState NumberValue { get => m_numberValue; set { if (!ReferenceEquals(m_numberValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_numberValue = value; } } /// public AnalogItemState IntegerValue { get => m_integerValue; set { if (!ReferenceEquals(m_integerValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_integerValue = value; } } /// public AnalogItemState UIntegerValue { get => m_uIntegerValue; set { if (!ReferenceEquals(m_uIntegerValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_uIntegerValue = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_sByteValue != null) { children.Add(m_sByteValue); } if (m_byteValue != null) { children.Add(m_byteValue); } if (m_int16Value != null) { children.Add(m_int16Value); } if (m_uInt16Value != null) { children.Add(m_uInt16Value); } if (m_int32Value != null) { children.Add(m_int32Value); } if (m_uInt32Value != null) { children.Add(m_uInt32Value); } if (m_int64Value != null) { children.Add(m_int64Value); } if (m_uInt64Value != null) { children.Add(m_uInt64Value); } if (m_floatValue != null) { children.Add(m_floatValue); } if (m_doubleValue != null) { children.Add(m_doubleValue); } if (m_numberValue != null) { children.Add(m_numberValue); } if (m_integerValue != null) { children.Add(m_integerValue); } if (m_uIntegerValue != null) { children.Add(m_uIntegerValue); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// /// /// /// /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case BrowseNames.SByteValue: { if (createOrReplace && SByteValue == null) { if (replacement == null) { SByteValue = new AnalogItemState(this); } else { SByteValue = (AnalogItemState)replacement; } } instance = SByteValue; break; } case BrowseNames.ByteValue: { if (createOrReplace && ByteValue == null) { if (replacement == null) { ByteValue = new AnalogItemState(this); } else { ByteValue = (AnalogItemState)replacement; } } instance = ByteValue; break; } case BrowseNames.Int16Value: { if (createOrReplace && Int16Value == null) { if (replacement == null) { Int16Value = new AnalogItemState(this); } else { Int16Value = (AnalogItemState)replacement; } } instance = Int16Value; break; } case BrowseNames.UInt16Value: { if (createOrReplace && UInt16Value == null) { if (replacement == null) { UInt16Value = new AnalogItemState(this); } else { UInt16Value = (AnalogItemState)replacement; } } instance = UInt16Value; break; } case BrowseNames.Int32Value: { if (createOrReplace && Int32Value == null) { if (replacement == null) { Int32Value = new AnalogItemState(this); } else { Int32Value = (AnalogItemState)replacement; } } instance = Int32Value; break; } case BrowseNames.UInt32Value: { if (createOrReplace && UInt32Value == null) { if (replacement == null) { UInt32Value = new AnalogItemState(this); } else { UInt32Value = (AnalogItemState)replacement; } } instance = UInt32Value; break; } case BrowseNames.Int64Value: { if (createOrReplace && Int64Value == null) { if (replacement == null) { Int64Value = new AnalogItemState(this); } else { Int64Value = (AnalogItemState)replacement; } } instance = Int64Value; break; } case BrowseNames.UInt64Value: { if (createOrReplace && UInt64Value == null) { if (replacement == null) { UInt64Value = new AnalogItemState(this); } else { UInt64Value = (AnalogItemState)replacement; } } instance = UInt64Value; break; } case BrowseNames.FloatValue: { if (createOrReplace && FloatValue == null) { if (replacement == null) { FloatValue = new AnalogItemState(this); } else { FloatValue = (AnalogItemState)replacement; } } instance = FloatValue; break; } case BrowseNames.DoubleValue: { if (createOrReplace && DoubleValue == null) { if (replacement == null) { DoubleValue = new AnalogItemState(this); } else { DoubleValue = (AnalogItemState)replacement; } } instance = DoubleValue; break; } case BrowseNames.NumberValue: { if (createOrReplace && NumberValue == null) { if (replacement == null) { NumberValue = new AnalogItemState(this); } else { NumberValue = (AnalogItemState)replacement; } } instance = NumberValue; break; } case BrowseNames.IntegerValue: { if (createOrReplace && IntegerValue == null) { if (replacement == null) { IntegerValue = new AnalogItemState(this); } else { IntegerValue = (AnalogItemState)replacement; } } instance = IntegerValue; break; } case BrowseNames.UIntegerValue: { if (createOrReplace && UIntegerValue == null) { if (replacement == null) { UIntegerValue = new AnalogItemState(this); } else { UIntegerValue = (AnalogItemState)replacement; } } instance = UIntegerValue; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private AnalogItemState m_sByteValue; private AnalogItemState m_byteValue; private AnalogItemState m_int16Value; private AnalogItemState m_uInt16Value; private AnalogItemState m_int32Value; private AnalogItemState m_uInt32Value; private AnalogItemState m_int64Value; private AnalogItemState m_uInt64Value; private AnalogItemState m_floatValue; private AnalogItemState m_doubleValue; private AnalogItemState m_numberValue; private AnalogItemState m_integerValue; private AnalogItemState m_uIntegerValue; #endregion } #endif #endregion #region UserScalarValueObjectState Class #if (!OPCUA_EXCLUDE_UserScalarValueObjectState) /// /// Stores an instance of the UserScalarValueObjectType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCode("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class UserScalarValueObjectState : TestDataObjectState { #region Constructors /// /// Initializes the type with its default attribute values. /// /// public UserScalarValueObjectState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return NodeId.Create(ObjectTypes.UserScalarValueObjectType, Namespaces.TestData, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// /// /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAABgAAABodHRwOi8vdGVzdC5vcmcvVUEvRGF0YS//////BGCAAgEAAAABACEAAABVc2VyU2NhbGFy" + "VmFsdWVPYmplY3RUeXBlSW5zdGFuY2UBAcEmAQHBJsEmAAABAAAAACQAAQHFJhkAAAA1YIkKAgAAAAEA" + "EAAAAFNpbXVsYXRpb25BY3RpdmUBAcImAwAAAABHAAAASWYgdHJ1ZSB0aGUgc2VydmVyIHdpbGwgcHJv" + "ZHVjZSBuZXcgdmFsdWVzIGZvciBlYWNoIG1vbml0b3JlZCB2YXJpYWJsZS4ALgBEwiYAAAAB/////wEB" + "/////wAAAAAEYYIKBAAAAAEADgAAAEdlbmVyYXRlVmFsdWVzAQHDJgAvAQGpJMMmAAABAf////8BAAAA" + "F2CpCgIAAAAAAA4AAABJbnB1dEFyZ3VtZW50cwEBxCYALgBExCYAAJYBAAAAAQAqAQFGAAAACgAAAEl0" + "ZXJhdGlvbnMAB/////8AAAAAAwAAAAAlAAAAVGhlIG51bWJlciBvZiBuZXcgdmFsdWVzIHRvIGdlbmVy" + "YXRlLgEAKAEBAAAAAQAAAAAAAAABAf////8AAAAABGCACgEAAAABAA0AAABDeWNsZUNvbXBsZXRlAQHF" + "JgAvAQBBC8UmAAABAAAAACQBAQHBJhcAAAAVYIkKAgAAAAAABwAAAEV2ZW50SWQBAcYmAC4ARMYmAAAA" + "D/////8BAf////8AAAAAFWCJCgIAAAAAAAkAAABFdmVudFR5cGUBAccmAC4ARMcmAAAAEf////8BAf//" + "//8AAAAAFWCJCgIAAAAAAAoAAABTb3VyY2VOb2RlAQHIJgAuAETIJgAAABH/////AQH/////AAAAABVg" + "iQoCAAAAAAAKAAAAU291cmNlTmFtZQEBySYALgBEySYAAAAM/////wEB/////wAAAAAVYIkKAgAAAAAA" + "BAAAAFRpbWUBAcomAC4ARMomAAABACYB/////wEB/////wAAAAAVYIkKAgAAAAAACwAAAFJlY2VpdmVU" + "aW1lAQHLJgAuAETLJgAAAQAmAf////8BAf////8AAAAAFWCJCgIAAAAAAAcAAABNZXNzYWdlAQHNJgAu" + "AETNJgAAABX/////AQH/////AAAAABVgiQoCAAAAAAAIAAAAU2V2ZXJpdHkBAc4mAC4ARM4mAAAABf//" + "//8BAf////8AAAAAFWCJCgIAAAAAABAAAABDb25kaXRpb25DbGFzc0lkAQFELQAuAERELQAAABH/////" + "AQH/////AAAAABVgiQoCAAAAAAASAAAAQ29uZGl0aW9uQ2xhc3NOYW1lAQFFLQAuAERFLQAAABX/////" + "AQH/////AAAAABVgiQoCAAAAAAANAAAAQ29uZGl0aW9uTmFtZQEBKi0ALgBEKi0AAAAM/////wEB////" + "/wAAAAAVYIkKAgAAAAAACAAAAEJyYW5jaElkAQHPJgAuAETPJgAAABH/////AQH/////AAAAABVgiQoC" + "AAAAAAAGAAAAUmV0YWluAQHQJgAuAETQJgAAAAH/////AQH/////AAAAABVgiQoCAAAAAAAMAAAARW5h" + "YmxlZFN0YXRlAQHRJgAvAQAjI9EmAAAAFf////8BAQIAAAABACwjAAEB5iYBACwjAAEB7iYBAAAAFWCJ" + "CgIAAAAAAAIAAABJZAEB0iYALgBE0iYAAAAB/////wEB/////wAAAAAVYIkKAgAAAAAABwAAAFF1YWxp" + "dHkBAdcmAC8BACoj1yYAAAAT/////wEB/////wEAAAAVYIkKAgAAAAAADwAAAFNvdXJjZVRpbWVzdGFt" + "cAEB2CYALgBE2CYAAAEAJgH/////AQH/////AAAAABVgiQoCAAAAAAAMAAAATGFzdFNldmVyaXR5AQHb" + "JgAvAQAqI9smAAAABf////8BAf////8BAAAAFWCJCgIAAAAAAA8AAABTb3VyY2VUaW1lc3RhbXABAdwm" + "AC4ARNwmAAABACYB/////wEB/////wAAAAAVYIkKAgAAAAAABwAAAENvbW1lbnQBAd0mAC8BACoj3SYA" + "AAAV/////wEB/////wEAAAAVYIkKAgAAAAAADwAAAFNvdXJjZVRpbWVzdGFtcAEB3iYALgBE3iYAAAEA" + "JgH/////AQH/////AAAAABVgiQoCAAAAAAAMAAAAQ2xpZW50VXNlcklkAQHfJgAuAETfJgAAAAz/////" + "AQH/////AAAAAARhggoEAAAAAAAHAAAARGlzYWJsZQEB4SYALwEARCPhJgAAAQEBAAAAAQD5CwABAPMK" + "AAAAAARhggoEAAAAAAAGAAAARW5hYmxlAQHgJgAvAQBDI+AmAAABAQEAAAABAPkLAAEA8woAAAAABGGC" + "CgQAAAAAAAoAAABBZGRDb21tZW50AQHiJgAvAQBFI+ImAAABAQEAAAABAPkLAAEADQsBAAAAF2CpCgIA" + "AAAAAA4AAABJbnB1dEFyZ3VtZW50cwEB4yYALgBE4yYAAJYCAAAAAQAqAQFGAAAABwAAAEV2ZW50SWQA" + "D/////8AAAAAAwAAAAAoAAAAVGhlIGlkZW50aWZpZXIgZm9yIHRoZSBldmVudCB0byBjb21tZW50LgEA" + "KgEBQgAAAAcAAABDb21tZW50ABX/////AAAAAAMAAAAAJAAAAFRoZSBjb21tZW50IHRvIGFkZCB0byB0" + "aGUgY29uZGl0aW9uLgEAKAEBAAAAAQAAAAAAAAABAf////8AAAAAFWCJCgIAAAAAAAoAAABBY2tlZFN0" + "YXRlAQHmJgAvAQAjI+YmAAAAFf////8BAQEAAAABACwjAQEB0SYBAAAAFWCJCgIAAAAAAAIAAABJZAEB" + "5yYALgBE5yYAAAAB/////wEB/////wAAAAAEYYIKBAAAAAAACwAAAEFja25vd2xlZGdlAQH2JgAvAQCX" + "I/YmAAABAQEAAAABAPkLAAEA8CIBAAAAF2CpCgIAAAAAAA4AAABJbnB1dEFyZ3VtZW50cwEB9yYALgBE" + "9yYAAJYCAAAAAQAqAQFGAAAABwAAAEV2ZW50SWQAD/////8AAAAAAwAAAAAoAAAAVGhlIGlkZW50aWZp" + "ZXIgZm9yIHRoZSBldmVudCB0byBjb21tZW50LgEAKgEBQgAAAAcAAABDb21tZW50ABX/////AAAAAAMA" + "AAAAJAAAAFRoZSBjb21tZW50IHRvIGFkZCB0byB0aGUgY29uZGl0aW9uLgEAKAEBAAAAAQAAAAAAAAAB" + "Af////8AAAAAFWCJCgIAAAABAAwAAABCb29sZWFuVmFsdWUBAfomAC8AP/omAAABAaom/////wEB////" + "/wAAAAAVYIkKAgAAAAEACgAAAFNCeXRlVmFsdWUBAfsmAC8AP/smAAABAasm/////wEB/////wAAAAAV" + "YIkKAgAAAAEACQAAAEJ5dGVWYWx1ZQEB/CYALwA//CYAAAEBrCb/////AQH/////AAAAABVgiQoCAAAA" + "AQAKAAAASW50MTZWYWx1ZQEB/SYALwA//SYAAAEBrSb/////AQH/////AAAAABVgiQoCAAAAAQALAAAA" + "VUludDE2VmFsdWUBAf4mAC8AP/4mAAABAa4m/////wEB/////wAAAAAVYIkKAgAAAAEACgAAAEludDMy" + "VmFsdWUBAf8mAC8AP/8mAAABAa8m/////wEB/////wAAAAAVYIkKAgAAAAEACwAAAFVJbnQzMlZhbHVl" + "AQEAJwAvAD8AJwAAAQGwJv////8BAf////8AAAAAFWCJCgIAAAABAAoAAABJbnQ2NFZhbHVlAQEBJwAv" + "AD8BJwAAAQGxJv////8BAf////8AAAAAFWCJCgIAAAABAAsAAABVSW50NjRWYWx1ZQEBAicALwA/AicA" + "AAEBsib/////AQH/////AAAAABVgiQoCAAAAAQAKAAAARmxvYXRWYWx1ZQEBAycALwA/AycAAAEBsyb/" + "////AQH/////AAAAABVgiQoCAAAAAQALAAAARG91YmxlVmFsdWUBAQQnAC8APwQnAAABAbQm/////wEB" + "/////wAAAAAVYIkKAgAAAAEACwAAAFN0cmluZ1ZhbHVlAQEFJwAvAD8FJwAAAQG1Jv////8BAf////8A" + "AAAAFWCJCgIAAAABAA0AAABEYXRlVGltZVZhbHVlAQEGJwAvAD8GJwAAAQG2Jv////8BAf////8AAAAA" + "FWCJCgIAAAABAAkAAABHdWlkVmFsdWUBAQcnAC8APwcnAAABAbcm/////wEB/////wAAAAAVYIkKAgAA" + "AAEADwAAAEJ5dGVTdHJpbmdWYWx1ZQEBCCcALwA/CCcAAAEBuCb/////AQH/////AAAAABVgiQoCAAAA" + "AQAPAAAAWG1sRWxlbWVudFZhbHVlAQEJJwAvAD8JJwAAAQG5Jv////8BAf////8AAAAAFWCJCgIAAAAB" + "AAsAAABOb2RlSWRWYWx1ZQEBCicALwA/CicAAAEBuib/////AQH/////AAAAABVgiQoCAAAAAQATAAAA" + "RXhwYW5kZWROb2RlSWRWYWx1ZQEBCycALwA/CycAAAEBuyb/////AQH/////AAAAABVgiQoCAAAAAQAS" + "AAAAUXVhbGlmaWVkTmFtZVZhbHVlAQEMJwAvAD8MJwAAAQG8Jv////8BAf////8AAAAAFWCJCgIAAAAB" + "ABIAAABMb2NhbGl6ZWRUZXh0VmFsdWUBAQ0nAC8APw0nAAABAb0m/////wEB/////wAAAAAVYIkKAgAA" + "AAEADwAAAFN0YXR1c0NvZGVWYWx1ZQEBDicALwA/DicAAAEBvib/////AQH/////AAAAABVgiQoCAAAA" + "AQAMAAAAVmFyaWFudFZhbHVlAQEPJwAvAD8PJwAAAQG/Jv////8BAf////8AAAAA"; #endregion #endif #endregion #region Public Properties /// public BaseDataVariableState BooleanValue { get => m_booleanValue; set { if (!ReferenceEquals(m_booleanValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_booleanValue = value; } } /// public BaseDataVariableState SByteValue { get => m_sByteValue; set { if (!ReferenceEquals(m_sByteValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_sByteValue = value; } } /// public BaseDataVariableState ByteValue { get => m_byteValue; set { if (!ReferenceEquals(m_byteValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_byteValue = value; } } /// public BaseDataVariableState Int16Value { get => m_int16Value; set { if (!ReferenceEquals(m_int16Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_int16Value = value; } } /// public BaseDataVariableState UInt16Value { get => m_uInt16Value; set { if (!ReferenceEquals(m_uInt16Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_uInt16Value = value; } } /// public BaseDataVariableState Int32Value { get => m_int32Value; set { if (!ReferenceEquals(m_int32Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_int32Value = value; } } /// public BaseDataVariableState UInt32Value { get => m_uInt32Value; set { if (!ReferenceEquals(m_uInt32Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_uInt32Value = value; } } /// public BaseDataVariableState Int64Value { get => m_int64Value; set { if (!ReferenceEquals(m_int64Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_int64Value = value; } } /// public BaseDataVariableState UInt64Value { get => m_uInt64Value; set { if (!ReferenceEquals(m_uInt64Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_uInt64Value = value; } } /// public BaseDataVariableState FloatValue { get => m_floatValue; set { if (!ReferenceEquals(m_floatValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_floatValue = value; } } /// public BaseDataVariableState DoubleValue { get => m_doubleValue; set { if (!ReferenceEquals(m_doubleValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_doubleValue = value; } } /// public BaseDataVariableState StringValue { get => m_stringValue; set { if (!ReferenceEquals(m_stringValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_stringValue = value; } } /// public BaseDataVariableState DateTimeValue { get => m_dateTimeValue; set { if (!ReferenceEquals(m_dateTimeValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_dateTimeValue = value; } } /// public BaseDataVariableState GuidValue { get => m_guidValue; set { if (!ReferenceEquals(m_guidValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_guidValue = value; } } /// public BaseDataVariableState ByteStringValue { get => m_byteStringValue; set { if (!ReferenceEquals(m_byteStringValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_byteStringValue = value; } } /// public BaseDataVariableState XmlElementValue { get => m_xmlElementValue; set { if (!ReferenceEquals(m_xmlElementValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_xmlElementValue = value; } } /// public BaseDataVariableState NodeIdValue { get => m_nodeIdValue; set { if (!ReferenceEquals(m_nodeIdValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_nodeIdValue = value; } } /// public BaseDataVariableState ExpandedNodeIdValue { get => m_expandedNodeIdValue; set { if (!ReferenceEquals(m_expandedNodeIdValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_expandedNodeIdValue = value; } } /// public BaseDataVariableState QualifiedNameValue { get => m_qualifiedNameValue; set { if (!ReferenceEquals(m_qualifiedNameValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_qualifiedNameValue = value; } } /// public BaseDataVariableState LocalizedTextValue { get => m_localizedTextValue; set { if (!ReferenceEquals(m_localizedTextValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_localizedTextValue = value; } } /// public BaseDataVariableState StatusCodeValue { get => m_statusCodeValue; set { if (!ReferenceEquals(m_statusCodeValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_statusCodeValue = value; } } /// public BaseDataVariableState VariantValue { get => m_variantValue; set { if (!ReferenceEquals(m_variantValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_variantValue = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_booleanValue != null) { children.Add(m_booleanValue); } if (m_sByteValue != null) { children.Add(m_sByteValue); } if (m_byteValue != null) { children.Add(m_byteValue); } if (m_int16Value != null) { children.Add(m_int16Value); } if (m_uInt16Value != null) { children.Add(m_uInt16Value); } if (m_int32Value != null) { children.Add(m_int32Value); } if (m_uInt32Value != null) { children.Add(m_uInt32Value); } if (m_int64Value != null) { children.Add(m_int64Value); } if (m_uInt64Value != null) { children.Add(m_uInt64Value); } if (m_floatValue != null) { children.Add(m_floatValue); } if (m_doubleValue != null) { children.Add(m_doubleValue); } if (m_stringValue != null) { children.Add(m_stringValue); } if (m_dateTimeValue != null) { children.Add(m_dateTimeValue); } if (m_guidValue != null) { children.Add(m_guidValue); } if (m_byteStringValue != null) { children.Add(m_byteStringValue); } if (m_xmlElementValue != null) { children.Add(m_xmlElementValue); } if (m_nodeIdValue != null) { children.Add(m_nodeIdValue); } if (m_expandedNodeIdValue != null) { children.Add(m_expandedNodeIdValue); } if (m_qualifiedNameValue != null) { children.Add(m_qualifiedNameValue); } if (m_localizedTextValue != null) { children.Add(m_localizedTextValue); } if (m_statusCodeValue != null) { children.Add(m_statusCodeValue); } if (m_variantValue != null) { children.Add(m_variantValue); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// /// /// /// /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case BrowseNames.BooleanValue: { if (createOrReplace && BooleanValue == null) { if (replacement == null) { BooleanValue = new BaseDataVariableState(this); } else { BooleanValue = (BaseDataVariableState)replacement; } } instance = BooleanValue; break; } case BrowseNames.SByteValue: { if (createOrReplace && SByteValue == null) { if (replacement == null) { SByteValue = new BaseDataVariableState(this); } else { SByteValue = (BaseDataVariableState)replacement; } } instance = SByteValue; break; } case BrowseNames.ByteValue: { if (createOrReplace && ByteValue == null) { if (replacement == null) { ByteValue = new BaseDataVariableState(this); } else { ByteValue = (BaseDataVariableState)replacement; } } instance = ByteValue; break; } case BrowseNames.Int16Value: { if (createOrReplace && Int16Value == null) { if (replacement == null) { Int16Value = new BaseDataVariableState(this); } else { Int16Value = (BaseDataVariableState)replacement; } } instance = Int16Value; break; } case BrowseNames.UInt16Value: { if (createOrReplace && UInt16Value == null) { if (replacement == null) { UInt16Value = new BaseDataVariableState(this); } else { UInt16Value = (BaseDataVariableState)replacement; } } instance = UInt16Value; break; } case BrowseNames.Int32Value: { if (createOrReplace && Int32Value == null) { if (replacement == null) { Int32Value = new BaseDataVariableState(this); } else { Int32Value = (BaseDataVariableState)replacement; } } instance = Int32Value; break; } case BrowseNames.UInt32Value: { if (createOrReplace && UInt32Value == null) { if (replacement == null) { UInt32Value = new BaseDataVariableState(this); } else { UInt32Value = (BaseDataVariableState)replacement; } } instance = UInt32Value; break; } case BrowseNames.Int64Value: { if (createOrReplace && Int64Value == null) { if (replacement == null) { Int64Value = new BaseDataVariableState(this); } else { Int64Value = (BaseDataVariableState)replacement; } } instance = Int64Value; break; } case BrowseNames.UInt64Value: { if (createOrReplace && UInt64Value == null) { if (replacement == null) { UInt64Value = new BaseDataVariableState(this); } else { UInt64Value = (BaseDataVariableState)replacement; } } instance = UInt64Value; break; } case BrowseNames.FloatValue: { if (createOrReplace && FloatValue == null) { if (replacement == null) { FloatValue = new BaseDataVariableState(this); } else { FloatValue = (BaseDataVariableState)replacement; } } instance = FloatValue; break; } case BrowseNames.DoubleValue: { if (createOrReplace && DoubleValue == null) { if (replacement == null) { DoubleValue = new BaseDataVariableState(this); } else { DoubleValue = (BaseDataVariableState)replacement; } } instance = DoubleValue; break; } case BrowseNames.StringValue: { if (createOrReplace && StringValue == null) { if (replacement == null) { StringValue = new BaseDataVariableState(this); } else { StringValue = (BaseDataVariableState)replacement; } } instance = StringValue; break; } case BrowseNames.DateTimeValue: { if (createOrReplace && DateTimeValue == null) { if (replacement == null) { DateTimeValue = new BaseDataVariableState(this); } else { DateTimeValue = (BaseDataVariableState)replacement; } } instance = DateTimeValue; break; } case BrowseNames.GuidValue: { if (createOrReplace && GuidValue == null) { if (replacement == null) { GuidValue = new BaseDataVariableState(this); } else { GuidValue = (BaseDataVariableState)replacement; } } instance = GuidValue; break; } case BrowseNames.ByteStringValue: { if (createOrReplace && ByteStringValue == null) { if (replacement == null) { ByteStringValue = new BaseDataVariableState(this); } else { ByteStringValue = (BaseDataVariableState)replacement; } } instance = ByteStringValue; break; } case BrowseNames.XmlElementValue: { if (createOrReplace && XmlElementValue == null) { if (replacement == null) { XmlElementValue = new BaseDataVariableState(this); } else { XmlElementValue = (BaseDataVariableState)replacement; } } instance = XmlElementValue; break; } case BrowseNames.NodeIdValue: { if (createOrReplace && NodeIdValue == null) { if (replacement == null) { NodeIdValue = new BaseDataVariableState(this); } else { NodeIdValue = (BaseDataVariableState)replacement; } } instance = NodeIdValue; break; } case BrowseNames.ExpandedNodeIdValue: { if (createOrReplace && ExpandedNodeIdValue == null) { if (replacement == null) { ExpandedNodeIdValue = new BaseDataVariableState(this); } else { ExpandedNodeIdValue = (BaseDataVariableState)replacement; } } instance = ExpandedNodeIdValue; break; } case BrowseNames.QualifiedNameValue: { if (createOrReplace && QualifiedNameValue == null) { if (replacement == null) { QualifiedNameValue = new BaseDataVariableState(this); } else { QualifiedNameValue = (BaseDataVariableState)replacement; } } instance = QualifiedNameValue; break; } case BrowseNames.LocalizedTextValue: { if (createOrReplace && LocalizedTextValue == null) { if (replacement == null) { LocalizedTextValue = new BaseDataVariableState(this); } else { LocalizedTextValue = (BaseDataVariableState)replacement; } } instance = LocalizedTextValue; break; } case BrowseNames.StatusCodeValue: { if (createOrReplace && StatusCodeValue == null) { if (replacement == null) { StatusCodeValue = new BaseDataVariableState(this); } else { StatusCodeValue = (BaseDataVariableState)replacement; } } instance = StatusCodeValue; break; } case BrowseNames.VariantValue: { if (createOrReplace && VariantValue == null) { if (replacement == null) { VariantValue = new BaseDataVariableState(this); } else { VariantValue = (BaseDataVariableState)replacement; } } instance = VariantValue; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private BaseDataVariableState m_booleanValue; private BaseDataVariableState m_sByteValue; private BaseDataVariableState m_byteValue; private BaseDataVariableState m_int16Value; private BaseDataVariableState m_uInt16Value; private BaseDataVariableState m_int32Value; private BaseDataVariableState m_uInt32Value; private BaseDataVariableState m_int64Value; private BaseDataVariableState m_uInt64Value; private BaseDataVariableState m_floatValue; private BaseDataVariableState m_doubleValue; private BaseDataVariableState m_stringValue; private BaseDataVariableState m_dateTimeValue; private BaseDataVariableState m_guidValue; private BaseDataVariableState m_byteStringValue; private BaseDataVariableState m_xmlElementValue; private BaseDataVariableState m_nodeIdValue; private BaseDataVariableState m_expandedNodeIdValue; private BaseDataVariableState m_qualifiedNameValue; private BaseDataVariableState m_localizedTextValue; private BaseDataVariableState m_statusCodeValue; private BaseDataVariableState m_variantValue; #endregion } #endif #endregion #region UserScalarValue1MethodState Class #if (!OPCUA_EXCLUDE_UserScalarValue1MethodState) /// /// Stores an instance of the UserScalarValue1MethodType Method. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class UserScalarValue1MethodState : MethodState { #region Constructors /// /// Initializes the type with its default attribute values. /// public UserScalarValue1MethodState(NodeState parent) : base(parent) { } /// /// Constructs an instance of a node. /// /// The parent. /// The new node. public new static NodeState Construct(NodeState parent) { return new UserScalarValue1MethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAABgAAABodHRwOi8vdGVzdC5vcmcvVUEvRGF0YS//////BGGCCgQAAAABABoAAABVc2VyU2NhbGFy" + "VmFsdWUxTWV0aG9kVHlwZQEBECcALwEBECcQJwAAAQH/////AgAAABdgqQoCAAAAAAAOAAAASW5wdXRB" + "cmd1bWVudHMBAREnAC4ARBEnAACWDAAAAAEAKgEBGgAAAAkAAABCb29sZWFuSW4BAaom/////wAAAAAA" + "AQAqAQEYAAAABwAAAFNCeXRlSW4BAasm/////wAAAAAAAQAqAQEXAAAABgAAAEJ5dGVJbgEBrCb/////" + "AAAAAAABACoBARgAAAAHAAAASW50MTZJbgEBrSb/////AAAAAAABACoBARkAAAAIAAAAVUludDE2SW4B" + "Aa4m/////wAAAAAAAQAqAQEYAAAABwAAAEludDMySW4BAa8m/////wAAAAAAAQAqAQEZAAAACAAAAFVJ" + "bnQzMkluAQGwJv////8AAAAAAAEAKgEBGAAAAAcAAABJbnQ2NEluAQGxJv////8AAAAAAAEAKgEBGQAA" + "AAgAAABVSW50NjRJbgEBsib/////AAAAAAABACoBARgAAAAHAAAARmxvYXRJbgEBsyb/////AAAAAAAB" + "ACoBARkAAAAIAAAARG91YmxlSW4BAbQm/////wAAAAAAAQAqAQEZAAAACAAAAFN0cmluZ0luAQG1Jv//" + "//8AAAAAAAEAKAEBAAAAAQAAAAAAAAABAf////8AAAAAF2CpCgIAAAAAAA8AAABPdXRwdXRBcmd1bWVu" + "dHMBARInAC4ARBInAACWDAAAAAEAKgEBGwAAAAoAAABCb29sZWFuT3V0AQGqJv////8AAAAAAAEAKgEB" + "GQAAAAgAAABTQnl0ZU91dAEBqyb/////AAAAAAABACoBARgAAAAHAAAAQnl0ZU91dAEBrCb/////AAAA" + "AAABACoBARkAAAAIAAAASW50MTZPdXQBAa0m/////wAAAAAAAQAqAQEaAAAACQAAAFVJbnQxNk91dAEB" + "rib/////AAAAAAABACoBARkAAAAIAAAASW50MzJPdXQBAa8m/////wAAAAAAAQAqAQEaAAAACQAAAFVJ" + "bnQzMk91dAEBsCb/////AAAAAAABACoBARkAAAAIAAAASW50NjRPdXQBAbEm/////wAAAAAAAQAqAQEa" + "AAAACQAAAFVJbnQ2NE91dAEBsib/////AAAAAAABACoBARkAAAAIAAAARmxvYXRPdXQBAbMm/////wAA" + "AAAAAQAqAQEaAAAACQAAAERvdWJsZU91dAEBtCb/////AAAAAAABACoBARoAAAAJAAAAU3RyaW5nT3V0" + "AQG1Jv////8AAAAAAAEAKAEBAAAAAQAAAAAAAAABAf////8AAAAA"; #endregion #endif #endregion #region Event Callbacks /// /// Raised when the the method is called. /// public UserScalarValue1MethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// /// Invokes the method, returns the result and output argument. /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult result = null; bool booleanIn = (bool)_inputArguments[0]; sbyte sByteIn = (sbyte)_inputArguments[1]; byte byteIn = (byte)_inputArguments[2]; short int16In = (short)_inputArguments[3]; ushort uInt16In = (ushort)_inputArguments[4]; int int32In = (int)_inputArguments[5]; uint uInt32In = (uint)_inputArguments[6]; long int64In = (long)_inputArguments[7]; ulong uInt64In = (ulong)_inputArguments[8]; float floatIn = (float)_inputArguments[9]; double doubleIn = (double)_inputArguments[10]; string stringIn = (string)_inputArguments[11]; bool booleanOut = (bool)_outputArguments[0]; sbyte sByteOut = (sbyte)_outputArguments[1]; byte byteOut = (byte)_outputArguments[2]; short int16Out = (short)_outputArguments[3]; ushort uInt16Out = (ushort)_outputArguments[4]; int int32Out = (int)_outputArguments[5]; uint uInt32Out = (uint)_outputArguments[6]; long int64Out = (long)_outputArguments[7]; ulong uInt64Out = (ulong)_outputArguments[8]; float floatOut = (float)_outputArguments[9]; double doubleOut = (double)_outputArguments[10]; string stringOut = (string)_outputArguments[11]; if (OnCall != null) { result = OnCall( _context, this, _objectId, booleanIn, sByteIn, byteIn, int16In, uInt16In, int32In, uInt32In, int64In, uInt64In, floatIn, doubleIn, stringIn, ref booleanOut, ref sByteOut, ref byteOut, ref int16Out, ref uInt16Out, ref int32Out, ref uInt32Out, ref int64Out, ref uInt64Out, ref floatOut, ref doubleOut, ref stringOut); } _outputArguments[0] = booleanOut; _outputArguments[1] = sByteOut; _outputArguments[2] = byteOut; _outputArguments[3] = int16Out; _outputArguments[4] = uInt16Out; _outputArguments[5] = int32Out; _outputArguments[6] = uInt32Out; _outputArguments[7] = int64Out; _outputArguments[8] = uInt64Out; _outputArguments[9] = floatOut; _outputArguments[10] = doubleOut; _outputArguments[11] = stringOut; return result; } #endregion #region Private Fields #endregion } /// /// Used to receive notifications when the method is called. /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// public delegate ServiceResult UserScalarValue1MethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, bool booleanIn, sbyte sByteIn, byte byteIn, short int16In, ushort uInt16In, int int32In, uint uInt32In, long int64In, ulong uInt64In, float floatIn, double doubleIn, string stringIn, ref bool booleanOut, ref sbyte sByteOut, ref byte byteOut, ref short int16Out, ref ushort uInt16Out, ref int int32Out, ref uint uInt32Out, ref long int64Out, ref ulong uInt64Out, ref float floatOut, ref double doubleOut, ref string stringOut); #endif #endregion #region UserScalarValue2MethodState Class #if (!OPCUA_EXCLUDE_UserScalarValue2MethodState) /// /// Stores an instance of the UserScalarValue2MethodType Method. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class UserScalarValue2MethodState : MethodState { #region Constructors /// /// Initializes the type with its default attribute values. /// public UserScalarValue2MethodState(NodeState parent) : base(parent) { } /// /// Constructs an instance of a node. /// /// The parent. /// The new node. public new static NodeState Construct(NodeState parent) { return new UserScalarValue2MethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAABgAAABodHRwOi8vdGVzdC5vcmcvVUEvRGF0YS//////BGGCCgQAAAABABoAAABVc2VyU2NhbGFy" + "VmFsdWUyTWV0aG9kVHlwZQEBEycALwEBEycTJwAAAQH/////AgAAABdgqQoCAAAAAAAOAAAASW5wdXRB" + "cmd1bWVudHMBARQnAC4ARBQnAACWCgAAAAEAKgEBGwAAAAoAAABEYXRlVGltZUluAQG2Jv////8AAAAA" + "AAEAKgEBFwAAAAYAAABHdWlkSW4BAbcm/////wAAAAAAAQAqAQEdAAAADAAAAEJ5dGVTdHJpbmdJbgEB" + "uCb/////AAAAAAABACoBAR0AAAAMAAAAWG1sRWxlbWVudEluAQG5Jv////8AAAAAAAEAKgEBGQAAAAgA" + "AABOb2RlSWRJbgEBuib/////AAAAAAABACoBASEAAAAQAAAARXhwYW5kZWROb2RlSWRJbgEBuyb/////" + "AAAAAAABACoBASAAAAAPAAAAUXVhbGlmaWVkTmFtZUluAQG8Jv////8AAAAAAAEAKgEBIAAAAA8AAABM" + "b2NhbGl6ZWRUZXh0SW4BAb0m/////wAAAAAAAQAqAQEdAAAADAAAAFN0YXR1c0NvZGVJbgEBvib/////" + "AAAAAAABACoBARoAAAAJAAAAVmFyaWFudEluAQG/Jv////8AAAAAAAEAKAEBAAAAAQAAAAAAAAABAf//" + "//8AAAAAF2CpCgIAAAAAAA8AAABPdXRwdXRBcmd1bWVudHMBARUnAC4ARBUnAACWCgAAAAEAKgEBHAAA" + "AAsAAABEYXRlVGltZU91dAEBtib/////AAAAAAABACoBARgAAAAHAAAAR3VpZE91dAEBtyb/////AAAA" + "AAABACoBAR4AAAANAAAAQnl0ZVN0cmluZ091dAEBuCb/////AAAAAAABACoBAR4AAAANAAAAWG1sRWxl" + "bWVudE91dAEBuSb/////AAAAAAABACoBARoAAAAJAAAATm9kZUlkT3V0AQG6Jv////8AAAAAAAEAKgEB" + "IgAAABEAAABFeHBhbmRlZE5vZGVJZE91dAEBuyb/////AAAAAAABACoBASEAAAAQAAAAUXVhbGlmaWVk" + "TmFtZU91dAEBvCb/////AAAAAAABACoBASEAAAAQAAAATG9jYWxpemVkVGV4dE91dAEBvSb/////AAAA" + "AAABACoBAR4AAAANAAAAU3RhdHVzQ29kZU91dAEBvib/////AAAAAAABACoBARsAAAAKAAAAVmFyaWFu" + "dE91dAEBvyb/////AAAAAAABACgBAQAAAAEAAAAAAAAAAQH/////AAAAAA=="; #endregion #endif #endregion #region Event Callbacks /// /// Raised when the the method is called. /// public UserScalarValue2MethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// /// Invokes the method, returns the result and output argument. /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult result = null; DateTime dateTimeIn = (DateTime)_inputArguments[0]; Uuid guidIn = (Uuid)_inputArguments[1]; byte[] byteStringIn = (byte[])_inputArguments[2]; XmlElement xmlElementIn = (XmlElement)_inputArguments[3]; NodeId nodeIdIn = (NodeId)_inputArguments[4]; ExpandedNodeId expandedNodeIdIn = (ExpandedNodeId)_inputArguments[5]; QualifiedName qualifiedNameIn = (QualifiedName)_inputArguments[6]; LocalizedText localizedTextIn = (LocalizedText)_inputArguments[7]; StatusCode statusCodeIn = (StatusCode)_inputArguments[8]; object variantIn = (object)_inputArguments[9]; DateTime dateTimeOut = (DateTime)_outputArguments[0]; Uuid guidOut = (Uuid)_outputArguments[1]; byte[] byteStringOut = (byte[])_outputArguments[2]; XmlElement xmlElementOut = (XmlElement)_outputArguments[3]; NodeId nodeIdOut = (NodeId)_outputArguments[4]; ExpandedNodeId expandedNodeIdOut = (ExpandedNodeId)_outputArguments[5]; QualifiedName qualifiedNameOut = (QualifiedName)_outputArguments[6]; LocalizedText localizedTextOut = (LocalizedText)_outputArguments[7]; StatusCode statusCodeOut = (StatusCode)_outputArguments[8]; object variantOut = (object)_outputArguments[9]; if (OnCall != null) { result = OnCall( _context, this, _objectId, dateTimeIn, guidIn, byteStringIn, xmlElementIn, nodeIdIn, expandedNodeIdIn, qualifiedNameIn, localizedTextIn, statusCodeIn, variantIn, ref dateTimeOut, ref guidOut, ref byteStringOut, ref xmlElementOut, ref nodeIdOut, ref expandedNodeIdOut, ref qualifiedNameOut, ref localizedTextOut, ref statusCodeOut, ref variantOut); } _outputArguments[0] = dateTimeOut; _outputArguments[1] = guidOut; _outputArguments[2] = byteStringOut; _outputArguments[3] = xmlElementOut; _outputArguments[4] = nodeIdOut; _outputArguments[5] = expandedNodeIdOut; _outputArguments[6] = qualifiedNameOut; _outputArguments[7] = localizedTextOut; _outputArguments[8] = statusCodeOut; _outputArguments[9] = variantOut; return result; } #endregion #region Private Fields #endregion } /// /// Used to receive notifications when the method is called. /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// public delegate ServiceResult UserScalarValue2MethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, DateTime dateTimeIn, Uuid guidIn, byte[] byteStringIn, XmlElement xmlElementIn, NodeId nodeIdIn, ExpandedNodeId expandedNodeIdIn, QualifiedName qualifiedNameIn, LocalizedText localizedTextIn, StatusCode statusCodeIn, object variantIn, ref DateTime dateTimeOut, ref Uuid guidOut, ref byte[] byteStringOut, ref XmlElement xmlElementOut, ref NodeId nodeIdOut, ref ExpandedNodeId expandedNodeIdOut, ref QualifiedName qualifiedNameOut, ref LocalizedText localizedTextOut, ref StatusCode statusCodeOut, ref object variantOut); #endif #endregion #region UserArrayValueObjectState Class #if (!OPCUA_EXCLUDE_UserArrayValueObjectState) /// /// Stores an instance of the UserArrayValueObjectType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCode("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class UserArrayValueObjectState : TestDataObjectState { #region Constructors /// /// Initializes the type with its default attribute values. /// /// public UserArrayValueObjectState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return NodeId.Create(ObjectTypes.UserArrayValueObjectType, Namespaces.TestData, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// /// /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAABgAAABodHRwOi8vdGVzdC5vcmcvVUEvRGF0YS//////BGCAAgEAAAABACAAAABVc2VyQXJyYXlW" + "YWx1ZU9iamVjdFR5cGVJbnN0YW5jZQEBFycBARcnFycAAAEAAAAAJAABARsnGQAAADVgiQoCAAAAAQAQ" + "AAAAU2ltdWxhdGlvbkFjdGl2ZQEBGCcDAAAAAEcAAABJZiB0cnVlIHRoZSBzZXJ2ZXIgd2lsbCBwcm9k" + "dWNlIG5ldyB2YWx1ZXMgZm9yIGVhY2ggbW9uaXRvcmVkIHZhcmlhYmxlLgAuAEQYJwAAAAH/////AQH/" + "////AAAAAARhggoEAAAAAQAOAAAAR2VuZXJhdGVWYWx1ZXMBARknAC8BAakkGScAAAEB/////wEAAAAX" + "YKkKAgAAAAAADgAAAElucHV0QXJndW1lbnRzAQEaJwAuAEQaJwAAlgEAAAABACoBAUYAAAAKAAAASXRl" + "cmF0aW9ucwAH/////wAAAAADAAAAACUAAABUaGUgbnVtYmVyIG9mIG5ldyB2YWx1ZXMgdG8gZ2VuZXJh" + "dGUuAQAoAQEAAAABAAAAAAAAAAEB/////wAAAAAEYIAKAQAAAAEADQAAAEN5Y2xlQ29tcGxldGUBARsn" + "AC8BAEELGycAAAEAAAAAJAEBARcnFwAAABVgiQoCAAAAAAAHAAAARXZlbnRJZAEBHCcALgBEHCcAAAAP" + "/////wEB/////wAAAAAVYIkKAgAAAAAACQAAAEV2ZW50VHlwZQEBHScALgBEHScAAAAR/////wEB////" + "/wAAAAAVYIkKAgAAAAAACgAAAFNvdXJjZU5vZGUBAR4nAC4ARB4nAAAAEf////8BAf////8AAAAAFWCJ" + "CgIAAAAAAAoAAABTb3VyY2VOYW1lAQEfJwAuAEQfJwAAAAz/////AQH/////AAAAABVgiQoCAAAAAAAE" + "AAAAVGltZQEBICcALgBEICcAAAEAJgH/////AQH/////AAAAABVgiQoCAAAAAAALAAAAUmVjZWl2ZVRp" + "bWUBASEnAC4ARCEnAAABACYB/////wEB/////wAAAAAVYIkKAgAAAAAABwAAAE1lc3NhZ2UBASMnAC4A" + "RCMnAAAAFf////8BAf////8AAAAAFWCJCgIAAAAAAAgAAABTZXZlcml0eQEBJCcALgBEJCcAAAAF////" + "/wEB/////wAAAAAVYIkKAgAAAAAAEAAAAENvbmRpdGlvbkNsYXNzSWQBAUYtAC4AREYtAAAAEf////8B" + "Af////8AAAAAFWCJCgIAAAAAABIAAABDb25kaXRpb25DbGFzc05hbWUBAUctAC4AREctAAAAFf////8B" + "Af////8AAAAAFWCJCgIAAAAAAA0AAABDb25kaXRpb25OYW1lAQErLQAuAEQrLQAAAAz/////AQH/////" + "AAAAABVgiQoCAAAAAAAIAAAAQnJhbmNoSWQBASUnAC4ARCUnAAAAEf////8BAf////8AAAAAFWCJCgIA" + "AAAAAAYAAABSZXRhaW4BASYnAC4ARCYnAAAAAf////8BAf////8AAAAAFWCJCgIAAAAAAAwAAABFbmFi" + "bGVkU3RhdGUBAScnAC8BACMjJycAAAAV/////wEBAgAAAAEALCMAAQE8JwEALCMAAQFEJwEAAAAVYIkK" + "AgAAAAAAAgAAAElkAQEoJwAuAEQoJwAAAAH/////AQH/////AAAAABVgiQoCAAAAAAAHAAAAUXVhbGl0" + "eQEBLScALwEAKiMtJwAAABP/////AQH/////AQAAABVgiQoCAAAAAAAPAAAAU291cmNlVGltZXN0YW1w" + "AQEuJwAuAEQuJwAAAQAmAf////8BAf////8AAAAAFWCJCgIAAAAAAAwAAABMYXN0U2V2ZXJpdHkBATEn" + "AC8BACojMScAAAAF/////wEB/////wEAAAAVYIkKAgAAAAAADwAAAFNvdXJjZVRpbWVzdGFtcAEBMicA" + "LgBEMicAAAEAJgH/////AQH/////AAAAABVgiQoCAAAAAAAHAAAAQ29tbWVudAEBMycALwEAKiMzJwAA" + "ABX/////AQH/////AQAAABVgiQoCAAAAAAAPAAAAU291cmNlVGltZXN0YW1wAQE0JwAuAEQ0JwAAAQAm" + "Af////8BAf////8AAAAAFWCJCgIAAAAAAAwAAABDbGllbnRVc2VySWQBATUnAC4ARDUnAAAADP////8B" + "Af////8AAAAABGGCCgQAAAAAAAcAAABEaXNhYmxlAQE3JwAvAQBEIzcnAAABAQEAAAABAPkLAAEA8woA" + "AAAABGGCCgQAAAAAAAYAAABFbmFibGUBATYnAC8BAEMjNicAAAEBAQAAAAEA+QsAAQDzCgAAAAAEYYIK" + "BAAAAAAACgAAAEFkZENvbW1lbnQBATgnAC8BAEUjOCcAAAEBAQAAAAEA+QsAAQANCwEAAAAXYKkKAgAA" + "AAAADgAAAElucHV0QXJndW1lbnRzAQE5JwAuAEQ5JwAAlgIAAAABACoBAUYAAAAHAAAARXZlbnRJZAAP" + "/////wAAAAADAAAAACgAAABUaGUgaWRlbnRpZmllciBmb3IgdGhlIGV2ZW50IHRvIGNvbW1lbnQuAQAq" + "AQFCAAAABwAAAENvbW1lbnQAFf////8AAAAAAwAAAAAkAAAAVGhlIGNvbW1lbnQgdG8gYWRkIHRvIHRo" + "ZSBjb25kaXRpb24uAQAoAQEAAAABAAAAAAAAAAEB/////wAAAAAVYIkKAgAAAAAACgAAAEFja2VkU3Rh" + "dGUBATwnAC8BACMjPCcAAAAV/////wEBAQAAAAEALCMBAQEnJwEAAAAVYIkKAgAAAAAAAgAAAElkAQE9" + "JwAuAEQ9JwAAAAH/////AQH/////AAAAAARhggoEAAAAAAALAAAAQWNrbm93bGVkZ2UBAUwnAC8BAJcj" + "TCcAAAEBAQAAAAEA+QsAAQDwIgEAAAAXYKkKAgAAAAAADgAAAElucHV0QXJndW1lbnRzAQFNJwAuAERN" + "JwAAlgIAAAABACoBAUYAAAAHAAAARXZlbnRJZAAP/////wAAAAADAAAAACgAAABUaGUgaWRlbnRpZmll" + "ciBmb3IgdGhlIGV2ZW50IHRvIGNvbW1lbnQuAQAqAQFCAAAABwAAAENvbW1lbnQAFf////8AAAAAAwAA" + "AAAkAAAAVGhlIGNvbW1lbnQgdG8gYWRkIHRvIHRoZSBjb25kaXRpb24uAQAoAQEAAAABAAAAAAAAAAEB" + "/////wAAAAAXYIkKAgAAAAEADAAAAEJvb2xlYW5WYWx1ZQEBUCcALwA/UCcAAAEBqiYBAAAAAQAAAAAA" + "AAABAf////8AAAAAF2CJCgIAAAABAAoAAABTQnl0ZVZhbHVlAQFRJwAvAD9RJwAAAQGrJgEAAAABAAAA" + "AAAAAAEB/////wAAAAAXYIkKAgAAAAEACQAAAEJ5dGVWYWx1ZQEBUicALwA/UicAAAEBrCYBAAAAAQAA" + "AAAAAAABAf////8AAAAAF2CJCgIAAAABAAoAAABJbnQxNlZhbHVlAQFTJwAvAD9TJwAAAQGtJgEAAAAB" + "AAAAAAAAAAEB/////wAAAAAXYIkKAgAAAAEACwAAAFVJbnQxNlZhbHVlAQFUJwAvAD9UJwAAAQGuJgEA" + "AAABAAAAAAAAAAEB/////wAAAAAXYIkKAgAAAAEACgAAAEludDMyVmFsdWUBAVUnAC8AP1UnAAABAa8m" + "AQAAAAEAAAAAAAAAAQH/////AAAAABdgiQoCAAAAAQALAAAAVUludDMyVmFsdWUBAVYnAC8AP1YnAAAB" + "AbAmAQAAAAEAAAAAAAAAAQH/////AAAAABdgiQoCAAAAAQAKAAAASW50NjRWYWx1ZQEBVycALwA/VycA" + "AAEBsSYBAAAAAQAAAAAAAAABAf////8AAAAAF2CJCgIAAAABAAsAAABVSW50NjRWYWx1ZQEBWCcALwA/" + "WCcAAAEBsiYBAAAAAQAAAAAAAAABAf////8AAAAAF2CJCgIAAAABAAoAAABGbG9hdFZhbHVlAQFZJwAv" + "AD9ZJwAAAQGzJgEAAAABAAAAAAAAAAEB/////wAAAAAXYIkKAgAAAAEACwAAAERvdWJsZVZhbHVlAQFa" + "JwAvAD9aJwAAAQG0JgEAAAABAAAAAAAAAAEB/////wAAAAAXYIkKAgAAAAEACwAAAFN0cmluZ1ZhbHVl" + "AQFbJwAvAD9bJwAAAQG1JgEAAAABAAAAAAAAAAEB/////wAAAAAXYIkKAgAAAAEADQAAAERhdGVUaW1l" + "VmFsdWUBAVwnAC8AP1wnAAABAbYmAQAAAAEAAAAAAAAAAQH/////AAAAABdgiQoCAAAAAQAJAAAAR3Vp" + "ZFZhbHVlAQFdJwAvAD9dJwAAAQG3JgEAAAABAAAAAAAAAAEB/////wAAAAAXYIkKAgAAAAEADwAAAEJ5" + "dGVTdHJpbmdWYWx1ZQEBXicALwA/XicAAAEBuCYBAAAAAQAAAAAAAAABAf////8AAAAAF2CJCgIAAAAB" + "AA8AAABYbWxFbGVtZW50VmFsdWUBAV8nAC8AP18nAAABAbkmAQAAAAEAAAAAAAAAAQH/////AAAAABdg" + "iQoCAAAAAQALAAAATm9kZUlkVmFsdWUBAWAnAC8AP2AnAAABAbomAQAAAAEAAAAAAAAAAQH/////AAAA" + "ABdgiQoCAAAAAQATAAAARXhwYW5kZWROb2RlSWRWYWx1ZQEBYScALwA/YScAAAEBuyYBAAAAAQAAAAAA" + "AAABAf////8AAAAAF2CJCgIAAAABABIAAABRdWFsaWZpZWROYW1lVmFsdWUBAWInAC8AP2InAAABAbwm" + "AQAAAAEAAAAAAAAAAQH/////AAAAABdgiQoCAAAAAQASAAAATG9jYWxpemVkVGV4dFZhbHVlAQFjJwAv" + "AD9jJwAAAQG9JgEAAAABAAAAAAAAAAEB/////wAAAAAXYIkKAgAAAAEADwAAAFN0YXR1c0NvZGVWYWx1" + "ZQEBZCcALwA/ZCcAAAEBviYBAAAAAQAAAAAAAAABAf////8AAAAAF2CJCgIAAAABAAwAAABWYXJpYW50" + "VmFsdWUBAWUnAC8AP2UnAAABAb8mAQAAAAEAAAAAAAAAAQH/////AAAAAA=="; #endregion #endif #endregion #region Public Properties /// public BaseDataVariableState BooleanValue { get => m_booleanValue; set { if (!ReferenceEquals(m_booleanValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_booleanValue = value; } } /// public BaseDataVariableState SByteValue { get => m_sByteValue; set { if (!ReferenceEquals(m_sByteValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_sByteValue = value; } } /// public BaseDataVariableState ByteValue { get => m_byteValue; set { if (!ReferenceEquals(m_byteValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_byteValue = value; } } /// public BaseDataVariableState Int16Value { get => m_int16Value; set { if (!ReferenceEquals(m_int16Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_int16Value = value; } } /// public BaseDataVariableState UInt16Value { get => m_uInt16Value; set { if (!ReferenceEquals(m_uInt16Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_uInt16Value = value; } } /// public BaseDataVariableState Int32Value { get => m_int32Value; set { if (!ReferenceEquals(m_int32Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_int32Value = value; } } /// public BaseDataVariableState UInt32Value { get => m_uInt32Value; set { if (!ReferenceEquals(m_uInt32Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_uInt32Value = value; } } /// public BaseDataVariableState Int64Value { get => m_int64Value; set { if (!ReferenceEquals(m_int64Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_int64Value = value; } } /// public BaseDataVariableState UInt64Value { get => m_uInt64Value; set { if (!ReferenceEquals(m_uInt64Value, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_uInt64Value = value; } } /// public BaseDataVariableState FloatValue { get => m_floatValue; set { if (!ReferenceEquals(m_floatValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_floatValue = value; } } /// public BaseDataVariableState DoubleValue { get => m_doubleValue; set { if (!ReferenceEquals(m_doubleValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_doubleValue = value; } } /// public BaseDataVariableState StringValue { get => m_stringValue; set { if (!ReferenceEquals(m_stringValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_stringValue = value; } } /// public BaseDataVariableState DateTimeValue { get => m_dateTimeValue; set { if (!ReferenceEquals(m_dateTimeValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_dateTimeValue = value; } } /// public BaseDataVariableState GuidValue { get => m_guidValue; set { if (!ReferenceEquals(m_guidValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_guidValue = value; } } /// public BaseDataVariableState ByteStringValue { get => m_byteStringValue; set { if (!ReferenceEquals(m_byteStringValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_byteStringValue = value; } } /// public BaseDataVariableState XmlElementValue { get => m_xmlElementValue; set { if (!ReferenceEquals(m_xmlElementValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_xmlElementValue = value; } } /// public BaseDataVariableState NodeIdValue { get => m_nodeIdValue; set { if (!ReferenceEquals(m_nodeIdValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_nodeIdValue = value; } } /// public BaseDataVariableState ExpandedNodeIdValue { get => m_expandedNodeIdValue; set { if (!ReferenceEquals(m_expandedNodeIdValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_expandedNodeIdValue = value; } } /// public BaseDataVariableState QualifiedNameValue { get => m_qualifiedNameValue; set { if (!ReferenceEquals(m_qualifiedNameValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_qualifiedNameValue = value; } } /// public BaseDataVariableState LocalizedTextValue { get => m_localizedTextValue; set { if (!ReferenceEquals(m_localizedTextValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_localizedTextValue = value; } } /// public BaseDataVariableState StatusCodeValue { get => m_statusCodeValue; set { if (!ReferenceEquals(m_statusCodeValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_statusCodeValue = value; } } /// public BaseDataVariableState VariantValue { get => m_variantValue; set { if (!ReferenceEquals(m_variantValue, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_variantValue = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_booleanValue != null) { children.Add(m_booleanValue); } if (m_sByteValue != null) { children.Add(m_sByteValue); } if (m_byteValue != null) { children.Add(m_byteValue); } if (m_int16Value != null) { children.Add(m_int16Value); } if (m_uInt16Value != null) { children.Add(m_uInt16Value); } if (m_int32Value != null) { children.Add(m_int32Value); } if (m_uInt32Value != null) { children.Add(m_uInt32Value); } if (m_int64Value != null) { children.Add(m_int64Value); } if (m_uInt64Value != null) { children.Add(m_uInt64Value); } if (m_floatValue != null) { children.Add(m_floatValue); } if (m_doubleValue != null) { children.Add(m_doubleValue); } if (m_stringValue != null) { children.Add(m_stringValue); } if (m_dateTimeValue != null) { children.Add(m_dateTimeValue); } if (m_guidValue != null) { children.Add(m_guidValue); } if (m_byteStringValue != null) { children.Add(m_byteStringValue); } if (m_xmlElementValue != null) { children.Add(m_xmlElementValue); } if (m_nodeIdValue != null) { children.Add(m_nodeIdValue); } if (m_expandedNodeIdValue != null) { children.Add(m_expandedNodeIdValue); } if (m_qualifiedNameValue != null) { children.Add(m_qualifiedNameValue); } if (m_localizedTextValue != null) { children.Add(m_localizedTextValue); } if (m_statusCodeValue != null) { children.Add(m_statusCodeValue); } if (m_variantValue != null) { children.Add(m_variantValue); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// /// /// /// /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case BrowseNames.BooleanValue: { if (createOrReplace && BooleanValue == null) { if (replacement == null) { BooleanValue = new BaseDataVariableState(this); } else { BooleanValue = (BaseDataVariableState)replacement; } } instance = BooleanValue; break; } case BrowseNames.SByteValue: { if (createOrReplace && SByteValue == null) { if (replacement == null) { SByteValue = new BaseDataVariableState(this); } else { SByteValue = (BaseDataVariableState)replacement; } } instance = SByteValue; break; } case BrowseNames.ByteValue: { if (createOrReplace && ByteValue == null) { if (replacement == null) { ByteValue = new BaseDataVariableState(this); } else { ByteValue = (BaseDataVariableState)replacement; } } instance = ByteValue; break; } case BrowseNames.Int16Value: { if (createOrReplace && Int16Value == null) { if (replacement == null) { Int16Value = new BaseDataVariableState(this); } else { Int16Value = (BaseDataVariableState)replacement; } } instance = Int16Value; break; } case BrowseNames.UInt16Value: { if (createOrReplace && UInt16Value == null) { if (replacement == null) { UInt16Value = new BaseDataVariableState(this); } else { UInt16Value = (BaseDataVariableState)replacement; } } instance = UInt16Value; break; } case BrowseNames.Int32Value: { if (createOrReplace && Int32Value == null) { if (replacement == null) { Int32Value = new BaseDataVariableState(this); } else { Int32Value = (BaseDataVariableState)replacement; } } instance = Int32Value; break; } case BrowseNames.UInt32Value: { if (createOrReplace && UInt32Value == null) { if (replacement == null) { UInt32Value = new BaseDataVariableState(this); } else { UInt32Value = (BaseDataVariableState)replacement; } } instance = UInt32Value; break; } case BrowseNames.Int64Value: { if (createOrReplace && Int64Value == null) { if (replacement == null) { Int64Value = new BaseDataVariableState(this); } else { Int64Value = (BaseDataVariableState)replacement; } } instance = Int64Value; break; } case BrowseNames.UInt64Value: { if (createOrReplace && UInt64Value == null) { if (replacement == null) { UInt64Value = new BaseDataVariableState(this); } else { UInt64Value = (BaseDataVariableState)replacement; } } instance = UInt64Value; break; } case BrowseNames.FloatValue: { if (createOrReplace && FloatValue == null) { if (replacement == null) { FloatValue = new BaseDataVariableState(this); } else { FloatValue = (BaseDataVariableState)replacement; } } instance = FloatValue; break; } case BrowseNames.DoubleValue: { if (createOrReplace && DoubleValue == null) { if (replacement == null) { DoubleValue = new BaseDataVariableState(this); } else { DoubleValue = (BaseDataVariableState)replacement; } } instance = DoubleValue; break; } case BrowseNames.StringValue: { if (createOrReplace && StringValue == null) { if (replacement == null) { StringValue = new BaseDataVariableState(this); } else { StringValue = (BaseDataVariableState)replacement; } } instance = StringValue; break; } case BrowseNames.DateTimeValue: { if (createOrReplace && DateTimeValue == null) { if (replacement == null) { DateTimeValue = new BaseDataVariableState(this); } else { DateTimeValue = (BaseDataVariableState)replacement; } } instance = DateTimeValue; break; } case BrowseNames.GuidValue: { if (createOrReplace && GuidValue == null) { if (replacement == null) { GuidValue = new BaseDataVariableState(this); } else { GuidValue = (BaseDataVariableState)replacement; } } instance = GuidValue; break; } case BrowseNames.ByteStringValue: { if (createOrReplace && ByteStringValue == null) { if (replacement == null) { ByteStringValue = new BaseDataVariableState(this); } else { ByteStringValue = (BaseDataVariableState)replacement; } } instance = ByteStringValue; break; } case BrowseNames.XmlElementValue: { if (createOrReplace && XmlElementValue == null) { if (replacement == null) { XmlElementValue = new BaseDataVariableState(this); } else { XmlElementValue = (BaseDataVariableState)replacement; } } instance = XmlElementValue; break; } case BrowseNames.NodeIdValue: { if (createOrReplace && NodeIdValue == null) { if (replacement == null) { NodeIdValue = new BaseDataVariableState(this); } else { NodeIdValue = (BaseDataVariableState)replacement; } } instance = NodeIdValue; break; } case BrowseNames.ExpandedNodeIdValue: { if (createOrReplace && ExpandedNodeIdValue == null) { if (replacement == null) { ExpandedNodeIdValue = new BaseDataVariableState(this); } else { ExpandedNodeIdValue = (BaseDataVariableState)replacement; } } instance = ExpandedNodeIdValue; break; } case BrowseNames.QualifiedNameValue: { if (createOrReplace && QualifiedNameValue == null) { if (replacement == null) { QualifiedNameValue = new BaseDataVariableState(this); } else { QualifiedNameValue = (BaseDataVariableState)replacement; } } instance = QualifiedNameValue; break; } case BrowseNames.LocalizedTextValue: { if (createOrReplace && LocalizedTextValue == null) { if (replacement == null) { LocalizedTextValue = new BaseDataVariableState(this); } else { LocalizedTextValue = (BaseDataVariableState)replacement; } } instance = LocalizedTextValue; break; } case BrowseNames.StatusCodeValue: { if (createOrReplace && StatusCodeValue == null) { if (replacement == null) { StatusCodeValue = new BaseDataVariableState(this); } else { StatusCodeValue = (BaseDataVariableState)replacement; } } instance = StatusCodeValue; break; } case BrowseNames.VariantValue: { if (createOrReplace && VariantValue == null) { if (replacement == null) { VariantValue = new BaseDataVariableState(this); } else { VariantValue = (BaseDataVariableState)replacement; } } instance = VariantValue; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private BaseDataVariableState m_booleanValue; private BaseDataVariableState m_sByteValue; private BaseDataVariableState m_byteValue; private BaseDataVariableState m_int16Value; private BaseDataVariableState m_uInt16Value; private BaseDataVariableState m_int32Value; private BaseDataVariableState m_uInt32Value; private BaseDataVariableState m_int64Value; private BaseDataVariableState m_uInt64Value; private BaseDataVariableState m_floatValue; private BaseDataVariableState m_doubleValue; private BaseDataVariableState m_stringValue; private BaseDataVariableState m_dateTimeValue; private BaseDataVariableState m_guidValue; private BaseDataVariableState m_byteStringValue; private BaseDataVariableState m_xmlElementValue; private BaseDataVariableState m_nodeIdValue; private BaseDataVariableState m_expandedNodeIdValue; private BaseDataVariableState m_qualifiedNameValue; private BaseDataVariableState m_localizedTextValue; private BaseDataVariableState m_statusCodeValue; private BaseDataVariableState m_variantValue; #endregion } #endif #endregion #region UserArrayValue1MethodState Class #if (!OPCUA_EXCLUDE_UserArrayValue1MethodState) /// /// Stores an instance of the UserArrayValue1MethodType Method. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class UserArrayValue1MethodState : MethodState { #region Constructors /// /// Initializes the type with its default attribute values. /// public UserArrayValue1MethodState(NodeState parent) : base(parent) { } /// /// Constructs an instance of a node. /// /// The parent. /// The new node. public new static NodeState Construct(NodeState parent) { return new UserArrayValue1MethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAABgAAABodHRwOi8vdGVzdC5vcmcvVUEvRGF0YS//////BGGCCgQAAAABABkAAABVc2VyQXJyYXlW" + "YWx1ZTFNZXRob2RUeXBlAQFmJwAvAQFmJ2YnAAABAf////8CAAAAF2CpCgIAAAAAAA4AAABJbnB1dEFy" + "Z3VtZW50cwEBZycALgBEZycAAJYMAAAAAQAqAQEeAAAACQAAAEJvb2xlYW5JbgEBqiYBAAAAAQAAAAAA" + "AAAAAQAqAQEcAAAABwAAAFNCeXRlSW4BAasmAQAAAAEAAAAAAAAAAAEAKgEBGwAAAAYAAABCeXRlSW4B" + "AawmAQAAAAEAAAAAAAAAAAEAKgEBHAAAAAcAAABJbnQxNkluAQGtJgEAAAABAAAAAAAAAAABACoBAR0A" + "AAAIAAAAVUludDE2SW4BAa4mAQAAAAEAAAAAAAAAAAEAKgEBHAAAAAcAAABJbnQzMkluAQGvJgEAAAAB" + "AAAAAAAAAAABACoBAR0AAAAIAAAAVUludDMySW4BAbAmAQAAAAEAAAAAAAAAAAEAKgEBHAAAAAcAAABJ" + "bnQ2NEluAQGxJgEAAAABAAAAAAAAAAABACoBAR0AAAAIAAAAVUludDY0SW4BAbImAQAAAAEAAAAAAAAA" + "AAEAKgEBHAAAAAcAAABGbG9hdEluAQGzJgEAAAABAAAAAAAAAAABACoBAR0AAAAIAAAARG91YmxlSW4B" + "AbQmAQAAAAEAAAAAAAAAAAEAKgEBHQAAAAgAAABTdHJpbmdJbgEBtSYBAAAAAQAAAAAAAAAAAQAoAQEA" + "AAABAAAAAAAAAAEB/////wAAAAAXYKkKAgAAAAAADwAAAE91dHB1dEFyZ3VtZW50cwEBaCcALgBEaCcA" + "AJYMAAAAAQAqAQEfAAAACgAAAEJvb2xlYW5PdXQBAaomAQAAAAEAAAAAAAAAAAEAKgEBHQAAAAgAAABT" + "Qnl0ZU91dAEBqyYBAAAAAQAAAAAAAAAAAQAqAQEcAAAABwAAAEJ5dGVPdXQBAawmAQAAAAEAAAAAAAAA" + "AAEAKgEBHQAAAAgAAABJbnQxNk91dAEBrSYBAAAAAQAAAAAAAAAAAQAqAQEeAAAACQAAAFVJbnQxNk91" + "dAEBriYBAAAAAQAAAAAAAAAAAQAqAQEdAAAACAAAAEludDMyT3V0AQGvJgEAAAABAAAAAAAAAAABACoB" + "AR4AAAAJAAAAVUludDMyT3V0AQGwJgEAAAABAAAAAAAAAAABACoBAR0AAAAIAAAASW50NjRPdXQBAbEm" + "AQAAAAEAAAAAAAAAAAEAKgEBHgAAAAkAAABVSW50NjRPdXQBAbImAQAAAAEAAAAAAAAAAAEAKgEBHQAA" + "AAgAAABGbG9hdE91dAEBsyYBAAAAAQAAAAAAAAAAAQAqAQEeAAAACQAAAERvdWJsZU91dAEBtCYBAAAA" + "AQAAAAAAAAAAAQAqAQEeAAAACQAAAFN0cmluZ091dAEBtSYBAAAAAQAAAAAAAAAAAQAoAQEAAAABAAAA" + "AAAAAAEB/////wAAAAA="; #endregion #endif #endregion #region Event Callbacks /// /// Raised when the the method is called. /// public UserArrayValue1MethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// /// Invokes the method, returns the result and output argument. /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult result = null; bool[] booleanIn = (bool[])_inputArguments[0]; sbyte[] sByteIn = (sbyte[])_inputArguments[1]; byte[] byteIn = (byte[])_inputArguments[2]; short[] int16In = (short[])_inputArguments[3]; ushort[] uInt16In = (ushort[])_inputArguments[4]; int[] int32In = (int[])_inputArguments[5]; uint[] uInt32In = (uint[])_inputArguments[6]; long[] int64In = (long[])_inputArguments[7]; ulong[] uInt64In = (ulong[])_inputArguments[8]; float[] floatIn = (float[])_inputArguments[9]; double[] doubleIn = (double[])_inputArguments[10]; string[] stringIn = (string[])_inputArguments[11]; bool[] booleanOut = (bool[])_outputArguments[0]; sbyte[] sByteOut = (sbyte[])_outputArguments[1]; byte[] byteOut = (byte[])_outputArguments[2]; short[] int16Out = (short[])_outputArguments[3]; ushort[] uInt16Out = (ushort[])_outputArguments[4]; int[] int32Out = (int[])_outputArguments[5]; uint[] uInt32Out = (uint[])_outputArguments[6]; long[] int64Out = (long[])_outputArguments[7]; ulong[] uInt64Out = (ulong[])_outputArguments[8]; float[] floatOut = (float[])_outputArguments[9]; double[] doubleOut = (double[])_outputArguments[10]; string[] stringOut = (string[])_outputArguments[11]; if (OnCall != null) { result = OnCall( _context, this, _objectId, booleanIn, sByteIn, byteIn, int16In, uInt16In, int32In, uInt32In, int64In, uInt64In, floatIn, doubleIn, stringIn, ref booleanOut, ref sByteOut, ref byteOut, ref int16Out, ref uInt16Out, ref int32Out, ref uInt32Out, ref int64Out, ref uInt64Out, ref floatOut, ref doubleOut, ref stringOut); } _outputArguments[0] = booleanOut; _outputArguments[1] = sByteOut; _outputArguments[2] = byteOut; _outputArguments[3] = int16Out; _outputArguments[4] = uInt16Out; _outputArguments[5] = int32Out; _outputArguments[6] = uInt32Out; _outputArguments[7] = int64Out; _outputArguments[8] = uInt64Out; _outputArguments[9] = floatOut; _outputArguments[10] = doubleOut; _outputArguments[11] = stringOut; return result; } #endregion #region Private Fields #endregion } /// /// Used to receive notifications when the method is called. /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// public delegate ServiceResult UserArrayValue1MethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, bool[] booleanIn, sbyte[] sByteIn, byte[] byteIn, short[] int16In, ushort[] uInt16In, int[] int32In, uint[] uInt32In, long[] int64In, ulong[] uInt64In, float[] floatIn, double[] doubleIn, string[] stringIn, ref bool[] booleanOut, ref sbyte[] sByteOut, ref byte[] byteOut, ref short[] int16Out, ref ushort[] uInt16Out, ref int[] int32Out, ref uint[] uInt32Out, ref long[] int64Out, ref ulong[] uInt64Out, ref float[] floatOut, ref double[] doubleOut, ref string[] stringOut); #endif #endregion #region UserArrayValue2MethodState Class #if (!OPCUA_EXCLUDE_UserArrayValue2MethodState) /// /// Stores an instance of the UserArrayValue2MethodType Method. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class UserArrayValue2MethodState : MethodState { #region Constructors /// /// Initializes the type with its default attribute values. /// public UserArrayValue2MethodState(NodeState parent) : base(parent) { } /// /// Constructs an instance of a node. /// /// The parent. /// The new node. public new static NodeState Construct(NodeState parent) { return new UserArrayValue2MethodState(parent); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAABgAAABodHRwOi8vdGVzdC5vcmcvVUEvRGF0YS//////BGGCCgQAAAABABkAAABVc2VyQXJyYXlW" + "YWx1ZTJNZXRob2RUeXBlAQFpJwAvAQFpJ2knAAABAf////8CAAAAF2CpCgIAAAAAAA4AAABJbnB1dEFy" + "Z3VtZW50cwEBaicALgBEaicAAJYKAAAAAQAqAQEfAAAACgAAAERhdGVUaW1lSW4BAbYmAQAAAAEAAAAA" + "AAAAAAEAKgEBGwAAAAYAAABHdWlkSW4BAbcmAQAAAAEAAAAAAAAAAAEAKgEBIQAAAAwAAABCeXRlU3Ry" + "aW5nSW4BAbgmAQAAAAEAAAAAAAAAAAEAKgEBIQAAAAwAAABYbWxFbGVtZW50SW4BAbkmAQAAAAEAAAAA" + "AAAAAAEAKgEBHQAAAAgAAABOb2RlSWRJbgEBuiYBAAAAAQAAAAAAAAAAAQAqAQElAAAAEAAAAEV4cGFu" + "ZGVkTm9kZUlkSW4BAbsmAQAAAAEAAAAAAAAAAAEAKgEBJAAAAA8AAABRdWFsaWZpZWROYW1lSW4BAbwm" + "AQAAAAEAAAAAAAAAAAEAKgEBJAAAAA8AAABMb2NhbGl6ZWRUZXh0SW4BAb0mAQAAAAEAAAAAAAAAAAEA" + "KgEBIQAAAAwAAABTdGF0dXNDb2RlSW4BAb4mAQAAAAEAAAAAAAAAAAEAKgEBHgAAAAkAAABWYXJpYW50" + "SW4BAb8mAQAAAAEAAAAAAAAAAAEAKAEBAAAAAQAAAAAAAAABAf////8AAAAAF2CpCgIAAAAAAA8AAABP" + "dXRwdXRBcmd1bWVudHMBAWsnAC4ARGsnAACWCgAAAAEAKgEBIAAAAAsAAABEYXRlVGltZU91dAEBtiYB" + "AAAAAQAAAAAAAAAAAQAqAQEcAAAABwAAAEd1aWRPdXQBAbcmAQAAAAEAAAAAAAAAAAEAKgEBIgAAAA0A" + "AABCeXRlU3RyaW5nT3V0AQG4JgEAAAABAAAAAAAAAAABACoBASIAAAANAAAAWG1sRWxlbWVudE91dAEB" + "uSYBAAAAAQAAAAAAAAAAAQAqAQEeAAAACQAAAE5vZGVJZE91dAEBuiYBAAAAAQAAAAAAAAAAAQAqAQEm" + "AAAAEQAAAEV4cGFuZGVkTm9kZUlkT3V0AQG7JgEAAAABAAAAAAAAAAABACoBASUAAAAQAAAAUXVhbGlm" + "aWVkTmFtZU91dAEBvCYBAAAAAQAAAAAAAAAAAQAqAQElAAAAEAAAAExvY2FsaXplZFRleHRPdXQBAb0m" + "AQAAAAEAAAAAAAAAAAEAKgEBIgAAAA0AAABTdGF0dXNDb2RlT3V0AQG+JgEAAAABAAAAAAAAAAABACoB" + "AR8AAAAKAAAAVmFyaWFudE91dAEBvyYBAAAAAQAAAAAAAAAAAQAoAQEAAAABAAAAAAAAAAEB/////wAA" + "AAA="; #endregion #endif #endregion #region Event Callbacks /// /// Raised when the the method is called. /// public UserArrayValue2MethodStateMethodCallHandler OnCall; #endregion #region Public Properties #endregion #region Overridden Methods /// /// Invokes the method, returns the result and output argument. /// protected override ServiceResult Call( ISystemContext _context, NodeId _objectId, IList _inputArguments, IList _outputArguments) { if (OnCall == null) { return base.Call(_context, _objectId, _inputArguments, _outputArguments); } ServiceResult result = null; DateTime[] dateTimeIn = (DateTime[])_inputArguments[0]; Uuid[] guidIn = (Uuid[])_inputArguments[1]; byte[][] byteStringIn = (byte[][])_inputArguments[2]; XmlElement[] xmlElementIn = (XmlElement[])_inputArguments[3]; NodeId[] nodeIdIn = (NodeId[])_inputArguments[4]; ExpandedNodeId[] expandedNodeIdIn = (ExpandedNodeId[])_inputArguments[5]; QualifiedName[] qualifiedNameIn = (QualifiedName[])_inputArguments[6]; LocalizedText[] localizedTextIn = (LocalizedText[])_inputArguments[7]; StatusCode[] statusCodeIn = (StatusCode[])_inputArguments[8]; Variant[] variantIn = (Variant[])_inputArguments[9]; DateTime[] dateTimeOut = (DateTime[])_outputArguments[0]; Uuid[] guidOut = (Uuid[])_outputArguments[1]; byte[][] byteStringOut = (byte[][])_outputArguments[2]; XmlElement[] xmlElementOut = (XmlElement[])_outputArguments[3]; NodeId[] nodeIdOut = (NodeId[])_outputArguments[4]; ExpandedNodeId[] expandedNodeIdOut = (ExpandedNodeId[])_outputArguments[5]; QualifiedName[] qualifiedNameOut = (QualifiedName[])_outputArguments[6]; LocalizedText[] localizedTextOut = (LocalizedText[])_outputArguments[7]; StatusCode[] statusCodeOut = (StatusCode[])_outputArguments[8]; Variant[] variantOut = (Variant[])_outputArguments[9]; if (OnCall != null) { result = OnCall( _context, this, _objectId, dateTimeIn, guidIn, byteStringIn, xmlElementIn, nodeIdIn, expandedNodeIdIn, qualifiedNameIn, localizedTextIn, statusCodeIn, variantIn, ref dateTimeOut, ref guidOut, ref byteStringOut, ref xmlElementOut, ref nodeIdOut, ref expandedNodeIdOut, ref qualifiedNameOut, ref localizedTextOut, ref statusCodeOut, ref variantOut); } _outputArguments[0] = dateTimeOut; _outputArguments[1] = guidOut; _outputArguments[2] = byteStringOut; _outputArguments[3] = xmlElementOut; _outputArguments[4] = nodeIdOut; _outputArguments[5] = expandedNodeIdOut; _outputArguments[6] = qualifiedNameOut; _outputArguments[7] = localizedTextOut; _outputArguments[8] = statusCodeOut; _outputArguments[9] = variantOut; return result; } #endregion #region Private Fields #endregion } /// /// Used to receive notifications when the method is called. /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// public delegate ServiceResult UserArrayValue2MethodStateMethodCallHandler( ISystemContext _context, MethodState _method, NodeId _objectId, DateTime[] dateTimeIn, Uuid[] guidIn, byte[][] byteStringIn, XmlElement[] xmlElementIn, NodeId[] nodeIdIn, ExpandedNodeId[] expandedNodeIdIn, QualifiedName[] qualifiedNameIn, LocalizedText[] localizedTextIn, StatusCode[] statusCodeIn, Variant[] variantIn, ref DateTime[] dateTimeOut, ref Uuid[] guidOut, ref byte[][] byteStringOut, ref XmlElement[] xmlElementOut, ref NodeId[] nodeIdOut, ref ExpandedNodeId[] expandedNodeIdOut, ref QualifiedName[] qualifiedNameOut, ref LocalizedText[] localizedTextOut, ref StatusCode[] statusCodeOut, ref Variant[] variantOut); #endif #endregion #region MethodTestState Class #if (!OPCUA_EXCLUDE_MethodTestState) /// /// Stores an instance of the MethodTestType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCode("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class MethodTestState : FolderState { #region Constructors /// /// Initializes the type with its default attribute values. /// /// public MethodTestState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return NodeId.Create(ObjectTypes.MethodTestType, Namespaces.TestData, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// /// /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAABgAAABodHRwOi8vdGVzdC5vcmcvVUEvRGF0YS//////BGCAAgEAAAABABYAAABNZXRob2RUZXN0" + "VHlwZUluc3RhbmNlAQFsJwEBbCdsJwAA/////woAAAAEYYIKBAAAAAEADQAAAFNjYWxhck1ldGhvZDEB" + "AW0nAC8BAW0nbScAAAEB/////wIAAAAXYKkKAgAAAAAADgAAAElucHV0QXJndW1lbnRzAQFuJwAuAERu" + "JwAAlgsAAAABACoBARgAAAAJAAAAQm9vbGVhbkluAAH/////AAAAAAABACoBARYAAAAHAAAAU0J5dGVJ" + "bgAC/////wAAAAAAAQAqAQEVAAAABgAAAEJ5dGVJbgAD/////wAAAAAAAQAqAQEWAAAABwAAAEludDE2" + "SW4ABP////8AAAAAAAEAKgEBFwAAAAgAAABVSW50MTZJbgAF/////wAAAAAAAQAqAQEWAAAABwAAAElu" + "dDMySW4ABv////8AAAAAAAEAKgEBFwAAAAgAAABVSW50MzJJbgAH/////wAAAAAAAQAqAQEWAAAABwAA" + "AEludDY0SW4ACP////8AAAAAAAEAKgEBFwAAAAgAAABVSW50NjRJbgAJ/////wAAAAAAAQAqAQEWAAAA" + "BwAAAEZsb2F0SW4ACv////8AAAAAAAEAKgEBFwAAAAgAAABEb3VibGVJbgAL/////wAAAAAAAQAoAQEA" + "AAABAAAAAAAAAAEB/////wAAAAAXYKkKAgAAAAAADwAAAE91dHB1dEFyZ3VtZW50cwEBbycALgBEbycA" + "AJYLAAAAAQAqAQEZAAAACgAAAEJvb2xlYW5PdXQAAf////8AAAAAAAEAKgEBFwAAAAgAAABTQnl0ZU91" + "dAAC/////wAAAAAAAQAqAQEWAAAABwAAAEJ5dGVPdXQAA/////8AAAAAAAEAKgEBFwAAAAgAAABJbnQx" + "Nk91dAAE/////wAAAAAAAQAqAQEYAAAACQAAAFVJbnQxNk91dAAF/////wAAAAAAAQAqAQEXAAAACAAA" + "AEludDMyT3V0AAb/////AAAAAAABACoBARgAAAAJAAAAVUludDMyT3V0AAf/////AAAAAAABACoBARcA" + "AAAIAAAASW50NjRPdXQACP////8AAAAAAAEAKgEBGAAAAAkAAABVSW50NjRPdXQACf////8AAAAAAAEA" + "KgEBFwAAAAgAAABGbG9hdE91dAAK/////wAAAAAAAQAqAQEYAAAACQAAAERvdWJsZU91dAAL/////wAA" + "AAAAAQAoAQEAAAABAAAAAAAAAAEB/////wAAAAAEYYIKBAAAAAEADQAAAFNjYWxhck1ldGhvZDIBAXAn" + "AC8BAXAncCcAAAEB/////wIAAAAXYKkKAgAAAAAADgAAAElucHV0QXJndW1lbnRzAQFxJwAuAERxJwAA" + "lgoAAAABACoBARcAAAAIAAAAU3RyaW5nSW4ADP////8AAAAAAAEAKgEBGQAAAAoAAABEYXRlVGltZUlu" + "AA3/////AAAAAAABACoBARUAAAAGAAAAR3VpZEluAA7/////AAAAAAABACoBARsAAAAMAAAAQnl0ZVN0" + "cmluZ0luAA//////AAAAAAABACoBARsAAAAMAAAAWG1sRWxlbWVudEluABD/////AAAAAAABACoBARcA" + "AAAIAAAATm9kZUlkSW4AEf////8AAAAAAAEAKgEBHwAAABAAAABFeHBhbmRlZE5vZGVJZEluABL/////" + "AAAAAAABACoBAR4AAAAPAAAAUXVhbGlmaWVkTmFtZUluABT/////AAAAAAABACoBAR4AAAAPAAAATG9j" + "YWxpemVkVGV4dEluABX/////AAAAAAABACoBARsAAAAMAAAAU3RhdHVzQ29kZUluABP/////AAAAAAAB" + "ACgBAQAAAAEAAAAAAAAAAQH/////AAAAABdgqQoCAAAAAAAPAAAAT3V0cHV0QXJndW1lbnRzAQFyJwAu" + "AERyJwAAlgoAAAABACoBARgAAAAJAAAAU3RyaW5nT3V0AAz/////AAAAAAABACoBARoAAAALAAAARGF0" + "ZVRpbWVPdXQADf////8AAAAAAAEAKgEBFgAAAAcAAABHdWlkT3V0AA7/////AAAAAAABACoBARwAAAAN" + "AAAAQnl0ZVN0cmluZ091dAAP/////wAAAAAAAQAqAQEcAAAADQAAAFhtbEVsZW1lbnRPdXQAEP////8A" + "AAAAAAEAKgEBGAAAAAkAAABOb2RlSWRPdXQAEf////8AAAAAAAEAKgEBIAAAABEAAABFeHBhbmRlZE5v" + "ZGVJZE91dAAS/////wAAAAAAAQAqAQEfAAAAEAAAAFF1YWxpZmllZE5hbWVPdXQAFP////8AAAAAAAEA" + "KgEBHwAAABAAAABMb2NhbGl6ZWRUZXh0T3V0ABX/////AAAAAAABACoBARwAAAANAAAAU3RhdHVzQ29k" + "ZU91dAAT/////wAAAAAAAQAoAQEAAAABAAAAAAAAAAEB/////wAAAAAEYYIKBAAAAAEADQAAAFNjYWxh" + "ck1ldGhvZDMBAXMnAC8BAXMncycAAAEB/////wIAAAAXYKkKAgAAAAAADgAAAElucHV0QXJndW1lbnRz" + "AQF0JwAuAER0JwAAlgMAAAABACoBARgAAAAJAAAAVmFyaWFudEluABj/////AAAAAAABACoBARwAAAAN" + "AAAARW51bWVyYXRpb25JbgAd/////wAAAAAAAQAqAQEaAAAACwAAAFN0cnVjdHVyZUluABb/////AAAA" + "AAABACgBAQAAAAEAAAAAAAAAAQH/////AAAAABdgqQoCAAAAAAAPAAAAT3V0cHV0QXJndW1lbnRzAQF1" + "JwAuAER1JwAAlgMAAAABACoBARkAAAAKAAAAVmFyaWFudE91dAAY/////wAAAAAAAQAqAQEdAAAADgAA" + "AEVudW1lcmF0aW9uT3V0AB3/////AAAAAAABACoBARsAAAAMAAAAU3RydWN0dXJlT3V0ABb/////AAAA" + "AAABACgBAQAAAAEAAAAAAAAAAQH/////AAAAAARhggoEAAAAAQAMAAAAQXJyYXlNZXRob2QxAQF2JwAv" + "AQF2J3YnAAABAf////8CAAAAF2CpCgIAAAAAAA4AAABJbnB1dEFyZ3VtZW50cwEBdycALgBEdycAAJYL" + "AAAAAQAqAQEcAAAACQAAAEJvb2xlYW5JbgABAQAAAAEAAAAAAAAAAAEAKgEBGgAAAAcAAABTQnl0ZUlu" + "AAIBAAAAAQAAAAAAAAAAAQAqAQEZAAAABgAAAEJ5dGVJbgADAQAAAAEAAAAAAAAAAAEAKgEBGgAAAAcA" + "AABJbnQxNkluAAQBAAAAAQAAAAAAAAAAAQAqAQEbAAAACAAAAFVJbnQxNkluAAUBAAAAAQAAAAAAAAAA" + "AQAqAQEaAAAABwAAAEludDMySW4ABgEAAAABAAAAAAAAAAABACoBARsAAAAIAAAAVUludDMySW4ABwEA" + "AAABAAAAAAAAAAABACoBARoAAAAHAAAASW50NjRJbgAIAQAAAAEAAAAAAAAAAAEAKgEBGwAAAAgAAABV" + "SW50NjRJbgAJAQAAAAEAAAAAAAAAAAEAKgEBGgAAAAcAAABGbG9hdEluAAoBAAAAAQAAAAAAAAAAAQAq" + "AQEbAAAACAAAAERvdWJsZUluAAsBAAAAAQAAAAAAAAAAAQAoAQEAAAABAAAAAAAAAAEB/////wAAAAAX" + "YKkKAgAAAAAADwAAAE91dHB1dEFyZ3VtZW50cwEBeCcALgBEeCcAAJYLAAAAAQAqAQEdAAAACgAAAEJv" + "b2xlYW5PdXQAAQEAAAABAAAAAAAAAAABACoBARsAAAAIAAAAU0J5dGVPdXQAAgEAAAABAAAAAAAAAAAB" + "ACoBARoAAAAHAAAAQnl0ZU91dAADAQAAAAEAAAAAAAAAAAEAKgEBGwAAAAgAAABJbnQxNk91dAAEAQAA" + "AAEAAAAAAAAAAAEAKgEBHAAAAAkAAABVSW50MTZPdXQABQEAAAABAAAAAAAAAAABACoBARsAAAAIAAAA" + "SW50MzJPdXQABgEAAAABAAAAAAAAAAABACoBARwAAAAJAAAAVUludDMyT3V0AAcBAAAAAQAAAAAAAAAA" + "AQAqAQEbAAAACAAAAEludDY0T3V0AAgBAAAAAQAAAAAAAAAAAQAqAQEcAAAACQAAAFVJbnQ2NE91dAAJ" + "AQAAAAEAAAAAAAAAAAEAKgEBGwAAAAgAAABGbG9hdE91dAAKAQAAAAEAAAAAAAAAAAEAKgEBHAAAAAkA" + "AABEb3VibGVPdXQACwEAAAABAAAAAAAAAAABACgBAQAAAAEAAAAAAAAAAQH/////AAAAAARhggoEAAAA" + "AQAMAAAAQXJyYXlNZXRob2QyAQF5JwAvAQF5J3knAAABAf////8CAAAAF2CpCgIAAAAAAA4AAABJbnB1" + "dEFyZ3VtZW50cwEBeicALgBEeicAAJYKAAAAAQAqAQEbAAAACAAAAFN0cmluZ0luAAwBAAAAAQAAAAAA" + "AAAAAQAqAQEdAAAACgAAAERhdGVUaW1lSW4ADQEAAAABAAAAAAAAAAABACoBARkAAAAGAAAAR3VpZElu" + "AA4BAAAAAQAAAAAAAAAAAQAqAQEfAAAADAAAAEJ5dGVTdHJpbmdJbgAPAQAAAAEAAAAAAAAAAAEAKgEB" + "HwAAAAwAAABYbWxFbGVtZW50SW4AEAEAAAABAAAAAAAAAAABACoBARsAAAAIAAAATm9kZUlkSW4AEQEA" + "AAABAAAAAAAAAAABACoBASMAAAAQAAAARXhwYW5kZWROb2RlSWRJbgASAQAAAAEAAAAAAAAAAAEAKgEB" + "IgAAAA8AAABRdWFsaWZpZWROYW1lSW4AFAEAAAABAAAAAAAAAAABACoBASIAAAAPAAAATG9jYWxpemVk" + "VGV4dEluABUBAAAAAQAAAAAAAAAAAQAqAQEfAAAADAAAAFN0YXR1c0NvZGVJbgATAQAAAAEAAAAAAAAA" + "AAEAKAEBAAAAAQAAAAAAAAABAf////8AAAAAF2CpCgIAAAAAAA8AAABPdXRwdXRBcmd1bWVudHMBAXsn" + "AC4ARHsnAACWCgAAAAEAKgEBHAAAAAkAAABTdHJpbmdPdXQADAEAAAABAAAAAAAAAAABACoBAR4AAAAL" + "AAAARGF0ZVRpbWVPdXQADQEAAAABAAAAAAAAAAABACoBARoAAAAHAAAAR3VpZE91dAAOAQAAAAEAAAAA" + "AAAAAAEAKgEBIAAAAA0AAABCeXRlU3RyaW5nT3V0AA8BAAAAAQAAAAAAAAAAAQAqAQEgAAAADQAAAFht" + "bEVsZW1lbnRPdXQAEAEAAAABAAAAAAAAAAABACoBARwAAAAJAAAATm9kZUlkT3V0ABEBAAAAAQAAAAAA" + "AAAAAQAqAQEkAAAAEQAAAEV4cGFuZGVkTm9kZUlkT3V0ABIBAAAAAQAAAAAAAAAAAQAqAQEjAAAAEAAA" + "AFF1YWxpZmllZE5hbWVPdXQAFAEAAAABAAAAAAAAAAABACoBASMAAAAQAAAATG9jYWxpemVkVGV4dE91" + "dAAVAQAAAAEAAAAAAAAAAAEAKgEBIAAAAA0AAABTdGF0dXNDb2RlT3V0ABMBAAAAAQAAAAAAAAAAAQAo" + "AQEAAAABAAAAAAAAAAEB/////wAAAAAEYYIKBAAAAAEADAAAAEFycmF5TWV0aG9kMwEBfCcALwEBfCd8" + "JwAAAQH/////AgAAABdgqQoCAAAAAAAOAAAASW5wdXRBcmd1bWVudHMBAX0nAC4ARH0nAACWAwAAAAEA" + "KgEBHAAAAAkAAABWYXJpYW50SW4AGAEAAAABAAAAAAAAAAABACoBASAAAAANAAAARW51bWVyYXRpb25J" + "bgAdAQAAAAEAAAAAAAAAAAEAKgEBHgAAAAsAAABTdHJ1Y3R1cmVJbgAWAQAAAAEAAAAAAAAAAAEAKAEB" + "AAAAAQAAAAAAAAABAf////8AAAAAF2CpCgIAAAAAAA8AAABPdXRwdXRBcmd1bWVudHMBAX4nAC4ARH4n" + "AACWAwAAAAEAKgEBHQAAAAoAAABWYXJpYW50T3V0ABgBAAAAAQAAAAAAAAAAAQAqAQEhAAAADgAAAEVu" + "dW1lcmF0aW9uT3V0AB0BAAAAAQAAAAAAAAAAAQAqAQEfAAAADAAAAFN0cnVjdHVyZU91dAAWAQAAAAEA" + "AAAAAAAAAAEAKAEBAAAAAQAAAAAAAAABAf////8AAAAABGGCCgQAAAABABEAAABVc2VyU2NhbGFyTWV0" + "aG9kMQEBfycALwEBfyd/JwAAAQH/////AgAAABdgqQoCAAAAAAAOAAAASW5wdXRBcmd1bWVudHMBAYAn" + "AC4ARIAnAACWDAAAAAEAKgEBGgAAAAkAAABCb29sZWFuSW4BAaom/////wAAAAAAAQAqAQEYAAAABwAA" + "AFNCeXRlSW4BAasm/////wAAAAAAAQAqAQEXAAAABgAAAEJ5dGVJbgEBrCb/////AAAAAAABACoBARgA" + "AAAHAAAASW50MTZJbgEBrSb/////AAAAAAABACoBARkAAAAIAAAAVUludDE2SW4BAa4m/////wAAAAAA" + "AQAqAQEYAAAABwAAAEludDMySW4BAa8m/////wAAAAAAAQAqAQEZAAAACAAAAFVJbnQzMkluAQGwJv//" + "//8AAAAAAAEAKgEBGAAAAAcAAABJbnQ2NEluAQGxJv////8AAAAAAAEAKgEBGQAAAAgAAABVSW50NjRJ" + "bgEBsib/////AAAAAAABACoBARgAAAAHAAAARmxvYXRJbgEBsyb/////AAAAAAABACoBARkAAAAIAAAA" + "RG91YmxlSW4BAbQm/////wAAAAAAAQAqAQEZAAAACAAAAFN0cmluZ0luAQG1Jv////8AAAAAAAEAKAEB" + "AAAAAQAAAAAAAAABAf////8AAAAAF2CpCgIAAAAAAA8AAABPdXRwdXRBcmd1bWVudHMBAYEnAC4ARIEn" + "AACWDAAAAAEAKgEBGwAAAAoAAABCb29sZWFuT3V0AQGqJv////8AAAAAAAEAKgEBGQAAAAgAAABTQnl0" + "ZU91dAEBqyb/////AAAAAAABACoBARgAAAAHAAAAQnl0ZU91dAEBrCb/////AAAAAAABACoBARkAAAAI" + "AAAASW50MTZPdXQBAa0m/////wAAAAAAAQAqAQEaAAAACQAAAFVJbnQxNk91dAEBrib/////AAAAAAAB" + "ACoBARkAAAAIAAAASW50MzJPdXQBAa8m/////wAAAAAAAQAqAQEaAAAACQAAAFVJbnQzMk91dAEBsCb/" + "////AAAAAAABACoBARkAAAAIAAAASW50NjRPdXQBAbEm/////wAAAAAAAQAqAQEaAAAACQAAAFVJbnQ2" + "NE91dAEBsib/////AAAAAAABACoBARkAAAAIAAAARmxvYXRPdXQBAbMm/////wAAAAAAAQAqAQEaAAAA" + "CQAAAERvdWJsZU91dAEBtCb/////AAAAAAABACoBARoAAAAJAAAAU3RyaW5nT3V0AQG1Jv////8AAAAA" + "AAEAKAEBAAAAAQAAAAAAAAABAf////8AAAAABGGCCgQAAAABABEAAABVc2VyU2NhbGFyTWV0aG9kMgEB" + "gicALwEBgieCJwAAAQH/////AgAAABdgqQoCAAAAAAAOAAAASW5wdXRBcmd1bWVudHMBAYMnAC4ARIMn" + "AACWCgAAAAEAKgEBGwAAAAoAAABEYXRlVGltZUluAQG2Jv////8AAAAAAAEAKgEBFwAAAAYAAABHdWlk" + "SW4BAbcm/////wAAAAAAAQAqAQEdAAAADAAAAEJ5dGVTdHJpbmdJbgEBuCb/////AAAAAAABACoBAR0A" + "AAAMAAAAWG1sRWxlbWVudEluAQG5Jv////8AAAAAAAEAKgEBGQAAAAgAAABOb2RlSWRJbgEBuib/////" + "AAAAAAABACoBASEAAAAQAAAARXhwYW5kZWROb2RlSWRJbgEBuyb/////AAAAAAABACoBASAAAAAPAAAA" + "UXVhbGlmaWVkTmFtZUluAQG8Jv////8AAAAAAAEAKgEBIAAAAA8AAABMb2NhbGl6ZWRUZXh0SW4BAb0m" + "/////wAAAAAAAQAqAQEdAAAADAAAAFN0YXR1c0NvZGVJbgEBvib/////AAAAAAABACoBARoAAAAJAAAA" + "VmFyaWFudEluAQG/Jv////8AAAAAAAEAKAEBAAAAAQAAAAAAAAABAf////8AAAAAF2CpCgIAAAAAAA8A" + "AABPdXRwdXRBcmd1bWVudHMBAYQnAC4ARIQnAACWCgAAAAEAKgEBHAAAAAsAAABEYXRlVGltZU91dAEB" + "tib/////AAAAAAABACoBARgAAAAHAAAAR3VpZE91dAEBtyb/////AAAAAAABACoBAR4AAAANAAAAQnl0" + "ZVN0cmluZ091dAEBuCb/////AAAAAAABACoBAR4AAAANAAAAWG1sRWxlbWVudE91dAEBuSb/////AAAA" + "AAABACoBARoAAAAJAAAATm9kZUlkT3V0AQG6Jv////8AAAAAAAEAKgEBIgAAABEAAABFeHBhbmRlZE5v" + "ZGVJZE91dAEBuyb/////AAAAAAABACoBASEAAAAQAAAAUXVhbGlmaWVkTmFtZU91dAEBvCb/////AAAA" + "AAABACoBASEAAAAQAAAATG9jYWxpemVkVGV4dE91dAEBvSb/////AAAAAAABACoBAR4AAAANAAAAU3Rh" + "dHVzQ29kZU91dAEBvib/////AAAAAAABACoBARsAAAAKAAAAVmFyaWFudE91dAEBvyb/////AAAAAAAB" + "ACgBAQAAAAEAAAAAAAAAAQH/////AAAAAARhggoEAAAAAQAQAAAAVXNlckFycmF5TWV0aG9kMQEBhScA" + "LwEBhSeFJwAAAQH/////AgAAABdgqQoCAAAAAAAOAAAASW5wdXRBcmd1bWVudHMBAYYnAC4ARIYnAACW" + "DAAAAAEAKgEBHgAAAAkAAABCb29sZWFuSW4BAaomAQAAAAEAAAAAAAAAAAEAKgEBHAAAAAcAAABTQnl0" + "ZUluAQGrJgEAAAABAAAAAAAAAAABACoBARsAAAAGAAAAQnl0ZUluAQGsJgEAAAABAAAAAAAAAAABACoB" + "ARwAAAAHAAAASW50MTZJbgEBrSYBAAAAAQAAAAAAAAAAAQAqAQEdAAAACAAAAFVJbnQxNkluAQGuJgEA" + "AAABAAAAAAAAAAABACoBARwAAAAHAAAASW50MzJJbgEBryYBAAAAAQAAAAAAAAAAAQAqAQEdAAAACAAA" + "AFVJbnQzMkluAQGwJgEAAAABAAAAAAAAAAABACoBARwAAAAHAAAASW50NjRJbgEBsSYBAAAAAQAAAAAA" + "AAAAAQAqAQEdAAAACAAAAFVJbnQ2NEluAQGyJgEAAAABAAAAAAAAAAABACoBARwAAAAHAAAARmxvYXRJ" + "bgEBsyYBAAAAAQAAAAAAAAAAAQAqAQEdAAAACAAAAERvdWJsZUluAQG0JgEAAAABAAAAAAAAAAABACoB" + "AR0AAAAIAAAAU3RyaW5nSW4BAbUmAQAAAAEAAAAAAAAAAAEAKAEBAAAAAQAAAAAAAAABAf////8AAAAA" + "F2CpCgIAAAAAAA8AAABPdXRwdXRBcmd1bWVudHMBAYcnAC4ARIcnAACWDAAAAAEAKgEBHwAAAAoAAABC" + "b29sZWFuT3V0AQGqJgEAAAABAAAAAAAAAAABACoBAR0AAAAIAAAAU0J5dGVPdXQBAasmAQAAAAEAAAAA" + "AAAAAAEAKgEBHAAAAAcAAABCeXRlT3V0AQGsJgEAAAABAAAAAAAAAAABACoBAR0AAAAIAAAASW50MTZP" + "dXQBAa0mAQAAAAEAAAAAAAAAAAEAKgEBHgAAAAkAAABVSW50MTZPdXQBAa4mAQAAAAEAAAAAAAAAAAEA" + "KgEBHQAAAAgAAABJbnQzMk91dAEBryYBAAAAAQAAAAAAAAAAAQAqAQEeAAAACQAAAFVJbnQzMk91dAEB" + "sCYBAAAAAQAAAAAAAAAAAQAqAQEdAAAACAAAAEludDY0T3V0AQGxJgEAAAABAAAAAAAAAAABACoBAR4A" + "AAAJAAAAVUludDY0T3V0AQGyJgEAAAABAAAAAAAAAAABACoBAR0AAAAIAAAARmxvYXRPdXQBAbMmAQAA" + "AAEAAAAAAAAAAAEAKgEBHgAAAAkAAABEb3VibGVPdXQBAbQmAQAAAAEAAAAAAAAAAAEAKgEBHgAAAAkA" + "AABTdHJpbmdPdXQBAbUmAQAAAAEAAAAAAAAAAAEAKAEBAAAAAQAAAAAAAAABAf////8AAAAABGGCCgQA" + "AAABABAAAABVc2VyQXJyYXlNZXRob2QyAQGIJwAvAQGIJ4gnAAABAf////8CAAAAF2CpCgIAAAAAAA4A" + "AABJbnB1dEFyZ3VtZW50cwEBiScALgBEiScAAJYKAAAAAQAqAQEfAAAACgAAAERhdGVUaW1lSW4BAbYm" + "AQAAAAEAAAAAAAAAAAEAKgEBGwAAAAYAAABHdWlkSW4BAbcmAQAAAAEAAAAAAAAAAAEAKgEBIQAAAAwA" + "AABCeXRlU3RyaW5nSW4BAbgmAQAAAAEAAAAAAAAAAAEAKgEBIQAAAAwAAABYbWxFbGVtZW50SW4BAbkm" + "AQAAAAEAAAAAAAAAAAEAKgEBHQAAAAgAAABOb2RlSWRJbgEBuiYBAAAAAQAAAAAAAAAAAQAqAQElAAAA" + "EAAAAEV4cGFuZGVkTm9kZUlkSW4BAbsmAQAAAAEAAAAAAAAAAAEAKgEBJAAAAA8AAABRdWFsaWZpZWRO" + "YW1lSW4BAbwmAQAAAAEAAAAAAAAAAAEAKgEBJAAAAA8AAABMb2NhbGl6ZWRUZXh0SW4BAb0mAQAAAAEA" + "AAAAAAAAAAEAKgEBIQAAAAwAAABTdGF0dXNDb2RlSW4BAb4mAQAAAAEAAAAAAAAAAAEAKgEBHgAAAAkA" + "AABWYXJpYW50SW4BAb8mAQAAAAEAAAAAAAAAAAEAKAEBAAAAAQAAAAAAAAABAf////8AAAAAF2CpCgIA" + "AAAAAA8AAABPdXRwdXRBcmd1bWVudHMBAYonAC4ARIonAACWCgAAAAEAKgEBIAAAAAsAAABEYXRlVGlt" + "ZU91dAEBtiYBAAAAAQAAAAAAAAAAAQAqAQEcAAAABwAAAEd1aWRPdXQBAbcmAQAAAAEAAAAAAAAAAAEA" + "KgEBIgAAAA0AAABCeXRlU3RyaW5nT3V0AQG4JgEAAAABAAAAAAAAAAABACoBASIAAAANAAAAWG1sRWxl" + "bWVudE91dAEBuSYBAAAAAQAAAAAAAAAAAQAqAQEeAAAACQAAAE5vZGVJZE91dAEBuiYBAAAAAQAAAAAA" + "AAAAAQAqAQEmAAAAEQAAAEV4cGFuZGVkTm9kZUlkT3V0AQG7JgEAAAABAAAAAAAAAAABACoBASUAAAAQ" + "AAAAUXVhbGlmaWVkTmFtZU91dAEBvCYBAAAAAQAAAAAAAAAAAQAqAQElAAAAEAAAAExvY2FsaXplZFRl" + "eHRPdXQBAb0mAQAAAAEAAAAAAAAAAAEAKgEBIgAAAA0AAABTdGF0dXNDb2RlT3V0AQG+JgEAAAABAAAA" + "AAAAAAABACoBAR8AAAAKAAAAVmFyaWFudE91dAEBvyYBAAAAAQAAAAAAAAAAAQAoAQEAAAABAAAAAAAA" + "AAEB/////wAAAAA="; #endregion #endif #endregion #region Public Properties /// public ScalarValue1MethodState ScalarMethod1 { get => m_scalarMethod1Method; set { if (!ReferenceEquals(m_scalarMethod1Method, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_scalarMethod1Method = value; } } /// public ScalarValue2MethodState ScalarMethod2 { get => m_scalarMethod2Method; set { if (!ReferenceEquals(m_scalarMethod2Method, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_scalarMethod2Method = value; } } /// public ScalarValue3MethodState ScalarMethod3 { get => m_scalarMethod3Method; set { if (!ReferenceEquals(m_scalarMethod3Method, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_scalarMethod3Method = value; } } /// public ArrayValue1MethodState ArrayMethod1 { get => m_arrayMethod1Method; set { if (!ReferenceEquals(m_arrayMethod1Method, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_arrayMethod1Method = value; } } /// public ArrayValue2MethodState ArrayMethod2 { get => m_arrayMethod2Method; set { if (!ReferenceEquals(m_arrayMethod2Method, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_arrayMethod2Method = value; } } /// public ArrayValue3MethodState ArrayMethod3 { get => m_arrayMethod3Method; set { if (!ReferenceEquals(m_arrayMethod3Method, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_arrayMethod3Method = value; } } /// public UserScalarValue1MethodState UserScalarMethod1 { get => m_userScalarMethod1Method; set { if (!ReferenceEquals(m_userScalarMethod1Method, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_userScalarMethod1Method = value; } } /// public UserScalarValue2MethodState UserScalarMethod2 { get => m_userScalarMethod2Method; set { if (!ReferenceEquals(m_userScalarMethod2Method, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_userScalarMethod2Method = value; } } /// public UserArrayValue1MethodState UserArrayMethod1 { get => m_userArrayMethod1Method; set { if (!ReferenceEquals(m_userArrayMethod1Method, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_userArrayMethod1Method = value; } } /// public UserArrayValue2MethodState UserArrayMethod2 { get => m_userArrayMethod2Method; set { if (!ReferenceEquals(m_userArrayMethod2Method, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_userArrayMethod2Method = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_scalarMethod1Method != null) { children.Add(m_scalarMethod1Method); } if (m_scalarMethod2Method != null) { children.Add(m_scalarMethod2Method); } if (m_scalarMethod3Method != null) { children.Add(m_scalarMethod3Method); } if (m_arrayMethod1Method != null) { children.Add(m_arrayMethod1Method); } if (m_arrayMethod2Method != null) { children.Add(m_arrayMethod2Method); } if (m_arrayMethod3Method != null) { children.Add(m_arrayMethod3Method); } if (m_userScalarMethod1Method != null) { children.Add(m_userScalarMethod1Method); } if (m_userScalarMethod2Method != null) { children.Add(m_userScalarMethod2Method); } if (m_userArrayMethod1Method != null) { children.Add(m_userArrayMethod1Method); } if (m_userArrayMethod2Method != null) { children.Add(m_userArrayMethod2Method); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// /// /// /// /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case BrowseNames.ScalarMethod1: { if (createOrReplace && ScalarMethod1 == null) { if (replacement == null) { ScalarMethod1 = new ScalarValue1MethodState(this); } else { ScalarMethod1 = (ScalarValue1MethodState)replacement; } } instance = ScalarMethod1; break; } case BrowseNames.ScalarMethod2: { if (createOrReplace && ScalarMethod2 == null) { if (replacement == null) { ScalarMethod2 = new ScalarValue2MethodState(this); } else { ScalarMethod2 = (ScalarValue2MethodState)replacement; } } instance = ScalarMethod2; break; } case BrowseNames.ScalarMethod3: { if (createOrReplace && ScalarMethod3 == null) { if (replacement == null) { ScalarMethod3 = new ScalarValue3MethodState(this); } else { ScalarMethod3 = (ScalarValue3MethodState)replacement; } } instance = ScalarMethod3; break; } case BrowseNames.ArrayMethod1: { if (createOrReplace && ArrayMethod1 == null) { if (replacement == null) { ArrayMethod1 = new ArrayValue1MethodState(this); } else { ArrayMethod1 = (ArrayValue1MethodState)replacement; } } instance = ArrayMethod1; break; } case BrowseNames.ArrayMethod2: { if (createOrReplace && ArrayMethod2 == null) { if (replacement == null) { ArrayMethod2 = new ArrayValue2MethodState(this); } else { ArrayMethod2 = (ArrayValue2MethodState)replacement; } } instance = ArrayMethod2; break; } case BrowseNames.ArrayMethod3: { if (createOrReplace && ArrayMethod3 == null) { if (replacement == null) { ArrayMethod3 = new ArrayValue3MethodState(this); } else { ArrayMethod3 = (ArrayValue3MethodState)replacement; } } instance = ArrayMethod3; break; } case BrowseNames.UserScalarMethod1: { if (createOrReplace && UserScalarMethod1 == null) { if (replacement == null) { UserScalarMethod1 = new UserScalarValue1MethodState(this); } else { UserScalarMethod1 = (UserScalarValue1MethodState)replacement; } } instance = UserScalarMethod1; break; } case BrowseNames.UserScalarMethod2: { if (createOrReplace && UserScalarMethod2 == null) { if (replacement == null) { UserScalarMethod2 = new UserScalarValue2MethodState(this); } else { UserScalarMethod2 = (UserScalarValue2MethodState)replacement; } } instance = UserScalarMethod2; break; } case BrowseNames.UserArrayMethod1: { if (createOrReplace && UserArrayMethod1 == null) { if (replacement == null) { UserArrayMethod1 = new UserArrayValue1MethodState(this); } else { UserArrayMethod1 = (UserArrayValue1MethodState)replacement; } } instance = UserArrayMethod1; break; } case BrowseNames.UserArrayMethod2: { if (createOrReplace && UserArrayMethod2 == null) { if (replacement == null) { UserArrayMethod2 = new UserArrayValue2MethodState(this); } else { UserArrayMethod2 = (UserArrayValue2MethodState)replacement; } } instance = UserArrayMethod2; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private ScalarValue1MethodState m_scalarMethod1Method; private ScalarValue2MethodState m_scalarMethod2Method; private ScalarValue3MethodState m_scalarMethod3Method; private ArrayValue1MethodState m_arrayMethod1Method; private ArrayValue2MethodState m_arrayMethod2Method; private ArrayValue3MethodState m_arrayMethod3Method; private UserScalarValue1MethodState m_userScalarMethod1Method; private UserScalarValue2MethodState m_userScalarMethod2Method; private UserArrayValue1MethodState m_userArrayMethod1Method; private UserArrayValue2MethodState m_userArrayMethod2Method; #endregion } #endif #endregion #region TestSystemConditionState Class #if (!OPCUA_EXCLUDE_TestSystemConditionState) /// /// Stores an instance of the TestSystemConditionType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCode("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class TestSystemConditionState : ConditionState { #region Constructors /// /// Initializes the type with its default attribute values. /// /// public TestSystemConditionState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return NodeId.Create(ObjectTypes.TestSystemConditionType, Namespaces.TestData, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// /// protected override void Initialize(ISystemContext context) { base.Initialize(context); Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// /// /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAABgAAABodHRwOi8vdGVzdC5vcmcvVUEvRGF0YS//////BGCAAgEAAAABAB8AAABUZXN0U3lzdGVt" + "Q29uZGl0aW9uVHlwZUluc3RhbmNlAQGLJwEBiyeLJwAA/////xYAAAAVYIkKAgAAAAAABwAAAEV2ZW50" + "SWQBAYwnAC4ARIwnAAAAD/////8BAf////8AAAAAFWCJCgIAAAAAAAkAAABFdmVudFR5cGUBAY0nAC4A" + "RI0nAAAAEf////8BAf////8AAAAAFWCJCgIAAAAAAAoAAABTb3VyY2VOb2RlAQGOJwAuAESOJwAAABH/" + "////AQH/////AAAAABVgiQoCAAAAAAAKAAAAU291cmNlTmFtZQEBjycALgBEjycAAAAM/////wEB////" + "/wAAAAAVYIkKAgAAAAAABAAAAFRpbWUBAZAnAC4ARJAnAAABACYB/////wEB/////wAAAAAVYIkKAgAA" + "AAAACwAAAFJlY2VpdmVUaW1lAQGRJwAuAESRJwAAAQAmAf////8BAf////8AAAAAFWCJCgIAAAAAAAcA" + "AABNZXNzYWdlAQGTJwAuAESTJwAAABX/////AQH/////AAAAABVgiQoCAAAAAAAIAAAAU2V2ZXJpdHkB" + "AZQnAC4ARJQnAAAABf////8BAf////8AAAAAFWCJCgIAAAAAABAAAABDb25kaXRpb25DbGFzc0lkAQFI" + "LQAuAERILQAAABH/////AQH/////AAAAABVgiQoCAAAAAAASAAAAQ29uZGl0aW9uQ2xhc3NOYW1lAQFJ" + "LQAuAERJLQAAABX/////AQH/////AAAAABVgiQoCAAAAAAANAAAAQ29uZGl0aW9uTmFtZQEBLC0ALgBE" + "LC0AAAAM/////wEB/////wAAAAAVYIkKAgAAAAAACAAAAEJyYW5jaElkAQGVJwAuAESVJwAAABH/////" + "AQH/////AAAAABVgiQoCAAAAAAAGAAAAUmV0YWluAQGWJwAuAESWJwAAAAH/////AQH/////AAAAABVg" + "iQoCAAAAAAAMAAAARW5hYmxlZFN0YXRlAQGXJwAvAQAjI5cnAAAAFf////8BAf////8BAAAAFWCJCgIA" + "AAAAAAIAAABJZAEBmCcALgBEmCcAAAAB/////wEB/////wAAAAAVYIkKAgAAAAAABwAAAFF1YWxpdHkB" + "AZ0nAC8BACojnScAAAAT/////wEB/////wEAAAAVYIkKAgAAAAAADwAAAFNvdXJjZVRpbWVzdGFtcAEB" + "nicALgBEnicAAAEAJgH/////AQH/////AAAAABVgiQoCAAAAAAAMAAAATGFzdFNldmVyaXR5AQGhJwAv" + "AQAqI6EnAAAABf////8BAf////8BAAAAFWCJCgIAAAAAAA8AAABTb3VyY2VUaW1lc3RhbXABAaInAC4A" + "RKInAAABACYB/////wEB/////wAAAAAVYIkKAgAAAAAABwAAAENvbW1lbnQBAaMnAC8BACojoycAAAAV" + "/////wEB/////wEAAAAVYIkKAgAAAAAADwAAAFNvdXJjZVRpbWVzdGFtcAEBpCcALgBEpCcAAAEAJgH/" + "////AQH/////AAAAABVgiQoCAAAAAAAMAAAAQ2xpZW50VXNlcklkAQGlJwAuAESlJwAAAAz/////AQH/" + "////AAAAAARhggoEAAAAAAAHAAAARGlzYWJsZQEBpycALwEARCOnJwAAAQEBAAAAAQD5CwABAPMKAAAA" + "AARhggoEAAAAAAAGAAAARW5hYmxlAQGmJwAvAQBDI6YnAAABAQEAAAABAPkLAAEA8woAAAAABGGCCgQA" + "AAAAAAoAAABBZGRDb21tZW50AQGoJwAvAQBFI6gnAAABAQEAAAABAPkLAAEADQsBAAAAF2CpCgIAAAAA" + "AA4AAABJbnB1dEFyZ3VtZW50cwEBqScALgBEqScAAJYCAAAAAQAqAQFGAAAABwAAAEV2ZW50SWQAD///" + "//8AAAAAAwAAAAAoAAAAVGhlIGlkZW50aWZpZXIgZm9yIHRoZSBldmVudCB0byBjb21tZW50LgEAKgEB" + "QgAAAAcAAABDb21tZW50ABX/////AAAAAAMAAAAAJAAAAFRoZSBjb21tZW50IHRvIGFkZCB0byB0aGUg" + "Y29uZGl0aW9uLgEAKAEBAAAAAQAAAAAAAAABAf////8AAAAAFWCJCgIAAAABABIAAABNb25pdG9yZWRO" + "b2RlQ291bnQBAawnAC4ARKwnAAAABv////8BAf////8AAAAA"; #endregion #endif #endregion #region Public Properties /// public PropertyState MonitoredNodeCount { get => m_monitoredNodeCount; set { if (!ReferenceEquals(m_monitoredNodeCount, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_monitoredNodeCount = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_monitoredNodeCount != null) { children.Add(m_monitoredNodeCount); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// /// /// /// /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case BrowseNames.MonitoredNodeCount: { if (createOrReplace && MonitoredNodeCount == null) { if (replacement == null) { MonitoredNodeCount = new PropertyState(this); } else { MonitoredNodeCount = (PropertyState)replacement; } } instance = MonitoredNodeCount; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private PropertyState m_monitoredNodeCount; #endregion } #endif #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/TestData/Design/TestData.Constants.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2021 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; namespace TestData { #region DataType Identifiers /// /// A class that declares constants for all DataTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class DataTypes { /// /// The identifier for the ScalarValueDataType DataType. /// public const uint ScalarValueDataType = 9440; /// /// The identifier for the ArrayValueDataType DataType. /// public const uint ArrayValueDataType = 9669; /// /// The identifier for the BooleanDataType DataType. /// public const uint BooleanDataType = 9898; /// /// The identifier for the SByteDataType DataType. /// public const uint SByteDataType = 9899; /// /// The identifier for the ByteDataType DataType. /// public const uint ByteDataType = 9900; /// /// The identifier for the Int16DataType DataType. /// public const uint Int16DataType = 9901; /// /// The identifier for the UInt16DataType DataType. /// public const uint UInt16DataType = 9902; /// /// The identifier for the Int32DataType DataType. /// public const uint Int32DataType = 9903; /// /// The identifier for the UInt32DataType DataType. /// public const uint UInt32DataType = 9904; /// /// The identifier for the Int64DataType DataType. /// public const uint Int64DataType = 9905; /// /// The identifier for the UInt64DataType DataType. /// public const uint UInt64DataType = 9906; /// /// The identifier for the FloatDataType DataType. /// public const uint FloatDataType = 9907; /// /// The identifier for the DoubleDataType DataType. /// public const uint DoubleDataType = 9908; /// /// The identifier for the StringDataType DataType. /// public const uint StringDataType = 9909; /// /// The identifier for the DateTimeDataType DataType. /// public const uint DateTimeDataType = 9910; /// /// The identifier for the GuidDataType DataType. /// public const uint GuidDataType = 9911; /// /// The identifier for the ByteStringDataType DataType. /// public const uint ByteStringDataType = 9912; /// /// The identifier for the XmlElementDataType DataType. /// public const uint XmlElementDataType = 9913; /// /// The identifier for the NodeIdDataType DataType. /// public const uint NodeIdDataType = 9914; /// /// The identifier for the ExpandedNodeIdDataType DataType. /// public const uint ExpandedNodeIdDataType = 9915; /// /// The identifier for the QualifiedNameDataType DataType. /// public const uint QualifiedNameDataType = 9916; /// /// The identifier for the LocalizedTextDataType DataType. /// public const uint LocalizedTextDataType = 9917; /// /// The identifier for the StatusCodeDataType DataType. /// public const uint StatusCodeDataType = 9918; /// /// The identifier for the VariantDataType DataType. /// public const uint VariantDataType = 9919; /// /// The identifier for the UserScalarValueDataType DataType. /// public const uint UserScalarValueDataType = 9920; /// /// The identifier for the UserArrayValueDataType DataType. /// public const uint UserArrayValueDataType = 10006; /// /// The identifier for the Vector DataType. /// public const uint Vector = 1000; /// /// The identifier for the WorkOrderStatusType DataType. /// public const uint WorkOrderStatusType = 1004; /// /// The identifier for the WorkOrderType DataType. /// public const uint WorkOrderType = 1005; } #endregion #region Method Identifiers /// /// A class that declares constants for all Methods in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Methods { /// /// The identifier for the TestDataObjectType_GenerateValues Method. /// public const uint TestDataObjectType_GenerateValues = 9385; /// /// The identifier for the TestDataObjectType_CycleComplete_Disable Method. /// public const uint TestDataObjectType_CycleComplete_Disable = 9415; /// /// The identifier for the TestDataObjectType_CycleComplete_Enable Method. /// public const uint TestDataObjectType_CycleComplete_Enable = 9414; /// /// The identifier for the TestDataObjectType_CycleComplete_AddComment Method. /// public const uint TestDataObjectType_CycleComplete_AddComment = 9416; /// /// The identifier for the TestDataObjectType_CycleComplete_Acknowledge Method. /// public const uint TestDataObjectType_CycleComplete_Acknowledge = 9436; /// /// The identifier for the ScalarValueObjectType_CycleComplete_Disable Method. /// public const uint ScalarValueObjectType_CycleComplete_Disable = 9482; /// /// The identifier for the ScalarValueObjectType_CycleComplete_Enable Method. /// public const uint ScalarValueObjectType_CycleComplete_Enable = 9481; /// /// The identifier for the ScalarValueObjectType_CycleComplete_AddComment Method. /// public const uint ScalarValueObjectType_CycleComplete_AddComment = 9483; /// /// The identifier for the ScalarValueObjectType_CycleComplete_Acknowledge Method. /// public const uint ScalarValueObjectType_CycleComplete_Acknowledge = 9503; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Disable Method. /// public const uint AnalogScalarValueObjectType_CycleComplete_Disable = 9566; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Enable Method. /// public const uint AnalogScalarValueObjectType_CycleComplete_Enable = 9565; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_AddComment Method. /// public const uint AnalogScalarValueObjectType_CycleComplete_AddComment = 9567; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Acknowledge Method. /// public const uint AnalogScalarValueObjectType_CycleComplete_Acknowledge = 9587; /// /// The identifier for the ArrayValueObjectType_CycleComplete_Disable Method. /// public const uint ArrayValueObjectType_CycleComplete_Disable = 9711; /// /// The identifier for the ArrayValueObjectType_CycleComplete_Enable Method. /// public const uint ArrayValueObjectType_CycleComplete_Enable = 9710; /// /// The identifier for the ArrayValueObjectType_CycleComplete_AddComment Method. /// public const uint ArrayValueObjectType_CycleComplete_AddComment = 9712; /// /// The identifier for the ArrayValueObjectType_CycleComplete_Acknowledge Method. /// public const uint ArrayValueObjectType_CycleComplete_Acknowledge = 9732; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Disable Method. /// public const uint AnalogArrayValueObjectType_CycleComplete_Disable = 9795; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Enable Method. /// public const uint AnalogArrayValueObjectType_CycleComplete_Enable = 9794; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_AddComment Method. /// public const uint AnalogArrayValueObjectType_CycleComplete_AddComment = 9796; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Acknowledge Method. /// public const uint AnalogArrayValueObjectType_CycleComplete_Acknowledge = 9816; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Disable Method. /// public const uint UserScalarValueObjectType_CycleComplete_Disable = 9953; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Enable Method. /// public const uint UserScalarValueObjectType_CycleComplete_Enable = 9952; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_AddComment Method. /// public const uint UserScalarValueObjectType_CycleComplete_AddComment = 9954; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Acknowledge Method. /// public const uint UserScalarValueObjectType_CycleComplete_Acknowledge = 9974; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Disable Method. /// public const uint UserArrayValueObjectType_CycleComplete_Disable = 10039; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Enable Method. /// public const uint UserArrayValueObjectType_CycleComplete_Enable = 10038; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_AddComment Method. /// public const uint UserArrayValueObjectType_CycleComplete_AddComment = 10040; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Acknowledge Method. /// public const uint UserArrayValueObjectType_CycleComplete_Acknowledge = 10060; /// /// The identifier for the MethodTestType_ScalarMethod1 Method. /// public const uint MethodTestType_ScalarMethod1 = 10093; /// /// The identifier for the MethodTestType_ScalarMethod2 Method. /// public const uint MethodTestType_ScalarMethod2 = 10096; /// /// The identifier for the MethodTestType_ScalarMethod3 Method. /// public const uint MethodTestType_ScalarMethod3 = 10099; /// /// The identifier for the MethodTestType_ArrayMethod1 Method. /// public const uint MethodTestType_ArrayMethod1 = 10102; /// /// The identifier for the MethodTestType_ArrayMethod2 Method. /// public const uint MethodTestType_ArrayMethod2 = 10105; /// /// The identifier for the MethodTestType_ArrayMethod3 Method. /// public const uint MethodTestType_ArrayMethod3 = 10108; /// /// The identifier for the MethodTestType_UserScalarMethod1 Method. /// public const uint MethodTestType_UserScalarMethod1 = 10111; /// /// The identifier for the MethodTestType_UserScalarMethod2 Method. /// public const uint MethodTestType_UserScalarMethod2 = 10114; /// /// The identifier for the MethodTestType_UserArrayMethod1 Method. /// public const uint MethodTestType_UserArrayMethod1 = 10117; /// /// The identifier for the MethodTestType_UserArrayMethod2 Method. /// public const uint MethodTestType_UserArrayMethod2 = 10120; /// /// The identifier for the Data_Static_Scalar_GenerateValues Method. /// public const uint Data_Static_Scalar_GenerateValues = 10161; /// /// The identifier for the Data_Static_Scalar_CycleComplete_Disable Method. /// public const uint Data_Static_Scalar_CycleComplete_Disable = 10191; /// /// The identifier for the Data_Static_Scalar_CycleComplete_Enable Method. /// public const uint Data_Static_Scalar_CycleComplete_Enable = 10190; /// /// The identifier for the Data_Static_Scalar_CycleComplete_AddComment Method. /// public const uint Data_Static_Scalar_CycleComplete_AddComment = 10192; /// /// The identifier for the Data_Static_Scalar_CycleComplete_Acknowledge Method. /// public const uint Data_Static_Scalar_CycleComplete_Acknowledge = 10212; /// /// The identifier for the Data_Static_Array_GenerateValues Method. /// public const uint Data_Static_Array_GenerateValues = 10245; /// /// The identifier for the Data_Static_Array_CycleComplete_Disable Method. /// public const uint Data_Static_Array_CycleComplete_Disable = 10275; /// /// The identifier for the Data_Static_Array_CycleComplete_Enable Method. /// public const uint Data_Static_Array_CycleComplete_Enable = 10274; /// /// The identifier for the Data_Static_Array_CycleComplete_AddComment Method. /// public const uint Data_Static_Array_CycleComplete_AddComment = 10276; /// /// The identifier for the Data_Static_Array_CycleComplete_Acknowledge Method. /// public const uint Data_Static_Array_CycleComplete_Acknowledge = 10296; /// /// The identifier for the Data_Static_UserScalar_GenerateValues Method. /// public const uint Data_Static_UserScalar_GenerateValues = 10329; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Disable Method. /// public const uint Data_Static_UserScalar_CycleComplete_Disable = 10359; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Enable Method. /// public const uint Data_Static_UserScalar_CycleComplete_Enable = 10358; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_AddComment Method. /// public const uint Data_Static_UserScalar_CycleComplete_AddComment = 10360; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Acknowledge Method. /// public const uint Data_Static_UserScalar_CycleComplete_Acknowledge = 10380; /// /// The identifier for the Data_Static_UserArray_GenerateValues Method. /// public const uint Data_Static_UserArray_GenerateValues = 10408; /// /// The identifier for the Data_Static_UserArray_CycleComplete_Disable Method. /// public const uint Data_Static_UserArray_CycleComplete_Disable = 10438; /// /// The identifier for the Data_Static_UserArray_CycleComplete_Enable Method. /// public const uint Data_Static_UserArray_CycleComplete_Enable = 10437; /// /// The identifier for the Data_Static_UserArray_CycleComplete_AddComment Method. /// public const uint Data_Static_UserArray_CycleComplete_AddComment = 10439; /// /// The identifier for the Data_Static_UserArray_CycleComplete_Acknowledge Method. /// public const uint Data_Static_UserArray_CycleComplete_Acknowledge = 10459; /// /// The identifier for the Data_Static_AnalogScalar_GenerateValues Method. /// public const uint Data_Static_AnalogScalar_GenerateValues = 10487; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Disable Method. /// public const uint Data_Static_AnalogScalar_CycleComplete_Disable = 10517; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Enable Method. /// public const uint Data_Static_AnalogScalar_CycleComplete_Enable = 10516; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_AddComment Method. /// public const uint Data_Static_AnalogScalar_CycleComplete_AddComment = 10518; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Acknowledge Method. /// public const uint Data_Static_AnalogScalar_CycleComplete_Acknowledge = 10538; /// /// The identifier for the Data_Static_AnalogArray_GenerateValues Method. /// public const uint Data_Static_AnalogArray_GenerateValues = 10622; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Disable Method. /// public const uint Data_Static_AnalogArray_CycleComplete_Disable = 10652; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Enable Method. /// public const uint Data_Static_AnalogArray_CycleComplete_Enable = 10651; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_AddComment Method. /// public const uint Data_Static_AnalogArray_CycleComplete_AddComment = 10653; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Acknowledge Method. /// public const uint Data_Static_AnalogArray_CycleComplete_Acknowledge = 10673; /// /// The identifier for the Data_Static_MethodTest_ScalarMethod1 Method. /// public const uint Data_Static_MethodTest_ScalarMethod1 = 10756; /// /// The identifier for the Data_Static_MethodTest_ScalarMethod2 Method. /// public const uint Data_Static_MethodTest_ScalarMethod2 = 10759; /// /// The identifier for the Data_Static_MethodTest_ScalarMethod3 Method. /// public const uint Data_Static_MethodTest_ScalarMethod3 = 10762; /// /// The identifier for the Data_Static_MethodTest_ArrayMethod1 Method. /// public const uint Data_Static_MethodTest_ArrayMethod1 = 10765; /// /// The identifier for the Data_Static_MethodTest_ArrayMethod2 Method. /// public const uint Data_Static_MethodTest_ArrayMethod2 = 10768; /// /// The identifier for the Data_Static_MethodTest_ArrayMethod3 Method. /// public const uint Data_Static_MethodTest_ArrayMethod3 = 10771; /// /// The identifier for the Data_Static_MethodTest_UserScalarMethod1 Method. /// public const uint Data_Static_MethodTest_UserScalarMethod1 = 10774; /// /// The identifier for the Data_Static_MethodTest_UserScalarMethod2 Method. /// public const uint Data_Static_MethodTest_UserScalarMethod2 = 10777; /// /// The identifier for the Data_Static_MethodTest_UserArrayMethod1 Method. /// public const uint Data_Static_MethodTest_UserArrayMethod1 = 10780; /// /// The identifier for the Data_Static_MethodTest_UserArrayMethod2 Method. /// public const uint Data_Static_MethodTest_UserArrayMethod2 = 10783; /// /// The identifier for the Data_Dynamic_Scalar_GenerateValues Method. /// public const uint Data_Dynamic_Scalar_GenerateValues = 10789; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Disable Method. /// public const uint Data_Dynamic_Scalar_CycleComplete_Disable = 10819; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Enable Method. /// public const uint Data_Dynamic_Scalar_CycleComplete_Enable = 10818; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_AddComment Method. /// public const uint Data_Dynamic_Scalar_CycleComplete_AddComment = 10820; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Acknowledge Method. /// public const uint Data_Dynamic_Scalar_CycleComplete_Acknowledge = 10840; /// /// The identifier for the Data_Dynamic_Array_GenerateValues Method. /// public const uint Data_Dynamic_Array_GenerateValues = 10873; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Disable Method. /// public const uint Data_Dynamic_Array_CycleComplete_Disable = 10903; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Enable Method. /// public const uint Data_Dynamic_Array_CycleComplete_Enable = 10902; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_AddComment Method. /// public const uint Data_Dynamic_Array_CycleComplete_AddComment = 10904; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Acknowledge Method. /// public const uint Data_Dynamic_Array_CycleComplete_Acknowledge = 10924; /// /// The identifier for the Data_Dynamic_UserScalar_GenerateValues Method. /// public const uint Data_Dynamic_UserScalar_GenerateValues = 10957; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Disable Method. /// public const uint Data_Dynamic_UserScalar_CycleComplete_Disable = 10987; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Enable Method. /// public const uint Data_Dynamic_UserScalar_CycleComplete_Enable = 10986; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_AddComment Method. /// public const uint Data_Dynamic_UserScalar_CycleComplete_AddComment = 10988; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Acknowledge Method. /// public const uint Data_Dynamic_UserScalar_CycleComplete_Acknowledge = 11008; /// /// The identifier for the Data_Dynamic_UserArray_GenerateValues Method. /// public const uint Data_Dynamic_UserArray_GenerateValues = 11036; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Disable Method. /// public const uint Data_Dynamic_UserArray_CycleComplete_Disable = 11066; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Enable Method. /// public const uint Data_Dynamic_UserArray_CycleComplete_Enable = 11065; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_AddComment Method. /// public const uint Data_Dynamic_UserArray_CycleComplete_AddComment = 11067; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Acknowledge Method. /// public const uint Data_Dynamic_UserArray_CycleComplete_Acknowledge = 11087; /// /// The identifier for the Data_Dynamic_AnalogScalar_GenerateValues Method. /// public const uint Data_Dynamic_AnalogScalar_GenerateValues = 11115; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Disable Method. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_Disable = 11145; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Enable Method. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_Enable = 11144; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_AddComment Method. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_AddComment = 11146; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Acknowledge Method. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_Acknowledge = 11166; /// /// The identifier for the Data_Dynamic_AnalogArray_GenerateValues Method. /// public const uint Data_Dynamic_AnalogArray_GenerateValues = 11250; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Disable Method. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_Disable = 11280; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Enable Method. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_Enable = 11279; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_AddComment Method. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_AddComment = 11281; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Acknowledge Method. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_Acknowledge = 11301; /// /// The identifier for the Data_Conditions_SystemStatus_Disable Method. /// public const uint Data_Conditions_SystemStatus_Disable = 11412; /// /// The identifier for the Data_Conditions_SystemStatus_Enable Method. /// public const uint Data_Conditions_SystemStatus_Enable = 11411; /// /// The identifier for the Data_Conditions_SystemStatus_AddComment Method. /// public const uint Data_Conditions_SystemStatus_AddComment = 11413; } #endregion #region Object Identifiers /// /// A class that declares constants for all Objects in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Objects { /// /// The identifier for the TestDataObjectType_CycleComplete Object. /// public const uint TestDataObjectType_CycleComplete = 9387; /// /// The identifier for the Data Object. /// public const uint Data = 10157; /// /// The identifier for the Data_Static Object. /// public const uint Data_Static = 10158; /// /// The identifier for the Data_Static_Scalar Object. /// public const uint Data_Static_Scalar = 10159; /// /// The identifier for the Data_Static_Scalar_CycleComplete Object. /// public const uint Data_Static_Scalar_CycleComplete = 10163; /// /// The identifier for the Data_Static_Array Object. /// public const uint Data_Static_Array = 10243; /// /// The identifier for the Data_Static_Array_CycleComplete Object. /// public const uint Data_Static_Array_CycleComplete = 10247; /// /// The identifier for the Data_Static_UserScalar Object. /// public const uint Data_Static_UserScalar = 10327; /// /// The identifier for the Data_Static_UserScalar_CycleComplete Object. /// public const uint Data_Static_UserScalar_CycleComplete = 10331; /// /// The identifier for the Data_Static_UserArray Object. /// public const uint Data_Static_UserArray = 10406; /// /// The identifier for the Data_Static_UserArray_CycleComplete Object. /// public const uint Data_Static_UserArray_CycleComplete = 10410; /// /// The identifier for the Data_Static_AnalogScalar Object. /// public const uint Data_Static_AnalogScalar = 10485; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete Object. /// public const uint Data_Static_AnalogScalar_CycleComplete = 10489; /// /// The identifier for the Data_Static_AnalogArray Object. /// public const uint Data_Static_AnalogArray = 10620; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete Object. /// public const uint Data_Static_AnalogArray_CycleComplete = 10624; /// /// The identifier for the Data_Static_MethodTest Object. /// public const uint Data_Static_MethodTest = 10755; /// /// The identifier for the Data_Dynamic Object. /// public const uint Data_Dynamic = 10786; /// /// The identifier for the Data_Dynamic_Scalar Object. /// public const uint Data_Dynamic_Scalar = 10787; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete Object. /// public const uint Data_Dynamic_Scalar_CycleComplete = 10791; /// /// The identifier for the Data_Dynamic_Array Object. /// public const uint Data_Dynamic_Array = 10871; /// /// The identifier for the Data_Dynamic_Array_CycleComplete Object. /// public const uint Data_Dynamic_Array_CycleComplete = 10875; /// /// The identifier for the Data_Dynamic_UserScalar Object. /// public const uint Data_Dynamic_UserScalar = 10955; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete Object. /// public const uint Data_Dynamic_UserScalar_CycleComplete = 10959; /// /// The identifier for the Data_Dynamic_UserArray Object. /// public const uint Data_Dynamic_UserArray = 11034; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete Object. /// public const uint Data_Dynamic_UserArray_CycleComplete = 11038; /// /// The identifier for the Data_Dynamic_AnalogScalar Object. /// public const uint Data_Dynamic_AnalogScalar = 11113; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete Object. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete = 11117; /// /// The identifier for the Data_Dynamic_AnalogArray Object. /// public const uint Data_Dynamic_AnalogArray = 11248; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete Object. /// public const uint Data_Dynamic_AnalogArray_CycleComplete = 11252; /// /// The identifier for the Data_Conditions Object. /// public const uint Data_Conditions = 11383; /// /// The identifier for the Data_Conditions_SystemStatus Object. /// public const uint Data_Conditions_SystemStatus = 11384; /// /// The identifier for the ScalarValueDataType_Encoding_DefaultBinary Object. /// public const uint ScalarValueDataType_Encoding_DefaultBinary = 11437; /// /// The identifier for the ArrayValueDataType_Encoding_DefaultBinary Object. /// public const uint ArrayValueDataType_Encoding_DefaultBinary = 11438; /// /// The identifier for the UserScalarValueDataType_Encoding_DefaultBinary Object. /// public const uint UserScalarValueDataType_Encoding_DefaultBinary = 11439; /// /// The identifier for the UserArrayValueDataType_Encoding_DefaultBinary Object. /// public const uint UserArrayValueDataType_Encoding_DefaultBinary = 11440; /// /// The identifier for the Vector_Encoding_DefaultBinary Object. /// public const uint Vector_Encoding_DefaultBinary = 1008; /// /// The identifier for the WorkOrderStatusType_Encoding_DefaultBinary Object. /// public const uint WorkOrderStatusType_Encoding_DefaultBinary = 1011; /// /// The identifier for the WorkOrderType_Encoding_DefaultBinary Object. /// public const uint WorkOrderType_Encoding_DefaultBinary = 1012; /// /// The identifier for the ScalarValueDataType_Encoding_DefaultXml Object. /// public const uint ScalarValueDataType_Encoding_DefaultXml = 11418; /// /// The identifier for the ArrayValueDataType_Encoding_DefaultXml Object. /// public const uint ArrayValueDataType_Encoding_DefaultXml = 11419; /// /// The identifier for the UserScalarValueDataType_Encoding_DefaultXml Object. /// public const uint UserScalarValueDataType_Encoding_DefaultXml = 11420; /// /// The identifier for the UserArrayValueDataType_Encoding_DefaultXml Object. /// public const uint UserArrayValueDataType_Encoding_DefaultXml = 11421; /// /// The identifier for the Vector_Encoding_DefaultXml Object. /// public const uint Vector_Encoding_DefaultXml = 36; /// /// The identifier for the WorkOrderStatusType_Encoding_DefaultXml Object. /// public const uint WorkOrderStatusType_Encoding_DefaultXml = 39; /// /// The identifier for the WorkOrderType_Encoding_DefaultXml Object. /// public const uint WorkOrderType_Encoding_DefaultXml = 40; /// /// The identifier for the ScalarValueDataType_Encoding_DefaultJson Object. /// public const uint ScalarValueDataType_Encoding_DefaultJson = 15047; /// /// The identifier for the ArrayValueDataType_Encoding_DefaultJson Object. /// public const uint ArrayValueDataType_Encoding_DefaultJson = 15048; /// /// The identifier for the UserScalarValueDataType_Encoding_DefaultJson Object. /// public const uint UserScalarValueDataType_Encoding_DefaultJson = 15049; /// /// The identifier for the UserArrayValueDataType_Encoding_DefaultJson Object. /// public const uint UserArrayValueDataType_Encoding_DefaultJson = 15050; /// /// The identifier for the Vector_Encoding_DefaultJson Object. /// public const uint Vector_Encoding_DefaultJson = 64; /// /// The identifier for the WorkOrderStatusType_Encoding_DefaultJson Object. /// public const uint WorkOrderStatusType_Encoding_DefaultJson = 67; /// /// The identifier for the WorkOrderType_Encoding_DefaultJson Object. /// public const uint WorkOrderType_Encoding_DefaultJson = 68; } #endregion #region ObjectType Identifiers /// /// A class that declares constants for all ObjectTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectTypes { /// /// The identifier for the GenerateValuesEventType ObjectType. /// public const uint GenerateValuesEventType = 9371; /// /// The identifier for the TestDataObjectType ObjectType. /// public const uint TestDataObjectType = 9383; /// /// The identifier for the ScalarValueObjectType ObjectType. /// public const uint ScalarValueObjectType = 9450; /// /// The identifier for the AnalogScalarValueObjectType ObjectType. /// public const uint AnalogScalarValueObjectType = 9534; /// /// The identifier for the ArrayValueObjectType ObjectType. /// public const uint ArrayValueObjectType = 9679; /// /// The identifier for the AnalogArrayValueObjectType ObjectType. /// public const uint AnalogArrayValueObjectType = 9763; /// /// The identifier for the UserScalarValueObjectType ObjectType. /// public const uint UserScalarValueObjectType = 9921; /// /// The identifier for the UserArrayValueObjectType ObjectType. /// public const uint UserArrayValueObjectType = 10007; /// /// The identifier for the MethodTestType ObjectType. /// public const uint MethodTestType = 10092; /// /// The identifier for the TestSystemConditionType ObjectType. /// public const uint TestSystemConditionType = 10123; } #endregion #region Variable Identifiers /// /// A class that declares constants for all Variables in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Variables { /// /// The identifier for the GenerateValuesEventType_Iterations Variable. /// public const uint GenerateValuesEventType_Iterations = 9381; /// /// The identifier for the GenerateValuesEventType_NewValueCount Variable. /// public const uint GenerateValuesEventType_NewValueCount = 9382; /// /// The identifier for the TestDataObjectType_SimulationActive Variable. /// public const uint TestDataObjectType_SimulationActive = 9384; /// /// The identifier for the TestDataObjectType_GenerateValues_InputArguments Variable. /// public const uint TestDataObjectType_GenerateValues_InputArguments = 9386; /// /// The identifier for the TestDataObjectType_CycleComplete_EventId Variable. /// public const uint TestDataObjectType_CycleComplete_EventId = 9388; /// /// The identifier for the TestDataObjectType_CycleComplete_EventType Variable. /// public const uint TestDataObjectType_CycleComplete_EventType = 9389; /// /// The identifier for the TestDataObjectType_CycleComplete_SourceNode Variable. /// public const uint TestDataObjectType_CycleComplete_SourceNode = 9390; /// /// The identifier for the TestDataObjectType_CycleComplete_SourceName Variable. /// public const uint TestDataObjectType_CycleComplete_SourceName = 9391; /// /// The identifier for the TestDataObjectType_CycleComplete_Time Variable. /// public const uint TestDataObjectType_CycleComplete_Time = 9392; /// /// The identifier for the TestDataObjectType_CycleComplete_ReceiveTime Variable. /// public const uint TestDataObjectType_CycleComplete_ReceiveTime = 9393; /// /// The identifier for the TestDataObjectType_CycleComplete_Message Variable. /// public const uint TestDataObjectType_CycleComplete_Message = 9395; /// /// The identifier for the TestDataObjectType_CycleComplete_Severity Variable. /// public const uint TestDataObjectType_CycleComplete_Severity = 9396; /// /// The identifier for the TestDataObjectType_CycleComplete_ConditionClassId Variable. /// public const uint TestDataObjectType_CycleComplete_ConditionClassId = 11578; /// /// The identifier for the TestDataObjectType_CycleComplete_ConditionClassName Variable. /// public const uint TestDataObjectType_CycleComplete_ConditionClassName = 11579; /// /// The identifier for the TestDataObjectType_CycleComplete_ConditionName Variable. /// public const uint TestDataObjectType_CycleComplete_ConditionName = 11557; /// /// The identifier for the TestDataObjectType_CycleComplete_BranchId Variable. /// public const uint TestDataObjectType_CycleComplete_BranchId = 9397; /// /// The identifier for the TestDataObjectType_CycleComplete_Retain Variable. /// public const uint TestDataObjectType_CycleComplete_Retain = 9398; /// /// The identifier for the TestDataObjectType_CycleComplete_EnabledState Variable. /// public const uint TestDataObjectType_CycleComplete_EnabledState = 9399; /// /// The identifier for the TestDataObjectType_CycleComplete_EnabledState_Id Variable. /// public const uint TestDataObjectType_CycleComplete_EnabledState_Id = 9400; /// /// The identifier for the TestDataObjectType_CycleComplete_Quality Variable. /// public const uint TestDataObjectType_CycleComplete_Quality = 9405; /// /// The identifier for the TestDataObjectType_CycleComplete_Quality_SourceTimestamp Variable. /// public const uint TestDataObjectType_CycleComplete_Quality_SourceTimestamp = 9406; /// /// The identifier for the TestDataObjectType_CycleComplete_LastSeverity Variable. /// public const uint TestDataObjectType_CycleComplete_LastSeverity = 9409; /// /// The identifier for the TestDataObjectType_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public const uint TestDataObjectType_CycleComplete_LastSeverity_SourceTimestamp = 9410; /// /// The identifier for the TestDataObjectType_CycleComplete_Comment Variable. /// public const uint TestDataObjectType_CycleComplete_Comment = 9411; /// /// The identifier for the TestDataObjectType_CycleComplete_Comment_SourceTimestamp Variable. /// public const uint TestDataObjectType_CycleComplete_Comment_SourceTimestamp = 9412; /// /// The identifier for the TestDataObjectType_CycleComplete_ClientUserId Variable. /// public const uint TestDataObjectType_CycleComplete_ClientUserId = 9413; /// /// The identifier for the TestDataObjectType_CycleComplete_AddComment_InputArguments Variable. /// public const uint TestDataObjectType_CycleComplete_AddComment_InputArguments = 9417; /// /// The identifier for the TestDataObjectType_CycleComplete_AckedState Variable. /// public const uint TestDataObjectType_CycleComplete_AckedState = 9420; /// /// The identifier for the TestDataObjectType_CycleComplete_AckedState_Id Variable. /// public const uint TestDataObjectType_CycleComplete_AckedState_Id = 9421; /// /// The identifier for the TestDataObjectType_CycleComplete_ConfirmedState_Id Variable. /// public const uint TestDataObjectType_CycleComplete_ConfirmedState_Id = 9429; /// /// The identifier for the TestDataObjectType_CycleComplete_Acknowledge_InputArguments Variable. /// public const uint TestDataObjectType_CycleComplete_Acknowledge_InputArguments = 9437; /// /// The identifier for the TestDataObjectType_CycleComplete_Confirm_InputArguments Variable. /// public const uint TestDataObjectType_CycleComplete_Confirm_InputArguments = 9439; /// /// The identifier for the ScalarValueObjectType_GenerateValues_InputArguments Variable. /// public const uint ScalarValueObjectType_GenerateValues_InputArguments = 9453; /// /// The identifier for the ScalarValueObjectType_CycleComplete_EventId Variable. /// public const uint ScalarValueObjectType_CycleComplete_EventId = 9455; /// /// The identifier for the ScalarValueObjectType_CycleComplete_EventType Variable. /// public const uint ScalarValueObjectType_CycleComplete_EventType = 9456; /// /// The identifier for the ScalarValueObjectType_CycleComplete_SourceNode Variable. /// public const uint ScalarValueObjectType_CycleComplete_SourceNode = 9457; /// /// The identifier for the ScalarValueObjectType_CycleComplete_SourceName Variable. /// public const uint ScalarValueObjectType_CycleComplete_SourceName = 9458; /// /// The identifier for the ScalarValueObjectType_CycleComplete_Time Variable. /// public const uint ScalarValueObjectType_CycleComplete_Time = 9459; /// /// The identifier for the ScalarValueObjectType_CycleComplete_ReceiveTime Variable. /// public const uint ScalarValueObjectType_CycleComplete_ReceiveTime = 9460; /// /// The identifier for the ScalarValueObjectType_CycleComplete_Message Variable. /// public const uint ScalarValueObjectType_CycleComplete_Message = 9462; /// /// The identifier for the ScalarValueObjectType_CycleComplete_Severity Variable. /// public const uint ScalarValueObjectType_CycleComplete_Severity = 9463; /// /// The identifier for the ScalarValueObjectType_CycleComplete_ConditionClassId Variable. /// public const uint ScalarValueObjectType_CycleComplete_ConditionClassId = 11580; /// /// The identifier for the ScalarValueObjectType_CycleComplete_ConditionClassName Variable. /// public const uint ScalarValueObjectType_CycleComplete_ConditionClassName = 11581; /// /// The identifier for the ScalarValueObjectType_CycleComplete_ConditionName Variable. /// public const uint ScalarValueObjectType_CycleComplete_ConditionName = 11558; /// /// The identifier for the ScalarValueObjectType_CycleComplete_BranchId Variable. /// public const uint ScalarValueObjectType_CycleComplete_BranchId = 9464; /// /// The identifier for the ScalarValueObjectType_CycleComplete_Retain Variable. /// public const uint ScalarValueObjectType_CycleComplete_Retain = 9465; /// /// The identifier for the ScalarValueObjectType_CycleComplete_EnabledState Variable. /// public const uint ScalarValueObjectType_CycleComplete_EnabledState = 9466; /// /// The identifier for the ScalarValueObjectType_CycleComplete_EnabledState_Id Variable. /// public const uint ScalarValueObjectType_CycleComplete_EnabledState_Id = 9467; /// /// The identifier for the ScalarValueObjectType_CycleComplete_Quality Variable. /// public const uint ScalarValueObjectType_CycleComplete_Quality = 9472; /// /// The identifier for the ScalarValueObjectType_CycleComplete_Quality_SourceTimestamp Variable. /// public const uint ScalarValueObjectType_CycleComplete_Quality_SourceTimestamp = 9473; /// /// The identifier for the ScalarValueObjectType_CycleComplete_LastSeverity Variable. /// public const uint ScalarValueObjectType_CycleComplete_LastSeverity = 9476; /// /// The identifier for the ScalarValueObjectType_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public const uint ScalarValueObjectType_CycleComplete_LastSeverity_SourceTimestamp = 9477; /// /// The identifier for the ScalarValueObjectType_CycleComplete_Comment Variable. /// public const uint ScalarValueObjectType_CycleComplete_Comment = 9478; /// /// The identifier for the ScalarValueObjectType_CycleComplete_Comment_SourceTimestamp Variable. /// public const uint ScalarValueObjectType_CycleComplete_Comment_SourceTimestamp = 9479; /// /// The identifier for the ScalarValueObjectType_CycleComplete_ClientUserId Variable. /// public const uint ScalarValueObjectType_CycleComplete_ClientUserId = 9480; /// /// The identifier for the ScalarValueObjectType_CycleComplete_AddComment_InputArguments Variable. /// public const uint ScalarValueObjectType_CycleComplete_AddComment_InputArguments = 9484; /// /// The identifier for the ScalarValueObjectType_CycleComplete_AckedState Variable. /// public const uint ScalarValueObjectType_CycleComplete_AckedState = 9487; /// /// The identifier for the ScalarValueObjectType_CycleComplete_AckedState_Id Variable. /// public const uint ScalarValueObjectType_CycleComplete_AckedState_Id = 9488; /// /// The identifier for the ScalarValueObjectType_CycleComplete_ConfirmedState_Id Variable. /// public const uint ScalarValueObjectType_CycleComplete_ConfirmedState_Id = 9496; /// /// The identifier for the ScalarValueObjectType_CycleComplete_Acknowledge_InputArguments Variable. /// public const uint ScalarValueObjectType_CycleComplete_Acknowledge_InputArguments = 9504; /// /// The identifier for the ScalarValueObjectType_CycleComplete_Confirm_InputArguments Variable. /// public const uint ScalarValueObjectType_CycleComplete_Confirm_InputArguments = 9506; /// /// The identifier for the ScalarValueObjectType_BooleanValue Variable. /// public const uint ScalarValueObjectType_BooleanValue = 9507; /// /// The identifier for the ScalarValueObjectType_SByteValue Variable. /// public const uint ScalarValueObjectType_SByteValue = 9508; /// /// The identifier for the ScalarValueObjectType_ByteValue Variable. /// public const uint ScalarValueObjectType_ByteValue = 9509; /// /// The identifier for the ScalarValueObjectType_Int16Value Variable. /// public const uint ScalarValueObjectType_Int16Value = 9510; /// /// The identifier for the ScalarValueObjectType_UInt16Value Variable. /// public const uint ScalarValueObjectType_UInt16Value = 9511; /// /// The identifier for the ScalarValueObjectType_Int32Value Variable. /// public const uint ScalarValueObjectType_Int32Value = 9512; /// /// The identifier for the ScalarValueObjectType_UInt32Value Variable. /// public const uint ScalarValueObjectType_UInt32Value = 9513; /// /// The identifier for the ScalarValueObjectType_Int64Value Variable. /// public const uint ScalarValueObjectType_Int64Value = 9514; /// /// The identifier for the ScalarValueObjectType_UInt64Value Variable. /// public const uint ScalarValueObjectType_UInt64Value = 9515; /// /// The identifier for the ScalarValueObjectType_FloatValue Variable. /// public const uint ScalarValueObjectType_FloatValue = 9516; /// /// The identifier for the ScalarValueObjectType_DoubleValue Variable. /// public const uint ScalarValueObjectType_DoubleValue = 9517; /// /// The identifier for the ScalarValueObjectType_StringValue Variable. /// public const uint ScalarValueObjectType_StringValue = 9518; /// /// The identifier for the ScalarValueObjectType_DateTimeValue Variable. /// public const uint ScalarValueObjectType_DateTimeValue = 9519; /// /// The identifier for the ScalarValueObjectType_GuidValue Variable. /// public const uint ScalarValueObjectType_GuidValue = 9520; /// /// The identifier for the ScalarValueObjectType_ByteStringValue Variable. /// public const uint ScalarValueObjectType_ByteStringValue = 9521; /// /// The identifier for the ScalarValueObjectType_XmlElementValue Variable. /// public const uint ScalarValueObjectType_XmlElementValue = 9522; /// /// The identifier for the ScalarValueObjectType_NodeIdValue Variable. /// public const uint ScalarValueObjectType_NodeIdValue = 9523; /// /// The identifier for the ScalarValueObjectType_ExpandedNodeIdValue Variable. /// public const uint ScalarValueObjectType_ExpandedNodeIdValue = 9524; /// /// The identifier for the ScalarValueObjectType_QualifiedNameValue Variable. /// public const uint ScalarValueObjectType_QualifiedNameValue = 9525; /// /// The identifier for the ScalarValueObjectType_LocalizedTextValue Variable. /// public const uint ScalarValueObjectType_LocalizedTextValue = 9526; /// /// The identifier for the ScalarValueObjectType_StatusCodeValue Variable. /// public const uint ScalarValueObjectType_StatusCodeValue = 9527; /// /// The identifier for the ScalarValueObjectType_VariantValue Variable. /// public const uint ScalarValueObjectType_VariantValue = 9528; /// /// The identifier for the ScalarValueObjectType_EnumerationValue Variable. /// public const uint ScalarValueObjectType_EnumerationValue = 9529; /// /// The identifier for the ScalarValueObjectType_StructureValue Variable. /// public const uint ScalarValueObjectType_StructureValue = 9530; /// /// The identifier for the ScalarValueObjectType_NumberValue Variable. /// public const uint ScalarValueObjectType_NumberValue = 9531; /// /// The identifier for the ScalarValueObjectType_IntegerValue Variable. /// public const uint ScalarValueObjectType_IntegerValue = 9532; /// /// The identifier for the ScalarValueObjectType_UIntegerValue Variable. /// public const uint ScalarValueObjectType_UIntegerValue = 9533; /// /// The identifier for the AnalogScalarValueObjectType_GenerateValues_InputArguments Variable. /// public const uint AnalogScalarValueObjectType_GenerateValues_InputArguments = 9537; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_EventId Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_EventId = 9539; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_EventType Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_EventType = 9540; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_SourceNode Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_SourceNode = 9541; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_SourceName Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_SourceName = 9542; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Time Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_Time = 9543; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_ReceiveTime Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_ReceiveTime = 9544; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Message Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_Message = 9546; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Severity Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_Severity = 9547; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_ConditionClassId Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_ConditionClassId = 11582; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_ConditionClassName Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_ConditionClassName = 11583; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_ConditionName Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_ConditionName = 11559; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_BranchId Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_BranchId = 9548; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Retain Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_Retain = 9549; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_EnabledState Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_EnabledState = 9550; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_EnabledState_Id Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_EnabledState_Id = 9551; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Quality Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_Quality = 9556; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Quality_SourceTimestamp Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_Quality_SourceTimestamp = 9557; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_LastSeverity Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_LastSeverity = 9560; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_LastSeverity_SourceTimestamp = 9561; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Comment Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_Comment = 9562; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Comment_SourceTimestamp Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_Comment_SourceTimestamp = 9563; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_ClientUserId Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_ClientUserId = 9564; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_AddComment_InputArguments Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_AddComment_InputArguments = 9568; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_AckedState Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_AckedState = 9571; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_AckedState_Id Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_AckedState_Id = 9572; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_ConfirmedState_Id Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_ConfirmedState_Id = 9580; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Acknowledge_InputArguments Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_Acknowledge_InputArguments = 9588; /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Confirm_InputArguments Variable. /// public const uint AnalogScalarValueObjectType_CycleComplete_Confirm_InputArguments = 9590; /// /// The identifier for the AnalogScalarValueObjectType_SByteValue Variable. /// public const uint AnalogScalarValueObjectType_SByteValue = 9591; /// /// The identifier for the AnalogScalarValueObjectType_SByteValue_EURange Variable. /// public const uint AnalogScalarValueObjectType_SByteValue_EURange = 9594; /// /// The identifier for the AnalogScalarValueObjectType_ByteValue Variable. /// public const uint AnalogScalarValueObjectType_ByteValue = 9597; /// /// The identifier for the AnalogScalarValueObjectType_ByteValue_EURange Variable. /// public const uint AnalogScalarValueObjectType_ByteValue_EURange = 9600; /// /// The identifier for the AnalogScalarValueObjectType_Int16Value Variable. /// public const uint AnalogScalarValueObjectType_Int16Value = 9603; /// /// The identifier for the AnalogScalarValueObjectType_Int16Value_EURange Variable. /// public const uint AnalogScalarValueObjectType_Int16Value_EURange = 9606; /// /// The identifier for the AnalogScalarValueObjectType_UInt16Value Variable. /// public const uint AnalogScalarValueObjectType_UInt16Value = 9609; /// /// The identifier for the AnalogScalarValueObjectType_UInt16Value_EURange Variable. /// public const uint AnalogScalarValueObjectType_UInt16Value_EURange = 9612; /// /// The identifier for the AnalogScalarValueObjectType_Int32Value Variable. /// public const uint AnalogScalarValueObjectType_Int32Value = 9615; /// /// The identifier for the AnalogScalarValueObjectType_Int32Value_EURange Variable. /// public const uint AnalogScalarValueObjectType_Int32Value_EURange = 9618; /// /// The identifier for the AnalogScalarValueObjectType_UInt32Value Variable. /// public const uint AnalogScalarValueObjectType_UInt32Value = 9621; /// /// The identifier for the AnalogScalarValueObjectType_UInt32Value_EURange Variable. /// public const uint AnalogScalarValueObjectType_UInt32Value_EURange = 9624; /// /// The identifier for the AnalogScalarValueObjectType_Int64Value Variable. /// public const uint AnalogScalarValueObjectType_Int64Value = 9627; /// /// The identifier for the AnalogScalarValueObjectType_Int64Value_EURange Variable. /// public const uint AnalogScalarValueObjectType_Int64Value_EURange = 9630; /// /// The identifier for the AnalogScalarValueObjectType_UInt64Value Variable. /// public const uint AnalogScalarValueObjectType_UInt64Value = 9633; /// /// The identifier for the AnalogScalarValueObjectType_UInt64Value_EURange Variable. /// public const uint AnalogScalarValueObjectType_UInt64Value_EURange = 9636; /// /// The identifier for the AnalogScalarValueObjectType_FloatValue Variable. /// public const uint AnalogScalarValueObjectType_FloatValue = 9639; /// /// The identifier for the AnalogScalarValueObjectType_FloatValue_EURange Variable. /// public const uint AnalogScalarValueObjectType_FloatValue_EURange = 9642; /// /// The identifier for the AnalogScalarValueObjectType_DoubleValue Variable. /// public const uint AnalogScalarValueObjectType_DoubleValue = 9645; /// /// The identifier for the AnalogScalarValueObjectType_DoubleValue_EURange Variable. /// public const uint AnalogScalarValueObjectType_DoubleValue_EURange = 9648; /// /// The identifier for the AnalogScalarValueObjectType_NumberValue Variable. /// public const uint AnalogScalarValueObjectType_NumberValue = 9651; /// /// The identifier for the AnalogScalarValueObjectType_NumberValue_EURange Variable. /// public const uint AnalogScalarValueObjectType_NumberValue_EURange = 9654; /// /// The identifier for the AnalogScalarValueObjectType_IntegerValue Variable. /// public const uint AnalogScalarValueObjectType_IntegerValue = 9657; /// /// The identifier for the AnalogScalarValueObjectType_IntegerValue_EURange Variable. /// public const uint AnalogScalarValueObjectType_IntegerValue_EURange = 9660; /// /// The identifier for the AnalogScalarValueObjectType_UIntegerValue Variable. /// public const uint AnalogScalarValueObjectType_UIntegerValue = 9663; /// /// The identifier for the AnalogScalarValueObjectType_UIntegerValue_EURange Variable. /// public const uint AnalogScalarValueObjectType_UIntegerValue_EURange = 9666; /// /// The identifier for the ArrayValueObjectType_GenerateValues_InputArguments Variable. /// public const uint ArrayValueObjectType_GenerateValues_InputArguments = 9682; /// /// The identifier for the ArrayValueObjectType_CycleComplete_EventId Variable. /// public const uint ArrayValueObjectType_CycleComplete_EventId = 9684; /// /// The identifier for the ArrayValueObjectType_CycleComplete_EventType Variable. /// public const uint ArrayValueObjectType_CycleComplete_EventType = 9685; /// /// The identifier for the ArrayValueObjectType_CycleComplete_SourceNode Variable. /// public const uint ArrayValueObjectType_CycleComplete_SourceNode = 9686; /// /// The identifier for the ArrayValueObjectType_CycleComplete_SourceName Variable. /// public const uint ArrayValueObjectType_CycleComplete_SourceName = 9687; /// /// The identifier for the ArrayValueObjectType_CycleComplete_Time Variable. /// public const uint ArrayValueObjectType_CycleComplete_Time = 9688; /// /// The identifier for the ArrayValueObjectType_CycleComplete_ReceiveTime Variable. /// public const uint ArrayValueObjectType_CycleComplete_ReceiveTime = 9689; /// /// The identifier for the ArrayValueObjectType_CycleComplete_Message Variable. /// public const uint ArrayValueObjectType_CycleComplete_Message = 9691; /// /// The identifier for the ArrayValueObjectType_CycleComplete_Severity Variable. /// public const uint ArrayValueObjectType_CycleComplete_Severity = 9692; /// /// The identifier for the ArrayValueObjectType_CycleComplete_ConditionClassId Variable. /// public const uint ArrayValueObjectType_CycleComplete_ConditionClassId = 11584; /// /// The identifier for the ArrayValueObjectType_CycleComplete_ConditionClassName Variable. /// public const uint ArrayValueObjectType_CycleComplete_ConditionClassName = 11585; /// /// The identifier for the ArrayValueObjectType_CycleComplete_ConditionName Variable. /// public const uint ArrayValueObjectType_CycleComplete_ConditionName = 11560; /// /// The identifier for the ArrayValueObjectType_CycleComplete_BranchId Variable. /// public const uint ArrayValueObjectType_CycleComplete_BranchId = 9693; /// /// The identifier for the ArrayValueObjectType_CycleComplete_Retain Variable. /// public const uint ArrayValueObjectType_CycleComplete_Retain = 9694; /// /// The identifier for the ArrayValueObjectType_CycleComplete_EnabledState Variable. /// public const uint ArrayValueObjectType_CycleComplete_EnabledState = 9695; /// /// The identifier for the ArrayValueObjectType_CycleComplete_EnabledState_Id Variable. /// public const uint ArrayValueObjectType_CycleComplete_EnabledState_Id = 9696; /// /// The identifier for the ArrayValueObjectType_CycleComplete_Quality Variable. /// public const uint ArrayValueObjectType_CycleComplete_Quality = 9701; /// /// The identifier for the ArrayValueObjectType_CycleComplete_Quality_SourceTimestamp Variable. /// public const uint ArrayValueObjectType_CycleComplete_Quality_SourceTimestamp = 9702; /// /// The identifier for the ArrayValueObjectType_CycleComplete_LastSeverity Variable. /// public const uint ArrayValueObjectType_CycleComplete_LastSeverity = 9705; /// /// The identifier for the ArrayValueObjectType_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public const uint ArrayValueObjectType_CycleComplete_LastSeverity_SourceTimestamp = 9706; /// /// The identifier for the ArrayValueObjectType_CycleComplete_Comment Variable. /// public const uint ArrayValueObjectType_CycleComplete_Comment = 9707; /// /// The identifier for the ArrayValueObjectType_CycleComplete_Comment_SourceTimestamp Variable. /// public const uint ArrayValueObjectType_CycleComplete_Comment_SourceTimestamp = 9708; /// /// The identifier for the ArrayValueObjectType_CycleComplete_ClientUserId Variable. /// public const uint ArrayValueObjectType_CycleComplete_ClientUserId = 9709; /// /// The identifier for the ArrayValueObjectType_CycleComplete_AddComment_InputArguments Variable. /// public const uint ArrayValueObjectType_CycleComplete_AddComment_InputArguments = 9713; /// /// The identifier for the ArrayValueObjectType_CycleComplete_AckedState Variable. /// public const uint ArrayValueObjectType_CycleComplete_AckedState = 9716; /// /// The identifier for the ArrayValueObjectType_CycleComplete_AckedState_Id Variable. /// public const uint ArrayValueObjectType_CycleComplete_AckedState_Id = 9717; /// /// The identifier for the ArrayValueObjectType_CycleComplete_ConfirmedState_Id Variable. /// public const uint ArrayValueObjectType_CycleComplete_ConfirmedState_Id = 9725; /// /// The identifier for the ArrayValueObjectType_CycleComplete_Acknowledge_InputArguments Variable. /// public const uint ArrayValueObjectType_CycleComplete_Acknowledge_InputArguments = 9733; /// /// The identifier for the ArrayValueObjectType_CycleComplete_Confirm_InputArguments Variable. /// public const uint ArrayValueObjectType_CycleComplete_Confirm_InputArguments = 9735; /// /// The identifier for the ArrayValueObjectType_BooleanValue Variable. /// public const uint ArrayValueObjectType_BooleanValue = 9736; /// /// The identifier for the ArrayValueObjectType_SByteValue Variable. /// public const uint ArrayValueObjectType_SByteValue = 9737; /// /// The identifier for the ArrayValueObjectType_ByteValue Variable. /// public const uint ArrayValueObjectType_ByteValue = 9738; /// /// The identifier for the ArrayValueObjectType_Int16Value Variable. /// public const uint ArrayValueObjectType_Int16Value = 9739; /// /// The identifier for the ArrayValueObjectType_UInt16Value Variable. /// public const uint ArrayValueObjectType_UInt16Value = 9740; /// /// The identifier for the ArrayValueObjectType_Int32Value Variable. /// public const uint ArrayValueObjectType_Int32Value = 9741; /// /// The identifier for the ArrayValueObjectType_UInt32Value Variable. /// public const uint ArrayValueObjectType_UInt32Value = 9742; /// /// The identifier for the ArrayValueObjectType_Int64Value Variable. /// public const uint ArrayValueObjectType_Int64Value = 9743; /// /// The identifier for the ArrayValueObjectType_UInt64Value Variable. /// public const uint ArrayValueObjectType_UInt64Value = 9744; /// /// The identifier for the ArrayValueObjectType_FloatValue Variable. /// public const uint ArrayValueObjectType_FloatValue = 9745; /// /// The identifier for the ArrayValueObjectType_DoubleValue Variable. /// public const uint ArrayValueObjectType_DoubleValue = 9746; /// /// The identifier for the ArrayValueObjectType_StringValue Variable. /// public const uint ArrayValueObjectType_StringValue = 9747; /// /// The identifier for the ArrayValueObjectType_DateTimeValue Variable. /// public const uint ArrayValueObjectType_DateTimeValue = 9748; /// /// The identifier for the ArrayValueObjectType_GuidValue Variable. /// public const uint ArrayValueObjectType_GuidValue = 9749; /// /// The identifier for the ArrayValueObjectType_ByteStringValue Variable. /// public const uint ArrayValueObjectType_ByteStringValue = 9750; /// /// The identifier for the ArrayValueObjectType_XmlElementValue Variable. /// public const uint ArrayValueObjectType_XmlElementValue = 9751; /// /// The identifier for the ArrayValueObjectType_NodeIdValue Variable. /// public const uint ArrayValueObjectType_NodeIdValue = 9752; /// /// The identifier for the ArrayValueObjectType_ExpandedNodeIdValue Variable. /// public const uint ArrayValueObjectType_ExpandedNodeIdValue = 9753; /// /// The identifier for the ArrayValueObjectType_QualifiedNameValue Variable. /// public const uint ArrayValueObjectType_QualifiedNameValue = 9754; /// /// The identifier for the ArrayValueObjectType_LocalizedTextValue Variable. /// public const uint ArrayValueObjectType_LocalizedTextValue = 9755; /// /// The identifier for the ArrayValueObjectType_StatusCodeValue Variable. /// public const uint ArrayValueObjectType_StatusCodeValue = 9756; /// /// The identifier for the ArrayValueObjectType_VariantValue Variable. /// public const uint ArrayValueObjectType_VariantValue = 9757; /// /// The identifier for the ArrayValueObjectType_EnumerationValue Variable. /// public const uint ArrayValueObjectType_EnumerationValue = 9758; /// /// The identifier for the ArrayValueObjectType_StructureValue Variable. /// public const uint ArrayValueObjectType_StructureValue = 9759; /// /// The identifier for the ArrayValueObjectType_NumberValue Variable. /// public const uint ArrayValueObjectType_NumberValue = 9760; /// /// The identifier for the ArrayValueObjectType_IntegerValue Variable. /// public const uint ArrayValueObjectType_IntegerValue = 9761; /// /// The identifier for the ArrayValueObjectType_UIntegerValue Variable. /// public const uint ArrayValueObjectType_UIntegerValue = 9762; /// /// The identifier for the AnalogArrayValueObjectType_GenerateValues_InputArguments Variable. /// public const uint AnalogArrayValueObjectType_GenerateValues_InputArguments = 9766; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_EventId Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_EventId = 9768; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_EventType Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_EventType = 9769; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_SourceNode Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_SourceNode = 9770; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_SourceName Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_SourceName = 9771; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Time Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_Time = 9772; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_ReceiveTime Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_ReceiveTime = 9773; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Message Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_Message = 9775; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Severity Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_Severity = 9776; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_ConditionClassId Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_ConditionClassId = 11586; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_ConditionClassName Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_ConditionClassName = 11587; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_ConditionName Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_ConditionName = 11561; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_BranchId Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_BranchId = 9777; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Retain Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_Retain = 9778; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_EnabledState Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_EnabledState = 9779; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_EnabledState_Id Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_EnabledState_Id = 9780; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Quality Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_Quality = 9785; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Quality_SourceTimestamp Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_Quality_SourceTimestamp = 9786; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_LastSeverity Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_LastSeverity = 9789; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_LastSeverity_SourceTimestamp = 9790; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Comment Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_Comment = 9791; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Comment_SourceTimestamp Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_Comment_SourceTimestamp = 9792; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_ClientUserId Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_ClientUserId = 9793; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_AddComment_InputArguments Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_AddComment_InputArguments = 9797; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_AckedState Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_AckedState = 9800; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_AckedState_Id Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_AckedState_Id = 9801; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_ConfirmedState_Id Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_ConfirmedState_Id = 9809; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Acknowledge_InputArguments Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_Acknowledge_InputArguments = 9817; /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Confirm_InputArguments Variable. /// public const uint AnalogArrayValueObjectType_CycleComplete_Confirm_InputArguments = 9819; /// /// The identifier for the AnalogArrayValueObjectType_SByteValue Variable. /// public const uint AnalogArrayValueObjectType_SByteValue = 9820; /// /// The identifier for the AnalogArrayValueObjectType_SByteValue_EURange Variable. /// public const uint AnalogArrayValueObjectType_SByteValue_EURange = 9823; /// /// The identifier for the AnalogArrayValueObjectType_ByteValue Variable. /// public const uint AnalogArrayValueObjectType_ByteValue = 9826; /// /// The identifier for the AnalogArrayValueObjectType_ByteValue_EURange Variable. /// public const uint AnalogArrayValueObjectType_ByteValue_EURange = 9829; /// /// The identifier for the AnalogArrayValueObjectType_Int16Value Variable. /// public const uint AnalogArrayValueObjectType_Int16Value = 9832; /// /// The identifier for the AnalogArrayValueObjectType_Int16Value_EURange Variable. /// public const uint AnalogArrayValueObjectType_Int16Value_EURange = 9835; /// /// The identifier for the AnalogArrayValueObjectType_UInt16Value Variable. /// public const uint AnalogArrayValueObjectType_UInt16Value = 9838; /// /// The identifier for the AnalogArrayValueObjectType_UInt16Value_EURange Variable. /// public const uint AnalogArrayValueObjectType_UInt16Value_EURange = 9841; /// /// The identifier for the AnalogArrayValueObjectType_Int32Value Variable. /// public const uint AnalogArrayValueObjectType_Int32Value = 9844; /// /// The identifier for the AnalogArrayValueObjectType_Int32Value_EURange Variable. /// public const uint AnalogArrayValueObjectType_Int32Value_EURange = 9847; /// /// The identifier for the AnalogArrayValueObjectType_UInt32Value Variable. /// public const uint AnalogArrayValueObjectType_UInt32Value = 9850; /// /// The identifier for the AnalogArrayValueObjectType_UInt32Value_EURange Variable. /// public const uint AnalogArrayValueObjectType_UInt32Value_EURange = 9853; /// /// The identifier for the AnalogArrayValueObjectType_Int64Value Variable. /// public const uint AnalogArrayValueObjectType_Int64Value = 9856; /// /// The identifier for the AnalogArrayValueObjectType_Int64Value_EURange Variable. /// public const uint AnalogArrayValueObjectType_Int64Value_EURange = 9859; /// /// The identifier for the AnalogArrayValueObjectType_UInt64Value Variable. /// public const uint AnalogArrayValueObjectType_UInt64Value = 9862; /// /// The identifier for the AnalogArrayValueObjectType_UInt64Value_EURange Variable. /// public const uint AnalogArrayValueObjectType_UInt64Value_EURange = 9865; /// /// The identifier for the AnalogArrayValueObjectType_FloatValue Variable. /// public const uint AnalogArrayValueObjectType_FloatValue = 9868; /// /// The identifier for the AnalogArrayValueObjectType_FloatValue_EURange Variable. /// public const uint AnalogArrayValueObjectType_FloatValue_EURange = 9871; /// /// The identifier for the AnalogArrayValueObjectType_DoubleValue Variable. /// public const uint AnalogArrayValueObjectType_DoubleValue = 9874; /// /// The identifier for the AnalogArrayValueObjectType_DoubleValue_EURange Variable. /// public const uint AnalogArrayValueObjectType_DoubleValue_EURange = 9877; /// /// The identifier for the AnalogArrayValueObjectType_NumberValue Variable. /// public const uint AnalogArrayValueObjectType_NumberValue = 9880; /// /// The identifier for the AnalogArrayValueObjectType_NumberValue_EURange Variable. /// public const uint AnalogArrayValueObjectType_NumberValue_EURange = 9883; /// /// The identifier for the AnalogArrayValueObjectType_IntegerValue Variable. /// public const uint AnalogArrayValueObjectType_IntegerValue = 9886; /// /// The identifier for the AnalogArrayValueObjectType_IntegerValue_EURange Variable. /// public const uint AnalogArrayValueObjectType_IntegerValue_EURange = 9889; /// /// The identifier for the AnalogArrayValueObjectType_UIntegerValue Variable. /// public const uint AnalogArrayValueObjectType_UIntegerValue = 9892; /// /// The identifier for the AnalogArrayValueObjectType_UIntegerValue_EURange Variable. /// public const uint AnalogArrayValueObjectType_UIntegerValue_EURange = 9895; /// /// The identifier for the UserScalarValueObjectType_GenerateValues_InputArguments Variable. /// public const uint UserScalarValueObjectType_GenerateValues_InputArguments = 9924; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_EventId Variable. /// public const uint UserScalarValueObjectType_CycleComplete_EventId = 9926; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_EventType Variable. /// public const uint UserScalarValueObjectType_CycleComplete_EventType = 9927; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_SourceNode Variable. /// public const uint UserScalarValueObjectType_CycleComplete_SourceNode = 9928; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_SourceName Variable. /// public const uint UserScalarValueObjectType_CycleComplete_SourceName = 9929; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Time Variable. /// public const uint UserScalarValueObjectType_CycleComplete_Time = 9930; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_ReceiveTime Variable. /// public const uint UserScalarValueObjectType_CycleComplete_ReceiveTime = 9931; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Message Variable. /// public const uint UserScalarValueObjectType_CycleComplete_Message = 9933; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Severity Variable. /// public const uint UserScalarValueObjectType_CycleComplete_Severity = 9934; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_ConditionClassId Variable. /// public const uint UserScalarValueObjectType_CycleComplete_ConditionClassId = 11588; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_ConditionClassName Variable. /// public const uint UserScalarValueObjectType_CycleComplete_ConditionClassName = 11589; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_ConditionName Variable. /// public const uint UserScalarValueObjectType_CycleComplete_ConditionName = 11562; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_BranchId Variable. /// public const uint UserScalarValueObjectType_CycleComplete_BranchId = 9935; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Retain Variable. /// public const uint UserScalarValueObjectType_CycleComplete_Retain = 9936; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_EnabledState Variable. /// public const uint UserScalarValueObjectType_CycleComplete_EnabledState = 9937; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_EnabledState_Id Variable. /// public const uint UserScalarValueObjectType_CycleComplete_EnabledState_Id = 9938; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Quality Variable. /// public const uint UserScalarValueObjectType_CycleComplete_Quality = 9943; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Quality_SourceTimestamp Variable. /// public const uint UserScalarValueObjectType_CycleComplete_Quality_SourceTimestamp = 9944; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_LastSeverity Variable. /// public const uint UserScalarValueObjectType_CycleComplete_LastSeverity = 9947; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public const uint UserScalarValueObjectType_CycleComplete_LastSeverity_SourceTimestamp = 9948; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Comment Variable. /// public const uint UserScalarValueObjectType_CycleComplete_Comment = 9949; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Comment_SourceTimestamp Variable. /// public const uint UserScalarValueObjectType_CycleComplete_Comment_SourceTimestamp = 9950; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_ClientUserId Variable. /// public const uint UserScalarValueObjectType_CycleComplete_ClientUserId = 9951; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_AddComment_InputArguments Variable. /// public const uint UserScalarValueObjectType_CycleComplete_AddComment_InputArguments = 9955; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_AckedState Variable. /// public const uint UserScalarValueObjectType_CycleComplete_AckedState = 9958; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_AckedState_Id Variable. /// public const uint UserScalarValueObjectType_CycleComplete_AckedState_Id = 9959; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_ConfirmedState_Id Variable. /// public const uint UserScalarValueObjectType_CycleComplete_ConfirmedState_Id = 9967; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Acknowledge_InputArguments Variable. /// public const uint UserScalarValueObjectType_CycleComplete_Acknowledge_InputArguments = 9975; /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Confirm_InputArguments Variable. /// public const uint UserScalarValueObjectType_CycleComplete_Confirm_InputArguments = 9977; /// /// The identifier for the UserScalarValueObjectType_BooleanValue Variable. /// public const uint UserScalarValueObjectType_BooleanValue = 9978; /// /// The identifier for the UserScalarValueObjectType_SByteValue Variable. /// public const uint UserScalarValueObjectType_SByteValue = 9979; /// /// The identifier for the UserScalarValueObjectType_ByteValue Variable. /// public const uint UserScalarValueObjectType_ByteValue = 9980; /// /// The identifier for the UserScalarValueObjectType_Int16Value Variable. /// public const uint UserScalarValueObjectType_Int16Value = 9981; /// /// The identifier for the UserScalarValueObjectType_UInt16Value Variable. /// public const uint UserScalarValueObjectType_UInt16Value = 9982; /// /// The identifier for the UserScalarValueObjectType_Int32Value Variable. /// public const uint UserScalarValueObjectType_Int32Value = 9983; /// /// The identifier for the UserScalarValueObjectType_UInt32Value Variable. /// public const uint UserScalarValueObjectType_UInt32Value = 9984; /// /// The identifier for the UserScalarValueObjectType_Int64Value Variable. /// public const uint UserScalarValueObjectType_Int64Value = 9985; /// /// The identifier for the UserScalarValueObjectType_UInt64Value Variable. /// public const uint UserScalarValueObjectType_UInt64Value = 9986; /// /// The identifier for the UserScalarValueObjectType_FloatValue Variable. /// public const uint UserScalarValueObjectType_FloatValue = 9987; /// /// The identifier for the UserScalarValueObjectType_DoubleValue Variable. /// public const uint UserScalarValueObjectType_DoubleValue = 9988; /// /// The identifier for the UserScalarValueObjectType_StringValue Variable. /// public const uint UserScalarValueObjectType_StringValue = 9989; /// /// The identifier for the UserScalarValueObjectType_DateTimeValue Variable. /// public const uint UserScalarValueObjectType_DateTimeValue = 9990; /// /// The identifier for the UserScalarValueObjectType_GuidValue Variable. /// public const uint UserScalarValueObjectType_GuidValue = 9991; /// /// The identifier for the UserScalarValueObjectType_ByteStringValue Variable. /// public const uint UserScalarValueObjectType_ByteStringValue = 9992; /// /// The identifier for the UserScalarValueObjectType_XmlElementValue Variable. /// public const uint UserScalarValueObjectType_XmlElementValue = 9993; /// /// The identifier for the UserScalarValueObjectType_NodeIdValue Variable. /// public const uint UserScalarValueObjectType_NodeIdValue = 9994; /// /// The identifier for the UserScalarValueObjectType_ExpandedNodeIdValue Variable. /// public const uint UserScalarValueObjectType_ExpandedNodeIdValue = 9995; /// /// The identifier for the UserScalarValueObjectType_QualifiedNameValue Variable. /// public const uint UserScalarValueObjectType_QualifiedNameValue = 9996; /// /// The identifier for the UserScalarValueObjectType_LocalizedTextValue Variable. /// public const uint UserScalarValueObjectType_LocalizedTextValue = 9997; /// /// The identifier for the UserScalarValueObjectType_StatusCodeValue Variable. /// public const uint UserScalarValueObjectType_StatusCodeValue = 9998; /// /// The identifier for the UserScalarValueObjectType_VariantValue Variable. /// public const uint UserScalarValueObjectType_VariantValue = 9999; /// /// The identifier for the UserArrayValueObjectType_GenerateValues_InputArguments Variable. /// public const uint UserArrayValueObjectType_GenerateValues_InputArguments = 10010; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_EventId Variable. /// public const uint UserArrayValueObjectType_CycleComplete_EventId = 10012; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_EventType Variable. /// public const uint UserArrayValueObjectType_CycleComplete_EventType = 10013; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_SourceNode Variable. /// public const uint UserArrayValueObjectType_CycleComplete_SourceNode = 10014; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_SourceName Variable. /// public const uint UserArrayValueObjectType_CycleComplete_SourceName = 10015; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Time Variable. /// public const uint UserArrayValueObjectType_CycleComplete_Time = 10016; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_ReceiveTime Variable. /// public const uint UserArrayValueObjectType_CycleComplete_ReceiveTime = 10017; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Message Variable. /// public const uint UserArrayValueObjectType_CycleComplete_Message = 10019; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Severity Variable. /// public const uint UserArrayValueObjectType_CycleComplete_Severity = 10020; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_ConditionClassId Variable. /// public const uint UserArrayValueObjectType_CycleComplete_ConditionClassId = 11590; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_ConditionClassName Variable. /// public const uint UserArrayValueObjectType_CycleComplete_ConditionClassName = 11591; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_ConditionName Variable. /// public const uint UserArrayValueObjectType_CycleComplete_ConditionName = 11563; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_BranchId Variable. /// public const uint UserArrayValueObjectType_CycleComplete_BranchId = 10021; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Retain Variable. /// public const uint UserArrayValueObjectType_CycleComplete_Retain = 10022; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_EnabledState Variable. /// public const uint UserArrayValueObjectType_CycleComplete_EnabledState = 10023; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_EnabledState_Id Variable. /// public const uint UserArrayValueObjectType_CycleComplete_EnabledState_Id = 10024; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Quality Variable. /// public const uint UserArrayValueObjectType_CycleComplete_Quality = 10029; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Quality_SourceTimestamp Variable. /// public const uint UserArrayValueObjectType_CycleComplete_Quality_SourceTimestamp = 10030; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_LastSeverity Variable. /// public const uint UserArrayValueObjectType_CycleComplete_LastSeverity = 10033; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public const uint UserArrayValueObjectType_CycleComplete_LastSeverity_SourceTimestamp = 10034; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Comment Variable. /// public const uint UserArrayValueObjectType_CycleComplete_Comment = 10035; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Comment_SourceTimestamp Variable. /// public const uint UserArrayValueObjectType_CycleComplete_Comment_SourceTimestamp = 10036; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_ClientUserId Variable. /// public const uint UserArrayValueObjectType_CycleComplete_ClientUserId = 10037; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_AddComment_InputArguments Variable. /// public const uint UserArrayValueObjectType_CycleComplete_AddComment_InputArguments = 10041; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_AckedState Variable. /// public const uint UserArrayValueObjectType_CycleComplete_AckedState = 10044; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_AckedState_Id Variable. /// public const uint UserArrayValueObjectType_CycleComplete_AckedState_Id = 10045; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_ConfirmedState_Id Variable. /// public const uint UserArrayValueObjectType_CycleComplete_ConfirmedState_Id = 10053; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Acknowledge_InputArguments Variable. /// public const uint UserArrayValueObjectType_CycleComplete_Acknowledge_InputArguments = 10061; /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Confirm_InputArguments Variable. /// public const uint UserArrayValueObjectType_CycleComplete_Confirm_InputArguments = 10063; /// /// The identifier for the UserArrayValueObjectType_BooleanValue Variable. /// public const uint UserArrayValueObjectType_BooleanValue = 10064; /// /// The identifier for the UserArrayValueObjectType_SByteValue Variable. /// public const uint UserArrayValueObjectType_SByteValue = 10065; /// /// The identifier for the UserArrayValueObjectType_ByteValue Variable. /// public const uint UserArrayValueObjectType_ByteValue = 10066; /// /// The identifier for the UserArrayValueObjectType_Int16Value Variable. /// public const uint UserArrayValueObjectType_Int16Value = 10067; /// /// The identifier for the UserArrayValueObjectType_UInt16Value Variable. /// public const uint UserArrayValueObjectType_UInt16Value = 10068; /// /// The identifier for the UserArrayValueObjectType_Int32Value Variable. /// public const uint UserArrayValueObjectType_Int32Value = 10069; /// /// The identifier for the UserArrayValueObjectType_UInt32Value Variable. /// public const uint UserArrayValueObjectType_UInt32Value = 10070; /// /// The identifier for the UserArrayValueObjectType_Int64Value Variable. /// public const uint UserArrayValueObjectType_Int64Value = 10071; /// /// The identifier for the UserArrayValueObjectType_UInt64Value Variable. /// public const uint UserArrayValueObjectType_UInt64Value = 10072; /// /// The identifier for the UserArrayValueObjectType_FloatValue Variable. /// public const uint UserArrayValueObjectType_FloatValue = 10073; /// /// The identifier for the UserArrayValueObjectType_DoubleValue Variable. /// public const uint UserArrayValueObjectType_DoubleValue = 10074; /// /// The identifier for the UserArrayValueObjectType_StringValue Variable. /// public const uint UserArrayValueObjectType_StringValue = 10075; /// /// The identifier for the UserArrayValueObjectType_DateTimeValue Variable. /// public const uint UserArrayValueObjectType_DateTimeValue = 10076; /// /// The identifier for the UserArrayValueObjectType_GuidValue Variable. /// public const uint UserArrayValueObjectType_GuidValue = 10077; /// /// The identifier for the UserArrayValueObjectType_ByteStringValue Variable. /// public const uint UserArrayValueObjectType_ByteStringValue = 10078; /// /// The identifier for the UserArrayValueObjectType_XmlElementValue Variable. /// public const uint UserArrayValueObjectType_XmlElementValue = 10079; /// /// The identifier for the UserArrayValueObjectType_NodeIdValue Variable. /// public const uint UserArrayValueObjectType_NodeIdValue = 10080; /// /// The identifier for the UserArrayValueObjectType_ExpandedNodeIdValue Variable. /// public const uint UserArrayValueObjectType_ExpandedNodeIdValue = 10081; /// /// The identifier for the UserArrayValueObjectType_QualifiedNameValue Variable. /// public const uint UserArrayValueObjectType_QualifiedNameValue = 10082; /// /// The identifier for the UserArrayValueObjectType_LocalizedTextValue Variable. /// public const uint UserArrayValueObjectType_LocalizedTextValue = 10083; /// /// The identifier for the UserArrayValueObjectType_StatusCodeValue Variable. /// public const uint UserArrayValueObjectType_StatusCodeValue = 10084; /// /// The identifier for the UserArrayValueObjectType_VariantValue Variable. /// public const uint UserArrayValueObjectType_VariantValue = 10085; /// /// The identifier for the MethodTestType_ScalarMethod1_InputArguments Variable. /// public const uint MethodTestType_ScalarMethod1_InputArguments = 10094; /// /// The identifier for the MethodTestType_ScalarMethod1_OutputArguments Variable. /// public const uint MethodTestType_ScalarMethod1_OutputArguments = 10095; /// /// The identifier for the MethodTestType_ScalarMethod2_InputArguments Variable. /// public const uint MethodTestType_ScalarMethod2_InputArguments = 10097; /// /// The identifier for the MethodTestType_ScalarMethod2_OutputArguments Variable. /// public const uint MethodTestType_ScalarMethod2_OutputArguments = 10098; /// /// The identifier for the MethodTestType_ScalarMethod3_InputArguments Variable. /// public const uint MethodTestType_ScalarMethod3_InputArguments = 10100; /// /// The identifier for the MethodTestType_ScalarMethod3_OutputArguments Variable. /// public const uint MethodTestType_ScalarMethod3_OutputArguments = 10101; /// /// The identifier for the MethodTestType_ArrayMethod1_InputArguments Variable. /// public const uint MethodTestType_ArrayMethod1_InputArguments = 10103; /// /// The identifier for the MethodTestType_ArrayMethod1_OutputArguments Variable. /// public const uint MethodTestType_ArrayMethod1_OutputArguments = 10104; /// /// The identifier for the MethodTestType_ArrayMethod2_InputArguments Variable. /// public const uint MethodTestType_ArrayMethod2_InputArguments = 10106; /// /// The identifier for the MethodTestType_ArrayMethod2_OutputArguments Variable. /// public const uint MethodTestType_ArrayMethod2_OutputArguments = 10107; /// /// The identifier for the MethodTestType_ArrayMethod3_InputArguments Variable. /// public const uint MethodTestType_ArrayMethod3_InputArguments = 10109; /// /// The identifier for the MethodTestType_ArrayMethod3_OutputArguments Variable. /// public const uint MethodTestType_ArrayMethod3_OutputArguments = 10110; /// /// The identifier for the MethodTestType_UserScalarMethod1_InputArguments Variable. /// public const uint MethodTestType_UserScalarMethod1_InputArguments = 10112; /// /// The identifier for the MethodTestType_UserScalarMethod1_OutputArguments Variable. /// public const uint MethodTestType_UserScalarMethod1_OutputArguments = 10113; /// /// The identifier for the MethodTestType_UserScalarMethod2_InputArguments Variable. /// public const uint MethodTestType_UserScalarMethod2_InputArguments = 10115; /// /// The identifier for the MethodTestType_UserScalarMethod2_OutputArguments Variable. /// public const uint MethodTestType_UserScalarMethod2_OutputArguments = 10116; /// /// The identifier for the MethodTestType_UserArrayMethod1_InputArguments Variable. /// public const uint MethodTestType_UserArrayMethod1_InputArguments = 10118; /// /// The identifier for the MethodTestType_UserArrayMethod1_OutputArguments Variable. /// public const uint MethodTestType_UserArrayMethod1_OutputArguments = 10119; /// /// The identifier for the MethodTestType_UserArrayMethod2_InputArguments Variable. /// public const uint MethodTestType_UserArrayMethod2_InputArguments = 10121; /// /// The identifier for the MethodTestType_UserArrayMethod2_OutputArguments Variable. /// public const uint MethodTestType_UserArrayMethod2_OutputArguments = 10122; /// /// The identifier for the TestSystemConditionType_EnabledState_Id Variable. /// public const uint TestSystemConditionType_EnabledState_Id = 10136; /// /// The identifier for the TestSystemConditionType_Quality_SourceTimestamp Variable. /// public const uint TestSystemConditionType_Quality_SourceTimestamp = 10142; /// /// The identifier for the TestSystemConditionType_LastSeverity_SourceTimestamp Variable. /// public const uint TestSystemConditionType_LastSeverity_SourceTimestamp = 10146; /// /// The identifier for the TestSystemConditionType_Comment_SourceTimestamp Variable. /// public const uint TestSystemConditionType_Comment_SourceTimestamp = 10148; /// /// The identifier for the TestSystemConditionType_AddComment_InputArguments Variable. /// public const uint TestSystemConditionType_AddComment_InputArguments = 10153; /// /// The identifier for the TestSystemConditionType_ConditionRefresh_InputArguments Variable. /// public const uint TestSystemConditionType_ConditionRefresh_InputArguments = 10155; /// /// The identifier for the TestSystemConditionType_ConditionRefresh2_InputArguments Variable. /// public const uint TestSystemConditionType_ConditionRefresh2_InputArguments = 15018; /// /// The identifier for the TestSystemConditionType_MonitoredNodeCount Variable. /// public const uint TestSystemConditionType_MonitoredNodeCount = 10156; /// /// The identifier for the Data_Static_Scalar_SimulationActive Variable. /// public const uint Data_Static_Scalar_SimulationActive = 10160; /// /// The identifier for the Data_Static_Scalar_GenerateValues_InputArguments Variable. /// public const uint Data_Static_Scalar_GenerateValues_InputArguments = 10162; /// /// The identifier for the Data_Static_Scalar_CycleComplete_EventId Variable. /// public const uint Data_Static_Scalar_CycleComplete_EventId = 10164; /// /// The identifier for the Data_Static_Scalar_CycleComplete_EventType Variable. /// public const uint Data_Static_Scalar_CycleComplete_EventType = 10165; /// /// The identifier for the Data_Static_Scalar_CycleComplete_SourceNode Variable. /// public const uint Data_Static_Scalar_CycleComplete_SourceNode = 10166; /// /// The identifier for the Data_Static_Scalar_CycleComplete_SourceName Variable. /// public const uint Data_Static_Scalar_CycleComplete_SourceName = 10167; /// /// The identifier for the Data_Static_Scalar_CycleComplete_Time Variable. /// public const uint Data_Static_Scalar_CycleComplete_Time = 10168; /// /// The identifier for the Data_Static_Scalar_CycleComplete_ReceiveTime Variable. /// public const uint Data_Static_Scalar_CycleComplete_ReceiveTime = 10169; /// /// The identifier for the Data_Static_Scalar_CycleComplete_Message Variable. /// public const uint Data_Static_Scalar_CycleComplete_Message = 10171; /// /// The identifier for the Data_Static_Scalar_CycleComplete_Severity Variable. /// public const uint Data_Static_Scalar_CycleComplete_Severity = 10172; /// /// The identifier for the Data_Static_Scalar_CycleComplete_ConditionClassId Variable. /// public const uint Data_Static_Scalar_CycleComplete_ConditionClassId = 11594; /// /// The identifier for the Data_Static_Scalar_CycleComplete_ConditionClassName Variable. /// public const uint Data_Static_Scalar_CycleComplete_ConditionClassName = 11595; /// /// The identifier for the Data_Static_Scalar_CycleComplete_ConditionName Variable. /// public const uint Data_Static_Scalar_CycleComplete_ConditionName = 11565; /// /// The identifier for the Data_Static_Scalar_CycleComplete_BranchId Variable. /// public const uint Data_Static_Scalar_CycleComplete_BranchId = 10173; /// /// The identifier for the Data_Static_Scalar_CycleComplete_Retain Variable. /// public const uint Data_Static_Scalar_CycleComplete_Retain = 10174; /// /// The identifier for the Data_Static_Scalar_CycleComplete_EnabledState Variable. /// public const uint Data_Static_Scalar_CycleComplete_EnabledState = 10175; /// /// The identifier for the Data_Static_Scalar_CycleComplete_EnabledState_Id Variable. /// public const uint Data_Static_Scalar_CycleComplete_EnabledState_Id = 10176; /// /// The identifier for the Data_Static_Scalar_CycleComplete_Quality Variable. /// public const uint Data_Static_Scalar_CycleComplete_Quality = 10181; /// /// The identifier for the Data_Static_Scalar_CycleComplete_Quality_SourceTimestamp Variable. /// public const uint Data_Static_Scalar_CycleComplete_Quality_SourceTimestamp = 10182; /// /// The identifier for the Data_Static_Scalar_CycleComplete_LastSeverity Variable. /// public const uint Data_Static_Scalar_CycleComplete_LastSeverity = 10185; /// /// The identifier for the Data_Static_Scalar_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public const uint Data_Static_Scalar_CycleComplete_LastSeverity_SourceTimestamp = 10186; /// /// The identifier for the Data_Static_Scalar_CycleComplete_Comment Variable. /// public const uint Data_Static_Scalar_CycleComplete_Comment = 10187; /// /// The identifier for the Data_Static_Scalar_CycleComplete_Comment_SourceTimestamp Variable. /// public const uint Data_Static_Scalar_CycleComplete_Comment_SourceTimestamp = 10188; /// /// The identifier for the Data_Static_Scalar_CycleComplete_ClientUserId Variable. /// public const uint Data_Static_Scalar_CycleComplete_ClientUserId = 10189; /// /// The identifier for the Data_Static_Scalar_CycleComplete_AddComment_InputArguments Variable. /// public const uint Data_Static_Scalar_CycleComplete_AddComment_InputArguments = 10193; /// /// The identifier for the Data_Static_Scalar_CycleComplete_AckedState Variable. /// public const uint Data_Static_Scalar_CycleComplete_AckedState = 10196; /// /// The identifier for the Data_Static_Scalar_CycleComplete_AckedState_Id Variable. /// public const uint Data_Static_Scalar_CycleComplete_AckedState_Id = 10197; /// /// The identifier for the Data_Static_Scalar_CycleComplete_ConfirmedState_Id Variable. /// public const uint Data_Static_Scalar_CycleComplete_ConfirmedState_Id = 10205; /// /// The identifier for the Data_Static_Scalar_CycleComplete_Acknowledge_InputArguments Variable. /// public const uint Data_Static_Scalar_CycleComplete_Acknowledge_InputArguments = 10213; /// /// The identifier for the Data_Static_Scalar_CycleComplete_Confirm_InputArguments Variable. /// public const uint Data_Static_Scalar_CycleComplete_Confirm_InputArguments = 10215; /// /// The identifier for the Data_Static_Scalar_BooleanValue Variable. /// public const uint Data_Static_Scalar_BooleanValue = 10216; /// /// The identifier for the Data_Static_Scalar_SByteValue Variable. /// public const uint Data_Static_Scalar_SByteValue = 10217; /// /// The identifier for the Data_Static_Scalar_ByteValue Variable. /// public const uint Data_Static_Scalar_ByteValue = 10218; /// /// The identifier for the Data_Static_Scalar_Int16Value Variable. /// public const uint Data_Static_Scalar_Int16Value = 10219; /// /// The identifier for the Data_Static_Scalar_UInt16Value Variable. /// public const uint Data_Static_Scalar_UInt16Value = 10220; /// /// The identifier for the Data_Static_Scalar_Int32Value Variable. /// public const uint Data_Static_Scalar_Int32Value = 10221; /// /// The identifier for the Data_Static_Scalar_UInt32Value Variable. /// public const uint Data_Static_Scalar_UInt32Value = 10222; /// /// The identifier for the Data_Static_Scalar_Int64Value Variable. /// public const uint Data_Static_Scalar_Int64Value = 10223; /// /// The identifier for the Data_Static_Scalar_UInt64Value Variable. /// public const uint Data_Static_Scalar_UInt64Value = 10224; /// /// The identifier for the Data_Static_Scalar_FloatValue Variable. /// public const uint Data_Static_Scalar_FloatValue = 10225; /// /// The identifier for the Data_Static_Scalar_DoubleValue Variable. /// public const uint Data_Static_Scalar_DoubleValue = 10226; /// /// The identifier for the Data_Static_Scalar_StringValue Variable. /// public const uint Data_Static_Scalar_StringValue = 10227; /// /// The identifier for the Data_Static_Scalar_DateTimeValue Variable. /// public const uint Data_Static_Scalar_DateTimeValue = 10228; /// /// The identifier for the Data_Static_Scalar_GuidValue Variable. /// public const uint Data_Static_Scalar_GuidValue = 10229; /// /// The identifier for the Data_Static_Scalar_ByteStringValue Variable. /// public const uint Data_Static_Scalar_ByteStringValue = 10230; /// /// The identifier for the Data_Static_Scalar_XmlElementValue Variable. /// public const uint Data_Static_Scalar_XmlElementValue = 10231; /// /// The identifier for the Data_Static_Scalar_NodeIdValue Variable. /// public const uint Data_Static_Scalar_NodeIdValue = 10232; /// /// The identifier for the Data_Static_Scalar_ExpandedNodeIdValue Variable. /// public const uint Data_Static_Scalar_ExpandedNodeIdValue = 10233; /// /// The identifier for the Data_Static_Scalar_QualifiedNameValue Variable. /// public const uint Data_Static_Scalar_QualifiedNameValue = 10234; /// /// The identifier for the Data_Static_Scalar_LocalizedTextValue Variable. /// public const uint Data_Static_Scalar_LocalizedTextValue = 10235; /// /// The identifier for the Data_Static_Scalar_StatusCodeValue Variable. /// public const uint Data_Static_Scalar_StatusCodeValue = 10236; /// /// The identifier for the Data_Static_Scalar_VariantValue Variable. /// public const uint Data_Static_Scalar_VariantValue = 10237; /// /// The identifier for the Data_Static_Scalar_EnumerationValue Variable. /// public const uint Data_Static_Scalar_EnumerationValue = 10238; /// /// The identifier for the Data_Static_Scalar_StructureValue Variable. /// public const uint Data_Static_Scalar_StructureValue = 10239; /// /// The identifier for the Data_Static_Scalar_NumberValue Variable. /// public const uint Data_Static_Scalar_NumberValue = 10240; /// /// The identifier for the Data_Static_Scalar_IntegerValue Variable. /// public const uint Data_Static_Scalar_IntegerValue = 10241; /// /// The identifier for the Data_Static_Scalar_UIntegerValue Variable. /// public const uint Data_Static_Scalar_UIntegerValue = 10242; /// /// The identifier for the Data_Static_Array_SimulationActive Variable. /// public const uint Data_Static_Array_SimulationActive = 10244; /// /// The identifier for the Data_Static_Array_GenerateValues_InputArguments Variable. /// public const uint Data_Static_Array_GenerateValues_InputArguments = 10246; /// /// The identifier for the Data_Static_Array_CycleComplete_EventId Variable. /// public const uint Data_Static_Array_CycleComplete_EventId = 10248; /// /// The identifier for the Data_Static_Array_CycleComplete_EventType Variable. /// public const uint Data_Static_Array_CycleComplete_EventType = 10249; /// /// The identifier for the Data_Static_Array_CycleComplete_SourceNode Variable. /// public const uint Data_Static_Array_CycleComplete_SourceNode = 10250; /// /// The identifier for the Data_Static_Array_CycleComplete_SourceName Variable. /// public const uint Data_Static_Array_CycleComplete_SourceName = 10251; /// /// The identifier for the Data_Static_Array_CycleComplete_Time Variable. /// public const uint Data_Static_Array_CycleComplete_Time = 10252; /// /// The identifier for the Data_Static_Array_CycleComplete_ReceiveTime Variable. /// public const uint Data_Static_Array_CycleComplete_ReceiveTime = 10253; /// /// The identifier for the Data_Static_Array_CycleComplete_Message Variable. /// public const uint Data_Static_Array_CycleComplete_Message = 10255; /// /// The identifier for the Data_Static_Array_CycleComplete_Severity Variable. /// public const uint Data_Static_Array_CycleComplete_Severity = 10256; /// /// The identifier for the Data_Static_Array_CycleComplete_ConditionClassId Variable. /// public const uint Data_Static_Array_CycleComplete_ConditionClassId = 11596; /// /// The identifier for the Data_Static_Array_CycleComplete_ConditionClassName Variable. /// public const uint Data_Static_Array_CycleComplete_ConditionClassName = 11597; /// /// The identifier for the Data_Static_Array_CycleComplete_ConditionName Variable. /// public const uint Data_Static_Array_CycleComplete_ConditionName = 11566; /// /// The identifier for the Data_Static_Array_CycleComplete_BranchId Variable. /// public const uint Data_Static_Array_CycleComplete_BranchId = 10257; /// /// The identifier for the Data_Static_Array_CycleComplete_Retain Variable. /// public const uint Data_Static_Array_CycleComplete_Retain = 10258; /// /// The identifier for the Data_Static_Array_CycleComplete_EnabledState Variable. /// public const uint Data_Static_Array_CycleComplete_EnabledState = 10259; /// /// The identifier for the Data_Static_Array_CycleComplete_EnabledState_Id Variable. /// public const uint Data_Static_Array_CycleComplete_EnabledState_Id = 10260; /// /// The identifier for the Data_Static_Array_CycleComplete_Quality Variable. /// public const uint Data_Static_Array_CycleComplete_Quality = 10265; /// /// The identifier for the Data_Static_Array_CycleComplete_Quality_SourceTimestamp Variable. /// public const uint Data_Static_Array_CycleComplete_Quality_SourceTimestamp = 10266; /// /// The identifier for the Data_Static_Array_CycleComplete_LastSeverity Variable. /// public const uint Data_Static_Array_CycleComplete_LastSeverity = 10269; /// /// The identifier for the Data_Static_Array_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public const uint Data_Static_Array_CycleComplete_LastSeverity_SourceTimestamp = 10270; /// /// The identifier for the Data_Static_Array_CycleComplete_Comment Variable. /// public const uint Data_Static_Array_CycleComplete_Comment = 10271; /// /// The identifier for the Data_Static_Array_CycleComplete_Comment_SourceTimestamp Variable. /// public const uint Data_Static_Array_CycleComplete_Comment_SourceTimestamp = 10272; /// /// The identifier for the Data_Static_Array_CycleComplete_ClientUserId Variable. /// public const uint Data_Static_Array_CycleComplete_ClientUserId = 10273; /// /// The identifier for the Data_Static_Array_CycleComplete_AddComment_InputArguments Variable. /// public const uint Data_Static_Array_CycleComplete_AddComment_InputArguments = 10277; /// /// The identifier for the Data_Static_Array_CycleComplete_AckedState Variable. /// public const uint Data_Static_Array_CycleComplete_AckedState = 10280; /// /// The identifier for the Data_Static_Array_CycleComplete_AckedState_Id Variable. /// public const uint Data_Static_Array_CycleComplete_AckedState_Id = 10281; /// /// The identifier for the Data_Static_Array_CycleComplete_ConfirmedState_Id Variable. /// public const uint Data_Static_Array_CycleComplete_ConfirmedState_Id = 10289; /// /// The identifier for the Data_Static_Array_CycleComplete_Acknowledge_InputArguments Variable. /// public const uint Data_Static_Array_CycleComplete_Acknowledge_InputArguments = 10297; /// /// The identifier for the Data_Static_Array_CycleComplete_Confirm_InputArguments Variable. /// public const uint Data_Static_Array_CycleComplete_Confirm_InputArguments = 10299; /// /// The identifier for the Data_Static_Array_BooleanValue Variable. /// public const uint Data_Static_Array_BooleanValue = 10300; /// /// The identifier for the Data_Static_Array_SByteValue Variable. /// public const uint Data_Static_Array_SByteValue = 10301; /// /// The identifier for the Data_Static_Array_ByteValue Variable. /// public const uint Data_Static_Array_ByteValue = 10302; /// /// The identifier for the Data_Static_Array_Int16Value Variable. /// public const uint Data_Static_Array_Int16Value = 10303; /// /// The identifier for the Data_Static_Array_UInt16Value Variable. /// public const uint Data_Static_Array_UInt16Value = 10304; /// /// The identifier for the Data_Static_Array_Int32Value Variable. /// public const uint Data_Static_Array_Int32Value = 10305; /// /// The identifier for the Data_Static_Array_UInt32Value Variable. /// public const uint Data_Static_Array_UInt32Value = 10306; /// /// The identifier for the Data_Static_Array_Int64Value Variable. /// public const uint Data_Static_Array_Int64Value = 10307; /// /// The identifier for the Data_Static_Array_UInt64Value Variable. /// public const uint Data_Static_Array_UInt64Value = 10308; /// /// The identifier for the Data_Static_Array_FloatValue Variable. /// public const uint Data_Static_Array_FloatValue = 10309; /// /// The identifier for the Data_Static_Array_DoubleValue Variable. /// public const uint Data_Static_Array_DoubleValue = 10310; /// /// The identifier for the Data_Static_Array_StringValue Variable. /// public const uint Data_Static_Array_StringValue = 10311; /// /// The identifier for the Data_Static_Array_DateTimeValue Variable. /// public const uint Data_Static_Array_DateTimeValue = 10312; /// /// The identifier for the Data_Static_Array_GuidValue Variable. /// public const uint Data_Static_Array_GuidValue = 10313; /// /// The identifier for the Data_Static_Array_ByteStringValue Variable. /// public const uint Data_Static_Array_ByteStringValue = 10314; /// /// The identifier for the Data_Static_Array_XmlElementValue Variable. /// public const uint Data_Static_Array_XmlElementValue = 10315; /// /// The identifier for the Data_Static_Array_NodeIdValue Variable. /// public const uint Data_Static_Array_NodeIdValue = 10316; /// /// The identifier for the Data_Static_Array_ExpandedNodeIdValue Variable. /// public const uint Data_Static_Array_ExpandedNodeIdValue = 10317; /// /// The identifier for the Data_Static_Array_QualifiedNameValue Variable. /// public const uint Data_Static_Array_QualifiedNameValue = 10318; /// /// The identifier for the Data_Static_Array_LocalizedTextValue Variable. /// public const uint Data_Static_Array_LocalizedTextValue = 10319; /// /// The identifier for the Data_Static_Array_StatusCodeValue Variable. /// public const uint Data_Static_Array_StatusCodeValue = 10320; /// /// The identifier for the Data_Static_Array_VariantValue Variable. /// public const uint Data_Static_Array_VariantValue = 10321; /// /// The identifier for the Data_Static_Array_EnumerationValue Variable. /// public const uint Data_Static_Array_EnumerationValue = 10322; /// /// The identifier for the Data_Static_Array_StructureValue Variable. /// public const uint Data_Static_Array_StructureValue = 10323; /// /// The identifier for the Data_Static_Array_NumberValue Variable. /// public const uint Data_Static_Array_NumberValue = 10324; /// /// The identifier for the Data_Static_Array_IntegerValue Variable. /// public const uint Data_Static_Array_IntegerValue = 10325; /// /// The identifier for the Data_Static_Array_UIntegerValue Variable. /// public const uint Data_Static_Array_UIntegerValue = 10326; /// /// The identifier for the Data_Static_UserScalar_SimulationActive Variable. /// public const uint Data_Static_UserScalar_SimulationActive = 10328; /// /// The identifier for the Data_Static_UserScalar_GenerateValues_InputArguments Variable. /// public const uint Data_Static_UserScalar_GenerateValues_InputArguments = 10330; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_EventId Variable. /// public const uint Data_Static_UserScalar_CycleComplete_EventId = 10332; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_EventType Variable. /// public const uint Data_Static_UserScalar_CycleComplete_EventType = 10333; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_SourceNode Variable. /// public const uint Data_Static_UserScalar_CycleComplete_SourceNode = 10334; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_SourceName Variable. /// public const uint Data_Static_UserScalar_CycleComplete_SourceName = 10335; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Time Variable. /// public const uint Data_Static_UserScalar_CycleComplete_Time = 10336; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_ReceiveTime Variable. /// public const uint Data_Static_UserScalar_CycleComplete_ReceiveTime = 10337; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Message Variable. /// public const uint Data_Static_UserScalar_CycleComplete_Message = 10339; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Severity Variable. /// public const uint Data_Static_UserScalar_CycleComplete_Severity = 10340; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_ConditionClassId Variable. /// public const uint Data_Static_UserScalar_CycleComplete_ConditionClassId = 11598; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_ConditionClassName Variable. /// public const uint Data_Static_UserScalar_CycleComplete_ConditionClassName = 11599; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_ConditionName Variable. /// public const uint Data_Static_UserScalar_CycleComplete_ConditionName = 11567; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_BranchId Variable. /// public const uint Data_Static_UserScalar_CycleComplete_BranchId = 10341; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Retain Variable. /// public const uint Data_Static_UserScalar_CycleComplete_Retain = 10342; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_EnabledState Variable. /// public const uint Data_Static_UserScalar_CycleComplete_EnabledState = 10343; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_EnabledState_Id Variable. /// public const uint Data_Static_UserScalar_CycleComplete_EnabledState_Id = 10344; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Quality Variable. /// public const uint Data_Static_UserScalar_CycleComplete_Quality = 10349; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Quality_SourceTimestamp Variable. /// public const uint Data_Static_UserScalar_CycleComplete_Quality_SourceTimestamp = 10350; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_LastSeverity Variable. /// public const uint Data_Static_UserScalar_CycleComplete_LastSeverity = 10353; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public const uint Data_Static_UserScalar_CycleComplete_LastSeverity_SourceTimestamp = 10354; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Comment Variable. /// public const uint Data_Static_UserScalar_CycleComplete_Comment = 10355; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Comment_SourceTimestamp Variable. /// public const uint Data_Static_UserScalar_CycleComplete_Comment_SourceTimestamp = 10356; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_ClientUserId Variable. /// public const uint Data_Static_UserScalar_CycleComplete_ClientUserId = 10357; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_AddComment_InputArguments Variable. /// public const uint Data_Static_UserScalar_CycleComplete_AddComment_InputArguments = 10361; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_AckedState Variable. /// public const uint Data_Static_UserScalar_CycleComplete_AckedState = 10364; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_AckedState_Id Variable. /// public const uint Data_Static_UserScalar_CycleComplete_AckedState_Id = 10365; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_ConfirmedState_Id Variable. /// public const uint Data_Static_UserScalar_CycleComplete_ConfirmedState_Id = 10373; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Acknowledge_InputArguments Variable. /// public const uint Data_Static_UserScalar_CycleComplete_Acknowledge_InputArguments = 10381; /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Confirm_InputArguments Variable. /// public const uint Data_Static_UserScalar_CycleComplete_Confirm_InputArguments = 10383; /// /// The identifier for the Data_Static_UserScalar_BooleanValue Variable. /// public const uint Data_Static_UserScalar_BooleanValue = 10384; /// /// The identifier for the Data_Static_UserScalar_SByteValue Variable. /// public const uint Data_Static_UserScalar_SByteValue = 10385; /// /// The identifier for the Data_Static_UserScalar_ByteValue Variable. /// public const uint Data_Static_UserScalar_ByteValue = 10386; /// /// The identifier for the Data_Static_UserScalar_Int16Value Variable. /// public const uint Data_Static_UserScalar_Int16Value = 10387; /// /// The identifier for the Data_Static_UserScalar_UInt16Value Variable. /// public const uint Data_Static_UserScalar_UInt16Value = 10388; /// /// The identifier for the Data_Static_UserScalar_Int32Value Variable. /// public const uint Data_Static_UserScalar_Int32Value = 10389; /// /// The identifier for the Data_Static_UserScalar_UInt32Value Variable. /// public const uint Data_Static_UserScalar_UInt32Value = 10390; /// /// The identifier for the Data_Static_UserScalar_Int64Value Variable. /// public const uint Data_Static_UserScalar_Int64Value = 10391; /// /// The identifier for the Data_Static_UserScalar_UInt64Value Variable. /// public const uint Data_Static_UserScalar_UInt64Value = 10392; /// /// The identifier for the Data_Static_UserScalar_FloatValue Variable. /// public const uint Data_Static_UserScalar_FloatValue = 10393; /// /// The identifier for the Data_Static_UserScalar_DoubleValue Variable. /// public const uint Data_Static_UserScalar_DoubleValue = 10394; /// /// The identifier for the Data_Static_UserScalar_StringValue Variable. /// public const uint Data_Static_UserScalar_StringValue = 10395; /// /// The identifier for the Data_Static_UserScalar_DateTimeValue Variable. /// public const uint Data_Static_UserScalar_DateTimeValue = 10396; /// /// The identifier for the Data_Static_UserScalar_GuidValue Variable. /// public const uint Data_Static_UserScalar_GuidValue = 10397; /// /// The identifier for the Data_Static_UserScalar_ByteStringValue Variable. /// public const uint Data_Static_UserScalar_ByteStringValue = 10398; /// /// The identifier for the Data_Static_UserScalar_XmlElementValue Variable. /// public const uint Data_Static_UserScalar_XmlElementValue = 10399; /// /// The identifier for the Data_Static_UserScalar_NodeIdValue Variable. /// public const uint Data_Static_UserScalar_NodeIdValue = 10400; /// /// The identifier for the Data_Static_UserScalar_ExpandedNodeIdValue Variable. /// public const uint Data_Static_UserScalar_ExpandedNodeIdValue = 10401; /// /// The identifier for the Data_Static_UserScalar_QualifiedNameValue Variable. /// public const uint Data_Static_UserScalar_QualifiedNameValue = 10402; /// /// The identifier for the Data_Static_UserScalar_LocalizedTextValue Variable. /// public const uint Data_Static_UserScalar_LocalizedTextValue = 10403; /// /// The identifier for the Data_Static_UserScalar_StatusCodeValue Variable. /// public const uint Data_Static_UserScalar_StatusCodeValue = 10404; /// /// The identifier for the Data_Static_UserScalar_VariantValue Variable. /// public const uint Data_Static_UserScalar_VariantValue = 10405; /// /// The identifier for the Data_Static_UserArray_SimulationActive Variable. /// public const uint Data_Static_UserArray_SimulationActive = 10407; /// /// The identifier for the Data_Static_UserArray_GenerateValues_InputArguments Variable. /// public const uint Data_Static_UserArray_GenerateValues_InputArguments = 10409; /// /// The identifier for the Data_Static_UserArray_CycleComplete_EventId Variable. /// public const uint Data_Static_UserArray_CycleComplete_EventId = 10411; /// /// The identifier for the Data_Static_UserArray_CycleComplete_EventType Variable. /// public const uint Data_Static_UserArray_CycleComplete_EventType = 10412; /// /// The identifier for the Data_Static_UserArray_CycleComplete_SourceNode Variable. /// public const uint Data_Static_UserArray_CycleComplete_SourceNode = 10413; /// /// The identifier for the Data_Static_UserArray_CycleComplete_SourceName Variable. /// public const uint Data_Static_UserArray_CycleComplete_SourceName = 10414; /// /// The identifier for the Data_Static_UserArray_CycleComplete_Time Variable. /// public const uint Data_Static_UserArray_CycleComplete_Time = 10415; /// /// The identifier for the Data_Static_UserArray_CycleComplete_ReceiveTime Variable. /// public const uint Data_Static_UserArray_CycleComplete_ReceiveTime = 10416; /// /// The identifier for the Data_Static_UserArray_CycleComplete_Message Variable. /// public const uint Data_Static_UserArray_CycleComplete_Message = 10418; /// /// The identifier for the Data_Static_UserArray_CycleComplete_Severity Variable. /// public const uint Data_Static_UserArray_CycleComplete_Severity = 10419; /// /// The identifier for the Data_Static_UserArray_CycleComplete_ConditionClassId Variable. /// public const uint Data_Static_UserArray_CycleComplete_ConditionClassId = 11600; /// /// The identifier for the Data_Static_UserArray_CycleComplete_ConditionClassName Variable. /// public const uint Data_Static_UserArray_CycleComplete_ConditionClassName = 11601; /// /// The identifier for the Data_Static_UserArray_CycleComplete_ConditionName Variable. /// public const uint Data_Static_UserArray_CycleComplete_ConditionName = 11568; /// /// The identifier for the Data_Static_UserArray_CycleComplete_BranchId Variable. /// public const uint Data_Static_UserArray_CycleComplete_BranchId = 10420; /// /// The identifier for the Data_Static_UserArray_CycleComplete_Retain Variable. /// public const uint Data_Static_UserArray_CycleComplete_Retain = 10421; /// /// The identifier for the Data_Static_UserArray_CycleComplete_EnabledState Variable. /// public const uint Data_Static_UserArray_CycleComplete_EnabledState = 10422; /// /// The identifier for the Data_Static_UserArray_CycleComplete_EnabledState_Id Variable. /// public const uint Data_Static_UserArray_CycleComplete_EnabledState_Id = 10423; /// /// The identifier for the Data_Static_UserArray_CycleComplete_Quality Variable. /// public const uint Data_Static_UserArray_CycleComplete_Quality = 10428; /// /// The identifier for the Data_Static_UserArray_CycleComplete_Quality_SourceTimestamp Variable. /// public const uint Data_Static_UserArray_CycleComplete_Quality_SourceTimestamp = 10429; /// /// The identifier for the Data_Static_UserArray_CycleComplete_LastSeverity Variable. /// public const uint Data_Static_UserArray_CycleComplete_LastSeverity = 10432; /// /// The identifier for the Data_Static_UserArray_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public const uint Data_Static_UserArray_CycleComplete_LastSeverity_SourceTimestamp = 10433; /// /// The identifier for the Data_Static_UserArray_CycleComplete_Comment Variable. /// public const uint Data_Static_UserArray_CycleComplete_Comment = 10434; /// /// The identifier for the Data_Static_UserArray_CycleComplete_Comment_SourceTimestamp Variable. /// public const uint Data_Static_UserArray_CycleComplete_Comment_SourceTimestamp = 10435; /// /// The identifier for the Data_Static_UserArray_CycleComplete_ClientUserId Variable. /// public const uint Data_Static_UserArray_CycleComplete_ClientUserId = 10436; /// /// The identifier for the Data_Static_UserArray_CycleComplete_AddComment_InputArguments Variable. /// public const uint Data_Static_UserArray_CycleComplete_AddComment_InputArguments = 10440; /// /// The identifier for the Data_Static_UserArray_CycleComplete_AckedState Variable. /// public const uint Data_Static_UserArray_CycleComplete_AckedState = 10443; /// /// The identifier for the Data_Static_UserArray_CycleComplete_AckedState_Id Variable. /// public const uint Data_Static_UserArray_CycleComplete_AckedState_Id = 10444; /// /// The identifier for the Data_Static_UserArray_CycleComplete_ConfirmedState_Id Variable. /// public const uint Data_Static_UserArray_CycleComplete_ConfirmedState_Id = 10452; /// /// The identifier for the Data_Static_UserArray_CycleComplete_Acknowledge_InputArguments Variable. /// public const uint Data_Static_UserArray_CycleComplete_Acknowledge_InputArguments = 10460; /// /// The identifier for the Data_Static_UserArray_CycleComplete_Confirm_InputArguments Variable. /// public const uint Data_Static_UserArray_CycleComplete_Confirm_InputArguments = 10462; /// /// The identifier for the Data_Static_UserArray_BooleanValue Variable. /// public const uint Data_Static_UserArray_BooleanValue = 10463; /// /// The identifier for the Data_Static_UserArray_SByteValue Variable. /// public const uint Data_Static_UserArray_SByteValue = 10464; /// /// The identifier for the Data_Static_UserArray_ByteValue Variable. /// public const uint Data_Static_UserArray_ByteValue = 10465; /// /// The identifier for the Data_Static_UserArray_Int16Value Variable. /// public const uint Data_Static_UserArray_Int16Value = 10466; /// /// The identifier for the Data_Static_UserArray_UInt16Value Variable. /// public const uint Data_Static_UserArray_UInt16Value = 10467; /// /// The identifier for the Data_Static_UserArray_Int32Value Variable. /// public const uint Data_Static_UserArray_Int32Value = 10468; /// /// The identifier for the Data_Static_UserArray_UInt32Value Variable. /// public const uint Data_Static_UserArray_UInt32Value = 10469; /// /// The identifier for the Data_Static_UserArray_Int64Value Variable. /// public const uint Data_Static_UserArray_Int64Value = 10470; /// /// The identifier for the Data_Static_UserArray_UInt64Value Variable. /// public const uint Data_Static_UserArray_UInt64Value = 10471; /// /// The identifier for the Data_Static_UserArray_FloatValue Variable. /// public const uint Data_Static_UserArray_FloatValue = 10472; /// /// The identifier for the Data_Static_UserArray_DoubleValue Variable. /// public const uint Data_Static_UserArray_DoubleValue = 10473; /// /// The identifier for the Data_Static_UserArray_StringValue Variable. /// public const uint Data_Static_UserArray_StringValue = 10474; /// /// The identifier for the Data_Static_UserArray_DateTimeValue Variable. /// public const uint Data_Static_UserArray_DateTimeValue = 10475; /// /// The identifier for the Data_Static_UserArray_GuidValue Variable. /// public const uint Data_Static_UserArray_GuidValue = 10476; /// /// The identifier for the Data_Static_UserArray_ByteStringValue Variable. /// public const uint Data_Static_UserArray_ByteStringValue = 10477; /// /// The identifier for the Data_Static_UserArray_XmlElementValue Variable. /// public const uint Data_Static_UserArray_XmlElementValue = 10478; /// /// The identifier for the Data_Static_UserArray_NodeIdValue Variable. /// public const uint Data_Static_UserArray_NodeIdValue = 10479; /// /// The identifier for the Data_Static_UserArray_ExpandedNodeIdValue Variable. /// public const uint Data_Static_UserArray_ExpandedNodeIdValue = 10480; /// /// The identifier for the Data_Static_UserArray_QualifiedNameValue Variable. /// public const uint Data_Static_UserArray_QualifiedNameValue = 10481; /// /// The identifier for the Data_Static_UserArray_LocalizedTextValue Variable. /// public const uint Data_Static_UserArray_LocalizedTextValue = 10482; /// /// The identifier for the Data_Static_UserArray_StatusCodeValue Variable. /// public const uint Data_Static_UserArray_StatusCodeValue = 10483; /// /// The identifier for the Data_Static_UserArray_VariantValue Variable. /// public const uint Data_Static_UserArray_VariantValue = 10484; /// /// The identifier for the Data_Static_AnalogScalar_SimulationActive Variable. /// public const uint Data_Static_AnalogScalar_SimulationActive = 10486; /// /// The identifier for the Data_Static_AnalogScalar_GenerateValues_InputArguments Variable. /// public const uint Data_Static_AnalogScalar_GenerateValues_InputArguments = 10488; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_EventId Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_EventId = 10490; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_EventType Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_EventType = 10491; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_SourceNode Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_SourceNode = 10492; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_SourceName Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_SourceName = 10493; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Time Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_Time = 10494; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_ReceiveTime Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_ReceiveTime = 10495; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Message Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_Message = 10497; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Severity Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_Severity = 10498; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_ConditionClassId Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_ConditionClassId = 11602; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_ConditionClassName Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_ConditionClassName = 11603; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_ConditionName Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_ConditionName = 11569; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_BranchId Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_BranchId = 10499; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Retain Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_Retain = 10500; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_EnabledState Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_EnabledState = 10501; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_EnabledState_Id Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_EnabledState_Id = 10502; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Quality Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_Quality = 10507; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Quality_SourceTimestamp Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_Quality_SourceTimestamp = 10508; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_LastSeverity Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_LastSeverity = 10511; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_LastSeverity_SourceTimestamp = 10512; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Comment Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_Comment = 10513; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Comment_SourceTimestamp Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_Comment_SourceTimestamp = 10514; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_ClientUserId Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_ClientUserId = 10515; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_AddComment_InputArguments Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_AddComment_InputArguments = 10519; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_AckedState Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_AckedState = 10522; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_AckedState_Id Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_AckedState_Id = 10523; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_ConfirmedState_Id Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_ConfirmedState_Id = 10531; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Acknowledge_InputArguments Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_Acknowledge_InputArguments = 10539; /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Confirm_InputArguments Variable. /// public const uint Data_Static_AnalogScalar_CycleComplete_Confirm_InputArguments = 10541; /// /// The identifier for the Data_Static_AnalogScalar_SByteValue Variable. /// public const uint Data_Static_AnalogScalar_SByteValue = 10542; /// /// The identifier for the Data_Static_AnalogScalar_SByteValue_EURange Variable. /// public const uint Data_Static_AnalogScalar_SByteValue_EURange = 10545; /// /// The identifier for the Data_Static_AnalogScalar_ByteValue Variable. /// public const uint Data_Static_AnalogScalar_ByteValue = 10548; /// /// The identifier for the Data_Static_AnalogScalar_ByteValue_EURange Variable. /// public const uint Data_Static_AnalogScalar_ByteValue_EURange = 10551; /// /// The identifier for the Data_Static_AnalogScalar_Int16Value Variable. /// public const uint Data_Static_AnalogScalar_Int16Value = 10554; /// /// The identifier for the Data_Static_AnalogScalar_Int16Value_EURange Variable. /// public const uint Data_Static_AnalogScalar_Int16Value_EURange = 10557; /// /// The identifier for the Data_Static_AnalogScalar_UInt16Value Variable. /// public const uint Data_Static_AnalogScalar_UInt16Value = 10560; /// /// The identifier for the Data_Static_AnalogScalar_UInt16Value_EURange Variable. /// public const uint Data_Static_AnalogScalar_UInt16Value_EURange = 10563; /// /// The identifier for the Data_Static_AnalogScalar_Int32Value Variable. /// public const uint Data_Static_AnalogScalar_Int32Value = 10566; /// /// The identifier for the Data_Static_AnalogScalar_Int32Value_EURange Variable. /// public const uint Data_Static_AnalogScalar_Int32Value_EURange = 10569; /// /// The identifier for the Data_Static_AnalogScalar_UInt32Value Variable. /// public const uint Data_Static_AnalogScalar_UInt32Value = 10572; /// /// The identifier for the Data_Static_AnalogScalar_UInt32Value_EURange Variable. /// public const uint Data_Static_AnalogScalar_UInt32Value_EURange = 10575; /// /// The identifier for the Data_Static_AnalogScalar_Int64Value Variable. /// public const uint Data_Static_AnalogScalar_Int64Value = 10578; /// /// The identifier for the Data_Static_AnalogScalar_Int64Value_EURange Variable. /// public const uint Data_Static_AnalogScalar_Int64Value_EURange = 10581; /// /// The identifier for the Data_Static_AnalogScalar_UInt64Value Variable. /// public const uint Data_Static_AnalogScalar_UInt64Value = 10584; /// /// The identifier for the Data_Static_AnalogScalar_UInt64Value_EURange Variable. /// public const uint Data_Static_AnalogScalar_UInt64Value_EURange = 10587; /// /// The identifier for the Data_Static_AnalogScalar_FloatValue Variable. /// public const uint Data_Static_AnalogScalar_FloatValue = 10590; /// /// The identifier for the Data_Static_AnalogScalar_FloatValue_EURange Variable. /// public const uint Data_Static_AnalogScalar_FloatValue_EURange = 10593; /// /// The identifier for the Data_Static_AnalogScalar_DoubleValue Variable. /// public const uint Data_Static_AnalogScalar_DoubleValue = 10596; /// /// The identifier for the Data_Static_AnalogScalar_DoubleValue_EURange Variable. /// public const uint Data_Static_AnalogScalar_DoubleValue_EURange = 10599; /// /// The identifier for the Data_Static_AnalogScalar_NumberValue Variable. /// public const uint Data_Static_AnalogScalar_NumberValue = 10602; /// /// The identifier for the Data_Static_AnalogScalar_NumberValue_EURange Variable. /// public const uint Data_Static_AnalogScalar_NumberValue_EURange = 10605; /// /// The identifier for the Data_Static_AnalogScalar_IntegerValue Variable. /// public const uint Data_Static_AnalogScalar_IntegerValue = 10608; /// /// The identifier for the Data_Static_AnalogScalar_IntegerValue_EURange Variable. /// public const uint Data_Static_AnalogScalar_IntegerValue_EURange = 10611; /// /// The identifier for the Data_Static_AnalogScalar_UIntegerValue Variable. /// public const uint Data_Static_AnalogScalar_UIntegerValue = 10614; /// /// The identifier for the Data_Static_AnalogScalar_UIntegerValue_EURange Variable. /// public const uint Data_Static_AnalogScalar_UIntegerValue_EURange = 10617; /// /// The identifier for the Data_Static_AnalogArray_SimulationActive Variable. /// public const uint Data_Static_AnalogArray_SimulationActive = 10621; /// /// The identifier for the Data_Static_AnalogArray_GenerateValues_InputArguments Variable. /// public const uint Data_Static_AnalogArray_GenerateValues_InputArguments = 10623; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_EventId Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_EventId = 10625; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_EventType Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_EventType = 10626; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_SourceNode Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_SourceNode = 10627; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_SourceName Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_SourceName = 10628; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Time Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_Time = 10629; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_ReceiveTime Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_ReceiveTime = 10630; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Message Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_Message = 10632; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Severity Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_Severity = 10633; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_ConditionClassId Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_ConditionClassId = 11604; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_ConditionClassName Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_ConditionClassName = 11605; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_ConditionName Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_ConditionName = 11570; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_BranchId Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_BranchId = 10634; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Retain Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_Retain = 10635; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_EnabledState Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_EnabledState = 10636; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_EnabledState_Id Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_EnabledState_Id = 10637; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Quality Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_Quality = 10642; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Quality_SourceTimestamp Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_Quality_SourceTimestamp = 10643; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_LastSeverity Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_LastSeverity = 10646; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_LastSeverity_SourceTimestamp = 10647; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Comment Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_Comment = 10648; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Comment_SourceTimestamp Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_Comment_SourceTimestamp = 10649; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_ClientUserId Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_ClientUserId = 10650; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_AddComment_InputArguments Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_AddComment_InputArguments = 10654; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_AckedState Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_AckedState = 10657; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_AckedState_Id Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_AckedState_Id = 10658; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_ConfirmedState_Id Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_ConfirmedState_Id = 10666; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Acknowledge_InputArguments Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_Acknowledge_InputArguments = 10674; /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Confirm_InputArguments Variable. /// public const uint Data_Static_AnalogArray_CycleComplete_Confirm_InputArguments = 10676; /// /// The identifier for the Data_Static_AnalogArray_SByteValue Variable. /// public const uint Data_Static_AnalogArray_SByteValue = 10677; /// /// The identifier for the Data_Static_AnalogArray_SByteValue_EURange Variable. /// public const uint Data_Static_AnalogArray_SByteValue_EURange = 10680; /// /// The identifier for the Data_Static_AnalogArray_ByteValue Variable. /// public const uint Data_Static_AnalogArray_ByteValue = 10683; /// /// The identifier for the Data_Static_AnalogArray_ByteValue_EURange Variable. /// public const uint Data_Static_AnalogArray_ByteValue_EURange = 10686; /// /// The identifier for the Data_Static_AnalogArray_Int16Value Variable. /// public const uint Data_Static_AnalogArray_Int16Value = 10689; /// /// The identifier for the Data_Static_AnalogArray_Int16Value_EURange Variable. /// public const uint Data_Static_AnalogArray_Int16Value_EURange = 10692; /// /// The identifier for the Data_Static_AnalogArray_UInt16Value Variable. /// public const uint Data_Static_AnalogArray_UInt16Value = 10695; /// /// The identifier for the Data_Static_AnalogArray_UInt16Value_EURange Variable. /// public const uint Data_Static_AnalogArray_UInt16Value_EURange = 10698; /// /// The identifier for the Data_Static_AnalogArray_Int32Value Variable. /// public const uint Data_Static_AnalogArray_Int32Value = 10701; /// /// The identifier for the Data_Static_AnalogArray_Int32Value_EURange Variable. /// public const uint Data_Static_AnalogArray_Int32Value_EURange = 10704; /// /// The identifier for the Data_Static_AnalogArray_UInt32Value Variable. /// public const uint Data_Static_AnalogArray_UInt32Value = 10707; /// /// The identifier for the Data_Static_AnalogArray_UInt32Value_EURange Variable. /// public const uint Data_Static_AnalogArray_UInt32Value_EURange = 10710; /// /// The identifier for the Data_Static_AnalogArray_Int64Value Variable. /// public const uint Data_Static_AnalogArray_Int64Value = 10713; /// /// The identifier for the Data_Static_AnalogArray_Int64Value_EURange Variable. /// public const uint Data_Static_AnalogArray_Int64Value_EURange = 10716; /// /// The identifier for the Data_Static_AnalogArray_UInt64Value Variable. /// public const uint Data_Static_AnalogArray_UInt64Value = 10719; /// /// The identifier for the Data_Static_AnalogArray_UInt64Value_EURange Variable. /// public const uint Data_Static_AnalogArray_UInt64Value_EURange = 10722; /// /// The identifier for the Data_Static_AnalogArray_FloatValue Variable. /// public const uint Data_Static_AnalogArray_FloatValue = 10725; /// /// The identifier for the Data_Static_AnalogArray_FloatValue_EURange Variable. /// public const uint Data_Static_AnalogArray_FloatValue_EURange = 10728; /// /// The identifier for the Data_Static_AnalogArray_DoubleValue Variable. /// public const uint Data_Static_AnalogArray_DoubleValue = 10731; /// /// The identifier for the Data_Static_AnalogArray_DoubleValue_EURange Variable. /// public const uint Data_Static_AnalogArray_DoubleValue_EURange = 10734; /// /// The identifier for the Data_Static_AnalogArray_NumberValue Variable. /// public const uint Data_Static_AnalogArray_NumberValue = 10737; /// /// The identifier for the Data_Static_AnalogArray_NumberValue_EURange Variable. /// public const uint Data_Static_AnalogArray_NumberValue_EURange = 10740; /// /// The identifier for the Data_Static_AnalogArray_IntegerValue Variable. /// public const uint Data_Static_AnalogArray_IntegerValue = 10743; /// /// The identifier for the Data_Static_AnalogArray_IntegerValue_EURange Variable. /// public const uint Data_Static_AnalogArray_IntegerValue_EURange = 10746; /// /// The identifier for the Data_Static_AnalogArray_UIntegerValue Variable. /// public const uint Data_Static_AnalogArray_UIntegerValue = 10749; /// /// The identifier for the Data_Static_AnalogArray_UIntegerValue_EURange Variable. /// public const uint Data_Static_AnalogArray_UIntegerValue_EURange = 10752; /// /// The identifier for the Data_Static_MethodTest_ScalarMethod1_InputArguments Variable. /// public const uint Data_Static_MethodTest_ScalarMethod1_InputArguments = 10757; /// /// The identifier for the Data_Static_MethodTest_ScalarMethod1_OutputArguments Variable. /// public const uint Data_Static_MethodTest_ScalarMethod1_OutputArguments = 10758; /// /// The identifier for the Data_Static_MethodTest_ScalarMethod2_InputArguments Variable. /// public const uint Data_Static_MethodTest_ScalarMethod2_InputArguments = 10760; /// /// The identifier for the Data_Static_MethodTest_ScalarMethod2_OutputArguments Variable. /// public const uint Data_Static_MethodTest_ScalarMethod2_OutputArguments = 10761; /// /// The identifier for the Data_Static_MethodTest_ScalarMethod3_InputArguments Variable. /// public const uint Data_Static_MethodTest_ScalarMethod3_InputArguments = 10763; /// /// The identifier for the Data_Static_MethodTest_ScalarMethod3_OutputArguments Variable. /// public const uint Data_Static_MethodTest_ScalarMethod3_OutputArguments = 10764; /// /// The identifier for the Data_Static_MethodTest_ArrayMethod1_InputArguments Variable. /// public const uint Data_Static_MethodTest_ArrayMethod1_InputArguments = 10766; /// /// The identifier for the Data_Static_MethodTest_ArrayMethod1_OutputArguments Variable. /// public const uint Data_Static_MethodTest_ArrayMethod1_OutputArguments = 10767; /// /// The identifier for the Data_Static_MethodTest_ArrayMethod2_InputArguments Variable. /// public const uint Data_Static_MethodTest_ArrayMethod2_InputArguments = 10769; /// /// The identifier for the Data_Static_MethodTest_ArrayMethod2_OutputArguments Variable. /// public const uint Data_Static_MethodTest_ArrayMethod2_OutputArguments = 10770; /// /// The identifier for the Data_Static_MethodTest_ArrayMethod3_InputArguments Variable. /// public const uint Data_Static_MethodTest_ArrayMethod3_InputArguments = 10772; /// /// The identifier for the Data_Static_MethodTest_ArrayMethod3_OutputArguments Variable. /// public const uint Data_Static_MethodTest_ArrayMethod3_OutputArguments = 10773; /// /// The identifier for the Data_Static_MethodTest_UserScalarMethod1_InputArguments Variable. /// public const uint Data_Static_MethodTest_UserScalarMethod1_InputArguments = 10775; /// /// The identifier for the Data_Static_MethodTest_UserScalarMethod1_OutputArguments Variable. /// public const uint Data_Static_MethodTest_UserScalarMethod1_OutputArguments = 10776; /// /// The identifier for the Data_Static_MethodTest_UserScalarMethod2_InputArguments Variable. /// public const uint Data_Static_MethodTest_UserScalarMethod2_InputArguments = 10778; /// /// The identifier for the Data_Static_MethodTest_UserScalarMethod2_OutputArguments Variable. /// public const uint Data_Static_MethodTest_UserScalarMethod2_OutputArguments = 10779; /// /// The identifier for the Data_Static_MethodTest_UserArrayMethod1_InputArguments Variable. /// public const uint Data_Static_MethodTest_UserArrayMethod1_InputArguments = 10781; /// /// The identifier for the Data_Static_MethodTest_UserArrayMethod1_OutputArguments Variable. /// public const uint Data_Static_MethodTest_UserArrayMethod1_OutputArguments = 10782; /// /// The identifier for the Data_Static_MethodTest_UserArrayMethod2_InputArguments Variable. /// public const uint Data_Static_MethodTest_UserArrayMethod2_InputArguments = 10784; /// /// The identifier for the Data_Static_MethodTest_UserArrayMethod2_OutputArguments Variable. /// public const uint Data_Static_MethodTest_UserArrayMethod2_OutputArguments = 10785; /// /// The identifier for the Data_Dynamic_Scalar_SimulationActive Variable. /// public const uint Data_Dynamic_Scalar_SimulationActive = 10788; /// /// The identifier for the Data_Dynamic_Scalar_GenerateValues_InputArguments Variable. /// public const uint Data_Dynamic_Scalar_GenerateValues_InputArguments = 10790; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_EventId Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_EventId = 10792; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_EventType Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_EventType = 10793; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_SourceNode Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_SourceNode = 10794; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_SourceName Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_SourceName = 10795; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Time Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_Time = 10796; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_ReceiveTime Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_ReceiveTime = 10797; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Message Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_Message = 10799; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Severity Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_Severity = 10800; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_ConditionClassId Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_ConditionClassId = 11606; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_ConditionClassName Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_ConditionClassName = 11607; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_ConditionName Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_ConditionName = 11571; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_BranchId Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_BranchId = 10801; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Retain Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_Retain = 10802; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_EnabledState Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_EnabledState = 10803; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_EnabledState_Id Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_EnabledState_Id = 10804; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Quality Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_Quality = 10809; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Quality_SourceTimestamp Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_Quality_SourceTimestamp = 10810; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_LastSeverity Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_LastSeverity = 10813; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_LastSeverity_SourceTimestamp = 10814; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Comment Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_Comment = 10815; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Comment_SourceTimestamp Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_Comment_SourceTimestamp = 10816; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_ClientUserId Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_ClientUserId = 10817; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_AddComment_InputArguments Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_AddComment_InputArguments = 10821; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_AckedState Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_AckedState = 10824; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_AckedState_Id Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_AckedState_Id = 10825; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_ConfirmedState_Id Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_ConfirmedState_Id = 10833; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Acknowledge_InputArguments Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_Acknowledge_InputArguments = 10841; /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Confirm_InputArguments Variable. /// public const uint Data_Dynamic_Scalar_CycleComplete_Confirm_InputArguments = 10843; /// /// The identifier for the Data_Dynamic_Scalar_BooleanValue Variable. /// public const uint Data_Dynamic_Scalar_BooleanValue = 10844; /// /// The identifier for the Data_Dynamic_Scalar_SByteValue Variable. /// public const uint Data_Dynamic_Scalar_SByteValue = 10845; /// /// The identifier for the Data_Dynamic_Scalar_ByteValue Variable. /// public const uint Data_Dynamic_Scalar_ByteValue = 10846; /// /// The identifier for the Data_Dynamic_Scalar_Int16Value Variable. /// public const uint Data_Dynamic_Scalar_Int16Value = 10847; /// /// The identifier for the Data_Dynamic_Scalar_UInt16Value Variable. /// public const uint Data_Dynamic_Scalar_UInt16Value = 10848; /// /// The identifier for the Data_Dynamic_Scalar_Int32Value Variable. /// public const uint Data_Dynamic_Scalar_Int32Value = 10849; /// /// The identifier for the Data_Dynamic_Scalar_UInt32Value Variable. /// public const uint Data_Dynamic_Scalar_UInt32Value = 10850; /// /// The identifier for the Data_Dynamic_Scalar_Int64Value Variable. /// public const uint Data_Dynamic_Scalar_Int64Value = 10851; /// /// The identifier for the Data_Dynamic_Scalar_UInt64Value Variable. /// public const uint Data_Dynamic_Scalar_UInt64Value = 10852; /// /// The identifier for the Data_Dynamic_Scalar_FloatValue Variable. /// public const uint Data_Dynamic_Scalar_FloatValue = 10853; /// /// The identifier for the Data_Dynamic_Scalar_DoubleValue Variable. /// public const uint Data_Dynamic_Scalar_DoubleValue = 10854; /// /// The identifier for the Data_Dynamic_Scalar_StringValue Variable. /// public const uint Data_Dynamic_Scalar_StringValue = 10855; /// /// The identifier for the Data_Dynamic_Scalar_DateTimeValue Variable. /// public const uint Data_Dynamic_Scalar_DateTimeValue = 10856; /// /// The identifier for the Data_Dynamic_Scalar_GuidValue Variable. /// public const uint Data_Dynamic_Scalar_GuidValue = 10857; /// /// The identifier for the Data_Dynamic_Scalar_ByteStringValue Variable. /// public const uint Data_Dynamic_Scalar_ByteStringValue = 10858; /// /// The identifier for the Data_Dynamic_Scalar_XmlElementValue Variable. /// public const uint Data_Dynamic_Scalar_XmlElementValue = 10859; /// /// The identifier for the Data_Dynamic_Scalar_NodeIdValue Variable. /// public const uint Data_Dynamic_Scalar_NodeIdValue = 10860; /// /// The identifier for the Data_Dynamic_Scalar_ExpandedNodeIdValue Variable. /// public const uint Data_Dynamic_Scalar_ExpandedNodeIdValue = 10861; /// /// The identifier for the Data_Dynamic_Scalar_QualifiedNameValue Variable. /// public const uint Data_Dynamic_Scalar_QualifiedNameValue = 10862; /// /// The identifier for the Data_Dynamic_Scalar_LocalizedTextValue Variable. /// public const uint Data_Dynamic_Scalar_LocalizedTextValue = 10863; /// /// The identifier for the Data_Dynamic_Scalar_StatusCodeValue Variable. /// public const uint Data_Dynamic_Scalar_StatusCodeValue = 10864; /// /// The identifier for the Data_Dynamic_Scalar_VariantValue Variable. /// public const uint Data_Dynamic_Scalar_VariantValue = 10865; /// /// The identifier for the Data_Dynamic_Scalar_EnumerationValue Variable. /// public const uint Data_Dynamic_Scalar_EnumerationValue = 10866; /// /// The identifier for the Data_Dynamic_Scalar_StructureValue Variable. /// public const uint Data_Dynamic_Scalar_StructureValue = 10867; /// /// The identifier for the Data_Dynamic_Scalar_NumberValue Variable. /// public const uint Data_Dynamic_Scalar_NumberValue = 10868; /// /// The identifier for the Data_Dynamic_Scalar_IntegerValue Variable. /// public const uint Data_Dynamic_Scalar_IntegerValue = 10869; /// /// The identifier for the Data_Dynamic_Scalar_UIntegerValue Variable. /// public const uint Data_Dynamic_Scalar_UIntegerValue = 10870; /// /// The identifier for the Data_Dynamic_Array_SimulationActive Variable. /// public const uint Data_Dynamic_Array_SimulationActive = 10872; /// /// The identifier for the Data_Dynamic_Array_GenerateValues_InputArguments Variable. /// public const uint Data_Dynamic_Array_GenerateValues_InputArguments = 10874; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_EventId Variable. /// public const uint Data_Dynamic_Array_CycleComplete_EventId = 10876; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_EventType Variable. /// public const uint Data_Dynamic_Array_CycleComplete_EventType = 10877; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_SourceNode Variable. /// public const uint Data_Dynamic_Array_CycleComplete_SourceNode = 10878; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_SourceName Variable. /// public const uint Data_Dynamic_Array_CycleComplete_SourceName = 10879; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Time Variable. /// public const uint Data_Dynamic_Array_CycleComplete_Time = 10880; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_ReceiveTime Variable. /// public const uint Data_Dynamic_Array_CycleComplete_ReceiveTime = 10881; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Message Variable. /// public const uint Data_Dynamic_Array_CycleComplete_Message = 10883; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Severity Variable. /// public const uint Data_Dynamic_Array_CycleComplete_Severity = 10884; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_ConditionClassId Variable. /// public const uint Data_Dynamic_Array_CycleComplete_ConditionClassId = 11608; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_ConditionClassName Variable. /// public const uint Data_Dynamic_Array_CycleComplete_ConditionClassName = 11609; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_ConditionName Variable. /// public const uint Data_Dynamic_Array_CycleComplete_ConditionName = 11572; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_BranchId Variable. /// public const uint Data_Dynamic_Array_CycleComplete_BranchId = 10885; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Retain Variable. /// public const uint Data_Dynamic_Array_CycleComplete_Retain = 10886; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_EnabledState Variable. /// public const uint Data_Dynamic_Array_CycleComplete_EnabledState = 10887; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_EnabledState_Id Variable. /// public const uint Data_Dynamic_Array_CycleComplete_EnabledState_Id = 10888; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Quality Variable. /// public const uint Data_Dynamic_Array_CycleComplete_Quality = 10893; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Quality_SourceTimestamp Variable. /// public const uint Data_Dynamic_Array_CycleComplete_Quality_SourceTimestamp = 10894; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_LastSeverity Variable. /// public const uint Data_Dynamic_Array_CycleComplete_LastSeverity = 10897; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public const uint Data_Dynamic_Array_CycleComplete_LastSeverity_SourceTimestamp = 10898; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Comment Variable. /// public const uint Data_Dynamic_Array_CycleComplete_Comment = 10899; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Comment_SourceTimestamp Variable. /// public const uint Data_Dynamic_Array_CycleComplete_Comment_SourceTimestamp = 10900; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_ClientUserId Variable. /// public const uint Data_Dynamic_Array_CycleComplete_ClientUserId = 10901; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_AddComment_InputArguments Variable. /// public const uint Data_Dynamic_Array_CycleComplete_AddComment_InputArguments = 10905; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_AckedState Variable. /// public const uint Data_Dynamic_Array_CycleComplete_AckedState = 10908; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_AckedState_Id Variable. /// public const uint Data_Dynamic_Array_CycleComplete_AckedState_Id = 10909; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_ConfirmedState_Id Variable. /// public const uint Data_Dynamic_Array_CycleComplete_ConfirmedState_Id = 10917; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Acknowledge_InputArguments Variable. /// public const uint Data_Dynamic_Array_CycleComplete_Acknowledge_InputArguments = 10925; /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Confirm_InputArguments Variable. /// public const uint Data_Dynamic_Array_CycleComplete_Confirm_InputArguments = 10927; /// /// The identifier for the Data_Dynamic_Array_BooleanValue Variable. /// public const uint Data_Dynamic_Array_BooleanValue = 10928; /// /// The identifier for the Data_Dynamic_Array_SByteValue Variable. /// public const uint Data_Dynamic_Array_SByteValue = 10929; /// /// The identifier for the Data_Dynamic_Array_ByteValue Variable. /// public const uint Data_Dynamic_Array_ByteValue = 10930; /// /// The identifier for the Data_Dynamic_Array_Int16Value Variable. /// public const uint Data_Dynamic_Array_Int16Value = 10931; /// /// The identifier for the Data_Dynamic_Array_UInt16Value Variable. /// public const uint Data_Dynamic_Array_UInt16Value = 10932; /// /// The identifier for the Data_Dynamic_Array_Int32Value Variable. /// public const uint Data_Dynamic_Array_Int32Value = 10933; /// /// The identifier for the Data_Dynamic_Array_UInt32Value Variable. /// public const uint Data_Dynamic_Array_UInt32Value = 10934; /// /// The identifier for the Data_Dynamic_Array_Int64Value Variable. /// public const uint Data_Dynamic_Array_Int64Value = 10935; /// /// The identifier for the Data_Dynamic_Array_UInt64Value Variable. /// public const uint Data_Dynamic_Array_UInt64Value = 10936; /// /// The identifier for the Data_Dynamic_Array_FloatValue Variable. /// public const uint Data_Dynamic_Array_FloatValue = 10937; /// /// The identifier for the Data_Dynamic_Array_DoubleValue Variable. /// public const uint Data_Dynamic_Array_DoubleValue = 10938; /// /// The identifier for the Data_Dynamic_Array_StringValue Variable. /// public const uint Data_Dynamic_Array_StringValue = 10939; /// /// The identifier for the Data_Dynamic_Array_DateTimeValue Variable. /// public const uint Data_Dynamic_Array_DateTimeValue = 10940; /// /// The identifier for the Data_Dynamic_Array_GuidValue Variable. /// public const uint Data_Dynamic_Array_GuidValue = 10941; /// /// The identifier for the Data_Dynamic_Array_ByteStringValue Variable. /// public const uint Data_Dynamic_Array_ByteStringValue = 10942; /// /// The identifier for the Data_Dynamic_Array_XmlElementValue Variable. /// public const uint Data_Dynamic_Array_XmlElementValue = 10943; /// /// The identifier for the Data_Dynamic_Array_NodeIdValue Variable. /// public const uint Data_Dynamic_Array_NodeIdValue = 10944; /// /// The identifier for the Data_Dynamic_Array_ExpandedNodeIdValue Variable. /// public const uint Data_Dynamic_Array_ExpandedNodeIdValue = 10945; /// /// The identifier for the Data_Dynamic_Array_QualifiedNameValue Variable. /// public const uint Data_Dynamic_Array_QualifiedNameValue = 10946; /// /// The identifier for the Data_Dynamic_Array_LocalizedTextValue Variable. /// public const uint Data_Dynamic_Array_LocalizedTextValue = 10947; /// /// The identifier for the Data_Dynamic_Array_StatusCodeValue Variable. /// public const uint Data_Dynamic_Array_StatusCodeValue = 10948; /// /// The identifier for the Data_Dynamic_Array_VariantValue Variable. /// public const uint Data_Dynamic_Array_VariantValue = 10949; /// /// The identifier for the Data_Dynamic_Array_EnumerationValue Variable. /// public const uint Data_Dynamic_Array_EnumerationValue = 10950; /// /// The identifier for the Data_Dynamic_Array_StructureValue Variable. /// public const uint Data_Dynamic_Array_StructureValue = 10951; /// /// The identifier for the Data_Dynamic_Array_NumberValue Variable. /// public const uint Data_Dynamic_Array_NumberValue = 10952; /// /// The identifier for the Data_Dynamic_Array_IntegerValue Variable. /// public const uint Data_Dynamic_Array_IntegerValue = 10953; /// /// The identifier for the Data_Dynamic_Array_UIntegerValue Variable. /// public const uint Data_Dynamic_Array_UIntegerValue = 10954; /// /// The identifier for the Data_Dynamic_UserScalar_SimulationActive Variable. /// public const uint Data_Dynamic_UserScalar_SimulationActive = 10956; /// /// The identifier for the Data_Dynamic_UserScalar_GenerateValues_InputArguments Variable. /// public const uint Data_Dynamic_UserScalar_GenerateValues_InputArguments = 10958; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_EventId Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_EventId = 10960; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_EventType Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_EventType = 10961; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_SourceNode Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_SourceNode = 10962; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_SourceName Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_SourceName = 10963; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Time Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_Time = 10964; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_ReceiveTime Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_ReceiveTime = 10965; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Message Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_Message = 10967; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Severity Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_Severity = 10968; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_ConditionClassId Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_ConditionClassId = 11610; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_ConditionClassName Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_ConditionClassName = 11611; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_ConditionName Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_ConditionName = 11573; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_BranchId Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_BranchId = 10969; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Retain Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_Retain = 10970; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_EnabledState Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_EnabledState = 10971; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_EnabledState_Id Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_EnabledState_Id = 10972; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Quality Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_Quality = 10977; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Quality_SourceTimestamp Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_Quality_SourceTimestamp = 10978; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_LastSeverity Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_LastSeverity = 10981; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_LastSeverity_SourceTimestamp = 10982; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Comment Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_Comment = 10983; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Comment_SourceTimestamp Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_Comment_SourceTimestamp = 10984; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_ClientUserId Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_ClientUserId = 10985; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_AddComment_InputArguments Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_AddComment_InputArguments = 10989; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_AckedState Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_AckedState = 10992; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_AckedState_Id Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_AckedState_Id = 10993; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_ConfirmedState_Id Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_ConfirmedState_Id = 11001; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Acknowledge_InputArguments Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_Acknowledge_InputArguments = 11009; /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Confirm_InputArguments Variable. /// public const uint Data_Dynamic_UserScalar_CycleComplete_Confirm_InputArguments = 11011; /// /// The identifier for the Data_Dynamic_UserScalar_BooleanValue Variable. /// public const uint Data_Dynamic_UserScalar_BooleanValue = 11012; /// /// The identifier for the Data_Dynamic_UserScalar_SByteValue Variable. /// public const uint Data_Dynamic_UserScalar_SByteValue = 11013; /// /// The identifier for the Data_Dynamic_UserScalar_ByteValue Variable. /// public const uint Data_Dynamic_UserScalar_ByteValue = 11014; /// /// The identifier for the Data_Dynamic_UserScalar_Int16Value Variable. /// public const uint Data_Dynamic_UserScalar_Int16Value = 11015; /// /// The identifier for the Data_Dynamic_UserScalar_UInt16Value Variable. /// public const uint Data_Dynamic_UserScalar_UInt16Value = 11016; /// /// The identifier for the Data_Dynamic_UserScalar_Int32Value Variable. /// public const uint Data_Dynamic_UserScalar_Int32Value = 11017; /// /// The identifier for the Data_Dynamic_UserScalar_UInt32Value Variable. /// public const uint Data_Dynamic_UserScalar_UInt32Value = 11018; /// /// The identifier for the Data_Dynamic_UserScalar_Int64Value Variable. /// public const uint Data_Dynamic_UserScalar_Int64Value = 11019; /// /// The identifier for the Data_Dynamic_UserScalar_UInt64Value Variable. /// public const uint Data_Dynamic_UserScalar_UInt64Value = 11020; /// /// The identifier for the Data_Dynamic_UserScalar_FloatValue Variable. /// public const uint Data_Dynamic_UserScalar_FloatValue = 11021; /// /// The identifier for the Data_Dynamic_UserScalar_DoubleValue Variable. /// public const uint Data_Dynamic_UserScalar_DoubleValue = 11022; /// /// The identifier for the Data_Dynamic_UserScalar_StringValue Variable. /// public const uint Data_Dynamic_UserScalar_StringValue = 11023; /// /// The identifier for the Data_Dynamic_UserScalar_DateTimeValue Variable. /// public const uint Data_Dynamic_UserScalar_DateTimeValue = 11024; /// /// The identifier for the Data_Dynamic_UserScalar_GuidValue Variable. /// public const uint Data_Dynamic_UserScalar_GuidValue = 11025; /// /// The identifier for the Data_Dynamic_UserScalar_ByteStringValue Variable. /// public const uint Data_Dynamic_UserScalar_ByteStringValue = 11026; /// /// The identifier for the Data_Dynamic_UserScalar_XmlElementValue Variable. /// public const uint Data_Dynamic_UserScalar_XmlElementValue = 11027; /// /// The identifier for the Data_Dynamic_UserScalar_NodeIdValue Variable. /// public const uint Data_Dynamic_UserScalar_NodeIdValue = 11028; /// /// The identifier for the Data_Dynamic_UserScalar_ExpandedNodeIdValue Variable. /// public const uint Data_Dynamic_UserScalar_ExpandedNodeIdValue = 11029; /// /// The identifier for the Data_Dynamic_UserScalar_QualifiedNameValue Variable. /// public const uint Data_Dynamic_UserScalar_QualifiedNameValue = 11030; /// /// The identifier for the Data_Dynamic_UserScalar_LocalizedTextValue Variable. /// public const uint Data_Dynamic_UserScalar_LocalizedTextValue = 11031; /// /// The identifier for the Data_Dynamic_UserScalar_StatusCodeValue Variable. /// public const uint Data_Dynamic_UserScalar_StatusCodeValue = 11032; /// /// The identifier for the Data_Dynamic_UserScalar_VariantValue Variable. /// public const uint Data_Dynamic_UserScalar_VariantValue = 11033; /// /// The identifier for the Data_Dynamic_UserArray_SimulationActive Variable. /// public const uint Data_Dynamic_UserArray_SimulationActive = 11035; /// /// The identifier for the Data_Dynamic_UserArray_GenerateValues_InputArguments Variable. /// public const uint Data_Dynamic_UserArray_GenerateValues_InputArguments = 11037; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_EventId Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_EventId = 11039; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_EventType Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_EventType = 11040; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_SourceNode Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_SourceNode = 11041; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_SourceName Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_SourceName = 11042; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Time Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_Time = 11043; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_ReceiveTime Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_ReceiveTime = 11044; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Message Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_Message = 11046; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Severity Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_Severity = 11047; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_ConditionClassId Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_ConditionClassId = 11612; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_ConditionClassName Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_ConditionClassName = 11613; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_ConditionName Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_ConditionName = 11574; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_BranchId Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_BranchId = 11048; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Retain Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_Retain = 11049; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_EnabledState Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_EnabledState = 11050; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_EnabledState_Id Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_EnabledState_Id = 11051; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Quality Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_Quality = 11056; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Quality_SourceTimestamp Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_Quality_SourceTimestamp = 11057; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_LastSeverity Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_LastSeverity = 11060; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_LastSeverity_SourceTimestamp = 11061; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Comment Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_Comment = 11062; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Comment_SourceTimestamp Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_Comment_SourceTimestamp = 11063; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_ClientUserId Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_ClientUserId = 11064; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_AddComment_InputArguments Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_AddComment_InputArguments = 11068; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_AckedState Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_AckedState = 11071; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_AckedState_Id Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_AckedState_Id = 11072; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_ConfirmedState_Id Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_ConfirmedState_Id = 11080; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Acknowledge_InputArguments Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_Acknowledge_InputArguments = 11088; /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Confirm_InputArguments Variable. /// public const uint Data_Dynamic_UserArray_CycleComplete_Confirm_InputArguments = 11090; /// /// The identifier for the Data_Dynamic_UserArray_BooleanValue Variable. /// public const uint Data_Dynamic_UserArray_BooleanValue = 11091; /// /// The identifier for the Data_Dynamic_UserArray_SByteValue Variable. /// public const uint Data_Dynamic_UserArray_SByteValue = 11092; /// /// The identifier for the Data_Dynamic_UserArray_ByteValue Variable. /// public const uint Data_Dynamic_UserArray_ByteValue = 11093; /// /// The identifier for the Data_Dynamic_UserArray_Int16Value Variable. /// public const uint Data_Dynamic_UserArray_Int16Value = 11094; /// /// The identifier for the Data_Dynamic_UserArray_UInt16Value Variable. /// public const uint Data_Dynamic_UserArray_UInt16Value = 11095; /// /// The identifier for the Data_Dynamic_UserArray_Int32Value Variable. /// public const uint Data_Dynamic_UserArray_Int32Value = 11096; /// /// The identifier for the Data_Dynamic_UserArray_UInt32Value Variable. /// public const uint Data_Dynamic_UserArray_UInt32Value = 11097; /// /// The identifier for the Data_Dynamic_UserArray_Int64Value Variable. /// public const uint Data_Dynamic_UserArray_Int64Value = 11098; /// /// The identifier for the Data_Dynamic_UserArray_UInt64Value Variable. /// public const uint Data_Dynamic_UserArray_UInt64Value = 11099; /// /// The identifier for the Data_Dynamic_UserArray_FloatValue Variable. /// public const uint Data_Dynamic_UserArray_FloatValue = 11100; /// /// The identifier for the Data_Dynamic_UserArray_DoubleValue Variable. /// public const uint Data_Dynamic_UserArray_DoubleValue = 11101; /// /// The identifier for the Data_Dynamic_UserArray_StringValue Variable. /// public const uint Data_Dynamic_UserArray_StringValue = 11102; /// /// The identifier for the Data_Dynamic_UserArray_DateTimeValue Variable. /// public const uint Data_Dynamic_UserArray_DateTimeValue = 11103; /// /// The identifier for the Data_Dynamic_UserArray_GuidValue Variable. /// public const uint Data_Dynamic_UserArray_GuidValue = 11104; /// /// The identifier for the Data_Dynamic_UserArray_ByteStringValue Variable. /// public const uint Data_Dynamic_UserArray_ByteStringValue = 11105; /// /// The identifier for the Data_Dynamic_UserArray_XmlElementValue Variable. /// public const uint Data_Dynamic_UserArray_XmlElementValue = 11106; /// /// The identifier for the Data_Dynamic_UserArray_NodeIdValue Variable. /// public const uint Data_Dynamic_UserArray_NodeIdValue = 11107; /// /// The identifier for the Data_Dynamic_UserArray_ExpandedNodeIdValue Variable. /// public const uint Data_Dynamic_UserArray_ExpandedNodeIdValue = 11108; /// /// The identifier for the Data_Dynamic_UserArray_QualifiedNameValue Variable. /// public const uint Data_Dynamic_UserArray_QualifiedNameValue = 11109; /// /// The identifier for the Data_Dynamic_UserArray_LocalizedTextValue Variable. /// public const uint Data_Dynamic_UserArray_LocalizedTextValue = 11110; /// /// The identifier for the Data_Dynamic_UserArray_StatusCodeValue Variable. /// public const uint Data_Dynamic_UserArray_StatusCodeValue = 11111; /// /// The identifier for the Data_Dynamic_UserArray_VariantValue Variable. /// public const uint Data_Dynamic_UserArray_VariantValue = 11112; /// /// The identifier for the Data_Dynamic_AnalogScalar_SimulationActive Variable. /// public const uint Data_Dynamic_AnalogScalar_SimulationActive = 11114; /// /// The identifier for the Data_Dynamic_AnalogScalar_GenerateValues_InputArguments Variable. /// public const uint Data_Dynamic_AnalogScalar_GenerateValues_InputArguments = 11116; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_EventId Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_EventId = 11118; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_EventType Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_EventType = 11119; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_SourceNode Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_SourceNode = 11120; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_SourceName Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_SourceName = 11121; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Time Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_Time = 11122; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_ReceiveTime Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_ReceiveTime = 11123; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Message Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_Message = 11125; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Severity Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_Severity = 11126; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_ConditionClassId Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_ConditionClassId = 11614; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_ConditionClassName Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_ConditionClassName = 11615; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_ConditionName Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_ConditionName = 11575; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_BranchId Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_BranchId = 11127; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Retain Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_Retain = 11128; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_EnabledState Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_EnabledState = 11129; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_EnabledState_Id Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_EnabledState_Id = 11130; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Quality Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_Quality = 11135; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Quality_SourceTimestamp Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_Quality_SourceTimestamp = 11136; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_LastSeverity Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_LastSeverity = 11139; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_LastSeverity_SourceTimestamp = 11140; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Comment Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_Comment = 11141; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Comment_SourceTimestamp Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_Comment_SourceTimestamp = 11142; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_ClientUserId Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_ClientUserId = 11143; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_AddComment_InputArguments Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_AddComment_InputArguments = 11147; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_AckedState Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_AckedState = 11150; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_AckedState_Id Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_AckedState_Id = 11151; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_ConfirmedState_Id Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_ConfirmedState_Id = 11159; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Acknowledge_InputArguments Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_Acknowledge_InputArguments = 11167; /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Confirm_InputArguments Variable. /// public const uint Data_Dynamic_AnalogScalar_CycleComplete_Confirm_InputArguments = 11169; /// /// The identifier for the Data_Dynamic_AnalogScalar_SByteValue Variable. /// public const uint Data_Dynamic_AnalogScalar_SByteValue = 11170; /// /// The identifier for the Data_Dynamic_AnalogScalar_SByteValue_EURange Variable. /// public const uint Data_Dynamic_AnalogScalar_SByteValue_EURange = 11173; /// /// The identifier for the Data_Dynamic_AnalogScalar_ByteValue Variable. /// public const uint Data_Dynamic_AnalogScalar_ByteValue = 11176; /// /// The identifier for the Data_Dynamic_AnalogScalar_ByteValue_EURange Variable. /// public const uint Data_Dynamic_AnalogScalar_ByteValue_EURange = 11179; /// /// The identifier for the Data_Dynamic_AnalogScalar_Int16Value Variable. /// public const uint Data_Dynamic_AnalogScalar_Int16Value = 11182; /// /// The identifier for the Data_Dynamic_AnalogScalar_Int16Value_EURange Variable. /// public const uint Data_Dynamic_AnalogScalar_Int16Value_EURange = 11185; /// /// The identifier for the Data_Dynamic_AnalogScalar_UInt16Value Variable. /// public const uint Data_Dynamic_AnalogScalar_UInt16Value = 11188; /// /// The identifier for the Data_Dynamic_AnalogScalar_UInt16Value_EURange Variable. /// public const uint Data_Dynamic_AnalogScalar_UInt16Value_EURange = 11191; /// /// The identifier for the Data_Dynamic_AnalogScalar_Int32Value Variable. /// public const uint Data_Dynamic_AnalogScalar_Int32Value = 11194; /// /// The identifier for the Data_Dynamic_AnalogScalar_Int32Value_EURange Variable. /// public const uint Data_Dynamic_AnalogScalar_Int32Value_EURange = 11197; /// /// The identifier for the Data_Dynamic_AnalogScalar_UInt32Value Variable. /// public const uint Data_Dynamic_AnalogScalar_UInt32Value = 11200; /// /// The identifier for the Data_Dynamic_AnalogScalar_UInt32Value_EURange Variable. /// public const uint Data_Dynamic_AnalogScalar_UInt32Value_EURange = 11203; /// /// The identifier for the Data_Dynamic_AnalogScalar_Int64Value Variable. /// public const uint Data_Dynamic_AnalogScalar_Int64Value = 11206; /// /// The identifier for the Data_Dynamic_AnalogScalar_Int64Value_EURange Variable. /// public const uint Data_Dynamic_AnalogScalar_Int64Value_EURange = 11209; /// /// The identifier for the Data_Dynamic_AnalogScalar_UInt64Value Variable. /// public const uint Data_Dynamic_AnalogScalar_UInt64Value = 11212; /// /// The identifier for the Data_Dynamic_AnalogScalar_UInt64Value_EURange Variable. /// public const uint Data_Dynamic_AnalogScalar_UInt64Value_EURange = 11215; /// /// The identifier for the Data_Dynamic_AnalogScalar_FloatValue Variable. /// public const uint Data_Dynamic_AnalogScalar_FloatValue = 11218; /// /// The identifier for the Data_Dynamic_AnalogScalar_FloatValue_EURange Variable. /// public const uint Data_Dynamic_AnalogScalar_FloatValue_EURange = 11221; /// /// The identifier for the Data_Dynamic_AnalogScalar_DoubleValue Variable. /// public const uint Data_Dynamic_AnalogScalar_DoubleValue = 11224; /// /// The identifier for the Data_Dynamic_AnalogScalar_DoubleValue_EURange Variable. /// public const uint Data_Dynamic_AnalogScalar_DoubleValue_EURange = 11227; /// /// The identifier for the Data_Dynamic_AnalogScalar_NumberValue Variable. /// public const uint Data_Dynamic_AnalogScalar_NumberValue = 11230; /// /// The identifier for the Data_Dynamic_AnalogScalar_NumberValue_EURange Variable. /// public const uint Data_Dynamic_AnalogScalar_NumberValue_EURange = 11233; /// /// The identifier for the Data_Dynamic_AnalogScalar_IntegerValue Variable. /// public const uint Data_Dynamic_AnalogScalar_IntegerValue = 11236; /// /// The identifier for the Data_Dynamic_AnalogScalar_IntegerValue_EURange Variable. /// public const uint Data_Dynamic_AnalogScalar_IntegerValue_EURange = 11239; /// /// The identifier for the Data_Dynamic_AnalogScalar_UIntegerValue Variable. /// public const uint Data_Dynamic_AnalogScalar_UIntegerValue = 11242; /// /// The identifier for the Data_Dynamic_AnalogScalar_UIntegerValue_EURange Variable. /// public const uint Data_Dynamic_AnalogScalar_UIntegerValue_EURange = 11245; /// /// The identifier for the Data_Dynamic_AnalogArray_SimulationActive Variable. /// public const uint Data_Dynamic_AnalogArray_SimulationActive = 11249; /// /// The identifier for the Data_Dynamic_AnalogArray_GenerateValues_InputArguments Variable. /// public const uint Data_Dynamic_AnalogArray_GenerateValues_InputArguments = 11251; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_EventId Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_EventId = 11253; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_EventType Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_EventType = 11254; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_SourceNode Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_SourceNode = 11255; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_SourceName Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_SourceName = 11256; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Time Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_Time = 11257; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_ReceiveTime Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_ReceiveTime = 11258; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Message Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_Message = 11260; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Severity Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_Severity = 11261; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_ConditionClassId Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_ConditionClassId = 11616; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_ConditionClassName Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_ConditionClassName = 11617; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_ConditionName Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_ConditionName = 11576; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_BranchId Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_BranchId = 11262; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Retain Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_Retain = 11263; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_EnabledState Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_EnabledState = 11264; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_EnabledState_Id Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_EnabledState_Id = 11265; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Quality Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_Quality = 11270; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Quality_SourceTimestamp Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_Quality_SourceTimestamp = 11271; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_LastSeverity Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_LastSeverity = 11274; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_LastSeverity_SourceTimestamp = 11275; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Comment Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_Comment = 11276; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Comment_SourceTimestamp Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_Comment_SourceTimestamp = 11277; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_ClientUserId Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_ClientUserId = 11278; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_AddComment_InputArguments Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_AddComment_InputArguments = 11282; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_AckedState Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_AckedState = 11285; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_AckedState_Id Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_AckedState_Id = 11286; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_ConfirmedState_Id Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_ConfirmedState_Id = 11294; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Acknowledge_InputArguments Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_Acknowledge_InputArguments = 11302; /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Confirm_InputArguments Variable. /// public const uint Data_Dynamic_AnalogArray_CycleComplete_Confirm_InputArguments = 11304; /// /// The identifier for the Data_Dynamic_AnalogArray_SByteValue Variable. /// public const uint Data_Dynamic_AnalogArray_SByteValue = 11305; /// /// The identifier for the Data_Dynamic_AnalogArray_SByteValue_EURange Variable. /// public const uint Data_Dynamic_AnalogArray_SByteValue_EURange = 11308; /// /// The identifier for the Data_Dynamic_AnalogArray_ByteValue Variable. /// public const uint Data_Dynamic_AnalogArray_ByteValue = 11311; /// /// The identifier for the Data_Dynamic_AnalogArray_ByteValue_EURange Variable. /// public const uint Data_Dynamic_AnalogArray_ByteValue_EURange = 11314; /// /// The identifier for the Data_Dynamic_AnalogArray_Int16Value Variable. /// public const uint Data_Dynamic_AnalogArray_Int16Value = 11317; /// /// The identifier for the Data_Dynamic_AnalogArray_Int16Value_EURange Variable. /// public const uint Data_Dynamic_AnalogArray_Int16Value_EURange = 11320; /// /// The identifier for the Data_Dynamic_AnalogArray_UInt16Value Variable. /// public const uint Data_Dynamic_AnalogArray_UInt16Value = 11323; /// /// The identifier for the Data_Dynamic_AnalogArray_UInt16Value_EURange Variable. /// public const uint Data_Dynamic_AnalogArray_UInt16Value_EURange = 11326; /// /// The identifier for the Data_Dynamic_AnalogArray_Int32Value Variable. /// public const uint Data_Dynamic_AnalogArray_Int32Value = 11329; /// /// The identifier for the Data_Dynamic_AnalogArray_Int32Value_EURange Variable. /// public const uint Data_Dynamic_AnalogArray_Int32Value_EURange = 11332; /// /// The identifier for the Data_Dynamic_AnalogArray_UInt32Value Variable. /// public const uint Data_Dynamic_AnalogArray_UInt32Value = 11335; /// /// The identifier for the Data_Dynamic_AnalogArray_UInt32Value_EURange Variable. /// public const uint Data_Dynamic_AnalogArray_UInt32Value_EURange = 11338; /// /// The identifier for the Data_Dynamic_AnalogArray_Int64Value Variable. /// public const uint Data_Dynamic_AnalogArray_Int64Value = 11341; /// /// The identifier for the Data_Dynamic_AnalogArray_Int64Value_EURange Variable. /// public const uint Data_Dynamic_AnalogArray_Int64Value_EURange = 11344; /// /// The identifier for the Data_Dynamic_AnalogArray_UInt64Value Variable. /// public const uint Data_Dynamic_AnalogArray_UInt64Value = 11347; /// /// The identifier for the Data_Dynamic_AnalogArray_UInt64Value_EURange Variable. /// public const uint Data_Dynamic_AnalogArray_UInt64Value_EURange = 11350; /// /// The identifier for the Data_Dynamic_AnalogArray_FloatValue Variable. /// public const uint Data_Dynamic_AnalogArray_FloatValue = 11353; /// /// The identifier for the Data_Dynamic_AnalogArray_FloatValue_EURange Variable. /// public const uint Data_Dynamic_AnalogArray_FloatValue_EURange = 11356; /// /// The identifier for the Data_Dynamic_AnalogArray_DoubleValue Variable. /// public const uint Data_Dynamic_AnalogArray_DoubleValue = 11359; /// /// The identifier for the Data_Dynamic_AnalogArray_DoubleValue_EURange Variable. /// public const uint Data_Dynamic_AnalogArray_DoubleValue_EURange = 11362; /// /// The identifier for the Data_Dynamic_AnalogArray_NumberValue Variable. /// public const uint Data_Dynamic_AnalogArray_NumberValue = 11365; /// /// The identifier for the Data_Dynamic_AnalogArray_NumberValue_EURange Variable. /// public const uint Data_Dynamic_AnalogArray_NumberValue_EURange = 11368; /// /// The identifier for the Data_Dynamic_AnalogArray_IntegerValue Variable. /// public const uint Data_Dynamic_AnalogArray_IntegerValue = 11371; /// /// The identifier for the Data_Dynamic_AnalogArray_IntegerValue_EURange Variable. /// public const uint Data_Dynamic_AnalogArray_IntegerValue_EURange = 11374; /// /// The identifier for the Data_Dynamic_AnalogArray_UIntegerValue Variable. /// public const uint Data_Dynamic_AnalogArray_UIntegerValue = 11377; /// /// The identifier for the Data_Dynamic_AnalogArray_UIntegerValue_EURange Variable. /// public const uint Data_Dynamic_AnalogArray_UIntegerValue_EURange = 11380; /// /// The identifier for the Data_Conditions_SystemStatus_EventId Variable. /// public const uint Data_Conditions_SystemStatus_EventId = 11385; /// /// The identifier for the Data_Conditions_SystemStatus_EventType Variable. /// public const uint Data_Conditions_SystemStatus_EventType = 11386; /// /// The identifier for the Data_Conditions_SystemStatus_SourceNode Variable. /// public const uint Data_Conditions_SystemStatus_SourceNode = 11387; /// /// The identifier for the Data_Conditions_SystemStatus_SourceName Variable. /// public const uint Data_Conditions_SystemStatus_SourceName = 11388; /// /// The identifier for the Data_Conditions_SystemStatus_Time Variable. /// public const uint Data_Conditions_SystemStatus_Time = 11389; /// /// The identifier for the Data_Conditions_SystemStatus_ReceiveTime Variable. /// public const uint Data_Conditions_SystemStatus_ReceiveTime = 11390; /// /// The identifier for the Data_Conditions_SystemStatus_Message Variable. /// public const uint Data_Conditions_SystemStatus_Message = 11392; /// /// The identifier for the Data_Conditions_SystemStatus_Severity Variable. /// public const uint Data_Conditions_SystemStatus_Severity = 11393; /// /// The identifier for the Data_Conditions_SystemStatus_ConditionClassId Variable. /// public const uint Data_Conditions_SystemStatus_ConditionClassId = 11618; /// /// The identifier for the Data_Conditions_SystemStatus_ConditionClassName Variable. /// public const uint Data_Conditions_SystemStatus_ConditionClassName = 11619; /// /// The identifier for the Data_Conditions_SystemStatus_ConditionName Variable. /// public const uint Data_Conditions_SystemStatus_ConditionName = 11577; /// /// The identifier for the Data_Conditions_SystemStatus_BranchId Variable. /// public const uint Data_Conditions_SystemStatus_BranchId = 11394; /// /// The identifier for the Data_Conditions_SystemStatus_Retain Variable. /// public const uint Data_Conditions_SystemStatus_Retain = 11395; /// /// The identifier for the Data_Conditions_SystemStatus_EnabledState Variable. /// public const uint Data_Conditions_SystemStatus_EnabledState = 11396; /// /// The identifier for the Data_Conditions_SystemStatus_EnabledState_Id Variable. /// public const uint Data_Conditions_SystemStatus_EnabledState_Id = 11397; /// /// The identifier for the Data_Conditions_SystemStatus_Quality Variable. /// public const uint Data_Conditions_SystemStatus_Quality = 11402; /// /// The identifier for the Data_Conditions_SystemStatus_Quality_SourceTimestamp Variable. /// public const uint Data_Conditions_SystemStatus_Quality_SourceTimestamp = 11403; /// /// The identifier for the Data_Conditions_SystemStatus_LastSeverity Variable. /// public const uint Data_Conditions_SystemStatus_LastSeverity = 11406; /// /// The identifier for the Data_Conditions_SystemStatus_LastSeverity_SourceTimestamp Variable. /// public const uint Data_Conditions_SystemStatus_LastSeverity_SourceTimestamp = 11407; /// /// The identifier for the Data_Conditions_SystemStatus_Comment Variable. /// public const uint Data_Conditions_SystemStatus_Comment = 11408; /// /// The identifier for the Data_Conditions_SystemStatus_Comment_SourceTimestamp Variable. /// public const uint Data_Conditions_SystemStatus_Comment_SourceTimestamp = 11409; /// /// The identifier for the Data_Conditions_SystemStatus_ClientUserId Variable. /// public const uint Data_Conditions_SystemStatus_ClientUserId = 11410; /// /// The identifier for the Data_Conditions_SystemStatus_AddComment_InputArguments Variable. /// public const uint Data_Conditions_SystemStatus_AddComment_InputArguments = 11414; /// /// The identifier for the Data_Conditions_SystemStatus_MonitoredNodeCount Variable. /// public const uint Data_Conditions_SystemStatus_MonitoredNodeCount = 11417; /// /// The identifier for the TestData_BinarySchema Variable. /// public const uint TestData_BinarySchema = 11422; /// /// The identifier for the TestData_BinarySchema_NamespaceUri Variable. /// public const uint TestData_BinarySchema_NamespaceUri = 11424; /// /// The identifier for the TestData_BinarySchema_Deprecated Variable. /// public const uint TestData_BinarySchema_Deprecated = 15045; /// /// The identifier for the TestData_BinarySchema_ScalarValueDataType Variable. /// public const uint TestData_BinarySchema_ScalarValueDataType = 11425; /// /// The identifier for the TestData_BinarySchema_ArrayValueDataType Variable. /// public const uint TestData_BinarySchema_ArrayValueDataType = 11428; /// /// The identifier for the TestData_BinarySchema_UserScalarValueDataType Variable. /// public const uint TestData_BinarySchema_UserScalarValueDataType = 11431; /// /// The identifier for the TestData_BinarySchema_UserArrayValueDataType Variable. /// public const uint TestData_BinarySchema_UserArrayValueDataType = 11434; /// /// The identifier for the TestData_BinarySchema_Vector Variable. /// public const uint TestData_BinarySchema_Vector = 1015; /// /// The identifier for the TestData_BinarySchema_WorkOrderStatusType Variable. /// public const uint TestData_BinarySchema_WorkOrderStatusType = 24; /// /// The identifier for the TestData_BinarySchema_WorkOrderType Variable. /// public const uint TestData_BinarySchema_WorkOrderType = 27; /// /// The identifier for the TestData_XmlSchema Variable. /// public const uint TestData_XmlSchema = 11441; /// /// The identifier for the TestData_XmlSchema_NamespaceUri Variable. /// public const uint TestData_XmlSchema_NamespaceUri = 11443; /// /// The identifier for the TestData_XmlSchema_Deprecated Variable. /// public const uint TestData_XmlSchema_Deprecated = 15046; /// /// The identifier for the TestData_XmlSchema_ScalarValueDataType Variable. /// public const uint TestData_XmlSchema_ScalarValueDataType = 11444; /// /// The identifier for the TestData_XmlSchema_ArrayValueDataType Variable. /// public const uint TestData_XmlSchema_ArrayValueDataType = 11447; /// /// The identifier for the TestData_XmlSchema_UserScalarValueDataType Variable. /// public const uint TestData_XmlSchema_UserScalarValueDataType = 11450; /// /// The identifier for the TestData_XmlSchema_UserArrayValueDataType Variable. /// public const uint TestData_XmlSchema_UserArrayValueDataType = 11453; /// /// The identifier for the TestData_XmlSchema_Vector Variable. /// public const uint TestData_XmlSchema_Vector = 43; /// /// The identifier for the TestData_XmlSchema_WorkOrderStatusType Variable. /// public const uint TestData_XmlSchema_WorkOrderStatusType = 52; /// /// The identifier for the TestData_XmlSchema_WorkOrderType Variable. /// public const uint TestData_XmlSchema_WorkOrderType = 55; } #endregion #region DataType Node Identifiers /// /// A class that declares constants for all DataTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class DataTypeIds { /// /// The identifier for the ScalarValueDataType DataType. /// public static readonly ExpandedNodeId ScalarValueDataType = new ExpandedNodeId(TestData.DataTypes.ScalarValueDataType, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueDataType DataType. /// public static readonly ExpandedNodeId ArrayValueDataType = new ExpandedNodeId(TestData.DataTypes.ArrayValueDataType, TestData.Namespaces.TestData); /// /// The identifier for the BooleanDataType DataType. /// public static readonly ExpandedNodeId BooleanDataType = new ExpandedNodeId(TestData.DataTypes.BooleanDataType, TestData.Namespaces.TestData); /// /// The identifier for the SByteDataType DataType. /// public static readonly ExpandedNodeId SByteDataType = new ExpandedNodeId(TestData.DataTypes.SByteDataType, TestData.Namespaces.TestData); /// /// The identifier for the ByteDataType DataType. /// public static readonly ExpandedNodeId ByteDataType = new ExpandedNodeId(TestData.DataTypes.ByteDataType, TestData.Namespaces.TestData); /// /// The identifier for the Int16DataType DataType. /// public static readonly ExpandedNodeId Int16DataType = new ExpandedNodeId(TestData.DataTypes.Int16DataType, TestData.Namespaces.TestData); /// /// The identifier for the UInt16DataType DataType. /// public static readonly ExpandedNodeId UInt16DataType = new ExpandedNodeId(TestData.DataTypes.UInt16DataType, TestData.Namespaces.TestData); /// /// The identifier for the Int32DataType DataType. /// public static readonly ExpandedNodeId Int32DataType = new ExpandedNodeId(TestData.DataTypes.Int32DataType, TestData.Namespaces.TestData); /// /// The identifier for the UInt32DataType DataType. /// public static readonly ExpandedNodeId UInt32DataType = new ExpandedNodeId(TestData.DataTypes.UInt32DataType, TestData.Namespaces.TestData); /// /// The identifier for the Int64DataType DataType. /// public static readonly ExpandedNodeId Int64DataType = new ExpandedNodeId(TestData.DataTypes.Int64DataType, TestData.Namespaces.TestData); /// /// The identifier for the UInt64DataType DataType. /// public static readonly ExpandedNodeId UInt64DataType = new ExpandedNodeId(TestData.DataTypes.UInt64DataType, TestData.Namespaces.TestData); /// /// The identifier for the FloatDataType DataType. /// public static readonly ExpandedNodeId FloatDataType = new ExpandedNodeId(TestData.DataTypes.FloatDataType, TestData.Namespaces.TestData); /// /// The identifier for the DoubleDataType DataType. /// public static readonly ExpandedNodeId DoubleDataType = new ExpandedNodeId(TestData.DataTypes.DoubleDataType, TestData.Namespaces.TestData); /// /// The identifier for the StringDataType DataType. /// public static readonly ExpandedNodeId StringDataType = new ExpandedNodeId(TestData.DataTypes.StringDataType, TestData.Namespaces.TestData); /// /// The identifier for the DateTimeDataType DataType. /// public static readonly ExpandedNodeId DateTimeDataType = new ExpandedNodeId(TestData.DataTypes.DateTimeDataType, TestData.Namespaces.TestData); /// /// The identifier for the GuidDataType DataType. /// public static readonly ExpandedNodeId GuidDataType = new ExpandedNodeId(TestData.DataTypes.GuidDataType, TestData.Namespaces.TestData); /// /// The identifier for the ByteStringDataType DataType. /// public static readonly ExpandedNodeId ByteStringDataType = new ExpandedNodeId(TestData.DataTypes.ByteStringDataType, TestData.Namespaces.TestData); /// /// The identifier for the XmlElementDataType DataType. /// public static readonly ExpandedNodeId XmlElementDataType = new ExpandedNodeId(TestData.DataTypes.XmlElementDataType, TestData.Namespaces.TestData); /// /// The identifier for the NodeIdDataType DataType. /// public static readonly ExpandedNodeId NodeIdDataType = new ExpandedNodeId(TestData.DataTypes.NodeIdDataType, TestData.Namespaces.TestData); /// /// The identifier for the ExpandedNodeIdDataType DataType. /// public static readonly ExpandedNodeId ExpandedNodeIdDataType = new ExpandedNodeId(TestData.DataTypes.ExpandedNodeIdDataType, TestData.Namespaces.TestData); /// /// The identifier for the QualifiedNameDataType DataType. /// public static readonly ExpandedNodeId QualifiedNameDataType = new ExpandedNodeId(TestData.DataTypes.QualifiedNameDataType, TestData.Namespaces.TestData); /// /// The identifier for the LocalizedTextDataType DataType. /// public static readonly ExpandedNodeId LocalizedTextDataType = new ExpandedNodeId(TestData.DataTypes.LocalizedTextDataType, TestData.Namespaces.TestData); /// /// The identifier for the StatusCodeDataType DataType. /// public static readonly ExpandedNodeId StatusCodeDataType = new ExpandedNodeId(TestData.DataTypes.StatusCodeDataType, TestData.Namespaces.TestData); /// /// The identifier for the VariantDataType DataType. /// public static readonly ExpandedNodeId VariantDataType = new ExpandedNodeId(TestData.DataTypes.VariantDataType, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueDataType DataType. /// public static readonly ExpandedNodeId UserScalarValueDataType = new ExpandedNodeId(TestData.DataTypes.UserScalarValueDataType, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueDataType DataType. /// public static readonly ExpandedNodeId UserArrayValueDataType = new ExpandedNodeId(TestData.DataTypes.UserArrayValueDataType, TestData.Namespaces.TestData); /// /// The identifier for the Vector DataType. /// public static readonly ExpandedNodeId Vector = new ExpandedNodeId(TestData.DataTypes.Vector, TestData.Namespaces.TestData); /// /// The identifier for the WorkOrderStatusType DataType. /// public static readonly ExpandedNodeId WorkOrderStatusType = new ExpandedNodeId(TestData.DataTypes.WorkOrderStatusType, TestData.Namespaces.TestData); /// /// The identifier for the WorkOrderType DataType. /// public static readonly ExpandedNodeId WorkOrderType = new ExpandedNodeId(TestData.DataTypes.WorkOrderType, TestData.Namespaces.TestData); } #endregion #region Method Node Identifiers /// /// A class that declares constants for all Methods in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class MethodIds { /// /// The identifier for the TestDataObjectType_GenerateValues Method. /// public static readonly ExpandedNodeId TestDataObjectType_GenerateValues = new ExpandedNodeId(TestData.Methods.TestDataObjectType_GenerateValues, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_Disable Method. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_Disable = new ExpandedNodeId(TestData.Methods.TestDataObjectType_CycleComplete_Disable, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_Enable Method. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_Enable = new ExpandedNodeId(TestData.Methods.TestDataObjectType_CycleComplete_Enable, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_AddComment Method. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_AddComment = new ExpandedNodeId(TestData.Methods.TestDataObjectType_CycleComplete_AddComment, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_Acknowledge Method. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_Acknowledge = new ExpandedNodeId(TestData.Methods.TestDataObjectType_CycleComplete_Acknowledge, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_Disable Method. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_Disable = new ExpandedNodeId(TestData.Methods.ScalarValueObjectType_CycleComplete_Disable, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_Enable Method. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_Enable = new ExpandedNodeId(TestData.Methods.ScalarValueObjectType_CycleComplete_Enable, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_AddComment Method. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_AddComment = new ExpandedNodeId(TestData.Methods.ScalarValueObjectType_CycleComplete_AddComment, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_Acknowledge Method. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_Acknowledge = new ExpandedNodeId(TestData.Methods.ScalarValueObjectType_CycleComplete_Acknowledge, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Disable Method. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_Disable = new ExpandedNodeId(TestData.Methods.AnalogScalarValueObjectType_CycleComplete_Disable, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Enable Method. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_Enable = new ExpandedNodeId(TestData.Methods.AnalogScalarValueObjectType_CycleComplete_Enable, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_AddComment Method. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_AddComment = new ExpandedNodeId(TestData.Methods.AnalogScalarValueObjectType_CycleComplete_AddComment, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Acknowledge Method. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_Acknowledge = new ExpandedNodeId(TestData.Methods.AnalogScalarValueObjectType_CycleComplete_Acknowledge, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_Disable Method. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_Disable = new ExpandedNodeId(TestData.Methods.ArrayValueObjectType_CycleComplete_Disable, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_Enable Method. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_Enable = new ExpandedNodeId(TestData.Methods.ArrayValueObjectType_CycleComplete_Enable, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_AddComment Method. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_AddComment = new ExpandedNodeId(TestData.Methods.ArrayValueObjectType_CycleComplete_AddComment, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_Acknowledge Method. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_Acknowledge = new ExpandedNodeId(TestData.Methods.ArrayValueObjectType_CycleComplete_Acknowledge, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Disable Method. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_Disable = new ExpandedNodeId(TestData.Methods.AnalogArrayValueObjectType_CycleComplete_Disable, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Enable Method. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_Enable = new ExpandedNodeId(TestData.Methods.AnalogArrayValueObjectType_CycleComplete_Enable, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_AddComment Method. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_AddComment = new ExpandedNodeId(TestData.Methods.AnalogArrayValueObjectType_CycleComplete_AddComment, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Acknowledge Method. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_Acknowledge = new ExpandedNodeId(TestData.Methods.AnalogArrayValueObjectType_CycleComplete_Acknowledge, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Disable Method. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_Disable = new ExpandedNodeId(TestData.Methods.UserScalarValueObjectType_CycleComplete_Disable, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Enable Method. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_Enable = new ExpandedNodeId(TestData.Methods.UserScalarValueObjectType_CycleComplete_Enable, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_AddComment Method. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_AddComment = new ExpandedNodeId(TestData.Methods.UserScalarValueObjectType_CycleComplete_AddComment, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Acknowledge Method. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_Acknowledge = new ExpandedNodeId(TestData.Methods.UserScalarValueObjectType_CycleComplete_Acknowledge, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Disable Method. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_Disable = new ExpandedNodeId(TestData.Methods.UserArrayValueObjectType_CycleComplete_Disable, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Enable Method. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_Enable = new ExpandedNodeId(TestData.Methods.UserArrayValueObjectType_CycleComplete_Enable, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_AddComment Method. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_AddComment = new ExpandedNodeId(TestData.Methods.UserArrayValueObjectType_CycleComplete_AddComment, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Acknowledge Method. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_Acknowledge = new ExpandedNodeId(TestData.Methods.UserArrayValueObjectType_CycleComplete_Acknowledge, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_ScalarMethod1 Method. /// public static readonly ExpandedNodeId MethodTestType_ScalarMethod1 = new ExpandedNodeId(TestData.Methods.MethodTestType_ScalarMethod1, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_ScalarMethod2 Method. /// public static readonly ExpandedNodeId MethodTestType_ScalarMethod2 = new ExpandedNodeId(TestData.Methods.MethodTestType_ScalarMethod2, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_ScalarMethod3 Method. /// public static readonly ExpandedNodeId MethodTestType_ScalarMethod3 = new ExpandedNodeId(TestData.Methods.MethodTestType_ScalarMethod3, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_ArrayMethod1 Method. /// public static readonly ExpandedNodeId MethodTestType_ArrayMethod1 = new ExpandedNodeId(TestData.Methods.MethodTestType_ArrayMethod1, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_ArrayMethod2 Method. /// public static readonly ExpandedNodeId MethodTestType_ArrayMethod2 = new ExpandedNodeId(TestData.Methods.MethodTestType_ArrayMethod2, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_ArrayMethod3 Method. /// public static readonly ExpandedNodeId MethodTestType_ArrayMethod3 = new ExpandedNodeId(TestData.Methods.MethodTestType_ArrayMethod3, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_UserScalarMethod1 Method. /// public static readonly ExpandedNodeId MethodTestType_UserScalarMethod1 = new ExpandedNodeId(TestData.Methods.MethodTestType_UserScalarMethod1, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_UserScalarMethod2 Method. /// public static readonly ExpandedNodeId MethodTestType_UserScalarMethod2 = new ExpandedNodeId(TestData.Methods.MethodTestType_UserScalarMethod2, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_UserArrayMethod1 Method. /// public static readonly ExpandedNodeId MethodTestType_UserArrayMethod1 = new ExpandedNodeId(TestData.Methods.MethodTestType_UserArrayMethod1, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_UserArrayMethod2 Method. /// public static readonly ExpandedNodeId MethodTestType_UserArrayMethod2 = new ExpandedNodeId(TestData.Methods.MethodTestType_UserArrayMethod2, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_GenerateValues Method. /// public static readonly ExpandedNodeId Data_Static_Scalar_GenerateValues = new ExpandedNodeId(TestData.Methods.Data_Static_Scalar_GenerateValues, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_Disable Method. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_Disable = new ExpandedNodeId(TestData.Methods.Data_Static_Scalar_CycleComplete_Disable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_Enable Method. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_Enable = new ExpandedNodeId(TestData.Methods.Data_Static_Scalar_CycleComplete_Enable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_AddComment Method. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_AddComment = new ExpandedNodeId(TestData.Methods.Data_Static_Scalar_CycleComplete_AddComment, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_Acknowledge Method. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_Acknowledge = new ExpandedNodeId(TestData.Methods.Data_Static_Scalar_CycleComplete_Acknowledge, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_GenerateValues Method. /// public static readonly ExpandedNodeId Data_Static_Array_GenerateValues = new ExpandedNodeId(TestData.Methods.Data_Static_Array_GenerateValues, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_Disable Method. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_Disable = new ExpandedNodeId(TestData.Methods.Data_Static_Array_CycleComplete_Disable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_Enable Method. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_Enable = new ExpandedNodeId(TestData.Methods.Data_Static_Array_CycleComplete_Enable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_AddComment Method. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_AddComment = new ExpandedNodeId(TestData.Methods.Data_Static_Array_CycleComplete_AddComment, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_Acknowledge Method. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_Acknowledge = new ExpandedNodeId(TestData.Methods.Data_Static_Array_CycleComplete_Acknowledge, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_GenerateValues Method. /// public static readonly ExpandedNodeId Data_Static_UserScalar_GenerateValues = new ExpandedNodeId(TestData.Methods.Data_Static_UserScalar_GenerateValues, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Disable Method. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_Disable = new ExpandedNodeId(TestData.Methods.Data_Static_UserScalar_CycleComplete_Disable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Enable Method. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_Enable = new ExpandedNodeId(TestData.Methods.Data_Static_UserScalar_CycleComplete_Enable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_AddComment Method. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_AddComment = new ExpandedNodeId(TestData.Methods.Data_Static_UserScalar_CycleComplete_AddComment, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Acknowledge Method. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_Acknowledge = new ExpandedNodeId(TestData.Methods.Data_Static_UserScalar_CycleComplete_Acknowledge, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_GenerateValues Method. /// public static readonly ExpandedNodeId Data_Static_UserArray_GenerateValues = new ExpandedNodeId(TestData.Methods.Data_Static_UserArray_GenerateValues, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_Disable Method. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_Disable = new ExpandedNodeId(TestData.Methods.Data_Static_UserArray_CycleComplete_Disable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_Enable Method. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_Enable = new ExpandedNodeId(TestData.Methods.Data_Static_UserArray_CycleComplete_Enable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_AddComment Method. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_AddComment = new ExpandedNodeId(TestData.Methods.Data_Static_UserArray_CycleComplete_AddComment, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_Acknowledge Method. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_Acknowledge = new ExpandedNodeId(TestData.Methods.Data_Static_UserArray_CycleComplete_Acknowledge, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_GenerateValues Method. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_GenerateValues = new ExpandedNodeId(TestData.Methods.Data_Static_AnalogScalar_GenerateValues, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Disable Method. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_Disable = new ExpandedNodeId(TestData.Methods.Data_Static_AnalogScalar_CycleComplete_Disable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Enable Method. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_Enable = new ExpandedNodeId(TestData.Methods.Data_Static_AnalogScalar_CycleComplete_Enable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_AddComment Method. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_AddComment = new ExpandedNodeId(TestData.Methods.Data_Static_AnalogScalar_CycleComplete_AddComment, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Acknowledge Method. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_Acknowledge = new ExpandedNodeId(TestData.Methods.Data_Static_AnalogScalar_CycleComplete_Acknowledge, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_GenerateValues Method. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_GenerateValues = new ExpandedNodeId(TestData.Methods.Data_Static_AnalogArray_GenerateValues, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Disable Method. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_Disable = new ExpandedNodeId(TestData.Methods.Data_Static_AnalogArray_CycleComplete_Disable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Enable Method. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_Enable = new ExpandedNodeId(TestData.Methods.Data_Static_AnalogArray_CycleComplete_Enable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_AddComment Method. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_AddComment = new ExpandedNodeId(TestData.Methods.Data_Static_AnalogArray_CycleComplete_AddComment, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Acknowledge Method. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_Acknowledge = new ExpandedNodeId(TestData.Methods.Data_Static_AnalogArray_CycleComplete_Acknowledge, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_ScalarMethod1 Method. /// public static readonly ExpandedNodeId Data_Static_MethodTest_ScalarMethod1 = new ExpandedNodeId(TestData.Methods.Data_Static_MethodTest_ScalarMethod1, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_ScalarMethod2 Method. /// public static readonly ExpandedNodeId Data_Static_MethodTest_ScalarMethod2 = new ExpandedNodeId(TestData.Methods.Data_Static_MethodTest_ScalarMethod2, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_ScalarMethod3 Method. /// public static readonly ExpandedNodeId Data_Static_MethodTest_ScalarMethod3 = new ExpandedNodeId(TestData.Methods.Data_Static_MethodTest_ScalarMethod3, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_ArrayMethod1 Method. /// public static readonly ExpandedNodeId Data_Static_MethodTest_ArrayMethod1 = new ExpandedNodeId(TestData.Methods.Data_Static_MethodTest_ArrayMethod1, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_ArrayMethod2 Method. /// public static readonly ExpandedNodeId Data_Static_MethodTest_ArrayMethod2 = new ExpandedNodeId(TestData.Methods.Data_Static_MethodTest_ArrayMethod2, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_ArrayMethod3 Method. /// public static readonly ExpandedNodeId Data_Static_MethodTest_ArrayMethod3 = new ExpandedNodeId(TestData.Methods.Data_Static_MethodTest_ArrayMethod3, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_UserScalarMethod1 Method. /// public static readonly ExpandedNodeId Data_Static_MethodTest_UserScalarMethod1 = new ExpandedNodeId(TestData.Methods.Data_Static_MethodTest_UserScalarMethod1, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_UserScalarMethod2 Method. /// public static readonly ExpandedNodeId Data_Static_MethodTest_UserScalarMethod2 = new ExpandedNodeId(TestData.Methods.Data_Static_MethodTest_UserScalarMethod2, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_UserArrayMethod1 Method. /// public static readonly ExpandedNodeId Data_Static_MethodTest_UserArrayMethod1 = new ExpandedNodeId(TestData.Methods.Data_Static_MethodTest_UserArrayMethod1, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_UserArrayMethod2 Method. /// public static readonly ExpandedNodeId Data_Static_MethodTest_UserArrayMethod2 = new ExpandedNodeId(TestData.Methods.Data_Static_MethodTest_UserArrayMethod2, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_GenerateValues Method. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_GenerateValues = new ExpandedNodeId(TestData.Methods.Data_Dynamic_Scalar_GenerateValues, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Disable Method. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_Disable = new ExpandedNodeId(TestData.Methods.Data_Dynamic_Scalar_CycleComplete_Disable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Enable Method. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_Enable = new ExpandedNodeId(TestData.Methods.Data_Dynamic_Scalar_CycleComplete_Enable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_AddComment Method. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_AddComment = new ExpandedNodeId(TestData.Methods.Data_Dynamic_Scalar_CycleComplete_AddComment, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Acknowledge Method. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_Acknowledge = new ExpandedNodeId(TestData.Methods.Data_Dynamic_Scalar_CycleComplete_Acknowledge, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_GenerateValues Method. /// public static readonly ExpandedNodeId Data_Dynamic_Array_GenerateValues = new ExpandedNodeId(TestData.Methods.Data_Dynamic_Array_GenerateValues, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Disable Method. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_Disable = new ExpandedNodeId(TestData.Methods.Data_Dynamic_Array_CycleComplete_Disable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Enable Method. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_Enable = new ExpandedNodeId(TestData.Methods.Data_Dynamic_Array_CycleComplete_Enable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_AddComment Method. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_AddComment = new ExpandedNodeId(TestData.Methods.Data_Dynamic_Array_CycleComplete_AddComment, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Acknowledge Method. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_Acknowledge = new ExpandedNodeId(TestData.Methods.Data_Dynamic_Array_CycleComplete_Acknowledge, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_GenerateValues Method. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_GenerateValues = new ExpandedNodeId(TestData.Methods.Data_Dynamic_UserScalar_GenerateValues, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Disable Method. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_Disable = new ExpandedNodeId(TestData.Methods.Data_Dynamic_UserScalar_CycleComplete_Disable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Enable Method. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_Enable = new ExpandedNodeId(TestData.Methods.Data_Dynamic_UserScalar_CycleComplete_Enable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_AddComment Method. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_AddComment = new ExpandedNodeId(TestData.Methods.Data_Dynamic_UserScalar_CycleComplete_AddComment, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Acknowledge Method. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_Acknowledge = new ExpandedNodeId(TestData.Methods.Data_Dynamic_UserScalar_CycleComplete_Acknowledge, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_GenerateValues Method. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_GenerateValues = new ExpandedNodeId(TestData.Methods.Data_Dynamic_UserArray_GenerateValues, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Disable Method. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_Disable = new ExpandedNodeId(TestData.Methods.Data_Dynamic_UserArray_CycleComplete_Disable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Enable Method. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_Enable = new ExpandedNodeId(TestData.Methods.Data_Dynamic_UserArray_CycleComplete_Enable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_AddComment Method. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_AddComment = new ExpandedNodeId(TestData.Methods.Data_Dynamic_UserArray_CycleComplete_AddComment, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Acknowledge Method. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_Acknowledge = new ExpandedNodeId(TestData.Methods.Data_Dynamic_UserArray_CycleComplete_Acknowledge, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_GenerateValues Method. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_GenerateValues = new ExpandedNodeId(TestData.Methods.Data_Dynamic_AnalogScalar_GenerateValues, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Disable Method. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_Disable = new ExpandedNodeId(TestData.Methods.Data_Dynamic_AnalogScalar_CycleComplete_Disable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Enable Method. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_Enable = new ExpandedNodeId(TestData.Methods.Data_Dynamic_AnalogScalar_CycleComplete_Enable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_AddComment Method. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_AddComment = new ExpandedNodeId(TestData.Methods.Data_Dynamic_AnalogScalar_CycleComplete_AddComment, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Acknowledge Method. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_Acknowledge = new ExpandedNodeId(TestData.Methods.Data_Dynamic_AnalogScalar_CycleComplete_Acknowledge, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_GenerateValues Method. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_GenerateValues = new ExpandedNodeId(TestData.Methods.Data_Dynamic_AnalogArray_GenerateValues, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Disable Method. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_Disable = new ExpandedNodeId(TestData.Methods.Data_Dynamic_AnalogArray_CycleComplete_Disable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Enable Method. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_Enable = new ExpandedNodeId(TestData.Methods.Data_Dynamic_AnalogArray_CycleComplete_Enable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_AddComment Method. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_AddComment = new ExpandedNodeId(TestData.Methods.Data_Dynamic_AnalogArray_CycleComplete_AddComment, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Acknowledge Method. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_Acknowledge = new ExpandedNodeId(TestData.Methods.Data_Dynamic_AnalogArray_CycleComplete_Acknowledge, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_Disable Method. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_Disable = new ExpandedNodeId(TestData.Methods.Data_Conditions_SystemStatus_Disable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_Enable Method. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_Enable = new ExpandedNodeId(TestData.Methods.Data_Conditions_SystemStatus_Enable, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_AddComment Method. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_AddComment = new ExpandedNodeId(TestData.Methods.Data_Conditions_SystemStatus_AddComment, TestData.Namespaces.TestData); } #endregion #region Object Node Identifiers /// /// A class that declares constants for all Objects in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectIds { /// /// The identifier for the TestDataObjectType_CycleComplete Object. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete = new ExpandedNodeId(TestData.Objects.TestDataObjectType_CycleComplete, TestData.Namespaces.TestData); /// /// The identifier for the Data Object. /// public static readonly ExpandedNodeId Data = new ExpandedNodeId(TestData.Objects.Data, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static Object. /// public static readonly ExpandedNodeId Data_Static = new ExpandedNodeId(TestData.Objects.Data_Static, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar Object. /// public static readonly ExpandedNodeId Data_Static_Scalar = new ExpandedNodeId(TestData.Objects.Data_Static_Scalar, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete Object. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete = new ExpandedNodeId(TestData.Objects.Data_Static_Scalar_CycleComplete, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array Object. /// public static readonly ExpandedNodeId Data_Static_Array = new ExpandedNodeId(TestData.Objects.Data_Static_Array, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete Object. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete = new ExpandedNodeId(TestData.Objects.Data_Static_Array_CycleComplete, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar Object. /// public static readonly ExpandedNodeId Data_Static_UserScalar = new ExpandedNodeId(TestData.Objects.Data_Static_UserScalar, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete Object. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete = new ExpandedNodeId(TestData.Objects.Data_Static_UserScalar_CycleComplete, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray Object. /// public static readonly ExpandedNodeId Data_Static_UserArray = new ExpandedNodeId(TestData.Objects.Data_Static_UserArray, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete Object. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete = new ExpandedNodeId(TestData.Objects.Data_Static_UserArray_CycleComplete, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar Object. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar = new ExpandedNodeId(TestData.Objects.Data_Static_AnalogScalar, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete Object. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete = new ExpandedNodeId(TestData.Objects.Data_Static_AnalogScalar_CycleComplete, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray Object. /// public static readonly ExpandedNodeId Data_Static_AnalogArray = new ExpandedNodeId(TestData.Objects.Data_Static_AnalogArray, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete Object. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete = new ExpandedNodeId(TestData.Objects.Data_Static_AnalogArray_CycleComplete, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest Object. /// public static readonly ExpandedNodeId Data_Static_MethodTest = new ExpandedNodeId(TestData.Objects.Data_Static_MethodTest, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic Object. /// public static readonly ExpandedNodeId Data_Dynamic = new ExpandedNodeId(TestData.Objects.Data_Dynamic, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar Object. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar = new ExpandedNodeId(TestData.Objects.Data_Dynamic_Scalar, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete Object. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete = new ExpandedNodeId(TestData.Objects.Data_Dynamic_Scalar_CycleComplete, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array Object. /// public static readonly ExpandedNodeId Data_Dynamic_Array = new ExpandedNodeId(TestData.Objects.Data_Dynamic_Array, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete Object. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete = new ExpandedNodeId(TestData.Objects.Data_Dynamic_Array_CycleComplete, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar Object. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar = new ExpandedNodeId(TestData.Objects.Data_Dynamic_UserScalar, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete Object. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete = new ExpandedNodeId(TestData.Objects.Data_Dynamic_UserScalar_CycleComplete, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray Object. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray = new ExpandedNodeId(TestData.Objects.Data_Dynamic_UserArray, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete Object. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete = new ExpandedNodeId(TestData.Objects.Data_Dynamic_UserArray_CycleComplete, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar Object. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar = new ExpandedNodeId(TestData.Objects.Data_Dynamic_AnalogScalar, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete Object. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete = new ExpandedNodeId(TestData.Objects.Data_Dynamic_AnalogScalar_CycleComplete, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray Object. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray = new ExpandedNodeId(TestData.Objects.Data_Dynamic_AnalogArray, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete Object. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete = new ExpandedNodeId(TestData.Objects.Data_Dynamic_AnalogArray_CycleComplete, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions Object. /// public static readonly ExpandedNodeId Data_Conditions = new ExpandedNodeId(TestData.Objects.Data_Conditions, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus Object. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus = new ExpandedNodeId(TestData.Objects.Data_Conditions_SystemStatus, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueDataType_Encoding_DefaultBinary Object. /// public static readonly ExpandedNodeId ScalarValueDataType_Encoding_DefaultBinary = new ExpandedNodeId(TestData.Objects.ScalarValueDataType_Encoding_DefaultBinary, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueDataType_Encoding_DefaultBinary Object. /// public static readonly ExpandedNodeId ArrayValueDataType_Encoding_DefaultBinary = new ExpandedNodeId(TestData.Objects.ArrayValueDataType_Encoding_DefaultBinary, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueDataType_Encoding_DefaultBinary Object. /// public static readonly ExpandedNodeId UserScalarValueDataType_Encoding_DefaultBinary = new ExpandedNodeId(TestData.Objects.UserScalarValueDataType_Encoding_DefaultBinary, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueDataType_Encoding_DefaultBinary Object. /// public static readonly ExpandedNodeId UserArrayValueDataType_Encoding_DefaultBinary = new ExpandedNodeId(TestData.Objects.UserArrayValueDataType_Encoding_DefaultBinary, TestData.Namespaces.TestData); /// /// The identifier for the Vector_Encoding_DefaultBinary Object. /// public static readonly ExpandedNodeId Vector_Encoding_DefaultBinary = new ExpandedNodeId(TestData.Objects.Vector_Encoding_DefaultBinary, TestData.Namespaces.TestData); /// /// The identifier for the WorkOrderStatusType_Encoding_DefaultBinary Object. /// public static readonly ExpandedNodeId WorkOrderStatusType_Encoding_DefaultBinary = new ExpandedNodeId(TestData.Objects.WorkOrderStatusType_Encoding_DefaultBinary, TestData.Namespaces.TestData); /// /// The identifier for the WorkOrderType_Encoding_DefaultBinary Object. /// public static readonly ExpandedNodeId WorkOrderType_Encoding_DefaultBinary = new ExpandedNodeId(TestData.Objects.WorkOrderType_Encoding_DefaultBinary, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueDataType_Encoding_DefaultXml Object. /// public static readonly ExpandedNodeId ScalarValueDataType_Encoding_DefaultXml = new ExpandedNodeId(TestData.Objects.ScalarValueDataType_Encoding_DefaultXml, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueDataType_Encoding_DefaultXml Object. /// public static readonly ExpandedNodeId ArrayValueDataType_Encoding_DefaultXml = new ExpandedNodeId(TestData.Objects.ArrayValueDataType_Encoding_DefaultXml, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueDataType_Encoding_DefaultXml Object. /// public static readonly ExpandedNodeId UserScalarValueDataType_Encoding_DefaultXml = new ExpandedNodeId(TestData.Objects.UserScalarValueDataType_Encoding_DefaultXml, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueDataType_Encoding_DefaultXml Object. /// public static readonly ExpandedNodeId UserArrayValueDataType_Encoding_DefaultXml = new ExpandedNodeId(TestData.Objects.UserArrayValueDataType_Encoding_DefaultXml, TestData.Namespaces.TestData); /// /// The identifier for the Vector_Encoding_DefaultXml Object. /// public static readonly ExpandedNodeId Vector_Encoding_DefaultXml = new ExpandedNodeId(TestData.Objects.Vector_Encoding_DefaultXml, TestData.Namespaces.TestData); /// /// The identifier for the WorkOrderStatusType_Encoding_DefaultXml Object. /// public static readonly ExpandedNodeId WorkOrderStatusType_Encoding_DefaultXml = new ExpandedNodeId(TestData.Objects.WorkOrderStatusType_Encoding_DefaultXml, TestData.Namespaces.TestData); /// /// The identifier for the WorkOrderType_Encoding_DefaultXml Object. /// public static readonly ExpandedNodeId WorkOrderType_Encoding_DefaultXml = new ExpandedNodeId(TestData.Objects.WorkOrderType_Encoding_DefaultXml, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueDataType_Encoding_DefaultJson Object. /// public static readonly ExpandedNodeId ScalarValueDataType_Encoding_DefaultJson = new ExpandedNodeId(TestData.Objects.ScalarValueDataType_Encoding_DefaultJson, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueDataType_Encoding_DefaultJson Object. /// public static readonly ExpandedNodeId ArrayValueDataType_Encoding_DefaultJson = new ExpandedNodeId(TestData.Objects.ArrayValueDataType_Encoding_DefaultJson, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueDataType_Encoding_DefaultJson Object. /// public static readonly ExpandedNodeId UserScalarValueDataType_Encoding_DefaultJson = new ExpandedNodeId(TestData.Objects.UserScalarValueDataType_Encoding_DefaultJson, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueDataType_Encoding_DefaultJson Object. /// public static readonly ExpandedNodeId UserArrayValueDataType_Encoding_DefaultJson = new ExpandedNodeId(TestData.Objects.UserArrayValueDataType_Encoding_DefaultJson, TestData.Namespaces.TestData); /// /// The identifier for the Vector_Encoding_DefaultJson Object. /// public static readonly ExpandedNodeId Vector_Encoding_DefaultJson = new ExpandedNodeId(TestData.Objects.Vector_Encoding_DefaultJson, TestData.Namespaces.TestData); /// /// The identifier for the WorkOrderStatusType_Encoding_DefaultJson Object. /// public static readonly ExpandedNodeId WorkOrderStatusType_Encoding_DefaultJson = new ExpandedNodeId(TestData.Objects.WorkOrderStatusType_Encoding_DefaultJson, TestData.Namespaces.TestData); /// /// The identifier for the WorkOrderType_Encoding_DefaultJson Object. /// public static readonly ExpandedNodeId WorkOrderType_Encoding_DefaultJson = new ExpandedNodeId(TestData.Objects.WorkOrderType_Encoding_DefaultJson, TestData.Namespaces.TestData); } #endregion #region ObjectType Node Identifiers /// /// A class that declares constants for all ObjectTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectTypeIds { /// /// The identifier for the GenerateValuesEventType ObjectType. /// public static readonly ExpandedNodeId GenerateValuesEventType = new ExpandedNodeId(TestData.ObjectTypes.GenerateValuesEventType, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType ObjectType. /// public static readonly ExpandedNodeId TestDataObjectType = new ExpandedNodeId(TestData.ObjectTypes.TestDataObjectType, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType ObjectType. /// public static readonly ExpandedNodeId ScalarValueObjectType = new ExpandedNodeId(TestData.ObjectTypes.ScalarValueObjectType, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType ObjectType. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType = new ExpandedNodeId(TestData.ObjectTypes.AnalogScalarValueObjectType, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType ObjectType. /// public static readonly ExpandedNodeId ArrayValueObjectType = new ExpandedNodeId(TestData.ObjectTypes.ArrayValueObjectType, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType ObjectType. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType = new ExpandedNodeId(TestData.ObjectTypes.AnalogArrayValueObjectType, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType ObjectType. /// public static readonly ExpandedNodeId UserScalarValueObjectType = new ExpandedNodeId(TestData.ObjectTypes.UserScalarValueObjectType, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType ObjectType. /// public static readonly ExpandedNodeId UserArrayValueObjectType = new ExpandedNodeId(TestData.ObjectTypes.UserArrayValueObjectType, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType ObjectType. /// public static readonly ExpandedNodeId MethodTestType = new ExpandedNodeId(TestData.ObjectTypes.MethodTestType, TestData.Namespaces.TestData); /// /// The identifier for the TestSystemConditionType ObjectType. /// public static readonly ExpandedNodeId TestSystemConditionType = new ExpandedNodeId(TestData.ObjectTypes.TestSystemConditionType, TestData.Namespaces.TestData); } #endregion #region Variable Node Identifiers /// /// A class that declares constants for all Variables in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class VariableIds { /// /// The identifier for the GenerateValuesEventType_Iterations Variable. /// public static readonly ExpandedNodeId GenerateValuesEventType_Iterations = new ExpandedNodeId(TestData.Variables.GenerateValuesEventType_Iterations, TestData.Namespaces.TestData); /// /// The identifier for the GenerateValuesEventType_NewValueCount Variable. /// public static readonly ExpandedNodeId GenerateValuesEventType_NewValueCount = new ExpandedNodeId(TestData.Variables.GenerateValuesEventType_NewValueCount, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_SimulationActive Variable. /// public static readonly ExpandedNodeId TestDataObjectType_SimulationActive = new ExpandedNodeId(TestData.Variables.TestDataObjectType_SimulationActive, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_GenerateValues_InputArguments Variable. /// public static readonly ExpandedNodeId TestDataObjectType_GenerateValues_InputArguments = new ExpandedNodeId(TestData.Variables.TestDataObjectType_GenerateValues_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_EventId Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_EventId = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_EventId, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_EventType Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_EventType = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_EventType, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_SourceNode Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_SourceNode = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_SourceNode, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_SourceName Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_SourceName = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_SourceName, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_Time Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_Time = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_Time, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_ReceiveTime Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_ReceiveTime = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_ReceiveTime, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_Message Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_Message = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_Message, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_Severity Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_Severity = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_Severity, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_ConditionClassId Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_ConditionClassId = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_ConditionClassId, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_ConditionClassName Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_ConditionClassName = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_ConditionClassName, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_ConditionName Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_ConditionName = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_ConditionName, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_BranchId Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_BranchId = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_BranchId, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_Retain Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_Retain = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_Retain, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_EnabledState Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_EnabledState = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_EnabledState, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_EnabledState_Id Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_EnabledState_Id = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_EnabledState_Id, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_Quality Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_Quality = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_Quality, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_Quality_SourceTimestamp Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_Quality_SourceTimestamp = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_Quality_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_LastSeverity Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_LastSeverity = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_LastSeverity, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_LastSeverity_SourceTimestamp = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_LastSeverity_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_Comment Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_Comment = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_Comment, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_Comment_SourceTimestamp Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_Comment_SourceTimestamp = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_Comment_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_ClientUserId Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_ClientUserId = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_ClientUserId, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_AddComment_InputArguments Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_AddComment_InputArguments = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_AddComment_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_AckedState Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_AckedState = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_AckedState, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_AckedState_Id Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_AckedState_Id = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_AckedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_ConfirmedState_Id Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_ConfirmedState_Id = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_ConfirmedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_Acknowledge_InputArguments Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_Acknowledge_InputArguments = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_Acknowledge_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the TestDataObjectType_CycleComplete_Confirm_InputArguments Variable. /// public static readonly ExpandedNodeId TestDataObjectType_CycleComplete_Confirm_InputArguments = new ExpandedNodeId(TestData.Variables.TestDataObjectType_CycleComplete_Confirm_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_GenerateValues_InputArguments Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_GenerateValues_InputArguments = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_GenerateValues_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_EventId Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_EventId = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_EventId, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_EventType Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_EventType = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_EventType, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_SourceNode Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_SourceNode = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_SourceNode, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_SourceName Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_SourceName = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_SourceName, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_Time Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_Time = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_Time, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_ReceiveTime Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_ReceiveTime = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_ReceiveTime, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_Message Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_Message = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_Message, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_Severity Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_Severity = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_Severity, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_ConditionClassId Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_ConditionClassId = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_ConditionClassId, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_ConditionClassName Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_ConditionClassName = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_ConditionClassName, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_ConditionName Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_ConditionName = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_ConditionName, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_BranchId Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_BranchId = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_BranchId, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_Retain Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_Retain = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_Retain, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_EnabledState Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_EnabledState = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_EnabledState, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_EnabledState_Id Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_EnabledState_Id = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_EnabledState_Id, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_Quality Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_Quality = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_Quality, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_Quality_SourceTimestamp Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_Quality_SourceTimestamp = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_Quality_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_LastSeverity Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_LastSeverity = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_LastSeverity, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_LastSeverity_SourceTimestamp = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_LastSeverity_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_Comment Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_Comment = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_Comment, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_Comment_SourceTimestamp Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_Comment_SourceTimestamp = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_Comment_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_ClientUserId Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_ClientUserId = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_ClientUserId, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_AddComment_InputArguments Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_AddComment_InputArguments = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_AddComment_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_AckedState Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_AckedState = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_AckedState, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_AckedState_Id Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_AckedState_Id = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_AckedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_ConfirmedState_Id Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_ConfirmedState_Id = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_ConfirmedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_Acknowledge_InputArguments Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_Acknowledge_InputArguments = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_Acknowledge_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_CycleComplete_Confirm_InputArguments Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_CycleComplete_Confirm_InputArguments = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_CycleComplete_Confirm_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_BooleanValue Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_BooleanValue = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_BooleanValue, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_SByteValue Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_SByteValue = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_SByteValue, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_ByteValue Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_ByteValue = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_ByteValue, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_Int16Value Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_Int16Value = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_Int16Value, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_UInt16Value Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_UInt16Value = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_UInt16Value, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_Int32Value Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_Int32Value = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_Int32Value, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_UInt32Value Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_UInt32Value = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_UInt32Value, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_Int64Value Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_Int64Value = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_Int64Value, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_UInt64Value Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_UInt64Value = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_UInt64Value, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_FloatValue Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_FloatValue = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_FloatValue, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_DoubleValue Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_DoubleValue = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_DoubleValue, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_StringValue Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_StringValue = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_StringValue, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_DateTimeValue Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_DateTimeValue = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_DateTimeValue, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_GuidValue Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_GuidValue = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_GuidValue, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_ByteStringValue Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_ByteStringValue = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_ByteStringValue, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_XmlElementValue Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_XmlElementValue = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_XmlElementValue, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_NodeIdValue Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_NodeIdValue = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_NodeIdValue, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_ExpandedNodeIdValue Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_ExpandedNodeIdValue = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_ExpandedNodeIdValue, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_QualifiedNameValue Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_QualifiedNameValue = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_QualifiedNameValue, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_LocalizedTextValue Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_LocalizedTextValue = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_LocalizedTextValue, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_StatusCodeValue Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_StatusCodeValue = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_StatusCodeValue, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_VariantValue Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_VariantValue = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_VariantValue, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_EnumerationValue Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_EnumerationValue = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_EnumerationValue, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_StructureValue Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_StructureValue = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_StructureValue, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_NumberValue Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_NumberValue = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_NumberValue, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_IntegerValue Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_IntegerValue = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_IntegerValue, TestData.Namespaces.TestData); /// /// The identifier for the ScalarValueObjectType_UIntegerValue Variable. /// public static readonly ExpandedNodeId ScalarValueObjectType_UIntegerValue = new ExpandedNodeId(TestData.Variables.ScalarValueObjectType_UIntegerValue, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_GenerateValues_InputArguments Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_GenerateValues_InputArguments = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_GenerateValues_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_EventId Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_EventId = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_EventId, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_EventType Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_EventType = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_EventType, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_SourceNode Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_SourceNode = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_SourceNode, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_SourceName Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_SourceName = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_SourceName, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Time Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_Time = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_Time, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_ReceiveTime Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_ReceiveTime = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_ReceiveTime, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Message Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_Message = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_Message, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Severity Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_Severity = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_Severity, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_ConditionClassId Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_ConditionClassId = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_ConditionClassId, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_ConditionClassName Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_ConditionClassName = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_ConditionClassName, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_ConditionName Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_ConditionName = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_ConditionName, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_BranchId Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_BranchId = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_BranchId, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Retain Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_Retain = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_Retain, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_EnabledState Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_EnabledState = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_EnabledState, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_EnabledState_Id Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_EnabledState_Id = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_EnabledState_Id, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Quality Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_Quality = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_Quality, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Quality_SourceTimestamp Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_Quality_SourceTimestamp = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_Quality_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_LastSeverity Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_LastSeverity = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_LastSeverity, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_LastSeverity_SourceTimestamp = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_LastSeverity_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Comment Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_Comment = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_Comment, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Comment_SourceTimestamp Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_Comment_SourceTimestamp = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_Comment_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_ClientUserId Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_ClientUserId = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_ClientUserId, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_AddComment_InputArguments Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_AddComment_InputArguments = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_AddComment_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_AckedState Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_AckedState = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_AckedState, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_AckedState_Id Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_AckedState_Id = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_AckedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_ConfirmedState_Id Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_ConfirmedState_Id = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_ConfirmedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Acknowledge_InputArguments Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_Acknowledge_InputArguments = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_Acknowledge_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_CycleComplete_Confirm_InputArguments Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_CycleComplete_Confirm_InputArguments = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_CycleComplete_Confirm_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_SByteValue Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_SByteValue = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_SByteValue, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_SByteValue_EURange Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_SByteValue_EURange = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_SByteValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_ByteValue Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_ByteValue = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_ByteValue, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_ByteValue_EURange Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_ByteValue_EURange = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_ByteValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_Int16Value Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_Int16Value = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_Int16Value, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_Int16Value_EURange Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_Int16Value_EURange = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_Int16Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_UInt16Value Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_UInt16Value = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_UInt16Value, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_UInt16Value_EURange Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_UInt16Value_EURange = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_UInt16Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_Int32Value Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_Int32Value = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_Int32Value, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_Int32Value_EURange Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_Int32Value_EURange = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_Int32Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_UInt32Value Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_UInt32Value = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_UInt32Value, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_UInt32Value_EURange Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_UInt32Value_EURange = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_UInt32Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_Int64Value Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_Int64Value = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_Int64Value, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_Int64Value_EURange Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_Int64Value_EURange = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_Int64Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_UInt64Value Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_UInt64Value = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_UInt64Value, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_UInt64Value_EURange Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_UInt64Value_EURange = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_UInt64Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_FloatValue Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_FloatValue = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_FloatValue, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_FloatValue_EURange Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_FloatValue_EURange = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_FloatValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_DoubleValue Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_DoubleValue = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_DoubleValue, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_DoubleValue_EURange Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_DoubleValue_EURange = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_DoubleValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_NumberValue Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_NumberValue = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_NumberValue, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_NumberValue_EURange Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_NumberValue_EURange = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_NumberValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_IntegerValue Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_IntegerValue = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_IntegerValue, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_IntegerValue_EURange Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_IntegerValue_EURange = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_IntegerValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_UIntegerValue Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_UIntegerValue = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_UIntegerValue, TestData.Namespaces.TestData); /// /// The identifier for the AnalogScalarValueObjectType_UIntegerValue_EURange Variable. /// public static readonly ExpandedNodeId AnalogScalarValueObjectType_UIntegerValue_EURange = new ExpandedNodeId(TestData.Variables.AnalogScalarValueObjectType_UIntegerValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_GenerateValues_InputArguments Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_GenerateValues_InputArguments = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_GenerateValues_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_EventId Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_EventId = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_EventId, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_EventType Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_EventType = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_EventType, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_SourceNode Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_SourceNode = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_SourceNode, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_SourceName Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_SourceName = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_SourceName, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_Time Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_Time = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_Time, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_ReceiveTime Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_ReceiveTime = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_ReceiveTime, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_Message Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_Message = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_Message, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_Severity Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_Severity = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_Severity, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_ConditionClassId Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_ConditionClassId = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_ConditionClassId, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_ConditionClassName Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_ConditionClassName = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_ConditionClassName, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_ConditionName Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_ConditionName = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_ConditionName, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_BranchId Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_BranchId = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_BranchId, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_Retain Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_Retain = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_Retain, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_EnabledState Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_EnabledState = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_EnabledState, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_EnabledState_Id Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_EnabledState_Id = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_EnabledState_Id, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_Quality Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_Quality = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_Quality, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_Quality_SourceTimestamp Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_Quality_SourceTimestamp = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_Quality_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_LastSeverity Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_LastSeverity = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_LastSeverity, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_LastSeverity_SourceTimestamp = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_LastSeverity_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_Comment Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_Comment = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_Comment, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_Comment_SourceTimestamp Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_Comment_SourceTimestamp = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_Comment_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_ClientUserId Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_ClientUserId = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_ClientUserId, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_AddComment_InputArguments Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_AddComment_InputArguments = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_AddComment_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_AckedState Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_AckedState = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_AckedState, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_AckedState_Id Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_AckedState_Id = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_AckedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_ConfirmedState_Id Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_ConfirmedState_Id = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_ConfirmedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_Acknowledge_InputArguments Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_Acknowledge_InputArguments = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_Acknowledge_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_CycleComplete_Confirm_InputArguments Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_CycleComplete_Confirm_InputArguments = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_CycleComplete_Confirm_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_BooleanValue Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_BooleanValue = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_BooleanValue, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_SByteValue Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_SByteValue = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_SByteValue, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_ByteValue Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_ByteValue = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_ByteValue, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_Int16Value Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_Int16Value = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_Int16Value, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_UInt16Value Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_UInt16Value = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_UInt16Value, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_Int32Value Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_Int32Value = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_Int32Value, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_UInt32Value Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_UInt32Value = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_UInt32Value, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_Int64Value Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_Int64Value = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_Int64Value, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_UInt64Value Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_UInt64Value = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_UInt64Value, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_FloatValue Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_FloatValue = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_FloatValue, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_DoubleValue Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_DoubleValue = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_DoubleValue, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_StringValue Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_StringValue = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_StringValue, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_DateTimeValue Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_DateTimeValue = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_DateTimeValue, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_GuidValue Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_GuidValue = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_GuidValue, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_ByteStringValue Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_ByteStringValue = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_ByteStringValue, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_XmlElementValue Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_XmlElementValue = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_XmlElementValue, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_NodeIdValue Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_NodeIdValue = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_NodeIdValue, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_ExpandedNodeIdValue Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_ExpandedNodeIdValue = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_ExpandedNodeIdValue, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_QualifiedNameValue Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_QualifiedNameValue = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_QualifiedNameValue, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_LocalizedTextValue Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_LocalizedTextValue = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_LocalizedTextValue, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_StatusCodeValue Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_StatusCodeValue = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_StatusCodeValue, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_VariantValue Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_VariantValue = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_VariantValue, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_EnumerationValue Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_EnumerationValue = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_EnumerationValue, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_StructureValue Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_StructureValue = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_StructureValue, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_NumberValue Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_NumberValue = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_NumberValue, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_IntegerValue Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_IntegerValue = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_IntegerValue, TestData.Namespaces.TestData); /// /// The identifier for the ArrayValueObjectType_UIntegerValue Variable. /// public static readonly ExpandedNodeId ArrayValueObjectType_UIntegerValue = new ExpandedNodeId(TestData.Variables.ArrayValueObjectType_UIntegerValue, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_GenerateValues_InputArguments Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_GenerateValues_InputArguments = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_GenerateValues_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_EventId Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_EventId = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_EventId, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_EventType Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_EventType = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_EventType, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_SourceNode Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_SourceNode = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_SourceNode, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_SourceName Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_SourceName = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_SourceName, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Time Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_Time = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_Time, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_ReceiveTime Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_ReceiveTime = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_ReceiveTime, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Message Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_Message = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_Message, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Severity Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_Severity = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_Severity, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_ConditionClassId Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_ConditionClassId = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_ConditionClassId, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_ConditionClassName Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_ConditionClassName = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_ConditionClassName, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_ConditionName Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_ConditionName = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_ConditionName, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_BranchId Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_BranchId = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_BranchId, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Retain Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_Retain = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_Retain, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_EnabledState Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_EnabledState = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_EnabledState, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_EnabledState_Id Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_EnabledState_Id = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_EnabledState_Id, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Quality Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_Quality = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_Quality, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Quality_SourceTimestamp Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_Quality_SourceTimestamp = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_Quality_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_LastSeverity Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_LastSeverity = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_LastSeverity, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_LastSeverity_SourceTimestamp = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_LastSeverity_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Comment Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_Comment = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_Comment, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Comment_SourceTimestamp Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_Comment_SourceTimestamp = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_Comment_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_ClientUserId Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_ClientUserId = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_ClientUserId, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_AddComment_InputArguments Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_AddComment_InputArguments = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_AddComment_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_AckedState Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_AckedState = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_AckedState, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_AckedState_Id Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_AckedState_Id = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_AckedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_ConfirmedState_Id Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_ConfirmedState_Id = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_ConfirmedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Acknowledge_InputArguments Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_Acknowledge_InputArguments = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_Acknowledge_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_CycleComplete_Confirm_InputArguments Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_CycleComplete_Confirm_InputArguments = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_CycleComplete_Confirm_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_SByteValue Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_SByteValue = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_SByteValue, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_SByteValue_EURange Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_SByteValue_EURange = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_SByteValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_ByteValue Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_ByteValue = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_ByteValue, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_ByteValue_EURange Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_ByteValue_EURange = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_ByteValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_Int16Value Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_Int16Value = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_Int16Value, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_Int16Value_EURange Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_Int16Value_EURange = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_Int16Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_UInt16Value Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_UInt16Value = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_UInt16Value, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_UInt16Value_EURange Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_UInt16Value_EURange = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_UInt16Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_Int32Value Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_Int32Value = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_Int32Value, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_Int32Value_EURange Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_Int32Value_EURange = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_Int32Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_UInt32Value Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_UInt32Value = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_UInt32Value, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_UInt32Value_EURange Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_UInt32Value_EURange = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_UInt32Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_Int64Value Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_Int64Value = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_Int64Value, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_Int64Value_EURange Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_Int64Value_EURange = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_Int64Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_UInt64Value Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_UInt64Value = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_UInt64Value, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_UInt64Value_EURange Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_UInt64Value_EURange = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_UInt64Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_FloatValue Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_FloatValue = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_FloatValue, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_FloatValue_EURange Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_FloatValue_EURange = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_FloatValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_DoubleValue Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_DoubleValue = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_DoubleValue, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_DoubleValue_EURange Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_DoubleValue_EURange = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_DoubleValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_NumberValue Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_NumberValue = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_NumberValue, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_NumberValue_EURange Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_NumberValue_EURange = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_NumberValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_IntegerValue Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_IntegerValue = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_IntegerValue, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_IntegerValue_EURange Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_IntegerValue_EURange = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_IntegerValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_UIntegerValue Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_UIntegerValue = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_UIntegerValue, TestData.Namespaces.TestData); /// /// The identifier for the AnalogArrayValueObjectType_UIntegerValue_EURange Variable. /// public static readonly ExpandedNodeId AnalogArrayValueObjectType_UIntegerValue_EURange = new ExpandedNodeId(TestData.Variables.AnalogArrayValueObjectType_UIntegerValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_GenerateValues_InputArguments Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_GenerateValues_InputArguments = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_GenerateValues_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_EventId Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_EventId = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_EventId, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_EventType Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_EventType = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_EventType, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_SourceNode Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_SourceNode = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_SourceNode, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_SourceName Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_SourceName = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_SourceName, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Time Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_Time = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_Time, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_ReceiveTime Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_ReceiveTime = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_ReceiveTime, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Message Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_Message = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_Message, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Severity Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_Severity = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_Severity, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_ConditionClassId Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_ConditionClassId = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_ConditionClassId, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_ConditionClassName Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_ConditionClassName = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_ConditionClassName, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_ConditionName Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_ConditionName = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_ConditionName, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_BranchId Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_BranchId = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_BranchId, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Retain Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_Retain = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_Retain, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_EnabledState Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_EnabledState = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_EnabledState, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_EnabledState_Id Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_EnabledState_Id = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_EnabledState_Id, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Quality Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_Quality = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_Quality, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Quality_SourceTimestamp Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_Quality_SourceTimestamp = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_Quality_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_LastSeverity Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_LastSeverity = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_LastSeverity, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_LastSeverity_SourceTimestamp = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_LastSeverity_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Comment Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_Comment = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_Comment, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Comment_SourceTimestamp Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_Comment_SourceTimestamp = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_Comment_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_ClientUserId Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_ClientUserId = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_ClientUserId, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_AddComment_InputArguments Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_AddComment_InputArguments = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_AddComment_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_AckedState Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_AckedState = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_AckedState, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_AckedState_Id Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_AckedState_Id = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_AckedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_ConfirmedState_Id Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_ConfirmedState_Id = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_ConfirmedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Acknowledge_InputArguments Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_Acknowledge_InputArguments = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_Acknowledge_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_CycleComplete_Confirm_InputArguments Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_CycleComplete_Confirm_InputArguments = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_CycleComplete_Confirm_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_BooleanValue Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_BooleanValue = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_BooleanValue, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_SByteValue Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_SByteValue = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_SByteValue, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_ByteValue Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_ByteValue = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_ByteValue, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_Int16Value Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_Int16Value = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_Int16Value, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_UInt16Value Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_UInt16Value = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_UInt16Value, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_Int32Value Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_Int32Value = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_Int32Value, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_UInt32Value Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_UInt32Value = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_UInt32Value, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_Int64Value Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_Int64Value = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_Int64Value, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_UInt64Value Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_UInt64Value = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_UInt64Value, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_FloatValue Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_FloatValue = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_FloatValue, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_DoubleValue Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_DoubleValue = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_DoubleValue, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_StringValue Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_StringValue = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_StringValue, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_DateTimeValue Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_DateTimeValue = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_DateTimeValue, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_GuidValue Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_GuidValue = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_GuidValue, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_ByteStringValue Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_ByteStringValue = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_ByteStringValue, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_XmlElementValue Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_XmlElementValue = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_XmlElementValue, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_NodeIdValue Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_NodeIdValue = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_NodeIdValue, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_ExpandedNodeIdValue Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_ExpandedNodeIdValue = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_ExpandedNodeIdValue, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_QualifiedNameValue Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_QualifiedNameValue = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_QualifiedNameValue, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_LocalizedTextValue Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_LocalizedTextValue = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_LocalizedTextValue, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_StatusCodeValue Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_StatusCodeValue = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_StatusCodeValue, TestData.Namespaces.TestData); /// /// The identifier for the UserScalarValueObjectType_VariantValue Variable. /// public static readonly ExpandedNodeId UserScalarValueObjectType_VariantValue = new ExpandedNodeId(TestData.Variables.UserScalarValueObjectType_VariantValue, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_GenerateValues_InputArguments Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_GenerateValues_InputArguments = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_GenerateValues_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_EventId Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_EventId = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_EventId, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_EventType Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_EventType = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_EventType, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_SourceNode Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_SourceNode = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_SourceNode, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_SourceName Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_SourceName = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_SourceName, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Time Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_Time = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_Time, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_ReceiveTime Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_ReceiveTime = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_ReceiveTime, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Message Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_Message = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_Message, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Severity Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_Severity = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_Severity, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_ConditionClassId Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_ConditionClassId = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_ConditionClassId, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_ConditionClassName Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_ConditionClassName = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_ConditionClassName, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_ConditionName Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_ConditionName = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_ConditionName, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_BranchId Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_BranchId = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_BranchId, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Retain Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_Retain = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_Retain, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_EnabledState Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_EnabledState = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_EnabledState, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_EnabledState_Id Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_EnabledState_Id = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_EnabledState_Id, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Quality Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_Quality = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_Quality, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Quality_SourceTimestamp Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_Quality_SourceTimestamp = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_Quality_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_LastSeverity Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_LastSeverity = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_LastSeverity, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_LastSeverity_SourceTimestamp = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_LastSeverity_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Comment Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_Comment = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_Comment, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Comment_SourceTimestamp Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_Comment_SourceTimestamp = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_Comment_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_ClientUserId Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_ClientUserId = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_ClientUserId, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_AddComment_InputArguments Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_AddComment_InputArguments = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_AddComment_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_AckedState Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_AckedState = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_AckedState, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_AckedState_Id Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_AckedState_Id = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_AckedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_ConfirmedState_Id Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_ConfirmedState_Id = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_ConfirmedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Acknowledge_InputArguments Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_Acknowledge_InputArguments = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_Acknowledge_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_CycleComplete_Confirm_InputArguments Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_CycleComplete_Confirm_InputArguments = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_CycleComplete_Confirm_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_BooleanValue Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_BooleanValue = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_BooleanValue, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_SByteValue Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_SByteValue = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_SByteValue, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_ByteValue Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_ByteValue = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_ByteValue, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_Int16Value Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_Int16Value = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_Int16Value, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_UInt16Value Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_UInt16Value = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_UInt16Value, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_Int32Value Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_Int32Value = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_Int32Value, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_UInt32Value Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_UInt32Value = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_UInt32Value, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_Int64Value Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_Int64Value = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_Int64Value, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_UInt64Value Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_UInt64Value = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_UInt64Value, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_FloatValue Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_FloatValue = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_FloatValue, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_DoubleValue Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_DoubleValue = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_DoubleValue, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_StringValue Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_StringValue = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_StringValue, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_DateTimeValue Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_DateTimeValue = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_DateTimeValue, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_GuidValue Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_GuidValue = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_GuidValue, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_ByteStringValue Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_ByteStringValue = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_ByteStringValue, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_XmlElementValue Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_XmlElementValue = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_XmlElementValue, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_NodeIdValue Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_NodeIdValue = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_NodeIdValue, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_ExpandedNodeIdValue Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_ExpandedNodeIdValue = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_ExpandedNodeIdValue, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_QualifiedNameValue Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_QualifiedNameValue = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_QualifiedNameValue, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_LocalizedTextValue Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_LocalizedTextValue = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_LocalizedTextValue, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_StatusCodeValue Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_StatusCodeValue = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_StatusCodeValue, TestData.Namespaces.TestData); /// /// The identifier for the UserArrayValueObjectType_VariantValue Variable. /// public static readonly ExpandedNodeId UserArrayValueObjectType_VariantValue = new ExpandedNodeId(TestData.Variables.UserArrayValueObjectType_VariantValue, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_ScalarMethod1_InputArguments Variable. /// public static readonly ExpandedNodeId MethodTestType_ScalarMethod1_InputArguments = new ExpandedNodeId(TestData.Variables.MethodTestType_ScalarMethod1_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_ScalarMethod1_OutputArguments Variable. /// public static readonly ExpandedNodeId MethodTestType_ScalarMethod1_OutputArguments = new ExpandedNodeId(TestData.Variables.MethodTestType_ScalarMethod1_OutputArguments, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_ScalarMethod2_InputArguments Variable. /// public static readonly ExpandedNodeId MethodTestType_ScalarMethod2_InputArguments = new ExpandedNodeId(TestData.Variables.MethodTestType_ScalarMethod2_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_ScalarMethod2_OutputArguments Variable. /// public static readonly ExpandedNodeId MethodTestType_ScalarMethod2_OutputArguments = new ExpandedNodeId(TestData.Variables.MethodTestType_ScalarMethod2_OutputArguments, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_ScalarMethod3_InputArguments Variable. /// public static readonly ExpandedNodeId MethodTestType_ScalarMethod3_InputArguments = new ExpandedNodeId(TestData.Variables.MethodTestType_ScalarMethod3_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_ScalarMethod3_OutputArguments Variable. /// public static readonly ExpandedNodeId MethodTestType_ScalarMethod3_OutputArguments = new ExpandedNodeId(TestData.Variables.MethodTestType_ScalarMethod3_OutputArguments, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_ArrayMethod1_InputArguments Variable. /// public static readonly ExpandedNodeId MethodTestType_ArrayMethod1_InputArguments = new ExpandedNodeId(TestData.Variables.MethodTestType_ArrayMethod1_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_ArrayMethod1_OutputArguments Variable. /// public static readonly ExpandedNodeId MethodTestType_ArrayMethod1_OutputArguments = new ExpandedNodeId(TestData.Variables.MethodTestType_ArrayMethod1_OutputArguments, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_ArrayMethod2_InputArguments Variable. /// public static readonly ExpandedNodeId MethodTestType_ArrayMethod2_InputArguments = new ExpandedNodeId(TestData.Variables.MethodTestType_ArrayMethod2_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_ArrayMethod2_OutputArguments Variable. /// public static readonly ExpandedNodeId MethodTestType_ArrayMethod2_OutputArguments = new ExpandedNodeId(TestData.Variables.MethodTestType_ArrayMethod2_OutputArguments, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_ArrayMethod3_InputArguments Variable. /// public static readonly ExpandedNodeId MethodTestType_ArrayMethod3_InputArguments = new ExpandedNodeId(TestData.Variables.MethodTestType_ArrayMethod3_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_ArrayMethod3_OutputArguments Variable. /// public static readonly ExpandedNodeId MethodTestType_ArrayMethod3_OutputArguments = new ExpandedNodeId(TestData.Variables.MethodTestType_ArrayMethod3_OutputArguments, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_UserScalarMethod1_InputArguments Variable. /// public static readonly ExpandedNodeId MethodTestType_UserScalarMethod1_InputArguments = new ExpandedNodeId(TestData.Variables.MethodTestType_UserScalarMethod1_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_UserScalarMethod1_OutputArguments Variable. /// public static readonly ExpandedNodeId MethodTestType_UserScalarMethod1_OutputArguments = new ExpandedNodeId(TestData.Variables.MethodTestType_UserScalarMethod1_OutputArguments, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_UserScalarMethod2_InputArguments Variable. /// public static readonly ExpandedNodeId MethodTestType_UserScalarMethod2_InputArguments = new ExpandedNodeId(TestData.Variables.MethodTestType_UserScalarMethod2_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_UserScalarMethod2_OutputArguments Variable. /// public static readonly ExpandedNodeId MethodTestType_UserScalarMethod2_OutputArguments = new ExpandedNodeId(TestData.Variables.MethodTestType_UserScalarMethod2_OutputArguments, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_UserArrayMethod1_InputArguments Variable. /// public static readonly ExpandedNodeId MethodTestType_UserArrayMethod1_InputArguments = new ExpandedNodeId(TestData.Variables.MethodTestType_UserArrayMethod1_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_UserArrayMethod1_OutputArguments Variable. /// public static readonly ExpandedNodeId MethodTestType_UserArrayMethod1_OutputArguments = new ExpandedNodeId(TestData.Variables.MethodTestType_UserArrayMethod1_OutputArguments, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_UserArrayMethod2_InputArguments Variable. /// public static readonly ExpandedNodeId MethodTestType_UserArrayMethod2_InputArguments = new ExpandedNodeId(TestData.Variables.MethodTestType_UserArrayMethod2_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the MethodTestType_UserArrayMethod2_OutputArguments Variable. /// public static readonly ExpandedNodeId MethodTestType_UserArrayMethod2_OutputArguments = new ExpandedNodeId(TestData.Variables.MethodTestType_UserArrayMethod2_OutputArguments, TestData.Namespaces.TestData); /// /// The identifier for the TestSystemConditionType_EnabledState_Id Variable. /// public static readonly ExpandedNodeId TestSystemConditionType_EnabledState_Id = new ExpandedNodeId(TestData.Variables.TestSystemConditionType_EnabledState_Id, TestData.Namespaces.TestData); /// /// The identifier for the TestSystemConditionType_Quality_SourceTimestamp Variable. /// public static readonly ExpandedNodeId TestSystemConditionType_Quality_SourceTimestamp = new ExpandedNodeId(TestData.Variables.TestSystemConditionType_Quality_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the TestSystemConditionType_LastSeverity_SourceTimestamp Variable. /// public static readonly ExpandedNodeId TestSystemConditionType_LastSeverity_SourceTimestamp = new ExpandedNodeId(TestData.Variables.TestSystemConditionType_LastSeverity_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the TestSystemConditionType_Comment_SourceTimestamp Variable. /// public static readonly ExpandedNodeId TestSystemConditionType_Comment_SourceTimestamp = new ExpandedNodeId(TestData.Variables.TestSystemConditionType_Comment_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the TestSystemConditionType_AddComment_InputArguments Variable. /// public static readonly ExpandedNodeId TestSystemConditionType_AddComment_InputArguments = new ExpandedNodeId(TestData.Variables.TestSystemConditionType_AddComment_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the TestSystemConditionType_ConditionRefresh_InputArguments Variable. /// public static readonly ExpandedNodeId TestSystemConditionType_ConditionRefresh_InputArguments = new ExpandedNodeId(TestData.Variables.TestSystemConditionType_ConditionRefresh_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the TestSystemConditionType_ConditionRefresh2_InputArguments Variable. /// public static readonly ExpandedNodeId TestSystemConditionType_ConditionRefresh2_InputArguments = new ExpandedNodeId(TestData.Variables.TestSystemConditionType_ConditionRefresh2_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the TestSystemConditionType_MonitoredNodeCount Variable. /// public static readonly ExpandedNodeId TestSystemConditionType_MonitoredNodeCount = new ExpandedNodeId(TestData.Variables.TestSystemConditionType_MonitoredNodeCount, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_SimulationActive Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_SimulationActive = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_SimulationActive, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_GenerateValues_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_GenerateValues_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_GenerateValues_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_EventId Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_EventId = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_EventId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_EventType Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_EventType = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_EventType, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_SourceNode Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_SourceNode = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_SourceNode, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_SourceName Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_SourceName = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_SourceName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_Time Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_Time = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_Time, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_ReceiveTime Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_ReceiveTime = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_ReceiveTime, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_Message Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_Message = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_Message, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_Severity Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_Severity = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_Severity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_ConditionClassId Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_ConditionClassId = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_ConditionClassId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_ConditionClassName Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_ConditionClassName = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_ConditionClassName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_ConditionName Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_ConditionName = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_ConditionName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_BranchId Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_BranchId = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_BranchId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_Retain Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_Retain = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_Retain, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_EnabledState Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_EnabledState = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_EnabledState, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_EnabledState_Id Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_EnabledState_Id = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_EnabledState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_Quality Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_Quality = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_Quality, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_Quality_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_Quality_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_Quality_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_LastSeverity Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_LastSeverity = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_LastSeverity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_LastSeverity_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_LastSeverity_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_Comment Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_Comment = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_Comment, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_Comment_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_Comment_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_Comment_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_ClientUserId Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_ClientUserId = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_ClientUserId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_AddComment_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_AddComment_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_AddComment_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_AckedState Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_AckedState = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_AckedState, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_AckedState_Id Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_AckedState_Id = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_AckedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_ConfirmedState_Id Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_ConfirmedState_Id = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_ConfirmedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_Acknowledge_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_Acknowledge_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_Acknowledge_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_CycleComplete_Confirm_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_CycleComplete_Confirm_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_CycleComplete_Confirm_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_BooleanValue Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_BooleanValue = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_BooleanValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_SByteValue Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_SByteValue = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_SByteValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_ByteValue Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_ByteValue = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_ByteValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_Int16Value Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_Int16Value = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_Int16Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_UInt16Value Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_UInt16Value = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_UInt16Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_Int32Value Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_Int32Value = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_Int32Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_UInt32Value Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_UInt32Value = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_UInt32Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_Int64Value Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_Int64Value = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_Int64Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_UInt64Value Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_UInt64Value = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_UInt64Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_FloatValue Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_FloatValue = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_FloatValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_DoubleValue Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_DoubleValue = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_DoubleValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_StringValue Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_StringValue = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_StringValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_DateTimeValue Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_DateTimeValue = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_DateTimeValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_GuidValue Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_GuidValue = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_GuidValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_ByteStringValue Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_ByteStringValue = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_ByteStringValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_XmlElementValue Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_XmlElementValue = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_XmlElementValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_NodeIdValue Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_NodeIdValue = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_NodeIdValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_ExpandedNodeIdValue Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_ExpandedNodeIdValue = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_ExpandedNodeIdValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_QualifiedNameValue Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_QualifiedNameValue = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_QualifiedNameValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_LocalizedTextValue Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_LocalizedTextValue = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_LocalizedTextValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_StatusCodeValue Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_StatusCodeValue = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_StatusCodeValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_VariantValue Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_VariantValue = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_VariantValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_EnumerationValue Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_EnumerationValue = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_EnumerationValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_StructureValue Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_StructureValue = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_StructureValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_NumberValue Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_NumberValue = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_NumberValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_IntegerValue Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_IntegerValue = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_IntegerValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Scalar_UIntegerValue Variable. /// public static readonly ExpandedNodeId Data_Static_Scalar_UIntegerValue = new ExpandedNodeId(TestData.Variables.Data_Static_Scalar_UIntegerValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_SimulationActive Variable. /// public static readonly ExpandedNodeId Data_Static_Array_SimulationActive = new ExpandedNodeId(TestData.Variables.Data_Static_Array_SimulationActive, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_GenerateValues_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_Array_GenerateValues_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_Array_GenerateValues_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_EventId Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_EventId = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_EventId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_EventType Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_EventType = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_EventType, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_SourceNode Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_SourceNode = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_SourceNode, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_SourceName Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_SourceName = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_SourceName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_Time Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_Time = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_Time, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_ReceiveTime Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_ReceiveTime = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_ReceiveTime, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_Message Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_Message = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_Message, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_Severity Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_Severity = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_Severity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_ConditionClassId Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_ConditionClassId = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_ConditionClassId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_ConditionClassName Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_ConditionClassName = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_ConditionClassName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_ConditionName Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_ConditionName = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_ConditionName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_BranchId Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_BranchId = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_BranchId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_Retain Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_Retain = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_Retain, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_EnabledState Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_EnabledState = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_EnabledState, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_EnabledState_Id Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_EnabledState_Id = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_EnabledState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_Quality Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_Quality = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_Quality, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_Quality_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_Quality_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_Quality_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_LastSeverity Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_LastSeverity = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_LastSeverity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_LastSeverity_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_LastSeverity_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_Comment Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_Comment = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_Comment, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_Comment_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_Comment_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_Comment_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_ClientUserId Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_ClientUserId = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_ClientUserId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_AddComment_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_AddComment_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_AddComment_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_AckedState Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_AckedState = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_AckedState, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_AckedState_Id Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_AckedState_Id = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_AckedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_ConfirmedState_Id Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_ConfirmedState_Id = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_ConfirmedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_Acknowledge_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_Acknowledge_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_Acknowledge_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_CycleComplete_Confirm_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_Array_CycleComplete_Confirm_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_Array_CycleComplete_Confirm_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_BooleanValue Variable. /// public static readonly ExpandedNodeId Data_Static_Array_BooleanValue = new ExpandedNodeId(TestData.Variables.Data_Static_Array_BooleanValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_SByteValue Variable. /// public static readonly ExpandedNodeId Data_Static_Array_SByteValue = new ExpandedNodeId(TestData.Variables.Data_Static_Array_SByteValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_ByteValue Variable. /// public static readonly ExpandedNodeId Data_Static_Array_ByteValue = new ExpandedNodeId(TestData.Variables.Data_Static_Array_ByteValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_Int16Value Variable. /// public static readonly ExpandedNodeId Data_Static_Array_Int16Value = new ExpandedNodeId(TestData.Variables.Data_Static_Array_Int16Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_UInt16Value Variable. /// public static readonly ExpandedNodeId Data_Static_Array_UInt16Value = new ExpandedNodeId(TestData.Variables.Data_Static_Array_UInt16Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_Int32Value Variable. /// public static readonly ExpandedNodeId Data_Static_Array_Int32Value = new ExpandedNodeId(TestData.Variables.Data_Static_Array_Int32Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_UInt32Value Variable. /// public static readonly ExpandedNodeId Data_Static_Array_UInt32Value = new ExpandedNodeId(TestData.Variables.Data_Static_Array_UInt32Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_Int64Value Variable. /// public static readonly ExpandedNodeId Data_Static_Array_Int64Value = new ExpandedNodeId(TestData.Variables.Data_Static_Array_Int64Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_UInt64Value Variable. /// public static readonly ExpandedNodeId Data_Static_Array_UInt64Value = new ExpandedNodeId(TestData.Variables.Data_Static_Array_UInt64Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_FloatValue Variable. /// public static readonly ExpandedNodeId Data_Static_Array_FloatValue = new ExpandedNodeId(TestData.Variables.Data_Static_Array_FloatValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_DoubleValue Variable. /// public static readonly ExpandedNodeId Data_Static_Array_DoubleValue = new ExpandedNodeId(TestData.Variables.Data_Static_Array_DoubleValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_StringValue Variable. /// public static readonly ExpandedNodeId Data_Static_Array_StringValue = new ExpandedNodeId(TestData.Variables.Data_Static_Array_StringValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_DateTimeValue Variable. /// public static readonly ExpandedNodeId Data_Static_Array_DateTimeValue = new ExpandedNodeId(TestData.Variables.Data_Static_Array_DateTimeValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_GuidValue Variable. /// public static readonly ExpandedNodeId Data_Static_Array_GuidValue = new ExpandedNodeId(TestData.Variables.Data_Static_Array_GuidValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_ByteStringValue Variable. /// public static readonly ExpandedNodeId Data_Static_Array_ByteStringValue = new ExpandedNodeId(TestData.Variables.Data_Static_Array_ByteStringValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_XmlElementValue Variable. /// public static readonly ExpandedNodeId Data_Static_Array_XmlElementValue = new ExpandedNodeId(TestData.Variables.Data_Static_Array_XmlElementValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_NodeIdValue Variable. /// public static readonly ExpandedNodeId Data_Static_Array_NodeIdValue = new ExpandedNodeId(TestData.Variables.Data_Static_Array_NodeIdValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_ExpandedNodeIdValue Variable. /// public static readonly ExpandedNodeId Data_Static_Array_ExpandedNodeIdValue = new ExpandedNodeId(TestData.Variables.Data_Static_Array_ExpandedNodeIdValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_QualifiedNameValue Variable. /// public static readonly ExpandedNodeId Data_Static_Array_QualifiedNameValue = new ExpandedNodeId(TestData.Variables.Data_Static_Array_QualifiedNameValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_LocalizedTextValue Variable. /// public static readonly ExpandedNodeId Data_Static_Array_LocalizedTextValue = new ExpandedNodeId(TestData.Variables.Data_Static_Array_LocalizedTextValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_StatusCodeValue Variable. /// public static readonly ExpandedNodeId Data_Static_Array_StatusCodeValue = new ExpandedNodeId(TestData.Variables.Data_Static_Array_StatusCodeValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_VariantValue Variable. /// public static readonly ExpandedNodeId Data_Static_Array_VariantValue = new ExpandedNodeId(TestData.Variables.Data_Static_Array_VariantValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_EnumerationValue Variable. /// public static readonly ExpandedNodeId Data_Static_Array_EnumerationValue = new ExpandedNodeId(TestData.Variables.Data_Static_Array_EnumerationValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_StructureValue Variable. /// public static readonly ExpandedNodeId Data_Static_Array_StructureValue = new ExpandedNodeId(TestData.Variables.Data_Static_Array_StructureValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_NumberValue Variable. /// public static readonly ExpandedNodeId Data_Static_Array_NumberValue = new ExpandedNodeId(TestData.Variables.Data_Static_Array_NumberValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_IntegerValue Variable. /// public static readonly ExpandedNodeId Data_Static_Array_IntegerValue = new ExpandedNodeId(TestData.Variables.Data_Static_Array_IntegerValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_Array_UIntegerValue Variable. /// public static readonly ExpandedNodeId Data_Static_Array_UIntegerValue = new ExpandedNodeId(TestData.Variables.Data_Static_Array_UIntegerValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_SimulationActive Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_SimulationActive = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_SimulationActive, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_GenerateValues_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_GenerateValues_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_GenerateValues_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_EventId Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_EventId = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_EventId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_EventType Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_EventType = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_EventType, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_SourceNode Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_SourceNode = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_SourceNode, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_SourceName Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_SourceName = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_SourceName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Time Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_Time = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_Time, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_ReceiveTime Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_ReceiveTime = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_ReceiveTime, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Message Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_Message = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_Message, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Severity Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_Severity = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_Severity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_ConditionClassId Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_ConditionClassId = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_ConditionClassId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_ConditionClassName Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_ConditionClassName = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_ConditionClassName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_ConditionName Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_ConditionName = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_ConditionName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_BranchId Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_BranchId = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_BranchId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Retain Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_Retain = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_Retain, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_EnabledState Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_EnabledState = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_EnabledState, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_EnabledState_Id Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_EnabledState_Id = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_EnabledState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Quality Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_Quality = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_Quality, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Quality_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_Quality_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_Quality_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_LastSeverity Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_LastSeverity = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_LastSeverity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_LastSeverity_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_LastSeverity_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Comment Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_Comment = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_Comment, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Comment_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_Comment_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_Comment_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_ClientUserId Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_ClientUserId = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_ClientUserId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_AddComment_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_AddComment_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_AddComment_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_AckedState Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_AckedState = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_AckedState, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_AckedState_Id Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_AckedState_Id = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_AckedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_ConfirmedState_Id Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_ConfirmedState_Id = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_ConfirmedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Acknowledge_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_Acknowledge_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_Acknowledge_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_CycleComplete_Confirm_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_CycleComplete_Confirm_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_CycleComplete_Confirm_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_BooleanValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_BooleanValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_BooleanValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_SByteValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_SByteValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_SByteValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_ByteValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_ByteValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_ByteValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_Int16Value Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_Int16Value = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_Int16Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_UInt16Value Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_UInt16Value = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_UInt16Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_Int32Value Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_Int32Value = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_Int32Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_UInt32Value Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_UInt32Value = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_UInt32Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_Int64Value Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_Int64Value = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_Int64Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_UInt64Value Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_UInt64Value = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_UInt64Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_FloatValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_FloatValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_FloatValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_DoubleValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_DoubleValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_DoubleValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_StringValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_StringValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_StringValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_DateTimeValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_DateTimeValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_DateTimeValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_GuidValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_GuidValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_GuidValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_ByteStringValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_ByteStringValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_ByteStringValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_XmlElementValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_XmlElementValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_XmlElementValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_NodeIdValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_NodeIdValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_NodeIdValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_ExpandedNodeIdValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_ExpandedNodeIdValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_ExpandedNodeIdValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_QualifiedNameValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_QualifiedNameValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_QualifiedNameValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_LocalizedTextValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_LocalizedTextValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_LocalizedTextValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_StatusCodeValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_StatusCodeValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_StatusCodeValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserScalar_VariantValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserScalar_VariantValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserScalar_VariantValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_SimulationActive Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_SimulationActive = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_SimulationActive, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_GenerateValues_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_GenerateValues_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_GenerateValues_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_EventId Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_EventId = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_EventId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_EventType Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_EventType = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_EventType, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_SourceNode Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_SourceNode = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_SourceNode, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_SourceName Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_SourceName = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_SourceName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_Time Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_Time = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_Time, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_ReceiveTime Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_ReceiveTime = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_ReceiveTime, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_Message Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_Message = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_Message, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_Severity Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_Severity = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_Severity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_ConditionClassId Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_ConditionClassId = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_ConditionClassId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_ConditionClassName Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_ConditionClassName = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_ConditionClassName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_ConditionName Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_ConditionName = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_ConditionName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_BranchId Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_BranchId = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_BranchId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_Retain Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_Retain = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_Retain, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_EnabledState Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_EnabledState = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_EnabledState, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_EnabledState_Id Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_EnabledState_Id = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_EnabledState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_Quality Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_Quality = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_Quality, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_Quality_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_Quality_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_Quality_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_LastSeverity Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_LastSeverity = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_LastSeverity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_LastSeverity_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_LastSeverity_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_Comment Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_Comment = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_Comment, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_Comment_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_Comment_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_Comment_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_ClientUserId Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_ClientUserId = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_ClientUserId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_AddComment_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_AddComment_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_AddComment_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_AckedState Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_AckedState = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_AckedState, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_AckedState_Id Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_AckedState_Id = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_AckedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_ConfirmedState_Id Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_ConfirmedState_Id = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_ConfirmedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_Acknowledge_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_Acknowledge_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_Acknowledge_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_CycleComplete_Confirm_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_CycleComplete_Confirm_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_CycleComplete_Confirm_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_BooleanValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_BooleanValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_BooleanValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_SByteValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_SByteValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_SByteValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_ByteValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_ByteValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_ByteValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_Int16Value Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_Int16Value = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_Int16Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_UInt16Value Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_UInt16Value = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_UInt16Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_Int32Value Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_Int32Value = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_Int32Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_UInt32Value Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_UInt32Value = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_UInt32Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_Int64Value Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_Int64Value = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_Int64Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_UInt64Value Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_UInt64Value = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_UInt64Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_FloatValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_FloatValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_FloatValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_DoubleValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_DoubleValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_DoubleValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_StringValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_StringValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_StringValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_DateTimeValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_DateTimeValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_DateTimeValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_GuidValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_GuidValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_GuidValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_ByteStringValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_ByteStringValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_ByteStringValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_XmlElementValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_XmlElementValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_XmlElementValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_NodeIdValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_NodeIdValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_NodeIdValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_ExpandedNodeIdValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_ExpandedNodeIdValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_ExpandedNodeIdValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_QualifiedNameValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_QualifiedNameValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_QualifiedNameValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_LocalizedTextValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_LocalizedTextValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_LocalizedTextValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_StatusCodeValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_StatusCodeValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_StatusCodeValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_UserArray_VariantValue Variable. /// public static readonly ExpandedNodeId Data_Static_UserArray_VariantValue = new ExpandedNodeId(TestData.Variables.Data_Static_UserArray_VariantValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_SimulationActive Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_SimulationActive = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_SimulationActive, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_GenerateValues_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_GenerateValues_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_GenerateValues_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_EventId Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_EventId = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_EventId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_EventType Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_EventType = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_EventType, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_SourceNode Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_SourceNode = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_SourceNode, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_SourceName Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_SourceName = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_SourceName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Time Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_Time = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_Time, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_ReceiveTime Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_ReceiveTime = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_ReceiveTime, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Message Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_Message = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_Message, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Severity Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_Severity = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_Severity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_ConditionClassId Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_ConditionClassId = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_ConditionClassId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_ConditionClassName Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_ConditionClassName = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_ConditionClassName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_ConditionName Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_ConditionName = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_ConditionName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_BranchId Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_BranchId = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_BranchId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Retain Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_Retain = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_Retain, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_EnabledState Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_EnabledState = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_EnabledState, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_EnabledState_Id Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_EnabledState_Id = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_EnabledState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Quality Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_Quality = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_Quality, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Quality_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_Quality_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_Quality_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_LastSeverity Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_LastSeverity = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_LastSeverity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_LastSeverity_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_LastSeverity_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Comment Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_Comment = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_Comment, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Comment_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_Comment_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_Comment_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_ClientUserId Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_ClientUserId = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_ClientUserId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_AddComment_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_AddComment_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_AddComment_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_AckedState Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_AckedState = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_AckedState, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_AckedState_Id Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_AckedState_Id = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_AckedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_ConfirmedState_Id Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_ConfirmedState_Id = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_ConfirmedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Acknowledge_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_Acknowledge_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_Acknowledge_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_CycleComplete_Confirm_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_CycleComplete_Confirm_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_CycleComplete_Confirm_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_SByteValue Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_SByteValue = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_SByteValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_SByteValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_SByteValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_SByteValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_ByteValue Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_ByteValue = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_ByteValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_ByteValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_ByteValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_ByteValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_Int16Value Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_Int16Value = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_Int16Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_Int16Value_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_Int16Value_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_Int16Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_UInt16Value Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_UInt16Value = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_UInt16Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_UInt16Value_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_UInt16Value_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_UInt16Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_Int32Value Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_Int32Value = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_Int32Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_Int32Value_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_Int32Value_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_Int32Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_UInt32Value Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_UInt32Value = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_UInt32Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_UInt32Value_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_UInt32Value_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_UInt32Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_Int64Value Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_Int64Value = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_Int64Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_Int64Value_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_Int64Value_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_Int64Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_UInt64Value Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_UInt64Value = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_UInt64Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_UInt64Value_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_UInt64Value_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_UInt64Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_FloatValue Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_FloatValue = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_FloatValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_FloatValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_FloatValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_FloatValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_DoubleValue Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_DoubleValue = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_DoubleValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_DoubleValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_DoubleValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_DoubleValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_NumberValue Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_NumberValue = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_NumberValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_NumberValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_NumberValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_NumberValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_IntegerValue Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_IntegerValue = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_IntegerValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_IntegerValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_IntegerValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_IntegerValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_UIntegerValue Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_UIntegerValue = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_UIntegerValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogScalar_UIntegerValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogScalar_UIntegerValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogScalar_UIntegerValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_SimulationActive Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_SimulationActive = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_SimulationActive, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_GenerateValues_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_GenerateValues_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_GenerateValues_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_EventId Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_EventId = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_EventId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_EventType Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_EventType = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_EventType, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_SourceNode Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_SourceNode = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_SourceNode, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_SourceName Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_SourceName = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_SourceName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Time Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_Time = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_Time, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_ReceiveTime Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_ReceiveTime = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_ReceiveTime, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Message Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_Message = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_Message, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Severity Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_Severity = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_Severity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_ConditionClassId Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_ConditionClassId = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_ConditionClassId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_ConditionClassName Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_ConditionClassName = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_ConditionClassName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_ConditionName Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_ConditionName = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_ConditionName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_BranchId Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_BranchId = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_BranchId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Retain Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_Retain = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_Retain, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_EnabledState Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_EnabledState = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_EnabledState, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_EnabledState_Id Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_EnabledState_Id = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_EnabledState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Quality Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_Quality = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_Quality, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Quality_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_Quality_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_Quality_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_LastSeverity Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_LastSeverity = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_LastSeverity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_LastSeverity_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_LastSeverity_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Comment Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_Comment = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_Comment, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Comment_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_Comment_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_Comment_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_ClientUserId Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_ClientUserId = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_ClientUserId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_AddComment_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_AddComment_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_AddComment_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_AckedState Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_AckedState = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_AckedState, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_AckedState_Id Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_AckedState_Id = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_AckedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_ConfirmedState_Id Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_ConfirmedState_Id = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_ConfirmedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Acknowledge_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_Acknowledge_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_Acknowledge_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_CycleComplete_Confirm_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_CycleComplete_Confirm_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_CycleComplete_Confirm_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_SByteValue Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_SByteValue = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_SByteValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_SByteValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_SByteValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_SByteValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_ByteValue Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_ByteValue = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_ByteValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_ByteValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_ByteValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_ByteValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_Int16Value Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_Int16Value = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_Int16Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_Int16Value_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_Int16Value_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_Int16Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_UInt16Value Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_UInt16Value = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_UInt16Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_UInt16Value_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_UInt16Value_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_UInt16Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_Int32Value Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_Int32Value = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_Int32Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_Int32Value_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_Int32Value_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_Int32Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_UInt32Value Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_UInt32Value = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_UInt32Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_UInt32Value_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_UInt32Value_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_UInt32Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_Int64Value Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_Int64Value = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_Int64Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_Int64Value_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_Int64Value_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_Int64Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_UInt64Value Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_UInt64Value = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_UInt64Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_UInt64Value_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_UInt64Value_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_UInt64Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_FloatValue Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_FloatValue = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_FloatValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_FloatValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_FloatValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_FloatValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_DoubleValue Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_DoubleValue = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_DoubleValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_DoubleValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_DoubleValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_DoubleValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_NumberValue Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_NumberValue = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_NumberValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_NumberValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_NumberValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_NumberValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_IntegerValue Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_IntegerValue = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_IntegerValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_IntegerValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_IntegerValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_IntegerValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_UIntegerValue Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_UIntegerValue = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_UIntegerValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_AnalogArray_UIntegerValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Static_AnalogArray_UIntegerValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Static_AnalogArray_UIntegerValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_ScalarMethod1_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_MethodTest_ScalarMethod1_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_MethodTest_ScalarMethod1_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_ScalarMethod1_OutputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_MethodTest_ScalarMethod1_OutputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_MethodTest_ScalarMethod1_OutputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_ScalarMethod2_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_MethodTest_ScalarMethod2_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_MethodTest_ScalarMethod2_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_ScalarMethod2_OutputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_MethodTest_ScalarMethod2_OutputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_MethodTest_ScalarMethod2_OutputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_ScalarMethod3_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_MethodTest_ScalarMethod3_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_MethodTest_ScalarMethod3_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_ScalarMethod3_OutputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_MethodTest_ScalarMethod3_OutputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_MethodTest_ScalarMethod3_OutputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_ArrayMethod1_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_MethodTest_ArrayMethod1_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_MethodTest_ArrayMethod1_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_ArrayMethod1_OutputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_MethodTest_ArrayMethod1_OutputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_MethodTest_ArrayMethod1_OutputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_ArrayMethod2_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_MethodTest_ArrayMethod2_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_MethodTest_ArrayMethod2_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_ArrayMethod2_OutputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_MethodTest_ArrayMethod2_OutputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_MethodTest_ArrayMethod2_OutputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_ArrayMethod3_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_MethodTest_ArrayMethod3_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_MethodTest_ArrayMethod3_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_ArrayMethod3_OutputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_MethodTest_ArrayMethod3_OutputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_MethodTest_ArrayMethod3_OutputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_UserScalarMethod1_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_MethodTest_UserScalarMethod1_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_MethodTest_UserScalarMethod1_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_UserScalarMethod1_OutputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_MethodTest_UserScalarMethod1_OutputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_MethodTest_UserScalarMethod1_OutputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_UserScalarMethod2_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_MethodTest_UserScalarMethod2_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_MethodTest_UserScalarMethod2_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_UserScalarMethod2_OutputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_MethodTest_UserScalarMethod2_OutputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_MethodTest_UserScalarMethod2_OutputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_UserArrayMethod1_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_MethodTest_UserArrayMethod1_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_MethodTest_UserArrayMethod1_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_UserArrayMethod1_OutputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_MethodTest_UserArrayMethod1_OutputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_MethodTest_UserArrayMethod1_OutputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_UserArrayMethod2_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_MethodTest_UserArrayMethod2_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_MethodTest_UserArrayMethod2_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Static_MethodTest_UserArrayMethod2_OutputArguments Variable. /// public static readonly ExpandedNodeId Data_Static_MethodTest_UserArrayMethod2_OutputArguments = new ExpandedNodeId(TestData.Variables.Data_Static_MethodTest_UserArrayMethod2_OutputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_SimulationActive Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_SimulationActive = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_SimulationActive, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_GenerateValues_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_GenerateValues_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_GenerateValues_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_EventId Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_EventId = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_EventId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_EventType Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_EventType = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_EventType, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_SourceNode Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_SourceNode = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_SourceNode, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_SourceName Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_SourceName = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_SourceName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Time Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_Time = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_Time, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_ReceiveTime Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_ReceiveTime = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_ReceiveTime, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Message Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_Message = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_Message, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Severity Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_Severity = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_Severity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_ConditionClassId Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_ConditionClassId = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_ConditionClassId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_ConditionClassName Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_ConditionClassName = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_ConditionClassName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_ConditionName Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_ConditionName = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_ConditionName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_BranchId Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_BranchId = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_BranchId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Retain Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_Retain = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_Retain, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_EnabledState Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_EnabledState = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_EnabledState, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_EnabledState_Id Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_EnabledState_Id = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_EnabledState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Quality Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_Quality = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_Quality, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Quality_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_Quality_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_Quality_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_LastSeverity Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_LastSeverity = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_LastSeverity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_LastSeverity_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_LastSeverity_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Comment Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_Comment = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_Comment, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Comment_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_Comment_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_Comment_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_ClientUserId Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_ClientUserId = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_ClientUserId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_AddComment_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_AddComment_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_AddComment_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_AckedState Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_AckedState = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_AckedState, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_AckedState_Id Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_AckedState_Id = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_AckedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_ConfirmedState_Id Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_ConfirmedState_Id = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_ConfirmedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Acknowledge_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_Acknowledge_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_Acknowledge_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_CycleComplete_Confirm_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_CycleComplete_Confirm_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_CycleComplete_Confirm_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_BooleanValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_BooleanValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_BooleanValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_SByteValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_SByteValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_SByteValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_ByteValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_ByteValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_ByteValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_Int16Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_Int16Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_Int16Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_UInt16Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_UInt16Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_UInt16Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_Int32Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_Int32Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_Int32Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_UInt32Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_UInt32Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_UInt32Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_Int64Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_Int64Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_Int64Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_UInt64Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_UInt64Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_UInt64Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_FloatValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_FloatValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_FloatValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_DoubleValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_DoubleValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_DoubleValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_StringValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_StringValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_StringValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_DateTimeValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_DateTimeValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_DateTimeValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_GuidValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_GuidValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_GuidValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_ByteStringValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_ByteStringValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_ByteStringValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_XmlElementValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_XmlElementValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_XmlElementValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_NodeIdValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_NodeIdValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_NodeIdValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_ExpandedNodeIdValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_ExpandedNodeIdValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_ExpandedNodeIdValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_QualifiedNameValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_QualifiedNameValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_QualifiedNameValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_LocalizedTextValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_LocalizedTextValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_LocalizedTextValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_StatusCodeValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_StatusCodeValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_StatusCodeValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_VariantValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_VariantValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_VariantValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_EnumerationValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_EnumerationValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_EnumerationValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_StructureValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_StructureValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_StructureValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_NumberValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_NumberValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_NumberValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_IntegerValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_IntegerValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_IntegerValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Scalar_UIntegerValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Scalar_UIntegerValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Scalar_UIntegerValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_SimulationActive Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_SimulationActive = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_SimulationActive, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_GenerateValues_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_GenerateValues_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_GenerateValues_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_EventId Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_EventId = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_EventId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_EventType Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_EventType = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_EventType, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_SourceNode Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_SourceNode = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_SourceNode, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_SourceName Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_SourceName = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_SourceName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Time Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_Time = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_Time, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_ReceiveTime Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_ReceiveTime = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_ReceiveTime, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Message Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_Message = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_Message, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Severity Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_Severity = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_Severity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_ConditionClassId Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_ConditionClassId = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_ConditionClassId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_ConditionClassName Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_ConditionClassName = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_ConditionClassName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_ConditionName Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_ConditionName = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_ConditionName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_BranchId Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_BranchId = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_BranchId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Retain Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_Retain = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_Retain, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_EnabledState Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_EnabledState = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_EnabledState, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_EnabledState_Id Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_EnabledState_Id = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_EnabledState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Quality Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_Quality = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_Quality, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Quality_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_Quality_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_Quality_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_LastSeverity Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_LastSeverity = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_LastSeverity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_LastSeverity_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_LastSeverity_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Comment Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_Comment = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_Comment, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Comment_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_Comment_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_Comment_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_ClientUserId Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_ClientUserId = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_ClientUserId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_AddComment_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_AddComment_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_AddComment_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_AckedState Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_AckedState = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_AckedState, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_AckedState_Id Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_AckedState_Id = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_AckedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_ConfirmedState_Id Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_ConfirmedState_Id = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_ConfirmedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Acknowledge_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_Acknowledge_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_Acknowledge_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_CycleComplete_Confirm_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_CycleComplete_Confirm_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_CycleComplete_Confirm_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_BooleanValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_BooleanValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_BooleanValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_SByteValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_SByteValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_SByteValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_ByteValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_ByteValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_ByteValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_Int16Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_Int16Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_Int16Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_UInt16Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_UInt16Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_UInt16Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_Int32Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_Int32Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_Int32Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_UInt32Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_UInt32Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_UInt32Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_Int64Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_Int64Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_Int64Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_UInt64Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_UInt64Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_UInt64Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_FloatValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_FloatValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_FloatValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_DoubleValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_DoubleValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_DoubleValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_StringValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_StringValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_StringValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_DateTimeValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_DateTimeValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_DateTimeValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_GuidValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_GuidValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_GuidValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_ByteStringValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_ByteStringValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_ByteStringValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_XmlElementValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_XmlElementValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_XmlElementValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_NodeIdValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_NodeIdValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_NodeIdValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_ExpandedNodeIdValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_ExpandedNodeIdValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_ExpandedNodeIdValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_QualifiedNameValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_QualifiedNameValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_QualifiedNameValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_LocalizedTextValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_LocalizedTextValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_LocalizedTextValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_StatusCodeValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_StatusCodeValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_StatusCodeValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_VariantValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_VariantValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_VariantValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_EnumerationValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_EnumerationValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_EnumerationValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_StructureValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_StructureValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_StructureValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_NumberValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_NumberValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_NumberValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_IntegerValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_IntegerValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_IntegerValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_Array_UIntegerValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_Array_UIntegerValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_Array_UIntegerValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_SimulationActive Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_SimulationActive = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_SimulationActive, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_GenerateValues_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_GenerateValues_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_GenerateValues_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_EventId Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_EventId = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_EventId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_EventType Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_EventType = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_EventType, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_SourceNode Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_SourceNode = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_SourceNode, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_SourceName Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_SourceName = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_SourceName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Time Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_Time = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_Time, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_ReceiveTime Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_ReceiveTime = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_ReceiveTime, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Message Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_Message = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_Message, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Severity Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_Severity = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_Severity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_ConditionClassId Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_ConditionClassId = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_ConditionClassId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_ConditionClassName Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_ConditionClassName = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_ConditionClassName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_ConditionName Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_ConditionName = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_ConditionName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_BranchId Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_BranchId = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_BranchId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Retain Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_Retain = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_Retain, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_EnabledState Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_EnabledState = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_EnabledState, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_EnabledState_Id Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_EnabledState_Id = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_EnabledState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Quality Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_Quality = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_Quality, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Quality_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_Quality_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_Quality_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_LastSeverity Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_LastSeverity = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_LastSeverity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_LastSeverity_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_LastSeverity_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Comment Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_Comment = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_Comment, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Comment_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_Comment_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_Comment_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_ClientUserId Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_ClientUserId = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_ClientUserId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_AddComment_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_AddComment_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_AddComment_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_AckedState Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_AckedState = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_AckedState, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_AckedState_Id Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_AckedState_Id = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_AckedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_ConfirmedState_Id Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_ConfirmedState_Id = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_ConfirmedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Acknowledge_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_Acknowledge_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_Acknowledge_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_CycleComplete_Confirm_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_CycleComplete_Confirm_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_CycleComplete_Confirm_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_BooleanValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_BooleanValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_BooleanValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_SByteValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_SByteValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_SByteValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_ByteValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_ByteValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_ByteValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_Int16Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_Int16Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_Int16Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_UInt16Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_UInt16Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_UInt16Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_Int32Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_Int32Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_Int32Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_UInt32Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_UInt32Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_UInt32Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_Int64Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_Int64Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_Int64Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_UInt64Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_UInt64Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_UInt64Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_FloatValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_FloatValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_FloatValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_DoubleValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_DoubleValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_DoubleValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_StringValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_StringValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_StringValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_DateTimeValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_DateTimeValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_DateTimeValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_GuidValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_GuidValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_GuidValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_ByteStringValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_ByteStringValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_ByteStringValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_XmlElementValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_XmlElementValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_XmlElementValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_NodeIdValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_NodeIdValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_NodeIdValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_ExpandedNodeIdValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_ExpandedNodeIdValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_ExpandedNodeIdValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_QualifiedNameValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_QualifiedNameValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_QualifiedNameValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_LocalizedTextValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_LocalizedTextValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_LocalizedTextValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_StatusCodeValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_StatusCodeValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_StatusCodeValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserScalar_VariantValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserScalar_VariantValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserScalar_VariantValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_SimulationActive Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_SimulationActive = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_SimulationActive, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_GenerateValues_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_GenerateValues_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_GenerateValues_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_EventId Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_EventId = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_EventId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_EventType Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_EventType = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_EventType, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_SourceNode Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_SourceNode = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_SourceNode, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_SourceName Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_SourceName = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_SourceName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Time Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_Time = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_Time, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_ReceiveTime Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_ReceiveTime = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_ReceiveTime, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Message Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_Message = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_Message, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Severity Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_Severity = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_Severity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_ConditionClassId Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_ConditionClassId = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_ConditionClassId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_ConditionClassName Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_ConditionClassName = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_ConditionClassName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_ConditionName Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_ConditionName = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_ConditionName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_BranchId Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_BranchId = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_BranchId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Retain Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_Retain = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_Retain, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_EnabledState Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_EnabledState = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_EnabledState, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_EnabledState_Id Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_EnabledState_Id = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_EnabledState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Quality Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_Quality = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_Quality, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Quality_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_Quality_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_Quality_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_LastSeverity Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_LastSeverity = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_LastSeverity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_LastSeverity_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_LastSeverity_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Comment Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_Comment = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_Comment, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Comment_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_Comment_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_Comment_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_ClientUserId Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_ClientUserId = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_ClientUserId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_AddComment_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_AddComment_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_AddComment_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_AckedState Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_AckedState = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_AckedState, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_AckedState_Id Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_AckedState_Id = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_AckedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_ConfirmedState_Id Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_ConfirmedState_Id = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_ConfirmedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Acknowledge_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_Acknowledge_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_Acknowledge_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_CycleComplete_Confirm_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_CycleComplete_Confirm_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_CycleComplete_Confirm_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_BooleanValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_BooleanValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_BooleanValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_SByteValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_SByteValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_SByteValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_ByteValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_ByteValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_ByteValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_Int16Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_Int16Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_Int16Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_UInt16Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_UInt16Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_UInt16Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_Int32Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_Int32Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_Int32Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_UInt32Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_UInt32Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_UInt32Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_Int64Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_Int64Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_Int64Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_UInt64Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_UInt64Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_UInt64Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_FloatValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_FloatValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_FloatValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_DoubleValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_DoubleValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_DoubleValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_StringValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_StringValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_StringValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_DateTimeValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_DateTimeValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_DateTimeValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_GuidValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_GuidValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_GuidValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_ByteStringValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_ByteStringValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_ByteStringValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_XmlElementValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_XmlElementValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_XmlElementValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_NodeIdValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_NodeIdValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_NodeIdValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_ExpandedNodeIdValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_ExpandedNodeIdValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_ExpandedNodeIdValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_QualifiedNameValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_QualifiedNameValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_QualifiedNameValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_LocalizedTextValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_LocalizedTextValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_LocalizedTextValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_StatusCodeValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_StatusCodeValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_StatusCodeValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_UserArray_VariantValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_UserArray_VariantValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_UserArray_VariantValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_SimulationActive Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_SimulationActive = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_SimulationActive, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_GenerateValues_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_GenerateValues_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_GenerateValues_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_EventId Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_EventId = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_EventId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_EventType Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_EventType = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_EventType, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_SourceNode Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_SourceNode = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_SourceNode, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_SourceName Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_SourceName = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_SourceName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Time Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_Time = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_Time, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_ReceiveTime Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_ReceiveTime = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_ReceiveTime, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Message Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_Message = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_Message, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Severity Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_Severity = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_Severity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_ConditionClassId Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_ConditionClassId = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_ConditionClassId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_ConditionClassName Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_ConditionClassName = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_ConditionClassName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_ConditionName Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_ConditionName = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_ConditionName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_BranchId Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_BranchId = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_BranchId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Retain Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_Retain = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_Retain, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_EnabledState Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_EnabledState = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_EnabledState, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_EnabledState_Id Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_EnabledState_Id = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_EnabledState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Quality Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_Quality = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_Quality, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Quality_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_Quality_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_Quality_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_LastSeverity Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_LastSeverity = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_LastSeverity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_LastSeverity_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_LastSeverity_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Comment Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_Comment = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_Comment, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Comment_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_Comment_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_Comment_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_ClientUserId Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_ClientUserId = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_ClientUserId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_AddComment_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_AddComment_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_AddComment_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_AckedState Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_AckedState = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_AckedState, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_AckedState_Id Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_AckedState_Id = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_AckedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_ConfirmedState_Id Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_ConfirmedState_Id = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_ConfirmedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Acknowledge_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_Acknowledge_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_Acknowledge_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_CycleComplete_Confirm_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_CycleComplete_Confirm_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_CycleComplete_Confirm_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_SByteValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_SByteValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_SByteValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_SByteValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_SByteValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_SByteValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_ByteValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_ByteValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_ByteValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_ByteValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_ByteValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_ByteValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_Int16Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_Int16Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_Int16Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_Int16Value_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_Int16Value_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_Int16Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_UInt16Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_UInt16Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_UInt16Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_UInt16Value_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_UInt16Value_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_UInt16Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_Int32Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_Int32Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_Int32Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_Int32Value_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_Int32Value_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_Int32Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_UInt32Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_UInt32Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_UInt32Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_UInt32Value_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_UInt32Value_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_UInt32Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_Int64Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_Int64Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_Int64Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_Int64Value_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_Int64Value_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_Int64Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_UInt64Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_UInt64Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_UInt64Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_UInt64Value_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_UInt64Value_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_UInt64Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_FloatValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_FloatValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_FloatValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_FloatValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_FloatValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_FloatValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_DoubleValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_DoubleValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_DoubleValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_DoubleValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_DoubleValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_DoubleValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_NumberValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_NumberValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_NumberValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_NumberValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_NumberValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_NumberValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_IntegerValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_IntegerValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_IntegerValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_IntegerValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_IntegerValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_IntegerValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_UIntegerValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_UIntegerValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_UIntegerValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogScalar_UIntegerValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogScalar_UIntegerValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogScalar_UIntegerValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_SimulationActive Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_SimulationActive = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_SimulationActive, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_GenerateValues_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_GenerateValues_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_GenerateValues_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_EventId Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_EventId = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_EventId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_EventType Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_EventType = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_EventType, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_SourceNode Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_SourceNode = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_SourceNode, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_SourceName Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_SourceName = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_SourceName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Time Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_Time = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_Time, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_ReceiveTime Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_ReceiveTime = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_ReceiveTime, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Message Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_Message = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_Message, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Severity Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_Severity = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_Severity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_ConditionClassId Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_ConditionClassId = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_ConditionClassId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_ConditionClassName Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_ConditionClassName = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_ConditionClassName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_ConditionName Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_ConditionName = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_ConditionName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_BranchId Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_BranchId = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_BranchId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Retain Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_Retain = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_Retain, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_EnabledState Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_EnabledState = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_EnabledState, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_EnabledState_Id Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_EnabledState_Id = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_EnabledState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Quality Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_Quality = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_Quality, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Quality_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_Quality_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_Quality_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_LastSeverity Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_LastSeverity = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_LastSeverity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_LastSeverity_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_LastSeverity_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_LastSeverity_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Comment Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_Comment = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_Comment, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Comment_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_Comment_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_Comment_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_ClientUserId Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_ClientUserId = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_ClientUserId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_AddComment_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_AddComment_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_AddComment_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_AckedState Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_AckedState = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_AckedState, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_AckedState_Id Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_AckedState_Id = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_AckedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_ConfirmedState_Id Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_ConfirmedState_Id = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_ConfirmedState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Acknowledge_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_Acknowledge_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_Acknowledge_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_CycleComplete_Confirm_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_CycleComplete_Confirm_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_CycleComplete_Confirm_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_SByteValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_SByteValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_SByteValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_SByteValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_SByteValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_SByteValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_ByteValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_ByteValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_ByteValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_ByteValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_ByteValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_ByteValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_Int16Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_Int16Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_Int16Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_Int16Value_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_Int16Value_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_Int16Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_UInt16Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_UInt16Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_UInt16Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_UInt16Value_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_UInt16Value_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_UInt16Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_Int32Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_Int32Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_Int32Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_Int32Value_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_Int32Value_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_Int32Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_UInt32Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_UInt32Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_UInt32Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_UInt32Value_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_UInt32Value_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_UInt32Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_Int64Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_Int64Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_Int64Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_Int64Value_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_Int64Value_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_Int64Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_UInt64Value Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_UInt64Value = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_UInt64Value, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_UInt64Value_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_UInt64Value_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_UInt64Value_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_FloatValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_FloatValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_FloatValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_FloatValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_FloatValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_FloatValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_DoubleValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_DoubleValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_DoubleValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_DoubleValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_DoubleValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_DoubleValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_NumberValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_NumberValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_NumberValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_NumberValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_NumberValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_NumberValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_IntegerValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_IntegerValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_IntegerValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_IntegerValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_IntegerValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_IntegerValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_UIntegerValue Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_UIntegerValue = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_UIntegerValue, TestData.Namespaces.TestData); /// /// The identifier for the Data_Dynamic_AnalogArray_UIntegerValue_EURange Variable. /// public static readonly ExpandedNodeId Data_Dynamic_AnalogArray_UIntegerValue_EURange = new ExpandedNodeId(TestData.Variables.Data_Dynamic_AnalogArray_UIntegerValue_EURange, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_EventId Variable. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_EventId = new ExpandedNodeId(TestData.Variables.Data_Conditions_SystemStatus_EventId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_EventType Variable. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_EventType = new ExpandedNodeId(TestData.Variables.Data_Conditions_SystemStatus_EventType, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_SourceNode Variable. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_SourceNode = new ExpandedNodeId(TestData.Variables.Data_Conditions_SystemStatus_SourceNode, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_SourceName Variable. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_SourceName = new ExpandedNodeId(TestData.Variables.Data_Conditions_SystemStatus_SourceName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_Time Variable. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_Time = new ExpandedNodeId(TestData.Variables.Data_Conditions_SystemStatus_Time, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_ReceiveTime Variable. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_ReceiveTime = new ExpandedNodeId(TestData.Variables.Data_Conditions_SystemStatus_ReceiveTime, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_Message Variable. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_Message = new ExpandedNodeId(TestData.Variables.Data_Conditions_SystemStatus_Message, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_Severity Variable. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_Severity = new ExpandedNodeId(TestData.Variables.Data_Conditions_SystemStatus_Severity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_ConditionClassId Variable. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_ConditionClassId = new ExpandedNodeId(TestData.Variables.Data_Conditions_SystemStatus_ConditionClassId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_ConditionClassName Variable. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_ConditionClassName = new ExpandedNodeId(TestData.Variables.Data_Conditions_SystemStatus_ConditionClassName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_ConditionName Variable. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_ConditionName = new ExpandedNodeId(TestData.Variables.Data_Conditions_SystemStatus_ConditionName, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_BranchId Variable. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_BranchId = new ExpandedNodeId(TestData.Variables.Data_Conditions_SystemStatus_BranchId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_Retain Variable. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_Retain = new ExpandedNodeId(TestData.Variables.Data_Conditions_SystemStatus_Retain, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_EnabledState Variable. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_EnabledState = new ExpandedNodeId(TestData.Variables.Data_Conditions_SystemStatus_EnabledState, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_EnabledState_Id Variable. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_EnabledState_Id = new ExpandedNodeId(TestData.Variables.Data_Conditions_SystemStatus_EnabledState_Id, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_Quality Variable. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_Quality = new ExpandedNodeId(TestData.Variables.Data_Conditions_SystemStatus_Quality, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_Quality_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_Quality_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Conditions_SystemStatus_Quality_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_LastSeverity Variable. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_LastSeverity = new ExpandedNodeId(TestData.Variables.Data_Conditions_SystemStatus_LastSeverity, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_LastSeverity_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_LastSeverity_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Conditions_SystemStatus_LastSeverity_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_Comment Variable. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_Comment = new ExpandedNodeId(TestData.Variables.Data_Conditions_SystemStatus_Comment, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_Comment_SourceTimestamp Variable. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_Comment_SourceTimestamp = new ExpandedNodeId(TestData.Variables.Data_Conditions_SystemStatus_Comment_SourceTimestamp, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_ClientUserId Variable. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_ClientUserId = new ExpandedNodeId(TestData.Variables.Data_Conditions_SystemStatus_ClientUserId, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_AddComment_InputArguments Variable. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_AddComment_InputArguments = new ExpandedNodeId(TestData.Variables.Data_Conditions_SystemStatus_AddComment_InputArguments, TestData.Namespaces.TestData); /// /// The identifier for the Data_Conditions_SystemStatus_MonitoredNodeCount Variable. /// public static readonly ExpandedNodeId Data_Conditions_SystemStatus_MonitoredNodeCount = new ExpandedNodeId(TestData.Variables.Data_Conditions_SystemStatus_MonitoredNodeCount, TestData.Namespaces.TestData); /// /// The identifier for the TestData_BinarySchema Variable. /// public static readonly ExpandedNodeId TestData_BinarySchema = new ExpandedNodeId(TestData.Variables.TestData_BinarySchema, TestData.Namespaces.TestData); /// /// The identifier for the TestData_BinarySchema_NamespaceUri Variable. /// public static readonly ExpandedNodeId TestData_BinarySchema_NamespaceUri = new ExpandedNodeId(TestData.Variables.TestData_BinarySchema_NamespaceUri, TestData.Namespaces.TestData); /// /// The identifier for the TestData_BinarySchema_Deprecated Variable. /// public static readonly ExpandedNodeId TestData_BinarySchema_Deprecated = new ExpandedNodeId(TestData.Variables.TestData_BinarySchema_Deprecated, TestData.Namespaces.TestData); /// /// The identifier for the TestData_BinarySchema_ScalarValueDataType Variable. /// public static readonly ExpandedNodeId TestData_BinarySchema_ScalarValueDataType = new ExpandedNodeId(TestData.Variables.TestData_BinarySchema_ScalarValueDataType, TestData.Namespaces.TestData); /// /// The identifier for the TestData_BinarySchema_ArrayValueDataType Variable. /// public static readonly ExpandedNodeId TestData_BinarySchema_ArrayValueDataType = new ExpandedNodeId(TestData.Variables.TestData_BinarySchema_ArrayValueDataType, TestData.Namespaces.TestData); /// /// The identifier for the TestData_BinarySchema_UserScalarValueDataType Variable. /// public static readonly ExpandedNodeId TestData_BinarySchema_UserScalarValueDataType = new ExpandedNodeId(TestData.Variables.TestData_BinarySchema_UserScalarValueDataType, TestData.Namespaces.TestData); /// /// The identifier for the TestData_BinarySchema_UserArrayValueDataType Variable. /// public static readonly ExpandedNodeId TestData_BinarySchema_UserArrayValueDataType = new ExpandedNodeId(TestData.Variables.TestData_BinarySchema_UserArrayValueDataType, TestData.Namespaces.TestData); /// /// The identifier for the TestData_BinarySchema_Vector Variable. /// public static readonly ExpandedNodeId TestData_BinarySchema_Vector = new ExpandedNodeId(TestData.Variables.TestData_BinarySchema_Vector, TestData.Namespaces.TestData); /// /// The identifier for the TestData_BinarySchema_WorkOrderStatusType Variable. /// public static readonly ExpandedNodeId TestData_BinarySchema_WorkOrderStatusType = new ExpandedNodeId(TestData.Variables.TestData_BinarySchema_WorkOrderStatusType, TestData.Namespaces.TestData); /// /// The identifier for the TestData_BinarySchema_WorkOrderType Variable. /// public static readonly ExpandedNodeId TestData_BinarySchema_WorkOrderType = new ExpandedNodeId(TestData.Variables.TestData_BinarySchema_WorkOrderType, TestData.Namespaces.TestData); /// /// The identifier for the TestData_XmlSchema Variable. /// public static readonly ExpandedNodeId TestData_XmlSchema = new ExpandedNodeId(TestData.Variables.TestData_XmlSchema, TestData.Namespaces.TestData); /// /// The identifier for the TestData_XmlSchema_NamespaceUri Variable. /// public static readonly ExpandedNodeId TestData_XmlSchema_NamespaceUri = new ExpandedNodeId(TestData.Variables.TestData_XmlSchema_NamespaceUri, TestData.Namespaces.TestData); /// /// The identifier for the TestData_XmlSchema_Deprecated Variable. /// public static readonly ExpandedNodeId TestData_XmlSchema_Deprecated = new ExpandedNodeId(TestData.Variables.TestData_XmlSchema_Deprecated, TestData.Namespaces.TestData); /// /// The identifier for the TestData_XmlSchema_ScalarValueDataType Variable. /// public static readonly ExpandedNodeId TestData_XmlSchema_ScalarValueDataType = new ExpandedNodeId(TestData.Variables.TestData_XmlSchema_ScalarValueDataType, TestData.Namespaces.TestData); /// /// The identifier for the TestData_XmlSchema_ArrayValueDataType Variable. /// public static readonly ExpandedNodeId TestData_XmlSchema_ArrayValueDataType = new ExpandedNodeId(TestData.Variables.TestData_XmlSchema_ArrayValueDataType, TestData.Namespaces.TestData); /// /// The identifier for the TestData_XmlSchema_UserScalarValueDataType Variable. /// public static readonly ExpandedNodeId TestData_XmlSchema_UserScalarValueDataType = new ExpandedNodeId(TestData.Variables.TestData_XmlSchema_UserScalarValueDataType, TestData.Namespaces.TestData); /// /// The identifier for the TestData_XmlSchema_UserArrayValueDataType Variable. /// public static readonly ExpandedNodeId TestData_XmlSchema_UserArrayValueDataType = new ExpandedNodeId(TestData.Variables.TestData_XmlSchema_UserArrayValueDataType, TestData.Namespaces.TestData); /// /// The identifier for the TestData_XmlSchema_Vector Variable. /// public static readonly ExpandedNodeId TestData_XmlSchema_Vector = new ExpandedNodeId(TestData.Variables.TestData_XmlSchema_Vector, TestData.Namespaces.TestData); /// /// The identifier for the TestData_XmlSchema_WorkOrderStatusType Variable. /// public static readonly ExpandedNodeId TestData_XmlSchema_WorkOrderStatusType = new ExpandedNodeId(TestData.Variables.TestData_XmlSchema_WorkOrderStatusType, TestData.Namespaces.TestData); /// /// The identifier for the TestData_XmlSchema_WorkOrderType Variable. /// public static readonly ExpandedNodeId TestData_XmlSchema_WorkOrderType = new ExpandedNodeId(TestData.Variables.TestData_XmlSchema_WorkOrderType, TestData.Namespaces.TestData); } #endregion #region BrowseName Declarations /// /// Declares all of the BrowseNames used in the Model Design. /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class BrowseNames { /// /// The BrowseName for the AnalogArrayValueObjectType component. /// public const string AnalogArrayValueObjectType = "AnalogArrayValueObjectType"; /// /// The BrowseName for the AnalogScalarValueObjectType component. /// public const string AnalogScalarValueObjectType = "AnalogScalarValueObjectType"; /// /// The BrowseName for the ArrayMethod1 component. /// public const string ArrayMethod1 = "ArrayMethod1"; /// /// The BrowseName for the ArrayMethod2 component. /// public const string ArrayMethod2 = "ArrayMethod2"; /// /// The BrowseName for the ArrayMethod3 component. /// public const string ArrayMethod3 = "ArrayMethod3"; /// /// The BrowseName for the ArrayValueDataType component. /// public const string ArrayValueDataType = "ArrayValueDataType"; /// /// The BrowseName for the ArrayValueObjectType component. /// public const string ArrayValueObjectType = "ArrayValueObjectType"; /// /// The BrowseName for the BooleanDataType component. /// public const string BooleanDataType = "BooleanDataType"; /// /// The BrowseName for the BooleanValue component. /// public const string BooleanValue = "BooleanValue"; /// /// The BrowseName for the ByteDataType component. /// public const string ByteDataType = "ByteDataType"; /// /// The BrowseName for the ByteStringDataType component. /// public const string ByteStringDataType = "ByteStringDataType"; /// /// The BrowseName for the ByteStringValue component. /// public const string ByteStringValue = "ByteStringValue"; /// /// The BrowseName for the ByteValue component. /// public const string ByteValue = "ByteValue"; /// /// The BrowseName for the Conditions component. /// public const string Conditions = "Conditions"; /// /// The BrowseName for the CycleComplete component. /// public const string CycleComplete = "CycleComplete"; /// /// The BrowseName for the Data component. /// public const string Data = "Data"; /// /// The BrowseName for the DateTimeDataType component. /// public const string DateTimeDataType = "DateTimeDataType"; /// /// The BrowseName for the DateTimeValue component. /// public const string DateTimeValue = "DateTimeValue"; /// /// The BrowseName for the DoubleDataType component. /// public const string DoubleDataType = "DoubleDataType"; /// /// The BrowseName for the DoubleValue component. /// public const string DoubleValue = "DoubleValue"; /// /// The BrowseName for the Dynamic component. /// public const string Dynamic = "Dynamic"; /// /// The BrowseName for the EnumerationValue component. /// public const string EnumerationValue = "EnumerationValue"; /// /// The BrowseName for the ExpandedNodeIdDataType component. /// public const string ExpandedNodeIdDataType = "ExpandedNodeIdDataType"; /// /// The BrowseName for the ExpandedNodeIdValue component. /// public const string ExpandedNodeIdValue = "ExpandedNodeIdValue"; /// /// The BrowseName for the FloatDataType component. /// public const string FloatDataType = "FloatDataType"; /// /// The BrowseName for the FloatValue component. /// public const string FloatValue = "FloatValue"; /// /// The BrowseName for the GenerateValues component. /// public const string GenerateValues = "GenerateValues"; /// /// The BrowseName for the GenerateValuesEventType component. /// public const string GenerateValuesEventType = "GenerateValuesEventType"; /// /// The BrowseName for the GuidDataType component. /// public const string GuidDataType = "GuidDataType"; /// /// The BrowseName for the GuidValue component. /// public const string GuidValue = "GuidValue"; /// /// The BrowseName for the Int16DataType component. /// public const string Int16DataType = "Int16DataType"; /// /// The BrowseName for the Int16Value component. /// public const string Int16Value = "Int16Value"; /// /// The BrowseName for the Int32DataType component. /// public const string Int32DataType = "Int32DataType"; /// /// The BrowseName for the Int32Value component. /// public const string Int32Value = "Int32Value"; /// /// The BrowseName for the Int64DataType component. /// public const string Int64DataType = "Int64DataType"; /// /// The BrowseName for the Int64Value component. /// public const string Int64Value = "Int64Value"; /// /// The BrowseName for the IntegerValue component. /// public const string IntegerValue = "IntegerValue"; /// /// The BrowseName for the Iterations component. /// public const string Iterations = "Iterations"; /// /// The BrowseName for the LocalizedTextDataType component. /// public const string LocalizedTextDataType = "LocalizedTextDataType"; /// /// The BrowseName for the LocalizedTextValue component. /// public const string LocalizedTextValue = "LocalizedTextValue"; /// /// The BrowseName for the MethodTestType component. /// public const string MethodTestType = "MethodTestType"; /// /// The BrowseName for the MonitoredNodeCount component. /// public const string MonitoredNodeCount = "MonitoredNodeCount"; /// /// The BrowseName for the NewValueCount component. /// public const string NewValueCount = "NewValueCount"; /// /// The BrowseName for the NodeIdDataType component. /// public const string NodeIdDataType = "NodeIdDataType"; /// /// The BrowseName for the NodeIdValue component. /// public const string NodeIdValue = "NodeIdValue"; /// /// The BrowseName for the NumberValue component. /// public const string NumberValue = "NumberValue"; /// /// The BrowseName for the QualifiedNameDataType component. /// public const string QualifiedNameDataType = "QualifiedNameDataType"; /// /// The BrowseName for the QualifiedNameValue component. /// public const string QualifiedNameValue = "QualifiedNameValue"; /// /// The BrowseName for the SByteDataType component. /// public const string SByteDataType = "SByteDataType"; /// /// The BrowseName for the SByteValue component. /// public const string SByteValue = "SByteValue"; /// /// The BrowseName for the ScalarMethod1 component. /// public const string ScalarMethod1 = "ScalarMethod1"; /// /// The BrowseName for the ScalarMethod2 component. /// public const string ScalarMethod2 = "ScalarMethod2"; /// /// The BrowseName for the ScalarMethod3 component. /// public const string ScalarMethod3 = "ScalarMethod3"; /// /// The BrowseName for the ScalarValueDataType component. /// public const string ScalarValueDataType = "ScalarValueDataType"; /// /// The BrowseName for the ScalarValueObjectType component. /// public const string ScalarValueObjectType = "ScalarValueObjectType"; /// /// The BrowseName for the SimulationActive component. /// public const string SimulationActive = "SimulationActive"; /// /// The BrowseName for the Static component. /// public const string Static = "Static"; /// /// The BrowseName for the StatusCodeDataType component. /// public const string StatusCodeDataType = "StatusCodeDataType"; /// /// The BrowseName for the StatusCodeValue component. /// public const string StatusCodeValue = "StatusCodeValue"; /// /// The BrowseName for the StringDataType component. /// public const string StringDataType = "StringDataType"; /// /// The BrowseName for the StringValue component. /// public const string StringValue = "StringValue"; /// /// The BrowseName for the StructureValue component. /// public const string StructureValue = "StructureValue"; /// /// The BrowseName for the TestData_BinarySchema component. /// public const string TestData_BinarySchema = "TestData"; /// /// The BrowseName for the TestData_XmlSchema component. /// public const string TestData_XmlSchema = "TestData"; /// /// The BrowseName for the TestDataObjectType component. /// public const string TestDataObjectType = "TestDataObjectType"; /// /// The BrowseName for the TestSystemConditionType component. /// public const string TestSystemConditionType = "TestSystemConditionType"; /// /// The BrowseName for the UInt16DataType component. /// public const string UInt16DataType = "UInt16DataType"; /// /// The BrowseName for the UInt16Value component. /// public const string UInt16Value = "UInt16Value"; /// /// The BrowseName for the UInt32DataType component. /// public const string UInt32DataType = "UInt32DataType"; /// /// The BrowseName for the UInt32Value component. /// public const string UInt32Value = "UInt32Value"; /// /// The BrowseName for the UInt64DataType component. /// public const string UInt64DataType = "UInt64DataType"; /// /// The BrowseName for the UInt64Value component. /// public const string UInt64Value = "UInt64Value"; /// /// The BrowseName for the UIntegerValue component. /// public const string UIntegerValue = "UIntegerValue"; /// /// The BrowseName for the UserArrayMethod1 component. /// public const string UserArrayMethod1 = "UserArrayMethod1"; /// /// The BrowseName for the UserArrayMethod2 component. /// public const string UserArrayMethod2 = "UserArrayMethod2"; /// /// The BrowseName for the UserArrayValueDataType component. /// public const string UserArrayValueDataType = "UserArrayValueDataType"; /// /// The BrowseName for the UserArrayValueObjectType component. /// public const string UserArrayValueObjectType = "UserArrayValueObjectType"; /// /// The BrowseName for the UserScalarMethod1 component. /// public const string UserScalarMethod1 = "UserScalarMethod1"; /// /// The BrowseName for the UserScalarMethod2 component. /// public const string UserScalarMethod2 = "UserScalarMethod2"; /// /// The BrowseName for the UserScalarValueDataType component. /// public const string UserScalarValueDataType = "UserScalarValueDataType"; /// /// The BrowseName for the UserScalarValueObjectType component. /// public const string UserScalarValueObjectType = "UserScalarValueObjectType"; /// /// The BrowseName for the VariantDataType component. /// public const string VariantDataType = "VariantDataType"; /// /// The BrowseName for the VariantValue component. /// public const string VariantValue = "VariantValue"; /// /// The BrowseName for the Vector component. /// public const string Vector = "Vector"; /// /// The BrowseName for the WorkOrderStatusType component. /// public const string WorkOrderStatusType = "WorkOrderStatusType"; /// /// The BrowseName for the WorkOrderType component. /// public const string WorkOrderType = "WorkOrderType"; /// /// The BrowseName for the XmlElementDataType component. /// public const string XmlElementDataType = "XmlElementDataType"; /// /// The BrowseName for the XmlElementValue component. /// public const string XmlElementValue = "XmlElementValue"; } #endregion #region Namespace Declarations /// /// Defines constants for all namespaces referenced by the model design. /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Namespaces { /// /// The URI for the OpcUa namespace (.NET code namespace is 'Opc.Ua'). /// public const string OpcUa = "http://opcfoundation.org/UA/"; /// /// The URI for the OpcUaXsd namespace (.NET code namespace is 'Opc.Ua'). /// public const string OpcUaXsd = "http://opcfoundation.org/UA/2008/02/Types.xsd"; /// /// The URI for the TestData namespace (.NET code namespace is 'TestData'). /// public const string TestData = "http://test.org/UA/Data/"; } #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/TestData/Design/TestData.DataTypes.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2021 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; using System; using System.Collections.Generic; using System.Runtime.Serialization; using System.Xml; namespace TestData { #region ScalarValueDataType Class #if (!OPCUA_EXCLUDE_ScalarValueDataType) /// /// /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = TestData.Namespaces.TestData)] public partial class ScalarValueDataType : IEncodeable { #region Constructors /// /// The default constructor. /// public ScalarValueDataType() { Initialize(); } /// /// Called by the .NET framework during deserialization. /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { m_booleanValue = true; m_sByteValue = (sbyte)0; m_byteValue = (byte)0; m_int16Value = (short)0; m_uInt16Value = (ushort)0; m_int32Value = (int)0; m_uInt32Value = (uint)0; m_int64Value = (long)0; m_uInt64Value = (ulong)0; m_floatValue = (float)0; m_doubleValue = (double)0; m_stringValue = null; m_dateTimeValue = DateTime.MinValue; m_guidValue = Uuid.Empty; m_byteStringValue = null; m_xmlElementValue = null; m_nodeIdValue = null; m_expandedNodeIdValue = null; m_qualifiedNameValue = null; m_localizedTextValue = null; m_statusCodeValue = StatusCodes.Good; m_variantValue = Variant.Null; m_enumerationValue = 0; m_structureValue = null; m_number = (double)0; m_integer = (long)0; m_uInteger = (ulong)0; } #endregion #region Public Properties /// [DataMember(Name = "BooleanValue", IsRequired = false, Order = 1)] public bool BooleanValue { get { return m_booleanValue; } set { m_booleanValue = value; } } /// [DataMember(Name = "SByteValue", IsRequired = false, Order = 2)] public sbyte SByteValue { get { return m_sByteValue; } set { m_sByteValue = value; } } /// [DataMember(Name = "ByteValue", IsRequired = false, Order = 3)] public byte ByteValue { get { return m_byteValue; } set { m_byteValue = value; } } /// [DataMember(Name = "Int16Value", IsRequired = false, Order = 4)] public short Int16Value { get { return m_int16Value; } set { m_int16Value = value; } } /// [DataMember(Name = "UInt16Value", IsRequired = false, Order = 5)] public ushort UInt16Value { get { return m_uInt16Value; } set { m_uInt16Value = value; } } /// [DataMember(Name = "Int32Value", IsRequired = false, Order = 6)] public int Int32Value { get { return m_int32Value; } set { m_int32Value = value; } } /// [DataMember(Name = "UInt32Value", IsRequired = false, Order = 7)] public uint UInt32Value { get { return m_uInt32Value; } set { m_uInt32Value = value; } } /// [DataMember(Name = "Int64Value", IsRequired = false, Order = 8)] public long Int64Value { get { return m_int64Value; } set { m_int64Value = value; } } /// [DataMember(Name = "UInt64Value", IsRequired = false, Order = 9)] public ulong UInt64Value { get { return m_uInt64Value; } set { m_uInt64Value = value; } } /// [DataMember(Name = "FloatValue", IsRequired = false, Order = 10)] public float FloatValue { get { return m_floatValue; } set { m_floatValue = value; } } /// [DataMember(Name = "DoubleValue", IsRequired = false, Order = 11)] public double DoubleValue { get { return m_doubleValue; } set { m_doubleValue = value; } } /// [DataMember(Name = "StringValue", IsRequired = false, Order = 12)] public string StringValue { get { return m_stringValue; } set { m_stringValue = value; } } /// [DataMember(Name = "DateTimeValue", IsRequired = false, Order = 13)] public DateTime DateTimeValue { get { return m_dateTimeValue; } set { m_dateTimeValue = value; } } /// [DataMember(Name = "GuidValue", IsRequired = false, Order = 14)] public Uuid GuidValue { get { return m_guidValue; } set { m_guidValue = value; } } /// [DataMember(Name = "ByteStringValue", IsRequired = false, Order = 15)] public byte[] ByteStringValue { get { return m_byteStringValue; } set { m_byteStringValue = value; } } /// [DataMember(Name = "XmlElementValue", IsRequired = false, Order = 16)] public XmlElement XmlElementValue { get { return m_xmlElementValue; } set { m_xmlElementValue = value; } } /// [DataMember(Name = "NodeIdValue", IsRequired = false, Order = 17)] public NodeId NodeIdValue { get { return m_nodeIdValue; } set { m_nodeIdValue = value; } } /// [DataMember(Name = "ExpandedNodeIdValue", IsRequired = false, Order = 18)] public ExpandedNodeId ExpandedNodeIdValue { get { return m_expandedNodeIdValue; } set { m_expandedNodeIdValue = value; } } /// [DataMember(Name = "QualifiedNameValue", IsRequired = false, Order = 19)] public QualifiedName QualifiedNameValue { get { return m_qualifiedNameValue; } set { m_qualifiedNameValue = value; } } /// [DataMember(Name = "LocalizedTextValue", IsRequired = false, Order = 20)] public LocalizedText LocalizedTextValue { get { return m_localizedTextValue; } set { m_localizedTextValue = value; } } /// [DataMember(Name = "StatusCodeValue", IsRequired = false, Order = 21)] public StatusCode StatusCodeValue { get { return m_statusCodeValue; } set { m_statusCodeValue = value; } } /// [DataMember(Name = "VariantValue", IsRequired = false, Order = 22)] public Variant VariantValue { get { return m_variantValue; } set { m_variantValue = value; } } /// [DataMember(Name = "EnumerationValue", IsRequired = false, Order = 23)] public int EnumerationValue { get { return m_enumerationValue; } set { m_enumerationValue = value; } } /// [DataMember(Name = "StructureValue", IsRequired = false, Order = 24)] public ExtensionObject StructureValue { get { return m_structureValue; } set { m_structureValue = value; } } /// [DataMember(Name = "Number", IsRequired = false, Order = 25)] public Variant Number { get { return m_number; } set { m_number = value; } } /// [DataMember(Name = "Integer", IsRequired = false, Order = 26)] public Variant Integer { get { return m_integer; } set { m_integer = value; } } /// [DataMember(Name = "UInteger", IsRequired = false, Order = 27)] public Variant UInteger { get { return m_uInteger; } set { m_uInteger = value; } } #endregion #region IEncodeable Members /// public virtual ExpandedNodeId TypeId { get { return DataTypeIds.ScalarValueDataType; } } /// public virtual ExpandedNodeId BinaryEncodingId { get { return ObjectIds.ScalarValueDataType_Encoding_DefaultBinary; } } /// public virtual ExpandedNodeId XmlEncodingId { get { return ObjectIds.ScalarValueDataType_Encoding_DefaultXml; } } /// public virtual void Encode(IEncoder encoder) { encoder.PushNamespace(TestData.Namespaces.TestData); encoder.WriteBoolean("BooleanValue", BooleanValue); encoder.WriteSByte("SByteValue", SByteValue); encoder.WriteByte("ByteValue", ByteValue); encoder.WriteInt16("Int16Value", Int16Value); encoder.WriteUInt16("UInt16Value", UInt16Value); encoder.WriteInt32("Int32Value", Int32Value); encoder.WriteUInt32("UInt32Value", UInt32Value); encoder.WriteInt64("Int64Value", Int64Value); encoder.WriteUInt64("UInt64Value", UInt64Value); encoder.WriteFloat("FloatValue", FloatValue); encoder.WriteDouble("DoubleValue", DoubleValue); encoder.WriteString("StringValue", StringValue); encoder.WriteDateTime("DateTimeValue", DateTimeValue); encoder.WriteGuid("GuidValue", GuidValue); encoder.WriteByteString("ByteStringValue", ByteStringValue); encoder.WriteXmlElement("XmlElementValue", XmlElementValue); encoder.WriteNodeId("NodeIdValue", NodeIdValue); encoder.WriteExpandedNodeId("ExpandedNodeIdValue", ExpandedNodeIdValue); encoder.WriteQualifiedName("QualifiedNameValue", QualifiedNameValue); encoder.WriteLocalizedText("LocalizedTextValue", LocalizedTextValue); encoder.WriteStatusCode("StatusCodeValue", StatusCodeValue); encoder.WriteVariant("VariantValue", VariantValue); encoder.WriteInt32("EnumerationValue", EnumerationValue); encoder.WriteExtensionObject("StructureValue", StructureValue); encoder.WriteVariant("Number", Number); encoder.WriteVariant("Integer", Integer); encoder.WriteVariant("UInteger", UInteger); encoder.PopNamespace(); } /// public virtual void Decode(IDecoder decoder) { decoder.PushNamespace(TestData.Namespaces.TestData); BooleanValue = decoder.ReadBoolean("BooleanValue"); SByteValue = decoder.ReadSByte("SByteValue"); ByteValue = decoder.ReadByte("ByteValue"); Int16Value = decoder.ReadInt16("Int16Value"); UInt16Value = decoder.ReadUInt16("UInt16Value"); Int32Value = decoder.ReadInt32("Int32Value"); UInt32Value = decoder.ReadUInt32("UInt32Value"); Int64Value = decoder.ReadInt64("Int64Value"); UInt64Value = decoder.ReadUInt64("UInt64Value"); FloatValue = decoder.ReadFloat("FloatValue"); DoubleValue = decoder.ReadDouble("DoubleValue"); StringValue = decoder.ReadString("StringValue"); DateTimeValue = decoder.ReadDateTime("DateTimeValue"); GuidValue = decoder.ReadGuid("GuidValue"); ByteStringValue = decoder.ReadByteString("ByteStringValue"); XmlElementValue = decoder.ReadXmlElement("XmlElementValue"); NodeIdValue = decoder.ReadNodeId("NodeIdValue"); ExpandedNodeIdValue = decoder.ReadExpandedNodeId("ExpandedNodeIdValue"); QualifiedNameValue = decoder.ReadQualifiedName("QualifiedNameValue"); LocalizedTextValue = decoder.ReadLocalizedText("LocalizedTextValue"); StatusCodeValue = decoder.ReadStatusCode("StatusCodeValue"); VariantValue = decoder.ReadVariant("VariantValue"); EnumerationValue = decoder.ReadInt32("EnumerationValue"); StructureValue = decoder.ReadExtensionObject("StructureValue"); Number = decoder.ReadVariant("Number"); Integer = decoder.ReadVariant("Integer"); UInteger = decoder.ReadVariant("UInteger"); decoder.PopNamespace(); } /// public virtual bool IsEqual(IEncodeable encodeable) { if (Object.ReferenceEquals(this, encodeable)) { return true; } ScalarValueDataType value = encodeable as ScalarValueDataType; if (value == null) { return false; } if (!Utils.IsEqual(m_booleanValue, value.m_booleanValue)) return false; if (!Utils.IsEqual(m_sByteValue, value.m_sByteValue)) return false; if (!Utils.IsEqual(m_byteValue, value.m_byteValue)) return false; if (!Utils.IsEqual(m_int16Value, value.m_int16Value)) return false; if (!Utils.IsEqual(m_uInt16Value, value.m_uInt16Value)) return false; if (!Utils.IsEqual(m_int32Value, value.m_int32Value)) return false; if (!Utils.IsEqual(m_uInt32Value, value.m_uInt32Value)) return false; if (!Utils.IsEqual(m_int64Value, value.m_int64Value)) return false; if (!Utils.IsEqual(m_uInt64Value, value.m_uInt64Value)) return false; if (!Utils.IsEqual(m_floatValue, value.m_floatValue)) return false; if (!Utils.IsEqual(m_doubleValue, value.m_doubleValue)) return false; if (!Utils.IsEqual(m_stringValue, value.m_stringValue)) return false; if (!Utils.IsEqual(m_dateTimeValue, value.m_dateTimeValue)) return false; if (!Utils.IsEqual(m_guidValue, value.m_guidValue)) return false; if (!Utils.IsEqual(m_byteStringValue, value.m_byteStringValue)) return false; if (!Utils.IsEqual(m_xmlElementValue, value.m_xmlElementValue)) return false; if (!Utils.IsEqual(m_nodeIdValue, value.m_nodeIdValue)) return false; if (!Utils.IsEqual(m_expandedNodeIdValue, value.m_expandedNodeIdValue)) return false; if (!Utils.IsEqual(m_qualifiedNameValue, value.m_qualifiedNameValue)) return false; if (!Utils.IsEqual(m_localizedTextValue, value.m_localizedTextValue)) return false; if (!Utils.IsEqual(m_statusCodeValue, value.m_statusCodeValue)) return false; if (!Utils.IsEqual(m_variantValue, value.m_variantValue)) return false; if (!Utils.IsEqual(m_enumerationValue, value.m_enumerationValue)) return false; if (!Utils.IsEqual(m_structureValue, value.m_structureValue)) return false; if (!Utils.IsEqual(m_number, value.m_number)) return false; if (!Utils.IsEqual(m_integer, value.m_integer)) return false; if (!Utils.IsEqual(m_uInteger, value.m_uInteger)) return false; return true; } #if !NET_STANDARD /// public virtual object Clone() { return (ScalarValueDataType)this.MemberwiseClone(); } #endif /// public new object MemberwiseClone() { ScalarValueDataType clone = (ScalarValueDataType)base.MemberwiseClone(); clone.m_booleanValue = (bool)Utils.Clone(this.m_booleanValue); clone.m_sByteValue = (sbyte)Utils.Clone(this.m_sByteValue); clone.m_byteValue = (byte)Utils.Clone(this.m_byteValue); clone.m_int16Value = (short)Utils.Clone(this.m_int16Value); clone.m_uInt16Value = (ushort)Utils.Clone(this.m_uInt16Value); clone.m_int32Value = (int)Utils.Clone(this.m_int32Value); clone.m_uInt32Value = (uint)Utils.Clone(this.m_uInt32Value); clone.m_int64Value = (long)Utils.Clone(this.m_int64Value); clone.m_uInt64Value = (ulong)Utils.Clone(this.m_uInt64Value); clone.m_floatValue = (float)Utils.Clone(this.m_floatValue); clone.m_doubleValue = (double)Utils.Clone(this.m_doubleValue); clone.m_stringValue = (string)Utils.Clone(this.m_stringValue); clone.m_dateTimeValue = (DateTime)Utils.Clone(this.m_dateTimeValue); clone.m_guidValue = (Uuid)Utils.Clone(this.m_guidValue); clone.m_byteStringValue = (byte[])Utils.Clone(this.m_byteStringValue); clone.m_xmlElementValue = (XmlElement)Utils.Clone(this.m_xmlElementValue); clone.m_nodeIdValue = (NodeId)Utils.Clone(this.m_nodeIdValue); clone.m_expandedNodeIdValue = (ExpandedNodeId)Utils.Clone(this.m_expandedNodeIdValue); clone.m_qualifiedNameValue = (QualifiedName)Utils.Clone(this.m_qualifiedNameValue); clone.m_localizedTextValue = (LocalizedText)Utils.Clone(this.m_localizedTextValue); clone.m_statusCodeValue = (StatusCode)Utils.Clone(this.m_statusCodeValue); clone.m_variantValue = (Variant)Utils.Clone(this.m_variantValue); clone.m_enumerationValue = (int)Utils.Clone(this.m_enumerationValue); clone.m_structureValue = (ExtensionObject)Utils.Clone(this.m_structureValue); clone.m_number = (Variant)Utils.Clone(this.m_number); clone.m_integer = (Variant)Utils.Clone(this.m_integer); clone.m_uInteger = (Variant)Utils.Clone(this.m_uInteger); return clone; } #endregion #region Private Fields private bool m_booleanValue; private sbyte m_sByteValue; private byte m_byteValue; private short m_int16Value; private ushort m_uInt16Value; private int m_int32Value; private uint m_uInt32Value; private long m_int64Value; private ulong m_uInt64Value; private float m_floatValue; private double m_doubleValue; private string m_stringValue; private DateTime m_dateTimeValue; private Uuid m_guidValue; private byte[] m_byteStringValue; private XmlElement m_xmlElementValue; private NodeId m_nodeIdValue; private ExpandedNodeId m_expandedNodeIdValue; private QualifiedName m_qualifiedNameValue; private LocalizedText m_localizedTextValue; private StatusCode m_statusCodeValue; private Variant m_variantValue; private int m_enumerationValue; private ExtensionObject m_structureValue; private Variant m_number; private Variant m_integer; private Variant m_uInteger; #endregion } #region ScalarValueDataTypeCollection Class /// /// A collection of ScalarValueDataType objects. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfScalarValueDataType", Namespace = TestData.Namespaces.TestData, ItemName = "ScalarValueDataType")] #if !NET_STANDARD public partial class ScalarValueDataTypeCollection : List, ICloneable #else public partial class ScalarValueDataTypeCollection : List #endif { #region Constructors /// /// Initializes the collection with default values. /// public ScalarValueDataTypeCollection() { } /// /// Initializes the collection with an initial capacity. /// public ScalarValueDataTypeCollection(int capacity) : base(capacity) { } /// /// Initializes the collection with another collection. /// public ScalarValueDataTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// /// Converts an array to a collection. /// public static implicit operator ScalarValueDataTypeCollection(ScalarValueDataType[] values) { if (values != null) { return new ScalarValueDataTypeCollection(values); } return new ScalarValueDataTypeCollection(); } /// /// Converts a collection to an array. /// public static explicit operator ScalarValueDataType[](ScalarValueDataTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #if !NET_STANDARD #region ICloneable Methods /// /// Creates a deep copy of the collection. /// public object Clone() { return (ScalarValueDataTypeCollection)this.MemberwiseClone(); } #endregion #endif /// public new object MemberwiseClone() { ScalarValueDataTypeCollection clone = new ScalarValueDataTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((ScalarValueDataType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion #region ArrayValueDataType Class #if (!OPCUA_EXCLUDE_ArrayValueDataType) /// /// /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = TestData.Namespaces.TestData)] public partial class ArrayValueDataType : IEncodeable { #region Constructors /// /// The default constructor. /// public ArrayValueDataType() { Initialize(); } /// /// Called by the .NET framework during deserialization. /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { m_booleanValue = new BooleanCollection(); m_sByteValue = new SByteCollection(); m_byteValue = new ByteCollection(); m_int16Value = new Int16Collection(); m_uInt16Value = new UInt16Collection(); m_int32Value = new Int32Collection(); m_uInt32Value = new UInt32Collection(); m_int64Value = new Int64Collection(); m_uInt64Value = new UInt64Collection(); m_floatValue = new FloatCollection(); m_doubleValue = new DoubleCollection(); m_stringValue = new StringCollection(); m_dateTimeValue = new DateTimeCollection(); m_guidValue = new UuidCollection(); m_byteStringValue = new ByteStringCollection(); m_xmlElementValue = new XmlElementCollection(); m_nodeIdValue = new NodeIdCollection(); m_expandedNodeIdValue = new ExpandedNodeIdCollection(); m_qualifiedNameValue = new QualifiedNameCollection(); m_localizedTextValue = new LocalizedTextCollection(); m_statusCodeValue = new StatusCodeCollection(); m_variantValue = new VariantCollection(); m_enumerationValue = new Int32Collection(); m_structureValue = new ExtensionObjectCollection(); m_number = new VariantCollection(); m_integer = new VariantCollection(); m_uInteger = new VariantCollection(); } #endregion #region Public Properties /// /// /// [DataMember(Name = "BooleanValue", IsRequired = false, Order = 1)] public BooleanCollection BooleanValue { get { return m_booleanValue; } set { m_booleanValue = value; if (value == null) { m_booleanValue = new BooleanCollection(); } } } /// /// /// [DataMember(Name = "SByteValue", IsRequired = false, Order = 2)] public SByteCollection SByteValue { get { return m_sByteValue; } set { m_sByteValue = value; if (value == null) { m_sByteValue = new SByteCollection(); } } } /// /// /// [DataMember(Name = "ByteValue", IsRequired = false, Order = 3)] public ByteCollection ByteValue { get { return m_byteValue; } set { m_byteValue = value; if (value == null) { m_byteValue = new ByteCollection(); } } } /// /// /// [DataMember(Name = "Int16Value", IsRequired = false, Order = 4)] public Int16Collection Int16Value { get { return m_int16Value; } set { m_int16Value = value; if (value == null) { m_int16Value = new Int16Collection(); } } } /// /// /// [DataMember(Name = "UInt16Value", IsRequired = false, Order = 5)] public UInt16Collection UInt16Value { get { return m_uInt16Value; } set { m_uInt16Value = value; if (value == null) { m_uInt16Value = new UInt16Collection(); } } } /// /// /// [DataMember(Name = "Int32Value", IsRequired = false, Order = 6)] public Int32Collection Int32Value { get { return m_int32Value; } set { m_int32Value = value; if (value == null) { m_int32Value = new Int32Collection(); } } } /// /// /// [DataMember(Name = "UInt32Value", IsRequired = false, Order = 7)] public UInt32Collection UInt32Value { get { return m_uInt32Value; } set { m_uInt32Value = value; if (value == null) { m_uInt32Value = new UInt32Collection(); } } } /// /// /// [DataMember(Name = "Int64Value", IsRequired = false, Order = 8)] public Int64Collection Int64Value { get { return m_int64Value; } set { m_int64Value = value; if (value == null) { m_int64Value = new Int64Collection(); } } } /// /// /// [DataMember(Name = "UInt64Value", IsRequired = false, Order = 9)] public UInt64Collection UInt64Value { get { return m_uInt64Value; } set { m_uInt64Value = value; if (value == null) { m_uInt64Value = new UInt64Collection(); } } } /// /// /// [DataMember(Name = "FloatValue", IsRequired = false, Order = 10)] public FloatCollection FloatValue { get { return m_floatValue; } set { m_floatValue = value; if (value == null) { m_floatValue = new FloatCollection(); } } } /// /// /// [DataMember(Name = "DoubleValue", IsRequired = false, Order = 11)] public DoubleCollection DoubleValue { get { return m_doubleValue; } set { m_doubleValue = value; if (value == null) { m_doubleValue = new DoubleCollection(); } } } /// /// /// [DataMember(Name = "StringValue", IsRequired = false, Order = 12)] public StringCollection StringValue { get { return m_stringValue; } set { m_stringValue = value; if (value == null) { m_stringValue = new StringCollection(); } } } /// /// /// [DataMember(Name = "DateTimeValue", IsRequired = false, Order = 13)] public DateTimeCollection DateTimeValue { get { return m_dateTimeValue; } set { m_dateTimeValue = value; if (value == null) { m_dateTimeValue = new DateTimeCollection(); } } } /// /// /// [DataMember(Name = "GuidValue", IsRequired = false, Order = 14)] public UuidCollection GuidValue { get { return m_guidValue; } set { m_guidValue = value; if (value == null) { m_guidValue = new UuidCollection(); } } } /// /// /// [DataMember(Name = "ByteStringValue", IsRequired = false, Order = 15)] public ByteStringCollection ByteStringValue { get { return m_byteStringValue; } set { m_byteStringValue = value; if (value == null) { m_byteStringValue = new ByteStringCollection(); } } } /// /// /// [DataMember(Name = "XmlElementValue", IsRequired = false, Order = 16)] public XmlElementCollection XmlElementValue { get { return m_xmlElementValue; } set { m_xmlElementValue = value; if (value == null) { m_xmlElementValue = new XmlElementCollection(); } } } /// /// /// [DataMember(Name = "NodeIdValue", IsRequired = false, Order = 17)] public NodeIdCollection NodeIdValue { get { return m_nodeIdValue; } set { m_nodeIdValue = value; if (value == null) { m_nodeIdValue = new NodeIdCollection(); } } } /// /// /// [DataMember(Name = "ExpandedNodeIdValue", IsRequired = false, Order = 18)] public ExpandedNodeIdCollection ExpandedNodeIdValue { get { return m_expandedNodeIdValue; } set { m_expandedNodeIdValue = value; if (value == null) { m_expandedNodeIdValue = new ExpandedNodeIdCollection(); } } } /// /// /// [DataMember(Name = "QualifiedNameValue", IsRequired = false, Order = 19)] public QualifiedNameCollection QualifiedNameValue { get { return m_qualifiedNameValue; } set { m_qualifiedNameValue = value; if (value == null) { m_qualifiedNameValue = new QualifiedNameCollection(); } } } /// /// /// [DataMember(Name = "LocalizedTextValue", IsRequired = false, Order = 20)] public LocalizedTextCollection LocalizedTextValue { get { return m_localizedTextValue; } set { m_localizedTextValue = value; if (value == null) { m_localizedTextValue = new LocalizedTextCollection(); } } } /// /// /// [DataMember(Name = "StatusCodeValue", IsRequired = false, Order = 21)] public StatusCodeCollection StatusCodeValue { get { return m_statusCodeValue; } set { m_statusCodeValue = value; if (value == null) { m_statusCodeValue = new StatusCodeCollection(); } } } /// /// /// [DataMember(Name = "VariantValue", IsRequired = false, Order = 22)] public VariantCollection VariantValue { get { return m_variantValue; } set { m_variantValue = value; if (value == null) { m_variantValue = new VariantCollection(); } } } /// /// /// [DataMember(Name = "EnumerationValue", IsRequired = false, Order = 23)] public Int32Collection EnumerationValue { get { return m_enumerationValue; } set { m_enumerationValue = value; if (value == null) { m_enumerationValue = new Int32Collection(); } } } /// /// /// [DataMember(Name = "StructureValue", IsRequired = false, Order = 24)] public ExtensionObjectCollection StructureValue { get { return m_structureValue; } set { m_structureValue = value; if (value == null) { m_structureValue = new ExtensionObjectCollection(); } } } /// /// /// [DataMember(Name = "Number", IsRequired = false, Order = 25)] public VariantCollection Number { get { return m_number; } set { m_number = value; if (value == null) { m_number = new VariantCollection(); } } } /// /// /// [DataMember(Name = "Integer", IsRequired = false, Order = 26)] public VariantCollection Integer { get { return m_integer; } set { m_integer = value; if (value == null) { m_integer = new VariantCollection(); } } } /// /// /// [DataMember(Name = "UInteger", IsRequired = false, Order = 27)] public VariantCollection UInteger { get { return m_uInteger; } set { m_uInteger = value; if (value == null) { m_uInteger = new VariantCollection(); } } } #endregion #region IEncodeable Members /// public virtual ExpandedNodeId TypeId { get { return DataTypeIds.ArrayValueDataType; } } /// public virtual ExpandedNodeId BinaryEncodingId { get { return ObjectIds.ArrayValueDataType_Encoding_DefaultBinary; } } /// public virtual ExpandedNodeId XmlEncodingId { get { return ObjectIds.ArrayValueDataType_Encoding_DefaultXml; } } /// public virtual void Encode(IEncoder encoder) { encoder.PushNamespace(TestData.Namespaces.TestData); encoder.WriteBooleanArray("BooleanValue", BooleanValue); encoder.WriteSByteArray("SByteValue", SByteValue); encoder.WriteByteArray("ByteValue", ByteValue); encoder.WriteInt16Array("Int16Value", Int16Value); encoder.WriteUInt16Array("UInt16Value", UInt16Value); encoder.WriteInt32Array("Int32Value", Int32Value); encoder.WriteUInt32Array("UInt32Value", UInt32Value); encoder.WriteInt64Array("Int64Value", Int64Value); encoder.WriteUInt64Array("UInt64Value", UInt64Value); encoder.WriteFloatArray("FloatValue", FloatValue); encoder.WriteDoubleArray("DoubleValue", DoubleValue); encoder.WriteStringArray("StringValue", StringValue); encoder.WriteDateTimeArray("DateTimeValue", DateTimeValue); encoder.WriteGuidArray("GuidValue", GuidValue); encoder.WriteByteStringArray("ByteStringValue", ByteStringValue); encoder.WriteXmlElementArray("XmlElementValue", XmlElementValue); encoder.WriteNodeIdArray("NodeIdValue", NodeIdValue); encoder.WriteExpandedNodeIdArray("ExpandedNodeIdValue", ExpandedNodeIdValue); encoder.WriteQualifiedNameArray("QualifiedNameValue", QualifiedNameValue); encoder.WriteLocalizedTextArray("LocalizedTextValue", LocalizedTextValue); encoder.WriteStatusCodeArray("StatusCodeValue", StatusCodeValue); encoder.WriteVariantArray("VariantValue", VariantValue); encoder.WriteInt32Array("EnumerationValue", EnumerationValue); encoder.WriteExtensionObjectArray("StructureValue", StructureValue); encoder.WriteVariantArray("Number", Number); encoder.WriteVariantArray("Integer", Integer); encoder.WriteVariantArray("UInteger", UInteger); encoder.PopNamespace(); } /// public virtual void Decode(IDecoder decoder) { decoder.PushNamespace(TestData.Namespaces.TestData); BooleanValue = decoder.ReadBooleanArray("BooleanValue"); SByteValue = decoder.ReadSByteArray("SByteValue"); ByteValue = decoder.ReadByteArray("ByteValue"); Int16Value = decoder.ReadInt16Array("Int16Value"); UInt16Value = decoder.ReadUInt16Array("UInt16Value"); Int32Value = decoder.ReadInt32Array("Int32Value"); UInt32Value = decoder.ReadUInt32Array("UInt32Value"); Int64Value = decoder.ReadInt64Array("Int64Value"); UInt64Value = decoder.ReadUInt64Array("UInt64Value"); FloatValue = decoder.ReadFloatArray("FloatValue"); DoubleValue = decoder.ReadDoubleArray("DoubleValue"); StringValue = decoder.ReadStringArray("StringValue"); DateTimeValue = decoder.ReadDateTimeArray("DateTimeValue"); GuidValue = decoder.ReadGuidArray("GuidValue"); ByteStringValue = decoder.ReadByteStringArray("ByteStringValue"); XmlElementValue = decoder.ReadXmlElementArray("XmlElementValue"); NodeIdValue = decoder.ReadNodeIdArray("NodeIdValue"); ExpandedNodeIdValue = decoder.ReadExpandedNodeIdArray("ExpandedNodeIdValue"); QualifiedNameValue = decoder.ReadQualifiedNameArray("QualifiedNameValue"); LocalizedTextValue = decoder.ReadLocalizedTextArray("LocalizedTextValue"); StatusCodeValue = decoder.ReadStatusCodeArray("StatusCodeValue"); VariantValue = decoder.ReadVariantArray("VariantValue"); EnumerationValue = decoder.ReadInt32Array("EnumerationValue"); StructureValue = decoder.ReadExtensionObjectArray("StructureValue"); Number = decoder.ReadVariantArray("Number"); Integer = decoder.ReadVariantArray("Integer"); UInteger = decoder.ReadVariantArray("UInteger"); decoder.PopNamespace(); } /// public virtual bool IsEqual(IEncodeable encodeable) { if (Object.ReferenceEquals(this, encodeable)) { return true; } ArrayValueDataType value = encodeable as ArrayValueDataType; if (value == null) { return false; } if (!Utils.IsEqual(m_booleanValue, value.m_booleanValue)) return false; if (!Utils.IsEqual(m_sByteValue, value.m_sByteValue)) return false; if (!Utils.IsEqual(m_byteValue, value.m_byteValue)) return false; if (!Utils.IsEqual(m_int16Value, value.m_int16Value)) return false; if (!Utils.IsEqual(m_uInt16Value, value.m_uInt16Value)) return false; if (!Utils.IsEqual(m_int32Value, value.m_int32Value)) return false; if (!Utils.IsEqual(m_uInt32Value, value.m_uInt32Value)) return false; if (!Utils.IsEqual(m_int64Value, value.m_int64Value)) return false; if (!Utils.IsEqual(m_uInt64Value, value.m_uInt64Value)) return false; if (!Utils.IsEqual(m_floatValue, value.m_floatValue)) return false; if (!Utils.IsEqual(m_doubleValue, value.m_doubleValue)) return false; if (!Utils.IsEqual(m_stringValue, value.m_stringValue)) return false; if (!Utils.IsEqual(m_dateTimeValue, value.m_dateTimeValue)) return false; if (!Utils.IsEqual(m_guidValue, value.m_guidValue)) return false; if (!Utils.IsEqual(m_byteStringValue, value.m_byteStringValue)) return false; if (!Utils.IsEqual(m_xmlElementValue, value.m_xmlElementValue)) return false; if (!Utils.IsEqual(m_nodeIdValue, value.m_nodeIdValue)) return false; if (!Utils.IsEqual(m_expandedNodeIdValue, value.m_expandedNodeIdValue)) return false; if (!Utils.IsEqual(m_qualifiedNameValue, value.m_qualifiedNameValue)) return false; if (!Utils.IsEqual(m_localizedTextValue, value.m_localizedTextValue)) return false; if (!Utils.IsEqual(m_statusCodeValue, value.m_statusCodeValue)) return false; if (!Utils.IsEqual(m_variantValue, value.m_variantValue)) return false; if (!Utils.IsEqual(m_enumerationValue, value.m_enumerationValue)) return false; if (!Utils.IsEqual(m_structureValue, value.m_structureValue)) return false; if (!Utils.IsEqual(m_number, value.m_number)) return false; if (!Utils.IsEqual(m_integer, value.m_integer)) return false; if (!Utils.IsEqual(m_uInteger, value.m_uInteger)) return false; return true; } #if !NET_STANDARD /// public virtual object Clone() { return (ArrayValueDataType)this.MemberwiseClone(); } #endif /// public new object MemberwiseClone() { ArrayValueDataType clone = (ArrayValueDataType)base.MemberwiseClone(); clone.m_booleanValue = (BooleanCollection)Utils.Clone(this.m_booleanValue); clone.m_sByteValue = (SByteCollection)Utils.Clone(this.m_sByteValue); clone.m_byteValue = (ByteCollection)Utils.Clone(this.m_byteValue); clone.m_int16Value = (Int16Collection)Utils.Clone(this.m_int16Value); clone.m_uInt16Value = (UInt16Collection)Utils.Clone(this.m_uInt16Value); clone.m_int32Value = (Int32Collection)Utils.Clone(this.m_int32Value); clone.m_uInt32Value = (UInt32Collection)Utils.Clone(this.m_uInt32Value); clone.m_int64Value = (Int64Collection)Utils.Clone(this.m_int64Value); clone.m_uInt64Value = (UInt64Collection)Utils.Clone(this.m_uInt64Value); clone.m_floatValue = (FloatCollection)Utils.Clone(this.m_floatValue); clone.m_doubleValue = (DoubleCollection)Utils.Clone(this.m_doubleValue); clone.m_stringValue = (StringCollection)Utils.Clone(this.m_stringValue); clone.m_dateTimeValue = (DateTimeCollection)Utils.Clone(this.m_dateTimeValue); clone.m_guidValue = (UuidCollection)Utils.Clone(this.m_guidValue); clone.m_byteStringValue = (ByteStringCollection)Utils.Clone(this.m_byteStringValue); clone.m_xmlElementValue = (XmlElementCollection)Utils.Clone(this.m_xmlElementValue); clone.m_nodeIdValue = (NodeIdCollection)Utils.Clone(this.m_nodeIdValue); clone.m_expandedNodeIdValue = (ExpandedNodeIdCollection)Utils.Clone(this.m_expandedNodeIdValue); clone.m_qualifiedNameValue = (QualifiedNameCollection)Utils.Clone(this.m_qualifiedNameValue); clone.m_localizedTextValue = (LocalizedTextCollection)Utils.Clone(this.m_localizedTextValue); clone.m_statusCodeValue = (StatusCodeCollection)Utils.Clone(this.m_statusCodeValue); clone.m_variantValue = (VariantCollection)Utils.Clone(this.m_variantValue); clone.m_enumerationValue = (Int32Collection)Utils.Clone(this.m_enumerationValue); clone.m_structureValue = (ExtensionObjectCollection)Utils.Clone(this.m_structureValue); clone.m_number = (VariantCollection)Utils.Clone(this.m_number); clone.m_integer = (VariantCollection)Utils.Clone(this.m_integer); clone.m_uInteger = (VariantCollection)Utils.Clone(this.m_uInteger); return clone; } #endregion #region Private Fields private BooleanCollection m_booleanValue; private SByteCollection m_sByteValue; private ByteCollection m_byteValue; private Int16Collection m_int16Value; private UInt16Collection m_uInt16Value; private Int32Collection m_int32Value; private UInt32Collection m_uInt32Value; private Int64Collection m_int64Value; private UInt64Collection m_uInt64Value; private FloatCollection m_floatValue; private DoubleCollection m_doubleValue; private StringCollection m_stringValue; private DateTimeCollection m_dateTimeValue; private UuidCollection m_guidValue; private ByteStringCollection m_byteStringValue; private XmlElementCollection m_xmlElementValue; private NodeIdCollection m_nodeIdValue; private ExpandedNodeIdCollection m_expandedNodeIdValue; private QualifiedNameCollection m_qualifiedNameValue; private LocalizedTextCollection m_localizedTextValue; private StatusCodeCollection m_statusCodeValue; private VariantCollection m_variantValue; private Int32Collection m_enumerationValue; private ExtensionObjectCollection m_structureValue; private VariantCollection m_number; private VariantCollection m_integer; private VariantCollection m_uInteger; #endregion } #region ArrayValueDataTypeCollection Class /// /// A collection of ArrayValueDataType objects. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfArrayValueDataType", Namespace = TestData.Namespaces.TestData, ItemName = "ArrayValueDataType")] #if !NET_STANDARD public partial class ArrayValueDataTypeCollection : List, ICloneable #else public partial class ArrayValueDataTypeCollection : List #endif { #region Constructors /// /// Initializes the collection with default values. /// public ArrayValueDataTypeCollection() { } /// /// Initializes the collection with an initial capacity. /// public ArrayValueDataTypeCollection(int capacity) : base(capacity) { } /// /// Initializes the collection with another collection. /// public ArrayValueDataTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// /// Converts an array to a collection. /// public static implicit operator ArrayValueDataTypeCollection(ArrayValueDataType[] values) { if (values != null) { return new ArrayValueDataTypeCollection(values); } return new ArrayValueDataTypeCollection(); } /// /// Converts a collection to an array. /// public static explicit operator ArrayValueDataType[](ArrayValueDataTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #if !NET_STANDARD #region ICloneable Methods /// /// Creates a deep copy of the collection. /// public object Clone() { return (ArrayValueDataTypeCollection)this.MemberwiseClone(); } #endregion #endif /// public new object MemberwiseClone() { ArrayValueDataTypeCollection clone = new ArrayValueDataTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((ArrayValueDataType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion #region UserScalarValueDataType Class #if (!OPCUA_EXCLUDE_UserScalarValueDataType) /// /// /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = TestData.Namespaces.TestData)] public partial class UserScalarValueDataType : IEncodeable { #region Constructors /// /// The default constructor. /// public UserScalarValueDataType() { Initialize(); } /// /// Called by the .NET framework during deserialization. /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { m_booleanDataType = true; m_sByteDataType = (sbyte)0; m_byteDataType = (byte)0; m_int16DataType = (short)0; m_uInt16DataType = (ushort)0; m_int32DataType = (int)0; m_uInt32DataType = (uint)0; m_int64DataType = (long)0; m_uInt64DataType = (ulong)0; m_floatDataType = (float)0; m_doubleDataType = (double)0; m_stringDataType = null; m_dateTimeDataType = DateTime.MinValue; m_guidDataType = Uuid.Empty; m_byteStringDataType = null; m_xmlElementDataType = null; m_nodeIdDataType = null; m_expandedNodeIdDataType = null; m_qualifiedNameDataType = null; m_localizedTextDataType = null; m_statusCodeDataType = StatusCodes.Good; m_variantDataType = Variant.Null; } #endregion #region Public Properties /// [DataMember(Name = "BooleanDataType", IsRequired = false, Order = 1)] public bool BooleanDataType { get { return m_booleanDataType; } set { m_booleanDataType = value; } } /// [DataMember(Name = "SByteDataType", IsRequired = false, Order = 2)] public sbyte SByteDataType { get { return m_sByteDataType; } set { m_sByteDataType = value; } } /// [DataMember(Name = "ByteDataType", IsRequired = false, Order = 3)] public byte ByteDataType { get { return m_byteDataType; } set { m_byteDataType = value; } } /// [DataMember(Name = "Int16DataType", IsRequired = false, Order = 4)] public short Int16DataType { get { return m_int16DataType; } set { m_int16DataType = value; } } /// [DataMember(Name = "UInt16DataType", IsRequired = false, Order = 5)] public ushort UInt16DataType { get { return m_uInt16DataType; } set { m_uInt16DataType = value; } } /// [DataMember(Name = "Int32DataType", IsRequired = false, Order = 6)] public int Int32DataType { get { return m_int32DataType; } set { m_int32DataType = value; } } /// [DataMember(Name = "UInt32DataType", IsRequired = false, Order = 7)] public uint UInt32DataType { get { return m_uInt32DataType; } set { m_uInt32DataType = value; } } /// [DataMember(Name = "Int64DataType", IsRequired = false, Order = 8)] public long Int64DataType { get { return m_int64DataType; } set { m_int64DataType = value; } } /// [DataMember(Name = "UInt64DataType", IsRequired = false, Order = 9)] public ulong UInt64DataType { get { return m_uInt64DataType; } set { m_uInt64DataType = value; } } /// [DataMember(Name = "FloatDataType", IsRequired = false, Order = 10)] public float FloatDataType { get { return m_floatDataType; } set { m_floatDataType = value; } } /// [DataMember(Name = "DoubleDataType", IsRequired = false, Order = 11)] public double DoubleDataType { get { return m_doubleDataType; } set { m_doubleDataType = value; } } /// [DataMember(Name = "StringDataType", IsRequired = false, Order = 12)] public string StringDataType { get { return m_stringDataType; } set { m_stringDataType = value; } } /// [DataMember(Name = "DateTimeDataType", IsRequired = false, Order = 13)] public DateTime DateTimeDataType { get { return m_dateTimeDataType; } set { m_dateTimeDataType = value; } } /// [DataMember(Name = "GuidDataType", IsRequired = false, Order = 14)] public Uuid GuidDataType { get { return m_guidDataType; } set { m_guidDataType = value; } } /// [DataMember(Name = "ByteStringDataType", IsRequired = false, Order = 15)] public byte[] ByteStringDataType { get { return m_byteStringDataType; } set { m_byteStringDataType = value; } } /// [DataMember(Name = "XmlElementDataType", IsRequired = false, Order = 16)] public XmlElement XmlElementDataType { get { return m_xmlElementDataType; } set { m_xmlElementDataType = value; } } /// [DataMember(Name = "NodeIdDataType", IsRequired = false, Order = 17)] public NodeId NodeIdDataType { get { return m_nodeIdDataType; } set { m_nodeIdDataType = value; } } /// [DataMember(Name = "ExpandedNodeIdDataType", IsRequired = false, Order = 18)] public ExpandedNodeId ExpandedNodeIdDataType { get { return m_expandedNodeIdDataType; } set { m_expandedNodeIdDataType = value; } } /// [DataMember(Name = "QualifiedNameDataType", IsRequired = false, Order = 19)] public QualifiedName QualifiedNameDataType { get { return m_qualifiedNameDataType; } set { m_qualifiedNameDataType = value; } } /// [DataMember(Name = "LocalizedTextDataType", IsRequired = false, Order = 20)] public LocalizedText LocalizedTextDataType { get { return m_localizedTextDataType; } set { m_localizedTextDataType = value; } } /// [DataMember(Name = "StatusCodeDataType", IsRequired = false, Order = 21)] public StatusCode StatusCodeDataType { get { return m_statusCodeDataType; } set { m_statusCodeDataType = value; } } /// [DataMember(Name = "VariantDataType", IsRequired = false, Order = 22)] public Variant VariantDataType { get { return m_variantDataType; } set { m_variantDataType = value; } } #endregion #region IEncodeable Members /// public virtual ExpandedNodeId TypeId { get { return DataTypeIds.UserScalarValueDataType; } } /// public virtual ExpandedNodeId BinaryEncodingId { get { return ObjectIds.UserScalarValueDataType_Encoding_DefaultBinary; } } /// public virtual ExpandedNodeId XmlEncodingId { get { return ObjectIds.UserScalarValueDataType_Encoding_DefaultXml; } } /// public virtual void Encode(IEncoder encoder) { encoder.PushNamespace(TestData.Namespaces.TestData); encoder.WriteBoolean("BooleanDataType", BooleanDataType); encoder.WriteSByte("SByteDataType", SByteDataType); encoder.WriteByte("ByteDataType", ByteDataType); encoder.WriteInt16("Int16DataType", Int16DataType); encoder.WriteUInt16("UInt16DataType", UInt16DataType); encoder.WriteInt32("Int32DataType", Int32DataType); encoder.WriteUInt32("UInt32DataType", UInt32DataType); encoder.WriteInt64("Int64DataType", Int64DataType); encoder.WriteUInt64("UInt64DataType", UInt64DataType); encoder.WriteFloat("FloatDataType", FloatDataType); encoder.WriteDouble("DoubleDataType", DoubleDataType); encoder.WriteString("StringDataType", StringDataType); encoder.WriteDateTime("DateTimeDataType", DateTimeDataType); encoder.WriteGuid("GuidDataType", GuidDataType); encoder.WriteByteString("ByteStringDataType", ByteStringDataType); encoder.WriteXmlElement("XmlElementDataType", XmlElementDataType); encoder.WriteNodeId("NodeIdDataType", NodeIdDataType); encoder.WriteExpandedNodeId("ExpandedNodeIdDataType", ExpandedNodeIdDataType); encoder.WriteQualifiedName("QualifiedNameDataType", QualifiedNameDataType); encoder.WriteLocalizedText("LocalizedTextDataType", LocalizedTextDataType); encoder.WriteStatusCode("StatusCodeDataType", StatusCodeDataType); encoder.WriteVariant("VariantDataType", VariantDataType); encoder.PopNamespace(); } /// public virtual void Decode(IDecoder decoder) { decoder.PushNamespace(TestData.Namespaces.TestData); BooleanDataType = decoder.ReadBoolean("BooleanDataType"); SByteDataType = decoder.ReadSByte("SByteDataType"); ByteDataType = decoder.ReadByte("ByteDataType"); Int16DataType = decoder.ReadInt16("Int16DataType"); UInt16DataType = decoder.ReadUInt16("UInt16DataType"); Int32DataType = decoder.ReadInt32("Int32DataType"); UInt32DataType = decoder.ReadUInt32("UInt32DataType"); Int64DataType = decoder.ReadInt64("Int64DataType"); UInt64DataType = decoder.ReadUInt64("UInt64DataType"); FloatDataType = decoder.ReadFloat("FloatDataType"); DoubleDataType = decoder.ReadDouble("DoubleDataType"); StringDataType = decoder.ReadString("StringDataType"); DateTimeDataType = decoder.ReadDateTime("DateTimeDataType"); GuidDataType = decoder.ReadGuid("GuidDataType"); ByteStringDataType = decoder.ReadByteString("ByteStringDataType"); XmlElementDataType = decoder.ReadXmlElement("XmlElementDataType"); NodeIdDataType = decoder.ReadNodeId("NodeIdDataType"); ExpandedNodeIdDataType = decoder.ReadExpandedNodeId("ExpandedNodeIdDataType"); QualifiedNameDataType = decoder.ReadQualifiedName("QualifiedNameDataType"); LocalizedTextDataType = decoder.ReadLocalizedText("LocalizedTextDataType"); StatusCodeDataType = decoder.ReadStatusCode("StatusCodeDataType"); VariantDataType = decoder.ReadVariant("VariantDataType"); decoder.PopNamespace(); } /// public virtual bool IsEqual(IEncodeable encodeable) { if (Object.ReferenceEquals(this, encodeable)) { return true; } UserScalarValueDataType value = encodeable as UserScalarValueDataType; if (value == null) { return false; } if (!Utils.IsEqual(m_booleanDataType, value.m_booleanDataType)) return false; if (!Utils.IsEqual(m_sByteDataType, value.m_sByteDataType)) return false; if (!Utils.IsEqual(m_byteDataType, value.m_byteDataType)) return false; if (!Utils.IsEqual(m_int16DataType, value.m_int16DataType)) return false; if (!Utils.IsEqual(m_uInt16DataType, value.m_uInt16DataType)) return false; if (!Utils.IsEqual(m_int32DataType, value.m_int32DataType)) return false; if (!Utils.IsEqual(m_uInt32DataType, value.m_uInt32DataType)) return false; if (!Utils.IsEqual(m_int64DataType, value.m_int64DataType)) return false; if (!Utils.IsEqual(m_uInt64DataType, value.m_uInt64DataType)) return false; if (!Utils.IsEqual(m_floatDataType, value.m_floatDataType)) return false; if (!Utils.IsEqual(m_doubleDataType, value.m_doubleDataType)) return false; if (!Utils.IsEqual(m_stringDataType, value.m_stringDataType)) return false; if (!Utils.IsEqual(m_dateTimeDataType, value.m_dateTimeDataType)) return false; if (!Utils.IsEqual(m_guidDataType, value.m_guidDataType)) return false; if (!Utils.IsEqual(m_byteStringDataType, value.m_byteStringDataType)) return false; if (!Utils.IsEqual(m_xmlElementDataType, value.m_xmlElementDataType)) return false; if (!Utils.IsEqual(m_nodeIdDataType, value.m_nodeIdDataType)) return false; if (!Utils.IsEqual(m_expandedNodeIdDataType, value.m_expandedNodeIdDataType)) return false; if (!Utils.IsEqual(m_qualifiedNameDataType, value.m_qualifiedNameDataType)) return false; if (!Utils.IsEqual(m_localizedTextDataType, value.m_localizedTextDataType)) return false; if (!Utils.IsEqual(m_statusCodeDataType, value.m_statusCodeDataType)) return false; if (!Utils.IsEqual(m_variantDataType, value.m_variantDataType)) return false; return true; } #if !NET_STANDARD /// public virtual object Clone() { return (UserScalarValueDataType)this.MemberwiseClone(); } #endif /// public new object MemberwiseClone() { UserScalarValueDataType clone = (UserScalarValueDataType)base.MemberwiseClone(); clone.m_booleanDataType = (bool)Utils.Clone(this.m_booleanDataType); clone.m_sByteDataType = (sbyte)Utils.Clone(this.m_sByteDataType); clone.m_byteDataType = (byte)Utils.Clone(this.m_byteDataType); clone.m_int16DataType = (short)Utils.Clone(this.m_int16DataType); clone.m_uInt16DataType = (ushort)Utils.Clone(this.m_uInt16DataType); clone.m_int32DataType = (int)Utils.Clone(this.m_int32DataType); clone.m_uInt32DataType = (uint)Utils.Clone(this.m_uInt32DataType); clone.m_int64DataType = (long)Utils.Clone(this.m_int64DataType); clone.m_uInt64DataType = (ulong)Utils.Clone(this.m_uInt64DataType); clone.m_floatDataType = (float)Utils.Clone(this.m_floatDataType); clone.m_doubleDataType = (double)Utils.Clone(this.m_doubleDataType); clone.m_stringDataType = (string)Utils.Clone(this.m_stringDataType); clone.m_dateTimeDataType = (DateTime)Utils.Clone(this.m_dateTimeDataType); clone.m_guidDataType = (Uuid)Utils.Clone(this.m_guidDataType); clone.m_byteStringDataType = (byte[])Utils.Clone(this.m_byteStringDataType); clone.m_xmlElementDataType = (XmlElement)Utils.Clone(this.m_xmlElementDataType); clone.m_nodeIdDataType = (NodeId)Utils.Clone(this.m_nodeIdDataType); clone.m_expandedNodeIdDataType = (ExpandedNodeId)Utils.Clone(this.m_expandedNodeIdDataType); clone.m_qualifiedNameDataType = (QualifiedName)Utils.Clone(this.m_qualifiedNameDataType); clone.m_localizedTextDataType = (LocalizedText)Utils.Clone(this.m_localizedTextDataType); clone.m_statusCodeDataType = (StatusCode)Utils.Clone(this.m_statusCodeDataType); clone.m_variantDataType = (Variant)Utils.Clone(this.m_variantDataType); return clone; } #endregion #region Private Fields private bool m_booleanDataType; private sbyte m_sByteDataType; private byte m_byteDataType; private short m_int16DataType; private ushort m_uInt16DataType; private int m_int32DataType; private uint m_uInt32DataType; private long m_int64DataType; private ulong m_uInt64DataType; private float m_floatDataType; private double m_doubleDataType; private string m_stringDataType; private DateTime m_dateTimeDataType; private Uuid m_guidDataType; private byte[] m_byteStringDataType; private XmlElement m_xmlElementDataType; private NodeId m_nodeIdDataType; private ExpandedNodeId m_expandedNodeIdDataType; private QualifiedName m_qualifiedNameDataType; private LocalizedText m_localizedTextDataType; private StatusCode m_statusCodeDataType; private Variant m_variantDataType; #endregion } #region UserScalarValueDataTypeCollection Class /// /// A collection of UserScalarValueDataType objects. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfUserScalarValueDataType", Namespace = TestData.Namespaces.TestData, ItemName = "UserScalarValueDataType")] #if !NET_STANDARD public partial class UserScalarValueDataTypeCollection : List, ICloneable #else public partial class UserScalarValueDataTypeCollection : List #endif { #region Constructors /// /// Initializes the collection with default values. /// public UserScalarValueDataTypeCollection() { } /// /// Initializes the collection with an initial capacity. /// public UserScalarValueDataTypeCollection(int capacity) : base(capacity) { } /// /// Initializes the collection with another collection. /// public UserScalarValueDataTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// /// Converts an array to a collection. /// public static implicit operator UserScalarValueDataTypeCollection(UserScalarValueDataType[] values) { if (values != null) { return new UserScalarValueDataTypeCollection(values); } return new UserScalarValueDataTypeCollection(); } /// /// Converts a collection to an array. /// public static explicit operator UserScalarValueDataType[](UserScalarValueDataTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #if !NET_STANDARD #region ICloneable Methods /// /// Creates a deep copy of the collection. /// public object Clone() { return (UserScalarValueDataTypeCollection)this.MemberwiseClone(); } #endregion #endif /// public new object MemberwiseClone() { UserScalarValueDataTypeCollection clone = new UserScalarValueDataTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((UserScalarValueDataType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion #region UserArrayValueDataType Class #if (!OPCUA_EXCLUDE_UserArrayValueDataType) /// /// /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = TestData.Namespaces.TestData)] public partial class UserArrayValueDataType : IEncodeable { #region Constructors /// /// The default constructor. /// public UserArrayValueDataType() { Initialize(); } /// /// Called by the .NET framework during deserialization. /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { m_booleanDataType = new BooleanCollection(); m_sByteDataType = new SByteCollection(); m_byteDataType = new ByteCollection(); m_int16DataType = new Int16Collection(); m_uInt16DataType = new UInt16Collection(); m_int32DataType = new Int32Collection(); m_uInt32DataType = new UInt32Collection(); m_int64DataType = new Int64Collection(); m_uInt64DataType = new UInt64Collection(); m_floatDataType = new FloatCollection(); m_doubleDataType = new DoubleCollection(); m_stringDataType = new StringCollection(); m_dateTimeDataType = new DateTimeCollection(); m_guidDataType = new UuidCollection(); m_byteStringDataType = new ByteStringCollection(); m_xmlElementDataType = new XmlElementCollection(); m_nodeIdDataType = new NodeIdCollection(); m_expandedNodeIdDataType = new ExpandedNodeIdCollection(); m_qualifiedNameDataType = new QualifiedNameCollection(); m_localizedTextDataType = new LocalizedTextCollection(); m_statusCodeDataType = new StatusCodeCollection(); m_variantDataType = new VariantCollection(); } #endregion #region Public Properties /// /// /// [DataMember(Name = "BooleanDataType", IsRequired = false, Order = 1)] public BooleanCollection BooleanDataType { get { return m_booleanDataType; } set { m_booleanDataType = value; if (value == null) { m_booleanDataType = new BooleanCollection(); } } } /// /// /// [DataMember(Name = "SByteDataType", IsRequired = false, Order = 2)] public SByteCollection SByteDataType { get { return m_sByteDataType; } set { m_sByteDataType = value; if (value == null) { m_sByteDataType = new SByteCollection(); } } } /// /// /// [DataMember(Name = "ByteDataType", IsRequired = false, Order = 3)] public ByteCollection ByteDataType { get { return m_byteDataType; } set { m_byteDataType = value; if (value == null) { m_byteDataType = new ByteCollection(); } } } /// /// /// [DataMember(Name = "Int16DataType", IsRequired = false, Order = 4)] public Int16Collection Int16DataType { get { return m_int16DataType; } set { m_int16DataType = value; if (value == null) { m_int16DataType = new Int16Collection(); } } } /// /// /// [DataMember(Name = "UInt16DataType", IsRequired = false, Order = 5)] public UInt16Collection UInt16DataType { get { return m_uInt16DataType; } set { m_uInt16DataType = value; if (value == null) { m_uInt16DataType = new UInt16Collection(); } } } /// /// /// [DataMember(Name = "Int32DataType", IsRequired = false, Order = 6)] public Int32Collection Int32DataType { get { return m_int32DataType; } set { m_int32DataType = value; if (value == null) { m_int32DataType = new Int32Collection(); } } } /// /// /// [DataMember(Name = "UInt32DataType", IsRequired = false, Order = 7)] public UInt32Collection UInt32DataType { get { return m_uInt32DataType; } set { m_uInt32DataType = value; if (value == null) { m_uInt32DataType = new UInt32Collection(); } } } /// /// /// [DataMember(Name = "Int64DataType", IsRequired = false, Order = 8)] public Int64Collection Int64DataType { get { return m_int64DataType; } set { m_int64DataType = value; if (value == null) { m_int64DataType = new Int64Collection(); } } } /// /// /// [DataMember(Name = "UInt64DataType", IsRequired = false, Order = 9)] public UInt64Collection UInt64DataType { get { return m_uInt64DataType; } set { m_uInt64DataType = value; if (value == null) { m_uInt64DataType = new UInt64Collection(); } } } /// /// /// [DataMember(Name = "FloatDataType", IsRequired = false, Order = 10)] public FloatCollection FloatDataType { get { return m_floatDataType; } set { m_floatDataType = value; if (value == null) { m_floatDataType = new FloatCollection(); } } } /// /// /// [DataMember(Name = "DoubleDataType", IsRequired = false, Order = 11)] public DoubleCollection DoubleDataType { get { return m_doubleDataType; } set { m_doubleDataType = value; if (value == null) { m_doubleDataType = new DoubleCollection(); } } } /// /// /// [DataMember(Name = "StringDataType", IsRequired = false, Order = 12)] public StringCollection StringDataType { get { return m_stringDataType; } set { m_stringDataType = value; if (value == null) { m_stringDataType = new StringCollection(); } } } /// /// /// [DataMember(Name = "DateTimeDataType", IsRequired = false, Order = 13)] public DateTimeCollection DateTimeDataType { get { return m_dateTimeDataType; } set { m_dateTimeDataType = value; if (value == null) { m_dateTimeDataType = new DateTimeCollection(); } } } /// /// /// [DataMember(Name = "GuidDataType", IsRequired = false, Order = 14)] public UuidCollection GuidDataType { get { return m_guidDataType; } set { m_guidDataType = value; if (value == null) { m_guidDataType = new UuidCollection(); } } } /// /// /// [DataMember(Name = "ByteStringDataType", IsRequired = false, Order = 15)] public ByteStringCollection ByteStringDataType { get { return m_byteStringDataType; } set { m_byteStringDataType = value; if (value == null) { m_byteStringDataType = new ByteStringCollection(); } } } /// /// /// [DataMember(Name = "XmlElementDataType", IsRequired = false, Order = 16)] public XmlElementCollection XmlElementDataType { get { return m_xmlElementDataType; } set { m_xmlElementDataType = value; if (value == null) { m_xmlElementDataType = new XmlElementCollection(); } } } /// /// /// [DataMember(Name = "NodeIdDataType", IsRequired = false, Order = 17)] public NodeIdCollection NodeIdDataType { get { return m_nodeIdDataType; } set { m_nodeIdDataType = value; if (value == null) { m_nodeIdDataType = new NodeIdCollection(); } } } /// /// /// [DataMember(Name = "ExpandedNodeIdDataType", IsRequired = false, Order = 18)] public ExpandedNodeIdCollection ExpandedNodeIdDataType { get { return m_expandedNodeIdDataType; } set { m_expandedNodeIdDataType = value; if (value == null) { m_expandedNodeIdDataType = new ExpandedNodeIdCollection(); } } } /// /// /// [DataMember(Name = "QualifiedNameDataType", IsRequired = false, Order = 19)] public QualifiedNameCollection QualifiedNameDataType { get { return m_qualifiedNameDataType; } set { m_qualifiedNameDataType = value; if (value == null) { m_qualifiedNameDataType = new QualifiedNameCollection(); } } } /// /// /// [DataMember(Name = "LocalizedTextDataType", IsRequired = false, Order = 20)] public LocalizedTextCollection LocalizedTextDataType { get { return m_localizedTextDataType; } set { m_localizedTextDataType = value; if (value == null) { m_localizedTextDataType = new LocalizedTextCollection(); } } } /// /// /// [DataMember(Name = "StatusCodeDataType", IsRequired = false, Order = 21)] public StatusCodeCollection StatusCodeDataType { get { return m_statusCodeDataType; } set { m_statusCodeDataType = value; if (value == null) { m_statusCodeDataType = new StatusCodeCollection(); } } } /// /// /// [DataMember(Name = "VariantDataType", IsRequired = false, Order = 22)] public VariantCollection VariantDataType { get { return m_variantDataType; } set { m_variantDataType = value; if (value == null) { m_variantDataType = new VariantCollection(); } } } #endregion #region IEncodeable Members /// public virtual ExpandedNodeId TypeId { get { return DataTypeIds.UserArrayValueDataType; } } /// public virtual ExpandedNodeId BinaryEncodingId { get { return ObjectIds.UserArrayValueDataType_Encoding_DefaultBinary; } } /// public virtual ExpandedNodeId XmlEncodingId { get { return ObjectIds.UserArrayValueDataType_Encoding_DefaultXml; } } /// public virtual void Encode(IEncoder encoder) { encoder.PushNamespace(TestData.Namespaces.TestData); encoder.WriteBooleanArray("BooleanDataType", BooleanDataType); encoder.WriteSByteArray("SByteDataType", SByteDataType); encoder.WriteByteArray("ByteDataType", ByteDataType); encoder.WriteInt16Array("Int16DataType", Int16DataType); encoder.WriteUInt16Array("UInt16DataType", UInt16DataType); encoder.WriteInt32Array("Int32DataType", Int32DataType); encoder.WriteUInt32Array("UInt32DataType", UInt32DataType); encoder.WriteInt64Array("Int64DataType", Int64DataType); encoder.WriteUInt64Array("UInt64DataType", UInt64DataType); encoder.WriteFloatArray("FloatDataType", FloatDataType); encoder.WriteDoubleArray("DoubleDataType", DoubleDataType); encoder.WriteStringArray("StringDataType", StringDataType); encoder.WriteDateTimeArray("DateTimeDataType", DateTimeDataType); encoder.WriteGuidArray("GuidDataType", GuidDataType); encoder.WriteByteStringArray("ByteStringDataType", ByteStringDataType); encoder.WriteXmlElementArray("XmlElementDataType", XmlElementDataType); encoder.WriteNodeIdArray("NodeIdDataType", NodeIdDataType); encoder.WriteExpandedNodeIdArray("ExpandedNodeIdDataType", ExpandedNodeIdDataType); encoder.WriteQualifiedNameArray("QualifiedNameDataType", QualifiedNameDataType); encoder.WriteLocalizedTextArray("LocalizedTextDataType", LocalizedTextDataType); encoder.WriteStatusCodeArray("StatusCodeDataType", StatusCodeDataType); encoder.WriteVariantArray("VariantDataType", VariantDataType); encoder.PopNamespace(); } /// public virtual void Decode(IDecoder decoder) { decoder.PushNamespace(TestData.Namespaces.TestData); BooleanDataType = decoder.ReadBooleanArray("BooleanDataType"); SByteDataType = decoder.ReadSByteArray("SByteDataType"); ByteDataType = decoder.ReadByteArray("ByteDataType"); Int16DataType = decoder.ReadInt16Array("Int16DataType"); UInt16DataType = decoder.ReadUInt16Array("UInt16DataType"); Int32DataType = decoder.ReadInt32Array("Int32DataType"); UInt32DataType = decoder.ReadUInt32Array("UInt32DataType"); Int64DataType = decoder.ReadInt64Array("Int64DataType"); UInt64DataType = decoder.ReadUInt64Array("UInt64DataType"); FloatDataType = decoder.ReadFloatArray("FloatDataType"); DoubleDataType = decoder.ReadDoubleArray("DoubleDataType"); StringDataType = decoder.ReadStringArray("StringDataType"); DateTimeDataType = decoder.ReadDateTimeArray("DateTimeDataType"); GuidDataType = decoder.ReadGuidArray("GuidDataType"); ByteStringDataType = decoder.ReadByteStringArray("ByteStringDataType"); XmlElementDataType = decoder.ReadXmlElementArray("XmlElementDataType"); NodeIdDataType = decoder.ReadNodeIdArray("NodeIdDataType"); ExpandedNodeIdDataType = decoder.ReadExpandedNodeIdArray("ExpandedNodeIdDataType"); QualifiedNameDataType = decoder.ReadQualifiedNameArray("QualifiedNameDataType"); LocalizedTextDataType = decoder.ReadLocalizedTextArray("LocalizedTextDataType"); StatusCodeDataType = decoder.ReadStatusCodeArray("StatusCodeDataType"); VariantDataType = decoder.ReadVariantArray("VariantDataType"); decoder.PopNamespace(); } /// public virtual bool IsEqual(IEncodeable encodeable) { if (Object.ReferenceEquals(this, encodeable)) { return true; } UserArrayValueDataType value = encodeable as UserArrayValueDataType; if (value == null) { return false; } if (!Utils.IsEqual(m_booleanDataType, value.m_booleanDataType)) return false; if (!Utils.IsEqual(m_sByteDataType, value.m_sByteDataType)) return false; if (!Utils.IsEqual(m_byteDataType, value.m_byteDataType)) return false; if (!Utils.IsEqual(m_int16DataType, value.m_int16DataType)) return false; if (!Utils.IsEqual(m_uInt16DataType, value.m_uInt16DataType)) return false; if (!Utils.IsEqual(m_int32DataType, value.m_int32DataType)) return false; if (!Utils.IsEqual(m_uInt32DataType, value.m_uInt32DataType)) return false; if (!Utils.IsEqual(m_int64DataType, value.m_int64DataType)) return false; if (!Utils.IsEqual(m_uInt64DataType, value.m_uInt64DataType)) return false; if (!Utils.IsEqual(m_floatDataType, value.m_floatDataType)) return false; if (!Utils.IsEqual(m_doubleDataType, value.m_doubleDataType)) return false; if (!Utils.IsEqual(m_stringDataType, value.m_stringDataType)) return false; if (!Utils.IsEqual(m_dateTimeDataType, value.m_dateTimeDataType)) return false; if (!Utils.IsEqual(m_guidDataType, value.m_guidDataType)) return false; if (!Utils.IsEqual(m_byteStringDataType, value.m_byteStringDataType)) return false; if (!Utils.IsEqual(m_xmlElementDataType, value.m_xmlElementDataType)) return false; if (!Utils.IsEqual(m_nodeIdDataType, value.m_nodeIdDataType)) return false; if (!Utils.IsEqual(m_expandedNodeIdDataType, value.m_expandedNodeIdDataType)) return false; if (!Utils.IsEqual(m_qualifiedNameDataType, value.m_qualifiedNameDataType)) return false; if (!Utils.IsEqual(m_localizedTextDataType, value.m_localizedTextDataType)) return false; if (!Utils.IsEqual(m_statusCodeDataType, value.m_statusCodeDataType)) return false; if (!Utils.IsEqual(m_variantDataType, value.m_variantDataType)) return false; return true; } #if !NET_STANDARD /// public virtual object Clone() { return (UserArrayValueDataType)this.MemberwiseClone(); } #endif /// public new object MemberwiseClone() { UserArrayValueDataType clone = (UserArrayValueDataType)base.MemberwiseClone(); clone.m_booleanDataType = (BooleanCollection)Utils.Clone(this.m_booleanDataType); clone.m_sByteDataType = (SByteCollection)Utils.Clone(this.m_sByteDataType); clone.m_byteDataType = (ByteCollection)Utils.Clone(this.m_byteDataType); clone.m_int16DataType = (Int16Collection)Utils.Clone(this.m_int16DataType); clone.m_uInt16DataType = (UInt16Collection)Utils.Clone(this.m_uInt16DataType); clone.m_int32DataType = (Int32Collection)Utils.Clone(this.m_int32DataType); clone.m_uInt32DataType = (UInt32Collection)Utils.Clone(this.m_uInt32DataType); clone.m_int64DataType = (Int64Collection)Utils.Clone(this.m_int64DataType); clone.m_uInt64DataType = (UInt64Collection)Utils.Clone(this.m_uInt64DataType); clone.m_floatDataType = (FloatCollection)Utils.Clone(this.m_floatDataType); clone.m_doubleDataType = (DoubleCollection)Utils.Clone(this.m_doubleDataType); clone.m_stringDataType = (StringCollection)Utils.Clone(this.m_stringDataType); clone.m_dateTimeDataType = (DateTimeCollection)Utils.Clone(this.m_dateTimeDataType); clone.m_guidDataType = (UuidCollection)Utils.Clone(this.m_guidDataType); clone.m_byteStringDataType = (ByteStringCollection)Utils.Clone(this.m_byteStringDataType); clone.m_xmlElementDataType = (XmlElementCollection)Utils.Clone(this.m_xmlElementDataType); clone.m_nodeIdDataType = (NodeIdCollection)Utils.Clone(this.m_nodeIdDataType); clone.m_expandedNodeIdDataType = (ExpandedNodeIdCollection)Utils.Clone(this.m_expandedNodeIdDataType); clone.m_qualifiedNameDataType = (QualifiedNameCollection)Utils.Clone(this.m_qualifiedNameDataType); clone.m_localizedTextDataType = (LocalizedTextCollection)Utils.Clone(this.m_localizedTextDataType); clone.m_statusCodeDataType = (StatusCodeCollection)Utils.Clone(this.m_statusCodeDataType); clone.m_variantDataType = (VariantCollection)Utils.Clone(this.m_variantDataType); return clone; } #endregion #region Private Fields private BooleanCollection m_booleanDataType; private SByteCollection m_sByteDataType; private ByteCollection m_byteDataType; private Int16Collection m_int16DataType; private UInt16Collection m_uInt16DataType; private Int32Collection m_int32DataType; private UInt32Collection m_uInt32DataType; private Int64Collection m_int64DataType; private UInt64Collection m_uInt64DataType; private FloatCollection m_floatDataType; private DoubleCollection m_doubleDataType; private StringCollection m_stringDataType; private DateTimeCollection m_dateTimeDataType; private UuidCollection m_guidDataType; private ByteStringCollection m_byteStringDataType; private XmlElementCollection m_xmlElementDataType; private NodeIdCollection m_nodeIdDataType; private ExpandedNodeIdCollection m_expandedNodeIdDataType; private QualifiedNameCollection m_qualifiedNameDataType; private LocalizedTextCollection m_localizedTextDataType; private StatusCodeCollection m_statusCodeDataType; private VariantCollection m_variantDataType; #endregion } #region UserArrayValueDataTypeCollection Class /// /// A collection of UserArrayValueDataType objects. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfUserArrayValueDataType", Namespace = TestData.Namespaces.TestData, ItemName = "UserArrayValueDataType")] #if !NET_STANDARD public partial class UserArrayValueDataTypeCollection : List, ICloneable #else public partial class UserArrayValueDataTypeCollection : List #endif { #region Constructors /// /// Initializes the collection with default values. /// public UserArrayValueDataTypeCollection() { } /// /// Initializes the collection with an initial capacity. /// public UserArrayValueDataTypeCollection(int capacity) : base(capacity) { } /// /// Initializes the collection with another collection. /// public UserArrayValueDataTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// /// Converts an array to a collection. /// public static implicit operator UserArrayValueDataTypeCollection(UserArrayValueDataType[] values) { if (values != null) { return new UserArrayValueDataTypeCollection(values); } return new UserArrayValueDataTypeCollection(); } /// /// Converts a collection to an array. /// public static explicit operator UserArrayValueDataType[](UserArrayValueDataTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #if !NET_STANDARD #region ICloneable Methods /// /// Creates a deep copy of the collection. /// public object Clone() { return (UserArrayValueDataTypeCollection)this.MemberwiseClone(); } #endregion #endif /// public new object MemberwiseClone() { UserArrayValueDataTypeCollection clone = new UserArrayValueDataTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((UserArrayValueDataType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion #region Vector Class #if (!OPCUA_EXCLUDE_Vector) /// /// /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = TestData.Namespaces.TestData)] public partial class Vector : IEncodeable { #region Constructors /// /// The default constructor. /// public Vector() { Initialize(); } /// /// Called by the .NET framework during deserialization. /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { m_x = (double)0; m_y = (double)0; m_z = (double)0; } #endregion #region Public Properties /// [DataMember(Name = "X", IsRequired = false, Order = 1)] public double X { get { return m_x; } set { m_x = value; } } /// [DataMember(Name = "Y", IsRequired = false, Order = 2)] public double Y { get { return m_y; } set { m_y = value; } } /// [DataMember(Name = "Z", IsRequired = false, Order = 3)] public double Z { get { return m_z; } set { m_z = value; } } #endregion #region IEncodeable Members /// public virtual ExpandedNodeId TypeId { get { return DataTypeIds.Vector; } } /// public virtual ExpandedNodeId BinaryEncodingId { get { return ObjectIds.Vector_Encoding_DefaultBinary; } } /// public virtual ExpandedNodeId XmlEncodingId { get { return ObjectIds.Vector_Encoding_DefaultXml; } } /// public virtual void Encode(IEncoder encoder) { encoder.PushNamespace(TestData.Namespaces.TestData); encoder.WriteDouble("X", X); encoder.WriteDouble("Y", Y); encoder.WriteDouble("Z", Z); encoder.PopNamespace(); } /// public virtual void Decode(IDecoder decoder) { decoder.PushNamespace(TestData.Namespaces.TestData); X = decoder.ReadDouble("X"); Y = decoder.ReadDouble("Y"); Z = decoder.ReadDouble("Z"); decoder.PopNamespace(); } /// public virtual bool IsEqual(IEncodeable encodeable) { if (Object.ReferenceEquals(this, encodeable)) { return true; } Vector value = encodeable as Vector; if (value == null) { return false; } if (!Utils.IsEqual(m_x, value.m_x)) return false; if (!Utils.IsEqual(m_y, value.m_y)) return false; if (!Utils.IsEqual(m_z, value.m_z)) return false; return true; } #if !NET_STANDARD /// public virtual object Clone() { return (Vector)this.MemberwiseClone(); } #endif /// public new object MemberwiseClone() { Vector clone = (Vector)base.MemberwiseClone(); clone.m_x = (double)Utils.Clone(this.m_x); clone.m_y = (double)Utils.Clone(this.m_y); clone.m_z = (double)Utils.Clone(this.m_z); return clone; } #endregion #region Private Fields private double m_x; private double m_y; private double m_z; #endregion } #region VectorCollection Class /// /// A collection of Vector objects. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfVector", Namespace = TestData.Namespaces.TestData, ItemName = "Vector")] #if !NET_STANDARD public partial class VectorCollection : List, ICloneable #else public partial class VectorCollection : List #endif { #region Constructors /// /// Initializes the collection with default values. /// public VectorCollection() { } /// /// Initializes the collection with an initial capacity. /// public VectorCollection(int capacity) : base(capacity) { } /// /// Initializes the collection with another collection. /// public VectorCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// /// Converts an array to a collection. /// public static implicit operator VectorCollection(Vector[] values) { if (values != null) { return new VectorCollection(values); } return new VectorCollection(); } /// /// Converts a collection to an array. /// public static explicit operator Vector[](VectorCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #if !NET_STANDARD #region ICloneable Methods /// /// Creates a deep copy of the collection. /// public object Clone() { return (VectorCollection)this.MemberwiseClone(); } #endregion #endif /// public new object MemberwiseClone() { VectorCollection clone = new VectorCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((Vector)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion #region WorkOrderStatusType Class #if (!OPCUA_EXCLUDE_WorkOrderStatusType) /// /// /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = TestData.Namespaces.TestData)] public partial class WorkOrderStatusType : IEncodeable { #region Constructors /// /// The default constructor. /// public WorkOrderStatusType() { Initialize(); } /// /// Called by the .NET framework during deserialization. /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { m_actor = null; m_timestamp = DateTime.MinValue; m_comment = null; } #endregion #region Public Properties /// [DataMember(Name = "Actor", IsRequired = false, Order = 1)] public string Actor { get { return m_actor; } set { m_actor = value; } } /// [DataMember(Name = "Timestamp", IsRequired = false, Order = 2)] public DateTime Timestamp { get { return m_timestamp; } set { m_timestamp = value; } } /// [DataMember(Name = "Comment", IsRequired = false, Order = 3)] public LocalizedText Comment { get { return m_comment; } set { m_comment = value; } } #endregion #region IEncodeable Members /// public virtual ExpandedNodeId TypeId { get { return DataTypeIds.WorkOrderStatusType; } } /// public virtual ExpandedNodeId BinaryEncodingId { get { return ObjectIds.WorkOrderStatusType_Encoding_DefaultBinary; } } /// public virtual ExpandedNodeId XmlEncodingId { get { return ObjectIds.WorkOrderStatusType_Encoding_DefaultXml; } } /// public virtual void Encode(IEncoder encoder) { encoder.PushNamespace(TestData.Namespaces.TestData); encoder.WriteString("Actor", Actor); encoder.WriteDateTime("Timestamp", Timestamp); encoder.WriteLocalizedText("Comment", Comment); encoder.PopNamespace(); } /// public virtual void Decode(IDecoder decoder) { decoder.PushNamespace(TestData.Namespaces.TestData); Actor = decoder.ReadString("Actor"); Timestamp = decoder.ReadDateTime("Timestamp"); Comment = decoder.ReadLocalizedText("Comment"); decoder.PopNamespace(); } /// public virtual bool IsEqual(IEncodeable encodeable) { if (Object.ReferenceEquals(this, encodeable)) { return true; } WorkOrderStatusType value = encodeable as WorkOrderStatusType; if (value == null) { return false; } if (!Utils.IsEqual(m_actor, value.m_actor)) return false; if (!Utils.IsEqual(m_timestamp, value.m_timestamp)) return false; if (!Utils.IsEqual(m_comment, value.m_comment)) return false; return true; } #if !NET_STANDARD /// public virtual object Clone() { return (WorkOrderStatusType)this.MemberwiseClone(); } #endif /// public new object MemberwiseClone() { WorkOrderStatusType clone = (WorkOrderStatusType)base.MemberwiseClone(); clone.m_actor = (string)Utils.Clone(this.m_actor); clone.m_timestamp = (DateTime)Utils.Clone(this.m_timestamp); clone.m_comment = (LocalizedText)Utils.Clone(this.m_comment); return clone; } #endregion #region Private Fields private string m_actor; private DateTime m_timestamp; private LocalizedText m_comment; #endregion } #region WorkOrderStatusTypeCollection Class /// /// A collection of WorkOrderStatusType objects. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfWorkOrderStatusType", Namespace = TestData.Namespaces.TestData, ItemName = "WorkOrderStatusType")] #if !NET_STANDARD public partial class WorkOrderStatusTypeCollection : List, ICloneable #else public partial class WorkOrderStatusTypeCollection : List #endif { #region Constructors /// /// Initializes the collection with default values. /// public WorkOrderStatusTypeCollection() { } /// /// Initializes the collection with an initial capacity. /// public WorkOrderStatusTypeCollection(int capacity) : base(capacity) { } /// /// Initializes the collection with another collection. /// public WorkOrderStatusTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// /// Converts an array to a collection. /// public static implicit operator WorkOrderStatusTypeCollection(WorkOrderStatusType[] values) { if (values != null) { return new WorkOrderStatusTypeCollection(values); } return new WorkOrderStatusTypeCollection(); } /// /// Converts a collection to an array. /// public static explicit operator WorkOrderStatusType[](WorkOrderStatusTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #if !NET_STANDARD #region ICloneable Methods /// /// Creates a deep copy of the collection. /// public object Clone() { return (WorkOrderStatusTypeCollection)this.MemberwiseClone(); } #endregion #endif /// public new object MemberwiseClone() { WorkOrderStatusTypeCollection clone = new WorkOrderStatusTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((WorkOrderStatusType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion #region WorkOrderType Class #if (!OPCUA_EXCLUDE_WorkOrderType) /// /// /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = TestData.Namespaces.TestData)] public partial class WorkOrderType : IEncodeable { #region Constructors /// /// The default constructor. /// public WorkOrderType() { Initialize(); } /// /// Called by the .NET framework during deserialization. /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { m_iD = Uuid.Empty; m_assetID = null; m_startTime = DateTime.MinValue; m_statusComments = new WorkOrderStatusTypeCollection(); } #endregion #region Public Properties /// [DataMember(Name = "ID", IsRequired = false, Order = 1)] public Uuid ID { get { return m_iD; } set { m_iD = value; } } /// [DataMember(Name = "AssetID", IsRequired = false, Order = 2)] public string AssetID { get { return m_assetID; } set { m_assetID = value; } } /// [DataMember(Name = "StartTime", IsRequired = false, Order = 3)] public DateTime StartTime { get { return m_startTime; } set { m_startTime = value; } } /// /// /// [DataMember(Name = "StatusComments", IsRequired = false, Order = 4)] public WorkOrderStatusTypeCollection StatusComments { get { return m_statusComments; } set { m_statusComments = value; if (value == null) { m_statusComments = new WorkOrderStatusTypeCollection(); } } } #endregion #region IEncodeable Members /// public virtual ExpandedNodeId TypeId { get { return DataTypeIds.WorkOrderType; } } /// public virtual ExpandedNodeId BinaryEncodingId { get { return ObjectIds.WorkOrderType_Encoding_DefaultBinary; } } /// public virtual ExpandedNodeId XmlEncodingId { get { return ObjectIds.WorkOrderType_Encoding_DefaultXml; } } /// public virtual void Encode(IEncoder encoder) { encoder.PushNamespace(TestData.Namespaces.TestData); encoder.WriteGuid("ID", ID); encoder.WriteString("AssetID", AssetID); encoder.WriteDateTime("StartTime", StartTime); encoder.WriteEncodeableArray("StatusComments", StatusComments.ToArray(), typeof(WorkOrderStatusType)); encoder.PopNamespace(); } /// public virtual void Decode(IDecoder decoder) { decoder.PushNamespace(TestData.Namespaces.TestData); ID = decoder.ReadGuid("ID"); AssetID = decoder.ReadString("AssetID"); StartTime = decoder.ReadDateTime("StartTime"); StatusComments = (WorkOrderStatusTypeCollection)decoder.ReadEncodeableArray("StatusComments", typeof(WorkOrderStatusType)); decoder.PopNamespace(); } /// public virtual bool IsEqual(IEncodeable encodeable) { if (Object.ReferenceEquals(this, encodeable)) { return true; } WorkOrderType value = encodeable as WorkOrderType; if (value == null) { return false; } if (!Utils.IsEqual(m_iD, value.m_iD)) return false; if (!Utils.IsEqual(m_assetID, value.m_assetID)) return false; if (!Utils.IsEqual(m_startTime, value.m_startTime)) return false; if (!Utils.IsEqual(m_statusComments, value.m_statusComments)) return false; return true; } #if !NET_STANDARD /// public virtual object Clone() { return (WorkOrderType)this.MemberwiseClone(); } #endif /// public new object MemberwiseClone() { WorkOrderType clone = (WorkOrderType)base.MemberwiseClone(); clone.m_iD = (Uuid)Utils.Clone(this.m_iD); clone.m_assetID = (string)Utils.Clone(this.m_assetID); clone.m_startTime = (DateTime)Utils.Clone(this.m_startTime); clone.m_statusComments = (WorkOrderStatusTypeCollection)Utils.Clone(this.m_statusComments); return clone; } #endregion #region Private Fields private Uuid m_iD; private string m_assetID; private DateTime m_startTime; private WorkOrderStatusTypeCollection m_statusComments; #endregion } #region WorkOrderTypeCollection Class /// /// A collection of WorkOrderType objects. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfWorkOrderType", Namespace = TestData.Namespaces.TestData, ItemName = "WorkOrderType")] #if !NET_STANDARD public partial class WorkOrderTypeCollection : List, ICloneable #else public partial class WorkOrderTypeCollection : List #endif { #region Constructors /// /// Initializes the collection with default values. /// public WorkOrderTypeCollection() { } /// /// Initializes the collection with an initial capacity. /// public WorkOrderTypeCollection(int capacity) : base(capacity) { } /// /// Initializes the collection with another collection. /// public WorkOrderTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// /// Converts an array to a collection. /// public static implicit operator WorkOrderTypeCollection(WorkOrderType[] values) { if (values != null) { return new WorkOrderTypeCollection(values); } return new WorkOrderTypeCollection(); } /// /// Converts a collection to an array. /// public static explicit operator WorkOrderType[](WorkOrderTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #if !NET_STANDARD #region ICloneable Methods /// /// Creates a deep copy of the collection. /// public object Clone() { return (WorkOrderTypeCollection)this.MemberwiseClone(); } #endregion #endif /// public new object MemberwiseClone() { WorkOrderTypeCollection clone = new WorkOrderTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((WorkOrderType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/TestData/Design/TestData.NodeIds.csv ================================================ AnalogArrayValueObjectType,9763,ObjectType AnalogScalarValueObjectType,9534,ObjectType ArrayValueDataType,9669,DataType ArrayValueDataType_Encoding_DefaultBinary,11438,Object ArrayValueDataType_Encoding_DefaultJson,15048,Object ArrayValueDataType_Encoding_DefaultXml,11419,Object ArrayValueObjectType,9679,ObjectType BooleanDataType,9898,DataType ByteDataType,9900,DataType ByteStringDataType,9912,DataType Data,10157,Object DateTimeDataType,9910,DataType DoubleDataType,9908,DataType ExpandedNodeIdDataType,9915,DataType FloatDataType,9907,DataType GenerateValuesEventType,9371,ObjectType GuidDataType,9911,DataType Int16DataType,9901,DataType Int32DataType,9903,DataType Int64DataType,9905,DataType LocalizedTextDataType,9917,DataType MethodTestType,10092,ObjectType NodeIdDataType,9914,DataType QualifiedNameDataType,9916,DataType SByteDataType,9899,DataType ScalarValueDataType,9440,DataType ScalarValueDataType_Encoding_DefaultBinary,11437,Object ScalarValueDataType_Encoding_DefaultJson,15047,Object ScalarValueDataType_Encoding_DefaultXml,11418,Object ScalarValueObjectType,9450,ObjectType StatusCodeDataType,9918,DataType StringDataType,9909,DataType TestData_BinarySchema,11422,Variable TestData_XmlSchema,11441,Variable TestDataObjectType,9383,ObjectType TestSystemConditionType,10123,ObjectType UInt16DataType,9902,DataType UInt32DataType,9904,DataType UInt64DataType,9906,DataType UserArrayValueDataType,10006,DataType UserArrayValueDataType_Encoding_DefaultBinary,11440,Object UserArrayValueDataType_Encoding_DefaultJson,15050,Object UserArrayValueDataType_Encoding_DefaultXml,11421,Object UserArrayValueObjectType,10007,ObjectType UserScalarValueDataType,9920,DataType UserScalarValueDataType_Encoding_DefaultBinary,11439,Object UserScalarValueDataType_Encoding_DefaultJson,15049,Object UserScalarValueDataType_Encoding_DefaultXml,11420,Object UserScalarValueObjectType,9921,ObjectType VariantDataType,9919,DataType Vector,1000,DataType Vector_Encoding_DefaultBinary,1008,Object Vector_Encoding_DefaultJson,64,Object Vector_Encoding_DefaultXml,36,Object WorkOrderStatusType,1004,DataType WorkOrderStatusType_Encoding_DefaultBinary,1011,Object WorkOrderStatusType_Encoding_DefaultJson,67,Object WorkOrderStatusType_Encoding_DefaultXml,39,Object WorkOrderType,1005,DataType WorkOrderType_Encoding_DefaultBinary,1012,Object WorkOrderType_Encoding_DefaultJson,68,Object WorkOrderType_Encoding_DefaultXml,40,Object XmlElementDataType,9913,DataType ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/TestData/Design/TestData.NodeSet.xml ================================================  http://opcfoundation.org/UA/ http://test.org/UA/Data/ ns=1;i=24 Variable_2 1 WorkOrderStatusType WorkOrderStatusType 0 0 0 i=47 true ns=1;i=11422 i=40 false i=69 WorkOrderStatusType i=12 -1 1 1 0 false 0 ns=1;i=27 Variable_2 1 WorkOrderType WorkOrderType 0 0 0 i=47 true ns=1;i=11422 i=40 false i=69 WorkOrderType i=12 -1 1 1 0 false 0 ns=1;i=36 Object_1 0 Default XML Default XML 0 0 0 i=40 false i=76 i=38 true ns=1;i=1000 i=39 false ns=1;i=43 0 ns=1;i=39 Object_1 0 Default XML Default XML 0 0 0 i=40 false i=76 i=38 true ns=1;i=1004 i=39 false ns=1;i=52 0 ns=1;i=40 Object_1 0 Default XML Default XML 0 0 0 i=40 false i=76 i=38 true ns=1;i=1005 i=39 false ns=1;i=55 0 ns=1;i=43 Variable_2 1 Vector Vector 0 0 0 i=47 true ns=1;i=11441 i=40 false i=69 //xs:element[@name='Vector'] i=12 -1 1 1 0 false 0 ns=1;i=52 Variable_2 1 WorkOrderStatusType WorkOrderStatusType 0 0 0 i=47 true ns=1;i=11441 i=40 false i=69 //xs:element[@name='WorkOrderStatusType'] i=12 -1 1 1 0 false 0 ns=1;i=55 Variable_2 1 WorkOrderType WorkOrderType 0 0 0 i=47 true ns=1;i=11441 i=40 false i=69 //xs:element[@name='WorkOrderType'] i=12 -1 1 1 0 false 0 ns=1;i=64 Object_1 0 Default JSON Default JSON 0 0 0 i=40 false i=76 i=38 true ns=1;i=1000 0 ns=1;i=67 Object_1 0 Default JSON Default JSON 0 0 0 i=40 false i=76 i=38 true ns=1;i=1004 0 ns=1;i=68 Object_1 0 Default JSON Default JSON 0 0 0 i=40 false i=76 i=38 true ns=1;i=1005 0 ns=1;i=1000 DataType_64 1 Vector Vector 0 0 0 i=45 true i=22 i=38 false ns=1;i=1008 i=38 false ns=1;i=36 i=38 false ns=1;i=64 false ns=1;i=1004 DataType_64 1 WorkOrderStatusType WorkOrderStatusType 0 0 0 i=45 true i=22 i=38 false ns=1;i=1011 i=38 false ns=1;i=39 i=38 false ns=1;i=67 false ns=1;i=1005 DataType_64 1 WorkOrderType WorkOrderType 0 0 0 i=45 true i=22 i=38 false ns=1;i=1012 i=38 false ns=1;i=40 i=38 false ns=1;i=68 false ns=1;i=1008 Object_1 0 Default Binary Default Binary 0 0 0 i=40 false i=76 i=38 true ns=1;i=1000 i=39 false ns=1;i=1015 0 ns=1;i=1011 Object_1 0 Default Binary Default Binary 0 0 0 i=40 false i=76 i=38 true ns=1;i=1004 i=39 false ns=1;i=24 0 ns=1;i=1012 Object_1 0 Default Binary Default Binary 0 0 0 i=40 false i=76 i=38 true ns=1;i=1005 i=39 false ns=1;i=27 0 ns=1;i=1015 Variable_2 1 Vector Vector 0 0 0 i=47 true ns=1;i=11422 i=40 false i=69 Vector i=12 -1 1 1 0 false 0 ns=1;i=9371 ObjectType_8 1 GenerateValuesEventType GenerateValuesEventType 0 0 0 i=45 true i=2041 i=46 false ns=1;i=9381 i=46 false ns=1;i=9382 false ns=1;i=9381 Variable_2 1 Iterations Iterations 0 0 0 i=46 true ns=1;i=9371 i=40 false i=68 i=37 false i=78 0 i=7 -1 1 1 0 false 0 ns=1;i=9382 Variable_2 1 NewValueCount NewValueCount 0 0 0 i=46 true ns=1;i=9371 i=40 false i=68 i=37 false i=78 0 i=7 -1 1 1 0 false 0 ns=1;i=9383 ObjectType_8 1 TestDataObjectType TestDataObjectType 0 0 0 i=45 true i=58 i=36 false ns=1;i=9387 i=46 false ns=1;i=9384 i=47 false ns=1;i=9385 i=47 false ns=1;i=9387 i=45 false ns=1;i=9450 i=45 false ns=1;i=9534 i=45 false ns=1;i=9679 i=45 false ns=1;i=9763 i=45 false ns=1;i=9921 i=45 false ns=1;i=10007 false ns=1;i=9384 Variable_2 1 SimulationActive SimulationActive If true the server will produce new values for each monitored variable. 0 0 0 i=46 true ns=1;i=9383 i=40 false i=68 i=37 false i=78 false i=1 -1 1 1 0 false 0 ns=1;i=9385 Method_4 1 GenerateValues GenerateValues 0 0 0 i=47 true ns=1;i=9383 i=37 false i=78 i=46 false ns=1;i=9386 true true ns=1;i=9386 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=9385 i=40 false i=68 i=37 false i=78 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 0 false 0 ns=1;i=9387 Object_1 1 CycleComplete CycleComplete 0 0 0 i=47 true ns=1;i=9383 i=40 false i=2881 i=37 false i=78 i=36 true ns=1;i=9383 i=46 false ns=1;i=9388 i=46 false ns=1;i=9389 i=46 false ns=1;i=9390 i=46 false ns=1;i=9391 i=46 false ns=1;i=9392 i=46 false ns=1;i=9393 i=46 false ns=1;i=9395 i=46 false ns=1;i=9396 i=46 false ns=1;i=11578 i=46 false ns=1;i=11579 i=46 false ns=1;i=11557 i=46 false ns=1;i=9397 i=46 false ns=1;i=9398 i=47 false ns=1;i=9399 i=47 false ns=1;i=9405 i=47 false ns=1;i=9409 i=47 false ns=1;i=9411 i=46 false ns=1;i=9413 i=47 false ns=1;i=9415 i=47 false ns=1;i=9414 i=47 false ns=1;i=9416 i=47 false ns=1;i=9420 i=47 false ns=1;i=9436 0 ns=1;i=9388 Variable_2 0 EventId EventId 0 0 0 i=46 true ns=1;i=9387 i=40 false i=68 i=37 false i=78 i=15 -1 1 1 0 false 0 ns=1;i=9389 Variable_2 0 EventType EventType 0 0 0 i=46 true ns=1;i=9387 i=40 false i=68 i=37 false i=78 i=0 i=17 -1 1 1 0 false 0 ns=1;i=9390 Variable_2 0 SourceNode SourceNode 0 0 0 i=46 true ns=1;i=9387 i=40 false i=68 i=37 false i=78 i=0 i=17 -1 1 1 0 false 0 ns=1;i=9391 Variable_2 0 SourceName SourceName 0 0 0 i=46 true ns=1;i=9387 i=40 false i=68 i=37 false i=78 i=12 -1 1 1 0 false 0 ns=1;i=9392 Variable_2 0 Time Time 0 0 0 i=46 true ns=1;i=9387 i=40 false i=68 i=37 false i=78 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=9393 Variable_2 0 ReceiveTime ReceiveTime 0 0 0 i=46 true ns=1;i=9387 i=40 false i=68 i=37 false i=78 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=9395 Variable_2 0 Message Message 0 0 0 i=46 true ns=1;i=9387 i=40 false i=68 i=37 false i=78 i=21 -1 1 1 0 false 0 ns=1;i=9396 Variable_2 0 Severity Severity 0 0 0 i=46 true ns=1;i=9387 i=40 false i=68 i=37 false i=78 0 i=5 -1 1 1 0 false 0 ns=1;i=9397 Variable_2 0 BranchId BranchId 0 0 0 i=46 true ns=1;i=9387 i=40 false i=68 i=37 false i=78 i=0 i=17 -1 1 1 0 false 0 ns=1;i=9398 Variable_2 0 Retain Retain 0 0 0 i=46 true ns=1;i=9387 i=40 false i=68 i=37 false i=78 false i=1 -1 1 1 0 false 0 ns=1;i=9399 Variable_2 0 EnabledState EnabledState 0 0 0 i=47 true ns=1;i=9387 i=40 false i=8995 i=37 false i=78 i=46 false ns=1;i=9400 i=21 -1 1 1 0 false 0 ns=1;i=9400 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=9399 i=40 false i=68 i=37 false i=78 false i=1 -1 1 1 0 false 0 ns=1;i=9405 Variable_2 0 Quality Quality 0 0 0 i=47 true ns=1;i=9387 i=40 false i=9002 i=37 false i=78 i=46 false ns=1;i=9406 0 i=19 -1 1 1 0 false 0 ns=1;i=9406 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=9405 i=40 false i=68 i=37 false i=78 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=9409 Variable_2 0 LastSeverity LastSeverity 0 0 0 i=47 true ns=1;i=9387 i=40 false i=9002 i=37 false i=78 i=46 false ns=1;i=9410 0 i=5 -1 1 1 0 false 0 ns=1;i=9410 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=9409 i=40 false i=68 i=37 false i=78 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=9411 Variable_2 0 Comment Comment 0 0 0 i=47 true ns=1;i=9387 i=40 false i=9002 i=37 false i=78 i=46 false ns=1;i=9412 i=21 -1 1 1 0 false 0 ns=1;i=9412 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=9411 i=40 false i=68 i=37 false i=78 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=9413 Variable_2 0 ClientUserId ClientUserId 0 0 0 i=46 true ns=1;i=9387 i=40 false i=68 i=37 false i=78 i=12 -1 1 1 0 false 0 ns=1;i=9414 Method_4 0 Enable Enable 0 0 0 i=47 true ns=1;i=9387 i=37 false i=78 i=3065 false i=2803 true true ns=1;i=9415 Method_4 0 Disable Disable 0 0 0 i=47 true ns=1;i=9387 i=37 false i=78 i=3065 false i=2803 true true ns=1;i=9416 Method_4 0 AddComment AddComment 0 0 0 i=47 true ns=1;i=9387 i=37 false i=78 i=3065 false i=2829 i=46 false ns=1;i=9417 true true ns=1;i=9417 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=9416 i=40 false i=68 i=37 false i=78 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=9420 Variable_2 0 AckedState AckedState 0 0 0 i=47 true ns=1;i=9387 i=40 false i=8995 i=37 false i=78 i=46 false ns=1;i=9421 i=21 -1 1 1 0 false 0 ns=1;i=9421 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=9420 i=40 false i=68 i=37 false i=78 false i=1 -1 1 1 0 false 0 ns=1;i=9436 Method_4 0 Acknowledge Acknowledge 0 0 0 i=47 true ns=1;i=9387 i=37 false i=78 i=3065 false i=8944 i=46 false ns=1;i=9437 true true ns=1;i=9437 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=9436 i=40 false i=68 i=37 false i=78 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=9440 DataType_64 1 ScalarValueDataType ScalarValueDataType 0 0 0 i=45 true i=22 i=38 false ns=1;i=11437 i=38 false ns=1;i=11418 i=38 false ns=1;i=15047 false ns=1;i=9450 ObjectType_8 1 ScalarValueObjectType ScalarValueObjectType 0 0 0 i=45 true ns=1;i=9383 i=47 false ns=1;i=9507 i=47 false ns=1;i=9508 i=47 false ns=1;i=9509 i=47 false ns=1;i=9510 i=47 false ns=1;i=9511 i=47 false ns=1;i=9512 i=47 false ns=1;i=9513 i=47 false ns=1;i=9514 i=47 false ns=1;i=9515 i=47 false ns=1;i=9516 i=47 false ns=1;i=9517 i=47 false ns=1;i=9518 i=47 false ns=1;i=9519 i=47 false ns=1;i=9520 i=47 false ns=1;i=9521 i=47 false ns=1;i=9522 i=47 false ns=1;i=9523 i=47 false ns=1;i=9524 i=47 false ns=1;i=9525 i=47 false ns=1;i=9526 i=47 false ns=1;i=9527 i=47 false ns=1;i=9528 i=47 false ns=1;i=9529 i=47 false ns=1;i=9530 i=47 false ns=1;i=9531 i=47 false ns=1;i=9532 i=47 false ns=1;i=9533 false ns=1;i=9507 Variable_2 1 BooleanValue BooleanValue 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 false i=1 -1 1 1 0 false 0 ns=1;i=9508 Variable_2 1 SByteValue SByteValue 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 0 i=2 -1 1 1 0 false 0 ns=1;i=9509 Variable_2 1 ByteValue ByteValue 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 0 i=3 -1 1 1 0 false 0 ns=1;i=9510 Variable_2 1 Int16Value Int16Value 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 0 i=4 -1 1 1 0 false 0 ns=1;i=9511 Variable_2 1 UInt16Value UInt16Value 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 0 i=5 -1 1 1 0 false 0 ns=1;i=9512 Variable_2 1 Int32Value Int32Value 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 0 i=6 -1 1 1 0 false 0 ns=1;i=9513 Variable_2 1 UInt32Value UInt32Value 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 0 i=7 -1 1 1 0 false 0 ns=1;i=9514 Variable_2 1 Int64Value Int64Value 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 0 i=8 -1 1 1 0 false 0 ns=1;i=9515 Variable_2 1 UInt64Value UInt64Value 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 0 i=9 -1 1 1 0 false 0 ns=1;i=9516 Variable_2 1 FloatValue FloatValue 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 0 i=10 -1 1 1 0 false 0 ns=1;i=9517 Variable_2 1 DoubleValue DoubleValue 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 0 i=11 -1 1 1 0 false 0 ns=1;i=9518 Variable_2 1 StringValue StringValue 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 i=12 -1 1 1 0 false 0 ns=1;i=9519 Variable_2 1 DateTimeValue DateTimeValue 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 0001-01-01T00:00:00 i=13 -1 1 1 0 false 0 ns=1;i=9520 Variable_2 1 GuidValue GuidValue 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 00000000-0000-0000-0000-000000000000 i=14 -1 1 1 0 false 0 ns=1;i=9521 Variable_2 1 ByteStringValue ByteStringValue 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 i=15 -1 1 1 0 false 0 ns=1;i=9522 Variable_2 1 XmlElementValue XmlElementValue 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 i=16 -1 1 1 0 false 0 ns=1;i=9523 Variable_2 1 NodeIdValue NodeIdValue 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 i=0 i=17 -1 1 1 0 false 0 ns=1;i=9524 Variable_2 1 ExpandedNodeIdValue ExpandedNodeIdValue 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 i=0 i=18 -1 1 1 0 false 0 ns=1;i=9525 Variable_2 1 QualifiedNameValue QualifiedNameValue 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 0 i=20 -1 1 1 0 false 0 ns=1;i=9526 Variable_2 1 LocalizedTextValue LocalizedTextValue 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 i=21 -1 1 1 0 false 0 ns=1;i=9527 Variable_2 1 StatusCodeValue StatusCodeValue 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 0 i=19 -1 1 1 0 false 0 ns=1;i=9528 Variable_2 1 VariantValue VariantValue 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 i=24 -1 1 1 0 false 0 ns=1;i=9529 Variable_2 1 EnumerationValue EnumerationValue 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 0 i=29 -1 1 1 0 false 0 ns=1;i=9530 Variable_2 1 StructureValue StructureValue 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 i=22 -1 1 1 0 false 0 ns=1;i=9531 Variable_2 1 NumberValue NumberValue 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 0 i=26 -1 1 1 0 false 0 ns=1;i=9532 Variable_2 1 IntegerValue IntegerValue 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 0 i=27 -1 1 1 0 false 0 ns=1;i=9533 Variable_2 1 UIntegerValue UIntegerValue 0 0 0 i=47 true ns=1;i=9450 i=40 false i=63 i=37 false i=78 0 i=28 -1 1 1 0 false 0 ns=1;i=9534 ObjectType_8 1 AnalogScalarValueObjectType AnalogScalarValueObjectType 0 0 0 i=45 true ns=1;i=9383 i=47 false ns=1;i=9591 i=47 false ns=1;i=9597 i=47 false ns=1;i=9603 i=47 false ns=1;i=9609 i=47 false ns=1;i=9615 i=47 false ns=1;i=9621 i=47 false ns=1;i=9627 i=47 false ns=1;i=9633 i=47 false ns=1;i=9639 i=47 false ns=1;i=9645 i=47 false ns=1;i=9651 i=47 false ns=1;i=9657 i=47 false ns=1;i=9663 false ns=1;i=9591 Variable_2 1 SByteValue SByteValue 0 0 0 i=47 true ns=1;i=9534 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9594 0 i=2 -1 1 1 0 false 0 ns=1;i=9594 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9591 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9597 Variable_2 1 ByteValue ByteValue 0 0 0 i=47 true ns=1;i=9534 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9600 0 i=3 -1 1 1 0 false 0 ns=1;i=9600 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9597 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9603 Variable_2 1 Int16Value Int16Value 0 0 0 i=47 true ns=1;i=9534 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9606 0 i=4 -1 1 1 0 false 0 ns=1;i=9606 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9603 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9609 Variable_2 1 UInt16Value UInt16Value 0 0 0 i=47 true ns=1;i=9534 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9612 0 i=5 -1 1 1 0 false 0 ns=1;i=9612 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9609 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9615 Variable_2 1 Int32Value Int32Value 0 0 0 i=47 true ns=1;i=9534 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9618 0 i=6 -1 1 1 0 false 0 ns=1;i=9618 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9615 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9621 Variable_2 1 UInt32Value UInt32Value 0 0 0 i=47 true ns=1;i=9534 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9624 0 i=7 -1 1 1 0 false 0 ns=1;i=9624 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9621 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9627 Variable_2 1 Int64Value Int64Value 0 0 0 i=47 true ns=1;i=9534 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9630 0 i=8 -1 1 1 0 false 0 ns=1;i=9630 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9627 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9633 Variable_2 1 UInt64Value UInt64Value 0 0 0 i=47 true ns=1;i=9534 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9636 0 i=9 -1 1 1 0 false 0 ns=1;i=9636 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9633 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9639 Variable_2 1 FloatValue FloatValue 0 0 0 i=47 true ns=1;i=9534 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9642 0 i=10 -1 1 1 0 false 0 ns=1;i=9642 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9639 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9645 Variable_2 1 DoubleValue DoubleValue 0 0 0 i=47 true ns=1;i=9534 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9648 0 i=11 -1 1 1 0 false 0 ns=1;i=9648 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9645 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9651 Variable_2 1 NumberValue NumberValue 0 0 0 i=47 true ns=1;i=9534 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9654 0 i=26 -1 1 1 0 false 0 ns=1;i=9654 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9651 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9657 Variable_2 1 IntegerValue IntegerValue 0 0 0 i=47 true ns=1;i=9534 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9660 0 i=27 -1 1 1 0 false 0 ns=1;i=9660 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9657 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9663 Variable_2 1 UIntegerValue UIntegerValue 0 0 0 i=47 true ns=1;i=9534 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9666 0 i=28 -1 1 1 0 false 0 ns=1;i=9666 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9663 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9669 DataType_64 1 ArrayValueDataType ArrayValueDataType 0 0 0 i=45 true i=22 i=38 false ns=1;i=11438 i=38 false ns=1;i=11419 i=38 false ns=1;i=15048 false ns=1;i=9679 ObjectType_8 1 ArrayValueObjectType ArrayValueObjectType 0 0 0 i=45 true ns=1;i=9383 i=47 false ns=1;i=9736 i=47 false ns=1;i=9737 i=47 false ns=1;i=9738 i=47 false ns=1;i=9739 i=47 false ns=1;i=9740 i=47 false ns=1;i=9741 i=47 false ns=1;i=9742 i=47 false ns=1;i=9743 i=47 false ns=1;i=9744 i=47 false ns=1;i=9745 i=47 false ns=1;i=9746 i=47 false ns=1;i=9747 i=47 false ns=1;i=9748 i=47 false ns=1;i=9749 i=47 false ns=1;i=9750 i=47 false ns=1;i=9751 i=47 false ns=1;i=9752 i=47 false ns=1;i=9753 i=47 false ns=1;i=9754 i=47 false ns=1;i=9755 i=47 false ns=1;i=9756 i=47 false ns=1;i=9757 i=47 false ns=1;i=9758 i=47 false ns=1;i=9759 i=47 false ns=1;i=9760 i=47 false ns=1;i=9761 i=47 false ns=1;i=9762 false ns=1;i=9736 Variable_2 1 BooleanValue BooleanValue 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=1 1 0 1 1 0 false 0 ns=1;i=9737 Variable_2 1 SByteValue SByteValue 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=2 1 0 1 1 0 false 0 ns=1;i=9738 Variable_2 1 ByteValue ByteValue 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=3 1 0 1 1 0 false 0 ns=1;i=9739 Variable_2 1 Int16Value Int16Value 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=4 1 0 1 1 0 false 0 ns=1;i=9740 Variable_2 1 UInt16Value UInt16Value 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=5 1 0 1 1 0 false 0 ns=1;i=9741 Variable_2 1 Int32Value Int32Value 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=6 1 0 1 1 0 false 0 ns=1;i=9742 Variable_2 1 UInt32Value UInt32Value 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=7 1 0 1 1 0 false 0 ns=1;i=9743 Variable_2 1 Int64Value Int64Value 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=8 1 0 1 1 0 false 0 ns=1;i=9744 Variable_2 1 UInt64Value UInt64Value 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=9 1 0 1 1 0 false 0 ns=1;i=9745 Variable_2 1 FloatValue FloatValue 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=10 1 0 1 1 0 false 0 ns=1;i=9746 Variable_2 1 DoubleValue DoubleValue 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=11 1 0 1 1 0 false 0 ns=1;i=9747 Variable_2 1 StringValue StringValue 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=12 1 0 1 1 0 false 0 ns=1;i=9748 Variable_2 1 DateTimeValue DateTimeValue 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=13 1 0 1 1 0 false 0 ns=1;i=9749 Variable_2 1 GuidValue GuidValue 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=14 1 0 1 1 0 false 0 ns=1;i=9750 Variable_2 1 ByteStringValue ByteStringValue 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=15 1 0 1 1 0 false 0 ns=1;i=9751 Variable_2 1 XmlElementValue XmlElementValue 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=16 1 0 1 1 0 false 0 ns=1;i=9752 Variable_2 1 NodeIdValue NodeIdValue 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=17 1 0 1 1 0 false 0 ns=1;i=9753 Variable_2 1 ExpandedNodeIdValue ExpandedNodeIdValue 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=18 1 0 1 1 0 false 0 ns=1;i=9754 Variable_2 1 QualifiedNameValue QualifiedNameValue 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=20 1 0 1 1 0 false 0 ns=1;i=9755 Variable_2 1 LocalizedTextValue LocalizedTextValue 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=21 1 0 1 1 0 false 0 ns=1;i=9756 Variable_2 1 StatusCodeValue StatusCodeValue 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=19 1 0 1 1 0 false 0 ns=1;i=9757 Variable_2 1 VariantValue VariantValue 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=24 1 0 1 1 0 false 0 ns=1;i=9758 Variable_2 1 EnumerationValue EnumerationValue 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=29 1 0 1 1 0 false 0 ns=1;i=9759 Variable_2 1 StructureValue StructureValue 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=22 1 0 1 1 0 false 0 ns=1;i=9760 Variable_2 1 NumberValue NumberValue 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=26 1 0 1 1 0 false 0 ns=1;i=9761 Variable_2 1 IntegerValue IntegerValue 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=27 1 0 1 1 0 false 0 ns=1;i=9762 Variable_2 1 UIntegerValue UIntegerValue 0 0 0 i=47 true ns=1;i=9679 i=40 false i=63 i=37 false i=78 i=28 1 0 1 1 0 false 0 ns=1;i=9763 ObjectType_8 1 AnalogArrayValueObjectType AnalogArrayValueObjectType 0 0 0 i=45 true ns=1;i=9383 i=47 false ns=1;i=9820 i=47 false ns=1;i=9826 i=47 false ns=1;i=9832 i=47 false ns=1;i=9838 i=47 false ns=1;i=9844 i=47 false ns=1;i=9850 i=47 false ns=1;i=9856 i=47 false ns=1;i=9862 i=47 false ns=1;i=9868 i=47 false ns=1;i=9874 i=47 false ns=1;i=9880 i=47 false ns=1;i=9886 i=47 false ns=1;i=9892 false ns=1;i=9820 Variable_2 1 SByteValue SByteValue 0 0 0 i=47 true ns=1;i=9763 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9823 i=2 1 0 1 1 0 false 0 ns=1;i=9823 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9820 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9826 Variable_2 1 ByteValue ByteValue 0 0 0 i=47 true ns=1;i=9763 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9829 i=3 1 0 1 1 0 false 0 ns=1;i=9829 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9826 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9832 Variable_2 1 Int16Value Int16Value 0 0 0 i=47 true ns=1;i=9763 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9835 i=4 1 0 1 1 0 false 0 ns=1;i=9835 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9832 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9838 Variable_2 1 UInt16Value UInt16Value 0 0 0 i=47 true ns=1;i=9763 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9841 i=5 1 0 1 1 0 false 0 ns=1;i=9841 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9838 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9844 Variable_2 1 Int32Value Int32Value 0 0 0 i=47 true ns=1;i=9763 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9847 i=6 1 0 1 1 0 false 0 ns=1;i=9847 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9844 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9850 Variable_2 1 UInt32Value UInt32Value 0 0 0 i=47 true ns=1;i=9763 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9853 i=7 1 0 1 1 0 false 0 ns=1;i=9853 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9850 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9856 Variable_2 1 Int64Value Int64Value 0 0 0 i=47 true ns=1;i=9763 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9859 i=8 1 0 1 1 0 false 0 ns=1;i=9859 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9856 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9862 Variable_2 1 UInt64Value UInt64Value 0 0 0 i=47 true ns=1;i=9763 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9865 i=9 1 0 1 1 0 false 0 ns=1;i=9865 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9862 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9868 Variable_2 1 FloatValue FloatValue 0 0 0 i=47 true ns=1;i=9763 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9871 i=10 1 0 1 1 0 false 0 ns=1;i=9871 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9868 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9874 Variable_2 1 DoubleValue DoubleValue 0 0 0 i=47 true ns=1;i=9763 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9877 i=11 1 0 1 1 0 false 0 ns=1;i=9877 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9874 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9880 Variable_2 1 NumberValue NumberValue 0 0 0 i=47 true ns=1;i=9763 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9883 i=26 1 0 1 1 0 false 0 ns=1;i=9883 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9880 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9886 Variable_2 1 IntegerValue IntegerValue 0 0 0 i=47 true ns=1;i=9763 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9889 i=27 1 0 1 1 0 false 0 ns=1;i=9889 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9886 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9892 Variable_2 1 UIntegerValue UIntegerValue 0 0 0 i=47 true ns=1;i=9763 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=9895 i=28 1 0 1 1 0 false 0 ns=1;i=9895 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=9892 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=9898 DataType_64 1 BooleanDataType BooleanDataType 0 0 0 i=45 true i=1 false ns=1;i=9899 DataType_64 1 SByteDataType SByteDataType 0 0 0 i=45 true i=2 false ns=1;i=9900 DataType_64 1 ByteDataType ByteDataType 0 0 0 i=45 true i=3 false ns=1;i=9901 DataType_64 1 Int16DataType Int16DataType 0 0 0 i=45 true i=4 false ns=1;i=9902 DataType_64 1 UInt16DataType UInt16DataType 0 0 0 i=45 true i=5 false ns=1;i=9903 DataType_64 1 Int32DataType Int32DataType 0 0 0 i=45 true i=6 false ns=1;i=9904 DataType_64 1 UInt32DataType UInt32DataType 0 0 0 i=45 true i=7 false ns=1;i=9905 DataType_64 1 Int64DataType Int64DataType 0 0 0 i=45 true i=8 false ns=1;i=9906 DataType_64 1 UInt64DataType UInt64DataType 0 0 0 i=45 true i=9 false ns=1;i=9907 DataType_64 1 FloatDataType FloatDataType 0 0 0 i=45 true i=10 false ns=1;i=9908 DataType_64 1 DoubleDataType DoubleDataType 0 0 0 i=45 true i=11 false ns=1;i=9909 DataType_64 1 StringDataType StringDataType 0 0 0 i=45 true i=12 false ns=1;i=9910 DataType_64 1 DateTimeDataType DateTimeDataType 0 0 0 i=45 true i=13 false ns=1;i=9911 DataType_64 1 GuidDataType GuidDataType 0 0 0 i=45 true i=14 false ns=1;i=9912 DataType_64 1 ByteStringDataType ByteStringDataType 0 0 0 i=45 true i=15 false ns=1;i=9913 DataType_64 1 XmlElementDataType XmlElementDataType 0 0 0 i=45 true i=16 false ns=1;i=9914 DataType_64 1 NodeIdDataType NodeIdDataType 0 0 0 i=45 true i=17 false ns=1;i=9915 DataType_64 1 ExpandedNodeIdDataType ExpandedNodeIdDataType 0 0 0 i=45 true i=18 false ns=1;i=9916 DataType_64 1 QualifiedNameDataType QualifiedNameDataType 0 0 0 i=45 true i=20 false ns=1;i=9917 DataType_64 1 LocalizedTextDataType LocalizedTextDataType 0 0 0 i=45 true i=21 false ns=1;i=9918 DataType_64 1 StatusCodeDataType StatusCodeDataType 0 0 0 i=45 true i=19 false ns=1;i=9919 DataType_64 1 VariantDataType VariantDataType 0 0 0 i=45 true i=24 false ns=1;i=9920 DataType_64 1 UserScalarValueDataType UserScalarValueDataType 0 0 0 i=45 true i=22 i=38 false ns=1;i=11439 i=38 false ns=1;i=11420 i=38 false ns=1;i=15049 false ns=1;i=9921 ObjectType_8 1 UserScalarValueObjectType UserScalarValueObjectType 0 0 0 i=45 true ns=1;i=9383 i=47 false ns=1;i=9978 i=47 false ns=1;i=9979 i=47 false ns=1;i=9980 i=47 false ns=1;i=9981 i=47 false ns=1;i=9982 i=47 false ns=1;i=9983 i=47 false ns=1;i=9984 i=47 false ns=1;i=9985 i=47 false ns=1;i=9986 i=47 false ns=1;i=9987 i=47 false ns=1;i=9988 i=47 false ns=1;i=9989 i=47 false ns=1;i=9990 i=47 false ns=1;i=9991 i=47 false ns=1;i=9992 i=47 false ns=1;i=9993 i=47 false ns=1;i=9994 i=47 false ns=1;i=9995 i=47 false ns=1;i=9996 i=47 false ns=1;i=9997 i=47 false ns=1;i=9998 i=47 false ns=1;i=9999 false ns=1;i=9978 Variable_2 1 BooleanValue BooleanValue 0 0 0 i=47 true ns=1;i=9921 i=40 false i=63 i=37 false i=78 ns=1;i=9898 -1 1 1 0 false 0 ns=1;i=9979 Variable_2 1 SByteValue SByteValue 0 0 0 i=47 true ns=1;i=9921 i=40 false i=63 i=37 false i=78 ns=1;i=9899 -1 1 1 0 false 0 ns=1;i=9980 Variable_2 1 ByteValue ByteValue 0 0 0 i=47 true ns=1;i=9921 i=40 false i=63 i=37 false i=78 ns=1;i=9900 -1 1 1 0 false 0 ns=1;i=9981 Variable_2 1 Int16Value Int16Value 0 0 0 i=47 true ns=1;i=9921 i=40 false i=63 i=37 false i=78 ns=1;i=9901 -1 1 1 0 false 0 ns=1;i=9982 Variable_2 1 UInt16Value UInt16Value 0 0 0 i=47 true ns=1;i=9921 i=40 false i=63 i=37 false i=78 ns=1;i=9902 -1 1 1 0 false 0 ns=1;i=9983 Variable_2 1 Int32Value Int32Value 0 0 0 i=47 true ns=1;i=9921 i=40 false i=63 i=37 false i=78 ns=1;i=9903 -1 1 1 0 false 0 ns=1;i=9984 Variable_2 1 UInt32Value UInt32Value 0 0 0 i=47 true ns=1;i=9921 i=40 false i=63 i=37 false i=78 ns=1;i=9904 -1 1 1 0 false 0 ns=1;i=9985 Variable_2 1 Int64Value Int64Value 0 0 0 i=47 true ns=1;i=9921 i=40 false i=63 i=37 false i=78 ns=1;i=9905 -1 1 1 0 false 0 ns=1;i=9986 Variable_2 1 UInt64Value UInt64Value 0 0 0 i=47 true ns=1;i=9921 i=40 false i=63 i=37 false i=78 ns=1;i=9906 -1 1 1 0 false 0 ns=1;i=9987 Variable_2 1 FloatValue FloatValue 0 0 0 i=47 true ns=1;i=9921 i=40 false i=63 i=37 false i=78 ns=1;i=9907 -1 1 1 0 false 0 ns=1;i=9988 Variable_2 1 DoubleValue DoubleValue 0 0 0 i=47 true ns=1;i=9921 i=40 false i=63 i=37 false i=78 ns=1;i=9908 -1 1 1 0 false 0 ns=1;i=9989 Variable_2 1 StringValue StringValue 0 0 0 i=47 true ns=1;i=9921 i=40 false i=63 i=37 false i=78 ns=1;i=9909 -1 1 1 0 false 0 ns=1;i=9990 Variable_2 1 DateTimeValue DateTimeValue 0 0 0 i=47 true ns=1;i=9921 i=40 false i=63 i=37 false i=78 ns=1;i=9910 -1 1 1 0 false 0 ns=1;i=9991 Variable_2 1 GuidValue GuidValue 0 0 0 i=47 true ns=1;i=9921 i=40 false i=63 i=37 false i=78 ns=1;i=9911 -1 1 1 0 false 0 ns=1;i=9992 Variable_2 1 ByteStringValue ByteStringValue 0 0 0 i=47 true ns=1;i=9921 i=40 false i=63 i=37 false i=78 ns=1;i=9912 -1 1 1 0 false 0 ns=1;i=9993 Variable_2 1 XmlElementValue XmlElementValue 0 0 0 i=47 true ns=1;i=9921 i=40 false i=63 i=37 false i=78 ns=1;i=9913 -1 1 1 0 false 0 ns=1;i=9994 Variable_2 1 NodeIdValue NodeIdValue 0 0 0 i=47 true ns=1;i=9921 i=40 false i=63 i=37 false i=78 ns=1;i=9914 -1 1 1 0 false 0 ns=1;i=9995 Variable_2 1 ExpandedNodeIdValue ExpandedNodeIdValue 0 0 0 i=47 true ns=1;i=9921 i=40 false i=63 i=37 false i=78 ns=1;i=9915 -1 1 1 0 false 0 ns=1;i=9996 Variable_2 1 QualifiedNameValue QualifiedNameValue 0 0 0 i=47 true ns=1;i=9921 i=40 false i=63 i=37 false i=78 ns=1;i=9916 -1 1 1 0 false 0 ns=1;i=9997 Variable_2 1 LocalizedTextValue LocalizedTextValue 0 0 0 i=47 true ns=1;i=9921 i=40 false i=63 i=37 false i=78 ns=1;i=9917 -1 1 1 0 false 0 ns=1;i=9998 Variable_2 1 StatusCodeValue StatusCodeValue 0 0 0 i=47 true ns=1;i=9921 i=40 false i=63 i=37 false i=78 ns=1;i=9918 -1 1 1 0 false 0 ns=1;i=9999 Variable_2 1 VariantValue VariantValue 0 0 0 i=47 true ns=1;i=9921 i=40 false i=63 i=37 false i=78 ns=1;i=9919 -1 1 1 0 false 0 ns=1;i=10006 DataType_64 1 UserArrayValueDataType UserArrayValueDataType 0 0 0 i=45 true i=22 i=38 false ns=1;i=11440 i=38 false ns=1;i=11421 i=38 false ns=1;i=15050 false ns=1;i=10007 ObjectType_8 1 UserArrayValueObjectType UserArrayValueObjectType 0 0 0 i=45 true ns=1;i=9383 i=47 false ns=1;i=10064 i=47 false ns=1;i=10065 i=47 false ns=1;i=10066 i=47 false ns=1;i=10067 i=47 false ns=1;i=10068 i=47 false ns=1;i=10069 i=47 false ns=1;i=10070 i=47 false ns=1;i=10071 i=47 false ns=1;i=10072 i=47 false ns=1;i=10073 i=47 false ns=1;i=10074 i=47 false ns=1;i=10075 i=47 false ns=1;i=10076 i=47 false ns=1;i=10077 i=47 false ns=1;i=10078 i=47 false ns=1;i=10079 i=47 false ns=1;i=10080 i=47 false ns=1;i=10081 i=47 false ns=1;i=10082 i=47 false ns=1;i=10083 i=47 false ns=1;i=10084 i=47 false ns=1;i=10085 false ns=1;i=10064 Variable_2 1 BooleanValue BooleanValue 0 0 0 i=47 true ns=1;i=10007 i=40 false i=63 i=37 false i=78 ns=1;i=9898 1 0 1 1 0 false 0 ns=1;i=10065 Variable_2 1 SByteValue SByteValue 0 0 0 i=47 true ns=1;i=10007 i=40 false i=63 i=37 false i=78 ns=1;i=9899 1 0 1 1 0 false 0 ns=1;i=10066 Variable_2 1 ByteValue ByteValue 0 0 0 i=47 true ns=1;i=10007 i=40 false i=63 i=37 false i=78 ns=1;i=9900 1 0 1 1 0 false 0 ns=1;i=10067 Variable_2 1 Int16Value Int16Value 0 0 0 i=47 true ns=1;i=10007 i=40 false i=63 i=37 false i=78 ns=1;i=9901 1 0 1 1 0 false 0 ns=1;i=10068 Variable_2 1 UInt16Value UInt16Value 0 0 0 i=47 true ns=1;i=10007 i=40 false i=63 i=37 false i=78 ns=1;i=9902 1 0 1 1 0 false 0 ns=1;i=10069 Variable_2 1 Int32Value Int32Value 0 0 0 i=47 true ns=1;i=10007 i=40 false i=63 i=37 false i=78 ns=1;i=9903 1 0 1 1 0 false 0 ns=1;i=10070 Variable_2 1 UInt32Value UInt32Value 0 0 0 i=47 true ns=1;i=10007 i=40 false i=63 i=37 false i=78 ns=1;i=9904 1 0 1 1 0 false 0 ns=1;i=10071 Variable_2 1 Int64Value Int64Value 0 0 0 i=47 true ns=1;i=10007 i=40 false i=63 i=37 false i=78 ns=1;i=9905 1 0 1 1 0 false 0 ns=1;i=10072 Variable_2 1 UInt64Value UInt64Value 0 0 0 i=47 true ns=1;i=10007 i=40 false i=63 i=37 false i=78 ns=1;i=9906 1 0 1 1 0 false 0 ns=1;i=10073 Variable_2 1 FloatValue FloatValue 0 0 0 i=47 true ns=1;i=10007 i=40 false i=63 i=37 false i=78 ns=1;i=9907 1 0 1 1 0 false 0 ns=1;i=10074 Variable_2 1 DoubleValue DoubleValue 0 0 0 i=47 true ns=1;i=10007 i=40 false i=63 i=37 false i=78 ns=1;i=9908 1 0 1 1 0 false 0 ns=1;i=10075 Variable_2 1 StringValue StringValue 0 0 0 i=47 true ns=1;i=10007 i=40 false i=63 i=37 false i=78 ns=1;i=9909 1 0 1 1 0 false 0 ns=1;i=10076 Variable_2 1 DateTimeValue DateTimeValue 0 0 0 i=47 true ns=1;i=10007 i=40 false i=63 i=37 false i=78 ns=1;i=9910 1 0 1 1 0 false 0 ns=1;i=10077 Variable_2 1 GuidValue GuidValue 0 0 0 i=47 true ns=1;i=10007 i=40 false i=63 i=37 false i=78 ns=1;i=9911 1 0 1 1 0 false 0 ns=1;i=10078 Variable_2 1 ByteStringValue ByteStringValue 0 0 0 i=47 true ns=1;i=10007 i=40 false i=63 i=37 false i=78 ns=1;i=9912 1 0 1 1 0 false 0 ns=1;i=10079 Variable_2 1 XmlElementValue XmlElementValue 0 0 0 i=47 true ns=1;i=10007 i=40 false i=63 i=37 false i=78 ns=1;i=9913 1 0 1 1 0 false 0 ns=1;i=10080 Variable_2 1 NodeIdValue NodeIdValue 0 0 0 i=47 true ns=1;i=10007 i=40 false i=63 i=37 false i=78 ns=1;i=9914 1 0 1 1 0 false 0 ns=1;i=10081 Variable_2 1 ExpandedNodeIdValue ExpandedNodeIdValue 0 0 0 i=47 true ns=1;i=10007 i=40 false i=63 i=37 false i=78 ns=1;i=9915 1 0 1 1 0 false 0 ns=1;i=10082 Variable_2 1 QualifiedNameValue QualifiedNameValue 0 0 0 i=47 true ns=1;i=10007 i=40 false i=63 i=37 false i=78 ns=1;i=9916 1 0 1 1 0 false 0 ns=1;i=10083 Variable_2 1 LocalizedTextValue LocalizedTextValue 0 0 0 i=47 true ns=1;i=10007 i=40 false i=63 i=37 false i=78 ns=1;i=9917 1 0 1 1 0 false 0 ns=1;i=10084 Variable_2 1 StatusCodeValue StatusCodeValue 0 0 0 i=47 true ns=1;i=10007 i=40 false i=63 i=37 false i=78 ns=1;i=9918 1 0 1 1 0 false 0 ns=1;i=10085 Variable_2 1 VariantValue VariantValue 0 0 0 i=47 true ns=1;i=10007 i=40 false i=63 i=37 false i=78 ns=1;i=9919 1 0 1 1 0 false 0 ns=1;i=10092 ObjectType_8 1 MethodTestType MethodTestType 0 0 0 i=45 true i=61 i=47 false ns=1;i=10093 i=47 false ns=1;i=10096 i=47 false ns=1;i=10099 i=47 false ns=1;i=10102 i=47 false ns=1;i=10105 i=47 false ns=1;i=10108 i=47 false ns=1;i=10111 i=47 false ns=1;i=10114 i=47 false ns=1;i=10117 i=47 false ns=1;i=10120 false ns=1;i=10093 Method_4 1 ScalarMethod1 ScalarMethod1 0 0 0 i=47 true ns=1;i=10092 i=37 false i=78 i=46 false ns=1;i=10094 i=46 false ns=1;i=10095 true true ns=1;i=10094 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10093 i=40 false i=68 i=37 false i=78 i=297 BooleanIn i=1 -1 i=297 SByteIn i=2 -1 i=297 ByteIn i=3 -1 i=297 Int16In i=4 -1 i=297 UInt16In i=5 -1 i=297 Int32In i=6 -1 i=297 UInt32In i=7 -1 i=297 Int64In i=8 -1 i=297 UInt64In i=9 -1 i=297 FloatIn i=10 -1 i=297 DoubleIn i=11 -1 i=296 1 0 1 1 0 false 0 ns=1;i=10095 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=10093 i=40 false i=68 i=37 false i=78 i=297 BooleanOut i=1 -1 i=297 SByteOut i=2 -1 i=297 ByteOut i=3 -1 i=297 Int16Out i=4 -1 i=297 UInt16Out i=5 -1 i=297 Int32Out i=6 -1 i=297 UInt32Out i=7 -1 i=297 Int64Out i=8 -1 i=297 UInt64Out i=9 -1 i=297 FloatOut i=10 -1 i=297 DoubleOut i=11 -1 i=296 1 0 1 1 0 false 0 ns=1;i=10096 Method_4 1 ScalarMethod2 ScalarMethod2 0 0 0 i=47 true ns=1;i=10092 i=37 false i=78 i=46 false ns=1;i=10097 i=46 false ns=1;i=10098 true true ns=1;i=10097 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10096 i=40 false i=68 i=37 false i=78 i=297 StringIn i=12 -1 i=297 DateTimeIn i=13 -1 i=297 GuidIn i=14 -1 i=297 ByteStringIn i=15 -1 i=297 XmlElementIn i=16 -1 i=297 NodeIdIn i=17 -1 i=297 ExpandedNodeIdIn i=18 -1 i=297 QualifiedNameIn i=20 -1 i=297 LocalizedTextIn i=21 -1 i=297 StatusCodeIn i=19 -1 i=296 1 0 1 1 0 false 0 ns=1;i=10098 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=10096 i=40 false i=68 i=37 false i=78 i=297 StringOut i=12 -1 i=297 DateTimeOut i=13 -1 i=297 GuidOut i=14 -1 i=297 ByteStringOut i=15 -1 i=297 XmlElementOut i=16 -1 i=297 NodeIdOut i=17 -1 i=297 ExpandedNodeIdOut i=18 -1 i=297 QualifiedNameOut i=20 -1 i=297 LocalizedTextOut i=21 -1 i=297 StatusCodeOut i=19 -1 i=296 1 0 1 1 0 false 0 ns=1;i=10099 Method_4 1 ScalarMethod3 ScalarMethod3 0 0 0 i=47 true ns=1;i=10092 i=37 false i=78 i=46 false ns=1;i=10100 i=46 false ns=1;i=10101 true true ns=1;i=10100 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10099 i=40 false i=68 i=37 false i=78 i=297 VariantIn i=24 -1 i=297 EnumerationIn i=29 -1 i=297 StructureIn i=22 -1 i=296 1 0 1 1 0 false 0 ns=1;i=10101 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=10099 i=40 false i=68 i=37 false i=78 i=297 VariantOut i=24 -1 i=297 EnumerationOut i=29 -1 i=297 StructureOut i=22 -1 i=296 1 0 1 1 0 false 0 ns=1;i=10102 Method_4 1 ArrayMethod1 ArrayMethod1 0 0 0 i=47 true ns=1;i=10092 i=37 false i=78 i=46 false ns=1;i=10103 i=46 false ns=1;i=10104 true true ns=1;i=10103 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10102 i=40 false i=68 i=37 false i=78 i=297 BooleanIn i=1 1 0 i=297 SByteIn i=2 1 0 i=297 ByteIn i=3 1 0 i=297 Int16In i=4 1 0 i=297 UInt16In i=5 1 0 i=297 Int32In i=6 1 0 i=297 UInt32In i=7 1 0 i=297 Int64In i=8 1 0 i=297 UInt64In i=9 1 0 i=297 FloatIn i=10 1 0 i=297 DoubleIn i=11 1 0 i=296 1 0 1 1 0 false 0 ns=1;i=10104 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=10102 i=40 false i=68 i=37 false i=78 i=297 BooleanOut i=1 1 0 i=297 SByteOut i=2 1 0 i=297 ByteOut i=3 1 0 i=297 Int16Out i=4 1 0 i=297 UInt16Out i=5 1 0 i=297 Int32Out i=6 1 0 i=297 UInt32Out i=7 1 0 i=297 Int64Out i=8 1 0 i=297 UInt64Out i=9 1 0 i=297 FloatOut i=10 1 0 i=297 DoubleOut i=11 1 0 i=296 1 0 1 1 0 false 0 ns=1;i=10105 Method_4 1 ArrayMethod2 ArrayMethod2 0 0 0 i=47 true ns=1;i=10092 i=37 false i=78 i=46 false ns=1;i=10106 i=46 false ns=1;i=10107 true true ns=1;i=10106 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10105 i=40 false i=68 i=37 false i=78 i=297 StringIn i=12 1 0 i=297 DateTimeIn i=13 1 0 i=297 GuidIn i=14 1 0 i=297 ByteStringIn i=15 1 0 i=297 XmlElementIn i=16 1 0 i=297 NodeIdIn i=17 1 0 i=297 ExpandedNodeIdIn i=18 1 0 i=297 QualifiedNameIn i=20 1 0 i=297 LocalizedTextIn i=21 1 0 i=297 StatusCodeIn i=19 1 0 i=296 1 0 1 1 0 false 0 ns=1;i=10107 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=10105 i=40 false i=68 i=37 false i=78 i=297 StringOut i=12 1 0 i=297 DateTimeOut i=13 1 0 i=297 GuidOut i=14 1 0 i=297 ByteStringOut i=15 1 0 i=297 XmlElementOut i=16 1 0 i=297 NodeIdOut i=17 1 0 i=297 ExpandedNodeIdOut i=18 1 0 i=297 QualifiedNameOut i=20 1 0 i=297 LocalizedTextOut i=21 1 0 i=297 StatusCodeOut i=19 1 0 i=296 1 0 1 1 0 false 0 ns=1;i=10108 Method_4 1 ArrayMethod3 ArrayMethod3 0 0 0 i=47 true ns=1;i=10092 i=37 false i=78 i=46 false ns=1;i=10109 i=46 false ns=1;i=10110 true true ns=1;i=10109 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10108 i=40 false i=68 i=37 false i=78 i=297 VariantIn i=24 1 0 i=297 EnumerationIn i=29 1 0 i=297 StructureIn i=22 1 0 i=296 1 0 1 1 0 false 0 ns=1;i=10110 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=10108 i=40 false i=68 i=37 false i=78 i=297 VariantOut i=24 1 0 i=297 EnumerationOut i=29 1 0 i=297 StructureOut i=22 1 0 i=296 1 0 1 1 0 false 0 ns=1;i=10111 Method_4 1 UserScalarMethod1 UserScalarMethod1 0 0 0 i=47 true ns=1;i=10092 i=37 false i=78 i=46 false ns=1;i=10112 i=46 false ns=1;i=10113 true true ns=1;i=10112 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10111 i=40 false i=68 i=37 false i=78 i=297 BooleanIn ns=1;i=9898 -1 i=297 SByteIn ns=1;i=9899 -1 i=297 ByteIn ns=1;i=9900 -1 i=297 Int16In ns=1;i=9901 -1 i=297 UInt16In ns=1;i=9902 -1 i=297 Int32In ns=1;i=9903 -1 i=297 UInt32In ns=1;i=9904 -1 i=297 Int64In ns=1;i=9905 -1 i=297 UInt64In ns=1;i=9906 -1 i=297 FloatIn ns=1;i=9907 -1 i=297 DoubleIn ns=1;i=9908 -1 i=297 StringIn ns=1;i=9909 -1 i=296 1 0 1 1 0 false 0 ns=1;i=10113 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=10111 i=40 false i=68 i=37 false i=78 i=297 BooleanOut ns=1;i=9898 -1 i=297 SByteOut ns=1;i=9899 -1 i=297 ByteOut ns=1;i=9900 -1 i=297 Int16Out ns=1;i=9901 -1 i=297 UInt16Out ns=1;i=9902 -1 i=297 Int32Out ns=1;i=9903 -1 i=297 UInt32Out ns=1;i=9904 -1 i=297 Int64Out ns=1;i=9905 -1 i=297 UInt64Out ns=1;i=9906 -1 i=297 FloatOut ns=1;i=9907 -1 i=297 DoubleOut ns=1;i=9908 -1 i=297 StringOut ns=1;i=9909 -1 i=296 1 0 1 1 0 false 0 ns=1;i=10114 Method_4 1 UserScalarMethod2 UserScalarMethod2 0 0 0 i=47 true ns=1;i=10092 i=37 false i=78 i=46 false ns=1;i=10115 i=46 false ns=1;i=10116 true true ns=1;i=10115 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10114 i=40 false i=68 i=37 false i=78 i=297 DateTimeIn ns=1;i=9910 -1 i=297 GuidIn ns=1;i=9911 -1 i=297 ByteStringIn ns=1;i=9912 -1 i=297 XmlElementIn ns=1;i=9913 -1 i=297 NodeIdIn ns=1;i=9914 -1 i=297 ExpandedNodeIdIn ns=1;i=9915 -1 i=297 QualifiedNameIn ns=1;i=9916 -1 i=297 LocalizedTextIn ns=1;i=9917 -1 i=297 StatusCodeIn ns=1;i=9918 -1 i=297 VariantIn ns=1;i=9919 -1 i=296 1 0 1 1 0 false 0 ns=1;i=10116 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=10114 i=40 false i=68 i=37 false i=78 i=297 DateTimeOut ns=1;i=9910 -1 i=297 GuidOut ns=1;i=9911 -1 i=297 ByteStringOut ns=1;i=9912 -1 i=297 XmlElementOut ns=1;i=9913 -1 i=297 NodeIdOut ns=1;i=9914 -1 i=297 ExpandedNodeIdOut ns=1;i=9915 -1 i=297 QualifiedNameOut ns=1;i=9916 -1 i=297 LocalizedTextOut ns=1;i=9917 -1 i=297 StatusCodeOut ns=1;i=9918 -1 i=297 VariantOut ns=1;i=9919 -1 i=296 1 0 1 1 0 false 0 ns=1;i=10117 Method_4 1 UserArrayMethod1 UserArrayMethod1 0 0 0 i=47 true ns=1;i=10092 i=37 false i=78 i=46 false ns=1;i=10118 i=46 false ns=1;i=10119 true true ns=1;i=10118 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10117 i=40 false i=68 i=37 false i=78 i=297 BooleanIn ns=1;i=9898 1 0 i=297 SByteIn ns=1;i=9899 1 0 i=297 ByteIn ns=1;i=9900 1 0 i=297 Int16In ns=1;i=9901 1 0 i=297 UInt16In ns=1;i=9902 1 0 i=297 Int32In ns=1;i=9903 1 0 i=297 UInt32In ns=1;i=9904 1 0 i=297 Int64In ns=1;i=9905 1 0 i=297 UInt64In ns=1;i=9906 1 0 i=297 FloatIn ns=1;i=9907 1 0 i=297 DoubleIn ns=1;i=9908 1 0 i=297 StringIn ns=1;i=9909 1 0 i=296 1 0 1 1 0 false 0 ns=1;i=10119 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=10117 i=40 false i=68 i=37 false i=78 i=297 BooleanOut ns=1;i=9898 1 0 i=297 SByteOut ns=1;i=9899 1 0 i=297 ByteOut ns=1;i=9900 1 0 i=297 Int16Out ns=1;i=9901 1 0 i=297 UInt16Out ns=1;i=9902 1 0 i=297 Int32Out ns=1;i=9903 1 0 i=297 UInt32Out ns=1;i=9904 1 0 i=297 Int64Out ns=1;i=9905 1 0 i=297 UInt64Out ns=1;i=9906 1 0 i=297 FloatOut ns=1;i=9907 1 0 i=297 DoubleOut ns=1;i=9908 1 0 i=297 StringOut ns=1;i=9909 1 0 i=296 1 0 1 1 0 false 0 ns=1;i=10120 Method_4 1 UserArrayMethod2 UserArrayMethod2 0 0 0 i=47 true ns=1;i=10092 i=37 false i=78 i=46 false ns=1;i=10121 i=46 false ns=1;i=10122 true true ns=1;i=10121 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10120 i=40 false i=68 i=37 false i=78 i=297 DateTimeIn ns=1;i=9910 1 0 i=297 GuidIn ns=1;i=9911 1 0 i=297 ByteStringIn ns=1;i=9912 1 0 i=297 XmlElementIn ns=1;i=9913 1 0 i=297 NodeIdIn ns=1;i=9914 1 0 i=297 ExpandedNodeIdIn ns=1;i=9915 1 0 i=297 QualifiedNameIn ns=1;i=9916 1 0 i=297 LocalizedTextIn ns=1;i=9917 1 0 i=297 StatusCodeIn ns=1;i=9918 1 0 i=297 VariantIn ns=1;i=9919 1 0 i=296 1 0 1 1 0 false 0 ns=1;i=10122 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=10120 i=40 false i=68 i=37 false i=78 i=297 DateTimeOut ns=1;i=9910 1 0 i=297 GuidOut ns=1;i=9911 1 0 i=297 ByteStringOut ns=1;i=9912 1 0 i=297 XmlElementOut ns=1;i=9913 1 0 i=297 NodeIdOut ns=1;i=9914 1 0 i=297 ExpandedNodeIdOut ns=1;i=9915 1 0 i=297 QualifiedNameOut ns=1;i=9916 1 0 i=297 LocalizedTextOut ns=1;i=9917 1 0 i=297 StatusCodeOut ns=1;i=9918 1 0 i=297 VariantOut ns=1;i=9919 1 0 i=296 1 0 1 1 0 false 0 ns=1;i=10123 ObjectType_8 1 TestSystemConditionType TestSystemConditionType 0 0 0 i=45 true i=2782 i=46 false ns=1;i=10156 false ns=1;i=10156 Variable_2 1 MonitoredNodeCount MonitoredNodeCount 0 0 0 i=46 true ns=1;i=10123 i=40 false i=68 i=37 false i=78 0 i=6 -1 1 1 0 false 0 ns=1;i=10157 Object_1 1 Data Data 0 0 0 i=40 false i=61 i=35 true i=85 i=48 true i=2253 i=48 false ns=1;i=10158 i=48 false ns=1;i=10786 i=47 false ns=1;i=10158 i=47 false ns=1;i=10786 i=47 false ns=1;i=11383 1 ns=1;i=10158 Object_1 1 Static Static 0 0 0 i=47 true ns=1;i=10157 i=40 false i=61 i=48 true ns=1;i=10157 i=36 false ns=1;i=10159 i=36 false ns=1;i=10243 i=47 false ns=1;i=10159 i=47 false ns=1;i=10243 i=47 false ns=1;i=10327 i=47 false ns=1;i=10406 i=47 false ns=1;i=10485 i=47 false ns=1;i=10620 i=47 false ns=1;i=10755 1 ns=1;i=10159 Object_1 1 Scalar Scalar 0 0 0 i=47 true ns=1;i=10158 i=40 false ns=1;i=9450 i=36 true ns=1;i=10158 i=36 false ns=1;i=10163 i=46 false ns=1;i=10160 i=47 false ns=1;i=10161 i=47 false ns=1;i=10163 i=47 false ns=1;i=10216 i=47 false ns=1;i=10217 i=47 false ns=1;i=10218 i=47 false ns=1;i=10219 i=47 false ns=1;i=10220 i=47 false ns=1;i=10221 i=47 false ns=1;i=10222 i=47 false ns=1;i=10223 i=47 false ns=1;i=10224 i=47 false ns=1;i=10225 i=47 false ns=1;i=10226 i=47 false ns=1;i=10227 i=47 false ns=1;i=10228 i=47 false ns=1;i=10229 i=47 false ns=1;i=10230 i=47 false ns=1;i=10231 i=47 false ns=1;i=10232 i=47 false ns=1;i=10233 i=47 false ns=1;i=10234 i=47 false ns=1;i=10235 i=47 false ns=1;i=10236 i=47 false ns=1;i=10237 i=47 false ns=1;i=10238 i=47 false ns=1;i=10239 i=47 false ns=1;i=10240 i=47 false ns=1;i=10241 i=47 false ns=1;i=10242 0 ns=1;i=10160 Variable_2 1 SimulationActive SimulationActive If true the server will produce new values for each monitored variable. 0 0 0 i=46 true ns=1;i=10159 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10161 Method_4 1 GenerateValues GenerateValues 0 0 0 i=47 true ns=1;i=10159 i=46 false ns=1;i=10162 true true ns=1;i=10162 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10161 i=40 false i=68 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 0 false 0 ns=1;i=10163 Object_1 1 CycleComplete CycleComplete 0 0 0 i=47 true ns=1;i=10159 i=40 false i=2881 i=36 true ns=1;i=10159 i=46 false ns=1;i=10164 i=46 false ns=1;i=10165 i=46 false ns=1;i=10166 i=46 false ns=1;i=10167 i=46 false ns=1;i=10168 i=46 false ns=1;i=10169 i=46 false ns=1;i=10171 i=46 false ns=1;i=10172 i=46 false ns=1;i=11594 i=46 false ns=1;i=11595 i=46 false ns=1;i=11565 i=46 false ns=1;i=10173 i=46 false ns=1;i=10174 i=47 false ns=1;i=10175 i=47 false ns=1;i=10181 i=47 false ns=1;i=10185 i=47 false ns=1;i=10187 i=46 false ns=1;i=10189 i=47 false ns=1;i=10191 i=47 false ns=1;i=10190 i=47 false ns=1;i=10192 i=47 false ns=1;i=10196 i=47 false ns=1;i=10212 0 ns=1;i=10164 Variable_2 0 EventId EventId 0 0 0 i=46 true ns=1;i=10163 i=40 false i=68 i=15 -1 1 1 0 false 0 ns=1;i=10165 Variable_2 0 EventType EventType 0 0 0 i=46 true ns=1;i=10163 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10166 Variable_2 0 SourceNode SourceNode 0 0 0 i=46 true ns=1;i=10163 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10167 Variable_2 0 SourceName SourceName 0 0 0 i=46 true ns=1;i=10163 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=10168 Variable_2 0 Time Time 0 0 0 i=46 true ns=1;i=10163 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10169 Variable_2 0 ReceiveTime ReceiveTime 0 0 0 i=46 true ns=1;i=10163 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10171 Variable_2 0 Message Message 0 0 0 i=46 true ns=1;i=10163 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=10172 Variable_2 0 Severity Severity 0 0 0 i=46 true ns=1;i=10163 i=40 false i=68 0 i=5 -1 1 1 0 false 0 ns=1;i=10173 Variable_2 0 BranchId BranchId 0 0 0 i=46 true ns=1;i=10163 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10174 Variable_2 0 Retain Retain 0 0 0 i=46 true ns=1;i=10163 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10175 Variable_2 0 EnabledState EnabledState 0 0 0 i=47 true ns=1;i=10163 i=40 false i=8995 i=9004 false ns=1;i=10196 i=9004 false ns=1;i=10204 i=46 false ns=1;i=10176 i=21 -1 1 1 0 false 0 ns=1;i=10176 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=10175 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10181 Variable_2 0 Quality Quality 0 0 0 i=47 true ns=1;i=10163 i=40 false i=9002 i=46 false ns=1;i=10182 0 i=19 -1 1 1 0 false 0 ns=1;i=10182 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10181 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10185 Variable_2 0 LastSeverity LastSeverity 0 0 0 i=47 true ns=1;i=10163 i=40 false i=9002 i=46 false ns=1;i=10186 0 i=5 -1 1 1 0 false 0 ns=1;i=10186 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10185 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10187 Variable_2 0 Comment Comment 0 0 0 i=47 true ns=1;i=10163 i=40 false i=9002 i=46 false ns=1;i=10188 i=21 -1 1 1 0 false 0 ns=1;i=10188 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10187 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10189 Variable_2 0 ClientUserId ClientUserId 0 0 0 i=46 true ns=1;i=10163 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=10190 Method_4 0 Enable Enable 0 0 0 i=47 true ns=1;i=10163 i=3065 false i=2803 true true ns=1;i=10191 Method_4 0 Disable Disable 0 0 0 i=47 true ns=1;i=10163 i=3065 false i=2803 true true ns=1;i=10192 Method_4 0 AddComment AddComment 0 0 0 i=47 true ns=1;i=10163 i=3065 false i=2829 i=46 false ns=1;i=10193 true true ns=1;i=10193 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10192 i=40 false i=68 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=10196 Variable_2 0 AckedState AckedState 0 0 0 i=47 true ns=1;i=10163 i=40 false i=8995 i=9004 true ns=1;i=10175 i=46 false ns=1;i=10197 i=21 -1 1 1 0 false 0 ns=1;i=10197 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=10196 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10212 Method_4 0 Acknowledge Acknowledge 0 0 0 i=47 true ns=1;i=10163 i=3065 false i=8944 i=46 false ns=1;i=10213 true true ns=1;i=10213 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10212 i=40 false i=68 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=10216 Variable_2 1 BooleanValue BooleanValue 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 false i=1 -1 1 1 0 false 0 ns=1;i=10217 Variable_2 1 SByteValue SByteValue 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 0 i=2 -1 1 1 0 false 0 ns=1;i=10218 Variable_2 1 ByteValue ByteValue 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 0 i=3 -1 1 1 0 false 0 ns=1;i=10219 Variable_2 1 Int16Value Int16Value 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 0 i=4 -1 1 1 0 false 0 ns=1;i=10220 Variable_2 1 UInt16Value UInt16Value 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 0 i=5 -1 1 1 0 false 0 ns=1;i=10221 Variable_2 1 Int32Value Int32Value 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 0 i=6 -1 1 1 0 false 0 ns=1;i=10222 Variable_2 1 UInt32Value UInt32Value 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 0 i=7 -1 1 1 0 false 0 ns=1;i=10223 Variable_2 1 Int64Value Int64Value 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 0 i=8 -1 1 1 0 false 0 ns=1;i=10224 Variable_2 1 UInt64Value UInt64Value 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 0 i=9 -1 1 1 0 false 0 ns=1;i=10225 Variable_2 1 FloatValue FloatValue 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 0 i=10 -1 1 1 0 false 0 ns=1;i=10226 Variable_2 1 DoubleValue DoubleValue 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 0 i=11 -1 1 1 0 false 0 ns=1;i=10227 Variable_2 1 StringValue StringValue 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 i=12 -1 1 1 0 false 0 ns=1;i=10228 Variable_2 1 DateTimeValue DateTimeValue 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 0001-01-01T00:00:00 i=13 -1 1 1 0 false 0 ns=1;i=10229 Variable_2 1 GuidValue GuidValue 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 00000000-0000-0000-0000-000000000000 i=14 -1 1 1 0 false 0 ns=1;i=10230 Variable_2 1 ByteStringValue ByteStringValue 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 i=15 -1 1 1 0 false 0 ns=1;i=10231 Variable_2 1 XmlElementValue XmlElementValue 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 i=16 -1 1 1 0 false 0 ns=1;i=10232 Variable_2 1 NodeIdValue NodeIdValue 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10233 Variable_2 1 ExpandedNodeIdValue ExpandedNodeIdValue 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 i=0 i=18 -1 1 1 0 false 0 ns=1;i=10234 Variable_2 1 QualifiedNameValue QualifiedNameValue 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 0 i=20 -1 1 1 0 false 0 ns=1;i=10235 Variable_2 1 LocalizedTextValue LocalizedTextValue 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 i=21 -1 1 1 0 false 0 ns=1;i=10236 Variable_2 1 StatusCodeValue StatusCodeValue 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 0 i=19 -1 1 1 0 false 0 ns=1;i=10237 Variable_2 1 VariantValue VariantValue 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 i=24 -1 1 1 0 false 0 ns=1;i=10238 Variable_2 1 EnumerationValue EnumerationValue 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 0 i=29 -1 1 1 0 false 0 ns=1;i=10239 Variable_2 1 StructureValue StructureValue 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 i=22 -1 1 1 0 false 0 ns=1;i=10240 Variable_2 1 NumberValue NumberValue 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 0 i=26 -1 1 1 0 false 0 ns=1;i=10241 Variable_2 1 IntegerValue IntegerValue 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 0 i=27 -1 1 1 0 false 0 ns=1;i=10242 Variable_2 1 UIntegerValue UIntegerValue 0 0 0 i=47 true ns=1;i=10159 i=40 false i=63 0 i=28 -1 1 1 0 false 0 ns=1;i=10243 Object_1 1 Array Array 0 0 0 i=47 true ns=1;i=10158 i=40 false ns=1;i=9679 i=36 true ns=1;i=10158 i=36 false ns=1;i=10247 i=46 false ns=1;i=10244 i=47 false ns=1;i=10245 i=47 false ns=1;i=10247 i=47 false ns=1;i=10300 i=47 false ns=1;i=10301 i=47 false ns=1;i=10302 i=47 false ns=1;i=10303 i=47 false ns=1;i=10304 i=47 false ns=1;i=10305 i=47 false ns=1;i=10306 i=47 false ns=1;i=10307 i=47 false ns=1;i=10308 i=47 false ns=1;i=10309 i=47 false ns=1;i=10310 i=47 false ns=1;i=10311 i=47 false ns=1;i=10312 i=47 false ns=1;i=10313 i=47 false ns=1;i=10314 i=47 false ns=1;i=10315 i=47 false ns=1;i=10316 i=47 false ns=1;i=10317 i=47 false ns=1;i=10318 i=47 false ns=1;i=10319 i=47 false ns=1;i=10320 i=47 false ns=1;i=10321 i=47 false ns=1;i=10322 i=47 false ns=1;i=10323 i=47 false ns=1;i=10324 i=47 false ns=1;i=10325 i=47 false ns=1;i=10326 0 ns=1;i=10244 Variable_2 1 SimulationActive SimulationActive If true the server will produce new values for each monitored variable. 0 0 0 i=46 true ns=1;i=10243 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10245 Method_4 1 GenerateValues GenerateValues 0 0 0 i=47 true ns=1;i=10243 i=46 false ns=1;i=10246 true true ns=1;i=10246 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10245 i=40 false i=68 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 0 false 0 ns=1;i=10247 Object_1 1 CycleComplete CycleComplete 0 0 0 i=47 true ns=1;i=10243 i=40 false i=2881 i=36 true ns=1;i=10243 i=46 false ns=1;i=10248 i=46 false ns=1;i=10249 i=46 false ns=1;i=10250 i=46 false ns=1;i=10251 i=46 false ns=1;i=10252 i=46 false ns=1;i=10253 i=46 false ns=1;i=10255 i=46 false ns=1;i=10256 i=46 false ns=1;i=11596 i=46 false ns=1;i=11597 i=46 false ns=1;i=11566 i=46 false ns=1;i=10257 i=46 false ns=1;i=10258 i=47 false ns=1;i=10259 i=47 false ns=1;i=10265 i=47 false ns=1;i=10269 i=47 false ns=1;i=10271 i=46 false ns=1;i=10273 i=47 false ns=1;i=10275 i=47 false ns=1;i=10274 i=47 false ns=1;i=10276 i=47 false ns=1;i=10280 i=47 false ns=1;i=10296 0 ns=1;i=10248 Variable_2 0 EventId EventId 0 0 0 i=46 true ns=1;i=10247 i=40 false i=68 i=15 -1 1 1 0 false 0 ns=1;i=10249 Variable_2 0 EventType EventType 0 0 0 i=46 true ns=1;i=10247 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10250 Variable_2 0 SourceNode SourceNode 0 0 0 i=46 true ns=1;i=10247 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10251 Variable_2 0 SourceName SourceName 0 0 0 i=46 true ns=1;i=10247 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=10252 Variable_2 0 Time Time 0 0 0 i=46 true ns=1;i=10247 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10253 Variable_2 0 ReceiveTime ReceiveTime 0 0 0 i=46 true ns=1;i=10247 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10255 Variable_2 0 Message Message 0 0 0 i=46 true ns=1;i=10247 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=10256 Variable_2 0 Severity Severity 0 0 0 i=46 true ns=1;i=10247 i=40 false i=68 0 i=5 -1 1 1 0 false 0 ns=1;i=10257 Variable_2 0 BranchId BranchId 0 0 0 i=46 true ns=1;i=10247 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10258 Variable_2 0 Retain Retain 0 0 0 i=46 true ns=1;i=10247 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10259 Variable_2 0 EnabledState EnabledState 0 0 0 i=47 true ns=1;i=10247 i=40 false i=8995 i=9004 false ns=1;i=10280 i=9004 false ns=1;i=10288 i=46 false ns=1;i=10260 i=21 -1 1 1 0 false 0 ns=1;i=10260 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=10259 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10265 Variable_2 0 Quality Quality 0 0 0 i=47 true ns=1;i=10247 i=40 false i=9002 i=46 false ns=1;i=10266 0 i=19 -1 1 1 0 false 0 ns=1;i=10266 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10265 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10269 Variable_2 0 LastSeverity LastSeverity 0 0 0 i=47 true ns=1;i=10247 i=40 false i=9002 i=46 false ns=1;i=10270 0 i=5 -1 1 1 0 false 0 ns=1;i=10270 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10269 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10271 Variable_2 0 Comment Comment 0 0 0 i=47 true ns=1;i=10247 i=40 false i=9002 i=46 false ns=1;i=10272 i=21 -1 1 1 0 false 0 ns=1;i=10272 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10271 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10273 Variable_2 0 ClientUserId ClientUserId 0 0 0 i=46 true ns=1;i=10247 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=10274 Method_4 0 Enable Enable 0 0 0 i=47 true ns=1;i=10247 i=3065 false i=2803 true true ns=1;i=10275 Method_4 0 Disable Disable 0 0 0 i=47 true ns=1;i=10247 i=3065 false i=2803 true true ns=1;i=10276 Method_4 0 AddComment AddComment 0 0 0 i=47 true ns=1;i=10247 i=3065 false i=2829 i=46 false ns=1;i=10277 true true ns=1;i=10277 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10276 i=40 false i=68 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=10280 Variable_2 0 AckedState AckedState 0 0 0 i=47 true ns=1;i=10247 i=40 false i=8995 i=9004 true ns=1;i=10259 i=46 false ns=1;i=10281 i=21 -1 1 1 0 false 0 ns=1;i=10281 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=10280 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10296 Method_4 0 Acknowledge Acknowledge 0 0 0 i=47 true ns=1;i=10247 i=3065 false i=8944 i=46 false ns=1;i=10297 true true ns=1;i=10297 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10296 i=40 false i=68 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=10300 Variable_2 1 BooleanValue BooleanValue 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=1 1 0 1 1 0 false 0 ns=1;i=10301 Variable_2 1 SByteValue SByteValue 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=2 1 0 1 1 0 false 0 ns=1;i=10302 Variable_2 1 ByteValue ByteValue 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=3 1 0 1 1 0 false 0 ns=1;i=10303 Variable_2 1 Int16Value Int16Value 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=4 1 0 1 1 0 false 0 ns=1;i=10304 Variable_2 1 UInt16Value UInt16Value 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=5 1 0 1 1 0 false 0 ns=1;i=10305 Variable_2 1 Int32Value Int32Value 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=6 1 0 1 1 0 false 0 ns=1;i=10306 Variable_2 1 UInt32Value UInt32Value 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=7 1 0 1 1 0 false 0 ns=1;i=10307 Variable_2 1 Int64Value Int64Value 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=8 1 0 1 1 0 false 0 ns=1;i=10308 Variable_2 1 UInt64Value UInt64Value 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=9 1 0 1 1 0 false 0 ns=1;i=10309 Variable_2 1 FloatValue FloatValue 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=10 1 0 1 1 0 false 0 ns=1;i=10310 Variable_2 1 DoubleValue DoubleValue 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=11 1 0 1 1 0 false 0 ns=1;i=10311 Variable_2 1 StringValue StringValue 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=12 1 0 1 1 0 false 0 ns=1;i=10312 Variable_2 1 DateTimeValue DateTimeValue 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=13 1 0 1 1 0 false 0 ns=1;i=10313 Variable_2 1 GuidValue GuidValue 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=14 1 0 1 1 0 false 0 ns=1;i=10314 Variable_2 1 ByteStringValue ByteStringValue 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=15 1 0 1 1 0 false 0 ns=1;i=10315 Variable_2 1 XmlElementValue XmlElementValue 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=16 1 0 1 1 0 false 0 ns=1;i=10316 Variable_2 1 NodeIdValue NodeIdValue 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=17 1 0 1 1 0 false 0 ns=1;i=10317 Variable_2 1 ExpandedNodeIdValue ExpandedNodeIdValue 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=18 1 0 1 1 0 false 0 ns=1;i=10318 Variable_2 1 QualifiedNameValue QualifiedNameValue 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=20 1 0 1 1 0 false 0 ns=1;i=10319 Variable_2 1 LocalizedTextValue LocalizedTextValue 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=21 1 0 1 1 0 false 0 ns=1;i=10320 Variable_2 1 StatusCodeValue StatusCodeValue 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=19 1 0 1 1 0 false 0 ns=1;i=10321 Variable_2 1 VariantValue VariantValue 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=24 1 0 1 1 0 false 0 ns=1;i=10322 Variable_2 1 EnumerationValue EnumerationValue 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=29 1 0 1 1 0 false 0 ns=1;i=10323 Variable_2 1 StructureValue StructureValue 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=22 1 0 1 1 0 false 0 ns=1;i=10324 Variable_2 1 NumberValue NumberValue 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=26 1 0 1 1 0 false 0 ns=1;i=10325 Variable_2 1 IntegerValue IntegerValue 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=27 1 0 1 1 0 false 0 ns=1;i=10326 Variable_2 1 UIntegerValue UIntegerValue 0 0 0 i=47 true ns=1;i=10243 i=40 false i=63 i=28 1 0 1 1 0 false 0 ns=1;i=10327 Object_1 1 UserScalar UserScalar 0 0 0 i=47 true ns=1;i=10158 i=40 false ns=1;i=9921 i=36 false ns=1;i=10331 i=46 false ns=1;i=10328 i=47 false ns=1;i=10329 i=47 false ns=1;i=10331 i=47 false ns=1;i=10384 i=47 false ns=1;i=10385 i=47 false ns=1;i=10386 i=47 false ns=1;i=10387 i=47 false ns=1;i=10388 i=47 false ns=1;i=10389 i=47 false ns=1;i=10390 i=47 false ns=1;i=10391 i=47 false ns=1;i=10392 i=47 false ns=1;i=10393 i=47 false ns=1;i=10394 i=47 false ns=1;i=10395 i=47 false ns=1;i=10396 i=47 false ns=1;i=10397 i=47 false ns=1;i=10398 i=47 false ns=1;i=10399 i=47 false ns=1;i=10400 i=47 false ns=1;i=10401 i=47 false ns=1;i=10402 i=47 false ns=1;i=10403 i=47 false ns=1;i=10404 i=47 false ns=1;i=10405 0 ns=1;i=10328 Variable_2 1 SimulationActive SimulationActive If true the server will produce new values for each monitored variable. 0 0 0 i=46 true ns=1;i=10327 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10329 Method_4 1 GenerateValues GenerateValues 0 0 0 i=47 true ns=1;i=10327 i=46 false ns=1;i=10330 true true ns=1;i=10330 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10329 i=40 false i=68 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 0 false 0 ns=1;i=10331 Object_1 1 CycleComplete CycleComplete 0 0 0 i=47 true ns=1;i=10327 i=40 false i=2881 i=36 true ns=1;i=10327 i=46 false ns=1;i=10332 i=46 false ns=1;i=10333 i=46 false ns=1;i=10334 i=46 false ns=1;i=10335 i=46 false ns=1;i=10336 i=46 false ns=1;i=10337 i=46 false ns=1;i=10339 i=46 false ns=1;i=10340 i=46 false ns=1;i=11598 i=46 false ns=1;i=11599 i=46 false ns=1;i=11567 i=46 false ns=1;i=10341 i=46 false ns=1;i=10342 i=47 false ns=1;i=10343 i=47 false ns=1;i=10349 i=47 false ns=1;i=10353 i=47 false ns=1;i=10355 i=46 false ns=1;i=10357 i=47 false ns=1;i=10359 i=47 false ns=1;i=10358 i=47 false ns=1;i=10360 i=47 false ns=1;i=10364 i=47 false ns=1;i=10380 0 ns=1;i=10332 Variable_2 0 EventId EventId 0 0 0 i=46 true ns=1;i=10331 i=40 false i=68 i=15 -1 1 1 0 false 0 ns=1;i=10333 Variable_2 0 EventType EventType 0 0 0 i=46 true ns=1;i=10331 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10334 Variable_2 0 SourceNode SourceNode 0 0 0 i=46 true ns=1;i=10331 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10335 Variable_2 0 SourceName SourceName 0 0 0 i=46 true ns=1;i=10331 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=10336 Variable_2 0 Time Time 0 0 0 i=46 true ns=1;i=10331 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10337 Variable_2 0 ReceiveTime ReceiveTime 0 0 0 i=46 true ns=1;i=10331 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10339 Variable_2 0 Message Message 0 0 0 i=46 true ns=1;i=10331 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=10340 Variable_2 0 Severity Severity 0 0 0 i=46 true ns=1;i=10331 i=40 false i=68 0 i=5 -1 1 1 0 false 0 ns=1;i=10341 Variable_2 0 BranchId BranchId 0 0 0 i=46 true ns=1;i=10331 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10342 Variable_2 0 Retain Retain 0 0 0 i=46 true ns=1;i=10331 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10343 Variable_2 0 EnabledState EnabledState 0 0 0 i=47 true ns=1;i=10331 i=40 false i=8995 i=9004 false ns=1;i=10364 i=9004 false ns=1;i=10372 i=46 false ns=1;i=10344 i=21 -1 1 1 0 false 0 ns=1;i=10344 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=10343 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10349 Variable_2 0 Quality Quality 0 0 0 i=47 true ns=1;i=10331 i=40 false i=9002 i=46 false ns=1;i=10350 0 i=19 -1 1 1 0 false 0 ns=1;i=10350 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10349 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10353 Variable_2 0 LastSeverity LastSeverity 0 0 0 i=47 true ns=1;i=10331 i=40 false i=9002 i=46 false ns=1;i=10354 0 i=5 -1 1 1 0 false 0 ns=1;i=10354 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10353 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10355 Variable_2 0 Comment Comment 0 0 0 i=47 true ns=1;i=10331 i=40 false i=9002 i=46 false ns=1;i=10356 i=21 -1 1 1 0 false 0 ns=1;i=10356 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10355 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10357 Variable_2 0 ClientUserId ClientUserId 0 0 0 i=46 true ns=1;i=10331 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=10358 Method_4 0 Enable Enable 0 0 0 i=47 true ns=1;i=10331 i=3065 false i=2803 true true ns=1;i=10359 Method_4 0 Disable Disable 0 0 0 i=47 true ns=1;i=10331 i=3065 false i=2803 true true ns=1;i=10360 Method_4 0 AddComment AddComment 0 0 0 i=47 true ns=1;i=10331 i=3065 false i=2829 i=46 false ns=1;i=10361 true true ns=1;i=10361 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10360 i=40 false i=68 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=10364 Variable_2 0 AckedState AckedState 0 0 0 i=47 true ns=1;i=10331 i=40 false i=8995 i=9004 true ns=1;i=10343 i=46 false ns=1;i=10365 i=21 -1 1 1 0 false 0 ns=1;i=10365 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=10364 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10380 Method_4 0 Acknowledge Acknowledge 0 0 0 i=47 true ns=1;i=10331 i=3065 false i=8944 i=46 false ns=1;i=10381 true true ns=1;i=10381 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10380 i=40 false i=68 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=10384 Variable_2 1 BooleanValue BooleanValue 0 0 0 i=47 true ns=1;i=10327 i=40 false i=63 ns=1;i=9898 -1 1 1 0 false 0 ns=1;i=10385 Variable_2 1 SByteValue SByteValue 0 0 0 i=47 true ns=1;i=10327 i=40 false i=63 ns=1;i=9899 -1 1 1 0 false 0 ns=1;i=10386 Variable_2 1 ByteValue ByteValue 0 0 0 i=47 true ns=1;i=10327 i=40 false i=63 ns=1;i=9900 -1 1 1 0 false 0 ns=1;i=10387 Variable_2 1 Int16Value Int16Value 0 0 0 i=47 true ns=1;i=10327 i=40 false i=63 ns=1;i=9901 -1 1 1 0 false 0 ns=1;i=10388 Variable_2 1 UInt16Value UInt16Value 0 0 0 i=47 true ns=1;i=10327 i=40 false i=63 ns=1;i=9902 -1 1 1 0 false 0 ns=1;i=10389 Variable_2 1 Int32Value Int32Value 0 0 0 i=47 true ns=1;i=10327 i=40 false i=63 ns=1;i=9903 -1 1 1 0 false 0 ns=1;i=10390 Variable_2 1 UInt32Value UInt32Value 0 0 0 i=47 true ns=1;i=10327 i=40 false i=63 ns=1;i=9904 -1 1 1 0 false 0 ns=1;i=10391 Variable_2 1 Int64Value Int64Value 0 0 0 i=47 true ns=1;i=10327 i=40 false i=63 ns=1;i=9905 -1 1 1 0 false 0 ns=1;i=10392 Variable_2 1 UInt64Value UInt64Value 0 0 0 i=47 true ns=1;i=10327 i=40 false i=63 ns=1;i=9906 -1 1 1 0 false 0 ns=1;i=10393 Variable_2 1 FloatValue FloatValue 0 0 0 i=47 true ns=1;i=10327 i=40 false i=63 ns=1;i=9907 -1 1 1 0 false 0 ns=1;i=10394 Variable_2 1 DoubleValue DoubleValue 0 0 0 i=47 true ns=1;i=10327 i=40 false i=63 ns=1;i=9908 -1 1 1 0 false 0 ns=1;i=10395 Variable_2 1 StringValue StringValue 0 0 0 i=47 true ns=1;i=10327 i=40 false i=63 ns=1;i=9909 -1 1 1 0 false 0 ns=1;i=10396 Variable_2 1 DateTimeValue DateTimeValue 0 0 0 i=47 true ns=1;i=10327 i=40 false i=63 ns=1;i=9910 -1 1 1 0 false 0 ns=1;i=10397 Variable_2 1 GuidValue GuidValue 0 0 0 i=47 true ns=1;i=10327 i=40 false i=63 ns=1;i=9911 -1 1 1 0 false 0 ns=1;i=10398 Variable_2 1 ByteStringValue ByteStringValue 0 0 0 i=47 true ns=1;i=10327 i=40 false i=63 ns=1;i=9912 -1 1 1 0 false 0 ns=1;i=10399 Variable_2 1 XmlElementValue XmlElementValue 0 0 0 i=47 true ns=1;i=10327 i=40 false i=63 ns=1;i=9913 -1 1 1 0 false 0 ns=1;i=10400 Variable_2 1 NodeIdValue NodeIdValue 0 0 0 i=47 true ns=1;i=10327 i=40 false i=63 ns=1;i=9914 -1 1 1 0 false 0 ns=1;i=10401 Variable_2 1 ExpandedNodeIdValue ExpandedNodeIdValue 0 0 0 i=47 true ns=1;i=10327 i=40 false i=63 ns=1;i=9915 -1 1 1 0 false 0 ns=1;i=10402 Variable_2 1 QualifiedNameValue QualifiedNameValue 0 0 0 i=47 true ns=1;i=10327 i=40 false i=63 ns=1;i=9916 -1 1 1 0 false 0 ns=1;i=10403 Variable_2 1 LocalizedTextValue LocalizedTextValue 0 0 0 i=47 true ns=1;i=10327 i=40 false i=63 ns=1;i=9917 -1 1 1 0 false 0 ns=1;i=10404 Variable_2 1 StatusCodeValue StatusCodeValue 0 0 0 i=47 true ns=1;i=10327 i=40 false i=63 ns=1;i=9918 -1 1 1 0 false 0 ns=1;i=10405 Variable_2 1 VariantValue VariantValue 0 0 0 i=47 true ns=1;i=10327 i=40 false i=63 ns=1;i=9919 -1 1 1 0 false 0 ns=1;i=10406 Object_1 1 UserArray UserArray 0 0 0 i=47 true ns=1;i=10158 i=40 false ns=1;i=10007 i=36 false ns=1;i=10410 i=46 false ns=1;i=10407 i=47 false ns=1;i=10408 i=47 false ns=1;i=10410 i=47 false ns=1;i=10463 i=47 false ns=1;i=10464 i=47 false ns=1;i=10465 i=47 false ns=1;i=10466 i=47 false ns=1;i=10467 i=47 false ns=1;i=10468 i=47 false ns=1;i=10469 i=47 false ns=1;i=10470 i=47 false ns=1;i=10471 i=47 false ns=1;i=10472 i=47 false ns=1;i=10473 i=47 false ns=1;i=10474 i=47 false ns=1;i=10475 i=47 false ns=1;i=10476 i=47 false ns=1;i=10477 i=47 false ns=1;i=10478 i=47 false ns=1;i=10479 i=47 false ns=1;i=10480 i=47 false ns=1;i=10481 i=47 false ns=1;i=10482 i=47 false ns=1;i=10483 i=47 false ns=1;i=10484 0 ns=1;i=10407 Variable_2 1 SimulationActive SimulationActive If true the server will produce new values for each monitored variable. 0 0 0 i=46 true ns=1;i=10406 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10408 Method_4 1 GenerateValues GenerateValues 0 0 0 i=47 true ns=1;i=10406 i=46 false ns=1;i=10409 true true ns=1;i=10409 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10408 i=40 false i=68 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 0 false 0 ns=1;i=10410 Object_1 1 CycleComplete CycleComplete 0 0 0 i=47 true ns=1;i=10406 i=40 false i=2881 i=36 true ns=1;i=10406 i=46 false ns=1;i=10411 i=46 false ns=1;i=10412 i=46 false ns=1;i=10413 i=46 false ns=1;i=10414 i=46 false ns=1;i=10415 i=46 false ns=1;i=10416 i=46 false ns=1;i=10418 i=46 false ns=1;i=10419 i=46 false ns=1;i=11600 i=46 false ns=1;i=11601 i=46 false ns=1;i=11568 i=46 false ns=1;i=10420 i=46 false ns=1;i=10421 i=47 false ns=1;i=10422 i=47 false ns=1;i=10428 i=47 false ns=1;i=10432 i=47 false ns=1;i=10434 i=46 false ns=1;i=10436 i=47 false ns=1;i=10438 i=47 false ns=1;i=10437 i=47 false ns=1;i=10439 i=47 false ns=1;i=10443 i=47 false ns=1;i=10459 0 ns=1;i=10411 Variable_2 0 EventId EventId 0 0 0 i=46 true ns=1;i=10410 i=40 false i=68 i=15 -1 1 1 0 false 0 ns=1;i=10412 Variable_2 0 EventType EventType 0 0 0 i=46 true ns=1;i=10410 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10413 Variable_2 0 SourceNode SourceNode 0 0 0 i=46 true ns=1;i=10410 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10414 Variable_2 0 SourceName SourceName 0 0 0 i=46 true ns=1;i=10410 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=10415 Variable_2 0 Time Time 0 0 0 i=46 true ns=1;i=10410 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10416 Variable_2 0 ReceiveTime ReceiveTime 0 0 0 i=46 true ns=1;i=10410 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10418 Variable_2 0 Message Message 0 0 0 i=46 true ns=1;i=10410 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=10419 Variable_2 0 Severity Severity 0 0 0 i=46 true ns=1;i=10410 i=40 false i=68 0 i=5 -1 1 1 0 false 0 ns=1;i=10420 Variable_2 0 BranchId BranchId 0 0 0 i=46 true ns=1;i=10410 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10421 Variable_2 0 Retain Retain 0 0 0 i=46 true ns=1;i=10410 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10422 Variable_2 0 EnabledState EnabledState 0 0 0 i=47 true ns=1;i=10410 i=40 false i=8995 i=9004 false ns=1;i=10443 i=9004 false ns=1;i=10451 i=46 false ns=1;i=10423 i=21 -1 1 1 0 false 0 ns=1;i=10423 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=10422 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10428 Variable_2 0 Quality Quality 0 0 0 i=47 true ns=1;i=10410 i=40 false i=9002 i=46 false ns=1;i=10429 0 i=19 -1 1 1 0 false 0 ns=1;i=10429 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10428 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10432 Variable_2 0 LastSeverity LastSeverity 0 0 0 i=47 true ns=1;i=10410 i=40 false i=9002 i=46 false ns=1;i=10433 0 i=5 -1 1 1 0 false 0 ns=1;i=10433 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10432 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10434 Variable_2 0 Comment Comment 0 0 0 i=47 true ns=1;i=10410 i=40 false i=9002 i=46 false ns=1;i=10435 i=21 -1 1 1 0 false 0 ns=1;i=10435 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10434 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10436 Variable_2 0 ClientUserId ClientUserId 0 0 0 i=46 true ns=1;i=10410 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=10437 Method_4 0 Enable Enable 0 0 0 i=47 true ns=1;i=10410 i=3065 false i=2803 true true ns=1;i=10438 Method_4 0 Disable Disable 0 0 0 i=47 true ns=1;i=10410 i=3065 false i=2803 true true ns=1;i=10439 Method_4 0 AddComment AddComment 0 0 0 i=47 true ns=1;i=10410 i=3065 false i=2829 i=46 false ns=1;i=10440 true true ns=1;i=10440 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10439 i=40 false i=68 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=10443 Variable_2 0 AckedState AckedState 0 0 0 i=47 true ns=1;i=10410 i=40 false i=8995 i=9004 true ns=1;i=10422 i=46 false ns=1;i=10444 i=21 -1 1 1 0 false 0 ns=1;i=10444 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=10443 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10459 Method_4 0 Acknowledge Acknowledge 0 0 0 i=47 true ns=1;i=10410 i=3065 false i=8944 i=46 false ns=1;i=10460 true true ns=1;i=10460 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10459 i=40 false i=68 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=10463 Variable_2 1 BooleanValue BooleanValue 0 0 0 i=47 true ns=1;i=10406 i=40 false i=63 ns=1;i=9898 1 0 1 1 0 false 0 ns=1;i=10464 Variable_2 1 SByteValue SByteValue 0 0 0 i=47 true ns=1;i=10406 i=40 false i=63 ns=1;i=9899 1 0 1 1 0 false 0 ns=1;i=10465 Variable_2 1 ByteValue ByteValue 0 0 0 i=47 true ns=1;i=10406 i=40 false i=63 ns=1;i=9900 1 0 1 1 0 false 0 ns=1;i=10466 Variable_2 1 Int16Value Int16Value 0 0 0 i=47 true ns=1;i=10406 i=40 false i=63 ns=1;i=9901 1 0 1 1 0 false 0 ns=1;i=10467 Variable_2 1 UInt16Value UInt16Value 0 0 0 i=47 true ns=1;i=10406 i=40 false i=63 ns=1;i=9902 1 0 1 1 0 false 0 ns=1;i=10468 Variable_2 1 Int32Value Int32Value 0 0 0 i=47 true ns=1;i=10406 i=40 false i=63 ns=1;i=9903 1 0 1 1 0 false 0 ns=1;i=10469 Variable_2 1 UInt32Value UInt32Value 0 0 0 i=47 true ns=1;i=10406 i=40 false i=63 ns=1;i=9904 1 0 1 1 0 false 0 ns=1;i=10470 Variable_2 1 Int64Value Int64Value 0 0 0 i=47 true ns=1;i=10406 i=40 false i=63 ns=1;i=9905 1 0 1 1 0 false 0 ns=1;i=10471 Variable_2 1 UInt64Value UInt64Value 0 0 0 i=47 true ns=1;i=10406 i=40 false i=63 ns=1;i=9906 1 0 1 1 0 false 0 ns=1;i=10472 Variable_2 1 FloatValue FloatValue 0 0 0 i=47 true ns=1;i=10406 i=40 false i=63 ns=1;i=9907 1 0 1 1 0 false 0 ns=1;i=10473 Variable_2 1 DoubleValue DoubleValue 0 0 0 i=47 true ns=1;i=10406 i=40 false i=63 ns=1;i=9908 1 0 1 1 0 false 0 ns=1;i=10474 Variable_2 1 StringValue StringValue 0 0 0 i=47 true ns=1;i=10406 i=40 false i=63 ns=1;i=9909 1 0 1 1 0 false 0 ns=1;i=10475 Variable_2 1 DateTimeValue DateTimeValue 0 0 0 i=47 true ns=1;i=10406 i=40 false i=63 ns=1;i=9910 1 0 1 1 0 false 0 ns=1;i=10476 Variable_2 1 GuidValue GuidValue 0 0 0 i=47 true ns=1;i=10406 i=40 false i=63 ns=1;i=9911 1 0 1 1 0 false 0 ns=1;i=10477 Variable_2 1 ByteStringValue ByteStringValue 0 0 0 i=47 true ns=1;i=10406 i=40 false i=63 ns=1;i=9912 1 0 1 1 0 false 0 ns=1;i=10478 Variable_2 1 XmlElementValue XmlElementValue 0 0 0 i=47 true ns=1;i=10406 i=40 false i=63 ns=1;i=9913 1 0 1 1 0 false 0 ns=1;i=10479 Variable_2 1 NodeIdValue NodeIdValue 0 0 0 i=47 true ns=1;i=10406 i=40 false i=63 ns=1;i=9914 1 0 1 1 0 false 0 ns=1;i=10480 Variable_2 1 ExpandedNodeIdValue ExpandedNodeIdValue 0 0 0 i=47 true ns=1;i=10406 i=40 false i=63 ns=1;i=9915 1 0 1 1 0 false 0 ns=1;i=10481 Variable_2 1 QualifiedNameValue QualifiedNameValue 0 0 0 i=47 true ns=1;i=10406 i=40 false i=63 ns=1;i=9916 1 0 1 1 0 false 0 ns=1;i=10482 Variable_2 1 LocalizedTextValue LocalizedTextValue 0 0 0 i=47 true ns=1;i=10406 i=40 false i=63 ns=1;i=9917 1 0 1 1 0 false 0 ns=1;i=10483 Variable_2 1 StatusCodeValue StatusCodeValue 0 0 0 i=47 true ns=1;i=10406 i=40 false i=63 ns=1;i=9918 1 0 1 1 0 false 0 ns=1;i=10484 Variable_2 1 VariantValue VariantValue 0 0 0 i=47 true ns=1;i=10406 i=40 false i=63 ns=1;i=9919 1 0 1 1 0 false 0 ns=1;i=10485 Object_1 1 AnalogScalar AnalogScalar 0 0 0 i=47 true ns=1;i=10158 i=40 false ns=1;i=9534 i=36 false ns=1;i=10489 i=46 false ns=1;i=10486 i=47 false ns=1;i=10487 i=47 false ns=1;i=10489 i=47 false ns=1;i=10542 i=47 false ns=1;i=10548 i=47 false ns=1;i=10554 i=47 false ns=1;i=10560 i=47 false ns=1;i=10566 i=47 false ns=1;i=10572 i=47 false ns=1;i=10578 i=47 false ns=1;i=10584 i=47 false ns=1;i=10590 i=47 false ns=1;i=10596 i=47 false ns=1;i=10602 i=47 false ns=1;i=10608 i=47 false ns=1;i=10614 0 ns=1;i=10486 Variable_2 1 SimulationActive SimulationActive If true the server will produce new values for each monitored variable. 0 0 0 i=46 true ns=1;i=10485 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10487 Method_4 1 GenerateValues GenerateValues 0 0 0 i=47 true ns=1;i=10485 i=46 false ns=1;i=10488 true true ns=1;i=10488 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10487 i=40 false i=68 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 0 false 0 ns=1;i=10489 Object_1 1 CycleComplete CycleComplete 0 0 0 i=47 true ns=1;i=10485 i=40 false i=2881 i=36 true ns=1;i=10485 i=46 false ns=1;i=10490 i=46 false ns=1;i=10491 i=46 false ns=1;i=10492 i=46 false ns=1;i=10493 i=46 false ns=1;i=10494 i=46 false ns=1;i=10495 i=46 false ns=1;i=10497 i=46 false ns=1;i=10498 i=46 false ns=1;i=11602 i=46 false ns=1;i=11603 i=46 false ns=1;i=11569 i=46 false ns=1;i=10499 i=46 false ns=1;i=10500 i=47 false ns=1;i=10501 i=47 false ns=1;i=10507 i=47 false ns=1;i=10511 i=47 false ns=1;i=10513 i=46 false ns=1;i=10515 i=47 false ns=1;i=10517 i=47 false ns=1;i=10516 i=47 false ns=1;i=10518 i=47 false ns=1;i=10522 i=47 false ns=1;i=10538 0 ns=1;i=10490 Variable_2 0 EventId EventId 0 0 0 i=46 true ns=1;i=10489 i=40 false i=68 i=15 -1 1 1 0 false 0 ns=1;i=10491 Variable_2 0 EventType EventType 0 0 0 i=46 true ns=1;i=10489 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10492 Variable_2 0 SourceNode SourceNode 0 0 0 i=46 true ns=1;i=10489 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10493 Variable_2 0 SourceName SourceName 0 0 0 i=46 true ns=1;i=10489 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=10494 Variable_2 0 Time Time 0 0 0 i=46 true ns=1;i=10489 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10495 Variable_2 0 ReceiveTime ReceiveTime 0 0 0 i=46 true ns=1;i=10489 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10497 Variable_2 0 Message Message 0 0 0 i=46 true ns=1;i=10489 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=10498 Variable_2 0 Severity Severity 0 0 0 i=46 true ns=1;i=10489 i=40 false i=68 0 i=5 -1 1 1 0 false 0 ns=1;i=10499 Variable_2 0 BranchId BranchId 0 0 0 i=46 true ns=1;i=10489 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10500 Variable_2 0 Retain Retain 0 0 0 i=46 true ns=1;i=10489 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10501 Variable_2 0 EnabledState EnabledState 0 0 0 i=47 true ns=1;i=10489 i=40 false i=8995 i=9004 false ns=1;i=10522 i=9004 false ns=1;i=10530 i=46 false ns=1;i=10502 i=21 -1 1 1 0 false 0 ns=1;i=10502 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=10501 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10507 Variable_2 0 Quality Quality 0 0 0 i=47 true ns=1;i=10489 i=40 false i=9002 i=46 false ns=1;i=10508 0 i=19 -1 1 1 0 false 0 ns=1;i=10508 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10507 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10511 Variable_2 0 LastSeverity LastSeverity 0 0 0 i=47 true ns=1;i=10489 i=40 false i=9002 i=46 false ns=1;i=10512 0 i=5 -1 1 1 0 false 0 ns=1;i=10512 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10511 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10513 Variable_2 0 Comment Comment 0 0 0 i=47 true ns=1;i=10489 i=40 false i=9002 i=46 false ns=1;i=10514 i=21 -1 1 1 0 false 0 ns=1;i=10514 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10513 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10515 Variable_2 0 ClientUserId ClientUserId 0 0 0 i=46 true ns=1;i=10489 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=10516 Method_4 0 Enable Enable 0 0 0 i=47 true ns=1;i=10489 i=3065 false i=2803 true true ns=1;i=10517 Method_4 0 Disable Disable 0 0 0 i=47 true ns=1;i=10489 i=3065 false i=2803 true true ns=1;i=10518 Method_4 0 AddComment AddComment 0 0 0 i=47 true ns=1;i=10489 i=3065 false i=2829 i=46 false ns=1;i=10519 true true ns=1;i=10519 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10518 i=40 false i=68 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=10522 Variable_2 0 AckedState AckedState 0 0 0 i=47 true ns=1;i=10489 i=40 false i=8995 i=9004 true ns=1;i=10501 i=46 false ns=1;i=10523 i=21 -1 1 1 0 false 0 ns=1;i=10523 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=10522 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10538 Method_4 0 Acknowledge Acknowledge 0 0 0 i=47 true ns=1;i=10489 i=3065 false i=8944 i=46 false ns=1;i=10539 true true ns=1;i=10539 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10538 i=40 false i=68 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=10542 Variable_2 1 SByteValue SByteValue 0 0 0 i=47 true ns=1;i=10485 i=40 false i=2368 i=46 false ns=1;i=10545 0 i=2 -1 1 1 0 false 0 ns=1;i=10545 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10542 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10548 Variable_2 1 ByteValue ByteValue 0 0 0 i=47 true ns=1;i=10485 i=40 false i=2368 i=46 false ns=1;i=10551 0 i=3 -1 1 1 0 false 0 ns=1;i=10551 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10548 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10554 Variable_2 1 Int16Value Int16Value 0 0 0 i=47 true ns=1;i=10485 i=40 false i=2368 i=46 false ns=1;i=10557 0 i=4 -1 1 1 0 false 0 ns=1;i=10557 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10554 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10560 Variable_2 1 UInt16Value UInt16Value 0 0 0 i=47 true ns=1;i=10485 i=40 false i=2368 i=46 false ns=1;i=10563 0 i=5 -1 1 1 0 false 0 ns=1;i=10563 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10560 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10566 Variable_2 1 Int32Value Int32Value 0 0 0 i=47 true ns=1;i=10485 i=40 false i=2368 i=46 false ns=1;i=10569 0 i=6 -1 1 1 0 false 0 ns=1;i=10569 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10566 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10572 Variable_2 1 UInt32Value UInt32Value 0 0 0 i=47 true ns=1;i=10485 i=40 false i=2368 i=46 false ns=1;i=10575 0 i=7 -1 1 1 0 false 0 ns=1;i=10575 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10572 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10578 Variable_2 1 Int64Value Int64Value 0 0 0 i=47 true ns=1;i=10485 i=40 false i=2368 i=46 false ns=1;i=10581 0 i=8 -1 1 1 0 false 0 ns=1;i=10581 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10578 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10584 Variable_2 1 UInt64Value UInt64Value 0 0 0 i=47 true ns=1;i=10485 i=40 false i=2368 i=46 false ns=1;i=10587 0 i=9 -1 1 1 0 false 0 ns=1;i=10587 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10584 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10590 Variable_2 1 FloatValue FloatValue 0 0 0 i=47 true ns=1;i=10485 i=40 false i=2368 i=46 false ns=1;i=10593 0 i=10 -1 1 1 0 false 0 ns=1;i=10593 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10590 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10596 Variable_2 1 DoubleValue DoubleValue 0 0 0 i=47 true ns=1;i=10485 i=40 false i=2368 i=46 false ns=1;i=10599 0 i=11 -1 1 1 0 false 0 ns=1;i=10599 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10596 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10602 Variable_2 1 NumberValue NumberValue 0 0 0 i=47 true ns=1;i=10485 i=40 false i=2368 i=46 false ns=1;i=10605 0 i=26 -1 1 1 0 false 0 ns=1;i=10605 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10602 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10608 Variable_2 1 IntegerValue IntegerValue 0 0 0 i=47 true ns=1;i=10485 i=40 false i=2368 i=46 false ns=1;i=10611 0 i=27 -1 1 1 0 false 0 ns=1;i=10611 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10608 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10614 Variable_2 1 UIntegerValue UIntegerValue 0 0 0 i=47 true ns=1;i=10485 i=40 false i=2368 i=46 false ns=1;i=10617 0 i=28 -1 1 1 0 false 0 ns=1;i=10617 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10614 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10620 Object_1 1 AnalogArray AnalogArray 0 0 0 i=47 true ns=1;i=10158 i=40 false ns=1;i=9763 i=36 false ns=1;i=10624 i=46 false ns=1;i=10621 i=47 false ns=1;i=10622 i=47 false ns=1;i=10624 i=47 false ns=1;i=10677 i=47 false ns=1;i=10683 i=47 false ns=1;i=10689 i=47 false ns=1;i=10695 i=47 false ns=1;i=10701 i=47 false ns=1;i=10707 i=47 false ns=1;i=10713 i=47 false ns=1;i=10719 i=47 false ns=1;i=10725 i=47 false ns=1;i=10731 i=47 false ns=1;i=10737 i=47 false ns=1;i=10743 i=47 false ns=1;i=10749 0 ns=1;i=10621 Variable_2 1 SimulationActive SimulationActive If true the server will produce new values for each monitored variable. 0 0 0 i=46 true ns=1;i=10620 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10622 Method_4 1 GenerateValues GenerateValues 0 0 0 i=47 true ns=1;i=10620 i=46 false ns=1;i=10623 true true ns=1;i=10623 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10622 i=40 false i=68 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 0 false 0 ns=1;i=10624 Object_1 1 CycleComplete CycleComplete 0 0 0 i=47 true ns=1;i=10620 i=40 false i=2881 i=36 true ns=1;i=10620 i=46 false ns=1;i=10625 i=46 false ns=1;i=10626 i=46 false ns=1;i=10627 i=46 false ns=1;i=10628 i=46 false ns=1;i=10629 i=46 false ns=1;i=10630 i=46 false ns=1;i=10632 i=46 false ns=1;i=10633 i=46 false ns=1;i=11604 i=46 false ns=1;i=11605 i=46 false ns=1;i=11570 i=46 false ns=1;i=10634 i=46 false ns=1;i=10635 i=47 false ns=1;i=10636 i=47 false ns=1;i=10642 i=47 false ns=1;i=10646 i=47 false ns=1;i=10648 i=46 false ns=1;i=10650 i=47 false ns=1;i=10652 i=47 false ns=1;i=10651 i=47 false ns=1;i=10653 i=47 false ns=1;i=10657 i=47 false ns=1;i=10673 0 ns=1;i=10625 Variable_2 0 EventId EventId 0 0 0 i=46 true ns=1;i=10624 i=40 false i=68 i=15 -1 1 1 0 false 0 ns=1;i=10626 Variable_2 0 EventType EventType 0 0 0 i=46 true ns=1;i=10624 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10627 Variable_2 0 SourceNode SourceNode 0 0 0 i=46 true ns=1;i=10624 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10628 Variable_2 0 SourceName SourceName 0 0 0 i=46 true ns=1;i=10624 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=10629 Variable_2 0 Time Time 0 0 0 i=46 true ns=1;i=10624 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10630 Variable_2 0 ReceiveTime ReceiveTime 0 0 0 i=46 true ns=1;i=10624 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10632 Variable_2 0 Message Message 0 0 0 i=46 true ns=1;i=10624 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=10633 Variable_2 0 Severity Severity 0 0 0 i=46 true ns=1;i=10624 i=40 false i=68 0 i=5 -1 1 1 0 false 0 ns=1;i=10634 Variable_2 0 BranchId BranchId 0 0 0 i=46 true ns=1;i=10624 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10635 Variable_2 0 Retain Retain 0 0 0 i=46 true ns=1;i=10624 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10636 Variable_2 0 EnabledState EnabledState 0 0 0 i=47 true ns=1;i=10624 i=40 false i=8995 i=9004 false ns=1;i=10657 i=9004 false ns=1;i=10665 i=46 false ns=1;i=10637 i=21 -1 1 1 0 false 0 ns=1;i=10637 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=10636 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10642 Variable_2 0 Quality Quality 0 0 0 i=47 true ns=1;i=10624 i=40 false i=9002 i=46 false ns=1;i=10643 0 i=19 -1 1 1 0 false 0 ns=1;i=10643 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10642 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10646 Variable_2 0 LastSeverity LastSeverity 0 0 0 i=47 true ns=1;i=10624 i=40 false i=9002 i=46 false ns=1;i=10647 0 i=5 -1 1 1 0 false 0 ns=1;i=10647 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10646 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10648 Variable_2 0 Comment Comment 0 0 0 i=47 true ns=1;i=10624 i=40 false i=9002 i=46 false ns=1;i=10649 i=21 -1 1 1 0 false 0 ns=1;i=10649 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10648 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10650 Variable_2 0 ClientUserId ClientUserId 0 0 0 i=46 true ns=1;i=10624 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=10651 Method_4 0 Enable Enable 0 0 0 i=47 true ns=1;i=10624 i=3065 false i=2803 true true ns=1;i=10652 Method_4 0 Disable Disable 0 0 0 i=47 true ns=1;i=10624 i=3065 false i=2803 true true ns=1;i=10653 Method_4 0 AddComment AddComment 0 0 0 i=47 true ns=1;i=10624 i=3065 false i=2829 i=46 false ns=1;i=10654 true true ns=1;i=10654 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10653 i=40 false i=68 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=10657 Variable_2 0 AckedState AckedState 0 0 0 i=47 true ns=1;i=10624 i=40 false i=8995 i=9004 true ns=1;i=10636 i=46 false ns=1;i=10658 i=21 -1 1 1 0 false 0 ns=1;i=10658 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=10657 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10673 Method_4 0 Acknowledge Acknowledge 0 0 0 i=47 true ns=1;i=10624 i=3065 false i=8944 i=46 false ns=1;i=10674 true true ns=1;i=10674 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10673 i=40 false i=68 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=10677 Variable_2 1 SByteValue SByteValue 0 0 0 i=47 true ns=1;i=10620 i=40 false i=2368 i=46 false ns=1;i=10680 i=2 1 0 1 1 0 false 0 ns=1;i=10680 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10677 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10683 Variable_2 1 ByteValue ByteValue 0 0 0 i=47 true ns=1;i=10620 i=40 false i=2368 i=46 false ns=1;i=10686 i=3 1 0 1 1 0 false 0 ns=1;i=10686 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10683 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10689 Variable_2 1 Int16Value Int16Value 0 0 0 i=47 true ns=1;i=10620 i=40 false i=2368 i=46 false ns=1;i=10692 i=4 1 0 1 1 0 false 0 ns=1;i=10692 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10689 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10695 Variable_2 1 UInt16Value UInt16Value 0 0 0 i=47 true ns=1;i=10620 i=40 false i=2368 i=46 false ns=1;i=10698 i=5 1 0 1 1 0 false 0 ns=1;i=10698 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10695 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10701 Variable_2 1 Int32Value Int32Value 0 0 0 i=47 true ns=1;i=10620 i=40 false i=2368 i=46 false ns=1;i=10704 i=6 1 0 1 1 0 false 0 ns=1;i=10704 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10701 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10707 Variable_2 1 UInt32Value UInt32Value 0 0 0 i=47 true ns=1;i=10620 i=40 false i=2368 i=46 false ns=1;i=10710 i=7 1 0 1 1 0 false 0 ns=1;i=10710 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10707 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10713 Variable_2 1 Int64Value Int64Value 0 0 0 i=47 true ns=1;i=10620 i=40 false i=2368 i=46 false ns=1;i=10716 i=8 1 0 1 1 0 false 0 ns=1;i=10716 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10713 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10719 Variable_2 1 UInt64Value UInt64Value 0 0 0 i=47 true ns=1;i=10620 i=40 false i=2368 i=46 false ns=1;i=10722 i=9 1 0 1 1 0 false 0 ns=1;i=10722 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10719 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10725 Variable_2 1 FloatValue FloatValue 0 0 0 i=47 true ns=1;i=10620 i=40 false i=2368 i=46 false ns=1;i=10728 i=10 1 0 1 1 0 false 0 ns=1;i=10728 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10725 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10731 Variable_2 1 DoubleValue DoubleValue 0 0 0 i=47 true ns=1;i=10620 i=40 false i=2368 i=46 false ns=1;i=10734 i=11 1 0 1 1 0 false 0 ns=1;i=10734 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10731 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10737 Variable_2 1 NumberValue NumberValue 0 0 0 i=47 true ns=1;i=10620 i=40 false i=2368 i=46 false ns=1;i=10740 i=26 1 0 1 1 0 false 0 ns=1;i=10740 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10737 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10743 Variable_2 1 IntegerValue IntegerValue 0 0 0 i=47 true ns=1;i=10620 i=40 false i=2368 i=46 false ns=1;i=10746 i=27 1 0 1 1 0 false 0 ns=1;i=10746 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10743 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10749 Variable_2 1 UIntegerValue UIntegerValue 0 0 0 i=47 true ns=1;i=10620 i=40 false i=2368 i=46 false ns=1;i=10752 i=28 1 0 1 1 0 false 0 ns=1;i=10752 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=10749 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=10755 Object_1 1 MethodTest MethodTest 0 0 0 i=47 true ns=1;i=10158 i=40 false ns=1;i=10092 i=47 false ns=1;i=10756 i=47 false ns=1;i=10759 i=47 false ns=1;i=10762 i=47 false ns=1;i=10765 i=47 false ns=1;i=10768 i=47 false ns=1;i=10771 i=47 false ns=1;i=10774 i=47 false ns=1;i=10777 i=47 false ns=1;i=10780 i=47 false ns=1;i=10783 0 ns=1;i=10756 Method_4 1 ScalarMethod1 ScalarMethod1 0 0 0 i=47 true ns=1;i=10755 i=46 false ns=1;i=10757 i=46 false ns=1;i=10758 true true ns=1;i=10757 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10756 i=40 false i=68 i=297 BooleanIn i=1 -1 i=297 SByteIn i=2 -1 i=297 ByteIn i=3 -1 i=297 Int16In i=4 -1 i=297 UInt16In i=5 -1 i=297 Int32In i=6 -1 i=297 UInt32In i=7 -1 i=297 Int64In i=8 -1 i=297 UInt64In i=9 -1 i=297 FloatIn i=10 -1 i=297 DoubleIn i=11 -1 i=296 1 0 1 1 0 false 0 ns=1;i=10758 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=10756 i=40 false i=68 i=297 BooleanOut i=1 -1 i=297 SByteOut i=2 -1 i=297 ByteOut i=3 -1 i=297 Int16Out i=4 -1 i=297 UInt16Out i=5 -1 i=297 Int32Out i=6 -1 i=297 UInt32Out i=7 -1 i=297 Int64Out i=8 -1 i=297 UInt64Out i=9 -1 i=297 FloatOut i=10 -1 i=297 DoubleOut i=11 -1 i=296 1 0 1 1 0 false 0 ns=1;i=10759 Method_4 1 ScalarMethod2 ScalarMethod2 0 0 0 i=47 true ns=1;i=10755 i=46 false ns=1;i=10760 i=46 false ns=1;i=10761 true true ns=1;i=10760 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10759 i=40 false i=68 i=297 StringIn i=12 -1 i=297 DateTimeIn i=13 -1 i=297 GuidIn i=14 -1 i=297 ByteStringIn i=15 -1 i=297 XmlElementIn i=16 -1 i=297 NodeIdIn i=17 -1 i=297 ExpandedNodeIdIn i=18 -1 i=297 QualifiedNameIn i=20 -1 i=297 LocalizedTextIn i=21 -1 i=297 StatusCodeIn i=19 -1 i=296 1 0 1 1 0 false 0 ns=1;i=10761 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=10759 i=40 false i=68 i=297 StringOut i=12 -1 i=297 DateTimeOut i=13 -1 i=297 GuidOut i=14 -1 i=297 ByteStringOut i=15 -1 i=297 XmlElementOut i=16 -1 i=297 NodeIdOut i=17 -1 i=297 ExpandedNodeIdOut i=18 -1 i=297 QualifiedNameOut i=20 -1 i=297 LocalizedTextOut i=21 -1 i=297 StatusCodeOut i=19 -1 i=296 1 0 1 1 0 false 0 ns=1;i=10762 Method_4 1 ScalarMethod3 ScalarMethod3 0 0 0 i=47 true ns=1;i=10755 i=46 false ns=1;i=10763 i=46 false ns=1;i=10764 true true ns=1;i=10763 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10762 i=40 false i=68 i=297 VariantIn i=24 -1 i=297 EnumerationIn i=29 -1 i=297 StructureIn i=22 -1 i=296 1 0 1 1 0 false 0 ns=1;i=10764 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=10762 i=40 false i=68 i=297 VariantOut i=24 -1 i=297 EnumerationOut i=29 -1 i=297 StructureOut i=22 -1 i=296 1 0 1 1 0 false 0 ns=1;i=10765 Method_4 1 ArrayMethod1 ArrayMethod1 0 0 0 i=47 true ns=1;i=10755 i=46 false ns=1;i=10766 i=46 false ns=1;i=10767 true true ns=1;i=10766 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10765 i=40 false i=68 i=297 BooleanIn i=1 1 0 i=297 SByteIn i=2 1 0 i=297 ByteIn i=3 1 0 i=297 Int16In i=4 1 0 i=297 UInt16In i=5 1 0 i=297 Int32In i=6 1 0 i=297 UInt32In i=7 1 0 i=297 Int64In i=8 1 0 i=297 UInt64In i=9 1 0 i=297 FloatIn i=10 1 0 i=297 DoubleIn i=11 1 0 i=296 1 0 1 1 0 false 0 ns=1;i=10767 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=10765 i=40 false i=68 i=297 BooleanOut i=1 1 0 i=297 SByteOut i=2 1 0 i=297 ByteOut i=3 1 0 i=297 Int16Out i=4 1 0 i=297 UInt16Out i=5 1 0 i=297 Int32Out i=6 1 0 i=297 UInt32Out i=7 1 0 i=297 Int64Out i=8 1 0 i=297 UInt64Out i=9 1 0 i=297 FloatOut i=10 1 0 i=297 DoubleOut i=11 1 0 i=296 1 0 1 1 0 false 0 ns=1;i=10768 Method_4 1 ArrayMethod2 ArrayMethod2 0 0 0 i=47 true ns=1;i=10755 i=46 false ns=1;i=10769 i=46 false ns=1;i=10770 true true ns=1;i=10769 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10768 i=40 false i=68 i=297 StringIn i=12 1 0 i=297 DateTimeIn i=13 1 0 i=297 GuidIn i=14 1 0 i=297 ByteStringIn i=15 1 0 i=297 XmlElementIn i=16 1 0 i=297 NodeIdIn i=17 1 0 i=297 ExpandedNodeIdIn i=18 1 0 i=297 QualifiedNameIn i=20 1 0 i=297 LocalizedTextIn i=21 1 0 i=297 StatusCodeIn i=19 1 0 i=296 1 0 1 1 0 false 0 ns=1;i=10770 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=10768 i=40 false i=68 i=297 StringOut i=12 1 0 i=297 DateTimeOut i=13 1 0 i=297 GuidOut i=14 1 0 i=297 ByteStringOut i=15 1 0 i=297 XmlElementOut i=16 1 0 i=297 NodeIdOut i=17 1 0 i=297 ExpandedNodeIdOut i=18 1 0 i=297 QualifiedNameOut i=20 1 0 i=297 LocalizedTextOut i=21 1 0 i=297 StatusCodeOut i=19 1 0 i=296 1 0 1 1 0 false 0 ns=1;i=10771 Method_4 1 ArrayMethod3 ArrayMethod3 0 0 0 i=47 true ns=1;i=10755 i=46 false ns=1;i=10772 i=46 false ns=1;i=10773 true true ns=1;i=10772 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10771 i=40 false i=68 i=297 VariantIn i=24 1 0 i=297 EnumerationIn i=29 1 0 i=297 StructureIn i=22 1 0 i=296 1 0 1 1 0 false 0 ns=1;i=10773 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=10771 i=40 false i=68 i=297 VariantOut i=24 1 0 i=297 EnumerationOut i=29 1 0 i=297 StructureOut i=22 1 0 i=296 1 0 1 1 0 false 0 ns=1;i=10774 Method_4 1 UserScalarMethod1 UserScalarMethod1 0 0 0 i=47 true ns=1;i=10755 i=46 false ns=1;i=10775 i=46 false ns=1;i=10776 true true ns=1;i=10775 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10774 i=40 false i=68 i=297 BooleanIn ns=1;i=9898 -1 i=297 SByteIn ns=1;i=9899 -1 i=297 ByteIn ns=1;i=9900 -1 i=297 Int16In ns=1;i=9901 -1 i=297 UInt16In ns=1;i=9902 -1 i=297 Int32In ns=1;i=9903 -1 i=297 UInt32In ns=1;i=9904 -1 i=297 Int64In ns=1;i=9905 -1 i=297 UInt64In ns=1;i=9906 -1 i=297 FloatIn ns=1;i=9907 -1 i=297 DoubleIn ns=1;i=9908 -1 i=297 StringIn ns=1;i=9909 -1 i=296 1 0 1 1 0 false 0 ns=1;i=10776 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=10774 i=40 false i=68 i=297 BooleanOut ns=1;i=9898 -1 i=297 SByteOut ns=1;i=9899 -1 i=297 ByteOut ns=1;i=9900 -1 i=297 Int16Out ns=1;i=9901 -1 i=297 UInt16Out ns=1;i=9902 -1 i=297 Int32Out ns=1;i=9903 -1 i=297 UInt32Out ns=1;i=9904 -1 i=297 Int64Out ns=1;i=9905 -1 i=297 UInt64Out ns=1;i=9906 -1 i=297 FloatOut ns=1;i=9907 -1 i=297 DoubleOut ns=1;i=9908 -1 i=297 StringOut ns=1;i=9909 -1 i=296 1 0 1 1 0 false 0 ns=1;i=10777 Method_4 1 UserScalarMethod2 UserScalarMethod2 0 0 0 i=47 true ns=1;i=10755 i=46 false ns=1;i=10778 i=46 false ns=1;i=10779 true true ns=1;i=10778 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10777 i=40 false i=68 i=297 DateTimeIn ns=1;i=9910 -1 i=297 GuidIn ns=1;i=9911 -1 i=297 ByteStringIn ns=1;i=9912 -1 i=297 XmlElementIn ns=1;i=9913 -1 i=297 NodeIdIn ns=1;i=9914 -1 i=297 ExpandedNodeIdIn ns=1;i=9915 -1 i=297 QualifiedNameIn ns=1;i=9916 -1 i=297 LocalizedTextIn ns=1;i=9917 -1 i=297 StatusCodeIn ns=1;i=9918 -1 i=297 VariantIn ns=1;i=9919 -1 i=296 1 0 1 1 0 false 0 ns=1;i=10779 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=10777 i=40 false i=68 i=297 DateTimeOut ns=1;i=9910 -1 i=297 GuidOut ns=1;i=9911 -1 i=297 ByteStringOut ns=1;i=9912 -1 i=297 XmlElementOut ns=1;i=9913 -1 i=297 NodeIdOut ns=1;i=9914 -1 i=297 ExpandedNodeIdOut ns=1;i=9915 -1 i=297 QualifiedNameOut ns=1;i=9916 -1 i=297 LocalizedTextOut ns=1;i=9917 -1 i=297 StatusCodeOut ns=1;i=9918 -1 i=297 VariantOut ns=1;i=9919 -1 i=296 1 0 1 1 0 false 0 ns=1;i=10780 Method_4 1 UserArrayMethod1 UserArrayMethod1 0 0 0 i=47 true ns=1;i=10755 i=46 false ns=1;i=10781 i=46 false ns=1;i=10782 true true ns=1;i=10781 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10780 i=40 false i=68 i=297 BooleanIn ns=1;i=9898 1 0 i=297 SByteIn ns=1;i=9899 1 0 i=297 ByteIn ns=1;i=9900 1 0 i=297 Int16In ns=1;i=9901 1 0 i=297 UInt16In ns=1;i=9902 1 0 i=297 Int32In ns=1;i=9903 1 0 i=297 UInt32In ns=1;i=9904 1 0 i=297 Int64In ns=1;i=9905 1 0 i=297 UInt64In ns=1;i=9906 1 0 i=297 FloatIn ns=1;i=9907 1 0 i=297 DoubleIn ns=1;i=9908 1 0 i=297 StringIn ns=1;i=9909 1 0 i=296 1 0 1 1 0 false 0 ns=1;i=10782 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=10780 i=40 false i=68 i=297 BooleanOut ns=1;i=9898 1 0 i=297 SByteOut ns=1;i=9899 1 0 i=297 ByteOut ns=1;i=9900 1 0 i=297 Int16Out ns=1;i=9901 1 0 i=297 UInt16Out ns=1;i=9902 1 0 i=297 Int32Out ns=1;i=9903 1 0 i=297 UInt32Out ns=1;i=9904 1 0 i=297 Int64Out ns=1;i=9905 1 0 i=297 UInt64Out ns=1;i=9906 1 0 i=297 FloatOut ns=1;i=9907 1 0 i=297 DoubleOut ns=1;i=9908 1 0 i=297 StringOut ns=1;i=9909 1 0 i=296 1 0 1 1 0 false 0 ns=1;i=10783 Method_4 1 UserArrayMethod2 UserArrayMethod2 0 0 0 i=47 true ns=1;i=10755 i=46 false ns=1;i=10784 i=46 false ns=1;i=10785 true true ns=1;i=10784 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10783 i=40 false i=68 i=297 DateTimeIn ns=1;i=9910 1 0 i=297 GuidIn ns=1;i=9911 1 0 i=297 ByteStringIn ns=1;i=9912 1 0 i=297 XmlElementIn ns=1;i=9913 1 0 i=297 NodeIdIn ns=1;i=9914 1 0 i=297 ExpandedNodeIdIn ns=1;i=9915 1 0 i=297 QualifiedNameIn ns=1;i=9916 1 0 i=297 LocalizedTextIn ns=1;i=9917 1 0 i=297 StatusCodeIn ns=1;i=9918 1 0 i=297 VariantIn ns=1;i=9919 1 0 i=296 1 0 1 1 0 false 0 ns=1;i=10785 Variable_2 0 OutputArguments OutputArguments 0 0 0 i=46 true ns=1;i=10783 i=40 false i=68 i=297 DateTimeOut ns=1;i=9910 1 0 i=297 GuidOut ns=1;i=9911 1 0 i=297 ByteStringOut ns=1;i=9912 1 0 i=297 XmlElementOut ns=1;i=9913 1 0 i=297 NodeIdOut ns=1;i=9914 1 0 i=297 ExpandedNodeIdOut ns=1;i=9915 1 0 i=297 QualifiedNameOut ns=1;i=9916 1 0 i=297 LocalizedTextOut ns=1;i=9917 1 0 i=297 StatusCodeOut ns=1;i=9918 1 0 i=297 VariantOut ns=1;i=9919 1 0 i=296 1 0 1 1 0 false 0 ns=1;i=10786 Object_1 1 Dynamic Dynamic 0 0 0 i=47 true ns=1;i=10157 i=40 false i=61 i=48 true ns=1;i=10157 i=36 false ns=1;i=10787 i=36 false ns=1;i=10871 i=47 false ns=1;i=10787 i=47 false ns=1;i=10871 i=47 false ns=1;i=10955 i=47 false ns=1;i=11034 i=47 false ns=1;i=11113 i=47 false ns=1;i=11248 1 ns=1;i=10787 Object_1 1 Scalar Scalar 0 0 0 i=47 true ns=1;i=10786 i=40 false ns=1;i=9450 i=36 true ns=1;i=10786 i=36 false ns=1;i=10791 i=46 false ns=1;i=10788 i=47 false ns=1;i=10789 i=47 false ns=1;i=10791 i=47 false ns=1;i=10844 i=47 false ns=1;i=10845 i=47 false ns=1;i=10846 i=47 false ns=1;i=10847 i=47 false ns=1;i=10848 i=47 false ns=1;i=10849 i=47 false ns=1;i=10850 i=47 false ns=1;i=10851 i=47 false ns=1;i=10852 i=47 false ns=1;i=10853 i=47 false ns=1;i=10854 i=47 false ns=1;i=10855 i=47 false ns=1;i=10856 i=47 false ns=1;i=10857 i=47 false ns=1;i=10858 i=47 false ns=1;i=10859 i=47 false ns=1;i=10860 i=47 false ns=1;i=10861 i=47 false ns=1;i=10862 i=47 false ns=1;i=10863 i=47 false ns=1;i=10864 i=47 false ns=1;i=10865 i=47 false ns=1;i=10866 i=47 false ns=1;i=10867 i=47 false ns=1;i=10868 i=47 false ns=1;i=10869 i=47 false ns=1;i=10870 0 ns=1;i=10788 Variable_2 1 SimulationActive SimulationActive If true the server will produce new values for each monitored variable. 0 0 0 i=46 true ns=1;i=10787 i=40 false i=68 true i=1 -1 1 1 0 false 0 ns=1;i=10789 Method_4 1 GenerateValues GenerateValues 0 0 0 i=47 true ns=1;i=10787 i=46 false ns=1;i=10790 true true ns=1;i=10790 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10789 i=40 false i=68 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 0 false 0 ns=1;i=10791 Object_1 1 CycleComplete CycleComplete 0 0 0 i=47 true ns=1;i=10787 i=40 false i=2881 i=36 true ns=1;i=10787 i=46 false ns=1;i=10792 i=46 false ns=1;i=10793 i=46 false ns=1;i=10794 i=46 false ns=1;i=10795 i=46 false ns=1;i=10796 i=46 false ns=1;i=10797 i=46 false ns=1;i=10799 i=46 false ns=1;i=10800 i=46 false ns=1;i=11606 i=46 false ns=1;i=11607 i=46 false ns=1;i=11571 i=46 false ns=1;i=10801 i=46 false ns=1;i=10802 i=47 false ns=1;i=10803 i=47 false ns=1;i=10809 i=47 false ns=1;i=10813 i=47 false ns=1;i=10815 i=46 false ns=1;i=10817 i=47 false ns=1;i=10819 i=47 false ns=1;i=10818 i=47 false ns=1;i=10820 i=47 false ns=1;i=10824 i=47 false ns=1;i=10840 0 ns=1;i=10792 Variable_2 0 EventId EventId 0 0 0 i=46 true ns=1;i=10791 i=40 false i=68 i=15 -1 1 1 0 false 0 ns=1;i=10793 Variable_2 0 EventType EventType 0 0 0 i=46 true ns=1;i=10791 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10794 Variable_2 0 SourceNode SourceNode 0 0 0 i=46 true ns=1;i=10791 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10795 Variable_2 0 SourceName SourceName 0 0 0 i=46 true ns=1;i=10791 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=10796 Variable_2 0 Time Time 0 0 0 i=46 true ns=1;i=10791 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10797 Variable_2 0 ReceiveTime ReceiveTime 0 0 0 i=46 true ns=1;i=10791 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10799 Variable_2 0 Message Message 0 0 0 i=46 true ns=1;i=10791 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=10800 Variable_2 0 Severity Severity 0 0 0 i=46 true ns=1;i=10791 i=40 false i=68 0 i=5 -1 1 1 0 false 0 ns=1;i=10801 Variable_2 0 BranchId BranchId 0 0 0 i=46 true ns=1;i=10791 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10802 Variable_2 0 Retain Retain 0 0 0 i=46 true ns=1;i=10791 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10803 Variable_2 0 EnabledState EnabledState 0 0 0 i=47 true ns=1;i=10791 i=40 false i=8995 i=9004 false ns=1;i=10824 i=9004 false ns=1;i=10832 i=46 false ns=1;i=10804 i=21 -1 1 1 0 false 0 ns=1;i=10804 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=10803 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10809 Variable_2 0 Quality Quality 0 0 0 i=47 true ns=1;i=10791 i=40 false i=9002 i=46 false ns=1;i=10810 0 i=19 -1 1 1 0 false 0 ns=1;i=10810 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10809 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10813 Variable_2 0 LastSeverity LastSeverity 0 0 0 i=47 true ns=1;i=10791 i=40 false i=9002 i=46 false ns=1;i=10814 0 i=5 -1 1 1 0 false 0 ns=1;i=10814 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10813 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10815 Variable_2 0 Comment Comment 0 0 0 i=47 true ns=1;i=10791 i=40 false i=9002 i=46 false ns=1;i=10816 i=21 -1 1 1 0 false 0 ns=1;i=10816 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10815 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10817 Variable_2 0 ClientUserId ClientUserId 0 0 0 i=46 true ns=1;i=10791 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=10818 Method_4 0 Enable Enable 0 0 0 i=47 true ns=1;i=10791 i=3065 false i=2803 true true ns=1;i=10819 Method_4 0 Disable Disable 0 0 0 i=47 true ns=1;i=10791 i=3065 false i=2803 true true ns=1;i=10820 Method_4 0 AddComment AddComment 0 0 0 i=47 true ns=1;i=10791 i=3065 false i=2829 i=46 false ns=1;i=10821 true true ns=1;i=10821 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10820 i=40 false i=68 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=10824 Variable_2 0 AckedState AckedState 0 0 0 i=47 true ns=1;i=10791 i=40 false i=8995 i=9004 true ns=1;i=10803 i=46 false ns=1;i=10825 i=21 -1 1 1 0 false 0 ns=1;i=10825 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=10824 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10840 Method_4 0 Acknowledge Acknowledge 0 0 0 i=47 true ns=1;i=10791 i=3065 false i=8944 i=46 false ns=1;i=10841 true true ns=1;i=10841 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10840 i=40 false i=68 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=10844 Variable_2 1 BooleanValue BooleanValue 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 false i=1 -1 1 1 0 false 0 ns=1;i=10845 Variable_2 1 SByteValue SByteValue 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 0 i=2 -1 1 1 0 false 0 ns=1;i=10846 Variable_2 1 ByteValue ByteValue 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 0 i=3 -1 1 1 0 false 0 ns=1;i=10847 Variable_2 1 Int16Value Int16Value 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 0 i=4 -1 1 1 0 false 0 ns=1;i=10848 Variable_2 1 UInt16Value UInt16Value 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 0 i=5 -1 1 1 0 false 0 ns=1;i=10849 Variable_2 1 Int32Value Int32Value 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 0 i=6 -1 1 1 0 false 0 ns=1;i=10850 Variable_2 1 UInt32Value UInt32Value 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 0 i=7 -1 1 1 0 false 0 ns=1;i=10851 Variable_2 1 Int64Value Int64Value 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 0 i=8 -1 1 1 0 false 0 ns=1;i=10852 Variable_2 1 UInt64Value UInt64Value 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 0 i=9 -1 1 1 0 false 0 ns=1;i=10853 Variable_2 1 FloatValue FloatValue 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 0 i=10 -1 1 1 0 false 0 ns=1;i=10854 Variable_2 1 DoubleValue DoubleValue 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 0 i=11 -1 1 1 0 false 0 ns=1;i=10855 Variable_2 1 StringValue StringValue 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 i=12 -1 1 1 0 false 0 ns=1;i=10856 Variable_2 1 DateTimeValue DateTimeValue 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 0001-01-01T00:00:00 i=13 -1 1 1 0 false 0 ns=1;i=10857 Variable_2 1 GuidValue GuidValue 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 00000000-0000-0000-0000-000000000000 i=14 -1 1 1 0 false 0 ns=1;i=10858 Variable_2 1 ByteStringValue ByteStringValue 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 i=15 -1 1 1 0 false 0 ns=1;i=10859 Variable_2 1 XmlElementValue XmlElementValue 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 i=16 -1 1 1 0 false 0 ns=1;i=10860 Variable_2 1 NodeIdValue NodeIdValue 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10861 Variable_2 1 ExpandedNodeIdValue ExpandedNodeIdValue 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 i=0 i=18 -1 1 1 0 false 0 ns=1;i=10862 Variable_2 1 QualifiedNameValue QualifiedNameValue 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 0 i=20 -1 1 1 0 false 0 ns=1;i=10863 Variable_2 1 LocalizedTextValue LocalizedTextValue 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 i=21 -1 1 1 0 false 0 ns=1;i=10864 Variable_2 1 StatusCodeValue StatusCodeValue 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 0 i=19 -1 1 1 0 false 0 ns=1;i=10865 Variable_2 1 VariantValue VariantValue 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 i=24 -1 1 1 0 false 0 ns=1;i=10866 Variable_2 1 EnumerationValue EnumerationValue 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 0 i=29 -1 1 1 0 false 0 ns=1;i=10867 Variable_2 1 StructureValue StructureValue 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 i=22 -1 1 1 0 false 0 ns=1;i=10868 Variable_2 1 NumberValue NumberValue 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 0 i=26 -1 1 1 0 false 0 ns=1;i=10869 Variable_2 1 IntegerValue IntegerValue 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 0 i=27 -1 1 1 0 false 0 ns=1;i=10870 Variable_2 1 UIntegerValue UIntegerValue 0 0 0 i=47 true ns=1;i=10787 i=40 false i=63 0 i=28 -1 1 1 0 false 0 ns=1;i=10871 Object_1 1 Array Array 0 0 0 i=47 true ns=1;i=10786 i=40 false ns=1;i=9679 i=36 true ns=1;i=10786 i=36 false ns=1;i=10875 i=46 false ns=1;i=10872 i=47 false ns=1;i=10873 i=47 false ns=1;i=10875 i=47 false ns=1;i=10928 i=47 false ns=1;i=10929 i=47 false ns=1;i=10930 i=47 false ns=1;i=10931 i=47 false ns=1;i=10932 i=47 false ns=1;i=10933 i=47 false ns=1;i=10934 i=47 false ns=1;i=10935 i=47 false ns=1;i=10936 i=47 false ns=1;i=10937 i=47 false ns=1;i=10938 i=47 false ns=1;i=10939 i=47 false ns=1;i=10940 i=47 false ns=1;i=10941 i=47 false ns=1;i=10942 i=47 false ns=1;i=10943 i=47 false ns=1;i=10944 i=47 false ns=1;i=10945 i=47 false ns=1;i=10946 i=47 false ns=1;i=10947 i=47 false ns=1;i=10948 i=47 false ns=1;i=10949 i=47 false ns=1;i=10950 i=47 false ns=1;i=10951 i=47 false ns=1;i=10952 i=47 false ns=1;i=10953 i=47 false ns=1;i=10954 0 ns=1;i=10872 Variable_2 1 SimulationActive SimulationActive If true the server will produce new values for each monitored variable. 0 0 0 i=46 true ns=1;i=10871 i=40 false i=68 true i=1 -1 1 1 0 false 0 ns=1;i=10873 Method_4 1 GenerateValues GenerateValues 0 0 0 i=47 true ns=1;i=10871 i=46 false ns=1;i=10874 true true ns=1;i=10874 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10873 i=40 false i=68 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 0 false 0 ns=1;i=10875 Object_1 1 CycleComplete CycleComplete 0 0 0 i=47 true ns=1;i=10871 i=40 false i=2881 i=36 true ns=1;i=10871 i=46 false ns=1;i=10876 i=46 false ns=1;i=10877 i=46 false ns=1;i=10878 i=46 false ns=1;i=10879 i=46 false ns=1;i=10880 i=46 false ns=1;i=10881 i=46 false ns=1;i=10883 i=46 false ns=1;i=10884 i=46 false ns=1;i=11608 i=46 false ns=1;i=11609 i=46 false ns=1;i=11572 i=46 false ns=1;i=10885 i=46 false ns=1;i=10886 i=47 false ns=1;i=10887 i=47 false ns=1;i=10893 i=47 false ns=1;i=10897 i=47 false ns=1;i=10899 i=46 false ns=1;i=10901 i=47 false ns=1;i=10903 i=47 false ns=1;i=10902 i=47 false ns=1;i=10904 i=47 false ns=1;i=10908 i=47 false ns=1;i=10924 0 ns=1;i=10876 Variable_2 0 EventId EventId 0 0 0 i=46 true ns=1;i=10875 i=40 false i=68 i=15 -1 1 1 0 false 0 ns=1;i=10877 Variable_2 0 EventType EventType 0 0 0 i=46 true ns=1;i=10875 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10878 Variable_2 0 SourceNode SourceNode 0 0 0 i=46 true ns=1;i=10875 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10879 Variable_2 0 SourceName SourceName 0 0 0 i=46 true ns=1;i=10875 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=10880 Variable_2 0 Time Time 0 0 0 i=46 true ns=1;i=10875 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10881 Variable_2 0 ReceiveTime ReceiveTime 0 0 0 i=46 true ns=1;i=10875 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10883 Variable_2 0 Message Message 0 0 0 i=46 true ns=1;i=10875 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=10884 Variable_2 0 Severity Severity 0 0 0 i=46 true ns=1;i=10875 i=40 false i=68 0 i=5 -1 1 1 0 false 0 ns=1;i=10885 Variable_2 0 BranchId BranchId 0 0 0 i=46 true ns=1;i=10875 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10886 Variable_2 0 Retain Retain 0 0 0 i=46 true ns=1;i=10875 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10887 Variable_2 0 EnabledState EnabledState 0 0 0 i=47 true ns=1;i=10875 i=40 false i=8995 i=9004 false ns=1;i=10908 i=9004 false ns=1;i=10916 i=46 false ns=1;i=10888 i=21 -1 1 1 0 false 0 ns=1;i=10888 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=10887 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10893 Variable_2 0 Quality Quality 0 0 0 i=47 true ns=1;i=10875 i=40 false i=9002 i=46 false ns=1;i=10894 0 i=19 -1 1 1 0 false 0 ns=1;i=10894 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10893 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10897 Variable_2 0 LastSeverity LastSeverity 0 0 0 i=47 true ns=1;i=10875 i=40 false i=9002 i=46 false ns=1;i=10898 0 i=5 -1 1 1 0 false 0 ns=1;i=10898 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10897 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10899 Variable_2 0 Comment Comment 0 0 0 i=47 true ns=1;i=10875 i=40 false i=9002 i=46 false ns=1;i=10900 i=21 -1 1 1 0 false 0 ns=1;i=10900 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10899 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10901 Variable_2 0 ClientUserId ClientUserId 0 0 0 i=46 true ns=1;i=10875 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=10902 Method_4 0 Enable Enable 0 0 0 i=47 true ns=1;i=10875 i=3065 false i=2803 true true ns=1;i=10903 Method_4 0 Disable Disable 0 0 0 i=47 true ns=1;i=10875 i=3065 false i=2803 true true ns=1;i=10904 Method_4 0 AddComment AddComment 0 0 0 i=47 true ns=1;i=10875 i=3065 false i=2829 i=46 false ns=1;i=10905 true true ns=1;i=10905 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10904 i=40 false i=68 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=10908 Variable_2 0 AckedState AckedState 0 0 0 i=47 true ns=1;i=10875 i=40 false i=8995 i=9004 true ns=1;i=10887 i=46 false ns=1;i=10909 i=21 -1 1 1 0 false 0 ns=1;i=10909 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=10908 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10924 Method_4 0 Acknowledge Acknowledge 0 0 0 i=47 true ns=1;i=10875 i=3065 false i=8944 i=46 false ns=1;i=10925 true true ns=1;i=10925 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10924 i=40 false i=68 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=10928 Variable_2 1 BooleanValue BooleanValue 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=1 1 0 1 1 0 false 0 ns=1;i=10929 Variable_2 1 SByteValue SByteValue 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=2 1 0 1 1 0 false 0 ns=1;i=10930 Variable_2 1 ByteValue ByteValue 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=3 1 0 1 1 0 false 0 ns=1;i=10931 Variable_2 1 Int16Value Int16Value 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=4 1 0 1 1 0 false 0 ns=1;i=10932 Variable_2 1 UInt16Value UInt16Value 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=5 1 0 1 1 0 false 0 ns=1;i=10933 Variable_2 1 Int32Value Int32Value 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=6 1 0 1 1 0 false 0 ns=1;i=10934 Variable_2 1 UInt32Value UInt32Value 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=7 1 0 1 1 0 false 0 ns=1;i=10935 Variable_2 1 Int64Value Int64Value 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=8 1 0 1 1 0 false 0 ns=1;i=10936 Variable_2 1 UInt64Value UInt64Value 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=9 1 0 1 1 0 false 0 ns=1;i=10937 Variable_2 1 FloatValue FloatValue 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=10 1 0 1 1 0 false 0 ns=1;i=10938 Variable_2 1 DoubleValue DoubleValue 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=11 1 0 1 1 0 false 0 ns=1;i=10939 Variable_2 1 StringValue StringValue 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=12 1 0 1 1 0 false 0 ns=1;i=10940 Variable_2 1 DateTimeValue DateTimeValue 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=13 1 0 1 1 0 false 0 ns=1;i=10941 Variable_2 1 GuidValue GuidValue 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=14 1 0 1 1 0 false 0 ns=1;i=10942 Variable_2 1 ByteStringValue ByteStringValue 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=15 1 0 1 1 0 false 0 ns=1;i=10943 Variable_2 1 XmlElementValue XmlElementValue 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=16 1 0 1 1 0 false 0 ns=1;i=10944 Variable_2 1 NodeIdValue NodeIdValue 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=17 1 0 1 1 0 false 0 ns=1;i=10945 Variable_2 1 ExpandedNodeIdValue ExpandedNodeIdValue 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=18 1 0 1 1 0 false 0 ns=1;i=10946 Variable_2 1 QualifiedNameValue QualifiedNameValue 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=20 1 0 1 1 0 false 0 ns=1;i=10947 Variable_2 1 LocalizedTextValue LocalizedTextValue 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=21 1 0 1 1 0 false 0 ns=1;i=10948 Variable_2 1 StatusCodeValue StatusCodeValue 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=19 1 0 1 1 0 false 0 ns=1;i=10949 Variable_2 1 VariantValue VariantValue 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=24 1 0 1 1 0 false 0 ns=1;i=10950 Variable_2 1 EnumerationValue EnumerationValue 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=29 1 0 1 1 0 false 0 ns=1;i=10951 Variable_2 1 StructureValue StructureValue 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=22 1 0 1 1 0 false 0 ns=1;i=10952 Variable_2 1 NumberValue NumberValue 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=26 1 0 1 1 0 false 0 ns=1;i=10953 Variable_2 1 IntegerValue IntegerValue 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=27 1 0 1 1 0 false 0 ns=1;i=10954 Variable_2 1 UIntegerValue UIntegerValue 0 0 0 i=47 true ns=1;i=10871 i=40 false i=63 i=28 1 0 1 1 0 false 0 ns=1;i=10955 Object_1 1 UserScalar UserScalar 0 0 0 i=47 true ns=1;i=10786 i=40 false ns=1;i=9921 i=36 false ns=1;i=10959 i=46 false ns=1;i=10956 i=47 false ns=1;i=10957 i=47 false ns=1;i=10959 i=47 false ns=1;i=11012 i=47 false ns=1;i=11013 i=47 false ns=1;i=11014 i=47 false ns=1;i=11015 i=47 false ns=1;i=11016 i=47 false ns=1;i=11017 i=47 false ns=1;i=11018 i=47 false ns=1;i=11019 i=47 false ns=1;i=11020 i=47 false ns=1;i=11021 i=47 false ns=1;i=11022 i=47 false ns=1;i=11023 i=47 false ns=1;i=11024 i=47 false ns=1;i=11025 i=47 false ns=1;i=11026 i=47 false ns=1;i=11027 i=47 false ns=1;i=11028 i=47 false ns=1;i=11029 i=47 false ns=1;i=11030 i=47 false ns=1;i=11031 i=47 false ns=1;i=11032 i=47 false ns=1;i=11033 0 ns=1;i=10956 Variable_2 1 SimulationActive SimulationActive If true the server will produce new values for each monitored variable. 0 0 0 i=46 true ns=1;i=10955 i=40 false i=68 true i=1 -1 1 1 0 false 0 ns=1;i=10957 Method_4 1 GenerateValues GenerateValues 0 0 0 i=47 true ns=1;i=10955 i=46 false ns=1;i=10958 true true ns=1;i=10958 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10957 i=40 false i=68 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 0 false 0 ns=1;i=10959 Object_1 1 CycleComplete CycleComplete 0 0 0 i=47 true ns=1;i=10955 i=40 false i=2881 i=36 true ns=1;i=10955 i=46 false ns=1;i=10960 i=46 false ns=1;i=10961 i=46 false ns=1;i=10962 i=46 false ns=1;i=10963 i=46 false ns=1;i=10964 i=46 false ns=1;i=10965 i=46 false ns=1;i=10967 i=46 false ns=1;i=10968 i=46 false ns=1;i=11610 i=46 false ns=1;i=11611 i=46 false ns=1;i=11573 i=46 false ns=1;i=10969 i=46 false ns=1;i=10970 i=47 false ns=1;i=10971 i=47 false ns=1;i=10977 i=47 false ns=1;i=10981 i=47 false ns=1;i=10983 i=46 false ns=1;i=10985 i=47 false ns=1;i=10987 i=47 false ns=1;i=10986 i=47 false ns=1;i=10988 i=47 false ns=1;i=10992 i=47 false ns=1;i=11008 0 ns=1;i=10960 Variable_2 0 EventId EventId 0 0 0 i=46 true ns=1;i=10959 i=40 false i=68 i=15 -1 1 1 0 false 0 ns=1;i=10961 Variable_2 0 EventType EventType 0 0 0 i=46 true ns=1;i=10959 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10962 Variable_2 0 SourceNode SourceNode 0 0 0 i=46 true ns=1;i=10959 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10963 Variable_2 0 SourceName SourceName 0 0 0 i=46 true ns=1;i=10959 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=10964 Variable_2 0 Time Time 0 0 0 i=46 true ns=1;i=10959 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10965 Variable_2 0 ReceiveTime ReceiveTime 0 0 0 i=46 true ns=1;i=10959 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10967 Variable_2 0 Message Message 0 0 0 i=46 true ns=1;i=10959 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=10968 Variable_2 0 Severity Severity 0 0 0 i=46 true ns=1;i=10959 i=40 false i=68 0 i=5 -1 1 1 0 false 0 ns=1;i=10969 Variable_2 0 BranchId BranchId 0 0 0 i=46 true ns=1;i=10959 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=10970 Variable_2 0 Retain Retain 0 0 0 i=46 true ns=1;i=10959 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10971 Variable_2 0 EnabledState EnabledState 0 0 0 i=47 true ns=1;i=10959 i=40 false i=8995 i=9004 false ns=1;i=10992 i=9004 false ns=1;i=11000 i=46 false ns=1;i=10972 i=21 -1 1 1 0 false 0 ns=1;i=10972 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=10971 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=10977 Variable_2 0 Quality Quality 0 0 0 i=47 true ns=1;i=10959 i=40 false i=9002 i=46 false ns=1;i=10978 0 i=19 -1 1 1 0 false 0 ns=1;i=10978 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10977 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10981 Variable_2 0 LastSeverity LastSeverity 0 0 0 i=47 true ns=1;i=10959 i=40 false i=9002 i=46 false ns=1;i=10982 0 i=5 -1 1 1 0 false 0 ns=1;i=10982 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10981 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10983 Variable_2 0 Comment Comment 0 0 0 i=47 true ns=1;i=10959 i=40 false i=9002 i=46 false ns=1;i=10984 i=21 -1 1 1 0 false 0 ns=1;i=10984 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=10983 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=10985 Variable_2 0 ClientUserId ClientUserId 0 0 0 i=46 true ns=1;i=10959 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=10986 Method_4 0 Enable Enable 0 0 0 i=47 true ns=1;i=10959 i=3065 false i=2803 true true ns=1;i=10987 Method_4 0 Disable Disable 0 0 0 i=47 true ns=1;i=10959 i=3065 false i=2803 true true ns=1;i=10988 Method_4 0 AddComment AddComment 0 0 0 i=47 true ns=1;i=10959 i=3065 false i=2829 i=46 false ns=1;i=10989 true true ns=1;i=10989 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=10988 i=40 false i=68 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=10992 Variable_2 0 AckedState AckedState 0 0 0 i=47 true ns=1;i=10959 i=40 false i=8995 i=9004 true ns=1;i=10971 i=46 false ns=1;i=10993 i=21 -1 1 1 0 false 0 ns=1;i=10993 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=10992 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=11008 Method_4 0 Acknowledge Acknowledge 0 0 0 i=47 true ns=1;i=10959 i=3065 false i=8944 i=46 false ns=1;i=11009 true true ns=1;i=11009 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=11008 i=40 false i=68 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=11012 Variable_2 1 BooleanValue BooleanValue 0 0 0 i=47 true ns=1;i=10955 i=40 false i=63 ns=1;i=9898 -1 1 1 0 false 0 ns=1;i=11013 Variable_2 1 SByteValue SByteValue 0 0 0 i=47 true ns=1;i=10955 i=40 false i=63 ns=1;i=9899 -1 1 1 0 false 0 ns=1;i=11014 Variable_2 1 ByteValue ByteValue 0 0 0 i=47 true ns=1;i=10955 i=40 false i=63 ns=1;i=9900 -1 1 1 0 false 0 ns=1;i=11015 Variable_2 1 Int16Value Int16Value 0 0 0 i=47 true ns=1;i=10955 i=40 false i=63 ns=1;i=9901 -1 1 1 0 false 0 ns=1;i=11016 Variable_2 1 UInt16Value UInt16Value 0 0 0 i=47 true ns=1;i=10955 i=40 false i=63 ns=1;i=9902 -1 1 1 0 false 0 ns=1;i=11017 Variable_2 1 Int32Value Int32Value 0 0 0 i=47 true ns=1;i=10955 i=40 false i=63 ns=1;i=9903 -1 1 1 0 false 0 ns=1;i=11018 Variable_2 1 UInt32Value UInt32Value 0 0 0 i=47 true ns=1;i=10955 i=40 false i=63 ns=1;i=9904 -1 1 1 0 false 0 ns=1;i=11019 Variable_2 1 Int64Value Int64Value 0 0 0 i=47 true ns=1;i=10955 i=40 false i=63 ns=1;i=9905 -1 1 1 0 false 0 ns=1;i=11020 Variable_2 1 UInt64Value UInt64Value 0 0 0 i=47 true ns=1;i=10955 i=40 false i=63 ns=1;i=9906 -1 1 1 0 false 0 ns=1;i=11021 Variable_2 1 FloatValue FloatValue 0 0 0 i=47 true ns=1;i=10955 i=40 false i=63 ns=1;i=9907 -1 1 1 0 false 0 ns=1;i=11022 Variable_2 1 DoubleValue DoubleValue 0 0 0 i=47 true ns=1;i=10955 i=40 false i=63 ns=1;i=9908 -1 1 1 0 false 0 ns=1;i=11023 Variable_2 1 StringValue StringValue 0 0 0 i=47 true ns=1;i=10955 i=40 false i=63 ns=1;i=9909 -1 1 1 0 false 0 ns=1;i=11024 Variable_2 1 DateTimeValue DateTimeValue 0 0 0 i=47 true ns=1;i=10955 i=40 false i=63 ns=1;i=9910 -1 1 1 0 false 0 ns=1;i=11025 Variable_2 1 GuidValue GuidValue 0 0 0 i=47 true ns=1;i=10955 i=40 false i=63 ns=1;i=9911 -1 1 1 0 false 0 ns=1;i=11026 Variable_2 1 ByteStringValue ByteStringValue 0 0 0 i=47 true ns=1;i=10955 i=40 false i=63 ns=1;i=9912 -1 1 1 0 false 0 ns=1;i=11027 Variable_2 1 XmlElementValue XmlElementValue 0 0 0 i=47 true ns=1;i=10955 i=40 false i=63 ns=1;i=9913 -1 1 1 0 false 0 ns=1;i=11028 Variable_2 1 NodeIdValue NodeIdValue 0 0 0 i=47 true ns=1;i=10955 i=40 false i=63 ns=1;i=9914 -1 1 1 0 false 0 ns=1;i=11029 Variable_2 1 ExpandedNodeIdValue ExpandedNodeIdValue 0 0 0 i=47 true ns=1;i=10955 i=40 false i=63 ns=1;i=9915 -1 1 1 0 false 0 ns=1;i=11030 Variable_2 1 QualifiedNameValue QualifiedNameValue 0 0 0 i=47 true ns=1;i=10955 i=40 false i=63 ns=1;i=9916 -1 1 1 0 false 0 ns=1;i=11031 Variable_2 1 LocalizedTextValue LocalizedTextValue 0 0 0 i=47 true ns=1;i=10955 i=40 false i=63 ns=1;i=9917 -1 1 1 0 false 0 ns=1;i=11032 Variable_2 1 StatusCodeValue StatusCodeValue 0 0 0 i=47 true ns=1;i=10955 i=40 false i=63 ns=1;i=9918 -1 1 1 0 false 0 ns=1;i=11033 Variable_2 1 VariantValue VariantValue 0 0 0 i=47 true ns=1;i=10955 i=40 false i=63 ns=1;i=9919 -1 1 1 0 false 0 ns=1;i=11034 Object_1 1 UserArray UserArray 0 0 0 i=47 true ns=1;i=10786 i=40 false ns=1;i=10007 i=36 false ns=1;i=11038 i=46 false ns=1;i=11035 i=47 false ns=1;i=11036 i=47 false ns=1;i=11038 i=47 false ns=1;i=11091 i=47 false ns=1;i=11092 i=47 false ns=1;i=11093 i=47 false ns=1;i=11094 i=47 false ns=1;i=11095 i=47 false ns=1;i=11096 i=47 false ns=1;i=11097 i=47 false ns=1;i=11098 i=47 false ns=1;i=11099 i=47 false ns=1;i=11100 i=47 false ns=1;i=11101 i=47 false ns=1;i=11102 i=47 false ns=1;i=11103 i=47 false ns=1;i=11104 i=47 false ns=1;i=11105 i=47 false ns=1;i=11106 i=47 false ns=1;i=11107 i=47 false ns=1;i=11108 i=47 false ns=1;i=11109 i=47 false ns=1;i=11110 i=47 false ns=1;i=11111 i=47 false ns=1;i=11112 0 ns=1;i=11035 Variable_2 1 SimulationActive SimulationActive If true the server will produce new values for each monitored variable. 0 0 0 i=46 true ns=1;i=11034 i=40 false i=68 true i=1 -1 1 1 0 false 0 ns=1;i=11036 Method_4 1 GenerateValues GenerateValues 0 0 0 i=47 true ns=1;i=11034 i=46 false ns=1;i=11037 true true ns=1;i=11037 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=11036 i=40 false i=68 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 0 false 0 ns=1;i=11038 Object_1 1 CycleComplete CycleComplete 0 0 0 i=47 true ns=1;i=11034 i=40 false i=2881 i=36 true ns=1;i=11034 i=46 false ns=1;i=11039 i=46 false ns=1;i=11040 i=46 false ns=1;i=11041 i=46 false ns=1;i=11042 i=46 false ns=1;i=11043 i=46 false ns=1;i=11044 i=46 false ns=1;i=11046 i=46 false ns=1;i=11047 i=46 false ns=1;i=11612 i=46 false ns=1;i=11613 i=46 false ns=1;i=11574 i=46 false ns=1;i=11048 i=46 false ns=1;i=11049 i=47 false ns=1;i=11050 i=47 false ns=1;i=11056 i=47 false ns=1;i=11060 i=47 false ns=1;i=11062 i=46 false ns=1;i=11064 i=47 false ns=1;i=11066 i=47 false ns=1;i=11065 i=47 false ns=1;i=11067 i=47 false ns=1;i=11071 i=47 false ns=1;i=11087 0 ns=1;i=11039 Variable_2 0 EventId EventId 0 0 0 i=46 true ns=1;i=11038 i=40 false i=68 i=15 -1 1 1 0 false 0 ns=1;i=11040 Variable_2 0 EventType EventType 0 0 0 i=46 true ns=1;i=11038 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11041 Variable_2 0 SourceNode SourceNode 0 0 0 i=46 true ns=1;i=11038 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11042 Variable_2 0 SourceName SourceName 0 0 0 i=46 true ns=1;i=11038 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=11043 Variable_2 0 Time Time 0 0 0 i=46 true ns=1;i=11038 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=11044 Variable_2 0 ReceiveTime ReceiveTime 0 0 0 i=46 true ns=1;i=11038 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=11046 Variable_2 0 Message Message 0 0 0 i=46 true ns=1;i=11038 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=11047 Variable_2 0 Severity Severity 0 0 0 i=46 true ns=1;i=11038 i=40 false i=68 0 i=5 -1 1 1 0 false 0 ns=1;i=11048 Variable_2 0 BranchId BranchId 0 0 0 i=46 true ns=1;i=11038 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11049 Variable_2 0 Retain Retain 0 0 0 i=46 true ns=1;i=11038 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=11050 Variable_2 0 EnabledState EnabledState 0 0 0 i=47 true ns=1;i=11038 i=40 false i=8995 i=9004 false ns=1;i=11071 i=9004 false ns=1;i=11079 i=46 false ns=1;i=11051 i=21 -1 1 1 0 false 0 ns=1;i=11051 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=11050 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=11056 Variable_2 0 Quality Quality 0 0 0 i=47 true ns=1;i=11038 i=40 false i=9002 i=46 false ns=1;i=11057 0 i=19 -1 1 1 0 false 0 ns=1;i=11057 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=11056 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=11060 Variable_2 0 LastSeverity LastSeverity 0 0 0 i=47 true ns=1;i=11038 i=40 false i=9002 i=46 false ns=1;i=11061 0 i=5 -1 1 1 0 false 0 ns=1;i=11061 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=11060 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=11062 Variable_2 0 Comment Comment 0 0 0 i=47 true ns=1;i=11038 i=40 false i=9002 i=46 false ns=1;i=11063 i=21 -1 1 1 0 false 0 ns=1;i=11063 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=11062 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=11064 Variable_2 0 ClientUserId ClientUserId 0 0 0 i=46 true ns=1;i=11038 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=11065 Method_4 0 Enable Enable 0 0 0 i=47 true ns=1;i=11038 i=3065 false i=2803 true true ns=1;i=11066 Method_4 0 Disable Disable 0 0 0 i=47 true ns=1;i=11038 i=3065 false i=2803 true true ns=1;i=11067 Method_4 0 AddComment AddComment 0 0 0 i=47 true ns=1;i=11038 i=3065 false i=2829 i=46 false ns=1;i=11068 true true ns=1;i=11068 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=11067 i=40 false i=68 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=11071 Variable_2 0 AckedState AckedState 0 0 0 i=47 true ns=1;i=11038 i=40 false i=8995 i=9004 true ns=1;i=11050 i=46 false ns=1;i=11072 i=21 -1 1 1 0 false 0 ns=1;i=11072 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=11071 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=11087 Method_4 0 Acknowledge Acknowledge 0 0 0 i=47 true ns=1;i=11038 i=3065 false i=8944 i=46 false ns=1;i=11088 true true ns=1;i=11088 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=11087 i=40 false i=68 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=11091 Variable_2 1 BooleanValue BooleanValue 0 0 0 i=47 true ns=1;i=11034 i=40 false i=63 ns=1;i=9898 1 0 1 1 0 false 0 ns=1;i=11092 Variable_2 1 SByteValue SByteValue 0 0 0 i=47 true ns=1;i=11034 i=40 false i=63 ns=1;i=9899 1 0 1 1 0 false 0 ns=1;i=11093 Variable_2 1 ByteValue ByteValue 0 0 0 i=47 true ns=1;i=11034 i=40 false i=63 ns=1;i=9900 1 0 1 1 0 false 0 ns=1;i=11094 Variable_2 1 Int16Value Int16Value 0 0 0 i=47 true ns=1;i=11034 i=40 false i=63 ns=1;i=9901 1 0 1 1 0 false 0 ns=1;i=11095 Variable_2 1 UInt16Value UInt16Value 0 0 0 i=47 true ns=1;i=11034 i=40 false i=63 ns=1;i=9902 1 0 1 1 0 false 0 ns=1;i=11096 Variable_2 1 Int32Value Int32Value 0 0 0 i=47 true ns=1;i=11034 i=40 false i=63 ns=1;i=9903 1 0 1 1 0 false 0 ns=1;i=11097 Variable_2 1 UInt32Value UInt32Value 0 0 0 i=47 true ns=1;i=11034 i=40 false i=63 ns=1;i=9904 1 0 1 1 0 false 0 ns=1;i=11098 Variable_2 1 Int64Value Int64Value 0 0 0 i=47 true ns=1;i=11034 i=40 false i=63 ns=1;i=9905 1 0 1 1 0 false 0 ns=1;i=11099 Variable_2 1 UInt64Value UInt64Value 0 0 0 i=47 true ns=1;i=11034 i=40 false i=63 ns=1;i=9906 1 0 1 1 0 false 0 ns=1;i=11100 Variable_2 1 FloatValue FloatValue 0 0 0 i=47 true ns=1;i=11034 i=40 false i=63 ns=1;i=9907 1 0 1 1 0 false 0 ns=1;i=11101 Variable_2 1 DoubleValue DoubleValue 0 0 0 i=47 true ns=1;i=11034 i=40 false i=63 ns=1;i=9908 1 0 1 1 0 false 0 ns=1;i=11102 Variable_2 1 StringValue StringValue 0 0 0 i=47 true ns=1;i=11034 i=40 false i=63 ns=1;i=9909 1 0 1 1 0 false 0 ns=1;i=11103 Variable_2 1 DateTimeValue DateTimeValue 0 0 0 i=47 true ns=1;i=11034 i=40 false i=63 ns=1;i=9910 1 0 1 1 0 false 0 ns=1;i=11104 Variable_2 1 GuidValue GuidValue 0 0 0 i=47 true ns=1;i=11034 i=40 false i=63 ns=1;i=9911 1 0 1 1 0 false 0 ns=1;i=11105 Variable_2 1 ByteStringValue ByteStringValue 0 0 0 i=47 true ns=1;i=11034 i=40 false i=63 ns=1;i=9912 1 0 1 1 0 false 0 ns=1;i=11106 Variable_2 1 XmlElementValue XmlElementValue 0 0 0 i=47 true ns=1;i=11034 i=40 false i=63 ns=1;i=9913 1 0 1 1 0 false 0 ns=1;i=11107 Variable_2 1 NodeIdValue NodeIdValue 0 0 0 i=47 true ns=1;i=11034 i=40 false i=63 ns=1;i=9914 1 0 1 1 0 false 0 ns=1;i=11108 Variable_2 1 ExpandedNodeIdValue ExpandedNodeIdValue 0 0 0 i=47 true ns=1;i=11034 i=40 false i=63 ns=1;i=9915 1 0 1 1 0 false 0 ns=1;i=11109 Variable_2 1 QualifiedNameValue QualifiedNameValue 0 0 0 i=47 true ns=1;i=11034 i=40 false i=63 ns=1;i=9916 1 0 1 1 0 false 0 ns=1;i=11110 Variable_2 1 LocalizedTextValue LocalizedTextValue 0 0 0 i=47 true ns=1;i=11034 i=40 false i=63 ns=1;i=9917 1 0 1 1 0 false 0 ns=1;i=11111 Variable_2 1 StatusCodeValue StatusCodeValue 0 0 0 i=47 true ns=1;i=11034 i=40 false i=63 ns=1;i=9918 1 0 1 1 0 false 0 ns=1;i=11112 Variable_2 1 VariantValue VariantValue 0 0 0 i=47 true ns=1;i=11034 i=40 false i=63 ns=1;i=9919 1 0 1 1 0 false 0 ns=1;i=11113 Object_1 1 AnalogScalar AnalogScalar 0 0 0 i=47 true ns=1;i=10786 i=40 false ns=1;i=9534 i=36 false ns=1;i=11117 i=46 false ns=1;i=11114 i=47 false ns=1;i=11115 i=47 false ns=1;i=11117 i=47 false ns=1;i=11170 i=47 false ns=1;i=11176 i=47 false ns=1;i=11182 i=47 false ns=1;i=11188 i=47 false ns=1;i=11194 i=47 false ns=1;i=11200 i=47 false ns=1;i=11206 i=47 false ns=1;i=11212 i=47 false ns=1;i=11218 i=47 false ns=1;i=11224 i=47 false ns=1;i=11230 i=47 false ns=1;i=11236 i=47 false ns=1;i=11242 0 ns=1;i=11114 Variable_2 1 SimulationActive SimulationActive If true the server will produce new values for each monitored variable. 0 0 0 i=46 true ns=1;i=11113 i=40 false i=68 true i=1 -1 1 1 0 false 0 ns=1;i=11115 Method_4 1 GenerateValues GenerateValues 0 0 0 i=47 true ns=1;i=11113 i=46 false ns=1;i=11116 true true ns=1;i=11116 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=11115 i=40 false i=68 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 0 false 0 ns=1;i=11117 Object_1 1 CycleComplete CycleComplete 0 0 0 i=47 true ns=1;i=11113 i=40 false i=2881 i=36 true ns=1;i=11113 i=46 false ns=1;i=11118 i=46 false ns=1;i=11119 i=46 false ns=1;i=11120 i=46 false ns=1;i=11121 i=46 false ns=1;i=11122 i=46 false ns=1;i=11123 i=46 false ns=1;i=11125 i=46 false ns=1;i=11126 i=46 false ns=1;i=11614 i=46 false ns=1;i=11615 i=46 false ns=1;i=11575 i=46 false ns=1;i=11127 i=46 false ns=1;i=11128 i=47 false ns=1;i=11129 i=47 false ns=1;i=11135 i=47 false ns=1;i=11139 i=47 false ns=1;i=11141 i=46 false ns=1;i=11143 i=47 false ns=1;i=11145 i=47 false ns=1;i=11144 i=47 false ns=1;i=11146 i=47 false ns=1;i=11150 i=47 false ns=1;i=11166 0 ns=1;i=11118 Variable_2 0 EventId EventId 0 0 0 i=46 true ns=1;i=11117 i=40 false i=68 i=15 -1 1 1 0 false 0 ns=1;i=11119 Variable_2 0 EventType EventType 0 0 0 i=46 true ns=1;i=11117 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11120 Variable_2 0 SourceNode SourceNode 0 0 0 i=46 true ns=1;i=11117 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11121 Variable_2 0 SourceName SourceName 0 0 0 i=46 true ns=1;i=11117 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=11122 Variable_2 0 Time Time 0 0 0 i=46 true ns=1;i=11117 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=11123 Variable_2 0 ReceiveTime ReceiveTime 0 0 0 i=46 true ns=1;i=11117 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=11125 Variable_2 0 Message Message 0 0 0 i=46 true ns=1;i=11117 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=11126 Variable_2 0 Severity Severity 0 0 0 i=46 true ns=1;i=11117 i=40 false i=68 0 i=5 -1 1 1 0 false 0 ns=1;i=11127 Variable_2 0 BranchId BranchId 0 0 0 i=46 true ns=1;i=11117 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11128 Variable_2 0 Retain Retain 0 0 0 i=46 true ns=1;i=11117 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=11129 Variable_2 0 EnabledState EnabledState 0 0 0 i=47 true ns=1;i=11117 i=40 false i=8995 i=9004 false ns=1;i=11150 i=9004 false ns=1;i=11158 i=46 false ns=1;i=11130 i=21 -1 1 1 0 false 0 ns=1;i=11130 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=11129 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=11135 Variable_2 0 Quality Quality 0 0 0 i=47 true ns=1;i=11117 i=40 false i=9002 i=46 false ns=1;i=11136 0 i=19 -1 1 1 0 false 0 ns=1;i=11136 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=11135 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=11139 Variable_2 0 LastSeverity LastSeverity 0 0 0 i=47 true ns=1;i=11117 i=40 false i=9002 i=46 false ns=1;i=11140 0 i=5 -1 1 1 0 false 0 ns=1;i=11140 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=11139 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=11141 Variable_2 0 Comment Comment 0 0 0 i=47 true ns=1;i=11117 i=40 false i=9002 i=46 false ns=1;i=11142 i=21 -1 1 1 0 false 0 ns=1;i=11142 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=11141 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=11143 Variable_2 0 ClientUserId ClientUserId 0 0 0 i=46 true ns=1;i=11117 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=11144 Method_4 0 Enable Enable 0 0 0 i=47 true ns=1;i=11117 i=3065 false i=2803 true true ns=1;i=11145 Method_4 0 Disable Disable 0 0 0 i=47 true ns=1;i=11117 i=3065 false i=2803 true true ns=1;i=11146 Method_4 0 AddComment AddComment 0 0 0 i=47 true ns=1;i=11117 i=3065 false i=2829 i=46 false ns=1;i=11147 true true ns=1;i=11147 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=11146 i=40 false i=68 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=11150 Variable_2 0 AckedState AckedState 0 0 0 i=47 true ns=1;i=11117 i=40 false i=8995 i=9004 true ns=1;i=11129 i=46 false ns=1;i=11151 i=21 -1 1 1 0 false 0 ns=1;i=11151 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=11150 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=11166 Method_4 0 Acknowledge Acknowledge 0 0 0 i=47 true ns=1;i=11117 i=3065 false i=8944 i=46 false ns=1;i=11167 true true ns=1;i=11167 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=11166 i=40 false i=68 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=11170 Variable_2 1 SByteValue SByteValue 0 0 0 i=47 true ns=1;i=11113 i=40 false i=2368 i=46 false ns=1;i=11173 0 i=2 -1 1 1 0 false 0 ns=1;i=11173 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11170 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11176 Variable_2 1 ByteValue ByteValue 0 0 0 i=47 true ns=1;i=11113 i=40 false i=2368 i=46 false ns=1;i=11179 0 i=3 -1 1 1 0 false 0 ns=1;i=11179 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11176 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11182 Variable_2 1 Int16Value Int16Value 0 0 0 i=47 true ns=1;i=11113 i=40 false i=2368 i=46 false ns=1;i=11185 0 i=4 -1 1 1 0 false 0 ns=1;i=11185 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11182 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11188 Variable_2 1 UInt16Value UInt16Value 0 0 0 i=47 true ns=1;i=11113 i=40 false i=2368 i=46 false ns=1;i=11191 0 i=5 -1 1 1 0 false 0 ns=1;i=11191 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11188 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11194 Variable_2 1 Int32Value Int32Value 0 0 0 i=47 true ns=1;i=11113 i=40 false i=2368 i=46 false ns=1;i=11197 0 i=6 -1 1 1 0 false 0 ns=1;i=11197 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11194 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11200 Variable_2 1 UInt32Value UInt32Value 0 0 0 i=47 true ns=1;i=11113 i=40 false i=2368 i=46 false ns=1;i=11203 0 i=7 -1 1 1 0 false 0 ns=1;i=11203 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11200 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11206 Variable_2 1 Int64Value Int64Value 0 0 0 i=47 true ns=1;i=11113 i=40 false i=2368 i=46 false ns=1;i=11209 0 i=8 -1 1 1 0 false 0 ns=1;i=11209 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11206 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11212 Variable_2 1 UInt64Value UInt64Value 0 0 0 i=47 true ns=1;i=11113 i=40 false i=2368 i=46 false ns=1;i=11215 0 i=9 -1 1 1 0 false 0 ns=1;i=11215 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11212 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11218 Variable_2 1 FloatValue FloatValue 0 0 0 i=47 true ns=1;i=11113 i=40 false i=2368 i=46 false ns=1;i=11221 0 i=10 -1 1 1 0 false 0 ns=1;i=11221 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11218 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11224 Variable_2 1 DoubleValue DoubleValue 0 0 0 i=47 true ns=1;i=11113 i=40 false i=2368 i=46 false ns=1;i=11227 0 i=11 -1 1 1 0 false 0 ns=1;i=11227 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11224 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11230 Variable_2 1 NumberValue NumberValue 0 0 0 i=47 true ns=1;i=11113 i=40 false i=2368 i=46 false ns=1;i=11233 0 i=26 -1 1 1 0 false 0 ns=1;i=11233 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11230 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11236 Variable_2 1 IntegerValue IntegerValue 0 0 0 i=47 true ns=1;i=11113 i=40 false i=2368 i=46 false ns=1;i=11239 0 i=27 -1 1 1 0 false 0 ns=1;i=11239 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11236 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11242 Variable_2 1 UIntegerValue UIntegerValue 0 0 0 i=47 true ns=1;i=11113 i=40 false i=2368 i=46 false ns=1;i=11245 0 i=28 -1 1 1 0 false 0 ns=1;i=11245 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11242 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11248 Object_1 1 AnalogArray AnalogArray 0 0 0 i=47 true ns=1;i=10786 i=40 false ns=1;i=9763 i=36 false ns=1;i=11252 i=46 false ns=1;i=11249 i=47 false ns=1;i=11250 i=47 false ns=1;i=11252 i=47 false ns=1;i=11305 i=47 false ns=1;i=11311 i=47 false ns=1;i=11317 i=47 false ns=1;i=11323 i=47 false ns=1;i=11329 i=47 false ns=1;i=11335 i=47 false ns=1;i=11341 i=47 false ns=1;i=11347 i=47 false ns=1;i=11353 i=47 false ns=1;i=11359 i=47 false ns=1;i=11365 i=47 false ns=1;i=11371 i=47 false ns=1;i=11377 0 ns=1;i=11249 Variable_2 1 SimulationActive SimulationActive If true the server will produce new values for each monitored variable. 0 0 0 i=46 true ns=1;i=11248 i=40 false i=68 true i=1 -1 1 1 0 false 0 ns=1;i=11250 Method_4 1 GenerateValues GenerateValues 0 0 0 i=47 true ns=1;i=11248 i=46 false ns=1;i=11251 true true ns=1;i=11251 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=11250 i=40 false i=68 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 0 false 0 ns=1;i=11252 Object_1 1 CycleComplete CycleComplete 0 0 0 i=47 true ns=1;i=11248 i=40 false i=2881 i=36 true ns=1;i=11248 i=46 false ns=1;i=11253 i=46 false ns=1;i=11254 i=46 false ns=1;i=11255 i=46 false ns=1;i=11256 i=46 false ns=1;i=11257 i=46 false ns=1;i=11258 i=46 false ns=1;i=11260 i=46 false ns=1;i=11261 i=46 false ns=1;i=11616 i=46 false ns=1;i=11617 i=46 false ns=1;i=11576 i=46 false ns=1;i=11262 i=46 false ns=1;i=11263 i=47 false ns=1;i=11264 i=47 false ns=1;i=11270 i=47 false ns=1;i=11274 i=47 false ns=1;i=11276 i=46 false ns=1;i=11278 i=47 false ns=1;i=11280 i=47 false ns=1;i=11279 i=47 false ns=1;i=11281 i=47 false ns=1;i=11285 i=47 false ns=1;i=11301 0 ns=1;i=11253 Variable_2 0 EventId EventId 0 0 0 i=46 true ns=1;i=11252 i=40 false i=68 i=15 -1 1 1 0 false 0 ns=1;i=11254 Variable_2 0 EventType EventType 0 0 0 i=46 true ns=1;i=11252 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11255 Variable_2 0 SourceNode SourceNode 0 0 0 i=46 true ns=1;i=11252 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11256 Variable_2 0 SourceName SourceName 0 0 0 i=46 true ns=1;i=11252 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=11257 Variable_2 0 Time Time 0 0 0 i=46 true ns=1;i=11252 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=11258 Variable_2 0 ReceiveTime ReceiveTime 0 0 0 i=46 true ns=1;i=11252 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=11260 Variable_2 0 Message Message 0 0 0 i=46 true ns=1;i=11252 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=11261 Variable_2 0 Severity Severity 0 0 0 i=46 true ns=1;i=11252 i=40 false i=68 0 i=5 -1 1 1 0 false 0 ns=1;i=11262 Variable_2 0 BranchId BranchId 0 0 0 i=46 true ns=1;i=11252 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11263 Variable_2 0 Retain Retain 0 0 0 i=46 true ns=1;i=11252 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=11264 Variable_2 0 EnabledState EnabledState 0 0 0 i=47 true ns=1;i=11252 i=40 false i=8995 i=9004 false ns=1;i=11285 i=9004 false ns=1;i=11293 i=46 false ns=1;i=11265 i=21 -1 1 1 0 false 0 ns=1;i=11265 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=11264 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=11270 Variable_2 0 Quality Quality 0 0 0 i=47 true ns=1;i=11252 i=40 false i=9002 i=46 false ns=1;i=11271 0 i=19 -1 1 1 0 false 0 ns=1;i=11271 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=11270 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=11274 Variable_2 0 LastSeverity LastSeverity 0 0 0 i=47 true ns=1;i=11252 i=40 false i=9002 i=46 false ns=1;i=11275 0 i=5 -1 1 1 0 false 0 ns=1;i=11275 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=11274 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=11276 Variable_2 0 Comment Comment 0 0 0 i=47 true ns=1;i=11252 i=40 false i=9002 i=46 false ns=1;i=11277 i=21 -1 1 1 0 false 0 ns=1;i=11277 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=11276 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=11278 Variable_2 0 ClientUserId ClientUserId 0 0 0 i=46 true ns=1;i=11252 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=11279 Method_4 0 Enable Enable 0 0 0 i=47 true ns=1;i=11252 i=3065 false i=2803 true true ns=1;i=11280 Method_4 0 Disable Disable 0 0 0 i=47 true ns=1;i=11252 i=3065 false i=2803 true true ns=1;i=11281 Method_4 0 AddComment AddComment 0 0 0 i=47 true ns=1;i=11252 i=3065 false i=2829 i=46 false ns=1;i=11282 true true ns=1;i=11282 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=11281 i=40 false i=68 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=11285 Variable_2 0 AckedState AckedState 0 0 0 i=47 true ns=1;i=11252 i=40 false i=8995 i=9004 true ns=1;i=11264 i=46 false ns=1;i=11286 i=21 -1 1 1 0 false 0 ns=1;i=11286 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=11285 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=11301 Method_4 0 Acknowledge Acknowledge 0 0 0 i=47 true ns=1;i=11252 i=3065 false i=8944 i=46 false ns=1;i=11302 true true ns=1;i=11302 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=11301 i=40 false i=68 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=11305 Variable_2 1 SByteValue SByteValue 0 0 0 i=47 true ns=1;i=11248 i=40 false i=2368 i=46 false ns=1;i=11308 i=2 1 0 1 1 0 false 0 ns=1;i=11308 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11305 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11311 Variable_2 1 ByteValue ByteValue 0 0 0 i=47 true ns=1;i=11248 i=40 false i=2368 i=46 false ns=1;i=11314 i=3 1 0 1 1 0 false 0 ns=1;i=11314 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11311 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11317 Variable_2 1 Int16Value Int16Value 0 0 0 i=47 true ns=1;i=11248 i=40 false i=2368 i=46 false ns=1;i=11320 i=4 1 0 1 1 0 false 0 ns=1;i=11320 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11317 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11323 Variable_2 1 UInt16Value UInt16Value 0 0 0 i=47 true ns=1;i=11248 i=40 false i=2368 i=46 false ns=1;i=11326 i=5 1 0 1 1 0 false 0 ns=1;i=11326 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11323 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11329 Variable_2 1 Int32Value Int32Value 0 0 0 i=47 true ns=1;i=11248 i=40 false i=2368 i=46 false ns=1;i=11332 i=6 1 0 1 1 0 false 0 ns=1;i=11332 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11329 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11335 Variable_2 1 UInt32Value UInt32Value 0 0 0 i=47 true ns=1;i=11248 i=40 false i=2368 i=46 false ns=1;i=11338 i=7 1 0 1 1 0 false 0 ns=1;i=11338 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11335 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11341 Variable_2 1 Int64Value Int64Value 0 0 0 i=47 true ns=1;i=11248 i=40 false i=2368 i=46 false ns=1;i=11344 i=8 1 0 1 1 0 false 0 ns=1;i=11344 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11341 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11347 Variable_2 1 UInt64Value UInt64Value 0 0 0 i=47 true ns=1;i=11248 i=40 false i=2368 i=46 false ns=1;i=11350 i=9 1 0 1 1 0 false 0 ns=1;i=11350 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11347 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11353 Variable_2 1 FloatValue FloatValue 0 0 0 i=47 true ns=1;i=11248 i=40 false i=2368 i=46 false ns=1;i=11356 i=10 1 0 1 1 0 false 0 ns=1;i=11356 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11353 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11359 Variable_2 1 DoubleValue DoubleValue 0 0 0 i=47 true ns=1;i=11248 i=40 false i=2368 i=46 false ns=1;i=11362 i=11 1 0 1 1 0 false 0 ns=1;i=11362 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11359 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11365 Variable_2 1 NumberValue NumberValue 0 0 0 i=47 true ns=1;i=11248 i=40 false i=2368 i=46 false ns=1;i=11368 i=26 1 0 1 1 0 false 0 ns=1;i=11368 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11365 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11371 Variable_2 1 IntegerValue IntegerValue 0 0 0 i=47 true ns=1;i=11248 i=40 false i=2368 i=46 false ns=1;i=11374 i=27 1 0 1 1 0 false 0 ns=1;i=11374 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11371 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11377 Variable_2 1 UIntegerValue UIntegerValue 0 0 0 i=47 true ns=1;i=11248 i=40 false i=2368 i=46 false ns=1;i=11380 i=28 1 0 1 1 0 false 0 ns=1;i=11380 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=11377 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=11383 Object_1 1 Conditions Conditions 0 0 0 i=47 true ns=1;i=10157 i=40 false i=61 i=36 false ns=1;i=11384 i=47 false ns=1;i=11384 1 ns=1;i=11384 Object_1 1 SystemStatus SystemStatus 0 0 0 i=47 true ns=1;i=11383 i=40 false ns=1;i=10123 i=36 true ns=1;i=11383 i=46 false ns=1;i=11385 i=46 false ns=1;i=11386 i=46 false ns=1;i=11387 i=46 false ns=1;i=11388 i=46 false ns=1;i=11389 i=46 false ns=1;i=11390 i=46 false ns=1;i=11392 i=46 false ns=1;i=11393 i=46 false ns=1;i=11618 i=46 false ns=1;i=11619 i=46 false ns=1;i=11577 i=46 false ns=1;i=11394 i=46 false ns=1;i=11395 i=47 false ns=1;i=11396 i=47 false ns=1;i=11402 i=47 false ns=1;i=11406 i=47 false ns=1;i=11408 i=46 false ns=1;i=11410 i=47 false ns=1;i=11412 i=47 false ns=1;i=11411 i=47 false ns=1;i=11413 i=46 false ns=1;i=11417 0 ns=1;i=11385 Variable_2 0 EventId EventId 0 0 0 i=46 true ns=1;i=11384 i=40 false i=68 i=15 -1 1 1 0 false 0 ns=1;i=11386 Variable_2 0 EventType EventType 0 0 0 i=46 true ns=1;i=11384 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11387 Variable_2 0 SourceNode SourceNode 0 0 0 i=46 true ns=1;i=11384 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11388 Variable_2 0 SourceName SourceName 0 0 0 i=46 true ns=1;i=11384 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=11389 Variable_2 0 Time Time 0 0 0 i=46 true ns=1;i=11384 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=11390 Variable_2 0 ReceiveTime ReceiveTime 0 0 0 i=46 true ns=1;i=11384 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=11392 Variable_2 0 Message Message 0 0 0 i=46 true ns=1;i=11384 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=11393 Variable_2 0 Severity Severity 0 0 0 i=46 true ns=1;i=11384 i=40 false i=68 0 i=5 -1 1 1 0 false 0 ns=1;i=11394 Variable_2 0 BranchId BranchId 0 0 0 i=46 true ns=1;i=11384 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11395 Variable_2 0 Retain Retain 0 0 0 i=46 true ns=1;i=11384 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=11396 Variable_2 0 EnabledState EnabledState 0 0 0 i=47 true ns=1;i=11384 i=40 false i=8995 i=46 false ns=1;i=11397 i=21 -1 1 1 0 false 0 ns=1;i=11397 Variable_2 0 Id Id 0 0 0 i=46 true ns=1;i=11396 i=40 false i=68 false i=1 -1 1 1 0 false 0 ns=1;i=11402 Variable_2 0 Quality Quality 0 0 0 i=47 true ns=1;i=11384 i=40 false i=9002 i=46 false ns=1;i=11403 0 i=19 -1 1 1 0 false 0 ns=1;i=11403 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=11402 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=11406 Variable_2 0 LastSeverity LastSeverity 0 0 0 i=47 true ns=1;i=11384 i=40 false i=9002 i=46 false ns=1;i=11407 0 i=5 -1 1 1 0 false 0 ns=1;i=11407 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=11406 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=11408 Variable_2 0 Comment Comment 0 0 0 i=47 true ns=1;i=11384 i=40 false i=9002 i=46 false ns=1;i=11409 i=21 -1 1 1 0 false 0 ns=1;i=11409 Variable_2 0 SourceTimestamp SourceTimestamp 0 0 0 i=46 true ns=1;i=11408 i=40 false i=68 0001-01-01T00:00:00 i=294 -1 1 1 0 false 0 ns=1;i=11410 Variable_2 0 ClientUserId ClientUserId 0 0 0 i=46 true ns=1;i=11384 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=11411 Method_4 0 Enable Enable 0 0 0 i=47 true ns=1;i=11384 i=3065 false i=2803 true true ns=1;i=11412 Method_4 0 Disable Disable 0 0 0 i=47 true ns=1;i=11384 i=3065 false i=2803 true true ns=1;i=11413 Method_4 0 AddComment AddComment 0 0 0 i=47 true ns=1;i=11384 i=3065 false i=2829 i=46 false ns=1;i=11414 true true ns=1;i=11414 Variable_2 0 InputArguments InputArguments 0 0 0 i=46 true ns=1;i=11413 i=40 false i=68 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 0 false 0 ns=1;i=11417 Variable_2 1 MonitoredNodeCount MonitoredNodeCount 0 0 0 i=46 true ns=1;i=11384 i=40 false i=68 0 i=6 -1 1 1 0 false 0 ns=1;i=11418 Object_1 0 Default XML Default XML 0 0 0 i=40 false i=76 i=38 true ns=1;i=9440 i=39 false ns=1;i=11444 0 ns=1;i=11419 Object_1 0 Default XML Default XML 0 0 0 i=40 false i=76 i=38 true ns=1;i=9669 i=39 false ns=1;i=11447 0 ns=1;i=11420 Object_1 0 Default XML Default XML 0 0 0 i=40 false i=76 i=38 true ns=1;i=9920 i=39 false ns=1;i=11450 0 ns=1;i=11421 Object_1 0 Default XML Default XML 0 0 0 i=40 false i=76 i=38 true ns=1;i=10006 i=39 false ns=1;i=11453 0 ns=1;i=11422 Variable_2 1 TestData TestData 0 0 0 i=40 false i=72 i=47 true i=93 i=46 false ns=1;i=11424 i=46 false ns=1;i=15045 i=47 false ns=1;i=11425 i=47 false ns=1;i=11428 i=47 false ns=1;i=11431 i=47 false ns=1;i=11434 i=47 false ns=1;i=1015 i=47 false ns=1;i=24 i=47 false ns=1;i=27 PG9wYzpUeXBlRGljdGlvbmFyeQ0KICB4bWxuczpvcGM9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9y Zy9CaW5hcnlTY2hlbWEvIg0KICB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1M U2NoZW1hLWluc3RhbmNlIg0KICB4bWxuczp1YT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VB LyINCiAgeG1sbnM6dG5zPSJodHRwOi8vdGVzdC5vcmcvVUEvRGF0YS8iDQogIERlZmF1bHRCeXRl T3JkZXI9IkxpdHRsZUVuZGlhbiINCiAgVGFyZ2V0TmFtZXNwYWNlPSJodHRwOi8vdGVzdC5vcmcv VUEvRGF0YS8iDQo+DQogIDxvcGM6SW1wb3J0IE5hbWVzcGFjZT0iaHR0cDovL29wY2ZvdW5kYXRp b24ub3JnL1VBLyIgTG9jYXRpb249Ik9wYy5VYS5CaW5hcnlTY2hlbWEuYnNkIi8+DQoNCiAgPG9w YzpTdHJ1Y3R1cmVkVHlwZSBOYW1lPSJTY2FsYXJWYWx1ZURhdGFUeXBlIiBCYXNlVHlwZT0idWE6 RXh0ZW5zaW9uT2JqZWN0Ij4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkJvb2xlYW5WYWx1ZSIgVHlw ZU5hbWU9Im9wYzpCb29sZWFuIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iU0J5dGVWYWx1ZSIg VHlwZU5hbWU9Im9wYzpTQnl0ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkJ5dGVWYWx1ZSIg VHlwZU5hbWU9Im9wYzpCeXRlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iSW50MTZWYWx1ZSIg VHlwZU5hbWU9Im9wYzpJbnQxNiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IlVJbnQxNlZhbHVl IiBUeXBlTmFtZT0ib3BjOlVJbnQxNiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkludDMyVmFs dWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJVSW50MzJW YWx1ZSIgVHlwZU5hbWU9Im9wYzpVSW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJJbnQ2 NFZhbHVlIiBUeXBlTmFtZT0ib3BjOkludDY0IiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iVUlu dDY0VmFsdWUiIFR5cGVOYW1lPSJvcGM6VUludDY0IiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0i RmxvYXRWYWx1ZSIgVHlwZU5hbWU9Im9wYzpGbG9hdCIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9 IkRvdWJsZVZhbHVlIiBUeXBlTmFtZT0ib3BjOkRvdWJsZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5h bWU9IlN0cmluZ1ZhbHVlIiBUeXBlTmFtZT0ib3BjOlN0cmluZyIgLz4NCiAgICA8b3BjOkZpZWxk IE5hbWU9IkRhdGVUaW1lVmFsdWUiIFR5cGVOYW1lPSJvcGM6RGF0ZVRpbWUiIC8+DQogICAgPG9w YzpGaWVsZCBOYW1lPSJHdWlkVmFsdWUiIFR5cGVOYW1lPSJvcGM6R3VpZCIgLz4NCiAgICA8b3Bj OkZpZWxkIE5hbWU9IkJ5dGVTdHJpbmdWYWx1ZSIgVHlwZU5hbWU9Im9wYzpCeXRlU3RyaW5nIiAv Pg0KICAgIDxvcGM6RmllbGQgTmFtZT0iWG1sRWxlbWVudFZhbHVlIiBUeXBlTmFtZT0idWE6WG1s RWxlbWVudCIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vZGVJZFZhbHVlIiBUeXBlTmFtZT0i dWE6Tm9kZUlkIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iRXhwYW5kZWROb2RlSWRWYWx1ZSIg VHlwZU5hbWU9InVhOkV4cGFuZGVkTm9kZUlkIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iUXVh bGlmaWVkTmFtZVZhbHVlIiBUeXBlTmFtZT0idWE6UXVhbGlmaWVkTmFtZSIgLz4NCiAgICA8b3Bj OkZpZWxkIE5hbWU9IkxvY2FsaXplZFRleHRWYWx1ZSIgVHlwZU5hbWU9InVhOkxvY2FsaXplZFRl eHQiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJTdGF0dXNDb2RlVmFsdWUiIFR5cGVOYW1lPSJ1 YTpTdGF0dXNDb2RlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iVmFyaWFudFZhbHVlIiBUeXBl TmFtZT0idWE6VmFyaWFudCIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkVudW1lcmF0aW9uVmFs dWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJTdHJ1Y3R1 cmVWYWx1ZSIgVHlwZU5hbWU9InVhOkV4dGVuc2lvbk9iamVjdCIgLz4NCiAgICA8b3BjOkZpZWxk IE5hbWU9Ik51bWJlciIgVHlwZU5hbWU9InVhOlZhcmlhbnQiIC8+DQogICAgPG9wYzpGaWVsZCBO YW1lPSJJbnRlZ2VyIiBUeXBlTmFtZT0idWE6VmFyaWFudCIgLz4NCiAgICA8b3BjOkZpZWxkIE5h bWU9IlVJbnRlZ2VyIiBUeXBlTmFtZT0idWE6VmFyaWFudCIgLz4NCiAgPC9vcGM6U3RydWN0dXJl ZFR5cGU+DQoNCiAgPG9wYzpTdHJ1Y3R1cmVkVHlwZSBOYW1lPSJBcnJheVZhbHVlRGF0YVR5cGUi IEJhc2VUeXBlPSJ1YTpFeHRlbnNpb25PYmplY3QiPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9P ZkJvb2xlYW5WYWx1ZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8b3BjOkZpZWxkIE5h bWU9IkJvb2xlYW5WYWx1ZSIgVHlwZU5hbWU9Im9wYzpCb29sZWFuIiBMZW5ndGhGaWVsZD0iTm9P ZkJvb2xlYW5WYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZTQnl0ZVZhbHVlIiBU eXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iU0J5dGVWYWx1ZSIg VHlwZU5hbWU9Im9wYzpTQnl0ZSIgTGVuZ3RoRmllbGQ9Ik5vT2ZTQnl0ZVZhbHVlIiAvPg0KICAg IDxvcGM6RmllbGQgTmFtZT0iTm9PZkJ5dGVWYWx1ZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4N CiAgICA8b3BjOkZpZWxkIE5hbWU9IkJ5dGVWYWx1ZSIgVHlwZU5hbWU9Im9wYzpCeXRlIiBMZW5n dGhGaWVsZD0iTm9PZkJ5dGVWYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZJbnQx NlZhbHVlIiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iSW50 MTZWYWx1ZSIgVHlwZU5hbWU9Im9wYzpJbnQxNiIgTGVuZ3RoRmllbGQ9Ik5vT2ZJbnQxNlZhbHVl IiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZlVJbnQxNlZhbHVlIiBUeXBlTmFtZT0ib3Bj OkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iVUludDE2VmFsdWUiIFR5cGVOYW1lPSJv cGM6VUludDE2IiBMZW5ndGhGaWVsZD0iTm9PZlVJbnQxNlZhbHVlIiAvPg0KICAgIDxvcGM6Rmll bGQgTmFtZT0iTm9PZkludDMyVmFsdWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9w YzpGaWVsZCBOYW1lPSJJbnQzMlZhbHVlIiBUeXBlTmFtZT0ib3BjOkludDMyIiBMZW5ndGhGaWVs ZD0iTm9PZkludDMyVmFsdWUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mVUludDMyVmFs dWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJVSW50MzJW YWx1ZSIgVHlwZU5hbWU9Im9wYzpVSW50MzIiIExlbmd0aEZpZWxkPSJOb09mVUludDMyVmFsdWUi IC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mSW50NjRWYWx1ZSIgVHlwZU5hbWU9Im9wYzpJ bnQzMiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkludDY0VmFsdWUiIFR5cGVOYW1lPSJvcGM6 SW50NjQiIExlbmd0aEZpZWxkPSJOb09mSW50NjRWYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5h bWU9Ik5vT2ZVSW50NjRWYWx1ZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8b3BjOkZp ZWxkIE5hbWU9IlVJbnQ2NFZhbHVlIiBUeXBlTmFtZT0ib3BjOlVJbnQ2NCIgTGVuZ3RoRmllbGQ9 Ik5vT2ZVSW50NjRWYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZGbG9hdFZhbHVl IiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iRmxvYXRWYWx1 ZSIgVHlwZU5hbWU9Im9wYzpGbG9hdCIgTGVuZ3RoRmllbGQ9Ik5vT2ZGbG9hdFZhbHVlIiAvPg0K ICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZkRvdWJsZVZhbHVlIiBUeXBlTmFtZT0ib3BjOkludDMy IiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iRG91YmxlVmFsdWUiIFR5cGVOYW1lPSJvcGM6RG91 YmxlIiBMZW5ndGhGaWVsZD0iTm9PZkRvdWJsZVZhbHVlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFt ZT0iTm9PZlN0cmluZ1ZhbHVlIiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6Rmll bGQgTmFtZT0iU3RyaW5nVmFsdWUiIFR5cGVOYW1lPSJvcGM6U3RyaW5nIiBMZW5ndGhGaWVsZD0i Tm9PZlN0cmluZ1ZhbHVlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZkRhdGVUaW1lVmFs dWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJEYXRlVGlt ZVZhbHVlIiBUeXBlTmFtZT0ib3BjOkRhdGVUaW1lIiBMZW5ndGhGaWVsZD0iTm9PZkRhdGVUaW1l VmFsdWUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mR3VpZFZhbHVlIiBUeXBlTmFtZT0i b3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iR3VpZFZhbHVlIiBUeXBlTmFtZT0i b3BjOkd1aWQiIExlbmd0aEZpZWxkPSJOb09mR3VpZFZhbHVlIiAvPg0KICAgIDxvcGM6RmllbGQg TmFtZT0iTm9PZkJ5dGVTdHJpbmdWYWx1ZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8 b3BjOkZpZWxkIE5hbWU9IkJ5dGVTdHJpbmdWYWx1ZSIgVHlwZU5hbWU9Im9wYzpCeXRlU3RyaW5n IiBMZW5ndGhGaWVsZD0iTm9PZkJ5dGVTdHJpbmdWYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5h bWU9Ik5vT2ZYbWxFbGVtZW50VmFsdWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9w YzpGaWVsZCBOYW1lPSJYbWxFbGVtZW50VmFsdWUiIFR5cGVOYW1lPSJ1YTpYbWxFbGVtZW50IiBM ZW5ndGhGaWVsZD0iTm9PZlhtbEVsZW1lbnRWYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9 Ik5vT2ZOb2RlSWRWYWx1ZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8b3BjOkZpZWxk IE5hbWU9Ik5vZGVJZFZhbHVlIiBUeXBlTmFtZT0idWE6Tm9kZUlkIiBMZW5ndGhGaWVsZD0iTm9P Zk5vZGVJZFZhbHVlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZkV4cGFuZGVkTm9kZUlk VmFsdWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJFeHBh bmRlZE5vZGVJZFZhbHVlIiBUeXBlTmFtZT0idWE6RXhwYW5kZWROb2RlSWQiIExlbmd0aEZpZWxk PSJOb09mRXhwYW5kZWROb2RlSWRWYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZR dWFsaWZpZWROYW1lVmFsdWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVs ZCBOYW1lPSJRdWFsaWZpZWROYW1lVmFsdWUiIFR5cGVOYW1lPSJ1YTpRdWFsaWZpZWROYW1lIiBM ZW5ndGhGaWVsZD0iTm9PZlF1YWxpZmllZE5hbWVWYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5h bWU9Ik5vT2ZMb2NhbGl6ZWRUZXh0VmFsdWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAg PG9wYzpGaWVsZCBOYW1lPSJMb2NhbGl6ZWRUZXh0VmFsdWUiIFR5cGVOYW1lPSJ1YTpMb2NhbGl6 ZWRUZXh0IiBMZW5ndGhGaWVsZD0iTm9PZkxvY2FsaXplZFRleHRWYWx1ZSIgLz4NCiAgICA8b3Bj OkZpZWxkIE5hbWU9Ik5vT2ZTdGF0dXNDb2RlVmFsdWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+ DQogICAgPG9wYzpGaWVsZCBOYW1lPSJTdGF0dXNDb2RlVmFsdWUiIFR5cGVOYW1lPSJ1YTpTdGF0 dXNDb2RlIiBMZW5ndGhGaWVsZD0iTm9PZlN0YXR1c0NvZGVWYWx1ZSIgLz4NCiAgICA8b3BjOkZp ZWxkIE5hbWU9Ik5vT2ZWYXJpYW50VmFsdWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAg PG9wYzpGaWVsZCBOYW1lPSJWYXJpYW50VmFsdWUiIFR5cGVOYW1lPSJ1YTpWYXJpYW50IiBMZW5n dGhGaWVsZD0iTm9PZlZhcmlhbnRWYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZF bnVtZXJhdGlvblZhbHVlIiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQg TmFtZT0iRW51bWVyYXRpb25WYWx1ZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgTGVuZ3RoRmllbGQ9 Ik5vT2ZFbnVtZXJhdGlvblZhbHVlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZlN0cnVj dHVyZVZhbHVlIiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0i U3RydWN0dXJlVmFsdWUiIFR5cGVOYW1lPSJ1YTpFeHRlbnNpb25PYmplY3QiIExlbmd0aEZpZWxk PSJOb09mU3RydWN0dXJlVmFsdWUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mTnVtYmVy IiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTnVtYmVyIiBU eXBlTmFtZT0idWE6VmFyaWFudCIgTGVuZ3RoRmllbGQ9Ik5vT2ZOdW1iZXIiIC8+DQogICAgPG9w YzpGaWVsZCBOYW1lPSJOb09mSW50ZWdlciIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8 b3BjOkZpZWxkIE5hbWU9IkludGVnZXIiIFR5cGVOYW1lPSJ1YTpWYXJpYW50IiBMZW5ndGhGaWVs ZD0iTm9PZkludGVnZXIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mVUludGVnZXIiIFR5 cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJVSW50ZWdlciIgVHlw ZU5hbWU9InVhOlZhcmlhbnQiIExlbmd0aEZpZWxkPSJOb09mVUludGVnZXIiIC8+DQogIDwvb3Bj OlN0cnVjdHVyZWRUeXBlPg0KDQogIDxvcGM6T3BhcXVlVHlwZSBOYW1lPSJCb29sZWFuRGF0YVR5 cGUiPg0KICA8L29wYzpPcGFxdWVUeXBlPg0KDQogIDxvcGM6T3BhcXVlVHlwZSBOYW1lPSJTQnl0 ZURhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFt ZT0iQnl0ZURhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5 cGUgTmFtZT0iSW50MTZEYXRhVHlwZSI+DQogIDwvb3BjOk9wYXF1ZVR5cGU+DQoNCiAgPG9wYzpP cGFxdWVUeXBlIE5hbWU9IlVJbnQxNkRhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0K ICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0iSW50MzJEYXRhVHlwZSI+DQogIDwvb3BjOk9wYXF1ZVR5 cGU+DQoNCiAgPG9wYzpPcGFxdWVUeXBlIE5hbWU9IlVJbnQzMkRhdGFUeXBlIj4NCiAgPC9vcGM6 T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0iSW50NjREYXRhVHlwZSI+DQog IDwvb3BjOk9wYXF1ZVR5cGU+DQoNCiAgPG9wYzpPcGFxdWVUeXBlIE5hbWU9IlVJbnQ2NERhdGFU eXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0iRmxv YXREYXRhVHlwZSI+DQogIDwvb3BjOk9wYXF1ZVR5cGU+DQoNCiAgPG9wYzpPcGFxdWVUeXBlIE5h bWU9IkRvdWJsZURhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1 ZVR5cGUgTmFtZT0iU3RyaW5nRGF0YVR5cGUiPg0KICA8L29wYzpPcGFxdWVUeXBlPg0KDQogIDxv cGM6T3BhcXVlVHlwZSBOYW1lPSJEYXRlVGltZURhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlw ZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0iR3VpZERhdGFUeXBlIj4NCiAgPC9vcGM6T3Bh cXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0iQnl0ZVN0cmluZ0RhdGFUeXBlIj4N CiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0iWG1sRWxlbWVu dERhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFt ZT0iTm9kZUlkRGF0YVR5cGUiPg0KICA8L29wYzpPcGFxdWVUeXBlPg0KDQogIDxvcGM6T3BhcXVl VHlwZSBOYW1lPSJFeHBhbmRlZE5vZGVJZERhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4N Cg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0iUXVhbGlmaWVkTmFtZURhdGFUeXBlIj4NCiAgPC9v cGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0iTG9jYWxpemVkVGV4dERh dGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0i U3RhdHVzQ29kZURhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1 ZVR5cGUgTmFtZT0iVmFyaWFudERhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8 b3BjOlN0cnVjdHVyZWRUeXBlIE5hbWU9IlVzZXJTY2FsYXJWYWx1ZURhdGFUeXBlIiBCYXNlVHlw ZT0idWE6RXh0ZW5zaW9uT2JqZWN0Ij4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkJvb2xlYW5EYXRh VHlwZSIgVHlwZU5hbWU9Im9wYzpCb29sZWFuIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iU0J5 dGVEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpTQnl0ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9 IkJ5dGVEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpCeXRlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFt ZT0iSW50MTZEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpJbnQxNiIgLz4NCiAgICA8b3BjOkZpZWxk IE5hbWU9IlVJbnQxNkRhdGFUeXBlIiBUeXBlTmFtZT0ib3BjOlVJbnQxNiIgLz4NCiAgICA8b3Bj OkZpZWxkIE5hbWU9IkludDMyRGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAg PG9wYzpGaWVsZCBOYW1lPSJVSW50MzJEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpVSW50MzIiIC8+ DQogICAgPG9wYzpGaWVsZCBOYW1lPSJJbnQ2NERhdGFUeXBlIiBUeXBlTmFtZT0ib3BjOkludDY0 IiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iVUludDY0RGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6 VUludDY0IiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iRmxvYXREYXRhVHlwZSIgVHlwZU5hbWU9 Im9wYzpGbG9hdCIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkRvdWJsZURhdGFUeXBlIiBUeXBl TmFtZT0ib3BjOkRvdWJsZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IlN0cmluZ0RhdGFUeXBl IiBUeXBlTmFtZT0ib3BjOlN0cmluZyIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkRhdGVUaW1l RGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6RGF0ZVRpbWUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1l PSJHdWlkRGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6R3VpZCIgLz4NCiAgICA8b3BjOkZpZWxkIE5h bWU9IkJ5dGVTdHJpbmdEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpCeXRlU3RyaW5nIiAvPg0KICAg IDxvcGM6RmllbGQgTmFtZT0iWG1sRWxlbWVudERhdGFUeXBlIiBUeXBlTmFtZT0idWE6WG1sRWxl bWVudCIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vZGVJZERhdGFUeXBlIiBUeXBlTmFtZT0i dWE6Tm9kZUlkIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iRXhwYW5kZWROb2RlSWREYXRhVHlw ZSIgVHlwZU5hbWU9InVhOkV4cGFuZGVkTm9kZUlkIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0i UXVhbGlmaWVkTmFtZURhdGFUeXBlIiBUeXBlTmFtZT0idWE6UXVhbGlmaWVkTmFtZSIgLz4NCiAg ICA8b3BjOkZpZWxkIE5hbWU9IkxvY2FsaXplZFRleHREYXRhVHlwZSIgVHlwZU5hbWU9InVhOkxv Y2FsaXplZFRleHQiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJTdGF0dXNDb2RlRGF0YVR5cGUi IFR5cGVOYW1lPSJ1YTpTdGF0dXNDb2RlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iVmFyaWFu dERhdGFUeXBlIiBUeXBlTmFtZT0idWE6VmFyaWFudCIgLz4NCiAgPC9vcGM6U3RydWN0dXJlZFR5 cGU+DQoNCiAgPG9wYzpTdHJ1Y3R1cmVkVHlwZSBOYW1lPSJVc2VyQXJyYXlWYWx1ZURhdGFUeXBl IiBCYXNlVHlwZT0idWE6RXh0ZW5zaW9uT2JqZWN0Ij4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5v T2ZCb29sZWFuRGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVs ZCBOYW1lPSJCb29sZWFuRGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6Qm9vbGVhbiIgTGVuZ3RoRmll bGQ9Ik5vT2ZCb29sZWFuRGF0YVR5cGUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mU0J5 dGVEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9 IlNCeXRlRGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6U0J5dGUiIExlbmd0aEZpZWxkPSJOb09mU0J5 dGVEYXRhVHlwZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZCeXRlRGF0YVR5cGUiIFR5 cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJCeXRlRGF0YVR5cGUi IFR5cGVOYW1lPSJvcGM6Qnl0ZSIgTGVuZ3RoRmllbGQ9Ik5vT2ZCeXRlRGF0YVR5cGUiIC8+DQog ICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mSW50MTZEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpJbnQz MiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkludDE2RGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6 SW50MTYiIExlbmd0aEZpZWxkPSJOb09mSW50MTZEYXRhVHlwZSIgLz4NCiAgICA8b3BjOkZpZWxk IE5hbWU9Ik5vT2ZVSW50MTZEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8 b3BjOkZpZWxkIE5hbWU9IlVJbnQxNkRhdGFUeXBlIiBUeXBlTmFtZT0ib3BjOlVJbnQxNiIgTGVu Z3RoRmllbGQ9Ik5vT2ZVSW50MTZEYXRhVHlwZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5v T2ZJbnQzMkRhdGFUeXBlIiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQg TmFtZT0iSW50MzJEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgTGVuZ3RoRmllbGQ9Ik5v T2ZJbnQzMkRhdGFUeXBlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZlVJbnQzMkRhdGFU eXBlIiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iVUludDMy RGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6VUludDMyIiBMZW5ndGhGaWVsZD0iTm9PZlVJbnQzMkRh dGFUeXBlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZkludDY0RGF0YVR5cGUiIFR5cGVO YW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJJbnQ2NERhdGFUeXBlIiBU eXBlTmFtZT0ib3BjOkludDY0IiBMZW5ndGhGaWVsZD0iTm9PZkludDY0RGF0YVR5cGUiIC8+DQog ICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mVUludDY0RGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6SW50 MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJVSW50NjREYXRhVHlwZSIgVHlwZU5hbWU9Im9w YzpVSW50NjQiIExlbmd0aEZpZWxkPSJOb09mVUludDY0RGF0YVR5cGUiIC8+DQogICAgPG9wYzpG aWVsZCBOYW1lPSJOb09mRmxvYXREYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAg ICA8b3BjOkZpZWxkIE5hbWU9IkZsb2F0RGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6RmxvYXQiIExl bmd0aEZpZWxkPSJOb09mRmxvYXREYXRhVHlwZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5v T2ZEb3VibGVEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8b3BjOkZpZWxk IE5hbWU9IkRvdWJsZURhdGFUeXBlIiBUeXBlTmFtZT0ib3BjOkRvdWJsZSIgTGVuZ3RoRmllbGQ9 Ik5vT2ZEb3VibGVEYXRhVHlwZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZTdHJpbmdE YXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IlN0 cmluZ0RhdGFUeXBlIiBUeXBlTmFtZT0ib3BjOlN0cmluZyIgTGVuZ3RoRmllbGQ9Ik5vT2ZTdHJp bmdEYXRhVHlwZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZEYXRlVGltZURhdGFUeXBl IiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iRGF0ZVRpbWVE YXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpEYXRlVGltZSIgTGVuZ3RoRmllbGQ9Ik5vT2ZEYXRlVGlt ZURhdGFUeXBlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZkd1aWREYXRhVHlwZSIgVHlw ZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ikd1aWREYXRhVHlwZSIg VHlwZU5hbWU9Im9wYzpHdWlkIiBMZW5ndGhGaWVsZD0iTm9PZkd1aWREYXRhVHlwZSIgLz4NCiAg ICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZCeXRlU3RyaW5nRGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6 SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJCeXRlU3RyaW5nRGF0YVR5cGUiIFR5cGVO YW1lPSJvcGM6Qnl0ZVN0cmluZyIgTGVuZ3RoRmllbGQ9Ik5vT2ZCeXRlU3RyaW5nRGF0YVR5cGUi IC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mWG1sRWxlbWVudERhdGFUeXBlIiBUeXBlTmFt ZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iWG1sRWxlbWVudERhdGFUeXBl IiBUeXBlTmFtZT0idWE6WG1sRWxlbWVudCIgTGVuZ3RoRmllbGQ9Ik5vT2ZYbWxFbGVtZW50RGF0 YVR5cGUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mTm9kZUlkRGF0YVR5cGUiIFR5cGVO YW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb2RlSWREYXRhVHlwZSIg VHlwZU5hbWU9InVhOk5vZGVJZCIgTGVuZ3RoRmllbGQ9Ik5vT2ZOb2RlSWREYXRhVHlwZSIgLz4N CiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZFeHBhbmRlZE5vZGVJZERhdGFUeXBlIiBUeXBlTmFt ZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iRXhwYW5kZWROb2RlSWREYXRh VHlwZSIgVHlwZU5hbWU9InVhOkV4cGFuZGVkTm9kZUlkIiBMZW5ndGhGaWVsZD0iTm9PZkV4cGFu ZGVkTm9kZUlkRGF0YVR5cGUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mUXVhbGlmaWVk TmFtZURhdGFUeXBlIiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFt ZT0iUXVhbGlmaWVkTmFtZURhdGFUeXBlIiBUeXBlTmFtZT0idWE6UXVhbGlmaWVkTmFtZSIgTGVu Z3RoRmllbGQ9Ik5vT2ZRdWFsaWZpZWROYW1lRGF0YVR5cGUiIC8+DQogICAgPG9wYzpGaWVsZCBO YW1lPSJOb09mTG9jYWxpemVkVGV4dERhdGFUeXBlIiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0K ICAgIDxvcGM6RmllbGQgTmFtZT0iTG9jYWxpemVkVGV4dERhdGFUeXBlIiBUeXBlTmFtZT0idWE6 TG9jYWxpemVkVGV4dCIgTGVuZ3RoRmllbGQ9Ik5vT2ZMb2NhbGl6ZWRUZXh0RGF0YVR5cGUiIC8+ DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mU3RhdHVzQ29kZURhdGFUeXBlIiBUeXBlTmFtZT0i b3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iU3RhdHVzQ29kZURhdGFUeXBlIiBU eXBlTmFtZT0idWE6U3RhdHVzQ29kZSIgTGVuZ3RoRmllbGQ9Ik5vT2ZTdGF0dXNDb2RlRGF0YVR5 cGUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mVmFyaWFudERhdGFUeXBlIiBUeXBlTmFt ZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iVmFyaWFudERhdGFUeXBlIiBU eXBlTmFtZT0idWE6VmFyaWFudCIgTGVuZ3RoRmllbGQ9Ik5vT2ZWYXJpYW50RGF0YVR5cGUiIC8+ DQogIDwvb3BjOlN0cnVjdHVyZWRUeXBlPg0KDQogIDxvcGM6U3RydWN0dXJlZFR5cGUgTmFtZT0i VmVjdG9yIiBCYXNlVHlwZT0idWE6RXh0ZW5zaW9uT2JqZWN0Ij4NCiAgICA8b3BjOkZpZWxkIE5h bWU9IlgiIFR5cGVOYW1lPSJvcGM6RG91YmxlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iWSIg VHlwZU5hbWU9Im9wYzpEb3VibGUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJaIiBUeXBlTmFt ZT0ib3BjOkRvdWJsZSIgLz4NCiAgPC9vcGM6U3RydWN0dXJlZFR5cGU+DQoNCiAgPG9wYzpTdHJ1 Y3R1cmVkVHlwZSBOYW1lPSJXb3JrT3JkZXJTdGF0dXNUeXBlIiBCYXNlVHlwZT0idWE6RXh0ZW5z aW9uT2JqZWN0Ij4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkFjdG9yIiBUeXBlTmFtZT0ib3BjOlN0 cmluZyIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IlRpbWVzdGFtcCIgVHlwZU5hbWU9Im9wYzpE YXRlVGltZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkNvbW1lbnQiIFR5cGVOYW1lPSJ1YTpM b2NhbGl6ZWRUZXh0IiAvPg0KICA8L29wYzpTdHJ1Y3R1cmVkVHlwZT4NCg0KICA8b3BjOlN0cnVj dHVyZWRUeXBlIE5hbWU9IldvcmtPcmRlclR5cGUiIEJhc2VUeXBlPSJ1YTpFeHRlbnNpb25PYmpl Y3QiPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iSUQiIFR5cGVOYW1lPSJvcGM6R3VpZCIgLz4NCiAg ICA8b3BjOkZpZWxkIE5hbWU9IkFzc2V0SUQiIFR5cGVOYW1lPSJvcGM6U3RyaW5nIiAvPg0KICAg IDxvcGM6RmllbGQgTmFtZT0iU3RhcnRUaW1lIiBUeXBlTmFtZT0ib3BjOkRhdGVUaW1lIiAvPg0K ICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZlN0YXR1c0NvbW1lbnRzIiBUeXBlTmFtZT0ib3BjOklu dDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iU3RhdHVzQ29tbWVudHMiIFR5cGVOYW1lPSJ0 bnM6V29ya09yZGVyU3RhdHVzVHlwZSIgTGVuZ3RoRmllbGQ9Ik5vT2ZTdGF0dXNDb21tZW50cyIg Lz4NCiAgPC9vcGM6U3RydWN0dXJlZFR5cGU+DQoNCjwvb3BjOlR5cGVEaWN0aW9uYXJ5Pg== i=15 -1 1 1 0 false 0 ns=1;i=11424 Variable_2 0 NamespaceUri NamespaceUri 0 0 0 i=46 true ns=1;i=11422 i=40 false i=68 http://test.org/UA/Data/ i=12 -1 1 1 0 false 0 ns=1;i=11425 Variable_2 1 ScalarValueDataType ScalarValueDataType 0 0 0 i=47 true ns=1;i=11422 i=40 false i=69 ScalarValueDataType i=12 -1 1 1 0 false 0 ns=1;i=11428 Variable_2 1 ArrayValueDataType ArrayValueDataType 0 0 0 i=47 true ns=1;i=11422 i=40 false i=69 ArrayValueDataType i=12 -1 1 1 0 false 0 ns=1;i=11431 Variable_2 1 UserScalarValueDataType UserScalarValueDataType 0 0 0 i=47 true ns=1;i=11422 i=40 false i=69 UserScalarValueDataType i=12 -1 1 1 0 false 0 ns=1;i=11434 Variable_2 1 UserArrayValueDataType UserArrayValueDataType 0 0 0 i=47 true ns=1;i=11422 i=40 false i=69 UserArrayValueDataType i=12 -1 1 1 0 false 0 ns=1;i=11437 Object_1 0 Default Binary Default Binary 0 0 0 i=40 false i=76 i=38 true ns=1;i=9440 i=39 false ns=1;i=11425 0 ns=1;i=11438 Object_1 0 Default Binary Default Binary 0 0 0 i=40 false i=76 i=38 true ns=1;i=9669 i=39 false ns=1;i=11428 0 ns=1;i=11439 Object_1 0 Default Binary Default Binary 0 0 0 i=40 false i=76 i=38 true ns=1;i=9920 i=39 false ns=1;i=11431 0 ns=1;i=11440 Object_1 0 Default Binary Default Binary 0 0 0 i=40 false i=76 i=38 true ns=1;i=10006 i=39 false ns=1;i=11434 0 ns=1;i=11441 Variable_2 1 TestData TestData 0 0 0 i=40 false i=72 i=47 true i=92 i=46 false ns=1;i=11443 i=46 false ns=1;i=15046 i=47 false ns=1;i=11444 i=47 false ns=1;i=11447 i=47 false ns=1;i=11450 i=47 false ns=1;i=11453 i=47 false ns=1;i=43 i=47 false ns=1;i=52 i=47 false ns=1;i=55 PHhzOnNjaGVtYQ0KICB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEi DQogIHhtbG5zOnVhPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvMjAwOC8wMi9UeXBlcy54 c2QiDQogIHhtbG5zOnRucz0iaHR0cDovL3Rlc3Qub3JnL1VBL0RhdGEvIg0KICB0YXJnZXROYW1l c3BhY2U9Imh0dHA6Ly90ZXN0Lm9yZy9VQS9EYXRhLyINCiAgZWxlbWVudEZvcm1EZWZhdWx0PSJx dWFsaWZpZWQiDQo+DQogIDx4czppbXBvcnQgbmFtZXNwYWNlPSJodHRwOi8vb3BjZm91bmRhdGlv bi5vcmcvVUEvMjAwOC8wMi9UeXBlcy54c2QiIC8+DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9 IlNjYWxhclZhbHVlRGF0YVR5cGUiPg0KICAgIDx4czpzZXF1ZW5jZT4NCiAgICAgIDx4czplbGVt ZW50IG5hbWU9IkJvb2xlYW5WYWx1ZSIgdHlwZT0ieHM6Ym9vbGVhbiIgbWluT2NjdXJzPSIwIiAv Pg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iU0J5dGVWYWx1ZSIgdHlwZT0ieHM6Ynl0ZSIgbWlu T2NjdXJzPSIwIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iQnl0ZVZhbHVlIiB0eXBlPSJ4 czp1bnNpZ25lZEJ5dGUiIG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9 IkludDE2VmFsdWUiIHR5cGU9InhzOnNob3J0IiBtaW5PY2N1cnM9IjAiIC8+DQogICAgICA8eHM6 ZWxlbWVudCBuYW1lPSJVSW50MTZWYWx1ZSIgdHlwZT0ieHM6dW5zaWduZWRTaG9ydCIgbWluT2Nj dXJzPSIwIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iSW50MzJWYWx1ZSIgdHlwZT0ieHM6 aW50IiBtaW5PY2N1cnM9IjAiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJVSW50MzJWYWx1 ZSIgdHlwZT0ieHM6dW5zaWduZWRJbnQiIG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVt ZW50IG5hbWU9IkludDY0VmFsdWUiIHR5cGU9InhzOmxvbmciIG1pbk9jY3Vycz0iMCIgLz4NCiAg ICAgIDx4czplbGVtZW50IG5hbWU9IlVJbnQ2NFZhbHVlIiB0eXBlPSJ4czp1bnNpZ25lZExvbmci IG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IkZsb2F0VmFsdWUiIHR5 cGU9InhzOmZsb2F0IiBtaW5PY2N1cnM9IjAiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJE b3VibGVWYWx1ZSIgdHlwZT0ieHM6ZG91YmxlIiBtaW5PY2N1cnM9IjAiIC8+DQogICAgICA8eHM6 ZWxlbWVudCBuYW1lPSJTdHJpbmdWYWx1ZSIgdHlwZT0ieHM6c3RyaW5nIiBtaW5PY2N1cnM9IjAi IG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iRGF0ZVRpbWVWYWx1 ZSIgdHlwZT0ieHM6ZGF0ZVRpbWUiIG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVtZW50 IG5hbWU9Ikd1aWRWYWx1ZSIgdHlwZT0idWE6R3VpZCIgbWluT2NjdXJzPSIwIiAvPg0KICAgICAg PHhzOmVsZW1lbnQgbmFtZT0iQnl0ZVN0cmluZ1ZhbHVlIiB0eXBlPSJ4czpiYXNlNjRCaW5hcnki IG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1l PSJYbWxFbGVtZW50VmFsdWUiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiPg0KICAgICAg ICA8eHM6Y29tcGxleFR5cGU+DQogICAgICAgICAgPHhzOnNlcXVlbmNlPg0KICAgICAgICAgICAg PHhzOmFueSBtaW5PY2N1cnM9IjAiIHByb2Nlc3NDb250ZW50cz0ibGF4IiAvPg0KICAgICAgICAg IDwveHM6c2VxdWVuY2U+DQogICAgICAgIDwveHM6Y29tcGxleFR5cGU+DQogICAgICA8L3hzOmVs ZW1lbnQ+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJOb2RlSWRWYWx1ZSIgdHlwZT0idWE6Tm9k ZUlkIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQg bmFtZT0iRXhwYW5kZWROb2RlSWRWYWx1ZSIgdHlwZT0idWE6RXhwYW5kZWROb2RlSWQiIG1pbk9j Y3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJRdWFs aWZpZWROYW1lVmFsdWUiIHR5cGU9InVhOlF1YWxpZmllZE5hbWUiIG1pbk9jY3Vycz0iMCIgbmls bGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJMb2NhbGl6ZWRUZXh0VmFs dWUiIHR5cGU9InVhOkxvY2FsaXplZFRleHQiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUi IC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJTdGF0dXNDb2RlVmFsdWUiIHR5cGU9InVhOlN0 YXR1c0NvZGUiIG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlZhcmlh bnRWYWx1ZSIgdHlwZT0idWE6VmFyaWFudCIgbWluT2NjdXJzPSIwIiAvPg0KICAgICAgPHhzOmVs ZW1lbnQgbmFtZT0iRW51bWVyYXRpb25WYWx1ZSIgdHlwZT0ieHM6aW50IiBtaW5PY2N1cnM9IjAi IC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJTdHJ1Y3R1cmVWYWx1ZSIgdHlwZT0idWE6RXh0 ZW5zaW9uT2JqZWN0IiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhz OmVsZW1lbnQgbmFtZT0iTnVtYmVyIiB0eXBlPSJ1YTpWYXJpYW50IiBtaW5PY2N1cnM9IjAiIC8+ DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJJbnRlZ2VyIiB0eXBlPSJ1YTpWYXJpYW50IiBtaW5P Y2N1cnM9IjAiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJVSW50ZWdlciIgdHlwZT0idWE6 VmFyaWFudCIgbWluT2NjdXJzPSIwIiAvPg0KICAgIDwveHM6c2VxdWVuY2U+DQogIDwveHM6Y29t cGxleFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9IlNjYWxhclZhbHVlRGF0YVR5cGUiIHR5cGU9 InRuczpTY2FsYXJWYWx1ZURhdGFUeXBlIiAvPg0KDQogIDx4czpjb21wbGV4VHlwZSBuYW1lPSJM aXN0T2ZTY2FsYXJWYWx1ZURhdGFUeXBlIj4NCiAgICA8eHM6c2VxdWVuY2U+DQogICAgICA8eHM6 ZWxlbWVudCBuYW1lPSJTY2FsYXJWYWx1ZURhdGFUeXBlIiB0eXBlPSJ0bnM6U2NhbGFyVmFsdWVE YXRhVHlwZSIgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9InVuYm91bmRlZCIgbmlsbGFibGU9InRy dWUiIC8+DQogICAgPC94czpzZXF1ZW5jZT4NCiAgPC94czpjb21wbGV4VHlwZT4NCiAgPHhzOmVs ZW1lbnQgbmFtZT0iTGlzdE9mU2NhbGFyVmFsdWVEYXRhVHlwZSIgdHlwZT0idG5zOkxpc3RPZlNj YWxhclZhbHVlRGF0YVR5cGUiIG5pbGxhYmxlPSJ0cnVlIj48L3hzOmVsZW1lbnQ+DQoNCiAgPHhz OmNvbXBsZXhUeXBlIG5hbWU9IkFycmF5VmFsdWVEYXRhVHlwZSI+DQogICAgPHhzOnNlcXVlbmNl Pg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iQm9vbGVhblZhbHVlIiB0eXBlPSJ1YTpMaXN0T2ZC b29sZWFuIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1l bnQgbmFtZT0iU0J5dGVWYWx1ZSIgdHlwZT0idWE6TGlzdE9mU0J5dGUiIG1pbk9jY3Vycz0iMCIg bmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJCeXRlVmFsdWUiIHR5 cGU9InVhOkxpc3RPZkJ5dGUiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAg ICA8eHM6ZWxlbWVudCBuYW1lPSJJbnQxNlZhbHVlIiB0eXBlPSJ1YTpMaXN0T2ZJbnQxNiIgbWlu T2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlVJ bnQxNlZhbHVlIiB0eXBlPSJ1YTpMaXN0T2ZVSW50MTYiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9 InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJJbnQzMlZhbHVlIiB0eXBlPSJ1YTpM aXN0T2ZJbnQzMiIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICAgIDx4czpl bGVtZW50IG5hbWU9IlVJbnQzMlZhbHVlIiB0eXBlPSJ1YTpMaXN0T2ZVSW50MzIiIG1pbk9jY3Vy cz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJJbnQ2NFZh bHVlIiB0eXBlPSJ1YTpMaXN0T2ZJbnQ2NCIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIg Lz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlVJbnQ2NFZhbHVlIiB0eXBlPSJ1YTpMaXN0T2ZV SW50NjQiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVu dCBuYW1lPSJGbG9hdFZhbHVlIiB0eXBlPSJ1YTpMaXN0T2ZGbG9hdCIgbWluT2NjdXJzPSIwIiBu aWxsYWJsZT0idHJ1ZSIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IkRvdWJsZVZhbHVlIiB0 eXBlPSJ1YTpMaXN0T2ZEb3VibGUiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQog ICAgICA8eHM6ZWxlbWVudCBuYW1lPSJTdHJpbmdWYWx1ZSIgdHlwZT0idWE6TGlzdE9mU3RyaW5n IiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFt ZT0iRGF0ZVRpbWVWYWx1ZSIgdHlwZT0idWE6TGlzdE9mRGF0ZVRpbWUiIG1pbk9jY3Vycz0iMCIg bmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJHdWlkVmFsdWUiIHR5 cGU9InVhOkxpc3RPZkd1aWQiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAg ICA8eHM6ZWxlbWVudCBuYW1lPSJCeXRlU3RyaW5nVmFsdWUiIHR5cGU9InVhOkxpc3RPZkJ5dGVT dHJpbmciIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVu dCBuYW1lPSJYbWxFbGVtZW50VmFsdWUiIHR5cGU9InVhOkxpc3RPZlhtbEVsZW1lbnQiIG1pbk9j Y3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJOb2Rl SWRWYWx1ZSIgdHlwZT0idWE6TGlzdE9mTm9kZUlkIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0 cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iRXhwYW5kZWROb2RlSWRWYWx1ZSIgdHlw ZT0idWE6TGlzdE9mRXhwYW5kZWROb2RlSWQiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUi IC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJRdWFsaWZpZWROYW1lVmFsdWUiIHR5cGU9InVh Okxpc3RPZlF1YWxpZmllZE5hbWUiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQog ICAgICA8eHM6ZWxlbWVudCBuYW1lPSJMb2NhbGl6ZWRUZXh0VmFsdWUiIHR5cGU9InVhOkxpc3RP ZkxvY2FsaXplZFRleHQiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8 eHM6ZWxlbWVudCBuYW1lPSJTdGF0dXNDb2RlVmFsdWUiIHR5cGU9InVhOkxpc3RPZlN0YXR1c0Nv ZGUiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBu YW1lPSJWYXJpYW50VmFsdWUiIHR5cGU9InVhOkxpc3RPZlZhcmlhbnQiIG1pbk9jY3Vycz0iMCIg bmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJFbnVtZXJhdGlvblZh bHVlIiB0eXBlPSJ1YTpMaXN0T2ZJbnQzMiIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIg Lz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlN0cnVjdHVyZVZhbHVlIiB0eXBlPSJ1YTpMaXN0 T2ZFeHRlbnNpb25PYmplY3QiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAg ICA8eHM6ZWxlbWVudCBuYW1lPSJOdW1iZXIiIHR5cGU9InVhOkxpc3RPZlZhcmlhbnQiIG1pbk9j Y3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJJbnRl Z2VyIiB0eXBlPSJ1YTpMaXN0T2ZWYXJpYW50IiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVl IiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iVUludGVnZXIiIHR5cGU9InVhOkxpc3RPZlZh cmlhbnQiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgPC94czpzZXF1ZW5j ZT4NCiAgPC94czpjb21wbGV4VHlwZT4NCiAgPHhzOmVsZW1lbnQgbmFtZT0iQXJyYXlWYWx1ZURh dGFUeXBlIiB0eXBlPSJ0bnM6QXJyYXlWYWx1ZURhdGFUeXBlIiAvPg0KDQogIDx4czpjb21wbGV4 VHlwZSBuYW1lPSJMaXN0T2ZBcnJheVZhbHVlRGF0YVR5cGUiPg0KICAgIDx4czpzZXF1ZW5jZT4N CiAgICAgIDx4czplbGVtZW50IG5hbWU9IkFycmF5VmFsdWVEYXRhVHlwZSIgdHlwZT0idG5zOkFy cmF5VmFsdWVEYXRhVHlwZSIgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9InVuYm91bmRlZCIgbmls bGFibGU9InRydWUiIC8+DQogICAgPC94czpzZXF1ZW5jZT4NCiAgPC94czpjb21wbGV4VHlwZT4N CiAgPHhzOmVsZW1lbnQgbmFtZT0iTGlzdE9mQXJyYXlWYWx1ZURhdGFUeXBlIiB0eXBlPSJ0bnM6 TGlzdE9mQXJyYXlWYWx1ZURhdGFUeXBlIiBuaWxsYWJsZT0idHJ1ZSI+PC94czplbGVtZW50Pg0K DQogIDx4czplbGVtZW50IG5hbWU9IkJvb2xlYW5EYXRhVHlwZSIgdHlwZT0ieHM6Ym9vbGVhbiIg Lz4NCg0KICA8eHM6ZWxlbWVudCBuYW1lPSJTQnl0ZURhdGFUeXBlIiB0eXBlPSJ4czpieXRlIiAv Pg0KDQogIDx4czplbGVtZW50IG5hbWU9IkJ5dGVEYXRhVHlwZSIgdHlwZT0ieHM6dW5zaWduZWRC eXRlIiAvPg0KDQogIDx4czplbGVtZW50IG5hbWU9IkludDE2RGF0YVR5cGUiIHR5cGU9InhzOnNo b3J0IiAvPg0KDQogIDx4czplbGVtZW50IG5hbWU9IlVJbnQxNkRhdGFUeXBlIiB0eXBlPSJ4czp1 bnNpZ25lZFNob3J0IiAvPg0KDQogIDx4czplbGVtZW50IG5hbWU9IkludDMyRGF0YVR5cGUiIHR5 cGU9InhzOmludCIgLz4NCg0KICA8eHM6ZWxlbWVudCBuYW1lPSJVSW50MzJEYXRhVHlwZSIgdHlw ZT0ieHM6dW5zaWduZWRJbnQiIC8+DQoNCiAgPHhzOmVsZW1lbnQgbmFtZT0iSW50NjREYXRhVHlw ZSIgdHlwZT0ieHM6bG9uZyIgLz4NCg0KICA8eHM6ZWxlbWVudCBuYW1lPSJVSW50NjREYXRhVHlw ZSIgdHlwZT0ieHM6dW5zaWduZWRMb25nIiAvPg0KDQogIDx4czplbGVtZW50IG5hbWU9IkZsb2F0 RGF0YVR5cGUiIHR5cGU9InhzOmZsb2F0IiAvPg0KDQogIDx4czplbGVtZW50IG5hbWU9IkRvdWJs ZURhdGFUeXBlIiB0eXBlPSJ4czpkb3VibGUiIC8+DQoNCiAgPHhzOmVsZW1lbnQgbmFtZT0iU3Ry aW5nRGF0YVR5cGUiIHR5cGU9InhzOnN0cmluZyIgLz4NCg0KICA8eHM6ZWxlbWVudCBuYW1lPSJE YXRlVGltZURhdGFUeXBlIiB0eXBlPSJ4czpkYXRlVGltZSIgLz4NCg0KICA8eHM6ZWxlbWVudCBu YW1lPSJHdWlkRGF0YVR5cGUiIHR5cGU9InVhOkd1aWQiIC8+DQoNCiAgPHhzOmVsZW1lbnQgbmFt ZT0iQnl0ZVN0cmluZ0RhdGFUeXBlIiB0eXBlPSJ4czpiYXNlNjRCaW5hcnkiIC8+DQoNCiAgPHhz OmVsZW1lbnQgbmFtZT0iWG1sRWxlbWVudERhdGFUeXBlIiB0eXBlPSJ1YTpYbWxFbGVtZW50IiAv Pg0KDQogIDx4czplbGVtZW50IG5hbWU9Ik5vZGVJZERhdGFUeXBlIiB0eXBlPSJ1YTpOb2RlSWQi IC8+DQoNCiAgPHhzOmVsZW1lbnQgbmFtZT0iRXhwYW5kZWROb2RlSWREYXRhVHlwZSIgdHlwZT0i dWE6RXhwYW5kZWROb2RlSWQiIC8+DQoNCiAgPHhzOmVsZW1lbnQgbmFtZT0iUXVhbGlmaWVkTmFt ZURhdGFUeXBlIiB0eXBlPSJ1YTpRdWFsaWZpZWROYW1lIiAvPg0KDQogIDx4czplbGVtZW50IG5h bWU9IkxvY2FsaXplZFRleHREYXRhVHlwZSIgdHlwZT0idWE6TG9jYWxpemVkVGV4dCIgLz4NCg0K ICA8eHM6ZWxlbWVudCBuYW1lPSJTdGF0dXNDb2RlRGF0YVR5cGUiIHR5cGU9InVhOlN0YXR1c0Nv ZGUiIC8+DQoNCiAgPHhzOmVsZW1lbnQgbmFtZT0iVmFyaWFudERhdGFUeXBlIiB0eXBlPSJ1YTpW YXJpYW50IiAvPg0KDQogIDx4czpjb21wbGV4VHlwZSBuYW1lPSJVc2VyU2NhbGFyVmFsdWVEYXRh VHlwZSI+DQogICAgPHhzOnNlcXVlbmNlPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iQm9vbGVh bkRhdGFUeXBlIiB0eXBlPSJ4czpib29sZWFuIiBtaW5PY2N1cnM9IjAiIC8+DQogICAgICA8eHM6 ZWxlbWVudCBuYW1lPSJTQnl0ZURhdGFUeXBlIiB0eXBlPSJ4czpieXRlIiBtaW5PY2N1cnM9IjAi IC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJCeXRlRGF0YVR5cGUiIHR5cGU9InhzOnVuc2ln bmVkQnl0ZSIgbWluT2NjdXJzPSIwIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iSW50MTZE YXRhVHlwZSIgdHlwZT0ieHM6c2hvcnQiIG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVt ZW50IG5hbWU9IlVJbnQxNkRhdGFUeXBlIiB0eXBlPSJ4czp1bnNpZ25lZFNob3J0IiBtaW5PY2N1 cnM9IjAiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJJbnQzMkRhdGFUeXBlIiB0eXBlPSJ4 czppbnQiIG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlVJbnQzMkRh dGFUeXBlIiB0eXBlPSJ4czp1bnNpZ25lZEludCIgbWluT2NjdXJzPSIwIiAvPg0KICAgICAgPHhz OmVsZW1lbnQgbmFtZT0iSW50NjREYXRhVHlwZSIgdHlwZT0ieHM6bG9uZyIgbWluT2NjdXJzPSIw IiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iVUludDY0RGF0YVR5cGUiIHR5cGU9InhzOnVu c2lnbmVkTG9uZyIgbWluT2NjdXJzPSIwIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iRmxv YXREYXRhVHlwZSIgdHlwZT0ieHM6ZmxvYXQiIG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czpl bGVtZW50IG5hbWU9IkRvdWJsZURhdGFUeXBlIiB0eXBlPSJ4czpkb3VibGUiIG1pbk9jY3Vycz0i MCIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlN0cmluZ0RhdGFUeXBlIiB0eXBlPSJ4czpz dHJpbmciIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVu dCBuYW1lPSJEYXRlVGltZURhdGFUeXBlIiB0eXBlPSJ4czpkYXRlVGltZSIgbWluT2NjdXJzPSIw IiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iR3VpZERhdGFUeXBlIiB0eXBlPSJ1YTpHdWlk IiBtaW5PY2N1cnM9IjAiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJCeXRlU3RyaW5nRGF0 YVR5cGUiIHR5cGU9InhzOmJhc2U2NEJpbmFyeSIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1 ZSIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlhtbEVsZW1lbnREYXRhVHlwZSIgbWluT2Nj dXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSI+DQogICAgICAgIDx4czpjb21wbGV4VHlwZT4NCiAgICAg ICAgICA8eHM6c2VxdWVuY2U+DQogICAgICAgICAgICA8eHM6YW55IG1pbk9jY3Vycz0iMCIgcHJv Y2Vzc0NvbnRlbnRzPSJsYXgiIC8+DQogICAgICAgICAgPC94czpzZXF1ZW5jZT4NCiAgICAgICAg PC94czpjb21wbGV4VHlwZT4NCiAgICAgIDwveHM6ZWxlbWVudD4NCiAgICAgIDx4czplbGVtZW50 IG5hbWU9Ik5vZGVJZERhdGFUeXBlIiB0eXBlPSJ1YTpOb2RlSWQiIG1pbk9jY3Vycz0iMCIgbmls bGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJFeHBhbmRlZE5vZGVJZERh dGFUeXBlIiB0eXBlPSJ1YTpFeHBhbmRlZE5vZGVJZCIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0i dHJ1ZSIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlF1YWxpZmllZE5hbWVEYXRhVHlwZSIg dHlwZT0idWE6UXVhbGlmaWVkTmFtZSIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4N CiAgICAgIDx4czplbGVtZW50IG5hbWU9IkxvY2FsaXplZFRleHREYXRhVHlwZSIgdHlwZT0idWE6 TG9jYWxpemVkVGV4dCIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICAgIDx4 czplbGVtZW50IG5hbWU9IlN0YXR1c0NvZGVEYXRhVHlwZSIgdHlwZT0idWE6U3RhdHVzQ29kZSIg bWluT2NjdXJzPSIwIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iVmFyaWFudERhdGFUeXBl IiB0eXBlPSJ1YTpWYXJpYW50IiBtaW5PY2N1cnM9IjAiIC8+DQogICAgPC94czpzZXF1ZW5jZT4N CiAgPC94czpjb21wbGV4VHlwZT4NCiAgPHhzOmVsZW1lbnQgbmFtZT0iVXNlclNjYWxhclZhbHVl RGF0YVR5cGUiIHR5cGU9InRuczpVc2VyU2NhbGFyVmFsdWVEYXRhVHlwZSIgLz4NCg0KICA8eHM6 Y29tcGxleFR5cGUgbmFtZT0iTGlzdE9mVXNlclNjYWxhclZhbHVlRGF0YVR5cGUiPg0KICAgIDx4 czpzZXF1ZW5jZT4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlVzZXJTY2FsYXJWYWx1ZURhdGFU eXBlIiB0eXBlPSJ0bnM6VXNlclNjYWxhclZhbHVlRGF0YVR5cGUiIG1pbk9jY3Vycz0iMCIgbWF4 T2NjdXJzPSJ1bmJvdW5kZWQiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgIDwveHM6c2VxdWVuY2U+ DQogIDwveHM6Y29tcGxleFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9Ikxpc3RPZlVzZXJTY2Fs YXJWYWx1ZURhdGFUeXBlIiB0eXBlPSJ0bnM6TGlzdE9mVXNlclNjYWxhclZhbHVlRGF0YVR5cGUi IG5pbGxhYmxlPSJ0cnVlIj48L3hzOmVsZW1lbnQ+DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9 IlVzZXJBcnJheVZhbHVlRGF0YVR5cGUiPg0KICAgIDx4czpzZXF1ZW5jZT4NCiAgICAgIDx4czpl bGVtZW50IG5hbWU9IkJvb2xlYW5EYXRhVHlwZSIgdHlwZT0idWE6TGlzdE9mQm9vbGVhbiIgbWlu T2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlNC eXRlRGF0YVR5cGUiIHR5cGU9InVhOkxpc3RPZlNCeXRlIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxl PSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iQnl0ZURhdGFUeXBlIiB0eXBlPSJ0 bnM6TGlzdE9mQnl0ZURhdGFUeXBlIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0K ICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iSW50MTZEYXRhVHlwZSIgdHlwZT0idWE6TGlzdE9mSW50 MTYiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBu YW1lPSJVSW50MTZEYXRhVHlwZSIgdHlwZT0idWE6TGlzdE9mVUludDE2IiBtaW5PY2N1cnM9IjAi IG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iSW50MzJEYXRhVHlw ZSIgdHlwZT0idWE6TGlzdE9mSW50MzIiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+ DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJVSW50MzJEYXRhVHlwZSIgdHlwZT0idWE6TGlzdE9m VUludDMyIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1l bnQgbmFtZT0iSW50NjREYXRhVHlwZSIgdHlwZT0idWE6TGlzdE9mSW50NjQiIG1pbk9jY3Vycz0i MCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJVSW50NjREYXRh VHlwZSIgdHlwZT0idWE6TGlzdE9mVUludDY0IiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVl IiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iRmxvYXREYXRhVHlwZSIgdHlwZT0idWE6TGlz dE9mRmxvYXQiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxl bWVudCBuYW1lPSJEb3VibGVEYXRhVHlwZSIgdHlwZT0idWE6TGlzdE9mRG91YmxlIiBtaW5PY2N1 cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iU3RyaW5n RGF0YVR5cGUiIHR5cGU9InVhOkxpc3RPZlN0cmluZyIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0i dHJ1ZSIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IkRhdGVUaW1lRGF0YVR5cGUiIHR5cGU9 InVhOkxpc3RPZkRhdGVUaW1lIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAg ICAgPHhzOmVsZW1lbnQgbmFtZT0iR3VpZERhdGFUeXBlIiB0eXBlPSJ1YTpMaXN0T2ZHdWlkIiBt aW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0i Qnl0ZVN0cmluZ0RhdGFUeXBlIiB0eXBlPSJ1YTpMaXN0T2ZCeXRlU3RyaW5nIiBtaW5PY2N1cnM9 IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iWG1sRWxlbWVu dERhdGFUeXBlIiB0eXBlPSJ1YTpMaXN0T2ZYbWxFbGVtZW50IiBtaW5PY2N1cnM9IjAiIG5pbGxh YmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iTm9kZUlkRGF0YVR5cGUiIHR5 cGU9InVhOkxpc3RPZk5vZGVJZCIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAg ICAgIDx4czplbGVtZW50IG5hbWU9IkV4cGFuZGVkTm9kZUlkRGF0YVR5cGUiIHR5cGU9InVhOkxp c3RPZkV4cGFuZGVkTm9kZUlkIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAg ICAgPHhzOmVsZW1lbnQgbmFtZT0iUXVhbGlmaWVkTmFtZURhdGFUeXBlIiB0eXBlPSJ1YTpMaXN0 T2ZRdWFsaWZpZWROYW1lIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAg PHhzOmVsZW1lbnQgbmFtZT0iTG9jYWxpemVkVGV4dERhdGFUeXBlIiB0eXBlPSJ1YTpMaXN0T2ZM b2NhbGl6ZWRUZXh0IiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhz OmVsZW1lbnQgbmFtZT0iU3RhdHVzQ29kZURhdGFUeXBlIiB0eXBlPSJ1YTpMaXN0T2ZTdGF0dXND b2RlIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQg bmFtZT0iVmFyaWFudERhdGFUeXBlIiB0eXBlPSJ1YTpMaXN0T2ZWYXJpYW50IiBtaW5PY2N1cnM9 IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgIDwveHM6c2VxdWVuY2U+DQogIDwveHM6Y29tcGxl eFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9IlVzZXJBcnJheVZhbHVlRGF0YVR5cGUiIHR5cGU9 InRuczpVc2VyQXJyYXlWYWx1ZURhdGFUeXBlIiAvPg0KDQogIDx4czpjb21wbGV4VHlwZSBuYW1l PSJMaXN0T2ZVc2VyQXJyYXlWYWx1ZURhdGFUeXBlIj4NCiAgICA8eHM6c2VxdWVuY2U+DQogICAg ICA8eHM6ZWxlbWVudCBuYW1lPSJVc2VyQXJyYXlWYWx1ZURhdGFUeXBlIiB0eXBlPSJ0bnM6VXNl ckFycmF5VmFsdWVEYXRhVHlwZSIgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9InVuYm91bmRlZCIg bmlsbGFibGU9InRydWUiIC8+DQogICAgPC94czpzZXF1ZW5jZT4NCiAgPC94czpjb21wbGV4VHlw ZT4NCiAgPHhzOmVsZW1lbnQgbmFtZT0iTGlzdE9mVXNlckFycmF5VmFsdWVEYXRhVHlwZSIgdHlw ZT0idG5zOkxpc3RPZlVzZXJBcnJheVZhbHVlRGF0YVR5cGUiIG5pbGxhYmxlPSJ0cnVlIj48L3hz OmVsZW1lbnQ+DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9IlZlY3RvciI+DQogICAgPHhzOnNl cXVlbmNlPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iWCIgdHlwZT0ieHM6ZG91YmxlIiBtaW5P Y2N1cnM9IjAiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJZIiB0eXBlPSJ4czpkb3VibGUi IG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IloiIHR5cGU9InhzOmRv dWJsZSIgbWluT2NjdXJzPSIwIiAvPg0KICAgIDwveHM6c2VxdWVuY2U+DQogIDwveHM6Y29tcGxl eFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9IlZlY3RvciIgdHlwZT0idG5zOlZlY3RvciIgLz4N Cg0KICA8eHM6Y29tcGxleFR5cGUgbmFtZT0iTGlzdE9mVmVjdG9yIj4NCiAgICA8eHM6c2VxdWVu Y2U+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJWZWN0b3IiIHR5cGU9InRuczpWZWN0b3IiIG1p bk9jY3Vycz0iMCIgbWF4T2NjdXJzPSJ1bmJvdW5kZWQiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAg IDwveHM6c2VxdWVuY2U+DQogIDwveHM6Y29tcGxleFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9 Ikxpc3RPZlZlY3RvciIgdHlwZT0idG5zOkxpc3RPZlZlY3RvciIgbmlsbGFibGU9InRydWUiPjwv eHM6ZWxlbWVudD4NCg0KICA8eHM6Y29tcGxleFR5cGUgbmFtZT0iV29ya09yZGVyU3RhdHVzVHlw ZSI+DQogICAgPHhzOnNlcXVlbmNlPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iQWN0b3IiIHR5 cGU9InhzOnN0cmluZyIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICAgIDx4 czplbGVtZW50IG5hbWU9IlRpbWVzdGFtcCIgdHlwZT0ieHM6ZGF0ZVRpbWUiIG1pbk9jY3Vycz0i MCIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IkNvbW1lbnQiIHR5cGU9InVhOkxvY2FsaXpl ZFRleHQiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgPC94czpzZXF1ZW5j ZT4NCiAgPC94czpjb21wbGV4VHlwZT4NCiAgPHhzOmVsZW1lbnQgbmFtZT0iV29ya09yZGVyU3Rh dHVzVHlwZSIgdHlwZT0idG5zOldvcmtPcmRlclN0YXR1c1R5cGUiIC8+DQoNCiAgPHhzOmNvbXBs ZXhUeXBlIG5hbWU9Ikxpc3RPZldvcmtPcmRlclN0YXR1c1R5cGUiPg0KICAgIDx4czpzZXF1ZW5j ZT4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IldvcmtPcmRlclN0YXR1c1R5cGUiIHR5cGU9InRu czpXb3JrT3JkZXJTdGF0dXNUeXBlIiBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0idW5ib3VuZGVk IiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICA8L3hzOnNlcXVlbmNlPg0KICA8L3hzOmNvbXBsZXhU eXBlPg0KICA8eHM6ZWxlbWVudCBuYW1lPSJMaXN0T2ZXb3JrT3JkZXJTdGF0dXNUeXBlIiB0eXBl PSJ0bnM6TGlzdE9mV29ya09yZGVyU3RhdHVzVHlwZSIgbmlsbGFibGU9InRydWUiPjwveHM6ZWxl bWVudD4NCg0KICA8eHM6Y29tcGxleFR5cGUgbmFtZT0iV29ya09yZGVyVHlwZSI+DQogICAgPHhz OnNlcXVlbmNlPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iSUQiIHR5cGU9InVhOkd1aWQiIG1p bk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IkFzc2V0SUQiIHR5cGU9Inhz OnN0cmluZyIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICAgIDx4czplbGVt ZW50IG5hbWU9IlN0YXJ0VGltZSIgdHlwZT0ieHM6ZGF0ZVRpbWUiIG1pbk9jY3Vycz0iMCIgLz4N CiAgICAgIDx4czplbGVtZW50IG5hbWU9IlN0YXR1c0NvbW1lbnRzIiB0eXBlPSJ0bnM6TGlzdE9m V29ya09yZGVyU3RhdHVzVHlwZSIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAg ICA8L3hzOnNlcXVlbmNlPg0KICA8L3hzOmNvbXBsZXhUeXBlPg0KICA8eHM6ZWxlbWVudCBuYW1l PSJXb3JrT3JkZXJUeXBlIiB0eXBlPSJ0bnM6V29ya09yZGVyVHlwZSIgLz4NCg0KICA8eHM6Y29t cGxleFR5cGUgbmFtZT0iTGlzdE9mV29ya09yZGVyVHlwZSI+DQogICAgPHhzOnNlcXVlbmNlPg0K ICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iV29ya09yZGVyVHlwZSIgdHlwZT0idG5zOldvcmtPcmRl clR5cGUiIG1pbk9jY3Vycz0iMCIgbWF4T2NjdXJzPSJ1bmJvdW5kZWQiIG5pbGxhYmxlPSJ0cnVl IiAvPg0KICAgIDwveHM6c2VxdWVuY2U+DQogIDwveHM6Y29tcGxleFR5cGU+DQogIDx4czplbGVt ZW50IG5hbWU9Ikxpc3RPZldvcmtPcmRlclR5cGUiIHR5cGU9InRuczpMaXN0T2ZXb3JrT3JkZXJU eXBlIiBuaWxsYWJsZT0idHJ1ZSI+PC94czplbGVtZW50Pg0KDQo8L3hzOnNjaGVtYT4= i=15 -1 1 1 0 false 0 ns=1;i=11443 Variable_2 0 NamespaceUri NamespaceUri 0 0 0 i=46 true ns=1;i=11441 i=40 false i=68 http://test.org/UA/Data/ i=12 -1 1 1 0 false 0 ns=1;i=11444 Variable_2 1 ScalarValueDataType ScalarValueDataType 0 0 0 i=47 true ns=1;i=11441 i=40 false i=69 //xs:element[@name='ScalarValueDataType'] i=12 -1 1 1 0 false 0 ns=1;i=11447 Variable_2 1 ArrayValueDataType ArrayValueDataType 0 0 0 i=47 true ns=1;i=11441 i=40 false i=69 //xs:element[@name='ArrayValueDataType'] i=12 -1 1 1 0 false 0 ns=1;i=11450 Variable_2 1 UserScalarValueDataType UserScalarValueDataType 0 0 0 i=47 true ns=1;i=11441 i=40 false i=69 //xs:element[@name='UserScalarValueDataType'] i=12 -1 1 1 0 false 0 ns=1;i=11453 Variable_2 1 UserArrayValueDataType UserArrayValueDataType 0 0 0 i=47 true ns=1;i=11441 i=40 false i=69 //xs:element[@name='UserArrayValueDataType'] i=12 -1 1 1 0 false 0 ns=1;i=11557 Variable_2 0 ConditionName ConditionName 0 0 0 i=46 true ns=1;i=9387 i=40 false i=68 i=37 false i=78 i=12 -1 1 1 0 false 0 ns=1;i=11565 Variable_2 0 ConditionName ConditionName 0 0 0 i=46 true ns=1;i=10163 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=11566 Variable_2 0 ConditionName ConditionName 0 0 0 i=46 true ns=1;i=10247 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=11567 Variable_2 0 ConditionName ConditionName 0 0 0 i=46 true ns=1;i=10331 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=11568 Variable_2 0 ConditionName ConditionName 0 0 0 i=46 true ns=1;i=10410 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=11569 Variable_2 0 ConditionName ConditionName 0 0 0 i=46 true ns=1;i=10489 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=11570 Variable_2 0 ConditionName ConditionName 0 0 0 i=46 true ns=1;i=10624 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=11571 Variable_2 0 ConditionName ConditionName 0 0 0 i=46 true ns=1;i=10791 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=11572 Variable_2 0 ConditionName ConditionName 0 0 0 i=46 true ns=1;i=10875 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=11573 Variable_2 0 ConditionName ConditionName 0 0 0 i=46 true ns=1;i=10959 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=11574 Variable_2 0 ConditionName ConditionName 0 0 0 i=46 true ns=1;i=11038 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=11575 Variable_2 0 ConditionName ConditionName 0 0 0 i=46 true ns=1;i=11117 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=11576 Variable_2 0 ConditionName ConditionName 0 0 0 i=46 true ns=1;i=11252 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=11577 Variable_2 0 ConditionName ConditionName 0 0 0 i=46 true ns=1;i=11384 i=40 false i=68 i=12 -1 1 1 0 false 0 ns=1;i=11578 Variable_2 0 ConditionClassId ConditionClassId 0 0 0 i=46 true ns=1;i=9387 i=40 false i=68 i=37 false i=78 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11579 Variable_2 0 ConditionClassName ConditionClassName 0 0 0 i=46 true ns=1;i=9387 i=40 false i=68 i=37 false i=78 i=21 -1 1 1 0 false 0 ns=1;i=11594 Variable_2 0 ConditionClassId ConditionClassId 0 0 0 i=46 true ns=1;i=10163 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11595 Variable_2 0 ConditionClassName ConditionClassName 0 0 0 i=46 true ns=1;i=10163 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=11596 Variable_2 0 ConditionClassId ConditionClassId 0 0 0 i=46 true ns=1;i=10247 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11597 Variable_2 0 ConditionClassName ConditionClassName 0 0 0 i=46 true ns=1;i=10247 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=11598 Variable_2 0 ConditionClassId ConditionClassId 0 0 0 i=46 true ns=1;i=10331 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11599 Variable_2 0 ConditionClassName ConditionClassName 0 0 0 i=46 true ns=1;i=10331 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=11600 Variable_2 0 ConditionClassId ConditionClassId 0 0 0 i=46 true ns=1;i=10410 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11601 Variable_2 0 ConditionClassName ConditionClassName 0 0 0 i=46 true ns=1;i=10410 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=11602 Variable_2 0 ConditionClassId ConditionClassId 0 0 0 i=46 true ns=1;i=10489 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11603 Variable_2 0 ConditionClassName ConditionClassName 0 0 0 i=46 true ns=1;i=10489 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=11604 Variable_2 0 ConditionClassId ConditionClassId 0 0 0 i=46 true ns=1;i=10624 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11605 Variable_2 0 ConditionClassName ConditionClassName 0 0 0 i=46 true ns=1;i=10624 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=11606 Variable_2 0 ConditionClassId ConditionClassId 0 0 0 i=46 true ns=1;i=10791 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11607 Variable_2 0 ConditionClassName ConditionClassName 0 0 0 i=46 true ns=1;i=10791 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=11608 Variable_2 0 ConditionClassId ConditionClassId 0 0 0 i=46 true ns=1;i=10875 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11609 Variable_2 0 ConditionClassName ConditionClassName 0 0 0 i=46 true ns=1;i=10875 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=11610 Variable_2 0 ConditionClassId ConditionClassId 0 0 0 i=46 true ns=1;i=10959 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11611 Variable_2 0 ConditionClassName ConditionClassName 0 0 0 i=46 true ns=1;i=10959 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=11612 Variable_2 0 ConditionClassId ConditionClassId 0 0 0 i=46 true ns=1;i=11038 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11613 Variable_2 0 ConditionClassName ConditionClassName 0 0 0 i=46 true ns=1;i=11038 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=11614 Variable_2 0 ConditionClassId ConditionClassId 0 0 0 i=46 true ns=1;i=11117 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11615 Variable_2 0 ConditionClassName ConditionClassName 0 0 0 i=46 true ns=1;i=11117 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=11616 Variable_2 0 ConditionClassId ConditionClassId 0 0 0 i=46 true ns=1;i=11252 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11617 Variable_2 0 ConditionClassName ConditionClassName 0 0 0 i=46 true ns=1;i=11252 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=11618 Variable_2 0 ConditionClassId ConditionClassId 0 0 0 i=46 true ns=1;i=11384 i=40 false i=68 i=0 i=17 -1 1 1 0 false 0 ns=1;i=11619 Variable_2 0 ConditionClassName ConditionClassName 0 0 0 i=46 true ns=1;i=11384 i=40 false i=68 i=21 -1 1 1 0 false 0 ns=1;i=15045 Variable_2 0 Deprecated Deprecated 0 0 0 i=46 true ns=1;i=11422 i=40 false i=68 true i=1 -1 1 1 0 false 0 ns=1;i=15046 Variable_2 0 Deprecated Deprecated 0 0 0 i=46 true ns=1;i=11441 i=40 false i=68 true i=1 -1 1 1 0 false 0 ns=1;i=15047 Object_1 0 Default JSON Default JSON 0 0 0 i=40 false i=76 i=38 true ns=1;i=9440 0 ns=1;i=15048 Object_1 0 Default JSON Default JSON 0 0 0 i=40 false i=76 i=38 true ns=1;i=9669 0 ns=1;i=15049 Object_1 0 Default JSON Default JSON 0 0 0 i=40 false i=76 i=38 true ns=1;i=9920 0 ns=1;i=15050 Object_1 0 Default JSON Default JSON 0 0 0 i=40 false i=76 i=38 true ns=1;i=10006 0 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/TestData/Design/TestData.NodeSet2.xml ================================================  http://test.org/UA/Data/ i=1 i=2 i=3 i=4 i=5 i=6 i=7 i=8 i=9 i=10 i=11 i=13 i=12 i=15 i=14 i=16 i=17 i=18 i=20 i=21 i=19 i=22 i=26 i=27 i=28 i=47 i=46 i=35 i=36 i=48 i=45 i=40 i=37 i=38 i=39 i=53 i=52 i=51 i=54 i=9004 i=9005 i=17597 i=9006 i=15112 i=17604 i=17603 GenerateValuesEventType ns=1;i=9381 ns=1;i=9382 i=2041 Iterations i=68 i=78 ns=1;i=9371 NewValueCount i=68 i=78 ns=1;i=9371 TestDataObjectType ns=1;i=9384 ns=1;i=9385 ns=1;i=9387 ns=1;i=9387 i=58 SimulationActive If true the server will produce new values for each monitored variable. i=68 i=78 ns=1;i=9383 GenerateValues ns=1;i=9386 i=78 ns=1;i=9383 InputArguments i=68 i=78 ns=1;i=9385 i=297 Iterations i=7 -1 The number of new values to generate. CycleComplete ns=1;i=9388 ns=1;i=9389 ns=1;i=9390 ns=1;i=9391 ns=1;i=9392 ns=1;i=9393 ns=1;i=9395 ns=1;i=9396 ns=1;i=11578 ns=1;i=11579 ns=1;i=11557 ns=1;i=9397 ns=1;i=9398 ns=1;i=9399 ns=1;i=9405 ns=1;i=9409 ns=1;i=9411 ns=1;i=9413 ns=1;i=9415 ns=1;i=9414 ns=1;i=9416 ns=1;i=9420 ns=1;i=9436 ns=1;i=9383 i=2881 i=78 ns=1;i=9383 EventId i=68 i=78 ns=1;i=9387 EventType i=68 i=78 ns=1;i=9387 SourceNode i=68 i=78 ns=1;i=9387 SourceName i=68 i=78 ns=1;i=9387 Time i=68 i=78 ns=1;i=9387 ReceiveTime i=68 i=78 ns=1;i=9387 Message i=68 i=78 ns=1;i=9387 Severity i=68 i=78 ns=1;i=9387 ConditionClassId i=68 i=78 ns=1;i=9387 ConditionClassName i=68 i=78 ns=1;i=9387 ConditionName i=68 i=78 ns=1;i=9387 BranchId i=68 i=78 ns=1;i=9387 Retain i=68 i=78 ns=1;i=9387 EnabledState ns=1;i=9400 i=8995 i=78 ns=1;i=9387 Id i=68 i=78 ns=1;i=9399 Quality ns=1;i=9406 i=9002 i=78 ns=1;i=9387 SourceTimestamp i=68 i=78 ns=1;i=9405 LastSeverity ns=1;i=9410 i=9002 i=78 ns=1;i=9387 SourceTimestamp i=68 i=78 ns=1;i=9409 Comment ns=1;i=9412 i=9002 i=78 ns=1;i=9387 SourceTimestamp i=68 i=78 ns=1;i=9411 ClientUserId i=68 i=78 ns=1;i=9387 Disable i=2803 i=78 ns=1;i=9387 Enable i=2803 i=78 ns=1;i=9387 AddComment ns=1;i=9417 i=2829 i=78 ns=1;i=9387 InputArguments i=68 i=78 ns=1;i=9416 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. AckedState ns=1;i=9421 i=8995 i=78 ns=1;i=9387 Id i=68 i=78 ns=1;i=9420 Acknowledge ns=1;i=9437 i=8944 i=78 ns=1;i=9387 InputArguments i=68 i=78 ns=1;i=9436 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. ScalarValueDataType i=22 ScalarValueObjectType ns=1;i=9507 ns=1;i=9508 ns=1;i=9509 ns=1;i=9510 ns=1;i=9511 ns=1;i=9512 ns=1;i=9513 ns=1;i=9514 ns=1;i=9515 ns=1;i=9516 ns=1;i=9517 ns=1;i=9518 ns=1;i=9519 ns=1;i=9520 ns=1;i=9521 ns=1;i=9522 ns=1;i=9523 ns=1;i=9524 ns=1;i=9525 ns=1;i=9526 ns=1;i=9527 ns=1;i=9528 ns=1;i=9529 ns=1;i=9530 ns=1;i=9531 ns=1;i=9532 ns=1;i=9533 ns=1;i=9383 BooleanValue i=63 i=78 ns=1;i=9450 SByteValue i=63 i=78 ns=1;i=9450 ByteValue i=63 i=78 ns=1;i=9450 Int16Value i=63 i=78 ns=1;i=9450 UInt16Value i=63 i=78 ns=1;i=9450 Int32Value i=63 i=78 ns=1;i=9450 UInt32Value i=63 i=78 ns=1;i=9450 Int64Value i=63 i=78 ns=1;i=9450 UInt64Value i=63 i=78 ns=1;i=9450 FloatValue i=63 i=78 ns=1;i=9450 DoubleValue i=63 i=78 ns=1;i=9450 StringValue i=63 i=78 ns=1;i=9450 DateTimeValue i=63 i=78 ns=1;i=9450 GuidValue i=63 i=78 ns=1;i=9450 ByteStringValue i=63 i=78 ns=1;i=9450 XmlElementValue i=63 i=78 ns=1;i=9450 NodeIdValue i=63 i=78 ns=1;i=9450 ExpandedNodeIdValue i=63 i=78 ns=1;i=9450 QualifiedNameValue i=63 i=78 ns=1;i=9450 LocalizedTextValue i=63 i=78 ns=1;i=9450 StatusCodeValue i=63 i=78 ns=1;i=9450 VariantValue i=63 i=78 ns=1;i=9450 EnumerationValue i=63 i=78 ns=1;i=9450 StructureValue i=63 i=78 ns=1;i=9450 NumberValue i=63 i=78 ns=1;i=9450 IntegerValue i=63 i=78 ns=1;i=9450 UIntegerValue i=63 i=78 ns=1;i=9450 AnalogScalarValueObjectType ns=1;i=9591 ns=1;i=9597 ns=1;i=9603 ns=1;i=9609 ns=1;i=9615 ns=1;i=9621 ns=1;i=9627 ns=1;i=9633 ns=1;i=9639 ns=1;i=9645 ns=1;i=9651 ns=1;i=9657 ns=1;i=9663 ns=1;i=9383 SByteValue ns=1;i=9594 i=2368 i=78 ns=1;i=9534 EURange i=68 i=78 ns=1;i=9591 ByteValue ns=1;i=9600 i=2368 i=78 ns=1;i=9534 EURange i=68 i=78 ns=1;i=9597 Int16Value ns=1;i=9606 i=2368 i=78 ns=1;i=9534 EURange i=68 i=78 ns=1;i=9603 UInt16Value ns=1;i=9612 i=2368 i=78 ns=1;i=9534 EURange i=68 i=78 ns=1;i=9609 Int32Value ns=1;i=9618 i=2368 i=78 ns=1;i=9534 EURange i=68 i=78 ns=1;i=9615 UInt32Value ns=1;i=9624 i=2368 i=78 ns=1;i=9534 EURange i=68 i=78 ns=1;i=9621 Int64Value ns=1;i=9630 i=2368 i=78 ns=1;i=9534 EURange i=68 i=78 ns=1;i=9627 UInt64Value ns=1;i=9636 i=2368 i=78 ns=1;i=9534 EURange i=68 i=78 ns=1;i=9633 FloatValue ns=1;i=9642 i=2368 i=78 ns=1;i=9534 EURange i=68 i=78 ns=1;i=9639 DoubleValue ns=1;i=9648 i=2368 i=78 ns=1;i=9534 EURange i=68 i=78 ns=1;i=9645 NumberValue ns=1;i=9654 i=2368 i=78 ns=1;i=9534 EURange i=68 i=78 ns=1;i=9651 IntegerValue ns=1;i=9660 i=2368 i=78 ns=1;i=9534 EURange i=68 i=78 ns=1;i=9657 UIntegerValue ns=1;i=9666 i=2368 i=78 ns=1;i=9534 EURange i=68 i=78 ns=1;i=9663 ArrayValueDataType i=22 ArrayValueObjectType ns=1;i=9736 ns=1;i=9737 ns=1;i=9738 ns=1;i=9739 ns=1;i=9740 ns=1;i=9741 ns=1;i=9742 ns=1;i=9743 ns=1;i=9744 ns=1;i=9745 ns=1;i=9746 ns=1;i=9747 ns=1;i=9748 ns=1;i=9749 ns=1;i=9750 ns=1;i=9751 ns=1;i=9752 ns=1;i=9753 ns=1;i=9754 ns=1;i=9755 ns=1;i=9756 ns=1;i=9757 ns=1;i=9758 ns=1;i=9759 ns=1;i=9760 ns=1;i=9761 ns=1;i=9762 ns=1;i=9383 BooleanValue i=63 i=78 ns=1;i=9679 SByteValue i=63 i=78 ns=1;i=9679 ByteValue i=63 i=78 ns=1;i=9679 Int16Value i=63 i=78 ns=1;i=9679 UInt16Value i=63 i=78 ns=1;i=9679 Int32Value i=63 i=78 ns=1;i=9679 UInt32Value i=63 i=78 ns=1;i=9679 Int64Value i=63 i=78 ns=1;i=9679 UInt64Value i=63 i=78 ns=1;i=9679 FloatValue i=63 i=78 ns=1;i=9679 DoubleValue i=63 i=78 ns=1;i=9679 StringValue i=63 i=78 ns=1;i=9679 DateTimeValue i=63 i=78 ns=1;i=9679 GuidValue i=63 i=78 ns=1;i=9679 ByteStringValue i=63 i=78 ns=1;i=9679 XmlElementValue i=63 i=78 ns=1;i=9679 NodeIdValue i=63 i=78 ns=1;i=9679 ExpandedNodeIdValue i=63 i=78 ns=1;i=9679 QualifiedNameValue i=63 i=78 ns=1;i=9679 LocalizedTextValue i=63 i=78 ns=1;i=9679 StatusCodeValue i=63 i=78 ns=1;i=9679 VariantValue i=63 i=78 ns=1;i=9679 EnumerationValue i=63 i=78 ns=1;i=9679 StructureValue i=63 i=78 ns=1;i=9679 NumberValue i=63 i=78 ns=1;i=9679 IntegerValue i=63 i=78 ns=1;i=9679 UIntegerValue i=63 i=78 ns=1;i=9679 AnalogArrayValueObjectType ns=1;i=9820 ns=1;i=9826 ns=1;i=9832 ns=1;i=9838 ns=1;i=9844 ns=1;i=9850 ns=1;i=9856 ns=1;i=9862 ns=1;i=9868 ns=1;i=9874 ns=1;i=9880 ns=1;i=9886 ns=1;i=9892 ns=1;i=9383 SByteValue ns=1;i=9823 i=2368 i=78 ns=1;i=9763 EURange i=68 i=78 ns=1;i=9820 ByteValue ns=1;i=9829 i=2368 i=78 ns=1;i=9763 EURange i=68 i=78 ns=1;i=9826 Int16Value ns=1;i=9835 i=2368 i=78 ns=1;i=9763 EURange i=68 i=78 ns=1;i=9832 UInt16Value ns=1;i=9841 i=2368 i=78 ns=1;i=9763 EURange i=68 i=78 ns=1;i=9838 Int32Value ns=1;i=9847 i=2368 i=78 ns=1;i=9763 EURange i=68 i=78 ns=1;i=9844 UInt32Value ns=1;i=9853 i=2368 i=78 ns=1;i=9763 EURange i=68 i=78 ns=1;i=9850 Int64Value ns=1;i=9859 i=2368 i=78 ns=1;i=9763 EURange i=68 i=78 ns=1;i=9856 UInt64Value ns=1;i=9865 i=2368 i=78 ns=1;i=9763 EURange i=68 i=78 ns=1;i=9862 FloatValue ns=1;i=9871 i=2368 i=78 ns=1;i=9763 EURange i=68 i=78 ns=1;i=9868 DoubleValue ns=1;i=9877 i=2368 i=78 ns=1;i=9763 EURange i=68 i=78 ns=1;i=9874 NumberValue ns=1;i=9883 i=2368 i=78 ns=1;i=9763 EURange i=68 i=78 ns=1;i=9880 IntegerValue ns=1;i=9889 i=2368 i=78 ns=1;i=9763 EURange i=68 i=78 ns=1;i=9886 UIntegerValue ns=1;i=9895 i=2368 i=78 ns=1;i=9763 EURange i=68 i=78 ns=1;i=9892 BooleanDataType i=1 SByteDataType i=2 ByteDataType i=3 Int16DataType i=4 UInt16DataType i=5 Int32DataType i=6 UInt32DataType i=7 Int64DataType i=8 UInt64DataType i=9 FloatDataType i=10 DoubleDataType i=11 StringDataType i=12 DateTimeDataType i=13 GuidDataType i=14 ByteStringDataType i=15 XmlElementDataType i=16 NodeIdDataType i=17 ExpandedNodeIdDataType i=18 QualifiedNameDataType i=20 LocalizedTextDataType i=21 StatusCodeDataType i=19 VariantDataType i=24 UserScalarValueDataType i=22 UserScalarValueObjectType ns=1;i=9978 ns=1;i=9979 ns=1;i=9980 ns=1;i=9981 ns=1;i=9982 ns=1;i=9983 ns=1;i=9984 ns=1;i=9985 ns=1;i=9986 ns=1;i=9987 ns=1;i=9988 ns=1;i=9989 ns=1;i=9990 ns=1;i=9991 ns=1;i=9992 ns=1;i=9993 ns=1;i=9994 ns=1;i=9995 ns=1;i=9996 ns=1;i=9997 ns=1;i=9998 ns=1;i=9999 ns=1;i=9383 BooleanValue i=63 i=78 ns=1;i=9921 SByteValue i=63 i=78 ns=1;i=9921 ByteValue i=63 i=78 ns=1;i=9921 Int16Value i=63 i=78 ns=1;i=9921 UInt16Value i=63 i=78 ns=1;i=9921 Int32Value i=63 i=78 ns=1;i=9921 UInt32Value i=63 i=78 ns=1;i=9921 Int64Value i=63 i=78 ns=1;i=9921 UInt64Value i=63 i=78 ns=1;i=9921 FloatValue i=63 i=78 ns=1;i=9921 DoubleValue i=63 i=78 ns=1;i=9921 StringValue i=63 i=78 ns=1;i=9921 DateTimeValue i=63 i=78 ns=1;i=9921 GuidValue i=63 i=78 ns=1;i=9921 ByteStringValue i=63 i=78 ns=1;i=9921 XmlElementValue i=63 i=78 ns=1;i=9921 NodeIdValue i=63 i=78 ns=1;i=9921 ExpandedNodeIdValue i=63 i=78 ns=1;i=9921 QualifiedNameValue i=63 i=78 ns=1;i=9921 LocalizedTextValue i=63 i=78 ns=1;i=9921 StatusCodeValue i=63 i=78 ns=1;i=9921 VariantValue i=63 i=78 ns=1;i=9921 UserArrayValueDataType i=22 UserArrayValueObjectType ns=1;i=10064 ns=1;i=10065 ns=1;i=10066 ns=1;i=10067 ns=1;i=10068 ns=1;i=10069 ns=1;i=10070 ns=1;i=10071 ns=1;i=10072 ns=1;i=10073 ns=1;i=10074 ns=1;i=10075 ns=1;i=10076 ns=1;i=10077 ns=1;i=10078 ns=1;i=10079 ns=1;i=10080 ns=1;i=10081 ns=1;i=10082 ns=1;i=10083 ns=1;i=10084 ns=1;i=10085 ns=1;i=9383 BooleanValue i=63 i=78 ns=1;i=10007 SByteValue i=63 i=78 ns=1;i=10007 ByteValue i=63 i=78 ns=1;i=10007 Int16Value i=63 i=78 ns=1;i=10007 UInt16Value i=63 i=78 ns=1;i=10007 Int32Value i=63 i=78 ns=1;i=10007 UInt32Value i=63 i=78 ns=1;i=10007 Int64Value i=63 i=78 ns=1;i=10007 UInt64Value i=63 i=78 ns=1;i=10007 FloatValue i=63 i=78 ns=1;i=10007 DoubleValue i=63 i=78 ns=1;i=10007 StringValue i=63 i=78 ns=1;i=10007 DateTimeValue i=63 i=78 ns=1;i=10007 GuidValue i=63 i=78 ns=1;i=10007 ByteStringValue i=63 i=78 ns=1;i=10007 XmlElementValue i=63 i=78 ns=1;i=10007 NodeIdValue i=63 i=78 ns=1;i=10007 ExpandedNodeIdValue i=63 i=78 ns=1;i=10007 QualifiedNameValue i=63 i=78 ns=1;i=10007 LocalizedTextValue i=63 i=78 ns=1;i=10007 StatusCodeValue i=63 i=78 ns=1;i=10007 VariantValue i=63 i=78 ns=1;i=10007 Vector i=22 WorkOrderStatusType i=22 WorkOrderType i=22 MethodTestType ns=1;i=10093 ns=1;i=10096 ns=1;i=10099 ns=1;i=10102 ns=1;i=10105 ns=1;i=10108 ns=1;i=10111 ns=1;i=10114 ns=1;i=10117 ns=1;i=10120 i=61 ScalarMethod1 ns=1;i=10094 ns=1;i=10095 i=78 ns=1;i=10092 InputArguments i=68 i=78 ns=1;i=10093 i=297 BooleanIn i=1 -1 i=297 SByteIn i=2 -1 i=297 ByteIn i=3 -1 i=297 Int16In i=4 -1 i=297 UInt16In i=5 -1 i=297 Int32In i=6 -1 i=297 UInt32In i=7 -1 i=297 Int64In i=8 -1 i=297 UInt64In i=9 -1 i=297 FloatIn i=10 -1 i=297 DoubleIn i=11 -1 OutputArguments i=68 i=78 ns=1;i=10093 i=297 BooleanOut i=1 -1 i=297 SByteOut i=2 -1 i=297 ByteOut i=3 -1 i=297 Int16Out i=4 -1 i=297 UInt16Out i=5 -1 i=297 Int32Out i=6 -1 i=297 UInt32Out i=7 -1 i=297 Int64Out i=8 -1 i=297 UInt64Out i=9 -1 i=297 FloatOut i=10 -1 i=297 DoubleOut i=11 -1 ScalarMethod2 ns=1;i=10097 ns=1;i=10098 i=78 ns=1;i=10092 InputArguments i=68 i=78 ns=1;i=10096 i=297 StringIn i=12 -1 i=297 DateTimeIn i=13 -1 i=297 GuidIn i=14 -1 i=297 ByteStringIn i=15 -1 i=297 XmlElementIn i=16 -1 i=297 NodeIdIn i=17 -1 i=297 ExpandedNodeIdIn i=18 -1 i=297 QualifiedNameIn i=20 -1 i=297 LocalizedTextIn i=21 -1 i=297 StatusCodeIn i=19 -1 OutputArguments i=68 i=78 ns=1;i=10096 i=297 StringOut i=12 -1 i=297 DateTimeOut i=13 -1 i=297 GuidOut i=14 -1 i=297 ByteStringOut i=15 -1 i=297 XmlElementOut i=16 -1 i=297 NodeIdOut i=17 -1 i=297 ExpandedNodeIdOut i=18 -1 i=297 QualifiedNameOut i=20 -1 i=297 LocalizedTextOut i=21 -1 i=297 StatusCodeOut i=19 -1 ScalarMethod3 ns=1;i=10100 ns=1;i=10101 i=78 ns=1;i=10092 InputArguments i=68 i=78 ns=1;i=10099 i=297 VariantIn i=24 -1 i=297 EnumerationIn i=29 -1 i=297 StructureIn i=22 -1 OutputArguments i=68 i=78 ns=1;i=10099 i=297 VariantOut i=24 -1 i=297 EnumerationOut i=29 -1 i=297 StructureOut i=22 -1 ArrayMethod1 ns=1;i=10103 ns=1;i=10104 i=78 ns=1;i=10092 InputArguments i=68 i=78 ns=1;i=10102 i=297 BooleanIn i=1 1 0 i=297 SByteIn i=2 1 0 i=297 ByteIn i=3 1 0 i=297 Int16In i=4 1 0 i=297 UInt16In i=5 1 0 i=297 Int32In i=6 1 0 i=297 UInt32In i=7 1 0 i=297 Int64In i=8 1 0 i=297 UInt64In i=9 1 0 i=297 FloatIn i=10 1 0 i=297 DoubleIn i=11 1 0 OutputArguments i=68 i=78 ns=1;i=10102 i=297 BooleanOut i=1 1 0 i=297 SByteOut i=2 1 0 i=297 ByteOut i=3 1 0 i=297 Int16Out i=4 1 0 i=297 UInt16Out i=5 1 0 i=297 Int32Out i=6 1 0 i=297 UInt32Out i=7 1 0 i=297 Int64Out i=8 1 0 i=297 UInt64Out i=9 1 0 i=297 FloatOut i=10 1 0 i=297 DoubleOut i=11 1 0 ArrayMethod2 ns=1;i=10106 ns=1;i=10107 i=78 ns=1;i=10092 InputArguments i=68 i=78 ns=1;i=10105 i=297 StringIn i=12 1 0 i=297 DateTimeIn i=13 1 0 i=297 GuidIn i=14 1 0 i=297 ByteStringIn i=15 1 0 i=297 XmlElementIn i=16 1 0 i=297 NodeIdIn i=17 1 0 i=297 ExpandedNodeIdIn i=18 1 0 i=297 QualifiedNameIn i=20 1 0 i=297 LocalizedTextIn i=21 1 0 i=297 StatusCodeIn i=19 1 0 OutputArguments i=68 i=78 ns=1;i=10105 i=297 StringOut i=12 1 0 i=297 DateTimeOut i=13 1 0 i=297 GuidOut i=14 1 0 i=297 ByteStringOut i=15 1 0 i=297 XmlElementOut i=16 1 0 i=297 NodeIdOut i=17 1 0 i=297 ExpandedNodeIdOut i=18 1 0 i=297 QualifiedNameOut i=20 1 0 i=297 LocalizedTextOut i=21 1 0 i=297 StatusCodeOut i=19 1 0 ArrayMethod3 ns=1;i=10109 ns=1;i=10110 i=78 ns=1;i=10092 InputArguments i=68 i=78 ns=1;i=10108 i=297 VariantIn i=24 1 0 i=297 EnumerationIn i=29 1 0 i=297 StructureIn i=22 1 0 OutputArguments i=68 i=78 ns=1;i=10108 i=297 VariantOut i=24 1 0 i=297 EnumerationOut i=29 1 0 i=297 StructureOut i=22 1 0 UserScalarMethod1 ns=1;i=10112 ns=1;i=10113 i=78 ns=1;i=10092 InputArguments i=68 i=78 ns=1;i=10111 i=297 BooleanIn ns=1;i=9898 -1 i=297 SByteIn ns=1;i=9899 -1 i=297 ByteIn ns=1;i=9900 -1 i=297 Int16In ns=1;i=9901 -1 i=297 UInt16In ns=1;i=9902 -1 i=297 Int32In ns=1;i=9903 -1 i=297 UInt32In ns=1;i=9904 -1 i=297 Int64In ns=1;i=9905 -1 i=297 UInt64In ns=1;i=9906 -1 i=297 FloatIn ns=1;i=9907 -1 i=297 DoubleIn ns=1;i=9908 -1 i=297 StringIn ns=1;i=9909 -1 OutputArguments i=68 i=78 ns=1;i=10111 i=297 BooleanOut ns=1;i=9898 -1 i=297 SByteOut ns=1;i=9899 -1 i=297 ByteOut ns=1;i=9900 -1 i=297 Int16Out ns=1;i=9901 -1 i=297 UInt16Out ns=1;i=9902 -1 i=297 Int32Out ns=1;i=9903 -1 i=297 UInt32Out ns=1;i=9904 -1 i=297 Int64Out ns=1;i=9905 -1 i=297 UInt64Out ns=1;i=9906 -1 i=297 FloatOut ns=1;i=9907 -1 i=297 DoubleOut ns=1;i=9908 -1 i=297 StringOut ns=1;i=9909 -1 UserScalarMethod2 ns=1;i=10115 ns=1;i=10116 i=78 ns=1;i=10092 InputArguments i=68 i=78 ns=1;i=10114 i=297 DateTimeIn ns=1;i=9910 -1 i=297 GuidIn ns=1;i=9911 -1 i=297 ByteStringIn ns=1;i=9912 -1 i=297 XmlElementIn ns=1;i=9913 -1 i=297 NodeIdIn ns=1;i=9914 -1 i=297 ExpandedNodeIdIn ns=1;i=9915 -1 i=297 QualifiedNameIn ns=1;i=9916 -1 i=297 LocalizedTextIn ns=1;i=9917 -1 i=297 StatusCodeIn ns=1;i=9918 -1 i=297 VariantIn ns=1;i=9919 -1 OutputArguments i=68 i=78 ns=1;i=10114 i=297 DateTimeOut ns=1;i=9910 -1 i=297 GuidOut ns=1;i=9911 -1 i=297 ByteStringOut ns=1;i=9912 -1 i=297 XmlElementOut ns=1;i=9913 -1 i=297 NodeIdOut ns=1;i=9914 -1 i=297 ExpandedNodeIdOut ns=1;i=9915 -1 i=297 QualifiedNameOut ns=1;i=9916 -1 i=297 LocalizedTextOut ns=1;i=9917 -1 i=297 StatusCodeOut ns=1;i=9918 -1 i=297 VariantOut ns=1;i=9919 -1 UserArrayMethod1 ns=1;i=10118 ns=1;i=10119 i=78 ns=1;i=10092 InputArguments i=68 i=78 ns=1;i=10117 i=297 BooleanIn ns=1;i=9898 1 0 i=297 SByteIn ns=1;i=9899 1 0 i=297 ByteIn ns=1;i=9900 1 0 i=297 Int16In ns=1;i=9901 1 0 i=297 UInt16In ns=1;i=9902 1 0 i=297 Int32In ns=1;i=9903 1 0 i=297 UInt32In ns=1;i=9904 1 0 i=297 Int64In ns=1;i=9905 1 0 i=297 UInt64In ns=1;i=9906 1 0 i=297 FloatIn ns=1;i=9907 1 0 i=297 DoubleIn ns=1;i=9908 1 0 i=297 StringIn ns=1;i=9909 1 0 OutputArguments i=68 i=78 ns=1;i=10117 i=297 BooleanOut ns=1;i=9898 1 0 i=297 SByteOut ns=1;i=9899 1 0 i=297 ByteOut ns=1;i=9900 1 0 i=297 Int16Out ns=1;i=9901 1 0 i=297 UInt16Out ns=1;i=9902 1 0 i=297 Int32Out ns=1;i=9903 1 0 i=297 UInt32Out ns=1;i=9904 1 0 i=297 Int64Out ns=1;i=9905 1 0 i=297 UInt64Out ns=1;i=9906 1 0 i=297 FloatOut ns=1;i=9907 1 0 i=297 DoubleOut ns=1;i=9908 1 0 i=297 StringOut ns=1;i=9909 1 0 UserArrayMethod2 ns=1;i=10121 ns=1;i=10122 i=78 ns=1;i=10092 InputArguments i=68 i=78 ns=1;i=10120 i=297 DateTimeIn ns=1;i=9910 1 0 i=297 GuidIn ns=1;i=9911 1 0 i=297 ByteStringIn ns=1;i=9912 1 0 i=297 XmlElementIn ns=1;i=9913 1 0 i=297 NodeIdIn ns=1;i=9914 1 0 i=297 ExpandedNodeIdIn ns=1;i=9915 1 0 i=297 QualifiedNameIn ns=1;i=9916 1 0 i=297 LocalizedTextIn ns=1;i=9917 1 0 i=297 StatusCodeIn ns=1;i=9918 1 0 i=297 VariantIn ns=1;i=9919 1 0 OutputArguments i=68 i=78 ns=1;i=10120 i=297 DateTimeOut ns=1;i=9910 1 0 i=297 GuidOut ns=1;i=9911 1 0 i=297 ByteStringOut ns=1;i=9912 1 0 i=297 XmlElementOut ns=1;i=9913 1 0 i=297 NodeIdOut ns=1;i=9914 1 0 i=297 ExpandedNodeIdOut ns=1;i=9915 1 0 i=297 QualifiedNameOut ns=1;i=9916 1 0 i=297 LocalizedTextOut ns=1;i=9917 1 0 i=297 StatusCodeOut ns=1;i=9918 1 0 i=297 VariantOut ns=1;i=9919 1 0 TestSystemConditionType ns=1;i=10156 i=2782 MonitoredNodeCount i=68 i=78 ns=1;i=10123 Data ns=1;i=10158 ns=1;i=10786 ns=1;i=11383 i=85 i=2253 ns=1;i=10158 ns=1;i=10786 i=61 Static ns=1;i=10159 ns=1;i=10243 ns=1;i=10327 ns=1;i=10406 ns=1;i=10485 ns=1;i=10620 ns=1;i=10755 ns=1;i=10157 ns=1;i=10159 ns=1;i=10243 i=61 ns=1;i=10157 Scalar ns=1;i=10160 ns=1;i=10161 ns=1;i=10163 ns=1;i=10216 ns=1;i=10217 ns=1;i=10218 ns=1;i=10219 ns=1;i=10220 ns=1;i=10221 ns=1;i=10222 ns=1;i=10223 ns=1;i=10224 ns=1;i=10225 ns=1;i=10226 ns=1;i=10227 ns=1;i=10228 ns=1;i=10229 ns=1;i=10230 ns=1;i=10231 ns=1;i=10232 ns=1;i=10233 ns=1;i=10234 ns=1;i=10235 ns=1;i=10236 ns=1;i=10237 ns=1;i=10238 ns=1;i=10239 ns=1;i=10240 ns=1;i=10241 ns=1;i=10242 ns=1;i=10158 ns=1;i=10163 ns=1;i=9450 ns=1;i=10158 SimulationActive If true the server will produce new values for each monitored variable. i=68 ns=1;i=10159 GenerateValues ns=1;i=10162 ns=1;i=10159 InputArguments i=68 ns=1;i=10161 i=297 Iterations i=7 -1 The number of new values to generate. CycleComplete ns=1;i=10164 ns=1;i=10165 ns=1;i=10166 ns=1;i=10167 ns=1;i=10168 ns=1;i=10169 ns=1;i=10171 ns=1;i=10172 ns=1;i=11594 ns=1;i=11595 ns=1;i=11565 ns=1;i=10173 ns=1;i=10174 ns=1;i=10175 ns=1;i=10181 ns=1;i=10185 ns=1;i=10187 ns=1;i=10189 ns=1;i=10191 ns=1;i=10190 ns=1;i=10192 ns=1;i=10196 ns=1;i=10212 ns=1;i=10159 i=2881 ns=1;i=10159 EventId i=68 ns=1;i=10163 EventType i=68 ns=1;i=10163 SourceNode i=68 ns=1;i=10163 SourceName i=68 ns=1;i=10163 Time i=68 ns=1;i=10163 ReceiveTime i=68 ns=1;i=10163 Message i=68 ns=1;i=10163 Severity i=68 ns=1;i=10163 ConditionClassId i=68 ns=1;i=10163 ConditionClassName i=68 ns=1;i=10163 ConditionName i=68 ns=1;i=10163 BranchId i=68 ns=1;i=10163 Retain i=68 ns=1;i=10163 EnabledState ns=1;i=10176 ns=1;i=10196 ns=1;i=10204 i=8995 ns=1;i=10163 Id i=68 ns=1;i=10175 Quality ns=1;i=10182 i=9002 ns=1;i=10163 SourceTimestamp i=68 ns=1;i=10181 LastSeverity ns=1;i=10186 i=9002 ns=1;i=10163 SourceTimestamp i=68 ns=1;i=10185 Comment ns=1;i=10188 i=9002 ns=1;i=10163 SourceTimestamp i=68 ns=1;i=10187 ClientUserId i=68 ns=1;i=10163 Disable i=2803 ns=1;i=10163 Enable i=2803 ns=1;i=10163 AddComment ns=1;i=10193 i=2829 ns=1;i=10163 InputArguments i=68 ns=1;i=10192 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. AckedState ns=1;i=10197 ns=1;i=10175 i=8995 ns=1;i=10163 Id i=68 ns=1;i=10196 Acknowledge ns=1;i=10213 i=8944 ns=1;i=10163 InputArguments i=68 ns=1;i=10212 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. BooleanValue i=63 ns=1;i=10159 SByteValue i=63 ns=1;i=10159 ByteValue i=63 ns=1;i=10159 Int16Value i=63 ns=1;i=10159 UInt16Value i=63 ns=1;i=10159 Int32Value i=63 ns=1;i=10159 UInt32Value i=63 ns=1;i=10159 Int64Value i=63 ns=1;i=10159 UInt64Value i=63 ns=1;i=10159 FloatValue i=63 ns=1;i=10159 DoubleValue i=63 ns=1;i=10159 StringValue i=63 ns=1;i=10159 DateTimeValue i=63 ns=1;i=10159 GuidValue i=63 ns=1;i=10159 ByteStringValue i=63 ns=1;i=10159 XmlElementValue i=63 ns=1;i=10159 NodeIdValue i=63 ns=1;i=10159 ExpandedNodeIdValue i=63 ns=1;i=10159 QualifiedNameValue i=63 ns=1;i=10159 LocalizedTextValue i=63 ns=1;i=10159 StatusCodeValue i=63 ns=1;i=10159 VariantValue i=63 ns=1;i=10159 EnumerationValue i=63 ns=1;i=10159 StructureValue i=63 ns=1;i=10159 NumberValue i=63 ns=1;i=10159 IntegerValue i=63 ns=1;i=10159 UIntegerValue i=63 ns=1;i=10159 Array ns=1;i=10244 ns=1;i=10245 ns=1;i=10247 ns=1;i=10300 ns=1;i=10301 ns=1;i=10302 ns=1;i=10303 ns=1;i=10304 ns=1;i=10305 ns=1;i=10306 ns=1;i=10307 ns=1;i=10308 ns=1;i=10309 ns=1;i=10310 ns=1;i=10311 ns=1;i=10312 ns=1;i=10313 ns=1;i=10314 ns=1;i=10315 ns=1;i=10316 ns=1;i=10317 ns=1;i=10318 ns=1;i=10319 ns=1;i=10320 ns=1;i=10321 ns=1;i=10322 ns=1;i=10323 ns=1;i=10324 ns=1;i=10325 ns=1;i=10326 ns=1;i=10158 ns=1;i=10247 ns=1;i=9679 ns=1;i=10158 SimulationActive If true the server will produce new values for each monitored variable. i=68 ns=1;i=10243 GenerateValues ns=1;i=10246 ns=1;i=10243 InputArguments i=68 ns=1;i=10245 i=297 Iterations i=7 -1 The number of new values to generate. CycleComplete ns=1;i=10248 ns=1;i=10249 ns=1;i=10250 ns=1;i=10251 ns=1;i=10252 ns=1;i=10253 ns=1;i=10255 ns=1;i=10256 ns=1;i=11596 ns=1;i=11597 ns=1;i=11566 ns=1;i=10257 ns=1;i=10258 ns=1;i=10259 ns=1;i=10265 ns=1;i=10269 ns=1;i=10271 ns=1;i=10273 ns=1;i=10275 ns=1;i=10274 ns=1;i=10276 ns=1;i=10280 ns=1;i=10296 ns=1;i=10243 i=2881 ns=1;i=10243 EventId i=68 ns=1;i=10247 EventType i=68 ns=1;i=10247 SourceNode i=68 ns=1;i=10247 SourceName i=68 ns=1;i=10247 Time i=68 ns=1;i=10247 ReceiveTime i=68 ns=1;i=10247 Message i=68 ns=1;i=10247 Severity i=68 ns=1;i=10247 ConditionClassId i=68 ns=1;i=10247 ConditionClassName i=68 ns=1;i=10247 ConditionName i=68 ns=1;i=10247 BranchId i=68 ns=1;i=10247 Retain i=68 ns=1;i=10247 EnabledState ns=1;i=10260 ns=1;i=10280 ns=1;i=10288 i=8995 ns=1;i=10247 Id i=68 ns=1;i=10259 Quality ns=1;i=10266 i=9002 ns=1;i=10247 SourceTimestamp i=68 ns=1;i=10265 LastSeverity ns=1;i=10270 i=9002 ns=1;i=10247 SourceTimestamp i=68 ns=1;i=10269 Comment ns=1;i=10272 i=9002 ns=1;i=10247 SourceTimestamp i=68 ns=1;i=10271 ClientUserId i=68 ns=1;i=10247 Disable i=2803 ns=1;i=10247 Enable i=2803 ns=1;i=10247 AddComment ns=1;i=10277 i=2829 ns=1;i=10247 InputArguments i=68 ns=1;i=10276 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. AckedState ns=1;i=10281 ns=1;i=10259 i=8995 ns=1;i=10247 Id i=68 ns=1;i=10280 Acknowledge ns=1;i=10297 i=8944 ns=1;i=10247 InputArguments i=68 ns=1;i=10296 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. BooleanValue i=63 ns=1;i=10243 SByteValue i=63 ns=1;i=10243 ByteValue i=63 ns=1;i=10243 Int16Value i=63 ns=1;i=10243 UInt16Value i=63 ns=1;i=10243 Int32Value i=63 ns=1;i=10243 UInt32Value i=63 ns=1;i=10243 Int64Value i=63 ns=1;i=10243 UInt64Value i=63 ns=1;i=10243 FloatValue i=63 ns=1;i=10243 DoubleValue i=63 ns=1;i=10243 StringValue i=63 ns=1;i=10243 DateTimeValue i=63 ns=1;i=10243 GuidValue i=63 ns=1;i=10243 ByteStringValue i=63 ns=1;i=10243 XmlElementValue i=63 ns=1;i=10243 NodeIdValue i=63 ns=1;i=10243 ExpandedNodeIdValue i=63 ns=1;i=10243 QualifiedNameValue i=63 ns=1;i=10243 LocalizedTextValue i=63 ns=1;i=10243 StatusCodeValue i=63 ns=1;i=10243 VariantValue i=63 ns=1;i=10243 EnumerationValue i=63 ns=1;i=10243 StructureValue i=63 ns=1;i=10243 NumberValue i=63 ns=1;i=10243 IntegerValue i=63 ns=1;i=10243 UIntegerValue i=63 ns=1;i=10243 UserScalar ns=1;i=10328 ns=1;i=10329 ns=1;i=10331 ns=1;i=10384 ns=1;i=10385 ns=1;i=10386 ns=1;i=10387 ns=1;i=10388 ns=1;i=10389 ns=1;i=10390 ns=1;i=10391 ns=1;i=10392 ns=1;i=10393 ns=1;i=10394 ns=1;i=10395 ns=1;i=10396 ns=1;i=10397 ns=1;i=10398 ns=1;i=10399 ns=1;i=10400 ns=1;i=10401 ns=1;i=10402 ns=1;i=10403 ns=1;i=10404 ns=1;i=10405 ns=1;i=10331 ns=1;i=9921 ns=1;i=10158 SimulationActive If true the server will produce new values for each monitored variable. i=68 ns=1;i=10327 GenerateValues ns=1;i=10330 ns=1;i=10327 InputArguments i=68 ns=1;i=10329 i=297 Iterations i=7 -1 The number of new values to generate. CycleComplete ns=1;i=10332 ns=1;i=10333 ns=1;i=10334 ns=1;i=10335 ns=1;i=10336 ns=1;i=10337 ns=1;i=10339 ns=1;i=10340 ns=1;i=11598 ns=1;i=11599 ns=1;i=11567 ns=1;i=10341 ns=1;i=10342 ns=1;i=10343 ns=1;i=10349 ns=1;i=10353 ns=1;i=10355 ns=1;i=10357 ns=1;i=10359 ns=1;i=10358 ns=1;i=10360 ns=1;i=10364 ns=1;i=10380 ns=1;i=10327 i=2881 ns=1;i=10327 EventId i=68 ns=1;i=10331 EventType i=68 ns=1;i=10331 SourceNode i=68 ns=1;i=10331 SourceName i=68 ns=1;i=10331 Time i=68 ns=1;i=10331 ReceiveTime i=68 ns=1;i=10331 Message i=68 ns=1;i=10331 Severity i=68 ns=1;i=10331 ConditionClassId i=68 ns=1;i=10331 ConditionClassName i=68 ns=1;i=10331 ConditionName i=68 ns=1;i=10331 BranchId i=68 ns=1;i=10331 Retain i=68 ns=1;i=10331 EnabledState ns=1;i=10344 ns=1;i=10364 ns=1;i=10372 i=8995 ns=1;i=10331 Id i=68 ns=1;i=10343 Quality ns=1;i=10350 i=9002 ns=1;i=10331 SourceTimestamp i=68 ns=1;i=10349 LastSeverity ns=1;i=10354 i=9002 ns=1;i=10331 SourceTimestamp i=68 ns=1;i=10353 Comment ns=1;i=10356 i=9002 ns=1;i=10331 SourceTimestamp i=68 ns=1;i=10355 ClientUserId i=68 ns=1;i=10331 Disable i=2803 ns=1;i=10331 Enable i=2803 ns=1;i=10331 AddComment ns=1;i=10361 i=2829 ns=1;i=10331 InputArguments i=68 ns=1;i=10360 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. AckedState ns=1;i=10365 ns=1;i=10343 i=8995 ns=1;i=10331 Id i=68 ns=1;i=10364 Acknowledge ns=1;i=10381 i=8944 ns=1;i=10331 InputArguments i=68 ns=1;i=10380 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. BooleanValue i=63 ns=1;i=10327 SByteValue i=63 ns=1;i=10327 ByteValue i=63 ns=1;i=10327 Int16Value i=63 ns=1;i=10327 UInt16Value i=63 ns=1;i=10327 Int32Value i=63 ns=1;i=10327 UInt32Value i=63 ns=1;i=10327 Int64Value i=63 ns=1;i=10327 UInt64Value i=63 ns=1;i=10327 FloatValue i=63 ns=1;i=10327 DoubleValue i=63 ns=1;i=10327 StringValue i=63 ns=1;i=10327 DateTimeValue i=63 ns=1;i=10327 GuidValue i=63 ns=1;i=10327 ByteStringValue i=63 ns=1;i=10327 XmlElementValue i=63 ns=1;i=10327 NodeIdValue i=63 ns=1;i=10327 ExpandedNodeIdValue i=63 ns=1;i=10327 QualifiedNameValue i=63 ns=1;i=10327 LocalizedTextValue i=63 ns=1;i=10327 StatusCodeValue i=63 ns=1;i=10327 VariantValue i=63 ns=1;i=10327 UserArray ns=1;i=10407 ns=1;i=10408 ns=1;i=10410 ns=1;i=10463 ns=1;i=10464 ns=1;i=10465 ns=1;i=10466 ns=1;i=10467 ns=1;i=10468 ns=1;i=10469 ns=1;i=10470 ns=1;i=10471 ns=1;i=10472 ns=1;i=10473 ns=1;i=10474 ns=1;i=10475 ns=1;i=10476 ns=1;i=10477 ns=1;i=10478 ns=1;i=10479 ns=1;i=10480 ns=1;i=10481 ns=1;i=10482 ns=1;i=10483 ns=1;i=10484 ns=1;i=10410 ns=1;i=10007 ns=1;i=10158 SimulationActive If true the server will produce new values for each monitored variable. i=68 ns=1;i=10406 GenerateValues ns=1;i=10409 ns=1;i=10406 InputArguments i=68 ns=1;i=10408 i=297 Iterations i=7 -1 The number of new values to generate. CycleComplete ns=1;i=10411 ns=1;i=10412 ns=1;i=10413 ns=1;i=10414 ns=1;i=10415 ns=1;i=10416 ns=1;i=10418 ns=1;i=10419 ns=1;i=11600 ns=1;i=11601 ns=1;i=11568 ns=1;i=10420 ns=1;i=10421 ns=1;i=10422 ns=1;i=10428 ns=1;i=10432 ns=1;i=10434 ns=1;i=10436 ns=1;i=10438 ns=1;i=10437 ns=1;i=10439 ns=1;i=10443 ns=1;i=10459 ns=1;i=10406 i=2881 ns=1;i=10406 EventId i=68 ns=1;i=10410 EventType i=68 ns=1;i=10410 SourceNode i=68 ns=1;i=10410 SourceName i=68 ns=1;i=10410 Time i=68 ns=1;i=10410 ReceiveTime i=68 ns=1;i=10410 Message i=68 ns=1;i=10410 Severity i=68 ns=1;i=10410 ConditionClassId i=68 ns=1;i=10410 ConditionClassName i=68 ns=1;i=10410 ConditionName i=68 ns=1;i=10410 BranchId i=68 ns=1;i=10410 Retain i=68 ns=1;i=10410 EnabledState ns=1;i=10423 ns=1;i=10443 ns=1;i=10451 i=8995 ns=1;i=10410 Id i=68 ns=1;i=10422 Quality ns=1;i=10429 i=9002 ns=1;i=10410 SourceTimestamp i=68 ns=1;i=10428 LastSeverity ns=1;i=10433 i=9002 ns=1;i=10410 SourceTimestamp i=68 ns=1;i=10432 Comment ns=1;i=10435 i=9002 ns=1;i=10410 SourceTimestamp i=68 ns=1;i=10434 ClientUserId i=68 ns=1;i=10410 Disable i=2803 ns=1;i=10410 Enable i=2803 ns=1;i=10410 AddComment ns=1;i=10440 i=2829 ns=1;i=10410 InputArguments i=68 ns=1;i=10439 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. AckedState ns=1;i=10444 ns=1;i=10422 i=8995 ns=1;i=10410 Id i=68 ns=1;i=10443 Acknowledge ns=1;i=10460 i=8944 ns=1;i=10410 InputArguments i=68 ns=1;i=10459 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. BooleanValue i=63 ns=1;i=10406 SByteValue i=63 ns=1;i=10406 ByteValue i=63 ns=1;i=10406 Int16Value i=63 ns=1;i=10406 UInt16Value i=63 ns=1;i=10406 Int32Value i=63 ns=1;i=10406 UInt32Value i=63 ns=1;i=10406 Int64Value i=63 ns=1;i=10406 UInt64Value i=63 ns=1;i=10406 FloatValue i=63 ns=1;i=10406 DoubleValue i=63 ns=1;i=10406 StringValue i=63 ns=1;i=10406 DateTimeValue i=63 ns=1;i=10406 GuidValue i=63 ns=1;i=10406 ByteStringValue i=63 ns=1;i=10406 XmlElementValue i=63 ns=1;i=10406 NodeIdValue i=63 ns=1;i=10406 ExpandedNodeIdValue i=63 ns=1;i=10406 QualifiedNameValue i=63 ns=1;i=10406 LocalizedTextValue i=63 ns=1;i=10406 StatusCodeValue i=63 ns=1;i=10406 VariantValue i=63 ns=1;i=10406 AnalogScalar ns=1;i=10486 ns=1;i=10487 ns=1;i=10489 ns=1;i=10542 ns=1;i=10548 ns=1;i=10554 ns=1;i=10560 ns=1;i=10566 ns=1;i=10572 ns=1;i=10578 ns=1;i=10584 ns=1;i=10590 ns=1;i=10596 ns=1;i=10602 ns=1;i=10608 ns=1;i=10614 ns=1;i=10489 ns=1;i=9534 ns=1;i=10158 SimulationActive If true the server will produce new values for each monitored variable. i=68 ns=1;i=10485 GenerateValues ns=1;i=10488 ns=1;i=10485 InputArguments i=68 ns=1;i=10487 i=297 Iterations i=7 -1 The number of new values to generate. CycleComplete ns=1;i=10490 ns=1;i=10491 ns=1;i=10492 ns=1;i=10493 ns=1;i=10494 ns=1;i=10495 ns=1;i=10497 ns=1;i=10498 ns=1;i=11602 ns=1;i=11603 ns=1;i=11569 ns=1;i=10499 ns=1;i=10500 ns=1;i=10501 ns=1;i=10507 ns=1;i=10511 ns=1;i=10513 ns=1;i=10515 ns=1;i=10517 ns=1;i=10516 ns=1;i=10518 ns=1;i=10522 ns=1;i=10538 ns=1;i=10485 i=2881 ns=1;i=10485 EventId i=68 ns=1;i=10489 EventType i=68 ns=1;i=10489 SourceNode i=68 ns=1;i=10489 SourceName i=68 ns=1;i=10489 Time i=68 ns=1;i=10489 ReceiveTime i=68 ns=1;i=10489 Message i=68 ns=1;i=10489 Severity i=68 ns=1;i=10489 ConditionClassId i=68 ns=1;i=10489 ConditionClassName i=68 ns=1;i=10489 ConditionName i=68 ns=1;i=10489 BranchId i=68 ns=1;i=10489 Retain i=68 ns=1;i=10489 EnabledState ns=1;i=10502 ns=1;i=10522 ns=1;i=10530 i=8995 ns=1;i=10489 Id i=68 ns=1;i=10501 Quality ns=1;i=10508 i=9002 ns=1;i=10489 SourceTimestamp i=68 ns=1;i=10507 LastSeverity ns=1;i=10512 i=9002 ns=1;i=10489 SourceTimestamp i=68 ns=1;i=10511 Comment ns=1;i=10514 i=9002 ns=1;i=10489 SourceTimestamp i=68 ns=1;i=10513 ClientUserId i=68 ns=1;i=10489 Disable i=2803 ns=1;i=10489 Enable i=2803 ns=1;i=10489 AddComment ns=1;i=10519 i=2829 ns=1;i=10489 InputArguments i=68 ns=1;i=10518 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. AckedState ns=1;i=10523 ns=1;i=10501 i=8995 ns=1;i=10489 Id i=68 ns=1;i=10522 Acknowledge ns=1;i=10539 i=8944 ns=1;i=10489 InputArguments i=68 ns=1;i=10538 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. SByteValue ns=1;i=10545 i=2368 ns=1;i=10485 EURange i=68 ns=1;i=10542 ByteValue ns=1;i=10551 i=2368 ns=1;i=10485 EURange i=68 ns=1;i=10548 Int16Value ns=1;i=10557 i=2368 ns=1;i=10485 EURange i=68 ns=1;i=10554 UInt16Value ns=1;i=10563 i=2368 ns=1;i=10485 EURange i=68 ns=1;i=10560 Int32Value ns=1;i=10569 i=2368 ns=1;i=10485 EURange i=68 ns=1;i=10566 UInt32Value ns=1;i=10575 i=2368 ns=1;i=10485 EURange i=68 ns=1;i=10572 Int64Value ns=1;i=10581 i=2368 ns=1;i=10485 EURange i=68 ns=1;i=10578 UInt64Value ns=1;i=10587 i=2368 ns=1;i=10485 EURange i=68 ns=1;i=10584 FloatValue ns=1;i=10593 i=2368 ns=1;i=10485 EURange i=68 ns=1;i=10590 DoubleValue ns=1;i=10599 i=2368 ns=1;i=10485 EURange i=68 ns=1;i=10596 NumberValue ns=1;i=10605 i=2368 ns=1;i=10485 EURange i=68 ns=1;i=10602 IntegerValue ns=1;i=10611 i=2368 ns=1;i=10485 EURange i=68 ns=1;i=10608 UIntegerValue ns=1;i=10617 i=2368 ns=1;i=10485 EURange i=68 ns=1;i=10614 AnalogArray ns=1;i=10621 ns=1;i=10622 ns=1;i=10624 ns=1;i=10677 ns=1;i=10683 ns=1;i=10689 ns=1;i=10695 ns=1;i=10701 ns=1;i=10707 ns=1;i=10713 ns=1;i=10719 ns=1;i=10725 ns=1;i=10731 ns=1;i=10737 ns=1;i=10743 ns=1;i=10749 ns=1;i=10624 ns=1;i=9763 ns=1;i=10158 SimulationActive If true the server will produce new values for each monitored variable. i=68 ns=1;i=10620 GenerateValues ns=1;i=10623 ns=1;i=10620 InputArguments i=68 ns=1;i=10622 i=297 Iterations i=7 -1 The number of new values to generate. CycleComplete ns=1;i=10625 ns=1;i=10626 ns=1;i=10627 ns=1;i=10628 ns=1;i=10629 ns=1;i=10630 ns=1;i=10632 ns=1;i=10633 ns=1;i=11604 ns=1;i=11605 ns=1;i=11570 ns=1;i=10634 ns=1;i=10635 ns=1;i=10636 ns=1;i=10642 ns=1;i=10646 ns=1;i=10648 ns=1;i=10650 ns=1;i=10652 ns=1;i=10651 ns=1;i=10653 ns=1;i=10657 ns=1;i=10673 ns=1;i=10620 i=2881 ns=1;i=10620 EventId i=68 ns=1;i=10624 EventType i=68 ns=1;i=10624 SourceNode i=68 ns=1;i=10624 SourceName i=68 ns=1;i=10624 Time i=68 ns=1;i=10624 ReceiveTime i=68 ns=1;i=10624 Message i=68 ns=1;i=10624 Severity i=68 ns=1;i=10624 ConditionClassId i=68 ns=1;i=10624 ConditionClassName i=68 ns=1;i=10624 ConditionName i=68 ns=1;i=10624 BranchId i=68 ns=1;i=10624 Retain i=68 ns=1;i=10624 EnabledState ns=1;i=10637 ns=1;i=10657 ns=1;i=10665 i=8995 ns=1;i=10624 Id i=68 ns=1;i=10636 Quality ns=1;i=10643 i=9002 ns=1;i=10624 SourceTimestamp i=68 ns=1;i=10642 LastSeverity ns=1;i=10647 i=9002 ns=1;i=10624 SourceTimestamp i=68 ns=1;i=10646 Comment ns=1;i=10649 i=9002 ns=1;i=10624 SourceTimestamp i=68 ns=1;i=10648 ClientUserId i=68 ns=1;i=10624 Disable i=2803 ns=1;i=10624 Enable i=2803 ns=1;i=10624 AddComment ns=1;i=10654 i=2829 ns=1;i=10624 InputArguments i=68 ns=1;i=10653 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. AckedState ns=1;i=10658 ns=1;i=10636 i=8995 ns=1;i=10624 Id i=68 ns=1;i=10657 Acknowledge ns=1;i=10674 i=8944 ns=1;i=10624 InputArguments i=68 ns=1;i=10673 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. SByteValue ns=1;i=10680 i=2368 ns=1;i=10620 EURange i=68 ns=1;i=10677 ByteValue ns=1;i=10686 i=2368 ns=1;i=10620 EURange i=68 ns=1;i=10683 Int16Value ns=1;i=10692 i=2368 ns=1;i=10620 EURange i=68 ns=1;i=10689 UInt16Value ns=1;i=10698 i=2368 ns=1;i=10620 EURange i=68 ns=1;i=10695 Int32Value ns=1;i=10704 i=2368 ns=1;i=10620 EURange i=68 ns=1;i=10701 UInt32Value ns=1;i=10710 i=2368 ns=1;i=10620 EURange i=68 ns=1;i=10707 Int64Value ns=1;i=10716 i=2368 ns=1;i=10620 EURange i=68 ns=1;i=10713 UInt64Value ns=1;i=10722 i=2368 ns=1;i=10620 EURange i=68 ns=1;i=10719 FloatValue ns=1;i=10728 i=2368 ns=1;i=10620 EURange i=68 ns=1;i=10725 DoubleValue ns=1;i=10734 i=2368 ns=1;i=10620 EURange i=68 ns=1;i=10731 NumberValue ns=1;i=10740 i=2368 ns=1;i=10620 EURange i=68 ns=1;i=10737 IntegerValue ns=1;i=10746 i=2368 ns=1;i=10620 EURange i=68 ns=1;i=10743 UIntegerValue ns=1;i=10752 i=2368 ns=1;i=10620 EURange i=68 ns=1;i=10749 MethodTest ns=1;i=10756 ns=1;i=10759 ns=1;i=10762 ns=1;i=10765 ns=1;i=10768 ns=1;i=10771 ns=1;i=10774 ns=1;i=10777 ns=1;i=10780 ns=1;i=10783 ns=1;i=10092 ns=1;i=10158 ScalarMethod1 ns=1;i=10757 ns=1;i=10758 ns=1;i=10755 InputArguments i=68 ns=1;i=10756 i=297 BooleanIn i=1 -1 i=297 SByteIn i=2 -1 i=297 ByteIn i=3 -1 i=297 Int16In i=4 -1 i=297 UInt16In i=5 -1 i=297 Int32In i=6 -1 i=297 UInt32In i=7 -1 i=297 Int64In i=8 -1 i=297 UInt64In i=9 -1 i=297 FloatIn i=10 -1 i=297 DoubleIn i=11 -1 OutputArguments i=68 ns=1;i=10756 i=297 BooleanOut i=1 -1 i=297 SByteOut i=2 -1 i=297 ByteOut i=3 -1 i=297 Int16Out i=4 -1 i=297 UInt16Out i=5 -1 i=297 Int32Out i=6 -1 i=297 UInt32Out i=7 -1 i=297 Int64Out i=8 -1 i=297 UInt64Out i=9 -1 i=297 FloatOut i=10 -1 i=297 DoubleOut i=11 -1 ScalarMethod2 ns=1;i=10760 ns=1;i=10761 ns=1;i=10755 InputArguments i=68 ns=1;i=10759 i=297 StringIn i=12 -1 i=297 DateTimeIn i=13 -1 i=297 GuidIn i=14 -1 i=297 ByteStringIn i=15 -1 i=297 XmlElementIn i=16 -1 i=297 NodeIdIn i=17 -1 i=297 ExpandedNodeIdIn i=18 -1 i=297 QualifiedNameIn i=20 -1 i=297 LocalizedTextIn i=21 -1 i=297 StatusCodeIn i=19 -1 OutputArguments i=68 ns=1;i=10759 i=297 StringOut i=12 -1 i=297 DateTimeOut i=13 -1 i=297 GuidOut i=14 -1 i=297 ByteStringOut i=15 -1 i=297 XmlElementOut i=16 -1 i=297 NodeIdOut i=17 -1 i=297 ExpandedNodeIdOut i=18 -1 i=297 QualifiedNameOut i=20 -1 i=297 LocalizedTextOut i=21 -1 i=297 StatusCodeOut i=19 -1 ScalarMethod3 ns=1;i=10763 ns=1;i=10764 ns=1;i=10755 InputArguments i=68 ns=1;i=10762 i=297 VariantIn i=24 -1 i=297 EnumerationIn i=29 -1 i=297 StructureIn i=22 -1 OutputArguments i=68 ns=1;i=10762 i=297 VariantOut i=24 -1 i=297 EnumerationOut i=29 -1 i=297 StructureOut i=22 -1 ArrayMethod1 ns=1;i=10766 ns=1;i=10767 ns=1;i=10755 InputArguments i=68 ns=1;i=10765 i=297 BooleanIn i=1 1 0 i=297 SByteIn i=2 1 0 i=297 ByteIn i=3 1 0 i=297 Int16In i=4 1 0 i=297 UInt16In i=5 1 0 i=297 Int32In i=6 1 0 i=297 UInt32In i=7 1 0 i=297 Int64In i=8 1 0 i=297 UInt64In i=9 1 0 i=297 FloatIn i=10 1 0 i=297 DoubleIn i=11 1 0 OutputArguments i=68 ns=1;i=10765 i=297 BooleanOut i=1 1 0 i=297 SByteOut i=2 1 0 i=297 ByteOut i=3 1 0 i=297 Int16Out i=4 1 0 i=297 UInt16Out i=5 1 0 i=297 Int32Out i=6 1 0 i=297 UInt32Out i=7 1 0 i=297 Int64Out i=8 1 0 i=297 UInt64Out i=9 1 0 i=297 FloatOut i=10 1 0 i=297 DoubleOut i=11 1 0 ArrayMethod2 ns=1;i=10769 ns=1;i=10770 ns=1;i=10755 InputArguments i=68 ns=1;i=10768 i=297 StringIn i=12 1 0 i=297 DateTimeIn i=13 1 0 i=297 GuidIn i=14 1 0 i=297 ByteStringIn i=15 1 0 i=297 XmlElementIn i=16 1 0 i=297 NodeIdIn i=17 1 0 i=297 ExpandedNodeIdIn i=18 1 0 i=297 QualifiedNameIn i=20 1 0 i=297 LocalizedTextIn i=21 1 0 i=297 StatusCodeIn i=19 1 0 OutputArguments i=68 ns=1;i=10768 i=297 StringOut i=12 1 0 i=297 DateTimeOut i=13 1 0 i=297 GuidOut i=14 1 0 i=297 ByteStringOut i=15 1 0 i=297 XmlElementOut i=16 1 0 i=297 NodeIdOut i=17 1 0 i=297 ExpandedNodeIdOut i=18 1 0 i=297 QualifiedNameOut i=20 1 0 i=297 LocalizedTextOut i=21 1 0 i=297 StatusCodeOut i=19 1 0 ArrayMethod3 ns=1;i=10772 ns=1;i=10773 ns=1;i=10755 InputArguments i=68 ns=1;i=10771 i=297 VariantIn i=24 1 0 i=297 EnumerationIn i=29 1 0 i=297 StructureIn i=22 1 0 OutputArguments i=68 ns=1;i=10771 i=297 VariantOut i=24 1 0 i=297 EnumerationOut i=29 1 0 i=297 StructureOut i=22 1 0 UserScalarMethod1 ns=1;i=10775 ns=1;i=10776 ns=1;i=10755 InputArguments i=68 ns=1;i=10774 i=297 BooleanIn ns=1;i=9898 -1 i=297 SByteIn ns=1;i=9899 -1 i=297 ByteIn ns=1;i=9900 -1 i=297 Int16In ns=1;i=9901 -1 i=297 UInt16In ns=1;i=9902 -1 i=297 Int32In ns=1;i=9903 -1 i=297 UInt32In ns=1;i=9904 -1 i=297 Int64In ns=1;i=9905 -1 i=297 UInt64In ns=1;i=9906 -1 i=297 FloatIn ns=1;i=9907 -1 i=297 DoubleIn ns=1;i=9908 -1 i=297 StringIn ns=1;i=9909 -1 OutputArguments i=68 ns=1;i=10774 i=297 BooleanOut ns=1;i=9898 -1 i=297 SByteOut ns=1;i=9899 -1 i=297 ByteOut ns=1;i=9900 -1 i=297 Int16Out ns=1;i=9901 -1 i=297 UInt16Out ns=1;i=9902 -1 i=297 Int32Out ns=1;i=9903 -1 i=297 UInt32Out ns=1;i=9904 -1 i=297 Int64Out ns=1;i=9905 -1 i=297 UInt64Out ns=1;i=9906 -1 i=297 FloatOut ns=1;i=9907 -1 i=297 DoubleOut ns=1;i=9908 -1 i=297 StringOut ns=1;i=9909 -1 UserScalarMethod2 ns=1;i=10778 ns=1;i=10779 ns=1;i=10755 InputArguments i=68 ns=1;i=10777 i=297 DateTimeIn ns=1;i=9910 -1 i=297 GuidIn ns=1;i=9911 -1 i=297 ByteStringIn ns=1;i=9912 -1 i=297 XmlElementIn ns=1;i=9913 -1 i=297 NodeIdIn ns=1;i=9914 -1 i=297 ExpandedNodeIdIn ns=1;i=9915 -1 i=297 QualifiedNameIn ns=1;i=9916 -1 i=297 LocalizedTextIn ns=1;i=9917 -1 i=297 StatusCodeIn ns=1;i=9918 -1 i=297 VariantIn ns=1;i=9919 -1 OutputArguments i=68 ns=1;i=10777 i=297 DateTimeOut ns=1;i=9910 -1 i=297 GuidOut ns=1;i=9911 -1 i=297 ByteStringOut ns=1;i=9912 -1 i=297 XmlElementOut ns=1;i=9913 -1 i=297 NodeIdOut ns=1;i=9914 -1 i=297 ExpandedNodeIdOut ns=1;i=9915 -1 i=297 QualifiedNameOut ns=1;i=9916 -1 i=297 LocalizedTextOut ns=1;i=9917 -1 i=297 StatusCodeOut ns=1;i=9918 -1 i=297 VariantOut ns=1;i=9919 -1 UserArrayMethod1 ns=1;i=10781 ns=1;i=10782 ns=1;i=10755 InputArguments i=68 ns=1;i=10780 i=297 BooleanIn ns=1;i=9898 1 0 i=297 SByteIn ns=1;i=9899 1 0 i=297 ByteIn ns=1;i=9900 1 0 i=297 Int16In ns=1;i=9901 1 0 i=297 UInt16In ns=1;i=9902 1 0 i=297 Int32In ns=1;i=9903 1 0 i=297 UInt32In ns=1;i=9904 1 0 i=297 Int64In ns=1;i=9905 1 0 i=297 UInt64In ns=1;i=9906 1 0 i=297 FloatIn ns=1;i=9907 1 0 i=297 DoubleIn ns=1;i=9908 1 0 i=297 StringIn ns=1;i=9909 1 0 OutputArguments i=68 ns=1;i=10780 i=297 BooleanOut ns=1;i=9898 1 0 i=297 SByteOut ns=1;i=9899 1 0 i=297 ByteOut ns=1;i=9900 1 0 i=297 Int16Out ns=1;i=9901 1 0 i=297 UInt16Out ns=1;i=9902 1 0 i=297 Int32Out ns=1;i=9903 1 0 i=297 UInt32Out ns=1;i=9904 1 0 i=297 Int64Out ns=1;i=9905 1 0 i=297 UInt64Out ns=1;i=9906 1 0 i=297 FloatOut ns=1;i=9907 1 0 i=297 DoubleOut ns=1;i=9908 1 0 i=297 StringOut ns=1;i=9909 1 0 UserArrayMethod2 ns=1;i=10784 ns=1;i=10785 ns=1;i=10755 InputArguments i=68 ns=1;i=10783 i=297 DateTimeIn ns=1;i=9910 1 0 i=297 GuidIn ns=1;i=9911 1 0 i=297 ByteStringIn ns=1;i=9912 1 0 i=297 XmlElementIn ns=1;i=9913 1 0 i=297 NodeIdIn ns=1;i=9914 1 0 i=297 ExpandedNodeIdIn ns=1;i=9915 1 0 i=297 QualifiedNameIn ns=1;i=9916 1 0 i=297 LocalizedTextIn ns=1;i=9917 1 0 i=297 StatusCodeIn ns=1;i=9918 1 0 i=297 VariantIn ns=1;i=9919 1 0 OutputArguments i=68 ns=1;i=10783 i=297 DateTimeOut ns=1;i=9910 1 0 i=297 GuidOut ns=1;i=9911 1 0 i=297 ByteStringOut ns=1;i=9912 1 0 i=297 XmlElementOut ns=1;i=9913 1 0 i=297 NodeIdOut ns=1;i=9914 1 0 i=297 ExpandedNodeIdOut ns=1;i=9915 1 0 i=297 QualifiedNameOut ns=1;i=9916 1 0 i=297 LocalizedTextOut ns=1;i=9917 1 0 i=297 StatusCodeOut ns=1;i=9918 1 0 i=297 VariantOut ns=1;i=9919 1 0 Dynamic ns=1;i=10787 ns=1;i=10871 ns=1;i=10955 ns=1;i=11034 ns=1;i=11113 ns=1;i=11248 ns=1;i=10157 ns=1;i=10787 ns=1;i=10871 i=61 ns=1;i=10157 Scalar ns=1;i=10788 ns=1;i=10789 ns=1;i=10791 ns=1;i=10844 ns=1;i=10845 ns=1;i=10846 ns=1;i=10847 ns=1;i=10848 ns=1;i=10849 ns=1;i=10850 ns=1;i=10851 ns=1;i=10852 ns=1;i=10853 ns=1;i=10854 ns=1;i=10855 ns=1;i=10856 ns=1;i=10857 ns=1;i=10858 ns=1;i=10859 ns=1;i=10860 ns=1;i=10861 ns=1;i=10862 ns=1;i=10863 ns=1;i=10864 ns=1;i=10865 ns=1;i=10866 ns=1;i=10867 ns=1;i=10868 ns=1;i=10869 ns=1;i=10870 ns=1;i=10786 ns=1;i=10791 ns=1;i=9450 ns=1;i=10786 SimulationActive If true the server will produce new values for each monitored variable. i=68 ns=1;i=10787 true GenerateValues ns=1;i=10790 ns=1;i=10787 InputArguments i=68 ns=1;i=10789 i=297 Iterations i=7 -1 The number of new values to generate. CycleComplete ns=1;i=10792 ns=1;i=10793 ns=1;i=10794 ns=1;i=10795 ns=1;i=10796 ns=1;i=10797 ns=1;i=10799 ns=1;i=10800 ns=1;i=11606 ns=1;i=11607 ns=1;i=11571 ns=1;i=10801 ns=1;i=10802 ns=1;i=10803 ns=1;i=10809 ns=1;i=10813 ns=1;i=10815 ns=1;i=10817 ns=1;i=10819 ns=1;i=10818 ns=1;i=10820 ns=1;i=10824 ns=1;i=10840 ns=1;i=10787 i=2881 ns=1;i=10787 EventId i=68 ns=1;i=10791 EventType i=68 ns=1;i=10791 SourceNode i=68 ns=1;i=10791 SourceName i=68 ns=1;i=10791 Time i=68 ns=1;i=10791 ReceiveTime i=68 ns=1;i=10791 Message i=68 ns=1;i=10791 Severity i=68 ns=1;i=10791 ConditionClassId i=68 ns=1;i=10791 ConditionClassName i=68 ns=1;i=10791 ConditionName i=68 ns=1;i=10791 BranchId i=68 ns=1;i=10791 Retain i=68 ns=1;i=10791 EnabledState ns=1;i=10804 ns=1;i=10824 ns=1;i=10832 i=8995 ns=1;i=10791 Id i=68 ns=1;i=10803 Quality ns=1;i=10810 i=9002 ns=1;i=10791 SourceTimestamp i=68 ns=1;i=10809 LastSeverity ns=1;i=10814 i=9002 ns=1;i=10791 SourceTimestamp i=68 ns=1;i=10813 Comment ns=1;i=10816 i=9002 ns=1;i=10791 SourceTimestamp i=68 ns=1;i=10815 ClientUserId i=68 ns=1;i=10791 Disable i=2803 ns=1;i=10791 Enable i=2803 ns=1;i=10791 AddComment ns=1;i=10821 i=2829 ns=1;i=10791 InputArguments i=68 ns=1;i=10820 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. AckedState ns=1;i=10825 ns=1;i=10803 i=8995 ns=1;i=10791 Id i=68 ns=1;i=10824 Acknowledge ns=1;i=10841 i=8944 ns=1;i=10791 InputArguments i=68 ns=1;i=10840 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. BooleanValue i=63 ns=1;i=10787 SByteValue i=63 ns=1;i=10787 ByteValue i=63 ns=1;i=10787 Int16Value i=63 ns=1;i=10787 UInt16Value i=63 ns=1;i=10787 Int32Value i=63 ns=1;i=10787 UInt32Value i=63 ns=1;i=10787 Int64Value i=63 ns=1;i=10787 UInt64Value i=63 ns=1;i=10787 FloatValue i=63 ns=1;i=10787 DoubleValue i=63 ns=1;i=10787 StringValue i=63 ns=1;i=10787 DateTimeValue i=63 ns=1;i=10787 GuidValue i=63 ns=1;i=10787 ByteStringValue i=63 ns=1;i=10787 XmlElementValue i=63 ns=1;i=10787 NodeIdValue i=63 ns=1;i=10787 ExpandedNodeIdValue i=63 ns=1;i=10787 QualifiedNameValue i=63 ns=1;i=10787 LocalizedTextValue i=63 ns=1;i=10787 StatusCodeValue i=63 ns=1;i=10787 VariantValue i=63 ns=1;i=10787 EnumerationValue i=63 ns=1;i=10787 StructureValue i=63 ns=1;i=10787 NumberValue i=63 ns=1;i=10787 IntegerValue i=63 ns=1;i=10787 UIntegerValue i=63 ns=1;i=10787 Array ns=1;i=10872 ns=1;i=10873 ns=1;i=10875 ns=1;i=10928 ns=1;i=10929 ns=1;i=10930 ns=1;i=10931 ns=1;i=10932 ns=1;i=10933 ns=1;i=10934 ns=1;i=10935 ns=1;i=10936 ns=1;i=10937 ns=1;i=10938 ns=1;i=10939 ns=1;i=10940 ns=1;i=10941 ns=1;i=10942 ns=1;i=10943 ns=1;i=10944 ns=1;i=10945 ns=1;i=10946 ns=1;i=10947 ns=1;i=10948 ns=1;i=10949 ns=1;i=10950 ns=1;i=10951 ns=1;i=10952 ns=1;i=10953 ns=1;i=10954 ns=1;i=10786 ns=1;i=10875 ns=1;i=9679 ns=1;i=10786 SimulationActive If true the server will produce new values for each monitored variable. i=68 ns=1;i=10871 true GenerateValues ns=1;i=10874 ns=1;i=10871 InputArguments i=68 ns=1;i=10873 i=297 Iterations i=7 -1 The number of new values to generate. CycleComplete ns=1;i=10876 ns=1;i=10877 ns=1;i=10878 ns=1;i=10879 ns=1;i=10880 ns=1;i=10881 ns=1;i=10883 ns=1;i=10884 ns=1;i=11608 ns=1;i=11609 ns=1;i=11572 ns=1;i=10885 ns=1;i=10886 ns=1;i=10887 ns=1;i=10893 ns=1;i=10897 ns=1;i=10899 ns=1;i=10901 ns=1;i=10903 ns=1;i=10902 ns=1;i=10904 ns=1;i=10908 ns=1;i=10924 ns=1;i=10871 i=2881 ns=1;i=10871 EventId i=68 ns=1;i=10875 EventType i=68 ns=1;i=10875 SourceNode i=68 ns=1;i=10875 SourceName i=68 ns=1;i=10875 Time i=68 ns=1;i=10875 ReceiveTime i=68 ns=1;i=10875 Message i=68 ns=1;i=10875 Severity i=68 ns=1;i=10875 ConditionClassId i=68 ns=1;i=10875 ConditionClassName i=68 ns=1;i=10875 ConditionName i=68 ns=1;i=10875 BranchId i=68 ns=1;i=10875 Retain i=68 ns=1;i=10875 EnabledState ns=1;i=10888 ns=1;i=10908 ns=1;i=10916 i=8995 ns=1;i=10875 Id i=68 ns=1;i=10887 Quality ns=1;i=10894 i=9002 ns=1;i=10875 SourceTimestamp i=68 ns=1;i=10893 LastSeverity ns=1;i=10898 i=9002 ns=1;i=10875 SourceTimestamp i=68 ns=1;i=10897 Comment ns=1;i=10900 i=9002 ns=1;i=10875 SourceTimestamp i=68 ns=1;i=10899 ClientUserId i=68 ns=1;i=10875 Disable i=2803 ns=1;i=10875 Enable i=2803 ns=1;i=10875 AddComment ns=1;i=10905 i=2829 ns=1;i=10875 InputArguments i=68 ns=1;i=10904 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. AckedState ns=1;i=10909 ns=1;i=10887 i=8995 ns=1;i=10875 Id i=68 ns=1;i=10908 Acknowledge ns=1;i=10925 i=8944 ns=1;i=10875 InputArguments i=68 ns=1;i=10924 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. BooleanValue i=63 ns=1;i=10871 SByteValue i=63 ns=1;i=10871 ByteValue i=63 ns=1;i=10871 Int16Value i=63 ns=1;i=10871 UInt16Value i=63 ns=1;i=10871 Int32Value i=63 ns=1;i=10871 UInt32Value i=63 ns=1;i=10871 Int64Value i=63 ns=1;i=10871 UInt64Value i=63 ns=1;i=10871 FloatValue i=63 ns=1;i=10871 DoubleValue i=63 ns=1;i=10871 StringValue i=63 ns=1;i=10871 DateTimeValue i=63 ns=1;i=10871 GuidValue i=63 ns=1;i=10871 ByteStringValue i=63 ns=1;i=10871 XmlElementValue i=63 ns=1;i=10871 NodeIdValue i=63 ns=1;i=10871 ExpandedNodeIdValue i=63 ns=1;i=10871 QualifiedNameValue i=63 ns=1;i=10871 LocalizedTextValue i=63 ns=1;i=10871 StatusCodeValue i=63 ns=1;i=10871 VariantValue i=63 ns=1;i=10871 EnumerationValue i=63 ns=1;i=10871 StructureValue i=63 ns=1;i=10871 NumberValue i=63 ns=1;i=10871 IntegerValue i=63 ns=1;i=10871 UIntegerValue i=63 ns=1;i=10871 UserScalar ns=1;i=10956 ns=1;i=10957 ns=1;i=10959 ns=1;i=11012 ns=1;i=11013 ns=1;i=11014 ns=1;i=11015 ns=1;i=11016 ns=1;i=11017 ns=1;i=11018 ns=1;i=11019 ns=1;i=11020 ns=1;i=11021 ns=1;i=11022 ns=1;i=11023 ns=1;i=11024 ns=1;i=11025 ns=1;i=11026 ns=1;i=11027 ns=1;i=11028 ns=1;i=11029 ns=1;i=11030 ns=1;i=11031 ns=1;i=11032 ns=1;i=11033 ns=1;i=10959 ns=1;i=9921 ns=1;i=10786 SimulationActive If true the server will produce new values for each monitored variable. i=68 ns=1;i=10955 true GenerateValues ns=1;i=10958 ns=1;i=10955 InputArguments i=68 ns=1;i=10957 i=297 Iterations i=7 -1 The number of new values to generate. CycleComplete ns=1;i=10960 ns=1;i=10961 ns=1;i=10962 ns=1;i=10963 ns=1;i=10964 ns=1;i=10965 ns=1;i=10967 ns=1;i=10968 ns=1;i=11610 ns=1;i=11611 ns=1;i=11573 ns=1;i=10969 ns=1;i=10970 ns=1;i=10971 ns=1;i=10977 ns=1;i=10981 ns=1;i=10983 ns=1;i=10985 ns=1;i=10987 ns=1;i=10986 ns=1;i=10988 ns=1;i=10992 ns=1;i=11008 ns=1;i=10955 i=2881 ns=1;i=10955 EventId i=68 ns=1;i=10959 EventType i=68 ns=1;i=10959 SourceNode i=68 ns=1;i=10959 SourceName i=68 ns=1;i=10959 Time i=68 ns=1;i=10959 ReceiveTime i=68 ns=1;i=10959 Message i=68 ns=1;i=10959 Severity i=68 ns=1;i=10959 ConditionClassId i=68 ns=1;i=10959 ConditionClassName i=68 ns=1;i=10959 ConditionName i=68 ns=1;i=10959 BranchId i=68 ns=1;i=10959 Retain i=68 ns=1;i=10959 EnabledState ns=1;i=10972 ns=1;i=10992 ns=1;i=11000 i=8995 ns=1;i=10959 Id i=68 ns=1;i=10971 Quality ns=1;i=10978 i=9002 ns=1;i=10959 SourceTimestamp i=68 ns=1;i=10977 LastSeverity ns=1;i=10982 i=9002 ns=1;i=10959 SourceTimestamp i=68 ns=1;i=10981 Comment ns=1;i=10984 i=9002 ns=1;i=10959 SourceTimestamp i=68 ns=1;i=10983 ClientUserId i=68 ns=1;i=10959 Disable i=2803 ns=1;i=10959 Enable i=2803 ns=1;i=10959 AddComment ns=1;i=10989 i=2829 ns=1;i=10959 InputArguments i=68 ns=1;i=10988 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. AckedState ns=1;i=10993 ns=1;i=10971 i=8995 ns=1;i=10959 Id i=68 ns=1;i=10992 Acknowledge ns=1;i=11009 i=8944 ns=1;i=10959 InputArguments i=68 ns=1;i=11008 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. BooleanValue i=63 ns=1;i=10955 SByteValue i=63 ns=1;i=10955 ByteValue i=63 ns=1;i=10955 Int16Value i=63 ns=1;i=10955 UInt16Value i=63 ns=1;i=10955 Int32Value i=63 ns=1;i=10955 UInt32Value i=63 ns=1;i=10955 Int64Value i=63 ns=1;i=10955 UInt64Value i=63 ns=1;i=10955 FloatValue i=63 ns=1;i=10955 DoubleValue i=63 ns=1;i=10955 StringValue i=63 ns=1;i=10955 DateTimeValue i=63 ns=1;i=10955 GuidValue i=63 ns=1;i=10955 ByteStringValue i=63 ns=1;i=10955 XmlElementValue i=63 ns=1;i=10955 NodeIdValue i=63 ns=1;i=10955 ExpandedNodeIdValue i=63 ns=1;i=10955 QualifiedNameValue i=63 ns=1;i=10955 LocalizedTextValue i=63 ns=1;i=10955 StatusCodeValue i=63 ns=1;i=10955 VariantValue i=63 ns=1;i=10955 UserArray ns=1;i=11035 ns=1;i=11036 ns=1;i=11038 ns=1;i=11091 ns=1;i=11092 ns=1;i=11093 ns=1;i=11094 ns=1;i=11095 ns=1;i=11096 ns=1;i=11097 ns=1;i=11098 ns=1;i=11099 ns=1;i=11100 ns=1;i=11101 ns=1;i=11102 ns=1;i=11103 ns=1;i=11104 ns=1;i=11105 ns=1;i=11106 ns=1;i=11107 ns=1;i=11108 ns=1;i=11109 ns=1;i=11110 ns=1;i=11111 ns=1;i=11112 ns=1;i=11038 ns=1;i=10007 ns=1;i=10786 SimulationActive If true the server will produce new values for each monitored variable. i=68 ns=1;i=11034 true GenerateValues ns=1;i=11037 ns=1;i=11034 InputArguments i=68 ns=1;i=11036 i=297 Iterations i=7 -1 The number of new values to generate. CycleComplete ns=1;i=11039 ns=1;i=11040 ns=1;i=11041 ns=1;i=11042 ns=1;i=11043 ns=1;i=11044 ns=1;i=11046 ns=1;i=11047 ns=1;i=11612 ns=1;i=11613 ns=1;i=11574 ns=1;i=11048 ns=1;i=11049 ns=1;i=11050 ns=1;i=11056 ns=1;i=11060 ns=1;i=11062 ns=1;i=11064 ns=1;i=11066 ns=1;i=11065 ns=1;i=11067 ns=1;i=11071 ns=1;i=11087 ns=1;i=11034 i=2881 ns=1;i=11034 EventId i=68 ns=1;i=11038 EventType i=68 ns=1;i=11038 SourceNode i=68 ns=1;i=11038 SourceName i=68 ns=1;i=11038 Time i=68 ns=1;i=11038 ReceiveTime i=68 ns=1;i=11038 Message i=68 ns=1;i=11038 Severity i=68 ns=1;i=11038 ConditionClassId i=68 ns=1;i=11038 ConditionClassName i=68 ns=1;i=11038 ConditionName i=68 ns=1;i=11038 BranchId i=68 ns=1;i=11038 Retain i=68 ns=1;i=11038 EnabledState ns=1;i=11051 ns=1;i=11071 ns=1;i=11079 i=8995 ns=1;i=11038 Id i=68 ns=1;i=11050 Quality ns=1;i=11057 i=9002 ns=1;i=11038 SourceTimestamp i=68 ns=1;i=11056 LastSeverity ns=1;i=11061 i=9002 ns=1;i=11038 SourceTimestamp i=68 ns=1;i=11060 Comment ns=1;i=11063 i=9002 ns=1;i=11038 SourceTimestamp i=68 ns=1;i=11062 ClientUserId i=68 ns=1;i=11038 Disable i=2803 ns=1;i=11038 Enable i=2803 ns=1;i=11038 AddComment ns=1;i=11068 i=2829 ns=1;i=11038 InputArguments i=68 ns=1;i=11067 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. AckedState ns=1;i=11072 ns=1;i=11050 i=8995 ns=1;i=11038 Id i=68 ns=1;i=11071 Acknowledge ns=1;i=11088 i=8944 ns=1;i=11038 InputArguments i=68 ns=1;i=11087 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. BooleanValue i=63 ns=1;i=11034 SByteValue i=63 ns=1;i=11034 ByteValue i=63 ns=1;i=11034 Int16Value i=63 ns=1;i=11034 UInt16Value i=63 ns=1;i=11034 Int32Value i=63 ns=1;i=11034 UInt32Value i=63 ns=1;i=11034 Int64Value i=63 ns=1;i=11034 UInt64Value i=63 ns=1;i=11034 FloatValue i=63 ns=1;i=11034 DoubleValue i=63 ns=1;i=11034 StringValue i=63 ns=1;i=11034 DateTimeValue i=63 ns=1;i=11034 GuidValue i=63 ns=1;i=11034 ByteStringValue i=63 ns=1;i=11034 XmlElementValue i=63 ns=1;i=11034 NodeIdValue i=63 ns=1;i=11034 ExpandedNodeIdValue i=63 ns=1;i=11034 QualifiedNameValue i=63 ns=1;i=11034 LocalizedTextValue i=63 ns=1;i=11034 StatusCodeValue i=63 ns=1;i=11034 VariantValue i=63 ns=1;i=11034 AnalogScalar ns=1;i=11114 ns=1;i=11115 ns=1;i=11117 ns=1;i=11170 ns=1;i=11176 ns=1;i=11182 ns=1;i=11188 ns=1;i=11194 ns=1;i=11200 ns=1;i=11206 ns=1;i=11212 ns=1;i=11218 ns=1;i=11224 ns=1;i=11230 ns=1;i=11236 ns=1;i=11242 ns=1;i=11117 ns=1;i=9534 ns=1;i=10786 SimulationActive If true the server will produce new values for each monitored variable. i=68 ns=1;i=11113 true GenerateValues ns=1;i=11116 ns=1;i=11113 InputArguments i=68 ns=1;i=11115 i=297 Iterations i=7 -1 The number of new values to generate. CycleComplete ns=1;i=11118 ns=1;i=11119 ns=1;i=11120 ns=1;i=11121 ns=1;i=11122 ns=1;i=11123 ns=1;i=11125 ns=1;i=11126 ns=1;i=11614 ns=1;i=11615 ns=1;i=11575 ns=1;i=11127 ns=1;i=11128 ns=1;i=11129 ns=1;i=11135 ns=1;i=11139 ns=1;i=11141 ns=1;i=11143 ns=1;i=11145 ns=1;i=11144 ns=1;i=11146 ns=1;i=11150 ns=1;i=11166 ns=1;i=11113 i=2881 ns=1;i=11113 EventId i=68 ns=1;i=11117 EventType i=68 ns=1;i=11117 SourceNode i=68 ns=1;i=11117 SourceName i=68 ns=1;i=11117 Time i=68 ns=1;i=11117 ReceiveTime i=68 ns=1;i=11117 Message i=68 ns=1;i=11117 Severity i=68 ns=1;i=11117 ConditionClassId i=68 ns=1;i=11117 ConditionClassName i=68 ns=1;i=11117 ConditionName i=68 ns=1;i=11117 BranchId i=68 ns=1;i=11117 Retain i=68 ns=1;i=11117 EnabledState ns=1;i=11130 ns=1;i=11150 ns=1;i=11158 i=8995 ns=1;i=11117 Id i=68 ns=1;i=11129 Quality ns=1;i=11136 i=9002 ns=1;i=11117 SourceTimestamp i=68 ns=1;i=11135 LastSeverity ns=1;i=11140 i=9002 ns=1;i=11117 SourceTimestamp i=68 ns=1;i=11139 Comment ns=1;i=11142 i=9002 ns=1;i=11117 SourceTimestamp i=68 ns=1;i=11141 ClientUserId i=68 ns=1;i=11117 Disable i=2803 ns=1;i=11117 Enable i=2803 ns=1;i=11117 AddComment ns=1;i=11147 i=2829 ns=1;i=11117 InputArguments i=68 ns=1;i=11146 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. AckedState ns=1;i=11151 ns=1;i=11129 i=8995 ns=1;i=11117 Id i=68 ns=1;i=11150 Acknowledge ns=1;i=11167 i=8944 ns=1;i=11117 InputArguments i=68 ns=1;i=11166 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. SByteValue ns=1;i=11173 i=2368 ns=1;i=11113 EURange i=68 ns=1;i=11170 ByteValue ns=1;i=11179 i=2368 ns=1;i=11113 EURange i=68 ns=1;i=11176 Int16Value ns=1;i=11185 i=2368 ns=1;i=11113 EURange i=68 ns=1;i=11182 UInt16Value ns=1;i=11191 i=2368 ns=1;i=11113 EURange i=68 ns=1;i=11188 Int32Value ns=1;i=11197 i=2368 ns=1;i=11113 EURange i=68 ns=1;i=11194 UInt32Value ns=1;i=11203 i=2368 ns=1;i=11113 EURange i=68 ns=1;i=11200 Int64Value ns=1;i=11209 i=2368 ns=1;i=11113 EURange i=68 ns=1;i=11206 UInt64Value ns=1;i=11215 i=2368 ns=1;i=11113 EURange i=68 ns=1;i=11212 FloatValue ns=1;i=11221 i=2368 ns=1;i=11113 EURange i=68 ns=1;i=11218 DoubleValue ns=1;i=11227 i=2368 ns=1;i=11113 EURange i=68 ns=1;i=11224 NumberValue ns=1;i=11233 i=2368 ns=1;i=11113 EURange i=68 ns=1;i=11230 IntegerValue ns=1;i=11239 i=2368 ns=1;i=11113 EURange i=68 ns=1;i=11236 UIntegerValue ns=1;i=11245 i=2368 ns=1;i=11113 EURange i=68 ns=1;i=11242 AnalogArray ns=1;i=11249 ns=1;i=11250 ns=1;i=11252 ns=1;i=11305 ns=1;i=11311 ns=1;i=11317 ns=1;i=11323 ns=1;i=11329 ns=1;i=11335 ns=1;i=11341 ns=1;i=11347 ns=1;i=11353 ns=1;i=11359 ns=1;i=11365 ns=1;i=11371 ns=1;i=11377 ns=1;i=11252 ns=1;i=9763 ns=1;i=10786 SimulationActive If true the server will produce new values for each monitored variable. i=68 ns=1;i=11248 true GenerateValues ns=1;i=11251 ns=1;i=11248 InputArguments i=68 ns=1;i=11250 i=297 Iterations i=7 -1 The number of new values to generate. CycleComplete ns=1;i=11253 ns=1;i=11254 ns=1;i=11255 ns=1;i=11256 ns=1;i=11257 ns=1;i=11258 ns=1;i=11260 ns=1;i=11261 ns=1;i=11616 ns=1;i=11617 ns=1;i=11576 ns=1;i=11262 ns=1;i=11263 ns=1;i=11264 ns=1;i=11270 ns=1;i=11274 ns=1;i=11276 ns=1;i=11278 ns=1;i=11280 ns=1;i=11279 ns=1;i=11281 ns=1;i=11285 ns=1;i=11301 ns=1;i=11248 i=2881 ns=1;i=11248 EventId i=68 ns=1;i=11252 EventType i=68 ns=1;i=11252 SourceNode i=68 ns=1;i=11252 SourceName i=68 ns=1;i=11252 Time i=68 ns=1;i=11252 ReceiveTime i=68 ns=1;i=11252 Message i=68 ns=1;i=11252 Severity i=68 ns=1;i=11252 ConditionClassId i=68 ns=1;i=11252 ConditionClassName i=68 ns=1;i=11252 ConditionName i=68 ns=1;i=11252 BranchId i=68 ns=1;i=11252 Retain i=68 ns=1;i=11252 EnabledState ns=1;i=11265 ns=1;i=11285 ns=1;i=11293 i=8995 ns=1;i=11252 Id i=68 ns=1;i=11264 Quality ns=1;i=11271 i=9002 ns=1;i=11252 SourceTimestamp i=68 ns=1;i=11270 LastSeverity ns=1;i=11275 i=9002 ns=1;i=11252 SourceTimestamp i=68 ns=1;i=11274 Comment ns=1;i=11277 i=9002 ns=1;i=11252 SourceTimestamp i=68 ns=1;i=11276 ClientUserId i=68 ns=1;i=11252 Disable i=2803 ns=1;i=11252 Enable i=2803 ns=1;i=11252 AddComment ns=1;i=11282 i=2829 ns=1;i=11252 InputArguments i=68 ns=1;i=11281 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. AckedState ns=1;i=11286 ns=1;i=11264 i=8995 ns=1;i=11252 Id i=68 ns=1;i=11285 Acknowledge ns=1;i=11302 i=8944 ns=1;i=11252 InputArguments i=68 ns=1;i=11301 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. SByteValue ns=1;i=11308 i=2368 ns=1;i=11248 EURange i=68 ns=1;i=11305 ByteValue ns=1;i=11314 i=2368 ns=1;i=11248 EURange i=68 ns=1;i=11311 Int16Value ns=1;i=11320 i=2368 ns=1;i=11248 EURange i=68 ns=1;i=11317 UInt16Value ns=1;i=11326 i=2368 ns=1;i=11248 EURange i=68 ns=1;i=11323 Int32Value ns=1;i=11332 i=2368 ns=1;i=11248 EURange i=68 ns=1;i=11329 UInt32Value ns=1;i=11338 i=2368 ns=1;i=11248 EURange i=68 ns=1;i=11335 Int64Value ns=1;i=11344 i=2368 ns=1;i=11248 EURange i=68 ns=1;i=11341 UInt64Value ns=1;i=11350 i=2368 ns=1;i=11248 EURange i=68 ns=1;i=11347 FloatValue ns=1;i=11356 i=2368 ns=1;i=11248 EURange i=68 ns=1;i=11353 DoubleValue ns=1;i=11362 i=2368 ns=1;i=11248 EURange i=68 ns=1;i=11359 NumberValue ns=1;i=11368 i=2368 ns=1;i=11248 EURange i=68 ns=1;i=11365 IntegerValue ns=1;i=11374 i=2368 ns=1;i=11248 EURange i=68 ns=1;i=11371 UIntegerValue ns=1;i=11380 i=2368 ns=1;i=11248 EURange i=68 ns=1;i=11377 Conditions ns=1;i=11384 ns=1;i=11384 i=61 ns=1;i=10157 SystemStatus ns=1;i=11385 ns=1;i=11386 ns=1;i=11387 ns=1;i=11388 ns=1;i=11389 ns=1;i=11390 ns=1;i=11392 ns=1;i=11393 ns=1;i=11618 ns=1;i=11619 ns=1;i=11577 ns=1;i=11394 ns=1;i=11395 ns=1;i=11396 ns=1;i=11402 ns=1;i=11406 ns=1;i=11408 ns=1;i=11410 ns=1;i=11412 ns=1;i=11411 ns=1;i=11413 ns=1;i=11417 ns=1;i=11383 ns=1;i=10123 ns=1;i=11383 EventId i=68 ns=1;i=11384 EventType i=68 ns=1;i=11384 SourceNode i=68 ns=1;i=11384 SourceName i=68 ns=1;i=11384 Time i=68 ns=1;i=11384 ReceiveTime i=68 ns=1;i=11384 Message i=68 ns=1;i=11384 Severity i=68 ns=1;i=11384 ConditionClassId i=68 ns=1;i=11384 ConditionClassName i=68 ns=1;i=11384 ConditionName i=68 ns=1;i=11384 BranchId i=68 ns=1;i=11384 Retain i=68 ns=1;i=11384 EnabledState ns=1;i=11397 i=8995 ns=1;i=11384 Id i=68 ns=1;i=11396 Quality ns=1;i=11403 i=9002 ns=1;i=11384 SourceTimestamp i=68 ns=1;i=11402 LastSeverity ns=1;i=11407 i=9002 ns=1;i=11384 SourceTimestamp i=68 ns=1;i=11406 Comment ns=1;i=11409 i=9002 ns=1;i=11384 SourceTimestamp i=68 ns=1;i=11408 ClientUserId i=68 ns=1;i=11384 Disable i=2803 ns=1;i=11384 Enable i=2803 ns=1;i=11384 AddComment ns=1;i=11414 i=2829 ns=1;i=11384 InputArguments i=68 ns=1;i=11413 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. MonitoredNodeCount i=68 ns=1;i=11384 Default Binary ns=1;i=9440 ns=1;i=11425 i=76 Default Binary ns=1;i=9669 ns=1;i=11428 i=76 Default Binary ns=1;i=9920 ns=1;i=11431 i=76 Default Binary ns=1;i=10006 ns=1;i=11434 i=76 Default Binary ns=1;i=1000 ns=1;i=1015 i=76 Default Binary ns=1;i=1004 ns=1;i=24 i=76 Default Binary ns=1;i=1005 ns=1;i=27 i=76 TestData ns=1;i=11424 ns=1;i=15045 ns=1;i=11425 ns=1;i=11428 ns=1;i=11431 ns=1;i=11434 ns=1;i=1015 ns=1;i=24 ns=1;i=27 i=93 i=72 PG9wYzpUeXBlRGljdGlvbmFyeQ0KICB4bWxuczpvcGM9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9y Zy9CaW5hcnlTY2hlbWEvIg0KICB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1M U2NoZW1hLWluc3RhbmNlIg0KICB4bWxuczp1YT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VB LyINCiAgeG1sbnM6dG5zPSJodHRwOi8vdGVzdC5vcmcvVUEvRGF0YS8iDQogIERlZmF1bHRCeXRl T3JkZXI9IkxpdHRsZUVuZGlhbiINCiAgVGFyZ2V0TmFtZXNwYWNlPSJodHRwOi8vdGVzdC5vcmcv VUEvRGF0YS8iDQo+DQogIDxvcGM6SW1wb3J0IE5hbWVzcGFjZT0iaHR0cDovL29wY2ZvdW5kYXRp b24ub3JnL1VBLyIgTG9jYXRpb249Ik9wYy5VYS5CaW5hcnlTY2hlbWEuYnNkIi8+DQoNCiAgPG9w YzpTdHJ1Y3R1cmVkVHlwZSBOYW1lPSJTY2FsYXJWYWx1ZURhdGFUeXBlIiBCYXNlVHlwZT0idWE6 RXh0ZW5zaW9uT2JqZWN0Ij4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkJvb2xlYW5WYWx1ZSIgVHlw ZU5hbWU9Im9wYzpCb29sZWFuIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iU0J5dGVWYWx1ZSIg VHlwZU5hbWU9Im9wYzpTQnl0ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkJ5dGVWYWx1ZSIg VHlwZU5hbWU9Im9wYzpCeXRlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iSW50MTZWYWx1ZSIg VHlwZU5hbWU9Im9wYzpJbnQxNiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IlVJbnQxNlZhbHVl IiBUeXBlTmFtZT0ib3BjOlVJbnQxNiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkludDMyVmFs dWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJVSW50MzJW YWx1ZSIgVHlwZU5hbWU9Im9wYzpVSW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJJbnQ2 NFZhbHVlIiBUeXBlTmFtZT0ib3BjOkludDY0IiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iVUlu dDY0VmFsdWUiIFR5cGVOYW1lPSJvcGM6VUludDY0IiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0i RmxvYXRWYWx1ZSIgVHlwZU5hbWU9Im9wYzpGbG9hdCIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9 IkRvdWJsZVZhbHVlIiBUeXBlTmFtZT0ib3BjOkRvdWJsZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5h bWU9IlN0cmluZ1ZhbHVlIiBUeXBlTmFtZT0ib3BjOlN0cmluZyIgLz4NCiAgICA8b3BjOkZpZWxk IE5hbWU9IkRhdGVUaW1lVmFsdWUiIFR5cGVOYW1lPSJvcGM6RGF0ZVRpbWUiIC8+DQogICAgPG9w YzpGaWVsZCBOYW1lPSJHdWlkVmFsdWUiIFR5cGVOYW1lPSJvcGM6R3VpZCIgLz4NCiAgICA8b3Bj OkZpZWxkIE5hbWU9IkJ5dGVTdHJpbmdWYWx1ZSIgVHlwZU5hbWU9Im9wYzpCeXRlU3RyaW5nIiAv Pg0KICAgIDxvcGM6RmllbGQgTmFtZT0iWG1sRWxlbWVudFZhbHVlIiBUeXBlTmFtZT0idWE6WG1s RWxlbWVudCIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vZGVJZFZhbHVlIiBUeXBlTmFtZT0i dWE6Tm9kZUlkIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iRXhwYW5kZWROb2RlSWRWYWx1ZSIg VHlwZU5hbWU9InVhOkV4cGFuZGVkTm9kZUlkIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iUXVh bGlmaWVkTmFtZVZhbHVlIiBUeXBlTmFtZT0idWE6UXVhbGlmaWVkTmFtZSIgLz4NCiAgICA8b3Bj OkZpZWxkIE5hbWU9IkxvY2FsaXplZFRleHRWYWx1ZSIgVHlwZU5hbWU9InVhOkxvY2FsaXplZFRl eHQiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJTdGF0dXNDb2RlVmFsdWUiIFR5cGVOYW1lPSJ1 YTpTdGF0dXNDb2RlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iVmFyaWFudFZhbHVlIiBUeXBl TmFtZT0idWE6VmFyaWFudCIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkVudW1lcmF0aW9uVmFs dWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJTdHJ1Y3R1 cmVWYWx1ZSIgVHlwZU5hbWU9InVhOkV4dGVuc2lvbk9iamVjdCIgLz4NCiAgICA8b3BjOkZpZWxk IE5hbWU9Ik51bWJlciIgVHlwZU5hbWU9InVhOlZhcmlhbnQiIC8+DQogICAgPG9wYzpGaWVsZCBO YW1lPSJJbnRlZ2VyIiBUeXBlTmFtZT0idWE6VmFyaWFudCIgLz4NCiAgICA8b3BjOkZpZWxkIE5h bWU9IlVJbnRlZ2VyIiBUeXBlTmFtZT0idWE6VmFyaWFudCIgLz4NCiAgPC9vcGM6U3RydWN0dXJl ZFR5cGU+DQoNCiAgPG9wYzpTdHJ1Y3R1cmVkVHlwZSBOYW1lPSJBcnJheVZhbHVlRGF0YVR5cGUi IEJhc2VUeXBlPSJ1YTpFeHRlbnNpb25PYmplY3QiPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9P ZkJvb2xlYW5WYWx1ZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8b3BjOkZpZWxkIE5h bWU9IkJvb2xlYW5WYWx1ZSIgVHlwZU5hbWU9Im9wYzpCb29sZWFuIiBMZW5ndGhGaWVsZD0iTm9P ZkJvb2xlYW5WYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZTQnl0ZVZhbHVlIiBU eXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iU0J5dGVWYWx1ZSIg VHlwZU5hbWU9Im9wYzpTQnl0ZSIgTGVuZ3RoRmllbGQ9Ik5vT2ZTQnl0ZVZhbHVlIiAvPg0KICAg IDxvcGM6RmllbGQgTmFtZT0iTm9PZkJ5dGVWYWx1ZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4N CiAgICA8b3BjOkZpZWxkIE5hbWU9IkJ5dGVWYWx1ZSIgVHlwZU5hbWU9Im9wYzpCeXRlIiBMZW5n dGhGaWVsZD0iTm9PZkJ5dGVWYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZJbnQx NlZhbHVlIiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iSW50 MTZWYWx1ZSIgVHlwZU5hbWU9Im9wYzpJbnQxNiIgTGVuZ3RoRmllbGQ9Ik5vT2ZJbnQxNlZhbHVl IiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZlVJbnQxNlZhbHVlIiBUeXBlTmFtZT0ib3Bj OkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iVUludDE2VmFsdWUiIFR5cGVOYW1lPSJv cGM6VUludDE2IiBMZW5ndGhGaWVsZD0iTm9PZlVJbnQxNlZhbHVlIiAvPg0KICAgIDxvcGM6Rmll bGQgTmFtZT0iTm9PZkludDMyVmFsdWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9w YzpGaWVsZCBOYW1lPSJJbnQzMlZhbHVlIiBUeXBlTmFtZT0ib3BjOkludDMyIiBMZW5ndGhGaWVs ZD0iTm9PZkludDMyVmFsdWUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mVUludDMyVmFs dWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJVSW50MzJW YWx1ZSIgVHlwZU5hbWU9Im9wYzpVSW50MzIiIExlbmd0aEZpZWxkPSJOb09mVUludDMyVmFsdWUi IC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mSW50NjRWYWx1ZSIgVHlwZU5hbWU9Im9wYzpJ bnQzMiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkludDY0VmFsdWUiIFR5cGVOYW1lPSJvcGM6 SW50NjQiIExlbmd0aEZpZWxkPSJOb09mSW50NjRWYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5h bWU9Ik5vT2ZVSW50NjRWYWx1ZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8b3BjOkZp ZWxkIE5hbWU9IlVJbnQ2NFZhbHVlIiBUeXBlTmFtZT0ib3BjOlVJbnQ2NCIgTGVuZ3RoRmllbGQ9 Ik5vT2ZVSW50NjRWYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZGbG9hdFZhbHVl IiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iRmxvYXRWYWx1 ZSIgVHlwZU5hbWU9Im9wYzpGbG9hdCIgTGVuZ3RoRmllbGQ9Ik5vT2ZGbG9hdFZhbHVlIiAvPg0K ICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZkRvdWJsZVZhbHVlIiBUeXBlTmFtZT0ib3BjOkludDMy IiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iRG91YmxlVmFsdWUiIFR5cGVOYW1lPSJvcGM6RG91 YmxlIiBMZW5ndGhGaWVsZD0iTm9PZkRvdWJsZVZhbHVlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFt ZT0iTm9PZlN0cmluZ1ZhbHVlIiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6Rmll bGQgTmFtZT0iU3RyaW5nVmFsdWUiIFR5cGVOYW1lPSJvcGM6U3RyaW5nIiBMZW5ndGhGaWVsZD0i Tm9PZlN0cmluZ1ZhbHVlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZkRhdGVUaW1lVmFs dWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJEYXRlVGlt ZVZhbHVlIiBUeXBlTmFtZT0ib3BjOkRhdGVUaW1lIiBMZW5ndGhGaWVsZD0iTm9PZkRhdGVUaW1l VmFsdWUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mR3VpZFZhbHVlIiBUeXBlTmFtZT0i b3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iR3VpZFZhbHVlIiBUeXBlTmFtZT0i b3BjOkd1aWQiIExlbmd0aEZpZWxkPSJOb09mR3VpZFZhbHVlIiAvPg0KICAgIDxvcGM6RmllbGQg TmFtZT0iTm9PZkJ5dGVTdHJpbmdWYWx1ZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8 b3BjOkZpZWxkIE5hbWU9IkJ5dGVTdHJpbmdWYWx1ZSIgVHlwZU5hbWU9Im9wYzpCeXRlU3RyaW5n IiBMZW5ndGhGaWVsZD0iTm9PZkJ5dGVTdHJpbmdWYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5h bWU9Ik5vT2ZYbWxFbGVtZW50VmFsdWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9w YzpGaWVsZCBOYW1lPSJYbWxFbGVtZW50VmFsdWUiIFR5cGVOYW1lPSJ1YTpYbWxFbGVtZW50IiBM ZW5ndGhGaWVsZD0iTm9PZlhtbEVsZW1lbnRWYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9 Ik5vT2ZOb2RlSWRWYWx1ZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8b3BjOkZpZWxk IE5hbWU9Ik5vZGVJZFZhbHVlIiBUeXBlTmFtZT0idWE6Tm9kZUlkIiBMZW5ndGhGaWVsZD0iTm9P Zk5vZGVJZFZhbHVlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZkV4cGFuZGVkTm9kZUlk VmFsdWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJFeHBh bmRlZE5vZGVJZFZhbHVlIiBUeXBlTmFtZT0idWE6RXhwYW5kZWROb2RlSWQiIExlbmd0aEZpZWxk PSJOb09mRXhwYW5kZWROb2RlSWRWYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZR dWFsaWZpZWROYW1lVmFsdWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVs ZCBOYW1lPSJRdWFsaWZpZWROYW1lVmFsdWUiIFR5cGVOYW1lPSJ1YTpRdWFsaWZpZWROYW1lIiBM ZW5ndGhGaWVsZD0iTm9PZlF1YWxpZmllZE5hbWVWYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5h bWU9Ik5vT2ZMb2NhbGl6ZWRUZXh0VmFsdWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAg PG9wYzpGaWVsZCBOYW1lPSJMb2NhbGl6ZWRUZXh0VmFsdWUiIFR5cGVOYW1lPSJ1YTpMb2NhbGl6 ZWRUZXh0IiBMZW5ndGhGaWVsZD0iTm9PZkxvY2FsaXplZFRleHRWYWx1ZSIgLz4NCiAgICA8b3Bj OkZpZWxkIE5hbWU9Ik5vT2ZTdGF0dXNDb2RlVmFsdWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+ DQogICAgPG9wYzpGaWVsZCBOYW1lPSJTdGF0dXNDb2RlVmFsdWUiIFR5cGVOYW1lPSJ1YTpTdGF0 dXNDb2RlIiBMZW5ndGhGaWVsZD0iTm9PZlN0YXR1c0NvZGVWYWx1ZSIgLz4NCiAgICA8b3BjOkZp ZWxkIE5hbWU9Ik5vT2ZWYXJpYW50VmFsdWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAg PG9wYzpGaWVsZCBOYW1lPSJWYXJpYW50VmFsdWUiIFR5cGVOYW1lPSJ1YTpWYXJpYW50IiBMZW5n dGhGaWVsZD0iTm9PZlZhcmlhbnRWYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZF bnVtZXJhdGlvblZhbHVlIiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQg TmFtZT0iRW51bWVyYXRpb25WYWx1ZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgTGVuZ3RoRmllbGQ9 Ik5vT2ZFbnVtZXJhdGlvblZhbHVlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZlN0cnVj dHVyZVZhbHVlIiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0i U3RydWN0dXJlVmFsdWUiIFR5cGVOYW1lPSJ1YTpFeHRlbnNpb25PYmplY3QiIExlbmd0aEZpZWxk PSJOb09mU3RydWN0dXJlVmFsdWUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mTnVtYmVy IiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTnVtYmVyIiBU eXBlTmFtZT0idWE6VmFyaWFudCIgTGVuZ3RoRmllbGQ9Ik5vT2ZOdW1iZXIiIC8+DQogICAgPG9w YzpGaWVsZCBOYW1lPSJOb09mSW50ZWdlciIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8 b3BjOkZpZWxkIE5hbWU9IkludGVnZXIiIFR5cGVOYW1lPSJ1YTpWYXJpYW50IiBMZW5ndGhGaWVs ZD0iTm9PZkludGVnZXIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mVUludGVnZXIiIFR5 cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJVSW50ZWdlciIgVHlw ZU5hbWU9InVhOlZhcmlhbnQiIExlbmd0aEZpZWxkPSJOb09mVUludGVnZXIiIC8+DQogIDwvb3Bj OlN0cnVjdHVyZWRUeXBlPg0KDQogIDxvcGM6T3BhcXVlVHlwZSBOYW1lPSJCb29sZWFuRGF0YVR5 cGUiPg0KICA8L29wYzpPcGFxdWVUeXBlPg0KDQogIDxvcGM6T3BhcXVlVHlwZSBOYW1lPSJTQnl0 ZURhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFt ZT0iQnl0ZURhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5 cGUgTmFtZT0iSW50MTZEYXRhVHlwZSI+DQogIDwvb3BjOk9wYXF1ZVR5cGU+DQoNCiAgPG9wYzpP cGFxdWVUeXBlIE5hbWU9IlVJbnQxNkRhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0K ICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0iSW50MzJEYXRhVHlwZSI+DQogIDwvb3BjOk9wYXF1ZVR5 cGU+DQoNCiAgPG9wYzpPcGFxdWVUeXBlIE5hbWU9IlVJbnQzMkRhdGFUeXBlIj4NCiAgPC9vcGM6 T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0iSW50NjREYXRhVHlwZSI+DQog IDwvb3BjOk9wYXF1ZVR5cGU+DQoNCiAgPG9wYzpPcGFxdWVUeXBlIE5hbWU9IlVJbnQ2NERhdGFU eXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0iRmxv YXREYXRhVHlwZSI+DQogIDwvb3BjOk9wYXF1ZVR5cGU+DQoNCiAgPG9wYzpPcGFxdWVUeXBlIE5h bWU9IkRvdWJsZURhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1 ZVR5cGUgTmFtZT0iU3RyaW5nRGF0YVR5cGUiPg0KICA8L29wYzpPcGFxdWVUeXBlPg0KDQogIDxv cGM6T3BhcXVlVHlwZSBOYW1lPSJEYXRlVGltZURhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlw ZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0iR3VpZERhdGFUeXBlIj4NCiAgPC9vcGM6T3Bh cXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0iQnl0ZVN0cmluZ0RhdGFUeXBlIj4N CiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0iWG1sRWxlbWVu dERhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFt ZT0iTm9kZUlkRGF0YVR5cGUiPg0KICA8L29wYzpPcGFxdWVUeXBlPg0KDQogIDxvcGM6T3BhcXVl VHlwZSBOYW1lPSJFeHBhbmRlZE5vZGVJZERhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4N Cg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0iUXVhbGlmaWVkTmFtZURhdGFUeXBlIj4NCiAgPC9v cGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0iTG9jYWxpemVkVGV4dERh dGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0i U3RhdHVzQ29kZURhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1 ZVR5cGUgTmFtZT0iVmFyaWFudERhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8 b3BjOlN0cnVjdHVyZWRUeXBlIE5hbWU9IlVzZXJTY2FsYXJWYWx1ZURhdGFUeXBlIiBCYXNlVHlw ZT0idWE6RXh0ZW5zaW9uT2JqZWN0Ij4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkJvb2xlYW5EYXRh VHlwZSIgVHlwZU5hbWU9Im9wYzpCb29sZWFuIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iU0J5 dGVEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpTQnl0ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9 IkJ5dGVEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpCeXRlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFt ZT0iSW50MTZEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpJbnQxNiIgLz4NCiAgICA8b3BjOkZpZWxk IE5hbWU9IlVJbnQxNkRhdGFUeXBlIiBUeXBlTmFtZT0ib3BjOlVJbnQxNiIgLz4NCiAgICA8b3Bj OkZpZWxkIE5hbWU9IkludDMyRGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAg PG9wYzpGaWVsZCBOYW1lPSJVSW50MzJEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpVSW50MzIiIC8+ DQogICAgPG9wYzpGaWVsZCBOYW1lPSJJbnQ2NERhdGFUeXBlIiBUeXBlTmFtZT0ib3BjOkludDY0 IiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iVUludDY0RGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6 VUludDY0IiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iRmxvYXREYXRhVHlwZSIgVHlwZU5hbWU9 Im9wYzpGbG9hdCIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkRvdWJsZURhdGFUeXBlIiBUeXBl TmFtZT0ib3BjOkRvdWJsZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IlN0cmluZ0RhdGFUeXBl IiBUeXBlTmFtZT0ib3BjOlN0cmluZyIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkRhdGVUaW1l RGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6RGF0ZVRpbWUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1l PSJHdWlkRGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6R3VpZCIgLz4NCiAgICA8b3BjOkZpZWxkIE5h bWU9IkJ5dGVTdHJpbmdEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpCeXRlU3RyaW5nIiAvPg0KICAg IDxvcGM6RmllbGQgTmFtZT0iWG1sRWxlbWVudERhdGFUeXBlIiBUeXBlTmFtZT0idWE6WG1sRWxl bWVudCIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vZGVJZERhdGFUeXBlIiBUeXBlTmFtZT0i dWE6Tm9kZUlkIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iRXhwYW5kZWROb2RlSWREYXRhVHlw ZSIgVHlwZU5hbWU9InVhOkV4cGFuZGVkTm9kZUlkIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0i UXVhbGlmaWVkTmFtZURhdGFUeXBlIiBUeXBlTmFtZT0idWE6UXVhbGlmaWVkTmFtZSIgLz4NCiAg ICA8b3BjOkZpZWxkIE5hbWU9IkxvY2FsaXplZFRleHREYXRhVHlwZSIgVHlwZU5hbWU9InVhOkxv Y2FsaXplZFRleHQiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJTdGF0dXNDb2RlRGF0YVR5cGUi IFR5cGVOYW1lPSJ1YTpTdGF0dXNDb2RlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iVmFyaWFu dERhdGFUeXBlIiBUeXBlTmFtZT0idWE6VmFyaWFudCIgLz4NCiAgPC9vcGM6U3RydWN0dXJlZFR5 cGU+DQoNCiAgPG9wYzpTdHJ1Y3R1cmVkVHlwZSBOYW1lPSJVc2VyQXJyYXlWYWx1ZURhdGFUeXBl IiBCYXNlVHlwZT0idWE6RXh0ZW5zaW9uT2JqZWN0Ij4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5v T2ZCb29sZWFuRGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVs ZCBOYW1lPSJCb29sZWFuRGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6Qm9vbGVhbiIgTGVuZ3RoRmll bGQ9Ik5vT2ZCb29sZWFuRGF0YVR5cGUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mU0J5 dGVEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9 IlNCeXRlRGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6U0J5dGUiIExlbmd0aEZpZWxkPSJOb09mU0J5 dGVEYXRhVHlwZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZCeXRlRGF0YVR5cGUiIFR5 cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJCeXRlRGF0YVR5cGUi IFR5cGVOYW1lPSJvcGM6Qnl0ZSIgTGVuZ3RoRmllbGQ9Ik5vT2ZCeXRlRGF0YVR5cGUiIC8+DQog ICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mSW50MTZEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpJbnQz MiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkludDE2RGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6 SW50MTYiIExlbmd0aEZpZWxkPSJOb09mSW50MTZEYXRhVHlwZSIgLz4NCiAgICA8b3BjOkZpZWxk IE5hbWU9Ik5vT2ZVSW50MTZEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8 b3BjOkZpZWxkIE5hbWU9IlVJbnQxNkRhdGFUeXBlIiBUeXBlTmFtZT0ib3BjOlVJbnQxNiIgTGVu Z3RoRmllbGQ9Ik5vT2ZVSW50MTZEYXRhVHlwZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5v T2ZJbnQzMkRhdGFUeXBlIiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQg TmFtZT0iSW50MzJEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgTGVuZ3RoRmllbGQ9Ik5v T2ZJbnQzMkRhdGFUeXBlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZlVJbnQzMkRhdGFU eXBlIiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iVUludDMy RGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6VUludDMyIiBMZW5ndGhGaWVsZD0iTm9PZlVJbnQzMkRh dGFUeXBlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZkludDY0RGF0YVR5cGUiIFR5cGVO YW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJJbnQ2NERhdGFUeXBlIiBU eXBlTmFtZT0ib3BjOkludDY0IiBMZW5ndGhGaWVsZD0iTm9PZkludDY0RGF0YVR5cGUiIC8+DQog ICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mVUludDY0RGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6SW50 MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJVSW50NjREYXRhVHlwZSIgVHlwZU5hbWU9Im9w YzpVSW50NjQiIExlbmd0aEZpZWxkPSJOb09mVUludDY0RGF0YVR5cGUiIC8+DQogICAgPG9wYzpG aWVsZCBOYW1lPSJOb09mRmxvYXREYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAg ICA8b3BjOkZpZWxkIE5hbWU9IkZsb2F0RGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6RmxvYXQiIExl bmd0aEZpZWxkPSJOb09mRmxvYXREYXRhVHlwZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5v T2ZEb3VibGVEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8b3BjOkZpZWxk IE5hbWU9IkRvdWJsZURhdGFUeXBlIiBUeXBlTmFtZT0ib3BjOkRvdWJsZSIgTGVuZ3RoRmllbGQ9 Ik5vT2ZEb3VibGVEYXRhVHlwZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZTdHJpbmdE YXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IlN0 cmluZ0RhdGFUeXBlIiBUeXBlTmFtZT0ib3BjOlN0cmluZyIgTGVuZ3RoRmllbGQ9Ik5vT2ZTdHJp bmdEYXRhVHlwZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZEYXRlVGltZURhdGFUeXBl IiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iRGF0ZVRpbWVE YXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpEYXRlVGltZSIgTGVuZ3RoRmllbGQ9Ik5vT2ZEYXRlVGlt ZURhdGFUeXBlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZkd1aWREYXRhVHlwZSIgVHlw ZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ikd1aWREYXRhVHlwZSIg VHlwZU5hbWU9Im9wYzpHdWlkIiBMZW5ndGhGaWVsZD0iTm9PZkd1aWREYXRhVHlwZSIgLz4NCiAg ICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZCeXRlU3RyaW5nRGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6 SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJCeXRlU3RyaW5nRGF0YVR5cGUiIFR5cGVO YW1lPSJvcGM6Qnl0ZVN0cmluZyIgTGVuZ3RoRmllbGQ9Ik5vT2ZCeXRlU3RyaW5nRGF0YVR5cGUi IC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mWG1sRWxlbWVudERhdGFUeXBlIiBUeXBlTmFt ZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iWG1sRWxlbWVudERhdGFUeXBl IiBUeXBlTmFtZT0idWE6WG1sRWxlbWVudCIgTGVuZ3RoRmllbGQ9Ik5vT2ZYbWxFbGVtZW50RGF0 YVR5cGUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mTm9kZUlkRGF0YVR5cGUiIFR5cGVO YW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb2RlSWREYXRhVHlwZSIg VHlwZU5hbWU9InVhOk5vZGVJZCIgTGVuZ3RoRmllbGQ9Ik5vT2ZOb2RlSWREYXRhVHlwZSIgLz4N CiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZFeHBhbmRlZE5vZGVJZERhdGFUeXBlIiBUeXBlTmFt ZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iRXhwYW5kZWROb2RlSWREYXRh VHlwZSIgVHlwZU5hbWU9InVhOkV4cGFuZGVkTm9kZUlkIiBMZW5ndGhGaWVsZD0iTm9PZkV4cGFu ZGVkTm9kZUlkRGF0YVR5cGUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mUXVhbGlmaWVk TmFtZURhdGFUeXBlIiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFt ZT0iUXVhbGlmaWVkTmFtZURhdGFUeXBlIiBUeXBlTmFtZT0idWE6UXVhbGlmaWVkTmFtZSIgTGVu Z3RoRmllbGQ9Ik5vT2ZRdWFsaWZpZWROYW1lRGF0YVR5cGUiIC8+DQogICAgPG9wYzpGaWVsZCBO YW1lPSJOb09mTG9jYWxpemVkVGV4dERhdGFUeXBlIiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0K ICAgIDxvcGM6RmllbGQgTmFtZT0iTG9jYWxpemVkVGV4dERhdGFUeXBlIiBUeXBlTmFtZT0idWE6 TG9jYWxpemVkVGV4dCIgTGVuZ3RoRmllbGQ9Ik5vT2ZMb2NhbGl6ZWRUZXh0RGF0YVR5cGUiIC8+ DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mU3RhdHVzQ29kZURhdGFUeXBlIiBUeXBlTmFtZT0i b3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iU3RhdHVzQ29kZURhdGFUeXBlIiBU eXBlTmFtZT0idWE6U3RhdHVzQ29kZSIgTGVuZ3RoRmllbGQ9Ik5vT2ZTdGF0dXNDb2RlRGF0YVR5 cGUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mVmFyaWFudERhdGFUeXBlIiBUeXBlTmFt ZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iVmFyaWFudERhdGFUeXBlIiBU eXBlTmFtZT0idWE6VmFyaWFudCIgTGVuZ3RoRmllbGQ9Ik5vT2ZWYXJpYW50RGF0YVR5cGUiIC8+ DQogIDwvb3BjOlN0cnVjdHVyZWRUeXBlPg0KDQogIDxvcGM6U3RydWN0dXJlZFR5cGUgTmFtZT0i VmVjdG9yIiBCYXNlVHlwZT0idWE6RXh0ZW5zaW9uT2JqZWN0Ij4NCiAgICA8b3BjOkZpZWxkIE5h bWU9IlgiIFR5cGVOYW1lPSJvcGM6RG91YmxlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iWSIg VHlwZU5hbWU9Im9wYzpEb3VibGUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJaIiBUeXBlTmFt ZT0ib3BjOkRvdWJsZSIgLz4NCiAgPC9vcGM6U3RydWN0dXJlZFR5cGU+DQoNCiAgPG9wYzpTdHJ1 Y3R1cmVkVHlwZSBOYW1lPSJXb3JrT3JkZXJTdGF0dXNUeXBlIiBCYXNlVHlwZT0idWE6RXh0ZW5z aW9uT2JqZWN0Ij4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkFjdG9yIiBUeXBlTmFtZT0ib3BjOlN0 cmluZyIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IlRpbWVzdGFtcCIgVHlwZU5hbWU9Im9wYzpE YXRlVGltZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkNvbW1lbnQiIFR5cGVOYW1lPSJ1YTpM b2NhbGl6ZWRUZXh0IiAvPg0KICA8L29wYzpTdHJ1Y3R1cmVkVHlwZT4NCg0KICA8b3BjOlN0cnVj dHVyZWRUeXBlIE5hbWU9IldvcmtPcmRlclR5cGUiIEJhc2VUeXBlPSJ1YTpFeHRlbnNpb25PYmpl Y3QiPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iSUQiIFR5cGVOYW1lPSJvcGM6R3VpZCIgLz4NCiAg ICA8b3BjOkZpZWxkIE5hbWU9IkFzc2V0SUQiIFR5cGVOYW1lPSJvcGM6U3RyaW5nIiAvPg0KICAg IDxvcGM6RmllbGQgTmFtZT0iU3RhcnRUaW1lIiBUeXBlTmFtZT0ib3BjOkRhdGVUaW1lIiAvPg0K ICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZlN0YXR1c0NvbW1lbnRzIiBUeXBlTmFtZT0ib3BjOklu dDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iU3RhdHVzQ29tbWVudHMiIFR5cGVOYW1lPSJ0 bnM6V29ya09yZGVyU3RhdHVzVHlwZSIgTGVuZ3RoRmllbGQ9Ik5vT2ZTdGF0dXNDb21tZW50cyIg Lz4NCiAgPC9vcGM6U3RydWN0dXJlZFR5cGU+DQoNCjwvb3BjOlR5cGVEaWN0aW9uYXJ5Pg== NamespaceUri i=68 ns=1;i=11422 http://test.org/UA/Data/ Deprecated i=68 ns=1;i=11422 true ScalarValueDataType i=69 ns=1;i=11422 ScalarValueDataType ArrayValueDataType i=69 ns=1;i=11422 ArrayValueDataType UserScalarValueDataType i=69 ns=1;i=11422 UserScalarValueDataType UserArrayValueDataType i=69 ns=1;i=11422 UserArrayValueDataType Vector i=69 ns=1;i=11422 Vector WorkOrderStatusType i=69 ns=1;i=11422 WorkOrderStatusType WorkOrderType i=69 ns=1;i=11422 WorkOrderType Default XML ns=1;i=9440 ns=1;i=11444 i=76 Default XML ns=1;i=9669 ns=1;i=11447 i=76 Default XML ns=1;i=9920 ns=1;i=11450 i=76 Default XML ns=1;i=10006 ns=1;i=11453 i=76 Default XML ns=1;i=1000 ns=1;i=43 i=76 Default XML ns=1;i=1004 ns=1;i=52 i=76 Default XML ns=1;i=1005 ns=1;i=55 i=76 TestData ns=1;i=11443 ns=1;i=15046 ns=1;i=11444 ns=1;i=11447 ns=1;i=11450 ns=1;i=11453 ns=1;i=43 ns=1;i=52 ns=1;i=55 i=92 i=72 PHhzOnNjaGVtYQ0KICB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEi DQogIHhtbG5zOnVhPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvMjAwOC8wMi9UeXBlcy54 c2QiDQogIHhtbG5zOnRucz0iaHR0cDovL3Rlc3Qub3JnL1VBL0RhdGEvIg0KICB0YXJnZXROYW1l c3BhY2U9Imh0dHA6Ly90ZXN0Lm9yZy9VQS9EYXRhLyINCiAgZWxlbWVudEZvcm1EZWZhdWx0PSJx dWFsaWZpZWQiDQo+DQogIDx4czppbXBvcnQgbmFtZXNwYWNlPSJodHRwOi8vb3BjZm91bmRhdGlv bi5vcmcvVUEvMjAwOC8wMi9UeXBlcy54c2QiIC8+DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9 IlNjYWxhclZhbHVlRGF0YVR5cGUiPg0KICAgIDx4czpzZXF1ZW5jZT4NCiAgICAgIDx4czplbGVt ZW50IG5hbWU9IkJvb2xlYW5WYWx1ZSIgdHlwZT0ieHM6Ym9vbGVhbiIgbWluT2NjdXJzPSIwIiAv Pg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iU0J5dGVWYWx1ZSIgdHlwZT0ieHM6Ynl0ZSIgbWlu T2NjdXJzPSIwIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iQnl0ZVZhbHVlIiB0eXBlPSJ4 czp1bnNpZ25lZEJ5dGUiIG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9 IkludDE2VmFsdWUiIHR5cGU9InhzOnNob3J0IiBtaW5PY2N1cnM9IjAiIC8+DQogICAgICA8eHM6 ZWxlbWVudCBuYW1lPSJVSW50MTZWYWx1ZSIgdHlwZT0ieHM6dW5zaWduZWRTaG9ydCIgbWluT2Nj dXJzPSIwIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iSW50MzJWYWx1ZSIgdHlwZT0ieHM6 aW50IiBtaW5PY2N1cnM9IjAiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJVSW50MzJWYWx1 ZSIgdHlwZT0ieHM6dW5zaWduZWRJbnQiIG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVt ZW50IG5hbWU9IkludDY0VmFsdWUiIHR5cGU9InhzOmxvbmciIG1pbk9jY3Vycz0iMCIgLz4NCiAg ICAgIDx4czplbGVtZW50IG5hbWU9IlVJbnQ2NFZhbHVlIiB0eXBlPSJ4czp1bnNpZ25lZExvbmci IG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IkZsb2F0VmFsdWUiIHR5 cGU9InhzOmZsb2F0IiBtaW5PY2N1cnM9IjAiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJE b3VibGVWYWx1ZSIgdHlwZT0ieHM6ZG91YmxlIiBtaW5PY2N1cnM9IjAiIC8+DQogICAgICA8eHM6 ZWxlbWVudCBuYW1lPSJTdHJpbmdWYWx1ZSIgdHlwZT0ieHM6c3RyaW5nIiBtaW5PY2N1cnM9IjAi IG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iRGF0ZVRpbWVWYWx1 ZSIgdHlwZT0ieHM6ZGF0ZVRpbWUiIG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVtZW50 IG5hbWU9Ikd1aWRWYWx1ZSIgdHlwZT0idWE6R3VpZCIgbWluT2NjdXJzPSIwIiAvPg0KICAgICAg PHhzOmVsZW1lbnQgbmFtZT0iQnl0ZVN0cmluZ1ZhbHVlIiB0eXBlPSJ4czpiYXNlNjRCaW5hcnki IG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1l PSJYbWxFbGVtZW50VmFsdWUiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiPg0KICAgICAg ICA8eHM6Y29tcGxleFR5cGU+DQogICAgICAgICAgPHhzOnNlcXVlbmNlPg0KICAgICAgICAgICAg PHhzOmFueSBtaW5PY2N1cnM9IjAiIHByb2Nlc3NDb250ZW50cz0ibGF4IiAvPg0KICAgICAgICAg IDwveHM6c2VxdWVuY2U+DQogICAgICAgIDwveHM6Y29tcGxleFR5cGU+DQogICAgICA8L3hzOmVs ZW1lbnQ+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJOb2RlSWRWYWx1ZSIgdHlwZT0idWE6Tm9k ZUlkIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQg bmFtZT0iRXhwYW5kZWROb2RlSWRWYWx1ZSIgdHlwZT0idWE6RXhwYW5kZWROb2RlSWQiIG1pbk9j Y3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJRdWFs aWZpZWROYW1lVmFsdWUiIHR5cGU9InVhOlF1YWxpZmllZE5hbWUiIG1pbk9jY3Vycz0iMCIgbmls bGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJMb2NhbGl6ZWRUZXh0VmFs dWUiIHR5cGU9InVhOkxvY2FsaXplZFRleHQiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUi IC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJTdGF0dXNDb2RlVmFsdWUiIHR5cGU9InVhOlN0 YXR1c0NvZGUiIG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlZhcmlh bnRWYWx1ZSIgdHlwZT0idWE6VmFyaWFudCIgbWluT2NjdXJzPSIwIiAvPg0KICAgICAgPHhzOmVs ZW1lbnQgbmFtZT0iRW51bWVyYXRpb25WYWx1ZSIgdHlwZT0ieHM6aW50IiBtaW5PY2N1cnM9IjAi IC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJTdHJ1Y3R1cmVWYWx1ZSIgdHlwZT0idWE6RXh0 ZW5zaW9uT2JqZWN0IiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhz OmVsZW1lbnQgbmFtZT0iTnVtYmVyIiB0eXBlPSJ1YTpWYXJpYW50IiBtaW5PY2N1cnM9IjAiIC8+ DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJJbnRlZ2VyIiB0eXBlPSJ1YTpWYXJpYW50IiBtaW5P Y2N1cnM9IjAiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJVSW50ZWdlciIgdHlwZT0idWE6 VmFyaWFudCIgbWluT2NjdXJzPSIwIiAvPg0KICAgIDwveHM6c2VxdWVuY2U+DQogIDwveHM6Y29t cGxleFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9IlNjYWxhclZhbHVlRGF0YVR5cGUiIHR5cGU9 InRuczpTY2FsYXJWYWx1ZURhdGFUeXBlIiAvPg0KDQogIDx4czpjb21wbGV4VHlwZSBuYW1lPSJM aXN0T2ZTY2FsYXJWYWx1ZURhdGFUeXBlIj4NCiAgICA8eHM6c2VxdWVuY2U+DQogICAgICA8eHM6 ZWxlbWVudCBuYW1lPSJTY2FsYXJWYWx1ZURhdGFUeXBlIiB0eXBlPSJ0bnM6U2NhbGFyVmFsdWVE YXRhVHlwZSIgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9InVuYm91bmRlZCIgbmlsbGFibGU9InRy dWUiIC8+DQogICAgPC94czpzZXF1ZW5jZT4NCiAgPC94czpjb21wbGV4VHlwZT4NCiAgPHhzOmVs ZW1lbnQgbmFtZT0iTGlzdE9mU2NhbGFyVmFsdWVEYXRhVHlwZSIgdHlwZT0idG5zOkxpc3RPZlNj YWxhclZhbHVlRGF0YVR5cGUiIG5pbGxhYmxlPSJ0cnVlIj48L3hzOmVsZW1lbnQ+DQoNCiAgPHhz OmNvbXBsZXhUeXBlIG5hbWU9IkFycmF5VmFsdWVEYXRhVHlwZSI+DQogICAgPHhzOnNlcXVlbmNl Pg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iQm9vbGVhblZhbHVlIiB0eXBlPSJ1YTpMaXN0T2ZC b29sZWFuIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1l bnQgbmFtZT0iU0J5dGVWYWx1ZSIgdHlwZT0idWE6TGlzdE9mU0J5dGUiIG1pbk9jY3Vycz0iMCIg bmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJCeXRlVmFsdWUiIHR5 cGU9InVhOkxpc3RPZkJ5dGUiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAg ICA8eHM6ZWxlbWVudCBuYW1lPSJJbnQxNlZhbHVlIiB0eXBlPSJ1YTpMaXN0T2ZJbnQxNiIgbWlu T2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlVJ bnQxNlZhbHVlIiB0eXBlPSJ1YTpMaXN0T2ZVSW50MTYiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9 InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJJbnQzMlZhbHVlIiB0eXBlPSJ1YTpM aXN0T2ZJbnQzMiIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICAgIDx4czpl bGVtZW50IG5hbWU9IlVJbnQzMlZhbHVlIiB0eXBlPSJ1YTpMaXN0T2ZVSW50MzIiIG1pbk9jY3Vy cz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJJbnQ2NFZh bHVlIiB0eXBlPSJ1YTpMaXN0T2ZJbnQ2NCIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIg Lz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlVJbnQ2NFZhbHVlIiB0eXBlPSJ1YTpMaXN0T2ZV SW50NjQiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVu dCBuYW1lPSJGbG9hdFZhbHVlIiB0eXBlPSJ1YTpMaXN0T2ZGbG9hdCIgbWluT2NjdXJzPSIwIiBu aWxsYWJsZT0idHJ1ZSIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IkRvdWJsZVZhbHVlIiB0 eXBlPSJ1YTpMaXN0T2ZEb3VibGUiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQog ICAgICA8eHM6ZWxlbWVudCBuYW1lPSJTdHJpbmdWYWx1ZSIgdHlwZT0idWE6TGlzdE9mU3RyaW5n IiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFt ZT0iRGF0ZVRpbWVWYWx1ZSIgdHlwZT0idWE6TGlzdE9mRGF0ZVRpbWUiIG1pbk9jY3Vycz0iMCIg bmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJHdWlkVmFsdWUiIHR5 cGU9InVhOkxpc3RPZkd1aWQiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAg ICA8eHM6ZWxlbWVudCBuYW1lPSJCeXRlU3RyaW5nVmFsdWUiIHR5cGU9InVhOkxpc3RPZkJ5dGVT dHJpbmciIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVu dCBuYW1lPSJYbWxFbGVtZW50VmFsdWUiIHR5cGU9InVhOkxpc3RPZlhtbEVsZW1lbnQiIG1pbk9j Y3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJOb2Rl SWRWYWx1ZSIgdHlwZT0idWE6TGlzdE9mTm9kZUlkIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0 cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iRXhwYW5kZWROb2RlSWRWYWx1ZSIgdHlw ZT0idWE6TGlzdE9mRXhwYW5kZWROb2RlSWQiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUi IC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJRdWFsaWZpZWROYW1lVmFsdWUiIHR5cGU9InVh Okxpc3RPZlF1YWxpZmllZE5hbWUiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQog ICAgICA8eHM6ZWxlbWVudCBuYW1lPSJMb2NhbGl6ZWRUZXh0VmFsdWUiIHR5cGU9InVhOkxpc3RP ZkxvY2FsaXplZFRleHQiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8 eHM6ZWxlbWVudCBuYW1lPSJTdGF0dXNDb2RlVmFsdWUiIHR5cGU9InVhOkxpc3RPZlN0YXR1c0Nv ZGUiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBu YW1lPSJWYXJpYW50VmFsdWUiIHR5cGU9InVhOkxpc3RPZlZhcmlhbnQiIG1pbk9jY3Vycz0iMCIg bmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJFbnVtZXJhdGlvblZh bHVlIiB0eXBlPSJ1YTpMaXN0T2ZJbnQzMiIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIg Lz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlN0cnVjdHVyZVZhbHVlIiB0eXBlPSJ1YTpMaXN0 T2ZFeHRlbnNpb25PYmplY3QiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAg ICA8eHM6ZWxlbWVudCBuYW1lPSJOdW1iZXIiIHR5cGU9InVhOkxpc3RPZlZhcmlhbnQiIG1pbk9j Y3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJJbnRl Z2VyIiB0eXBlPSJ1YTpMaXN0T2ZWYXJpYW50IiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVl IiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iVUludGVnZXIiIHR5cGU9InVhOkxpc3RPZlZh cmlhbnQiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgPC94czpzZXF1ZW5j ZT4NCiAgPC94czpjb21wbGV4VHlwZT4NCiAgPHhzOmVsZW1lbnQgbmFtZT0iQXJyYXlWYWx1ZURh dGFUeXBlIiB0eXBlPSJ0bnM6QXJyYXlWYWx1ZURhdGFUeXBlIiAvPg0KDQogIDx4czpjb21wbGV4 VHlwZSBuYW1lPSJMaXN0T2ZBcnJheVZhbHVlRGF0YVR5cGUiPg0KICAgIDx4czpzZXF1ZW5jZT4N CiAgICAgIDx4czplbGVtZW50IG5hbWU9IkFycmF5VmFsdWVEYXRhVHlwZSIgdHlwZT0idG5zOkFy cmF5VmFsdWVEYXRhVHlwZSIgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9InVuYm91bmRlZCIgbmls bGFibGU9InRydWUiIC8+DQogICAgPC94czpzZXF1ZW5jZT4NCiAgPC94czpjb21wbGV4VHlwZT4N CiAgPHhzOmVsZW1lbnQgbmFtZT0iTGlzdE9mQXJyYXlWYWx1ZURhdGFUeXBlIiB0eXBlPSJ0bnM6 TGlzdE9mQXJyYXlWYWx1ZURhdGFUeXBlIiBuaWxsYWJsZT0idHJ1ZSI+PC94czplbGVtZW50Pg0K DQogIDx4czplbGVtZW50IG5hbWU9IkJvb2xlYW5EYXRhVHlwZSIgdHlwZT0ieHM6Ym9vbGVhbiIg Lz4NCg0KICA8eHM6ZWxlbWVudCBuYW1lPSJTQnl0ZURhdGFUeXBlIiB0eXBlPSJ4czpieXRlIiAv Pg0KDQogIDx4czplbGVtZW50IG5hbWU9IkJ5dGVEYXRhVHlwZSIgdHlwZT0ieHM6dW5zaWduZWRC eXRlIiAvPg0KDQogIDx4czplbGVtZW50IG5hbWU9IkludDE2RGF0YVR5cGUiIHR5cGU9InhzOnNo b3J0IiAvPg0KDQogIDx4czplbGVtZW50IG5hbWU9IlVJbnQxNkRhdGFUeXBlIiB0eXBlPSJ4czp1 bnNpZ25lZFNob3J0IiAvPg0KDQogIDx4czplbGVtZW50IG5hbWU9IkludDMyRGF0YVR5cGUiIHR5 cGU9InhzOmludCIgLz4NCg0KICA8eHM6ZWxlbWVudCBuYW1lPSJVSW50MzJEYXRhVHlwZSIgdHlw ZT0ieHM6dW5zaWduZWRJbnQiIC8+DQoNCiAgPHhzOmVsZW1lbnQgbmFtZT0iSW50NjREYXRhVHlw ZSIgdHlwZT0ieHM6bG9uZyIgLz4NCg0KICA8eHM6ZWxlbWVudCBuYW1lPSJVSW50NjREYXRhVHlw ZSIgdHlwZT0ieHM6dW5zaWduZWRMb25nIiAvPg0KDQogIDx4czplbGVtZW50IG5hbWU9IkZsb2F0 RGF0YVR5cGUiIHR5cGU9InhzOmZsb2F0IiAvPg0KDQogIDx4czplbGVtZW50IG5hbWU9IkRvdWJs ZURhdGFUeXBlIiB0eXBlPSJ4czpkb3VibGUiIC8+DQoNCiAgPHhzOmVsZW1lbnQgbmFtZT0iU3Ry aW5nRGF0YVR5cGUiIHR5cGU9InhzOnN0cmluZyIgLz4NCg0KICA8eHM6ZWxlbWVudCBuYW1lPSJE YXRlVGltZURhdGFUeXBlIiB0eXBlPSJ4czpkYXRlVGltZSIgLz4NCg0KICA8eHM6ZWxlbWVudCBu YW1lPSJHdWlkRGF0YVR5cGUiIHR5cGU9InVhOkd1aWQiIC8+DQoNCiAgPHhzOmVsZW1lbnQgbmFt ZT0iQnl0ZVN0cmluZ0RhdGFUeXBlIiB0eXBlPSJ4czpiYXNlNjRCaW5hcnkiIC8+DQoNCiAgPHhz OmVsZW1lbnQgbmFtZT0iWG1sRWxlbWVudERhdGFUeXBlIiB0eXBlPSJ1YTpYbWxFbGVtZW50IiAv Pg0KDQogIDx4czplbGVtZW50IG5hbWU9Ik5vZGVJZERhdGFUeXBlIiB0eXBlPSJ1YTpOb2RlSWQi IC8+DQoNCiAgPHhzOmVsZW1lbnQgbmFtZT0iRXhwYW5kZWROb2RlSWREYXRhVHlwZSIgdHlwZT0i dWE6RXhwYW5kZWROb2RlSWQiIC8+DQoNCiAgPHhzOmVsZW1lbnQgbmFtZT0iUXVhbGlmaWVkTmFt ZURhdGFUeXBlIiB0eXBlPSJ1YTpRdWFsaWZpZWROYW1lIiAvPg0KDQogIDx4czplbGVtZW50IG5h bWU9IkxvY2FsaXplZFRleHREYXRhVHlwZSIgdHlwZT0idWE6TG9jYWxpemVkVGV4dCIgLz4NCg0K ICA8eHM6ZWxlbWVudCBuYW1lPSJTdGF0dXNDb2RlRGF0YVR5cGUiIHR5cGU9InVhOlN0YXR1c0Nv ZGUiIC8+DQoNCiAgPHhzOmVsZW1lbnQgbmFtZT0iVmFyaWFudERhdGFUeXBlIiB0eXBlPSJ1YTpW YXJpYW50IiAvPg0KDQogIDx4czpjb21wbGV4VHlwZSBuYW1lPSJVc2VyU2NhbGFyVmFsdWVEYXRh VHlwZSI+DQogICAgPHhzOnNlcXVlbmNlPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iQm9vbGVh bkRhdGFUeXBlIiB0eXBlPSJ4czpib29sZWFuIiBtaW5PY2N1cnM9IjAiIC8+DQogICAgICA8eHM6 ZWxlbWVudCBuYW1lPSJTQnl0ZURhdGFUeXBlIiB0eXBlPSJ4czpieXRlIiBtaW5PY2N1cnM9IjAi IC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJCeXRlRGF0YVR5cGUiIHR5cGU9InhzOnVuc2ln bmVkQnl0ZSIgbWluT2NjdXJzPSIwIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iSW50MTZE YXRhVHlwZSIgdHlwZT0ieHM6c2hvcnQiIG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVt ZW50IG5hbWU9IlVJbnQxNkRhdGFUeXBlIiB0eXBlPSJ4czp1bnNpZ25lZFNob3J0IiBtaW5PY2N1 cnM9IjAiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJJbnQzMkRhdGFUeXBlIiB0eXBlPSJ4 czppbnQiIG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlVJbnQzMkRh dGFUeXBlIiB0eXBlPSJ4czp1bnNpZ25lZEludCIgbWluT2NjdXJzPSIwIiAvPg0KICAgICAgPHhz OmVsZW1lbnQgbmFtZT0iSW50NjREYXRhVHlwZSIgdHlwZT0ieHM6bG9uZyIgbWluT2NjdXJzPSIw IiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iVUludDY0RGF0YVR5cGUiIHR5cGU9InhzOnVu c2lnbmVkTG9uZyIgbWluT2NjdXJzPSIwIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iRmxv YXREYXRhVHlwZSIgdHlwZT0ieHM6ZmxvYXQiIG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czpl bGVtZW50IG5hbWU9IkRvdWJsZURhdGFUeXBlIiB0eXBlPSJ4czpkb3VibGUiIG1pbk9jY3Vycz0i MCIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlN0cmluZ0RhdGFUeXBlIiB0eXBlPSJ4czpz dHJpbmciIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVu dCBuYW1lPSJEYXRlVGltZURhdGFUeXBlIiB0eXBlPSJ4czpkYXRlVGltZSIgbWluT2NjdXJzPSIw IiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iR3VpZERhdGFUeXBlIiB0eXBlPSJ1YTpHdWlk IiBtaW5PY2N1cnM9IjAiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJCeXRlU3RyaW5nRGF0 YVR5cGUiIHR5cGU9InhzOmJhc2U2NEJpbmFyeSIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1 ZSIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlhtbEVsZW1lbnREYXRhVHlwZSIgbWluT2Nj dXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSI+DQogICAgICAgIDx4czpjb21wbGV4VHlwZT4NCiAgICAg ICAgICA8eHM6c2VxdWVuY2U+DQogICAgICAgICAgICA8eHM6YW55IG1pbk9jY3Vycz0iMCIgcHJv Y2Vzc0NvbnRlbnRzPSJsYXgiIC8+DQogICAgICAgICAgPC94czpzZXF1ZW5jZT4NCiAgICAgICAg PC94czpjb21wbGV4VHlwZT4NCiAgICAgIDwveHM6ZWxlbWVudD4NCiAgICAgIDx4czplbGVtZW50 IG5hbWU9Ik5vZGVJZERhdGFUeXBlIiB0eXBlPSJ1YTpOb2RlSWQiIG1pbk9jY3Vycz0iMCIgbmls bGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJFeHBhbmRlZE5vZGVJZERh dGFUeXBlIiB0eXBlPSJ1YTpFeHBhbmRlZE5vZGVJZCIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0i dHJ1ZSIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlF1YWxpZmllZE5hbWVEYXRhVHlwZSIg dHlwZT0idWE6UXVhbGlmaWVkTmFtZSIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4N CiAgICAgIDx4czplbGVtZW50IG5hbWU9IkxvY2FsaXplZFRleHREYXRhVHlwZSIgdHlwZT0idWE6 TG9jYWxpemVkVGV4dCIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICAgIDx4 czplbGVtZW50IG5hbWU9IlN0YXR1c0NvZGVEYXRhVHlwZSIgdHlwZT0idWE6U3RhdHVzQ29kZSIg bWluT2NjdXJzPSIwIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iVmFyaWFudERhdGFUeXBl IiB0eXBlPSJ1YTpWYXJpYW50IiBtaW5PY2N1cnM9IjAiIC8+DQogICAgPC94czpzZXF1ZW5jZT4N CiAgPC94czpjb21wbGV4VHlwZT4NCiAgPHhzOmVsZW1lbnQgbmFtZT0iVXNlclNjYWxhclZhbHVl RGF0YVR5cGUiIHR5cGU9InRuczpVc2VyU2NhbGFyVmFsdWVEYXRhVHlwZSIgLz4NCg0KICA8eHM6 Y29tcGxleFR5cGUgbmFtZT0iTGlzdE9mVXNlclNjYWxhclZhbHVlRGF0YVR5cGUiPg0KICAgIDx4 czpzZXF1ZW5jZT4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlVzZXJTY2FsYXJWYWx1ZURhdGFU eXBlIiB0eXBlPSJ0bnM6VXNlclNjYWxhclZhbHVlRGF0YVR5cGUiIG1pbk9jY3Vycz0iMCIgbWF4 T2NjdXJzPSJ1bmJvdW5kZWQiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgIDwveHM6c2VxdWVuY2U+ DQogIDwveHM6Y29tcGxleFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9Ikxpc3RPZlVzZXJTY2Fs YXJWYWx1ZURhdGFUeXBlIiB0eXBlPSJ0bnM6TGlzdE9mVXNlclNjYWxhclZhbHVlRGF0YVR5cGUi IG5pbGxhYmxlPSJ0cnVlIj48L3hzOmVsZW1lbnQ+DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9 IlVzZXJBcnJheVZhbHVlRGF0YVR5cGUiPg0KICAgIDx4czpzZXF1ZW5jZT4NCiAgICAgIDx4czpl bGVtZW50IG5hbWU9IkJvb2xlYW5EYXRhVHlwZSIgdHlwZT0idWE6TGlzdE9mQm9vbGVhbiIgbWlu T2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlNC eXRlRGF0YVR5cGUiIHR5cGU9InVhOkxpc3RPZlNCeXRlIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxl PSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iQnl0ZURhdGFUeXBlIiB0eXBlPSJ0 bnM6TGlzdE9mQnl0ZURhdGFUeXBlIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0K ICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iSW50MTZEYXRhVHlwZSIgdHlwZT0idWE6TGlzdE9mSW50 MTYiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBu YW1lPSJVSW50MTZEYXRhVHlwZSIgdHlwZT0idWE6TGlzdE9mVUludDE2IiBtaW5PY2N1cnM9IjAi IG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iSW50MzJEYXRhVHlw ZSIgdHlwZT0idWE6TGlzdE9mSW50MzIiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+ DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJVSW50MzJEYXRhVHlwZSIgdHlwZT0idWE6TGlzdE9m VUludDMyIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1l bnQgbmFtZT0iSW50NjREYXRhVHlwZSIgdHlwZT0idWE6TGlzdE9mSW50NjQiIG1pbk9jY3Vycz0i MCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJVSW50NjREYXRh VHlwZSIgdHlwZT0idWE6TGlzdE9mVUludDY0IiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVl IiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iRmxvYXREYXRhVHlwZSIgdHlwZT0idWE6TGlz dE9mRmxvYXQiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxl bWVudCBuYW1lPSJEb3VibGVEYXRhVHlwZSIgdHlwZT0idWE6TGlzdE9mRG91YmxlIiBtaW5PY2N1 cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iU3RyaW5n RGF0YVR5cGUiIHR5cGU9InVhOkxpc3RPZlN0cmluZyIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0i dHJ1ZSIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IkRhdGVUaW1lRGF0YVR5cGUiIHR5cGU9 InVhOkxpc3RPZkRhdGVUaW1lIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAg ICAgPHhzOmVsZW1lbnQgbmFtZT0iR3VpZERhdGFUeXBlIiB0eXBlPSJ1YTpMaXN0T2ZHdWlkIiBt aW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0i Qnl0ZVN0cmluZ0RhdGFUeXBlIiB0eXBlPSJ1YTpMaXN0T2ZCeXRlU3RyaW5nIiBtaW5PY2N1cnM9 IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iWG1sRWxlbWVu dERhdGFUeXBlIiB0eXBlPSJ1YTpMaXN0T2ZYbWxFbGVtZW50IiBtaW5PY2N1cnM9IjAiIG5pbGxh YmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iTm9kZUlkRGF0YVR5cGUiIHR5 cGU9InVhOkxpc3RPZk5vZGVJZCIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAg ICAgIDx4czplbGVtZW50IG5hbWU9IkV4cGFuZGVkTm9kZUlkRGF0YVR5cGUiIHR5cGU9InVhOkxp c3RPZkV4cGFuZGVkTm9kZUlkIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAg ICAgPHhzOmVsZW1lbnQgbmFtZT0iUXVhbGlmaWVkTmFtZURhdGFUeXBlIiB0eXBlPSJ1YTpMaXN0 T2ZRdWFsaWZpZWROYW1lIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAg PHhzOmVsZW1lbnQgbmFtZT0iTG9jYWxpemVkVGV4dERhdGFUeXBlIiB0eXBlPSJ1YTpMaXN0T2ZM b2NhbGl6ZWRUZXh0IiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhz OmVsZW1lbnQgbmFtZT0iU3RhdHVzQ29kZURhdGFUeXBlIiB0eXBlPSJ1YTpMaXN0T2ZTdGF0dXND b2RlIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQg bmFtZT0iVmFyaWFudERhdGFUeXBlIiB0eXBlPSJ1YTpMaXN0T2ZWYXJpYW50IiBtaW5PY2N1cnM9 IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgIDwveHM6c2VxdWVuY2U+DQogIDwveHM6Y29tcGxl eFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9IlVzZXJBcnJheVZhbHVlRGF0YVR5cGUiIHR5cGU9 InRuczpVc2VyQXJyYXlWYWx1ZURhdGFUeXBlIiAvPg0KDQogIDx4czpjb21wbGV4VHlwZSBuYW1l PSJMaXN0T2ZVc2VyQXJyYXlWYWx1ZURhdGFUeXBlIj4NCiAgICA8eHM6c2VxdWVuY2U+DQogICAg ICA8eHM6ZWxlbWVudCBuYW1lPSJVc2VyQXJyYXlWYWx1ZURhdGFUeXBlIiB0eXBlPSJ0bnM6VXNl ckFycmF5VmFsdWVEYXRhVHlwZSIgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9InVuYm91bmRlZCIg bmlsbGFibGU9InRydWUiIC8+DQogICAgPC94czpzZXF1ZW5jZT4NCiAgPC94czpjb21wbGV4VHlw ZT4NCiAgPHhzOmVsZW1lbnQgbmFtZT0iTGlzdE9mVXNlckFycmF5VmFsdWVEYXRhVHlwZSIgdHlw ZT0idG5zOkxpc3RPZlVzZXJBcnJheVZhbHVlRGF0YVR5cGUiIG5pbGxhYmxlPSJ0cnVlIj48L3hz OmVsZW1lbnQ+DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9IlZlY3RvciI+DQogICAgPHhzOnNl cXVlbmNlPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iWCIgdHlwZT0ieHM6ZG91YmxlIiBtaW5P Y2N1cnM9IjAiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJZIiB0eXBlPSJ4czpkb3VibGUi IG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IloiIHR5cGU9InhzOmRv dWJsZSIgbWluT2NjdXJzPSIwIiAvPg0KICAgIDwveHM6c2VxdWVuY2U+DQogIDwveHM6Y29tcGxl eFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9IlZlY3RvciIgdHlwZT0idG5zOlZlY3RvciIgLz4N Cg0KICA8eHM6Y29tcGxleFR5cGUgbmFtZT0iTGlzdE9mVmVjdG9yIj4NCiAgICA8eHM6c2VxdWVu Y2U+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJWZWN0b3IiIHR5cGU9InRuczpWZWN0b3IiIG1p bk9jY3Vycz0iMCIgbWF4T2NjdXJzPSJ1bmJvdW5kZWQiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAg IDwveHM6c2VxdWVuY2U+DQogIDwveHM6Y29tcGxleFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9 Ikxpc3RPZlZlY3RvciIgdHlwZT0idG5zOkxpc3RPZlZlY3RvciIgbmlsbGFibGU9InRydWUiPjwv eHM6ZWxlbWVudD4NCg0KICA8eHM6Y29tcGxleFR5cGUgbmFtZT0iV29ya09yZGVyU3RhdHVzVHlw ZSI+DQogICAgPHhzOnNlcXVlbmNlPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iQWN0b3IiIHR5 cGU9InhzOnN0cmluZyIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICAgIDx4 czplbGVtZW50IG5hbWU9IlRpbWVzdGFtcCIgdHlwZT0ieHM6ZGF0ZVRpbWUiIG1pbk9jY3Vycz0i MCIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IkNvbW1lbnQiIHR5cGU9InVhOkxvY2FsaXpl ZFRleHQiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgPC94czpzZXF1ZW5j ZT4NCiAgPC94czpjb21wbGV4VHlwZT4NCiAgPHhzOmVsZW1lbnQgbmFtZT0iV29ya09yZGVyU3Rh dHVzVHlwZSIgdHlwZT0idG5zOldvcmtPcmRlclN0YXR1c1R5cGUiIC8+DQoNCiAgPHhzOmNvbXBs ZXhUeXBlIG5hbWU9Ikxpc3RPZldvcmtPcmRlclN0YXR1c1R5cGUiPg0KICAgIDx4czpzZXF1ZW5j ZT4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IldvcmtPcmRlclN0YXR1c1R5cGUiIHR5cGU9InRu czpXb3JrT3JkZXJTdGF0dXNUeXBlIiBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0idW5ib3VuZGVk IiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICA8L3hzOnNlcXVlbmNlPg0KICA8L3hzOmNvbXBsZXhU eXBlPg0KICA8eHM6ZWxlbWVudCBuYW1lPSJMaXN0T2ZXb3JrT3JkZXJTdGF0dXNUeXBlIiB0eXBl PSJ0bnM6TGlzdE9mV29ya09yZGVyU3RhdHVzVHlwZSIgbmlsbGFibGU9InRydWUiPjwveHM6ZWxl bWVudD4NCg0KICA8eHM6Y29tcGxleFR5cGUgbmFtZT0iV29ya09yZGVyVHlwZSI+DQogICAgPHhz OnNlcXVlbmNlPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iSUQiIHR5cGU9InVhOkd1aWQiIG1p bk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IkFzc2V0SUQiIHR5cGU9Inhz OnN0cmluZyIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICAgIDx4czplbGVt ZW50IG5hbWU9IlN0YXJ0VGltZSIgdHlwZT0ieHM6ZGF0ZVRpbWUiIG1pbk9jY3Vycz0iMCIgLz4N CiAgICAgIDx4czplbGVtZW50IG5hbWU9IlN0YXR1c0NvbW1lbnRzIiB0eXBlPSJ0bnM6TGlzdE9m V29ya09yZGVyU3RhdHVzVHlwZSIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAg ICA8L3hzOnNlcXVlbmNlPg0KICA8L3hzOmNvbXBsZXhUeXBlPg0KICA8eHM6ZWxlbWVudCBuYW1l PSJXb3JrT3JkZXJUeXBlIiB0eXBlPSJ0bnM6V29ya09yZGVyVHlwZSIgLz4NCg0KICA8eHM6Y29t cGxleFR5cGUgbmFtZT0iTGlzdE9mV29ya09yZGVyVHlwZSI+DQogICAgPHhzOnNlcXVlbmNlPg0K ICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iV29ya09yZGVyVHlwZSIgdHlwZT0idG5zOldvcmtPcmRl clR5cGUiIG1pbk9jY3Vycz0iMCIgbWF4T2NjdXJzPSJ1bmJvdW5kZWQiIG5pbGxhYmxlPSJ0cnVl IiAvPg0KICAgIDwveHM6c2VxdWVuY2U+DQogIDwveHM6Y29tcGxleFR5cGU+DQogIDx4czplbGVt ZW50IG5hbWU9Ikxpc3RPZldvcmtPcmRlclR5cGUiIHR5cGU9InRuczpMaXN0T2ZXb3JrT3JkZXJU eXBlIiBuaWxsYWJsZT0idHJ1ZSI+PC94czplbGVtZW50Pg0KDQo8L3hzOnNjaGVtYT4= NamespaceUri i=68 ns=1;i=11441 http://test.org/UA/Data/ Deprecated i=68 ns=1;i=11441 true ScalarValueDataType i=69 ns=1;i=11441 //xs:element[@name='ScalarValueDataType'] ArrayValueDataType i=69 ns=1;i=11441 //xs:element[@name='ArrayValueDataType'] UserScalarValueDataType i=69 ns=1;i=11441 //xs:element[@name='UserScalarValueDataType'] UserArrayValueDataType i=69 ns=1;i=11441 //xs:element[@name='UserArrayValueDataType'] Vector i=69 ns=1;i=11441 //xs:element[@name='Vector'] WorkOrderStatusType i=69 ns=1;i=11441 //xs:element[@name='WorkOrderStatusType'] WorkOrderType i=69 ns=1;i=11441 //xs:element[@name='WorkOrderType'] Default JSON ns=1;i=9440 i=76 Default JSON ns=1;i=9669 i=76 Default JSON ns=1;i=9920 i=76 Default JSON ns=1;i=10006 i=76 Default JSON ns=1;i=1000 i=76 Default JSON ns=1;i=1004 i=76 Default JSON ns=1;i=1005 i=76 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/TestData/Design/TestData.PredefinedNodes.xml ================================================  http://test.org/UA/Data/ ObjectType_8 ns=1;i=9371 1 GenerateValuesEventType i=2041 Variable_2 ns=1;i=9381 1 Iterations i=46 i=68 i=78 9381 i=7 -1 1 1 Variable_2 ns=1;i=9382 1 NewValueCount i=46 i=68 i=78 9382 i=7 -1 1 1 ObjectType_8 ns=1;i=9383 1 TestDataObjectType i=58 i=36 ns=1;i=9387 Variable_2 ns=1;i=9384 1 SimulationActive If true the server will produce new values for each monitored variable. i=46 i=68 i=78 9384 i=1 -1 1 1 Method_4 ns=1;i=9385 1 GenerateValues i=47 ns=1;i=9385 i=78 9385 true true Variable_2 ns=1;i=9386 0 InputArguments i=46 i=68 i=78 9386 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 Object_1 ns=1;i=9387 1 CycleComplete i=47 i=2881 i=78 9387 i=36 true ns=1;i=9383 Variable_2 ns=1;i=9388 0 EventId i=46 i=68 i=78 9388 i=15 -1 1 1 Variable_2 ns=1;i=9389 0 EventType i=46 i=68 i=78 9389 i=17 -1 1 1 Variable_2 ns=1;i=9390 0 SourceNode i=46 i=68 i=78 9390 i=17 -1 1 1 Variable_2 ns=1;i=9391 0 SourceName i=46 i=68 i=78 9391 i=12 -1 1 1 Variable_2 ns=1;i=9393 0 ReceiveTime i=46 i=68 i=78 9393 i=294 -1 1 1 Variable_2 ns=1;i=9395 0 Message i=46 i=68 i=78 9395 i=21 -1 1 1 Variable_2 ns=1;i=9396 0 Severity i=46 i=68 i=78 9396 i=5 -1 1 1 Variable_2 ns=1;i=11578 0 ConditionClassId i=46 i=68 i=78 11578 i=17 -1 1 1 Variable_2 ns=1;i=11579 0 ConditionClassName i=46 i=68 i=78 11579 i=21 -1 1 1 Variable_2 ns=1;i=11557 0 ConditionName i=46 i=68 i=78 11557 i=12 -1 1 1 Variable_2 ns=1;i=9397 0 BranchId i=46 i=68 i=78 9397 i=17 -1 1 1 Variable_2 ns=1;i=9398 0 Retain i=46 i=68 i=78 9398 i=1 -1 1 1 Variable_2 ns=1;i=9399 0 EnabledState i=47 i=8995 i=78 9399 i=21 -1 1 1 Variable_2 ns=1;i=9400 0 Id i=46 i=68 i=78 9400 i=1 -1 1 1 Variable_2 ns=1;i=9405 0 Quality i=47 i=9002 i=78 9405 i=19 -1 1 1 Variable_2 ns=1;i=9406 0 SourceTimestamp i=46 i=68 i=78 9406 i=294 -1 1 1 Variable_2 ns=1;i=9409 0 LastSeverity i=47 i=9002 i=78 9409 i=5 -1 1 1 Variable_2 ns=1;i=9410 0 SourceTimestamp i=46 i=68 i=78 9410 i=294 -1 1 1 Variable_2 ns=1;i=9411 0 Comment i=47 i=9002 i=78 9411 i=21 -1 1 1 Variable_2 ns=1;i=9412 0 SourceTimestamp i=46 i=68 i=78 9412 i=294 -1 1 1 Variable_2 ns=1;i=9413 0 ClientUserId i=46 i=68 i=78 9413 i=12 -1 1 1 Method_4 ns=1;i=9415 0 Disable i=47 i=9028 i=78 9415 true true i=3065 i=2803 Method_4 ns=1;i=9414 0 Enable i=47 i=9027 i=78 9414 true true i=3065 i=2803 Method_4 ns=1;i=9416 0 AddComment i=47 i=9029 i=78 9416 true true i=3065 i=2829 Variable_2 ns=1;i=9417 0 InputArguments i=46 i=68 i=78 9417 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=9420 0 AckedState i=47 i=8995 i=78 9420 i=21 -1 1 1 Variable_2 ns=1;i=9421 0 Id i=46 i=68 i=78 9421 i=1 -1 1 1 Method_4 ns=1;i=9436 0 Acknowledge i=47 i=9111 i=78 9436 true true i=3065 i=8944 Variable_2 ns=1;i=9437 0 InputArguments i=46 i=68 i=78 9437 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 DataType_64 ns=1;i=9440 1 ScalarValueDataType i=22 i=14798 i=22 Structure_0 BooleanValue i=1 -1 0 false SByteValue i=2 -1 0 false ByteValue i=3 -1 0 false Int16Value i=4 -1 0 false UInt16Value i=5 -1 0 false Int32Value i=6 -1 0 false UInt32Value i=7 -1 0 false Int64Value i=8 -1 0 false UInt64Value i=9 -1 0 false FloatValue i=10 -1 0 false DoubleValue i=11 -1 0 false StringValue i=12 -1 0 false DateTimeValue i=13 -1 0 false GuidValue i=14 -1 0 false ByteStringValue i=15 -1 0 false XmlElementValue i=16 -1 0 false NodeIdValue i=17 -1 0 false ExpandedNodeIdValue i=18 -1 0 false QualifiedNameValue i=20 -1 0 false LocalizedTextValue i=21 -1 0 false StatusCodeValue i=19 -1 0 false VariantValue i=24 -1 0 false EnumerationValue i=29 -1 0 false StructureValue i=22 -1 0 false Number i=26 -1 0 false Integer i=27 -1 0 false UInteger i=28 -1 0 false ObjectType_8 ns=1;i=9450 1 ScalarValueObjectType ns=1;i=9383 Variable_2 ns=1;i=9507 1 BooleanValue i=47 i=63 i=78 9507 i=1 -1 1 1 Variable_2 ns=1;i=9508 1 SByteValue i=47 i=63 i=78 9508 i=2 -1 1 1 Variable_2 ns=1;i=9509 1 ByteValue i=47 i=63 i=78 9509 i=3 -1 1 1 Variable_2 ns=1;i=9510 1 Int16Value i=47 i=63 i=78 9510 i=4 -1 1 1 Variable_2 ns=1;i=9511 1 UInt16Value i=47 i=63 i=78 9511 i=5 -1 1 1 Variable_2 ns=1;i=9512 1 Int32Value i=47 i=63 i=78 9512 i=6 -1 1 1 Variable_2 ns=1;i=9513 1 UInt32Value i=47 i=63 i=78 9513 i=7 -1 1 1 Variable_2 ns=1;i=9514 1 Int64Value i=47 i=63 i=78 9514 i=8 -1 1 1 Variable_2 ns=1;i=9515 1 UInt64Value i=47 i=63 i=78 9515 i=9 -1 1 1 Variable_2 ns=1;i=9516 1 FloatValue i=47 i=63 i=78 9516 i=10 -1 1 1 Variable_2 ns=1;i=9517 1 DoubleValue i=47 i=63 i=78 9517 i=11 -1 1 1 Variable_2 ns=1;i=9518 1 StringValue i=47 i=63 i=78 9518 i=12 -1 1 1 Variable_2 ns=1;i=9519 1 DateTimeValue i=47 i=63 i=78 9519 i=13 -1 1 1 Variable_2 ns=1;i=9520 1 GuidValue i=47 i=63 i=78 9520 i=14 -1 1 1 Variable_2 ns=1;i=9521 1 ByteStringValue i=47 i=63 i=78 9521 i=15 -1 1 1 Variable_2 ns=1;i=9522 1 XmlElementValue i=47 i=63 i=78 9522 i=16 -1 1 1 Variable_2 ns=1;i=9523 1 NodeIdValue i=47 i=63 i=78 9523 i=17 -1 1 1 Variable_2 ns=1;i=9524 1 ExpandedNodeIdValue i=47 i=63 i=78 9524 i=18 -1 1 1 Variable_2 ns=1;i=9525 1 QualifiedNameValue i=47 i=63 i=78 9525 i=20 -1 1 1 Variable_2 ns=1;i=9526 1 LocalizedTextValue i=47 i=63 i=78 9526 i=21 -1 1 1 Variable_2 ns=1;i=9527 1 StatusCodeValue i=47 i=63 i=78 9527 i=19 -1 1 1 Variable_2 ns=1;i=9528 1 VariantValue i=47 i=63 i=78 9528 i=24 -1 1 1 Variable_2 ns=1;i=9529 1 EnumerationValue i=47 i=63 i=78 9529 i=29 -1 1 1 Variable_2 ns=1;i=9530 1 StructureValue i=47 i=63 i=78 9530 i=22 -1 1 1 Variable_2 ns=1;i=9531 1 NumberValue i=47 i=63 i=78 9531 i=26 -1 1 1 Variable_2 ns=1;i=9532 1 IntegerValue i=47 i=63 i=78 9532 i=27 -1 1 1 Variable_2 ns=1;i=9533 1 UIntegerValue i=47 i=63 i=78 9533 i=28 -1 1 1 ObjectType_8 ns=1;i=9534 1 AnalogScalarValueObjectType ns=1;i=9383 Variable_2 ns=1;i=9591 1 SByteValue i=47 i=2368 i=78 9591 i=2 -1 1 1 Variable_2 ns=1;i=9594 0 EURange i=46 i=68 i=78 9594 i=884 -1 1 1 Variable_2 ns=1;i=9597 1 ByteValue i=47 i=2368 i=78 9597 i=3 -1 1 1 Variable_2 ns=1;i=9600 0 EURange i=46 i=68 i=78 9600 i=884 -1 1 1 Variable_2 ns=1;i=9603 1 Int16Value i=47 i=2368 i=78 9603 i=4 -1 1 1 Variable_2 ns=1;i=9606 0 EURange i=46 i=68 i=78 9606 i=884 -1 1 1 Variable_2 ns=1;i=9609 1 UInt16Value i=47 i=2368 i=78 9609 i=5 -1 1 1 Variable_2 ns=1;i=9612 0 EURange i=46 i=68 i=78 9612 i=884 -1 1 1 Variable_2 ns=1;i=9615 1 Int32Value i=47 i=2368 i=78 9615 i=6 -1 1 1 Variable_2 ns=1;i=9618 0 EURange i=46 i=68 i=78 9618 i=884 -1 1 1 Variable_2 ns=1;i=9621 1 UInt32Value i=47 i=2368 i=78 9621 i=7 -1 1 1 Variable_2 ns=1;i=9624 0 EURange i=46 i=68 i=78 9624 i=884 -1 1 1 Variable_2 ns=1;i=9627 1 Int64Value i=47 i=2368 i=78 9627 i=8 -1 1 1 Variable_2 ns=1;i=9630 0 EURange i=46 i=68 i=78 9630 i=884 -1 1 1 Variable_2 ns=1;i=9633 1 UInt64Value i=47 i=2368 i=78 9633 i=9 -1 1 1 Variable_2 ns=1;i=9636 0 EURange i=46 i=68 i=78 9636 i=884 -1 1 1 Variable_2 ns=1;i=9639 1 FloatValue i=47 i=2368 i=78 9639 i=10 -1 1 1 Variable_2 ns=1;i=9642 0 EURange i=46 i=68 i=78 9642 i=884 -1 1 1 Variable_2 ns=1;i=9645 1 DoubleValue i=47 i=2368 i=78 9645 i=11 -1 1 1 Variable_2 ns=1;i=9648 0 EURange i=46 i=68 i=78 9648 i=884 -1 1 1 Variable_2 ns=1;i=9651 1 NumberValue i=47 i=2368 i=78 9651 i=26 -1 1 1 Variable_2 ns=1;i=9654 0 EURange i=46 i=68 i=78 9654 i=884 -1 1 1 Variable_2 ns=1;i=9657 1 IntegerValue i=47 i=2368 i=78 9657 i=27 -1 1 1 Variable_2 ns=1;i=9660 0 EURange i=46 i=68 i=78 9660 i=884 -1 1 1 Variable_2 ns=1;i=9663 1 UIntegerValue i=47 i=2368 i=78 9663 i=28 -1 1 1 Variable_2 ns=1;i=9666 0 EURange i=46 i=68 i=78 9666 i=884 -1 1 1 DataType_64 ns=1;i=9669 1 ArrayValueDataType i=22 i=14798 i=22 Structure_0 BooleanValue i=1 1 0 0 false SByteValue i=2 1 0 0 false ByteValue i=3 1 0 0 false Int16Value i=4 1 0 0 false UInt16Value i=5 1 0 0 false Int32Value i=6 1 0 0 false UInt32Value i=7 1 0 0 false Int64Value i=8 1 0 0 false UInt64Value i=9 1 0 0 false FloatValue i=10 1 0 0 false DoubleValue i=11 1 0 0 false StringValue i=12 1 0 0 false DateTimeValue i=13 1 0 0 false GuidValue i=14 1 0 0 false ByteStringValue i=15 1 0 0 false XmlElementValue i=16 1 0 0 false NodeIdValue i=17 1 0 0 false ExpandedNodeIdValue i=18 1 0 0 false QualifiedNameValue i=20 1 0 0 false LocalizedTextValue i=21 1 0 0 false StatusCodeValue i=19 1 0 0 false VariantValue i=24 1 0 0 false EnumerationValue i=29 1 0 0 false StructureValue i=22 1 0 0 false Number i=26 1 0 0 false Integer i=27 1 0 0 false UInteger i=28 1 0 0 false ObjectType_8 ns=1;i=9679 1 ArrayValueObjectType ns=1;i=9383 Variable_2 ns=1;i=9736 1 BooleanValue i=47 i=63 i=78 9736 i=1 1 0 1 1 Variable_2 ns=1;i=9737 1 SByteValue i=47 i=63 i=78 9737 i=2 1 0 1 1 Variable_2 ns=1;i=9738 1 ByteValue i=47 i=63 i=78 9738 i=3 1 0 1 1 Variable_2 ns=1;i=9739 1 Int16Value i=47 i=63 i=78 9739 i=4 1 0 1 1 Variable_2 ns=1;i=9740 1 UInt16Value i=47 i=63 i=78 9740 i=5 1 0 1 1 Variable_2 ns=1;i=9741 1 Int32Value i=47 i=63 i=78 9741 i=6 1 0 1 1 Variable_2 ns=1;i=9742 1 UInt32Value i=47 i=63 i=78 9742 i=7 1 0 1 1 Variable_2 ns=1;i=9743 1 Int64Value i=47 i=63 i=78 9743 i=8 1 0 1 1 Variable_2 ns=1;i=9744 1 UInt64Value i=47 i=63 i=78 9744 i=9 1 0 1 1 Variable_2 ns=1;i=9745 1 FloatValue i=47 i=63 i=78 9745 i=10 1 0 1 1 Variable_2 ns=1;i=9746 1 DoubleValue i=47 i=63 i=78 9746 i=11 1 0 1 1 Variable_2 ns=1;i=9747 1 StringValue i=47 i=63 i=78 9747 i=12 1 0 1 1 Variable_2 ns=1;i=9748 1 DateTimeValue i=47 i=63 i=78 9748 i=13 1 0 1 1 Variable_2 ns=1;i=9749 1 GuidValue i=47 i=63 i=78 9749 i=14 1 0 1 1 Variable_2 ns=1;i=9750 1 ByteStringValue i=47 i=63 i=78 9750 i=15 1 0 1 1 Variable_2 ns=1;i=9751 1 XmlElementValue i=47 i=63 i=78 9751 i=16 1 0 1 1 Variable_2 ns=1;i=9752 1 NodeIdValue i=47 i=63 i=78 9752 i=17 1 0 1 1 Variable_2 ns=1;i=9753 1 ExpandedNodeIdValue i=47 i=63 i=78 9753 i=18 1 0 1 1 Variable_2 ns=1;i=9754 1 QualifiedNameValue i=47 i=63 i=78 9754 i=20 1 0 1 1 Variable_2 ns=1;i=9755 1 LocalizedTextValue i=47 i=63 i=78 9755 i=21 1 0 1 1 Variable_2 ns=1;i=9756 1 StatusCodeValue i=47 i=63 i=78 9756 i=19 1 0 1 1 Variable_2 ns=1;i=9757 1 VariantValue i=47 i=63 i=78 9757 i=24 1 0 1 1 Variable_2 ns=1;i=9758 1 EnumerationValue i=47 i=63 i=78 9758 i=29 1 0 1 1 Variable_2 ns=1;i=9759 1 StructureValue i=47 i=63 i=78 9759 i=22 1 0 1 1 Variable_2 ns=1;i=9760 1 NumberValue i=47 i=63 i=78 9760 i=26 1 0 1 1 Variable_2 ns=1;i=9761 1 IntegerValue i=47 i=63 i=78 9761 i=27 1 0 1 1 Variable_2 ns=1;i=9762 1 UIntegerValue i=47 i=63 i=78 9762 i=28 1 0 1 1 ObjectType_8 ns=1;i=9763 1 AnalogArrayValueObjectType ns=1;i=9383 Variable_2 ns=1;i=9820 1 SByteValue i=47 i=2368 i=78 9820 i=2 1 0 1 1 Variable_2 ns=1;i=9823 0 EURange i=46 i=68 i=78 9823 i=884 -1 1 1 Variable_2 ns=1;i=9826 1 ByteValue i=47 i=2368 i=78 9826 i=3 1 0 1 1 Variable_2 ns=1;i=9829 0 EURange i=46 i=68 i=78 9829 i=884 -1 1 1 Variable_2 ns=1;i=9832 1 Int16Value i=47 i=2368 i=78 9832 i=4 1 0 1 1 Variable_2 ns=1;i=9835 0 EURange i=46 i=68 i=78 9835 i=884 -1 1 1 Variable_2 ns=1;i=9838 1 UInt16Value i=47 i=2368 i=78 9838 i=5 1 0 1 1 Variable_2 ns=1;i=9841 0 EURange i=46 i=68 i=78 9841 i=884 -1 1 1 Variable_2 ns=1;i=9844 1 Int32Value i=47 i=2368 i=78 9844 i=6 1 0 1 1 Variable_2 ns=1;i=9847 0 EURange i=46 i=68 i=78 9847 i=884 -1 1 1 Variable_2 ns=1;i=9850 1 UInt32Value i=47 i=2368 i=78 9850 i=7 1 0 1 1 Variable_2 ns=1;i=9853 0 EURange i=46 i=68 i=78 9853 i=884 -1 1 1 Variable_2 ns=1;i=9856 1 Int64Value i=47 i=2368 i=78 9856 i=8 1 0 1 1 Variable_2 ns=1;i=9859 0 EURange i=46 i=68 i=78 9859 i=884 -1 1 1 Variable_2 ns=1;i=9862 1 UInt64Value i=47 i=2368 i=78 9862 i=9 1 0 1 1 Variable_2 ns=1;i=9865 0 EURange i=46 i=68 i=78 9865 i=884 -1 1 1 Variable_2 ns=1;i=9868 1 FloatValue i=47 i=2368 i=78 9868 i=10 1 0 1 1 Variable_2 ns=1;i=9871 0 EURange i=46 i=68 i=78 9871 i=884 -1 1 1 Variable_2 ns=1;i=9874 1 DoubleValue i=47 i=2368 i=78 9874 i=11 1 0 1 1 Variable_2 ns=1;i=9877 0 EURange i=46 i=68 i=78 9877 i=884 -1 1 1 Variable_2 ns=1;i=9880 1 NumberValue i=47 i=2368 i=78 9880 i=26 1 0 1 1 Variable_2 ns=1;i=9883 0 EURange i=46 i=68 i=78 9883 i=884 -1 1 1 Variable_2 ns=1;i=9886 1 IntegerValue i=47 i=2368 i=78 9886 i=27 1 0 1 1 Variable_2 ns=1;i=9889 0 EURange i=46 i=68 i=78 9889 i=884 -1 1 1 Variable_2 ns=1;i=9892 1 UIntegerValue i=47 i=2368 i=78 9892 i=28 1 0 1 1 Variable_2 ns=1;i=9895 0 EURange i=46 i=68 i=78 9895 i=884 -1 1 1 DataType_64 ns=1;i=9898 1 BooleanDataType i=1 DataType_64 ns=1;i=9899 1 SByteDataType i=2 DataType_64 ns=1;i=9900 1 ByteDataType i=3 DataType_64 ns=1;i=9901 1 Int16DataType i=4 DataType_64 ns=1;i=9902 1 UInt16DataType i=5 DataType_64 ns=1;i=9903 1 Int32DataType i=6 DataType_64 ns=1;i=9904 1 UInt32DataType i=7 DataType_64 ns=1;i=9905 1 Int64DataType i=8 DataType_64 ns=1;i=9906 1 UInt64DataType i=9 DataType_64 ns=1;i=9907 1 FloatDataType i=10 DataType_64 ns=1;i=9908 1 DoubleDataType i=11 DataType_64 ns=1;i=9909 1 StringDataType i=12 DataType_64 ns=1;i=9910 1 DateTimeDataType i=13 DataType_64 ns=1;i=9911 1 GuidDataType i=14 DataType_64 ns=1;i=9912 1 ByteStringDataType i=15 DataType_64 ns=1;i=9913 1 XmlElementDataType i=16 DataType_64 ns=1;i=9914 1 NodeIdDataType i=17 DataType_64 ns=1;i=9915 1 ExpandedNodeIdDataType i=18 DataType_64 ns=1;i=9916 1 QualifiedNameDataType i=20 DataType_64 ns=1;i=9917 1 LocalizedTextDataType i=21 DataType_64 ns=1;i=9918 1 StatusCodeDataType i=19 DataType_64 ns=1;i=9919 1 VariantDataType i=24 DataType_64 ns=1;i=9920 1 UserScalarValueDataType i=22 i=14798 i=22 Structure_0 BooleanDataType ns=1;i=9898 -1 0 false SByteDataType ns=1;i=9899 -1 0 false ByteDataType ns=1;i=9900 -1 0 false Int16DataType ns=1;i=9901 -1 0 false UInt16DataType ns=1;i=9902 -1 0 false Int32DataType ns=1;i=9903 -1 0 false UInt32DataType ns=1;i=9904 -1 0 false Int64DataType ns=1;i=9905 -1 0 false UInt64DataType ns=1;i=9906 -1 0 false FloatDataType ns=1;i=9907 -1 0 false DoubleDataType ns=1;i=9908 -1 0 false StringDataType ns=1;i=9909 -1 0 false DateTimeDataType ns=1;i=9910 -1 0 false GuidDataType ns=1;i=9911 -1 0 false ByteStringDataType ns=1;i=9912 -1 0 false XmlElementDataType ns=1;i=9913 -1 0 false NodeIdDataType ns=1;i=9914 -1 0 false ExpandedNodeIdDataType ns=1;i=9915 -1 0 false QualifiedNameDataType ns=1;i=9916 -1 0 false LocalizedTextDataType ns=1;i=9917 -1 0 false StatusCodeDataType ns=1;i=9918 -1 0 false VariantDataType ns=1;i=9919 -1 0 false ObjectType_8 ns=1;i=9921 1 UserScalarValueObjectType ns=1;i=9383 Variable_2 ns=1;i=9978 1 BooleanValue i=47 i=63 i=78 9978 ns=1;i=9898 -1 1 1 Variable_2 ns=1;i=9979 1 SByteValue i=47 i=63 i=78 9979 ns=1;i=9899 -1 1 1 Variable_2 ns=1;i=9980 1 ByteValue i=47 i=63 i=78 9980 ns=1;i=9900 -1 1 1 Variable_2 ns=1;i=9981 1 Int16Value i=47 i=63 i=78 9981 ns=1;i=9901 -1 1 1 Variable_2 ns=1;i=9982 1 UInt16Value i=47 i=63 i=78 9982 ns=1;i=9902 -1 1 1 Variable_2 ns=1;i=9983 1 Int32Value i=47 i=63 i=78 9983 ns=1;i=9903 -1 1 1 Variable_2 ns=1;i=9984 1 UInt32Value i=47 i=63 i=78 9984 ns=1;i=9904 -1 1 1 Variable_2 ns=1;i=9985 1 Int64Value i=47 i=63 i=78 9985 ns=1;i=9905 -1 1 1 Variable_2 ns=1;i=9986 1 UInt64Value i=47 i=63 i=78 9986 ns=1;i=9906 -1 1 1 Variable_2 ns=1;i=9987 1 FloatValue i=47 i=63 i=78 9987 ns=1;i=9907 -1 1 1 Variable_2 ns=1;i=9988 1 DoubleValue i=47 i=63 i=78 9988 ns=1;i=9908 -1 1 1 Variable_2 ns=1;i=9989 1 StringValue i=47 i=63 i=78 9989 ns=1;i=9909 -1 1 1 Variable_2 ns=1;i=9990 1 DateTimeValue i=47 i=63 i=78 9990 ns=1;i=9910 -1 1 1 Variable_2 ns=1;i=9991 1 GuidValue i=47 i=63 i=78 9991 ns=1;i=9911 -1 1 1 Variable_2 ns=1;i=9992 1 ByteStringValue i=47 i=63 i=78 9992 ns=1;i=9912 -1 1 1 Variable_2 ns=1;i=9993 1 XmlElementValue i=47 i=63 i=78 9993 ns=1;i=9913 -1 1 1 Variable_2 ns=1;i=9994 1 NodeIdValue i=47 i=63 i=78 9994 ns=1;i=9914 -1 1 1 Variable_2 ns=1;i=9995 1 ExpandedNodeIdValue i=47 i=63 i=78 9995 ns=1;i=9915 -1 1 1 Variable_2 ns=1;i=9996 1 QualifiedNameValue i=47 i=63 i=78 9996 ns=1;i=9916 -1 1 1 Variable_2 ns=1;i=9997 1 LocalizedTextValue i=47 i=63 i=78 9997 ns=1;i=9917 -1 1 1 Variable_2 ns=1;i=9998 1 StatusCodeValue i=47 i=63 i=78 9998 ns=1;i=9918 -1 1 1 Variable_2 ns=1;i=9999 1 VariantValue i=47 i=63 i=78 9999 ns=1;i=9919 -1 1 1 DataType_64 ns=1;i=10006 1 UserArrayValueDataType i=22 i=14798 i=22 Structure_0 BooleanDataType ns=1;i=9898 1 0 0 false SByteDataType ns=1;i=9899 1 0 0 false ByteDataType ns=1;i=9900 1 0 0 false Int16DataType ns=1;i=9901 1 0 0 false UInt16DataType ns=1;i=9902 1 0 0 false Int32DataType ns=1;i=9903 1 0 0 false UInt32DataType ns=1;i=9904 1 0 0 false Int64DataType ns=1;i=9905 1 0 0 false UInt64DataType ns=1;i=9906 1 0 0 false FloatDataType ns=1;i=9907 1 0 0 false DoubleDataType ns=1;i=9908 1 0 0 false StringDataType ns=1;i=9909 1 0 0 false DateTimeDataType ns=1;i=9910 1 0 0 false GuidDataType ns=1;i=9911 1 0 0 false ByteStringDataType ns=1;i=9912 1 0 0 false XmlElementDataType ns=1;i=9913 1 0 0 false NodeIdDataType ns=1;i=9914 1 0 0 false ExpandedNodeIdDataType ns=1;i=9915 1 0 0 false QualifiedNameDataType ns=1;i=9916 1 0 0 false LocalizedTextDataType ns=1;i=9917 1 0 0 false StatusCodeDataType ns=1;i=9918 1 0 0 false VariantDataType ns=1;i=9919 1 0 0 false ObjectType_8 ns=1;i=10007 1 UserArrayValueObjectType ns=1;i=9383 Variable_2 ns=1;i=10064 1 BooleanValue i=47 i=63 i=78 10064 ns=1;i=9898 1 0 1 1 Variable_2 ns=1;i=10065 1 SByteValue i=47 i=63 i=78 10065 ns=1;i=9899 1 0 1 1 Variable_2 ns=1;i=10066 1 ByteValue i=47 i=63 i=78 10066 ns=1;i=9900 1 0 1 1 Variable_2 ns=1;i=10067 1 Int16Value i=47 i=63 i=78 10067 ns=1;i=9901 1 0 1 1 Variable_2 ns=1;i=10068 1 UInt16Value i=47 i=63 i=78 10068 ns=1;i=9902 1 0 1 1 Variable_2 ns=1;i=10069 1 Int32Value i=47 i=63 i=78 10069 ns=1;i=9903 1 0 1 1 Variable_2 ns=1;i=10070 1 UInt32Value i=47 i=63 i=78 10070 ns=1;i=9904 1 0 1 1 Variable_2 ns=1;i=10071 1 Int64Value i=47 i=63 i=78 10071 ns=1;i=9905 1 0 1 1 Variable_2 ns=1;i=10072 1 UInt64Value i=47 i=63 i=78 10072 ns=1;i=9906 1 0 1 1 Variable_2 ns=1;i=10073 1 FloatValue i=47 i=63 i=78 10073 ns=1;i=9907 1 0 1 1 Variable_2 ns=1;i=10074 1 DoubleValue i=47 i=63 i=78 10074 ns=1;i=9908 1 0 1 1 Variable_2 ns=1;i=10075 1 StringValue i=47 i=63 i=78 10075 ns=1;i=9909 1 0 1 1 Variable_2 ns=1;i=10076 1 DateTimeValue i=47 i=63 i=78 10076 ns=1;i=9910 1 0 1 1 Variable_2 ns=1;i=10077 1 GuidValue i=47 i=63 i=78 10077 ns=1;i=9911 1 0 1 1 Variable_2 ns=1;i=10078 1 ByteStringValue i=47 i=63 i=78 10078 ns=1;i=9912 1 0 1 1 Variable_2 ns=1;i=10079 1 XmlElementValue i=47 i=63 i=78 10079 ns=1;i=9913 1 0 1 1 Variable_2 ns=1;i=10080 1 NodeIdValue i=47 i=63 i=78 10080 ns=1;i=9914 1 0 1 1 Variable_2 ns=1;i=10081 1 ExpandedNodeIdValue i=47 i=63 i=78 10081 ns=1;i=9915 1 0 1 1 Variable_2 ns=1;i=10082 1 QualifiedNameValue i=47 i=63 i=78 10082 ns=1;i=9916 1 0 1 1 Variable_2 ns=1;i=10083 1 LocalizedTextValue i=47 i=63 i=78 10083 ns=1;i=9917 1 0 1 1 Variable_2 ns=1;i=10084 1 StatusCodeValue i=47 i=63 i=78 10084 ns=1;i=9918 1 0 1 1 Variable_2 ns=1;i=10085 1 VariantValue i=47 i=63 i=78 10085 ns=1;i=9919 1 0 1 1 DataType_64 ns=1;i=1000 1 Vector i=22 i=14798 i=22 Structure_0 X i=11 -1 0 false Y i=11 -1 0 false Z i=11 -1 0 false DataType_64 ns=1;i=1004 1 WorkOrderStatusType i=22 i=14798 i=22 Structure_0 Actor i=12 -1 0 false Timestamp i=13 -1 0 false Comment i=21 -1 0 false DataType_64 ns=1;i=1005 1 WorkOrderType i=22 i=14798 i=22 Structure_0 ID i=14 -1 0 false AssetID i=12 -1 0 false StartTime i=13 -1 0 false StatusComments ns=1;i=1004 1 0 0 false ObjectType_8 ns=1;i=10092 1 MethodTestType i=61 Method_4 ns=1;i=10093 1 ScalarMethod1 i=47 ns=1;i=10093 i=78 10093 true true Variable_2 ns=1;i=10094 0 InputArguments i=46 i=68 i=78 10094 i=297 BooleanIn i=1 -1 i=297 SByteIn i=2 -1 i=297 ByteIn i=3 -1 i=297 Int16In i=4 -1 i=297 UInt16In i=5 -1 i=297 Int32In i=6 -1 i=297 UInt32In i=7 -1 i=297 Int64In i=8 -1 i=297 UInt64In i=9 -1 i=297 FloatIn i=10 -1 i=297 DoubleIn i=11 -1 i=296 1 0 1 1 Variable_2 ns=1;i=10095 0 OutputArguments i=46 i=68 i=78 10095 i=297 BooleanOut i=1 -1 i=297 SByteOut i=2 -1 i=297 ByteOut i=3 -1 i=297 Int16Out i=4 -1 i=297 UInt16Out i=5 -1 i=297 Int32Out i=6 -1 i=297 UInt32Out i=7 -1 i=297 Int64Out i=8 -1 i=297 UInt64Out i=9 -1 i=297 FloatOut i=10 -1 i=297 DoubleOut i=11 -1 i=296 1 0 1 1 Method_4 ns=1;i=10096 1 ScalarMethod2 i=47 ns=1;i=10096 i=78 10096 true true Variable_2 ns=1;i=10097 0 InputArguments i=46 i=68 i=78 10097 i=297 StringIn i=12 -1 i=297 DateTimeIn i=13 -1 i=297 GuidIn i=14 -1 i=297 ByteStringIn i=15 -1 i=297 XmlElementIn i=16 -1 i=297 NodeIdIn i=17 -1 i=297 ExpandedNodeIdIn i=18 -1 i=297 QualifiedNameIn i=20 -1 i=297 LocalizedTextIn i=21 -1 i=297 StatusCodeIn i=19 -1 i=296 1 0 1 1 Variable_2 ns=1;i=10098 0 OutputArguments i=46 i=68 i=78 10098 i=297 StringOut i=12 -1 i=297 DateTimeOut i=13 -1 i=297 GuidOut i=14 -1 i=297 ByteStringOut i=15 -1 i=297 XmlElementOut i=16 -1 i=297 NodeIdOut i=17 -1 i=297 ExpandedNodeIdOut i=18 -1 i=297 QualifiedNameOut i=20 -1 i=297 LocalizedTextOut i=21 -1 i=297 StatusCodeOut i=19 -1 i=296 1 0 1 1 Method_4 ns=1;i=10099 1 ScalarMethod3 i=47 ns=1;i=10099 i=78 10099 true true Variable_2 ns=1;i=10100 0 InputArguments i=46 i=68 i=78 10100 i=297 VariantIn i=24 -1 i=297 EnumerationIn i=29 -1 i=297 StructureIn i=22 -1 i=296 1 0 1 1 Variable_2 ns=1;i=10101 0 OutputArguments i=46 i=68 i=78 10101 i=297 VariantOut i=24 -1 i=297 EnumerationOut i=29 -1 i=297 StructureOut i=22 -1 i=296 1 0 1 1 Method_4 ns=1;i=10102 1 ArrayMethod1 i=47 ns=1;i=10102 i=78 10102 true true Variable_2 ns=1;i=10103 0 InputArguments i=46 i=68 i=78 10103 i=297 BooleanIn i=1 1 0 i=297 SByteIn i=2 1 0 i=297 ByteIn i=3 1 0 i=297 Int16In i=4 1 0 i=297 UInt16In i=5 1 0 i=297 Int32In i=6 1 0 i=297 UInt32In i=7 1 0 i=297 Int64In i=8 1 0 i=297 UInt64In i=9 1 0 i=297 FloatIn i=10 1 0 i=297 DoubleIn i=11 1 0 i=296 1 0 1 1 Variable_2 ns=1;i=10104 0 OutputArguments i=46 i=68 i=78 10104 i=297 BooleanOut i=1 1 0 i=297 SByteOut i=2 1 0 i=297 ByteOut i=3 1 0 i=297 Int16Out i=4 1 0 i=297 UInt16Out i=5 1 0 i=297 Int32Out i=6 1 0 i=297 UInt32Out i=7 1 0 i=297 Int64Out i=8 1 0 i=297 UInt64Out i=9 1 0 i=297 FloatOut i=10 1 0 i=297 DoubleOut i=11 1 0 i=296 1 0 1 1 Method_4 ns=1;i=10105 1 ArrayMethod2 i=47 ns=1;i=10105 i=78 10105 true true Variable_2 ns=1;i=10106 0 InputArguments i=46 i=68 i=78 10106 i=297 StringIn i=12 1 0 i=297 DateTimeIn i=13 1 0 i=297 GuidIn i=14 1 0 i=297 ByteStringIn i=15 1 0 i=297 XmlElementIn i=16 1 0 i=297 NodeIdIn i=17 1 0 i=297 ExpandedNodeIdIn i=18 1 0 i=297 QualifiedNameIn i=20 1 0 i=297 LocalizedTextIn i=21 1 0 i=297 StatusCodeIn i=19 1 0 i=296 1 0 1 1 Variable_2 ns=1;i=10107 0 OutputArguments i=46 i=68 i=78 10107 i=297 StringOut i=12 1 0 i=297 DateTimeOut i=13 1 0 i=297 GuidOut i=14 1 0 i=297 ByteStringOut i=15 1 0 i=297 XmlElementOut i=16 1 0 i=297 NodeIdOut i=17 1 0 i=297 ExpandedNodeIdOut i=18 1 0 i=297 QualifiedNameOut i=20 1 0 i=297 LocalizedTextOut i=21 1 0 i=297 StatusCodeOut i=19 1 0 i=296 1 0 1 1 Method_4 ns=1;i=10108 1 ArrayMethod3 i=47 ns=1;i=10108 i=78 10108 true true Variable_2 ns=1;i=10109 0 InputArguments i=46 i=68 i=78 10109 i=297 VariantIn i=24 1 0 i=297 EnumerationIn i=29 1 0 i=297 StructureIn i=22 1 0 i=296 1 0 1 1 Variable_2 ns=1;i=10110 0 OutputArguments i=46 i=68 i=78 10110 i=297 VariantOut i=24 1 0 i=297 EnumerationOut i=29 1 0 i=297 StructureOut i=22 1 0 i=296 1 0 1 1 Method_4 ns=1;i=10111 1 UserScalarMethod1 i=47 ns=1;i=10111 i=78 10111 true true Variable_2 ns=1;i=10112 0 InputArguments i=46 i=68 i=78 10112 i=297 BooleanIn ns=1;i=9898 -1 i=297 SByteIn ns=1;i=9899 -1 i=297 ByteIn ns=1;i=9900 -1 i=297 Int16In ns=1;i=9901 -1 i=297 UInt16In ns=1;i=9902 -1 i=297 Int32In ns=1;i=9903 -1 i=297 UInt32In ns=1;i=9904 -1 i=297 Int64In ns=1;i=9905 -1 i=297 UInt64In ns=1;i=9906 -1 i=297 FloatIn ns=1;i=9907 -1 i=297 DoubleIn ns=1;i=9908 -1 i=297 StringIn ns=1;i=9909 -1 i=296 1 0 1 1 Variable_2 ns=1;i=10113 0 OutputArguments i=46 i=68 i=78 10113 i=297 BooleanOut ns=1;i=9898 -1 i=297 SByteOut ns=1;i=9899 -1 i=297 ByteOut ns=1;i=9900 -1 i=297 Int16Out ns=1;i=9901 -1 i=297 UInt16Out ns=1;i=9902 -1 i=297 Int32Out ns=1;i=9903 -1 i=297 UInt32Out ns=1;i=9904 -1 i=297 Int64Out ns=1;i=9905 -1 i=297 UInt64Out ns=1;i=9906 -1 i=297 FloatOut ns=1;i=9907 -1 i=297 DoubleOut ns=1;i=9908 -1 i=297 StringOut ns=1;i=9909 -1 i=296 1 0 1 1 Method_4 ns=1;i=10114 1 UserScalarMethod2 i=47 ns=1;i=10114 i=78 10114 true true Variable_2 ns=1;i=10115 0 InputArguments i=46 i=68 i=78 10115 i=297 DateTimeIn ns=1;i=9910 -1 i=297 GuidIn ns=1;i=9911 -1 i=297 ByteStringIn ns=1;i=9912 -1 i=297 XmlElementIn ns=1;i=9913 -1 i=297 NodeIdIn ns=1;i=9914 -1 i=297 ExpandedNodeIdIn ns=1;i=9915 -1 i=297 QualifiedNameIn ns=1;i=9916 -1 i=297 LocalizedTextIn ns=1;i=9917 -1 i=297 StatusCodeIn ns=1;i=9918 -1 i=297 VariantIn ns=1;i=9919 -1 i=296 1 0 1 1 Variable_2 ns=1;i=10116 0 OutputArguments i=46 i=68 i=78 10116 i=297 DateTimeOut ns=1;i=9910 -1 i=297 GuidOut ns=1;i=9911 -1 i=297 ByteStringOut ns=1;i=9912 -1 i=297 XmlElementOut ns=1;i=9913 -1 i=297 NodeIdOut ns=1;i=9914 -1 i=297 ExpandedNodeIdOut ns=1;i=9915 -1 i=297 QualifiedNameOut ns=1;i=9916 -1 i=297 LocalizedTextOut ns=1;i=9917 -1 i=297 StatusCodeOut ns=1;i=9918 -1 i=297 VariantOut ns=1;i=9919 -1 i=296 1 0 1 1 Method_4 ns=1;i=10117 1 UserArrayMethod1 i=47 ns=1;i=10117 i=78 10117 true true Variable_2 ns=1;i=10118 0 InputArguments i=46 i=68 i=78 10118 i=297 BooleanIn ns=1;i=9898 1 0 i=297 SByteIn ns=1;i=9899 1 0 i=297 ByteIn ns=1;i=9900 1 0 i=297 Int16In ns=1;i=9901 1 0 i=297 UInt16In ns=1;i=9902 1 0 i=297 Int32In ns=1;i=9903 1 0 i=297 UInt32In ns=1;i=9904 1 0 i=297 Int64In ns=1;i=9905 1 0 i=297 UInt64In ns=1;i=9906 1 0 i=297 FloatIn ns=1;i=9907 1 0 i=297 DoubleIn ns=1;i=9908 1 0 i=297 StringIn ns=1;i=9909 1 0 i=296 1 0 1 1 Variable_2 ns=1;i=10119 0 OutputArguments i=46 i=68 i=78 10119 i=297 BooleanOut ns=1;i=9898 1 0 i=297 SByteOut ns=1;i=9899 1 0 i=297 ByteOut ns=1;i=9900 1 0 i=297 Int16Out ns=1;i=9901 1 0 i=297 UInt16Out ns=1;i=9902 1 0 i=297 Int32Out ns=1;i=9903 1 0 i=297 UInt32Out ns=1;i=9904 1 0 i=297 Int64Out ns=1;i=9905 1 0 i=297 UInt64Out ns=1;i=9906 1 0 i=297 FloatOut ns=1;i=9907 1 0 i=297 DoubleOut ns=1;i=9908 1 0 i=297 StringOut ns=1;i=9909 1 0 i=296 1 0 1 1 Method_4 ns=1;i=10120 1 UserArrayMethod2 i=47 ns=1;i=10120 i=78 10120 true true Variable_2 ns=1;i=10121 0 InputArguments i=46 i=68 i=78 10121 i=297 DateTimeIn ns=1;i=9910 1 0 i=297 GuidIn ns=1;i=9911 1 0 i=297 ByteStringIn ns=1;i=9912 1 0 i=297 XmlElementIn ns=1;i=9913 1 0 i=297 NodeIdIn ns=1;i=9914 1 0 i=297 ExpandedNodeIdIn ns=1;i=9915 1 0 i=297 QualifiedNameIn ns=1;i=9916 1 0 i=297 LocalizedTextIn ns=1;i=9917 1 0 i=297 StatusCodeIn ns=1;i=9918 1 0 i=297 VariantIn ns=1;i=9919 1 0 i=296 1 0 1 1 Variable_2 ns=1;i=10122 0 OutputArguments i=46 i=68 i=78 10122 i=297 DateTimeOut ns=1;i=9910 1 0 i=297 GuidOut ns=1;i=9911 1 0 i=297 ByteStringOut ns=1;i=9912 1 0 i=297 XmlElementOut ns=1;i=9913 1 0 i=297 NodeIdOut ns=1;i=9914 1 0 i=297 ExpandedNodeIdOut ns=1;i=9915 1 0 i=297 QualifiedNameOut ns=1;i=9916 1 0 i=297 LocalizedTextOut ns=1;i=9917 1 0 i=297 StatusCodeOut ns=1;i=9918 1 0 i=297 VariantOut ns=1;i=9919 1 0 i=296 1 0 1 1 ObjectType_8 ns=1;i=10123 1 TestSystemConditionType i=2782 Variable_2 ns=1;i=10156 1 MonitoredNodeCount i=46 i=68 i=78 10156 i=6 -1 1 1 Object_1 ns=1;i=10157 1 Data i=47 i=61 10157 1 i=35 true i=85 i=48 true i=2253 i=48 ns=1;i=10158 i=48 ns=1;i=10786 Object_1 ns=1;i=10158 1 Static i=47 i=61 10158 1 i=48 true ns=1;i=10157 i=36 ns=1;i=10159 i=36 ns=1;i=10243 Object_1 ns=1;i=10159 1 Scalar i=47 ns=1;i=9450 10159 i=36 true ns=1;i=10158 i=36 ns=1;i=10163 Variable_2 ns=1;i=10160 1 SimulationActive If true the server will produce new values for each monitored variable. i=46 i=68 10160 i=1 -1 1 1 Method_4 ns=1;i=10161 1 GenerateValues i=47 ns=1;i=9385 10161 true true Variable_2 ns=1;i=10162 0 InputArguments i=46 i=68 10162 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 Object_1 ns=1;i=10163 1 CycleComplete i=47 i=2881 10163 i=36 true ns=1;i=10159 Variable_2 ns=1;i=10164 0 EventId i=46 i=68 10164 i=15 -1 1 1 Variable_2 ns=1;i=10165 0 EventType i=46 i=68 10165 i=17 -1 1 1 Variable_2 ns=1;i=10166 0 SourceNode i=46 i=68 10166 i=17 -1 1 1 Variable_2 ns=1;i=10167 0 SourceName i=46 i=68 10167 i=12 -1 1 1 Variable_2 ns=1;i=10169 0 ReceiveTime i=46 i=68 10169 i=294 -1 1 1 Variable_2 ns=1;i=10171 0 Message i=46 i=68 10171 i=21 -1 1 1 Variable_2 ns=1;i=10172 0 Severity i=46 i=68 10172 i=5 -1 1 1 Variable_2 ns=1;i=11594 0 ConditionClassId i=46 i=68 11594 i=17 -1 1 1 Variable_2 ns=1;i=11595 0 ConditionClassName i=46 i=68 11595 i=21 -1 1 1 Variable_2 ns=1;i=11565 0 ConditionName i=46 i=68 11565 i=12 -1 1 1 Variable_2 ns=1;i=10173 0 BranchId i=46 i=68 10173 i=17 -1 1 1 Variable_2 ns=1;i=10174 0 Retain i=46 i=68 10174 i=1 -1 1 1 Variable_2 ns=1;i=10175 0 EnabledState i=47 i=8995 10175 i=21 -1 1 1 i=9004 ns=1;i=10196 i=9004 ns=1;i=10204 Variable_2 ns=1;i=10176 0 Id i=46 i=68 10176 i=1 -1 1 1 Variable_2 ns=1;i=10181 0 Quality i=47 i=9002 10181 i=19 -1 1 1 Variable_2 ns=1;i=10182 0 SourceTimestamp i=46 i=68 10182 i=294 -1 1 1 Variable_2 ns=1;i=10185 0 LastSeverity i=47 i=9002 10185 i=5 -1 1 1 Variable_2 ns=1;i=10186 0 SourceTimestamp i=46 i=68 10186 i=294 -1 1 1 Variable_2 ns=1;i=10187 0 Comment i=47 i=9002 10187 i=21 -1 1 1 Variable_2 ns=1;i=10188 0 SourceTimestamp i=46 i=68 10188 i=294 -1 1 1 Variable_2 ns=1;i=10189 0 ClientUserId i=46 i=68 10189 i=12 -1 1 1 Method_4 ns=1;i=10191 0 Disable i=47 i=9028 10191 true true i=3065 i=2803 Method_4 ns=1;i=10190 0 Enable i=47 i=9027 10190 true true i=3065 i=2803 Method_4 ns=1;i=10192 0 AddComment i=47 i=9029 10192 true true i=3065 i=2829 Variable_2 ns=1;i=10193 0 InputArguments i=46 i=68 10193 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=10196 0 AckedState i=47 i=8995 10196 i=21 -1 1 1 i=9004 true ns=1;i=10175 Variable_2 ns=1;i=10197 0 Id i=46 i=68 10197 i=1 -1 1 1 Method_4 ns=1;i=10212 0 Acknowledge i=47 i=9111 10212 true true i=3065 i=8944 Variable_2 ns=1;i=10213 0 InputArguments i=46 i=68 10213 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=10216 1 BooleanValue i=47 i=63 10216 i=1 -1 1 1 Variable_2 ns=1;i=10217 1 SByteValue i=47 i=63 10217 i=2 -1 1 1 Variable_2 ns=1;i=10218 1 ByteValue i=47 i=63 10218 i=3 -1 1 1 Variable_2 ns=1;i=10219 1 Int16Value i=47 i=63 10219 i=4 -1 1 1 Variable_2 ns=1;i=10220 1 UInt16Value i=47 i=63 10220 i=5 -1 1 1 Variable_2 ns=1;i=10221 1 Int32Value i=47 i=63 10221 i=6 -1 1 1 Variable_2 ns=1;i=10222 1 UInt32Value i=47 i=63 10222 i=7 -1 1 1 Variable_2 ns=1;i=10223 1 Int64Value i=47 i=63 10223 i=8 -1 1 1 Variable_2 ns=1;i=10224 1 UInt64Value i=47 i=63 10224 i=9 -1 1 1 Variable_2 ns=1;i=10225 1 FloatValue i=47 i=63 10225 i=10 -1 1 1 Variable_2 ns=1;i=10226 1 DoubleValue i=47 i=63 10226 i=11 -1 1 1 Variable_2 ns=1;i=10227 1 StringValue i=47 i=63 10227 i=12 -1 1 1 Variable_2 ns=1;i=10228 1 DateTimeValue i=47 i=63 10228 i=13 -1 1 1 Variable_2 ns=1;i=10229 1 GuidValue i=47 i=63 10229 i=14 -1 1 1 Variable_2 ns=1;i=10230 1 ByteStringValue i=47 i=63 10230 i=15 -1 1 1 Variable_2 ns=1;i=10231 1 XmlElementValue i=47 i=63 10231 i=16 -1 1 1 Variable_2 ns=1;i=10232 1 NodeIdValue i=47 i=63 10232 i=17 -1 1 1 Variable_2 ns=1;i=10233 1 ExpandedNodeIdValue i=47 i=63 10233 i=18 -1 1 1 Variable_2 ns=1;i=10234 1 QualifiedNameValue i=47 i=63 10234 i=20 -1 1 1 Variable_2 ns=1;i=10235 1 LocalizedTextValue i=47 i=63 10235 i=21 -1 1 1 Variable_2 ns=1;i=10236 1 StatusCodeValue i=47 i=63 10236 i=19 -1 1 1 Variable_2 ns=1;i=10237 1 VariantValue i=47 i=63 10237 i=24 -1 1 1 Variable_2 ns=1;i=10238 1 EnumerationValue i=47 i=63 10238 i=29 -1 1 1 Variable_2 ns=1;i=10239 1 StructureValue i=47 i=63 10239 i=22 -1 1 1 Variable_2 ns=1;i=10240 1 NumberValue i=47 i=63 10240 i=26 -1 1 1 Variable_2 ns=1;i=10241 1 IntegerValue i=47 i=63 10241 i=27 -1 1 1 Variable_2 ns=1;i=10242 1 UIntegerValue i=47 i=63 10242 i=28 -1 1 1 Object_1 ns=1;i=10243 1 Array i=47 ns=1;i=9679 10243 i=36 true ns=1;i=10158 i=36 ns=1;i=10247 Variable_2 ns=1;i=10244 1 SimulationActive If true the server will produce new values for each monitored variable. i=46 i=68 10244 i=1 -1 1 1 Method_4 ns=1;i=10245 1 GenerateValues i=47 ns=1;i=9385 10245 true true Variable_2 ns=1;i=10246 0 InputArguments i=46 i=68 10246 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 Object_1 ns=1;i=10247 1 CycleComplete i=47 i=2881 10247 i=36 true ns=1;i=10243 Variable_2 ns=1;i=10248 0 EventId i=46 i=68 10248 i=15 -1 1 1 Variable_2 ns=1;i=10249 0 EventType i=46 i=68 10249 i=17 -1 1 1 Variable_2 ns=1;i=10250 0 SourceNode i=46 i=68 10250 i=17 -1 1 1 Variable_2 ns=1;i=10251 0 SourceName i=46 i=68 10251 i=12 -1 1 1 Variable_2 ns=1;i=10253 0 ReceiveTime i=46 i=68 10253 i=294 -1 1 1 Variable_2 ns=1;i=10255 0 Message i=46 i=68 10255 i=21 -1 1 1 Variable_2 ns=1;i=10256 0 Severity i=46 i=68 10256 i=5 -1 1 1 Variable_2 ns=1;i=11596 0 ConditionClassId i=46 i=68 11596 i=17 -1 1 1 Variable_2 ns=1;i=11597 0 ConditionClassName i=46 i=68 11597 i=21 -1 1 1 Variable_2 ns=1;i=11566 0 ConditionName i=46 i=68 11566 i=12 -1 1 1 Variable_2 ns=1;i=10257 0 BranchId i=46 i=68 10257 i=17 -1 1 1 Variable_2 ns=1;i=10258 0 Retain i=46 i=68 10258 i=1 -1 1 1 Variable_2 ns=1;i=10259 0 EnabledState i=47 i=8995 10259 i=21 -1 1 1 i=9004 ns=1;i=10280 i=9004 ns=1;i=10288 Variable_2 ns=1;i=10260 0 Id i=46 i=68 10260 i=1 -1 1 1 Variable_2 ns=1;i=10265 0 Quality i=47 i=9002 10265 i=19 -1 1 1 Variable_2 ns=1;i=10266 0 SourceTimestamp i=46 i=68 10266 i=294 -1 1 1 Variable_2 ns=1;i=10269 0 LastSeverity i=47 i=9002 10269 i=5 -1 1 1 Variable_2 ns=1;i=10270 0 SourceTimestamp i=46 i=68 10270 i=294 -1 1 1 Variable_2 ns=1;i=10271 0 Comment i=47 i=9002 10271 i=21 -1 1 1 Variable_2 ns=1;i=10272 0 SourceTimestamp i=46 i=68 10272 i=294 -1 1 1 Variable_2 ns=1;i=10273 0 ClientUserId i=46 i=68 10273 i=12 -1 1 1 Method_4 ns=1;i=10275 0 Disable i=47 i=9028 10275 true true i=3065 i=2803 Method_4 ns=1;i=10274 0 Enable i=47 i=9027 10274 true true i=3065 i=2803 Method_4 ns=1;i=10276 0 AddComment i=47 i=9029 10276 true true i=3065 i=2829 Variable_2 ns=1;i=10277 0 InputArguments i=46 i=68 10277 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=10280 0 AckedState i=47 i=8995 10280 i=21 -1 1 1 i=9004 true ns=1;i=10259 Variable_2 ns=1;i=10281 0 Id i=46 i=68 10281 i=1 -1 1 1 Method_4 ns=1;i=10296 0 Acknowledge i=47 i=9111 10296 true true i=3065 i=8944 Variable_2 ns=1;i=10297 0 InputArguments i=46 i=68 10297 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=10300 1 BooleanValue i=47 i=63 10300 i=1 1 0 1 1 Variable_2 ns=1;i=10301 1 SByteValue i=47 i=63 10301 i=2 1 0 1 1 Variable_2 ns=1;i=10302 1 ByteValue i=47 i=63 10302 i=3 1 0 1 1 Variable_2 ns=1;i=10303 1 Int16Value i=47 i=63 10303 i=4 1 0 1 1 Variable_2 ns=1;i=10304 1 UInt16Value i=47 i=63 10304 i=5 1 0 1 1 Variable_2 ns=1;i=10305 1 Int32Value i=47 i=63 10305 i=6 1 0 1 1 Variable_2 ns=1;i=10306 1 UInt32Value i=47 i=63 10306 i=7 1 0 1 1 Variable_2 ns=1;i=10307 1 Int64Value i=47 i=63 10307 i=8 1 0 1 1 Variable_2 ns=1;i=10308 1 UInt64Value i=47 i=63 10308 i=9 1 0 1 1 Variable_2 ns=1;i=10309 1 FloatValue i=47 i=63 10309 i=10 1 0 1 1 Variable_2 ns=1;i=10310 1 DoubleValue i=47 i=63 10310 i=11 1 0 1 1 Variable_2 ns=1;i=10311 1 StringValue i=47 i=63 10311 i=12 1 0 1 1 Variable_2 ns=1;i=10312 1 DateTimeValue i=47 i=63 10312 i=13 1 0 1 1 Variable_2 ns=1;i=10313 1 GuidValue i=47 i=63 10313 i=14 1 0 1 1 Variable_2 ns=1;i=10314 1 ByteStringValue i=47 i=63 10314 i=15 1 0 1 1 Variable_2 ns=1;i=10315 1 XmlElementValue i=47 i=63 10315 i=16 1 0 1 1 Variable_2 ns=1;i=10316 1 NodeIdValue i=47 i=63 10316 i=17 1 0 1 1 Variable_2 ns=1;i=10317 1 ExpandedNodeIdValue i=47 i=63 10317 i=18 1 0 1 1 Variable_2 ns=1;i=10318 1 QualifiedNameValue i=47 i=63 10318 i=20 1 0 1 1 Variable_2 ns=1;i=10319 1 LocalizedTextValue i=47 i=63 10319 i=21 1 0 1 1 Variable_2 ns=1;i=10320 1 StatusCodeValue i=47 i=63 10320 i=19 1 0 1 1 Variable_2 ns=1;i=10321 1 VariantValue i=47 i=63 10321 i=24 1 0 1 1 Variable_2 ns=1;i=10322 1 EnumerationValue i=47 i=63 10322 i=29 1 0 1 1 Variable_2 ns=1;i=10323 1 StructureValue i=47 i=63 10323 i=22 1 0 1 1 Variable_2 ns=1;i=10324 1 NumberValue i=47 i=63 10324 i=26 1 0 1 1 Variable_2 ns=1;i=10325 1 IntegerValue i=47 i=63 10325 i=27 1 0 1 1 Variable_2 ns=1;i=10326 1 UIntegerValue i=47 i=63 10326 i=28 1 0 1 1 Object_1 ns=1;i=10327 1 UserScalar i=47 ns=1;i=9921 10327 i=36 ns=1;i=10331 Variable_2 ns=1;i=10328 1 SimulationActive If true the server will produce new values for each monitored variable. i=46 i=68 10328 i=1 -1 1 1 Method_4 ns=1;i=10329 1 GenerateValues i=47 ns=1;i=9385 10329 true true Variable_2 ns=1;i=10330 0 InputArguments i=46 i=68 10330 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 Object_1 ns=1;i=10331 1 CycleComplete i=47 i=2881 10331 i=36 true ns=1;i=10327 Variable_2 ns=1;i=10332 0 EventId i=46 i=68 10332 i=15 -1 1 1 Variable_2 ns=1;i=10333 0 EventType i=46 i=68 10333 i=17 -1 1 1 Variable_2 ns=1;i=10334 0 SourceNode i=46 i=68 10334 i=17 -1 1 1 Variable_2 ns=1;i=10335 0 SourceName i=46 i=68 10335 i=12 -1 1 1 Variable_2 ns=1;i=10337 0 ReceiveTime i=46 i=68 10337 i=294 -1 1 1 Variable_2 ns=1;i=10339 0 Message i=46 i=68 10339 i=21 -1 1 1 Variable_2 ns=1;i=10340 0 Severity i=46 i=68 10340 i=5 -1 1 1 Variable_2 ns=1;i=11598 0 ConditionClassId i=46 i=68 11598 i=17 -1 1 1 Variable_2 ns=1;i=11599 0 ConditionClassName i=46 i=68 11599 i=21 -1 1 1 Variable_2 ns=1;i=11567 0 ConditionName i=46 i=68 11567 i=12 -1 1 1 Variable_2 ns=1;i=10341 0 BranchId i=46 i=68 10341 i=17 -1 1 1 Variable_2 ns=1;i=10342 0 Retain i=46 i=68 10342 i=1 -1 1 1 Variable_2 ns=1;i=10343 0 EnabledState i=47 i=8995 10343 i=21 -1 1 1 i=9004 ns=1;i=10364 i=9004 ns=1;i=10372 Variable_2 ns=1;i=10344 0 Id i=46 i=68 10344 i=1 -1 1 1 Variable_2 ns=1;i=10349 0 Quality i=47 i=9002 10349 i=19 -1 1 1 Variable_2 ns=1;i=10350 0 SourceTimestamp i=46 i=68 10350 i=294 -1 1 1 Variable_2 ns=1;i=10353 0 LastSeverity i=47 i=9002 10353 i=5 -1 1 1 Variable_2 ns=1;i=10354 0 SourceTimestamp i=46 i=68 10354 i=294 -1 1 1 Variable_2 ns=1;i=10355 0 Comment i=47 i=9002 10355 i=21 -1 1 1 Variable_2 ns=1;i=10356 0 SourceTimestamp i=46 i=68 10356 i=294 -1 1 1 Variable_2 ns=1;i=10357 0 ClientUserId i=46 i=68 10357 i=12 -1 1 1 Method_4 ns=1;i=10359 0 Disable i=47 i=9028 10359 true true i=3065 i=2803 Method_4 ns=1;i=10358 0 Enable i=47 i=9027 10358 true true i=3065 i=2803 Method_4 ns=1;i=10360 0 AddComment i=47 i=9029 10360 true true i=3065 i=2829 Variable_2 ns=1;i=10361 0 InputArguments i=46 i=68 10361 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=10364 0 AckedState i=47 i=8995 10364 i=21 -1 1 1 i=9004 true ns=1;i=10343 Variable_2 ns=1;i=10365 0 Id i=46 i=68 10365 i=1 -1 1 1 Method_4 ns=1;i=10380 0 Acknowledge i=47 i=9111 10380 true true i=3065 i=8944 Variable_2 ns=1;i=10381 0 InputArguments i=46 i=68 10381 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=10384 1 BooleanValue i=47 i=63 10384 ns=1;i=9898 -1 1 1 Variable_2 ns=1;i=10385 1 SByteValue i=47 i=63 10385 ns=1;i=9899 -1 1 1 Variable_2 ns=1;i=10386 1 ByteValue i=47 i=63 10386 ns=1;i=9900 -1 1 1 Variable_2 ns=1;i=10387 1 Int16Value i=47 i=63 10387 ns=1;i=9901 -1 1 1 Variable_2 ns=1;i=10388 1 UInt16Value i=47 i=63 10388 ns=1;i=9902 -1 1 1 Variable_2 ns=1;i=10389 1 Int32Value i=47 i=63 10389 ns=1;i=9903 -1 1 1 Variable_2 ns=1;i=10390 1 UInt32Value i=47 i=63 10390 ns=1;i=9904 -1 1 1 Variable_2 ns=1;i=10391 1 Int64Value i=47 i=63 10391 ns=1;i=9905 -1 1 1 Variable_2 ns=1;i=10392 1 UInt64Value i=47 i=63 10392 ns=1;i=9906 -1 1 1 Variable_2 ns=1;i=10393 1 FloatValue i=47 i=63 10393 ns=1;i=9907 -1 1 1 Variable_2 ns=1;i=10394 1 DoubleValue i=47 i=63 10394 ns=1;i=9908 -1 1 1 Variable_2 ns=1;i=10395 1 StringValue i=47 i=63 10395 ns=1;i=9909 -1 1 1 Variable_2 ns=1;i=10396 1 DateTimeValue i=47 i=63 10396 ns=1;i=9910 -1 1 1 Variable_2 ns=1;i=10397 1 GuidValue i=47 i=63 10397 ns=1;i=9911 -1 1 1 Variable_2 ns=1;i=10398 1 ByteStringValue i=47 i=63 10398 ns=1;i=9912 -1 1 1 Variable_2 ns=1;i=10399 1 XmlElementValue i=47 i=63 10399 ns=1;i=9913 -1 1 1 Variable_2 ns=1;i=10400 1 NodeIdValue i=47 i=63 10400 ns=1;i=9914 -1 1 1 Variable_2 ns=1;i=10401 1 ExpandedNodeIdValue i=47 i=63 10401 ns=1;i=9915 -1 1 1 Variable_2 ns=1;i=10402 1 QualifiedNameValue i=47 i=63 10402 ns=1;i=9916 -1 1 1 Variable_2 ns=1;i=10403 1 LocalizedTextValue i=47 i=63 10403 ns=1;i=9917 -1 1 1 Variable_2 ns=1;i=10404 1 StatusCodeValue i=47 i=63 10404 ns=1;i=9918 -1 1 1 Variable_2 ns=1;i=10405 1 VariantValue i=47 i=63 10405 ns=1;i=9919 -1 1 1 Object_1 ns=1;i=10406 1 UserArray i=47 ns=1;i=10007 10406 i=36 ns=1;i=10410 Variable_2 ns=1;i=10407 1 SimulationActive If true the server will produce new values for each monitored variable. i=46 i=68 10407 i=1 -1 1 1 Method_4 ns=1;i=10408 1 GenerateValues i=47 ns=1;i=9385 10408 true true Variable_2 ns=1;i=10409 0 InputArguments i=46 i=68 10409 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 Object_1 ns=1;i=10410 1 CycleComplete i=47 i=2881 10410 i=36 true ns=1;i=10406 Variable_2 ns=1;i=10411 0 EventId i=46 i=68 10411 i=15 -1 1 1 Variable_2 ns=1;i=10412 0 EventType i=46 i=68 10412 i=17 -1 1 1 Variable_2 ns=1;i=10413 0 SourceNode i=46 i=68 10413 i=17 -1 1 1 Variable_2 ns=1;i=10414 0 SourceName i=46 i=68 10414 i=12 -1 1 1 Variable_2 ns=1;i=10416 0 ReceiveTime i=46 i=68 10416 i=294 -1 1 1 Variable_2 ns=1;i=10418 0 Message i=46 i=68 10418 i=21 -1 1 1 Variable_2 ns=1;i=10419 0 Severity i=46 i=68 10419 i=5 -1 1 1 Variable_2 ns=1;i=11600 0 ConditionClassId i=46 i=68 11600 i=17 -1 1 1 Variable_2 ns=1;i=11601 0 ConditionClassName i=46 i=68 11601 i=21 -1 1 1 Variable_2 ns=1;i=11568 0 ConditionName i=46 i=68 11568 i=12 -1 1 1 Variable_2 ns=1;i=10420 0 BranchId i=46 i=68 10420 i=17 -1 1 1 Variable_2 ns=1;i=10421 0 Retain i=46 i=68 10421 i=1 -1 1 1 Variable_2 ns=1;i=10422 0 EnabledState i=47 i=8995 10422 i=21 -1 1 1 i=9004 ns=1;i=10443 i=9004 ns=1;i=10451 Variable_2 ns=1;i=10423 0 Id i=46 i=68 10423 i=1 -1 1 1 Variable_2 ns=1;i=10428 0 Quality i=47 i=9002 10428 i=19 -1 1 1 Variable_2 ns=1;i=10429 0 SourceTimestamp i=46 i=68 10429 i=294 -1 1 1 Variable_2 ns=1;i=10432 0 LastSeverity i=47 i=9002 10432 i=5 -1 1 1 Variable_2 ns=1;i=10433 0 SourceTimestamp i=46 i=68 10433 i=294 -1 1 1 Variable_2 ns=1;i=10434 0 Comment i=47 i=9002 10434 i=21 -1 1 1 Variable_2 ns=1;i=10435 0 SourceTimestamp i=46 i=68 10435 i=294 -1 1 1 Variable_2 ns=1;i=10436 0 ClientUserId i=46 i=68 10436 i=12 -1 1 1 Method_4 ns=1;i=10438 0 Disable i=47 i=9028 10438 true true i=3065 i=2803 Method_4 ns=1;i=10437 0 Enable i=47 i=9027 10437 true true i=3065 i=2803 Method_4 ns=1;i=10439 0 AddComment i=47 i=9029 10439 true true i=3065 i=2829 Variable_2 ns=1;i=10440 0 InputArguments i=46 i=68 10440 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=10443 0 AckedState i=47 i=8995 10443 i=21 -1 1 1 i=9004 true ns=1;i=10422 Variable_2 ns=1;i=10444 0 Id i=46 i=68 10444 i=1 -1 1 1 Method_4 ns=1;i=10459 0 Acknowledge i=47 i=9111 10459 true true i=3065 i=8944 Variable_2 ns=1;i=10460 0 InputArguments i=46 i=68 10460 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=10463 1 BooleanValue i=47 i=63 10463 ns=1;i=9898 1 0 1 1 Variable_2 ns=1;i=10464 1 SByteValue i=47 i=63 10464 ns=1;i=9899 1 0 1 1 Variable_2 ns=1;i=10465 1 ByteValue i=47 i=63 10465 ns=1;i=9900 1 0 1 1 Variable_2 ns=1;i=10466 1 Int16Value i=47 i=63 10466 ns=1;i=9901 1 0 1 1 Variable_2 ns=1;i=10467 1 UInt16Value i=47 i=63 10467 ns=1;i=9902 1 0 1 1 Variable_2 ns=1;i=10468 1 Int32Value i=47 i=63 10468 ns=1;i=9903 1 0 1 1 Variable_2 ns=1;i=10469 1 UInt32Value i=47 i=63 10469 ns=1;i=9904 1 0 1 1 Variable_2 ns=1;i=10470 1 Int64Value i=47 i=63 10470 ns=1;i=9905 1 0 1 1 Variable_2 ns=1;i=10471 1 UInt64Value i=47 i=63 10471 ns=1;i=9906 1 0 1 1 Variable_2 ns=1;i=10472 1 FloatValue i=47 i=63 10472 ns=1;i=9907 1 0 1 1 Variable_2 ns=1;i=10473 1 DoubleValue i=47 i=63 10473 ns=1;i=9908 1 0 1 1 Variable_2 ns=1;i=10474 1 StringValue i=47 i=63 10474 ns=1;i=9909 1 0 1 1 Variable_2 ns=1;i=10475 1 DateTimeValue i=47 i=63 10475 ns=1;i=9910 1 0 1 1 Variable_2 ns=1;i=10476 1 GuidValue i=47 i=63 10476 ns=1;i=9911 1 0 1 1 Variable_2 ns=1;i=10477 1 ByteStringValue i=47 i=63 10477 ns=1;i=9912 1 0 1 1 Variable_2 ns=1;i=10478 1 XmlElementValue i=47 i=63 10478 ns=1;i=9913 1 0 1 1 Variable_2 ns=1;i=10479 1 NodeIdValue i=47 i=63 10479 ns=1;i=9914 1 0 1 1 Variable_2 ns=1;i=10480 1 ExpandedNodeIdValue i=47 i=63 10480 ns=1;i=9915 1 0 1 1 Variable_2 ns=1;i=10481 1 QualifiedNameValue i=47 i=63 10481 ns=1;i=9916 1 0 1 1 Variable_2 ns=1;i=10482 1 LocalizedTextValue i=47 i=63 10482 ns=1;i=9917 1 0 1 1 Variable_2 ns=1;i=10483 1 StatusCodeValue i=47 i=63 10483 ns=1;i=9918 1 0 1 1 Variable_2 ns=1;i=10484 1 VariantValue i=47 i=63 10484 ns=1;i=9919 1 0 1 1 Object_1 ns=1;i=10485 1 AnalogScalar i=47 ns=1;i=9534 10485 i=36 ns=1;i=10489 Variable_2 ns=1;i=10486 1 SimulationActive If true the server will produce new values for each monitored variable. i=46 i=68 10486 i=1 -1 1 1 Method_4 ns=1;i=10487 1 GenerateValues i=47 ns=1;i=9385 10487 true true Variable_2 ns=1;i=10488 0 InputArguments i=46 i=68 10488 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 Object_1 ns=1;i=10489 1 CycleComplete i=47 i=2881 10489 i=36 true ns=1;i=10485 Variable_2 ns=1;i=10490 0 EventId i=46 i=68 10490 i=15 -1 1 1 Variable_2 ns=1;i=10491 0 EventType i=46 i=68 10491 i=17 -1 1 1 Variable_2 ns=1;i=10492 0 SourceNode i=46 i=68 10492 i=17 -1 1 1 Variable_2 ns=1;i=10493 0 SourceName i=46 i=68 10493 i=12 -1 1 1 Variable_2 ns=1;i=10495 0 ReceiveTime i=46 i=68 10495 i=294 -1 1 1 Variable_2 ns=1;i=10497 0 Message i=46 i=68 10497 i=21 -1 1 1 Variable_2 ns=1;i=10498 0 Severity i=46 i=68 10498 i=5 -1 1 1 Variable_2 ns=1;i=11602 0 ConditionClassId i=46 i=68 11602 i=17 -1 1 1 Variable_2 ns=1;i=11603 0 ConditionClassName i=46 i=68 11603 i=21 -1 1 1 Variable_2 ns=1;i=11569 0 ConditionName i=46 i=68 11569 i=12 -1 1 1 Variable_2 ns=1;i=10499 0 BranchId i=46 i=68 10499 i=17 -1 1 1 Variable_2 ns=1;i=10500 0 Retain i=46 i=68 10500 i=1 -1 1 1 Variable_2 ns=1;i=10501 0 EnabledState i=47 i=8995 10501 i=21 -1 1 1 i=9004 ns=1;i=10522 i=9004 ns=1;i=10530 Variable_2 ns=1;i=10502 0 Id i=46 i=68 10502 i=1 -1 1 1 Variable_2 ns=1;i=10507 0 Quality i=47 i=9002 10507 i=19 -1 1 1 Variable_2 ns=1;i=10508 0 SourceTimestamp i=46 i=68 10508 i=294 -1 1 1 Variable_2 ns=1;i=10511 0 LastSeverity i=47 i=9002 10511 i=5 -1 1 1 Variable_2 ns=1;i=10512 0 SourceTimestamp i=46 i=68 10512 i=294 -1 1 1 Variable_2 ns=1;i=10513 0 Comment i=47 i=9002 10513 i=21 -1 1 1 Variable_2 ns=1;i=10514 0 SourceTimestamp i=46 i=68 10514 i=294 -1 1 1 Variable_2 ns=1;i=10515 0 ClientUserId i=46 i=68 10515 i=12 -1 1 1 Method_4 ns=1;i=10517 0 Disable i=47 i=9028 10517 true true i=3065 i=2803 Method_4 ns=1;i=10516 0 Enable i=47 i=9027 10516 true true i=3065 i=2803 Method_4 ns=1;i=10518 0 AddComment i=47 i=9029 10518 true true i=3065 i=2829 Variable_2 ns=1;i=10519 0 InputArguments i=46 i=68 10519 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=10522 0 AckedState i=47 i=8995 10522 i=21 -1 1 1 i=9004 true ns=1;i=10501 Variable_2 ns=1;i=10523 0 Id i=46 i=68 10523 i=1 -1 1 1 Method_4 ns=1;i=10538 0 Acknowledge i=47 i=9111 10538 true true i=3065 i=8944 Variable_2 ns=1;i=10539 0 InputArguments i=46 i=68 10539 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=10542 1 SByteValue i=47 i=2368 10542 i=2 -1 1 1 Variable_2 ns=1;i=10545 0 EURange i=46 i=68 10545 i=884 -1 1 1 Variable_2 ns=1;i=10548 1 ByteValue i=47 i=2368 10548 i=3 -1 1 1 Variable_2 ns=1;i=10551 0 EURange i=46 i=68 10551 i=884 -1 1 1 Variable_2 ns=1;i=10554 1 Int16Value i=47 i=2368 10554 i=4 -1 1 1 Variable_2 ns=1;i=10557 0 EURange i=46 i=68 10557 i=884 -1 1 1 Variable_2 ns=1;i=10560 1 UInt16Value i=47 i=2368 10560 i=5 -1 1 1 Variable_2 ns=1;i=10563 0 EURange i=46 i=68 10563 i=884 -1 1 1 Variable_2 ns=1;i=10566 1 Int32Value i=47 i=2368 10566 i=6 -1 1 1 Variable_2 ns=1;i=10569 0 EURange i=46 i=68 10569 i=884 -1 1 1 Variable_2 ns=1;i=10572 1 UInt32Value i=47 i=2368 10572 i=7 -1 1 1 Variable_2 ns=1;i=10575 0 EURange i=46 i=68 10575 i=884 -1 1 1 Variable_2 ns=1;i=10578 1 Int64Value i=47 i=2368 10578 i=8 -1 1 1 Variable_2 ns=1;i=10581 0 EURange i=46 i=68 10581 i=884 -1 1 1 Variable_2 ns=1;i=10584 1 UInt64Value i=47 i=2368 10584 i=9 -1 1 1 Variable_2 ns=1;i=10587 0 EURange i=46 i=68 10587 i=884 -1 1 1 Variable_2 ns=1;i=10590 1 FloatValue i=47 i=2368 10590 i=10 -1 1 1 Variable_2 ns=1;i=10593 0 EURange i=46 i=68 10593 i=884 -1 1 1 Variable_2 ns=1;i=10596 1 DoubleValue i=47 i=2368 10596 i=11 -1 1 1 Variable_2 ns=1;i=10599 0 EURange i=46 i=68 10599 i=884 -1 1 1 Variable_2 ns=1;i=10602 1 NumberValue i=47 i=2368 10602 i=26 -1 1 1 Variable_2 ns=1;i=10605 0 EURange i=46 i=68 10605 i=884 -1 1 1 Variable_2 ns=1;i=10608 1 IntegerValue i=47 i=2368 10608 i=27 -1 1 1 Variable_2 ns=1;i=10611 0 EURange i=46 i=68 10611 i=884 -1 1 1 Variable_2 ns=1;i=10614 1 UIntegerValue i=47 i=2368 10614 i=28 -1 1 1 Variable_2 ns=1;i=10617 0 EURange i=46 i=68 10617 i=884 -1 1 1 Object_1 ns=1;i=10620 1 AnalogArray i=47 ns=1;i=9763 10620 i=36 ns=1;i=10624 Variable_2 ns=1;i=10621 1 SimulationActive If true the server will produce new values for each monitored variable. i=46 i=68 10621 i=1 -1 1 1 Method_4 ns=1;i=10622 1 GenerateValues i=47 ns=1;i=9385 10622 true true Variable_2 ns=1;i=10623 0 InputArguments i=46 i=68 10623 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 Object_1 ns=1;i=10624 1 CycleComplete i=47 i=2881 10624 i=36 true ns=1;i=10620 Variable_2 ns=1;i=10625 0 EventId i=46 i=68 10625 i=15 -1 1 1 Variable_2 ns=1;i=10626 0 EventType i=46 i=68 10626 i=17 -1 1 1 Variable_2 ns=1;i=10627 0 SourceNode i=46 i=68 10627 i=17 -1 1 1 Variable_2 ns=1;i=10628 0 SourceName i=46 i=68 10628 i=12 -1 1 1 Variable_2 ns=1;i=10630 0 ReceiveTime i=46 i=68 10630 i=294 -1 1 1 Variable_2 ns=1;i=10632 0 Message i=46 i=68 10632 i=21 -1 1 1 Variable_2 ns=1;i=10633 0 Severity i=46 i=68 10633 i=5 -1 1 1 Variable_2 ns=1;i=11604 0 ConditionClassId i=46 i=68 11604 i=17 -1 1 1 Variable_2 ns=1;i=11605 0 ConditionClassName i=46 i=68 11605 i=21 -1 1 1 Variable_2 ns=1;i=11570 0 ConditionName i=46 i=68 11570 i=12 -1 1 1 Variable_2 ns=1;i=10634 0 BranchId i=46 i=68 10634 i=17 -1 1 1 Variable_2 ns=1;i=10635 0 Retain i=46 i=68 10635 i=1 -1 1 1 Variable_2 ns=1;i=10636 0 EnabledState i=47 i=8995 10636 i=21 -1 1 1 i=9004 ns=1;i=10657 i=9004 ns=1;i=10665 Variable_2 ns=1;i=10637 0 Id i=46 i=68 10637 i=1 -1 1 1 Variable_2 ns=1;i=10642 0 Quality i=47 i=9002 10642 i=19 -1 1 1 Variable_2 ns=1;i=10643 0 SourceTimestamp i=46 i=68 10643 i=294 -1 1 1 Variable_2 ns=1;i=10646 0 LastSeverity i=47 i=9002 10646 i=5 -1 1 1 Variable_2 ns=1;i=10647 0 SourceTimestamp i=46 i=68 10647 i=294 -1 1 1 Variable_2 ns=1;i=10648 0 Comment i=47 i=9002 10648 i=21 -1 1 1 Variable_2 ns=1;i=10649 0 SourceTimestamp i=46 i=68 10649 i=294 -1 1 1 Variable_2 ns=1;i=10650 0 ClientUserId i=46 i=68 10650 i=12 -1 1 1 Method_4 ns=1;i=10652 0 Disable i=47 i=9028 10652 true true i=3065 i=2803 Method_4 ns=1;i=10651 0 Enable i=47 i=9027 10651 true true i=3065 i=2803 Method_4 ns=1;i=10653 0 AddComment i=47 i=9029 10653 true true i=3065 i=2829 Variable_2 ns=1;i=10654 0 InputArguments i=46 i=68 10654 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=10657 0 AckedState i=47 i=8995 10657 i=21 -1 1 1 i=9004 true ns=1;i=10636 Variable_2 ns=1;i=10658 0 Id i=46 i=68 10658 i=1 -1 1 1 Method_4 ns=1;i=10673 0 Acknowledge i=47 i=9111 10673 true true i=3065 i=8944 Variable_2 ns=1;i=10674 0 InputArguments i=46 i=68 10674 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=10677 1 SByteValue i=47 i=2368 10677 i=2 1 0 1 1 Variable_2 ns=1;i=10680 0 EURange i=46 i=68 10680 i=884 -1 1 1 Variable_2 ns=1;i=10683 1 ByteValue i=47 i=2368 10683 i=3 1 0 1 1 Variable_2 ns=1;i=10686 0 EURange i=46 i=68 10686 i=884 -1 1 1 Variable_2 ns=1;i=10689 1 Int16Value i=47 i=2368 10689 i=4 1 0 1 1 Variable_2 ns=1;i=10692 0 EURange i=46 i=68 10692 i=884 -1 1 1 Variable_2 ns=1;i=10695 1 UInt16Value i=47 i=2368 10695 i=5 1 0 1 1 Variable_2 ns=1;i=10698 0 EURange i=46 i=68 10698 i=884 -1 1 1 Variable_2 ns=1;i=10701 1 Int32Value i=47 i=2368 10701 i=6 1 0 1 1 Variable_2 ns=1;i=10704 0 EURange i=46 i=68 10704 i=884 -1 1 1 Variable_2 ns=1;i=10707 1 UInt32Value i=47 i=2368 10707 i=7 1 0 1 1 Variable_2 ns=1;i=10710 0 EURange i=46 i=68 10710 i=884 -1 1 1 Variable_2 ns=1;i=10713 1 Int64Value i=47 i=2368 10713 i=8 1 0 1 1 Variable_2 ns=1;i=10716 0 EURange i=46 i=68 10716 i=884 -1 1 1 Variable_2 ns=1;i=10719 1 UInt64Value i=47 i=2368 10719 i=9 1 0 1 1 Variable_2 ns=1;i=10722 0 EURange i=46 i=68 10722 i=884 -1 1 1 Variable_2 ns=1;i=10725 1 FloatValue i=47 i=2368 10725 i=10 1 0 1 1 Variable_2 ns=1;i=10728 0 EURange i=46 i=68 10728 i=884 -1 1 1 Variable_2 ns=1;i=10731 1 DoubleValue i=47 i=2368 10731 i=11 1 0 1 1 Variable_2 ns=1;i=10734 0 EURange i=46 i=68 10734 i=884 -1 1 1 Variable_2 ns=1;i=10737 1 NumberValue i=47 i=2368 10737 i=26 1 0 1 1 Variable_2 ns=1;i=10740 0 EURange i=46 i=68 10740 i=884 -1 1 1 Variable_2 ns=1;i=10743 1 IntegerValue i=47 i=2368 10743 i=27 1 0 1 1 Variable_2 ns=1;i=10746 0 EURange i=46 i=68 10746 i=884 -1 1 1 Variable_2 ns=1;i=10749 1 UIntegerValue i=47 i=2368 10749 i=28 1 0 1 1 Variable_2 ns=1;i=10752 0 EURange i=46 i=68 10752 i=884 -1 1 1 Object_1 ns=1;i=10755 1 MethodTest i=47 ns=1;i=10092 10755 Method_4 ns=1;i=10756 1 ScalarMethod1 i=47 ns=1;i=10093 10756 true true Variable_2 ns=1;i=10757 0 InputArguments i=46 i=68 10757 i=297 BooleanIn i=1 -1 i=297 SByteIn i=2 -1 i=297 ByteIn i=3 -1 i=297 Int16In i=4 -1 i=297 UInt16In i=5 -1 i=297 Int32In i=6 -1 i=297 UInt32In i=7 -1 i=297 Int64In i=8 -1 i=297 UInt64In i=9 -1 i=297 FloatIn i=10 -1 i=297 DoubleIn i=11 -1 i=296 1 0 1 1 Variable_2 ns=1;i=10758 0 OutputArguments i=46 i=68 10758 i=297 BooleanOut i=1 -1 i=297 SByteOut i=2 -1 i=297 ByteOut i=3 -1 i=297 Int16Out i=4 -1 i=297 UInt16Out i=5 -1 i=297 Int32Out i=6 -1 i=297 UInt32Out i=7 -1 i=297 Int64Out i=8 -1 i=297 UInt64Out i=9 -1 i=297 FloatOut i=10 -1 i=297 DoubleOut i=11 -1 i=296 1 0 1 1 Method_4 ns=1;i=10759 1 ScalarMethod2 i=47 ns=1;i=10096 10759 true true Variable_2 ns=1;i=10760 0 InputArguments i=46 i=68 10760 i=297 StringIn i=12 -1 i=297 DateTimeIn i=13 -1 i=297 GuidIn i=14 -1 i=297 ByteStringIn i=15 -1 i=297 XmlElementIn i=16 -1 i=297 NodeIdIn i=17 -1 i=297 ExpandedNodeIdIn i=18 -1 i=297 QualifiedNameIn i=20 -1 i=297 LocalizedTextIn i=21 -1 i=297 StatusCodeIn i=19 -1 i=296 1 0 1 1 Variable_2 ns=1;i=10761 0 OutputArguments i=46 i=68 10761 i=297 StringOut i=12 -1 i=297 DateTimeOut i=13 -1 i=297 GuidOut i=14 -1 i=297 ByteStringOut i=15 -1 i=297 XmlElementOut i=16 -1 i=297 NodeIdOut i=17 -1 i=297 ExpandedNodeIdOut i=18 -1 i=297 QualifiedNameOut i=20 -1 i=297 LocalizedTextOut i=21 -1 i=297 StatusCodeOut i=19 -1 i=296 1 0 1 1 Method_4 ns=1;i=10762 1 ScalarMethod3 i=47 ns=1;i=10099 10762 true true Variable_2 ns=1;i=10763 0 InputArguments i=46 i=68 10763 i=297 VariantIn i=24 -1 i=297 EnumerationIn i=29 -1 i=297 StructureIn i=22 -1 i=296 1 0 1 1 Variable_2 ns=1;i=10764 0 OutputArguments i=46 i=68 10764 i=297 VariantOut i=24 -1 i=297 EnumerationOut i=29 -1 i=297 StructureOut i=22 -1 i=296 1 0 1 1 Method_4 ns=1;i=10765 1 ArrayMethod1 i=47 ns=1;i=10102 10765 true true Variable_2 ns=1;i=10766 0 InputArguments i=46 i=68 10766 i=297 BooleanIn i=1 1 0 i=297 SByteIn i=2 1 0 i=297 ByteIn i=3 1 0 i=297 Int16In i=4 1 0 i=297 UInt16In i=5 1 0 i=297 Int32In i=6 1 0 i=297 UInt32In i=7 1 0 i=297 Int64In i=8 1 0 i=297 UInt64In i=9 1 0 i=297 FloatIn i=10 1 0 i=297 DoubleIn i=11 1 0 i=296 1 0 1 1 Variable_2 ns=1;i=10767 0 OutputArguments i=46 i=68 10767 i=297 BooleanOut i=1 1 0 i=297 SByteOut i=2 1 0 i=297 ByteOut i=3 1 0 i=297 Int16Out i=4 1 0 i=297 UInt16Out i=5 1 0 i=297 Int32Out i=6 1 0 i=297 UInt32Out i=7 1 0 i=297 Int64Out i=8 1 0 i=297 UInt64Out i=9 1 0 i=297 FloatOut i=10 1 0 i=297 DoubleOut i=11 1 0 i=296 1 0 1 1 Method_4 ns=1;i=10768 1 ArrayMethod2 i=47 ns=1;i=10105 10768 true true Variable_2 ns=1;i=10769 0 InputArguments i=46 i=68 10769 i=297 StringIn i=12 1 0 i=297 DateTimeIn i=13 1 0 i=297 GuidIn i=14 1 0 i=297 ByteStringIn i=15 1 0 i=297 XmlElementIn i=16 1 0 i=297 NodeIdIn i=17 1 0 i=297 ExpandedNodeIdIn i=18 1 0 i=297 QualifiedNameIn i=20 1 0 i=297 LocalizedTextIn i=21 1 0 i=297 StatusCodeIn i=19 1 0 i=296 1 0 1 1 Variable_2 ns=1;i=10770 0 OutputArguments i=46 i=68 10770 i=297 StringOut i=12 1 0 i=297 DateTimeOut i=13 1 0 i=297 GuidOut i=14 1 0 i=297 ByteStringOut i=15 1 0 i=297 XmlElementOut i=16 1 0 i=297 NodeIdOut i=17 1 0 i=297 ExpandedNodeIdOut i=18 1 0 i=297 QualifiedNameOut i=20 1 0 i=297 LocalizedTextOut i=21 1 0 i=297 StatusCodeOut i=19 1 0 i=296 1 0 1 1 Method_4 ns=1;i=10771 1 ArrayMethod3 i=47 ns=1;i=10108 10771 true true Variable_2 ns=1;i=10772 0 InputArguments i=46 i=68 10772 i=297 VariantIn i=24 1 0 i=297 EnumerationIn i=29 1 0 i=297 StructureIn i=22 1 0 i=296 1 0 1 1 Variable_2 ns=1;i=10773 0 OutputArguments i=46 i=68 10773 i=297 VariantOut i=24 1 0 i=297 EnumerationOut i=29 1 0 i=297 StructureOut i=22 1 0 i=296 1 0 1 1 Method_4 ns=1;i=10774 1 UserScalarMethod1 i=47 ns=1;i=10111 10774 true true Variable_2 ns=1;i=10775 0 InputArguments i=46 i=68 10775 i=297 BooleanIn ns=1;i=9898 -1 i=297 SByteIn ns=1;i=9899 -1 i=297 ByteIn ns=1;i=9900 -1 i=297 Int16In ns=1;i=9901 -1 i=297 UInt16In ns=1;i=9902 -1 i=297 Int32In ns=1;i=9903 -1 i=297 UInt32In ns=1;i=9904 -1 i=297 Int64In ns=1;i=9905 -1 i=297 UInt64In ns=1;i=9906 -1 i=297 FloatIn ns=1;i=9907 -1 i=297 DoubleIn ns=1;i=9908 -1 i=297 StringIn ns=1;i=9909 -1 i=296 1 0 1 1 Variable_2 ns=1;i=10776 0 OutputArguments i=46 i=68 10776 i=297 BooleanOut ns=1;i=9898 -1 i=297 SByteOut ns=1;i=9899 -1 i=297 ByteOut ns=1;i=9900 -1 i=297 Int16Out ns=1;i=9901 -1 i=297 UInt16Out ns=1;i=9902 -1 i=297 Int32Out ns=1;i=9903 -1 i=297 UInt32Out ns=1;i=9904 -1 i=297 Int64Out ns=1;i=9905 -1 i=297 UInt64Out ns=1;i=9906 -1 i=297 FloatOut ns=1;i=9907 -1 i=297 DoubleOut ns=1;i=9908 -1 i=297 StringOut ns=1;i=9909 -1 i=296 1 0 1 1 Method_4 ns=1;i=10777 1 UserScalarMethod2 i=47 ns=1;i=10114 10777 true true Variable_2 ns=1;i=10778 0 InputArguments i=46 i=68 10778 i=297 DateTimeIn ns=1;i=9910 -1 i=297 GuidIn ns=1;i=9911 -1 i=297 ByteStringIn ns=1;i=9912 -1 i=297 XmlElementIn ns=1;i=9913 -1 i=297 NodeIdIn ns=1;i=9914 -1 i=297 ExpandedNodeIdIn ns=1;i=9915 -1 i=297 QualifiedNameIn ns=1;i=9916 -1 i=297 LocalizedTextIn ns=1;i=9917 -1 i=297 StatusCodeIn ns=1;i=9918 -1 i=297 VariantIn ns=1;i=9919 -1 i=296 1 0 1 1 Variable_2 ns=1;i=10779 0 OutputArguments i=46 i=68 10779 i=297 DateTimeOut ns=1;i=9910 -1 i=297 GuidOut ns=1;i=9911 -1 i=297 ByteStringOut ns=1;i=9912 -1 i=297 XmlElementOut ns=1;i=9913 -1 i=297 NodeIdOut ns=1;i=9914 -1 i=297 ExpandedNodeIdOut ns=1;i=9915 -1 i=297 QualifiedNameOut ns=1;i=9916 -1 i=297 LocalizedTextOut ns=1;i=9917 -1 i=297 StatusCodeOut ns=1;i=9918 -1 i=297 VariantOut ns=1;i=9919 -1 i=296 1 0 1 1 Method_4 ns=1;i=10780 1 UserArrayMethod1 i=47 ns=1;i=10117 10780 true true Variable_2 ns=1;i=10781 0 InputArguments i=46 i=68 10781 i=297 BooleanIn ns=1;i=9898 1 0 i=297 SByteIn ns=1;i=9899 1 0 i=297 ByteIn ns=1;i=9900 1 0 i=297 Int16In ns=1;i=9901 1 0 i=297 UInt16In ns=1;i=9902 1 0 i=297 Int32In ns=1;i=9903 1 0 i=297 UInt32In ns=1;i=9904 1 0 i=297 Int64In ns=1;i=9905 1 0 i=297 UInt64In ns=1;i=9906 1 0 i=297 FloatIn ns=1;i=9907 1 0 i=297 DoubleIn ns=1;i=9908 1 0 i=297 StringIn ns=1;i=9909 1 0 i=296 1 0 1 1 Variable_2 ns=1;i=10782 0 OutputArguments i=46 i=68 10782 i=297 BooleanOut ns=1;i=9898 1 0 i=297 SByteOut ns=1;i=9899 1 0 i=297 ByteOut ns=1;i=9900 1 0 i=297 Int16Out ns=1;i=9901 1 0 i=297 UInt16Out ns=1;i=9902 1 0 i=297 Int32Out ns=1;i=9903 1 0 i=297 UInt32Out ns=1;i=9904 1 0 i=297 Int64Out ns=1;i=9905 1 0 i=297 UInt64Out ns=1;i=9906 1 0 i=297 FloatOut ns=1;i=9907 1 0 i=297 DoubleOut ns=1;i=9908 1 0 i=297 StringOut ns=1;i=9909 1 0 i=296 1 0 1 1 Method_4 ns=1;i=10783 1 UserArrayMethod2 i=47 ns=1;i=10120 10783 true true Variable_2 ns=1;i=10784 0 InputArguments i=46 i=68 10784 i=297 DateTimeIn ns=1;i=9910 1 0 i=297 GuidIn ns=1;i=9911 1 0 i=297 ByteStringIn ns=1;i=9912 1 0 i=297 XmlElementIn ns=1;i=9913 1 0 i=297 NodeIdIn ns=1;i=9914 1 0 i=297 ExpandedNodeIdIn ns=1;i=9915 1 0 i=297 QualifiedNameIn ns=1;i=9916 1 0 i=297 LocalizedTextIn ns=1;i=9917 1 0 i=297 StatusCodeIn ns=1;i=9918 1 0 i=297 VariantIn ns=1;i=9919 1 0 i=296 1 0 1 1 Variable_2 ns=1;i=10785 0 OutputArguments i=46 i=68 10785 i=297 DateTimeOut ns=1;i=9910 1 0 i=297 GuidOut ns=1;i=9911 1 0 i=297 ByteStringOut ns=1;i=9912 1 0 i=297 XmlElementOut ns=1;i=9913 1 0 i=297 NodeIdOut ns=1;i=9914 1 0 i=297 ExpandedNodeIdOut ns=1;i=9915 1 0 i=297 QualifiedNameOut ns=1;i=9916 1 0 i=297 LocalizedTextOut ns=1;i=9917 1 0 i=297 StatusCodeOut ns=1;i=9918 1 0 i=297 VariantOut ns=1;i=9919 1 0 i=296 1 0 1 1 Object_1 ns=1;i=10786 1 Dynamic i=47 i=61 10786 1 i=48 true ns=1;i=10157 i=36 ns=1;i=10787 i=36 ns=1;i=10871 Object_1 ns=1;i=10787 1 Scalar i=47 ns=1;i=9450 10787 i=36 true ns=1;i=10786 i=36 ns=1;i=10791 Variable_2 ns=1;i=10788 1 SimulationActive If true the server will produce new values for each monitored variable. i=46 i=68 10788 true i=1 -1 1 1 Method_4 ns=1;i=10789 1 GenerateValues i=47 ns=1;i=9385 10789 true true Variable_2 ns=1;i=10790 0 InputArguments i=46 i=68 10790 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 Object_1 ns=1;i=10791 1 CycleComplete i=47 i=2881 10791 i=36 true ns=1;i=10787 Variable_2 ns=1;i=10792 0 EventId i=46 i=68 10792 i=15 -1 1 1 Variable_2 ns=1;i=10793 0 EventType i=46 i=68 10793 i=17 -1 1 1 Variable_2 ns=1;i=10794 0 SourceNode i=46 i=68 10794 i=17 -1 1 1 Variable_2 ns=1;i=10795 0 SourceName i=46 i=68 10795 i=12 -1 1 1 Variable_2 ns=1;i=10797 0 ReceiveTime i=46 i=68 10797 i=294 -1 1 1 Variable_2 ns=1;i=10799 0 Message i=46 i=68 10799 i=21 -1 1 1 Variable_2 ns=1;i=10800 0 Severity i=46 i=68 10800 i=5 -1 1 1 Variable_2 ns=1;i=11606 0 ConditionClassId i=46 i=68 11606 i=17 -1 1 1 Variable_2 ns=1;i=11607 0 ConditionClassName i=46 i=68 11607 i=21 -1 1 1 Variable_2 ns=1;i=11571 0 ConditionName i=46 i=68 11571 i=12 -1 1 1 Variable_2 ns=1;i=10801 0 BranchId i=46 i=68 10801 i=17 -1 1 1 Variable_2 ns=1;i=10802 0 Retain i=46 i=68 10802 i=1 -1 1 1 Variable_2 ns=1;i=10803 0 EnabledState i=47 i=8995 10803 i=21 -1 1 1 i=9004 ns=1;i=10824 i=9004 ns=1;i=10832 Variable_2 ns=1;i=10804 0 Id i=46 i=68 10804 i=1 -1 1 1 Variable_2 ns=1;i=10809 0 Quality i=47 i=9002 10809 i=19 -1 1 1 Variable_2 ns=1;i=10810 0 SourceTimestamp i=46 i=68 10810 i=294 -1 1 1 Variable_2 ns=1;i=10813 0 LastSeverity i=47 i=9002 10813 i=5 -1 1 1 Variable_2 ns=1;i=10814 0 SourceTimestamp i=46 i=68 10814 i=294 -1 1 1 Variable_2 ns=1;i=10815 0 Comment i=47 i=9002 10815 i=21 -1 1 1 Variable_2 ns=1;i=10816 0 SourceTimestamp i=46 i=68 10816 i=294 -1 1 1 Variable_2 ns=1;i=10817 0 ClientUserId i=46 i=68 10817 i=12 -1 1 1 Method_4 ns=1;i=10819 0 Disable i=47 i=9028 10819 true true i=3065 i=2803 Method_4 ns=1;i=10818 0 Enable i=47 i=9027 10818 true true i=3065 i=2803 Method_4 ns=1;i=10820 0 AddComment i=47 i=9029 10820 true true i=3065 i=2829 Variable_2 ns=1;i=10821 0 InputArguments i=46 i=68 10821 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=10824 0 AckedState i=47 i=8995 10824 i=21 -1 1 1 i=9004 true ns=1;i=10803 Variable_2 ns=1;i=10825 0 Id i=46 i=68 10825 i=1 -1 1 1 Method_4 ns=1;i=10840 0 Acknowledge i=47 i=9111 10840 true true i=3065 i=8944 Variable_2 ns=1;i=10841 0 InputArguments i=46 i=68 10841 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=10844 1 BooleanValue i=47 i=63 10844 i=1 -1 1 1 Variable_2 ns=1;i=10845 1 SByteValue i=47 i=63 10845 i=2 -1 1 1 Variable_2 ns=1;i=10846 1 ByteValue i=47 i=63 10846 i=3 -1 1 1 Variable_2 ns=1;i=10847 1 Int16Value i=47 i=63 10847 i=4 -1 1 1 Variable_2 ns=1;i=10848 1 UInt16Value i=47 i=63 10848 i=5 -1 1 1 Variable_2 ns=1;i=10849 1 Int32Value i=47 i=63 10849 i=6 -1 1 1 Variable_2 ns=1;i=10850 1 UInt32Value i=47 i=63 10850 i=7 -1 1 1 Variable_2 ns=1;i=10851 1 Int64Value i=47 i=63 10851 i=8 -1 1 1 Variable_2 ns=1;i=10852 1 UInt64Value i=47 i=63 10852 i=9 -1 1 1 Variable_2 ns=1;i=10853 1 FloatValue i=47 i=63 10853 i=10 -1 1 1 Variable_2 ns=1;i=10854 1 DoubleValue i=47 i=63 10854 i=11 -1 1 1 Variable_2 ns=1;i=10855 1 StringValue i=47 i=63 10855 i=12 -1 1 1 Variable_2 ns=1;i=10856 1 DateTimeValue i=47 i=63 10856 i=13 -1 1 1 Variable_2 ns=1;i=10857 1 GuidValue i=47 i=63 10857 i=14 -1 1 1 Variable_2 ns=1;i=10858 1 ByteStringValue i=47 i=63 10858 i=15 -1 1 1 Variable_2 ns=1;i=10859 1 XmlElementValue i=47 i=63 10859 i=16 -1 1 1 Variable_2 ns=1;i=10860 1 NodeIdValue i=47 i=63 10860 i=17 -1 1 1 Variable_2 ns=1;i=10861 1 ExpandedNodeIdValue i=47 i=63 10861 i=18 -1 1 1 Variable_2 ns=1;i=10862 1 QualifiedNameValue i=47 i=63 10862 i=20 -1 1 1 Variable_2 ns=1;i=10863 1 LocalizedTextValue i=47 i=63 10863 i=21 -1 1 1 Variable_2 ns=1;i=10864 1 StatusCodeValue i=47 i=63 10864 i=19 -1 1 1 Variable_2 ns=1;i=10865 1 VariantValue i=47 i=63 10865 i=24 -1 1 1 Variable_2 ns=1;i=10866 1 EnumerationValue i=47 i=63 10866 i=29 -1 1 1 Variable_2 ns=1;i=10867 1 StructureValue i=47 i=63 10867 i=22 -1 1 1 Variable_2 ns=1;i=10868 1 NumberValue i=47 i=63 10868 i=26 -1 1 1 Variable_2 ns=1;i=10869 1 IntegerValue i=47 i=63 10869 i=27 -1 1 1 Variable_2 ns=1;i=10870 1 UIntegerValue i=47 i=63 10870 i=28 -1 1 1 Object_1 ns=1;i=10871 1 Array i=47 ns=1;i=9679 10871 i=36 true ns=1;i=10786 i=36 ns=1;i=10875 Variable_2 ns=1;i=10872 1 SimulationActive If true the server will produce new values for each monitored variable. i=46 i=68 10872 true i=1 -1 1 1 Method_4 ns=1;i=10873 1 GenerateValues i=47 ns=1;i=9385 10873 true true Variable_2 ns=1;i=10874 0 InputArguments i=46 i=68 10874 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 Object_1 ns=1;i=10875 1 CycleComplete i=47 i=2881 10875 i=36 true ns=1;i=10871 Variable_2 ns=1;i=10876 0 EventId i=46 i=68 10876 i=15 -1 1 1 Variable_2 ns=1;i=10877 0 EventType i=46 i=68 10877 i=17 -1 1 1 Variable_2 ns=1;i=10878 0 SourceNode i=46 i=68 10878 i=17 -1 1 1 Variable_2 ns=1;i=10879 0 SourceName i=46 i=68 10879 i=12 -1 1 1 Variable_2 ns=1;i=10881 0 ReceiveTime i=46 i=68 10881 i=294 -1 1 1 Variable_2 ns=1;i=10883 0 Message i=46 i=68 10883 i=21 -1 1 1 Variable_2 ns=1;i=10884 0 Severity i=46 i=68 10884 i=5 -1 1 1 Variable_2 ns=1;i=11608 0 ConditionClassId i=46 i=68 11608 i=17 -1 1 1 Variable_2 ns=1;i=11609 0 ConditionClassName i=46 i=68 11609 i=21 -1 1 1 Variable_2 ns=1;i=11572 0 ConditionName i=46 i=68 11572 i=12 -1 1 1 Variable_2 ns=1;i=10885 0 BranchId i=46 i=68 10885 i=17 -1 1 1 Variable_2 ns=1;i=10886 0 Retain i=46 i=68 10886 i=1 -1 1 1 Variable_2 ns=1;i=10887 0 EnabledState i=47 i=8995 10887 i=21 -1 1 1 i=9004 ns=1;i=10908 i=9004 ns=1;i=10916 Variable_2 ns=1;i=10888 0 Id i=46 i=68 10888 i=1 -1 1 1 Variable_2 ns=1;i=10893 0 Quality i=47 i=9002 10893 i=19 -1 1 1 Variable_2 ns=1;i=10894 0 SourceTimestamp i=46 i=68 10894 i=294 -1 1 1 Variable_2 ns=1;i=10897 0 LastSeverity i=47 i=9002 10897 i=5 -1 1 1 Variable_2 ns=1;i=10898 0 SourceTimestamp i=46 i=68 10898 i=294 -1 1 1 Variable_2 ns=1;i=10899 0 Comment i=47 i=9002 10899 i=21 -1 1 1 Variable_2 ns=1;i=10900 0 SourceTimestamp i=46 i=68 10900 i=294 -1 1 1 Variable_2 ns=1;i=10901 0 ClientUserId i=46 i=68 10901 i=12 -1 1 1 Method_4 ns=1;i=10903 0 Disable i=47 i=9028 10903 true true i=3065 i=2803 Method_4 ns=1;i=10902 0 Enable i=47 i=9027 10902 true true i=3065 i=2803 Method_4 ns=1;i=10904 0 AddComment i=47 i=9029 10904 true true i=3065 i=2829 Variable_2 ns=1;i=10905 0 InputArguments i=46 i=68 10905 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=10908 0 AckedState i=47 i=8995 10908 i=21 -1 1 1 i=9004 true ns=1;i=10887 Variable_2 ns=1;i=10909 0 Id i=46 i=68 10909 i=1 -1 1 1 Method_4 ns=1;i=10924 0 Acknowledge i=47 i=9111 10924 true true i=3065 i=8944 Variable_2 ns=1;i=10925 0 InputArguments i=46 i=68 10925 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=10928 1 BooleanValue i=47 i=63 10928 i=1 1 0 1 1 Variable_2 ns=1;i=10929 1 SByteValue i=47 i=63 10929 i=2 1 0 1 1 Variable_2 ns=1;i=10930 1 ByteValue i=47 i=63 10930 i=3 1 0 1 1 Variable_2 ns=1;i=10931 1 Int16Value i=47 i=63 10931 i=4 1 0 1 1 Variable_2 ns=1;i=10932 1 UInt16Value i=47 i=63 10932 i=5 1 0 1 1 Variable_2 ns=1;i=10933 1 Int32Value i=47 i=63 10933 i=6 1 0 1 1 Variable_2 ns=1;i=10934 1 UInt32Value i=47 i=63 10934 i=7 1 0 1 1 Variable_2 ns=1;i=10935 1 Int64Value i=47 i=63 10935 i=8 1 0 1 1 Variable_2 ns=1;i=10936 1 UInt64Value i=47 i=63 10936 i=9 1 0 1 1 Variable_2 ns=1;i=10937 1 FloatValue i=47 i=63 10937 i=10 1 0 1 1 Variable_2 ns=1;i=10938 1 DoubleValue i=47 i=63 10938 i=11 1 0 1 1 Variable_2 ns=1;i=10939 1 StringValue i=47 i=63 10939 i=12 1 0 1 1 Variable_2 ns=1;i=10940 1 DateTimeValue i=47 i=63 10940 i=13 1 0 1 1 Variable_2 ns=1;i=10941 1 GuidValue i=47 i=63 10941 i=14 1 0 1 1 Variable_2 ns=1;i=10942 1 ByteStringValue i=47 i=63 10942 i=15 1 0 1 1 Variable_2 ns=1;i=10943 1 XmlElementValue i=47 i=63 10943 i=16 1 0 1 1 Variable_2 ns=1;i=10944 1 NodeIdValue i=47 i=63 10944 i=17 1 0 1 1 Variable_2 ns=1;i=10945 1 ExpandedNodeIdValue i=47 i=63 10945 i=18 1 0 1 1 Variable_2 ns=1;i=10946 1 QualifiedNameValue i=47 i=63 10946 i=20 1 0 1 1 Variable_2 ns=1;i=10947 1 LocalizedTextValue i=47 i=63 10947 i=21 1 0 1 1 Variable_2 ns=1;i=10948 1 StatusCodeValue i=47 i=63 10948 i=19 1 0 1 1 Variable_2 ns=1;i=10949 1 VariantValue i=47 i=63 10949 i=24 1 0 1 1 Variable_2 ns=1;i=10950 1 EnumerationValue i=47 i=63 10950 i=29 1 0 1 1 Variable_2 ns=1;i=10951 1 StructureValue i=47 i=63 10951 i=22 1 0 1 1 Variable_2 ns=1;i=10952 1 NumberValue i=47 i=63 10952 i=26 1 0 1 1 Variable_2 ns=1;i=10953 1 IntegerValue i=47 i=63 10953 i=27 1 0 1 1 Variable_2 ns=1;i=10954 1 UIntegerValue i=47 i=63 10954 i=28 1 0 1 1 Object_1 ns=1;i=10955 1 UserScalar i=47 ns=1;i=9921 10955 i=36 ns=1;i=10959 Variable_2 ns=1;i=10956 1 SimulationActive If true the server will produce new values for each monitored variable. i=46 i=68 10956 true i=1 -1 1 1 Method_4 ns=1;i=10957 1 GenerateValues i=47 ns=1;i=9385 10957 true true Variable_2 ns=1;i=10958 0 InputArguments i=46 i=68 10958 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 Object_1 ns=1;i=10959 1 CycleComplete i=47 i=2881 10959 i=36 true ns=1;i=10955 Variable_2 ns=1;i=10960 0 EventId i=46 i=68 10960 i=15 -1 1 1 Variable_2 ns=1;i=10961 0 EventType i=46 i=68 10961 i=17 -1 1 1 Variable_2 ns=1;i=10962 0 SourceNode i=46 i=68 10962 i=17 -1 1 1 Variable_2 ns=1;i=10963 0 SourceName i=46 i=68 10963 i=12 -1 1 1 Variable_2 ns=1;i=10965 0 ReceiveTime i=46 i=68 10965 i=294 -1 1 1 Variable_2 ns=1;i=10967 0 Message i=46 i=68 10967 i=21 -1 1 1 Variable_2 ns=1;i=10968 0 Severity i=46 i=68 10968 i=5 -1 1 1 Variable_2 ns=1;i=11610 0 ConditionClassId i=46 i=68 11610 i=17 -1 1 1 Variable_2 ns=1;i=11611 0 ConditionClassName i=46 i=68 11611 i=21 -1 1 1 Variable_2 ns=1;i=11573 0 ConditionName i=46 i=68 11573 i=12 -1 1 1 Variable_2 ns=1;i=10969 0 BranchId i=46 i=68 10969 i=17 -1 1 1 Variable_2 ns=1;i=10970 0 Retain i=46 i=68 10970 i=1 -1 1 1 Variable_2 ns=1;i=10971 0 EnabledState i=47 i=8995 10971 i=21 -1 1 1 i=9004 ns=1;i=10992 i=9004 ns=1;i=11000 Variable_2 ns=1;i=10972 0 Id i=46 i=68 10972 i=1 -1 1 1 Variable_2 ns=1;i=10977 0 Quality i=47 i=9002 10977 i=19 -1 1 1 Variable_2 ns=1;i=10978 0 SourceTimestamp i=46 i=68 10978 i=294 -1 1 1 Variable_2 ns=1;i=10981 0 LastSeverity i=47 i=9002 10981 i=5 -1 1 1 Variable_2 ns=1;i=10982 0 SourceTimestamp i=46 i=68 10982 i=294 -1 1 1 Variable_2 ns=1;i=10983 0 Comment i=47 i=9002 10983 i=21 -1 1 1 Variable_2 ns=1;i=10984 0 SourceTimestamp i=46 i=68 10984 i=294 -1 1 1 Variable_2 ns=1;i=10985 0 ClientUserId i=46 i=68 10985 i=12 -1 1 1 Method_4 ns=1;i=10987 0 Disable i=47 i=9028 10987 true true i=3065 i=2803 Method_4 ns=1;i=10986 0 Enable i=47 i=9027 10986 true true i=3065 i=2803 Method_4 ns=1;i=10988 0 AddComment i=47 i=9029 10988 true true i=3065 i=2829 Variable_2 ns=1;i=10989 0 InputArguments i=46 i=68 10989 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=10992 0 AckedState i=47 i=8995 10992 i=21 -1 1 1 i=9004 true ns=1;i=10971 Variable_2 ns=1;i=10993 0 Id i=46 i=68 10993 i=1 -1 1 1 Method_4 ns=1;i=11008 0 Acknowledge i=47 i=9111 11008 true true i=3065 i=8944 Variable_2 ns=1;i=11009 0 InputArguments i=46 i=68 11009 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=11012 1 BooleanValue i=47 i=63 11012 ns=1;i=9898 -1 1 1 Variable_2 ns=1;i=11013 1 SByteValue i=47 i=63 11013 ns=1;i=9899 -1 1 1 Variable_2 ns=1;i=11014 1 ByteValue i=47 i=63 11014 ns=1;i=9900 -1 1 1 Variable_2 ns=1;i=11015 1 Int16Value i=47 i=63 11015 ns=1;i=9901 -1 1 1 Variable_2 ns=1;i=11016 1 UInt16Value i=47 i=63 11016 ns=1;i=9902 -1 1 1 Variable_2 ns=1;i=11017 1 Int32Value i=47 i=63 11017 ns=1;i=9903 -1 1 1 Variable_2 ns=1;i=11018 1 UInt32Value i=47 i=63 11018 ns=1;i=9904 -1 1 1 Variable_2 ns=1;i=11019 1 Int64Value i=47 i=63 11019 ns=1;i=9905 -1 1 1 Variable_2 ns=1;i=11020 1 UInt64Value i=47 i=63 11020 ns=1;i=9906 -1 1 1 Variable_2 ns=1;i=11021 1 FloatValue i=47 i=63 11021 ns=1;i=9907 -1 1 1 Variable_2 ns=1;i=11022 1 DoubleValue i=47 i=63 11022 ns=1;i=9908 -1 1 1 Variable_2 ns=1;i=11023 1 StringValue i=47 i=63 11023 ns=1;i=9909 -1 1 1 Variable_2 ns=1;i=11024 1 DateTimeValue i=47 i=63 11024 ns=1;i=9910 -1 1 1 Variable_2 ns=1;i=11025 1 GuidValue i=47 i=63 11025 ns=1;i=9911 -1 1 1 Variable_2 ns=1;i=11026 1 ByteStringValue i=47 i=63 11026 ns=1;i=9912 -1 1 1 Variable_2 ns=1;i=11027 1 XmlElementValue i=47 i=63 11027 ns=1;i=9913 -1 1 1 Variable_2 ns=1;i=11028 1 NodeIdValue i=47 i=63 11028 ns=1;i=9914 -1 1 1 Variable_2 ns=1;i=11029 1 ExpandedNodeIdValue i=47 i=63 11029 ns=1;i=9915 -1 1 1 Variable_2 ns=1;i=11030 1 QualifiedNameValue i=47 i=63 11030 ns=1;i=9916 -1 1 1 Variable_2 ns=1;i=11031 1 LocalizedTextValue i=47 i=63 11031 ns=1;i=9917 -1 1 1 Variable_2 ns=1;i=11032 1 StatusCodeValue i=47 i=63 11032 ns=1;i=9918 -1 1 1 Variable_2 ns=1;i=11033 1 VariantValue i=47 i=63 11033 ns=1;i=9919 -1 1 1 Object_1 ns=1;i=11034 1 UserArray i=47 ns=1;i=10007 11034 i=36 ns=1;i=11038 Variable_2 ns=1;i=11035 1 SimulationActive If true the server will produce new values for each monitored variable. i=46 i=68 11035 true i=1 -1 1 1 Method_4 ns=1;i=11036 1 GenerateValues i=47 ns=1;i=9385 11036 true true Variable_2 ns=1;i=11037 0 InputArguments i=46 i=68 11037 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 Object_1 ns=1;i=11038 1 CycleComplete i=47 i=2881 11038 i=36 true ns=1;i=11034 Variable_2 ns=1;i=11039 0 EventId i=46 i=68 11039 i=15 -1 1 1 Variable_2 ns=1;i=11040 0 EventType i=46 i=68 11040 i=17 -1 1 1 Variable_2 ns=1;i=11041 0 SourceNode i=46 i=68 11041 i=17 -1 1 1 Variable_2 ns=1;i=11042 0 SourceName i=46 i=68 11042 i=12 -1 1 1 Variable_2 ns=1;i=11044 0 ReceiveTime i=46 i=68 11044 i=294 -1 1 1 Variable_2 ns=1;i=11046 0 Message i=46 i=68 11046 i=21 -1 1 1 Variable_2 ns=1;i=11047 0 Severity i=46 i=68 11047 i=5 -1 1 1 Variable_2 ns=1;i=11612 0 ConditionClassId i=46 i=68 11612 i=17 -1 1 1 Variable_2 ns=1;i=11613 0 ConditionClassName i=46 i=68 11613 i=21 -1 1 1 Variable_2 ns=1;i=11574 0 ConditionName i=46 i=68 11574 i=12 -1 1 1 Variable_2 ns=1;i=11048 0 BranchId i=46 i=68 11048 i=17 -1 1 1 Variable_2 ns=1;i=11049 0 Retain i=46 i=68 11049 i=1 -1 1 1 Variable_2 ns=1;i=11050 0 EnabledState i=47 i=8995 11050 i=21 -1 1 1 i=9004 ns=1;i=11071 i=9004 ns=1;i=11079 Variable_2 ns=1;i=11051 0 Id i=46 i=68 11051 i=1 -1 1 1 Variable_2 ns=1;i=11056 0 Quality i=47 i=9002 11056 i=19 -1 1 1 Variable_2 ns=1;i=11057 0 SourceTimestamp i=46 i=68 11057 i=294 -1 1 1 Variable_2 ns=1;i=11060 0 LastSeverity i=47 i=9002 11060 i=5 -1 1 1 Variable_2 ns=1;i=11061 0 SourceTimestamp i=46 i=68 11061 i=294 -1 1 1 Variable_2 ns=1;i=11062 0 Comment i=47 i=9002 11062 i=21 -1 1 1 Variable_2 ns=1;i=11063 0 SourceTimestamp i=46 i=68 11063 i=294 -1 1 1 Variable_2 ns=1;i=11064 0 ClientUserId i=46 i=68 11064 i=12 -1 1 1 Method_4 ns=1;i=11066 0 Disable i=47 i=9028 11066 true true i=3065 i=2803 Method_4 ns=1;i=11065 0 Enable i=47 i=9027 11065 true true i=3065 i=2803 Method_4 ns=1;i=11067 0 AddComment i=47 i=9029 11067 true true i=3065 i=2829 Variable_2 ns=1;i=11068 0 InputArguments i=46 i=68 11068 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=11071 0 AckedState i=47 i=8995 11071 i=21 -1 1 1 i=9004 true ns=1;i=11050 Variable_2 ns=1;i=11072 0 Id i=46 i=68 11072 i=1 -1 1 1 Method_4 ns=1;i=11087 0 Acknowledge i=47 i=9111 11087 true true i=3065 i=8944 Variable_2 ns=1;i=11088 0 InputArguments i=46 i=68 11088 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=11091 1 BooleanValue i=47 i=63 11091 ns=1;i=9898 1 0 1 1 Variable_2 ns=1;i=11092 1 SByteValue i=47 i=63 11092 ns=1;i=9899 1 0 1 1 Variable_2 ns=1;i=11093 1 ByteValue i=47 i=63 11093 ns=1;i=9900 1 0 1 1 Variable_2 ns=1;i=11094 1 Int16Value i=47 i=63 11094 ns=1;i=9901 1 0 1 1 Variable_2 ns=1;i=11095 1 UInt16Value i=47 i=63 11095 ns=1;i=9902 1 0 1 1 Variable_2 ns=1;i=11096 1 Int32Value i=47 i=63 11096 ns=1;i=9903 1 0 1 1 Variable_2 ns=1;i=11097 1 UInt32Value i=47 i=63 11097 ns=1;i=9904 1 0 1 1 Variable_2 ns=1;i=11098 1 Int64Value i=47 i=63 11098 ns=1;i=9905 1 0 1 1 Variable_2 ns=1;i=11099 1 UInt64Value i=47 i=63 11099 ns=1;i=9906 1 0 1 1 Variable_2 ns=1;i=11100 1 FloatValue i=47 i=63 11100 ns=1;i=9907 1 0 1 1 Variable_2 ns=1;i=11101 1 DoubleValue i=47 i=63 11101 ns=1;i=9908 1 0 1 1 Variable_2 ns=1;i=11102 1 StringValue i=47 i=63 11102 ns=1;i=9909 1 0 1 1 Variable_2 ns=1;i=11103 1 DateTimeValue i=47 i=63 11103 ns=1;i=9910 1 0 1 1 Variable_2 ns=1;i=11104 1 GuidValue i=47 i=63 11104 ns=1;i=9911 1 0 1 1 Variable_2 ns=1;i=11105 1 ByteStringValue i=47 i=63 11105 ns=1;i=9912 1 0 1 1 Variable_2 ns=1;i=11106 1 XmlElementValue i=47 i=63 11106 ns=1;i=9913 1 0 1 1 Variable_2 ns=1;i=11107 1 NodeIdValue i=47 i=63 11107 ns=1;i=9914 1 0 1 1 Variable_2 ns=1;i=11108 1 ExpandedNodeIdValue i=47 i=63 11108 ns=1;i=9915 1 0 1 1 Variable_2 ns=1;i=11109 1 QualifiedNameValue i=47 i=63 11109 ns=1;i=9916 1 0 1 1 Variable_2 ns=1;i=11110 1 LocalizedTextValue i=47 i=63 11110 ns=1;i=9917 1 0 1 1 Variable_2 ns=1;i=11111 1 StatusCodeValue i=47 i=63 11111 ns=1;i=9918 1 0 1 1 Variable_2 ns=1;i=11112 1 VariantValue i=47 i=63 11112 ns=1;i=9919 1 0 1 1 Object_1 ns=1;i=11113 1 AnalogScalar i=47 ns=1;i=9534 11113 i=36 ns=1;i=11117 Variable_2 ns=1;i=11114 1 SimulationActive If true the server will produce new values for each monitored variable. i=46 i=68 11114 true i=1 -1 1 1 Method_4 ns=1;i=11115 1 GenerateValues i=47 ns=1;i=9385 11115 true true Variable_2 ns=1;i=11116 0 InputArguments i=46 i=68 11116 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 Object_1 ns=1;i=11117 1 CycleComplete i=47 i=2881 11117 i=36 true ns=1;i=11113 Variable_2 ns=1;i=11118 0 EventId i=46 i=68 11118 i=15 -1 1 1 Variable_2 ns=1;i=11119 0 EventType i=46 i=68 11119 i=17 -1 1 1 Variable_2 ns=1;i=11120 0 SourceNode i=46 i=68 11120 i=17 -1 1 1 Variable_2 ns=1;i=11121 0 SourceName i=46 i=68 11121 i=12 -1 1 1 Variable_2 ns=1;i=11123 0 ReceiveTime i=46 i=68 11123 i=294 -1 1 1 Variable_2 ns=1;i=11125 0 Message i=46 i=68 11125 i=21 -1 1 1 Variable_2 ns=1;i=11126 0 Severity i=46 i=68 11126 i=5 -1 1 1 Variable_2 ns=1;i=11614 0 ConditionClassId i=46 i=68 11614 i=17 -1 1 1 Variable_2 ns=1;i=11615 0 ConditionClassName i=46 i=68 11615 i=21 -1 1 1 Variable_2 ns=1;i=11575 0 ConditionName i=46 i=68 11575 i=12 -1 1 1 Variable_2 ns=1;i=11127 0 BranchId i=46 i=68 11127 i=17 -1 1 1 Variable_2 ns=1;i=11128 0 Retain i=46 i=68 11128 i=1 -1 1 1 Variable_2 ns=1;i=11129 0 EnabledState i=47 i=8995 11129 i=21 -1 1 1 i=9004 ns=1;i=11150 i=9004 ns=1;i=11158 Variable_2 ns=1;i=11130 0 Id i=46 i=68 11130 i=1 -1 1 1 Variable_2 ns=1;i=11135 0 Quality i=47 i=9002 11135 i=19 -1 1 1 Variable_2 ns=1;i=11136 0 SourceTimestamp i=46 i=68 11136 i=294 -1 1 1 Variable_2 ns=1;i=11139 0 LastSeverity i=47 i=9002 11139 i=5 -1 1 1 Variable_2 ns=1;i=11140 0 SourceTimestamp i=46 i=68 11140 i=294 -1 1 1 Variable_2 ns=1;i=11141 0 Comment i=47 i=9002 11141 i=21 -1 1 1 Variable_2 ns=1;i=11142 0 SourceTimestamp i=46 i=68 11142 i=294 -1 1 1 Variable_2 ns=1;i=11143 0 ClientUserId i=46 i=68 11143 i=12 -1 1 1 Method_4 ns=1;i=11145 0 Disable i=47 i=9028 11145 true true i=3065 i=2803 Method_4 ns=1;i=11144 0 Enable i=47 i=9027 11144 true true i=3065 i=2803 Method_4 ns=1;i=11146 0 AddComment i=47 i=9029 11146 true true i=3065 i=2829 Variable_2 ns=1;i=11147 0 InputArguments i=46 i=68 11147 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=11150 0 AckedState i=47 i=8995 11150 i=21 -1 1 1 i=9004 true ns=1;i=11129 Variable_2 ns=1;i=11151 0 Id i=46 i=68 11151 i=1 -1 1 1 Method_4 ns=1;i=11166 0 Acknowledge i=47 i=9111 11166 true true i=3065 i=8944 Variable_2 ns=1;i=11167 0 InputArguments i=46 i=68 11167 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=11170 1 SByteValue i=47 i=2368 11170 i=2 -1 1 1 Variable_2 ns=1;i=11173 0 EURange i=46 i=68 11173 i=884 -1 1 1 Variable_2 ns=1;i=11176 1 ByteValue i=47 i=2368 11176 i=3 -1 1 1 Variable_2 ns=1;i=11179 0 EURange i=46 i=68 11179 i=884 -1 1 1 Variable_2 ns=1;i=11182 1 Int16Value i=47 i=2368 11182 i=4 -1 1 1 Variable_2 ns=1;i=11185 0 EURange i=46 i=68 11185 i=884 -1 1 1 Variable_2 ns=1;i=11188 1 UInt16Value i=47 i=2368 11188 i=5 -1 1 1 Variable_2 ns=1;i=11191 0 EURange i=46 i=68 11191 i=884 -1 1 1 Variable_2 ns=1;i=11194 1 Int32Value i=47 i=2368 11194 i=6 -1 1 1 Variable_2 ns=1;i=11197 0 EURange i=46 i=68 11197 i=884 -1 1 1 Variable_2 ns=1;i=11200 1 UInt32Value i=47 i=2368 11200 i=7 -1 1 1 Variable_2 ns=1;i=11203 0 EURange i=46 i=68 11203 i=884 -1 1 1 Variable_2 ns=1;i=11206 1 Int64Value i=47 i=2368 11206 i=8 -1 1 1 Variable_2 ns=1;i=11209 0 EURange i=46 i=68 11209 i=884 -1 1 1 Variable_2 ns=1;i=11212 1 UInt64Value i=47 i=2368 11212 i=9 -1 1 1 Variable_2 ns=1;i=11215 0 EURange i=46 i=68 11215 i=884 -1 1 1 Variable_2 ns=1;i=11218 1 FloatValue i=47 i=2368 11218 i=10 -1 1 1 Variable_2 ns=1;i=11221 0 EURange i=46 i=68 11221 i=884 -1 1 1 Variable_2 ns=1;i=11224 1 DoubleValue i=47 i=2368 11224 i=11 -1 1 1 Variable_2 ns=1;i=11227 0 EURange i=46 i=68 11227 i=884 -1 1 1 Variable_2 ns=1;i=11230 1 NumberValue i=47 i=2368 11230 i=26 -1 1 1 Variable_2 ns=1;i=11233 0 EURange i=46 i=68 11233 i=884 -1 1 1 Variable_2 ns=1;i=11236 1 IntegerValue i=47 i=2368 11236 i=27 -1 1 1 Variable_2 ns=1;i=11239 0 EURange i=46 i=68 11239 i=884 -1 1 1 Variable_2 ns=1;i=11242 1 UIntegerValue i=47 i=2368 11242 i=28 -1 1 1 Variable_2 ns=1;i=11245 0 EURange i=46 i=68 11245 i=884 -1 1 1 Object_1 ns=1;i=11248 1 AnalogArray i=47 ns=1;i=9763 11248 i=36 ns=1;i=11252 Variable_2 ns=1;i=11249 1 SimulationActive If true the server will produce new values for each monitored variable. i=46 i=68 11249 true i=1 -1 1 1 Method_4 ns=1;i=11250 1 GenerateValues i=47 ns=1;i=9385 11250 true true Variable_2 ns=1;i=11251 0 InputArguments i=46 i=68 11251 i=297 Iterations i=7 -1 The number of new values to generate. i=296 1 0 1 1 Object_1 ns=1;i=11252 1 CycleComplete i=47 i=2881 11252 i=36 true ns=1;i=11248 Variable_2 ns=1;i=11253 0 EventId i=46 i=68 11253 i=15 -1 1 1 Variable_2 ns=1;i=11254 0 EventType i=46 i=68 11254 i=17 -1 1 1 Variable_2 ns=1;i=11255 0 SourceNode i=46 i=68 11255 i=17 -1 1 1 Variable_2 ns=1;i=11256 0 SourceName i=46 i=68 11256 i=12 -1 1 1 Variable_2 ns=1;i=11258 0 ReceiveTime i=46 i=68 11258 i=294 -1 1 1 Variable_2 ns=1;i=11260 0 Message i=46 i=68 11260 i=21 -1 1 1 Variable_2 ns=1;i=11261 0 Severity i=46 i=68 11261 i=5 -1 1 1 Variable_2 ns=1;i=11616 0 ConditionClassId i=46 i=68 11616 i=17 -1 1 1 Variable_2 ns=1;i=11617 0 ConditionClassName i=46 i=68 11617 i=21 -1 1 1 Variable_2 ns=1;i=11576 0 ConditionName i=46 i=68 11576 i=12 -1 1 1 Variable_2 ns=1;i=11262 0 BranchId i=46 i=68 11262 i=17 -1 1 1 Variable_2 ns=1;i=11263 0 Retain i=46 i=68 11263 i=1 -1 1 1 Variable_2 ns=1;i=11264 0 EnabledState i=47 i=8995 11264 i=21 -1 1 1 i=9004 ns=1;i=11285 i=9004 ns=1;i=11293 Variable_2 ns=1;i=11265 0 Id i=46 i=68 11265 i=1 -1 1 1 Variable_2 ns=1;i=11270 0 Quality i=47 i=9002 11270 i=19 -1 1 1 Variable_2 ns=1;i=11271 0 SourceTimestamp i=46 i=68 11271 i=294 -1 1 1 Variable_2 ns=1;i=11274 0 LastSeverity i=47 i=9002 11274 i=5 -1 1 1 Variable_2 ns=1;i=11275 0 SourceTimestamp i=46 i=68 11275 i=294 -1 1 1 Variable_2 ns=1;i=11276 0 Comment i=47 i=9002 11276 i=21 -1 1 1 Variable_2 ns=1;i=11277 0 SourceTimestamp i=46 i=68 11277 i=294 -1 1 1 Variable_2 ns=1;i=11278 0 ClientUserId i=46 i=68 11278 i=12 -1 1 1 Method_4 ns=1;i=11280 0 Disable i=47 i=9028 11280 true true i=3065 i=2803 Method_4 ns=1;i=11279 0 Enable i=47 i=9027 11279 true true i=3065 i=2803 Method_4 ns=1;i=11281 0 AddComment i=47 i=9029 11281 true true i=3065 i=2829 Variable_2 ns=1;i=11282 0 InputArguments i=46 i=68 11282 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=11285 0 AckedState i=47 i=8995 11285 i=21 -1 1 1 i=9004 true ns=1;i=11264 Variable_2 ns=1;i=11286 0 Id i=46 i=68 11286 i=1 -1 1 1 Method_4 ns=1;i=11301 0 Acknowledge i=47 i=9111 11301 true true i=3065 i=8944 Variable_2 ns=1;i=11302 0 InputArguments i=46 i=68 11302 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=11305 1 SByteValue i=47 i=2368 11305 i=2 1 0 1 1 Variable_2 ns=1;i=11308 0 EURange i=46 i=68 11308 i=884 -1 1 1 Variable_2 ns=1;i=11311 1 ByteValue i=47 i=2368 11311 i=3 1 0 1 1 Variable_2 ns=1;i=11314 0 EURange i=46 i=68 11314 i=884 -1 1 1 Variable_2 ns=1;i=11317 1 Int16Value i=47 i=2368 11317 i=4 1 0 1 1 Variable_2 ns=1;i=11320 0 EURange i=46 i=68 11320 i=884 -1 1 1 Variable_2 ns=1;i=11323 1 UInt16Value i=47 i=2368 11323 i=5 1 0 1 1 Variable_2 ns=1;i=11326 0 EURange i=46 i=68 11326 i=884 -1 1 1 Variable_2 ns=1;i=11329 1 Int32Value i=47 i=2368 11329 i=6 1 0 1 1 Variable_2 ns=1;i=11332 0 EURange i=46 i=68 11332 i=884 -1 1 1 Variable_2 ns=1;i=11335 1 UInt32Value i=47 i=2368 11335 i=7 1 0 1 1 Variable_2 ns=1;i=11338 0 EURange i=46 i=68 11338 i=884 -1 1 1 Variable_2 ns=1;i=11341 1 Int64Value i=47 i=2368 11341 i=8 1 0 1 1 Variable_2 ns=1;i=11344 0 EURange i=46 i=68 11344 i=884 -1 1 1 Variable_2 ns=1;i=11347 1 UInt64Value i=47 i=2368 11347 i=9 1 0 1 1 Variable_2 ns=1;i=11350 0 EURange i=46 i=68 11350 i=884 -1 1 1 Variable_2 ns=1;i=11353 1 FloatValue i=47 i=2368 11353 i=10 1 0 1 1 Variable_2 ns=1;i=11356 0 EURange i=46 i=68 11356 i=884 -1 1 1 Variable_2 ns=1;i=11359 1 DoubleValue i=47 i=2368 11359 i=11 1 0 1 1 Variable_2 ns=1;i=11362 0 EURange i=46 i=68 11362 i=884 -1 1 1 Variable_2 ns=1;i=11365 1 NumberValue i=47 i=2368 11365 i=26 1 0 1 1 Variable_2 ns=1;i=11368 0 EURange i=46 i=68 11368 i=884 -1 1 1 Variable_2 ns=1;i=11371 1 IntegerValue i=47 i=2368 11371 i=27 1 0 1 1 Variable_2 ns=1;i=11374 0 EURange i=46 i=68 11374 i=884 -1 1 1 Variable_2 ns=1;i=11377 1 UIntegerValue i=47 i=2368 11377 i=28 1 0 1 1 Variable_2 ns=1;i=11380 0 EURange i=46 i=68 11380 i=884 -1 1 1 Object_1 ns=1;i=11383 1 Conditions i=47 i=61 11383 1 i=36 ns=1;i=11384 Object_1 ns=1;i=11384 1 SystemStatus i=47 ns=1;i=10123 11384 i=36 true ns=1;i=11383 Variable_2 ns=1;i=11385 0 EventId i=46 i=68 11385 i=15 -1 1 1 Variable_2 ns=1;i=11386 0 EventType i=46 i=68 11386 i=17 -1 1 1 Variable_2 ns=1;i=11387 0 SourceNode i=46 i=68 11387 i=17 -1 1 1 Variable_2 ns=1;i=11388 0 SourceName i=46 i=68 11388 i=12 -1 1 1 Variable_2 ns=1;i=11390 0 ReceiveTime i=46 i=68 11390 i=294 -1 1 1 Variable_2 ns=1;i=11392 0 Message i=46 i=68 11392 i=21 -1 1 1 Variable_2 ns=1;i=11393 0 Severity i=46 i=68 11393 i=5 -1 1 1 Variable_2 ns=1;i=11618 0 ConditionClassId i=46 i=68 11618 i=17 -1 1 1 Variable_2 ns=1;i=11619 0 ConditionClassName i=46 i=68 11619 i=21 -1 1 1 Variable_2 ns=1;i=11577 0 ConditionName i=46 i=68 11577 i=12 -1 1 1 Variable_2 ns=1;i=11394 0 BranchId i=46 i=68 11394 i=17 -1 1 1 Variable_2 ns=1;i=11395 0 Retain i=46 i=68 11395 i=1 -1 1 1 Variable_2 ns=1;i=11396 0 EnabledState i=47 i=8995 11396 i=21 -1 1 1 Variable_2 ns=1;i=11397 0 Id i=46 i=68 11397 i=1 -1 1 1 Variable_2 ns=1;i=11402 0 Quality i=47 i=9002 11402 i=19 -1 1 1 Variable_2 ns=1;i=11403 0 SourceTimestamp i=46 i=68 11403 i=294 -1 1 1 Variable_2 ns=1;i=11406 0 LastSeverity i=47 i=9002 11406 i=5 -1 1 1 Variable_2 ns=1;i=11407 0 SourceTimestamp i=46 i=68 11407 i=294 -1 1 1 Variable_2 ns=1;i=11408 0 Comment i=47 i=9002 11408 i=21 -1 1 1 Variable_2 ns=1;i=11409 0 SourceTimestamp i=46 i=68 11409 i=294 -1 1 1 Variable_2 ns=1;i=11410 0 ClientUserId i=46 i=68 11410 i=12 -1 1 1 Method_4 ns=1;i=11412 0 Disable i=47 i=9028 11412 true true i=3065 i=2803 Method_4 ns=1;i=11411 0 Enable i=47 i=9027 11411 true true i=3065 i=2803 Method_4 ns=1;i=11413 0 AddComment i=47 i=9029 11413 true true i=3065 i=2829 Variable_2 ns=1;i=11414 0 InputArguments i=46 i=68 11414 i=297 EventId i=15 -1 The identifier for the event to comment. i=297 Comment i=21 -1 The comment to add to the condition. i=296 1 0 1 1 Variable_2 ns=1;i=11417 1 MonitoredNodeCount i=46 i=68 11417 i=6 -1 1 1 Object_1 ns=1;i=11437 0 Default Binary i=76 11437 i=38 true ns=1;i=9440 i=39 ns=1;i=11425 Object_1 ns=1;i=11438 0 Default Binary i=76 11438 i=38 true ns=1;i=9669 i=39 ns=1;i=11428 Object_1 ns=1;i=11439 0 Default Binary i=76 11439 i=38 true ns=1;i=9920 i=39 ns=1;i=11431 Object_1 ns=1;i=11440 0 Default Binary i=76 11440 i=38 true ns=1;i=10006 i=39 ns=1;i=11434 Object_1 ns=1;i=1008 0 Default Binary i=76 1008 i=38 true ns=1;i=1000 i=39 ns=1;i=1015 Object_1 ns=1;i=1011 0 Default Binary i=76 1011 i=38 true ns=1;i=1004 i=39 ns=1;i=24 Object_1 ns=1;i=1012 0 Default Binary i=76 1012 i=38 true ns=1;i=1005 i=39 ns=1;i=27 Variable_2 ns=1;i=11422 1 TestData i=72 11422 PG9wYzpUeXBlRGljdGlvbmFyeQ0KICB4bWxuczpvcGM9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9y Zy9CaW5hcnlTY2hlbWEvIg0KICB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1M U2NoZW1hLWluc3RhbmNlIg0KICB4bWxuczp1YT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VB LyINCiAgeG1sbnM6dG5zPSJodHRwOi8vdGVzdC5vcmcvVUEvRGF0YS8iDQogIERlZmF1bHRCeXRl T3JkZXI9IkxpdHRsZUVuZGlhbiINCiAgVGFyZ2V0TmFtZXNwYWNlPSJodHRwOi8vdGVzdC5vcmcv VUEvRGF0YS8iDQo+DQogIDxvcGM6SW1wb3J0IE5hbWVzcGFjZT0iaHR0cDovL29wY2ZvdW5kYXRp b24ub3JnL1VBLyIgTG9jYXRpb249Ik9wYy5VYS5CaW5hcnlTY2hlbWEuYnNkIi8+DQoNCiAgPG9w YzpTdHJ1Y3R1cmVkVHlwZSBOYW1lPSJTY2FsYXJWYWx1ZURhdGFUeXBlIiBCYXNlVHlwZT0idWE6 RXh0ZW5zaW9uT2JqZWN0Ij4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkJvb2xlYW5WYWx1ZSIgVHlw ZU5hbWU9Im9wYzpCb29sZWFuIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iU0J5dGVWYWx1ZSIg VHlwZU5hbWU9Im9wYzpTQnl0ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkJ5dGVWYWx1ZSIg VHlwZU5hbWU9Im9wYzpCeXRlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iSW50MTZWYWx1ZSIg VHlwZU5hbWU9Im9wYzpJbnQxNiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IlVJbnQxNlZhbHVl IiBUeXBlTmFtZT0ib3BjOlVJbnQxNiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkludDMyVmFs dWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJVSW50MzJW YWx1ZSIgVHlwZU5hbWU9Im9wYzpVSW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJJbnQ2 NFZhbHVlIiBUeXBlTmFtZT0ib3BjOkludDY0IiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iVUlu dDY0VmFsdWUiIFR5cGVOYW1lPSJvcGM6VUludDY0IiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0i RmxvYXRWYWx1ZSIgVHlwZU5hbWU9Im9wYzpGbG9hdCIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9 IkRvdWJsZVZhbHVlIiBUeXBlTmFtZT0ib3BjOkRvdWJsZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5h bWU9IlN0cmluZ1ZhbHVlIiBUeXBlTmFtZT0ib3BjOlN0cmluZyIgLz4NCiAgICA8b3BjOkZpZWxk IE5hbWU9IkRhdGVUaW1lVmFsdWUiIFR5cGVOYW1lPSJvcGM6RGF0ZVRpbWUiIC8+DQogICAgPG9w YzpGaWVsZCBOYW1lPSJHdWlkVmFsdWUiIFR5cGVOYW1lPSJvcGM6R3VpZCIgLz4NCiAgICA8b3Bj OkZpZWxkIE5hbWU9IkJ5dGVTdHJpbmdWYWx1ZSIgVHlwZU5hbWU9Im9wYzpCeXRlU3RyaW5nIiAv Pg0KICAgIDxvcGM6RmllbGQgTmFtZT0iWG1sRWxlbWVudFZhbHVlIiBUeXBlTmFtZT0idWE6WG1s RWxlbWVudCIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vZGVJZFZhbHVlIiBUeXBlTmFtZT0i dWE6Tm9kZUlkIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iRXhwYW5kZWROb2RlSWRWYWx1ZSIg VHlwZU5hbWU9InVhOkV4cGFuZGVkTm9kZUlkIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iUXVh bGlmaWVkTmFtZVZhbHVlIiBUeXBlTmFtZT0idWE6UXVhbGlmaWVkTmFtZSIgLz4NCiAgICA8b3Bj OkZpZWxkIE5hbWU9IkxvY2FsaXplZFRleHRWYWx1ZSIgVHlwZU5hbWU9InVhOkxvY2FsaXplZFRl eHQiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJTdGF0dXNDb2RlVmFsdWUiIFR5cGVOYW1lPSJ1 YTpTdGF0dXNDb2RlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iVmFyaWFudFZhbHVlIiBUeXBl TmFtZT0idWE6VmFyaWFudCIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkVudW1lcmF0aW9uVmFs dWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJTdHJ1Y3R1 cmVWYWx1ZSIgVHlwZU5hbWU9InVhOkV4dGVuc2lvbk9iamVjdCIgLz4NCiAgICA8b3BjOkZpZWxk IE5hbWU9Ik51bWJlciIgVHlwZU5hbWU9InVhOlZhcmlhbnQiIC8+DQogICAgPG9wYzpGaWVsZCBO YW1lPSJJbnRlZ2VyIiBUeXBlTmFtZT0idWE6VmFyaWFudCIgLz4NCiAgICA8b3BjOkZpZWxkIE5h bWU9IlVJbnRlZ2VyIiBUeXBlTmFtZT0idWE6VmFyaWFudCIgLz4NCiAgPC9vcGM6U3RydWN0dXJl ZFR5cGU+DQoNCiAgPG9wYzpTdHJ1Y3R1cmVkVHlwZSBOYW1lPSJBcnJheVZhbHVlRGF0YVR5cGUi IEJhc2VUeXBlPSJ1YTpFeHRlbnNpb25PYmplY3QiPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9P ZkJvb2xlYW5WYWx1ZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8b3BjOkZpZWxkIE5h bWU9IkJvb2xlYW5WYWx1ZSIgVHlwZU5hbWU9Im9wYzpCb29sZWFuIiBMZW5ndGhGaWVsZD0iTm9P ZkJvb2xlYW5WYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZTQnl0ZVZhbHVlIiBU eXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iU0J5dGVWYWx1ZSIg VHlwZU5hbWU9Im9wYzpTQnl0ZSIgTGVuZ3RoRmllbGQ9Ik5vT2ZTQnl0ZVZhbHVlIiAvPg0KICAg IDxvcGM6RmllbGQgTmFtZT0iTm9PZkJ5dGVWYWx1ZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4N CiAgICA8b3BjOkZpZWxkIE5hbWU9IkJ5dGVWYWx1ZSIgVHlwZU5hbWU9Im9wYzpCeXRlIiBMZW5n dGhGaWVsZD0iTm9PZkJ5dGVWYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZJbnQx NlZhbHVlIiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iSW50 MTZWYWx1ZSIgVHlwZU5hbWU9Im9wYzpJbnQxNiIgTGVuZ3RoRmllbGQ9Ik5vT2ZJbnQxNlZhbHVl IiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZlVJbnQxNlZhbHVlIiBUeXBlTmFtZT0ib3Bj OkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iVUludDE2VmFsdWUiIFR5cGVOYW1lPSJv cGM6VUludDE2IiBMZW5ndGhGaWVsZD0iTm9PZlVJbnQxNlZhbHVlIiAvPg0KICAgIDxvcGM6Rmll bGQgTmFtZT0iTm9PZkludDMyVmFsdWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9w YzpGaWVsZCBOYW1lPSJJbnQzMlZhbHVlIiBUeXBlTmFtZT0ib3BjOkludDMyIiBMZW5ndGhGaWVs ZD0iTm9PZkludDMyVmFsdWUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mVUludDMyVmFs dWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJVSW50MzJW YWx1ZSIgVHlwZU5hbWU9Im9wYzpVSW50MzIiIExlbmd0aEZpZWxkPSJOb09mVUludDMyVmFsdWUi IC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mSW50NjRWYWx1ZSIgVHlwZU5hbWU9Im9wYzpJ bnQzMiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkludDY0VmFsdWUiIFR5cGVOYW1lPSJvcGM6 SW50NjQiIExlbmd0aEZpZWxkPSJOb09mSW50NjRWYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5h bWU9Ik5vT2ZVSW50NjRWYWx1ZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8b3BjOkZp ZWxkIE5hbWU9IlVJbnQ2NFZhbHVlIiBUeXBlTmFtZT0ib3BjOlVJbnQ2NCIgTGVuZ3RoRmllbGQ9 Ik5vT2ZVSW50NjRWYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZGbG9hdFZhbHVl IiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iRmxvYXRWYWx1 ZSIgVHlwZU5hbWU9Im9wYzpGbG9hdCIgTGVuZ3RoRmllbGQ9Ik5vT2ZGbG9hdFZhbHVlIiAvPg0K ICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZkRvdWJsZVZhbHVlIiBUeXBlTmFtZT0ib3BjOkludDMy IiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iRG91YmxlVmFsdWUiIFR5cGVOYW1lPSJvcGM6RG91 YmxlIiBMZW5ndGhGaWVsZD0iTm9PZkRvdWJsZVZhbHVlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFt ZT0iTm9PZlN0cmluZ1ZhbHVlIiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6Rmll bGQgTmFtZT0iU3RyaW5nVmFsdWUiIFR5cGVOYW1lPSJvcGM6U3RyaW5nIiBMZW5ndGhGaWVsZD0i Tm9PZlN0cmluZ1ZhbHVlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZkRhdGVUaW1lVmFs dWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJEYXRlVGlt ZVZhbHVlIiBUeXBlTmFtZT0ib3BjOkRhdGVUaW1lIiBMZW5ndGhGaWVsZD0iTm9PZkRhdGVUaW1l VmFsdWUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mR3VpZFZhbHVlIiBUeXBlTmFtZT0i b3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iR3VpZFZhbHVlIiBUeXBlTmFtZT0i b3BjOkd1aWQiIExlbmd0aEZpZWxkPSJOb09mR3VpZFZhbHVlIiAvPg0KICAgIDxvcGM6RmllbGQg TmFtZT0iTm9PZkJ5dGVTdHJpbmdWYWx1ZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8 b3BjOkZpZWxkIE5hbWU9IkJ5dGVTdHJpbmdWYWx1ZSIgVHlwZU5hbWU9Im9wYzpCeXRlU3RyaW5n IiBMZW5ndGhGaWVsZD0iTm9PZkJ5dGVTdHJpbmdWYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5h bWU9Ik5vT2ZYbWxFbGVtZW50VmFsdWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9w YzpGaWVsZCBOYW1lPSJYbWxFbGVtZW50VmFsdWUiIFR5cGVOYW1lPSJ1YTpYbWxFbGVtZW50IiBM ZW5ndGhGaWVsZD0iTm9PZlhtbEVsZW1lbnRWYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9 Ik5vT2ZOb2RlSWRWYWx1ZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8b3BjOkZpZWxk IE5hbWU9Ik5vZGVJZFZhbHVlIiBUeXBlTmFtZT0idWE6Tm9kZUlkIiBMZW5ndGhGaWVsZD0iTm9P Zk5vZGVJZFZhbHVlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZkV4cGFuZGVkTm9kZUlk VmFsdWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJFeHBh bmRlZE5vZGVJZFZhbHVlIiBUeXBlTmFtZT0idWE6RXhwYW5kZWROb2RlSWQiIExlbmd0aEZpZWxk PSJOb09mRXhwYW5kZWROb2RlSWRWYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZR dWFsaWZpZWROYW1lVmFsdWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVs ZCBOYW1lPSJRdWFsaWZpZWROYW1lVmFsdWUiIFR5cGVOYW1lPSJ1YTpRdWFsaWZpZWROYW1lIiBM ZW5ndGhGaWVsZD0iTm9PZlF1YWxpZmllZE5hbWVWYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5h bWU9Ik5vT2ZMb2NhbGl6ZWRUZXh0VmFsdWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAg PG9wYzpGaWVsZCBOYW1lPSJMb2NhbGl6ZWRUZXh0VmFsdWUiIFR5cGVOYW1lPSJ1YTpMb2NhbGl6 ZWRUZXh0IiBMZW5ndGhGaWVsZD0iTm9PZkxvY2FsaXplZFRleHRWYWx1ZSIgLz4NCiAgICA8b3Bj OkZpZWxkIE5hbWU9Ik5vT2ZTdGF0dXNDb2RlVmFsdWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+ DQogICAgPG9wYzpGaWVsZCBOYW1lPSJTdGF0dXNDb2RlVmFsdWUiIFR5cGVOYW1lPSJ1YTpTdGF0 dXNDb2RlIiBMZW5ndGhGaWVsZD0iTm9PZlN0YXR1c0NvZGVWYWx1ZSIgLz4NCiAgICA8b3BjOkZp ZWxkIE5hbWU9Ik5vT2ZWYXJpYW50VmFsdWUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAg PG9wYzpGaWVsZCBOYW1lPSJWYXJpYW50VmFsdWUiIFR5cGVOYW1lPSJ1YTpWYXJpYW50IiBMZW5n dGhGaWVsZD0iTm9PZlZhcmlhbnRWYWx1ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZF bnVtZXJhdGlvblZhbHVlIiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQg TmFtZT0iRW51bWVyYXRpb25WYWx1ZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgTGVuZ3RoRmllbGQ9 Ik5vT2ZFbnVtZXJhdGlvblZhbHVlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZlN0cnVj dHVyZVZhbHVlIiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0i U3RydWN0dXJlVmFsdWUiIFR5cGVOYW1lPSJ1YTpFeHRlbnNpb25PYmplY3QiIExlbmd0aEZpZWxk PSJOb09mU3RydWN0dXJlVmFsdWUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mTnVtYmVy IiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTnVtYmVyIiBU eXBlTmFtZT0idWE6VmFyaWFudCIgTGVuZ3RoRmllbGQ9Ik5vT2ZOdW1iZXIiIC8+DQogICAgPG9w YzpGaWVsZCBOYW1lPSJOb09mSW50ZWdlciIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8 b3BjOkZpZWxkIE5hbWU9IkludGVnZXIiIFR5cGVOYW1lPSJ1YTpWYXJpYW50IiBMZW5ndGhGaWVs ZD0iTm9PZkludGVnZXIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mVUludGVnZXIiIFR5 cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJVSW50ZWdlciIgVHlw ZU5hbWU9InVhOlZhcmlhbnQiIExlbmd0aEZpZWxkPSJOb09mVUludGVnZXIiIC8+DQogIDwvb3Bj OlN0cnVjdHVyZWRUeXBlPg0KDQogIDxvcGM6T3BhcXVlVHlwZSBOYW1lPSJCb29sZWFuRGF0YVR5 cGUiPg0KICA8L29wYzpPcGFxdWVUeXBlPg0KDQogIDxvcGM6T3BhcXVlVHlwZSBOYW1lPSJTQnl0 ZURhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFt ZT0iQnl0ZURhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5 cGUgTmFtZT0iSW50MTZEYXRhVHlwZSI+DQogIDwvb3BjOk9wYXF1ZVR5cGU+DQoNCiAgPG9wYzpP cGFxdWVUeXBlIE5hbWU9IlVJbnQxNkRhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0K ICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0iSW50MzJEYXRhVHlwZSI+DQogIDwvb3BjOk9wYXF1ZVR5 cGU+DQoNCiAgPG9wYzpPcGFxdWVUeXBlIE5hbWU9IlVJbnQzMkRhdGFUeXBlIj4NCiAgPC9vcGM6 T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0iSW50NjREYXRhVHlwZSI+DQog IDwvb3BjOk9wYXF1ZVR5cGU+DQoNCiAgPG9wYzpPcGFxdWVUeXBlIE5hbWU9IlVJbnQ2NERhdGFU eXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0iRmxv YXREYXRhVHlwZSI+DQogIDwvb3BjOk9wYXF1ZVR5cGU+DQoNCiAgPG9wYzpPcGFxdWVUeXBlIE5h bWU9IkRvdWJsZURhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1 ZVR5cGUgTmFtZT0iU3RyaW5nRGF0YVR5cGUiPg0KICA8L29wYzpPcGFxdWVUeXBlPg0KDQogIDxv cGM6T3BhcXVlVHlwZSBOYW1lPSJEYXRlVGltZURhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlw ZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0iR3VpZERhdGFUeXBlIj4NCiAgPC9vcGM6T3Bh cXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0iQnl0ZVN0cmluZ0RhdGFUeXBlIj4N CiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0iWG1sRWxlbWVu dERhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFt ZT0iTm9kZUlkRGF0YVR5cGUiPg0KICA8L29wYzpPcGFxdWVUeXBlPg0KDQogIDxvcGM6T3BhcXVl VHlwZSBOYW1lPSJFeHBhbmRlZE5vZGVJZERhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4N Cg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0iUXVhbGlmaWVkTmFtZURhdGFUeXBlIj4NCiAgPC9v cGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0iTG9jYWxpemVkVGV4dERh dGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1ZVR5cGUgTmFtZT0i U3RhdHVzQ29kZURhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8b3BjOk9wYXF1 ZVR5cGUgTmFtZT0iVmFyaWFudERhdGFUeXBlIj4NCiAgPC9vcGM6T3BhcXVlVHlwZT4NCg0KICA8 b3BjOlN0cnVjdHVyZWRUeXBlIE5hbWU9IlVzZXJTY2FsYXJWYWx1ZURhdGFUeXBlIiBCYXNlVHlw ZT0idWE6RXh0ZW5zaW9uT2JqZWN0Ij4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkJvb2xlYW5EYXRh VHlwZSIgVHlwZU5hbWU9Im9wYzpCb29sZWFuIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iU0J5 dGVEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpTQnl0ZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9 IkJ5dGVEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpCeXRlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFt ZT0iSW50MTZEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpJbnQxNiIgLz4NCiAgICA8b3BjOkZpZWxk IE5hbWU9IlVJbnQxNkRhdGFUeXBlIiBUeXBlTmFtZT0ib3BjOlVJbnQxNiIgLz4NCiAgICA8b3Bj OkZpZWxkIE5hbWU9IkludDMyRGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAg PG9wYzpGaWVsZCBOYW1lPSJVSW50MzJEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpVSW50MzIiIC8+ DQogICAgPG9wYzpGaWVsZCBOYW1lPSJJbnQ2NERhdGFUeXBlIiBUeXBlTmFtZT0ib3BjOkludDY0 IiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iVUludDY0RGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6 VUludDY0IiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iRmxvYXREYXRhVHlwZSIgVHlwZU5hbWU9 Im9wYzpGbG9hdCIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkRvdWJsZURhdGFUeXBlIiBUeXBl TmFtZT0ib3BjOkRvdWJsZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IlN0cmluZ0RhdGFUeXBl IiBUeXBlTmFtZT0ib3BjOlN0cmluZyIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkRhdGVUaW1l RGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6RGF0ZVRpbWUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1l PSJHdWlkRGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6R3VpZCIgLz4NCiAgICA8b3BjOkZpZWxkIE5h bWU9IkJ5dGVTdHJpbmdEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpCeXRlU3RyaW5nIiAvPg0KICAg IDxvcGM6RmllbGQgTmFtZT0iWG1sRWxlbWVudERhdGFUeXBlIiBUeXBlTmFtZT0idWE6WG1sRWxl bWVudCIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vZGVJZERhdGFUeXBlIiBUeXBlTmFtZT0i dWE6Tm9kZUlkIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iRXhwYW5kZWROb2RlSWREYXRhVHlw ZSIgVHlwZU5hbWU9InVhOkV4cGFuZGVkTm9kZUlkIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0i UXVhbGlmaWVkTmFtZURhdGFUeXBlIiBUeXBlTmFtZT0idWE6UXVhbGlmaWVkTmFtZSIgLz4NCiAg ICA8b3BjOkZpZWxkIE5hbWU9IkxvY2FsaXplZFRleHREYXRhVHlwZSIgVHlwZU5hbWU9InVhOkxv Y2FsaXplZFRleHQiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJTdGF0dXNDb2RlRGF0YVR5cGUi IFR5cGVOYW1lPSJ1YTpTdGF0dXNDb2RlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iVmFyaWFu dERhdGFUeXBlIiBUeXBlTmFtZT0idWE6VmFyaWFudCIgLz4NCiAgPC9vcGM6U3RydWN0dXJlZFR5 cGU+DQoNCiAgPG9wYzpTdHJ1Y3R1cmVkVHlwZSBOYW1lPSJVc2VyQXJyYXlWYWx1ZURhdGFUeXBl IiBCYXNlVHlwZT0idWE6RXh0ZW5zaW9uT2JqZWN0Ij4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5v T2ZCb29sZWFuRGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVs ZCBOYW1lPSJCb29sZWFuRGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6Qm9vbGVhbiIgTGVuZ3RoRmll bGQ9Ik5vT2ZCb29sZWFuRGF0YVR5cGUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mU0J5 dGVEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9 IlNCeXRlRGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6U0J5dGUiIExlbmd0aEZpZWxkPSJOb09mU0J5 dGVEYXRhVHlwZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZCeXRlRGF0YVR5cGUiIFR5 cGVOYW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJCeXRlRGF0YVR5cGUi IFR5cGVOYW1lPSJvcGM6Qnl0ZSIgTGVuZ3RoRmllbGQ9Ik5vT2ZCeXRlRGF0YVR5cGUiIC8+DQog ICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mSW50MTZEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpJbnQz MiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkludDE2RGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6 SW50MTYiIExlbmd0aEZpZWxkPSJOb09mSW50MTZEYXRhVHlwZSIgLz4NCiAgICA8b3BjOkZpZWxk IE5hbWU9Ik5vT2ZVSW50MTZEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8 b3BjOkZpZWxkIE5hbWU9IlVJbnQxNkRhdGFUeXBlIiBUeXBlTmFtZT0ib3BjOlVJbnQxNiIgTGVu Z3RoRmllbGQ9Ik5vT2ZVSW50MTZEYXRhVHlwZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5v T2ZJbnQzMkRhdGFUeXBlIiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQg TmFtZT0iSW50MzJEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgTGVuZ3RoRmllbGQ9Ik5v T2ZJbnQzMkRhdGFUeXBlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZlVJbnQzMkRhdGFU eXBlIiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iVUludDMy RGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6VUludDMyIiBMZW5ndGhGaWVsZD0iTm9PZlVJbnQzMkRh dGFUeXBlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZkludDY0RGF0YVR5cGUiIFR5cGVO YW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJJbnQ2NERhdGFUeXBlIiBU eXBlTmFtZT0ib3BjOkludDY0IiBMZW5ndGhGaWVsZD0iTm9PZkludDY0RGF0YVR5cGUiIC8+DQog ICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mVUludDY0RGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6SW50 MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJVSW50NjREYXRhVHlwZSIgVHlwZU5hbWU9Im9w YzpVSW50NjQiIExlbmd0aEZpZWxkPSJOb09mVUludDY0RGF0YVR5cGUiIC8+DQogICAgPG9wYzpG aWVsZCBOYW1lPSJOb09mRmxvYXREYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAg ICA8b3BjOkZpZWxkIE5hbWU9IkZsb2F0RGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6RmxvYXQiIExl bmd0aEZpZWxkPSJOb09mRmxvYXREYXRhVHlwZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5v T2ZEb3VibGVEYXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8b3BjOkZpZWxk IE5hbWU9IkRvdWJsZURhdGFUeXBlIiBUeXBlTmFtZT0ib3BjOkRvdWJsZSIgTGVuZ3RoRmllbGQ9 Ik5vT2ZEb3VibGVEYXRhVHlwZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZTdHJpbmdE YXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IlN0 cmluZ0RhdGFUeXBlIiBUeXBlTmFtZT0ib3BjOlN0cmluZyIgTGVuZ3RoRmllbGQ9Ik5vT2ZTdHJp bmdEYXRhVHlwZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZEYXRlVGltZURhdGFUeXBl IiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iRGF0ZVRpbWVE YXRhVHlwZSIgVHlwZU5hbWU9Im9wYzpEYXRlVGltZSIgTGVuZ3RoRmllbGQ9Ik5vT2ZEYXRlVGlt ZURhdGFUeXBlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZkd1aWREYXRhVHlwZSIgVHlw ZU5hbWU9Im9wYzpJbnQzMiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ikd1aWREYXRhVHlwZSIg VHlwZU5hbWU9Im9wYzpHdWlkIiBMZW5ndGhGaWVsZD0iTm9PZkd1aWREYXRhVHlwZSIgLz4NCiAg ICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZCeXRlU3RyaW5nRGF0YVR5cGUiIFR5cGVOYW1lPSJvcGM6 SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJCeXRlU3RyaW5nRGF0YVR5cGUiIFR5cGVO YW1lPSJvcGM6Qnl0ZVN0cmluZyIgTGVuZ3RoRmllbGQ9Ik5vT2ZCeXRlU3RyaW5nRGF0YVR5cGUi IC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mWG1sRWxlbWVudERhdGFUeXBlIiBUeXBlTmFt ZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iWG1sRWxlbWVudERhdGFUeXBl IiBUeXBlTmFtZT0idWE6WG1sRWxlbWVudCIgTGVuZ3RoRmllbGQ9Ik5vT2ZYbWxFbGVtZW50RGF0 YVR5cGUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mTm9kZUlkRGF0YVR5cGUiIFR5cGVO YW1lPSJvcGM6SW50MzIiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb2RlSWREYXRhVHlwZSIg VHlwZU5hbWU9InVhOk5vZGVJZCIgTGVuZ3RoRmllbGQ9Ik5vT2ZOb2RlSWREYXRhVHlwZSIgLz4N CiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZFeHBhbmRlZE5vZGVJZERhdGFUeXBlIiBUeXBlTmFt ZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iRXhwYW5kZWROb2RlSWREYXRh VHlwZSIgVHlwZU5hbWU9InVhOkV4cGFuZGVkTm9kZUlkIiBMZW5ndGhGaWVsZD0iTm9PZkV4cGFu ZGVkTm9kZUlkRGF0YVR5cGUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mUXVhbGlmaWVk TmFtZURhdGFUeXBlIiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFt ZT0iUXVhbGlmaWVkTmFtZURhdGFUeXBlIiBUeXBlTmFtZT0idWE6UXVhbGlmaWVkTmFtZSIgTGVu Z3RoRmllbGQ9Ik5vT2ZRdWFsaWZpZWROYW1lRGF0YVR5cGUiIC8+DQogICAgPG9wYzpGaWVsZCBO YW1lPSJOb09mTG9jYWxpemVkVGV4dERhdGFUeXBlIiBUeXBlTmFtZT0ib3BjOkludDMyIiAvPg0K ICAgIDxvcGM6RmllbGQgTmFtZT0iTG9jYWxpemVkVGV4dERhdGFUeXBlIiBUeXBlTmFtZT0idWE6 TG9jYWxpemVkVGV4dCIgTGVuZ3RoRmllbGQ9Ik5vT2ZMb2NhbGl6ZWRUZXh0RGF0YVR5cGUiIC8+ DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mU3RhdHVzQ29kZURhdGFUeXBlIiBUeXBlTmFtZT0i b3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iU3RhdHVzQ29kZURhdGFUeXBlIiBU eXBlTmFtZT0idWE6U3RhdHVzQ29kZSIgTGVuZ3RoRmllbGQ9Ik5vT2ZTdGF0dXNDb2RlRGF0YVR5 cGUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJOb09mVmFyaWFudERhdGFUeXBlIiBUeXBlTmFt ZT0ib3BjOkludDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iVmFyaWFudERhdGFUeXBlIiBU eXBlTmFtZT0idWE6VmFyaWFudCIgTGVuZ3RoRmllbGQ9Ik5vT2ZWYXJpYW50RGF0YVR5cGUiIC8+ DQogIDwvb3BjOlN0cnVjdHVyZWRUeXBlPg0KDQogIDxvcGM6U3RydWN0dXJlZFR5cGUgTmFtZT0i VmVjdG9yIiBCYXNlVHlwZT0idWE6RXh0ZW5zaW9uT2JqZWN0Ij4NCiAgICA8b3BjOkZpZWxkIE5h bWU9IlgiIFR5cGVOYW1lPSJvcGM6RG91YmxlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iWSIg VHlwZU5hbWU9Im9wYzpEb3VibGUiIC8+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJaIiBUeXBlTmFt ZT0ib3BjOkRvdWJsZSIgLz4NCiAgPC9vcGM6U3RydWN0dXJlZFR5cGU+DQoNCiAgPG9wYzpTdHJ1 Y3R1cmVkVHlwZSBOYW1lPSJXb3JrT3JkZXJTdGF0dXNUeXBlIiBCYXNlVHlwZT0idWE6RXh0ZW5z aW9uT2JqZWN0Ij4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkFjdG9yIiBUeXBlTmFtZT0ib3BjOlN0 cmluZyIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IlRpbWVzdGFtcCIgVHlwZU5hbWU9Im9wYzpE YXRlVGltZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9IkNvbW1lbnQiIFR5cGVOYW1lPSJ1YTpM b2NhbGl6ZWRUZXh0IiAvPg0KICA8L29wYzpTdHJ1Y3R1cmVkVHlwZT4NCg0KICA8b3BjOlN0cnVj dHVyZWRUeXBlIE5hbWU9IldvcmtPcmRlclR5cGUiIEJhc2VUeXBlPSJ1YTpFeHRlbnNpb25PYmpl Y3QiPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iSUQiIFR5cGVOYW1lPSJvcGM6R3VpZCIgLz4NCiAg ICA8b3BjOkZpZWxkIE5hbWU9IkFzc2V0SUQiIFR5cGVOYW1lPSJvcGM6U3RyaW5nIiAvPg0KICAg IDxvcGM6RmllbGQgTmFtZT0iU3RhcnRUaW1lIiBUeXBlTmFtZT0ib3BjOkRhdGVUaW1lIiAvPg0K ICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZlN0YXR1c0NvbW1lbnRzIiBUeXBlTmFtZT0ib3BjOklu dDMyIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iU3RhdHVzQ29tbWVudHMiIFR5cGVOYW1lPSJ0 bnM6V29ya09yZGVyU3RhdHVzVHlwZSIgTGVuZ3RoRmllbGQ9Ik5vT2ZTdGF0dXNDb21tZW50cyIg Lz4NCiAgPC9vcGM6U3RydWN0dXJlZFR5cGU+DQoNCjwvb3BjOlR5cGVEaWN0aW9uYXJ5Pg== i=15 -1 1 1 i=47 true i=93 Variable_2 ns=1;i=11424 0 NamespaceUri i=46 i=68 11424 http://test.org/UA/Data/ i=12 -1 1 1 Variable_2 ns=1;i=15045 0 Deprecated i=46 i=68 15045 true i=1 -1 1 1 Variable_2 ns=1;i=11425 1 ScalarValueDataType i=47 i=69 11425 ScalarValueDataType i=12 -1 1 1 Variable_2 ns=1;i=11428 1 ArrayValueDataType i=47 i=69 11428 ArrayValueDataType i=12 -1 1 1 Variable_2 ns=1;i=11431 1 UserScalarValueDataType i=47 i=69 11431 UserScalarValueDataType i=12 -1 1 1 Variable_2 ns=1;i=11434 1 UserArrayValueDataType i=47 i=69 11434 UserArrayValueDataType i=12 -1 1 1 Variable_2 ns=1;i=1015 1 Vector i=47 i=69 1015 Vector i=12 -1 1 1 Variable_2 ns=1;i=24 1 WorkOrderStatusType i=47 i=69 24 WorkOrderStatusType i=12 -1 1 1 Variable_2 ns=1;i=27 1 WorkOrderType i=47 i=69 27 WorkOrderType i=12 -1 1 1 Object_1 ns=1;i=11418 0 Default XML i=76 11418 i=38 true ns=1;i=9440 i=39 ns=1;i=11444 Object_1 ns=1;i=11419 0 Default XML i=76 11419 i=38 true ns=1;i=9669 i=39 ns=1;i=11447 Object_1 ns=1;i=11420 0 Default XML i=76 11420 i=38 true ns=1;i=9920 i=39 ns=1;i=11450 Object_1 ns=1;i=11421 0 Default XML i=76 11421 i=38 true ns=1;i=10006 i=39 ns=1;i=11453 Object_1 ns=1;i=36 0 Default XML i=76 36 i=38 true ns=1;i=1000 i=39 ns=1;i=43 Object_1 ns=1;i=39 0 Default XML i=76 39 i=38 true ns=1;i=1004 i=39 ns=1;i=52 Object_1 ns=1;i=40 0 Default XML i=76 40 i=38 true ns=1;i=1005 i=39 ns=1;i=55 Variable_2 ns=1;i=11441 1 TestData i=72 11441 PHhzOnNjaGVtYQ0KICB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEi DQogIHhtbG5zOnVhPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvMjAwOC8wMi9UeXBlcy54 c2QiDQogIHhtbG5zOnRucz0iaHR0cDovL3Rlc3Qub3JnL1VBL0RhdGEvIg0KICB0YXJnZXROYW1l c3BhY2U9Imh0dHA6Ly90ZXN0Lm9yZy9VQS9EYXRhLyINCiAgZWxlbWVudEZvcm1EZWZhdWx0PSJx dWFsaWZpZWQiDQo+DQogIDx4czppbXBvcnQgbmFtZXNwYWNlPSJodHRwOi8vb3BjZm91bmRhdGlv bi5vcmcvVUEvMjAwOC8wMi9UeXBlcy54c2QiIC8+DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9 IlNjYWxhclZhbHVlRGF0YVR5cGUiPg0KICAgIDx4czpzZXF1ZW5jZT4NCiAgICAgIDx4czplbGVt ZW50IG5hbWU9IkJvb2xlYW5WYWx1ZSIgdHlwZT0ieHM6Ym9vbGVhbiIgbWluT2NjdXJzPSIwIiAv Pg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iU0J5dGVWYWx1ZSIgdHlwZT0ieHM6Ynl0ZSIgbWlu T2NjdXJzPSIwIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iQnl0ZVZhbHVlIiB0eXBlPSJ4 czp1bnNpZ25lZEJ5dGUiIG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9 IkludDE2VmFsdWUiIHR5cGU9InhzOnNob3J0IiBtaW5PY2N1cnM9IjAiIC8+DQogICAgICA8eHM6 ZWxlbWVudCBuYW1lPSJVSW50MTZWYWx1ZSIgdHlwZT0ieHM6dW5zaWduZWRTaG9ydCIgbWluT2Nj dXJzPSIwIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iSW50MzJWYWx1ZSIgdHlwZT0ieHM6 aW50IiBtaW5PY2N1cnM9IjAiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJVSW50MzJWYWx1 ZSIgdHlwZT0ieHM6dW5zaWduZWRJbnQiIG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVt ZW50IG5hbWU9IkludDY0VmFsdWUiIHR5cGU9InhzOmxvbmciIG1pbk9jY3Vycz0iMCIgLz4NCiAg ICAgIDx4czplbGVtZW50IG5hbWU9IlVJbnQ2NFZhbHVlIiB0eXBlPSJ4czp1bnNpZ25lZExvbmci IG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IkZsb2F0VmFsdWUiIHR5 cGU9InhzOmZsb2F0IiBtaW5PY2N1cnM9IjAiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJE b3VibGVWYWx1ZSIgdHlwZT0ieHM6ZG91YmxlIiBtaW5PY2N1cnM9IjAiIC8+DQogICAgICA8eHM6 ZWxlbWVudCBuYW1lPSJTdHJpbmdWYWx1ZSIgdHlwZT0ieHM6c3RyaW5nIiBtaW5PY2N1cnM9IjAi IG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iRGF0ZVRpbWVWYWx1 ZSIgdHlwZT0ieHM6ZGF0ZVRpbWUiIG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVtZW50 IG5hbWU9Ikd1aWRWYWx1ZSIgdHlwZT0idWE6R3VpZCIgbWluT2NjdXJzPSIwIiAvPg0KICAgICAg PHhzOmVsZW1lbnQgbmFtZT0iQnl0ZVN0cmluZ1ZhbHVlIiB0eXBlPSJ4czpiYXNlNjRCaW5hcnki IG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1l PSJYbWxFbGVtZW50VmFsdWUiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiPg0KICAgICAg ICA8eHM6Y29tcGxleFR5cGU+DQogICAgICAgICAgPHhzOnNlcXVlbmNlPg0KICAgICAgICAgICAg PHhzOmFueSBtaW5PY2N1cnM9IjAiIHByb2Nlc3NDb250ZW50cz0ibGF4IiAvPg0KICAgICAgICAg IDwveHM6c2VxdWVuY2U+DQogICAgICAgIDwveHM6Y29tcGxleFR5cGU+DQogICAgICA8L3hzOmVs ZW1lbnQ+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJOb2RlSWRWYWx1ZSIgdHlwZT0idWE6Tm9k ZUlkIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQg bmFtZT0iRXhwYW5kZWROb2RlSWRWYWx1ZSIgdHlwZT0idWE6RXhwYW5kZWROb2RlSWQiIG1pbk9j Y3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJRdWFs aWZpZWROYW1lVmFsdWUiIHR5cGU9InVhOlF1YWxpZmllZE5hbWUiIG1pbk9jY3Vycz0iMCIgbmls bGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJMb2NhbGl6ZWRUZXh0VmFs dWUiIHR5cGU9InVhOkxvY2FsaXplZFRleHQiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUi IC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJTdGF0dXNDb2RlVmFsdWUiIHR5cGU9InVhOlN0 YXR1c0NvZGUiIG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlZhcmlh bnRWYWx1ZSIgdHlwZT0idWE6VmFyaWFudCIgbWluT2NjdXJzPSIwIiAvPg0KICAgICAgPHhzOmVs ZW1lbnQgbmFtZT0iRW51bWVyYXRpb25WYWx1ZSIgdHlwZT0ieHM6aW50IiBtaW5PY2N1cnM9IjAi IC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJTdHJ1Y3R1cmVWYWx1ZSIgdHlwZT0idWE6RXh0 ZW5zaW9uT2JqZWN0IiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhz OmVsZW1lbnQgbmFtZT0iTnVtYmVyIiB0eXBlPSJ1YTpWYXJpYW50IiBtaW5PY2N1cnM9IjAiIC8+ DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJJbnRlZ2VyIiB0eXBlPSJ1YTpWYXJpYW50IiBtaW5P Y2N1cnM9IjAiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJVSW50ZWdlciIgdHlwZT0idWE6 VmFyaWFudCIgbWluT2NjdXJzPSIwIiAvPg0KICAgIDwveHM6c2VxdWVuY2U+DQogIDwveHM6Y29t cGxleFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9IlNjYWxhclZhbHVlRGF0YVR5cGUiIHR5cGU9 InRuczpTY2FsYXJWYWx1ZURhdGFUeXBlIiAvPg0KDQogIDx4czpjb21wbGV4VHlwZSBuYW1lPSJM aXN0T2ZTY2FsYXJWYWx1ZURhdGFUeXBlIj4NCiAgICA8eHM6c2VxdWVuY2U+DQogICAgICA8eHM6 ZWxlbWVudCBuYW1lPSJTY2FsYXJWYWx1ZURhdGFUeXBlIiB0eXBlPSJ0bnM6U2NhbGFyVmFsdWVE YXRhVHlwZSIgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9InVuYm91bmRlZCIgbmlsbGFibGU9InRy dWUiIC8+DQogICAgPC94czpzZXF1ZW5jZT4NCiAgPC94czpjb21wbGV4VHlwZT4NCiAgPHhzOmVs ZW1lbnQgbmFtZT0iTGlzdE9mU2NhbGFyVmFsdWVEYXRhVHlwZSIgdHlwZT0idG5zOkxpc3RPZlNj YWxhclZhbHVlRGF0YVR5cGUiIG5pbGxhYmxlPSJ0cnVlIj48L3hzOmVsZW1lbnQ+DQoNCiAgPHhz OmNvbXBsZXhUeXBlIG5hbWU9IkFycmF5VmFsdWVEYXRhVHlwZSI+DQogICAgPHhzOnNlcXVlbmNl Pg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iQm9vbGVhblZhbHVlIiB0eXBlPSJ1YTpMaXN0T2ZC b29sZWFuIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1l bnQgbmFtZT0iU0J5dGVWYWx1ZSIgdHlwZT0idWE6TGlzdE9mU0J5dGUiIG1pbk9jY3Vycz0iMCIg bmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJCeXRlVmFsdWUiIHR5 cGU9InVhOkxpc3RPZkJ5dGUiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAg ICA8eHM6ZWxlbWVudCBuYW1lPSJJbnQxNlZhbHVlIiB0eXBlPSJ1YTpMaXN0T2ZJbnQxNiIgbWlu T2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlVJ bnQxNlZhbHVlIiB0eXBlPSJ1YTpMaXN0T2ZVSW50MTYiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9 InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJJbnQzMlZhbHVlIiB0eXBlPSJ1YTpM aXN0T2ZJbnQzMiIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICAgIDx4czpl bGVtZW50IG5hbWU9IlVJbnQzMlZhbHVlIiB0eXBlPSJ1YTpMaXN0T2ZVSW50MzIiIG1pbk9jY3Vy cz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJJbnQ2NFZh bHVlIiB0eXBlPSJ1YTpMaXN0T2ZJbnQ2NCIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIg Lz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlVJbnQ2NFZhbHVlIiB0eXBlPSJ1YTpMaXN0T2ZV SW50NjQiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVu dCBuYW1lPSJGbG9hdFZhbHVlIiB0eXBlPSJ1YTpMaXN0T2ZGbG9hdCIgbWluT2NjdXJzPSIwIiBu aWxsYWJsZT0idHJ1ZSIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IkRvdWJsZVZhbHVlIiB0 eXBlPSJ1YTpMaXN0T2ZEb3VibGUiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQog ICAgICA8eHM6ZWxlbWVudCBuYW1lPSJTdHJpbmdWYWx1ZSIgdHlwZT0idWE6TGlzdE9mU3RyaW5n IiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFt ZT0iRGF0ZVRpbWVWYWx1ZSIgdHlwZT0idWE6TGlzdE9mRGF0ZVRpbWUiIG1pbk9jY3Vycz0iMCIg bmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJHdWlkVmFsdWUiIHR5 cGU9InVhOkxpc3RPZkd1aWQiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAg ICA8eHM6ZWxlbWVudCBuYW1lPSJCeXRlU3RyaW5nVmFsdWUiIHR5cGU9InVhOkxpc3RPZkJ5dGVT dHJpbmciIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVu dCBuYW1lPSJYbWxFbGVtZW50VmFsdWUiIHR5cGU9InVhOkxpc3RPZlhtbEVsZW1lbnQiIG1pbk9j Y3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJOb2Rl SWRWYWx1ZSIgdHlwZT0idWE6TGlzdE9mTm9kZUlkIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0 cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iRXhwYW5kZWROb2RlSWRWYWx1ZSIgdHlw ZT0idWE6TGlzdE9mRXhwYW5kZWROb2RlSWQiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUi IC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJRdWFsaWZpZWROYW1lVmFsdWUiIHR5cGU9InVh Okxpc3RPZlF1YWxpZmllZE5hbWUiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQog ICAgICA8eHM6ZWxlbWVudCBuYW1lPSJMb2NhbGl6ZWRUZXh0VmFsdWUiIHR5cGU9InVhOkxpc3RP ZkxvY2FsaXplZFRleHQiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8 eHM6ZWxlbWVudCBuYW1lPSJTdGF0dXNDb2RlVmFsdWUiIHR5cGU9InVhOkxpc3RPZlN0YXR1c0Nv ZGUiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBu YW1lPSJWYXJpYW50VmFsdWUiIHR5cGU9InVhOkxpc3RPZlZhcmlhbnQiIG1pbk9jY3Vycz0iMCIg bmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJFbnVtZXJhdGlvblZh bHVlIiB0eXBlPSJ1YTpMaXN0T2ZJbnQzMiIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIg Lz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlN0cnVjdHVyZVZhbHVlIiB0eXBlPSJ1YTpMaXN0 T2ZFeHRlbnNpb25PYmplY3QiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAg ICA8eHM6ZWxlbWVudCBuYW1lPSJOdW1iZXIiIHR5cGU9InVhOkxpc3RPZlZhcmlhbnQiIG1pbk9j Y3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJJbnRl Z2VyIiB0eXBlPSJ1YTpMaXN0T2ZWYXJpYW50IiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVl IiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iVUludGVnZXIiIHR5cGU9InVhOkxpc3RPZlZh cmlhbnQiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgPC94czpzZXF1ZW5j ZT4NCiAgPC94czpjb21wbGV4VHlwZT4NCiAgPHhzOmVsZW1lbnQgbmFtZT0iQXJyYXlWYWx1ZURh dGFUeXBlIiB0eXBlPSJ0bnM6QXJyYXlWYWx1ZURhdGFUeXBlIiAvPg0KDQogIDx4czpjb21wbGV4 VHlwZSBuYW1lPSJMaXN0T2ZBcnJheVZhbHVlRGF0YVR5cGUiPg0KICAgIDx4czpzZXF1ZW5jZT4N CiAgICAgIDx4czplbGVtZW50IG5hbWU9IkFycmF5VmFsdWVEYXRhVHlwZSIgdHlwZT0idG5zOkFy cmF5VmFsdWVEYXRhVHlwZSIgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9InVuYm91bmRlZCIgbmls bGFibGU9InRydWUiIC8+DQogICAgPC94czpzZXF1ZW5jZT4NCiAgPC94czpjb21wbGV4VHlwZT4N CiAgPHhzOmVsZW1lbnQgbmFtZT0iTGlzdE9mQXJyYXlWYWx1ZURhdGFUeXBlIiB0eXBlPSJ0bnM6 TGlzdE9mQXJyYXlWYWx1ZURhdGFUeXBlIiBuaWxsYWJsZT0idHJ1ZSI+PC94czplbGVtZW50Pg0K DQogIDx4czplbGVtZW50IG5hbWU9IkJvb2xlYW5EYXRhVHlwZSIgdHlwZT0ieHM6Ym9vbGVhbiIg Lz4NCg0KICA8eHM6ZWxlbWVudCBuYW1lPSJTQnl0ZURhdGFUeXBlIiB0eXBlPSJ4czpieXRlIiAv Pg0KDQogIDx4czplbGVtZW50IG5hbWU9IkJ5dGVEYXRhVHlwZSIgdHlwZT0ieHM6dW5zaWduZWRC eXRlIiAvPg0KDQogIDx4czplbGVtZW50IG5hbWU9IkludDE2RGF0YVR5cGUiIHR5cGU9InhzOnNo b3J0IiAvPg0KDQogIDx4czplbGVtZW50IG5hbWU9IlVJbnQxNkRhdGFUeXBlIiB0eXBlPSJ4czp1 bnNpZ25lZFNob3J0IiAvPg0KDQogIDx4czplbGVtZW50IG5hbWU9IkludDMyRGF0YVR5cGUiIHR5 cGU9InhzOmludCIgLz4NCg0KICA8eHM6ZWxlbWVudCBuYW1lPSJVSW50MzJEYXRhVHlwZSIgdHlw ZT0ieHM6dW5zaWduZWRJbnQiIC8+DQoNCiAgPHhzOmVsZW1lbnQgbmFtZT0iSW50NjREYXRhVHlw ZSIgdHlwZT0ieHM6bG9uZyIgLz4NCg0KICA8eHM6ZWxlbWVudCBuYW1lPSJVSW50NjREYXRhVHlw ZSIgdHlwZT0ieHM6dW5zaWduZWRMb25nIiAvPg0KDQogIDx4czplbGVtZW50IG5hbWU9IkZsb2F0 RGF0YVR5cGUiIHR5cGU9InhzOmZsb2F0IiAvPg0KDQogIDx4czplbGVtZW50IG5hbWU9IkRvdWJs ZURhdGFUeXBlIiB0eXBlPSJ4czpkb3VibGUiIC8+DQoNCiAgPHhzOmVsZW1lbnQgbmFtZT0iU3Ry aW5nRGF0YVR5cGUiIHR5cGU9InhzOnN0cmluZyIgLz4NCg0KICA8eHM6ZWxlbWVudCBuYW1lPSJE YXRlVGltZURhdGFUeXBlIiB0eXBlPSJ4czpkYXRlVGltZSIgLz4NCg0KICA8eHM6ZWxlbWVudCBu YW1lPSJHdWlkRGF0YVR5cGUiIHR5cGU9InVhOkd1aWQiIC8+DQoNCiAgPHhzOmVsZW1lbnQgbmFt ZT0iQnl0ZVN0cmluZ0RhdGFUeXBlIiB0eXBlPSJ4czpiYXNlNjRCaW5hcnkiIC8+DQoNCiAgPHhz OmVsZW1lbnQgbmFtZT0iWG1sRWxlbWVudERhdGFUeXBlIiB0eXBlPSJ1YTpYbWxFbGVtZW50IiAv Pg0KDQogIDx4czplbGVtZW50IG5hbWU9Ik5vZGVJZERhdGFUeXBlIiB0eXBlPSJ1YTpOb2RlSWQi IC8+DQoNCiAgPHhzOmVsZW1lbnQgbmFtZT0iRXhwYW5kZWROb2RlSWREYXRhVHlwZSIgdHlwZT0i dWE6RXhwYW5kZWROb2RlSWQiIC8+DQoNCiAgPHhzOmVsZW1lbnQgbmFtZT0iUXVhbGlmaWVkTmFt ZURhdGFUeXBlIiB0eXBlPSJ1YTpRdWFsaWZpZWROYW1lIiAvPg0KDQogIDx4czplbGVtZW50IG5h bWU9IkxvY2FsaXplZFRleHREYXRhVHlwZSIgdHlwZT0idWE6TG9jYWxpemVkVGV4dCIgLz4NCg0K ICA8eHM6ZWxlbWVudCBuYW1lPSJTdGF0dXNDb2RlRGF0YVR5cGUiIHR5cGU9InVhOlN0YXR1c0Nv ZGUiIC8+DQoNCiAgPHhzOmVsZW1lbnQgbmFtZT0iVmFyaWFudERhdGFUeXBlIiB0eXBlPSJ1YTpW YXJpYW50IiAvPg0KDQogIDx4czpjb21wbGV4VHlwZSBuYW1lPSJVc2VyU2NhbGFyVmFsdWVEYXRh VHlwZSI+DQogICAgPHhzOnNlcXVlbmNlPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iQm9vbGVh bkRhdGFUeXBlIiB0eXBlPSJ4czpib29sZWFuIiBtaW5PY2N1cnM9IjAiIC8+DQogICAgICA8eHM6 ZWxlbWVudCBuYW1lPSJTQnl0ZURhdGFUeXBlIiB0eXBlPSJ4czpieXRlIiBtaW5PY2N1cnM9IjAi IC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJCeXRlRGF0YVR5cGUiIHR5cGU9InhzOnVuc2ln bmVkQnl0ZSIgbWluT2NjdXJzPSIwIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iSW50MTZE YXRhVHlwZSIgdHlwZT0ieHM6c2hvcnQiIG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVt ZW50IG5hbWU9IlVJbnQxNkRhdGFUeXBlIiB0eXBlPSJ4czp1bnNpZ25lZFNob3J0IiBtaW5PY2N1 cnM9IjAiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJJbnQzMkRhdGFUeXBlIiB0eXBlPSJ4 czppbnQiIG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlVJbnQzMkRh dGFUeXBlIiB0eXBlPSJ4czp1bnNpZ25lZEludCIgbWluT2NjdXJzPSIwIiAvPg0KICAgICAgPHhz OmVsZW1lbnQgbmFtZT0iSW50NjREYXRhVHlwZSIgdHlwZT0ieHM6bG9uZyIgbWluT2NjdXJzPSIw IiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iVUludDY0RGF0YVR5cGUiIHR5cGU9InhzOnVu c2lnbmVkTG9uZyIgbWluT2NjdXJzPSIwIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iRmxv YXREYXRhVHlwZSIgdHlwZT0ieHM6ZmxvYXQiIG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czpl bGVtZW50IG5hbWU9IkRvdWJsZURhdGFUeXBlIiB0eXBlPSJ4czpkb3VibGUiIG1pbk9jY3Vycz0i MCIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlN0cmluZ0RhdGFUeXBlIiB0eXBlPSJ4czpz dHJpbmciIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVu dCBuYW1lPSJEYXRlVGltZURhdGFUeXBlIiB0eXBlPSJ4czpkYXRlVGltZSIgbWluT2NjdXJzPSIw IiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iR3VpZERhdGFUeXBlIiB0eXBlPSJ1YTpHdWlk IiBtaW5PY2N1cnM9IjAiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJCeXRlU3RyaW5nRGF0 YVR5cGUiIHR5cGU9InhzOmJhc2U2NEJpbmFyeSIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1 ZSIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlhtbEVsZW1lbnREYXRhVHlwZSIgbWluT2Nj dXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSI+DQogICAgICAgIDx4czpjb21wbGV4VHlwZT4NCiAgICAg ICAgICA8eHM6c2VxdWVuY2U+DQogICAgICAgICAgICA8eHM6YW55IG1pbk9jY3Vycz0iMCIgcHJv Y2Vzc0NvbnRlbnRzPSJsYXgiIC8+DQogICAgICAgICAgPC94czpzZXF1ZW5jZT4NCiAgICAgICAg PC94czpjb21wbGV4VHlwZT4NCiAgICAgIDwveHM6ZWxlbWVudD4NCiAgICAgIDx4czplbGVtZW50 IG5hbWU9Ik5vZGVJZERhdGFUeXBlIiB0eXBlPSJ1YTpOb2RlSWQiIG1pbk9jY3Vycz0iMCIgbmls bGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJFeHBhbmRlZE5vZGVJZERh dGFUeXBlIiB0eXBlPSJ1YTpFeHBhbmRlZE5vZGVJZCIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0i dHJ1ZSIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlF1YWxpZmllZE5hbWVEYXRhVHlwZSIg dHlwZT0idWE6UXVhbGlmaWVkTmFtZSIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4N CiAgICAgIDx4czplbGVtZW50IG5hbWU9IkxvY2FsaXplZFRleHREYXRhVHlwZSIgdHlwZT0idWE6 TG9jYWxpemVkVGV4dCIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICAgIDx4 czplbGVtZW50IG5hbWU9IlN0YXR1c0NvZGVEYXRhVHlwZSIgdHlwZT0idWE6U3RhdHVzQ29kZSIg bWluT2NjdXJzPSIwIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iVmFyaWFudERhdGFUeXBl IiB0eXBlPSJ1YTpWYXJpYW50IiBtaW5PY2N1cnM9IjAiIC8+DQogICAgPC94czpzZXF1ZW5jZT4N CiAgPC94czpjb21wbGV4VHlwZT4NCiAgPHhzOmVsZW1lbnQgbmFtZT0iVXNlclNjYWxhclZhbHVl RGF0YVR5cGUiIHR5cGU9InRuczpVc2VyU2NhbGFyVmFsdWVEYXRhVHlwZSIgLz4NCg0KICA8eHM6 Y29tcGxleFR5cGUgbmFtZT0iTGlzdE9mVXNlclNjYWxhclZhbHVlRGF0YVR5cGUiPg0KICAgIDx4 czpzZXF1ZW5jZT4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlVzZXJTY2FsYXJWYWx1ZURhdGFU eXBlIiB0eXBlPSJ0bnM6VXNlclNjYWxhclZhbHVlRGF0YVR5cGUiIG1pbk9jY3Vycz0iMCIgbWF4 T2NjdXJzPSJ1bmJvdW5kZWQiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgIDwveHM6c2VxdWVuY2U+ DQogIDwveHM6Y29tcGxleFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9Ikxpc3RPZlVzZXJTY2Fs YXJWYWx1ZURhdGFUeXBlIiB0eXBlPSJ0bnM6TGlzdE9mVXNlclNjYWxhclZhbHVlRGF0YVR5cGUi IG5pbGxhYmxlPSJ0cnVlIj48L3hzOmVsZW1lbnQ+DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9 IlVzZXJBcnJheVZhbHVlRGF0YVR5cGUiPg0KICAgIDx4czpzZXF1ZW5jZT4NCiAgICAgIDx4czpl bGVtZW50IG5hbWU9IkJvb2xlYW5EYXRhVHlwZSIgdHlwZT0idWE6TGlzdE9mQm9vbGVhbiIgbWlu T2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IlNC eXRlRGF0YVR5cGUiIHR5cGU9InVhOkxpc3RPZlNCeXRlIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxl PSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iQnl0ZURhdGFUeXBlIiB0eXBlPSJ0 bnM6TGlzdE9mQnl0ZURhdGFUeXBlIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0K ICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iSW50MTZEYXRhVHlwZSIgdHlwZT0idWE6TGlzdE9mSW50 MTYiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBu YW1lPSJVSW50MTZEYXRhVHlwZSIgdHlwZT0idWE6TGlzdE9mVUludDE2IiBtaW5PY2N1cnM9IjAi IG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iSW50MzJEYXRhVHlw ZSIgdHlwZT0idWE6TGlzdE9mSW50MzIiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+ DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJVSW50MzJEYXRhVHlwZSIgdHlwZT0idWE6TGlzdE9m VUludDMyIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1l bnQgbmFtZT0iSW50NjREYXRhVHlwZSIgdHlwZT0idWE6TGlzdE9mSW50NjQiIG1pbk9jY3Vycz0i MCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJVSW50NjREYXRh VHlwZSIgdHlwZT0idWE6TGlzdE9mVUludDY0IiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVl IiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iRmxvYXREYXRhVHlwZSIgdHlwZT0idWE6TGlz dE9mRmxvYXQiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxl bWVudCBuYW1lPSJEb3VibGVEYXRhVHlwZSIgdHlwZT0idWE6TGlzdE9mRG91YmxlIiBtaW5PY2N1 cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iU3RyaW5n RGF0YVR5cGUiIHR5cGU9InVhOkxpc3RPZlN0cmluZyIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0i dHJ1ZSIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IkRhdGVUaW1lRGF0YVR5cGUiIHR5cGU9 InVhOkxpc3RPZkRhdGVUaW1lIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAg ICAgPHhzOmVsZW1lbnQgbmFtZT0iR3VpZERhdGFUeXBlIiB0eXBlPSJ1YTpMaXN0T2ZHdWlkIiBt aW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0i Qnl0ZVN0cmluZ0RhdGFUeXBlIiB0eXBlPSJ1YTpMaXN0T2ZCeXRlU3RyaW5nIiBtaW5PY2N1cnM9 IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iWG1sRWxlbWVu dERhdGFUeXBlIiB0eXBlPSJ1YTpMaXN0T2ZYbWxFbGVtZW50IiBtaW5PY2N1cnM9IjAiIG5pbGxh YmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iTm9kZUlkRGF0YVR5cGUiIHR5 cGU9InVhOkxpc3RPZk5vZGVJZCIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAg ICAgIDx4czplbGVtZW50IG5hbWU9IkV4cGFuZGVkTm9kZUlkRGF0YVR5cGUiIHR5cGU9InVhOkxp c3RPZkV4cGFuZGVkTm9kZUlkIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAg ICAgPHhzOmVsZW1lbnQgbmFtZT0iUXVhbGlmaWVkTmFtZURhdGFUeXBlIiB0eXBlPSJ1YTpMaXN0 T2ZRdWFsaWZpZWROYW1lIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAg PHhzOmVsZW1lbnQgbmFtZT0iTG9jYWxpemVkVGV4dERhdGFUeXBlIiB0eXBlPSJ1YTpMaXN0T2ZM b2NhbGl6ZWRUZXh0IiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhz OmVsZW1lbnQgbmFtZT0iU3RhdHVzQ29kZURhdGFUeXBlIiB0eXBlPSJ1YTpMaXN0T2ZTdGF0dXND b2RlIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgPHhzOmVsZW1lbnQg bmFtZT0iVmFyaWFudERhdGFUeXBlIiB0eXBlPSJ1YTpMaXN0T2ZWYXJpYW50IiBtaW5PY2N1cnM9 IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgIDwveHM6c2VxdWVuY2U+DQogIDwveHM6Y29tcGxl eFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9IlVzZXJBcnJheVZhbHVlRGF0YVR5cGUiIHR5cGU9 InRuczpVc2VyQXJyYXlWYWx1ZURhdGFUeXBlIiAvPg0KDQogIDx4czpjb21wbGV4VHlwZSBuYW1l PSJMaXN0T2ZVc2VyQXJyYXlWYWx1ZURhdGFUeXBlIj4NCiAgICA8eHM6c2VxdWVuY2U+DQogICAg ICA8eHM6ZWxlbWVudCBuYW1lPSJVc2VyQXJyYXlWYWx1ZURhdGFUeXBlIiB0eXBlPSJ0bnM6VXNl ckFycmF5VmFsdWVEYXRhVHlwZSIgbWluT2NjdXJzPSIwIiBtYXhPY2N1cnM9InVuYm91bmRlZCIg bmlsbGFibGU9InRydWUiIC8+DQogICAgPC94czpzZXF1ZW5jZT4NCiAgPC94czpjb21wbGV4VHlw ZT4NCiAgPHhzOmVsZW1lbnQgbmFtZT0iTGlzdE9mVXNlckFycmF5VmFsdWVEYXRhVHlwZSIgdHlw ZT0idG5zOkxpc3RPZlVzZXJBcnJheVZhbHVlRGF0YVR5cGUiIG5pbGxhYmxlPSJ0cnVlIj48L3hz OmVsZW1lbnQ+DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9IlZlY3RvciI+DQogICAgPHhzOnNl cXVlbmNlPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iWCIgdHlwZT0ieHM6ZG91YmxlIiBtaW5P Y2N1cnM9IjAiIC8+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJZIiB0eXBlPSJ4czpkb3VibGUi IG1pbk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IloiIHR5cGU9InhzOmRv dWJsZSIgbWluT2NjdXJzPSIwIiAvPg0KICAgIDwveHM6c2VxdWVuY2U+DQogIDwveHM6Y29tcGxl eFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9IlZlY3RvciIgdHlwZT0idG5zOlZlY3RvciIgLz4N Cg0KICA8eHM6Y29tcGxleFR5cGUgbmFtZT0iTGlzdE9mVmVjdG9yIj4NCiAgICA8eHM6c2VxdWVu Y2U+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJWZWN0b3IiIHR5cGU9InRuczpWZWN0b3IiIG1p bk9jY3Vycz0iMCIgbWF4T2NjdXJzPSJ1bmJvdW5kZWQiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAg IDwveHM6c2VxdWVuY2U+DQogIDwveHM6Y29tcGxleFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9 Ikxpc3RPZlZlY3RvciIgdHlwZT0idG5zOkxpc3RPZlZlY3RvciIgbmlsbGFibGU9InRydWUiPjwv eHM6ZWxlbWVudD4NCg0KICA8eHM6Y29tcGxleFR5cGUgbmFtZT0iV29ya09yZGVyU3RhdHVzVHlw ZSI+DQogICAgPHhzOnNlcXVlbmNlPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iQWN0b3IiIHR5 cGU9InhzOnN0cmluZyIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICAgIDx4 czplbGVtZW50IG5hbWU9IlRpbWVzdGFtcCIgdHlwZT0ieHM6ZGF0ZVRpbWUiIG1pbk9jY3Vycz0i MCIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IkNvbW1lbnQiIHR5cGU9InVhOkxvY2FsaXpl ZFRleHQiIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgPC94czpzZXF1ZW5j ZT4NCiAgPC94czpjb21wbGV4VHlwZT4NCiAgPHhzOmVsZW1lbnQgbmFtZT0iV29ya09yZGVyU3Rh dHVzVHlwZSIgdHlwZT0idG5zOldvcmtPcmRlclN0YXR1c1R5cGUiIC8+DQoNCiAgPHhzOmNvbXBs ZXhUeXBlIG5hbWU9Ikxpc3RPZldvcmtPcmRlclN0YXR1c1R5cGUiPg0KICAgIDx4czpzZXF1ZW5j ZT4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IldvcmtPcmRlclN0YXR1c1R5cGUiIHR5cGU9InRu czpXb3JrT3JkZXJTdGF0dXNUeXBlIiBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0idW5ib3VuZGVk IiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICA8L3hzOnNlcXVlbmNlPg0KICA8L3hzOmNvbXBsZXhU eXBlPg0KICA8eHM6ZWxlbWVudCBuYW1lPSJMaXN0T2ZXb3JrT3JkZXJTdGF0dXNUeXBlIiB0eXBl PSJ0bnM6TGlzdE9mV29ya09yZGVyU3RhdHVzVHlwZSIgbmlsbGFibGU9InRydWUiPjwveHM6ZWxl bWVudD4NCg0KICA8eHM6Y29tcGxleFR5cGUgbmFtZT0iV29ya09yZGVyVHlwZSI+DQogICAgPHhz OnNlcXVlbmNlPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iSUQiIHR5cGU9InVhOkd1aWQiIG1p bk9jY3Vycz0iMCIgLz4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IkFzc2V0SUQiIHR5cGU9Inhz OnN0cmluZyIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAgICAgIDx4czplbGVt ZW50IG5hbWU9IlN0YXJ0VGltZSIgdHlwZT0ieHM6ZGF0ZVRpbWUiIG1pbk9jY3Vycz0iMCIgLz4N CiAgICAgIDx4czplbGVtZW50IG5hbWU9IlN0YXR1c0NvbW1lbnRzIiB0eXBlPSJ0bnM6TGlzdE9m V29ya09yZGVyU3RhdHVzVHlwZSIgbWluT2NjdXJzPSIwIiBuaWxsYWJsZT0idHJ1ZSIgLz4NCiAg ICA8L3hzOnNlcXVlbmNlPg0KICA8L3hzOmNvbXBsZXhUeXBlPg0KICA8eHM6ZWxlbWVudCBuYW1l PSJXb3JrT3JkZXJUeXBlIiB0eXBlPSJ0bnM6V29ya09yZGVyVHlwZSIgLz4NCg0KICA8eHM6Y29t cGxleFR5cGUgbmFtZT0iTGlzdE9mV29ya09yZGVyVHlwZSI+DQogICAgPHhzOnNlcXVlbmNlPg0K ICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iV29ya09yZGVyVHlwZSIgdHlwZT0idG5zOldvcmtPcmRl clR5cGUiIG1pbk9jY3Vycz0iMCIgbWF4T2NjdXJzPSJ1bmJvdW5kZWQiIG5pbGxhYmxlPSJ0cnVl IiAvPg0KICAgIDwveHM6c2VxdWVuY2U+DQogIDwveHM6Y29tcGxleFR5cGU+DQogIDx4czplbGVt ZW50IG5hbWU9Ikxpc3RPZldvcmtPcmRlclR5cGUiIHR5cGU9InRuczpMaXN0T2ZXb3JrT3JkZXJU eXBlIiBuaWxsYWJsZT0idHJ1ZSI+PC94czplbGVtZW50Pg0KDQo8L3hzOnNjaGVtYT4= i=15 -1 1 1 i=47 true i=92 Variable_2 ns=1;i=11443 0 NamespaceUri i=46 i=68 11443 http://test.org/UA/Data/ i=12 -1 1 1 Variable_2 ns=1;i=15046 0 Deprecated i=46 i=68 15046 true i=1 -1 1 1 Variable_2 ns=1;i=11444 1 ScalarValueDataType i=47 i=69 11444 //xs:element[@name='ScalarValueDataType'] i=12 -1 1 1 Variable_2 ns=1;i=11447 1 ArrayValueDataType i=47 i=69 11447 //xs:element[@name='ArrayValueDataType'] i=12 -1 1 1 Variable_2 ns=1;i=11450 1 UserScalarValueDataType i=47 i=69 11450 //xs:element[@name='UserScalarValueDataType'] i=12 -1 1 1 Variable_2 ns=1;i=11453 1 UserArrayValueDataType i=47 i=69 11453 //xs:element[@name='UserArrayValueDataType'] i=12 -1 1 1 Variable_2 ns=1;i=43 1 Vector i=47 i=69 43 //xs:element[@name='Vector'] i=12 -1 1 1 Variable_2 ns=1;i=52 1 WorkOrderStatusType i=47 i=69 52 //xs:element[@name='WorkOrderStatusType'] i=12 -1 1 1 Variable_2 ns=1;i=55 1 WorkOrderType i=47 i=69 55 //xs:element[@name='WorkOrderType'] i=12 -1 1 1 Object_1 ns=1;i=15047 0 Default JSON i=76 15047 i=38 true ns=1;i=9440 Object_1 ns=1;i=15048 0 Default JSON i=76 15048 i=38 true ns=1;i=9669 Object_1 ns=1;i=15049 0 Default JSON i=76 15049 i=38 true ns=1;i=9920 Object_1 ns=1;i=15050 0 Default JSON i=76 15050 i=38 true ns=1;i=10006 Object_1 ns=1;i=64 0 Default JSON i=76 64 i=38 true ns=1;i=1000 Object_1 ns=1;i=67 0 Default JSON i=76 67 i=38 true ns=1;i=1004 Object_1 ns=1;i=68 0 Default JSON i=76 68 i=38 true ns=1;i=1005 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/TestData/Design/TestData.Types.bsd ================================================ ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/TestData/Design/TestData.Types.xsd ================================================ ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/TestData/Design/TestDataDesign.csv ================================================ TestData_BinarySchema_WorkOrderStatusType,24,Variable TestData_BinarySchema_WorkOrderStatusType_DataTypeVersion,25,Variable TestData_BinarySchema_WorkOrderStatusType_DictionaryFragment,26,Variable TestData_BinarySchema_WorkOrderType,27,Variable TestData_BinarySchema_WorkOrderType_DataTypeVersion,28,Variable TestData_BinarySchema_WorkOrderType_DictionaryFragment,29,Variable Vector_Encoding_DefaultXml,36,Object WorkOrderStatusType_Encoding_DefaultXml,39,Object WorkOrderType_Encoding_DefaultXml,40,Object TestData_XmlSchema_Vector,43,Variable TestData_XmlSchema_Vector_DataTypeVersion,44,Variable TestData_XmlSchema_Vector_DictionaryFragment,45,Variable TestData_XmlSchema_VectorWithOptionalFields,49,Unspecified TestData_XmlSchema_VectorWithOptionalFields_DataTypeVersion,50,Unspecified TestData_XmlSchema_VectorWithOptionalFields_DictionaryFragment,51,Unspecified TestData_XmlSchema_WorkOrderStatusType,52,Variable TestData_XmlSchema_WorkOrderStatusType_DataTypeVersion,53,Variable TestData_XmlSchema_WorkOrderStatusType_DictionaryFragment,54,Variable TestData_XmlSchema_WorkOrderType,55,Variable TestData_XmlSchema_WorkOrderType_DataTypeVersion,56,Variable TestData_XmlSchema_WorkOrderType_DictionaryFragment,57,Variable Vector_Encoding_DefaultJson,64,Object VectorWithOptionalFields_Encoding_DefaultJson,66,Unspecified WorkOrderStatusType_Encoding_DefaultJson,67,Object WorkOrderType_Encoding_DefaultJson,68,Object Vector,1000,DataType WorkOrderStatusType,1004,DataType WorkOrderType,1005,DataType Vector_Encoding_DefaultBinary,1008,Object WorkOrderStatusType_Encoding_DefaultBinary,1011,Object WorkOrderType_Encoding_DefaultBinary,1012,Object TestData_BinarySchema_Vector,1015,Variable TestData_BinarySchema_Vector_DataTypeVersion,1016,Variable TestData_BinarySchema_Vector_DictionaryFragment,1017,Variable GenerateValuesMethodType,9369,Method GenerateValuesMethodType_InputArguments,9370,Variable GenerateValuesEventType,9371,ObjectType GenerateValuesEventType_EventId,9372,Variable GenerateValuesEventType_EventType,9373,Variable GenerateValuesEventType_SourceNode,9374,Variable GenerateValuesEventType_SourceName,9375,Variable GenerateValuesEventType_Time,9376,Variable GenerateValuesEventType_ReceiveTime,9377,Variable GenerateValuesEventType_LocalTime,9378,Variable GenerateValuesEventType_Message,9379,Variable GenerateValuesEventType_Severity,9380,Variable GenerateValuesEventType_Iterations,9381,Variable GenerateValuesEventType_NewValueCount,9382,Variable TestDataObjectType,9383,ObjectType TestDataObjectType_SimulationActive,9384,Variable TestDataObjectType_GenerateValues,9385,Method TestDataObjectType_GenerateValues_InputArguments,9386,Variable TestDataObjectType_CycleComplete,9387,Object TestDataObjectType_CycleComplete_EventId,9388,Variable TestDataObjectType_CycleComplete_EventType,9389,Variable TestDataObjectType_CycleComplete_SourceNode,9390,Variable TestDataObjectType_CycleComplete_SourceName,9391,Variable TestDataObjectType_CycleComplete_Time,9392,Variable TestDataObjectType_CycleComplete_ReceiveTime,9393,Variable TestDataObjectType_CycleComplete_LocalTime,9394,Variable TestDataObjectType_CycleComplete_Message,9395,Variable TestDataObjectType_CycleComplete_Severity,9396,Variable TestDataObjectType_CycleComplete_BranchId,9397,Variable TestDataObjectType_CycleComplete_Retain,9398,Variable TestDataObjectType_CycleComplete_EnabledState,9399,Variable TestDataObjectType_CycleComplete_EnabledState_Id,9400,Variable TestDataObjectType_CycleComplete_EnabledState_Name,9401,Variable TestDataObjectType_CycleComplete_EnabledState_Number,9402,Variable TestDataObjectType_CycleComplete_EnabledState_EffectiveDisplayName,9403,Variable TestDataObjectType_CycleComplete_EnabledState_TransitionTime,9404,Variable TestDataObjectType_CycleComplete_Quality,9405,Variable TestDataObjectType_CycleComplete_Quality_SourceTimestamp,9406,Variable TestDataObjectType_CycleComplete_LastSeverity,9409,Variable TestDataObjectType_CycleComplete_LastSeverity_SourceTimestamp,9410,Variable TestDataObjectType_CycleComplete_Comment,9411,Variable TestDataObjectType_CycleComplete_Comment_SourceTimestamp,9412,Variable TestDataObjectType_CycleComplete_ClientUserId,9413,Variable TestDataObjectType_CycleComplete_Enable,9414,Method TestDataObjectType_CycleComplete_Disable,9415,Method TestDataObjectType_CycleComplete_AddComment,9416,Method TestDataObjectType_CycleComplete_AddComment_InputArguments,9417,Variable TestDataObjectType_CycleComplete_AckedState,9420,Variable TestDataObjectType_CycleComplete_AckedState_Id,9421,Variable TestDataObjectType_CycleComplete_AckedState_Name,9422,Variable TestDataObjectType_CycleComplete_AckedState_Number,9423,Variable TestDataObjectType_CycleComplete_AckedState_EffectiveDisplayName,9424,Variable TestDataObjectType_CycleComplete_AckedState_TransitionTime,9425,Variable TestDataObjectType_CycleComplete_AckedState_TrueState,9426,Variable TestDataObjectType_CycleComplete_AckedState_FalseState,9427,Variable TestDataObjectType_CycleComplete_ConfirmedState,9428,Variable TestDataObjectType_CycleComplete_ConfirmedState_Id,9429,Variable TestDataObjectType_CycleComplete_ConfirmedState_Name,9430,Variable TestDataObjectType_CycleComplete_ConfirmedState_Number,9431,Variable TestDataObjectType_CycleComplete_ConfirmedState_EffectiveDisplayName,9432,Variable TestDataObjectType_CycleComplete_ConfirmedState_TransitionTime,9433,Variable TestDataObjectType_CycleComplete_ConfirmedState_TrueState,9434,Variable TestDataObjectType_CycleComplete_ConfirmedState_FalseState,9435,Variable TestDataObjectType_CycleComplete_Acknowledge,9436,Method TestDataObjectType_CycleComplete_Acknowledge_InputArguments,9437,Variable TestDataObjectType_CycleComplete_Confirm,9438,Method TestDataObjectType_CycleComplete_Confirm_InputArguments,9439,Variable ScalarValueDataType,9440,DataType ScalarValue1MethodType,9441,Method ScalarValue1MethodType_InputArguments,9442,Variable ScalarValue1MethodType_OutputArguments,9443,Variable ScalarValue2MethodType,9444,Method ScalarValue2MethodType_InputArguments,9445,Variable ScalarValue2MethodType_OutputArguments,9446,Variable ScalarValue3MethodType,9447,Method ScalarValue3MethodType_InputArguments,9448,Variable ScalarValue3MethodType_OutputArguments,9449,Variable ScalarValueObjectType,9450,ObjectType ScalarValueObjectType_SimulationActive,9451,Variable ScalarValueObjectType_GenerateValues,9452,Method ScalarValueObjectType_GenerateValues_InputArguments,9453,Variable ScalarValueObjectType_CycleComplete,9454,Object ScalarValueObjectType_CycleComplete_EventId,9455,Variable ScalarValueObjectType_CycleComplete_EventType,9456,Variable ScalarValueObjectType_CycleComplete_SourceNode,9457,Variable ScalarValueObjectType_CycleComplete_SourceName,9458,Variable ScalarValueObjectType_CycleComplete_Time,9459,Variable ScalarValueObjectType_CycleComplete_ReceiveTime,9460,Variable ScalarValueObjectType_CycleComplete_LocalTime,9461,Variable ScalarValueObjectType_CycleComplete_Message,9462,Variable ScalarValueObjectType_CycleComplete_Severity,9463,Variable ScalarValueObjectType_CycleComplete_BranchId,9464,Variable ScalarValueObjectType_CycleComplete_Retain,9465,Variable ScalarValueObjectType_CycleComplete_EnabledState,9466,Variable ScalarValueObjectType_CycleComplete_EnabledState_Id,9467,Variable ScalarValueObjectType_CycleComplete_EnabledState_Name,9468,Variable ScalarValueObjectType_CycleComplete_EnabledState_Number,9469,Variable ScalarValueObjectType_CycleComplete_EnabledState_EffectiveDisplayName,9470,Variable ScalarValueObjectType_CycleComplete_EnabledState_TransitionTime,9471,Variable ScalarValueObjectType_CycleComplete_Quality,9472,Variable ScalarValueObjectType_CycleComplete_Quality_SourceTimestamp,9473,Variable ScalarValueObjectType_CycleComplete_LastSeverity,9476,Variable ScalarValueObjectType_CycleComplete_LastSeverity_SourceTimestamp,9477,Variable ScalarValueObjectType_CycleComplete_Comment,9478,Variable ScalarValueObjectType_CycleComplete_Comment_SourceTimestamp,9479,Variable ScalarValueObjectType_CycleComplete_ClientUserId,9480,Variable ScalarValueObjectType_CycleComplete_Enable,9481,Method ScalarValueObjectType_CycleComplete_Disable,9482,Method ScalarValueObjectType_CycleComplete_AddComment,9483,Method ScalarValueObjectType_CycleComplete_AddComment_InputArguments,9484,Variable ScalarValueObjectType_CycleComplete_AckedState,9487,Variable ScalarValueObjectType_CycleComplete_AckedState_Id,9488,Variable ScalarValueObjectType_CycleComplete_AckedState_Name,9489,Variable ScalarValueObjectType_CycleComplete_AckedState_Number,9490,Variable ScalarValueObjectType_CycleComplete_AckedState_EffectiveDisplayName,9491,Variable ScalarValueObjectType_CycleComplete_AckedState_TransitionTime,9492,Variable ScalarValueObjectType_CycleComplete_AckedState_TrueState,9493,Variable ScalarValueObjectType_CycleComplete_AckedState_FalseState,9494,Variable ScalarValueObjectType_CycleComplete_ConfirmedState,9495,Variable ScalarValueObjectType_CycleComplete_ConfirmedState_Id,9496,Variable ScalarValueObjectType_CycleComplete_ConfirmedState_Name,9497,Variable ScalarValueObjectType_CycleComplete_ConfirmedState_Number,9498,Variable ScalarValueObjectType_CycleComplete_ConfirmedState_EffectiveDisplayName,9499,Variable ScalarValueObjectType_CycleComplete_ConfirmedState_TransitionTime,9500,Variable ScalarValueObjectType_CycleComplete_ConfirmedState_TrueState,9501,Variable ScalarValueObjectType_CycleComplete_ConfirmedState_FalseState,9502,Variable ScalarValueObjectType_CycleComplete_Acknowledge,9503,Method ScalarValueObjectType_CycleComplete_Acknowledge_InputArguments,9504,Variable ScalarValueObjectType_CycleComplete_Confirm,9505,Method ScalarValueObjectType_CycleComplete_Confirm_InputArguments,9506,Variable ScalarValueObjectType_BooleanValue,9507,Variable ScalarValueObjectType_SByteValue,9508,Variable ScalarValueObjectType_ByteValue,9509,Variable ScalarValueObjectType_Int16Value,9510,Variable ScalarValueObjectType_UInt16Value,9511,Variable ScalarValueObjectType_Int32Value,9512,Variable ScalarValueObjectType_UInt32Value,9513,Variable ScalarValueObjectType_Int64Value,9514,Variable ScalarValueObjectType_UInt64Value,9515,Variable ScalarValueObjectType_FloatValue,9516,Variable ScalarValueObjectType_DoubleValue,9517,Variable ScalarValueObjectType_StringValue,9518,Variable ScalarValueObjectType_DateTimeValue,9519,Variable ScalarValueObjectType_GuidValue,9520,Variable ScalarValueObjectType_ByteStringValue,9521,Variable ScalarValueObjectType_XmlElementValue,9522,Variable ScalarValueObjectType_NodeIdValue,9523,Variable ScalarValueObjectType_ExpandedNodeIdValue,9524,Variable ScalarValueObjectType_QualifiedNameValue,9525,Variable ScalarValueObjectType_LocalizedTextValue,9526,Variable ScalarValueObjectType_StatusCodeValue,9527,Variable ScalarValueObjectType_VariantValue,9528,Variable ScalarValueObjectType_EnumerationValue,9529,Variable ScalarValueObjectType_StructureValue,9530,Variable ScalarValueObjectType_NumberValue,9531,Variable ScalarValueObjectType_IntegerValue,9532,Variable ScalarValueObjectType_UIntegerValue,9533,Variable AnalogScalarValueObjectType,9534,ObjectType AnalogScalarValueObjectType_SimulationActive,9535,Variable AnalogScalarValueObjectType_GenerateValues,9536,Method AnalogScalarValueObjectType_GenerateValues_InputArguments,9537,Variable AnalogScalarValueObjectType_CycleComplete,9538,Object AnalogScalarValueObjectType_CycleComplete_EventId,9539,Variable AnalogScalarValueObjectType_CycleComplete_EventType,9540,Variable AnalogScalarValueObjectType_CycleComplete_SourceNode,9541,Variable AnalogScalarValueObjectType_CycleComplete_SourceName,9542,Variable AnalogScalarValueObjectType_CycleComplete_Time,9543,Variable AnalogScalarValueObjectType_CycleComplete_ReceiveTime,9544,Variable AnalogScalarValueObjectType_CycleComplete_LocalTime,9545,Variable AnalogScalarValueObjectType_CycleComplete_Message,9546,Variable AnalogScalarValueObjectType_CycleComplete_Severity,9547,Variable AnalogScalarValueObjectType_CycleComplete_BranchId,9548,Variable AnalogScalarValueObjectType_CycleComplete_Retain,9549,Variable AnalogScalarValueObjectType_CycleComplete_EnabledState,9550,Variable AnalogScalarValueObjectType_CycleComplete_EnabledState_Id,9551,Variable AnalogScalarValueObjectType_CycleComplete_EnabledState_Name,9552,Variable AnalogScalarValueObjectType_CycleComplete_EnabledState_Number,9553,Variable AnalogScalarValueObjectType_CycleComplete_EnabledState_EffectiveDisplayName,9554,Variable AnalogScalarValueObjectType_CycleComplete_EnabledState_TransitionTime,9555,Variable AnalogScalarValueObjectType_CycleComplete_Quality,9556,Variable AnalogScalarValueObjectType_CycleComplete_Quality_SourceTimestamp,9557,Variable AnalogScalarValueObjectType_CycleComplete_LastSeverity,9560,Variable AnalogScalarValueObjectType_CycleComplete_LastSeverity_SourceTimestamp,9561,Variable AnalogScalarValueObjectType_CycleComplete_Comment,9562,Variable AnalogScalarValueObjectType_CycleComplete_Comment_SourceTimestamp,9563,Variable AnalogScalarValueObjectType_CycleComplete_ClientUserId,9564,Variable AnalogScalarValueObjectType_CycleComplete_Enable,9565,Method AnalogScalarValueObjectType_CycleComplete_Disable,9566,Method AnalogScalarValueObjectType_CycleComplete_AddComment,9567,Method AnalogScalarValueObjectType_CycleComplete_AddComment_InputArguments,9568,Variable AnalogScalarValueObjectType_CycleComplete_AckedState,9571,Variable AnalogScalarValueObjectType_CycleComplete_AckedState_Id,9572,Variable AnalogScalarValueObjectType_CycleComplete_AckedState_Name,9573,Variable AnalogScalarValueObjectType_CycleComplete_AckedState_Number,9574,Variable AnalogScalarValueObjectType_CycleComplete_AckedState_EffectiveDisplayName,9575,Variable AnalogScalarValueObjectType_CycleComplete_AckedState_TransitionTime,9576,Variable AnalogScalarValueObjectType_CycleComplete_AckedState_TrueState,9577,Variable AnalogScalarValueObjectType_CycleComplete_AckedState_FalseState,9578,Variable AnalogScalarValueObjectType_CycleComplete_ConfirmedState,9579,Variable AnalogScalarValueObjectType_CycleComplete_ConfirmedState_Id,9580,Variable AnalogScalarValueObjectType_CycleComplete_ConfirmedState_Name,9581,Variable AnalogScalarValueObjectType_CycleComplete_ConfirmedState_Number,9582,Variable AnalogScalarValueObjectType_CycleComplete_ConfirmedState_EffectiveDisplayName,9583,Variable AnalogScalarValueObjectType_CycleComplete_ConfirmedState_TransitionTime,9584,Variable AnalogScalarValueObjectType_CycleComplete_ConfirmedState_TrueState,9585,Variable AnalogScalarValueObjectType_CycleComplete_ConfirmedState_FalseState,9586,Variable AnalogScalarValueObjectType_CycleComplete_Acknowledge,9587,Method AnalogScalarValueObjectType_CycleComplete_Acknowledge_InputArguments,9588,Variable AnalogScalarValueObjectType_CycleComplete_Confirm,9589,Method AnalogScalarValueObjectType_CycleComplete_Confirm_InputArguments,9590,Variable AnalogScalarValueObjectType_SByteValue,9591,Variable AnalogScalarValueObjectType_SByteValue_Definition,9592,Variable AnalogScalarValueObjectType_SByteValue_ValuePrecision,9593,Variable AnalogScalarValueObjectType_SByteValue_EURange,9594,Variable AnalogScalarValueObjectType_SByteValue_InstrumentRange,9595,Variable AnalogScalarValueObjectType_SByteValue_EngineeringUnits,9596,Variable AnalogScalarValueObjectType_ByteValue,9597,Variable AnalogScalarValueObjectType_ByteValue_Definition,9598,Variable AnalogScalarValueObjectType_ByteValue_ValuePrecision,9599,Variable AnalogScalarValueObjectType_ByteValue_EURange,9600,Variable AnalogScalarValueObjectType_ByteValue_InstrumentRange,9601,Variable AnalogScalarValueObjectType_ByteValue_EngineeringUnits,9602,Variable AnalogScalarValueObjectType_Int16Value,9603,Variable AnalogScalarValueObjectType_Int16Value_Definition,9604,Variable AnalogScalarValueObjectType_Int16Value_ValuePrecision,9605,Variable AnalogScalarValueObjectType_Int16Value_EURange,9606,Variable AnalogScalarValueObjectType_Int16Value_InstrumentRange,9607,Variable AnalogScalarValueObjectType_Int16Value_EngineeringUnits,9608,Variable AnalogScalarValueObjectType_UInt16Value,9609,Variable AnalogScalarValueObjectType_UInt16Value_Definition,9610,Variable AnalogScalarValueObjectType_UInt16Value_ValuePrecision,9611,Variable AnalogScalarValueObjectType_UInt16Value_EURange,9612,Variable AnalogScalarValueObjectType_UInt16Value_InstrumentRange,9613,Variable AnalogScalarValueObjectType_UInt16Value_EngineeringUnits,9614,Variable AnalogScalarValueObjectType_Int32Value,9615,Variable AnalogScalarValueObjectType_Int32Value_Definition,9616,Variable AnalogScalarValueObjectType_Int32Value_ValuePrecision,9617,Variable AnalogScalarValueObjectType_Int32Value_EURange,9618,Variable AnalogScalarValueObjectType_Int32Value_InstrumentRange,9619,Variable AnalogScalarValueObjectType_Int32Value_EngineeringUnits,9620,Variable AnalogScalarValueObjectType_UInt32Value,9621,Variable AnalogScalarValueObjectType_UInt32Value_Definition,9622,Variable AnalogScalarValueObjectType_UInt32Value_ValuePrecision,9623,Variable AnalogScalarValueObjectType_UInt32Value_EURange,9624,Variable AnalogScalarValueObjectType_UInt32Value_InstrumentRange,9625,Variable AnalogScalarValueObjectType_UInt32Value_EngineeringUnits,9626,Variable AnalogScalarValueObjectType_Int64Value,9627,Variable AnalogScalarValueObjectType_Int64Value_Definition,9628,Variable AnalogScalarValueObjectType_Int64Value_ValuePrecision,9629,Variable AnalogScalarValueObjectType_Int64Value_EURange,9630,Variable AnalogScalarValueObjectType_Int64Value_InstrumentRange,9631,Variable AnalogScalarValueObjectType_Int64Value_EngineeringUnits,9632,Variable AnalogScalarValueObjectType_UInt64Value,9633,Variable AnalogScalarValueObjectType_UInt64Value_Definition,9634,Variable AnalogScalarValueObjectType_UInt64Value_ValuePrecision,9635,Variable AnalogScalarValueObjectType_UInt64Value_EURange,9636,Variable AnalogScalarValueObjectType_UInt64Value_InstrumentRange,9637,Variable AnalogScalarValueObjectType_UInt64Value_EngineeringUnits,9638,Variable AnalogScalarValueObjectType_FloatValue,9639,Variable AnalogScalarValueObjectType_FloatValue_Definition,9640,Variable AnalogScalarValueObjectType_FloatValue_ValuePrecision,9641,Variable AnalogScalarValueObjectType_FloatValue_EURange,9642,Variable AnalogScalarValueObjectType_FloatValue_InstrumentRange,9643,Variable AnalogScalarValueObjectType_FloatValue_EngineeringUnits,9644,Variable AnalogScalarValueObjectType_DoubleValue,9645,Variable AnalogScalarValueObjectType_DoubleValue_Definition,9646,Variable AnalogScalarValueObjectType_DoubleValue_ValuePrecision,9647,Variable AnalogScalarValueObjectType_DoubleValue_EURange,9648,Variable AnalogScalarValueObjectType_DoubleValue_InstrumentRange,9649,Variable AnalogScalarValueObjectType_DoubleValue_EngineeringUnits,9650,Variable AnalogScalarValueObjectType_NumberValue,9651,Variable AnalogScalarValueObjectType_NumberValue_Definition,9652,Variable AnalogScalarValueObjectType_NumberValue_ValuePrecision,9653,Variable AnalogScalarValueObjectType_NumberValue_EURange,9654,Variable AnalogScalarValueObjectType_NumberValue_InstrumentRange,9655,Variable AnalogScalarValueObjectType_NumberValue_EngineeringUnits,9656,Variable AnalogScalarValueObjectType_IntegerValue,9657,Variable AnalogScalarValueObjectType_IntegerValue_Definition,9658,Variable AnalogScalarValueObjectType_IntegerValue_ValuePrecision,9659,Variable AnalogScalarValueObjectType_IntegerValue_EURange,9660,Variable AnalogScalarValueObjectType_IntegerValue_InstrumentRange,9661,Variable AnalogScalarValueObjectType_IntegerValue_EngineeringUnits,9662,Variable AnalogScalarValueObjectType_UIntegerValue,9663,Variable AnalogScalarValueObjectType_UIntegerValue_Definition,9664,Variable AnalogScalarValueObjectType_UIntegerValue_ValuePrecision,9665,Variable AnalogScalarValueObjectType_UIntegerValue_EURange,9666,Variable AnalogScalarValueObjectType_UIntegerValue_InstrumentRange,9667,Variable AnalogScalarValueObjectType_UIntegerValue_EngineeringUnits,9668,Variable ArrayValueDataType,9669,DataType ArrayValue1MethodType,9670,Method ArrayValue1MethodType_InputArguments,9671,Variable ArrayValue1MethodType_OutputArguments,9672,Variable ArrayValue2MethodType,9673,Method ArrayValue2MethodType_InputArguments,9674,Variable ArrayValue2MethodType_OutputArguments,9675,Variable ArrayValue3MethodType,9676,Method ArrayValue3MethodType_InputArguments,9677,Variable ArrayValue3MethodType_OutputArguments,9678,Variable ArrayValueObjectType,9679,ObjectType ArrayValueObjectType_SimulationActive,9680,Variable ArrayValueObjectType_GenerateValues,9681,Method ArrayValueObjectType_GenerateValues_InputArguments,9682,Variable ArrayValueObjectType_CycleComplete,9683,Object ArrayValueObjectType_CycleComplete_EventId,9684,Variable ArrayValueObjectType_CycleComplete_EventType,9685,Variable ArrayValueObjectType_CycleComplete_SourceNode,9686,Variable ArrayValueObjectType_CycleComplete_SourceName,9687,Variable ArrayValueObjectType_CycleComplete_Time,9688,Variable ArrayValueObjectType_CycleComplete_ReceiveTime,9689,Variable ArrayValueObjectType_CycleComplete_LocalTime,9690,Variable ArrayValueObjectType_CycleComplete_Message,9691,Variable ArrayValueObjectType_CycleComplete_Severity,9692,Variable ArrayValueObjectType_CycleComplete_BranchId,9693,Variable ArrayValueObjectType_CycleComplete_Retain,9694,Variable ArrayValueObjectType_CycleComplete_EnabledState,9695,Variable ArrayValueObjectType_CycleComplete_EnabledState_Id,9696,Variable ArrayValueObjectType_CycleComplete_EnabledState_Name,9697,Variable ArrayValueObjectType_CycleComplete_EnabledState_Number,9698,Variable ArrayValueObjectType_CycleComplete_EnabledState_EffectiveDisplayName,9699,Variable ArrayValueObjectType_CycleComplete_EnabledState_TransitionTime,9700,Variable ArrayValueObjectType_CycleComplete_Quality,9701,Variable ArrayValueObjectType_CycleComplete_Quality_SourceTimestamp,9702,Variable ArrayValueObjectType_CycleComplete_LastSeverity,9705,Variable ArrayValueObjectType_CycleComplete_LastSeverity_SourceTimestamp,9706,Variable ArrayValueObjectType_CycleComplete_Comment,9707,Variable ArrayValueObjectType_CycleComplete_Comment_SourceTimestamp,9708,Variable ArrayValueObjectType_CycleComplete_ClientUserId,9709,Variable ArrayValueObjectType_CycleComplete_Enable,9710,Method ArrayValueObjectType_CycleComplete_Disable,9711,Method ArrayValueObjectType_CycleComplete_AddComment,9712,Method ArrayValueObjectType_CycleComplete_AddComment_InputArguments,9713,Variable ArrayValueObjectType_CycleComplete_AckedState,9716,Variable ArrayValueObjectType_CycleComplete_AckedState_Id,9717,Variable ArrayValueObjectType_CycleComplete_AckedState_Name,9718,Variable ArrayValueObjectType_CycleComplete_AckedState_Number,9719,Variable ArrayValueObjectType_CycleComplete_AckedState_EffectiveDisplayName,9720,Variable ArrayValueObjectType_CycleComplete_AckedState_TransitionTime,9721,Variable ArrayValueObjectType_CycleComplete_AckedState_TrueState,9722,Variable ArrayValueObjectType_CycleComplete_AckedState_FalseState,9723,Variable ArrayValueObjectType_CycleComplete_ConfirmedState,9724,Variable ArrayValueObjectType_CycleComplete_ConfirmedState_Id,9725,Variable ArrayValueObjectType_CycleComplete_ConfirmedState_Name,9726,Variable ArrayValueObjectType_CycleComplete_ConfirmedState_Number,9727,Variable ArrayValueObjectType_CycleComplete_ConfirmedState_EffectiveDisplayName,9728,Variable ArrayValueObjectType_CycleComplete_ConfirmedState_TransitionTime,9729,Variable ArrayValueObjectType_CycleComplete_ConfirmedState_TrueState,9730,Variable ArrayValueObjectType_CycleComplete_ConfirmedState_FalseState,9731,Variable ArrayValueObjectType_CycleComplete_Acknowledge,9732,Method ArrayValueObjectType_CycleComplete_Acknowledge_InputArguments,9733,Variable ArrayValueObjectType_CycleComplete_Confirm,9734,Method ArrayValueObjectType_CycleComplete_Confirm_InputArguments,9735,Variable ArrayValueObjectType_BooleanValue,9736,Variable ArrayValueObjectType_SByteValue,9737,Variable ArrayValueObjectType_ByteValue,9738,Variable ArrayValueObjectType_Int16Value,9739,Variable ArrayValueObjectType_UInt16Value,9740,Variable ArrayValueObjectType_Int32Value,9741,Variable ArrayValueObjectType_UInt32Value,9742,Variable ArrayValueObjectType_Int64Value,9743,Variable ArrayValueObjectType_UInt64Value,9744,Variable ArrayValueObjectType_FloatValue,9745,Variable ArrayValueObjectType_DoubleValue,9746,Variable ArrayValueObjectType_StringValue,9747,Variable ArrayValueObjectType_DateTimeValue,9748,Variable ArrayValueObjectType_GuidValue,9749,Variable ArrayValueObjectType_ByteStringValue,9750,Variable ArrayValueObjectType_XmlElementValue,9751,Variable ArrayValueObjectType_NodeIdValue,9752,Variable ArrayValueObjectType_ExpandedNodeIdValue,9753,Variable ArrayValueObjectType_QualifiedNameValue,9754,Variable ArrayValueObjectType_LocalizedTextValue,9755,Variable ArrayValueObjectType_StatusCodeValue,9756,Variable ArrayValueObjectType_VariantValue,9757,Variable ArrayValueObjectType_EnumerationValue,9758,Variable ArrayValueObjectType_StructureValue,9759,Variable ArrayValueObjectType_NumberValue,9760,Variable ArrayValueObjectType_IntegerValue,9761,Variable ArrayValueObjectType_UIntegerValue,9762,Variable AnalogArrayValueObjectType,9763,ObjectType AnalogArrayValueObjectType_SimulationActive,9764,Variable AnalogArrayValueObjectType_GenerateValues,9765,Method AnalogArrayValueObjectType_GenerateValues_InputArguments,9766,Variable AnalogArrayValueObjectType_CycleComplete,9767,Object AnalogArrayValueObjectType_CycleComplete_EventId,9768,Variable AnalogArrayValueObjectType_CycleComplete_EventType,9769,Variable AnalogArrayValueObjectType_CycleComplete_SourceNode,9770,Variable AnalogArrayValueObjectType_CycleComplete_SourceName,9771,Variable AnalogArrayValueObjectType_CycleComplete_Time,9772,Variable AnalogArrayValueObjectType_CycleComplete_ReceiveTime,9773,Variable AnalogArrayValueObjectType_CycleComplete_LocalTime,9774,Variable AnalogArrayValueObjectType_CycleComplete_Message,9775,Variable AnalogArrayValueObjectType_CycleComplete_Severity,9776,Variable AnalogArrayValueObjectType_CycleComplete_BranchId,9777,Variable AnalogArrayValueObjectType_CycleComplete_Retain,9778,Variable AnalogArrayValueObjectType_CycleComplete_EnabledState,9779,Variable AnalogArrayValueObjectType_CycleComplete_EnabledState_Id,9780,Variable AnalogArrayValueObjectType_CycleComplete_EnabledState_Name,9781,Variable AnalogArrayValueObjectType_CycleComplete_EnabledState_Number,9782,Variable AnalogArrayValueObjectType_CycleComplete_EnabledState_EffectiveDisplayName,9783,Variable AnalogArrayValueObjectType_CycleComplete_EnabledState_TransitionTime,9784,Variable AnalogArrayValueObjectType_CycleComplete_Quality,9785,Variable AnalogArrayValueObjectType_CycleComplete_Quality_SourceTimestamp,9786,Variable AnalogArrayValueObjectType_CycleComplete_LastSeverity,9789,Variable AnalogArrayValueObjectType_CycleComplete_LastSeverity_SourceTimestamp,9790,Variable AnalogArrayValueObjectType_CycleComplete_Comment,9791,Variable AnalogArrayValueObjectType_CycleComplete_Comment_SourceTimestamp,9792,Variable AnalogArrayValueObjectType_CycleComplete_ClientUserId,9793,Variable AnalogArrayValueObjectType_CycleComplete_Enable,9794,Method AnalogArrayValueObjectType_CycleComplete_Disable,9795,Method AnalogArrayValueObjectType_CycleComplete_AddComment,9796,Method AnalogArrayValueObjectType_CycleComplete_AddComment_InputArguments,9797,Variable AnalogArrayValueObjectType_CycleComplete_AckedState,9800,Variable AnalogArrayValueObjectType_CycleComplete_AckedState_Id,9801,Variable AnalogArrayValueObjectType_CycleComplete_AckedState_Name,9802,Variable AnalogArrayValueObjectType_CycleComplete_AckedState_Number,9803,Variable AnalogArrayValueObjectType_CycleComplete_AckedState_EffectiveDisplayName,9804,Variable AnalogArrayValueObjectType_CycleComplete_AckedState_TransitionTime,9805,Variable AnalogArrayValueObjectType_CycleComplete_AckedState_TrueState,9806,Variable AnalogArrayValueObjectType_CycleComplete_AckedState_FalseState,9807,Variable AnalogArrayValueObjectType_CycleComplete_ConfirmedState,9808,Variable AnalogArrayValueObjectType_CycleComplete_ConfirmedState_Id,9809,Variable AnalogArrayValueObjectType_CycleComplete_ConfirmedState_Name,9810,Variable AnalogArrayValueObjectType_CycleComplete_ConfirmedState_Number,9811,Variable AnalogArrayValueObjectType_CycleComplete_ConfirmedState_EffectiveDisplayName,9812,Variable AnalogArrayValueObjectType_CycleComplete_ConfirmedState_TransitionTime,9813,Variable AnalogArrayValueObjectType_CycleComplete_ConfirmedState_TrueState,9814,Variable AnalogArrayValueObjectType_CycleComplete_ConfirmedState_FalseState,9815,Variable AnalogArrayValueObjectType_CycleComplete_Acknowledge,9816,Method AnalogArrayValueObjectType_CycleComplete_Acknowledge_InputArguments,9817,Variable AnalogArrayValueObjectType_CycleComplete_Confirm,9818,Method AnalogArrayValueObjectType_CycleComplete_Confirm_InputArguments,9819,Variable AnalogArrayValueObjectType_SByteValue,9820,Variable AnalogArrayValueObjectType_SByteValue_Definition,9821,Variable AnalogArrayValueObjectType_SByteValue_ValuePrecision,9822,Variable AnalogArrayValueObjectType_SByteValue_EURange,9823,Variable AnalogArrayValueObjectType_SByteValue_InstrumentRange,9824,Variable AnalogArrayValueObjectType_SByteValue_EngineeringUnits,9825,Variable AnalogArrayValueObjectType_ByteValue,9826,Variable AnalogArrayValueObjectType_ByteValue_Definition,9827,Variable AnalogArrayValueObjectType_ByteValue_ValuePrecision,9828,Variable AnalogArrayValueObjectType_ByteValue_EURange,9829,Variable AnalogArrayValueObjectType_ByteValue_InstrumentRange,9830,Variable AnalogArrayValueObjectType_ByteValue_EngineeringUnits,9831,Variable AnalogArrayValueObjectType_Int16Value,9832,Variable AnalogArrayValueObjectType_Int16Value_Definition,9833,Variable AnalogArrayValueObjectType_Int16Value_ValuePrecision,9834,Variable AnalogArrayValueObjectType_Int16Value_EURange,9835,Variable AnalogArrayValueObjectType_Int16Value_InstrumentRange,9836,Variable AnalogArrayValueObjectType_Int16Value_EngineeringUnits,9837,Variable AnalogArrayValueObjectType_UInt16Value,9838,Variable AnalogArrayValueObjectType_UInt16Value_Definition,9839,Variable AnalogArrayValueObjectType_UInt16Value_ValuePrecision,9840,Variable AnalogArrayValueObjectType_UInt16Value_EURange,9841,Variable AnalogArrayValueObjectType_UInt16Value_InstrumentRange,9842,Variable AnalogArrayValueObjectType_UInt16Value_EngineeringUnits,9843,Variable AnalogArrayValueObjectType_Int32Value,9844,Variable AnalogArrayValueObjectType_Int32Value_Definition,9845,Variable AnalogArrayValueObjectType_Int32Value_ValuePrecision,9846,Variable AnalogArrayValueObjectType_Int32Value_EURange,9847,Variable AnalogArrayValueObjectType_Int32Value_InstrumentRange,9848,Variable AnalogArrayValueObjectType_Int32Value_EngineeringUnits,9849,Variable AnalogArrayValueObjectType_UInt32Value,9850,Variable AnalogArrayValueObjectType_UInt32Value_Definition,9851,Variable AnalogArrayValueObjectType_UInt32Value_ValuePrecision,9852,Variable AnalogArrayValueObjectType_UInt32Value_EURange,9853,Variable AnalogArrayValueObjectType_UInt32Value_InstrumentRange,9854,Variable AnalogArrayValueObjectType_UInt32Value_EngineeringUnits,9855,Variable AnalogArrayValueObjectType_Int64Value,9856,Variable AnalogArrayValueObjectType_Int64Value_Definition,9857,Variable AnalogArrayValueObjectType_Int64Value_ValuePrecision,9858,Variable AnalogArrayValueObjectType_Int64Value_EURange,9859,Variable AnalogArrayValueObjectType_Int64Value_InstrumentRange,9860,Variable AnalogArrayValueObjectType_Int64Value_EngineeringUnits,9861,Variable AnalogArrayValueObjectType_UInt64Value,9862,Variable AnalogArrayValueObjectType_UInt64Value_Definition,9863,Variable AnalogArrayValueObjectType_UInt64Value_ValuePrecision,9864,Variable AnalogArrayValueObjectType_UInt64Value_EURange,9865,Variable AnalogArrayValueObjectType_UInt64Value_InstrumentRange,9866,Variable AnalogArrayValueObjectType_UInt64Value_EngineeringUnits,9867,Variable AnalogArrayValueObjectType_FloatValue,9868,Variable AnalogArrayValueObjectType_FloatValue_Definition,9869,Variable AnalogArrayValueObjectType_FloatValue_ValuePrecision,9870,Variable AnalogArrayValueObjectType_FloatValue_EURange,9871,Variable AnalogArrayValueObjectType_FloatValue_InstrumentRange,9872,Variable AnalogArrayValueObjectType_FloatValue_EngineeringUnits,9873,Variable AnalogArrayValueObjectType_DoubleValue,9874,Variable AnalogArrayValueObjectType_DoubleValue_Definition,9875,Variable AnalogArrayValueObjectType_DoubleValue_ValuePrecision,9876,Variable AnalogArrayValueObjectType_DoubleValue_EURange,9877,Variable AnalogArrayValueObjectType_DoubleValue_InstrumentRange,9878,Variable AnalogArrayValueObjectType_DoubleValue_EngineeringUnits,9879,Variable AnalogArrayValueObjectType_NumberValue,9880,Variable AnalogArrayValueObjectType_NumberValue_Definition,9881,Variable AnalogArrayValueObjectType_NumberValue_ValuePrecision,9882,Variable AnalogArrayValueObjectType_NumberValue_EURange,9883,Variable AnalogArrayValueObjectType_NumberValue_InstrumentRange,9884,Variable AnalogArrayValueObjectType_NumberValue_EngineeringUnits,9885,Variable AnalogArrayValueObjectType_IntegerValue,9886,Variable AnalogArrayValueObjectType_IntegerValue_Definition,9887,Variable AnalogArrayValueObjectType_IntegerValue_ValuePrecision,9888,Variable AnalogArrayValueObjectType_IntegerValue_EURange,9889,Variable AnalogArrayValueObjectType_IntegerValue_InstrumentRange,9890,Variable AnalogArrayValueObjectType_IntegerValue_EngineeringUnits,9891,Variable AnalogArrayValueObjectType_UIntegerValue,9892,Variable AnalogArrayValueObjectType_UIntegerValue_Definition,9893,Variable AnalogArrayValueObjectType_UIntegerValue_ValuePrecision,9894,Variable AnalogArrayValueObjectType_UIntegerValue_EURange,9895,Variable AnalogArrayValueObjectType_UIntegerValue_InstrumentRange,9896,Variable AnalogArrayValueObjectType_UIntegerValue_EngineeringUnits,9897,Variable BooleanDataType,9898,DataType SByteDataType,9899,DataType ByteDataType,9900,DataType Int16DataType,9901,DataType UInt16DataType,9902,DataType Int32DataType,9903,DataType UInt32DataType,9904,DataType Int64DataType,9905,DataType UInt64DataType,9906,DataType FloatDataType,9907,DataType DoubleDataType,9908,DataType StringDataType,9909,DataType DateTimeDataType,9910,DataType GuidDataType,9911,DataType ByteStringDataType,9912,DataType XmlElementDataType,9913,DataType NodeIdDataType,9914,DataType ExpandedNodeIdDataType,9915,DataType QualifiedNameDataType,9916,DataType LocalizedTextDataType,9917,DataType StatusCodeDataType,9918,DataType VariantDataType,9919,DataType UserScalarValueDataType,9920,DataType UserScalarValueObjectType,9921,ObjectType UserScalarValueObjectType_SimulationActive,9922,Variable UserScalarValueObjectType_GenerateValues,9923,Method UserScalarValueObjectType_GenerateValues_InputArguments,9924,Variable UserScalarValueObjectType_CycleComplete,9925,Object UserScalarValueObjectType_CycleComplete_EventId,9926,Variable UserScalarValueObjectType_CycleComplete_EventType,9927,Variable UserScalarValueObjectType_CycleComplete_SourceNode,9928,Variable UserScalarValueObjectType_CycleComplete_SourceName,9929,Variable UserScalarValueObjectType_CycleComplete_Time,9930,Variable UserScalarValueObjectType_CycleComplete_ReceiveTime,9931,Variable UserScalarValueObjectType_CycleComplete_LocalTime,9932,Variable UserScalarValueObjectType_CycleComplete_Message,9933,Variable UserScalarValueObjectType_CycleComplete_Severity,9934,Variable UserScalarValueObjectType_CycleComplete_BranchId,9935,Variable UserScalarValueObjectType_CycleComplete_Retain,9936,Variable UserScalarValueObjectType_CycleComplete_EnabledState,9937,Variable UserScalarValueObjectType_CycleComplete_EnabledState_Id,9938,Variable UserScalarValueObjectType_CycleComplete_EnabledState_Name,9939,Variable UserScalarValueObjectType_CycleComplete_EnabledState_Number,9940,Variable UserScalarValueObjectType_CycleComplete_EnabledState_EffectiveDisplayName,9941,Variable UserScalarValueObjectType_CycleComplete_EnabledState_TransitionTime,9942,Variable UserScalarValueObjectType_CycleComplete_Quality,9943,Variable UserScalarValueObjectType_CycleComplete_Quality_SourceTimestamp,9944,Variable UserScalarValueObjectType_CycleComplete_LastSeverity,9947,Variable UserScalarValueObjectType_CycleComplete_LastSeverity_SourceTimestamp,9948,Variable UserScalarValueObjectType_CycleComplete_Comment,9949,Variable UserScalarValueObjectType_CycleComplete_Comment_SourceTimestamp,9950,Variable UserScalarValueObjectType_CycleComplete_ClientUserId,9951,Variable UserScalarValueObjectType_CycleComplete_Enable,9952,Method UserScalarValueObjectType_CycleComplete_Disable,9953,Method UserScalarValueObjectType_CycleComplete_AddComment,9954,Method UserScalarValueObjectType_CycleComplete_AddComment_InputArguments,9955,Variable UserScalarValueObjectType_CycleComplete_AckedState,9958,Variable UserScalarValueObjectType_CycleComplete_AckedState_Id,9959,Variable UserScalarValueObjectType_CycleComplete_AckedState_Name,9960,Variable UserScalarValueObjectType_CycleComplete_AckedState_Number,9961,Variable UserScalarValueObjectType_CycleComplete_AckedState_EffectiveDisplayName,9962,Variable UserScalarValueObjectType_CycleComplete_AckedState_TransitionTime,9963,Variable UserScalarValueObjectType_CycleComplete_AckedState_TrueState,9964,Variable UserScalarValueObjectType_CycleComplete_AckedState_FalseState,9965,Variable UserScalarValueObjectType_CycleComplete_ConfirmedState,9966,Variable UserScalarValueObjectType_CycleComplete_ConfirmedState_Id,9967,Variable UserScalarValueObjectType_CycleComplete_ConfirmedState_Name,9968,Variable UserScalarValueObjectType_CycleComplete_ConfirmedState_Number,9969,Variable UserScalarValueObjectType_CycleComplete_ConfirmedState_EffectiveDisplayName,9970,Variable UserScalarValueObjectType_CycleComplete_ConfirmedState_TransitionTime,9971,Variable UserScalarValueObjectType_CycleComplete_ConfirmedState_TrueState,9972,Variable UserScalarValueObjectType_CycleComplete_ConfirmedState_FalseState,9973,Variable UserScalarValueObjectType_CycleComplete_Acknowledge,9974,Method UserScalarValueObjectType_CycleComplete_Acknowledge_InputArguments,9975,Variable UserScalarValueObjectType_CycleComplete_Confirm,9976,Method UserScalarValueObjectType_CycleComplete_Confirm_InputArguments,9977,Variable UserScalarValueObjectType_BooleanValue,9978,Variable UserScalarValueObjectType_SByteValue,9979,Variable UserScalarValueObjectType_ByteValue,9980,Variable UserScalarValueObjectType_Int16Value,9981,Variable UserScalarValueObjectType_UInt16Value,9982,Variable UserScalarValueObjectType_Int32Value,9983,Variable UserScalarValueObjectType_UInt32Value,9984,Variable UserScalarValueObjectType_Int64Value,9985,Variable UserScalarValueObjectType_UInt64Value,9986,Variable UserScalarValueObjectType_FloatValue,9987,Variable UserScalarValueObjectType_DoubleValue,9988,Variable UserScalarValueObjectType_StringValue,9989,Variable UserScalarValueObjectType_DateTimeValue,9990,Variable UserScalarValueObjectType_GuidValue,9991,Variable UserScalarValueObjectType_ByteStringValue,9992,Variable UserScalarValueObjectType_XmlElementValue,9993,Variable UserScalarValueObjectType_NodeIdValue,9994,Variable UserScalarValueObjectType_ExpandedNodeIdValue,9995,Variable UserScalarValueObjectType_QualifiedNameValue,9996,Variable UserScalarValueObjectType_LocalizedTextValue,9997,Variable UserScalarValueObjectType_StatusCodeValue,9998,Variable UserScalarValueObjectType_VariantValue,9999,Variable UserScalarValue1MethodType,10000,Method UserScalarValue1MethodType_InputArguments,10001,Variable UserScalarValue1MethodType_OutputArguments,10002,Variable UserScalarValue2MethodType,10003,Method UserScalarValue2MethodType_InputArguments,10004,Variable UserScalarValue2MethodType_OutputArguments,10005,Variable UserArrayValueDataType,10006,DataType UserArrayValueObjectType,10007,ObjectType UserArrayValueObjectType_SimulationActive,10008,Variable UserArrayValueObjectType_GenerateValues,10009,Method UserArrayValueObjectType_GenerateValues_InputArguments,10010,Variable UserArrayValueObjectType_CycleComplete,10011,Object UserArrayValueObjectType_CycleComplete_EventId,10012,Variable UserArrayValueObjectType_CycleComplete_EventType,10013,Variable UserArrayValueObjectType_CycleComplete_SourceNode,10014,Variable UserArrayValueObjectType_CycleComplete_SourceName,10015,Variable UserArrayValueObjectType_CycleComplete_Time,10016,Variable UserArrayValueObjectType_CycleComplete_ReceiveTime,10017,Variable UserArrayValueObjectType_CycleComplete_LocalTime,10018,Variable UserArrayValueObjectType_CycleComplete_Message,10019,Variable UserArrayValueObjectType_CycleComplete_Severity,10020,Variable UserArrayValueObjectType_CycleComplete_BranchId,10021,Variable UserArrayValueObjectType_CycleComplete_Retain,10022,Variable UserArrayValueObjectType_CycleComplete_EnabledState,10023,Variable UserArrayValueObjectType_CycleComplete_EnabledState_Id,10024,Variable UserArrayValueObjectType_CycleComplete_EnabledState_Name,10025,Variable UserArrayValueObjectType_CycleComplete_EnabledState_Number,10026,Variable UserArrayValueObjectType_CycleComplete_EnabledState_EffectiveDisplayName,10027,Variable UserArrayValueObjectType_CycleComplete_EnabledState_TransitionTime,10028,Variable UserArrayValueObjectType_CycleComplete_Quality,10029,Variable UserArrayValueObjectType_CycleComplete_Quality_SourceTimestamp,10030,Variable UserArrayValueObjectType_CycleComplete_LastSeverity,10033,Variable UserArrayValueObjectType_CycleComplete_LastSeverity_SourceTimestamp,10034,Variable UserArrayValueObjectType_CycleComplete_Comment,10035,Variable UserArrayValueObjectType_CycleComplete_Comment_SourceTimestamp,10036,Variable UserArrayValueObjectType_CycleComplete_ClientUserId,10037,Variable UserArrayValueObjectType_CycleComplete_Enable,10038,Method UserArrayValueObjectType_CycleComplete_Disable,10039,Method UserArrayValueObjectType_CycleComplete_AddComment,10040,Method UserArrayValueObjectType_CycleComplete_AddComment_InputArguments,10041,Variable UserArrayValueObjectType_CycleComplete_AckedState,10044,Variable UserArrayValueObjectType_CycleComplete_AckedState_Id,10045,Variable UserArrayValueObjectType_CycleComplete_AckedState_Name,10046,Variable UserArrayValueObjectType_CycleComplete_AckedState_Number,10047,Variable UserArrayValueObjectType_CycleComplete_AckedState_EffectiveDisplayName,10048,Variable UserArrayValueObjectType_CycleComplete_AckedState_TransitionTime,10049,Variable UserArrayValueObjectType_CycleComplete_AckedState_TrueState,10050,Variable UserArrayValueObjectType_CycleComplete_AckedState_FalseState,10051,Variable UserArrayValueObjectType_CycleComplete_ConfirmedState,10052,Variable UserArrayValueObjectType_CycleComplete_ConfirmedState_Id,10053,Variable UserArrayValueObjectType_CycleComplete_ConfirmedState_Name,10054,Variable UserArrayValueObjectType_CycleComplete_ConfirmedState_Number,10055,Variable UserArrayValueObjectType_CycleComplete_ConfirmedState_EffectiveDisplayName,10056,Variable UserArrayValueObjectType_CycleComplete_ConfirmedState_TransitionTime,10057,Variable UserArrayValueObjectType_CycleComplete_ConfirmedState_TrueState,10058,Variable UserArrayValueObjectType_CycleComplete_ConfirmedState_FalseState,10059,Variable UserArrayValueObjectType_CycleComplete_Acknowledge,10060,Method UserArrayValueObjectType_CycleComplete_Acknowledge_InputArguments,10061,Variable UserArrayValueObjectType_CycleComplete_Confirm,10062,Method UserArrayValueObjectType_CycleComplete_Confirm_InputArguments,10063,Variable UserArrayValueObjectType_BooleanValue,10064,Variable UserArrayValueObjectType_SByteValue,10065,Variable UserArrayValueObjectType_ByteValue,10066,Variable UserArrayValueObjectType_Int16Value,10067,Variable UserArrayValueObjectType_UInt16Value,10068,Variable UserArrayValueObjectType_Int32Value,10069,Variable UserArrayValueObjectType_UInt32Value,10070,Variable UserArrayValueObjectType_Int64Value,10071,Variable UserArrayValueObjectType_UInt64Value,10072,Variable UserArrayValueObjectType_FloatValue,10073,Variable UserArrayValueObjectType_DoubleValue,10074,Variable UserArrayValueObjectType_StringValue,10075,Variable UserArrayValueObjectType_DateTimeValue,10076,Variable UserArrayValueObjectType_GuidValue,10077,Variable UserArrayValueObjectType_ByteStringValue,10078,Variable UserArrayValueObjectType_XmlElementValue,10079,Variable UserArrayValueObjectType_NodeIdValue,10080,Variable UserArrayValueObjectType_ExpandedNodeIdValue,10081,Variable UserArrayValueObjectType_QualifiedNameValue,10082,Variable UserArrayValueObjectType_LocalizedTextValue,10083,Variable UserArrayValueObjectType_StatusCodeValue,10084,Variable UserArrayValueObjectType_VariantValue,10085,Variable UserArrayValue1MethodType,10086,Method UserArrayValue1MethodType_InputArguments,10087,Variable UserArrayValue1MethodType_OutputArguments,10088,Variable UserArrayValue2MethodType,10089,Method UserArrayValue2MethodType_InputArguments,10090,Variable UserArrayValue2MethodType_OutputArguments,10091,Variable MethodTestType,10092,ObjectType MethodTestType_ScalarMethod1,10093,Method MethodTestType_ScalarMethod1_InputArguments,10094,Variable MethodTestType_ScalarMethod1_OutputArguments,10095,Variable MethodTestType_ScalarMethod2,10096,Method MethodTestType_ScalarMethod2_InputArguments,10097,Variable MethodTestType_ScalarMethod2_OutputArguments,10098,Variable MethodTestType_ScalarMethod3,10099,Method MethodTestType_ScalarMethod3_InputArguments,10100,Variable MethodTestType_ScalarMethod3_OutputArguments,10101,Variable MethodTestType_ArrayMethod1,10102,Method MethodTestType_ArrayMethod1_InputArguments,10103,Variable MethodTestType_ArrayMethod1_OutputArguments,10104,Variable MethodTestType_ArrayMethod2,10105,Method MethodTestType_ArrayMethod2_InputArguments,10106,Variable MethodTestType_ArrayMethod2_OutputArguments,10107,Variable MethodTestType_ArrayMethod3,10108,Method MethodTestType_ArrayMethod3_InputArguments,10109,Variable MethodTestType_ArrayMethod3_OutputArguments,10110,Variable MethodTestType_UserScalarMethod1,10111,Method MethodTestType_UserScalarMethod1_InputArguments,10112,Variable MethodTestType_UserScalarMethod1_OutputArguments,10113,Variable MethodTestType_UserScalarMethod2,10114,Method MethodTestType_UserScalarMethod2_InputArguments,10115,Variable MethodTestType_UserScalarMethod2_OutputArguments,10116,Variable MethodTestType_UserArrayMethod1,10117,Method MethodTestType_UserArrayMethod1_InputArguments,10118,Variable MethodTestType_UserArrayMethod1_OutputArguments,10119,Variable MethodTestType_UserArrayMethod2,10120,Method MethodTestType_UserArrayMethod2_InputArguments,10121,Variable MethodTestType_UserArrayMethod2_OutputArguments,10122,Variable TestSystemConditionType,10123,ObjectType TestSystemConditionType_EventId,10124,Variable TestSystemConditionType_EventType,10125,Variable TestSystemConditionType_SourceNode,10126,Variable TestSystemConditionType_SourceName,10127,Variable TestSystemConditionType_Time,10128,Variable TestSystemConditionType_ReceiveTime,10129,Variable TestSystemConditionType_LocalTime,10130,Variable TestSystemConditionType_Message,10131,Variable TestSystemConditionType_Severity,10132,Variable TestSystemConditionType_BranchId,10133,Variable TestSystemConditionType_Retain,10134,Variable TestSystemConditionType_EnabledState,10135,Variable TestSystemConditionType_EnabledState_Id,10136,Variable TestSystemConditionType_EnabledState_Name,10137,Variable TestSystemConditionType_EnabledState_Number,10138,Variable TestSystemConditionType_EnabledState_EffectiveDisplayName,10139,Variable TestSystemConditionType_EnabledState_TransitionTime,10140,Variable TestSystemConditionType_Quality,10141,Variable TestSystemConditionType_Quality_SourceTimestamp,10142,Variable TestSystemConditionType_LastSeverity,10145,Variable TestSystemConditionType_LastSeverity_SourceTimestamp,10146,Variable TestSystemConditionType_Comment,10147,Variable TestSystemConditionType_Comment_SourceTimestamp,10148,Variable TestSystemConditionType_ClientUserId,10149,Variable TestSystemConditionType_Enable,10150,Method TestSystemConditionType_Disable,10151,Method TestSystemConditionType_AddComment,10152,Method TestSystemConditionType_AddComment_InputArguments,10153,Variable TestSystemConditionType_ConditionRefresh,10154,Method TestSystemConditionType_ConditionRefresh_InputArguments,10155,Variable TestSystemConditionType_MonitoredNodeCount,10156,Variable Data,10157,Object Data_Static,10158,Object Data_Static_Scalar,10159,Object Data_Static_Scalar_SimulationActive,10160,Variable Data_Static_Scalar_GenerateValues,10161,Method Data_Static_Scalar_GenerateValues_InputArguments,10162,Variable Data_Static_Scalar_CycleComplete,10163,Object Data_Static_Scalar_CycleComplete_EventId,10164,Variable Data_Static_Scalar_CycleComplete_EventType,10165,Variable Data_Static_Scalar_CycleComplete_SourceNode,10166,Variable Data_Static_Scalar_CycleComplete_SourceName,10167,Variable Data_Static_Scalar_CycleComplete_Time,10168,Variable Data_Static_Scalar_CycleComplete_ReceiveTime,10169,Variable Data_Static_Scalar_CycleComplete_LocalTime,10170,Variable Data_Static_Scalar_CycleComplete_Message,10171,Variable Data_Static_Scalar_CycleComplete_Severity,10172,Variable Data_Static_Scalar_CycleComplete_BranchId,10173,Variable Data_Static_Scalar_CycleComplete_Retain,10174,Variable Data_Static_Scalar_CycleComplete_EnabledState,10175,Variable Data_Static_Scalar_CycleComplete_EnabledState_Id,10176,Variable Data_Static_Scalar_CycleComplete_EnabledState_Name,10177,Variable Data_Static_Scalar_CycleComplete_EnabledState_Number,10178,Variable Data_Static_Scalar_CycleComplete_EnabledState_EffectiveDisplayName,10179,Variable Data_Static_Scalar_CycleComplete_EnabledState_TransitionTime,10180,Variable Data_Static_Scalar_CycleComplete_Quality,10181,Variable Data_Static_Scalar_CycleComplete_Quality_SourceTimestamp,10182,Variable Data_Static_Scalar_CycleComplete_LastSeverity,10185,Variable Data_Static_Scalar_CycleComplete_LastSeverity_SourceTimestamp,10186,Variable Data_Static_Scalar_CycleComplete_Comment,10187,Variable Data_Static_Scalar_CycleComplete_Comment_SourceTimestamp,10188,Variable Data_Static_Scalar_CycleComplete_ClientUserId,10189,Variable Data_Static_Scalar_CycleComplete_Enable,10190,Method Data_Static_Scalar_CycleComplete_Disable,10191,Method Data_Static_Scalar_CycleComplete_AddComment,10192,Method Data_Static_Scalar_CycleComplete_AddComment_InputArguments,10193,Variable Data_Static_Scalar_CycleComplete_AckedState,10196,Variable Data_Static_Scalar_CycleComplete_AckedState_Id,10197,Variable Data_Static_Scalar_CycleComplete_AckedState_Name,10198,Variable Data_Static_Scalar_CycleComplete_AckedState_Number,10199,Variable Data_Static_Scalar_CycleComplete_AckedState_EffectiveDisplayName,10200,Variable Data_Static_Scalar_CycleComplete_AckedState_TransitionTime,10201,Variable Data_Static_Scalar_CycleComplete_AckedState_TrueState,10202,Variable Data_Static_Scalar_CycleComplete_AckedState_FalseState,10203,Variable Data_Static_Scalar_CycleComplete_ConfirmedState,10204,Variable Data_Static_Scalar_CycleComplete_ConfirmedState_Id,10205,Variable Data_Static_Scalar_CycleComplete_ConfirmedState_Name,10206,Variable Data_Static_Scalar_CycleComplete_ConfirmedState_Number,10207,Variable Data_Static_Scalar_CycleComplete_ConfirmedState_EffectiveDisplayName,10208,Variable Data_Static_Scalar_CycleComplete_ConfirmedState_TransitionTime,10209,Variable Data_Static_Scalar_CycleComplete_ConfirmedState_TrueState,10210,Variable Data_Static_Scalar_CycleComplete_ConfirmedState_FalseState,10211,Variable Data_Static_Scalar_CycleComplete_Acknowledge,10212,Method Data_Static_Scalar_CycleComplete_Acknowledge_InputArguments,10213,Variable Data_Static_Scalar_CycleComplete_Confirm,10214,Method Data_Static_Scalar_CycleComplete_Confirm_InputArguments,10215,Variable Data_Static_Scalar_BooleanValue,10216,Variable Data_Static_Scalar_SByteValue,10217,Variable Data_Static_Scalar_ByteValue,10218,Variable Data_Static_Scalar_Int16Value,10219,Variable Data_Static_Scalar_UInt16Value,10220,Variable Data_Static_Scalar_Int32Value,10221,Variable Data_Static_Scalar_UInt32Value,10222,Variable Data_Static_Scalar_Int64Value,10223,Variable Data_Static_Scalar_UInt64Value,10224,Variable Data_Static_Scalar_FloatValue,10225,Variable Data_Static_Scalar_DoubleValue,10226,Variable Data_Static_Scalar_StringValue,10227,Variable Data_Static_Scalar_DateTimeValue,10228,Variable Data_Static_Scalar_GuidValue,10229,Variable Data_Static_Scalar_ByteStringValue,10230,Variable Data_Static_Scalar_XmlElementValue,10231,Variable Data_Static_Scalar_NodeIdValue,10232,Variable Data_Static_Scalar_ExpandedNodeIdValue,10233,Variable Data_Static_Scalar_QualifiedNameValue,10234,Variable Data_Static_Scalar_LocalizedTextValue,10235,Variable Data_Static_Scalar_StatusCodeValue,10236,Variable Data_Static_Scalar_VariantValue,10237,Variable Data_Static_Scalar_EnumerationValue,10238,Variable Data_Static_Scalar_StructureValue,10239,Variable Data_Static_Scalar_NumberValue,10240,Variable Data_Static_Scalar_IntegerValue,10241,Variable Data_Static_Scalar_UIntegerValue,10242,Variable Data_Static_Array,10243,Object Data_Static_Array_SimulationActive,10244,Variable Data_Static_Array_GenerateValues,10245,Method Data_Static_Array_GenerateValues_InputArguments,10246,Variable Data_Static_Array_CycleComplete,10247,Object Data_Static_Array_CycleComplete_EventId,10248,Variable Data_Static_Array_CycleComplete_EventType,10249,Variable Data_Static_Array_CycleComplete_SourceNode,10250,Variable Data_Static_Array_CycleComplete_SourceName,10251,Variable Data_Static_Array_CycleComplete_Time,10252,Variable Data_Static_Array_CycleComplete_ReceiveTime,10253,Variable Data_Static_Array_CycleComplete_LocalTime,10254,Variable Data_Static_Array_CycleComplete_Message,10255,Variable Data_Static_Array_CycleComplete_Severity,10256,Variable Data_Static_Array_CycleComplete_BranchId,10257,Variable Data_Static_Array_CycleComplete_Retain,10258,Variable Data_Static_Array_CycleComplete_EnabledState,10259,Variable Data_Static_Array_CycleComplete_EnabledState_Id,10260,Variable Data_Static_Array_CycleComplete_EnabledState_Name,10261,Variable Data_Static_Array_CycleComplete_EnabledState_Number,10262,Variable Data_Static_Array_CycleComplete_EnabledState_EffectiveDisplayName,10263,Variable Data_Static_Array_CycleComplete_EnabledState_TransitionTime,10264,Variable Data_Static_Array_CycleComplete_Quality,10265,Variable Data_Static_Array_CycleComplete_Quality_SourceTimestamp,10266,Variable Data_Static_Array_CycleComplete_LastSeverity,10269,Variable Data_Static_Array_CycleComplete_LastSeverity_SourceTimestamp,10270,Variable Data_Static_Array_CycleComplete_Comment,10271,Variable Data_Static_Array_CycleComplete_Comment_SourceTimestamp,10272,Variable Data_Static_Array_CycleComplete_ClientUserId,10273,Variable Data_Static_Array_CycleComplete_Enable,10274,Method Data_Static_Array_CycleComplete_Disable,10275,Method Data_Static_Array_CycleComplete_AddComment,10276,Method Data_Static_Array_CycleComplete_AddComment_InputArguments,10277,Variable Data_Static_Array_CycleComplete_AckedState,10280,Variable Data_Static_Array_CycleComplete_AckedState_Id,10281,Variable Data_Static_Array_CycleComplete_AckedState_Name,10282,Variable Data_Static_Array_CycleComplete_AckedState_Number,10283,Variable Data_Static_Array_CycleComplete_AckedState_EffectiveDisplayName,10284,Variable Data_Static_Array_CycleComplete_AckedState_TransitionTime,10285,Variable Data_Static_Array_CycleComplete_AckedState_TrueState,10286,Variable Data_Static_Array_CycleComplete_AckedState_FalseState,10287,Variable Data_Static_Array_CycleComplete_ConfirmedState,10288,Variable Data_Static_Array_CycleComplete_ConfirmedState_Id,10289,Variable Data_Static_Array_CycleComplete_ConfirmedState_Name,10290,Variable Data_Static_Array_CycleComplete_ConfirmedState_Number,10291,Variable Data_Static_Array_CycleComplete_ConfirmedState_EffectiveDisplayName,10292,Variable Data_Static_Array_CycleComplete_ConfirmedState_TransitionTime,10293,Variable Data_Static_Array_CycleComplete_ConfirmedState_TrueState,10294,Variable Data_Static_Array_CycleComplete_ConfirmedState_FalseState,10295,Variable Data_Static_Array_CycleComplete_Acknowledge,10296,Method Data_Static_Array_CycleComplete_Acknowledge_InputArguments,10297,Variable Data_Static_Array_CycleComplete_Confirm,10298,Method Data_Static_Array_CycleComplete_Confirm_InputArguments,10299,Variable Data_Static_Array_BooleanValue,10300,Variable Data_Static_Array_SByteValue,10301,Variable Data_Static_Array_ByteValue,10302,Variable Data_Static_Array_Int16Value,10303,Variable Data_Static_Array_UInt16Value,10304,Variable Data_Static_Array_Int32Value,10305,Variable Data_Static_Array_UInt32Value,10306,Variable Data_Static_Array_Int64Value,10307,Variable Data_Static_Array_UInt64Value,10308,Variable Data_Static_Array_FloatValue,10309,Variable Data_Static_Array_DoubleValue,10310,Variable Data_Static_Array_StringValue,10311,Variable Data_Static_Array_DateTimeValue,10312,Variable Data_Static_Array_GuidValue,10313,Variable Data_Static_Array_ByteStringValue,10314,Variable Data_Static_Array_XmlElementValue,10315,Variable Data_Static_Array_NodeIdValue,10316,Variable Data_Static_Array_ExpandedNodeIdValue,10317,Variable Data_Static_Array_QualifiedNameValue,10318,Variable Data_Static_Array_LocalizedTextValue,10319,Variable Data_Static_Array_StatusCodeValue,10320,Variable Data_Static_Array_VariantValue,10321,Variable Data_Static_Array_EnumerationValue,10322,Variable Data_Static_Array_StructureValue,10323,Variable Data_Static_Array_NumberValue,10324,Variable Data_Static_Array_IntegerValue,10325,Variable Data_Static_Array_UIntegerValue,10326,Variable Data_Static_UserScalar,10327,Object Data_Static_UserScalar_SimulationActive,10328,Variable Data_Static_UserScalar_GenerateValues,10329,Method Data_Static_UserScalar_GenerateValues_InputArguments,10330,Variable Data_Static_UserScalar_CycleComplete,10331,Object Data_Static_UserScalar_CycleComplete_EventId,10332,Variable Data_Static_UserScalar_CycleComplete_EventType,10333,Variable Data_Static_UserScalar_CycleComplete_SourceNode,10334,Variable Data_Static_UserScalar_CycleComplete_SourceName,10335,Variable Data_Static_UserScalar_CycleComplete_Time,10336,Variable Data_Static_UserScalar_CycleComplete_ReceiveTime,10337,Variable Data_Static_UserScalar_CycleComplete_LocalTime,10338,Variable Data_Static_UserScalar_CycleComplete_Message,10339,Variable Data_Static_UserScalar_CycleComplete_Severity,10340,Variable Data_Static_UserScalar_CycleComplete_BranchId,10341,Variable Data_Static_UserScalar_CycleComplete_Retain,10342,Variable Data_Static_UserScalar_CycleComplete_EnabledState,10343,Variable Data_Static_UserScalar_CycleComplete_EnabledState_Id,10344,Variable Data_Static_UserScalar_CycleComplete_EnabledState_Name,10345,Variable Data_Static_UserScalar_CycleComplete_EnabledState_Number,10346,Variable Data_Static_UserScalar_CycleComplete_EnabledState_EffectiveDisplayName,10347,Variable Data_Static_UserScalar_CycleComplete_EnabledState_TransitionTime,10348,Variable Data_Static_UserScalar_CycleComplete_Quality,10349,Variable Data_Static_UserScalar_CycleComplete_Quality_SourceTimestamp,10350,Variable Data_Static_UserScalar_CycleComplete_LastSeverity,10353,Variable Data_Static_UserScalar_CycleComplete_LastSeverity_SourceTimestamp,10354,Variable Data_Static_UserScalar_CycleComplete_Comment,10355,Variable Data_Static_UserScalar_CycleComplete_Comment_SourceTimestamp,10356,Variable Data_Static_UserScalar_CycleComplete_ClientUserId,10357,Variable Data_Static_UserScalar_CycleComplete_Enable,10358,Method Data_Static_UserScalar_CycleComplete_Disable,10359,Method Data_Static_UserScalar_CycleComplete_AddComment,10360,Method Data_Static_UserScalar_CycleComplete_AddComment_InputArguments,10361,Variable Data_Static_UserScalar_CycleComplete_AckedState,10364,Variable Data_Static_UserScalar_CycleComplete_AckedState_Id,10365,Variable Data_Static_UserScalar_CycleComplete_AckedState_Name,10366,Variable Data_Static_UserScalar_CycleComplete_AckedState_Number,10367,Variable Data_Static_UserScalar_CycleComplete_AckedState_EffectiveDisplayName,10368,Variable Data_Static_UserScalar_CycleComplete_AckedState_TransitionTime,10369,Variable Data_Static_UserScalar_CycleComplete_AckedState_TrueState,10370,Variable Data_Static_UserScalar_CycleComplete_AckedState_FalseState,10371,Variable Data_Static_UserScalar_CycleComplete_ConfirmedState,10372,Variable Data_Static_UserScalar_CycleComplete_ConfirmedState_Id,10373,Variable Data_Static_UserScalar_CycleComplete_ConfirmedState_Name,10374,Variable Data_Static_UserScalar_CycleComplete_ConfirmedState_Number,10375,Variable Data_Static_UserScalar_CycleComplete_ConfirmedState_EffectiveDisplayName,10376,Variable Data_Static_UserScalar_CycleComplete_ConfirmedState_TransitionTime,10377,Variable Data_Static_UserScalar_CycleComplete_ConfirmedState_TrueState,10378,Variable Data_Static_UserScalar_CycleComplete_ConfirmedState_FalseState,10379,Variable Data_Static_UserScalar_CycleComplete_Acknowledge,10380,Method Data_Static_UserScalar_CycleComplete_Acknowledge_InputArguments,10381,Variable Data_Static_UserScalar_CycleComplete_Confirm,10382,Method Data_Static_UserScalar_CycleComplete_Confirm_InputArguments,10383,Variable Data_Static_UserScalar_BooleanValue,10384,Variable Data_Static_UserScalar_SByteValue,10385,Variable Data_Static_UserScalar_ByteValue,10386,Variable Data_Static_UserScalar_Int16Value,10387,Variable Data_Static_UserScalar_UInt16Value,10388,Variable Data_Static_UserScalar_Int32Value,10389,Variable Data_Static_UserScalar_UInt32Value,10390,Variable Data_Static_UserScalar_Int64Value,10391,Variable Data_Static_UserScalar_UInt64Value,10392,Variable Data_Static_UserScalar_FloatValue,10393,Variable Data_Static_UserScalar_DoubleValue,10394,Variable Data_Static_UserScalar_StringValue,10395,Variable Data_Static_UserScalar_DateTimeValue,10396,Variable Data_Static_UserScalar_GuidValue,10397,Variable Data_Static_UserScalar_ByteStringValue,10398,Variable Data_Static_UserScalar_XmlElementValue,10399,Variable Data_Static_UserScalar_NodeIdValue,10400,Variable Data_Static_UserScalar_ExpandedNodeIdValue,10401,Variable Data_Static_UserScalar_QualifiedNameValue,10402,Variable Data_Static_UserScalar_LocalizedTextValue,10403,Variable Data_Static_UserScalar_StatusCodeValue,10404,Variable Data_Static_UserScalar_VariantValue,10405,Variable Data_Static_UserArray,10406,Object Data_Static_UserArray_SimulationActive,10407,Variable Data_Static_UserArray_GenerateValues,10408,Method Data_Static_UserArray_GenerateValues_InputArguments,10409,Variable Data_Static_UserArray_CycleComplete,10410,Object Data_Static_UserArray_CycleComplete_EventId,10411,Variable Data_Static_UserArray_CycleComplete_EventType,10412,Variable Data_Static_UserArray_CycleComplete_SourceNode,10413,Variable Data_Static_UserArray_CycleComplete_SourceName,10414,Variable Data_Static_UserArray_CycleComplete_Time,10415,Variable Data_Static_UserArray_CycleComplete_ReceiveTime,10416,Variable Data_Static_UserArray_CycleComplete_LocalTime,10417,Variable Data_Static_UserArray_CycleComplete_Message,10418,Variable Data_Static_UserArray_CycleComplete_Severity,10419,Variable Data_Static_UserArray_CycleComplete_BranchId,10420,Variable Data_Static_UserArray_CycleComplete_Retain,10421,Variable Data_Static_UserArray_CycleComplete_EnabledState,10422,Variable Data_Static_UserArray_CycleComplete_EnabledState_Id,10423,Variable Data_Static_UserArray_CycleComplete_EnabledState_Name,10424,Variable Data_Static_UserArray_CycleComplete_EnabledState_Number,10425,Variable Data_Static_UserArray_CycleComplete_EnabledState_EffectiveDisplayName,10426,Variable Data_Static_UserArray_CycleComplete_EnabledState_TransitionTime,10427,Variable Data_Static_UserArray_CycleComplete_Quality,10428,Variable Data_Static_UserArray_CycleComplete_Quality_SourceTimestamp,10429,Variable Data_Static_UserArray_CycleComplete_LastSeverity,10432,Variable Data_Static_UserArray_CycleComplete_LastSeverity_SourceTimestamp,10433,Variable Data_Static_UserArray_CycleComplete_Comment,10434,Variable Data_Static_UserArray_CycleComplete_Comment_SourceTimestamp,10435,Variable Data_Static_UserArray_CycleComplete_ClientUserId,10436,Variable Data_Static_UserArray_CycleComplete_Enable,10437,Method Data_Static_UserArray_CycleComplete_Disable,10438,Method Data_Static_UserArray_CycleComplete_AddComment,10439,Method Data_Static_UserArray_CycleComplete_AddComment_InputArguments,10440,Variable Data_Static_UserArray_CycleComplete_AckedState,10443,Variable Data_Static_UserArray_CycleComplete_AckedState_Id,10444,Variable Data_Static_UserArray_CycleComplete_AckedState_Name,10445,Variable Data_Static_UserArray_CycleComplete_AckedState_Number,10446,Variable Data_Static_UserArray_CycleComplete_AckedState_EffectiveDisplayName,10447,Variable Data_Static_UserArray_CycleComplete_AckedState_TransitionTime,10448,Variable Data_Static_UserArray_CycleComplete_AckedState_TrueState,10449,Variable Data_Static_UserArray_CycleComplete_AckedState_FalseState,10450,Variable Data_Static_UserArray_CycleComplete_ConfirmedState,10451,Variable Data_Static_UserArray_CycleComplete_ConfirmedState_Id,10452,Variable Data_Static_UserArray_CycleComplete_ConfirmedState_Name,10453,Variable Data_Static_UserArray_CycleComplete_ConfirmedState_Number,10454,Variable Data_Static_UserArray_CycleComplete_ConfirmedState_EffectiveDisplayName,10455,Variable Data_Static_UserArray_CycleComplete_ConfirmedState_TransitionTime,10456,Variable Data_Static_UserArray_CycleComplete_ConfirmedState_TrueState,10457,Variable Data_Static_UserArray_CycleComplete_ConfirmedState_FalseState,10458,Variable Data_Static_UserArray_CycleComplete_Acknowledge,10459,Method Data_Static_UserArray_CycleComplete_Acknowledge_InputArguments,10460,Variable Data_Static_UserArray_CycleComplete_Confirm,10461,Method Data_Static_UserArray_CycleComplete_Confirm_InputArguments,10462,Variable Data_Static_UserArray_BooleanValue,10463,Variable Data_Static_UserArray_SByteValue,10464,Variable Data_Static_UserArray_ByteValue,10465,Variable Data_Static_UserArray_Int16Value,10466,Variable Data_Static_UserArray_UInt16Value,10467,Variable Data_Static_UserArray_Int32Value,10468,Variable Data_Static_UserArray_UInt32Value,10469,Variable Data_Static_UserArray_Int64Value,10470,Variable Data_Static_UserArray_UInt64Value,10471,Variable Data_Static_UserArray_FloatValue,10472,Variable Data_Static_UserArray_DoubleValue,10473,Variable Data_Static_UserArray_StringValue,10474,Variable Data_Static_UserArray_DateTimeValue,10475,Variable Data_Static_UserArray_GuidValue,10476,Variable Data_Static_UserArray_ByteStringValue,10477,Variable Data_Static_UserArray_XmlElementValue,10478,Variable Data_Static_UserArray_NodeIdValue,10479,Variable Data_Static_UserArray_ExpandedNodeIdValue,10480,Variable Data_Static_UserArray_QualifiedNameValue,10481,Variable Data_Static_UserArray_LocalizedTextValue,10482,Variable Data_Static_UserArray_StatusCodeValue,10483,Variable Data_Static_UserArray_VariantValue,10484,Variable Data_Static_AnalogScalar,10485,Object Data_Static_AnalogScalar_SimulationActive,10486,Variable Data_Static_AnalogScalar_GenerateValues,10487,Method Data_Static_AnalogScalar_GenerateValues_InputArguments,10488,Variable Data_Static_AnalogScalar_CycleComplete,10489,Object Data_Static_AnalogScalar_CycleComplete_EventId,10490,Variable Data_Static_AnalogScalar_CycleComplete_EventType,10491,Variable Data_Static_AnalogScalar_CycleComplete_SourceNode,10492,Variable Data_Static_AnalogScalar_CycleComplete_SourceName,10493,Variable Data_Static_AnalogScalar_CycleComplete_Time,10494,Variable Data_Static_AnalogScalar_CycleComplete_ReceiveTime,10495,Variable Data_Static_AnalogScalar_CycleComplete_LocalTime,10496,Variable Data_Static_AnalogScalar_CycleComplete_Message,10497,Variable Data_Static_AnalogScalar_CycleComplete_Severity,10498,Variable Data_Static_AnalogScalar_CycleComplete_BranchId,10499,Variable Data_Static_AnalogScalar_CycleComplete_Retain,10500,Variable Data_Static_AnalogScalar_CycleComplete_EnabledState,10501,Variable Data_Static_AnalogScalar_CycleComplete_EnabledState_Id,10502,Variable Data_Static_AnalogScalar_CycleComplete_EnabledState_Name,10503,Variable Data_Static_AnalogScalar_CycleComplete_EnabledState_Number,10504,Variable Data_Static_AnalogScalar_CycleComplete_EnabledState_EffectiveDisplayName,10505,Variable Data_Static_AnalogScalar_CycleComplete_EnabledState_TransitionTime,10506,Variable Data_Static_AnalogScalar_CycleComplete_Quality,10507,Variable Data_Static_AnalogScalar_CycleComplete_Quality_SourceTimestamp,10508,Variable Data_Static_AnalogScalar_CycleComplete_LastSeverity,10511,Variable Data_Static_AnalogScalar_CycleComplete_LastSeverity_SourceTimestamp,10512,Variable Data_Static_AnalogScalar_CycleComplete_Comment,10513,Variable Data_Static_AnalogScalar_CycleComplete_Comment_SourceTimestamp,10514,Variable Data_Static_AnalogScalar_CycleComplete_ClientUserId,10515,Variable Data_Static_AnalogScalar_CycleComplete_Enable,10516,Method Data_Static_AnalogScalar_CycleComplete_Disable,10517,Method Data_Static_AnalogScalar_CycleComplete_AddComment,10518,Method Data_Static_AnalogScalar_CycleComplete_AddComment_InputArguments,10519,Variable Data_Static_AnalogScalar_CycleComplete_AckedState,10522,Variable Data_Static_AnalogScalar_CycleComplete_AckedState_Id,10523,Variable Data_Static_AnalogScalar_CycleComplete_AckedState_Name,10524,Variable Data_Static_AnalogScalar_CycleComplete_AckedState_Number,10525,Variable Data_Static_AnalogScalar_CycleComplete_AckedState_EffectiveDisplayName,10526,Variable Data_Static_AnalogScalar_CycleComplete_AckedState_TransitionTime,10527,Variable Data_Static_AnalogScalar_CycleComplete_AckedState_TrueState,10528,Variable Data_Static_AnalogScalar_CycleComplete_AckedState_FalseState,10529,Variable Data_Static_AnalogScalar_CycleComplete_ConfirmedState,10530,Variable Data_Static_AnalogScalar_CycleComplete_ConfirmedState_Id,10531,Variable Data_Static_AnalogScalar_CycleComplete_ConfirmedState_Name,10532,Variable Data_Static_AnalogScalar_CycleComplete_ConfirmedState_Number,10533,Variable Data_Static_AnalogScalar_CycleComplete_ConfirmedState_EffectiveDisplayName,10534,Variable Data_Static_AnalogScalar_CycleComplete_ConfirmedState_TransitionTime,10535,Variable Data_Static_AnalogScalar_CycleComplete_ConfirmedState_TrueState,10536,Variable Data_Static_AnalogScalar_CycleComplete_ConfirmedState_FalseState,10537,Variable Data_Static_AnalogScalar_CycleComplete_Acknowledge,10538,Method Data_Static_AnalogScalar_CycleComplete_Acknowledge_InputArguments,10539,Variable Data_Static_AnalogScalar_CycleComplete_Confirm,10540,Method Data_Static_AnalogScalar_CycleComplete_Confirm_InputArguments,10541,Variable Data_Static_AnalogScalar_SByteValue,10542,Variable Data_Static_AnalogScalar_SByteValue_Definition,10543,Variable Data_Static_AnalogScalar_SByteValue_ValuePrecision,10544,Variable Data_Static_AnalogScalar_SByteValue_EURange,10545,Variable Data_Static_AnalogScalar_SByteValue_InstrumentRange,10546,Variable Data_Static_AnalogScalar_SByteValue_EngineeringUnits,10547,Variable Data_Static_AnalogScalar_ByteValue,10548,Variable Data_Static_AnalogScalar_ByteValue_Definition,10549,Variable Data_Static_AnalogScalar_ByteValue_ValuePrecision,10550,Variable Data_Static_AnalogScalar_ByteValue_EURange,10551,Variable Data_Static_AnalogScalar_ByteValue_InstrumentRange,10552,Variable Data_Static_AnalogScalar_ByteValue_EngineeringUnits,10553,Variable Data_Static_AnalogScalar_Int16Value,10554,Variable Data_Static_AnalogScalar_Int16Value_Definition,10555,Variable Data_Static_AnalogScalar_Int16Value_ValuePrecision,10556,Variable Data_Static_AnalogScalar_Int16Value_EURange,10557,Variable Data_Static_AnalogScalar_Int16Value_InstrumentRange,10558,Variable Data_Static_AnalogScalar_Int16Value_EngineeringUnits,10559,Variable Data_Static_AnalogScalar_UInt16Value,10560,Variable Data_Static_AnalogScalar_UInt16Value_Definition,10561,Variable Data_Static_AnalogScalar_UInt16Value_ValuePrecision,10562,Variable Data_Static_AnalogScalar_UInt16Value_EURange,10563,Variable Data_Static_AnalogScalar_UInt16Value_InstrumentRange,10564,Variable Data_Static_AnalogScalar_UInt16Value_EngineeringUnits,10565,Variable Data_Static_AnalogScalar_Int32Value,10566,Variable Data_Static_AnalogScalar_Int32Value_Definition,10567,Variable Data_Static_AnalogScalar_Int32Value_ValuePrecision,10568,Variable Data_Static_AnalogScalar_Int32Value_EURange,10569,Variable Data_Static_AnalogScalar_Int32Value_InstrumentRange,10570,Variable Data_Static_AnalogScalar_Int32Value_EngineeringUnits,10571,Variable Data_Static_AnalogScalar_UInt32Value,10572,Variable Data_Static_AnalogScalar_UInt32Value_Definition,10573,Variable Data_Static_AnalogScalar_UInt32Value_ValuePrecision,10574,Variable Data_Static_AnalogScalar_UInt32Value_EURange,10575,Variable Data_Static_AnalogScalar_UInt32Value_InstrumentRange,10576,Variable Data_Static_AnalogScalar_UInt32Value_EngineeringUnits,10577,Variable Data_Static_AnalogScalar_Int64Value,10578,Variable Data_Static_AnalogScalar_Int64Value_Definition,10579,Variable Data_Static_AnalogScalar_Int64Value_ValuePrecision,10580,Variable Data_Static_AnalogScalar_Int64Value_EURange,10581,Variable Data_Static_AnalogScalar_Int64Value_InstrumentRange,10582,Variable Data_Static_AnalogScalar_Int64Value_EngineeringUnits,10583,Variable Data_Static_AnalogScalar_UInt64Value,10584,Variable Data_Static_AnalogScalar_UInt64Value_Definition,10585,Variable Data_Static_AnalogScalar_UInt64Value_ValuePrecision,10586,Variable Data_Static_AnalogScalar_UInt64Value_EURange,10587,Variable Data_Static_AnalogScalar_UInt64Value_InstrumentRange,10588,Variable Data_Static_AnalogScalar_UInt64Value_EngineeringUnits,10589,Variable Data_Static_AnalogScalar_FloatValue,10590,Variable Data_Static_AnalogScalar_FloatValue_Definition,10591,Variable Data_Static_AnalogScalar_FloatValue_ValuePrecision,10592,Variable Data_Static_AnalogScalar_FloatValue_EURange,10593,Variable Data_Static_AnalogScalar_FloatValue_InstrumentRange,10594,Variable Data_Static_AnalogScalar_FloatValue_EngineeringUnits,10595,Variable Data_Static_AnalogScalar_DoubleValue,10596,Variable Data_Static_AnalogScalar_DoubleValue_Definition,10597,Variable Data_Static_AnalogScalar_DoubleValue_ValuePrecision,10598,Variable Data_Static_AnalogScalar_DoubleValue_EURange,10599,Variable Data_Static_AnalogScalar_DoubleValue_InstrumentRange,10600,Variable Data_Static_AnalogScalar_DoubleValue_EngineeringUnits,10601,Variable Data_Static_AnalogScalar_NumberValue,10602,Variable Data_Static_AnalogScalar_NumberValue_Definition,10603,Variable Data_Static_AnalogScalar_NumberValue_ValuePrecision,10604,Variable Data_Static_AnalogScalar_NumberValue_EURange,10605,Variable Data_Static_AnalogScalar_NumberValue_InstrumentRange,10606,Variable Data_Static_AnalogScalar_NumberValue_EngineeringUnits,10607,Variable Data_Static_AnalogScalar_IntegerValue,10608,Variable Data_Static_AnalogScalar_IntegerValue_Definition,10609,Variable Data_Static_AnalogScalar_IntegerValue_ValuePrecision,10610,Variable Data_Static_AnalogScalar_IntegerValue_EURange,10611,Variable Data_Static_AnalogScalar_IntegerValue_InstrumentRange,10612,Variable Data_Static_AnalogScalar_IntegerValue_EngineeringUnits,10613,Variable Data_Static_AnalogScalar_UIntegerValue,10614,Variable Data_Static_AnalogScalar_UIntegerValue_Definition,10615,Variable Data_Static_AnalogScalar_UIntegerValue_ValuePrecision,10616,Variable Data_Static_AnalogScalar_UIntegerValue_EURange,10617,Variable Data_Static_AnalogScalar_UIntegerValue_InstrumentRange,10618,Variable Data_Static_AnalogScalar_UIntegerValue_EngineeringUnits,10619,Variable Data_Static_AnalogArray,10620,Object Data_Static_AnalogArray_SimulationActive,10621,Variable Data_Static_AnalogArray_GenerateValues,10622,Method Data_Static_AnalogArray_GenerateValues_InputArguments,10623,Variable Data_Static_AnalogArray_CycleComplete,10624,Object Data_Static_AnalogArray_CycleComplete_EventId,10625,Variable Data_Static_AnalogArray_CycleComplete_EventType,10626,Variable Data_Static_AnalogArray_CycleComplete_SourceNode,10627,Variable Data_Static_AnalogArray_CycleComplete_SourceName,10628,Variable Data_Static_AnalogArray_CycleComplete_Time,10629,Variable Data_Static_AnalogArray_CycleComplete_ReceiveTime,10630,Variable Data_Static_AnalogArray_CycleComplete_LocalTime,10631,Variable Data_Static_AnalogArray_CycleComplete_Message,10632,Variable Data_Static_AnalogArray_CycleComplete_Severity,10633,Variable Data_Static_AnalogArray_CycleComplete_BranchId,10634,Variable Data_Static_AnalogArray_CycleComplete_Retain,10635,Variable Data_Static_AnalogArray_CycleComplete_EnabledState,10636,Variable Data_Static_AnalogArray_CycleComplete_EnabledState_Id,10637,Variable Data_Static_AnalogArray_CycleComplete_EnabledState_Name,10638,Variable Data_Static_AnalogArray_CycleComplete_EnabledState_Number,10639,Variable Data_Static_AnalogArray_CycleComplete_EnabledState_EffectiveDisplayName,10640,Variable Data_Static_AnalogArray_CycleComplete_EnabledState_TransitionTime,10641,Variable Data_Static_AnalogArray_CycleComplete_Quality,10642,Variable Data_Static_AnalogArray_CycleComplete_Quality_SourceTimestamp,10643,Variable Data_Static_AnalogArray_CycleComplete_LastSeverity,10646,Variable Data_Static_AnalogArray_CycleComplete_LastSeverity_SourceTimestamp,10647,Variable Data_Static_AnalogArray_CycleComplete_Comment,10648,Variable Data_Static_AnalogArray_CycleComplete_Comment_SourceTimestamp,10649,Variable Data_Static_AnalogArray_CycleComplete_ClientUserId,10650,Variable Data_Static_AnalogArray_CycleComplete_Enable,10651,Method Data_Static_AnalogArray_CycleComplete_Disable,10652,Method Data_Static_AnalogArray_CycleComplete_AddComment,10653,Method Data_Static_AnalogArray_CycleComplete_AddComment_InputArguments,10654,Variable Data_Static_AnalogArray_CycleComplete_AckedState,10657,Variable Data_Static_AnalogArray_CycleComplete_AckedState_Id,10658,Variable Data_Static_AnalogArray_CycleComplete_AckedState_Name,10659,Variable Data_Static_AnalogArray_CycleComplete_AckedState_Number,10660,Variable Data_Static_AnalogArray_CycleComplete_AckedState_EffectiveDisplayName,10661,Variable Data_Static_AnalogArray_CycleComplete_AckedState_TransitionTime,10662,Variable Data_Static_AnalogArray_CycleComplete_AckedState_TrueState,10663,Variable Data_Static_AnalogArray_CycleComplete_AckedState_FalseState,10664,Variable Data_Static_AnalogArray_CycleComplete_ConfirmedState,10665,Variable Data_Static_AnalogArray_CycleComplete_ConfirmedState_Id,10666,Variable Data_Static_AnalogArray_CycleComplete_ConfirmedState_Name,10667,Variable Data_Static_AnalogArray_CycleComplete_ConfirmedState_Number,10668,Variable Data_Static_AnalogArray_CycleComplete_ConfirmedState_EffectiveDisplayName,10669,Variable Data_Static_AnalogArray_CycleComplete_ConfirmedState_TransitionTime,10670,Variable Data_Static_AnalogArray_CycleComplete_ConfirmedState_TrueState,10671,Variable Data_Static_AnalogArray_CycleComplete_ConfirmedState_FalseState,10672,Variable Data_Static_AnalogArray_CycleComplete_Acknowledge,10673,Method Data_Static_AnalogArray_CycleComplete_Acknowledge_InputArguments,10674,Variable Data_Static_AnalogArray_CycleComplete_Confirm,10675,Method Data_Static_AnalogArray_CycleComplete_Confirm_InputArguments,10676,Variable Data_Static_AnalogArray_SByteValue,10677,Variable Data_Static_AnalogArray_SByteValue_Definition,10678,Variable Data_Static_AnalogArray_SByteValue_ValuePrecision,10679,Variable Data_Static_AnalogArray_SByteValue_EURange,10680,Variable Data_Static_AnalogArray_SByteValue_InstrumentRange,10681,Variable Data_Static_AnalogArray_SByteValue_EngineeringUnits,10682,Variable Data_Static_AnalogArray_ByteValue,10683,Variable Data_Static_AnalogArray_ByteValue_Definition,10684,Variable Data_Static_AnalogArray_ByteValue_ValuePrecision,10685,Variable Data_Static_AnalogArray_ByteValue_EURange,10686,Variable Data_Static_AnalogArray_ByteValue_InstrumentRange,10687,Variable Data_Static_AnalogArray_ByteValue_EngineeringUnits,10688,Variable Data_Static_AnalogArray_Int16Value,10689,Variable Data_Static_AnalogArray_Int16Value_Definition,10690,Variable Data_Static_AnalogArray_Int16Value_ValuePrecision,10691,Variable Data_Static_AnalogArray_Int16Value_EURange,10692,Variable Data_Static_AnalogArray_Int16Value_InstrumentRange,10693,Variable Data_Static_AnalogArray_Int16Value_EngineeringUnits,10694,Variable Data_Static_AnalogArray_UInt16Value,10695,Variable Data_Static_AnalogArray_UInt16Value_Definition,10696,Variable Data_Static_AnalogArray_UInt16Value_ValuePrecision,10697,Variable Data_Static_AnalogArray_UInt16Value_EURange,10698,Variable Data_Static_AnalogArray_UInt16Value_InstrumentRange,10699,Variable Data_Static_AnalogArray_UInt16Value_EngineeringUnits,10700,Variable Data_Static_AnalogArray_Int32Value,10701,Variable Data_Static_AnalogArray_Int32Value_Definition,10702,Variable Data_Static_AnalogArray_Int32Value_ValuePrecision,10703,Variable Data_Static_AnalogArray_Int32Value_EURange,10704,Variable Data_Static_AnalogArray_Int32Value_InstrumentRange,10705,Variable Data_Static_AnalogArray_Int32Value_EngineeringUnits,10706,Variable Data_Static_AnalogArray_UInt32Value,10707,Variable Data_Static_AnalogArray_UInt32Value_Definition,10708,Variable Data_Static_AnalogArray_UInt32Value_ValuePrecision,10709,Variable Data_Static_AnalogArray_UInt32Value_EURange,10710,Variable Data_Static_AnalogArray_UInt32Value_InstrumentRange,10711,Variable Data_Static_AnalogArray_UInt32Value_EngineeringUnits,10712,Variable Data_Static_AnalogArray_Int64Value,10713,Variable Data_Static_AnalogArray_Int64Value_Definition,10714,Variable Data_Static_AnalogArray_Int64Value_ValuePrecision,10715,Variable Data_Static_AnalogArray_Int64Value_EURange,10716,Variable Data_Static_AnalogArray_Int64Value_InstrumentRange,10717,Variable Data_Static_AnalogArray_Int64Value_EngineeringUnits,10718,Variable Data_Static_AnalogArray_UInt64Value,10719,Variable Data_Static_AnalogArray_UInt64Value_Definition,10720,Variable Data_Static_AnalogArray_UInt64Value_ValuePrecision,10721,Variable Data_Static_AnalogArray_UInt64Value_EURange,10722,Variable Data_Static_AnalogArray_UInt64Value_InstrumentRange,10723,Variable Data_Static_AnalogArray_UInt64Value_EngineeringUnits,10724,Variable Data_Static_AnalogArray_FloatValue,10725,Variable Data_Static_AnalogArray_FloatValue_Definition,10726,Variable Data_Static_AnalogArray_FloatValue_ValuePrecision,10727,Variable Data_Static_AnalogArray_FloatValue_EURange,10728,Variable Data_Static_AnalogArray_FloatValue_InstrumentRange,10729,Variable Data_Static_AnalogArray_FloatValue_EngineeringUnits,10730,Variable Data_Static_AnalogArray_DoubleValue,10731,Variable Data_Static_AnalogArray_DoubleValue_Definition,10732,Variable Data_Static_AnalogArray_DoubleValue_ValuePrecision,10733,Variable Data_Static_AnalogArray_DoubleValue_EURange,10734,Variable Data_Static_AnalogArray_DoubleValue_InstrumentRange,10735,Variable Data_Static_AnalogArray_DoubleValue_EngineeringUnits,10736,Variable Data_Static_AnalogArray_NumberValue,10737,Variable Data_Static_AnalogArray_NumberValue_Definition,10738,Variable Data_Static_AnalogArray_NumberValue_ValuePrecision,10739,Variable Data_Static_AnalogArray_NumberValue_EURange,10740,Variable Data_Static_AnalogArray_NumberValue_InstrumentRange,10741,Variable Data_Static_AnalogArray_NumberValue_EngineeringUnits,10742,Variable Data_Static_AnalogArray_IntegerValue,10743,Variable Data_Static_AnalogArray_IntegerValue_Definition,10744,Variable Data_Static_AnalogArray_IntegerValue_ValuePrecision,10745,Variable Data_Static_AnalogArray_IntegerValue_EURange,10746,Variable Data_Static_AnalogArray_IntegerValue_InstrumentRange,10747,Variable Data_Static_AnalogArray_IntegerValue_EngineeringUnits,10748,Variable Data_Static_AnalogArray_UIntegerValue,10749,Variable Data_Static_AnalogArray_UIntegerValue_Definition,10750,Variable Data_Static_AnalogArray_UIntegerValue_ValuePrecision,10751,Variable Data_Static_AnalogArray_UIntegerValue_EURange,10752,Variable Data_Static_AnalogArray_UIntegerValue_InstrumentRange,10753,Variable Data_Static_AnalogArray_UIntegerValue_EngineeringUnits,10754,Variable Data_Static_MethodTest,10755,Object Data_Static_MethodTest_ScalarMethod1,10756,Method Data_Static_MethodTest_ScalarMethod1_InputArguments,10757,Variable Data_Static_MethodTest_ScalarMethod1_OutputArguments,10758,Variable Data_Static_MethodTest_ScalarMethod2,10759,Method Data_Static_MethodTest_ScalarMethod2_InputArguments,10760,Variable Data_Static_MethodTest_ScalarMethod2_OutputArguments,10761,Variable Data_Static_MethodTest_ScalarMethod3,10762,Method Data_Static_MethodTest_ScalarMethod3_InputArguments,10763,Variable Data_Static_MethodTest_ScalarMethod3_OutputArguments,10764,Variable Data_Static_MethodTest_ArrayMethod1,10765,Method Data_Static_MethodTest_ArrayMethod1_InputArguments,10766,Variable Data_Static_MethodTest_ArrayMethod1_OutputArguments,10767,Variable Data_Static_MethodTest_ArrayMethod2,10768,Method Data_Static_MethodTest_ArrayMethod2_InputArguments,10769,Variable Data_Static_MethodTest_ArrayMethod2_OutputArguments,10770,Variable Data_Static_MethodTest_ArrayMethod3,10771,Method Data_Static_MethodTest_ArrayMethod3_InputArguments,10772,Variable Data_Static_MethodTest_ArrayMethod3_OutputArguments,10773,Variable Data_Static_MethodTest_UserScalarMethod1,10774,Method Data_Static_MethodTest_UserScalarMethod1_InputArguments,10775,Variable Data_Static_MethodTest_UserScalarMethod1_OutputArguments,10776,Variable Data_Static_MethodTest_UserScalarMethod2,10777,Method Data_Static_MethodTest_UserScalarMethod2_InputArguments,10778,Variable Data_Static_MethodTest_UserScalarMethod2_OutputArguments,10779,Variable Data_Static_MethodTest_UserArrayMethod1,10780,Method Data_Static_MethodTest_UserArrayMethod1_InputArguments,10781,Variable Data_Static_MethodTest_UserArrayMethod1_OutputArguments,10782,Variable Data_Static_MethodTest_UserArrayMethod2,10783,Method Data_Static_MethodTest_UserArrayMethod2_InputArguments,10784,Variable Data_Static_MethodTest_UserArrayMethod2_OutputArguments,10785,Variable Data_Dynamic,10786,Object Data_Dynamic_Scalar,10787,Object Data_Dynamic_Scalar_SimulationActive,10788,Variable Data_Dynamic_Scalar_GenerateValues,10789,Method Data_Dynamic_Scalar_GenerateValues_InputArguments,10790,Variable Data_Dynamic_Scalar_CycleComplete,10791,Object Data_Dynamic_Scalar_CycleComplete_EventId,10792,Variable Data_Dynamic_Scalar_CycleComplete_EventType,10793,Variable Data_Dynamic_Scalar_CycleComplete_SourceNode,10794,Variable Data_Dynamic_Scalar_CycleComplete_SourceName,10795,Variable Data_Dynamic_Scalar_CycleComplete_Time,10796,Variable Data_Dynamic_Scalar_CycleComplete_ReceiveTime,10797,Variable Data_Dynamic_Scalar_CycleComplete_LocalTime,10798,Variable Data_Dynamic_Scalar_CycleComplete_Message,10799,Variable Data_Dynamic_Scalar_CycleComplete_Severity,10800,Variable Data_Dynamic_Scalar_CycleComplete_BranchId,10801,Variable Data_Dynamic_Scalar_CycleComplete_Retain,10802,Variable Data_Dynamic_Scalar_CycleComplete_EnabledState,10803,Variable Data_Dynamic_Scalar_CycleComplete_EnabledState_Id,10804,Variable Data_Dynamic_Scalar_CycleComplete_EnabledState_Name,10805,Variable Data_Dynamic_Scalar_CycleComplete_EnabledState_Number,10806,Variable Data_Dynamic_Scalar_CycleComplete_EnabledState_EffectiveDisplayName,10807,Variable Data_Dynamic_Scalar_CycleComplete_EnabledState_TransitionTime,10808,Variable Data_Dynamic_Scalar_CycleComplete_Quality,10809,Variable Data_Dynamic_Scalar_CycleComplete_Quality_SourceTimestamp,10810,Variable Data_Dynamic_Scalar_CycleComplete_LastSeverity,10813,Variable Data_Dynamic_Scalar_CycleComplete_LastSeverity_SourceTimestamp,10814,Variable Data_Dynamic_Scalar_CycleComplete_Comment,10815,Variable Data_Dynamic_Scalar_CycleComplete_Comment_SourceTimestamp,10816,Variable Data_Dynamic_Scalar_CycleComplete_ClientUserId,10817,Variable Data_Dynamic_Scalar_CycleComplete_Enable,10818,Method Data_Dynamic_Scalar_CycleComplete_Disable,10819,Method Data_Dynamic_Scalar_CycleComplete_AddComment,10820,Method Data_Dynamic_Scalar_CycleComplete_AddComment_InputArguments,10821,Variable Data_Dynamic_Scalar_CycleComplete_AckedState,10824,Variable Data_Dynamic_Scalar_CycleComplete_AckedState_Id,10825,Variable Data_Dynamic_Scalar_CycleComplete_AckedState_Name,10826,Variable Data_Dynamic_Scalar_CycleComplete_AckedState_Number,10827,Variable Data_Dynamic_Scalar_CycleComplete_AckedState_EffectiveDisplayName,10828,Variable Data_Dynamic_Scalar_CycleComplete_AckedState_TransitionTime,10829,Variable Data_Dynamic_Scalar_CycleComplete_AckedState_TrueState,10830,Variable Data_Dynamic_Scalar_CycleComplete_AckedState_FalseState,10831,Variable Data_Dynamic_Scalar_CycleComplete_ConfirmedState,10832,Variable Data_Dynamic_Scalar_CycleComplete_ConfirmedState_Id,10833,Variable Data_Dynamic_Scalar_CycleComplete_ConfirmedState_Name,10834,Variable Data_Dynamic_Scalar_CycleComplete_ConfirmedState_Number,10835,Variable Data_Dynamic_Scalar_CycleComplete_ConfirmedState_EffectiveDisplayName,10836,Variable Data_Dynamic_Scalar_CycleComplete_ConfirmedState_TransitionTime,10837,Variable Data_Dynamic_Scalar_CycleComplete_ConfirmedState_TrueState,10838,Variable Data_Dynamic_Scalar_CycleComplete_ConfirmedState_FalseState,10839,Variable Data_Dynamic_Scalar_CycleComplete_Acknowledge,10840,Method Data_Dynamic_Scalar_CycleComplete_Acknowledge_InputArguments,10841,Variable Data_Dynamic_Scalar_CycleComplete_Confirm,10842,Method Data_Dynamic_Scalar_CycleComplete_Confirm_InputArguments,10843,Variable Data_Dynamic_Scalar_BooleanValue,10844,Variable Data_Dynamic_Scalar_SByteValue,10845,Variable Data_Dynamic_Scalar_ByteValue,10846,Variable Data_Dynamic_Scalar_Int16Value,10847,Variable Data_Dynamic_Scalar_UInt16Value,10848,Variable Data_Dynamic_Scalar_Int32Value,10849,Variable Data_Dynamic_Scalar_UInt32Value,10850,Variable Data_Dynamic_Scalar_Int64Value,10851,Variable Data_Dynamic_Scalar_UInt64Value,10852,Variable Data_Dynamic_Scalar_FloatValue,10853,Variable Data_Dynamic_Scalar_DoubleValue,10854,Variable Data_Dynamic_Scalar_StringValue,10855,Variable Data_Dynamic_Scalar_DateTimeValue,10856,Variable Data_Dynamic_Scalar_GuidValue,10857,Variable Data_Dynamic_Scalar_ByteStringValue,10858,Variable Data_Dynamic_Scalar_XmlElementValue,10859,Variable Data_Dynamic_Scalar_NodeIdValue,10860,Variable Data_Dynamic_Scalar_ExpandedNodeIdValue,10861,Variable Data_Dynamic_Scalar_QualifiedNameValue,10862,Variable Data_Dynamic_Scalar_LocalizedTextValue,10863,Variable Data_Dynamic_Scalar_StatusCodeValue,10864,Variable Data_Dynamic_Scalar_VariantValue,10865,Variable Data_Dynamic_Scalar_EnumerationValue,10866,Variable Data_Dynamic_Scalar_StructureValue,10867,Variable Data_Dynamic_Scalar_NumberValue,10868,Variable Data_Dynamic_Scalar_IntegerValue,10869,Variable Data_Dynamic_Scalar_UIntegerValue,10870,Variable Data_Dynamic_Array,10871,Object Data_Dynamic_Array_SimulationActive,10872,Variable Data_Dynamic_Array_GenerateValues,10873,Method Data_Dynamic_Array_GenerateValues_InputArguments,10874,Variable Data_Dynamic_Array_CycleComplete,10875,Object Data_Dynamic_Array_CycleComplete_EventId,10876,Variable Data_Dynamic_Array_CycleComplete_EventType,10877,Variable Data_Dynamic_Array_CycleComplete_SourceNode,10878,Variable Data_Dynamic_Array_CycleComplete_SourceName,10879,Variable Data_Dynamic_Array_CycleComplete_Time,10880,Variable Data_Dynamic_Array_CycleComplete_ReceiveTime,10881,Variable Data_Dynamic_Array_CycleComplete_LocalTime,10882,Variable Data_Dynamic_Array_CycleComplete_Message,10883,Variable Data_Dynamic_Array_CycleComplete_Severity,10884,Variable Data_Dynamic_Array_CycleComplete_BranchId,10885,Variable Data_Dynamic_Array_CycleComplete_Retain,10886,Variable Data_Dynamic_Array_CycleComplete_EnabledState,10887,Variable Data_Dynamic_Array_CycleComplete_EnabledState_Id,10888,Variable Data_Dynamic_Array_CycleComplete_EnabledState_Name,10889,Variable Data_Dynamic_Array_CycleComplete_EnabledState_Number,10890,Variable Data_Dynamic_Array_CycleComplete_EnabledState_EffectiveDisplayName,10891,Variable Data_Dynamic_Array_CycleComplete_EnabledState_TransitionTime,10892,Variable Data_Dynamic_Array_CycleComplete_Quality,10893,Variable Data_Dynamic_Array_CycleComplete_Quality_SourceTimestamp,10894,Variable Data_Dynamic_Array_CycleComplete_LastSeverity,10897,Variable Data_Dynamic_Array_CycleComplete_LastSeverity_SourceTimestamp,10898,Variable Data_Dynamic_Array_CycleComplete_Comment,10899,Variable Data_Dynamic_Array_CycleComplete_Comment_SourceTimestamp,10900,Variable Data_Dynamic_Array_CycleComplete_ClientUserId,10901,Variable Data_Dynamic_Array_CycleComplete_Enable,10902,Method Data_Dynamic_Array_CycleComplete_Disable,10903,Method Data_Dynamic_Array_CycleComplete_AddComment,10904,Method Data_Dynamic_Array_CycleComplete_AddComment_InputArguments,10905,Variable Data_Dynamic_Array_CycleComplete_AckedState,10908,Variable Data_Dynamic_Array_CycleComplete_AckedState_Id,10909,Variable Data_Dynamic_Array_CycleComplete_AckedState_Name,10910,Variable Data_Dynamic_Array_CycleComplete_AckedState_Number,10911,Variable Data_Dynamic_Array_CycleComplete_AckedState_EffectiveDisplayName,10912,Variable Data_Dynamic_Array_CycleComplete_AckedState_TransitionTime,10913,Variable Data_Dynamic_Array_CycleComplete_AckedState_TrueState,10914,Variable Data_Dynamic_Array_CycleComplete_AckedState_FalseState,10915,Variable Data_Dynamic_Array_CycleComplete_ConfirmedState,10916,Variable Data_Dynamic_Array_CycleComplete_ConfirmedState_Id,10917,Variable Data_Dynamic_Array_CycleComplete_ConfirmedState_Name,10918,Variable Data_Dynamic_Array_CycleComplete_ConfirmedState_Number,10919,Variable Data_Dynamic_Array_CycleComplete_ConfirmedState_EffectiveDisplayName,10920,Variable Data_Dynamic_Array_CycleComplete_ConfirmedState_TransitionTime,10921,Variable Data_Dynamic_Array_CycleComplete_ConfirmedState_TrueState,10922,Variable Data_Dynamic_Array_CycleComplete_ConfirmedState_FalseState,10923,Variable Data_Dynamic_Array_CycleComplete_Acknowledge,10924,Method Data_Dynamic_Array_CycleComplete_Acknowledge_InputArguments,10925,Variable Data_Dynamic_Array_CycleComplete_Confirm,10926,Method Data_Dynamic_Array_CycleComplete_Confirm_InputArguments,10927,Variable Data_Dynamic_Array_BooleanValue,10928,Variable Data_Dynamic_Array_SByteValue,10929,Variable Data_Dynamic_Array_ByteValue,10930,Variable Data_Dynamic_Array_Int16Value,10931,Variable Data_Dynamic_Array_UInt16Value,10932,Variable Data_Dynamic_Array_Int32Value,10933,Variable Data_Dynamic_Array_UInt32Value,10934,Variable Data_Dynamic_Array_Int64Value,10935,Variable Data_Dynamic_Array_UInt64Value,10936,Variable Data_Dynamic_Array_FloatValue,10937,Variable Data_Dynamic_Array_DoubleValue,10938,Variable Data_Dynamic_Array_StringValue,10939,Variable Data_Dynamic_Array_DateTimeValue,10940,Variable Data_Dynamic_Array_GuidValue,10941,Variable Data_Dynamic_Array_ByteStringValue,10942,Variable Data_Dynamic_Array_XmlElementValue,10943,Variable Data_Dynamic_Array_NodeIdValue,10944,Variable Data_Dynamic_Array_ExpandedNodeIdValue,10945,Variable Data_Dynamic_Array_QualifiedNameValue,10946,Variable Data_Dynamic_Array_LocalizedTextValue,10947,Variable Data_Dynamic_Array_StatusCodeValue,10948,Variable Data_Dynamic_Array_VariantValue,10949,Variable Data_Dynamic_Array_EnumerationValue,10950,Variable Data_Dynamic_Array_StructureValue,10951,Variable Data_Dynamic_Array_NumberValue,10952,Variable Data_Dynamic_Array_IntegerValue,10953,Variable Data_Dynamic_Array_UIntegerValue,10954,Variable Data_Dynamic_UserScalar,10955,Object Data_Dynamic_UserScalar_SimulationActive,10956,Variable Data_Dynamic_UserScalar_GenerateValues,10957,Method Data_Dynamic_UserScalar_GenerateValues_InputArguments,10958,Variable Data_Dynamic_UserScalar_CycleComplete,10959,Object Data_Dynamic_UserScalar_CycleComplete_EventId,10960,Variable Data_Dynamic_UserScalar_CycleComplete_EventType,10961,Variable Data_Dynamic_UserScalar_CycleComplete_SourceNode,10962,Variable Data_Dynamic_UserScalar_CycleComplete_SourceName,10963,Variable Data_Dynamic_UserScalar_CycleComplete_Time,10964,Variable Data_Dynamic_UserScalar_CycleComplete_ReceiveTime,10965,Variable Data_Dynamic_UserScalar_CycleComplete_LocalTime,10966,Variable Data_Dynamic_UserScalar_CycleComplete_Message,10967,Variable Data_Dynamic_UserScalar_CycleComplete_Severity,10968,Variable Data_Dynamic_UserScalar_CycleComplete_BranchId,10969,Variable Data_Dynamic_UserScalar_CycleComplete_Retain,10970,Variable Data_Dynamic_UserScalar_CycleComplete_EnabledState,10971,Variable Data_Dynamic_UserScalar_CycleComplete_EnabledState_Id,10972,Variable Data_Dynamic_UserScalar_CycleComplete_EnabledState_Name,10973,Variable Data_Dynamic_UserScalar_CycleComplete_EnabledState_Number,10974,Variable Data_Dynamic_UserScalar_CycleComplete_EnabledState_EffectiveDisplayName,10975,Variable Data_Dynamic_UserScalar_CycleComplete_EnabledState_TransitionTime,10976,Variable Data_Dynamic_UserScalar_CycleComplete_Quality,10977,Variable Data_Dynamic_UserScalar_CycleComplete_Quality_SourceTimestamp,10978,Variable Data_Dynamic_UserScalar_CycleComplete_LastSeverity,10981,Variable Data_Dynamic_UserScalar_CycleComplete_LastSeverity_SourceTimestamp,10982,Variable Data_Dynamic_UserScalar_CycleComplete_Comment,10983,Variable Data_Dynamic_UserScalar_CycleComplete_Comment_SourceTimestamp,10984,Variable Data_Dynamic_UserScalar_CycleComplete_ClientUserId,10985,Variable Data_Dynamic_UserScalar_CycleComplete_Enable,10986,Method Data_Dynamic_UserScalar_CycleComplete_Disable,10987,Method Data_Dynamic_UserScalar_CycleComplete_AddComment,10988,Method Data_Dynamic_UserScalar_CycleComplete_AddComment_InputArguments,10989,Variable Data_Dynamic_UserScalar_CycleComplete_AckedState,10992,Variable Data_Dynamic_UserScalar_CycleComplete_AckedState_Id,10993,Variable Data_Dynamic_UserScalar_CycleComplete_AckedState_Name,10994,Variable Data_Dynamic_UserScalar_CycleComplete_AckedState_Number,10995,Variable Data_Dynamic_UserScalar_CycleComplete_AckedState_EffectiveDisplayName,10996,Variable Data_Dynamic_UserScalar_CycleComplete_AckedState_TransitionTime,10997,Variable Data_Dynamic_UserScalar_CycleComplete_AckedState_TrueState,10998,Variable Data_Dynamic_UserScalar_CycleComplete_AckedState_FalseState,10999,Variable Data_Dynamic_UserScalar_CycleComplete_ConfirmedState,11000,Variable Data_Dynamic_UserScalar_CycleComplete_ConfirmedState_Id,11001,Variable Data_Dynamic_UserScalar_CycleComplete_ConfirmedState_Name,11002,Variable Data_Dynamic_UserScalar_CycleComplete_ConfirmedState_Number,11003,Variable Data_Dynamic_UserScalar_CycleComplete_ConfirmedState_EffectiveDisplayName,11004,Variable Data_Dynamic_UserScalar_CycleComplete_ConfirmedState_TransitionTime,11005,Variable Data_Dynamic_UserScalar_CycleComplete_ConfirmedState_TrueState,11006,Variable Data_Dynamic_UserScalar_CycleComplete_ConfirmedState_FalseState,11007,Variable Data_Dynamic_UserScalar_CycleComplete_Acknowledge,11008,Method Data_Dynamic_UserScalar_CycleComplete_Acknowledge_InputArguments,11009,Variable Data_Dynamic_UserScalar_CycleComplete_Confirm,11010,Method Data_Dynamic_UserScalar_CycleComplete_Confirm_InputArguments,11011,Variable Data_Dynamic_UserScalar_BooleanValue,11012,Variable Data_Dynamic_UserScalar_SByteValue,11013,Variable Data_Dynamic_UserScalar_ByteValue,11014,Variable Data_Dynamic_UserScalar_Int16Value,11015,Variable Data_Dynamic_UserScalar_UInt16Value,11016,Variable Data_Dynamic_UserScalar_Int32Value,11017,Variable Data_Dynamic_UserScalar_UInt32Value,11018,Variable Data_Dynamic_UserScalar_Int64Value,11019,Variable Data_Dynamic_UserScalar_UInt64Value,11020,Variable Data_Dynamic_UserScalar_FloatValue,11021,Variable Data_Dynamic_UserScalar_DoubleValue,11022,Variable Data_Dynamic_UserScalar_StringValue,11023,Variable Data_Dynamic_UserScalar_DateTimeValue,11024,Variable Data_Dynamic_UserScalar_GuidValue,11025,Variable Data_Dynamic_UserScalar_ByteStringValue,11026,Variable Data_Dynamic_UserScalar_XmlElementValue,11027,Variable Data_Dynamic_UserScalar_NodeIdValue,11028,Variable Data_Dynamic_UserScalar_ExpandedNodeIdValue,11029,Variable Data_Dynamic_UserScalar_QualifiedNameValue,11030,Variable Data_Dynamic_UserScalar_LocalizedTextValue,11031,Variable Data_Dynamic_UserScalar_StatusCodeValue,11032,Variable Data_Dynamic_UserScalar_VariantValue,11033,Variable Data_Dynamic_UserArray,11034,Object Data_Dynamic_UserArray_SimulationActive,11035,Variable Data_Dynamic_UserArray_GenerateValues,11036,Method Data_Dynamic_UserArray_GenerateValues_InputArguments,11037,Variable Data_Dynamic_UserArray_CycleComplete,11038,Object Data_Dynamic_UserArray_CycleComplete_EventId,11039,Variable Data_Dynamic_UserArray_CycleComplete_EventType,11040,Variable Data_Dynamic_UserArray_CycleComplete_SourceNode,11041,Variable Data_Dynamic_UserArray_CycleComplete_SourceName,11042,Variable Data_Dynamic_UserArray_CycleComplete_Time,11043,Variable Data_Dynamic_UserArray_CycleComplete_ReceiveTime,11044,Variable Data_Dynamic_UserArray_CycleComplete_LocalTime,11045,Variable Data_Dynamic_UserArray_CycleComplete_Message,11046,Variable Data_Dynamic_UserArray_CycleComplete_Severity,11047,Variable Data_Dynamic_UserArray_CycleComplete_BranchId,11048,Variable Data_Dynamic_UserArray_CycleComplete_Retain,11049,Variable Data_Dynamic_UserArray_CycleComplete_EnabledState,11050,Variable Data_Dynamic_UserArray_CycleComplete_EnabledState_Id,11051,Variable Data_Dynamic_UserArray_CycleComplete_EnabledState_Name,11052,Variable Data_Dynamic_UserArray_CycleComplete_EnabledState_Number,11053,Variable Data_Dynamic_UserArray_CycleComplete_EnabledState_EffectiveDisplayName,11054,Variable Data_Dynamic_UserArray_CycleComplete_EnabledState_TransitionTime,11055,Variable Data_Dynamic_UserArray_CycleComplete_Quality,11056,Variable Data_Dynamic_UserArray_CycleComplete_Quality_SourceTimestamp,11057,Variable Data_Dynamic_UserArray_CycleComplete_LastSeverity,11060,Variable Data_Dynamic_UserArray_CycleComplete_LastSeverity_SourceTimestamp,11061,Variable Data_Dynamic_UserArray_CycleComplete_Comment,11062,Variable Data_Dynamic_UserArray_CycleComplete_Comment_SourceTimestamp,11063,Variable Data_Dynamic_UserArray_CycleComplete_ClientUserId,11064,Variable Data_Dynamic_UserArray_CycleComplete_Enable,11065,Method Data_Dynamic_UserArray_CycleComplete_Disable,11066,Method Data_Dynamic_UserArray_CycleComplete_AddComment,11067,Method Data_Dynamic_UserArray_CycleComplete_AddComment_InputArguments,11068,Variable Data_Dynamic_UserArray_CycleComplete_AckedState,11071,Variable Data_Dynamic_UserArray_CycleComplete_AckedState_Id,11072,Variable Data_Dynamic_UserArray_CycleComplete_AckedState_Name,11073,Variable Data_Dynamic_UserArray_CycleComplete_AckedState_Number,11074,Variable Data_Dynamic_UserArray_CycleComplete_AckedState_EffectiveDisplayName,11075,Variable Data_Dynamic_UserArray_CycleComplete_AckedState_TransitionTime,11076,Variable Data_Dynamic_UserArray_CycleComplete_AckedState_TrueState,11077,Variable Data_Dynamic_UserArray_CycleComplete_AckedState_FalseState,11078,Variable Data_Dynamic_UserArray_CycleComplete_ConfirmedState,11079,Variable Data_Dynamic_UserArray_CycleComplete_ConfirmedState_Id,11080,Variable Data_Dynamic_UserArray_CycleComplete_ConfirmedState_Name,11081,Variable Data_Dynamic_UserArray_CycleComplete_ConfirmedState_Number,11082,Variable Data_Dynamic_UserArray_CycleComplete_ConfirmedState_EffectiveDisplayName,11083,Variable Data_Dynamic_UserArray_CycleComplete_ConfirmedState_TransitionTime,11084,Variable Data_Dynamic_UserArray_CycleComplete_ConfirmedState_TrueState,11085,Variable Data_Dynamic_UserArray_CycleComplete_ConfirmedState_FalseState,11086,Variable Data_Dynamic_UserArray_CycleComplete_Acknowledge,11087,Method Data_Dynamic_UserArray_CycleComplete_Acknowledge_InputArguments,11088,Variable Data_Dynamic_UserArray_CycleComplete_Confirm,11089,Method Data_Dynamic_UserArray_CycleComplete_Confirm_InputArguments,11090,Variable Data_Dynamic_UserArray_BooleanValue,11091,Variable Data_Dynamic_UserArray_SByteValue,11092,Variable Data_Dynamic_UserArray_ByteValue,11093,Variable Data_Dynamic_UserArray_Int16Value,11094,Variable Data_Dynamic_UserArray_UInt16Value,11095,Variable Data_Dynamic_UserArray_Int32Value,11096,Variable Data_Dynamic_UserArray_UInt32Value,11097,Variable Data_Dynamic_UserArray_Int64Value,11098,Variable Data_Dynamic_UserArray_UInt64Value,11099,Variable Data_Dynamic_UserArray_FloatValue,11100,Variable Data_Dynamic_UserArray_DoubleValue,11101,Variable Data_Dynamic_UserArray_StringValue,11102,Variable Data_Dynamic_UserArray_DateTimeValue,11103,Variable Data_Dynamic_UserArray_GuidValue,11104,Variable Data_Dynamic_UserArray_ByteStringValue,11105,Variable Data_Dynamic_UserArray_XmlElementValue,11106,Variable Data_Dynamic_UserArray_NodeIdValue,11107,Variable Data_Dynamic_UserArray_ExpandedNodeIdValue,11108,Variable Data_Dynamic_UserArray_QualifiedNameValue,11109,Variable Data_Dynamic_UserArray_LocalizedTextValue,11110,Variable Data_Dynamic_UserArray_StatusCodeValue,11111,Variable Data_Dynamic_UserArray_VariantValue,11112,Variable Data_Dynamic_AnalogScalar,11113,Object Data_Dynamic_AnalogScalar_SimulationActive,11114,Variable Data_Dynamic_AnalogScalar_GenerateValues,11115,Method Data_Dynamic_AnalogScalar_GenerateValues_InputArguments,11116,Variable Data_Dynamic_AnalogScalar_CycleComplete,11117,Object Data_Dynamic_AnalogScalar_CycleComplete_EventId,11118,Variable Data_Dynamic_AnalogScalar_CycleComplete_EventType,11119,Variable Data_Dynamic_AnalogScalar_CycleComplete_SourceNode,11120,Variable Data_Dynamic_AnalogScalar_CycleComplete_SourceName,11121,Variable Data_Dynamic_AnalogScalar_CycleComplete_Time,11122,Variable Data_Dynamic_AnalogScalar_CycleComplete_ReceiveTime,11123,Variable Data_Dynamic_AnalogScalar_CycleComplete_LocalTime,11124,Variable Data_Dynamic_AnalogScalar_CycleComplete_Message,11125,Variable Data_Dynamic_AnalogScalar_CycleComplete_Severity,11126,Variable Data_Dynamic_AnalogScalar_CycleComplete_BranchId,11127,Variable Data_Dynamic_AnalogScalar_CycleComplete_Retain,11128,Variable Data_Dynamic_AnalogScalar_CycleComplete_EnabledState,11129,Variable Data_Dynamic_AnalogScalar_CycleComplete_EnabledState_Id,11130,Variable Data_Dynamic_AnalogScalar_CycleComplete_EnabledState_Name,11131,Variable Data_Dynamic_AnalogScalar_CycleComplete_EnabledState_Number,11132,Variable Data_Dynamic_AnalogScalar_CycleComplete_EnabledState_EffectiveDisplayName,11133,Variable Data_Dynamic_AnalogScalar_CycleComplete_EnabledState_TransitionTime,11134,Variable Data_Dynamic_AnalogScalar_CycleComplete_Quality,11135,Variable Data_Dynamic_AnalogScalar_CycleComplete_Quality_SourceTimestamp,11136,Variable Data_Dynamic_AnalogScalar_CycleComplete_LastSeverity,11139,Variable Data_Dynamic_AnalogScalar_CycleComplete_LastSeverity_SourceTimestamp,11140,Variable Data_Dynamic_AnalogScalar_CycleComplete_Comment,11141,Variable Data_Dynamic_AnalogScalar_CycleComplete_Comment_SourceTimestamp,11142,Variable Data_Dynamic_AnalogScalar_CycleComplete_ClientUserId,11143,Variable Data_Dynamic_AnalogScalar_CycleComplete_Enable,11144,Method Data_Dynamic_AnalogScalar_CycleComplete_Disable,11145,Method Data_Dynamic_AnalogScalar_CycleComplete_AddComment,11146,Method Data_Dynamic_AnalogScalar_CycleComplete_AddComment_InputArguments,11147,Variable Data_Dynamic_AnalogScalar_CycleComplete_AckedState,11150,Variable Data_Dynamic_AnalogScalar_CycleComplete_AckedState_Id,11151,Variable Data_Dynamic_AnalogScalar_CycleComplete_AckedState_Name,11152,Variable Data_Dynamic_AnalogScalar_CycleComplete_AckedState_Number,11153,Variable Data_Dynamic_AnalogScalar_CycleComplete_AckedState_EffectiveDisplayName,11154,Variable Data_Dynamic_AnalogScalar_CycleComplete_AckedState_TransitionTime,11155,Variable Data_Dynamic_AnalogScalar_CycleComplete_AckedState_TrueState,11156,Variable Data_Dynamic_AnalogScalar_CycleComplete_AckedState_FalseState,11157,Variable Data_Dynamic_AnalogScalar_CycleComplete_ConfirmedState,11158,Variable Data_Dynamic_AnalogScalar_CycleComplete_ConfirmedState_Id,11159,Variable Data_Dynamic_AnalogScalar_CycleComplete_ConfirmedState_Name,11160,Variable Data_Dynamic_AnalogScalar_CycleComplete_ConfirmedState_Number,11161,Variable Data_Dynamic_AnalogScalar_CycleComplete_ConfirmedState_EffectiveDisplayName,11162,Variable Data_Dynamic_AnalogScalar_CycleComplete_ConfirmedState_TransitionTime,11163,Variable Data_Dynamic_AnalogScalar_CycleComplete_ConfirmedState_TrueState,11164,Variable Data_Dynamic_AnalogScalar_CycleComplete_ConfirmedState_FalseState,11165,Variable Data_Dynamic_AnalogScalar_CycleComplete_Acknowledge,11166,Method Data_Dynamic_AnalogScalar_CycleComplete_Acknowledge_InputArguments,11167,Variable Data_Dynamic_AnalogScalar_CycleComplete_Confirm,11168,Method Data_Dynamic_AnalogScalar_CycleComplete_Confirm_InputArguments,11169,Variable Data_Dynamic_AnalogScalar_SByteValue,11170,Variable Data_Dynamic_AnalogScalar_SByteValue_Definition,11171,Variable Data_Dynamic_AnalogScalar_SByteValue_ValuePrecision,11172,Variable Data_Dynamic_AnalogScalar_SByteValue_EURange,11173,Variable Data_Dynamic_AnalogScalar_SByteValue_InstrumentRange,11174,Variable Data_Dynamic_AnalogScalar_SByteValue_EngineeringUnits,11175,Variable Data_Dynamic_AnalogScalar_ByteValue,11176,Variable Data_Dynamic_AnalogScalar_ByteValue_Definition,11177,Variable Data_Dynamic_AnalogScalar_ByteValue_ValuePrecision,11178,Variable Data_Dynamic_AnalogScalar_ByteValue_EURange,11179,Variable Data_Dynamic_AnalogScalar_ByteValue_InstrumentRange,11180,Variable Data_Dynamic_AnalogScalar_ByteValue_EngineeringUnits,11181,Variable Data_Dynamic_AnalogScalar_Int16Value,11182,Variable Data_Dynamic_AnalogScalar_Int16Value_Definition,11183,Variable Data_Dynamic_AnalogScalar_Int16Value_ValuePrecision,11184,Variable Data_Dynamic_AnalogScalar_Int16Value_EURange,11185,Variable Data_Dynamic_AnalogScalar_Int16Value_InstrumentRange,11186,Variable Data_Dynamic_AnalogScalar_Int16Value_EngineeringUnits,11187,Variable Data_Dynamic_AnalogScalar_UInt16Value,11188,Variable Data_Dynamic_AnalogScalar_UInt16Value_Definition,11189,Variable Data_Dynamic_AnalogScalar_UInt16Value_ValuePrecision,11190,Variable Data_Dynamic_AnalogScalar_UInt16Value_EURange,11191,Variable Data_Dynamic_AnalogScalar_UInt16Value_InstrumentRange,11192,Variable Data_Dynamic_AnalogScalar_UInt16Value_EngineeringUnits,11193,Variable Data_Dynamic_AnalogScalar_Int32Value,11194,Variable Data_Dynamic_AnalogScalar_Int32Value_Definition,11195,Variable Data_Dynamic_AnalogScalar_Int32Value_ValuePrecision,11196,Variable Data_Dynamic_AnalogScalar_Int32Value_EURange,11197,Variable Data_Dynamic_AnalogScalar_Int32Value_InstrumentRange,11198,Variable Data_Dynamic_AnalogScalar_Int32Value_EngineeringUnits,11199,Variable Data_Dynamic_AnalogScalar_UInt32Value,11200,Variable Data_Dynamic_AnalogScalar_UInt32Value_Definition,11201,Variable Data_Dynamic_AnalogScalar_UInt32Value_ValuePrecision,11202,Variable Data_Dynamic_AnalogScalar_UInt32Value_EURange,11203,Variable Data_Dynamic_AnalogScalar_UInt32Value_InstrumentRange,11204,Variable Data_Dynamic_AnalogScalar_UInt32Value_EngineeringUnits,11205,Variable Data_Dynamic_AnalogScalar_Int64Value,11206,Variable Data_Dynamic_AnalogScalar_Int64Value_Definition,11207,Variable Data_Dynamic_AnalogScalar_Int64Value_ValuePrecision,11208,Variable Data_Dynamic_AnalogScalar_Int64Value_EURange,11209,Variable Data_Dynamic_AnalogScalar_Int64Value_InstrumentRange,11210,Variable Data_Dynamic_AnalogScalar_Int64Value_EngineeringUnits,11211,Variable Data_Dynamic_AnalogScalar_UInt64Value,11212,Variable Data_Dynamic_AnalogScalar_UInt64Value_Definition,11213,Variable Data_Dynamic_AnalogScalar_UInt64Value_ValuePrecision,11214,Variable Data_Dynamic_AnalogScalar_UInt64Value_EURange,11215,Variable Data_Dynamic_AnalogScalar_UInt64Value_InstrumentRange,11216,Variable Data_Dynamic_AnalogScalar_UInt64Value_EngineeringUnits,11217,Variable Data_Dynamic_AnalogScalar_FloatValue,11218,Variable Data_Dynamic_AnalogScalar_FloatValue_Definition,11219,Variable Data_Dynamic_AnalogScalar_FloatValue_ValuePrecision,11220,Variable Data_Dynamic_AnalogScalar_FloatValue_EURange,11221,Variable Data_Dynamic_AnalogScalar_FloatValue_InstrumentRange,11222,Variable Data_Dynamic_AnalogScalar_FloatValue_EngineeringUnits,11223,Variable Data_Dynamic_AnalogScalar_DoubleValue,11224,Variable Data_Dynamic_AnalogScalar_DoubleValue_Definition,11225,Variable Data_Dynamic_AnalogScalar_DoubleValue_ValuePrecision,11226,Variable Data_Dynamic_AnalogScalar_DoubleValue_EURange,11227,Variable Data_Dynamic_AnalogScalar_DoubleValue_InstrumentRange,11228,Variable Data_Dynamic_AnalogScalar_DoubleValue_EngineeringUnits,11229,Variable Data_Dynamic_AnalogScalar_NumberValue,11230,Variable Data_Dynamic_AnalogScalar_NumberValue_Definition,11231,Variable Data_Dynamic_AnalogScalar_NumberValue_ValuePrecision,11232,Variable Data_Dynamic_AnalogScalar_NumberValue_EURange,11233,Variable Data_Dynamic_AnalogScalar_NumberValue_InstrumentRange,11234,Variable Data_Dynamic_AnalogScalar_NumberValue_EngineeringUnits,11235,Variable Data_Dynamic_AnalogScalar_IntegerValue,11236,Variable Data_Dynamic_AnalogScalar_IntegerValue_Definition,11237,Variable Data_Dynamic_AnalogScalar_IntegerValue_ValuePrecision,11238,Variable Data_Dynamic_AnalogScalar_IntegerValue_EURange,11239,Variable Data_Dynamic_AnalogScalar_IntegerValue_InstrumentRange,11240,Variable Data_Dynamic_AnalogScalar_IntegerValue_EngineeringUnits,11241,Variable Data_Dynamic_AnalogScalar_UIntegerValue,11242,Variable Data_Dynamic_AnalogScalar_UIntegerValue_Definition,11243,Variable Data_Dynamic_AnalogScalar_UIntegerValue_ValuePrecision,11244,Variable Data_Dynamic_AnalogScalar_UIntegerValue_EURange,11245,Variable Data_Dynamic_AnalogScalar_UIntegerValue_InstrumentRange,11246,Variable Data_Dynamic_AnalogScalar_UIntegerValue_EngineeringUnits,11247,Variable Data_Dynamic_AnalogArray,11248,Object Data_Dynamic_AnalogArray_SimulationActive,11249,Variable Data_Dynamic_AnalogArray_GenerateValues,11250,Method Data_Dynamic_AnalogArray_GenerateValues_InputArguments,11251,Variable Data_Dynamic_AnalogArray_CycleComplete,11252,Object Data_Dynamic_AnalogArray_CycleComplete_EventId,11253,Variable Data_Dynamic_AnalogArray_CycleComplete_EventType,11254,Variable Data_Dynamic_AnalogArray_CycleComplete_SourceNode,11255,Variable Data_Dynamic_AnalogArray_CycleComplete_SourceName,11256,Variable Data_Dynamic_AnalogArray_CycleComplete_Time,11257,Variable Data_Dynamic_AnalogArray_CycleComplete_ReceiveTime,11258,Variable Data_Dynamic_AnalogArray_CycleComplete_LocalTime,11259,Variable Data_Dynamic_AnalogArray_CycleComplete_Message,11260,Variable Data_Dynamic_AnalogArray_CycleComplete_Severity,11261,Variable Data_Dynamic_AnalogArray_CycleComplete_BranchId,11262,Variable Data_Dynamic_AnalogArray_CycleComplete_Retain,11263,Variable Data_Dynamic_AnalogArray_CycleComplete_EnabledState,11264,Variable Data_Dynamic_AnalogArray_CycleComplete_EnabledState_Id,11265,Variable Data_Dynamic_AnalogArray_CycleComplete_EnabledState_Name,11266,Variable Data_Dynamic_AnalogArray_CycleComplete_EnabledState_Number,11267,Variable Data_Dynamic_AnalogArray_CycleComplete_EnabledState_EffectiveDisplayName,11268,Variable Data_Dynamic_AnalogArray_CycleComplete_EnabledState_TransitionTime,11269,Variable Data_Dynamic_AnalogArray_CycleComplete_Quality,11270,Variable Data_Dynamic_AnalogArray_CycleComplete_Quality_SourceTimestamp,11271,Variable Data_Dynamic_AnalogArray_CycleComplete_LastSeverity,11274,Variable Data_Dynamic_AnalogArray_CycleComplete_LastSeverity_SourceTimestamp,11275,Variable Data_Dynamic_AnalogArray_CycleComplete_Comment,11276,Variable Data_Dynamic_AnalogArray_CycleComplete_Comment_SourceTimestamp,11277,Variable Data_Dynamic_AnalogArray_CycleComplete_ClientUserId,11278,Variable Data_Dynamic_AnalogArray_CycleComplete_Enable,11279,Method Data_Dynamic_AnalogArray_CycleComplete_Disable,11280,Method Data_Dynamic_AnalogArray_CycleComplete_AddComment,11281,Method Data_Dynamic_AnalogArray_CycleComplete_AddComment_InputArguments,11282,Variable Data_Dynamic_AnalogArray_CycleComplete_AckedState,11285,Variable Data_Dynamic_AnalogArray_CycleComplete_AckedState_Id,11286,Variable Data_Dynamic_AnalogArray_CycleComplete_AckedState_Name,11287,Variable Data_Dynamic_AnalogArray_CycleComplete_AckedState_Number,11288,Variable Data_Dynamic_AnalogArray_CycleComplete_AckedState_EffectiveDisplayName,11289,Variable Data_Dynamic_AnalogArray_CycleComplete_AckedState_TransitionTime,11290,Variable Data_Dynamic_AnalogArray_CycleComplete_AckedState_TrueState,11291,Variable Data_Dynamic_AnalogArray_CycleComplete_AckedState_FalseState,11292,Variable Data_Dynamic_AnalogArray_CycleComplete_ConfirmedState,11293,Variable Data_Dynamic_AnalogArray_CycleComplete_ConfirmedState_Id,11294,Variable Data_Dynamic_AnalogArray_CycleComplete_ConfirmedState_Name,11295,Variable Data_Dynamic_AnalogArray_CycleComplete_ConfirmedState_Number,11296,Variable Data_Dynamic_AnalogArray_CycleComplete_ConfirmedState_EffectiveDisplayName,11297,Variable Data_Dynamic_AnalogArray_CycleComplete_ConfirmedState_TransitionTime,11298,Variable Data_Dynamic_AnalogArray_CycleComplete_ConfirmedState_TrueState,11299,Variable Data_Dynamic_AnalogArray_CycleComplete_ConfirmedState_FalseState,11300,Variable Data_Dynamic_AnalogArray_CycleComplete_Acknowledge,11301,Method Data_Dynamic_AnalogArray_CycleComplete_Acknowledge_InputArguments,11302,Variable Data_Dynamic_AnalogArray_CycleComplete_Confirm,11303,Method Data_Dynamic_AnalogArray_CycleComplete_Confirm_InputArguments,11304,Variable Data_Dynamic_AnalogArray_SByteValue,11305,Variable Data_Dynamic_AnalogArray_SByteValue_Definition,11306,Variable Data_Dynamic_AnalogArray_SByteValue_ValuePrecision,11307,Variable Data_Dynamic_AnalogArray_SByteValue_EURange,11308,Variable Data_Dynamic_AnalogArray_SByteValue_InstrumentRange,11309,Variable Data_Dynamic_AnalogArray_SByteValue_EngineeringUnits,11310,Variable Data_Dynamic_AnalogArray_ByteValue,11311,Variable Data_Dynamic_AnalogArray_ByteValue_Definition,11312,Variable Data_Dynamic_AnalogArray_ByteValue_ValuePrecision,11313,Variable Data_Dynamic_AnalogArray_ByteValue_EURange,11314,Variable Data_Dynamic_AnalogArray_ByteValue_InstrumentRange,11315,Variable Data_Dynamic_AnalogArray_ByteValue_EngineeringUnits,11316,Variable Data_Dynamic_AnalogArray_Int16Value,11317,Variable Data_Dynamic_AnalogArray_Int16Value_Definition,11318,Variable Data_Dynamic_AnalogArray_Int16Value_ValuePrecision,11319,Variable Data_Dynamic_AnalogArray_Int16Value_EURange,11320,Variable Data_Dynamic_AnalogArray_Int16Value_InstrumentRange,11321,Variable Data_Dynamic_AnalogArray_Int16Value_EngineeringUnits,11322,Variable Data_Dynamic_AnalogArray_UInt16Value,11323,Variable Data_Dynamic_AnalogArray_UInt16Value_Definition,11324,Variable Data_Dynamic_AnalogArray_UInt16Value_ValuePrecision,11325,Variable Data_Dynamic_AnalogArray_UInt16Value_EURange,11326,Variable Data_Dynamic_AnalogArray_UInt16Value_InstrumentRange,11327,Variable Data_Dynamic_AnalogArray_UInt16Value_EngineeringUnits,11328,Variable Data_Dynamic_AnalogArray_Int32Value,11329,Variable Data_Dynamic_AnalogArray_Int32Value_Definition,11330,Variable Data_Dynamic_AnalogArray_Int32Value_ValuePrecision,11331,Variable Data_Dynamic_AnalogArray_Int32Value_EURange,11332,Variable Data_Dynamic_AnalogArray_Int32Value_InstrumentRange,11333,Variable Data_Dynamic_AnalogArray_Int32Value_EngineeringUnits,11334,Variable Data_Dynamic_AnalogArray_UInt32Value,11335,Variable Data_Dynamic_AnalogArray_UInt32Value_Definition,11336,Variable Data_Dynamic_AnalogArray_UInt32Value_ValuePrecision,11337,Variable Data_Dynamic_AnalogArray_UInt32Value_EURange,11338,Variable Data_Dynamic_AnalogArray_UInt32Value_InstrumentRange,11339,Variable Data_Dynamic_AnalogArray_UInt32Value_EngineeringUnits,11340,Variable Data_Dynamic_AnalogArray_Int64Value,11341,Variable Data_Dynamic_AnalogArray_Int64Value_Definition,11342,Variable Data_Dynamic_AnalogArray_Int64Value_ValuePrecision,11343,Variable Data_Dynamic_AnalogArray_Int64Value_EURange,11344,Variable Data_Dynamic_AnalogArray_Int64Value_InstrumentRange,11345,Variable Data_Dynamic_AnalogArray_Int64Value_EngineeringUnits,11346,Variable Data_Dynamic_AnalogArray_UInt64Value,11347,Variable Data_Dynamic_AnalogArray_UInt64Value_Definition,11348,Variable Data_Dynamic_AnalogArray_UInt64Value_ValuePrecision,11349,Variable Data_Dynamic_AnalogArray_UInt64Value_EURange,11350,Variable Data_Dynamic_AnalogArray_UInt64Value_InstrumentRange,11351,Variable Data_Dynamic_AnalogArray_UInt64Value_EngineeringUnits,11352,Variable Data_Dynamic_AnalogArray_FloatValue,11353,Variable Data_Dynamic_AnalogArray_FloatValue_Definition,11354,Variable Data_Dynamic_AnalogArray_FloatValue_ValuePrecision,11355,Variable Data_Dynamic_AnalogArray_FloatValue_EURange,11356,Variable Data_Dynamic_AnalogArray_FloatValue_InstrumentRange,11357,Variable Data_Dynamic_AnalogArray_FloatValue_EngineeringUnits,11358,Variable Data_Dynamic_AnalogArray_DoubleValue,11359,Variable Data_Dynamic_AnalogArray_DoubleValue_Definition,11360,Variable Data_Dynamic_AnalogArray_DoubleValue_ValuePrecision,11361,Variable Data_Dynamic_AnalogArray_DoubleValue_EURange,11362,Variable Data_Dynamic_AnalogArray_DoubleValue_InstrumentRange,11363,Variable Data_Dynamic_AnalogArray_DoubleValue_EngineeringUnits,11364,Variable Data_Dynamic_AnalogArray_NumberValue,11365,Variable Data_Dynamic_AnalogArray_NumberValue_Definition,11366,Variable Data_Dynamic_AnalogArray_NumberValue_ValuePrecision,11367,Variable Data_Dynamic_AnalogArray_NumberValue_EURange,11368,Variable Data_Dynamic_AnalogArray_NumberValue_InstrumentRange,11369,Variable Data_Dynamic_AnalogArray_NumberValue_EngineeringUnits,11370,Variable Data_Dynamic_AnalogArray_IntegerValue,11371,Variable Data_Dynamic_AnalogArray_IntegerValue_Definition,11372,Variable Data_Dynamic_AnalogArray_IntegerValue_ValuePrecision,11373,Variable Data_Dynamic_AnalogArray_IntegerValue_EURange,11374,Variable Data_Dynamic_AnalogArray_IntegerValue_InstrumentRange,11375,Variable Data_Dynamic_AnalogArray_IntegerValue_EngineeringUnits,11376,Variable Data_Dynamic_AnalogArray_UIntegerValue,11377,Variable Data_Dynamic_AnalogArray_UIntegerValue_Definition,11378,Variable Data_Dynamic_AnalogArray_UIntegerValue_ValuePrecision,11379,Variable Data_Dynamic_AnalogArray_UIntegerValue_EURange,11380,Variable Data_Dynamic_AnalogArray_UIntegerValue_InstrumentRange,11381,Variable Data_Dynamic_AnalogArray_UIntegerValue_EngineeringUnits,11382,Variable Data_Conditions,11383,Object Data_Conditions_SystemStatus,11384,Object Data_Conditions_SystemStatus_EventId,11385,Variable Data_Conditions_SystemStatus_EventType,11386,Variable Data_Conditions_SystemStatus_SourceNode,11387,Variable Data_Conditions_SystemStatus_SourceName,11388,Variable Data_Conditions_SystemStatus_Time,11389,Variable Data_Conditions_SystemStatus_ReceiveTime,11390,Variable Data_Conditions_SystemStatus_LocalTime,11391,Variable Data_Conditions_SystemStatus_Message,11392,Variable Data_Conditions_SystemStatus_Severity,11393,Variable Data_Conditions_SystemStatus_BranchId,11394,Variable Data_Conditions_SystemStatus_Retain,11395,Variable Data_Conditions_SystemStatus_EnabledState,11396,Variable Data_Conditions_SystemStatus_EnabledState_Id,11397,Variable Data_Conditions_SystemStatus_EnabledState_Name,11398,Variable Data_Conditions_SystemStatus_EnabledState_Number,11399,Variable Data_Conditions_SystemStatus_EnabledState_EffectiveDisplayName,11400,Variable Data_Conditions_SystemStatus_EnabledState_TransitionTime,11401,Variable Data_Conditions_SystemStatus_Quality,11402,Variable Data_Conditions_SystemStatus_Quality_SourceTimestamp,11403,Variable Data_Conditions_SystemStatus_LastSeverity,11406,Variable Data_Conditions_SystemStatus_LastSeverity_SourceTimestamp,11407,Variable Data_Conditions_SystemStatus_Comment,11408,Variable Data_Conditions_SystemStatus_Comment_SourceTimestamp,11409,Variable Data_Conditions_SystemStatus_ClientUserId,11410,Variable Data_Conditions_SystemStatus_Enable,11411,Method Data_Conditions_SystemStatus_Disable,11412,Method Data_Conditions_SystemStatus_AddComment,11413,Method Data_Conditions_SystemStatus_AddComment_InputArguments,11414,Variable Data_Conditions_SystemStatus_MonitoredNodeCount,11417,Variable ScalarValueDataType_Encoding_DefaultXml,11418,Object ArrayValueDataType_Encoding_DefaultXml,11419,Object UserScalarValueDataType_Encoding_DefaultXml,11420,Object UserArrayValueDataType_Encoding_DefaultXml,11421,Object TestData_BinarySchema,11422,Variable TestData_BinarySchema_DataTypeVersion,11423,Variable TestData_BinarySchema_NamespaceUri,11424,Variable TestData_BinarySchema_ScalarValueDataType,11425,Variable TestData_BinarySchema_ScalarValueDataType_DataTypeVersion,11426,Variable TestData_BinarySchema_ScalarValueDataType_DictionaryFragment,11427,Variable TestData_BinarySchema_ArrayValueDataType,11428,Variable TestData_BinarySchema_ArrayValueDataType_DataTypeVersion,11429,Variable TestData_BinarySchema_ArrayValueDataType_DictionaryFragment,11430,Variable TestData_BinarySchema_UserScalarValueDataType,11431,Variable TestData_BinarySchema_UserScalarValueDataType_DataTypeVersion,11432,Variable TestData_BinarySchema_UserScalarValueDataType_DictionaryFragment,11433,Variable TestData_BinarySchema_UserArrayValueDataType,11434,Variable TestData_BinarySchema_UserArrayValueDataType_DataTypeVersion,11435,Variable TestData_BinarySchema_UserArrayValueDataType_DictionaryFragment,11436,Variable ScalarValueDataType_Encoding_DefaultBinary,11437,Object ArrayValueDataType_Encoding_DefaultBinary,11438,Object UserScalarValueDataType_Encoding_DefaultBinary,11439,Object UserArrayValueDataType_Encoding_DefaultBinary,11440,Object TestData_XmlSchema,11441,Variable TestData_XmlSchema_DataTypeVersion,11442,Variable TestData_XmlSchema_NamespaceUri,11443,Variable TestData_XmlSchema_ScalarValueDataType,11444,Variable TestData_XmlSchema_ScalarValueDataType_DataTypeVersion,11445,Variable TestData_XmlSchema_ScalarValueDataType_DictionaryFragment,11446,Variable TestData_XmlSchema_ArrayValueDataType,11447,Variable TestData_XmlSchema_ArrayValueDataType_DataTypeVersion,11448,Variable TestData_XmlSchema_ArrayValueDataType_DictionaryFragment,11449,Variable TestData_XmlSchema_UserScalarValueDataType,11450,Variable TestData_XmlSchema_UserScalarValueDataType_DataTypeVersion,11451,Variable TestData_XmlSchema_UserScalarValueDataType_DictionaryFragment,11452,Variable TestData_XmlSchema_UserArrayValueDataType,11453,Variable TestData_XmlSchema_UserArrayValueDataType_DataTypeVersion,11454,Variable TestData_XmlSchema_UserArrayValueDataType_DictionaryFragment,11455,Variable TestDataObjectType_CycleComplete_EnabledState_EffectiveTransitionTime,11456,Variable TestDataObjectType_CycleComplete_EnabledState_TrueState,11457,Variable TestDataObjectType_CycleComplete_EnabledState_FalseState,11458,Variable TestDataObjectType_CycleComplete_AckedState_EffectiveTransitionTime,11459,Variable TestDataObjectType_CycleComplete_ConfirmedState_EffectiveTransitionTime,11460,Variable ScalarValueObjectType_CycleComplete_EnabledState_EffectiveTransitionTime,11461,Variable ScalarValueObjectType_CycleComplete_EnabledState_TrueState,11462,Variable ScalarValueObjectType_CycleComplete_EnabledState_FalseState,11463,Variable ScalarValueObjectType_CycleComplete_AckedState_EffectiveTransitionTime,11464,Variable ScalarValueObjectType_CycleComplete_ConfirmedState_EffectiveTransitionTime,11465,Variable AnalogScalarValueObjectType_CycleComplete_EnabledState_EffectiveTransitionTime,11466,Variable AnalogScalarValueObjectType_CycleComplete_EnabledState_TrueState,11467,Variable AnalogScalarValueObjectType_CycleComplete_EnabledState_FalseState,11468,Variable AnalogScalarValueObjectType_CycleComplete_AckedState_EffectiveTransitionTime,11469,Variable AnalogScalarValueObjectType_CycleComplete_ConfirmedState_EffectiveTransitionTime,11470,Variable ArrayValueObjectType_CycleComplete_EnabledState_EffectiveTransitionTime,11471,Variable ArrayValueObjectType_CycleComplete_EnabledState_TrueState,11472,Variable ArrayValueObjectType_CycleComplete_EnabledState_FalseState,11473,Variable ArrayValueObjectType_CycleComplete_AckedState_EffectiveTransitionTime,11474,Variable ArrayValueObjectType_CycleComplete_ConfirmedState_EffectiveTransitionTime,11475,Variable AnalogArrayValueObjectType_CycleComplete_EnabledState_EffectiveTransitionTime,11476,Variable AnalogArrayValueObjectType_CycleComplete_EnabledState_TrueState,11477,Variable AnalogArrayValueObjectType_CycleComplete_EnabledState_FalseState,11478,Variable AnalogArrayValueObjectType_CycleComplete_AckedState_EffectiveTransitionTime,11479,Variable AnalogArrayValueObjectType_CycleComplete_ConfirmedState_EffectiveTransitionTime,11480,Variable UserScalarValueObjectType_CycleComplete_EnabledState_EffectiveTransitionTime,11481,Variable UserScalarValueObjectType_CycleComplete_EnabledState_TrueState,11482,Variable UserScalarValueObjectType_CycleComplete_EnabledState_FalseState,11483,Variable UserScalarValueObjectType_CycleComplete_AckedState_EffectiveTransitionTime,11484,Variable UserScalarValueObjectType_CycleComplete_ConfirmedState_EffectiveTransitionTime,11485,Variable UserArrayValueObjectType_CycleComplete_EnabledState_EffectiveTransitionTime,11486,Variable UserArrayValueObjectType_CycleComplete_EnabledState_TrueState,11487,Variable UserArrayValueObjectType_CycleComplete_EnabledState_FalseState,11488,Variable UserArrayValueObjectType_CycleComplete_AckedState_EffectiveTransitionTime,11489,Variable UserArrayValueObjectType_CycleComplete_ConfirmedState_EffectiveTransitionTime,11490,Variable TestSystemConditionType_EnabledState_EffectiveTransitionTime,11491,Variable TestSystemConditionType_EnabledState_TrueState,11492,Variable TestSystemConditionType_EnabledState_FalseState,11493,Variable Data_Static_Scalar_CycleComplete_EnabledState_EffectiveTransitionTime,11494,Variable Data_Static_Scalar_CycleComplete_EnabledState_TrueState,11495,Variable Data_Static_Scalar_CycleComplete_EnabledState_FalseState,11496,Variable Data_Static_Scalar_CycleComplete_AckedState_EffectiveTransitionTime,11497,Variable Data_Static_Scalar_CycleComplete_ConfirmedState_EffectiveTransitionTime,11498,Variable Data_Static_Array_CycleComplete_EnabledState_EffectiveTransitionTime,11499,Variable Data_Static_Array_CycleComplete_EnabledState_TrueState,11500,Variable Data_Static_Array_CycleComplete_EnabledState_FalseState,11501,Variable Data_Static_Array_CycleComplete_AckedState_EffectiveTransitionTime,11502,Variable Data_Static_Array_CycleComplete_ConfirmedState_EffectiveTransitionTime,11503,Variable Data_Static_UserScalar_CycleComplete_EnabledState_EffectiveTransitionTime,11504,Variable Data_Static_UserScalar_CycleComplete_EnabledState_TrueState,11505,Variable Data_Static_UserScalar_CycleComplete_EnabledState_FalseState,11506,Variable Data_Static_UserScalar_CycleComplete_AckedState_EffectiveTransitionTime,11507,Variable Data_Static_UserScalar_CycleComplete_ConfirmedState_EffectiveTransitionTime,11508,Variable Data_Static_UserArray_CycleComplete_EnabledState_EffectiveTransitionTime,11509,Variable Data_Static_UserArray_CycleComplete_EnabledState_TrueState,11510,Variable Data_Static_UserArray_CycleComplete_EnabledState_FalseState,11511,Variable Data_Static_UserArray_CycleComplete_AckedState_EffectiveTransitionTime,11512,Variable Data_Static_UserArray_CycleComplete_ConfirmedState_EffectiveTransitionTime,11513,Variable Data_Static_AnalogScalar_CycleComplete_EnabledState_EffectiveTransitionTime,11514,Variable Data_Static_AnalogScalar_CycleComplete_EnabledState_TrueState,11515,Variable Data_Static_AnalogScalar_CycleComplete_EnabledState_FalseState,11516,Variable Data_Static_AnalogScalar_CycleComplete_AckedState_EffectiveTransitionTime,11517,Variable Data_Static_AnalogScalar_CycleComplete_ConfirmedState_EffectiveTransitionTime,11518,Variable Data_Static_AnalogArray_CycleComplete_EnabledState_EffectiveTransitionTime,11519,Variable Data_Static_AnalogArray_CycleComplete_EnabledState_TrueState,11520,Variable Data_Static_AnalogArray_CycleComplete_EnabledState_FalseState,11521,Variable Data_Static_AnalogArray_CycleComplete_AckedState_EffectiveTransitionTime,11522,Variable Data_Static_AnalogArray_CycleComplete_ConfirmedState_EffectiveTransitionTime,11523,Variable Data_Dynamic_Scalar_CycleComplete_EnabledState_EffectiveTransitionTime,11524,Variable Data_Dynamic_Scalar_CycleComplete_EnabledState_TrueState,11525,Variable Data_Dynamic_Scalar_CycleComplete_EnabledState_FalseState,11526,Variable Data_Dynamic_Scalar_CycleComplete_AckedState_EffectiveTransitionTime,11527,Variable Data_Dynamic_Scalar_CycleComplete_ConfirmedState_EffectiveTransitionTime,11528,Variable Data_Dynamic_Array_CycleComplete_EnabledState_EffectiveTransitionTime,11529,Variable Data_Dynamic_Array_CycleComplete_EnabledState_TrueState,11530,Variable Data_Dynamic_Array_CycleComplete_EnabledState_FalseState,11531,Variable Data_Dynamic_Array_CycleComplete_AckedState_EffectiveTransitionTime,11532,Variable Data_Dynamic_Array_CycleComplete_ConfirmedState_EffectiveTransitionTime,11533,Variable Data_Dynamic_UserScalar_CycleComplete_EnabledState_EffectiveTransitionTime,11534,Variable Data_Dynamic_UserScalar_CycleComplete_EnabledState_TrueState,11535,Variable Data_Dynamic_UserScalar_CycleComplete_EnabledState_FalseState,11536,Variable Data_Dynamic_UserScalar_CycleComplete_AckedState_EffectiveTransitionTime,11537,Variable Data_Dynamic_UserScalar_CycleComplete_ConfirmedState_EffectiveTransitionTime,11538,Variable Data_Dynamic_UserArray_CycleComplete_EnabledState_EffectiveTransitionTime,11539,Variable Data_Dynamic_UserArray_CycleComplete_EnabledState_TrueState,11540,Variable Data_Dynamic_UserArray_CycleComplete_EnabledState_FalseState,11541,Variable Data_Dynamic_UserArray_CycleComplete_AckedState_EffectiveTransitionTime,11542,Variable Data_Dynamic_UserArray_CycleComplete_ConfirmedState_EffectiveTransitionTime,11543,Variable Data_Dynamic_AnalogScalar_CycleComplete_EnabledState_EffectiveTransitionTime,11544,Variable Data_Dynamic_AnalogScalar_CycleComplete_EnabledState_TrueState,11545,Variable Data_Dynamic_AnalogScalar_CycleComplete_EnabledState_FalseState,11546,Variable Data_Dynamic_AnalogScalar_CycleComplete_AckedState_EffectiveTransitionTime,11547,Variable Data_Dynamic_AnalogScalar_CycleComplete_ConfirmedState_EffectiveTransitionTime,11548,Variable Data_Dynamic_AnalogArray_CycleComplete_EnabledState_EffectiveTransitionTime,11549,Variable Data_Dynamic_AnalogArray_CycleComplete_EnabledState_TrueState,11550,Variable Data_Dynamic_AnalogArray_CycleComplete_EnabledState_FalseState,11551,Variable Data_Dynamic_AnalogArray_CycleComplete_AckedState_EffectiveTransitionTime,11552,Variable Data_Dynamic_AnalogArray_CycleComplete_ConfirmedState_EffectiveTransitionTime,11553,Variable Data_Conditions_SystemStatus_EnabledState_EffectiveTransitionTime,11554,Variable Data_Conditions_SystemStatus_EnabledState_TrueState,11555,Variable Data_Conditions_SystemStatus_EnabledState_FalseState,11556,Variable TestDataObjectType_CycleComplete_ConditionName,11557,Variable ScalarValueObjectType_CycleComplete_ConditionName,11558,Variable AnalogScalarValueObjectType_CycleComplete_ConditionName,11559,Variable ArrayValueObjectType_CycleComplete_ConditionName,11560,Variable AnalogArrayValueObjectType_CycleComplete_ConditionName,11561,Variable UserScalarValueObjectType_CycleComplete_ConditionName,11562,Variable UserArrayValueObjectType_CycleComplete_ConditionName,11563,Variable TestSystemConditionType_ConditionName,11564,Variable Data_Static_Scalar_CycleComplete_ConditionName,11565,Variable Data_Static_Array_CycleComplete_ConditionName,11566,Variable Data_Static_UserScalar_CycleComplete_ConditionName,11567,Variable Data_Static_UserArray_CycleComplete_ConditionName,11568,Variable Data_Static_AnalogScalar_CycleComplete_ConditionName,11569,Variable Data_Static_AnalogArray_CycleComplete_ConditionName,11570,Variable Data_Dynamic_Scalar_CycleComplete_ConditionName,11571,Variable Data_Dynamic_Array_CycleComplete_ConditionName,11572,Variable Data_Dynamic_UserScalar_CycleComplete_ConditionName,11573,Variable Data_Dynamic_UserArray_CycleComplete_ConditionName,11574,Variable Data_Dynamic_AnalogScalar_CycleComplete_ConditionName,11575,Variable Data_Dynamic_AnalogArray_CycleComplete_ConditionName,11576,Variable Data_Conditions_SystemStatus_ConditionName,11577,Variable TestDataObjectType_CycleComplete_ConditionClassId,11578,Variable TestDataObjectType_CycleComplete_ConditionClassName,11579,Variable ScalarValueObjectType_CycleComplete_ConditionClassId,11580,Variable ScalarValueObjectType_CycleComplete_ConditionClassName,11581,Variable AnalogScalarValueObjectType_CycleComplete_ConditionClassId,11582,Variable AnalogScalarValueObjectType_CycleComplete_ConditionClassName,11583,Variable ArrayValueObjectType_CycleComplete_ConditionClassId,11584,Variable ArrayValueObjectType_CycleComplete_ConditionClassName,11585,Variable AnalogArrayValueObjectType_CycleComplete_ConditionClassId,11586,Variable AnalogArrayValueObjectType_CycleComplete_ConditionClassName,11587,Variable UserScalarValueObjectType_CycleComplete_ConditionClassId,11588,Variable UserScalarValueObjectType_CycleComplete_ConditionClassName,11589,Variable UserArrayValueObjectType_CycleComplete_ConditionClassId,11590,Variable UserArrayValueObjectType_CycleComplete_ConditionClassName,11591,Variable TestSystemConditionType_ConditionClassId,11592,Variable TestSystemConditionType_ConditionClassName,11593,Variable Data_Static_Scalar_CycleComplete_ConditionClassId,11594,Variable Data_Static_Scalar_CycleComplete_ConditionClassName,11595,Variable Data_Static_Array_CycleComplete_ConditionClassId,11596,Variable Data_Static_Array_CycleComplete_ConditionClassName,11597,Variable Data_Static_UserScalar_CycleComplete_ConditionClassId,11598,Variable Data_Static_UserScalar_CycleComplete_ConditionClassName,11599,Variable Data_Static_UserArray_CycleComplete_ConditionClassId,11600,Variable Data_Static_UserArray_CycleComplete_ConditionClassName,11601,Variable Data_Static_AnalogScalar_CycleComplete_ConditionClassId,11602,Variable Data_Static_AnalogScalar_CycleComplete_ConditionClassName,11603,Variable Data_Static_AnalogArray_CycleComplete_ConditionClassId,11604,Variable Data_Static_AnalogArray_CycleComplete_ConditionClassName,11605,Variable Data_Dynamic_Scalar_CycleComplete_ConditionClassId,11606,Variable Data_Dynamic_Scalar_CycleComplete_ConditionClassName,11607,Variable Data_Dynamic_Array_CycleComplete_ConditionClassId,11608,Variable Data_Dynamic_Array_CycleComplete_ConditionClassName,11609,Variable Data_Dynamic_UserScalar_CycleComplete_ConditionClassId,11610,Variable Data_Dynamic_UserScalar_CycleComplete_ConditionClassName,11611,Variable Data_Dynamic_UserArray_CycleComplete_ConditionClassId,11612,Variable Data_Dynamic_UserArray_CycleComplete_ConditionClassName,11613,Variable Data_Dynamic_AnalogScalar_CycleComplete_ConditionClassId,11614,Variable Data_Dynamic_AnalogScalar_CycleComplete_ConditionClassName,11615,Variable Data_Dynamic_AnalogArray_CycleComplete_ConditionClassId,11616,Variable Data_Dynamic_AnalogArray_CycleComplete_ConditionClassName,11617,Variable Data_Conditions_SystemStatus_ConditionClassId,11618,Variable Data_Conditions_SystemStatus_ConditionClassName,11619,Variable TestDataObjectType_CycleComplete_ConditionSubClassId,15001,Variable TestDataObjectType_CycleComplete_ConditionSubClassName,15002,Variable ScalarValueObjectType_CycleComplete_ConditionSubClassId,15003,Variable ScalarValueObjectType_CycleComplete_ConditionSubClassName,15004,Variable AnalogScalarValueObjectType_CycleComplete_ConditionSubClassId,15005,Variable AnalogScalarValueObjectType_CycleComplete_ConditionSubClassName,15006,Variable ArrayValueObjectType_CycleComplete_ConditionSubClassId,15007,Variable ArrayValueObjectType_CycleComplete_ConditionSubClassName,15008,Variable AnalogArrayValueObjectType_CycleComplete_ConditionSubClassId,15009,Variable AnalogArrayValueObjectType_CycleComplete_ConditionSubClassName,15010,Variable UserScalarValueObjectType_CycleComplete_ConditionSubClassId,15011,Variable UserScalarValueObjectType_CycleComplete_ConditionSubClassName,15012,Variable UserArrayValueObjectType_CycleComplete_ConditionSubClassId,15013,Variable UserArrayValueObjectType_CycleComplete_ConditionSubClassName,15014,Variable TestSystemConditionType_ConditionSubClassId,15015,Variable TestSystemConditionType_ConditionSubClassName,15016,Variable TestSystemConditionType_ConditionRefresh2,15017,Method TestSystemConditionType_ConditionRefresh2_InputArguments,15018,Variable Data_Static_Scalar_CycleComplete_ConditionSubClassId,15019,Variable Data_Static_Scalar_CycleComplete_ConditionSubClassName,15020,Variable Data_Static_Array_CycleComplete_ConditionSubClassId,15021,Variable Data_Static_Array_CycleComplete_ConditionSubClassName,15022,Variable Data_Static_UserScalar_CycleComplete_ConditionSubClassId,15023,Variable Data_Static_UserScalar_CycleComplete_ConditionSubClassName,15024,Variable Data_Static_UserArray_CycleComplete_ConditionSubClassId,15025,Variable Data_Static_UserArray_CycleComplete_ConditionSubClassName,15026,Variable Data_Static_AnalogScalar_CycleComplete_ConditionSubClassId,15027,Variable Data_Static_AnalogScalar_CycleComplete_ConditionSubClassName,15028,Variable Data_Static_AnalogArray_CycleComplete_ConditionSubClassId,15029,Variable Data_Static_AnalogArray_CycleComplete_ConditionSubClassName,15030,Variable Data_Dynamic_Scalar_CycleComplete_ConditionSubClassId,15031,Variable Data_Dynamic_Scalar_CycleComplete_ConditionSubClassName,15032,Variable Data_Dynamic_Array_CycleComplete_ConditionSubClassId,15033,Variable Data_Dynamic_Array_CycleComplete_ConditionSubClassName,15034,Variable Data_Dynamic_UserScalar_CycleComplete_ConditionSubClassId,15035,Variable Data_Dynamic_UserScalar_CycleComplete_ConditionSubClassName,15036,Variable Data_Dynamic_UserArray_CycleComplete_ConditionSubClassId,15037,Variable Data_Dynamic_UserArray_CycleComplete_ConditionSubClassName,15038,Variable Data_Dynamic_AnalogScalar_CycleComplete_ConditionSubClassId,15039,Variable Data_Dynamic_AnalogScalar_CycleComplete_ConditionSubClassName,15040,Variable Data_Dynamic_AnalogArray_CycleComplete_ConditionSubClassId,15041,Variable Data_Dynamic_AnalogArray_CycleComplete_ConditionSubClassName,15042,Variable Data_Conditions_SystemStatus_ConditionSubClassId,15043,Variable Data_Conditions_SystemStatus_ConditionSubClassName,15044,Variable TestData_BinarySchema_Deprecated,15045,Variable TestData_XmlSchema_Deprecated,15046,Variable ScalarValueDataType_Encoding_DefaultJson,15047,Object ArrayValueDataType_Encoding_DefaultJson,15048,Object UserScalarValueDataType_Encoding_DefaultJson,15049,Object UserArrayValueDataType_Encoding_DefaultJson,15050,Object ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/TestData/Design/TestDataDesign.xml ================================================  http://opcfoundation.org/UA/ http://test.org/UA/Data/ The number of new values to generate. If true the server will produce new values for each monitored variable. ua:HasEventSource TestDataObjectType ua:HasEventSource Data_Static_Scalar ua:HasEventSource Data_Static_Array true true true true true true ua:HasEventSource Data_Dynamic_Scalar ua:HasEventSource Data_Dynamic_Array ua:HasEventSource Data_Conditions_SystemStatus ua:Organizes ua:ObjectsFolder ua:HasNotifier ua:Server ua:HasNotifier Data_Static ua:HasNotifier Data_Dynamic ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Vehicles/Design/ModelDesign1.csv ================================================ Vehicles_XmlSchema,287,Variable Vehicles_XmlSchema_DataTypeVersion,288,Variable Vehicles_XmlSchema_NamespaceUri,289,Variable Vehicles_BinarySchema,302,Variable Vehicles_BinarySchema_DataTypeVersion,303,Variable Vehicles_BinarySchema_NamespaceUri,304,Variable VehicleType,314,DataType CarType,315,DataType TruckType,316,DataType VehicleType_Encoding_DefaultXml,317,Object CarType_Encoding_DefaultXml,318,Object TruckType_Encoding_DefaultXml,319,Object Vehicles_XmlSchema_VehicleType,320,Variable Vehicles_XmlSchema_VehicleType_DataTypeVersion,321,Variable Vehicles_XmlSchema_VehicleType_DictionaryFragment,322,Variable Vehicles_XmlSchema_CarType,323,Variable Vehicles_XmlSchema_CarType_DataTypeVersion,324,Variable Vehicles_XmlSchema_CarType_DictionaryFragment,325,Variable Vehicles_XmlSchema_TruckType,326,Variable Vehicles_XmlSchema_TruckType_DataTypeVersion,327,Variable Vehicles_XmlSchema_TruckType_DictionaryFragment,328,Variable VehicleType_Encoding_DefaultBinary,329,Object CarType_Encoding_DefaultBinary,330,Object TruckType_Encoding_DefaultBinary,331,Object Vehicles_BinarySchema_VehicleType,332,Variable Vehicles_BinarySchema_VehicleType_DataTypeVersion,333,Variable Vehicles_BinarySchema_VehicleType_DictionaryFragment,334,Variable Vehicles_BinarySchema_CarType,335,Variable Vehicles_BinarySchema_CarType_DataTypeVersion,336,Variable Vehicles_BinarySchema_CarType_DictionaryFragment,337,Variable Vehicles_BinarySchema_TruckType,338,Variable Vehicles_BinarySchema_TruckType_DataTypeVersion,339,Variable Vehicles_BinarySchema_TruckType_DictionaryFragment,340,Variable DriverType,341,ObjectType DriverType_PrimaryVehicle,342,Variable DriverType_OwnedVehicles,344,Variable Vehicles_BinarySchema_Deprecated,15001,Variable Vehicles_XmlSchema_Deprecated,15002,Variable VehicleType_Encoding_DefaultJson,15003,Object CarType_Encoding_DefaultJson,15004,Object TruckType_Encoding_DefaultJson,15005,Object ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Vehicles/Design/ModelDesign1.xml ================================================ http://opcfoundation.org/UA/ http://opcfoundation.org/UA/Vehicles/Types Toyota Prius 4 Dodge Ram 500 Porche Roadster 2 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Vehicles/Design/ModelDesign2.csv ================================================ ParkingLot,281,Object ParkingLot_VehiclesInLot,283,Variable VehiclesInstances_XmlSchema,341,Variable VehiclesInstances_XmlSchema_DataTypeVersion,342,Variable VehiclesInstances_XmlSchema_NamespaceUri,343,Variable VehiclesInstances_BinarySchema,353,Variable VehiclesInstances_BinarySchema_DataTypeVersion,354,Variable VehiclesInstances_BinarySchema_NamespaceUri,355,Variable BicycleType,365,DataType BicycleType_Encoding_DefaultXml,366,Object VehiclesInstances_XmlSchema_BicycleType,367,Variable VehiclesInstances_XmlSchema_BicycleType_DataTypeVersion,368,Variable VehiclesInstances_XmlSchema_BicycleType_DictionaryFragment,369,Variable BicycleType_Encoding_DefaultBinary,370,Object VehiclesInstances_BinarySchema_BicycleType,371,Variable VehiclesInstances_BinarySchema_BicycleType_DataTypeVersion,372,Variable VehiclesInstances_BinarySchema_BicycleType_DictionaryFragment,373,Variable ParkingLot_DriverOfTheMonth,375,Object ParkingLot_DriverOfTheMonth_PrimaryVehicle,376,Variable ParkingLot_DriverOfTheMonth_OwnedVehicles,377,Variable ParkingLotType,378,DataType ParkingLot_LotType,380,Variable ParkingLotType_EnumValues,15001,Variable VehiclesInstances_BinarySchema_Deprecated,15002,Variable VehiclesInstances_XmlSchema_Deprecated,15003,Variable BicycleType_Encoding_DefaultJson,15004,Object ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Vehicles/Design/ModelDesign2.xml ================================================ http://opcfoundation.org/UA/ http://opcfoundation.org/UA/Vehicles/Types http://opcfoundation.org/UA/Vehicles/Instances Trek Compact 10 1 Hello ua:Organizes ua:ObjectsFolder ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Vehicles/Design/Vehicles.Instances.Constants.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; namespace Vehicles.Instances { #region DataType Identifiers /// /// A class that declares constants for all DataTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class DataTypes { /// /// The identifier for the ParkingLotType DataType. /// public const uint ParkingLotType = 378; /// /// The identifier for the BicycleType DataType. /// public const uint BicycleType = 365; } #endregion #region Object Identifiers /// /// A class that declares constants for all Objects in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Objects { /// /// The identifier for the ParkingLot Object. /// public const uint ParkingLot = 281; /// /// The identifier for the ParkingLot_DriverOfTheMonth Object. /// public const uint ParkingLot_DriverOfTheMonth = 375; /// /// The identifier for the BicycleType_Encoding_DefaultBinary Object. /// public const uint BicycleType_Encoding_DefaultBinary = 370; /// /// The identifier for the BicycleType_Encoding_DefaultXml Object. /// public const uint BicycleType_Encoding_DefaultXml = 366; /// /// The identifier for the BicycleType_Encoding_DefaultJson Object. /// public const uint BicycleType_Encoding_DefaultJson = 15004; } #endregion #region Variable Identifiers /// /// A class that declares constants for all Variables in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Variables { /// /// The identifier for the ParkingLotType_EnumValues Variable. /// public const uint ParkingLotType_EnumValues = 15001; /// /// The identifier for the ParkingLot_LotType Variable. /// public const uint ParkingLot_LotType = 380; /// /// The identifier for the ParkingLot_DriverOfTheMonth_PrimaryVehicle Variable. /// public const uint ParkingLot_DriverOfTheMonth_PrimaryVehicle = 376; /// /// The identifier for the ParkingLot_DriverOfTheMonth_OwnedVehicles Variable. /// public const uint ParkingLot_DriverOfTheMonth_OwnedVehicles = 377; /// /// The identifier for the ParkingLot_VehiclesInLot Variable. /// public const uint ParkingLot_VehiclesInLot = 283; /// /// The identifier for the VehiclesInstances_BinarySchema Variable. /// public const uint VehiclesInstances_BinarySchema = 353; /// /// The identifier for the VehiclesInstances_BinarySchema_NamespaceUri Variable. /// public const uint VehiclesInstances_BinarySchema_NamespaceUri = 355; /// /// The identifier for the VehiclesInstances_BinarySchema_Deprecated Variable. /// public const uint VehiclesInstances_BinarySchema_Deprecated = 15002; /// /// The identifier for the VehiclesInstances_BinarySchema_BicycleType Variable. /// public const uint VehiclesInstances_BinarySchema_BicycleType = 371; /// /// The identifier for the VehiclesInstances_XmlSchema Variable. /// public const uint VehiclesInstances_XmlSchema = 341; /// /// The identifier for the VehiclesInstances_XmlSchema_NamespaceUri Variable. /// public const uint VehiclesInstances_XmlSchema_NamespaceUri = 343; /// /// The identifier for the VehiclesInstances_XmlSchema_Deprecated Variable. /// public const uint VehiclesInstances_XmlSchema_Deprecated = 15003; /// /// The identifier for the VehiclesInstances_XmlSchema_BicycleType Variable. /// public const uint VehiclesInstances_XmlSchema_BicycleType = 367; } #endregion #region DataType Node Identifiers /// /// A class that declares constants for all DataTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class DataTypeIds { /// /// The identifier for the ParkingLotType DataType. /// public static readonly ExpandedNodeId ParkingLotType = new ExpandedNodeId(Vehicles.Instances.DataTypes.ParkingLotType, Vehicles.Instances.Namespaces.VehiclesInstances); /// /// The identifier for the BicycleType DataType. /// public static readonly ExpandedNodeId BicycleType = new ExpandedNodeId(Vehicles.Instances.DataTypes.BicycleType, Vehicles.Instances.Namespaces.VehiclesInstances); } #endregion #region Object Node Identifiers /// /// A class that declares constants for all Objects in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectIds { /// /// The identifier for the ParkingLot Object. /// public static readonly ExpandedNodeId ParkingLot = new ExpandedNodeId(Vehicles.Instances.Objects.ParkingLot, Vehicles.Instances.Namespaces.VehiclesInstances); /// /// The identifier for the ParkingLot_DriverOfTheMonth Object. /// public static readonly ExpandedNodeId ParkingLot_DriverOfTheMonth = new ExpandedNodeId(Vehicles.Instances.Objects.ParkingLot_DriverOfTheMonth, Vehicles.Instances.Namespaces.VehiclesInstances); /// /// The identifier for the BicycleType_Encoding_DefaultBinary Object. /// public static readonly ExpandedNodeId BicycleType_Encoding_DefaultBinary = new ExpandedNodeId(Vehicles.Instances.Objects.BicycleType_Encoding_DefaultBinary, Vehicles.Instances.Namespaces.VehiclesInstances); /// /// The identifier for the BicycleType_Encoding_DefaultXml Object. /// public static readonly ExpandedNodeId BicycleType_Encoding_DefaultXml = new ExpandedNodeId(Vehicles.Instances.Objects.BicycleType_Encoding_DefaultXml, Vehicles.Instances.Namespaces.VehiclesInstances); /// /// The identifier for the BicycleType_Encoding_DefaultJson Object. /// public static readonly ExpandedNodeId BicycleType_Encoding_DefaultJson = new ExpandedNodeId(Vehicles.Instances.Objects.BicycleType_Encoding_DefaultJson, Vehicles.Instances.Namespaces.VehiclesInstances); } #endregion #region Variable Node Identifiers /// /// A class that declares constants for all Variables in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class VariableIds { /// /// The identifier for the ParkingLotType_EnumValues Variable. /// public static readonly ExpandedNodeId ParkingLotType_EnumValues = new ExpandedNodeId(Vehicles.Instances.Variables.ParkingLotType_EnumValues, Vehicles.Instances.Namespaces.VehiclesInstances); /// /// The identifier for the ParkingLot_LotType Variable. /// public static readonly ExpandedNodeId ParkingLot_LotType = new ExpandedNodeId(Vehicles.Instances.Variables.ParkingLot_LotType, Vehicles.Instances.Namespaces.VehiclesInstances); /// /// The identifier for the ParkingLot_DriverOfTheMonth_PrimaryVehicle Variable. /// public static readonly ExpandedNodeId ParkingLot_DriverOfTheMonth_PrimaryVehicle = new ExpandedNodeId(Vehicles.Instances.Variables.ParkingLot_DriverOfTheMonth_PrimaryVehicle, Vehicles.Instances.Namespaces.VehiclesInstances); /// /// The identifier for the ParkingLot_DriverOfTheMonth_OwnedVehicles Variable. /// public static readonly ExpandedNodeId ParkingLot_DriverOfTheMonth_OwnedVehicles = new ExpandedNodeId(Vehicles.Instances.Variables.ParkingLot_DriverOfTheMonth_OwnedVehicles, Vehicles.Instances.Namespaces.VehiclesInstances); /// /// The identifier for the ParkingLot_VehiclesInLot Variable. /// public static readonly ExpandedNodeId ParkingLot_VehiclesInLot = new ExpandedNodeId(Vehicles.Instances.Variables.ParkingLot_VehiclesInLot, Vehicles.Instances.Namespaces.VehiclesInstances); /// /// The identifier for the VehiclesInstances_BinarySchema Variable. /// public static readonly ExpandedNodeId VehiclesInstances_BinarySchema = new ExpandedNodeId(Vehicles.Instances.Variables.VehiclesInstances_BinarySchema, Vehicles.Instances.Namespaces.VehiclesInstances); /// /// The identifier for the VehiclesInstances_BinarySchema_NamespaceUri Variable. /// public static readonly ExpandedNodeId VehiclesInstances_BinarySchema_NamespaceUri = new ExpandedNodeId(Vehicles.Instances.Variables.VehiclesInstances_BinarySchema_NamespaceUri, Vehicles.Instances.Namespaces.VehiclesInstances); /// /// The identifier for the VehiclesInstances_BinarySchema_Deprecated Variable. /// public static readonly ExpandedNodeId VehiclesInstances_BinarySchema_Deprecated = new ExpandedNodeId(Vehicles.Instances.Variables.VehiclesInstances_BinarySchema_Deprecated, Vehicles.Instances.Namespaces.VehiclesInstances); /// /// The identifier for the VehiclesInstances_BinarySchema_BicycleType Variable. /// public static readonly ExpandedNodeId VehiclesInstances_BinarySchema_BicycleType = new ExpandedNodeId(Vehicles.Instances.Variables.VehiclesInstances_BinarySchema_BicycleType, Vehicles.Instances.Namespaces.VehiclesInstances); /// /// The identifier for the VehiclesInstances_XmlSchema Variable. /// public static readonly ExpandedNodeId VehiclesInstances_XmlSchema = new ExpandedNodeId(Vehicles.Instances.Variables.VehiclesInstances_XmlSchema, Vehicles.Instances.Namespaces.VehiclesInstances); /// /// The identifier for the VehiclesInstances_XmlSchema_NamespaceUri Variable. /// public static readonly ExpandedNodeId VehiclesInstances_XmlSchema_NamespaceUri = new ExpandedNodeId(Vehicles.Instances.Variables.VehiclesInstances_XmlSchema_NamespaceUri, Vehicles.Instances.Namespaces.VehiclesInstances); /// /// The identifier for the VehiclesInstances_XmlSchema_Deprecated Variable. /// public static readonly ExpandedNodeId VehiclesInstances_XmlSchema_Deprecated = new ExpandedNodeId(Vehicles.Instances.Variables.VehiclesInstances_XmlSchema_Deprecated, Vehicles.Instances.Namespaces.VehiclesInstances); /// /// The identifier for the VehiclesInstances_XmlSchema_BicycleType Variable. /// public static readonly ExpandedNodeId VehiclesInstances_XmlSchema_BicycleType = new ExpandedNodeId(Vehicles.Instances.Variables.VehiclesInstances_XmlSchema_BicycleType, Vehicles.Instances.Namespaces.VehiclesInstances); } #endregion #region BrowseName Declarations /// /// Declares all of the BrowseNames used in the Model Design. /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class BrowseNames { /// /// The BrowseName for the BicycleType component. /// public const string BicycleType = "BicycleType"; /// /// The BrowseName for the DriverOfTheMonth component. /// public const string DriverOfTheMonth = "DriverOfTheMonth"; /// /// The BrowseName for the LotType component. /// public const string LotType = "LotType"; /// /// The BrowseName for the ParkingLot component. /// public const string ParkingLot = "ParkingLot"; /// /// The BrowseName for the ParkingLotType component. /// public const string ParkingLotType = "ParkingLotType"; /// /// The BrowseName for the VehiclesInLot component. /// public const string VehiclesInLot = "VehiclesInLot"; /// /// The BrowseName for the VehiclesInstances_BinarySchema component. /// public const string VehiclesInstances_BinarySchema = "Vehicles.Instances"; /// /// The BrowseName for the VehiclesInstances_XmlSchema component. /// public const string VehiclesInstances_XmlSchema = "Vehicles.Instances"; } #endregion #region Namespace Declarations /// /// Defines constants for all namespaces referenced by the model design. /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Namespaces { /// /// The URI for the OpcUa namespace (.NET code namespace is 'Opc.Ua'). /// public const string OpcUa = "http://opcfoundation.org/UA/"; /// /// The URI for the OpcUaXsd namespace (.NET code namespace is 'Opc.Ua'). /// public const string OpcUaXsd = "http://opcfoundation.org/UA/2008/02/Types.xsd"; /// /// The URI for the Vehicles namespace (.NET code namespace is 'Vehicles.Types'). /// public const string Vehicles = "http://opcfoundation.org/UA/Vehicles/Types"; /// /// The URI for the VehiclesInstances namespace (.NET code namespace is 'Vehicles.Instances'). /// public const string VehiclesInstances = "http://opcfoundation.org/UA/Vehicles/Instances"; } #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Vehicles/Design/Vehicles.Instances.DataTypes.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; using System; using System.Collections.Generic; using System.Runtime.Serialization; using Vehicles.Types; namespace Vehicles.Instances { #region ParkingLotType Enumeration #if (!OPCUA_EXCLUDE_ParkingLotType) /// /// /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = Vehicles.Instances.Namespaces.VehiclesInstances)] public enum ParkingLotType { /// [EnumMember(Value = "Open_1")] Open = 1, /// [EnumMember(Value = "Covered_2")] Covered = 2, } #region ParkingLotTypeCollection Class /// /// A collection of ParkingLotType objects. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfParkingLotType", Namespace = Vehicles.Instances.Namespaces.VehiclesInstances, ItemName = "ParkingLotType")] #if !NET_STANDARD public partial class ParkingLotTypeCollection : List, ICloneable #else public partial class ParkingLotTypeCollection : List #endif { #region Constructors /// /// Initializes the collection with default values. /// public ParkingLotTypeCollection() { } /// /// Initializes the collection with an initial capacity. /// public ParkingLotTypeCollection(int capacity) : base(capacity) { } /// /// Initializes the collection with another collection. /// public ParkingLotTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// /// Converts an array to a collection. /// public static implicit operator ParkingLotTypeCollection(ParkingLotType[] values) { if (values != null) { return new ParkingLotTypeCollection(values); } return new ParkingLotTypeCollection(); } /// /// Converts a collection to an array. /// public static explicit operator ParkingLotType[](ParkingLotTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #if !NET_STANDARD #region ICloneable Methods /// /// Creates a deep copy of the collection. /// public object Clone() { return (ParkingLotTypeCollection)this.MemberwiseClone(); } #endregion #endif /// public new object MemberwiseClone() { ParkingLotTypeCollection clone = new ParkingLotTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((ParkingLotType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion #region BicycleType Class #if (!OPCUA_EXCLUDE_BicycleType) /// /// /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = Vehicles.Instances.Namespaces.VehiclesInstances)] public partial class BicycleType : VehicleType { #region Constructors /// /// The default constructor. /// public BicycleType() { Initialize(); } /// /// Called by the .NET framework during deserialization. /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { m_noOfGears = (uint)0; m_manufacterName = null; } #endregion #region Public Properties /// [DataMember(Name = "NoOfGears", IsRequired = false, Order = 1)] public uint NoOfGears { get { return m_noOfGears; } set { m_noOfGears = value; } } /// [DataMember(Name = "ManufacterName", IsRequired = false, Order = 2)] public QualifiedName ManufacterName { get { return m_manufacterName; } set { m_manufacterName = value; } } #endregion #region IEncodeable Members /// public override ExpandedNodeId TypeId { get { return DataTypeIds.BicycleType; } } /// public override ExpandedNodeId BinaryEncodingId { get { return ObjectIds.BicycleType_Encoding_DefaultBinary; } } /// public override ExpandedNodeId XmlEncodingId { get { return ObjectIds.BicycleType_Encoding_DefaultXml; } } /// public override void Encode(IEncoder encoder) { base.Encode(encoder); encoder.PushNamespace(Vehicles.Instances.Namespaces.VehiclesInstances); encoder.WriteUInt32("NoOfGears", NoOfGears); encoder.WriteQualifiedName("ManufacterName", ManufacterName); encoder.PopNamespace(); } /// public override void Decode(IDecoder decoder) { base.Decode(decoder); decoder.PushNamespace(Vehicles.Instances.Namespaces.VehiclesInstances); NoOfGears = decoder.ReadUInt32("NoOfGears"); ManufacterName = decoder.ReadQualifiedName("ManufacterName"); decoder.PopNamespace(); } /// public override bool IsEqual(IEncodeable encodeable) { if (Object.ReferenceEquals(this, encodeable)) { return true; } BicycleType value = encodeable as BicycleType; if (value == null) { return false; } if (!base.IsEqual(encodeable)) return false; if (!Utils.IsEqual(m_noOfGears, value.m_noOfGears)) return false; if (!Utils.IsEqual(m_manufacterName, value.m_manufacterName)) return false; return true; } #if !NET_STANDARD /// public override object Clone() { return (BicycleType)this.MemberwiseClone(); } #endif /// public new object MemberwiseClone() { BicycleType clone = (BicycleType)base.MemberwiseClone(); clone.m_noOfGears = (uint)Utils.Clone(this.m_noOfGears); clone.m_manufacterName = (QualifiedName)Utils.Clone(this.m_manufacterName); return clone; } #endregion #region Private Fields private uint m_noOfGears; private QualifiedName m_manufacterName; #endregion } #region BicycleTypeCollection Class /// /// A collection of BicycleType objects. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfBicycleType", Namespace = Vehicles.Instances.Namespaces.VehiclesInstances, ItemName = "BicycleType")] #if !NET_STANDARD public partial class BicycleTypeCollection : List, ICloneable #else public partial class BicycleTypeCollection : List #endif { #region Constructors /// /// Initializes the collection with default values. /// public BicycleTypeCollection() { } /// /// Initializes the collection with an initial capacity. /// public BicycleTypeCollection(int capacity) : base(capacity) { } /// /// Initializes the collection with another collection. /// public BicycleTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// /// Converts an array to a collection. /// public static implicit operator BicycleTypeCollection(BicycleType[] values) { if (values != null) { return new BicycleTypeCollection(values); } return new BicycleTypeCollection(); } /// /// Converts a collection to an array. /// public static explicit operator BicycleType[](BicycleTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #if !NET_STANDARD #region ICloneable Methods /// /// Creates a deep copy of the collection. /// public object Clone() { return (BicycleTypeCollection)this.MemberwiseClone(); } #endregion #endif /// public new object MemberwiseClone() { BicycleTypeCollection clone = new BicycleTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((BicycleType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Vehicles/Design/Vehicles.Instances.NodeIds.csv ================================================ BicycleType,365,DataType BicycleType_Encoding_DefaultBinary,370,Object BicycleType_Encoding_DefaultJson,15004,Object BicycleType_Encoding_DefaultXml,366,Object ParkingLot,281,Object ParkingLotType,378,DataType VehiclesInstances_BinarySchema,353,Variable VehiclesInstances_XmlSchema,341,Variable ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Vehicles/Design/Vehicles.Instances.NodeSet.xml ================================================  http://opcfoundation.org/UA/ http://opcfoundation.org/UA/Vehicles/Instances http://opcfoundation.org/UA/Vehicles/Types ns=1;i=281 Object_1 1 ParkingLot ParkingLot 0 0 0 i=40 false i=58 i=35 true i=85 i=46 false ns=1;i=380 i=47 false ns=1;i=375 i=47 false ns=1;i=283 0 ns=1;i=283 Variable_2 1 VehiclesInLot VehiclesInLot 0 0 0 i=47 true ns=1;i=281 i=40 false i=63 ns=2;i=314 1 0 3 3 0 false 0 ns=1;i=341 Variable_2 1 Vehicles.Instances Vehicles.Instances 0 0 0 i=40 false i=72 i=47 true i=92 i=46 false ns=1;i=343 i=46 false ns=1;i=15003 i=47 false ns=1;i=367 PHhzOnNjaGVtYQ0KICB4bWxuczpzMT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VBL1ZlaGlj bGVzL1R5cGVzIg0KICB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEi DQogIHhtbG5zOnVhPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvMjAwOC8wMi9UeXBlcy54 c2QiDQogIHhtbG5zOnRucz0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VBL1ZlaGljbGVzL0lu c3RhbmNlcyINCiAgdGFyZ2V0TmFtZXNwYWNlPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEv VmVoaWNsZXMvSW5zdGFuY2VzIg0KICBlbGVtZW50Rm9ybURlZmF1bHQ9InF1YWxpZmllZCINCj4N CiAgPHhzOmltcG9ydCBuYW1lc3BhY2U9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9yZy9VQS8yMDA4 LzAyL1R5cGVzLnhzZCIgLz4NCiAgPHhzOmltcG9ydCBuYW1lc3BhY2U9Imh0dHA6Ly9vcGNmb3Vu ZGF0aW9uLm9yZy9VQS9WZWhpY2xlcy9UeXBlcyIgLz4NCg0KICA8eHM6c2ltcGxlVHlwZSAgbmFt ZT0iUGFya2luZ0xvdFR5cGUiPg0KICAgIDx4czpyZXN0cmljdGlvbiBiYXNlPSJ4czpzdHJpbmci Pg0KICAgICAgPHhzOmVudW1lcmF0aW9uIHZhbHVlPSJPcGVuXzEiIC8+DQogICAgICA8eHM6ZW51 bWVyYXRpb24gdmFsdWU9IkNvdmVyZWRfMiIgLz4NCiAgICA8L3hzOnJlc3RyaWN0aW9uPg0KICA8 L3hzOnNpbXBsZVR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9IlBhcmtpbmdMb3RUeXBlIiB0eXBl PSJ0bnM6UGFya2luZ0xvdFR5cGUiIC8+DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9Ikxpc3RP ZlBhcmtpbmdMb3RUeXBlIj4NCiAgICA8eHM6c2VxdWVuY2U+DQogICAgICA8eHM6ZWxlbWVudCBu YW1lPSJQYXJraW5nTG90VHlwZSIgdHlwZT0idG5zOlBhcmtpbmdMb3RUeXBlIiBtaW5PY2N1cnM9 IjAiIG1heE9jY3Vycz0idW5ib3VuZGVkIiAvPg0KICAgIDwveHM6c2VxdWVuY2U+DQogIDwveHM6 Y29tcGxleFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9Ikxpc3RPZlBhcmtpbmdMb3RUeXBlIiB0 eXBlPSJ0bnM6TGlzdE9mUGFya2luZ0xvdFR5cGUiIG5pbGxhYmxlPSJ0cnVlIj48L3hzOmVsZW1l bnQ+DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9IkJpY3ljbGVUeXBlIj4NCiAgICA8eHM6Y29t cGxleENvbnRlbnQgbWl4ZWQ9ImZhbHNlIj4NCiAgICAgIDx4czpleHRlbnNpb24gYmFzZT0iczE6 VmVoaWNsZVR5cGUiPg0KICAgICAgICA8eHM6c2VxdWVuY2U+DQogICAgICAgICAgPHhzOmVsZW1l bnQgbmFtZT0iTm9PZkdlYXJzIiB0eXBlPSJ4czp1bnNpZ25lZEludCIgbWluT2NjdXJzPSIwIiAv Pg0KICAgICAgICAgIDx4czplbGVtZW50IG5hbWU9Ik1hbnVmYWN0ZXJOYW1lIiB0eXBlPSJ1YTpR dWFsaWZpZWROYW1lIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgICA8 L3hzOnNlcXVlbmNlPg0KICAgICAgPC94czpleHRlbnNpb24+DQogICAgPC94czpjb21wbGV4Q29u dGVudD4NCiAgPC94czpjb21wbGV4VHlwZT4NCiAgPHhzOmVsZW1lbnQgbmFtZT0iQmljeWNsZVR5 cGUiIHR5cGU9InRuczpCaWN5Y2xlVHlwZSIgLz4NCg0KICA8eHM6Y29tcGxleFR5cGUgbmFtZT0i TGlzdE9mQmljeWNsZVR5cGUiPg0KICAgIDx4czpzZXF1ZW5jZT4NCiAgICAgIDx4czplbGVtZW50 IG5hbWU9IkJpY3ljbGVUeXBlIiB0eXBlPSJ0bnM6QmljeWNsZVR5cGUiIG1pbk9jY3Vycz0iMCIg bWF4T2NjdXJzPSJ1bmJvdW5kZWQiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgIDwveHM6c2VxdWVu Y2U+DQogIDwveHM6Y29tcGxleFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9Ikxpc3RPZkJpY3lj bGVUeXBlIiB0eXBlPSJ0bnM6TGlzdE9mQmljeWNsZVR5cGUiIG5pbGxhYmxlPSJ0cnVlIj48L3hz OmVsZW1lbnQ+DQoNCjwveHM6c2NoZW1hPg== i=15 -1 1 1 0 false 0 ns=1;i=343 Variable_2 0 NamespaceUri NamespaceUri 0 0 0 i=46 true ns=1;i=341 i=40 false i=68 http://opcfoundation.org/UA/Vehicles/Instances i=12 -1 1 1 0 false 0 ns=1;i=353 Variable_2 1 Vehicles.Instances Vehicles.Instances 0 0 0 i=40 false i=72 i=47 true i=93 i=46 false ns=1;i=355 i=46 false ns=1;i=15002 i=47 false ns=1;i=371 PG9wYzpUeXBlRGljdGlvbmFyeQ0KICB4bWxuczpzMT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3Jn L1VBL1ZlaGljbGVzL1R5cGVzIg0KICB4bWxuczpvcGM9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9y Zy9CaW5hcnlTY2hlbWEvIg0KICB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1M U2NoZW1hLWluc3RhbmNlIg0KICB4bWxuczp1YT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VB LyINCiAgeG1sbnM6dG5zPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvVmVoaWNsZXMvSW5z dGFuY2VzIg0KICBEZWZhdWx0Qnl0ZU9yZGVyPSJMaXR0bGVFbmRpYW4iDQogIFRhcmdldE5hbWVz cGFjZT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VBL1ZlaGljbGVzL0luc3RhbmNlcyINCj4N CiAgPG9wYzpJbXBvcnQgTmFtZXNwYWNlPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvIiBM b2NhdGlvbj0iT3BjLlVhLkJpbmFyeVNjaGVtYS5ic2QiLz4NCiAgPG9wYzpJbXBvcnQgTmFtZXNw YWNlPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvVmVoaWNsZXMvVHlwZXMiIExvY2F0aW9u PSJWZWhpY2xlcy5UeXBlcy5CaW5hcnlTY2hlbWEuYnNkIi8+DQoNCiAgPG9wYzpFbnVtZXJhdGVk VHlwZSBOYW1lPSJQYXJraW5nTG90VHlwZSIgTGVuZ3RoSW5CaXRzPSIzMiI+DQogICAgPG9wYzpF bnVtZXJhdGVkVmFsdWUgTmFtZT0iT3BlbiIgVmFsdWU9IjEiIC8+DQogICAgPG9wYzpFbnVtZXJh dGVkVmFsdWUgTmFtZT0iQ292ZXJlZCIgVmFsdWU9IjIiIC8+DQogIDwvb3BjOkVudW1lcmF0ZWRU eXBlPg0KDQogIDxvcGM6U3RydWN0dXJlZFR5cGUgTmFtZT0iQmljeWNsZVR5cGUiIEJhc2VUeXBl PSJzMTpWZWhpY2xlVHlwZSI+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJNYWtlIiBUeXBlTmFtZT0i b3BjOlN0cmluZyIgU291cmNlVHlwZT0iczE6VmVoaWNsZVR5cGUiIC8+DQogICAgPG9wYzpGaWVs ZCBOYW1lPSJNb2RlbCIgVHlwZU5hbWU9Im9wYzpTdHJpbmciIFNvdXJjZVR5cGU9InMxOlZlaGlj bGVUeXBlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZkdlYXJzIiBUeXBlTmFtZT0ib3Bj OlVJbnQzMiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik1hbnVmYWN0ZXJOYW1lIiBUeXBlTmFt ZT0idWE6UXVhbGlmaWVkTmFtZSIgLz4NCiAgPC9vcGM6U3RydWN0dXJlZFR5cGU+DQoNCjwvb3Bj OlR5cGVEaWN0aW9uYXJ5Pg== i=15 -1 1 1 0 false 0 ns=1;i=355 Variable_2 0 NamespaceUri NamespaceUri 0 0 0 i=46 true ns=1;i=353 i=40 false i=68 http://opcfoundation.org/UA/Vehicles/Instances i=12 -1 1 1 0 false 0 ns=1;i=365 DataType_64 1 BicycleType BicycleType 0 0 0 i=45 true ns=2;i=314 i=38 false ns=1;i=370 i=38 false ns=1;i=366 i=38 false ns=1;i=15004 false ns=1;i=366 Object_1 0 Default XML Default XML 0 0 0 i=40 false i=76 i=38 true ns=1;i=365 i=39 false ns=1;i=367 0 ns=1;i=367 Variable_2 1 BicycleType BicycleType 0 0 0 i=47 true ns=1;i=341 i=40 false i=69 //xs:element[@name='BicycleType'] i=12 -1 1 1 0 false 0 ns=1;i=370 Object_1 0 Default Binary Default Binary 0 0 0 i=40 false i=76 i=38 true ns=1;i=365 i=39 false ns=1;i=371 0 ns=1;i=371 Variable_2 1 BicycleType BicycleType 0 0 0 i=47 true ns=1;i=353 i=40 false i=69 BicycleType i=12 -1 1 1 0 false 0 ns=1;i=375 Object_1 1 DriverOfTheMonth DriverOfTheMonth 0 0 0 i=47 true ns=1;i=281 i=40 false ns=2;i=341 i=46 false ns=1;i=376 i=46 false ns=1;i=377 0 ns=1;i=376 Variable_2 2 PrimaryVehicle PrimaryVehicle 0 0 0 i=46 true ns=1;i=375 i=40 false i=68 ns=2;i=366 Trek Compact 10 1 Hello ns=2;i=314 -1 3 3 0 false 0 ns=1;i=377 Variable_2 2 OwnedVehicles OwnedVehicles 0 0 0 i=46 true ns=1;i=375 i=40 false i=68 ns=1;i=319 Dodge Ram 500 ns=1;i=318 Porche Roadster 2 ns=2;i=314 1 0 3 3 0 false 0 ns=1;i=378 DataType_64 1 ParkingLotType ParkingLotType 0 0 0 i=45 true i=29 i=46 false ns=1;i=15001 false ns=1;i=380 Variable_2 1 LotType LotType 0 0 0 i=46 true ns=1;i=281 i=40 false i=68 ns=1;i=378 -1 3 3 0 false 0 ns=1;i=15001 Variable_2 0 EnumValues EnumValues 0 0 0 i=46 true ns=1;i=378 i=40 false i=68 i=37 false i=78 i=7616 1 Open i=7616 2 Covered i=7594 1 0 1 1 0 false 0 ns=1;i=15002 Variable_2 0 Deprecated Deprecated 0 0 0 i=46 true ns=1;i=353 i=40 false i=68 true i=1 -1 1 1 0 false 0 ns=1;i=15003 Variable_2 0 Deprecated Deprecated 0 0 0 i=46 true ns=1;i=341 i=40 false i=68 true i=1 -1 1 1 0 false 0 ns=1;i=15004 Object_1 0 Default JSON Default JSON 0 0 0 i=40 false i=76 i=38 true ns=1;i=365 0 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Vehicles/Design/Vehicles.Instances.NodeSet2.xml ================================================  http://opcfoundation.org/UA/Vehicles/Instances http://opcfoundation.org/UA/Vehicles/Types i=1 i=2 i=3 i=4 i=5 i=6 i=7 i=8 i=9 i=10 i=11 i=13 i=12 i=15 i=14 i=16 i=17 i=18 i=20 i=21 i=19 i=22 i=26 i=27 i=28 i=47 i=46 i=35 i=36 i=48 i=45 i=40 i=37 i=38 i=39 ParkingLotType ns=1;i=15001 i=29 EnumValues i=68 i=78 ns=1;i=378 i=7616 1 Open i=7616 2 Covered BicycleType ns=2;i=314 ParkingLot ns=1;i=380 ns=1;i=375 ns=1;i=283 i=85 i=58 LotType i=68 ns=1;i=281 DriverOfTheMonth ns=1;i=376 ns=1;i=377 ns=2;i=341 ns=1;i=281 PrimaryVehicle i=68 ns=1;i=375 ns=1;i=366 Trek Compact 10 1 Hello OwnedVehicles i=68 ns=1;i=375 ns=2;i=319 Dodge Ram 500 ns=2;i=318 Porche Roadster 2 VehiclesInLot i=63 ns=1;i=281 Default Binary ns=1;i=365 ns=1;i=371 i=76 Vehicles.Instances ns=1;i=355 ns=1;i=15002 ns=1;i=371 i=93 i=72 PG9wYzpUeXBlRGljdGlvbmFyeQ0KICB4bWxuczpzMT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3Jn L1VBL1ZlaGljbGVzL1R5cGVzIg0KICB4bWxuczpvcGM9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9y Zy9CaW5hcnlTY2hlbWEvIg0KICB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1M U2NoZW1hLWluc3RhbmNlIg0KICB4bWxuczp1YT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VB LyINCiAgeG1sbnM6dG5zPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvVmVoaWNsZXMvSW5z dGFuY2VzIg0KICBEZWZhdWx0Qnl0ZU9yZGVyPSJMaXR0bGVFbmRpYW4iDQogIFRhcmdldE5hbWVz cGFjZT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VBL1ZlaGljbGVzL0luc3RhbmNlcyINCj4N CiAgPG9wYzpJbXBvcnQgTmFtZXNwYWNlPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvIiBM b2NhdGlvbj0iT3BjLlVhLkJpbmFyeVNjaGVtYS5ic2QiLz4NCiAgPG9wYzpJbXBvcnQgTmFtZXNw YWNlPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvVmVoaWNsZXMvVHlwZXMiIExvY2F0aW9u PSJWZWhpY2xlcy5UeXBlcy5CaW5hcnlTY2hlbWEuYnNkIi8+DQoNCiAgPG9wYzpFbnVtZXJhdGVk VHlwZSBOYW1lPSJQYXJraW5nTG90VHlwZSIgTGVuZ3RoSW5CaXRzPSIzMiI+DQogICAgPG9wYzpF bnVtZXJhdGVkVmFsdWUgTmFtZT0iT3BlbiIgVmFsdWU9IjEiIC8+DQogICAgPG9wYzpFbnVtZXJh dGVkVmFsdWUgTmFtZT0iQ292ZXJlZCIgVmFsdWU9IjIiIC8+DQogIDwvb3BjOkVudW1lcmF0ZWRU eXBlPg0KDQogIDxvcGM6U3RydWN0dXJlZFR5cGUgTmFtZT0iQmljeWNsZVR5cGUiIEJhc2VUeXBl PSJzMTpWZWhpY2xlVHlwZSI+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJNYWtlIiBUeXBlTmFtZT0i b3BjOlN0cmluZyIgU291cmNlVHlwZT0iczE6VmVoaWNsZVR5cGUiIC8+DQogICAgPG9wYzpGaWVs ZCBOYW1lPSJNb2RlbCIgVHlwZU5hbWU9Im9wYzpTdHJpbmciIFNvdXJjZVR5cGU9InMxOlZlaGlj bGVUeXBlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZkdlYXJzIiBUeXBlTmFtZT0ib3Bj OlVJbnQzMiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik1hbnVmYWN0ZXJOYW1lIiBUeXBlTmFt ZT0idWE6UXVhbGlmaWVkTmFtZSIgLz4NCiAgPC9vcGM6U3RydWN0dXJlZFR5cGU+DQoNCjwvb3Bj OlR5cGVEaWN0aW9uYXJ5Pg== NamespaceUri i=68 ns=1;i=353 http://opcfoundation.org/UA/Vehicles/Instances Deprecated i=68 ns=1;i=353 true BicycleType i=69 ns=1;i=353 BicycleType Default XML ns=1;i=365 ns=1;i=367 i=76 Vehicles.Instances ns=1;i=343 ns=1;i=15003 ns=1;i=367 i=92 i=72 PHhzOnNjaGVtYQ0KICB4bWxuczpzMT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VBL1ZlaGlj bGVzL1R5cGVzIg0KICB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEi DQogIHhtbG5zOnVhPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvMjAwOC8wMi9UeXBlcy54 c2QiDQogIHhtbG5zOnRucz0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VBL1ZlaGljbGVzL0lu c3RhbmNlcyINCiAgdGFyZ2V0TmFtZXNwYWNlPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEv VmVoaWNsZXMvSW5zdGFuY2VzIg0KICBlbGVtZW50Rm9ybURlZmF1bHQ9InF1YWxpZmllZCINCj4N CiAgPHhzOmltcG9ydCBuYW1lc3BhY2U9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9yZy9VQS8yMDA4 LzAyL1R5cGVzLnhzZCIgLz4NCiAgPHhzOmltcG9ydCBuYW1lc3BhY2U9Imh0dHA6Ly9vcGNmb3Vu ZGF0aW9uLm9yZy9VQS9WZWhpY2xlcy9UeXBlcyIgLz4NCg0KICA8eHM6c2ltcGxlVHlwZSAgbmFt ZT0iUGFya2luZ0xvdFR5cGUiPg0KICAgIDx4czpyZXN0cmljdGlvbiBiYXNlPSJ4czpzdHJpbmci Pg0KICAgICAgPHhzOmVudW1lcmF0aW9uIHZhbHVlPSJPcGVuXzEiIC8+DQogICAgICA8eHM6ZW51 bWVyYXRpb24gdmFsdWU9IkNvdmVyZWRfMiIgLz4NCiAgICA8L3hzOnJlc3RyaWN0aW9uPg0KICA8 L3hzOnNpbXBsZVR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9IlBhcmtpbmdMb3RUeXBlIiB0eXBl PSJ0bnM6UGFya2luZ0xvdFR5cGUiIC8+DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9Ikxpc3RP ZlBhcmtpbmdMb3RUeXBlIj4NCiAgICA8eHM6c2VxdWVuY2U+DQogICAgICA8eHM6ZWxlbWVudCBu YW1lPSJQYXJraW5nTG90VHlwZSIgdHlwZT0idG5zOlBhcmtpbmdMb3RUeXBlIiBtaW5PY2N1cnM9 IjAiIG1heE9jY3Vycz0idW5ib3VuZGVkIiAvPg0KICAgIDwveHM6c2VxdWVuY2U+DQogIDwveHM6 Y29tcGxleFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9Ikxpc3RPZlBhcmtpbmdMb3RUeXBlIiB0 eXBlPSJ0bnM6TGlzdE9mUGFya2luZ0xvdFR5cGUiIG5pbGxhYmxlPSJ0cnVlIj48L3hzOmVsZW1l bnQ+DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9IkJpY3ljbGVUeXBlIj4NCiAgICA8eHM6Y29t cGxleENvbnRlbnQgbWl4ZWQ9ImZhbHNlIj4NCiAgICAgIDx4czpleHRlbnNpb24gYmFzZT0iczE6 VmVoaWNsZVR5cGUiPg0KICAgICAgICA8eHM6c2VxdWVuY2U+DQogICAgICAgICAgPHhzOmVsZW1l bnQgbmFtZT0iTm9PZkdlYXJzIiB0eXBlPSJ4czp1bnNpZ25lZEludCIgbWluT2NjdXJzPSIwIiAv Pg0KICAgICAgICAgIDx4czplbGVtZW50IG5hbWU9Ik1hbnVmYWN0ZXJOYW1lIiB0eXBlPSJ1YTpR dWFsaWZpZWROYW1lIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgICA8 L3hzOnNlcXVlbmNlPg0KICAgICAgPC94czpleHRlbnNpb24+DQogICAgPC94czpjb21wbGV4Q29u dGVudD4NCiAgPC94czpjb21wbGV4VHlwZT4NCiAgPHhzOmVsZW1lbnQgbmFtZT0iQmljeWNsZVR5 cGUiIHR5cGU9InRuczpCaWN5Y2xlVHlwZSIgLz4NCg0KICA8eHM6Y29tcGxleFR5cGUgbmFtZT0i TGlzdE9mQmljeWNsZVR5cGUiPg0KICAgIDx4czpzZXF1ZW5jZT4NCiAgICAgIDx4czplbGVtZW50 IG5hbWU9IkJpY3ljbGVUeXBlIiB0eXBlPSJ0bnM6QmljeWNsZVR5cGUiIG1pbk9jY3Vycz0iMCIg bWF4T2NjdXJzPSJ1bmJvdW5kZWQiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgIDwveHM6c2VxdWVu Y2U+DQogIDwveHM6Y29tcGxleFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9Ikxpc3RPZkJpY3lj bGVUeXBlIiB0eXBlPSJ0bnM6TGlzdE9mQmljeWNsZVR5cGUiIG5pbGxhYmxlPSJ0cnVlIj48L3hz OmVsZW1lbnQ+DQoNCjwveHM6c2NoZW1hPg== NamespaceUri i=68 ns=1;i=341 http://opcfoundation.org/UA/Vehicles/Instances Deprecated i=68 ns=1;i=341 true BicycleType i=69 ns=1;i=341 //xs:element[@name='BicycleType'] Default JSON ns=1;i=365 i=76 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Vehicles/Design/Vehicles.Instances.PredefinedNodes.xml ================================================  http://opcfoundation.org/UA/Vehicles/Types http://opcfoundation.org/UA/Vehicles/Instances DataType_64 ns=2;i=378 2 ParkingLotType i=29 i=14799 1 Open Open 2 Covered Covered Variable_2 ns=2;i=15001 0 EnumValues i=46 i=68 i=78 15001 i=7616 1 Open i=7616 2 Covered i=7594 1 0 1 1 DataType_64 ns=2;i=365 2 BicycleType ns=1;i=314 i=14798 ns=1;i=314 Structure_0 Make i=12 -1 0 false Model i=12 -1 0 false NoOfGears i=7 -1 0 false ManufacterName i=20 -1 0 false Object_1 ns=2;i=281 2 ParkingLot i=47 i=58 281 i=35 true i=85 Variable_2 ns=2;i=380 2 LotType i=46 i=68 380 ns=2;i=378 -1 3 3 Object_1 ns=2;i=375 2 DriverOfTheMonth i=47 ns=1;i=341 375 Variable_2 ns=2;i=376 1 PrimaryVehicle i=46 i=68 376 ns=2;i=366 Trek Compact 10 1 Hello ns=1;i=314 -1 3 3 Variable_2 ns=2;i=377 1 OwnedVehicles i=46 i=68 377 ns=1;i=319 Dodge Ram 500 ns=1;i=318 Porche Roadster 2 ns=1;i=314 1 0 3 3 Variable_2 ns=2;i=283 2 VehiclesInLot i=47 i=63 283 ns=1;i=314 1 0 3 3 Object_1 ns=2;i=370 0 Default Binary i=76 370 i=38 true ns=2;i=365 i=39 ns=2;i=371 Variable_2 ns=2;i=353 2 Vehicles.Instances i=72 353 PG9wYzpUeXBlRGljdGlvbmFyeQ0KICB4bWxuczpzMT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3Jn L1VBL1ZlaGljbGVzL1R5cGVzIg0KICB4bWxuczpvcGM9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9y Zy9CaW5hcnlTY2hlbWEvIg0KICB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1M U2NoZW1hLWluc3RhbmNlIg0KICB4bWxuczp1YT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VB LyINCiAgeG1sbnM6dG5zPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvVmVoaWNsZXMvSW5z dGFuY2VzIg0KICBEZWZhdWx0Qnl0ZU9yZGVyPSJMaXR0bGVFbmRpYW4iDQogIFRhcmdldE5hbWVz cGFjZT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VBL1ZlaGljbGVzL0luc3RhbmNlcyINCj4N CiAgPG9wYzpJbXBvcnQgTmFtZXNwYWNlPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvIiBM b2NhdGlvbj0iT3BjLlVhLkJpbmFyeVNjaGVtYS5ic2QiLz4NCiAgPG9wYzpJbXBvcnQgTmFtZXNw YWNlPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvVmVoaWNsZXMvVHlwZXMiIExvY2F0aW9u PSJWZWhpY2xlcy5UeXBlcy5CaW5hcnlTY2hlbWEuYnNkIi8+DQoNCiAgPG9wYzpFbnVtZXJhdGVk VHlwZSBOYW1lPSJQYXJraW5nTG90VHlwZSIgTGVuZ3RoSW5CaXRzPSIzMiI+DQogICAgPG9wYzpF bnVtZXJhdGVkVmFsdWUgTmFtZT0iT3BlbiIgVmFsdWU9IjEiIC8+DQogICAgPG9wYzpFbnVtZXJh dGVkVmFsdWUgTmFtZT0iQ292ZXJlZCIgVmFsdWU9IjIiIC8+DQogIDwvb3BjOkVudW1lcmF0ZWRU eXBlPg0KDQogIDxvcGM6U3RydWN0dXJlZFR5cGUgTmFtZT0iQmljeWNsZVR5cGUiIEJhc2VUeXBl PSJzMTpWZWhpY2xlVHlwZSI+DQogICAgPG9wYzpGaWVsZCBOYW1lPSJNYWtlIiBUeXBlTmFtZT0i b3BjOlN0cmluZyIgU291cmNlVHlwZT0iczE6VmVoaWNsZVR5cGUiIC8+DQogICAgPG9wYzpGaWVs ZCBOYW1lPSJNb2RlbCIgVHlwZU5hbWU9Im9wYzpTdHJpbmciIFNvdXJjZVR5cGU9InMxOlZlaGlj bGVUeXBlIiAvPg0KICAgIDxvcGM6RmllbGQgTmFtZT0iTm9PZkdlYXJzIiBUeXBlTmFtZT0ib3Bj OlVJbnQzMiIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik1hbnVmYWN0ZXJOYW1lIiBUeXBlTmFt ZT0idWE6UXVhbGlmaWVkTmFtZSIgLz4NCiAgPC9vcGM6U3RydWN0dXJlZFR5cGU+DQoNCjwvb3Bj OlR5cGVEaWN0aW9uYXJ5Pg== i=15 -1 1 1 i=47 true i=93 Variable_2 ns=2;i=355 0 NamespaceUri i=46 i=68 355 http://opcfoundation.org/UA/Vehicles/Instances i=12 -1 1 1 Variable_2 ns=2;i=15002 0 Deprecated i=46 i=68 15002 true i=1 -1 1 1 Variable_2 ns=2;i=371 2 BicycleType i=47 i=69 371 BicycleType i=12 -1 1 1 Object_1 ns=2;i=366 0 Default XML i=76 366 i=38 true ns=2;i=365 i=39 ns=2;i=367 Variable_2 ns=2;i=341 2 Vehicles.Instances i=72 341 PHhzOnNjaGVtYQ0KICB4bWxuczpzMT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VBL1ZlaGlj bGVzL1R5cGVzIg0KICB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEi DQogIHhtbG5zOnVhPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvMjAwOC8wMi9UeXBlcy54 c2QiDQogIHhtbG5zOnRucz0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VBL1ZlaGljbGVzL0lu c3RhbmNlcyINCiAgdGFyZ2V0TmFtZXNwYWNlPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEv VmVoaWNsZXMvSW5zdGFuY2VzIg0KICBlbGVtZW50Rm9ybURlZmF1bHQ9InF1YWxpZmllZCINCj4N CiAgPHhzOmltcG9ydCBuYW1lc3BhY2U9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9yZy9VQS8yMDA4 LzAyL1R5cGVzLnhzZCIgLz4NCiAgPHhzOmltcG9ydCBuYW1lc3BhY2U9Imh0dHA6Ly9vcGNmb3Vu ZGF0aW9uLm9yZy9VQS9WZWhpY2xlcy9UeXBlcyIgLz4NCg0KICA8eHM6c2ltcGxlVHlwZSAgbmFt ZT0iUGFya2luZ0xvdFR5cGUiPg0KICAgIDx4czpyZXN0cmljdGlvbiBiYXNlPSJ4czpzdHJpbmci Pg0KICAgICAgPHhzOmVudW1lcmF0aW9uIHZhbHVlPSJPcGVuXzEiIC8+DQogICAgICA8eHM6ZW51 bWVyYXRpb24gdmFsdWU9IkNvdmVyZWRfMiIgLz4NCiAgICA8L3hzOnJlc3RyaWN0aW9uPg0KICA8 L3hzOnNpbXBsZVR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9IlBhcmtpbmdMb3RUeXBlIiB0eXBl PSJ0bnM6UGFya2luZ0xvdFR5cGUiIC8+DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9Ikxpc3RP ZlBhcmtpbmdMb3RUeXBlIj4NCiAgICA8eHM6c2VxdWVuY2U+DQogICAgICA8eHM6ZWxlbWVudCBu YW1lPSJQYXJraW5nTG90VHlwZSIgdHlwZT0idG5zOlBhcmtpbmdMb3RUeXBlIiBtaW5PY2N1cnM9 IjAiIG1heE9jY3Vycz0idW5ib3VuZGVkIiAvPg0KICAgIDwveHM6c2VxdWVuY2U+DQogIDwveHM6 Y29tcGxleFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9Ikxpc3RPZlBhcmtpbmdMb3RUeXBlIiB0 eXBlPSJ0bnM6TGlzdE9mUGFya2luZ0xvdFR5cGUiIG5pbGxhYmxlPSJ0cnVlIj48L3hzOmVsZW1l bnQ+DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9IkJpY3ljbGVUeXBlIj4NCiAgICA8eHM6Y29t cGxleENvbnRlbnQgbWl4ZWQ9ImZhbHNlIj4NCiAgICAgIDx4czpleHRlbnNpb24gYmFzZT0iczE6 VmVoaWNsZVR5cGUiPg0KICAgICAgICA8eHM6c2VxdWVuY2U+DQogICAgICAgICAgPHhzOmVsZW1l bnQgbmFtZT0iTm9PZkdlYXJzIiB0eXBlPSJ4czp1bnNpZ25lZEludCIgbWluT2NjdXJzPSIwIiAv Pg0KICAgICAgICAgIDx4czplbGVtZW50IG5hbWU9Ik1hbnVmYWN0ZXJOYW1lIiB0eXBlPSJ1YTpR dWFsaWZpZWROYW1lIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgICAgICA8 L3hzOnNlcXVlbmNlPg0KICAgICAgPC94czpleHRlbnNpb24+DQogICAgPC94czpjb21wbGV4Q29u dGVudD4NCiAgPC94czpjb21wbGV4VHlwZT4NCiAgPHhzOmVsZW1lbnQgbmFtZT0iQmljeWNsZVR5 cGUiIHR5cGU9InRuczpCaWN5Y2xlVHlwZSIgLz4NCg0KICA8eHM6Y29tcGxleFR5cGUgbmFtZT0i TGlzdE9mQmljeWNsZVR5cGUiPg0KICAgIDx4czpzZXF1ZW5jZT4NCiAgICAgIDx4czplbGVtZW50 IG5hbWU9IkJpY3ljbGVUeXBlIiB0eXBlPSJ0bnM6QmljeWNsZVR5cGUiIG1pbk9jY3Vycz0iMCIg bWF4T2NjdXJzPSJ1bmJvdW5kZWQiIG5pbGxhYmxlPSJ0cnVlIiAvPg0KICAgIDwveHM6c2VxdWVu Y2U+DQogIDwveHM6Y29tcGxleFR5cGU+DQogIDx4czplbGVtZW50IG5hbWU9Ikxpc3RPZkJpY3lj bGVUeXBlIiB0eXBlPSJ0bnM6TGlzdE9mQmljeWNsZVR5cGUiIG5pbGxhYmxlPSJ0cnVlIj48L3hz OmVsZW1lbnQ+DQoNCjwveHM6c2NoZW1hPg== i=15 -1 1 1 i=47 true i=92 Variable_2 ns=2;i=343 0 NamespaceUri i=46 i=68 343 http://opcfoundation.org/UA/Vehicles/Instances i=12 -1 1 1 Variable_2 ns=2;i=15003 0 Deprecated i=46 i=68 15003 true i=1 -1 1 1 Variable_2 ns=2;i=367 2 BicycleType i=47 i=69 367 //xs:element[@name='BicycleType'] i=12 -1 1 1 Object_1 ns=2;i=15004 0 Default JSON i=76 15004 i=38 true ns=2;i=365 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Vehicles/Design/Vehicles.Instances.Types.bsd ================================================ ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Vehicles/Design/Vehicles.Instances.Types.xsd ================================================ ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Vehicles/Design/Vehicles.Types.Classes.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; using System; using System.Collections.Generic; namespace Vehicles.Types { #region DriverState Class #if (!OPCUA_EXCLUDE_DriverState) /// /// Stores an instance of the DriverType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class DriverState : BaseObjectState { #region Constructors /// /// Initializes the type with its default attribute values. /// public DriverState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(Vehicles.Types.ObjectTypes.DriverType, Vehicles.Types.Namespaces.Vehicles, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AQAAACoAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvVmVoaWNsZXMvVHlwZXP/////BGCAAgEA" + "AAABABIAAABEcml2ZXJUeXBlSW5zdGFuY2UBAVUBAQFVAVUBAAD/////AgAAABVgqQoCAAAAAQAOAAAA" + "UHJpbWFyeVZlaGljbGUBAVYBAC4ARFYBAAAWAQE+AQKPAAAAPENhclR5cGUgeG1sbnM9Imh0dHA6Ly9v" + "cGNmb3VuZGF0aW9uLm9yZy9VQS9WZWhpY2xlcy9UeXBlcyI+PE1ha2U+VG95b3RhPC9NYWtlPjxNb2Rl" + "bD5Qcml1czwvTW9kZWw+PE5vT2ZQYXNzZW5nZXJzPjQ8L05vT2ZQYXNzZW5nZXJzPjwvQ2FyVHlwZT4B" + "AToB/////wMD/////wAAAAAXYKkKAgAAAAEADQAAAE93bmVkVmVoaWNsZXMBAVgBAC4ARFgBAACWAgAA" + "AAEBPwECkAAAADxUcnVja1R5cGUgeG1sbnM9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9yZy9VQS9WZWhp" + "Y2xlcy9UeXBlcyI+PE1ha2U+RG9kZ2U8L01ha2U+PE1vZGVsPlJhbTwvTW9kZWw+PENhcmdvQ2FwYWNp" + "dHk+NTAwPC9DYXJnb0NhcGFjaXR5PjwvVHJ1Y2tUeXBlPgEBPgEC4wAAADxWZWhpY2xlVHlwZSB4c2k6" + "dHlwZT0iQ2FyVHlwZSIgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1p" + "bnN0YW5jZSIgeG1sbnM9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9yZy9VQS9WZWhpY2xlcy9UeXBlcyI+" + "PE1ha2U+UG9yY2hlPC9NYWtlPjxNb2RlbD5Sb2Fkc3RlcjwvTW9kZWw+PE5vT2ZQYXNzZW5nZXJzPjI8" + "L05vT2ZQYXNzZW5nZXJzPjwvVmVoaWNsZVR5cGU+AQE6AQEAAAABAAAAAAAAAAMD/////wAAAAA="; #endregion #endif #endregion #region Public Properties /// public PropertyState PrimaryVehicle { get { return m_primaryVehicle; } set { if (!Object.ReferenceEquals(m_primaryVehicle, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_primaryVehicle = value; } } /// public PropertyState OwnedVehicles { get { return m_ownedVehicles; } set { if (!Object.ReferenceEquals(m_ownedVehicles, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_ownedVehicles = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_primaryVehicle != null) { children.Add(m_primaryVehicle); } if (m_ownedVehicles != null) { children.Add(m_ownedVehicles); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case Vehicles.Types.BrowseNames.PrimaryVehicle: { if (createOrReplace) { if (PrimaryVehicle == null) { if (replacement == null) { PrimaryVehicle = new PropertyState(this); } else { PrimaryVehicle = (PropertyState)replacement; } } } instance = PrimaryVehicle; break; } case Vehicles.Types.BrowseNames.OwnedVehicles: { if (createOrReplace) { if (OwnedVehicles == null) { if (replacement == null) { OwnedVehicles = new PropertyState(this); } else { OwnedVehicles = (PropertyState)replacement; } } } instance = OwnedVehicles; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private PropertyState m_primaryVehicle; private PropertyState m_ownedVehicles; #endregion } #endif #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Vehicles/Design/Vehicles.Types.Constants.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; namespace Vehicles.Types { #region DataType Identifiers /// /// A class that declares constants for all DataTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class DataTypes { /// /// The identifier for the VehicleType DataType. /// public const uint VehicleType = 314; /// /// The identifier for the CarType DataType. /// public const uint CarType = 315; /// /// The identifier for the TruckType DataType. /// public const uint TruckType = 316; } #endregion #region Object Identifiers /// /// A class that declares constants for all Objects in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Objects { /// /// The identifier for the VehicleType_Encoding_DefaultBinary Object. /// public const uint VehicleType_Encoding_DefaultBinary = 329; /// /// The identifier for the CarType_Encoding_DefaultBinary Object. /// public const uint CarType_Encoding_DefaultBinary = 330; /// /// The identifier for the TruckType_Encoding_DefaultBinary Object. /// public const uint TruckType_Encoding_DefaultBinary = 331; /// /// The identifier for the VehicleType_Encoding_DefaultXml Object. /// public const uint VehicleType_Encoding_DefaultXml = 317; /// /// The identifier for the CarType_Encoding_DefaultXml Object. /// public const uint CarType_Encoding_DefaultXml = 318; /// /// The identifier for the TruckType_Encoding_DefaultXml Object. /// public const uint TruckType_Encoding_DefaultXml = 319; /// /// The identifier for the VehicleType_Encoding_DefaultJson Object. /// public const uint VehicleType_Encoding_DefaultJson = 15003; /// /// The identifier for the CarType_Encoding_DefaultJson Object. /// public const uint CarType_Encoding_DefaultJson = 15004; /// /// The identifier for the TruckType_Encoding_DefaultJson Object. /// public const uint TruckType_Encoding_DefaultJson = 15005; } #endregion #region ObjectType Identifiers /// /// A class that declares constants for all ObjectTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectTypes { /// /// The identifier for the DriverType ObjectType. /// public const uint DriverType = 341; } #endregion #region Variable Identifiers /// /// A class that declares constants for all Variables in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Variables { /// /// The identifier for the DriverType_PrimaryVehicle Variable. /// public const uint DriverType_PrimaryVehicle = 342; /// /// The identifier for the DriverType_OwnedVehicles Variable. /// public const uint DriverType_OwnedVehicles = 344; /// /// The identifier for the Vehicles_BinarySchema Variable. /// public const uint Vehicles_BinarySchema = 302; /// /// The identifier for the Vehicles_BinarySchema_NamespaceUri Variable. /// public const uint Vehicles_BinarySchema_NamespaceUri = 304; /// /// The identifier for the Vehicles_BinarySchema_Deprecated Variable. /// public const uint Vehicles_BinarySchema_Deprecated = 15001; /// /// The identifier for the Vehicles_BinarySchema_VehicleType Variable. /// public const uint Vehicles_BinarySchema_VehicleType = 332; /// /// The identifier for the Vehicles_BinarySchema_CarType Variable. /// public const uint Vehicles_BinarySchema_CarType = 335; /// /// The identifier for the Vehicles_BinarySchema_TruckType Variable. /// public const uint Vehicles_BinarySchema_TruckType = 338; /// /// The identifier for the Vehicles_XmlSchema Variable. /// public const uint Vehicles_XmlSchema = 287; /// /// The identifier for the Vehicles_XmlSchema_NamespaceUri Variable. /// public const uint Vehicles_XmlSchema_NamespaceUri = 289; /// /// The identifier for the Vehicles_XmlSchema_Deprecated Variable. /// public const uint Vehicles_XmlSchema_Deprecated = 15002; /// /// The identifier for the Vehicles_XmlSchema_VehicleType Variable. /// public const uint Vehicles_XmlSchema_VehicleType = 320; /// /// The identifier for the Vehicles_XmlSchema_CarType Variable. /// public const uint Vehicles_XmlSchema_CarType = 323; /// /// The identifier for the Vehicles_XmlSchema_TruckType Variable. /// public const uint Vehicles_XmlSchema_TruckType = 326; } #endregion #region DataType Node Identifiers /// /// A class that declares constants for all DataTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class DataTypeIds { /// /// The identifier for the VehicleType DataType. /// public static readonly ExpandedNodeId VehicleType = new ExpandedNodeId(Vehicles.Types.DataTypes.VehicleType, Vehicles.Types.Namespaces.Vehicles); /// /// The identifier for the CarType DataType. /// public static readonly ExpandedNodeId CarType = new ExpandedNodeId(Vehicles.Types.DataTypes.CarType, Vehicles.Types.Namespaces.Vehicles); /// /// The identifier for the TruckType DataType. /// public static readonly ExpandedNodeId TruckType = new ExpandedNodeId(Vehicles.Types.DataTypes.TruckType, Vehicles.Types.Namespaces.Vehicles); } #endregion #region Object Node Identifiers /// /// A class that declares constants for all Objects in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectIds { /// /// The identifier for the VehicleType_Encoding_DefaultBinary Object. /// public static readonly ExpandedNodeId VehicleType_Encoding_DefaultBinary = new ExpandedNodeId(Vehicles.Types.Objects.VehicleType_Encoding_DefaultBinary, Vehicles.Types.Namespaces.Vehicles); /// /// The identifier for the CarType_Encoding_DefaultBinary Object. /// public static readonly ExpandedNodeId CarType_Encoding_DefaultBinary = new ExpandedNodeId(Vehicles.Types.Objects.CarType_Encoding_DefaultBinary, Vehicles.Types.Namespaces.Vehicles); /// /// The identifier for the TruckType_Encoding_DefaultBinary Object. /// public static readonly ExpandedNodeId TruckType_Encoding_DefaultBinary = new ExpandedNodeId(Vehicles.Types.Objects.TruckType_Encoding_DefaultBinary, Vehicles.Types.Namespaces.Vehicles); /// /// The identifier for the VehicleType_Encoding_DefaultXml Object. /// public static readonly ExpandedNodeId VehicleType_Encoding_DefaultXml = new ExpandedNodeId(Vehicles.Types.Objects.VehicleType_Encoding_DefaultXml, Vehicles.Types.Namespaces.Vehicles); /// /// The identifier for the CarType_Encoding_DefaultXml Object. /// public static readonly ExpandedNodeId CarType_Encoding_DefaultXml = new ExpandedNodeId(Vehicles.Types.Objects.CarType_Encoding_DefaultXml, Vehicles.Types.Namespaces.Vehicles); /// /// The identifier for the TruckType_Encoding_DefaultXml Object. /// public static readonly ExpandedNodeId TruckType_Encoding_DefaultXml = new ExpandedNodeId(Vehicles.Types.Objects.TruckType_Encoding_DefaultXml, Vehicles.Types.Namespaces.Vehicles); /// /// The identifier for the VehicleType_Encoding_DefaultJson Object. /// public static readonly ExpandedNodeId VehicleType_Encoding_DefaultJson = new ExpandedNodeId(Vehicles.Types.Objects.VehicleType_Encoding_DefaultJson, Vehicles.Types.Namespaces.Vehicles); /// /// The identifier for the CarType_Encoding_DefaultJson Object. /// public static readonly ExpandedNodeId CarType_Encoding_DefaultJson = new ExpandedNodeId(Vehicles.Types.Objects.CarType_Encoding_DefaultJson, Vehicles.Types.Namespaces.Vehicles); /// /// The identifier for the TruckType_Encoding_DefaultJson Object. /// public static readonly ExpandedNodeId TruckType_Encoding_DefaultJson = new ExpandedNodeId(Vehicles.Types.Objects.TruckType_Encoding_DefaultJson, Vehicles.Types.Namespaces.Vehicles); } #endregion #region ObjectType Node Identifiers /// /// A class that declares constants for all ObjectTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectTypeIds { /// /// The identifier for the DriverType ObjectType. /// public static readonly ExpandedNodeId DriverType = new ExpandedNodeId(Vehicles.Types.ObjectTypes.DriverType, Vehicles.Types.Namespaces.Vehicles); } #endregion #region Variable Node Identifiers /// /// A class that declares constants for all Variables in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class VariableIds { /// /// The identifier for the DriverType_PrimaryVehicle Variable. /// public static readonly ExpandedNodeId DriverType_PrimaryVehicle = new ExpandedNodeId(Vehicles.Types.Variables.DriverType_PrimaryVehicle, Vehicles.Types.Namespaces.Vehicles); /// /// The identifier for the DriverType_OwnedVehicles Variable. /// public static readonly ExpandedNodeId DriverType_OwnedVehicles = new ExpandedNodeId(Vehicles.Types.Variables.DriverType_OwnedVehicles, Vehicles.Types.Namespaces.Vehicles); /// /// The identifier for the Vehicles_BinarySchema Variable. /// public static readonly ExpandedNodeId Vehicles_BinarySchema = new ExpandedNodeId(Vehicles.Types.Variables.Vehicles_BinarySchema, Vehicles.Types.Namespaces.Vehicles); /// /// The identifier for the Vehicles_BinarySchema_NamespaceUri Variable. /// public static readonly ExpandedNodeId Vehicles_BinarySchema_NamespaceUri = new ExpandedNodeId(Vehicles.Types.Variables.Vehicles_BinarySchema_NamespaceUri, Vehicles.Types.Namespaces.Vehicles); /// /// The identifier for the Vehicles_BinarySchema_Deprecated Variable. /// public static readonly ExpandedNodeId Vehicles_BinarySchema_Deprecated = new ExpandedNodeId(Vehicles.Types.Variables.Vehicles_BinarySchema_Deprecated, Vehicles.Types.Namespaces.Vehicles); /// /// The identifier for the Vehicles_BinarySchema_VehicleType Variable. /// public static readonly ExpandedNodeId Vehicles_BinarySchema_VehicleType = new ExpandedNodeId(Vehicles.Types.Variables.Vehicles_BinarySchema_VehicleType, Vehicles.Types.Namespaces.Vehicles); /// /// The identifier for the Vehicles_BinarySchema_CarType Variable. /// public static readonly ExpandedNodeId Vehicles_BinarySchema_CarType = new ExpandedNodeId(Vehicles.Types.Variables.Vehicles_BinarySchema_CarType, Vehicles.Types.Namespaces.Vehicles); /// /// The identifier for the Vehicles_BinarySchema_TruckType Variable. /// public static readonly ExpandedNodeId Vehicles_BinarySchema_TruckType = new ExpandedNodeId(Vehicles.Types.Variables.Vehicles_BinarySchema_TruckType, Vehicles.Types.Namespaces.Vehicles); /// /// The identifier for the Vehicles_XmlSchema Variable. /// public static readonly ExpandedNodeId Vehicles_XmlSchema = new ExpandedNodeId(Vehicles.Types.Variables.Vehicles_XmlSchema, Vehicles.Types.Namespaces.Vehicles); /// /// The identifier for the Vehicles_XmlSchema_NamespaceUri Variable. /// public static readonly ExpandedNodeId Vehicles_XmlSchema_NamespaceUri = new ExpandedNodeId(Vehicles.Types.Variables.Vehicles_XmlSchema_NamespaceUri, Vehicles.Types.Namespaces.Vehicles); /// /// The identifier for the Vehicles_XmlSchema_Deprecated Variable. /// public static readonly ExpandedNodeId Vehicles_XmlSchema_Deprecated = new ExpandedNodeId(Vehicles.Types.Variables.Vehicles_XmlSchema_Deprecated, Vehicles.Types.Namespaces.Vehicles); /// /// The identifier for the Vehicles_XmlSchema_VehicleType Variable. /// public static readonly ExpandedNodeId Vehicles_XmlSchema_VehicleType = new ExpandedNodeId(Vehicles.Types.Variables.Vehicles_XmlSchema_VehicleType, Vehicles.Types.Namespaces.Vehicles); /// /// The identifier for the Vehicles_XmlSchema_CarType Variable. /// public static readonly ExpandedNodeId Vehicles_XmlSchema_CarType = new ExpandedNodeId(Vehicles.Types.Variables.Vehicles_XmlSchema_CarType, Vehicles.Types.Namespaces.Vehicles); /// /// The identifier for the Vehicles_XmlSchema_TruckType Variable. /// public static readonly ExpandedNodeId Vehicles_XmlSchema_TruckType = new ExpandedNodeId(Vehicles.Types.Variables.Vehicles_XmlSchema_TruckType, Vehicles.Types.Namespaces.Vehicles); } #endregion #region BrowseName Declarations /// /// Declares all of the BrowseNames used in the Model Design. /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class BrowseNames { /// /// The BrowseName for the CarType component. /// public const string CarType = "CarType"; /// /// The BrowseName for the DriverType component. /// public const string DriverType = "DriverType"; /// /// The BrowseName for the OwnedVehicles component. /// public const string OwnedVehicles = "OwnedVehicles"; /// /// The BrowseName for the PrimaryVehicle component. /// public const string PrimaryVehicle = "PrimaryVehicle"; /// /// The BrowseName for the TruckType component. /// public const string TruckType = "TruckType"; /// /// The BrowseName for the Vehicles_BinarySchema component. /// public const string Vehicles_BinarySchema = "Vehicles.Types"; /// /// The BrowseName for the Vehicles_XmlSchema component. /// public const string Vehicles_XmlSchema = "Vehicles.Types"; /// /// The BrowseName for the VehicleType component. /// public const string VehicleType = "VehicleType"; } #endregion #region Namespace Declarations /// /// Defines constants for all namespaces referenced by the model design. /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Namespaces { /// /// The URI for the OpcUa namespace (.NET code namespace is 'Opc.Ua'). /// public const string OpcUa = "http://opcfoundation.org/UA/"; /// /// The URI for the OpcUaXsd namespace (.NET code namespace is 'Opc.Ua'). /// public const string OpcUaXsd = "http://opcfoundation.org/UA/2008/02/Types.xsd"; /// /// The URI for the Vehicles namespace (.NET code namespace is 'Vehicles.Types'). /// public const string Vehicles = "http://opcfoundation.org/UA/Vehicles/Types"; } #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Vehicles/Design/Vehicles.Types.DataTypes.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; using System; using System.Collections.Generic; using System.Runtime.Serialization; namespace Vehicles.Types { #region VehicleType Class #if (!OPCUA_EXCLUDE_VehicleType) /// /// /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = Vehicles.Types.Namespaces.Vehicles)] public partial class VehicleType : IEncodeable { #region Constructors /// /// The default constructor. /// public VehicleType() { Initialize(); } /// /// Called by the .NET framework during deserialization. /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { m_make = null; m_model = null; } #endregion #region Public Properties /// [DataMember(Name = "Make", IsRequired = false, Order = 1)] public string Make { get { return m_make; } set { m_make = value; } } /// [DataMember(Name = "Model", IsRequired = false, Order = 2)] public string Model { get { return m_model; } set { m_model = value; } } #endregion #region IEncodeable Members /// public virtual ExpandedNodeId TypeId { get { return DataTypeIds.VehicleType; } } /// public virtual ExpandedNodeId BinaryEncodingId { get { return ObjectIds.VehicleType_Encoding_DefaultBinary; } } /// public virtual ExpandedNodeId XmlEncodingId { get { return ObjectIds.VehicleType_Encoding_DefaultXml; } } /// public virtual void Encode(IEncoder encoder) { encoder.PushNamespace(Vehicles.Types.Namespaces.Vehicles); encoder.WriteString("Make", Make); encoder.WriteString("Model", Model); encoder.PopNamespace(); } /// public virtual void Decode(IDecoder decoder) { decoder.PushNamespace(Vehicles.Types.Namespaces.Vehicles); Make = decoder.ReadString("Make"); Model = decoder.ReadString("Model"); decoder.PopNamespace(); } /// public virtual bool IsEqual(IEncodeable encodeable) { if (Object.ReferenceEquals(this, encodeable)) { return true; } VehicleType value = encodeable as VehicleType; if (value == null) { return false; } if (!Utils.IsEqual(m_make, value.m_make)) return false; if (!Utils.IsEqual(m_model, value.m_model)) return false; return true; } #if !NET_STANDARD /// public virtual object Clone() { return (VehicleType)this.MemberwiseClone(); } #endif /// public new object MemberwiseClone() { VehicleType clone = (VehicleType)base.MemberwiseClone(); clone.m_make = (string)Utils.Clone(this.m_make); clone.m_model = (string)Utils.Clone(this.m_model); return clone; } #endregion #region Private Fields private string m_make; private string m_model; #endregion } #region VehicleTypeCollection Class /// /// A collection of VehicleType objects. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfVehicleType", Namespace = Vehicles.Types.Namespaces.Vehicles, ItemName = "VehicleType")] #if !NET_STANDARD public partial class VehicleTypeCollection : List, ICloneable #else public partial class VehicleTypeCollection : List #endif { #region Constructors /// /// Initializes the collection with default values. /// public VehicleTypeCollection() { } /// /// Initializes the collection with an initial capacity. /// public VehicleTypeCollection(int capacity) : base(capacity) { } /// /// Initializes the collection with another collection. /// public VehicleTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// /// Converts an array to a collection. /// public static implicit operator VehicleTypeCollection(VehicleType[] values) { if (values != null) { return new VehicleTypeCollection(values); } return new VehicleTypeCollection(); } /// /// Converts a collection to an array. /// public static explicit operator VehicleType[](VehicleTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #if !NET_STANDARD #region ICloneable Methods /// /// Creates a deep copy of the collection. /// public object Clone() { return (VehicleTypeCollection)this.MemberwiseClone(); } #endregion #endif /// public new object MemberwiseClone() { VehicleTypeCollection clone = new VehicleTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((VehicleType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion #region CarType Class #if (!OPCUA_EXCLUDE_CarType) /// /// /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = Vehicles.Types.Namespaces.Vehicles)] public partial class CarType : VehicleType { #region Constructors /// /// The default constructor. /// public CarType() { Initialize(); } /// /// Called by the .NET framework during deserialization. /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { m_noOfPassengers = (uint)0; } #endregion #region Public Properties /// [DataMember(Name = "NoOfPassengers", IsRequired = false, Order = 1)] public uint NoOfPassengers { get { return m_noOfPassengers; } set { m_noOfPassengers = value; } } #endregion #region IEncodeable Members /// public override ExpandedNodeId TypeId { get { return DataTypeIds.CarType; } } /// public override ExpandedNodeId BinaryEncodingId { get { return ObjectIds.CarType_Encoding_DefaultBinary; } } /// public override ExpandedNodeId XmlEncodingId { get { return ObjectIds.CarType_Encoding_DefaultXml; } } /// public override void Encode(IEncoder encoder) { base.Encode(encoder); encoder.PushNamespace(Vehicles.Types.Namespaces.Vehicles); encoder.WriteUInt32("NoOfPassengers", NoOfPassengers); encoder.PopNamespace(); } /// public override void Decode(IDecoder decoder) { base.Decode(decoder); decoder.PushNamespace(Vehicles.Types.Namespaces.Vehicles); NoOfPassengers = decoder.ReadUInt32("NoOfPassengers"); decoder.PopNamespace(); } /// public override bool IsEqual(IEncodeable encodeable) { if (Object.ReferenceEquals(this, encodeable)) { return true; } CarType value = encodeable as CarType; if (value == null) { return false; } if (!base.IsEqual(encodeable)) return false; if (!Utils.IsEqual(m_noOfPassengers, value.m_noOfPassengers)) return false; return true; } #if !NET_STANDARD /// public override object Clone() { return (CarType)this.MemberwiseClone(); } #endif /// public new object MemberwiseClone() { CarType clone = (CarType)base.MemberwiseClone(); clone.m_noOfPassengers = (uint)Utils.Clone(this.m_noOfPassengers); return clone; } #endregion #region Private Fields private uint m_noOfPassengers; #endregion } #region CarTypeCollection Class /// /// A collection of CarType objects. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfCarType", Namespace = Vehicles.Types.Namespaces.Vehicles, ItemName = "CarType")] #if !NET_STANDARD public partial class CarTypeCollection : List, ICloneable #else public partial class CarTypeCollection : List #endif { #region Constructors /// /// Initializes the collection with default values. /// public CarTypeCollection() { } /// /// Initializes the collection with an initial capacity. /// public CarTypeCollection(int capacity) : base(capacity) { } /// /// Initializes the collection with another collection. /// public CarTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// /// Converts an array to a collection. /// public static implicit operator CarTypeCollection(CarType[] values) { if (values != null) { return new CarTypeCollection(values); } return new CarTypeCollection(); } /// /// Converts a collection to an array. /// public static explicit operator CarType[](CarTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #if !NET_STANDARD #region ICloneable Methods /// /// Creates a deep copy of the collection. /// public object Clone() { return (CarTypeCollection)this.MemberwiseClone(); } #endregion #endif /// public new object MemberwiseClone() { CarTypeCollection clone = new CarTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((CarType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion #region TruckType Class #if (!OPCUA_EXCLUDE_TruckType) /// /// /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [DataContract(Namespace = Vehicles.Types.Namespaces.Vehicles)] public partial class TruckType : VehicleType { #region Constructors /// /// The default constructor. /// public TruckType() { Initialize(); } /// /// Called by the .NET framework during deserialization. /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { m_cargoCapacity = (uint)0; } #endregion #region Public Properties /// [DataMember(Name = "CargoCapacity", IsRequired = false, Order = 1)] public uint CargoCapacity { get { return m_cargoCapacity; } set { m_cargoCapacity = value; } } #endregion #region IEncodeable Members /// public override ExpandedNodeId TypeId { get { return DataTypeIds.TruckType; } } /// public override ExpandedNodeId BinaryEncodingId { get { return ObjectIds.TruckType_Encoding_DefaultBinary; } } /// public override ExpandedNodeId XmlEncodingId { get { return ObjectIds.TruckType_Encoding_DefaultXml; } } /// public override void Encode(IEncoder encoder) { base.Encode(encoder); encoder.PushNamespace(Vehicles.Types.Namespaces.Vehicles); encoder.WriteUInt32("CargoCapacity", CargoCapacity); encoder.PopNamespace(); } /// public override void Decode(IDecoder decoder) { base.Decode(decoder); decoder.PushNamespace(Vehicles.Types.Namespaces.Vehicles); CargoCapacity = decoder.ReadUInt32("CargoCapacity"); decoder.PopNamespace(); } /// public override bool IsEqual(IEncodeable encodeable) { if (Object.ReferenceEquals(this, encodeable)) { return true; } TruckType value = encodeable as TruckType; if (value == null) { return false; } if (!base.IsEqual(encodeable)) return false; if (!Utils.IsEqual(m_cargoCapacity, value.m_cargoCapacity)) return false; return true; } #if !NET_STANDARD /// public override object Clone() { return (TruckType)this.MemberwiseClone(); } #endif /// public new object MemberwiseClone() { TruckType clone = (TruckType)base.MemberwiseClone(); clone.m_cargoCapacity = (uint)Utils.Clone(this.m_cargoCapacity); return clone; } #endregion #region Private Fields private uint m_cargoCapacity; #endregion } #region TruckTypeCollection Class /// /// A collection of TruckType objects. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] [CollectionDataContract(Name = "ListOfTruckType", Namespace = Vehicles.Types.Namespaces.Vehicles, ItemName = "TruckType")] #if !NET_STANDARD public partial class TruckTypeCollection : List, ICloneable #else public partial class TruckTypeCollection : List #endif { #region Constructors /// /// Initializes the collection with default values. /// public TruckTypeCollection() { } /// /// Initializes the collection with an initial capacity. /// public TruckTypeCollection(int capacity) : base(capacity) { } /// /// Initializes the collection with another collection. /// public TruckTypeCollection(IEnumerable collection) : base(collection) { } #endregion #region Static Operators /// /// Converts an array to a collection. /// public static implicit operator TruckTypeCollection(TruckType[] values) { if (values != null) { return new TruckTypeCollection(values); } return new TruckTypeCollection(); } /// /// Converts a collection to an array. /// public static explicit operator TruckType[](TruckTypeCollection values) { if (values != null) { return values.ToArray(); } return null; } #endregion #if !NET_STANDARD #region ICloneable Methods /// /// Creates a deep copy of the collection. /// public object Clone() { return (TruckTypeCollection)this.MemberwiseClone(); } #endregion #endif /// public new object MemberwiseClone() { TruckTypeCollection clone = new TruckTypeCollection(this.Count); for (int ii = 0; ii < this.Count; ii++) { clone.Add((TruckType)Utils.Clone(this[ii])); } return clone; } } #endregion #endif #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Vehicles/Design/Vehicles.Types.NodeIds.csv ================================================ CarType,315,DataType CarType_Encoding_DefaultBinary,330,Object CarType_Encoding_DefaultJson,15004,Object CarType_Encoding_DefaultXml,318,Object DriverType,341,ObjectType TruckType,316,DataType TruckType_Encoding_DefaultBinary,331,Object TruckType_Encoding_DefaultJson,15005,Object TruckType_Encoding_DefaultXml,319,Object Vehicles_BinarySchema,302,Variable Vehicles_XmlSchema,287,Variable VehicleType,314,DataType VehicleType_Encoding_DefaultBinary,329,Object VehicleType_Encoding_DefaultJson,15003,Object VehicleType_Encoding_DefaultXml,317,Object ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Vehicles/Design/Vehicles.Types.NodeSet.xml ================================================  http://opcfoundation.org/UA/ http://opcfoundation.org/UA/Vehicles/Types ns=1;i=287 Variable_2 1 Vehicles.Types Vehicles.Types 0 0 0 i=40 false i=72 i=47 true i=92 i=46 false ns=1;i=289 i=46 false ns=1;i=15002 i=47 false ns=1;i=320 i=47 false ns=1;i=323 i=47 false ns=1;i=326 PHhzOnNjaGVtYQ0KICB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEi DQogIHhtbG5zOnVhPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvMjAwOC8wMi9UeXBlcy54 c2QiDQogIHhtbG5zOnRucz0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VBL1ZlaGljbGVzL1R5 cGVzIg0KICB0YXJnZXROYW1lc3BhY2U9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9yZy9VQS9WZWhp Y2xlcy9UeXBlcyINCiAgZWxlbWVudEZvcm1EZWZhdWx0PSJxdWFsaWZpZWQiDQo+DQogIDx4czpp bXBvcnQgbmFtZXNwYWNlPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvMjAwOC8wMi9UeXBl cy54c2QiIC8+DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9IlZlaGljbGVUeXBlIj4NCiAgICA8 eHM6c2VxdWVuY2U+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJNYWtlIiB0eXBlPSJ4czpzdHJp bmciIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBu YW1lPSJNb2RlbCIgdHlwZT0ieHM6c3RyaW5nIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVl IiAvPg0KICAgIDwveHM6c2VxdWVuY2U+DQogIDwveHM6Y29tcGxleFR5cGU+DQogIDx4czplbGVt ZW50IG5hbWU9IlZlaGljbGVUeXBlIiB0eXBlPSJ0bnM6VmVoaWNsZVR5cGUiIC8+DQoNCiAgPHhz OmNvbXBsZXhUeXBlIG5hbWU9Ikxpc3RPZlZlaGljbGVUeXBlIj4NCiAgICA8eHM6c2VxdWVuY2U+ DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJWZWhpY2xlVHlwZSIgdHlwZT0idG5zOlZlaGljbGVU eXBlIiBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0idW5ib3VuZGVkIiBuaWxsYWJsZT0idHJ1ZSIg Lz4NCiAgICA8L3hzOnNlcXVlbmNlPg0KICA8L3hzOmNvbXBsZXhUeXBlPg0KICA8eHM6ZWxlbWVu dCBuYW1lPSJMaXN0T2ZWZWhpY2xlVHlwZSIgdHlwZT0idG5zOkxpc3RPZlZlaGljbGVUeXBlIiBu aWxsYWJsZT0idHJ1ZSI+PC94czplbGVtZW50Pg0KDQogIDx4czpjb21wbGV4VHlwZSBuYW1lPSJD YXJUeXBlIj4NCiAgICA8eHM6Y29tcGxleENvbnRlbnQgbWl4ZWQ9ImZhbHNlIj4NCiAgICAgIDx4 czpleHRlbnNpb24gYmFzZT0idG5zOlZlaGljbGVUeXBlIj4NCiAgICAgICAgPHhzOnNlcXVlbmNl Pg0KICAgICAgICAgIDx4czplbGVtZW50IG5hbWU9Ik5vT2ZQYXNzZW5nZXJzIiB0eXBlPSJ4czp1 bnNpZ25lZEludCIgbWluT2NjdXJzPSIwIiAvPg0KICAgICAgICA8L3hzOnNlcXVlbmNlPg0KICAg ICAgPC94czpleHRlbnNpb24+DQogICAgPC94czpjb21wbGV4Q29udGVudD4NCiAgPC94czpjb21w bGV4VHlwZT4NCiAgPHhzOmVsZW1lbnQgbmFtZT0iQ2FyVHlwZSIgdHlwZT0idG5zOkNhclR5cGUi IC8+DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9Ikxpc3RPZkNhclR5cGUiPg0KICAgIDx4czpz ZXF1ZW5jZT4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IkNhclR5cGUiIHR5cGU9InRuczpDYXJU eXBlIiBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0idW5ib3VuZGVkIiBuaWxsYWJsZT0idHJ1ZSIg Lz4NCiAgICA8L3hzOnNlcXVlbmNlPg0KICA8L3hzOmNvbXBsZXhUeXBlPg0KICA8eHM6ZWxlbWVu dCBuYW1lPSJMaXN0T2ZDYXJUeXBlIiB0eXBlPSJ0bnM6TGlzdE9mQ2FyVHlwZSIgbmlsbGFibGU9 InRydWUiPjwveHM6ZWxlbWVudD4NCg0KICA8eHM6Y29tcGxleFR5cGUgbmFtZT0iVHJ1Y2tUeXBl Ij4NCiAgICA8eHM6Y29tcGxleENvbnRlbnQgbWl4ZWQ9ImZhbHNlIj4NCiAgICAgIDx4czpleHRl bnNpb24gYmFzZT0idG5zOlZlaGljbGVUeXBlIj4NCiAgICAgICAgPHhzOnNlcXVlbmNlPg0KICAg ICAgICAgIDx4czplbGVtZW50IG5hbWU9IkNhcmdvQ2FwYWNpdHkiIHR5cGU9InhzOnVuc2lnbmVk SW50IiBtaW5PY2N1cnM9IjAiIC8+DQogICAgICAgIDwveHM6c2VxdWVuY2U+DQogICAgICA8L3hz OmV4dGVuc2lvbj4NCiAgICA8L3hzOmNvbXBsZXhDb250ZW50Pg0KICA8L3hzOmNvbXBsZXhUeXBl Pg0KICA8eHM6ZWxlbWVudCBuYW1lPSJUcnVja1R5cGUiIHR5cGU9InRuczpUcnVja1R5cGUiIC8+ DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9Ikxpc3RPZlRydWNrVHlwZSI+DQogICAgPHhzOnNl cXVlbmNlPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iVHJ1Y2tUeXBlIiB0eXBlPSJ0bnM6VHJ1 Y2tUeXBlIiBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0idW5ib3VuZGVkIiBuaWxsYWJsZT0idHJ1 ZSIgLz4NCiAgICA8L3hzOnNlcXVlbmNlPg0KICA8L3hzOmNvbXBsZXhUeXBlPg0KICA8eHM6ZWxl bWVudCBuYW1lPSJMaXN0T2ZUcnVja1R5cGUiIHR5cGU9InRuczpMaXN0T2ZUcnVja1R5cGUiIG5p bGxhYmxlPSJ0cnVlIj48L3hzOmVsZW1lbnQ+DQoNCjwveHM6c2NoZW1hPg== i=15 -1 1 1 0 false 0 ns=1;i=289 Variable_2 0 NamespaceUri NamespaceUri 0 0 0 i=46 true ns=1;i=287 i=40 false i=68 http://opcfoundation.org/UA/Vehicles/Types i=12 -1 1 1 0 false 0 ns=1;i=302 Variable_2 1 Vehicles.Types Vehicles.Types 0 0 0 i=40 false i=72 i=47 true i=93 i=46 false ns=1;i=304 i=46 false ns=1;i=15001 i=47 false ns=1;i=332 i=47 false ns=1;i=335 i=47 false ns=1;i=338 PG9wYzpUeXBlRGljdGlvbmFyeQ0KICB4bWxuczpvcGM9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9y Zy9CaW5hcnlTY2hlbWEvIg0KICB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1M U2NoZW1hLWluc3RhbmNlIg0KICB4bWxuczp1YT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VB LyINCiAgeG1sbnM6dG5zPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvVmVoaWNsZXMvVHlw ZXMiDQogIERlZmF1bHRCeXRlT3JkZXI9IkxpdHRsZUVuZGlhbiINCiAgVGFyZ2V0TmFtZXNwYWNl PSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvVmVoaWNsZXMvVHlwZXMiDQo+DQogIDxvcGM6 SW1wb3J0IE5hbWVzcGFjZT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VBLyIgTG9jYXRpb249 Ik9wYy5VYS5CaW5hcnlTY2hlbWEuYnNkIi8+DQoNCiAgPG9wYzpTdHJ1Y3R1cmVkVHlwZSBOYW1l PSJWZWhpY2xlVHlwZSIgQmFzZVR5cGU9InVhOkV4dGVuc2lvbk9iamVjdCI+DQogICAgPG9wYzpG aWVsZCBOYW1lPSJNYWtlIiBUeXBlTmFtZT0ib3BjOlN0cmluZyIgLz4NCiAgICA8b3BjOkZpZWxk IE5hbWU9Ik1vZGVsIiBUeXBlTmFtZT0ib3BjOlN0cmluZyIgLz4NCiAgPC9vcGM6U3RydWN0dXJl ZFR5cGU+DQoNCiAgPG9wYzpTdHJ1Y3R1cmVkVHlwZSBOYW1lPSJDYXJUeXBlIiBCYXNlVHlwZT0i dG5zOlZlaGljbGVUeXBlIj4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik1ha2UiIFR5cGVOYW1lPSJv cGM6U3RyaW5nIiBTb3VyY2VUeXBlPSJ0bnM6VmVoaWNsZVR5cGUiIC8+DQogICAgPG9wYzpGaWVs ZCBOYW1lPSJNb2RlbCIgVHlwZU5hbWU9Im9wYzpTdHJpbmciIFNvdXJjZVR5cGU9InRuczpWZWhp Y2xlVHlwZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZQYXNzZW5nZXJzIiBUeXBlTmFt ZT0ib3BjOlVJbnQzMiIgLz4NCiAgPC9vcGM6U3RydWN0dXJlZFR5cGU+DQoNCiAgPG9wYzpTdHJ1 Y3R1cmVkVHlwZSBOYW1lPSJUcnVja1R5cGUiIEJhc2VUeXBlPSJ0bnM6VmVoaWNsZVR5cGUiPg0K ICAgIDxvcGM6RmllbGQgTmFtZT0iTWFrZSIgVHlwZU5hbWU9Im9wYzpTdHJpbmciIFNvdXJjZVR5 cGU9InRuczpWZWhpY2xlVHlwZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik1vZGVsIiBUeXBl TmFtZT0ib3BjOlN0cmluZyIgU291cmNlVHlwZT0idG5zOlZlaGljbGVUeXBlIiAvPg0KICAgIDxv cGM6RmllbGQgTmFtZT0iQ2FyZ29DYXBhY2l0eSIgVHlwZU5hbWU9Im9wYzpVSW50MzIiIC8+DQog IDwvb3BjOlN0cnVjdHVyZWRUeXBlPg0KDQo8L29wYzpUeXBlRGljdGlvbmFyeT4= i=15 -1 1 1 0 false 0 ns=1;i=304 Variable_2 0 NamespaceUri NamespaceUri 0 0 0 i=46 true ns=1;i=302 i=40 false i=68 http://opcfoundation.org/UA/Vehicles/Types i=12 -1 1 1 0 false 0 ns=1;i=314 DataType_64 1 VehicleType VehicleType 0 0 0 i=45 true i=22 i=45 false ns=1;i=315 i=45 false ns=1;i=316 i=38 false ns=1;i=329 i=38 false ns=1;i=317 i=38 false ns=1;i=15003 false ns=1;i=315 DataType_64 1 CarType CarType 0 0 0 i=45 true ns=1;i=314 i=38 false ns=1;i=330 i=38 false ns=1;i=318 i=38 false ns=1;i=15004 false ns=1;i=316 DataType_64 1 TruckType TruckType 0 0 0 i=45 true ns=1;i=314 i=38 false ns=1;i=331 i=38 false ns=1;i=319 i=38 false ns=1;i=15005 false ns=1;i=317 Object_1 0 Default XML Default XML 0 0 0 i=40 false i=76 i=38 true ns=1;i=314 i=39 false ns=1;i=320 0 ns=1;i=318 Object_1 0 Default XML Default XML 0 0 0 i=40 false i=76 i=38 true ns=1;i=315 i=39 false ns=1;i=323 0 ns=1;i=319 Object_1 0 Default XML Default XML 0 0 0 i=40 false i=76 i=38 true ns=1;i=316 i=39 false ns=1;i=326 0 ns=1;i=320 Variable_2 1 VehicleType VehicleType 0 0 0 i=47 true ns=1;i=287 i=40 false i=69 //xs:element[@name='VehicleType'] i=12 -1 1 1 0 false 0 ns=1;i=323 Variable_2 1 CarType CarType 0 0 0 i=47 true ns=1;i=287 i=40 false i=69 //xs:element[@name='CarType'] i=12 -1 1 1 0 false 0 ns=1;i=326 Variable_2 1 TruckType TruckType 0 0 0 i=47 true ns=1;i=287 i=40 false i=69 //xs:element[@name='TruckType'] i=12 -1 1 1 0 false 0 ns=1;i=329 Object_1 0 Default Binary Default Binary 0 0 0 i=40 false i=76 i=38 true ns=1;i=314 i=39 false ns=1;i=332 0 ns=1;i=330 Object_1 0 Default Binary Default Binary 0 0 0 i=40 false i=76 i=38 true ns=1;i=315 i=39 false ns=1;i=335 0 ns=1;i=331 Object_1 0 Default Binary Default Binary 0 0 0 i=40 false i=76 i=38 true ns=1;i=316 i=39 false ns=1;i=338 0 ns=1;i=332 Variable_2 1 VehicleType VehicleType 0 0 0 i=47 true ns=1;i=302 i=40 false i=69 VehicleType i=12 -1 1 1 0 false 0 ns=1;i=335 Variable_2 1 CarType CarType 0 0 0 i=47 true ns=1;i=302 i=40 false i=69 CarType i=12 -1 1 1 0 false 0 ns=1;i=338 Variable_2 1 TruckType TruckType 0 0 0 i=47 true ns=1;i=302 i=40 false i=69 TruckType i=12 -1 1 1 0 false 0 ns=1;i=341 ObjectType_8 1 DriverType DriverType 0 0 0 i=45 true i=58 i=46 false ns=1;i=342 i=46 false ns=1;i=344 false ns=1;i=342 Variable_2 1 PrimaryVehicle PrimaryVehicle 0 0 0 i=46 true ns=1;i=341 i=40 false i=68 i=37 false i=78 ns=1;i=318 Toyota Prius 4 ns=1;i=314 -1 3 3 0 false 0 ns=1;i=344 Variable_2 1 OwnedVehicles OwnedVehicles 0 0 0 i=46 true ns=1;i=341 i=40 false i=68 i=37 false i=78 ns=1;i=319 Dodge Ram 500 ns=1;i=318 Porche Roadster 2 ns=1;i=314 1 0 3 3 0 false 0 ns=1;i=15001 Variable_2 0 Deprecated Deprecated 0 0 0 i=46 true ns=1;i=302 i=40 false i=68 true i=1 -1 1 1 0 false 0 ns=1;i=15002 Variable_2 0 Deprecated Deprecated 0 0 0 i=46 true ns=1;i=287 i=40 false i=68 true i=1 -1 1 1 0 false 0 ns=1;i=15003 Object_1 0 Default JSON Default JSON 0 0 0 i=40 false i=76 i=38 true ns=1;i=314 0 ns=1;i=15004 Object_1 0 Default JSON Default JSON 0 0 0 i=40 false i=76 i=38 true ns=1;i=315 0 ns=1;i=15005 Object_1 0 Default JSON Default JSON 0 0 0 i=40 false i=76 i=38 true ns=1;i=316 0 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Vehicles/Design/Vehicles.Types.NodeSet2.xml ================================================  http://opcfoundation.org/UA/Vehicles/Types i=1 i=2 i=3 i=4 i=5 i=6 i=7 i=8 i=9 i=10 i=11 i=13 i=12 i=15 i=14 i=16 i=17 i=18 i=20 i=21 i=19 i=22 i=26 i=27 i=28 i=47 i=46 i=35 i=36 i=48 i=45 i=40 i=37 i=38 i=39 VehicleType i=22 CarType ns=1;i=314 TruckType ns=1;i=314 DriverType ns=1;i=342 ns=1;i=344 i=58 PrimaryVehicle i=68 i=78 ns=1;i=341 ns=1;i=318 Toyota Prius 4 OwnedVehicles i=68 i=78 ns=1;i=341 ns=1;i=319 Dodge Ram 500 ns=1;i=318 Porche Roadster 2 Default Binary ns=1;i=314 ns=1;i=332 i=76 Default Binary ns=1;i=315 ns=1;i=335 i=76 Default Binary ns=1;i=316 ns=1;i=338 i=76 Vehicles.Types ns=1;i=304 ns=1;i=15001 ns=1;i=332 ns=1;i=335 ns=1;i=338 i=93 i=72 PG9wYzpUeXBlRGljdGlvbmFyeQ0KICB4bWxuczpvcGM9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9y Zy9CaW5hcnlTY2hlbWEvIg0KICB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1M U2NoZW1hLWluc3RhbmNlIg0KICB4bWxuczp1YT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VB LyINCiAgeG1sbnM6dG5zPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvVmVoaWNsZXMvVHlw ZXMiDQogIERlZmF1bHRCeXRlT3JkZXI9IkxpdHRsZUVuZGlhbiINCiAgVGFyZ2V0TmFtZXNwYWNl PSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvVmVoaWNsZXMvVHlwZXMiDQo+DQogIDxvcGM6 SW1wb3J0IE5hbWVzcGFjZT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VBLyIgTG9jYXRpb249 Ik9wYy5VYS5CaW5hcnlTY2hlbWEuYnNkIi8+DQoNCiAgPG9wYzpTdHJ1Y3R1cmVkVHlwZSBOYW1l PSJWZWhpY2xlVHlwZSIgQmFzZVR5cGU9InVhOkV4dGVuc2lvbk9iamVjdCI+DQogICAgPG9wYzpG aWVsZCBOYW1lPSJNYWtlIiBUeXBlTmFtZT0ib3BjOlN0cmluZyIgLz4NCiAgICA8b3BjOkZpZWxk IE5hbWU9Ik1vZGVsIiBUeXBlTmFtZT0ib3BjOlN0cmluZyIgLz4NCiAgPC9vcGM6U3RydWN0dXJl ZFR5cGU+DQoNCiAgPG9wYzpTdHJ1Y3R1cmVkVHlwZSBOYW1lPSJDYXJUeXBlIiBCYXNlVHlwZT0i dG5zOlZlaGljbGVUeXBlIj4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik1ha2UiIFR5cGVOYW1lPSJv cGM6U3RyaW5nIiBTb3VyY2VUeXBlPSJ0bnM6VmVoaWNsZVR5cGUiIC8+DQogICAgPG9wYzpGaWVs ZCBOYW1lPSJNb2RlbCIgVHlwZU5hbWU9Im9wYzpTdHJpbmciIFNvdXJjZVR5cGU9InRuczpWZWhp Y2xlVHlwZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZQYXNzZW5nZXJzIiBUeXBlTmFt ZT0ib3BjOlVJbnQzMiIgLz4NCiAgPC9vcGM6U3RydWN0dXJlZFR5cGU+DQoNCiAgPG9wYzpTdHJ1 Y3R1cmVkVHlwZSBOYW1lPSJUcnVja1R5cGUiIEJhc2VUeXBlPSJ0bnM6VmVoaWNsZVR5cGUiPg0K ICAgIDxvcGM6RmllbGQgTmFtZT0iTWFrZSIgVHlwZU5hbWU9Im9wYzpTdHJpbmciIFNvdXJjZVR5 cGU9InRuczpWZWhpY2xlVHlwZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik1vZGVsIiBUeXBl TmFtZT0ib3BjOlN0cmluZyIgU291cmNlVHlwZT0idG5zOlZlaGljbGVUeXBlIiAvPg0KICAgIDxv cGM6RmllbGQgTmFtZT0iQ2FyZ29DYXBhY2l0eSIgVHlwZU5hbWU9Im9wYzpVSW50MzIiIC8+DQog IDwvb3BjOlN0cnVjdHVyZWRUeXBlPg0KDQo8L29wYzpUeXBlRGljdGlvbmFyeT4= NamespaceUri i=68 ns=1;i=302 http://opcfoundation.org/UA/Vehicles/Types Deprecated i=68 ns=1;i=302 true VehicleType i=69 ns=1;i=302 VehicleType CarType i=69 ns=1;i=302 CarType TruckType i=69 ns=1;i=302 TruckType Default XML ns=1;i=314 ns=1;i=320 i=76 Default XML ns=1;i=315 ns=1;i=323 i=76 Default XML ns=1;i=316 ns=1;i=326 i=76 Vehicles.Types ns=1;i=289 ns=1;i=15002 ns=1;i=320 ns=1;i=323 ns=1;i=326 i=92 i=72 PHhzOnNjaGVtYQ0KICB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEi DQogIHhtbG5zOnVhPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvMjAwOC8wMi9UeXBlcy54 c2QiDQogIHhtbG5zOnRucz0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VBL1ZlaGljbGVzL1R5 cGVzIg0KICB0YXJnZXROYW1lc3BhY2U9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9yZy9VQS9WZWhp Y2xlcy9UeXBlcyINCiAgZWxlbWVudEZvcm1EZWZhdWx0PSJxdWFsaWZpZWQiDQo+DQogIDx4czpp bXBvcnQgbmFtZXNwYWNlPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvMjAwOC8wMi9UeXBl cy54c2QiIC8+DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9IlZlaGljbGVUeXBlIj4NCiAgICA8 eHM6c2VxdWVuY2U+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJNYWtlIiB0eXBlPSJ4czpzdHJp bmciIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBu YW1lPSJNb2RlbCIgdHlwZT0ieHM6c3RyaW5nIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVl IiAvPg0KICAgIDwveHM6c2VxdWVuY2U+DQogIDwveHM6Y29tcGxleFR5cGU+DQogIDx4czplbGVt ZW50IG5hbWU9IlZlaGljbGVUeXBlIiB0eXBlPSJ0bnM6VmVoaWNsZVR5cGUiIC8+DQoNCiAgPHhz OmNvbXBsZXhUeXBlIG5hbWU9Ikxpc3RPZlZlaGljbGVUeXBlIj4NCiAgICA8eHM6c2VxdWVuY2U+ DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJWZWhpY2xlVHlwZSIgdHlwZT0idG5zOlZlaGljbGVU eXBlIiBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0idW5ib3VuZGVkIiBuaWxsYWJsZT0idHJ1ZSIg Lz4NCiAgICA8L3hzOnNlcXVlbmNlPg0KICA8L3hzOmNvbXBsZXhUeXBlPg0KICA8eHM6ZWxlbWVu dCBuYW1lPSJMaXN0T2ZWZWhpY2xlVHlwZSIgdHlwZT0idG5zOkxpc3RPZlZlaGljbGVUeXBlIiBu aWxsYWJsZT0idHJ1ZSI+PC94czplbGVtZW50Pg0KDQogIDx4czpjb21wbGV4VHlwZSBuYW1lPSJD YXJUeXBlIj4NCiAgICA8eHM6Y29tcGxleENvbnRlbnQgbWl4ZWQ9ImZhbHNlIj4NCiAgICAgIDx4 czpleHRlbnNpb24gYmFzZT0idG5zOlZlaGljbGVUeXBlIj4NCiAgICAgICAgPHhzOnNlcXVlbmNl Pg0KICAgICAgICAgIDx4czplbGVtZW50IG5hbWU9Ik5vT2ZQYXNzZW5nZXJzIiB0eXBlPSJ4czp1 bnNpZ25lZEludCIgbWluT2NjdXJzPSIwIiAvPg0KICAgICAgICA8L3hzOnNlcXVlbmNlPg0KICAg ICAgPC94czpleHRlbnNpb24+DQogICAgPC94czpjb21wbGV4Q29udGVudD4NCiAgPC94czpjb21w bGV4VHlwZT4NCiAgPHhzOmVsZW1lbnQgbmFtZT0iQ2FyVHlwZSIgdHlwZT0idG5zOkNhclR5cGUi IC8+DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9Ikxpc3RPZkNhclR5cGUiPg0KICAgIDx4czpz ZXF1ZW5jZT4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IkNhclR5cGUiIHR5cGU9InRuczpDYXJU eXBlIiBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0idW5ib3VuZGVkIiBuaWxsYWJsZT0idHJ1ZSIg Lz4NCiAgICA8L3hzOnNlcXVlbmNlPg0KICA8L3hzOmNvbXBsZXhUeXBlPg0KICA8eHM6ZWxlbWVu dCBuYW1lPSJMaXN0T2ZDYXJUeXBlIiB0eXBlPSJ0bnM6TGlzdE9mQ2FyVHlwZSIgbmlsbGFibGU9 InRydWUiPjwveHM6ZWxlbWVudD4NCg0KICA8eHM6Y29tcGxleFR5cGUgbmFtZT0iVHJ1Y2tUeXBl Ij4NCiAgICA8eHM6Y29tcGxleENvbnRlbnQgbWl4ZWQ9ImZhbHNlIj4NCiAgICAgIDx4czpleHRl bnNpb24gYmFzZT0idG5zOlZlaGljbGVUeXBlIj4NCiAgICAgICAgPHhzOnNlcXVlbmNlPg0KICAg ICAgICAgIDx4czplbGVtZW50IG5hbWU9IkNhcmdvQ2FwYWNpdHkiIHR5cGU9InhzOnVuc2lnbmVk SW50IiBtaW5PY2N1cnM9IjAiIC8+DQogICAgICAgIDwveHM6c2VxdWVuY2U+DQogICAgICA8L3hz OmV4dGVuc2lvbj4NCiAgICA8L3hzOmNvbXBsZXhDb250ZW50Pg0KICA8L3hzOmNvbXBsZXhUeXBl Pg0KICA8eHM6ZWxlbWVudCBuYW1lPSJUcnVja1R5cGUiIHR5cGU9InRuczpUcnVja1R5cGUiIC8+ DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9Ikxpc3RPZlRydWNrVHlwZSI+DQogICAgPHhzOnNl cXVlbmNlPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iVHJ1Y2tUeXBlIiB0eXBlPSJ0bnM6VHJ1 Y2tUeXBlIiBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0idW5ib3VuZGVkIiBuaWxsYWJsZT0idHJ1 ZSIgLz4NCiAgICA8L3hzOnNlcXVlbmNlPg0KICA8L3hzOmNvbXBsZXhUeXBlPg0KICA8eHM6ZWxl bWVudCBuYW1lPSJMaXN0T2ZUcnVja1R5cGUiIHR5cGU9InRuczpMaXN0T2ZUcnVja1R5cGUiIG5p bGxhYmxlPSJ0cnVlIj48L3hzOmVsZW1lbnQ+DQoNCjwveHM6c2NoZW1hPg== NamespaceUri i=68 ns=1;i=287 http://opcfoundation.org/UA/Vehicles/Types Deprecated i=68 ns=1;i=287 true VehicleType i=69 ns=1;i=287 //xs:element[@name='VehicleType'] CarType i=69 ns=1;i=287 //xs:element[@name='CarType'] TruckType i=69 ns=1;i=287 //xs:element[@name='TruckType'] Default JSON ns=1;i=314 i=76 Default JSON ns=1;i=315 i=76 Default JSON ns=1;i=316 i=76 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Vehicles/Design/Vehicles.Types.PredefinedNodes.xml ================================================  http://opcfoundation.org/UA/Vehicles/Types DataType_64 ns=1;i=314 1 VehicleType i=22 i=14798 i=22 Structure_0 Make i=12 -1 0 false Model i=12 -1 0 false DataType_64 ns=1;i=315 1 CarType ns=1;i=314 i=14798 ns=1;i=314 Structure_0 Make i=12 -1 0 false Model i=12 -1 0 false NoOfPassengers i=7 -1 0 false DataType_64 ns=1;i=316 1 TruckType ns=1;i=314 i=14798 ns=1;i=314 Structure_0 Make i=12 -1 0 false Model i=12 -1 0 false CargoCapacity i=7 -1 0 false ObjectType_8 ns=1;i=341 1 DriverType i=58 Variable_2 ns=1;i=342 1 PrimaryVehicle i=46 i=68 i=78 342 ns=1;i=318 Toyota Prius 4 ns=1;i=314 -1 3 3 Variable_2 ns=1;i=344 1 OwnedVehicles i=46 i=68 i=78 344 ns=1;i=319 Dodge Ram 500 ns=1;i=318 Porche Roadster 2 ns=1;i=314 1 0 3 3 Object_1 ns=1;i=329 0 Default Binary i=76 329 i=38 true ns=1;i=314 i=39 ns=1;i=332 Object_1 ns=1;i=330 0 Default Binary i=76 330 i=38 true ns=1;i=315 i=39 ns=1;i=335 Object_1 ns=1;i=331 0 Default Binary i=76 331 i=38 true ns=1;i=316 i=39 ns=1;i=338 Variable_2 ns=1;i=302 1 Vehicles.Types i=72 302 PG9wYzpUeXBlRGljdGlvbmFyeQ0KICB4bWxuczpvcGM9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9y Zy9CaW5hcnlTY2hlbWEvIg0KICB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1M U2NoZW1hLWluc3RhbmNlIg0KICB4bWxuczp1YT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VB LyINCiAgeG1sbnM6dG5zPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvVmVoaWNsZXMvVHlw ZXMiDQogIERlZmF1bHRCeXRlT3JkZXI9IkxpdHRsZUVuZGlhbiINCiAgVGFyZ2V0TmFtZXNwYWNl PSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvVmVoaWNsZXMvVHlwZXMiDQo+DQogIDxvcGM6 SW1wb3J0IE5hbWVzcGFjZT0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VBLyIgTG9jYXRpb249 Ik9wYy5VYS5CaW5hcnlTY2hlbWEuYnNkIi8+DQoNCiAgPG9wYzpTdHJ1Y3R1cmVkVHlwZSBOYW1l PSJWZWhpY2xlVHlwZSIgQmFzZVR5cGU9InVhOkV4dGVuc2lvbk9iamVjdCI+DQogICAgPG9wYzpG aWVsZCBOYW1lPSJNYWtlIiBUeXBlTmFtZT0ib3BjOlN0cmluZyIgLz4NCiAgICA8b3BjOkZpZWxk IE5hbWU9Ik1vZGVsIiBUeXBlTmFtZT0ib3BjOlN0cmluZyIgLz4NCiAgPC9vcGM6U3RydWN0dXJl ZFR5cGU+DQoNCiAgPG9wYzpTdHJ1Y3R1cmVkVHlwZSBOYW1lPSJDYXJUeXBlIiBCYXNlVHlwZT0i dG5zOlZlaGljbGVUeXBlIj4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik1ha2UiIFR5cGVOYW1lPSJv cGM6U3RyaW5nIiBTb3VyY2VUeXBlPSJ0bnM6VmVoaWNsZVR5cGUiIC8+DQogICAgPG9wYzpGaWVs ZCBOYW1lPSJNb2RlbCIgVHlwZU5hbWU9Im9wYzpTdHJpbmciIFNvdXJjZVR5cGU9InRuczpWZWhp Y2xlVHlwZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik5vT2ZQYXNzZW5nZXJzIiBUeXBlTmFt ZT0ib3BjOlVJbnQzMiIgLz4NCiAgPC9vcGM6U3RydWN0dXJlZFR5cGU+DQoNCiAgPG9wYzpTdHJ1 Y3R1cmVkVHlwZSBOYW1lPSJUcnVja1R5cGUiIEJhc2VUeXBlPSJ0bnM6VmVoaWNsZVR5cGUiPg0K ICAgIDxvcGM6RmllbGQgTmFtZT0iTWFrZSIgVHlwZU5hbWU9Im9wYzpTdHJpbmciIFNvdXJjZVR5 cGU9InRuczpWZWhpY2xlVHlwZSIgLz4NCiAgICA8b3BjOkZpZWxkIE5hbWU9Ik1vZGVsIiBUeXBl TmFtZT0ib3BjOlN0cmluZyIgU291cmNlVHlwZT0idG5zOlZlaGljbGVUeXBlIiAvPg0KICAgIDxv cGM6RmllbGQgTmFtZT0iQ2FyZ29DYXBhY2l0eSIgVHlwZU5hbWU9Im9wYzpVSW50MzIiIC8+DQog IDwvb3BjOlN0cnVjdHVyZWRUeXBlPg0KDQo8L29wYzpUeXBlRGljdGlvbmFyeT4= i=15 -1 1 1 i=47 true i=93 Variable_2 ns=1;i=304 0 NamespaceUri i=46 i=68 304 http://opcfoundation.org/UA/Vehicles/Types i=12 -1 1 1 Variable_2 ns=1;i=15001 0 Deprecated i=46 i=68 15001 true i=1 -1 1 1 Variable_2 ns=1;i=332 1 VehicleType i=47 i=69 332 VehicleType i=12 -1 1 1 Variable_2 ns=1;i=335 1 CarType i=47 i=69 335 CarType i=12 -1 1 1 Variable_2 ns=1;i=338 1 TruckType i=47 i=69 338 TruckType i=12 -1 1 1 Object_1 ns=1;i=317 0 Default XML i=76 317 i=38 true ns=1;i=314 i=39 ns=1;i=320 Object_1 ns=1;i=318 0 Default XML i=76 318 i=38 true ns=1;i=315 i=39 ns=1;i=323 Object_1 ns=1;i=319 0 Default XML i=76 319 i=38 true ns=1;i=316 i=39 ns=1;i=326 Variable_2 ns=1;i=287 1 Vehicles.Types i=72 287 PHhzOnNjaGVtYQ0KICB4bWxuczp4cz0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEi DQogIHhtbG5zOnVhPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvMjAwOC8wMi9UeXBlcy54 c2QiDQogIHhtbG5zOnRucz0iaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VBL1ZlaGljbGVzL1R5 cGVzIg0KICB0YXJnZXROYW1lc3BhY2U9Imh0dHA6Ly9vcGNmb3VuZGF0aW9uLm9yZy9VQS9WZWhp Y2xlcy9UeXBlcyINCiAgZWxlbWVudEZvcm1EZWZhdWx0PSJxdWFsaWZpZWQiDQo+DQogIDx4czpp bXBvcnQgbmFtZXNwYWNlPSJodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvMjAwOC8wMi9UeXBl cy54c2QiIC8+DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9IlZlaGljbGVUeXBlIj4NCiAgICA8 eHM6c2VxdWVuY2U+DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJNYWtlIiB0eXBlPSJ4czpzdHJp bmciIG1pbk9jY3Vycz0iMCIgbmlsbGFibGU9InRydWUiIC8+DQogICAgICA8eHM6ZWxlbWVudCBu YW1lPSJNb2RlbCIgdHlwZT0ieHM6c3RyaW5nIiBtaW5PY2N1cnM9IjAiIG5pbGxhYmxlPSJ0cnVl IiAvPg0KICAgIDwveHM6c2VxdWVuY2U+DQogIDwveHM6Y29tcGxleFR5cGU+DQogIDx4czplbGVt ZW50IG5hbWU9IlZlaGljbGVUeXBlIiB0eXBlPSJ0bnM6VmVoaWNsZVR5cGUiIC8+DQoNCiAgPHhz OmNvbXBsZXhUeXBlIG5hbWU9Ikxpc3RPZlZlaGljbGVUeXBlIj4NCiAgICA8eHM6c2VxdWVuY2U+ DQogICAgICA8eHM6ZWxlbWVudCBuYW1lPSJWZWhpY2xlVHlwZSIgdHlwZT0idG5zOlZlaGljbGVU eXBlIiBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0idW5ib3VuZGVkIiBuaWxsYWJsZT0idHJ1ZSIg Lz4NCiAgICA8L3hzOnNlcXVlbmNlPg0KICA8L3hzOmNvbXBsZXhUeXBlPg0KICA8eHM6ZWxlbWVu dCBuYW1lPSJMaXN0T2ZWZWhpY2xlVHlwZSIgdHlwZT0idG5zOkxpc3RPZlZlaGljbGVUeXBlIiBu aWxsYWJsZT0idHJ1ZSI+PC94czplbGVtZW50Pg0KDQogIDx4czpjb21wbGV4VHlwZSBuYW1lPSJD YXJUeXBlIj4NCiAgICA8eHM6Y29tcGxleENvbnRlbnQgbWl4ZWQ9ImZhbHNlIj4NCiAgICAgIDx4 czpleHRlbnNpb24gYmFzZT0idG5zOlZlaGljbGVUeXBlIj4NCiAgICAgICAgPHhzOnNlcXVlbmNl Pg0KICAgICAgICAgIDx4czplbGVtZW50IG5hbWU9Ik5vT2ZQYXNzZW5nZXJzIiB0eXBlPSJ4czp1 bnNpZ25lZEludCIgbWluT2NjdXJzPSIwIiAvPg0KICAgICAgICA8L3hzOnNlcXVlbmNlPg0KICAg ICAgPC94czpleHRlbnNpb24+DQogICAgPC94czpjb21wbGV4Q29udGVudD4NCiAgPC94czpjb21w bGV4VHlwZT4NCiAgPHhzOmVsZW1lbnQgbmFtZT0iQ2FyVHlwZSIgdHlwZT0idG5zOkNhclR5cGUi IC8+DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9Ikxpc3RPZkNhclR5cGUiPg0KICAgIDx4czpz ZXF1ZW5jZT4NCiAgICAgIDx4czplbGVtZW50IG5hbWU9IkNhclR5cGUiIHR5cGU9InRuczpDYXJU eXBlIiBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0idW5ib3VuZGVkIiBuaWxsYWJsZT0idHJ1ZSIg Lz4NCiAgICA8L3hzOnNlcXVlbmNlPg0KICA8L3hzOmNvbXBsZXhUeXBlPg0KICA8eHM6ZWxlbWVu dCBuYW1lPSJMaXN0T2ZDYXJUeXBlIiB0eXBlPSJ0bnM6TGlzdE9mQ2FyVHlwZSIgbmlsbGFibGU9 InRydWUiPjwveHM6ZWxlbWVudD4NCg0KICA8eHM6Y29tcGxleFR5cGUgbmFtZT0iVHJ1Y2tUeXBl Ij4NCiAgICA8eHM6Y29tcGxleENvbnRlbnQgbWl4ZWQ9ImZhbHNlIj4NCiAgICAgIDx4czpleHRl bnNpb24gYmFzZT0idG5zOlZlaGljbGVUeXBlIj4NCiAgICAgICAgPHhzOnNlcXVlbmNlPg0KICAg ICAgICAgIDx4czplbGVtZW50IG5hbWU9IkNhcmdvQ2FwYWNpdHkiIHR5cGU9InhzOnVuc2lnbmVk SW50IiBtaW5PY2N1cnM9IjAiIC8+DQogICAgICAgIDwveHM6c2VxdWVuY2U+DQogICAgICA8L3hz OmV4dGVuc2lvbj4NCiAgICA8L3hzOmNvbXBsZXhDb250ZW50Pg0KICA8L3hzOmNvbXBsZXhUeXBl Pg0KICA8eHM6ZWxlbWVudCBuYW1lPSJUcnVja1R5cGUiIHR5cGU9InRuczpUcnVja1R5cGUiIC8+ DQoNCiAgPHhzOmNvbXBsZXhUeXBlIG5hbWU9Ikxpc3RPZlRydWNrVHlwZSI+DQogICAgPHhzOnNl cXVlbmNlPg0KICAgICAgPHhzOmVsZW1lbnQgbmFtZT0iVHJ1Y2tUeXBlIiB0eXBlPSJ0bnM6VHJ1 Y2tUeXBlIiBtaW5PY2N1cnM9IjAiIG1heE9jY3Vycz0idW5ib3VuZGVkIiBuaWxsYWJsZT0idHJ1 ZSIgLz4NCiAgICA8L3hzOnNlcXVlbmNlPg0KICA8L3hzOmNvbXBsZXhUeXBlPg0KICA8eHM6ZWxl bWVudCBuYW1lPSJMaXN0T2ZUcnVja1R5cGUiIHR5cGU9InRuczpMaXN0T2ZUcnVja1R5cGUiIG5p bGxhYmxlPSJ0cnVlIj48L3hzOmVsZW1lbnQ+DQoNCjwveHM6c2NoZW1hPg== i=15 -1 1 1 i=47 true i=92 Variable_2 ns=1;i=289 0 NamespaceUri i=46 i=68 289 http://opcfoundation.org/UA/Vehicles/Types i=12 -1 1 1 Variable_2 ns=1;i=15002 0 Deprecated i=46 i=68 15002 true i=1 -1 1 1 Variable_2 ns=1;i=320 1 VehicleType i=47 i=69 320 //xs:element[@name='VehicleType'] i=12 -1 1 1 Variable_2 ns=1;i=323 1 CarType i=47 i=69 323 //xs:element[@name='CarType'] i=12 -1 1 1 Variable_2 ns=1;i=326 1 TruckType i=47 i=69 326 //xs:element[@name='TruckType'] i=12 -1 1 1 Object_1 ns=1;i=15003 0 Default JSON i=76 15003 i=38 true ns=1;i=314 Object_1 ns=1;i=15004 0 Default JSON i=76 15004 i=38 true ns=1;i=315 Object_1 ns=1;i=15005 0 Default JSON i=76 15005 i=38 true ns=1;i=316 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Vehicles/Design/Vehicles.Types.Types.bsd ================================================ ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Vehicles/Design/Vehicles.Types.Types.xsd ================================================ ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/Engineering.Constants.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; namespace Engineering { #region Variable Identifiers /// /// A class that declares constants for all Variables in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Variables { /// /// The identifier for the SerialNumber Variable. /// public const uint SerialNumber = 443; /// /// The identifier for the Manufacturer Variable. /// public const uint Manufacturer = 444; } #endregion #region Variable Node Identifiers /// /// A class that declares constants for all Variables in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class VariableIds { /// /// The identifier for the SerialNumber Variable. /// public static readonly ExpandedNodeId SerialNumber = new ExpandedNodeId(Engineering.Variables.SerialNumber, Engineering.Namespaces.Engineering); /// /// The identifier for the Manufacturer Variable. /// public static readonly ExpandedNodeId Manufacturer = new ExpandedNodeId(Engineering.Variables.Manufacturer, Engineering.Namespaces.Engineering); } #endregion #region BrowseName Declarations /// /// Declares all of the BrowseNames used in the Model Design. /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class BrowseNames { /// /// The BrowseName for the Manufacturer component. /// public const string Manufacturer = "Manufacturer"; /// /// The BrowseName for the SerialNumber component. /// public const string SerialNumber = "SerialNumber"; } #endregion #region Namespace Declarations /// /// Defines constants for all namespaces referenced by the model design. /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Namespaces { /// /// The URI for the OpcUa namespace (.NET code namespace is 'Opc.Ua'). /// public const string OpcUa = "http://opcfoundation.org/UA/"; /// /// The URI for the OpcUaXsd namespace (.NET code namespace is 'Opc.Ua'). /// public const string OpcUaXsd = "http://opcfoundation.org/UA/2008/02/Types.xsd"; /// /// The URI for the Engineering namespace (.NET code namespace is 'Engineering'). /// public const string Engineering = "http://opcfoundation.org/UA/Engineering"; } #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/Engineering.NodeIds.csv ================================================ Manufacturer,444,Variable SerialNumber,443,Variable ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/Engineering.NodeSet.xml ================================================  http://opcfoundation.org/UA/ http://opcfoundation.org/UA/Engineering ns=1;i=443 Variable_2 1 SerialNumber SerialNumber 0 0 0 i=40 false i=68 i=12 -2 1 1 0 false 0 ns=1;i=444 Variable_2 1 Manufacturer Manufacturer 0 0 0 i=40 false i=68 i=12 -2 1 1 0 false 0 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/Engineering.NodeSet2.xml ================================================  http://opcfoundation.org/UA/Engineering i=1 i=2 i=3 i=4 i=5 i=6 i=7 i=8 i=9 i=10 i=11 i=13 i=12 i=15 i=14 i=16 i=17 i=18 i=20 i=21 i=19 i=22 i=26 i=27 i=28 i=47 i=46 i=35 i=36 i=48 i=45 i=40 i=37 i=38 i=39 SerialNumber i=68 Manufacturer i=68 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/Engineering.PredefinedNodes.xml ================================================  http://opcfoundation.org/UA/Engineering Variable_2 ns=1;i=443 1 SerialNumber i=46 i=68 443 i=12 1 1 Variable_2 ns=1;i=444 1 Manufacturer i=46 i=68 444 i=12 1 1 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/Engineering.Types.bsd ================================================ ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/Engineering.Types.xsd ================================================ ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/EngineeringDesign.csv ================================================ SerialNumber,443,Variable Manufacturer,444,Variable ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/EngineeringDesign.xml ================================================ http://opcfoundation.org/UA/ http://opcfoundation.org/UA/Engineering ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/Model.Classes.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; using System; using System.Collections.Generic; namespace Model { #region GenericControllerState Class #if (!OPCUA_EXCLUDE_GenericControllerState) /// /// Stores an instance of the GenericControllerType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class GenericControllerState : BaseObjectState { #region Constructors /// /// Initializes the type with its default attribute values. /// public GenericControllerState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(Model.ObjectTypes.GenericControllerType, Model.Namespaces.Views, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AwAAACcAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvRW5naW5lZXJpbmcmAAAAaHR0cDovL29w" + "Y2ZvdW5kYXRpb24ub3JnL1VBL09wZXJhdGlvbnMhAAAAaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VB" + "L1ZpZXdz/////wRggAIBAAAAAwAdAAAAR2VuZXJpY0NvbnRyb2xsZXJUeXBlSW5zdGFuY2UBA1kBAQNZ" + "AVkBAAD/////BAAAABVgiQoCAAAAAQAMAAAAU2VyaWFsTnVtYmVyAQNaAQAuAERaAQAAAAz/////AQH/" + "////AAAAABVgiQoCAAAAAQAMAAAATWFudWZhY3R1cmVyAQNbAQAuAERbAQAAAAz/////AQH/////AAAA" + "ABVgiQoCAAAAAgAIAAAAU2V0UG9pbnQBA1wBAC8BAEAJXAEAAAAL/////wEB/////wEAAAAVYIkKAgAA" + "AAAABwAAAEVVUmFuZ2UBA18BAC4ARF8BAAABAHQD/////wEB/////wAAAAAVYIkKAgAAAAIACwAAAE1l" + "YXN1cmVtZW50AQNiAQAvAQBACWIBAAAAC/////8BAf////8BAAAAFWCJCgIAAAAAAAcAAABFVVJhbmdl" + "AQNlAQAuAERlAQAAAQB0A/////8BAf////8AAAAA"; #endregion #endif #endregion #region Public Properties /// public PropertyState SerialNumber { get { return m_serialNumber; } set { if (!Object.ReferenceEquals(m_serialNumber, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_serialNumber = value; } } /// public PropertyState Manufacturer { get { return m_manufacturer; } set { if (!Object.ReferenceEquals(m_manufacturer, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_manufacturer = value; } } /// public AnalogItemState SetPoint { get { return m_setPoint; } set { if (!Object.ReferenceEquals(m_setPoint, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_setPoint = value; } } /// public AnalogItemState Measurement { get { return m_measurement; } set { if (!Object.ReferenceEquals(m_measurement, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_measurement = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_serialNumber != null) { children.Add(m_serialNumber); } if (m_manufacturer != null) { children.Add(m_manufacturer); } if (m_setPoint != null) { children.Add(m_setPoint); } if (m_measurement != null) { children.Add(m_measurement); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case Engineering.BrowseNames.SerialNumber: { if (createOrReplace) { if (SerialNumber == null) { if (replacement == null) { SerialNumber = new PropertyState(this); } else { SerialNumber = (PropertyState)replacement; } } } instance = SerialNumber; break; } case Engineering.BrowseNames.Manufacturer: { if (createOrReplace) { if (Manufacturer == null) { if (replacement == null) { Manufacturer = new PropertyState(this); } else { Manufacturer = (PropertyState)replacement; } } } instance = Manufacturer; break; } case Operations.BrowseNames.SetPoint: { if (createOrReplace) { if (SetPoint == null) { if (replacement == null) { SetPoint = new AnalogItemState(this); } else { SetPoint = (AnalogItemState)replacement; } } } instance = SetPoint; break; } case Operations.BrowseNames.Measurement: { if (createOrReplace) { if (Measurement == null) { if (replacement == null) { Measurement = new AnalogItemState(this); } else { Measurement = (AnalogItemState)replacement; } } } instance = Measurement; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private PropertyState m_serialNumber; private PropertyState m_manufacturer; private AnalogItemState m_setPoint; private AnalogItemState m_measurement; #endregion } #endif #endregion #region FlowControllerState Class #if (!OPCUA_EXCLUDE_FlowControllerState) /// /// Stores an instance of the FlowControllerType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class FlowControllerState : GenericControllerState { #region Constructors /// /// Initializes the type with its default attribute values. /// public FlowControllerState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(Model.ObjectTypes.FlowControllerType, Model.Namespaces.Views, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AwAAACcAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvRW5naW5lZXJpbmcmAAAAaHR0cDovL29w" + "Y2ZvdW5kYXRpb24ub3JnL1VBL09wZXJhdGlvbnMhAAAAaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VB" + "L1ZpZXdz/////wRggAIBAAAAAwAaAAAARmxvd0NvbnRyb2xsZXJUeXBlSW5zdGFuY2UBA2gBAQNoAWgB" + "AAD/////BAAAABVgiQoCAAAAAQAMAAAAU2VyaWFsTnVtYmVyAQNpAQAuAERpAQAAAAz/////AQH/////" + "AAAAABVgiQoCAAAAAQAMAAAATWFudWZhY3R1cmVyAQNqAQAuAERqAQAAAAz/////AQH/////AAAAABVg" + "iQoCAAAAAgAIAAAAU2V0UG9pbnQBA2sBAC8BAEAJawEAAAAL/////wEB/////wEAAAAVYIkKAgAAAAAA" + "BwAAAEVVUmFuZ2UBA24BAC4ARG4BAAABAHQD/////wEB/////wAAAAAVYIkKAgAAAAIACwAAAE1lYXN1" + "cmVtZW50AQNxAQAvAQBACXEBAAAAC/////8BAf////8BAAAAFWCJCgIAAAAAAAcAAABFVVJhbmdlAQN0" + "AQAuAER0AQAAAQB0A/////8BAf////8AAAAA"; #endregion #endif #endregion #region Public Properties #endregion #region Overridden Methods #endregion #region Private Fields #endregion } #endif #endregion #region LevelControllerState Class #if (!OPCUA_EXCLUDE_LevelControllerState) /// /// Stores an instance of the LevelControllerType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class LevelControllerState : GenericControllerState { #region Constructors /// /// Initializes the type with its default attribute values. /// public LevelControllerState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(Model.ObjectTypes.LevelControllerType, Model.Namespaces.Views, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AwAAACcAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvRW5naW5lZXJpbmcmAAAAaHR0cDovL29w" + "Y2ZvdW5kYXRpb24ub3JnL1VBL09wZXJhdGlvbnMhAAAAaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VB" + "L1ZpZXdz/////wRggAIBAAAAAwAbAAAATGV2ZWxDb250cm9sbGVyVHlwZUluc3RhbmNlAQN3AQEDdwF3" + "AQAA/////wQAAAAVYIkKAgAAAAEADAAAAFNlcmlhbE51bWJlcgEDeAEALgBEeAEAAAAM/////wEB////" + "/wAAAAAVYIkKAgAAAAEADAAAAE1hbnVmYWN0dXJlcgEDeQEALgBEeQEAAAAM/////wEB/////wAAAAAV" + "YIkKAgAAAAIACAAAAFNldFBvaW50AQN6AQAvAQBACXoBAAAAC/////8BAf////8BAAAAFWCJCgIAAAAA" + "AAcAAABFVVJhbmdlAQN9AQAuAER9AQAAAQB0A/////8BAf////8AAAAAFWCJCgIAAAACAAsAAABNZWFz" + "dXJlbWVudAEDgAEALwEAQAmAAQAAAAv/////AQH/////AQAAABVgiQoCAAAAAAAHAAAARVVSYW5nZQED" + "gwEALgBEgwEAAAEAdAP/////AQH/////AAAAAA=="; #endregion #endif #endregion #region Public Properties #endregion #region Overridden Methods #endregion #region Private Fields #endregion } #endif #endregion #region BoilerState Class #if (!OPCUA_EXCLUDE_BoilerState) /// /// Stores an instance of the BoilerType ObjectType. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public partial class BoilerState : BaseObjectState { #region Constructors /// /// Initializes the type with its default attribute values. /// public BoilerState(NodeState parent) : base(parent) { } /// /// Returns the id of the default type definition node for the instance. /// protected override NodeId GetDefaultTypeDefinitionId(NamespaceTable namespaceUris) { return Opc.Ua.NodeId.Create(Model.ObjectTypes.BoilerType, Model.Namespaces.Views, namespaceUris); } #if (!OPCUA_EXCLUDE_InitializationStrings) /// /// Initializes the instance. /// protected override void Initialize(ISystemContext context) { Initialize(context, InitializationString); InitializeOptionalChildren(context); } /// /// Initializes the instance with a node. /// protected override void Initialize(ISystemContext context, NodeState source) { InitializeOptionalChildren(context); base.Initialize(context, source); } /// /// Initializes the any option children defined for the instance. /// protected override void InitializeOptionalChildren(ISystemContext context) { base.InitializeOptionalChildren(context); } #region Initialization String private const string InitializationString = "AwAAACcAAABodHRwOi8vb3BjZm91bmRhdGlvbi5vcmcvVUEvRW5naW5lZXJpbmcmAAAAaHR0cDovL29w" + "Y2ZvdW5kYXRpb24ub3JnL1VBL09wZXJhdGlvbnMhAAAAaHR0cDovL29wY2ZvdW5kYXRpb24ub3JnL1VB" + "L1ZpZXdz/////wRggAIBAAAAAwASAAAAQm9pbGVyVHlwZUluc3RhbmNlAQOGAQEDhgGGAQAA/////wMA" + "AAAEYIAKAQAAAAMABwAAAFdhdGVySW4BA4cBAC8AOocBAAD/////AQAAAARggAoBAAAAAwAEAAAARmxv" + "dwEDiAEALwEDaAGIAQAA/////wQAAAAVYIkKAgAAAAEADAAAAFNlcmlhbE51bWJlcgEDiQEALgBEiQEA" + "AAAM/////wEB/////wAAAAAVYIkKAgAAAAEADAAAAE1hbnVmYWN0dXJlcgEDigEALgBEigEAAAAM////" + "/wEB/////wAAAAAVYIkKAgAAAAIACAAAAFNldFBvaW50AQOLAQAvAQBACYsBAAAAC/////8BAf////8B" + "AAAAFWCJCgIAAAAAAAcAAABFVVJhbmdlAQOOAQAuAESOAQAAAQB0A/////8BAf////8AAAAAFWCJCgIA" + "AAACAAsAAABNZWFzdXJlbWVudAEDkQEALwEAQAmRAQAAAAv/////AQH/////AQAAABVgiQoCAAAAAAAH" + "AAAARVVSYW5nZQEDlAEALgBElAEAAAEAdAP/////AQH/////AAAAAARggAoBAAAAAwAIAAAAU3RlYW1P" + "dXQBA5cBAC8AOpcBAAD/////AQAAAARggAoBAAAAAwAEAAAARmxvdwEDmAEALwEDaAGYAQAA/////wQA" + "AAAVYIkKAgAAAAEADAAAAFNlcmlhbE51bWJlcgEDmQEALgBEmQEAAAAM/////wEB/////wAAAAAVYIkK" + "AgAAAAEADAAAAE1hbnVmYWN0dXJlcgEDmgEALgBEmgEAAAAM/////wEB/////wAAAAAVYIkKAgAAAAIA" + "CAAAAFNldFBvaW50AQObAQAvAQBACZsBAAAAC/////8BAf////8BAAAAFWCJCgIAAAAAAAcAAABFVVJh" + "bmdlAQOeAQAuAESeAQAAAQB0A/////8BAf////8AAAAAFWCJCgIAAAACAAsAAABNZWFzdXJlbWVudAED" + "oQEALwEAQAmhAQAAAAv/////AQH/////AQAAABVgiQoCAAAAAAAHAAAARVVSYW5nZQEDpAEALgBEpAEA" + "AAEAdAP/////AQH/////AAAAAARggAoBAAAAAwAEAAAARHJ1bQEDpwEALwA6pwEAAP////8BAAAABGCA" + "CgEAAAADAAUAAABMZXZlbAEDqAEALwEDdwGoAQAA/////wQAAAAVYIkKAgAAAAEADAAAAFNlcmlhbE51" + "bWJlcgEDqQEALgBEqQEAAAAM/////wEB/////wAAAAAVYIkKAgAAAAEADAAAAE1hbnVmYWN0dXJlcgED" + "qgEALgBEqgEAAAAM/////wEB/////wAAAAAVYIkKAgAAAAIACAAAAFNldFBvaW50AQOrAQAvAQBACasB" + "AAAAC/////8BAf////8BAAAAFWCJCgIAAAAAAAcAAABFVVJhbmdlAQOuAQAuAESuAQAAAQB0A/////8B" + "Af////8AAAAAFWCJCgIAAAACAAsAAABNZWFzdXJlbWVudAEDsQEALwEAQAmxAQAAAAv/////AQH/////" + "AQAAABVgiQoCAAAAAAAHAAAARVVSYW5nZQEDtAEALgBEtAEAAAEAdAP/////AQH/////AAAAAA=="; #endregion #endif #endregion #region Public Properties /// public BaseObjectState WaterIn { get { return m_waterIn; } set { if (!Object.ReferenceEquals(m_waterIn, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_waterIn = value; } } /// public BaseObjectState SteamOut { get { return m_steamOut; } set { if (!Object.ReferenceEquals(m_steamOut, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_steamOut = value; } } /// public BaseObjectState Drum { get { return m_drum; } set { if (!Object.ReferenceEquals(m_drum, value)) { ChangeMasks |= NodeStateChangeMasks.Children; } m_drum = value; } } #endregion #region Overridden Methods /// /// Populates a list with the children that belong to the node. /// /// The context for the system being accessed. /// The list of children to populate. public override void GetChildren( ISystemContext context, IList children) { if (m_waterIn != null) { children.Add(m_waterIn); } if (m_steamOut != null) { children.Add(m_steamOut); } if (m_drum != null) { children.Add(m_drum); } base.GetChildren(context, children); } /// /// Finds the child with the specified browse name. /// protected override BaseInstanceState FindChild( ISystemContext context, QualifiedName browseName, bool createOrReplace, BaseInstanceState replacement) { if (QualifiedName.IsNull(browseName)) { return null; } BaseInstanceState instance = null; switch (browseName.Name) { case Model.BrowseNames.WaterIn: { if (createOrReplace) { if (WaterIn == null) { if (replacement == null) { WaterIn = new BaseObjectState(this); } else { WaterIn = (BaseObjectState)replacement; } } } instance = WaterIn; break; } case Model.BrowseNames.SteamOut: { if (createOrReplace) { if (SteamOut == null) { if (replacement == null) { SteamOut = new BaseObjectState(this); } else { SteamOut = (BaseObjectState)replacement; } } } instance = SteamOut; break; } case Model.BrowseNames.Drum: { if (createOrReplace) { if (Drum == null) { if (replacement == null) { Drum = new BaseObjectState(this); } else { Drum = (BaseObjectState)replacement; } } } instance = Drum; break; } } if (instance != null) { return instance; } return base.FindChild(context, browseName, createOrReplace, replacement); } #endregion #region Private Fields private BaseObjectState m_waterIn; private BaseObjectState m_steamOut; private BaseObjectState m_drum; #endregion } #endif #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/Model.Constants.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; namespace Model { #region Object Identifiers /// /// A class that declares constants for all Objects in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Objects { /// /// The identifier for the BoilerType_WaterIn Object. /// public const uint BoilerType_WaterIn = 391; /// /// The identifier for the BoilerType_WaterIn_Flow Object. /// public const uint BoilerType_WaterIn_Flow = 392; /// /// The identifier for the BoilerType_SteamOut Object. /// public const uint BoilerType_SteamOut = 407; /// /// The identifier for the BoilerType_SteamOut_Flow Object. /// public const uint BoilerType_SteamOut_Flow = 408; /// /// The identifier for the BoilerType_Drum Object. /// public const uint BoilerType_Drum = 423; /// /// The identifier for the BoilerType_Drum_Level Object. /// public const uint BoilerType_Drum_Level = 424; /// /// The identifier for the Plant Object. /// public const uint Plant = 442; } #endregion #region ObjectType Identifiers /// /// A class that declares constants for all ObjectTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectTypes { /// /// The identifier for the GenericControllerType ObjectType. /// public const uint GenericControllerType = 345; /// /// The identifier for the FlowControllerType ObjectType. /// public const uint FlowControllerType = 360; /// /// The identifier for the LevelControllerType ObjectType. /// public const uint LevelControllerType = 375; /// /// The identifier for the BoilerType ObjectType. /// public const uint BoilerType = 390; } #endregion #region Variable Identifiers /// /// A class that declares constants for all Variables in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Variables { /// /// The identifier for the GenericControllerType_SerialNumber Variable. /// public const uint GenericControllerType_SerialNumber = 346; /// /// The identifier for the GenericControllerType_Manufacturer Variable. /// public const uint GenericControllerType_Manufacturer = 347; /// /// The identifier for the GenericControllerType_SetPoint Variable. /// public const uint GenericControllerType_SetPoint = 348; /// /// The identifier for the GenericControllerType_SetPoint_EURange Variable. /// public const uint GenericControllerType_SetPoint_EURange = 351; /// /// The identifier for the GenericControllerType_Measurement Variable. /// public const uint GenericControllerType_Measurement = 354; /// /// The identifier for the GenericControllerType_Measurement_EURange Variable. /// public const uint GenericControllerType_Measurement_EURange = 357; /// /// The identifier for the FlowControllerType_SetPoint_EURange Variable. /// public const uint FlowControllerType_SetPoint_EURange = 366; /// /// The identifier for the FlowControllerType_Measurement_EURange Variable. /// public const uint FlowControllerType_Measurement_EURange = 372; /// /// The identifier for the LevelControllerType_SetPoint_EURange Variable. /// public const uint LevelControllerType_SetPoint_EURange = 381; /// /// The identifier for the LevelControllerType_Measurement_EURange Variable. /// public const uint LevelControllerType_Measurement_EURange = 387; /// /// The identifier for the BoilerType_WaterIn_Flow_SerialNumber Variable. /// public const uint BoilerType_WaterIn_Flow_SerialNumber = 393; /// /// The identifier for the BoilerType_WaterIn_Flow_Manufacturer Variable. /// public const uint BoilerType_WaterIn_Flow_Manufacturer = 394; /// /// The identifier for the BoilerType_WaterIn_Flow_SetPoint Variable. /// public const uint BoilerType_WaterIn_Flow_SetPoint = 395; /// /// The identifier for the BoilerType_WaterIn_Flow_SetPoint_EURange Variable. /// public const uint BoilerType_WaterIn_Flow_SetPoint_EURange = 398; /// /// The identifier for the BoilerType_WaterIn_Flow_Measurement Variable. /// public const uint BoilerType_WaterIn_Flow_Measurement = 401; /// /// The identifier for the BoilerType_WaterIn_Flow_Measurement_EURange Variable. /// public const uint BoilerType_WaterIn_Flow_Measurement_EURange = 404; /// /// The identifier for the BoilerType_SteamOut_Flow_SerialNumber Variable. /// public const uint BoilerType_SteamOut_Flow_SerialNumber = 409; /// /// The identifier for the BoilerType_SteamOut_Flow_Manufacturer Variable. /// public const uint BoilerType_SteamOut_Flow_Manufacturer = 410; /// /// The identifier for the BoilerType_SteamOut_Flow_SetPoint Variable. /// public const uint BoilerType_SteamOut_Flow_SetPoint = 411; /// /// The identifier for the BoilerType_SteamOut_Flow_SetPoint_EURange Variable. /// public const uint BoilerType_SteamOut_Flow_SetPoint_EURange = 414; /// /// The identifier for the BoilerType_SteamOut_Flow_Measurement Variable. /// public const uint BoilerType_SteamOut_Flow_Measurement = 417; /// /// The identifier for the BoilerType_SteamOut_Flow_Measurement_EURange Variable. /// public const uint BoilerType_SteamOut_Flow_Measurement_EURange = 420; /// /// The identifier for the BoilerType_Drum_Level_SerialNumber Variable. /// public const uint BoilerType_Drum_Level_SerialNumber = 425; /// /// The identifier for the BoilerType_Drum_Level_Manufacturer Variable. /// public const uint BoilerType_Drum_Level_Manufacturer = 426; /// /// The identifier for the BoilerType_Drum_Level_SetPoint Variable. /// public const uint BoilerType_Drum_Level_SetPoint = 427; /// /// The identifier for the BoilerType_Drum_Level_SetPoint_EURange Variable. /// public const uint BoilerType_Drum_Level_SetPoint_EURange = 430; /// /// The identifier for the BoilerType_Drum_Level_Measurement Variable. /// public const uint BoilerType_Drum_Level_Measurement = 433; /// /// The identifier for the BoilerType_Drum_Level_Measurement_EURange Variable. /// public const uint BoilerType_Drum_Level_Measurement_EURange = 436; } #endregion #region View Identifiers /// /// A class that declares constants for all Views in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Views { /// /// The identifier for the Engineering View. /// public const uint Engineering = 439; /// /// The identifier for the Operations View. /// public const uint Operations = 441; } #endregion #region Object Node Identifiers /// /// A class that declares constants for all Objects in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectIds { /// /// The identifier for the BoilerType_WaterIn Object. /// public static readonly ExpandedNodeId BoilerType_WaterIn = new ExpandedNodeId(Model.Objects.BoilerType_WaterIn, Model.Namespaces.Views); /// /// The identifier for the BoilerType_WaterIn_Flow Object. /// public static readonly ExpandedNodeId BoilerType_WaterIn_Flow = new ExpandedNodeId(Model.Objects.BoilerType_WaterIn_Flow, Model.Namespaces.Views); /// /// The identifier for the BoilerType_SteamOut Object. /// public static readonly ExpandedNodeId BoilerType_SteamOut = new ExpandedNodeId(Model.Objects.BoilerType_SteamOut, Model.Namespaces.Views); /// /// The identifier for the BoilerType_SteamOut_Flow Object. /// public static readonly ExpandedNodeId BoilerType_SteamOut_Flow = new ExpandedNodeId(Model.Objects.BoilerType_SteamOut_Flow, Model.Namespaces.Views); /// /// The identifier for the BoilerType_Drum Object. /// public static readonly ExpandedNodeId BoilerType_Drum = new ExpandedNodeId(Model.Objects.BoilerType_Drum, Model.Namespaces.Views); /// /// The identifier for the BoilerType_Drum_Level Object. /// public static readonly ExpandedNodeId BoilerType_Drum_Level = new ExpandedNodeId(Model.Objects.BoilerType_Drum_Level, Model.Namespaces.Views); /// /// The identifier for the Plant Object. /// public static readonly ExpandedNodeId Plant = new ExpandedNodeId(Model.Objects.Plant, Model.Namespaces.Views); } #endregion #region ObjectType Node Identifiers /// /// A class that declares constants for all ObjectTypes in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ObjectTypeIds { /// /// The identifier for the GenericControllerType ObjectType. /// public static readonly ExpandedNodeId GenericControllerType = new ExpandedNodeId(Model.ObjectTypes.GenericControllerType, Model.Namespaces.Views); /// /// The identifier for the FlowControllerType ObjectType. /// public static readonly ExpandedNodeId FlowControllerType = new ExpandedNodeId(Model.ObjectTypes.FlowControllerType, Model.Namespaces.Views); /// /// The identifier for the LevelControllerType ObjectType. /// public static readonly ExpandedNodeId LevelControllerType = new ExpandedNodeId(Model.ObjectTypes.LevelControllerType, Model.Namespaces.Views); /// /// The identifier for the BoilerType ObjectType. /// public static readonly ExpandedNodeId BoilerType = new ExpandedNodeId(Model.ObjectTypes.BoilerType, Model.Namespaces.Views); } #endregion #region Variable Node Identifiers /// /// A class that declares constants for all Variables in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class VariableIds { /// /// The identifier for the GenericControllerType_SerialNumber Variable. /// public static readonly ExpandedNodeId GenericControllerType_SerialNumber = new ExpandedNodeId(Model.Variables.GenericControllerType_SerialNumber, Model.Namespaces.Views); /// /// The identifier for the GenericControllerType_Manufacturer Variable. /// public static readonly ExpandedNodeId GenericControllerType_Manufacturer = new ExpandedNodeId(Model.Variables.GenericControllerType_Manufacturer, Model.Namespaces.Views); /// /// The identifier for the GenericControllerType_SetPoint Variable. /// public static readonly ExpandedNodeId GenericControllerType_SetPoint = new ExpandedNodeId(Model.Variables.GenericControllerType_SetPoint, Model.Namespaces.Views); /// /// The identifier for the GenericControllerType_SetPoint_EURange Variable. /// public static readonly ExpandedNodeId GenericControllerType_SetPoint_EURange = new ExpandedNodeId(Model.Variables.GenericControllerType_SetPoint_EURange, Model.Namespaces.Views); /// /// The identifier for the GenericControllerType_Measurement Variable. /// public static readonly ExpandedNodeId GenericControllerType_Measurement = new ExpandedNodeId(Model.Variables.GenericControllerType_Measurement, Model.Namespaces.Views); /// /// The identifier for the GenericControllerType_Measurement_EURange Variable. /// public static readonly ExpandedNodeId GenericControllerType_Measurement_EURange = new ExpandedNodeId(Model.Variables.GenericControllerType_Measurement_EURange, Model.Namespaces.Views); /// /// The identifier for the FlowControllerType_SetPoint_EURange Variable. /// public static readonly ExpandedNodeId FlowControllerType_SetPoint_EURange = new ExpandedNodeId(Model.Variables.FlowControllerType_SetPoint_EURange, Model.Namespaces.Views); /// /// The identifier for the FlowControllerType_Measurement_EURange Variable. /// public static readonly ExpandedNodeId FlowControllerType_Measurement_EURange = new ExpandedNodeId(Model.Variables.FlowControllerType_Measurement_EURange, Model.Namespaces.Views); /// /// The identifier for the LevelControllerType_SetPoint_EURange Variable. /// public static readonly ExpandedNodeId LevelControllerType_SetPoint_EURange = new ExpandedNodeId(Model.Variables.LevelControllerType_SetPoint_EURange, Model.Namespaces.Views); /// /// The identifier for the LevelControllerType_Measurement_EURange Variable. /// public static readonly ExpandedNodeId LevelControllerType_Measurement_EURange = new ExpandedNodeId(Model.Variables.LevelControllerType_Measurement_EURange, Model.Namespaces.Views); /// /// The identifier for the BoilerType_WaterIn_Flow_SerialNumber Variable. /// public static readonly ExpandedNodeId BoilerType_WaterIn_Flow_SerialNumber = new ExpandedNodeId(Model.Variables.BoilerType_WaterIn_Flow_SerialNumber, Model.Namespaces.Views); /// /// The identifier for the BoilerType_WaterIn_Flow_Manufacturer Variable. /// public static readonly ExpandedNodeId BoilerType_WaterIn_Flow_Manufacturer = new ExpandedNodeId(Model.Variables.BoilerType_WaterIn_Flow_Manufacturer, Model.Namespaces.Views); /// /// The identifier for the BoilerType_WaterIn_Flow_SetPoint Variable. /// public static readonly ExpandedNodeId BoilerType_WaterIn_Flow_SetPoint = new ExpandedNodeId(Model.Variables.BoilerType_WaterIn_Flow_SetPoint, Model.Namespaces.Views); /// /// The identifier for the BoilerType_WaterIn_Flow_SetPoint_EURange Variable. /// public static readonly ExpandedNodeId BoilerType_WaterIn_Flow_SetPoint_EURange = new ExpandedNodeId(Model.Variables.BoilerType_WaterIn_Flow_SetPoint_EURange, Model.Namespaces.Views); /// /// The identifier for the BoilerType_WaterIn_Flow_Measurement Variable. /// public static readonly ExpandedNodeId BoilerType_WaterIn_Flow_Measurement = new ExpandedNodeId(Model.Variables.BoilerType_WaterIn_Flow_Measurement, Model.Namespaces.Views); /// /// The identifier for the BoilerType_WaterIn_Flow_Measurement_EURange Variable. /// public static readonly ExpandedNodeId BoilerType_WaterIn_Flow_Measurement_EURange = new ExpandedNodeId(Model.Variables.BoilerType_WaterIn_Flow_Measurement_EURange, Model.Namespaces.Views); /// /// The identifier for the BoilerType_SteamOut_Flow_SerialNumber Variable. /// public static readonly ExpandedNodeId BoilerType_SteamOut_Flow_SerialNumber = new ExpandedNodeId(Model.Variables.BoilerType_SteamOut_Flow_SerialNumber, Model.Namespaces.Views); /// /// The identifier for the BoilerType_SteamOut_Flow_Manufacturer Variable. /// public static readonly ExpandedNodeId BoilerType_SteamOut_Flow_Manufacturer = new ExpandedNodeId(Model.Variables.BoilerType_SteamOut_Flow_Manufacturer, Model.Namespaces.Views); /// /// The identifier for the BoilerType_SteamOut_Flow_SetPoint Variable. /// public static readonly ExpandedNodeId BoilerType_SteamOut_Flow_SetPoint = new ExpandedNodeId(Model.Variables.BoilerType_SteamOut_Flow_SetPoint, Model.Namespaces.Views); /// /// The identifier for the BoilerType_SteamOut_Flow_SetPoint_EURange Variable. /// public static readonly ExpandedNodeId BoilerType_SteamOut_Flow_SetPoint_EURange = new ExpandedNodeId(Model.Variables.BoilerType_SteamOut_Flow_SetPoint_EURange, Model.Namespaces.Views); /// /// The identifier for the BoilerType_SteamOut_Flow_Measurement Variable. /// public static readonly ExpandedNodeId BoilerType_SteamOut_Flow_Measurement = new ExpandedNodeId(Model.Variables.BoilerType_SteamOut_Flow_Measurement, Model.Namespaces.Views); /// /// The identifier for the BoilerType_SteamOut_Flow_Measurement_EURange Variable. /// public static readonly ExpandedNodeId BoilerType_SteamOut_Flow_Measurement_EURange = new ExpandedNodeId(Model.Variables.BoilerType_SteamOut_Flow_Measurement_EURange, Model.Namespaces.Views); /// /// The identifier for the BoilerType_Drum_Level_SerialNumber Variable. /// public static readonly ExpandedNodeId BoilerType_Drum_Level_SerialNumber = new ExpandedNodeId(Model.Variables.BoilerType_Drum_Level_SerialNumber, Model.Namespaces.Views); /// /// The identifier for the BoilerType_Drum_Level_Manufacturer Variable. /// public static readonly ExpandedNodeId BoilerType_Drum_Level_Manufacturer = new ExpandedNodeId(Model.Variables.BoilerType_Drum_Level_Manufacturer, Model.Namespaces.Views); /// /// The identifier for the BoilerType_Drum_Level_SetPoint Variable. /// public static readonly ExpandedNodeId BoilerType_Drum_Level_SetPoint = new ExpandedNodeId(Model.Variables.BoilerType_Drum_Level_SetPoint, Model.Namespaces.Views); /// /// The identifier for the BoilerType_Drum_Level_SetPoint_EURange Variable. /// public static readonly ExpandedNodeId BoilerType_Drum_Level_SetPoint_EURange = new ExpandedNodeId(Model.Variables.BoilerType_Drum_Level_SetPoint_EURange, Model.Namespaces.Views); /// /// The identifier for the BoilerType_Drum_Level_Measurement Variable. /// public static readonly ExpandedNodeId BoilerType_Drum_Level_Measurement = new ExpandedNodeId(Model.Variables.BoilerType_Drum_Level_Measurement, Model.Namespaces.Views); /// /// The identifier for the BoilerType_Drum_Level_Measurement_EURange Variable. /// public static readonly ExpandedNodeId BoilerType_Drum_Level_Measurement_EURange = new ExpandedNodeId(Model.Variables.BoilerType_Drum_Level_Measurement_EURange, Model.Namespaces.Views); } #endregion #region View Node Identifiers /// /// A class that declares constants for all Views in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class ViewIds { /// /// The identifier for the Engineering View. /// public static readonly ExpandedNodeId Engineering = new ExpandedNodeId(Model.Views.Engineering, Model.Namespaces.Views); /// /// The identifier for the Operations View. /// public static readonly ExpandedNodeId Operations = new ExpandedNodeId(Model.Views.Operations, Model.Namespaces.Views); } #endregion #region BrowseName Declarations /// /// Declares all of the BrowseNames used in the Model Design. /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class BrowseNames { /// /// The BrowseName for the BoilerType component. /// public const string BoilerType = "BoilerType"; /// /// The BrowseName for the Drum component. /// public const string Drum = "Drum"; /// /// The BrowseName for the Engineering component. /// public const string Engineering = "Engineering"; /// /// The BrowseName for the FlowControllerType component. /// public const string FlowControllerType = "FlowControllerType"; /// /// The BrowseName for the GenericControllerType component. /// public const string GenericControllerType = "GenericControllerType"; /// /// The BrowseName for the LevelControllerType component. /// public const string LevelControllerType = "LevelControllerType"; /// /// The BrowseName for the Operations component. /// public const string Operations = "Operations"; /// /// The BrowseName for the Plant component. /// public const string Plant = "Plant"; /// /// The BrowseName for the SteamOut component. /// public const string SteamOut = "SteamOut"; /// /// The BrowseName for the WaterIn component. /// public const string WaterIn = "WaterIn"; } #endregion #region Namespace Declarations /// /// Defines constants for all namespaces referenced by the model design. /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Namespaces { /// /// The URI for the OpcUa namespace (.NET code namespace is 'Opc.Ua'). /// public const string OpcUa = "http://opcfoundation.org/UA/"; /// /// The URI for the OpcUaXsd namespace (.NET code namespace is 'Opc.Ua'). /// public const string OpcUaXsd = "http://opcfoundation.org/UA/2008/02/Types.xsd"; /// /// The URI for the Engineering namespace (.NET code namespace is 'Engineering'). /// public const string Engineering = "http://opcfoundation.org/UA/Engineering"; /// /// The URI for the Operations namespace (.NET code namespace is 'Operations'). /// public const string Operations = "http://opcfoundation.org/UA/Operations"; /// /// The URI for the Views namespace (.NET code namespace is 'Model'). /// public const string Views = "http://opcfoundation.org/UA/Views"; } #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/Model.NodeIds.csv ================================================ BoilerType,390,ObjectType Engineering,439,View FlowControllerType,360,ObjectType GenericControllerType,345,ObjectType LevelControllerType,375,ObjectType Operations,441,View Plant,442,Object ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/Model.NodeSet.xml ================================================  http://opcfoundation.org/UA/ http://opcfoundation.org/UA/Views http://opcfoundation.org/UA/Engineering http://opcfoundation.org/UA/Operations ns=1;i=345 ObjectType_8 1 GenericControllerType GenericControllerType 0 0 0 i=45 true i=58 i=46 false ns=1;i=346 i=46 false ns=1;i=347 i=47 false ns=1;i=348 i=47 false ns=1;i=354 i=45 false ns=1;i=360 i=45 false ns=1;i=375 false ns=1;i=346 Variable_2 2 SerialNumber SerialNumber 0 0 0 i=46 true ns=1;i=345 i=40 false i=68 i=37 false i=78 i=12 -1 1 1 0 false 0 ns=1;i=347 Variable_2 2 Manufacturer Manufacturer 0 0 0 i=46 true ns=1;i=345 i=40 false i=68 i=37 false i=78 i=12 -1 1 1 0 false 0 ns=1;i=348 Variable_2 3 SetPoint SetPoint 0 0 0 i=47 true ns=1;i=345 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=351 0 i=11 -1 1 1 0 false 0 ns=1;i=351 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=348 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=354 Variable_2 3 Measurement Measurement 0 0 0 i=47 true ns=1;i=345 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=357 0 i=11 -1 1 1 0 false 0 ns=1;i=357 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=354 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=360 ObjectType_8 1 FlowControllerType FlowControllerType 0 0 0 i=45 true ns=1;i=345 false ns=1;i=375 ObjectType_8 1 LevelControllerType LevelControllerType 0 0 0 i=45 true ns=1;i=345 false ns=1;i=390 ObjectType_8 1 BoilerType BoilerType 0 0 0 i=45 true i=58 i=47 false ns=1;i=391 i=47 false ns=1;i=407 i=47 false ns=1;i=423 false ns=1;i=391 Object_1 1 WaterIn WaterIn 0 0 0 i=47 true ns=1;i=390 i=40 false i=58 i=37 false i=78 i=47 false ns=1;i=392 0 ns=1;i=392 Object_1 1 Flow Flow 0 0 0 i=47 true ns=1;i=391 i=40 false ns=1;i=360 i=37 false i=78 i=46 false ns=1;i=393 i=46 false ns=1;i=394 i=47 false ns=1;i=395 i=47 false ns=1;i=401 0 ns=1;i=393 Variable_2 2 SerialNumber SerialNumber 0 0 0 i=46 true ns=1;i=392 i=40 false i=68 i=37 false i=78 i=12 -1 1 1 0 false 0 ns=1;i=394 Variable_2 2 Manufacturer Manufacturer 0 0 0 i=46 true ns=1;i=392 i=40 false i=68 i=37 false i=78 i=12 -1 1 1 0 false 0 ns=1;i=395 Variable_2 3 SetPoint SetPoint 0 0 0 i=47 true ns=1;i=392 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=398 0 i=11 -1 1 1 0 false 0 ns=1;i=398 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=395 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=401 Variable_2 3 Measurement Measurement 0 0 0 i=47 true ns=1;i=392 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=404 0 i=11 -1 1 1 0 false 0 ns=1;i=404 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=401 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=407 Object_1 1 SteamOut SteamOut 0 0 0 i=47 true ns=1;i=390 i=40 false i=58 i=37 false i=78 i=47 false ns=1;i=408 0 ns=1;i=408 Object_1 1 Flow Flow 0 0 0 i=47 true ns=1;i=407 i=40 false ns=1;i=360 i=37 false i=78 i=46 false ns=1;i=409 i=46 false ns=1;i=410 i=47 false ns=1;i=411 i=47 false ns=1;i=417 0 ns=1;i=409 Variable_2 2 SerialNumber SerialNumber 0 0 0 i=46 true ns=1;i=408 i=40 false i=68 i=37 false i=78 i=12 -1 1 1 0 false 0 ns=1;i=410 Variable_2 2 Manufacturer Manufacturer 0 0 0 i=46 true ns=1;i=408 i=40 false i=68 i=37 false i=78 i=12 -1 1 1 0 false 0 ns=1;i=411 Variable_2 3 SetPoint SetPoint 0 0 0 i=47 true ns=1;i=408 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=414 0 i=11 -1 1 1 0 false 0 ns=1;i=414 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=411 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=417 Variable_2 3 Measurement Measurement 0 0 0 i=47 true ns=1;i=408 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=420 0 i=11 -1 1 1 0 false 0 ns=1;i=420 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=417 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=423 Object_1 1 Drum Drum 0 0 0 i=47 true ns=1;i=390 i=40 false i=58 i=37 false i=78 i=47 false ns=1;i=424 0 ns=1;i=424 Object_1 1 Level Level 0 0 0 i=47 true ns=1;i=423 i=40 false ns=1;i=375 i=37 false i=78 i=46 false ns=1;i=425 i=46 false ns=1;i=426 i=47 false ns=1;i=427 i=47 false ns=1;i=433 0 ns=1;i=425 Variable_2 2 SerialNumber SerialNumber 0 0 0 i=46 true ns=1;i=424 i=40 false i=68 i=37 false i=78 i=12 -1 1 1 0 false 0 ns=1;i=426 Variable_2 2 Manufacturer Manufacturer 0 0 0 i=46 true ns=1;i=424 i=40 false i=68 i=37 false i=78 i=12 -1 1 1 0 false 0 ns=1;i=427 Variable_2 3 SetPoint SetPoint 0 0 0 i=47 true ns=1;i=424 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=430 0 i=11 -1 1 1 0 false 0 ns=1;i=430 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=427 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=433 Variable_2 3 Measurement Measurement 0 0 0 i=47 true ns=1;i=424 i=40 false i=2368 i=37 false i=78 i=46 false ns=1;i=436 0 i=11 -1 1 1 0 false 0 ns=1;i=436 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=433 i=40 false i=68 i=37 false i=78 i=884 -1 1 1 0 false 0 ns=1;i=439 View_128 1 Engineering Engineering 0 0 0 i=35 true i=87 false 0 ns=1;i=441 View_128 1 Operations Operations 0 0 0 i=35 true i=87 false 0 ns=1;i=442 Object_1 1 Plant Plant 0 0 0 i=40 false i=61 i=35 true i=85 0 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/Model.NodeSet2.xml ================================================  http://opcfoundation.org/UA/Views http://opcfoundation.org/UA/Engineering http://opcfoundation.org/UA/Operations i=1 i=2 i=3 i=4 i=5 i=6 i=7 i=8 i=9 i=10 i=11 i=13 i=12 i=15 i=14 i=16 i=17 i=18 i=20 i=21 i=19 i=22 i=26 i=27 i=28 i=47 i=46 i=35 i=36 i=48 i=45 i=40 i=37 i=38 i=39 Engineering i=87 Operations i=87 GenericControllerType ns=1;i=346 ns=1;i=347 ns=1;i=348 ns=1;i=354 i=58 SerialNumber i=68 i=78 ns=1;i=345 Manufacturer i=68 i=78 ns=1;i=345 SetPoint ns=1;i=351 i=2368 i=78 ns=1;i=345 EURange i=68 i=78 ns=1;i=348 Measurement ns=1;i=357 i=2368 i=78 ns=1;i=345 EURange i=68 i=78 ns=1;i=354 FlowControllerType ns=1;i=345 LevelControllerType ns=1;i=345 BoilerType ns=1;i=391 ns=1;i=407 ns=1;i=423 i=58 WaterIn ns=1;i=392 i=58 i=78 ns=1;i=390 Flow ns=1;i=393 ns=1;i=394 ns=1;i=395 ns=1;i=401 ns=1;i=360 i=78 ns=1;i=391 SerialNumber i=68 i=78 ns=1;i=392 Manufacturer i=68 i=78 ns=1;i=392 SetPoint ns=1;i=398 i=2368 i=78 ns=1;i=392 EURange i=68 i=78 ns=1;i=395 Measurement ns=1;i=404 i=2368 i=78 ns=1;i=392 EURange i=68 i=78 ns=1;i=401 SteamOut ns=1;i=408 i=58 i=78 ns=1;i=390 Flow ns=1;i=409 ns=1;i=410 ns=1;i=411 ns=1;i=417 ns=1;i=360 i=78 ns=1;i=407 SerialNumber i=68 i=78 ns=1;i=408 Manufacturer i=68 i=78 ns=1;i=408 SetPoint ns=1;i=414 i=2368 i=78 ns=1;i=408 EURange i=68 i=78 ns=1;i=411 Measurement ns=1;i=420 i=2368 i=78 ns=1;i=408 EURange i=68 i=78 ns=1;i=417 Drum ns=1;i=424 i=58 i=78 ns=1;i=390 Level ns=1;i=425 ns=1;i=426 ns=1;i=427 ns=1;i=433 ns=1;i=375 i=78 ns=1;i=423 SerialNumber i=68 i=78 ns=1;i=424 Manufacturer i=68 i=78 ns=1;i=424 SetPoint ns=1;i=430 i=2368 i=78 ns=1;i=424 EURange i=68 i=78 ns=1;i=427 Measurement ns=1;i=436 i=2368 i=78 ns=1;i=424 EURange i=68 i=78 ns=1;i=433 Plant i=85 i=61 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/Model.PredefinedNodes.xml ================================================  http://opcfoundation.org/UA/Engineering http://opcfoundation.org/UA/Operations http://opcfoundation.org/UA/Views View_128 ns=3;i=439 3 Engineering i=35 true i=87 View_128 ns=3;i=441 3 Operations i=35 true i=87 ObjectType_8 ns=3;i=345 3 GenericControllerType i=58 Variable_2 ns=3;i=346 1 SerialNumber i=46 i=68 i=78 346 i=12 -1 1 1 Variable_2 ns=3;i=347 1 Manufacturer i=46 i=68 i=78 347 i=12 -1 1 1 Variable_2 ns=3;i=348 2 SetPoint i=47 i=2368 i=78 348 i=11 -1 1 1 Variable_2 ns=3;i=351 0 EURange i=46 i=68 i=78 351 i=884 -1 1 1 Variable_2 ns=3;i=354 2 Measurement i=47 i=2368 i=78 354 i=11 -1 1 1 Variable_2 ns=3;i=357 0 EURange i=46 i=68 i=78 357 i=884 -1 1 1 ObjectType_8 ns=3;i=360 3 FlowControllerType ns=3;i=345 ObjectType_8 ns=3;i=375 3 LevelControllerType ns=3;i=345 ObjectType_8 ns=3;i=390 3 BoilerType i=58 Object_1 ns=3;i=391 3 WaterIn i=47 i=58 i=78 391 Object_1 ns=3;i=392 3 Flow i=47 ns=3;i=360 i=78 392 Variable_2 ns=3;i=393 1 SerialNumber i=46 i=68 i=78 393 i=12 -1 1 1 Variable_2 ns=3;i=394 1 Manufacturer i=46 i=68 i=78 394 i=12 -1 1 1 Variable_2 ns=3;i=395 2 SetPoint i=47 i=2368 i=78 395 i=11 -1 1 1 Variable_2 ns=3;i=398 0 EURange i=46 i=68 i=78 398 i=884 -1 1 1 Variable_2 ns=3;i=401 2 Measurement i=47 i=2368 i=78 401 i=11 -1 1 1 Variable_2 ns=3;i=404 0 EURange i=46 i=68 i=78 404 i=884 -1 1 1 Object_1 ns=3;i=407 3 SteamOut i=47 i=58 i=78 407 Object_1 ns=3;i=408 3 Flow i=47 ns=3;i=360 i=78 408 Variable_2 ns=3;i=409 1 SerialNumber i=46 i=68 i=78 409 i=12 -1 1 1 Variable_2 ns=3;i=410 1 Manufacturer i=46 i=68 i=78 410 i=12 -1 1 1 Variable_2 ns=3;i=411 2 SetPoint i=47 i=2368 i=78 411 i=11 -1 1 1 Variable_2 ns=3;i=414 0 EURange i=46 i=68 i=78 414 i=884 -1 1 1 Variable_2 ns=3;i=417 2 Measurement i=47 i=2368 i=78 417 i=11 -1 1 1 Variable_2 ns=3;i=420 0 EURange i=46 i=68 i=78 420 i=884 -1 1 1 Object_1 ns=3;i=423 3 Drum i=47 i=58 i=78 423 Object_1 ns=3;i=424 3 Level i=47 ns=3;i=375 i=78 424 Variable_2 ns=3;i=425 1 SerialNumber i=46 i=68 i=78 425 i=12 -1 1 1 Variable_2 ns=3;i=426 1 Manufacturer i=46 i=68 i=78 426 i=12 -1 1 1 Variable_2 ns=3;i=427 2 SetPoint i=47 i=2368 i=78 427 i=11 -1 1 1 Variable_2 ns=3;i=430 0 EURange i=46 i=68 i=78 430 i=884 -1 1 1 Variable_2 ns=3;i=433 2 Measurement i=47 i=2368 i=78 433 i=11 -1 1 1 Variable_2 ns=3;i=436 0 EURange i=46 i=68 i=78 436 i=884 -1 1 1 Object_1 ns=3;i=442 3 Plant i=47 i=61 442 i=35 true i=85 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/Model.Types.bsd ================================================ ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/Model.Types.xsd ================================================ ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/ModelDesign.csv ================================================ GenericControllerType,345,ObjectType GenericControllerType_SerialNumber,346,Variable GenericControllerType_Manufacturer,347,Variable GenericControllerType_SetPoint,348,Variable GenericControllerType_SetPoint_Definition,349,Variable GenericControllerType_SetPoint_ValuePrecision,350,Variable GenericControllerType_SetPoint_EURange,351,Variable GenericControllerType_SetPoint_InstrumentRange,352,Variable GenericControllerType_SetPoint_EngineeringUnits,353,Variable GenericControllerType_Measurement,354,Variable GenericControllerType_Measurement_Definition,355,Variable GenericControllerType_Measurement_ValuePrecision,356,Variable GenericControllerType_Measurement_EURange,357,Variable GenericControllerType_Measurement_InstrumentRange,358,Variable GenericControllerType_Measurement_EngineeringUnits,359,Variable FlowControllerType,360,ObjectType FlowControllerType_SerialNumber,361,Variable FlowControllerType_Manufacturer,362,Variable FlowControllerType_SetPoint,363,Variable FlowControllerType_SetPoint_Definition,364,Variable FlowControllerType_SetPoint_ValuePrecision,365,Variable FlowControllerType_SetPoint_EURange,366,Variable FlowControllerType_SetPoint_InstrumentRange,367,Variable FlowControllerType_SetPoint_EngineeringUnits,368,Variable FlowControllerType_Measurement,369,Variable FlowControllerType_Measurement_Definition,370,Variable FlowControllerType_Measurement_ValuePrecision,371,Variable FlowControllerType_Measurement_EURange,372,Variable FlowControllerType_Measurement_InstrumentRange,373,Variable FlowControllerType_Measurement_EngineeringUnits,374,Variable LevelControllerType,375,ObjectType LevelControllerType_SerialNumber,376,Variable LevelControllerType_Manufacturer,377,Variable LevelControllerType_SetPoint,378,Variable LevelControllerType_SetPoint_Definition,379,Variable LevelControllerType_SetPoint_ValuePrecision,380,Variable LevelControllerType_SetPoint_EURange,381,Variable LevelControllerType_SetPoint_InstrumentRange,382,Variable LevelControllerType_SetPoint_EngineeringUnits,383,Variable LevelControllerType_Measurement,384,Variable LevelControllerType_Measurement_Definition,385,Variable LevelControllerType_Measurement_ValuePrecision,386,Variable LevelControllerType_Measurement_EURange,387,Variable LevelControllerType_Measurement_InstrumentRange,388,Variable LevelControllerType_Measurement_EngineeringUnits,389,Variable BoilerType,390,ObjectType BoilerType_WaterIn,391,Object BoilerType_WaterIn_Flow,392,Object BoilerType_WaterIn_Flow_SerialNumber,393,Variable BoilerType_WaterIn_Flow_Manufacturer,394,Variable BoilerType_WaterIn_Flow_SetPoint,395,Variable BoilerType_WaterIn_Flow_SetPoint_Definition,396,Variable BoilerType_WaterIn_Flow_SetPoint_ValuePrecision,397,Variable BoilerType_WaterIn_Flow_SetPoint_EURange,398,Variable BoilerType_WaterIn_Flow_SetPoint_InstrumentRange,399,Variable BoilerType_WaterIn_Flow_SetPoint_EngineeringUnits,400,Variable BoilerType_WaterIn_Flow_Measurement,401,Variable BoilerType_WaterIn_Flow_Measurement_Definition,402,Variable BoilerType_WaterIn_Flow_Measurement_ValuePrecision,403,Variable BoilerType_WaterIn_Flow_Measurement_EURange,404,Variable BoilerType_WaterIn_Flow_Measurement_InstrumentRange,405,Variable BoilerType_WaterIn_Flow_Measurement_EngineeringUnits,406,Variable BoilerType_SteamOut,407,Object BoilerType_SteamOut_Flow,408,Object BoilerType_SteamOut_Flow_SerialNumber,409,Variable BoilerType_SteamOut_Flow_Manufacturer,410,Variable BoilerType_SteamOut_Flow_SetPoint,411,Variable BoilerType_SteamOut_Flow_SetPoint_Definition,412,Variable BoilerType_SteamOut_Flow_SetPoint_ValuePrecision,413,Variable BoilerType_SteamOut_Flow_SetPoint_EURange,414,Variable BoilerType_SteamOut_Flow_SetPoint_InstrumentRange,415,Variable BoilerType_SteamOut_Flow_SetPoint_EngineeringUnits,416,Variable BoilerType_SteamOut_Flow_Measurement,417,Variable BoilerType_SteamOut_Flow_Measurement_Definition,418,Variable BoilerType_SteamOut_Flow_Measurement_ValuePrecision,419,Variable BoilerType_SteamOut_Flow_Measurement_EURange,420,Variable BoilerType_SteamOut_Flow_Measurement_InstrumentRange,421,Variable BoilerType_SteamOut_Flow_Measurement_EngineeringUnits,422,Variable BoilerType_Drum,423,Object BoilerType_Drum_Level,424,Object BoilerType_Drum_Level_SerialNumber,425,Variable BoilerType_Drum_Level_Manufacturer,426,Variable BoilerType_Drum_Level_SetPoint,427,Variable BoilerType_Drum_Level_SetPoint_Definition,428,Variable BoilerType_Drum_Level_SetPoint_ValuePrecision,429,Variable BoilerType_Drum_Level_SetPoint_EURange,430,Variable BoilerType_Drum_Level_SetPoint_InstrumentRange,431,Variable BoilerType_Drum_Level_SetPoint_EngineeringUnits,432,Variable BoilerType_Drum_Level_Measurement,433,Variable BoilerType_Drum_Level_Measurement_Definition,434,Variable BoilerType_Drum_Level_Measurement_ValuePrecision,435,Variable BoilerType_Drum_Level_Measurement_EURange,436,Variable BoilerType_Drum_Level_Measurement_InstrumentRange,437,Variable BoilerType_Drum_Level_Measurement_EngineeringUnits,438,Variable Engineering,439,View Operations,441,View Plant,442,Object ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/ModelDesign.xml ================================================ http://opcfoundation.org/UA/ http://opcfoundation.org/UA/Engineering http://opcfoundation.org/UA/Operations http://opcfoundation.org/UA/Views ua:Organizes ua:ViewsFolder ua:Organizes ua:ViewsFolder ua:Organizes ua:ObjectsFolder ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/Operations.Constants.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2019 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ using Opc.Ua; namespace Operations { #region Variable Identifiers /// /// A class that declares constants for all Variables in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Variables { /// /// The identifier for the SetPoint Variable. /// public const uint SetPoint = 443; /// /// The identifier for the SetPoint_EURange Variable. /// public const uint SetPoint_EURange = 446; /// /// The identifier for the Measurement Variable. /// public const uint Measurement = 449; /// /// The identifier for the Measurement_EURange Variable. /// public const uint Measurement_EURange = 452; } #endregion #region Variable Node Identifiers /// /// A class that declares constants for all Variables in the Model Design. /// /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class VariableIds { /// /// The identifier for the SetPoint Variable. /// public static readonly ExpandedNodeId SetPoint = new ExpandedNodeId(Operations.Variables.SetPoint, Operations.Namespaces.Operations); /// /// The identifier for the SetPoint_EURange Variable. /// public static readonly ExpandedNodeId SetPoint_EURange = new ExpandedNodeId(Operations.Variables.SetPoint_EURange, Operations.Namespaces.Operations); /// /// The identifier for the Measurement Variable. /// public static readonly ExpandedNodeId Measurement = new ExpandedNodeId(Operations.Variables.Measurement, Operations.Namespaces.Operations); /// /// The identifier for the Measurement_EURange Variable. /// public static readonly ExpandedNodeId Measurement_EURange = new ExpandedNodeId(Operations.Variables.Measurement_EURange, Operations.Namespaces.Operations); } #endregion #region BrowseName Declarations /// /// Declares all of the BrowseNames used in the Model Design. /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class BrowseNames { /// /// The BrowseName for the Measurement component. /// public const string Measurement = "Measurement"; /// /// The BrowseName for the SetPoint component. /// public const string SetPoint = "SetPoint"; } #endregion #region Namespace Declarations /// /// Defines constants for all namespaces referenced by the model design. /// [System.CodeDom.Compiler.GeneratedCodeAttribute("Opc.Ua.ModelCompiler", "1.0.0.0")] public static partial class Namespaces { /// /// The URI for the OpcUa namespace (.NET code namespace is 'Opc.Ua'). /// public const string OpcUa = "http://opcfoundation.org/UA/"; /// /// The URI for the OpcUaXsd namespace (.NET code namespace is 'Opc.Ua'). /// public const string OpcUaXsd = "http://opcfoundation.org/UA/2008/02/Types.xsd"; /// /// The URI for the Operations namespace (.NET code namespace is 'Operations'). /// public const string Operations = "http://opcfoundation.org/UA/Operations"; } #endregion } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/Operations.NodeIds.csv ================================================ Measurement,449,Variable SetPoint,443,Variable ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/Operations.NodeSet.xml ================================================  http://opcfoundation.org/UA/ http://opcfoundation.org/UA/Operations ns=1;i=443 Variable_2 1 SetPoint SetPoint 0 0 0 i=40 false i=2368 i=46 false ns=1;i=446 i=11 -2 1 1 0 false 0 ns=1;i=446 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=443 i=40 false i=68 i=884 -1 1 1 0 false 0 ns=1;i=449 Variable_2 1 Measurement Measurement 0 0 0 i=40 false i=2368 i=46 false ns=1;i=452 i=11 -2 1 1 0 false 0 ns=1;i=452 Variable_2 0 EURange EURange 0 0 0 i=46 true ns=1;i=449 i=40 false i=68 i=884 -1 1 1 0 false 0 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/Operations.NodeSet2.xml ================================================  http://opcfoundation.org/UA/Operations i=1 i=2 i=3 i=4 i=5 i=6 i=7 i=8 i=9 i=10 i=11 i=13 i=12 i=15 i=14 i=16 i=17 i=18 i=20 i=21 i=19 i=22 i=26 i=27 i=28 i=47 i=46 i=35 i=36 i=48 i=45 i=40 i=37 i=38 i=39 SetPoint ns=1;i=446 i=2368 EURange i=68 ns=1;i=443 Measurement ns=1;i=452 i=2368 EURange i=68 ns=1;i=449 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/Operations.PredefinedNodes.xml ================================================  http://opcfoundation.org/UA/Operations Variable_2 ns=1;i=443 1 SetPoint i=47 i=2368 443 i=11 1 1 Variable_2 ns=1;i=446 0 EURange i=46 i=68 446 i=884 -1 1 1 Variable_2 ns=1;i=449 1 Measurement i=47 i=2368 449 i=11 1 1 Variable_2 ns=1;i=452 0 EURange i=46 i=68 452 i=884 -1 1 1 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/Operations.Types.bsd ================================================ ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/Operations.Types.xsd ================================================ ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/OperationsDesign.csv ================================================ SetPoint,443,Variable SetPoint_Definition,444,Variable SetPoint_ValuePrecision,445,Variable SetPoint_EURange,446,Variable SetPoint_InstrumentRange,447,Variable SetPoint_EngineeringUnits,448,Variable Measurement,449,Variable Measurement_Definition,450,Variable Measurement_ValuePrecision,451,Variable Measurement_EURange,452,Variable Measurement_InstrumentRange,453,Variable Measurement_EngineeringUnits,454,Variable ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Generated/Views/Design/OperationsDesign.xml ================================================ http://opcfoundation.org/UA/ http://opcfoundation.org/UA/Operations ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/GlobalSuppressions.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ // This file is used by Code Analysis to maintain SuppressMessage // attributes that are applied to this project. // Project-level suppressions either have no target or are given // a specific target and scoped to a namespace, type, member, etc. using System.Diagnostics.CodeAnalysis; [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.GenericControllerState.Measurement")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerState.CustomController")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerState.Drum")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerState.FlowController")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerState.InputPipe")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerState.LevelController")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerState.OutputPipe")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerState.Simulation")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerStateMachineState.Halt")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerStateMachineState.Reset")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerStateMachineState.Resume")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerStateMachineState.Start")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerStateMachineState.Suspend")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerStateMachineState.UpdateRate")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.GenericControllerState.ControlOut")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.GenericControllerState.SetPoint")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.ByteValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.DoubleValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.FloatValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.Int16Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.Int32Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.Int64Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.IntegerValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.NumberValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.SByteValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.UInt16Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.UInt32Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.UInt64Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.UIntegerValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.ByteValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.DoubleValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.FloatValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.Int16Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.Int32Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.Int64Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.IntegerValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.NumberValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.SByteValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.UInt16Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.UInt32Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.UInt64Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.UIntegerValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.BooleanValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.ByteStringValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.ByteValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.DateTimeValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.DoubleValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.EnumerationValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.ExpandedNodeIdValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.FloatValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.GuidValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.Int16Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.Int32Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.Int64Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.IntegerValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.LocalizedTextValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.NodeIdValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.NumberValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.QualifiedNameValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.SByteValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.StatusCodeValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.StringValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.StructureValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.UInt16Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.UInt32Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.UInt64Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.UIntegerValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.VariantValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.XmlElementValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.MethodTestState.ArrayMethod1")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.MethodTestState.ArrayMethod2")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.MethodTestState.ArrayMethod3")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.MethodTestState.ScalarMethod1")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.MethodTestState.ScalarMethod2")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.MethodTestState.ScalarMethod3")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.MethodTestState.UserArrayMethod1")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.MethodTestState.UserArrayMethod2")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.MethodTestState.UserScalarMethod1")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.MethodTestState.UserScalarMethod2")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.BooleanValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.ByteStringValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.ByteValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.DateTimeValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.DoubleValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.EnumerationValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.ExpandedNodeIdValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.FloatValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.GuidValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.Int16Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.Int32Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.Int64Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.IntegerValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.LocalizedTextValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.NodeIdValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.NumberValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.QualifiedNameValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.SByteValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.StatusCodeValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.StringValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.StructureValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.UInt16Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.UInt32Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.UInt64Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.UIntegerValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.VariantValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.XmlElementValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.TestDataObjectState.CycleComplete")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.TestDataObjectState.GenerateValues")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.TestDataObjectState.SimulationActive")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.TestSystemConditionState.MonitoredNodeCount")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.BooleanValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.ByteStringValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.ByteValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.DateTimeValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.DoubleValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.ExpandedNodeIdValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.FloatValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.GuidValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.Int16Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.Int32Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.Int64Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.LocalizedTextValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.NodeIdValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.QualifiedNameValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.SByteValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.StatusCodeValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.StringValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.UInt16Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.UInt32Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.UInt64Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.VariantValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.XmlElementValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.BooleanValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.ByteStringValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.ByteValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.DateTimeValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.DoubleValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.ExpandedNodeIdValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.FloatValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.GuidValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.Int16Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.Int32Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.Int64Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.LocalizedTextValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.NodeIdValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.QualifiedNameValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.SByteValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.StatusCodeValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.StringValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.UInt16Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.UInt32Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.UInt64Value")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.VariantValue")] [assembly: SuppressMessage("Potential Code Quality Issues", "RECS0016:Bitwise operation on enum which has no [Flags] attribute", Justification = "Code generated by external tool", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.XmlElementValue")] [assembly: SuppressMessage("Style", "IDE0027:Use expression body for accessors", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerState.CustomController")] [assembly: SuppressMessage("Style", "IDE0027:Use expression body for accessors", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerState.Drum")] [assembly: SuppressMessage("Style", "IDE0027:Use expression body for accessors", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerState.FlowController")] [assembly: SuppressMessage("Style", "IDE0027:Use expression body for accessors", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerState.InputPipe")] [assembly: SuppressMessage("Style", "IDE0027:Use expression body for accessors", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerState.LevelController")] [assembly: SuppressMessage("Style", "IDE0027:Use expression body for accessors", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerState.OutputPipe")] [assembly: SuppressMessage("Style", "IDE0027:Use expression body for accessors", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerState.Simulation")] [assembly: SuppressMessage("Style", "IDE0027:Use expression body for accessors", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerStateMachineState.Halt")] [assembly: SuppressMessage("Style", "IDE0027:Use expression body for accessors", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerStateMachineState.Reset")] [assembly: SuppressMessage("Style", "IDE0027:Use expression body for accessors", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerStateMachineState.Resume")] [assembly: SuppressMessage("Style", "IDE0027:Use expression body for accessors", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerStateMachineState.Start")] [assembly: SuppressMessage("Style", "IDE0027:Use expression body for accessors", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerStateMachineState.Suspend")] [assembly: SuppressMessage("Style", "IDE0027:Use expression body for accessors", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.BoilerStateMachineState.UpdateRate")] [assembly: SuppressMessage("Style", "IDE0027:Use expression body for accessors", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.GenericControllerState.ControlOut")] [assembly: SuppressMessage("Style", "IDE0027:Use expression body for accessors", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.GenericControllerState.Measurement")] [assembly: SuppressMessage("Style", "IDE0027:Use expression body for accessors", Justification = "Code generated by external tool", Scope = "member", Target = "~P:Boiler.GenericControllerState.SetPoint")] [assembly: SuppressMessage("Redundancies in Symbol Declarations", "RECS0154:Parameter is never used", Justification = "Code generated by external tool", Scope = "member", Target = "~M:Vehicles.Types.TruckType.Initialize(System.Runtime.Serialization.StreamingContext)")] [assembly: SuppressMessage("Redundancies in Symbol Declarations", "RECS0154:Parameter is never used", Justification = "Code generated by external tool", Scope = "member", Target = "~M:Vehicles.Types.VehicleType.Initialize(System.Runtime.Serialization.StreamingContext)")] [assembly: SuppressMessage("Redundancies in Symbol Declarations", "RECS0154:Parameter is never used", Justification = "Code generated by external tool", Scope = "member", Target = "~M:Vehicles.Types.CarType.Initialize(System.Runtime.Serialization.StreamingContext)")] [assembly: SuppressMessage("Redundancies in Symbol Declarations", "RECS0154:Parameter is never used", Justification = "Code generated by external tool", Scope = "member", Target = "~M:SimpleEvents.CycleStepDataType.Initialize(System.Runtime.Serialization.StreamingContext)")] [assembly: SuppressMessage("Redundancies in Symbol Declarations", "RECS0154:Parameter is never used", Justification = "Code generated by external tool", Scope = "member", Target = "~M:TestData.ArrayValueDataType.Initialize(System.Runtime.Serialization.StreamingContext)")] [assembly: SuppressMessage("Redundancies in Symbol Declarations", "RECS0154:Parameter is never used", Justification = "Code generated by external tool", Scope = "member", Target = "~M:TestData.ScalarValueDataType.Initialize(System.Runtime.Serialization.StreamingContext)")] [assembly: SuppressMessage("Redundancies in Symbol Declarations", "RECS0154:Parameter is never used", Justification = "Code generated by external tool", Scope = "member", Target = "~M:TestData.UserArrayValueDataType.Initialize(System.Runtime.Serialization.StreamingContext)")] [assembly: SuppressMessage("Redundancies in Symbol Declarations", "RECS0154:Parameter is never used", Justification = "Code generated by external tool", Scope = "member", Target = "~M:TestData.UserScalarValueDataType.Initialize(System.Runtime.Serialization.StreamingContext)")] [assembly: SuppressMessage("Redundancies in Symbol Declarations", "RECS0154:Parameter is never used", Justification = "Code generated by external tool", Scope = "member", Target = "~M:Vehicles.Instances.BicycleType.Initialize(System.Runtime.Serialization.StreamingContext)")] [assembly: SuppressMessage("Naming", "CA1720:Identifier contains type name", Justification = "", Scope = "member", Target = "~F:DataAccess.UnderlyingSystemDataType.String")] [assembly: SuppressMessage("Usage", "CA2213:Disposable fields should be disposed", Justification = "", Scope = "member", Target = "~F:HistoricalEvents.HistoricalEventsNodeManager._simulationTimer")] [assembly: SuppressMessage("Usage", "CA2213:Disposable fields should be disposed", Justification = "", Scope = "member", Target = "~F:SimpleEvents.SimpleEventsNodeManager._simulationTimer")] [assembly: SuppressMessage("Usage", "CA2213:Disposable fields should be disposed", Justification = "", Scope = "member", Target = "~F:TestData.TestDataNodeManager._systemStatusCondition")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Alarms.AlarmConditionServerNodeManager.CreateAddressSpace(System.Collections.Generic.IDictionary{Opc.Ua.NodeId,System.Collections.Generic.IList{Opc.Ua.IReference}})")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:Alarms.AlarmConditionServerNodeManager.OnRaiseSystemEvents(System.Object)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Alarms.AlarmConditionServerNodeManager.OnRaiseSystemEvents(System.Object)")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Alarms.AreaState.#ctor(Opc.Ua.ISystemContext,Alarms.AreaState,Opc.Ua.NodeId,Alarms.AreaConfiguration)")] [assembly: SuppressMessage("Globalization", "CA1307:Specify StringComparison", Justification = "", Scope = "member", Target = "~M:Alarms.ModelUtils.ConstructIdForComponent(Opc.Ua.NodeState,System.UInt16)~Opc.Ua.NodeId")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Alarms.SourceState.ConditionRefresh(Opc.Ua.ISystemContext,System.Collections.Generic.List{Opc.Ua.IFilterTarget},System.Boolean)")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:Alarms.SourceState.GetRecordNumber(Opc.Ua.AlarmConditionState)~System.UInt32")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:Alarms.SourceState.GetUserName(Opc.Ua.ISystemContext)~System.String")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Alarms.UnderlyingSystem.CreateSource(System.String,Alarms.AlarmChangedEventHandler)~Alarms.UnderlyingSystemSource")] [assembly: SuppressMessage("Globalization", "CA1307:Specify StringComparison", Justification = "", Scope = "member", Target = "~M:Alarms.UnderlyingSystem.CreateSource(System.String,Alarms.AlarmChangedEventHandler)~Alarms.UnderlyingSystemSource")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:Alarms.UnderlyingSystem.DoSimulation(System.Object)")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:Alarms.UnderlyingSystemSource.DoSimulation(System.Int64,System.Int32)")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:Alarms.UnderlyingSystemSource.ReportAlarmChange(Alarms.UnderlyingSystemAlarm)")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Boiler.BoilerNodeManager.#ctor(Opc.Ua.Server.IServerInternal,Opc.Ua.ApplicationConfiguration)")] [assembly: SuppressMessage("Globalization", "CA1307:Specify StringComparison", Justification = "", Scope = "member", Target = "~M:Boiler.BoilerNodeManager.UpdateDisplayName(Opc.Ua.BaseInstanceState,System.String)")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:Boiler.BoilerNodeManager.UpdateDisplayName(Opc.Ua.BaseInstanceState,System.String)")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:Boiler.BoilerState.Adjust(System.Double,System.Double,System.Double,Opc.Ua.Range)~System.Double")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:Boiler.BoilerState.DoSimulation(System.Object)")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Boiler.BoilerState.FindChild(Opc.Ua.ISystemContext,Opc.Ua.QualifiedName,System.Boolean,Opc.Ua.BaseInstanceState)~Opc.Ua.BaseInstanceState")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Boiler.BoilerState.GetChildren(Opc.Ua.ISystemContext,System.Collections.Generic.IList{Opc.Ua.BaseInstanceState})")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:Boiler.BoilerState.GetPercentage(Opc.Ua.AnalogItemState{System.Double})~System.Double")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:Boiler.BoilerState.GetValue(System.Double,Opc.Ua.Range)~System.Double")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Boiler.BoilerStateMachineState.FindChild(Opc.Ua.ISystemContext,Opc.Ua.QualifiedName,System.Boolean,Opc.Ua.BaseInstanceState)~Opc.Ua.BaseInstanceState")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Boiler.BoilerStateMachineState.GetChildren(Opc.Ua.ISystemContext,System.Collections.Generic.IList{Opc.Ua.BaseInstanceState})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Boiler.GenericControllerState.FindChild(Opc.Ua.ISystemContext,Opc.Ua.QualifiedName,System.Boolean,Opc.Ua.BaseInstanceState)~Opc.Ua.BaseInstanceState")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Boiler.GenericControllerState.GetChildren(Opc.Ua.ISystemContext,System.Collections.Generic.IList{Opc.Ua.BaseInstanceState})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Boiler.GenericControllerState.UpdateMeasurement(Opc.Ua.AnalogItemState{System.Double})~System.Double")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:DataAccess.BlockState.#ctor(DataAccess.DataAccessNodeManager,Opc.Ua.NodeId,DataAccess.UnderlyingSystemBlock)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:DataAccess.BlockState.#ctor(DataAccess.DataAccessNodeManager,Opc.Ua.NodeId,DataAccess.UnderlyingSystemBlock)")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:DataAccess.BlockState.OnWriteTagValue(Opc.Ua.ISystemContext,Opc.Ua.NodeState,System.Object@)~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:DataAccess.BlockState.PopulateBrowser(Opc.Ua.ISystemContext,Opc.Ua.NodeBrowser)")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:DataAccess.BlockState.StartMonitoring(Opc.Ua.Server.ServerSystemContext)")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:DataAccess.BlockState.StopMonitoring(Opc.Ua.Server.ServerSystemContext)~System.Boolean")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:DataAccess.BlockState.UpdateVariable(Opc.Ua.ISystemContext,DataAccess.UnderlyingSystemTag,Opc.Ua.BaseVariableState)")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:DataAccess.DataAccessNodeManager.#ctor(Opc.Ua.Server.IServerInternal,Opc.Ua.ApplicationConfiguration)")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:DataAccess.DataAccessNodeManager.CreateAddressSpace(System.Collections.Generic.IDictionary{Opc.Ua.NodeId,System.Collections.Generic.IList{Opc.Ua.IReference}})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:DataAccess.DataAccessNodeManager.GetManagerHandle(Opc.Ua.Server.ServerSystemContext,Opc.Ua.NodeId,System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})~Opc.Ua.Server.NodeHandle")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:DataAccess.DataAccessNodeManager.ValidateNode(Opc.Ua.Server.ServerSystemContext,Opc.Ua.Server.NodeHandle,System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})~Opc.Ua.NodeState")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:DataAccess.DataAccessServerConfiguration.Initialize")] [assembly: SuppressMessage("Globalization", "CA1307:Specify StringComparison", Justification = "", Scope = "member", Target = "~M:DataAccess.ModelUtils.ConstructIdForComponent(Opc.Ua.NodeState,System.UInt16)~Opc.Ua.NodeId")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:DataAccess.SegmentState.#ctor(Opc.Ua.ISystemContext,Opc.Ua.NodeId,DataAccess.UnderlyingSystemSegment)")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:DataAccess.SegmentState.PopulateBrowser(Opc.Ua.ISystemContext,Opc.Ua.NodeBrowser)")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:DataAccess.UnderlyingSystem.DoSimulation(System.Object)")] [assembly: SuppressMessage("Globalization", "CA1307:Specify StringComparison", Justification = "", Scope = "member", Target = "~M:DataAccess.UnderlyingSystem.FindBlocks(System.String)~System.Collections.Generic.IList{System.String}")] [assembly: SuppressMessage("Globalization", "CA1307:Specify StringComparison", Justification = "", Scope = "member", Target = "~M:DataAccess.UnderlyingSystem.FindSegments(System.String)~System.Collections.Generic.IList{DataAccess.UnderlyingSystemSegment}")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:DataAccess.UnderlyingSystemBlock.DoSimulation(System.Int64,System.Int32,Opc.Ua.Test.TestDataGenerator)")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:DataAccess.UnderlyingSystemBlock.DoSimulation(System.Int64,System.Int32,Opc.Ua.Test.TestDataGenerator)")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:DataAccess.UnderlyingSystemBlock.UpdateTagMetadata(DataAccess.UnderlyingSystemTag,Opc.Ua.Test.TestDataGenerator)~System.Boolean")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:DataAccess.UnderlyingSystemBlock.UpdateTagValue(DataAccess.UnderlyingSystemTag,Opc.Ua.Test.TestDataGenerator)~System.Boolean")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:DataAccess.UnderlyingSystemBlock.WriteTagValue(System.String,System.Object)~System.UInt32")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.ArchiveItem.#ctor(System.String,System.Reflection.Assembly,System.String)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.ArchiveItemState.DeleteHistory(Opc.Ua.SystemContext,System.DateTime)~System.UInt32")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.ArchiveItemState.DeleteHistory(Opc.Ua.SystemContext,System.DateTime)~System.UInt32")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.ArchiveItemState.DeleteHistory(Opc.Ua.SystemContext,System.DateTime,System.DateTime,System.Boolean)~System.UInt32")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.ArchiveItemState.DeleteHistory(Opc.Ua.SystemContext,System.DateTime,System.DateTime,System.Boolean)~System.UInt32")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.ArchiveItemState.FindValueAfter(System.Data.DataView,System.Int32,System.Boolean,System.Boolean@)~System.Int32")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.ArchiveItemState.FindValueAfter(System.Data.DataView,System.Int32,System.Boolean,System.Boolean@)~System.Int32")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.ArchiveItemState.FindValueAtOrBefore(System.Data.DataView,System.DateTime,System.Boolean,System.Boolean@)~System.Int32")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.ArchiveItemState.FindValueAtOrBefore(System.Data.DataView,System.DateTime,System.Boolean,System.Boolean@)~System.Int32")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.ArchiveItemState.GetModificationInfo(Opc.Ua.SystemContext,Opc.Ua.HistoryUpdateType)~Opc.Ua.ModificationInfo")] [assembly: SuppressMessage("Usage", "CA1801:Review unused parameters", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.ArchiveItemState.ReadHistory(System.DateTime,System.DateTime,System.Boolean,Opc.Ua.QualifiedName)~System.Data.DataView")] [assembly: SuppressMessage("Usage", "CA1801:Review unused parameters", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.ArchiveItemState.UpdateAnnotations(Opc.Ua.SystemContext,Opc.Ua.Annotation,Opc.Ua.DataValue,Opc.Ua.PerformUpdateType)~System.UInt32")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.ArchiveItemState.UpdateAnnotations(Opc.Ua.SystemContext,Opc.Ua.Annotation,Opc.Ua.DataValue,Opc.Ua.PerformUpdateType)~System.UInt32")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.ArchiveItemState.UpdateAnnotations(Opc.Ua.SystemContext,Opc.Ua.Annotation,Opc.Ua.DataValue,Opc.Ua.PerformUpdateType)~System.UInt32")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.ArchiveItemState.UpdateHistory(Opc.Ua.SystemContext,Opc.Ua.DataValue,Opc.Ua.PerformUpdateType)~System.UInt32")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.ArchiveItemState.UpdateHistory(Opc.Ua.SystemContext,Opc.Ua.DataValue,Opc.Ua.PerformUpdateType)~System.UInt32")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.DataFileReader.CreateData(HistoricalAccess.ArchiveItem)")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.DataFileReader.CreateDataSet~System.Data.DataSet")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.DataFileReader.ExtractField(System.Int32,System.String@,Opc.Ua.BuiltInType@)~System.Boolean")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.DataFileReader.ExtractField(System.Int32,System.String@,Opc.Ua.StatusCode@)~System.Boolean")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.DataFileReader.ExtractField(System.Int32,System.String@,System.Int32@)~System.Boolean")] [assembly: SuppressMessage("Globalization", "CA1305:Specify IFormatProvider", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.DataFileReader.ExtractField(System.Int32,System.String@,System.Int32@)~System.Boolean")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.DataFileReader.ExtractField(System.String@)~System.String")] [assembly: SuppressMessage("Globalization", "CA1307:Specify StringComparison", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.DataFileReader.ExtractField(System.String@)~System.String")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.DataFileReader.LoadConfiguration(Opc.Ua.ISystemContext,HistoricalAccess.ArchiveItem)~System.Boolean")] [assembly: SuppressMessage("Usage", "CA1801:Review unused parameters", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.DataFileReader.LoadConfiguration(Opc.Ua.ISystemContext,HistoricalAccess.ArchiveItem)~System.Boolean")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.DataFileReader.LoadHistoryData(Opc.Ua.ISystemContext,HistoricalAccess.ArchiveItem)")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerConfiguration.Initialize")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.CreateAddressSpace(System.Collections.Generic.IDictionary{Opc.Ua.NodeId,System.Collections.Generic.IList{Opc.Ua.IReference}})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.CreateAddressSpace(System.Collections.Generic.IDictionary{Opc.Ua.NodeId,System.Collections.Generic.IList{Opc.Ua.IReference}})")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.CreateFolderFromResources(Opc.Ua.NodeState,System.String)")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.DoSimulation(System.Object)")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.HistoryDeleteAtTime(Opc.Ua.Server.ServerSystemContext,System.Collections.Generic.IList{Opc.Ua.DeleteAtTimeDetails},System.Collections.Generic.IList{Opc.Ua.HistoryUpdateResult},System.Collections.Generic.IList{Opc.Ua.ServiceResult},System.Collections.Generic.List{Opc.Ua.Server.NodeHandle},System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.HistoryDeleteAtTime(Opc.Ua.Server.ServerSystemContext,System.Collections.Generic.IList{Opc.Ua.DeleteAtTimeDetails},System.Collections.Generic.IList{Opc.Ua.HistoryUpdateResult},System.Collections.Generic.IList{Opc.Ua.ServiceResult},System.Collections.Generic.List{Opc.Ua.Server.NodeHandle},System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.HistoryDeleteRawModified(Opc.Ua.Server.ServerSystemContext,System.Collections.Generic.IList{Opc.Ua.DeleteRawModifiedDetails},System.Collections.Generic.IList{Opc.Ua.HistoryUpdateResult},System.Collections.Generic.IList{Opc.Ua.ServiceResult},System.Collections.Generic.List{Opc.Ua.Server.NodeHandle},System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.HistoryDeleteRawModified(Opc.Ua.Server.ServerSystemContext,System.Collections.Generic.IList{Opc.Ua.DeleteRawModifiedDetails},System.Collections.Generic.IList{Opc.Ua.HistoryUpdateResult},System.Collections.Generic.IList{Opc.Ua.ServiceResult},System.Collections.Generic.List{Opc.Ua.Server.NodeHandle},System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.HistoryReadAtTime(Opc.Ua.Server.ServerSystemContext,Opc.Ua.ReadAtTimeDetails,Opc.Ua.TimestampsToReturn,System.Collections.Generic.IList{Opc.Ua.HistoryReadValueId},System.Collections.Generic.IList{Opc.Ua.HistoryReadResult},System.Collections.Generic.IList{Opc.Ua.ServiceResult},System.Collections.Generic.List{Opc.Ua.Server.NodeHandle},System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.HistoryReadAtTime(Opc.Ua.Server.ServerSystemContext,Opc.Ua.ReadAtTimeDetails,Opc.Ua.TimestampsToReturn,System.Collections.Generic.IList{Opc.Ua.HistoryReadValueId},System.Collections.Generic.IList{Opc.Ua.HistoryReadResult},System.Collections.Generic.IList{Opc.Ua.ServiceResult},System.Collections.Generic.List{Opc.Ua.Server.NodeHandle},System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.HistoryReadProcessed(Opc.Ua.Server.ServerSystemContext,Opc.Ua.ReadProcessedDetails,Opc.Ua.TimestampsToReturn,System.Collections.Generic.IList{Opc.Ua.HistoryReadValueId},System.Collections.Generic.IList{Opc.Ua.HistoryReadResult},System.Collections.Generic.IList{Opc.Ua.ServiceResult},System.Collections.Generic.List{Opc.Ua.Server.NodeHandle},System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.HistoryReadProcessed(Opc.Ua.Server.ServerSystemContext,Opc.Ua.ReadProcessedDetails,Opc.Ua.TimestampsToReturn,System.Collections.Generic.IList{Opc.Ua.HistoryReadValueId},System.Collections.Generic.IList{Opc.Ua.HistoryReadResult},System.Collections.Generic.IList{Opc.Ua.ServiceResult},System.Collections.Generic.List{Opc.Ua.Server.NodeHandle},System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.HistoryReadRawModified(Opc.Ua.Server.ServerSystemContext,Opc.Ua.ReadRawModifiedDetails,Opc.Ua.TimestampsToReturn,System.Collections.Generic.IList{Opc.Ua.HistoryReadValueId},System.Collections.Generic.IList{Opc.Ua.HistoryReadResult},System.Collections.Generic.IList{Opc.Ua.ServiceResult},System.Collections.Generic.List{Opc.Ua.Server.NodeHandle},System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.HistoryReadRawModified(Opc.Ua.Server.ServerSystemContext,Opc.Ua.ReadRawModifiedDetails,Opc.Ua.TimestampsToReturn,System.Collections.Generic.IList{Opc.Ua.HistoryReadValueId},System.Collections.Generic.IList{Opc.Ua.HistoryReadResult},System.Collections.Generic.IList{Opc.Ua.ServiceResult},System.Collections.Generic.List{Opc.Ua.Server.NodeHandle},System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.HistoryReleaseContinuationPoints(Opc.Ua.Server.ServerSystemContext,System.Collections.Generic.IList{Opc.Ua.HistoryReadValueId},System.Collections.Generic.IList{Opc.Ua.ServiceResult},System.Collections.Generic.List{Opc.Ua.Server.NodeHandle},System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.HistoryUpdateData(Opc.Ua.Server.ServerSystemContext,System.Collections.Generic.IList{Opc.Ua.UpdateDataDetails},System.Collections.Generic.IList{Opc.Ua.HistoryUpdateResult},System.Collections.Generic.IList{Opc.Ua.ServiceResult},System.Collections.Generic.List{Opc.Ua.Server.NodeHandle},System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.HistoryUpdateData(Opc.Ua.Server.ServerSystemContext,System.Collections.Generic.IList{Opc.Ua.UpdateDataDetails},System.Collections.Generic.IList{Opc.Ua.HistoryUpdateResult},System.Collections.Generic.IList{Opc.Ua.ServiceResult},System.Collections.Generic.List{Opc.Ua.Server.NodeHandle},System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.HistoryUpdateStructureData(Opc.Ua.Server.ServerSystemContext,System.Collections.Generic.IList{Opc.Ua.UpdateStructureDataDetails},System.Collections.Generic.IList{Opc.Ua.HistoryUpdateResult},System.Collections.Generic.IList{Opc.Ua.ServiceResult},System.Collections.Generic.List{Opc.Ua.Server.NodeHandle},System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.HistoryUpdateStructureData(Opc.Ua.Server.ServerSystemContext,System.Collections.Generic.IList{Opc.Ua.UpdateStructureDataDetails},System.Collections.Generic.IList{Opc.Ua.HistoryUpdateResult},System.Collections.Generic.IList{Opc.Ua.ServiceResult},System.Collections.Generic.List{Opc.Ua.Server.NodeHandle},System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.New(Opc.Ua.ISystemContext,Opc.Ua.NodeState)~Opc.Ua.NodeId")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.QueueProcessedValues(Opc.Ua.Server.ServerSystemContext,Opc.Ua.Server.IAggregateCalculator,Opc.Ua.NumericRange,Opc.Ua.QualifiedName,System.Boolean,System.Boolean,System.Collections.Generic.LinkedList{Opc.Ua.DataValue})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.Read(Opc.Ua.Server.ServerSystemContext,System.Collections.Generic.IList{Opc.Ua.ReadValueId},System.Collections.Generic.IList{Opc.Ua.DataValue},System.Collections.Generic.IList{Opc.Ua.ServiceResult},System.Collections.Generic.List{Opc.Ua.Server.NodeHandle},System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.Reload(Opc.Ua.Server.ServerSystemContext,Opc.Ua.Server.NodeHandle)~HistoricalAccess.ArchiveItemState")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.ReviseAggregateFilter(Opc.Ua.Server.ServerSystemContext,Opc.Ua.Server.NodeHandle,System.Double,System.UInt32,Opc.Ua.Server.ServerAggregateFilter)~Opc.Ua.StatusCode")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.RowToDataValue(Opc.Ua.Server.ServerSystemContext,Opc.Ua.HistoryReadValueId,System.Data.DataRowView,System.Boolean)~Opc.Ua.DataValue")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.ValidateNode(Opc.Ua.Server.ServerSystemContext,Opc.Ua.Server.NodeHandle,System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})~Opc.Ua.NodeState")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.HistoricalAccessServerNodeManager.ValidateNode(Opc.Ua.Server.ServerSystemContext,Opc.Ua.Server.NodeHandle,System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})~Opc.Ua.NodeState")] [assembly: SuppressMessage("Globalization", "CA1307:Specify StringComparison", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.NodeTypes.ConstructIdForComponent(Opc.Ua.NodeState,System.UInt16)~Opc.Ua.NodeId")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalAccess.UnderlyingSystem.GetItemState(Opc.Ua.ISystemContext,Opc.Ua.Server.ParsedNodeId)~HistoricalAccess.ArchiveItemState")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:HistoricalEvents.HistoricalEventsNodeManager.CreateAddressSpace(System.Collections.Generic.IDictionary{Opc.Ua.NodeId,System.Collections.Generic.IList{Opc.Ua.IReference}})")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:HistoricalEvents.HistoricalEventsNodeManager.CreateHistoryReadRequest(Opc.Ua.Server.ServerSystemContext,Opc.Ua.ReadEventDetails,Opc.Ua.Server.NodeHandle,Opc.Ua.HistoryReadValueId)~HistoricalEvents.HistoricalEventsNodeManager.HistoryReadRequest")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:HistoricalEvents.HistoricalEventsNodeManager.DoSimulation(System.Object)")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:HistoricalEvents.HistoricalEventsNodeManager.DoSimulation(System.Object)")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:HistoricalEvents.HistoricalEventsNodeManager.HistoryDeleteEvents(Opc.Ua.Server.ServerSystemContext,System.Collections.Generic.IList{Opc.Ua.DeleteEventDetails},System.Collections.Generic.IList{Opc.Ua.HistoryUpdateResult},System.Collections.Generic.IList{Opc.Ua.ServiceResult},System.Collections.Generic.List{Opc.Ua.Server.NodeHandle},System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalEvents.HistoricalEventsNodeManager.HistoryDeleteEvents(Opc.Ua.Server.ServerSystemContext,System.Collections.Generic.IList{Opc.Ua.DeleteEventDetails},System.Collections.Generic.IList{Opc.Ua.HistoryUpdateResult},System.Collections.Generic.IList{Opc.Ua.ServiceResult},System.Collections.Generic.List{Opc.Ua.Server.NodeHandle},System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalEvents.HistoricalEventsNodeManager.HistoryReadEvents(Opc.Ua.Server.ServerSystemContext,Opc.Ua.ReadEventDetails,Opc.Ua.TimestampsToReturn,System.Collections.Generic.IList{Opc.Ua.HistoryReadValueId},System.Collections.Generic.IList{Opc.Ua.HistoryReadResult},System.Collections.Generic.IList{Opc.Ua.ServiceResult},System.Collections.Generic.List{Opc.Ua.Server.NodeHandle},System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalEvents.HistoricalEventsNodeManager.HistoryReleaseContinuationPoints(Opc.Ua.Server.ServerSystemContext,System.Collections.Generic.IList{Opc.Ua.HistoryReadValueId},System.Collections.Generic.IList{Opc.Ua.ServiceResult},System.Collections.Generic.List{Opc.Ua.Server.NodeHandle},System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalEvents.HistoricalEventsNodeManager.HistoryUpdateEvents(Opc.Ua.Server.ServerSystemContext,System.Collections.Generic.IList{Opc.Ua.UpdateEventDetails},System.Collections.Generic.IList{Opc.Ua.HistoryUpdateResult},System.Collections.Generic.IList{Opc.Ua.ServiceResult},System.Collections.Generic.List{Opc.Ua.Server.NodeHandle},System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalEvents.HistoricalEventsNodeManager.New(Opc.Ua.ISystemContext,Opc.Ua.NodeState)~Opc.Ua.NodeId")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:HistoricalEvents.HistoricalEventsServerConfiguration.Initialize")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:HistoricalEvents.ReportGenerator.DeleteEvent(System.String)~System.Boolean")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:HistoricalEvents.ReportGenerator.GetAreas~System.String[]")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalEvents.ReportGenerator.GetFluidLevelTestReport(Opc.Ua.ISystemContext,System.UInt16,System.Data.DataRow)~Opc.Ua.BaseEventState")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:HistoricalEvents.ReportGenerator.GetInjectionTestReport(Opc.Ua.ISystemContext,System.UInt16,System.Data.DataRow)~Opc.Ua.BaseEventState")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:HistoricalEvents.ReportGenerator.GetWells(System.String)~HistoricalEvents.ReportGenerator.WellInfo[]")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:MemoryBuffer.MemoryBufferNodeManager.#ctor(Opc.Ua.Server.IServerInternal,Opc.Ua.ApplicationConfiguration)")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:MemoryBuffer.MemoryBufferNodeManager.DeleteMonitoredItem(Opc.Ua.ISystemContext,Opc.Ua.Server.IMonitoredItem,System.Boolean@)~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:MemoryBuffer.MemoryBufferNodeManager.GetManagerHandle(Opc.Ua.ISystemContext,Opc.Ua.NodeId,System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})~System.Object")] [assembly: SuppressMessage("Globalization", "CA1307:Specify StringComparison", Justification = "", Scope = "member", Target = "~M:MemoryBuffer.MemoryBufferNodeManager.GetManagerHandle(Opc.Ua.ISystemContext,Opc.Ua.NodeId,System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})~System.Object")] [assembly: SuppressMessage("Globalization", "CA1305:Specify IFormatProvider", Justification = "", Scope = "member", Target = "~M:MemoryBuffer.MemoryBufferNodeManager.GetManagerHandle(Opc.Ua.ISystemContext,Opc.Ua.NodeId,System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})~System.Object")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:MemoryBuffer.MemoryBufferNodeManager.ModifyMonitoredItem(Opc.Ua.ISystemContext,Opc.Ua.DiagnosticsMasks,Opc.Ua.TimestampsToReturn,Opc.Ua.Server.IMonitoredItem,Opc.Ua.MonitoredItemModifyRequest,Opc.Ua.MonitoringFilterResult@)~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:MemoryBuffer.MemoryBufferNodeManager.SetMonitoringMode(Opc.Ua.ISystemContext,Opc.Ua.Server.IMonitoredItem,Opc.Ua.MonitoringMode,System.Boolean@)~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:MemoryBuffer.MemoryBufferNodeManager.SetMonitoringMode(Opc.Ua.ISystemContext,Opc.Ua.Server.IMonitoredItem,Opc.Ua.MonitoringMode,System.Boolean@)~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:MemoryBuffer.MemoryBufferState.DeleteItem(MemoryBuffer.MemoryBufferMonitoredItem)")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:MemoryBuffer.MemoryBufferState.FindChild(Opc.Ua.ISystemContext,Opc.Ua.QualifiedName,System.Boolean,Opc.Ua.BaseInstanceState)~Opc.Ua.BaseInstanceState")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:MemoryBuffer.MemoryBufferState.GetChildren(Opc.Ua.ISystemContext,System.Collections.Generic.IList{Opc.Ua.BaseInstanceState})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:MemoryBuffer.MemoryTagState.#ctor(MemoryBuffer.MemoryBufferState,System.UInt32)")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.MonitoredNode.ConditionRefresh(Opc.Ua.ISystemContext,Opc.Ua.Server.IEventMonitoredItem)")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.#ctor(Opc.Ua.Server.IServerInternal)")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.AddExternalReference(Opc.Ua.NodeId,Opc.Ua.NodeId,System.Boolean,Opc.Ua.NodeId,System.Collections.Generic.IDictionary{Opc.Ua.NodeId,System.Collections.Generic.IList{Opc.Ua.IReference}})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.AddExternalReference(Opc.Ua.NodeId,Opc.Ua.NodeId,System.Boolean,Opc.Ua.NodeId,System.Collections.Generic.IDictionary{Opc.Ua.NodeId,System.Collections.Generic.IList{Opc.Ua.IReference}})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.AddReferences(System.Collections.Generic.IDictionary{Opc.Ua.NodeId,System.Collections.Generic.IList{Opc.Ua.IReference}})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.AddTypesToTypeTree(Opc.Ua.BaseTypeState)")] [assembly: SuppressMessage("Naming", "CA1716:Identifiers should not match keywords", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.Call(Opc.Ua.ISystemContext,Opc.Ua.CallMethodRequest,Opc.Ua.NodeState,Opc.Ua.MethodState,Opc.Ua.CallMethodResult)~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.Call(Opc.Ua.ISystemContext,Opc.Ua.CallMethodRequest,Opc.Ua.NodeState,Opc.Ua.MethodState,Opc.Ua.CallMethodResult)~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.Call(Opc.Ua.Server.OperationContext,System.Collections.Generic.IList{Opc.Ua.CallMethodRequest},System.Collections.Generic.IList{Opc.Ua.CallMethodResult},System.Collections.Generic.IList{Opc.Ua.ServiceResult})")] [assembly: SuppressMessage("Naming", "CA1716:Identifiers should not match keywords", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.Call(Opc.Ua.Server.OperationContext,System.Collections.Generic.IList{Opc.Ua.CallMethodRequest},System.Collections.Generic.IList{Opc.Ua.CallMethodResult},System.Collections.Generic.IList{Opc.Ua.ServiceResult})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.ConditionRefresh(Opc.Ua.Server.OperationContext,System.Collections.Generic.IList{Opc.Ua.Server.IEventMonitoredItem})~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.DeleteMonitoredItem(Opc.Ua.ISystemContext,Opc.Ua.Server.IMonitoredItem,System.Boolean@)~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.DeleteMonitoredItems(Opc.Ua.Server.OperationContext,System.Collections.Generic.IList{Opc.Ua.Server.IMonitoredItem},System.Collections.Generic.IList{System.Boolean},System.Collections.Generic.IList{Opc.Ua.ServiceResult})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.DeleteReference(System.Object,Opc.Ua.NodeId,System.Boolean,Opc.Ua.ExpandedNodeId,System.Boolean)~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Usage", "CA1816:Dispose methods should call SuppressFinalize", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.Dispose")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.DoSample(System.Object)")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.HistoryRead(Opc.Ua.Server.OperationContext,Opc.Ua.HistoryReadDetails,Opc.Ua.TimestampsToReturn,System.Boolean,System.Collections.Generic.IList{Opc.Ua.HistoryReadValueId},System.Collections.Generic.IList{Opc.Ua.HistoryReadResult},System.Collections.Generic.IList{Opc.Ua.ServiceResult})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.HistoryUpdate(Opc.Ua.Server.OperationContext,System.Type,System.Collections.Generic.IList{Opc.Ua.HistoryUpdateDetails},System.Collections.Generic.IList{Opc.Ua.HistoryUpdateResult},System.Collections.Generic.IList{Opc.Ua.ServiceResult})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.IsNodeIdInNamespace(Opc.Ua.NodeId)~System.Boolean")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.ModifyMonitoredItem(Opc.Ua.ISystemContext,Opc.Ua.DiagnosticsMasks,Opc.Ua.TimestampsToReturn,Opc.Ua.Server.IMonitoredItem,Opc.Ua.MonitoredItemModifyRequest,Opc.Ua.MonitoringFilterResult@)~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.ModifyMonitoredItems(Opc.Ua.Server.OperationContext,Opc.Ua.TimestampsToReturn,System.Collections.Generic.IList{Opc.Ua.Server.IMonitoredItem},System.Collections.Generic.IList{Opc.Ua.MonitoredItemModifyRequest},System.Collections.Generic.IList{Opc.Ua.ServiceResult},System.Collections.Generic.IList{Opc.Ua.MonitoringFilterResult})")] [assembly: SuppressMessage("Naming", "CA1716:Identifiers should not match keywords", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.New(Opc.Ua.ISystemContext,Opc.Ua.NodeState)~Opc.Ua.NodeId")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.New(Opc.Ua.ISystemContext,Opc.Ua.NodeState)~Opc.Ua.NodeId")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.Read(Opc.Ua.Server.OperationContext,System.Double,System.Collections.Generic.IList{Opc.Ua.ReadValueId},System.Collections.Generic.IList{Opc.Ua.DataValue},System.Collections.Generic.IList{Opc.Ua.ServiceResult})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.SetMonitoringMode(Opc.Ua.ISystemContext,Opc.Ua.Server.IMonitoredItem,Opc.Ua.MonitoringMode,System.Boolean@)~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.SetMonitoringMode(Opc.Ua.Server.OperationContext,Opc.Ua.MonitoringMode,System.Collections.Generic.IList{Opc.Ua.Server.IMonitoredItem},System.Collections.Generic.IList{System.Boolean},System.Collections.Generic.IList{Opc.Ua.ServiceResult})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.SubscribeToAllEvents(Opc.Ua.ISystemContext,Opc.Ua.Server.IEventMonitoredItem,System.Boolean,Opc.Ua.NodeState)")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.TranslateBrowsePath(Opc.Ua.Server.OperationContext,System.Object,Opc.Ua.RelativePathElement,System.Collections.Generic.IList{Opc.Ua.ExpandedNodeId},System.Collections.Generic.IList{Opc.Ua.NodeId})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.ValidateDataChangeFilter(Opc.Ua.ISystemContext,Opc.Ua.NodeState,System.UInt32,Opc.Ua.ExtensionObject,Opc.Ua.DataChangeFilter@,Opc.Ua.Range@)~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.ValidateNode(Opc.Ua.Server.ServerSystemContext,Opc.Ua.NodeState)~System.Boolean")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Sample.SampleNodeManager.Write(Opc.Ua.Server.OperationContext,System.Collections.Generic.IList{Opc.Ua.WriteValue},System.Collections.Generic.IList{Opc.Ua.ServiceResult})")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:Opc.Ua.Test.TestDataGenerator.LoadStringData(System.String)~System.Collections.Generic.SortedDictionary{System.String,System.String[]}")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:PerfTest.MemoryRegister.OnUpdate(System.Object)")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:PerfTest.MemoryRegisterState.#ctor(PerfTest.MemoryRegister,System.UInt16)")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:PerfTest.ModelUtils.GetRegisterId(PerfTest.MemoryRegister,System.UInt16)~Opc.Ua.NodeId")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:PerfTest.ModelUtils.GetRegisterVariable(PerfTest.MemoryRegister,System.Int32,System.UInt16)~Opc.Ua.BaseDataVariableState")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:PerfTest.ModelUtils.GetRegisterVariableId(PerfTest.MemoryRegister,System.Int32,System.UInt16)~Opc.Ua.NodeId")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:PerfTest.PerfTestNodeManager.#ctor(Opc.Ua.Server.IServerInternal,Opc.Ua.ApplicationConfiguration)")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:PerfTest.PerfTestNodeManager.CreateAddressSpace(System.Collections.Generic.IDictionary{Opc.Ua.NodeId,System.Collections.Generic.IList{Opc.Ua.IReference}})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:PerfTest.PerfTestNodeManager.GetManagerHandle(Opc.Ua.Server.ServerSystemContext,Opc.Ua.NodeId,System.Collections.Generic.IDictionary{Opc.Ua.NodeId,Opc.Ua.NodeState})~Opc.Ua.Server.NodeHandle")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:PerfTest.PerfTestNodeManager.New(Opc.Ua.ISystemContext,Opc.Ua.NodeState)~Opc.Ua.NodeId")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:PerfTest.PerfTestNodeManager.OnCreateMonitoredItemsComplete(Opc.Ua.Server.ServerSystemContext,System.Collections.Generic.IList{Opc.Ua.Server.IMonitoredItem})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:PerfTest.PerfTestNodeManager.OnDeleteMonitoredItemsComplete(Opc.Ua.Server.ServerSystemContext,System.Collections.Generic.IList{Opc.Ua.Server.IMonitoredItem})")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:PerfTest.PerfTestServerConfiguration.Initialize")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Plc.PlcNodeManager.CreateAddressSpace(System.Collections.Generic.IDictionary{Opc.Ua.NodeId,System.Collections.Generic.IList{Opc.Ua.IReference}})")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:Plc.PlcNodeManager.CreateAddressSpace(System.Collections.Generic.IDictionary{Opc.Ua.NodeId,System.Collections.Generic.IList{Opc.Ua.IReference}})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Plc.PlcNodeManager.CreateAddressSpace(System.Collections.Generic.IDictionary{Opc.Ua.NodeId,System.Collections.Generic.IList{Opc.Ua.IReference}})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Plc.PlcNodeManager.New(Opc.Ua.ISystemContext,Opc.Ua.NodeState)~Opc.Ua.NodeId")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:Reference.ReferenceServerConfiguration.Initialize")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:SimpleEvents.SimpleEventsNodeManager.#ctor(Opc.Ua.Server.IServerInternal,Opc.Ua.ApplicationConfiguration)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:SimpleEvents.SimpleEventsNodeManager.DoSimulation(System.Object)")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:SimpleEvents.SimpleEventsNodeManager.DoSimulation(System.Object)")] [assembly: SuppressMessage("Globalization", "CA1305:Specify IFormatProvider", Justification = "", Scope = "member", Target = "~M:SimpleEvents.SimpleEventsNodeManager.DoSimulation(System.Object)")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:SimpleEvents.SimpleEventsNodeManager.New(Opc.Ua.ISystemContext,Opc.Ua.NodeState)~Opc.Ua.NodeId")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:SimpleEvents.SimpleEventsServerConfiguration.Initialize")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.AnalogArrayValueObjectState.FindChild(Opc.Ua.ISystemContext,Opc.Ua.QualifiedName,System.Boolean,Opc.Ua.BaseInstanceState)~Opc.Ua.BaseInstanceState")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.AnalogArrayValueObjectState.GetChildren(Opc.Ua.ISystemContext,System.Collections.Generic.IList{Opc.Ua.BaseInstanceState})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.AnalogArrayValueObjectState.OnGenerateValues(Opc.Ua.ISystemContext,Opc.Ua.MethodState,Opc.Ua.NodeId,System.UInt32)~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.AnalogScalarValueObjectState.FindChild(Opc.Ua.ISystemContext,Opc.Ua.QualifiedName,System.Boolean,Opc.Ua.BaseInstanceState)~Opc.Ua.BaseInstanceState")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.AnalogScalarValueObjectState.GetChildren(Opc.Ua.ISystemContext,System.Collections.Generic.IList{Opc.Ua.BaseInstanceState})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.AnalogScalarValueObjectState.OnGenerateValues(Opc.Ua.ISystemContext,Opc.Ua.MethodState,Opc.Ua.NodeId,System.UInt32)~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.ArrayValueObjectState.FindChild(Opc.Ua.ISystemContext,Opc.Ua.QualifiedName,System.Boolean,Opc.Ua.BaseInstanceState)~Opc.Ua.BaseInstanceState")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.ArrayValueObjectState.GetChildren(Opc.Ua.ISystemContext,System.Collections.Generic.IList{Opc.Ua.BaseInstanceState})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.ArrayValueObjectState.OnGenerateValues(Opc.Ua.ISystemContext,Opc.Ua.MethodState,Opc.Ua.NodeId,System.UInt32)~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:TestData.HistoryArchive.OnUpdate(System.Object)")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.MethodTestState.FindChild(Opc.Ua.ISystemContext,Opc.Ua.QualifiedName,System.Boolean,Opc.Ua.BaseInstanceState)~Opc.Ua.BaseInstanceState")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.MethodTestState.GetChildren(Opc.Ua.ISystemContext,System.Collections.Generic.IList{Opc.Ua.BaseInstanceState})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.ScalarValueObjectState.FindChild(Opc.Ua.ISystemContext,Opc.Ua.QualifiedName,System.Boolean,Opc.Ua.BaseInstanceState)~Opc.Ua.BaseInstanceState")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.ScalarValueObjectState.GetChildren(Opc.Ua.ISystemContext,System.Collections.Generic.IList{Opc.Ua.BaseInstanceState})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.ScalarValueObjectState.OnGenerateValues(Opc.Ua.ISystemContext,Opc.Ua.MethodState,Opc.Ua.NodeId,System.UInt32)~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.TestDataNodeManager.#ctor(Opc.Ua.Server.IServerInternal,Opc.Ua.ApplicationConfiguration)")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.TestDataNodeManager.OnDataChange(Opc.Ua.BaseVariableState,System.Object,Opc.Ua.StatusCode,System.DateTime)")] [assembly: SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:TestData.TestDataObjectState.DoDeviceRead(Opc.Ua.ISystemContext,Opc.Ua.NodeState,Opc.Ua.NumericRange,Opc.Ua.QualifiedName,System.Object@,Opc.Ua.StatusCode@,System.DateTime@)~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.TestDataObjectState.FindChild(Opc.Ua.ISystemContext,Opc.Ua.QualifiedName,System.Boolean,Opc.Ua.BaseInstanceState)~Opc.Ua.BaseInstanceState")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:TestData.TestDataObjectState.GenerateValue(TestData.TestDataSystem,Opc.Ua.BaseVariableState)")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.TestDataObjectState.GenerateValue(TestData.TestDataSystem,Opc.Ua.BaseVariableState)")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.TestDataObjectState.GetChildren(Opc.Ua.ISystemContext,System.Collections.Generic.IList{Opc.Ua.BaseInstanceState})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.TestDataObjectState.InitializeVariable(Opc.Ua.ISystemContext,Opc.Ua.BaseVariableState,System.UInt32)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:TestData.TestDataObjectState.OnGenerateValues(Opc.Ua.ISystemContext,Opc.Ua.MethodState,Opc.Ua.NodeId,System.UInt32)~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Globalization", "CA1305:Specify IFormatProvider", Justification = "", Scope = "member", Target = "~M:TestData.TestDataObjectState.OnWriteAnalogValue(Opc.Ua.ISystemContext,Opc.Ua.NodeState,System.Object@)~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:TestData.TestDataObjectState.OnWriteAnalogValue(Opc.Ua.ISystemContext,Opc.Ua.NodeState,System.Object@)~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.TestDataObjectState.OnWriteAnalogValue(Opc.Ua.ISystemContext,Opc.Ua.NodeState,System.Object@)~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Usage", "CA2200:Rethrow to preserve stack details.", Justification = "", Scope = "member", Target = "~M:TestData.TestDataObjectState.OnWriteAnalogValue(Opc.Ua.ISystemContext,Opc.Ua.NodeState,System.Object@)~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Usage", "CA1816:Dispose methods should call SuppressFinalize", Justification = "", Scope = "member", Target = "~M:TestData.TestDataSystem.Dispose")] [assembly: SuppressMessage("Design", "CA1063:Implement IDisposable Correctly", Justification = "", Scope = "member", Target = "~M:TestData.TestDataSystem.Dispose")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.TestDataSystem.ReadValue(Opc.Ua.BaseVariableState)~System.Object")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.TestSystemConditionState.FindChild(Opc.Ua.ISystemContext,Opc.Ua.QualifiedName,System.Boolean,Opc.Ua.BaseInstanceState)~Opc.Ua.BaseInstanceState")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.TestSystemConditionState.GetChildren(Opc.Ua.ISystemContext,System.Collections.Generic.IList{Opc.Ua.BaseInstanceState})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.TestSystemConditionState.OnReadMonitoredNodeCount(Opc.Ua.ISystemContext,Opc.Ua.NodeState,System.Object@)~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.UserArrayValueObjectState.FindChild(Opc.Ua.ISystemContext,Opc.Ua.QualifiedName,System.Boolean,Opc.Ua.BaseInstanceState)~Opc.Ua.BaseInstanceState")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.UserArrayValueObjectState.GetChildren(Opc.Ua.ISystemContext,System.Collections.Generic.IList{Opc.Ua.BaseInstanceState})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.UserArrayValueObjectState.OnGenerateValues(Opc.Ua.ISystemContext,Opc.Ua.MethodState,Opc.Ua.NodeId,System.UInt32)~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.UserScalarValueObjectState.FindChild(Opc.Ua.ISystemContext,Opc.Ua.QualifiedName,System.Boolean,Opc.Ua.BaseInstanceState)~Opc.Ua.BaseInstanceState")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.UserScalarValueObjectState.GetChildren(Opc.Ua.ISystemContext,System.Collections.Generic.IList{Opc.Ua.BaseInstanceState})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:TestData.UserScalarValueObjectState.OnGenerateValues(Opc.Ua.ISystemContext,Opc.Ua.MethodState,Opc.Ua.NodeId,System.UInt32)~Opc.Ua.ServiceResult")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Vehicles.VehiclesNodeManager.#ctor(Opc.Ua.Server.IServerInternal,Opc.Ua.ApplicationConfiguration)")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:Vehicles.VehiclesNodeManager.LoadSchemaFromResource(System.String,System.Reflection.Assembly)~System.Byte[]")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Vehicles.VehiclesNodeManager.New(Opc.Ua.ISystemContext,Opc.Ua.NodeState)~Opc.Ua.NodeId")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:Vehicles.VehiclesServerConfiguration.Initialize")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Views.ViewsNodeManager.#ctor(Opc.Ua.Server.IServerInternal,Opc.Ua.ApplicationConfiguration)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Views.ViewsNodeManager.CreateAddressSpace(System.Collections.Generic.IDictionary{Opc.Ua.NodeId,System.Collections.Generic.IList{Opc.Ua.IReference}})")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Views.ViewsNodeManager.IsNodeInView(Opc.Ua.Server.ServerSystemContext,Opc.Ua.Server.ContinuationPoint,Opc.Ua.NodeState)~System.Boolean")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Views.ViewsNodeManager.IsReferenceInView(Opc.Ua.Server.ServerSystemContext,Opc.Ua.Server.ContinuationPoint,Opc.Ua.IReference)~System.Boolean")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:Views.ViewsNodeManager.New(Opc.Ua.ISystemContext,Opc.Ua.NodeState)~Opc.Ua.NodeId")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:Views.ViewsServerConfiguration.Initialize")] [assembly: SuppressMessage("Performance", "CA1819:Properties should not return arrays", Justification = "", Scope = "member", Target = "~P:Alarms.UnderlyingSystemAlarm.Limits")] [assembly: SuppressMessage("Performance", "CA1819:Properties should not return arrays", Justification = "", Scope = "member", Target = "~P:DataAccess.UnderlyingSystemTag.EuRange")] [assembly: SuppressMessage("Performance", "CA1819:Properties should not return arrays", Justification = "", Scope = "member", Target = "~P:DataAccess.UnderlyingSystemTag.Labels")] [assembly: SuppressMessage("Design", "CA1001:Types that own disposable fields should be disposable", Justification = "", Scope = "type", Target = "~T:HistoricalEvents.ReportGenerator")] [assembly: SuppressMessage("Design", "CA1034:Nested types should not be visible", Justification = "", Scope = "type", Target = "~T:HistoricalEvents.ReportGenerator.WellInfo")] [assembly: SuppressMessage("Design", "CA1001:Types that own disposable fields should be disposable", Justification = "", Scope = "type", Target = "~T:PerfTest.MemoryRegister")] [assembly: SuppressMessage("Design", "CA1063:Implement IDisposable Correctly", Justification = "", Scope = "type", Target = "~T:TestData.TestDataSystem")] [assembly: SuppressMessage("Style", "IDE0065:Misplaced using directive", Justification = "")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:Boiler.BoilerState.InitializationString")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:Boiler.BoilerStateMachineState.InitializationString")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:Boiler.GenericControllerState.InitializationString")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:DataAccess.UnderlyingSystem.s_BlockDatabase")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:DataAccess.UnderlyingSystem.s_BlockPathDatabase")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:MemoryBuffer.MemoryBufferState.InitializationString")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:MemoryBuffer.MemoryTagState.InitializationString")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogArrayValueObjectState.InitializationString")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogScalarValueObjectState.InitializationString")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.InitializationString")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.HistoryEntry.IsModified")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.HistoryEntry.Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.HistoryRecord.DataType")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.HistoryRecord.Historizing")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.HistoryRecord.RawData")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.MethodTestState.InitializationString")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.InitializationString")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.TestDataObjectState.InitializationString")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.TestDataSystem.Sample.StatusCode")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.TestDataSystem.Sample.Timestamp")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.TestDataSystem.Sample.Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.TestDataSystem.Sample.Variable")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.TestSystemConditionState.InitializationString")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserArrayValueObjectState.InitializationString")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserScalarValueObjectState.InitializationString")] [assembly: SuppressMessage("Security", "CA5394:Do not use insecure randomness", Justification = "", Scope = "member", Target = "~M:Boiler.BoilerState.RoundAndPerturb(System.Double,System.Byte)~System.Double")] [assembly: SuppressMessage("Security", "CA5394:Do not use insecure randomness", Justification = "", Scope = "member", Target = "~M:HistoricalEvents.ReportGenerator.GetRandom(System.Int32,System.Int32)~System.Int32")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Reference.ReferenceNodeManager.CreateAddressSpace(System.Collections.Generic.IDictionary{Opc.Ua.NodeId,System.Collections.Generic.IList{Opc.Ua.IReference}})")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Reference.ReferenceNodeManager.CreateDynamicVariables(Opc.Ua.NodeState,System.String,System.String,Opc.Ua.NodeId,System.Int32,System.UInt32)~Opc.Ua.BaseDataVariableState[]")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Reference.ReferenceNodeManager.CreateVariables(Opc.Ua.NodeState,System.String,System.String,Opc.Ua.NodeId,System.Int32,System.UInt16)~Opc.Ua.BaseDataVariableState[]")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:TestData.ArrayValue1MethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:TestData.ArrayValue2MethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:TestData.ArrayValue3MethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:TestData.GenerateValuesMethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:TestData.ScalarValue1MethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:TestData.ScalarValue2MethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:TestData.ScalarValue3MethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:TestData.UserArrayValue1MethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:TestData.UserArrayValue2MethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:TestData.UserScalarValue1MethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:TestData.UserScalarValue2MethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.ByteValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.DoubleValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.FloatValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.Int16Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.Int32Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.Int64Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.IntegerValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.NumberValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.SByteValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.UInt16Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.UInt32Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.UInt64Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogArrayValueObjectState.UIntegerValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.ByteValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.DoubleValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.FloatValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.Int16Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.Int32Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.Int64Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.IntegerValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.NumberValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.SByteValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.UInt16Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.UInt32Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.UInt64Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.AnalogScalarValueObjectState.UIntegerValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.BooleanValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.ByteStringValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.ByteValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.DateTimeValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.DoubleValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.EnumerationValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.ExpandedNodeIdValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.FloatValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.GuidValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.Int16Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.Int32Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.Int64Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.IntegerValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.LocalizedTextValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.NodeIdValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.NumberValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.QualifiedNameValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.SByteValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.StatusCodeValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.StringValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.StructureValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.UInt16Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.UInt32Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.UInt64Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.UIntegerValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.VariantValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ArrayValueObjectState.XmlElementValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.MethodTestState.ArrayMethod1")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.MethodTestState.ArrayMethod2")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.MethodTestState.ArrayMethod3")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.MethodTestState.ScalarMethod1")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.MethodTestState.ScalarMethod2")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.MethodTestState.ScalarMethod3")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.MethodTestState.UserArrayMethod1")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.MethodTestState.UserArrayMethod2")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.MethodTestState.UserScalarMethod1")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.MethodTestState.UserScalarMethod2")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.BooleanValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.ByteStringValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.ByteValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.DateTimeValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.DoubleValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.EnumerationValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.ExpandedNodeIdValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.FloatValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.GuidValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.Int16Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.Int32Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.Int64Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.IntegerValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.LocalizedTextValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.NodeIdValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.NumberValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.QualifiedNameValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.SByteValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.StatusCodeValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.StringValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.StructureValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.UInt16Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.UInt32Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.UInt64Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.UIntegerValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.VariantValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.ScalarValueObjectState.XmlElementValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.TestDataObjectState.CycleComplete")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.TestDataObjectState.GenerateValues")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.TestDataObjectState.SimulationActive")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.TestSystemConditionState.MonitoredNodeCount")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.BooleanValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.ByteStringValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.ByteValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.DateTimeValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.DoubleValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.ExpandedNodeIdValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.FloatValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.GuidValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.Int16Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.Int32Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.Int64Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.LocalizedTextValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.NodeIdValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.QualifiedNameValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.SByteValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.StatusCodeValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.StringValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.UInt16Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.UInt32Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.UInt64Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.VariantValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserArrayValueObjectState.XmlElementValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.BooleanValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.ByteStringValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.ByteValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.DateTimeValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.DoubleValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.ExpandedNodeIdValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.FloatValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.GuidValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.Int16Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.Int32Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.Int64Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.LocalizedTextValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.NodeIdValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.QualifiedNameValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.SByteValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.StatusCodeValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.StringValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.UInt16Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.UInt32Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.UInt64Value")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.VariantValue")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment.", Justification = "", Scope = "member", Target = "~P:TestData.UserScalarValueObjectState.XmlElementValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:Boiler.BoilerState.m_customController")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:Boiler.BoilerState.m_drum")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:Boiler.BoilerState.m_flowController")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:Boiler.BoilerState.m_inputPipe")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:Boiler.BoilerState.m_levelController")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:Boiler.BoilerState.m_outputPipe")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:Boiler.BoilerState.m_simulation")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:Boiler.BoilerStateMachineState.m_haltMethod")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:Boiler.BoilerStateMachineState.m_resetMethod")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:Boiler.BoilerStateMachineState.m_resumeMethod")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:Boiler.BoilerStateMachineState.m_startMethod")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:Boiler.BoilerStateMachineState.m_suspendMethod")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:Boiler.BoilerStateMachineState.m_updateRate")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:Boiler.GenericControllerState.m_controlOut")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:Boiler.GenericControllerState.m_measurement")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:Boiler.GenericControllerState.m_setPoint")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:MemoryBuffer.MemoryBufferState.m_sizeInBytes")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:MemoryBuffer.MemoryBufferState.m_startAddress")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogArrayValueObjectState.m_byteValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogArrayValueObjectState.m_doubleValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogArrayValueObjectState.m_floatValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogArrayValueObjectState.m_int16Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogArrayValueObjectState.m_int32Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogArrayValueObjectState.m_int64Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogArrayValueObjectState.m_integerValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogArrayValueObjectState.m_numberValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogArrayValueObjectState.m_sByteValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogArrayValueObjectState.m_uInt16Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogArrayValueObjectState.m_uInt32Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogArrayValueObjectState.m_uInt64Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogArrayValueObjectState.m_uIntegerValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogScalarValueObjectState.m_byteValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogScalarValueObjectState.m_doubleValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogScalarValueObjectState.m_floatValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogScalarValueObjectState.m_int16Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogScalarValueObjectState.m_int32Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogScalarValueObjectState.m_int64Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogScalarValueObjectState.m_integerValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogScalarValueObjectState.m_numberValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogScalarValueObjectState.m_sByteValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogScalarValueObjectState.m_uInt16Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogScalarValueObjectState.m_uInt32Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogScalarValueObjectState.m_uInt64Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.AnalogScalarValueObjectState.m_uIntegerValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_booleanValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_byteStringValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_byteValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_dateTimeValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_doubleValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_enumerationValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_expandedNodeIdValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_floatValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_guidValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_int16Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_int32Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_int64Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_integerValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_localizedTextValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_nodeIdValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_numberValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_qualifiedNameValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_sByteValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_statusCodeValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_stringValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_structureValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_uInt16Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_uInt32Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_uInt64Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_uIntegerValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_variantValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ArrayValueObjectState.m_xmlElementValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.MethodTestState.m_arrayMethod1Method")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.MethodTestState.m_arrayMethod2Method")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.MethodTestState.m_arrayMethod3Method")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.MethodTestState.m_scalarMethod1Method")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.MethodTestState.m_scalarMethod2Method")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.MethodTestState.m_scalarMethod3Method")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.MethodTestState.m_userArrayMethod1Method")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.MethodTestState.m_userArrayMethod2Method")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.MethodTestState.m_userScalarMethod1Method")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.MethodTestState.m_userScalarMethod2Method")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_booleanValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_byteStringValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_byteValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_dateTimeValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_doubleValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_enumerationValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_expandedNodeIdValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_floatValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_guidValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_int16Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_int32Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_int64Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_integerValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_localizedTextValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_nodeIdValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_numberValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_qualifiedNameValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_sByteValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_statusCodeValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_stringValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_structureValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_uInt16Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_uInt32Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_uInt64Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_uIntegerValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_variantValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.ScalarValueObjectState.m_xmlElementValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.TestDataObjectState.m_cycleComplete")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.TestDataObjectState.m_generateValuesMethod")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.TestDataObjectState.m_simulationActive")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.TestSystemConditionState.m_monitoredNodeCount")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserArrayValueObjectState.m_booleanValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserArrayValueObjectState.m_byteStringValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserArrayValueObjectState.m_byteValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserArrayValueObjectState.m_dateTimeValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserArrayValueObjectState.m_doubleValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserArrayValueObjectState.m_expandedNodeIdValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserArrayValueObjectState.m_floatValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserArrayValueObjectState.m_guidValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserArrayValueObjectState.m_int16Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserArrayValueObjectState.m_int32Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserArrayValueObjectState.m_int64Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserArrayValueObjectState.m_localizedTextValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserArrayValueObjectState.m_nodeIdValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserArrayValueObjectState.m_qualifiedNameValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserArrayValueObjectState.m_sByteValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserArrayValueObjectState.m_statusCodeValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserArrayValueObjectState.m_stringValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserArrayValueObjectState.m_uInt16Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserArrayValueObjectState.m_uInt32Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserArrayValueObjectState.m_uInt64Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserArrayValueObjectState.m_variantValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserArrayValueObjectState.m_xmlElementValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserScalarValueObjectState.m_booleanValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserScalarValueObjectState.m_byteStringValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserScalarValueObjectState.m_byteValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserScalarValueObjectState.m_dateTimeValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserScalarValueObjectState.m_doubleValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserScalarValueObjectState.m_expandedNodeIdValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserScalarValueObjectState.m_floatValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserScalarValueObjectState.m_guidValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserScalarValueObjectState.m_int16Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserScalarValueObjectState.m_int32Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserScalarValueObjectState.m_int64Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserScalarValueObjectState.m_localizedTextValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserScalarValueObjectState.m_nodeIdValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserScalarValueObjectState.m_qualifiedNameValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserScalarValueObjectState.m_sByteValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserScalarValueObjectState.m_statusCodeValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserScalarValueObjectState.m_stringValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserScalarValueObjectState.m_uInt16Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserScalarValueObjectState.m_uInt32Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserScalarValueObjectState.m_uInt64Value")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserScalarValueObjectState.m_variantValue")] [assembly: SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~F:TestData.UserScalarValueObjectState.m_xmlElementValue")] [assembly: SuppressMessage("Style", "IDE0047:Remove unnecessary parentheses", Justification = "", Scope = "member", Target = "~M:TestData.AnalogArrayValueObjectState.Initialize(Opc.Ua.ISystemContext)")] [assembly: SuppressMessage("Style", "IDE0047:Remove unnecessary parentheses", Justification = "", Scope = "member", Target = "~M:TestData.AnalogScalarValueObjectState.Initialize(Opc.Ua.ISystemContext)")] [assembly: SuppressMessage("Style", "IDE0047:Remove unnecessary parentheses", Justification = "", Scope = "member", Target = "~M:TestData.ArrayValueObjectState.Initialize(Opc.Ua.ISystemContext)")] [assembly: SuppressMessage("Style", "IDE0047:Remove unnecessary parentheses", Justification = "", Scope = "member", Target = "~M:TestData.MethodTestState.Initialize(Opc.Ua.ISystemContext)")] [assembly: SuppressMessage("Style", "IDE0047:Remove unnecessary parentheses", Justification = "", Scope = "member", Target = "~M:TestData.ScalarValueObjectState.Initialize(Opc.Ua.ISystemContext)")] [assembly: SuppressMessage("Style", "IDE0047:Remove unnecessary parentheses", Justification = "", Scope = "member", Target = "~M:TestData.TestDataObjectState.Initialize(Opc.Ua.ISystemContext)")] [assembly: SuppressMessage("Style", "IDE0047:Remove unnecessary parentheses", Justification = "", Scope = "member", Target = "~M:TestData.TestSystemConditionState.Initialize(Opc.Ua.ISystemContext)")] [assembly: SuppressMessage("Style", "IDE0047:Remove unnecessary parentheses", Justification = "", Scope = "member", Target = "~M:TestData.UserArrayValueObjectState.Initialize(Opc.Ua.ISystemContext)")] [assembly: SuppressMessage("Style", "IDE0047:Remove unnecessary parentheses", Justification = "", Scope = "member", Target = "~M:TestData.UserScalarValueObjectState.Initialize(Opc.Ua.ISystemContext)")] [assembly: SuppressMessage("Style", "IDE0047:Remove unnecessary parentheses", Justification = "", Scope = "type", Target = "~T:TestData.AnalogArrayValueObjectState")] [assembly: SuppressMessage("Style", "IDE0047:Remove unnecessary parentheses", Justification = "", Scope = "type", Target = "~T:TestData.AnalogScalarValueObjectState")] [assembly: SuppressMessage("Style", "IDE0047:Remove unnecessary parentheses", Justification = "", Scope = "type", Target = "~T:TestData.ArrayValueObjectState")] [assembly: SuppressMessage("Style", "IDE0047:Remove unnecessary parentheses", Justification = "", Scope = "type", Target = "~T:TestData.MethodTestState")] [assembly: SuppressMessage("Style", "IDE0047:Remove unnecessary parentheses", Justification = "", Scope = "type", Target = "~T:TestData.ScalarValueObjectState")] [assembly: SuppressMessage("Style", "IDE0047:Remove unnecessary parentheses", Justification = "", Scope = "type", Target = "~T:TestData.TestDataObjectState")] [assembly: SuppressMessage("Style", "IDE0047:Remove unnecessary parentheses", Justification = "", Scope = "type", Target = "~T:TestData.TestSystemConditionState")] [assembly: SuppressMessage("Style", "IDE0047:Remove unnecessary parentheses", Justification = "", Scope = "type", Target = "~T:TestData.UserArrayValueObjectState")] [assembly: SuppressMessage("Style", "IDE0047:Remove unnecessary parentheses", Justification = "", Scope = "type", Target = "~T:TestData.UserScalarValueObjectState")] [assembly: SuppressMessage("Roslynator", "RCS1173:Use coalesce expression instead of 'if'.", Justification = "", Scope = "member", Target = "~M:TestData.AnalogArrayValueObjectState.FindChild(Opc.Ua.ISystemContext,Opc.Ua.QualifiedName,System.Boolean,Opc.Ua.BaseInstanceState)~Opc.Ua.BaseInstanceState")] [assembly: SuppressMessage("Roslynator", "RCS1173:Use coalesce expression instead of 'if'.", Justification = "", Scope = "member", Target = "~M:TestData.AnalogScalarValueObjectState.FindChild(Opc.Ua.ISystemContext,Opc.Ua.QualifiedName,System.Boolean,Opc.Ua.BaseInstanceState)~Opc.Ua.BaseInstanceState")] [assembly: SuppressMessage("Roslynator", "RCS1173:Use coalesce expression instead of 'if'.", Justification = "", Scope = "member", Target = "~M:TestData.ArrayValueObjectState.FindChild(Opc.Ua.ISystemContext,Opc.Ua.QualifiedName,System.Boolean,Opc.Ua.BaseInstanceState)~Opc.Ua.BaseInstanceState")] [assembly: SuppressMessage("Roslynator", "RCS1173:Use coalesce expression instead of 'if'.", Justification = "", Scope = "member", Target = "~M:TestData.MethodTestState.FindChild(Opc.Ua.ISystemContext,Opc.Ua.QualifiedName,System.Boolean,Opc.Ua.BaseInstanceState)~Opc.Ua.BaseInstanceState")] [assembly: SuppressMessage("Roslynator", "RCS1173:Use coalesce expression instead of 'if'.", Justification = "", Scope = "member", Target = "~M:TestData.ScalarValueObjectState.FindChild(Opc.Ua.ISystemContext,Opc.Ua.QualifiedName,System.Boolean,Opc.Ua.BaseInstanceState)~Opc.Ua.BaseInstanceState")] [assembly: SuppressMessage("Roslynator", "RCS1173:Use coalesce expression instead of 'if'.", Justification = "", Scope = "member", Target = "~M:TestData.TestDataObjectState.FindChild(Opc.Ua.ISystemContext,Opc.Ua.QualifiedName,System.Boolean,Opc.Ua.BaseInstanceState)~Opc.Ua.BaseInstanceState")] [assembly: SuppressMessage("Roslynator", "RCS1173:Use coalesce expression instead of 'if'.", Justification = "", Scope = "member", Target = "~M:TestData.TestSystemConditionState.FindChild(Opc.Ua.ISystemContext,Opc.Ua.QualifiedName,System.Boolean,Opc.Ua.BaseInstanceState)~Opc.Ua.BaseInstanceState")] [assembly: SuppressMessage("Roslynator", "RCS1173:Use coalesce expression instead of 'if'.", Justification = "", Scope = "member", Target = "~M:TestData.UserArrayValueObjectState.FindChild(Opc.Ua.ISystemContext,Opc.Ua.QualifiedName,System.Boolean,Opc.Ua.BaseInstanceState)~Opc.Ua.BaseInstanceState")] [assembly: SuppressMessage("Roslynator", "RCS1173:Use coalesce expression instead of 'if'.", Justification = "", Scope = "member", Target = "~M:TestData.UserScalarValueObjectState.FindChild(Opc.Ua.ISystemContext,Opc.Ua.QualifiedName,System.Boolean,Opc.Ua.BaseInstanceState)~Opc.Ua.BaseInstanceState")] [assembly: SuppressMessage("Performance", "CA1819:Properties should not return arrays", Justification = "", Scope = "member", Target = "~P:DeterministicAlarms.Configuration.Folder.Sources")] [assembly: SuppressMessage("Performance", "CA1819:Properties should not return arrays", Justification = "", Scope = "member", Target = "~P:DeterministicAlarms.Configuration.Script.Steps")] [assembly: SuppressMessage("Performance", "CA1819:Properties should not return arrays", Justification = "", Scope = "member", Target = "~P:DeterministicAlarms.Configuration.Source.Alarms")] [assembly: SuppressMessage("Performance", "CA1819:Properties should not return arrays", Justification = "", Scope = "member", Target = "~P:DeterministicAlarms.Configuration.AlarmsConfiguration.Folders")] [assembly: SuppressMessage("Performance", "CA1819:Properties should not return arrays", Justification = "", Scope = "member", Target = "~P:DeterministicAlarms.Configuration.Event.StateChanges")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Plc.PlcNodeManager.CreateBaseVariable(Opc.Ua.NodeState,System.Object,System.String,Opc.Ua.NodeId,System.Int32,System.Byte,System.String,Plc.NamespaceType,System.Boolean,System.Object,System.Object,System.Object,System.Object)~Opc.Ua.BaseDataVariableState")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Plc.PlcNodeManager.CreateBaseVariable(Opc.Ua.NodeState,System.Object,System.String,Opc.Ua.NodeId,System.Int32,System.Byte,System.String,Plc.NamespaceType,System.Object)~Opc.Ua.BaseDataVariableState")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Plc.PlcSimulation.UpdateEventInstances")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Plc.PluginNodes.ComplexTypePlcPluginNode.AddNodes(Opc.Ua.FolderState)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Plc.PluginNodes.DataPluginNodes.AddMethods(Opc.Ua.FolderState)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Plc.PluginNodes.DataPluginNodes.AddToAddressSpace(Opc.Ua.FolderState,Opc.Ua.FolderState,Plc.PlcNodeManager)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Plc.PluginNodes.DeterministicGuidPluginNodes.AddToAddressSpace(Opc.Ua.FolderState,Opc.Ua.FolderState,Plc.PlcNodeManager)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Plc.PluginNodes.DipPluginNode.AddToAddressSpace(Opc.Ua.FolderState,Opc.Ua.FolderState,Plc.PlcNodeManager)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Plc.PluginNodes.FastPluginNodes.AddMethods(Opc.Ua.FolderState)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Plc.PluginNodes.FastPluginNodes.AddToAddressSpace(Opc.Ua.FolderState,Opc.Ua.FolderState,Plc.PlcNodeManager)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Plc.PluginNodes.FastRandomPluginNodes.AddMethods(Opc.Ua.FolderState)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Plc.PluginNodes.FastRandomPluginNodes.AddToAddressSpace(Opc.Ua.FolderState,Opc.Ua.FolderState,Plc.PlcNodeManager)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Plc.PluginNodes.LongIdPluginNode.AddToAddressSpace(Opc.Ua.FolderState,Opc.Ua.FolderState,Plc.PlcNodeManager)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Plc.PluginNodes.LongStringPluginNodes.AddToAddressSpace(Opc.Ua.FolderState,Opc.Ua.FolderState,Plc.PlcNodeManager)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Plc.PluginNodes.NegTrendPluginNode.AddMethods(Opc.Ua.FolderState)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Plc.PluginNodes.NegTrendPluginNode.AddToAddressSpace(Opc.Ua.FolderState,Opc.Ua.FolderState,Plc.PlcNodeManager)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Plc.PluginNodes.PosTrendPluginNode.AddMethods(Opc.Ua.FolderState)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Plc.PluginNodes.PosTrendPluginNode.AddToAddressSpace(Opc.Ua.FolderState,Opc.Ua.FolderState,Plc.PlcNodeManager)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Plc.PluginNodes.SlowPluginNodes.AddMethods(Opc.Ua.FolderState)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Plc.PluginNodes.SlowPluginNodes.AddToAddressSpace(Opc.Ua.FolderState,Opc.Ua.FolderState,Plc.PlcNodeManager)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Plc.PluginNodes.SlowRandomPluginNodes.AddMethods(Opc.Ua.FolderState)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Plc.PluginNodes.SlowRandomPluginNodes.AddToAddressSpace(Opc.Ua.FolderState,Opc.Ua.FolderState,Plc.PlcNodeManager)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Plc.PluginNodes.SpecialCharNamePluginNode.AddToAddressSpace(Opc.Ua.FolderState,Opc.Ua.FolderState,Plc.PlcNodeManager)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:Plc.PluginNodes.SpikePluginNode.AddToAddressSpace(Opc.Ua.FolderState,Opc.Ua.FolderState,Plc.PlcNodeManager)")] [assembly: SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "", Scope = "member", Target = "~M:MemoryBuffer.MemoryBufferBrowser.NextChild~Opc.Ua.NodeStateReference")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:Asset.CloseAndUpdateMethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:Asset.CreateAssetMethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:Asset.DeleteAssetMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:Asset.CloseAndUpdateMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1141:Add 'param' element to documentation comment", Justification = "", Scope = "type", Target = "~T:Asset.CloseAndUpdateMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:Asset.CreateAssetMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1141:Add 'param' element to documentation comment", Justification = "", Scope = "type", Target = "~T:Asset.CreateAssetMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:Asset.DeleteAssetMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1141:Add 'param' element to documentation comment", Justification = "", Scope = "type", Target = "~T:Asset.DeleteAssetMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:Asset.Namespaces")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "member", Target = "~F:Asset.Namespaces.WoT_Con")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "member", Target = "~F:UAModel.ISA95_JOBCONTROL_V2.ISA95EquipmentDataTypeFields.Properties")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "member", Target = "~F:UAModel.ISA95_JOBCONTROL_V2.ISA95JobOrderDataTypeFields.MaterialRequirements")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "member", Target = "~F:UAModel.ISA95_JOBCONTROL_V2.ISA95JobResponseDataTypeFields.MaterialActuals")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "member", Target = "~F:UAModel.ISA95_JOBCONTROL_V2.ISA95MaterialDataTypeFields.Properties")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "member", Target = "~F:UAModel.ISA95_JOBCONTROL_V2.ISA95ParameterDataTypeFields.Subparameters")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "member", Target = "~F:UAModel.ISA95_JOBCONTROL_V2.ISA95PersonnelDataTypeFields.Properties")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "member", Target = "~F:UAModel.ISA95_JOBCONTROL_V2.ISA95PhysicalAssetDataTypeFields.Properties")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "member", Target = "~F:UAModel.ISA95_JOBCONTROL_V2.ISA95PropertyDataTypeFields.Subproperties")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "member", Target = "~F:UAModel.ISA95_JOBCONTROL_V2.ISA95WorkMasterDataTypeFields.Parameters")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.AbortMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1141:Add 'param' element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.AbortMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.CancelMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1141:Add 'param' element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.CancelMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.ClearMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1141:Add 'param' element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.ClearMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.ISA95EquipmentDataTypeFields")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.ISA95JobOrderDataTypeFields")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.ISA95JobResponseDataTypeFields")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.ISA95MaterialDataTypeFields")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.ISA95ParameterDataTypeFields")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.ISA95PersonnelDataTypeFields")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.ISA95PhysicalAssetDataTypeFields")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.ISA95PropertyDataTypeFields")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.ISA95WorkMasterDataTypeFields")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.PauseMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1141:Add 'param' element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.PauseMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.ReceiveJobResponseMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1141:Add 'param' element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.ReceiveJobResponseMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.RequestJobResponseByJobOrderIDMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1141:Add 'param' element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.RequestJobResponseByJobOrderIDMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.RequestJobResponseByJobOrderStateMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1141:Add 'param' element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.RequestJobResponseByJobOrderStateMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.ResumeMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1141:Add 'param' element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.ResumeMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.RevokeStartMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1141:Add 'param' element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.RevokeStartMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.StartMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1141:Add 'param' element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.StartMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.StopMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1141:Add 'param' element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.StopMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.StoreAndStartMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1141:Add 'param' element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.StoreAndStartMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.StoreMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1141:Add 'param' element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.StoreMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1139:Add summary element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.UpdateMethodStateMethodCallHandler")] [assembly: SuppressMessage("Roslynator", "RCS1141:Add 'param' element to documentation comment", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.UpdateMethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "namespace", Target = "~N:UAModel.ISA95_JOBCONTROL_V2")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.AbortMethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.CancelMethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.ClearMethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.PauseMethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.ReceiveJobResponseMethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.RequestJobResponseByJobOrderIDMethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.RequestJobResponseByJobOrderStateMethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.ResumeMethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.RevokeStartMethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.StartMethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.StopMethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.StoreAndStartMethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.StoreMethodStateMethodCallHandler")] [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "", Scope = "type", Target = "~T:UAModel.ISA95_JOBCONTROL_V2.UpdateMethodStateMethodCallHandler")] [assembly: SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "", Scope = "member", Target = "~M:Isa95Jobs.Isa95JobControlServerConfiguration.Initialize")] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/ArchiveFolder.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace HistoricalAccess { using System.Collections.Generic; using System.IO; using System.Text; /// /// Stores the metadata for a node representing a folder on a file system. /// public class ArchiveFolder { /// /// Creates a new instance. /// /// /// public ArchiveFolder(string uniquePath, DirectoryInfo folder) { UniquePath = uniquePath; DirectoryInfo = folder; } /// /// Returns the child folders. /// public ArchiveFolder[] GetChildFolders() { var folders = new List(); if (!DirectoryInfo.Exists) { return [.. folders]; } foreach (var directory in DirectoryInfo.GetDirectories()) { var buffer = new StringBuilder(UniquePath); buffer.Append('/') .Append(directory.Name); folders.Add(new ArchiveFolder(buffer.ToString(), directory)); } return [.. folders]; } /// /// Returns the child folders. /// public ArchiveItem[] GetItems() { var items = new List(); if (!DirectoryInfo.Exists) { return [.. items]; } foreach (var file in DirectoryInfo.GetFiles("*.csv")) { var buffer = new StringBuilder(UniquePath); buffer.Append('/') .Append(file.Name); items.Add(new ArchiveItem(buffer.ToString(), file)); } return [.. items]; } /// /// Returns the parent folder. /// public ArchiveFolder GetParentFolder() { var parentPath = string.Empty; if (!DirectoryInfo.Exists) { return null; } var index = UniquePath.LastIndexOf('/'); if (index > 0) { parentPath = UniquePath[..index]; } return new ArchiveFolder(parentPath, DirectoryInfo.Parent); } /// /// The unique path to the folder in the archive. /// public string UniquePath { get; } /// /// A name for the folder. /// public string Name => DirectoryInfo.Name; /// /// The physical folder in the archive. /// public DirectoryInfo DirectoryInfo { get; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/ArchiveFolderBrowser.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace HistoricalAccess { using Opc.Ua; using System.Collections.Generic; /// /// Browses the references for an archive folder. /// public class ArchiveFolderBrowser : NodeBrowser { /// /// Creates a new browser object with a set of filters. /// /// The system context to use. /// The view which may restrict the set of references/nodes found. /// The type of references being followed. /// Whether subtypes of the reference type are followed. /// Which way the references are being followed. /// The browse name of a specific target (used when translating browse paths). /// Any additional references that should be included. /// If true the browser should not making blocking calls to external systems. /// The segment being accessed. public ArchiveFolderBrowser( ISystemContext context, ViewDescription view, NodeId referenceType, bool includeSubtypes, BrowseDirection browseDirection, QualifiedName browseName, IEnumerable additionalReferences, bool internalOnly, ArchiveFolderState source) : base( context, view, referenceType, includeSubtypes, browseDirection, browseName, additionalReferences, internalOnly) { _source = source; _stage = Stage.Begin; } /// /// Returns the next reference. /// /// The next reference that meets the browse criteria. public override IReference Next() { lock (DataLock) { // enumerate pre-defined references. // always call first to ensure any pushed-back references are returned first. var reference = base.Next(); if (reference != null) { return reference; } if (_stage == Stage.Begin) { _folders = _source.ArchiveFolder.GetChildFolders(); _stage = Stage.Folders; _position = 0; } // don't start browsing huge number of references when only internal references are requested. if (InternalOnly) { return null; } // enumerate folders. if (_stage == Stage.Folders) { if (IsRequired(ReferenceTypeIds.Organizes, false)) { reference = NextChild(); if (reference != null) { return reference; } } _items = _source.ArchiveFolder.GetItems(); _stage = Stage.Items; _position = 0; } // enumerate items. if (_stage == Stage.Items && IsRequired(ReferenceTypeIds.Organizes, false)) { reference = NextChild(); if (reference != null) { return reference; } _stage = Stage.Parents; _position = 0; } // enumerate parents. if (_stage == Stage.Parents && IsRequired(ReferenceTypeIds.Organizes, true)) { reference = NextChild(); if (reference != null) { return reference; } _stage = Stage.Done; _position = 0; } // all done. return null; } } /// /// Returns the next child. /// private NodeStateReference NextChild() { NodeId targetId = null; // check if a specific browse name is requested. if (!QualifiedName.IsNull(BrowseName)) { // check if match found previously. if (_position == int.MaxValue) { return null; } // browse name must be qualified by the correct namespace. if (_source.BrowseName.NamespaceIndex != BrowseName.NamespaceIndex) { return null; } // look for matching folder. if (_stage == Stage.Folders && _folders != null) { for (var ii = 0; ii < _folders.Length; ii++) { if (BrowseName.Name == _folders[ii].Name) { targetId = ArchiveFolderState.ConstructId(_folders[ii].UniquePath, _source.NodeId.NamespaceIndex); break; } } } // look for matching item. else if (_stage == Stage.Items && _items != null) { for (var ii = 0; ii < _items.Length; ii++) { if (BrowseName.Name == _items[ii].Name) { targetId = ArchiveItemState.ConstructId(_items[ii].UniquePath, _source.NodeId.NamespaceIndex); break; } } } // look for matching parent. else if (_stage == Stage.Parents) { var parent = _source.ArchiveFolder.GetParentFolder(); if (BrowseName.Name == parent.Name) { targetId = ArchiveFolderState.ConstructId(parent.UniquePath, _source.NodeId.NamespaceIndex); } } _position = int.MaxValue; } // return the child at the next position. else { // look for next folder. if (_stage == Stage.Folders && _folders != null) { if (_position >= _folders.Length) { return null; } targetId = ArchiveFolderState.ConstructId(_folders[_position++].UniquePath, _source.NodeId.NamespaceIndex); } // look for next item. else if (_stage == Stage.Items && _items != null) { if (_position >= _items.Length) { return null; } targetId = ArchiveItemState.ConstructId(_items[_position++].UniquePath, _source.NodeId.NamespaceIndex); } // look for matching parent. else if (_stage == Stage.Parents) { var parent = _source.ArchiveFolder.GetParentFolder(); if (parent != null) { targetId = ArchiveFolderState.ConstructId(parent.UniquePath, _source.NodeId.NamespaceIndex); } } } // create reference. if (targetId != null) { return new NodeStateReference(ReferenceTypeIds.Organizes, false, targetId); } return null; } /// /// The stages available in a browse operation. /// private enum Stage { Begin, Folders, Items, Parents, Done } private Stage _stage; private int _position; private readonly ArchiveFolderState _source; private ArchiveFolder[] _folders; private ArchiveItem[] _items; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/ArchiveFolderState.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace HistoricalAccess { using Opc.Ua; using Opc.Ua.Server; using System.Collections.Generic; /// /// Stores the metadata for a node representing a folder on a file system. /// public class ArchiveFolderState : FolderState { /// /// Creates a new instance of a folder. /// /// /// public ArchiveFolderState(ArchiveFolder folder, ushort namespaceIndex) : base(null) { ArchiveFolder = folder; TypeDefinitionId = ObjectTypeIds.FolderType; SymbolicName = folder.Name; NodeId = ConstructId(folder.UniquePath, namespaceIndex); BrowseName = new QualifiedName(folder.Name, namespaceIndex); DisplayName = new LocalizedText(BrowseName.Name); Description = null; WriteMask = 0; UserWriteMask = 0; EventNotifier = EventNotifiers.None; } /// /// Constructs a node identifier for a folder object. /// /// /// public static NodeId ConstructId(string filePath, ushort namespaceIndex) { var parsedNodeId = new ParsedNodeId { RootId = filePath, NamespaceIndex = namespaceIndex, RootType = NodeTypes.Folder }; return parsedNodeId.Construct(); } /// /// The physical folder referenced by the node. /// public ArchiveFolder ArchiveFolder { get; } /// /// Creates a browser that explores the structure of the block. /// /// /// /// /// /// /// /// /// public override INodeBrowser CreateBrowser( ISystemContext context, ViewDescription view, NodeId referenceType, bool includeSubtypes, BrowseDirection browseDirection, QualifiedName browseName, IEnumerable additionalReferences, bool internalOnly) { NodeBrowser browser = new ArchiveFolderBrowser( context, view, referenceType, includeSubtypes, browseDirection, browseName, additionalReferences, internalOnly, this); PopulateBrowser(context, browser); return browser; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/ArchiveItem.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace HistoricalAccess { using Opc.Ua; using System; using System.Data; using System.IO; using System.Reflection; using System.Text; /// /// Stores the metadata for a node representing a folder on a file system. /// public class ArchiveItem { /// /// Creates a new instance. /// /// /// public ArchiveItem(string uniquePath, FileInfo file) { UniquePath = uniquePath; FileInfo = file; Name = string.Empty; if (FileInfo != null) { Name = FileInfo.Name; var index = Name.LastIndexOf('.'); if (index > 0) { Name = Name[..index]; } } } /// /// Creates a new instance. /// /// /// /// public ArchiveItem(string uniquePath, Assembly assembly, string resourcePath) { UniquePath = uniquePath; ResourceInfo = new ResourceInfoType { Assembly = assembly, ResourcePath = resourcePath }; Name = string.Empty; Name = ResourceInfo.ResourcePath; var index = Name.LastIndexOf('.'); if (index > 0) { Name = Name[..index]; } index = Name.LastIndexOf('.'); if (index > 0) { Name = Name[(index + 1)..]; } } /// /// Returns a stream that can be used to read the archive. /// public StreamReader OpenArchive() { if (FileInfo != null) { return new StreamReader(FileInfo.FullName, Encoding.UTF8); } if (ResourceInfo.Assembly != null) { return new StreamReader(ResourceInfo.Assembly.GetManifestResourceStream(ResourceInfo.ResourcePath), Encoding.UTF8); } return null; } /// /// A name for the item. /// public string Name { get; } /// /// The unique path to the item in the archive. /// public string UniquePath { get; } /// /// The data type for the item. /// public BuiltInType DataType { get; set; } /// /// The value rank for the item. /// public int ValueRank { get; set; } /// /// The type of simulated data. /// public int SimulationType { get; set; } /// /// The amplitude of the simulated data. /// public double Amplitude { get; set; } /// /// The period of the simulated data. /// public double Period { get; set; } /// /// Whether the simulation is running. /// public bool Archiving { get; set; } /// /// Whether the data requires stepped interpolation. /// public bool Stepped { get; set; } /// /// The sampling interval for the simulation. /// public double SamplingInterval { get; set; } /// /// The history for the item. /// public DataSet DataSet { get; set; } /// /// The last the dataset was loaded from its source. /// public DateTime LastLoadTime { get; set; } /// /// Whether the source is perisistent and needs to be reloaded. /// public bool Persistent { get; set; } /// /// The aggregate configuration for the item. /// public AggregateConfiguration AggregateConfiguration { get; set; } /// /// The physical file containing the item history. /// private FileInfo FileInfo { get; } /// /// An embeddded resource in containing the item history. /// private ResourceInfoType ResourceInfo { get; set; } /// /// Stores information about an embedded resource. /// private struct ResourceInfoType { public Assembly Assembly { get; set; } public string ResourcePath { get; set; } } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/ArchiveItemState.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace HistoricalAccess { using Opc.Ua; using Opc.Ua.Server; using Opc.Ua.Test; using System; using System.Collections.Generic; using System.Data; /// /// Stores the metadata for a node representing an item in the archive. /// public class ArchiveItemState : DataItemState { /// /// Creates a new instance of a item. /// /// /// /// /// public ArchiveItemState(ISystemContext context, ArchiveItem item, ushort namespaceIndex, TimeService timeService) : base(null) { ArchiveItem = item; _timeService = timeService; TypeDefinitionId = VariableTypeIds.DataItemType; SymbolicName = ArchiveItem.Name; NodeId = ConstructId(ArchiveItem.UniquePath, namespaceIndex); BrowseName = new QualifiedName(ArchiveItem.Name, namespaceIndex); DisplayName = new LocalizedText(BrowseName.Name); Description = null; WriteMask = 0; UserWriteMask = 0; DataType = DataTypeIds.BaseDataType; ValueRank = ValueRanks.Scalar; AccessLevel = AccessLevels.HistoryReadOrWrite | AccessLevels.CurrentRead; UserAccessLevel = AccessLevels.HistoryReadOrWrite | AccessLevels.CurrentRead; MinimumSamplingInterval = MinimumSamplingIntervals.Indeterminate; Historizing = true; _annotations = new PropertyState(this) { ReferenceTypeId = ReferenceTypeIds.HasProperty, TypeDefinitionId = VariableTypeIds.PropertyType, SymbolicName = BrowseNames.Annotations, BrowseName = BrowseNames.Annotations }; _annotations.DisplayName = new LocalizedText(_annotations.BrowseName.Name); _annotations.Description = null; _annotations.WriteMask = 0; _annotations.UserWriteMask = 0; _annotations.DataType = DataTypeIds.Annotation; _annotations.ValueRank = ValueRanks.Scalar; _annotations.AccessLevel = AccessLevels.HistoryReadOrWrite; _annotations.UserAccessLevel = AccessLevels.HistoryReadOrWrite; _annotations.MinimumSamplingInterval = MinimumSamplingIntervals.Indeterminate; _annotations.Historizing = false; AddChild(_annotations); _annotations.NodeId = NodeTypes.ConstructIdForComponent(_annotations, namespaceIndex); _configuration = new HistoricalDataConfigurationState(this); _configuration.MaxTimeInterval = new PropertyState(_configuration); _configuration.MinTimeInterval = new PropertyState(_configuration); _configuration.StartOfArchive = new PropertyState(_configuration); _configuration.StartOfOnlineArchive = new PropertyState(_configuration); _configuration.Create( context, null, BrowseNames.HAConfiguration, null, true); _configuration.SymbolicName = BrowseNames.HAConfiguration; _configuration.ReferenceTypeId = ReferenceTypeIds.HasHistoricalConfiguration; AddChild(_configuration); } /// /// Loads the configuration. /// /// public void LoadConfiguration(SystemContext context) { var reader = new DataFileReader(_timeService); if (reader.LoadConfiguration(context, ArchiveItem)) { DataType = (uint)ArchiveItem.DataType; ValueRank = ArchiveItem.ValueRank; Historizing = ArchiveItem.Archiving; _configuration.MinTimeInterval.Value = ArchiveItem.SamplingInterval; _configuration.MaxTimeInterval.Value = ArchiveItem.SamplingInterval; _configuration.Stepped.Value = ArchiveItem.Stepped; var configuration = ArchiveItem.AggregateConfiguration; _configuration.AggregateConfiguration.PercentDataGood.Value = configuration.PercentDataGood; _configuration.AggregateConfiguration.PercentDataBad.Value = configuration.PercentDataBad; _configuration.AggregateConfiguration.UseSlopedExtrapolation.Value = configuration.UseSlopedExtrapolation; _configuration.AggregateConfiguration.TreatUncertainAsBad.Value = configuration.TreatUncertainAsBad; } } /// /// Loads the data. /// /// public void ReloadFromSource(SystemContext context) { LoadConfiguration(context); if (ArchiveItem.LastLoadTime == DateTime.MinValue || (ArchiveItem.Persistent && ArchiveItem.LastLoadTime.AddDays(1) < _timeService.UtcNow)) { var reader = new DataFileReader(_timeService); reader.LoadHistoryData(context, ArchiveItem); // set the start of the archive. if (ArchiveItem.DataSet.Tables[0].DefaultView.Count > 0) { _configuration.StartOfArchive.Value = (DateTime)ArchiveItem.DataSet.Tables[0].DefaultView[0].Row[0]; _configuration.StartOfOnlineArchive.Value = _configuration.StartOfArchive.Value; } if (ArchiveItem.Archiving) { // save the pattern used to produce new data. _pattern = []; foreach (DataRowView row in ArchiveItem.DataSet.Tables[0].DefaultView) { var value = (DataValue)row.Row[2]; _pattern.Add(value); _nextSampleTime = value.SourceTimestamp.AddMilliseconds(ArchiveItem.SamplingInterval); } // fill in data until the present time. _patternIndex = 0; NewSamples(context); } } } /// /// Creates a new sample. /// /// public IList NewSamples(SystemContext context) { System.Diagnostics.Contracts.Contract.Assume(context is not null); var newSamples = new List(); while (_pattern != null && _nextSampleTime < _timeService.UtcNow) { var value = new DataValue { WrappedValue = _pattern[_patternIndex].WrappedValue, ServerTimestamp = _nextSampleTime, SourceTimestamp = _nextSampleTime, StatusCode = _pattern[_patternIndex].StatusCode }; _nextSampleTime = value.SourceTimestamp.AddMilliseconds(ArchiveItem.SamplingInterval); newSamples.Add(value); var row = ArchiveItem.DataSet.Tables[0].NewRow(); row[0] = value.SourceTimestamp; row[1] = value.ServerTimestamp; row[2] = value; row[3] = value.WrappedValue.TypeInfo.BuiltInType; row[4] = value.WrappedValue.TypeInfo.ValueRank; ArchiveItem.DataSet.Tables[0].Rows.Add(row); _patternIndex = (_patternIndex + 1) % _pattern.Count; } ArchiveItem.DataSet.AcceptChanges(); return newSamples; } /// /// Updates the history. /// /// /// /// public uint UpdateHistory(SystemContext context, DataValue value, PerformUpdateType performUpdateType) { var replaced = false; if (performUpdateType == PerformUpdateType.Remove) { return StatusCodes.BadNotSupported; } if (StatusCode.IsNotBad(value.StatusCode)) { var typeInfo = value.WrappedValue.TypeInfo ?? TypeInfo.Construct(value.Value); if (typeInfo == null || typeInfo.BuiltInType != ArchiveItem.DataType || typeInfo.ValueRank != ValueRanks.Scalar) { return StatusCodes.BadTypeMismatch; } } var filter = string.Format(System.Globalization.CultureInfo.InvariantCulture, "SourceTimestamp = #{0}#", value.SourceTimestamp); var view = new DataView( ArchiveItem.DataSet.Tables[0], filter, null, DataViewRowState.CurrentRows); DataRow row = null; const int ii = 0; for (; ii < view.Count;) { if (performUpdateType == PerformUpdateType.Insert) { return StatusCodes.BadEntryExists; } // add record indicating it was replaced. var modifiedRow = ArchiveItem.DataSet.Tables[1].NewRow(); modifiedRow[0] = view[ii].Row[0]; modifiedRow[1] = view[ii].Row[1]; modifiedRow[2] = view[ii].Row[2]; modifiedRow[3] = view[ii].Row[3]; modifiedRow[4] = view[ii].Row[4]; modifiedRow[5] = HistoryUpdateType.Replace; modifiedRow[6] = GetModificationInfo(context, HistoryUpdateType.Replace); ArchiveItem.DataSet.Tables[1].Rows.Add(modifiedRow); replaced = true; row = view[ii].Row; break; } // add record indicating it was inserted. if (!replaced) { if (performUpdateType == PerformUpdateType.Replace) { return StatusCodes.BadNoEntryExists; } var modifiedRow = ArchiveItem.DataSet.Tables[1].NewRow(); modifiedRow[0] = value.SourceTimestamp; modifiedRow[1] = value.ServerTimestamp; modifiedRow[2] = value; if (value.WrappedValue.TypeInfo != null) { modifiedRow[3] = value.WrappedValue.TypeInfo.BuiltInType; modifiedRow[4] = value.WrappedValue.TypeInfo.ValueRank; } else { modifiedRow[3] = BuiltInType.Variant; modifiedRow[4] = ValueRanks.Scalar; } modifiedRow[5] = HistoryUpdateType.Insert; modifiedRow[6] = GetModificationInfo(context, HistoryUpdateType.Insert); ArchiveItem.DataSet.Tables[1].Rows.Add(modifiedRow); row = ArchiveItem.DataSet.Tables[0].NewRow(); } // add/update new record. row[0] = value.SourceTimestamp; row[1] = value.ServerTimestamp; row[2] = value; if (value.WrappedValue.TypeInfo != null) { row[3] = value.WrappedValue.TypeInfo.BuiltInType; row[4] = value.WrappedValue.TypeInfo.ValueRank; } else { row[3] = BuiltInType.Variant; row[4] = ValueRanks.Scalar; } if (!replaced) { ArchiveItem.DataSet.Tables[0].Rows.Add(row); } // accept all changes. ArchiveItem.DataSet.AcceptChanges(); return StatusCodes.Good; } /// /// Updates the history. /// /// /// /// /// public uint UpdateAnnotations(SystemContext context, Annotation annotation, DataValue value, PerformUpdateType performUpdateType) { System.Diagnostics.Contracts.Contract.Assume(context is not null); var replaced = false; var filter = string.Format(System.Globalization.CultureInfo.InvariantCulture, "SourceTimestamp = #{0}#", value.SourceTimestamp); var view = new DataView( ArchiveItem.DataSet.Tables[2], filter, null, DataViewRowState.CurrentRows); DataRow row = null; for (var ii = 0; ii < view.Count; ii++) { var current = (Annotation)view[ii].Row[5]; replaced = current.UserName == annotation.UserName; if (performUpdateType == PerformUpdateType.Insert && replaced) { return StatusCodes.BadEntryExists; } if (replaced) { row = view[ii].Row; break; } } // add record indicating it was inserted. if (!replaced) { if (performUpdateType == PerformUpdateType.Replace || performUpdateType == PerformUpdateType.Remove) { return StatusCodes.BadNoEntryExists; } row = ArchiveItem.DataSet.Tables[2].NewRow(); } // add/update new record. if (performUpdateType != PerformUpdateType.Remove) { row[0] = value.SourceTimestamp; row[1] = value.ServerTimestamp; row[2] = new DataValue(new ExtensionObject(annotation), StatusCodes.Good, value.SourceTimestamp, value.ServerTimestamp); row[3] = BuiltInType.ExtensionObject; row[4] = ValueRanks.Scalar; row[5] = annotation; if (!replaced) { ArchiveItem.DataSet.Tables[2].Rows.Add(row); } } // delete record. else { row.Delete(); } // accept all changes. ArchiveItem.DataSet.AcceptChanges(); return StatusCodes.Good; } /// /// Deletes a value from the history. /// /// /// public uint DeleteHistory(SystemContext context, DateTime sourceTimestamp) { var deleted = false; var filter = string.Format(System.Globalization.CultureInfo.InvariantCulture, "SourceTimestamp = #{0}#", sourceTimestamp); var view = new DataView( ArchiveItem.DataSet.Tables[0], filter, null, DataViewRowState.CurrentRows); for (var ii = 0; ii < view.Count; ii++) { var modifiedRow = ArchiveItem.DataSet.Tables[1].NewRow(); modifiedRow[0] = view[ii].Row[0]; modifiedRow[1] = view[ii].Row[1]; modifiedRow[2] = view[ii].Row[2]; modifiedRow[3] = view[ii].Row[3]; modifiedRow[4] = view[ii].Row[4]; modifiedRow[5] = HistoryUpdateType.Delete; modifiedRow[6] = GetModificationInfo(context, HistoryUpdateType.Delete); view[ii].Row.Delete(); ArchiveItem.DataSet.Tables[1].Rows.Add(modifiedRow); deleted = true; } if (!deleted) { return StatusCodes.BadNoEntryExists; } ArchiveItem.DataSet.AcceptChanges(); return StatusCodes.Good; } /// /// Deletes a value from the history. /// /// /// /// /// public uint DeleteHistory(SystemContext context, DateTime startTime, DateTime endTime, bool isModified) { // ensure time goes up. if (endTime < startTime) { (endTime, startTime) = (startTime, endTime); } var filter = string.Format( System.Globalization.CultureInfo.InvariantCulture, "SourceTimestamp >= #{0}# AND SourceTimestamp < #{1}#", startTime, endTime); // select the table. var table = ArchiveItem.DataSet.Tables[0]; if (isModified) { table = ArchiveItem.DataSet.Tables[1]; } // delete the values. var view = new DataView( table, filter, null, DataViewRowState.CurrentRows); var rowsToDelete = new List(); for (var ii = 0; ii < view.Count; ii++) { if (!isModified) { var modifiedRow = ArchiveItem.DataSet.Tables[1].NewRow(); modifiedRow[0] = view[ii].Row[0]; modifiedRow[1] = view[ii].Row[1]; modifiedRow[2] = view[ii].Row[2]; modifiedRow[3] = view[ii].Row[3]; modifiedRow[4] = view[ii].Row[4]; modifiedRow[5] = HistoryUpdateType.Delete; modifiedRow[6] = GetModificationInfo(context, HistoryUpdateType.Delete); ArchiveItem.DataSet.Tables[1].Rows.Add(modifiedRow); } rowsToDelete.Add(view[ii].Row); } // delete rows. foreach (var row in rowsToDelete) { row.Delete(); } // commit all changes. ArchiveItem.DataSet.AcceptChanges(); return StatusCodes.Good; } /// /// Creates a modification info record. /// /// /// private ModificationInfo GetModificationInfo(SystemContext context, HistoryUpdateType updateType) { var info = new ModificationInfo { UpdateType = updateType, ModificationTime = _timeService.UtcNow }; if (context.OperationContext?.UserIdentity != null) { info.UserName = context.OperationContext.UserIdentity.DisplayName; } return info; } /// /// Reads the history for the specified time range. /// /// /// /// public DataView ReadHistory(DateTime startTime, DateTime endTime, bool isModified) { return ReadHistory(startTime, endTime, isModified, null); } /// /// Reads the history for the specified time range. /// /// /// /// /// public DataView ReadHistory(DateTime startTime, DateTime endTime, bool isModified, QualifiedName browseName) { if (startTime != DateTime.MinValue && endTime != DateTime.MaxValue) { // } if (isModified) { return ArchiveItem.DataSet.Tables[1].DefaultView; } if (browseName == BrowseNames.Annotations) { return ArchiveItem.DataSet.Tables[2].DefaultView; } return ArchiveItem.DataSet.Tables[0].DefaultView; } /// /// Finds the value at or before the timestamp. /// /// /// /// /// public int FindValueAtOrBefore(DataView view, DateTime timestamp, bool ignoreBad, out bool dataIgnored) { dataIgnored = false; if (view.Count <= 0) { return -1; } var min = 0; var max = view.Count; var position = (max - min) / 2; while (position >= 0 && position < view.Count) { var current = (DateTime)view[position].Row[0]; // check for exact match. if (current == timestamp) { // skip the first timestamp. while (position > 0 && (DateTime)view[position - 1].Row[0] == timestamp) { position--; } return position; } // move up. if (current < timestamp) { min = position + 1; } // move down. if (current > timestamp) { max = position - 1; } // not found. if (max < min) { // find the value before. while (position >= 0) { timestamp = (DateTime)view[position].Row[0]; // skip the first timestamp in group. while (position > 0 && (DateTime)view[position - 1].Row[0] == timestamp) { position--; } // ignore bad data. if (ignoreBad) { var value = (DataValue)view[position].Row[2]; if (StatusCode.IsBad(value.StatusCode)) { position--; dataIgnored = true; continue; } } break; } // return the position. return position; } position = min + ((max - min) / 2); } return -1; } /// /// Returns the next value after the current position. /// /// /// /// /// public int FindValueAfter(DataView view, int position, bool ignoreBad, out bool dataIgnored) { dataIgnored = false; if (position < 0 || position >= view.Count) { return -1; } var timestamp = (DateTime)view[position].Row[0]; // skip the current timestamp. while (position < view.Count && (DateTime)view[position].Row[0] == timestamp) { position++; } if (position >= view.Count) { return -1; } // find the value after. while (position < view.Count) { _ = (DateTime)view[position].Row[0]; // ignore bad data. if (ignoreBad) { var value = (DataValue)view[position].Row[2]; if (StatusCode.IsBad(value.StatusCode)) { position++; dataIgnored = true; continue; } } break; } if (position >= view.Count) { return -1; } // return the position. return position; } /// /// Constructs a node identifier for a item object. /// /// /// public static NodeId ConstructId(string filePath, ushort namespaceIndex) { var parsedNodeId = new ParsedNodeId { RootId = filePath, NamespaceIndex = namespaceIndex, RootType = NodeTypes.Item }; return parsedNodeId.Construct(); } /// /// The item in the archive. /// public ArchiveItem ArchiveItem { get; } /// /// The item in the archive. /// public int SubscribeCount { get; set; } protected override void Dispose(bool disposing) { base.Dispose(disposing); _annotations?.Dispose(); _configuration?.Dispose(); } private readonly HistoricalDataConfigurationState _configuration; private readonly PropertyState _annotations; private readonly TimeService _timeService; private List _pattern; private int _patternIndex; private DateTime _nextSampleTime; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Dynamic/Boolean.txt ================================================ Boolean,1,1,0,0,0,1,0,0,0,1,1 10000,10000,0,0,,,Boolean,1 20000,20000,0,0,,,Boolean,1 30000,30000,0,0,,,Boolean,0 40000,40000,0x80000000,0,,,Boolean,0 50000,50000,0,0,,,Boolean,1 60000,60000,0,0,,,Boolean,1 70000,70000,0x40000000,0,,,Boolean,0 80000,80000,0,0,,,Boolean,1 90000,90000,0,0,,,Boolean,0 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Dynamic/Byte.txt ================================================ Byte,1,250,0,0,0,1,0,0,0,100,100 10000,10000,0,0,,,Byte,11 20000,20000,0,0,,,Byte,22 30000,30000,0,0,,,Byte,33 40000,40000,0x80000000,0,,,Byte,44 50000,50000,0,0,,,Byte,55 60000,60000,0,0,,,Byte,66 70000,70000,0x40000000,0,,,Byte,77 80000,80000,0,0,,,Byte,88 90000,90000,0,0,,,Byte,99 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Dynamic/DateTime.txt ================================================ DateTime,-1,10000,0,0,0,0,0,0,1,100,100 0,0,0x809B0000,0,,,Null 2000,2000,0,0,,,DateTime,2013-10-18T16:24:13.000 25000,25000,0,0,,,DateTime,2013-10-18T17:25:13.000 28000,28000,0,0,,,DateTime,2013-10-18T18:26:13.575 39000,39000,0,0,,,DateTime,2013-10-18T19:24:13.575 42000,42000,0x80000000,0,,,Null 48000,48000,0,0,,,DateTime,2013-10-18T21:24:13.575 52000,52000,0,0,,,DateTime,2013-10-18T12:30:13.575 72000,72000,0,0,,,DateTime,2013-10-18T13:36:13.575 77000,77000,0x40000000,0,,,DateTime,2013-10-18T14:24:13.575 83000,83000,0,0,,,DateTime,2013-10-18T16:28:33.575 86000,86000,0,0,,,DateTime,2013-10-18T18:24:13.575 90000,90000,0,0,,,DateTime,2013-10-18T19:24:13.575 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Dynamic/Double.txt ================================================ Double,-1,1000,0,0,0,1,0,0,0,100,100 10000,10000,0,0,,,Double,10.0 20000,20000,0,0,,,Double,20.0 30000,30000,0,0,,,Double,30.0 40000,40000,0x80000000,0,,,Double,40.0 50000,50000,0,0,,,Double,50.0 60000,60000,0,0,,,Double,60.0 70000,70000,0x40000000,0,,,Double,70.0 80000,80000,0,0,,,Double,80.0 90000,90000,0,0,,,Double,90.0 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Dynamic/Float.txt ================================================ Float,-1,1000,0,0,0,1,0,0,0,100,100 10000,10000,0,0,,,Float,10.0 20000,20000,0,0,,,Float,20.0 30000,30000,0,0,,,Float,30.0 40000,40000,0x80000000,0,,,Float,40.0 50000,50000,0,0,,,Float,50.0 60000,60000,0,0,,,Float,60.0 70000,70000,0x40000000,0,,,Float,70.0 80000,80000,0,0,,,Float,80.0 90000,90000,0,0,,,Float,90.0 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Dynamic/Int16.txt ================================================ Int16,-1,1000,0,0,0,1,1,0,0,100,100 10000,10000,0,0,,,Int16,10 20000,20000,0,0,,,Int16,20 30000,30000,0,0,,,Int16,30 40000,40000,0x80000000,0,,,Int16,40 50000,50000,0,0,,,Int16,50 60000,60000,0,0,,,Int16,60 70000,70000,0x40000000,0,,,Int16,70 80000,80000,0,0,,,Int16,80 90000,90000,0,0,,,Int16,90 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Dynamic/Int32.txt ================================================ Int32,-1,1000,0,0,0,1,1,0,0,100,100 10000,10000,0,0,,,Int32,10 20000,20000,0,0,,,Int32,20 30000,30000,0,0,,,Int32,30 40000,40000,0x80000000,0,,,Int32,40 50000,50000,0,0,,,Int32,50 60000,60000,0,0,,,Int32,60 70000,70000,0x40000000,0,,,Int32,70 80000,80000,0,0,,,Int32,80 90000,90000,0,0,,,Int32,90 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Dynamic/Int64.txt ================================================ Int64,-1,1000,0,0,0,1,1,0,0,100,100 10000,10000,0,0,,,Int64,10 20000,20000,0,0,,,Int64,20 30000,30000,0,0,,,Int64,30 40000,40000,0x80000000,0,,,Int64,40 50000,50000,0,0,,,Int64,50 60000,60000,0,0,,,Int64,60 70000,70000,0x40000000,0,,,Int64,70 80000,80000,0,0,,,Int64,80 90000,90000,0,0,,,Int64,90 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Dynamic/SByte.txt ================================================ SByte,-1,125,0,0,0,1,0,0,0,100,100 10000,10000,0,0,,,SByte,11 20000,20000,0,0,,,SByte,22 30000,30000,0,0,,,SByte,33 40000,40000,0x80000000,0,,,SByte,44 50000,50000,0,0,,,SByte,55 60000,60000,0,0,,,SByte,66 70000,70000,0x40000000,0,,,SByte,77 80000,80000,0,0,,,SByte,88 90000,90000,0,0,,,SByte,99 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Dynamic/String.txt ================================================ String,-1,10000,0,0,0,0,0,0,1,100,100 0,0,0x809B0000,0,,,Null 2000,2000,0,0,,,String,abcd 25000,25000,0,0,,,String,efgh 28000,28000,0,0,,,String,ijkl 39000,39000,0,0,,,String,mnop 42000,42000,0x80000000,0,,,Null 48000,48000,0,0,,,String,qrst 52000,52000,0,0,,,String,uvw 72000,72000,0,0,,,String,xyza 77000,77000,0x40000000,0,,,String,bcd 83000,83000,0,0,,,String,egh 86000,86000,0,0,,,String,sadga 90000,90000,0,0,,,String,erfhrty ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Dynamic/UInt16.txt ================================================ UInt16,-1,1000,0,0,0,1,1,0,0,100,100 10000,10000,0,0,,,UInt16,10 20000,20000,0,0,,,UInt16,20 30000,30000,0,0,,,UInt16,30 40000,40000,0x80000000,0,,,UInt16,40 50000,50000,0,0,,,UInt16,50 60000,60000,0,0,,,UInt16,60 70000,70000,0x40000000,0,,,UInt16,70 80000,80000,0,0,,,UInt16,80 90000,90000,0,0,,,UInt16,90 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Dynamic/UInt32.txt ================================================ UInt32,-1,1000,0,0,0,1,1,0,0,100,100 10000,10000,0,0,,,UInt32,10 20000,20000,0,0,,,UInt32,20 30000,30000,0,0,,,UInt32,30 40000,40000,0x80000000,0,,,UInt32,40 50000,50000,0,0,,,UInt32,50 60000,60000,0,0,,,UInt32,60 70000,70000,0x40000000,0,,,UInt32,70 80000,80000,0,0,,,UInt32,80 90000,90000,0,0,,,UInt32,90 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Dynamic/UInt64.txt ================================================ UInt64,-1,1000,0,0,0,1,1,0,0,100,100 10000,10000,0,0,,,UInt64,10 20000,20000,0,0,,,UInt64,20 30000,30000,0,0,,,UInt64,30 40000,40000,0x80000000,0,,,UInt64,40 50000,50000,0,0,,,UInt64,50 60000,60000,0,0,,,UInt64,60 70000,70000,0x40000000,0,,,UInt64,70 80000,80000,0,0,,,UInt64,80 90000,90000,0,0,,,UInt64,90 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Sample/Boolean.txt ================================================ Boolean,-1,10000,0,0,0,0,1,0,1,100,100 2000,2000,0,0,,,Boolean,true 25000,25000,0,0,,,Boolean,false 28000,28000,0,0,,,Boolean,true 39000,39000,0,0,,,Boolean,true 42000,42000,0x80000000,0,,,Null 48000,48000,0,0,,,Boolean,true 52000,52000,0,0,,,Boolean,false 72000,72000,0,0,,,Boolean,false 77000,77000,0x40000000,0,,,Boolean,true 83000,83000,0,0,,,Boolean,true 86000,86000,0,0,,,Boolean,false 90000,90000,0,0,,,Boolean,true ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Sample/Byte.txt ================================================ Byte,-1,10000,0,0,0,0,0,0,0,100,100 10000,10000,0,0,,,Byte,250 20000,20000,0,0,,,Byte,230 30000,30000,0,0,,,Byte,150 40000,40000,0x80000000,0,,,Byte,120 40000,40000,0,-1,,,100000,Operator,Someone pulled the plug. 50000,50000,0,0,,,Byte,100 60000,60000,0,0,,,Byte,80 70000,70000,0x40000000,0,,,Byte,70 80000,80000,0,0,,,Byte,40 90000,90000,0,0,,,Byte,20 90000,90000,0,-1,,,100000,Operator,End of data collection. ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Sample/ByteString.txt ================================================ ByteString,-1,10000,0,0,0,0,1,0,1,100,100 2000,2000,0,0,,,ByteString,00010203040506070809 25000,25000,0,0,,,ByteString,00102030405060708090 28000,28000,0,0,,,ByteString,01020304050607080900 39000,39000,0,0,,,ByteString,10203040506070809000 42000,42000,0x80000000,0,,,Null 48000,48000,0,0,,,ByteString,02030405060708090001 52000,52000,0,0,,,ByteString,20304050607080900010 72000,72000,0,0,,,ByteString,50607080900010203040 77000,77000,0x40000000,0,,,ByteString,03040506070809000102 83000,83000,0,0,,,ByteString,03040506070809001020 86000,86000,0,0,,,ByteString,00010050607080920304 90000,90000,0,0,,,ByteString,07080900010203040506 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Sample/DateTime.txt ================================================ DateTime,-1,10000,0,0,0,0,1,0,1,100,100 2000,2000,0,0,,,DateTime,2013-10-18T16:24:13.000 25000,25000,0,0,,,DateTime,2013-10-18T17:25:13.000 28000,28000,0,0,,,DateTime,2013-10-18T18:26:13.575 39000,39000,0,0,,,DateTime,2013-10-18T19:24:13.575 42000,42000,0x80000000,0,,,Null 48000,48000,0,0,,,DateTime,2013-10-18T21:24:13.575 52000,52000,0,0,,,DateTime,2013-10-18T12:30:13.575 72000,72000,0,0,,,DateTime,2013-10-18T13:36:13.575 77000,77000,0x40000000,0,,,DateTime,2013-10-18T14:24:13.575 83000,83000,0,0,,,DateTime,2013-10-18T16:28:33.575 86000,86000,0,0,,,DateTime,2013-10-18T18:24:13.575 90000,90000,0,0,,,DateTime,2013-10-18T19:24:13.575 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Sample/Double.txt ================================================ Double,-1,10000,0,0,0,0,0,0,0,100,100 10000,10000,0,0,,,Double,10.0 20000,20000,0,0,,,Double,20.0 30000,30000,0,0,,,Double,30.0 40000,40000,0x80000000,0,,,Double,40.0 40000,40000,0,-1,,,100000,Operator,Someone pulled the plug. 50000,50000,0,0,,,Double,50.0 60000,60000,0,0,,,Double,60.0 70000,70000,0x40000000,0,,,Double,70.0 80000,80000,0,0,,,Double,80.0 90000,90000,0,0,,,Double,90.0 90000,90000,0,-1,,,100000,Operator,End of data collection. ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Sample/Float.txt ================================================ Float,-1,10000,0,0,0,0,0,0,1,100,100 2000,2000,0,0,,,Float,10 25000,25000,0,0,,,Float,20 28000,28000,0,0,,,Float,25 39000,39000,0,0,,,Float,30 42000,42000,0x80000000,0,,,Null 48000,48000,0,0,,,Float,4 52000,52000,0,0,,,Float,50 72000,72000,0,0,,,Float,60 77000,77000,0x40000000,0,,,Float,70 83000,83000,0,0,,,Float,70 86000,86000,0,0,,,Float,80 90000,90000,0,0,,,Float,90 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Sample/Historian1ExpectedData.csv ================================================ Time,Interopolated #1,,Interopolated #2,,Start Bounds,,End Bounds,,Average,,Time Average,,Time Average Bounds,,Count,,Total,,Time 0,0,BR,0,BR,0,BR,0,BR,0,BR,0,BR,0,BR,0,GC,0,GC,0 5,0,BR,0,BR,0,BR,10,GR,0,BR,0,BR,0,BR,0,GC,0,GC,5 10,10,GR,10,GR,10,GR,15,GI,10,GC,12.5,GC,12.5,GC,1,GC,10,GC,10 15,15,GI,15,GI,15,GI,20,GR,0,BR,17.5,GC,17.5,GC,0,GC,0,GC,15 20,20,GR,20,GR,20,GR,25,GI,20,GC,22.5,GC,22.5,GC,1,GC,20,GC,20 25,25,GI,25,GI,25,GI,30,GR,0,BR,27.5,GC,27.5,GC,0,GC,0,GC,25 30,30,GR,30,GR,30,GR,30,UI,30,GC,32.5,GC,30,GC,1,GC,30,GC,30 35,35,UI,35,UI,30,UI,0,BD,0,BR,37.5,UC,30,UC,0,GC,0,GC,35 40,40,UI,40,UI,0,BD,0,BR,0,BR,42.5,UC,0,BR,0,GC,0,GC,40 45,45,UI,45,UI,0,BR,50,GR,0,BR,47.5,UC,0,BR,0,GC,0,GC,45 50,50,GR,50,GR,50,GR,55,GI,50,GC,52.5,GC,52.5,GC,1,GC,50,GC,50 55,55,GI,55,GI,55,GI,60,GR,0,BR,57.5,GC,57.5,GC,0,GC,0,GC,55 60,60,GR,60,GR,60,GR,65,UI,60,GC,62.5,GC,62.5,GC,1,GC,60,GC,60 65,65,UI,65,UI,65,UI,70,UR,0,BR,67.5,UC,67.5,UC,0,GC,0,GC,65 70,70,UR,70,UI,70,UR,75,UI,70,GC,72.5,UC,72.5,UC,1,GC,70,UC,70 75,75,UI,75,UI,75,UI,80,GR,0,BR,77.5,UC,77.5,UC,0,GC,0,GC,75 80,80,GR,80,GR,80,GR,85,GI,80,GC,82.5,GC,82.5,GC,1,GC,80,GC,80 85,85,GI,85,GI,85,GI,90,GR,0,BR,87.5,GC,87.5,GC,0,GC,0,GC,85 90,90,GR,90,GR,90,GR,0,BR,90,GC,92.5,UC,90,UC,1,GC,90,GC,90 95,95,UI,95,UI,0,BR,0,BR,0,BR,97.5,UC,0,BR,0,GC,0,GC,95 100,100,UI,100,UI,0,BR,0,BR,0,BR,105,UC,0,BR,0,GC,0,GC,100 ,,,,,,,,,,,,,,,,,,, ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Sample/Historian2ExpectedData.csv ================================================ Time,Interopolated #1,,Interopolated #2,,Start Bounds,,End Bounds,,Average,,Time Average,,Time Average Bounds,,Count,,Total,,Time 0,0,BR,0,BR,0,BR,11.30434783,GI,10,UC,10.65217391,UC,10.65217391,UC,1,GC,10,GC,0 5,11.30434783,GI,11.30434783,GI,11.30434783,GI,13.47826087,GI,0,BR,12.39130435,GC,12.39130435,GC,0,GC,0,GC,5 10,13.47826087,GI,13.47826087,GI,13.47826087,GI,15.65217391,GI,0,BR,14.56521739,GC,14.56521739,GC,0,GC,0,GC,10 15,15.65217391,GI,15.65217391,GI,15.65217391,GI,17.82608696,GI,0,BR,16.73913043,GC,16.73913043,GC,0,GC,0,GC,15 20,17.82608696,GI,17.82608696,GI,17.82608696,GI,20,GR,0,BR,18.91304348,GC,18.91304348,GC,0,GC,0,GC,20 25,20,GR,20,GR,20,GR,25.90909091,GI,22.5,GC,23.68181818,GC,23.68181818,GC,2,GC,45,GC,25 30,25.90909091,GI,25.90909091,GI,25.90909091,GI,28.18181818,GI,0,BR,27.04545455,GC,27.04545455,GC,0,GC,0,GC,30 35,28.18181818,GI,28.18181818,GI,28.18181818,GI,30,UI,30,GC,29.38383838,UC,29.27272727,UC,1,GC,30,GC,35 40,31.11111111,UI,31.11111111,UI,30,UI,0,BR,0,BR,33.88888889,UC,30,UC,0,GC,0,UC,40 45,36.66666667,UI,36.66666667,UI,0,BR,45,GI,40,UC,40,UC,42.5,UC,1,GC,40,GC,45 50,45,GI,45,GI,45,GI,51.5,GI,50,GC,49.45,GC,49.45,GC,1,GC,50,GC,50 55,51.5,GI,51.5,GI,51.5,GI,54,GI,0,BR,52.75,GC,52.75,GC,0,GC,0,GC,55 60,54,GI,54,GI,54,GI,56.5,GI,0,BR,55.25,GC,55.25,GC,0,GC,0,GC,60 65,56.5,GI,56.5,GI,56.5,GI,59,GI,0,BR,57.75,GC,57.75,GC,0,GC,0,GC,65 70,59,GI,59,GI,59,GI,60,UI,60,GC,60.61818182,UC,59.8,UC,1,GC,60,GC,70 75,62.72727273,UI,66,UI,60,UI,0,BR,0,BR,65,UC,60,UC,0,GC,0,UC,75 80,67.27272727,UI,70,UI,0,BR,76.66666667,GI,70,UC,70.51515152,UC,73.33333333,UC,1,GC,70,GC,80 85,76.66666667,GI,76.66666667,GI,76.66666667,GI,90,GR,80,GC,83.66666667,GC,83.66666667,GC,1,GC,80,GC,85 90,90,GR,90,GR,90,GR,0,BR,90,GC,96.25,UC,90,UC,1,GC,90,GC,90 95,102.5,UI,102.5,UI,0,BR,0,BR,0,BR,108.75,UC,0,BR,0,GC,0,GC,95 100,115,UI,115,UI,0,BR,0,BR,0,BR,117.5,UC,0,BR,0,GC,0,GC,100 ,,,,,,,,,,,,,,,,,,, ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Sample/Historian3ExpectedData.csv ================================================ Time,Interopolated #1,,Interopolated #2,,Start Bounds,,End Bounds,,Average,,Time Average,,Time Average Bounds,,Count,,Total, 0,0,BR,0,BR,0,BR,10,GI,10,UC,10,UC,10,UC,1,GC,10,GC 5,10,GI,10,GI,10,GI,10,GI,0,BR,10,GC,10,GC,0,GC,0,GC 10,10,GI,10,GI,10,GI,10,GI,0,BR,10,GC,10,GC,0,GC,0,GC 15,10,GI,10,GI,10,GI,10,GI,0,BR,10,GC,10,GC,0,GC,0,GC 20,10,GI,10,GI,10,GI,20,GR,0,BR,10,GC,10,GC,0,GC,0,GC 25,20,GR,20,GR,20,GR,25,GI,22.5,GC,22,GC,22,GC,2,GC,45,GC 30,25,GI,25,GI,25,GI,25,GI,0,BR,25,GC,25,GC,0,GC,0,GC 35,25,GI,25,GI,25,GI,30,GI,30,GC,26,GC,26,GC,1,GC,30,GC 40,30,GI,30,GI,30,GI,0,BR,0,BR,30,UC,30,UC,0,GC,0,UC 45,30,UI,30,UI,0,BR,40,GI,40,UC,34,UC,40,UC,1,GC,40,GC 50,40,GI,40,GI,40,GI,50,GI,50,GC,46,GC,46,GC,1,GC,50,GC 55,50,GI,50,GI,50,GI,50,GI,0,BR,50,GC,50,GC,0,GC,0,GC 60,50,GI,50,GI,50,GI,50,GI,0,BR,50,GC,50,GC,0,GC,0,GC 65,50,GI,50,GI,50,GI,50,GI,0,BR,50,GC,50,GC,0,GC,0,GC 70,50,GI,50,GI,50,GI,60,GI,60,GC,56,GC,56,GC,1,GC,60,GC 75,60,GI,60,GI,60,GI,0,BR,0,BR,60,UC,60,UC,0,GC,0,UC 80,60,UI,70,UI,0,BR,70,GI,70,UC,64,UC,70,UC,1,GC,70,GC 85,70,GI,70,GI,70,GI,90,GR,80,GC,78,GC,78,GC,1,GC,80,GC 90,90,GR,90,GR,90,GR,0,BR,90,GC,90,UC,90,UC,1,GC,90,GC 95,90,UI,90,UI,0,BR,0,BR,0,BR,90,UC,0,BR,0,GC,0,GC 100,90,UI,90,UI,0,BR,0,BR,0,BR,90,UC,0,BR,0,GC,0,GC ,,,,,,,,,,,,,,,,,, ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Sample/Int16.txt ================================================ Int16,-1,10000,0,0,0,0,0,0,1,100,100 2000,2000,0,0,,,Int16,10 25000,25000,0,0,,,Int16,20 28000,28000,0,0,,,Int16,25 39000,39000,0,0,,,Int16,30 42000,42000,0x80000000,0,,,Null 48000,48000,0,0,,,Int16,4 52000,52000,0,0,,,Int16,50 72000,72000,0,0,,,Int16,60 77000,77000,0x40000000,0,,,Int16,70 83000,83000,0,0,,,Int16,70 86000,86000,0,0,,,Int16,80 90000,90000,0,0,,,Int16,90 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Sample/Int32.txt ================================================ Int32,-1,10000,0,0,0,0,1,0,1,100,100 2000,2000,0,0,,,Int32,10 25000,25000,0,0,,,Int32,20 28000,28000,0,0,,,Int32,25 39000,39000,0,0,,,Int32,30 42000,42000,0x80000000,0,,,Null 48000,48000,0,0,,,Int32,40 52000,52000,0,0,,,Int32,50 72000,72000,0,0,,,Int32,60 77000,77000,0x40000000,0,,,Int32,70 83000,83000,0,0,,,Int32,70 86000,86000,0,0,,,Int32,80 90000,90000,0,0,,,Int32,90 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Sample/Int64.txt ================================================ Int64,-1,10000,0,0,0,0,1,0,1,100,100 2000,2000,0,0,,,Int64,10 25000,25000,0,0,,,Int64,20 28000,28000,0,0,,,Int64,25 39000,39000,0,0,,,Int64,30 42000,42000,0x80000000,0,,,Null 48000,48000,0,0,,,Int64,40 52000,52000,0,0,,,Int64,50 72000,72000,0,0,,,Int64,60 77000,77000,0x40000000,0,,,Int64,70 83000,83000,0,0,,,Int64,70 86000,86000,0,0,,,Int64,80 90000,90000,0,0,,,Int64,90 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Sample/SByte.txt ================================================ SByte,-1,10000,0,0,0,0,1,0,1,100,100 2000,2000,0,0,,,SByte,10 25000,25000,0,0,,,SByte,20 28000,28000,0,0,,,SByte,25 39000,39000,0,0,,,SByte,30 42000,42000,0x80000000,0,,,Null 48000,48000,0,0,,,SByte,40 52000,52000,0,0,,,SByte,50 72000,72000,0,0,,,SByte,60 77000,77000,0x40000000,0,,,SByte,70 83000,83000,0,0,,,SByte,70 86000,86000,0,0,,,SByte,80 90000,90000,0,0,,,SByte,90 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Sample/String.txt ================================================ String,-1,10000,0,0,0,0,1,0,1,100,100 2000,2000,0,0,,,String,jasOEWUT 25000,25000,0,0,,,String,JWYEJFDLJA 28000,28000,0,0,,,String,UFDfdc'po 39000,39000,0,0,,,String,wueyd20897 42000,42000,0x80000000,0,,,Null 48000,48000,0,0,,,String,jedf;ocv 52000,52000,0,0,,,String,e;jphg 72000,72000,0,0,,,String,shjdj 77000,77000,0x40000000,0,,,String,poewdrc 83000,83000,0,0,,,String,ouepofg 86000,86000,0,0,,,String,eglogf 90000,90000,0,0,,,String,wetrc ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Sample/UInt16.txt ================================================ UInt16,-1,10000,0,0,0,0,0,0,1,100,100 2000,2000,0,0,,,UInt16,10 25000,25000,0,0,,,UInt16,20 28000,28000,0,0,,,UInt16,25 39000,39000,0,0,,,UInt16,30 42000,42000,0x80000000,0,,,Null 48000,48000,0,0,,,UInt16,4 52000,52000,0,0,,,UInt16,50 72000,72000,0,0,,,UInt16,60 77000,77000,0x40000000,0,,,UInt16,70 83000,83000,0,0,,,UInt16,70 86000,86000,0,0,,,UInt16,80 90000,90000,0,0,,,UInt16,90 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Sample/UInt32.txt ================================================ UInt32,-1,10000,0,0,0,0,0,0,1,100,100 2000,2000,0,0,,,UInt32,10 25000,25000,0,0,,,UInt32,20 28000,28000,0,0,,,UInt32,25 39000,39000,0,0,,,UInt32,30 42000,42000,0x80000000,0,,,Null 48000,48000,0,0,,,UInt32,4 52000,52000,0,0,,,UInt32,50 72000,72000,0,0,,,UInt32,60 77000,77000,0x40000000,0,,,UInt32,70 83000,83000,0,0,,,UInt32,70 86000,86000,0,0,,,UInt32,80 90000,90000,0,0,,,UInt32,90 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Data/Sample/UInt64.txt ================================================ UInt64,-1,10000,0,0,0,0,0,0,1,100,100 2000,2000,0,0,,,UInt64,10 25000,25000,0,0,,,UInt64,20 28000,28000,0,0,,,UInt64,25 39000,39000,0,0,,,UInt64,30 42000,42000,0x80000000,0,,,Null 48000,48000,0,0,,,UInt64,4 52000,52000,0,0,,,UInt64,50 72000,72000,0,0,,,UInt64,60 77000,77000,0x40000000,0,,,UInt64,70 83000,83000,0,0,,,UInt64,70 86000,86000,0,0,,,UInt64,80 90000,90000,0,0,,,UInt64,90 ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/DataFileReader.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace HistoricalAccess { using Opc.Ua; using Opc.Ua.Test; using System; using System.Data; using System.Globalization; using System.IO; using System.Text; using System.Xml; /// /// Reads an item history from a file. /// public class DataFileReader { private readonly TimeService _timeService; public DataFileReader(TimeService timeService) { _timeService = timeService; } /// /// Creates a new data set. /// private DataSet CreateDataSet() { var dataset = new DataSet(); dataset.Tables.Add("CurrentData"); dataset.Tables[0].Columns.Add("SourceTimestamp", typeof(DateTime)); dataset.Tables[0].Columns.Add("ServerTimestamp", typeof(DateTime)); dataset.Tables[0].Columns.Add("Value", typeof(DataValue)); dataset.Tables[0].Columns.Add("DataType", typeof(BuiltInType)); dataset.Tables[0].Columns.Add("ValueRank", typeof(int)); dataset.Tables[0].DefaultView.Sort = "SourceTimestamp"; dataset.Tables.Add("ModifiedData"); dataset.Tables[1].Columns.Add("SourceTimestamp", typeof(DateTime)); dataset.Tables[1].Columns.Add("ServerTimestamp", typeof(DateTime)); dataset.Tables[1].Columns.Add("Value", typeof(DataValue)); dataset.Tables[1].Columns.Add("DataType", typeof(BuiltInType)); dataset.Tables[1].Columns.Add("ValueRank", typeof(int)); dataset.Tables[1].Columns.Add("UpdateType", typeof(int)); dataset.Tables[1].Columns.Add("ModificationInfo", typeof(ModificationInfo)); dataset.Tables[1].DefaultView.Sort = "SourceTimestamp"; dataset.Tables.Add("AnnotationData"); dataset.Tables[2].Columns.Add("SourceTimestamp", typeof(DateTime)); dataset.Tables[2].Columns.Add("ServerTimestamp", typeof(DateTime)); dataset.Tables[2].Columns.Add("Value", typeof(DataValue)); dataset.Tables[2].Columns.Add("DataType", typeof(BuiltInType)); dataset.Tables[2].Columns.Add("ValueRank", typeof(int)); dataset.Tables[2].Columns.Add("Annotation", typeof(Annotation)); dataset.Tables[2].DefaultView.Sort = "SourceTimestamp"; return dataset; } #pragma warning disable IDE0079 // Remove unnecessary suppression #pragma warning disable IDE0060 // Remove unused parameter /// /// Loads the item configuaration. /// /// /// public bool LoadConfiguration(ISystemContext context, ArchiveItem item) #pragma warning restore IDE0060 // Remove unused parameter #pragma warning restore IDE0079 // Remove unnecessary suppression { using var reader = item.OpenArchive(); while (!reader.EndOfStream) { var line = reader.ReadLine(); // check for end or error. if (line == null) { break; } // ignore blank lines. line = line.Trim(); if (string.IsNullOrEmpty(line)) { continue; } // ignore commented out lines. if (line.StartsWith("//", StringComparison.CurrentCulture)) { continue; } // get data type. if (!ExtractField(1, ref line, out BuiltInType dataType)) { return false; } // get value rank. if (!ExtractField(1, ref line, out int valueRank)) { return false; } // get sampling interval. if (!ExtractField(1, ref line, out int samplingInterval)) { return false; } // get simulation type. if (!ExtractField(1, ref line, out int simulationType)) { return false; } // get simulation amplitude. if (!ExtractField(1, ref line, out int amplitude)) { return false; } // get simulation period. if (!ExtractField(1, ref line, out int period)) { return false; } // get flag indicating whether new data is generated. if (!ExtractField(1, ref line, out int archiving)) { return false; } // get flag indicating whether stepped interpolation is used. if (!ExtractField(1, ref line, out int stepped)) { return false; } // get flag indicating whether sloped interpolation should be used. if (!ExtractField(1, ref line, out int useSlopedExtrapolation)) { return false; } // get flag indicating whether sloped interpolation should be used. if (!ExtractField(1, ref line, out int treatUncertainAsBad)) { return false; } // get the maximum permitted of bad data in an interval. if (!ExtractField(1, ref line, out int percentDataBad)) { return false; } // get the minimum amount of good data in an interval. if (!ExtractField(1, ref line, out int percentDataGood)) { return false; } // update the item. item.DataType = dataType; item.ValueRank = valueRank; item.SimulationType = simulationType; item.Amplitude = amplitude; item.Period = period; item.SamplingInterval = samplingInterval; item.Archiving = archiving != 0; item.Stepped = stepped != 0; item.AggregateConfiguration = new AggregateConfiguration { UseServerCapabilitiesDefaults = false, UseSlopedExtrapolation = useSlopedExtrapolation != 0, TreatUncertainAsBad = treatUncertainAsBad != 0, PercentDataBad = (byte)percentDataBad, PercentDataGood = (byte)percentDataGood }; break; } return true; } /// /// Creates new data. /// /// public void CreateData(ArchiveItem item) { // get the data set to use. var dataset = item.DataSet ?? CreateDataSet(); // generate one hour worth of data by default. var startTime = _timeService.UtcNow.AddHours(-1); startTime = new DateTime(startTime.Year, startTime.Month, startTime.Day, startTime.Hour, 0, 0, DateTimeKind.Utc); // check for existing data. if (dataset.Tables[0].Rows.Count > 0) { var index = dataset.Tables[0].DefaultView.Count; _ = (DateTime)dataset.Tables[0].DefaultView[index - 1].Row[0]; _ = startTime.AddMilliseconds(item.SamplingInterval); } var currentTime = startTime; var generator = new TestDataGenerator(); var endTime = startTime.AddHours(1); while (currentTime < endTime) { var dataValue = new DataValue { SourceTimestamp = currentTime, ServerTimestamp = currentTime, StatusCode = StatusCodes.Good }; // generate random value. if (item.ValueRank < 0) { dataValue.Value = generator.GetRandom(item.DataType); } else { dataValue.Value = generator.GetRandomArray(item.DataType, 10, false); } // add record to table. var row = dataset.Tables[0].NewRow(); row[0] = dataValue.SourceTimestamp; row[1] = dataValue.ServerTimestamp; row[2] = dataValue; row[3] = dataValue.WrappedValue.TypeInfo.BuiltInType; row[4] = dataValue.WrappedValue.TypeInfo.ValueRank; dataset.Tables[0].Rows.Add(row); // increment timestamp. currentTime = currentTime.AddMilliseconds(item.SamplingInterval); } dataset.AcceptChanges(); item.DataSet = dataset; } /// /// Loads the history for the item. /// /// /// public void LoadHistoryData(ISystemContext context, ArchiveItem item) { // use the beginning of the current hour for the baseline. var baseline = _timeService.UtcNow; baseline = new DateTime(baseline.Year, baseline.Month, baseline.Day, baseline.Hour, 0, 0, DateTimeKind.Utc); using (var reader = item.OpenArchive()) { // skip configuration line. reader.ReadLine(); item.DataSet = LoadData(context, baseline, reader); } // create a random dataset if nothing found in the archive, if (item.DataSet == null || item.DataSet.Tables[0].Rows.Count == 0) { CreateData(item); } // update the timestamp. item.LastLoadTime = _timeService.UtcNow; } /// /// Loads the history data from a stream. /// /// /// /// private DataSet LoadData(ISystemContext context, DateTime baseline, StreamReader reader) { var dataset = CreateDataSet(); var messageContext = new ServiceMessageContext(); if (context != null) { messageContext.NamespaceUris = context.NamespaceUris; messageContext.ServerUris = context.ServerUris; messageContext.Factory = context.EncodeableFactory; } else { messageContext.NamespaceUris = ServiceMessageContext.GlobalContext.NamespaceUris; messageContext.ServerUris = ServiceMessageContext.GlobalContext.ServerUris; messageContext.Factory = ServiceMessageContext.GlobalContext.Factory; } var valueType = BuiltInType.String; var value = Variant.Null; var annotationTimeOffet = 0; var annotationUser = string.Empty; var annotationMessage = string.Empty; var lineCount = 0; while (!reader.EndOfStream) { var line = reader.ReadLine(); // check for end or error. if (line == null) { break; } // ignore blank lines. line = line.Trim(); lineCount++; if (string.IsNullOrEmpty(line)) { continue; } // ignore commented out lines. if (line.StartsWith("//", StringComparison.CurrentCulture)) { continue; } // get source time. if (!ExtractField(lineCount, ref line, out int sourceTimeOffset)) { continue; } // get server time. if (!ExtractField(lineCount, ref line, out int serverTimeOffset)) { continue; } // get status code. if (!ExtractField(lineCount, ref line, out StatusCode status)) { continue; } // get modification type. if (!ExtractField(lineCount, ref line, out int recordType)) { continue; } // get modification time. if (!ExtractField(lineCount, ref line, out int modificationTimeOffet)) { continue; } // get modification user. if (!ExtractField(ref line, out var modificationUser)) { continue; } if (recordType >= 0) { // get value type. if (!ExtractField(lineCount, ref line, out valueType)) { continue; } // get value. if (!ExtractField(lineCount, ref line, messageContext, valueType, out value)) { continue; } } else { // get annotation time. if (!ExtractField(lineCount, ref line, out annotationTimeOffet)) { continue; } // get annotation user. if (!ExtractField(ref line, out annotationUser)) { continue; } // get annotation message. if (!ExtractField(ref line, out annotationMessage)) { continue; } } // add values to data table. var dataValue = new DataValue { WrappedValue = value, SourceTimestamp = baseline.AddMilliseconds(sourceTimeOffset), ServerTimestamp = baseline.AddMilliseconds(serverTimeOffset), StatusCode = status }; DataRow row; if (recordType == 0) { row = dataset.Tables[0].NewRow(); row[0] = dataValue.SourceTimestamp; row[1] = dataValue.ServerTimestamp; row[2] = dataValue; row[3] = valueType; row[4] = (value.TypeInfo != null) ? value.TypeInfo.ValueRank : ValueRanks.Any; dataset.Tables[0].Rows.Add(row); } else if (recordType > 0) { row = dataset.Tables[1].NewRow(); row[0] = dataValue.SourceTimestamp; row[1] = dataValue.ServerTimestamp; row[2] = dataValue; row[3] = valueType; row[4] = (value.TypeInfo != null) ? value.TypeInfo.ValueRank : ValueRanks.Any; row[5] = recordType; row[6] = new ModificationInfo { UpdateType = (HistoryUpdateType)recordType, ModificationTime = baseline.AddMilliseconds(modificationTimeOffet), UserName = modificationUser }; dataset.Tables[1].Rows.Add(row); } else if (recordType < 0) { row = dataset.Tables[2].NewRow(); var annotation = new Annotation { AnnotationTime = baseline.AddMilliseconds(annotationTimeOffet), UserName = annotationUser, Message = annotationMessage }; dataValue.WrappedValue = new ExtensionObject(annotation); row[0] = dataValue.SourceTimestamp; row[1] = dataValue.ServerTimestamp; row[2] = dataValue; row[3] = valueType; row[4] = (value.TypeInfo != null) ? value.TypeInfo.ValueRank : ValueRanks.Any; row[5] = annotation; dataset.Tables[2].Rows.Add(row); } dataset.AcceptChanges(); } return dataset; } /// /// Extracts the next comma seperated field from the line. /// /// private string ExtractField(ref string line) { var field = line; var index = field.IndexOf(','); if (index >= 0) { field = field[..index]; line = line[(index + 1)..]; } field = field.Trim(); if (string.IsNullOrEmpty(field)) { return null; } return field; } /// /// Extracts an integer value from the line. /// /// /// private bool ExtractField(ref string line, out string value) { value = string.Empty; var field = ExtractField(ref line); if (field == null) { return true; } value = field; return true; } /// /// Extracts an integer value from the line. /// /// /// /// private bool ExtractField(int lineCount, ref string line, out int value) { value = 0; var field = ExtractField(ref line); if (field == null) { return true; } try { value = Convert.ToInt32(field); } catch (Exception e) { Utils.Trace("PARSE ERROR [Line:{0}] - '{1}': {2}", lineCount, field, e.Message); return false; } return true; } /// /// Extracts a StatusCode value from the line. /// /// /// /// private bool ExtractField(int lineCount, ref string line, out StatusCode value) { value = 0; var field = ExtractField(ref line); if (field == null) { return true; } if (field.StartsWith("0x", StringComparison.CurrentCulture)) { field = field[2..]; } try { var code = Convert.ToUInt32(field, 16); value = new StatusCode(code); } catch (Exception e) { Utils.Trace("PARSE ERROR [Line:{0}] - '{1}': {2}", lineCount, field, e.Message); return false; } return true; } /// /// Extracts a BuiltInType value from the line. /// /// /// /// private bool ExtractField(int lineCount, ref string line, out BuiltInType value) { value = BuiltInType.String; var field = ExtractField(ref line); if (field == null) { return true; } try { value = Enum.Parse(field); } catch (Exception e) { Utils.Trace("PARSE ERROR [Line:{0}] - '{1}': {2}", lineCount, field, e.Message); return false; } return true; } /// /// Extracts a BuiltInType value from the line. /// /// /// /// /// /// private static bool ExtractField(int lineCount, ref string line, IServiceMessageContext context, BuiltInType valueType, out Variant value) { value = Variant.Null; var field = line; if (field == null) { return true; } if (valueType == BuiltInType.Null) { return true; } var builder = new StringBuilder() .AppendFormat(CultureInfo.InvariantCulture, "", Opc.Ua.Namespaces.OpcUaXsd) .AppendFormat(CultureInfo.InvariantCulture, "<{0}>", valueType) .Append(line) .AppendFormat(CultureInfo.InvariantCulture, "", valueType) .Append(""); var document = new XmlDocument { InnerXml = builder.ToString() }; XmlDecoder decoder = null; try { decoder = new XmlDecoder(document.DocumentElement, context); value = decoder.ReadVariant(null); } catch (Exception e) { Utils.Trace("PARSE ERROR [Line:{0}] - '{1}': {2}", lineCount, field, e.Message); return false; } finally { decoder?.Dispose(); } return true; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/HistoricalAccessNodeManager.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace HistoricalAccess { using Opc.Ua; using Opc.Ua.Server; using Opc.Ua.Test; using System; using System.Collections.Generic; using System.Data; using System.Reflection; using System.Threading; /// /// A node manager for a server that exposes several variables. /// public class HistoricalAccessServerNodeManager : CustomNodeManager2 { /// /// Initializes the node manager. /// /// /// /// public HistoricalAccessServerNodeManager(IServerInternal server, ApplicationConfiguration configuration, TimeService timeService) : base(server, configuration, Namespaces.HistoricalAccess) { AliasRoot = "HDA"; // get the configuration for the node manager. _configuration = configuration.ParseExtension(); // use suitable defaults if no configuration exists. _configuration ??= new HistoricalAccessServerConfiguration { ArchiveRoot = "Historian" }; _timeService = timeService; SystemContext.SystemHandle = _system = new UnderlyingSystem(_configuration, NamespaceIndex, timeService); SystemContext.NodeIdFactory = this; } /// /// An overrideable version of the Dispose. /// /// protected override void Dispose(bool disposing) { if (disposing && _simulationTimer != null) { _simulationTimer.Dispose(); _simulationTimer = null; } base.Dispose(disposing); } /// /// Creates the NodeId for the specified node. /// /// The context. /// The node. /// The new NodeId. /// /// This method is called by the NodeState.Create() method which initializes a Node from /// the type model. During initialization a number of child nodes are created and need to /// have NodeIds assigned to them. This implementation constructs NodeIds by constructing /// strings. Other implementations could assign unique integers or Guids and save the new /// Node in a dictionary for later lookup. /// public override NodeId New(ISystemContext context, NodeState node) { if (node is BaseInstanceState instance && instance.Parent != null) { return NodeTypes.ConstructIdForComponent(instance, instance.Parent.NodeId.NamespaceIndex); } return node.NodeId; } /// /// Does any initialization required before the address space can be used. /// /// public override void CreateAddressSpace(IDictionary> externalReferences) { lock (Server.DiagnosticsLock) { var capabilities = Server.DiagnosticsNodeManager.GetDefaultHistoryCapabilities(); capabilities.AccessHistoryDataCapability.Value = true; capabilities.InsertDataCapability.Value = true; capabilities.ReplaceDataCapability.Value = true; capabilities.UpdateDataCapability.Value = true; capabilities.DeleteRawCapability.Value = true; capabilities.DeleteAtTimeCapability.Value = true; capabilities.InsertAnnotationCapability.Value = true; } lock (Lock) { if (!externalReferences.TryGetValue(ObjectIds.ObjectsFolder, out var references)) { externalReferences[ObjectIds.ObjectsFolder] = references = []; } var root = _system.GetFolderState(string.Empty); references.Add(new NodeStateReference(ReferenceTypeIds.Organizes, false, root.NodeId)); root.AddReference(ReferenceTypeIds.Organizes, true, ObjectIds.ObjectsFolder); CreateFolderFromResources(root, "Sample"); // CreateFolderFromResources(root, "Dynamic"); } } /// /// Creates items from embedded resources. /// /// /// private void CreateFolderFromResources(NodeState root, string folderName) { var dataFolder = new FolderState(root) { ReferenceTypeId = ReferenceTypeIds.Organizes, TypeDefinitionId = ObjectTypeIds.FolderType, NodeId = new NodeId(folderName, NamespaceIndex), BrowseName = new QualifiedName(folderName, NamespaceIndex) }; dataFolder.DisplayName = dataFolder.BrowseName.Name; dataFolder.WriteMask = AttributeWriteMask.None; dataFolder.UserWriteMask = AttributeWriteMask.None; dataFolder.EventNotifier = EventNotifiers.None; root.AddChild(dataFolder); AddPredefinedNode(SystemContext, root); var type = GetType().GetTypeInfo(); foreach (var resourcePath in Assembly.GetExecutingAssembly().GetManifestResourceNames()) { if (!resourcePath.StartsWith($"{type.Assembly.GetName().Name}.HistoricalAccess.Data.{folderName}.", StringComparison.Ordinal)) { continue; } var item = new ArchiveItem(resourcePath, Assembly.GetExecutingAssembly(), resourcePath); var node = new ArchiveItemState(SystemContext, item, NamespaceIndex, _timeService); node.ReloadFromSource(SystemContext); dataFolder.AddReference(ReferenceTypeIds.Organizes, false, node.NodeId); node.AddReference(ReferenceTypeIds.Organizes, true, dataFolder.NodeId); AddPredefinedNode(SystemContext, node); } } /// /// Frees any resources allocated for the address space. /// public override void DeleteAddressSpace() { lock (Lock) { // TBD } } /// /// Returns a unique handle for the node. /// /// /// /// protected override NodeHandle GetManagerHandle(ServerSystemContext context, NodeId nodeId, IDictionary cache) { lock (Lock) { // quickly exclude nodes that are not in the namespace. if (!IsNodeIdInNamespace(nodeId)) { return null; } // check for check for nodes that are being currently monitored. if (MonitoredNodes.TryGetValue(nodeId, out var monitoredNode)) { return new NodeHandle { NodeId = nodeId, Validated = true, Node = monitoredNode.Node }; } // check for predefined nodes, if (PredefinedNodes.TryGetValue(nodeId, out var node)) { return new NodeHandle { NodeId = nodeId, Node = node, Validated = true }; } // parse the identifier. var parsedNodeId = ParsedNodeId.Parse(nodeId); if (parsedNodeId != null) { return new NodeHandle { NodeId = nodeId, Validated = false, Node = null, ParsedNodeId = parsedNodeId }; } return null; } } /// /// Verifies that the specified node exists. /// /// /// /// protected override NodeState ValidateNode( ServerSystemContext context, NodeHandle handle, IDictionary cache) { // lookup in cache. var target = FindNodeInCache(context, handle, cache); if (target != null) { handle.Node = target; handle.Validated = true; return handle.Node; } var pnd = (ParsedNodeId)handle.ParsedNodeId; // check for a new node. switch (pnd.RootType) { case NodeTypes.Folder: { target = _system.GetFolderState(pnd.RootId); break; } case NodeTypes.Item: { var item = _system.GetItemState(SystemContext, pnd); item.LoadConfiguration(context); target = item; break; } } // root is not valid. if (target == null) { return null; } // validate component. if (!string.IsNullOrEmpty(pnd.ComponentPath)) { NodeState component = target.FindChildBySymbolicName(context, pnd.ComponentPath); // component does not exist. if (component == null) { return null; } target = component; } // put root into cache. if (cache != null) { cache[handle.NodeId] = target; } handle.Node = target; handle.Validated = true; return handle.Node; } /// /// Validates the nodes and reads the values from the underlying source. /// /// /// /// /// /// /// protected override void Read( ServerSystemContext context, IList nodesToRead, IList values, IList errors, List nodesToValidate, IDictionary cache) { for (var ii = 0; ii < nodesToValidate.Count; ii++) { var handle = nodesToValidate[ii]; lock (Lock) { // validate node. var source = ValidateNode(context, handle, cache); if (source == null) { continue; } // check if the node needs to be initialized from disk. if (source.GetHierarchyRoot() is ArchiveItemState item && item.ArchiveItem.LastLoadTime.AddDays(1) < _timeService.UtcNow) { item.LoadConfiguration(context); } var nodeToRead = nodesToRead[handle.Index]; var value = values[handle.Index]; // update the attribute value. errors[handle.Index] = source.ReadAttribute( context, nodeToRead.AttributeId, nodeToRead.ParsedIndexRange, nodeToRead.DataEncoding, value); } } } /// /// Reads the initial value for a monitored item. /// /// The context. /// The item handle. /// The monitored item. protected override ServiceResult ReadInitialValue( ISystemContext context, NodeHandle handle, IDataChangeMonitoredItem2 monitoredItem) { var monitoredItemObj = monitoredItem as MonitoredItem; if (handle.Node is not ArchiveItemState || monitoredItemObj?.AttributeId != Attributes.Value) { return base.ReadInitialValue(context, handle, monitoredItem); } if (monitoredItemObj?.Filter is not AggregateFilter filter || filter.StartTime >= _timeService.UtcNow.AddMilliseconds(-filter.ProcessingInterval)) { return base.ReadInitialValue(context, handle, monitoredItem); } var details = new ReadRawModifiedDetails { StartTime = filter.StartTime, EndTime = _timeService.UtcNow, ReturnBounds = true, IsReadModified = false, NumValuesPerNode = 0 }; var nodeToRead = new HistoryReadValueId { NodeId = handle.NodeId, ParsedIndexRange = NumericRange.Empty }; try { var request = CreateHistoryReadRequest( context as ServerSystemContext, details, handle, nodeToRead); while (request.Values.Count > 0) { if (request.Values.Count == 0) { break; } var value = request.Values.First.Value; request.Values.RemoveFirst(); monitoredItemObj.QueueValue(value, null, true); } return StatusCodes.Good; } catch (Exception e) { var error = ServiceResult.Create(e, StatusCodes.BadUnexpectedError, "Unexpected error fetching initial values."); monitoredItemObj.QueueValue(null, error, true); return error; } } /// /// Called after creating a MonitoredItem. /// /// /// /// protected override void OnMonitoredItemCreated(ServerSystemContext context, NodeHandle handle, ISampledDataChangeMonitoredItem monitoredItem) { lock (Lock) { var root = handle.Node.GetHierarchyRoot(); if (root != null && root is ArchiveItemState item) { _monitoredItems ??= []; _monitoredItems.TryAdd(item.ArchiveItem.UniquePath, item); item.SubscribeCount++; _simulationTimer ??= new Timer(DoSimulation, null, 500, 500); } } } /// /// Revises an aggregate filter (may require knowledge of the variable being used). /// /// The context. /// The handle. /// The sampling interval for the monitored item. /// The queue size for the monitored item. /// The filter to revise. /// Good if the filter is acceptable. protected override StatusCode ReviseAggregateFilter( ServerSystemContext context, NodeHandle handle, double samplingInterval, uint queueSize, ServerAggregateFilter filterToUse) { // use the sampling interval to limit the processing interval. if (filterToUse.ProcessingInterval < samplingInterval) { filterToUse.ProcessingInterval = samplingInterval; } // check if an archive item. if (handle.Node is not ArchiveItemState item) { // no historial data so must start in the future. while (filterToUse.StartTime < _timeService.UtcNow) { filterToUse.StartTime = filterToUse.StartTime.AddMilliseconds(filterToUse.ProcessingInterval); } // use suitable defaults for values which are are not archived items. filterToUse.AggregateConfiguration.UseServerCapabilitiesDefaults = false; filterToUse.AggregateConfiguration.UseSlopedExtrapolation = false; filterToUse.AggregateConfiguration.TreatUncertainAsBad = false; filterToUse.AggregateConfiguration.PercentDataBad = 100; filterToUse.AggregateConfiguration.PercentDataGood = 100; filterToUse.Stepped = true; } else { // use the archive acquisition sampling interval to limit the processing interval. if (filterToUse.ProcessingInterval < item.ArchiveItem.SamplingInterval) { filterToUse.ProcessingInterval = item.ArchiveItem.SamplingInterval; } // ensure the buffer does not get overfilled. while (filterToUse.StartTime.AddMilliseconds(queueSize * filterToUse.ProcessingInterval) < _timeService.UtcNow) { filterToUse.StartTime = filterToUse.StartTime.AddMilliseconds(filterToUse.ProcessingInterval); } filterToUse.Stepped = item.ArchiveItem.Stepped; // revise the configration. ReviseAggregateConfiguration(context, item, filterToUse.AggregateConfiguration); } return StatusCodes.Good; } /// /// Revises the aggregate configuration. /// /// /// /// private void ReviseAggregateConfiguration( ServerSystemContext context, ArchiveItemState item, AggregateConfiguration configurationToUse) { System.Diagnostics.Contracts.Contract.Assume(context != null); // set configuration from defaults. if (configurationToUse.UseServerCapabilitiesDefaults) { var configuration = item.ArchiveItem.AggregateConfiguration; if (configuration?.UseServerCapabilitiesDefaults != false) { configuration = Server.AggregateManager.GetDefaultConfiguration(null); } configurationToUse.UseSlopedExtrapolation = configuration.UseSlopedExtrapolation; configurationToUse.TreatUncertainAsBad = configuration.TreatUncertainAsBad; configurationToUse.PercentDataBad = configuration.PercentDataBad; configurationToUse.PercentDataGood = configuration.PercentDataGood; } // override configuration when it does not make sense for the item. configurationToUse.UseServerCapabilitiesDefaults = false; if (item.ArchiveItem.Stepped) { configurationToUse.UseSlopedExtrapolation = false; } } /// /// Called after deleting a MonitoredItem. /// /// /// /// protected override void OnMonitoredItemDeleted(ServerSystemContext context, NodeHandle handle, ISampledDataChangeMonitoredItem monitoredItem) { lock (Lock) { var root = handle.Node.GetHierarchyRoot(); if (root != null && root is ArchiveItemState item && _monitoredItems.TryGetValue(item.ArchiveItem.UniquePath, out var item2)) { item2.SubscribeCount--; if (item2.SubscribeCount == 0) { _monitoredItems.Remove(item.ArchiveItem.UniquePath); } if (_monitoredItems.Count == 0 && _simulationTimer != null) { _simulationTimer.Dispose(); _simulationTimer = null; } } } } /// /// Reads the raw data for an item. /// /// /// /// /// /// /// /// /// protected override void HistoryReadRawModified( ServerSystemContext context, ReadRawModifiedDetails details, TimestampsToReturn timestampsToReturn, IList nodesToRead, IList results, IList errors, List nodesToProcess, IDictionary cache) { for (var ii = 0; ii < nodesToRead.Count; ii++) { var handle = nodesToProcess[ii]; var nodeToRead = nodesToRead[handle.Index]; var result = results[handle.Index]; try { // validate node. var source = ValidateNode(context, handle, cache); if (source == null) { continue; } HistoryReadRequest request; // load an exising request. if (nodeToRead.ContinuationPoint != null) { request = LoadContinuationPoint(context, nodeToRead.ContinuationPoint); if (request == null) { errors[handle.Index] = StatusCodes.BadContinuationPointInvalid; continue; } } // create a new request. else { request = CreateHistoryReadRequest( context, details, handle, nodeToRead); } // process values until the max is reached. var data = details.IsReadModified ? new HistoryModifiedData() : new HistoryData(); while (request.NumValuesPerNode == 0 || data.DataValues.Count < request.NumValuesPerNode) { if (request.Values.Count == 0) { break; } var value = request.Values.First.Value; request.Values.RemoveFirst(); data.DataValues.Add(value); if (data is HistoryModifiedData modifiedData) { ModificationInfo modificationInfo = null; if (request.ModificationInfos?.Count > 0) { modificationInfo = request.ModificationInfos.First.Value; request.ModificationInfos.RemoveFirst(); } modifiedData.ModificationInfos.Add(modificationInfo); } } errors[handle.Index] = ServiceResult.Good; // check if a continuation point is requred. if (request.Values.Count > 0) { // only set if both end time and start time are specified. if (details.StartTime != DateTime.MinValue && details.EndTime != DateTime.MinValue) { result.ContinuationPoint = SaveContinuationPoint(context, request); } } // check if no data returned. else { errors[handle.Index] = StatusCodes.GoodNoData; } // return the data. result.HistoryData = new ExtensionObject(data); } catch (Exception e) { errors[handle.Index] = ServiceResult.Create(e, StatusCodes.BadUnexpectedError, "Unexpected error processing request."); } } } /// /// Reads the processed data for an item. /// /// /// /// /// /// /// /// /// protected override void HistoryReadProcessed( ServerSystemContext context, ReadProcessedDetails details, TimestampsToReturn timestampsToReturn, IList nodesToRead, IList results, IList errors, List nodesToProcess, IDictionary cache) { for (var ii = 0; ii < nodesToRead.Count; ii++) { var handle = nodesToProcess[ii]; var nodeToRead = nodesToRead[handle.Index]; var result = results[handle.Index]; try { // validate node. var source = ValidateNode(context, handle, cache); if (source == null) { continue; } HistoryReadRequest request; // load an exising request. if (nodeToRead.ContinuationPoint != null) { request = LoadContinuationPoint(context, nodeToRead.ContinuationPoint); if (request == null) { errors[handle.Index] = StatusCodes.BadContinuationPointInvalid; continue; } } // create a new request. else { // validate aggregate type. if (details.AggregateType.Count <= ii || !Server.AggregateManager.IsSupported(details.AggregateType[ii])) { errors[handle.Index] = StatusCodes.BadAggregateNotSupported; continue; } request = CreateHistoryReadRequest( context, details, handle, nodeToRead, details.AggregateType[ii]); } // process values until the max is reached. var data = new HistoryData(); while (request.NumValuesPerNode == 0 || data.DataValues.Count < request.NumValuesPerNode) { if (request.Values.Count == 0) { break; } var value = request.Values.First.Value; request.Values.RemoveFirst(); data.DataValues.Add(value); } errors[handle.Index] = ServiceResult.Good; // check if a continuation point is requred. if (request.Values.Count > 0) { result.ContinuationPoint = SaveContinuationPoint(context, request); } // check if no data returned. else { errors[handle.Index] = StatusCodes.GoodNoData; } // return the data. result.HistoryData = new ExtensionObject(data); } catch (Exception e) { errors[handle.Index] = ServiceResult.Create(e, StatusCodes.BadUnexpectedError, "Unexpected error processing request."); } } } /// /// Reads the data at the specified time for an item. /// /// /// /// /// /// /// /// /// protected override void HistoryReadAtTime( ServerSystemContext context, ReadAtTimeDetails details, TimestampsToReturn timestampsToReturn, IList nodesToRead, IList results, IList errors, List nodesToProcess, IDictionary cache) { for (var ii = 0; ii < nodesToRead.Count; ii++) { var handle = nodesToProcess[ii]; var nodeToRead = nodesToRead[handle.Index]; var result = results[handle.Index]; try { // validate node. var source = ValidateNode(context, handle, cache); if (source == null) { continue; } HistoryReadRequest request; // load an exising request. if (nodeToRead.ContinuationPoint != null) { request = LoadContinuationPoint(context, nodeToRead.ContinuationPoint); if (request == null) { errors[handle.Index] = StatusCodes.BadContinuationPointInvalid; continue; } } // create a new request. else { request = CreateHistoryReadRequest( context, details, handle, nodeToRead); } // process values until the max is reached. var data = new HistoryData(); while (request.NumValuesPerNode == 0 || data.DataValues.Count < request.NumValuesPerNode) { if (request.Values.Count == 0) { break; } var value = request.Values.First.Value; request.Values.RemoveFirst(); data.DataValues.Add(value); } errors[handle.Index] = ServiceResult.Good; // check if a continuation point is requred. if (request.Values.Count > 0) { result.ContinuationPoint = SaveContinuationPoint(context, request); } // check if no data returned. else { errors[handle.Index] = StatusCodes.GoodNoData; } // return the data. result.HistoryData = new ExtensionObject(data); } catch (Exception e) { errors[handle.Index] = ServiceResult.Create(e, StatusCodes.BadUnexpectedError, "Unexpected error processing request."); } } } /// /// Updates the data history for one or more nodes. /// /// /// /// /// /// /// protected override void HistoryUpdateData( ServerSystemContext context, IList nodesToUpdate, IList results, IList errors, List nodesToProcess, IDictionary cache) { for (var ii = 0; ii < nodesToProcess.Count; ii++) { var handle = nodesToProcess[ii]; var nodeToUpdate = nodesToUpdate[handle.Index]; var result = results[handle.Index]; try { // remove not supported. if (nodeToUpdate.PerformInsertReplace == PerformUpdateType.Remove) { continue; } // validate node. var source = ValidateNode(context, handle, cache); if (source == null) { continue; } // load the archive. if (handle.Node is not ArchiveItemState item) { continue; } item.ReloadFromSource(context); // process each item. for (var jj = 0; jj < nodeToUpdate.UpdateValues.Count; jj++) { StatusCode error = item.UpdateHistory(context, nodeToUpdate.UpdateValues[jj], nodeToUpdate.PerformInsertReplace); result.OperationResults.Add(error); } errors[handle.Index] = ServiceResult.Good; } catch (Exception e) { errors[handle.Index] = ServiceResult.Create(e, StatusCodes.BadUnexpectedError, "Unexpected error processing request."); } } } /// /// Updates the data history for one or more nodes. /// /// /// /// /// /// /// protected override void HistoryUpdateStructureData( ServerSystemContext context, IList nodesToUpdate, IList results, IList errors, List nodesToProcess, IDictionary cache) { for (var ii = 0; ii < nodesToProcess.Count; ii++) { var handle = nodesToProcess[ii]; var nodeToUpdate = nodesToUpdate[handle.Index]; var result = results[handle.Index]; try { // validate node. var source = ValidateNode(context, handle, cache); if (source == null) { continue; } // only support annotations. if (handle.Node.BrowseName != BrowseNames.Annotations) { continue; } // load the archive. var item = Reload(context, handle); if (item == null) { continue; } // process each item. for (var jj = 0; jj < nodeToUpdate.UpdateValues.Count; jj++) { if (ExtensionObject.ToEncodeable(nodeToUpdate.UpdateValues[jj].Value as ExtensionObject) is not Annotation annotation) { result.OperationResults.Add(StatusCodes.BadTypeMismatch); continue; } StatusCode error = item.UpdateAnnotations( context, annotation, nodeToUpdate.UpdateValues[jj], nodeToUpdate.PerformInsertReplace); result.OperationResults.Add(error); } errors[handle.Index] = ServiceResult.Good; } catch (Exception e) { errors[handle.Index] = ServiceResult.Create(e, StatusCodes.BadUnexpectedError, "Unexpected error processing request."); } } } /// /// Deletes the data history for one or more nodes. /// /// /// /// /// /// /// protected override void HistoryDeleteRawModified( ServerSystemContext context, IList nodesToUpdate, IList results, IList errors, List nodesToProcess, IDictionary cache) { for (var ii = 0; ii < nodesToProcess.Count; ii++) { var handle = nodesToProcess[ii]; var nodeToUpdate = nodesToUpdate[handle.Index]; try { // validate node. var source = ValidateNode(context, handle, cache); if (source == null) { continue; } // load the archive. if (handle.Node is not ArchiveItemState item) { continue; } item.ReloadFromSource(context); // delete the history. item.DeleteHistory(context, nodeToUpdate.StartTime, nodeToUpdate.EndTime, nodeToUpdate.IsDeleteModified); errors[handle.Index] = ServiceResult.Good; } catch (Exception e) { errors[handle.Index] = ServiceResult.Create(e, StatusCodes.BadUnexpectedError, "Error deleting data from archive."); } } } /// /// Deletes the data history for one or more nodes. /// /// /// /// /// /// /// protected override void HistoryDeleteAtTime( ServerSystemContext context, IList nodesToUpdate, IList results, IList errors, List nodesToProcess, IDictionary cache) { for (var ii = 0; ii < nodesToProcess.Count; ii++) { var handle = nodesToProcess[ii]; var nodeToUpdate = nodesToUpdate[handle.Index]; var result = results[handle.Index]; try { // validate node. var source = ValidateNode(context, handle, cache); if (source == null) { continue; } // load the archive. if (handle.Node is not ArchiveItemState item) { continue; } item.ReloadFromSource(context); // process each item. for (var jj = 0; jj < nodeToUpdate.ReqTimes.Count; jj++) { StatusCode error = item.DeleteHistory(context, nodeToUpdate.ReqTimes[jj]); result.OperationResults.Add(error); } errors[handle.Index] = ServiceResult.Good; } catch (Exception e) { errors[handle.Index] = ServiceResult.Create(e, StatusCodes.BadUnexpectedError, "Unexpected error processing request."); } } } /// /// Loads the archive item state from the underlying source. /// /// /// private ArchiveItemState Reload(ServerSystemContext context, NodeHandle handle) { var item = handle.Node as ArchiveItemState; if (item == null && handle.Node is BaseInstanceState property) { item = property.Parent as ArchiveItemState; } item?.ReloadFromSource(context); return item; } /// /// Creates a new history request. /// /// /// /// /// /// private HistoryReadRequest CreateHistoryReadRequest( ServerSystemContext context, ReadRawModifiedDetails details, NodeHandle handle, HistoryReadValueId nodeToRead) { var sizeLimited = details.StartTime == DateTime.MinValue || details.EndTime == DateTime.MinValue; var applyIndexRangeOrEncoding = nodeToRead.ParsedIndexRange != NumericRange.Empty || !QualifiedName.IsNull(nodeToRead.DataEncoding); var returnBounds = !details.IsReadModified && details.ReturnBounds; var timeFlowsBackward = (details.StartTime == DateTime.MinValue) || (details.EndTime != DateTime.MinValue && details.EndTime < details.StartTime); // find the archive item. var item = Reload(context, handle); if (item == null) { throw new ServiceResultException(StatusCodes.BadNotSupported); } var values = new LinkedList(); LinkedList modificationInfos = null; if (details.IsReadModified) { modificationInfos = new LinkedList(); } // read history. var view = item.ReadHistory(details.StartTime, details.EndTime, details.IsReadModified, handle.Node.BrowseName); var startBound = -1; var endBound = -1; var ii = timeFlowsBackward ? view.Count - 1 : 0; while (ii >= 0 && ii < view.Count) { try { var timestamp = (DateTime)view[ii].Row[0]; // check if looking for start of data. if (values.Count == 0) { if (timeFlowsBackward) { if ((details.StartTime != DateTime.MinValue && timestamp >= details.StartTime) || (details.StartTime == DateTime.MinValue && timestamp >= details.EndTime)) { startBound = ii; if (timestamp > details.StartTime) { continue; } } } else { if (timestamp <= details.StartTime) { startBound = ii; if (timestamp < details.StartTime) { continue; } } } } // check if absolute max values specified. if (sizeLimited && details.NumValuesPerNode > 0 && details.NumValuesPerNode < values.Count) { break; } // check for end bound. if (details.EndTime != DateTime.MinValue && timestamp >= details.EndTime) { if (timeFlowsBackward) { if (timestamp <= details.EndTime) { endBound = ii; break; } } else { if (timestamp >= details.EndTime) { endBound = ii; break; } } } // check if the start bound needs to be returned. if (returnBounds && values.Count == 0 && startBound != ii && details.StartTime != DateTime.MinValue) { // add start bound. if (startBound == -1) { values.AddLast(new DataValue(Variant.Null, StatusCodes.BadBoundNotFound, details.StartTime, details.StartTime)); } else { values.AddLast(RowToDataValue(context, nodeToRead, view[startBound], applyIndexRangeOrEncoding)); } // check if absolute max values specified. if (sizeLimited && details.NumValuesPerNode > 0 && details.NumValuesPerNode < values.Count) { break; } } // add value. values.AddLast(RowToDataValue(context, nodeToRead, view[ii], applyIndexRangeOrEncoding)); modificationInfos?.AddLast((ModificationInfo)view[ii].Row[6]); } finally { if (timeFlowsBackward) { ii--; } else { ii++; } } } // add late bound. while (returnBounds && details.EndTime != DateTime.MinValue) { // add start bound. if (values.Count == 0) { if (startBound == -1) { values.AddLast(new DataValue(Variant.Null, StatusCodes.BadBoundNotFound, details.StartTime, details.StartTime)); } else { values.AddLast(RowToDataValue(context, nodeToRead, view[startBound], applyIndexRangeOrEncoding)); } } // check if absolute max values specified. if (sizeLimited && details.NumValuesPerNode > 0 && details.NumValuesPerNode < values.Count) { break; } // add end bound. if (endBound == -1) { values.AddLast(new DataValue(Variant.Null, StatusCodes.BadBoundNotFound, details.EndTime, details.EndTime)); } else { values.AddLast(RowToDataValue(context, nodeToRead, view[endBound], applyIndexRangeOrEncoding)); } break; } return new HistoryReadRequest { Values = values, ModificationInfos = modificationInfos, NumValuesPerNode = details.NumValuesPerNode, Filter = null }; } /// /// Creates a new history request. /// /// /// /// /// /// /// private HistoryReadRequest CreateHistoryReadRequest( ServerSystemContext context, ReadProcessedDetails details, NodeHandle handle, HistoryReadValueId nodeToRead, NodeId aggregateId) { var applyIndexRangeOrEncoding = nodeToRead.ParsedIndexRange != NumericRange.Empty || !QualifiedName.IsNull(nodeToRead.DataEncoding); var timeFlowsBackward = details.EndTime < details.StartTime; if (handle.Node is not ArchiveItemState item) { throw new ServiceResultException(StatusCodes.BadNotSupported); } item.ReloadFromSource(context); var values = new LinkedList(); // read history. var view = item.ReadHistory(details.StartTime, details.EndTime, false); var ii = timeFlowsBackward ? view.Count - 1 : 0; // choose the aggregate configuration. var configuration = (AggregateConfiguration)details.AggregateConfiguration.MemberwiseClone(); ReviseAggregateConfiguration(context, item, configuration); // create the aggregate calculator. var calculator = Server.AggregateManager.CreateCalculator( aggregateId, details.StartTime, details.EndTime, details.ProcessingInterval, item.ArchiveItem.Stepped, configuration); while (ii >= 0 && ii < view.Count) { try { var value = (DataValue)view[ii].Row[2]; calculator.QueueRawValue(value); // queue any processed values. QueueProcessedValues( context, calculator, nodeToRead.ParsedIndexRange, nodeToRead.DataEncoding, applyIndexRangeOrEncoding, false, values); } finally { if (timeFlowsBackward) { ii--; } else { ii++; } } } // queue any processed values beyond the end of the data. QueueProcessedValues( context, calculator, nodeToRead.ParsedIndexRange, nodeToRead.DataEncoding, applyIndexRangeOrEncoding, true, values); return new HistoryReadRequest { Values = values, NumValuesPerNode = 0, Filter = null }; } /// /// Creates a new history request. /// /// /// /// /// /// private static HistoryReadRequest CreateHistoryReadRequest( ServerSystemContext context, ReadAtTimeDetails details, NodeHandle handle, HistoryReadValueId nodeToRead) { System.Diagnostics.Contracts.Contract.Assume(nodeToRead is not null); if (handle.Node is not ArchiveItemState item) { throw new ServiceResultException(StatusCodes.BadNotSupported); } item.ReloadFromSource(context); // find the start and end times. var startTime = DateTime.MaxValue; var endTime = DateTime.MinValue; for (var ii = 0; ii < details.ReqTimes.Count; ii++) { if (startTime > details.ReqTimes[ii]) { startTime = details.ReqTimes[ii]; } if (endTime < details.ReqTimes[ii]) { endTime = details.ReqTimes[ii]; } } var view = item.ReadHistory(startTime, endTime, false); var values = new LinkedList(); for (var ii = 0; ii < details.ReqTimes.Count; ii++) { // find the value at the time. var index = item.FindValueAtOrBefore(view, details.ReqTimes[ii], !details.UseSimpleBounds, out var dataBeforeIgnored); if (index < 0) { values.AddLast(new DataValue(StatusCodes.BadNoData, details.ReqTimes[ii])); continue; } // nothing more to do if a raw value exists. if ((DateTime)view[index].Row[0] == details.ReqTimes[ii]) { values.AddLast((DataValue)view[index].Row[2]); continue; } var before = (DataValue)view[index].Row[2]; DataValue value; // find the value after the time. var afterIndex = item.FindValueAfter(view, index, !details.UseSimpleBounds, out var dataAfterIgnored); if (afterIndex < 0) { // use stepped interpolation if no end bound exists. value = AggregateCalculator.SteppedInterpolate(details.ReqTimes[ii], before); if (StatusCode.IsNotBad(value.StatusCode) && dataBeforeIgnored) { value.StatusCode = value.StatusCode.SetCodeBits(StatusCodes.UncertainDataSubNormal); } values.AddLast(value); continue; } // use stepped or slopped interpolation depending on the value. if (item.ArchiveItem.Stepped) { value = AggregateCalculator.SteppedInterpolate(details.ReqTimes[ii], before); if (StatusCode.IsNotBad(value.StatusCode) && dataBeforeIgnored) { value.StatusCode = value.StatusCode.SetCodeBits(StatusCodes.UncertainDataSubNormal); } } else { value = AggregateCalculator.SlopedInterpolate(details.ReqTimes[ii], before, (DataValue)view[afterIndex].Row[2]); if (StatusCode.IsNotBad(value.StatusCode) && (dataBeforeIgnored || dataAfterIgnored)) { value.StatusCode = value.StatusCode.SetCodeBits(StatusCodes.UncertainDataSubNormal); } } values.AddLast(value); } return new HistoryReadRequest { Values = values, NumValuesPerNode = 0, Filter = null }; } /// /// Extracts and queues any processed values. /// /// /// /// /// /// /// /// private void QueueProcessedValues( ServerSystemContext context, IAggregateCalculator calculator, NumericRange indexRange, QualifiedName dataEncoding, bool applyIndexRangeOrEncoding, bool returnPartial, LinkedList values) { var proccessedValue = calculator.GetProcessedValue(returnPartial); while (proccessedValue != null) { // apply any index range or encoding. if (applyIndexRangeOrEncoding) { var rawValue = proccessedValue.Value; var result = BaseVariableState.ApplyIndexRangeAndDataEncoding(context, indexRange, dataEncoding, ref rawValue); if (ServiceResult.IsBad(result)) { proccessedValue.Value = rawValue; } else { proccessedValue.Value = null; proccessedValue.StatusCode = result.StatusCode; } } // queue the result. values.AddLast(proccessedValue); proccessedValue = calculator.GetProcessedValue(returnPartial); } } /// /// Creates a new history request. /// /// /// /// /// private DataValue RowToDataValue( ServerSystemContext context, HistoryReadValueId nodeToRead, DataRowView row, bool applyIndexRangeOrEncoding) { var value = (DataValue)row[2]; // apply any index range or encoding. if (applyIndexRangeOrEncoding) { var rawValue = value.Value; var result = BaseVariableState.ApplyIndexRangeAndDataEncoding(context, nodeToRead.ParsedIndexRange, nodeToRead.DataEncoding, ref rawValue); if (ServiceResult.IsBad(result)) { value.Value = rawValue; } else { value.Value = null; value.StatusCode = result.StatusCode; } } return value; } /// /// Stores a read history request. /// private sealed class HistoryReadRequest { public byte[] ContinuationPoint { get; set; } public LinkedList Values { get; set; } public LinkedList ModificationInfos { get; set; } public uint NumValuesPerNode { get; set; } public AggregateFilter Filter { get; set; } } /// /// Releases the history continuation point. /// /// /// /// /// /// protected override void HistoryReleaseContinuationPoints( ServerSystemContext context, IList nodesToRead, IList errors, List nodesToProcess, IDictionary cache) { for (var ii = 0; ii < nodesToProcess.Count; ii++) { var handle = nodesToProcess[ii]; var nodeToRead = nodesToRead[handle.Index]; // find the continuation point. var request = LoadContinuationPoint(context, nodeToRead.ContinuationPoint); if (request == null) { errors[handle.Index] = StatusCodes.BadContinuationPointInvalid; continue; } // all done. errors[handle.Index] = StatusCodes.Good; } } /// /// Loads a history continuation point. /// /// /// private static HistoryReadRequest LoadContinuationPoint( ServerSystemContext context, byte[] continuationPoint) { var session = context.OperationContext.Session; if (session == null) { return null; } if (session.RestoreHistoryContinuationPoint(continuationPoint) is not HistoryReadRequest request) { return null; } return request; } /// /// Saves a history continuation point. /// /// /// private static byte[] SaveContinuationPoint( ServerSystemContext context, HistoryReadRequest request) { var session = context.OperationContext.Session; if (session == null) { return null; } var id = Guid.NewGuid(); session.SaveHistoryContinuationPoint(id, request); request.ContinuationPoint = id.ToByteArray(); return request.ContinuationPoint; } /// /// Runs the simulation. /// /// private void DoSimulation(object state) { try { lock (Lock) { foreach (var item in _monitoredItems.Values) { if (item.ArchiveItem.LastLoadTime.AddDays(1) < _timeService.UtcNow) { item.LoadConfiguration(SystemContext); } foreach (var value in item.NewSamples(SystemContext)) { item.WrappedValue = value.WrappedValue; item.Timestamp = value.SourceTimestamp; item.StatusCode = value.StatusCode; item.ClearChangeMasks(SystemContext, true); } } } } catch (Exception e) { Utils.Trace("Unexpected error during simulation: {0}", e.Message); } } private readonly UnderlyingSystem _system; private readonly HistoricalAccessServerConfiguration _configuration; private readonly TimeService _timeService; private Timer _simulationTimer; private Dictionary _monitoredItems; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/HistoricalAccessServer.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace HistoricalAccess { using Opc.Ua; using Opc.Ua.Server; using Opc.Ua.Test; /// public class HistoricalAccessServer : INodeManagerFactory { /// public StringCollection NamespacesUris { get { return [ Namespaces.HistoricalAccess ]; } } /// public HistoricalAccessServer(TimeService timeservice) { _timeservice = timeservice; } /// public INodeManager Create(IServerInternal server, ApplicationConfiguration configuration) { return new HistoricalAccessServerNodeManager(server, configuration, _timeservice); } private readonly TimeService _timeservice; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/HistoricalAccessServerConfiguration.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace HistoricalAccess { using System.Runtime.Serialization; /// /// Stores the configuration the data access node manager. /// [DataContract(Namespace = Namespaces.HistoricalAccess)] public class HistoricalAccessServerConfiguration { /// /// The default constructor. /// public HistoricalAccessServerConfiguration() { Initialize(); } /// /// Initializes the object during deserialization. /// /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { } /// /// The root of the archive. /// [DataMember(Order = 1)] public string ArchiveRoot { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/Namespaces.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace HistoricalAccess { /// /// Defines constants for namespaces used by the application. /// public static class Namespaces { /// /// The namespace for the nodes provided by the server. /// public const string HistoricalAccess = "http://opcfoundation.org/HistoricalAccess"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/NodeTypes.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace HistoricalAccess { using Opc.Ua; using System.Text; /// /// Defines the types of nodes exposed by the HistoricalAccessServer NodeManager. /// public static class NodeTypes { /// /// A node representing a Folder. /// public const int Folder = 0; /// /// A node representing an Item. /// public const int Item = 1; /// /// Constructs the node identifier for a component. /// /// The component. /// Index of the namespace. /// The node identifier for a component. public static NodeId ConstructIdForComponent(NodeState component, ushort namespaceIndex) { if (component == null) { return null; } // components must be instances with a parent. if (component is not BaseInstanceState instance || instance.Parent == null) { return component.NodeId; } // parent must have a string identifier. if (instance.Parent.NodeId.Identifier is not string parentId) { return null; } var buffer = new StringBuilder(); buffer.Append(parentId); // check if the parent is another component. var index = parentId.IndexOf('?'); if (index < 0) { buffer.Append('?'); } else { buffer.Append('/'); } buffer.Append(component.SymbolicName); // return the node identifier. return new NodeId(buffer.ToString(), namespaceIndex); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalAccess/UnderlyingSystem.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace HistoricalAccess { using Opc.Ua; using Opc.Ua.Server; using Opc.Ua.Test; using System.IO; using System.Text; /// /// Provides access to the system which stores the data. /// public class UnderlyingSystem { /// /// Constructs a new system. /// /// /// /// public UnderlyingSystem(HistoricalAccessServerConfiguration configuration, ushort namespaceIndex, TimeService timeService) { _configuration = configuration; _namespaceIndex = namespaceIndex; _timeService = timeService; } /// /// Returns a folder object for the specified node. /// /// public ArchiveFolderState GetFolderState(string rootId) { var path = new StringBuilder() .Append(_configuration.ArchiveRoot) .Append('/') .Append(rootId); var folder = new ArchiveFolder(rootId, new DirectoryInfo(path.ToString())); return new ArchiveFolderState(folder, _namespaceIndex); } /// /// Returns a item object for the specified node. /// /// /// public ArchiveItemState GetItemState(ISystemContext context, ParsedNodeId parsedNodeId) { if (parsedNodeId.RootType != NodeTypes.Item) { return null; } var path = new StringBuilder() .Append(_configuration.ArchiveRoot) .Append('/') .Append(parsedNodeId.RootId); var item = new ArchiveItem(parsedNodeId.RootId, new FileInfo(path.ToString())); return new ArchiveItemState(context, item, _namespaceIndex, _timeService); } private readonly ushort _namespaceIndex; private readonly TimeService _timeService; private readonly HistoricalAccessServerConfiguration _configuration; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalEvents/HistoricalEventsNodeManager.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace HistoricalEvents { using Opc.Ua; using Opc.Ua.Server; using Opc.Ua.Test; using System; using System.Collections.Generic; using System.Data; using System.Reflection; using System.Threading; /// /// A node manager for a server that exposes several variables. /// public class HistoricalEventsNodeManager : CustomNodeManager2 { /// /// Initializes the node manager. /// /// /// /// public HistoricalEventsNodeManager(IServerInternal server, ApplicationConfiguration configuration, TimeService timeService) : base(server, configuration) { SystemContext.NodeIdFactory = this; // set one namespace for the type model and one names for dynamically created nodes. var namespaceUrls = new string[1]; namespaceUrls[0] = Namespaces.HistoricalEvents; SetNamespaces(namespaceUrls); // get the configuration for the node manager. // use suitable defaults if no configuration exists. _configuration = configuration.ParseExtension() ?? new HistoricalEventsServerConfiguration(); // initilize the report generator. _generator = new ReportGenerator(timeService); _generator.Initialize(); } /// /// An overrideable version of the Dispose. /// /// protected override void Dispose(bool disposing) { if (disposing && _simulationTimer != null) { Utils.SilentDispose(_simulationTimer); _simulationTimer = null; } base.Dispose(disposing); } /// /// Creates the NodeId for the specified node. /// /// /// public override NodeId New(ISystemContext context, NodeState node) { return node.NodeId; } /// /// Loads a node set from a file or resource and addes them to the set of predefined nodes. /// /// protected override NodeStateCollection LoadPredefinedNodes(ISystemContext context) { var type = GetType().GetTypeInfo(); var predefinedNodes = new NodeStateCollection(); predefinedNodes.LoadFromBinaryResource(context, $"{type.Assembly.GetName().Name}.Generated.{type.Namespace}.Design.{type.Namespace}.PredefinedNodes.uanodes", type.Assembly, true); return predefinedNodes; } /// /// Does any initialization required before the address space can be used. /// /// /// /// The externalReferences is an out parameter that allows the node manager to link to nodes /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and /// should have a reference to the root folder node(s) exposed by this node manager. /// public override void CreateAddressSpace(IDictionary> externalReferences) { lock (Lock) { LoadPredefinedNodes(SystemContext, externalReferences); var platforms = (BaseObjectState)FindPredefinedNode(new NodeId(Objects.Plaforms, NamespaceIndex), typeof(BaseObjectState)); platforms.EventNotifier = EventNotifiers.SubscribeToEvents | EventNotifiers.HistoryRead | EventNotifiers.HistoryWrite; base.AddRootNotifier(platforms); foreach (var areaName in _generator.GetAreas()) { var area = CreateArea(SystemContext, platforms, areaName); foreach (var well in _generator.GetWells(areaName)) { CreateWell(SystemContext, area, well.Id, well.Name); } } // start the simulation. _simulationTimer = new Timer(DoSimulation, null, 10000, 10000); } } /// /// Creates a new area. /// /// /// /// private FolderState CreateArea(SystemContext context, BaseObjectState platforms, string areaName) { System.Diagnostics.Contracts.Contract.Assume(context != null); var area = new FolderState(null) { NodeId = new NodeId(areaName, NamespaceIndex), BrowseName = new QualifiedName(areaName, NamespaceIndex) }; area.DisplayName = area.BrowseName.Name; area.EventNotifier = EventNotifiers.SubscribeToEvents | EventNotifiers.HistoryRead | EventNotifiers.HistoryWrite; area.TypeDefinitionId = Opc.Ua.ObjectTypeIds.FolderType; platforms.AddNotifier(SystemContext, ReferenceTypeIds.HasNotifier, false, area); area.AddNotifier(SystemContext, ReferenceTypeIds.HasNotifier, true, platforms); AddPredefinedNode(SystemContext, area); return area; } /// /// Creates a new well. /// /// /// /// /// private void CreateWell(SystemContext context, FolderState area, string wellId, string wellName) { System.Diagnostics.Contracts.Contract.Assume(context != null); #pragma warning disable CA2000 // Dispose objects before losing scope var well = new WellState(null) { NodeId = new NodeId(wellId, NamespaceIndex), BrowseName = new QualifiedName(wellName, NamespaceIndex), DisplayName = wellName, EventNotifier = EventNotifiers.SubscribeToEvents | EventNotifiers.HistoryRead | EventNotifiers.HistoryWrite, TypeDefinitionId = new NodeId(ObjectTypes.WellType, NamespaceIndex) }; #pragma warning restore CA2000 // Dispose objects before losing scope area.AddNotifier(SystemContext, ReferenceTypeIds.HasNotifier, false, well); well.AddNotifier(SystemContext, ReferenceTypeIds.HasNotifier, true, area); AddPredefinedNode(SystemContext, well); } /// /// Frees any resources allocated for the address space. /// public override void DeleteAddressSpace() { lock (Lock) { base.DeleteAddressSpace(); } } /// /// Returns a unique handle for the node. /// /// /// /// protected override NodeHandle GetManagerHandle(ServerSystemContext context, NodeId nodeId, IDictionary cache) { lock (Lock) { // quickly exclude nodes that are not in the namespace. if (!IsNodeIdInNamespace(nodeId)) { return null; } // check for predefined nodes. if (PredefinedNodes != null && PredefinedNodes.TryGetValue(nodeId, out var node)) { return new NodeHandle { NodeId = nodeId, Validated = true, Node = node }; } return null; } } /// /// Verifies that the specified node exists. /// /// /// /// protected override NodeState ValidateNode( ServerSystemContext context, NodeHandle handle, IDictionary cache) { // not valid if no root. if (handle == null) { return null; } // check if previously validated. if (handle.Validated) { return handle.Node; } // TBD return null; } /// /// Reads history events. /// /// /// /// /// /// /// /// /// protected override void HistoryReadEvents( ServerSystemContext context, ReadEventDetails details, TimestampsToReturn timestampsToReturn, IList nodesToRead, IList results, IList errors, List nodesToProcess, IDictionary cache) { for (var ii = 0; ii < nodesToProcess.Count; ii++) { var handle = nodesToProcess[ii]; var nodeToRead = nodesToRead[handle.Index]; var result = results[handle.Index]; HistoryReadRequest request; // load an exising request. if (nodeToRead.ContinuationPoint != null) { request = LoadContinuationPoint(context, nodeToRead.ContinuationPoint); if (request == null) { errors[handle.Index] = StatusCodes.BadContinuationPointInvalid; continue; } } // create a new request. else { request = CreateHistoryReadRequest( context, details, handle, nodeToRead); } // process events until the max is reached. var events = new HistoryEvent(); while (request.NumValuesPerNode == 0 || events.Events.Count < request.NumValuesPerNode) { if (request.Events.Count == 0) { break; } BaseEventState e; if (request.TimeFlowsBackward) { e = request.Events.Last.Value; request.Events.RemoveLast(); } else { e = request.Events.First.Value; request.Events.RemoveFirst(); } events.Events.Add(GetEventFields(request, e)); } errors[handle.Index] = ServiceResult.Good; // check if a continuation point is requred. if (request.Events.Count > 0) { // only set if both end time and start time are specified. if (details.StartTime != DateTime.MinValue && details.EndTime != DateTime.MinValue) { result.ContinuationPoint = SaveContinuationPoint(context, request); } } // check if no data returned. else { errors[handle.Index] = StatusCodes.GoodNoData; } // return the data. result.HistoryData = new ExtensionObject(events); } } /// /// Updates or inserts events. /// /// /// /// /// /// /// protected override void HistoryUpdateEvents( ServerSystemContext context, IList nodesToUpdate, IList results, IList errors, List nodesToProcess, IDictionary cache) { for (var ii = 0; ii < nodesToProcess.Count; ii++) { var handle = nodesToProcess[ii]; var nodeToUpdate = nodesToUpdate[handle.Index]; // validate the event filter. var filterContext = new FilterContext(context.NamespaceUris, context.TypeTable, context); var filterResult = nodeToUpdate.Filter.Validate(filterContext); if (ServiceResult.IsBad(filterResult.Status)) { errors[handle.Index] = filterResult.Status; continue; } // all done. errors[handle.Index] = StatusCodes.BadNotImplemented; } } /// /// Deletes history events. /// /// /// /// /// /// /// protected override void HistoryDeleteEvents( ServerSystemContext context, IList nodesToUpdate, IList results, IList errors, List nodesToProcess, IDictionary cache) { for (var ii = 0; ii < nodesToProcess.Count; ii++) { var handle = nodesToProcess[ii]; var nodeToUpdate = nodesToUpdate[handle.Index]; var result = results[handle.Index]; // delete events. var failed = false; for (var jj = 0; jj < nodeToUpdate.EventIds.Count; jj++) { try { var eventId = new Guid(nodeToUpdate.EventIds[jj]).ToString(); if (!_generator.DeleteEvent(eventId)) { result.OperationResults.Add(StatusCodes.BadEventIdUnknown); failed = true; continue; } result.OperationResults.Add(StatusCodes.Good); } catch { result.OperationResults.Add(StatusCodes.BadEventIdUnknown); failed = true; } } // check if diagnostics are required. if (failed) { if ((context.DiagnosticsMask & DiagnosticsMasks.OperationAll) != 0) { for (var jj = 0; jj < nodeToUpdate.EventIds.Count; jj++) { if (StatusCode.IsBad(result.OperationResults[jj])) { result.DiagnosticInfos.Add(ServerUtils.CreateDiagnosticInfo(Server, context.OperationContext, result.OperationResults[jj])); } } } } // clear operation results if all good. else { result.OperationResults.Clear(); } // all done. errors[handle.Index] = ServiceResult.Good; } } /// /// Fetches the requested event fields from the event. /// /// /// private HistoryEventFieldList GetEventFields(HistoryReadRequest request, BaseEventState instance) { // fetch the event fields. var fields = new HistoryEventFieldList(); foreach (var clause in request.Filter.SelectClauses) { // get the value of the attribute (apply localization). var value = instance.GetAttributeValue( request.FilterContext, clause.TypeDefinitionId, clause.BrowsePath, clause.AttributeId, clause.ParsedIndexRange); // add the value to the list of event fields. if (value != null) { // translate any localized text. var text = value as LocalizedText; if (text != null) { value = Server.ResourceManager.Translate(request.FilterContext.PreferredLocales, text); } // add value. fields.EventFields.Add(new Variant(value)); } // add a dummy entry for missing values. else { fields.EventFields.Add(Variant.Null); } } return fields; } /// /// Creates a new history request. /// /// /// /// /// private HistoryReadRequest CreateHistoryReadRequest( ServerSystemContext context, ReadEventDetails details, NodeHandle handle, HistoryReadValueId nodeToRead) { System.Diagnostics.Contracts.Contract.Assume(nodeToRead != null); var filterContext = new FilterContext(context.NamespaceUris, context.TypeTable, context.PreferredLocales); var events = new LinkedList(); for (var ii = ReportType.FluidLevelTest; ii <= ReportType.InjectionTest; ii++) { DataView view; if (handle.Node is WellState) { view = _generator.ReadHistoryForWellId( ii, (string)handle.Node.NodeId.Identifier, details.StartTime, details.EndTime); } else { view = _generator.ReadHistoryForArea( ii, handle.Node.NodeId.Identifier as string, details.StartTime, details.EndTime); } var pos = events.First; var sizeLimited = details.StartTime == DateTime.MinValue || details.EndTime == DateTime.MinValue; foreach (DataRowView row in view) { // check if reached max results. if (sizeLimited && events.Count >= details.NumValuesPerNode) { break; } var e = _generator.GetReport(context, NamespaceIndex, ii, row.Row); if (details.Filter.WhereClause?.Elements.Count > 0 && !details.Filter.WhereClause.Evaluate(filterContext, e)) { continue; } var inserted = false; for (var jj = pos; jj != null; jj = jj.Next) { if (jj.Value.Time.Value > e.Time.Value) { events.AddBefore(jj, e); pos = jj; inserted = true; break; } } if (!inserted) { events.AddLast(e); pos = null; } } } return new HistoryReadRequest { Events = events, TimeFlowsBackward = details.StartTime == DateTime.MinValue || (details.EndTime != DateTime.MinValue && details.EndTime < details.StartTime), NumValuesPerNode = details.NumValuesPerNode, Filter = details.Filter, FilterContext = filterContext }; } /// /// Stores a read history request. /// private sealed class HistoryReadRequest { public byte[] ContinuationPoint { get; set; } public LinkedList Events { get; set; } public bool TimeFlowsBackward { get; set; } public uint NumValuesPerNode { get; set; } public EventFilter Filter { get; set; } public FilterContext FilterContext { get; set; } } /// /// Releases the history continuation point. /// /// /// /// /// /// protected override void HistoryReleaseContinuationPoints( ServerSystemContext context, IList nodesToRead, IList errors, List nodesToProcess, IDictionary cache) { for (var ii = 0; ii < nodesToProcess.Count; ii++) { var handle = nodesToProcess[ii]; var nodeToRead = nodesToRead[handle.Index]; // find the continuation point. var request = LoadContinuationPoint(context, nodeToRead.ContinuationPoint); if (request == null) { errors[handle.Index] = StatusCodes.BadContinuationPointInvalid; continue; } // all done. errors[handle.Index] = StatusCodes.Good; } } /// /// Loads a history continuation point. /// /// /// private static HistoryReadRequest LoadContinuationPoint( ServerSystemContext context, byte[] continuationPoint) { var session = context.OperationContext.Session; if (session == null) { return null; } if (session.RestoreHistoryContinuationPoint(continuationPoint) is not HistoryReadRequest request) { return null; } return request; } /// /// Saves a history continuation point. /// /// /// private static byte[] SaveContinuationPoint( ServerSystemContext context, HistoryReadRequest request) { var session = context.OperationContext.Session; if (session == null) { return null; } var id = Guid.NewGuid(); session.SaveHistoryContinuationPoint(id, request); request.ContinuationPoint = id.ToByteArray(); return request.ContinuationPoint; } /// /// Does the simulation. /// /// The state. private void DoSimulation(object state) { try { { var row = _generator.GenerateFluidLevelTestReport(); var well = (BaseObjectState)FindPredefinedNode(new NodeId((string)row[BrowseNames.UidWell], NamespaceIndex), typeof(BaseObjectState)); if (well?.AreEventsMonitored == true) { var e = _generator.GetFluidLevelTestReport(SystemContext, NamespaceIndex, row); well.ReportEvent(SystemContext, e); } } { var row = _generator.GenerateInjectionTestReport(); var well = (BaseObjectState)FindPredefinedNode(new NodeId((string)row[BrowseNames.UidWell], NamespaceIndex), typeof(BaseObjectState)); if (well?.AreEventsMonitored == true) { var e = _generator.GetInjectionTestReport(SystemContext, NamespaceIndex, row); well.ReportEvent(SystemContext, e); } } } catch (NullReferenceException) { // Stop simulation because the subscription is closed. This should be fixed in the server library. _simulationTimer.Change(Timeout.Infinite, Timeout.Infinite); } catch (Exception e) { Utils.Trace(e, "Unexpected error during simulation."); } } #pragma warning disable IDE0052 // Remove unread private members private readonly HistoricalEventsServerConfiguration _configuration; #pragma warning restore IDE0052 // Remove unread private members private Timer _simulationTimer; private readonly ReportGenerator _generator; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalEvents/HistoricalEventsServer.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace HistoricalEvents { using Opc.Ua; using Opc.Ua.Server; using Opc.Ua.Test; /// public class HistoricalEventsServer : INodeManagerFactory { /// public StringCollection NamespacesUris { get { return [ Namespaces.HistoricalEvents ]; } } /// public HistoricalEventsServer(TimeService timeservice) { _timeservice = timeservice; } /// public INodeManager Create(IServerInternal server, ApplicationConfiguration configuration) { return new HistoricalEventsNodeManager(server, configuration, _timeservice); } private readonly TimeService _timeservice; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalEvents/HistoricalEventsServerConfiguration.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace HistoricalEvents { using System.Runtime.Serialization; /// /// Stores the configuration the data access node manager. /// [DataContract(Namespace = Namespaces.HistoricalEvents)] public class HistoricalEventsServerConfiguration { /// /// The default constructor. /// public HistoricalEventsServerConfiguration() { Initialize(); } /// /// Initializes the object during deserialization. /// /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/HistoricalEvents/ReportGenerator.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace HistoricalEvents { using Opc.Ua; using Opc.Ua.Test; using System; using System.Collections.Generic; using System.Data; using System.Text; public class ReportGenerator { public ReportGenerator(TimeService timeService) { _timeService = timeService; } public void Initialize() { _dataset = new DataSet(); _dataset.Tables.Add("FluidLevelTests"); _dataset.Tables[0].Columns.Add(Opc.Ua.BrowseNames.EventId, typeof(string)); _dataset.Tables[0].Columns.Add(Opc.Ua.BrowseNames.Time, typeof(DateTime)); _dataset.Tables[0].Columns.Add(BrowseNames.NameWell, typeof(string)); _dataset.Tables[0].Columns.Add(BrowseNames.UidWell, typeof(string)); _dataset.Tables[0].Columns.Add(BrowseNames.TestDate, typeof(DateTime)); _dataset.Tables[0].Columns.Add(BrowseNames.TestReason, typeof(string)); _dataset.Tables[0].Columns.Add(BrowseNames.FluidLevel, typeof(double)); _dataset.Tables[0].Columns.Add(Opc.Ua.BrowseNames.EngineeringUnits, typeof(string)); _dataset.Tables[0].Columns.Add(BrowseNames.TestedBy, typeof(string)); _dataset.Tables.Add("InjectionTests"); _dataset.Tables[1].Columns.Add(Opc.Ua.BrowseNames.EventId, typeof(string)); _dataset.Tables[1].Columns.Add(Opc.Ua.BrowseNames.Time, typeof(DateTime)); _dataset.Tables[1].Columns.Add(BrowseNames.NameWell, typeof(string)); _dataset.Tables[1].Columns.Add(BrowseNames.UidWell, typeof(string)); _dataset.Tables[1].Columns.Add(BrowseNames.TestDate, typeof(DateTime)); _dataset.Tables[1].Columns.Add(BrowseNames.TestReason, typeof(string)); _dataset.Tables[1].Columns.Add(BrowseNames.TestDuration, typeof(double)); _dataset.Tables[1].Columns.Add(Opc.Ua.BrowseNames.EngineeringUnits, typeof(string)); _dataset.Tables[1].Columns.Add(BrowseNames.InjectedFluid, typeof(string)); _random = new Random(); // look up the local timezone. var timeZone = TimeZoneInfo.Local; _timeZone = new TimeZoneDataType { Offset = (short)timeZone.GetUtcOffset(_timeService.Now).TotalMinutes, DaylightSavingInOffset = timeZone.IsDaylightSavingTime(_timeService.Now) }; } private static readonly string[] kWellNames = [ "Area51/Jupiter", "Area51/Titan", "Area99/Saturn", "Area99/Mars" ]; private static readonly string[] kWellUIDs = [ "Well_24412", "Well_48306", "Well_86234", "Well_91423" ]; private static readonly string[] kTestReasons = [ "initial", "periodic", "revision", "unknown", "other" ]; private static readonly string[] kTesters = [ "Anne", "Bob", "Charley", "Dawn" ]; private static readonly string[] kUnitLengths = [ "m", "yd" ]; private static readonly string[] kUnitTimes = [ "s", "min", "h" ]; private static readonly string[] kInjectionFluids = [ "oil", "gas", "non HC gas", "CO2", "water", "brine", "fresh water", "oil-gas", "oil-water", "gas-water", "condensate", "steam", "air", "dry", "unknown", "other" ]; private int GetRandom(int min, int max) { return (int)Math.Truncate((_random.NextDouble() * (max - min + 1)) + min); } private string GetRandom(string[] values) { return values[GetRandom(0, values.Length - 1)]; } public string[] GetAreas() { var area = new List(); for (var ii = 0; ii < kWellNames.Length; ii++) { var index = kWellNames[ii].LastIndexOf('/'); if (index >= 0) { var areaName = kWellNames[ii][..index]; if (!area.Contains(areaName)) { area.Add(areaName); } } } return [.. area]; } public WellInfo[] GetWells(string areaName) { var wells = new List(); for (var ii = 0; ii < kWellUIDs.Length; ii++) { var well = new WellInfo { Id = kWellUIDs[ii], Name = kWellUIDs[ii] }; if (kWellNames.Length > ii) { var index = kWellNames[ii].LastIndexOf('/'); if (index >= 0 && kWellNames[ii][..index] == areaName) { well.Name = kWellNames[ii][(index + 1)..]; wells.Add(well); } } } return [.. wells]; } public class WellInfo { public string Id { get; set; } public string Name { get; set; } } public DataRow GenerateFluidLevelTestReport() { lock (_dataset) { var row = _dataset.Tables[0].NewRow(); row[0] = Guid.NewGuid().ToString(); row[1] = _timeService.UtcNow; var index = GetRandom(0, kWellUIDs.Length - 1); row[2] = kWellNames[index]; row[3] = kWellUIDs[index]; row[4] = _timeService.UtcNow.AddHours(-GetRandom(0, 10)); row[5] = GetRandom(kTestReasons); row[6] = GetRandom(0, 1000); row[7] = GetRandom(kUnitLengths); row[8] = GetRandom(kTesters); _dataset.Tables[0].Rows.Add(row); _dataset.AcceptChanges(); return row; } } /// /// Deletes the event with the specified event id. /// /// public bool DeleteEvent(string eventId) { var filter = new StringBuilder() .Append('(') .Append(Opc.Ua.BrowseNames.EventId) .Append('=') .Append('\'') .Append(eventId) .Append('\'') .Append(')'); lock (_dataset) { for (var ii = 0; ii < _dataset.Tables.Count; ii++) { var view = new DataView(_dataset.Tables[ii], filter.ToString(), null, DataViewRowState.CurrentRows); if (view.Count > 0) { view[0].Delete(); _dataset.AcceptChanges(); return true; } } } return false; } /// /// Reads the report history for the specified time range. /// /// /// /// /// public DataView ReadHistoryForWellId(ReportType reportType, string uidWell, DateTime startTime, DateTime endTime) { var filter = new StringBuilder() .Append('(') .Append(BrowseNames.UidWell) .Append('=') .Append('\'') .Append(uidWell) .Append('\'') .Append(')'); return ReadHistory(reportType, filter, startTime, endTime); } /// /// Reads the report history for the specified time range. /// /// /// /// /// public DataView ReadHistoryForArea(ReportType reportType, string areaName, DateTime startTime, DateTime endTime) { var filter = new StringBuilder(); if (!string.IsNullOrEmpty(areaName)) { filter .Append('(') .Append(BrowseNames.NameWell) .Append(" LIKE ") .Append('\'') .Append(areaName) .Append('*') .Append('\'') .Append(')'); } return ReadHistory(reportType, filter, startTime, endTime); } /// /// Reads the history for the specified time range. /// /// /// /// /// private DataView ReadHistory(ReportType reportType, StringBuilder filter, DateTime startTime, DateTime endTime) { var earlyTime = startTime; var lateTime = endTime; if (endTime < startTime && endTime != DateTime.MinValue) { earlyTime = endTime; lateTime = startTime; } if (earlyTime != DateTime.MinValue) { if (filter.Length > 0) { filter.Append(" AND "); } filter .Append('(') .Append(Opc.Ua.BrowseNames.Time) .Append(">=") .Append('#') .Append(earlyTime) .Append('#') .Append(')'); } if (lateTime != DateTime.MinValue) { if (filter.Length > 0) { filter.Append(" AND "); } filter .Append('(') .Append(Opc.Ua.BrowseNames.Time) .Append('<') .Append('#') .Append(lateTime) .Append('#') .Append(')'); } lock (_dataset) { return new DataView( _dataset.Tables[(int)reportType], filter.ToString(), Opc.Ua.BrowseNames.Time, DataViewRowState.CurrentRows); } } /// /// Converts the DB row to a UA event, /// /// The UA context to use for the conversion. /// The index assigned to the type model namespace. /// The type of report. /// The source for the report. /// The new report. public BaseEventState GetReport(ISystemContext context, ushort namespaceIndex, ReportType reportType, DataRow row) { switch (reportType) { case ReportType.FluidLevelTest: return GetFluidLevelTestReport(context, namespaceIndex, row); case ReportType.InjectionTest: return GetInjectionTestReport(context, namespaceIndex, row); } return null; } public BaseEventState GetFluidLevelTestReport(ISystemContext SystemContext, ushort namespaceIndex, DataRow row) { // construct translation object with default text. var info = new TranslationInfo( "FluidLevelTestReport", "en-US", "A fluid level test report is available."); // construct the event. var e = new FluidLevelTestReportState(null); e.Initialize( SystemContext, null, EventSeverity.Medium, new LocalizedText(info)); // override event id and time. e.EventId.Value = new Guid((string)row[Opc.Ua.BrowseNames.EventId]).ToByteArray(); e.Time.Value = (DateTime)row[Opc.Ua.BrowseNames.Time]; var nameWell = (string)row[BrowseNames.NameWell]; var uidWell = (string)row[BrowseNames.UidWell]; e.SetChildValue(SystemContext, Opc.Ua.BrowseNames.SourceName, nameWell, false); e.SetChildValue(SystemContext, Opc.Ua.BrowseNames.SourceNode, new NodeId(uidWell, namespaceIndex), false); e.SetChildValue(SystemContext, Opc.Ua.BrowseNames.LocalTime, _timeZone, false); e.SetChildValue(SystemContext, new QualifiedName(BrowseNames.NameWell, namespaceIndex), nameWell, false); e.SetChildValue(SystemContext, new QualifiedName(BrowseNames.UidWell, namespaceIndex), uidWell, false); e.SetChildValue(SystemContext, new QualifiedName(BrowseNames.TestDate, namespaceIndex), row[BrowseNames.TestDate], false); e.SetChildValue(SystemContext, new QualifiedName(BrowseNames.TestReason, namespaceIndex), row[BrowseNames.TestReason], false); e.SetChildValue(SystemContext, new QualifiedName(BrowseNames.TestedBy, namespaceIndex), row[BrowseNames.TestedBy], false); e.SetChildValue(SystemContext, new QualifiedName(BrowseNames.FluidLevel, namespaceIndex), row[BrowseNames.FluidLevel], false); e.FluidLevel.SetChildValue(SystemContext, Opc.Ua.BrowseNames.EngineeringUnits, new EUInformation((string)row[Opc.Ua.BrowseNames.EngineeringUnits], Namespaces.HistoricalEvents), false); return e; } public DataRow GenerateInjectionTestReport() { lock (_dataset) { var row = _dataset.Tables[1].NewRow(); row[0] = Guid.NewGuid().ToString(); row[1] = _timeService.UtcNow; var index = GetRandom(0, kWellUIDs.Length - 1); row[2] = kWellNames[index]; row[3] = kWellUIDs[index]; row[4] = _timeService.UtcNow.AddHours(-GetRandom(0, 10)); row[5] = GetRandom(kTestReasons); row[6] = GetRandom(0, 1000); row[7] = GetRandom(kUnitTimes); row[8] = GetRandom(kInjectionFluids); _dataset.Tables[1].Rows.Add(row); _dataset.AcceptChanges(); return row; } } public BaseEventState GetInjectionTestReport(ISystemContext SystemContext, ushort namespaceIndex, DataRow row) { // construct translation object with default text. var info = new TranslationInfo( "InjectionTestReport", "en-US", "An injection test report is available."); // construct the event. var e = new InjectionTestReportState(null); e.Initialize( SystemContext, null, EventSeverity.Medium, new LocalizedText(info)); // override event id and time. e.EventId.Value = new Guid((string)row[Opc.Ua.BrowseNames.EventId]).ToByteArray(); e.Time.Value = (DateTime)row[Opc.Ua.BrowseNames.Time]; var nameWell = (string)row[BrowseNames.NameWell]; var uidWell = (string)row[BrowseNames.UidWell]; e.SetChildValue(SystemContext, Opc.Ua.BrowseNames.SourceName, nameWell, false); e.SetChildValue(SystemContext, Opc.Ua.BrowseNames.SourceNode, new NodeId(uidWell, namespaceIndex), false); e.SetChildValue(SystemContext, Opc.Ua.BrowseNames.LocalTime, _timeZone, false); e.SetChildValue(SystemContext, new QualifiedName(BrowseNames.NameWell, namespaceIndex), nameWell, false); e.SetChildValue(SystemContext, new QualifiedName(BrowseNames.UidWell, namespaceIndex), uidWell, false); e.SetChildValue(SystemContext, new QualifiedName(BrowseNames.TestDate, namespaceIndex), row[BrowseNames.TestDate], false); e.SetChildValue(SystemContext, new QualifiedName(BrowseNames.TestReason, namespaceIndex), row[BrowseNames.TestReason], false); e.SetChildValue(SystemContext, new QualifiedName(BrowseNames.InjectedFluid, namespaceIndex), row[BrowseNames.InjectedFluid], false); e.SetChildValue(SystemContext, new QualifiedName(BrowseNames.TestDuration, namespaceIndex), row[BrowseNames.TestDuration], false); e.TestDuration.SetChildValue(SystemContext, Opc.Ua.BrowseNames.EngineeringUnits, new EUInformation((string)row[Opc.Ua.BrowseNames.EngineeringUnits], Namespaces.HistoricalEvents), false); return e; } private DataSet _dataset; private Random _random; private TimeZoneDataType _timeZone; private readonly TimeService _timeService; } public enum ReportType { FluidLevelTest, InjectionTest } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/IServerFactory.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { using Opc.Ua; using System; using System.Collections.Generic; /// /// Create servers /// public interface IServerFactory { /// /// Create server and server configuration for hosting. /// /// /// /// /// /// /// /// /// /// ApplicationConfiguration CreateServer(IEnumerable ports, string pkiRootPath, out ServerBase server, string listenHostName = null, IEnumerable alternativeAddresses = null, string path = null, string certStoreType = null, Action configure = null); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/IServerHost.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { using System; using System.Collections.Generic; using System.Security.Cryptography.X509Certificates; using System.Threading.Tasks; /// /// Server host /// public interface IServerHost : IDisposable { /// /// Server application instance certificate /// X509Certificate2 Certificate { get; } /// /// Set auto accept mode /// bool AutoAccept { get; set; } /// /// Start server listening on the specified /// ports. /// /// /// Task StartAsync(IEnumerable ports); /// /// Restart server. /// /// /// Task RestartAsync(Func predicate = null); /// /// Add reverse connection /// /// /// Task AddReverseConnectionAsync(Uri client, int maxSessionCount); /// /// Remove reverse connection /// /// Task RemoveReverseConnectionAsync(Uri client); /// /// Stop server - same as dispose but async. /// Task StopAsync(); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/ITestServer.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { /// /// Test server interface /// public interface ITestServer { /// /// Get published nodes json /// /// public string PublishedNodesJson { get; } /// /// Run in choas mode and randomly delete sessions, subscriptions /// inject errors and so on. /// bool Chaos { get; set; } /// /// Inject errors responding to incoming requests. The error /// rate is the probability of injection, e.g. 3 means 1 out /// of 3 requests will be injected with an error. /// int InjectErrorResponseRate { get; set; } /// /// Close sessions /// /// void CloseSessions(bool deleteSubscriptions = false); /// /// Close subscription. Notify expiration (timeout) of the /// subscription before closing (status message) if notifyExpiration /// is set to true. /// /// /// void CloseSubscription(uint subscriptionId, bool notifyExpiration); /// /// Close all subscriptions. Notify expiration (timeout) of the /// subscription before closing (status message) if notifyExpiration /// is set to true. /// /// void CloseSubscriptions(bool notifyExpiration = false); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Isa95Jobs/Isa95JobControlNodeManager.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Isa95Jobs { using Opc.Ua; using Opc.Ua.Server; using System; using System.Collections.Generic; using System.Globalization; using System.Reflection; using System.Threading; using UAModel.ISA95_JOBCONTROL_V2; /// /// A node manager for a server that exposes several variables. /// public class Isa95JobControlNodeManager : CustomNodeManager2 { /// /// Initializes the node manager. /// /// /// public Isa95JobControlNodeManager(IServerInternal server, ApplicationConfiguration configuration) : base(server, configuration) { SystemContext.NodeIdFactory = this; // set one namespace for the type model and one names for dynamically created nodes. var namespaceUrls = new string[1]; namespaceUrls[0] = UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2; SetNamespaces(namespaceUrls); // get the configuration for the node manager. // use suitable defaults if no configuration exists. _configuration = configuration.ParseExtension() ?? new Isa95JobControlServerConfiguration(); } /// /// An overrideable version of the Dispose. /// /// protected override void Dispose(bool disposing) { if (disposing && _simulationTimer != null) { Utils.SilentDispose(_simulationTimer); _simulationTimer = null; } base.Dispose(disposing); } /// /// Creates the NodeId for the specified node. /// /// /// public override NodeId New(ISystemContext context, NodeState node) { return node.NodeId; } /// /// Loads a node set from a file or resource and addes them to the set of predefined nodes. /// /// protected override NodeStateCollection LoadPredefinedNodes(ISystemContext context) { var type = GetType().GetTypeInfo(); var predefinedNodes = new NodeStateCollection(); predefinedNodes.LoadFromBinaryResource(context, $"{type.Assembly.GetName().Name}.Generated.{type.Namespace}.Design.UAModel.ISA95_JOBCONTROL_V2.PredefinedNodes.uanodes", type.Assembly, true); return predefinedNodes; } /// /// Does any initialization required before the address space can be used. /// /// /// /// The externalReferences is an out parameter that allows the node manager to link to nodes /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and /// should have a reference to the root folder node(s) exposed by this node manager. /// public override void CreateAddressSpace(IDictionary> externalReferences) { lock (Lock) { LoadPredefinedNodes(SystemContext, externalReferences); // start a simulation that changes the values of the nodes. _simulationTimer = new Timer(DoSimulation, null, kEventInterval, kEventInterval); } } /// /// Frees any resources allocated for the address space. /// public override void DeleteAddressSpace() { lock (Lock) { base.DeleteAddressSpace(); } } /// /// Returns a unique handle for the node. /// /// /// /// protected override NodeHandle GetManagerHandle(ServerSystemContext context, NodeId nodeId, IDictionary cache) { lock (Lock) { // quickly exclude nodes that are not in the namespace. if (!IsNodeIdInNamespace(nodeId)) { return null; } // check for predefined nodes. if (PredefinedNodes != null && PredefinedNodes.TryGetValue(nodeId, out var node)) { return new NodeHandle { NodeId = nodeId, Validated = true, Node = node }; } return null; } } /// /// Verifies that the specified node exists. /// /// /// /// protected override NodeState ValidateNode( ServerSystemContext context, NodeHandle handle, IDictionary cache) { // not valid if no root. if (handle == null) { return null; } // check if previously validated. if (handle.Validated) { return handle.Node; } // TBD return null; } /// /// Does the simulation. /// /// The state. private void DoSimulation(object state) { try { // construct translation object with default text. var info = new TranslationInfo( "ISA95JobResponse", "en-US", "The job '{0}' has completed.", ++_jobId); // construct the event. var e = new ISA95JobOrderStatusEventTypeState(null); e.Initialize( SystemContext, null, (EventSeverity)0, new LocalizedText(info)); e.SetChildValue(SystemContext, Opc.Ua.BrowseNames.SourceName, "GB05_ServerTEST", false); e.SetChildValue(SystemContext, Opc.Ua.BrowseNames.SourceNode, Opc.Ua.ObjectIds.Server, false); var startTime = DateTime.UtcNow.Subtract(TimeSpan.FromMinutes(3)); var endTime = DateTime.UtcNow; var response = new ISA95JobResponseDataType { EncodingMask = (ISA95JobResponseDataTypeFields)( (int)ISA95JobResponseDataTypeFields.None | (int)ISA95JobResponseDataTypeFields.StartTime | (int)ISA95JobResponseDataTypeFields.EndTime | (int)ISA95JobResponseDataTypeFields.EquipmentActuals | (int)ISA95JobResponseDataTypeFields.MaterialActuals), JobOrderID = _jobId.ToString(CultureInfo.InvariantCulture), JobResponseID = Guid.NewGuid().ToString(), StartTime = startTime, EndTime = endTime, EquipmentActuals = [ new ISA95EquipmentDataType { EncodingMask = (ISA95EquipmentDataTypeFields)( (int)ISA95EquipmentDataTypeFields.EquipmentUse | (int)ISA95EquipmentDataTypeFields.EngineeringUnits | (int)ISA95EquipmentDataTypeFields.Quantity), EngineeringUnits = new EUInformation("rpm", "RPM"), EquipmentUse = "consumable", Quantity = "500" }, new ISA95EquipmentDataType { EncodingMask = (ISA95EquipmentDataTypeFields)( (int)ISA95EquipmentDataTypeFields.EquipmentUse | (int)ISA95EquipmentDataTypeFields.EngineeringUnits | (int)ISA95EquipmentDataTypeFields.Quantity), EngineeringUnits = new EUInformation("C", "Celsius"), EquipmentUse = "consumable", Quantity = "3" } ], MaterialActuals = [ new ISA95MaterialDataType { EncodingMask = (ISA95MaterialDataTypeFields)( (int)ISA95MaterialDataTypeFields.MaterialClassID | (int)ISA95MaterialDataTypeFields.MaterialUse | (int)ISA95MaterialDataTypeFields.Quantity), MaterialClassID = Guid.NewGuid().ToString(), MaterialUse = "consumable", Quantity = "1" }, new ISA95MaterialDataType { EncodingMask = (ISA95MaterialDataTypeFields)( (int)ISA95MaterialDataTypeFields.MaterialClassID | (int)ISA95MaterialDataTypeFields.MaterialUse | (int)ISA95MaterialDataTypeFields.Quantity), MaterialClassID = Guid.NewGuid().ToString(), MaterialUse = "consumable", Quantity = "2" } ] }; e.SetChildValue(SystemContext, new QualifiedName(UAModel.ISA95_JOBCONTROL_V2.BrowseNames.JobResponse, NamespaceIndex), response, false); var jobOrderState = new ISA95JobOrderAndStateDataType { JobOrder = new ISA95JobOrderDataType { EncodingMask = ISA95JobOrderDataTypeFields.None, JobOrderID = _jobId.ToString(CultureInfo.InvariantCulture), EquipmentRequirements = [ new ISA95EquipmentDataType { EncodingMask = (ISA95EquipmentDataTypeFields)( (int)ISA95EquipmentDataTypeFields.EquipmentUse | (int) ISA95EquipmentDataTypeFields.EngineeringUnits | (int)ISA95EquipmentDataTypeFields.Quantity), EngineeringUnits = new EUInformation("rpm", "RPM"), EquipmentUse = "free", Quantity = "1000" } ] }, State = [ new ISA95StateDataType { StateNumber = ++_state, BrowsePath = new RelativePath(new QualifiedName("State " + _state, NamespaceIndex)), StateText = new LocalizedText("en-US", "State " + _state) }, new ISA95StateDataType { StateNumber = ++_state, BrowsePath = new RelativePath(new QualifiedName("State " + _state, NamespaceIndex)), StateText = new LocalizedText("en-US", "State " + _state) }, new ISA95StateDataType { StateNumber = ++_state, BrowsePath = new RelativePath(new QualifiedName("State " + _state, NamespaceIndex)), StateText = new LocalizedText("en-US", "State " + _state) } ] }; e.SetChildValue(SystemContext, new QualifiedName(UAModel.ISA95_JOBCONTROL_V2.BrowseNames.JobState, NamespaceIndex), jobOrderState, false); // e.SetChildValue(SystemContext, new QualifiedName(UAModel.ISA95_JOBCONTROL_V2.BrowseNames.JobOrder, NamespaceIndex), state, false); Server.ReportEvent(e); } catch (NullReferenceException) { // Stop simulation because the subscription is closed. This should be fixed in the server library. _simulationTimer.Change(Timeout.Infinite, Timeout.Infinite); } catch (Exception e) { Utils.Trace(e, "Unexpected error during simulation."); } } #pragma warning disable IDE0052 // Remove unread private members private readonly Isa95JobControlServerConfiguration _configuration; #pragma warning restore IDE0052 // Remove unread private members private Timer _simulationTimer; private int _jobId; private uint _state; private const int kEventInterval = 1000; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Isa95Jobs/Isa95JobControlServer.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Isa95Jobs { using Opc.Ua; using Opc.Ua.Server; /// public class Isa95JobControlServer : INodeManagerFactory { /// public StringCollection NamespacesUris { get { return [ UAModel.ISA95_JOBCONTROL_V2.Namespaces.ISA95_JOBCONTROL_V2 ]; } } /// public INodeManager Create(IServerInternal server, ApplicationConfiguration configuration) { return new Isa95JobControlNodeManager(server, configuration); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Isa95Jobs/Isa95JobControlServerConfiguration.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Isa95Jobs { using System.Runtime.Serialization; using UAModel.ISA95_JOBCONTROL_V2; /// /// Stores the configuration the data access node manager. /// [DataContract(Namespace = Namespaces.ISA95_JOBCONTROL_V2)] public class Isa95JobControlServerConfiguration { /// /// The default constructor. /// public Isa95JobControlServerConfiguration() { Initialize(); } /// /// Initializes the object during deserialization. /// /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/MemoryBuffer/MemoryBufferBrowser.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace MemoryBuffer { using Opc.Ua; using System; using System.Collections.Generic; /// /// A class to browse the references for a memory buffer. /// public class MemoryBufferBrowser : NodeBrowser { /// /// Creates a new browser object with a set of filters. /// /// /// /// /// /// /// /// /// /// public MemoryBufferBrowser( ISystemContext context, ViewDescription view, NodeId referenceType, bool includeSubtypes, BrowseDirection browseDirection, QualifiedName browseName, IEnumerable additionalReferences, bool internalOnly, MemoryBufferState buffer) : base( context, view, referenceType, includeSubtypes, browseDirection, browseName, additionalReferences, internalOnly) { _buffer = buffer; _stage = Stage.Begin; } /// /// Returns the next reference. /// /// public override IReference Next() { lock (DataLock) { // enumerate pre-defined references. // always call first to ensure any pushed-back references are returned first. var reference = base.Next(); if (reference != null) { return reference; } if (_stage == Stage.Begin) { _stage = Stage.Components; _position = 0; } // don't start browsing huge number of references when only internal references are requested. if (InternalOnly) { return null; } // enumerate components. if (_stage == Stage.Components) { if (IsRequired(ReferenceTypeIds.HasComponent, false)) { reference = NextChild(); if (reference != null) { return reference; } } _stage = Stage.ModelParents; _position = 0; } // all done. return null; } } /// /// Returns the next child. /// private NodeStateReference NextChild() { MemoryTagState tag; // check if a specific browse name is requested. if (!QualifiedName.IsNull(BrowseName)) { // check if match found previously. if (_position == uint.MaxValue) { return null; } // browse name must be qualified by the correct namespace. if (_buffer.TypeDefinitionId.NamespaceIndex != BrowseName.NamespaceIndex) { return null; } var name = BrowseName.Name; for (var ii = 0; ii < name.Length; ii++) { #pragma warning disable CA2249 // Consider using 'string.Contains' instead of 'string.IndexOf' if ("0123456789ABCDEF".IndexOf(name[ii], StringComparison.Ordinal) == -1) { #pragma warning restore CA2249 // Consider using 'string.Contains' instead of 'string.IndexOf' return null; } } _position = Convert.ToUInt32(name, 16); // check for memory overflow. if (_position >= _buffer.SizeInBytes.Value) { return null; } tag = new MemoryTagState(_buffer, _position); _position = uint.MaxValue; } // return the child at the next position. else { if (_position >= _buffer.SizeInBytes.Value) { return null; } tag = new MemoryTagState(_buffer, _position); _position += _buffer.ElementSize; // check for memory overflow. if (_position >= _buffer.SizeInBytes.Value) { return null; } } return new NodeStateReference(ReferenceTypeIds.HasComponent, false, tag); } /// /// The stages available in a browse operation. /// private enum Stage { Begin, Components, ModelParents, Done } private Stage _stage; private uint _position; private readonly MemoryBufferState _buffer; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/MemoryBuffer/MemoryBufferConfiguration.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace MemoryBuffer { using System.Collections.Generic; using System.Runtime.Serialization; /// /// Stores the configuration the test node manager /// [DataContract(Namespace = Namespaces.MemoryBuffer)] public class MemoryBufferConfiguration { /// /// The default constructor. /// public MemoryBufferConfiguration() { Initialize(); } /// /// Initializes the object during deserialization. /// /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { Buffers = null; } /// /// The buffers exposed by the memory /// [DataMember(Order = 1)] public MemoryBufferInstanceCollection Buffers { get; set; } } /// /// Stores the configuration for a memory buffer instance. /// [DataContract(Namespace = Namespaces.MemoryBuffer)] public class MemoryBufferInstance { /// /// The default constructor. /// public MemoryBufferInstance() { Initialize(); } /// /// Initializes the object during deserialization. /// /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { Name = null; TagCount = 0; DataType = null; } /// /// The browse name for the instance. /// [DataMember(Order = 1)] public string Name { get; set; } /// /// The number of tags in the buffer. /// [DataMember(Order = 2)] public int TagCount { get; set; } /// /// The data type of the tags in the buffer. /// [DataMember(Order = 3)] public string DataType { get; set; } } /// /// A collection of MemoryBufferInstances. /// [CollectionDataContract(Name = "ListOfMemoryBufferInstance", Namespace = Namespaces.MemoryBuffer, ItemName = "MemoryBufferInstance")] public class MemoryBufferInstanceCollection : List; } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/MemoryBuffer/MemoryBufferMonitoredItem.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace MemoryBuffer { using Opc.Ua; using Opc.Ua.Server; /// /// Provides a basic monitored item implementation which does not support queuing. /// public class MemoryBufferMonitoredItem : MonitoredItem { /// /// Initializes the object with its node type. /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// public MemoryBufferMonitoredItem( IServerInternal server, INodeManager nodeManager, object mangerHandle, uint offset, uint subscriptionId, uint id, ReadValueId itemToMonitor, DiagnosticsMasks diagnosticsMasks, TimestampsToReturn timestampsToReturn, MonitoringMode monitoringMode, uint clientHandle, MonitoringFilter originalFilter, MonitoringFilter filterToUse, Range range, double samplingInterval, uint queueSize, bool discardOldest, double minimumSamplingInterval) : base( server, nodeManager, mangerHandle, subscriptionId, id, itemToMonitor, diagnosticsMasks, timestampsToReturn, monitoringMode, clientHandle, originalFilter, filterToUse, range, samplingInterval, queueSize, discardOldest, minimumSamplingInterval) { Offset = offset; } /// /// Modifies the monitored item parameters, /// /// /// /// /// public ServiceResult Modify( DiagnosticsMasks diagnosticsMasks, TimestampsToReturn timestampsToReturn, uint clientHandle, double samplingInterval) { return ModifyAttributes(diagnosticsMasks, timestampsToReturn, clientHandle, null, null, null, samplingInterval, 0, false); } /// /// The offset in the memory buffer. /// public uint Offset { get; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/MemoryBuffer/MemoryBufferNodeManager.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace MemoryBuffer { using Opc.Ua; using Opc.Ua.Sample; using Opc.Ua.Server; using System; using System.Collections.Generic; using System.Reflection; /// /// A node manager for a variety of test data. /// public class MemoryBufferNodeManager : SampleNodeManager { /// /// Initializes the node manager. /// /// /// public MemoryBufferNodeManager(IServerInternal server, ApplicationConfiguration configuration) : base(server) { NamespaceUris = new List { Namespaces.MemoryBuffer, Namespaces.MemoryBuffer + "/Instance" }; // get the configuration for the node manager. // use suitable defaults if no configuration exists. _configuration = configuration.ParseExtension() ?? new MemoryBufferConfiguration(); _buffers = []; } /// /// Dispose /// /// protected override void Dispose(bool disposing) { base.Dispose(disposing); if (disposing && _buffers != null) { foreach (var buffer in _buffers.Values) { buffer.Dispose(); } _buffers.Clear(); _buffers = null; } } /// /// Does any initialization required before the address space can be used. /// /// /// /// The externalReferences is an out parameter that allows the node manager to link to nodes /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and /// should have a reference to the root folder node(s) exposed by this node manager. /// public override void CreateAddressSpace(IDictionary> externalReferences) { lock (Lock) { base.CreateAddressSpace(externalReferences); // create the nodes from configuration. var namespaceIndex = Server.NamespaceUris.GetIndexOrAppend(Namespaces.MemoryBuffer); var root = (BaseInstanceState)FindPredefinedNode( new NodeId(Objects.MemoryBuffers, namespaceIndex), typeof(BaseInstanceState)); // create the nodes from configuration. namespaceIndex = Server.NamespaceUris.GetIndexOrAppend(Namespaces.MemoryBuffer + "/Instance"); if (_configuration?.Buffers != null) { for (var ii = 0; ii < _configuration.Buffers.Count; ii++) { var instance = _configuration.Buffers[ii]; // create a new buffer. var bufferNode = new MemoryBufferState(SystemContext, instance); // assign node ids. bufferNode.Create( SystemContext, new NodeId(bufferNode.SymbolicName, namespaceIndex), new QualifiedName(bufferNode.SymbolicName, namespaceIndex), null, true); bufferNode.CreateBuffer(instance.DataType, instance.TagCount); bufferNode.InitializeMonitoring(Server, this); // save the buffers for easy look up later. _buffers[bufferNode.SymbolicName] = bufferNode; // link to root. root.AddChild(bufferNode); } } } } /// /// Loads a node set from a file or resource and addes them to the set of predefined nodes. /// /// protected override NodeStateCollection LoadPredefinedNodes(ISystemContext context) { var type = GetType().GetTypeInfo(); var predefinedNodes = new NodeStateCollection(); predefinedNodes.LoadFromBinaryResource(context, $"{type.Assembly.GetName().Name}.Generated.{type.Namespace}.Design.{type.Namespace}.PredefinedNodes.uanodes", type.Assembly, true); return predefinedNodes; } /// /// Frees any resources allocated for the address space. /// public override void DeleteAddressSpace() { lock (Lock) { base.DeleteAddressSpace(); } } /// /// Returns a unique handle for the node. /// /// /// /// /// /// This must efficiently determine whether the node belongs to the node manager. If it does belong to /// NodeManager it should return a handle that does not require the NodeId to be validated again when /// the handle is passed into other methods such as 'Read' or 'Write'. /// protected override object GetManagerHandle(ISystemContext context, NodeId nodeId, IDictionary cache) { lock (Lock) { if (!IsNodeIdInNamespace(nodeId)) { return null; } if (nodeId.Identifier is string id) { // check for a reference to the buffer. if (_buffers.TryGetValue(id, out var buffer)) { return buffer; } // tag ids have the syntax [
] if (id[^1] != ']') { return null; } var index = id.IndexOf('['); if (index == -1) { return null; } var bufferName = id[..index]; // verify the buffer. if (!_buffers.TryGetValue(bufferName, out buffer)) { return null; } // validate the address. var offsetText = id.Substring(index + 1, id.Length - index - 2); for (var ii = 0; ii < offsetText.Length; ii++) { if (!char.IsDigit(offsetText[ii])) { return null; } } // check range on offset. var offset = Convert.ToUInt32(offsetText); if (offset >= buffer.SizeInBytes.Value) { return null; } // the tags contain all of the metadata required to support the UA // operations and pointers to functions in the buffer object that // allow the value to be accessed. These tags are ephemeral and are // discarded after the operation completes. This design pattern allows // the server to expose potentially millions of UA nodes without // creating millions of objects that reside in memory. return new MemoryTagState(buffer, offset); } return base.GetManagerHandle(context, nodeId, cache); } } /// /// Creates a new set of monitored items for a set of variables. /// /// /// /// /// /// /// /// /// /// /// /// /// /// This method only handles data change subscriptions. Event subscriptions are created by the SDK. /// protected override ServiceResult CreateMonitoredItem( ISystemContext context, NodeState source, uint subscriptionId, double publishingInterval, DiagnosticsMasks diagnosticsMasks, TimestampsToReturn timestampsToReturn, MonitoredItemCreateRequest itemToCreate, bool createDurable, ref long globalIdCounter, out MonitoringFilterResult filterError, out IMonitoredItem monitoredItem) { filterError = null; monitoredItem = null; // use default behavoir for non-tag sources. if (source is not MemoryTagState tag) { return base.CreateMonitoredItem( context, source, subscriptionId, publishingInterval, diagnosticsMasks, timestampsToReturn, itemToCreate, createDurable, ref globalIdCounter, out filterError, out monitoredItem); } // validate parameters. var parameters = itemToCreate.RequestedParameters; // no filters supported at this time. var filter = (MonitoringFilter)ExtensionObject.ToEncodeable(parameters.Filter); if (filter != null) { return StatusCodes.BadFilterNotAllowed; } // index range not supported. if (itemToCreate.ItemToMonitor.ParsedIndexRange != NumericRange.Empty) { return StatusCodes.BadIndexRangeInvalid; } // data encoding not supported. if (!QualifiedName.IsNull(itemToCreate.ItemToMonitor.DataEncoding)) { return StatusCodes.BadDataEncodingInvalid; } // read initial value. var initialValue = new DataValue { Value = null, ServerTimestamp = DateTime.UtcNow, SourceTimestamp = DateTime.MinValue, StatusCode = StatusCodes.Good }; var error = source.ReadAttribute( context, itemToCreate.ItemToMonitor.AttributeId, itemToCreate.ItemToMonitor.ParsedIndexRange, itemToCreate.ItemToMonitor.DataEncoding, initialValue); if (ServiceResult.IsBad(error)) { return error; } // get the monitored node for the containing buffer. if (tag.Parent is not MemoryBufferState buffer) { return StatusCodes.BadInternalError; } // create a globally unique identifier. var monitoredItemId = Utils.IncrementIdentifier(ref globalIdCounter); // determine the sampling interval. var samplingInterval = itemToCreate.RequestedParameters.SamplingInterval; if (samplingInterval < 0) { samplingInterval = publishingInterval; } // create the item. var datachangeItem = buffer.CreateDataChangeItem( tag, monitoredItemId, itemToCreate.ItemToMonitor, diagnosticsMasks, timestampsToReturn, itemToCreate.MonitoringMode, itemToCreate.RequestedParameters.ClientHandle, samplingInterval); /* // create the item. MemoryBufferMonitoredItem datachangeItem = buffer.CreateDataChangeItem( context, tag, monitoredItemId, itemToCreate.ItemToMonitor.AttributeId, diagnosticsMasks, timestampsToReturn, itemToCreate.MonitoringMode, itemToCreate.RequestedParameters.ClientHandle, samplingInterval); */ // report the initial value. datachangeItem.QueueValue(initialValue, null); // update monitored item list. monitoredItem = datachangeItem; return ServiceResult.Good; } /// /// Modifies the parameters for a monitored item. /// /// /// /// /// /// /// protected override ServiceResult ModifyMonitoredItem( ISystemContext context, DiagnosticsMasks diagnosticsMasks, TimestampsToReturn timestampsToReturn, IMonitoredItem monitoredItem, MonitoredItemModifyRequest itemToModify, out MonitoringFilterResult filterError) { filterError = null; // check for valid handle. if (monitoredItem.ManagerHandle is not MemoryBufferState) { return base.ModifyMonitoredItem( context, diagnosticsMasks, timestampsToReturn, monitoredItem, itemToModify, out filterError); } // owned by this node manager. itemToModify.Processed = true; // get the monitored item. if (monitoredItem is not MemoryBufferMonitoredItem datachangeItem) { return StatusCodes.BadMonitoredItemIdInvalid; } // validate parameters. var parameters = itemToModify.RequestedParameters; // no filters supported at this time. var filter = (MonitoringFilter)ExtensionObject.ToEncodeable(parameters.Filter); if (filter != null) { return StatusCodes.BadFilterNotAllowed; } // modify the monitored item parameters. _ = datachangeItem.Modify( diagnosticsMasks, timestampsToReturn, itemToModify.RequestedParameters.ClientHandle, itemToModify.RequestedParameters.SamplingInterval); return ServiceResult.Good; } /// /// Deletes a monitored item. /// /// /// /// protected override ServiceResult DeleteMonitoredItem( ISystemContext context, IMonitoredItem monitoredItem, out bool processed) { // check for valid handle. if (monitoredItem.ManagerHandle is not MemoryBufferState buffer) { return base.DeleteMonitoredItem( context, monitoredItem, out processed); } // owned by this node manager. processed = true; // get the monitored item. if (monitoredItem is not MemoryBufferMonitoredItem datachangeItem) { return StatusCodes.BadMonitoredItemIdInvalid; } // delete the item. buffer.DeleteItem(datachangeItem); return ServiceResult.Good; } /// /// Changes the monitoring mode for an item. /// /// /// /// /// protected override ServiceResult SetMonitoringMode( ISystemContext context, IMonitoredItem monitoredItem, MonitoringMode monitoringMode, out bool processed) { // check for valid handle. if (monitoredItem.ManagerHandle is not MemoryBufferState buffer) { return base.SetMonitoringMode( context, monitoredItem, monitoringMode, out processed); } // owned by this node manager. processed = true; // get the monitored item. if (monitoredItem is not MemoryBufferMonitoredItem datachangeItem) { return StatusCodes.BadMonitoredItemIdInvalid; } // delete the item. var previousMode = datachangeItem.SetMonitoringMode(monitoringMode); // need to provide an immediate update after enabling. if (previousMode == MonitoringMode.Disabled && monitoringMode != MonitoringMode.Disabled) { var initialValue = new DataValue { Value = null, ServerTimestamp = DateTime.UtcNow, SourceTimestamp = DateTime.MinValue, StatusCode = StatusCodes.Good }; var tag = new MemoryTagState(buffer, datachangeItem.Offset); var error = tag.ReadAttribute( context, datachangeItem.AttributeId, NumericRange.Empty, null, initialValue); datachangeItem.QueueValue(initialValue, error); } return ServiceResult.Good; } private readonly MemoryBufferConfiguration _configuration; private Dictionary _buffers; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/MemoryBuffer/MemoryBufferServer.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace MemoryBuffer { using Opc.Ua; using Opc.Ua.Server; /// public class MemoryBufferServer : INodeManagerFactory { /// public StringCollection NamespacesUris { get { return [ Namespaces.MemoryBuffer, Namespaces.MemoryBuffer + "/Instance" ]; } } /// public INodeManager Create(IServerInternal server, ApplicationConfiguration configuration) { return new MemoryBufferNodeManager(server, configuration); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/MemoryBuffer/MemoryBufferState.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace MemoryBuffer { using Opc.Ua; using Opc.Ua.Server; using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading; public partial class MemoryBufferState { /// /// Initializes the buffer from the configuration. /// /// /// public MemoryBufferState(ISystemContext context, MemoryBufferInstance configuration) : base(null) { Initialize(context); var dataType = "UInt32"; var name = dataType; var count = 10; if (configuration != null) { count = configuration.TagCount; if (!string.IsNullOrEmpty(configuration.DataType)) { dataType = configuration.DataType; } if (!string.IsNullOrEmpty(configuration.Name)) { name = dataType; } } SymbolicName = name; var elementType = BuiltInType.UInt32; switch (dataType) { case "Double": { elementType = BuiltInType.Double; break; } } CreateBuffer(elementType, count); } protected override void Dispose(bool disposing) { if (disposing && _scanTimer != null) { _scanTimer.Dispose(); _scanTimer = null; } base.Dispose(disposing); } /// /// The server that the buffer belongs to. /// public IServerInternal Server { get; private set; } /// /// The node manager that the buffer belongs to. /// public INodeManager NodeManager { get; private set; } /// /// The built-in type for the values stored in the buffer. /// public BuiltInType ElementType { get; private set; } /// /// The size of each element in the buffer. /// public uint ElementSize => (uint)_elementSize; /// /// The rate at which the buffer is scanned. /// public int MaximumScanRate { get; private set; } /// /// Initializes the buffer with enough space to hold the specified number of elements. /// /// The type of element. /// The number of elements. public void CreateBuffer(string elementName, int noOfElements) { if (string.IsNullOrEmpty(elementName)) { elementName = "UInt32"; } var elementType = BuiltInType.UInt32; switch (elementName) { case "Double": { elementType = BuiltInType.Double; break; } } CreateBuffer(elementType, noOfElements); } /// /// Initializes the buffer with enough space to hold the specified number of elements. /// /// The type of element. /// The number of elements. public void CreateBuffer(BuiltInType elementType, int noOfElements) { lock (_dataLock) { ElementType = elementType; _elementSize = 1; switch (ElementType) { case BuiltInType.UInt32: { _elementSize = 4; break; } case BuiltInType.Double: { _elementSize = 8; break; } } _lastScanTime = DateTime.UtcNow; MaximumScanRate = 1000; _buffer = new byte[_elementSize * noOfElements]; SizeInBytes.Value = (uint)_buffer.Length; } } /// /// Creates an object which can browser the tags in the buffer. /// /// /// /// /// /// /// /// /// public override INodeBrowser CreateBrowser( ISystemContext context, ViewDescription view, NodeId referenceType, bool includeSubtypes, BrowseDirection browseDirection, QualifiedName browseName, IEnumerable additionalReferences, bool internalOnly) { NodeBrowser browser = new MemoryBufferBrowser( context, view, referenceType, includeSubtypes, browseDirection, browseName, additionalReferences, internalOnly, this); PopulateBrowser(context, browser); return browser; } /// /// Handles the read operation for an invidual tag. /// /// /// /// /// /// /// /// public ServiceResult ReadTagValue( #pragma warning disable IDE0079 // Remove unnecessary suppression #pragma warning disable IDE0060 // Remove unused parameter ISystemContext context, #pragma warning restore IDE0060 // Remove unused parameter #pragma warning restore IDE0079 // Remove unnecessary suppression NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp) { if (node is not MemoryTagState tag) { return StatusCodes.BadNodeIdUnknown; } if (NumericRange.Empty != indexRange) { return StatusCodes.BadIndexRangeInvalid; } if (!QualifiedName.IsNull(dataEncoding)) { return StatusCodes.BadDataEncodingInvalid; } var offset = (int)tag.Offset; lock (_dataLock) { if (offset < 0 || offset >= _buffer.Length) { return StatusCodes.BadNodeIdUnknown; } if (_buffer == null) { return StatusCodes.BadOutOfService; } value = GetValueAtOffset(offset).Value; } statusCode = StatusCodes.Good; timestamp = _lastScanTime; return ServiceResult.Good; } /// /// Handles a write operation for an individual tag. /// /// /// /// /// /// /// /// public ServiceResult WriteTagValue( #pragma warning disable IDE0079 // Remove unnecessary suppression #pragma warning disable IDE0060 // Remove unused parameter ISystemContext context, #pragma warning restore IDE0060 // Remove unused parameter #pragma warning restore IDE0079 // Remove unnecessary suppression NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp) { if (node is not MemoryTagState tag) { return StatusCodes.BadNodeIdUnknown; } if (NumericRange.Empty != indexRange) { return StatusCodes.BadIndexRangeInvalid; } if (!QualifiedName.IsNull(dataEncoding)) { return StatusCodes.BadDataEncodingInvalid; } if (statusCode != StatusCodes.Good) { return StatusCodes.BadWriteNotSupported; } if (timestamp != DateTime.MinValue) { return StatusCodes.BadWriteNotSupported; } var changed = false; var offset = (int)tag.Offset; lock (_dataLock) { if (offset < 0 || offset >= _buffer.Length) { return StatusCodes.BadNodeIdUnknown; } if (_buffer == null) { return StatusCodes.BadOutOfService; } byte[] bytes = null; switch (ElementType) { case BuiltInType.UInt32: { if (value is not uint valueToWrite) { return StatusCodes.BadTypeMismatch; } bytes = BitConverter.GetBytes(valueToWrite); break; } case BuiltInType.Double: { if (value is not double valueToWrite) { return StatusCodes.BadTypeMismatch; } bytes = BitConverter.GetBytes(valueToWrite); break; } default: { return StatusCodes.BadNodeIdUnknown; } } for (var ii = 0; ii < bytes.Length; ii++) { if (!changed && _buffer[offset + ii] != bytes[ii]) { changed = true; } _buffer[offset + ii] = bytes[ii]; } } if (changed) { OnBufferChanged(offset); } return ServiceResult.Good; } /// /// Returns the value at the specified offset. /// /// public Variant GetValueAtOffset(int offset) { lock (_dataLock) { if (offset < 0 || offset >= _buffer.Length) { return Variant.Null; } if (_buffer == null) { return Variant.Null; } switch (ElementType) { case BuiltInType.UInt32: { return new Variant(BitConverter.ToUInt32(_buffer, offset)); } case BuiltInType.Double: { return new Variant(BitConverter.ToDouble(_buffer, offset)); } } return Variant.Null; } } /// /// Initializes the instance with the context for the node being monitored. /// /// /// public void InitializeMonitoring( IServerInternal server, INodeManager nodeManager) { lock (_dataLock) { Server = server; NodeManager = nodeManager; _nonValueMonitoredItems = []; } } /// /// Creates a new data change monitored item. /// /// /// /// /// /// /// /// /// public MemoryBufferMonitoredItem CreateDataChangeItem( MemoryTagState tag, uint monitoredItemId, ReadValueId itemToMonitor, DiagnosticsMasks diagnosticsMasks, TimestampsToReturn timestampsToReturn, MonitoringMode monitoringMode, uint clientHandle, double samplingInterval) { lock (_dataLock) { var monitoredItem = new MemoryBufferMonitoredItem( Server, NodeManager, this, tag.Offset, 0, monitoredItemId, itemToMonitor, diagnosticsMasks, timestampsToReturn, monitoringMode, clientHandle, null, null, null, samplingInterval, 0, false, 0); if (itemToMonitor.AttributeId != Attributes.Value) { _nonValueMonitoredItems.Add(monitoredItem.Id, monitoredItem); return monitoredItem; } var elementCount = (int)(SizeInBytes.Value / ElementSize); if (_monitoringTable == null) { _monitoringTable = new MemoryBufferMonitoredItem[elementCount][]; _scanTimer = new Timer(DoScan, null, 100, 100); } var elementOffet = (int)(tag.Offset / ElementSize); var monitoredItems = _monitoringTable[elementOffet]; if (monitoredItems == null) { monitoredItems = new MemoryBufferMonitoredItem[1]; } else { monitoredItems = new MemoryBufferMonitoredItem[monitoredItems.Length + 1]; _monitoringTable[elementOffet].CopyTo(monitoredItems, 0); } monitoredItems[^1] = monitoredItem; _monitoringTable[elementOffet] = monitoredItems; _itemCount++; return monitoredItem; } } /// /// Scans the buffer and updates every other element. /// /// private void DoScan(object state) { var start1 = DateTime.UtcNow; lock (_dataLock) { for (var ii = 0; ii < _buffer.Length; ii += _elementSize) { _buffer[ii]++; // notify any monitored items that the value has changed. OnBufferChanged(ii); } _lastScanTime = DateTime.UtcNow; } var end1 = DateTime.UtcNow; var delta1 = ((double)(end1.Ticks - start1.Ticks)) / TimeSpan.TicksPerMillisecond; if (delta1 > 100) { Debug.WriteLine("SAMPLING DELAY ({0}ms)", delta1); } } /// /// Deletes the monitored item. /// /// public void DeleteItem(MemoryBufferMonitoredItem monitoredItem) { lock (_dataLock) { if (monitoredItem.AttributeId != Attributes.Value) { _nonValueMonitoredItems.Remove(monitoredItem.Id); return; } if (_monitoringTable != null) { var elementOffet = (int)(monitoredItem.Offset / ElementSize); var monitoredItems = _monitoringTable[elementOffet]; if (monitoredItems != null) { var index = -1; for (var ii = 0; ii < monitoredItems.Length; ii++) { if (ReferenceEquals(monitoredItems[ii], monitoredItem)) { index = ii; break; } } if (index >= 0) { _itemCount--; if (monitoredItems.Length == 1) { monitoredItems = null; } else { monitoredItems = new MemoryBufferMonitoredItem[monitoredItems.Length - 1]; Array.Copy(_monitoringTable[elementOffet], 0, monitoredItems, 0, index); Array.Copy(_monitoringTable[elementOffet], index + 1, monitoredItems, index, monitoredItems.Length - index); } _monitoringTable[elementOffet] = monitoredItems; } } } } } /// /// Handles change events raised by the node. /// /// public void OnBufferChanged(int offset) { lock (_dataLock) { if (_monitoringTable != null) { var elementOffet = (int)(offset / ElementSize); var monitoredItems = _monitoringTable[elementOffet]; if (monitoredItems != null) { var value = new DataValue { WrappedValue = GetValueAtOffset(offset), StatusCode = StatusCodes.Good, ServerTimestamp = DateTime.UtcNow, SourceTimestamp = _lastScanTime }; for (var ii = 0; ii < monitoredItems.Length; ii++) { monitoredItems[ii].QueueValue(value, null); _updateCount++; } } } } } private void ScanTimer_Tick(object sender, EventArgs e) { DoScan(null); } private void PublishTimer_Tick(object sender, EventArgs e) { var start1 = DateTime.UtcNow; lock (_dataLock) { if (_itemCount > 0 && _updateCount < _itemCount) { Debug.WriteLine("{0:HH:mm:ss.fff} MEMORYBUFFER Reported {1}/{2} items ***.", DateTime.Now, _updateCount, _itemCount); } _updateCount = 0; } var end1 = DateTime.UtcNow; var delta1 = ((double)(end1.Ticks - start1.Ticks)) / TimeSpan.TicksPerMillisecond; if (delta1 > 100) { Debug.WriteLine("****** PUBLISH DELAY ({0}ms) ******", delta1); } } private readonly Lock _dataLock = new(); private MemoryBufferMonitoredItem[][] _monitoringTable; private Dictionary _nonValueMonitoredItems; private int _elementSize; private DateTime _lastScanTime; private byte[] _buffer; private Timer _scanTimer; private int _updateCount; private int _itemCount; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/MemoryBuffer/MemoryTagState.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace MemoryBuffer { using Opc.Ua; public partial class MemoryTagState { /// /// Initializes a memory tag for a buffer. /// /// The buffer that owns the tag. /// The offset of the tag address in the memory buffer. public MemoryTagState(MemoryBufferState parent, uint offet) : base(parent) { // these objects are created an discarded during each operation. // the metadata is derived from the parameters passed to constructors. NodeId = new NodeId(Utils.Format("{0}[{1}]", parent.SymbolicName, offet), parent.NodeId.NamespaceIndex); BrowseName = new QualifiedName(Utils.Format("{1:X8}", parent.SymbolicName, offet), parent.TypeDefinitionId.NamespaceIndex); DisplayName = BrowseName.Name; Description = null; WriteMask = AttributeWriteMask.None; UserWriteMask = AttributeWriteMask.None; ReferenceTypeId = ReferenceTypeIds.HasComponent; TypeDefinitionId = new NodeId(VariableTypes.MemoryTagType, parent.TypeDefinitionId.NamespaceIndex); ModellingRuleId = null; NumericId = offet; DataType = new NodeId((uint)parent.ElementType); ValueRank = ValueRanks.Scalar; ArrayDimensions = null; AccessLevel = AccessLevels.CurrentReadOrWrite; UserAccessLevel = AccessLevels.CurrentReadOrWrite; MinimumSamplingInterval = parent.MaximumScanRate; Historizing = false; // re-direct read and write operations to the parent. OnReadValue = parent.ReadTagValue; OnWriteValue = parent.WriteTagValue; Offset = offet; } /// /// The offset of the tag address in the memory buffer. /// public uint Offset { get; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/PerfTest/MemoryRegisterState.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace PerfTest { using Opc.Ua; using System; using System.Collections.Generic; public static class ModelUtils { public static NodeId GetRegisterId(MemoryRegister register, ushort namespaceIndex) { return new NodeId((uint)register.Id, namespaceIndex); } public static NodeId GetRegisterVariableId(MemoryRegister register, int index, ushort namespaceIndex) { var id = (uint)(register.Id << 24) + (uint)index; return new NodeId(id, namespaceIndex); } public static MemoryRegisterState GetRegister(MemoryRegister register, ushort namespaceIndex) { return new MemoryRegisterState(register, namespaceIndex); } public static BaseDataVariableState GetRegisterVariable(MemoryRegister register, int index, ushort namespaceIndex) { if (index < 0 || index >= register.Size) { return null; } var variable = new BaseDataVariableState(null) { NodeId = GetRegisterVariableId(register, index, namespaceIndex), BrowseName = new QualifiedName(Utils.Format("{0:000000}", index), namespaceIndex) }; variable.DisplayName = variable.BrowseName.Name; variable.Value = register.Read(index); variable.DataType = DataTypeIds.Int32; variable.ValueRank = ValueRanks.Scalar; variable.MinimumSamplingInterval = 100; variable.AccessLevel = AccessLevels.CurrentReadOrWrite; variable.UserAccessLevel = AccessLevels.CurrentReadOrWrite; variable.Handle = register; variable.NumericId = (uint)index; return variable; } } public class MemoryRegisterState : FolderState { public MemoryRegisterState(MemoryRegister register, ushort namespaceIndex) : base(null) { Register = register; NodeId = new NodeId((uint)register.Id, namespaceIndex); BrowseName = new QualifiedName(register.Name, namespaceIndex); DisplayName = BrowseName.Name; AddReference(ReferenceTypeIds.Organizes, true, ObjectIds.ObjectsFolder); } public MemoryRegister Register { get; } public override INodeBrowser CreateBrowser( ISystemContext context, ViewDescription view, NodeId referenceType, bool includeSubtypes, BrowseDirection browseDirection, QualifiedName browseName, IEnumerable additionalReferences, bool internalOnly) { return new MemoryRegisterBrowser( context, view, referenceType, includeSubtypes, browseDirection, browseName, additionalReferences, internalOnly, this); } } /// /// Browses the children of a segment. /// public class MemoryRegisterBrowser : NodeBrowser { /// /// Creates a new browser object with a set of filters. /// /// /// /// /// /// /// /// /// /// public MemoryRegisterBrowser( ISystemContext context, ViewDescription view, NodeId referenceType, bool includeSubtypes, BrowseDirection browseDirection, QualifiedName browseName, IEnumerable additionalReferences, bool internalOnly, MemoryRegisterState parent) : base( context, view, referenceType, includeSubtypes, browseDirection, browseName, additionalReferences, internalOnly) { _parent = parent; _stage = Stage.Begin; } /// /// Returns the next reference. /// /// The next reference that meets the browse criteria. public override IReference Next() { _ = (UnderlyingSystem)SystemContext.SystemHandle; lock (DataLock) { // enumerate pre-defined references. // always call first to ensure any pushed-back references are returned first. var reference = base.Next(); if (reference != null) { return reference; } if (_stage == Stage.Begin) { _stage = Stage.Tags; _position = 0; } // don't start browsing huge number of references when only internal references are requested. if (InternalOnly) { return null; } // enumerate tags. if (_stage == Stage.Tags && IsRequired(ReferenceTypeIds.Organizes, false)) { reference = NextChild(); if (reference != null) { return reference; } } // all done. return null; } } /// /// Returns the next child. /// private NodeStateReference NextChild() { _ = (UnderlyingSystem)SystemContext.SystemHandle; NodeId targetId; // check if a specific browse name is requested. if (!QualifiedName.IsNull(BrowseName)) { // browse name must be qualified by the correct namespace. if (_parent.BrowseName.NamespaceIndex != BrowseName.NamespaceIndex) { return null; } // parse the browse name. var index = 0; for (var ii = 0; ii < BrowseName.Name.Length; ii++) { var ch = BrowseName.Name[ii]; if (!char.IsDigit(ch)) { return null; } index *= 10; index += Convert.ToInt32(ch - '0'); } // check for valid browse name. if (index < 0 || index > _parent.Register.Size) { return null; } // return target. targetId = ModelUtils.GetRegisterVariableId(_parent.Register, index, _parent.NodeId.NamespaceIndex); } // return the child at the next position. else { // look for next segment. if (_position >= _parent.Register.Size) { return null; } // return target. targetId = ModelUtils.GetRegisterVariableId(_parent.Register, _position, _parent.NodeId.NamespaceIndex); _position++; } // create reference. if (targetId != null) { return new NodeStateReference(ReferenceTypeIds.Organizes, false, targetId); } return null; } /// /// The stages available in a browse operation. /// private enum Stage { Begin, Tags, Done } private Stage _stage; private int _position; private readonly MemoryRegisterState _parent; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/PerfTest/Namespaces.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace PerfTest { /// /// Defines constants for namespaces used by the application. /// public static class Namespaces { /// /// The namespace for the nodes provided by the server. /// public const string PerfTest = "http://opcfoundation.org/PerfTest"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/PerfTest/PerfTestNodeManager.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace PerfTest { using Opc.Ua; using Opc.Ua.Server; using System.Collections.Generic; /// /// A node manager for a server that exposes several variables. /// public class PerfTestNodeManager : CustomNodeManager2 { /// /// Initializes the node manager. /// /// /// public PerfTestNodeManager(IServerInternal server, ApplicationConfiguration configuration) : base(server, configuration, Namespaces.PerfTest) { SystemContext.NodeIdFactory = this; SystemContext.SystemHandle = _system = new UnderlyingSystem(); // get the configuration for the node manager. // use suitable defaults if no configuration exists. _configuration = configuration.ParseExtension() ?? new PerfTestServerConfiguration(); } /// /// An overrideable version of the Dispose. /// /// protected override void Dispose(bool disposing) { if (disposing) { // TBD } base.Dispose(disposing); } /// /// Creates the NodeId for the specified node. /// /// /// public override NodeId New(ISystemContext context, NodeState node) { return node.NodeId; } /// /// Does any initialization required before the address space can be used. /// /// /// /// The externalReferences is an out parameter that allows the node manager to link to nodes /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and /// should have a reference to the root folder node(s) exposed by this node manager. /// public override void CreateAddressSpace(IDictionary> externalReferences) { lock (Lock) { _system.Initialize(); var registers = _system.Registers; for (var ii = 0; ii < registers.Count; ii++) { var targetId = ModelUtils.GetRegisterId(registers[ii], NamespaceIndex); if (!externalReferences.TryGetValue(ObjectIds.ObjectsFolder, out var references)) { externalReferences[ObjectIds.ObjectsFolder] = references = []; } references.Add(new NodeStateReference(ReferenceTypeIds.Organizes, false, targetId)); } } } /// /// Frees any resources allocated for the address space. /// public override void DeleteAddressSpace() { lock (Lock) { // TBD } } /// /// Returns a unique handle for the node. /// /// /// /// protected override NodeHandle GetManagerHandle(ServerSystemContext context, NodeId nodeId, IDictionary cache) { lock (Lock) { // quickly exclude nodes that are not in the namespace. if (!IsNodeIdInNamespace(nodeId)) { return null; } var handle = new NodeHandle { NodeId = nodeId, Validated = true }; var id = (uint)nodeId.Identifier; // find register var registerId = (int)((id & 0xFF000000) >> 24); var index = (int)(id & 0x00FFFFFF); if (registerId == 0) { var register = _system.GetRegister(index); if (register == null) { return null; } handle.Node = ModelUtils.GetRegister(register, NamespaceIndex); } // find register variable. else { var register = _system.GetRegister(registerId); if (register == null) { return null; } // find register variable. var variable = ModelUtils.GetRegisterVariable(register, index, NamespaceIndex); if (variable == null) { return null; } handle.Node = variable; } return handle; } } /// /// Verifies that the specified node exists. /// /// /// /// protected override NodeState ValidateNode( ServerSystemContext context, NodeHandle handle, IDictionary cache) { // not valid if no root. if (handle == null) { return null; } // check if previously validated. if (handle.Validated) { return handle.Node; } // TBD return null; } protected override void OnCreateMonitoredItemsComplete(ServerSystemContext context, IList monitoredItems) { for (var ii = 0; ii < monitoredItems.Count; ii++) { var handle = IsHandleInNamespace(monitoredItems[ii].ManagerHandle); if (handle == null) { continue; } var variable = handle.Node as BaseVariableState; if (handle.Node.Handle is MemoryRegister register) { register.Subscribe((int)variable.NumericId, (IDataChangeMonitoredItem2)monitoredItems[ii]); } } } protected override void OnDeleteMonitoredItemsComplete(ServerSystemContext context, IList monitoredItems) { for (var ii = 0; ii < monitoredItems.Count; ii++) { var handle = IsHandleInNamespace(monitoredItems[ii].ManagerHandle); if (handle == null) { continue; } var variable = handle.Node as BaseVariableState; if (handle.Node.Handle is MemoryRegister register) { register.Unsubscribe((int)variable.NumericId, (IDataChangeMonitoredItem2)monitoredItems[ii]); } } } #pragma warning disable IDE0052 // Remove unread private members private readonly PerfTestServerConfiguration _configuration; #pragma warning restore IDE0052 // Remove unread private members private readonly UnderlyingSystem _system; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/PerfTest/PerfTestServer.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace PerfTest { using Opc.Ua; using Opc.Ua.Server; /// public class PerfTestServer : INodeManagerFactory { /// public StringCollection NamespacesUris { get { return [ Namespaces.PerfTest ]; } } /// public INodeManager Create(IServerInternal server, ApplicationConfiguration configuration) { return new PerfTestNodeManager(server, configuration); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/PerfTest/PerfTestServerConfiguration.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace PerfTest { using System.Runtime.Serialization; /// /// Stores the configuration the data access node manager. /// [DataContract(Namespace = Namespaces.PerfTest)] public class PerfTestServerConfiguration { /// /// The default constructor. /// public PerfTestServerConfiguration() { Initialize(); } /// /// Initializes the object during deserialization. /// /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/PerfTest/UnderlyingSystem.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace PerfTest { using Opc.Ua; using Opc.Ua.Server; using System; using System.Collections.Generic; using System.Threading; public class UnderlyingSystem { public void Initialize() { _registers = []; var register1 = new MemoryRegister(); register1.Initialize(1, "R1", 50000); _registers.Add(register1); } public IList Registers => _registers; public MemoryRegister GetRegister(int id) { if (id > 0 && id <= _registers.Count) { return _registers[id - 1]; } return null; } private List _registers; } public class MemoryRegister { public int Id { get; private set; } public string Name { get; private set; } public int Size => _values.Length; public void Initialize(int id, string name, int size) { Id = id; Name = name; _values = new int[size]; _monitoredItems = new IDataChangeMonitoredItem2[size][]; } public int Read(int index) { if (index >= 0 && index < _values.Length) { return _values[index]; } return 0; } public void Subscribe(int index, IDataChangeMonitoredItem2 monitoredItem) { lock (_lock) { _timer ??= new Timer(OnUpdate, null, 45, 45); if (index >= 0 && index < _values.Length) { var monitoredItems = _monitoredItems[index]; if (monitoredItems == null) { _monitoredItems[index] = monitoredItems = new IDataChangeMonitoredItem2[1]; } else { _monitoredItems[index] = new IDataChangeMonitoredItem2[monitoredItems.Length + 1]; Array.Copy(monitoredItems, _monitoredItems[index], monitoredItems.Length); monitoredItems = _monitoredItems[index]; } monitoredItems[^1] = monitoredItem; } } } public void Unsubscribe(int index, IDataChangeMonitoredItem2 monitoredItem) { lock (_lock) { if (index >= 0 && index < _values.Length) { var monitoredItems = _monitoredItems[index]; if (monitoredItems != null) { for (var ii = 0; ii < monitoredItems.Length; ii++) { if (ReferenceEquals(monitoredItems[ii], monitoredItem)) { _monitoredItems[index] = new IDataChangeMonitoredItem2[monitoredItems.Length - 1]; if (ii > 0) { Array.Copy(monitoredItems, _monitoredItems[index], ii); } if (ii < monitoredItems.Length - 1) { Array.Copy(monitoredItems, ii + 1, _monitoredItems[index], 0, monitoredItems.Length - ii - 1); } break; } } } } } } private void OnUpdate(object state) { try { lock (_lock) { var start = HiResClock.UtcNow; var delta = _values.Length / 2; var value = new DataValue { ServerTimestamp = DateTime.UtcNow, SourceTimestamp = DateTime.UtcNow }; for (var ii = _start; ii < delta + _start && ii < _values.Length; ii++) { _values[ii] += ii + 1; var monitoredItems = _monitoredItems[ii]; if (monitoredItems != null) { value.WrappedValue = new Variant(_values[ii]); for (var jj = 0; jj < monitoredItems.Length; jj++) { monitoredItems[jj].QueueValue(value, null, true); } } } _start += delta; if (_start >= _values.Length) { _start = 0; } if ((HiResClock.UtcNow - start).TotalMilliseconds > 50) { Utils.Trace("Update took {0}ms.", (HiResClock.UtcNow - start).TotalMilliseconds); } } } catch (Exception e) { Utils.Trace(e, "Unexpected error updating items."); } } private readonly Lock _lock = new(); private int[] _values; private int _start; private Timer _timer; private IDataChangeMonitoredItem2[][] _monitoredItems; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/Models/BaseDataVariableStateExtended.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Plc { using Opc.Ua; using System; /// /// Extended BaseDataVariableState class to hold additional parameters for simulation. /// public class BaseDataVariableStateExtended : BaseDataVariableState { public bool Randomize { get; } public object StepSize { get; } public object MinValue { get; } public object MaxValue { get; } public BaseDataVariableStateExtended(NodeState nodeState, bool randomize, object stepSize, object minValue, object maxValue) : base(nodeState) { ArgumentNullException.ThrowIfNull(nodeState); Randomize = randomize; StepSize = stepSize ?? throw new ArgumentNullException(nameof(stepSize)); MinValue = minValue ?? throw new ArgumentNullException(nameof(minValue)); MaxValue = maxValue ?? throw new ArgumentNullException(nameof(maxValue)); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/Models/IPluginNodes.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Plc.PluginNodes.Models { using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Test; using System.Collections.Generic; public interface IPluginNodes { uint ScaleUnits { get; set; } ILogger Logger { get; set; } TimeService TimeService { get; set; } IReadOnlyCollection Nodes { get; } void AddToAddressSpace(FolderState telemetryFolder, FolderState methodsFolder, PlcNodeManager plcNodeManager); void StartSimulation(); void StopSimulation(); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/Models/NodeWithIntervals.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Plc.PluginNodes.Models { using Opc.Ua; public sealed class NodeWithIntervals { public string NodeId { get; set; } public string NodeIdTypePrefix { get; set; } = "s"; public string Namespace { get; set; } public uint PublishingInterval { get; set; } public uint SamplingInterval { get; set; } internal static string GetPrefix(IdType idType) { switch (idType) { case IdType.Numeric: return "i"; case IdType.Guid: return "g"; case IdType.Opaque: return "b"; default: return "s"; } } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/Models/SimulatedVariableNode.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Plc { using Opc.Ua; using Opc.Ua.Test; using System; public sealed class SimulatedVariableNode : IDisposable { private readonly ISystemContext _context; private readonly BaseDataVariableState _variable; private ITimer _timer; private readonly TimeService _timeService; public T Value { get => (T)_variable.Value; set => SetValue(_variable, value); } public SimulatedVariableNode(ISystemContext context, BaseDataVariableState variable, TimeService timeService) { _context = context; _variable = variable; _timeService = timeService; } public void Dispose() { Stop(); _timer.Dispose(); } /// /// Start periodic update. /// The update Func gets the current value as input and should return the updated value. /// /// /// public void Start(Func update, int periodMs) { _timer = _timeService.NewTimer((s, o) => Value = update(Value), (uint)periodMs); } public void Stop() { if (_timer == null) { return; } _timer.Enabled = false; } private void SetValue(BaseDataVariableState variable, T value) { variable.Value = value; variable.Timestamp = _timeService.Now; variable.ClearChangeMasks(_context, false); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/NamespaceType.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Plc { public enum NamespaceType { PlcApplications, PlcSimulation, PlcInstance, } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/Namespaces.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Plc { /// /// Defines constants for namespaces used by the application. /// public static class Namespaces { /// /// The namespace for the nodes provided by for boiler type. /// public const string PlcSimulation = "http://opcfoundation.org/UA/Plc"; /// /// The namespace for the nodes provided by the for the boiler instance. /// public const string PlcInstance = "http://opcfoundation.org/UA/Plc/PlcInstance"; /// /// The namespace for the nodes provided by the plc server. /// public const string PlcApplications = "http://opcfoundation.org/UA/Plc/Applications"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/PlcNodeManager.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Plc { using Plc.PluginNodes; using Plc.PluginNodes.Models; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Server; using Opc.Ua.Test; using System; using System.Collections.Generic; using System.Globalization; public class PlcNodeManager : CustomNodeManager2 { public IEnumerable PluginNodes { get; } public PlcNodeManager(IServerInternal server, ApplicationConfiguration configuration, TimeService timeService, ILogger logger, uint scaleunits) : base(server, configuration, [ Namespaces.PlcApplications, Namespaces.PlcSimulation, Namespaces.PlcInstance ]) { _timeService = timeService; _logger = logger; SystemContext.NodeIdFactory = this; PluginNodes = new List { new ComplexTypePlcPluginNode(), new DataPluginNodes(), new DeterministicGuidPluginNodes(), new DipPluginNode(), new FastPluginNodes(), new FastRandomPluginNodes(), new LongIdPluginNode(), new LongStringPluginNodes(), new NegTrendPluginNode(), new PosTrendPluginNode(), new SlowPluginNodes(), new SlowRandomPluginNodes(), new SpecialCharNamePluginNode(), new SpikePluginNode() }; foreach (var plugin in PluginNodes) { plugin.Logger = logger; plugin.TimeService = timeService; plugin.ScaleUnits = scaleunits; } _simulation = new PlcSimulation(this, timeService); } protected override void Dispose(bool disposing) { _simulation.Stop(); base.Dispose(disposing); } public string GetPnJson() { return _simulation.GetPublisherConfigJson(); } /// /// Creates the NodeId for the specified node. /// /// /// public override NodeId New(ISystemContext context, NodeState node) { if (node is BaseInstanceState instance && instance.Parent?.NodeId.Identifier is string id) { return new NodeId(id + "_" + instance.SymbolicName, instance.Parent.NodeId.NamespaceIndex); } return node.NodeId; } /// /// Does any initialization required before the address space can be used. /// /// /// /// The externalReferences is an out parameter that allows the node manager to link to nodes /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and /// should have a reference to the root folder node(s) exposed by this node manager. /// public override void CreateAddressSpace(IDictionary> externalReferences) { lock (Lock) { if (!externalReferences.TryGetValue(ObjectIds.ObjectsFolder, out var references)) { externalReferences[ObjectIds.ObjectsFolder] = references = []; } _externalReferences = externalReferences; var root = CreateFolder(null, "OpcPlc", "OpcPlc", NamespaceType.PlcApplications); root.AddReference(ReferenceTypes.Organizes, true, ObjectIds.ObjectsFolder); references.Add(new NodeStateReference(ReferenceTypes.Organizes, false, root.NodeId)); root.EventNotifier = EventNotifiers.SubscribeToEvents; AddRootNotifier(root); try { var telemetryFolder = CreateFolder(root, "Telemetry", "Telemetry", NamespaceType.PlcApplications); var methodsFolder = CreateFolder(root, "Methods", "Methods", NamespaceType.PlcApplications); // Add nodes to address space from plugin nodes list. foreach (var plugin in PluginNodes) { plugin.AddToAddressSpace(telemetryFolder, methodsFolder, plcNodeManager: this); } } catch (Exception e) { _logger.AddressSpaceError(e); } AddPredefinedNode(SystemContext, root); } _simulation.Start(); } public SimulatedVariableNode CreateVariableNode(BaseDataVariableState variable) { return new SimulatedVariableNode(SystemContext, variable, _timeService); } /// /// Creates a new folder. /// /// /// /// /// public FolderState CreateFolder(NodeState parent, string path, string name, NamespaceType namespaceType) { var existingFolder = parent?.FindChildBySymbolicName(SystemContext, name); if (existingFolder != null) { return (FolderState)existingFolder; } var namespaceIndex = NamespaceIndexes[(int)namespaceType]; var folder = new FolderState(parent) { SymbolicName = name, ReferenceTypeId = ReferenceTypes.Organizes, TypeDefinitionId = ObjectTypeIds.FolderType, NodeId = new NodeId(path, namespaceIndex), BrowseName = new QualifiedName(path, namespaceIndex), DisplayName = new LocalizedText("en", name), WriteMask = AttributeWriteMask.None, UserWriteMask = AttributeWriteMask.None, EventNotifier = EventNotifiers.None }; parent?.AddChild(folder); return folder; } /// /// Creates a new extended variable. /// /// /// /// /// /// /// /// /// /// /// /// /// /// public BaseDataVariableState CreateBaseVariable(NodeState parent, dynamic path, string name, NodeId dataType, int valueRank, byte accessLevel, string description, NamespaceType namespaceType, bool randomize, object stepSizeValue, object minTypeValue, object maxTypeValue, object defaultValue = null) { var baseDataVariableState = new BaseDataVariableStateExtended(parent, randomize, stepSizeValue, minTypeValue, maxTypeValue) { SymbolicName = name, ReferenceTypeId = ReferenceTypes.Organizes, TypeDefinitionId = VariableTypeIds.BaseDataVariableType }; return CreateBaseVariable(baseDataVariableState, parent, path, name, dataType, valueRank, accessLevel, description, namespaceType, defaultValue); } /// /// Creates a new variable. /// /// /// /// /// /// /// /// /// /// public BaseDataVariableState CreateBaseVariable(NodeState parent, dynamic path, string name, NodeId dataType, int valueRank, byte accessLevel, string description, NamespaceType namespaceType, object defaultValue = null) { var baseDataVariableState = new BaseDataVariableState(parent) { SymbolicName = name, ReferenceTypeId = ReferenceTypes.Organizes, TypeDefinitionId = VariableTypeIds.BaseDataVariableType }; return CreateBaseVariable(baseDataVariableState, parent, path, name, dataType, valueRank, accessLevel, description, namespaceType, defaultValue); } /// /// Creates a new method. /// /// /// /// /// /// public MethodState CreateMethod(NodeState parent, string path, string name, string description, NamespaceType namespaceType) { var namespaceIndex = NamespaceIndexes[(int)namespaceType]; var method = new MethodState(parent) { SymbolicName = name, ReferenceTypeId = ReferenceTypeIds.HasComponent, NodeId = new NodeId(path, namespaceIndex), BrowseName = new QualifiedName(path, namespaceIndex), DisplayName = new LocalizedText("en", name), WriteMask = AttributeWriteMask.None, UserWriteMask = AttributeWriteMask.None, Executable = true, UserExecutable = true, Description = new LocalizedText(description) }; parent?.AddChild(method); return method; } private BaseDataVariableState CreateBaseVariable(BaseDataVariableState baseDataVariableState, NodeState parent, dynamic path, string name, NodeId dataType, int valueRank, byte accessLevel, string description, NamespaceType namespaceType, object defaultValue = null) { var namespaceIndex = NamespaceIndexes[(int)namespaceType]; if (path is uint || path is long) { baseDataVariableState.NodeId = new NodeId((uint)path, namespaceIndex); baseDataVariableState.BrowseName = new QualifiedName(((uint)path) .ToString(CultureInfo.CurrentCulture), namespaceIndex); } else if (path is string) { baseDataVariableState.NodeId = new NodeId(path, namespaceIndex); baseDataVariableState.BrowseName = new QualifiedName(path, namespaceIndex); } else { _logger.NodeIdType((string)path.GetType().ToString()); baseDataVariableState.NodeId = new NodeId(path, namespaceIndex); baseDataVariableState.BrowseName = new QualifiedName(name, namespaceIndex); } baseDataVariableState.DisplayName = new LocalizedText("en", name); baseDataVariableState.WriteMask = AttributeWriteMask.DisplayName | AttributeWriteMask.Description; baseDataVariableState.UserWriteMask = AttributeWriteMask.DisplayName | AttributeWriteMask.Description; baseDataVariableState.DataType = dataType; baseDataVariableState.ValueRank = valueRank; baseDataVariableState.AccessLevel = accessLevel; baseDataVariableState.UserAccessLevel = accessLevel; baseDataVariableState.Historizing = false; baseDataVariableState.Value = defaultValue ?? TypeInfo.GetDefaultValue(dataType, valueRank, Server.TypeTree); baseDataVariableState.StatusCode = StatusCodes.Good; baseDataVariableState.Timestamp = _timeService.UtcNow; baseDataVariableState.Description = new LocalizedText(description); if (valueRank == ValueRanks.OneDimension) { baseDataVariableState.ArrayDimensions = new ReadOnlyList([0]); } else if (valueRank == ValueRanks.TwoDimensions) { baseDataVariableState.ArrayDimensions = new ReadOnlyList([0, 0]); } parent?.AddChild(baseDataVariableState); return baseDataVariableState; } /// /// Loads a predefined node set by using the specified handler. /// /// public void LoadPredefinedNodes(Func loadPredefinedNodeshandler) { _loadPredefinedNodeshandler = loadPredefinedNodeshandler; base.LoadPredefinedNodes(SystemContext, _externalReferences); } /// /// Adds a predefined node set. /// /// public void AddPredefinedNode(NodeState node) { base.AddPredefinedNode(SystemContext, node); } protected override NodeStateCollection LoadPredefinedNodes(ISystemContext context) { return _loadPredefinedNodeshandler?.Invoke(context); } private readonly TimeService _timeService; private readonly ILogger _logger; private IDictionary> _externalReferences; private Func _loadPredefinedNodeshandler; private readonly PlcSimulation _simulation; } /// /// Source-generated logging definitions for PlcNodeManager /// internal static partial class PlcNodeManagerLogging { private const int EventClass = 50; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Error, Message = "Error creating address space.")] public static partial void AddressSpaceError(this ILogger logger, Exception e); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Debug, Message = "NodeId type is {NodeIdType}")] public static partial void NodeIdType(this ILogger logger, string nodeIdType); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/PlcServer.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Plc { using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Server; using Opc.Ua.Test; /// public class PlcServer : INodeManagerFactory { /// public StringCollection NamespacesUris { get { return [ Namespaces.PlcApplications, Namespaces.PlcSimulation, Namespaces.PlcInstance ]; } } /// public PlcServer(TimeService timeservice, ILogger logger, uint scaleunits) { _timeservice = timeservice; _logger = logger; _scaleunits = scaleunits; } /// public INodeManager Create(IServerInternal server, ApplicationConfiguration configuration) { return new PlcNodeManager(server, configuration, _timeservice, _logger, _scaleunits); } private readonly TimeService _timeservice; private readonly ILogger _logger; private readonly uint _scaleunits; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/PlcSimulation.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Plc { using Opc.Ua; using Opc.Ua.Test; using System; using System.Diagnostics; using System.Text; using System.Text.Encodings.Web; using System.Text.Json; using System.Timers; public class PlcSimulation { public static uint EventInstanceCount { get; set; } = 1; /// /// ms. /// public static uint EventInstanceRate { get; set; } = 1000; /// /// Simulation data. /// public static int SimulationCycleCount { get; set; } = kSimulationCycleCountDefault; public static int SimulationCycleLength { get; set; } = kSimulationCycleLengthDefault; /// /// Ctor for simulation server. /// /// /// public PlcSimulation(PlcNodeManager plcNodeManager, TimeService timeService) { _plcNodeManager = plcNodeManager; _timeService = timeService; } /// /// Start the simulation. /// public void Start() { if (EventInstanceCount > 0) { _eventInstanceGenerator = EventInstanceRate >= 50 || !Stopwatch.IsHighResolution ? _timeService.NewTimer(UpdateEventInstances, EventInstanceRate) : _timeService.NewFastTimer(UpdateVeryFastEventInstances, EventInstanceRate); } // Start simulation of nodes from plugin nodes list. foreach (var plugin in _plcNodeManager.PluginNodes) { plugin.StartSimulation(); } } /// /// Stop the simulation. /// public void Stop() { Disable(_eventInstanceGenerator); // Stop simulation of nodes from plugin nodes list. foreach (var plugin in _plcNodeManager.PluginNodes) { plugin.StopSimulation(); } } private void UpdateEventInstances(object state, ElapsedEventArgs elapsedEventArgs) { UpdateEventInstances(); } private void UpdateVeryFastEventInstances(object state, FastTimerElapsedEventArgs elapsedEventArgs) { UpdateEventInstances(); } private void UpdateEventInstances() { var eventInstanceCycle = _eventInstanceCycle++; for (uint i = 0; i < EventInstanceCount; i++) { var e = new BaseEventState(null); var info = new TranslationInfo( "EventInstanceCycleEventKey", "en-us", "Event with index '{0}' and event cycle '{1}'", i, eventInstanceCycle); e.Initialize( _plcNodeManager.SystemContext, source: null, EventSeverity.Medium, new LocalizedText(info)); e.SetChildValue(_plcNodeManager.SystemContext, BrowseNames.SourceName, "System", false); e.SetChildValue(_plcNodeManager.SystemContext, BrowseNames.SourceNode, ObjectIds.Server, false); _plcNodeManager.Server.ReportEvent(e); } } private static void Disable(ITimer timer) { if (timer == null) { return; } timer.Enabled = false; } /// /// Get pn.json /// public string GetPublisherConfigJson() { var sb = new StringBuilder(); sb.Append(Environment.NewLine) .AppendLine("[") .AppendLine(" {") .AppendLine(" \"EndpointUrl\": \"{{EndpointUrl}}\",") .AppendLine(" \"UseSecurity\": true,") .AppendLine(" \"OpcNodes\": ["); // Print config from plugin nodes list. foreach (var plugin in _plcNodeManager.PluginNodes) { foreach (var node in plugin.Nodes) { // Show only if > 0 and != 1000 ms. var publishingInterval = node.PublishingInterval > 0 && node.PublishingInterval != 1000 ? $", \"OpcPublishingInterval\": {node.PublishingInterval}" : string.Empty; // Show only if > 0 ms. var samplingInterval = node.SamplingInterval > 0 ? $", \"OpcSamplingInterval\": {node.SamplingInterval}" : string.Empty; var nodeId = JsonEncodedText.Encode(node.NodeId, JavaScriptEncoder.Default).ToString(); sb.Append(" { \"Id\": \"nsu=") .Append(node.Namespace) .Append(';') .Append(node.NodeIdTypePrefix) .Append('=') .Append(nodeId) .Append('\"') .Append(publishingInterval) .Append(samplingInterval) .AppendLine(" },") ; } } var trimLen = Environment.NewLine.Length + 1; sb .Remove(sb.Length - trimLen, trimLen) .Append(Environment.NewLine).AppendLine(" ]") .AppendLine(" }") .AppendLine("]"); // Trim trailing ,\n. return sb.ToString(); } /// /// in cycles /// private const int kSimulationCycleCountDefault = 50; /// /// in msec /// private const int kSimulationCycleLengthDefault = 100; private readonly PlcNodeManager _plcNodeManager; private readonly TimeService _timeService; private ITimer _eventInstanceGenerator; private uint _eventInstanceCycle; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/PluginNodes/ComplexTypePluginNode.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Plc.PluginNodes { using Plc.PluginNodes.Models; using PlcModel; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Test; using System; using System.Collections.Generic; using System.Reflection; using System.Timers; /// /// Complex type boiler node. /// public sealed class ComplexTypePlcPluginNode : IPluginNodes, IDisposable { public IReadOnlyCollection Nodes { get; private set; } = new List(); public TimeService TimeService { get; set; } public ILogger Logger { get; set; } public uint ScaleUnits { get; set; } private PlcNodeManager _plcNodeManager; private PlcState _node; private ITimer _nodeGenerator; public void AddToAddressSpace(FolderState telemetryFolder, FolderState methodsFolder, PlcNodeManager plcNodeManager) { _plcNodeManager = plcNodeManager; AddNodes(methodsFolder); } public void Dispose() { _node.Dispose(); _nodeGenerator.Dispose(); } public void StartSimulation() { _nodeGenerator = TimeService.NewTimer(UpdatePlc1, 1000); } public void StopSimulation() { if (_nodeGenerator != null) { _nodeGenerator.Enabled = false; } } private void AddNodes(FolderState methodsFolder) { // Load complex types from binary uanodes file. _plcNodeManager.LoadPredefinedNodes(LoadPredefinedNodes); // Find the Plc1 node that was created when the model was loaded. var passiveNode = (BaseObjectState)_plcNodeManager.FindPredefinedNode( new NodeId(PlcModel.Objects.Plc1, _plcNodeManager.NamespaceIndexes[(int)NamespaceType.PlcSimulation]), typeof(BaseObjectState)); // Convert to node that can be manipulated within the server. _node = new PlcState(null); _node.Create(_plcNodeManager.SystemContext, passiveNode); _node.PlcStatus.Value = new PlcDataType(); _plcNodeManager.AddPredefinedNode(_node); // Create heater on/off methods. var heaterOnMethod = _plcNodeManager.CreateMethod( methodsFolder, path: "HeaterOn", name: "HeaterOn", "Turn the heater on", NamespaceType.PlcSimulation); SetHeaterOnMethodProperties(ref heaterOnMethod); var heaterOffMethod = _plcNodeManager.CreateMethod( methodsFolder, path: "HeaterOff", name: "HeaterOff", "Turn the heater off", NamespaceType.PlcSimulation); SetHeaterOffMethodProperties(ref heaterOffMethod); Nodes = new List { new() { NodeId = "Plc", Namespace = Plc.Namespaces.PlcSimulation } }; } /// /// Loads a node set from a file or resource and adds them to the set of predefined nodes. /// /// private NodeStateCollection LoadPredefinedNodes(ISystemContext context) { var type = GetType().GetTypeInfo(); var predefinedNodes = new NodeStateCollection(); predefinedNodes.LoadFromBinaryResource(context, $"{type.Assembly.GetName().Name}.Generated.Plc.Design.PlcModel.PredefinedNodes.uanodes", typeof(PlcNodeManager).GetTypeInfo().Assembly, updateTables: true); return predefinedNodes; } private void UpdatePlc1(object state, ElapsedEventArgs elapsedEventArgs) { var newValue = new PlcDataType { HeaterState = _node.PlcStatus.Value.HeaterState }; var currentTemperatureBottom = _node.PlcStatus.Value.Temperature.Bottom; var newTemperature = newValue.Temperature; if (_node.PlcStatus.Value.HeaterState == PlcHeaterStateType.On) { // Heater on, increase by 1. newTemperature.Bottom = currentTemperatureBottom + 1; } else { // Heater off, decrease down to a minimum of 20. newTemperature.Bottom = currentTemperatureBottom > 20 ? currentTemperatureBottom - 1 : currentTemperatureBottom; } // Top is always 5 degrees less than bottom, with a minimum value of 20. newTemperature.Top = Math.Max(20, newTemperature.Bottom - 5); // Pressure is always 100_000 + bottom temperature. newValue.Pressure = 100_000 + newTemperature.Bottom; // Change complex value in one atomic step. _node.PlcStatus.Value = newValue; _node.PlcStatus.ClearChangeMasks(_plcNodeManager.SystemContext, includeChildren: true); } private void SetHeaterOnMethodProperties(ref MethodState method) { method.OnCallMethod += OnHeaterOnCall; } private void SetHeaterOffMethodProperties(ref MethodState method) { method.OnCallMethod += OnHeaterOffCall; } /// /// Method to turn the heater on. Executes synchronously. /// /// /// /// /// private ServiceResult OnHeaterOnCall(ISystemContext context, MethodState method, IList inputArguments, IList outputArguments) { _node.PlcStatus.Value.HeaterState = PlcHeaterStateType.On; Logger.LogDebug("OnHeaterOnCall method called"); return ServiceResult.Good; } /// /// Method to turn the heater off. Executes synchronously. /// /// /// /// /// private ServiceResult OnHeaterOffCall(ISystemContext context, MethodState method, IList inputArguments, IList outputArguments) { _node.PlcStatus.Value.HeaterState = PlcHeaterStateType.Off; Logger.LogDebug("OnHeaterOffCall method called"); return ServiceResult.Good; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/PluginNodes/DataPluginNodes.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Plc.PluginNodes { using Plc.PluginNodes.Models; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Test; using System; using System.Collections.Generic; /// /// Nodes with values: Cycling step-up, alternating boolean, random signed 32-bit integer and random unsigend 32-bit integer. /// public class DataPluginNodes : IPluginNodes { public IReadOnlyCollection Nodes { get; private set; } = new List(); public TimeService TimeService { get; set; } public ILogger Logger { get; set; } public uint ScaleUnits { get; set; } public void AddToAddressSpace(FolderState telemetryFolder, FolderState methodsFolder, PlcNodeManager plcNodeManager) { _plcNodeManager = plcNodeManager; var folder = _plcNodeManager.CreateFolder( telemetryFolder, path: "Basic", name: "Basic", NamespaceType.PlcApplications); AddNodes(folder); AddMethods(methodsFolder); } public void StartSimulation() { _stepUpCycleInPhase = PlcSimulation.SimulationCycleCount; _stepUpStarted = true; _alternatingBooleanCycleInPhase = PlcSimulation.SimulationCycleCount; _stepUpNode.Start(StepUpGenerator, PlcSimulation.SimulationCycleLength); _alternatingBooleanNode.Start(AlternatingBooleanGenerator, PlcSimulation.SimulationCycleLength); #pragma warning disable CA5394 // Do not use insecure randomness _randomSignedInt32.Start(_ => _random.Next(int.MinValue, int.MaxValue), PlcSimulation.SimulationCycleLength); #pragma warning restore CA5394 // Do not use insecure randomness #pragma warning disable CA5394 // Do not use insecure randomness _randomUnsignedInt32.Start(_ => (uint)_random.Next(), PlcSimulation.SimulationCycleLength); #pragma warning restore CA5394 // Do not use insecure randomness } public void StopSimulation() { _stepUpNode.Stop(); _alternatingBooleanNode.Stop(); _randomSignedInt32.Stop(); _randomUnsignedInt32.Stop(); } private void AddNodes(FolderState folder) { _stepUpNode = _plcNodeManager.CreateVariableNode( _plcNodeManager.CreateBaseVariable( folder, path: "StepUp", name: "StepUp", new NodeId((uint)BuiltInType.UInt32), ValueRanks.Scalar, AccessLevels.CurrentReadOrWrite, "Constantly increasing value", NamespaceType.PlcApplications)); _alternatingBooleanNode = _plcNodeManager.CreateVariableNode( _plcNodeManager.CreateBaseVariable( folder, path: "AlternatingBoolean", name: "AlternatingBoolean", new NodeId((uint)BuiltInType.Boolean), ValueRanks.Scalar, AccessLevels.CurrentRead, "Alternating boolean value", NamespaceType.PlcApplications)); _randomSignedInt32 = _plcNodeManager.CreateVariableNode( _plcNodeManager.CreateBaseVariable( folder, path: "RandomSignedInt32", name: "RandomSignedInt32", new NodeId((uint)BuiltInType.Int32), ValueRanks.Scalar, AccessLevels.CurrentRead, "Random signed 32 bit integer value", NamespaceType.PlcApplications)); _randomUnsignedInt32 = _plcNodeManager.CreateVariableNode( _plcNodeManager.CreateBaseVariable( folder, path: "RandomUnsignedInt32", "RandomUnsignedInt32", new NodeId((uint)BuiltInType.UInt32), ValueRanks.Scalar, AccessLevels.CurrentRead, "Random unsigned 32 bit integer value", NamespaceType.PlcApplications)); Nodes = new List { new() { NodeId = "StepUp", Namespace = Plc.Namespaces.PlcApplications }, new() { NodeId = "AlternatingBoolean", Namespace = Plc.Namespaces.PlcApplications }, new() { NodeId = "RandomSignedInt32", Namespace = Plc.Namespaces.PlcApplications }, new() { NodeId = "RandomUnsignedInt32", Namespace = Plc.Namespaces.PlcApplications } }; } private void AddMethods(FolderState parentFolder) { var resetStepUpMethod = _plcNodeManager.CreateMethod(parentFolder, "ResetStepUp", "ResetStepUp", "Resets the StepUp counter to 0", NamespaceType.PlcApplications); SetResetStepUpMethodProperties(ref resetStepUpMethod); var startStepUpMethod = _plcNodeManager.CreateMethod(parentFolder, "StartStepUp", "StartStepUp", "Starts the StepUp counter", NamespaceType.PlcApplications); SetStartStepUpMethodProperties(ref startStepUpMethod); var stopStepUpMethod = _plcNodeManager.CreateMethod(parentFolder, "StopStepUp", "StopStepUp", "Stops the StepUp counter", NamespaceType.PlcApplications); SetStopStepUpMethodProperties(ref stopStepUpMethod); } private void SetResetStepUpMethodProperties(ref MethodState method) { method.OnCallMethod += OnResetStepUpCall; } private void SetStartStepUpMethodProperties(ref MethodState method) { method.OnCallMethod += OnStartStepUpCall; } private void SetStopStepUpMethodProperties(ref MethodState method) { method.OnCallMethod += OnStopStepUpCall; } /// /// Method to reset the stepup value. Executes synchronously. /// /// /// /// /// private ServiceResult OnResetStepUpCall(ISystemContext context, MethodState method, IList inputArguments, IList outputArguments) { ResetStepUpData(); Logger.LogDebug("ResetStepUp method called"); return ServiceResult.Good; } /// /// Method to start the stepup value. Executes synchronously. /// /// /// /// /// private ServiceResult OnStartStepUpCall(ISystemContext context, MethodState method, IList inputArguments, IList outputArguments) { StartStepUp(); Logger.LogDebug("StartStepUp method called"); return ServiceResult.Good; } /// /// Method to stop the stepup value. Executes synchronously. /// /// /// /// /// private ServiceResult OnStopStepUpCall(ISystemContext context, MethodState method, IList inputArguments, IList outputArguments) { StopStepUp(); Logger.LogDebug("StopStepUp method called"); return ServiceResult.Good; } /// /// Updates simulation values. Called each SimulationCycleLength msec. /// Using SimulationCycleCount cycles per simulation phase. /// /// private uint StepUpGenerator(uint value) { // increase step up value if (_stepUpStarted && (_stepUpCycleInPhase % (PlcSimulation.SimulationCycleCount / 50) == 0)) { value++; } // end of cycle: reset cycle count if (--_stepUpCycleInPhase == 0) { _stepUpCycleInPhase = PlcSimulation.SimulationCycleCount; } return value; } /// /// Updates simulation values. Called each SimulationCycleLength msec. /// Using SimulationCycleCount cycles per simulation phase. /// /// private bool AlternatingBooleanGenerator(bool value) { // calculate next boolean value var nextAlternatingBoolean = _alternatingBooleanCycleInPhase % PlcSimulation.SimulationCycleCount == 0 ? !value : value; if (value != nextAlternatingBoolean) { Logger.LogTrace("Data change to: {NextAlternatingBoolean}", nextAlternatingBoolean); } // end of cycle: reset cycle count if (--_alternatingBooleanCycleInPhase == 0) { _alternatingBooleanCycleInPhase = PlcSimulation.SimulationCycleCount; } return nextAlternatingBoolean; } /// /// Method implementation to reset the StepUp data. /// public void ResetStepUpData() { _stepUpNode.Value = 0; } /// /// Method implementation to start the StepUp. /// public void StartStepUp() { _stepUpStarted = true; } /// /// Method implementation to stop the StepUp. /// public void StopStepUp() { _stepUpStarted = false; } private PlcNodeManager _plcNodeManager; private SimulatedVariableNode _stepUpNode; private SimulatedVariableNode _alternatingBooleanNode; private SimulatedVariableNode _randomSignedInt32; private SimulatedVariableNode _randomUnsignedInt32; private readonly Random _random = new(); private bool _stepUpStarted; private int _stepUpCycleInPhase; private int _alternatingBooleanCycleInPhase; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/PluginNodes/DeterministicGuidPluginNodes.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Plc.PluginNodes { using Plc.PluginNodes.Models; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Test; using System.Collections.Generic; /// /// Nodes with deterministic GUIDs as ID. /// public class DeterministicGuidPluginNodes : IPluginNodes { public IReadOnlyCollection Nodes { get; private set; } = new List(); public TimeService TimeService { get; set; } public ILogger Logger { get; set; } public uint ScaleUnits { get; set; } private uint NodeCount => ScaleUnits == 0 ? 1u : ScaleUnits * 50; /// /// ms. /// private uint NodeRate { get; } = 1000; private NodeType NodeType { get; } = NodeType.UIntScalar; public void AddToAddressSpace(FolderState telemetryFolder, FolderState methodsFolder, PlcNodeManager plcNodeManager) { _plcNodeManager = plcNodeManager; var folder = _plcNodeManager.CreateFolder( telemetryFolder, path: "Deterministic GUID", name: "Deterministic GUID", NamespaceType.PlcApplications); AddNodes(folder); } public void StartSimulation() { foreach (var node in _nodes) { node.Start(value => value + 1, periodMs: 1000); } } public void StopSimulation() { foreach (var node in _nodes) { node.Stop(); } } private void AddNodes(FolderState folder) { _nodes = new SimulatedVariableNode[NodeCount]; var nodes = new List((int)NodeCount); if (NodeCount > 0) { Logger.LogInformation("Creating {NodeCount} GUID node(s) of type: {NodeType}", NodeCount, NodeType); Logger.LogInformation("Node values will change every {NodeRate} ms", NodeRate); } for (var i = 0; i < NodeCount; i++) { var id = DeterministicGuid.NewGuid().ToString(); _nodes[i] = _plcNodeManager.CreateVariableNode( _plcNodeManager.CreateBaseVariable( folder, path: id, name: id, new NodeId((uint)BuiltInType.UInt32), ValueRanks.Scalar, AccessLevels.CurrentReadOrWrite, "Constantly increasing value", NamespaceType.PlcApplications, defaultValue: (uint)0)); nodes.Add(new NodeWithIntervals { NodeId = id, Namespace = Plc.Namespaces.PlcApplications }); } Nodes = nodes; } private PlcNodeManager _plcNodeManager; private SimulatedVariableNode[] _nodes; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/PluginNodes/DipPluginNode.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Plc.PluginNodes { using Plc.PluginNodes.Models; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Test; using System; using System.Collections.Generic; /// /// Node with a sine wave value with a dip anomaly. /// public class DipPluginNode : IPluginNodes { public IReadOnlyCollection Nodes { get; private set; } = new List(); public TimeService TimeService { get; set; } public ILogger Logger { get; set; } public uint ScaleUnits { get; set; } public void AddToAddressSpace(FolderState telemetryFolder, FolderState methodsFolder, PlcNodeManager plcNodeManager) { _plcNodeManager = plcNodeManager; var folder = _plcNodeManager.CreateFolder( telemetryFolder, path: "Anomaly", name: "Anomaly", NamespaceType.PlcApplications); AddNodes(folder); } public void StartSimulation() { _dipCycleInPhase = PlcSimulation.SimulationCycleCount; #pragma warning disable CA5394 // Do not use insecure randomness _dipAnomalyCycle = _random.Next(PlcSimulation.SimulationCycleCount); #pragma warning restore CA5394 // Do not use insecure randomness Logger.LogTrace("First dip anomaly cycle: {DipAnomalyCycle}", _dipAnomalyCycle); _node.Start(DipGenerator, PlcSimulation.SimulationCycleLength); } public void StopSimulation() { _node.Stop(); } private void AddNodes(FolderState folder) { _node = _plcNodeManager.CreateVariableNode( _plcNodeManager.CreateBaseVariable( folder, path: "DipData", name: "DipData", new NodeId((uint)BuiltInType.Double), ValueRanks.Scalar, AccessLevels.CurrentRead, "Value with random dips", NamespaceType.PlcApplications)); Nodes = new List { new() { NodeId = "DipData", Namespace = Plc.Namespaces.PlcApplications } }; } /// /// Generates a sine wave with dips at a random cycle in the phase. /// Called each SimulationCycleLength msec. /// /// private double DipGenerator(double value) { // calculate next value double nextValue; if (_dipCycleInPhase == _dipAnomalyCycle) { nextValue = kSimulationMaxAmplitude * -10; Logger.LogTrace("Generate dip anomaly"); } else { nextValue = kSimulationMaxAmplitude * Math.Sin(2 * Math.PI / PlcSimulation.SimulationCycleCount * _dipCycleInPhase); } Logger.LogTrace("Spike cycle: {DipCycleInPhase} data: {NextValue}", _dipCycleInPhase, nextValue); // end of cycle: reset cycle count and calc next anomaly cycle if (--_dipCycleInPhase == 0) { _dipCycleInPhase = PlcSimulation.SimulationCycleCount; #pragma warning disable CA5394 // Do not use insecure randomness _dipAnomalyCycle = _random.Next(PlcSimulation.SimulationCycleCount); #pragma warning restore CA5394 // Do not use insecure randomness Logger.LogTrace("Next dip anomaly cycle: {AnomalyCycle}", _dipAnomalyCycle); } return nextValue; } private PlcNodeManager _plcNodeManager; private SimulatedVariableNode _node; private readonly Random _random = new(); private int _dipCycleInPhase; private int _dipAnomalyCycle; private const double kSimulationMaxAmplitude = 100.0; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/PluginNodes/FastPluginNodes.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Plc.PluginNodes { using Plc.PluginNodes.Models; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Test; using System.Collections.Generic; using System.Diagnostics; using System.Timers; /// /// Nodes with fast changing values. /// public class FastPluginNodes : IPluginNodes { public TimeService TimeService { get; set; } public IReadOnlyCollection Nodes { get; private set; } = new List(); private uint NodeCount => ScaleUnits == 0 ? 3u : ScaleUnits * 1000; public uint ScaleUnits { get; set; } /// /// ms. /// private uint NodeRate { get; } = 1000; private NodeType NodeType { get; } = NodeType.UIntScalar; private string NodeMinValue { get; } private string NodeMaxValue { get; } private string NodeStepSize { get; } = "1"; /// /// ms. /// private uint NodeSamplingInterval { get; } public ILogger Logger { get; set; } public void AddToAddressSpace(FolderState telemetryFolder, FolderState methodsFolder, PlcNodeManager plcNodeManager) { _plcNodeManager = plcNodeManager; _slowFastCommon = new SlowFastCommon(_plcNodeManager, TimeService, Logger); var folder = _plcNodeManager.CreateFolder( telemetryFolder, path: "Fast", name: "Fast", NamespaceType.PlcApplications); // Used for methods to limit the number of updates to a fixed count. var simulatorFolder = _plcNodeManager.CreateFolder( telemetryFolder.Parent, // Root. path: "SimulatorConfiguration", name: "SimulatorConfiguration", NamespaceType.PlcApplications); AddNodes(folder, simulatorFolder); AddMethods(methodsFolder); } private void AddMethods(FolderState methodsFolder) { var stopUpdateMethod = _plcNodeManager.CreateMethod( methodsFolder, path: "StopUpdateFastNodes", name: "StopUpdateFastNodes", "Stop the increase of value of fast nodes", NamespaceType.PlcApplications); SetStopUpdateFastNodesProperties(ref stopUpdateMethod); var startUpdateMethod = _plcNodeManager.CreateMethod( methodsFolder, path: "StartUpdateFastNodes", name: "StartUpdateFastNodes", "Start the increase of value of fast nodes", NamespaceType.PlcApplications); SetStartUpdateFastNodesProperties(ref startUpdateMethod); } public void StartSimulation() { // Only use the fast timers when we need to go really fast, // since they consume more resources and create an own thread. _nodeGenerator = NodeRate >= 50 || !Stopwatch.IsHighResolution ? TimeService.NewTimer(UpdateNodes, NodeRate) : TimeService.NewFastTimer(UpdateVeryFastNodes, NodeRate); } public void StopSimulation() { if (_nodeGenerator != null) { _nodeGenerator.Enabled = false; } } private void AddNodes(FolderState folder, FolderState simulatorFolder) { (_nodes, _badNodes) = _slowFastCommon.CreateNodes(NodeType, "Fast", NodeCount, folder, simulatorFolder, false, NodeStepSize, NodeMinValue, NodeMaxValue, NodeRate, NodeSamplingInterval); ExposeNodesWithIntervals(); } /// /// Expose node information for dumping pn.json. /// private void ExposeNodesWithIntervals() { var nodes = new List(); foreach (var node in _nodes) { nodes.Add(new NodeWithIntervals { NodeId = node.NodeId.Identifier.ToString(), NodeIdTypePrefix = NodeWithIntervals.GetPrefix(node.NodeId.IdType), Namespace = Plc.Namespaces.PlcApplications, PublishingInterval = NodeRate, SamplingInterval = NodeSamplingInterval }); } foreach (var node in _badNodes) { nodes.Add(new NodeWithIntervals { NodeId = node.NodeId.Identifier.ToString(), NodeIdTypePrefix = NodeWithIntervals.GetPrefix(node.NodeId.IdType), Namespace = Plc.Namespaces.PlcApplications, PublishingInterval = NodeRate, SamplingInterval = NodeSamplingInterval }); } Nodes = nodes; } private void SetStopUpdateFastNodesProperties(ref MethodState method) { method.OnCallMethod += OnStopUpdateFastNodes; } private void SetStartUpdateFastNodesProperties(ref MethodState method) { method.OnCallMethod += OnStartUpdateFastNodes; } /// /// Method to stop updating the fast nodes. /// /// /// /// /// private ServiceResult OnStopUpdateFastNodes(ISystemContext context, MethodState method, IList inputArguments, IList outputArguments) { _updateNodes = false; Logger.LogDebug("StopUpdateFastNodes method called"); return ServiceResult.Good; } /// /// Method to start updating the fast nodes. /// /// /// /// /// private ServiceResult OnStartUpdateFastNodes(ISystemContext context, MethodState method, IList inputArguments, IList outputArguments) { _updateNodes = true; Logger.LogDebug("StartUpdateFastNodes method called"); return ServiceResult.Good; } private void UpdateNodes(object state, ElapsedEventArgs elapsedEventArgs) { _slowFastCommon.UpdateNodes(_nodes, _badNodes, NodeType, _updateNodes); } private void UpdateVeryFastNodes(object state, FastTimerElapsedEventArgs elapsedEventArgs) { _slowFastCommon.UpdateNodes(_nodes, _badNodes, NodeType, _updateNodes); } private PlcNodeManager _plcNodeManager; private SlowFastCommon _slowFastCommon; private BaseDataVariableState[] _nodes; private BaseDataVariableState[] _badNodes; private ITimer _nodeGenerator; private bool _updateNodes = true; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/PluginNodes/FastRandomPluginNodes.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Plc.PluginNodes { using Plc.PluginNodes.Models; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Test; using System.Collections.Generic; using System.Diagnostics; using System.Timers; /// /// Nodes with fast changing values. /// public class FastRandomPluginNodes : IPluginNodes { public TimeService TimeService { get; set; } public IReadOnlyCollection Nodes { get; private set; } = new List(); private uint NodeCount => ScaleUnits == 0 ? 3u : ScaleUnits * 1000; public uint ScaleUnits { get; set; } /// /// ms. /// private uint NodeRate { get; } = 1000; private NodeType NodeType { get; } = NodeType.UIntScalar; private string NodeMinValue { get; } private string NodeMaxValue { get; } private string NodeStepSize { get; } = "1"; /// /// ms. /// private uint NodeSamplingInterval { get; } public ILogger Logger { get; set; } public void AddToAddressSpace(FolderState telemetryFolder, FolderState methodsFolder, PlcNodeManager plcNodeManager) { _plcNodeManager = plcNodeManager; _slowFastCommon = new SlowFastCommon(_plcNodeManager, TimeService, Logger); var folder = _plcNodeManager.CreateFolder( telemetryFolder, path: "Fast", name: "Fast", NamespaceType.PlcApplications); // Used for methods to limit the number of updates to a fixed count. var simulatorFolder = _plcNodeManager.CreateFolder( telemetryFolder.Parent, // Root. path: "SimulatorConfiguration", name: "SimulatorConfiguration", NamespaceType.PlcApplications); AddNodes(folder, simulatorFolder); AddMethods(methodsFolder); } private void AddMethods(FolderState methodsFolder) { var stopUpdateMethod = _plcNodeManager.CreateMethod( methodsFolder, path: "StopUpdateFastNodes", name: "StopUpdateFastNodes", "Stop the increase of value of fast nodes", NamespaceType.PlcApplications); SetStopUpdateFastNodesProperties(ref stopUpdateMethod); var startUpdateMethod = _plcNodeManager.CreateMethod( methodsFolder, path: "StartUpdateFastNodes", name: "StartUpdateFastNodes", "Start the increase of value of fast nodes", NamespaceType.PlcApplications); SetStartUpdateFastNodesProperties(ref startUpdateMethod); } public void StartSimulation() { // Only use the fast timers when we need to go really fast, // since they consume more resources and create an own thread. _nodeGenerator = NodeRate >= 50 || !Stopwatch.IsHighResolution ? TimeService.NewTimer(UpdateNodes, NodeRate) : TimeService.NewFastTimer(UpdateVeryFastNodes, NodeRate); } public void StopSimulation() { if (_nodeGenerator != null) { _nodeGenerator.Enabled = false; } } private void AddNodes(FolderState folder, FolderState simulatorFolder) { (_nodes, _badNodes) = _slowFastCommon.CreateNodes(NodeType, "FastRandom", NodeCount, folder, simulatorFolder, true, NodeStepSize, NodeMinValue, NodeMaxValue, NodeRate, NodeSamplingInterval); ExposeNodesWithIntervals(); } /// /// Expose node information for dumping pn.json. /// private void ExposeNodesWithIntervals() { var nodes = new List(); foreach (var node in _nodes) { nodes.Add(new NodeWithIntervals { NodeId = node.NodeId.Identifier.ToString(), NodeIdTypePrefix = NodeWithIntervals.GetPrefix(node.NodeId.IdType), Namespace = Plc.Namespaces.PlcApplications, PublishingInterval = NodeRate, SamplingInterval = NodeSamplingInterval }); } foreach (var node in _badNodes) { nodes.Add(new NodeWithIntervals { NodeId = node.NodeId.Identifier.ToString(), NodeIdTypePrefix = NodeWithIntervals.GetPrefix(node.NodeId.IdType), Namespace = Plc.Namespaces.PlcApplications, PublishingInterval = NodeRate, SamplingInterval = NodeSamplingInterval }); } Nodes = nodes; } private void SetStopUpdateFastNodesProperties(ref MethodState method) { method.OnCallMethod += OnStopUpdateFastNodes; } private void SetStartUpdateFastNodesProperties(ref MethodState method) { method.OnCallMethod += OnStartUpdateFastNodes; } /// /// Method to stop updating the fast nodes. /// /// /// /// /// private ServiceResult OnStopUpdateFastNodes(ISystemContext context, MethodState method, IList inputArguments, IList outputArguments) { _updateNodes = false; Logger.LogDebug("StopUpdateFastNodes method called"); return ServiceResult.Good; } /// /// Method to start updating the fast nodes. /// /// /// /// /// private ServiceResult OnStartUpdateFastNodes(ISystemContext context, MethodState method, IList inputArguments, IList outputArguments) { _updateNodes = true; Logger.LogDebug("StartUpdateFastNodes method called"); return ServiceResult.Good; } private void UpdateNodes(object state, ElapsedEventArgs elapsedEventArgs) { _slowFastCommon.UpdateNodes(_nodes, _badNodes, NodeType, _updateNodes); } private void UpdateVeryFastNodes(object state, FastTimerElapsedEventArgs elapsedEventArgs) { _slowFastCommon.UpdateNodes(_nodes, _badNodes, NodeType, _updateNodes); } private PlcNodeManager _plcNodeManager; private SlowFastCommon _slowFastCommon; private BaseDataVariableState[] _nodes; private BaseDataVariableState[] _badNodes; private ITimer _nodeGenerator; private bool _updateNodes = true; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/PluginNodes/LongIdPluginNode.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Plc.PluginNodes { using Plc.PluginNodes.Models; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Test; using System.Collections.Generic; using System.Text; /// /// Node with ID of 3950 chars. /// public class LongIdPluginNode : IPluginNodes { public IReadOnlyCollection Nodes { get; private set; } = new List(); public TimeService TimeService { get; set; } public ILogger Logger { get; set; } public uint ScaleUnits { get; set; } public void AddToAddressSpace(FolderState telemetryFolder, FolderState methodsFolder, PlcNodeManager plcNodeManager) { _plcNodeManager = plcNodeManager; var folder = _plcNodeManager.CreateFolder( telemetryFolder, path: "Special", name: "Special", NamespaceType.PlcApplications); AddNodes(folder); } public void StartSimulation() { _node.Start(value => value + 1, periodMs: 1000); } public void StopSimulation() { _node.Stop(); } private void AddNodes(FolderState folder) { // Repeat A-Z until 3950 chars are collected. var id = new StringBuilder(4000); for (var i = 0; i < 3950; i++) { id.Append((char)(65 + (i % 26))); } _node = _plcNodeManager.CreateVariableNode( _plcNodeManager.CreateBaseVariable( folder, path: id.ToString(), name: "LongId3950", new NodeId((uint)BuiltInType.UInt32), ValueRanks.Scalar, AccessLevels.CurrentReadOrWrite, "Constantly increasing value", NamespaceType.PlcApplications, defaultValue: (uint)0)); Nodes = new List { new() { NodeId = id.ToString(), Namespace = Plc.Namespaces.PlcApplications } }; } private PlcNodeManager _plcNodeManager; private SimulatedVariableNode _node; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/PluginNodes/LongStringPluginNodes.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Plc.PluginNodes { using Plc.PluginNodes.Models; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Test; using System; using System.Collections.Generic; using System.Text; /// /// Nodes that change value every second to string containing single repeated uppercase letter. /// public class LongStringPluginNodes : IPluginNodes { public IReadOnlyCollection Nodes { get; private set; } = new List(); public TimeService TimeService { get; set; } public ILogger Logger { get; set; } public uint ScaleUnits { get; set; } private PlcNodeManager _plcNodeManager; private SimulatedVariableNode _longStringIdNode10; private SimulatedVariableNode _longStringIdNode50; private SimulatedVariableNode _longStringIdNode100; private SimulatedVariableNode _longStringIdNode200; private readonly Random _random = new(); public void AddToAddressSpace(FolderState telemetryFolder, FolderState methodsFolder, PlcNodeManager plcNodeManager) { _plcNodeManager = plcNodeManager; var folder = _plcNodeManager.CreateFolder( telemetryFolder, path: "Special", name: "Special", NamespaceType.PlcApplications); AddNodes(folder); } public void StartSimulation() { // Change value every second to string containing single repeated uppercase letter. const int A = 65, Z = 90 + 1; #pragma warning disable CA5394 // Do not use insecure randomness _longStringIdNode10.Start(_ => new string((char)_random.Next(A, Z), 10 * 1024), periodMs: 1000); #pragma warning restore CA5394 // Do not use insecure randomness #pragma warning disable CA5394 // Do not use insecure randomness _longStringIdNode50.Start(_ => new string((char)_random.Next(A, Z), 50 * 1024), periodMs: 1000); #pragma warning restore CA5394 // Do not use insecure randomness #pragma warning disable CA5394 // Do not use insecure randomness _longStringIdNode100.Start(_ => Encoding.UTF8.GetBytes(new string((char)_random.Next(A, Z), 100 * 1024)), periodMs: 1000); #pragma warning restore CA5394 // Do not use insecure randomness #pragma warning disable CA5394 // Do not use insecure randomness _longStringIdNode200.Start(_ => Encoding.UTF8.GetBytes(new string((char)_random.Next(A, Z), 200 * 1024)), periodMs: 1000); #pragma warning restore CA5394 // Do not use insecure randomness } public void StopSimulation() { _longStringIdNode10.Stop(); _longStringIdNode50.Stop(); _longStringIdNode100.Stop(); _longStringIdNode200.Stop(); } private void AddNodes(FolderState folder) { // 10 kB. var initialString = new string('A', 10 * 1024); _longStringIdNode10 = _plcNodeManager.CreateVariableNode( _plcNodeManager.CreateBaseVariable( folder, path: "LongString10kB", name: "LongString10kB", new NodeId((uint)BuiltInType.String), ValueRanks.Scalar, AccessLevels.CurrentReadOrWrite, "Long string", NamespaceType.PlcApplications, initialString)); // 50 kB. initialString = new string('A', 50 * 1024); _longStringIdNode50 = _plcNodeManager.CreateVariableNode( _plcNodeManager.CreateBaseVariable( folder, path: "LongString50kB", name: "LongString50kB", new NodeId((uint)BuiltInType.String), ValueRanks.Scalar, AccessLevels.CurrentReadOrWrite, "Long string", NamespaceType.PlcApplications, initialString)); // 100 kB. var initialByteArray = Encoding.UTF8.GetBytes(new string('A', 100 * 1024)); _longStringIdNode100 = _plcNodeManager.CreateVariableNode( _plcNodeManager.CreateBaseVariable( folder, path: "LongString100kB", name: "LongString100kB", new NodeId((uint)BuiltInType.ByteString), ValueRanks.Scalar, AccessLevels.CurrentReadOrWrite, "Long string", NamespaceType.PlcApplications, initialByteArray)); // 200 kB. initialByteArray = Encoding.UTF8.GetBytes(new string('A', 200 * 1024)); _longStringIdNode200 = _plcNodeManager.CreateVariableNode( _plcNodeManager.CreateBaseVariable( folder, path: "LongString200kB", name: "LongString200kB", new NodeId((uint)BuiltInType.Byte), ValueRanks.OneDimension, AccessLevels.CurrentReadOrWrite, "Long string", NamespaceType.PlcApplications, initialByteArray)); Nodes = new List { new() { NodeId = "LongString10kB", Namespace = Plc.Namespaces.PlcApplications }, new() { NodeId = "LongString50kB", Namespace = Plc.Namespaces.PlcApplications }, new() { NodeId = "LongString100kB", Namespace = Plc.Namespaces.PlcApplications }, new() { NodeId = "LongString200kB", Namespace = Plc.Namespaces.PlcApplications } }; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/PluginNodes/NegTrendPluginNode.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Plc.PluginNodes { using Plc.PluginNodes.Models; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Test; using System; using System.Collections.Generic; /// /// Node with a value that shows a negative trend. /// public class NegTrendPluginNode : IPluginNodes { public IReadOnlyCollection Nodes { get; private set; } = new List(); public TimeService TimeService { get; set; } public ILogger Logger { get; set; } public uint ScaleUnits { get; set; } public void AddToAddressSpace(FolderState telemetryFolder, FolderState methodsFolder, PlcNodeManager plcNodeManager) { _plcNodeManager = plcNodeManager; var folder = _plcNodeManager.CreateFolder( telemetryFolder, path: "Anomaly", name: "Anomaly", NamespaceType.PlcApplications); AddNodes(folder); AddMethods(methodsFolder); } public void StartSimulation() { #pragma warning disable CA5394 // Do not use insecure randomness _negTrendAnomalyPhase = _random.Next(10); #pragma warning restore CA5394 // Do not use insecure randomness _negTrendCycleInPhase = PlcSimulation.SimulationCycleCount; Logger.LogTrace("First neg trend anomaly phase: {NegTrendAnomalyPhase}", _negTrendAnomalyPhase); _node.Start(NegTrendGenerator, PlcSimulation.SimulationCycleLength); } public void StopSimulation() { _node.Stop(); } private void AddNodes(FolderState folder) { _node = _plcNodeManager.CreateVariableNode( _plcNodeManager.CreateBaseVariable( folder, path: "NegativeTrendData", name: "NegativeTrendData", new NodeId((uint)BuiltInType.Double), ValueRanks.Scalar, AccessLevels.CurrentRead, "Value with a slow negative trend", NamespaceType.PlcApplications)); Nodes = new List { new() { NodeId = "NegativeTrendData", Namespace = Plc.Namespaces.PlcApplications } }; } private void AddMethods(FolderState methodsFolder) { var resetTrendMethod = _plcNodeManager.CreateMethod( methodsFolder, path: "ResetNegTrend", name: "ResetNegTrend", "Reset the negative trend values to their baseline value", NamespaceType.PlcApplications); SetResetTrendMethodProperties(ref resetTrendMethod); } /// /// Generates a sine wave with spikes at a configurable cycle in the phase. /// Called each SimulationCycleLength msec. /// /// private double NegTrendGenerator(double value) { // calculate next value var nextValue = kTrendBaseValue; if (_negTrendPhase >= _negTrendAnomalyPhase) { nextValue = kTrendBaseValue - ((_negTrendPhase - _negTrendAnomalyPhase) / 10d); Logger.LogTrace("Generate negtrend anomaly"); } // end of cycle: reset cycle count and calc next anomaly cycle if (--_negTrendCycleInPhase == 0) { _negTrendCycleInPhase = PlcSimulation.SimulationCycleCount; _negTrendPhase++; Logger.LogTrace("Neg trend phase: {NegTrendPhase}, data: {NextValue}", _negTrendPhase, nextValue); } return nextValue; } private void SetResetTrendMethodProperties(ref MethodState method) { method.OnCallMethod += OnResetTrendCall; } /// /// Method to reset the trend values. Executes synchronously. /// /// /// /// /// private ServiceResult OnResetTrendCall(ISystemContext context, MethodState method, IList inputArguments, IList outputArguments) { ResetTrendData(); Logger.LogDebug("ResetNegTrend method called"); return ServiceResult.Good; } /// /// Method implementation to reset the trend data. /// public void ResetTrendData() { #pragma warning disable CA5394 // Do not use insecure randomness _negTrendAnomalyPhase = _random.Next(10); #pragma warning restore CA5394 // Do not use insecure randomness _negTrendCycleInPhase = PlcSimulation.SimulationCycleCount; _negTrendPhase = 0; } private PlcNodeManager _plcNodeManager; private SimulatedVariableNode _node; private readonly Random _random = new(); private int _negTrendCycleInPhase; private int _negTrendPhase; private int _negTrendAnomalyPhase; private const double kTrendBaseValue = 100.0; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/PluginNodes/NodeType.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Plc.PluginNodes { public enum NodeType { UIntScalar, DoubleScalar, BoolScalar, UIntArray, } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/PluginNodes/PosTrendPluginNode.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Plc.PluginNodes { using Plc.PluginNodes.Models; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Test; using System; using System.Collections.Generic; /// /// Node with a value that shows a positive trend. /// public class PosTrendPluginNode : IPluginNodes { public IReadOnlyCollection Nodes { get; private set; } = new List(); public TimeService TimeService { get; set; } public ILogger Logger { get; set; } public uint ScaleUnits { get; set; } public void AddToAddressSpace(FolderState telemetryFolder, FolderState methodsFolder, PlcNodeManager plcNodeManager) { _plcNodeManager = plcNodeManager; var folder = _plcNodeManager.CreateFolder( telemetryFolder, path: "Anomaly", name: "Anomaly", NamespaceType.PlcApplications); AddNodes(folder); AddMethods(methodsFolder); } public void StartSimulation() { #pragma warning disable CA5394 // Do not use insecure randomness _posTrendAnomalyPhase = _random.Next(10); #pragma warning restore CA5394 // Do not use insecure randomness _posTrendCycleInPhase = PlcSimulation.SimulationCycleCount; Logger.LogTrace("First pos trend anomaly phase: {PosTrendAnomalyPhase}", _posTrendAnomalyPhase); _node.Start(PosTrendGenerator, PlcSimulation.SimulationCycleLength); } public void StopSimulation() { _node.Stop(); } private void AddNodes(FolderState folder) { _node = _plcNodeManager.CreateVariableNode( _plcNodeManager.CreateBaseVariable( folder, path: "PositiveTrendData", name: "PositiveTrendData", new NodeId((uint)BuiltInType.Double), ValueRanks.Scalar, AccessLevels.CurrentRead, "Value with a slow positive trend", NamespaceType.PlcApplications)); Nodes = new List { new() { NodeId = "PositiveTrendData", Namespace = Plc.Namespaces.PlcApplications } }; } private void AddMethods(FolderState methodsFolder) { var resetTrendMethod = _plcNodeManager.CreateMethod( methodsFolder, path: "ResetPosTrend", name: "ResetPosTrend", "Reset the positive trend values to their baseline value", NamespaceType.PlcApplications); SetResetTrendMethodProperties(ref resetTrendMethod); } /// /// Generates a sine wave with spikes at a configurable cycle in the phase. /// Called each SimulationCycleLength msec. /// /// private double PosTrendGenerator(double value) { // calculate next value var nextValue = kTrendBaseValue; if (_posTrendPhase >= _posTrendAnomalyPhase) { nextValue = kTrendBaseValue + ((_posTrendPhase - _posTrendAnomalyPhase) / 10d); Logger.LogTrace("Generate postrend anomaly"); } // end of cycle: reset cycle count and calc next anomaly cycle if (--_posTrendCycleInPhase == 0) { _posTrendCycleInPhase = PlcSimulation.SimulationCycleCount; _posTrendPhase++; Logger.LogTrace("Pos trend phase: {PosTrendPhase}, data: {NextValue}", _posTrendPhase, nextValue); } return nextValue; } private void SetResetTrendMethodProperties(ref MethodState method) { method.OnCallMethod += OnResetTrendCall; } /// /// Method to reset the trend values. Executes synchronously. /// /// /// /// /// private ServiceResult OnResetTrendCall(ISystemContext context, MethodState method, IList inputArguments, IList outputArguments) { ResetTrendData(); Logger.LogDebug("ResetPosTrend method called"); return ServiceResult.Good; } /// /// Method implementation to reset the trend data. /// public void ResetTrendData() { #pragma warning disable CA5394 // Do not use insecure randomness _posTrendAnomalyPhase = _random.Next(10); #pragma warning restore CA5394 // Do not use insecure randomness _posTrendCycleInPhase = PlcSimulation.SimulationCycleCount; _posTrendPhase = 0; } private PlcNodeManager _plcNodeManager; private SimulatedVariableNode _node; private readonly Random _random = new(); private int _posTrendCycleInPhase; private int _posTrendPhase; private int _posTrendAnomalyPhase; private const double kTrendBaseValue = 100.0; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/PluginNodes/SlowFastCommon.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Plc.PluginNodes { using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Test; using System; using System.Globalization; public class SlowFastCommon { public SlowFastCommon(PlcNodeManager plcNodeManager, TimeService timeService, ILogger logger) { _plcNodeManager = plcNodeManager ?? throw new ArgumentNullException(nameof(plcNodeManager)); _timeService = timeService; _logger = logger; } public (BaseDataVariableState[] nodes, BaseDataVariableState[] badNodes) CreateNodes(NodeType nodeType, string name, uint count, FolderState folder, FolderState simulatorFolder, bool nodeRandomization, string nodeStepSize, string nodeMinValue, string nodeMaxValue, uint nodeRate, uint nodeSamplingInterval) { var nodes = CreateBaseLoadNodes(folder, name, count, nodeType, nodeRandomization, nodeStepSize, nodeMinValue, nodeMaxValue, nodeRate, nodeSamplingInterval); var badNodes = CreateBaseLoadNodes(folder, $"Bad{name}", count: 1, nodeType, nodeRandomization, nodeStepSize, nodeMinValue, nodeMaxValue, nodeRate, nodeSamplingInterval); _numberOfUpdates = CreateNumberOfUpdatesVariable(name, simulatorFolder); return (nodes, badNodes); } private BaseDataVariableState[] CreateBaseLoadNodes(FolderState folder, string name, uint count, NodeType type, bool randomize, string stepSize, string minValue, string maxValue, uint nodeRate, uint nodeSamplingInterval) { var nodes = new BaseDataVariableState[count]; if (count > 0) { _logger.CreatingNodes(count, name, type); _logger.NodeChangeRate(nodeRate); _logger.SamplingRate(nodeSamplingInterval); } for (var i = 0; i < count; i++) { var (dataType, valueRank, defaultValue, stepTypeSize, minTypeValue, maxTypeValue) = GetNodeType(type, stepSize, minValue, maxValue); var id = (i + 1).ToString(CultureInfo.InvariantCulture); nodes[i] = _plcNodeManager.CreateBaseVariable( folder, path: $"{name}{type}{id}", name: $"{name}{type}{id}", dataType, valueRank, AccessLevels.CurrentReadOrWrite, "Constantly increasing value(s)", NamespaceType.PlcApplications, randomize, stepTypeSize, minTypeValue, maxTypeValue, defaultValue); } return nodes; } private BaseDataVariableState CreateNumberOfUpdatesVariable(string baseName, FolderState simulatorFolder) { // Create property to hold NumberOfUpdates (to stop simulated updates after a given count) var variable = new BaseDataVariableState(simulatorFolder); var name = $"{baseName}{kNumberOfUpdates}"; variable.NodeId = new NodeId(name, _plcNodeManager.NamespaceIndexes[(int)NamespaceType.PlcApplications]); variable.DataType = DataTypeIds.Int32; variable.Value = -1; // a value < 0 means to update nodes indefinitely. variable.ValueRank = ValueRanks.Scalar; variable.AccessLevel = AccessLevels.CurrentReadOrWrite; variable.UserAccessLevel = AccessLevels.CurrentReadOrWrite; variable.BrowseName = name; variable.DisplayName = name; variable.Description = new LocalizedText( "The number of times to update the {name} nodes. Set to -1 to update indefinitely."); simulatorFolder.AddChild(variable); return variable; } private static (NodeId dataType, int valueRank, object defaultValue, object stepSize, object minValue, object maxValue) GetNodeType(NodeType nodeType, string stepSize, string minValue, string maxValue) { return nodeType switch { NodeType.BoolScalar => (new NodeId((uint)BuiltInType.Boolean), ValueRanks.Scalar, true, null, null, null), NodeType.DoubleScalar => (new NodeId((uint)BuiltInType.Double), ValueRanks.Scalar, 0.0, double.Parse(stepSize, CultureInfo.InvariantCulture), minValue == null ? 0.0 : double.Parse(minValue, CultureInfo.InvariantCulture), maxValue == null ? double.MaxValue : double.Parse(maxValue, CultureInfo.InvariantCulture)), NodeType.UIntArray => (new NodeId((uint)BuiltInType.UInt32), ValueRanks.OneDimension, new uint[32], null, null, null), NodeType.UIntScalar => (new NodeId((uint)BuiltInType.UInt32), ValueRanks.Scalar, 0u, uint.Parse(stepSize, CultureInfo.InvariantCulture), minValue == null ? uint.MinValue : uint.Parse(minValue, CultureInfo.InvariantCulture), maxValue == null ? uint.MaxValue : uint.Parse(maxValue, CultureInfo.InvariantCulture)), _ => throw new NotSupportedException("Node type unknown") }; } public void UpdateNodes(BaseDataVariableState[] nodes, BaseDataVariableState[] badNodes, NodeType nodeType, bool updateNodes) { if (!ShouldUpdateNodes(_numberOfUpdates) || !updateNodes) { return; } if (nodes != null) { UpdateNodes(nodes, nodeType, StatusCodes.Good, false); } if (badNodes != null) { (var status, var addBadValue) = _badStatusSequence[_badNodesCycle++ % _badStatusSequence.Length]; UpdateNodes(badNodes, nodeType, status, addBadValue); } } private void UpdateNodes(BaseDataVariableState[] nodes, NodeType type, StatusCode status, bool addBadValue) { if (nodes == null || nodes.Length == 0) { _logger.InvalidArgument(nodes); return; } for (var nodeIndex = 0; nodeIndex < nodes.Length; nodeIndex++) { var extendedNode = (BaseDataVariableStateExtended)nodes[nodeIndex]; object value = null; if (StatusCode.IsNotBad(status) || addBadValue) { switch (type) { case NodeType.DoubleScalar: var minDoubleValue = (double)extendedNode.MinValue; var maxDoubleValue = (double)extendedNode.MaxValue; var extendedDoubleNodeValue = (double)(extendedNode.Value ?? minDoubleValue); if (extendedNode.Randomize) { if (minDoubleValue != maxDoubleValue) { // Hybrid range case (e.g. -5.0 to 5.0). if (minDoubleValue < 0 && maxDoubleValue > 0) { // If new random value is same as previous one, generate a new one until it is not. while (value == null || extendedDoubleNodeValue == (double)value) { // Split the range from 0 on both sides. #pragma warning disable CA5394 // Do not use insecure randomness var value1 = _random.NextDouble() * maxDoubleValue; #pragma warning restore CA5394 // Do not use insecure randomness #pragma warning disable CA5394 // Do not use insecure randomness var value2 = _random.NextDouble() * minDoubleValue; #pragma warning restore CA5394 // Do not use insecure randomness // Return random value from postive or negative range, randomly. #pragma warning disable CA5394 // Do not use insecure randomness value = _random.Next(10) % 2 == 0 ? value1 : value2; #pragma warning restore CA5394 // Do not use insecure randomness } } else // Negative and positive only range cases (e.g. -5.0 to -8.0 or 0 to 9.5). { // If new random value is same as previous one, generate a new one until it is not. while (value == null || extendedDoubleNodeValue == (double)value) { #pragma warning disable CA5394 // Do not use insecure randomness value = minDoubleValue + (_random.NextDouble() * (maxDoubleValue - minDoubleValue)); #pragma warning restore CA5394 // Do not use insecure randomness } } } else { throw new ArgumentException($"Range {minDoubleValue} to {maxDoubleValue}does not have provision for randomness."); } } else { // Positive only range cases (e.g. 0 to 9.5). if (minDoubleValue >= 0 && maxDoubleValue > 0) { value = (extendedDoubleNodeValue % maxDoubleValue) < minDoubleValue ? minDoubleValue : ((extendedDoubleNodeValue % maxDoubleValue) + (double)extendedNode.StepSize) > maxDoubleValue ? minDoubleValue : ((extendedDoubleNodeValue % maxDoubleValue) + (double)extendedNode.StepSize); } else if (maxDoubleValue <= 0 && minDoubleValue < 0) // Negative only range cases (e.g. 0 to -9.5). { value = (extendedDoubleNodeValue % minDoubleValue) > maxDoubleValue ? maxDoubleValue : ((extendedDoubleNodeValue % minDoubleValue) - (double)extendedNode.StepSize) < minDoubleValue ? maxDoubleValue : (extendedDoubleNodeValue % minDoubleValue) - (double)extendedNode.StepSize; } else { // This is to prevent infinte loop while attempting to create a different random number than previous one if no range is provided. throw new ArgumentException($"Negative to positive range {minDoubleValue} to {maxDoubleValue} for sequential node values is not supported currently."); } } break; case NodeType.BoolScalar: value = extendedNode.Value == null || !(bool)extendedNode.Value; break; case NodeType.UIntArray: var arrayValue = (uint[])extendedNode.Value; if (arrayValue != null) { for (var arrayIndex = 0; arrayIndex < arrayValue.Length; arrayIndex++) { arrayValue[arrayIndex]++; } } else { arrayValue = new uint[32]; } value = arrayValue; break; case NodeType.UIntScalar: var minUIntValue = (uint)extendedNode.MinValue; var maxUIntValue = (uint)extendedNode.MaxValue; var extendedUIntNodeValue = (uint)(extendedNode.Value ?? minUIntValue); if (extendedNode.Randomize) { if (minUIntValue != maxUIntValue) { // If new random value is same as previous one, generate a new one until it is not. while (value == null || extendedUIntNodeValue == (uint)value) { // uint.MaxValue + 1 cycles back to 0 which causes infinte loop here hence a check maxUIntValue == uint.MaxValue to prevent it. #pragma warning disable CA5394 // Do not use insecure randomness value = (uint)(minUIntValue + (_random.NextDouble() * ((maxUIntValue == uint.MaxValue ? maxUIntValue : maxUIntValue + 1) - minUIntValue))); #pragma warning restore CA5394 // Do not use insecure randomness } } else { // This is to prevent infinte loop while attempting to create a different random number than previous one if no range is provided. throw new ArgumentException($"Range {minUIntValue} to {maxUIntValue} does not have provision for randomness."); } } else { value = (extendedUIntNodeValue % maxUIntValue) < minUIntValue ? minUIntValue : ((extendedUIntNodeValue % maxUIntValue) + (uint)extendedNode.StepSize) > maxUIntValue ? minUIntValue : ((extendedUIntNodeValue % maxUIntValue) + (uint)extendedNode.StepSize); } break; default: throw new NotSupportedException("Node type unknown"); } } extendedNode.StatusCode = status; SetValue(extendedNode, value); } } private void SetValue(BaseVariableState variable, T value) { variable.Value = value; variable.Timestamp = _timeService.Now; variable.ClearChangeMasks(_plcNodeManager.SystemContext, false); } /// /// Determines whether the values of simulated nodes should be updated, based /// on the value of the corresponding variable. /// Decrements the NumberOfUpdates variable value and returns true if the NumberOfUpdates variable value if greater than zero, /// returns false if the NumberOfUpdates variable value is zero, /// returns true if the NumberOfUpdates variable value is less than zero. /// /// Node that contains the setting of the number of updates to apply. /// True if the value of the node should be updated by the simulator, false otherwise. private bool ShouldUpdateNodes(BaseDataVariableState numberOfUpdatesVariable) { var value = (int)numberOfUpdatesVariable.Value; if (value == 0) { return false; } if (value > 0) { SetValue(numberOfUpdatesVariable, value - 1); } return true; } private readonly (StatusCode, bool)[] _badStatusSequence = [ ( StatusCodes.Good, true ), ( StatusCodes.Good, true ), ( StatusCodes.Good, true ), ( StatusCodes.UncertainLastUsableValue, true), ( StatusCodes.Good, true ), ( StatusCodes.Good, true ), ( StatusCodes.Good, true ), ( StatusCodes.UncertainLastUsableValue, true), ( StatusCodes.BadDataLost, true), ( StatusCodes.BadNoCommunication, false) ]; private readonly PlcNodeManager _plcNodeManager; private readonly TimeService _timeService; private readonly ILogger _logger; private readonly Random _random = new(); private BaseDataVariableState _numberOfUpdates; private uint _badNodesCycle; private const string kNumberOfUpdates = "NumberOfUpdates"; } /// /// Source-generated logging definitions for SlowFastCommon /// internal static partial class SlowFastCommonLogging { private const int EventClass = 80; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Information, Message = "Creating {Count} {Name} nodes of type: {Type}")] public static partial void CreatingNodes(this ILogger logger, uint count, string name, NodeType type); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Information, Message = "Node values will change every {Rate} ms")] public static partial void NodeChangeRate(this ILogger logger, uint rate); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Information, Message = "Node values sampling rate is {NodeSamplingInterval} ms")] public static partial void SamplingRate(this ILogger logger, uint nodeSamplingInterval); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Warning, Message = "Invalid argument {Argument} provided.")] public static partial void InvalidArgument(this ILogger logger, object argument); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/PluginNodes/SlowPluginNodes.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Plc.PluginNodes { using Plc.PluginNodes.Models; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Test; using System.Collections.Generic; using System.Timers; /// /// Nodes with slow changing values. /// public class SlowPluginNodes : IPluginNodes { public IReadOnlyCollection Nodes { get; private set; } = new List(); public TimeService TimeService { get; set; } public ILogger Logger { get; set; } public uint ScaleUnits { get; set; } private uint NodeCount => ScaleUnits == 0 ? 3u : ScaleUnits * 1000; /// /// ms. /// private uint NodeRate { get; } = 10000; private NodeType NodeType { get; } = NodeType.UIntScalar; private string NodeMinValue { get; } private string NodeMaxValue { get; } private string NodeStepSize { get; } = "1"; /// /// ms. /// private uint NodeSamplingInterval { get; } private PlcNodeManager _plcNodeManager; private SlowFastCommon _slowFastCommon; private BaseDataVariableState[] _nodes; private BaseDataVariableState[] _badNodes; private ITimer _nodeGenerator; private bool _updateNodes = true; public void AddToAddressSpace(FolderState telemetryFolder, FolderState methodsFolder, PlcNodeManager plcNodeManager) { _plcNodeManager = plcNodeManager; _slowFastCommon = new SlowFastCommon(_plcNodeManager, TimeService, Logger); var folder = _plcNodeManager.CreateFolder( telemetryFolder, path: "Slow", name: "Slow", NamespaceType.PlcApplications); // Used for methods to limit the number of updates to a fixed count. var simulatorFolder = _plcNodeManager.CreateFolder( telemetryFolder.Parent, // Root. path: "SimulatorConfiguration", name: "SimulatorConfiguration", NamespaceType.PlcApplications); AddNodes(folder, simulatorFolder); AddMethods(methodsFolder); } private void AddMethods(FolderState methodsFolder) { var stopUpdateMethod = _plcNodeManager.CreateMethod( methodsFolder, path: "StopUpdateSlowNodes", name: "StopUpdateSlowNodes", "Stop the increase of value of slow nodes", NamespaceType.PlcApplications); SetStopUpdateSlowNodesProperties(ref stopUpdateMethod); var startUpdateMethod = _plcNodeManager.CreateMethod( methodsFolder, path: "StartUpdateSlowNodes", name: "StartUpdateSlowNodes", "Start the increase of value of slow nodes", NamespaceType.PlcApplications); SetStartUpdateSlowNodesProperties(ref startUpdateMethod); } public void StartSimulation() { _nodeGenerator = TimeService.NewTimer(UpdateNodes, NodeRate); } public void StopSimulation() { if (_nodeGenerator != null) { _nodeGenerator.Enabled = false; } } private void AddNodes(FolderState folder, FolderState simulatorFolder) { (_nodes, _badNodes) = _slowFastCommon.CreateNodes(NodeType, "Slow", NodeCount, folder, simulatorFolder, false, NodeStepSize, NodeMinValue, NodeMaxValue, NodeRate, NodeSamplingInterval); ExposeNodesWithIntervals(); } /// /// Expose node information for dumping pn.json. /// private void ExposeNodesWithIntervals() { var nodes = new List(); foreach (var node in _nodes) { nodes.Add(new NodeWithIntervals { NodeId = node.NodeId.Identifier.ToString(), NodeIdTypePrefix = NodeWithIntervals.GetPrefix(node.NodeId.IdType), Namespace = Plc.Namespaces.PlcApplications, PublishingInterval = NodeRate, SamplingInterval = NodeSamplingInterval }); } foreach (var node in _badNodes) { nodes.Add(new NodeWithIntervals { NodeId = node.NodeId.Identifier.ToString(), NodeIdTypePrefix = NodeWithIntervals.GetPrefix(node.NodeId.IdType), Namespace = Plc.Namespaces.PlcApplications, PublishingInterval = NodeRate, SamplingInterval = NodeSamplingInterval }); } Nodes = nodes; } private void SetStopUpdateSlowNodesProperties(ref MethodState method) { method.OnCallMethod += OnStopUpdateSlowNodes; } private void SetStartUpdateSlowNodesProperties(ref MethodState method) { method.OnCallMethod += OnStartUpdateSlowNodes; } /// /// Method to stop updating the slow nodes. /// /// /// /// /// private ServiceResult OnStopUpdateSlowNodes(ISystemContext context, MethodState method, IList inputArguments, IList outputArguments) { _updateNodes = false; Logger.LogDebug("StopUpdateSlowNodes method called"); return ServiceResult.Good; } /// /// Method to start updating the slow nodes. /// /// /// /// /// private ServiceResult OnStartUpdateSlowNodes(ISystemContext context, MethodState method, IList inputArguments, IList outputArguments) { _updateNodes = true; Logger.LogDebug("StartUpdateSlowNodes method called"); return ServiceResult.Good; } private void UpdateNodes(object state, ElapsedEventArgs elapsedEventArgs) { _slowFastCommon.UpdateNodes(_nodes, _badNodes, NodeType, _updateNodes); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/PluginNodes/SlowRandomPluginNodes.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Plc.PluginNodes { using Plc.PluginNodes.Models; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Test; using System.Collections.Generic; using System.Timers; /// /// Nodes with slow changing values. /// public class SlowRandomPluginNodes : IPluginNodes { public IReadOnlyCollection Nodes { get; private set; } = new List(); public TimeService TimeService { get; set; } public ILogger Logger { get; set; } public uint ScaleUnits { get; set; } private uint NodeCount => ScaleUnits == 0 ? 3u : ScaleUnits * 1000; /// /// ms. /// private uint NodeRate { get; } = 10000; private NodeType NodeType { get; } = NodeType.UIntScalar; private string NodeMinValue { get; } private string NodeMaxValue { get; } private string NodeStepSize { get; } = "1"; /// /// ms. /// private uint NodeSamplingInterval { get; } private PlcNodeManager _plcNodeManager; private SlowFastCommon _slowFastCommon; private BaseDataVariableState[] _nodes; private BaseDataVariableState[] _badNodes; private ITimer _nodeGenerator; private bool _updateNodes = true; public void AddToAddressSpace(FolderState telemetryFolder, FolderState methodsFolder, PlcNodeManager plcNodeManager) { _plcNodeManager = plcNodeManager; _slowFastCommon = new SlowFastCommon(_plcNodeManager, TimeService, Logger); var folder = _plcNodeManager.CreateFolder( telemetryFolder, path: "Slow", name: "Slow", NamespaceType.PlcApplications); // Used for methods to limit the number of updates to a fixed count. var simulatorFolder = _plcNodeManager.CreateFolder( telemetryFolder.Parent, // Root. path: "SimulatorConfiguration", name: "SimulatorConfiguration", NamespaceType.PlcApplications); AddNodes(folder, simulatorFolder); AddMethods(methodsFolder); } private void AddMethods(FolderState methodsFolder) { var stopUpdateMethod = _plcNodeManager.CreateMethod( methodsFolder, path: "StopUpdateSlowNodes", name: "StopUpdateSlowNodes", "Stop the increase of value of slow nodes", NamespaceType.PlcApplications); SetStopUpdateSlowNodesProperties(ref stopUpdateMethod); var startUpdateMethod = _plcNodeManager.CreateMethod( methodsFolder, path: "StartUpdateSlowNodes", name: "StartUpdateSlowNodes", "Start the increase of value of slow nodes", NamespaceType.PlcApplications); SetStartUpdateSlowNodesProperties(ref startUpdateMethod); } public void StartSimulation() { _nodeGenerator = TimeService.NewTimer(UpdateNodes, NodeRate); } public void StopSimulation() { if (_nodeGenerator != null) { _nodeGenerator.Enabled = false; } } private void AddNodes(FolderState folder, FolderState simulatorFolder) { (_nodes, _badNodes) = _slowFastCommon.CreateNodes(NodeType, "SlowRandom", NodeCount, folder, simulatorFolder, true, NodeStepSize, NodeMinValue, NodeMaxValue, NodeRate, NodeSamplingInterval); ExposeNodesWithIntervals(); } /// /// Expose node information for dumping pn.json. /// private void ExposeNodesWithIntervals() { var nodes = new List(); foreach (var node in _nodes) { nodes.Add(new NodeWithIntervals { NodeId = node.NodeId.Identifier.ToString(), NodeIdTypePrefix = NodeWithIntervals.GetPrefix(node.NodeId.IdType), Namespace = Plc.Namespaces.PlcApplications, PublishingInterval = NodeRate, SamplingInterval = NodeSamplingInterval }); } foreach (var node in _badNodes) { nodes.Add(new NodeWithIntervals { NodeId = node.NodeId.Identifier.ToString(), NodeIdTypePrefix = NodeWithIntervals.GetPrefix(node.NodeId.IdType), Namespace = Plc.Namespaces.PlcApplications, PublishingInterval = NodeRate, SamplingInterval = NodeSamplingInterval }); } Nodes = nodes; } private void SetStopUpdateSlowNodesProperties(ref MethodState method) { method.OnCallMethod += OnStopUpdateSlowNodes; } private void SetStartUpdateSlowNodesProperties(ref MethodState method) { method.OnCallMethod += OnStartUpdateSlowNodes; } /// /// Method to stop updating the slow nodes. /// /// /// /// /// private ServiceResult OnStopUpdateSlowNodes(ISystemContext context, MethodState method, IList inputArguments, IList outputArguments) { _updateNodes = false; Logger.LogDebug("StopUpdateSlowNodes method called"); return ServiceResult.Good; } /// /// Method to start updating the slow nodes. /// /// /// /// /// private ServiceResult OnStartUpdateSlowNodes(ISystemContext context, MethodState method, IList inputArguments, IList outputArguments) { _updateNodes = true; Logger.LogDebug("StartUpdateSlowNodes method called"); return ServiceResult.Good; } private void UpdateNodes(object state, ElapsedEventArgs elapsedEventArgs) { _slowFastCommon.UpdateNodes(_nodes, _badNodes, NodeType, _updateNodes); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/PluginNodes/SpecialCharNamePluginNode.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Plc.PluginNodes { using Plc.PluginNodes.Models; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Test; using System.Collections.Generic; using System.Web; /// /// Node with special chars in name and ID. /// public class SpecialCharNamePluginNode : IPluginNodes { public IReadOnlyCollection Nodes { get; private set; } = new List(); public TimeService TimeService { get; set; } public ILogger Logger { get; set; } public uint ScaleUnits { get; set; } private PlcNodeManager _plcNodeManager; private SimulatedVariableNode _node; public void AddToAddressSpace(FolderState telemetryFolder, FolderState methodsFolder, PlcNodeManager plcNodeManager) { _plcNodeManager = plcNodeManager; var folder = _plcNodeManager.CreateFolder( telemetryFolder, path: "Special", name: "Special", NamespaceType.PlcApplications); AddNodes(folder); } public void StartSimulation() { _node.Start(value => value + 1, periodMs: 1000); } public void StopSimulation() { _node.Stop(); } private void AddNodes(FolderState folder) { var SpecialChars = HttpUtility.HtmlDecode(@""!§$%&/()=?`´\+~*'#_-:.;,<>|@^°€µ{[]}"); _node = _plcNodeManager.CreateVariableNode( _plcNodeManager.CreateBaseVariable( folder, path: "Special_" + SpecialChars, name: SpecialChars, new NodeId((uint)BuiltInType.UInt32), ValueRanks.Scalar, AccessLevels.CurrentReadOrWrite, "Constantly increasing value", NamespaceType.PlcApplications, defaultValue: (uint)0)); Nodes = new List { new() { NodeId = "Special_" + SpecialChars, Namespace = Plc.Namespaces.PlcApplications } }; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Plc/PluginNodes/SpikePluginNode.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Plc.PluginNodes { using Plc.PluginNodes.Models; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Test; using System; using System.Collections.Generic; /// /// Node with a sine wave value with a spike anomaly. /// public class SpikePluginNode : IPluginNodes { public IReadOnlyCollection Nodes { get; private set; } = new List(); public TimeService TimeService { get; set; } public ILogger Logger { get; set; } public uint ScaleUnits { get; set; } public void AddToAddressSpace(FolderState telemetryFolder, FolderState methodsFolder, PlcNodeManager plcNodeManager) { _plcNodeManager = plcNodeManager; var folder = _plcNodeManager.CreateFolder( telemetryFolder, path: "Anomaly", name: "Anomaly", NamespaceType.PlcApplications); AddNodes(folder); } public void StartSimulation() { _spikeCycleInPhase = PlcSimulation.SimulationCycleCount; #pragma warning disable CA5394 // Do not use insecure randomness _spikeAnomalyCycle = _random.Next(PlcSimulation.SimulationCycleCount); #pragma warning restore CA5394 // Do not use insecure randomness Logger.LogTrace("First spike anomaly cycle: {SpikeAnomalyCycle}", _spikeAnomalyCycle); _node.Start(SpikeGenerator, PlcSimulation.SimulationCycleLength); } public void StopSimulation() { _node.Stop(); } private void AddNodes(FolderState folder) { _node = _plcNodeManager.CreateVariableNode( _plcNodeManager.CreateBaseVariable( folder, path: "SpikeData", name: "SpikeData", new NodeId((uint)BuiltInType.Double), ValueRanks.Scalar, AccessLevels.CurrentRead, "Value with random spikes", NamespaceType.PlcApplications)); Nodes = new List { new() { NodeId = "SpikeData", Namespace = Plc.Namespaces.PlcApplications } }; } /// /// Generates a sine wave with spikes at a random cycle in the phase. /// Called each SimulationCycleLength msec. /// /// private double SpikeGenerator(double value) { // calculate next value double nextValue; if (_spikeCycleInPhase == _spikeAnomalyCycle) { // todo calculate nextValue = kSimulationMaxAmplitude * 10; Logger.LogTrace("Generate spike anomaly"); } else { nextValue = kSimulationMaxAmplitude * Math.Sin(2 * Math.PI / PlcSimulation.SimulationCycleCount * _spikeCycleInPhase); } Logger.LogTrace("Spike cycle: {SpikeCycleInPhase} data: {NextValue}", _spikeCycleInPhase, nextValue); // end of cycle: reset cycle count and calc next anomaly cycle if (--_spikeCycleInPhase == 0) { _spikeCycleInPhase = PlcSimulation.SimulationCycleCount; #pragma warning disable CA5394 // Do not use insecure randomness _spikeAnomalyCycle = _random.Next(PlcSimulation.SimulationCycleCount); #pragma warning restore CA5394 // Do not use insecure randomness Logger.LogTrace("Next spike anomaly cycle: {SpikeAnomalyCycle}", _spikeAnomalyCycle); } return nextValue; } private PlcNodeManager _plcNodeManager; private SimulatedVariableNode _node; private readonly Random _random = new(); private int _spikeCycleInPhase; private int _spikeAnomalyCycle; private const double kSimulationMaxAmplitude = 100.0; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Properties/AssemblyInfo.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using System; [assembly: CLSCompliant(false)] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Reference/Namespaces.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Reference { /// /// Defines constants for namespaces used by the application. /// public static class Namespaces { /// /// The namespace for the nodes provided by the server. /// public const string ReferenceApplications = "http://opcfoundation.org/ReferenceApplications"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Reference/ReferenceNodeManager.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2020 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Reference { using Opc.Ua; using Opc.Ua.Server; using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Numerics; using System.Threading; using System.Xml; /// /// A node manager for a server that exposes several variables. /// public class ReferenceNodeManager : CustomNodeManager2 { /// /// Initializes the node manager. /// /// /// public ReferenceNodeManager(IServerInternal server, ApplicationConfiguration configuration) : base(server, configuration, Namespaces.ReferenceApplications) { SystemContext.NodeIdFactory = this; _dynamicNodes = []; } /// /// An overrideable version of the Dispose. /// /// protected override void Dispose(bool disposing) { if (disposing && _simulationTimer != null) { _simulationTimer.Dispose(); _simulationTimer = null; } base.Dispose(disposing); } /// /// Creates the NodeId for the specified node. /// /// /// public override NodeId New(ISystemContext context, NodeState node) { if (node is BaseInstanceState instance && instance.Parent?.NodeId.Identifier is string id) { return new NodeId(id + "_" + instance.SymbolicName, instance.Parent.NodeId.NamespaceIndex); } return node.NodeId; } private static bool IsAnalogType(BuiltInType builtInType) { switch (builtInType) { case BuiltInType.Byte: case BuiltInType.UInt16: case BuiltInType.UInt32: case BuiltInType.UInt64: case BuiltInType.SByte: case BuiltInType.Int16: case BuiltInType.Int32: case BuiltInType.Int64: case BuiltInType.Float: case BuiltInType.Double: return true; } return false; } private static Opc.Ua.Range GetAnalogRange(BuiltInType builtInType) { switch (builtInType) { case BuiltInType.UInt16: return new Opc.Ua.Range(ushort.MaxValue, ushort.MinValue); case BuiltInType.UInt32: return new Opc.Ua.Range(uint.MaxValue, uint.MinValue); case BuiltInType.UInt64: return new Opc.Ua.Range(ulong.MaxValue, ulong.MinValue); case BuiltInType.SByte: return new Opc.Ua.Range(sbyte.MaxValue, sbyte.MinValue); case BuiltInType.Int16: return new Opc.Ua.Range(short.MaxValue, short.MinValue); case BuiltInType.Int32: return new Opc.Ua.Range(int.MaxValue, int.MinValue); case BuiltInType.Int64: return new Opc.Ua.Range(long.MaxValue, long.MinValue); case BuiltInType.Float: return new Opc.Ua.Range(float.MaxValue, float.MinValue); case BuiltInType.Double: return new Opc.Ua.Range(double.MaxValue, double.MinValue); case BuiltInType.Byte: return new Opc.Ua.Range(byte.MaxValue, byte.MinValue); default: return new Opc.Ua.Range(sbyte.MaxValue, sbyte.MinValue); } } /// /// Does any initialization required before the address space can be used. /// /// /// /// The externalReferences is an out parameter that allows the node manager to link to nodes /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and /// should have a reference to the root folder node(s) exposed by this node manager. /// public override void CreateAddressSpace(IDictionary> externalReferences) { lock (Lock) { if (!externalReferences.TryGetValue(ObjectIds.ObjectsFolder, out var references)) { externalReferences[ObjectIds.ObjectsFolder] = references = []; } var root = CreateFolder(null, "CTT", "CTT"); root.AddReference(ReferenceTypes.Organizes, true, ObjectIds.ObjectsFolder); references.Add(new NodeStateReference(ReferenceTypes.Organizes, false, root.NodeId)); root.EventNotifier = EventNotifiers.SubscribeToEvents; AddRootNotifier(root); var variables = new List(); try { // Scalar_Static ResetRandomGenerator(1); var scalarFolder = CreateFolder(root, "Scalar", "Scalar"); var scalarInstructions = CreateVariable(scalarFolder, "Scalar_Instructions", "Scalar_Instructions", DataTypeIds.String, ValueRanks.Scalar); scalarInstructions.Value = "A library of Read/Write Variables of all supported data-types."; variables.Add(scalarInstructions); var staticFolder = CreateFolder(scalarFolder, "Scalar_Static", "Scalar_Static"); const string scalarStatic = "Scalar_Static_"; variables.Add(CreateVariable(staticFolder, scalarStatic + "Boolean", "Boolean", DataTypeIds.Boolean, ValueRanks.Scalar)); variables.Add(CreateVariable(staticFolder, scalarStatic + "Byte", "Byte", DataTypeIds.Byte, ValueRanks.Scalar)); variables.Add(CreateVariable(staticFolder, scalarStatic + "ByteString", "ByteString", DataTypeIds.ByteString, ValueRanks.Scalar)); variables.Add(CreateVariable(staticFolder, scalarStatic + "DateTime", "DateTime", DataTypeIds.DateTime, ValueRanks.Scalar)); variables.Add(CreateVariable(staticFolder, scalarStatic + "Double", "Double", DataTypeIds.Double, ValueRanks.Scalar)); variables.Add(CreateVariable(staticFolder, scalarStatic + "Duration", "Duration", DataTypeIds.Duration, ValueRanks.Scalar)); variables.Add(CreateVariable(staticFolder, scalarStatic + "Float", "Float", DataTypeIds.Float, ValueRanks.Scalar).MinimumSamplingInterval(100)); variables.Add(CreateVariable(staticFolder, scalarStatic + "Guid", "Guid", DataTypeIds.Guid, ValueRanks.Scalar)); variables.Add(CreateVariable(staticFolder, scalarStatic + "Int16", "Int16", DataTypeIds.Int16, ValueRanks.Scalar)); variables.Add(CreateVariable(staticFolder, scalarStatic + "Int32", "Int32", DataTypeIds.Int32, ValueRanks.Scalar)); variables.Add(CreateVariable(staticFolder, scalarStatic + "Int64", "Int64", DataTypeIds.Int64, ValueRanks.Scalar)); variables.Add(CreateVariable(staticFolder, scalarStatic + "Integer", "Integer", DataTypeIds.Integer, ValueRanks.Scalar)); variables.Add(CreateVariable(staticFolder, scalarStatic + "LocaleId", "LocaleId", DataTypeIds.LocaleId, ValueRanks.Scalar)); variables.Add(CreateVariable(staticFolder, scalarStatic + "LocalizedText", "LocalizedText", DataTypeIds.LocalizedText, ValueRanks.Scalar)); variables.Add(CreateVariable(staticFolder, scalarStatic + "NodeId", "NodeId", DataTypeIds.NodeId, ValueRanks.Scalar)); variables.Add(CreateVariable(staticFolder, scalarStatic + "Number", "Number", DataTypeIds.Number, ValueRanks.Scalar)); variables.Add(CreateVariable(staticFolder, scalarStatic + "QualifiedName", "QualifiedName", DataTypeIds.QualifiedName, ValueRanks.Scalar)); variables.Add(CreateVariable(staticFolder, scalarStatic + "SByte", "SByte", DataTypeIds.SByte, ValueRanks.Scalar)); variables.Add(CreateVariable(staticFolder, scalarStatic + "String", "String", DataTypeIds.String, ValueRanks.Scalar)); variables.Add(CreateVariable(staticFolder, scalarStatic + "TimeString", "TimeString", DataTypeIds.TimeString, ValueRanks.Scalar)); variables.Add(CreateVariable(staticFolder, scalarStatic + "UInt16", "UInt16", DataTypeIds.UInt16, ValueRanks.Scalar)); variables.Add(CreateVariable(staticFolder, scalarStatic + "UInt32", "UInt32", DataTypeIds.UInt32, ValueRanks.Scalar)); variables.Add(CreateVariable(staticFolder, scalarStatic + "UInt64", "UInt64", DataTypeIds.UInt64, ValueRanks.Scalar)); variables.Add(CreateVariable(staticFolder, scalarStatic + "UInteger", "UInteger", DataTypeIds.UInteger, ValueRanks.Scalar)); variables.Add(CreateVariable(staticFolder, scalarStatic + "UtcTime", "UtcTime", DataTypeIds.UtcTime, ValueRanks.Scalar)); variables.Add(CreateVariable(staticFolder, scalarStatic + "Variant", "Variant", BuiltInType.Variant, ValueRanks.Scalar)); variables.Add(CreateVariable(staticFolder, scalarStatic + "XmlElement", "XmlElement", DataTypeIds.XmlElement, ValueRanks.Scalar).MinimumSamplingInterval(1000)); var decimalVariable = CreateVariable(staticFolder, scalarStatic + "Decimal", "Decimal", DataTypeIds.DecimalDataType, ValueRanks.Scalar); // Set an arbitrary precision decimal value. var largeInteger = BigInteger.Parse("1234567890123546789012345678901234567890123456789012345", CultureInfo.InvariantCulture); decimalVariable.Value = new DecimalDataType { Scale = 100, Value = largeInteger.ToByteArray() }; variables.Add(decimalVariable); // Scalar_Static_Arrays ResetRandomGenerator(2); var arraysFolder = CreateFolder(staticFolder, "Scalar_Static_Arrays", "Arrays"); const string staticArrays = "Scalar_Static_Arrays_"; variables.Add(CreateVariable(arraysFolder, staticArrays + "Boolean", "Boolean", DataTypeIds.Boolean, ValueRanks.OneDimension)); variables.Add(CreateVariable(arraysFolder, staticArrays + "Byte", "Byte", DataTypeIds.Byte, ValueRanks.OneDimension)); variables.Add(CreateVariable(arraysFolder, staticArrays + "ByteString", "ByteString", DataTypeIds.ByteString, ValueRanks.OneDimension)); variables.Add(CreateVariable(arraysFolder, staticArrays + "DateTime", "DateTime", DataTypeIds.DateTime, ValueRanks.OneDimension)); var doubleArrayVar = CreateVariable(arraysFolder, staticArrays + "Double", "Double", DataTypeIds.Double, ValueRanks.OneDimension); // Set the first elements of the array to a smaller value. var doubleArrayVal = doubleArrayVar.Value as double[]; doubleArrayVal[0] %= 10E+10; doubleArrayVal[1] %= 10E+10; doubleArrayVal[2] %= 10E+10; doubleArrayVal[3] %= 10E+10; variables.Add(doubleArrayVar); variables.Add(CreateVariable(arraysFolder, staticArrays + "Duration", "Duration", DataTypeIds.Duration, ValueRanks.OneDimension)); var floatArrayVar = CreateVariable(arraysFolder, staticArrays + "Float", "Float", DataTypeIds.Float, ValueRanks.OneDimension); // Set the first elements of the array to a smaller value. var floatArrayVal = floatArrayVar.Value as float[]; floatArrayVal[0] %= 0xf10E + 4; floatArrayVal[1] %= 0xf10E + 4; floatArrayVal[2] %= 0xf10E + 4; floatArrayVal[3] %= 0xf10E + 4; variables.Add(floatArrayVar); variables.Add(CreateVariable(arraysFolder, staticArrays + "Guid", "Guid", DataTypeIds.Guid, ValueRanks.OneDimension)); variables.Add(CreateVariable(arraysFolder, staticArrays + "Int16", "Int16", DataTypeIds.Int16, ValueRanks.OneDimension)); variables.Add(CreateVariable(arraysFolder, staticArrays + "Int32", "Int32", DataTypeIds.Int32, ValueRanks.OneDimension)); variables.Add(CreateVariable(arraysFolder, staticArrays + "Int64", "Int64", DataTypeIds.Int64, ValueRanks.OneDimension)); variables.Add(CreateVariable(arraysFolder, staticArrays + "Integer", "Integer", DataTypeIds.Integer, ValueRanks.OneDimension)); variables.Add(CreateVariable(arraysFolder, staticArrays + "LocaleId", "LocaleId", DataTypeIds.LocaleId, ValueRanks.OneDimension)); variables.Add(CreateVariable(arraysFolder, staticArrays + "LocalizedText", "LocalizedText", DataTypeIds.LocalizedText, ValueRanks.OneDimension)); variables.Add(CreateVariable(arraysFolder, staticArrays + "NodeId", "NodeId", DataTypeIds.NodeId, ValueRanks.OneDimension)); variables.Add(CreateVariable(arraysFolder, staticArrays + "Number", "Number", DataTypeIds.Number, ValueRanks.OneDimension)); variables.Add(CreateVariable(arraysFolder, staticArrays + "QualifiedName", "QualifiedName", DataTypeIds.QualifiedName, ValueRanks.OneDimension)); variables.Add(CreateVariable(arraysFolder, staticArrays + "SByte", "SByte", DataTypeIds.SByte, ValueRanks.OneDimension)); var stringArrayVar = CreateVariable(arraysFolder, staticArrays + "String", "String", DataTypeIds.String, ValueRanks.OneDimension); stringArrayVar.Value = new string[] { "Лошадь_ Пурпурово( Змейка( Слон", "猪 绿色 绵羊 大象~ 狗 菠萝 猪鼠", "Лошадь Овцы Голубика Овцы Змейка", "Чернота` Дракон Бело Дракон", "Horse# Black Lemon Lemon Grape", "猫< パイナップル; ドラゴン 犬 モモ", "레몬} 빨간% 자주색 쥐 백색; 들" , "Yellow Sheep Peach Elephant Cow", "Крыса Корова Свинья Собака Кот", "龙_ 绵羊 大象 芒果; 猫'" }; variables.Add(stringArrayVar); variables.Add(CreateVariable(arraysFolder, staticArrays + "TimeString", "TimeString", DataTypeIds.TimeString, ValueRanks.OneDimension)); variables.Add(CreateVariable(arraysFolder, staticArrays + "UInt16", "UInt16", DataTypeIds.UInt16, ValueRanks.OneDimension)); variables.Add(CreateVariable(arraysFolder, staticArrays + "UInt32", "UInt32", DataTypeIds.UInt32, ValueRanks.OneDimension)); variables.Add(CreateVariable(arraysFolder, staticArrays + "UInt64", "UInt64", DataTypeIds.UInt64, ValueRanks.OneDimension)); variables.Add(CreateVariable(arraysFolder, staticArrays + "UInteger", "UInteger", DataTypeIds.UInteger, ValueRanks.OneDimension)); variables.Add(CreateVariable(arraysFolder, staticArrays + "UtcTime", "UtcTime", DataTypeIds.UtcTime, ValueRanks.OneDimension)); variables.Add(CreateVariable(arraysFolder, staticArrays + "Variant", "Variant", BuiltInType.Variant, ValueRanks.OneDimension)); variables.Add(CreateVariable(arraysFolder, staticArrays + "XmlElement", "XmlElement", DataTypeIds.XmlElement, ValueRanks.OneDimension)); // Scalar_Static_Arrays2D ResetRandomGenerator(3); var arrays2DFolder = CreateFolder(staticFolder, "Scalar_Static_Arrays2D", "Arrays2D"); const string staticArrays2D = "Scalar_Static_Arrays2D_"; variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "Boolean", "Boolean", DataTypeIds.Boolean, ValueRanks.TwoDimensions)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "Byte", "Byte", DataTypeIds.Byte, ValueRanks.TwoDimensions)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "ByteString", "ByteString", DataTypeIds.ByteString, ValueRanks.TwoDimensions)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "DateTime", "DateTime", DataTypeIds.DateTime, ValueRanks.TwoDimensions)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "Double", "Double", DataTypeIds.Double, ValueRanks.TwoDimensions)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "Duration", "Duration", DataTypeIds.Duration, ValueRanks.TwoDimensions)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "Float", "Float", DataTypeIds.Float, ValueRanks.TwoDimensions)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "Guid", "Guid", DataTypeIds.Guid, ValueRanks.TwoDimensions)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "Int16", "Int16", DataTypeIds.Int16, ValueRanks.TwoDimensions)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "Int32", "Int32", DataTypeIds.Int32, ValueRanks.TwoDimensions)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "Int64", "Int64", DataTypeIds.Int64, ValueRanks.TwoDimensions)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "Integer", "Integer", DataTypeIds.Integer, ValueRanks.TwoDimensions)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "LocaleId", "LocaleId", DataTypeIds.LocaleId, ValueRanks.TwoDimensions)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "LocalizedText", "LocalizedText", DataTypeIds.LocalizedText, ValueRanks.TwoDimensions).MinimumSamplingInterval(1000)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "NodeId", "NodeId", DataTypeIds.NodeId, ValueRanks.TwoDimensions)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "Number", "Number", DataTypeIds.Number, ValueRanks.TwoDimensions)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "QualifiedName", "QualifiedName", DataTypeIds.QualifiedName, ValueRanks.TwoDimensions)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "SByte", "SByte", DataTypeIds.SByte, ValueRanks.TwoDimensions)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "String", "String", DataTypeIds.String, ValueRanks.TwoDimensions)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "TimeString", "TimeString", DataTypeIds.TimeString, ValueRanks.TwoDimensions)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "UInt16", "UInt16", DataTypeIds.UInt16, ValueRanks.TwoDimensions)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "UInt32", "UInt32", DataTypeIds.UInt32, ValueRanks.TwoDimensions)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "UInt64", "UInt64", DataTypeIds.UInt64, ValueRanks.TwoDimensions)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "UInteger", "UInteger", DataTypeIds.UInteger, ValueRanks.TwoDimensions)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "UtcTime", "UtcTime", DataTypeIds.UtcTime, ValueRanks.TwoDimensions)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "Variant", "Variant", BuiltInType.Variant, ValueRanks.TwoDimensions)); variables.Add(CreateVariable(arrays2DFolder, staticArrays2D + "XmlElement", "XmlElement", DataTypeIds.XmlElement, ValueRanks.TwoDimensions).MinimumSamplingInterval(1000)); // Scalar_Static_ArrayDynamic ResetRandomGenerator(4); var arrayDynamicFolder = CreateFolder(staticFolder, "Scalar_Static_ArrayDynamic", "ArrayDynamic"); const string staticArraysDynamic = "Scalar_Static_ArrayDynamic_"; variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "Boolean", "Boolean", DataTypeIds.Boolean, ValueRanks.OneOrMoreDimensions)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "Byte", "Byte", DataTypeIds.Byte, ValueRanks.OneOrMoreDimensions)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "ByteString", "ByteString", DataTypeIds.ByteString, ValueRanks.OneOrMoreDimensions)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "DateTime", "DateTime", DataTypeIds.DateTime, ValueRanks.OneOrMoreDimensions)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "Double", "Double", DataTypeIds.Double, ValueRanks.OneOrMoreDimensions)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "Duration", "Duration", DataTypeIds.Duration, ValueRanks.OneOrMoreDimensions)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "Float", "Float", DataTypeIds.Float, ValueRanks.OneOrMoreDimensions)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "Guid", "Guid", DataTypeIds.Guid, ValueRanks.OneOrMoreDimensions)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "Int16", "Int16", DataTypeIds.Int16, ValueRanks.OneOrMoreDimensions)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "Int32", "Int32", DataTypeIds.Int32, ValueRanks.OneOrMoreDimensions)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "Int64", "Int64", DataTypeIds.Int64, ValueRanks.OneOrMoreDimensions)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "Integer", "Integer", DataTypeIds.Integer, ValueRanks.OneOrMoreDimensions)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "LocaleId", "LocaleId", DataTypeIds.LocaleId, ValueRanks.OneOrMoreDimensions)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "LocalizedText", "LocalizedText", DataTypeIds.LocalizedText, ValueRanks.OneOrMoreDimensions).MinimumSamplingInterval(1000)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "NodeId", "NodeId", DataTypeIds.NodeId, ValueRanks.OneOrMoreDimensions)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "Number", "Number", DataTypeIds.Number, ValueRanks.OneOrMoreDimensions)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "QualifiedName", "QualifiedName", DataTypeIds.QualifiedName, ValueRanks.OneOrMoreDimensions).MinimumSamplingInterval(1000)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "SByte", "SByte", DataTypeIds.SByte, ValueRanks.OneOrMoreDimensions)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "String", "String", DataTypeIds.String, ValueRanks.OneOrMoreDimensions)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "TimeString", "TimeString", DataTypeIds.TimeString, ValueRanks.OneOrMoreDimensions)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "UInt16", "UInt16", DataTypeIds.UInt16, ValueRanks.OneOrMoreDimensions)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "UInt32", "UInt32", DataTypeIds.UInt32, ValueRanks.OneOrMoreDimensions)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "UInt64", "UInt64", DataTypeIds.UInt64, ValueRanks.OneOrMoreDimensions)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "UInteger", "UInteger", DataTypeIds.UInteger, ValueRanks.OneOrMoreDimensions)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "UtcTime", "UtcTime", DataTypeIds.UtcTime, ValueRanks.OneOrMoreDimensions)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "Variant", "Variant", BuiltInType.Variant, ValueRanks.OneOrMoreDimensions)); variables.Add(CreateVariable(arrayDynamicFolder, staticArraysDynamic + "XmlElement", "XmlElement", DataTypeIds.XmlElement, ValueRanks.OneOrMoreDimensions).MinimumSamplingInterval(1000)); // Scalar_Static_Mass ResetRandomGenerator(5); // create 100 instances of each static scalar type var massFolder = CreateFolder(staticFolder, "Scalar_Static_Mass", "Mass"); const string staticMass = "Scalar_Static_Mass_"; variables.AddRange(CreateVariables(massFolder, staticMass + "Boolean", "Boolean", DataTypeIds.Boolean, ValueRanks.Scalar, 100)); variables.AddRange(CreateVariables(massFolder, staticMass + "Byte", "Byte", DataTypeIds.Byte, ValueRanks.Scalar, 100)); variables.AddRange(CreateVariables(massFolder, staticMass + "ByteString", "ByteString", DataTypeIds.ByteString, ValueRanks.Scalar, 100)); variables.AddRange(CreateVariables(massFolder, staticMass + "DateTime", "DateTime", DataTypeIds.DateTime, ValueRanks.Scalar, 100)); variables.AddRange(CreateVariables(massFolder, staticMass + "Double", "Double", DataTypeIds.Double, ValueRanks.Scalar, 100)); variables.AddRange(CreateVariables(massFolder, staticMass + "Duration", "Duration", DataTypeIds.Duration, ValueRanks.Scalar, 100)); variables.AddRange(CreateVariables(massFolder, staticMass + "Float", "Float", DataTypeIds.Float, ValueRanks.Scalar, 100)); variables.AddRange(CreateVariables(massFolder, staticMass + "Guid", "Guid", DataTypeIds.Guid, ValueRanks.Scalar, 100)); variables.AddRange(CreateVariables(massFolder, staticMass + "Int16", "Int16", DataTypeIds.Int16, ValueRanks.Scalar, 100)); variables.AddRange(CreateVariables(massFolder, staticMass + "Int32", "Int32", DataTypeIds.Int32, ValueRanks.Scalar, 100)); variables.AddRange(CreateVariables(massFolder, staticMass + "Int64", "Int64", DataTypeIds.Int64, ValueRanks.Scalar, 100)); variables.AddRange(CreateVariables(massFolder, staticMass + "Integer", "Integer", DataTypeIds.Integer, ValueRanks.Scalar, 100)); variables.AddRange(CreateVariables(massFolder, staticMass + "LocalizedText", "LocalizedText", DataTypeIds.LocalizedText, ValueRanks.Scalar, 100)); variables.AddRange(CreateVariables(massFolder, staticMass + "NodeId", "NodeId", DataTypeIds.NodeId, ValueRanks.Scalar, 100)); variables.AddRange(CreateVariables(massFolder, staticMass + "Number", "Number", DataTypeIds.Number, ValueRanks.Scalar, 100)); variables.AddRange(CreateVariables(massFolder, staticMass + "SByte", "SByte", DataTypeIds.SByte, ValueRanks.Scalar, 100)); variables.AddRange(CreateVariables(massFolder, staticMass + "String", "String", DataTypeIds.String, ValueRanks.Scalar, 100)); variables.AddRange(CreateVariables(massFolder, staticMass + "TimeString", "TimeString", DataTypeIds.TimeString, ValueRanks.Scalar, 100)); variables.AddRange(CreateVariables(massFolder, staticMass + "UInt16", "UInt16", DataTypeIds.UInt16, ValueRanks.Scalar, 100)); variables.AddRange(CreateVariables(massFolder, staticMass + "UInt32", "UInt32", DataTypeIds.UInt32, ValueRanks.Scalar, 100)); variables.AddRange(CreateVariables(massFolder, staticMass + "UInt64", "UInt64", DataTypeIds.UInt64, ValueRanks.Scalar, 100)); variables.AddRange(CreateVariables(massFolder, staticMass + "UInteger", "UInteger", DataTypeIds.UInteger, ValueRanks.Scalar, 100)); variables.AddRange(CreateVariables(massFolder, staticMass + "UtcTime", "UtcTime", DataTypeIds.UtcTime, ValueRanks.Scalar, 100)); variables.AddRange(CreateVariables(massFolder, staticMass + "Variant", "Variant", BuiltInType.Variant, ValueRanks.Scalar, 100)); variables.AddRange(CreateVariables(massFolder, staticMass + "XmlElement", "XmlElement", DataTypeIds.XmlElement, ValueRanks.Scalar, 100)); // Scalar_Simulation ResetRandomGenerator(6); var simulationFolder = CreateFolder(scalarFolder, "Scalar_Simulation", "Simulation"); const string scalarSimulation = "Scalar_Simulation_"; CreateDynamicVariable(simulationFolder, scalarSimulation + "Boolean", "Boolean", DataTypeIds.Boolean, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "Byte", "Byte", DataTypeIds.Byte, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "ByteString", "ByteString", DataTypeIds.ByteString, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "DateTime", "DateTime", DataTypeIds.DateTime, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "Double", "Double", DataTypeIds.Double, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "Duration", "Duration", DataTypeIds.Duration, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "Float", "Float", DataTypeIds.Float, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "Guid", "Guid", DataTypeIds.Guid, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "Int16", "Int16", DataTypeIds.Int16, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "Int32", "Int32", DataTypeIds.Int32, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "Int64", "Int64", DataTypeIds.Int64, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "Integer", "Integer", DataTypeIds.Integer, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "LocaleId", "LocaleId", DataTypeIds.LocaleId, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "LocalizedText", "LocalizedText", DataTypeIds.LocalizedText, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "NodeId", "NodeId", DataTypeIds.NodeId, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "Number", "Number", DataTypeIds.Number, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "QualifiedName", "QualifiedName", DataTypeIds.QualifiedName, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "SByte", "SByte", DataTypeIds.SByte, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "String", "String", DataTypeIds.String, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "TimeString", "TimeString", DataTypeIds.TimeString, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "UInt16", "UInt16", DataTypeIds.UInt16, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "UInt32", "UInt32", DataTypeIds.UInt32, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "UInt64", "UInt64", DataTypeIds.UInt64, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "UInteger", "UInteger", DataTypeIds.UInteger, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "UtcTime", "UtcTime", DataTypeIds.UtcTime, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "Variant", "Variant", BuiltInType.Variant, ValueRanks.Scalar); CreateDynamicVariable(simulationFolder, scalarSimulation + "XmlElement", "XmlElement", DataTypeIds.XmlElement, ValueRanks.Scalar); var intervalVariable = CreateVariable(simulationFolder, scalarSimulation + "Interval", "Interval", DataTypeIds.UInt16, ValueRanks.Scalar); intervalVariable.Value = _simulationInterval; intervalVariable.OnSimpleWriteValue = OnWriteInterval; var enabledVariable = CreateVariable(simulationFolder, scalarSimulation + "Enabled", "Enabled", DataTypeIds.Boolean, ValueRanks.Scalar); enabledVariable.Value = _simulationEnabled; enabledVariable.OnSimpleWriteValue = OnWriteEnabled; // Scalar_Simulation_Arrays ResetRandomGenerator(7); var arraysSimulationFolder = CreateFolder(simulationFolder, "Scalar_Simulation_Arrays", "Arrays"); const string simulationArrays = "Scalar_Simulation_Arrays_"; CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "Boolean", "Boolean", DataTypeIds.Boolean, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "Byte", "Byte", DataTypeIds.Byte, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "ByteString", "ByteString", DataTypeIds.ByteString, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "DateTime", "DateTime", DataTypeIds.DateTime, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "Double", "Double", DataTypeIds.Double, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "Duration", "Duration", DataTypeIds.Duration, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "Float", "Float", DataTypeIds.Float, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "Guid", "Guid", DataTypeIds.Guid, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "Int16", "Int16", DataTypeIds.Int16, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "Int32", "Int32", DataTypeIds.Int32, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "Int64", "Int64", DataTypeIds.Int64, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "Integer", "Integer", DataTypeIds.Integer, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "LocaleId", "LocaleId", DataTypeIds.LocaleId, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "LocalizedText", "LocalizedText", DataTypeIds.LocalizedText, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "NodeId", "NodeId", DataTypeIds.NodeId, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "Number", "Number", DataTypeIds.Number, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "QualifiedName", "QualifiedName", DataTypeIds.QualifiedName, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "SByte", "SByte", DataTypeIds.SByte, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "String", "String", DataTypeIds.String, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "TimeString", "TimeString", DataTypeIds.TimeString, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "UInt16", "UInt16", DataTypeIds.UInt16, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "UInt32", "UInt32", DataTypeIds.UInt32, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "UInt64", "UInt64", DataTypeIds.UInt64, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "UInteger", "UInteger", DataTypeIds.UInteger, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "UtcTime", "UtcTime", DataTypeIds.UtcTime, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "Variant", "Variant", BuiltInType.Variant, ValueRanks.OneDimension); CreateDynamicVariable(arraysSimulationFolder, simulationArrays + "XmlElement", "XmlElement", DataTypeIds.XmlElement, ValueRanks.OneDimension); // Scalar_Simulation_Mass ResetRandomGenerator(8); var massSimulationFolder = CreateFolder(simulationFolder, "Scalar_Simulation_Mass", "Mass"); const string massSimulation = "Scalar_Simulation_Mass_"; CreateDynamicVariables(massSimulationFolder, massSimulation + "Boolean", "Boolean", DataTypeIds.Boolean, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "Byte", "Byte", DataTypeIds.Byte, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "ByteString", "ByteString", DataTypeIds.ByteString, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "DateTime", "DateTime", DataTypeIds.DateTime, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "Double", "Double", DataTypeIds.Double, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "Duration", "Duration", DataTypeIds.Duration, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "Float", "Float", DataTypeIds.Float, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "Guid", "Guid", DataTypeIds.Guid, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "Int16", "Int16", DataTypeIds.Int16, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "Int32", "Int32", DataTypeIds.Int32, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "Int64", "Int64", DataTypeIds.Int64, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "Integer", "Integer", DataTypeIds.Integer, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "LocaleId", "LocaleId", DataTypeIds.LocaleId, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "LocalizedText", "LocalizedText", DataTypeIds.LocalizedText, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "NodeId", "NodeId", DataTypeIds.NodeId, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "Number", "Number", DataTypeIds.Number, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "QualifiedName", "QualifiedName", DataTypeIds.QualifiedName, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "SByte", "SByte", DataTypeIds.SByte, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "String", "String", DataTypeIds.String, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "TimeString", "TimeString", DataTypeIds.TimeString, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "UInt16", "UInt16", DataTypeIds.UInt16, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "UInt32", "UInt32", DataTypeIds.UInt32, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "UInt64", "UInt64", DataTypeIds.UInt64, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "UInteger", "UInteger", DataTypeIds.UInteger, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "UtcTime", "UtcTime", DataTypeIds.UtcTime, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "Variant", "Variant", BuiltInType.Variant, ValueRanks.Scalar, 100); CreateDynamicVariables(massSimulationFolder, massSimulation + "XmlElement", "XmlElement", DataTypeIds.XmlElement, ValueRanks.Scalar, 100); // DataAccess_DataItem ResetRandomGenerator(9); var daFolder = CreateFolder(root, "DataAccess", "DataAccess"); var daInstructions = CreateVariable(daFolder, "DataAccess_Instructions", "Instructions", DataTypeIds.String, ValueRanks.Scalar); daInstructions.Value = "A library of Read/Write Variables of all supported data-types."; variables.Add(daInstructions); var dataItemFolder = CreateFolder(daFolder, "DataAccess_DataItem", "DataItem"); const string daDataItem = "DataAccess_DataIte_"; foreach (var name in Enum.GetNames()) { var item = CreateDataItemVariable(dataItemFolder, daDataItem + name, name, Enum.Parse(name), ValueRanks.Scalar); // set initial value to String.Empty for String node. if (name == nameof(BuiltInType.String)) { item.Value = string.Empty; } } // DataAccess_AnalogType ResetRandomGenerator(10); var analogItemFolder = CreateFolder(daFolder, "DataAccess_AnalogType", "AnalogType"); const string daAnalogItem = "DataAccess_AnalogType_"; foreach (var name in Enum.GetNames()) { var builtInType = Enum.Parse(name); if (IsAnalogType(builtInType)) { var item = CreateAnalogItemVariable(analogItemFolder, daAnalogItem + name, name, builtInType, ValueRanks.Scalar); if (builtInType == BuiltInType.Int64 || builtInType == BuiltInType.UInt64) { // make test case without optional ranges item.EngineeringUnits = null; item.InstrumentRange = null; } else if (builtInType == BuiltInType.Float) { item.EURange.Value.High = 0; item.EURange.Value.Low = 0; } //set default value for Definition property if (item.Definition != null) { item.Definition.Value = string.Empty; } } } // DataAccess_AnalogType_Array ResetRandomGenerator(11); var analogArrayFolder = CreateFolder(analogItemFolder, "DataAccess_AnalogType_Array", "Array"); const string daAnalogArray = "DataAccess_AnalogType_Array_"; CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "Boolean", "Boolean", BuiltInType.Boolean, ValueRanks.OneDimension, new bool[] { true, false, true, false, true, false, true, false, true }); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "Byte", "Byte", BuiltInType.Byte, ValueRanks.OneDimension, new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "ByteString", "ByteString", BuiltInType.ByteString, ValueRanks.OneDimension, new byte[][] { [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] }); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "DateTime", "DateTime", BuiltInType.DateTime, ValueRanks.OneDimension, new DateTime[] { DateTime.MinValue, DateTime.MaxValue, DateTime.MinValue, DateTime.MaxValue, DateTime.MinValue, DateTime.MaxValue, DateTime.MinValue, DateTime.MaxValue, DateTime.MinValue }); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "Double", "Double", BuiltInType.Double, ValueRanks.OneDimension, new double[] { 9.00001d, 9.0002d, 9.003d, 9.04d, 9.5d, 9.06d, 9.007d, 9.008d, 9.0009d }); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "Duration", "Duration", DataTypeIds.Duration, ValueRanks.OneDimension, new double[] { 9.00001d, 9.0002d, 9.003d, 9.04d, 9.5d, 9.06d, 9.007d, 9.008d, 9.0009d }, null); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "Float", "Float", BuiltInType.Float, ValueRanks.OneDimension, new float[] { 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 1.1f, 2.2f, 3.3f, 4.4f, 5.5f }); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "Guid", "Guid", BuiltInType.Guid, ValueRanks.OneDimension, new Guid[] { Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid() }); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "Int16", "Int16", BuiltInType.Int16, ValueRanks.OneDimension, new short[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "Int32", "Int32", BuiltInType.Int32, ValueRanks.OneDimension, new int[] { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "Int64", "Int64", BuiltInType.Int64, ValueRanks.OneDimension, new long[] { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "Integer", "Integer", BuiltInType.Integer, ValueRanks.OneDimension, new long[] { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "LocaleId", "LocaleId", DataTypeIds.LocaleId, ValueRanks.OneDimension, new string[] { "en", "fr", "de", "en", "fr", "de", "en", "fr", "de", "en" }, null); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "LocalizedText", "LocalizedText", BuiltInType.LocalizedText, ValueRanks.OneDimension, new LocalizedText[] { new("en", "Hello World1"), new("en", "Hello World2"), new("en", "Hello World3"), new("en", "Hello World4"), new("en", "Hello World5"), new("en", "Hello World6"), new("en", "Hello World7"), new("en", "Hello World8"), new("en", "Hello World9"), new("en", "Hello World10") }); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "NodeId", "NodeId", BuiltInType.NodeId, ValueRanks.OneDimension, new NodeId[] { new(Guid.NewGuid()), new(Guid.NewGuid()), new(Guid.NewGuid()), new(Guid.NewGuid()), new(Guid.NewGuid()), new(Guid.NewGuid()), new(Guid.NewGuid()), new(Guid.NewGuid()), new(Guid.NewGuid()), new(Guid.NewGuid()) }); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "Number", "Number", BuiltInType.Number, ValueRanks.OneDimension, new short[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "QualifiedName", "QualifiedName", BuiltInType.QualifiedName, ValueRanks.OneDimension, new short[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "SByte", "SByte", BuiltInType.SByte, ValueRanks.OneDimension, new sbyte[] { 10, 20, 30, 40, 50, 60, 70, 80, 90 }); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "String", "String", BuiltInType.String, ValueRanks.OneDimension, new string[] { "a00", "b10", "c20", "d30", "e40", "f50", "g60", "h70", "i80", "j90" }); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "TimeString", "TimeString", DataTypeIds.TimeString, ValueRanks.OneDimension, new string[] { DateTime.MinValue.ToString(CultureInfo.InvariantCulture), DateTime.MaxValue.ToString(CultureInfo.InvariantCulture), DateTime.MinValue.ToString(CultureInfo.InvariantCulture), DateTime.MaxValue.ToString(CultureInfo.InvariantCulture), DateTime.MinValue.ToString(CultureInfo.InvariantCulture), DateTime.MaxValue.ToString(CultureInfo.InvariantCulture), DateTime.MinValue.ToString(CultureInfo.InvariantCulture), DateTime.MaxValue.ToString(CultureInfo.InvariantCulture), DateTime.MinValue.ToString(CultureInfo.InvariantCulture), DateTime.MaxValue.ToString(CultureInfo.InvariantCulture) }, null); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "UInt16", "UInt16", BuiltInType.UInt16, ValueRanks.OneDimension, new ushort[] { 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 }); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "UInt32", "UInt32", BuiltInType.UInt32, ValueRanks.OneDimension, new uint[] { 30, 31, 32, 33, 34, 35, 36, 37, 38, 39 }); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "UInt64", "UInt64", BuiltInType.UInt64, ValueRanks.OneDimension, new ulong[] { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "UInteger", "UInteger", BuiltInType.UInteger, ValueRanks.OneDimension, new ulong[] { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "UtcTime", "UtcTime", DataTypeIds.UtcTime, ValueRanks.OneDimension, new DateTime[] { DateTime.MinValue.ToUniversalTime(), DateTime.MaxValue.ToUniversalTime(), DateTime.MinValue.ToUniversalTime(), DateTime.MaxValue.ToUniversalTime(), DateTime.MinValue.ToUniversalTime(), DateTime.MaxValue.ToUniversalTime(), DateTime.MinValue.ToUniversalTime(), DateTime.MaxValue.ToUniversalTime(), DateTime.MinValue.ToUniversalTime() }, null); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "Variant", "Variant", BuiltInType.Variant, ValueRanks.OneDimension, new Variant[] { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }); var doc1 = new XmlDocument(); CreateAnalogItemVariable(analogArrayFolder, daAnalogArray + "XmlElement", "XmlElement", BuiltInType.XmlElement, ValueRanks.OneDimension, new XmlElement[] { doc1.CreateElement("tag1"), doc1.CreateElement("tag2"), doc1.CreateElement("tag3"), doc1.CreateElement("tag4"), doc1.CreateElement("tag5"), doc1.CreateElement("tag6"), doc1.CreateElement("tag7"), doc1.CreateElement("tag8"), doc1.CreateElement("tag9"), doc1.CreateElement("tag10") }); // DataAccess_DiscreteType ResetRandomGenerator(12); var discreteTypeFolder = CreateFolder(daFolder, "DataAccess_DiscreteType", "DiscreteType"); var twoStateDiscreteFolder = CreateFolder(discreteTypeFolder, "DataAccess_TwoStateDiscreteType", "TwoStateDiscreteType"); const string daTwoStateDiscrete = "DataAccess_TwoStateDiscreteType_"; // Add our Nodes to the folder, and specify their customized discrete enumerations CreateTwoStateDiscreteItemVariable(twoStateDiscreteFolder, daTwoStateDiscrete + "001", "001", "red", "blue"); CreateTwoStateDiscreteItemVariable(twoStateDiscreteFolder, daTwoStateDiscrete + "002", "002", "open", "close"); CreateTwoStateDiscreteItemVariable(twoStateDiscreteFolder, daTwoStateDiscrete + "003", "003", "up", "down"); CreateTwoStateDiscreteItemVariable(twoStateDiscreteFolder, daTwoStateDiscrete + "004", "004", "left", "right"); CreateTwoStateDiscreteItemVariable(twoStateDiscreteFolder, daTwoStateDiscrete + "005", "005", "circle", "cross"); var multiStateDiscreteFolder = CreateFolder(discreteTypeFolder, "DataAccess_MultiStateDiscreteType", "MultiStateDiscreteType"); const string daMultiStateDiscrete = "DataAccess_MultiStateDiscreteType_"; // Add our Nodes to the folder, and specify their customized discrete enumerations CreateMultiStateDiscreteItemVariable(multiStateDiscreteFolder, daMultiStateDiscrete + "001", "001", "open", "closed", "jammed"); CreateMultiStateDiscreteItemVariable(multiStateDiscreteFolder, daMultiStateDiscrete + "002", "002", "red", "green", "blue", "cyan"); CreateMultiStateDiscreteItemVariable(multiStateDiscreteFolder, daMultiStateDiscrete + "003", "003", "lolo", "lo", "normal", "hi", "hihi"); CreateMultiStateDiscreteItemVariable(multiStateDiscreteFolder, daMultiStateDiscrete + "004", "004", "left", "right", "center"); CreateMultiStateDiscreteItemVariable(multiStateDiscreteFolder, daMultiStateDiscrete + "005", "005", "circle", "cross", "triangle"); // DataAccess_MultiStateValueDiscreteType ResetRandomGenerator(13); var multiStateValueDiscreteFolder = CreateFolder(discreteTypeFolder, "DataAccess_MultiStateValueDiscreteType", "MultiStateValueDiscreteType"); const string daMultiStateValueDiscrete = "DataAccess_MultiStateValueDiscreteType_"; // Add our Nodes to the folder, and specify their customized discrete enumerations CreateMultiStateValueDiscreteItemVariable(multiStateValueDiscreteFolder, daMultiStateValueDiscrete + "001", "001", ["open", "closed", "jammed"]); CreateMultiStateValueDiscreteItemVariable(multiStateValueDiscreteFolder, daMultiStateValueDiscrete + "002", "002", ["red", "green", "blue", "cyan"]); CreateMultiStateValueDiscreteItemVariable(multiStateValueDiscreteFolder, daMultiStateValueDiscrete + "003", "003", ["lolo", "lo", "normal", "hi", "hihi"]); CreateMultiStateValueDiscreteItemVariable(multiStateValueDiscreteFolder, daMultiStateValueDiscrete + "004", "004", ["left", "right", "center"]); CreateMultiStateValueDiscreteItemVariable(multiStateValueDiscreteFolder, daMultiStateValueDiscrete + "005", "005", ["circle", "cross", "triangle"]); // Add our Nodes to the folder and specify varying data types CreateMultiStateValueDiscreteItemVariable(multiStateValueDiscreteFolder, daMultiStateValueDiscrete + "Byte", "Byte", DataTypeIds.Byte, ["open", "closed", "jammed"]); CreateMultiStateValueDiscreteItemVariable(multiStateValueDiscreteFolder, daMultiStateValueDiscrete + "Int16", "Int16", DataTypeIds.Int16, ["red", "green", "blue", "cyan"]); CreateMultiStateValueDiscreteItemVariable(multiStateValueDiscreteFolder, daMultiStateValueDiscrete + "Int32", "Int32", DataTypeIds.Int32, ["lolo", "lo", "normal", "hi", "hihi"]); CreateMultiStateValueDiscreteItemVariable(multiStateValueDiscreteFolder, daMultiStateValueDiscrete + "Int64", "Int64", DataTypeIds.Int64, ["left", "right", "center"]); CreateMultiStateValueDiscreteItemVariable(multiStateValueDiscreteFolder, daMultiStateValueDiscrete + "SByte", "SByte", DataTypeIds.SByte, ["open", "closed", "jammed"]); CreateMultiStateValueDiscreteItemVariable(multiStateValueDiscreteFolder, daMultiStateValueDiscrete + "UInt16", "UInt16", DataTypeIds.UInt16, ["red", "green", "blue", "cyan"]); CreateMultiStateValueDiscreteItemVariable(multiStateValueDiscreteFolder, daMultiStateValueDiscrete + "UInt32", "UInt32", DataTypeIds.UInt32, ["lolo", "lo", "normal", "hi", "hihi"]); CreateMultiStateValueDiscreteItemVariable(multiStateValueDiscreteFolder, daMultiStateValueDiscrete + "UInt64", "UInt64", DataTypeIds.UInt64, ["left", "right", "center"]); // References ResetRandomGenerator(14); var referencesFolder = CreateFolder(root, "References", "References"); const string referencesPrefix = "References_"; var referencesInstructions = CreateVariable(referencesFolder, "References_Instructions", "Instructions", DataTypeIds.String, ValueRanks.Scalar); referencesInstructions.Value = "This folder will contain nodes that have specific Reference configurations."; variables.Add(referencesInstructions); // create variable nodes with specific references var hasForwardReference = CreateMeshVariable(referencesFolder, referencesPrefix + "HasForwardReference", "HasForwardReference"); hasForwardReference.AddReference(ReferenceTypes.HasCause, false, variables[0].NodeId); variables.Add(hasForwardReference); var hasInverseReference = CreateMeshVariable(referencesFolder, referencesPrefix + "HasInverseReference", "HasInverseReference"); hasInverseReference.AddReference(ReferenceTypes.HasCause, true, variables[0].NodeId); variables.Add(hasInverseReference); BaseDataVariableState has3InverseReference = null; for (var i = 1; i <= 5; i++) { var referenceString = "Has3ForwardReferences"; if (i > 1) { referenceString += i.ToString(CultureInfo.InvariantCulture); } var has3ForwardReferences = CreateMeshVariable(referencesFolder, referencesPrefix + referenceString, referenceString); has3ForwardReferences.AddReference(ReferenceTypes.HasCause, false, variables[0].NodeId); has3ForwardReferences.AddReference(ReferenceTypes.HasCause, false, variables[1].NodeId); has3ForwardReferences.AddReference(ReferenceTypes.HasCause, false, variables[2].NodeId); if (i == 1) { has3InverseReference = has3ForwardReferences; } variables.Add(has3ForwardReferences); } var has3InverseReferences = CreateMeshVariable(referencesFolder, referencesPrefix + "Has3InverseReferences", "Has3InverseReferences"); has3InverseReferences.AddReference(ReferenceTypes.HasEffect, true, variables[0].NodeId); has3InverseReferences.AddReference(ReferenceTypes.HasEffect, true, variables[1].NodeId); has3InverseReferences.AddReference(ReferenceTypes.HasEffect, true, variables[2].NodeId); variables.Add(has3InverseReferences); var hasForwardAndInverseReferences = CreateMeshVariable(referencesFolder, referencesPrefix + "HasForwardAndInverseReference", "HasForwardAndInverseReference", hasForwardReference, hasInverseReference, has3InverseReference, has3InverseReferences, variables[0]); variables.Add(hasForwardAndInverseReferences); // AccessRights ResetRandomGenerator(15); var folderAccessRights = CreateFolder(root, "AccessRights", "AccessRights"); const string accessRights = "AccessRights_"; var accessRightsInstructions = CreateVariable(folderAccessRights, accessRights + "Instructions", "Instructions", DataTypeIds.String, ValueRanks.Scalar); accessRightsInstructions.Value = "This folder will be accessible to all who enter, but contents therein will be secured."; variables.Add(accessRightsInstructions); // sub-folder for "AccessAll" var folderAccessRightsAccessAll = CreateFolder(folderAccessRights, "AccessRights_AccessAll", "AccessAll"); const string accessRightsAccessAll = "AccessRights_AccessAll_"; var arAllRO = CreateVariable(folderAccessRightsAccessAll, accessRightsAccessAll + "RO", "RO", BuiltInType.Int16, ValueRanks.Scalar); arAllRO.AccessLevel = AccessLevels.CurrentRead; arAllRO.UserAccessLevel = AccessLevels.CurrentRead; variables.Add(arAllRO); var arAllWO = CreateVariable(folderAccessRightsAccessAll, accessRightsAccessAll + "WO", "WO", BuiltInType.Int16, ValueRanks.Scalar); arAllWO.AccessLevel = AccessLevels.CurrentWrite; arAllWO.UserAccessLevel = AccessLevels.CurrentWrite; variables.Add(arAllWO); var arAllRW = CreateVariable(folderAccessRightsAccessAll, accessRightsAccessAll + "RW", "RW", BuiltInType.Int16, ValueRanks.Scalar); arAllRW.AccessLevel = AccessLevels.CurrentReadOrWrite; arAllRW.UserAccessLevel = AccessLevels.CurrentReadOrWrite; variables.Add(arAllRW); var arAllRONotUser = CreateVariable(folderAccessRightsAccessAll, accessRightsAccessAll + "RO_NotUser", "RO_NotUser", BuiltInType.Int16, ValueRanks.Scalar); arAllRONotUser.AccessLevel = AccessLevels.CurrentRead; arAllRONotUser.UserAccessLevel = AccessLevels.None; variables.Add(arAllRONotUser); var arAllWONotUser = CreateVariable(folderAccessRightsAccessAll, accessRightsAccessAll + "WO_NotUser", "WO_NotUser", BuiltInType.Int16, ValueRanks.Scalar); arAllWONotUser.AccessLevel = AccessLevels.CurrentWrite; arAllWONotUser.UserAccessLevel = AccessLevels.None; variables.Add(arAllWONotUser); var arAllRWNotUser = CreateVariable(folderAccessRightsAccessAll, accessRightsAccessAll + "RW_NotUser", "RW_NotUser", BuiltInType.Int16, ValueRanks.Scalar); arAllRWNotUser.AccessLevel = AccessLevels.CurrentReadOrWrite; arAllRWNotUser.UserAccessLevel = AccessLevels.CurrentRead; variables.Add(arAllRWNotUser); var arAllROUserRW = CreateVariable(folderAccessRightsAccessAll, accessRightsAccessAll + "RO_User1_RW", "RO_User1_RW", BuiltInType.Int16, ValueRanks.Scalar); arAllROUserRW.AccessLevel = AccessLevels.CurrentRead; arAllROUserRW.UserAccessLevel = AccessLevels.CurrentReadOrWrite; variables.Add(arAllROUserRW); var arAllROGroupRW = CreateVariable(folderAccessRightsAccessAll, accessRightsAccessAll + "RO_Group1_RW", "RO_Group1_RW", BuiltInType.Int16, ValueRanks.Scalar); arAllROGroupRW.AccessLevel = AccessLevels.CurrentRead; arAllROGroupRW.UserAccessLevel = AccessLevels.CurrentReadOrWrite; variables.Add(arAllROGroupRW); // sub-folder for "AccessUser1" var folderAccessRightsAccessUser1 = CreateFolder(folderAccessRights, "AccessRights_AccessUser1", "AccessUser1"); const string accessRightsAccessUser1 = "AccessRights_AccessUser1_"; var arUserRO = CreateVariable(folderAccessRightsAccessUser1, accessRightsAccessUser1 + "RO", "RO", BuiltInType.Int16, ValueRanks.Scalar); arUserRO.AccessLevel = AccessLevels.CurrentRead; arUserRO.UserAccessLevel = AccessLevels.CurrentRead; variables.Add(arUserRO); var arUserWO = CreateVariable(folderAccessRightsAccessUser1, accessRightsAccessUser1 + "WO", "WO", BuiltInType.Int16, ValueRanks.Scalar); arUserWO.AccessLevel = AccessLevels.CurrentWrite; arUserWO.UserAccessLevel = AccessLevels.CurrentWrite; variables.Add(arUserWO); var arUserRW = CreateVariable(folderAccessRightsAccessUser1, accessRightsAccessUser1 + "RW", "RW", BuiltInType.Int16, ValueRanks.Scalar); arUserRW.AccessLevel = AccessLevels.CurrentReadOrWrite; arUserRW.UserAccessLevel = AccessLevels.CurrentReadOrWrite; variables.Add(arUserRW); // sub-folder for "AccessGroup1" var folderAccessRightsAccessGroup1 = CreateFolder(folderAccessRights, "AccessRights_AccessGroup1", "AccessGroup1"); const string accessRightsAccessGroup1 = "AccessRights_AccessGroup1_"; var arGroupRO = CreateVariable(folderAccessRightsAccessGroup1, accessRightsAccessGroup1 + "RO", "RO", BuiltInType.Int16, ValueRanks.Scalar); arGroupRO.AccessLevel = AccessLevels.CurrentRead; arGroupRO.UserAccessLevel = AccessLevels.CurrentRead; variables.Add(arGroupRO); var arGroupWO = CreateVariable(folderAccessRightsAccessGroup1, accessRightsAccessGroup1 + "WO", "WO", BuiltInType.Int16, ValueRanks.Scalar); arGroupWO.AccessLevel = AccessLevels.CurrentWrite; arGroupWO.UserAccessLevel = AccessLevels.CurrentWrite; variables.Add(arGroupWO); var arGroupRW = CreateVariable(folderAccessRightsAccessGroup1, accessRightsAccessGroup1 + "RW", "RW", BuiltInType.Int16, ValueRanks.Scalar); arGroupRW.AccessLevel = AccessLevels.CurrentReadOrWrite; arGroupRW.UserAccessLevel = AccessLevels.CurrentReadOrWrite; variables.Add(arGroupRW); // sub folder for "RolePermissions" var folderRolePermissions = CreateFolder(folderAccessRights, "AccessRights_RolePermissions", "RolePermissions"); const string rolePermissions = "AccessRights_RolePermissions_"; var rpAnonymous = CreateVariable(folderRolePermissions, rolePermissions + "AnonymousAccess", "AnonymousAccess", BuiltInType.Int16, ValueRanks.Scalar); rpAnonymous.Description = "This node can be accessed by users that have Anonymous Role"; rpAnonymous.RolePermissions = [ // allow access to users with Anonymous role new RolePermissionType() { RoleId = ObjectIds.WellKnownRole_Anonymous, Permissions = (uint)(PermissionType.Browse |PermissionType.Read|PermissionType.ReadRolePermissions | PermissionType.Write) } ]; variables.Add(rpAnonymous); var rpAuthenticatedUser = CreateVariable(folderRolePermissions, rolePermissions + "AuthenticatedUser", "AuthenticatedUser", BuiltInType.Int16, ValueRanks.Scalar); rpAuthenticatedUser.Description = "This node can be accessed by users that have AuthenticatedUser Role"; rpAuthenticatedUser.RolePermissions = [ // allow access to users with AuthenticatedUser role new RolePermissionType() { RoleId = ObjectIds.WellKnownRole_AuthenticatedUser, Permissions = (uint)(PermissionType.Browse |PermissionType.Read|PermissionType.ReadRolePermissions | PermissionType.Write) } ]; variables.Add(rpAuthenticatedUser); var rpAdminUser = CreateVariable(folderRolePermissions, rolePermissions + "AdminUser", "AdminUser", BuiltInType.Int16, ValueRanks.Scalar); rpAdminUser.Description = "This node can be accessed by users that have SecurityAdmin Role over an encrypted connection"; rpAdminUser.AccessRestrictions = AccessRestrictionType.EncryptionRequired; rpAdminUser.RolePermissions = [ // allow access to users with SecurityAdmin role new RolePermissionType() { RoleId = ObjectIds.WellKnownRole_SecurityAdmin, Permissions = (uint)(PermissionType.Browse |PermissionType.Read|PermissionType.ReadRolePermissions | PermissionType.Write) } ]; variables.Add(rpAdminUser); // sub-folder for "AccessRestrictions" var folderAccessRestrictions = CreateFolder(folderAccessRights, "AccessRights_AccessRestrictions", "AccessRestrictions"); const string accessRestrictions = "AccessRights_AccessRestrictions_"; var arNone = CreateVariable(folderAccessRestrictions, accessRestrictions + "None", "None", BuiltInType.Int16, ValueRanks.Scalar); arNone.AccessLevel = AccessLevels.CurrentRead; arNone.UserAccessLevel = AccessLevels.CurrentRead; arNone.AccessRestrictions = AccessRestrictionType.None; variables.Add(arNone); var arSigningRequired = CreateVariable(folderAccessRestrictions, accessRestrictions + "SigningRequired", "SigningRequired", BuiltInType.Int16, ValueRanks.Scalar); arSigningRequired.AccessLevel = AccessLevels.CurrentRead; arSigningRequired.UserAccessLevel = AccessLevels.CurrentRead; arSigningRequired.AccessRestrictions = AccessRestrictionType.SigningRequired; variables.Add(arSigningRequired); var arEncryptionRequired = CreateVariable(folderAccessRestrictions, accessRestrictions + "EncryptionRequired", "EncryptionRequired", BuiltInType.Int16, ValueRanks.Scalar); arEncryptionRequired.AccessLevel = AccessLevels.CurrentRead; arEncryptionRequired.UserAccessLevel = AccessLevels.CurrentRead; arEncryptionRequired.AccessRestrictions = AccessRestrictionType.EncryptionRequired; variables.Add(arEncryptionRequired); var arSessionRequired = CreateVariable(folderAccessRestrictions, accessRestrictions + "SessionRequired", "SessionRequired", BuiltInType.Int16, ValueRanks.Scalar); arSessionRequired.AccessLevel = AccessLevels.CurrentRead; arSessionRequired.UserAccessLevel = AccessLevels.CurrentRead; arSessionRequired.AccessRestrictions = AccessRestrictionType.SessionRequired; variables.Add(arSessionRequired); // NodeIds ResetRandomGenerator(16); var nodeIdsFolder = CreateFolder(root, "NodeIds", "NodeIds"); const string nodeIds = "NodeIds_"; var nodeIdsInstructions = CreateVariable(folderAccessRights, nodeIds + "Instructions", "Instructions", DataTypeIds.String, ValueRanks.Scalar); nodeIdsInstructions.Value = "All supported Node types are available except whichever is in use for the other nodes."; variables.Add(nodeIdsInstructions); var integerNodeId = CreateVariable(nodeIdsFolder, nodeIds + "Int16Integer", "Int16Integer", DataTypeIds.Int16, ValueRanks.Scalar); integerNodeId.NodeId = new NodeId(9202, NamespaceIndex); variables.Add(integerNodeId); variables.Add(CreateVariable(nodeIdsFolder, nodeIds + "Int16String", "Int16String", DataTypeIds.Int16, ValueRanks.Scalar)); var guidNodeId = CreateVariable(nodeIdsFolder, nodeIds + "Int16GUID", "Int16GUID", DataTypeIds.Int16, ValueRanks.Scalar); guidNodeId.NodeId = new NodeId(new Guid("00000000-0000-0000-0000-000000009204"), NamespaceIndex); variables.Add(guidNodeId); var opaqueNodeId = CreateVariable(nodeIdsFolder, nodeIds + "Int16Opaque", "Int16Opaque", DataTypeIds.Int16, ValueRanks.Scalar); opaqueNodeId.NodeId = new NodeId([9, 2, 0, 5], NamespaceIndex); variables.Add(opaqueNodeId); // Methods ResetRandomGenerator(17); var methodsFolder = CreateFolder(root, "Methods", "Methods"); const string methods = "Methods_"; var methodsInstructions = CreateVariable(methodsFolder, methods + "Instructions", "Instructions", DataTypeIds.String, ValueRanks.Scalar); methodsInstructions.Value = "Contains methods with varying parameter definitions."; variables.Add(methodsInstructions); var voidMethod = CreateMethod(methodsFolder, methods + "Void", "Void"); voidMethod.OnCallMethod = new GenericMethodCalledEventHandler(OnVoidCall); // Add Method var addMethod = CreateMethod(methodsFolder, methods + "Add", "Add"); // set input arguments addMethod.InputArguments = new PropertyState(addMethod) { NodeId = new NodeId(addMethod.BrowseName.Name + "InArgs", NamespaceIndex), BrowseName = BrowseNames.InputArguments }; addMethod.InputArguments.DisplayName = addMethod.InputArguments.BrowseName.Name; addMethod.InputArguments.TypeDefinitionId = VariableTypeIds.PropertyType; addMethod.InputArguments.ReferenceTypeId = ReferenceTypeIds.HasProperty; addMethod.InputArguments.DataType = DataTypeIds.Argument; addMethod.InputArguments.ValueRank = ValueRanks.OneDimension; addMethod.InputArguments.Value = [ new() { Name = "Float value", Description = "Float value", DataType = DataTypeIds.Float, ValueRank = ValueRanks.Scalar }, new() { Name = "UInt32 value", Description = "UInt32 value", DataType = DataTypeIds.UInt32, ValueRank = ValueRanks.Scalar } ]; // set output arguments addMethod.OutputArguments = new PropertyState(addMethod) { NodeId = new NodeId(addMethod.BrowseName.Name + "OutArgs", NamespaceIndex), BrowseName = BrowseNames.OutputArguments }; addMethod.OutputArguments.DisplayName = addMethod.OutputArguments.BrowseName.Name; addMethod.OutputArguments.TypeDefinitionId = VariableTypeIds.PropertyType; addMethod.OutputArguments.ReferenceTypeId = ReferenceTypeIds.HasProperty; addMethod.OutputArguments.DataType = DataTypeIds.Argument; addMethod.OutputArguments.ValueRank = ValueRanks.OneDimension; addMethod.OutputArguments.Value = [ new() { Name = "Add Result", Description = "Add Result", DataType = DataTypeIds.Float, ValueRank = ValueRanks.Scalar } ]; addMethod.OnCallMethod = new GenericMethodCalledEventHandler(OnAddCall); // Multiply Method var multiplyMethod = CreateMethod(methodsFolder, methods + "Multiply", "Multiply"); // set input arguments multiplyMethod.InputArguments = new PropertyState(multiplyMethod) { NodeId = new NodeId(multiplyMethod.BrowseName.Name + "InArgs", NamespaceIndex), BrowseName = BrowseNames.InputArguments }; multiplyMethod.InputArguments.DisplayName = multiplyMethod.InputArguments.BrowseName.Name; multiplyMethod.InputArguments.TypeDefinitionId = VariableTypeIds.PropertyType; multiplyMethod.InputArguments.ReferenceTypeId = ReferenceTypeIds.HasProperty; multiplyMethod.InputArguments.DataType = DataTypeIds.Argument; multiplyMethod.InputArguments.ValueRank = ValueRanks.OneDimension; multiplyMethod.InputArguments.Value = [ new() { Name = "Int16 value", Description = "Int16 value", DataType = DataTypeIds.Int16, ValueRank = ValueRanks.Scalar }, new() { Name = "UInt16 value", Description = "UInt16 value", DataType = DataTypeIds.UInt16, ValueRank = ValueRanks.Scalar } ]; // set output arguments multiplyMethod.OutputArguments = new PropertyState(multiplyMethod) { NodeId = new NodeId(multiplyMethod.BrowseName.Name + "OutArgs", NamespaceIndex), BrowseName = BrowseNames.OutputArguments }; multiplyMethod.OutputArguments.DisplayName = multiplyMethod.OutputArguments.BrowseName.Name; multiplyMethod.OutputArguments.TypeDefinitionId = VariableTypeIds.PropertyType; multiplyMethod.OutputArguments.ReferenceTypeId = ReferenceTypeIds.HasProperty; multiplyMethod.OutputArguments.DataType = DataTypeIds.Argument; multiplyMethod.OutputArguments.ValueRank = ValueRanks.OneDimension; multiplyMethod.OutputArguments.Value = [ new() { Name = "Multiply Result", Description = "Multiply Result", DataType = DataTypeIds.Int32, ValueRank = ValueRanks.Scalar } ]; multiplyMethod.OnCallMethod = new GenericMethodCalledEventHandler(OnMultiplyCall); // Divide Method var divideMethod = CreateMethod(methodsFolder, methods + "Divide", "Divide"); // set input arguments divideMethod.InputArguments = new PropertyState(divideMethod) { NodeId = new NodeId(divideMethod.BrowseName.Name + "InArgs", NamespaceIndex), BrowseName = BrowseNames.InputArguments }; divideMethod.InputArguments.DisplayName = divideMethod.InputArguments.BrowseName.Name; divideMethod.InputArguments.TypeDefinitionId = VariableTypeIds.PropertyType; divideMethod.InputArguments.ReferenceTypeId = ReferenceTypeIds.HasProperty; divideMethod.InputArguments.DataType = DataTypeIds.Argument; divideMethod.InputArguments.ValueRank = ValueRanks.OneDimension; divideMethod.InputArguments.Value = [ new() { Name = "Int32 value", Description = "Int32 value", DataType = DataTypeIds.Int32, ValueRank = ValueRanks.Scalar }, new() { Name = "UInt16 value", Description = "UInt16 value", DataType = DataTypeIds.UInt16, ValueRank = ValueRanks.Scalar } ]; // set output arguments divideMethod.OutputArguments = new PropertyState(divideMethod) { NodeId = new NodeId(divideMethod.BrowseName.Name + "OutArgs", NamespaceIndex), BrowseName = BrowseNames.OutputArguments }; divideMethod.OutputArguments.DisplayName = divideMethod.OutputArguments.BrowseName.Name; divideMethod.OutputArguments.TypeDefinitionId = VariableTypeIds.PropertyType; divideMethod.OutputArguments.ReferenceTypeId = ReferenceTypeIds.HasProperty; divideMethod.OutputArguments.DataType = DataTypeIds.Argument; divideMethod.OutputArguments.ValueRank = ValueRanks.OneDimension; divideMethod.OutputArguments.Value = [ new() { Name = "Divide Result", Description = "Divide Result", DataType = DataTypeIds.Float, ValueRank = ValueRanks.Scalar } ]; divideMethod.OnCallMethod = new GenericMethodCalledEventHandler(OnDivideCall); // Substract Method var substractMethod = CreateMethod(methodsFolder, methods + "Substract", "Substract"); // set input arguments substractMethod.InputArguments = new PropertyState(substractMethod) { NodeId = new NodeId(substractMethod.BrowseName.Name + "InArgs", NamespaceIndex), BrowseName = BrowseNames.InputArguments }; substractMethod.InputArguments.DisplayName = substractMethod.InputArguments.BrowseName.Name; substractMethod.InputArguments.TypeDefinitionId = VariableTypeIds.PropertyType; substractMethod.InputArguments.ReferenceTypeId = ReferenceTypeIds.HasProperty; substractMethod.InputArguments.DataType = DataTypeIds.Argument; substractMethod.InputArguments.ValueRank = ValueRanks.OneDimension; substractMethod.InputArguments.Value = [ new() { Name = "Int16 value", Description = "Int16 value", DataType = DataTypeIds.Int16, ValueRank = ValueRanks.Scalar }, new() { Name = "Byte value", Description = "Byte value", DataType = DataTypeIds.Byte, ValueRank = ValueRanks.Scalar } ]; // set output arguments substractMethod.OutputArguments = new PropertyState(substractMethod) { NodeId = new NodeId(substractMethod.BrowseName.Name + "OutArgs", NamespaceIndex), BrowseName = BrowseNames.OutputArguments }; substractMethod.OutputArguments.DisplayName = substractMethod.OutputArguments.BrowseName.Name; substractMethod.OutputArguments.TypeDefinitionId = VariableTypeIds.PropertyType; substractMethod.OutputArguments.ReferenceTypeId = ReferenceTypeIds.HasProperty; substractMethod.OutputArguments.DataType = DataTypeIds.Argument; substractMethod.OutputArguments.ValueRank = ValueRanks.OneDimension; substractMethod.OutputArguments.Value = [ new() { Name = "Substract Result", Description = "Substract Result", DataType = DataTypeIds.Int16, ValueRank = ValueRanks.Scalar } ]; substractMethod.OnCallMethod = new GenericMethodCalledEventHandler(OnSubstractCall); // Hello Method var helloMethod = CreateMethod(methodsFolder, methods + "Hello", "Hello"); // set input arguments helloMethod.InputArguments = new PropertyState(helloMethod) { NodeId = new NodeId(helloMethod.BrowseName.Name + "InArgs", NamespaceIndex), BrowseName = BrowseNames.InputArguments }; helloMethod.InputArguments.DisplayName = helloMethod.InputArguments.BrowseName.Name; helloMethod.InputArguments.TypeDefinitionId = VariableTypeIds.PropertyType; helloMethod.InputArguments.ReferenceTypeId = ReferenceTypeIds.HasProperty; helloMethod.InputArguments.DataType = DataTypeIds.Argument; helloMethod.InputArguments.ValueRank = ValueRanks.OneDimension; helloMethod.InputArguments.Value = [ new() { Name = "String value", Description = "String value", DataType = DataTypeIds.String, ValueRank = ValueRanks.Scalar } ]; // set output arguments helloMethod.OutputArguments = new PropertyState(helloMethod) { NodeId = new NodeId(helloMethod.BrowseName.Name + "OutArgs", NamespaceIndex), BrowseName = BrowseNames.OutputArguments }; helloMethod.OutputArguments.DisplayName = helloMethod.OutputArguments.BrowseName.Name; helloMethod.OutputArguments.TypeDefinitionId = VariableTypeIds.PropertyType; helloMethod.OutputArguments.ReferenceTypeId = ReferenceTypeIds.HasProperty; helloMethod.OutputArguments.DataType = DataTypeIds.Argument; helloMethod.OutputArguments.ValueRank = ValueRanks.OneDimension; helloMethod.OutputArguments.Value = [ new() { Name = "Hello Result", Description = "Hello Result", DataType = DataTypeIds.String, ValueRank = ValueRanks.Scalar } ]; helloMethod.OnCallMethod = new GenericMethodCalledEventHandler(OnHelloCall); // Input Method var inputMethod = CreateMethod(methodsFolder, methods + "Input", "Input"); // set input arguments inputMethod.InputArguments = new PropertyState(inputMethod) { NodeId = new NodeId(inputMethod.BrowseName.Name + "InArgs", NamespaceIndex), BrowseName = BrowseNames.InputArguments }; inputMethod.InputArguments.DisplayName = inputMethod.InputArguments.BrowseName.Name; inputMethod.InputArguments.TypeDefinitionId = VariableTypeIds.PropertyType; inputMethod.InputArguments.ReferenceTypeId = ReferenceTypeIds.HasProperty; inputMethod.InputArguments.DataType = DataTypeIds.Argument; inputMethod.InputArguments.ValueRank = ValueRanks.OneDimension; inputMethod.InputArguments.Value = [ new() { Name = "String value", Description = "String value", DataType = DataTypeIds.String, ValueRank = ValueRanks.Scalar } ]; inputMethod.OnCallMethod = new GenericMethodCalledEventHandler(OnInputCall); // Output Method var outputMethod = CreateMethod(methodsFolder, methods + "Output", "Output"); // set output arguments outputMethod.OutputArguments = new PropertyState(helloMethod) { NodeId = new NodeId(helloMethod.BrowseName.Name + "OutArgs", NamespaceIndex), BrowseName = BrowseNames.OutputArguments }; outputMethod.OutputArguments.DisplayName = helloMethod.OutputArguments.BrowseName.Name; outputMethod.OutputArguments.TypeDefinitionId = VariableTypeIds.PropertyType; outputMethod.OutputArguments.ReferenceTypeId = ReferenceTypeIds.HasProperty; outputMethod.OutputArguments.DataType = DataTypeIds.Argument; outputMethod.OutputArguments.ValueRank = ValueRanks.OneDimension; outputMethod.OutputArguments.Value = [ new() { Name = "Output Result", Description = "Output Result", DataType = DataTypeIds.String, ValueRank = ValueRanks.Scalar } ]; outputMethod.OnCallMethod = new GenericMethodCalledEventHandler(OnOutputCall); // Views ResetRandomGenerator(18); var viewsFolder = CreateFolder(root, "Views", "Views"); const string views = "Views_"; var viewStateOperations = CreateView(viewsFolder, externalReferences, views + "Operations", "Operations"); viewStateOperations.AddReference(ReferenceTypes.Organizes, false, massFolder.NodeId); massFolder.AddReference(ReferenceTypes.Organizes, true, viewStateOperations.NodeId); var viewStateEngineering = CreateView(viewsFolder, externalReferences, views + "Engineering", "Engineering"); viewStateEngineering.AddReference(ReferenceTypes.Organizes, false, simulationFolder.NodeId); simulationFolder.AddReference(ReferenceTypes.Organizes, true, viewStateEngineering.NodeId); // Locales ResetRandomGenerator(19); var localesFolder = CreateFolder(root, "Locales", "Locales"); const string locales = "Locales_"; var qnEnglishVariable = CreateVariable(localesFolder, locales + "QNEnglish", "QNEnglish", DataTypeIds.QualifiedName, ValueRanks.Scalar); qnEnglishVariable.Description = new LocalizedText("en", "English"); qnEnglishVariable.Value = new QualifiedName("Hello World", NamespaceIndex); variables.Add(qnEnglishVariable); var ltEnglishVariable = CreateVariable(localesFolder, locales + "LTEnglish", "LTEnglish", DataTypeIds.LocalizedText, ValueRanks.Scalar); ltEnglishVariable.Description = new LocalizedText("en", "English"); ltEnglishVariable.Value = new LocalizedText("en", "Hello World"); variables.Add(ltEnglishVariable); var qnFrancaisVariable = CreateVariable(localesFolder, locales + "QNFrancais", "QNFrancais", DataTypeIds.QualifiedName, ValueRanks.Scalar); qnFrancaisVariable.Description = new LocalizedText("en", "Francais"); qnFrancaisVariable.Value = new QualifiedName("Salut tout le monde", NamespaceIndex); variables.Add(qnFrancaisVariable); var ltFrancaisVariable = CreateVariable(localesFolder, locales + "LTFrancais", "LTFrancais", DataTypeIds.LocalizedText, ValueRanks.Scalar); ltFrancaisVariable.Description = new LocalizedText("en", "Francais"); ltFrancaisVariable.Value = new LocalizedText("fr", "Salut tout le monde"); variables.Add(ltFrancaisVariable); var qnDeutschVariable = CreateVariable(localesFolder, locales + "QNDeutsch", "QNDeutsch", DataTypeIds.QualifiedName, ValueRanks.Scalar); qnDeutschVariable.Description = new LocalizedText("en", "Deutsch"); qnDeutschVariable.Value = new QualifiedName("Hallo Welt", NamespaceIndex); variables.Add(qnDeutschVariable); var ltDeutschVariable = CreateVariable(localesFolder, locales + "LTDeutsch", "LTDeutsch", DataTypeIds.LocalizedText, ValueRanks.Scalar); ltDeutschVariable.Description = new LocalizedText("en", "Deutsch"); ltDeutschVariable.Value = new LocalizedText("de", "Hallo Welt"); variables.Add(ltDeutschVariable); var qnEspanolVariable = CreateVariable(localesFolder, locales + "QNEspanol", "QNEspanol", DataTypeIds.QualifiedName, ValueRanks.Scalar); qnEspanolVariable.Description = new LocalizedText("en", "Espanol"); qnEspanolVariable.Value = new QualifiedName("Hola mundo", NamespaceIndex); variables.Add(qnEspanolVariable); var ltEspanolVariable = CreateVariable(localesFolder, locales + "LTEspanol", "LTEspanol", DataTypeIds.LocalizedText, ValueRanks.Scalar); ltEspanolVariable.Description = new LocalizedText("en", "Espanol"); ltEspanolVariable.Value = new LocalizedText("es", "Hola mundo"); variables.Add(ltEspanolVariable); var qnJapaneseVariable = CreateVariable(localesFolder, locales + "QN日本の", "QN日本の", DataTypeIds.QualifiedName, ValueRanks.Scalar); qnJapaneseVariable.Description = new LocalizedText("en", "Japanese"); qnJapaneseVariable.Value = new QualifiedName("ハローワールド", NamespaceIndex); variables.Add(qnJapaneseVariable); var ltJapaneseVariable = CreateVariable(localesFolder, locales + "LT日本の", "LT日本の", DataTypeIds.LocalizedText, ValueRanks.Scalar); ltJapaneseVariable.Description = new LocalizedText("en", "Japanese"); ltJapaneseVariable.Value = new LocalizedText("jp", "ハローワールド"); variables.Add(ltJapaneseVariable); var qnChineseVariable = CreateVariable(localesFolder, locales + "QN中國的", "QN中國的", DataTypeIds.QualifiedName, ValueRanks.Scalar); qnChineseVariable.Description = new LocalizedText("en", "Chinese"); qnChineseVariable.Value = new QualifiedName("世界您好", NamespaceIndex); variables.Add(qnChineseVariable); var ltChineseVariable = CreateVariable(localesFolder, locales + "LT中國的", "LT中國的", DataTypeIds.LocalizedText, ValueRanks.Scalar); ltChineseVariable.Description = new LocalizedText("en", "Chinese"); ltChineseVariable.Value = new LocalizedText("ch", "世界您好"); variables.Add(ltChineseVariable); var qnRussianVariable = CreateVariable(localesFolder, locales + "QNрусский", "QNрусский", DataTypeIds.QualifiedName, ValueRanks.Scalar); qnRussianVariable.Description = new LocalizedText("en", "Russian"); qnRussianVariable.Value = new QualifiedName("LTрусский", NamespaceIndex); variables.Add(qnRussianVariable); var ltRussianVariable = CreateVariable(localesFolder, locales + "LTрусский", "LTрусский", DataTypeIds.LocalizedText, ValueRanks.Scalar); ltRussianVariable.Description = new LocalizedText("en", "Russian"); ltRussianVariable.Value = new LocalizedText("ru", "LTрусский"); variables.Add(ltRussianVariable); var qnArabicVariable = CreateVariable(localesFolder, locales + "QNالعربية", "QNالعربية", DataTypeIds.QualifiedName, ValueRanks.Scalar); qnArabicVariable.Description = new LocalizedText("en", "Arabic"); qnArabicVariable.Value = new QualifiedName("مرحبا بالعال", NamespaceIndex); variables.Add(qnArabicVariable); var ltArabicVariable = CreateVariable(localesFolder, locales + "LTالعربية", "LTالعربية", DataTypeIds.LocalizedText, ValueRanks.Scalar); ltArabicVariable.Description = new LocalizedText("en", "Arabic"); ltArabicVariable.Value = new LocalizedText("ae", "مرحبا بالعال"); variables.Add(ltArabicVariable); var qnKlingonVariable = CreateVariable(localesFolder, locales + "QNtlhIngan", "QNtlhIngan", DataTypeIds.QualifiedName, ValueRanks.Scalar); qnKlingonVariable.Description = new LocalizedText("en", "Klingon"); qnKlingonVariable.Value = new QualifiedName("qo' vIvan", NamespaceIndex); variables.Add(qnKlingonVariable); var ltKlingonVariable = CreateVariable(localesFolder, locales + "LTtlhIngan", "LTtlhIngan", DataTypeIds.LocalizedText, ValueRanks.Scalar); ltKlingonVariable.Description = new LocalizedText("en", "Klingon"); ltKlingonVariable.Value = new LocalizedText("ko", "qo' vIvan"); variables.Add(ltKlingonVariable); // Attributes ResetRandomGenerator(20); var folderAttributes = CreateFolder(root, "Attributes", "Attributes"); // AccessAll var folderAttributesAccessAll = CreateFolder(folderAttributes, "Attributes_AccessAll", "AccessAll"); const string attributesAccessAll = "Attributes_AccessAll_"; var accessLevelAccessAll = CreateVariable(folderAttributesAccessAll, attributesAccessAll + "AccessLevel", "AccessLevel", DataTypeIds.Double, ValueRanks.Scalar); accessLevelAccessAll.WriteMask = AttributeWriteMask.AccessLevel; accessLevelAccessAll.UserWriteMask = AttributeWriteMask.AccessLevel; variables.Add(accessLevelAccessAll); var arrayDimensionsAccessLevel = CreateVariable(folderAttributesAccessAll, attributesAccessAll + "ArrayDimensions", "ArrayDimensions", DataTypeIds.Double, ValueRanks.Scalar); arrayDimensionsAccessLevel.WriteMask = AttributeWriteMask.ArrayDimensions; arrayDimensionsAccessLevel.UserWriteMask = AttributeWriteMask.ArrayDimensions; variables.Add(arrayDimensionsAccessLevel); var browseNameAccessLevel = CreateVariable(folderAttributesAccessAll, attributesAccessAll + "BrowseName", "BrowseName", DataTypeIds.Double, ValueRanks.Scalar); browseNameAccessLevel.WriteMask = AttributeWriteMask.BrowseName; browseNameAccessLevel.UserWriteMask = AttributeWriteMask.BrowseName; variables.Add(browseNameAccessLevel); var containsNoLoopsAccessLevel = CreateVariable(folderAttributesAccessAll, attributesAccessAll + "ContainsNoLoops", "ContainsNoLoops", DataTypeIds.Double, ValueRanks.Scalar); containsNoLoopsAccessLevel.WriteMask = AttributeWriteMask.ContainsNoLoops; containsNoLoopsAccessLevel.UserWriteMask = AttributeWriteMask.ContainsNoLoops; variables.Add(containsNoLoopsAccessLevel); var dataTypeAccessLevel = CreateVariable(folderAttributesAccessAll, attributesAccessAll + "DataType", "DataType", DataTypeIds.Double, ValueRanks.Scalar); dataTypeAccessLevel.WriteMask = AttributeWriteMask.DataType; dataTypeAccessLevel.UserWriteMask = AttributeWriteMask.DataType; variables.Add(dataTypeAccessLevel); var descriptionAccessLevel = CreateVariable(folderAttributesAccessAll, attributesAccessAll + "Description", "Description", DataTypeIds.Double, ValueRanks.Scalar); descriptionAccessLevel.WriteMask = AttributeWriteMask.Description; descriptionAccessLevel.UserWriteMask = AttributeWriteMask.Description; variables.Add(descriptionAccessLevel); var eventNotifierAccessLevel = CreateVariable(folderAttributesAccessAll, attributesAccessAll + "EventNotifier", "EventNotifier", DataTypeIds.Double, ValueRanks.Scalar); eventNotifierAccessLevel.WriteMask = AttributeWriteMask.EventNotifier; eventNotifierAccessLevel.UserWriteMask = AttributeWriteMask.EventNotifier; variables.Add(eventNotifierAccessLevel); var executableAccessLevel = CreateVariable(folderAttributesAccessAll, attributesAccessAll + "Executable", "Executable", DataTypeIds.Double, ValueRanks.Scalar); executableAccessLevel.WriteMask = AttributeWriteMask.Executable; executableAccessLevel.UserWriteMask = AttributeWriteMask.Executable; variables.Add(executableAccessLevel); var historizingAccessLevel = CreateVariable(folderAttributesAccessAll, attributesAccessAll + "Historizing", "Historizing", DataTypeIds.Double, ValueRanks.Scalar); historizingAccessLevel.WriteMask = AttributeWriteMask.Historizing; historizingAccessLevel.UserWriteMask = AttributeWriteMask.Historizing; variables.Add(historizingAccessLevel); var inverseNameAccessLevel = CreateVariable(folderAttributesAccessAll, attributesAccessAll + "InverseName", "InverseName", DataTypeIds.Double, ValueRanks.Scalar); inverseNameAccessLevel.WriteMask = AttributeWriteMask.InverseName; inverseNameAccessLevel.UserWriteMask = AttributeWriteMask.InverseName; variables.Add(inverseNameAccessLevel); var isAbstractAccessLevel = CreateVariable(folderAttributesAccessAll, attributesAccessAll + "IsAbstract", "IsAbstract", DataTypeIds.Double, ValueRanks.Scalar); isAbstractAccessLevel.WriteMask = AttributeWriteMask.IsAbstract; isAbstractAccessLevel.UserWriteMask = AttributeWriteMask.IsAbstract; variables.Add(isAbstractAccessLevel); var minimumSamplingIntervalAccessLevel = CreateVariable(folderAttributesAccessAll, attributesAccessAll + "MinimumSamplingInterval", "MinimumSamplingInterval", DataTypeIds.Double, ValueRanks.Scalar); minimumSamplingIntervalAccessLevel.WriteMask = AttributeWriteMask.MinimumSamplingInterval; minimumSamplingIntervalAccessLevel.UserWriteMask = AttributeWriteMask.MinimumSamplingInterval; variables.Add(minimumSamplingIntervalAccessLevel); var nodeClassIntervalAccessLevel = CreateVariable(folderAttributesAccessAll, attributesAccessAll + "NodeClass", "NodeClass", DataTypeIds.Double, ValueRanks.Scalar); nodeClassIntervalAccessLevel.WriteMask = AttributeWriteMask.NodeClass; nodeClassIntervalAccessLevel.UserWriteMask = AttributeWriteMask.NodeClass; variables.Add(nodeClassIntervalAccessLevel); var nodeIdAccessLevel = CreateVariable(folderAttributesAccessAll, attributesAccessAll + "NodeId", "NodeId", DataTypeIds.Double, ValueRanks.Scalar); nodeIdAccessLevel.WriteMask = AttributeWriteMask.NodeId; nodeIdAccessLevel.UserWriteMask = AttributeWriteMask.NodeId; variables.Add(nodeIdAccessLevel); var symmetricAccessLevel = CreateVariable(folderAttributesAccessAll, attributesAccessAll + "Symmetric", "Symmetric", DataTypeIds.Double, ValueRanks.Scalar); symmetricAccessLevel.WriteMask = AttributeWriteMask.Symmetric; symmetricAccessLevel.UserWriteMask = AttributeWriteMask.Symmetric; variables.Add(symmetricAccessLevel); var userAccessLevelAccessLevel = CreateVariable(folderAttributesAccessAll, attributesAccessAll + "UserAccessLevel", "UserAccessLevel", DataTypeIds.Double, ValueRanks.Scalar); userAccessLevelAccessLevel.WriteMask = AttributeWriteMask.UserAccessLevel; userAccessLevelAccessLevel.UserWriteMask = AttributeWriteMask.UserAccessLevel; variables.Add(userAccessLevelAccessLevel); var userExecutableAccessLevel = CreateVariable(folderAttributesAccessAll, attributesAccessAll + "UserExecutable", "UserExecutable", DataTypeIds.Double, ValueRanks.Scalar); userExecutableAccessLevel.WriteMask = AttributeWriteMask.UserExecutable; userExecutableAccessLevel.UserWriteMask = AttributeWriteMask.UserExecutable; variables.Add(userExecutableAccessLevel); var valueRankAccessLevel = CreateVariable(folderAttributesAccessAll, attributesAccessAll + "ValueRank", "ValueRank", DataTypeIds.Double, ValueRanks.Scalar); valueRankAccessLevel.WriteMask = AttributeWriteMask.ValueRank; valueRankAccessLevel.UserWriteMask = AttributeWriteMask.ValueRank; variables.Add(valueRankAccessLevel); var writeMaskAccessLevel = CreateVariable(folderAttributesAccessAll, attributesAccessAll + "WriteMask", "WriteMask", DataTypeIds.Double, ValueRanks.Scalar); writeMaskAccessLevel.WriteMask = AttributeWriteMask.WriteMask; writeMaskAccessLevel.UserWriteMask = AttributeWriteMask.WriteMask; variables.Add(writeMaskAccessLevel); var valueForVariableTypeAccessLevel = CreateVariable(folderAttributesAccessAll, attributesAccessAll + "ValueForVariableType", "ValueForVariableType", DataTypeIds.Double, ValueRanks.Scalar); valueForVariableTypeAccessLevel.WriteMask = AttributeWriteMask.ValueForVariableType; valueForVariableTypeAccessLevel.UserWriteMask = AttributeWriteMask.ValueForVariableType; variables.Add(valueForVariableTypeAccessLevel); var allAccessLevel = CreateVariable(folderAttributesAccessAll, attributesAccessAll + "All", "All", DataTypeIds.Double, ValueRanks.Scalar); allAccessLevel.WriteMask = AttributeWriteMask.AccessLevel | AttributeWriteMask.ArrayDimensions | AttributeWriteMask.BrowseName | AttributeWriteMask.ContainsNoLoops | AttributeWriteMask.DataType | AttributeWriteMask.Description | AttributeWriteMask.DisplayName | AttributeWriteMask.EventNotifier | AttributeWriteMask.Executable | AttributeWriteMask.Historizing | AttributeWriteMask.InverseName | AttributeWriteMask.IsAbstract | AttributeWriteMask.MinimumSamplingInterval | AttributeWriteMask.NodeClass | AttributeWriteMask.NodeId | AttributeWriteMask.Symmetric | AttributeWriteMask.UserAccessLevel | AttributeWriteMask.UserExecutable | AttributeWriteMask.UserWriteMask | AttributeWriteMask.ValueForVariableType | AttributeWriteMask.ValueRank | AttributeWriteMask.WriteMask; allAccessLevel.UserWriteMask = AttributeWriteMask.AccessLevel | AttributeWriteMask.ArrayDimensions | AttributeWriteMask.BrowseName | AttributeWriteMask.ContainsNoLoops | AttributeWriteMask.DataType | AttributeWriteMask.Description | AttributeWriteMask.DisplayName | AttributeWriteMask.EventNotifier | AttributeWriteMask.Executable | AttributeWriteMask.Historizing | AttributeWriteMask.InverseName | AttributeWriteMask.IsAbstract | AttributeWriteMask.MinimumSamplingInterval | AttributeWriteMask.NodeClass | AttributeWriteMask.NodeId | AttributeWriteMask.Symmetric | AttributeWriteMask.UserAccessLevel | AttributeWriteMask.UserExecutable | AttributeWriteMask.UserWriteMask | AttributeWriteMask.ValueForVariableType | AttributeWriteMask.ValueRank | AttributeWriteMask.WriteMask; variables.Add(allAccessLevel); // AccessUser1 var folderAttributesAccessUser1 = CreateFolder(folderAttributes, "Attributes_AccessUser1", "AccessUser1"); const string attributesAccessUser1 = "Attributes_AccessUser1_"; var accessLevelAccessUser1 = CreateVariable(folderAttributesAccessUser1, attributesAccessUser1 + "AccessLevel", "AccessLevel", DataTypeIds.Double, ValueRanks.Scalar); accessLevelAccessAll.WriteMask = AttributeWriteMask.AccessLevel; accessLevelAccessAll.UserWriteMask = AttributeWriteMask.AccessLevel; variables.Add(accessLevelAccessAll); var arrayDimensionsAccessUser1 = CreateVariable(folderAttributesAccessUser1, attributesAccessUser1 + "ArrayDimensions", "ArrayDimensions", DataTypeIds.Double, ValueRanks.Scalar); arrayDimensionsAccessUser1.WriteMask = AttributeWriteMask.ArrayDimensions; arrayDimensionsAccessUser1.UserWriteMask = AttributeWriteMask.ArrayDimensions; variables.Add(arrayDimensionsAccessUser1); var browseNameAccessUser1 = CreateVariable(folderAttributesAccessUser1, attributesAccessUser1 + "BrowseName", "BrowseName", DataTypeIds.Double, ValueRanks.Scalar); browseNameAccessUser1.WriteMask = AttributeWriteMask.BrowseName; browseNameAccessUser1.UserWriteMask = AttributeWriteMask.BrowseName; variables.Add(browseNameAccessUser1); var containsNoLoopsAccessUser1 = CreateVariable(folderAttributesAccessUser1, attributesAccessUser1 + "ContainsNoLoops", "ContainsNoLoops", DataTypeIds.Double, ValueRanks.Scalar); containsNoLoopsAccessUser1.WriteMask = AttributeWriteMask.ContainsNoLoops; containsNoLoopsAccessUser1.UserWriteMask = AttributeWriteMask.ContainsNoLoops; variables.Add(containsNoLoopsAccessUser1); var dataTypeAccessUser1 = CreateVariable(folderAttributesAccessUser1, attributesAccessUser1 + "DataType", "DataType", DataTypeIds.Double, ValueRanks.Scalar); dataTypeAccessUser1.WriteMask = AttributeWriteMask.DataType; dataTypeAccessUser1.UserWriteMask = AttributeWriteMask.DataType; variables.Add(dataTypeAccessUser1); var descriptionAccessUser1 = CreateVariable(folderAttributesAccessUser1, attributesAccessUser1 + "Description", "Description", DataTypeIds.Double, ValueRanks.Scalar); descriptionAccessUser1.WriteMask = AttributeWriteMask.Description; descriptionAccessUser1.UserWriteMask = AttributeWriteMask.Description; variables.Add(descriptionAccessUser1); var eventNotifierAccessUser1 = CreateVariable(folderAttributesAccessUser1, attributesAccessUser1 + "EventNotifier", "EventNotifier", DataTypeIds.Double, ValueRanks.Scalar); eventNotifierAccessUser1.WriteMask = AttributeWriteMask.EventNotifier; eventNotifierAccessUser1.UserWriteMask = AttributeWriteMask.EventNotifier; variables.Add(eventNotifierAccessUser1); var executableAccessUser1 = CreateVariable(folderAttributesAccessUser1, attributesAccessUser1 + "Executable", "Executable", DataTypeIds.Double, ValueRanks.Scalar); executableAccessUser1.WriteMask = AttributeWriteMask.Executable; executableAccessUser1.UserWriteMask = AttributeWriteMask.Executable; variables.Add(executableAccessUser1); var historizingAccessUser1 = CreateVariable(folderAttributesAccessUser1, attributesAccessUser1 + "Historizing", "Historizing", DataTypeIds.Double, ValueRanks.Scalar); historizingAccessUser1.WriteMask = AttributeWriteMask.Historizing; historizingAccessUser1.UserWriteMask = AttributeWriteMask.Historizing; variables.Add(historizingAccessUser1); var inverseNameAccessUser1 = CreateVariable(folderAttributesAccessUser1, attributesAccessUser1 + "InverseName", "InverseName", DataTypeIds.Double, ValueRanks.Scalar); inverseNameAccessUser1.WriteMask = AttributeWriteMask.InverseName; inverseNameAccessUser1.UserWriteMask = AttributeWriteMask.InverseName; variables.Add(inverseNameAccessUser1); var isAbstractAccessUser1 = CreateVariable(folderAttributesAccessUser1, attributesAccessUser1 + "IsAbstract", "IsAbstract", DataTypeIds.Double, ValueRanks.Scalar); isAbstractAccessUser1.WriteMask = AttributeWriteMask.IsAbstract; isAbstractAccessUser1.UserWriteMask = AttributeWriteMask.IsAbstract; variables.Add(isAbstractAccessUser1); var minimumSamplingIntervalAccessUser1 = CreateVariable(folderAttributesAccessUser1, attributesAccessUser1 + "MinimumSamplingInterval", "MinimumSamplingInterval", DataTypeIds.Double, ValueRanks.Scalar); minimumSamplingIntervalAccessUser1.WriteMask = AttributeWriteMask.MinimumSamplingInterval; minimumSamplingIntervalAccessUser1.UserWriteMask = AttributeWriteMask.MinimumSamplingInterval; variables.Add(minimumSamplingIntervalAccessUser1); var nodeClassIntervalAccessUser1 = CreateVariable(folderAttributesAccessUser1, attributesAccessUser1 + "NodeClass", "NodeClass", DataTypeIds.Double, ValueRanks.Scalar); nodeClassIntervalAccessUser1.WriteMask = AttributeWriteMask.NodeClass; nodeClassIntervalAccessUser1.UserWriteMask = AttributeWriteMask.NodeClass; variables.Add(nodeClassIntervalAccessUser1); var nodeIdAccessUser1 = CreateVariable(folderAttributesAccessUser1, attributesAccessUser1 + "NodeId", "NodeId", DataTypeIds.Double, ValueRanks.Scalar); nodeIdAccessUser1.WriteMask = AttributeWriteMask.NodeId; nodeIdAccessUser1.UserWriteMask = AttributeWriteMask.NodeId; variables.Add(nodeIdAccessUser1); var symmetricAccessUser1 = CreateVariable(folderAttributesAccessUser1, attributesAccessUser1 + "Symmetric", "Symmetric", DataTypeIds.Double, ValueRanks.Scalar); symmetricAccessUser1.WriteMask = AttributeWriteMask.Symmetric; symmetricAccessUser1.UserWriteMask = AttributeWriteMask.Symmetric; variables.Add(symmetricAccessUser1); var userAccessUser1AccessUser1 = CreateVariable(folderAttributesAccessUser1, attributesAccessUser1 + "UserAccessUser1", "UserAccessUser1", DataTypeIds.Double, ValueRanks.Scalar); userAccessUser1AccessUser1.WriteMask = AttributeWriteMask.UserAccessLevel; userAccessUser1AccessUser1.UserWriteMask = AttributeWriteMask.UserAccessLevel; variables.Add(userAccessUser1AccessUser1); var userExecutableAccessUser1 = CreateVariable(folderAttributesAccessUser1, attributesAccessUser1 + "UserExecutable", "UserExecutable", DataTypeIds.Double, ValueRanks.Scalar); userExecutableAccessUser1.WriteMask = AttributeWriteMask.UserExecutable; userExecutableAccessUser1.UserWriteMask = AttributeWriteMask.UserExecutable; variables.Add(userExecutableAccessUser1); var valueRankAccessUser1 = CreateVariable(folderAttributesAccessUser1, attributesAccessUser1 + "ValueRank", "ValueRank", DataTypeIds.Double, ValueRanks.Scalar); valueRankAccessUser1.WriteMask = AttributeWriteMask.ValueRank; valueRankAccessUser1.UserWriteMask = AttributeWriteMask.ValueRank; variables.Add(valueRankAccessUser1); var writeMaskAccessUser1 = CreateVariable(folderAttributesAccessUser1, attributesAccessUser1 + "WriteMask", "WriteMask", DataTypeIds.Double, ValueRanks.Scalar); writeMaskAccessUser1.WriteMask = AttributeWriteMask.WriteMask; writeMaskAccessUser1.UserWriteMask = AttributeWriteMask.WriteMask; variables.Add(writeMaskAccessUser1); var valueForVariableTypeAccessUser1 = CreateVariable(folderAttributesAccessUser1, attributesAccessUser1 + "ValueForVariableType", "ValueForVariableType", DataTypeIds.Double, ValueRanks.Scalar); valueForVariableTypeAccessUser1.WriteMask = AttributeWriteMask.ValueForVariableType; valueForVariableTypeAccessUser1.UserWriteMask = AttributeWriteMask.ValueForVariableType; variables.Add(valueForVariableTypeAccessUser1); var allAccessUser1 = CreateVariable(folderAttributesAccessUser1, attributesAccessUser1 + "All", "All", DataTypeIds.Double, ValueRanks.Scalar); allAccessUser1.WriteMask = AttributeWriteMask.AccessLevel | AttributeWriteMask.ArrayDimensions | AttributeWriteMask.BrowseName | AttributeWriteMask.ContainsNoLoops | AttributeWriteMask.DataType | AttributeWriteMask.Description | AttributeWriteMask.DisplayName | AttributeWriteMask.EventNotifier | AttributeWriteMask.Executable | AttributeWriteMask.Historizing | AttributeWriteMask.InverseName | AttributeWriteMask.IsAbstract | AttributeWriteMask.MinimumSamplingInterval | AttributeWriteMask.NodeClass | AttributeWriteMask.NodeId | AttributeWriteMask.Symmetric | AttributeWriteMask.UserAccessLevel | AttributeWriteMask.UserExecutable | AttributeWriteMask.UserWriteMask | AttributeWriteMask.ValueForVariableType | AttributeWriteMask.ValueRank | AttributeWriteMask.WriteMask; allAccessUser1.UserWriteMask = AttributeWriteMask.AccessLevel | AttributeWriteMask.ArrayDimensions | AttributeWriteMask.BrowseName | AttributeWriteMask.ContainsNoLoops | AttributeWriteMask.DataType | AttributeWriteMask.Description | AttributeWriteMask.DisplayName | AttributeWriteMask.EventNotifier | AttributeWriteMask.Executable | AttributeWriteMask.Historizing | AttributeWriteMask.InverseName | AttributeWriteMask.IsAbstract | AttributeWriteMask.MinimumSamplingInterval | AttributeWriteMask.NodeClass | AttributeWriteMask.NodeId | AttributeWriteMask.Symmetric | AttributeWriteMask.UserAccessLevel | AttributeWriteMask.UserExecutable | AttributeWriteMask.UserWriteMask | AttributeWriteMask.ValueForVariableType | AttributeWriteMask.ValueRank | AttributeWriteMask.WriteMask; variables.Add(allAccessUser1); // MyCompany ResetRandomGenerator(21); var myCompanyFolder = CreateFolder(root, "MyCompany", "MyCompany"); const string myCompany = "MyCompany_"; var myCompanyInstructions = CreateVariable(myCompanyFolder, myCompany + "Instructions", "Instructions", DataTypeIds.String, ValueRanks.Scalar); myCompanyInstructions.Value = "A place for the vendor to describe their address-space."; variables.Add(myCompanyInstructions); } catch (Exception e) { Utils.LogError(e, "Error creating the ReferenceNodeManager address space."); } AddPredefinedNode(SystemContext, root); // reset random generator and generate boundary values ResetRandomGenerator(100, 1); _simulationTimer = new Timer(DoSimulation, null, 1000, 1000); } } private ServiceResult OnWriteInterval(ISystemContext context, NodeState node, ref object value) { try { _simulationInterval = (ushort)value; if (_simulationEnabled) { _simulationTimer.Change(100, _simulationInterval); } return ServiceResult.Good; } catch (Exception e) { Utils.LogError(e, "Error writing Interval variable."); return ServiceResult.Create(e, StatusCodes.Bad, "Error writing Interval variable."); } } private ServiceResult OnWriteEnabled(ISystemContext context, NodeState node, ref object value) { try { _simulationEnabled = (bool)value; if (_simulationEnabled) { _simulationTimer.Change(100, _simulationInterval); } else { _simulationTimer.Change(100, 0); } return ServiceResult.Good; } catch (Exception e) { Utils.LogError(e, "Error writing Enabled variable."); return ServiceResult.Create(e, StatusCodes.Bad, "Error writing Enabled variable."); } } /// /// Creates a new folder. /// /// /// /// private FolderState CreateFolder(NodeState parent, string path, string name) { var folder = new FolderState(parent) { SymbolicName = name, ReferenceTypeId = ReferenceTypes.Organizes, TypeDefinitionId = ObjectTypeIds.FolderType, NodeId = new NodeId(path, NamespaceIndex), BrowseName = new QualifiedName(path, NamespaceIndex), DisplayName = new LocalizedText("en", name), WriteMask = AttributeWriteMask.None, UserWriteMask = AttributeWriteMask.None, EventNotifier = EventNotifiers.None }; parent?.AddChild(folder); return folder; } /// /// Creates a new variable. /// /// /// /// /// private BaseDataVariableState CreateMeshVariable(NodeState parent, string path, string name, params NodeState[] peers) { var variable = CreateVariable(parent, path, name, BuiltInType.Double, ValueRanks.Scalar); if (peers != null) { foreach (var peer in peers) { peer.AddReference(ReferenceTypes.HasCause, false, variable.NodeId); variable.AddReference(ReferenceTypes.HasCause, true, peer.NodeId); peer.AddReference(ReferenceTypes.HasEffect, true, variable.NodeId); variable.AddReference(ReferenceTypes.HasEffect, false, peer.NodeId); } } return variable; } /// /// Creates a new variable. /// /// /// /// /// /// private DataItemState CreateDataItemVariable(NodeState parent, string path, string name, BuiltInType dataType, int valueRank) { var variable = new DataItemState(parent); variable.ValuePrecision = new PropertyState(variable); variable.Definition = new PropertyState(variable); variable.Create( SystemContext, null, variable.BrowseName, null, true); variable.SymbolicName = name; variable.ReferenceTypeId = ReferenceTypes.Organizes; variable.NodeId = new NodeId(path, NamespaceIndex); variable.BrowseName = new QualifiedName(path, NamespaceIndex); variable.DisplayName = new LocalizedText("en", name); variable.WriteMask = AttributeWriteMask.None; variable.UserWriteMask = AttributeWriteMask.None; variable.DataType = (uint)dataType; variable.ValueRank = valueRank; variable.AccessLevel = AccessLevels.CurrentReadOrWrite; variable.UserAccessLevel = AccessLevels.CurrentReadOrWrite; variable.Historizing = false; variable.Value = TypeInfo.GetDefaultValue((uint)dataType, valueRank, Server.TypeTree); variable.StatusCode = StatusCodes.Good; variable.Timestamp = DateTime.UtcNow; if (valueRank == ValueRanks.OneDimension) { variable.ArrayDimensions = new ReadOnlyList([0]); } else if (valueRank == ValueRanks.TwoDimensions) { variable.ArrayDimensions = new ReadOnlyList([0, 0]); } variable.ValuePrecision.Value = 2; variable.ValuePrecision.AccessLevel = AccessLevels.CurrentReadOrWrite; variable.ValuePrecision.UserAccessLevel = AccessLevels.CurrentReadOrWrite; variable.Definition.Value = string.Empty; variable.Definition.AccessLevel = AccessLevels.CurrentReadOrWrite; variable.Definition.UserAccessLevel = AccessLevels.CurrentReadOrWrite; parent?.AddChild(variable); return variable; } /// /// Creates a new variable. /// /// /// /// /// /// private AnalogItemState CreateAnalogItemVariable(NodeState parent, string path, string name, BuiltInType dataType, int valueRank) { return CreateAnalogItemVariable(parent, path, name, dataType, valueRank, null); } private AnalogItemState CreateAnalogItemVariable(NodeState parent, string path, string name, BuiltInType dataType, int valueRank, object initialValues) { return CreateAnalogItemVariable(parent, path, name, dataType, valueRank, initialValues, null); } private AnalogItemState CreateAnalogItemVariable(NodeState parent, string path, string name, BuiltInType dataType, int valueRank, object initialValues, Opc.Ua.Range customRange) { return CreateAnalogItemVariable(parent, path, name, (uint)dataType, valueRank, initialValues, customRange); } private AnalogItemState CreateAnalogItemVariable(NodeState parent, string path, string name, NodeId dataType, int valueRank, object initialValues, Opc.Ua.Range customRange) { var variable = new AnalogItemState(parent) { BrowseName = new QualifiedName(path, NamespaceIndex) }; variable.EngineeringUnits = new PropertyState(variable); variable.InstrumentRange = new PropertyState(variable); variable.Create( SystemContext, new NodeId(path, NamespaceIndex), variable.BrowseName, null, true); variable.NodeId = new NodeId(path, NamespaceIndex); variable.SymbolicName = name; variable.DisplayName = new LocalizedText("en", name); variable.WriteMask = AttributeWriteMask.None; variable.UserWriteMask = AttributeWriteMask.None; variable.ReferenceTypeId = ReferenceTypes.Organizes; variable.DataType = dataType; variable.ValueRank = valueRank; variable.AccessLevel = AccessLevels.CurrentReadOrWrite; variable.UserAccessLevel = AccessLevels.CurrentReadOrWrite; variable.Historizing = false; if (valueRank == ValueRanks.OneDimension) { variable.ArrayDimensions = new ReadOnlyList([0]); } else if (valueRank == ValueRanks.TwoDimensions) { variable.ArrayDimensions = new ReadOnlyList([0, 0]); } var builtInType = TypeInfo.GetBuiltInType(dataType, Server.TypeTree); // Simulate a mV Voltmeter var newRange = GetAnalogRange(builtInType); // Using anything but 120,-10 fails a few tests newRange.High = Math.Min(newRange.High, 120); newRange.Low = Math.Max(newRange.Low, -10); variable.InstrumentRange.Value = newRange; variable.EURange.Value = customRange ?? new Opc.Ua.Range(100, 0); variable.Value = initialValues ?? TypeInfo.GetDefaultValue(dataType, valueRank, Server.TypeTree); variable.StatusCode = StatusCodes.Good; variable.Timestamp = DateTime.UtcNow; // The latest UNECE version (Rev 11, published in 2015) is available here: // http://www.opcfoundation.org/UA/EngineeringUnits/UNECE/rec20_latest_08052015.zip variable.EngineeringUnits.Value = new EUInformation("mV", "millivolt", "http://www.opcfoundation.org/UA/units/un/cefact") { // The mapping of the UNECE codes to OPC UA(EUInformation.unitId) is available here: // http://www.opcfoundation.org/UA/EngineeringUnits/UNECE/UNECE_to_OPCUA.csv UnitId = 12890 // "2Z" }; variable.OnWriteValue = OnWriteAnalog; variable.EURange.OnWriteValue = OnWriteAnalogRange; variable.EURange.AccessLevel = AccessLevels.CurrentReadOrWrite; variable.EURange.UserAccessLevel = AccessLevels.CurrentReadOrWrite; variable.EngineeringUnits.AccessLevel = AccessLevels.CurrentReadOrWrite; variable.EngineeringUnits.UserAccessLevel = AccessLevels.CurrentReadOrWrite; variable.InstrumentRange.OnWriteValue = OnWriteAnalogRange; variable.InstrumentRange.AccessLevel = AccessLevels.CurrentReadOrWrite; variable.InstrumentRange.UserAccessLevel = AccessLevels.CurrentReadOrWrite; parent?.AddChild(variable); return variable; } /// /// Creates a new variable. /// /// /// /// /// /// private TwoStateDiscreteState CreateTwoStateDiscreteItemVariable(NodeState parent, string path, string name, string trueState, string falseState) { var variable = new TwoStateDiscreteState(parent) { NodeId = new NodeId(path, NamespaceIndex), BrowseName = new QualifiedName(path, NamespaceIndex), DisplayName = new LocalizedText("en", name), WriteMask = AttributeWriteMask.None, UserWriteMask = AttributeWriteMask.None }; variable.Create( SystemContext, null, variable.BrowseName, null, true); variable.SymbolicName = name; variable.ReferenceTypeId = ReferenceTypes.Organizes; variable.DataType = DataTypeIds.Boolean; variable.ValueRank = ValueRanks.Scalar; variable.AccessLevel = AccessLevels.CurrentReadOrWrite; variable.UserAccessLevel = AccessLevels.CurrentReadOrWrite; variable.Historizing = false; variable.Value = (bool)GetNewValue(variable); variable.StatusCode = StatusCodes.Good; variable.Timestamp = DateTime.UtcNow; variable.TrueState.Value = trueState; variable.TrueState.AccessLevel = AccessLevels.CurrentReadOrWrite; variable.TrueState.UserAccessLevel = AccessLevels.CurrentReadOrWrite; variable.FalseState.Value = falseState; variable.FalseState.AccessLevel = AccessLevels.CurrentReadOrWrite; variable.FalseState.UserAccessLevel = AccessLevels.CurrentReadOrWrite; parent?.AddChild(variable); return variable; } /// /// Creates a new variable. /// /// /// /// /// private MultiStateDiscreteState CreateMultiStateDiscreteItemVariable(NodeState parent, string path, string name, params string[] values) { var variable = new MultiStateDiscreteState(parent) { NodeId = new NodeId(path, NamespaceIndex), BrowseName = new QualifiedName(path, NamespaceIndex), DisplayName = new LocalizedText("en", name), WriteMask = AttributeWriteMask.None, UserWriteMask = AttributeWriteMask.None }; variable.Create( SystemContext, null, variable.BrowseName, null, true); variable.SymbolicName = name; variable.ReferenceTypeId = ReferenceTypes.Organizes; variable.DataType = DataTypeIds.UInt32; variable.ValueRank = ValueRanks.Scalar; variable.AccessLevel = AccessLevels.CurrentReadOrWrite; variable.UserAccessLevel = AccessLevels.CurrentReadOrWrite; variable.Historizing = false; variable.Value = (uint)0; variable.StatusCode = StatusCodes.Good; variable.Timestamp = DateTime.UtcNow; variable.OnWriteValue = OnWriteDiscrete; var strings = new LocalizedText[values.Length]; for (var ii = 0; ii < strings.Length; ii++) { strings[ii] = values[ii]; } variable.EnumStrings.Value = strings; variable.EnumStrings.AccessLevel = AccessLevels.CurrentReadOrWrite; variable.EnumStrings.UserAccessLevel = AccessLevels.CurrentReadOrWrite; parent?.AddChild(variable); return variable; } /// /// Creates a new UInt32 variable. /// /// /// /// /// private MultiStateValueDiscreteState CreateMultiStateValueDiscreteItemVariable(NodeState parent, string path, string name, params string[] enumNames) { return CreateMultiStateValueDiscreteItemVariable(parent, path, name, null, enumNames); } /// /// Creates a new variable. /// /// /// /// /// /// private MultiStateValueDiscreteState CreateMultiStateValueDiscreteItemVariable(NodeState parent, string path, string name, NodeId nodeId, params string[] enumNames) { var variable = new MultiStateValueDiscreteState(parent) { NodeId = new NodeId(path, NamespaceIndex), BrowseName = new QualifiedName(path, NamespaceIndex), DisplayName = new LocalizedText("en", name), WriteMask = AttributeWriteMask.None, UserWriteMask = AttributeWriteMask.None }; variable.Create( SystemContext, null, variable.BrowseName, null, true); variable.SymbolicName = name; variable.ReferenceTypeId = ReferenceTypes.Organizes; variable.DataType = nodeId ?? DataTypeIds.UInt32; variable.ValueRank = ValueRanks.Scalar; variable.AccessLevel = AccessLevels.CurrentReadOrWrite; variable.UserAccessLevel = AccessLevels.CurrentReadOrWrite; variable.Historizing = false; variable.Value = (uint)0; variable.StatusCode = StatusCodes.Good; variable.Timestamp = DateTime.UtcNow; variable.OnWriteValue = OnWriteValueDiscrete; // there are two enumerations for this type: // EnumStrings = the string representations for enumerated values // ValueAsText = the actual enumerated value // set the enumerated strings var strings = new LocalizedText[enumNames.Length]; for (var ii = 0; ii < strings.Length; ii++) { strings[ii] = enumNames[ii]; } // set the enumerated values var values = new EnumValueType[enumNames.Length]; for (var ii = 0; ii < values.Length; ii++) { values[ii] = new EnumValueType { Value = ii, Description = strings[ii], DisplayName = strings[ii] }; } variable.EnumValues.Value = values; variable.EnumValues.AccessLevel = AccessLevels.CurrentReadOrWrite; variable.EnumValues.UserAccessLevel = AccessLevels.CurrentReadOrWrite; variable.ValueAsText.Value = variable.EnumValues.Value[0].DisplayName; parent?.AddChild(variable); return variable; } private ServiceResult OnWriteDiscrete( ISystemContext context, NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp) { var variable = node as MultiStateDiscreteState; // verify data type. var typeInfo = TypeInfo.IsInstanceOfDataType( value, variable.DataType, variable.ValueRank, context.NamespaceUris, context.TypeTable); if (typeInfo == null || typeInfo == TypeInfo.Unknown) { return StatusCodes.BadTypeMismatch; } if (indexRange != NumericRange.Empty) { return StatusCodes.BadIndexRangeInvalid; } var number = Convert.ToDouble(value, CultureInfo.InvariantCulture); if (number >= variable.EnumStrings.Value.Length || number < 0) { return StatusCodes.BadOutOfRange; } return ServiceResult.Good; } private ServiceResult OnWriteValueDiscrete( ISystemContext context, NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp) { var typeInfo = TypeInfo.Construct(value); if (node is not MultiStateValueDiscreteState variable || typeInfo == null || typeInfo == TypeInfo.Unknown || !TypeInfo.IsNumericType(typeInfo.BuiltInType)) { return StatusCodes.BadTypeMismatch; } if (indexRange != NumericRange.Empty) { return StatusCodes.BadIndexRangeInvalid; } var number = Convert.ToInt32(value, CultureInfo.InvariantCulture); if (number >= variable.EnumValues.Value.Length || number < 0) { return StatusCodes.BadOutOfRange; } if (!node.SetChildValue(context, BrowseNames.ValueAsText, variable.EnumValues.Value[number].DisplayName, true)) { return StatusCodes.BadOutOfRange; } node.ClearChangeMasks(context, true); return ServiceResult.Good; } private ServiceResult OnWriteAnalog( ISystemContext context, NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp) { var variable = node as AnalogItemState; // verify data type. var typeInfo = TypeInfo.IsInstanceOfDataType( value, variable.DataType, variable.ValueRank, context.NamespaceUris, context.TypeTable); if (typeInfo == null || typeInfo == TypeInfo.Unknown) { return StatusCodes.BadTypeMismatch; } // check index range. if (variable.ValueRank >= 0) { if (indexRange != NumericRange.Empty) { var target = variable.Value; ServiceResult result = indexRange.UpdateRange(ref target, value); if (ServiceResult.IsBad(result)) { return result; } value = target; } } // check instrument range. else { if (indexRange != NumericRange.Empty) { return StatusCodes.BadIndexRangeInvalid; } var number = Convert.ToDouble(value, CultureInfo.InvariantCulture); if (variable.InstrumentRange != null && (number < variable.InstrumentRange.Value.Low || number > variable.InstrumentRange.Value.High)) { return StatusCodes.BadOutOfRange; } } return ServiceResult.Good; } private ServiceResult OnWriteAnalogRange( ISystemContext context, NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp) { var typeInfo = TypeInfo.Construct(value); if (node is not PropertyState variable || value is not ExtensionObject extensionObject || typeInfo == null || typeInfo == TypeInfo.Unknown) { return StatusCodes.BadTypeMismatch; } if (extensionObject.Body is not Opc.Ua.Range newRange || variable.Parent is not AnalogItemState parent) { return StatusCodes.BadTypeMismatch; } if (indexRange != NumericRange.Empty) { return StatusCodes.BadIndexRangeInvalid; } var parentTypeInfo = TypeInfo.Construct(parent.Value); var parentRange = GetAnalogRange(parentTypeInfo.BuiltInType); if (parentRange.High < newRange.High || parentRange.Low > newRange.Low) { return StatusCodes.BadOutOfRange; } value = newRange; return ServiceResult.Good; } /// /// Creates a new variable. /// /// /// /// /// /// private BaseDataVariableState CreateVariable(NodeState parent, string path, string name, BuiltInType dataType, int valueRank) { return CreateVariable(parent, path, name, (uint)dataType, valueRank); } /// /// Creates a new variable. /// /// /// /// /// /// private BaseDataVariableState CreateVariable(NodeState parent, string path, string name, NodeId dataType, int valueRank) { var variable = new BaseDataVariableState(parent) { SymbolicName = name, ReferenceTypeId = ReferenceTypes.Organizes, TypeDefinitionId = VariableTypeIds.BaseDataVariableType, NodeId = new NodeId(path, NamespaceIndex), BrowseName = new QualifiedName(path, NamespaceIndex), DisplayName = new LocalizedText("en", name), WriteMask = AttributeWriteMask.DisplayName | AttributeWriteMask.Description, UserWriteMask = AttributeWriteMask.DisplayName | AttributeWriteMask.Description, DataType = dataType, ValueRank = valueRank, AccessLevel = AccessLevels.CurrentReadOrWrite, UserAccessLevel = AccessLevels.CurrentReadOrWrite, Historizing = false }; variable.Value = GetNewValue(variable); variable.StatusCode = StatusCodes.Good; variable.Timestamp = DateTime.UtcNow; if (valueRank == ValueRanks.OneDimension) { variable.ArrayDimensions = new ReadOnlyList([0]); } else if (valueRank == ValueRanks.TwoDimensions) { variable.ArrayDimensions = new ReadOnlyList([0, 0]); } parent?.AddChild(variable); return variable; } private BaseDataVariableState[] CreateVariables(NodeState parent, string path, string name, BuiltInType dataType, int valueRank, ushort numVariables) { return CreateVariables(parent, path, name, (uint)dataType, valueRank, numVariables); } private BaseDataVariableState[] CreateVariables(NodeState parent, string path, string name, NodeId dataType, int valueRank, ushort numVariables) { // first, create a new Parent folder for this data-type var newParentFolder = CreateFolder(parent, path, name); var itemsCreated = new List(); // now to create the remaining NUMBERED items for (uint i = 0; i < numVariables; i++) { var newName = string.Format(CultureInfo.InvariantCulture, "{0}_{1}", name, i.ToString("00", CultureInfo.InvariantCulture)); var newPath = string.Format(CultureInfo.InvariantCulture, "{0}_{1}", path, newName); itemsCreated.Add(CreateVariable(newParentFolder, newPath, newName, dataType, valueRank)); } return [.. itemsCreated]; } /// /// Creates a new variable. /// /// /// /// /// /// private BaseDataVariableState CreateDynamicVariable(NodeState parent, string path, string name, BuiltInType dataType, int valueRank) { return CreateDynamicVariable(parent, path, name, (uint)dataType, valueRank); } /// /// Creates a new variable. /// /// /// /// /// /// private BaseDataVariableState CreateDynamicVariable(NodeState parent, string path, string name, NodeId dataType, int valueRank) { var variable = CreateVariable(parent, path, name, dataType, valueRank); _dynamicNodes.Add(variable); return variable; } private BaseDataVariableState[] CreateDynamicVariables(NodeState parent, string path, string name, BuiltInType dataType, int valueRank, uint numVariables) { return CreateDynamicVariables(parent, path, name, (uint)dataType, valueRank, numVariables); } private BaseDataVariableState[] CreateDynamicVariables(NodeState parent, string path, string name, NodeId dataType, int valueRank, uint numVariables) { // first, create a new Parent folder for this data-type var newParentFolder = CreateFolder(parent, path, name); var itemsCreated = new List(); // now to create the remaining NUMBERED items for (uint i = 0; i < numVariables; i++) { var newName = string.Format(CultureInfo.InvariantCulture, "{0}_{1}", name, i.ToString("00", CultureInfo.InvariantCulture)); var newPath = string.Format(CultureInfo.InvariantCulture, "{0}_{1}", path, newName); itemsCreated.Add(CreateDynamicVariable(newParentFolder, newPath, newName, dataType, valueRank)); }//for i return [.. itemsCreated]; } /// /// Creates a new view. /// /// /// /// /// private ViewState CreateView(NodeState parent, IDictionary> externalReferences, string path, string name) { var type = new ViewState { SymbolicName = name, NodeId = new NodeId(path, NamespaceIndex), BrowseName = new QualifiedName(name, NamespaceIndex) }; type.DisplayName = type.BrowseName.Name; type.WriteMask = AttributeWriteMask.None; type.UserWriteMask = AttributeWriteMask.None; type.ContainsNoLoops = true; if (!externalReferences.TryGetValue(ObjectIds.ViewsFolder, out var references)) { externalReferences[ObjectIds.ViewsFolder] = references = []; } type.AddReference(ReferenceTypeIds.Organizes, true, ObjectIds.ViewsFolder); references.Add(new NodeStateReference(ReferenceTypeIds.Organizes, false, type.NodeId)); if (parent != null) { parent.AddReference(ReferenceTypes.Organizes, false, type.NodeId); type.AddReference(ReferenceTypes.Organizes, true, parent.NodeId); } AddPredefinedNode(SystemContext, type); return type; } /// /// Creates a new method. /// /// /// /// private MethodState CreateMethod(NodeState parent, string path, string name) { var method = new MethodState(parent) { SymbolicName = name, ReferenceTypeId = ReferenceTypeIds.HasComponent, NodeId = new NodeId(path, NamespaceIndex), BrowseName = new QualifiedName(path, NamespaceIndex), DisplayName = new LocalizedText("en", name), WriteMask = AttributeWriteMask.None, UserWriteMask = AttributeWriteMask.None, Executable = true, UserExecutable = true }; parent?.AddChild(method); return method; } private ServiceResult OnVoidCall( ISystemContext context, MethodState method, IList inputArguments, IList outputArguments) { return ServiceResult.Good; } private ServiceResult OnAddCall( ISystemContext context, MethodState method, IList inputArguments, IList outputArguments) { // all arguments must be provided. if (inputArguments.Count < 2) { return StatusCodes.BadArgumentsMissing; } try { var floatValue = (float)inputArguments[0]; var uintValue = (uint)inputArguments[1]; // set output parameter outputArguments[0] = floatValue + uintValue; return ServiceResult.Good; } catch { return new ServiceResult(StatusCodes.BadInvalidArgument); } } private ServiceResult OnMultiplyCall( ISystemContext context, MethodState method, IList inputArguments, IList outputArguments) { // all arguments must be provided. if (inputArguments.Count < 2) { return StatusCodes.BadArgumentsMissing; } try { var op1 = (short)inputArguments[0]; var op2 = (ushort)inputArguments[1]; // set output parameter outputArguments[0] = op1 * op2; return ServiceResult.Good; } catch { return new ServiceResult(StatusCodes.BadInvalidArgument); } } private ServiceResult OnDivideCall( ISystemContext context, MethodState method, IList inputArguments, IList outputArguments) { // all arguments must be provided. if (inputArguments.Count < 2) { return StatusCodes.BadArgumentsMissing; } try { var op1 = (int)inputArguments[0]; var op2 = (ushort)inputArguments[1]; // set output parameter outputArguments[0] = op1 / (float)op2; return ServiceResult.Good; } catch { return new ServiceResult(StatusCodes.BadInvalidArgument); } } private ServiceResult OnSubstractCall( ISystemContext context, MethodState method, IList inputArguments, IList outputArguments) { // all arguments must be provided. if (inputArguments.Count < 2) { return StatusCodes.BadArgumentsMissing; } try { var op1 = (short)inputArguments[0]; var op2 = (byte)inputArguments[1]; // set output parameter outputArguments[0] = (short)(op1 - op2); return ServiceResult.Good; } catch { return new ServiceResult(StatusCodes.BadInvalidArgument); } } private ServiceResult OnHelloCall( ISystemContext context, MethodState method, IList inputArguments, IList outputArguments) { // all arguments must be provided. if (inputArguments.Count < 1) { return StatusCodes.BadArgumentsMissing; } try { var op1 = (string)inputArguments[0]; // set output parameter outputArguments[0] = "hello " + op1; return ServiceResult.Good; } catch { return new ServiceResult(StatusCodes.BadInvalidArgument); } } private ServiceResult OnInputCall( ISystemContext context, MethodState method, IList inputArguments, IList outputArguments) { // all arguments must be provided. if (inputArguments.Count < 1) { return StatusCodes.BadArgumentsMissing; } return ServiceResult.Good; } private ServiceResult OnOutputCall( ISystemContext context, MethodState method, IList inputArguments, IList outputArguments) { // all arguments must be provided. try { // set output parameter outputArguments[0] = "Output"; return ServiceResult.Good; } catch { return new ServiceResult(StatusCodes.BadInvalidArgument); } } private void ResetRandomGenerator(int seed, int boundaryValueFrequency = 0) { _randomSource = new Opc.Ua.Test.RandomSource(seed); _generator = new Opc.Ua.Test.TestDataGenerator(_randomSource) { BoundaryValueFrequency = boundaryValueFrequency }; } private object GetNewValue(BaseVariableState variable) { Debug.Assert(_generator != null, "Need a random generator!"); object value = null; for (var retryCount = 0; value == null && retryCount < 10; retryCount++) { value = _generator.GetRandom(variable.DataType, variable.ValueRank, new uint[] { 10 }, Server.TypeTree); if (value is Variant variant && variant.Value == null) { value = null; } } return value; } private void DoSimulation(object state) { try { lock (Lock) { var timeStamp = DateTime.UtcNow; foreach (var variable in _dynamicNodes) { variable.Value = GetNewValue(variable); variable.Timestamp = timeStamp; variable.ClearChangeMasks(SystemContext, false); } } } catch (Exception e) { Utils.LogError(e, "Unexpected error doing simulation."); } } /// /// Frees any resources allocated for the address space. /// public override void DeleteAddressSpace() { lock (Lock) { // TBD } } /// /// Returns a unique handle for the node. /// /// /// /// protected override NodeHandle GetManagerHandle(ServerSystemContext context, NodeId nodeId, IDictionary cache) { lock (Lock) { // quickly exclude nodes that are not in the namespace. if (!IsNodeIdInNamespace(nodeId)) { return null; } if (!PredefinedNodes.TryGetValue(nodeId, out var node)) { return null; } return new NodeHandle { NodeId = nodeId, Node = node, Validated = true }; } } /// /// Verifies that the specified node exists. /// /// /// /// protected override NodeState ValidateNode( ServerSystemContext context, NodeHandle handle, IDictionary cache) { // not valid if no root. if (handle == null) { return null; } // check if previously validated. if (handle.Validated) { return handle.Node; } // TBD return null; } private Opc.Ua.Test.RandomSource _randomSource; private Opc.Ua.Test.TestDataGenerator _generator; private Timer _simulationTimer; private ushort _simulationInterval = 1000; private bool _simulationEnabled = true; private readonly List _dynamicNodes; } public static class VariableExtensions { public static BaseDataVariableState MinimumSamplingInterval(this BaseDataVariableState variable, int minimumSamplingInterval) { variable.MinimumSamplingInterval = minimumSamplingInterval; return variable; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Reference/ReferenceServer.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Reference { using Opc.Ua; using Opc.Ua.Server; /// public class ReferenceServer : INodeManagerFactory { /// public StringCollection NamespacesUris { get { return [ Namespaces.ReferenceApplications ]; } } /// public INodeManager Create(IServerInternal server, ApplicationConfiguration configuration) { return new ReferenceNodeManager(server, configuration); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Reference/ReferenceServerConfiguration.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Reference { using System.Runtime.Serialization; /// /// Stores the configuration the data access node manager. /// [DataContract(Namespace = Namespaces.ReferenceApplications)] public class ReferenceServerConfiguration { /// /// The default constructor. /// public ReferenceServerConfiguration() { Initialize(); } /// /// Initializes the object during deserialization. /// /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/ServerConsoleHost.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Services { using Azure.IIoT.OpcUa.Publisher.Stack; using Furly.Exceptions; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Configuration; using Opc.Ua.Server; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; /// /// Console host for servers /// public sealed class ServerConsoleHost : IServerHost { /// public X509Certificate2 Certificate { get; private set; } /// public string PkiRootPath { get; set; } /// public bool AutoAccept { get; set; } /// public string HostName { get; set; } /// public List AlternativeHosts { get; set; } /// public string UriPath { get; set; } /// public string CertStoreType { get; set; } /// /// Get access to the server /// public ITestServer TestServer => _server as ITestServer; /// /// Create server console host /// /// /// public ServerConsoleHost(IServerFactory factory, ILogger logger) { _instance = Guid.NewGuid().ToString(); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _factory = factory ?? throw new ArgumentNullException(nameof(factory)); } /// public async Task StopAsync() { if (_server != null) { await _lock.WaitAsync().ConfigureAwait(false); try { #pragma warning disable CA1508 // Avoid dead conditional code if (_server != null) { _logger.StoppingServer(this); try { _server.Stop(); } catch (OperationCanceledException) { } catch (Exception se) { _logger.ServerStopError(se, this); } _server.Dispose(); _logger.ServerStopped(this); } #pragma warning restore CA1508 // Avoid dead conditional code } catch (Exception ce) { _logger.StoppingError(ce, this); } finally { _server = null; Certificate = null; _lock.Release(); } } } /// public async Task AddReverseConnectionAsync(Uri client, int maxSessionCount) { await _lock.WaitAsync().ConfigureAwait(false); try { if (_server is ReverseConnectServer server) { server.AddReverseConnection(client, maxSessionCount: maxSessionCount); } } catch (Exception ex) { _logger.AddReverseConnectionError(ex, this); } finally { _lock.Release(); } } /// public async Task RemoveReverseConnectionAsync(Uri client) { await _lock.WaitAsync().ConfigureAwait(false); try { if (_server is ReverseConnectServer server) { server.RemoveReverseConnection(client); } } catch (Exception ex) { _logger.RemoveReverseConnectionError(ex, this); } finally { _lock.Release(); } } /// public async Task StartAsync(IEnumerable ports) { if (_server == null) { await _lock.WaitAsync().ConfigureAwait(false); try { #pragma warning disable CA1508 // Avoid dead conditional code if (_server == null) { await StartServerInternalAsync(ports).ConfigureAwait(false); _ports = ports.ToArray(); return; } #pragma warning restore CA1508 // Avoid dead conditional code } catch (Exception ex) { _logger.StartingError(ex, this); _server?.Dispose(); _server = null; throw; } finally { _lock.Release(); } } throw new InvalidOperationException($"Server {this} already started"); } /// public async Task RestartAsync(Func predicate) { await _lock.WaitAsync().ConfigureAwait(false); try { if (_server != null) { _server.Stop(); _server.Dispose(); if (predicate != null) { await predicate().ConfigureAwait(false); } _logger.Restarting(this); Debug.Assert(_ports != null); await StartServerInternalAsync(_ports).ConfigureAwait(false); } } finally { _lock.Release(); } } /// public void Dispose() { StopAsync().WaitAsync(TimeSpan.FromMinutes(1)).GetAwaiter().GetResult(); _lock.Dispose(); } /// public override string ToString() { return _instance; } /// /// Start server /// /// /// /// private async Task StartServerInternalAsync(IEnumerable ports) { ApplicationInstance.MessageDlg = new DummyDialog(); var config = _factory.CreateServer(ports, PkiRootPath, out _server, listenHostName: HostName, alternativeAddresses: AlternativeHosts, path: UriPath, certStoreType: CertStoreType, configure: configuration => configuration.DiagnosticsEnabled = true); _logger.ServerCreated(this); config.SecurityConfiguration.AutoAcceptUntrustedCertificates = AutoAccept; config = ApplicationInstance.FixupAppConfig(config); _logger.ValidatingConfig(this); await config.ValidateAsync(config.ApplicationType).ConfigureAwait(false); _logger.InitializingCertValidation(this); var application = new ApplicationInstance(config); // check the application certificate. var hasAppCertificate = await application.CheckApplicationInstanceCertificatesAsync( silent: true).ConfigureAwait(false); if (!hasAppCertificate) { _logger.CertValidationError(this); throw new InvalidConfigurationException("Application instance certificate invalid!"); } config.CertificateValidator.CertificateValidation += (v, e) => { if (e.Error.StatusCode == StatusCodes.BadCertificateUntrusted) { e.Accept = AutoAccept; _logger.CertificateAction(this, e.Accept ? "Accepted" : "Rejected", e.Certificate.Subject); } }; await config.CertificateValidator.UpdateAsync(config).ConfigureAwait(false); // Set Certificate try { // just take the public key Certificate = X509CertificateLoader.LoadCertificate( config.SecurityConfiguration.ApplicationCertificate.Certificate.RawData); } catch { Certificate = config.SecurityConfiguration.ApplicationCertificate.Certificate; } _logger.StartingServer(); // start the server. await application.StartAsync(_server).ConfigureAwait(false); foreach (var ep in config.ServerConfiguration.BaseAddresses) { _logger.ServerEndpoint(this, ep); } _logger.ServerStarted(this); } /// private sealed class DummyDialog : IApplicationMessageDlg { /// public override void Message(string text, bool ask) { } /// public override Task ShowAsync() { return Task.FromResult(true); } } private readonly string _instance; private readonly ILogger _logger; private readonly IServerFactory _factory; private readonly SemaphoreSlim _lock = new(1, 1); private ServerBase _server; private int[] _ports; } /// /// Source-generated logging definitions for ServerConsoleHost /// internal static partial class ServerConsoleHostLogging { private const int EventClass = 100; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Information, Message = "Stopping server {Instance}.")] public static partial void StoppingServer(this ILogger logger, object instance); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Error, Message = "Server {Instance} not cleanly stopped.")] public static partial void ServerStopError(this ILogger logger, Exception ex, object instance); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Information, Message = "Server {Instance} stopped.")] public static partial void ServerStopped(this ILogger logger, object instance); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Error, Message = "Stopping server {Instance} caused exception.")] public static partial void StoppingError(this ILogger logger, Exception ex, object instance); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Error, Message = "Adding reverse connection in server {Instance} failed.")] public static partial void AddReverseConnectionError(this ILogger logger, Exception ex, object instance); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Error, Message = "Remove reverse connection in server {Instance} failed.")] public static partial void RemoveReverseConnectionError(this ILogger logger, Exception ex, object instance); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Error, Message = "Starting server {Instance} caused exception.")] public static partial void StartingError(this ILogger logger, Exception ex, object instance); [LoggerMessage(EventId = EventClass + 8, Level = LogLevel.Information, Message = "Restarting server {Instance}...")] public static partial void Restarting(this ILogger logger, object instance); [LoggerMessage(EventId = EventClass + 9, Level = LogLevel.Information, Message = "Server {Instance} created...")] public static partial void ServerCreated(this ILogger logger, object instance); [LoggerMessage(EventId = EventClass + 10, Level = LogLevel.Information, Message = "Server {Instance} - Validate configuration...")] public static partial void ValidatingConfig(this ILogger logger, object instance); [LoggerMessage(EventId = EventClass + 11, Level = LogLevel.Information, Message = "Server {Instance} - Initialize certificate validation...")] public static partial void InitializingCertValidation(this ILogger logger, object instance); [LoggerMessage(EventId = EventClass + 12, Level = LogLevel.Error, Message = "Server {Instance} - Failed validating own certificate!")] public static partial void CertValidationError(this ILogger logger, object instance); [LoggerMessage(EventId = EventClass + 13, Level = LogLevel.Information, Message = "Server {Instance} - {Action} Certificate {Subject}")] public static partial void CertificateAction(this ILogger logger, object instance, string action, string subject); [LoggerMessage(EventId = EventClass + 14, Level = LogLevel.Information, Message = "Starting server ...")] public static partial void StartingServer(this ILogger logger); [LoggerMessage(EventId = EventClass + 15, Level = LogLevel.Information, Message = "Server {Instance} - Listening on {Endpoint}")] public static partial void ServerEndpoint(this ILogger logger, object instance, string endpoint); [LoggerMessage(EventId = EventClass + 16, Level = LogLevel.Information, Message = "Server {Instance} started.")] public static partial void ServerStarted(this ILogger logger, object instance); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/ServerFactory.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack.Sample { using Azure.IIoT.OpcUa.Publisher.Stack; using Furly.Extensions.Utils; using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Server; using Opc.Ua.Test; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; using System.Xml; /// /// Server factory /// public sealed class ServerFactory : IServerFactory { /// /// Whether to log status /// public bool LogStatus { get; set; } /// /// Whether to enable diagnostics /// public bool EnableDiagnostics { get; set; } /// /// Server factory /// /// /// /// public ServerFactory(ILogger logger, string tempPath, IEnumerable nodes) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _nodes = nodes ?? throw new ArgumentNullException(nameof(nodes)); _tempPath = tempPath; } /// /// Full set of servers /// /// /// /// public ServerFactory(ILogger logger, string tempPath, uint scaleunits = 0) : this(logger, tempPath, new List { new TestData.TestDataServer(), new MemoryBuffer.MemoryBufferServer(), new Boiler.BoilerServer(), new Vehicles.VehiclesServer(), new Reference.ReferenceServer(), new HistoricalEvents.HistoricalEventsServer(new TimeService()), new HistoricalAccess.HistoricalAccessServer(new TimeService()), new Views.ViewsServer(), new DataAccess.DataAccessServer(), new Alarms.AlarmConditionServer(new TimeService()), new SimpleEvents.SimpleEventsServer(), new Plc.PlcServer(new TimeService(), logger, scaleunits), new Isa95Jobs.Isa95JobControlServer() // new FileSystem.FileSystemServer(), // new Asset.AssetServer(logger), // new PerfTest.PerfTestServer(), }) { } /// public ApplicationConfiguration CreateServer(IEnumerable ports, string pkiRootPath, out ServerBase server, string listenHostName, IEnumerable alternativeAddresses, string path, string certStoreType, Action configure) { server = new Server(LogStatus, _nodes, _logger); return Server.CreateServerConfiguration(_tempPath, ports, listenHostName, alternativeAddresses, path, pkiRootPath, certStoreType, EnableDiagnostics, configure); } /// private sealed class Server : ReverseConnectServer, ITestServer { /// public string PublishedNodesJson => _plc.GetPnJson(); /// public bool Chaos { get { return _chaosMode != null; } set { if (value) { if (_chaosMode == null) { _chaosCts = new CancellationTokenSource(); _chaosMode = ChaosAsync(_chaosCts.Token); } } else if (_chaosMode != null) { _chaosCts.Cancel(); _chaosMode.GetAwaiter().GetResult(); _chaosCts.Dispose(); _chaosMode = null; _chaosCts = null; } } } /// public int InjectErrorResponseRate { get; set; } /// /// Create server /// /// /// /// public Server(bool logStatus, IEnumerable nodes, ILogger logger) { _logger = logger; _logStatus = logStatus; _nodes = nodes; } /// /// Create configuration /// /// /// /// /// /// /// /// /// /// /// public static ApplicationConfiguration CreateServerConfiguration(string curDir, IEnumerable ports, string hostName, IEnumerable alternativeAddresses, string path, string pkiRootPath, string certStoreType, bool enableDiagnostics = false, Action configure = null) { var extensions = new List { new MemoryBuffer.MemoryBufferConfiguration { Buffers = [ new MemoryBuffer.MemoryBufferInstance { Name = "UInt32", TagCount = 10000, DataType = "UInt32" }, new MemoryBuffer.MemoryBufferInstance { Name = "Double", TagCount = 100, DataType = "Double" } ] }, // ... new FolderConfiguration { CurrentDirectory = curDir } }; certStoreType ??= CertificateStoreType.Directory; if (string.IsNullOrEmpty(pkiRootPath)) { pkiRootPath = "pki"; } path ??= "/UA/SampleServer"; if (path.Length > 0 && !path.StartsWith('/')) { path = "/" + path; } var configuration = new ApplicationConfiguration { ApplicationName = "UA Core Sample Server", ApplicationType = ApplicationType.Server, ApplicationUri = $"urn:{hostName ?? Utils.GetHostName()}:OPCFoundation:CoreSampleServer", Extensions = [.. extensions.Select(XmlElementEx.SerializeObject)], ProductUri = "http://opcfoundation.org/UA/SampleServer", SecurityConfiguration = new SecurityConfiguration { ApplicationCertificate = new CertificateIdentifier { StoreType = certStoreType, StorePath = $"{pkiRootPath}/own", SubjectName = "UA Core Sample Server" }, TrustedPeerCertificates = new CertificateTrustList { StoreType = certStoreType, StorePath = $"{pkiRootPath}/trusted" }, TrustedIssuerCertificates = new CertificateTrustList { StoreType = certStoreType, StorePath = $"{pkiRootPath}/issuer" }, RejectedCertificateStore = new CertificateTrustList { StoreType = certStoreType, StorePath = $"{pkiRootPath}/rejected" }, MinimumCertificateKeySize = 1024, RejectSHA1SignedCertificates = false, AutoAcceptUntrustedCertificates = true, AddAppCertToTrustedStore = true, RejectUnknownRevocationStatus = true }, TransportConfigurations = [], TransportQuotas = new TransportQuotas { SecurityTokenLifetime = 60 * 60 * 1000, ChannelLifetime = 300 * 1000, MaxBufferSize = (64 * 1024) - 1, MaxMessageSize = 4 * 1024 * 1024, MaxArrayLength = (64 * 1024) - 1, MaxByteStringLength = 1024 * 1024, MaxStringLength = (128 * 1024) - 256, OperationTimeout = 120 * 1000 }, ServerConfiguration = new ServerConfiguration { // Sample server specific ServerProfileArray = [ "Standard UA Server Profile", "Data Access Server Facet", "Method Server Facet" ], ServerCapabilities = [ "DA" ], SupportedPrivateKeyFormats = [ "PFX", "PEM" ], ReverseConnect = new ReverseConnectServerConfiguration { ConnectInterval = 1000, ConnectTimeout = 120000, RejectTimeout = 120000 }, NodeManagerSaveFile = "nodes.xml", DiagnosticsEnabled = enableDiagnostics, ShutdownDelay = 0, // Runtime configuration BaseAddresses = [.. ports .Distinct() .Select(p => $"opc.tcp://{hostName ?? "localhost"}:{p}{path}")], AlternateBaseAddresses = alternativeAddresses == null ? null : [.. alternativeAddresses.Distinct().SelectMany(e => ports .Distinct() .Select(p => $"opc.tcp://{e}:{p}{path}"))], SecurityPolicies = [ new ServerSecurityPolicy { SecurityMode = MessageSecurityMode.Sign, SecurityPolicyUri = SecurityPolicies.Basic256Sha256 }, new ServerSecurityPolicy { SecurityMode = MessageSecurityMode.SignAndEncrypt, SecurityPolicyUri =SecurityPolicies.Basic256Sha256 }, new ServerSecurityPolicy { SecurityMode = MessageSecurityMode.None, SecurityPolicyUri = SecurityPolicies.None } ], UserTokenPolicies = [ new UserTokenPolicy { TokenType = UserTokenType.Anonymous, SecurityPolicyUri = SecurityPolicies.None }, new UserTokenPolicy { TokenType = UserTokenType.UserName }, new UserTokenPolicy { TokenType = UserTokenType.Certificate } ], MinRequestThreadCount = 200, MaxRequestThreadCount = 2000, MaxQueuedRequestCount = 2000000, MaxSessionCount = 30, MinSessionTimeout = 10000, MaxSessionTimeout = 3600000, MaxBrowseContinuationPoints = 1000, MaxQueryContinuationPoints = 1000, MaxHistoryContinuationPoints = 1000, MaxRequestAge = 600000, MinPublishingInterval = 100, MaxPublishingInterval = 3600000, PublishingResolution = 50, MaxSubscriptionLifetime = 3600000, MaxMessageQueueSize = 100, MaxNotificationQueueSize = 100, MaxNotificationsPerPublish = 1000, MinMetadataSamplingInterval = 1000, MaxPublishRequestCount = 8, MaxSubscriptionCount = 30, MaxEventQueueSize = 10000, MinSubscriptionLifetime = 10000, // Do not register with LDS MaxRegistrationInterval = 0, // TODO RegistrationEndpoint = null }, TraceConfiguration = new TraceConfiguration { TraceMasks = 1 } }; configure?.Invoke(configuration.ServerConfiguration); return configuration; } private NodeId[] Sessions => CurrentInstance.SessionManager .GetSessions() .Select(s => s.Id) .ToArray(); /// public void CloseSessions(bool deleteSubscriptions = false) { foreach (var session in Sessions) { CurrentInstance.CloseSession(null, session, deleteSubscriptions); } } private uint[] Subscriptions => CurrentInstance.SubscriptionManager .GetSubscriptions() .Select(s => s.Id) .ToArray(); /// public void CloseSubscriptions(bool notifyExpiration = false) { foreach (var subscription in Subscriptions) { CloseSubscription(subscription, notifyExpiration); } } /// public void CloseSubscription(uint subscriptionId, bool notifyExpiration) { if (notifyExpiration) { NotifySubscriptionExpiration(subscriptionId); } CurrentInstance.DeleteSubscription(subscriptionId); } /// public void NotifySubscriptionExpiration(uint subscriptionId) { try { var subscription = CurrentInstance.SubscriptionManager .GetSubscriptions() .FirstOrDefault(s => s.Id == subscriptionId); if (subscription != null) { var expireMethod = typeof(SubscriptionManager).GetMethod("SubscriptionExpired", BindingFlags.NonPublic | BindingFlags.Instance); expireMethod?.Invoke( CurrentInstance.SubscriptionManager, new object[] { subscription }); } } catch { // Nothing to do } } /// protected override ServerProperties LoadServerProperties() { return new ServerProperties { ManufacturerName = "OPC Foundation", ProductName = "OPC UA Sample Servers", ProductUri = "http://opcfoundation.org/UA/Samples/v1.0", SoftwareVersion = Utils.GetAssemblySoftwareVersion(), BuildNumber = Utils.GetAssemblyBuildNumber(), BuildDate = Utils.GetAssemblyTimestamp() }; } /// protected override MasterNodeManager CreateMasterNodeManager( IServerInternal server, ApplicationConfiguration configuration) { _logger.CreatingNodeManagers(); var nodeManagers = _nodes .Select(n => n.Create(server, configuration)) .ToArray(); _plc = nodeManagers.OfType().FirstOrDefault(); return new MasterNodeManager(server, configuration, null, nodeManagers); } /// protected override void OnServerStopping() { _logger.ServerStopping(); base.OnServerStopping(); _cts.Cancel(); _statusLogger?.Wait(); } /// protected override void OnServerStarted(IServerInternal server) { // start the status thread _cts = new CancellationTokenSource(); if (_logStatus) { _statusLogger = Task.Run(() => LogStatusAsync(_cts.Token)); // print notification on session events CurrentInstance.SessionManager.SessionActivated += OnEvent; CurrentInstance.SessionManager.SessionClosing += OnEvent; CurrentInstance.SessionManager.SessionCreated += OnEvent; } base.OnServerStarted(server); // request notifications when the user identity is changed. all valid users are accepted by default. server.SessionManager.ImpersonateUser += SessionManager_ImpersonateUser; } /// protected override void OnServerStarting(ApplicationConfiguration configuration) { _logger.ServerStarting(); CreateUserIdentityValidators(configuration); base.OnServerStarting(configuration); } /// protected override void OnNodeManagerStarted(IServerInternal server) { _logger.NodeManagersStarted(); base.OnNodeManagerStarted(server); } /// protected override void Dispose(bool disposing) { base.Dispose(disposing); _cts?.Dispose(); } /// /// Handle session event by logging status /// /// /// private void OnEvent(ISession session, SessionEventReason reason) { _lastEventTime = DateTime.UtcNow; LogSessionStatus(session, reason.ToString()); } /// /// Continously log session status if not logged during events /// /// /// private async Task LogStatusAsync(CancellationToken ct) { while (!ct.IsCancellationRequested) { if (DateTime.UtcNow - _lastEventTime > TimeSpan.FromMilliseconds(6000)) { _lastEventTime = DateTime.UtcNow; foreach (var session in CurrentInstance.SessionManager.GetSessions()) { LogSessionStatus(session, "-Status-", _lastEventTime); } } await Try.Async(() => Task.Delay(1000, ct)).ConfigureAwait(false); } } /// /// Helper to log session status /// /// /// /// private void LogSessionStatus(ISession session, string reason, DateTime? lastContact = null) { lock (session.DiagnosticsLock) { if (lastContact.HasValue) { _logger.SessionLastContact(reason, session.SessionDiagnostics.SessionName, lastContact.Value); } else { _logger.SessionStatus(reason, session.SessionDiagnostics.SessionName, session.Identity.DisplayName ?? "session", session.Id); } } } /// /// Creates the objects used to validate the user identity tokens supported by the server. /// /// private void CreateUserIdentityValidators(ApplicationConfiguration configuration) { for (var ii = 0; ii < configuration.ServerConfiguration.UserTokenPolicies.Count; ii++) { var policy = configuration.ServerConfiguration.UserTokenPolicies[ii]; // ignore policies without an explicit id. if (string.IsNullOrEmpty(policy.PolicyId)) { continue; } // create a validator for an issued token policy. if (policy.TokenType == UserTokenType.IssuedToken) { // the name of the element in the configuration file. var qname = new XmlQualifiedName(policy.PolicyId, Namespaces.OpcUa); // find the id for the issuer certificate. var id = configuration.ParseExtension(qname); if (id == null) { Utils.Trace( Utils.TraceMasks.Error, "Could not load CertificateIdentifier for UserTokenPolicy {0}", policy.PolicyId); continue; } } // create a validator for a certificate token policy. if (policy.TokenType == UserTokenType.Certificate) { // the name of the element in the configuration file. var qname = new XmlQualifiedName(policy.PolicyId, Namespaces.OpcUa); // find the location of the trusted issuers. var trustedIssuers = configuration.ParseExtension(qname); if (trustedIssuers == null) { Utils.Trace( Utils.TraceMasks.Error, "Could not load CertificateTrustList for UserTokenPolicy {0}", policy.PolicyId); continue; } // trusts any certificate in the trusted people store. _certificateValidator = CertificateValidator.GetChannelValidator(); } } } /// /// Called when a client tries to change its user identity. /// /// /// /// is null. /// private void SessionManager_ImpersonateUser(ISession session, ImpersonateEventArgs args) { ArgumentNullException.ThrowIfNull(session); if (args.NewIdentity is AnonymousIdentityToken guest) { args.Identity = new UserIdentity(guest); Utils.Trace("Guest access accepted: {0}", args.Identity.DisplayName); return; } // check for a user name token. if (args.NewIdentity is UserNameIdentityToken userNameToken) { var admin = VerifyPassword(userNameToken.UserName, userNameToken.DecryptedPassword); args.Identity = new UserIdentity(userNameToken); if (admin) { args.Identity = new SystemConfigurationIdentity(args.Identity); } Utils.Trace("UserName Token accepted: {0}", args.Identity.DisplayName); return; } // check for x509 user token. if (args.NewIdentity is X509IdentityToken x509Token) { var admin = VerifyCertificate(x509Token.Certificate); args.Identity = new UserIdentity(x509Token); if (admin) { args.Identity = new SystemConfigurationIdentity(args.Identity); } Utils.Trace("X509 Token accepted: {0}", args.Identity.DisplayName); return; } // check for x509 user token. if (args.NewIdentity is IssuedIdentityToken wssToken) { var admin = VerifyToken(wssToken); args.Identity = new UserIdentity(wssToken); if (admin) { args.Identity = new SystemConfigurationIdentity(args.Identity); } Utils.Trace("Issued Token accepted: {0}", args.Identity.DisplayName); return; } // construct translation object with default text. var info = new TranslationInfo("InvalidToken", "en-US", "Specified token is not valid."); // create an exception with a vendor defined sub-code. throw new ServiceResultException(new ServiceResult( StatusCodes.BadIdentityTokenRejected, "Bad token", kServerNamespaceUri, new LocalizedText(info))); } /// /// Validates the token /// /// /// private static bool VerifyToken(IssuedIdentityToken wssToken) { if ((wssToken.TokenData?.Length ?? 0) == 0) { var info = new TranslationInfo("InvalidToken", "en-US", "Specified token is empty."); // create an exception with a vendor defined sub-code. throw new ServiceResultException(new ServiceResult( StatusCodes.BadIdentityTokenRejected, "Bad token", kServerNamespaceUri, new LocalizedText(info))); } return false; } /// /// Validates the password for a username token. /// /// /// /// private static bool VerifyPassword(string userName, string password) { if (string.IsNullOrEmpty(password)) { // construct translation object with default text. var info = new TranslationInfo( "InvalidPassword", "en-US", "Specified password is not valid for user '{0}'.", userName); // create an exception with a vendor defined sub-code. throw new ServiceResultException(new ServiceResult( StatusCodes.BadIdentityTokenRejected, "InvalidPassword", kServerNamespaceUri, new LocalizedText(info))); } if (StringComparer.OrdinalIgnoreCase.Equals(userName, "test") && password == "test") { // Testing purposes only return true; } return false; } /// /// Verifies that a certificate user token is trusted. /// /// /// private bool VerifyCertificate(X509Certificate2 certificate) { try { if (_certificateValidator != null) { _certificateValidator.Validate(certificate); } else { CertificateValidator.Validate(certificate); } // determine if self-signed. var isSelfSigned = X509Utils.CompareDistinguishedName( certificate.Subject, certificate.Issuer); // do not allow self signed application certs as user token if (isSelfSigned && X509Utils.HasApplicationURN(certificate)) { throw new ServiceResultException(StatusCodes.BadCertificateUseNotAllowed); } return false; } catch (Exception e) { TranslationInfo info; StatusCode result = StatusCodes.BadIdentityTokenRejected; if (e is ServiceResultException se && se.StatusCode == StatusCodes.BadCertificateUseNotAllowed) { info = new TranslationInfo( "InvalidCertificate", "en-US", "'{0}' is an invalid user certificate.", certificate.Subject); result = StatusCodes.BadIdentityTokenInvalid; } else { // construct translation object with default text. info = new TranslationInfo( "UntrustedCertificate", "en-US", "'{0}' is not a trusted user certificate.", certificate.Subject); } // create an exception with a vendor defined sub-code. throw new ServiceResultException(new ServiceResult( result, info.Key, kServerNamespaceUri, new LocalizedText(info))); } } /// /// Chaos monkey mode /// /// /// #pragma warning disable CA5394 // Do not use insecure randomness private async Task ChaosAsync(CancellationToken ct) { try { while (!ct.IsCancellationRequested) { await Task.Delay(TimeSpan.FromSeconds(Random.Shared.Next(10, 60)), ct).ConfigureAwait(false); Console.WriteLine("===================\nCHAOS MONKEY TIME\n==================="); Console.WriteLine($"{Subscriptions.Length} subscriptions in {Sessions.Length} sessions!"); switch (Random.Shared.Next(0, 16)) { case 0: Console.WriteLine("!!!!! Closing all sessions and associated subscriptions. !!!!!!"); CloseSessions(true); break; case 1: Console.WriteLine("!!!!! Closing all sessions. !!!!! "); CloseSessions(false); break; case 2: Console.WriteLine("!!!!! Notifying expiration and closing all subscriptions. !!!!! "); CloseSubscriptions(true); break; case 3: Console.WriteLine("!!!!! Closing all subscriptions. !!!!!"); CloseSubscriptions(false); break; case > 3 and < 8: var sessions = Sessions; if (sessions.Length == 0) { break; } var session = sessions[Random.Shared.Next(0, sessions.Length)]; var delete = Random.Shared.Next() % 2 == 0; Console.WriteLine($"!!!!! Closing session {session} (delete subscriptions:{delete}). !!!!!"); CurrentInstance.CloseSession(null, session, delete); break; case > 10 and < 13: if (InjectErrorResponseRate != 0) { break; } InjectErrorResponseRate = Random.Shared.Next(1, 20); var duration = TimeSpan.FromSeconds(Random.Shared.Next(10, 150)); Console.WriteLine($"!!!!! Injecting random errors every {InjectErrorResponseRate} " + $"responses for {duration.TotalMicroseconds} ms. !!!!!"); _ = Task.Run(async () => { try { await Task.Delay(duration, ct).ConfigureAwait(false); } catch (OperationCanceledException) { } InjectErrorResponseRate = 0; }, ct); break; default: var subscriptions = Subscriptions; if (subscriptions.Length == 0) { break; } var subscription = subscriptions[Random.Shared.Next(0, subscriptions.Length)]; var notify = Random.Shared.Next() % 2 == 0; Console.WriteLine($"!!!!! Closing subscription {subscription} (notify:{notify}). !!!!!"); CloseSubscription(subscription, notify); break; } } } catch (OperationCanceledException) { // Nothing to do } } private static readonly StatusCode[] kStatusCodes = { StatusCodes.BadCertificateInvalid, StatusCodes.BadAlreadyExists, StatusCodes.BadNoSubscription, StatusCodes.BadSecureChannelClosed, StatusCodes.BadSessionClosed, StatusCodes.BadSessionIdInvalid, StatusCodes.BadSessionIdInvalid, StatusCodes.BadSessionIdInvalid, StatusCodes.BadSessionIdInvalid, StatusCodes.BadSessionIdInvalid, StatusCodes.BadSessionIdInvalid, StatusCodes.BadSessionIdInvalid, StatusCodes.BadSessionIdInvalid, StatusCodes.BadConnectionClosed, StatusCodes.BadServerHalted, StatusCodes.BadNotConnected, StatusCodes.BadNoCommunication, StatusCodes.BadRequestInterrupted, StatusCodes.BadRequestInterrupted, StatusCodes.BadRequestInterrupted }; protected override OperationContext ValidateRequest(RequestHeader requestHeader, RequestType requestType) { if (InjectErrorResponseRate != 0) { var dice = Random.Shared.Next(0, kStatusCodes.Length * InjectErrorResponseRate); if (dice < kStatusCodes.Length) { Console.WriteLine("--------> Injecting error: {0}", kStatusCodes[dice]); throw new ServiceResultException(kStatusCodes[dice]); } } return base.ValidateRequest(requestHeader, requestType); } #pragma warning restore CA5394 // Do not use insecure randomness private readonly ILogger _logger; private readonly bool _logStatus; private readonly IEnumerable _nodes; private Task _statusLogger; private DateTime _lastEventTime; private CancellationTokenSource _cts; private ICertificateValidator _certificateValidator; private CancellationTokenSource _chaosCts; private Task _chaosMode; #pragma warning disable CA2213 // Disposable fields should be disposed private Plc.PlcNodeManager _plc; #pragma warning restore CA2213 // Disposable fields should be disposed private const string kServerNamespaceUri = "http://opcfoundation.org/UA/Sample/"; } private readonly ILogger _logger; private readonly IEnumerable _nodes; private readonly string _tempPath; } /// /// Source-generated logging definitions for Server /// internal static partial class ServerLogging { private const int EventClass = 150; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Information, Message = "Creating the Node Managers.")] public static partial void CreatingNodeManagers(this ILogger logger); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Debug, Message = "The server is stopping.")] public static partial void ServerStopping(this ILogger logger); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Debug, Message = "The server is starting.")] public static partial void ServerStarting(this ILogger logger); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Information, Message = "The NodeManagers have started.")] public static partial void NodeManagersStarted(this ILogger logger); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Information, Message = "{Reason,9}:{SessionName,20}:Last Event:{LastEvent:HH:mm:ss}")] public static partial void SessionLastContact(this ILogger logger, string reason, string sessionName, DateTime lastEvent); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Information, Message = "{Reason,9}:{SessionName,20}:{DisplayName,20}:{SessionId}")] public static partial void SessionStatus(this ILogger logger, string reason, string sessionName, string displayName, NodeId sessionId); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/SimpleEvents/SimpleEventsNodeManager.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace SimpleEvents { using Opc.Ua; using Opc.Ua.Server; using System; using System.Collections.Generic; using System.Reflection; using System.Threading; /// /// A node manager for a server that exposes several variables. /// public class SimpleEventsNodeManager : CustomNodeManager2 { /// /// Initializes the node manager. /// /// /// public SimpleEventsNodeManager(IServerInternal server, ApplicationConfiguration configuration) : base(server, configuration) { SystemContext.NodeIdFactory = this; // set one namespace for the type model and one names for dynamically created nodes. var namespaceUrls = new string[1]; namespaceUrls[0] = Namespaces.SimpleEvents; SetNamespaces(namespaceUrls); // get the configuration for the node manager. // use suitable defaults if no configuration exists. _configuration = configuration.ParseExtension() ?? new SimpleEventsServerConfiguration(); } /// /// An overrideable version of the Dispose. /// /// protected override void Dispose(bool disposing) { if (disposing && _simulationTimer != null) { Utils.SilentDispose(_simulationTimer); _simulationTimer = null; } base.Dispose(disposing); } /// /// Creates the NodeId for the specified node. /// /// /// public override NodeId New(ISystemContext context, NodeState node) { return node.NodeId; } /// /// Loads a node set from a file or resource and addes them to the set of predefined nodes. /// /// protected override NodeStateCollection LoadPredefinedNodes(ISystemContext context) { var type = GetType().GetTypeInfo(); var predefinedNodes = new NodeStateCollection(); predefinedNodes.LoadFromBinaryResource(context, $"{type.Assembly.GetName().Name}.Generated.{type.Namespace}.Design.{type.Namespace}.PredefinedNodes.uanodes", type.Assembly, true); return predefinedNodes; } /// /// Does any initialization required before the address space can be used. /// /// /// /// The externalReferences is an out parameter that allows the node manager to link to nodes /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and /// should have a reference to the root folder node(s) exposed by this node manager. /// public override void CreateAddressSpace(IDictionary> externalReferences) { lock (Lock) { LoadPredefinedNodes(SystemContext, externalReferences); // start a simulation that changes the values of the nodes. _simulationTimer = new Timer(DoSimulation, null, kEventInterval, kEventInterval); } } /// /// Frees any resources allocated for the address space. /// public override void DeleteAddressSpace() { lock (Lock) { base.DeleteAddressSpace(); } } /// /// Returns a unique handle for the node. /// /// /// /// protected override NodeHandle GetManagerHandle(ServerSystemContext context, NodeId nodeId, IDictionary cache) { lock (Lock) { // quickly exclude nodes that are not in the namespace. if (!IsNodeIdInNamespace(nodeId)) { return null; } // check for predefined nodes. if (PredefinedNodes != null && PredefinedNodes.TryGetValue(nodeId, out var node)) { return new NodeHandle { NodeId = nodeId, Validated = true, Node = node }; } return null; } } /// /// Verifies that the specified node exists. /// /// /// /// protected override NodeState ValidateNode( ServerSystemContext context, NodeHandle handle, IDictionary cache) { // not valid if no root. if (handle == null) { return null; } // check if previously validated. if (handle.Validated) { return handle.Node; } // TBD return null; } /// /// Does the simulation. /// /// The state. private void DoSimulation(object state) { try { for (var ii = 1; ii < 3; ii++) { // construct translation object with default text. var info = new TranslationInfo( "SystemCycleStarted", "en-US", "The system cycle '{0}' has started.", ++_cycleId); // construct the event. var e = new SystemCycleStartedEventState(null); e.Initialize( SystemContext, null, (EventSeverity)ii, new LocalizedText(info)); e.SetChildValue(SystemContext, Opc.Ua.BrowseNames.SourceName, "System", false); e.SetChildValue(SystemContext, Opc.Ua.BrowseNames.SourceNode, Opc.Ua.ObjectIds.Server, false); e.SetChildValue(SystemContext, new QualifiedName(BrowseNames.CycleId, NamespaceIndex), _cycleId.ToString(), false); var step = new CycleStepDataType { Name = "Step 1", Duration = 1000 }; e.SetChildValue(SystemContext, new QualifiedName(BrowseNames.CurrentStep, NamespaceIndex), step, false); e.SetChildValue(SystemContext, new QualifiedName(BrowseNames.Steps, NamespaceIndex), new CycleStepDataType[] { step, step }, false); Server.ReportEvent(e); } } catch (NullReferenceException) { // Stop simulation because the subscription is closed. This should be fixed in the server library. _simulationTimer.Change(Timeout.Infinite, Timeout.Infinite); } catch (Exception e) { Utils.Trace(e, "Unexpected error during simulation."); } } #pragma warning disable IDE0052 // Remove unread private members private readonly SimpleEventsServerConfiguration _configuration; #pragma warning restore IDE0052 // Remove unread private members private Timer _simulationTimer; private int _cycleId; private const int kEventInterval = 1000; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/SimpleEvents/SimpleEventsServer.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace SimpleEvents { using Opc.Ua; using Opc.Ua.Server; /// public class SimpleEventsServer : INodeManagerFactory { /// public StringCollection NamespacesUris { get { return [ Namespaces.SimpleEvents ]; } } /// public INodeManager Create(IServerInternal server, ApplicationConfiguration configuration) { return new SimpleEventsNodeManager(server, configuration); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/SimpleEvents/SimpleEventsServerConfiguration.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace SimpleEvents { using System.Runtime.Serialization; /// /// Stores the configuration the data access node manager. /// [DataContract(Namespace = Namespaces.SimpleEvents)] public class SimpleEventsServerConfiguration { /// /// The default constructor. /// public SimpleEventsServerConfiguration() { Initialize(); } /// /// Initializes the object during deserialization. /// /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/TestData/AnalogArrayValueObjectState.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace TestData { using Opc.Ua; public partial class AnalogArrayValueObjectState { /// /// Initializes the object as a collection of counters which change value on read. /// /// /// protected override void OnAfterCreate(ISystemContext context, NodeState node) { base.OnAfterCreate(context, node); InitializeVariable(context, SByteValue, Variables.AnalogArrayValueObjectType_SByteValue); InitializeVariable(context, ByteValue, Variables.AnalogArrayValueObjectType_ByteValue); InitializeVariable(context, Int16Value, Variables.AnalogArrayValueObjectType_Int16Value); InitializeVariable(context, UInt16Value, Variables.AnalogArrayValueObjectType_UInt16Value); InitializeVariable(context, Int32Value, Variables.AnalogArrayValueObjectType_Int32Value); InitializeVariable(context, UInt32Value, Variables.AnalogArrayValueObjectType_UInt32Value); InitializeVariable(context, Int64Value, Variables.AnalogArrayValueObjectType_Int64Value); InitializeVariable(context, UInt64Value, Variables.AnalogArrayValueObjectType_UInt64Value); InitializeVariable(context, FloatValue, Variables.AnalogArrayValueObjectType_FloatValue); InitializeVariable(context, DoubleValue, Variables.AnalogArrayValueObjectType_DoubleValue); InitializeVariable(context, NumberValue, Variables.AnalogArrayValueObjectType_NumberValue); InitializeVariable(context, IntegerValue, Variables.AnalogArrayValueObjectType_IntegerValue); InitializeVariable(context, UIntegerValue, Variables.AnalogArrayValueObjectType_UIntegerValue); } /// /// Handles the generate values method. /// /// /// /// /// protected override ServiceResult OnGenerateValues( ISystemContext context, MethodState method, NodeId objectId, uint count) { if (context.SystemHandle is not TestDataSystem system) { return StatusCodes.BadOutOfService; } GenerateValue(system, SByteValue); GenerateValue(system, ByteValue); GenerateValue(system, Int16Value); GenerateValue(system, UInt16Value); GenerateValue(system, Int32Value); GenerateValue(system, UInt32Value); GenerateValue(system, UInt32Value); GenerateValue(system, Int64Value); GenerateValue(system, UInt64Value); GenerateValue(system, FloatValue); GenerateValue(system, DoubleValue); GenerateValue(system, NumberValue); GenerateValue(system, IntegerValue); GenerateValue(system, UIntegerValue); return base.OnGenerateValues(context, method, objectId, count); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/TestData/AnalogScalarValueObjectState.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace TestData { using Opc.Ua; public partial class AnalogScalarValueObjectState { /// /// Initializes the object as a collection of counters which change value on read. /// /// /// protected override void OnAfterCreate(ISystemContext context, NodeState node) { base.OnAfterCreate(context, node); InitializeVariable(context, SByteValue, Variables.AnalogScalarValueObjectType_SByteValue); InitializeVariable(context, ByteValue, Variables.AnalogScalarValueObjectType_ByteValue); InitializeVariable(context, Int16Value, Variables.AnalogScalarValueObjectType_Int16Value); InitializeVariable(context, UInt16Value, Variables.AnalogScalarValueObjectType_UInt16Value); InitializeVariable(context, Int32Value, Variables.AnalogScalarValueObjectType_Int32Value); InitializeVariable(context, UInt32Value, Variables.AnalogScalarValueObjectType_UInt32Value); InitializeVariable(context, Int64Value, Variables.AnalogScalarValueObjectType_Int64Value); InitializeVariable(context, UInt64Value, Variables.AnalogScalarValueObjectType_UInt64Value); InitializeVariable(context, FloatValue, Variables.AnalogScalarValueObjectType_FloatValue); InitializeVariable(context, DoubleValue, Variables.AnalogScalarValueObjectType_DoubleValue); InitializeVariable(context, NumberValue, Variables.AnalogScalarValueObjectType_NumberValue); InitializeVariable(context, IntegerValue, Variables.AnalogScalarValueObjectType_IntegerValue); InitializeVariable(context, UIntegerValue, Variables.AnalogScalarValueObjectType_UIntegerValue); } /// /// Handles the generate values method. /// /// /// /// /// protected override ServiceResult OnGenerateValues( ISystemContext context, MethodState method, NodeId objectId, uint count) { if (context.SystemHandle is not TestDataSystem system) { return StatusCodes.BadOutOfService; } GenerateValue(system, SByteValue); GenerateValue(system, ByteValue); GenerateValue(system, Int16Value); GenerateValue(system, UInt16Value); GenerateValue(system, Int32Value); GenerateValue(system, UInt32Value); GenerateValue(system, UInt32Value); GenerateValue(system, Int64Value); GenerateValue(system, UInt64Value); GenerateValue(system, FloatValue); GenerateValue(system, DoubleValue); GenerateValue(system, NumberValue); GenerateValue(system, IntegerValue); GenerateValue(system, UIntegerValue); return base.OnGenerateValues(context, method, objectId, count); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/TestData/ArrayValueObjectState.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace TestData { using Opc.Ua; public partial class ArrayValueObjectState { /// /// Initializes the object as a collection of counters which change value on read. /// /// /// protected override void OnAfterCreate(ISystemContext context, NodeState node) { base.OnAfterCreate(context, node); InitializeVariable(context, BooleanValue, Variables.ArrayValueObjectType_BooleanValue); InitializeVariable(context, SByteValue, Variables.ArrayValueObjectType_SByteValue); InitializeVariable(context, ByteValue, Variables.ArrayValueObjectType_ByteValue); InitializeVariable(context, Int16Value, Variables.ArrayValueObjectType_Int16Value); InitializeVariable(context, UInt16Value, Variables.ArrayValueObjectType_UInt16Value); InitializeVariable(context, Int32Value, Variables.ArrayValueObjectType_Int32Value); InitializeVariable(context, UInt32Value, Variables.ArrayValueObjectType_UInt32Value); InitializeVariable(context, Int64Value, Variables.ArrayValueObjectType_Int64Value); InitializeVariable(context, UInt64Value, Variables.ArrayValueObjectType_UInt64Value); InitializeVariable(context, FloatValue, Variables.ArrayValueObjectType_FloatValue); InitializeVariable(context, DoubleValue, Variables.ArrayValueObjectType_DoubleValue); InitializeVariable(context, StringValue, Variables.ArrayValueObjectType_StringValue); InitializeVariable(context, DateTimeValue, Variables.ArrayValueObjectType_DateTimeValue); InitializeVariable(context, GuidValue, Variables.ArrayValueObjectType_GuidValue); InitializeVariable(context, ByteStringValue, Variables.ArrayValueObjectType_ByteStringValue); InitializeVariable(context, XmlElementValue, Variables.ArrayValueObjectType_XmlElementValue); InitializeVariable(context, NodeIdValue, Variables.ArrayValueObjectType_NodeIdValue); InitializeVariable(context, ExpandedNodeIdValue, Variables.ArrayValueObjectType_ExpandedNodeIdValue); InitializeVariable(context, QualifiedNameValue, Variables.ArrayValueObjectType_QualifiedNameValue); InitializeVariable(context, LocalizedTextValue, Variables.ArrayValueObjectType_LocalizedTextValue); InitializeVariable(context, StatusCodeValue, Variables.ArrayValueObjectType_StatusCodeValue); InitializeVariable(context, VariantValue, Variables.ArrayValueObjectType_VariantValue); InitializeVariable(context, EnumerationValue, Variables.ArrayValueObjectType_EnumerationValue); InitializeVariable(context, StructureValue, Variables.ArrayValueObjectType_StructureValue); InitializeVariable(context, NumberValue, Variables.ArrayValueObjectType_NumberValue); InitializeVariable(context, IntegerValue, Variables.ArrayValueObjectType_IntegerValue); InitializeVariable(context, UIntegerValue, Variables.ArrayValueObjectType_UIntegerValue); } /// /// Handles the generate values method. /// /// /// /// /// protected override ServiceResult OnGenerateValues( ISystemContext context, MethodState method, NodeId objectId, uint count) { if (context.SystemHandle is not TestDataSystem system) { return StatusCodes.BadOutOfService; } GenerateValue(system, BooleanValue); GenerateValue(system, SByteValue); GenerateValue(system, ByteValue); GenerateValue(system, Int16Value); GenerateValue(system, UInt16Value); GenerateValue(system, Int32Value); GenerateValue(system, UInt32Value); GenerateValue(system, UInt32Value); GenerateValue(system, Int64Value); GenerateValue(system, UInt64Value); GenerateValue(system, FloatValue); GenerateValue(system, DoubleValue); GenerateValue(system, StringValue); GenerateValue(system, DateTimeValue); GenerateValue(system, GuidValue); GenerateValue(system, ByteStringValue); GenerateValue(system, XmlElementValue); GenerateValue(system, NodeIdValue); GenerateValue(system, ExpandedNodeIdValue); GenerateValue(system, QualifiedNameValue); GenerateValue(system, LocalizedTextValue); GenerateValue(system, StatusCodeValue); GenerateValue(system, VariantValue); GenerateValue(system, EnumerationValue); GenerateValue(system, StructureValue); GenerateValue(system, NumberValue); GenerateValue(system, IntegerValue); GenerateValue(system, UIntegerValue); return base.OnGenerateValues(context, method, objectId, count); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/TestData/HistoryArchive.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace TestData { using Opc.Ua; using System; using System.Collections.Generic; using System.Threading; /// /// A class that provides access to archived data. /// internal sealed class HistoryArchive : IDisposable { /// /// Frees any unmanaged resources. /// public void Dispose() { if (_updateTimer != null) { _updateTimer.Dispose(); _updateTimer = null; } } /// /// Creates a new record in the archive. /// /// /// public void CreateRecord(NodeId nodeId, BuiltInType dataType) { lock (_lock) { var record = new HistoryRecord { RawData = [], Historizing = true, DataType = dataType }; var now = DateTime.UtcNow; for (var ii = 1000; ii >= 0; ii--) { var entry = new HistoryEntry { Value = new DataValue { ServerTimestamp = now.AddSeconds(-(ii * 10)) } }; entry.Value.SourceTimestamp = entry.Value.ServerTimestamp.AddMilliseconds(1234); entry.IsModified = false; switch (dataType) { case BuiltInType.Int32: { entry.Value.Value = ii; break; } } record.RawData.Add(entry); } _records ??= []; _records[nodeId] = record; _updateTimer ??= new Timer(OnUpdate, null, 10000, 10000); } } /// /// Periodically adds new values into the archive. /// /// private void OnUpdate(object state) { try { var now = DateTime.UtcNow; lock (_lock) { foreach (var record in _records.Values) { if (!record.Historizing || record.RawData.Count >= 2000) { continue; } var entry = new HistoryEntry { Value = new DataValue { ServerTimestamp = now } }; entry.Value.SourceTimestamp = entry.Value.ServerTimestamp.AddMilliseconds(-4567); entry.IsModified = false; switch (record.DataType) { case BuiltInType.Int32: { var lastValue = (int)record.RawData[^1].Value.Value; entry.Value.Value = lastValue + 1; break; } } record.RawData.Add(entry); } } } catch (Exception e) { Utils.Trace(e, "Unexpected error updating history."); } } private readonly Lock _lock = new(); private Timer _updateTimer; private Dictionary _records; } /// /// A single entry in the archive. /// internal sealed class HistoryEntry { public DataValue Value; public bool IsModified; } /// /// A record in the archive. /// internal sealed class HistoryRecord { public List RawData; public bool Historizing; public BuiltInType DataType; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/TestData/MethodTestState.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace TestData { using Opc.Ua; using System; using System.Xml; public partial class MethodTestState { /// /// Initializes the object as a collection of counters which change value on read. /// /// /// protected override void OnAfterCreate(ISystemContext context, NodeState node) { base.OnAfterCreate(context, node); ScalarMethod1.OnCall = OnScalarValue1; ScalarMethod2.OnCall = OnScalarValue2; ScalarMethod3.OnCall = OnScalarValue3; ArrayMethod1.OnCall = OnArrayValue1; ArrayMethod2.OnCall = OnArrayValue2; ArrayMethod3.OnCall = OnArrayValue3; UserScalarMethod1.OnCall = OnUserScalarValue1; UserScalarMethod2.OnCall = OnUserScalarValue2; UserArrayMethod1.OnCall = OnUserArrayValue1; UserArrayMethod2.OnCall = OnUserArrayValue2; } private ServiceResult OnScalarValue1( ISystemContext context, MethodState method, NodeId objectId, bool booleanIn, sbyte sByteIn, byte byteIn, short int16In, ushort uInt16In, int int32In, uint uInt32In, long int64In, ulong uInt64In, float floatIn, double doubleIn, ref bool booleanOut, ref sbyte sByteOut, ref byte byteOut, ref short int16Out, ref ushort uInt16Out, ref int int32Out, ref uint uInt32Out, ref long int64Out, ref ulong uInt64Out, ref float floatOut, ref double doubleOut) { booleanOut = booleanIn; sByteOut = sByteIn; byteOut = byteIn; int16Out = int16In; uInt16Out = uInt16In; int32Out = int32In; uInt32Out = uInt32In; int64Out = int64In; uInt64Out = uInt64In; floatOut = floatIn; doubleOut = doubleIn; return ServiceResult.Good; } private ServiceResult OnScalarValue2( ISystemContext context, MethodState method, NodeId objectId, string stringIn, DateTime dateTimeIn, Uuid guidIn, byte[] byteStringIn, XmlElement xmlElementIn, NodeId nodeIdIn, ExpandedNodeId expandedNodeIdIn, QualifiedName qualifiedNameIn, LocalizedText localizedTextIn, StatusCode statusCodeIn, ref string stringOut, ref DateTime dateTimeOut, ref Uuid guidOut, ref byte[] byteStringOut, ref XmlElement xmlElementOut, ref NodeId nodeIdOut, ref ExpandedNodeId expandedNodeIdOut, ref QualifiedName qualifiedNameOut, ref LocalizedText localizedTextOut, ref StatusCode statusCodeOut) { stringOut = stringIn; dateTimeOut = dateTimeIn; guidOut = guidIn; byteStringOut = byteStringIn; xmlElementOut = xmlElementIn; nodeIdOut = nodeIdIn; expandedNodeIdOut = expandedNodeIdIn; qualifiedNameOut = qualifiedNameIn; localizedTextOut = localizedTextIn; statusCodeOut = statusCodeIn; return ServiceResult.Good; } private ServiceResult OnScalarValue3( ISystemContext context, MethodState method, NodeId objectId, object variantIn, int enumerationIn, ExtensionObject structureIn, ref object variantOut, ref int enumerationOut, ref ExtensionObject structureOut) { variantOut = variantIn; enumerationOut = enumerationIn; structureOut = structureIn; return ServiceResult.Good; } private ServiceResult OnArrayValue1( ISystemContext context, MethodState method, NodeId objectId, bool[] booleanIn, sbyte[] sByteIn, byte[] byteIn, short[] int16In, ushort[] uInt16In, int[] int32In, uint[] uInt32In, long[] int64In, ulong[] uInt64In, float[] floatIn, double[] doubleIn, ref bool[] booleanOut, ref sbyte[] sByteOut, ref byte[] byteOut, ref short[] int16Out, ref ushort[] uInt16Out, ref int[] int32Out, ref uint[] uInt32Out, ref long[] int64Out, ref ulong[] uInt64Out, ref float[] floatOut, ref double[] doubleOut) { booleanOut = booleanIn; sByteOut = sByteIn; byteOut = byteIn; int16Out = int16In; uInt16Out = uInt16In; int32Out = int32In; uInt32Out = uInt32In; int64Out = int64In; uInt64Out = uInt64In; floatOut = floatIn; doubleOut = doubleIn; return ServiceResult.Good; } private ServiceResult OnArrayValue2( ISystemContext context, MethodState method, NodeId objectId, string[] stringIn, DateTime[] dateTimeIn, Uuid[] guidIn, byte[][] byteStringIn, XmlElement[] xmlElementIn, NodeId[] nodeIdIn, ExpandedNodeId[] expandedNodeIdIn, QualifiedName[] qualifiedNameIn, LocalizedText[] localizedTextIn, StatusCode[] statusCodeIn, ref string[] stringOut, ref DateTime[] dateTimeOut, ref Uuid[] guidOut, ref byte[][] byteStringOut, ref XmlElement[] xmlElementOut, ref NodeId[] nodeIdOut, ref ExpandedNodeId[] expandedNodeIdOut, ref QualifiedName[] qualifiedNameOut, ref LocalizedText[] localizedTextOut, ref StatusCode[] statusCodeOut) { stringOut = stringIn; dateTimeOut = dateTimeIn; guidOut = guidIn; byteStringOut = byteStringIn; xmlElementOut = xmlElementIn; nodeIdOut = nodeIdIn; expandedNodeIdOut = expandedNodeIdIn; qualifiedNameOut = qualifiedNameIn; localizedTextOut = localizedTextIn; statusCodeOut = statusCodeIn; return ServiceResult.Good; } private ServiceResult OnArrayValue3( ISystemContext context, MethodState method, NodeId objectId, Variant[] variantIn, int[] enumerationIn, ExtensionObject[] structureIn, ref Variant[] variantOut, ref int[] enumerationOut, ref ExtensionObject[] structureOut) { variantOut = variantIn; enumerationOut = enumerationIn; structureOut = structureIn; return ServiceResult.Good; } private ServiceResult OnUserScalarValue1( ISystemContext context, MethodState method, NodeId objectId, bool booleanIn, sbyte sByteIn, byte byteIn, short int16In, ushort uInt16In, int int32In, uint uInt32In, long int64In, ulong uInt64In, float floatIn, double doubleIn, string stringIn, ref bool booleanOut, ref sbyte sByteOut, ref byte byteOut, ref short int16Out, ref ushort uInt16Out, ref int int32Out, ref uint uInt32Out, ref long int64Out, ref ulong uInt64Out, ref float floatOut, ref double doubleOut, ref string stringOut) { booleanOut = booleanIn; sByteOut = sByteIn; byteOut = byteIn; int16Out = int16In; uInt16Out = uInt16In; int32Out = int32In; uInt32Out = uInt32In; int64Out = int64In; uInt64Out = uInt64In; floatOut = floatIn; doubleOut = doubleIn; stringOut = stringIn; return ServiceResult.Good; } private ServiceResult OnUserScalarValue2( ISystemContext context, MethodState method, NodeId objectId, DateTime dateTimeIn, Uuid guidIn, byte[] byteStringIn, XmlElement xmlElementIn, NodeId nodeIdIn, ExpandedNodeId expandedNodeIdIn, QualifiedName qualifiedNameIn, LocalizedText localizedTextIn, StatusCode statusCodeIn, object variantIn, ref DateTime dateTimeOut, ref Uuid guidOut, ref byte[] byteStringOut, ref XmlElement xmlElementOut, ref NodeId nodeIdOut, ref ExpandedNodeId expandedNodeIdOut, ref QualifiedName qualifiedNameOut, ref LocalizedText localizedTextOut, ref StatusCode statusCodeOut, ref object variantOut) { dateTimeOut = dateTimeIn; guidOut = guidIn; byteStringOut = byteStringIn; xmlElementOut = xmlElementIn; nodeIdOut = nodeIdIn; expandedNodeIdOut = expandedNodeIdIn; qualifiedNameOut = qualifiedNameIn; localizedTextOut = localizedTextIn; statusCodeOut = statusCodeIn; variantOut = variantIn; return ServiceResult.Good; } private ServiceResult OnUserArrayValue1( ISystemContext context, MethodState method, NodeId objectId, bool[] booleanIn, sbyte[] sByteIn, byte[] byteIn, short[] int16In, ushort[] uInt16In, int[] int32In, uint[] uInt32In, long[] int64In, ulong[] uInt64In, float[] floatIn, double[] doubleIn, string[] stringIn, ref bool[] booleanOut, ref sbyte[] sByteOut, ref byte[] byteOut, ref short[] int16Out, ref ushort[] uInt16Out, ref int[] int32Out, ref uint[] uInt32Out, ref long[] int64Out, ref ulong[] uInt64Out, ref float[] floatOut, ref double[] doubleOut, ref string[] stringOut) { booleanOut = booleanIn; sByteOut = sByteIn; byteOut = byteIn; int16Out = int16In; uInt16Out = uInt16In; int32Out = int32In; uInt32Out = uInt32In; int64Out = int64In; uInt64Out = uInt64In; floatOut = floatIn; doubleOut = doubleIn; stringOut = stringIn; return ServiceResult.Good; } private ServiceResult OnUserArrayValue2( ISystemContext context, MethodState method, NodeId objectId, DateTime[] dateTimeIn, Uuid[] guidIn, byte[][] byteStringIn, XmlElement[] xmlElementIn, NodeId[] nodeIdIn, ExpandedNodeId[] expandedNodeIdIn, QualifiedName[] qualifiedNameIn, LocalizedText[] localizedTextIn, StatusCode[] statusCodeIn, Variant[] variantIn, ref DateTime[] dateTimeOut, ref Uuid[] guidOut, ref byte[][] byteStringOut, ref XmlElement[] xmlElementOut, ref NodeId[] nodeIdOut, ref ExpandedNodeId[] expandedNodeIdOut, ref QualifiedName[] qualifiedNameOut, ref LocalizedText[] localizedTextOut, ref StatusCode[] statusCodeOut, ref Variant[] variantOut) { dateTimeOut = dateTimeIn; guidOut = guidIn; byteStringOut = byteStringIn; xmlElementOut = xmlElementIn; nodeIdOut = nodeIdIn; expandedNodeIdOut = expandedNodeIdIn; qualifiedNameOut = qualifiedNameIn; localizedTextOut = localizedTextIn; statusCodeOut = statusCodeIn; variantOut = variantIn; return ServiceResult.Good; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/TestData/ScalarValueObjectState.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace TestData { using Opc.Ua; public partial class ScalarValueObjectState { /// /// Initializes the object as a collection of counters which change value on read. /// /// /// protected override void OnAfterCreate(ISystemContext context, NodeState node) { base.OnAfterCreate(context, node); InitializeVariable(context, BooleanValue, Variables.ScalarValueObjectType_BooleanValue); InitializeVariable(context, SByteValue, Variables.ScalarValueObjectType_SByteValue); InitializeVariable(context, ByteValue, Variables.ScalarValueObjectType_ByteValue); InitializeVariable(context, Int16Value, Variables.ScalarValueObjectType_Int16Value); InitializeVariable(context, UInt16Value, Variables.ScalarValueObjectType_UInt16Value); InitializeVariable(context, Int32Value, Variables.ScalarValueObjectType_Int32Value); InitializeVariable(context, UInt32Value, Variables.ScalarValueObjectType_UInt32Value); InitializeVariable(context, Int64Value, Variables.ScalarValueObjectType_Int64Value); InitializeVariable(context, UInt64Value, Variables.ScalarValueObjectType_UInt64Value); InitializeVariable(context, FloatValue, Variables.ScalarValueObjectType_FloatValue); InitializeVariable(context, DoubleValue, Variables.ScalarValueObjectType_DoubleValue); InitializeVariable(context, StringValue, Variables.ScalarValueObjectType_StringValue); InitializeVariable(context, DateTimeValue, Variables.ScalarValueObjectType_DateTimeValue); InitializeVariable(context, GuidValue, Variables.ScalarValueObjectType_GuidValue); InitializeVariable(context, ByteStringValue, Variables.ScalarValueObjectType_ByteStringValue); InitializeVariable(context, XmlElementValue, Variables.ScalarValueObjectType_XmlElementValue); InitializeVariable(context, NodeIdValue, Variables.ScalarValueObjectType_NodeIdValue); InitializeVariable(context, ExpandedNodeIdValue, Variables.ScalarValueObjectType_ExpandedNodeIdValue); InitializeVariable(context, QualifiedNameValue, Variables.ScalarValueObjectType_QualifiedNameValue); InitializeVariable(context, LocalizedTextValue, Variables.ScalarValueObjectType_LocalizedTextValue); InitializeVariable(context, StatusCodeValue, Variables.ScalarValueObjectType_StatusCodeValue); InitializeVariable(context, VariantValue, Variables.ScalarValueObjectType_VariantValue); InitializeVariable(context, EnumerationValue, Variables.ScalarValueObjectType_EnumerationValue); InitializeVariable(context, StructureValue, Variables.ScalarValueObjectType_StructureValue); InitializeVariable(context, NumberValue, Variables.ScalarValueObjectType_NumberValue); InitializeVariable(context, IntegerValue, Variables.ScalarValueObjectType_IntegerValue); InitializeVariable(context, UIntegerValue, Variables.ScalarValueObjectType_UIntegerValue); } /// /// Handles the generate values method. /// /// /// /// /// protected override ServiceResult OnGenerateValues( ISystemContext context, MethodState method, NodeId objectId, uint count) { if (context.SystemHandle is not TestDataSystem system) { return StatusCodes.BadOutOfService; } GenerateValue(system, BooleanValue); GenerateValue(system, SByteValue); GenerateValue(system, ByteValue); GenerateValue(system, Int16Value); GenerateValue(system, UInt16Value); GenerateValue(system, Int32Value); GenerateValue(system, UInt32Value); GenerateValue(system, UInt32Value); GenerateValue(system, Int64Value); GenerateValue(system, UInt64Value); GenerateValue(system, FloatValue); GenerateValue(system, DoubleValue); GenerateValue(system, StringValue); GenerateValue(system, DateTimeValue); GenerateValue(system, GuidValue); GenerateValue(system, ByteStringValue); GenerateValue(system, XmlElementValue); GenerateValue(system, NodeIdValue); GenerateValue(system, ExpandedNodeIdValue); GenerateValue(system, QualifiedNameValue); GenerateValue(system, LocalizedTextValue); GenerateValue(system, StatusCodeValue); GenerateValue(system, VariantValue); GenerateValue(system, EnumerationValue); GenerateValue(system, StructureValue); GenerateValue(system, NumberValue); GenerateValue(system, IntegerValue); GenerateValue(system, UIntegerValue); return base.OnGenerateValues(context, method, objectId, count); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/TestData/TestDataNodeManager.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace TestData { using Opc.Ua; using Opc.Ua.Server; using System; using System.Collections.Generic; using System.Reflection; using System.Threading; /// /// A node manager for a variety of test data. /// public class TestDataNodeManager : CustomNodeManager2, ITestDataSystemCallback { /// /// Initializes the node manager. /// /// /// public TestDataNodeManager(IServerInternal server, ApplicationConfiguration configuration) : base(server, configuration) { // update the namespaces. NamespaceUris = new List { Namespaces.TestData, Namespaces.TestData + "/Instance" }; // get the configuration for the node manager. // use suitable defaults if no configuration exists. _configuration = configuration.ParseExtension() ?? new TestDataNodeManagerConfiguration(); _lastUsedId = _configuration.NextUnusedId - 1; // create the object used to access the test system. _system = new TestDataSystem(this, server.NamespaceUris, server.ServerUris); // update the default context. SystemContext.SystemHandle = _system; } protected override void Dispose(bool disposing) { if (disposing) { if (_systemStatusTimer != null) { _systemStatusTimer.Dispose(); _systemStatusTimer = null; } if (_system != null) { _system.Dispose(); _system = null; } } base.Dispose(disposing); } /// /// Updates the variable after receiving a notification that it has changed in the underlying system. /// /// /// /// /// public void OnDataChange(BaseVariableState variable, object value, StatusCode statusCode, DateTime timestamp) { lock (Lock) { variable.Value = value; variable.StatusCode = statusCode; variable.Timestamp = timestamp; // notifies any monitored items that the value has changed. variable.ClearChangeMasks(SystemContext, false); } } /// /// Creates the NodeId for the specified node. /// /// The context. /// The node. /// The new NodeId. public override NodeId New(ISystemContext context, NodeState node) { var id = Utils.IncrementIdentifier(ref _lastUsedId); return new NodeId(id, _namespaceIndex); } /// /// Does any initialization required before the address space can be used. /// /// /// /// The externalReferences is an out parameter that allows the node manager to link to nodes /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and /// should have a reference to the root folder node(s) exposed by this node manager. /// public override void CreateAddressSpace(IDictionary> externalReferences) { lock (Lock) { // ensure the namespace used by the node manager is in the server's namespace table. _typeNamespaceIndex = Server.NamespaceUris.GetIndexOrAppend(Namespaces.TestData); _namespaceIndex = Server.NamespaceUris.GetIndexOrAppend(Namespaces.TestData + "/Instance"); base.CreateAddressSpace(externalReferences); // start monitoring the system status. _systemStatusCondition = (TestSystemConditionState)FindPredefinedNode( new NodeId(Objects.Data_Conditions_SystemStatus, _typeNamespaceIndex), typeof(TestSystemConditionState)); if (_systemStatusCondition != null) { _systemStatusTimer = new Timer(OnCheckSystemStatus, null, 5000, 5000); _systemStatusCondition.Retain.Value = true; } // link all conditions to the conditions folder. var conditionsFolder = FindPredefinedNode( new NodeId(Objects.Data_Conditions, _typeNamespaceIndex), typeof(NodeState)); foreach (var node in PredefinedNodes.Values) { if (node is ConditionState condition && !ReferenceEquals(condition.Parent, conditionsFolder)) { condition.AddNotifier(SystemContext, null, true, conditionsFolder); conditionsFolder.AddNotifier(SystemContext, null, false, condition); } } // enable history for all numeric scalar values. var scalarValues = (ScalarValueObjectState)FindPredefinedNode( new NodeId(Objects.Data_Dynamic_Scalar, _typeNamespaceIndex), typeof(ScalarValueObjectState)); scalarValues.Int32Value.Historizing = true; scalarValues.Int32Value.AccessLevel = (byte)(scalarValues.Int32Value.AccessLevel | AccessLevels.HistoryRead); _system.EnableHistoryArchiving(scalarValues.Int32Value); } } /// /// Loads a node set from a file or resource and addes them to the set of predefined nodes. /// /// protected override NodeStateCollection LoadPredefinedNodes(ISystemContext context) { var type = GetType().GetTypeInfo(); var predefinedNodes = new NodeStateCollection(); predefinedNodes.LoadFromBinaryResource(context, $"{type.Assembly.GetName().Name}.Generated.{type.Namespace}.Design.{type.Namespace}.PredefinedNodes.uanodes", type.Assembly, true); return predefinedNodes; } /// /// Replaces the generic node with a node specific to the model. /// /// /// protected override NodeState AddBehaviourToPredefinedNode(ISystemContext context, NodeState predefinedNode) { if (predefinedNode is not BaseObjectState passiveNode) { return predefinedNode; } var typeId = passiveNode.TypeDefinitionId; if (!IsNodeIdInNamespace(typeId) || typeId.IdType != IdType.Numeric) { return predefinedNode; } switch ((uint)typeId.Identifier) { case ObjectTypes.TestSystemConditionType: { if (passiveNode is TestSystemConditionState) { break; } var activeNode = new TestSystemConditionState(passiveNode.Parent); activeNode.Create(context, passiveNode); passiveNode.Parent?.ReplaceChild(context, activeNode); return activeNode; } case ObjectTypes.ScalarValueObjectType: { if (passiveNode is ScalarValueObjectState) { break; } var activeNode = new ScalarValueObjectState(passiveNode.Parent); activeNode.Create(context, passiveNode); passiveNode.Parent?.ReplaceChild(context, activeNode); return activeNode; } case ObjectTypes.AnalogScalarValueObjectType: { if (passiveNode is AnalogScalarValueObjectState) { break; } var activeNode = new AnalogScalarValueObjectState(passiveNode.Parent); activeNode.Create(context, passiveNode); passiveNode.Parent?.ReplaceChild(context, activeNode); return activeNode; } case ObjectTypes.ArrayValueObjectType: { if (passiveNode is ArrayValueObjectState) { break; } var activeNode = new ArrayValueObjectState(passiveNode.Parent); activeNode.Create(context, passiveNode); passiveNode.Parent?.ReplaceChild(context, activeNode); return activeNode; } case ObjectTypes.AnalogArrayValueObjectType: { if (passiveNode is AnalogArrayValueObjectState) { break; } var activeNode = new AnalogArrayValueObjectState(passiveNode.Parent); activeNode.Create(context, passiveNode); passiveNode.Parent?.ReplaceChild(context, activeNode); return activeNode; } case ObjectTypes.UserScalarValueObjectType: { if (passiveNode is UserScalarValueObjectState) { break; } var activeNode = new UserScalarValueObjectState(passiveNode.Parent); activeNode.Create(context, passiveNode); passiveNode.Parent?.ReplaceChild(context, activeNode); return activeNode; } case ObjectTypes.UserArrayValueObjectType: { if (passiveNode is UserArrayValueObjectState) { break; } var activeNode = new UserArrayValueObjectState(passiveNode.Parent); activeNode.Create(context, passiveNode); passiveNode.Parent?.ReplaceChild(context, activeNode); return activeNode; } case ObjectTypes.MethodTestType: { if (passiveNode is MethodTestState) { break; } var activeNode = new MethodTestState(passiveNode.Parent); activeNode.Create(context, passiveNode); passiveNode.Parent?.ReplaceChild(context, activeNode); return activeNode; } } return predefinedNode; } /// /// Returns true if the system must be scanning to provide updates for the monitored item. /// /// /// private static bool SystemScanRequired(MonitoredNode2 monitoredNode, ISampledDataChangeMonitoredItem monitoredItem) { // ingore other types of monitored items. if (monitoredItem == null) { return false; } // only care about variables. if (monitoredNode.Node is not BaseDataVariableState source) { return false; } // check for variables that need to be scanned. if (monitoredItem.AttributeId == Attributes.Value && source.Parent is TestDataObjectState test && test.SimulationActive.Value) { return true; } return false; } /// /// Called after creating a MonitoredItem2. /// /// The context. /// The handle for the node. /// The monitored item. protected override void OnMonitoredItemCreated( ServerSystemContext context, NodeHandle handle, ISampledDataChangeMonitoredItem monitoredItem) { if (SystemScanRequired(handle.MonitoredNode, monitoredItem) && monitoredItem.MonitoringMode != MonitoringMode.Disabled) { _system.StartMonitoringValue( monitoredItem.Id, monitoredItem.SamplingInterval, handle.Node as BaseVariableState); } } /// /// Called after modifying a MonitoredItem2. /// /// The context. /// The handle for the node. /// The monitored item. protected override void OnMonitoredItemModified( ServerSystemContext context, NodeHandle handle, ISampledDataChangeMonitoredItem monitoredItem) { if (SystemScanRequired(handle.MonitoredNode, monitoredItem) && monitoredItem.MonitoringMode != MonitoringMode.Disabled) { var source = handle.Node as BaseVariableState; _system.StopMonitoringValue(monitoredItem.Id); _system.StartMonitoringValue(monitoredItem.Id, monitoredItem.SamplingInterval, source); } } /// /// Called after deleting a MonitoredItem2. /// /// The context. /// The handle for the node. /// The monitored item. protected override void OnMonitoredItemDeleted( ServerSystemContext context, NodeHandle handle, ISampledDataChangeMonitoredItem monitoredItem) { // check for variables that need to be scanned. if (SystemScanRequired(handle.MonitoredNode, monitoredItem)) { _system.StopMonitoringValue(monitoredItem.Id); } } /// /// Called after changing the MonitoringMode for a MonitoredItem2. /// /// The context. /// The handle for the node. /// The monitored item. /// The previous monitoring mode. /// The current monitoring mode. protected override void OnMonitoringModeChanged( ServerSystemContext context, NodeHandle handle, ISampledDataChangeMonitoredItem monitoredItem, MonitoringMode previousMode, MonitoringMode monitoringMode) { if (SystemScanRequired(handle.MonitoredNode, monitoredItem)) { var source = handle.Node as BaseVariableState; if (previousMode != MonitoringMode.Disabled && monitoredItem.MonitoringMode == MonitoringMode.Disabled) { _system.StopMonitoringValue(monitoredItem.Id); } if (previousMode == MonitoringMode.Disabled && monitoredItem.MonitoringMode != MonitoringMode.Disabled) { _system.StartMonitoringValue(monitoredItem.Id, monitoredItem.SamplingInterval, source); } } } /// /// Peridically checks the system state. /// /// private void OnCheckSystemStatus(object state) { #if CONDITION_SAMPLES lock (Lock) { try { // create the dialog. if (_dialog == null) { _dialog = new DialogConditionState(null); CreateNode( SystemContext, ExpandedNodeId.ToNodeId(ObjectIds.Data_Conditions, SystemContext.NamespaceUris), ReferenceTypeIds.HasComponent, new QualifiedName("ResetSystemDialog", _namespaceIndex), _dialog); _dialog.OnAfterResponse = OnDialogComplete; } StatusCode systemStatus = _system.SystemStatus; _systemStatusCondition.UpdateStatus(systemStatus); // cycle through different status codes in order to simulate a real system. if (StatusCode.IsGood(systemStatus)) { _systemStatusCondition.UpdateSeverity((ushort)EventSeverity.Low); _system.SystemStatus = StatusCodes.Uncertain; } else if (StatusCode.IsUncertain(systemStatus)) { _systemStatusCondition.UpdateSeverity((ushort)EventSeverity.Medium); _system.SystemStatus = StatusCodes.Bad; } else { _systemStatusCondition.UpdateSeverity((ushort)EventSeverity.High); _system.SystemStatus = StatusCodes.Good; } // request a reset if status is bad. if (StatusCode.IsBad(systemStatus)) { _dialog.RequestResponse( SystemContext, "Reset the test system?", (uint)(int)(DialogConditionChoice.Ok | DialogConditionChoice.Cancel), (ushort)EventSeverity.MediumHigh); } // report the event. TranslationInfo info = new TranslationInfo( "TestSystemStatusChange", "en-US", "The TestSystem status is now {0}.", systemStatus); _systemStatusCondition.ReportConditionChange( SystemContext, null, new LocalizedText(info), false); } catch (Exception e) { Utils.Trace(e, "Unexpected error monitoring system status."); } } #endif } #if CONDITION_SAMPLES /// /// Handles a user response to a dialog. /// private ServiceResult OnDialogComplete( ISystemContext context, DialogConditionState dialog, DialogConditionChoice response) { if (_dialog != null) { DeleteNode(SystemContext, _dialog.NodeId); _dialog = null; } return ServiceResult.Good; } #endif private readonly TestDataNodeManagerConfiguration _configuration; private ushort _namespaceIndex; private ushort _typeNamespaceIndex; private TestDataSystem _system; private long _lastUsedId; private Timer _systemStatusTimer; private TestSystemConditionState _systemStatusCondition; #if CONDITION_SAMPLES private DialogConditionState _dialog; #endif } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/TestData/TestDataNodeManagerConfiguration.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace TestData { using System.Runtime.Serialization; /// /// Stores the configuration the test node manager /// [DataContract(Namespace = Namespaces.TestData)] public class TestDataNodeManagerConfiguration { /// /// The default constructor. /// public TestDataNodeManagerConfiguration() { Initialize(); } /// /// Initializes the object during deserialization. /// /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { SaveFilePath = null; MaxQueueSize = 100; } /// /// The path to the file that stores state of the node manager. /// [DataMember(Order = 1)] public string SaveFilePath { get; set; } /// /// The maximum length for a monitored item sampling queue. /// [DataMember(Order = 2)] public uint MaxQueueSize { get; set; } /// /// The next unused value that can be assigned to new nodes. /// [DataMember(Order = 3)] public uint NextUnusedId { get; set; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/TestData/TestDataObjectState.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace TestData { using Opc.Ua; using System; public partial class TestDataObjectState { /// /// Initializes the object as a collection of counters which change value on read. /// /// /// protected override void OnAfterCreate(ISystemContext context, NodeState node) { base.OnAfterCreate(context, node); GenerateValues.OnCall = OnGenerateValues; } /// /// Initialzies the variable as a counter. /// /// /// /// protected void InitializeVariable(ISystemContext context, BaseVariableState variable, uint numericId) { variable.NumericId = numericId; // provide an implementation that produces a random value on each read. if (SimulationActive.Value) { variable.OnReadValue = DoDeviceRead; } // set a valid initial value. if (context.SystemHandle is TestDataSystem system) { GenerateValue(system, variable); } // allow writes if the simulation is not active. if (!SimulationActive.Value) { variable.AccessLevel = variable.UserAccessLevel = AccessLevels.CurrentReadOrWrite; } // set the EU range. if (variable.FindChild(context, Opc.Ua.BrowseNames.EURange) is BaseVariableState euRange) { if (context.TypeTable.IsTypeOf(variable.DataType, Opc.Ua.DataTypeIds.UInteger)) { euRange.Value = new Opc.Ua.Range(250, 50); } else { euRange.Value = new Opc.Ua.Range(100, -100); } } variable.OnSimpleWriteValue = OnWriteAnalogValue; } /// /// Validates a written value. /// /// /// /// public ServiceResult OnWriteAnalogValue( ISystemContext context, NodeState node, ref object value) { if (node.FindChild(context, Opc.Ua.BrowseNames.EURange) is not BaseVariableState euRange) { return ServiceResult.Good; } if (euRange.Value is not Opc.Ua.Range range) { return ServiceResult.Good; } if (value is Array array) { for (var ii = 0; ii < array.Length; ii++) { var element = array.GetValue(ii); if (typeof(Variant).IsInstanceOfType(element)) { element = ((Variant)element).Value; } var elementNumber = Convert.ToDouble(element); if (elementNumber > range.High || elementNumber < range.Low) { return StatusCodes.BadOutOfRange; } } return ServiceResult.Good; } var number = Convert.ToDouble(value); if (number > range.High || number < range.Low) { return StatusCodes.BadOutOfRange; } return ServiceResult.Good; } /// /// Generates a new value for the variable. /// /// /// protected void GenerateValue(TestDataSystem system, BaseVariableState variable) { variable.Value = system.ReadValue(variable); variable.Timestamp = DateTime.UtcNow; variable.StatusCode = StatusCodes.Good; } /// /// Handles the generate values method. /// /// /// /// /// protected virtual ServiceResult OnGenerateValues( ISystemContext context, MethodState method, NodeId objectId, uint count) { ClearChangeMasks(context, true); if (AreEventsMonitored) { var e = new GenerateValuesEventState(null); var message = new TranslationInfo( "GenerateValuesEventType", "en-US", "New values generated for test source '{0}'.", DisplayName); e.Initialize( context, this, EventSeverity.MediumLow, new LocalizedText(message)); e.Iterations = new PropertyState(e) { Value = count }; e.NewValueCount = new PropertyState(e) { Value = 10 }; ReportEvent(context, e); } #if CONDITION_SAMPLES this.CycleComplete.RequestAcknowledgement(context, (ushort)EventSeverity.Low); #endif return ServiceResult.Good; } /// /// Generates a new value each time the value is read. /// /// /// /// /// /// /// /// private ServiceResult DoDeviceRead( ISystemContext context, NodeState node, NumericRange indexRange, QualifiedName dataEncoding, ref object value, ref StatusCode statusCode, ref DateTime timestamp) { if (node is not BaseVariableState variable) { return ServiceResult.Good; } if (!SimulationActive.Value) { return ServiceResult.Good; } if (context.SystemHandle is not TestDataSystem system) { return StatusCodes.BadOutOfService; } try { value = system.ReadValue(variable); statusCode = StatusCodes.Good; timestamp = DateTime.UtcNow; var error = BaseVariableState.ApplyIndexRangeAndDataEncoding( context, indexRange, dataEncoding, ref value); if (ServiceResult.IsBad(error)) { statusCode = error.StatusCode; } return ServiceResult.Good; } catch (Exception e) { return new ServiceResult(e); } } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/TestData/TestDataServer.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace TestData { using Opc.Ua; using Opc.Ua.Server; /// public class TestDataServer : INodeManagerFactory { /// public StringCollection NamespacesUris { get { return [ Namespaces.TestData, Namespaces.TestData + "/Instance" ]; } } /// public INodeManager Create(IServerInternal server, ApplicationConfiguration configuration) { return new TestDataNodeManager(server, configuration); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/TestData/TestDataSystem.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace TestData { using Opc.Ua; using System; using System.Collections.Generic; using System.Threading; using System.Xml; public interface ITestDataSystemCallback { void OnDataChange( BaseVariableState variable, object value, StatusCode statusCode, DateTime timestamp); } public class TestDataSystem : IDisposable { public TestDataSystem(ITestDataSystemCallback callback, NamespaceTable namespaceUris, StringTable serverUris) { _callback = callback; _minimumSamplingInterval = int.MaxValue; _monitoredNodes = []; _generator = new Opc.Ua.Test.TestDataGenerator() { NamespaceUris = namespaceUris, ServerUris = serverUris }; _historyArchive = new HistoryArchive(); } public void Dispose() { if (_historyArchive != null) { _historyArchive.Dispose(); _historyArchive = null; } if (_timer != null) { _timer.Dispose(); _timer = null; } } /// /// The number of nodes being monitored. /// public int MonitoredNodeCount { get { lock (_lock) { if (_monitoredNodes == null) { return 0; } return _monitoredNodes.Count; } } } /// /// Creates an archive for the variable. /// /// public void EnableHistoryArchiving(BaseVariableState variable) { if (variable == null) { return; } if (variable.ValueRank == ValueRanks.Scalar) { _historyArchive.CreateRecord(variable.NodeId, TypeInfo.GetBuiltInType(variable.DataType)); } } /// /// Returns a new value for the variable. /// /// public object ReadValue(BaseVariableState variable) { lock (_lock) { switch (variable.NumericId) { case Variables.ScalarValueObjectType_BooleanValue: case Variables.UserScalarValueObjectType_BooleanValue: return _generator.GetRandom(); case Variables.ScalarValueObjectType_SByteValue: case Variables.UserScalarValueObjectType_SByteValue: return _generator.GetRandom(); case Variables.AnalogScalarValueObjectType_SByteValue: return (sbyte)(((int)(_generator.GetRandom() % 201)) - 100); case Variables.ScalarValueObjectType_ByteValue: case Variables.UserScalarValueObjectType_ByteValue: return _generator.GetRandom(); case Variables.AnalogScalarValueObjectType_ByteValue: return (byte)((_generator.GetRandom() % 201) + 50); case Variables.ScalarValueObjectType_Int16Value: case Variables.UserScalarValueObjectType_Int16Value: return _generator.GetRandom(); case Variables.AnalogScalarValueObjectType_Int16Value: return (short)(((int)(_generator.GetRandom() % 201)) - 100); case Variables.ScalarValueObjectType_UInt16Value: case Variables.UserScalarValueObjectType_UInt16Value: return _generator.GetRandom(); case Variables.AnalogScalarValueObjectType_UInt16Value: return (ushort)((_generator.GetRandom() % 201) + 50); case Variables.ScalarValueObjectType_Int32Value: case Variables.UserScalarValueObjectType_Int32Value: return _generator.GetRandom(); case Variables.AnalogScalarValueObjectType_Int32Value: case Variables.AnalogScalarValueObjectType_IntegerValue: return ((int)(_generator.GetRandom() % 201)) - 100; case Variables.ScalarValueObjectType_UInt32Value: case Variables.UserScalarValueObjectType_UInt32Value: return _generator.GetRandom(); case Variables.AnalogScalarValueObjectType_UInt32Value: case Variables.AnalogScalarValueObjectType_UIntegerValue: return (_generator.GetRandom() % 201) + 50; case Variables.ScalarValueObjectType_Int64Value: case Variables.UserScalarValueObjectType_Int64Value: return _generator.GetRandom(); case Variables.AnalogScalarValueObjectType_Int64Value: return (long)(((int)(_generator.GetRandom() % 201)) - 100); case Variables.ScalarValueObjectType_UInt64Value: case Variables.UserScalarValueObjectType_UInt64Value: return _generator.GetRandom(); case Variables.AnalogScalarValueObjectType_UInt64Value: return (ulong)((_generator.GetRandom() % 201) + 50); case Variables.ScalarValueObjectType_FloatValue: case Variables.UserScalarValueObjectType_FloatValue: return _generator.GetRandom(); case Variables.AnalogScalarValueObjectType_FloatValue: return (float)(((int)(_generator.GetRandom() % 201)) - 100); case Variables.ScalarValueObjectType_DoubleValue: case Variables.UserScalarValueObjectType_DoubleValue: return _generator.GetRandom(); case Variables.AnalogScalarValueObjectType_DoubleValue: case Variables.AnalogScalarValueObjectType_NumberValue: return (double)(((int)(_generator.GetRandom() % 201)) - 100); case Variables.ScalarValueObjectType_StringValue: case Variables.UserScalarValueObjectType_StringValue: return _generator.GetRandom(); case Variables.ScalarValueObjectType_DateTimeValue: case Variables.UserScalarValueObjectType_DateTimeValue: return _generator.GetRandom(); case Variables.ScalarValueObjectType_GuidValue: case Variables.UserScalarValueObjectType_GuidValue: return _generator.GetRandom(); case Variables.ScalarValueObjectType_ByteStringValue: case Variables.UserScalarValueObjectType_ByteStringValue: return _generator.GetRandom(); case Variables.ScalarValueObjectType_XmlElementValue: case Variables.UserScalarValueObjectType_XmlElementValue: return _generator.GetRandom(); case Variables.ScalarValueObjectType_NodeIdValue: case Variables.UserScalarValueObjectType_NodeIdValue: return _generator.GetRandom(); case Variables.ScalarValueObjectType_ExpandedNodeIdValue: case Variables.UserScalarValueObjectType_ExpandedNodeIdValue: return _generator.GetRandom(); case Variables.ScalarValueObjectType_QualifiedNameValue: case Variables.UserScalarValueObjectType_QualifiedNameValue: return _generator.GetRandom(); case Variables.ScalarValueObjectType_LocalizedTextValue: case Variables.UserScalarValueObjectType_LocalizedTextValue: return _generator.GetRandom(); case Variables.ScalarValueObjectType_StatusCodeValue: case Variables.UserScalarValueObjectType_StatusCodeValue: return _generator.GetRandom(); case Variables.ScalarValueObjectType_VariantValue: case Variables.UserScalarValueObjectType_VariantValue: return _generator.GetRandomVariant().Value; case Variables.ScalarValueObjectType_StructureValue: return GetRandomStructure(); case Variables.ScalarValueObjectType_EnumerationValue: return _generator.GetRandom(); case Variables.ScalarValueObjectType_NumberValue: return _generator.GetRandom(BuiltInType.Number); case Variables.ScalarValueObjectType_IntegerValue: return _generator.GetRandom(BuiltInType.Integer); case Variables.ScalarValueObjectType_UIntegerValue: return _generator.GetRandom(BuiltInType.UInteger); case Variables.ArrayValueObjectType_BooleanValue: case Variables.UserArrayValueObjectType_BooleanValue: return _generator.GetRandomArray(); case Variables.ArrayValueObjectType_SByteValue: case Variables.UserArrayValueObjectType_SByteValue: return _generator.GetRandomArray(); case Variables.ArrayValueObjectType_ByteValue: case Variables.UserArrayValueObjectType_ByteValue: return _generator.GetRandomArray(); case Variables.ArrayValueObjectType_Int16Value: case Variables.UserArrayValueObjectType_Int16Value: return _generator.GetRandomArray(); case Variables.ArrayValueObjectType_UInt16Value: case Variables.UserArrayValueObjectType_UInt16Value: return _generator.GetRandomArray(); case Variables.ArrayValueObjectType_Int32Value: case Variables.UserArrayValueObjectType_Int32Value: return _generator.GetRandomArray(); case Variables.ArrayValueObjectType_UInt32Value: case Variables.UserArrayValueObjectType_UInt32Value: return _generator.GetRandomArray(); case Variables.ArrayValueObjectType_Int64Value: case Variables.UserArrayValueObjectType_Int64Value: return _generator.GetRandomArray(); case Variables.ArrayValueObjectType_UInt64Value: case Variables.UserArrayValueObjectType_UInt64Value: return _generator.GetRandomArray(); case Variables.ArrayValueObjectType_FloatValue: case Variables.UserArrayValueObjectType_FloatValue: return _generator.GetRandomArray(); case Variables.ArrayValueObjectType_DoubleValue: case Variables.UserArrayValueObjectType_DoubleValue: return _generator.GetRandomArray(); case Variables.ArrayValueObjectType_StringValue: case Variables.UserArrayValueObjectType_StringValue: return _generator.GetRandomArray(); case Variables.ArrayValueObjectType_DateTimeValue: case Variables.UserArrayValueObjectType_DateTimeValue: return _generator.GetRandomArray(); case Variables.ArrayValueObjectType_GuidValue: case Variables.UserArrayValueObjectType_GuidValue: return _generator.GetRandomArray(); case Variables.ArrayValueObjectType_ByteStringValue: case Variables.UserArrayValueObjectType_ByteStringValue: return _generator.GetRandomArray(); case Variables.ArrayValueObjectType_XmlElementValue: case Variables.UserArrayValueObjectType_XmlElementValue: return _generator.GetRandomArray(); case Variables.ArrayValueObjectType_NodeIdValue: case Variables.UserArrayValueObjectType_NodeIdValue: return _generator.GetRandomArray(); case Variables.ArrayValueObjectType_ExpandedNodeIdValue: case Variables.UserArrayValueObjectType_ExpandedNodeIdValue: return _generator.GetRandomArray(); case Variables.ArrayValueObjectType_QualifiedNameValue: case Variables.UserArrayValueObjectType_QualifiedNameValue: return _generator.GetRandomArray(); case Variables.ArrayValueObjectType_LocalizedTextValue: case Variables.UserArrayValueObjectType_LocalizedTextValue: return _generator.GetRandomArray(); case Variables.ArrayValueObjectType_StatusCodeValue: case Variables.UserArrayValueObjectType_StatusCodeValue: return _generator.GetRandomArray(); case Variables.ArrayValueObjectType_VariantValue: case Variables.UserArrayValueObjectType_VariantValue: return _generator.GetRandomArray(); case Variables.ArrayValueObjectType_EnumerationValue: return _generator.GetRandomArray(); case Variables.ArrayValueObjectType_NumberValue: return _generator.GetRandomArray(BuiltInType.Number, 100, false); case Variables.ArrayValueObjectType_IntegerValue: return _generator.GetRandomArray(BuiltInType.Integer, 100, false); case Variables.ArrayValueObjectType_UIntegerValue: return _generator.GetRandomArray(BuiltInType.UInteger, 100, false); case Variables.AnalogArrayValueObjectType_SByteValue: { var values = _generator.GetRandomArray(); for (var i = 0; i < values.Length; i++) { values[i] = (sbyte)(((int)(_generator.GetRandom() % 201)) - 100); } return values; } case Variables.AnalogArrayValueObjectType_ByteValue: { var values = _generator.GetRandomArray(); for (var i = 0; i < values.Length; i++) { values[i] = (byte)((_generator.GetRandom() % 201) + 50); } return values; } case Variables.AnalogArrayValueObjectType_Int16Value: { var values = _generator.GetRandomArray(); for (var i = 0; i < values.Length; i++) { values[i] = (short)(((int)(_generator.GetRandom() % 201)) - 100); } return values; } case Variables.AnalogArrayValueObjectType_UInt16Value: { var values = _generator.GetRandomArray(); for (var i = 0; i < values.Length; i++) { values[i] = (ushort)((_generator.GetRandom() % 201) + 50); } return values; } case Variables.AnalogArrayValueObjectType_Int32Value: case Variables.AnalogArrayValueObjectType_IntegerValue: { var values = _generator.GetRandomArray(); for (var i = 0; i < values.Length; i++) { values[i] = ((int)(_generator.GetRandom() % 201)) - 100; } return values; } case Variables.AnalogArrayValueObjectType_UInt32Value: case Variables.AnalogArrayValueObjectType_UIntegerValue: { var values = _generator.GetRandomArray(); for (var i = 0; i < values.Length; i++) { values[i] = (_generator.GetRandom() % 201) + 50; } return values; } case Variables.AnalogArrayValueObjectType_Int64Value: { var values = _generator.GetRandomArray(); for (var i = 0; i < values.Length; i++) { values[i] = ((int)(_generator.GetRandom() % 201)) - 100; } return values; } case Variables.AnalogArrayValueObjectType_UInt64Value: { var values = _generator.GetRandomArray(); for (var i = 0; i < values.Length; i++) { values[i] = (_generator.GetRandom() % 201) + 50; } return values; } case Variables.AnalogArrayValueObjectType_FloatValue: { var values = _generator.GetRandomArray(); for (var i = 0; i < values.Length; i++) { values[i] = ((int)(_generator.GetRandom() % 201)) - 100; } return values; } case Variables.AnalogArrayValueObjectType_DoubleValue: case Variables.AnalogArrayValueObjectType_NumberValue: { var values = _generator.GetRandomArray(); for (var i = 0; i < values.Length; i++) { values[i] = ((int)(_generator.GetRandom() % 201)) - 100; } return values; } case Variables.ArrayValueObjectType_StructureValue: { var values = _generator.GetRandomArray(10); for (var i = 0; values != null && i < values.Length; i++) { values[i] = GetRandomStructure(); } return values; } } return null; } } /// /// Returns a random structure. /// private ExtensionObject GetRandomStructure() { if (_generator.GetRandomBoolean()) { var scalar = new ScalarValueDataType { BooleanValue = _generator.GetRandom(), SByteValue = _generator.GetRandom(), ByteValue = _generator.GetRandom(), Int16Value = _generator.GetRandom(), UInt16Value = _generator.GetRandom(), Int32Value = _generator.GetRandom(), UInt32Value = _generator.GetRandom(), Int64Value = _generator.GetRandom(), UInt64Value = _generator.GetRandom(), FloatValue = _generator.GetRandom(), DoubleValue = _generator.GetRandom(), StringValue = _generator.GetRandom(), DateTimeValue = _generator.GetRandom(), GuidValue = _generator.GetRandom(), ByteStringValue = _generator.GetRandom(), XmlElementValue = _generator.GetRandom(), NodeIdValue = _generator.GetRandom(), ExpandedNodeIdValue = _generator.GetRandom(), QualifiedNameValue = _generator.GetRandom(), LocalizedTextValue = _generator.GetRandom(), StatusCodeValue = _generator.GetRandom(), VariantValue = _generator.GetRandomVariant() }; return new ExtensionObject(scalar); } var array = new ArrayValueDataType { BooleanValue = _generator.GetRandomArray(10), SByteValue = _generator.GetRandomArray(10), ByteValue = _generator.GetRandomArray(10), Int16Value = _generator.GetRandomArray(10), UInt16Value = _generator.GetRandomArray(10), Int32Value = _generator.GetRandomArray(10), UInt32Value = _generator.GetRandomArray(10), Int64Value = _generator.GetRandomArray(10), UInt64Value = _generator.GetRandomArray(10), FloatValue = _generator.GetRandomArray(10), DoubleValue = _generator.GetRandomArray(10), StringValue = _generator.GetRandomArray(10), DateTimeValue = _generator.GetRandomArray(10), GuidValue = _generator.GetRandomArray(10), ByteStringValue = _generator.GetRandomArray(10), XmlElementValue = _generator.GetRandomArray(10), NodeIdValue = _generator.GetRandomArray(10), ExpandedNodeIdValue = _generator.GetRandomArray(10), QualifiedNameValue = _generator.GetRandomArray(10), LocalizedTextValue = _generator.GetRandomArray(10), StatusCodeValue = _generator.GetRandomArray(10) }; var values = _generator.GetRandomArray(10); for (var i = 0; values != null && i < values.Length; i++) { array.VariantValue.Add(new Variant(values[i])); } return new ExtensionObject(array.TypeId, array); } public void StartMonitoringValue(uint monitoredItemId, double samplingInterval, BaseVariableState variable) { lock (_lock) { _monitoredNodes ??= []; _monitoredNodes[monitoredItemId] = variable; SetSamplingInterval(samplingInterval); } } public void SetSamplingInterval(double samplingInterval) { lock (_lock) { if (samplingInterval < 0) { // _samplingEvent.Set(); _minimumSamplingInterval = int.MaxValue; if (_timer != null) { _timer.Dispose(); _timer = null; } return; } if (_minimumSamplingInterval > samplingInterval) { _minimumSamplingInterval = (int)samplingInterval; if (_minimumSamplingInterval < 100) { _minimumSamplingInterval = 100; } if (_timer != null) { _timer.Dispose(); _timer = null; } _timer = new Timer(DoSample, null, _minimumSamplingInterval, _minimumSamplingInterval); } } } private void DoSample(object state) { Utils.Trace("DoSample HiRes={0:ss.ffff} Now={1:ss.ffff}", HiResClock.UtcNow, DateTime.UtcNow); var samples = new Queue(); lock (_lock) { if (_monitoredNodes == null) { return; } foreach (var variable in _monitoredNodes.Values) { var sample = new Sample { Variable = variable }; sample.Value = ReadValue(sample.Variable); sample.StatusCode = StatusCodes.Good; sample.Timestamp = DateTime.UtcNow; samples.Enqueue(sample); } } while (samples.Count > 0) { var sample = samples.Dequeue(); _callback.OnDataChange( sample.Variable, sample.Value, sample.StatusCode, sample.Timestamp); } } public void StopMonitoringValue(uint monitoredItemId) { lock (_lock) { if (_monitoredNodes == null) { return; } _monitoredNodes.Remove(monitoredItemId); if (_monitoredNodes.Count == 0) { SetSamplingInterval(-1); } } } private sealed class Sample { public BaseVariableState Variable; public object Value; public StatusCode StatusCode; public DateTime Timestamp; } private readonly Lock _lock = new(); private readonly ITestDataSystemCallback _callback; private readonly Opc.Ua.Test.TestDataGenerator _generator; private int _minimumSamplingInterval; private Dictionary _monitoredNodes; private Timer _timer; private HistoryArchive _historyArchive; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/TestData/TestSystemConditionState.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace TestData { using Opc.Ua; public partial class TestSystemConditionState { /// /// Initializes the object as a collection of counters which change value on read. /// /// /// protected override void OnAfterCreate(ISystemContext context, NodeState node) { base.OnAfterCreate(context, node); MonitoredNodeCount.OnSimpleReadValue = OnReadMonitoredNodeCount; } /// /// Reads the value for the MonitoredNodeCount. /// /// /// /// protected virtual ServiceResult OnReadMonitoredNodeCount( ISystemContext context, NodeState node, ref object value) { if (context.SystemHandle is not TestDataSystem system) { return StatusCodes.BadOutOfService; } value = system.MonitoredNodeCount; return ServiceResult.Good; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/TestData/UserArrayValueObjectState.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace TestData { using Opc.Ua; public partial class UserArrayValueObjectState { /// /// Initializes the object as a collection of counters which change value on read. /// /// /// protected override void OnAfterCreate(ISystemContext context, NodeState node) { base.OnAfterCreate(context, node); InitializeVariable(context, BooleanValue, Variables.UserArrayValueObjectType_BooleanValue); InitializeVariable(context, SByteValue, Variables.UserArrayValueObjectType_SByteValue); InitializeVariable(context, ByteValue, Variables.UserArrayValueObjectType_ByteValue); InitializeVariable(context, Int16Value, Variables.UserArrayValueObjectType_Int16Value); InitializeVariable(context, UInt16Value, Variables.UserArrayValueObjectType_UInt16Value); InitializeVariable(context, Int32Value, Variables.UserArrayValueObjectType_Int32Value); InitializeVariable(context, UInt32Value, Variables.UserArrayValueObjectType_UInt32Value); InitializeVariable(context, Int64Value, Variables.UserArrayValueObjectType_Int64Value); InitializeVariable(context, UInt64Value, Variables.UserArrayValueObjectType_UInt64Value); InitializeVariable(context, FloatValue, Variables.UserArrayValueObjectType_FloatValue); InitializeVariable(context, DoubleValue, Variables.UserArrayValueObjectType_DoubleValue); InitializeVariable(context, StringValue, Variables.UserArrayValueObjectType_StringValue); InitializeVariable(context, DateTimeValue, Variables.UserArrayValueObjectType_DateTimeValue); InitializeVariable(context, GuidValue, Variables.UserArrayValueObjectType_GuidValue); InitializeVariable(context, ByteStringValue, Variables.UserArrayValueObjectType_ByteStringValue); InitializeVariable(context, XmlElementValue, Variables.UserArrayValueObjectType_XmlElementValue); InitializeVariable(context, NodeIdValue, Variables.UserArrayValueObjectType_NodeIdValue); InitializeVariable(context, ExpandedNodeIdValue, Variables.UserArrayValueObjectType_ExpandedNodeIdValue); InitializeVariable(context, QualifiedNameValue, Variables.UserArrayValueObjectType_QualifiedNameValue); InitializeVariable(context, LocalizedTextValue, Variables.UserArrayValueObjectType_LocalizedTextValue); InitializeVariable(context, StatusCodeValue, Variables.UserArrayValueObjectType_StatusCodeValue); InitializeVariable(context, VariantValue, Variables.UserArrayValueObjectType_VariantValue); } /// /// Handles the generate values method. /// /// /// /// /// protected override ServiceResult OnGenerateValues( ISystemContext context, MethodState method, NodeId objectId, uint count) { if (context.SystemHandle is not TestDataSystem system) { return StatusCodes.BadOutOfService; } GenerateValue(system, BooleanValue); GenerateValue(system, SByteValue); GenerateValue(system, ByteValue); GenerateValue(system, Int16Value); GenerateValue(system, UInt16Value); GenerateValue(system, Int32Value); GenerateValue(system, UInt32Value); GenerateValue(system, UInt32Value); GenerateValue(system, Int64Value); GenerateValue(system, UInt64Value); GenerateValue(system, FloatValue); GenerateValue(system, DoubleValue); GenerateValue(system, StringValue); GenerateValue(system, DateTimeValue); GenerateValue(system, GuidValue); GenerateValue(system, ByteStringValue); GenerateValue(system, XmlElementValue); GenerateValue(system, NodeIdValue); GenerateValue(system, ExpandedNodeIdValue); GenerateValue(system, QualifiedNameValue); GenerateValue(system, LocalizedTextValue); GenerateValue(system, StatusCodeValue); GenerateValue(system, VariantValue); return base.OnGenerateValues(context, method, objectId, count); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/TestData/UserScalarValueObjectState.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2016 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace TestData { using Opc.Ua; public partial class UserScalarValueObjectState { /// /// Initializes the object as a collection of counters which change value on read. /// /// /// protected override void OnAfterCreate(ISystemContext context, NodeState node) { base.OnAfterCreate(context, node); InitializeVariable(context, BooleanValue, Variables.UserScalarValueObjectType_BooleanValue); InitializeVariable(context, SByteValue, Variables.UserScalarValueObjectType_SByteValue); InitializeVariable(context, ByteValue, Variables.UserScalarValueObjectType_ByteValue); InitializeVariable(context, Int16Value, Variables.UserScalarValueObjectType_Int16Value); InitializeVariable(context, UInt16Value, Variables.UserScalarValueObjectType_UInt16Value); InitializeVariable(context, Int32Value, Variables.UserScalarValueObjectType_Int32Value); InitializeVariable(context, UInt32Value, Variables.UserScalarValueObjectType_UInt32Value); InitializeVariable(context, Int64Value, Variables.UserScalarValueObjectType_Int64Value); InitializeVariable(context, UInt64Value, Variables.UserScalarValueObjectType_UInt64Value); InitializeVariable(context, FloatValue, Variables.UserScalarValueObjectType_FloatValue); InitializeVariable(context, DoubleValue, Variables.UserScalarValueObjectType_DoubleValue); InitializeVariable(context, StringValue, Variables.UserScalarValueObjectType_StringValue); InitializeVariable(context, DateTimeValue, Variables.UserScalarValueObjectType_DateTimeValue); InitializeVariable(context, GuidValue, Variables.UserScalarValueObjectType_GuidValue); InitializeVariable(context, ByteStringValue, Variables.UserScalarValueObjectType_ByteStringValue); InitializeVariable(context, XmlElementValue, Variables.UserScalarValueObjectType_XmlElementValue); InitializeVariable(context, NodeIdValue, Variables.UserScalarValueObjectType_NodeIdValue); InitializeVariable(context, ExpandedNodeIdValue, Variables.UserScalarValueObjectType_ExpandedNodeIdValue); InitializeVariable(context, QualifiedNameValue, Variables.UserScalarValueObjectType_QualifiedNameValue); InitializeVariable(context, LocalizedTextValue, Variables.UserScalarValueObjectType_LocalizedTextValue); InitializeVariable(context, StatusCodeValue, Variables.UserScalarValueObjectType_StatusCodeValue); InitializeVariable(context, VariantValue, Variables.UserScalarValueObjectType_VariantValue); } /// /// Handles the generate values method. /// /// /// /// /// protected override ServiceResult OnGenerateValues( ISystemContext context, MethodState method, NodeId objectId, uint count) { if (context.SystemHandle is not TestDataSystem system) { return StatusCodes.BadOutOfService; } GenerateValue(system, BooleanValue); GenerateValue(system, SByteValue); GenerateValue(system, ByteValue); GenerateValue(system, Int16Value); GenerateValue(system, UInt16Value); GenerateValue(system, Int32Value); GenerateValue(system, UInt32Value); GenerateValue(system, UInt32Value); GenerateValue(system, Int64Value); GenerateValue(system, UInt64Value); GenerateValue(system, FloatValue); GenerateValue(system, DoubleValue); GenerateValue(system, StringValue); GenerateValue(system, DateTimeValue); GenerateValue(system, GuidValue); GenerateValue(system, ByteStringValue); GenerateValue(system, XmlElementValue); GenerateValue(system, NodeIdValue); GenerateValue(system, ExpandedNodeIdValue); GenerateValue(system, QualifiedNameValue); GenerateValue(system, LocalizedTextValue); GenerateValue(system, StatusCodeValue); GenerateValue(system, VariantValue); return base.OnGenerateValues(context, method, objectId, count); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Utils/DeterministicGuid.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Opc.Ua.Test { using System; public static class DeterministicGuid { public static Guid NewGuid() { return new Guid($"{GetRandHex(4)}-{GetRandHex(2)}-{GetRandHex(2)}-{GetRandHex(2)}-{GetRandHex(6)}"); } private static string GetRandHex(int length) { var hexString = string.Empty; for (var i = 0; i < length; i++) { #pragma warning disable CA5394 // Do not use insecure randomness hexString += $"{Random.Shared.Next(0, 255):x2}"; #pragma warning restore CA5394 // Do not use insecure randomness } return hexString; } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Utils/FastTimer.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Opc.Ua.Test { using System; using System.Diagnostics; using System.Threading; public sealed class FastTimer : ITimer { /// /// Initializes a new instance of the FastTimer class and sets all properties to their default values /// public FastTimer() { } /// /// Initializes a new instance of the FastTimer class and sets all properties to their default values except interval /// /// public FastTimer(double interval) { Interval = interval; } /// /// Property that sets if the timer should restart when an event has been fired /// public bool AutoReset { get; set; } = true; /// /// Is this timer currently running? /// public bool Enabled { get => _isEnabled; set { _isEnabled = value; if (_isEnabled) { Start(); } else { Stop(); } } } /// /// The current interval between triggering of this timer /// public double Interval { get; set; } /// /// The event handler we call when the timer is triggered /// public event EventHandler Elapsed; public void Close() { Enabled = false; } /// /// Starts the timer /// private void Start() { var isRunning = Interlocked.Exchange(ref _isRunning, 1); if (isRunning == 0) { var thread = new Thread(Runner) { Priority = ThreadPriority.Highest }; thread.Start(); } } /// /// Stops the timer /// private void Stop() { Interlocked.Exchange(ref _isRunning, 0); } private void Runner() { double nextTrigger = 0f; var sw = new Stopwatch(); sw.Start(); while (_isRunning == 1) { WaitInterval(sw, ref nextTrigger); if (_isRunning == 1) { Elapsed?.Invoke(this, new FastTimerElapsedEventArgs()); if (!AutoReset) { Interlocked.Exchange(ref _isRunning, 0); Enabled = false; break; } // restarting the timer in every hour to prevent precision problems if (sw.Elapsed.TotalHours >= 1d) { sw.Restart(); nextTrigger = 0f; } } } sw.Stop(); } private void WaitInterval(Stopwatch sw, ref double nextTrigger) { var intervalLocal = Interval; nextTrigger += intervalLocal; while (true) { var elapsed = sw.ElapsedTicks * kTickFrequency; var diff = nextTrigger - elapsed; if (diff <= 0f) { break; } if (diff < 1f) { Thread.SpinWait(10); } else if (diff < 10f) { Thread.SpinWait(100); } else { if (diff >= 16f) { Thread.Sleep(diff >= 100f ? 50 : 1); } else { Thread.SpinWait(1000); Thread.Sleep(0); } // if we have a larger time to wait, we check if the interval has been changed in the meantime var newInterval = Interval; if (intervalLocal != newInterval) { nextTrigger += newInterval - intervalLocal; intervalLocal = newInterval; } } if (_isRunning == 0) { return; } } } public void Dispose() { Interlocked.Exchange(ref _isRunning, 0); } private static readonly float kTickFrequency = 1000f / Stopwatch.Frequency; private bool _isEnabled; private int _isRunning; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Utils/FastTimerElapsedEventArgs.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Opc.Ua.Test { using System; public class FastTimerElapsedEventArgs : EventArgs; } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Utils/ITimer.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Opc.Ua.Test { using System; using Timer = System.Timers.Timer; /// /// An interface expressing the methods from the class /// used in this project. Used for mocking. /// Add methods and properties from to this interface as needed. /// public interface ITimer : IDisposable { bool Enabled { get; set; } bool AutoReset { get; set; } double Interval { get; set; } void Close(); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Utils/TestDataGenerator.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Opc.Ua.Test { using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Text; using System.Xml; /// /// Data generator that generates non null typed data. This is a /// fork of the DataGenerator, but ensuring that the data generated /// is consistent for the use in unit tests. /// public class TestDataGenerator { /// /// Set max array length /// public int MaxArrayLength { get; set; } = 100; /// /// Set max string length /// public int MaxStringLength { get; set; } = 100; /// /// Set min date time value /// public DateTime MinDateTimeValue { get; set; } /// /// Set max date time value /// public DateTime MaxDateTimeValue { get; set; } /// /// Max xml attribute count /// public int MaxXmlAttributeCount { get; set; } = 10; /// /// Max xml element count /// public int MaxXmlElementCount { get; set; } = 10; /// /// Namespace uris /// public NamespaceTable NamespaceUris { get; set; } /// /// Server uris /// public StringTable ServerUris { get; set; } /// /// Frequency of boundary values used /// public int BoundaryValueFrequency { get; set; } = 20; /// /// Create generator /// /// public TestDataGenerator(IRandomSource random = null) { MinDateTimeValue = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc); MaxDateTimeValue = new DateTime(2100, 1, 1, 0, 0, 0, DateTimeKind.Utc); NamespaceUris = new NamespaceTable(); ServerUris = new StringTable(); _random = random ?? new RandomSource(); _boundaryValues = []; for (var i = 0; i < kAvailableBoundaryValues.Length; i++) { _boundaryValues[kAvailableBoundaryValues[i].SystemType.Name] = [.. kAvailableBoundaryValues[i].Values]; } _tokenValues = LoadStringData("Opc.Ua.Types.Utils.LocalizedData.txt"); if (_tokenValues.Count == 0) { _tokenValues = LoadStringData("Opc.Ua.Utils.LocalizedData.txt"); } _availableLocales = new string[_tokenValues.Count]; var num = 0; foreach (var key in _tokenValues.Keys) { _availableLocales[num++] = key; } } /// /// Get random data /// /// /// /// /// /// public object GetRandom(NodeId dataType, int valueRank, IList arrayDimensions, ITypeTable typeTree) { var builtInType = Ua.TypeInfo.GetBuiltInType(dataType, typeTree); int num; switch (valueRank) { case -2: num = (arrayDimensions == null || arrayDimensions.Count == 0) ? GetRandomRange(0, 1) : arrayDimensions.Count; break; case -3: num = GetRandomRange(0, 1); break; case 0: num = (arrayDimensions == null || arrayDimensions.Count == 0) ? GetRandomRange(1, 1) : arrayDimensions.Count; break; case -1: num = 0; break; default: num = valueRank; break; } if (num == 0) { if (builtInType == BuiltInType.Variant) { var builtInType2 = BuiltInType.Variant; while (builtInType2 == BuiltInType.Variant || builtInType2 == BuiltInType.DataValue) { builtInType2 = (BuiltInType)_random.NextInt32(24); } return GetRandomVariant(builtInType2, isArray: false); } return GetRandom(builtInType); } var array = new int[num]; for (var i = 0; i < num; i++) { if (arrayDimensions != null && arrayDimensions.Count > i) { array[i] = (int)arrayDimensions[i]; } while (array[i] == 0) { array[i] = _random.NextInt32(MaxArrayLength); } } var array2 = Ua.TypeInfo.CreateArray(builtInType, array); var length = array2.Length; var array3 = new int[array.Length]; for (var j = 0; j < length; j++) { var num2 = array2.Length; for (var k = 0; k < array3.Length; k++) { num2 /= array[k]; array3[k] = j / num2 % array[k]; } var obj = GetRandom(dataType, -1, null, typeTree); if (obj != null) { if (builtInType == BuiltInType.Guid) { obj = new Uuid((Guid)obj); } array2.SetValue(obj, array3); } } return array2; } /// /// Get random data /// /// /// /// public object GetRandom(BuiltInType expectedType) { switch (expectedType) { case BuiltInType.Boolean: return GetRandomBoolean(); case BuiltInType.SByte: return GetRandomSByte(); case BuiltInType.Byte: return GetRandomByte(); case BuiltInType.Int16: return GetRandomInt16(); case BuiltInType.UInt16: return GetRandomUInt16(); case BuiltInType.Int32: return GetRandomInt32(); case BuiltInType.UInt32: return GetRandomUInt32(); case BuiltInType.Int64: return GetRandomInt64(); case BuiltInType.UInt64: return GetRandomUInt64(); case BuiltInType.Float: return GetRandomFloat(); case BuiltInType.Double: return GetRandomDouble(); case BuiltInType.String: return GetRandomString(); case BuiltInType.DateTime: return GetRandomDateTime(); case BuiltInType.Guid: return GetRandomGuid(); case BuiltInType.ByteString: return GetRandomByteString(); case BuiltInType.XmlElement: return GetRandomXmlElement(); case BuiltInType.NodeId: return GetRandomNodeId(); case BuiltInType.ExpandedNodeId: return GetRandomExpandedNodeId(); case BuiltInType.QualifiedName: return GetRandomQualifiedName(); case BuiltInType.LocalizedText: return GetRandomLocalizedText(); case BuiltInType.StatusCode: return GetRandomStatusCode(); case BuiltInType.Variant: return GetRandomVariant(); case BuiltInType.Enumeration: return GetRandomInt32(); case BuiltInType.ExtensionObject: return GetRandomExtensionObject(); case BuiltInType.Number: { var builtInType = (BuiltInType)(_random.NextInt32(9) + 2); return GetRandomVariant(builtInType, isArray: false); } case BuiltInType.Integer: { var builtInType = (BuiltInType)((_random.NextInt32(3) * 2) + 2); return GetRandomVariant(builtInType, isArray: false); } case BuiltInType.UInteger: { var builtInType = (BuiltInType)((_random.NextInt32(3) * 2) + 3); return GetRandomVariant(builtInType, isArray: false); } case BuiltInType.Null: return null; default: throw new ArgumentException($"Unexpected scalar type {expectedType} passed"); } } /// /// Get random array data /// /// /// /// /// /// public Array GetRandomArray(BuiltInType expectedType, int length, bool fixedLength) { switch (expectedType) { case BuiltInType.Boolean: return GetRandomArray(length, fixedLength); case BuiltInType.SByte: return GetRandomArray(length, fixedLength); case BuiltInType.Byte: return GetRandomArray(length, fixedLength); case BuiltInType.Int16: return GetRandomArray(length, fixedLength); case BuiltInType.UInt16: return GetRandomArray(length, fixedLength); case BuiltInType.Int32: return GetRandomArray(length, fixedLength); case BuiltInType.UInt32: return GetRandomArray(length, fixedLength); case BuiltInType.Int64: return GetRandomArray(length, fixedLength); case BuiltInType.UInt64: return GetRandomArray(length, fixedLength); case BuiltInType.Float: return GetRandomArray(length, fixedLength); case BuiltInType.Double: return GetRandomArray(length, fixedLength); case BuiltInType.String: return GetRandomArray(length, fixedLength); case BuiltInType.DateTime: return GetRandomArray(length, fixedLength); case BuiltInType.Guid: return GetRandomArray(length, fixedLength); case BuiltInType.ByteString: return GetRandomArray(length, fixedLength); case BuiltInType.XmlElement: return GetRandomArray(length, fixedLength); case BuiltInType.NodeId: return GetRandomArray(length, fixedLength); case BuiltInType.ExpandedNodeId: return GetRandomArray(length, fixedLength); case BuiltInType.QualifiedName: return GetRandomArray(length, fixedLength); case BuiltInType.LocalizedText: return GetRandomArray(length, fixedLength); case BuiltInType.StatusCode: return GetRandomArray(length, fixedLength); case BuiltInType.Variant: return GetRandomArray(length, fixedLength); case BuiltInType.Enumeration: return GetRandomArray(length, fixedLength); case BuiltInType.ExtensionObject: return GetRandomArray(length, fixedLength); case BuiltInType.Number: { var builtInType3 = (BuiltInType)(_random.NextInt32(9) + 2); return GetRandomArrayInVariant(builtInType3, length, fixedLength); } case BuiltInType.Integer: { var builtInType2 = (BuiltInType)((_random.NextInt32(3) * 2) + 2); return GetRandomArrayInVariant(builtInType2, length, fixedLength); } case BuiltInType.UInteger: { var builtInType = (BuiltInType)((_random.NextInt32(3) * 2) + 3); return GetRandomArrayInVariant(builtInType, length, fixedLength); } case BuiltInType.Null: return null; default: throw new ArgumentException($"Unexpected array type {expectedType} passed"); } } /// /// Get random /// /// /// public T GetRandom() { if (UseBoundaryValue()) { var boundaryValue = GetBoundaryValue(typeof(T)); if (boundaryValue != null) { return (T)boundaryValue; } } return (T)GetRandom(typeof(T)); } /// /// Get random array /// /// /// /// /// /// public T[] GetRandomArray(int length = 100, bool fixedLength = false) { if (length < 0) { throw new ArgumentOutOfRangeException(nameof(length), $"Length is negative {length}"); } if (!fixedLength) { length = _random.NextInt32(length); } var array = new T[length]; for (var i = 0; i < array.Length; i++) { object obj = null; do { if (UseBoundaryValue()) { obj = GetBoundaryValue(typeof(T)); } obj ??= GetRandom(); } while (obj == null); array[i] = (T)obj; } return array; } /// /// Random boolean /// /// public bool GetRandomBoolean() { return _random.NextInt32(1) != 0; } /// /// Random signed byte /// /// public sbyte GetRandomSByte() { var num = _random.NextInt32(255); if (num > 127) { return (sbyte)(-128 + (num - 127) - 1); } return (sbyte)num; } /// /// Random byte /// /// public byte GetRandomByte() { return (byte)_random.NextInt32(255); } /// /// Random short /// /// public short GetRandomInt16() { var array = new byte[2]; _random.NextBytes(array, 0, array.Length); return BitConverter.ToInt16(array, 0); } /// /// random ushort /// /// public ushort GetRandomUInt16() { var array = new byte[2]; _random.NextBytes(array, 0, array.Length); return BitConverter.ToUInt16(array, 0); } /// /// Random int32 /// /// public int GetRandomInt32() { var array = new byte[4]; _random.NextBytes(array, 0, array.Length); return BitConverter.ToInt32(array, 0); } /// /// Random uint32 /// /// public uint GetRandomUInt32() { var array = new byte[4]; _random.NextBytes(array, 0, array.Length); return BitConverter.ToUInt32(array, 0); } /// /// Random uint64 /// /// public long GetRandomInt64() { var array = new byte[8]; _random.NextBytes(array, 0, array.Length); return BitConverter.ToInt64(array, 0); } /// /// Random int64 /// /// public ulong GetRandomUInt64() { var array = new byte[8]; _random.NextBytes(array, 0, array.Length); return BitConverter.ToUInt64(array, 0); } public float GetRandomFloat() { var array = new byte[4]; _random.NextBytes(array, 0, array.Length); return BitConverter.ToSingle(array, 0); } /// /// Get random double /// /// public double GetRandomDouble() { var array = new byte[8]; _random.NextBytes(array, 0, array.Length); return BitConverter.ToDouble(array, 0); } /// /// Random string /// /// public string GetRandomString() { return CreateString(GetRandomLocale(), false); } public DateTime GetRandomDateTime() { var min = (int)(MinDateTimeValue.Ticks >> 32); var max = (int)(MaxDateTimeValue.Ticks >> 32); long num = GetRandomRange(min, max); var num2 = num << 32; var randomUInt = GetRandomUInt32(); return new DateTime(num2 + randomUInt, DateTimeKind.Utc); } /// /// Get random guid /// /// public Guid GetRandomGuid() { var array = new byte[16]; _random.NextBytes(array, 0, array.Length); return new Guid(array); } /// /// Get random byte array /// /// public byte[] GetRandomByteString() { var num = _random.NextInt32(MaxStringLength); var array = new byte[num]; _random.NextBytes(array, 0, array.Length); return array; } /// /// Get random xml element /// /// public XmlElement GetRandomXmlElement() { var randomLocale = GetRandomLocale(); var randomLocale2 = GetRandomLocale(); var xmlDocument = new XmlDocument(); var xmlElement = xmlDocument.CreateElement("n0", CreateString(randomLocale, true), Utils.Format("http://{0}", CreateString(randomLocale, true))); xmlDocument.AppendChild(xmlElement); var num = _random.NextInt32(MaxXmlAttributeCount); for (var i = 0; i < num; i++) { var name = CreateString(randomLocale, true); var xmlAttribute = xmlDocument.CreateAttribute(name); xmlAttribute.Value = CreateString(randomLocale2, true); xmlElement.SetAttributeNode(xmlAttribute); } var num2 = _random.NextInt32(MaxXmlElementCount); for (var j = 0; j < num2; j++) { var localName = CreateString(randomLocale, true); var xmlElement2 = xmlDocument.CreateElement(xmlElement.Prefix, localName, xmlElement.NamespaceURI); xmlElement2.InnerText = CreateString(randomLocale2, false); xmlElement.AppendChild(xmlElement2); } return xmlElement; } /// /// Get random node id /// /// public NodeId GetRandomNodeId() { var namespaceIndex = (ushort)_random.NextInt32(NamespaceUris.Count - 1); switch (_random.NextInt32(4)) { case 1: return new NodeId(CreateString(GetRandomLocale(), true), namespaceIndex); case 2: return new NodeId(GetRandomGuid(), namespaceIndex); case 3: return new NodeId(GetRandomByteString(), namespaceIndex); default: return new NodeId(GetRandomUInt32(), namespaceIndex); } } /// /// Get random expanded node id /// /// public ExpandedNodeId GetRandomExpandedNodeId() { var randomNodeId = GetRandomNodeId(); var serverIndex = (ushort)((ServerUris.Count != 0) ? ((ushort)_random.NextInt32(ServerUris.Count - 1)) : 0); return new ExpandedNodeId(randomNodeId, NamespaceUris.GetString(randomNodeId.NamespaceIndex), serverIndex); } /// /// Get random qn /// /// public QualifiedName GetRandomQualifiedName() { var namespaceIndex = (ushort)_random.NextInt32(NamespaceUris.Count - 1); return new QualifiedName(CreateString(GetRandomLocale(), true), namespaceIndex); } /// /// Get random localized text /// /// public LocalizedText GetRandomLocalizedText() { var randomLocale = GetRandomLocale(); return new LocalizedText(randomLocale, CreateString(randomLocale, false)); } /// /// Get random status code /// /// public StatusCode GetRandomStatusCode() { var randomRange = GetRandomRange(32769, 32951); return (uint)(2147549184u + (randomRange << 16)); } /// /// Create random variant /// /// /// public Variant GetRandomVariant(bool allowArrays = true) { var builtInType = BuiltInType.Variant; while (builtInType == BuiltInType.Variant || builtInType == BuiltInType.DataValue || builtInType == BuiltInType.Null) { builtInType = (BuiltInType)_random.NextInt32(24); } return GetRandomVariant(builtInType, allowArrays && _random.NextInt32(1) == 1); } private bool UseBoundaryValue() { if (!_useBoundaryValues) { return false; } return _random.NextInt32(99) < BoundaryValueFrequency; } private Variant[] GetRandomArrayInVariant(BuiltInType builtInType, int length, bool fixedLength) { var randomArray = GetRandomArray(builtInType, length, fixedLength); var array = new Variant[randomArray.Length]; var typeInfo = new Ua.TypeInfo(builtInType, -1); for (var i = 0; i < array.Length; i++) { array[i] = new Variant(randomArray.GetValue(i), typeInfo); } return array; } private Variant GetRandomVariant(BuiltInType builtInType, bool isArray) { if (builtInType == BuiltInType.Null) { return Variant.Null; } var num = -1; if (isArray) { num = _random.NextInt32(MaxArrayLength - 1); } else if (builtInType == BuiltInType.Variant) { num = 1; } if (num >= 0) { switch (builtInType) { case BuiltInType.Boolean: return new Variant(GetRandomArray(num, true)); case BuiltInType.SByte: return new Variant(GetRandomArray(num, true)); case BuiltInType.Byte: return new Variant(GetRandomArray(num, true)); case BuiltInType.Int16: return new Variant(GetRandomArray(num, true)); case BuiltInType.UInt16: return new Variant(GetRandomArray(num, true)); case BuiltInType.Int32: return new Variant(GetRandomArray(num, true)); case BuiltInType.UInt32: return new Variant(GetRandomArray(num, true)); case BuiltInType.Int64: return new Variant(GetRandomArray(num, true)); case BuiltInType.UInt64: return new Variant(GetRandomArray(num, true)); case BuiltInType.Float: return new Variant(GetRandomArray(num, true)); case BuiltInType.Double: return new Variant(GetRandomArray(num, true)); case BuiltInType.String: return new Variant(GetRandomArray(num, true)); case BuiltInType.DateTime: return new Variant(GetRandomArray(num, true)); case BuiltInType.Guid: return new Variant(GetRandomArray(num, true)); case BuiltInType.ByteString: return new Variant(GetRandomArray(num, true)); case BuiltInType.XmlElement: return new Variant(GetRandomArray(num, true)); case BuiltInType.NodeId: return new Variant(GetRandomArray(num, true)); case BuiltInType.ExpandedNodeId: return new Variant(GetRandomArray(num, true)); case BuiltInType.QualifiedName: return new Variant(GetRandomArray(num, true)); case BuiltInType.LocalizedText: return new Variant(GetRandomArray(num, true)); case BuiltInType.StatusCode: return new Variant(GetRandomArray(num, true)); case BuiltInType.Variant: return new Variant(GetRandomArray(num, true)); case BuiltInType.ExtensionObject: return new Variant(GetRandomArray(num, true)); default: throw new ArgumentException($"Unexpected type {builtInType} constructing variant"); } } return new Variant(GetRandom(builtInType)); } public ExtensionObject GetRandomExtensionObject() { var randomNodeId = GetRandomNodeId(); if (!NodeId.IsNull(randomNodeId)) { return new ExtensionObject(randomNodeId, (_random.NextInt32(1) == 0) ? GetRandomXmlElement() : GetRandomByteString()); } return new ExtensionObject(); } private static SortedDictionary LoadStringData(string resourceName) { var sortedDictionary = new SortedDictionary(); try { string text = null; List list = null; var stream = typeof(DataGenerator).GetTypeInfo().Assembly.GetManifestResourceStream(resourceName); if (stream == null) { var fileInfo = new FileInfo(resourceName); stream = fileInfo.OpenRead(); } using (var streamReader = new StreamReader(stream)) { for (var text2 = streamReader.ReadLine(); text2 != null; text2 = streamReader.ReadLine()) { var text3 = text2.Trim(); if (!string.IsNullOrEmpty(text3)) { if (text3.StartsWith('=')) { if (text != null) { sortedDictionary.Add(text, [.. list]); } text = text3[1..]; list = []; } else { list.Add(text3); } } } } return sortedDictionary; } catch (Exception) { return sortedDictionary; } } private object GetBoundaryValue(Type type) { if (type == null) { return null; } if (!_boundaryValues.TryGetValue(type.Name, out var value)) { return null; } if (value == null || value.Length == 0) { return null; } var num = _random.NextInt32(value.Length - 1); if (type.IsInstanceOfType(value[num])) { return value[num]; } return null; } private int GetRandomRange(int min, int max) { if (min < 0) { min = 0; } if (max < 0) { max = 0; } if (min >= max) { return min; } return _random.NextInt32(max - min) + min; } private object GetRandom(Type expectedType) { var random = GetRandom(Ua.TypeInfo.Construct(expectedType).BuiltInType); if (expectedType == typeof(Uuid)) { return new Uuid((Guid)random); } return random; } private string GetRandomLocale() { var num = _random.NextInt32(_availableLocales.Length - 1); return _availableLocales[num]; } private string CreateString(string locale, bool isSymbol) { if (!_tokenValues.TryGetValue(locale, out var value)) { value = _tokenValues["en-US"]; } var num = (!isSymbol) ? (_random.NextInt32(MaxStringLength) + 1) : (_random.NextInt32(2) + 1); var stringBuilder = new StringBuilder(); while (stringBuilder.Length < num) { if (!isSymbol && stringBuilder.Length > 0) { stringBuilder.Append(' '); } var num2 = _random.NextInt32(value.Length - 1); stringBuilder.Append(value[num2]); if (!isSymbol && _random.NextInt32(1) != 0) { num2 = _random.NextInt32("`~!@#$%^&*()_-+={}[]:\"';?><,./".Length - 1); stringBuilder.Append("`~!@#$%^&*()_-+={}[]:\"';?><,./"[num2]); } } return stringBuilder.ToString(); } /// /// Boundary value holder /// private sealed class BoundaryValues { public Type SystemType { get; set; } public List Values { get; set; } public BoundaryValues(Type systemType, params object[] values) { SystemType = systemType; if (values != null) { Values = [.. values]; } else { Values = []; } } } private static readonly BoundaryValues[] kAvailableBoundaryValues = [ new BoundaryValues(typeof(sbyte), sbyte.MinValue, (sbyte)0, sbyte.MaxValue), new BoundaryValues(typeof(byte), (byte)0, byte.MaxValue), new BoundaryValues(typeof(short), short.MinValue, (short)0, short.MaxValue), new BoundaryValues(typeof(ushort), (ushort)0, ushort.MaxValue), new BoundaryValues(typeof(int), -2147483648, 0, 2147483647), new BoundaryValues(typeof(uint), 0u, uint.MaxValue), new BoundaryValues(typeof(long), -9223372036854775808L, 0L, 9223372036854775807L), new BoundaryValues(typeof(ulong), 0uL, ulong.MaxValue), new BoundaryValues(typeof(float), 1.401298E-45f, 3.40282347E+38f, -3.40282347E+38f, float.NaN, float.NegativeInfinity, float.PositiveInfinity, 0f), new BoundaryValues(typeof(double), 4.94065645841247E-324, 1.7976931348623157E+308, -1.7976931348623157E+308, double.NaN, double.NegativeInfinity, double.PositiveInfinity, 0.0), new BoundaryValues(typeof(string), string.Empty), // TODO: Fix // new BoundaryValues(typeof(DateTime), DateTime.MinValue, DateTime.MaxValue, // new DateTime(1099, 1, 1), new DateTime(2039, 4, 4), // new DateTime(2001, 9, 11, 9, 15, 0, DateTimeKind.Local)), new BoundaryValues(typeof(byte[]), Array.Empty()), new BoundaryValues(typeof(StatusCode), 0u, 1073741824u, 2147483648u) ]; private readonly IRandomSource _random; private readonly SortedDictionary _boundaryValues; private readonly bool _useBoundaryValues = true; private readonly string[] _availableLocales; private readonly SortedDictionary _tokenValues; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Utils/TimeService.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Opc.Ua.Test { using System; using System.Timers; using Timer = System.Timers.Timer; /// /// Service returning values and instances. Mocked in tests. /// public class TimeService { /// /// Create a new instance with set to true /// and set to true. The will call the /// provided callback at regular intervals. This method is overridden in tests to return /// a mock object. /// /// Event handler to call at regular intervals. /// Time interval at which to call the callback. /// A . public virtual ITimer NewTimer( ElapsedEventHandler callback, uint intervalInMilliseconds) { var timer = new TimerAdapter { Interval = intervalInMilliseconds, AutoReset = true, Enabled = true }; timer.Elapsed += callback; return timer; } /// /// Create a new instance with set to true /// and set to true. The will call the /// provided callback at regular intervals. This method is overridden in tests to return /// a mock object. /// /// Event handler to call at regular intervals. /// Time interval at which to call the callback. /// A . public virtual ITimer NewFastTimer( EventHandler callback, uint intervalInMilliseconds) { var timer = new FastTimer { Interval = intervalInMilliseconds, AutoReset = true }; timer.Elapsed += callback; timer.Enabled = true; return timer; } /// /// Returns the current time. Overridden in tests. /// /// The current time. public virtual DateTime Now => DateTime.Now; /// /// Returns the current UTC time. Overridden in tests. /// /// The current UTC time. public virtual DateTime UtcNow => DateTime.UtcNow; /// /// An adapter allowing the construction of objects /// that explicitly implement the interface. /// The adapter itself must remain empty, add any required properties /// or methods from the class into the /// interface. /// private sealed class TimerAdapter : Timer, ITimer; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Vehicles/Namespaces.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Vehicles { /// /// Defines constants for namespaces used by the application. /// public static class Namespaces { /// /// The namespace for the nodes provided by the server. /// public const string Vehicles = "urn:localhost:somecompany.com:VehiclesServer"; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Vehicles/VehiclesNodeManager.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Vehicles { using Opc.Ua; using Opc.Ua.Server; using System; using System.Collections.Generic; using System.Reflection; /// /// A node manager for a server that exposes several variables. /// public class VehiclesNodeManager : CustomNodeManager2 { /// /// Initializes the node manager. /// /// /// public VehiclesNodeManager(IServerInternal server, ApplicationConfiguration configuration) : base(server, configuration) { SystemContext.NodeIdFactory = this; SetNamespaces( Namespaces.Vehicles, Types.Namespaces.Vehicles, Instances.Namespaces.VehiclesInstances); // get the configuration for the node manager. // use suitable defaults if no configuration exists. _configuration = configuration.ParseExtension() ?? new VehiclesServerConfiguration(); } /// /// An overrideable version of the Dispose. /// /// protected override void Dispose(bool disposing) { if (disposing) { // TBD } base.Dispose(disposing); } /// /// Creates the NodeId for the specified node. /// /// /// public override NodeId New(ISystemContext context, NodeState node) { // generate a numeric node id if the node has a parent and no node id assigned. if (node is BaseInstanceState instance && instance.Parent != null) { return GenerateNodeId(); } return node.NodeId; } /// /// Does any initialization required before the address space can be used. /// /// /// /// The externalReferences is an out parameter that allows the node manager to link to nodes /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and /// should have a reference to the root folder node(s) exposed by this node manager. /// public override void CreateAddressSpace(IDictionary> externalReferences) { lock (Lock) { base.CreateAddressSpace(externalReferences); var dictionary = (BaseDataVariableState)FindPredefinedNode( ExpandedNodeId.ToNodeId(Types.VariableIds.Vehicles_BinarySchema, Server.NamespaceUris), typeof(BaseDataVariableState)); var type = GetType().GetTypeInfo(); dictionary.Value = LoadSchemaFromResource( $"{type.Assembly.GetName().Name}.Generated.{type.Namespace}.Design.{type.Namespace}.Types.Types.bsd", typeof(Types.VehicleType).Assembly); dictionary = (BaseDataVariableState)FindPredefinedNode( ExpandedNodeId.ToNodeId(Types.VariableIds.Vehicles_XmlSchema, Server.NamespaceUris), typeof(BaseDataVariableState)); dictionary.Value = LoadSchemaFromResource( $"{type.Assembly.GetName().Name}.Generated.{type.Namespace}.Design.{type.Namespace}.Types.Types.xsd", typeof(Types.VehicleType).Assembly); } } /// /// Loads the schema from an embedded resource. /// /// /// /// is null. /// public byte[] LoadSchemaFromResource(string resourcePath, Assembly assembly) { ArgumentNullException.ThrowIfNull(resourcePath); if (assembly == null) { assembly = Assembly.GetCallingAssembly(); } var istrm = assembly.GetManifestResourceStream(resourcePath); if (istrm == null) { throw ServiceResultException.Create(StatusCodes.BadDecodingError, "Could not load nodes from resource: {0}", resourcePath); } var buffer = new byte[istrm.Length]; istrm.ReadExactly(buffer, 0, (int)istrm.Length); return buffer; } /// /// Loads a node set from a file or resource and addes them to the set of predefined nodes. /// /// protected override NodeStateCollection LoadPredefinedNodes(ISystemContext context) { var type = GetType().GetTypeInfo(); var predefinedNodes = new NodeStateCollection(); predefinedNodes.LoadFromBinaryResource(context, $"{type.Assembly.GetName().Name}.Generated.{type.Namespace}.Design.{type.Namespace}.Types.PredefinedNodes.uanodes", type.Assembly, true); predefinedNodes.LoadFromBinaryResource(context, $"{type.Assembly.GetName().Name}.Generated.{type.Namespace}.Design.{type.Namespace}.Instances.PredefinedNodes.uanodes", type.Assembly, true); return predefinedNodes; } /// /// Frees any resources allocated for the address space. /// public override void DeleteAddressSpace() { lock (Lock) { // TBD } } /// /// Returns a unique handle for the node. /// /// /// /// protected override NodeHandle GetManagerHandle(ServerSystemContext context, NodeId nodeId, IDictionary cache) { lock (Lock) { // quickly exclude nodes that are not in the namespace. if (!IsNodeIdInNamespace(nodeId)) { return null; } // check cache (the cache is used because the same node id can appear many times in a single request). if (cache != null && cache.TryGetValue(nodeId, out var node)) { return new NodeHandle(nodeId, node); } // look up predefined node. if (PredefinedNodes.TryGetValue(nodeId, out node)) { var handle = new NodeHandle(nodeId, node); cache?.Add(nodeId, node); return handle; } // node not found. return null; } } /// /// Verifies that the specified node exists. /// /// /// /// protected override NodeState ValidateNode( ServerSystemContext context, NodeHandle handle, IDictionary cache) { // not valid if no root. if (handle == null) { return null; } // check if previously validated. if (handle.Validated) { return handle.Node; } // lookup in operation cache. var target = FindNodeInCache(context, handle, cache); if (target != null) { handle.Node = target; handle.Validated = true; return handle.Node; } // put root into operation cache. if (cache != null) { cache[handle.NodeId] = target; } handle.Node = target; handle.Validated = true; return handle.Node; } /// /// Generates a new node id. /// private NodeId GenerateNodeId() { return new NodeId(++_nextNodeId, NamespaceIndex); } private uint _nextNodeId; #pragma warning disable IDE0052 // Remove unread private members private readonly VehiclesServerConfiguration _configuration; #pragma warning restore IDE0052 // Remove unread private members } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Vehicles/VehiclesServer.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Vehicles { using Opc.Ua; using Opc.Ua.Server; /// public class VehiclesServer : INodeManagerFactory { /// public StringCollection NamespacesUris { get { return [ Namespaces.Vehicles, Types.Namespaces.Vehicles, Instances.Namespaces.VehiclesInstances ]; } } /// public INodeManager Create(IServerInternal server, ApplicationConfiguration configuration) { return new VehiclesNodeManager(server, configuration); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Vehicles/VehiclesServerConfiguration.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Vehicles { using System.Runtime.Serialization; /// /// Stores the configuration the data access node manager. /// [DataContract(Namespace = Namespaces.Vehicles)] public class VehiclesServerConfiguration { /// /// The default constructor. /// public VehiclesServerConfiguration() { Initialize(); } /// /// Initializes the object during deserialization. /// /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Views/ViewsNodeManager.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Views { using Opc.Ua; using Opc.Ua.Server; using System.Collections.Generic; using System.Reflection; /// /// A node manager for a server that exposes several variables. /// public class ViewsNodeManager : CustomNodeManager2 { /// /// Initializes the node manager. /// /// /// public ViewsNodeManager(IServerInternal server, ApplicationConfiguration configuration) : base(server, configuration, Model.Namespaces.Views, Model.Namespaces.Engineering, Model.Namespaces.Operations) { SystemContext.NodeIdFactory = this; // get the configuration for the node manager. // use suitable defaults if no configuration exists. _configuration = configuration.ParseExtension() ?? new ViewsServerConfiguration(); } /// /// An overrideable version of the Dispose. /// /// protected override void Dispose(bool disposing) { if (disposing) { // TBD } base.Dispose(disposing); } /// /// Creates the NodeId for the specified node. /// /// /// public override NodeId New(ISystemContext context, NodeState node) { if (node is BaseInstanceState instance && instance.Parent != null) { var pnd = ParsedNodeId.Parse(instance.Parent.NodeId); if (pnd != null) { return pnd.Construct(instance.SymbolicName); } } return node.NodeId; } /// /// Loads a node set from a file or resource and addes them to the set of predefined nodes. /// /// protected override NodeStateCollection LoadPredefinedNodes(ISystemContext context) { var type = GetType().GetTypeInfo(); var predefinedNodes = new NodeStateCollection(); predefinedNodes.LoadFromBinaryResource(context, $"{type.Assembly.GetName().Name}.Generated.{type.Namespace}.Design.Model.PredefinedNodes.uanodes", type.Assembly, true); return predefinedNodes; } /// /// Does any initialization required before the address space can be used. /// /// /// /// The externalReferences is an out parameter that allows the node manager to link to nodes /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and /// should have a reference to the root folder node(s) exposed by this node manager. /// public override void CreateAddressSpace(IDictionary> externalReferences) { lock (Lock) { base.CreateAddressSpace(externalReferences); var root = FindPredefinedNode(new NodeId(Model.Objects.Plant, NamespaceIndex), typeof(NodeState)); var boiler1 = new Model.BoilerState(null); var pnd1 = new ParsedNodeId { NamespaceIndex = NamespaceIndex, RootId = "Boiler #1" }; boiler1.Create( SystemContext, pnd1.Construct(), new QualifiedName("Boiler #1", NamespaceIndex), null, true); boiler1.AddReference(ReferenceTypeIds.Organizes, true, root.NodeId); root.AddReference(ReferenceTypeIds.Organizes, false, boiler1.NodeId); AddPredefinedNode(SystemContext, boiler1); var boiler2 = new Model.BoilerState(null); var pnd2 = new ParsedNodeId { NamespaceIndex = NamespaceIndex, RootId = "Boiler #2" }; boiler2.Create( SystemContext, pnd2.Construct(), new QualifiedName("Boiler #2", NamespaceIndex), null, true); boiler2.AddReference(ReferenceTypeIds.Organizes, true, root.NodeId); root.AddReference(ReferenceTypeIds.Organizes, false, boiler2.NodeId); AddPredefinedNode(SystemContext, boiler2); } } /// /// Checks if the node is in the view. /// /// /// /// protected override bool IsNodeInView(ServerSystemContext context, ContinuationPoint continuationPoint, NodeState node) { if (continuationPoint.View != null) { if (continuationPoint.View.ViewId == new NodeId(Model.Views.Engineering, NamespaceIndex)) { // suppress operations properties. if (node != null && node.BrowseName.NamespaceIndex == NamespaceIndexes[2]) { return false; } } if (continuationPoint.View.ViewId == new NodeId(Model.Views.Operations, NamespaceIndex)) { // suppress engineering properties. if (node != null && node.BrowseName.NamespaceIndex == NamespaceIndexes[1]) { return false; } } } return true; } /// /// Checks if the reference is in the view. /// /// /// /// protected override bool IsReferenceInView(ServerSystemContext context, ContinuationPoint continuationPoint, IReference reference) { if (continuationPoint.View != null) { // guard against absolute node ids. if (reference.TargetId.IsAbsolute) { return true; } // find the node. var node = FindPredefinedNode((NodeId)reference.TargetId, typeof(NodeState)); if (node != null) { return IsNodeInView(context, continuationPoint, node); } } return true; } /// /// Frees any resources allocated for the address space. /// public override void DeleteAddressSpace() { } /// /// Returns a unique handle for the node. /// /// /// /// protected override NodeHandle GetManagerHandle(ServerSystemContext context, NodeId nodeId, IDictionary cache) { lock (Lock) { // quickly exclude nodes that are not in the namespace. if (!IsNodeIdInNamespace(nodeId)) { return null; } // check cache (the cache is used because the same node id can appear many times in a single request). if (cache != null && cache.TryGetValue(nodeId, out var node)) { return new NodeHandle(nodeId, node); } // look up predefined node. if (PredefinedNodes.TryGetValue(nodeId, out node)) { var handle = new NodeHandle(nodeId, node); cache?.Add(nodeId, node); return handle; } return null; } } /// /// Verifies that the specified node exists. /// /// /// /// protected override NodeState ValidateNode( ServerSystemContext context, NodeHandle handle, IDictionary cache) { // not valid if no root. if (handle == null) { return null; } // check if previously validated. if (handle.Validated) { return handle.Node; } // lookup in operation cache. var target = FindNodeInCache(context, handle, cache); if (target == null) { // TBD return null; } return ValidationComplete(context, handle, target, cache); } #pragma warning disable IDE0052 // Remove unread private members private readonly ViewsServerConfiguration _configuration; #pragma warning restore IDE0052 // Remove unread private members } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Views/ViewsServer.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Views { using Opc.Ua; using Opc.Ua.Server; /// public class ViewsServer : INodeManagerFactory { /// public StringCollection NamespacesUris { get { return [ Model.Namespaces.Views, Model.Namespaces.Engineering, Model.Namespaces.Operations ]; } } /// public INodeManager Create(IServerInternal server, ApplicationConfiguration configuration) { return new ViewsNodeManager(server, configuration); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/src/Views/ViewsServerConfiguration.cs ================================================ /* ======================================================================== * Copyright (c) 2005-2017 The OPC Foundation, Inc. All rights reserved. * * OPC Foundation MIT License 1.00 * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * The complete license agreement can be found here: * http://opcfoundation.org/License/MIT/1.00/ * ======================================================================*/ namespace Views { using System.Runtime.Serialization; /// /// Stores the configuration the data access node manager. /// [DataContract(Namespace = Model.Namespaces.Views)] public class ViewsServerConfiguration { /// /// The default constructor. /// public ViewsServerConfiguration() { Initialize(); } /// /// Initializes the object during deserialization. /// /// [OnDeserializing] private void Initialize(StreamingContext context) { Initialize(); } /// /// Sets private members to default values. /// private void Initialize() { } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Azure.IIoT.OpcUa.Publisher.Testing.csproj ================================================  net9.0 Contains fixtures and tests executing against test servers enable ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Extensions/OpcUaClientManagerEx.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Stack { using Azure.IIoT.OpcUa.Encoders; using Furly.Extensions.Serializers; using Opc.Ua; using Opc.Ua.Extensions; using System.Threading; using System.Threading.Tasks; /// /// Session provider extensions /// public static class OpcUaClientManagerEx { /// /// Read value /// /// /// /// /// /// /// /// public static Task ReadValueAsync(this IOpcUaClientManager client, T connection, string readNode, IJsonSerializer serializer, CancellationToken ct = default) { return client.ExecuteAsync(connection, async context => { var nodesToRead = new ReadValueIdCollection { new ReadValueId { NodeId = readNode.ToNodeId(context.Session.MessageContext), AttributeId = Attributes.Value } }; var response = await context.Session.Services.ReadAsync( new RequestHeader(), 0, TimestampsToReturn.Both, nodesToRead, context.Ct).ConfigureAwait(false); return new JsonVariantEncoder(context.Session.MessageContext, serializer) .Encode(response.Results[0].WrappedValue, out var tmp); }, ct: ct); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Fixtures/AlarmsServer.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Fixtures { using Microsoft.Extensions.Logging; using Opc.Ua.Server; using Opc.Ua.Test; using System.Collections.Generic; /// /// Alarms server fixture /// public class AlarmsServer : BaseServerFixture { /// /// Alarm server nodes /// /// /// public static IEnumerable Alarms( ILoggerFactory? factory, TimeService timeservice) { yield return new Alarms.AlarmConditionServer(timeservice); } /// public AlarmsServer() : base(Alarms) { } /// private AlarmsServer(ILoggerFactory loggerFactory) : base(Alarms, loggerFactory) { } /// public static AlarmsServer Create(ILoggerFactory loggerFactory) { return new AlarmsServer(loggerFactory); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Fixtures/AssetServer.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Fixtures { using Furly.Extensions.Logging; using Microsoft.Extensions.Logging; using Opc.Ua.Server; using Opc.Ua.Test; using System.Collections.Generic; /// /// Asset server fixture /// public class AssetServer : BaseServerFixture { /// /// Sample server nodes /// /// /// public static IEnumerable Asset( ILoggerFactory? factory, TimeService timeservice) { var logger = (factory ?? Log.ConsoleFactory()) .CreateLogger(); yield return new Asset.AssetServer(logger); } /// public AssetServer() : base(Asset) { } /// private AssetServer(ILoggerFactory loggerFactory) : base(Asset, loggerFactory) { } /// public static AssetServer Create(ILoggerFactory loggerFactory) { return new AssetServer(loggerFactory); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Fixtures/BaseServerFixture.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Fixtures { using Azure.IIoT.OpcUa.Publisher.Testing.Runtime; using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Publisher.Parser; using Azure.IIoT.OpcUa.Publisher.Stack; using Azure.IIoT.OpcUa.Publisher.Stack.Sample; using Azure.IIoT.OpcUa.Publisher.Stack.Services; using Autofac; using Furly.Extensions.Logging; using Furly.Extensions.Utils; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Moq; using Opc.Ua; using Opc.Ua.Server; using Opc.Ua.Test; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Security.Cryptography.X509Certificates; using System.Threading.Tasks; using System.Timers; /// /// Adds sample server as fixture to unit tests /// public abstract class BaseServerFixture : IDisposable { /// /// Host server is running on /// public IPHostEntry? Host { get; } /// /// Use reverse connect /// public bool UseReverseConnect { get; } /// /// Client port /// public int ReverseConnectPort { get; } /// /// Certificate of the server /// public X509Certificate2 Certificate => _serverHost.Certificate; /// /// Client /// public IOpcUaClientManager Client => _container.Resolve>(); /// /// Now /// public DateTime Now { get; private set; } /// /// Time service /// public TimeService TimeService => _timeService.Object; /// /// Temporary path /// public string TempPath { get; } = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); /// /// Filter parser /// public IFilterParser Parser => _container.Resolve(); /// /// EndpointUrl /// public string EndpointUrl => $"opc.tcp://{HostName}:{_port}/{kSampleServerPath}"; /// /// Host name /// /// There is a quirk in registration matching inside the reconnect manager the /// server must present their endpoint in RHEL exactly like it is requested by /// the client. The reconnect manager compares to the endpoint url and if it is /// not the same it will reject. /// /// /// In this test the host name is the FQDN host name here, but the one it matches /// against and presented by the server is just the machine's host name and /// therefore rejects even though it is the same. /// /// private string HostName => (UseReverseConnect ? Utils.GetHostName() : Host?.HostName) ?? "localhost"; /// /// Get server connection /// /// public ConnectionModel GetConnection() { return new ConnectionModel { Endpoint = new EndpointModel { Url = EndpointUrl, AlternativeUrls = Host?.AddressList .Where(ip => ip.AddressFamily == AddressFamily.InterNetwork) .Select(ip => $"opc.tcp://{ip}:{_port}/{kSampleServerPath}") .ToHashSet(), Certificate = Certificate?.RawData?.ToThumbprint() }, Options = UseReverseConnect ? ConnectionOptions.UseReverseConnect : ConnectionOptions.None }; } /// /// Create fixture /// /// /// /// protected BaseServerFixture( Func> nodesFactory, ILoggerFactory? loggerFactory = null, bool useReverseConnect = false) { var sw = Stopwatch.StartNew(); Host = Try.Op(() => Dns.GetHostEntry(Utils.GetHostName())) ?? Try.Op(() => Dns.GetHostEntry("localhost")); _container = CreateContainer(loggerFactory ?? Log.ConsoleFactory(LogLevel.Debug)); Now = new DateTime(2023, 1, 1, 7, 15, 0, DateTimeKind.Utc); _timeService = CreateTimeServiceMock(Now); _port = NextPort(); var logger = _container.Resolve>(); var options = _container.Resolve>(); var nodes = nodesFactory(_container.Resolve(), TimeService); ServerConsoleHost? serverHost = null; while (true) { try { serverHost = new ServerConsoleHost(new ServerFactory( _container.Resolve>(), TempPath, nodes) { LogStatus = false }, _container.Resolve>()) { PkiRootPath = options.Value.Security.PkiRootPath, AutoAccept = true }; logger.StartingServerHost(serverHost, _port); serverHost.StartAsync(new int[] { _port }).Wait(); // // Test server connection. Sometimes the server has not // started and tests are failing with Not reachable, this // should ensure the server has started up correctly. // var endpoint = _container.Resolve>(); var result = endpoint.TestConnectionAsync(new ConnectionModel { Endpoint = new EndpointModel { Url = EndpointUrl } }, new TestConnectionRequestModel()).WaitAsync(TimeSpan.FromSeconds(10)) .GetAwaiter().GetResult(); if (result.ErrorInfo != null) { throw new IOException( result.ErrorInfo.ErrorMessage ?? "Failed testing connection."); } logger.ServerHostListening(serverHost, EndpointUrl); _serverHost = serverHost; if (!useReverseConnect) { break; } int clientPort; // Find a port for the client while (true) { clientPort = NextPort(); try { logger.TryAddingReverseConnect(clientPort); using var listener = TcpListener.Create(clientPort); listener.Start(); // Throws if used and cleans up. listener.Stop(); // Cleanup break; } catch (Exception ex) { logger.PortNotAccessible(ex, clientPort); kPorts.AddOrUpdate(clientPort, false, (_, _) => false); } } UseReverseConnect = true; ReverseConnectPort = clientPort; var clientUrl = $"opc.tcp://{HostName}:{clientPort}"; _serverHost.AddReverseConnectionAsync(new Uri(clientUrl), 4) .WaitAsync(TimeSpan.FromMinutes(1)).GetAwaiter().GetResult(); logger.StartReverseConnect(clientUrl); break; } catch (Exception ex) { kPorts.AddOrUpdate(_port, false, (_, _) => false); _port = NextPort(); logger.FailedToStartHost(ex, serverHost, _port); serverHost?.Dispose(); serverHost = null; } } logger.ServerHostStarted(serverHost, sw.Elapsed); } /// public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } /// /// Restart server /// /// /// public Task RestartAsync(Func predicate) { return _serverHost.RestartAsync(predicate); } /// /// Override to dispose /// /// protected virtual void Dispose(bool disposing) { if (!_disposedValue) { if (disposing) { var sw = Stopwatch.StartNew(); var logger = _container.Resolve>(); logger.DisposingServerHost(_serverHost); string? pkiPath = null; if (_container.TryResolve>(out var options) && Directory.Exists(options.Value.Security.PkiRootPath)) { pkiPath = options.Value.Security.PkiRootPath; } _container.Dispose(); _serverHost.Dispose(); kPorts.TryRemove(_port, out _); logger.ServerHostDisposed(_serverHost, pkiPath, sw.Elapsed); // Clean up all created certificates if (!string.IsNullOrEmpty(pkiPath) && Directory.Exists(pkiPath)) { Try.Op(() => Directory.Delete(pkiPath, true)); } logger.ServerDisposingElapsed(sw.Elapsed); if (Directory.Exists(TempPath)) { Try.Op(() => Directory.Delete(TempPath, true)); } } _disposedValue = true; } } private static IContainer CreateContainer(ILoggerFactory loggerFactory) { var builder = new ContainerBuilder(); builder.ConfigureServices(services => services.AddLogging()); builder.RegisterInstance(new ConfigurationBuilder().Build()) .AsImplementedInterfaces(); builder.RegisterInstance(loggerFactory) .AsImplementedInterfaces(); builder.AddDefaultJsonSerializer(); // builder.AddNewtonsoftJsonSerializer(); builder.RegisterType() .AsImplementedInterfaces(); builder.AddOpcUaStack(); return builder.Build(); } /// /// Cause a subset of the mocked timers to fire a number of times, /// and the current mocked time to advance accordingly. /// /// Defines the timers to fire: /// only timers with this interval are fired. /// Number of times the timer /// should be fired. #pragma warning disable CA1030 // Use events where appropriate public void FireTimersWithPeriod(TimeSpan period, int numberOfTimes) #pragma warning restore CA1030 // Use events where appropriate { var matchedHandlers = GetTimerHandlersForPeriod((uint)period.TotalMilliseconds); for (var i = 0; i < numberOfTimes; i++) { Now += period; foreach (var handler in matchedHandlers) { handler(); } } } /// /// Retrieve the timer handlers for the given period /// /// /// private List GetTimerHandlersForPeriod(uint periodInMilliseconds) { var matchedTimers = _timers.Where(t => t.timer.Enabled && CloseTo(t.timer.Interval, periodInMilliseconds)) .Select(t => (Action)(() => t.handler(null, null!))) .ToList(); var matchedFastTimers = _fastTimers.Where(t => t.timer.Enabled && CloseTo(t.timer.Interval, periodInMilliseconds)) .Select(t => (Action)(() => t.handler(null, null!))) .ToList(); return matchedTimers.Union(matchedFastTimers).ToList(); static bool CloseTo(double a, double b) => Math.Abs(a - b) <= Math.Abs(a * .00001); } /// /// Get another port /// /// private static int NextPort() { while (true) { #pragma warning disable CA5394 // Do not use insecure randomness var port = Random.Shared.Next(53000, 58000); #pragma warning restore CA5394 // Do not use insecure randomness if (kPorts.TryAdd(port, true)) { return port; } } } /// /// Create a mocked time service for the tests to be able to /// control time in the server. /// /// The start time /// private Mock CreateTimeServiceMock(DateTime now) { var mock = new Mock(); mock.Setup(f => f.NewTimer( It.IsAny(), It.IsAny())) .Returns((ElapsedEventHandler handler, uint intervalInMilliseconds) => { var mockTimer = new Mock(); mockTimer.SetupAllProperties(); var timer = mockTimer.Object; timer.Interval = intervalInMilliseconds; timer.AutoReset = true; timer.Enabled = true; _timers.Add((timer, handler)); return timer; }); mock.Setup(f => f.NewFastTimer( It.IsAny>(), It.IsAny())) .Returns((EventHandler handler, uint intervalInMilliseconds) => { var mockTimer = new Mock(); mockTimer.SetupAllProperties(); var timer = mockTimer.Object; timer.Interval = intervalInMilliseconds; timer.AutoReset = true; timer.Enabled = true; _fastTimers.Add((timer, handler)); return timer; }); mock.Setup(f => f.Now) .Returns(() => now); mock.Setup(f => f.UtcNow) .Returns(() => now); return mock; } /// Registry of mocked timers. private readonly ConcurrentBag<(ITimer timer, ElapsedEventHandler handler)> _timers = []; /// Registry of mocked fast timers. private readonly ConcurrentBag<(ITimer timer, EventHandler handler)> _fastTimers = []; private static readonly ConcurrentDictionary kPorts = new(); private bool _disposedValue; private readonly int _port; private readonly IContainer _container; private readonly ServerConsoleHost _serverHost; private readonly Mock _timeService; private const string kSampleServerPath = "UA/SampleServer"; } /// /// Generated logging methods for BaseServerFixture /// internal static partial class BaseServerFixtureLogging { private const int EventClass = 0; [LoggerMessage(EventId = EventClass + 1, Level = LogLevel.Information, Message = "Starting server host {Host} on {Port}...")] public static partial void StartingServerHost(this ILogger logger, ServerConsoleHost host, int port); [LoggerMessage(EventId = EventClass + 2, Level = LogLevel.Information, Message = "Server host {Host} listening on {EndpointUrl}!")] public static partial void ServerHostListening(this ILogger logger, ServerConsoleHost host, string endpointUrl); [LoggerMessage(EventId = EventClass + 3, Level = LogLevel.Information, Message = "Try adding reverse connect client on {Port}...")] public static partial void TryAddingReverseConnect(this ILogger logger, int port); [LoggerMessage(EventId = EventClass + 4, Level = LogLevel.Error, Message = "Port {Port} is not accessible...")] public static partial void PortNotAccessible(this ILogger logger, Exception ex, int port); [LoggerMessage(EventId = EventClass + 5, Level = LogLevel.Information, Message = "Start reverse connect to client at {Url}...")] public static partial void StartReverseConnect(this ILogger logger, string url); [LoggerMessage(EventId = EventClass + 6, Level = LogLevel.Error, Message = "Failed to start host {Host}, retrying with port {Port}...")] public static partial void FailedToStartHost(this ILogger logger, Exception ex, ServerConsoleHost? host, int port); [LoggerMessage(EventId = EventClass + 7, Level = LogLevel.Information, Message = "Server host {Host} started in {Elapsed}...")] public static partial void ServerHostStarted(this ILogger logger, ServerConsoleHost host, TimeSpan elapsed); [LoggerMessage(EventId = EventClass + 8, Level = LogLevel.Information, Message = "Disposing server host {Host} and client fixture...")] public static partial void DisposingServerHost(this ILogger logger, ServerConsoleHost host); [LoggerMessage(EventId = EventClass + 9, Level = LogLevel.Information, Message = "Client fixture and server host {Host} disposed - cleaning up server certificates at '{PkiRoot}' ({Elapsed})...")] public static partial void ServerHostDisposed(this ILogger logger, ServerConsoleHost host, string? pkiRoot, TimeSpan elapsed); [LoggerMessage(EventId = EventClass + 10, Level = LogLevel.Information, Message = "Disposing Server took {Elapsed}...")] public static partial void ServerDisposingElapsed(this ILogger logger, TimeSpan elapsed); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Fixtures/DeterministicAlarmsServer1.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Fixtures { using Furly.Extensions.Logging; using Microsoft.Extensions.Logging; using Opc.Ua.Server; using Opc.Ua.Test; using System.Collections.Generic; /// /// Alarms server fixture /// public class DeterministicAlarmsServer1 : BaseServerFixture { public static readonly string Config = """ { "folders": [ { "name": "VendingMachines", "sources": [ { "objectType": "BaseObjectState", "name": "VendingMachine1", "alarms": [ { "objectType": "TripAlarmType", "name": "VendingMachine1_DoorOpen", "id": "V1_DoorOpen" }, { "objectType": "LimitAlarmType", "name": "VendingMachine1_TemperatureHigh", "id": "V1_TemperatureHigh" } ] }, { "objectType": "BaseObjectState", "name": "VendingMachine2", "alarms": [ { "objectType": "TripAlarmType", "name": "VendingMachine2_DoorOpen", "id": "V2_DoorOpen" }, { "objectType": "OffNormalAlarmType", "name": "VendingMachine2_LightOff", "id": "V2_LightOff" } ] } ] } ], "script": { "waitUntilStartInSeconds": 9, "isScriptInRepeatingLoop": true, "runningForSeconds": 22, "steps": [ { "event": { "alarmId": "V1_DoorOpen", "reason": "Door Open", "severity": "High", "eventId": "V1_DoorOpen-1", "stateChanges": [ { "stateType": "Enabled", "state": true }, { "stateType": "Activated", "state": true } ] } }, { "sleepInSeconds": 5 }, { "event": { "alarmId": "V2_LightOff", "reason": "Light Off in machine", "severity": "Medium", "eventId": "V2_LightOff-1", "stateChanges": [ { "stateType": "Enabled", "state": true }, { "stateType": "Activated", "state": true } ] } }, { "sleepInSeconds": 7 }, { "event": { "alarmId": "V1_DoorOpen", "reason": "Door Closed", "severity": "Medium", "eventId": "V1_DoorOpen-2", "stateChanges": [ { "stateType": "Activated", "state": false } ] } }, { "sleepInSeconds": 4 }, { "event": { "alarmId": "V1_TemperatureHigh", "reason": "Temperature is HIGH", "severity": "High", "eventId": "V1_TemperatureHigh-1", "stateChanges": [ { "stateType": "Activated", "state": true }, { "stateType": "Enabled", "state": true } ] } } ] } } """; /// public static IEnumerable DeterministicAlarms1( ILoggerFactory? factory, TimeService timeservice) { var logger = (factory ?? Log.ConsoleFactory()) .CreateLogger(); yield return new DeterministicAlarms.DeterministicAlarmsServer( timeservice, Config, logger); } /// public DeterministicAlarmsServer1() : base(DeterministicAlarms1) { } /// private DeterministicAlarmsServer1(ILoggerFactory loggerFactory) : base(DeterministicAlarms1, loggerFactory) { } /// public static DeterministicAlarmsServer1 Create(ILoggerFactory loggerFactory) { return new DeterministicAlarmsServer1(loggerFactory); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Fixtures/DeterministicAlarmsServer2.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Fixtures { using Furly.Extensions.Logging; using Microsoft.Extensions.Logging; using Opc.Ua.Server; using Opc.Ua.Test; using System.Collections.Generic; /// /// Alarms server fixture /// public class DeterministicAlarmsServer2 : BaseServerFixture { public static readonly string Config = """ { "folders": [ { "name": "VendingMachines", "sources": [ { "objectType": "BaseObjectState", "name": "VendingMachine1", "alarms": [ { "objectType": "TripAlarmType", "name": "VendingMachine1_DoorOpen", "id": "V1_DoorOpen" } ] } ] } ], "script": { "waitUntilStartInSeconds": 5, "isScriptInRepeatingLoop": false, "runningForSeconds": 36000, "steps": [ { "event": { "alarmId": "V1_DoorOpen", "reason": "Door Open", "severity": "High", "eventId": "V1_DoorOpen-1", "stateChanges": [ { "stateType": "Enabled", "state": true }, { "stateType": "Activated", "state": true } ] } }, { "sleepInSeconds": 5 }, { "event": { "alarmId": "V1_DoorOpen", "reason": "Door Closed", "severity": "Medium", "eventId": "V1_DoorOpen-2", "stateChanges": [ { "stateType": "Enabled", "state": false }, { "stateType": "Activated", "state": false } ] } } ] } } """; /// public static IEnumerable DeterministicAlarms2( ILoggerFactory? factory, TimeService timeservice) { var logger = (factory ?? Log.ConsoleFactory()) .CreateLogger(); yield return new DeterministicAlarms.DeterministicAlarmsServer( timeservice, Config, logger); } /// public DeterministicAlarmsServer2() : base(DeterministicAlarms2) { } /// private DeterministicAlarmsServer2(ILoggerFactory loggerFactory) : base(DeterministicAlarms2, loggerFactory) { } /// public static DeterministicAlarmsServer2 Create(ILoggerFactory loggerFactory) { return new DeterministicAlarmsServer2(loggerFactory); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Fixtures/FileSystemServer.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Fixtures { using Microsoft.Extensions.Logging; using Opc.Ua.Server; using Opc.Ua.Test; using System.Collections.Generic; /// /// Sample server fixture /// public class FileSystemServer : BaseServerFixture { /// /// Sample server nodes /// /// /// public static IEnumerable FileSystem( ILoggerFactory? factory, TimeService timeservice) { yield return new FileSystem.FileSystemServer(); } /// public FileSystemServer() : base(FileSystem) { } /// private FileSystemServer(ILoggerFactory loggerFactory) : base(FileSystem, loggerFactory) { } /// public static FileSystemServer Create(ILoggerFactory loggerFactory) { return new FileSystemServer(loggerFactory); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Fixtures/HistoricalAccessServer.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Fixtures { using Microsoft.Extensions.Logging; using Opc.Ua.Server; using Opc.Ua.Test; using System.Collections.Generic; /// /// Sample server fixture /// public class HistoricalAccessServer : BaseServerFixture { /// /// Sample server nodes /// /// /// public static IEnumerable HistoricalAccess( ILoggerFactory? factory, TimeService timeservice) { yield return new HistoricalAccess.HistoricalAccessServer(timeservice); } /// public HistoricalAccessServer() : base(HistoricalAccess) { } /// private HistoricalAccessServer(ILoggerFactory loggerFactory) : base(HistoricalAccess, loggerFactory) { } /// public static HistoricalAccessServer Create(ILoggerFactory loggerFactory) { return new HistoricalAccessServer(loggerFactory); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Fixtures/HistoricalEventsServer.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Fixtures { using Microsoft.Extensions.Logging; using Opc.Ua.Server; using Opc.Ua.Test; using System.Collections.Generic; /// /// Sample server fixture /// public class HistoricalEventsServer : BaseServerFixture { /// /// Sample server nodes /// /// /// public static IEnumerable HistoricalEvents( ILoggerFactory? factory, TimeService timeservice) { yield return new HistoricalEvents.HistoricalEventsServer(timeservice); } /// public HistoricalEventsServer() : base(HistoricalEvents) { } /// private HistoricalEventsServer(ILoggerFactory loggerFactory) : base(HistoricalEvents, loggerFactory) { } /// public static HistoricalEventsServer Create(ILoggerFactory loggerFactory) { return new HistoricalEventsServer(loggerFactory); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Fixtures/Isa95JobsServer.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Fixtures { using Microsoft.Extensions.Logging; using Opc.Ua.Server; using Opc.Ua.Test; using System.Collections.Generic; /// /// Isa95Jobs fixture /// public class Isa95JobsServer : BaseServerFixture { /// public static IEnumerable Isa95Jobs( ILoggerFactory? factory, TimeService timeservice) { yield return new Isa95Jobs.Isa95JobControlServer(); } /// public Isa95JobsServer() : base(Isa95Jobs) { } /// private Isa95JobsServer(ILoggerFactory loggerFactory) : base(Isa95Jobs, loggerFactory) { } /// public static Isa95JobsServer Create(ILoggerFactory loggerFactory) { return new Isa95JobsServer(loggerFactory); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Fixtures/PlcServer.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Fixtures { using Furly.Extensions.Logging; using Microsoft.Extensions.Logging; using Opc.Ua.Server; using Opc.Ua.Test; using System.Collections.Generic; /// /// Plc server fixture /// public class PlcServer : BaseServerFixture { /// public static IEnumerable Plc( ILoggerFactory? factory, TimeService timeservice) { yield return new Plc.PlcServer(timeservice, (factory ?? Log.ConsoleFactory()).CreateLogger(), 0); } /// public PlcServer() : base(Plc) { } /// private PlcServer(ILoggerFactory loggerFactory) : base(Plc, loggerFactory) { } /// public static PlcServer Create(ILoggerFactory loggerFactory) { return new PlcServer(loggerFactory); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Fixtures/ReferenceServer.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Fixtures { using Furly.Extensions.Logging; using Microsoft.Extensions.Logging; using Opc.Ua.Server; using Opc.Ua.Test; using System.Collections.Generic; /// /// Reference server fixture /// public class ReferenceServer : BaseServerFixture { /// /// Sample server nodes /// /// /// public static IEnumerable Reference( ILoggerFactory? factory, TimeService timeservice) { yield return new TestData.TestDataServer(); yield return new MemoryBuffer.MemoryBufferServer(); yield return new Boiler.BoilerServer(); yield return new Vehicles.VehiclesServer(); yield return new Reference.ReferenceServer(); yield return new HistoricalEvents.HistoricalEventsServer(timeservice); yield return new HistoricalAccess.HistoricalAccessServer(timeservice); yield return new Views.ViewsServer(); yield return new DataAccess.DataAccessServer(); yield return new Alarms.AlarmConditionServer(timeservice); yield return new SimpleEvents.SimpleEventsServer(); yield return new Plc.PlcServer(timeservice, (factory ?? Log.ConsoleFactory()).CreateLogger(), 0); } /// public ReferenceServer() : base(Reference) { } /// private ReferenceServer(ILoggerFactory loggerFactory, bool useReverseConnect) : base(Reference, loggerFactory, useReverseConnect) { } /// public static ReferenceServer Create(ILoggerFactory loggerFactory, bool useReverseConnect = false) { return new ReferenceServer(loggerFactory, useReverseConnect); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Fixtures/SimpleEventsServer.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Fixtures { using Microsoft.Extensions.Logging; using Opc.Ua.Server; using Opc.Ua.Test; using System.Collections.Generic; /// /// Simple events fixture /// public class SimpleEventsServer : BaseServerFixture { /// public static IEnumerable SimpleEvents( ILoggerFactory? factory, TimeService timeservice) { yield return new SimpleEvents.SimpleEventsServer(); } /// public SimpleEventsServer() : base(SimpleEvents) { } /// private SimpleEventsServer(ILoggerFactory loggerFactory) : base(SimpleEvents, loggerFactory) { } /// public static SimpleEventsServer Create(ILoggerFactory loggerFactory) { return new SimpleEventsServer(loggerFactory); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Fixtures/TestDataServer.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Fixtures { using Microsoft.Extensions.Logging; using Opc.Ua.Server; using Opc.Ua.Test; using System.Collections.Generic; /// /// Sample server fixture /// public class TestDataServer : BaseServerFixture { /// /// Sample server nodes /// /// /// public static IEnumerable TestData( ILoggerFactory? factory, TimeService timeservice) { yield return new TestData.TestDataServer(); yield return new MemoryBuffer.MemoryBufferServer(); yield return new Boiler.BoilerServer(); yield return new DataAccess.DataAccessServer(); } /// public TestDataServer() : base(TestData) { } /// private TestDataServer(ILoggerFactory loggerFactory) : base(TestData, loggerFactory) { } /// public static TestDataServer Create(ILoggerFactory loggerFactory) { return new TestDataServer(loggerFactory); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Properties/AssemblyInfo.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ using System; [assembly: CLSCompliant(false)] ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Runtime/TestClientConfig.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Runtime { using Azure.IIoT.OpcUa.Publisher.Stack; using Furly.Extensions.Configuration; using Furly.Extensions.Utils; using Microsoft.Extensions.Configuration; using System; using System.IO; /// /// Client's application configuration implementation /// public sealed class TestClientConfig : ConfigureOptionBase, IDisposable { public TestClientConfig(IConfiguration configuration) : base(configuration) { _path = Path.Combine(Directory.GetCurrentDirectory(), "pki", Guid.NewGuid().ToByteArray().ToBase16String()); } /// public override void Configure(string? name, OpcUaClientOptions options) { options.Security.PkiRootPath = _path; options.LingerTimeoutDuration = TimeSpan.FromSeconds(20); } /// public void Dispose() { if (Directory.Exists(_path)) { Try.Op(() => Directory.Delete(_path, true)); } } private readonly string _path; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/Alarms/AlarmServerTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher; using Azure.IIoT.OpcUa.Publisher.Models; using Alarms; using FluentAssertions; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Xunit; /// /// Alarms server node tests /// /// public class AlarmServerTests { public AlarmServerTests(Func> services, T connection) { _services = services; _connection = connection; } public async Task BrowseAreaPathTestAsync(CancellationToken ct = default) { var services = _services(); var results = await services.BrowsePathAsync(_connection, new BrowsePathRequestModel { NodeId = Opc.Ua.ObjectIds.Server.ToString(), BrowsePaths = new[] { new[] { Namespaces.AlarmCondition + "#Green", Namespaces.AlarmCondition + "#East", Namespaces.AlarmCondition + "#Blue" } } }, ct).ConfigureAwait(false); Assert.Null(results.ErrorInfo); var target = Assert.Single(results.Targets!); Assert.NotNull(target.BrowsePath); Assert.NotNull(target.Target); Assert.Equal("http://opcfoundation.org/AlarmCondition#s=0%3aEast%2fBlue", target.Target.NodeId); } public async Task BrowseMetalsSouthMotorTestAsync(CancellationToken ct = default) { var services = _services(); var results = await services.BrowsePathAsync(_connection, new BrowsePathRequestModel { NodeId = Opc.Ua.ObjectIds.Server.ToString(), BrowsePaths = new[] { new[] { Namespaces.AlarmCondition + "#Green", Namespaces.AlarmCondition + "#East", Namespaces.AlarmCondition + "#Blue", Namespaces.AlarmCondition + "#SouthMotor" } } }, ct).ConfigureAwait(false); Assert.Null(results.ErrorInfo); var target = Assert.Single(results.Targets!); Assert.NotNull(target.BrowsePath); Assert.NotNull(target.Target); Assert.Equal("http://opcfoundation.org/AlarmCondition#s=1%3aMetals%2fSouthMotor", target.Target.NodeId); } public async Task BrowseColoursEastTankTestAsync(CancellationToken ct = default) { var services = _services(); var results = await services.BrowsePathAsync(_connection, new BrowsePathRequestModel { NodeId = Opc.Ua.ObjectIds.Server.ToString(), BrowsePaths = new[] { new[] { Namespaces.AlarmCondition + "#Yellow", Namespaces.AlarmCondition + "#West", Namespaces.AlarmCondition + "#Blue", Namespaces.AlarmCondition + "#EastTank" } } }, ct).ConfigureAwait(false); Assert.Null(results.ErrorInfo); var target = Assert.Single(results.Targets!); Assert.NotNull(target.BrowsePath); Assert.NotNull(target.Target); Assert.Equal("http://opcfoundation.org/AlarmCondition#s=1%3aColours%2fEastTank", target.Target.NodeId); } public async Task CompileSimpleBaseEventQueryTestAsync(CancellationToken ct = default) { var services = _services(); var result = await services.CompileQueryAsync(_connection, new QueryCompilationRequestModel { Query = "select * from BaseEventType", QueryType = QueryType.Event }, ct).ConfigureAwait(false); Assert.NotNull(result); Assert.Null(result.ErrorInfo); var expected = new EventFilterModel { SelectClauses = new List { new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/EventId" }, AttributeId = NodeAttribute.Value, DisplayName = "/EventId.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/EventType" }, AttributeId = NodeAttribute.Value, DisplayName = "/EventType.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/SourceNode" }, AttributeId = NodeAttribute.Value, DisplayName = "/SourceNode.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/SourceName" }, AttributeId = NodeAttribute.Value, DisplayName = "/SourceName.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/Time" }, AttributeId = NodeAttribute.Value, DisplayName = "/Time.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/ReceiveTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/ReceiveTime.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/LocalTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/LocalTime.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/Message" }, AttributeId = NodeAttribute.Value, DisplayName = "/Message.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/Severity" }, AttributeId = NodeAttribute.Value, DisplayName = "/Severity.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/ConditionClassId" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionClassId.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/ConditionClassName" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionClassName.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/ConditionSubClassId" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionSubClassId.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/ConditionSubClassName" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionSubClassName.Value" } } }; result.EventFilter.Should().BeEquivalentTo(expected); } public async Task CompileSimpleTripAlarmQueryTestAsync(CancellationToken ct = default) { var services = _services(); var result = await services.CompileQueryAsync(_connection, new QueryCompilationRequestModel { Query = "select * from TripAlarmType", QueryType = QueryType.Event }, ct).ConfigureAwait(false); Assert.NotNull(result); Assert.Null(result.ErrorInfo); var expected = new EventFilterModel { SelectClauses = new List { new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/EventId" }, AttributeId = NodeAttribute.Value, DisplayName = "/EventId.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/EventType" }, AttributeId = NodeAttribute.Value, DisplayName = "/EventType.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/SourceNode" }, AttributeId = NodeAttribute.Value, DisplayName = "/SourceNode.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/SourceName" }, AttributeId = NodeAttribute.Value, DisplayName = "/SourceName.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/Time" }, AttributeId = NodeAttribute.Value, DisplayName = "/Time.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/ReceiveTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/ReceiveTime.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/LocalTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/LocalTime.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/Message" }, AttributeId = NodeAttribute.Value, DisplayName = "/Message.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/Severity" }, AttributeId = NodeAttribute.Value, DisplayName = "/Severity.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/ConditionClassId" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionClassId.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/ConditionClassName" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionClassName.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/ConditionSubClassId" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionSubClassId.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/ConditionSubClassName" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionSubClassName.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/ConditionName" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionName.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/BranchId" }, AttributeId = NodeAttribute.Value, DisplayName = "/BranchId.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/Retain" }, AttributeId = NodeAttribute.Value, DisplayName = "/Retain.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/SupportsFilteredRetain" }, AttributeId = NodeAttribute.Value, DisplayName = "/SupportsFilteredRetain.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/EnabledState" }, AttributeId = NodeAttribute.Value, DisplayName = "/EnabledState.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/EnabledState", "/Id" }, AttributeId = NodeAttribute.Value, DisplayName = "/EnabledState/Id.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/EnabledState", "/EffectiveDisplayName" }, AttributeId = NodeAttribute.Value, DisplayName = "/EnabledState/EffectiveDisplayName.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/EnabledState", "/TransitionTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/EnabledState/TransitionTime.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/EnabledState", "/EffectiveTransitionTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/EnabledState/EffectiveTransitionTime.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/Quality" }, AttributeId = NodeAttribute.Value, DisplayName = "/Quality.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/Quality", "/SourceTimestamp" }, AttributeId = NodeAttribute.Value, DisplayName = "/Quality/SourceTimestamp.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/LastSeverity" }, AttributeId = NodeAttribute.Value, DisplayName = "/LastSeverity.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/LastSeverity", "/SourceTimestamp" }, AttributeId = NodeAttribute.Value, DisplayName = "/LastSeverity/SourceTimestamp.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/Comment" }, AttributeId = NodeAttribute.Value, DisplayName = "/Comment.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/Comment", "/SourceTimestamp" }, AttributeId = NodeAttribute.Value, DisplayName = "/Comment/SourceTimestamp.Value" }, new() { TypeDefinitionId = "i=2881", BrowsePath = new[] { "/AckedState" }, AttributeId = NodeAttribute.Value, DisplayName = "/AckedState.Value" }, new() { TypeDefinitionId = "i=2881", BrowsePath = new[] { "/AckedState", "/Id" }, AttributeId = NodeAttribute.Value, DisplayName = "/AckedState/Id.Value" }, new() { TypeDefinitionId = "i=2881", BrowsePath = new[] { "/AckedState", "/TransitionTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/AckedState/TransitionTime.Value" }, new() { TypeDefinitionId = "i=2881", BrowsePath = new[] { "/ConfirmedState" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConfirmedState.Value" }, new() { TypeDefinitionId = "i=2881", BrowsePath = new[] { "/ConfirmedState", "/Id" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConfirmedState/Id.Value" }, new() { TypeDefinitionId = "i=2881", BrowsePath = new[] { "/ConfirmedState", "/TransitionTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConfirmedState/TransitionTime.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ActiveState" }, AttributeId = NodeAttribute.Value, DisplayName = "/ActiveState.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ActiveState", "/Id" }, AttributeId = NodeAttribute.Value, DisplayName = "/ActiveState/Id.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ActiveState", "/EffectiveDisplayName" }, AttributeId = NodeAttribute.Value, DisplayName = "/ActiveState/EffectiveDisplayName.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ActiveState", "/TransitionTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/ActiveState/TransitionTime.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ActiveState", "/EffectiveTransitionTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/ActiveState/EffectiveTransitionTime.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/InputNode" }, AttributeId = NodeAttribute.Value, DisplayName = "/InputNode.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/SuppressedState" }, AttributeId = NodeAttribute.Value, DisplayName = "/SuppressedState.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/SuppressedState", "/Id" }, AttributeId = NodeAttribute.Value, DisplayName = "/SuppressedState/Id.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/SuppressedState", "/TransitionTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/SuppressedState/TransitionTime.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/OutOfServiceState" }, AttributeId = NodeAttribute.Value, DisplayName = "/OutOfServiceState.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/OutOfServiceState", "/Id" }, AttributeId = NodeAttribute.Value, DisplayName = "/OutOfServiceState/Id.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/OutOfServiceState", "/TransitionTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/OutOfServiceState/TransitionTime.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ShelvingState" }, AttributeId = NodeAttribute.Value, DisplayName = "/ShelvingState.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ShelvingState", "/CurrentState" }, AttributeId = NodeAttribute.Value, DisplayName = "/ShelvingState/CurrentState.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ShelvingState", "/CurrentState", "/Id" }, AttributeId = NodeAttribute.Value, DisplayName = "/ShelvingState/CurrentState/Id.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ShelvingState", "/LastTransition" }, AttributeId = NodeAttribute.Value, DisplayName = "/ShelvingState/LastTransition.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ShelvingState", "/LastTransition", "/Id" }, AttributeId = NodeAttribute.Value, DisplayName = "/ShelvingState/LastTransition/Id.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ShelvingState", "/LastTransition", "/TransitionTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/ShelvingState/LastTransition/TransitionTime.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ShelvingState", "/UnshelveTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/ShelvingState/UnshelveTime.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ShelvingState", "/TimedShelve" }, AttributeId = NodeAttribute.Value, DisplayName = "/ShelvingState/TimedShelve.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ShelvingState", "/TimedShelve", "/InputArguments" }, AttributeId = NodeAttribute.Value, DisplayName = "/ShelvingState/TimedShelve/InputArguments.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ShelvingState", "/Unshelve" }, AttributeId = NodeAttribute.Value, DisplayName = "/ShelvingState/Unshelve.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ShelvingState", "/OneShotShelve" }, AttributeId = NodeAttribute.Value, DisplayName = "/ShelvingState/OneShotShelve.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/SuppressedOrShelved" }, AttributeId = NodeAttribute.Value, DisplayName = "/SuppressedOrShelved.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/MaxTimeShelved" }, AttributeId = NodeAttribute.Value, DisplayName = "/MaxTimeShelved.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/AudibleEnabled" }, AttributeId = NodeAttribute.Value, DisplayName = "/AudibleEnabled.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/AudibleSound" }, AttributeId = NodeAttribute.Value, DisplayName = "/AudibleSound.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/SilenceState" }, AttributeId = NodeAttribute.Value, DisplayName = "/SilenceState.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/SilenceState", "/Id" }, AttributeId = NodeAttribute.Value, DisplayName = "/SilenceState/Id.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/SilenceState", "/TransitionTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/SilenceState/TransitionTime.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/OnDelay" }, AttributeId = NodeAttribute.Value, DisplayName = "/OnDelay.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/OffDelay" }, AttributeId = NodeAttribute.Value, DisplayName = "/OffDelay.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/FirstInGroupFlag" }, AttributeId = NodeAttribute.Value, DisplayName = "/FirstInGroupFlag.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/FirstInGroup" }, AttributeId = NodeAttribute.Value, DisplayName = "/FirstInGroup.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/LatchedState" }, AttributeId = NodeAttribute.Value, DisplayName = "/LatchedState.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/LatchedState", "/Id" }, AttributeId = NodeAttribute.Value, DisplayName = "/LatchedState/Id.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/LatchedState", "/TransitionTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/LatchedState/TransitionTime.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/%3cAlarmGroup%3e" }, AttributeId = NodeAttribute.Value, DisplayName = "/.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ReAlarmTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/ReAlarmTime.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ReAlarmRepeatCount" }, AttributeId = NodeAttribute.Value, DisplayName = "/ReAlarmRepeatCount.Value" }, new() { TypeDefinitionId = "i=10637", BrowsePath = new[] { "/NormalState" }, AttributeId = NodeAttribute.Value, DisplayName = "/NormalState.Value" } } }; result.EventFilter.Should().BeEquivalentTo(expected); } public async Task CompileAlarmQueryTest1Async(CancellationToken ct = default) { var services = _services(); var result = await services.CompileQueryAsync(_connection, new QueryCompilationRequestModel { Query = @" PREFIX ac SELECT /Comment, /Severity, /SourceNode FROM TripAlarmType, BaseEventType WHERE OFTYPE TripAlarmType AND /SourceNode IN ('ac:s=1%3aMetals%2fSouthMotor'^^NodeId) ", QueryType = QueryType.Event }, ct).ConfigureAwait(false); Assert.NotNull(result); Assert.Null(result.ErrorInfo); var expected = new EventFilterModel { SelectClauses = new List { new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/Comment" }, AttributeId = NodeAttribute.Value, DisplayName = "/Comment.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/Severity" }, AttributeId = NodeAttribute.Value, DisplayName = "/Severity.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/SourceNode" }, AttributeId = NodeAttribute.Value, DisplayName = "/SourceNode.Value" } }, WhereClause = new ContentFilterModel { Elements = new List { new() { FilterOperator = FilterOperatorType.And, FilterOperands = new [] { new FilterOperandModel { Index = 1 }, new FilterOperandModel { Index = 2 } } }, new() { FilterOperator = FilterOperatorType.InList, FilterOperands = new List { new() { NodeId = "i=2041", BrowsePath = new[] { "/SourceNode" }, AttributeId = NodeAttribute.Value }, new() { Value = "http://opcfoundation.org/AlarmCondition#s=1%3aMetals%2fSouthMotor", DataType = "NodeId" } } }, new() { FilterOperator = FilterOperatorType.OfType, FilterOperands = new List { new() { Value = "i=10751", DataType = "NodeId" } } } } } }; result.EventFilter.Should().BeEquivalentTo(expected); } public async Task CompileAlarmQueryTest2Async(CancellationToken ct = default) { var services = _services(); var result = await services.CompileQueryAsync(_connection, new QueryCompilationRequestModel { Query = @" PREFIX ac SELECT * FROM BaseEventType, TripAlarmType WHERE OFTYPE TripAlarmType AND /SourceNode IN ('ac:s=1%3aMetals%2fSouthMotor'^^NodeId) ", QueryType = QueryType.Event }, ct).ConfigureAwait(false); Assert.NotNull(result); Assert.Null(result.ErrorInfo); var expected = new EventFilterModel { SelectClauses = new List { new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/EventId" }, AttributeId = NodeAttribute.Value, DisplayName = "/EventId.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/EventType" }, AttributeId = NodeAttribute.Value, DisplayName = "/EventType.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/SourceNode" }, AttributeId = NodeAttribute.Value, DisplayName = "/SourceNode.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/SourceName" }, AttributeId = NodeAttribute.Value, DisplayName = "/SourceName.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/Time" }, AttributeId = NodeAttribute.Value, DisplayName = "/Time.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/ReceiveTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/ReceiveTime.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/LocalTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/LocalTime.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/Message" }, AttributeId = NodeAttribute.Value, DisplayName = "/Message.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/Severity" }, AttributeId = NodeAttribute.Value, DisplayName = "/Severity.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/ConditionClassId" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionClassId.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/ConditionClassName" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionClassName.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/ConditionSubClassId" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionSubClassId.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/ConditionSubClassName" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionSubClassName.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/ConditionClassId" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionClassId.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/ConditionClassName" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionClassName.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/ConditionSubClassId" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionSubClassId.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/ConditionSubClassName" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionSubClassName.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/ConditionName" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionName.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/BranchId" }, AttributeId = NodeAttribute.Value, DisplayName = "/BranchId.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/Retain" }, AttributeId = NodeAttribute.Value, DisplayName = "/Retain.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/SupportsFilteredRetain" }, AttributeId = NodeAttribute.Value, DisplayName = "/SupportsFilteredRetain.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/EnabledState" }, AttributeId = NodeAttribute.Value, DisplayName = "/EnabledState.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/EnabledState", "/Id" }, AttributeId = NodeAttribute.Value, DisplayName = "/EnabledState/Id.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/EnabledState", "/EffectiveDisplayName" }, AttributeId = NodeAttribute.Value, DisplayName = "/EnabledState/EffectiveDisplayName.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/EnabledState", "/TransitionTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/EnabledState/TransitionTime.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/EnabledState", "/EffectiveTransitionTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/EnabledState/EffectiveTransitionTime.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/Quality" }, AttributeId = NodeAttribute.Value, DisplayName = "/Quality.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/Quality", "/SourceTimestamp" }, AttributeId = NodeAttribute.Value, DisplayName = "/Quality/SourceTimestamp.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/LastSeverity" }, AttributeId = NodeAttribute.Value, DisplayName = "/LastSeverity.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/LastSeverity", "/SourceTimestamp" }, AttributeId = NodeAttribute.Value, DisplayName = "/LastSeverity/SourceTimestamp.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/Comment" }, AttributeId = NodeAttribute.Value, DisplayName = "/Comment.Value" }, new() { TypeDefinitionId = "i=2782", BrowsePath = new[] { "/Comment", "/SourceTimestamp" }, AttributeId = NodeAttribute.Value, DisplayName = "/Comment/SourceTimestamp.Value" }, new() { TypeDefinitionId = "i=2881", BrowsePath = new[] { "/AckedState" }, AttributeId = NodeAttribute.Value, DisplayName = "/AckedState.Value" }, new() { TypeDefinitionId = "i=2881", BrowsePath = new[] { "/AckedState", "/Id" }, AttributeId = NodeAttribute.Value, DisplayName = "/AckedState/Id.Value" }, new() { TypeDefinitionId = "i=2881", BrowsePath = new[] { "/AckedState", "/TransitionTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/AckedState/TransitionTime.Value" }, new() { TypeDefinitionId = "i=2881", BrowsePath = new[] { "/ConfirmedState" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConfirmedState.Value" }, new() { TypeDefinitionId = "i=2881", BrowsePath = new[] { "/ConfirmedState", "/Id" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConfirmedState/Id.Value" }, new() { TypeDefinitionId = "i=2881", BrowsePath = new[] { "/ConfirmedState", "/TransitionTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConfirmedState/TransitionTime.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ActiveState" }, AttributeId = NodeAttribute.Value, DisplayName = "/ActiveState.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ActiveState", "/Id" }, AttributeId = NodeAttribute.Value, DisplayName = "/ActiveState/Id.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ActiveState", "/EffectiveDisplayName" }, AttributeId = NodeAttribute.Value, DisplayName = "/ActiveState/EffectiveDisplayName.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ActiveState", "/TransitionTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/ActiveState/TransitionTime.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ActiveState", "/EffectiveTransitionTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/ActiveState/EffectiveTransitionTime.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/InputNode" }, AttributeId = NodeAttribute.Value, DisplayName = "/InputNode.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/SuppressedState" }, AttributeId = NodeAttribute.Value, DisplayName = "/SuppressedState.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/SuppressedState", "/Id" }, AttributeId = NodeAttribute.Value, DisplayName = "/SuppressedState/Id.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/SuppressedState", "/TransitionTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/SuppressedState/TransitionTime.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/OutOfServiceState" }, AttributeId = NodeAttribute.Value, DisplayName = "/OutOfServiceState.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/OutOfServiceState", "/Id" }, AttributeId = NodeAttribute.Value, DisplayName = "/OutOfServiceState/Id.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/OutOfServiceState", "/TransitionTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/OutOfServiceState/TransitionTime.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ShelvingState" }, AttributeId = NodeAttribute.Value, DisplayName = "/ShelvingState.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ShelvingState", "/CurrentState" }, AttributeId = NodeAttribute.Value, DisplayName = "/ShelvingState/CurrentState.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ShelvingState", "/CurrentState", "/Id" }, AttributeId = NodeAttribute.Value, DisplayName = "/ShelvingState/CurrentState/Id.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ShelvingState", "/LastTransition" }, AttributeId = NodeAttribute.Value, DisplayName = "/ShelvingState/LastTransition.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ShelvingState", "/LastTransition", "/Id" }, AttributeId = NodeAttribute.Value, DisplayName = "/ShelvingState/LastTransition/Id.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ShelvingState", "/LastTransition", "/TransitionTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/ShelvingState/LastTransition/TransitionTime.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ShelvingState", "/UnshelveTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/ShelvingState/UnshelveTime.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ShelvingState", "/TimedShelve" }, AttributeId = NodeAttribute.Value, DisplayName = "/ShelvingState/TimedShelve.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ShelvingState", "/TimedShelve", "/InputArguments" }, AttributeId = NodeAttribute.Value, DisplayName = "/ShelvingState/TimedShelve/InputArguments.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ShelvingState", "/Unshelve" }, AttributeId = NodeAttribute.Value, DisplayName = "/ShelvingState/Unshelve.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ShelvingState", "/OneShotShelve" }, AttributeId = NodeAttribute.Value, DisplayName = "/ShelvingState/OneShotShelve.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/SuppressedOrShelved" }, AttributeId = NodeAttribute.Value, DisplayName = "/SuppressedOrShelved.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/MaxTimeShelved" }, AttributeId = NodeAttribute.Value, DisplayName = "/MaxTimeShelved.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/AudibleEnabled" }, AttributeId = NodeAttribute.Value, DisplayName = "/AudibleEnabled.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/AudibleSound" }, AttributeId = NodeAttribute.Value, DisplayName = "/AudibleSound.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/SilenceState" }, AttributeId = NodeAttribute.Value, DisplayName = "/SilenceState.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/SilenceState", "/Id" }, AttributeId = NodeAttribute.Value, DisplayName = "/SilenceState/Id.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/SilenceState", "/TransitionTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/SilenceState/TransitionTime.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/OnDelay" }, AttributeId = NodeAttribute.Value, DisplayName = "/OnDelay.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/OffDelay" }, AttributeId = NodeAttribute.Value, DisplayName = "/OffDelay.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/FirstInGroupFlag" }, AttributeId = NodeAttribute.Value, DisplayName = "/FirstInGroupFlag.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/FirstInGroup" }, AttributeId = NodeAttribute.Value, DisplayName = "/FirstInGroup.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/LatchedState" }, AttributeId = NodeAttribute.Value, DisplayName = "/LatchedState.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/LatchedState", "/Id" }, AttributeId = NodeAttribute.Value, DisplayName = "/LatchedState/Id.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/LatchedState", "/TransitionTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/LatchedState/TransitionTime.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/%3cAlarmGroup%3e" }, AttributeId = NodeAttribute.Value, DisplayName = "/.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ReAlarmTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/ReAlarmTime.Value" }, new() { TypeDefinitionId = "i=2915", BrowsePath = new[] { "/ReAlarmRepeatCount" }, AttributeId = NodeAttribute.Value, DisplayName = "/ReAlarmRepeatCount.Value" }, new() { TypeDefinitionId = "i=10637", BrowsePath = new[] { "/NormalState" }, AttributeId = NodeAttribute.Value, DisplayName = "/NormalState.Value" } }, WhereClause = new ContentFilterModel { Elements = new List { new() { FilterOperator = FilterOperatorType.And, FilterOperands = new [] { new FilterOperandModel { Index = 1u }, new FilterOperandModel { Index = 2u } } }, new() { FilterOperator = FilterOperatorType.InList, FilterOperands = new [] { new FilterOperandModel { NodeId = "i=2041", BrowsePath = new[] { "/SourceNode" }, AttributeId = NodeAttribute.Value }, new FilterOperandModel { Value = "http://opcfoundation.org/AlarmCondition#s=1%3aMetals%2fSouthMotor", DataType = "NodeId" } } }, new() { FilterOperator = FilterOperatorType.OfType, FilterOperands = new [] { new FilterOperandModel { Value = "i=10751", DataType = "NodeId" } } } } } }; result.EventFilter.Should().BeEquivalentTo(expected); } private readonly T _connection; private readonly Func> _services; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/Asset/AssetTests1.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Config.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Moq; using Moq.Language.Flow; using System; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Xunit; public class AssetTests1 { /// /// Create configuration tests /// /// /// /// public AssetTests1(Func> services, ConnectionModel connection, bool verify = true) { _verify = verify; _service = services; _connection = connection; _publishedNodesServices = new Mock(); _createCall = _publishedNodesServices.Setup(s => s.CreateOrUpdateDataSetWriterEntryAsync( It.IsAny(), It.IsAny())) .Returns(Task.CompletedTask); _deleteCall = _publishedNodesServices.Setup(s => s.RemoveDataSetWriterEntryAsync( "WriterGroup1", It.IsAny(), false, It.IsAny())) .Returns(Task.CompletedTask); } public async Task ConfigureAndDeleteAssetsAsync(CancellationToken ct = default) { var service = _service(_publishedNodesServices.Object); ServiceResponse result; var asset1 = _connection.ToPublishedNodesEntry(); asset1.DataSetWriterGroup = "WriterGroup1"; asset1.DataSetName = "Sim3264Asset"; _createCall.Verifiable(Times.Exactly(2)); _deleteCall.Verifiable(Times.Once); const string Asset1 = """ { "@context": [ "https://www.w3.org/2022/wot/td/v1.1" ], "id": "urn:sim3264", "securityDefinitions": { "nosec_sc": { "scheme": "nosec" } }, "security": [ "nosec_sc" ], "@type": [ "Thing" ], "name": "sim-3264", "base": "sim://simserver1:443", "title": "Simulated Asset", "properties": { "VoltageL1-N": { "type": "number", "opcua:nodeId": "s=VoltageL-N", "readOnly": true, "observable": true, "forms": [ { "href": "1", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL2-N": { "type": "number", "opcua:nodeId": "s=VoltageL-N", "readOnly": true, "observable": true, "forms": [ { "href": "3", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL3-N": { "type": "number", "opcua:nodeId": "s=VoltageL-N", "readOnly": true, "observable": true, "forms": [ { "href": "5", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL1-L2": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "7", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL2-L3": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "9", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL3-L1": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "11", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "CurrentL1": { "type": "number", "opcua:nodeId": "s=Current", "readOnly": true, "observable": true, "forms": [ { "href": "13", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "CurrentL2": { "type": "number", "opcua:nodeId": "s=Current", "readOnly": true, "observable": true, "forms": [ { "href": "15", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "CurrentL3": { "type": "number", "opcua:nodeId": "s=Current", "readOnly": true, "observable": true, "forms": [ { "href": "17", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "PowerFactorL1": { "type": "number", "opcua:nodeId": "s=PowerFactor", "readOnly": true, "observable": true, "forms": [ { "href": "19", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "PowerFactorL2": { "type": "number", "opcua:nodeId": "s=PowerFactor", "readOnly": true, "observable": true, "forms": [ { "href": "139", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "PowerFactorL3": { "type": "number", "opcua:nodeId": "s=PowerFactor", "readOnly": true, "observable": true, "forms": [ { "href": "141", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalApparentPower": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "63", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalActivePower": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "65", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalReactivePower": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "67", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalPowerFactor": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "69", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] } } } """; var stream = new MemoryStream(Encoding.UTF8.GetBytes(Asset1)); await using (var c1 = stream.ConfigureAwait(false)) { var request = new PublishedNodeCreateAssetRequestModel { Configuration = stream, Entry = asset1 }; result = await service.CreateOrUpdateAssetAsync( request, ct).ConfigureAwait(false); Assert.Null(result.ErrorInfo); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); Assert.Equal(16, result.Result.OpcNodes.Count); Assert.Equal("nsu=http://opcfoundation.org/AssetServer;i=1", result.Result.DataSetWriterId); asset1 = result.Result; } var asset2 = _connection.ToPublishedNodesEntry(); asset2.DataSetWriterGroup = "WriterGroup1"; asset2.DataSetName = "Sim3265Asset"; const string Asset2 = """ { "@context": [ "https://www.w3.org/2022/wot/td/v1.1" ], "id": "urn:sim3265", "securityDefinitions": { "nosec_sc": { "scheme": "nosec" } }, "security": [ "nosec_sc" ], "@type": [ "Thing" ], "name": "sim-3264", "base": "sim://simserver1:443", "title": "Simulated Asset", "properties": { "VoltageL1-N": { "type": "number", "opcua:nodeId": "s=VoltageL-N", "readOnly": true, "observable": true, "forms": [ { "href": "1", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL2-N": { "type": "number", "opcua:nodeId": "s=VoltageL-N", "readOnly": true, "observable": true, "forms": [ { "href": "3", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL3-N": { "type": "number", "opcua:nodeId": "s=VoltageL-N", "readOnly": true, "observable": true, "forms": [ { "href": "5", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL1-L2": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "7", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL2-L3": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "9", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL3-L1": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "11", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "CurrentL1": { "type": "number", "opcua:nodeId": "s=Current", "readOnly": true, "observable": true, "forms": [ { "href": "13", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "CurrentL2": { "type": "number", "opcua:nodeId": "s=Current", "readOnly": true, "observable": true, "forms": [ { "href": "15", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "CurrentL3": { "type": "number", "opcua:nodeId": "s=Current", "readOnly": true, "observable": true, "forms": [ { "href": "17", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "PowerFactorL1": { "type": "number", "opcua:nodeId": "s=PowerFactor", "readOnly": true, "observable": true, "forms": [ { "href": "19", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "PowerFactorL2": { "type": "number", "opcua:nodeId": "s=PowerFactor", "readOnly": true, "observable": true, "forms": [ { "href": "139", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "PowerFactorL3": { "type": "number", "opcua:nodeId": "s=PowerFactor", "readOnly": true, "observable": true, "forms": [ { "href": "141", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalApparentPower": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "63", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalActivePower": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "65", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalReactivePower": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "67", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalPowerFactor": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "69", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] } } } """; var stream2 = new MemoryStream(Encoding.UTF8.GetBytes(Asset2)); await using (var c2 = stream2.ConfigureAwait(false)) { var request = new PublishedNodeCreateAssetRequestModel { Configuration = stream2, Entry = asset2 }; result = await service.CreateOrUpdateAssetAsync( request, ct).ConfigureAwait(false); Assert.Null(result.ErrorInfo); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); Assert.Equal(16, result.Result.OpcNodes.Count); Assert.Equal("nsu=http://opcfoundation.org/AssetServer;i=24", result.Result.DataSetWriterId); asset2 = result.Result; } // Now we have 2 assets created var results = await service.GetAllAssetsAsync(result.Result, ct: ct) .ToListAsync(ct).ConfigureAwait(false); Assert.Equal(2, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.Equal(16, r.Result.OpcNodes.Count); }); var errorInfo = await service.DeleteAssetAsync( new PublishedNodeDeleteAssetRequestModel { Entry = asset2 }, ct).ConfigureAwait(false); Assert.NotNull(errorInfo); Assert.Equal(0u, errorInfo.StatusCode); // Now we have 1 asset remaining results = await service.GetAllAssetsAsync(asset1, ct: ct) .ToListAsync(ct).ConfigureAwait(false); var remainingAsset = Assert.Single(results); Assert.Null(remainingAsset.ErrorInfo); Assert.NotNull(remainingAsset.Result); Assert.NotNull(remainingAsset.Result.OpcNodes); Assert.Equal(16, remainingAsset.Result.OpcNodes.Count); Verify(); } private void Verify() { if (_verify) { _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } } private readonly ConnectionModel _connection; private readonly bool _verify; private readonly Mock _publishedNodesServices; private readonly IReturnsResult _createCall; private readonly IReturnsResult _deleteCall; private readonly Func> _service; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/Asset/AssetTests2.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Config.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Moq; using Moq.Language.Flow; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Xunit; public class AssetTests2 { /// /// Create configuration tests /// /// /// /// public AssetTests2(Func> services, ConnectionModel connection, bool verify = true) { _verify = verify; _service = services; _connection = connection; _publishedNodesServices = new Mock(); _createCall = _publishedNodesServices.Setup(s => s.CreateOrUpdateDataSetWriterEntryAsync( It.IsAny(), It.IsAny())) .Returns(Task.CompletedTask); _deleteCall = _publishedNodesServices.Setup(s => s.RemoveDataSetWriterEntryAsync( "WriterGroup1", It.IsAny(), false, It.IsAny())) .Returns(Task.CompletedTask); } public async Task ConfigureAsset1Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.DataSetWriterGroup = "WriterGroup1"; entry.DataSetName = "Sim3264Asset"; const string Asset1 = """ { "@context": [ "https://www.w3.org/2022/wot/td/v1.1" ], "id": "urn:sim3264", "securityDefinitions": { "nosec_sc": { "scheme": "nosec" } }, "security": [ "nosec_sc" ], "@type": [ "Thing" ], "name": "sim-3264", "base": "sim://simserver1:443", "title": "Simulated Asset", "properties": { "VoltageL1-N": { "type": "number", "opcua:nodeId": "s=VoltageL-N", "readOnly": true, "observable": true, "forms": [ { "href": "1", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL2-N": { "type": "number", "opcua:nodeId": "s=VoltageL-N", "readOnly": true, "observable": true, "forms": [ { "href": "3", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL3-N": { "type": "number", "opcua:nodeId": "s=VoltageL-N", "readOnly": true, "observable": true, "forms": [ { "href": "5", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL1-L2": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "7", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL2-L3": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "9", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL3-L1": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "11", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "CurrentL1": { "type": "number", "opcua:nodeId": "s=Current", "readOnly": true, "observable": true, "forms": [ { "href": "13", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "CurrentL2": { "type": "number", "opcua:nodeId": "s=Current", "readOnly": true, "observable": true, "forms": [ { "href": "15", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "CurrentL3": { "type": "number", "opcua:nodeId": "s=Current", "readOnly": true, "observable": true, "forms": [ { "href": "17", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "PowerFactorL1": { "type": "number", "opcua:nodeId": "s=PowerFactor", "readOnly": true, "observable": true, "forms": [ { "href": "19", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "PowerFactorL2": { "type": "number", "opcua:nodeId": "s=PowerFactor", "readOnly": true, "observable": true, "forms": [ { "href": "139", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "PowerFactorL3": { "type": "number", "opcua:nodeId": "s=PowerFactor", "readOnly": true, "observable": true, "forms": [ { "href": "141", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalApparentPower": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "63", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalActivePower": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "65", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalReactivePower": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "67", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalPowerFactor": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "69", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] } } } """; var stream = new MemoryStream(Encoding.UTF8.GetBytes(Asset1)); await using var _ = stream.ConfigureAwait(false); var request = new PublishedNodeCreateAssetRequestModel { Configuration = stream, Entry = entry }; _createCall.Verifiable(Times.Once); var result = await _service(_publishedNodesServices.Object).CreateOrUpdateAssetAsync( request, ct).ConfigureAwait(false); Assert.Null(result.ErrorInfo); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); Assert.Equal(16, result.Result.OpcNodes.Count); Assert.StartsWith("nsu=http://opcfoundation.org/AssetServer;i=", result.Result.DataSetWriterId, StringComparison.Ordinal); Verify(); } public async Task ConfigureAsset2Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.DataSetWriterGroup = "WriterGroup1"; entry.DataSetName = "Sim3265Asset"; const string Asset2 = """ { "@context": [ "https://www.w3.org/2022/wot/td/v1.1" ], "id": "urn:sim3265", "securityDefinitions": { "nosec_sc": { "scheme": "nosec" } }, "security": [ "nosec_sc" ], "@type": [ "Thing" ], "name": "sim-3265", "base": "sim://simserver1:443", "title": "Simulated Asset", "properties": { "VoltageL1-N": { "type": "number", "opcua:nodeId": "s=VoltageL-N", "readOnly": true, "observable": true, "forms": [ { "href": "1", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL2-N": { "type": "number", "opcua:nodeId": "s=VoltageL-N", "readOnly": true, "observable": true, "forms": [ { "href": "3", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL3-N": { "type": "number", "opcua:nodeId": "s=VoltageL-N", "readOnly": true, "observable": true, "forms": [ { "href": "5", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL1-L2": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "7", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL2-L3": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "9", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL3-L1": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "11", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "CurrentL1": { "type": "number", "opcua:nodeId": "s=Current", "readOnly": true, "observable": true, "forms": [ { "href": "13", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "CurrentL2": { "type": "number", "opcua:nodeId": "s=Current", "readOnly": true, "observable": true, "forms": [ { "href": "15", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "CurrentL3": { "type": "number", "opcua:nodeId": "s=Current", "readOnly": true, "observable": true, "forms": [ { "href": "17", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "PowerFactorL1": { "type": "number", "opcua:nodeId": "s=PowerFactor", "readOnly": true, "observable": true, "forms": [ { "href": "19", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "PowerFactorL2": { "type": "number", "opcua:nodeId": "s=PowerFactor", "readOnly": true, "observable": true, "forms": [ { "href": "139", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "PowerFactorL3": { "type": "number", "opcua:nodeId": "s=PowerFactor", "readOnly": true, "observable": true, "forms": [ { "href": "141", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalApparentPower": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "63", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalActivePower": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "65", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalReactivePower": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "67", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalPowerFactor": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "69", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] } } } """; var stream = new MemoryStream(Encoding.UTF8.GetBytes(Asset2)); await using var _ = stream.ConfigureAwait(false); var request = new PublishedNodeCreateAssetRequestModel { Configuration = stream, Entry = entry }; _createCall.Verifiable(Times.Once); _deleteCall.Verifiable(Times.Once); var result = await _service(_publishedNodesServices.Object).CreateOrUpdateAssetAsync( request, ct).ConfigureAwait(false); Assert.Null(result.ErrorInfo); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); Assert.Equal(16, result.Result.OpcNodes.Count); Assert.StartsWith("nsu=http://opcfoundation.org/AssetServer;i=", result.Result.DataSetWriterId, StringComparison.Ordinal); var errorInfo = await _service(_publishedNodesServices.Object).DeleteAssetAsync( new PublishedNodeDeleteAssetRequestModel { Entry = result.Result }, ct).ConfigureAwait(false); Assert.Null(result.ErrorInfo); Verify(); } public async Task ConfigureAsset3Async(CancellationToken ct = default) { var service = _service(_publishedNodesServices.Object); const string Template = """ { "@context": [ "https://www.w3.org/2022/wot/td/v1.1" ], "id": "urn:<>", "securityDefinitions": { "nosec_sc": { "scheme": "nosec" } }, "security": [ "nosec_sc" ], "@type": [ "Thing" ], "name": "<>", "base": "sim://<>:443", "title": "Simulated Asset <>", "properties": { "AssetTag": { "type": "number", "observable": true, "forms": [ { "href": "1", "op": [ "readproperty", "writeproperty", "observeproperty" ], "sim:type": "String", "sim:pollingTime": 1000 } ] } } } """; const int NumberOfAssets = 50; const string AssetPrefix = "SimAsset__"; _createCall.Verifiable(Times.Exactly(NumberOfAssets)); _deleteCall.Verifiable(Times.Exactly(NumberOfAssets)); var assets = new List(); for (var i = 0; i < NumberOfAssets; i++) { var asset = _connection.ToPublishedNodesEntry(); asset.DataSetWriterGroup = "WriterGroup1"; asset.DataSetName = AssetPrefix + i; var t = Template.Replace("<>", "sim" + i, StringComparison.Ordinal); var stream = new MemoryStream(Encoding.UTF8.GetBytes(t)); await using var c1 = stream.ConfigureAwait(false); var request = new PublishedNodeCreateAssetRequestModel { Configuration = stream, Entry = asset }; var result = await service.CreateOrUpdateAssetAsync( request, ct).ConfigureAwait(false); AssertResult(result); assets.Add(result.Result!); } var firstAsset = assets[0]; foreach (var asset in assets.ToList()) { var results = await service.GetAllAssetsAsync(firstAsset, ct: ct) .ToListAsync(ct).ConfigureAwait(false); results = results.Where(e => e.Result?.DataSetName? .StartsWith(AssetPrefix, StringComparison.Ordinal) ?? true).ToList(); Assert.Equal(assets.Count, results.Count); Assert.All(results, AssertResult); var errorInfo = await service.DeleteAssetAsync( new PublishedNodeDeleteAssetRequestModel { Entry = asset }, ct).ConfigureAwait(false); Assert.NotNull(errorInfo); Assert.Equal(0u, errorInfo.StatusCode); assets.Remove(asset); } // Now none remaining var nothingLeft = await service.GetAllAssetsAsync(firstAsset, ct: ct) .ToListAsync(ct).ConfigureAwait(false); nothingLeft = nothingLeft.Where(e => e.Result?.DataSetName? .StartsWith(AssetPrefix, StringComparison.Ordinal) ?? true).ToList(); Assert.Empty(nothingLeft); Verify(); static void AssertResult(ServiceResponse result) { Assert.Null(result.ErrorInfo); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); Assert.StartsWith(AssetPrefix, result.Result.DataSetName, StringComparison.Ordinal); var node = Assert.Single(result.Result.OpcNodes); } } private void Verify() { if (_verify) { _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } } private readonly ConnectionModel _connection; private readonly Mock _publishedNodesServices; private readonly IReturnsResult _createCall; private readonly IReturnsResult _deleteCall; private readonly Func> _service; private readonly bool _verify; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/Asset/AssetTests3.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Config.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Moq; using Moq.Language.Flow; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Xunit; public class AssetTests3 { /// /// Create configuration tests /// /// /// /// public AssetTests3(Func> services, ConnectionModel connection, bool verify = true) { _verify = verify; _service = services; _connection = connection; _publishedNodesServices = new Mock(); _createCall = _publishedNodesServices.Setup(s => s.CreateOrUpdateDataSetWriterEntryAsync( It.IsAny(), It.IsAny())) .Returns(Task.CompletedTask); _deleteCall = _publishedNodesServices.Setup(s => s.RemoveDataSetWriterEntryAsync( "WriterGroup1", It.IsAny(), false, It.IsAny())) .Returns(Task.CompletedTask); } public async Task ConfigureAsset1Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.DataSetWriterGroup = "WriterGroup1"; entry.DataSetName = "Sim3264Asset"; const string Asset1 = """ { "@context": [ "https://www.w3.org/2022/wot/td/v1.1" ], "id": "urn:sim3264", "securityDefinitions": { "nosec_sc": { "scheme": "nosec" } }, "security": [ "nosec_sc" ], "@type": [ "Thing" ], "name": "sim-3264", "base": "sim://simserver1:443", "title": "Simulated Asset", "properties": { "VoltageL1-N": { "type": "number", "opcua:nodeId": "s=VoltageL-N", "readOnly": true, "observable": true, "forms": [ { "href": "1", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL2-N": { "type": "number", "opcua:nodeId": "s=VoltageL-N", "readOnly": true, "observable": true, "forms": [ { "href": "3", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL3-N": { "type": "number", "opcua:nodeId": "s=VoltageL-N", "readOnly": true, "observable": true, "forms": [ { "href": "5", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL1-L2": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "7", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL2-L3": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "9", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL3-L1": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "11", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "CurrentL1": { "type": "number", "opcua:nodeId": "s=Current", "readOnly": true, "observable": true, "forms": [ { "href": "13", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "CurrentL2": { "type": "number", "opcua:nodeId": "s=Current", "readOnly": true, "observable": true, "forms": [ { "href": "15", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "CurrentL3": { "type": "number", "opcua:nodeId": "s=Current", "readOnly": true, "observable": true, "forms": [ { "href": "17", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "PowerFactorL1": { "type": "number", "opcua:nodeId": "s=PowerFactor", "readOnly": true, "observable": true, "forms": [ { "href": "19", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "PowerFactorL2": { "type": "number", "opcua:nodeId": "s=PowerFactor", "readOnly": true, "observable": true, "forms": [ { "href": "139", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "PowerFactorL3": { "type": "number", "opcua:nodeId": "s=PowerFactor", "readOnly": true, "observable": true, "forms": [ { "href": "141", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalApparentPower": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "63", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalActivePower": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "65", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalReactivePower": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "67", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalPowerFactor": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "69", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] } } } """; var request = new PublishedNodeCreateAssetRequestModel { Configuration = Encoding.UTF8.GetBytes(Asset1), Entry = entry }; _createCall.Verifiable(Times.Once); var result = await _service(_publishedNodesServices.Object).CreateOrUpdateAssetAsync( request, ct).ConfigureAwait(false); Assert.Null(result.ErrorInfo); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); Assert.Equal(16, result.Result.OpcNodes.Count); Assert.StartsWith("nsu=http://opcfoundation.org/AssetServer;i=", result.Result.DataSetWriterId, StringComparison.Ordinal); Verify(); } public async Task ConfigureAsset2Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.DataSetWriterGroup = "WriterGroup1"; entry.DataSetName = "Sim3265Asset"; const string Asset2 = """ { "@context": [ "https://www.w3.org/2022/wot/td/v1.1" ], "id": "urn:sim3265", "securityDefinitions": { "nosec_sc": { "scheme": "nosec" } }, "security": [ "nosec_sc" ], "@type": [ "Thing" ], "name": "sim-3265", "base": "sim://simserver1:443", "title": "Simulated Asset", "properties": { "VoltageL1-N": { "type": "number", "opcua:nodeId": "s=VoltageL-N", "readOnly": true, "observable": true, "forms": [ { "href": "1", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL2-N": { "type": "number", "opcua:nodeId": "s=VoltageL-N", "readOnly": true, "observable": true, "forms": [ { "href": "3", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL3-N": { "type": "number", "opcua:nodeId": "s=VoltageL-N", "readOnly": true, "observable": true, "forms": [ { "href": "5", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL1-L2": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "7", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL2-L3": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "9", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "VoltageL3-L1": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "11", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "CurrentL1": { "type": "number", "opcua:nodeId": "s=Current", "readOnly": true, "observable": true, "forms": [ { "href": "13", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "CurrentL2": { "type": "number", "opcua:nodeId": "s=Current", "readOnly": true, "observable": true, "forms": [ { "href": "15", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "CurrentL3": { "type": "number", "opcua:nodeId": "s=Current", "readOnly": true, "observable": true, "forms": [ { "href": "17", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "PowerFactorL1": { "type": "number", "opcua:nodeId": "s=PowerFactor", "readOnly": true, "observable": true, "forms": [ { "href": "19", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "PowerFactorL2": { "type": "number", "opcua:nodeId": "s=PowerFactor", "readOnly": true, "observable": true, "forms": [ { "href": "139", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "PowerFactorL3": { "type": "number", "opcua:nodeId": "s=PowerFactor", "readOnly": true, "observable": true, "forms": [ { "href": "141", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalApparentPower": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "63", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalActivePower": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "65", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalReactivePower": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "67", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] }, "TotalPowerFactor": { "type": "number", "readOnly": true, "observable": true, "forms": [ { "href": "69", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] } } } """; var request = new PublishedNodeCreateAssetRequestModel { Configuration = Encoding.UTF8.GetBytes(Asset2), Entry = entry }; _createCall.Verifiable(Times.Once); _deleteCall.Verifiable(Times.Once); var result = await _service(_publishedNodesServices.Object).CreateOrUpdateAssetAsync( request, ct).ConfigureAwait(false); Assert.Null(result.ErrorInfo); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); Assert.Equal(16, result.Result.OpcNodes.Count); Assert.StartsWith("nsu=http://opcfoundation.org/AssetServer;i=", result.Result.DataSetWriterId, StringComparison.Ordinal); var errorInfo = await _service(_publishedNodesServices.Object).DeleteAssetAsync( new PublishedNodeDeleteAssetRequestModel { Entry = result.Result }, ct).ConfigureAwait(false); Assert.Null(result.ErrorInfo); Verify(); } public async Task ConfigureAsset3Async(CancellationToken ct = default) { var service = _service(_publishedNodesServices.Object); const string Template = """ { "@context": [ "https://www.w3.org/2022/wot/td/v1.1" ], "id": "urn:<>", "securityDefinitions": { "nosec_sc": { "scheme": "nosec" } }, "security": [ "nosec_sc" ], "@type": [ "Thing" ], "name": "<>", "base": "sim://<>:443", "title": "Simulated Asset <>", "properties": { "AssetTag": { "type": "number", "observable": true, "forms": [ { "href": "1", "op": [ "readproperty", "writeproperty", "observeproperty" ], "sim:type": "String", "sim:pollingTime": 1000 } ] } } } """; const int NumberOfAssets = 33; const string AssetPrefix = "SimAsset__"; _createCall.Verifiable(Times.Exactly(NumberOfAssets)); _deleteCall.Verifiable(Times.Exactly(NumberOfAssets)); var assets = new List(); for (var i = 0; i < NumberOfAssets; i++) { var asset = _connection.ToPublishedNodesEntry(); asset.DataSetWriterGroup = "WriterGroup1"; asset.DataSetName = AssetPrefix + i; var t = Template.Replace("<>", "sim" + i, StringComparison.Ordinal); var request = new PublishedNodeCreateAssetRequestModel { Configuration = Encoding.UTF8.GetBytes(t), Entry = asset }; var result = await service.CreateOrUpdateAssetAsync( request, ct).ConfigureAwait(false); AssertResult(result); assets.Add(result.Result!); } var firstAsset = assets[0]; foreach (var asset in assets.ToList()) { var results = await service.GetAllAssetsAsync(firstAsset, ct: ct) .ToListAsync(ct).ConfigureAwait(false); results = results.Where(e => e.Result?.DataSetName? .StartsWith(AssetPrefix, StringComparison.Ordinal) ?? true).ToList(); Assert.Equal(assets.Count, results.Count); Assert.All(results, AssertResult); var errorInfo = await service.DeleteAssetAsync( new PublishedNodeDeleteAssetRequestModel { Entry = asset }, ct).ConfigureAwait(false); Assert.NotNull(errorInfo); Assert.Equal(0u, errorInfo.StatusCode); assets.Remove(asset); } // Now none remaining var nothingLeft = await service.GetAllAssetsAsync(firstAsset, ct: ct) .ToListAsync(ct).ConfigureAwait(false); nothingLeft = nothingLeft.Where(e => e.Result?.DataSetName? .StartsWith(AssetPrefix, StringComparison.Ordinal) ?? true).ToList(); Assert.Empty(nothingLeft); Verify(); static void AssertResult(ServiceResponse result) { Assert.Null(result.ErrorInfo); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); Assert.StartsWith(AssetPrefix, result.Result.DataSetName, StringComparison.Ordinal); var node = Assert.Single(result.Result.OpcNodes); } } private void Verify() { if (_verify) { _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } } private readonly ConnectionModel _connection; private readonly Mock _publishedNodesServices; private readonly IReturnsResult _createCall; private readonly IReturnsResult _deleteCall; private readonly Func> _service; private readonly bool _verify; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/Asset/AssetTests4.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Config.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Moq; using System; using System.IO; using System.Text; using System.Threading; using System.Threading.Tasks; using Xunit; public class AssetTests4 { /// /// Create configuration tests /// /// /// /// public AssetTests4(Func> services, ConnectionModel connection, bool verify = true) { _verify = verify; _service = services; _connection = connection; _publishedNodesServices = new Mock(); } public async Task ConfigureDuplicateAssetFailsAsync(CancellationToken ct = default) { var asset1 = _connection.ToPublishedNodesEntry(); asset1.DataSetWriterGroup = "WriterGroup1"; asset1.DataSetName = "ConfigureDuplicateAssetFailsAsync"; var stream1 = new MemoryStream(Encoding.UTF8.GetBytes(kTestAsset)); await using (var s1 = stream1.ConfigureAwait(false)) { var request1 = new PublishedNodeCreateAssetRequestModel { Configuration = stream1, Entry = asset1 }; var createCall = _publishedNodesServices.Setup(s => s.CreateOrUpdateDataSetWriterEntryAsync( It.IsAny(), It.IsAny())) .Returns(Task.CompletedTask); createCall.Verifiable(Times.Once); var result = await _service(_publishedNodesServices.Object).CreateOrUpdateAssetAsync( request1, ct).ConfigureAwait(false); Assert.Null(result.ErrorInfo); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); var node = Assert.Single(result.Result.OpcNodes); Assert.StartsWith("nsu=http://opcfoundation.org/AssetServer;i=", result.Result.DataSetWriterId, StringComparison.Ordinal); } var asset2 = _connection.ToPublishedNodesEntry(); asset2.DataSetWriterGroup = "WriterGroup2"; asset2.DataSetName = asset1.DataSetName; var stream2 = new MemoryStream(Encoding.UTF8.GetBytes(kTestAsset)); await using (var s2 = stream2.ConfigureAwait(false)) { var request2 = new PublishedNodeCreateAssetRequestModel { Configuration = stream2, Entry = asset2 }; var dup = await _service(_publishedNodesServices.Object).CreateOrUpdateAssetAsync( request2, ct).ConfigureAwait(false); Assert.NotNull(dup.ErrorInfo); Assert.Equal(Opc.Ua.StatusCodes.BadBrowseNameDuplicated, dup.ErrorInfo.StatusCode); } Verify(); } public async Task ConfigureWithBadStreamFails1Async(CancellationToken ct = default) { var asset = _connection.ToPublishedNodesEntry(); asset.DataSetWriterGroup = "WriterGroup1"; asset.DataSetName = "ConfigureWithBadStreamFails1Async"; var stream = new MemoryStream(Encoding.UTF8.GetBytes(kTestAsset)); await stream.DisposeAsync().ConfigureAwait(false); var request = new PublishedNodeCreateAssetRequestModel { Configuration = stream, Entry = asset }; var result = await _service(_publishedNodesServices.Object).CreateOrUpdateAssetAsync( request, ct).ConfigureAwait(false); Assert.NotNull(result.ErrorInfo); Assert.Equal(Opc.Ua.StatusCodes.Bad, result.ErrorInfo.StatusCode); Verify(); } public async Task ConfigureWithBadStreamFails2Async(CancellationToken ct = default) { // Test passing a stream that throws on read var asset = _connection.ToPublishedNodesEntry(); asset.DataSetWriterGroup = "WriterGroup1"; asset.DataSetName = "ConfigureWithBadStreamFails2Async"; var stream = new Mock(); stream.Setup(s => s.Read(It.IsAny(), It.IsAny(), It.IsAny())) .Throws(new IOException()); var request = new PublishedNodeCreateAssetRequestModel { Configuration = stream.Object, Entry = asset }; var result = await _service(_publishedNodesServices.Object).CreateOrUpdateAssetAsync( request, ct).ConfigureAwait(false); Assert.NotNull(result.ErrorInfo); Assert.Equal(Opc.Ua.StatusCodes.BadUnexpectedError, result.ErrorInfo.StatusCode); Verify(); } public async Task ConfigureWithBadStreamFails3Async(CancellationToken ct = default) { // Test passing a stream that throws on close var asset = _connection.ToPublishedNodesEntry(); asset.DataSetWriterGroup = "WriterGroup1"; asset.DataSetName = "ConfigureWithBadStreamFails3Async"; var stream = new Mock(); stream.Setup(s => s.Close()).Throws(new IOException()); var request = new PublishedNodeCreateAssetRequestModel { Configuration = stream.Object, Entry = asset }; var result = await _service(_publishedNodesServices.Object).CreateOrUpdateAssetAsync( request, ct).ConfigureAwait(false); Assert.NotNull(result.ErrorInfo); Assert.Equal(Opc.Ua.StatusCodes.BadUnexpectedError, result.ErrorInfo.StatusCode); Verify(); } public async Task ConfigureAssetFails1Async(CancellationToken ct = default) { // Throw in when calling create or update var asset = _connection.ToPublishedNodesEntry(); asset.DataSetWriterGroup = "WriterGroup1"; asset.DataSetName = "ConfigureAssetFails1Async"; var stream = new MemoryStream(Encoding.UTF8.GetBytes(kTestAsset)); var request = new PublishedNodeCreateAssetRequestModel { Configuration = stream, Entry = asset }; var createCall = _publishedNodesServices.Setup(s => s.CreateOrUpdateDataSetWriterEntryAsync( It.IsAny(), It.IsAny())) .Returns(Task.FromException(new IOException("Bad"))); createCall.Verifiable(Times.Once); var result = await _service(_publishedNodesServices.Object).CreateOrUpdateAssetAsync( request, ct).ConfigureAwait(false); Assert.NotNull(result.ErrorInfo); Assert.Equal(Opc.Ua.StatusCodes.Bad, result.ErrorInfo.StatusCode); Verify(); } private void Verify() { if (_verify) { _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } } private readonly ConnectionModel _connection; private readonly Mock _publishedNodesServices; private readonly Func> _service; private readonly bool _verify; private const string kTestAsset = """ { "@context": [ "https://www.w3.org/2022/wot/td/v1.1" ], "id": "urn:sim3264", "securityDefinitions": { "nosec_sc": { "scheme": "nosec" } }, "security": [ "nosec_sc" ], "@type": [ "Thing" ], "name": "sim-3264", "base": "sim://simserver1:443", "title": "Simulated Asset", "properties": { "VoltageL1-N": { "type": "number", "opcua:nodeId": "s=VoltageL-N", "readOnly": true, "observable": true, "forms": [ { "href": "1", "op": [ "readproperty", "observeproperty" ], "sim:type": "Double", "sim:pollingTime": 120 } ] } } } """; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/DeterministicAlarms/DeterministicAlarmsTests1.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher; using Azure.IIoT.OpcUa.Publisher.Models; using DeterministicAlarms; using System; using System.Threading; using System.Threading.Tasks; using Xunit; public class DeterministicAlarmsTests1 { public DeterministicAlarmsTests1(Func> services, T connection) { _services = services; _connection = connection; } public async Task BrowseAreaPathVendingMachine1DoorOpenTestAsync(CancellationToken ct = default) { var services = _services(); var results = await services.BrowsePathAsync(_connection, new BrowsePathRequestModel { NodeId = Namespaces.DeterministicAlarmsInstance + "#s=VendingMachine1", BrowsePaths = new[] { new[] { Namespaces.DeterministicAlarmsInstance + "#VendingMachine1_DoorOpen" } } }, ct).ConfigureAwait(false); Assert.Null(results.ErrorInfo); var target = Assert.Single(results.Targets!); Assert.NotNull(target.BrowsePath); Assert.NotNull(target.Target); Assert.Equal(Namespaces.DeterministicAlarmsInstance + "#i=1", target.Target.NodeId); } public async Task BrowseAreaPathVendingMachine2DoorOpenTestAsync(CancellationToken ct = default) { var services = _services(); var results = await services.BrowsePathAsync(_connection, new BrowsePathRequestModel { NodeId = Namespaces.DeterministicAlarmsInstance + "#s=VendingMachine2", BrowsePaths = new[] { new[] { Namespaces.DeterministicAlarmsInstance + "#VendingMachine2_DoorOpen" } } }, ct).ConfigureAwait(false); Assert.Null(results.ErrorInfo); var target = Assert.Single(results.Targets!); Assert.NotNull(target.BrowsePath); Assert.NotNull(target.Target); Assert.Equal(Namespaces.DeterministicAlarmsInstance + "#i=234", target.Target.NodeId); } public async Task BrowseAreaPathVendingMachine1TemperatureHighTestAsync(CancellationToken ct = default) { var services = _services(); var results = await services.BrowsePathAsync(_connection, new BrowsePathRequestModel { NodeId = Namespaces.DeterministicAlarmsInstance + "#s=VendingMachine1", BrowsePaths = new[] { new[] { Namespaces.DeterministicAlarmsInstance + "#VendingMachine1_TemperatureHigh" } } }, ct).ConfigureAwait(false); Assert.Null(results.ErrorInfo); var target = Assert.Single(results.Targets!); Assert.NotNull(target.BrowsePath); Assert.NotNull(target.Target); Assert.Equal(Namespaces.DeterministicAlarmsInstance + "#i=110", target.Target.NodeId); } public async Task BrowseAreaPathVendingMachine2LightOffTestAsync(CancellationToken ct = default) { var services = _services(); var results = await services.BrowsePathAsync(_connection, new BrowsePathRequestModel { NodeId = Namespaces.DeterministicAlarmsInstance + "#s=VendingMachine2", BrowsePaths = new[] { new[] { Namespaces.DeterministicAlarmsInstance + "#VendingMachine2_LightOff" } } }, ct).ConfigureAwait(false); Assert.Null(results.ErrorInfo); var target = Assert.Single(results.Targets!); Assert.NotNull(target.BrowsePath); Assert.NotNull(target.Target); Assert.Equal(Namespaces.DeterministicAlarmsInstance + "#i=343", target.Target.NodeId); } #if UNUSED public async Task FiresEventSequenceTestWithEdgeFilteringAsync(CancellationToken ct = default) { // Subscribe to server events using var provider = _subscription(); var services = _services(); var monitoredItem = await provider.AddMonitoredItemAsync(new MonitoredItemModel { NodeId = Opc.Ua.ObjectIds.Server.ToString(), Attribute = NodeAttribute.EventNotifier, Settings = new MonitoredItemSettingsModel { QueueSize = 1000 } }).ConfigureAwait(false); const string machine1 = Namespaces.DeterministicAlarmsInstance + "#s=VendingMachine1"; const string machine2 = Namespaces.DeterministicAlarmsInstance + "#s=VendingMachine2"; const string doorOpen1 = Namespaces.DeterministicAlarmsInstance + "#i=1"; const string tempHigh1 = Namespaces.DeterministicAlarmsInstance + "#i=110"; const string doorOpen2 = Namespaces.DeterministicAlarmsInstance + "#i=226"; const string lightOff2 = Namespaces.DeterministicAlarmsInstance + "#i=335"; await services.NodeShouldHaveStatesAsync(_connection, doorOpen1, "Inactive", "Disabled").ConfigureAwait(false); await services.NodeShouldHaveStatesAsync(_connection, tempHigh1, "Inactive", "Disabled").ConfigureAwait(false); await services.NodeShouldHaveStatesAsync(_connection, doorOpen2, "Inactive", "Disabled").ConfigureAwait(false); await services.NodeShouldHaveStatesAsync(_connection, lightOff2, "Inactive", "Disabled").ConfigureAwait(false); var waitUntilStartInSeconds = TimeSpan.FromSeconds(9); // value in *.json file _server.FireTimersWithPeriod(waitUntilStartInSeconds, 1); var opcEvent1 = await provider.GetEventChangesAsDictionary(1, true, Filter) .FirstAsync(CancellationToken ct = default).ConfigureAwait(false); Assert.Equal(opcEvent1["/EventId"], Encoding.UTF8.GetBytes("V1_DoorOpen-1 (1)")); Assert.Equal(opcEvent1["/EventType"], Opc.Ua.ObjectTypeIds.TripAlarmType.ToString()); Assert.Equal(opcEvent1["/SourceNode"], machine1); Assert.Equal(opcEvent1["/SourceName"], "VendingMachine1"); Assert.Equal(opcEvent1["/Message"].GetByPath("Text"), "Door Open"); Assert.Equal(opcEvent1["/Severity"], (int)Opc.Ua.EventSeverity.High); await services.NodeShouldHaveStatesAsync(_connection, doorOpen1, "Active", "Enabled").ConfigureAwait(false); await services.NodeShouldHaveStatesAsync(_connection, tempHigh1, "Inactive", "Disabled").ConfigureAwait(false); await services.NodeShouldHaveStatesAsync(_connection, doorOpen2, "Inactive", "Disabled").ConfigureAwait(false); await services.NodeShouldHaveStatesAsync(_connection, lightOff2, "Inactive", "Disabled").ConfigureAwait(false); _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(1), 1); // advance to next step _server.FireTimersWithPeriod(TimeSpan.FromSeconds(5), 1); var opcEvent2 = await provider.GetEventChangesAsDictionary(1, true, Filter) .FirstAsync(CancellationToken ct = default).ConfigureAwait(false); Assert.Equal(opcEvent2["/EventId"], Encoding.UTF8.GetBytes("V2_LightOff-1 (1)")); Assert.Equal(opcEvent2["/EventType"], Opc.Ua.ObjectTypeIds.OffNormalAlarmType.ToString()); Assert.Equal(opcEvent2["/SourceNode"], machine2); Assert.Equal(opcEvent2["/SourceName"], "VendingMachine2"); Assert.Equal(opcEvent2["/Message"].GetByPath("Text"), "Light Off in machine"); Assert.Equal(opcEvent2["/Severity"], (int)Opc.Ua.EventSeverity.Medium); await services.NodeShouldHaveStatesAsync(_connection, lightOff2, "Active", "Enabled").ConfigureAwait(false); _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(1), 1); // advance to next step _server.FireTimersWithPeriod(TimeSpan.FromSeconds(7), 1); var opcEvent3 = await provider.GetEventChangesAsDictionary(1, true, Filter) .FirstAsync(CancellationToken ct = default).ConfigureAwait(false); Assert.Equal(opcEvent3["/EventId"], Encoding.UTF8.GetBytes("V1_DoorOpen-2 (1)")); Assert.Equal(opcEvent3["/EventType"], Opc.Ua.ObjectTypeIds.TripAlarmType.ToString()); Assert.Equal(opcEvent3["/SourceNode"], machine1); Assert.Equal(opcEvent3["/SourceName"], "VendingMachine1"); Assert.Equal(opcEvent3["/Message"].GetByPath("Text"), "Door Closed"); Assert.Equal(opcEvent3["/Severity"], (int)Opc.Ua.EventSeverity.Medium); await services.NodeShouldHaveStatesAsync(_connection, doorOpen1, "Inactive", "Enabled").ConfigureAwait(false); _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(1), 1); // advance to next step _server.FireTimersWithPeriod(TimeSpan.FromSeconds(4), 1); var opcEvent4 = await provider.GetEventChangesAsDictionary(1, true, Filter) .FirstAsync(CancellationToken ct = default).ConfigureAwait(false); Assert.Equal(opcEvent4["/EventId"], Encoding.UTF8.GetBytes("V1_TemperatureHigh-1 (1)")); Assert.Equal(opcEvent4["/EventType"], Opc.Ua.ObjectTypeIds.LimitAlarmType.ToString()); Assert.Equal(opcEvent4["/SourceNode"], machine1); Assert.Equal(opcEvent4["/SourceName"], "VendingMachine1"); Assert.Equal(opcEvent4["/Message"].GetByPath("Text"), "Temperature is HIGH"); Assert.Equal(opcEvent4["/Severity"], (int)Opc.Ua.EventSeverity.High); await services.NodeShouldHaveStatesAsync(_connection, tempHigh1, "Active", "Enabled").ConfigureAwait(false); _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(1), 1); var opcEvent5 = await provider.GetEventChangesAsDictionary(1, true, Filter) .FirstAsync(CancellationToken ct = default).ConfigureAwait(false); Assert.Equal(opcEvent5["/EventId"], Encoding.UTF8.GetBytes("V1_DoorOpen-1 (2)")); Assert.Equal(opcEvent5["/Message"].GetByPath("Text"), "Door Open"); await services.NodeShouldHaveStatesAsync(_connection, doorOpen1, "Active", "Enabled").ConfigureAwait(false); _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(1), 1); // advance to next step _server.FireTimersWithPeriod(TimeSpan.FromSeconds(5), 1); var opcEvent6 = await provider.GetEventChangesAsDictionary(1, true, Filter) .FirstAsync(CancellationToken ct = default).ConfigureAwait(false); Assert.Equal(opcEvent6["/EventId"], Encoding.UTF8.GetBytes("V2_LightOff-1 (2)")); Assert.Equal(opcEvent6["/Message"].GetByPath("Text"), "Light Off in machine"); await services.NodeShouldHaveStatesAsync(_connection, lightOff2, "Active", "Enabled").ConfigureAwait(false); _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(1), 1); // advance to next step // At this point, the *runningForSeconds* limit in the JSON config causes execution to stop _server.FireTimersWithPeriod(TimeSpan.FromSeconds(1), 1); await services.NodeShouldHaveStatesAsync(_connection, doorOpen1, "Active", "Enabled").ConfigureAwait(false); await services.NodeShouldHaveStatesAsync(_connection, tempHigh1, "Active", "Enabled").ConfigureAwait(false); await services.NodeShouldHaveStatesAsync(_connection, doorOpen2, "Inactive", "Disabled").ConfigureAwait(false); await services.NodeShouldHaveStatesAsync(_connection, lightOff2, "Active", "Enabled").ConfigureAwait(false); static bool Filter(Dictionary evt) { return ((string?)evt["/SourceNode"])?.StartsWith( Namespaces.DeterministicAlarmsInstance, StringComparison.OrdinalIgnoreCase) == true; } } public async Task FiresEventSequenceTestWithServerFilteringAsync(CancellationToken ct = default) { var services = _services(); var result = await services.CompileQueryAsync(_connection, new QueryCompilationRequestModel { Query = $@" PREFIX ns <{Namespaces.DeterministicAlarmsInstance}> SELECT * FROM BaseEventType WHERE /SourceNode IN ( 'ns:s=VendingMachine1'^^NodeId, 'ns:s=VendingMachine2'^^NodeId ) " }).ConfigureAwait(false); Assert.NotNull(result); Assert.Null(result.ErrorInfo); // Subscribe to server events using var provider = _subscription(); var monitoredItem = await provider.AddMonitoredItemAsync(new MonitoredItemModel { NodeId = Opc.Ua.ObjectIds.Server.ToString(), Attribute = NodeAttribute.EventNotifier, Settings = new MonitoredItemSettingsModel { EventFilter = result.EventFilter } }).ConfigureAwait(false); const string machine1 = Namespaces.DeterministicAlarmsInstance + "#s=VendingMachine1"; const string machine2 = Namespaces.DeterministicAlarmsInstance + "#s=VendingMachine2"; const string doorOpen1 = Namespaces.DeterministicAlarmsInstance + "#i=1"; const string tempHigh1 = Namespaces.DeterministicAlarmsInstance + "#i=110"; const string doorOpen2 = Namespaces.DeterministicAlarmsInstance + "#i=226"; const string lightOff2 = Namespaces.DeterministicAlarmsInstance + "#i=335"; await services.NodeShouldHaveStatesAsync(_connection, doorOpen1, "Inactive", "Disabled").ConfigureAwait(false); await services.NodeShouldHaveStatesAsync(_connection, tempHigh1, "Inactive", "Disabled").ConfigureAwait(false); await services.NodeShouldHaveStatesAsync(_connection, doorOpen2, "Inactive", "Disabled").ConfigureAwait(false); await services.NodeShouldHaveStatesAsync(_connection, lightOff2, "Inactive", "Disabled").ConfigureAwait(false); var waitUntilStartInSeconds = TimeSpan.FromSeconds(9); // value in *.json file _server.FireTimersWithPeriod(waitUntilStartInSeconds, 1); var opcEvent1 = await provider.GetEventChangesAsDictionary(1) .FirstAsync(CancellationToken ct = default).ConfigureAwait(false); Assert.Equal(opcEvent1["/EventId"], Encoding.UTF8.GetBytes("V1_DoorOpen-1 (1)")); Assert.Equal(opcEvent1["/EventType"], Opc.Ua.ObjectTypeIds.TripAlarmType.ToString()); Assert.Equal(opcEvent1["/SourceNode"], machine1); Assert.Equal(opcEvent1["/SourceName"], "VendingMachine1"); Assert.Equal(opcEvent1["/Message"].GetByPath("Text"), "Door Open"); Assert.Equal(opcEvent1["/Severity"], (int)Opc.Ua.EventSeverity.High); await services.NodeShouldHaveStatesAsync(_connection, doorOpen1, "Active", "Enabled").ConfigureAwait(false); await services.NodeShouldHaveStatesAsync(_connection, tempHigh1, "Inactive", "Disabled").ConfigureAwait(false); await services.NodeShouldHaveStatesAsync(_connection, doorOpen2, "Inactive", "Disabled").ConfigureAwait(false); await services.NodeShouldHaveStatesAsync(_connection, lightOff2, "Inactive", "Disabled").ConfigureAwait(false); _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(1), 1); // advance to next step _server.FireTimersWithPeriod(TimeSpan.FromSeconds(5), 1); var opcEvent2 = await provider.GetEventChangesAsDictionary(1) .FirstAsync(CancellationToken ct = default).ConfigureAwait(false); Assert.Equal(opcEvent2["/EventId"], Encoding.UTF8.GetBytes("V2_LightOff-1 (1)")); Assert.Equal(opcEvent2["/EventType"], Opc.Ua.ObjectTypeIds.OffNormalAlarmType.ToString()); Assert.Equal(opcEvent2["/SourceNode"], machine2); Assert.Equal(opcEvent2["/SourceName"], "VendingMachine2"); Assert.Equal(opcEvent2["/Message"].GetByPath("Text"), "Light Off in machine"); Assert.Equal(opcEvent2["/Severity"], (int)Opc.Ua.EventSeverity.Medium); await services.NodeShouldHaveStatesAsync(_connection, lightOff2, "Active", "Enabled").ConfigureAwait(false); _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(1), 1); // advance to next step _server.FireTimersWithPeriod(TimeSpan.FromSeconds(7), 1); var opcEvent3 = await provider.GetEventChangesAsDictionary(1) .FirstAsync(CancellationToken ct = default).ConfigureAwait(false); Assert.Equal(opcEvent3["/EventId"], Encoding.UTF8.GetBytes("V1_DoorOpen-2 (1)")); Assert.Equal(opcEvent3["/EventType"], Opc.Ua.ObjectTypeIds.TripAlarmType.ToString()); Assert.Equal(opcEvent3["/SourceNode"], machine1); Assert.Equal(opcEvent3["/SourceName"], "VendingMachine1"); Assert.Equal(opcEvent3["/Message"].GetByPath("Text"), "Door Closed"); Assert.Equal(opcEvent3["/Severity"], (int)Opc.Ua.EventSeverity.Medium); await services.NodeShouldHaveStatesAsync(_connection, doorOpen1, "Inactive", "Enabled").ConfigureAwait(false); _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(1), 1); // advance to next step _server.FireTimersWithPeriod(TimeSpan.FromSeconds(4), 1); var opcEvent4 = await provider.GetEventChangesAsDictionary(1) .FirstAsync(CancellationToken ct = default).ConfigureAwait(false); Assert.Equal(opcEvent4["/EventId"], Encoding.UTF8.GetBytes("V1_TemperatureHigh-1 (1)")); Assert.Equal(opcEvent4["/EventType"], Opc.Ua.ObjectTypeIds.LimitAlarmType.ToString()); Assert.Equal(opcEvent4["/SourceNode"], machine1); Assert.Equal(opcEvent4["/SourceName"], "VendingMachine1"); Assert.Equal(opcEvent4["/Message"].GetByPath("Text"), "Temperature is HIGH"); Assert.Equal(opcEvent4["/Severity"], (int)Opc.Ua.EventSeverity.High); await services.NodeShouldHaveStatesAsync(_connection, tempHigh1, "Active", "Enabled").ConfigureAwait(false); _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(1), 1); var opcEvent5 = await provider.GetEventChangesAsDictionary(1) .FirstAsync(CancellationToken ct = default).ConfigureAwait(false); Assert.Equal(opcEvent5["/EventId"], Encoding.UTF8.GetBytes("V1_DoorOpen-1 (2)")); Assert.Equal(opcEvent5["/Message"].GetByPath("Text"), "Door Open"); await services.NodeShouldHaveStatesAsync(_connection, doorOpen1, "Active", "Enabled").ConfigureAwait(false); _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(1), 1); // advance to next step _server.FireTimersWithPeriod(TimeSpan.FromSeconds(5), 1); var opcEvent6 = await provider.GetEventChangesAsDictionary(1) .FirstAsync(CancellationToken ct = default).ConfigureAwait(false); Assert.Equal(opcEvent6["/EventId"], Encoding.UTF8.GetBytes("V2_LightOff-1 (2)")); Assert.Equal(opcEvent6["/Message"].GetByPath("Text"), "Light Off in machine"); await services.NodeShouldHaveStatesAsync(_connection, lightOff2, "Active", "Enabled").ConfigureAwait(false); _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(1), 1); // advance to next step // At this point, the *runningForSeconds* limit in the JSON config causes execution to stop _server.FireTimersWithPeriod(TimeSpan.FromSeconds(1), 1); await services.NodeShouldHaveStatesAsync(_connection, doorOpen1, "Active", "Enabled").ConfigureAwait(false); await services.NodeShouldHaveStatesAsync(_connection, tempHigh1, "Active", "Enabled").ConfigureAwait(false); await services.NodeShouldHaveStatesAsync(_connection, doorOpen2, "Inactive", "Disabled").ConfigureAwait(false); await services.NodeShouldHaveStatesAsync(_connection, lightOff2, "Active", "Enabled").ConfigureAwait(false); } private readonly DeterministicAlarmsServer1 _server; #endif private readonly Func> _services; private readonly T _connection; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/DeterministicAlarms/DeterministicAlarmsTests2.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher; using Azure.IIoT.OpcUa.Publisher.Models; using DeterministicAlarms; using System; using System.Threading; using System.Threading.Tasks; using Xunit; public class DeterministicAlarmsTests2 { public DeterministicAlarmsTests2(Func> services, T connection) { _services = services; _connection = connection; } public async Task BrowseAreaPathVendingMachine1DoorOpenTestAsync(CancellationToken ct = default) { var services = _services(); var results = await services.BrowsePathAsync(_connection, new BrowsePathRequestModel { NodeId = Namespaces.DeterministicAlarmsInstance + "#s=VendingMachine1", BrowsePaths = new[] { new[] { Namespaces.DeterministicAlarmsInstance + "#VendingMachine1_DoorOpen" } } }, ct).ConfigureAwait(false); Assert.Null(results.ErrorInfo); var target = Assert.Single(results.Targets!); Assert.NotNull(target.BrowsePath); Assert.NotNull(target.Target); Assert.Equal(Namespaces.DeterministicAlarmsInstance + "#i=1", target.Target.NodeId); } #if UNUSED public async Task VerifyThatTimeForEventsChangesEdgeFilteredAsync(CancellationToken ct = default) { // Subscribe to server events using var provider = _subscription(); var services = _services(); var connection = await _connection().ConfigureAwait(false); var monitoredItem = await provider.AddMonitoredItemAsync(new MonitoredItemModel { NodeId = Opc.Ua.ObjectIds.Server.ToString(), Attribute = NodeAttribute.EventNotifier, Settings = new MonitoredItemSettingsModel { QueueSize = 1000 } }).ConfigureAwait(false); const string doorOpen1 = Namespaces.DeterministicAlarmsInstance + "#i=1"; await services.NodeShouldHaveStatesAsync(connection, doorOpen1, "Inactive", "Disabled").ConfigureAwait(false); var waitUntilStartInSeconds = TimeSpan.FromSeconds(5); // value in config _server.FireTimersWithPeriod(waitUntilStartInSeconds, 1); var opcEvent1 = await provider.GetEventChangesAsDictionary(1, true, Filter) .FirstAsync(CancellationToken ct = default).ConfigureAwait(false); var timeForFirstEvent = (DateTime)opcEvent1["/Time"]; await services.NodeShouldHaveStatesAsync(connection, doorOpen1, "Active", "Enabled").ConfigureAwait(false); _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(1), 1); // advance to next step _server.FireTimersWithPeriod(waitUntilStartInSeconds, 1); var opcEvent2 = await provider.GetEventChangesAsDictionary(1, true, Filter) .FirstAsync(CancellationToken ct = default).ConfigureAwait(false); var timeForNextEvent = (DateTime)opcEvent2["/Time"]; await services.NodeShouldHaveStatesAsync(connection, doorOpen1, "Inactive", "Disabled").ConfigureAwait(false); Assert.NotEqual(timeForFirstEvent, timeForNextEvent); static bool Filter(Dictionary evt) { return ((string?)evt["/SourceNode"])?.StartsWith( Namespaces.DeterministicAlarmsInstance, StringComparison.OrdinalIgnoreCase) == true; } } public async Task VerifyThatTimeForEventsChangesServerFilteredAsync(CancellationToken ct = default) { var services = _services(); var result = await services.CompileQueryAsync(connection, new QueryCompilationRequestModel { Query = $@" PREFIX ns <{Namespaces.DeterministicAlarmsInstance}> SELECT * FROM BaseEventType WHERE /SourceNode IN ( 'ns:s=VendingMachine1'^^NodeId, 'ns:s=VendingMachine2'^^NodeId ) " }).ConfigureAwait(false); Assert.NotNull(result); Assert.Null(result.ErrorInfo); // Subscribe to server events using var provider = _subscription(); var monitoredItem = await provider.AddMonitoredItemAsync(new MonitoredItemModel { NodeId = Opc.Ua.ObjectIds.Server.ToString(), Attribute = NodeAttribute.EventNotifier, Settings = new MonitoredItemSettingsModel { EventFilter = result.EventFilter } }).ConfigureAwait(false); const string doorOpen1 = Namespaces.DeterministicAlarmsInstance + "#i=1"; await services.NodeShouldHaveStatesAsync(connection, doorOpen1, "Inactive", "Disabled").ConfigureAwait(false); var waitUntilStartInSeconds = TimeSpan.FromSeconds(5); // value in config _server.FireTimersWithPeriod(waitUntilStartInSeconds, 1); var opcEvent1 = await provider.GetEventChangesAsDictionary(1) .FirstAsync(CancellationToken ct = default).ConfigureAwait(false); var timeForFirstEvent = (DateTime)opcEvent1["/Time"]; await services.NodeShouldHaveStatesAsync(connection, doorOpen1, "Active", "Enabled").ConfigureAwait(false); _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(1), 1); // advance to next step _server.FireTimersWithPeriod(waitUntilStartInSeconds, 1); var opcEvent2 = await provider.GetEventChangesAsDictionary(1) .FirstAsync(CancellationToken ct = default).ConfigureAwait(false); var timeForNextEvent = (DateTime)opcEvent2["/Time"]; await services.NodeShouldHaveStatesAsync(connection, doorOpen1, "Inactive", "Disabled").ConfigureAwait(false); Assert.NotEqual(timeForFirstEvent, timeForNextEvent); } private readonly DeterministicAlarmsServer2 _server; #endif private readonly Func> _services; private readonly T _connection; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/DeterministicAlarms/Extensions/Extensions.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace DeterministicAlarms.Tests { using Azure.IIoT.OpcUa.Publisher; using Azure.IIoT.OpcUa.Publisher.Models; using FluentAssertions; using System.Threading.Tasks; internal static class Extensions { public static async Task NodeShouldHaveStatesAsync(this INodeServices server, T connectionId, string node, string activeState, string enabledState) { await server.NodeShouldHaveStateAsync(connectionId, node, "ActiveState", activeState).ConfigureAwait(false); await server.NodeShouldHaveStateAsync(connectionId, node, "EnabledState", enabledState).ConfigureAwait(false); } private static async Task NodeShouldHaveStateAsync(this INodeServices server, T connectionId, string node, string state, string expectedValue) { var value = await server.ValueReadAsync(connectionId, new ValueReadRequestModel { NodeId = node, BrowsePath = new[] { "." + state } }).ConfigureAwait(false); var text = value?.Value?["Text"]; text.Should().NotBeNull().And.Be(expectedValue, "{0} should be {1}", state, expectedValue); var loc = value?.Value?["Locale"]; loc.Should().NotBeNull().And.Be("en-US"); } } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/FileSystem/BrowseTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using Xunit; public class BrowseTests { /// /// Create metadata tests /// /// /// /// public BrowseTests(Func> services, T connection, string tempPath) { _services = services; _connection = connection; _tempPath = tempPath; } public async Task GetFileSystemsTest1Async(CancellationToken ct = default) { var services = _services(); var drives = DriveInfo.GetDrives().Select(d => d.Name).ToHashSet(); await foreach (var fs in services.GetFileSystemsAsync(_connection, ct).ConfigureAwait(false)) { Assert.Null(fs.ErrorInfo); Assert.NotNull(fs.Result); Assert.NotNull(fs.Result.Name); Assert.True(drives.Remove(fs.Result.Name), $"{fs.Result.Name} not found in {string.Join('\n', drives)}"); } Assert.Empty(drives); } public async Task GetDirectoriesTest1Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); var directoryNodeId = $"nsu=FileSystem;s=1:{path}"; var directories = await services.GetDirectoriesAsync(_connection, new FileSystemObjectModel { NodeId = directoryNodeId }, ct).ConfigureAwait(false); Assert.Null(directories.ErrorInfo); Assert.NotNull(directories.Result); Assert.Empty(directories.Result); } public async Task GetDirectoriesTest2Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); var path2 = Path.Combine(path, Path.GetRandomFileName()); Directory.CreateDirectory(path2); var directoryNodeId = $"nsu=FileSystem;s=1:{path}"; var directories = await services.GetDirectoriesAsync(_connection, new FileSystemObjectModel { NodeId = directoryNodeId }, ct).ConfigureAwait(false); Assert.Null(directories.ErrorInfo); Assert.NotNull(directories.Result); var item = Assert.Single(directories.Result); Assert.NotNull(item); Assert.Equal(Path.GetFileName(path2), item.Name); } public async Task GetDirectoriesTest3Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); for (var i = 0; i < 10; i++) { var path2 = Path.Combine(path, i.ToString(CultureInfo.InvariantCulture)); Directory.CreateDirectory(path2); } var directoryNodeId = $"nsu=FileSystem;s=1:{path}"; var directories = await services.GetDirectoriesAsync(_connection, new FileSystemObjectModel { NodeId = directoryNodeId }, ct).ConfigureAwait(false); Assert.Null(directories.ErrorInfo); Assert.NotNull(directories.Result); var result = directories.Result.ToList(); Assert.Equal(10, result.Count); Assert.All(result, item => Assert.NotNull(item.Name)); Assert.All(result.Select(r => r.Name).Order(), (item, i) => Assert.Equal(i.ToString(CultureInfo.InvariantCulture), item)); } public async Task GetDirectoriesTest4Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); for (var i = 0; i < 10; i++) { CreateFile(path, i.ToString(CultureInfo.InvariantCulture), 1024); } var directoryNodeId = $"nsu=FileSystem;s=1:{path}"; var directories = await services.GetDirectoriesAsync(_connection, new FileSystemObjectModel { NodeId = directoryNodeId }, ct).ConfigureAwait(false); Assert.Null(directories.ErrorInfo); Assert.NotNull(directories.Result); Assert.Empty(directories.Result); } public async Task GetDirectoriesTest5Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); var directoryNodeId = $"nsu=FileSystem;s=1:{path}"; var directories = await services.GetDirectoriesAsync(_connection, new FileSystemObjectModel { NodeId = directoryNodeId }, ct).ConfigureAwait(false); Assert.NotNull(directories.ErrorInfo); Assert.NotNull(directories.Result); Assert.Empty(directories.Result); Assert.Equal(Opc.Ua.StatusCodes.BadNodeIdUnknown, directories.ErrorInfo.StatusCode); } public async Task GetDirectoriesTest6Async(CancellationToken ct = default) { var services = _services(); var root = _tempPath; var p1 = Path.GetRandomFileName(); var p2 = Path.GetRandomFileName(); var p3 = Path.GetRandomFileName(); var path = Path.Combine(root, p1, p2, p3); Directory.CreateDirectory(path); var path2 = Path.Combine(path, Path.GetRandomFileName()); Directory.CreateDirectory(path2); var directories = await services.GetDirectoriesAsync(_connection, new FileSystemObjectModel { NodeId = $"nsu=FileSystem;s=1:{root}", BrowsePath = new List { $"nsu=FileSystem;{p1}", $"nsu=FileSystem;{p2}", $"nsu=FileSystem;{p3}" } }, ct).ConfigureAwait(false); Assert.Null(directories.ErrorInfo); Assert.NotNull(directories.Result); var item = Assert.Single(directories.Result); Assert.NotNull(item); Assert.Equal(Path.GetFileName(path2), item.Name); } public async Task GetFilesTest1Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); for (var i = 10; i < 20; i++) { var path2 = Path.Combine(path, i.ToString(CultureInfo.InvariantCulture)); Directory.CreateDirectory(path2); } var directoryNodeId = $"nsu=FileSystem;s=1:{path}"; var files = await services.GetFilesAsync(_connection, new FileSystemObjectModel { NodeId = directoryNodeId }, ct).ConfigureAwait(false); Assert.Null(files.ErrorInfo); Assert.NotNull(files.Result); Assert.Empty(files.Result); } public async Task GetFilesTest2Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); for (var i = 0; i < 10; i++) { CreateFile(path, i.ToString(CultureInfo.InvariantCulture), 1024); } var directoryNodeId = $"nsu=FileSystem;s=1:{path}"; var files = await services.GetFilesAsync(_connection, new FileSystemObjectModel { NodeId = directoryNodeId }, ct).ConfigureAwait(false); Assert.Null(files.ErrorInfo); Assert.NotNull(files.Result); var result = files.Result.ToList(); Assert.Equal(10, result.Count); Assert.All(result, item => Assert.NotNull(item.Name)); Assert.All(result.Select(r => r.Name).Order(), (item, i) => Assert.Equal(i.ToString(CultureInfo.InvariantCulture), item)); } public async Task GetFilesTest3Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); for (var i = 0; i < 10; i++) { CreateFile(path, i.ToString(CultureInfo.InvariantCulture), 1024); } for (var i = 10; i < 20; i++) { var path2 = Path.Combine(path, i.ToString(CultureInfo.InvariantCulture)); Directory.CreateDirectory(path2); } var directoryNodeId = $"nsu=FileSystem;s=1:{path}"; var files = await services.GetFilesAsync(_connection, new FileSystemObjectModel { NodeId = directoryNodeId }, ct).ConfigureAwait(false); Assert.Null(files.ErrorInfo); Assert.NotNull(files.Result); var result = files.Result.ToList(); Assert.Equal(10, result.Count); Assert.All(result, item => Assert.NotNull(item.Name)); Assert.All(result.Select(r => r.Name).Order(), (item, i) => Assert.Equal(i.ToString(CultureInfo.InvariantCulture), item)); } public async Task GetFilesTest4Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); for (var i = 0; i < 5; i++) { CreateFile(path, i.ToString(CultureInfo.InvariantCulture), 1024); } var directoryNodeId = $"nsu=FileSystem;s=1:{path}"; var files = await services.GetFilesAsync(_connection, new FileSystemObjectModel { NodeId = directoryNodeId }, ct).ConfigureAwait(false); Assert.Null(files.ErrorInfo); Assert.NotNull(files.Result); var result = files.Result.ToList(); Assert.Equal(5, result.Count); Assert.All(result, item => Assert.NotNull(item.Name)); Assert.All(result.Select(r => r.Name).Order(), (item, i) => Assert.Equal(i.ToString(CultureInfo.InvariantCulture), item)); for (var i = 5; i < 10; i++) { CreateFile(path, i.ToString(CultureInfo.InvariantCulture), 1024); } files = await services.GetFilesAsync(_connection, new FileSystemObjectModel { NodeId = directoryNodeId }, ct).ConfigureAwait(false); Assert.Null(files.ErrorInfo); Assert.NotNull(files.Result); result = files.Result.ToList(); Assert.Equal(10, result.Count); Assert.All(result, item => Assert.NotNull(item.Name)); Assert.All(result.Select(r => r.Name).Order(), (item, i) => Assert.Equal(i.ToString(CultureInfo.InvariantCulture), item)); for (var i = 0; i < 6; i++) { var path2 = Path.Combine(path, i.ToString(CultureInfo.InvariantCulture)); File.Delete(path2); } files = await services.GetFilesAsync(_connection, new FileSystemObjectModel { NodeId = directoryNodeId }, ct).ConfigureAwait(false); Assert.Null(files.ErrorInfo); Assert.NotNull(files.Result); result = files.Result.ToList(); Assert.Equal(4, result.Count); Assert.All(result, item => Assert.NotNull(item.Name)); Assert.All(result.Select(r => r.Name).Order(), (item, i) => Assert.Equal((i + 6).ToString(CultureInfo.InvariantCulture), item)); foreach (var file in Directory.GetFiles(path)) { File.Delete(file); } files = await services.GetFilesAsync(_connection, new FileSystemObjectModel { NodeId = directoryNodeId }, ct).ConfigureAwait(false); Assert.Null(files.ErrorInfo); Assert.NotNull(files.Result); Assert.Empty(files.Result); } public async Task GetFilesTest5Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); var directoryNodeId = $"nsu=FileSystem;s=1:{path}"; var files = await services.GetFilesAsync(_connection, new FileSystemObjectModel { NodeId = directoryNodeId }, ct).ConfigureAwait(false); Assert.NotNull(files.Result); Assert.Empty(files.Result); Assert.NotNull(files.ErrorInfo); Assert.Equal(Opc.Ua.StatusCodes.BadNodeIdUnknown, files.ErrorInfo.StatusCode); } public async Task GetFilesTest6Async(CancellationToken ct = default) { var services = _services(); var root = _tempPath; var p1 = Path.GetRandomFileName(); var p2 = Path.GetRandomFileName(); var p3 = Path.GetRandomFileName(); var path = Path.Combine(root, p1, p2, p3); Directory.CreateDirectory(path); CreateFile(path, "test", 1000); var files = await services.GetFilesAsync(_connection, new FileSystemObjectModel { NodeId = $"nsu=FileSystem;s=1:{root}", BrowsePath = new List { $"nsu=FileSystem;{p1}", $"nsu=FileSystem;{p2}", $"nsu=FileSystem;{p3}" } }, ct).ConfigureAwait(false); Assert.Null(files.ErrorInfo); Assert.NotNull(files.Result); var item = Assert.Single(files.Result); Assert.Equal("test", item.Name); } private static string CreateFile(string path, string name, long length) { var fullPath = Path.Combine(path, name); using var f = File.Create(fullPath); var buffer = new byte[length]; for (var i = 0; i < buffer.Length; i++) { buffer[i] = (byte)i; } f.Write(buffer); return fullPath; } private readonly T _connection; private readonly string _tempPath; private readonly Func> _services; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/FileSystem/OperationsTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; using Xunit; public class OperationsTests { /// /// Create tests /// /// /// /// public OperationsTests(Func> services, T connection, string tempPath) { _services = services; _connection = connection; _tempPath = tempPath; } public async Task CreateDirectoryTest1Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); var directoryNodeId = $"nsu=FileSystem;s=1:{path}"; var directory = await services.CreateDirectoryAsync(_connection, new FileSystemObjectModel { NodeId = directoryNodeId }, "testdirectory", ct).ConfigureAwait(false); Assert.Null(directory.ErrorInfo); Assert.True(Directory.Exists(Path.Combine(path, "testdirectory"))); var directories = await services.GetDirectoriesAsync(_connection, new FileSystemObjectModel { NodeId = directoryNodeId }, ct).ConfigureAwait(false); Assert.Null(directories.ErrorInfo); Assert.NotNull(directories.Result); var item = Assert.Single(directories.Result); Assert.Equal(item, directory.Result); } public async Task CreateDirectoryTest2Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); Directory.CreateDirectory(Path.Combine(path, "testdirectory")); var directoryNodeId = $"nsu=FileSystem;s=1:{path}"; var directory = await services.CreateDirectoryAsync(_connection, new FileSystemObjectModel { NodeId = directoryNodeId }, "testdirectory", ct).ConfigureAwait(false); Assert.NotNull(directory.ErrorInfo); Assert.Equal(Opc.Ua.StatusCodes.BadBrowseNameDuplicated, directory.ErrorInfo.StatusCode); } public async Task CreateDirectoryTest3Async(CancellationToken ct = default) { var services = _services(); var root = _tempPath; var p1 = Path.GetRandomFileName(); var p2 = Path.GetRandomFileName(); var p3 = Path.GetRandomFileName(); var path = Path.Combine(root, p1, p2, p3); Directory.CreateDirectory(path); Assert.Empty(Directory.GetDirectories(path)); var directory = await services.CreateDirectoryAsync(_connection, new FileSystemObjectModel { NodeId = $"nsu=FileSystem;s=1:{root}", BrowsePath = new List { $"nsu=FileSystem;{p1}", $"nsu=FileSystem;{p2}", $"nsu=FileSystem;{p3}" } }, "testdir", ct).ConfigureAwait(false); Assert.Null(directory.ErrorInfo); Assert.NotEmpty(Directory.GetDirectories(path)); Assert.True(Directory.Exists(Path.Combine(path, "testdir"))); } public async Task CreateDirectoryTest4Async(CancellationToken ct = default) { var services = _services(); var root = _tempPath; var p1 = Path.GetRandomFileName(); var p2 = Path.GetRandomFileName(); var p3 = Path.GetRandomFileName(); var path = Path.Combine(root, p1, p2, p3); Directory.CreateDirectory(path); Assert.Empty(Directory.GetDirectories(path)); var directory = await services.CreateDirectoryAsync(_connection, new FileSystemObjectModel { NodeId = $"nsu=FileSystem;s=1:{root}", BrowsePath = new List { $"nsu=FileSystem;{p1}", $"nsu=FileSystem;{p2}", "nsu=FileSystem;Bad" } }, "testdir", ct).ConfigureAwait(false); Assert.NotNull(directory.ErrorInfo); Assert.Equal(Opc.Ua.StatusCodes.BadNotFound, directory.ErrorInfo.StatusCode); Assert.Empty(Directory.GetDirectories(path)); } public async Task DeleteDirectoryTest1Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); var path2 = Path.Combine(path, "testDirectory"); Directory.CreateDirectory(Path.Combine(path, "testDirectory")); var parentDirectoryId = $"nsu=FileSystem;s=1:{path}"; Assert.NotEmpty(Directory.GetDirectories(path)); var nodeToDelete = $"nsu=FileSystem;s=1:{path2}"; var result = await services.DeleteFileSystemObjectAsync(_connection, new FileSystemObjectModel { NodeId = nodeToDelete }, new FileSystemObjectModel { NodeId = parentDirectoryId }, ct).ConfigureAwait(false); Assert.NotNull(result); Assert.Equal(0u, result.StatusCode); Assert.Empty(Directory.GetDirectories(path)); } public async Task DeleteDirectoryTest2Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); var path2 = Path.Combine(path, "testDirectory"); Directory.CreateDirectory(Path.Combine(path, "testDirectory")); Assert.NotEmpty(Directory.GetDirectories(path)); var nodeToDelete = $"nsu=FileSystem;s=1:{path2}"; var result = await services.DeleteFileSystemObjectAsync(_connection, new FileSystemObjectModel { NodeId = nodeToDelete }, ct: ct).ConfigureAwait(false); Assert.NotNull(result); Assert.Equal(0u, result.StatusCode); Assert.Empty(Directory.GetDirectories(path)); } public async Task DeleteDirectoryTest3Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); var parentDirectoryId = $"nsu=FileSystem;s=1:{path}"; var fileToDeleteId = $"nsu=FileSystem;s=1:{Path.Combine(path, "wrong")}"; var result = await services.DeleteFileSystemObjectAsync(_connection, new FileSystemObjectModel { NodeId = fileToDeleteId }, new FileSystemObjectModel { NodeId = parentDirectoryId }, ct).ConfigureAwait(false); Assert.NotNull(result); Assert.Equal(Opc.Ua.StatusCodes.BadNotFound, result.StatusCode); } public async Task CreateFileTest1Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); var directoryNodeId = $"nsu=FileSystem;s=1:{path}"; var file = await services.CreateFileAsync(_connection, new FileSystemObjectModel { NodeId = directoryNodeId }, "testfile", ct).ConfigureAwait(false); Assert.Null(file.ErrorInfo); Assert.True(File.Exists(Path.Combine(path, "testfile"))); var files = await services.GetFilesAsync(_connection, new FileSystemObjectModel { NodeId = directoryNodeId }, ct).ConfigureAwait(false); Assert.Null(files.ErrorInfo); Assert.NotNull(files.Result); var item = Assert.Single(files.Result); Assert.Equal(item, file.Result); } public async Task CreateFileTest2Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); var directoryNodeId = $"nsu=FileSystem;s=1:{path}"; var file = await services.CreateFileAsync(_connection, new FileSystemObjectModel { NodeId = directoryNodeId }, "testfile", ct).ConfigureAwait(false); Assert.Null(file.ErrorInfo); Assert.True(File.Exists(Path.Combine(path, "testfile"))); var file2 = await services.CreateFileAsync(_connection, new FileSystemObjectModel { NodeId = directoryNodeId }, "testfile", ct).ConfigureAwait(false); Assert.Null(file2.Result); Assert.NotNull(file2.ErrorInfo); Assert.Equal(Opc.Ua.StatusCodes.BadBrowseNameDuplicated, file2.ErrorInfo.StatusCode); } public async Task CreateFileTest3Async(CancellationToken ct = default) { var services = _services(); var root = _tempPath; var p1 = Path.GetRandomFileName(); var p2 = Path.GetRandomFileName(); var path = Path.Combine(root, p1, p2); Directory.CreateDirectory(path); Assert.Empty(Directory.GetFiles(path)); var file = await services.CreateFileAsync(_connection, new FileSystemObjectModel { NodeId = $"nsu=FileSystem;s=1:{root}", BrowsePath = new List { $"nsu=FileSystem;{p1}", $"nsu=FileSystem;{p2}" } }, "testfile", ct).ConfigureAwait(false); Assert.Null(file.ErrorInfo); Assert.True(File.Exists(Path.Combine(path, "testfile"))); } public async Task CreateFileTest4Async(CancellationToken ct = default) { var services = _services(); var root = _tempPath; var p1 = Path.GetRandomFileName(); var p2 = Path.GetRandomFileName(); var path = Path.Combine(root, p1, p2); Directory.CreateDirectory(path); Assert.Empty(Directory.GetFiles(path)); var file = await services.CreateFileAsync(_connection, new FileSystemObjectModel { NodeId = $"nsu=FileSystem;s=1:{root}", BrowsePath = new List { $"nsu=FileSystem;{p1}", "nsu=FileSystem;Bad" } }, "testfile", ct).ConfigureAwait(false); Assert.NotNull(file.ErrorInfo); } public async Task GetFileInfoTest1Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); var path2 = CreateFile(path, "testfile", 1024); var fileNodeId = $"nsu=FileSystem;s=2:{path2}"; var fileInfo = await services.GetFileInfoAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.Null(fileInfo.ErrorInfo); Assert.NotNull(fileInfo.Result); Assert.Equal(1024, fileInfo.Result.Size); Assert.True(fileInfo.Result.Writable); Assert.Equal(0, fileInfo.Result.OpenCount); } public async Task GetFileInfoTest2Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); var fileNodeId = $"nsu=FileSystem;s=2:{Path.Combine(path, "bad")}"; var fileInfo = await services.GetFileInfoAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.NotNull(fileInfo.ErrorInfo); Assert.Null(fileInfo.Result); } public async Task GetFileInfoTest3Async(CancellationToken ct = default) { var services = _services(); var root = _tempPath; var p1 = Path.GetRandomFileName(); var p2 = Path.GetRandomFileName(); var f = Path.GetRandomFileName(); var path = Path.Combine(root, p1, p2); Directory.CreateDirectory(path); CreateFile(path, f, 100); var fileInfo = await services.GetFileInfoAsync(_connection, new FileSystemObjectModel { NodeId = $"nsu=FileSystem;s=1:{Path.Combine(root, p1)}", BrowsePath = new List { $"nsu=FileSystem;{p2}", $"nsu=FileSystem;{f}" } }, ct).ConfigureAwait(false); Assert.Null(fileInfo.ErrorInfo); Assert.NotNull(fileInfo.Result); Assert.Equal(100, fileInfo.Result.Size); Assert.True(fileInfo.Result.Writable); Assert.Equal(0, fileInfo.Result.OpenCount); } public async Task DeleteFileTest1Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); var path2 = CreateFile(path, "testfile", 1024); var fileToDeleteId = $"nsu=FileSystem;s=2:{path2}"; Assert.NotEmpty(Directory.GetFiles(path)); var result = await services.DeleteFileSystemObjectAsync(_connection, new FileSystemObjectModel { NodeId = fileToDeleteId }, ct: ct).ConfigureAwait(false); Assert.NotNull(result); Assert.Equal(0u, result.StatusCode); Assert.Empty(Directory.GetFiles(path)); } public async Task DeleteFileTest2Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); var path2 = CreateFile(path, "testfile", 1024); Assert.NotEmpty(Directory.GetFiles(path)); var parentDirectoryId = $"nsu=FileSystem;s=1:{path}"; var fileToDeleteId = $"nsu=FileSystem;s=2:{path2}"; var result = await services.DeleteFileSystemObjectAsync(_connection, new FileSystemObjectModel { NodeId = fileToDeleteId }, new FileSystemObjectModel { NodeId = parentDirectoryId }, ct).ConfigureAwait(false); Assert.NotNull(result); Assert.Equal(0u, result.StatusCode); Assert.Empty(Directory.GetFiles(path)); } public async Task DeleteFileTest3Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); var parentDirectoryId = $"nsu=FileSystem;s=1:{path}"; var fileToDeleteId = $"nsu=FileSystem;s=2:{Path.Combine(path, "wrong")}"; var result = await services.DeleteFileSystemObjectAsync(_connection, new FileSystemObjectModel { NodeId = fileToDeleteId }, new FileSystemObjectModel { NodeId = parentDirectoryId }, ct).ConfigureAwait(false); Assert.NotNull(result); Assert.Equal(Opc.Ua.StatusCodes.BadNotFound, result.StatusCode); } public async Task DeleteFileTest4Async(CancellationToken ct = default) { var services = _services(); var root = _tempPath; var p1 = Path.GetRandomFileName(); var p2 = Path.GetRandomFileName(); var f = Path.GetRandomFileName(); var path = Path.Combine(root, p1, p2); Directory.CreateDirectory(path); CreateFile(path, f, 100); Assert.NotEmpty(Directory.GetFiles(path)); var result = await services.DeleteFileSystemObjectAsync(_connection, new FileSystemObjectModel { NodeId = $"nsu=FileSystem;s=1:{Path.Combine(root, p1)}", BrowsePath = new List { $"nsu=FileSystem;{p2}", $"nsu=FileSystem;{f}" } }, ct: ct).ConfigureAwait(false); Assert.NotNull(result); Assert.Equal(0u, result.StatusCode); Assert.Empty(Directory.GetFiles(path)); } public async Task DeleteFileTest5Async(CancellationToken ct = default) { var services = _services(); var root = _tempPath; var p1 = Path.GetRandomFileName(); var p2 = Path.GetRandomFileName(); var f = Path.GetRandomFileName(); var path = Path.Combine(root, p1, p2); Directory.CreateDirectory(path); CreateFile(path, f, 100); Assert.NotEmpty(Directory.GetFiles(path)); var result = await services.DeleteFileSystemObjectAsync(_connection, new FileSystemObjectModel { NodeId = $"nsu=FileSystem;s=1:{Path.Combine(root, p1)}", BrowsePath = new List { $"nsu=FileSystem;{p2}", "nsu=FileSystem;Notexisting" } }, ct: ct).ConfigureAwait(false); Assert.NotNull(result); Assert.Equal(Opc.Ua.StatusCodes.BadNotFound, result.StatusCode); } private static string CreateFile(string path, string name, long length) { var fullPath = Path.Combine(path, name); using var f = File.Create(fullPath); var buffer = new byte[length]; for (var i = 0; i < buffer.Length; i++) { buffer[i] = (byte)i; } f.Write(buffer); return fullPath; } private readonly T _connection; private readonly string _tempPath; private readonly Func> _services; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/FileSystem/ReadTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.IO; using System.Threading; using System.Threading.Tasks; using Xunit; public class ReadTests { /// /// Create tests /// /// /// /// public ReadTests(Func> services, T connection, string tempPath) { _services = services; _connection = connection; _tempPath = tempPath; } public async Task ReadFileTest0Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); var file = CreateFile(path, "testfile", 1 * 1024 * 1024); var fileNodeId = $"nsu=FileSystem;s=2:{file}"; var stream = await services.OpenReadAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.Null(stream.ErrorInfo); Assert.NotNull(stream.Result); await using var _ = stream.Result.ConfigureAwait(false); var buffer = new byte[256 * 1024]; await stream.Result.ReadExactlyAsync(buffer, ct).ConfigureAwait(false); for (var i = 0; i < buffer.Length; i++) { Assert.Equal((byte)i, buffer[i]); } await stream.Result.ReadExactlyAsync(buffer, ct).ConfigureAwait(false); } public async Task ReadFileTest1Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); var file = CreateFile(path, "testfile", 1024); var fileNodeId = $"nsu=FileSystem;s=2:{file}"; var stream = await services.OpenReadAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.Null(stream.ErrorInfo); Assert.NotNull(stream.Result); await using (var _ = stream.Result.ConfigureAwait(false)) { var fi = await services.GetFileInfoAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.NotNull(fi.Result); Assert.Equal(1024, fi.Result.Size); Assert.Equal(1, fi.Result.OpenCount); Assert.False(fi.Result.Writable); var buffer = new byte[1024]; var read = await stream.Result.ReadAsync(buffer, ct).ConfigureAwait(false); Assert.Equal(read, buffer.Length); for (var i = 0; i < buffer.Length; i++) { Assert.Equal((byte)i, buffer[i]); } read = await stream.Result.ReadAsync(buffer, ct).ConfigureAwait(false); Assert.Equal(0, read); } { // Now check it is closed var fi = await services.GetFileInfoAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.NotNull(fi.Result); Assert.Equal(0, fi.Result.OpenCount); Assert.True(fi.Result.Writable); } } public async Task ReadFileTest2Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); var file = CreateFile(path, "testfile", 1 * 1024 * 1024); var fileNodeId = $"nsu=FileSystem;s=2:{file}"; var stream = await services.OpenReadAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.Null(stream.ErrorInfo); Assert.NotNull(stream.Result); await using (var _ = stream.Result.ConfigureAwait(false)) { var fi = await services.GetFileInfoAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.NotNull(fi.Result); Assert.Equal(1 * 1024 * 1024, fi.Result.Size); Assert.Equal(1, fi.Result.OpenCount); Assert.False(fi.Result.Writable); var buffer = new byte[256 * 1024]; var read = await stream.Result.ReadAsync(buffer, ct).ConfigureAwait(false); Assert.Equal(read, buffer.Length); for (var i = 0; i < buffer.Length; i++) { Assert.Equal((byte)i, buffer[i]); } read = await stream.Result.ReadAsync(buffer, ct).ConfigureAwait(false); Assert.Equal(buffer.Length, read); } { // Now check it is closed var fi = await services.GetFileInfoAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.NotNull(fi.Result); Assert.Equal(0, fi.Result.OpenCount); Assert.True(fi.Result.Writable); } } public async Task ReadFileTest3Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); var file = CreateFile(path, "testfile", 1024); var fileNodeId = $"nsu=FileSystem;s=2:{file}"; var stream = await services.OpenReadAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.Null(stream.ErrorInfo); Assert.NotNull(stream.Result); await using (var _ = stream.Result.ConfigureAwait(false)) { var fi = await services.GetFileInfoAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.NotNull(fi.Result); Assert.Equal(1024, fi.Result.Size); Assert.Equal(1, fi.Result.OpenCount); Assert.False(fi.Result.Writable); var buffer = new byte[2 * 1024]; var read = await stream.Result.ReadAsync(buffer, ct).ConfigureAwait(false); Assert.Equal(1024, read); for (var i = 0; i < read; i++) { Assert.Equal((byte)i, buffer[i]); } read = await stream.Result.ReadAsync(buffer, ct).ConfigureAwait(false); Assert.Equal(0, read); } { // Now check it is closed var fi = await services.GetFileInfoAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.NotNull(fi.Result); Assert.Equal(0, fi.Result.OpenCount); Assert.True(fi.Result.Writable); } } public async Task ReadFileTest4Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); var file = CreateFile(path, "testfile", 1024); var fileNodeId = $"nsu=FileSystem;s=2:{file}"; var stream1 = await services.OpenReadAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.Null(stream1.ErrorInfo); Assert.NotNull(stream1.Result); await using var __ = stream1.Result.ConfigureAwait(false); var stream = await services.OpenReadAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.Null(stream.ErrorInfo); Assert.NotNull(stream.Result); await using (var _ = stream.Result.ConfigureAwait(false)) { var fi = await services.GetFileInfoAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.NotNull(fi.Result); Assert.Equal(1024, fi.Result.Size); Assert.Equal(2, fi.Result.OpenCount); Assert.False(fi.Result.Writable); var buffer = new byte[2 * 1024]; var read = await stream.Result.ReadAsync(buffer, ct).ConfigureAwait(false); Assert.Equal(1024, read); for (var i = 0; i < read; i++) { Assert.Equal((byte)i, buffer[i]); } read = await stream.Result.ReadAsync(buffer, ct).ConfigureAwait(false); Assert.Equal(0, read); } { // Now check it is closed var fi = await services.GetFileInfoAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.NotNull(fi.Result); Assert.Equal(1, fi.Result.OpenCount); Assert.False(fi.Result.Writable); } } private static string CreateFile(string path, string name, long length) { var fullPath = Path.Combine(path, name); using var f = File.Create(fullPath); var buffer = new byte[length]; for (var i = 0; i < buffer.Length; i++) { buffer[i] = (byte)i; } f.Write(buffer); return fullPath; } private readonly T _connection; private readonly string _tempPath; private readonly Func> _services; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/FileSystem/WriteTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using Xunit; public class WriteTests { /// /// Create tests /// /// /// /// public WriteTests(Func> services, T connection, string tempPath) { _services = services; _connection = connection; _tempPath = tempPath; } public async Task WriteFileTest0Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); var file = CreateFile(path, "testfile", 8 * 1024); var fileNodeId = $"nsu=FileSystem;s=2:{file}"; var stream = await services.OpenWriteAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct: ct).ConfigureAwait(false); Assert.Null(stream.ErrorInfo); Assert.NotNull(stream.Result); await using (var _ = stream.Result.ConfigureAwait(false)) { // Now write file var buffer = Enumerable.Range(0, 1024).Select(b => (byte)b).ToArray(); await stream.Result.WriteAsync(buffer, ct).ConfigureAwait(false); } { var buffer = await File.ReadAllBytesAsync(file, ct).ConfigureAwait(false); Assert.Equal(1024, buffer.Length); for (var i = 0; i < buffer.Length; i++) { Assert.Equal((byte)i, buffer[i]); } } } public async Task WriteFileTest1Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); var file = CreateFile(path, "testfile", 8 * 1024); var fileNodeId = $"nsu=FileSystem;s=2:{file}"; var fi = await services.GetFileInfoAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.NotNull(fi.Result); Assert.Equal(8 * 1024, fi.Result.Size); Assert.Equal(0, fi.Result.OpenCount); var stream = await services.OpenWriteAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct: ct).ConfigureAwait(false); Assert.Null(stream.ErrorInfo); Assert.NotNull(stream.Result); await using (var _ = stream.Result.ConfigureAwait(false)) { fi = await services.GetFileInfoAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.NotNull(fi.Result); Assert.Equal(0, fi.Result.Size); Assert.Equal(1, fi.Result.OpenCount); // Now write file var buffer = Enumerable.Range(0, 1024).Select(b => (byte)b).ToArray(); await stream.Result.WriteAsync(buffer, ct).ConfigureAwait(false); } { // Now check it is closed fi = await services.GetFileInfoAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.NotNull(fi.Result); Assert.Equal(0, fi.Result.OpenCount); Assert.True(fi.Result.Writable); Assert.Equal(1024, fi.Result.Size); var buffer = await File.ReadAllBytesAsync(file, ct).ConfigureAwait(false); Assert.Equal(1024, buffer.Length); for (var i = 0; i < buffer.Length; i++) { Assert.Equal((byte)i, buffer[i]); } } } public async Task WriteFileTest2Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); var file = CreateFile(path, "testfile", 2 * 1024 * 1024); var fileNodeId = $"nsu=FileSystem;s=2:{file}"; var fi = await services.GetFileInfoAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.NotNull(fi.Result); Assert.Equal(2 * 1024 * 1024, fi.Result.Size); Assert.Equal(0, fi.Result.OpenCount); var stream = await services.OpenWriteAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, new FileOpenWriteOptionsModel { Mode = FileWriteMode.Write }, ct).ConfigureAwait(false); Assert.Null(stream.ErrorInfo); Assert.NotNull(stream.Result); await using (var _ = stream.Result.ConfigureAwait(false)) { fi = await services.GetFileInfoAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.NotNull(fi.Result); Assert.Equal(2 * 1024 * 1024, fi.Result.Size); Assert.Equal(1, fi.Result.OpenCount); // Now write first half of file var buffer = new byte[1 * 1024 * 1024]; await stream.Result.WriteAsync(buffer, ct).ConfigureAwait(false); } { // Now check it is closed fi = await services.GetFileInfoAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.NotNull(fi.Result); Assert.Equal(0, fi.Result.OpenCount); Assert.True(fi.Result.Writable); Assert.Equal(2 * 1024 * 1024, fi.Result.Size); var buffer = await File.ReadAllBytesAsync(file, ct).ConfigureAwait(false); Assert.Equal(2 * 1024 * 1024, buffer.Length); for (var i = 0; i < buffer.Length / 2; i++) { Assert.Equal(0, buffer[i]); } for (var i = buffer.Length / 2; i < buffer.Length; i++) { Assert.Equal((byte)i, buffer[i]); } } } public async Task AppendFileTest0Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); var file = CreateFile(path, "testfile", 8 * 1024); var fileNodeId = $"nsu=FileSystem;s=2:{file}"; var stream = await services.OpenWriteAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, new FileOpenWriteOptionsModel { Mode = FileWriteMode.Append }, ct).ConfigureAwait(false); Assert.Null(stream.ErrorInfo); Assert.NotNull(stream.Result); await using (var _ = stream.Result.ConfigureAwait(false)) { // Now write file var buffer = Enumerable.Range(8 * 1024, 2 * 1024).Select(b => (byte)b).ToArray(); await stream.Result.WriteAsync(buffer, ct).ConfigureAwait(false); } { var buffer = await File.ReadAllBytesAsync(file, ct).ConfigureAwait(false); Assert.Equal(10 * 1024, buffer.Length); for (var i = 0; i < buffer.Length; i++) { Assert.Equal((byte)i, buffer[i]); } } } public async Task AppendFileTest1Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); var file = CreateFile(path, "testfile", 8 * 1024); var fileNodeId = $"nsu=FileSystem;s=2:{file}"; var fi = await services.GetFileInfoAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.NotNull(fi.Result); Assert.Equal(8 * 1024, fi.Result.Size); Assert.Equal(0, fi.Result.OpenCount); var stream = await services.OpenWriteAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, new FileOpenWriteOptionsModel { Mode = FileWriteMode.Append }, ct).ConfigureAwait(false); Assert.Null(stream.ErrorInfo); Assert.NotNull(stream.Result); await using (var _ = stream.Result.ConfigureAwait(false)) { fi = await services.GetFileInfoAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.NotNull(fi.Result); Assert.Equal(8 * 1024, fi.Result.Size); Assert.Equal(1, fi.Result.OpenCount); // Now write file var buffer = Enumerable.Range(8 * 1024, 2 * 1024).Select(b => (byte)b).ToArray(); await stream.Result.WriteAsync(buffer, ct).ConfigureAwait(false); } { // Now check it is closed fi = await services.GetFileInfoAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.NotNull(fi.Result); Assert.Equal(0, fi.Result.OpenCount); Assert.True(fi.Result.Writable); Assert.Equal(10 * 1024, fi.Result.Size); var buffer = await File.ReadAllBytesAsync(file, ct).ConfigureAwait(false); Assert.Equal(10 * 1024, buffer.Length); for (var i = 0; i < buffer.Length; i++) { Assert.Equal((byte)i, buffer[i]); } } } public async Task AppendFileTest2Async(CancellationToken ct = default) { var services = _services(); var path = Path.Combine(_tempPath, Path.GetRandomFileName()); Directory.CreateDirectory(path); var file = Path.Combine(path, "testfile"); var fileNodeId = $"nsu=FileSystem;s=2:{file}"; await File.Create(file).DisposeAsync().ConfigureAwait(false); for (var i = 0; i < 10; i++) { var stream = await services.OpenWriteAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, new FileOpenWriteOptionsModel { Mode = FileWriteMode.Append }, ct).ConfigureAwait(false); Assert.Null(stream.ErrorInfo); Assert.NotNull(stream.Result); await using var _ = stream.Result.ConfigureAwait(false); // Now write file var buffer = new byte[130000]; Array.Fill(buffer, (byte)i); await stream.Result.WriteAsync(buffer, ct).ConfigureAwait(false); } { // Now check it is closed var fi = await services.GetFileInfoAsync(_connection, new FileSystemObjectModel { NodeId = fileNodeId }, ct).ConfigureAwait(false); Assert.NotNull(fi.Result); Assert.Equal(0, fi.Result.OpenCount); Assert.True(fi.Result.Writable); Assert.Equal(10 * 130000, fi.Result.Size); var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); await using var _ = fs.ConfigureAwait(false); for (var i = 0; i < 10; i++) { fs.Seek(i * 130000, SeekOrigin.Begin); Assert.Equal(i, fs.ReadByte()); } } } private static string CreateFile(string path, string name, long length) { var fullPath = Path.Combine(path, name); using var f = File.Create(fullPath); var buffer = new byte[length]; for (var i = 0; i < buffer.Length; i++) { buffer[i] = (byte)i; } f.Write(buffer); return fullPath; } private readonly T _connection; private readonly string _tempPath; private readonly Func> _services; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/HistoricalAccess/HistoryReadValuesAtTimes.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.Linq; using System.Threading; using System.Threading.Tasks; using Xunit; public class HistoryReadValuesAtTimesTests { /// /// Create history services tests /// /// /// /// public HistoryReadValuesAtTimesTests(BaseServerFixture server, Func> services, T connection) { _server = server; _services = services; _connection = connection; } public async Task HistoryReadInt32ValuesAtTimesTest1Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int32.txt"; var startTime = _server.Now.Subtract(TimeSpan.FromHours(1)); var results = await services.HistoryReadValuesAtTimesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadValuesAtTimesDetailsModel { ReqTimes = Enumerable.Repeat(0, 10).Select((_, i) => startTime.AddMilliseconds(i * 10000)).ToArray(), UseSimpleBounds = true } }, ct).ConfigureAwait(false); Assert.NotNull(results.History); Assert.Equal(10, results.History.Length); Assert.All(results.History, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 10); Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Null(arg.AdditionalData); Assert.Equal(DataLocation.Interpolated, arg.DataLocation); }); } public async Task HistoryReadInt32ValuesAtTimesTest2Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int32.txt"; var startTime = _server.Now.Subtract(TimeSpan.FromHours(1)); var results = await services.HistoryReadValuesAtTimesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadValuesAtTimesDetailsModel { ReqTimes = Enumerable.Repeat(0, 10).Select((_, i) => startTime.AddMilliseconds(i * 10000)).ToArray(), UseSimpleBounds = false } }, ct).ConfigureAwait(false); Assert.NotNull(results.History); Assert.Equal(10, results.History.Length); Assert.All(results.History, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 10); Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Null(arg.AdditionalData); Assert.Equal(DataLocation.Interpolated, arg.DataLocation); }); } public async Task HistoryReadInt32ValuesAtTimesTest3Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int32.txt"; var startTime = _server.Now.Subtract(TimeSpan.FromHours(1)); var results = await services.HistoryReadValuesAtTimesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadValuesAtTimesDetailsModel { ReqTimes = Enumerable.Repeat(0, 1).Select((_, i) => startTime.AddMilliseconds(i * 10000)).ToArray(), UseSimpleBounds = true } }, ct).ConfigureAwait(false); Assert.NotNull(results.History); Assert.Equal(1, results.History.Length); Assert.All(results.History, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 10); Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Null(arg.AdditionalData); Assert.Equal(DataLocation.Interpolated, arg.DataLocation); }); } public async Task HistoryReadInt32ValuesAtTimesTest4Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int32.txt"; var startTime = _server.Now.Subtract(TimeSpan.FromHours(1)); var results = await services.HistoryReadValuesAtTimesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, TimestampsToReturn = TimestampsToReturn.Source, Details = new ReadValuesAtTimesDetailsModel { ReqTimes = Enumerable.Repeat(0, 1).Select((_, i) => startTime.AddMilliseconds(i * 10000)).ToArray(), UseSimpleBounds = false } }, ct).ConfigureAwait(false); Assert.NotNull(results.History); Assert.Equal(1, results.History.Length); Assert.All(results.History, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 10); Assert.NotNull(arg.SourceTimestamp); // Assert.Null(arg.ServerTimestamp); Assert.Null(arg.AdditionalData); Assert.Equal(DataLocation.Interpolated, arg.DataLocation); }); } public async Task HistoryStreamInt32ValuesAtTimesTest1Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int32.txt"; var startTime = _server.Now.Subtract(TimeSpan.FromHours(5)); var history = await services.HistoryStreamValuesAtTimesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadValuesAtTimesDetailsModel { ReqTimes = Enumerable.Repeat(0, 500).Select((_, i) => startTime.AddMilliseconds(i * 10000)).ToArray(), UseSimpleBounds = false } }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); Assert.NotNull(history); Assert.Equal(500, history.Count); Assert.All(history, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 10); Assert.Equal(DataLocation.Interpolated, arg.DataLocation); }); } public async Task HistoryStreamInt32ValuesAtTimesTest2Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int32.txt"; var startTime = _server.Now.Subtract(TimeSpan.FromHours(5)); var history = await services.HistoryStreamValuesAtTimesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadValuesAtTimesDetailsModel { ReqTimes = Enumerable.Repeat(0, 500).Select((_, i) => startTime.AddMilliseconds(i * 10000)).ToArray(), UseSimpleBounds = true } }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); Assert.NotNull(history); Assert.Equal(500, history.Count); Assert.All(history, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 10); Assert.Equal(DataLocation.Interpolated, arg.DataLocation); }); } private readonly T _connection; private readonly BaseServerFixture _server; private readonly Func> _services; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/HistoricalAccess/HistoryReadValuesModified.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.Linq; using System.Threading; using System.Threading.Tasks; using Xunit; public class HistoryReadValuesModifiedTests { /// /// Create history services tests /// /// /// /// public HistoryReadValuesModifiedTests(BaseServerFixture server, Func> services, T connection) { _server = server; _services = services; _connection = connection; } public async Task HistoryReadInt16ValuesModifiedTestAsync(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int16.txt"; var results = await services.HistoryReadModifiedValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadModifiedValuesDetailsModel { StartTime = _server.Now - TimeSpan.FromDays(600), EndTime = _server.Now + TimeSpan.FromDays(1), NumValues = 14 } }, ct).ConfigureAwait(false); Assert.NotNull(results.History); Assert.Equal(0, results.History.Length); Assert.Empty(results.History); } public async Task HistoryStreamInt16ValuesModifiedTestAsync(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int16.txt"; var history = await services.HistoryStreamModifiedValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadModifiedValuesDetailsModel { EndTime = _server.Now + TimeSpan.FromDays(1), NumValues = 10 } }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); Assert.NotNull(history); Assert.Equal(0, history.Count); } private readonly T _connection; private readonly BaseServerFixture _server; private readonly Func> _services; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/HistoricalAccess/HistoryReadValuesProcessed.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Extensions.Serializers; using System; using System.Linq; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Xunit; public class HistoryReadValuesProcessedTests { /// /// Create history services tests /// /// /// /// public HistoryReadValuesProcessedTests(BaseServerFixture server, Func> services, T connection) { _server = server; _services = services; _connection = connection; } public async Task HistoryReadUInt64ProcessedValuesTest1Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.UInt64.txt"; var now = _server.Now; now = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 0, 0, DateTimeKind.Utc); var results = await services.HistoryReadProcessedValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadProcessedValuesDetailsModel { StartTime = now - TimeSpan.FromHours(1), EndTime = now, ProcessingInterval = TimeSpan.FromMinutes(1), AggregateType = "i=2347" } }, ct).ConfigureAwait(false); Assert.NotNull(results.History); Assert.All(results.History.Where(h => VariantValue.IsNullOrNullValue(h.Value)), arg => { Assert.Equal("BadNoData", arg.Status?.SymbolicId); Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Null(arg.Value); Assert.Null(arg.DataLocation); Assert.Null(arg.AdditionalData); }); var values = results.History.Where(h => !VariantValue.IsNullOrNullValue(h.Value)).ToList(); Assert.True(values.Count == 2, JsonSerializer.Serialize(values)); Assert.Equal(2, values.Count); Assert.Collection(values, arg => { Assert.Equal("UncertainDataSubNormal", arg.Status?.SymbolicId); Assert.True(arg.Value == 50); Assert.Equal(DataLocation.Calculated, arg.DataLocation); Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Equal(AdditionalData.Partial, arg.AdditionalData); }, arg => { Assert.Equal("UncertainDataSubNormal", arg.Status?.SymbolicId); Assert.True(arg.Value == 90); Assert.Equal(DataLocation.Calculated, arg.DataLocation); Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Equal(AdditionalData.Partial, arg.AdditionalData); }); } public async Task HistoryReadUInt64ProcessedValuesTest2Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.UInt64.txt"; var now = _server.Now; now = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 0, 0, DateTimeKind.Utc); var results = await services.HistoryReadProcessedValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadProcessedValuesDetailsModel { StartTime = now - TimeSpan.FromHours(1), EndTime = now, ProcessingInterval = TimeSpan.FromMinutes(1), AggregateType = "Count" } }, ct).ConfigureAwait(false); Assert.NotNull(results.History); Assert.All(results.History.Where(h => VariantValue.IsNullOrNullValue(h.Value)), arg => { Assert.Equal("BadNoData", arg.Status?.SymbolicId); Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Null(arg.Value); Assert.Null(arg.DataLocation); Assert.Null(arg.AdditionalData); }); var values = results.History.Where(h => !VariantValue.IsNullOrNullValue(h.Value)).ToList(); Assert.True(values.Count == 2, JsonSerializer.Serialize(values)); Assert.Equal(2, values.Count); Assert.Collection(values, arg => { Assert.Equal("UncertainDataSubNormal", arg.Status?.SymbolicId); Assert.True(arg.Value == 6); Assert.Equal(DataLocation.Calculated, arg.DataLocation); Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Equal(AdditionalData.Partial, arg.AdditionalData); }, arg => { Assert.Equal("UncertainDataSubNormal", arg.Status?.SymbolicId); Assert.True(arg.Value == 4); Assert.Equal(DataLocation.Calculated, arg.DataLocation); Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Equal(AdditionalData.Partial, arg.AdditionalData); }); } public async Task HistoryReadUInt64ProcessedValuesTest3Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.UInt64.txt"; var now = _server.Now; now = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 0, 0, DateTimeKind.Utc); var results = await services.HistoryReadProcessedValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadProcessedValuesDetailsModel { StartTime = now - TimeSpan.FromHours(1), EndTime = now, ProcessingInterval = TimeSpan.FromMinutes(20), AggregateType = "Delta" } }, ct).ConfigureAwait(false); Assert.NotNull(results.History); Assert.All(results.History.Where(h => VariantValue.IsNullOrNullValue(h.Value)), arg => { Assert.Equal("BadNoData", arg.Status?.SymbolicId); Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Null(arg.Value); Assert.Null(arg.DataLocation); Assert.Null(arg.AdditionalData); }); Assert.True(results.History.Count(h => !VariantValue.IsNullOrNullValue(h.Value)) == 1, JsonSerializer.Serialize(results.History)); var arg = Assert.Single(results.History.Where(h => !VariantValue.IsNullOrNullValue(h.Value))); Assert.Null(arg.Status); Assert.True(arg.Value == 80, JsonSerializer.Serialize(arg)); Assert.Equal(DataLocation.Calculated, arg.DataLocation); Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Equal(AdditionalData.Partial, arg.AdditionalData); } public async Task HistoryStreamUInt64ProcessedValuesTest1Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.UInt64.txt"; var now = _server.Now; now = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 0, 0, DateTimeKind.Utc); var history = await services.HistoryStreamProcessedValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadProcessedValuesDetailsModel { StartTime = now - TimeSpan.FromHours(1), EndTime = now, ProcessingInterval = TimeSpan.FromMinutes(1), AggregateType = "i=2347" } }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); Assert.NotNull(history); Assert.All(history.Where(h => VariantValue.IsNullOrNullValue(h.Value)), arg => { Assert.Equal("BadNoData", arg.Status?.SymbolicId); Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Null(arg.Value); Assert.Null(arg.DataLocation); Assert.Null(arg.AdditionalData); }); var values = history.Where(h => !VariantValue.IsNullOrNullValue(h.Value)).ToList(); Assert.True(values.Count == 2, JsonSerializer.Serialize(values)); Assert.Equal(2, values.Count); Assert.Collection(values, arg => { Assert.Equal("UncertainDataSubNormal", arg.Status?.SymbolicId); Assert.True(arg.Value == 50); Assert.Equal(DataLocation.Calculated, arg.DataLocation); Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Equal(AdditionalData.Partial, arg.AdditionalData); }, arg => { Assert.Equal("UncertainDataSubNormal", arg.Status?.SymbolicId); Assert.True(arg.Value == 90); Assert.Equal(DataLocation.Calculated, arg.DataLocation); Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Equal(AdditionalData.Partial, arg.AdditionalData); }); } public async Task HistoryStreamUInt64ProcessedValuesTest2Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.UInt64.txt"; var now = _server.Now; now = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 0, 0, DateTimeKind.Utc); var history = await services.HistoryStreamProcessedValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadProcessedValuesDetailsModel { StartTime = now - TimeSpan.FromHours(1), EndTime = now, ProcessingInterval = TimeSpan.FromMinutes(1), AggregateType = "Count" } }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); Assert.NotNull(history); Assert.All(history.Where(h => VariantValue.IsNullOrNullValue(h.Value)), arg => { Assert.Equal("BadNoData", arg.Status?.SymbolicId); Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Null(arg.Value); Assert.Null(arg.DataLocation); Assert.Null(arg.AdditionalData); }); var values = history.Where(h => !VariantValue.IsNullOrNullValue(h.Value)).ToList(); Assert.True(values.Count == 2, JsonSerializer.Serialize(values)); Assert.Equal(2, values.Count); Assert.Collection(values, arg => { Assert.Equal("UncertainDataSubNormal", arg.Status?.SymbolicId); Assert.True(arg.Value == 6); Assert.Equal(DataLocation.Calculated, arg.DataLocation); Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Equal(AdditionalData.Partial, arg.AdditionalData); }, arg => { Assert.Equal("UncertainDataSubNormal", arg.Status?.SymbolicId); Assert.True(arg.Value == 4); Assert.Equal(DataLocation.Calculated, arg.DataLocation); Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Equal(AdditionalData.Partial, arg.AdditionalData); }); } public async Task HistoryStreamUInt64ProcessedValuesTest3Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.UInt64.txt"; var now = _server.Now; now = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 0, 0, DateTimeKind.Utc); var history = await services.HistoryStreamProcessedValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadProcessedValuesDetailsModel { StartTime = now - TimeSpan.FromHours(1), EndTime = now, ProcessingInterval = TimeSpan.FromMinutes(10), AggregateType = "Delta" } }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); Assert.NotNull(history); Assert.All(history.Where(h => VariantValue.IsNullOrNullValue(h.Value)), arg => { Assert.Equal("BadNoData", arg.Status?.SymbolicId); Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Null(arg.Value); Assert.Null(arg.DataLocation); Assert.Null(arg.AdditionalData); }); Assert.True(history.Count(h => !VariantValue.IsNullOrNullValue(h.Value)) == 1, JsonSerializer.Serialize(history)); var arg = Assert.Single(history.Where(h => !VariantValue.IsNullOrNullValue(h.Value))); Assert.Null(arg.Status); Assert.True(arg.Value == 80); Assert.Equal(DataLocation.Calculated, arg.DataLocation); Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Equal(AdditionalData.Partial, arg.AdditionalData); } private readonly T _connection; private readonly BaseServerFixture _server; private readonly Func> _services; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/HistoricalAccess/HistoryReadValuesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.Linq; using System.Threading; using System.Threading.Tasks; using Xunit; public class HistoryReadValuesTests { /// /// Create history services tests /// /// /// /// public HistoryReadValuesTests(BaseServerFixture server, Func> services, T connection) { _server = server; _services = services; _connection = connection; } public async Task HistoryReadInt64ValuesTest1Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int64.txt"; var results = await services.HistoryReadValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadValuesDetailsModel { StartTime = _server.Now - TimeSpan.FromDays(600), EndTime = _server.Now + TimeSpan.FromDays(1), ReturnBounds = true } }, ct).ConfigureAwait(false); Assert.NotNull(results.History); Assert.Equal(14, results.History.Length); Assert.Collection(results.History, arg => { Assert.Equal(2161573888, arg.Status?.StatusCode); Assert.Null(arg.Value); Assert.Null(arg.DataLocation); Assert.Null(arg.AdditionalData); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 10); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 20); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 25); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 30); }, arg => { Assert.Equal(2147483648, arg.Status?.StatusCode); Assert.Null(arg.Value); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 40); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 50); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 60); }, arg => { Assert.Equal(1073741824u, arg.Status?.StatusCode); Assert.True(arg.Value == 70); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 70); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 80); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 90); }, arg => { Assert.Equal(2161573888, arg.Status?.StatusCode); Assert.Null(arg.Value); }); Assert.All(results.History, arg => { Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Null(arg.AdditionalData); Assert.Null(arg.DataLocation); }); } public async Task HistoryReadInt64ValuesTest2Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int64.txt"; var results = await services.HistoryReadValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadValuesDetailsModel { StartTime = _server.Now - TimeSpan.FromDays(600), NumValues = 10 } }, ct).ConfigureAwait(false); Assert.NotNull(results.History); Assert.Equal(10, results.History.Length); Assert.Collection(results.History, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 10); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 20); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 25); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 30); }, arg => { Assert.Equal(2147483648u, arg.Status?.StatusCode); Assert.Null(arg.Value); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 40); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 50); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 60); }, arg => { Assert.Equal(1073741824u, arg.Status?.StatusCode); Assert.True(arg.Value == 70); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 70); }); Assert.All(results.History, arg => { Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Null(arg.AdditionalData); Assert.Null(arg.DataLocation); }); } public async Task HistoryReadInt64ValuesTest3Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int64.txt"; var results = await services.HistoryReadValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadValuesDetailsModel { StartTime = _server.Now - TimeSpan.FromDays(600), EndTime = _server.Now + TimeSpan.FromDays(1) } }, ct).ConfigureAwait(false); Assert.NotNull(results.History); Assert.Equal(12, results.History.Length); Assert.Collection(results.History, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 10); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 20); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 25); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 30); }, arg => { Assert.Equal(2147483648, arg.Status?.StatusCode); Assert.Null(arg.Value); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 40); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 50); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 60); }, arg => { Assert.Equal(1073741824u, arg.Status?.StatusCode); Assert.True(arg.Value == 70); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 70); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 80); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 90); }); Assert.All(results.History, arg => { Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Null(arg.AdditionalData); Assert.Null(arg.DataLocation); }); } public async Task HistoryReadInt64ValuesTest4Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int64.txt"; var results = await services.HistoryReadValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadValuesDetailsModel { EndTime = _server.Now + TimeSpan.FromDays(1), NumValues = 10 } }, ct).ConfigureAwait(false); Assert.NotNull(results.History); Assert.Equal(10, results.History.Length); Assert.Collection(results.History, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 90); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 80); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 70); }, arg => { Assert.Equal(1073741824u, arg.Status?.StatusCode); Assert.True(arg.Value == 70); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 60); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 50); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 40); }, arg => { Assert.Equal(2147483648, arg.Status?.StatusCode); Assert.Null(arg.Value); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 30); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 25); }); Assert.All(results.History, arg => { Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Null(arg.AdditionalData); Assert.Null(arg.DataLocation); }); } public async Task HistoryStreamInt64ValuesTest1Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int64.txt"; var history = await services.HistoryStreamValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadValuesDetailsModel { StartTime = _server.Now - TimeSpan.FromDays(600), EndTime = _server.Now + TimeSpan.FromDays(1), ReturnBounds = true } }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); Assert.NotNull(history); Assert.Equal(14, history.Count); Assert.Collection(history, arg => { Assert.Equal(2161573888, arg.Status?.StatusCode); Assert.Null(arg.Value); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 10); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 20); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 25); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 30); }, arg => { Assert.Equal(2147483648, arg.Status?.StatusCode); Assert.Null(arg.Value); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 40); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 50); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 60); }, arg => { Assert.Equal(1073741824u, arg.Status?.StatusCode); Assert.True(arg.Value == 70); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 70); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 80); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 90); }, arg => { Assert.Equal(2161573888, arg.Status?.StatusCode); Assert.Null(arg.Value); }); Assert.All(history, arg => { Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Null(arg.AdditionalData); Assert.Null(arg.DataLocation); }); } public async Task HistoryStreamInt64ValuesTest2Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int64.txt"; var history = await services.HistoryStreamValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadValuesDetailsModel { StartTime = _server.Now - TimeSpan.FromDays(600), NumValues = 10 } }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); Assert.NotNull(history); Assert.Equal(10, history.Count); Assert.Collection(history, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 10); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 20); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 25); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 30); }, arg => { Assert.Equal(2147483648u, arg.Status?.StatusCode); Assert.Null(arg.Value); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 40); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 50); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 60); }, arg => { Assert.Equal(1073741824u, arg.Status?.StatusCode); Assert.True(arg.Value == 70); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 70); }); Assert.All(history, arg => { Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Null(arg.AdditionalData); Assert.Null(arg.DataLocation); }); } public async Task HistoryStreamInt64ValuesTest3Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int64.txt"; var history = await services.HistoryStreamValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadValuesDetailsModel { StartTime = _server.Now - TimeSpan.FromDays(600), EndTime = _server.Now + TimeSpan.FromDays(1) } }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); Assert.NotNull(history); Assert.Equal(12, history.Count); Assert.Collection(history, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 10); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 20); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 25); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 30); }, arg => { Assert.Equal(2147483648, arg.Status?.StatusCode); Assert.Null(arg.Value); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 40); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 50); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 60); }, arg => { Assert.Equal(1073741824u, arg.Status?.StatusCode); Assert.True(arg.Value == 70); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 70); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 80); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 90); }); Assert.All(history, arg => { Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Null(arg.AdditionalData); Assert.Null(arg.DataLocation); }); } public async Task HistoryStreamInt64ValuesTest4Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int64.txt"; var history = await services.HistoryStreamValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadValuesDetailsModel { EndTime = _server.Now + TimeSpan.FromDays(1), NumValues = 10 } }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); Assert.NotNull(history); Assert.Equal(10, history.Count); Assert.Collection(history, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 90); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 80); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 70); }, arg => { Assert.Equal(1073741824u, arg.Status?.StatusCode); Assert.True(arg.Value == 70); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 60); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 50); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 40); }, arg => { Assert.Equal(2147483648, arg.Status?.StatusCode); Assert.Null(arg.Value); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 30); }, arg => { Assert.Null(arg.Status); Assert.True(arg.Value == 25); }); Assert.All(history, arg => { Assert.NotNull(arg.SourceTimestamp); Assert.NotNull(arg.ServerTimestamp); Assert.Null(arg.AdditionalData); Assert.Null(arg.DataLocation); }); } private readonly T _connection; private readonly BaseServerFixture _server; private readonly Func> _services; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/HistoricalAccess/HistoryUpdateValuesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.Linq; using System.Threading; using System.Threading.Tasks; using Xunit; public class HistoryUpdateValuesTests { /// /// Create history services tests /// /// /// public HistoryUpdateValuesTests(Func> services, T connection) { _services = services; _connection = connection; } public async Task HistoryInsertUInt32ValuesTest1Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int32.txt"; var startTime = StartTime(); var toUpsert = Enumerable.Repeat(0, 10) .Select((_, i) => startTime.AddMilliseconds(i * 10000)) .Select(ts => new HistoricValueModel { DataType = "Int32", SourceTimestamp = ts, Value = 77 }) .ToArray(); var insert = await services.HistoryInsertValuesAsync(_connection, new HistoryUpdateRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new UpdateValuesDetailsModel { Values = toUpsert } }, ct).ConfigureAwait(false); Assert.Null(insert.ErrorInfo); Assert.Equal(toUpsert.Length, insert.Results?.Count); Assert.All(insert.Results!, arg => Assert.Equal("Good", arg.SymbolicId)); var read2 = await services.HistoryReadValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadValuesDetailsModel { StartTime = startTime, NumValues = (uint)toUpsert.Length } }, ct).ConfigureAwait(false); Assert.Null(read2.ErrorInfo); Assert.NotNull(read2.History); Assert.Equal(10, read2.History.Length); Assert.All(read2.History, arg => Assert.True(arg.Value == 77)); } public async Task HistoryInsertUInt32ValuesTest2Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int32.txt"; var startTime = StartTime(); var toUpsert = Enumerable.Repeat(0, 10) .Select((_, i) => startTime.AddMilliseconds(i * 10000)) .Select(ts => new HistoricValueModel { DataType = "Int32", SourceTimestamp = ts, Value = 77 }) .ToArray(); var insert = await services.HistoryInsertValuesAsync(_connection, new HistoryUpdateRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new UpdateValuesDetailsModel { Values = toUpsert } }, ct).ConfigureAwait(false); Assert.Null(insert.ErrorInfo); Assert.Equal(toUpsert.Length, insert.Results?.Count); Assert.All(insert.Results!, arg => Assert.Equal("Good", arg.SymbolicId)); var insert2 = await services.HistoryInsertValuesAsync(_connection, new HistoryUpdateRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new UpdateValuesDetailsModel { Values = toUpsert } }, ct).ConfigureAwait(false); Assert.Null(insert2.ErrorInfo); Assert.Equal(toUpsert.Length, insert2.Results?.Count); Assert.All(insert2.Results!, arg => Assert.Equal("BadEntryExists", arg.SymbolicId)); } public async Task HistoryUpsertUInt32ValuesTest1Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int32.txt"; var startTime = StartTime(); var toUpsert = Enumerable.Repeat(0, 10) .Select((_, i) => startTime.AddMilliseconds(i * 10000)) .Select(ts => new HistoricValueModel { DataType = "Int32", SourceTimestamp = ts, Value = 5 }) .ToArray(); var upsert = await services.HistoryUpsertValuesAsync(_connection, new HistoryUpdateRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new UpdateValuesDetailsModel { Values = toUpsert } }, ct).ConfigureAwait(false); Assert.Null(upsert.ErrorInfo); Assert.Equal(toUpsert.Length, upsert.Results?.Count); Assert.All(upsert.Results!, arg => Assert.Equal("Good", arg.SymbolicId)); var read2 = await services.HistoryReadValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadValuesDetailsModel { StartTime = startTime, NumValues = (uint)toUpsert.Length } }, ct).ConfigureAwait(false); Assert.Null(read2.ErrorInfo); Assert.NotNull(read2.History); Assert.Equal(10, read2.History.Length); Assert.All(read2.History, arg => Assert.True(arg.Value == 5)); } public async Task HistoryUpsertUInt32ValuesTest2Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int32.txt"; var startTime = StartTime(); var reqTimes = Enumerable.Repeat(0, 10) .Select((_, i) => startTime.AddMinutes(i)).ToArray(); var toUpsert = reqTimes .Select(ts => new HistoricValueModel { DataType = "Int32", SourceTimestamp = ts, Value = 5 }) .ToArray(); var upsert = await services.HistoryInsertValuesAsync(_connection, new HistoryUpdateRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new UpdateValuesDetailsModel { Values = toUpsert } }, ct).ConfigureAwait(false); Assert.Null(upsert.ErrorInfo); Assert.Equal(toUpsert.Length, upsert.Results?.Count); Assert.All(upsert.Results!, arg => Assert.Equal("Good", arg.SymbolicId)); var toReplace = toUpsert.Select(v => v with { Value = 99 }).ToArray(); var replace = await services.HistoryUpsertValuesAsync(_connection, new HistoryUpdateRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new UpdateValuesDetailsModel { Values = toReplace } }, ct).ConfigureAwait(false); Assert.Null(replace.ErrorInfo); Assert.Equal(toReplace.Length, replace.Results?.Count); Assert.All(replace.Results!, arg => Assert.Equal("Good", arg.SymbolicId)); var read2 = await services.HistoryReadValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadValuesDetailsModel { StartTime = startTime, NumValues = (uint)reqTimes.Length } }, ct).ConfigureAwait(false); Assert.Null(read2.ErrorInfo); Assert.NotNull(read2.History); Assert.Equal(10, read2.History.Length); Assert.All(read2.History, arg => Assert.True(arg.Value == 99)); var read3 = await services.HistoryReadModifiedValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadModifiedValuesDetailsModel { StartTime = startTime, NumValues = (uint)reqTimes.Length } }, ct).ConfigureAwait(false); Assert.Null(read3.ErrorInfo); Assert.NotNull(read3.History); Assert.Equal(10, read3.History.Length); Assert.All(read3.History, arg => Assert.True(arg.Value == 5)); } public async Task HistoryReplaceUInt32ValuesTest1Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int32.txt"; var startTime = StartTime(); var reqTimes = Enumerable.Repeat(0, 10) .Select((_, i) => startTime.AddMinutes(i)).ToArray(); var toUpsert = reqTimes .Select(ts => new HistoricValueModel { DataType = "Int32", SourceTimestamp = ts, Value = 5 }) .ToArray(); var upsert = await services.HistoryInsertValuesAsync(_connection, new HistoryUpdateRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new UpdateValuesDetailsModel { Values = toUpsert } }, ct).ConfigureAwait(false); Assert.Null(upsert.ErrorInfo); Assert.Equal(toUpsert.Length, upsert.Results?.Count); Assert.All(upsert.Results!, arg => Assert.Equal("Good", arg.SymbolicId)); var toReplace = toUpsert.Select(v => v with { Value = 99 }).ToArray(); var replace = await services.HistoryReplaceValuesAsync(_connection, new HistoryUpdateRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new UpdateValuesDetailsModel { Values = toReplace } }, ct).ConfigureAwait(false); Assert.Null(replace.ErrorInfo); Assert.Equal(toReplace.Length, replace.Results?.Count); Assert.All(replace.Results!, arg => Assert.Equal("Good", arg.SymbolicId)); var read2 = await services.HistoryReadValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadValuesDetailsModel { StartTime = startTime, NumValues = (uint)reqTimes.Length } }, ct).ConfigureAwait(false); Assert.Null(read2.ErrorInfo); Assert.NotNull(read2.History); Assert.Equal(10, read2.History.Length); Assert.All(read2.History, arg => Assert.True(arg.Value == 99)); var read3 = await services.HistoryReadModifiedValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadModifiedValuesDetailsModel { StartTime = startTime, NumValues = (uint)reqTimes.Length * 2 } }, ct).ConfigureAwait(false); Assert.NotNull(read3.History); Assert.Equal(20, read3.History.Length); Assert.Null(read3.ErrorInfo); Assert.All(read3.History, arg => { Assert.True(arg.Value == 5); Assert.NotNull(arg.ModificationInfo); }); Assert.Equal(10, read3.History.Count( h => h.ModificationInfo?.UpdateType == HistoryUpdateOperation.Insert)); Assert.Equal(10, read3.History.Count( h => h.ModificationInfo?.UpdateType == HistoryUpdateOperation.Replace)); } public async Task HistoryReplaceUInt32ValuesTest2Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int32.txt"; var startTime = StartTime(); var reqTimes = Enumerable.Repeat(0, 10) .Select((_, i) => startTime.AddMinutes(i)).ToArray(); var toReplace = reqTimes .Select(ts => new HistoricValueModel { DataType = "Int32", SourceTimestamp = ts, Value = 5 }) .ToArray(); var replace = await services.HistoryReplaceValuesAsync(_connection, new HistoryUpdateRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new UpdateValuesDetailsModel { Values = toReplace } }, ct).ConfigureAwait(false); Assert.Null(replace.ErrorInfo); Assert.Equal(toReplace.Length, replace.Results?.Count); Assert.All(replace.Results!, arg => Assert.Equal("BadNoEntryExists", arg.SymbolicId)); } public async Task HistoryInsertDeleteUInt32ValuesTest1Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int32.txt"; var startTime = StartTime(); var reqTimes = Enumerable.Repeat(0, 10) .Select((_, i) => startTime.AddMinutes(i)).ToArray(); var toUpsert = reqTimes .Select(ts => new HistoricValueModel { DataType = null, // Discover data type SourceTimestamp = ts, Value = 5 }) .ToArray(); var upsert = await services.HistoryInsertValuesAsync(_connection, new HistoryUpdateRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new UpdateValuesDetailsModel { Values = toUpsert } }, ct).ConfigureAwait(false); Assert.Null(upsert.ErrorInfo); Assert.Equal(toUpsert.Length, upsert.Results?.Count); Assert.All(upsert.Results!, arg => Assert.Equal("Good", arg.SymbolicId)); var replace = await services.HistoryDeleteValuesAsync(_connection, new HistoryUpdateRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new DeleteValuesDetailsModel { StartTime = startTime, EndTime = reqTimes[^1].AddHours(1) } }, ct).ConfigureAwait(false); Assert.Null(replace.ErrorInfo); Assert.Empty(replace.Results!); var read2 = await services.HistoryReadValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadValuesDetailsModel { StartTime = startTime, EndTime = reqTimes[^1].AddHours(1) } }, ct).ConfigureAwait(false); Assert.NotNull(read2.ErrorInfo); Assert.Equal("GoodNoData", read2.ErrorInfo.SymbolicId); Assert.NotNull(read2.History); Assert.Empty(read2.History); var read3 = await services.HistoryReadModifiedValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadModifiedValuesDetailsModel { StartTime = startTime, EndTime = reqTimes[^1].AddHours(1) } }, ct).ConfigureAwait(false); Assert.Null(read3.ErrorInfo); // Insert + Delete = 20 Assert.NotNull(read3.History); Assert.Equal(20, read3.History.Length); Assert.All(read3.History, arg => { Assert.NotNull(arg.ModificationInfo); Assert.True(arg.Value == 5); }); Assert.Equal(10, read3.History.Count( h => h.ModificationInfo?.UpdateType == HistoryUpdateOperation.Insert)); Assert.Equal(10, read3.History.Count( h => h.ModificationInfo?.UpdateType == HistoryUpdateOperation.Delete)); } public async Task HistoryInsertDeleteUInt32ValuesTest2Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int32.txt"; var startTime = StartTime(); var reqTimes = Enumerable.Repeat(0, 10) .Select((_, i) => startTime.AddMinutes(i)).ToArray(); var toUpsert = reqTimes .Select(ts => new HistoricValueModel { DataType = "Int32", SourceTimestamp = ts, Value = 66 }) .ToArray(); var upsert = await services.HistoryInsertValuesAsync(_connection, new HistoryUpdateRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new UpdateValuesDetailsModel { Values = toUpsert } }, ct).ConfigureAwait(false); Assert.Null(upsert.ErrorInfo); Assert.Equal(toUpsert.Length, upsert.Results?.Count); Assert.All(upsert.Results!, arg => Assert.Equal("Good", arg.SymbolicId)); var read2 = await services.HistoryReadModifiedValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadModifiedValuesDetailsModel { StartTime = startTime, EndTime = reqTimes[^1].AddHours(1) } }, ct).ConfigureAwait(false); Assert.Null(read2.ErrorInfo); Assert.NotNull(read2.History); Assert.Equal(10, read2.History.Length); Assert.All(read2.History, arg => { Assert.NotNull(arg.ModificationInfo); Assert.True(arg.Value == 66); Assert.Equal(HistoryUpdateOperation.Insert, arg.ModificationInfo?.UpdateType); }); var deleteModified = await services.HistoryDeleteModifiedValuesAsync(_connection, new HistoryUpdateRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new DeleteValuesDetailsModel { StartTime = startTime, EndTime = reqTimes[^1].AddHours(1) } }, ct).ConfigureAwait(false); Assert.Null(deleteModified.ErrorInfo); Assert.Empty(deleteModified.Results!); var read3 = await services.HistoryReadModifiedValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadModifiedValuesDetailsModel { StartTime = startTime, EndTime = reqTimes[^1].AddHours(1) } }, ct).ConfigureAwait(false); Assert.NotNull(read3.ErrorInfo); Assert.Equal("GoodNoData", read3.ErrorInfo.SymbolicId); Assert.NotNull(read3.History); Assert.Empty(read3.History); } public async Task HistoryInsertDeleteUInt32ValuesTest3Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int32.txt"; var startTime = StartTime(); var reqTimes = Enumerable.Repeat(0, 10) .Select((_, i) => startTime.AddMinutes(i)).ToArray(); var toUpsert = reqTimes .Select(ts => new HistoricValueModel { DataType = "Int32", SourceTimestamp = ts, Value = 66 }) .ToArray(); var upsert = await services.HistoryInsertValuesAsync(_connection, new HistoryUpdateRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new UpdateValuesDetailsModel { Values = toUpsert } }, ct).ConfigureAwait(false); Assert.Null(upsert.ErrorInfo); Assert.Equal(toUpsert.Length, upsert.Results?.Count); Assert.All(upsert.Results!, arg => Assert.Equal("Good", arg.SymbolicId)); var read2 = await services.HistoryReadModifiedValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadModifiedValuesDetailsModel { StartTime = startTime, EndTime = reqTimes[^1].AddHours(1) } }, ct).ConfigureAwait(false); Assert.Null(read2.ErrorInfo); Assert.NotNull(read2.History); Assert.Equal(10, read2.History.Length); Assert.All(read2.History, arg => { Assert.NotNull(arg.ModificationInfo); Assert.True(arg.Value == 66); Assert.Equal(HistoryUpdateOperation.Insert, arg.ModificationInfo?.UpdateType); }); var delete = await services.HistoryDeleteValuesAsync(_connection, new HistoryUpdateRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new DeleteValuesDetailsModel { StartTime = startTime, EndTime = reqTimes[^1].AddHours(1) } }, ct).ConfigureAwait(false); Assert.Null(delete.ErrorInfo); Assert.Empty(delete.Results!); var deleteModified = await services.HistoryDeleteModifiedValuesAsync(_connection, new HistoryUpdateRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new DeleteValuesDetailsModel { StartTime = startTime, EndTime = reqTimes[^1].AddHours(1) } }, ct).ConfigureAwait(false); Assert.Null(deleteModified.ErrorInfo); Assert.Empty(deleteModified.Results!); var read3 = await services.HistoryReadModifiedValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadModifiedValuesDetailsModel { StartTime = startTime, EndTime = reqTimes[^1].AddHours(1) } }, ct).ConfigureAwait(false); Assert.NotNull(read3.ErrorInfo); Assert.Equal("GoodNoData", read3.ErrorInfo.SymbolicId); // TODO: Check this Assert.NotNull(read3.History); Assert.Empty(read3.History); } public async Task HistoryInsertDeleteUInt32ValuesTest4Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int32.txt"; var startTime = StartTime(); var reqTimes = Enumerable.Repeat(0, 10) .Select((_, i) => startTime.AddMinutes(i)).ToArray(); var toInsert = reqTimes .Select(ts => new HistoricValueModel { DataType = "Int32", SourceTimestamp = ts, Value = 88 }) .ToArray(); var upsert = await services.HistoryInsertValuesAsync(_connection, new HistoryUpdateRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new UpdateValuesDetailsModel { Values = toInsert } }, ct).ConfigureAwait(false); Assert.Null(upsert.ErrorInfo); Assert.Equal(toInsert.Length, upsert.Results?.Count); Assert.All(upsert.Results!, arg => Assert.Equal("Good", arg.SymbolicId)); var read2 = await services.HistoryReadModifiedValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadModifiedValuesDetailsModel { StartTime = startTime, EndTime = reqTimes[^1].AddHours(1) } }, ct).ConfigureAwait(false); Assert.Null(read2.ErrorInfo); Assert.NotNull(read2.History); Assert.Equal(10, read2.History.Length); Assert.All(read2.History, arg => { Assert.NotNull(arg.ModificationInfo); Assert.NotNull(arg.SourceTimestamp); Assert.True(arg.Value == 88); Assert.Equal(HistoryUpdateOperation.Insert, arg.ModificationInfo?.UpdateType); }); var delete = await services.HistoryDeleteValuesAtTimesAsync(_connection, new HistoryUpdateRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new DeleteValuesAtTimesDetailsModel { ReqTimes = new[] { startTime } } }, ct).ConfigureAwait(false); Assert.Null(delete.ErrorInfo); var arg = Assert.Single(delete.Results!); Assert.Equal("Good", arg.SymbolicId); var read4 = await services.HistoryReadValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadValuesDetailsModel { StartTime = startTime, EndTime = reqTimes[^1].AddHours(1) } }, ct).ConfigureAwait(false); Assert.Null(read4.ErrorInfo); Assert.NotNull(read4.History); Assert.Equal(9, read4.History.Length); Assert.All(read4.History, arg => Assert.True(arg.Value == 88)); var read3 = await services.HistoryReadModifiedValuesAsync(_connection, new HistoryReadRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new ReadModifiedValuesDetailsModel { StartTime = startTime, EndTime = reqTimes[^1].AddHours(1) } }, ct).ConfigureAwait(false); Assert.Null(read3.ErrorInfo); // Insert + Delete = 11 Assert.NotNull(read3.History); Assert.Equal(11, read3.History.Length); Assert.All(read3.History, arg => { Assert.NotNull(arg.ModificationInfo); Assert.True(arg.Value == 88); }); Assert.Equal(10, read3.History.Count( h => h.ModificationInfo?.UpdateType == HistoryUpdateOperation.Insert)); Assert.Single(read3.History.Where( h => h.ModificationInfo?.UpdateType == HistoryUpdateOperation.Delete)); } public async Task HistoryDeleteUInt32ValuesTest1Async(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int32.txt"; var startTime = StartTime(); var reqTimes = Enumerable.Repeat(0, 10) .Select((_, i) => startTime.AddMinutes(i)).ToArray(); var delete = await services.HistoryDeleteValuesAtTimesAsync(_connection, new HistoryUpdateRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples, Details = new DeleteValuesAtTimesDetailsModel { ReqTimes = reqTimes } }, ct).ConfigureAwait(false); Assert.Null(delete.ErrorInfo); Assert.Equal(10, delete.Results?.Count); Assert.All(delete.Results!, arg => Assert.Equal("BadNoEntryExists", arg.SymbolicId)); } private static DateTime StartTime() { return new DateTime(1973, 1, 1, 0, 0, 0, DateTimeKind.Utc) .AddYears(Interlocked.Increment(ref _counter)); } private static int _counter; private readonly T _connection; private readonly Func> _services; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/HistoricalAccess/NodeHistoricalAccessTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.Threading; using System.Threading.Tasks; using Xunit; public class NodeHistoricalAccessTests { /// /// Create history services tests /// /// /// public NodeHistoricalAccessTests(Func> services, T connection) { _services = services; _connection = connection; } public async Task GetServerCapabilitiesTestAsync(CancellationToken ct = default) { var services = _services(); var results = await services.GetServerCapabilitiesAsync(_connection, null, ct).ConfigureAwait(false); Assert.NotNull(results); Assert.NotNull(results.AggregateFunctions); Assert.Equal(37, results.AggregateFunctions?.Count); Assert.Single(results.SupportedLocales!); Assert.Equal("en-US", results.SupportedLocales?[0]); Assert.NotEmpty(results.ServerProfiles!); Assert.Equal(3, results.ServerProfiles!.Count); Assert.NotNull(results.OperationLimits); Assert.Null(results.OperationLimits.MinSupportedSampleRate); Assert.Equal(1000u, results.OperationLimits.MaxBrowseContinuationPoints!.Value); Assert.Equal(1000u, results.OperationLimits.MaxQueryContinuationPoints!.Value); Assert.Equal(1000u, results.OperationLimits.MaxHistoryContinuationPoints!.Value); Assert.Null(results.OperationLimits.MaxNodesPerBrowse); Assert.Null(results.OperationLimits.MaxNodesPerRegisterNodes); Assert.Null(results.OperationLimits.MaxNodesPerWrite); Assert.Null(results.OperationLimits.MaxNodesPerMethodCall); Assert.Null(results.OperationLimits.MaxNodesPerNodeManagement); Assert.Null(results.OperationLimits.MaxMonitoredItemsPerCall); Assert.Null(results.OperationLimits.MaxNodesPerHistoryReadData); Assert.Null(results.OperationLimits.MaxNodesPerHistoryReadEvents); Assert.Null(results.OperationLimits.MaxNodesPerHistoryUpdateData); Assert.Null(results.OperationLimits.MaxNodesPerHistoryUpdateEvents); Assert.Equal(65535u, results.OperationLimits.MaxArrayLength); Assert.Equal(130816u, results.OperationLimits.MaxStringLength); Assert.Equal(1048576u, results.OperationLimits.MaxByteStringLength); Assert.Null(results.ModellingRules); } public async Task HistoryGetServerCapabilitiesTestAsync(CancellationToken ct = default) { var services = _services(); var results = await services.HistoryGetServerCapabilitiesAsync(_connection, null, ct).ConfigureAwait(false); Assert.NotNull(results); Assert.NotNull(results.AggregateFunctions); Assert.Equal(37, results.AggregateFunctions?.Count); Assert.True(results.AccessHistoryDataCapability); Assert.False(results.AccessHistoryEventsCapability); Assert.True(results.InsertDataCapability); Assert.False(results.InsertEventCapability); Assert.True(results.InsertAnnotationCapability); Assert.True(results.ReplaceDataCapability); Assert.False(results.ReplaceEventCapability); Assert.True(results.DeleteRawCapability); Assert.True(results.DeleteAtTimeCapability); Assert.False(results.DeleteEventCapability); Assert.False(results.ServerTimestampSupported); Assert.True(results.UpdateDataCapability); Assert.False(results.UpdateEventCapability); Assert.NotNull(results.MaxReturnDataValues); Assert.Equal(uint.MaxValue, results.MaxReturnDataValues!.Value); Assert.Null(results.MaxReturnEventValues); } public async Task HistoryGetInt16NodeHistoryConfigurationAsync(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int16.txt"; var results = await services.HistoryGetConfigurationAsync(_connection, new HistoryConfigurationRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples }, ct).ConfigureAwait(false); Assert.NotNull(results); Assert.NotNull(results.Configuration); Assert.NotNull(results.Configuration?.StartOfArchive); Assert.NotNull(results.Configuration?.EndOfArchive); Assert.NotNull(results.Configuration?.StartOfOnlineArchive); Assert.Equal(ExceptionDeviationType.AbsoluteValue, results.Configuration?.ExceptionDeviationType); Assert.Equal(0, results.Configuration?.ExceptionDeviation); Assert.Null(results.Configuration?.AggregateFunctions); Assert.NotNull(results.Configuration?.AggregateConfiguration); Assert.Equal((byte)100, results.Configuration?.AggregateConfiguration?.PercentDataGood); Assert.Equal((byte)100, results.Configuration?.AggregateConfiguration?.PercentDataBad); Assert.False(results.Configuration?.AggregateConfiguration?.UseSlopedExtrapolation); Assert.True(results.Configuration?.AggregateConfiguration?.TreatUncertainAsBad); Assert.Equal(TimeSpan.FromSeconds(10), results.Configuration?.MinTimeInterval); Assert.Equal(TimeSpan.FromSeconds(10), results.Configuration?.MaxTimeInterval); Assert.False(results.Configuration?.ServerTimestampSupported); Assert.False(results.Configuration?.Stepped); Assert.Null(results.ErrorInfo); } public async Task HistoryGetInt64NodeHistoryConfigurationAsync(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Int64.txt"; var results = await services.HistoryGetConfigurationAsync(_connection, new HistoryConfigurationRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples }, ct).ConfigureAwait(false); Assert.NotNull(results); Assert.NotNull(results.Configuration); Assert.NotNull(results.Configuration?.StartOfArchive); Assert.NotNull(results.Configuration?.EndOfArchive); Assert.NotNull(results.Configuration?.StartOfOnlineArchive); Assert.Equal(ExceptionDeviationType.AbsoluteValue, results.Configuration?.ExceptionDeviationType); Assert.Equal(0, results.Configuration?.ExceptionDeviation); Assert.Null(results.Configuration?.AggregateFunctions); Assert.NotNull(results.Configuration?.AggregateConfiguration); Assert.Equal((byte)100, results.Configuration?.AggregateConfiguration?.PercentDataGood); Assert.Equal((byte)100, results.Configuration?.AggregateConfiguration?.PercentDataBad); Assert.False(results.Configuration?.AggregateConfiguration?.UseSlopedExtrapolation); Assert.True(results.Configuration?.AggregateConfiguration?.TreatUncertainAsBad); Assert.Equal(TimeSpan.FromSeconds(10), results.Configuration?.MinTimeInterval); Assert.Equal(TimeSpan.FromSeconds(10), results.Configuration?.MaxTimeInterval); Assert.False(results.Configuration?.ServerTimestampSupported); Assert.True(results.Configuration?.Stepped); Assert.Null(results.ErrorInfo); } public async Task HistoryGetNodeHistoryConfigurationFromBadNodeAsync(CancellationToken ct = default) { var services = _services(); const string samples = "s=1:Azure.IIoT.OpcUa.Publisher.Testing.Servers.HistoricalAccess.Data.Sample.Unknown.txt"; var results = await services.HistoryGetConfigurationAsync(_connection, new HistoryConfigurationRequestModel { NodeId = "http://opcfoundation.org/HistoricalAccess#" + samples }, ct).ConfigureAwait(false); Assert.NotNull(results); Assert.Null(results.Configuration); Assert.NotNull(results.ErrorInfo); // Assert.Equal("BadNodeIdUnknown", results.ErrorInfo.SymbolicId); Assert.Equal("BadUnexpectedError", results.ErrorInfo.SymbolicId); } private readonly T _connection; private readonly Func> _services; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/HistoricalEvents/NodeHistoricalEventsTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using System; using System.Threading; using System.Threading.Tasks; using Xunit; public class NodeHistoricalEventsTests { /// /// Create history services tests /// /// /// public NodeHistoricalEventsTests(Func> services, T connection) { _services = services; _connection = connection; } public async Task GetServerCapabilitiesTestAsync(CancellationToken ct = default) { var services = _services(); var results = await services.GetServerCapabilitiesAsync(_connection, null, ct).ConfigureAwait(false); Assert.NotNull(results); Assert.NotNull(results.AggregateFunctions); Assert.Equal(37, results.AggregateFunctions?.Count); Assert.Single(results.SupportedLocales!); Assert.Equal("en-US", results.SupportedLocales?[0]); Assert.NotEmpty(results.ServerProfiles!); Assert.Equal(3, results.ServerProfiles!.Count); Assert.NotNull(results.OperationLimits); Assert.Null(results.OperationLimits.MinSupportedSampleRate); Assert.Equal(1000u, results.OperationLimits.MaxBrowseContinuationPoints!.Value); Assert.Equal(1000u, results.OperationLimits.MaxQueryContinuationPoints!.Value); Assert.Equal(1000u, results.OperationLimits.MaxHistoryContinuationPoints!.Value); Assert.Null(results.OperationLimits.MaxNodesPerBrowse); Assert.Null(results.OperationLimits.MaxNodesPerRegisterNodes); Assert.Null(results.OperationLimits.MaxNodesPerWrite); Assert.Null(results.OperationLimits.MaxNodesPerMethodCall); Assert.Null(results.OperationLimits.MaxNodesPerNodeManagement); Assert.Null(results.OperationLimits.MaxMonitoredItemsPerCall); Assert.Null(results.OperationLimits.MaxNodesPerHistoryReadData); Assert.Null(results.OperationLimits.MaxNodesPerHistoryReadEvents); Assert.Null(results.OperationLimits.MaxNodesPerHistoryUpdateData); Assert.Null(results.OperationLimits.MaxNodesPerHistoryUpdateEvents); Assert.Equal(65535u, results.OperationLimits.MaxArrayLength); Assert.Equal(130816u, results.OperationLimits.MaxStringLength); Assert.Equal(1048576u, results.OperationLimits.MaxByteStringLength); Assert.Null(results.ModellingRules); } public async Task HistoryGetServerCapabilitiesTestAsync(CancellationToken ct = default) { var services = _services(); var results = await services.HistoryGetServerCapabilitiesAsync(_connection, null, ct).ConfigureAwait(false); Assert.NotNull(results); // Assert.NotNull(results.AggregateFunctions); // Assert.Equal(37, results.AggregateFunctions.Count); // Assert.False(results.AccessHistoryDataCapability); // Assert.True(results.AccessHistoryEventsCapability); // Assert.False(results.InsertDataCapability); // Assert.True(results.InsertEventCapability); // Assert.True(results.InsertAnnotationCapability); // Assert.False(results.ReplaceDataCapability); // Assert.True(results.ReplaceEventCapability); // Assert.False(results.DeleteRawCapability); // Assert.False(results.DeleteAtTimeCapability); // Assert.True(results.DeleteEventCapability); // Assert.False(results.ServerTimestampSupported); // Assert.False(results.UpdateDataCapability); // Assert.True(results.UpdateEventCapability); // Assert.Null(results.MaxReturnDataValues); // Assert.NotNull(results.MaxReturnEventValues); // Assert.Equal(uint.MaxValue, results.MaxReturnEventValues.Value); } private readonly T _connection; private readonly Func> _services; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/Isa95Jobs/Isa95JobsServerTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher; using System; /// /// Simple Events server node tests /// /// public class Isa95JobsServerTests { public Isa95JobsServerTests(Func> services, T connection) { _services = services; _connection = connection; } private readonly T _connection; private readonly Func> _services; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/Plc/PlcModelComplexTypeTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher; using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.Threading; using System.Threading.Tasks; using Xunit; /// /// Tests for the Plc model, which is a complex type. /// /// public sealed class PlcModelComplexTypeTests { public PlcModelComplexTypeTests(BaseServerFixture server, Func> services, T connection) { _server = server; _services = services; _connection = connection; } public async Task PlcModelHeaterTestsAsync(CancellationToken ct = default) { var services = _services(); await TurnHeaterOnAsync(ct).ConfigureAwait(false); _server.FireTimersWithPeriod(TimeSpan.FromSeconds(1), 1000); // TODO: Fix flaky test #if FALSE var model = await GetPlcModelAsync(ct).ConfigureAwait(false); var state = model?.HeaterState; var temperature = model?.Temperature; var pressure = model?.Pressure; state.Should().Be(PlcHeaterStateType.On, "heater should start in 'on' state"); pressure.Should().BeGreaterThan(10_000, "pressure should start at 10k and get higher"); temperature?.Top.Should().Be(pressure - 100_005, "top is always 100,005 less than pressure. Pressure: {0}", pressure); temperature?.Bottom.Should().Be(pressure - 100_000, "bottom is always 100,000 less than pressure. Pressure: {0}", pressure); var previousPressure = 0; for (var i = 0; i < 5; i++) { _server.FireTimersWithPeriod(TimeSpan.FromSeconds(1), 1000); model = await GetPlcModelAsync(ct).ConfigureAwait(false); pressure = model?.Pressure; pressure.Should().BeGreaterThan(previousPressure, "pressure should build when heater is on"); previousPressure = pressure ?? int.MaxValue; } // let heater run for a few seconds to make temperature rise _server.FireTimersWithPeriod(TimeSpan.FromSeconds(1), 1000); await TurnHeaterOffAsync(ct).ConfigureAwait(false); _server.FireTimersWithPeriod(TimeSpan.FromSeconds(1), 1000); model = await GetPlcModelAsync(ct).ConfigureAwait(false); state = model?.HeaterState; temperature = model?.Temperature; pressure = model?.Pressure; state.Should().Be(PlcHeaterStateType.Off, "heater should have been turned off"); pressure.Should().BeGreaterThan(10_000, "pressure should start at 10k and get higher"); temperature?.Top.Should().Be(pressure - 100_005, "top is always 100,005 less than pressure. Pressure: {0}", pressure); temperature?.Bottom.Should().Be(pressure - 100_000, "btoom is always 100,000 less than pressure. Pressure: {0}", pressure); await TurnHeaterOffAsync(ct).ConfigureAwait(false); for (var i = 0; i < 5; i++) { _server.FireTimersWithPeriod(TimeSpan.FromSeconds(1), 1000); model = await GetPlcModelAsync(ct).ConfigureAwait(false); pressure = model?.Pressure; pressure.Should().BeLessThan(previousPressure, "pressure should drop when heater is off"); previousPressure = pressure ?? 0; } #endif async Task TurnHeaterOnAsync(CancellationToken ct = default) { var result = await services.MethodCallAsync(_connection, new MethodCallRequestModel { ObjectId = Plc.Namespaces.PlcApplications + "#s=Methods", MethodId = Plc.Namespaces.PlcSimulation + "#s=HeaterOn" }, ct).ConfigureAwait(false); Assert.NotNull(result); Assert.Null(result.ErrorInfo); } #if FALSE async Task TurnHeaterOffAsync(CancellationToken ct = default) { var result = await services.MethodCallAsync(_connection, new MethodCallRequestModel { ObjectId = Plc.Namespaces.PlcApplications + "#s=Methods", MethodId = Plc.Namespaces.PlcSimulation + "#s=HeaterOff" }, ct).ConfigureAwait(false); Assert.NotNull(result); Assert.Null(result.ErrorInfo); } async Task GetPlcModelAsync(CancellationToken ct = default) { var value = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcSimulation + "#i=" + Variables.Plc1_PlcStatus }, ct).ConfigureAwait(false); Assert.NotNull(value); Assert.Null(value.ErrorInfo); Assert.NotNull(value.Value); Assert.True(value.Value.TryGetProperty("Body", out var body)); // TODO: workaround decoder shortfall. Need to look into this. var serializer = new NewtonsoftJsonSerializer(); return serializer.Deserialize(serializer.SerializeToString(body)); } #endif } private readonly T _connection; private readonly BaseServerFixture _server; private readonly Func> _services; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/Plc/SimulatorNodesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Testing.Fixtures; using Azure.IIoT.OpcUa.Publisher; using Azure.IIoT.OpcUa.Publisher.Models; using FluentAssertions; using Opc.Ua; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Xunit; /// /// Tests for the variables defined in the simulator, such /// as fast-changing and trended nodes. /// /// public class SimulatorNodesTests { public SimulatorNodesTests(BaseServerFixture server, Func> services, T connection) { _server = server; _services = services; _connection = connection; } public async Task TelemetryStepUpTestAsync(CancellationToken ct = default) { var services = _services(); // need to track the first value encountered b/c the measurement stream starts when // the server starts and it can take several seconds for our test to start uint? firstValue = null; var measurements = new List(); for (var i = 0; i < 10; i++) { _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(100), 1); var value = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=StepUp" }, ct).ConfigureAwait(false); firstValue ??= (uint?)value?.Value; measurements.Add((uint?)value?.Value); } var expectedValues = Enumerable.Range((int)(firstValue ?? 0u), 10) .Select(i => (uint)i) .ToList(); measurements.Should().NotBeEmpty() .And.HaveCount(10) .And.ContainInOrder(expectedValues) .And.ContainItemsAssignableTo(); } public async Task TelemetryFastNodeTestAsync(CancellationToken ct = default) { var services = _services(); uint? lastValue = null; for (var i = 0; i < 10; i++) { var value = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=FastUIntScalar1" }, ct).ConfigureAwait(false); if (lastValue == null) { lastValue = (uint?)value?.Value; } else { Assert.Equal(lastValue + 1, (uint)(value?.Value ?? 0)); lastValue = (uint?)value?.Value; } _server.FireTimersWithPeriod(TimeSpan.FromSeconds(1), 1); } lastValue++; await services.MethodCallAsync(_connection, new MethodCallRequestModel { ObjectId = Plc.Namespaces.PlcApplications + "#s=Methods", MethodId = Plc.Namespaces.PlcApplications + "#s=StopUpdateFastNodes" }, ct).ConfigureAwait(false); var nextValue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=FastUIntScalar1" }, ct).ConfigureAwait(false); Assert.Equal(lastValue, (uint?)nextValue?.Value); _server.FireTimersWithPeriod(TimeSpan.FromSeconds(1), 1); nextValue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=FastUIntScalar1" }, ct).ConfigureAwait(false); Assert.Equal(lastValue, (uint?)nextValue?.Value); _server.FireTimersWithPeriod(TimeSpan.FromSeconds(1), 1); await services.MethodCallAsync(_connection, new MethodCallRequestModel { ObjectId = Plc.Namespaces.PlcApplications + "#s=Methods", MethodId = Plc.Namespaces.PlcApplications + "#s=StartUpdateFastNodes" }, ct).ConfigureAwait(false); _server.FireTimersWithPeriod(TimeSpan.FromSeconds(1), 1); nextValue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=FastUIntScalar1" }, ct).ConfigureAwait(false); Assert.Equal(lastValue + 1, (uint?)nextValue?.Value); } public async Task TelemetryContainsOutlierInDipDataAsync(CancellationToken ct = default) { var services = _services(); const int outlierValue = -1000; var outlierCount = 0; var maxValue = 0d; var minValue = 0d; // take 300 measurements, which is enough that at least a few outliers should be present for (var i = 0; i < 300; i++) { _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(100), 1); var rawvalue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=DipData" }, ct).ConfigureAwait(false); var value = (double?)rawvalue?.Value; if (Math.Round(value ?? 0.0) == outlierValue) { outlierCount++; } else { maxValue = Math.Max(maxValue, value ?? double.MaxValue); minValue = Math.Min(minValue, value ?? 0.0); } } maxValue.Should().BeInRange(90, 100, "measurement data should have a ceiling around 100"); minValue.Should().BeInRange(-100, -90, "measurement data should have a floor around -100"); outlierCount.Should().BeGreaterThan(0, "there should be at least a few measurements that were {0}", outlierValue); } public async Task TelemetryContainsOutlierInSpikeDataAsync(CancellationToken ct = default) { var services = _services(); const int outlierValue = 1000; var outlierCount = 0; var maxValue = 0d; var minValue = 0d; // take 300 measurements, which is enough that at least a few outliers should be present for (var i = 0; i < 300; i++) { _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(100), 1); var rawvalue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=SpikeData" }, ct).ConfigureAwait(false); var value = (double?)rawvalue?.Value; if (Math.Round(value ?? 0.0) == outlierValue) { outlierCount++; } else { maxValue = Math.Max(maxValue, value ?? double.MaxValue); minValue = Math.Min(minValue, value ?? 0.0); } } maxValue.Should().BeInRange(90, 100, "measurement data should have a ceiling around 100"); minValue.Should().BeInRange(-100, -90, "measurement data should have a floor around -100"); outlierCount.Should().BeGreaterThan(0, "there should be at least a few measurements that were {0}", outlierValue); } public async Task RandomSignedInt32TelemetryChangesWithPeriodAsync(CancellationToken ct = default) { var services = _services(); int? lastValue = null; var numberOfValueChanges = 0; for (var i = 0; i < 4; i++) { _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(100), 1); var rawvalue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=RandomSignedInt32" }, ct).ConfigureAwait(false); var value = (int?)rawvalue?.Value; if (i > 0 && value?.CompareTo(lastValue) != 0) { numberOfValueChanges++; } lastValue = value; } numberOfValueChanges.Should().Be(3); } public async Task RandomUnsignedInt32TelemetryChangesWithPeriodAsync(CancellationToken ct = default) { var services = _services(); uint? lastValue = null; var numberOfValueChanges = 0; for (var i = 0; i < 4; i++) { _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(100), 1); var rawvalue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=RandomUnsignedInt32" }, ct).ConfigureAwait(false); var value = (uint?)rawvalue?.Value; if (i > 0 && value?.CompareTo(lastValue) != 0) { numberOfValueChanges++; } lastValue = value; } numberOfValueChanges.Should().Be(3); } public async Task AlternatingBooleanTelemetryChangesWithPeriodAsync(CancellationToken ct = default) { var services = _services(); bool? lastValue = null; var numberOfValueChanges = 0; for (var i = 0; i < 4; i++) { _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(100), 50); var rawvalue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=AlternatingBoolean" }, ct).ConfigureAwait(false); var value = (bool?)rawvalue.Value; if (i > 0 && value?.CompareTo(lastValue) != 0) { numberOfValueChanges++; } lastValue = value; } numberOfValueChanges.Should().Be(3); } public async Task NegativeTrendDataTelemetryChangesWithPeriodAsync(CancellationToken ct = default) { var services = _services(); const uint periodInMilliseconds = 100u; const int invocations = 50; const int rampUpPeriods = kRampUpPeriods; const int numberOfTimes = invocations * rampUpPeriods; _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(periodInMilliseconds), numberOfTimes); // Measure the value 4 times, sleeping for a third of the period at which the value changes each time. // The number of times the value changes over the 4 measurements should be between 1 and 2. double? lastValue = null; var numberOfValueChanges = 0; for (var i = 0; i < 4; i++) { _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(periodInMilliseconds), invocations); var rawvalue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=NegativeTrendData" }, ct).ConfigureAwait(false); var value = (double?)rawvalue?.Value; if (i > 0 && value?.CompareTo(lastValue) != 0) { numberOfValueChanges++; } lastValue = value; } numberOfValueChanges.Should().Be(3); } public async Task PositiveTrendDataTelemetryChangesWithPeriodAsync(CancellationToken ct = default) { var services = _services(); const uint periodInMilliseconds = 100u; const int invocations = 50; const int rampUpPeriods = kRampUpPeriods; const int numberOfTimes = invocations * rampUpPeriods; _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(periodInMilliseconds), numberOfTimes); double? lastValue = null; var numberOfValueChanges = 0; for (var i = 0; i < 4; i++) { _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(periodInMilliseconds), invocations); var rawvalue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=PositiveTrendData" }, ct).ConfigureAwait(false); var value = (double?)rawvalue?.Value; if (i > 0 && value?.CompareTo(lastValue) != 0) { numberOfValueChanges++; } lastValue = value; } numberOfValueChanges.Should().Be(3); } public async Task SlowUIntScalar1TelemetryChangesWithPeriodAsync(CancellationToken ct = default) { var services = _services(); uint? lastValue = null; var numberOfValueChanges = 0; for (var i = 0; i < 4; i++) { _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(10000), 1); var rawvalue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=SlowUIntScalar1" }, ct).ConfigureAwait(false); var value = (uint?)rawvalue?.Value; if (i > 0 && value?.CompareTo(lastValue) != 0) { numberOfValueChanges++; } lastValue = value; } numberOfValueChanges.Should().Be(3); } public async Task FastUIntScalar1TelemetryChangesWithPeriodAsync(CancellationToken ct = default) { var services = _services(); uint? lastValue = null; var numberOfValueChanges = 0; for (var i = 0; i < 4; i++) { _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(1000), 1); var rawvalue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=FastUIntScalar1" }, ct).ConfigureAwait(false); var value = (uint?)rawvalue?.Value; if (i > 0 && value?.CompareTo(lastValue) != 0) { numberOfValueChanges++; } lastValue = value; } numberOfValueChanges.Should().Be(3); } public async Task BadNodeHasAlternatingStatusCodeAsync(CancellationToken ct = default) { var services = _services(); const uint periodInMilliseconds = 1000u; const int invocations = 1; const int cycles = 15; var values = await AsyncEnumerable.Range(0, cycles) .SelectAwait(async i => { _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(periodInMilliseconds), invocations); var value = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=BadFastUIntScalar1" }).ConfigureAwait(false); return (value.ErrorInfo?.StatusCode ?? StatusCodes.Good, value.Value); }).ToListAsync(cancellationToken: ct).ConfigureAwait(false); var valuesByStatus = values.GroupBy(v => v.Item1).ToDictionary(g => g.Key, g => g.ToList()); valuesByStatus .Keys.Should().BeEquivalentTo(new[] { StatusCodes.Good, StatusCodes.UncertainLastUsableValue, StatusCodes.BadDataLost, StatusCodes.BadNoCommunication }); valuesByStatus .Should().ContainKey(StatusCodes.Good) .WhoseValue .Should().HaveCountGreaterThan(cycles * 5 / 10) .And.OnlyContain(v => v.Value != null); valuesByStatus .Should().ContainKey(StatusCodes.UncertainLastUsableValue) .WhoseValue .Should().OnlyContain(v => v.Value != null); } public async Task FastLimitNumberOfUpdatesStopsUpdatingAfterLimitAsync(CancellationToken ct = default) { var services = _services(); const uint periodInMilliseconds = 1000u; var rawvalue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=FastUIntScalar1" }, ct).ConfigureAwait(false); var value1 = (uint?)rawvalue?.Value; // Change the value of the NumberOfUpdates control variable to 6. await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=FastNumberOfUpdates", Value = 6 }, ct).ConfigureAwait(false); // Fire the timer 6 times, should increase the value each time. _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(periodInMilliseconds), 6); rawvalue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=FastUIntScalar1" }, ct).ConfigureAwait(false); var value2 = (uint?)rawvalue?.Value; value2.Should().Be(value1 + 6); // NumberOfUpdates variable should now be 0. The Fast node value should not change anymore. for (var i = 0; i < 10; i++) { rawvalue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=FastNumberOfUpdates" }, ct).ConfigureAwait(false); ((int?)rawvalue?.Value).Should().Be(0); _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(periodInMilliseconds), 1); rawvalue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=FastUIntScalar1" }, ct).ConfigureAwait(false); var value3 = (uint?)rawvalue?.Value; value3.Should().Be(value1 + 6); } // Change the value of the NumberOfUpdates control variable to -1. // The Fast node value should now increase indefinitely. await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=FastNumberOfUpdates", Value = kNoLimit }, ct).ConfigureAwait(false); _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(periodInMilliseconds), 3); rawvalue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=FastUIntScalar1" }, ct).ConfigureAwait(false); var value4 = (uint?)rawvalue?.Value; value4.Should().Be(value1 + 6 + 3); rawvalue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=FastNumberOfUpdates" }, ct).ConfigureAwait(false); ((int?)rawvalue?.Value).Should().Be(kNoLimit, "NumberOfUpdates node value should not change when it is {0}", kNoLimit); } public async Task SlowLimitNumberOfUpdatesStopsUpdatingAfterLimitAsync(CancellationToken ct = default) { var services = _services(); const uint periodInMilliseconds = 10000u; var rawvalue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=SlowUIntScalar1" }, ct).ConfigureAwait(false); var value1 = (uint?)rawvalue?.Value; // Change the value of the NumberOfUpdates control variable to 6. await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=SlowNumberOfUpdates", Value = 6 }, ct).ConfigureAwait(false); // Fire the timer 6 times, should increase the value each time. _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(periodInMilliseconds), 6); rawvalue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=SlowUIntScalar1" }, ct).ConfigureAwait(false); var value2 = (uint?)rawvalue?.Value; value2.Should().Be(value1 + 6); // NumberOfUpdates variable should now be 0. The Fast node value should not change anymore. for (var i = 0; i < 10; i++) { rawvalue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=SlowNumberOfUpdates" }, ct).ConfigureAwait(false); ((int?)rawvalue?.Value).Should().Be(0); _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(periodInMilliseconds), 1); rawvalue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=SlowUIntScalar1" }, ct).ConfigureAwait(false); var value3 = (uint?)rawvalue?.Value; value3.Should().Be(value1 + 6); } // Change the value of the NumberOfUpdates control variable to -1. // The Fast node value should now increase indefinitely. await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=SlowNumberOfUpdates", Value = kNoLimit }, ct).ConfigureAwait(false); _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(periodInMilliseconds), 3); rawvalue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=SlowUIntScalar1" }, ct).ConfigureAwait(false); var value4 = (uint?)rawvalue?.Value; value4.Should().Be(value1 + 6 + 3); rawvalue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=SlowNumberOfUpdates" }, ct).ConfigureAwait(false); ((int?)rawvalue?.Value).Should().Be(kNoLimit, "NumberOfUpdates node value should not change when it is {0}", kNoLimit); } public async Task PositiveTrendDataNodeHasValueWithTrendAsync(CancellationToken ct = default) { var services = _services(); _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(100), 50 * kRampUpPeriods); var rawvalue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=PositiveTrendData" }, ct).ConfigureAwait(false); var firstValue = (double?)rawvalue?.Value; _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(100), 50); rawvalue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=PositiveTrendData" }, ct).ConfigureAwait(false); var secondValue = (double?)rawvalue?.Value; secondValue.Should().BeGreaterThan(firstValue ?? double.MaxValue); } public async Task NegativeTrendDataNodeHasValueWithTrendAsync(CancellationToken ct = default) { var services = _services(); _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(100), 50 * kRampUpPeriods); var rawvalue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=NegativeTrendData" }, ct).ConfigureAwait(false); var firstValue = (double?)rawvalue?.Value; _server.FireTimersWithPeriod(TimeSpan.FromMilliseconds(100), 50); rawvalue = await services.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = Plc.Namespaces.PlcApplications + "#s=NegativeTrendData" }, ct).ConfigureAwait(false); var secondValue = (double?)rawvalue?.Value; secondValue.Should().BeLessThan(firstValue ?? 0.0); } /// /// Simulator does not update trended and boolean values in the first few cycles /// (a random number of cycles between 1 and 10) /// private const int kRampUpPeriods = 10; /// /// Value set for NumberOfUpdates for the simulator to update value indefinitely. /// private const int kNoLimit = -1; private readonly T _connection; private readonly BaseServerFixture _server; private readonly Func> _services; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/SimpleEvents/SimpleEventsServerTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher; using Azure.IIoT.OpcUa.Publisher.Models; using FluentAssertions; using SimpleEvents; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Xunit; /// /// Simple Events server node tests /// /// public class SimpleEventsServerTests { public SimpleEventsServerTests(Func> services, T connection) { _services = services; _connection = connection; } public async Task CompileSimpleBaseEventQueryTestAsync(CancellationToken ct = default) { var services = _services(); var result = await services.CompileQueryAsync(_connection, new QueryCompilationRequestModel { Query = "select * from BaseEventType", QueryType = QueryType.Event }, ct).ConfigureAwait(false); Assert.NotNull(result); Assert.Null(result.ErrorInfo); Assert.NotNull(result.EventFilter); result.EventFilter.Should().BeEquivalentTo(new EventFilterModel { SelectClauses = new List { new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/EventId" }, AttributeId = NodeAttribute.Value, DisplayName = "/EventId.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/EventType" }, AttributeId = NodeAttribute.Value, DisplayName = "/EventType.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/SourceNode" }, AttributeId = NodeAttribute.Value, DisplayName = "/SourceNode.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/SourceName" }, AttributeId = NodeAttribute.Value, DisplayName = "/SourceName.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/Time" }, AttributeId = NodeAttribute.Value, DisplayName = "/Time.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/ReceiveTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/ReceiveTime.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/LocalTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/LocalTime.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/Message" }, AttributeId = NodeAttribute.Value, DisplayName = "/Message.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/Severity" }, AttributeId = NodeAttribute.Value, DisplayName = "/Severity.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/ConditionClassId" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionClassId.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/ConditionClassName" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionClassName.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/ConditionSubClassId" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionSubClassId.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/ConditionSubClassName" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionSubClassName.Value" } } }); } public async Task CompileSimpleEventsQueryTestAsync(CancellationToken ct = default) { var services = _services(); var result = await services.CompileQueryAsync(_connection, new QueryCompilationRequestModel { Query = "prefix se " + $"select * from se:i={ObjectTypes.SystemCycleStartedEventType} " + $"where oftype se:i={ObjectTypes.SystemCycleStartedEventType}", QueryType = QueryType.Event }, ct).ConfigureAwait(false); Assert.NotNull(result); Assert.Null(result.ErrorInfo); Assert.NotNull(result.EventFilter); result.EventFilter.Should().BeEquivalentTo(new EventFilterModel { SelectClauses = new List { new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/EventId" }, AttributeId = NodeAttribute.Value, DisplayName = "/EventId.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/EventType" }, AttributeId = NodeAttribute.Value, DisplayName = "/EventType.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/SourceNode" }, AttributeId = NodeAttribute.Value, DisplayName = "/SourceNode.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/SourceName" }, AttributeId = NodeAttribute.Value, DisplayName = "/SourceName.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/Time" }, AttributeId = NodeAttribute.Value, DisplayName = "/Time.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/ReceiveTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/ReceiveTime.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/LocalTime" }, AttributeId = NodeAttribute.Value, DisplayName = "/LocalTime.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/Message" }, AttributeId = NodeAttribute.Value, DisplayName = "/Message.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/Severity" }, AttributeId = NodeAttribute.Value, DisplayName = "/Severity.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/ConditionClassId" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionClassId.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/ConditionClassName" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionClassName.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/ConditionSubClassId" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionSubClassId.Value" }, new() { TypeDefinitionId = "i=2041", BrowsePath = new[] { "/ConditionSubClassName" }, AttributeId = NodeAttribute.Value, DisplayName = "/ConditionSubClassName.Value" }, new() { TypeDefinitionId = "http://opcfoundation.org/SimpleEvents#i=235", BrowsePath = new[] { "/http://opcfoundation.org/SimpleEvents#CycleId" }, AttributeId = NodeAttribute.Value, DisplayName = "/CycleId.Value" }, new() { TypeDefinitionId = "http://opcfoundation.org/SimpleEvents#i=235", BrowsePath = new[] { "/http://opcfoundation.org/SimpleEvents#CurrentStep" }, AttributeId = NodeAttribute.Value, DisplayName = "/CurrentStep.Value" }, new() { TypeDefinitionId = "http://opcfoundation.org/SimpleEvents#i=184", BrowsePath = new[] { "/http://opcfoundation.org/SimpleEvents#Steps" }, AttributeId = NodeAttribute.Value, DisplayName = "/Steps.Value" } }, WhereClause = new ContentFilterModel { Elements = new List { new() { FilterOperator = FilterOperatorType.OfType, FilterOperands = new List { new() { Value = "http://opcfoundation.org/SimpleEvents#i=184", DataType = "NodeId" } } } } } }); } private readonly T _connection; private readonly Func> _services; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/BrowsePathTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Xunit; public class BrowsePathTests { /// /// Create browse path tests /// /// /// public BrowsePathTests(Func> services, T connection) { _services = services; _connection = connection; } public async Task NodeBrowsePathStaticScalarMethod3Test1Async(CancellationToken ct = default) { const string nodeId = "http://test.org/UA/Data/#i=10157"; // Data var pathElements = new[] { "http://test.org/UA/Data/#Static", "http://test.org/UA/Data/#MethodTest", "http://test.org/UA/Data/#ScalarMethod3" }; var browser = _services(); // Act var results = await browser.BrowsePathAsync(_connection, new BrowsePathRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { Level = DiagnosticsLevel.None } }, NodeId = nodeId, BrowsePaths = new List { pathElements } }, ct).ConfigureAwait(false); // Assert Assert.Null(results.ErrorInfo); Assert.Collection(results.Targets!, target => { Assert.Equal("http://test.org/UA/Data/#ScalarMethod3", target.Target.BrowseName); Assert.Equal("ScalarMethod3", target.Target.DisplayName); Assert.Equal("http://test.org/UA/Data/#i=10762", target.Target.NodeId); Assert.Equal(false, target.Target.Children); Assert.Equal(-1, target.RemainingPathIndex); }); } public async Task NodeBrowsePathStaticScalarMethod3Test2Async(CancellationToken ct = default) { const string nodeId = "http://test.org/UA/Data/#i=10157"; // Data var pathElements = new[] { ".http://test.org/UA/Data/#Static", ".http://test.org/UA/Data/#MethodTest", ".http://test.org/UA/Data/#ScalarMethod3" }; var browser = _services(); // Act var results = await browser.BrowsePathAsync(_connection, new BrowsePathRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { Level = DiagnosticsLevel.None } }, NodeId = nodeId, BrowsePaths = new List { pathElements } }, ct).ConfigureAwait(false); // Assert Assert.Null(results.ErrorInfo); Assert.Collection(results.Targets!, target => { Assert.Equal("http://test.org/UA/Data/#ScalarMethod3", target.Target.BrowseName); Assert.Equal("ScalarMethod3", target.Target.DisplayName); Assert.Equal("http://test.org/UA/Data/#i=10762", target.Target.NodeId); Assert.Equal(false, target.Target.Children); Assert.Equal(-1, target.RemainingPathIndex); }); } public async Task NodeBrowsePathStaticScalarMethod3Test3Async(CancellationToken ct = default) { const string nodeId = "http://test.org/UA/Data/#i=10157"; // Data var pathElements = new[] { "http://test.org/UA/Data/#Static", "http://test.org/UA/Data/#MethodTest", "http://test.org/UA/Data/#ScalarMethod3" }; var browser = _services(); // Act var results = await browser.BrowsePathAsync(_connection, new BrowsePathRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { Level = DiagnosticsLevel.None } }, NodeId = nodeId, BrowsePaths = new List { pathElements } }, ct).ConfigureAwait(false); // Assert Assert.Null(results.ErrorInfo); Assert.Collection(results.Targets!, target => { Assert.Equal("http://test.org/UA/Data/#ScalarMethod3", target.Target.BrowseName); Assert.Equal("ScalarMethod3", target.Target.DisplayName); Assert.Equal("http://test.org/UA/Data/#i=10762", target.Target.NodeId); Assert.Equal(false, target.Target.Children); Assert.Equal(-1, target.RemainingPathIndex); }); } public async Task NodeBrowsePathStaticScalarMethodsTestAsync(CancellationToken ct = default) { const string nodeId = "http://test.org/UA/Data/#i=10157"; // Data var pathElements3 = new[] { ".http://test.org/UA/Data/#Static", ".http://test.org/UA/Data/#MethodTest", ".http://test.org/UA/Data/#ScalarMethod3" }; var pathElements2 = new[] { ".http://test.org/UA/Data/#Static", ".http://test.org/UA/Data/#MethodTest", ".http://test.org/UA/Data/#ScalarMethod2" }; var browser = _services(); // Act var results = await browser.BrowsePathAsync(_connection, new BrowsePathRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { Level = DiagnosticsLevel.None } }, NodeId = nodeId, BrowsePaths = new List { pathElements3, pathElements2 } }, ct).ConfigureAwait(false); // Assert Assert.Null(results.ErrorInfo); Assert.Collection(results.Targets!, target => { Assert.Equal("http://test.org/UA/Data/#ScalarMethod3", target.Target.BrowseName); Assert.Equal("ScalarMethod3", target.Target.DisplayName); Assert.Equal("http://test.org/UA/Data/#i=10762", target.Target.NodeId); Assert.Equal(false, target.Target.Children); Assert.Equal(-1, target.RemainingPathIndex); }, target => { Assert.Equal("http://test.org/UA/Data/#ScalarMethod2", target.Target.BrowseName); Assert.Equal("ScalarMethod2", target.Target.DisplayName); Assert.Equal("http://test.org/UA/Data/#i=10759", target.Target.NodeId); Assert.Equal(false, target.Target.Children); Assert.Equal(-1, target.RemainingPathIndex); }); } private readonly T _connection; private readonly Func> _services; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/BrowseServicesTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Json; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Xunit; public class BrowseServicesTests { /// /// Create browse services tests /// /// /// public BrowseServicesTests(Func> services, T connection) { _services = services; _connection = connection; _serializer = new DefaultJsonSerializer(); } public async Task NodeBrowseInRootTest1Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseFirstRequestModel(), ct: ct).ConfigureAwait(false); // Assert Assert.Equal("i=84", results.Node.NodeId); Assert.Equal("Root", results.Node.DisplayName); Assert.Equal(true, results.Node.Children); Assert.Equal("The root of the server address space.", results.Node.Description); Assert.Null(results.Node.AccessRestrictions); Assert.Null(results.ContinuationToken); Assert.NotNull(results.References); // No order anymore in stack // Assert.Collection(results.References, // reference => // { // Assert.Equal("i=35", reference.ReferenceTypeId); // Assert.Equal(BrowseDirection.Forward, reference.Direction); // Assert.Equal("Objects", reference.Target.BrowseName); // Assert.Equal("Objects", reference.Target.DisplayName); // Assert.Equal("i=85", reference.Target.NodeId); // Assert.True(reference.Target.Value.IsNull()); // Assert.True(reference.Target.Children); // }, // reference => // { // Assert.Equal("i=35", reference.ReferenceTypeId); // Assert.Equal(BrowseDirection.Forward, reference.Direction); // Assert.Equal("Types", reference.Target.BrowseName); // Assert.Equal("Types", reference.Target.DisplayName); // Assert.Equal("i=86", reference.Target.NodeId); // Assert.True(reference.Target.Value.IsNull()); // Assert.True(reference.Target.Children); // }, // reference => // { // Assert.Equal("i=35", reference.ReferenceTypeId); // Assert.Equal(BrowseDirection.Forward, reference.Direction); // Assert.Equal("Views", reference.Target.BrowseName); // Assert.Equal("Views", reference.Target.DisplayName); // Assert.Equal("i=87", reference.Target.NodeId); // Assert.True(reference.Target.Value.IsNull()); // Assert.False(reference.Target.Children); // }); } public async Task NodeBrowseInRootTest2Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseFirstRequestModel { TargetNodesOnly = true, ReadVariableValues = true }, ct: ct).ConfigureAwait(false); // Assert Assert.Equal("i=84", results.Node.NodeId); Assert.Equal("Root", results.Node.DisplayName); Assert.Equal(true, results.Node.Children); Assert.Equal("The root of the server address space.", results.Node.Description); Assert.Null(results.Node.AccessRestrictions); Assert.Null(results.ContinuationToken); Assert.NotNull(results.References); // No order anymore in stack // Assert.Collection(results.References, // reference => // { // Assert.Null(reference.ReferenceTypeId); // Assert.Null(reference.Direction); // Assert.Equal("Objects", reference.Target.BrowseName); // Assert.Equal("Objects", reference.Target.DisplayName); // Assert.Equal("i=85", reference.Target.NodeId); // Assert.True(reference.Target.Value.IsNull()); // Assert.True(reference.Target.Children); // }, // reference => // { // Assert.Null(reference.ReferenceTypeId); // Assert.Null(reference.Direction); // Assert.Equal("Types", reference.Target.BrowseName); // Assert.Equal("Types", reference.Target.DisplayName); // Assert.Equal("i=86", reference.Target.NodeId); // Assert.True(reference.Target.Value.IsNull()); // Assert.True(reference.Target.Children); // }, // reference => // { // Assert.Null(reference.ReferenceTypeId); // Assert.Null(reference.Direction); // Assert.Equal("Views", reference.Target.BrowseName); // Assert.Equal("Views", reference.Target.DisplayName); // Assert.Equal("i=87", reference.Target.NodeId); // Assert.True(reference.Target.Value.IsNull()); // Assert.False(reference.Target.Children); // }); } public async Task NodeBrowseFirstInRootTest1Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseFirstAsync(_connection, new BrowseFirstRequestModel { TargetNodesOnly = false, MaxReferencesToReturn = 1 }, ct).ConfigureAwait(false); // Assert Assert.Equal("i=84", results.Node.NodeId); Assert.Equal("Root", results.Node.DisplayName); Assert.Equal(true, results.Node.Children); Assert.Equal("The root of the server address space.", results.Node.Description); Assert.Null(results.Node.AccessRestrictions); Assert.NotNull(results.ContinuationToken); Assert.NotNull(results.References); Assert.True(results.References.Count == 1); // No order anymore in stack // Assert.Collection(results.References, // reference => // { // Assert.Equal("i=35", reference.ReferenceTypeId); // Assert.Equal(BrowseDirection.Forward, reference.Direction); // Assert.Equal("Objects", reference.Target.BrowseName); // Assert.Equal("Objects", reference.Target.DisplayName); // Assert.Equal("i=85", reference.Target.NodeId); // Assert.True(reference.Target.Children); // }); } public async Task NodeBrowseFirstInRootTest2Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseFirstAsync(_connection, new BrowseFirstRequestModel { TargetNodesOnly = false, MaxReferencesToReturn = 2 }, ct).ConfigureAwait(false); // Assert Assert.Equal("i=84", results.Node.NodeId); Assert.Equal("Root", results.Node.DisplayName); Assert.Equal(true, results.Node.Children); Assert.Equal("The root of the server address space.", results.Node.Description); Assert.Null(results.Node.AccessRestrictions); Assert.NotNull(results.ContinuationToken); Assert.NotNull(results.References); Assert.True(results.References.Count == 2); // No order anymore in stack // Assert.Collection(results.References, // reference => // { // Assert.Equal("i=35", reference.ReferenceTypeId); // Assert.Equal(BrowseDirection.Forward, reference.Direction); // Assert.Equal("Objects", reference.Target.BrowseName); // Assert.Equal("Objects", reference.Target.DisplayName); // Assert.Equal("i=85", reference.Target.NodeId); // Assert.True(reference.Target.Children); // }, // reference => // { // Assert.Equal("i=35", reference.ReferenceTypeId); // Assert.Equal(BrowseDirection.Forward, reference.Direction); // Assert.Equal("Types", reference.Target.BrowseName); // Assert.Equal("Types", reference.Target.DisplayName); // Assert.Equal("i=86", reference.Target.NodeId); // Assert.True(reference.Target.Children); // }); } public async Task NodeBrowseBoilersObjectsTest1Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseFirstRequestModel { NodeId = "http://opcfoundation.org/UA/Boiler/#i=1240", TargetNodesOnly = true }, ct: ct).ConfigureAwait(false); // Assert Assert.NotNull(results.Node); Assert.Equal("http://opcfoundation.org/UA/Boiler/#i=1240", results.Node.NodeId); Assert.Equal("Boilers", results.Node.DisplayName); Assert.Equal(true, results.Node.Children); Assert.Equal(NodeEventNotifier.SubscribeToEvents, results.Node.EventNotifier); Assert.Null(results.Node.Description); Assert.Null(results.Node.AccessRestrictions); Assert.Null(results.ContinuationToken); Assert.NotNull(results.References); Assert.Collection(results.References, reference => { Assert.Null(reference.ReferenceTypeId); Assert.Null(reference.Direction); Assert.Equal("Boiler #1", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("http://opcfoundation.org/UA/Boiler/#i=1241", reference.Target.NodeId); Assert.True(reference.Target.Children); }, reference => { Assert.Null(reference.ReferenceTypeId); Assert.Null(reference.Direction); Assert.Equal("Boiler #2", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("http://opcfoundation.org/UA/Boiler//Instance#i=1", reference.Target.NodeId); Assert.True(reference.Target.Children); }); } public async Task NodeBrowseDataAccessObjectsTest1Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseFirstRequestModel { NodeId = "nsu=DataAccess;s=0:TestData/Static", TargetNodesOnly = false }, ct: ct).ConfigureAwait(false); // Assert Assert.Equal("nsu=DataAccess;s=0:TestData/Static", results.Node.NodeId); Assert.Equal("Static", results.Node.DisplayName); Assert.Equal(true, results.Node.Children); Assert.Equal(NodeClass.Object, results.Node.NodeClass); Assert.Null(results.Node.EventNotifier); Assert.Null(results.Node.Description); Assert.Null(results.Node.AccessRestrictions); Assert.Null(results.ContinuationToken); Assert.NotNull(results.References); Assert.Collection(results.References, reference => { Assert.Equal("i=35", reference.ReferenceTypeId); Assert.Equal("DataAccess#FC1001", reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Direction); Assert.Equal("FC1001", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:FC1001", reference.Target.NodeId); Assert.True(reference.Target.Children); }, reference => { Assert.Equal("i=35", reference.ReferenceTypeId); Assert.Equal("DataAccess#LC1001", reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Direction); Assert.Equal("LC1001", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:LC1001", reference.Target.NodeId); Assert.True(reference.Target.Children); }, reference => { Assert.Equal("i=35", reference.ReferenceTypeId); Assert.Equal("DataAccess#CC1001", reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Direction); Assert.Equal("CC1001", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:CC1001", reference.Target.NodeId); Assert.True(reference.Target.Children); }, reference => { Assert.Equal("i=35", reference.ReferenceTypeId); Assert.Equal("DataAccess#FC2001", reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Direction); Assert.Equal("FC2001", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:FC2001", reference.Target.NodeId); Assert.True(reference.Target.Children); }, reference => { Assert.Equal("i=35", reference.ReferenceTypeId); Assert.Equal("DataAccess#LC2001", reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Direction); Assert.Equal("LC2001", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:LC2001", reference.Target.NodeId); Assert.True(reference.Target.Children); }, reference => { Assert.Equal("i=35", reference.ReferenceTypeId); Assert.Equal("DataAccess#CC2001", reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Direction); Assert.Equal("CC2001", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:CC2001", reference.Target.NodeId); Assert.True(reference.Target.Children); }); } public async Task NodeBrowseDataAccessObjectsTest2Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseFirstRequestModel { NodeId = "DataAccess#s=0:TestData/Static", TargetNodesOnly = false }, ct: ct).ConfigureAwait(false); // Assert Assert.Equal("nsu=DataAccess;s=0:TestData/Static", results.Node.NodeId); Assert.Equal("Static", results.Node.DisplayName); Assert.Equal(true, results.Node.Children); Assert.Equal(NodeClass.Object, results.Node.NodeClass); Assert.Null(results.Node.EventNotifier); Assert.Null(results.Node.Description); Assert.Null(results.Node.AccessRestrictions); Assert.Null(results.ContinuationToken); Assert.NotNull(results.References); Assert.Collection(results.References, reference => { Assert.Equal("i=35", reference.ReferenceTypeId); Assert.Equal("DataAccess#FC1001", reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Direction); Assert.Equal("FC1001", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:FC1001", reference.Target.NodeId); Assert.True(reference.Target.Children); }, reference => { Assert.Equal("i=35", reference.ReferenceTypeId); Assert.Equal("DataAccess#LC1001", reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Direction); Assert.Equal("LC1001", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:LC1001", reference.Target.NodeId); Assert.True(reference.Target.Children); }, reference => { Assert.Equal("i=35", reference.ReferenceTypeId); Assert.Equal("DataAccess#CC1001", reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Direction); Assert.Equal("CC1001", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:CC1001", reference.Target.NodeId); Assert.True(reference.Target.Children); }, reference => { Assert.Equal("i=35", reference.ReferenceTypeId); Assert.Equal("DataAccess#FC2001", reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Direction); Assert.Equal("FC2001", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:FC2001", reference.Target.NodeId); Assert.True(reference.Target.Children); }, reference => { Assert.Equal("i=35", reference.ReferenceTypeId); Assert.Equal("DataAccess#LC2001", reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Direction); Assert.Equal("LC2001", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:LC2001", reference.Target.NodeId); Assert.True(reference.Target.Children); }, reference => { Assert.Equal("i=35", reference.ReferenceTypeId); Assert.Equal("DataAccess#CC2001", reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Direction); Assert.Equal("CC2001", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:CC2001", reference.Target.NodeId); Assert.True(reference.Target.Children); }); } public async Task NodeBrowseDataAccessObjectsTest3Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseFirstRequestModel { NodeId = "nsu=DataAccess;s=0:TestData/Static", TargetNodesOnly = true, ReadVariableValues = true }, ct: ct).ConfigureAwait(false); // Assert Assert.Equal("nsu=DataAccess;s=0:TestData/Static", results.Node.NodeId); Assert.Equal("Static", results.Node.DisplayName); Assert.Equal(true, results.Node.Children); Assert.Equal(NodeClass.Object, results.Node.NodeClass); Assert.Null(results.Node.EventNotifier); Assert.Null(results.Node.Description); Assert.Null(results.Node.AccessRestrictions); Assert.Null(results.ContinuationToken); Assert.NotNull(results.References); Assert.Collection(results.References, reference => { Assert.Null(reference.ReferenceTypeId); Assert.Equal("DataAccess#FC1001", reference.Target.BrowseName); Assert.Null(reference.Direction); Assert.Equal("FC1001", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:FC1001", reference.Target.NodeId); Assert.True(reference.Target.Value.IsNull()); Assert.True(reference.Target.Children); }, reference => { Assert.Null(reference.ReferenceTypeId); Assert.Equal("DataAccess#LC1001", reference.Target.BrowseName); Assert.Null(reference.Direction); Assert.Equal("LC1001", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:LC1001", reference.Target.NodeId); Assert.True(reference.Target.Value.IsNull()); Assert.True(reference.Target.Children); }, reference => { Assert.Null(reference.ReferenceTypeId); Assert.Equal("DataAccess#CC1001", reference.Target.BrowseName); Assert.Null(reference.Direction); Assert.Equal("CC1001", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:CC1001", reference.Target.NodeId); Assert.True(reference.Target.Value.IsNull()); Assert.True(reference.Target.Children); }, reference => { Assert.Null(reference.ReferenceTypeId); Assert.Equal("DataAccess#FC2001", reference.Target.BrowseName); Assert.Null(reference.Direction); Assert.Equal("FC2001", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:FC2001", reference.Target.NodeId); Assert.True(reference.Target.Value.IsNull()); Assert.True(reference.Target.Children); }, reference => { Assert.Null(reference.ReferenceTypeId); Assert.Equal("DataAccess#LC2001", reference.Target.BrowseName); Assert.Null(reference.Direction); Assert.Equal("LC2001", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:LC2001", reference.Target.NodeId); Assert.True(reference.Target.Value.IsNull()); Assert.True(reference.Target.Children); }, reference => { Assert.Null(reference.ReferenceTypeId); Assert.Equal("DataAccess#CC2001", reference.Target.BrowseName); Assert.Null(reference.Direction); Assert.Equal("CC2001", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:CC2001", reference.Target.NodeId); Assert.True(reference.Target.Value.IsNull()); Assert.True(reference.Target.Children); }); } public async Task NodeBrowseDataAccessObjectsTest4Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseFirstRequestModel { NodeId = "DataAccess#s=0:TestData/Static", TargetNodesOnly = true, ReadVariableValues = true }, ct: ct).ConfigureAwait(false); // Assert Assert.Equal("nsu=DataAccess;s=0:TestData/Static", results.Node.NodeId); Assert.Equal("Static", results.Node.DisplayName); Assert.Equal(true, results.Node.Children); Assert.Equal(NodeClass.Object, results.Node.NodeClass); Assert.Null(results.Node.EventNotifier); Assert.Null(results.Node.Description); Assert.Null(results.Node.AccessRestrictions); Assert.Null(results.ContinuationToken); Assert.NotNull(results.References); Assert.Collection(results.References, reference => { Assert.Null(reference.ReferenceTypeId); Assert.Equal("DataAccess#FC1001", reference.Target.BrowseName); Assert.Null(reference.Direction); Assert.Equal("FC1001", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:FC1001", reference.Target.NodeId); Assert.True(reference.Target.Value.IsNull()); Assert.True(reference.Target.Children); }, reference => { Assert.Null(reference.ReferenceTypeId); Assert.Equal("DataAccess#LC1001", reference.Target.BrowseName); Assert.Null(reference.Direction); Assert.Equal("LC1001", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:LC1001", reference.Target.NodeId); Assert.True(reference.Target.Value.IsNull()); Assert.True(reference.Target.Children); }, reference => { Assert.Null(reference.ReferenceTypeId); Assert.Equal("DataAccess#CC1001", reference.Target.BrowseName); Assert.Null(reference.Direction); Assert.Equal("CC1001", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:CC1001", reference.Target.NodeId); Assert.True(reference.Target.Value.IsNull()); Assert.True(reference.Target.Children); }, reference => { Assert.Null(reference.ReferenceTypeId); Assert.Equal("DataAccess#FC2001", reference.Target.BrowseName); Assert.Null(reference.Direction); Assert.Equal("FC2001", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:FC2001", reference.Target.NodeId); Assert.True(reference.Target.Value.IsNull()); Assert.True(reference.Target.Children); }, reference => { Assert.Null(reference.ReferenceTypeId); Assert.Equal("DataAccess#LC2001", reference.Target.BrowseName); Assert.Null(reference.Direction); Assert.Equal("LC2001", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:LC2001", reference.Target.NodeId); Assert.True(reference.Target.Value.IsNull()); Assert.True(reference.Target.Children); }, reference => { Assert.Null(reference.ReferenceTypeId); Assert.Equal("DataAccess#CC2001", reference.Target.BrowseName); Assert.Null(reference.Direction); Assert.Equal("CC2001", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:CC2001", reference.Target.NodeId); Assert.True(reference.Target.Value.IsNull()); Assert.True(reference.Target.Children); }); } public async Task NodeBrowseDataAccessFC1001Test1Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseFirstRequestModel { NodeId = "nsu=DataAccess;s=1:FC1001", TargetNodesOnly = false }, ct: ct).ConfigureAwait(false); // Assert Assert.Equal("nsu=DataAccess;s=1:FC1001", results.Node.NodeId); Assert.Equal("FC1001", results.Node.DisplayName); Assert.Equal(true, results.Node.Children); Assert.Equal(NodeClass.Object, results.Node.NodeClass); Assert.Null(results.Node.EventNotifier); Assert.Null(results.Node.Description); Assert.Null(results.Node.AccessRestrictions); Assert.Null(results.ContinuationToken); Assert.NotNull(results.References); Assert.Collection(results.References, reference => { Assert.Equal("i=47", reference.ReferenceTypeId); Assert.Equal("DataAccess#SetPoint", reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Direction); Assert.Equal("SetPoint", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:FC1001?SetPoint", reference.Target.NodeId); Assert.True(reference.Target.Children); }, reference => { Assert.Equal("i=47", reference.ReferenceTypeId); Assert.Equal("DataAccess#Measurement", reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Direction); Assert.Equal("Measurement", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:FC1001?Measurement", reference.Target.NodeId); Assert.Equal("i=2365", reference.Target.TypeDefinitionId); Assert.Equal("Float", reference.Target.DataType); Assert.True(reference.Target.Children); }, reference => { Assert.Equal("i=47", reference.ReferenceTypeId); Assert.Equal("DataAccess#Output", reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Direction); Assert.Equal("Output", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:FC1001?Output", reference.Target.NodeId); Assert.Equal("i=2365", reference.Target.TypeDefinitionId); Assert.Equal("Float", reference.Target.DataType); Assert.True(reference.Target.Children); }, reference => { Assert.Equal("i=47", reference.ReferenceTypeId); Assert.Equal("DataAccess#Status", reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Direction); Assert.Equal("Status", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:FC1001?Status", reference.Target.NodeId); Assert.Equal("i=2376", reference.Target.TypeDefinitionId); Assert.Equal("Int32", reference.Target.DataType); Assert.True(reference.Target.Children); }); } public async Task NodeBrowseDataAccessFC1001Test2Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseFirstRequestModel { NodeId = "nsu=DataAccess;s=1:FC1001", TargetNodesOnly = true, ReadVariableValues = true }, ct: ct).ConfigureAwait(false); // Assert Assert.Equal("nsu=DataAccess;s=1:FC1001", results.Node.NodeId); Assert.Equal("FC1001", results.Node.DisplayName); Assert.Equal(true, results.Node.Children); Assert.Equal(NodeClass.Object, results.Node.NodeClass); Assert.Null(results.Node.EventNotifier); Assert.Null(results.Node.Description); Assert.Null(results.Node.AccessRestrictions); Assert.Null(results.ContinuationToken); Assert.NotNull(results.References); Assert.Collection(results.References, reference => { Assert.Null(reference.ReferenceTypeId); Assert.Equal("DataAccess#SetPoint", reference.Target.BrowseName); Assert.Null(reference.Direction); Assert.Equal("SetPoint", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:FC1001?SetPoint", reference.Target.NodeId); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Children); }, reference => { Assert.Null(reference.ReferenceTypeId); Assert.Equal("DataAccess#Measurement", reference.Target.BrowseName); Assert.Null(reference.Direction); Assert.Equal("Measurement", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:FC1001?Measurement", reference.Target.NodeId); Assert.Equal("i=2365", reference.Target.TypeDefinitionId); Assert.Equal("Float", reference.Target.DataType); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Children); }, reference => { Assert.Null(reference.ReferenceTypeId); Assert.Equal("DataAccess#Output", reference.Target.BrowseName); Assert.Null(reference.Direction); Assert.Equal("Output", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:FC1001?Output", reference.Target.NodeId); Assert.Equal("i=2365", reference.Target.TypeDefinitionId); Assert.Equal("Float", reference.Target.DataType); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Children); }, reference => { Assert.Null(reference.ReferenceTypeId); Assert.Equal("DataAccess#Status", reference.Target.BrowseName); Assert.Null(reference.Direction); Assert.Equal("Status", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("nsu=DataAccess;s=1:FC1001?Status", reference.Target.NodeId); Assert.Equal("i=2376", reference.Target.TypeDefinitionId); Assert.Equal("Int32", reference.Target.DataType); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Children); }); } public async Task NodeBrowseBoilersObjectsTest2Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseFirstRequestModel { NodeId = "http://opcfoundation.org/UA/Boiler/#i=1240", TargetNodesOnly = false }, ct: ct).ConfigureAwait(false); // Assert Assert.NotNull(results.Node); Assert.Equal("http://opcfoundation.org/UA/Boiler/#i=1240", results.Node.NodeId); Assert.Equal("Boilers", results.Node.DisplayName); Assert.Equal(true, results.Node.Children); Assert.Equal(NodeEventNotifier.SubscribeToEvents, results.Node.EventNotifier); Assert.Null(results.Node.Description); Assert.Null(results.Node.AccessRestrictions); Assert.Null(results.ContinuationToken); Assert.NotNull(results.References); Assert.Contains(results.References, reference => { if (reference.ReferenceTypeId != "i=47") { return false; } Assert.Equal("i=47", reference.ReferenceTypeId); Assert.Equal("http://opcfoundation.org/UA/Boiler/#Boiler+%231", reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Direction); Assert.Equal("Boiler #1", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("http://opcfoundation.org/UA/Boiler/#i=1241", reference.Target.NodeId); Assert.True(reference.Target.Children); return true; }); Assert.Contains(results.References, reference => { if (reference.ReferenceTypeId != "i=48") { return false; } Assert.Equal("i=48", reference.ReferenceTypeId); Assert.Equal("http://opcfoundation.org/UA/Boiler/#Boiler+%231", reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Direction); Assert.Equal("Boiler #1", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("http://opcfoundation.org/UA/Boiler/#i=1241", reference.Target.NodeId); Assert.True(reference.Target.Children); return true; }); Assert.Contains(results.References, reference => { if (reference.ReferenceTypeId != "i=35") { return false; } Assert.Equal("i=35", reference.ReferenceTypeId); Assert.Equal("http://opcfoundation.org/UA/Boiler//Instance#Boiler+%232", reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Direction); Assert.Equal("Boiler #2", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("http://opcfoundation.org/UA/Boiler//Instance#i=1", reference.Target.NodeId); Assert.True(reference.Target.Children); return true; }); } public async Task NodeBrowseStaticScalarVariablesTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseFirstRequestModel { NodeId = "http://test.org/UA/Data/#i=10159", TargetNodesOnly = true }, ct: ct).ConfigureAwait(false); // Assert Assert.Null(results.ContinuationToken); Assert.Equal("http://test.org/UA/Data/#i=10159", results.Node.NodeId); Assert.Equal("Scalar", results.Node.DisplayName); Assert.Equal(NodeClass.Object, results.Node.NodeClass); Assert.True(results.Node.Children); Assert.NotNull(results.References); Assert.Collection(results.References, reference => { Assert.Equal("http://test.org/UA/Data/#i=10216", reference.Target.NodeId); Assert.Equal("Boolean", reference.Target.DataType); Assert.Equal("BooleanValue", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10217", reference.Target.NodeId); Assert.Equal("SByte", reference.Target.DataType); Assert.Equal("SByteValue", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10218", reference.Target.NodeId); Assert.Equal("Byte", reference.Target.DataType); Assert.Equal("ByteValue", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10219", reference.Target.NodeId); Assert.Equal("Int16", reference.Target.DataType); Assert.Equal("Int16Value", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10220", reference.Target.NodeId); Assert.Equal("UInt16", reference.Target.DataType); Assert.Equal("UInt16Value", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10221", reference.Target.NodeId); Assert.Equal("Int32", reference.Target.DataType); Assert.Equal("Int32Value", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10222", reference.Target.NodeId); Assert.Equal("UInt32", reference.Target.DataType); Assert.Equal("UInt32Value", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10223", reference.Target.NodeId); Assert.Equal("Int64", reference.Target.DataType); Assert.Equal("Int64Value", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10224", reference.Target.NodeId); Assert.Equal("UInt64", reference.Target.DataType); Assert.Equal("UInt64Value", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10225", reference.Target.NodeId); Assert.Equal("Float", reference.Target.DataType); Assert.Equal("FloatValue", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10226", reference.Target.NodeId); Assert.Equal("Double", reference.Target.DataType); Assert.Equal("DoubleValue", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10227", reference.Target.NodeId); Assert.Equal("String", reference.Target.DataType); Assert.Equal("StringValue", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10228", reference.Target.NodeId); Assert.Equal("DateTime", reference.Target.DataType); Assert.Equal("DateTimeValue", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10229", reference.Target.NodeId); Assert.Equal("Guid", reference.Target.DataType); Assert.Equal("GuidValue", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10230", reference.Target.NodeId); Assert.Equal("ByteString", reference.Target.DataType); Assert.Equal("ByteStringValue", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10231", reference.Target.NodeId); Assert.Equal("XmlElement", reference.Target.DataType); Assert.Equal("XmlElementValue", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10232", reference.Target.NodeId); Assert.Equal("NodeId", reference.Target.DataType); Assert.Equal("NodeIdValue", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10233", reference.Target.NodeId); Assert.Equal("ExpandedNodeId", reference.Target.DataType); Assert.Equal("ExpandedNodeIdValue", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10234", reference.Target.NodeId); Assert.Equal("QualifiedName", reference.Target.DataType); Assert.Equal("QualifiedNameValue", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10235", reference.Target.NodeId); Assert.Equal("LocalizedText", reference.Target.DataType); Assert.Equal("LocalizedTextValue", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10236", reference.Target.NodeId); Assert.Equal("StatusCode", reference.Target.DataType); Assert.Equal("StatusCodeValue", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10237", reference.Target.NodeId); Assert.Equal("Variant", reference.Target.DataType); Assert.Equal("VariantValue", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10238", reference.Target.NodeId); Assert.Equal("Enumeration", reference.Target.DataType); Assert.Equal("EnumerationValue", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10239", reference.Target.NodeId); Assert.Equal("ExtensionObject", reference.Target.DataType); Assert.Equal("StructureValue", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); } , reference => { Assert.Equal("http://test.org/UA/Data/#i=10240", reference.Target.NodeId); Assert.Equal("Number", reference.Target.DataType); Assert.Equal("NumberValue", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10241", reference.Target.NodeId); Assert.Equal("Integer", reference.Target.DataType); Assert.Equal("IntegerValue", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10242", reference.Target.NodeId); Assert.Equal("UInteger", reference.Target.DataType); Assert.Equal("UIntegerValue", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10160", reference.Target.NodeId); Assert.Equal("Boolean", reference.Target.DataType); Assert.Equal("SimulationActive", reference.Target.DisplayName); Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal(NodeAccessLevel.CurrentRead, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.False(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10161", reference.Target.NodeId); Assert.Equal("GenerateValues", reference.Target.DisplayName); Assert.Equal(NodeClass.Method, reference.Target.NodeClass); Assert.True(reference.Target.Executable); Assert.True(reference.Target.UserExecutable); Assert.True(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10163", reference.Target.NodeId); Assert.Equal("CycleComplete", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Null(reference.Target.Executable); Assert.Null(reference.Target.UserExecutable); Assert.True(reference.Target.Children); }); } public async Task NodeBrowseStaticScalarVariablesTestWithFilter1Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseFirstRequestModel { NodeId = "http://test.org/UA/Data/#i=10159", TargetNodesOnly = true, NodeClassFilter = new List { NodeClass.Method, NodeClass.Object } }, ct: ct).ConfigureAwait(false); // Assert Assert.Null(results.ContinuationToken); Assert.Equal("http://test.org/UA/Data/#i=10159", results.Node.NodeId); Assert.Equal("Scalar", results.Node.DisplayName); Assert.Equal(NodeClass.Object, results.Node.NodeClass); Assert.True(results.Node.Children); Assert.NotNull(results.References); Assert.Collection(results.References, reference => { Assert.Equal("http://test.org/UA/Data/#i=10161", reference.Target.NodeId); Assert.Equal("GenerateValues", reference.Target.DisplayName); Assert.Equal(NodeClass.Method, reference.Target.NodeClass); Assert.True(reference.Target.Executable); Assert.True(reference.Target.UserExecutable); Assert.True(reference.Target.Children); }, reference => { Assert.Equal("http://test.org/UA/Data/#i=10163", reference.Target.NodeId); Assert.Equal("CycleComplete", reference.Target.DisplayName); Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Null(reference.Target.Executable); Assert.Null(reference.Target.UserExecutable); Assert.True(reference.Target.Children); }); } public async Task NodeBrowseStaticScalarVariablesTestWithFilter2Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseFirstRequestModel { NodeId = "http://test.org/UA/Data/#i=10159", TargetNodesOnly = true, NodeClassFilter = new List { NodeClass.Method } }, ct: ct).ConfigureAwait(false); // Assert Assert.Null(results.ContinuationToken); Assert.Equal("http://test.org/UA/Data/#i=10159", results.Node.NodeId); Assert.Equal("Scalar", results.Node.DisplayName); Assert.Equal(NodeClass.Object, results.Node.NodeClass); Assert.True(results.Node.Children); Assert.NotNull(results.References); Assert.Collection(results.References, reference => { Assert.Equal("http://test.org/UA/Data/#i=10161", reference.Target.NodeId); Assert.Equal("GenerateValues", reference.Target.DisplayName); Assert.Equal(NodeClass.Method, reference.Target.NodeClass); Assert.True(reference.Target.Executable); Assert.True(reference.Target.UserExecutable); Assert.True(reference.Target.Children); }); } public async Task NodeBrowseStaticArrayVariablesTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseFirstRequestModel { NodeId = "http://test.org/UA/Data/#i=10243", TargetNodesOnly = true }, ct: ct).ConfigureAwait(false); // Assert Assert.Null(results.ContinuationToken); Assert.Equal("http://test.org/UA/Data/#i=10243", results.Node.NodeId); Assert.Equal("Array", results.Node.DisplayName); Assert.Equal(NodeClass.Object, results.Node.NodeClass); Assert.True(results.Node.Children); Assert.NotNull(results.References); Assert.True(results.References.Count == 30, _serializer.SerializeToString( results.References.Select(r => r.Target.DisplayName)) + results.ErrorInfo?.ToString()); Assert.Collection(results.References, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10300", reference.Target.NodeId); Assert.Equal("Boolean", reference.Target.DataType); Assert.Equal("BooleanValue", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10301", reference.Target.NodeId); Assert.Equal("SByte", reference.Target.DataType); Assert.Equal("SByteValue", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10302", reference.Target.NodeId); Assert.Equal("Byte", reference.Target.DataType); Assert.Equal("ByteValue", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10303", reference.Target.NodeId); Assert.Equal("Int16", reference.Target.DataType); Assert.Equal("Int16Value", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10304", reference.Target.NodeId); Assert.Equal("UInt16", reference.Target.DataType); Assert.Equal("UInt16Value", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10305", reference.Target.NodeId); Assert.Equal("Int32", reference.Target.DataType); Assert.Equal("Int32Value", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10306", reference.Target.NodeId); Assert.Equal("UInt32", reference.Target.DataType); Assert.Equal("UInt32Value", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10307", reference.Target.NodeId); Assert.Equal("Int64", reference.Target.DataType); Assert.Equal("Int64Value", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10308", reference.Target.NodeId); Assert.Equal("UInt64", reference.Target.DataType); Assert.Equal("UInt64Value", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10309", reference.Target.NodeId); Assert.Equal("Float", reference.Target.DataType); Assert.Equal("FloatValue", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10310", reference.Target.NodeId); Assert.Equal("Double", reference.Target.DataType); Assert.Equal("DoubleValue", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10311", reference.Target.NodeId); Assert.Equal("String", reference.Target.DataType); Assert.Equal("StringValue", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10312", reference.Target.NodeId); Assert.Equal("DateTime", reference.Target.DataType); Assert.Equal("DateTimeValue", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10313", reference.Target.NodeId); Assert.Equal("Guid", reference.Target.DataType); Assert.Equal("GuidValue", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10314", reference.Target.NodeId); Assert.Equal("ByteString", reference.Target.DataType); Assert.Equal("ByteStringValue", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10315", reference.Target.NodeId); Assert.Equal("XmlElement", reference.Target.DataType); Assert.Equal("XmlElementValue", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10316", reference.Target.NodeId); Assert.Equal("NodeId", reference.Target.DataType); Assert.Equal("NodeIdValue", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10317", reference.Target.NodeId); Assert.Equal("ExpandedNodeId", reference.Target.DataType); Assert.Equal("ExpandedNodeIdValue", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10318", reference.Target.NodeId); Assert.Equal("QualifiedName", reference.Target.DataType); Assert.Equal("QualifiedNameValue", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10319", reference.Target.NodeId); Assert.Equal("LocalizedText", reference.Target.DataType); Assert.Equal("LocalizedTextValue", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10320", reference.Target.NodeId); Assert.Equal("StatusCode", reference.Target.DataType); Assert.Equal("StatusCodeValue", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10321", reference.Target.NodeId); Assert.Equal("Variant", reference.Target.DataType); Assert.Equal("VariantValue", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10322", reference.Target.NodeId); Assert.Equal("Enumeration", reference.Target.DataType); Assert.Equal("EnumerationValue", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10323", reference.Target.NodeId); Assert.Equal("ExtensionObject", reference.Target.DataType); Assert.Equal("StructureValue", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10324", reference.Target.NodeId); Assert.Equal("Number", reference.Target.DataType); Assert.Equal("NumberValue", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10325", reference.Target.NodeId); Assert.Equal("Integer", reference.Target.DataType); Assert.Equal("IntegerValue", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10326", reference.Target.NodeId); Assert.Equal("UInteger", reference.Target.DataType); Assert.Equal("UIntegerValue", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead | NodeAccessLevel.CurrentWrite, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.OneDimension, reference.Target.ValueRank); Assert.NotNull(reference.Target.ArrayDimensions); Assert.Single(reference.Target.ArrayDimensions); Assert.Equal(0u, reference.Target.ArrayDimensions[0]); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10244", reference.Target.NodeId); Assert.Equal("Boolean", reference.Target.DataType); Assert.Equal("SimulationActive", reference.Target.DisplayName); Assert.Equal(NodeAccessLevel.CurrentRead, reference.Target.AccessLevel); Assert.Equal(NodeAccessLevel.CurrentRead, reference.Target.UserAccessLevel); Assert.Equal(NodeValueRank.Scalar, reference.Target.ValueRank); Assert.Null(reference.Target.ArrayDimensions); Assert.False(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Method, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10245", reference.Target.NodeId); Assert.Equal("GenerateValues", reference.Target.DisplayName); Assert.True(reference.Target.Executable); Assert.True(reference.Target.UserExecutable); Assert.True(reference.Target.Children); }, reference => { Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10247", reference.Target.NodeId); Assert.Equal("CycleComplete", reference.Target.DisplayName); Assert.Null(reference.Target.Executable); Assert.Null(reference.Target.UserExecutable); Assert.True(reference.Target.Children); }); } public async Task NodeBrowseStaticArrayVariablesWithValuesTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseFirstRequestModel { NodeId = "http://test.org/UA/Data/#i=10243", TargetNodesOnly = true, ReadVariableValues = true }, ct: ct).ConfigureAwait(false); // Assert Assert.Null(results.ContinuationToken); Assert.Equal("http://test.org/UA/Data/#i=10243", results.Node.NodeId); Assert.Equal("Array", results.Node.DisplayName); Assert.Equal(NodeClass.Object, results.Node.NodeClass); Assert.True(results.Node.Children); Assert.NotNull(results.References); Assert.True(results.References.Count == 30, _serializer.SerializeToString( results.References.Select(r => r.Target.DisplayName)) + results.ErrorInfo?.ToString()); Assert.Collection(results.References, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10300", reference.Target.NodeId); Assert.Equal("Boolean", reference.Target.DataType); Assert.Equal("BooleanValue", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Value!.IsListOfValues); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10301", reference.Target.NodeId); Assert.Equal("SByte", reference.Target.DataType); Assert.Equal("SByteValue", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Value!.IsListOfValues); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10302", reference.Target.NodeId); Assert.Equal("Byte", reference.Target.DataType); Assert.Equal("ByteValue", reference.Target.DisplayName); // Assert.False(reference.Target.Value.IsNull()); if (!reference.Target.Value.IsNull()) { Assert.True(reference.Target.Value!.IsString); } }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10303", reference.Target.NodeId); Assert.Equal("Int16", reference.Target.DataType); Assert.Equal("Int16Value", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Value!.IsListOfValues); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10304", reference.Target.NodeId); Assert.Equal("UInt16", reference.Target.DataType); Assert.Equal("UInt16Value", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Value!.IsListOfValues); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10305", reference.Target.NodeId); Assert.Equal("Int32", reference.Target.DataType); Assert.Equal("Int32Value", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Value!.IsListOfValues); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10306", reference.Target.NodeId); Assert.Equal("UInt32", reference.Target.DataType); Assert.Equal("UInt32Value", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Value!.IsListOfValues); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10307", reference.Target.NodeId); Assert.Equal("Int64", reference.Target.DataType); Assert.Equal("Int64Value", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Value!.IsListOfValues); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10308", reference.Target.NodeId); Assert.Equal("UInt64", reference.Target.DataType); Assert.Equal("UInt64Value", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Value!.IsListOfValues); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10309", reference.Target.NodeId); Assert.Equal("Float", reference.Target.DataType); Assert.Equal("FloatValue", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Value!.IsListOfValues); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10310", reference.Target.NodeId); Assert.Equal("Double", reference.Target.DataType); Assert.Equal("DoubleValue", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Value!.IsListOfValues); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10311", reference.Target.NodeId); Assert.Equal("String", reference.Target.DataType); Assert.Equal("StringValue", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Value!.IsListOfValues); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10312", reference.Target.NodeId); Assert.Equal("DateTime", reference.Target.DataType); Assert.Equal("DateTimeValue", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Value!.IsListOfValues); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10313", reference.Target.NodeId); Assert.Equal("Guid", reference.Target.DataType); Assert.Equal("GuidValue", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Value!.IsListOfValues); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10314", reference.Target.NodeId); Assert.Equal("ByteString", reference.Target.DataType); Assert.Equal("ByteStringValue", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Value!.IsListOfValues); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10315", reference.Target.NodeId); Assert.Equal("XmlElement", reference.Target.DataType); Assert.Equal("XmlElementValue", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Value!.IsListOfValues); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10316", reference.Target.NodeId); Assert.Equal("NodeId", reference.Target.DataType); Assert.Equal("NodeIdValue", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Value!.IsListOfValues); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10317", reference.Target.NodeId); Assert.Equal("ExpandedNodeId", reference.Target.DataType); Assert.Equal("ExpandedNodeIdValue", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Value!.IsListOfValues); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10318", reference.Target.NodeId); Assert.Equal("QualifiedName", reference.Target.DataType); Assert.Equal("QualifiedNameValue", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Value!.IsListOfValues); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10319", reference.Target.NodeId); Assert.Equal("LocalizedText", reference.Target.DataType); Assert.Equal("LocalizedTextValue", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Value!.IsListOfValues); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10320", reference.Target.NodeId); Assert.Equal("StatusCode", reference.Target.DataType); Assert.Equal("StatusCodeValue", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Value!.IsListOfValues); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10321", reference.Target.NodeId); Assert.Equal("Variant", reference.Target.DataType); Assert.Equal("VariantValue", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Value!.IsListOfValues); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10322", reference.Target.NodeId); Assert.Equal("Enumeration", reference.Target.DataType); Assert.Equal("EnumerationValue", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Value!.IsListOfValues); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10323", reference.Target.NodeId); Assert.Equal("ExtensionObject", reference.Target.DataType); Assert.Equal("StructureValue", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Value!.IsListOfValues); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10324", reference.Target.NodeId); // Assert.Equal("Number", reference.Target.DataType); Assert.Equal("NumberValue", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); // Assert.True(reference.Target.Value!.IsArray); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10325", reference.Target.NodeId); // Assert.Equal("Integer", reference.Target.DataType); Assert.Equal("IntegerValue", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); // Assert.True(reference.Target.Value!.IsArray); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10326", reference.Target.NodeId); // Assert.Equal("UInteger", reference.Target.DataType); Assert.Equal("UIntegerValue", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); // Assert.True(reference.Target.Value!.IsArray); }, reference => { Assert.Equal(NodeClass.Variable, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10244", reference.Target.NodeId); Assert.Equal("Boolean", reference.Target.DataType); Assert.Equal("SimulationActive", reference.Target.DisplayName); Assert.False(reference.Target.Value.IsNull()); Assert.True(reference.Target.Value!.IsBoolean); }, reference => { Assert.Equal(NodeClass.Method, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10245", reference.Target.NodeId); Assert.Equal("GenerateValues", reference.Target.DisplayName); }, reference => { Assert.Equal(NodeClass.Object, reference.Target.NodeClass); Assert.Equal("http://test.org/UA/Data/#i=10247", reference.Target.NodeId); Assert.Equal("CycleComplete", reference.Target.DisplayName); }); } public async Task NodeBrowseStaticArrayVariablesRawModeTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseFirstRequestModel { NodeId = "http://opcfoundation.org/UA/Boiler/#i=1240", NodeIdsOnly = true }, ct: ct).ConfigureAwait(false); // Assert Assert.Equal("http://opcfoundation.org/UA/Boiler/#i=1240", results.Node.NodeId); Assert.Null(results.Node.DisplayName); Assert.Null(results.Node.Children); Assert.Null(results.Node.EventNotifier); Assert.Null(results.Node.Description); Assert.Null(results.Node.AccessRestrictions); Assert.Null(results.ContinuationToken); Assert.NotNull(results.References); Assert.Contains(results.References, reference => { if (reference.ReferenceTypeId != "i=47") { return false; } Assert.Equal("i=47", reference.ReferenceTypeId); Assert.Equal("http://opcfoundation.org/UA/Boiler/#Boiler+%231", reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Direction); Assert.Equal("http://opcfoundation.org/UA/Boiler/#i=1241", reference.Target.NodeId); Assert.NotNull(reference.Target.NodeClass); Assert.Null(reference.Target.DataType); Assert.Null(reference.Target.Description); Assert.True(reference.Target.Value.IsNull()); Assert.Null(reference.Target.Children); return true; }); Assert.Contains(results.References, reference => { if (reference.ReferenceTypeId != "i=48") { return false; } Assert.Equal("i=48", reference.ReferenceTypeId); Assert.Equal("http://opcfoundation.org/UA/Boiler/#Boiler+%231", reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Direction); Assert.Equal("http://opcfoundation.org/UA/Boiler/#i=1241", reference.Target.NodeId); Assert.NotNull(reference.Target.NodeClass); Assert.Null(reference.Target.DataType); Assert.Null(reference.Target.Description); Assert.True(reference.Target.Value.IsNull()); Assert.Null(reference.Target.Children); return true; }); Assert.Contains(results.References, reference => { if (reference.ReferenceTypeId != "i=35") { return false; } Assert.Equal("i=35", reference.ReferenceTypeId); Assert.Equal("http://opcfoundation.org/UA/Boiler//Instance#Boiler+%232", reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Direction); Assert.Equal("http://opcfoundation.org/UA/Boiler//Instance#i=1", reference.Target.NodeId); Assert.NotNull(reference.Target.NodeClass); Assert.Null(reference.Target.DataType); Assert.Null(reference.Target.Description); Assert.True(reference.Target.Value.IsNull()); Assert.Null(reference.Target.Children); return true; }); } public async Task NodeBrowseContinuationTest1Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseFirstAsync(_connection, new BrowseFirstRequestModel { NodeId = "http://samples.org/UA/memorybuffer/Instance#s=UInt32", MaxReferencesToReturn = 5 }, ct).ConfigureAwait(false); Assert.Null(results.ErrorInfo); Assert.NotNull(results.ContinuationToken); Assert.NotNull(results.References); Assert.Equal(5, results.References.Count); // Act var results2 = await browser.BrowseNextAsync(_connection, new BrowseNextRequestModel { ContinuationToken = results.ContinuationToken }, ct).ConfigureAwait(false); Assert.Null(results2.ErrorInfo); Assert.NotNull(results2.ContinuationToken); Assert.NotNull(results.References); Assert.Equal(5, results2.References.Count); // Act var results3 = await browser.BrowseNextAsync(_connection, new BrowseNextRequestModel { ContinuationToken = results2.ContinuationToken }, ct).ConfigureAwait(false); Assert.Null(results3.ErrorInfo); Assert.NotNull(results3.ContinuationToken); Assert.NotNull(results3.References); Assert.Equal(5, results3.References.Count); // Act var results4 = await browser.BrowseNextAsync(_connection, new BrowseNextRequestModel { ContinuationToken = results3.ContinuationToken }, ct).ConfigureAwait(false); Assert.Null(results4.ErrorInfo); Assert.NotNull(results4.ContinuationToken); Assert.NotNull(results4.References); Assert.Equal(5, results4.References.Count); } public async Task NodeBrowseContinuationTest2Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseFirstAsync(_connection, new BrowseFirstRequestModel { NodeId = "http://samples.org/UA/memorybuffer/Instance#s=UInt32", MaxReferencesToReturn = 200 }, ct).ConfigureAwait(false); Assert.Null(results.ErrorInfo); Assert.NotNull(results.ContinuationToken); Assert.NotNull(results.References); Assert.Equal(200, results.References.Count); // Act var results2 = await browser.BrowseNextAsync(_connection, new BrowseNextRequestModel { ContinuationToken = results.ContinuationToken }, ct).ConfigureAwait(false); Assert.Null(results2.ErrorInfo); Assert.NotNull(results2.ContinuationToken); Assert.NotNull(results.References); Assert.Equal(200, results2.References.Count); } public async Task NodeBrowseContinuationTest3Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseFirstAsync(_connection, new BrowseFirstRequestModel { NodeId = "http://samples.org/UA/memorybuffer/Instance#s=UInt32", MaxReferencesToReturn = 1, NodeIdsOnly = true }, ct).ConfigureAwait(false); Assert.NotNull(results.ContinuationToken); Assert.NotNull(results.References); Assert.Single(results.References); } public async Task NodeBrowseContinuationTest4Async(CancellationToken ct = default) { var browser = _services(); const uint maxCount = 500; // Act var results = await browser.BrowseFirstAsync(_connection, new BrowseFirstRequestModel { NodeId = "http://samples.org/UA/memorybuffer/Instance#s=UInt32", MaxReferencesToReturn = maxCount, Direction = BrowseDirection.Forward, ReadVariableValues = false }, ct).ConfigureAwait(false); Assert.Null(results.ErrorInfo); Assert.NotNull(results.ContinuationToken); Assert.NotNull(results.References); Assert.Equal((int)maxCount, results.References.Count); var continuationToken = results.ContinuationToken; for (var i = 0; i < 50 && continuationToken != null; i++) // Ensure test does not run too long { var results2 = await browser.BrowseNextAsync(_connection, new BrowseNextRequestModel { ContinuationToken = continuationToken }, ct).ConfigureAwait(false); Assert.Null(results2.ErrorInfo); Assert.NotNull(results2.References); Assert.True(results2.References.Count > 0 && results2.References.Count <= maxCount); continuationToken = results2.ContinuationToken; } } public async Task NodeBrowseDiagnosticsNoneTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseFirstRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { Level = DiagnosticsLevel.None } }, NodeId = "http://opcfoundation.org/UA/Boiler/#s=unknown", TargetNodesOnly = true }, ct: ct).ConfigureAwait(false); // Assert Assert.NotNull(results.ErrorInfo); Assert.Null(results.ErrorInfo.NamespaceUri); Assert.Null(results.ErrorInfo.Locale); Assert.Null(results.ErrorInfo.Inner); Assert.Null(results.ErrorInfo.AdditionalInfo); Assert.Null(results.ErrorInfo.ErrorMessage); Assert.NotNull(results.ErrorInfo.SymbolicId); Assert.Equal(Opc.Ua.StatusCodes.BadNodeIdUnknown, results.ErrorInfo.StatusCode); } public async Task NodeBrowseDiagnosticsStatusTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseFirstRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { AuditId = nameof(NodeBrowseDiagnosticsStatusTestAsync), TimeStamp = DateTime.Now, Level = DiagnosticsLevel.Status } }, NodeId = "http://opcfoundation.org/UA/Boiler/#s=unknown", TargetNodesOnly = true }, ct: ct).ConfigureAwait(false); // Assert Assert.NotNull(results.ErrorInfo); Assert.Null(results.ErrorInfo.NamespaceUri); Assert.Equal("en-US", results.ErrorInfo.Locale); Assert.Equal("BadNodeIdUnknown", results.ErrorInfo.ErrorMessage); Assert.Null(results.ErrorInfo.Inner); Assert.Null(results.ErrorInfo.AdditionalInfo); Assert.NotNull(results.ErrorInfo.SymbolicId); Assert.Equal(Opc.Ua.StatusCodes.BadNodeIdUnknown, results.ErrorInfo.StatusCode); } public async Task NodeBrowseDiagnosticsInfoTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseFirstRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { Level = DiagnosticsLevel.Information } }, NodeId = "http://opcfoundation.org/UA/Boiler/#s=unknown", TargetNodesOnly = true }, ct: ct).ConfigureAwait(false); // Assert Assert.NotNull(results.ErrorInfo); Assert.Null(results.ErrorInfo.NamespaceUri); Assert.Equal("en-US", results.ErrorInfo.Locale); Assert.Equal("BadNodeIdUnknown", results.ErrorInfo.ErrorMessage); Assert.Null(results.ErrorInfo.Inner); Assert.Null(results.ErrorInfo.AdditionalInfo); Assert.NotNull(results.ErrorInfo.SymbolicId); Assert.Equal(Opc.Ua.StatusCodes.BadNodeIdUnknown, results.ErrorInfo.StatusCode); } public async Task NodeBrowseDiagnosticsVerboseTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseFirstAsync(_connection, new BrowseFirstRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { Level = DiagnosticsLevel.Verbose } }, NodeId = "http://opcfoundation.org/UA/Boiler/#s=unknown", TargetNodesOnly = true }, ct).ConfigureAwait(false); // Assert Assert.NotNull(results.ErrorInfo); Assert.Null(results.ErrorInfo.NamespaceUri); Assert.Equal("en-US", results.ErrorInfo.Locale); Assert.Equal("BadNodeIdUnknown", results.ErrorInfo.ErrorMessage); Assert.Null(results.ErrorInfo.Inner); Assert.Null(results.ErrorInfo.AdditionalInfo); Assert.NotNull(results.ErrorInfo.SymbolicId); Assert.Equal(Opc.Ua.StatusCodes.BadNodeIdUnknown, results.ErrorInfo.StatusCode); } private readonly T _connection; private readonly IJsonSerializer _serializer; private readonly Func> _services; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/BrowseStreamTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Json; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Xunit; public class BrowseStreamTests { /// /// Create browse tests /// /// /// public BrowseStreamTests(Func> services, T connection) { _services = services; _connection = connection; _serializer = new DefaultJsonSerializer(); } public async Task NodeBrowseInRootTest1Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseStreamRequestModel { NoRecurse = true }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); // Assert Assert.Contains(results, node => { if (node.Attributes?.DisplayName != "Root") { return false; } Assert.NotNull(node.Attributes); Assert.Null(node.Reference); Assert.Equal("i=84", node.SourceId); Assert.Equal("Root", node.Attributes.DisplayName); Assert.Equal("The root of the server address space.", node.Attributes.Description); Assert.Null(node.Attributes.AccessRestrictions); return true; }); Assert.Contains(results, reference => { if (reference.Reference?.Target.DisplayName != "Objects") { return false; } Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("i=84", reference.SourceId); Assert.Equal("i=35", reference.Reference.ReferenceTypeId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("Objects", reference.Reference.Target.BrowseName); Assert.Equal("Objects", reference.Reference.Target.DisplayName); Assert.Equal("i=85", reference.Reference.Target.NodeId); Assert.True(reference.Reference.Target.Value.IsNull()); return true; }); Assert.Contains(results, reference => { if (reference.Reference?.Target.DisplayName != "Types") { return false; } Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("i=84", reference.SourceId); Assert.Equal("i=35", reference.Reference.ReferenceTypeId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("Types", reference.Reference.Target.BrowseName); Assert.Equal("Types", reference.Reference.Target.DisplayName); Assert.Equal("i=86", reference.Reference.Target.NodeId); Assert.True(reference.Reference.Target.Value.IsNull()); return true; }); Assert.Contains(results, reference => { if (reference.Reference?.Target.DisplayName != "Views") { return false; } Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("i=84", reference.SourceId); Assert.Equal("i=35", reference.Reference.ReferenceTypeId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("Views", reference.Reference.Target.BrowseName); Assert.Equal("Views", reference.Reference.Target.DisplayName); Assert.Equal("i=87", reference.Reference.Target.NodeId); Assert.True(reference.Reference.Target.Value.IsNull()); return true; }); } public async Task NodeBrowseInRootTest2Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseStreamRequestModel { NoRecurse = true, Direction = BrowseDirection.Forward, ReadVariableValues = true }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); // Assert Assert.Contains(results, node => { if (node.Attributes?.DisplayName != "Root") { return false; } Assert.NotNull(node.Attributes); Assert.Null(node.Reference); Assert.Equal("i=84", node.SourceId); Assert.Equal("i=84", node.Attributes.NodeId); Assert.Equal("Root", node.Attributes.DisplayName); Assert.Equal("The root of the server address space.", node.Attributes.Description); Assert.Null(node.Attributes.AccessRestrictions); return true; }); Assert.Contains(results, reference => { if (reference.Reference?.Target.DisplayName != "Objects") { return false; } Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("i=84", reference.SourceId); Assert.Equal("i=35", reference.Reference.ReferenceTypeId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("Objects", reference.Reference.Target.BrowseName); Assert.Equal("Objects", reference.Reference.Target.DisplayName); Assert.Equal("i=85", reference.Reference.Target.NodeId); Assert.True(reference.Reference.Target.Value.IsNull()); return true; }); Assert.Contains(results, reference => { if (reference.Reference?.Target.DisplayName != "Types") { return false; } Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("i=84", reference.SourceId); Assert.Equal("i=35", reference.Reference.ReferenceTypeId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("Types", reference.Reference.Target.BrowseName); Assert.Equal("Types", reference.Reference.Target.DisplayName); Assert.Equal("i=86", reference.Reference.Target.NodeId); Assert.True(reference.Reference.Target.Value.IsNull()); return true; }); Assert.Contains(results, reference => { if (reference.Reference?.Target.DisplayName != "Views") { return false; } Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("i=84", reference.SourceId); Assert.Equal("i=35", reference.Reference.ReferenceTypeId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("Views", reference.Reference.Target.BrowseName); Assert.Equal("Views", reference.Reference.Target.DisplayName); Assert.Equal("i=87", reference.Reference.Target.NodeId); Assert.True(reference.Reference.Target.Value.IsNull()); return true; }); } public async Task NodeBrowseBoilersObjectsTest1Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseStreamRequestModel { NodeIds = new[] { "http://opcfoundation.org/UA/Boiler/#i=1240" }, Direction = BrowseDirection.Forward, NoRecurse = true }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); // Assert Assert.Contains(results, node => { if (node.Reference != null) { return false; } Assert.NotNull(node.Attributes); Assert.Null(node.Reference); Assert.Equal("http://opcfoundation.org/UA/Boiler/#i=1240", node.SourceId); Assert.Equal("http://opcfoundation.org/UA/Boiler/#i=1240", node.Attributes.NodeId); Assert.Equal("Boilers", node.Attributes.DisplayName); Assert.Equal(NodeEventNotifier.SubscribeToEvents, node.Attributes.EventNotifier); Assert.Null(node.Attributes.Description); Assert.Null(node.Attributes.AccessRestrictions); return true; }); Assert.Contains(results, reference => { if (reference.Reference?.ReferenceTypeId != "i=47") { return false; } Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://opcfoundation.org/UA/Boiler/#i=1240", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("i=47", reference.Reference.ReferenceTypeId); Assert.Equal("Boiler #1", reference.Reference.Target.DisplayName); Assert.Null(reference.Reference.Target.NodeClass); Assert.Equal("http://opcfoundation.org/UA/Boiler/#i=1241", reference.Reference.Target.NodeId); return true; }); Assert.Contains(results, reference => { if (reference.Reference?.ReferenceTypeId != "i=48") { return false; } Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://opcfoundation.org/UA/Boiler/#i=1240", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("i=48", reference.Reference.ReferenceTypeId); Assert.Equal("Boiler #1", reference.Reference.Target.DisplayName); Assert.Null(reference.Reference.Target.NodeClass); Assert.Equal("http://opcfoundation.org/UA/Boiler/#i=1241", reference.Reference.Target.NodeId); return true; }); Assert.Contains(results, reference => { if (reference.Reference?.ReferenceTypeId != "i=35") { return false; } Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://opcfoundation.org/UA/Boiler/#i=1240", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("i=35", reference.Reference.ReferenceTypeId); Assert.Equal("Boiler #2", reference.Reference.Target.DisplayName); Assert.Null(reference.Reference.Target.NodeClass); Assert.Equal("http://opcfoundation.org/UA/Boiler//Instance#i=1", reference.Reference.Target.NodeId); return true; }); } public async Task NodeBrowseDataAccessObjectsTest1Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseStreamRequestModel { NodeIds = new[] { "nsu=DataAccess;s=0:TestData/Static" }, NoRecurse = true }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); // Assert Assert.Collection(results, node => { Assert.NotNull(node.Attributes); Assert.Null(node.Reference); Assert.Equal("nsu=DataAccess;s=0:TestData/Static", node.SourceId); Assert.Equal("nsu=DataAccess;s=0:TestData/Static", node.Attributes.NodeId); Assert.Equal("Static", node.Attributes.DisplayName); Assert.Equal(NodeClass.Object, node.Attributes.NodeClass); Assert.Null(node.Attributes.EventNotifier); Assert.Null(node.Attributes.Description); Assert.Null(node.Attributes.AccessRestrictions); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("nsu=DataAccess;s=0:TestData/Static", reference.SourceId); Assert.Equal("i=35", reference.Reference.ReferenceTypeId); Assert.Equal("DataAccess#TestData", reference.Reference.Target.BrowseName); Assert.Equal(BrowseDirection.Backward, reference.Reference.Direction); Assert.Equal("TestData", reference.Reference.Target.DisplayName); Assert.Equal("nsu=DataAccess;s=0:TestData", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("nsu=DataAccess;s=0:TestData/Static", reference.SourceId); Assert.Equal("i=35", reference.Reference.ReferenceTypeId); Assert.Equal("DataAccess#FC1001", reference.Reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("FC1001", reference.Reference.Target.DisplayName); Assert.Equal("nsu=DataAccess;s=1:FC1001", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("nsu=DataAccess;s=0:TestData/Static", reference.SourceId); Assert.Equal("i=35", reference.Reference.ReferenceTypeId); Assert.Equal("DataAccess#LC1001", reference.Reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("LC1001", reference.Reference.Target.DisplayName); Assert.Equal("nsu=DataAccess;s=1:LC1001", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("nsu=DataAccess;s=0:TestData/Static", reference.SourceId); Assert.Equal("i=35", reference.Reference.ReferenceTypeId); Assert.Equal("DataAccess#CC1001", reference.Reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("CC1001", reference.Reference.Target.DisplayName); Assert.Equal("nsu=DataAccess;s=1:CC1001", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("nsu=DataAccess;s=0:TestData/Static", reference.SourceId); Assert.Equal("i=35", reference.Reference.ReferenceTypeId); Assert.Equal("DataAccess#FC2001", reference.Reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("FC2001", reference.Reference.Target.DisplayName); Assert.Equal("nsu=DataAccess;s=1:FC2001", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("nsu=DataAccess;s=0:TestData/Static", reference.SourceId); Assert.Equal("i=35", reference.Reference.ReferenceTypeId); Assert.Equal("DataAccess#LC2001", reference.Reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("LC2001", reference.Reference.Target.DisplayName); Assert.Equal("nsu=DataAccess;s=1:LC2001", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("nsu=DataAccess;s=0:TestData/Static", reference.SourceId); Assert.Equal("i=35", reference.Reference.ReferenceTypeId); Assert.Equal("DataAccess#CC2001", reference.Reference.Target.BrowseName); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("CC2001", reference.Reference.Target.DisplayName); Assert.Equal("nsu=DataAccess;s=1:CC2001", reference.Reference.Target.NodeId); }); } public async Task NodeBrowseStaticScalarVariablesTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseStreamRequestModel { NodeIds = new[] { "http://test.org/UA/Data/#i=10159" }, NoRecurse = true }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); // Assert Assert.Collection(results, node => { Assert.NotNull(node.Attributes); Assert.Null(node.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", node.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10159", node.Attributes.NodeId); Assert.Equal("Scalar", node.Attributes.DisplayName); Assert.Equal(NodeClass.Object, node.Attributes.NodeClass); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10216", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10217", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10218", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10219", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10220", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10221", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10222", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10223", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10224", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10225", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10226", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10227", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10228", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10229", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10230", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10231", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10232", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10233", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10234", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10235", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10236", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10237", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10238", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10239", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10240", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10241", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10242", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10160", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10161", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10163", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10163", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Backward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10158", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Backward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10158", reference.Reference.Target.NodeId); }); } public async Task NodeBrowseStaticScalarVariablesTestWithFilter1Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseStreamRequestModel { NodeIds = new[] { "http://test.org/UA/Data/#i=10159" }, NodeClassFilter = new List { NodeClass.Method, NodeClass.Object }, Direction = BrowseDirection.Forward, NoRecurse = true }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); // Assert Assert.Collection(results, node => { Assert.NotNull(node.Attributes); Assert.Null(node.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", node.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10159", node.Attributes.NodeId); Assert.Equal("Scalar", node.Attributes.DisplayName); Assert.Equal(NodeClass.Object, node.Attributes.NodeClass); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10161", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10163", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10163", reference.Reference.Target.NodeId); }); } public async Task NodeBrowseStaticScalarVariablesTestWithFilter2Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseStreamRequestModel { NodeIds = new[] { "http://test.org/UA/Data/#i=10159" }, NodeClassFilter = new List { NodeClass.Method }, Direction = BrowseDirection.Forward, NoRecurse = true }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); // Assert Assert.Collection(results, node => { Assert.NotNull(node.Attributes); Assert.Null(node.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", node.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10159", node.Attributes.NodeId); Assert.Equal("Scalar", node.Attributes.DisplayName); Assert.Equal(NodeClass.Object, node.Attributes.NodeClass); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10161", reference.Reference.Target.NodeId); }); } public async Task NodeBrowseStaticScalarVariablesTestWithFilter3Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseStreamRequestModel { NodeIds = new[] { "http://test.org/UA/Data/#i=10159" }, NodeClassFilter = new List { NodeClass.Method }, Direction = BrowseDirection.Forward }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); // Assert Assert.Collection(results, node => { Assert.NotNull(node.Attributes); Assert.Null(node.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", node.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10159", node.Attributes.NodeId); Assert.Equal("Scalar", node.Attributes.DisplayName); Assert.Equal(NodeClass.Object, node.Attributes.NodeClass); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10161", reference.Reference.Target.NodeId); }, node => { Assert.NotNull(node.Attributes); Assert.Null(node.Reference); Assert.Equal("http://test.org/UA/Data/#i=9385", node.SourceId); Assert.Equal("http://test.org/UA/Data/#i=9385", node.Attributes.NodeId); Assert.Equal("GenerateValues", node.Attributes.DisplayName); Assert.Equal(NodeClass.Method, node.Attributes.NodeClass); }, node => { Assert.NotNull(node.Attributes); Assert.Null(node.Reference); Assert.Equal("i=47", node.SourceId); Assert.Equal("i=47", node.Attributes.NodeId); Assert.Equal("HasComponent", node.Attributes.DisplayName); Assert.Equal(NodeClass.ReferenceType, node.Attributes.NodeClass); }, node => { Assert.NotNull(node.Attributes); Assert.Null(node.Reference); Assert.Equal("http://test.org/UA/Data/#i=10161", node.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10161", node.Attributes.NodeId); Assert.Equal("GenerateValues", node.Attributes.DisplayName); Assert.Equal(NodeClass.Method, node.Attributes.NodeClass); }); } public async Task NodeBrowseStaticScalarVariablesTestWithFilter4Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseStreamRequestModel { NodeIds = new[] { "http://test.org/UA/Data/#i=10159" }, NodeClassFilter = new List { NodeClass.Method }, Direction = BrowseDirection.Both }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); // Assert Assert.Collection(results, node => { Assert.NotNull(node.Attributes); Assert.Null(node.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", node.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10159", node.Attributes.NodeId); Assert.Equal("Scalar", node.Attributes.DisplayName); Assert.Equal(NodeClass.Object, node.Attributes.NodeClass); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10159", reference.SourceId); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10161", reference.Reference.Target.NodeId); }, node => { Assert.NotNull(node.Attributes); Assert.Null(node.Reference); Assert.Equal("http://test.org/UA/Data/#i=9385", node.SourceId); Assert.Equal("http://test.org/UA/Data/#i=9385", node.Attributes.NodeId); Assert.Equal("GenerateValues", node.Attributes.DisplayName); Assert.Equal(NodeClass.Method, node.Attributes.NodeClass); }, node => { Assert.NotNull(node.Attributes); Assert.Null(node.Reference); Assert.Equal("i=47", node.SourceId); Assert.Equal("i=47", node.Attributes.NodeId); Assert.Equal("HasComponent", node.Attributes.DisplayName); Assert.Equal(NodeClass.ReferenceType, node.Attributes.NodeClass); }, node => { Assert.NotNull(node.Attributes); Assert.Null(node.Reference); Assert.Equal("http://test.org/UA/Data/#i=10161", node.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10161", node.Attributes.NodeId); Assert.Equal("GenerateValues", node.Attributes.DisplayName); Assert.Equal(NodeClass.Method, node.Attributes.NodeClass); }); } public async Task NodeBrowseStaticScalarVariablesTestWithFilter5Async(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseStreamRequestModel { NodeIds = new[] { "http://test.org/UA/Data/#i=10159" }, NodeClassFilter = new List { NodeClass.Method, NodeClass.Object } }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); Assert.Equal(2547, results.Count); } public async Task NodeBrowseStaticArrayVariablesTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseStreamRequestModel { NodeIds = new[] { "http://test.org/UA/Data/#i=10243" }, Direction = BrowseDirection.Forward, NoRecurse = true }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); // Assert Assert.Collection(results, node => { Assert.NotNull(node.Attributes); Assert.Null(node.Reference); Assert.Equal("http://test.org/UA/Data/#i=10243", node.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10243", node.Attributes.NodeId); Assert.Equal("Array", node.Attributes.DisplayName); Assert.Equal(NodeClass.Object, node.Attributes.NodeClass); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10300", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10301", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10302", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10303", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10304", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10305", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10306", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10307", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10308", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10309", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10310", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10311", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10312", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10313", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10314", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10315", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10316", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10317", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10318", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10319", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10320", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10321", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10322", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10323", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10324", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10325", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10326", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10244", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10245", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10247", reference.Reference.Target.NodeId); }, reference => { Assert.Null(reference.Attributes); Assert.NotNull(reference.Reference); Assert.Equal(BrowseDirection.Forward, reference.Reference.Direction); Assert.Equal("http://test.org/UA/Data/#i=10243", reference.SourceId); Assert.Equal("http://test.org/UA/Data/#i=10247", reference.Reference.Target.NodeId); }); } public async Task NodeBrowseDiagnosticsNoneTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseStreamRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { Level = DiagnosticsLevel.None } }, NodeIds = new[] { "http://opcfoundation.org/UA/Boiler/#s=unknown" } }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); // Assert var result = Assert.Single(results); Assert.NotNull(result.ErrorInfo); Assert.Null(result.ErrorInfo.NamespaceUri); Assert.Null(result.ErrorInfo.Locale); Assert.Null(result.ErrorInfo.Inner); Assert.Null(result.ErrorInfo.AdditionalInfo); Assert.Null(result.ErrorInfo.ErrorMessage); Assert.NotNull(result.ErrorInfo.SymbolicId); Assert.Equal(Opc.Ua.StatusCodes.BadNodeIdUnknown, result.ErrorInfo.StatusCode); } public async Task NodeBrowseDiagnosticsStatusTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseStreamRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { AuditId = nameof(NodeBrowseDiagnosticsStatusTestAsync), TimeStamp = DateTime.Now, Level = DiagnosticsLevel.Status } }, NodeIds = new[] { "http://opcfoundation.org/UA/Boiler/#s=unknown" } }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); // Assert var result = Assert.Single(results); Assert.NotNull(result.ErrorInfo); Assert.Null(result.ErrorInfo.NamespaceUri); Assert.Equal("en-US", result.ErrorInfo.Locale); Assert.Equal("BadNodeIdUnknown", result.ErrorInfo.ErrorMessage); Assert.Null(result.ErrorInfo.Inner); Assert.Null(result.ErrorInfo.AdditionalInfo); Assert.NotNull(result.ErrorInfo.SymbolicId); Assert.Equal(Opc.Ua.StatusCodes.BadNodeIdUnknown, result.ErrorInfo.StatusCode); } public async Task NodeBrowseDiagnosticsInfoTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseStreamRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { Level = DiagnosticsLevel.Information } }, NodeIds = new[] { "http://opcfoundation.org/UA/Boiler/#s=unknown" } }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); // Assert var result = Assert.Single(results); Assert.NotNull(result.ErrorInfo); Assert.Null(result.ErrorInfo.NamespaceUri); Assert.Equal("en-US", result.ErrorInfo.Locale); Assert.Equal("BadNodeIdUnknown", result.ErrorInfo.ErrorMessage); Assert.Null(result.ErrorInfo.Inner); Assert.Null(result.ErrorInfo.AdditionalInfo); Assert.NotNull(result.ErrorInfo.SymbolicId); Assert.Equal(Opc.Ua.StatusCodes.BadNodeIdUnknown, result.ErrorInfo.StatusCode); } public async Task NodeBrowseDiagnosticsVerboseTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.BrowseAsync(_connection, new BrowseStreamRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { Level = DiagnosticsLevel.Verbose } }, NodeIds = new[] { "http://opcfoundation.org/UA/Boiler/#s=unknown" } }, ct).ToListAsync(cancellationToken: ct).ConfigureAwait(false); // Assert var result = Assert.Single(results); // Assert Assert.NotNull(result.ErrorInfo); Assert.Null(result.ErrorInfo.NamespaceUri); Assert.Equal("en-US", result.ErrorInfo.Locale); Assert.Equal("BadNodeIdUnknown", result.ErrorInfo.ErrorMessage); Assert.Null(result.ErrorInfo.Inner); Assert.Null(result.ErrorInfo.AdditionalInfo); Assert.NotNull(result.ErrorInfo.SymbolicId); Assert.Equal(Opc.Ua.StatusCodes.BadNodeIdUnknown, result.ErrorInfo.StatusCode); } private readonly T _connection; private readonly IJsonSerializer _serializer; private readonly Func> _services; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/CallArrayMethodTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Json; using Opc.Ua.Extensions; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Xunit; public class CallArrayMethodTests { /// /// Create node services tests /// /// /// /// public CallArrayMethodTests(Func> services, T connection, bool newMetadata = false) { _services = services; _connection = connection; _serializer = new DefaultJsonSerializer(); _newMetadata = newMetadata; } public async Task NodeMethodMetadataStaticArrayMethod1TestAsync(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10765"; const string objectId = "http://test.org/UA/Data/#i=10755"; // Act MethodMetadataModel result; if (!_newMetadata) { result = await service.GetMethodMetadataAsync(_connection, new MethodMetadataRequestModel { MethodId = methodId }, ct).ConfigureAwait(false); } else { var metadata = await service.GetMetadataAsync(_connection, new NodeMetadataRequestModel { NodeId = methodId }, ct).ConfigureAwait(false); result = metadata.MethodMetadata!; } // Assert Assert.Equal(objectId, result.ObjectId); Assert.Collection(result.InputArguments!, arg => { Assert.Equal("BooleanIn", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Boolean", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Boolean", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("SByteIn", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("SByte", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("SByte", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("ByteIn", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Byte", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Byte", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("Int16In", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Int16", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Int16", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("UInt16In", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("UInt16", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("UInt16", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("Int32In", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Int32", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Int32", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("UInt32In", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("UInt32", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("UInt32", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("Int64In", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Int64", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Int64", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("UInt64In", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("UInt64", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("UInt64", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("FloatIn", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Float", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Float", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("DoubleIn", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Double", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Double", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }); Assert.Collection(result.OutputArguments!, arg => { Assert.Equal("BooleanOut", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Boolean", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Boolean", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("SByteOut", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("SByte", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("SByte", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("ByteOut", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Byte", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Byte", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("Int16Out", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Int16", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Int16", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("UInt16Out", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("UInt16", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("UInt16", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("Int32Out", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Int32", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Int32", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("UInt32Out", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("UInt32", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("UInt32", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("Int64Out", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Int64", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Int64", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("UInt64Out", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("UInt64", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("UInt64", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("FloatOut", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Float", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Float", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("DoubleOut", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Double", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Double", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }); } public async Task NodeMethodMetadataStaticArrayMethod2TestAsync(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10768"; const string objectId = "http://test.org/UA/Data/#i=10755"; // Act MethodMetadataModel result; if (!_newMetadata) { result = await service.GetMethodMetadataAsync(_connection, new MethodMetadataRequestModel { MethodId = methodId }, ct).ConfigureAwait(false); } else { var metadata = await service.GetMetadataAsync(_connection, new NodeMetadataRequestModel { NodeId = methodId }, ct).ConfigureAwait(false); result = metadata.MethodMetadata!; } // Assert Assert.Equal(objectId, result.ObjectId); Assert.Collection(result.InputArguments!, arg => { Assert.Equal("StringIn", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("String", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("String", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("DateTimeIn", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("DateTime", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("DateTime", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("GuidIn", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Guid", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Guid", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("ByteStringIn", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("ByteString", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("ByteString", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("XmlElementIn", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("XmlElement", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("XmlElement", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("NodeIdIn", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("NodeId", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("NodeId", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("ExpandedNodeIdIn", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("ExpandedNodeId", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("ExpandedNodeId", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("QualifiedNameIn", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("QualifiedName", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("QualifiedName", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("LocalizedTextIn", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("LocalizedText", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("LocalizedText", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("StatusCodeIn", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("StatusCode", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("StatusCode", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }); Assert.Collection(result.OutputArguments!, arg => { Assert.Equal("StringOut", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("String", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("String", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("DateTimeOut", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("DateTime", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("DateTime", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("GuidOut", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Guid", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Guid", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("ByteStringOut", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("ByteString", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("ByteString", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("XmlElementOut", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("XmlElement", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("XmlElement", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("NodeIdOut", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("NodeId", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("NodeId", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("ExpandedNodeIdOut", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("ExpandedNodeId", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("ExpandedNodeId", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("QualifiedNameOut", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("QualifiedName", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("QualifiedName", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("LocalizedTextOut", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("LocalizedText", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("LocalizedText", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("StatusCodeOut", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("StatusCode", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("StatusCode", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }); } public async Task NodeMethodMetadataStaticArrayMethod3TestAsync(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10771"; const string objectId = "http://test.org/UA/Data/#i=10755"; // Act MethodMetadataModel result; if (!_newMetadata) { result = await service.GetMethodMetadataAsync(_connection, new MethodMetadataRequestModel { MethodId = methodId }, ct).ConfigureAwait(false); } else { var metadata = await service.GetMetadataAsync(_connection, new NodeMetadataRequestModel { NodeId = methodId }, ct).ConfigureAwait(false); result = metadata.MethodMetadata!; } // Assert Assert.Equal(objectId, result!.ObjectId); Assert.Collection(result.InputArguments!, arg => { Assert.Equal("VariantIn", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Variant", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("BaseDataType", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("EnumerationIn", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Enumeration", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Enumeration", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("StructureIn", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("ExtensionObject", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Structure", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }); Assert.Collection(result.OutputArguments!, arg => { Assert.Equal("VariantOut", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Variant", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("BaseDataType", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("EnumerationOut", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Enumeration", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Enumeration", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("StructureOut", arg.Name); Assert.Equal(NodeValueRank.OneDimension, arg.ValueRank); Assert.NotNull(arg.ArrayDimensions); Assert.Single(arg.ArrayDimensions); Assert.Equal(0u, arg.ArrayDimensions[0]); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("ExtensionObject", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Structure", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }); } public async Task NodeMethodCallStaticArrayMethod1Test1Async(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10765"; const string objectId = "http://test.org/UA/Data/#i=10755"; var input = new List { new() { DataType = "boolean", Value = _serializer.FromObject( new bool[] { true, false, true, true, false }) }, new() { DataType = "sbyte", Value = _serializer.FromObject( new sbyte[] { 1, 2, 3, 4, 5, -1, -2, -3 }) }, new() { DataType = "ByteString", Value = _serializer.FromObject( Encoding.UTF8.GetBytes("testtesttest")) }, new() { DataType = "Int16", Value = _serializer.FromObject( new short[] { short.MinValue, short.MaxValue, 0, 2 }) }, new() { DataType = "UInt16", Value = _serializer.FromObject( new ushort[] { ushort.MinValue, ushort.MaxValue, 0, 2 }) }, new() { DataType = "int32", Value = _serializer.FromObject( new int[] { int.MinValue, int.MaxValue, 0, 2 }) }, new() { DataType = "uInt32", Value = _serializer.FromObject( new uint[] { uint.MinValue, uint.MaxValue, 0, 2 }) }, new() { DataType = "Int64", Value = _serializer.FromObject( new long[] { long.MinValue, long.MaxValue, 0, 2 }) }, new() { DataType = "uint64", Value = _serializer.FromObject( new ulong[] { ulong.MinValue, ulong.MaxValue, 0, 2 }) }, new() { DataType = "float", Value = _serializer.FromObject( new float[] { float.MinValue, float.MaxValue, 0.0f, 2.0f }) }, new() { DataType = "DOUBLE", Value = _serializer.FromObject( new double[] { double.MinValue, double.MaxValue, 0.0, 2.0 }) } }; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodId = methodId, ObjectId = objectId, Arguments = input }, ct).ConfigureAwait(false); // Assert Assert.Equal(new List { "Boolean", "SByte", "ByteString", "Int16", "UInt16", "Int32", "UInt32", "Int64", "UInt64", "Float", "Double" }, result.Results.Select(arg => arg.DataType)); Assert.Equal(input.Select(arg => arg.Value), result.Results.Select(arg => arg.Value)); Assert.All(result.Results.Where(arg => arg.DataType != "ByteString"), arg => Assert.True(arg.Value!.IsListOfValues)); } public async Task NodeMethodCallStaticArrayMethod1Test2Async(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10765"; const string objectId = "http://test.org/UA/Data/#i=10755"; var input = new List { new() { DataType = "boolean", Value = _serializer.FromObject( new bool[] { true, false, true, true, false }) }, new() { DataType = "sbyte", Value = _serializer.FromObject( new sbyte[] { 1, 2, 3, 4, 5, -1, -2, -3 }) }, new() { DataType = "ByteString", Value = _serializer.FromObject( Encoding.UTF8.GetBytes("testtesttest")) } }; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodId = methodId, ObjectId = objectId, Arguments = input }, ct).ConfigureAwait(false); // Assert Assert.Equal(new List { "Boolean", "SByte", "ByteString", "Int16", "UInt16", "Int32", "UInt32", "Int64", "UInt64", "Float", "Double" }, result.Results.Select(arg => arg.DataType)); Assert.Collection(result.Results, arg => Assert.Equal(input[0].Value, arg.Value), arg => Assert.Equal(input[1].Value, arg.Value), arg => Assert.Equal(input[2].Value, arg.Value), arg => Assert.Empty(arg.Value!.Values), arg => Assert.Empty(arg.Value!.Values), arg => Assert.Empty(arg.Value!.Values), arg => Assert.Empty(arg.Value!.Values), arg => Assert.Empty(arg.Value!.Values), arg => Assert.Empty(arg.Value!.Values), arg => Assert.Empty(arg.Value!.Values), arg => Assert.Empty(arg.Value!.Values)); Assert.All(result.Results.Where(arg => arg.DataType != "ByteString"), arg => Assert.True(arg.Value!.IsListOfValues)); } public async Task NodeMethodCallStaticArrayMethod1Test3Async(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10765"; const string objectId = "http://test.org/UA/Data/#i=10755"; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodId = methodId, ObjectId = objectId }, ct).ConfigureAwait(false); // Assert Assert.Equal(new List { "Boolean", "SByte", "ByteString", "Int16", "UInt16", "Int32", "UInt32", "Int64", "UInt64", "Float", "Double" }, result.Results.Select(arg => arg.DataType)); Assert.All(result.Results.Where(arg => arg.DataType != "ByteString"), arg => Assert.Empty(arg.Value!.Values)); Assert.All(result.Results.Where(arg => arg.DataType != "ByteString"), arg => Assert.True(arg.Value!.IsListOfValues)); } public async Task NodeMethodCallStaticArrayMethod1Test4Async(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10765"; const string objectId = "http://test.org/UA/Data/#i=10755"; var input = new List { new() { DataType = "boolean", Value = _serializer.FromObject( new bool[] { true, false, true, true, false }) }, new() { DataType = "sbyte", Value = _serializer.FromObject( new sbyte[] { 1, 2, 3, 4, 5, -1, -2, -3 }) }, new() { DataType = "byte", Value = _serializer.FromObject( new ushort[] { 0, 1, 2, 3, 4, 5, 6, byte.MaxValue }) }, null, null, null, null, null, null, null, new() { DataType = "DOUBLE", Value = _serializer.FromObject( new double[] { 1234.4567, 23.34, 33 }) } }; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodId = methodId, ObjectId = objectId, Arguments = input }, ct).ConfigureAwait(false); // Assert Assert.Equal(new List { "Boolean", "SByte", "ByteString", "Int16", "UInt16", "Int32", "UInt32", "Int64", "UInt64", "Float", "Double" }, result.Results.Select(arg => arg.DataType)); Assert.Collection(result.Results, arg => Assert.Equal(input[0]!.Value, arg.Value), arg => Assert.Equal(input[1]!.Value, arg.Value), arg => { Assert.Equal(_serializer.FromObject( new byte[] { 0, 1, 2, 3, 4, 5, 6, byte.MaxValue }), arg.Value); }, arg => Assert.Empty(arg.Value!.Values), arg => Assert.Empty(arg.Value!.Values), arg => Assert.Empty(arg.Value!.Values), arg => Assert.Empty(arg.Value!.Values), arg => Assert.Empty(arg.Value!.Values), arg => Assert.Empty(arg.Value!.Values), arg => Assert.Empty(arg.Value!.Values), arg => Assert.Equal(input[10]!.Value, arg.Value)); Assert.All(result.Results.Where(arg => arg.DataType != "ByteString"), arg => Assert.True(arg.Value!.IsListOfValues)); } public async Task NodeMethodCallStaticArrayMethod1Test5Async(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10765"; const string objectId = "http://test.org/UA/Data/#i=10755"; var input = new List { new() { DataType = "boolean", Value = _serializer.FromObject(Array.Empty()) }, new() { DataType = "sbyte", Value = _serializer.FromObject(Array.Empty()) }, new() { DataType = "Byte", Value = _serializer.FromObject("[]") }, new() { DataType = "Int16", Value = _serializer.FromObject(Array.Empty()) }, new() { DataType = "UInt16", Value = _serializer.FromObject(Array.Empty()) }, new() { DataType = "int32", Value = _serializer.FromObject(Array.Empty()) }, new() { DataType = "uInt32", Value = _serializer.FromObject(Array.Empty()) }, new() { DataType = "Int64", Value = _serializer.FromObject(Array.Empty()) }, new() { DataType = "uint64", Value = _serializer.FromObject(Array.Empty()) }, new() { DataType = "float", Value = _serializer.FromObject(Array.Empty()) }, new() { DataType = "DOUBLE", Value = _serializer.FromObject(Array.Empty()) } }; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodId = methodId, ObjectId = objectId, Arguments = input }, ct).ConfigureAwait(false); // Assert Assert.Equal(new List { "Boolean", "SByte", "ByteString", "Int16", "UInt16", "Int32", "UInt32", "Int64", "UInt64", "Float", "Double" }, result.Results.Select(arg => arg.DataType)); Assert.All(result.Results.Where(arg => arg.DataType != "ByteString"), arg => Assert.True(arg.Value!.IsListOfValues)); Assert.Collection(result.Results, arg => Assert.Empty(arg.Value!.Values), arg => Assert.Empty(arg.Value!.Values), arg => Assert.True(arg.Value.IsNull()), arg => Assert.Empty(arg.Value!.Values), arg => Assert.Empty(arg.Value!.Values), arg => Assert.Empty(arg.Value!.Values), arg => Assert.Empty(arg.Value!.Values), arg => Assert.Empty(arg.Value!.Values), arg => Assert.Empty(arg.Value!.Values), arg => Assert.Empty(arg.Value!.Values), arg => Assert.Equal(input[10].Value, arg.Value)); } public async Task NodeMethodCallStaticArrayMethod2Test1Async(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10768"; const string objectId = "http://test.org/UA/Data/#i=10755"; var input = new List { new() { DataType = "String", Value = _serializer.FromObject(new string[] { "!adfasdfsdf!", "!46!", "!asdf!", "!adfasdfsdf!", "sfdgsfdgs", "ÜÖÄ" }) }, new() { DataType = "DateTime", Value = _serializer.FromObject(new DateTime[] { DateTime.UtcNow, DateTime.UtcNow, DateTime.UtcNow, DateTime.UtcNow }) }, new() { DataType = "Guid", Value = _serializer.FromObject(new Guid[] { Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid() }) }, new() { DataType = "ByteString", Value = _serializer.FromObject(new byte[][] { Encoding.UTF8.GetBytes("!adfasdfsdf!"), Encoding.UTF8.GetBytes("!46!"), Encoding.UTF8.GetBytes("!asdf!"), Encoding.UTF8.GetBytes("!adfasdfsdf!"), Encoding.UTF8.GetBytes("sfdgsfdgs"), Encoding.UTF8.GetBytes("ÜÖÄ") }) }, new() { DataType = "XmlElement", Value = _serializer.FromObject(Array.Empty()) }, new() { DataType = "NodeId", Value = _serializer.FromObject(new string[]{ "byte", "http://test.org/#i=23534", "http://muh.test/#s=35645", "http://test.org/test/#i=354" }) }, new() { DataType = "ExpandedNodeId", Value = _serializer.FromObject(new string[] { "byte", "http://test.org/#i=23534", "http://muh.test/#s=35645", "http://test.org/test/#i=354" }) }, new() { DataType = "QualifiedName", Value = _serializer.FromObject(new string[] { "http://test.org/#qn1", "http://test.org/#qn2", "http://test.org/#qn3", "test" }) }, new() { DataType = "LocalizedText", Value = _serializer.FromObject(new object[] { new { Text = "Hällö", Locale = "de" }, new { Text = "Hallo" }, new { Text = "Hello", Locale = "en" } }) }, new() { DataType = "StatusCode", Value = _serializer.FromObject(new object[] { new { Symbol = "BadEndOfStream", Code = 0x80B00000 }, new { Symbol = "BadWaitingForResponse", Code = 0x80B20000 }, new { Symbol = "BadOperationAbandoned", Code = 0x80B30000 } }) } }; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodId = methodId, ObjectId = objectId, Arguments = input }, ct).ConfigureAwait(false); // Assert Assert.Equal(new List { "String", "DateTime", "Guid", "ByteString", "XmlElement", "NodeId", "ExpandedNodeId", "QualifiedName","LocalizedText","StatusCode" }, result.Results.Select(arg => arg.DataType)); Assert.Collection(result.Results, arg => Assert.Equal(input[0].Value, arg.Value), arg => Assert.Equal(input[1].Value, arg.Value), arg => Assert.Equal(input[2].Value, arg.Value), arg => Assert.Equal(input[3].Value, arg.Value), arg => Assert.Equal(input[4].Value, arg.Value), arg => Assert.Equal(input[5].Value, arg.Value), arg => Assert.Equal(input[6].Value, arg.Value), arg => Assert.Equal(input[7].Value, arg.Value), arg => Assert.Equal(input[8].Value, arg.Value), arg => Assert.Equal(input[9].Value, arg.Value)); Assert.All(result.Results, arg => Assert.True(arg.Value!.IsListOfValues)); } public async Task NodeMethodCallStaticArrayMethod2Test2Async(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10768"; const string objectId = "http://test.org/UA/Data/#i=10755"; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodId = methodId, ObjectId = objectId }, ct).ConfigureAwait(false); // Assert Assert.Equal(new List { "String", "DateTime", "Guid", "ByteString", "XmlElement", "NodeId", "ExpandedNodeId", "QualifiedName","LocalizedText","StatusCode" }, result.Results.Select(arg => arg.DataType)); Assert.All(result.Results, arg => Assert.True(arg.Value!.IsListOfValues)); Assert.All(result.Results, arg => Assert.Empty(arg.Value!.Values)); } public async Task NodeMethodCallStaticArrayMethod2Test3Async(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10768"; const string objectId = "http://test.org/UA/Data/#i=10755"; var input = new List { null, null, null, null, null, null, null, null, new() { DataType = "LocalizedText", Value = _serializer.FromObject(new string[] { "unloc1", "unloc2", "unloc3" }) } }; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodId = methodId, ObjectId = objectId, Arguments = input }, ct).ConfigureAwait(false); // Assert Assert.Equal(new List { "String", "DateTime", "Guid", "ByteString", "XmlElement", "NodeId", "ExpandedNodeId", "QualifiedName","LocalizedText","StatusCode" }, result.Results.Select(arg => arg.DataType)); Assert.NotNull(result.Results); Assert.All(result.Results, arg => Assert.True(arg.Value!.IsListOfValues)); Assert.NotNull(result.Results[8].Value); Assert.Equal(3, result.Results[8].Value!.Count); } public async Task NodeMethodCallStaticArrayMethod2Test4Async(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10768"; const string objectId = "http://test.org/UA/Data/#i=10755"; #pragma warning disable CA1814 // Prefer jagged arrays over multidimensional var input = new List { new() { DataType = "String", Value = _serializer.FromObject(Array.Empty()) }, new() { DataType = "DateTime", Value = _serializer.FromObject(Array.Empty()) }, new() { DataType = "Guid", Value = _serializer.FromObject(Array.Empty()) }, new() { DataType = "ByteString", Value = _serializer.FromObject(new byte[0,0]) }, new() { DataType = "XmlElement", Value = _serializer.FromObject(Array.Empty()) }, new() { DataType = "NodeId", Value = _serializer.FromObject(Array.Empty()) }, new() { DataType = "ExpandedNodeId", Value = _serializer.FromObject(Array.Empty()) }, new() { DataType = "QualifiedName", Value = _serializer.FromObject(Array.Empty()) }, new() { DataType = "LocalizedText", Value = _serializer.FromObject(Array.Empty()) }, new() { DataType = "StatusCode", Value = _serializer.FromObject(Array.Empty()) } }; #pragma warning restore CA1814 // Prefer jagged arrays over multidimensional // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodId = methodId, ObjectId = objectId, Arguments = input }, ct).ConfigureAwait(false); // Assert Assert.Equal(new List { "String", "DateTime", "Guid", "ByteString", "XmlElement", "NodeId", "ExpandedNodeId", "QualifiedName", "LocalizedText", "StatusCode" }, result.Results.Select(arg => arg.DataType)); Assert.Equal(input.Select(arg => arg.Value), result.Results.Select(arg => arg.Value)); Assert.All(result.Results, arg => Assert.True(arg.Value!.IsListOfValues)); Assert.All(result.Results, arg => Assert.Empty(arg.Value!.Values)); } public async Task NodeMethodCallStaticArrayMethod3Test1Async(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10771"; const string objectId = "http://test.org/UA/Data/#i=10755"; var input = new List { new() { DataType = "Variant", Value = _serializer.FromArray() }, new() { DataType = "Enumeration", Value = _serializer.FromArray() }, new() { DataType = "ExtensionObject", Value = _serializer.FromArray() } }; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodId = methodId, ObjectId = objectId, Arguments = input }, ct).ConfigureAwait(false); // Assert Assert.Equal(new List { "Variant", "Int32", "ExtensionObject" }, result.Results.Select(arg => arg.DataType)); Assert.Equal(input.Select(arg => arg.Value), result.Results.Select(arg => arg.Value)); Assert.All(result.Results, arg => Assert.True(arg.Value!.IsListOfValues)); } public async Task NodeMethodCallStaticArrayMethod3Test2Async(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10771"; const string objectId = "http://test.org/UA/Data/#i=10755"; var input = new List { new() { Value = _serializer.FromObject(new object[] { new { Type = "UInt32", Body = 500000 }, new { Type = "String", Body = "test" }, new { Type = "Float", Body = 0.3f }, new { Type = "Byte", Body = 50 } }) }, new() { DataType = "int32", Value = _serializer.FromObject(new int[] { 1, 2, 3, 4, 5, 6 }) }, new() { DataType = "ExtensionObject", Value = _serializer.FromObject(new object[] { new { TypeId = "http://test.org/#s=test2", Body = new Opc.Ua.Argument("test1", Opc.Ua.DataTypes.String, -1, "desc1") .AsBinary(Opc.Ua.ServiceMessageContext.GlobalContext) }, new { TypeId = "http://test.org/#s=test55", Encoding = "Xml", Body = new Opc.Ua.Argument("test2", Opc.Ua.DataTypes.String, -2, "desc1") .AsXmlElement(Opc.Ua.ServiceMessageContext.GlobalContext) } }) } }; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodId = methodId, ObjectId = objectId, Arguments = input }, ct).ConfigureAwait(false); // Assert Assert.Equal(new List { "Variant", "Int32", "ExtensionObject" }, result.Results.Select(arg => arg.DataType)); Assert.All(result.Results, arg => Assert.True(arg.Value!.IsListOfValues)); } public async Task NodeMethodCallStaticArrayMethod3Test3Async(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10771"; const string objectId = "http://test.org/UA/Data/#i=10755"; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodId = methodId, ObjectId = objectId }, ct).ConfigureAwait(false); // Assert Assert.Equal(new List { "Variant", "Int32", "ExtensionObject" }, result.Results.Select(arg => arg.DataType)); Assert.All(result.Results, arg => Assert.True(arg.Value!.IsListOfValues)); Assert.All(result.Results, arg => Assert.Empty(arg.Value!.Values)); } private readonly bool _newMetadata; private readonly T _connection; private readonly Func> _services; private readonly DefaultJsonSerializer _serializer; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/CallScalarMethodTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Json; using MemoryBuffer; using Opc.Ua.Extensions; using System; using System.Collections.Generic; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Xml; using Xunit; public class CallScalarMethodTests { /// /// Create node services tests /// /// /// /// public CallScalarMethodTests(Func> services, T connection, bool newMetadata = false) { _services = services; _connection = connection; _serializer = new DefaultJsonSerializer(); _newMetadata = newMetadata; } public async Task NodeMethodMetadataStaticScalarMethod1TestAsync(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10756"; const string objectId = "http://test.org/UA/Data/#i=10755"; // Act MethodMetadataModel result; if (!_newMetadata) { result = await service.GetMethodMetadataAsync(_connection, new MethodMetadataRequestModel { MethodId = methodId }, ct).ConfigureAwait(false); } else { var metadata = await service.GetMetadataAsync(_connection, new NodeMetadataRequestModel { NodeId = methodId }, ct).ConfigureAwait(false); result = metadata.MethodMetadata!; } // Assert Assert.Equal(objectId, result.ObjectId); Assert.Collection(result.InputArguments!, arg => { Assert.Equal("BooleanIn", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Boolean", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Boolean", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("SByteIn", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("SByte", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("SByte", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("ByteIn", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Byte", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Byte", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("Int16In", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Int16", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Int16", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("UInt16In", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("UInt16", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("UInt16", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("Int32In", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Int32", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Int32", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("UInt32In", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("UInt32", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("UInt32", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("Int64In", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Int64", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Int64", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("UInt64In", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("UInt64", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("UInt64", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("FloatIn", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Float", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Float", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("DoubleIn", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Double", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Double", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }); Assert.Collection(result.OutputArguments!, arg => { Assert.Equal("BooleanOut", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Boolean", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Boolean", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("SByteOut", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("SByte", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("SByte", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("ByteOut", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Byte", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Byte", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("Int16Out", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Int16", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Int16", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("UInt16Out", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("UInt16", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("UInt16", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("Int32Out", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Int32", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Int32", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("UInt32Out", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("UInt32", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("UInt32", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("Int64Out", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Int64", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Int64", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("UInt64Out", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("UInt64", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("UInt64", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("FloatOut", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Float", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Float", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("DoubleOut", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Double", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Double", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }); } public async Task NodeMethodMetadataStaticScalarMethod2TestAsync(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10759"; const string objectId = "http://test.org/UA/Data/#i=10755"; // Act MethodMetadataModel result; if (!_newMetadata) { result = await service.GetMethodMetadataAsync(_connection, new MethodMetadataRequestModel { MethodId = methodId }, ct).ConfigureAwait(false); } else { var metadata = await service.GetMetadataAsync(_connection, new NodeMetadataRequestModel { NodeId = methodId }, ct).ConfigureAwait(false); result = metadata.MethodMetadata!; } // Assert Assert.Equal(objectId, result.ObjectId); Assert.Collection(result.InputArguments!, arg => { Assert.Equal("StringIn", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("String", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("String", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("DateTimeIn", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("DateTime", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("DateTime", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("GuidIn", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Guid", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Guid", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("ByteStringIn", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("ByteString", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("ByteString", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("XmlElementIn", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("XmlElement", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("XmlElement", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("NodeIdIn", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("NodeId", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("NodeId", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("ExpandedNodeIdIn", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("ExpandedNodeId", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("ExpandedNodeId", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("QualifiedNameIn", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("QualifiedName", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("QualifiedName", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("LocalizedTextIn", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("LocalizedText", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("LocalizedText", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("StatusCodeIn", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("StatusCode", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("StatusCode", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }); Assert.Collection(result.OutputArguments!, arg => { Assert.Equal("StringOut", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("String", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("String", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("DateTimeOut", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("DateTime", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("DateTime", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("GuidOut", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Guid", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Guid", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("ByteStringOut", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("ByteString", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("ByteString", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("XmlElementOut", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("XmlElement", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("XmlElement", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("NodeIdOut", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("NodeId", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("NodeId", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("ExpandedNodeIdOut", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("ExpandedNodeId", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("ExpandedNodeId", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("QualifiedNameOut", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("QualifiedName", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("QualifiedName", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("LocalizedTextOut", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("LocalizedText", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("LocalizedText", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("StatusCodeOut", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("StatusCode", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("StatusCode", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }); } public async Task NodeMethodMetadataStaticScalarMethod3TestAsync(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10762"; const string objectId = "http://test.org/UA/Data/#i=10755"; // Act MethodMetadataModel result; if (!_newMetadata) { result = await service.GetMethodMetadataAsync(_connection, new MethodMetadataRequestModel { MethodId = methodId }, ct).ConfigureAwait(false); } else { var metadata = await service.GetMetadataAsync(_connection, new NodeMetadataRequestModel { NodeId = methodId }, ct).ConfigureAwait(false); result = metadata.MethodMetadata!; } // Assert Assert.Equal(objectId, result.ObjectId); Assert.Collection(result.InputArguments!, arg => { Assert.Equal("VariantIn", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Variant", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("BaseDataType", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("EnumerationIn", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Enumeration", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Enumeration", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("StructureIn", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("ExtensionObject", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Structure", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }); Assert.Collection(result.OutputArguments!, arg => { Assert.Equal("VariantOut", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Variant", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("BaseDataType", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("EnumerationOut", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Enumeration", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Enumeration", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("StructureOut", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("ExtensionObject", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Structure", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }); } public async Task NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest1Async(CancellationToken ct = default) { var service = _services(); const string objectId = "http://test.org/UA/Data/#i=10755"; var path = new[] { ".http://test.org/UA/Data/#ScalarMethod3" }; // Act MethodMetadataModel result; if (!_newMetadata) { result = await service.GetMethodMetadataAsync(_connection, new MethodMetadataRequestModel { MethodId = objectId, MethodBrowsePath = path }, ct).ConfigureAwait(false); } else { var metadata = await service.GetMetadataAsync(_connection, new NodeMetadataRequestModel { NodeId = objectId, BrowsePath = path }, ct).ConfigureAwait(false); result = metadata.MethodMetadata!; } // Assert Assert.Equal(objectId, result.ObjectId); Assert.Collection(result.InputArguments!, arg => { Assert.Equal("VariantIn", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Variant", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("BaseDataType", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("EnumerationIn", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Enumeration", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Enumeration", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("StructureIn", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("ExtensionObject", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Structure", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }); Assert.Collection(result.OutputArguments!, arg => { Assert.Equal("VariantOut", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Variant", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("BaseDataType", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("EnumerationOut", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Enumeration", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Enumeration", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("StructureOut", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("ExtensionObject", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Structure", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }); } public async Task NodeMethodMetadataStaticScalarMethod3WithBrowsePathTest2Async(CancellationToken ct = default) { var service = _services(); var path = new[] { "Objects", "http://test.org/UA/Data/#Data", "http://test.org/UA/Data/#Static", "http://test.org/UA/Data/#MethodTest", "http://test.org/UA/Data/#ScalarMethod3" }; // Act MethodMetadataModel result; if (!_newMetadata) { result = await service.GetMethodMetadataAsync(_connection, new MethodMetadataRequestModel { MethodBrowsePath = path }, ct).ConfigureAwait(false); } else { var metadata = await service.GetMetadataAsync(_connection, new NodeMetadataRequestModel { BrowsePath = path }, ct).ConfigureAwait(false); result = metadata.MethodMetadata!; } // Assert Assert.Equal("http://test.org/UA/Data/#i=10755", result.ObjectId); Assert.Collection(result.InputArguments!, arg => { Assert.Equal("VariantIn", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Variant", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("BaseDataType", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("EnumerationIn", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Enumeration", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Enumeration", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("StructureIn", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("ExtensionObject", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Structure", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }); Assert.Collection(result.OutputArguments!, arg => { Assert.Equal("VariantOut", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Variant", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("BaseDataType", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("EnumerationOut", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("Enumeration", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Enumeration", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }, arg => { Assert.Equal("StructureOut", arg.Name); Assert.Null(arg.ValueRank); Assert.Equal("[]", _serializer.SerializeToString(arg.ArrayDimensions)); Assert.Equal(NodeClass.DataType, arg.Type.NodeClass); Assert.Equal("ExtensionObject", arg.Type.NodeId); Assert.Null(arg.Type.DataType); Assert.Equal("Structure", arg.Type.DisplayName); Assert.True(arg.DefaultValue.IsNull()); }); } public async Task NodeMethodCallStaticScalarMethod1Test1Async(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10756"; const string objectId = "http://test.org/UA/Data/#i=10755"; var input = new List { new() { DataType = "boolean", Value = true }, new() { DataType = "sbyte", Value = -1 }, new() { DataType = "byte", Value = 244 }, new() { DataType = "Int16", Value = short.MinValue }, new() { DataType = "UInt16", Value = 0 }, new() { DataType = "int32", Value = int.MinValue }, new() { DataType = "uInt32", Value = uint.MaxValue }, new() { DataType = "Int64", Value = -55555 }, new() { DataType = "uint64", Value = 55555 }, new() { DataType = "float", Value = 12.898345f }, new() { DataType = "DOUBLE", Value = 1234.4567 } }; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodId = methodId, ObjectId = objectId, Arguments = input }, ct).ConfigureAwait(false); // Assert Assert.Collection(result.Results, arg => Assert.True((bool)arg.Value!), arg => Assert.Equal((sbyte)input[1]!.Value!, (sbyte)arg.Value!), arg => Assert.Equal((byte)input[2]!.Value!, (byte)arg.Value!), arg => Assert.Equal(short.MinValue, (short)arg.Value!), arg => Assert.Equal((ushort)0, (ushort)arg.Value!), arg => Assert.Equal(int.MinValue, (int)arg.Value!), arg => Assert.Equal(uint.MaxValue, (uint)arg.Value!), arg => Assert.Equal((long)input[7]!.Value!, (long)arg.Value!), arg => Assert.Equal((ulong)input[8]!.Value!, (ulong)arg.Value!), arg => Assert.Equal((float)input[9]!.Value!, (float)arg.Value!), arg => Assert.Equal((double)input[10]!.Value!, (double)arg.Value!)); } public async Task NodeMethodCallStaticScalarMethod1Test2Async(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10756"; const string objectId = "http://test.org/UA/Data/#i=10755"; var input = new List { new() { DataType = "boolean", Value = false }, new() { DataType = "sbyte", Value = -100 }, new() { DataType = "byte", Value = 100 } }; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodId = methodId, ObjectId = objectId, Arguments = input }, ct).ConfigureAwait(false); // Assert Assert.Collection(result.Results, arg => Assert.False((bool)arg.Value!), arg => Assert.Equal((sbyte)input[1]!.Value!, (sbyte)arg.Value!), arg => Assert.Equal((byte)input[2]!.Value!, (byte)arg.Value!), arg => Assert.Equal((short)0, (short)arg.Value!), arg => Assert.Equal((ushort)0, (ushort)arg.Value!), arg => Assert.Equal(0, (int)arg.Value!), arg => Assert.Equal((uint)0, (uint)arg.Value!), arg => Assert.Equal(0, (long)arg.Value!), arg => Assert.Equal((ulong)0, (ulong)arg.Value!), arg => Assert.Equal(0, (float)arg.Value!), arg => Assert.Equal(0, (double)arg.Value!)); } public async Task NodeMethodCallStaticScalarMethod1Test3Async(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10756"; const string objectId = "http://test.org/UA/Data/#i=10755"; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodId = methodId, ObjectId = objectId }, ct).ConfigureAwait(false); // Assert Assert.Collection(result.Results, arg => Assert.False((bool)arg.Value!), arg => Assert.Equal((sbyte)0, (sbyte)arg.Value!), arg => Assert.Equal((byte)0, (byte)arg.Value!), arg => Assert.Equal((short)0, (short)arg.Value!), arg => Assert.Equal((ushort)0, (ushort)arg.Value!), arg => Assert.Equal(0, (int)arg.Value!), arg => Assert.Equal((uint)0, (uint)arg.Value!), arg => Assert.Equal(0, (long)arg.Value!), arg => Assert.Equal((ulong)0, (ulong)arg.Value!), arg => Assert.Equal(0, (float)arg.Value!), arg => Assert.Equal(0, (double)arg.Value!)); } public async Task NodeMethodCallStaticScalarMethod1Test4Async(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10756"; const string objectId = "http://test.org/UA/Data/#i=10755"; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodId = methodId, ObjectId = objectId, Arguments = new List() }, ct).ConfigureAwait(false); // Assert Assert.Collection(result.Results, arg => Assert.False((bool)arg.Value!), arg => Assert.Equal((sbyte)0, (sbyte)arg.Value!), arg => Assert.Equal((byte)0, (byte)arg.Value!), arg => Assert.Equal((short)0, (short)arg.Value!), arg => Assert.Equal((ushort)0, (ushort)arg.Value!), arg => Assert.Equal(0, (int)arg.Value!), arg => Assert.Equal((uint)0, (uint)arg.Value!), arg => Assert.Equal(0, (long)arg.Value!), arg => Assert.Equal((ulong)0, (ulong)arg.Value!), arg => Assert.Equal(0, (float)arg.Value!), arg => Assert.Equal(0, (double)arg.Value!)); } public async Task NodeMethodCallStaticScalarMethod1Test5Async(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10756"; const string objectId = "http://test.org/UA/Data/#i=10755"; var input = new List { new() { DataType = "boolean", Value = true }, new() { DataType = "sbyte", Value = -1 }, new() { DataType = "byte", Value = 244 }, null, null, null, null, null, null, null, new() { DataType = "DOUBLE", Value = 1234.4567 } }; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodId = methodId, ObjectId = objectId, Arguments = input }, ct).ConfigureAwait(false); // Assert Assert.Collection(result.Results, arg => Assert.True((bool)arg.Value!), arg => Assert.Equal((sbyte)input[1]!.Value!, (sbyte)arg.Value!), arg => Assert.Equal((byte)input[2]!.Value!, (byte)arg.Value!), arg => Assert.Equal((short)0, (short)arg.Value!), arg => Assert.Equal((ushort)0, (ushort)arg.Value!), arg => Assert.Equal(0, (int)arg.Value!), arg => Assert.Equal((uint)0, (uint)arg.Value!), arg => Assert.Equal(0, (long)arg.Value!), arg => Assert.Equal((ulong)0, (ulong)arg.Value!), arg => Assert.Equal(0, (float)arg.Value!), arg => Assert.Equal((double)input[10]!.Value!, (double)arg.Value!)); } public async Task NodeMethodCallStaticScalarMethod2Test1Async(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10759"; const string objectId = "http://test.org/UA/Data/#i=10755"; var input = new List { new() { DataType = "String", Value = "test" }, new() { DataType = "DateTime", Value = DateTime.UtcNow }, new() { DataType = "Guid", Value = Guid.NewGuid().ToString() }, new() { DataType = "ByteString", Value = Encoding.UTF32.GetBytes("asdfasdfadsfs") }, new() { DataType = "XmlElement", Value = _serializer.FromObject(XmlElementEx.SerializeObject( new MemoryBufferInstance{ Name = "test", TagCount = 333, DataType ="Byte" })) }, new() { DataType = "NodeId", Value = "http://test.org/#i=44" }, new() { DataType = "ExpandedNodeId", Value = "http://test.org/#i=45" }, new() { DataType = "QualifiedName", Value = "http://test.org/#name" }, new() { DataType = "LocalizedText", Value = _serializer.FromObject(new { Locale = "de", Text = "Hallo Welt" }) }, new() { DataType = "StatusCode", Value = 8888888 } }; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodId = methodId, ObjectId = objectId, Arguments = input }, ct).ConfigureAwait(false); // Assert Assert.Collection(result.Results, arg => { Assert.Equal(input[0].Value, arg.Value); Assert.Equal(input[0].DataType, arg.DataType); }, arg => { Assert.Equal(input[1].Value, arg.Value); Assert.Equal(input[1].DataType, arg.DataType); }, arg => { Assert.Equal(input[2].Value, arg.Value); Assert.Equal(input[2].DataType, arg.DataType); }, arg => { Assert.Equal(input[3].Value, arg.Value); Assert.Equal(input[3].DataType, arg.DataType); }, arg => { Assert.Equal(input[4].Value, arg.Value); Assert.Equal(input[4].DataType, arg.DataType); }, arg => { Assert.Equal(input[5].Value, arg.Value); Assert.Equal(input[5].DataType, arg.DataType); }, arg => { Assert.Equal(input[6].Value, arg.Value); Assert.Equal(input[6].DataType, arg.DataType); }, arg => { Assert.Equal(input[7].Value, arg.Value); Assert.Equal(input[7].DataType, arg.DataType); }, arg => { Assert.True(VariantValue.DeepEquals(input[8].Value, arg.Value), $"Expected: {input[8].Value} != Actual: {arg.Value}"); Assert.Equal(input[8].DataType, arg.DataType); }, arg => { Assert.Equal(8888888, (int)arg.Value!); Assert.Equal(input[9].DataType, arg.DataType); }); } public async Task NodeMethodCallStaticScalarMethod2Test2Async(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10759"; const string objectId = "http://test.org/UA/Data/#i=10755"; var types = new List { "String", "DateTime", "Guid", "ByteString", "XmlElement", "NodeId", "ExpandedNodeId", "QualifiedName","LocalizedText","StatusCode" }; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodId = methodId, ObjectId = objectId }, ct).ConfigureAwait(false); // Assert Assert.Collection(result.Results, arg => { Assert.True(arg.Value.IsNull()); Assert.Equal(types[0], arg.DataType); }, arg => { Assert.True(arg.Value.IsNull()); Assert.Equal(types[1], arg.DataType); }, arg => { Assert.True(arg.Value.IsNull()); Assert.Equal(types[2], arg.DataType); }, arg => { Assert.True(arg.Value.IsNull()); Assert.Equal(types[3], arg.DataType); }, arg => { Assert.True(arg.Value.IsNull()); Assert.Equal(types[4], arg.DataType); }, arg => { Assert.True(arg.Value.IsNull()); Assert.Equal(types[5], arg.DataType); }, arg => { Assert.True(arg.Value.IsNull()); Assert.Equal(types[6], arg.DataType); }, arg => { Assert.True(arg.Value.IsNull()); Assert.Equal(types[7], arg.DataType); }, arg => { Assert.True(arg.Value.IsNull()); Assert.Equal(types[8], arg.DataType); }, arg => { Assert.True(arg.Value.IsNull()); Assert.Equal(types[9], arg.DataType); }); } public async Task NodeMethodCallStaticScalarMethod3Test1Async(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10762"; const string objectId = "http://test.org/UA/Data/#i=10755"; var input = new List { new() { DataType = "Variant", Value = _serializer.FromObject(new { Type = "Uint32", Body = 50 }) }, new() { DataType = "Enumeration", Value = 8 }, new() { DataType = "ExtensionObject", Value = _serializer.FromObject(new { Encoding = "Xml", TypeId = "http://test.org/#s=test", Body = new Opc.Ua.Argument("test", Opc.Ua.DataTypes.String, -1, "desc") .AsXmlElement(Opc.Ua.ServiceMessageContext.GlobalContext) }) } }; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodId = methodId, ObjectId = objectId, Arguments = input }, ct).ConfigureAwait(false); // Assert Assert.Collection(result.Results, arg => Assert.Equal(50u, (uint)arg.Value!), arg => Assert.Equal(8, (int)arg.Value!), arg => { Assert.True(VariantValue.DeepEquals(input[2].Value, arg.Value), $"Expected: {input[2].Value} != Actual: {arg.Value}"); }); } public async Task NodeMethodCallStaticScalarMethod3Test2Async(CancellationToken ct = default) { var service = _services(); const string methodId = "http://test.org/UA/Data/#i=10762"; const string objectId = "http://test.org/UA/Data/#i=10755"; var input = new List { new() { DataType = "String", Value = "varianttest" }, new() { DataType = "int32", Value = 9999 }, new() { DataType = "ExtensionObject", Value = _serializer.FromObject(new { TypeId = "http://test.org/#s=test2", Body = new Opc.Ua.Argument("test1", Opc.Ua.DataTypes.String, -1, "desc1") .AsBinary(Opc.Ua.ServiceMessageContext.GlobalContext) }) } }; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodId = methodId, ObjectId = objectId, Arguments = input }, ct).ConfigureAwait(false); // Assert Assert.Collection(result.Results, arg => Assert.Equal("varianttest", (string)arg.Value!), arg => Assert.Equal(9999, (int)arg.Value!), arg => Assert.Equal(input[2].Value, arg.Value)); } public async Task NodeMethodCallStaticScalarMethod3WithBrowsePathNoIdsTestAsync(CancellationToken ct = default) { var service = _services(); var objectPath = new[] { "Objects", "http://test.org/UA/Data/#Data", "http://test.org/UA/Data/#Static", "http://test.org/UA/Data/#MethodTest" }; var methodPath = new[] { "http://test.org/UA/Data/#ScalarMethod3" }; var input = new List { new() { DataType = "Variant", Value = _serializer.FromObject(new { Type = "Uint32", Body = 50 }) }, new() { DataType = "Enumeration", Value = 8 }, new() { DataType = "ExtensionObject", Value = _serializer.FromObject(new { Encoding = "Xml", TypeId = "http://test.org/#s=test", Body = new Opc.Ua.Argument("test", Opc.Ua.DataTypes.String, -1, "desc") .AsXmlElement(Opc.Ua.ServiceMessageContext.GlobalContext) }) } }; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodBrowsePath = methodPath, ObjectBrowsePath = objectPath, Arguments = input }, ct).ConfigureAwait(false); // Assert Assert.Collection(result.Results, arg => Assert.Equal(50u, (uint)arg.Value!), arg => Assert.Equal(8, (int)arg.Value!), arg => { Assert.True(VariantValue.DeepEquals(input[2].Value, arg.Value), $"Expected: {input[2].Value} != Actual: {arg.Value}"); }); } public async Task NodeMethodCallStaticScalarMethod3WithObjectIdAndBrowsePathTestAsync(CancellationToken ct = default) { var service = _services(); const string objectId = "http://test.org/UA/Data/#i=10755"; var methodPath = new[] { "http://test.org/UA/Data/#ScalarMethod3" }; var input = new List { new() { DataType = "Variant", Value = _serializer.FromObject(new { Type = "Uint32", Body = 50 }) }, new() { DataType = "Enumeration", Value = 8 }, new() { DataType = "ExtensionObject", Value = _serializer.FromObject(new { Encoding = "Xml", TypeId = "http://test.org/#s=test", Body = new Opc.Ua.Argument("test", Opc.Ua.DataTypes.String, -1, "desc") .AsXmlElement(Opc.Ua.ServiceMessageContext.GlobalContext) }) } }; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodBrowsePath = methodPath, ObjectId = objectId, Arguments = input }, ct).ConfigureAwait(false); // Assert Assert.Collection(result.Results, arg => Assert.Equal(50u, (uint)arg.Value!), arg => Assert.Equal(8, (int)arg.Value!), arg => { Assert.True(VariantValue.DeepEquals(input[2].Value, arg.Value), $"Expected: {input[2].Value} != Actual: {arg.Value}"); }); } public async Task NodeMethodCallStaticScalarMethod3WithObjectIdAndMethodIdAndBrowsePathTestAsync(CancellationToken ct = default) { var service = _services(); const string objectId = "http://test.org/UA/Data/#i=10755"; const string methodId = "http://test.org/UA/Data/#i=10157"; // Data var methodPath = new[] { "http://test.org/UA/Data/#Static", "http://test.org/UA/Data/#MethodTest", "http://test.org/UA/Data/#ScalarMethod3" }; var input = new List { new() { DataType = "Variant", Value = _serializer.FromObject(new { Type = "Uint32", Body = 50 }) }, new() { DataType = "Enumeration", Value = 8 }, new() { DataType = "ExtensionObject", Value = _serializer.FromObject(new { Encoding = "Xml", TypeId = "http://test.org/#s=test", Body = new Opc.Ua.Argument("test", Opc.Ua.DataTypes.String, -1, "desc") .AsXmlElement(Opc.Ua.ServiceMessageContext.GlobalContext) }) } }; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodBrowsePath = methodPath, ObjectId = objectId, MethodId = methodId, Arguments = input }, ct).ConfigureAwait(false); // Assert Assert.Collection(result.Results, arg => Assert.Equal(50u, (uint)arg.Value!), arg => Assert.Equal(8, (int)arg.Value!), arg => { Assert.True(VariantValue.DeepEquals(input[2].Value, arg.Value), $"Expected: {input[2].Value} != Actual: {arg.Value}"); }); } public async Task NodeMethodCallStaticScalarMethod3WithObjectPathAndMethodIdAndBrowsePathTestAsync(CancellationToken ct = default) { var service = _services(); var objectPath = new[] { "Objects", "http://test.org/UA/Data/#Data", "http://test.org/UA/Data/#Static", "http://test.org/UA/Data/#MethodTest" }; const string methodId = "http://test.org/UA/Data/#i=10157"; // Data var methodPath = new[] { "http://test.org/UA/Data/#Static", "http://test.org/UA/Data/#MethodTest", "http://test.org/UA/Data/#ScalarMethod3" }; var input = new List { new() { DataType = "Variant", Value = _serializer.FromObject(new { Type = "Uint32", Body = 50 }) }, new() { DataType = "Enumeration", Value = 8 }, new() { DataType = "ExtensionObject", Value = _serializer.FromObject(new { Encoding = "Xml", TypeId = "http://test.org/#s=test", Body = new Opc.Ua.Argument("test", Opc.Ua.DataTypes.String, -1, "desc") .AsXmlElement(Opc.Ua.ServiceMessageContext.GlobalContext) }) } }; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodBrowsePath = methodPath, ObjectBrowsePath = objectPath, MethodId = methodId, Arguments = input }, ct).ConfigureAwait(false); // Assert Assert.Collection(result.Results, arg => Assert.Equal(50u, (uint)arg.Value!), arg => Assert.Equal(8, (int)arg.Value!), arg => { Assert.True(VariantValue.DeepEquals(input[2].Value, arg.Value), $"Expected: {input[2].Value} != Actual: {arg.Value}"); }); } public async Task NodeMethodCallStaticScalarMethod3WithObjectIdAndPathAndMethodIdAndPathTestAsync(CancellationToken ct = default) { var service = _services(); const string objectId = "http://test.org/UA/Data/#i=10157"; // Data var objectPath = new[] { "http://test.org/UA/Data/#Static", "http://test.org/UA/Data/#MethodTest" }; const string methodId = "http://test.org/UA/Data/#i=10157"; // Data var methodPath = new[] { "http://test.org/UA/Data/#Static", "http://test.org/UA/Data/#MethodTest", "http://test.org/UA/Data/#ScalarMethod3" }; var input = new List { new() { DataType = "Variant", Value = _serializer.FromObject(new { Type = "Uint32", Body = 50 }) }, new() { DataType = "Enumeration", Value = 8 }, new() { DataType = "ExtensionObject", Value = _serializer.FromObject(new { Encoding = "Xml", TypeId = "http://test.org/#s=test", Body = new Opc.Ua.Argument("test", Opc.Ua.DataTypes.String, -1, "desc") .AsXmlElement(Opc.Ua.ServiceMessageContext.GlobalContext) }) } }; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodBrowsePath = methodPath, ObjectBrowsePath = objectPath, MethodId = methodId, ObjectId = objectId, Arguments = input }, ct).ConfigureAwait(false); // Assert Assert.Collection(result.Results, arg => Assert.Equal(50u, (uint)arg.Value!), arg => Assert.Equal(8, (int)arg.Value!), arg => { Assert.True(VariantValue.DeepEquals(input[2].Value, arg.Value), $"Expected: {input[2].Value} != Actual: {arg.Value}"); }); } public async Task NodeMethodCallBoiler2ResetTestAsync(CancellationToken ct = default) { var service = _services(); const string methodId = "ns=4;i=37"; const string objectId = "ns=4;i=31"; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodId = methodId, ObjectId = objectId }, ct).ConfigureAwait(false); // Assert Assert.Empty(result.Results); Assert.Null(result.ErrorInfo); } public async Task NodeMethodCallBoiler1ResetTestAsync(CancellationToken ct = default) { var service = _services(); const string methodId = "http://opcfoundation.org/UA/Boiler/#i=15022"; const string objectId = "http://opcfoundation.org/UA/Boiler/#i=1287"; // Act var result = await service.MethodCallAsync(_connection, new MethodCallRequestModel { MethodId = methodId, ObjectId = objectId, Arguments = new List() }, ct).ConfigureAwait(false); // Assert Assert.Empty(result.Results); Assert.Null(result.ErrorInfo); } private readonly bool _newMetadata; private readonly T _connection; private readonly Func> _services; private readonly DefaultJsonSerializer _serializer; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/ConfigurationTests1.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Config.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Exceptions; using Opc.Ua; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Xunit; public class ConfigurationTests1 { /// /// Create configuration tests /// /// /// public ConfigurationTests1(IConfigurationServices services, ConnectionModel connection) { _service = services; _connection = connection; } public async Task ExpandObjectWithBrowsePathTest1Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10157", BrowsePath = new[] { "http://test.org/UA/Data/#Static" } } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(12, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); } public async Task ExpandObjectWithBrowsePathTest2Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10157", BrowsePath = new[] { "http://test.org/UA/Data/#Static" } } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, CreateSingleWriter = true }, ct).ToListAsync(ct).ConfigureAwait(false); var result = Assert.Single(results); Assert.Null(result.ErrorInfo); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); Assert.Equal(300, result.Result.OpcNodes.Count); Assert.All(result.Result.OpcNodes, result => { Assert.NotNull(result.DataSetFieldId); Assert.NotNull(result.Id); }); } public async Task ExpandObjectTest1Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10157" } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = true, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(25, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); } public async Task ExpandObjectTest2Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10157" } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = true, NoSubTypesOfTypeNodes = false, CreateSingleWriter = true }, ct).ToListAsync(ct).ConfigureAwait(false); var result = Assert.Single(results); Assert.Null(result.ErrorInfo); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); Assert.Equal(623, result.Result.OpcNodes.Count); } public async Task ExpandServerObjectTest1Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Opc.Ua.ObjectIds.Server.ToString() } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = true, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(77, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); } public async Task ExpandServerObjectTest2Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Opc.Ua.ObjectIds.Server.ToString() } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(78, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); } public async Task ExpandServerObjectTest3Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Opc.Ua.ObjectIds.Server.ToString() } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, CreateSingleWriter = true }, ct).ToListAsync(ct).ConfigureAwait(false); var result = Assert.Single(results); Assert.Null(result.ErrorInfo); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); Assert.Equal(940, result.Result.OpcNodes.Count); } public async Task ExpandServerObjectTest4Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Opc.Ua.ObjectIds.Server.ToString() } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, MaxDepth = 1, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(9, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); } public async Task ExpandServerObjectTest5Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Opc.Ua.ObjectIds.Server.ToString() } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, MaxDepth = 0, MaxLevelsToExpand = 1, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); var result = Assert.Single(results); Assert.Null(result.ErrorInfo); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); Assert.Equal(7, result.Result.OpcNodes.Count); } public async Task ExpandBaseObjectTypeTest1Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Opc.Ua.ObjectTypeIds.BaseObjectType.ToString() } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, FlattenTypeInstance = false, MaxLevelsToExpand = 1, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(81, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); } public async Task ExpandBaseObjectTypeTest2Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Opc.Ua.ObjectTypeIds.BaseObjectType.ToString() } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, FlattenTypeInstance = true, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(5, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); } public async Task ExpandBaseObjectsAndObjectTypesTestAsync(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Opc.Ua.ObjectTypeIds.BaseObjectType.ToString(), DataSetFieldId = "type" }, new OpcNodeModel { Id = Opc.Ua.ObjectIds.Server.ToString(), DataSetFieldId = "object" }, new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10157", DataSetFieldId = "data" } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, FlattenTypeInstance = false, NoSubTypesOfTypeNodes = false, MaxLevelsToExpand = 1, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(184, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); } public async Task ExpandServerTypeTestAsync(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Opc.Ua.ObjectTypeIds.ServerType.ToString() } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, FlattenTypeInstance = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(32, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); } public async Task ExpandServerTypeWithMethodsTestAsync(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Opc.Ua.ObjectTypeIds.ServerType.ToString() } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, IncludeMethods = true, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, FlattenTypeInstance = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(36, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); var methods = results .SelectMany(r => r.Result!.OpcNodes!).Where(n => n.MethodMetadata != null) .ToList(); Assert.Equal(108, methods.Count); Assert.All(methods, m => { Assert.NotNull(m.MethodMetadata?.InputArguments); Assert.NotNull(m.MethodMetadata?.OutputArguments); Assert.NotNull(m.MethodMetadata?.ObjectId); }); } public async Task ExpandPublishSubscribeTestAsync(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Opc.Ua.ObjectTypeIds.PublishSubscribeType.ToString() } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, FlattenTypeInstance = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(7, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); } public async Task ExpandTestDataObjectTypeTestAsync(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = TestData.ObjectTypeIds.TestDataObjectType.ToString() } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, FlattenTypeInstance = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(24, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); } public async Task ExpandBoilerTypeTestAsync(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Boiler.ObjectTypeIds.BoilerType.ToString() } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, FlattenTypeInstance = false, CreateSingleWriter = false, UseBrowseNameAsDisplayName = true }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(16, results.Count); var groups = results.GroupBy(r => r.Result?.DataSetWriterGroup); Assert.Equal(2, groups.Count()); Assert.All(groups, g => { Assert.Equal(8, g.Count()); Assert.Contains(g.Key, new HashSet { "Boiler #1", "Boiler #2" }); }); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); } public async Task ExpandBoilerDrumTypeTestAsync(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Boiler.ObjectTypeIds.BoilerDrumType.ToString() } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, FlattenTypeInstance = false, CreateSingleWriter = false, UseBrowseNameAsDisplayName = true }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(2, results.Count); var groups = results.GroupBy(r => r.Result?.DataSetWriterGroup); Assert.Equal(2, groups.Count()); Assert.All(groups, g => { Assert.Single(g); Assert.Contains(g.Key, new HashSet { "Boiler #1", "Boiler #2" }); }); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); } public async Task ExpandValveTypeTestAsync(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Boiler.ObjectTypeIds.ValveType.ToString() } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, FlattenTypeInstance = false, CreateSingleWriter = false, UseBrowseNameAsDisplayName = true }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(2, results.Count); var groups = results.GroupBy(r => (r.Result?.DataSetWriterGroup, r.Result?.WriterGroupRootNodeId)); Assert.Equal(2, groups.Count()); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); } public async Task ExpandBoilerDrumAndValveTypeTestAsync(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Boiler.ObjectTypeIds.BoilerDrumType.ToString() }, new OpcNodeModel { Id = Boiler.ObjectTypeIds.ValveType.ToString() } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, FlattenTypeInstance = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(4, results.Count); var groups = results.GroupBy(r => (r.Result?.DataSetWriterGroup, r.Result?.WriterGroupRootNodeId)); Assert.Equal(4, groups.Count()); // 2 drum, 2 valve Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); } public async Task ExpandVariablesTest1Async(CancellationToken ct = default) { // Test only variables as node ids in an entry var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10216" }, new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10217" }, new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10218" } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); var result = Assert.Single(results); Assert.Null(result.ErrorInfo); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); Assert.Equal(6, result.Result.OpcNodes.Count); } public async Task ExpandVariablesAndObjectsTest1Async(CancellationToken ct = default) { // Test mixing variables and objects in an entry to expand var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10217" }, new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10216" }, new OpcNodeModel { Id = Opc.Ua.ObjectIds.Server.ToString() }, new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10218" }, new OpcNodeModel { Id = Opc.Ua.ObjectTypeIds.BaseObjectType.ToString() } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, FlattenTypeInstance = false, MaxLevelsToExpand = 1, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(162, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); } public async Task ExpandVariableTypesTest1Async(CancellationToken ct = default) { // Test only variable types as node ids in an entry var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Opc.Ua.VariableTypeIds.PropertyType.ToString() } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); var result = Assert.Single(results); Assert.Null(result.ErrorInfo); Assert.NotNull(result.Result); Assert.Equal(Opc.Ua.VariableTypeIds.PropertyType + "/PropertyType", result.Result.DataSetWriterId); Assert.NotNull(result.Result.OpcNodes); Assert.Equal(697, result.Result.OpcNodes.Count); } public async Task ExpandVariableTypesTest2Async(CancellationToken ct = default) { // Test only variable types as node ids in an entry var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Opc.Ua.VariableTypeIds.DataItemType.ToString() } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false, UseBrowseNameAsDisplayName = true }, ct).ToListAsync(ct).ConfigureAwait(false); var result = Assert.Single(results); Assert.Null(result.ErrorInfo); Assert.NotNull(result.Result); Assert.Equal(Opc.Ua.VariableTypeIds.DataItemType + "/DataItemType", result.Result.DataSetWriterId); Assert.NotNull(result.Result.OpcNodes); Assert.Equal(96, result.Result.OpcNodes.Count); } public async Task ExpandVariableTypesTest3Async(CancellationToken ct = default) { // Test only variable types as node ids in an entry var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Opc.Ua.VariableTypeIds.PropertyType.ToString() }, new OpcNodeModel { Id = Opc.Ua.VariableTypeIds.DataItemType.ToString() } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(2, results.Count); var total = 0; Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); total += r.Result.OpcNodes.Count; }); Assert.Equal(793, total); } public async Task ExpandObjectWithNoObjectsTest1Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10791" } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = true, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); // An object node that has no objects and is excluded should result // in a service result model with "No objects resolved" var result = Assert.Single(results); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); Assert.Equal("http://test.org/UA/Data/#i=10791", Assert.Single(result.Result.OpcNodes).Id); Assert.NotNull(result.ErrorInfo); Assert.Equal("No objects resolved.", result.ErrorInfo.ErrorMessage); Assert.Equal(StatusCodes.BadNotFound, result.ErrorInfo.StatusCode); } public async Task ExpandObjectWithNoObjectsTest2Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10791" } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = true, ExcludeRootIfInstanceNode = true, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); // Discard errors -> no errors Assert.Empty(results); } public async Task ExpandEmptyEntryTest1Async(CancellationToken ct = default) { // Nothing should be returned when an empty entry passed var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = Array.Empty(); var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = true, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Empty(results); } public async Task ExpandEmptyEntryTest2Async(CancellationToken ct = default) { // Nothing should be returned when an empty entry passed var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = Array.Empty(); var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = true, NoSubTypesOfTypeNodes = false, CreateSingleWriter = true }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Empty(results); } public async Task ExpandBadNodeIdTest1Async(CancellationToken ct = default) { // Entry with bad node id should return error var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = "s=bad" } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = true, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); var result = Assert.Single(results); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); Assert.Equal("s=bad", Assert.Single(result.Result.OpcNodes).Id); Assert.NotNull(result.ErrorInfo); Assert.Equal(StatusCodes.BadNodeIdUnknown, result.ErrorInfo.StatusCode); } public async Task ExpandBadNodeIdTest2Async(CancellationToken ct = default) { // An entry with multiple nodes and duplicate field ids should return an error var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10157", DataSetFieldId = "test" }, new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10158", DataSetFieldId = "test" } }; var ex = await Assert.ThrowsAnyAsync(async () => await _service.ExpandAsync( entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = true, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false)).ConfigureAwait(false); Assert.True(ex is MethodCallStatusException or BadRequestException); } public async Task ExpandBadNodeIdTest3Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); // Method or view node id passed results in not supported error. entry.OpcNodes = new[] { new OpcNodeModel { Id = MethodIds.Server_GetMonitoredItems.ToString() } }; var results = await _service.ExpandAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); var result = Assert.Single(results); Assert.NotNull(result.ErrorInfo); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); Assert.Equal(MethodIds.Server_GetMonitoredItems.ToString(), Assert.Single(result.Result.OpcNodes).Id); Assert.Equal(StatusCodes.BadNotSupported, result.ErrorInfo.StatusCode); } // // 7. Object and maxdepth 0 -> max depth 1 // 7b.Object and stop first found -> organizes is used // 8. Object type with stop first found set uses organizes // private readonly ConnectionModel _connection; private readonly IConfigurationServices _service; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/ConfigurationTests2.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Config.Models; using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Exceptions; using Moq; using Moq.Language.Flow; using Opc.Ua; using System; using System.Linq; using System.Threading; using System.Threading.Tasks; using Xunit; public class ConfigurationTests2 { /// /// Create configuration tests /// /// /// public ConfigurationTests2(Func services, ConnectionModel connection) { _service = services; _connection = connection; _publishedNodesServices = new Mock(); _createCall = _publishedNodesServices.Setup(s => s.CreateOrUpdateDataSetWriterEntryAsync( It.IsAny(), It.IsAny())) .Returns(Task.CompletedTask); } public async Task ConfigureFromObjectErrorTest1Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10157" } }; // Save error will return error for entry var createCall = _publishedNodesServices.Setup(s => s.CreateOrUpdateDataSetWriterEntryAsync( It.IsAny(), It.IsAny())) .Throws(); createCall.Verifiable(Times.Exactly(25)); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = true, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(25, results.Count); Assert.All(results, r => { Assert.NotNull(r.ErrorInfo); Assert.Equal(StatusCodes.BadInvalidArgument, r.ErrorInfo.StatusCode); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromObjectErrorTest2Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10157" } }; // Save error will return error for entry var createCall = _publishedNodesServices.Setup(s => s.CreateOrUpdateDataSetWriterEntryAsync( It.IsAny(), It.IsAny())) .Throws(); createCall.Verifiable(Times.Exactly(25)); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = true, ExcludeRootIfInstanceNode = true, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Empty(results); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromObjectErrorTest3Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10157" } }; // Save error will return error for entry var createCall = _publishedNodesServices.Setup(s => s.CreateOrUpdateDataSetWriterEntryAsync( It.IsAny(), It.IsAny())) .Throws(); createCall.Verifiable(Times.Once); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = true, NoSubTypesOfTypeNodes = false, CreateSingleWriter = true }, ct).ToListAsync(ct).ConfigureAwait(false); var result = Assert.Single(results); Assert.NotNull(result.ErrorInfo); Assert.Equal(StatusCodes.BadInvalidArgument, result.ErrorInfo.StatusCode); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); Assert.Equal(623, result.Result.OpcNodes.Count); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromObjectWithBrowsePathTest1Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10157", BrowsePath = new[] { "http://test.org/UA/Data/#Static" } } }; _createCall.Verifiable(Times.Exactly(12)); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(12, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromObjectWithBrowsePathTest2Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10157", BrowsePath = new[] { "http://test.org/UA/Data/#Static" } } }; _createCall.Verifiable(Times.Once); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, CreateSingleWriter = true }, ct).ToListAsync(ct).ConfigureAwait(false); var result = Assert.Single(results); Assert.Null(result.ErrorInfo); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); Assert.Equal(300, result.Result.OpcNodes.Count); Assert.All(result.Result.OpcNodes, result => { Assert.NotNull(result.DataSetFieldId); Assert.NotNull(result.Id); }); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromObjectTest1Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10157" } }; _createCall.Verifiable(Times.Exactly(25)); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = true, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(25, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromObjectTest2Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10157" } }; _createCall.Verifiable(Times.Once); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = true, NoSubTypesOfTypeNodes = false, CreateSingleWriter = true }, ct).ToListAsync(ct).ConfigureAwait(false); var result = Assert.Single(results); Assert.Null(result.ErrorInfo); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); Assert.Equal(623, result.Result.OpcNodes.Count); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromServerObjectTest1Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Opc.Ua.ObjectIds.Server.ToString() } }; _createCall.Verifiable(Times.Exactly(77)); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = true, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(77, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromServerObjectTest2Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Opc.Ua.ObjectIds.Server.ToString() } }; _createCall.Verifiable(Times.Exactly(78)); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(78, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromServerObjectTest3Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Opc.Ua.ObjectIds.Server.ToString() } }; _createCall.Verifiable(Times.Once); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, CreateSingleWriter = true }, ct).ToListAsync(ct).ConfigureAwait(false); var result = Assert.Single(results); Assert.Null(result.ErrorInfo); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); Assert.Equal(940, result.Result.OpcNodes.Count); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromServerObjectTest4Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Opc.Ua.ObjectIds.Server.ToString() } }; _createCall.Verifiable(Times.Exactly(9)); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, MaxDepth = 1, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(9, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromServerObjectTest5Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Opc.Ua.ObjectIds.Server.ToString() } }; _createCall.Verifiable(Times.Once); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, MaxDepth = 0, MaxLevelsToExpand = 1, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); var result = Assert.Single(results); Assert.Null(result.ErrorInfo); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); Assert.Equal(7, result.Result.OpcNodes.Count); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromBaseObjectTypeTest1Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Opc.Ua.ObjectTypeIds.BaseObjectType.ToString() } }; _createCall.Verifiable(Times.Exactly(81)); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, FlattenTypeInstance = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(81, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromBaseObjectTypeTest2Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Opc.Ua.ObjectTypeIds.BaseObjectType.ToString() } }; _createCall.Verifiable(Times.Exactly(5)); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, FlattenTypeInstance = true, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(5, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromBaseObjectsAndObjectTypesTestAsync(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Opc.Ua.ObjectTypeIds.BaseObjectType.ToString(), DataSetFieldId = "type" }, new OpcNodeModel { Id = Opc.Ua.ObjectIds.Server.ToString(), DataSetFieldId = "object" }, new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10157", DataSetFieldId = "data" } }; _createCall.Verifiable(Times.Exactly(184)); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, FlattenTypeInstance = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(184, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromVariablesTest1Async(CancellationToken ct = default) { // Test only variables as node ids in an entry var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10216" }, new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10217" }, new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10218" } }; _createCall.Verifiable(Times.Once); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); var result = Assert.Single(results); Assert.Null(result.ErrorInfo); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); Assert.Equal(6, result.Result.OpcNodes.Count); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromVariablesAndObjectsTest1Async(CancellationToken ct = default) { // Test mixing variables and objects in an entry to expand var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10217" }, new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10216" }, new OpcNodeModel { Id = Opc.Ua.ObjectIds.Server.ToString() }, new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10218" }, new OpcNodeModel { Id = Opc.Ua.ObjectTypeIds.BaseObjectType.ToString() } }; _createCall.Verifiable(Times.Exactly(160)); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, FlattenTypeInstance = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(160, results.Count); Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); Assert.True(r.Result.OpcNodes.Count > 0); }); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromVariableTypesTest1Async(CancellationToken ct = default) { // Test only variable types as node ids in an entry var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Opc.Ua.VariableTypeIds.PropertyType.ToString() } }; _createCall.Verifiable(Times.Once); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); var result = Assert.Single(results); Assert.Null(result.ErrorInfo); Assert.NotNull(result.Result); Assert.Equal(Opc.Ua.VariableTypeIds.PropertyType + "/PropertyType", result.Result.DataSetWriterId); Assert.NotNull(result.Result.OpcNodes); Assert.Equal(697, result.Result.OpcNodes.Count); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromVariableTypesTest2Async(CancellationToken ct = default) { // Test only variable types as node ids in an entry var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Opc.Ua.VariableTypeIds.DataItemType.ToString() } }; _createCall.Verifiable(Times.Once); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); var result = Assert.Single(results); Assert.Null(result.ErrorInfo); Assert.NotNull(result.Result); Assert.Equal(Opc.Ua.VariableTypeIds.DataItemType + "/DataItemType", result.Result.DataSetWriterId); Assert.NotNull(result.Result.OpcNodes); Assert.Equal(96, result.Result.OpcNodes.Count); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromVariableTypesTest3Async(CancellationToken ct = default) { // Test only variable types as node ids in an entry var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = Opc.Ua.VariableTypeIds.PropertyType.ToString() }, new OpcNodeModel { Id = Opc.Ua.VariableTypeIds.DataItemType.ToString() } }; _createCall.Verifiable(Times.Exactly(2)); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Equal(2, results.Count); var total = 0; Assert.All(results, r => { Assert.Null(r.ErrorInfo); Assert.NotNull(r.Result); Assert.NotNull(r.Result.OpcNodes); total += r.Result.OpcNodes.Count; }); Assert.Equal(793, total); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromObjectWithNoObjectsTest1Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10791" } }; _createCall.Verifiable(Times.Never); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = true, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); // An object node that has no objects and is excluded should result // in a service result model with "No objects resolved" var result = Assert.Single(results); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); Assert.Equal("http://test.org/UA/Data/#i=10791", Assert.Single(result.Result.OpcNodes).Id); Assert.NotNull(result.ErrorInfo); Assert.Equal("No objects resolved.", result.ErrorInfo.ErrorMessage); Assert.Equal(StatusCodes.BadNotFound, result.ErrorInfo.StatusCode); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromObjectWithNoObjectsTest2Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10791" } }; _createCall.Verifiable(Times.Never); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = true, ExcludeRootIfInstanceNode = true, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); // Discard errors -> no errors Assert.Empty(results); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromEmptyEntryTest1Async(CancellationToken ct = default) { // Nothing should be returned when an empty entry passed var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = Array.Empty(); _createCall.Verifiable(Times.Never); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = true, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Empty(results); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromEmptyEntryTest2Async(CancellationToken ct = default) { // Nothing should be returned when an empty entry passed var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = Array.Empty(); _createCall.Verifiable(Times.Never); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = true, NoSubTypesOfTypeNodes = false, CreateSingleWriter = true }, ct).ToListAsync(ct).ConfigureAwait(false); Assert.Empty(results); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromBadNodeIdTest1Async(CancellationToken ct = default) { // Entry with bad node id should return error var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = "s=bad" } }; _createCall.Verifiable(Times.Never); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = true, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); var result = Assert.Single(results); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); Assert.Equal("s=bad", Assert.Single(result.Result.OpcNodes).Id); Assert.NotNull(result.ErrorInfo); Assert.Equal(StatusCodes.BadNodeIdUnknown, result.ErrorInfo.StatusCode); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromBadNodeIdTest2Async(CancellationToken ct = default) { // An entry with multiple nodes and duplicate field ids should return an error var entry = _connection.ToPublishedNodesEntry(); entry.OpcNodes = new[] { new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10157", DataSetFieldId = "test" }, new OpcNodeModel { Id = "http://test.org/UA/Data/#i=10158", DataSetFieldId = "test" } }; _createCall.Verifiable(Times.Never); var ex = await Assert.ThrowsAnyAsync(async () => await _service(_publishedNodesServices.Object).CreateOrUpdateAsync( entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = true, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false)).ConfigureAwait(false); Assert.True(ex is MethodCallStatusException or BadRequestException); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } public async Task ConfigureFromBadNodeIdTest3Async(CancellationToken ct = default) { var entry = _connection.ToPublishedNodesEntry(); // Method or view node id passed results in not supported error. entry.OpcNodes = new[] { new OpcNodeModel { Id = MethodIds.Server_GetMonitoredItems.ToString() } }; _createCall.Verifiable(Times.Never); var results = await _service(_publishedNodesServices.Object).CreateOrUpdateAsync(entry, new PublishedNodeExpansionModel { DiscardErrors = false, ExcludeRootIfInstanceNode = false, NoSubTypesOfTypeNodes = false, CreateSingleWriter = false }, ct).ToListAsync(ct).ConfigureAwait(false); var result = Assert.Single(results); Assert.NotNull(result.ErrorInfo); Assert.NotNull(result.Result); Assert.NotNull(result.Result.OpcNodes); Assert.Equal(MethodIds.Server_GetMonitoredItems.ToString(), Assert.Single(result.Result.OpcNodes).Id); Assert.Equal(StatusCodes.BadNotSupported, result.ErrorInfo.StatusCode); _publishedNodesServices.Verify(); _publishedNodesServices.VerifyNoOtherCalls(); } private readonly ConnectionModel _connection; private readonly Mock _publishedNodesServices; private readonly IReturnsResult _createCall; private readonly Func _service; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/NodeMetadataTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Models; using System; using System.Linq; using System.Threading; using System.Threading.Tasks; using Xunit; public class NodeMetadataTests { /// /// Create metadata tests /// /// /// public NodeMetadataTests(Func> services, T connection) { _services = services; _connection = connection; } public async Task GetServerCapabilitiesTestAsync(CancellationToken ct = default) { var services = _services(); var results = await services.GetServerCapabilitiesAsync(_connection, null, ct).ConfigureAwait(false); Assert.NotNull(results); Assert.NotNull(results.AggregateFunctions); Assert.Equal(37, results.AggregateFunctions.Count); Assert.Single(results.SupportedLocales!); Assert.Equal("en-US", results.SupportedLocales![0]); Assert.NotEmpty(results.ServerProfiles!); Assert.Equal(3, results.ServerProfiles!.Count); Assert.NotNull(results.OperationLimits); Assert.Null(results.OperationLimits.MinSupportedSampleRate); Assert.Equal(1000u, results.OperationLimits.MaxBrowseContinuationPoints!.Value); Assert.Equal(1000u, results.OperationLimits.MaxQueryContinuationPoints!.Value); Assert.Equal(1000u, results.OperationLimits.MaxHistoryContinuationPoints!.Value); Assert.Null(results.OperationLimits.MaxNodesPerBrowse); Assert.Null(results.OperationLimits.MaxNodesPerRegisterNodes); Assert.Null(results.OperationLimits.MaxNodesPerWrite); Assert.Null(results.OperationLimits.MaxNodesPerMethodCall); Assert.Null(results.OperationLimits.MaxNodesPerNodeManagement); Assert.Null(results.OperationLimits.MaxMonitoredItemsPerCall); Assert.Null(results.OperationLimits.MaxNodesPerHistoryReadData); Assert.Null(results.OperationLimits.MaxNodesPerHistoryReadEvents); Assert.Null(results.OperationLimits.MaxNodesPerHistoryUpdateData); Assert.Null(results.OperationLimits.MaxNodesPerHistoryUpdateEvents); Assert.Equal(65535u, results.OperationLimits.MaxArrayLength); Assert.Equal(130816u, results.OperationLimits.MaxStringLength); Assert.Equal(1048576u, results.OperationLimits.MaxByteStringLength); Assert.Null(results.ModellingRules); } public async Task HistoryGetServerCapabilitiesTestAsync(CancellationToken ct = default) { var services = _services(); var results = await services.HistoryGetServerCapabilitiesAsync(_connection, null, ct).ConfigureAwait(false); Assert.NotNull(results); Assert.Null(results.AggregateFunctions); Assert.False(results.AccessHistoryDataCapability); Assert.False(results.AccessHistoryEventsCapability); Assert.False(results.InsertDataCapability); Assert.False(results.InsertEventCapability); Assert.False(results.InsertAnnotationCapability); Assert.False(results.ReplaceDataCapability); Assert.False(results.ReplaceEventCapability); Assert.False(results.DeleteRawCapability); Assert.False(results.DeleteAtTimeCapability); Assert.False(results.DeleteEventCapability); Assert.False(results.ServerTimestampSupported); Assert.False(results.UpdateDataCapability); Assert.False(results.UpdateEventCapability); Assert.Null(results.MaxReturnDataValues); Assert.Null(results.MaxReturnEventValues); } public async Task NodeGetMetadataForFolderTypeTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var result = await browser.GetMetadataAsync(_connection, new NodeMetadataRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { Level = DiagnosticsLevel.Verbose } }, NodeId = Opc.Ua.ObjectTypeIds.FolderType.ToString() }, ct).ConfigureAwait(false); // Assert Assert.Null(result.ErrorInfo); Assert.NotNull(result.TypeDefinition); Assert.Equal(NodeType.Object, result.TypeDefinition.NodeType); Assert.NotNull(result.TypeDefinition.Declarations); Assert.Empty(result.TypeDefinition.Declarations); } public async Task NodeGetMetadataForServerObjectTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var result = await browser.GetMetadataAsync(_connection, new NodeMetadataRequestModel { NodeId = Opc.Ua.ObjectIds.Server.ToString() }, ct).ConfigureAwait(false); // Assert Assert.Null(result.ErrorInfo); Assert.NotNull(result.TypeDefinition); Assert.Equal("ServerType", result.TypeDefinition.BrowseName); Assert.Equal(Opc.Ua.ObjectTypeIds.ServerType.ToString(), result.TypeDefinition.TypeDefinitionId); Assert.Equal(NodeType.Object, result.TypeDefinition.NodeType); var baseType = Assert.Single(result.TypeDefinition.TypeHierarchy!); Assert.Equal("i=58", baseType.NodeId); Assert.Equal("BaseObjectType", baseType.BrowseName); Assert.NotNull(result.TypeDefinition.Declarations); Assert.NotEmpty(result.TypeDefinition.Declarations); Assert.Equal(63, result.TypeDefinition.Declarations.Count); Assert.Collection(result.TypeDefinition.Declarations.Select(d => d.BrowseName), arg => Assert.Equal("ServerArray", arg), arg => Assert.Equal("NamespaceArray", arg), arg => Assert.Equal("UrisVersion", arg), arg => Assert.Equal("ServerStatus", arg), arg => Assert.Equal("StartTime", arg), arg => Assert.Equal("CurrentTime", arg), arg => Assert.Equal("State", arg), arg => Assert.Equal("BuildInfo", arg), arg => Assert.Equal("ProductUri", arg), arg => Assert.Equal("ManufacturerName", arg), arg => Assert.Equal("ProductName", arg), arg => Assert.Equal("SoftwareVersion", arg), arg => Assert.Equal("BuildNumber", arg), arg => Assert.Equal("BuildDate", arg), arg => Assert.Equal("SecondsTillShutdown", arg), arg => Assert.Equal("ShutdownReason", arg), arg => Assert.Equal("ServiceLevel", arg), arg => Assert.Equal("Auditing", arg), arg => Assert.Equal("EstimatedReturnTime", arg), arg => Assert.Equal("LocalTime", arg), arg => Assert.Equal("ServerCapabilities", arg), arg => Assert.Equal("ServerProfileArray", arg), arg => Assert.Equal("LocaleIdArray", arg), arg => Assert.Equal("MinSupportedSampleRate", arg), arg => Assert.Equal("MaxBrowseContinuationPoints", arg), arg => Assert.Equal("MaxQueryContinuationPoints", arg), arg => Assert.Equal("MaxHistoryContinuationPoints", arg), arg => Assert.Equal("SoftwareCertificates", arg), arg => Assert.Equal("ModellingRules", arg), arg => Assert.Equal("AggregateFunctions", arg), arg => Assert.Equal("ServerDiagnostics", arg), arg => Assert.Equal("ServerDiagnosticsSummary", arg), arg => Assert.Equal("ServerViewCount", arg), arg => Assert.Equal("CurrentSessionCount", arg), arg => Assert.Equal("CumulatedSessionCount", arg), arg => Assert.Equal("SecurityRejectedSessionCount", arg), arg => Assert.Equal("RejectedSessionCount", arg), arg => Assert.Equal("SessionTimeoutCount", arg), arg => Assert.Equal("SessionAbortCount", arg), arg => Assert.Equal("PublishingIntervalCount", arg), arg => Assert.Equal("CurrentSubscriptionCount", arg), arg => Assert.Equal("CumulatedSubscriptionCount", arg), arg => Assert.Equal("SecurityRejectedRequestsCount", arg), arg => Assert.Equal("RejectedRequestsCount", arg), arg => Assert.Equal("SubscriptionDiagnosticsArray", arg), arg => Assert.Equal("SessionsDiagnosticsSummary", arg), arg => Assert.Equal("SessionDiagnosticsArray", arg), arg => Assert.Equal("SessionSecurityDiagnosticsArray", arg), arg => Assert.Equal("EnabledFlag", arg), arg => Assert.Equal("VendorServerInfo", arg), arg => Assert.Equal("ServerRedundancy", arg), arg => Assert.Equal("RedundancySupport", arg), arg => Assert.Equal("Namespaces", arg), arg => Assert.Equal("GetMonitoredItems", arg), arg => Assert.Equal("InputArguments", arg), arg => Assert.Equal("OutputArguments", arg), arg => Assert.Equal("ResendData", arg), arg => Assert.Equal("InputArguments", arg), arg => Assert.Equal("SetSubscriptionDurable", arg), arg => Assert.Equal("InputArguments", arg), arg => Assert.Equal("OutputArguments", arg), arg => Assert.Equal("RequestServerStateChange", arg), arg => Assert.Equal("InputArguments", arg)); } public async Task NodeGetMetadataForConditionTypeTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var result = await browser.GetMetadataAsync(_connection, new NodeMetadataRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { Level = DiagnosticsLevel.Verbose } }, NodeId = Opc.Ua.ObjectTypeIds.ConditionType.ToString() }, ct).ConfigureAwait(false); // Assert Assert.Null(result.ErrorInfo); Assert.NotNull(result.TypeDefinition); Assert.Equal(NodeType.Event, result.TypeDefinition.NodeType); Assert.NotEmpty(result.TypeDefinition.TypeHierarchy!); Assert.Equal(2, result.TypeDefinition.TypeHierarchy!.Count); Assert.NotNull(result.TypeDefinition.Declarations); Assert.NotEmpty(result.TypeDefinition.Declarations); Assert.Equal(35, result.TypeDefinition.Declarations.Count); } public async Task NodeGetMetadataForServerStatusVariableTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var result = await browser.GetMetadataAsync(_connection, new NodeMetadataRequestModel { NodeId = Opc.Ua.VariableIds.Server_ServerStatus.ToString() }, ct).ConfigureAwait(false); // Assert Assert.Null(result.ErrorInfo); Assert.NotNull(result.TypeDefinition); Assert.Equal("ServerStatusType", result.TypeDefinition.BrowseName); Assert.Equal(Opc.Ua.VariableTypeIds.ServerStatusType.ToString(), result.TypeDefinition.TypeDefinitionId); Assert.Equal(NodeType.DataVariable, result.TypeDefinition.NodeType); Assert.Equal(2, result.TypeDefinition.TypeHierarchy!.Count); Assert.Equal("i=62", result.TypeDefinition.TypeHierarchy[0].NodeId); Assert.Equal("BaseVariableType", result.TypeDefinition.TypeHierarchy[0].BrowseName); Assert.NotNull(result.TypeDefinition.Declarations); Assert.NotEmpty(result.TypeDefinition.Declarations); Assert.Equal(12, result.TypeDefinition.Declarations.Count); Assert.Collection(result.TypeDefinition.Declarations.Select(d => d.BrowseName), arg => Assert.Equal("StartTime", arg), arg => Assert.Equal("CurrentTime", arg), arg => Assert.Equal("State", arg), arg => Assert.Equal("BuildInfo", arg), arg => Assert.Equal("ProductUri", arg), arg => Assert.Equal("ManufacturerName", arg), arg => Assert.Equal("ProductName", arg), arg => Assert.Equal("SoftwareVersion", arg), arg => Assert.Equal("BuildNumber", arg), arg => Assert.Equal("BuildDate", arg), arg => Assert.Equal("SecondsTillShutdown", arg), arg => Assert.Equal("ShutdownReason", arg)); } public async Task NodeGetMetadataForRedundancySupportPropertyTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var result = await browser.GetMetadataAsync(_connection, new NodeMetadataRequestModel { NodeId = Opc.Ua.VariableIds.Server_ServerRedundancy_RedundancySupport.ToString() }, ct).ConfigureAwait(false); // Assert Assert.Null(result.ErrorInfo); Assert.NotNull(result.TypeDefinition); Assert.Equal("PropertyType", result.TypeDefinition.BrowseName); Assert.Equal(Opc.Ua.VariableTypeIds.PropertyType.ToString(), result.TypeDefinition.TypeDefinitionId); Assert.Equal(NodeType.Property, result.TypeDefinition.NodeType); var baseType = Assert.Single(result.TypeDefinition.TypeHierarchy!); Assert.Equal("i=62", baseType.NodeId); Assert.Equal("BaseVariableType", baseType.BrowseName); Assert.NotNull(result.TypeDefinition.Declarations); Assert.Empty(result.TypeDefinition.Declarations); } public async Task NodeGetMetadataForBaseInterfaceTypeTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var result = await browser.GetMetadataAsync(_connection, new NodeMetadataRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { Level = DiagnosticsLevel.Verbose } }, NodeId = Opc.Ua.ObjectTypeIds.BaseInterfaceType.ToString() }, ct).ConfigureAwait(false); // Assert Assert.Null(result.ErrorInfo); Assert.NotNull(result.TypeDefinition); Assert.NotEmpty(result.TypeDefinition.TypeHierarchy!); var baseType = Assert.Single(result.TypeDefinition.TypeHierarchy!); Assert.Equal("i=58", baseType.NodeId); Assert.Equal("BaseObjectType", baseType.BrowseName); Assert.Equal(NodeType.Interface, result.TypeDefinition.NodeType); Assert.NotNull(result.TypeDefinition.Declarations); Assert.Empty(result.TypeDefinition.Declarations); } public async Task NodeGetMetadataTestForBaseEventTypeTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var result = await browser.GetMetadataAsync(_connection, new NodeMetadataRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { Level = DiagnosticsLevel.Verbose } }, NodeId = Opc.Ua.ObjectTypeIds.BaseEventType.ToString() }, ct).ConfigureAwait(false); // Assert Assert.Null(result.ErrorInfo); Assert.NotNull(result.TypeDefinition); Assert.NotNull(result.TypeDefinition.Declarations); Assert.NotEmpty(result.TypeDefinition.Declarations); Assert.NotEmpty(result.TypeDefinition.TypeHierarchy!); var baseType = Assert.Single(result.TypeDefinition!.TypeHierarchy!); Assert.Equal("i=58", baseType.NodeId); Assert.Equal("BaseObjectType", baseType.BrowseName); Assert.Equal(NodeType.Event, result.TypeDefinition.NodeType); Assert.All(result.TypeDefinition.Declarations, arg => { Assert.Equal("i=2041", arg.RootTypeId); Assert.Equal(NodeClass.Variable, arg.NodeClass); Assert.NotNull(arg.VariableMetadata); Assert.NotNull(arg.VariableMetadata.DataType); Assert.Null(arg.Description); Assert.Null(arg.OverriddenDeclaration); }); Assert.Collection(result.TypeDefinition.Declarations, arg => { Assert.Equal("/EventId", Assert.Single(arg.BrowsePath!)); Assert.Equal("EventId", arg.DisplayName); Assert.Equal("ByteString", arg.VariableMetadata!.DataType!.DataType); Assert.Equal("Mandatory", arg.ModellingRule); Assert.Equal("i=2042", arg.NodeId); Assert.Null(arg.VariableMetadata.ArrayDimensions); Assert.Equal(NodeValueRank.Scalar, arg.VariableMetadata.ValueRank!.Value); }, arg => { Assert.Equal("/EventType", Assert.Single(arg.BrowsePath!)); Assert.Equal("EventType", arg.DisplayName); Assert.Equal("NodeId", arg.VariableMetadata!.DataType!.DataType); Assert.Equal("Mandatory", arg.ModellingRule); Assert.Equal("i=2043", arg.NodeId); Assert.Null(arg.VariableMetadata.ArrayDimensions); Assert.Equal(NodeValueRank.Scalar, arg.VariableMetadata.ValueRank!.Value); }, arg => { Assert.Equal("/SourceNode", Assert.Single(arg.BrowsePath!)); Assert.Equal("SourceNode", arg.DisplayName); Assert.Equal("NodeId", arg.VariableMetadata!.DataType!.DataType); Assert.Equal("Mandatory", arg.ModellingRule); Assert.Equal("i=2044", arg.NodeId); Assert.Null(arg.VariableMetadata.ArrayDimensions); Assert.Equal(NodeValueRank.Scalar, arg.VariableMetadata.ValueRank!.Value); }, arg => { Assert.Equal("/SourceName", Assert.Single(arg.BrowsePath!)); Assert.Equal("SourceName", arg.DisplayName); Assert.Equal("String", arg.VariableMetadata!.DataType!.DataType); Assert.Equal("Mandatory", arg.ModellingRule); Assert.Equal("i=2045", arg.NodeId); Assert.Null(arg.VariableMetadata.ArrayDimensions); Assert.Equal(NodeValueRank.Scalar, arg.VariableMetadata.ValueRank!.Value); }, arg => { Assert.Equal("/Time", Assert.Single(arg.BrowsePath!)); Assert.Equal("Time", arg.DisplayName); Assert.Equal("UtcTime", arg.VariableMetadata!.DataType!.DataType); Assert.Equal("Mandatory", arg.ModellingRule); Assert.Equal("i=2046", arg.NodeId); Assert.Null(arg.VariableMetadata.ArrayDimensions); Assert.Equal(NodeValueRank.Scalar, arg.VariableMetadata.ValueRank!.Value); }, arg => { Assert.Equal("/ReceiveTime", Assert.Single(arg.BrowsePath!)); Assert.Equal("ReceiveTime", arg.DisplayName); Assert.Equal("UtcTime", arg.VariableMetadata!.DataType!.DataType); Assert.Equal("Mandatory", arg.ModellingRule); Assert.Equal("i=2047", arg.NodeId); Assert.Null(arg.VariableMetadata.ArrayDimensions); Assert.Equal(NodeValueRank.Scalar, arg.VariableMetadata.ValueRank!.Value); }, arg => { Assert.Equal("/LocalTime", Assert.Single(arg.BrowsePath!)); Assert.Equal("LocalTime", arg.DisplayName); Assert.Equal("TimeZoneDataType", arg.VariableMetadata!.DataType!.DataType); Assert.Equal("Optional", arg.ModellingRule); Assert.Equal("i=3190", arg.NodeId); Assert.Null(arg.VariableMetadata.ArrayDimensions); Assert.Equal(NodeValueRank.Scalar, arg.VariableMetadata.ValueRank!.Value); }, arg => { Assert.Equal("/Message", Assert.Single(arg.BrowsePath!)); Assert.Equal("Message", arg.DisplayName); Assert.Equal("LocalizedText", arg.VariableMetadata!.DataType!.DataType); Assert.Equal("Mandatory", arg.ModellingRule); Assert.Equal("i=2050", arg.NodeId); Assert.Null(arg.VariableMetadata.ArrayDimensions); Assert.Equal(NodeValueRank.Scalar, arg.VariableMetadata.ValueRank!.Value); }, arg => { Assert.Equal("/Severity", Assert.Single(arg.BrowsePath!)); Assert.Equal("Severity", arg.DisplayName); Assert.Equal("UInt16", arg.VariableMetadata!.DataType!.DataType); Assert.Equal("Mandatory", arg.ModellingRule); Assert.Equal("i=2051", arg.NodeId); Assert.Null(arg.VariableMetadata.ArrayDimensions); Assert.Equal(NodeValueRank.Scalar, arg.VariableMetadata.ValueRank!.Value); }, arg => { Assert.Equal("/ConditionClassId", Assert.Single(arg.BrowsePath!)); Assert.Equal("ConditionClassId", arg.DisplayName); Assert.Equal("NodeId", arg.VariableMetadata!.DataType!.DataType); Assert.Equal("Optional", arg.ModellingRule); Assert.Equal("i=31771", arg.NodeId); Assert.Null(arg.VariableMetadata.ArrayDimensions); Assert.Equal(NodeValueRank.Scalar, arg.VariableMetadata.ValueRank!.Value); }, arg => { Assert.Equal("/ConditionClassName", Assert.Single(arg.BrowsePath!)); Assert.Equal("ConditionClassName", arg.DisplayName); Assert.Equal("LocalizedText", arg.VariableMetadata!.DataType!.DataType); Assert.Equal("Optional", arg.ModellingRule); Assert.Equal("i=31772", arg.NodeId); Assert.Null(arg.VariableMetadata.ArrayDimensions); Assert.Equal(NodeValueRank.Scalar, arg.VariableMetadata.ValueRank!.Value); }, arg => { Assert.Equal("/ConditionSubClassId", Assert.Single(arg.BrowsePath!)); Assert.Equal("ConditionSubClassId", arg.DisplayName); Assert.Equal("NodeId", arg.VariableMetadata!.DataType!.DataType); Assert.Equal("Optional", arg.ModellingRule); Assert.Equal("i=31773", arg.NodeId); Assert.NotNull(arg.VariableMetadata.ArrayDimensions); Assert.Equal(0u, Assert.Single(arg.VariableMetadata.ArrayDimensions)); Assert.Equal(NodeValueRank.OneDimension, arg.VariableMetadata.ValueRank!.Value); }, arg => { Assert.Equal("/ConditionSubClassName", Assert.Single(arg.BrowsePath!)); Assert.Equal("ConditionSubClassName", arg.DisplayName); Assert.Equal("LocalizedText", arg.VariableMetadata!.DataType!.DataType); Assert.Equal("Optional", arg.ModellingRule); Assert.Equal("i=31774", arg.NodeId); Assert.NotNull(arg.VariableMetadata.ArrayDimensions); Assert.Equal(0u, Assert.Single(arg.VariableMetadata.ArrayDimensions)); Assert.Equal(NodeValueRank.OneDimension, arg.VariableMetadata.ValueRank!.Value); }); } public async Task NodeGetMetadataForPropertyTypeTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var result = await browser.GetMetadataAsync(_connection, new NodeMetadataRequestModel { NodeId = Opc.Ua.VariableTypeIds.PropertyType.ToString() }, ct).ConfigureAwait(false); // Assert Assert.Null(result.ErrorInfo); Assert.NotNull(result.TypeDefinition); Assert.NotEmpty(result.TypeDefinition.TypeHierarchy!); var baseType = Assert.Single(result.TypeDefinition.TypeHierarchy!); Assert.Equal("i=62", baseType.NodeId); Assert.Equal("BaseVariableType", baseType.BrowseName); Assert.Equal(NodeType.Property, result.TypeDefinition.NodeType); Assert.NotNull(result.TypeDefinition.Declarations); Assert.Empty(result.TypeDefinition.Declarations); } public async Task NodeGetMetadataForBaseDataVariableTypeTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var result = await browser.GetMetadataAsync(_connection, new NodeMetadataRequestModel { NodeId = Opc.Ua.VariableTypeIds.BaseDataVariableType.ToString() }, ct).ConfigureAwait(false); // Assert Assert.Null(result.ErrorInfo); Assert.NotNull(result.TypeDefinition); Assert.NotEmpty(result.TypeDefinition.TypeHierarchy!); var baseType = Assert.Single(result.TypeDefinition.TypeHierarchy!); Assert.Equal("i=62", baseType.NodeId); Assert.Equal("BaseVariableType", baseType.BrowseName); Assert.Equal(NodeType.DataVariable, result.TypeDefinition.NodeType); Assert.NotNull(result.TypeDefinition.Declarations); Assert.Empty(result.TypeDefinition.Declarations); } public async Task NodeGetMetadataForAudioVariableTypeTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var result = await browser.GetMetadataAsync(_connection, new NodeMetadataRequestModel { NodeId = Opc.Ua.VariableTypeIds.AudioVariableType.ToString() }, ct).ConfigureAwait(false); // Assert Assert.Null(result.ErrorInfo); Assert.NotNull(result.TypeDefinition); Assert.NotEmpty(result.TypeDefinition.TypeHierarchy!); Assert.Equal(2, result.TypeDefinition.TypeHierarchy!.Count); Assert.Equal(NodeType.DataVariable, result.TypeDefinition.NodeType); Assert.NotNull(result.TypeDefinition.Declarations); Assert.Equal(3, result.TypeDefinition.Declarations.Count); Assert.All(result.TypeDefinition.Declarations, arg => { Assert.Equal(Opc.Ua.VariableTypeIds.AudioVariableType.ToString(), arg.RootTypeId); Assert.Equal(NodeClass.Variable, arg.NodeClass); Assert.NotNull(arg.VariableMetadata); Assert.Null(arg.VariableMetadata.ArrayDimensions); Assert.Null(arg.MethodMetadata); Assert.Null(arg.Description); Assert.Null(arg.OverriddenDeclaration); Assert.NotNull(arg.VariableMetadata.DataType); Assert.Equal("String", arg.VariableMetadata!.DataType!.DataType); Assert.Equal(NodeValueRank.Scalar, arg.VariableMetadata!.ValueRank!.Value); }); Assert.Collection(result.TypeDefinition.Declarations, arg => { Assert.Equal("Optional", arg.ModellingRule); Assert.Equal("ListId", arg.DisplayName); Assert.Equal("i=17988", arg.NodeId); }, arg => { Assert.Equal("Optional", arg.ModellingRule); Assert.Equal("AgencyId", arg.DisplayName); Assert.Equal("i=17989", arg.NodeId); }, arg => { Assert.Equal("Optional", arg.ModellingRule); Assert.Equal("VersionId", arg.DisplayName); Assert.Equal("i=17990", arg.NodeId); }); } private readonly T _connection; private readonly Func> _services; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/ReadArrayValueTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Json; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using System.Xml; using Xunit; public class ReadArrayValueTests { /// /// Create node services tests /// /// /// /// public ReadArrayValueTests(Func> services, T connection, Func> readExpected) { _services = services; _connection = connection; _readExpected = readExpected; _serializer = new DefaultJsonSerializer(); } public async Task NodeReadAllStaticArrayVariableNodeClassTest1Async(CancellationToken ct = default) { var browser = _services(); const Opc.Ua.NodeClass expected = Opc.Ua.NodeClass.Variable; var attributes = new List(); for (var i = 10300; i < 10326; i++) { attributes.Add(new AttributeReadRequestModel { Attribute = NodeAttribute.NodeClass, NodeId = "http://test.org/UA/Data/#i=" + i }); } // Act var result = await browser.ReadAsync(_connection, new ReadRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { AuditId = nameof(NodeReadAllStaticArrayVariableNodeClassTest1Async), TimeStamp = DateTime.Now } }, Attributes = attributes }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Results); Assert.Equal(attributes.Count, result.Results.Count); Assert.All(result.Results, r => Assert.Null(r.ErrorInfo)); Assert.All(result.Results, r => Assert.Equal((int)expected, (int)r.Value)); } public async Task NodeReadAllStaticArrayVariableAccessLevelTest1Async(CancellationToken ct = default) { var browser = _services(); const int expected = Opc.Ua.AccessLevels.CurrentRead | Opc.Ua.AccessLevels.CurrentWrite; var attributes = new List(); for (var i = 10300; i < 10326; i++) { attributes.Add(new AttributeReadRequestModel { Attribute = NodeAttribute.AccessLevel, NodeId = "http://test.org/UA/Data/#i=" + i }); } // Act var result = await browser.ReadAsync(_connection, new ReadRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { AuditId = nameof(NodeReadAllStaticArrayVariableAccessLevelTest1Async), TimeStamp = DateTime.Now } }, Attributes = attributes }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Results); Assert.Equal(attributes.Count, result.Results.Count); Assert.All(result.Results, r => Assert.Null(r.ErrorInfo)); Assert.All(result.Results, r => Assert.Equal(expected, (int)r.Value)); } public async Task NodeReadAllStaticArrayVariableWriteMaskTest1Async(CancellationToken ct = default) { var browser = _services(); var attributes = new List(); for (var i = 10300; i < 10326; i++) { attributes.Add(new AttributeReadRequestModel { Attribute = NodeAttribute.WriteMask, NodeId = "http://test.org/UA/Data/#i=" + i }); } // Act var result = await browser.ReadAsync(_connection, new ReadRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { AuditId = nameof(NodeReadAllStaticArrayVariableWriteMaskTest1Async), TimeStamp = DateTime.Now } }, Attributes = attributes }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Results); Assert.Equal(attributes.Count, result.Results.Count); Assert.All(result.Results, r => Assert.Null(r.ErrorInfo)); Assert.All(result.Results, r => Assert.Equal(0, (int)r.Value)); } public async Task NodeReadAllStaticArrayVariableWriteMaskTest2Async(CancellationToken ct = default) { var browser = _services(); var attributes = new List(); for (var i = 10300; i < 10326; i++) { attributes.Add(new AttributeReadRequestModel { Attribute = NodeAttribute.WriteMask, NodeId = "http://test.org/UA/Data/#i=10300" }); } // Act var result = await browser.ReadAsync(_connection, new ReadRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { AuditId = nameof(NodeReadAllStaticArrayVariableWriteMaskTest2Async), TimeStamp = DateTime.Now } }, Attributes = attributes }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Results); Assert.Equal(attributes.Count, result.Results.Count); Assert.All(result.Results, r => Assert.Null(r.ErrorInfo)); Assert.All(result.Results, r => Assert.Equal(0, (int)r.Value)); } public async Task NodeReadStaticArrayBooleanValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10300"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Value); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.True(result.Value.IsListOfValues, $"{result.Value} is not a list."); if (result.Value.Count == 0) { return; } Assert.True(result.Value[0].IsBoolean, $"{result.Value[0]} is not a boolean."); Assert.Equal("Boolean", result.DataType); } public async Task NodeReadStaticArraySByteValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10301"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Value); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.True(result.Value.IsListOfValues, $"{result.Value} is not a list."); if (result.Value.Count == 0) { return; } Assert.True(result.Value[0].IsInteger, $"{result.Value[0]} is not an integer."); Assert.Equal("SByte", result.DataType); } public async Task NodeReadStaticArrayByteValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10302"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.Equal("ByteString", result.DataType); Assert.True(result.Value.IsNull() || result.Value!.IsBytes); } public async Task NodeReadStaticArrayInt16ValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10303"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Value); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.True(result.Value.IsListOfValues, $"{result.Value} is not a list."); if (result.Value.Count == 0) { return; } Assert.True(result.Value[0].IsInteger, $"{result.Value[0]} is not an integer."); Assert.Equal("Int16", result.DataType); } public async Task NodeReadStaticArrayUInt16ValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10304"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Value); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.True(result.Value.IsListOfValues, $"{result.Value} is not a list."); if (result.Value.Count == 0) { return; } Assert.True(result.Value[0].IsInteger, $"{result.Value[0]} is not an integer."); Assert.Equal("UInt16", result.DataType); } public async Task NodeReadStaticArrayInt32ValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10305"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Value); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.True(result.Value.IsListOfValues, $"{result.Value} is not a list."); if (result.Value.Count == 0) { return; } Assert.True(result.Value[0].IsInteger, $"{result.Value[0]} is not an integer."); Assert.Equal("Int32", result.DataType); } public async Task NodeReadStaticArrayUInt32ValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10306"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Value); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.True(result.Value.IsListOfValues, $"{result.Value} is not a list."); if (result.Value.Count == 0) { return; } Assert.True(result.Value[0].IsInteger, $"{result.Value[0]} is not an integer."); Assert.Equal("UInt32", result.DataType); } public async Task NodeReadStaticArrayInt64ValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10307"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Value); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.True(result.Value.IsListOfValues, $"{result.Value} is not a list."); if (result.Value.Count == 0) { return; } Assert.True(result.Value[0].IsInteger, $"{result.Value[0]} is not an integer."); Assert.Equal("Int64", result.DataType); } public async Task NodeReadStaticArrayUInt64ValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10308"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Value); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.True(result.Value.IsListOfValues, $"{result.Value} is not a list."); if (result.Value.Count == 0) { return; } Assert.True(result.Value[0].IsInteger, $"{result.Value[0]} is not an integer."); Assert.Equal("UInt64", result.DataType); } public async Task NodeReadStaticArrayFloatValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10309"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Value); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.True(result.Value.IsListOfValues, $"{result.Value} is not a list."); if (result.Value.Count == 0) { return; } Assert.True(result.Value[0].IsFloat, $"First is {result.Value}"); Assert.Equal("Float", result.DataType); } public async Task NodeReadStaticArrayDoubleValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10310"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Value); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.True(result.Value.IsListOfValues, $"{result.Value} is not a list."); if (result.Value.Count == 0) { return; } Assert.True(result.Value[0].IsDouble); Assert.Equal("Double", result.DataType); } public async Task NodeReadStaticArrayStringValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10311"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Value); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.True(result.Value.IsListOfValues, $"{result.Value} is not a list."); if (result.Value.Count == 0) { return; } Assert.True(result.Value[0].IsString, $"{result.Value[0]} is not a string."); Assert.Equal("String", result.DataType); } public async Task NodeReadStaticArrayDateTimeValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10312"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Value); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.True(result.Value.IsListOfValues, $"{result.Value} is not a list."); if (result.Value.Count == 0) { return; } Assert.True(result.Value[0].IsDateTime); Assert.Equal("DateTime", result.DataType); } public async Task NodeReadStaticArrayGuidValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10313"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Value); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.True(result.Value.IsListOfValues, $"{result.Value} is not a list."); if (result.Value.Count == 0) { return; } Assert.True(result.Value[0].IsGuid); Assert.Equal("Guid", result.DataType); } public async Task NodeReadStaticArrayByteStringValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10314"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); if (result.Value.IsNull()) { return; } Assert.True(result.Value!.IsListOfValues); if (result.Value.Count == 0) { return; } // TODO: Can be null. Assert.Equal(VariantValueType.String, (result.Value)[0].Type); // TODO: Assert.Equal(VariantValueType.Bytes, (result.Value)[0].Type); Assert.Equal("ByteString", result.DataType); } public async Task NodeReadStaticArrayXmlElementValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10315"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Value); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.True(result.Value.IsListOfValues, $"{result.Value} is not a list."); if (result.Value.Count == 0) { return; } Assert.True(result.Value[0].IsBytes); Assert.Equal("XmlElement", result.DataType); var xml = result.Value[0].ConvertTo(); Assert.NotNull(xml); } public async Task NodeReadStaticArrayNodeIdValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10316"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Value); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.True(result.Value.IsListOfValues, $"{result.Value} is not a list."); if (result.Value.Count == 0) { return; } Assert.True(result.Value[0].IsString, $"{result.Value[0]} is not a string."); Assert.Equal("NodeId", result.DataType); } public async Task NodeReadStaticArrayExpandedNodeIdValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10317"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Value); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.True(result.Value.IsListOfValues, $"{result.Value} is not a list."); if (result.Value.Count == 0) { return; } Assert.True(result.Value[0].IsString, $"{result.Value[0]} is not a string."); Assert.Equal("ExpandedNodeId", result.DataType); } public async Task NodeReadStaticArrayQualifiedNameValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10318"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Value); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.True(result.Value.IsListOfValues, $"{result.Value} is not a list."); if (result.Value.Count == 0) { return; } Assert.True(result.Value[0].IsString, $"{result.Value[0]} is not a string."); Assert.Equal("QualifiedName", result.DataType); } public async Task NodeReadStaticArrayLocalizedTextValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10319"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Value); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.True(result.Value.IsListOfValues, $"{result.Value} is not a list."); if (result.Value.Count == 0) { return; } Assert.True(result.Value[0].IsObject, $"{result.Value[0]} is not an object."); Assert.Equal("LocalizedText", result.DataType); } public async Task NodeReadStaticArrayStatusCodeValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10320"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Value); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.True(result.Value.IsListOfValues, $"{result.Value} is not a list."); if (result.Value.Count == 0) { return; } Assert.True( result.Value[0].IsObject || result.Value[0].IsInteger, $"{result.Value[0]} is not a integer or object."); Assert.Equal("StatusCode", result.DataType); } public async Task NodeReadStaticArrayVariantValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10321"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Value); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.True(result.Value.IsListOfValues, $"{result.Value} is not a list."); } public async Task NodeReadStaticArrayEnumerationValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10322"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Value); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.True(result.Value.IsListOfValues, $"{result.Value} is not a list."); if (result.Value.Count == 0) { return; } Assert.True(result.Value[0].IsInteger, $"{result.Value[0]} is not an integer."); Assert.Equal("Int32", result.DataType); } public async Task NodeReadStaticArrayStructureValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10323"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Value); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.True(result.Value.IsListOfValues, $"{result.Value} is not a list."); if (result.Value.Count == 0) { return; } Assert.True(result.Value[0].IsObject, $"{result.Value[0]} is not an object."); // TODO: Assert.Equal(VariantValueType.Bytes, (result.Value)[0].Type); Assert.Equal("ExtensionObject", result.DataType); } public async Task NodeReadStaticArrayNumberValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10324"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Value); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.True(result.Value.IsArray, $"Not an array {result.Value}"); if (result.Value.Count == 0) { return; } Assert.True(result.Value[0].IsDouble || result.Value[0].IsDecimal, $"Not a number {result.Value[0]}"); } public async Task NodeReadStaticArrayIntegerValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10325"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Value); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.True(result.Value.IsListOfValues, $"{result.Value} is not a list."); if (result.Value.Count == 0) { return; } Assert.True(result.Value[0].IsInteger, $"{result.Value[0]} is not an integer."); } public async Task NodeReadStaticArrayUIntegerValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10326"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Value); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.True(result.Value.IsArray, $"Not an array {result.Value}"); if (result.Value.Count == 0) { return; } Assert.True(result.Value[0].IsInteger, $"{result.Value[0]} is not an integer."); } /// /// Helper to compare equal value /// /// /// private static void AssertEqualValue(VariantValue? expected, VariantValue? value) { Assert.True(VariantValue.DeepEquals(expected, value), $"Expected: {expected} != Actual: {value} "); } private readonly T _connection; private readonly Func> _readExpected; private readonly DefaultJsonSerializer _serializer; private readonly Func> _services; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/ReadScalarValueTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Json; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using System.Xml; using Xunit; public class ReadScalarValueTests { /// /// Create node services tests /// /// /// /// public ReadScalarValueTests(Func> services, T connection, Func> readExpected) { _services = services; _connection = connection; _serializer = new DefaultJsonSerializer(); _readExpected = readExpected; } public async Task NodeReadAllStaticScalarVariableNodeClassTest1Async(CancellationToken ct = default) { var browser = _services(); const Opc.Ua.NodeClass expected = Opc.Ua.NodeClass.Variable; var attributes = new List(); for (var i = 10216; i < 10243; i++) { attributes.Add(new AttributeReadRequestModel { Attribute = NodeAttribute.NodeClass, NodeId = "http://test.org/UA/Data/#i=" + i }); } // Act var result = await browser.ReadAsync(_connection, new ReadRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { AuditId = nameof(NodeReadAllStaticScalarVariableNodeClassTest1Async), TimeStamp = DateTime.Now } }, Attributes = attributes }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Results); Assert.Equal(attributes.Count, result.Results.Count); Assert.All(result.Results, r => Assert.Null(r.ErrorInfo)); Assert.All(result.Results, r => Assert.Equal((int)expected, (int)r.Value)); } public async Task NodeReadAllStaticScalarVariableAccessLevelTest1Async(CancellationToken ct = default) { var browser = _services(); const byte expected = Opc.Ua.AccessLevels.CurrentReadOrWrite; var attributes = new List(); for (var i = 10216; i < 10243; i++) { attributes.Add(new AttributeReadRequestModel { Attribute = NodeAttribute.AccessLevel, NodeId = "http://test.org/UA/Data/#i=" + i }); } // Act var result = await browser.ReadAsync(_connection, new ReadRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { AuditId = nameof(NodeReadAllStaticScalarVariableAccessLevelTest1Async), TimeStamp = DateTime.Now } }, Attributes = attributes }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Results); Assert.Equal(attributes.Count, result.Results.Count); Assert.All(result.Results, r => Assert.Null(r.ErrorInfo)); Assert.All(result.Results, r => Assert.Equal(expected, (int)r.Value)); } public async Task NodeReadAllStaticScalarVariableWriteMaskTest1Async(CancellationToken ct = default) { var browser = _services(); var attributes = new List(); for (var i = 10216; i < 10243; i++) { attributes.Add(new AttributeReadRequestModel { Attribute = NodeAttribute.WriteMask, NodeId = "http://test.org/UA/Data/#i=" + i }); } // Act var result = await browser.ReadAsync(_connection, new ReadRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { AuditId = nameof(NodeReadAllStaticScalarVariableWriteMaskTest1Async), TimeStamp = DateTime.Now } }, Attributes = attributes }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Results); Assert.Equal(attributes.Count, result.Results.Count); Assert.All(result.Results, r => Assert.Null(r.ErrorInfo)); Assert.All(result.Results, r => Assert.Equal(0, (int)r.Value)); } public async Task NodeReadAllStaticScalarVariableWriteMaskTest2Async(CancellationToken ct = default) { var browser = _services(); var attributes = new List(); for (var i = 10216; i < 10243; i++) { attributes.Add(new AttributeReadRequestModel { Attribute = NodeAttribute.WriteMask, NodeId = "http://test.org/UA/Data/#i=10216" }); } // Act var result = await browser.ReadAsync(_connection, new ReadRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { AuditId = nameof(NodeReadAllStaticScalarVariableWriteMaskTest2Async), TimeStamp = DateTime.Now } }, Attributes = attributes }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.Results); Assert.Equal(attributes.Count, result.Results.Count); Assert.All(result.Results, r => Assert.Null(r.ErrorInfo)); Assert.All(result.Results, r => Assert.Equal(0, (int)r.Value)); } public async Task NodeReadStaticScalarBooleanValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10216"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { AuditId = nameof(NodeReadStaticScalarBooleanValueVariableTestAsync), TimeStamp = DateTime.Now } }, NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); Assert.NotNull(result.Value); Assert.True(result.Value.IsBoolean, $"{result.Value} is not a boolean."); Assert.True(VariantValue.DeepEquals(expected, result.Value), $"Expected: {expected} != Actual: {result.Value}"); Assert.Equal("Boolean", result.DataType); } public async Task NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest1Async(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10159"; // Scalar var path = new[] { ".http://test.org/UA/Data/#BooleanValue" }; var expected = await _readExpected(_connection, "http://test.org/UA/Data/#i=10216", _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { AuditId = nameof(NodeReadStaticScalarBooleanValueVariableTestAsync), TimeStamp = DateTime.Now } }, NodeId = node, BrowsePath = path }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); Assert.NotNull(result.Value); Assert.True(result.Value.IsBoolean, $"{result.Value} is not a boolean."); AssertEqualValue(expected, result.Value); Assert.Equal("Boolean", result.DataType); } public async Task NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest2Async(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10159"; // Scalar var path = new[] { "http://test.org/UA/Data/#BooleanValue" }; var expected = await _readExpected(_connection, "http://test.org/UA/Data/#i=10216", _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { AuditId = nameof(NodeReadStaticScalarBooleanValueVariableTestAsync), TimeStamp = DateTime.Now } }, NodeId = node, BrowsePath = path }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); Assert.NotNull(result.Value); Assert.True(result.Value.IsBoolean, $"{result.Value} is not a boolean."); AssertEqualValue(expected, result.Value); Assert.Equal("Boolean", result.DataType); } public async Task NodeReadStaticScalarBooleanValueVariableWithBrowsePathTest3Async(CancellationToken ct = default) { var browser = _services(); var path = new[] { "Objects", "http://test.org/UA/Data/#Data", "http://test.org/UA/Data/#Static", "http://test.org/UA/Data/#Scalar", "http://test.org/UA/Data/#BooleanValue" }; var expected = await _readExpected(_connection, "http://test.org/UA/Data/#i=10216", _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { AuditId = nameof(NodeReadStaticScalarBooleanValueVariableTestAsync), TimeStamp = DateTime.Now } }, BrowsePath = path }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); Assert.NotNull(result.Value); Assert.True(result.Value.IsBoolean, $"{result.Value} is not a boolean."); AssertEqualValue(expected, result.Value); Assert.Equal("Boolean", result.DataType); } public async Task NodeReadStaticScalarSByteValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10217"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); Assert.NotNull(result.Value); Assert.True(result.Value.IsInteger, $"{result.Value} is not an integer."); AssertEqualValue(expected, result.Value); Assert.Equal("SByte", result.DataType); } public async Task NodeReadStaticScalarByteValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10218"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); Assert.NotNull(result.Value); Assert.True(result.Value.IsInteger, $"{result.Value} is not an integer."); AssertEqualValue(expected, result.Value); Assert.Equal("Byte", result.DataType); } public async Task NodeReadStaticScalarInt16ValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10219"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); Assert.NotNull(result.Value); Assert.True(result.Value.IsInteger, $"{result.Value} is not an integer."); AssertEqualValue(expected, result.Value); Assert.Equal("Int16", result.DataType); } public async Task NodeReadStaticScalarUInt16ValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10220"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { AuditId = nameof(NodeReadStaticScalarUInt16ValueVariableTestAsync), TimeStamp = DateTime.Now } }, NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); Assert.NotNull(result.Value); Assert.True(result.Value.IsInteger, $"{result.Value} is not an integer."); AssertEqualValue(expected, result.Value); Assert.Equal("UInt16", result.DataType); } public async Task NodeReadStaticScalarInt32ValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10221"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); Assert.NotNull(result.Value); Assert.True(result.Value.IsInteger, $"{result.Value} is not an integer."); AssertEqualValue(expected, result.Value); Assert.Equal("Int32", result.DataType); } public async Task NodeReadStaticScalarUInt32ValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10222"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.Value); Assert.NotNull(result.ServerTimestamp); Assert.True(result.Value.IsInteger, $"{result.Value} is not an integer."); AssertEqualValue(expected, result.Value); Assert.Equal("UInt32", result.DataType); } public async Task NodeReadStaticScalarInt64ValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10223"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); Assert.NotNull(result.Value); Assert.True(result.Value.IsInteger, $"{result.Value} is not an integer."); AssertEqualValue(expected, result.Value); Assert.Equal("Int64", result.DataType); } public async Task NodeReadStaticScalarUInt64ValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10224"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); Assert.NotNull(result.Value); Assert.True(result.Value.IsInteger, $"{result.Value} is not an integer."); AssertEqualValue(expected, result.Value); Assert.Equal("UInt64", result.DataType); } public async Task NodeReadStaticScalarFloatValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10225"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); Assert.NotNull(result.Value); Assert.True(result.Value.IsFloat); AssertEqualValue(expected, result.Value); Assert.Equal("Float", result.DataType); } public async Task NodeReadStaticScalarDoubleValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10226"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); Assert.NotNull(result.Value); Assert.True(result.Value.IsDouble); AssertEqualValue(expected, result.Value); Assert.Equal("Double", result.DataType); } public async Task NodeReadStaticScalarStringValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10227"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); Assert.NotNull(result.Value); Assert.True(result.Value.IsString, $"{result.Value} is not a string."); AssertEqualValue(expected, result.Value); Assert.Equal("String", result.DataType); } public async Task NodeReadStaticScalarDateTimeValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10228"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); Assert.NotNull(result.Value); Assert.True(result.Value.IsDateTime); AssertEqualValue(expected, result.Value); Assert.Equal("DateTime", result.DataType); } public async Task NodeReadStaticScalarGuidValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10229"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); Assert.NotNull(result.Value); Assert.True(result.Value.IsGuid); AssertEqualValue(expected, result.Value); Assert.Equal("Guid", result.DataType); } public async Task NodeReadStaticScalarByteStringValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10230"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.Equal("ByteString", result.DataType); // TODO : Assert.Equal(VariantValueType.Bytes, result.Value.Type); // TODO : Assert.Equal(VariantValueType.String, result.Value.Type); } public async Task NodeReadStaticScalarXmlElementValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10231"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); Assert.NotNull(result.Value); Assert.True(result.Value.IsBytes); AssertEqualValue(expected, result.Value); Assert.Equal("XmlElement", result.DataType); var xml = result.Value.ConvertTo(); Assert.NotNull(xml); } public async Task NodeReadStaticScalarNodeIdValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10232"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert // Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); Assert.NotNull(result.Value); Assert.True(result.Value.IsString, $"{result.Value} is not a string."); AssertEqualValue(expected, result.Value); Assert.Equal("NodeId", result.DataType); } public async Task NodeReadStaticScalarExpandedNodeIdValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10233"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); Assert.NotNull(result.Value); Assert.True(result.Value.IsString, $"{result.Value} is not a string."); AssertEqualValue(expected, result.Value); Assert.Equal("ExpandedNodeId", result.DataType); } public async Task NodeReadStaticScalarQualifiedNameValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10234"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); Assert.NotNull(result.Value); Assert.True(result.Value.IsString, $"{result.Value} is not a string."); AssertEqualValue(expected, result.Value); Assert.Equal("QualifiedName", result.DataType); } public async Task NodeReadStaticScalarLocalizedTextValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10235"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); Assert.NotNull(result.Value); Assert.True(result.Value.IsObject, $"{result.Value} is not an object."); AssertEqualValue(expected, result.Value); Assert.Equal("LocalizedText", result.DataType); } public async Task NodeReadStaticScalarStatusCodeValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10236"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); Assert.NotNull(result.Value); Assert.True( result.Value.IsObject || result.Value.IsInteger); AssertEqualValue(expected, result.Value); Assert.Equal("StatusCode", result.DataType); } public async Task NodeReadStaticScalarVariantValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10237"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); // Assert.Equal("BaseDataType", result.DataType); } public async Task NodeReadStaticScalarEnumerationValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10238"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); Assert.NotNull(result.Value); Assert.True(result.Value.IsInteger, $"{result.Value} is not an integer."); AssertEqualValue(expected, result.Value); // TODO: Assert.Equal("Enumeration", result.DataType); Assert.Equal("Int32", result.DataType); } public async Task NodeReadStaticScalarStructuredValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10239"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); Assert.True(result.Value!.IsObject); AssertEqualValue(expected, result.Value); Assert.Equal("ExtensionObject", result.DataType); // TODO: Assert.Equal("Structure", result.DataType); } public async Task NodeReadStaticScalarNumberValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10240"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); // Assert.Equal("Number", result.DataType); } public async Task NodeReadStaticScalarIntegerValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10241"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); // Assert.Equal("Integer", result.DataType); } public async Task NodeReadStaticScalarUIntegerValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10242"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); // Assert.Equal("UInteger", result.DataType); } public async Task NodeReadDataAccessMeasurementFloatValueTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "nsu=DataAccess;s=1:FC1001?Measurement"; var expected = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); // Act var result = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { NodeId = node }, ct).ConfigureAwait(false); // Assert Assert.NotNull(result); Assert.NotNull(result.SourceTimestamp); Assert.NotNull(result.ServerTimestamp); AssertEqualValue(expected, result.Value); Assert.Equal("Float", result.DataType); } public async Task NodeReadDiagnosticsNoneTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { AuditId = nameof(NodeReadDiagnosticsNoneTestAsync), Level = DiagnosticsLevel.None } }, NodeId = "http://opcfoundation.org/UA/Boiler/#s=unknown" }, ct).ConfigureAwait(false); // Assert Assert.NotNull(results.ErrorInfo); Assert.Null(results.ErrorInfo.NamespaceUri); Assert.Null(results.ErrorInfo.Locale); Assert.Null(results.ErrorInfo.Inner); Assert.Null(results.ErrorInfo.AdditionalInfo); Assert.Null(results.ErrorInfo.ErrorMessage); Assert.NotNull(results.ErrorInfo.SymbolicId); Assert.Equal(Opc.Ua.StatusCodes.BadNodeIdUnknown, results.ErrorInfo.StatusCode); } public async Task NodeReadDiagnosticsStatusTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { AuditId = nameof(NodeReadDiagnosticsStatusTestAsync), TimeStamp = DateTime.Now } }, NodeId = "http://opcfoundation.org/UA/Boiler/#s=unknown" }, ct).ConfigureAwait(false); // Assert Assert.NotNull(results.ErrorInfo); Assert.Null(results.ErrorInfo.NamespaceUri); Assert.Equal("en-US", results.ErrorInfo.Locale); Assert.Null(results.ErrorInfo.Inner); Assert.Null(results.ErrorInfo.AdditionalInfo); Assert.Equal("BadNodeIdUnknown", results.ErrorInfo.ErrorMessage); Assert.NotNull(results.ErrorInfo.SymbolicId); Assert.Equal(Opc.Ua.StatusCodes.BadNodeIdUnknown, results.ErrorInfo.StatusCode); } public async Task NodeReadDiagnosticsDebugTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { AuditId = nameof(NodeReadDiagnosticsDebugTestAsync), Level = DiagnosticsLevel.Information } }, NodeId = "http://opcfoundation.org/UA/Boiler/#s=unknown" }, ct).ConfigureAwait(false); // Assert Assert.NotNull(results.ErrorInfo); Assert.Null(results.ErrorInfo.NamespaceUri); Assert.Equal("en-US", results.ErrorInfo.Locale); Assert.Null(results.ErrorInfo.Inner); Assert.Null(results.ErrorInfo.AdditionalInfo); Assert.Equal("BadNodeIdUnknown", results.ErrorInfo.ErrorMessage); Assert.NotNull(results.ErrorInfo.SymbolicId); Assert.Equal(Opc.Ua.StatusCodes.BadNodeIdUnknown, results.ErrorInfo.StatusCode); } public async Task NodeReadDiagnosticsVerboseTestAsync(CancellationToken ct = default) { var browser = _services(); // Act var results = await browser.ValueReadAsync(_connection, new ValueReadRequestModel { Header = new RequestHeaderModel { Diagnostics = new DiagnosticsModel { AuditId = nameof(NodeReadDiagnosticsVerboseTestAsync), Level = DiagnosticsLevel.Verbose } }, NodeId = "http://opcfoundation.org/UA/Boiler/#s=unknown" }, ct).ConfigureAwait(false); // Assert Assert.NotNull(results.ErrorInfo); Assert.Null(results.ErrorInfo.NamespaceUri); Assert.Equal("en-US", results.ErrorInfo.Locale); Assert.Null(results.ErrorInfo.Inner); Assert.Null(results.ErrorInfo.AdditionalInfo); Assert.Equal("BadNodeIdUnknown", results.ErrorInfo.ErrorMessage); Assert.NotNull(results.ErrorInfo.SymbolicId); Assert.Equal(Opc.Ua.StatusCodes.BadNodeIdUnknown, results.ErrorInfo.StatusCode); } /// /// Helper to compare equal value /// /// /// private static void AssertEqualValue(VariantValue? expected, VariantValue? value) { Assert.True(VariantValue.DeepEquals(expected, value), $"Expected: {expected} != Actual: {value}"); } private readonly T _connection; private readonly DefaultJsonSerializer _serializer; private readonly Func> _readExpected; private readonly Func> _services; } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/WriteArrayValueTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Models; using Azure.IIoT.OpcUa.Encoders; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Json; using Opc.Ua; using System; using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Xml; using Xunit; public class WriteArrayValueTests { /// /// Create node services tests /// /// /// /// public WriteArrayValueTests(Func> services, T connection, Func> readExpected) { _services = services; _connection = connection; _serializer = new DefaultJsonSerializer(); _readExpected = readExpected; } public async Task NodeWriteStaticArrayBooleanValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10300"; var expected = _serializer.Parse( "[true,true,true,false,false,false,true,true,true,false,true," + "false,false,false,true,false,false,false,false,true,false,true," + "true,true,true,false]"); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "Boolean" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArraySByteValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10301"; var expected = _serializer.Parse( "[-94,94,62,22,-50,36,105,103,-60,56,-102,-14,-59,-83,119,-101," + "-39,85,-9,-14,-7,-100,64,122,-107,-61,13,-10,-19,81,-52,57," + "-32,-90,27,-128,92,44,-32,13,-93,-10,46,9,-38,55,116,-11,-43," + "63,-45,-103,2]"); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "SByte" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayByteValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10302"; var expected = _serializer.Parse( "\"jgYexIAKF3N6c2tgEh6R9j+tdOlOAm43n15OFyGtfjI2VhgVYpis1fYvfL" + "qdeiRVY94AJSUZ\""); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "ByteString" // TODO: Assert.Equal("Byte", result.DataType); }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayInt16ValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10303"; var expected = _serializer.FromObject(_generator.GetRandomArray()); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "Int16" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayUInt16ValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10304"; var expected = _serializer.FromObject(_generator.GetRandomArray()); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "UInt16" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayInt32ValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10305"; var expected = _serializer.FromObject(_generator.GetRandomArray()); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "Int32" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayUInt32ValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10306"; var expected = _serializer.FromObject(_generator.GetRandomArray()); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "UInt32" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayInt64ValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10307"; var expected = _serializer.FromObject(_generator.GetRandomArray()); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "Int64" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayUInt64ValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10308"; var expected = _serializer.FromObject(_generator.GetRandomArray()); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "UInt64" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayFloatValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10309"; var expected = _serializer.FromObject(new float[] { float.NaN, 0.0f, 1.0f, 0.0034f, 2543.354f, float.MaxValue, float.MinValue }); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "Float" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayDoubleValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10310"; var expected = _serializer.FromObject(new double[] { -5.0, 1.0, 0.0, 6.0, 10000.1, double.MinValue, double.MaxValue, double.PositiveInfinity, double.NegativeInfinity, double.NaN }); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "Double" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayStringValueVariableTest1Async(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10311"; var expected = _serializer.FromObject(new string[] { "test", "test2", "test3", "test4,", "Test", "TEST" }); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "String" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayStringValueVariableTest2Async(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10311"; var expected = _serializer.FromObject(_generator.GetRandomArray()); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "String" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayDateTimeValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10312"; var expected = _serializer.FromObject(_generator.GetRandomArray()); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "DateTime" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayGuidValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10313"; var expected = _serializer.FromObject(_generator.GetRandomArray()); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "Guid" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayByteStringValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10314"; var expected = _serializer.Parse( "[\"y5rM6KSrJ9+U0zDRyN8nPrLz4zyKydoagl0A2Sz0XTeJ0GevE2/tFCMCp" + "Fj9IA7zLA==\",\"OLyUL7UBwLFmRqtOs6B1+Ef3eHgqQgbPGIglgRxhTw2t" + "uLugo1obZe5hCadp1E4E4wTZFnuzSPa2xRYs3D+UBfeeoQ==\",\"5NVV7dw" + "Sicg5X2ZEOiCeGIc4kflvxeneQ+6Ir80Er8oz\",\"Hw2v7DpoKn+8V17S8r" + "uhfH2+DKeLH+t3qe2K2vs0r5sQ5wGQaZr+Kc/vCJJ/cPvMDlCG8b6LxwAhOE" + "JM3U+DiKfDwQu6EBPiv+PYmxZZ9znxvcyrrb3dhR8AbjFXsUt/bIDq\",\"r" + "vAR/TyjMtuzK+nIQAlbIIPY2urlPOy6oeKLDpdZL5ZuO4oB\",\"zm4JiwLS" + "9Bam8E5WK/uTpQDWcgRXW1oYI0Na+1NaBX5adLVp0F7javej+/I8uGxdm/Ft" + "ZBj9VHMU8Ge+ePjDTOvP+7dGKtWi8ggMtGBo3GvX/F9h7KBlXSBBVN/2JQ==" + "\",\"/9+uB2y8tRdxG8pyEPCfEqwU++d7mGFfSmmelgTV9azNFg3VsWFvryH" + "l7kUhLlVsgC+oyvo+dmZ9TrwCHR4SmyYepfrjymFLpUzFlqocPhwUMRbVLSq" + "xj5+nWGKkbJED0lIf\",\"iVuJts1dJa144LxhEKDu6wc9bvttFlo8cv6mOb" + "rCw1f8O5O5qGAHzwUDFr/q9lIEfqX7leQjlXIATUPPtuzzthxk\",\"1A00Q" + "6c2nvZp/5pRe6yiuxXGLnPYpiC5Wxw4GRkQYKOGkn32SWJUX0UtK3Nl+8giF" + "DHe7+3xjC7se+eK/YXcWZ/3y+kvq3Gycg==\",\"Lap7rVNfVBUF6DJwtZQG" + "TgnNeslhv1DR024w3/Novyt9Hg==\",\"4bM/KIg26ID0Jy9BNuPgoqQ4qG5" + "uWqnZ5S51IZwoBvKX0SSbyqXyk3g+W6qkLA==\",\"+xLGG/PUsFSGCWVCWc" + "HG48wgPKpkvkTX/kUV9S/+/jW4NHkO1g0THuZ8npFk\",\"mNGyWo+KZ4GVP" + "c7uHK2+uyWICy+JJUe3Db4MHsPoILNznK1EQ9VudM03njtA6PFmXytXFYY02" + "HOJ+k3Rfg==\",\"vawdGnp/AHp4UBmWYlKGDHYkzKa+mJEKLD7DObpIh532" + "g3nyHiVtcWXkswf879KF7H2DKQTXiyUbEu48vMbAL8h7oN7ZlO1QtltA2eSK" + "Dj1rPUw8xA==\",\"mR74U9YMNzG1nySDPoBO9KtYkDNyqJc=\",\"QJEEsd" + "B+eYNrauKC5Ya94BmEpqG1YUuN7neR9KuR6/CHRxJFCIZhNiWgGNOdzA==\"" + ",\"JZqvGe4C9fzfRXbCWOyF19o=\",\"8g==\",\"nnN42JMjb3sUSXjwImh" + "sWfx3/e2RSzMAkcMISqDIPVSr0XGxItaGy5N655bMhqDwgCvbYoEEaVNAd0f" + "PGiXaSwsjRFD3uzYl8DJaFmOcMwsiGMl07dvTpmcecKqPt7Bt\",\"m4upQV" + "D5xfS2ck+qUu+kRDutAltmXjBPnejZSoyVOYHsd8gRicnSHgR/NmmD/BUuzG" + "ZUCa4SOTxbWQ==\",\"ZyB6aCA4zr3bJ5O6cdrjVuYoxsyh06p+JUEv0to+i" + "7YvJmv+ihcWMLQ/Ogc5rOIvy7tSFJSNApN1/EPfCPzinZvciktv5cw=\",\"" + "EZYXYpmiRHlfAAcf63YhoiPXiI7TNyi4XJ1rXCGWwOXvgwL+daD607fJfwj1" + "w7Eku+g=\",\"l1w++9ptXwb8NuhYyEAhMGd0IyyD3LXWCbcgw5jrR6E4byi" + "IsIcnkBaa/pzOcbfH05NJsJe7o7un\",\"8SNNm20Q70cfWBiYf+BMkxbp3h" + "gHmP9Y7wShlgl9y2zhSZUEQnos7ayHUl6vOxRpZAOlut2PX1kk\",\"rGlvW" + "T2ijau3NUpIUZu98GyARqCos/A4MQXXEI9S6TzgTM7DflJJr9EEhN4eHLIJ/" + "ewi3hKDTfh5Nig3ynwbZUwOZwTN+nEZNpbPoy8RGQ==\",\"U84Toi8KKV3+" + "1UlHKhLlVOgfkhC0rjwDewmofLOqyWcdE+T8aHg1QeQKBfewKe4ksXu6D34J" + "YKSRECcmYqypVAzhKhct6etw6VErqalFUlEag8s477rpFLJAalg=\",\"D94" + "4YbDrzv/X9sePSiUt3rb7TL7WDN/hcWVS+BZk7X6THtpy8w==\",\"+FmDUU" + "KNA6illLw1/EQdmnsD/1bvS5nW6XIISPwrS7rqbQLyOoTJUt3JwL084GipYf" + "mj13OcWa3ArWg=\",\"hLuseUkBS45CK2D2Oq14JovbmQgKX+cCiHNHTRQ=\"" + ",\"MYwc+M0iHEZ0OpXZ\",\"NZisnMUkMiLlE1/FJNOp8dW6/Xnt+dPaQd9" + "VCURnXnMw+LFp29aBKeEyTHi8MqlPclSegJhgeTzF0lvmzindfbTrlSshPxb" + "+ONOXuqxaHQ42Bpbvyd4=\",\"0H91pAh7m1q4Vc/E0Z1+LTM+n0fEyL+Par" + "VMsMiS7bTWEMSsrJsOg51432TdlkxwuNhjsSmW\",\"CL/lOVMu6pIlZxvtw" + "dnRgJgwHKpM6Vqy1Gjb+O8vPIo/+bzsx2G6VLLmufzCqYuX5ljLgQ3syh5kM" + "mXqU/Ki9iuQrccc5Lg2dcf3ZS9d8CrdQxGXZLp8\",\"Lp2IlfvQAb9DwtEx" + "+8N7AZ+UC0X0ZO8GQToMD+ELknEUWZl+XCM7pcY3ImyMvy8ayBD3z642Xsmu" + "gVPAw/HeNzBf\",\"oSn8pHxZZn69QoJ5gQvxR9ATwsLd+9DQ28964dVY6js" + "soo3xy2t7dki4oYcrB9K10qkNJG6dP6ZZLMmt3oWpZFdGTd59AHxl\",\"S3" + "klWUik0/3FDytKxs2PY+eXnqLNmMIOPC/kuvM30S2oiyIjGkwQh/WwGHZ9Gp" + "F5vnuVaN0=\",\"yrO3Fh0ZwBkJjT3+oQ==\",\"qmtJm4cWrB1/TJEinWv8" + "d6FoT+XBb2wDL/bH26aLOX94Vs5TMfrhxxasM2qF+nxUHZLs1K68eTr+RmyQ" + "TtF39BMRqkac\",\"RqeHiM8UPAJ+NHpzvhSeZNG73ZNU645ReEU1Pldz\"," + "\"NrdzS0RNJu1l/vzHOBbbEmNVrkDuaQlUWhg1D4re/aoK40S7SshaF6rOd5" + "VYI1Y7nTLS6akzYsyuH/EsFxZjhgFRvVTSH8g=\",\"+5eVIPFz+zbC+nJXD" + "BQB1oF3DCvXLf+Ua/GUB2YBaX1qN+0RnkLbOiO6ah2kC3rsUOY=\",\"WhOd" + "w82YAbQA3/TQwJH07dQm7zg/m9EHHcPh7192p7Z/Lg5qzXQfeZ2N21su6amM" + "\",\"HqbGYK6Uv0GVpQq2EVSJOD1Rkg==\",\"ih9fBnabscB22DMaVT9B0O" + "BW0JlPKDfPFcKLOFEi8JgXCSX+RsDpE+L/yr1y8GHSErlY54D4M2HokPCzD3" + "huVOebA0sZQ4kgbLy3\",\"Xno=\",\"JWG4JZjKCRce1sQWts82A2mQdtXW" + "7Ba5zzA3esRB4wNtM8pSV1LWit6E5HVVLdJQNrhNv+elhjhL/lZnko9S3PLA" + "qIME5KwWuuz3UgihZKJd50ML\",\"JBvIrZIHWPxu904xB4KUhU9LUgw2Bfs" + "=\",\"NDCpmrMJq0tH6M6k39Vy3FMaS/SoIAAezx0Om/H+vR4gG3hiXb5IZE" + "wD6R+08KV52XW4HLoHBRMvisqW+w9ZSCqvhMQ=\",\"EH+U0eanpDbhat93l" + "cF8RaFkGBVlMtLzsWk8qqH0BGvhHMn1I0rTX2DdTiDrH2VN3QKJS2uu996so" + "R98avqV7WZzlnj4hiFWkLm1iOOyB5ID782ea7kAMiTrSIIrV/RmR2C5\",\"" + "iexVVuEyurL5b/r6mYx4ey33gq1zY1QNPZ8rOcROQIP4jgkWmna8OP5NObXx" + "Tuie3nk5T94MBSWYRxlBBoHuqi53AQqDYeE=\",\"OkmuJSqeHA==\",\"to" + "1aSw==\",\"8aTsieN+Ulx7Mn1ejoZ6TN0afZeCFJVd3/v5KyqLeSajlD3SF" + "YGg449avxcxx5sYoqLYct2zk9wPjqnnhCcy8LhWu/lJpzZceg==\",\"CCdV" + "fSwYYOGIh7IHSe8BYMOH17heaCfPXtsLoc77a3z4Q6prhpFhkYejnqo9sQzL" + "+Ojjr4TCOqD/hh9RDL4SjRw2DgVEldoyJUYwu8l9ka3OQKg=\",\"F7z3NQg" + "KbAByEITJ\",\"EI4HogeGYw6xiT6Rf9aC9HGDzBUsdl8/2Q==\",\"OinZv" + "xXCZiu574oKx7lF12UzuKOJM+kMAI23s2OZLg==\",\"yQlMOjTydHwrUx2T" + "ame8EtBUESyGNXMGP82/\",\"CrLHH8DBQb1tCqJzvjx4NRZWoZjRpOMOiAJ" + "BlJVF+2cy7HF4i/7SqCb+pcWynm1KvA==\",\"7+grJrVlzrmXvoCtJygPO0" + "DSygCpGIT5ctL/Hlw=\",\"lPfXV1UTOws2DKnSZxQoeNd9tnZdm4C8lNdjM" + "rPjZrBcrSmI1c/S/P81m71W17Fw0Pn7gmjmi/l2GsN+rwhXU6X5dQ==\",\"" + "6p+jB6q5dij/wmW8JvNhuufkSHYhLxK6DFRN991HGF1h94UxVvPXrm9i+bS0" + "Ble7p51rwbD/l7qN6Ps=\",\"bH9LuKoIWi5uMGP0DJkHvjZdBQb8kU8/3Fa" + "sYl/LpG74gEHwF0EKrKspTXc6d7QX99mEL+L1WtsvC9tTW/jOo4v0/IxXF6f" + "0U1la0kTYBWWilWo=\",\"RnWMAiVmwAtltlGzWqrrRXoov+AxkNyJmoeWVg" + "Z2scWNSFwWaPlm8VabjpwIp3ea7L/qedaJVLaZA2idz2kF7wU=\",\"JRJN1" + "d2Awc2K\",\"AT+A8xD8aUaMN+8D8w==\",\"fWWRyCHslp+WfYFlTBfiabc" + "I/760WYJ1jdM=\",\"vmLNmyEfp1d37/msnf9iqANxqq9SZCKA5gQ08STjHD" + "pO7dg8yeFfRaW/anm+W2K/UbB+A+MjrVk/TbQd6rUzlNO+XrAnJd8i\",\"Z" + "AqS+qjBiqF1oHNkGFcqP379eyxBWu+L1aYA/bKXK9Bc8n4YGl+WjCl7dRXAM" + "LpmM3CoKGT1zwkaBg==\",\"AsGN7910ogcm2RIkH2bvA8bl2suk65nJQe8D" + "bGcidP0TOpTKnIuXoR0plI0hS4jCdPIJJEA7gBYnw67ucTWfA2UUEeXRJGY6" + "TTmte1cMqPZmQPd1GU+92Ll9otjdqS/niZAn\",\"OqLwT4vP1gaOBL8bG7e" + "HMD4q6hVWOCtTgY1cpAnF8sY=\",\"mrvDUKfpSXm2SbW+h70lIf+pXqYStg" + "F3nM79cjL8yBH4NoD7w+CWQKGbn+52lfrQNoIKG5Mg0uS6TLPZ7NZHuYGjxl" + "E9KV4eEx4EdhcSAAc=\",\"LTyv8qx+2GSbQXYsvFTKVOVt0s+pkgwk6wh1G" + "1vNp0ysBr+amMfUJe3soejn8VfJOiIxpS04KpovigakCLwIzg==\",\"KoC1" + "lS+8Hpit\",\"vPEkPfmwq+A4mwIec9skaw==\",\"wDAdMeTSTrxxoTQKZh" + "MMgFdtqApNDPNc288zlwwM2nDErl1okK8=\",\"H9aBiA921dKI9Z0cbntgw" + "LQ8wFUUn7avZMfERri2o/CnlQ==\",\"NMuD5OUG/auibvBr9GTuqSzPWsR/" + "INEkR7KPGtJRrXXY8iz0MFjbTxb0FEB0W9DhyQ13IUzRChP6X5wyduPYUMF6" + "kwI4+njU8wutiwyRsA==\",\"4a1QxNqMKQfoGPrRu6jYMhvEf/nIzqnPlKM" + "tQCM=\",\"B2iusFHIkhR1NVGMGSAApxhKM3twRxK2JBMEgTA3XujjaRCRIg" + "tXD58HTkmnPLSJzu2K4g0=\",\"Dr9W94w9xBHjPtZpqLAPboQN8yPbafnID" + "udfe7JDrHvaO1tQOyp/GkuOIxBzPpMEeWBofe/q\",\"pcaN6KTeSF6gklqP" + "bVW+M1mO2NdMRelV0FNbAg==\",\"2i6M7222iq1C2jwDL4J9GK8mr7osDu8" + "WE4Bf3TgYUIJGDMZjzp//njSFF7Oc1B3DazwgLKxHJcs/ddztVq11KQ==\"," + "\"ub0jvBpKECcQhqf2O3o+Y5xx/Pcj1v7m+iNZwhFIhxDuKeMX+QZR8hAFnM" + "F+1QT7nYq5O3gyZuK+PcH28E0Vx/+XCBGXJ2mVIArnHjo8ZyUfXiSHjkuXvA" + "==\",\"AFi7RFoBwu/UwufM8mR2ICQabktHqIHVnNeSKI45s/9MTZbOrVHGC" + "CQuZnqAWCz6rmZqMChxfFfX5qiDbplhmw7ngKTNp3LT\",\"ZiYYQgdURKqY" + "eifPg9fb0T73x6hDmorNy2uZ2IgsB/SX28JKYxXPkWTY1h85zIsQpNKOr6sq" + "EcucSnebu2sia3IzNw==\",\"FJBuKSg1RGrEa5P/4IgztZ5XSG3K9q4YnjT" + "V+LZqrAaU4/sUZGWHdeWmBzG3eLsyOGzNG+rK3R7iVYr0YEy0Wb6NavyNHw=" + "=\"]"); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "ByteString" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayXmlElementValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10315"; var expected = _serializer.FromObject(_generator.GetRandomArray()); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "XmlElement" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayNodeIdValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10316"; var expected = _serializer.Parse( "[\"s=%eb%85%b9%ec%83%89%ec%9a%a9\"," + "\"http://test.org/UA/Data//Instance#g=bc3623b6-cb5f-e6be-1c13-378f9126c663\"," + "\"http://samples.org/UA/memorybuffer#i=1556000973\"," + "\"b=728HLX82OBG556w1XptI6JmYAeS%2bs33GiJu3gjZHWRJ8o3Bct7mc3f592D8ZLQ" + "l5hMckxA%2fVWjvxQaTkfrXbco2auLoq7DHg%2byPlQNs%2brFuRPf5vIpUCp0k0ag%3d%3d\"," + "\"http://samples.org/UA/memorybuffer#b=XkiiZbF%2bdE9PmJVDyOzvGWCzlElTQbdsT%2fiYEQ%3d%3d\"," + "\"i=1137425282\"," + "\"http://opcfoundation.org/UA/Boiler/#i=781022622\"," + "\"http://opcfoundation.org/UA/Boiler//Instance#i=3738789614\"," + "\"s=%e8%9b%87\"," + "\"http://samples.org/UA/memorybuffer#s=%ec%9b%90%ec%88%ad%ec%9d%b4\"," + "\"http://opcfoundation.org/UA/Boiler/#g=63e6b815-59de-d915-7884-26527beb2666\"," + "\"http://opcfoundation.org/UA/Boiler//Instance#b=UJJxK4FZQCLL2gDeqAtnX9RHg2OUUABmSO9ltOiQe2hT\"," + "\"http://opcfoundation.org/UA/Boiler//Instance#b=pI1kCZ03Sv93pn1HE4tSHt%2btvg%3d%3d\"," + "\"http://test.org/UA/Data/#i=4103267082\"," + "\"http://test.org/UA/Data/#s=%e9%bb%91%e8%89%b2\"," + "\"http://opcfoundation.org/UA/Diagnostics#i=1186710474\"," + "\"http://opcfoundation.org/UA/Boiler//Instance#b=XQUB7qFxHaBdPl2JpQtAEpqq0" + "hUQ%2fQ%2bf4BqefFDPCzpl52D6kBtBINbr2%2fwCDebTirEgnBFktV%2f2YQ6H0qFQjTIiJL6qRoF%2baLE%2b\"," + "\"http://opcfoundation.org/UA/Diagnostics#s=%e7%b7%91%e3%83%96%e3%83%89%e3%82%a6\"," + "\"http://samples.org/UA/memorybuffer/Instance#g=296faf9f-3101-0401-2e0c-b94d359a4dca\"," + "\"http://opcfoundation.org/UA/Diagnostics#i=792930600\"," + "\"http://samples.org/UA/memorybuffer/Instance#s=%eb%b0%94%eb%82%98%eb%82%98\"," + "\"http://opcfoundation.org/UA/Boiler/#i=139672771\"," + "\"http://opcfoundation.org/UA/Diagnostics#g=22f9c2de-a88d-5342-71ae-64098bd449bd\"," + "\"http://opcfoundation.org/UA/Boiler//Instance#i=225423009\"," + "\"http://test.org/UA/Data/#b=ocMhatBmRYbobwfmxpuAAdwwhPobBGmZBlNHZv" + "9B0YYvRvlIeihSBDomVB1yFwIK2T3bfOwJxah2R9H96Gp52AtnvmDz\"," + "\"http://samples.org/UA/memorybuffer/Instance#i=56793307\"," + "\"http://test.org/UA/Data/#b=1kZSrfTPYIdPipmDIylA%2fPvHwSChwYTMoE578" + "yc5Vi82S0iXM%2fmpsVb4XxFGcGsSmptnPJYOkBXChQ2mU21fFjNqTdjhqckBHg%2fKqWFzhi%2fiaFiM0hqY" + "J7sy1a7rAg%3d%3d\"," + "\"http://samples.org/UA/memorybuffer/Instance#b=Sd3cIpMx8dJmHYZE57NO%2f97D6hXTRBk%3d\"," + "\"http://test.org/UA/Data/#g=1ad3ae1c-1c15-e1b1-0f18-96aa0c4f3766\"]"); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "NodeId" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayExpandedNodeIdValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10317"; var expected = _serializer.Parse( "[\"http://samples.org/UA/memorybuffer/Instance#i=2144658193\"," + "\"http://samples.org/UA/memorybuffer#b=c9PGBcMJ%2fXaDHbdQAdVi15q4Vd" + "F0s64Z2BzAQUguTWwH3T4OSRPSoA%2fZs0gCG%2fs8gfzkzVk8yr8krC2nSLstV" + "dBLSCSWVI2H5rTBm%2f9mFrwhhMA%3d\", " + "\"http://opcfoundation.org/UA/Boiler/#g=7e12cb12-9cea-2be5-5753-ab5e78b7d3d7\"]"); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "ExpandedNodeId" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayQualifiedNameValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10318"; var expected = _serializer.FromObject(new string[] { "http://test.org/UA/Data/#afsdff", "http://test.org/UA/Data/#tt", "http://test.org/UA/Data/#sdf", "http://test.org/UA/Data/#afsdff", "http://test.org/UA/Data/#sg", "http://test.org/UA/Data/#afsdff", "http://test.org/UA/Data/#afsdff", "http://test.org/UA/Data/#23234", "nanananana", "http://test.org/UA/Data/#afsdff", "http://test.org/UA/Data/#w", "afsdff" }); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "QualifiedName" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayLocalizedTextValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10319"; var expected = _serializer.Parse("[" + "{\"Text\":\"복숭아_ 파인애플" 황색 말 검정: 황색 고양이 자주색! 파인애플 녹색( 암소& 개 딸기 양 망고 들쭉 뱀 용> 고양이 빨간 파란 빨간@ 들쭉\",\"Locale\":\"ko\"}," + "{\"Text\":\"Бело Корова. Известка\",\"Locale\":\"ru\"}," + "{\"Text\":\"석회* 파인애플) 말= 바나나^ 양/\",\"Locale\":\"ko\"}," + "{\"Text\":\"코끼리 백색! 황색# 뱀{ 바나나? 파인애플 녹색 백색^ 빨간> 녹색&\",\"Locale\":\"ko\"}," + "{\"Text\":\"Horse? Blueberry% Pineapple Peach Red/ Banana$ Cat& Black_ Lemon Cat Purple Pig Red Horse Pineapple"\",\"Locale\":\"en-US\"}," + "{\"Text\":\"紫色^ 菠萝 柠檬 桃子 蓝色; 马= 大象 马 狗 狗( 母牛$ 绵羊. 马 鼠 马 马 草莓 柠檬* 大象 马$ 柠檬 蛇 红色 白色$ 猴子 绿色 紫色* 猪 草莓& 草莓 龙# 绿色* 蛇 葡萄\",\"Locale\":\"zh-CN\"}," + "{\"Text\":\"绿色 紫色 白色 鼠 母牛} 蓝莓* 草莓 蛇< 猴子 香蕉_ 柠檬. 猫 猫 桃子 大象 柠檬 葡萄 桃子" 绿色 菠萝? 桃子\",\"Locale\":\"zh-CN\"}," + "{\"Text\":\"파란 바나나 빨간 파인애플" 검정 용 돼지 들쭉^ 암소 암소 고양이 황색> 복숭아\",\"Locale\":\"ko\"}," + "{\"Text\":\"Mango$ Snake Monkey" Dragon# Rat( Rat Mango] Pineapple Black Dog Dog/\",\"Locale\":\"en-US\"}," + "{\"Text\":\"Овцы" Овцы^ Дракон^ Манго Бело% Собака Змейка\",\"Locale\":\"ru\"}," + "{\"Text\":\"Чернота Собака] Корова Бело) Лимон/ Кот\",\"Locale\":\"ru\"}," + "{\"Text\":\"원숭이= 복숭아}\",\"Locale\":\"ko\"}," + "{\"Text\":\"黒% いちご; ブタ 赤い_ ドラゴン$ ブドウ- パイナップル@ 猫% バナナ 青い= レモン いちご* 象 バナナ 白い} 白い 犬" 紫色 馬 猫) 馬 マンゴ+ バナナ) ヒツジ ブドウ\",\"Locale\":\"jp\"}," + "{\"Text\":\"狗~ 大象, 柠檬 紫色 猴子 蓝色$ 柠檬 猫 猫 葡萄$ 猫 狗' 蓝色 绿色# 猴子 猪; 猴子 绿色/ 葡萄\",\"Locale\":\"zh-CN\"}," + "{\"Text\":\"Лимон# Желтыйцвет% Зеленыйцвет* Овцы Корова\",\"Locale\":\"ru\"}," + "{\"Text\":\"Известка Желтыйцвет^ Кот= Желтыйцвет( Зеленыйцвет) Кот Кот\",\"Locale\":\"ru\"}," + "{\"Text\":\"パイナップル ラット 犬* ドラゴン^ ドラゴン} ヘビ 猿- 黄色* パイナップル]\",\"Locale\":\"jp\"}," + "{\"Text\":\"말 돼지" 검정& 녹색* 딸기{ 망고] 들쭉" 뱀< 말# 양~ 용@ 뱀/ 파인애플 파인애플+ 돼지 황색{ 고양이, 녹색 검정 양. 뱀 용 자주색_ 들쭉\",\"Locale\":\"ko\"}," + "{\"Text\":\"파인애플 자주색 자주색: 빨간 백색 빨간\",\"Locale\":\"ko\"}," + "{\"Text\":\"猴子 猫! 桃子, 香蕉* 猴子; 蓝莓 草莓 红色 黄色 蓝莓/ 鼠 蛇 黑色> 芒果' 芒果, 红色@ 石灰 蓝色 猫{ 鼠\",\"Locale\":\"zh-CN\"}," + "{\"Text\":\"牛 石灰> 馬* ヒツジ 黒? 黒~ いちご_ バナナ_\",\"Locale\":\"jp\"}," + "{\"Text\":\"ヘビ} 青い 猿 猿 馬 ヘビ% 黄色) いちご いちご< 紫色/\",\"Locale\":\"jp\"}," + "{\"Text\":\"Овцы Голубика Красно Змейка` Ананас Персик` Кот Банан Крыса\",\"Locale\":\"ru\"}," + "{\"Text\":\"白色' 芒果 狗 芒果) 红色 桃子, 桃子; 蛇- 鼠 鼠 草莓 黄色 红色 蓝色* 白色" 葡萄%\",\"Locale\":\"zh-CN\"}]"); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "LocalizedText" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayStatusCodeValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10320"; var expected = _serializer.Parse("[2555904,9306112]"); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "StatusCode" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayVariantValueVariableTest1Async(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10321"; var encoder = new JsonVariantEncoder(new ServiceMessageContext(), _serializer); var values = _generator.GetRandomArray(); var expected = _serializer.FromObject(values .Select((object v) => { var body = encoder.Encode(new Variant(v), out var t); return _serializer.FromObject(new { Type = t.ToString(), Body = body }); })); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "Variant" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, _serializer.FromObject(values), result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayEnumerationValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10322"; var expected = _serializer.Parse( "[213809063,256148911,1403441746,1765077059,1459915248,178083" + "9730,1170915216,676529496,206863250,700571842,1421759593,311" + "197401,2102772218,857824445,1673233467,1438792918,682491618," + "113683929,1784104203,508655730,154788171,1059835353,18362300" + "58,201534405,291502570,265713070,1462120528,163301337,883718" + "228,387243245,241294166,1024734946,868521396,1226516137,2049" + "366608,1946103069,966183232,874571368,1377393447,1387753822," + "558428041,1888176372,210663882,185274868,1386322555,12440540" + "68,45448351,2138501043,223371060,643696097,1931984232,590598" + "358,992471751,2028344606,1582760362,1301457357,567402500,120" + "1907341,1473574489,1194202178,318719202,1007613879,194029491" + "5,1967103652,459277676,397024647,1590159652,876256081,955941" + "484,1874614045,472609686,1955403897,883774129,396350381,2097" + "711336,414095446,849171471,1650955190,962695497,1194932149,2" + "20264719]"); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "Int32" // Assert.Equal("Enumeration", result.DataType); }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayStructureValueVariableTestAsync(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10323"; var expected = _serializer.Parse(""" [ { "TypeId": "http://test.org/UA/Data/#i=9440", "Encoding": "Json", "Body": { "BooleanValue": true, "SByteValue": -38, "ByteValue": 110, "Int16Value": 8055, "UInt16Value": 55806, "Int32Value": 256543409, "UInt32Value": 1124716060, "Int64Value": 6272273485009155588, "UInt64Value": 8748332193282252019, "FloatValue": 1.3550572E+28, "DoubleValue": -55.151821136474609, "StringValue": "레몬 딸기^ 고양이) 파인애플", "DateTimeValue": "2071-08-08T14:25:16.7814639Z", "GuidValue": "2f1b64e2-9b6c-9ff9-9bcb-681a5030910b", "ByteStringValue": "XmIaOczWGerdvT4+Y1BOuQ==", "XmlElementValue": "PG4wOum7hOiJsiDjg5bjgr/jg6Ljg6I9IlZhY2EiIOOBhOOBoeOBlD0iQ2VyZG8iIOefs+eBsD0iQXLDoW5kYW5vIiDppqw9IlBlcnJvIiB4bWxuczpuMD0iaHR0cDovL+efs+eBsCI+PG4wOue0q+iJsj5Nb25vIFZlcmRlIFV2YSBTZXJwaWVudGUgTW9ubyBBenVsIFBpw7FhIE92ZWphLiBNYW5nbyBMaW1hPC9uMDrntKvoibI+PG4wOuefs+eBsD5NZWxvY290w7NuOyBQZXJybyBBcsOhbmRhbm8gTGltw7NuJmd0OyBBbWFyaWxsbzwvbjA655+z54GwPjxuMDrjg5bjg4njgqY+T3ZlamF+IFBlcnJvIFDDunJwdXJhXiBMaW1hIFJhdGEhIEJsYW5jb18gUMO6cnB1cmE9IEdhdG88L24wOuODluODieOCpj48L24wOum7hOiJsj4=", "NodeIdValue": "http://samples.org/UA/memorybuffer#b=672G6bOkm2X9OQ4V", "ExpandedNodeIdValue": "g=b869d987-396a-5018-7e4d-556d5e591587", "QualifiedNameValue": "http://opcfoundation.org/UA/Diagnostics#Dragon", "LocalizedTextValue": { "Text": "母牛@ 蛇 马- 蓝莓 猴子< 绿色 蛇{ 白色$ 绵羊 绵羊 紫色 紫色 猴子[ 猴子! 蓝莓(", "Locale": "zh-CN" }, "StatusCodeValue": 6356992, "VariantValue": { "Type": "ExtensionObject", "Body": { "TypeId": "http://test.org/UA/Data//Instance#g=a2a62a11-ee81-11e2-c797-f015f0dcc7bf", "Body": "+ejk7JrPhOKfaxAk3LnqVYIbn5/Oh111kBH5HcAc46atRudt/iWP1h6eT3cBow==" } }, "EnumerationValue": 0, "StructureValue": { "TypeId": null }, "Number": { "Type": "Double", "Body": 1.0 }, "Integer": { "Type": "Int64", "Body": 1 }, "UInteger": { "Type": "UInt64", "Body": 1 } } }, { "TypeId": "http://test.org/UA/Data/#i=9440", "Encoding": "Json", "Body": { "BooleanValue": true, "SByteValue": -71, "ByteValue": 165, "Int16Value": -31474, "UInt16Value": 60031, "Int32Value": 1002303007, "UInt32Value": 2322690949, "Int64Value": -8682057831558849682, "UInt64Value": 1004227894202161316, "FloatValue": 4.1843192E-05, "DoubleValue": 32635254472704.0, "StringValue": "Голубика> Дракон@", "DateTimeValue": "2014-01-20T12:32:21.1556352Z", "GuidValue": "252c98f0-ad64-fd43-2056-044339a3fb6e", "ByteStringValue": "E3P8wU/iTsNcmseUhcjHs2z228AvXUXixBcwI448g6SHNFPFKEwN8n/uLZBxf4/6s2ljkAsraA==", "XmlElementValue": null, "NodeIdValue": "http://samples.org/UA/memorybuffer/Instance#i=4010681507", "ExpandedNodeIdValue": "http://samples.org/UA/memorybuffer#g=979bd1d7-6e82-4d4e-813c-715d76a51cc9", "QualifiedNameValue": "http://samples.org/UA/memorybuffer#%e8%8a%92%e6%9e%9c", "LocalizedTextValue": { "Text": "黄色 猿, ヒツジ@ 黒 ドラゴン 猿< ラット% ラット* 猿 パイナップル< 白い 黄色 赤い 黄色< 赤い ブタ マンゴ 猫= 象 緑 ブタ", "Locale": "jp" }, "StatusCodeValue": 1441792, "VariantValue": { "Type": "UInt16", "Body": 36671 }, "EnumerationValue": 0, "StructureValue": { "TypeId": null }, "Number": { "Type": "Double", "Body": 1.0 }, "Integer": { "Type": "Int64", "Body": 1 }, "UInteger": { "Type": "UInt64", "Body": 1 } } }, { "TypeId": "http://test.org/UA/Data/#i=9440", "Encoding": "Json", "Body": { "BooleanValue": false, "SByteValue": -113, "ByteValue": 42, "Int16Value": -14982, "UInt16Value": 59442, "Int32Value": 85049805, "UInt32Value": 2602718263, "Int64Value": 3649290182186472621, "UInt64Value": 4161862115548090842, "FloatValue": -5.763605E-32, "DoubleValue": 3.4576486746766018E-34, "StringValue": "Виноградина Слон:", "DateTimeValue": "1923-03-18T00:11:38.731972Z", "GuidValue": "82622490-4f77-4562-6290-1295bf97c2e1", "ByteStringValue": "g6SHNFPFKEwN8n/uLZBxf4/6s2ljkAsraA==", "XmlElementValue": "PG4wOum7hOiJsiDjg5bjgr/jg6Ljg6I9IlZhY2EiIOOBhOOBoeOBlD0iQ2VyZG8iIOefs+eBsD0iQXLDoW5kYW5vIiDppqw9IlBlcnJvIiB4bWxuczpuMD0iaHR0cDovL+efs+eBsCI+PG4wOue0q+iJsj5Nb25vIFZlcmRlIFV2YSBTZXJwaWVudGUgTW9ubyBBenVsIFBpw7FhIE92ZWphLiBNYW5nbyBMaW1hPC9uMDrntKvoibI+PG4wOuefs+eBsD5NZWxvY290w7NuOyBQZXJybyBBcsOhbmRhbm8gTGltw7NuJmd0OyBBbWFyaWxsbzwvbjA655+z54GwPjxuMDrjg5bjg4njgqY+T3ZlamF+IFBlcnJvIFDDunJwdXJhXiBMaW1hIFJhdGEhIEJsYW5jb18gUMO6cnB1cmE9IEdhdG88L24wOuODluODieOCpj48L24wOum7hOiJsj4=", "NodeIdValue": "s=%d0%93%d0%be%d0%bb%d1%83%d0%b1%d0%b8%d0%ba%d0%b0", "ExpandedNodeIdValue": "http://test.org/UA/Data/#s=%e9%a9%ac%e7%b4%ab%e8%89%b2", "QualifiedNameValue": "http://opcfoundation.org/UA/Diagnostics#Elephant", "LocalizedTextValue": { "Text": "猪 猴子~ 红色\" 黄色 红色 葡萄 芒果 香蕉 蓝莓 香蕉 芒果? 葡萄 马& 菠萝 白色< 白色 绿色 绿色= 鼠 白色 猪 蓝莓 草莓 猪 狗", "Locale": "zh-CN" }, "StatusCodeValue": { "Symbol": "GoodShutdownEvent", "Code": 11010048 }, "VariantValue": { "Type": "Int64", "Body": 3678050018011977630 }, "EnumerationValue": 1, "StructureValue": { "TypeId": null }, "Number": { "Type": "Double", "Body": 1.0 }, "Integer": { "Type": "Int64", "Body": 1 }, "UInteger": { "Type": "UInt64", "Body": 1 } } }, { "TypeId": "http://test.org/UA/Data/#i=9440", "Encoding": "Json", "Body": { "BooleanValue": false, "SByteValue": 82, "ByteValue": 198, "Int16Value": 9215, "UInt16Value": 44960, "Int32Value": 1970614820, "UInt32Value": 4087763535, "Int64Value": 3156392098576755738, "UInt64Value": 1179071999846299015, "FloatValue": -1.2796896E-06, "DoubleValue": -2.4084619380135754E-35, "StringValue": "ヘビ~ 猫* 緑) マンゴ< レモン ブタ\" 石灰 石灰{ 黒! ブタ 猿 馬 ブタ@ 牛 ヘビ' 犬 犬\" 牛$", "DateTimeValue": "1949-12-22T18:46:59.3619463Z", "GuidValue": "bfa4b0cc-483b-8dcf-f31c-be1ab6a22373", "ByteStringValue": "5k3/MiwysaJQb0S+h/ZadiHED6kKXOEV505s59Gg", "XmlElementValue": "PG4wOum7hOiJsiDjg5bjgr/jg6Ljg6I9IlZhY2EiIOOBhOOBoeOBlD0iQ2VyZG8iIOefs+eBsD0iQXLDoW5kYW5vIiDppqw9IlBlcnJvIiB4bWxuczpuMD0iaHR0cDovL+efs+eBsCI+PG4wOue0q+iJsj5Nb25vIFZlcmRlIFV2YSBTZXJwaWVudGUgTW9ubyBBenVsIFBpw7FhIE92ZWphLiBNYW5nbyBMaW1hPC9uMDrntKvoibI+PG4wOuefs+eBsD5NZWxvY290w7NuOyBQZXJybyBBcsOhbmRhbm8gTGltw7NuJmd0OyBBbWFyaWxsbzwvbjA655+z54GwPjxuMDrjg5bjg4njgqY+T3ZlamF+IFBlcnJvIFDDunJwdXJhXiBMaW1hIFJhdGEhIEJsYW5jb18gUMO6cnB1cmE9IEdhdG88L24wOuODluODieOCpj48L24wOum7hOiJsj4=", "NodeIdValue": "http://opcfoundation.org/UA/Diagnostics#i=407765665", "ExpandedNodeIdValue": "http://opcfoundation.org/UA/Boiler/#g=f16b1f33-7701-a037-4b9b-c936ae51bc40", "QualifiedNameValue": "http://opcfoundation.org/UA/Boiler//Instance#%ec%bd%94%eb%81%bc%eb%a6%ac", "LocalizedTextValue": { "Text": "Персик Пурпурово\" Змейка` Овцы Крыса Пурпурово* Голубо< Бело& Крыса Змейка", "Locale": "ru" }, "StatusCodeValue": 4980736, "VariantValue": { "Type": "SByte", "Body": -114 }, "EnumerationValue": 1, "StructureValue": { "TypeId": null }, "Number": { "Type": "Double", "Body": 1.0 }, "Integer": { "Type": "Int64", "Body": 5 }, "UInteger": { "Type": "UInt64", "Body": 1 } } }, { "TypeId": "http://test.org/UA/Data/#i=9440", "Encoding": "Json", "Body": { "BooleanValue": false, "SByteValue": -97, "ByteValue": 121, "Int16Value": -29579, "UInt16Value": 52214, "Int32Value": 150448275, "UInt32Value": 2074081332, "Int64Value": -1011618571483371166, "UInt64Value": 3946747598058890327, "FloatValue": 7.858336E+35, "DoubleValue": 10017916.0, "StringValue": "яблоко Ананас~ Овцы Корова Пурпурово_ Банан Крыса Собака Кот Бело( Корова'", "DateTimeValue": "2034-12-05T15:52:28.675232Z", "GuidValue": "0500899c-1c30-8180-cbc7-333928152ed2", "ByteStringValue": "5xRa2IKDWkNPnQk0znSUOxE=", "XmlElementValue": "PG4wOum7hOiJsiDjg5bjgr/jg6Ljg6I9IlZhY2EiIOOBhOOBoeOBlD0iQ2VyZG8iIOefs+eBsD0iQXLDoW5kYW5vIiDppqw9IlBlcnJvIiB4bWxuczpuMD0iaHR0cDovL+efs+eBsCI+PG4wOue0q+iJsj5Nb25vIFZlcmRlIFV2YSBTZXJwaWVudGUgTW9ubyBBenVsIFBpw7FhIE92ZWphLiBNYW5nbyBMaW1hPC9uMDrntKvoibI+PG4wOuefs+eBsD5NZWxvY290w7NuOyBQZXJybyBBcsOhbmRhbm8gTGltw7NuJmd0OyBBbWFyaWxsbzwvbjA655+z54GwPjxuMDrjg5bjg4njgqY+T3ZlamF+IFBlcnJvIFDDunJwdXJhXiBMaW1hIFJhdGEhIEJsYW5jb18gUMO6cnB1cmE9IEdhdG88L24wOuODluODieOCpj48L24wOum7hOiJsj4=", "NodeIdValue": "http://opcfoundation.org/UA/Boiler//Instance#s=%e3%83%98%e3%83%93", "ExpandedNodeIdValue": "http://opcfoundation.org/UA/Boiler/#i=3489247698", "QualifiedNameValue": "DataAccess#%e9%a9%ac", "LocalizedTextValue": { "Text": "ブタ モモ 緑 いちご ドラゴン 犬; 青い~ モモ 黒; 緑 レモン} 猿% 馬 白い% 馬 牛 象 白い+ 象# いちご< 紫色: レモン~ モモ~ ブタ# マンゴ モモ", "Locale": "jp" }, "StatusCodeValue": 1245184, "VariantValue": { "Type": "ExpandedNodeId", "Body": "http://opcfoundation.org/UA/Boiler//Instance#b=4Ncr5uADYkU88S45mg%3d%3d" }, "EnumerationValue": 1, "StructureValue": { "TypeId": null }, "Number": { "Type": "Double", "Body": 1.0 }, "Integer": { "Type": "Int64", "Body": 1 }, "UInteger": { "Type": "UInt64", "Body": 88 } } }, { "TypeId": "http://test.org/UA/Data/#i=9669", "Encoding": "Json", "Body": { "BooleanValue": [ false, false, false, false, true ], "SByteValue": [ 120, 27, 27, 57, 117, 61, -42, 106 ], "ByteValue": [ 105, 241, 196, 82 ], "Int16Value": [ 22001, -1270, 27022, -11160 ], "UInt16Value": [ 31406, 22379, 11459, 18140 ], "Int32Value": [ 1147924132, 937096171, 293419963, 1355723363, 1682226035, 921241048, 946417831, 483648971, 1150550410 ], "UInt32Value": [ 405022290, 3763626854, 2219565007, 635093313, 1150728258 ], "Int64Value": [ -1689618757610414770, -1598013270992443575, -6068487195887049228, 3886489167998855712 ], "UInt64Value": [ 1434838700748177518, 579235881671951863, 1080167929345915653, 1330943213770414543 ], "FloatValue": [ 4.311362E-33, 6.620173E-35, -8.877828E-29, -1.2760576E+29, -1.646687E-22, 1.802464E-21 ], "DoubleValue": [ -6011373486080.0, 108132739055616.0, 8.3547184787473483E-36, 5.2422583022226784E+27, 1.0392232580248937E-32, 1.0094077198242765E+33, -8.35414627813762E-39 ], "StringValue": [ "녹색 들쭉 들쭉 돼지 녹색% 녹색 암소 원숭이 딸기+ 들쭉 암소~ 망고 망고 딸기 녹색 녹색 돼지 들쭉) 석회 개} 검정 쥐~ 쥐 코끼리= 들쭉", "Обезьяна Красно Зеленыйцвет Крыса", "Красно, Желтыйцвет Манго= Ананас Бело&", "Голубика Желтыйцвет", "蓝莓 大象~ 绵羊 柠檬 母牛 母牛 红色", "狗\" 马 紫色` 葡萄@ 柠檬 芒果 猪 菠萝 龙^ 黑色* 马 绿色 绵羊 大象 红色) 蓝莓 蛇# 狗 香蕉 草莓 黑色@ 红色 鼠~ 蓝色 香蕉 猫 红色% 黑色", "Чернота- Собака Пурпурово# Голубика Чернота Голубо: Дракон яблоко Бело Зеленыйцвет" ], "DateTimeValue": [ "1916-05-09T17:48:30.6223191Z" ], "GuidValue": [ "842d41a6-6123-30ce-5970-6c26b28dd4de", "9aa488f4-bf70-5b49-848a-9197639e0990", "63306802-aacd-cf0e-20eb-70b1d72bdbe2", "5763cae3-358e-e7ef-f7d1-0098d037cdbb", "4924dc67-715c-4910-79d4-7a844f978358", "99b3afae-b13b-cc01-7949-6bfbaa75ffe9", "fb4ab41e-9107-7285-b919-deb9bb6a975f", "20eaa74e-3383-b67f-da57-d01305159e03" ], "ByteStringValue": [ "ZppNiFEdKUHgItJIEQ+yC6wDi99l6zWUIa/Bcm2jetrkKQP9EsZVzPdCU1zjkUbBYPlpm3j1LHtkuGaiXLfUPQ==", "+GToC7X45q6+5yOY2bGPaf8RczrfYe79iJhaX7JwP20VteotXbarAYLtuQ0I44s=", "1jk=", "pWEDx5Z16oIcnof7Tqe1giTGYgtJZXK38qjg9KUNU4g=", "FJoMEu1Tt3Mzj2L78Q==", "ZVNgZ0B0LhI/7kvV7pX23A9L/oI5DahvNnOqmBbWD7wAPHqgRKUT", "SgFaHcYXZSJ8Vn8X/G8xWKvwMMzKlvxp34/UsRpVmGk36zc3soqpHg2HG79W98CRCyL1U3VGSbQF8T43Q7MIJ74=", "3xA3+aUgRxG/Q3o8EufOQqb4YETz8aKCMsFMcdtZfvQAQBivWhE=", "1AxjhwY5yd9WaQANEMd6Iu1utMfj1NY1ZcSGO9HPH+iUe4s3kGqbSGni9QjbTG4thh4qQKVKmAA2LSFBs40Nh0kXeZQ7QpKD0mteAd/NWhlVWbWz", "3kJK4osBYkhaldvUbb7D0tnxQ4unbTnrlyBo0wjsWQ==" ], "XmlElementValue": [ "PG4wOum7hOiJsiDjg5bjgr/jg6Ljg6I9IlZhY2EiIOOBhOOBoeOBlD0iQ2VyZG8iIOefs+eBsD0iQXLDoW5kYW5vIiDppqw9IlBlcnJvIiB4bWxuczpuMD0iaHR0cDovL+efs+eBsCI+PG4wOue0q+iJsj5Nb25vIFZlcmRlIFV2YSBTZXJwaWVudGUgTW9ubyBBenVsIFBpw7FhIE92ZWphLiBNYW5nbyBMaW1hPC9uMDrntKvoibI+PG4wOuefs+eBsD5NZWxvY290w7NuOyBQZXJybyBBcsOhbmRhbm8gTGltw7NuJmd0OyBBbWFyaWxsbzwvbjA655+z54GwPjxuMDrjg5bjg4njgqY+T3ZlamF+IFBlcnJvIFDDunJwdXJhXiBMaW1hIFJhdGEhIEJsYW5jb18gUMO6cnB1cmE9IEdhdG88L24wOuODluODieOCpj48L24wOum7hOiJsj4=", "PG4wOum7hOiJsiDjg5bjgr/jg6Ljg6I9IlZhY2EiIOOBhOOBoeOBlD0iQ2VyZG8iIOefs+eBsD0iQXLDoW5kYW5vIiDppqw9IlBlcnJvIiB4bWxuczpuMD0iaHR0cDovL+efs+eBsCI+PG4wOue0q+iJsj5Nb25vIFZlcmRlIFV2YSBTZXJwaWVudGUgTW9ubyBBenVsIFBpw7FhIE92ZWphLiBNYW5nbyBMaW1hPC9uMDrntKvoibI+PG4wOuefs+eBsD5NZWxvY290w7NuOyBQZXJybyBBcsOhbmRhbm8gTGltw7NuJmd0OyBBbWFyaWxsbzwvbjA655+z54GwPjxuMDrjg5bjg4njgqY+T3ZlamF+IFBlcnJvIFDDunJwdXJhXiBMaW1hIFJhdGEhIEJsYW5jb18gUMO6cnB1cmE9IEdhdG88L24wOuODluODieOCpj48L24wOum7hOiJsj4=" ], "NodeIdValue": [ "http://samples.org/UA/memorybuffer#g=8c9312a3-b893-ea53-91d1-2382907eca95", "http://test.org/UA/Data//Instance#b=mZWnGBQiqm%2fQtuce1kejQM%2bdwkrCBDsAWl6ZeX3GfNZshJIz%2fPp%2fauhIgjOqs0w6", "nsu=DataAccess;s=파인애플", "http://test.org/UA/Data//Instance#s=%e8%9b%87%e7%8c%ab%e9%a6%99%e8%95%89", "http://opcfoundation.org/UA/Boiler//Instance#i=272173553", "nsu=DataAccess;b=b0PVHldheYEHVqYSX40/y4R9IYv92lU7yuG4V3n6mgH5hHz6JtoB6X4TUlAXoiijsj61kpDGuJXumVN2qSIIDbul" ], "ExpandedNodeIdValue": [ "http://samples.org/UA/memorybuffer/Instance#g=7ca9a545-0c37-87ea-0423-27b914a43b44", "i=2349590220", "urn:manipc1:OPCFoundation:CoreSampleServer#g=94450a5c-8972-934d-6c99-0c1659b9ce0e", "http://test.org/UA/Data//Instance#s=%e6%a1%83%e5%ad%90", "http://opcfoundation.org/UA/Diagnostics#g=290ee634-1839-f122-f6b0-df426fb19e6b", "urn:manipc1:OPCFoundation:CoreSampleServer#i=2014900536", "http://opcfoundation.org/UA/Boiler//Instance#s=%ec%84%9d%ed%9a%8c", "http://test.org/UA/Data//Instance#b=4D2jPmkygekkYgnuy3rDjlEURSuQwxxtEVEYAMgjS9Cjxg%3d%3d", "http://opcfoundation.org/UA/Diagnostics#g=2005172c-cc4e-6fb5-0e0c-a653cb7c979a", "i=405616161" ], "QualifiedNameValue": [ "DataAccess#%eb%b0%94%eb%82%98%eb%82%98", "http://samples.org/UA/memorybuffer#%d0%9a%d0%be%d1%80%d0%be%d0%b2%d0%b0", "%eb%b0%b1%ec%83%89", "http://samples.org/UA/memorybuffer/Instance#%e3%83%90%e3%83%8a%e3%83%8a", "DataAccess#%e3%83%91%e3%82%a4%e3%83%8a%e3%83%83%e3%83%97%e3%83%ab", "http://opcfoundation.org/UA/Boiler//Instance#Mango" ], "LocalizedTextValue": [ { "Text": "Black~ Pig' Red Black' Lime! Black} Purple Blue Cat Strawberry:", "Locale": "en-US" }, { "Text": "蓝色 芒果 猫 紫色. 鼠; 紫色 紫色 蛇 芒果 葡萄 狗' 母牛", "Locale": "zh-CN" }, { "Text": "草莓, 绵羊 龙 白色{ 白色} 大象, 绿色% 葡萄 菠萝) 蛇 香蕉} 蓝色' 猪 大象' 大象` 芒果^ 猫= 黄色 母牛(", "Locale": "zh-CN" }, { "Text": "绵羊< 石灰/ 母牛: 大象", "Locale": "zh-CN" }, { "Text": "Овцы яблоко# Желтыйцвет Лимон( Змейка Собака Корова? Крыса Змейка> Лошадь Лошадь", "Locale": "ru" }, { "Text": "菠萝' 草莓. 狗 红色: 蛇, 菠萝 龙 猴子/ 菠萝$ 柠檬# 草莓. 蓝莓= 猫 菠萝< 柠檬: 狗 大象 石灰 马= 葡萄( 芒果/ 鼠;", "Locale": "zh-CN" }, { "Text": "Dog) Cat( Strawberry` Cat Monkey Elephant Horse! Grape- Peach Monkey} Blueberry! Red", "Locale": "en-US" }, { "Text": "Snake Grape Mango", "Locale": "en-US" }, { "Text": "蛇, 大象@ 红色 桃子+ 鼠 红色 紫色 草莓 菠萝", "Locale": "zh-CN" }, { "Text": "Кот Крыса Слон Свинья' Голубика Пурпурово@ Дракон- Обезьяна? Бело(", "Locale": "ru" } ], "StatusCodeValue": [ 6225920, 7995392, 5832704, 6553600, 3997696, 1900544, 8519680 ], "VariantValue": [ { "Type": "Byte", "Body": 82 } ], "EnumerationValue": [], "StructureValue": [], "Number": [], "Integer": [], "UInteger": [] } }, { "TypeId": "http://test.org/UA/Data/#i=9440", "Encoding": "Json", "Body": { "BooleanValue": true, "SByteValue": -56, "ByteValue": 104, "Int16Value": 3814, "UInt16Value": 38042, "Int32Value": 535350820, "UInt32Value": 3693060540, "Int64Value": -2577172637598593213, "UInt64Value": 1118748778070163278, "FloatValue": 1.931257E+17, "DoubleValue": -0.00033564501791261137, "StringValue": "ラット} 馬` いちご 青い 白い 象 レモン. パイナップル", "DateTimeValue": "1985-11-03T22:42:37.1296614Z", "GuidValue": "5b9f4a59-1a25-042a-e156-e9e08f8eed3d", "ByteStringValue": "wEYr6R2tv2YG6q2Z", "XmlElementValue": "PG4wOum7hOiJsiDjg5bjgr/jg6Ljg6I9IlZhY2EiIOOBhOOBoeOBlD0iQ2VyZG8iIOefs+eBsD0iQXLDoW5kYW5vIiDppqw9IlBlcnJvIiB4bWxuczpuMD0iaHR0cDovL+efs+eBsCI+PG4wOue0q+iJsj5Nb25vIFZlcmRlIFV2YSBTZXJwaWVudGUgTW9ubyBBenVsIFBpw7FhIE92ZWphLiBNYW5nbyBMaW1hPC9uMDrntKvoibI+PG4wOuefs+eBsD5NZWxvY290w7NuOyBQZXJybyBBcsOhbmRhbm8gTGltw7NuJmd0OyBBbWFyaWxsbzwvbjA655+z54GwPjxuMDrjg5bjg4njgqY+T3ZlamF+IFBlcnJvIFDDunJwdXJhXiBMaW1hIFJhdGEhIEJsYW5jb18gUMO6cnB1cmE9IEdhdG88L24wOuODluODieOCpj48L24wOum7hOiJsj4=", "NodeIdValue": "http://test.org/UA/Data//Instance#i=2103396786", "ExpandedNodeIdValue": "http://test.org/UA/Data//Instance#i=577318642", "QualifiedNameValue": "DataAccess#%e7%8a%ac%e3%83%96%e3%82%bf", "LocalizedTextValue": { "Text": "Red Green Lemon# Elephant Dog Horse Monkey: Lime' Strawberry Monkey", "Locale": "en-US" }, "StatusCodeValue": 1638400, "VariantValue": { "Type": "ExpandedNodeId", "Body": "http://samples.org/UA/memorybuffer#i=1429871234" }, "EnumerationValue": 1, "StructureValue": { "TypeId": null }, "Number": { "Type": "Double", "Body": 1.0 }, "Integer": { "Type": "Int64", "Body": 33 }, "UInteger": { "Type": "UInt64", "Body": 1 } } } ] """); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "ExtensionObject" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayNumberValueVariableTest1Async(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10324"; var values = _generator.GetRandomArray(); var expected = _serializer.FromObject(values .Select(v => new { Type = "SByte", Body = v })); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "Number" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, _serializer.FromObject(values), result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayNumberValueVariableTest2Async(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10324"; var values = _generator.GetRandomArray(); var expected = _serializer.FromObject(values); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "Number" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayIntegerValueVariableTest1Async(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10325"; var values = _generator.GetRandomArray(); var expected = _serializer.FromObject(values .Select(v => new { Type = "Int32", Body = v })); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "Integer" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, _serializer.FromObject(values), result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayIntegerValueVariableTest2Async(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10325"; var values = _generator.GetRandomArray(); var expected = _serializer.FromObject(values); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "Integer" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayUIntegerValueVariableTest1Async(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10326"; var values = _generator.GetRandomArray(); var expected = _serializer.FromObject(values .Select(v => new { Type = "UInt16", Body = v })); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "UInteger" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, _serializer.FromObject(values), result).ConfigureAwait(false); } public async Task NodeWriteStaticArrayUIntegerValueVariableTest2Async(CancellationToken ct = default) { var browser = _services(); const string node = "http://test.org/UA/Data/#i=10326"; var values = _generator.GetRandomArray(); var expected = _serializer.FromObject(values); // Act var result = await browser.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "UInteger" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } private async Task AssertResultAsync(string node, VariantValue expected, ValueWriteResponseModel result) { var value = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); Assert.NotNull(value); Assert.Null(result.ErrorInfo); Assert.True(expected.Equals(value), $"{expected} != {value}"); Assert.Equal(expected, value); } private readonly T _connection; private readonly Func> _readExpected; private readonly Func> _services; private readonly DefaultJsonSerializer _serializer; private readonly Opc.Ua.Test.TestDataGenerator _generator = new(); } } ================================================ FILE: src/Azure.IIoT.OpcUa.Publisher.Testing/tests/Tests/TestData/WriteScalarValueTests.cs ================================================ // ------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License (MIT). See License.txt in the repo root for license information. // ------------------------------------------------------------ namespace Azure.IIoT.OpcUa.Publisher.Testing.Tests { using Azure.IIoT.OpcUa.Publisher.Models; using Furly.Extensions.Serializers; using Furly.Extensions.Serializers.Json; using MemoryBuffer; using System; using System.Threading; using System.Threading.Tasks; using System.Xml; using Xunit; public class WriteScalarValueTests { /// /// Create node services tests /// /// /// /// public WriteScalarValueTests(Func> services, T connection, Func> readExpected) { _services = services; _connection = connection; _readExpected = readExpected; _serializer = new DefaultJsonSerializer(); } public async Task NodeWriteStaticScalarBooleanValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10216"; VariantValue expected = false; // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "Boolean" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); expected = true; // Act result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = "ns=2;i=10216", Value = expected, DataType = "Boolean" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest1Async(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10159"; // Scalar var path = new[] { ".http://test.org/UA/Data/#BooleanValue" }; VariantValue expected = false; // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, BrowsePath = path, Value = expected, DataType = "Boolean" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync("http://test.org/UA/Data/#i=10216", expected, result).ConfigureAwait(false); expected = true; // Act result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = "ns=2;i=10159", BrowsePath = path, Value = expected, DataType = "Boolean" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync("http://test.org/UA/Data/#i=10216", expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest2Async(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10159"; // Scalar var path = new[] { "http://test.org/UA/Data/#BooleanValue" }; VariantValue expected = false; // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, BrowsePath = path, Value = expected, DataType = "Boolean" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync("http://test.org/UA/Data/#i=10216", expected, result).ConfigureAwait(false); expected = true; // Act result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = "ns=2;i=10159", BrowsePath = path, Value = expected, DataType = "Boolean" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync("http://test.org/UA/Data/#i=10216", expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarBooleanValueVariableWithBrowsePathTest3Async(CancellationToken ct = default) { var services = _services(); var path = new[] { "Objects", "http://test.org/UA/Data/#Data", "http://test.org/UA/Data/#Static", "http://test.org/UA/Data/#Scalar", "http://test.org/UA/Data/#BooleanValue" }; VariantValue expected = false; // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { BrowsePath = path, Value = expected, DataType = "Boolean" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync("http://test.org/UA/Data/#i=10216", expected, result).ConfigureAwait(false); expected = true; // Act result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { BrowsePath = path, Value = expected, DataType = "Boolean" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync("http://test.org/UA/Data/#i=10216", expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarSByteValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10217"; var expected = _serializer.Parse("-61"); // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "SByte" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarByteValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10218"; var expected = _serializer.Parse("216"); // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "Byte" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarInt16ValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10219"; var expected = _serializer.Parse("15373"); // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "Int16" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarUInt16ValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10220"; var expected = _serializer.Parse("52454"); // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "UInt16" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarInt32ValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10221"; var expected = _serializer.Parse( "1966214362"); // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "Int32" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarUInt32ValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10222"; var expected = _serializer.Parse("2235103439"); // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "UInt32" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarInt64ValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10223"; var expected = _serializer.Parse("1485146186671575531"); // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "Int64" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarUInt64ValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10224"; var expected = _serializer.Parse("5415129398295885582"); // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "UInt64" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarFloatValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10225"; var expected = _serializer.Parse( "1.65278221E-37"); // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "Float" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarDoubleValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10226"; var expected = _serializer.Parse("103.27073669433594"); // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "Double" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarStringValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10227"; var expected = _serializer.Parse( "\"Red+ Green] Cow^ Purple Horse~ Elephant^ Horse Lime\""); // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "String" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarDateTimeValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10228"; VariantValue expected = DateTime.UtcNow + TimeSpan.FromDays(11); // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "DateTime" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarGuidValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10229"; VariantValue expected = "bdc1d303-2355-6173-9314-1816b7315b96"; // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "Guid" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarByteStringValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10230"; var expected = _serializer.Parse( "\"+1q+tSjpWzavev/hDIb4gk/xHLZGD4VscxJEWo2QzUU145zcKKra6WaGpq" + "hzgIeNIJNnQD/gruzUUkIWpQA=\""); // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "ByteString" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarXmlElementValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10231"; var expected = _serializer.FromObject(XmlElementEx.SerializeObject( new MemoryBufferInstance { Name = "test", TagCount = 333, DataType = "Byte" })); // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "XmlElement" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarNodeIdValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10232"; VariantValue expected = "http://samples.org/UA/memorybuffer#i=2040578002"; // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "NodeId" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarExpandedNodeIdValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10233"; VariantValue expected = "http://opcfoundation.org/UA/Diagnostics#i=1375605653"; // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "ExpandedNodeId" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarQualifiedNameValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10234"; var expected = _serializer.FromObject("http://test.org/UA/Data/#testname"); // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "QualifiedName" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarLocalizedTextValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10235"; var expected = _serializer.Parse( "{\"Text\":\"자주색 들쭉) 망고 고양이\",\"Locale\":\"ko\"}"); // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "LocalizedText" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarStatusCodeValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10236"; var expected = _serializer.Parse("11927552"); // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "StatusCode" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarVariantValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10237"; var expected = _serializer.Parse("-2.5828845095702735E-29"); // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "BaseDataType" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarEnumerationValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10238"; var expected = _serializer.Parse("1137262927"); // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "Int32" // TODO: Assert.Equal("Enumeration", result.DataType); }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarStructuredValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10239"; var expected = _serializer.Parse(""" { "TypeId": "http://test.org/UA/Data/#i=9440", "Encoding": "Json", "Body": { "BooleanValue": false, "SByteValue": 101, "ByteValue": 16, "Int16Value": -15522, "UInt16Value": 30310, "Int32Value": 1931620437, "UInt32Value": 1871434347, "Int64Value": -485429667643080766, "UInt64Value": 455062722452308260, "FloatValue": -5.00243E+26, "DoubleValue": 0.00046682002721354365, "StringValue": "黄色) 黄色] 桃子{ 黑色 狗[ 紫色 桃子] 狗 红色 葡萄% 桃子? 猫 猴子 绵羊", "DateTimeValue": "2027-02-05T11:29:29.9135123Z", "GuidValue": "64a055c1-1e60-67a1-e801-f996fece3eec", "ByteStringValue": "XmIaOczWGerdvT4+Y1BOuQ==", "XmlElementValue": "PG4wOum7hOiJsiDjg5bjgr/jg6Ljg6I9IlZhY2EiIOOBhOOBoeOBlD0iQ2VyZG8iIOefs+eBsD0iQXLDoW5kYW5vIiDppqw9IlBlcnJvIiB4bWxuczpuMD0iaHR0cDovL+efs+eBsCI+PG4wOue0q+iJsj5Nb25vIFZlcmRlIFV2YSBTZXJwaWVudGUgTW9ubyBBenVsIFBpw7FhIE92ZWphLiBNYW5nbyBMaW1hPC9uMDrntKvoibI+PG4wOuefs+eBsD5NZWxvY290w7NuOyBQZXJybyBBcsOhbmRhbm8gTGltw7NuJmd0OyBBbWFyaWxsbzwvbjA655+z54GwPjxuMDrjg5bjg4njgqY+T3ZlamF+IFBlcnJvIFDDunJwdXJhXiBMaW1hIFJhdGEhIEJsYW5jb18gUMO6cnB1cmE9IEdhdG88L24wOuODluODieOCpj48L24wOum7hOiJsj4=", "NodeIdValue": "nsu=DataAccess;s=狗绵羊", "ExpandedNodeIdValue": "http://test.org/UA/Data//Instance#b=pQ%3d%3d", "QualifiedNameValue": "http://test.org/UA/Data/#%e3%83%98%e3%83%93", "LocalizedTextValue": { "Text": "蓝色 紫色 蓝色 红色$", "Locale": "zh-CN" }, "StatusCodeValue": 1835008, "VariantValue": { "Type": "Int32", "Body": 184297559 }, "EnumerationValue": 0, "StructureValue": { "TypeId": null }, "Number": { "Type": "Double", "Body": 0.0 }, "Integer": { "Type": "Int64", "Body": 5 }, "UInteger": { "Type": "UInt64", "Body": 0 } } } """); // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "ExtensionObject" }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarNumberValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10240"; var expected = _serializer.Parse("-44"); // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "SByte" // Assert.Equal("Number", result.DataType); }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarIntegerValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10241"; var expected = _serializer.Parse("94903859"); // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "Int32" // Assert.Equal("Integer", result.DataType); }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } public async Task NodeWriteStaticScalarUIntegerValueVariableTestAsync(CancellationToken ct = default) { var services = _services(); const string node = "http://test.org/UA/Data/#i=10242"; var expected = _serializer.Parse("64817"); // Act var result = await services.ValueWriteAsync(_connection, new ValueWriteRequestModel { NodeId = node, Value = expected, DataType = "UInt32" // Assert.Equal("UInteger", result.DataType); }, ct).ConfigureAwait(false); // Assert await AssertResultAsync(node, expected, result).ConfigureAwait(false); } private async Task AssertResultAsync(string node, VariantValue expected, ValueWriteResponseModel result) { var value = await _readExpected(_connection, node, _serializer).ConfigureAwait(false); Assert.NotNull(value); Assert.Null(result.ErrorInfo); Assert.True(expected.Equals(value), $"{expected} != {value}"); Assert.Equal(expected, value); } private readonly T _connection; private readonly DefaultJsonSerializer _serializer; private readonly Func> _readExpected; private readonly Func> _services; } } ================================================ FILE: src/Directory.Build.props ================================================  ================================================ FILE: testenvironments.json ================================================ { "version": "1", "environments": [ { "name": "Ubuntu-22.04", "type": "wsl", "wslDistribution": "Ubuntu-22.04" } ] } ================================================ FILE: tools/checkdocs.cmd ================================================ @REM Copyright (c) Microsoft. All rights reserved. @REM Licensed under the MIT license. See LICENSE file in the project root for full license information. @setlocal EnableExtensions EnableDelayedExpansion @echo off set current-path=%~dp0 rem // remove trailing slash set current-path=%current-path:~0,-1% set build_root=%current-path%\.. pushd %build_root% cmd /c npm install -g markdown-link-validator > _tmp.out 2>&1 if "%1" == "-q" goto :quiet if "%1" == "--quiet" goto :quiet call markdown-link-validator . -i #.* -f gi if !ERRORLEVEL! == 0 goto :success goto :error :quiet call markdown-link-validator . -i #.* -f gi > _tmp.out 2>&1 if !ERRORLEVEL! == 0 goto :success goto :error :error if exist _tmp.out del /f _tmp.out popd exit /b 1 :success if exist _tmp.out del /f _tmp.out popd goto :eof ================================================ FILE: tools/clean.sh ================================================ #!/bin/bash # ------------------------------------------------------------------------------- usage(){ echo ' Usage: '"$0"' 1. Run first on the subscription using -m flag to mark groups for deletion. 2. Ask team to remove the tag for items they want to keep. 3. When done, run again with -y flag to remove all remaining tagged groups. --subscription, -s Subscription to clean up. If not set uses the default subscription for the account. --mark, -m Mark groups not tagged with Production for deletion. -y Perform actual deletion. --prefix Match and delete everything with prefix. --kv-purge Purge all soft deleted key vaults in subscription. --help Shows this help. ' exit 1 } args=( "$@" ) subscription= delete= prefix= mark= purgekv= while [ "$#" -gt 0 ]; do case "$1" in --subscription|-s) subscription="$2" ; shift ;; --kv-purge) purgekv=1 ;; --mark|-m) mark=1 ;; --prefix) prefix="$2" ; shift ;; -y) delete=1 ;; *) usage ;; esac shift done # ------------------------------------------------------------------------------- if ! az account show > /dev/null 2>&1 ; then az login fi if [[ -n "$subscription" ]]; then if ! az account set -s $subscription ; then echo "Failed to change subscription!" exit 1 fi fi # ------------------------------------------------------------------------------- if [[ -n "$prefix" ]] ; then # select groups with prefix that are not production groups=$(az group list \ --query "[?starts_with(name, '$prefix') && tags.Production==null].name" \ -o tsv | tr -d '\r') elif [[ -n "$mark" ]]; then # select groups to mark for deletion groups=$(az group list --query "[?tags.Production==null].name" \ -o tsv | tr -d '\r') else # select groups marked for deletion groups=$(az group list --query "[?tags.ReadyToDelete].name" \ -o tsv | tr -d '\r') fi # remove groups for group in $groups; do if [[ -n "$mark" ]]; then if [[ $group = MC_* ]] ; then echo "skipping $group ..." > /dev/null else echo "Marking group $group as ready to delete ..." az group update -g $group --set tags.ReadyToDelete='true' > /dev/null fi else if [[ $group = MC_* ]] ; then echo "skipping $group ..." > /dev/null elif [[ -z "$delete" ]]; then echo "$group up for deletion." else echo "Deleting resourcegroup $group ..." az group delete -g $group -y --no-wait fi fi done # ------------------------------------------------------------------------------- if [[ -n "$purgekv" ]]; then # purge deleted keyvault for vault in $(az keyvault list-deleted -o tsv | tr -d '\r'); do echo "deleting keyvault $vault ..." az keyvault purge --name $vault done fi # ------------------------------------------------------------------------------- ================================================ FILE: tools/codecoverage.cmd ================================================ @REM Copyright (c) Microsoft. All rights reserved. @REM Licensed under the MIT license. See LICENSE file in the project root for full license information. @setlocal EnableExtensions EnableDelayedExpansion @echo off set current-path=%~dp0 rem // remove trailing slash set current-path=%current-path:~0,-1% set build_root=%current-path%\.. cd %build_root% dotnet test "Industrial-IoT.sln" -v n --configuration Release /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura dotnet tool install -g dotnet-reportgenerator-globaltool reportgenerator -reports:./**/coverage.cobertura.xml -targetdir:./CodeCoverage -reporttypes:Badges;Html;HtmlSummary;Cobertura ================================================ FILE: tools/docgen.cmd ================================================ @REM Copyright (c) Microsoft. All rights reserved. @REM Licensed under the MIT license. See LICENSE file in the project root for full license information. @setlocal EnableExtensions EnableDelayedExpansion @echo off set current-path=%~dp0 rem // remove trailing slash set current-path=%current-path:~0,-1% set build_root=%current-path%\.. :args-loop if "%1" equ "" goto :args-done if "%1" equ "--xtrace" goto :arg-trace if "%1" equ "-x" goto :arg-trace goto :usage :args-continue shift goto :args-loop :usage echo docgen.cmd [options] echo options: echo -x --xtrace print a trace of each command. exit /b 1 :arg-trace echo on goto :args-continue :args-done goto :main rem rem generate docs rem :generate_docs pushd %build_root%\docs call :generate_doc_for_service opc-publisher set service= set convert= popd goto :eof rem rem generate doc rem :generate_doc_for_service set service=%1 pushd %service% if not exist openapi.json goto :eof if exist security.md move security.md security_save.md echo swagger2markup.markupLanguage=MARKDOWN > config.properties echo swagger2markup.generatedExamplesEnabled=false >> config.properties echo swagger2markup.pathsGroupedBy=TAGS >> config.properties echo swagger2markup.inlineSchemaEnabled=true >> config.properties echo swagger2markup.lineSeparator=WINDOWS >> config.properties echo swagger2markup.pathSecuritySectionEnabled=true >> config.properties echo swagger2markup.flatBodyEnabled=false >> config.properties echo swagger2markup.interDocumentCrossReferencesEnabled=true >> config.properties rem echo swagger2markup.overviewDocument=overview >> config.properties echo swagger2markup.separatedDefinitionsEnabled=false >> config.properties echo swagger2markup.separatedOperationsEnabled=false >> config.properties docker run --rm --mount type=bind,source=%cd%,target=/opt swagger2markup/swagger2markup:1.3.1 convert -i /opt/openapi.json -d /opt -c /opt/config.properties if exist security_save.md move security_save.md security.md if exist paths.md type paths.md > api.md if exist paths.md del /f paths.md if exist overview.md del /f overview.md if exist config.properties del /f config.properties popd goto :eof @rem @rem Main @rem :main call :generate_docs endlocal ================================================ FILE: tools/e2etesting/DeployAKS.ps1 ================================================ Param( [string] $ResourceGroupName, [Guid] $TenantId, [String] $Region = "northeurope", [string] $PublisherDeploymentFile = "./K8s-Standalone/publisher/deployment.yaml", [string] $ContainerRegistryServer = "mcr.microsoft.com", [string] $ContainerRegistryUsername, [string] $ContainerRegistryPassword, [string] $ImageNamespace = "", [string] $ImageTag = "latest" ) # Stop execution when an error occurs. $ErrorActionPreference = "Stop" if (!$ResourceGroupName) { Write-Error "ResourceGroupName not set." } if (!$Region) { Write-Error "Region not set." } if (!(Microsoft.PowerShell.Management\Test-Path -Path $PublisherDeploymentFile -PathType Leaf)) { Write-Error "OPC Publisher k8s deployment file '$PublisherDeploymentFile' does not exist" } ## show installed az.aks module Get-Module -listAvailable -Name Az.Aks, Az.ContainerRegistry ## Login if required $context = Get-AzContext if (!$context) { Write-Host "Logging in..." Login-AzAccount -Tenant $TenantId $context = Get-AzContext } ## Check if resource group exists $resourceGroup = Get-AzResourceGroup -Name $resourceGroupName -ErrorAction SilentlyContinue if (!$resourceGroup) { Write-Host "Creating Resource Group $($ResourceGroupName) in $($Region)..." $resourceGroup = New-AzResourceGroup -Name $ResourceGroupName -Location $Region } else { Write-Host "Using resource Group: $($resourceGroup.ResourceGroupName)" } ## Build verifier $registryName = "$($ResourceGroupName)acr" $registry = Get-AzContainerRegistry -ResourceGroupName $ResourceGroupName -Name $registryName -ErrorAction SilentlyContinue if (!$registry) { Write-Host "Creating container registry $($registryName) in $($Region) ..." $registry = New-AzContainerRegistry -ResourceGroupName $ResourceGroupName -Name $registryName -EnableAdminUser -Sku Standard -Location $Region } else { Write-Host "Using conainer registry: $($registry.Name)" } $registrySecret = Get-AzContainerRegistryCredential -ResourceGroupName $ResourceGroupName -Name $registryName Connect-AzContainerRegistry -Name $registryName $verifierImageName = "$($registry.LoginServer)/mqtt-verifier:latest" Write-Host "Build and push verifier image $($verifierImageName)..." docker build -t mqtt-verifier -f ./tools/e2etesting/MqttTestValidator/MqttTestValidator/Dockerfile ./tools/e2etesting/MqttTestValidator/MqttTestValidator docker image tag mqtt-verifier $verifierImageName docker push $verifierImageName Write-Host "Verifier image $($verifierImageName) created." ## Determine suffix for testing resources if (!$resourceGroup.Tags) { $resourceGroup.Tags = @{} } $testSuffix = $resourceGroup.Tags["TestingResourcesSuffix"] if (!$testSuffix) { $testSuffix = Get-Random -Minimum 10000 -Maximum 99999 $aksName = "aksCluster_$($testSuffix)" # Create ssh keys Write-Host "Creating ssh key" ssh-keygen -m PEM -t rsa -b 4096 -f ssh -q -N '""' Get-Content ssh.pub ## Create AKS Cluster Write-Host "Creating cluster $aksName" for ($i = 0; ($i -lt 20) -and (!$aksCluster); $i++) { try { $aksCluster = New-AzAksCluster -ResourceGroupName $resourceGroupName -Name $aksName -NodeCount 3 -SshKeyPath ssh.pub -Force if (!$aksCluster) { throw "Failed to create AKS cluster." } else { Write-Host "Cluster $aksName created" $aksCluster | Format-Table | Out-String | % { Write-Host $_ } } } catch { Write-Host "$($_.Exception.Message) for $($aksName) - Retrying..." Start-Sleep -s 2 } } if (!$aksCluster) { Write-Error "Failed to create AKS cluster." } else { $tags = $resourceGroup.Tags $tags += @{"TestingResourcesSuffix" = $testSuffix } Set-AzResourceGroup -Name $resourceGroup.ResourceGroupName -Tag $tags | Out-Null $resourceGroup = Get-AzResourceGroup -Name $resourceGroup.ResourceGroupName } } else { $aksName = "aksCluster_$($testSuffix)" } ## Install kubectl Install-AzAksKubectl -Version latest -Force ## Load AKS Cluster credentials Import-AzAksCredential -ResourceGroupName $resourceGroupName -Name $aksName -Force ## Create testing namespace in AKS kubectl apply -f ./tools/e2etesting/K8s-Standalone/e2etesting/ ## Load Mosquitto kubectl apply -f ./tools/e2etesting/K8s-Standalone/mosquitto/ ## Load OPC PLC kubectl apply -f ./tools/e2etesting/K8s-Standalone/opcplc/ ## Load OPC Publisher $deviceId = "device_$($testSuffix)" ### Create Image Pull Secret if required if (![string]::IsNullOrEmpty($ContainerRegistryUsername) -and ($ContainerRegistryPassword.Length -ne 0)) { $withImagePullSecret = $true kubectl create secret docker-registry dev-registry-pull-secret --docker-server=$ContainerRegistryServer --docker-username=$ContainerRegistryUsername --namespace=e2etesting --docker-password=$ContainerRegistryPassword } else { $withImagePullSecret = $false } ### Replace placeholder in deployment file $fileContent = Get-Content $PublisherDeploymentFile -Raw $fileContent = $fileContent -replace "{{ContainerRegistryServer}}", $ContainerRegistryServer if (![string]::IsNullOrEmpty($ImageNamespace)) { $ImageNamespace = "$($ImageNamespace)/" } $fileContent = $fileContent -replace "{{ImageNamespace}}", $ImageNamespace $fileContent = $fileContent -replace "{{ImageTag}}", $ImageTag $fileContent = $fileContent -replace "{{DeviceId}}", $deviceId if ($withImagePullSecret) { $fileContent = $fileContent -replace "{{ImagePullSecret}}", "" } else { $fileContent = $fileContent -replace "{{ImagePullSecret}}", "#" } $fileContent | Out-File $PublisherDeploymentFile -Force -Encoding utf8 $fileContent | Out-Host kubectl apply -f ./tools/e2etesting/K8s-Standalone/publisher $fileContent = Get-Content './tools/e2etesting/K8s-Standalone/verifier/deployment.yaml' -Raw $fileContent = $fileContent -replace "{{VerifierImage}}", $verifierImageName $fileContent | Out-File './tools/e2etesting/K8s-Standalone/verifier/deployment.yaml' -Force -Encoding utf8 $fileContent | Out-Host kubectl create secret docker-registry verifier-pull-secret --docker-server=$registry.LoginServer --docker-username=$registrySecret.Username --namespace=e2etesting --docker-password=$registrySecret.Password kubectl apply -f ./tools/e2etesting/K8s-Standalone/verifier ================================================ FILE: tools/e2etesting/DeployEdge.ps1 ================================================ Param( [string] $ResourceGroupName, [Guid] $TenantId, [string] $EdgeVmSize = "Standard_D2s_v3", [string] $EdgeVmLocation, [string] $KeysPath ) # Stop execution when an error occurs. $ErrorActionPreference = "Stop" if (!$ResourceGroupName) { Write-Error "ResourceGroupName not set." } if (!$KeysPath) { Write-Error "Path to store certifactes not set." } if (!(Test-Path -Path $KeysPath)) { New-Item -ItemType Directory -Path $KeysPath | Out-Null } $edgeVmUsername = 'sandboxuser' ## Login if required $context = Get-AzContext if (!$context) { Write-Host "Logging in..." Login-AzAccount -Tenant $TenantId $context = Get-AzContext } ## Check if resource group exists $resourceGroup = Get-AzResourceGroup -Name $resourceGroupName if (!$resourceGroup) { Write-Error "Could not find Resource Group '$($ResourceGroupName)'." } ## Determine suffix for testing resources $testSuffix = $resourceGroup.Tags["TestingResourcesSuffix"] if (!$testSuffix) { $testSuffix = Get-Random -Minimum 10000 -Maximum 99999 $tags = $resourceGroup.Tags $tags+= @{"TestingResourcesSuffix" = $testSuffix} Set-AzResourceGroup -Name $resourceGroup.ResourceGroupName -Tag $tags | Out-Null $resourceGroup = Get-AzResourceGroup -Name $resourceGroup.ResourceGroupName } Write-Host "Using suffix for testing resources: $($testSuffix)" ## Check if IoT Hub exists $iotHub = Get-AzIotHub -ResourceGroupName $ResourceGroupName if ($iotHub.Count -ne 1) { Write-Error "IotHub could not be automatically selected in Resource Group '$($ResourceGroupName)'." } Write-Host "IoT Hub Name: $($iotHub.Name)" ## Ensure that Edge Device exists $deviceName = "e2etestdevice_$($testSuffix)" Write-Host "Iot Hub Device Identity: $($deviceName)" $edgeIdentity = Get-AzIotHubDevice -ResourceGroupName $ResourceGroupName -IotHubName $iotHub.Name -DeviceId $deviceName -ErrorAction SilentlyContinue if (!$edgeIdentity) { Write-Host "Creating edge-enabled device identity $($deviceName) in Iot Hub $($iotHub.Name)" $edgeIdentity = Add-AzIotHubDevice -ResourceGroupName $ResourceGroupName -IotHubName $iotHub.Name -DeviceId $deviceName -EdgeEnabled } if (!$edgeIdentity.Capabilities.IotEdge) { Write-Error "Device '$($edgeIdentity.Id)' Iot Hub: '$($iotHub.Name)') is not edge-enabled." } Write-Host "Updating 'os' and '__type__'-Tags in Device Twin..." Update-AzIotHubDeviceTwin -ResourceGroupName $ResourceGroupName -IotHubName $iotHub.Name -DeviceId $edgeIdentity.Id -Tag @{ "os" = "Linux"; "__type__" = "iiotedge"; } | Out-Null ## Generate SSH keys $privateKeyFilePath = Join-Path $KeysPath "id_rsa_iotedge" $publicKeyFilePath = $privateKeyFilePath + ".pub" $keypassphrase = '"$($testSuffix)"' Write-Output "y" | ssh-keygen -q -m PEM -b 4096 -t rsa -f $privateKeyFilePath -N $keypassphrase $sshPrivateKey = Get-Content $privateKeyFilePath -Raw $sshPublicKey = Get-Content $publicKeyFilePath -Raw ## Delete SSH keys from file system Remove-Item -Path $privateKeyFilePath | Out-Null Remove-Item -Path $publicKeyFilePath | Out-Null ## Deploy Edge VM Write-Host "Getting Device Connection String for IoT Edge Deployment..." $edgeDeviceConnectionString = Get-AzIotHubDeviceConnectionString -ResourceGroupName $ResourceGroupName -IotHubName $iotHub.Name -DeviceId $edgeIdentity.Id -KeyType primary $edgeDeviceConnectionString = $edgeDeviceConnectionString.ConnectionString $dnsPrefix = "e2etesting-edgevm-" + $testSuffix Write-Host "Using DNS prefix: $($dnsPrefix)" $edgeParameters = @{ "dnsLabelPrefix" = [string]$dnsPrefix "adminUsername" = [string]$edgeVmUsername "deviceConnectionString" = [string]$edgeDeviceConnectionString "authenticationType" = "sshPublicKey" "adminPasswordOrKey" = [string]$sshPublicKey "allowSsh" = $true "vmSize" = [string]$EdgeVmSize } if ($EdgeVmLocation) { $edgeParameters["location"] = [string]$EdgeVmLocation } $edgeTemplateUri = "https://raw.githubusercontent.com/Azure/iotedge-vm-deploy/1.4/edgeDeploy.json" Write-Host "Running IoT Edge VM Deployment..." $edgeDeployment = New-AzResourceGroupDeployment -ResourceGroupName $ResourceGroupName -TemplateUri $edgeTemplateUri -TemplateParameterObject $edgeParameters $edgeDeployment | ConvertTo-Json | Out-Host if ($edgeDeployment.ProvisioningState -ne "Succeeded") { Write-Error "Deployment $($edgeDeployment.ProvisioningState)." } ## This needs to be refactored. However, currently the SSH-Command is the only output from the Edge deployment script. And that command includes the FQDN of the VM. $sshUrl = $edgeDeployment.Outputs["public_SSH"].Value if ([string]::IsNullOrEmpty($sshUrl)) { Write-Error "Deployment did not provide Public_SSH output." } $fqdn = $sshUrl.Split("@")[1] Write-Host "##vso[task.setvariable variable=EdgeIdentity]$($edgeIdentity.Id)" Write-Host "##vso[task.setvariable variable=EdgeVmUsername]$($edgeVmUsername)" Write-Host "##vso[task.setvariable variable=SshPrivateKey]$($sshPrivateKey)" Write-Host "##vso[task.setvariable variable=SshPublicKey]$($sshPublicKey)" Write-Host "##vso[task.setvariable variable=Fqdn]$($fqdn)" Write-Host "Deployment finished." ================================================ FILE: tools/e2etesting/DeployPLCs.ps1 ================================================ Param( [string] $ResourceGroupName, [int] $NumberOfSimulations = 10, [Guid] $TenantId, [int] $NumberOfSlowNodes = 250, [int] $SlowNodeRate = 10, [string] $SlowNodeType = "uint", [int] $NumberOfFastNodes = 50, [int] $FastNodeRate = 1, [string] $FastNodeType = "uint", [string] $PLCImage, [string] $ResourcesPrefix = "e2etesting", [Double] $MemoryInGb = 0.5, [int] $CpuCount = 1, [bool] $UsePrivateIp = $false ) # Stop execution when an error occurs. $ErrorActionPreference = "Stop" if (!$PLCImage) { $PLCImage = "mcr.microsoft.com/iotedge/opc-plc:latest" } if (!$ResourceGroupName) { Write-Error "ResourceGroupName not set." } ## Check if resource group exists $resourceGroup = az group show --name $ResourceGroupName | ConvertFrom-Json if (!$resourceGroup) { Write-Error "Could not find Resource Group '$($ResourceGroupName)'." } Write-Host "Resource Group: $($ResourceGroupName)" ## Determine suffix for testing resources $testSuffix = $resourceGroup.tags.TestingResourcesSuffix if (!$testSuffix) { $testSuffix = Get-Random -Minimum 10000 -Maximum 99999 # TODO: don't override the original tags az group update --name $resourceGroup --tags TestingResourcesSuffix=$testSuffix } ## Ensure Azure Container Instances ## $allAciNames = @() for ($i = 0; $i -lt $NumberOfSimulations; $i++) { $name = "$($ResourcesPrefix)-simulation-aci-" + $i.ToString().PadLeft(3, "0") + "-" + $testSuffix $allAciNames += $name } $existingACIs = az container list --resource-group $ResourceGroupName --query "[?starts_with(name,'$ResourcesPrefix') ].name" | ConvertFrom-Json $aciNamesToCreate = @() $allAciNames | %{ if (!@($existingACIs).Contains($_)) { $aciNamesToCreate += $_ } } Write-Host "Creating container instances with PLC Image $($PLCImage)..." $jobs = @() if ($aciNamesToCreate.Length -gt 0) { if ($UsePrivateIp -eq $false) { $script = { Param($Name) # create $ports = @(50000, 80) az container create --resource-group $using:ResourceGroupName --name $Name --image $using:PLCImage --os-type Linux --ports @ports --cpu $using:CpuCount --memory $using:MemoryInGb --ip-address Public --dns-name-label $Name $container = az container show --resource-group $using:ResourceGroupName --name $Name | ConvertFrom-Json if (!$container.ipAddress.ip) { throw "Create container failed with exit code: $LASTEXITCODE" } # update $aciCommand = "/bin/sh -c './opcplc --ph $($container.ipAddress.fqdn) --cdn $($container.ipAddress.ip) --ctb --pn=50000 --autoaccept --nospikes --nodips --nopostrend --nonegtrend --nodatavalues --sph --wp=80 --sn=$($using:NumberOfSlowNodes) --sr=$($using:SlowNodeRate) --st=$($using:SlowNodeType) --fn=$($using:NumberOfFastNodes) --fr=$($using:FastNodeRate) --ft=$($using:FastNodeType)'" az container create --resource-group $using:ResourceGroupName --name $Name --image $using:PLCImage --os-type Linux --ports @ports --cpu $using:CpuCount --memory $using:MemoryInGb --ip-address Public --dns-name-label $Name --command $aciCommand if ($LASTEXITCODE -ne 0) { az container delete -y --resource-group $using:ResourceGroupName --name $Name throw "Update container failed with exit code: $LASTEXITCODE" } } } else { Write-Host "Creating containers with private IP addresses" ## Set vNet and subNet parameters for nested edge $networkResourceGroup = $ResourceGroupName + "-RG-network" $vNet = az resource show --name "PurdueNetwork" --resource-group $networkResourceGroup --resource-type "Microsoft.Network/virtualNetworks" --query id $subNet = "3-L2-OT-AreaSupervisoryControl" Write-Host "vNet resource id is $vNet" $script = { Param($Name) #create $ports = @(50000, 80) az container create --resource-group $using:ResourceGroupName --name $Name --image $using:PLCImage --os-type Linux --ports @ports --cpu $using:CpuCount --memory $using:MemoryInGb --ip-address Private --vnet $using:vNet --subnet $using:subNet $container = az container show --resource-group $using:ResourceGroupName --name $Name | ConvertFrom-Json if (!$container.ipAddress.ip) { throw "Create container failed with exit code: $LASTEXITCODE" } # update $aciCommand = "/bin/sh -c './opcplc --ph $($container.ipAddress.fqdn) --cdn $($container.ipAddress.ip) --ctb --pn=50000 --autoaccept --nospikes --nodips --nopostrend --nonegtrend --nodatavalues --sph --wp=80 --sn=$($using:NumberOfSlowNodes) --sr=$($using:SlowNodeRate) --st=$($using:SlowNodeType) --fn=$($using:NumberOfFastNodes) --fr=$($using:FastNodeRate) --ft=$($using:FastNodeType)'" az container create --resource-group $using:ResourceGroupName --name $Name --image $using:PLCImage --os-type Linux --ports @ports --cpu $using:CpuCount --memory $using:MemoryInGb --ip-address Private --vnet $using:vNet --subnet $using:subNet --command $aciCommand if ($LASTEXITCODE -ne 0) { az container delete -y --resource-group $using:ResourceGroupName --name $Name throw "Update container failed with exit code: $LASTEXITCODE" } } } foreach ($aciNameToCreate in $aciNamesToCreate) { Write-Host "Creating ACI $($aciNameToCreate)..." $job = Start-Job -Scriptblock $script -ArgumentList $aciNameToCreate $jobs += $job } Write-Host "Waiting for deployments to finish..." $working = $true while($working) { $working = $false foreach ($job in $jobs) { if ($job.JobStateInfo.State -eq 'Running') { $working = $true break } } Start-Sleep -Seconds 1 } Wait-Job -Job $jobs | Out-Null Write-Host "Deployment finished." foreach ($job in $jobs) { if ($job.JobStateInfo.State -ne 'Completed') { Write-Host "Error while deploying ACI: $($job.JobStateInfo.State)." Receive-Job -Job $job } } } ## Write ACI FQDNs and ips ## Write-Host Write-Host "Getting IPs of ACIs for simulated PLCs..." $fqdnList = az container list --resource-group $ResourceGroupName --query "[?starts_with(name,'$ResourcesPrefix') ].ipAddress.fqdn" | ConvertFrom-Json $ipList = az container list --resource-group $ResourceGroupName --query "[?starts_with(name,'$ResourcesPrefix') ].ipAddress.ip" | ConvertFrom-Json if ($ipList.Count -eq 0) { Write-Error "No Azure Container Instances have been deployed. Please check that quota is not exceeded for this region." } foreach ($ip in $ipList) { Write-Host $ip $plcSimIps += $ip + ";" } foreach ($fqdn in $fqdnList) { Write-Host $ip $plcSimNames += $fqdn + ";" } Write-Host "##vso[task.setvariable variable=OpcPlcSimulationUrls]$($plcSimNames)" Write-Host "##vso[task.setvariable variable=OpcPlcSimulationIps]$($plcSimIps)" ================================================ FILE: tools/e2etesting/DeployStandalone.ps1 ================================================ Param( [string] $ResourceGroupName, [Guid] $TenantId, [string] $Region = "EastUS", [string] $ServicePrincipalId, [string] $OpcPlcAddresses ) # Stop execution when an error occurs. $ErrorActionPreference = "Stop" if (!$ResourceGroupName) { Write-Error "ResourceGroupName not set." } if (!$Region) { Write-Error "Region not set." } if (!$ServicePrincipalId) { Write-Warning "ServicePrincipalId not set, cannot update permissions." } ## Login if required Write-Host "Getting Azure Context..." $context = Get-AzContext if (!$context) { Write-Host "Logging in..." Login-AzAccount -Tenant $TenantId $context = Get-AzContext } if (!$TenantId) { $TenantId = $context.Tenant.Id Write-Host "Using TenantId $($TenantId)." } ## Check if resource group exists $resourceGroup = Get-AzResourceGroup -Name $resourceGroupName -ErrorAction SilentlyContinue if (!$resourceGroup) { Write-Host "Creating Resource Group $($ResourceGroupName) in $($Region)..." $resourceGroup = New-AzResourceGroup -Name $ResourceGroupName -Location $Region } Write-Host "Resource Group: $($resourceGroup.ResourceGroupName)" ## Determine suffix for testing resources if (!$resourceGroup.Tags) { $resourceGroup.Tags = @{} } $testSuffix = $resourceGroup.Tags["TestingResourcesSuffix"] if (!$testSuffix) { $testSuffix = Get-Random -Minimum 10000 -Maximum 99999 $tags = $resourceGroup.Tags $tags+= @{"TestingResourcesSuffix" = $testSuffix} Set-AzResourceGroup -Name $resourceGroup.ResourceGroupName -Tag $tags | Out-Null $resourceGroup = Get-AzResourceGroup -Name $resourceGroup.ResourceGroupName } Write-Host "Resources Suffix: $($testSuffix)" $iotHubName = "e2etesting-iotHub-$($testSuffix)" $keyVaultName = "e2etestingkeyVault$($testSuffix)" Write-Host "IoT Hub: $($iotHubName)" Write-Host "Key Vault: $($keyVaultName)" ## Ensure IoT Hub $iotHub = Get-AzIotHub -ResourceGroupName $ResourceGroupName -Name $iotHubName -ErrorAction SilentlyContinue if (!$iotHub) { Write-Host "Creating IoT Hub $($iotHubName)..." $iotHub = New-AzIotHub -ResourceGroupName $ResourceGroupName -Name $iotHubName -SkuName S1 -Units 1 -Location $resourceGroup.Location } # Ensure Event Hub additional consumer group for tests $cgName = "TestConsumer" $iotHubCg = Get-AzIotHubEventHubConsumerGroup -ResourceGroupName $ResourceGroupName -Name $iotHubName | Where-Object Name -eq $cgName if (!$iotHubCg) { Write-Host "Creating IoT Hub Event Hub Consumer Group $($cgName)..." $iotHubCg = Add-AzIotHubEventHubConsumerGroup -ResourceGroupName $ResourceGroupName -Name $iotHubName -EventHubConsumerGroupName $cgName } ## Ensure KeyVault $keyVault = Get-AzKeyVault -ResourceGroupName $ResourceGroupName -VaultName $keyVaultName -ErrorAction SilentlyContinue if (!$keyVault) { Write-Host "Creating Key Vault $($keyVaultName)" $keyVault = New-AzKeyVault -ResourceGroupName $ResourceGroupName -VaultName $keyVaultName -Location $resourceGroup.Location -DisableRbacAuthorization } else { $keyVault | Update-AzKeyVault -DisableRbacAuthorization } if ($ServicePrincipalId) { Write-Host "Setting Key Vault Permissions for Service Principal $($ServicePrincipalId)..." Set-AzKeyVaultAccessPolicy -VaultName $KeyVaultName -ResourceGroupName $ResourceGroupName -ServicePrincipalName $ServicePrincipalId -PermissionsToSecrets get,list,set } $connectionString = Get-AzIotHubConnectionString $ResourceGroupName -Name $iothub.Name -KeyName "iothubowner" $SubscriptionId = $context.Subscription.Id Write-Host "Adding/Updating KeyVault-Secret 'PCS-IOTHUB-CONNSTRING' with value '***'..." [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "")] $secret = ConvertTo-SecureString $connectionString.PrimaryConnectionString -AsPlainText -Force Set-AzKeyVaultSecret -VaultName $keyVault.VaultName -Name 'PCS-IOTHUB-CONNSTRING' -SecretValue $secret | Out-Null [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "")] $secret = ConvertTo-SecureString $TenantId -AsPlainText -Force Set-AzKeyVaultSecret -VaultName $keyVault.VaultName -Name 'PCS-AUTH-TENANT' -SecretValue $secret | Out-Null [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "")] $secret = ConvertTo-SecureString $SubscriptionId -AsPlainText -Force Set-AzKeyVaultSecret -VaultName $keyVault.VaultName -Name 'PCS-SUBSCRIPTION-ID' -SecretValue $secret | Out-Null [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "")] $secret = ConvertTo-SecureString $ResourceGroupName -AsPlainText -Force Set-AzKeyVaultSecret -VaultName $keyVault.VaultName -Name 'PCS-RESOURCE-GROUP' -SecretValue $secret | Out-Null Write-Host "Deployment finished." ================================================ FILE: tools/e2etesting/DeployTestResources.ps1 ================================================ Param( $ResourceGroupName, $StorageAccountName, $IoTHubName, $TenantId, $StorageFileShareName = "acishare" ) # Stop execution when an error occurs. $ErrorActionPreference = "Stop" ## Pre-Checks ## if (!$ResourceGroupName) { Write-Error "ResourceGroupName is empty." return } $context = Get-AzContext if (!$context) { Write-Host "Logging in..." Login-AzAccount -Tenant $TenantId $context = Get-AzContext } ## Ensure Resource Group ## $resourceGroup = Get-AzResourceGroup -Name $ResourceGroupName if (!$resourceGroup) { throw "ResourceGroup $($ResourceGroupName) does not exist!" } $suffix = $resourceGroup.Tags["TestingResourcesSuffix"] if ([String]::IsNullOrWhiteSpace($suffix)) { $suffix = (Get-Random -Minimum 10000 -Maximum 99999) $tags = $resourceGroup.Tags $tags+= @{"TestingResourcesSuffix"=$suffix} Set-AzResourceGroup -Name $resourceGroup.ResourceGroupName -Tag $tags | Out-Null $resourceGroup = Get-AzResourceGroup -Name $resourceGroup.ResourceGroupName } Write-Host "Using suffix $($suffix) for test-related resources." $keyVault = Get-AzKeyVault -ResourceGroupName $ResourceGroupName if ($keyVault.Count -ne 1) { throw "keyVault could not be automatically selected in Resource Group '$($ResourceGroupName)'." } ## Log parameters ## Write-Host "==============================================" Write-Host "Test suffix: $($suffix)" Write-Host "==============================================" Write-Host "Subscription Id: $($context.Subscription.Id)" Write-Host "Subscription Name: $($context.Subscription.Name)" Write-Host "Tenant Id: $($context.Tenant.Id)" Write-Host "Resource Group: $($ResourceGroupName)" Write-Host "==============================================" Write-Host "Storage Account: $($StorageAccountName)" Write-Host "KeyVault: $($keyVault.VaultName)" Write-Host "IoTHub: $($IoTHubName)" Write-Host "==============================================" Write-Host "##vso[build.addbuildtag]$($suffix)" Write-Host "##vso[build.addbuildtag]$($context.Subscription.Id)" Write-Host "##vso[build.addbuildtag]$($ResourceGroupName)" Write-Host "##vso[build.addbuildtag]$($keyVault.VaultName)" ## Check existence of IoT Hub ## if (!$IoTHubName) { $iothub = Get-AzIotHub -ResourceGroupName $ResourceGroupName if ($iotHub.Count -eq 1) { $IoTHubName = $iotHub.Name } else { throw "More then 1 IoT Hub instances found in resource group $($ResourceGroupName). Please specify IoTHubName argument of this script." } } else { $iotHub = Get-AzIotHub -ResourceGroupName $ResourceGroupName -Name $IoTHubName -ErrorAction SilentlyContinue } if (!$iotHub) { throw "Could not retrieve IoTHub '$($IoTHubName)' in Resource Group '$($ResourceGroupName)'. Please make sure that it exists." } ## Get IoT Hub EventHub-compatible Endpoint ## $ehEndpoint = $iotHub.Properties.EventHubEndpoints["events"].Endpoint $iotHubkey = Get-AzIotHubKey -ResourceGroupName $ResourceGroupName -Name $IoTHubName -KeyName "iothubowner" $ehConnectionString = "Endpoint={0};SharedAccessKeyName={1};SharedAccessKey={2};EntityPath={3}" -f $ehEndpoint,$iotHubkey.KeyName,$iotHubkey.PrimaryKey,$iotHub.Name Write-Host "Setting KeyVault Secret 'iothub-eventhub-connectionstring' to '***'." [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "")] $secret = ConvertTo-SecureString $ehConnectionString -AsPlainText -Force Set-AzKeyVaultSecret -VaultName $keyVault.VaultName -Name "iothub-eventhub-connectionstring" -SecretValue $secret | Out-Null # Ensure Event Hub additional consumer group for tests $cgName = "TestConsumer" $iotHubCg = Get-AzIotHubEventHubConsumerGroup -ResourceGroupName $ResourceGroupName -Name $IoTHubName | Where-Object Name -eq $cgName if (!$iotHubCg) { Write-Host "Creating IoT Hub $($IoTHubName) Event Hub Consumer Group $($cgName)..." $iotHubCg = Add-AzIotHubEventHubConsumerGroup -ResourceGroupName $ResourceGroupName -Name $IoTHubName -EventHubConsumerGroupName $cgName } ## Ensure Storage Account ## if (!$StorageAccountName) { $StorageAccountName = "e2etestingstorage" + $suffix } $storageAccount = Get-AzStorageAccount -ResourceGroupName $resourceGroup.ResourceGroupName -Name $StorageAccountName -ErrorAction SilentlyContinue if (!$storageAccount) { Write-Host "Storage Account '$($StorageAccountName)' does not exist, creating..." $storageAccount = New-AzStorageAccount -AllowCrossTenantReplication $True -ResourceGroupName $resourceGroup.ResourceGroupName -Name $StorageAccountName -SkuName Standard_LRS -Location $resourceGroup.Location } $storageContext = $storageAccount.Context ## Ensure file share for ACI mount and files to be able to support dynamic ACI:s in test $storageShare = Get-AzStorageShare -Context $storageContext.Context -Name $StorageFileShareName -ErrorAction SilentlyContinue if (!$storageShare) { Write-Host "Creating storage share '$($StorageFileShareName)' in storage account '$($storageAccount.StorageAccountName)'..." $storageShare = New-AzStorageShare -Context $storageContext.Context -Name $StorageFileShareName | Out-Null } ================================================ FILE: tools/e2etesting/DetermineKeyVaultName.ps1 ================================================ param($ResourceGroupName) # Stop execution when an error occurs. $ErrorActionPreference = "Stop" if (!$ResourceGroupName) { Write-Error "ResourceGroupName is empty." return } $keyVaultVariableName = "KeyVaultName" Write-Host "Looking for KeyVault in Resource group '$($ResourceGroupName)'" $resourceGroup = Get-AzResourceGroup -Name $ResourceGroupName if (!$resourceGroup) { Write-Host "##vso[task.complete result=Failed]Could not get Resource Group with name '$($ResourceGroupName)', exiting...'" } $keyVaults = Get-AzKeyVault -ResourceGroupName $resourceGroup.ResourceGroupName if (!$keyVaults) { Write-Host "##vso[task.complete result=Failed]Could not find any KeyVault on Resource Group '$($ResourceGroupName)'." } if ($keyVaults.Count -eq 1) { $applicationKeyVault = $keyVaults.VaultName } else { $application = $resourceGroup.Tags["application"] if (!$application) { Write-Host "##vso[task.complete result=Failed]Application-Tag on Resource Group does not exist or is empty. Please make sure that the Resource Group contains a valid IIoT Deployment." } foreach ($keyVault in $keyVaults) { $kvApplication = $keyVault.Tags["application"] if ($kvApplication -ne $application) { continue } else { $applicationKeyVault = $keyVault.VaultName break } } } if (!$applicationKeyVault) { Write-Host "##vso[task.complete result=Failed]Could not locate KeyVault with Tag 'application = $($application)' in Resource Group '$($ResourceGroupName)'." } Write-Host "Setting variable '$($keyVaultVariableName)' to '$($applicationKeyVault)'." Write-Host "##vso[task.setvariable variable=$($keyVaultVariableName)]$($applicationKeyVault)" ================================================ FILE: tools/e2etesting/GetSecrets.ps1 ================================================ param( [Parameter(Mandatory=$true)] [string] $KeyVaultName ) $ErrorActionPreference = "Stop" # Find the full path of the launchSettings.json file $folderName = "e2e-tests" $currentPath = (Get-Location).Path $path = Get-ChildItem -Path $currentPath $folderName -Recurse while (!$path) { $currentPath = $currentPath + '\..' $path = Get-ChildItem -Path $currentPath $folderName } $settingsFile = $path.FullName + "\.env" $confirmation = Read-Host "Do you want to overwrite the $($settingsFile) file? yes/no" $values = @{} # Get the resource group name $resourceGroup = (Get-AzResource -Name $KeyVaultName).ResourceGroupName $values["ApplicationName"] = $resourceGroup # Get the names of the secrets from the Key Vault $secrets = Get-AzKeyVaultSecret -VaultName $KeyVaultName # Get the values for the secrets foreach ($secret in $secrets) { $secretValueSec = Get-AzKeyVaultSecret -VaultName $KeyVaultName -Name $secret.Name $ssPtr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($secretValueSec.SecretValue) try { $secretValueText = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($ssPtr) } finally { [System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($ssPtr) } $values[$secret.Name.ToUpperInvariant().Replace("-", "_")] = $secretValueText.Replace("`n", "\n").Replace("`r", "\r") } # Write the secrets to .env $content = "" foreach ($variable in $values.Keys) { $content += "$($variable)=$($values[$variable])`n" } if ($confirmation -eq "yes"){ Set-Content -Path $settingsFile $content Write-Host "The file $($settingsFile) was successfully updated with the secrets from your key vault." } else { Write-Host $content } ================================================ FILE: tools/e2etesting/SetKeyVaultPermissions.ps1 ================================================ Param( [string] $ResourceGroupName, [string] $ServicePrincipalName ) # Stop execution when an error occurs. $ErrorActionPreference = "Stop" if (!$ResourceGroupName) { Write-Error "ResourceGroupName not set." } $keyVaults = Get-AzKeyVault -ResourceGroupName $ResourceGroupName if (!$keyVaults) { Write-Error "Could not find any KeyVaults in Resource Group ($ResourceGroupName)" } if ($ServicePrincipalName) { $keyVaults | %{ Write-Host "Adding List,Get,Set-Permissions for secrets of vault '$($_.VaultName)' for ServicePrincipalName '$($ServicePrincipalName)'" Set-AzKeyVaultAccessPolicy -VaultName $_.VaultName -ResourceGroupName $ResourceGroupName -ServicePrincipalName $ServicePrincipalName -PermissionsToSecrets get,list,set } } else { if ($azContext.Account.Id) { $keyVaults | %{ Write-Host "Adding List,Get,Set-Permissions for secrets of vault '$($_.VaultName)' for UserPrincipalName '$($azContext.Account.Id)'" Set-AzKeyVaultAccessPolicy -VaultName $_.VaultName -ResourceGroupName $ResourceGroupName -UserPrincipalName $azContext.Account.Id -PermissionsToSecrets get,list,set } } else { Write-Error "Not logged in" -ErrorAction Stop } } ================================================ FILE: tools/e2etesting/SetKeyVaultSecrets.ps1 ================================================ Param( [string] $KeyVaultName, [string] $ImageTag, [string] $ImageNamespace, [string] $ContainerRegistryServer, [string] $ContainerRegistryUsername, [string] $ContainerRegistryPassword ) # Stop execution when an error occurs. $ErrorActionPreference = "Stop" if (!$KeyVaultName) { Write-Error "KeyVaultName not set." } if (!$ImageTag) { $ImageNamespace = "latest" } if (!$ImageNamespace) { $ImageNamespace = "" } if (!$ContainerRegistryServer) { $ContainerRegistryServer = "mcr.microsoft.com" } if (!$ContainerRegistryUsername) { $ContainerRegistryUsername = "" } if (!$ContainerRegistryPassword) { $ContainerRegistryPassword = "" } ## Login if required Write-Host "Getting Azure Context..." $context = Get-AzContext if (!$context) { Write-Host "Logging in..." Login-AzAccount -Tenant $TenantId $context = Get-AzContext } ## Ensure KeyVault $resourceGroup = (Get-AzResource -Name $KeyVaultName).ResourceGroupName $keyVault = Get-AzKeyVault -ResourceGroupName $resourceGroup -VaultName $KeyVaultName Write-Host "Adding/Updating KeyVault-Secrets..." [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "")] $secret = ConvertTo-SecureString $ContainerRegistryServer -AsPlainText -Force Set-AzKeyVaultSecret -VaultName $keyVault.VaultName -Name 'PCS-DOCKER-SERVER' -SecretValue (ConvertTo-SecureString $ContainerRegistryServer -AsPlainText -Force) | Out-Null [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "")] $secret = ConvertTo-SecureString $ContainerRegistryUsername -AsPlainText -Force Set-AzKeyVaultSecret -VaultName $keyVault.VaultName -Name 'PCS-DOCKER-USER' -SecretValue (ConvertTo-SecureString $ContainerRegistryUsername -AsPlainText -Force) | Out-Null [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "")] $secret = ConvertTo-SecureString $ContainerRegistryPassword -AsPlainText -Force Set-AzKeyVaultSecret -VaultName $keyVault.VaultName -Name 'PCS-DOCKER-PASSWORD' -SecretValue (ConvertTo-SecureString $ContainerRegistryPassword -AsPlainText -Force) | Out-Null [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "")] $secret = ConvertTo-SecureString $ImageNamespace -AsPlainText -Force Set-AzKeyVaultSecret -VaultName $keyVault.VaultName -Name 'PCS-IMAGES-NAMESPACE' -SecretValue (ConvertTo-SecureString $ImageNamespace -AsPlainText -Force) | Out-Null [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "")] $secret = ConvertTo-SecureString $ImageTag -AsPlainText -Force Set-AzKeyVaultSecret -VaultName $keyVault.VaultName -Name 'PCS-IMAGES-TAG' -SecretValue (ConvertTo-SecureString $ImageTag -AsPlainText -Force) | Out-Null ================================================ FILE: tools/e2etesting/SetTestVariables.ps1 ================================================ Param( [string] $ResourceGroupName, [Guid] $TenantId, [string] $OpcPlcSimulationUrls, [string] $OpcPlcSimulationIps, [string] $EdgeIdentity, [string] $EdgeVmUsername, [string] $SshPrivateKey, [string] $SshPublicKey, [string] $Fqdn ) # Stop execution when an error occurs. $ErrorActionPreference = "Stop" if (!$ResourceGroupName) { Write-Error "ResourceGroupName not set." } ## Check if KeyVault exists $keyVault = "e2etestingkeyVault" + $testSuffix $keyVaultList = az keyvault list --resource-group $ResourceGroupName | ConvertFrom-Json if ($keyVaultList.Count -ne 1){ Write-Error "keyVault could not be automatically selected in Resource Group '$($ResourceGroupName)'." } $keyVault = $keyVaultList.name Write-Host "The following Key Vault has been selected: $keyVault" Write-Host "Adding/Updating KeyVault-Secret 'plc-simulation-urls' with value '$($OpcPlcSimulationUrls)'..." az keyvault secret set --vault-name $keyVault --name "plc-simulation-urls" --value $OpcPlcSimulationUrls > $null Write-Host "Adding/Updating KeyVault-Secret 'plc-simulation-ips' with value '$($OpcPlcSimulationIps)'..." az keyvault secret set --vault-name $keyVault --name "plc-simulation-ips" --value $OpcPlcSimulationIps > $null Write-Host "Adding/Updating KeyVault-Secret 'iot-edge-device-id' with value '$($EdgeIdentity)'..." az keyvault secret set --vault-name $keyVault --name 'iot-edge-device-id' --value $EdgeIdentity > $null Write-Host "Adding/Updating KeVault-Secret 'iot-edge-vm-username' with value '$($EdgeVmUsername)'..." az keyvault secret set --vault-name $keyVault --name 'iot-edge-vm-username' --value $EdgeVmUsername > $null Write-Host "Adding/Updating KeVault-Certificate 'iot-edge-vm-privatekey'..." az keyvault secret set --vault-name $keyVault --name 'iot-edge-vm-privatekey' --value $SshPrivateKey > $null Write-Host "Adding/Updating KeVault-Certificate 'iot-edge-vm-publickey'..." az keyvault secret set --vault-name $keyVault --name 'iot-edge-vm-publickey' --value $SshPublicKey > $null Write-Host "Adding/Updating KeyVault-Secret 'iot-edge-device-dnsname' with value '$($Fqdn)'..." az keyvault secret set --vault-name $keyVault --name 'iot-edge-device-dnsname' --value $Fqdn > $null Write-Host "Deployment finished." ================================================ FILE: tools/e2etesting/SetVariables.ps1 ================================================ Param( [string] $BranchName, [string] $Region, [string] $ImageTag, [string] $ContainerRegistryServer, [string] $ResourceGroupName, [string] $SubscriptionId ) # Stop execution when an error occurs. $ErrorActionPreference = "Stop" # Set-PSDebug -Trace 2 $registry = $script:ContainerRegistryServer if ([string]::IsNullOrWhiteSpace($registry)) { Write-Host "No container registry provided, using default." $registry = "industrialiotdev" } Write-Host "Looking up credentials for $($registry) registry in KV $KeyVaultName." if ($registry -eq "mcr.microsoft.com") { Write-Host "##vso[task.setvariable variable=ContainerRegistryServer]$($registry)" } else { if ([string]::IsNullOrWhiteSpace($ResourceGroupName)) { throw "ResourceGroupName not provided." } if ([string]::IsNullOrWhiteSpace($SubscriptionId)) { throw "SubscriptionId not provided." } # Get the ACR credentials $acrCredentials = Get-AzContainerRegistryCredential ` -ResourceGroupName $ResourceGroupName ` -RegistryName $registry ` -SubscriptionId $SubscriptionId Write-Host "##vso[task.setvariable variable=ContainerRegistryPassword]$($acrCredentials.Password)" Write-Host "##vso[task.setvariable variable=ContainerRegistryServer]$($registry).azurecr.io" Write-Host "##vso[task.setvariable variable=ContainerRegistryUsername]$($acrCredentials.Username)" } if ([string]::IsNullOrWhiteSpace($script:ImageTag)) { $script:ImageTag = "$($env:PlatformVersion)" } if ([string]::IsNullOrWhiteSpace($script:ImageTag)) { $script:ImageTag = "$($env:Version_Prefix)" if (![string]::IsNullOrWhiteSpace($env:Version_Suffix)) { Write-Host "##vso[task.setvariable variable=PlatformVersion]$($script:ImageTag)" } } if ([string]::IsNullOrWhiteSpace($script:ImageTag)) { try { dotnet tool install --global --framework net8.0 nbgv 2>&1 } catch {} try { Write-Host "Using get-version to determine version." $props = $(nbgv get-version -f json) | ConvertFrom-Json if ($LastExitCode -ne 0) { throw "Error: 'nbgv get-version -f json' failed with $($LastExitCode)." } $version = $props.CloudBuildAllVars.NBGV_SimpleVersion $script:ImageTag = "$($version)" Write-Host "##vso[task.setvariable variable=PlatformVersion]$($script:ImageTag)" } catch { $script:ImageTag = $null } } if ([string]::IsNullOrWhiteSpace($script:ImageTag)) { # build as latest if not building from ci/cd pipeline Write-Warning "Unable to determine version - use latest." $script:ImageTag = "latest" } # Set namespace name based on branch name if ($registry -eq "industrialiotdev") { if (![string]::IsNullOrWhiteSpace($script:BranchName)) { if ($script:BranchName.StartsWith("refs/heads/")) { $script:BranchName = $script:BranchName.Replace("refs/heads/", "") } } else { $script:BranchName = "main" } $imageNamespace = $script:BranchName if ($imageNamespace.StartsWith("feature/")) { # dev feature builds $imageNamespace = $imageNamespace.Replace("feature/", "") } $imageNamespace = $imageNamespace.Replace("_", "/") $imageNamespace = $imageNamespace.Substring(0, [Math]::Min($imageNamespace.Length, 24)) } elseif ($registry -eq "mcr.microsoft.com") { $imageNamespace = "" } else { $imageNamespace = "public" } Write-Host "==============================================================================" Write-Host "Selected $($script:ImageTag) images in namespace $($imageNamespace) from $($registry)." Write-Host "==============================================================================" Write-Host "" Write-Host "##vso[task.setvariable variable=ImageTag]$($script:ImageTag)" Write-Host "##vso[task.setvariable variable=ImageNamespace]$($imageNamespace)" if ([string]::IsNullOrEmpty($script:Region)) { $script:Region = "westus" } Write-Host "##vso[task.setvariable variable=Region]$($script:Region)" Write-Host "##vso[build.addbuildtag]$($script:ImageTag)" Write-Host "##vso[build.addbuildtag]$($registry)" if (![string]::IsNullOrWhiteSpace($imageNamespace)) { Write-Host "##vso[build.addbuildtag]$($imageNamespace)" } ================================================ FILE: tools/e2etesting/steps/cleanup.yml ================================================ parameters: - name: CleanupAppRegistrations type: boolean steps: - task: AzurePowerShell@5 displayName: "Delete Resource Group" inputs: azureSubscription: '$(AzureSubscription)' azurePowerShellVersion: 'latestVersion' scriptType: 'InlineScript' pwsh: true inline: | Write-Host "Deleting Resource group '$(ResourceGroupName)'..." $resourceGroup = Get-AzResourceGroup -Name "$(ResourceGroupName)" -ErrorAction SilentlyContinue if ($resourceGroup) { $resourceGroup | Remove-AzResourceGroup -Force } else { Write-Host "Resource group '$(ResourceGroupName)' not found." } ================================================ FILE: tools/e2etesting/steps/deploystandalone.yml ================================================ steps: - task: AzurePowerShell@5 displayName: 'Select Image to test' inputs: azureSubscription: '$(AzureSubscription)' azurePowerShellVersion: 'latestVersion' workingDirectory: '$(BasePath)' scriptType: filePath scriptPath: '$(BasePath)\tools\e2etesting\SetVariables.ps1' pwsh: true scriptArguments: > -BranchName "$(BranchName)" -Region "$(Region)" -ImageTag "$(PlatformVersion)" -ContainerRegistryServer "$(ContainerRegistryServer)" -SubscriptionId "d355e77f-e625-4931-b133-445d3dcf12cb" -ResourceGroupName "mcr-iot-industrial-do-not-delete" # Need to do this so we can update the permissions in key vault for this # service principal in the next scripts - task: AzureCLI@2 displayName: 'Set Service Principal Environment Variables' name: SetServicePrincipalId inputs: azureSubscription: '$(AzureSubscription)' azurePowerShellVersion: 'latestVersion' scriptLocation: 'InlineScript' scriptType: 'pscore' addSpnToEnvironment: true inlineScript: | Write-Host "##vso[task.setvariable variable=ServicePrincipalId]$($env:servicePrincipalId)" - task: AzurePowerShell@5 displayName: "Deploy standalone resources" inputs: azureSubscription: '$(AzureSubscription)' azurePowerShellVersion: 'latestVersion' workingDirectory: '$(BasePath)' scriptType: filePath scriptPath: '$(BasePath)\tools\e2etesting\DeployStandalone.ps1' pwsh: true scriptArguments: > -ResourceGroupName "$(ResourceGroupName)" -Region "$(Region)" -ServicePrincipalId "$(ServicePrincipalId)" - task: AzurePowerShell@5 displayName: 'Set KeyVaultName-Variable' inputs: azureSubscription: '$(AzureSubscription)' azurePowerShellVersion: 'latestVersion' workingDirectory: '$(BasePath)' scriptType: filePath scriptPath: '$(BasePath)\tools\e2etesting\DetermineKeyVaultName.ps1' pwsh: true scriptArguments: > -ResourceGroupName '$(ResourceGroupName)' - task: AzurePowerShell@5 displayName: 'Set keyvault container registry secrets' inputs: azureSubscription: '$(AzureSubscription)' azurePowerShellVersion: 'latestVersion' workingDirectory: '$(BasePath)' scriptType: filePath scriptPath: '$(BasePath)\tools\e2etesting\SetKeyVaultSecrets.ps1' pwsh: true scriptArguments: > -KeyVaultName "$(KeyVaultName)" -ImageTag "$(ImageTag)" -ImageNamespace "$(ImageNamespace)" -ContainerRegistryServer "$(ContainerRegistryServer)" -ContainerRegistryUsername "$(ContainerRegistryUsername)" -ContainerRegistryPassword "$(ContainerRegistryPassword)" ================================================ FILE: tools/e2etesting/steps/deploytestresources.yml ================================================ steps: - task: AzurePowerShell@5 displayName: "Deploy required test resources" timeoutInMinutes: 90 inputs: azureSubscription: '$(AzureSubscription)' azurePowerShellVersion: 'latestVersion' workingDirectory: '$(BasePath)' scriptType: filePath scriptPath: '$(BasePath)\tools\e2etesting\DeployTestResources.ps1' pwsh: true scriptArguments: > -ResourceGroupName "$(ResourceGroupName)" - task: AzureCLI@2 displayName: "Deploy containers with simulated PLCs with public ips" timeoutInMinutes: 90 inputs: azureSubscription: '$(AzureSubscription)' azurePowerShellVersion: 'latestVersion' workingDirectory: '$(BasePath)' scriptType: 'pscore' scriptPath: '$(BasePath)\tools\e2etesting\DeployPLCs.ps1' arguments: > -ResourceGroupName "$(ResourceGroupName)" -UsePrivateIp $false - task: AzurePowerShell@5 displayName: "Deploy VM with IoT Edge Runtime" timeoutInMinutes: 90 inputs: azureSubscription: '$(AzureSubscription)' azurePowerShellVersion: 'latestVersion' workingDirectory: '$(BasePath)' scriptType: filePath scriptPath: '$(BasePath)\tools\e2etesting\DeployEdge.ps1' pwsh: true scriptArguments: > -ResourceGroupName "$(ResourceGroupName)" -KeysPath "$(Agent.TempDirectory)" - task: AzureCLI@2 displayName: "Write test resource variables to Keyvault" inputs: azureSubscription: '$(AzureSubscription)' azurePowerShellVersion: 'latestVersion' workingDirectory: '$(BasePath)' scriptType: 'pscore' scriptPath: '$(BasePath)\tools\e2etesting\SetTestVariables.ps1' arguments: > -ResourceGroupName "$(ResourceGroupName)" -OpcPlcSimulationUrls "$(OpcPlcSimulationUrls)" -OpcPlcSimulationIps "$(OpcPlcSimulationIps)" -Fqdn "$(Fqdn)" -EdgeIdentity "$(EdgeIdentity)" -EdgeVmUsername "$(EdgeVmUsername)" -SshPrivateKey "$(SshPrivateKey)" -SshPublicKey "$(SshPublicKey)" ================================================ FILE: tools/e2etesting/steps/runtests.yml ================================================ parameters: - name: ModeName type: string - name: ModeValue type: string steps: - task: AzurePowerShell@5 displayName: 'Set KeyVaultName-Variable' inputs: azureSubscription: '$(AzureSubscription)' azurePowerShellVersion: 'latestVersion' workingDirectory: '$(BasePath)' scriptType: filePath scriptPath: '$(BasePath)\tools\e2etesting\DetermineKeyVaultName.ps1' pwsh: true scriptArguments: > -ResourceGroupName '$(ResourceGroupName)' # Need to do this so we can update the permissions in key vault for this # service principal in the next script - task: AzureCLI@2 displayName: 'Set Service Principal Environment Variables' name: SetServicePrincipalId inputs: azureSubscription: '$(AzureSubscription)' scriptLocation: 'InlineScript' scriptType: 'pscore' addSpnToEnvironment: true inlineScript: | Write-Host "##vso[task.setvariable variable=ServicePrincipalId]$($env:servicePrincipalId)" - task: AzurePowerShell@5 displayName: "Add permissions to KeyVault" name: keyvaultpermissions inputs: azureSubscription: '$(AzureSubscription)' azurePowerShellVersion: 'latestVersion' workingDirectory: '$(BasePath)' scriptType: filePath scriptPath: '$(BasePath)\tools\e2etesting\SetKeyVaultPermissions.ps1' pwsh: true scriptArguments: > -KeyVaultName "$(KeyVaultName)" -ResourceGroupName "$(ResourceGroupName)" -ServicePrincipalName "$(ServicePrincipalId)" - task: AzureKeyVault@2 displayName: 'Retrieve KeyVault secrets' inputs: azureSubscription: '$(AzureSubscription)' KeyVaultName: '$(KeyVaultName)' SecretsFilter: 'PCS-IOTHUB-CONNSTRING,plc-simulation-urls,plc-simulation-ips,iot-edge-vm-username,iot-edge-vm-publickey,iot-edge-vm-privatekey,iot-edge-device-id,iot-edge-device-dnsname,iothub-eventhub-connectionstring,PCS-SUBSCRIPTION-ID' - task: AzureKeyVault@2 displayName: 'Retrieve KeyVault secrets for API tests' condition: notIn( '${{ parameters.ModeValue }}', 'standalone', 'AE') inputs: azureSubscription: '$(AzureSubscription)' KeyVaultName: '$(KeyVaultName)' SecretsFilter: 'PCS-SERVICE-URL,PCS-AUTH-TENANT,PCS-AUTH-CLIENT-APPID,PCS-AUTH-CLIENT-SECRET,PCS-AUTH-SERVICE-APPID' - task: AzurePowerShell@5 displayName: 'Select Image to test' inputs: azureSubscription: '$(AzureSubscription)' azurePowerShellVersion: 'latestVersion' workingDirectory: '$(BasePath)' scriptType: filePath scriptPath: '$(BasePath)\tools\e2etesting\SetVariables.ps1' pwsh: true scriptArguments: > -BranchName "$(BranchName)" -Region "$(Region)" -ImageTag "$(PlatformVersion)" -ContainerRegistryServer "$(ContainerRegistryServer)" -SubscriptionId "d355e77f-e625-4931-b133-445d3dcf12cb" -ResourceGroupName "mcr-iot-industrial-do-not-delete" - task: UseDotNet@2 displayName: 'Install .NET Core SDK' inputs: packageType: sdk version: 8.0.x includePreviewVersions: false installationPath: $(Agent.ToolsDirectory)/dotnet - task: DotNetCoreCLI@2 displayName: 'Restore xUnit tests' inputs: command: restore feedsToUse: config nugetConfigPath: '$(Build.SourcesDirectory)/nuget.config' projects: '$(BasePath)\e2e-tests\IIoTPlatform-E2E-Tests.slnx' - task: DotNetCoreCLI@2 displayName: 'Build xUnit tests' inputs: command: build projects: '$(BasePath)\e2e-tests\IIoTPlatform-E2E-Tests.slnx' arguments: '--configuration Release' - task: DotNetCoreCLI@2 displayName: 'Executing xUnit tests (with ${{ parameters.ModeName }}=${{ parameters.ModeValue }})' timeoutInMinutes: 180 retryCountOnTaskFailure: 1 inputs: command: test projects: '$(TestPath)\IIoTPlatform-E2E-Tests.slnx' arguments: '--configuration Release --filter ${{ parameters.ModeName }}=${{ parameters.ModeValue }} --verbosity=normal --logger "console;verbosity=detailed" --logger trx' env: ApplicationName: '$(ApplicationName)' AzureSubscription: '$(AzureSubscription)' SYSTEM_ACCESSTOKEN: $(System.AccessToken) AZURE_CLIENT_ID: "$(ServicePrincipalId)" AZURE_CLIENT_SECRET: "$(ServicePrincipalKey)" AZURE_TENANT_ID: "$(pcs-auth-tenant)" PCS_IMAGES_TAG: '$(ImageTag)' PCS_DOCKER_SERVER: "$(ContainerRegistryServer)" PCS_DOCKER_USER: "$(ContainerRegistryUsername)" PCS_DOCKER_PASSWORD: "$(ContainerRegistryPassword)" PCS_IMAGES_NAMESPACE: "$(ImageNamespace)" PCS_SUBSCRIPTION_ID: '$(PCS-SUBSCRIPTION-ID)' PCS_RESOURCE_GROUP: '$(ResourceGroupName)' PCS_SERVICE_URL: '$(pcs-service-url)' PCS_AUTH_TENANT: '$(pcs-auth-tenant)' PCS_AUTH_CLIENT_APPID: '$(pcs-auth-client-appid)' PCS_AUTH_CLIENT_SECRET: '$(pcs-auth-client-secret)' PCS_AUTH_SERVICE_APPID: '$(pcs-auth-service-appid)' PCS_IOTHUB_CONNSTRING: '$(pcs-iothub-connstring)' PLC_SIMULATION_URLS: '$(plc-simulation-urls)' PLC_SIMULATION_IPS: '$(plc-simulation-ips)' IOT_EDGE_VERSION: "$(EdgeVersion)" IOT_EDGE_DEVICE_ID: '$(iot-edge-device-id)' IOT_EDGE_DEVICE_DNSNAME: '$(iot-edge-device-dnsname)' IOT_EDGE_VM_USERNAME: '$(iot-edge-vm-username)' IOT_EDGE_VM_PUBLICKEY: '$(iot-edge-vm-publickey)' IOT_EDGE_VM_PRIVATEKEY: '$(iot-edge-vm-privatekey)' IOTHUB_EVENTHUB_CONNECTIONSTRING: '$(iothub-eventhub-connectionstring)' - task: PublishTestResults@2 displayName: 'Publish test results' condition: always() inputs: testResultsFormat: VSTest testResultsFiles: '$(BasePath)\e2e-tests\**\*.trx' ================================================ FILE: tools/swagger.cmd ================================================ @REM Copyright (c) Microsoft. All rights reserved. @REM Licensed under the MIT license. See LICENSE file in the project root for full license information. @setlocal EnableExtensions EnableDelayedExpansion @echo off set current-path=%~dp0 rem // remove trailing slash set current-path=%current-path:~0,-1% set build_root=%current-path%\.. set clean= :args-loop if "%1" equ "" goto :args-done if "%1" equ "--xtrace" goto :arg-trace if "%1" equ "-x" goto :arg-trace if "%1" equ "--hostname" goto :arg-hostname if "%1" equ "-h" goto :arg-hostname goto :usage :args-continue shift goto :args-loop :usage echo swagger.cmd [options] echo options: echo -x --xtrace print a trace of each command. echo -h --hostname specify host name to retrieve from. exit /b 1 :arg-trace echo on goto :args-continue :arg-hostname shift set _hostname=%1 goto :args-continue :args-done goto :main rem rem wait until listening rem :retrieve_spec :retrieve_retry echo Retrieve swagger docs for %1 from %_hostname%. if not exist %build_root%\api\swagger mkdir %build_root%\api\swagger pushd %build_root%\api\swagger if exist %1.json del /f %1.json curl -o %1.json http://%_hostname%/swagger/v2/openapi.json if exist %1.json goto :eof ping nowhere -w 5000 >nul 2>&1 goto :retrieve_retry @rem @rem Main @rem :main rem start publisher module pushd %build_root%\src\Azure.IIoT.OpcUa.Publisher.Module\src start dotnet run --project Azure.IIoT.OpcUa.Publisher.Module.csproj --unsecurehttp=9072 set _hostname=localhost:9701 call :retrieve_spec opc-publisher :done if exist %TMP%\sdk_build.log del /f %TMP%\sdk_build.log popd endlocal ================================================ FILE: version.json ================================================ { "$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", "version": "2.9.15", "publicReleaseRefSpec": [ "^refs/heads/main$", "^refs/heads/release/\\d+\\.\\d+\\.\\d+" ], "cloudBuild": { "setVersionVariables": true, "buildNumber": { "enabled": false } } }